@mitcsutt/kiln-ui 0.5.0 → 0.7.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/components/actions/CopyButton/CopyButton.d.ts +58 -0
- package/dist/components/actions/CopyButton/CopyButton.js +63 -0
- package/dist/components/actions/CopyButton/CopyButton.js.map +1 -0
- package/dist/components/actions/CopyButton/CopyButton.module.js +9 -0
- package/dist/components/actions/CopyButton/CopyButton.module.js.map +1 -0
- package/dist/components/actions/CopyButton/index.d.ts +4 -0
- package/dist/components/actions/CopyButton/useClipboard.d.ts +35 -0
- package/dist/components/actions/CopyButton/useClipboard.js +62 -0
- package/dist/components/actions/CopyButton/useClipboard.js.map +1 -0
- package/dist/components/actions/ToggleChip/ToggleChip.d.ts +6 -0
- package/dist/components/actions/ToggleChip/ToggleChip.js +26 -24
- package/dist/components/actions/ToggleChip/ToggleChip.js.map +1 -1
- package/dist/components/display/Badge/Badge.d.ts +6 -0
- package/dist/components/display/Badge/Badge.js +16 -15
- package/dist/components/display/Badge/Badge.js.map +1 -1
- package/dist/components/display/CodeBlock/CodeBlock.d.ts +44 -3
- package/dist/components/display/CodeBlock/CodeBlock.js +39 -47
- package/dist/components/display/CodeBlock/CodeBlock.js.map +1 -1
- package/dist/components/display/CodeBlock/CodeBlock.module.js +4 -3
- package/dist/components/display/CodeBlock/CodeBlock.module.js.map +1 -1
- package/dist/components/display/CodeBlock/index.d.ts +1 -1
- package/dist/components/display/Swatch/Swatch.d.ts +52 -0
- package/dist/components/display/Swatch/Swatch.js +27 -0
- package/dist/components/display/Swatch/Swatch.js.map +1 -0
- package/dist/components/display/Swatch/Swatch.module.js +6 -0
- package/dist/components/display/Swatch/Swatch.module.js.map +1 -0
- package/dist/components/display/Swatch/index.d.ts +2 -0
- package/dist/components/display/Tag/Tag.d.ts +7 -0
- package/dist/components/display/Tag/Tag.js +31 -26
- package/dist/components/display/Tag/Tag.js.map +1 -1
- package/dist/components/feedback/Indicator/Indicator.d.ts +74 -0
- package/dist/components/feedback/Indicator/Indicator.js +50 -0
- package/dist/components/feedback/Indicator/Indicator.js.map +1 -0
- package/dist/components/feedback/Indicator/Indicator.module.js +12 -0
- package/dist/components/feedback/Indicator/Indicator.module.js.map +1 -0
- package/dist/components/feedback/Indicator/index.d.ts +2 -0
- package/dist/components/feedback/Toaster/Toaster.d.ts +71 -0
- package/dist/components/feedback/Toaster/Toaster.js +121 -0
- package/dist/components/feedback/Toaster/Toaster.js.map +1 -0
- package/dist/components/feedback/Toaster/Toaster.module.js +20 -0
- package/dist/components/feedback/Toaster/Toaster.module.js.map +1 -0
- package/dist/components/feedback/Toaster/index.d.ts +4 -0
- package/dist/components/feedback/Toaster/toast.d.ts +96 -0
- package/dist/components/feedback/Toaster/toast.js +131 -0
- package/dist/components/feedback/Toaster/toast.js.map +1 -0
- package/dist/components/inputs/Calendar/Calendar.d.ts +87 -0
- package/dist/components/inputs/Calendar/Calendar.js +217 -0
- package/dist/components/inputs/Calendar/Calendar.js.map +1 -0
- package/dist/components/inputs/Calendar/Calendar.module.js +18 -0
- package/dist/components/inputs/Calendar/Calendar.module.js.map +1 -0
- package/dist/components/inputs/Calendar/index.d.ts +2 -0
- package/dist/components/inputs/Combobox/Combobox.js +36 -44
- package/dist/components/inputs/Combobox/Combobox.js.map +1 -1
- package/dist/components/inputs/DateField/DateField.d.ts +17 -0
- package/dist/components/inputs/DateField/DateField.js +26 -0
- package/dist/components/inputs/DateField/DateField.js.map +1 -0
- package/dist/components/inputs/DateField/index.d.ts +2 -0
- package/dist/components/inputs/DateInput/DateInput.d.ts +75 -0
- package/dist/components/inputs/DateInput/DateInput.js +139 -0
- package/dist/components/inputs/DateInput/DateInput.js.map +1 -0
- package/dist/components/inputs/DateInput/index.d.ts +3 -0
- package/dist/components/inputs/DateRangeField/DateRangeField.d.ts +18 -3
- package/dist/components/inputs/DateRangeField/DateRangeField.js.map +1 -1
- package/dist/components/inputs/DateRangeField/DateRangeField.module.js +8 -3
- package/dist/components/inputs/DateRangeField/DateRangeField.module.js.map +1 -1
- package/dist/components/inputs/DateRangeField/DateRangePickerField.d.ts +48 -0
- package/dist/components/inputs/DateRangeField/DateRangePickerField.js +246 -0
- package/dist/components/inputs/DateRangeField/DateRangePickerField.js.map +1 -0
- package/dist/components/inputs/DateRangeField/index.d.ts +2 -0
- package/dist/components/inputs/DateTimeField/DateTimeField.d.ts +17 -0
- package/dist/components/inputs/DateTimeField/DateTimeField.js +26 -0
- package/dist/components/inputs/DateTimeField/DateTimeField.js.map +1 -0
- package/dist/components/inputs/DateTimeField/index.d.ts +2 -0
- package/dist/components/inputs/DateTimeInput/DateTimeInput.d.ts +83 -0
- package/dist/components/inputs/DateTimeInput/DateTimeInput.js +216 -0
- package/dist/components/inputs/DateTimeInput/DateTimeInput.js.map +1 -0
- package/dist/components/inputs/DateTimeInput/index.d.ts +2 -0
- package/dist/components/inputs/JsonField/JsonField.d.ts +23 -0
- package/dist/components/inputs/JsonField/JsonField.js +33 -0
- package/dist/components/inputs/JsonField/JsonField.js.map +1 -0
- package/dist/components/inputs/JsonField/index.d.ts +2 -0
- package/dist/components/inputs/JsonInput/JsonInput.d.ts +119 -0
- package/dist/components/inputs/JsonInput/JsonInput.js +282 -0
- package/dist/components/inputs/JsonInput/JsonInput.js.map +1 -0
- package/dist/components/inputs/JsonInput/JsonInput.module.js +16 -0
- package/dist/components/inputs/JsonInput/JsonInput.module.js.map +1 -0
- package/dist/components/inputs/JsonInput/index.d.ts +4 -0
- package/dist/components/inputs/JsonInput/json.d.ts +59 -0
- package/dist/components/inputs/JsonInput/json.js +231 -0
- package/dist/components/inputs/JsonInput/json.js.map +1 -0
- package/dist/components/inputs/TagsInput/TagsInput.js +5 -5
- package/dist/components/inputs/TimeField/TimeField.d.ts +17 -0
- package/dist/components/inputs/TimeField/TimeField.js +26 -0
- package/dist/components/inputs/TimeField/TimeField.js.map +1 -0
- package/dist/components/inputs/TimeField/index.d.ts +2 -0
- package/dist/components/inputs/TimeInput/TimeInput.d.ts +54 -0
- package/dist/components/inputs/TimeInput/TimeInput.js +107 -0
- package/dist/components/inputs/TimeInput/TimeInput.js.map +1 -0
- package/dist/components/inputs/TimeInput/index.d.ts +2 -0
- package/dist/components/inputs/internal/DateSegments.d.ts +80 -0
- package/dist/components/inputs/internal/DateSegments.js +345 -0
- package/dist/components/inputs/internal/DateSegments.js.map +1 -0
- package/dist/components/inputs/internal/dates.d.ts +101 -0
- package/dist/components/inputs/internal/dates.js +262 -0
- package/dist/components/inputs/internal/dates.js.map +1 -0
- package/dist/components/inputs/internal/filterOptions.d.ts +22 -1
- package/dist/components/inputs/internal/filterOptions.js +32 -1
- package/dist/components/inputs/internal/filterOptions.js.map +1 -1
- package/dist/components/inputs/internal/picker.d.ts +31 -0
- package/dist/components/inputs/internal/picker.js +29 -0
- package/dist/components/inputs/internal/picker.js.map +1 -0
- package/dist/components/inputs/internal/picker.module.js +15 -0
- package/dist/components/inputs/internal/picker.module.js.map +1 -0
- package/dist/components/inputs/internal/segments.module.js +10 -0
- package/dist/components/inputs/internal/segments.module.js.map +1 -0
- package/dist/components/layout/Collapse/Collapse.d.ts +39 -0
- package/dist/components/layout/Collapse/Collapse.js +24 -0
- package/dist/components/layout/Collapse/Collapse.js.map +1 -0
- package/dist/components/layout/Collapse/Collapse.module.js +6 -0
- package/dist/components/layout/Collapse/Collapse.module.js.map +1 -0
- package/dist/components/layout/Collapse/index.d.ts +2 -0
- package/dist/components/layout/Collapse/useHeightMotion.d.ts +16 -0
- package/dist/components/layout/Collapse/useHeightMotion.js +60 -0
- package/dist/components/layout/Collapse/useHeightMotion.js.map +1 -0
- package/dist/components/layout/ShowMore/ShowMore.d.ts +59 -0
- package/dist/components/layout/ShowMore/ShowMore.js +114 -0
- package/dist/components/layout/ShowMore/ShowMore.js.map +1 -0
- package/dist/components/layout/ShowMore/ShowMore.module.js +12 -0
- package/dist/components/layout/ShowMore/ShowMore.module.js.map +1 -0
- package/dist/components/layout/ShowMore/index.d.ts +2 -0
- package/dist/components/layout/Transition/Transition.d.ts +63 -0
- package/dist/components/layout/Transition/Transition.js +63 -0
- package/dist/components/layout/Transition/Transition.js.map +1 -0
- package/dist/components/layout/Transition/Transition.module.js +17 -0
- package/dist/components/layout/Transition/Transition.module.js.map +1 -0
- package/dist/components/layout/Transition/index.d.ts +2 -0
- package/dist/components/navigation/Collapsible/Collapsible.d.ts +49 -0
- package/dist/components/navigation/Collapsible/Collapsible.js +83 -0
- package/dist/components/navigation/Collapsible/Collapsible.js.map +1 -0
- package/dist/components/navigation/Collapsible/Collapsible.module.js +11 -0
- package/dist/components/navigation/Collapsible/Collapsible.module.js.map +1 -0
- package/dist/components/navigation/Collapsible/index.d.ts +2 -0
- package/dist/components/navigation/NavLinks/NavLinks.d.ts +32 -4
- package/dist/components/navigation/NavLinks/NavLinks.js +69 -39
- package/dist/components/navigation/NavLinks/NavLinks.js.map +1 -1
- package/dist/components/navigation/NavLinks/NavLinks.module.js +13 -3
- package/dist/components/navigation/NavLinks/NavLinks.module.js.map +1 -1
- package/dist/components/navigation/NavLinks/NavLinksGroup.d.ts +49 -0
- package/dist/components/navigation/NavLinks/NavLinksGroup.js +185 -0
- package/dist/components/navigation/NavLinks/NavLinksGroup.js.map +1 -0
- package/dist/components/navigation/NavLinks/context.d.ts +28 -0
- package/dist/components/navigation/NavLinks/context.js +13 -0
- package/dist/components/navigation/NavLinks/context.js.map +1 -0
- package/dist/components/navigation/NavLinks/index.d.ts +2 -0
- package/dist/components/navigation/NavLinks/treeKeys.d.ts +8 -0
- package/dist/components/navigation/NavLinks/treeKeys.js +57 -0
- package/dist/components/navigation/NavLinks/treeKeys.js.map +1 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.d.ts +120 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.js +386 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.js.map +1 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.module.js +31 -0
- package/dist/components/overlays/CommandPalette/CommandPalette.module.js.map +1 -0
- package/dist/components/overlays/CommandPalette/index.d.ts +2 -0
- package/dist/components/overlays/CommandPalette/shortcut.d.ts +28 -0
- package/dist/components/overlays/CommandPalette/shortcut.js +104 -0
- package/dist/components/overlays/CommandPalette/shortcut.js.map +1 -0
- package/dist/highlight/index.d.ts +18 -0
- package/dist/highlight/index.js +103 -0
- package/dist/highlight/index.js.map +1 -0
- package/dist/index.d.ts +41 -5
- package/dist/index.js +123 -100
- package/dist/styles.css +1 -1
- package/dist/themes/fiesta.css +1 -1
- package/dist/themes/flightdeck.css +1 -1
- package/dist/themes/ledger.css +1 -1
- package/dist/themes/monograph.css +1 -1
- package/dist/themes/riso.css +1 -1
- package/dist/utils/newlines.d.ts +2 -0
- package/dist/utils/newlines.js +10 -0
- package/dist/utils/newlines.js.map +1 -0
- package/package.json +13 -2
- package/skills/custom-theme/SKILL.md +32 -0
- package/skills/custom-theme/references/colour.md +20 -0
- package/skills/custom-theme/references/motion.md +9 -0
- package/skills/custom-theme/references/tokens.md +35 -0
- package/skills/design-rules/SKILL.md +5 -2
- package/skills/setup-and-theming/SKILL.md +2 -1
- package/skills/setup-and-theming/references/paper.md +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPalette.js","names":["_Fragment","styles","DialogPrimitive","CommandPalette_module_default","Fragment$1","findAction","action","actions","id","nested","resultsMessage","count","Highlight","range","matchRange","label","query","start","end","Overlay","forwardRef","theme","usePortalTheme","container","Dialog","Trigger","anchor","usePortalAnchor","composeRefs","ref","Panel","rest","baseId","useId","listboxId","inputRef","useRef","apple","useMemo","isApplePlatform","returnFocusRef","pendingRef","onActionRef","useLatest","onAction","openRef","open","flushPending","useCallback","pages","path","trail","page","pageActions","pageLabel","result","index","toRow","recent","recentRows","recentLabel","matched","filter","filterOptions","limited","limit","section","groupOptions","hasIcons","rows","row","enabled","activeKey","setActiveKey","useState","wasOpen","setWasOpen","useEffect","active","optionId","activeId","announcement","setAnnouncement","countText","loading","emptyMessage","statusText","timer","focusInput","goBack","setPath","setQuery","run","close","move","next","delta","handleChange","event","handleKeyDown","target","renderRow","disabled","shortcut","describeShortcut","hint","Kbd","key","ChevronRightIcon","cx","className","onOpenAutoFocus","returnFocus","prevented","hasTrigger","current","content","onEscapeKeyDown","VisuallyHidden","backLabel","ArrowLeftIcon","SearchIcon","placeholder","Spinner","sections","loadingMessage","CommandPalette","openProp","queryProp","usePortalAnchorRef","setOpenState","useControllableState","defaultOpen","onOpenChange","setQueryState","defaultQuery","onQueryChange","queryRef","setOpen","toggleRef","parsed","parseShortcut","handle","matchesShortcut","PortalAnchorContext","trigger"],"sources":["../../../../src/components/overlays/CommandPalette/CommandPalette.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type ComponentPropsWithoutRef,\n type KeyboardEvent,\n type ReactElement,\n type ReactNode,\n} from 'react'\nimport { Dialog as DialogPrimitive } from 'radix-ui'\nimport { ArrowLeftIcon, ChevronRightIcon, SearchIcon } from '#icons'\nimport { cx } from '#utils/cx'\nimport { Spinner } from '#components/feedback/Spinner'\nimport { VisuallyHidden } from '#components/layout/VisuallyHidden'\nimport { Kbd } from '#components/typography/Kbd'\nimport type { ComboboxOption } from '#components/inputs/Combobox'\nimport { useControllableState } from '#components/inputs/Combobox/useControllableState'\nimport { useLatest } from '#components/inputs/internal/useLatest'\nimport { filterOptions, groupOptions, matchRange } from '#components/inputs/internal/filterOptions'\nimport {\n PortalAnchorContext,\n composeRefs,\n usePortalAnchor,\n usePortalAnchorRef,\n usePortalTheme,\n} from '#components/overlays/usePortalTheme'\nimport { describeShortcut, isApplePlatform, matchesShortcut, parseShortcut } from './shortcut'\nimport styles from './CommandPalette.module.css'\n\n/**\n * One entry in the palette: a page to go to or a command to run. It's a `Combobox` option with\n * an `id` in place of `value`, so `label`, `description`, `keywords`, `group` and `disabled`\n * search and group the same way in both.\n */\nexport interface CommandAction extends Omit<ComboboxOption, 'value'> {\n /** Unique across the palette, nested actions included. `recent` refers to actions by it. */\n id: string\n /** A glyph before the label, such as one of the built-in icons. */\n icon?: ReactNode\n /**\n * The action's own keyboard shortcut, shown beside it, written like `mod+shift+l` (`mod` is\n * Command on a Mac and Control elsewhere). Display only: bind the shortcut yourself.\n */\n shortcut?: string\n /**\n * Runs when the action is picked, once the palette has closed and given focus back, so the\n * action can move focus itself (to a field, or another dialog) and keep it there.\n */\n onSelect?: () => void\n /**\n * Makes this action open a page of its own: picking it lists these instead of running\n * `onSelect`. Backspace in an empty search box, Escape or the back button returns.\n */\n actions?: readonly CommandAction[]\n /** The search box placeholder while this action's page is open. */\n placeholder?: string\n}\n\nexport interface CommandPaletteProps extends Omit<\n ComponentPropsWithoutRef<typeof DialogPrimitive.Content>,\n 'title' | 'children' | 'asChild' | 'forceMount'\n> {\n /** Everything the palette can find, in the order to list it when the search is empty. */\n actions: readonly CommandAction[]\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /** A button that opens the palette. Its theme scope themes the palette. */\n trigger?: ReactElement\n /**\n * A keyboard shortcut anywhere on the page that opens and closes the palette, written like\n * `mod+k` (Command-K on a Mac, Control-K elsewhere). Off when omitted.\n */\n shortcut?: string\n /** Accessible name of the palette and its search box. */\n label?: string\n placeholder?: string\n /** The search text. Controlled. */\n query?: string\n defaultQuery?: string\n onQueryChange?: (query: string) => void\n /**\n * `auto` (default) filters and ranks the actions by the search, like `Combobox`. `none` lists\n * them as given, for results your own search has already chosen.\n */\n filter?: 'auto' | 'none'\n /** Actions are being fetched: a spinner in the search box, and `loadingMessage` when empty. */\n loading?: boolean\n loadingMessage?: ReactNode\n /** Shown when nothing matches. */\n emptyMessage?: ReactNode\n /** The most actions to list at once, after ranking. */\n limit?: number\n /** Ids of recently used actions, most recent first, listed above the rest while the search is empty. */\n recent?: readonly string[]\n /** Heading of the recent actions. */\n recentLabel?: string\n /** Fires after any action runs (not when one opens a page): a place to record recent actions. */\n onAction?: (action: CommandAction) => void\n /** Accessible name of the back button on a nested page. */\n backLabel?: string\n /** Portal target. Defaults to `document.body`; its theme scope is also used. */\n container?: HTMLElement | null\n}\n\n/* ─── Pure helpers ────────────────────────────────────────────────────────── */\n\ninterface Row {\n key: string\n action: CommandAction\n index: number\n}\n\ninterface Section {\n key: string\n label?: string\n rows: Row[]\n}\n\nfunction findAction(actions: readonly CommandAction[], id: string): CommandAction | undefined {\n for (const action of actions) {\n if (action.id === id) return action\n const nested = action.actions ? findAction(action.actions, id) : undefined\n if (nested) return nested\n }\n return undefined\n}\n\nfunction resultsMessage(count: number): string {\n return `${String(count)} ${count === 1 ? 'result' : 'results'}`\n}\n\n/** The label with the matched part in a `<mark>`. */\nfunction Highlight({ label, query }: { label: string; query: string }) {\n const range = matchRange(label, query)\n if (!range) return <>{label}</>\n const [start, end] = range\n return (\n <>\n {label.slice(0, start)}\n <mark className={styles.match}>{label.slice(start, end)}</mark>\n {label.slice(end)}\n </>\n )\n}\n\n/* ─── Overlay (mounts on open, so it reads the theme at that moment) ──────── */\n\nconst Overlay = forwardRef<HTMLDivElement, { container?: HTMLElement | null }>(function Overlay(\n { container },\n ref,\n) {\n const theme = usePortalTheme(container)\n return <DialogPrimitive.Overlay ref={ref} className={styles.overlay} {...theme} />\n})\n\nconst Trigger = forwardRef<HTMLButtonElement, { children: ReactElement }>(function Trigger(\n { children },\n ref,\n) {\n const anchor = usePortalAnchor()\n return (\n <DialogPrimitive.Trigger ref={composeRefs(ref, anchor)} asChild>\n {children}\n </DialogPrimitive.Trigger>\n )\n})\n\n/* ─── Panel ───────────────────────────────────────────────────────────────── */\n\ninterface PanelProps extends Omit<\n CommandPaletteProps,\n | 'open'\n | 'defaultOpen'\n | 'onOpenChange'\n | 'trigger'\n | 'shortcut'\n | 'query'\n | 'defaultQuery'\n | 'onQueryChange'\n> {\n query: string\n setQuery: (query: string) => void\n /** Ids of the open pages, outermost first. */\n path: readonly string[]\n setPath: (path: readonly string[]) => void\n open: boolean\n hasTrigger: boolean\n close: () => void\n}\n\nconst Panel = forwardRef<HTMLDivElement, PanelProps>(function Panel(\n {\n actions,\n label = 'Command palette',\n placeholder = 'Search',\n query,\n setQuery,\n path,\n setPath,\n open,\n hasTrigger,\n close,\n filter = 'auto',\n loading = false,\n loadingMessage = 'Loading…',\n emptyMessage = 'No matches',\n limit,\n recent,\n recentLabel = 'Recent',\n onAction,\n backLabel = 'Back',\n container,\n className,\n onOpenAutoFocus,\n onCloseAutoFocus,\n onEscapeKeyDown,\n ...rest\n },\n ref,\n) {\n const theme = usePortalTheme(container)\n const baseId = useId()\n const listboxId = `${baseId}-listbox`\n const inputRef = useRef<HTMLInputElement>(null)\n const apple = useMemo(() => isApplePlatform(), [])\n const returnFocusRef = useRef<Element | null>(null)\n const anchor = usePortalAnchor()\n // The action picked to run once the palette has closed and let go of focus.\n const pendingRef = useRef<CommandAction | null>(null)\n const onActionRef = useLatest(onAction)\n const openRef = useLatest(open)\n const flushPending = useCallback(() => {\n const action = pendingRef.current\n if (!action) return\n pendingRef.current = null\n action.onSelect?.()\n onActionRef.current?.(action)\n }, [onActionRef])\n\n const pages = path.map((id) => findAction(actions, id))\n const trail = pages.every((action) => action?.actions) ? path : []\n const page = trail.length > 0 ? pages[pages.length - 1] : undefined\n const pageActions = page?.actions ?? actions\n const pageLabel = page?.label ?? label\n\n /* ─── Derived view ─── */\n const { sections, rows } = useMemo(() => {\n const result: Section[] = []\n let index = 0\n const toRow = (key: string, action: CommandAction): Row => ({ key, action, index: index++ })\n if (query.trim() === '' && !page && recent && recent.length > 0) {\n const recentRows = recent.flatMap((id) => {\n const action = findAction(actions, id)\n return action ? [toRow(`recent:${id}`, action)] : []\n })\n if (recentRows.length > 0)\n result.push({ key: 'recent', label: recentLabel, rows: recentRows })\n }\n const matched = filter === 'auto' ? filterOptions(pageActions, query) : [...pageActions]\n const limited = limit === undefined ? matched : matched.slice(0, Math.max(0, limit))\n for (const section of groupOptions(limited)) {\n result.push({\n key: section.key,\n label: section.label,\n rows: section.options.map((action) => toRow(action.id, action)),\n })\n }\n return { sections: result, rows: result.flatMap((section) => section.rows) }\n }, [actions, filter, limit, page, pageActions, query, recent, recentLabel])\n\n // When any row has an icon, every row keeps the icon column, so the labels line up.\n const hasIcons = rows.some((row) => row.action.icon !== undefined)\n const enabled = rows.filter((row) => !row.action.disabled)\n const [activeKey, setActiveKey] = useState<string | null>(null)\n // Every opening highlights the first result again (adjusted during render, not in an effect).\n const [wasOpen, setWasOpen] = useState(open)\n if (open !== wasOpen) {\n setWasOpen(open)\n if (open) setActiveKey(null)\n }\n // An action still waiting from the last close (the palette reopened before it finished\n // closing) runs now, so it never runs late or twice.\n useEffect(() => {\n if (open) flushPending()\n }, [open, flushPending])\n // The panel unmounts after every close. Radix's FocusScope restores focus (and calls\n // onCloseAutoFocus, which runs the action) in a timeout queued during that unmount, after this\n // cleanup; waiting one more tick runs the action only if onCloseAutoFocus never did.\n useEffect(\n () => () => {\n setTimeout(() => {\n setTimeout(flushPending)\n })\n },\n [flushPending],\n )\n // Nothing chosen yet, or the chosen row is gone: the first result, so Enter runs the best match.\n const active = enabled.find((row) => row.key === activeKey) ?? enabled[0]\n const optionId = (row: Row) => `${baseId}-option-${String(row.index)}`\n const activeId = active ? optionId(active) : undefined\n\n useEffect(() => {\n if (!activeId) return\n inputRef.current?.ownerDocument.getElementById(activeId)?.scrollIntoView({ block: 'nearest' })\n }, [activeId])\n\n /* ─── Live region: the result count, debounced ─── */\n const [announcement, setAnnouncement] = useState('')\n const countText = loading\n ? ''\n : rows.length === 0\n ? typeof emptyMessage === 'string'\n ? emptyMessage\n : 'No matches'\n : resultsMessage(rows.length)\n const statusText = countText === '' ? '' : page ? `${pageLabel}: ${countText}` : countText\n useEffect(() => {\n if (statusText === '') return\n const timer = setTimeout(() => {\n setAnnouncement(statusText)\n }, 500)\n return () => {\n clearTimeout(timer)\n }\n }, [statusText])\n\n /* ─── Actions ─── */\n const focusInput = () => {\n inputRef.current?.focus()\n }\n\n const goBack = () => {\n setPath(trail.slice(0, -1))\n setQuery('')\n setActiveKey(null)\n }\n\n const run = (action: CommandAction) => {\n if (action.disabled) return\n if (action.actions) {\n setPath([...trail, action.id])\n setQuery('')\n setActiveKey(null)\n return\n }\n // Runs from onCloseAutoFocus, once the focus trap has let go, so focus the action moves\n // (a field, another dialog) stays where it put it.\n pendingRef.current = action\n close()\n // A controller that keeps the palette open never lets go of focus, so run the action now.\n setTimeout(() => {\n if (openRef.current && pendingRef.current === action) flushPending()\n })\n }\n\n const move = (delta: 1 | -1) => {\n if (enabled.length === 0) return\n const index = active ? enabled.indexOf(active) : -1\n const next = enabled[(index + delta + enabled.length) % enabled.length]\n setActiveKey(next?.key ?? null)\n }\n\n /* ─── Events ─── */\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n setQuery(event.target.value)\n setActiveKey(null)\n }\n\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.nativeEvent.isComposing) return\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault()\n move(1)\n return\n case 'ArrowUp':\n event.preventDefault()\n move(-1)\n return\n case 'Home':\n case 'End': {\n const target = event.key === 'Home' ? enabled[0] : enabled[enabled.length - 1]\n if (!target) return\n event.preventDefault()\n setActiveKey(target.key)\n return\n }\n case 'Enter':\n event.preventDefault()\n if (active) run(active.action)\n return\n case 'Backspace':\n if (query === '' && page) {\n event.preventDefault()\n goBack()\n }\n return\n }\n }\n\n const renderRow = (row: Row) => {\n const { action } = row\n const disabled = Boolean(action.disabled)\n const id = optionId(row)\n const shortcut = action.shortcut ? describeShortcut(action.shortcut, apple) : undefined\n const hint = [action.description, shortcut?.spoken].filter(Boolean).join(', ')\n return (\n // The search box owns focus and the keyboard (aria-activedescendant points here), so a\n // row is never focused itself and its click is the pointer path only.\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/interactive-supports-focus\n <div\n key={row.key}\n id={id}\n role=\"option\"\n aria-selected={active?.key === row.key}\n aria-disabled={disabled || undefined}\n aria-label={action.label}\n aria-describedby={hint === '' ? undefined : `${id}-hint`}\n aria-keyshortcuts={shortcut?.aria}\n className={styles.option}\n data-active={active?.key === row.key || undefined}\n data-disabled={disabled || undefined}\n data-page={action.actions ? '' : undefined}\n onMouseDown={(event) => {\n event.preventDefault()\n }}\n onPointerMove={() => {\n if (!disabled && activeKey !== row.key) setActiveKey(row.key)\n }}\n onClick={() => {\n run(action)\n }}\n >\n {action.icon !== undefined || hasIcons ? (\n <span className={styles.icon} aria-hidden=\"true\">\n {action.icon}\n </span>\n ) : null}\n <span className={styles.text}>\n <span className={styles.label}>\n <Highlight label={action.label} query={query} />\n </span>\n {action.description ? (\n <span className={styles.description} aria-hidden=\"true\">\n {action.description}\n </span>\n ) : null}\n </span>\n {shortcut ? (\n <span className={styles.shortcut} aria-hidden=\"true\">\n {shortcut.keys.map((key, index) => (\n <Kbd key={index} size=\"sm\">\n {key}\n </Kbd>\n ))}\n </span>\n ) : null}\n {action.actions ? <ChevronRightIcon className={styles.chevron} /> : null}\n {hint === '' ? null : (\n <span id={`${id}-hint`} hidden>\n {hint}\n </span>\n )}\n </div>\n )\n }\n\n return (\n <DialogPrimitive.Content\n ref={ref}\n className={cx(styles.content, className)}\n aria-describedby={undefined}\n data-page={page ? '' : undefined}\n {...theme}\n {...rest}\n onOpenAutoFocus={(event) => {\n returnFocusRef.current = inputRef.current?.ownerDocument.activeElement ?? null\n onOpenAutoFocus?.(event)\n if (event.defaultPrevented) return\n event.preventDefault()\n focusInput()\n }}\n onCloseAutoFocus={(event) => {\n onCloseAutoFocus?.(event)\n const returnFocus = returnFocusRef.current\n returnFocusRef.current = null\n if (pendingRef.current) {\n // Put focus back first, then run the action, so whatever it focuses wins.\n const prevented = event.defaultPrevented\n event.preventDefault()\n const target = hasTrigger ? anchor?.current : returnFocus\n if (!prevented && target instanceof HTMLElement && target.isConnected) target.focus()\n flushPending()\n return\n }\n if (event.defaultPrevented || hasTrigger || !(returnFocus instanceof HTMLElement)) return\n if (!returnFocus.isConnected) return\n const current = returnFocus.ownerDocument.activeElement\n const content = event.target instanceof Node ? event.target : null\n if (current && current !== returnFocus.ownerDocument.body && !content?.contains(current))\n return\n event.preventDefault()\n returnFocus.focus()\n }}\n onEscapeKeyDown={(event) => {\n onEscapeKeyDown?.(event)\n if (event.defaultPrevented || !page) return\n // On a nested page, Escape goes back a level instead of closing.\n event.preventDefault()\n goBack()\n focusInput()\n }}\n >\n <DialogPrimitive.Title asChild>\n <VisuallyHidden as=\"h2\">{label}</VisuallyHidden>\n </DialogPrimitive.Title>\n <div className={styles.search}>\n {page ? (\n <button\n type=\"button\"\n className={styles.back}\n aria-label={backLabel}\n onMouseDown={(event) => {\n event.preventDefault()\n }}\n onClick={() => {\n goBack()\n focusInput()\n }}\n >\n <ArrowLeftIcon />\n </button>\n ) : (\n <SearchIcon className={styles.searchIcon} />\n )}\n {page ? (\n <span className={styles.crumb} aria-hidden=\"true\">\n {page.label}\n </span>\n ) : null}\n <input\n ref={inputRef}\n type=\"text\"\n role=\"combobox\"\n className={styles.input}\n value={query}\n placeholder={page?.placeholder ?? placeholder}\n autoComplete=\"off\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n aria-label={pageLabel}\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-expanded={rows.length > 0}\n aria-controls={listboxId}\n aria-activedescendant={activeId}\n aria-busy={loading || undefined}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n />\n {loading ? <Spinner size=\"sm\" label={null} className={styles.spinner} /> : null}\n </div>\n <div className={styles.body}>\n <div\n id={listboxId}\n role=\"listbox\"\n aria-label={pageLabel}\n aria-busy={loading || undefined}\n className={styles.listbox}\n >\n {sections.map((section, index) =>\n section.label === undefined ? (\n section.rows.map(renderRow)\n ) : (\n <div\n key={section.key}\n role=\"group\"\n aria-labelledby={`${baseId}-group-${String(index)}`}\n className={styles.group}\n >\n <div\n id={`${baseId}-group-${String(index)}`}\n role=\"presentation\"\n className={styles.groupLabel}\n >\n {section.label}\n </div>\n {section.rows.map(renderRow)}\n </div>\n ),\n )}\n </div>\n {rows.length === 0 ? (\n loading ? (\n <div className={styles.message}>\n <Spinner size=\"sm\" label={null} />\n <span>{loadingMessage}</span>\n </div>\n ) : (\n <div className={styles.message}>{emptyMessage}</div>\n )\n ) : null}\n </div>\n <VisuallyHidden as=\"div\" role=\"status\" aria-live=\"polite\">\n {announcement}\n </VisuallyHidden>\n </DialogPrimitive.Content>\n )\n})\n\n/* ─── CommandPalette ──────────────────────────────────────────────────────── */\n\n/**\n * A keyboard-first launcher: search every page and action in an app, then run one with Enter.\n *\n * @remarks\n * `CommandPalette` is a modal search over a list of actions. Each one is a page to go to or a\n * command to run, grouped under headings and ranked as you type, with the matched part of each\n * label marked. Open it with a `shortcut` (usually `mod+k`), a `trigger` button, or `open`.\n *\n * The arrow keys, Home and End move through the results and Enter runs the highlighted one; the\n * first result is highlighted as you type, so Enter alone runs the best match. An action with\n * its own `actions` opens them as a page, such as a list of projects to switch to: Backspace in\n * an empty search box, Escape or the back button returns. Escape at the top closes the palette.\n *\n * ## Search and grouping\n *\n * Actions search and group exactly like {@link Combobox | Combobox} options: by `label`, then\n * `keywords` and `description`, ignoring case and accents, with an exact match first, then a\n * match at the start of a word, then anywhere. Groups appear in the order of their best result.\n *\n * ## Results from a server\n *\n * For results your own search chooses, such as records, pass `filter=\"none\"`, set `loading` while\n * you fetch, and pass the results as `actions`. Control the search text with `query` and\n * `onQueryChange`.\n *\n * ## Recent actions\n *\n * `recent` takes the ids of actions to list first while the search is empty. The palette doesn't\n * remember anything itself: record each one in `onAction`, and keep the list wherever suits your\n * app.\n *\n * ## Accessibility\n *\n * It's a modal dialog, so focus is trapped inside and returns to whatever opened it. The search\n * box is an ARIA combobox that keeps focus while the arrow keys move a highlight through the\n * listbox, and a polite live region announces how many results there are. Each action's shortcut\n * is read as its description.\n *\n * @privateRemarks\n * Radix Dialog for focus (the same primitive and portal theming as Dialog and Sheet) around an\n * ARIA 1.2 combobox whose listbox is always shown. Options share Combobox's shape and its\n * `filterOptions`/`groupOptions`, so the two rank and group identically.\n *\n * <CommandPalette shortcut=\"mod+k\" actions={actions} onAction={remember} recent={recentIds} />\n */\nexport const CommandPalette = forwardRef<HTMLDivElement, CommandPaletteProps>(\n function CommandPalette(\n {\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n trigger,\n shortcut,\n query: queryProp,\n defaultQuery = '',\n onQueryChange,\n container,\n ...rest\n },\n ref,\n ) {\n const anchor = usePortalAnchorRef()\n\n const [open, setOpenState] = useControllableState(openProp, defaultOpen, onOpenChange)\n const [query, setQueryState] = useControllableState(queryProp, defaultQuery, onQueryChange)\n const [path, setPath] = useState<readonly string[]>([])\n\n const queryRef = useLatest(query)\n const setQuery = useCallback(\n (next: string) => {\n if (next !== queryRef.current) setQueryState(next)\n },\n [queryRef, setQueryState],\n )\n\n const openRef = useLatest(open)\n const setOpen = useCallback(\n (next: boolean) => {\n if (next !== openRef.current) setOpenState(next)\n },\n [openRef, setOpenState],\n )\n\n // Every opening starts fresh: once the palette closes, by any route, clear the search and\n // go back to the top level.\n const wasOpen = useRef(open)\n useEffect(() => {\n if (wasOpen.current && !open) {\n setQuery('')\n setPath((current) => (current.length > 0 ? [] : current))\n }\n wasOpen.current = open\n }, [open, setQuery])\n\n /* The page-wide shortcut toggles the palette. */\n const toggleRef = useLatest(() => {\n setOpen(!openRef.current)\n })\n useEffect(() => {\n if (!shortcut) return\n const parsed = parseShortcut(shortcut, isApplePlatform())\n const handle = (event: globalThis.KeyboardEvent) => {\n if (event.defaultPrevented || event.isComposing || event.repeat) return\n if (!matchesShortcut(event, parsed)) return\n event.preventDefault()\n toggleRef.current()\n }\n document.addEventListener('keydown', handle)\n return () => {\n document.removeEventListener('keydown', handle)\n }\n }, [shortcut, toggleRef])\n\n return (\n <PortalAnchorContext.Provider value={anchor}>\n <DialogPrimitive.Root open={open} onOpenChange={setOpen}>\n {trigger ? <Trigger>{trigger}</Trigger> : null}\n <DialogPrimitive.Portal container={container}>\n <Overlay container={container} />\n <Panel\n ref={ref}\n container={container}\n query={query}\n setQuery={setQuery}\n path={path}\n setPath={setPath}\n open={open}\n hasTrigger={Boolean(trigger)}\n close={() => {\n setOpen(false)\n }}\n {...rest}\n />\n </DialogPrimitive.Portal>\n </DialogPrimitive.Root>\n </PortalAnchorContext.Provider>\n )\n },\n)\n"],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/components/overlays/CommandPalette/CommandPalette.module.css
|
|
2
|
+
var e = "kiln-CommandPalette__overlay", t = "kiln-CommandPalette__content", n = "kiln-CommandPalette__search", r = "kiln-CommandPalette__searchIcon", i = "kiln-CommandPalette__back", a = "kiln-CommandPalette__crumb", o = "kiln-CommandPalette__input", s = "kiln-CommandPalette__spinner", c = "kiln-CommandPalette__body", l = "kiln-CommandPalette__listbox", u = "kiln-CommandPalette__group", d = "kiln-CommandPalette__option", f = "kiln-CommandPalette__groupLabel", p = "kiln-CommandPalette__icon", m = "kiln-CommandPalette__text", h = "kiln-CommandPalette__label", g = "kiln-CommandPalette__match", _ = "kiln-CommandPalette__description", v = "kiln-CommandPalette__shortcut", y = "kiln-CommandPalette__chevron", b = "kiln-CommandPalette__message", x = {
|
|
3
|
+
overlay: e,
|
|
4
|
+
"fade-in": "kiln-CommandPalette__fade-in",
|
|
5
|
+
"fade-out": "kiln-CommandPalette__fade-out",
|
|
6
|
+
content: t,
|
|
7
|
+
"palette-in": "kiln-CommandPalette__palette-in",
|
|
8
|
+
search: n,
|
|
9
|
+
searchIcon: r,
|
|
10
|
+
back: i,
|
|
11
|
+
crumb: a,
|
|
12
|
+
input: o,
|
|
13
|
+
spinner: s,
|
|
14
|
+
body: c,
|
|
15
|
+
listbox: l,
|
|
16
|
+
group: u,
|
|
17
|
+
option: d,
|
|
18
|
+
groupLabel: f,
|
|
19
|
+
icon: p,
|
|
20
|
+
text: m,
|
|
21
|
+
label: h,
|
|
22
|
+
match: g,
|
|
23
|
+
description: _,
|
|
24
|
+
shortcut: v,
|
|
25
|
+
chevron: y,
|
|
26
|
+
message: b
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
export { i as back, c as body, y as chevron, t as content, a as crumb, x as default, _ as description, u as group, f as groupLabel, p as icon, o as input, h as label, l as listbox, g as match, b as message, d as option, e as overlay, n as search, r as searchIcon, v as shortcut, s as spinner, m as text };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=CommandPalette.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandPalette.module.js","names":["overlay","content","search","searchIcon","back","crumb","input","spinner","body","listbox","group","option","groupLabel","icon","text","label","match","description","shortcut","chevron","message","CommandPalette_module_default"],"sources":["../../../../src/components/overlays/CommandPalette/CommandPalette.module.css"],"sourcesContent":["/*\n * Component tokens (themes may set any of these on [data-theme]):\n * --command-palette-radius default var(--radius-surface)\n * --command-palette-shadow default var(--shadow-overlay)\n * --command-palette-border default var(--color-line-strong)\n * --command-palette-surface default var(--color-surface-raised)\n * --command-palette-highlight default var(--color-surface-sunken) — keyboard/hover row\n * --command-palette-match default var(--color-accent) — underline under the matched text\n *\n * The panel hangs from the top third of the screen rather than the middle, so it stays put\n * while the results grow and shrink under the search box.\n */\n\n.overlay {\n position: fixed;\n inset: 0;\n z-index: var(--z-overlay);\n background: var(--color-scrim);\n}\n.overlay[data-state='open'] {\n animation: fade-in var(--dur-2) var(--ease-out);\n}\n.overlay[data-state='closed'] {\n animation: fade-out var(--dur-1) var(--ease-out);\n}\n\n.content {\n --_radius: var(--command-palette-radius, var(--radius-surface));\n --_pad: var(--space-1);\n\n position: fixed;\n inset-block-start: clamp(var(--space-4), 12vh, var(--space-9));\n inset-inline: 0;\n z-index: var(--z-overlay);\n display: flex;\n flex-direction: column;\n inline-size: min(var(--width-text), calc(100% - 2 * var(--space-4)));\n max-block-size: calc(100% - clamp(var(--space-4), 12vh, var(--space-9)) - var(--space-4));\n margin-inline: auto;\n overflow: hidden;\n border: var(--border-width) solid var(--command-palette-border, var(--color-line-strong));\n border-radius: var(--_radius);\n background: var(--command-palette-surface, var(--color-surface-raised));\n box-shadow: var(--command-palette-shadow, var(--shadow-overlay));\n color: var(--color-ink);\n font-family: var(--font-text);\n font-size: var(--text-md);\n line-height: var(--leading-snug);\n transform-origin: 50% 0;\n}\n.content:focus {\n outline: none;\n}\n.content[data-state='open'] {\n animation: palette-in var(--dur-2) var(--ease-spring);\n}\n.content[data-state='closed'] {\n animation: fade-out var(--dur-1) var(--ease-out);\n}\n\n/* ── Search row ── */\n.search {\n display: flex;\n flex: none;\n align-items: center;\n gap: var(--space-2);\n min-block-size: var(--control-lg);\n padding-inline: var(--space-4);\n border-block-end: var(--border-width) solid var(--color-line);\n color: var(--color-ink-muted);\n}\n.search:focus-within {\n color: var(--color-ink);\n}\n\n.searchIcon {\n flex: none;\n inline-size: 1.15em;\n block-size: 1.15em;\n}\n\n.back {\n position: relative;\n display: inline-grid;\n flex: none;\n place-items: center;\n inline-size: 1.75em;\n block-size: 1.75em;\n margin-inline-start: calc(var(--space-1) * -1);\n padding: 0;\n border: 0;\n border-radius: var(--radius-chip);\n background: transparent;\n color: inherit;\n font-size: inherit;\n cursor: pointer;\n}\n.back > svg {\n inline-size: 1.15em;\n block-size: 1.15em;\n}\n@media (hover: hover) {\n .back:hover {\n background: var(--command-palette-highlight, var(--color-surface-sunken));\n color: var(--color-ink);\n }\n}\n.back:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: 1px;\n}\n\n.crumb {\n flex: none;\n max-inline-size: 40%;\n overflow: hidden;\n padding-inline-end: var(--space-2);\n border-inline-end: var(--border-width) solid var(--color-line);\n color: var(--color-ink);\n font-size: var(--text-sm);\n font-weight: var(--label-weight);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.input {\n flex: 1;\n align-self: stretch;\n min-inline-size: 0;\n margin: 0;\n padding: 0;\n border: 0;\n background: transparent;\n color: var(--color-ink);\n font: inherit;\n font-size: var(--text-lg);\n letter-spacing: inherit;\n outline: none;\n}\n.input:focus-visible {\n outline: none;\n}\n.input::placeholder {\n color: var(--color-ink-subtle);\n opacity: 1;\n}\n\n.spinner {\n flex: none;\n color: var(--color-ink-subtle);\n}\n\n/* ── Results ── */\n.body {\n flex: 1 1 auto;\n max-block-size: min(26rem, 60vh);\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: var(--_pad);\n scroll-padding-block: var(--_pad);\n}\n\n.listbox:empty {\n display: none;\n}\n\n.group {\n display: block;\n}\n.group + .group,\n.option + .group,\n.group + .option {\n margin-block-start: var(--_pad);\n padding-block-start: var(--_pad);\n border-block-start: var(--border-width) solid var(--color-line);\n}\n\n.groupLabel {\n padding: var(--space-2) var(--space-3) var(--space-1);\n color: var(--color-ink-subtle);\n font-size: var(--text-xs);\n font-weight: var(--label-weight);\n letter-spacing: var(--label-tracking);\n text-transform: var(--label-transform);\n}\n\n/* Nested radius: the row sits inside the panel's padding, so it's that much smaller. */\n.option {\n display: flex;\n align-items: center;\n gap: var(--space-3);\n min-block-size: var(--control-md);\n padding-block: var(--space-1);\n padding-inline: var(--space-3);\n border-radius: max(2px, calc(var(--_radius) - var(--_pad)));\n cursor: default;\n user-select: none;\n}\n.option[data-active] {\n background-color: var(--command-palette-highlight, var(--color-surface-sunken));\n}\n.option[data-disabled] {\n color: var(--color-ink-subtle);\n opacity: 0.6;\n}\n\n.icon {\n display: inline-grid;\n flex: none;\n inline-size: 1.15em;\n place-items: center;\n color: var(--color-ink-muted);\n}\n.icon > svg {\n inline-size: 1.15em;\n block-size: 1.15em;\n}\n.option[data-active] .icon {\n color: var(--color-ink);\n}\n\n.text {\n display: flex;\n flex: 1;\n flex-direction: column;\n min-inline-size: 0;\n}\n\n.label {\n overflow-wrap: anywhere;\n}\n\n.match {\n background: transparent;\n color: inherit;\n font-weight: var(--label-weight);\n text-decoration: underline;\n text-decoration-color: var(--command-palette-match, var(--color-accent));\n text-decoration-thickness: 2px;\n text-underline-offset: 0.2em;\n}\n\n.description {\n color: var(--color-ink-muted);\n font-size: var(--text-sm);\n}\n\n.shortcut {\n display: inline-flex;\n flex: none;\n gap: var(--space-1);\n}\n\n.chevron {\n flex: none;\n inline-size: 1.1em;\n block-size: 1.1em;\n color: var(--color-ink-subtle);\n}\n\n.message {\n display: flex;\n align-items: center;\n gap: var(--space-2);\n padding: var(--space-4) var(--space-3);\n color: var(--color-ink-muted);\n font-size: var(--text-sm);\n}\n\n@keyframes palette-in {\n from {\n opacity: 0;\n scale: 0.98;\n translate: 0 calc(var(--space-2) * -1);\n }\n}\n@keyframes fade-in {\n from {\n opacity: 0;\n }\n}\n@keyframes fade-out {\n to {\n opacity: 0;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .overlay[data-state],\n .content[data-state] {\n animation: none;\n }\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyboard shortcuts written as `mod+shift+l`: parsing, matching a keydown, and showing them.
|
|
3
|
+
* Not exported from the package.
|
|
4
|
+
*
|
|
5
|
+
* `mod` is Command on Apple platforms and Control elsewhere. The other modifiers are `ctrl`,
|
|
6
|
+
* `alt`, `shift` and `meta`. The key is the last part: a letter, a digit or a key name
|
|
7
|
+
* (`enter`, `escape`, `arrowup`, `backspace`, `plus`…).
|
|
8
|
+
*/
|
|
9
|
+
export interface ParsedShortcut {
|
|
10
|
+
meta: boolean;
|
|
11
|
+
ctrl: boolean;
|
|
12
|
+
alt: boolean;
|
|
13
|
+
shift: boolean;
|
|
14
|
+
key: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function isApplePlatform(): boolean;
|
|
17
|
+
export declare function parseShortcut(shortcut: string, apple: boolean): ParsedShortcut;
|
|
18
|
+
/** Whether a keydown is exactly this shortcut: the same key and no other modifier held. */
|
|
19
|
+
export declare function matchesShortcut(event: KeyboardEvent, shortcut: ParsedShortcut): boolean;
|
|
20
|
+
export interface ShortcutLabel {
|
|
21
|
+
/** One entry per key, in order, as printed on the keycap. */
|
|
22
|
+
keys: string[];
|
|
23
|
+
/** Read aloud: "Command Shift L". */
|
|
24
|
+
spoken: string;
|
|
25
|
+
/** For `aria-keyshortcuts`: "Meta+Shift+L". */
|
|
26
|
+
aria: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function describeShortcut(shortcut: string, apple: boolean): ShortcutLabel;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
//#region src/components/overlays/CommandPalette/shortcut.ts
|
|
2
|
+
function e() {
|
|
3
|
+
return typeof navigator < "u" && /mac|iphone|ipad|ipod/i.test(navigator.userAgent);
|
|
4
|
+
}
|
|
5
|
+
function t(e, t) {
|
|
6
|
+
let n = e.toLowerCase().split("+").map((e) => e.trim()).filter(Boolean), r = {
|
|
7
|
+
meta: !1,
|
|
8
|
+
ctrl: !1,
|
|
9
|
+
alt: !1,
|
|
10
|
+
shift: !1,
|
|
11
|
+
key: ""
|
|
12
|
+
};
|
|
13
|
+
return n.forEach((e, i) => {
|
|
14
|
+
i === n.length - 1 ? r.key = e === "plus" ? "+" : e : e === "mod" ? r[t ? "meta" : "ctrl"] = !0 : e === "ctrl" || e === "control" ? r.ctrl = !0 : e === "alt" || e === "option" ? r.alt = !0 : e === "shift" ? r.shift = !0 : (e === "meta" || e === "cmd" || e === "command") && (r.meta = !0);
|
|
15
|
+
}), r;
|
|
16
|
+
}
|
|
17
|
+
function n(e, t) {
|
|
18
|
+
if (e.metaKey !== t.meta || e.ctrlKey !== t.ctrl || e.altKey !== t.alt || e.shiftKey !== t.shift) return !1;
|
|
19
|
+
let n = t.key;
|
|
20
|
+
return e.key.toLowerCase() === n ? !0 : /^[a-z]$/.test(n) ? e.code === `Key${n.toUpperCase()}` : /^[0-9]$/.test(n) ? e.code === `Digit${n}` : !1;
|
|
21
|
+
}
|
|
22
|
+
var r = {
|
|
23
|
+
enter: [
|
|
24
|
+
"↵",
|
|
25
|
+
"Enter",
|
|
26
|
+
"Enter"
|
|
27
|
+
],
|
|
28
|
+
escape: [
|
|
29
|
+
"Esc",
|
|
30
|
+
"Escape",
|
|
31
|
+
"Escape"
|
|
32
|
+
],
|
|
33
|
+
esc: [
|
|
34
|
+
"Esc",
|
|
35
|
+
"Escape",
|
|
36
|
+
"Escape"
|
|
37
|
+
],
|
|
38
|
+
backspace: [
|
|
39
|
+
"⌫",
|
|
40
|
+
"Backspace",
|
|
41
|
+
"Backspace"
|
|
42
|
+
],
|
|
43
|
+
delete: [
|
|
44
|
+
"Del",
|
|
45
|
+
"Delete",
|
|
46
|
+
"Delete"
|
|
47
|
+
],
|
|
48
|
+
tab: [
|
|
49
|
+
"Tab",
|
|
50
|
+
"Tab",
|
|
51
|
+
"Tab"
|
|
52
|
+
],
|
|
53
|
+
space: [
|
|
54
|
+
"Space",
|
|
55
|
+
"Space",
|
|
56
|
+
"Space"
|
|
57
|
+
],
|
|
58
|
+
arrowup: [
|
|
59
|
+
"↑",
|
|
60
|
+
"Up arrow",
|
|
61
|
+
"ArrowUp"
|
|
62
|
+
],
|
|
63
|
+
arrowdown: [
|
|
64
|
+
"↓",
|
|
65
|
+
"Down arrow",
|
|
66
|
+
"ArrowDown"
|
|
67
|
+
],
|
|
68
|
+
arrowleft: [
|
|
69
|
+
"←",
|
|
70
|
+
"Left arrow",
|
|
71
|
+
"ArrowLeft"
|
|
72
|
+
],
|
|
73
|
+
arrowright: [
|
|
74
|
+
"→",
|
|
75
|
+
"Right arrow",
|
|
76
|
+
"ArrowRight"
|
|
77
|
+
],
|
|
78
|
+
"+": [
|
|
79
|
+
"+",
|
|
80
|
+
"Plus",
|
|
81
|
+
"Plus"
|
|
82
|
+
]
|
|
83
|
+
};
|
|
84
|
+
function i(e, n) {
|
|
85
|
+
let i = t(e, n), a = [], o = [], s = [], c = (e, t, n) => {
|
|
86
|
+
a.push(e), o.push(t), s.push(n);
|
|
87
|
+
};
|
|
88
|
+
n ? (i.ctrl && c("⌃", "Control", "Control"), i.alt && c("⌥", "Option", "Alt"), i.shift && c("⇧", "Shift", "Shift"), i.meta && c("⌘", "Command", "Meta")) : (i.ctrl && c("Ctrl", "Control", "Control"), i.meta && c("Meta", "Meta", "Meta"), i.alt && c("Alt", "Alt", "Alt"), i.shift && c("Shift", "Shift", "Shift"));
|
|
89
|
+
let l = r[i.key];
|
|
90
|
+
if (l) c(...l);
|
|
91
|
+
else if (i.key !== "") {
|
|
92
|
+
let e = i.key.charAt(0).toUpperCase() + i.key.slice(1);
|
|
93
|
+
c(e, e, e);
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
keys: a,
|
|
97
|
+
spoken: o.join(" "),
|
|
98
|
+
aria: s.join("+")
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//#endregion
|
|
102
|
+
export { i as describeShortcut, e as isApplePlatform, n as matchesShortcut, t as parseShortcut };
|
|
103
|
+
|
|
104
|
+
//# sourceMappingURL=shortcut.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shortcut.js","names":["isApplePlatform","parseShortcut","parts","shortcut","part","parsed","index","apple","matchesShortcut","event","key","KEY_NAMES","describeShortcut","keys","spoken","aria","add","glyph","word","name","named"],"sources":["../../../../src/components/overlays/CommandPalette/shortcut.ts"],"sourcesContent":["/**\n * Keyboard shortcuts written as `mod+shift+l`: parsing, matching a keydown, and showing them.\n * Not exported from the package.\n *\n * `mod` is Command on Apple platforms and Control elsewhere. The other modifiers are `ctrl`,\n * `alt`, `shift` and `meta`. The key is the last part: a letter, a digit or a key name\n * (`enter`, `escape`, `arrowup`, `backspace`, `plus`…).\n */\n\nexport interface ParsedShortcut {\n meta: boolean\n ctrl: boolean\n alt: boolean\n shift: boolean\n key: string\n}\n\nexport function isApplePlatform(): boolean {\n return typeof navigator !== 'undefined' && /mac|iphone|ipad|ipod/i.test(navigator.userAgent)\n}\n\nexport function parseShortcut(shortcut: string, apple: boolean): ParsedShortcut {\n const parts = shortcut\n .toLowerCase()\n .split('+')\n .map((part) => part.trim())\n .filter(Boolean)\n const parsed: ParsedShortcut = { meta: false, ctrl: false, alt: false, shift: false, key: '' }\n parts.forEach((part, index) => {\n if (index === parts.length - 1) parsed.key = part === 'plus' ? '+' : part\n else if (part === 'mod') parsed[apple ? 'meta' : 'ctrl'] = true\n else if (part === 'ctrl' || part === 'control') parsed.ctrl = true\n else if (part === 'alt' || part === 'option') parsed.alt = true\n else if (part === 'shift') parsed.shift = true\n else if (part === 'meta' || part === 'cmd' || part === 'command') parsed.meta = true\n })\n return parsed\n}\n\n/** Whether a keydown is exactly this shortcut: the same key and no other modifier held. */\nexport function matchesShortcut(event: KeyboardEvent, shortcut: ParsedShortcut): boolean {\n if (\n event.metaKey !== shortcut.meta ||\n event.ctrlKey !== shortcut.ctrl ||\n event.altKey !== shortcut.alt ||\n event.shiftKey !== shortcut.shift\n ) {\n return false\n }\n const key = shortcut.key\n if (event.key.toLowerCase() === key) return true\n // Option and Shift change `event.key` (⌥K is \"˚\"), so letters and digits also match the code.\n if (/^[a-z]$/.test(key)) return event.code === `Key${key.toUpperCase()}`\n if (/^[0-9]$/.test(key)) return event.code === `Digit${key}`\n return false\n}\n\nconst KEY_NAMES: Record<string, [glyph: string, spoken: string, aria: string]> = {\n enter: ['↵', 'Enter', 'Enter'],\n escape: ['Esc', 'Escape', 'Escape'],\n esc: ['Esc', 'Escape', 'Escape'],\n backspace: ['⌫', 'Backspace', 'Backspace'],\n delete: ['Del', 'Delete', 'Delete'],\n tab: ['Tab', 'Tab', 'Tab'],\n space: ['Space', 'Space', 'Space'],\n arrowup: ['↑', 'Up arrow', 'ArrowUp'],\n arrowdown: ['↓', 'Down arrow', 'ArrowDown'],\n arrowleft: ['←', 'Left arrow', 'ArrowLeft'],\n arrowright: ['→', 'Right arrow', 'ArrowRight'],\n '+': ['+', 'Plus', 'Plus'],\n}\n\nexport interface ShortcutLabel {\n /** One entry per key, in order, as printed on the keycap. */\n keys: string[]\n /** Read aloud: \"Command Shift L\". */\n spoken: string\n /** For `aria-keyshortcuts`: \"Meta+Shift+L\". */\n aria: string\n}\n\nexport function describeShortcut(shortcut: string, apple: boolean): ShortcutLabel {\n const parsed = parseShortcut(shortcut, apple)\n const keys: string[] = []\n const spoken: string[] = []\n const aria: string[] = []\n const add = (glyph: string, word: string, name: string) => {\n keys.push(glyph)\n spoken.push(word)\n aria.push(name)\n }\n if (apple) {\n if (parsed.ctrl) add('⌃', 'Control', 'Control')\n if (parsed.alt) add('⌥', 'Option', 'Alt')\n if (parsed.shift) add('⇧', 'Shift', 'Shift')\n if (parsed.meta) add('⌘', 'Command', 'Meta')\n } else {\n if (parsed.ctrl) add('Ctrl', 'Control', 'Control')\n if (parsed.meta) add('Meta', 'Meta', 'Meta')\n if (parsed.alt) add('Alt', 'Alt', 'Alt')\n if (parsed.shift) add('Shift', 'Shift', 'Shift')\n }\n const named = KEY_NAMES[parsed.key]\n if (named) add(...named)\n else if (parsed.key !== '') {\n const name = parsed.key.charAt(0).toUpperCase() + parsed.key.slice(1)\n add(name, name, name)\n }\n return { keys, spoken: spoken.join(' '), aria: aria.join('+') }\n}\n"],"mappings":";AAiBA,SAAgBA,IAA2B;CACzC,OAAO,OAAO,YAAc,OAAe,wBAAwB,KAAK,UAAU,SAAS;AAC7F;AAEA,SAAgBC,EAAc,GAAkB,GAAgC;CAC9E,IAAMC,IAAQC,EACX,YAAY,CAAC,CACb,MAAM,GAAG,CAAC,CACV,KAAK,MAASC,EAAK,KAAK,CAAC,CAAC,CAC1B,OAAO,OAAO,GACXC,IAAyB;EAAE,MAAM;EAAO,MAAM;EAAO,KAAK;EAAO,OAAO;EAAO,KAAK;CAAG;CAS7F,OARAH,EAAM,SAAS,GAAM,MAAU;EAC7B,AAAII,MAAUJ,EAAM,SAAS,IAAG,EAAO,MAAME,MAAS,SAAS,MAAMA,IAC5DA,MAAS,QAAO,EAAOG,IAAQ,SAAS,UAAU,KAClDH,MAAS,UAAUA,MAAS,YAAW,EAAO,OAAO,KACrDA,MAAS,SAASA,MAAS,WAAU,EAAO,MAAM,KAClDA,MAAS,UAAS,EAAO,QAAQ,MACjCA,MAAS,UAAUA,MAAS,SAASA,MAAS,eAAW,EAAO,OAAO;CAClF,CAAC,GACMC;AACT;AAGA,SAAgBG,EAAgB,GAAsB,GAAmC;CACvF,IACEC,EAAM,YAAYN,EAAS,QAC3BM,EAAM,YAAYN,EAAS,QAC3BM,EAAM,WAAWN,EAAS,OAC1BM,EAAM,aAAaN,EAAS,OAE5B,OAAO;CAET,IAAMO,IAAMP,EAAS;CAKrB,OAJIM,EAAM,IAAI,YAAY,MAAMC,IAAY,KAExC,UAAU,KAAKA,CAAG,IAAUD,EAAM,SAAS,MAAMC,EAAI,YAAY,MACjE,UAAU,KAAKA,CAAG,IAAUD,EAAM,SAAS,QAAQC,MAChD;AACT;AAEA,IAAMC,IAA2E;CAC/E,OAAO;EAAC;EAAK;EAAS;CAAO;CAC7B,QAAQ;EAAC;EAAO;EAAU;CAAQ;CAClC,KAAK;EAAC;EAAO;EAAU;CAAQ;CAC/B,WAAW;EAAC;EAAK;EAAa;CAAW;CACzC,QAAQ;EAAC;EAAO;EAAU;CAAQ;CAClC,KAAK;EAAC;EAAO;EAAO;CAAK;CACzB,OAAO;EAAC;EAAS;EAAS;CAAO;CACjC,SAAS;EAAC;EAAK;EAAY;CAAS;CACpC,WAAW;EAAC;EAAK;EAAc;CAAW;CAC1C,WAAW;EAAC;EAAK;EAAc;CAAW;CAC1C,YAAY;EAAC;EAAK;EAAe;CAAY;CAC7C,KAAK;EAAC;EAAK;EAAQ;CAAM;AAC3B;AAWA,SAAgBC,EAAiB,GAAkB,GAA+B;CAChF,IAAMP,IAASJ,EAAcE,GAAUI,CAAK,GACtCM,IAAiB,CAAC,GAClBC,IAAmB,CAAC,GACpBC,IAAiB,CAAC,GAClBC,KAAO,GAAe,GAAc,MAAiB;EAGzD,AAFAH,EAAK,KAAKI,CAAK,GACfH,EAAO,KAAKI,CAAI,GAChBH,EAAK,KAAKI,CAAI;CAChB;CACA,AAAIZ,KACEF,EAAO,QAAMW,EAAI,KAAK,WAAW,SAAS,GAC1CX,EAAO,OAAKW,EAAI,KAAK,UAAU,KAAK,GACpCX,EAAO,SAAOW,EAAI,KAAK,SAAS,OAAO,GACvCX,EAAO,QAAMW,EAAI,KAAK,WAAW,MAAM,MAEvCX,EAAO,QAAMW,EAAI,QAAQ,WAAW,SAAS,GAC7CX,EAAO,QAAMW,EAAI,QAAQ,QAAQ,MAAM,GACvCX,EAAO,OAAKW,EAAI,OAAO,OAAO,KAAK,GACnCX,EAAO,SAAOW,EAAI,SAAS,SAAS,OAAO;CAEjD,IAAMI,IAAQT,EAAUN,EAAO;CAC/B,IAAIe,GAAO,EAAI,GAAGA,CAAK;MAClB,IAAIf,EAAO,QAAQ,IAAI;EAC1B,IAAMc,IAAOd,EAAO,IAAI,OAAO,CAAC,CAAC,CAAC,YAAY,IAAIA,EAAO,IAAI,MAAM,CAAC;EACpE,EAAIc,GAAMA,GAAMA,CAAI;CACtB;CACA,OAAO;EAAE;EAAM,QAAQL,EAAO,KAAK,GAAG;EAAG,MAAMC,EAAK,KAAK,GAAG;CAAE;AAChE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CodeToken } from '../components/display/CodeBlock/index.js';
|
|
2
|
+
/** The languages `highlight` understands, with their usual aliases. */
|
|
3
|
+
export type HighlightLanguage = 'js' | 'javascript' | 'jsx' | 'ts' | 'typescript' | 'tsx';
|
|
4
|
+
/**
|
|
5
|
+
* Tokens for `CodeBlock`'s `tokens` prop: one array per line of `code`, each token tagged with
|
|
6
|
+
* what it is (keyword, string, comment…) so the theme colours it. Resolves to `undefined` for a
|
|
7
|
+
* language it doesn't know, which `CodeBlock` shows as plain code.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* Install `shiki` alongside kiln-ui to use it. Call it wherever your code is ready: in a server
|
|
11
|
+
* component or at build time, so the browser downloads no highlighter, or in the browser, where
|
|
12
|
+
* Shiki and the grammar load on the first call.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* const tokens = await highlight(source, 'tsx')
|
|
16
|
+
* return <CodeBlock code={source} language="TSX" tokens={tokens} />
|
|
17
|
+
*/
|
|
18
|
+
export declare function highlight(code: string, language: string): Promise<CodeToken[][] | undefined>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { trimTrailingNewlines as e } from "../utils/newlines.js";
|
|
2
|
+
//#region src/highlight/index.ts
|
|
3
|
+
var t = {
|
|
4
|
+
js: "javascript",
|
|
5
|
+
javascript: "javascript",
|
|
6
|
+
jsx: "jsx",
|
|
7
|
+
ts: "typescript",
|
|
8
|
+
typescript: "typescript",
|
|
9
|
+
tsx: "tsx"
|
|
10
|
+
}, n = {
|
|
11
|
+
javascript: () => import("shiki/langs/javascript.mjs"),
|
|
12
|
+
jsx: () => import("shiki/langs/jsx.mjs"),
|
|
13
|
+
typescript: () => import("shiki/langs/typescript.mjs"),
|
|
14
|
+
tsx: () => import("shiki/langs/tsx.mjs")
|
|
15
|
+
}, r = [
|
|
16
|
+
"keyword",
|
|
17
|
+
"string",
|
|
18
|
+
"comment",
|
|
19
|
+
"constant",
|
|
20
|
+
"function",
|
|
21
|
+
"type",
|
|
22
|
+
"tag",
|
|
23
|
+
"attribute",
|
|
24
|
+
"punctuation"
|
|
25
|
+
], i = (e) => `#0000${(r.indexOf(e) + 1).toString(16).padStart(2, "0")}`, a = new Map(r.map((e) => [i(e), e])), o = "#000000", s = {
|
|
26
|
+
name: "kiln",
|
|
27
|
+
type: "light",
|
|
28
|
+
fg: o,
|
|
29
|
+
bg: "#ffffff",
|
|
30
|
+
settings: [
|
|
31
|
+
[["comment", "punctuation.definition.comment"], "comment"],
|
|
32
|
+
[["string", "punctuation.definition.string"], "string"],
|
|
33
|
+
[["meta.template.expression"], null],
|
|
34
|
+
[[
|
|
35
|
+
"constant.numeric",
|
|
36
|
+
"constant.language",
|
|
37
|
+
"constant.character",
|
|
38
|
+
"variable.language"
|
|
39
|
+
], "constant"],
|
|
40
|
+
[[
|
|
41
|
+
"keyword",
|
|
42
|
+
"storage",
|
|
43
|
+
"keyword.operator.new",
|
|
44
|
+
"keyword.operator.expression"
|
|
45
|
+
], "keyword"],
|
|
46
|
+
[["entity.name.function", "support.function"], "function"],
|
|
47
|
+
[[
|
|
48
|
+
"entity.name.type",
|
|
49
|
+
"entity.name.class",
|
|
50
|
+
"entity.other.inherited-class",
|
|
51
|
+
"support.type",
|
|
52
|
+
"support.class"
|
|
53
|
+
], "type"],
|
|
54
|
+
[["entity.name.tag"], "tag"],
|
|
55
|
+
[["entity.other.attribute-name"], "attribute"],
|
|
56
|
+
[[
|
|
57
|
+
"punctuation",
|
|
58
|
+
"meta.brace",
|
|
59
|
+
"keyword.operator"
|
|
60
|
+
], "punctuation"],
|
|
61
|
+
[["punctuation.definition.string.template.begin", "punctuation.definition.string.template.end"], "string"],
|
|
62
|
+
[["punctuation.definition.template-expression"], "punctuation"]
|
|
63
|
+
].map(([e, t]) => ({
|
|
64
|
+
scope: e,
|
|
65
|
+
settings: { foreground: t ? i(t) : o }
|
|
66
|
+
}))
|
|
67
|
+
}, c, l = /* @__PURE__ */ new Map();
|
|
68
|
+
function u(e) {
|
|
69
|
+
return c ??= Promise.all([import("shiki/core"), import("shiki/engine/javascript")]).then(([{ createHighlighterCore: e }, { createJavaScriptRegexEngine: t }]) => e({
|
|
70
|
+
themes: [s],
|
|
71
|
+
langs: [],
|
|
72
|
+
engine: t()
|
|
73
|
+
})), c.then(async (t) => {
|
|
74
|
+
let r = l.get(e);
|
|
75
|
+
return r || (r = n[e]().then((e) => t.loadLanguage(e.default)), l.set(e, r)), await r, t;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function d(e) {
|
|
79
|
+
return Object.hasOwn(t, e);
|
|
80
|
+
}
|
|
81
|
+
async function f(n, r) {
|
|
82
|
+
let i = r.toLowerCase();
|
|
83
|
+
if (!d(i)) return;
|
|
84
|
+
let o = t[i];
|
|
85
|
+
return (await u(o)).codeToTokensBase(e(n), {
|
|
86
|
+
lang: o,
|
|
87
|
+
theme: "kiln"
|
|
88
|
+
}).map((e) => {
|
|
89
|
+
let t = [];
|
|
90
|
+
for (let { content: n, color: r } of e) {
|
|
91
|
+
let e = r ? a.get(r.toLowerCase()) : void 0, i = t.at(-1);
|
|
92
|
+
i && i.type === e ? i.content += n : t.push(e ? {
|
|
93
|
+
content: n,
|
|
94
|
+
type: e
|
|
95
|
+
} : { content: n });
|
|
96
|
+
}
|
|
97
|
+
return t;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
export { f as highlight };
|
|
102
|
+
|
|
103
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["GRAMMARS","LOADERS","TYPES","colourOf","type","typeOf","PLAIN","THEME","scope","highlighter","loaded","load","createHighlighterCore","createJavaScriptRegexEngine","language","grammar","core","module","isHighlightLanguage","highlight","id","trimTrailingNewlines","code","tokens","line","color","previous","content"],"sources":["../../src/highlight/index.ts"],"sourcesContent":["/*\n * @mitcsutt/kiln-ui/highlight: syntax highlighting for CodeBlock, kept out of the main entry.\n * It runs Shiki (an optional peer dependency) with its JavaScript regex engine, and loads Shiki\n * and each grammar only when the first block in that language is highlighted.\n */\nimport type { CodeToken, CodeTokenType } from '#components/display/CodeBlock'\nimport { trimTrailingNewlines } from '#utils/newlines'\nimport type { HighlighterCore, LanguageRegistration, ThemeRegistration } from 'shiki/core'\n\n/** The languages `highlight` understands, with their usual aliases. */\nexport type HighlightLanguage = 'js' | 'javascript' | 'jsx' | 'ts' | 'typescript' | 'tsx'\n\ntype Grammar = 'javascript' | 'jsx' | 'typescript' | 'tsx'\n\nconst GRAMMARS: Record<HighlightLanguage, Grammar> = {\n js: 'javascript',\n javascript: 'javascript',\n jsx: 'jsx',\n ts: 'typescript',\n typescript: 'typescript',\n tsx: 'tsx',\n}\n\nconst LOADERS: Record<Grammar, () => Promise<{ default: LanguageRegistration[] }>> = {\n javascript: () => import('shiki/langs/javascript.mjs'),\n jsx: () => import('shiki/langs/jsx.mjs'),\n typescript: () => import('shiki/langs/typescript.mjs'),\n tsx: () => import('shiki/langs/tsx.mjs'),\n}\n\nconst TYPES: CodeTokenType[] = [\n 'keyword',\n 'string',\n 'comment',\n 'constant',\n 'function',\n 'type',\n 'tag',\n 'attribute',\n 'punctuation',\n]\n\n/** Each token type gets a stand-in colour, which `highlight` reads back as the type. */\nconst colourOf = (type: CodeTokenType) =>\n `#0000${(TYPES.indexOf(type) + 1).toString(16).padStart(2, '0')}`\nconst typeOf = new Map(TYPES.map((type) => [colourOf(type), type]))\nconst PLAIN = '#000000'\n\n/** TextMate scopes → token types. A deeper or longer scope wins, so the exceptions follow. */\nconst RULES: [string[], CodeTokenType | null][] = [\n [['comment', 'punctuation.definition.comment'], 'comment'],\n [['string', 'punctuation.definition.string'], 'string'],\n [['meta.template.expression'], null],\n [\n ['constant.numeric', 'constant.language', 'constant.character', 'variable.language'],\n 'constant',\n ],\n [['keyword', 'storage', 'keyword.operator.new', 'keyword.operator.expression'], 'keyword'],\n [['entity.name.function', 'support.function'], 'function'],\n [\n [\n 'entity.name.type',\n 'entity.name.class',\n 'entity.other.inherited-class',\n 'support.type',\n 'support.class',\n ],\n 'type',\n ],\n [['entity.name.tag'], 'tag'],\n [['entity.other.attribute-name'], 'attribute'],\n [['punctuation', 'meta.brace', 'keyword.operator'], 'punctuation'],\n [\n ['punctuation.definition.string.template.begin', 'punctuation.definition.string.template.end'],\n 'string',\n ],\n [['punctuation.definition.template-expression'], 'punctuation'],\n]\n\nconst THEME: ThemeRegistration = {\n name: 'kiln',\n type: 'light',\n fg: PLAIN,\n bg: '#ffffff',\n settings: RULES.map(([scope, type]) => ({\n scope,\n settings: { foreground: type ? colourOf(type) : PLAIN },\n })),\n}\n\nlet highlighter: Promise<HighlighterCore> | undefined\nconst loaded = new Map<Grammar, Promise<void>>()\n\nfunction load(grammar: Grammar): Promise<HighlighterCore> {\n highlighter ??= Promise.all([import('shiki/core'), import('shiki/engine/javascript')]).then(\n ([{ createHighlighterCore }, { createJavaScriptRegexEngine }]) =>\n createHighlighterCore({ themes: [THEME], langs: [], engine: createJavaScriptRegexEngine() }),\n )\n return highlighter.then(async (core) => {\n let language = loaded.get(grammar)\n if (!language) {\n language = LOADERS[grammar]().then((module) => core.loadLanguage(module.default))\n loaded.set(grammar, language)\n }\n await language\n return core\n })\n}\n\nfunction isHighlightLanguage(language: string): language is HighlightLanguage {\n return Object.hasOwn(GRAMMARS, language)\n}\n\n/**\n * Tokens for `CodeBlock`'s `tokens` prop: one array per line of `code`, each token tagged with\n * what it is (keyword, string, comment…) so the theme colours it. Resolves to `undefined` for a\n * language it doesn't know, which `CodeBlock` shows as plain code.\n *\n * @remarks\n * Install `shiki` alongside kiln-ui to use it. Call it wherever your code is ready: in a server\n * component or at build time, so the browser downloads no highlighter, or in the browser, where\n * Shiki and the grammar load on the first call.\n *\n * @example\n * const tokens = await highlight(source, 'tsx')\n * return <CodeBlock code={source} language=\"TSX\" tokens={tokens} />\n */\nexport async function highlight(\n code: string,\n language: string,\n): Promise<CodeToken[][] | undefined> {\n const id = language.toLowerCase()\n if (!isHighlightLanguage(id)) return undefined\n const grammar = GRAMMARS[id]\n const core = await load(grammar)\n const lines = core.codeToTokensBase(trimTrailingNewlines(code), { lang: grammar, theme: 'kiln' })\n return lines.map((line) => {\n const tokens: CodeToken[] = []\n for (const { content, color } of line) {\n const type = color ? typeOf.get(color.toLowerCase()) : undefined\n const previous = tokens.at(-1)\n if (previous && previous.type === type) previous.content += content\n else tokens.push(type ? { content, type } : { content })\n }\n return tokens\n })\n}\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,12 @@ export { ScrollArea } from './components/layout/ScrollArea/index.js';
|
|
|
32
32
|
export type { ScrollAreaProps, ScrollAreaAxis } from './components/layout/ScrollArea/index.js';
|
|
33
33
|
export { ActionBar } from './components/layout/ActionBar/index.js';
|
|
34
34
|
export type { ActionBarProps, ActionBarAlign, ActionBarElement, } from './components/layout/ActionBar/index.js';
|
|
35
|
+
export { Collapse } from './components/layout/Collapse/index.js';
|
|
36
|
+
export type { CollapseProps } from './components/layout/Collapse/index.js';
|
|
37
|
+
export { Transition } from './components/layout/Transition/index.js';
|
|
38
|
+
export type { TransitionProps, TransitionPreset } from './components/layout/Transition/index.js';
|
|
39
|
+
export { ShowMore } from './components/layout/ShowMore/index.js';
|
|
40
|
+
export type { ShowMoreProps, ShowMoreMode } from './components/layout/ShowMore/index.js';
|
|
35
41
|
export { Heading, DEFAULT_HEADING_SIZE } from './components/typography/Heading/index.js';
|
|
36
42
|
export type { HeadingProps, HeadingLevel, HeadingSize, HeadingTone, HeadingElement, HeadingMeasure, } from './components/typography/Heading/index.js';
|
|
37
43
|
export { Text } from './components/typography/Text/index.js';
|
|
@@ -56,6 +62,8 @@ export { Button } from './components/actions/Button/index.js';
|
|
|
56
62
|
export type { ButtonProps, ButtonVariant, ButtonTone } from './components/actions/Button/index.js';
|
|
57
63
|
export { IconButton } from './components/actions/IconButton/index.js';
|
|
58
64
|
export type { IconButtonProps, IconButtonShape } from './components/actions/IconButton/index.js';
|
|
65
|
+
export { CopyButton, useClipboard } from './components/actions/CopyButton/index.js';
|
|
66
|
+
export type { CopyButtonProps, CopyButtonRenderProps, UseClipboardOptions, UseClipboardResult, } from './components/actions/CopyButton/index.js';
|
|
59
67
|
export { ToggleChip } from './components/actions/ToggleChip/index.js';
|
|
60
68
|
export type { ToggleChipProps, ToggleChipSize } from './components/actions/ToggleChip/index.js';
|
|
61
69
|
export { ChipGroup } from './components/actions/ChipGroup/index.js';
|
|
@@ -110,8 +118,22 @@ export { ColorField } from './components/inputs/ColorField/index.js';
|
|
|
110
118
|
export type { ColorFieldProps } from './components/inputs/ColorField/index.js';
|
|
111
119
|
export { SwitchField } from './components/inputs/SwitchField/index.js';
|
|
112
120
|
export type { SwitchFieldProps } from './components/inputs/SwitchField/index.js';
|
|
113
|
-
export { DateRangeField } from './components/inputs/DateRangeField/index.js';
|
|
114
|
-
export type { DateRangeFieldProps, DateRangeValue } from './components/inputs/DateRangeField/index.js';
|
|
121
|
+
export { DateRangeField, DateRangePickerField } from './components/inputs/DateRangeField/index.js';
|
|
122
|
+
export type { DateRangeFieldProps, DateRangeValue, DateRangePickerFieldProps, DateRangePreset, } from './components/inputs/DateRangeField/index.js';
|
|
123
|
+
export { Calendar } from './components/inputs/Calendar/index.js';
|
|
124
|
+
export type { CalendarProps, CalendarSingleProps, CalendarRangeProps, CalendarLabels, } from './components/inputs/Calendar/index.js';
|
|
125
|
+
export { DateInput } from './components/inputs/DateInput/index.js';
|
|
126
|
+
export type { DateInputProps, DateTimeLabels } from './components/inputs/DateInput/index.js';
|
|
127
|
+
export { DateField } from './components/inputs/DateField/index.js';
|
|
128
|
+
export type { DateFieldProps } from './components/inputs/DateField/index.js';
|
|
129
|
+
export { TimeInput } from './components/inputs/TimeInput/index.js';
|
|
130
|
+
export type { TimeInputProps } from './components/inputs/TimeInput/index.js';
|
|
131
|
+
export { TimeField } from './components/inputs/TimeField/index.js';
|
|
132
|
+
export type { TimeFieldProps } from './components/inputs/TimeField/index.js';
|
|
133
|
+
export { DateTimeInput } from './components/inputs/DateTimeInput/index.js';
|
|
134
|
+
export type { DateTimeInputProps } from './components/inputs/DateTimeInput/index.js';
|
|
135
|
+
export { DateTimeField } from './components/inputs/DateTimeField/index.js';
|
|
136
|
+
export type { DateTimeFieldProps } from './components/inputs/DateTimeField/index.js';
|
|
115
137
|
export { CheckboxGroup } from './components/inputs/CheckboxGroup/index.js';
|
|
116
138
|
export type { CheckboxGroupProps, CheckboxGroupItemProps, CheckboxGroupColumns, ChoiceOption, } from './components/inputs/CheckboxGroup/index.js';
|
|
117
139
|
export { CheckboxGroupField } from './components/inputs/CheckboxGroupField/index.js';
|
|
@@ -150,12 +172,18 @@ export { FileDrop } from './components/inputs/FileDrop/index.js';
|
|
|
150
172
|
export type { FileDropProps, FileRejection, FileRejectReason, FileValue, StoredFile, } from './components/inputs/FileDrop/index.js';
|
|
151
173
|
export { FileField } from './components/inputs/FileField/index.js';
|
|
152
174
|
export type { FileFieldProps } from './components/inputs/FileField/index.js';
|
|
175
|
+
export { JsonInput, validateJson, formatJson, minifyJson } from './components/inputs/JsonInput/index.js';
|
|
176
|
+
export type { JsonInputProps, JsonValidation, JsonInputError, JsonIndent, JsonSyntaxError, } from './components/inputs/JsonInput/index.js';
|
|
177
|
+
export { JsonField, describeJsonError } from './components/inputs/JsonField/index.js';
|
|
178
|
+
export type { JsonFieldProps } from './components/inputs/JsonField/index.js';
|
|
153
179
|
export { Card } from './components/display/Card/index.js';
|
|
154
180
|
export type { CardProps, CardVariant, CardMediaProps, CardMediaRatio, CardTitleProps, CardTitleLevel, } from './components/display/Card/index.js';
|
|
155
181
|
export { Badge } from './components/display/Badge/index.js';
|
|
156
182
|
export type { BadgeProps, BadgeVariant, BadgeSize } from './components/display/Badge/index.js';
|
|
157
183
|
export { Tag, TagList } from './components/display/Tag/index.js';
|
|
158
184
|
export type { TagProps, TagColor, TagSize, TagListProps } from './components/display/Tag/index.js';
|
|
185
|
+
export { Swatch } from './components/display/Swatch/index.js';
|
|
186
|
+
export type { SwatchProps, SwatchColor, SwatchSize } from './components/display/Swatch/index.js';
|
|
159
187
|
export { Avatar, getInitials, avatarColor } from './components/display/Avatar/index.js';
|
|
160
188
|
export type { AvatarProps, AvatarSize, AvatarColor } from './components/display/Avatar/index.js';
|
|
161
189
|
export { AvatarGroup } from './components/display/AvatarGroup/index.js';
|
|
@@ -175,7 +203,7 @@ export type { MediaProps, MediaRatio, MediaFit, MediaRadius, MediaSize, } from '
|
|
|
175
203
|
export { Marquee } from './components/display/Marquee/index.js';
|
|
176
204
|
export type { MarqueeProps, MarqueeSpeed, MarqueeDirection, MarqueeSurface, } from './components/display/Marquee/index.js';
|
|
177
205
|
export { CodeBlock } from './components/display/CodeBlock/index.js';
|
|
178
|
-
export type { CodeBlockProps } from './components/display/CodeBlock/index.js';
|
|
206
|
+
export type { CodeBlockProps, CodeToken, CodeTokenType } from './components/display/CodeBlock/index.js';
|
|
179
207
|
export { Stamp } from './components/display/Stamp/index.js';
|
|
180
208
|
export type { StampProps, StampPlacement } from './components/display/Stamp/index.js';
|
|
181
209
|
export { Progress } from './components/display/Progress/index.js';
|
|
@@ -188,24 +216,30 @@ export { EmptyState } from './components/display/EmptyState/index.js';
|
|
|
188
216
|
export type { EmptyStateProps, EmptyStateTitleElement } from './components/display/EmptyState/index.js';
|
|
189
217
|
export { Tabs } from './components/navigation/Tabs/index.js';
|
|
190
218
|
export type { TabsProps, TabsVariant, TabsListProps, TabsTriggerProps, TabsContentProps, } from './components/navigation/Tabs/index.js';
|
|
191
|
-
export { NavLinks } from './components/navigation/NavLinks/index.js';
|
|
192
|
-
export type { NavLinksProps, NavLinksItemProps, NavLinksOrientation, NavLinksSize, } from './components/navigation/NavLinks/index.js';
|
|
219
|
+
export { NavLinks, NavLinksGroup } from './components/navigation/NavLinks/index.js';
|
|
220
|
+
export type { NavLinksProps, NavLinksItemProps, NavLinksGroupProps, NavLinksOrientation, NavLinksSize, } from './components/navigation/NavLinks/index.js';
|
|
193
221
|
export { BottomNav } from './components/navigation/BottomNav/index.js';
|
|
194
222
|
export type { BottomNavProps, BottomNavItemProps } from './components/navigation/BottomNav/index.js';
|
|
195
223
|
export { Accordion } from './components/navigation/Accordion/index.js';
|
|
196
224
|
export type { AccordionProps, AccordionVariant, AccordionSize, AccordionItemProps, AccordionTriggerProps, AccordionContentProps, } from './components/navigation/Accordion/index.js';
|
|
225
|
+
export { Collapsible } from './components/navigation/Collapsible/index.js';
|
|
226
|
+
export type { CollapsibleProps, CollapsibleTriggerProps, CollapsibleContentProps, } from './components/navigation/Collapsible/index.js';
|
|
197
227
|
export { Stepper } from './components/navigation/Stepper/index.js';
|
|
198
228
|
export type { StepperProps, StepperStep, StepperStatus } from './components/navigation/Stepper/index.js';
|
|
199
229
|
export { Spinner } from './components/feedback/Spinner/index.js';
|
|
200
230
|
export type { SpinnerProps } from './components/feedback/Spinner/index.js';
|
|
201
231
|
export { Alert } from './components/feedback/Alert/index.js';
|
|
202
232
|
export type { AlertProps, AlertTone, AlertVariant } from './components/feedback/Alert/index.js';
|
|
233
|
+
export { Toaster, toast } from './components/feedback/Toaster/index.js';
|
|
234
|
+
export type { ToasterProps, ToastPosition, ToastOptions, ToastTone, ToastAction, ToastPromiseMessage, ToastPromiseMessages, } from './components/feedback/Toaster/index.js';
|
|
203
235
|
export { LiveIndicator } from './components/feedback/LiveIndicator/index.js';
|
|
204
236
|
export type { LiveIndicatorProps, LiveIndicatorVariant } from './components/feedback/LiveIndicator/index.js';
|
|
205
237
|
export { Flash } from './components/feedback/Flash/index.js';
|
|
206
238
|
export type { FlashProps } from './components/feedback/Flash/index.js';
|
|
207
239
|
export { StatusDot } from './components/feedback/StatusDot/index.js';
|
|
208
240
|
export type { StatusDotProps } from './components/feedback/StatusDot/index.js';
|
|
241
|
+
export { Indicator } from './components/feedback/Indicator/index.js';
|
|
242
|
+
export type { IndicatorProps, IndicatorPosition, IndicatorShape, } from './components/feedback/Indicator/index.js';
|
|
209
243
|
export { RelativeTime, formatRelativeTime, formatAbsoluteTime, } from './components/feedback/RelativeTime/index.js';
|
|
210
244
|
export type { RelativeTimeProps, RelativeTimeStyle } from './components/feedback/RelativeTime/index.js';
|
|
211
245
|
export { Dialog } from './components/overlays/Dialog/index.js';
|
|
@@ -217,4 +251,6 @@ export type { PopoverProps, PopoverTriggerProps, PopoverAnchorProps, PopoverCont
|
|
|
217
251
|
export { DropdownMenu } from './components/overlays/DropdownMenu/index.js';
|
|
218
252
|
export type { DropdownMenuProps, DropdownMenuTriggerProps, DropdownMenuContentProps, DropdownMenuItemProps, DropdownMenuItemTone, DropdownMenuCheckboxItemProps, DropdownMenuRadioGroupProps, DropdownMenuRadioItemProps, DropdownMenuLabelProps, DropdownMenuSeparatorProps, DropdownMenuGroupProps, DropdownMenuSubProps, DropdownMenuSubTriggerProps, DropdownMenuSubContentProps, } from './components/overlays/DropdownMenu/index.js';
|
|
219
253
|
export { Tooltip, TooltipProvider } from './components/overlays/Tooltip/index.js';
|
|
254
|
+
export { CommandPalette } from './components/overlays/CommandPalette/index.js';
|
|
255
|
+
export type { CommandAction, CommandPaletteProps } from './components/overlays/CommandPalette/index.js';
|
|
220
256
|
export type { TooltipProps, TooltipProviderProps, TooltipSide, TooltipAlign, } from './components/overlays/Tooltip/index.js';
|