134 lines
7.5 KiB
TypeScript
134 lines
7.5 KiB
TypeScript
import { onMount, type ComponentProps, splitProps } from "solid-js"
|
|
|
|
const icons = {
|
|
edit: {
|
|
viewBox: "0 0 16 16",
|
|
body: `<path d="M13.5555 8.21534V13.5556H2.44434L2.44434 2.4445H7.78462M6.88878 9.11119C6.88878 9.11119 8.96327 9.0367 9.69678 8.3032L14.0301 3.96986C14.5824 3.4176 14.5824 2.52213 14.0301 1.96986C13.4778 1.4176 12.5824 1.4176 12.0301 1.96986L7.69678 6.3032C7.00513 6.99484 6.88878 9.11119 6.88878 9.11119Z" stroke="currentColor"/>`,
|
|
},
|
|
"folder-add-left": {
|
|
viewBox: "0 0 16 16",
|
|
body: `<path d="M7.5 13.3333H1.5V2H6.83333L8.83333 4H14.8333V6M10.1667 11.3333H15.5M12.8333 8.66667V14" stroke="currentColor" stroke-miterlimit="10" stroke-linecap="square"/>`,
|
|
},
|
|
"grid-plus": {
|
|
viewBox: "0 0 16 16",
|
|
body: `<path d="M13.9948 11.668H9.32812M11.6641 9.33203V13.9987M6.66667 9.33203V13.9987H2V9.33203H6.66667ZM6.66667 2V6.66667H2V2H6.66667ZM13.9948 2V6.66667H9.32812V2H13.9948Z" stroke="currentColor" stroke-miterlimit="10" stroke-linecap="square"/>`,
|
|
},
|
|
help: {
|
|
viewBox: "0 0 16 16",
|
|
body: `<path d="M6.33345 6.33349V5.00015H9.66679V7.00015L8.00015 8.00015V9.66679M8.27485 11.6819H7.71897M14.4446 8.00011C14.4446 11.5593 11.5593 14.4446 8.00011 14.4446C4.44094 14.4446 1.55566 11.5593 1.55566 8.00011C1.55566 4.44094 4.44094 1.55566 8.00011 1.55566C11.5593 1.55566 14.4446 4.44094 14.4446 8.00011Z" stroke="currentColor" stroke-linecap="square"/>`,
|
|
},
|
|
"sidebar-right": {
|
|
viewBox: "0 0 20 20",
|
|
body: `<path d="M2.91536 2.91406H2.36536V2.36406H2.91536V2.91406ZM2.91536 17.0807V17.6307H2.36536V17.0807H2.91536ZM17.082 17.0807H17.632V17.6307H17.082V17.0807ZM17.082 2.91406V2.36406H17.632V2.91406H17.082ZM6.9987 2.91406H6.4487V2.36406H6.9987V2.91406ZM6.9987 17.0807V17.6307H6.4487V17.0807H6.9987ZM2.91536 2.91406H3.46536V17.0807H2.91536H2.36536V2.91406H2.91536ZM2.91536 17.0807V16.5307H17.082V17.0807V17.6307H2.91536V17.0807ZM17.082 17.0807H16.532V2.91406H17.082H17.632V17.0807H17.082ZM17.082 2.91406V3.46406H2.91536V2.91406V2.36406H17.082V2.91406ZM6.9987 2.91406H7.5487V17.0807H6.9987H6.4487V2.91406H6.9987ZM17.082 17.0807L17.082 17.6307L6.9987 17.6307V17.0807V16.5307L17.082 16.5307L17.082 17.0807ZM6.9987 2.91406V2.36406H17.082V2.91406V3.46406H6.9987V2.91406Z" fill="currentColor"/>`,
|
|
},
|
|
status: {
|
|
viewBox: "0 0 20 20",
|
|
body: `<path d="M2 10V18H18V10M2 10V2H18V10M2 10H18M5 6H9M5 14H9" stroke="currentColor"/>`,
|
|
},
|
|
"status-active": {
|
|
viewBox: "0 0 20 20",
|
|
body: `<path d="M18 2H2V10H18V2Z" fill="currentColor" fill-opacity="0.1"/><path d="M2 18H18V10H2V18Z" fill="currentColor" fill-opacity="0.1"/><path d="M2 10V18H18V10M2 10V2H18V10M2 10H18M5 6H9M5 14H9" stroke="currentColor"/>`,
|
|
},
|
|
"magnifying-glass": {
|
|
viewBox: "0 0 16 16",
|
|
body: `<path d="M14 14L10.3454 10.3454M6.88889 11.7778C9.58889 11.7778 11.7778 9.58889 11.7778 6.88889C11.7778 4.18889 9.58889 2 6.88889 2C4.18889 2 2 4.18889 2 6.88889C2 9.58889 4.18889 11.7778 6.88889 11.7778Z" stroke="currentColor"/>`,
|
|
},
|
|
menu: {
|
|
viewBox: "0 0 16 16",
|
|
body: `<path d="M2 8H14M2 4.664H14M2 11.336H14" stroke="currentColor"/>`,
|
|
},
|
|
plus: {
|
|
viewBox: "0 0 16 16",
|
|
body: `<path d="M8 2.88867V13.1109" stroke="currentColor" stroke-linejoin="round"/><path d="M2.88867 8H13.1109" stroke="currentColor" stroke-linejoin="round"/>`,
|
|
},
|
|
"settings-gear": {
|
|
viewBox: "0 0 16 16",
|
|
body: `<path d="M7.99998 1.3335L14 4.66683V11.3335L7.99998 14.6668L2 11.3335V4.66683L7.99998 1.3335Z" stroke="currentColor"/><path d="M9.99998 8.00016C9.99998 9.10476 9.10458 10.0002 7.99998 10.0002C6.89538 10.0002 5.99998 9.10476 5.99998 8.00016C5.99998 6.89556 6.89538 6.00016 7.99998 6.00016C9.10458 6.00016 9.99998 6.89556 9.99998 8.00016Z" stroke="currentColor"/>`,
|
|
},
|
|
"chevron-down": {
|
|
viewBox: "0 0 16 16",
|
|
body: `<path d="M5 6.5L8 9.5L11 6.5" stroke="currentColor"/>`,
|
|
},
|
|
check: {
|
|
viewBox: "0 0 16 16",
|
|
body: `<path d="M3.53613 8.17857L6.39328 11.75L12.4647 4.25" stroke="currentColor"/>`,
|
|
},
|
|
close: {
|
|
viewBox: "0 0 20 20",
|
|
body: `<path d="M14.4446 5.55566L5.55566 14.4446M5.55566 5.55566L14.4446 14.4446" stroke="currentColor" stroke-linejoin="round"/>`,
|
|
},
|
|
"xmark-small": {
|
|
viewBox: "0 0 16 16",
|
|
body: `<path d="M4.25 11.75L11.75 4.25M11.75 11.75L4.25 4.25" stroke="currentColor"/>`,
|
|
},
|
|
"outline-chevron-down": {
|
|
viewBox: "0 0 16 16",
|
|
body: `<path d="M5 6.5L8 9.5L11 6.5" stroke="currentColor"/>`,
|
|
},
|
|
"outline-dots": {
|
|
viewBox: "0 0 16 16",
|
|
body: `<path d="M2.5 7.5H3.5V8.5H2.5V7.5Z" stroke="currentColor"/><path d="M7.5 7.5H8.5V8.5H7.5V7.5Z" stroke="currentColor"/><path d="M12.5 7.5H13.5V8.5H12.5V7.5Z" stroke="currentColor"/>`,
|
|
},
|
|
archive: {
|
|
viewBox: "0 0 16 16",
|
|
body: `<path d="M13.1112 13.5555V14.0555H13.6112V13.5555H13.1112ZM2.889 13.5555H2.389L2.389 14.0555H2.889V13.5555ZM3.38901 5.55546L3.38901 5.05546L2.38901 5.05546L2.38901 5.55546L2.88901 5.55546L3.38901 5.55546ZM14.4446 2.44434H14.9446V1.94434L14.4446 1.94434L14.4446 2.44434ZM14.4446 5.55545L14.4446 6.05545L14.9446 6.05545V5.55545H14.4446ZM1.55566 5.55546L1.05566 5.55545L1.05566 6.05546L1.55566 6.05546L1.55566 5.55546ZM1.5557 2.44436L1.5557 1.94436L1.05571 1.94436L1.0557 2.44435L1.5557 2.44436ZM13.1112 5.55546H12.6112V13.5555H13.1112H13.6112V5.55546H13.1112ZM2.889 13.5555H3.389L3.38901 5.55546L2.88901 5.55546L2.38901 5.55546L2.389 13.5555H2.889ZM14.4446 2.44434H13.9446V5.55545H14.4446H14.9446V2.44434H14.4446ZM1.55566 5.55546L2.05566 5.55547L2.0557 2.44436L1.5557 2.44436L1.0557 2.44435L1.05566 5.55545L1.55566 5.55546ZM6.22234 8.22213V8.72213H9.7779V8.22213V7.72213H6.22234V8.22213ZM13.1112 13.5555V13.0555H2.889V13.5555V14.0555H13.1112V13.5555ZM1.5557 2.44436L1.5557 2.94436L14.4446 2.94434L14.4446 2.44434L14.4446 1.94434L1.5557 1.94436L1.5557 2.44436ZM14.4446 5.55545L14.4446 5.05545L1.55566 5.05546L1.55566 5.55546L1.55566 6.05546L14.4446 6.05545L14.4446 5.55545Z" fill="currentColor"/>`,
|
|
},
|
|
}
|
|
|
|
const spriteID = "opencode-v2-icon-sprite"
|
|
const symbol = (name: keyof typeof icons) => `opencode-v2-icon-${name}`
|
|
let spriteInserted = false
|
|
|
|
function ensureSprite() {
|
|
if (spriteInserted) return
|
|
if (typeof document === "undefined") return
|
|
if (document.getElementById(spriteID)) {
|
|
spriteInserted = true
|
|
return
|
|
}
|
|
|
|
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg")
|
|
svg.id = spriteID
|
|
svg.setAttribute("aria-hidden", "true")
|
|
svg.setAttribute("width", "0")
|
|
svg.setAttribute("height", "0")
|
|
svg.style.position = "absolute"
|
|
svg.style.overflow = "hidden"
|
|
svg.innerHTML = Object.entries(icons)
|
|
.map(
|
|
([name, icon]) =>
|
|
`<symbol id="${symbol(name as keyof typeof icons)}" viewBox="${icon.viewBox}">${icon.body}</symbol>`,
|
|
)
|
|
.join("")
|
|
document.body.insertBefore(svg, document.body.firstChild)
|
|
spriteInserted = true
|
|
}
|
|
|
|
export interface IconProps extends ComponentProps<"svg"> {
|
|
name: keyof typeof icons | (string & {})
|
|
size?: "small" | "normal" | "large"
|
|
}
|
|
|
|
export function Icon(props: IconProps) {
|
|
const [split, rest] = splitProps(props, ["name", "size"])
|
|
const iconName = () => (icons[split.name as keyof typeof icons] ? (split.name as keyof typeof icons) : "plus")
|
|
const icon = () => icons[iconName()]
|
|
const pixelSize = split.size === "small" ? 14 : split.size === "large" ? 20 : 16
|
|
onMount(ensureSprite)
|
|
|
|
return (
|
|
<svg
|
|
{...rest}
|
|
data-slot="icon-svg"
|
|
width={pixelSize}
|
|
height={pixelSize}
|
|
viewBox={icon().viewBox}
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
aria-hidden={rest["aria-hidden"] ?? "true"}
|
|
>
|
|
<use href={`#${symbol(iconName())}`} />
|
|
</svg>
|
|
)
|
|
}
|