@driftime/sanity-plugin-icon 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["ObjectFieldProps","FormField","FieldProps","Field","t0","$","_c","title","description","inputId","validation","path","children","t1","gridCellSize","gridRowGap","gridRowHeight","gridColumns","gridVisibleRows","gridHeight","gridOverscan","gridLayoutStyle","justifyItems","rowGap","const","Button","ComponentProps","Drawing","gridCellSize","LibraryIcon","CellProps","Omit","icon","selected","focusable","position","total","onSelect","Cell","t0","$","_c","props","t1","t2","Symbol","for","width","height","t3","node","t4","t5","label","name","Button","Flex","Grid","Stack","Text","ComponentProps","Cell","gridColumns","gridLayoutStyle","LibraryIcon","RecentProps","Omit","icons","selected","onSelect","icon","onForget","Recent","t0","$","_c","props","t1","Symbol","for","t2","t3","t4","length","index","name","map","t5","Stack","Text","Popover","ComponentProps","LibraryIcon","isDefined","HoveredIcon","icon","element","HTMLElement","TooltipProps","Omit","hovered","Tooltip","t0","$","_c","props","t1","t2","t3","t4","Symbol","for","pointerEvents","t5","maxWidth","label","tags","t6","ComponentProps","defaultIconProps","width","height","strokeWidth","IconNode","parseIconNode","convertCase","isDefined","LibraryIcon","name","label","tags","node","terms","normaliseTerms","value","toLowerCase","replaceAll","trim","readLibrary","drawings","Promise","all","nodes","Record","default","Object","keys","flatMap","iconTags","join","libraryRequest","undefined","requestLibrary","library","useEffect","useState","LibraryIcon","requestLibrary","useIconLibrary","$","_c","library","setLibrary","t0","t1","Symbol","for","active","load","loaded","storageKey","limit","readRecent","stored","JSON","parse","globalThis","localStorage","getItem","Array","isArray","filter","entry","writeRecent","name","updated","slice","setItem","stringify","clearRecent","removeItem","useState","clearRecent","readRecent","writeRecent","useRecentIcons","$","_c","recent","setRecent","t0","Symbol","for","remember","name","t1","forget","t2","gridColumns","gridOverscan","gridVisibleRows","getNextIndex","key","current","last","undefined","getVisibleRows","scrollRow","count","totalRows","Math","ceil","firstRow","max","lastRow","min","SearchIcon","Box","Button","Dialog","Flex","Grid","Spinner","Stack","Text","TextInput","ChangeEvent","ComponentProps","KeyboardEvent","MouseEvent","useEffect","useRef","useState","Cell","Recent","HoveredIcon","Tooltip","defaultIconProps","gridColumns","gridHeight","gridLayoutStyle","gridRowHeight","useIconLibrary","useRecentIcons","getNextIndex","getVisibleRows","LibraryIcon","normaliseTerms","isDefined","PickerProps","Omit","selected","onSelect","icon","Picker","t0","$","_c","props","library","recent","remember","forget","search","setSearch","scrollRow","setScrollRow","movedIndex","setMovedIndex","hovered","setHovered","scrolling","setScrolling","scroller","activeCell","focusActiveCell","scrollFrame","undefined","scrollStop","hoverStart","query","searching","results","filter","terms","includes","byName","Map","map","_temp","recentIcons","flatMap","entry","icon_1","get","totalRows","firstRow","lastRow","length","visible","slice","selectedIndex","findIndex","icon_2","name","activeIndex","Math","max","t1","t2","element","current","scrollTop","floor","t3","t4","Symbol","for","cancelAnimationFrame","clearTimeout","t5","focus","t6","t7","handleSelect","icon_3","t8","handleSearch","event","currentTarget","value","selectActive","icon_4","handleSearchKeyDown","event_0","key","preventDefault","t9","handleScroll","setTimeout","requestAnimationFrame","element_0","handleHover","event_1","target","Element","closest","cell","HTMLElement","dataset","icon_5","t10","clearHover","handleGridKeyDown","event_2","last","next","index","min","element_1","top","t11","t12","t13","height","t14","t15","toLocaleString","overflowY","paddingTop","paddingBottom","icon_6","offset","index_0","icon_0","Nullable","T","iconTypeName","SanityIcon","_type","name","node","CloseIcon","Button","Flex","useState","ObjectInputProps","set","setIfMissing","unset","Drawing","Picker","defaultIconProps","LibraryIcon","resolveIconNode","serialiseIconNode","convertCase","isDefined","SanityIcon","iconTypeName","InputProps","Partial","Input","t0","$","_c","id","value","onChange","readOnly","name","node","open","setOpen","selectedNode","selectedLabel","undefined","t1","handleSelect","icon","_type","T0","t2","T1","t3","t4","t5","t6","t7","t8","t9","t10","t11","t12","Drawing","defaultIconProps","resolveIconNode","isDefined","SanityIcon","createIconPreview","value","node","undefined","IconPreview","ComponentProps","SquareDashedIconProps","SquareDashedIcon","props","$","_c","t0","t1","t10","t11","t2","t3","t4","t5","t6","t7","t8","t9","Symbol","for","t12","ComponentProps","ComponentType","createElement","defaultIconProps","createSanityIcon","icon","props","Icon","SanityIcon","defineField","defineType","Field","Input","createIconPreview","SquareDashedIcon","createSanityIcon","convertCase","isDefined","SanityIcon","iconTypeName","iconType","name","type","icon","description","components","field","input","preview","select","node","prepare","selection","title","media","_type","fields","definePlugin","iconType","iconPlugin","name","schema","types"],"sources":["../src/components/field.tsx","../src/config/grid.ts","../src/components/picker/cell.tsx","../src/components/picker/recent.tsx","../src/components/picker/tooltip.tsx","../src/config/defaults.ts","../src/lib/library.ts","../src/hooks/use-icon-library.ts","../src/lib/recent.ts","../src/hooks/use-recent-icons.ts","../src/lib/grid.ts","../src/components/picker/picker.tsx","../src/types.ts","../src/components/input.tsx","../src/components/preview.tsx","../src/icons/square-dashed.tsx","../src/lib/icons.ts","../src/schemas/types/icon.ts","../src/plugin.ts"],"sourcesContent":["import type { ObjectFieldProps } from \"sanity\";\nimport { FormField } from \"sanity\";\n\nexport type FieldProps = ObjectFieldProps;\n\n// Swaps the frame Sanity puts around a nested object for the flat one a plain field gets.\nexport function Field({ title, description, inputId, validation, path, children }: FieldProps) {\n return (\n <FormField title={title} description={description} inputId={inputId} validation={validation} path={path}>\n {children}\n </FormField>\n );\n}\n","/** Size of one cell, in pixels. Fixed so the grid never reflows. */\nexport const gridCellSize = 40;\n\n/** Space between rows, in pixels. */\nconst gridRowGap = 4;\n\n/** Distance from one row to the next, which placing a window over the grid depends on knowing. */\nexport const gridRowHeight = gridCellSize + gridRowGap;\n\n/** How many icons a row holds. */\nexport const gridColumns = 8;\n\n/** How many rows the scrolling area shows at once. */\nexport const gridVisibleRows = 8;\n\n/** Height of the scrolling area, sized to the rows it shows. The final row carries no trailing gap. */\nexport const gridHeight = gridVisibleRows * gridRowHeight - gridRowGap;\n\n/**\n * Rows built either side of the visible ones. Everything built is also painted, so a row scrolled\n * into view is already there rather than arriving with it.\n */\nexport const gridOverscan = gridVisibleRows;\n\n/** Layout both grids share, so a recent icon sits on the same columns as the library below it. */\nexport const gridLayoutStyle = { justifyItems: \"center\", rowGap: gridRowGap } as const;\n","import { Button } from \"@sanity/ui\";\nimport type { ComponentProps } from \"react\";\n\nimport { Drawing } from \"@/components/drawing\";\nimport { gridCellSize } from \"@/config/grid\";\nimport type { LibraryIcon } from \"@/lib/library\";\n\nexport type CellProps = Omit<ComponentProps<typeof Button>, \"icon\" | \"selected\" | \"onSelect\" | \"onClick\"> & {\n icon: LibraryIcon;\n selected: boolean;\n focusable: boolean;\n position: number;\n total: number;\n onSelect: (icon: LibraryIcon) => void;\n};\n\nexport function Cell({ icon, selected, focusable, position, total, onSelect, ...props }: CellProps) {\n return (\n <Button\n type=\"button\"\n role=\"option\"\n aria-selected={selected}\n // Stated, because counting the mounted cells would report the window rather than the library.\n aria-posinset={position}\n aria-setsize={total}\n tabIndex={focusable ? 0 : -1}\n mode=\"bleed\"\n selected={selected}\n padding={0}\n style={{ width: gridCellSize, height: gridCellSize }}\n icon={<Drawing node={icon.node} width=\"1.25em\" height=\"1.25em\" strokeWidth={1.5} />}\n aria-label={icon.label}\n data-icon={icon.name}\n onClick={() => {\n onSelect(icon);\n }}\n {...props}\n />\n );\n}\n","import { Button, Flex, Grid, Stack, Text } from \"@sanity/ui\";\nimport type { ComponentProps } from \"react\";\n\nimport { Cell } from \"@/components/picker/cell\";\nimport { gridColumns, gridLayoutStyle } from \"@/config/grid\";\nimport type { LibraryIcon } from \"@/lib/library\";\n\nexport type RecentProps = Omit<ComponentProps<typeof Stack>, \"children\" | \"onSelect\"> & {\n icons: LibraryIcon[];\n selected: string | undefined;\n onSelect: (icon: LibraryIcon) => void;\n onForget: () => void;\n};\n\nexport function Recent({ icons, selected, onSelect, onForget, ...props }: RecentProps) {\n return (\n <Stack gap={3} {...props}>\n <Flex align=\"center\" justify=\"space-between\" gap={2}>\n <Text size={1} weight=\"medium\" muted>\n Recent icons\n </Text>\n <Button\n type=\"button\"\n mode=\"bleed\"\n fontSize={1}\n padding={2}\n text=\"Clear\"\n onClick={onForget}\n aria-label=\"Forget the recently used icons.\"\n />\n </Flex>\n <Grid role=\"listbox\" aria-label=\"Recent icons\" gridTemplateColumns={gridColumns} style={gridLayoutStyle}>\n {icons.map((icon, index) => (\n <Cell\n key={icon.name}\n icon={icon}\n selected={icon.name === selected}\n focusable\n position={index + 1}\n total={icons.length}\n onSelect={onSelect}\n />\n ))}\n </Grid>\n </Stack>\n );\n}\n","import { Stack, Text } from \"@sanity/ui\";\nimport { Popover } from \"@sanity/ui/popover\";\nimport type { ComponentProps } from \"react\";\n\nimport type { LibraryIcon } from \"@/lib/library\";\nimport { isDefined } from \"@/lib/utils\";\n\n/** The icon a tooltip is describing, paired with the cell it points at. */\nexport interface HoveredIcon {\n /** Icon the cell holds. */\n icon: LibraryIcon;\n /** Cell the tooltip anchors itself to. */\n element: HTMLElement;\n}\n\nexport type TooltipProps = Omit<ComponentProps<typeof Popover>, \"open\" | \"referenceElement\" | \"content\"> & {\n hovered: HoveredIcon | undefined;\n};\n\nexport function Tooltip({ hovered, ...props }: TooltipProps) {\n return (\n <Popover\n open={isDefined(hovered)}\n referenceElement={hovered?.element ?? null}\n placement=\"top\"\n portal\n padding={3}\n // Unstable API, and the only lever for the gap. Top only, since the tooltip sits above.\n __unstable_margins={[-4, 0, 0, 0]}\n // Portalled out of the grid, so a cursor touching it would dismiss the icon it moved onto.\n style={{ pointerEvents: \"none\" }}\n content={\n isDefined(hovered) && (\n <Stack gap={3} style={{ maxWidth: \"16rem\" }}>\n <Text size={1} weight=\"medium\">\n {hovered.icon.label}\n </Text>\n {isDefined(hovered.icon.tags) && (\n <Text size={1} muted>\n {hovered.icon.tags}\n </Text>\n )}\n </Stack>\n )\n }\n {...props}\n />\n );\n}\n","import type { ComponentProps } from \"react\";\n\n/** Properties every icon the Studio draws is rendered with. */\nexport const defaultIconProps: ComponentProps<\"svg\"> = { width: \"1em\", height: \"1em\", strokeWidth: 1.5 };\n","import type { IconNode } from \"@/lib/nodes\";\nimport { parseIconNode } from \"@/lib/nodes\";\nimport { convertCase, isDefined } from \"@/lib/utils\";\n\n/** Single icon the library offers, carrying the terms a search matches it on. */\nexport interface LibraryIcon {\n /** Name the icon goes by in the library it came from. */\n name: string;\n /** Readable form of the name, shown beside the icon. */\n label: string;\n /** What the icon depicts, as a readable list. */\n tags: string;\n /** Shapes the icon is drawn from. */\n node: IconNode;\n /** Name and tags flattened into the form a search compares against. */\n terms: string;\n}\n\n/**\n * Flattens text into the form a search compares against, so a hyphenated icon name and a multi-word\n * tag are matched the same way.\n *\n * @param value - The text to flatten.\n * @returns The text in comparable form.\n */\nexport function normaliseTerms(value: string) {\n return value\n .toLowerCase()\n .replaceAll(/[\\s-]+/gu, \" \")\n .trim();\n}\n\n/**\n * Reads the icon library, pairing each drawing with the terms it can be found by. Both files come\n * from the same release as the icons themselves, so the drawings and their terms never disagree.\n *\n * @returns Every icon the library offers.\n */\nasync function readLibrary() {\n const [drawings, tags] = await Promise.all([\n import(\"lucide-static/icon-nodes.json\"),\n import(\"lucide-static/tags.json\"),\n ]);\n\n const nodes: Record<string, unknown> = drawings.default;\n const terms: Record<string, string[]> = tags.default;\n\n return Object.keys(nodes).flatMap((name) => {\n const node = parseIconNode(nodes[name]);\n if (!isDefined(node)) return [];\n\n const iconTags = terms[name] ?? [];\n\n return [\n {\n name,\n label: convertCase(name, \"sentence\"),\n tags: iconTags.join(\", \"),\n node,\n terms: normaliseTerms([name, ...iconTags].join(\" \")),\n },\n ];\n });\n}\n\n/** The library once asked for, held so every field in a Studio session shares the one request. */\nlet libraryRequest: Promise<LibraryIcon[]> | undefined = undefined;\n\n/**\n * Reads the icon library, sharing a single request across every field opened in the session. The\n * library is a megabyte of data that never changes within a release, so asking twice only ever costs.\n *\n * @returns Every icon the library offers.\n */\nexport async function requestLibrary() {\n libraryRequest ??= readLibrary();\n const library = await libraryRequest;\n\n return library;\n}\n","import { useEffect, useState } from \"react\";\n\nimport type { LibraryIcon } from \"@/lib/library\";\nimport { requestLibrary } from \"@/lib/library\";\n\n/**\n * Reads the icon library, sharing one request with every other field in the session. Callers mount\n * only while a picker is open, so a Studio that never opens one never pays the megabyte it costs.\n *\n * @returns Every icon the library offers, or undefined while it is still being read.\n */\nexport function useIconLibrary() {\n const [library, setLibrary] = useState<LibraryIcon[]>();\n\n useEffect(() => {\n let active = true;\n\n async function load() {\n const loaded = await requestLibrary();\n if (active) setLibrary(loaded);\n }\n\n void load();\n\n return () => {\n active = false;\n };\n }, []);\n\n return library;\n}\n","/** Where the icons an author reached for last are kept, in the browser rather than the dataset. */\nconst storageKey = \"driftime:sanity-plugin-icon:recent\";\n\n/** How many icons are remembered. */\nconst limit = 8;\n\n/**\n * Reads the icons an author reached for last.\n *\n * @returns Names of the remembered icons, most recent first.\n */\nexport function readRecent() {\n try {\n const stored: unknown = JSON.parse(globalThis.localStorage.getItem(storageKey) ?? \"[]\");\n if (!Array.isArray(stored)) return [];\n\n return stored.filter((entry: unknown) => typeof entry === \"string\");\n } catch {\n return [];\n }\n}\n\n/**\n * Remembers an icon as the one reached for most recently.\n *\n * @param name - Name of the chosen icon.\n * @returns Names of the remembered icons, most recent first.\n */\nexport function writeRecent(name: string) {\n const updated = [name, ...readRecent().filter((entry) => entry !== name)].slice(0, limit);\n\n try {\n globalThis.localStorage.setItem(storageKey, JSON.stringify(updated));\n } catch {\n // A Studio with storage blocked simply does not remember, which is not worth reporting.\n }\n\n return updated;\n}\n\n/** Forgets every icon reached for so far. */\nexport function clearRecent() {\n try {\n globalThis.localStorage.removeItem(storageKey);\n } catch {\n // A Studio with storage blocked has nothing to forget.\n }\n}\n","import { useState } from \"react\";\n\nimport { clearRecent, readRecent, writeRecent } from \"@/lib/recent\";\n\n/**\n * Tracks the icons an author reached for last, keeping what is remembered and what is drawn in step.\n * The stored list is read as the picker mounts, so another tab choosing an icon is picked up too.\n *\n * @returns The remembered names, most recent first, alongside ways to add to and empty them.\n */\nexport function useRecentIcons() {\n const [recent, setRecent] = useState<string[]>(readRecent);\n\n function remember(name: string) {\n setRecent(writeRecent(name));\n }\n\n function forget() {\n clearRecent();\n setRecent([]);\n }\n\n return { recent, remember, forget };\n}\n","import { gridColumns, gridOverscan, gridVisibleRows } from \"@/config/grid\";\n\n/**\n * Works out which icon a key press moves to, so the library can be walked without a mouse.\n *\n * @param key - The key pressed.\n * @param current - Index of the icon the grid is on.\n * @param last - Index of the final icon in the results.\n * @returns The index moved to, or undefined when the key does not move.\n */\nexport function getNextIndex(key: string, current: number, last: number) {\n if (key === \"ArrowRight\") return current + 1;\n if (key === \"ArrowLeft\") return current - 1;\n if (key === \"ArrowDown\") return current + gridColumns;\n if (key === \"ArrowUp\") return current - gridColumns;\n if (key === \"Home\") return 0;\n if (key === \"End\") return last;\n\n return undefined;\n}\n\n/**\n * Works out which rows the grid builds for a given scroll position, so only the icons near the\n * viewport are mounted. The rows above and below stand in as padding, keeping the scrollbar honest.\n *\n * @param scrollRow - Row the scrolling area has reached.\n * @param count - Number of icons in the results.\n * @returns The row the grid starts building at, the row it stops at, and the row count in total.\n */\nexport function getVisibleRows(scrollRow: number, count: number) {\n const totalRows = Math.ceil(count / gridColumns);\n const firstRow = Math.max(0, scrollRow - gridOverscan);\n const lastRow = Math.min(totalRows, firstRow + gridVisibleRows + gridOverscan * 2);\n\n return { totalRows, firstRow, lastRow };\n}\n","import { SearchIcon } from \"@sanity/icons/Search\";\nimport { Box, Button, Dialog, Flex, Grid, Spinner, Stack, Text, TextInput } from \"@sanity/ui\";\nimport type { ChangeEvent, ComponentProps, KeyboardEvent, MouseEvent } from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { Cell } from \"@/components/picker/cell\";\nimport { Recent } from \"@/components/picker/recent\";\nimport type { HoveredIcon } from \"@/components/picker/tooltip\";\nimport { Tooltip } from \"@/components/picker/tooltip\";\nimport { defaultIconProps } from \"@/config/defaults\";\nimport { gridColumns, gridHeight, gridLayoutStyle, gridRowHeight } from \"@/config/grid\";\nimport { useIconLibrary } from \"@/hooks/use-icon-library\";\nimport { useRecentIcons } from \"@/hooks/use-recent-icons\";\nimport { getNextIndex, getVisibleRows } from \"@/lib/grid\";\nimport type { LibraryIcon } from \"@/lib/library\";\nimport { normaliseTerms } from \"@/lib/library\";\nimport { isDefined } from \"@/lib/utils\";\n\nexport type PickerProps = Omit<\n ComponentProps<typeof Dialog>,\n \"children\" | \"header\" | \"width\" | \"selected\" | \"onSelect\"\n> & {\n selected: string | undefined;\n onSelect: (icon: LibraryIcon) => void;\n};\n\nexport function Picker({ selected, onSelect, ...props }: PickerProps) {\n const library = useIconLibrary();\n const { recent, remember, forget } = useRecentIcons();\n\n const [search, setSearch] = useState(\"\");\n const [scrollRow, setScrollRow] = useState(0);\n const [movedIndex, setMovedIndex] = useState<number>();\n const [hovered, setHovered] = useState<HoveredIcon>();\n const [scrolling, setScrolling] = useState(false);\n\n const scroller = useRef<HTMLDivElement>(null);\n const activeCell = useRef<HTMLButtonElement>(null);\n const focusActiveCell = useRef(false);\n const scrollFrame = useRef<number>(undefined);\n const scrollStop = useRef<ReturnType<typeof setTimeout>>(undefined);\n const hoverStart = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n const query = normaliseTerms(search);\n const searching = isDefined(query);\n const results = (library ?? []).filter((icon) => !searching || icon.terms.includes(query));\n\n const byName = new Map((library ?? []).map((icon) => [icon.name, icon]));\n const recentIcons = searching\n ? []\n : recent.flatMap((entry) => {\n const icon = byName.get(entry);\n\n return isDefined(icon) ? [icon] : [];\n });\n\n const { totalRows, firstRow, lastRow } = getVisibleRows(scrollRow, results.length);\n const visible = results.slice(firstRow * gridColumns, lastRow * gridColumns);\n\n // Derived rather than stored, so the grid cannot disagree with what is selected.\n const selectedIndex =\n searching || !isDefined(library) || !isDefined(selected) ? -1 : library.findIndex((icon) => icon.name === selected);\n const activeIndex = movedIndex ?? Math.max(0, selectedIndex);\n\n useEffect(() => {\n const element = scroller.current;\n if (!isDefined(element) || selectedIndex === -1) return;\n\n element.scrollTop = Math.max(0, Math.floor(selectedIndex / gridColumns) * gridRowHeight - gridHeight / 2);\n }, [selectedIndex]);\n\n useEffect(\n () => () => {\n if (isDefined(scrollFrame.current)) cancelAnimationFrame(scrollFrame.current);\n if (isDefined(scrollStop.current)) clearTimeout(scrollStop.current);\n if (isDefined(hoverStart.current)) clearTimeout(hoverStart.current);\n },\n [],\n );\n\n useEffect(() => {\n if (!focusActiveCell.current) return;\n\n focusActiveCell.current = false;\n if (isDefined(activeCell.current)) activeCell.current.focus();\n }, [activeIndex]);\n\n function handleSelect(icon: LibraryIcon) {\n remember(icon.name);\n onSelect(icon);\n }\n\n function handleSearch(event: ChangeEvent<HTMLInputElement>) {\n setSearch(event.currentTarget.value);\n setMovedIndex(undefined);\n\n if (isDefined(scroller.current)) scroller.current.scrollTop = 0;\n }\n\n function selectActive() {\n const icon = results[activeIndex];\n\n if (isDefined(icon)) handleSelect(icon);\n }\n\n function handleSearchKeyDown(event: KeyboardEvent<HTMLInputElement>) {\n if (event.key === \"Enter\") {\n event.preventDefault();\n selectActive();\n\n return;\n }\n\n if (event.key !== \"ArrowDown\") return;\n\n event.preventDefault();\n\n if (isDefined(activeCell.current)) activeCell.current.focus();\n }\n\n // Coalesced to a frame, so a scroll gesture moves the window a row at a time rather than per event.\n function handleScroll() {\n if (isDefined(hoverStart.current)) clearTimeout(hoverStart.current);\n setHovered(undefined);\n if (!scrolling) setScrolling(true);\n\n if (isDefined(scrollStop.current)) clearTimeout(scrollStop.current);\n scrollStop.current = setTimeout(() => {\n setScrolling(false);\n }, 150);\n\n if (isDefined(scrollFrame.current)) return;\n\n scrollFrame.current = requestAnimationFrame(() => {\n scrollFrame.current = undefined;\n\n const element = scroller.current;\n if (isDefined(element)) setScrollRow(Math.floor(element.scrollTop / gridRowHeight));\n });\n }\n\n // Rows passing under a still cursor fire hover events of their own, hence the scroll guard.\n function handleHover(event: MouseEvent<HTMLElement>) {\n if (scrolling) return;\n\n // Element rather than HTMLElement, since the glyph under the cursor is an SVG and inherits neither.\n const target = event.target instanceof Element ? event.target.closest(\"[data-icon]\") : undefined;\n const cell = target instanceof HTMLElement ? target : undefined;\n\n if (cell === hovered?.element) return;\n\n const name = cell?.dataset[\"icon\"];\n const icon = isDefined(name) ? byName.get(name) : undefined;\n\n if (isDefined(hoverStart.current)) clearTimeout(hoverStart.current);\n\n if (!isDefined(icon) || !isDefined(cell)) {\n setHovered(undefined);\n\n return;\n }\n\n // Once one tooltip is up, the next follows the cursor rather than waiting again.\n if (isDefined(hovered)) {\n setHovered({ icon, element: cell });\n\n return;\n }\n\n hoverStart.current = setTimeout(() => {\n setHovered({ icon, element: cell });\n }, 200);\n }\n\n function clearHover() {\n if (isDefined(hoverStart.current)) clearTimeout(hoverStart.current);\n if (isDefined(hovered)) setHovered(undefined);\n }\n\n function handleGridKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n const last = results.length - 1;\n if (last < 0) return;\n\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n selectActive();\n\n return;\n }\n\n const next = getNextIndex(event.key, activeIndex, last);\n if (!isDefined(next)) return;\n\n event.preventDefault();\n\n const index = Math.min(Math.max(next, 0), last);\n focusActiveCell.current = true;\n setMovedIndex(index);\n\n // Worked out from the index rather than the cell, since Home and End can land outside the window.\n const element = scroller.current;\n if (!isDefined(element)) return;\n\n const top = Math.floor(index / gridColumns) * gridRowHeight;\n\n if (top < element.scrollTop) {\n element.scrollTop = top;\n } else if (top + gridRowHeight > element.scrollTop + gridHeight) {\n element.scrollTop = top + gridRowHeight - gridHeight;\n }\n }\n\n return (\n <Dialog header=\"Select icon\" width={1} {...props}>\n <Stack gap={4} padding={4}>\n <TextInput\n icon={<SearchIcon {...defaultIconProps} />}\n placeholder=\"Search by name or by what the icon depicts\"\n value={search}\n onChange={handleSearch}\n onKeyDown={handleSearchKeyDown}\n disabled={!isDefined(library)}\n aria-label=\"Search the icon library\"\n />\n {!isDefined(library) && (\n <Flex align=\"center\" justify=\"center\" style={{ height: gridHeight }}>\n <Spinner muted />\n </Flex>\n )}\n {isDefined(recentIcons) && (\n <Recent\n icons={recentIcons}\n selected={selected}\n onSelect={handleSelect}\n onForget={forget}\n onMouseOver={handleHover}\n onMouseLeave={clearHover}\n />\n )}\n {isDefined(library) && (\n <Stack gap={3}>\n <Box paddingY={2}>\n <Text size={1} weight=\"medium\" muted>\n All icons ({results.length.toLocaleString(\"en-GB\")})\n </Text>\n </Box>\n <Box\n ref={scroller}\n role=\"listbox\"\n aria-label=\"Icon library\"\n onScroll={handleScroll}\n onMouseOver={handleHover}\n onMouseLeave={clearHover}\n onKeyDown={handleGridKeyDown}\n style={{ height: gridHeight, overflowY: \"auto\" }}\n >\n {results.length === 0 && (\n <Flex align=\"center\" justify=\"center\" direction=\"column\" gap={3} style={{ height: gridHeight }}>\n <Text size={1} muted>\n Nothing matches “{search}”.\n </Text>\n <Button\n type=\"button\"\n mode=\"ghost\"\n text=\"Clear search\"\n onClick={() => {\n setSearch(\"\");\n setMovedIndex(undefined);\n }}\n />\n </Flex>\n )}\n {results.length > 0 && (\n <Grid\n gridTemplateColumns={gridColumns}\n style={{\n ...gridLayoutStyle,\n paddingTop: firstRow * gridRowHeight,\n paddingBottom: (totalRows - lastRow) * gridRowHeight,\n }}\n >\n {visible.map((icon, offset) => {\n const index = firstRow * gridColumns + offset;\n\n return (\n <Cell\n key={icon.name}\n ref={index === activeIndex ? activeCell : undefined}\n icon={icon}\n selected={icon.name === selected}\n focusable={index === activeIndex}\n position={index + 1}\n total={results.length}\n onSelect={handleSelect}\n />\n );\n })}\n </Grid>\n )}\n </Box>\n </Stack>\n )}\n <Tooltip key={hovered?.icon.name} hovered={hovered} />\n </Stack>\n </Dialog>\n );\n}\n","/** A value that may be absent, covering both null and undefined. */\nexport type Nullable<T> = T | null | undefined;\n\n/** Type name of the icon object. */\nexport const iconTypeName = \"icon\";\n\n/**\n * An icon an author chose, stored as the name it was chosen by alongside the shapes it draws.\n *\n * @public\n */\nexport interface SanityIcon {\n _type: typeof iconTypeName;\n /** Name the icon goes by in the library it was taken from. */\n name?: string;\n /** Shapes the icon is drawn from, written when the icon is chosen. */\n node?: string;\n}\n","import { CloseIcon } from \"@sanity/icons/Close\";\nimport { Button, Flex } from \"@sanity/ui\";\nimport { useState } from \"react\";\nimport type { ObjectInputProps } from \"sanity\";\nimport { set, setIfMissing, unset } from \"sanity\";\n\nimport { Drawing } from \"@/components/drawing\";\nimport { Picker } from \"@/components/picker/picker\";\nimport { defaultIconProps } from \"@/config/defaults\";\nimport type { LibraryIcon } from \"@/lib/library\";\nimport { resolveIconNode, serialiseIconNode } from \"@/lib/nodes\";\nimport { convertCase, isDefined } from \"@/lib/utils\";\nimport type { SanityIcon } from \"@/types\";\nimport { iconTypeName } from \"@/types\";\n\nexport type InputProps = ObjectInputProps<Partial<SanityIcon>>;\n\nexport function Input({ id, value, onChange, readOnly }: InputProps) {\n const { name, node } = value ?? {};\n\n const [open, setOpen] = useState(false);\n\n const selectedNode = resolveIconNode(node);\n const selectedLabel = isDefined(name) ? convertCase(name, \"sentence\") : undefined;\n\n function handleSelect(icon: LibraryIcon) {\n onChange([\n setIfMissing({ _type: iconTypeName satisfies SanityIcon[\"_type\"] }),\n set(icon.name, [\"name\" satisfies keyof SanityIcon]),\n set(serialiseIconNode(icon.node), [\"node\" satisfies keyof SanityIcon]),\n ]);\n\n setOpen(false);\n }\n\n return (\n <Flex gap={2}>\n <Button\n id={id}\n type=\"button\"\n mode=\"ghost\"\n icon={isDefined(selectedNode) ? <Drawing node={selectedNode} {...defaultIconProps} /> : undefined}\n text={selectedLabel ?? \"Select icon\"}\n disabled={readOnly}\n onClick={() => {\n setOpen(true);\n }}\n aria-label={isDefined(selectedLabel) ? `${selectedLabel} currently selected` : \"Select icon\"}\n />\n {isDefined(value) && (\n <Button\n type=\"button\"\n mode=\"ghost\"\n tone=\"critical\"\n icon={<CloseIcon {...defaultIconProps} />}\n text=\"Clear\"\n disabled={readOnly}\n onClick={() => {\n onChange(unset());\n }}\n aria-label=\"Clear the currently selected icon.\"\n />\n )}\n {open && (\n <Picker\n id={`${id}-library`}\n selected={name}\n onSelect={handleSelect}\n onClose={() => {\n setOpen(false);\n }}\n onClickOutside={() => {\n setOpen(false);\n }}\n />\n )}\n </Flex>\n );\n}\n","import { Drawing } from \"@/components/drawing\";\nimport { defaultIconProps } from \"@/config/defaults\";\nimport { resolveIconNode } from \"@/lib/nodes\";\nimport { isDefined } from \"@/lib/utils\";\nimport type { SanityIcon } from \"@/types\";\n\n/**\n * Builds the media a stored icon previews with, so a document lists the drawing an author chose\n * rather than one placeholder standing in for every icon alike.\n *\n * @param value - The stored icon.\n * @returns The media component, or undefined when nothing readable was stored.\n * @public\n */\nexport function createIconPreview(value: SanityIcon | undefined) {\n const node = resolveIconNode(value?.node);\n if (!isDefined(node)) return undefined;\n\n return function IconPreview() {\n return <Drawing node={node} {...defaultIconProps} />;\n };\n}\n","import type { ComponentProps } from \"react\";\n\nexport type SquareDashedIconProps = ComponentProps<\"svg\">;\n\nexport function SquareDashedIcon(props: SquareDashedIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={24}\n height={24}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M5 3a2 2 0 0 0-2 2\" />\n <path d=\"M19 3a2 2 0 0 1 2 2\" />\n <path d=\"M21 19a2 2 0 0 1-2 2\" />\n <path d=\"M5 21a2 2 0 0 1-2-2\" />\n <path d=\"M9 3h1\" />\n <path d=\"M9 21h1\" />\n <path d=\"M14 3h1\" />\n <path d=\"M14 21h1\" />\n <path d=\"M3 9v1\" />\n <path d=\"M21 9v1\" />\n <path d=\"M3 14v1\" />\n <path d=\"M21 14v1\" />\n </svg>\n );\n}\n","import type { ComponentProps, ComponentType } from \"react\";\nimport { createElement } from \"react\";\n\nimport { defaultIconProps } from \"@/config/defaults\";\n\n/**\n * Creates a Sanity Studio icon component from an SVG icon.\n *\n * @param icon - The icon component to wrap.\n * @param props - Additional props merged over the default properties a Studio icon is drawn with.\n * @returns A Studio icon component.\n */\nexport function createSanityIcon(icon: ComponentType<ComponentProps<\"svg\">>, props?: ComponentProps<\"svg\">) {\n const Icon = icon;\n\n function SanityIcon() {\n return createElement(Icon, { ...defaultIconProps, ...props });\n }\n\n return SanityIcon;\n}\n","import { defineField, defineType } from \"sanity\";\n\nimport { Field } from \"@/components/field\";\nimport { Input } from \"@/components/input\";\nimport { createIconPreview } from \"@/components/preview\";\nimport { SquareDashedIcon } from \"@/icons/square-dashed\";\nimport { createSanityIcon } from \"@/lib/icons\";\nimport { convertCase, isDefined } from \"@/lib/utils\";\nimport type { SanityIcon } from \"@/types\";\nimport { iconTypeName } from \"@/types\";\n\nexport const iconType = defineType({\n name: iconTypeName satisfies SanityIcon[\"_type\"],\n type: \"object\",\n icon: createSanityIcon(SquareDashedIcon),\n description: \"Icon chosen from the Lucide library.\",\n components: { field: Field, input: Input },\n preview: {\n select: {\n name: \"name\",\n node: \"node\",\n },\n prepare(selection: { name?: string; node?: string }) {\n const { name, node } = selection;\n\n return {\n title: isDefined(name) ? convertCase(name, \"sentence\") : \"No icon\",\n media: createIconPreview({ _type: iconTypeName, name, node }),\n };\n },\n },\n fields: [\n defineField({\n name: \"name\" satisfies keyof SanityIcon,\n type: \"string\",\n description: \"Name of the chosen icon in the library it was taken from.\",\n }),\n defineField({\n name: \"node\" satisfies keyof SanityIcon,\n type: \"text\",\n description: \"Shapes the icon is drawn from, written when the icon is chosen.\",\n }),\n ],\n});\n","import { definePlugin } from \"sanity\";\n\nimport { iconType } from \"@/schemas/types/icon\";\n\n/**\n * Creates the icon field type for Sanity Studio, offering the Lucide library through a searchable\n * picker and storing the chosen drawing ready to render.\n *\n * @returns Sanity plugin definition.\n * @public\n */\nexport const iconPlugin = definePlugin({\n name: \"@driftime/sanity-plugin-icon\",\n schema: {\n types: [iconType],\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["isDefined","useState","ArrayOfObjectsFormNode","ArrayOfObjectsMember","BaseFormNode","DocumentFieldActionNode","ObjectFieldProps","ObjectFormNode","ObjectMember","ChangeIndicator","FieldActionsProvider","FieldActionsResolver","FormField","getPublishedId","useFormValue","hasMembers","node","collectNodeValidation","validation","collectMemberValidation","members","flatMap","member","kind","field","fieldSet","item","FieldProps","Field","t0","$","_c","actions","schemaType","title","description","presence","level","inputId","path","changed","children","inputProps","t1","Symbol","for","headerActions","setHeaderActions","t2","documentId","fieldValidation","focused","t3","publishedId","undefined","t4","name","t5","readOnly","deprecated","t6","t7","ComponentProps","ComponentType","createElement","defaultIconProps","width","height","strokeWidth","createSanityIcon","icon","props","Icon","SanityIcon","gridCellSize","gridRowGap","gridRowHeight","gridColumns","gridVisibleRows","gridHeight","gridOverscan","gridLayoutStyle","justifyItems","rowGap","const","Button","ComponentProps","Drawing","gridCellSize","LibraryIcon","CellProps","Omit","icon","selected","focusable","position","total","onSelect","onHover","element","HTMLElement","Cell","t0","$","_c","props","t1","t2","Symbol","for","width","height","t3","node","t4","t5","event","currentTarget","t6","label","Box","Button","Flex","Grid","Text","ComponentProps","RefObject","CellProps","Cell","gridColumns","gridHeight","gridLayoutStyle","gridRowHeight","getVisibleRows","LibraryIcon","LibraryProps","Omit","icons","rows","ReturnType","selected","activeIndex","activeCell","HTMLButtonElement","search","onSelect","icon","onHover","onClearSearch","Library","t0","$","_c","props","totalRows","firstRow","lastRow","t1","visible","slice","t2","Symbol","for","height","overflowY","t3","length","paddingTop","paddingBottom","map","offset","index","name","undefined","Button","Flex","Grid","Stack","Text","ComponentProps","CellProps","Cell","gridColumns","gridLayoutStyle","LibraryIcon","RecentProps","Omit","icons","selected","onSelect","icon","onHover","onForget","Recent","t0","$","_c","props","t1","Symbol","for","t2","t3","t4","length","index","name","map","t5","isDefined","Stack","Text","Popover","ComponentProps","LibraryIcon","HoveredIcon","icon","element","HTMLElement","tooltipMargins","TooltipProps","Omit","hovered","Tooltip","t0","$","_c","props","t1","t2","t3","Symbol","for","pointerEvents","t4","maxWidth","label","tags","t5","convertCase","isDefined","IconNode","parseIconNode","LibraryIcon","name","label","tags","node","terms","normalizeTerms","value","toLowerCase","replaceAll","trim","selectIcons","library","names","byName","Map","map","icon","Set","flatMap","get","readLibrary","drawings","Promise","all","nodes","Record","default","Object","keys","iconTags","join","libraryRequest","undefined","requestLibrary","useEffect","useState","LibraryIcon","requestLibrary","useIconLibrary","$","_c","library","setLibrary","t0","t1","Symbol","for","active","load","loaded","isDefined","useEffect","useRef","useState","HoveredIcon","LibraryIcon","useIconTooltip","scrolling","$","_c","hovered","setHovered","hoverStart","undefined","t0","t1","Symbol","for","current","clearTimeout","t2","clearHover","t3","handleHover","icon","element","setTimeout","t4","storageKey","limit","readRecent","stored","JSON","parse","globalThis","localStorage","getItem","Array","isArray","filter","entry","writeRecent","name","updated","slice","setItem","stringify","clearRecent","removeItem","useState","clearRecent","readRecent","writeRecent","useRecentIcons","$","_c","recent","setRecent","t0","Symbol","for","remember","name","t1","forget","t2","gridColumns","gridHeight","gridOverscan","gridRowHeight","gridVisibleRows","getNextIndex","key","current","last","undefined","getVisibleRows","scrollRow","count","totalRows","Math","ceil","firstRow","max","lastRow","min","getCenteredScrollTop","index","floor","getRevealedScrollTop","scrollTop","top","isDefined","SearchIcon","Box","Dialog","Flex","Spinner","Stack","Text","TextInput","ChangeEvent","ComponentProps","KeyboardEvent","useEffect","useRef","useState","Library","Recent","Tooltip","gridHeight","gridRowHeight","useIconLibrary","useIconTooltip","useRecentIcons","getCenteredScrollTop","getNextIndex","getRevealedScrollTop","getVisibleRows","LibraryIcon","normalizeTerms","selectIcons","SanityIconName","PickerProps","Omit","allowed","selected","onSelect","icon","Picker","t0","$","_c","props","library","icons","recent","remember","forget","search","setSearch","scrollRow","setScrollRow","movedIndex","setMovedIndex","scrolling","setScrolling","scroller","activeCell","focusIndex","undefined","scrollFrame","scrollStop","query","searching","results","filter","terms","includes","byName","Map","map","_temp","recentIcons","flatMap","entry","icon_1","get","hovered","handleHover","clearHover","rows","length","selectedIndex","findIndex","icon_2","name","activeIndex","Math","max","element","current","scrollTop","t1","t2","Symbol","for","cancelAnimationFrame","clearTimeout","t3","t4","focus","t5","handleSelect","icon_3","t6","clearSearch","handleSearch","event","currentTarget","value","selectActive","icon_4","handleSearchKeyDown","event_0","key","preventDefault","handleScroll","setTimeout","requestAnimationFrame","element_0","floor","handleGridKeyDown","event_1","last","next","index","min","element_1","t7","t8","height","t9","toLocaleString","t10","t11","icon_0","ComponentProps","SquareDashedIconProps","SquareDashedIcon","props","$","_c","t0","t1","t10","t11","t2","t3","t4","t5","t6","t7","t8","t9","Symbol","for","t12","SanityIconConfig","SanityIconOptions","resolveIconOptions","options","config","icons","iconTypeName","SanityIcon","_type","name","node","defaultIconProps","convertCase","isDefined","CloseIcon","Button","Flex","useState","ObjectInputProps","ObjectSchemaType","set","setIfMissing","unset","Drawing","Picker","SquareDashedIcon","LibraryIcon","resolveIconNode","serializeIconNode","resolveIconOptions","SanityIconConfig","SanityIconOptions","SanityIcon","iconTypeName","IconSchemaType","options","InputProps","Partial","createInput","config","Input","t0","$","_c","id","schemaType","value","onChange","readOnly","name","node","open","setOpen","t1","icons","selectedNode","selectedLabel","undefined","t2","handleSelect","icon","_type","T0","t3","T1","t4","t5","t6","t7","t8","t9","t10","t11","t12","t13","defaultIconProps","isDefined","createElement","Drawing","resolveIconNode","SanityIcon","createIconPreview","value","node","undefined","IconPreview","Field","createSanityIcon","convertCase","isDefined","defineField","defineType","createInput","SquareDashedIcon","createIconPreview","SanityIconConfig","SanityIcon","iconTypeName","createIconType","config","name","type","icon","description","components","field","input","validation","rule","custom","value","Partial","node","preview","select","prepare","selection","title","media","_type","fields","iconNodes","ObjectOptions","TypeAliasDefinition","definePlugin","createIconType","iconTypeName","IntrinsicDefinitions","icon","SanityIconDefinition","SanityIconName","SanityIconOptions","icons","Omit","options","SanityIconConfig","plugin","config","name","schema","types","iconPlugin"],"sources":["../../@repo/components/field.tsx","../../@repo/lib/icons.ts","../src/config/grid.ts","../src/components/picker/cell.tsx","../src/components/picker/library.tsx","../src/components/picker/recent.tsx","../src/components/picker/tooltip.tsx","../src/lib/library.ts","../src/hooks/use-icon-library.ts","../src/hooks/use-icon-tooltip.ts","../src/lib/recent.ts","../src/hooks/use-recent-icons.ts","../src/lib/grid.ts","../src/components/picker/picker.tsx","../src/icons/square-dashed.tsx","../src/lib/options.ts","../src/types.ts","../src/components/input.tsx","../src/lib/preview.ts","../src/schemas/types/icon.ts","../src/plugin.ts"],"sourcesContent":["import { isDefined } from \"@repo/lib/utils\";\nimport { useState } from \"react\";\nimport type {\n ArrayOfObjectsFormNode,\n ArrayOfObjectsMember,\n BaseFormNode,\n DocumentFieldActionNode,\n ObjectFieldProps,\n ObjectFormNode,\n ObjectMember,\n} from \"sanity\";\nimport {\n ChangeIndicator,\n FieldActionsProvider,\n FieldActionsResolver,\n FormField,\n getPublishedId,\n useFormValue,\n} from \"sanity\";\n\n/**\n * Checks whether a form node holds members of its own, as an object or an array of objects does.\n *\n * @param node - The form node to check.\n * @returns True if the node holds members.\n */\nfunction hasMembers(node: BaseFormNode): node is ObjectFormNode | ArrayOfObjectsFormNode {\n return \"members\" in node;\n}\n\n/**\n * Gathers the validation reported on a form node and on anything inside it.\n *\n * @param node - The form node to gather validation from.\n * @returns Every validation reported on the node or within it.\n */\nfunction collectNodeValidation(node: BaseFormNode): BaseFormNode[\"validation\"] {\n return [...node.validation, ...(hasMembers(node) ? collectMemberValidation(node.members) : [])];\n}\n\n/**\n * Gathers the validation reported anywhere inside a field's members. The form hands a field only what\n * is reported at its own path, which suits a frame drawing its members inline but leaves one that\n * hides them showing nothing they report.\n *\n * @param members - The members to gather validation from.\n * @returns Every validation reported on a member or within one.\n */\nfunction collectMemberValidation(members: (ObjectMember | ArrayOfObjectsMember)[]): BaseFormNode[\"validation\"] {\n return members.flatMap((member) => {\n if (member.kind === \"field\") return collectNodeValidation(member.field);\n if (member.kind === \"fieldSet\") return collectMemberValidation(member.fieldSet.members);\n if (member.kind === \"item\") return collectNodeValidation(member.item);\n\n return [];\n });\n}\n\nexport type FieldProps = ObjectFieldProps;\n\nexport function Field({\n actions,\n schemaType,\n title,\n description,\n presence,\n validation,\n level,\n inputId,\n path,\n changed,\n children,\n inputProps,\n}: FieldProps) {\n const [headerActions, setHeaderActions] = useState<DocumentFieldActionNode[]>([]);\n\n const documentId = useFormValue([\"_id\"]);\n const publishedId = typeof documentId === \"string\" ? getPublishedId(documentId) : undefined;\n const focused = inputProps.focused === true;\n const fieldValidation = [...validation, ...collectMemberValidation(inputProps.members)];\n\n return (\n <>\n {isDefined(publishedId) && isDefined(actions) && (\n <FieldActionsResolver\n actions={actions}\n documentId={publishedId}\n documentType={schemaType.name}\n onActions={setHeaderActions}\n path={path}\n schemaType={schemaType}\n />\n )}\n <FieldActionsProvider actions={headerActions} focused={focused} path={path}>\n <FormField\n __unstable_headerActions={headerActions}\n __unstable_presence={presence}\n description={description}\n inputId={inputId}\n level={level}\n title={title}\n validation={fieldValidation}\n deprecated={schemaType.deprecated}\n path={path}\n readOnly={inputProps.readOnly}\n >\n <ChangeIndicator path={path} hasFocus={focused} isChanged={changed}>\n {children}\n </ChangeIndicator>\n </FormField>\n </FieldActionsProvider>\n </>\n );\n}\n","import type { ComponentProps, ComponentType } from \"react\";\nimport { createElement } from \"react\";\n\n/**\n * Properties the plugin's own icons are drawn with. Icons taken from `@sanity/icons` are left alone,\n * since they already carry the sizing and stroke the rest of the Studio uses.\n */\nexport const defaultIconProps: ComponentProps<\"svg\"> = { width: \"1em\", height: \"1em\", strokeWidth: 1.5 };\n\n/**\n * Creates a Sanity Studio icon component from an SVG icon.\n *\n * @param icon - The icon component to wrap.\n * @param props - Additional props merged over the default properties a Studio icon is drawn with.\n * @returns A Studio icon component.\n */\nexport function createSanityIcon(icon: ComponentType<ComponentProps<\"svg\">>, props?: ComponentProps<\"svg\">) {\n const Icon = icon;\n\n function SanityIcon() {\n return createElement(Icon, { ...defaultIconProps, ...props });\n }\n\n return SanityIcon;\n}\n","/** Size of one cell, in pixels. Fixed so the grid never reflows. */\nexport const gridCellSize = 40;\n\n/** Space between rows, in pixels. */\nconst gridRowGap = 4;\n\n/** Distance from one row to the next, which placing a window over the grid depends on knowing. */\nexport const gridRowHeight = gridCellSize + gridRowGap;\n\n/** How many icons a row holds. */\nexport const gridColumns = 8;\n\n/** How many rows the scrolling area shows at once. */\nexport const gridVisibleRows = 8;\n\n/** Height of the scrolling area, sized to the rows it shows. The final row carries no trailing gap. */\nexport const gridHeight = gridVisibleRows * gridRowHeight - gridRowGap;\n\n/**\n * Rows built either side of the visible ones. Everything built is also painted, so a row scrolled\n * into view is already there rather than arriving with it.\n */\nexport const gridOverscan = gridVisibleRows;\n\n/** Layout both grids share, so a recent icon sits on the same columns as the library below it. */\nexport const gridLayoutStyle = { justifyItems: \"center\", rowGap: gridRowGap } as const;\n","import { Button } from \"@sanity/ui\";\nimport type { ComponentProps } from \"react\";\n\nimport { Drawing } from \"@/components/drawing\";\nimport { gridCellSize } from \"@/config/grid\";\nimport type { LibraryIcon } from \"@/lib/library\";\n\nexport type CellProps = Omit<\n ComponentProps<typeof Button>,\n \"icon\" | \"selected\" | \"onSelect\" | \"onClick\" | \"onMouseEnter\"\n> & {\n icon: LibraryIcon;\n selected: boolean;\n focusable: boolean;\n position: number;\n total: number;\n onSelect: (icon: LibraryIcon) => void;\n onHover: (icon: LibraryIcon, element: HTMLElement) => void;\n};\n\nexport function Cell({ icon, selected, focusable, position, total, onSelect, onHover, ...props }: CellProps) {\n return (\n <Button\n type=\"button\"\n role=\"option\"\n aria-selected={selected}\n aria-posinset={position}\n aria-setsize={total}\n tabIndex={focusable ? 0 : -1}\n mode=\"bleed\"\n selected={selected}\n padding={0}\n style={{ width: gridCellSize, height: gridCellSize }}\n icon={<Drawing node={icon.node} width=\"1.25em\" height=\"1.25em\" strokeWidth={1.5} />}\n aria-label={icon.label}\n onClick={() => {\n onSelect(icon);\n }}\n onMouseEnter={(event) => {\n onHover(icon, event.currentTarget);\n }}\n {...props}\n />\n );\n}\n","import { Box, Button, Flex, Grid, Text } from \"@sanity/ui\";\nimport type { ComponentProps, RefObject } from \"react\";\n\nimport type { CellProps } from \"@/components/picker/cell\";\nimport { Cell } from \"@/components/picker/cell\";\nimport { gridColumns, gridHeight, gridLayoutStyle, gridRowHeight } from \"@/config/grid\";\nimport type { getVisibleRows } from \"@/lib/grid\";\nimport type { LibraryIcon } from \"@/lib/library\";\n\nexport type LibraryProps = Omit<ComponentProps<typeof Box>, \"children\" | \"onSelect\"> & {\n icons: LibraryIcon[];\n rows: ReturnType<typeof getVisibleRows>;\n selected: string | undefined;\n activeIndex: number;\n activeCell: RefObject<HTMLButtonElement | null>;\n search: string;\n onSelect: (icon: LibraryIcon) => void;\n onHover: CellProps[\"onHover\"];\n onClearSearch: () => void;\n};\n\nexport function Library({\n icons,\n rows,\n selected,\n activeIndex,\n activeCell,\n search,\n onSelect,\n onHover,\n onClearSearch,\n ...props\n}: LibraryProps) {\n const { totalRows, firstRow, lastRow } = rows;\n const visible = icons.slice(firstRow * gridColumns, lastRow * gridColumns);\n\n return (\n <Box role=\"listbox\" aria-label=\"Icon library\" style={{ height: gridHeight, overflowY: \"auto\" }} {...props}>\n {icons.length === 0 && (\n <Flex align=\"center\" justify=\"center\" direction=\"column\" gap={3} style={{ height: gridHeight }}>\n <Text size={1} muted>{`Nothing matches \"${search}\".`}</Text>\n <Button type=\"button\" mode=\"ghost\" text=\"Clear search\" onClick={onClearSearch} />\n </Flex>\n )}\n {icons.length > 0 && (\n <Grid\n gridTemplateColumns={gridColumns}\n style={{\n ...gridLayoutStyle,\n paddingTop: firstRow * gridRowHeight,\n paddingBottom: (totalRows - lastRow) * gridRowHeight,\n }}\n >\n {visible.map((icon, offset) => {\n const index = firstRow * gridColumns + offset;\n\n return (\n <Cell\n key={icon.name}\n ref={index === activeIndex ? activeCell : undefined}\n icon={icon}\n selected={icon.name === selected}\n focusable={index === activeIndex}\n position={index + 1}\n total={icons.length}\n onSelect={onSelect}\n onHover={onHover}\n />\n );\n })}\n </Grid>\n )}\n </Box>\n );\n}\n","import { Button, Flex, Grid, Stack, Text } from \"@sanity/ui\";\nimport type { ComponentProps } from \"react\";\n\nimport type { CellProps } from \"@/components/picker/cell\";\nimport { Cell } from \"@/components/picker/cell\";\nimport { gridColumns, gridLayoutStyle } from \"@/config/grid\";\nimport type { LibraryIcon } from \"@/lib/library\";\n\nexport type RecentProps = Omit<ComponentProps<typeof Stack>, \"children\" | \"onSelect\"> & {\n icons: LibraryIcon[];\n selected: string | undefined;\n onSelect: (icon: LibraryIcon) => void;\n onHover: CellProps[\"onHover\"];\n onForget: () => void;\n};\n\nexport function Recent({ icons, selected, onSelect, onHover, onForget, ...props }: RecentProps) {\n return (\n <Stack gap={3} {...props}>\n <Flex align=\"center\" justify=\"space-between\" gap={2}>\n <Text size={1} weight=\"medium\" muted>\n Recent icons\n </Text>\n <Button\n type=\"button\"\n mode=\"bleed\"\n fontSize={1}\n padding={2}\n text=\"Clear\"\n onClick={onForget}\n aria-label=\"Forget the recently used icons\"\n />\n </Flex>\n <Grid role=\"listbox\" aria-label=\"Recent icons\" gridTemplateColumns={gridColumns} style={gridLayoutStyle}>\n {icons.map((icon, index) => (\n <Cell\n key={icon.name}\n icon={icon}\n selected={icon.name === selected}\n focusable\n position={index + 1}\n total={icons.length}\n onSelect={onSelect}\n onHover={onHover}\n />\n ))}\n </Grid>\n </Stack>\n );\n}\n","import { isDefined } from \"@repo/lib/utils\";\nimport { Stack, Text } from \"@sanity/ui\";\nimport { Popover } from \"@sanity/ui/popover\";\nimport type { ComponentProps } from \"react\";\n\nimport type { LibraryIcon } from \"@/lib/library\";\n\n/** The icon a tooltip is describing, paired with the cell it points at. */\nexport interface HoveredIcon {\n /** Icon the cell holds. */\n icon: LibraryIcon;\n /** Cell the tooltip anchors itself to. */\n element: HTMLElement;\n}\n\n/**\n * Gap between a tooltip and the cell it points at, given as margins because that is the only lever\n * `@sanity/ui` offers for it. Top only, since a tooltip always sits above.\n */\nconst tooltipMargins: [number, number, number, number] = [-4, 0, 0, 0];\n\nexport type TooltipProps = Omit<ComponentProps<typeof Popover>, \"open\" | \"referenceElement\" | \"content\"> & {\n hovered: HoveredIcon | undefined;\n};\n\nexport function Tooltip({ hovered, ...props }: TooltipProps) {\n return (\n <Popover\n open={isDefined(hovered)}\n referenceElement={hovered?.element ?? null}\n placement=\"top\"\n portal\n padding={3}\n __unstable_margins={tooltipMargins}\n style={{ pointerEvents: \"none\" }}\n content={\n isDefined(hovered) && (\n <Stack gap={3} style={{ maxWidth: \"16rem\" }}>\n <Text size={1} weight=\"medium\">\n {hovered.icon.label}\n </Text>\n {isDefined(hovered.icon.tags) && (\n <Text size={1} muted>\n {hovered.icon.tags}\n </Text>\n )}\n </Stack>\n )\n }\n {...props}\n />\n );\n}\n","import { convertCase, isDefined } from \"@repo/lib/utils\";\n\nimport type { IconNode } from \"@/lib/nodes\";\nimport { parseIconNode } from \"@/lib/nodes\";\n\n/** Single icon the library offers, carrying the terms a search matches it on. */\nexport interface LibraryIcon {\n /** Name the icon goes by in the library it came from. */\n name: string;\n /** Readable form of the name, shown beside the icon. */\n label: string;\n /** What the icon depicts, as a readable list. */\n tags: string;\n /** Shapes the icon is drawn from. */\n node: IconNode;\n /** Name and tags flattened into the form a search compares against. */\n terms: string;\n}\n\n/**\n * Flattens text into the form a search compares against, so a hyphenated icon name and a multi-word\n * tag are matched the same way.\n *\n * @param value - The text to flatten.\n * @returns The text in comparable form.\n */\nexport function normalizeTerms(value: string) {\n return value\n .toLowerCase()\n .replaceAll(/[\\s-]+/gu, \" \")\n .trim();\n}\n\n/**\n * Narrows the library to a chosen set of icons, in the order they were named. A name the library does\n * not recognise is skipped, so a set outlives the release it was written against.\n *\n * @param library - Every icon the library offers.\n * @param names - Names of the icons to offer, or nothing to offer them all.\n * @returns The icons on offer.\n */\nexport function selectIcons(library: LibraryIcon[], names: string[] | undefined) {\n if (!isDefined(names)) return library;\n\n const byName = new Map(library.map((icon) => [icon.name, icon]));\n\n return [...new Set(names)].flatMap((name) => {\n const icon = byName.get(name);\n\n return isDefined(icon) ? [icon] : [];\n });\n}\n\n/**\n * Reads the icon library, pairing each drawing with the terms it can be found by. Both files come\n * from the same release as the icons themselves, so the drawings and their terms never disagree.\n *\n * @returns Every icon the library offers.\n */\nasync function readLibrary() {\n const [drawings, tags] = await Promise.all([\n import(\"lucide-static/icon-nodes.json\"),\n import(\"lucide-static/tags.json\"),\n ]);\n\n const nodes: Record<string, unknown> = drawings.default;\n const terms: Record<string, string[]> = tags.default;\n\n return Object.keys(nodes).flatMap((name) => {\n const node = parseIconNode(nodes[name]);\n if (!isDefined(node)) return [];\n\n const iconTags = terms[name] ?? [];\n\n return [\n {\n name,\n label: convertCase(name, \"sentence\"),\n tags: iconTags.join(\", \"),\n node,\n terms: normalizeTerms([name, ...iconTags].join(\" \")),\n },\n ];\n });\n}\n\n/**\n * The library once asked for, held so every field in a Studio session shares the one request. It is a\n * megabyte of data that never changes within a release, so asking twice only ever costs.\n */\nlet libraryRequest: Promise<LibraryIcon[]> | undefined = undefined;\n\n/**\n * Reads the icon library, waiting on whatever request is already under way.\n *\n * @returns Every icon the library offers.\n */\nexport async function requestLibrary() {\n libraryRequest ??= readLibrary();\n const library = await libraryRequest;\n\n return library;\n}\n","import { useEffect, useState } from \"react\";\n\nimport type { LibraryIcon } from \"@/lib/library\";\nimport { requestLibrary } from \"@/lib/library\";\n\n/**\n * Reads the icon library. Callers mount only while a picker is open, so a Studio that never opens one\n * never pays what it costs to read.\n *\n * @returns Every icon the library offers, or undefined while it is still being read.\n */\nexport function useIconLibrary() {\n const [library, setLibrary] = useState<LibraryIcon[]>();\n\n useEffect(() => {\n let active = true;\n\n async function load() {\n const loaded = await requestLibrary();\n if (active) setLibrary(loaded);\n }\n\n void load();\n\n return () => {\n active = false;\n };\n }, []);\n\n return library;\n}\n","import { isDefined } from \"@repo/lib/utils\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport type { HoveredIcon } from \"@/components/picker/tooltip\";\nimport type { LibraryIcon } from \"@/lib/library\";\n\n/**\n * Tracks which icon the cursor rests on, holding a tooltip back until it has settled somewhere.\n *\n * @param scrolling - Whether the grid is currently moving under the cursor.\n * @returns The icon being hovered, alongside ways to follow the cursor and to dismiss it.\n */\nexport function useIconTooltip(scrolling: boolean) {\n const [hovered, setHovered] = useState<HoveredIcon>();\n const hoverStart = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n useEffect(\n () => () => {\n if (isDefined(hoverStart.current)) clearTimeout(hoverStart.current);\n },\n [],\n );\n\n function clearHover() {\n if (isDefined(hoverStart.current)) clearTimeout(hoverStart.current);\n if (isDefined(hovered)) setHovered(undefined);\n }\n\n function handleHover(icon: LibraryIcon, element: HTMLElement) {\n if (scrolling || element === hovered?.element) return;\n\n if (isDefined(hoverStart.current)) clearTimeout(hoverStart.current);\n\n if (isDefined(hovered)) {\n setHovered({ icon, element });\n\n return;\n }\n\n hoverStart.current = setTimeout(() => {\n setHovered({ icon, element });\n }, 200);\n }\n\n return { hovered, handleHover, clearHover };\n}\n","/** Where the icons an author reached for last are kept, in the browser rather than the dataset. */\nconst storageKey = \"driftime:sanity-plugin-icon:recent\";\n\n/** How many icons are remembered. */\nconst limit = 8;\n\n/**\n * Reads the icons an author reached for last.\n *\n * @returns Names of the remembered icons, most recent first.\n */\nexport function readRecent() {\n try {\n const stored: unknown = JSON.parse(globalThis.localStorage.getItem(storageKey) ?? \"[]\");\n if (!Array.isArray(stored)) return [];\n\n return stored.filter((entry: unknown) => typeof entry === \"string\");\n } catch {\n return [];\n }\n}\n\n/**\n * Remembers an icon as the one reached for most recently.\n *\n * @param name - Name of the chosen icon.\n * @returns Names of the remembered icons, most recent first.\n */\nexport function writeRecent(name: string) {\n const updated = [name, ...readRecent().filter((entry) => entry !== name)].slice(0, limit);\n\n try {\n globalThis.localStorage.setItem(storageKey, JSON.stringify(updated));\n } catch {\n // A Studio with storage blocked simply does not remember, which is not worth reporting.\n }\n\n return updated;\n}\n\n/** Forgets every icon reached for so far. */\nexport function clearRecent() {\n try {\n globalThis.localStorage.removeItem(storageKey);\n } catch {\n // A Studio with storage blocked has nothing to forget.\n }\n}\n","import { useState } from \"react\";\n\nimport { clearRecent, readRecent, writeRecent } from \"@/lib/recent\";\n\n/**\n * Tracks the icons an author reached for last, keeping what is remembered and what is drawn in step.\n * The stored list is read as the picker mounts, so another tab choosing an icon is picked up too.\n *\n * @returns The remembered names, most recent first, alongside ways to add to and empty them.\n */\nexport function useRecentIcons() {\n const [recent, setRecent] = useState<string[]>(readRecent);\n\n function remember(name: string) {\n setRecent(writeRecent(name));\n }\n\n function forget() {\n clearRecent();\n setRecent([]);\n }\n\n return { recent, remember, forget };\n}\n","import { gridColumns, gridHeight, gridOverscan, gridRowHeight, gridVisibleRows } from \"@/config/grid\";\n\n/**\n * Works out which icon a key press moves to, so the library can be walked without a mouse.\n *\n * @param key - The key pressed.\n * @param current - Index of the icon the grid is on.\n * @param last - Index of the final icon in the results.\n * @returns The index moved to, or undefined when the key does not move.\n */\nexport function getNextIndex(key: string, current: number, last: number) {\n if (key === \"ArrowRight\") return current + 1;\n if (key === \"ArrowLeft\") return current - 1;\n if (key === \"ArrowDown\") return current + gridColumns;\n if (key === \"ArrowUp\") return current - gridColumns;\n if (key === \"Home\") return 0;\n if (key === \"End\") return last;\n\n return undefined;\n}\n\n/**\n * Works out which rows the grid builds for a given scroll position, so only the icons near the\n * viewport are mounted. The rows above and below stand in as padding, keeping the scrollbar honest.\n *\n * @param scrollRow - Row the scrolling area has reached.\n * @param count - Number of icons in the results.\n * @returns The row the grid starts building at, the row it stops at, and the row count in total.\n */\nexport function getVisibleRows(scrollRow: number, count: number) {\n const totalRows = Math.ceil(count / gridColumns);\n const firstRow = Math.max(0, scrollRow - gridOverscan);\n const lastRow = Math.min(totalRows, firstRow + gridVisibleRows + gridOverscan * 2);\n\n return { totalRows, firstRow, lastRow };\n}\n\n/**\n * Works out where the scrolling area sits to show a given icon in the middle, for opening on the\n * icon already chosen.\n *\n * @param index - Index of the icon to show.\n * @returns The position to scroll to.\n */\nexport function getCenteredScrollTop(index: number) {\n return Math.max(0, Math.floor(index / gridColumns) * gridRowHeight - gridHeight / 2);\n}\n\n/**\n * Works out where the scrolling area moves to bring a given icon into view, staying put when the\n * icon already shows. Taken from the index rather than the icon's own cell, since Home and End can\n * land outside the rows that are mounted.\n *\n * @param index - Index of the icon to reveal.\n * @param scrollTop - Position the scrolling area has reached.\n * @returns The position to scroll to.\n */\nexport function getRevealedScrollTop(index: number, scrollTop: number) {\n const top = Math.floor(index / gridColumns) * gridRowHeight;\n\n if (top < scrollTop) return top;\n if (top + gridRowHeight > scrollTop + gridHeight) return top + gridRowHeight - gridHeight;\n\n return scrollTop;\n}\n","import { isDefined } from \"@repo/lib/utils\";\nimport { SearchIcon } from \"@sanity/icons/Search\";\nimport { Box, Dialog, Flex, Spinner, Stack, Text, TextInput } from \"@sanity/ui\";\nimport type { ChangeEvent, ComponentProps, KeyboardEvent } from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { Library } from \"@/components/picker/library\";\nimport { Recent } from \"@/components/picker/recent\";\nimport { Tooltip } from \"@/components/picker/tooltip\";\nimport { gridHeight, gridRowHeight } from \"@/config/grid\";\nimport { useIconLibrary } from \"@/hooks/use-icon-library\";\nimport { useIconTooltip } from \"@/hooks/use-icon-tooltip\";\nimport { useRecentIcons } from \"@/hooks/use-recent-icons\";\nimport { getCenteredScrollTop, getNextIndex, getRevealedScrollTop, getVisibleRows } from \"@/lib/grid\";\nimport type { LibraryIcon } from \"@/lib/library\";\nimport { normalizeTerms, selectIcons } from \"@/lib/library\";\nimport type { SanityIconName } from \"@/plugin\";\n\nexport type PickerProps = Omit<\n ComponentProps<typeof Dialog>,\n \"children\" | \"header\" | \"width\" | \"selected\" | \"onSelect\"\n> & {\n allowed: SanityIconName[] | undefined;\n selected: string | undefined;\n onSelect: (icon: LibraryIcon) => void;\n};\n\nexport function Picker({ allowed, selected, onSelect, ...props }: PickerProps) {\n const library = useIconLibrary();\n const icons = selectIcons(library ?? [], allowed);\n const { recent, remember, forget } = useRecentIcons();\n\n const [search, setSearch] = useState(\"\");\n const [scrollRow, setScrollRow] = useState(0);\n const [movedIndex, setMovedIndex] = useState<number>();\n const [scrolling, setScrolling] = useState(false);\n\n const scroller = useRef<HTMLDivElement>(null);\n const activeCell = useRef<HTMLButtonElement>(null);\n const focusIndex = useRef<number>(undefined);\n const scrollFrame = useRef<number>(undefined);\n const scrollStop = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n const query = normalizeTerms(search);\n const searching = isDefined(query);\n const results = icons.filter((icon) => !searching || icon.terms.includes(query));\n\n const byName = new Map(icons.map((icon) => [icon.name, icon]));\n const recentIcons = searching\n ? []\n : recent.flatMap((entry) => {\n const icon = byName.get(entry);\n\n return isDefined(icon) ? [icon] : [];\n });\n\n const { hovered, handleHover, clearHover } = useIconTooltip(scrolling);\n\n const rows = getVisibleRows(scrollRow, results.length);\n\n const selectedIndex = searching || !isDefined(selected) ? -1 : icons.findIndex((icon) => icon.name === selected);\n const activeIndex = movedIndex ?? Math.max(0, selectedIndex);\n\n useEffect(() => {\n const element = scroller.current;\n if (!isDefined(element) || selectedIndex === -1) return;\n\n element.scrollTop = getCenteredScrollTop(selectedIndex);\n }, [scroller, selectedIndex]);\n\n useEffect(\n () => () => {\n if (isDefined(scrollFrame.current)) cancelAnimationFrame(scrollFrame.current);\n if (isDefined(scrollStop.current)) clearTimeout(scrollStop.current);\n },\n [],\n );\n\n useEffect(() => {\n if (focusIndex.current !== activeIndex) return;\n\n focusIndex.current = undefined;\n if (isDefined(activeCell.current)) activeCell.current.focus();\n }, [activeIndex]);\n\n function handleSelect(icon: LibraryIcon) {\n remember(icon.name);\n onSelect(icon);\n }\n\n function clearSearch() {\n setSearch(\"\");\n setMovedIndex(undefined);\n }\n\n function handleSearch(event: ChangeEvent<HTMLInputElement>) {\n setSearch(event.currentTarget.value);\n setMovedIndex(undefined);\n\n if (isDefined(scroller.current)) scroller.current.scrollTop = 0;\n }\n\n function selectActive() {\n const icon = results[activeIndex];\n\n if (isDefined(icon)) handleSelect(icon);\n }\n\n function handleSearchKeyDown(event: KeyboardEvent<HTMLInputElement>) {\n if (event.key === \"Enter\") {\n event.preventDefault();\n selectActive();\n\n return;\n }\n\n if (event.key !== \"ArrowDown\") return;\n\n event.preventDefault();\n\n if (isDefined(activeCell.current)) activeCell.current.focus();\n }\n\n function handleScroll() {\n clearHover();\n if (!scrolling) setScrolling(true);\n\n if (isDefined(scrollStop.current)) clearTimeout(scrollStop.current);\n scrollStop.current = setTimeout(() => {\n setScrolling(false);\n }, 150);\n\n if (isDefined(scrollFrame.current)) return;\n\n scrollFrame.current = requestAnimationFrame(() => {\n scrollFrame.current = undefined;\n\n const element = scroller.current;\n if (isDefined(element)) setScrollRow(Math.floor(element.scrollTop / gridRowHeight));\n });\n }\n\n function handleGridKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n const last = results.length - 1;\n if (last < 0) return;\n\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n selectActive();\n\n return;\n }\n\n const next = getNextIndex(event.key, activeIndex, last);\n if (!isDefined(next)) return;\n\n event.preventDefault();\n\n const index = Math.min(Math.max(next, 0), last);\n focusIndex.current = index;\n setMovedIndex(index);\n\n const element = scroller.current;\n if (!isDefined(element)) return;\n\n element.scrollTop = getRevealedScrollTop(index, element.scrollTop);\n }\n\n return (\n <Dialog header=\"Select icon\" width={1} {...props}>\n <Stack gap={4} padding={4}>\n <TextInput\n icon={<SearchIcon />}\n placeholder=\"Search by name or by what the icon depicts\"\n value={search}\n onChange={handleSearch}\n onKeyDown={handleSearchKeyDown}\n disabled={!isDefined(library) || icons.length === 0}\n aria-label=\"Search the icon library\"\n />\n {!isDefined(library) && (\n <Flex align=\"center\" justify=\"center\" style={{ height: gridHeight }}>\n <Spinner muted />\n </Flex>\n )}\n {isDefined(recentIcons) && (\n <Recent\n icons={recentIcons}\n selected={selected}\n onSelect={handleSelect}\n onHover={handleHover}\n onForget={forget}\n onMouseLeave={clearHover}\n />\n )}\n {isDefined(library) && (\n <Stack gap={3}>\n <Box paddingY={2}>\n <Text size={1} weight=\"medium\" muted>\n All icons ({results.length.toLocaleString(\"en-US\")})\n </Text>\n </Box>\n {icons.length === 0 && (\n <Flex align=\"center\" justify=\"center\" style={{ height: gridHeight }}>\n <Text size={1} muted>\n No icons are available to choose from.\n </Text>\n </Flex>\n )}\n {icons.length > 0 && (\n <Library\n ref={scroller}\n icons={results}\n rows={rows}\n selected={selected}\n activeIndex={activeIndex}\n activeCell={activeCell}\n search={search}\n onSelect={handleSelect}\n onHover={handleHover}\n onClearSearch={clearSearch}\n onScroll={handleScroll}\n onMouseLeave={clearHover}\n onKeyDown={handleGridKeyDown}\n />\n )}\n </Stack>\n )}\n <Tooltip key={hovered?.icon.name} hovered={hovered} />\n </Stack>\n </Dialog>\n );\n}\n","import type { ComponentProps } from \"react\";\n\nexport type SquareDashedIconProps = ComponentProps<\"svg\">;\n\nexport function SquareDashedIcon(props: SquareDashedIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={24}\n height={24}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M5 3a2 2 0 0 0-2 2\" />\n <path d=\"M19 3a2 2 0 0 1 2 2\" />\n <path d=\"M21 19a2 2 0 0 1-2 2\" />\n <path d=\"M5 21a2 2 0 0 1-2-2\" />\n <path d=\"M9 3h1\" />\n <path d=\"M9 21h1\" />\n <path d=\"M14 3h1\" />\n <path d=\"M14 21h1\" />\n <path d=\"M3 9v1\" />\n <path d=\"M21 9v1\" />\n <path d=\"M3 14v1\" />\n <path d=\"M21 14v1\" />\n </svg>\n );\n}\n","import type { SanityIconConfig, SanityIconOptions } from \"@/plugin\";\n\n/**\n * Settles what an icon field offers. The list says what is on and replaces whatever the plugin was\n * given, so one line tells you the whole answer.\n *\n * @param options - Options the field itself was given.\n * @param config - Configuration the plugin was given.\n * @returns The settings the field runs on.\n */\nexport function resolveIconOptions(options: SanityIconOptions | undefined, config: SanityIconConfig) {\n return {\n icons: options?.icons ?? config.icons,\n };\n}\n","/** Type name of the icon object. */\nexport const iconTypeName = \"icon\";\n\n/**\n * An icon an author chose, stored as the name it was chosen by alongside the shapes it draws.\n *\n * @public\n */\nexport interface SanityIcon {\n _type: typeof iconTypeName;\n /** Name the icon goes by in the library it was taken from. */\n name?: string;\n /** Shapes the icon is drawn from, written when the icon is chosen. */\n node?: string;\n}\n","import { defaultIconProps } from \"@repo/lib/icons\";\nimport { convertCase, isDefined } from \"@repo/lib/utils\";\nimport { CloseIcon } from \"@sanity/icons/Close\";\nimport { Button, Flex } from \"@sanity/ui\";\nimport { useState } from \"react\";\nimport type { ObjectInputProps, ObjectSchemaType } from \"sanity\";\nimport { set, setIfMissing, unset } from \"sanity\";\n\nimport { Drawing } from \"@/components/drawing\";\nimport { Picker } from \"@/components/picker/picker\";\nimport { SquareDashedIcon } from \"@/icons/square-dashed\";\nimport type { LibraryIcon } from \"@/lib/library\";\nimport { resolveIconNode, serializeIconNode } from \"@/lib/nodes\";\nimport { resolveIconOptions } from \"@/lib/options\";\nimport type { SanityIconConfig, SanityIconOptions } from \"@/plugin\";\nimport type { SanityIcon } from \"@/types\";\nimport { iconTypeName } from \"@/types\";\n\n/** Compiled shape of an icon field, carrying the options the field itself was given. */\ninterface IconSchemaType extends ObjectSchemaType {\n options?: SanityIconOptions;\n}\n\nexport type InputProps = ObjectInputProps<Partial<SanityIcon>, IconSchemaType>;\n\n/**\n * Creates the input an icon field is drawn with, holding the configuration the plugin was given so a\n * field naming its own icons replaces them rather than adding to them.\n *\n * @param config - Configuration every field falls back to.\n * @returns The input component.\n */\nexport function createInput(config: SanityIconConfig) {\n function Input({ id, schemaType, value, onChange, readOnly }: InputProps) {\n const { name, node } = value ?? {};\n\n const [open, setOpen] = useState(false);\n\n const { icons } = resolveIconOptions(schemaType.options, config);\n const selectedNode = resolveIconNode(node);\n const selectedLabel = isDefined(name) ? convertCase(name, \"sentence\") : undefined;\n\n function handleSelect(icon: LibraryIcon) {\n onChange([\n setIfMissing({ _type: iconTypeName satisfies SanityIcon[\"_type\"] }),\n set(icon.name, [\"name\" satisfies keyof SanityIcon]),\n set(serializeIconNode(icon.node), [\"node\" satisfies keyof SanityIcon]),\n ]);\n\n setOpen(false);\n }\n\n return (\n <Flex gap={2}>\n <Button\n id={id}\n type=\"button\"\n mode=\"ghost\"\n icon={\n isDefined(selectedNode) ? (\n <Drawing node={selectedNode} {...defaultIconProps} />\n ) : (\n <SquareDashedIcon {...defaultIconProps} />\n )\n }\n text={selectedLabel ?? \"Select icon\"}\n disabled={readOnly}\n onClick={() => {\n setOpen(true);\n }}\n aria-label={isDefined(selectedLabel) ? `${selectedLabel} currently selected` : \"Select icon\"}\n />\n {isDefined(value) && (\n <Button\n type=\"button\"\n mode=\"ghost\"\n tone=\"critical\"\n icon={<CloseIcon />}\n text=\"Clear\"\n disabled={readOnly}\n onClick={() => {\n onChange(unset());\n }}\n aria-label=\"Clear the currently selected icon\"\n />\n )}\n {open && (\n <Picker\n id={`${id}-library`}\n allowed={icons}\n selected={name}\n onSelect={handleSelect}\n onClose={() => {\n setOpen(false);\n }}\n onClickOutside={() => {\n setOpen(false);\n }}\n />\n )}\n </Flex>\n );\n }\n\n return Input;\n}\n","import { defaultIconProps } from \"@repo/lib/icons\";\nimport { isDefined } from \"@repo/lib/utils\";\nimport { createElement } from \"react\";\n\nimport { Drawing } from \"@/components/drawing\";\nimport { resolveIconNode } from \"@/lib/nodes\";\nimport type { SanityIcon } from \"@/types\";\n\n/**\n * Builds the media a stored icon previews with, so a document lists the drawing an author chose\n * rather than one placeholder standing in for every icon alike.\n *\n * @param value - The stored icon.\n * @returns The media component, or undefined when nothing readable was stored.\n * @public\n */\nexport function createIconPreview(value: SanityIcon | undefined) {\n const node = resolveIconNode(value?.node);\n if (!isDefined(node)) return undefined;\n\n return function IconPreview() {\n return createElement(Drawing, { node, ...defaultIconProps });\n };\n}\n","import { Field } from \"@repo/components/field\";\nimport { createSanityIcon } from \"@repo/lib/icons\";\nimport { convertCase, isDefined } from \"@repo/lib/utils\";\nimport { defineField, defineType } from \"sanity\";\n\nimport { createInput } from \"@/components/input\";\nimport { SquareDashedIcon } from \"@/icons/square-dashed\";\nimport { createIconPreview } from \"@/lib/preview\";\nimport type { SanityIconConfig } from \"@/plugin\";\nimport type { SanityIcon } from \"@/types\";\nimport { iconTypeName } from \"@/types\";\n\n/**\n * Creates the object type an icon is stored as, offering the icons it is given to every field that\n * does not name its own.\n *\n * @param config - Configuration every field falls back to.\n * @returns An object type definition for a stored icon.\n */\nexport function createIconType(config: SanityIconConfig) {\n return defineType({\n name: iconTypeName satisfies SanityIcon[\"_type\"],\n type: \"object\",\n icon: createSanityIcon(SquareDashedIcon),\n description: \"Icon chosen from the Lucide library.\",\n // Deliberately the flat frame a primitive field gets, not the collapsible fieldset Sanity wraps an object in.\n components: { field: Field, input: createInput(config) },\n validation: (rule) =>\n rule.custom((value: Partial<SanityIcon> | undefined) =>\n !isDefined(value?.name) || isDefined(value.node) ? true : \"Select the icon again so its drawing is stored.\",\n ),\n preview: {\n select: {\n name: \"name\",\n node: \"node\",\n },\n prepare(selection: { name?: string; node?: string }) {\n const { name, node } = selection;\n\n return {\n title: isDefined(name) ? convertCase(name, \"sentence\") : \"No icon\",\n media: createIconPreview({ _type: iconTypeName, name, node }),\n };\n },\n },\n fields: [\n defineField({\n name: \"name\" satisfies keyof SanityIcon,\n type: \"string\",\n description: \"Name of the chosen icon in the library it was taken from.\",\n }),\n defineField({\n name: \"node\" satisfies keyof SanityIcon,\n type: \"text\",\n description: \"Shapes the icon is drawn from, written when the icon is chosen.\",\n }),\n ],\n });\n}\n","import type iconNodes from \"lucide-static/icon-nodes.json\";\nimport type { ObjectOptions, TypeAliasDefinition } from \"sanity\";\nimport { definePlugin } from \"sanity\";\n\nimport { createIconType } from \"@/schemas/types/icon\";\nimport type { iconTypeName } from \"@/types\";\n\ndeclare module \"@sanity/types\" {\n interface IntrinsicDefinitions {\n icon: SanityIconDefinition;\n }\n}\n\n/**\n * Names of every icon the library offers, read from the Lucide release a project resolved rather than\n * from a list this plugin ships, so an icon added since the last plugin release still completes.\n *\n * @public\n */\nexport type SanityIconName = keyof typeof iconNodes;\n\n/**\n * Options an icon field takes, narrowing what its picker offers.\n *\n * @public\n */\nexport interface SanityIconOptions extends ObjectOptions {\n /** Icons an author may choose from, offered in the order they are named. Every icon when omitted. */\n icons?: SanityIconName[];\n}\n\n/**\n * Shape of a field or array member holding an icon, so its options are completed and checked the way\n * a built-in type's are.\n *\n * @public\n */\nexport interface SanityIconDefinition extends Omit<TypeAliasDefinition<typeof iconTypeName, undefined>, \"options\"> {\n options?: SanityIconOptions;\n}\n\n/**\n * Everything the plugin accepts, all of which may be left out.\n *\n * @public\n */\nexport interface SanityIconConfig {\n /** Icons an author may choose from, offered in the order they are named. Every icon when omitted. */\n icons?: SanityIconName[];\n}\n\nconst plugin = definePlugin<SanityIconConfig>((config) => ({\n name: \"@driftime/sanity-plugin-icon\",\n schema: {\n types: [createIconType(config)],\n },\n}));\n\n/**\n * Creates the icon field type for Sanity Studio, offering the Lucide library through a searchable\n * picker and storing the chosen drawing ready to render.\n *\n * @param config - Plugin configuration.\n * @returns Sanity plugin definition.\n * @public\n */\nexport function iconPlugin(config: SanityIconConfig = {}) {\n return plugin(config);\n}\n"],"mappings":"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"}
package/dist/render.d.ts CHANGED
@@ -1,21 +1,21 @@
1
- import { t as SanityIcon } from "./types-nQUVfUHK.js";
1
+ import { t as SanityIcon } from "./types-_D2jGm25.js";
2
2
  import { ComponentProps } from "react";
3
3
  /**
4
4
  * Properties for drawing a stored icon, extending an SVG element with the value to read it from.
5
5
  *
6
6
  * @public
7
7
  */
8
- type IconProps = Omit<ComponentProps<"svg">, "children"> & {
8
+ type SanityIconProps = Omit<ComponentProps<"svg">, "children"> & {
9
+ /** Stored icon to draw. */
9
10
  value: SanityIcon | undefined;
10
11
  };
11
12
  /**
12
13
  * Draws the icon an author chose, taking the shapes from the stored value so nothing has to resolve
13
14
  * them against an icon library. Renders nothing when the value is absent or unreadable.
14
15
  *
15
- * @param props - The stored icon, alongside any attributes the SVG should carry.
16
16
  * @returns The icon, or nothing when there is nothing to draw.
17
17
  * @public
18
18
  */
19
- declare function Icon({ value, ...props }: IconProps): import("react").JSX.Element;
20
- export { Icon, type IconProps, type SanityIcon };
19
+ export declare function Icon({ value, ...props }: SanityIconProps): import("react").JSX.Element;
20
+ export type { SanityIcon, SanityIconProps };
21
21
  //# sourceMappingURL=render.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","names":[],"sources":["../src/components/icon.tsx"],"mappings":";;;;;;;KAcY,YAAY,KAAK;EAAuC,OAAO;;;;;;;;;;iBAU3D,OAAO,UAAU,SAAS,4BAAS,IAAA"}
1
+ {"version":3,"file":"render.d.ts","names":[],"sources":["../src/components/icon.tsx"],"mappings":";;;;;;;KAcY,kBAAkB,KAAK;;EAEjC,OAAO;;;;;;;;;wBAUO,OAAO,UAAU,SAAS,kCAAe,IAAA"}
package/dist/render.js CHANGED
@@ -1,10 +1,9 @@
1
- import { r as resolveIconNode, t as Drawing } from "./drawing-Bo0HTICv.js";
1
+ import { r as resolveIconNode, t as Drawing } from "./drawing-BThiR2bN.js";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  /**
4
4
  * Draws the icon an author chose, taking the shapes from the stored value so nothing has to resolve
5
5
  * them against an icon library. Renders nothing when the value is absent or unreadable.
6
6
  *
7
- * @param props - The stored icon, alongside any attributes the SVG should carry.
8
7
  * @returns The icon, or nothing when there is nothing to draw.
9
8
  * @public
10
9
  */
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","names":["ComponentProps","Drawing","resolveIconNode","SanityIcon","IconProps","Omit","value","Icon","props","node"],"sources":["../src/components/icon.tsx"],"sourcesContent":["// Runs inside a consumer's server components, where the compiler's memo cache hook cannot.\n\"use no memo\";\n\nimport type { ComponentProps } from \"react\";\n\nimport { Drawing } from \"@/components/drawing\";\nimport { resolveIconNode } from \"@/lib/nodes\";\nimport type { SanityIcon } from \"@/types\";\n\n/**\n * Properties for drawing a stored icon, extending an SVG element with the value to read it from.\n *\n * @public\n */\nexport type IconProps = Omit<ComponentProps<\"svg\">, \"children\"> & { value: SanityIcon | undefined };\n\n/**\n * Draws the icon an author chose, taking the shapes from the stored value so nothing has to resolve\n * them against an icon library. Renders nothing when the value is absent or unreadable.\n *\n * @param props - The stored icon, alongside any attributes the SVG should carry.\n * @returns The icon, or nothing when there is nothing to draw.\n * @public\n */\nexport function Icon({ value, ...props }: IconProps) {\n return <Drawing node={resolveIconNode(value?.node)} {...props} />;\n}\n"],"mappings":";;;;;;;;;;AAwBA,SAAgBO,KAAK,EAAED,OAAO,GAAGE,SAAoB;CACnD,OAAO,oBAAC,SAAD;EAAS,MAAMN,gBAAgBI,OAAOG,IAAI;EAAG,GAAID;CAAM,CAAA;AAChE"}
1
+ {"version":3,"file":"render.js","names":["ComponentProps","Drawing","resolveIconNode","SanityIcon","SanityIconProps","Omit","value","Icon","props","node"],"sources":["../src/components/icon.tsx"],"sourcesContent":["// Runs inside a consumer's server components, where the compiler's memo cache hook cannot.\n\"use no memo\";\n\nimport type { ComponentProps } from \"react\";\n\nimport { Drawing } from \"@/components/drawing\";\nimport { resolveIconNode } from \"@/lib/nodes\";\nimport type { SanityIcon } from \"@/types\";\n\n/**\n * Properties for drawing a stored icon, extending an SVG element with the value to read it from.\n *\n * @public\n */\nexport type SanityIconProps = Omit<ComponentProps<\"svg\">, \"children\"> & {\n /** Stored icon to draw. */\n value: SanityIcon | undefined;\n};\n\n/**\n * Draws the icon an author chose, taking the shapes from the stored value so nothing has to resolve\n * them against an icon library. Renders nothing when the value is absent or unreadable.\n *\n * @returns The icon, or nothing when there is nothing to draw.\n * @public\n */\nexport function Icon({ value, ...props }: SanityIconProps) {\n return <Drawing node={resolveIconNode(value?.node)} {...props} />;\n}\n"],"mappings":";;;;;;;;;AA0BA,SAAgBO,KAAK,EAAED,OAAO,GAAGE,SAA0B;CACzD,OAAO,oBAAC,SAAD;EAAS,MAAMN,gBAAgBI,OAAOG,IAAI;EAAG,GAAID;CAAM,CAAA;AAChE"}
@@ -12,5 +12,5 @@ interface SanityIcon {
12
12
  /** Shapes the icon is drawn from, written when the icon is chosen. */
13
13
  node?: string;
14
14
  }
15
- export { SanityIcon as t };
16
- //# sourceMappingURL=types-nQUVfUHK.d.ts.map
15
+ export { iconTypeName as n, SanityIcon as t };
16
+ //# sourceMappingURL=types-_D2jGm25.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-_D2jGm25.d.ts","names":[],"sources":["../src/types.ts"],"mappings":"AACA;cAAa;;;;;;UAOI;EACf,cAAc;;EAEd;;EAEA"}
package/package.json CHANGED
@@ -1,15 +1,19 @@
1
1
  {
2
2
  "name": "@driftime/sanity-plugin-icon",
3
- "version": "0.1.0",
4
- "description": "Lucide icons for Sanity Studio, stored as drawings and rendered without the library.",
3
+ "version": "0.3.0",
4
+ "description": "Lucide icons for Sanity Studio, stored as SVG and rendered without the library.",
5
5
  "keywords": [
6
+ "icon",
7
+ "icon-picker",
8
+ "icons",
9
+ "lucide",
6
10
  "sanity",
7
- "sanity-plugin"
11
+ "sanity-plugin",
12
+ "svg"
8
13
  ],
9
- "homepage": "https://github.com/driftime/sanity-plugin-icon",
14
+ "homepage": "https://github.com/driftime/sanity-plugins/tree/main/packages/icon#readme",
10
15
  "bugs": {
11
- "url": "https://github.com/driftime/sanity-plugin-icon/issues",
12
- "email": "kenny@driftime.com"
16
+ "url": "https://github.com/driftime/sanity-plugins/issues"
13
17
  },
14
18
  "license": "MIT",
15
19
  "author": {
@@ -19,7 +23,8 @@
19
23
  },
20
24
  "repository": {
21
25
  "type": "git",
22
- "url": "git+ssh://git@github.com/driftime/sanity-plugin-icon.git"
26
+ "url": "git+https://github.com/driftime/sanity-plugins.git",
27
+ "directory": "packages/icon"
23
28
  },
24
29
  "files": [
25
30
  "dist"
@@ -48,39 +53,25 @@
48
53
  },
49
54
  "scripts": {
50
55
  "typecheck": "tsc",
51
- "check": "oxfmt --check && oxlint",
52
- "fix": "oxfmt && oxlint --fix",
53
56
  "dev": "plugin-kit link-watch",
54
- "watch": "pkg-utils watch --strict",
55
- "build": "bun run check && bun run typecheck && plugin-kit verify-package --silent && pkg-utils build --strict --check --clean && node --check dist/index.js",
56
- "prepublishOnly": "bun run build"
57
+ "build": "bun run typecheck && plugin-kit verify-package --silent && pkg-utils build --strict --check --clean && node --check dist/index.js && node --check dist/render.js",
58
+ "prepublishOnly": "bun run build",
59
+ "push": "yalc push"
57
60
  },
58
61
  "dependencies": {
59
- "@sanity/client": "^7.26.2",
62
+ "@sanity/client": "^7.26.2 || ^8.0.0",
60
63
  "@sanity/icons": "^5.2.1",
61
64
  "@sanity/ui": "^4.0.3",
62
- "lucide-static": "^1.43.0"
65
+ "lucide-static": "^1.44.0"
63
66
  },
64
67
  "devDependencies": {
65
- "@sanity/browserslist-config": "1.0.5",
66
- "@sanity/pkg-utils": "12.1.2",
67
- "@sanity/plugin-kit": "10.0.5",
68
- "@sanity/tsconfig": "2.2.1",
69
- "@types/node": "26.2.0",
70
- "@types/react": "19.2.18",
71
- "@types/react-dom": "19.2.4",
72
- "babel-plugin-react-compiler": "1.0.0",
73
- "oxfmt": "0.63.0",
74
- "oxlint": "1.78.0",
75
- "oxlint-tsgolint": "7.0.2001",
76
- "react": "19.2.8",
77
- "react-dom": "19.2.8",
78
- "sanity": "6.9.2",
79
- "typescript": "7.0.2"
68
+ "@repo/components": "workspace:*",
69
+ "@repo/lib": "workspace:*",
70
+ "@sanity/pkg-utils": "catalog:"
80
71
  },
81
72
  "peerDependencies": {
82
73
  "react": "19",
83
- "sanity": "6"
74
+ "sanity": "^6.10.0"
84
75
  },
85
76
  "browserslist": "extends @sanity/browserslist-config",
86
77
  "engines": {
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Driftime®
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1 +0,0 @@
1
- {"version":3,"file":"drawing-Bo0HTICv.js","names":["Nullable","isDefined","value","T","undefined","trim","Array","isArray","some","element","prototype","Reflect","getPrototypeOf","Object","keys","length","convertCase","format","words","replaceAll","toLowerCase","_match","character","toUpperCase","stegaClean","isDefined","iconElements","const","IconElement","element","attributes","Record","IconNode","iconRootAttributes","xmlns","width","height","viewBox","fill","stroke","strokeWidth","strokeLinecap","strokeLinejoin","isIconNode","value","Array","isArray","every","length","some","name","parseIconNode","undefined","resolveIconNode","cleaned","parsed","JSON","parse","serialiseIconNode","node","stringify","ComponentProps","createElement","IconNode","iconRootAttributes","isDefined","DrawingProps","Omit","node","Drawing","props","map","element","attributes","index","key","String"],"sources":["../src/lib/utils.ts","../src/lib/nodes.ts","../src/components/drawing.tsx"],"sourcesContent":["import type { Nullable } from \"@/types\";\n\n/**\n * Checks whether a value is defined and non-empty, treating `false`, empty strings, and objects with\n * no keys as absent. An array is absent unless one of its elements is itself present, while anything\n * built from a class counts as present on existence alone. Not intended for boolean flags.\n *\n * @param value - The value to check.\n * @returns True if the value is defined and not empty.\n */\nexport function isDefined<T>(value: Nullable<T> | false): value is T {\n if (value === undefined || value === null || value === false) return false;\n if (typeof value === \"string\") return value.trim() !== \"\";\n if (Array.isArray(value)) return value.some((element) => isDefined(element));\n\n if (typeof value === \"object\") {\n const prototype = Reflect.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) return true;\n\n return Object.keys(value).length > 0;\n }\n\n return true;\n}\n\n/**\n * Converts a string between different casing formats.\n *\n * @param value - The string to convert.\n * @param format - The target casing format.\n * @returns The converted string.\n */\nexport function convertCase(value: string, format: \"kebab\" | \"snake\" | \"camel\" | \"pascal\" | \"title\" | \"sentence\") {\n const words = value\n .replaceAll(/(?<lower>[a-z0-9])(?<upper>[A-Z])/gu, \"$<lower> $<upper>\")\n .replaceAll(/[-_\\s]+/gu, \" \")\n .trim()\n .toLowerCase();\n\n switch (format) {\n case \"kebab\": {\n return words.replaceAll(/\\s+/gu, \"-\");\n }\n case \"snake\": {\n return words.replaceAll(/\\s+/gu, \"_\");\n }\n case \"camel\": {\n return words.replaceAll(/\\s+(?<character>.)/gu, (_match, character: string) => character.toUpperCase());\n }\n case \"pascal\": {\n return words.replaceAll(/(?:^|\\s+)(?<character>.)/gu, (_match, character: string) => character.toUpperCase());\n }\n case \"title\": {\n return words.replaceAll(/\\b\\w/gu, (character) => character.toUpperCase());\n }\n case \"sentence\": {\n return words.replaceAll(/^(?<character>.)/gu, (character) => character.toUpperCase());\n }\n default: {\n return value;\n }\n }\n}\n","import { stegaClean } from \"@sanity/client/stega\";\n\nimport { isDefined } from \"@/lib/utils\";\n\n/** Elements an icon's drawing may be built from, narrowed to those that describe a shape. */\nconst iconElements = [\"circle\", \"ellipse\", \"g\", \"line\", \"path\", \"polygon\", \"polyline\", \"rect\"] as const;\n\n/** Single shape in an icon's drawing, paired with the attributes it is drawn with. */\ntype IconElement = [element: (typeof iconElements)[number], attributes: Record<string, string>];\n\n/** An icon's drawing, held as the shapes it is built from rather than as a component. */\nexport type IconNode = IconElement[];\n\n/**\n * Attributes given to the SVG an icon's shapes are drawn inside, mirroring the grid and stroke Lucide\n * draws on. A library working to different conventions would need its own frame, which is why a\n * stored icon carries only what sits inside this one.\n */\nexport const iconRootAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n} as const;\n\n/**\n * Checks whether a parsed value is an icon's drawing, since it arrives as whatever happened to be\n * stored. Shapes are matched against the known elements so nothing else reaches the renderer.\n *\n * @param value - The value to check.\n * @returns True if the value is a drawing.\n */\nfunction isIconNode(value: unknown): value is IconNode {\n if (!Array.isArray(value)) return false;\n\n return value.every(\n (element: unknown) =>\n Array.isArray(element) &&\n element.length === 2 &&\n iconElements.some((name) => name === element[0]) &&\n typeof element[1] === \"object\" &&\n element[1] !== null,\n );\n}\n\n/**\n * Reads an icon's drawing from an already-parsed value, for a library handing over its drawings as\n * data rather than as a document field.\n *\n * @param value - The value to read.\n * @returns The drawing, or undefined when the value is not one.\n */\nexport function parseIconNode(value: unknown) {\n return isIconNode(value) ? value : undefined;\n}\n\n/**\n * Reads an icon's drawing back from the form it is stored in, clearing the stega characters a Sanity\n * fetch leaves behind.\n *\n * @param value - The stored drawing.\n * @returns The drawing, or undefined when nothing readable was stored.\n */\nexport function resolveIconNode(value: string | undefined) {\n const cleaned = stegaClean(value);\n if (!isDefined(cleaned)) return undefined;\n\n try {\n const parsed: unknown = JSON.parse(cleaned);\n\n return parseIconNode(parsed);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Writes an icon's drawing into the form it is stored in, so the shapes survive a round trip through\n * a document rather than a component reference that only resolves at build time.\n *\n * @param node - The drawing to store.\n * @returns The drawing ready to store.\n */\nexport function serialiseIconNode(node: IconNode) {\n return JSON.stringify(node);\n}\n","// Runs inside a consumer's server components, where the compiler's memo cache hook cannot.\n\"use no memo\";\n\nimport type { ComponentProps } from \"react\";\nimport { createElement } from \"react\";\n\nimport type { IconNode } from \"@/lib/nodes\";\nimport { iconRootAttributes } from \"@/lib/nodes\";\nimport { isDefined } from \"@/lib/utils\";\n\nexport type DrawingProps = Omit<ComponentProps<\"svg\">, \"children\"> & { node: IconNode | undefined };\n\nexport function Drawing({ node, ...props }: DrawingProps) {\n if (!isDefined(node)) return null;\n\n return (\n <svg {...iconRootAttributes} aria-hidden=\"true\" {...props}>\n {node.map(([element, attributes], index) => createElement(element, { ...attributes, key: String(index) }))}\n </svg>\n );\n}\n"],"mappings":";;;;;;;;;;;AAUA,SAAgBC,UAAaC,OAAwC;CACnE,IAAIA,SAAiC,QAAQA,UAAU,IAAO,OAAO;CACrE,IAAI,OAAOA,SAAU,UAAU,OAAOA,MAAMG,KAAK,MAAM;CACvD,IAAIC,MAAMC,QAAQL,KAAK,GAAG,OAAOA,MAAMM,MAAMC,YAAYR,UAAUQ,OAAO,CAAC;CAE3E,IAAI,OAAOP,SAAU,UAAU;EAC7B,IAAMQ,YAAYC,QAAQC,eAAeV,KAAK;EAG9C,OAFIQ,cAAcG,OAAOH,aAAaA,cAAc,QAE7CG,OAAOC,KAAKZ,KAAK,CAAC,CAACa,SAAS;CACrC;CAEA,OAAO;AACT;;;;;;;;AASA,SAAgBC,YAAYd,OAAee,QAAuE;CAChH,IAAMC,QAAQhB,MACXiB,WAAW,uCAAuC,mBAAmB,CAAC,CACtEA,WAAW,aAAa,GAAG,CAAC,CAC5Bd,KAAK,CAAC,CACNe,YAAY;CAEf,QAAQH,QAAR;EACE,KAAK,SACH,OAAOC,MAAMC,WAAW,SAAS,GAAG;EAEtC,KAAK,SACH,OAAOD,MAAMC,WAAW,SAAS,GAAG;EAEtC,KAAK,SACH,OAAOD,MAAMC,WAAW,yBAAyBE,QAAQC,cAAsBA,UAAUC,YAAY,CAAC;EAExG,KAAK,UACH,OAAOL,MAAMC,WAAW,+BAA+BE,QAAQC,cAAsBA,UAAUC,YAAY,CAAC;EAE9G,KAAK,SACH,OAAOL,MAAMC,WAAW,WAAWG,cAAcA,UAAUC,YAAY,CAAC;EAE1E,KAAK,YACH,OAAOL,MAAMC,WAAW,uBAAuBG,cAAcA,UAAUC,YAAY,CAAC;EAEtF,SACE,OAAOrB;CAEX;AACF;;ACzDA,MAAMwB,eAAe;CAAC;CAAU;CAAW;CAAK;CAAQ;CAAQ;CAAW;CAAY;AAAM,GAahFO,qBAAqB;CAChCC,OAAO;CACPC,OAAO;CACPC,QAAQ;CACRC,SAAS;CACTC,MAAM;CACNC,QAAQ;CACRC,aAAa;CACbC,eAAe;CACfC,gBAAgB;AAClB;;;;;;;;AASA,SAASC,WAAWC,OAAmC;CAGrD,OAFKC,MAAMC,QAAQF,KAAK,IAEjBA,MAAMG,OACVlB,YACCgB,MAAMC,QAAQjB,OAAO,KACrBA,QAAQmB,WAAW,KACnBtB,aAAauB,MAAMC,SAASA,SAASrB,QAAQ,EAAE,KAC/C,OAAOA,QAAQ,MAAO,YACtBA,QAAQ,OAAO,IACnB,IATkC;AAUpC;;;;;;;;AASA,SAAgBsB,cAAcP,OAAgB;CAC5C,OAAOD,WAAWC,KAAK,IAAIA,QAAQQ,KAAAA;AACrC;;;;;;;;AASA,SAAgBC,gBAAgBT,OAA2B;CACzD,IAAMU,UAAU9B,WAAWoB,KAAK;CAC3BnB,cAAU6B,OAAO,GAEtB,IAAI;EAGF,OAAOH,cAFiBK,KAAKC,MAAMH,OAEdC,CAAM;CAC7B,QAAQ;EACN;CACF;AACF;;;;;;;;AASA,SAAgBG,kBAAkBC,MAAgB;CAChD,OAAOH,KAAKI,UAAUD,IAAI;AAC5B;AC9EA,SAAgBU,QAAQ,EAAED,MAAM,GAAGE,SAAuB;CAGxD,OAFKL,UAAUG,IAAI,IAGjB,oBAAC,OAAD;EAAK,GAAIJ;EAAoB,eAAY;EAAO,GAAIM;EACjDF,UAAAA,KAAKG,KAAK,CAACC,SAASC,aAAaC,UAAUZ,cAAcU,SAAS;GAAE,GAAGC;GAAYE,KAAKC,OAAOF,KAAK;EAAE,CAAC,CAAC;CACtG,CAAA,IALsB;AAO/B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-nQUVfUHK.d.ts","names":[],"sources":["../src/types.ts"],"mappings":"AAIA;cAAa;;;;;;UAOI;EACf,cAAc;;EAEd;;EAEA"}