@cloudflare/kumo 1.10.0 → 1.11.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/CHANGELOG.md +97 -0
- package/ai/component-registry.json +21 -32
- package/ai/component-registry.md +66 -60
- package/ai/schemas.ts +2 -2
- package/dist/.build-complete +1 -1
- package/dist/ai/schemas.js +1 -2
- package/dist/ai/schemas.js.map +1 -1
- package/dist/checkbox-ZiHzIOCx.js +220 -0
- package/dist/checkbox-ZiHzIOCx.js.map +1 -0
- package/dist/{clipboard-text-DbvIaZ3g.js → clipboard-text-DXs1GdOt.js} +3 -3
- package/dist/{clipboard-text-DbvIaZ3g.js.map → clipboard-text-DXs1GdOt.js.map} +1 -1
- package/dist/code.js +62 -62
- package/dist/code.js.map +1 -1
- package/dist/{collapsible-OBNkTO48.js → collapsible-C3LJ1dfZ.js} +13 -11
- package/dist/collapsible-C3LJ1dfZ.js.map +1 -0
- package/dist/{combobox-CJqgoue6.js → combobox--ec3iibR.js} +63 -63
- package/dist/combobox--ec3iibR.js.map +1 -0
- package/dist/{command-palette-xctZ--ZT.js → command-palette-B_J7o7P-.js} +8 -8
- package/dist/{command-palette-xctZ--ZT.js.map → command-palette-B_J7o7P-.js.map} +1 -1
- package/dist/components/checkbox.js +1 -1
- package/dist/components/clipboard-text.js +1 -1
- package/dist/components/collapsible.js +1 -1
- package/dist/components/combobox.js +1 -1
- package/dist/components/command-palette.js +1 -1
- package/dist/components/dialog.js +1 -1
- package/dist/components/dropdown.js +1 -1
- package/dist/components/field.js +1 -1
- package/dist/components/flow.js +1857 -1803
- package/dist/components/flow.js.map +1 -1
- package/dist/components/input.js +3 -3
- package/dist/components/label.js +1 -1
- package/dist/components/link.js +1 -1
- package/dist/components/menubar.js +1 -1
- package/dist/components/meter.js +1 -1
- package/dist/components/pagination.js +1 -1
- package/dist/components/popover.js +1 -1
- package/dist/components/radio.js +1 -1
- package/dist/components/select.js +1 -1
- package/dist/components/sensitive-input.js +1 -1
- package/dist/components/switch.js +1 -1
- package/dist/components/table.js +1 -1
- package/dist/components/tabs.js +1 -1
- package/dist/components/toast.js +2 -2
- package/dist/components/tooltip.js +1 -1
- package/dist/{dialog-1pa-ezdL.js → dialog-DGaQTZVR.js} +2 -2
- package/dist/{dialog-1pa-ezdL.js.map → dialog-DGaQTZVR.js.map} +1 -1
- package/dist/{dropdown-BXg01-8j.js → dropdown-DBfVqi0v.js} +74 -75
- package/dist/dropdown-DBfVqi0v.js.map +1 -0
- package/dist/{field-BYaOyOtJ.js → field-CQmGKOVZ.js} +7 -7
- package/dist/{field-BYaOyOtJ.js.map → field-CQmGKOVZ.js.map} +1 -1
- package/dist/index.js +28 -28
- package/dist/{input-area-C3ddZhEo.js → input-area-BgpN8siO.js} +3 -3
- package/dist/{input-area-C3ddZhEo.js.map → input-area-BgpN8siO.js.map} +1 -1
- package/dist/{input-BXn3ElmF.js → input-gGpJCiT7.js} +3 -3
- package/dist/{input-BXn3ElmF.js.map → input-gGpJCiT7.js.map} +1 -1
- package/dist/{input-group-BiUKE2TR.js → input-group-DwPPwJEW.js} +2 -2
- package/dist/{input-group-BiUKE2TR.js.map → input-group-DwPPwJEW.js.map} +1 -1
- package/dist/label-hoE9-Nzo.js +62 -0
- package/dist/label-hoE9-Nzo.js.map +1 -0
- package/dist/{link-CfCaX9Ks.js → link-BFszrye7.js} +20 -14
- package/dist/link-BFszrye7.js.map +1 -0
- package/dist/{menubar-be9R8bE-.js → menubar-DF-6twXU.js} +2 -2
- package/dist/{menubar-be9R8bE-.js.map → menubar-DF-6twXU.js.map} +1 -1
- package/dist/{meter-CCpXrH8B.js → meter-CP6NBKRN.js} +2 -2
- package/dist/{meter-CCpXrH8B.js.map → meter-CP6NBKRN.js.map} +1 -1
- package/dist/{pagination-CaHm6TKa.js → pagination-BWkeDEqb.js} +44 -40
- package/dist/pagination-BWkeDEqb.js.map +1 -0
- package/dist/{popover-CHafAVT6.js → popover-B5CWcu7v.js} +2 -2
- package/dist/{popover-CHafAVT6.js.map → popover-B5CWcu7v.js.map} +1 -1
- package/dist/primitives/accordion.js +1 -1
- package/dist/primitives/alert-dialog.js +1 -1
- package/dist/primitives/autocomplete.js +1 -1
- package/dist/primitives/avatar.js +1 -1
- package/dist/primitives/button.js +1 -1
- package/dist/primitives/checkbox-group.js +1 -1
- package/dist/primitives/checkbox.js +1 -1
- package/dist/primitives/collapsible.js +1 -1
- package/dist/primitives/combobox.js +1 -1
- package/dist/primitives/context-menu.js +1 -1
- package/dist/primitives/csp-provider.js +1 -1
- package/dist/primitives/dialog.js +1 -1
- package/dist/primitives/direction-provider.js +1 -1
- package/dist/primitives/drawer.js +1 -1
- package/dist/primitives/field.js +1 -1
- package/dist/primitives/fieldset.js +1 -1
- package/dist/primitives/form.js +1 -1
- package/dist/primitives/input.js +1 -1
- package/dist/primitives/menu.js +1 -1
- package/dist/primitives/menubar.js +1 -1
- package/dist/primitives/meter.js +1 -1
- package/dist/primitives/navigation-menu.js +1 -1
- package/dist/primitives/number-field.js +1 -1
- package/dist/primitives/popover.js +1 -1
- package/dist/primitives/preview-card.js +1 -1
- package/dist/primitives/progress.js +1 -1
- package/dist/primitives/radio-group.js +1 -1
- package/dist/primitives/radio.js +1 -1
- package/dist/primitives/scroll-area.js +1 -1
- package/dist/primitives/select.js +1 -1
- package/dist/primitives/separator.js +1 -1
- package/dist/primitives/slider.js +1 -1
- package/dist/primitives/switch.js +1 -1
- package/dist/primitives/tabs.js +1 -1
- package/dist/primitives/toast.js +1 -1
- package/dist/primitives/toggle-group.js +1 -1
- package/dist/primitives/toggle.js +1 -1
- package/dist/primitives/toolbar.js +1 -1
- package/dist/primitives/tooltip.js +1 -1
- package/dist/primitives.js +1 -1
- package/dist/{radio-DZ1uS-zK.js → radio-BQTXNBkS.js} +6 -6
- package/dist/radio-BQTXNBkS.js.map +1 -0
- package/dist/scripts/theme-generator/config.js +1 -1
- package/dist/scripts/theme-generator/config.js.map +1 -1
- package/dist/scripts/theme-generator/generate-css.d.ts.map +1 -1
- package/dist/select-BWUNPPHQ.js +123 -0
- package/dist/select-BWUNPPHQ.js.map +1 -0
- package/dist/{sensitive-input-CI-gtdfw.js → sensitive-input-A6Kw7URa.js} +4 -4
- package/dist/{sensitive-input-CI-gtdfw.js.map → sensitive-input-A6Kw7URa.js.map} +1 -1
- package/dist/src/code/code-highlighted.d.ts.map +1 -1
- package/dist/src/components/collapsible/collapsible.d.ts.map +1 -1
- package/dist/src/components/dropdown/dropdown.d.ts.map +1 -1
- package/dist/src/components/flow/connectors.d.ts +4 -0
- package/dist/src/components/flow/connectors.d.ts.map +1 -1
- package/dist/src/components/flow/diagram.d.ts +27 -2
- package/dist/src/components/flow/diagram.d.ts.map +1 -1
- package/dist/src/components/flow/node.d.ts +6 -1
- package/dist/src/components/flow/node.d.ts.map +1 -1
- package/dist/src/components/flow/parallel.d.ts.map +1 -1
- package/dist/src/components/flow/use-children.d.ts +12 -1
- package/dist/src/components/flow/use-children.d.ts.map +1 -1
- package/dist/src/components/label/label.d.ts.map +1 -1
- package/dist/src/components/link/link.d.ts +2 -2
- package/dist/src/components/link/link.d.ts.map +1 -1
- package/dist/src/components/pagination/pagination.d.ts.map +1 -1
- package/dist/src/components/radio/radio.d.ts.map +1 -1
- package/dist/src/components/select/select.d.ts +29 -6
- package/dist/src/components/select/select.d.ts.map +1 -1
- package/dist/src/components/switch/switch.d.ts.map +1 -1
- package/dist/src/components/tabs/tabs.d.ts +6 -2
- package/dist/src/components/tabs/tabs.d.ts.map +1 -1
- package/dist/src/components/toast/toast.d.ts +1 -0
- package/dist/src/components/toast/toast.d.ts.map +1 -1
- package/dist/src/components/tooltip/tooltip.d.ts.map +1 -1
- package/dist/styles/kumo-binding.css +19 -0
- package/dist/styles/kumo-standalone.css +1 -1
- package/dist/styles/theme-fedramp.css +13 -0
- package/dist/styles/theme-kumo.css +77 -1
- package/dist/{switch-BxnAwAse.js → switch-CmUFBiJv.js} +4 -4
- package/dist/switch-CmUFBiJv.js.map +1 -0
- package/dist/{table-CdcsAm5X.js → table-CbU4Oe3o.js} +2 -2
- package/dist/{table-CdcsAm5X.js.map → table-CbU4Oe3o.js.map} +1 -1
- package/dist/{tabs-Cf12PXHz.js → tabs-uLzHh6SR.js} +14 -13
- package/dist/tabs-uLzHh6SR.js.map +1 -0
- package/dist/{toast-BzvG5cpW.js → toast-B-d56fkl.js} +124 -92
- package/dist/toast-B-d56fkl.js.map +1 -0
- package/dist/{tooltip-2KqOpTj0.js → tooltip-C7p2iJ0y.js} +24 -18
- package/dist/tooltip-C7p2iJ0y.js.map +1 -0
- package/dist/{vendor-base-ui-DvXlzG7n.js → vendor-base-ui-DN1j_aJS.js} +50 -49
- package/dist/{vendor-base-ui-DvXlzG7n.js.map → vendor-base-ui-DN1j_aJS.js.map} +1 -1
- package/package.json +3 -1
- package/scripts/theme-generator/config.ts +1 -1
- package/scripts/theme-generator/generate-css.test.ts +30 -0
- package/scripts/theme-generator/generate-css.ts +104 -6
- package/dist/checkbox-z5gO1lL8.js +0 -224
- package/dist/checkbox-z5gO1lL8.js.map +0 -1
- package/dist/collapsible-OBNkTO48.js.map +0 -1
- package/dist/combobox-CJqgoue6.js.map +0 -1
- package/dist/dropdown-BXg01-8j.js.map +0 -1
- package/dist/label-ByOtGj7z.js +0 -58
- package/dist/label-ByOtGj7z.js.map +0 -1
- package/dist/link-CfCaX9Ks.js.map +0 -1
- package/dist/pagination-CaHm6TKa.js.map +0 -1
- package/dist/radio-DZ1uS-zK.js.map +0 -1
- package/dist/select-BXZAlFAV.js +0 -113
- package/dist/select-BXZAlFAV.js.map +0 -1
- package/dist/switch-BxnAwAse.js.map +0 -1
- package/dist/tabs-Cf12PXHz.js.map +0 -1
- package/dist/toast-BzvG5cpW.js.map +0 -1
- package/dist/tooltip-2KqOpTj0.js.map +0 -1
package/dist/code.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code.js","sources":["../src/code/context.ts","../src/code/provider.tsx","../src/code/use-shiki-highlighter.ts","../src/code/code-highlighted.tsx"],"sourcesContent":["import { createContext } from \"react\";\nimport type { Highlighter } from \"shiki\";\nimport type { BundledLanguage, CodeHighlightedLabels } from \"./types\";\n\nexport interface ShikiContextValue {\n /** The initialized Shiki highlighter instance */\n highlighter: Highlighter | null;\n\n /** True while Shiki is loading */\n isLoading: boolean;\n\n /** Error if initialization failed */\n error: Error | null;\n\n /** Configured languages */\n languages: BundledLanguage[];\n\n /** Localized labels for UI elements */\n labels: CodeHighlightedLabels;\n}\n\nexport const ShikiContext = createContext<ShikiContextValue | null>(null);\n","\"use client\";\n\nimport { useState, useEffect, useMemo, type ReactNode } from \"react\";\nimport { ShikiContext, type ShikiContextValue } from \"./context\";\nimport type { ShikiProviderProps, BundledLanguage } from \"./types\";\n\n/**\n * Provider component that initializes and manages Shiki highlighting.\n *\n * Shiki is lazy-loaded on first render — no JavaScript is downloaded\n * until this provider mounts. While loading, child components can\n * render code as plain text.\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * import { ShikiProvider, CodeHighlighted } from \"@cloudflare/kumo/code\";\n *\n * function App() {\n * return (\n * <ShikiProvider\n * engine=\"javascript\"\n * languages={['tsx', 'bash', 'json']}\n * >\n * <CodeHighlighted code=\"const x = 1;\" lang=\"tsx\" />\n * </ShikiProvider>\n * );\n * }\n * ```\n */\nconst DEFAULT_LABELS = {\n copy: \"Copy\",\n copied: \"Copied!\",\n};\n\nexport function ShikiProvider({\n engine,\n languages,\n labels,\n children,\n}: ShikiProviderProps): ReactNode {\n const [state, setState] = useState<{\n highlighter: ShikiContextValue[\"highlighter\"];\n isLoading: boolean;\n error: Error | null;\n }>({\n highlighter: null,\n isLoading: true,\n error: null,\n });\n\n useEffect(() => {\n let cancelled = false;\n\n async function initializeShiki() {\n try {\n // Dynamic import — Shiki is only loaded when this effect runs\n const { createHighlighter } = await import(\"shiki\");\n\n // Load the appropriate engine\n const engineInstance =\n engine === \"wasm\"\n ? await import(\"shiki/engine/oniguruma\").then((m) =>\n m.createOnigurumaEngine(import(\"shiki/wasm\")),\n )\n : await import(\"shiki/engine/javascript\").then((m) =>\n m.createJavaScriptRegexEngine(),\n );\n\n const highlighter = await createHighlighter({\n themes: [\"github-light\", \"vesper\"],\n langs: languages,\n engine: engineInstance,\n });\n\n if (!cancelled) {\n setState({\n highlighter,\n isLoading: false,\n error: null,\n });\n }\n } catch (err) {\n if (!cancelled) {\n setState({\n highlighter: null,\n isLoading: false,\n error:\n err instanceof Error ? err : new Error(\"Failed to load Shiki\"),\n });\n }\n }\n }\n\n void initializeShiki();\n\n return () => {\n cancelled = true;\n };\n }, [engine, languages]);\n\n const mergedLabels = useMemo(\n () => ({ ...DEFAULT_LABELS, ...labels }),\n [labels],\n );\n\n const contextValue = useMemo<ShikiContextValue>(\n () => ({\n highlighter: state.highlighter,\n isLoading: state.isLoading,\n error: state.error,\n languages: languages as BundledLanguage[],\n labels: mergedLabels,\n }),\n [state.highlighter, state.isLoading, state.error, languages, mergedLabels],\n );\n\n return (\n <ShikiContext.Provider value={contextValue}>\n {children}\n </ShikiContext.Provider>\n );\n}\n\nShikiProvider.displayName = \"ShikiProvider\";\n","\"use client\";\n\nimport { useContext, useCallback } from \"react\";\nimport { ShikiContext } from \"./context\";\nimport type { UseShikiHighlighterResult, BundledLanguage } from \"./types\";\n\n/**\n * Hook for accessing Shiki highlighting in custom implementations.\n *\n * Must be used within a ShikiProvider.\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * import { useShikiHighlighter } from \"@cloudflare/kumo/code\";\n *\n * function CustomCodeBlock({ code, lang }) {\n * const { highlight, isLoading, isReady, error } = useShikiHighlighter();\n *\n * if (error) {\n * return <div>Failed to load highlighter</div>;\n * }\n *\n * if (isLoading) {\n * return <pre><code>{code}</code></pre>;\n * }\n *\n * const html = highlight(code, lang);\n *\n * // null means highlighting failed — render plain text\n * if (html === null) {\n * return <pre><code>{code}</code></pre>;\n * }\n *\n * return <pre dangerouslySetInnerHTML={{ __html: html }} />;\n * }\n * ```\n */\nexport function useShikiHighlighter(): UseShikiHighlighterResult {\n const context = useContext(ShikiContext);\n\n if (!context) {\n throw new Error(\n \"useShikiHighlighter must be used within a ShikiProvider. \" +\n \"Wrap your app with <ShikiProvider> from '@cloudflare/kumo/code'.\",\n );\n }\n\n const { highlighter, isLoading, error, languages, labels } = context;\n\n const highlight = useCallback(\n (code: string, lang: BundledLanguage): string | null => {\n if (!highlighter) {\n return null;\n }\n\n // Check if the language is supported\n if (!languages.includes(lang)) {\n console.warn(\n `[Kumo CodeHighlighted] Language \"${lang}\" is not in the ShikiProvider's languages list. ` +\n `Add it to the languages array: languages={[...existing, '${lang}']}. ` +\n `Rendering as plain text.`,\n );\n return null;\n }\n\n try {\n // Use dual theme for light/dark mode support with hardcoded themes\n const html = highlighter.codeToHtml(code, {\n lang,\n themes: {\n light: \"github-light\",\n dark: \"vesper\",\n },\n });\n\n return html;\n } catch (err) {\n console.warn(\n `[Kumo CodeHighlighted] Failed to highlight code with language \"${lang}\":`,\n err,\n );\n return null;\n }\n },\n [highlighter, languages],\n );\n\n return {\n highlight,\n isLoading,\n isReady: !isLoading && highlighter !== null,\n error,\n labels,\n };\n}\n","\"use client\";\n\nimport { useState, useCallback, useMemo, type ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Button } from \"../components/button\";\nimport { useShikiHighlighter } from \"./use-shiki-highlighter\";\nimport type { CodeHighlightedProps } from \"./types\";\n\n/**\n * Syntax-highlighted code block powered by Shiki.\n *\n * Must be used within a ShikiProvider. While Shiki is loading,\n * displays code as plain text (no layout shift, immediately readable).\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * import { ShikiProvider, CodeHighlighted } from \"@cloudflare/kumo/code\";\n *\n * <ShikiProvider\n * engine=\"javascript\"\n * languages={['tsx', 'bash']}\n * >\n * <CodeHighlighted\n * code={`const greeting = \"Hello!\";`}\n * lang=\"tsx\"\n * showLineNumbers\n * showCopyButton\n * />\n * </ShikiProvider>\n * ```\n */\nexport function CodeHighlighted({\n code,\n lang,\n showLineNumbers = false,\n highlightLines,\n showCopyButton = false,\n labels: labelOverrides,\n className,\n}: CodeHighlightedProps): ReactNode {\n const {\n highlight,\n isLoading,\n error,\n labels: providerLabels,\n } = useShikiHighlighter();\n const [copied, setCopied] = useState(false);\n\n // Merge provider labels with component-level overrides\n const labels = useMemo(\n () => ({ ...providerLabels, ...labelOverrides }),\n [providerLabels, labelOverrides],\n );\n\n const handleCopy = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (err) {\n console.error(\"[Kumo CodeHighlighted] Failed to copy to clipboard:\", err);\n }\n }, [code]);\n\n // Get highlighted HTML (or null if not ready/failed)\n const html = highlight(code, lang);\n\n // Count lines for line numbers\n const lineCount = useMemo(() => code.split(\"\\n\").length, [code]);\n\n // Detect single-line code for layout adjustments\n const isSingleLine = lineCount === 1;\n\n // Container styles - use flex layout for single-line with copy button\n const containerClasses = cn(\n \"group relative w-full min-w-0 rounded-md border border-kumo-fill bg-kumo-base\",\n showCopyButton && isSingleLine && \"flex items-center\",\n className,\n );\n\n // Copy button - inline for single-line, absolute for multi-line\n // Hidden until hover (or when showing \"Copied!\" feedback)\n const copyButton = showCopyButton ? (\n <div\n className={cn(\n isSingleLine ? \"shrink-0 px-2\" : \"absolute right-2 top-2\",\n !copied && \"opacity-0 transition-opacity group-hover:opacity-100\",\n )}\n >\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={handleCopy}\n aria-label={copied ? labels.copied : labels.copy}\n >\n {copied ? labels.copied : labels.copy}\n </Button>\n </div>\n ) : null;\n\n // Line numbers column\n const lineNumbers =\n showLineNumbers && !isSingleLine ? (\n <div\n className=\"kumo-line-numbers shrink-0 select-none py-4 pr-4 text-right font-mono text-sm opacity-40\"\n aria-hidden=\"true\"\n >\n {Array.from({ length: lineCount }, (_, i) => (\n <div key={i + 1} className=\"leading-relaxed\">\n {i + 1}\n </div>\n ))}\n </div>\n ) : null;\n\n // Error state — still show code, just log the error\n if (error) {\n console.error(\"[Kumo CodeHighlighted] Shiki initialization error:\", error);\n }\n\n // Loading or failed to highlight — show plain text\n if (isLoading || html === null) {\n return (\n <div className={containerClasses}>\n {lineNumbers && (\n <div className=\"flex\">\n {lineNumbers}\n <pre className=\"min-w-0 flex-1 overflow-x-auto p-4 font-mono text-sm leading-relaxed text-kumo-strong\">\n <code>{code}</code>\n </pre>\n </div>\n )}\n {!lineNumbers && (\n <pre className=\"min-w-0 flex-1 overflow-x-auto p-4 font-mono text-sm leading-relaxed text-kumo-strong\">\n <code>{code}</code>\n </pre>\n )}\n {copyButton}\n </div>\n );\n }\n\n // Highlighted code\n return (\n <div className={containerClasses}>\n {lineNumbers && (\n <div className=\"flex w-full\">\n {lineNumbers}\n <div className=\"min-w-0 flex-1 overflow-x-auto\">\n <div\n className=\"kumo-shiki [&>pre]:p-4 [&>pre]:font-mono [&>pre]:text-sm [&>pre]:leading-relaxed\"\n dangerouslySetInnerHTML={{\n __html: processHighlightedHtml(html, highlightLines),\n }}\n />\n </div>\n </div>\n )}\n {!lineNumbers && (\n <div className=\"overflow-x-auto\">\n <div\n className=\"kumo-shiki [&>pre]:p-4 [&>pre]:font-mono [&>pre]:text-sm [&>pre]:leading-relaxed\"\n dangerouslySetInnerHTML={{\n __html: processHighlightedHtml(html, highlightLines),\n }}\n />\n </div>\n )}\n {copyButton}\n </div>\n );\n}\n\nCodeHighlighted.displayName = \"CodeHighlighted\";\n\n/**\n * Process Shiki's HTML output to add line highlighting classes.\n * Does NOT modify Shiki's token structure - only adds classes to line spans.\n */\nfunction processHighlightedHtml(\n html: string,\n highlightLines?: number[],\n): string {\n // Line numbers are not yet supported - would require more complex approach\n // For now, only handle line highlighting which just adds a class\n\n if (!highlightLines?.length) {\n return html;\n }\n\n const highlightSet = new Set(highlightLines);\n let lineNumber = 0;\n\n // Only add the highlight class to lines, don't restructure the HTML\n return html.replace(/<span class=\"line\">/g, () => {\n lineNumber++;\n const isHighlighted = highlightSet.has(lineNumber);\n return isHighlighted\n ? '<span class=\"line line-highlighted\">'\n : '<span class=\"line\">';\n });\n}\n"],"names":["ShikiContext","createContext","DEFAULT_LABELS","ShikiProvider","engine","languages","labels","children","state","setState","useState","useEffect","cancelled","initializeShiki","createHighlighter","engineInstance","n","m","highlighter","err","mergedLabels","useMemo","contextValue","useShikiHighlighter","context","useContext","isLoading","error","useCallback","code","lang","CodeHighlighted","showLineNumbers","highlightLines","showCopyButton","labelOverrides","className","highlight","providerLabels","copied","setCopied","handleCopy","html","lineCount","isSingleLine","containerClasses","cn","copyButton","jsx","Button","lineNumbers","_","i","jsxs","processHighlightedHtml","highlightSet","lineNumber"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"code.js","sources":["../src/code/context.ts","../src/code/provider.tsx","../src/code/use-shiki-highlighter.ts","../src/code/code-highlighted.tsx"],"sourcesContent":["import { createContext } from \"react\";\nimport type { Highlighter } from \"shiki\";\nimport type { BundledLanguage, CodeHighlightedLabels } from \"./types\";\n\nexport interface ShikiContextValue {\n /** The initialized Shiki highlighter instance */\n highlighter: Highlighter | null;\n\n /** True while Shiki is loading */\n isLoading: boolean;\n\n /** Error if initialization failed */\n error: Error | null;\n\n /** Configured languages */\n languages: BundledLanguage[];\n\n /** Localized labels for UI elements */\n labels: CodeHighlightedLabels;\n}\n\nexport const ShikiContext = createContext<ShikiContextValue | null>(null);\n","\"use client\";\n\nimport { useState, useEffect, useMemo, type ReactNode } from \"react\";\nimport { ShikiContext, type ShikiContextValue } from \"./context\";\nimport type { ShikiProviderProps, BundledLanguage } from \"./types\";\n\n/**\n * Provider component that initializes and manages Shiki highlighting.\n *\n * Shiki is lazy-loaded on first render — no JavaScript is downloaded\n * until this provider mounts. While loading, child components can\n * render code as plain text.\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * import { ShikiProvider, CodeHighlighted } from \"@cloudflare/kumo/code\";\n *\n * function App() {\n * return (\n * <ShikiProvider\n * engine=\"javascript\"\n * languages={['tsx', 'bash', 'json']}\n * >\n * <CodeHighlighted code=\"const x = 1;\" lang=\"tsx\" />\n * </ShikiProvider>\n * );\n * }\n * ```\n */\nconst DEFAULT_LABELS = {\n copy: \"Copy\",\n copied: \"Copied!\",\n};\n\nexport function ShikiProvider({\n engine,\n languages,\n labels,\n children,\n}: ShikiProviderProps): ReactNode {\n const [state, setState] = useState<{\n highlighter: ShikiContextValue[\"highlighter\"];\n isLoading: boolean;\n error: Error | null;\n }>({\n highlighter: null,\n isLoading: true,\n error: null,\n });\n\n useEffect(() => {\n let cancelled = false;\n\n async function initializeShiki() {\n try {\n // Dynamic import — Shiki is only loaded when this effect runs\n const { createHighlighter } = await import(\"shiki\");\n\n // Load the appropriate engine\n const engineInstance =\n engine === \"wasm\"\n ? await import(\"shiki/engine/oniguruma\").then((m) =>\n m.createOnigurumaEngine(import(\"shiki/wasm\")),\n )\n : await import(\"shiki/engine/javascript\").then((m) =>\n m.createJavaScriptRegexEngine(),\n );\n\n const highlighter = await createHighlighter({\n themes: [\"github-light\", \"vesper\"],\n langs: languages,\n engine: engineInstance,\n });\n\n if (!cancelled) {\n setState({\n highlighter,\n isLoading: false,\n error: null,\n });\n }\n } catch (err) {\n if (!cancelled) {\n setState({\n highlighter: null,\n isLoading: false,\n error:\n err instanceof Error ? err : new Error(\"Failed to load Shiki\"),\n });\n }\n }\n }\n\n void initializeShiki();\n\n return () => {\n cancelled = true;\n };\n }, [engine, languages]);\n\n const mergedLabels = useMemo(\n () => ({ ...DEFAULT_LABELS, ...labels }),\n [labels],\n );\n\n const contextValue = useMemo<ShikiContextValue>(\n () => ({\n highlighter: state.highlighter,\n isLoading: state.isLoading,\n error: state.error,\n languages: languages as BundledLanguage[],\n labels: mergedLabels,\n }),\n [state.highlighter, state.isLoading, state.error, languages, mergedLabels],\n );\n\n return (\n <ShikiContext.Provider value={contextValue}>\n {children}\n </ShikiContext.Provider>\n );\n}\n\nShikiProvider.displayName = \"ShikiProvider\";\n","\"use client\";\n\nimport { useContext, useCallback } from \"react\";\nimport { ShikiContext } from \"./context\";\nimport type { UseShikiHighlighterResult, BundledLanguage } from \"./types\";\n\n/**\n * Hook for accessing Shiki highlighting in custom implementations.\n *\n * Must be used within a ShikiProvider.\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * import { useShikiHighlighter } from \"@cloudflare/kumo/code\";\n *\n * function CustomCodeBlock({ code, lang }) {\n * const { highlight, isLoading, isReady, error } = useShikiHighlighter();\n *\n * if (error) {\n * return <div>Failed to load highlighter</div>;\n * }\n *\n * if (isLoading) {\n * return <pre><code>{code}</code></pre>;\n * }\n *\n * const html = highlight(code, lang);\n *\n * // null means highlighting failed — render plain text\n * if (html === null) {\n * return <pre><code>{code}</code></pre>;\n * }\n *\n * return <pre dangerouslySetInnerHTML={{ __html: html }} />;\n * }\n * ```\n */\nexport function useShikiHighlighter(): UseShikiHighlighterResult {\n const context = useContext(ShikiContext);\n\n if (!context) {\n throw new Error(\n \"useShikiHighlighter must be used within a ShikiProvider. \" +\n \"Wrap your app with <ShikiProvider> from '@cloudflare/kumo/code'.\",\n );\n }\n\n const { highlighter, isLoading, error, languages, labels } = context;\n\n const highlight = useCallback(\n (code: string, lang: BundledLanguage): string | null => {\n if (!highlighter) {\n return null;\n }\n\n // Check if the language is supported\n if (!languages.includes(lang)) {\n console.warn(\n `[Kumo CodeHighlighted] Language \"${lang}\" is not in the ShikiProvider's languages list. ` +\n `Add it to the languages array: languages={[...existing, '${lang}']}. ` +\n `Rendering as plain text.`,\n );\n return null;\n }\n\n try {\n // Use dual theme for light/dark mode support with hardcoded themes\n const html = highlighter.codeToHtml(code, {\n lang,\n themes: {\n light: \"github-light\",\n dark: \"vesper\",\n },\n });\n\n return html;\n } catch (err) {\n console.warn(\n `[Kumo CodeHighlighted] Failed to highlight code with language \"${lang}\":`,\n err,\n );\n return null;\n }\n },\n [highlighter, languages],\n );\n\n return {\n highlight,\n isLoading,\n isReady: !isLoading && highlighter !== null,\n error,\n labels,\n };\n}\n","\"use client\";\n\nimport { useState, useCallback, useMemo, type ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Button } from \"../components/button\";\nimport { useShikiHighlighter } from \"./use-shiki-highlighter\";\nimport type { CodeHighlightedProps } from \"./types\";\n\n/**\n * Syntax-highlighted code block powered by Shiki.\n *\n * Must be used within a ShikiProvider. While Shiki is loading,\n * displays code as plain text (no layout shift, immediately readable).\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * import { ShikiProvider, CodeHighlighted } from \"@cloudflare/kumo/code\";\n *\n * <ShikiProvider\n * engine=\"javascript\"\n * languages={['tsx', 'bash']}\n * >\n * <CodeHighlighted\n * code={`const greeting = \"Hello!\";`}\n * lang=\"tsx\"\n * showLineNumbers\n * showCopyButton\n * />\n * </ShikiProvider>\n * ```\n */\nexport function CodeHighlighted({\n code,\n lang,\n showLineNumbers = false,\n highlightLines,\n showCopyButton = false,\n labels: labelOverrides,\n className,\n}: CodeHighlightedProps): ReactNode {\n const {\n highlight,\n isLoading,\n error,\n labels: providerLabels,\n } = useShikiHighlighter();\n const [copied, setCopied] = useState(false);\n\n // Merge provider labels with component-level overrides\n const labels = useMemo(\n () => ({ ...providerLabels, ...labelOverrides }),\n [providerLabels, labelOverrides],\n );\n\n const handleCopy = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (err) {\n console.error(\"[Kumo CodeHighlighted] Failed to copy to clipboard:\", err);\n }\n }, [code]);\n\n // Get highlighted HTML (or null if not ready/failed)\n const html = highlight(code, lang);\n\n // Count lines for line numbers\n const lineCount = useMemo(() => code.split(\"\\n\").length, [code]);\n\n // Detect single-line code for layout adjustments\n const isSingleLine = lineCount === 1;\n\n // Container styles - use flex layout for single-line with copy button\n // Includes defensive resets (m-0, p-0) to prevent global CSS pollution\n const containerClasses = cn(\n \"group relative m-0 w-full min-w-0 rounded-md border border-kumo-fill bg-kumo-base p-0\",\n showCopyButton && isSingleLine && \"flex items-center\",\n className,\n );\n\n // Copy button - inline for single-line, absolute for multi-line\n // Hidden until hover (or when showing \"Copied!\" feedback)\n const copyButton = showCopyButton ? (\n <div\n className={cn(\n isSingleLine ? \"shrink-0 px-2\" : \"absolute right-2 top-2\",\n !copied && \"opacity-0 transition-opacity group-hover:opacity-100\",\n )}\n >\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={handleCopy}\n aria-label={copied ? labels.copied : labels.copy}\n >\n {copied ? labels.copied : labels.copy}\n </Button>\n </div>\n ) : null;\n\n // Line numbers column\n const lineNumbers =\n showLineNumbers && !isSingleLine ? (\n <div\n className=\"kumo-line-numbers shrink-0 select-none py-4 pr-4 text-right font-mono text-sm opacity-40\"\n aria-hidden=\"true\"\n >\n {Array.from({ length: lineCount }, (_, i) => (\n <div key={i + 1} className=\"leading-relaxed\">\n {i + 1}\n </div>\n ))}\n </div>\n ) : null;\n\n // Error state — still show code, just log the error\n if (error) {\n console.error(\"[Kumo CodeHighlighted] Shiki initialization error:\", error);\n }\n\n // Loading or failed to highlight — show plain text\n if (isLoading || html === null) {\n return (\n <div className={containerClasses}>\n {lineNumbers && (\n <div className=\"flex\">\n {lineNumbers}\n <pre className=\"!m-0 min-w-0 flex-1 overflow-x-auto !p-4 font-mono text-sm leading-relaxed text-kumo-strong\">\n <code className=\"!m-0 !p-0\">{code}</code>\n </pre>\n </div>\n )}\n {!lineNumbers && (\n <pre className=\"!m-0 min-w-0 flex-1 overflow-x-auto !p-4 font-mono text-sm leading-relaxed text-kumo-strong\">\n <code className=\"!m-0 !p-0\">{code}</code>\n </pre>\n )}\n {copyButton}\n </div>\n );\n }\n\n // Highlighted code\n return (\n <div className={containerClasses}>\n {lineNumbers && (\n <div className=\"flex w-full\">\n {lineNumbers}\n <div className=\"min-w-0 flex-1 overflow-x-auto\">\n <div\n className=\"kumo-shiki [&>pre]:!m-0 [&>pre]:!border-0 [&>pre]:!rounded-none [&>pre]:!bg-transparent [&>pre]:!p-4 [&>pre]:font-mono [&>pre]:text-sm [&>pre]:leading-relaxed [&_code]:!m-0 [&_code]:!p-0 [&_code]:!bg-transparent [&_code]:!border-0\"\n dangerouslySetInnerHTML={{\n __html: processHighlightedHtml(html, highlightLines),\n }}\n />\n </div>\n </div>\n )}\n {!lineNumbers && (\n <div className=\"overflow-x-auto\">\n <div\n className=\"kumo-shiki [&>pre]:!m-0 [&>pre]:!border-0 [&>pre]:!rounded-none [&>pre]:!bg-transparent [&>pre]:!p-4 [&>pre]:font-mono [&>pre]:text-sm [&>pre]:leading-relaxed [&_code]:!m-0 [&_code]:!p-0 [&_code]:!bg-transparent [&_code]:!border-0\"\n dangerouslySetInnerHTML={{\n __html: processHighlightedHtml(html, highlightLines),\n }}\n />\n </div>\n )}\n {copyButton}\n </div>\n );\n}\n\nCodeHighlighted.displayName = \"CodeHighlighted\";\n\n/**\n * Process Shiki's HTML output to add line highlighting classes.\n * Does NOT modify Shiki's token structure - only adds classes to line spans.\n */\nfunction processHighlightedHtml(\n html: string,\n highlightLines?: number[],\n): string {\n // Line numbers are not yet supported - would require more complex approach\n // For now, only handle line highlighting which just adds a class\n\n if (!highlightLines?.length) {\n return html;\n }\n\n const highlightSet = new Set(highlightLines);\n let lineNumber = 0;\n\n // Only add the highlight class to lines, don't restructure the HTML\n return html.replace(/<span class=\"line\">/g, () => {\n lineNumber++;\n const isHighlighted = highlightSet.has(lineNumber);\n return isHighlighted\n ? '<span class=\"line line-highlighted\">'\n : '<span class=\"line\">';\n });\n}\n"],"names":["ShikiContext","createContext","DEFAULT_LABELS","ShikiProvider","engine","languages","labels","children","state","setState","useState","useEffect","cancelled","initializeShiki","createHighlighter","engineInstance","m","highlighter","err","mergedLabels","useMemo","contextValue","useShikiHighlighter","context","useContext","isLoading","error","useCallback","code","lang","CodeHighlighted","showLineNumbers","highlightLines","showCopyButton","labelOverrides","className","highlight","providerLabels","copied","setCopied","handleCopy","html","lineCount","isSingleLine","containerClasses","cn","copyButton","jsx","Button","lineNumbers","_","i","jsxs","processHighlightedHtml","highlightSet","lineNumber"],"mappings":"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"}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsxs as a, jsx as
|
|
2
|
+
import { jsxs as a, jsx as n } from "react/jsx-runtime";
|
|
3
3
|
import { CaretDownIcon as d } from "@phosphor-icons/react";
|
|
4
|
-
import { forwardRef as p, useId as u, useCallback as
|
|
4
|
+
import { forwardRef as p, useId as u, useCallback as b } from "react";
|
|
5
5
|
import { c as t } from "./cn-Bhsu1vx2.js";
|
|
6
|
-
function
|
|
6
|
+
function f(e = {}) {
|
|
7
7
|
return t(
|
|
8
|
+
// Defensive resets to prevent global button styles from polluting the trigger
|
|
9
|
+
"bg-transparent border-none shadow-none p-0 m-0",
|
|
8
10
|
// Base styles for the trigger
|
|
9
11
|
"flex cursor-pointer items-center gap-1 text-sm text-kumo-link select-none"
|
|
10
12
|
);
|
|
11
13
|
}
|
|
12
14
|
const x = p(
|
|
13
|
-
({ label: e, open: r, onOpenChange: o, children:
|
|
14
|
-
const s = u(), m =
|
|
15
|
+
({ label: e, open: r, onOpenChange: o, children: l, className: i }, c) => {
|
|
16
|
+
const s = u(), m = b(() => {
|
|
15
17
|
o?.(!r);
|
|
16
18
|
}, [r, o]);
|
|
17
19
|
return /* @__PURE__ */ a("div", { ref: c, children: [
|
|
@@ -21,12 +23,12 @@ const x = p(
|
|
|
21
23
|
type: "button",
|
|
22
24
|
"aria-expanded": r,
|
|
23
25
|
"aria-controls": s,
|
|
24
|
-
className:
|
|
26
|
+
className: f(),
|
|
25
27
|
onClick: m,
|
|
26
28
|
children: [
|
|
27
29
|
e,
|
|
28
30
|
" ",
|
|
29
|
-
/* @__PURE__ */
|
|
31
|
+
/* @__PURE__ */ n(
|
|
30
32
|
d,
|
|
31
33
|
{
|
|
32
34
|
className: t("h-4 w-4 transition-transform", r && "rotate-180")
|
|
@@ -35,15 +37,15 @@ const x = p(
|
|
|
35
37
|
]
|
|
36
38
|
}
|
|
37
39
|
),
|
|
38
|
-
r && /* @__PURE__ */
|
|
40
|
+
r && /* @__PURE__ */ n(
|
|
39
41
|
"div",
|
|
40
42
|
{
|
|
41
43
|
id: s,
|
|
42
44
|
className: t(
|
|
43
45
|
"my-2 space-y-4 border-l-2 border-kumo-fill pl-4",
|
|
44
|
-
|
|
46
|
+
i
|
|
45
47
|
),
|
|
46
|
-
children:
|
|
48
|
+
children: l
|
|
47
49
|
}
|
|
48
50
|
)
|
|
49
51
|
] });
|
|
@@ -53,4 +55,4 @@ x.displayName = "Collapsible";
|
|
|
53
55
|
export {
|
|
54
56
|
x as C
|
|
55
57
|
};
|
|
56
|
-
//# sourceMappingURL=collapsible-
|
|
58
|
+
//# sourceMappingURL=collapsible-C3LJ1dfZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collapsible-C3LJ1dfZ.js","sources":["../src/components/collapsible/collapsible.tsx"],"sourcesContent":["import { CaretDownIcon } from \"@phosphor-icons/react\";\nimport { type PropsWithChildren, forwardRef, useCallback, useId } from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport const KUMO_COLLAPSIBLE_VARIANTS = {} as const;\n\nexport const KUMO_COLLAPSIBLE_DEFAULT_VARIANTS = {} as const;\n\nexport interface KumoCollapsibleVariantsProps {}\n\nexport function collapsibleVariants(_props: KumoCollapsibleVariantsProps = {}) {\n return cn(\n // Defensive resets to prevent global button styles from polluting the trigger\n \"bg-transparent border-none shadow-none p-0 m-0\",\n // Base styles for the trigger\n \"flex cursor-pointer items-center gap-1 text-sm text-kumo-link select-none\",\n );\n}\n\n/**\n * Collapsible component props.\n *\n * @example\n * ```tsx\n * <Collapsible label=\"Show details\" open={open} onOpenChange={setOpen}>\n * <Text>Hidden content revealed when expanded.</Text>\n * </Collapsible>\n * ```\n */\nexport type CollapsibleProps = PropsWithChildren<\n KumoCollapsibleVariantsProps & {\n /** Text label displayed in the trigger button */\n label: string;\n /** Whether the collapsible content is visible */\n open?: boolean;\n /** Callback fired when the open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Additional CSS classes for the content panel */\n className?: string;\n }\n>;\n\n/**\n * Collapsible component for showing/hiding content.\n *\n * Features:\n * - Animated chevron indicator (rotates 180° when open)\n * - Accessible with aria-expanded and aria-controls\n * - Content panel with left border accent\n *\n * @example\n * ```tsx\n * const [open, setOpen] = useState(false);\n *\n * <Collapsible label=\"Show details\" open={open} onOpenChange={setOpen}>\n * <Text>Hidden content revealed when expanded.</Text>\n * </Collapsible>\n * ```\n *\n * @example Controlled accordion pattern\n * ```tsx\n * const [activeIndex, setActiveIndex] = useState<number | null>(null);\n *\n * {items.map((item, i) => (\n * <Collapsible\n * key={i}\n * label={item.title}\n * open={activeIndex === i}\n * onOpenChange={(open) => setActiveIndex(open ? i : null)}\n * >\n * {item.content}\n * </Collapsible>\n * ))}\n * ```\n */\nexport const Collapsible = forwardRef<HTMLDivElement, CollapsibleProps>(\n ({ label, open, onOpenChange, children, className }, ref) => {\n const contentId = useId();\n\n const handleOpen = useCallback(() => {\n onOpenChange?.(!open);\n }, [open, onOpenChange]);\n\n return (\n <div ref={ref}>\n <button\n type=\"button\"\n aria-expanded={open}\n aria-controls={contentId}\n className={collapsibleVariants()}\n onClick={handleOpen}\n >\n {label}{\" \"}\n <CaretDownIcon\n className={cn(\"h-4 w-4 transition-transform\", open && \"rotate-180\")}\n />\n </button>\n {open && (\n <div\n id={contentId}\n className={cn(\n \"my-2 space-y-4 border-l-2 border-kumo-fill pl-4\",\n className,\n )}\n >\n {children}\n </div>\n )}\n </div>\n );\n },\n);\n\nCollapsible.displayName = \"Collapsible\";\n"],"names":["collapsibleVariants","_props","cn","Collapsible","forwardRef","label","open","onOpenChange","children","className","ref","contentId","useId","handleOpen","useCallback","jsxs","jsx","CaretDownIcon"],"mappings":";;;;;AAUO,SAASA,EAAoBC,IAAuC,IAAI;AAC7E,SAAOC;AAAA;AAAA,IAEL;AAAA;AAAA,IAEA;AAAA,EAAA;AAEJ;AA0DO,MAAMC,IAAcC;AAAA,EACzB,CAAC,EAAE,OAAAC,GAAO,MAAAC,GAAM,cAAAC,GAAc,UAAAC,GAAU,WAAAC,EAAA,GAAaC,MAAQ;AAC3D,UAAMC,IAAYC,EAAA,GAEZC,IAAaC,EAAY,MAAM;AACnC,MAAAP,IAAe,CAACD,CAAI;AAAA,IACtB,GAAG,CAACA,GAAMC,CAAY,CAAC;AAEvB,WACE,gBAAAQ,EAAC,SAAI,KAAAL,GACH,UAAA;AAAA,MAAA,gBAAAK;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,iBAAeT;AAAA,UACf,iBAAeK;AAAA,UACf,WAAWX,EAAA;AAAA,UACX,SAASa;AAAA,UAER,UAAA;AAAA,YAAAR;AAAA,YAAO;AAAA,YACR,gBAAAW;AAAA,cAACC;AAAA,cAAA;AAAA,gBACC,WAAWf,EAAG,gCAAgCI,KAAQ,YAAY;AAAA,cAAA;AAAA,YAAA;AAAA,UACpE;AAAA,QAAA;AAAA,MAAA;AAAA,MAEDA,KACC,gBAAAU;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,IAAIL;AAAA,UACJ,WAAWT;AAAA,YACT;AAAA,YACAO;AAAA,UAAA;AAAA,UAGD,UAAAD;AAAA,QAAA;AAAA,MAAA;AAAA,IACH,GAEJ;AAAA,EAEJ;AACF;AAEAL,EAAY,cAAc;"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as
|
|
2
|
+
import { jsx as o, jsxs as c } from "react/jsx-runtime";
|
|
3
3
|
import { CheckIcon as w, XIcon as d, CaretDownIcon as x } from "@phosphor-icons/react";
|
|
4
4
|
import { createContext as T, useContext as u, Fragment as V } from "react";
|
|
5
|
-
import { i as b, K as P } from "./input-
|
|
5
|
+
import { i as b, K as P } from "./input-gGpJCiT7.js";
|
|
6
6
|
import { c as a } from "./cn-Bhsu1vx2.js";
|
|
7
|
-
import { F as j } from "./field-
|
|
8
|
-
import { a5 as G, a6 as L, a7 as M, a8 as F, a9 as _, aa as A, ab as p, ac as E, ad as K, ae as O, af as U, ag as W, ah as f, ai as D, aj as C, ak as N, al as H, am as X, an as q } from "./vendor-base-ui-
|
|
7
|
+
import { F as j } from "./field-CQmGKOVZ.js";
|
|
8
|
+
import { a5 as G, a6 as L, a7 as M, a8 as F, a9 as _, aa as A, ab as p, ac as E, ad as K, ae as O, af as U, ag as W, ah as f, ai as D, aj as C, ak as N, al as H, am as X, an as q } from "./vendor-base-ui-DN1j_aJS.js";
|
|
9
9
|
P.size;
|
|
10
10
|
const h = T("base");
|
|
11
11
|
function y({
|
|
12
|
-
label:
|
|
12
|
+
label: e,
|
|
13
13
|
required: i,
|
|
14
14
|
labelTooltip: t,
|
|
15
15
|
description: n,
|
|
@@ -18,11 +18,11 @@ function y({
|
|
|
18
18
|
size: l = "base",
|
|
19
19
|
...m
|
|
20
20
|
}) {
|
|
21
|
-
const g = /* @__PURE__ */
|
|
22
|
-
return
|
|
21
|
+
const g = /* @__PURE__ */ o(h.Provider, { value: l, children: /* @__PURE__ */ o(L, { ...m, children: s }) });
|
|
22
|
+
return e ? /* @__PURE__ */ o(
|
|
23
23
|
j,
|
|
24
24
|
{
|
|
25
|
-
label:
|
|
25
|
+
label: e,
|
|
26
26
|
required: i,
|
|
27
27
|
labelTooltip: t,
|
|
28
28
|
description: n,
|
|
@@ -32,14 +32,14 @@ function y({
|
|
|
32
32
|
) : g;
|
|
33
33
|
}
|
|
34
34
|
function z({
|
|
35
|
-
children:
|
|
35
|
+
children: e,
|
|
36
36
|
className: i,
|
|
37
37
|
align: t = "start",
|
|
38
38
|
sideOffset: n = 4,
|
|
39
39
|
alignOffset: r,
|
|
40
40
|
side: s
|
|
41
41
|
}) {
|
|
42
|
-
return /* @__PURE__ */
|
|
42
|
+
return /* @__PURE__ */ o(H, { children: /* @__PURE__ */ o(
|
|
43
43
|
X,
|
|
44
44
|
{
|
|
45
45
|
className: "outline-none",
|
|
@@ -47,7 +47,7 @@ function z({
|
|
|
47
47
|
sideOffset: n,
|
|
48
48
|
alignOffset: r,
|
|
49
49
|
side: s,
|
|
50
|
-
children: /* @__PURE__ */
|
|
50
|
+
children: /* @__PURE__ */ o(
|
|
51
51
|
q,
|
|
52
52
|
{
|
|
53
53
|
className: a(
|
|
@@ -60,7 +60,7 @@ function z({
|
|
|
60
60
|
// border part
|
|
61
61
|
i
|
|
62
62
|
),
|
|
63
|
-
children:
|
|
63
|
+
children: e
|
|
64
64
|
}
|
|
65
65
|
)
|
|
66
66
|
}
|
|
@@ -73,7 +73,7 @@ const B = {
|
|
|
73
73
|
lg: { padding: "pr-10", iconSize: 18, iconRight: "right-3" }
|
|
74
74
|
};
|
|
75
75
|
function v({
|
|
76
|
-
className:
|
|
76
|
+
className: e,
|
|
77
77
|
...i
|
|
78
78
|
}) {
|
|
79
79
|
const t = u(h), n = B[t];
|
|
@@ -84,18 +84,18 @@ function v({
|
|
|
84
84
|
b({ size: t }),
|
|
85
85
|
"relative flex items-center",
|
|
86
86
|
n.padding,
|
|
87
|
-
|
|
87
|
+
e
|
|
88
88
|
),
|
|
89
89
|
children: [
|
|
90
|
-
/* @__PURE__ */
|
|
91
|
-
/* @__PURE__ */
|
|
90
|
+
/* @__PURE__ */ o(f, { children: i.children }),
|
|
91
|
+
/* @__PURE__ */ o(
|
|
92
92
|
N,
|
|
93
93
|
{
|
|
94
94
|
className: a(
|
|
95
|
-
"absolute top-1/2 -translate-y-1/2",
|
|
95
|
+
"absolute top-1/2 -translate-y-1/2 flex items-center",
|
|
96
96
|
n.iconRight
|
|
97
97
|
),
|
|
98
|
-
children: /* @__PURE__ */
|
|
98
|
+
children: /* @__PURE__ */ o(x, { size: n.iconSize, className: "fill-kumo-ring" })
|
|
99
99
|
}
|
|
100
100
|
)
|
|
101
101
|
]
|
|
@@ -128,38 +128,38 @@ const J = {
|
|
|
128
128
|
caretRight: "right-3"
|
|
129
129
|
}
|
|
130
130
|
};
|
|
131
|
-
function R(
|
|
131
|
+
function R(e) {
|
|
132
132
|
const i = u(h), t = J[i];
|
|
133
133
|
return /* @__PURE__ */ c(
|
|
134
134
|
"div",
|
|
135
135
|
{
|
|
136
|
-
className: a("relative inline-block w-full max-w-xs",
|
|
136
|
+
className: a("relative inline-block w-full max-w-xs", e.className),
|
|
137
137
|
children: [
|
|
138
|
-
/* @__PURE__ */
|
|
138
|
+
/* @__PURE__ */ o(
|
|
139
139
|
p,
|
|
140
140
|
{
|
|
141
|
-
...
|
|
141
|
+
...e,
|
|
142
142
|
className: a(b({ size: i }), "w-full", t.padding)
|
|
143
143
|
}
|
|
144
144
|
),
|
|
145
|
-
/* @__PURE__ */
|
|
145
|
+
/* @__PURE__ */ o(
|
|
146
146
|
D,
|
|
147
147
|
{
|
|
148
148
|
className: a(
|
|
149
149
|
"absolute top-1/2 flex -translate-y-1/2 cursor-pointer bg-transparent p-0",
|
|
150
150
|
t.clearRight
|
|
151
151
|
),
|
|
152
|
-
children: /* @__PURE__ */
|
|
152
|
+
children: /* @__PURE__ */ o(d, { size: t.iconSize })
|
|
153
153
|
}
|
|
154
154
|
),
|
|
155
|
-
/* @__PURE__ */
|
|
155
|
+
/* @__PURE__ */ o(C, { className: "p-0", children: /* @__PURE__ */ o(
|
|
156
156
|
N,
|
|
157
157
|
{
|
|
158
158
|
className: a(
|
|
159
159
|
"absolute top-1/2 flex -translate-y-1/2 cursor-pointer",
|
|
160
160
|
t.caretRight
|
|
161
161
|
),
|
|
162
|
-
children: /* @__PURE__ */
|
|
162
|
+
children: /* @__PURE__ */ o(
|
|
163
163
|
x,
|
|
164
164
|
{
|
|
165
165
|
size: t.iconSize,
|
|
@@ -172,101 +172,101 @@ function R(o) {
|
|
|
172
172
|
}
|
|
173
173
|
);
|
|
174
174
|
}
|
|
175
|
-
function I({ children:
|
|
175
|
+
function I({ children: e, ...i }) {
|
|
176
176
|
return /* @__PURE__ */ c(
|
|
177
177
|
E,
|
|
178
178
|
{
|
|
179
179
|
...i,
|
|
180
180
|
className: "group mx-1.5 grid cursor-pointer grid-cols-[1fr_16px] gap-2 rounded px-2 py-1.5 text-base data-highlighted:bg-kumo-overlay",
|
|
181
181
|
children: [
|
|
182
|
-
/* @__PURE__ */
|
|
183
|
-
/* @__PURE__ */
|
|
182
|
+
/* @__PURE__ */ o("div", { className: "col-start-1", children: e }),
|
|
183
|
+
/* @__PURE__ */ o(K, { className: "col-start-2 flex items-center", children: /* @__PURE__ */ o(w, {}) })
|
|
184
184
|
]
|
|
185
185
|
}
|
|
186
186
|
);
|
|
187
187
|
}
|
|
188
|
-
function Q(
|
|
189
|
-
return /* @__PURE__ */
|
|
188
|
+
function Q(e) {
|
|
189
|
+
return /* @__PURE__ */ o(
|
|
190
190
|
A,
|
|
191
191
|
{
|
|
192
|
-
...
|
|
192
|
+
...e,
|
|
193
193
|
className: a(
|
|
194
194
|
"mx-1.5 shrink-0 px-4 py-2 text-[0.925rem] leading-4 text-kumo-subtle empty:m-0 empty:p-0"
|
|
195
195
|
),
|
|
196
|
-
children:
|
|
196
|
+
children: e.children ?? "No labels found."
|
|
197
197
|
}
|
|
198
198
|
);
|
|
199
199
|
}
|
|
200
|
-
function Y(
|
|
201
|
-
return /* @__PURE__ */
|
|
200
|
+
function Y(e) {
|
|
201
|
+
return /* @__PURE__ */ o(
|
|
202
202
|
p,
|
|
203
203
|
{
|
|
204
|
-
...
|
|
204
|
+
...e,
|
|
205
205
|
className: a(
|
|
206
206
|
b(),
|
|
207
207
|
"mx-1.5 w-[calc(100%-0.75rem)] shrink-0 first:mb-2",
|
|
208
|
-
|
|
208
|
+
e.className
|
|
209
209
|
)
|
|
210
210
|
}
|
|
211
211
|
);
|
|
212
212
|
}
|
|
213
213
|
function Z({
|
|
214
|
-
className:
|
|
214
|
+
className: e,
|
|
215
215
|
...i
|
|
216
216
|
}) {
|
|
217
|
-
return /* @__PURE__ */
|
|
217
|
+
return /* @__PURE__ */ o(
|
|
218
218
|
M,
|
|
219
219
|
{
|
|
220
220
|
...i,
|
|
221
221
|
className: a(
|
|
222
222
|
"min-h-0 flex-1 overflow-y-auto overscroll-contain scroll-pt-2 scroll-pb-2",
|
|
223
|
-
|
|
223
|
+
e
|
|
224
224
|
)
|
|
225
225
|
}
|
|
226
226
|
);
|
|
227
227
|
}
|
|
228
|
-
function $(
|
|
229
|
-
return /* @__PURE__ */
|
|
228
|
+
function $(e) {
|
|
229
|
+
return /* @__PURE__ */ o(
|
|
230
230
|
_,
|
|
231
231
|
{
|
|
232
|
-
...
|
|
232
|
+
...e,
|
|
233
233
|
className: a(
|
|
234
234
|
"mx-1.5 px-2 py-1.5 text-sm text-kumo-strong",
|
|
235
|
-
|
|
235
|
+
e.className
|
|
236
236
|
)
|
|
237
237
|
}
|
|
238
238
|
);
|
|
239
239
|
}
|
|
240
|
-
function
|
|
241
|
-
return /* @__PURE__ */
|
|
240
|
+
function ee(e) {
|
|
241
|
+
return /* @__PURE__ */ o(
|
|
242
242
|
F,
|
|
243
243
|
{
|
|
244
|
-
...
|
|
244
|
+
...e,
|
|
245
245
|
className: "border-t border-kumo-line mt-2 pt-2 first:border-t-0 first:mt-0 first:pt-0"
|
|
246
246
|
}
|
|
247
247
|
);
|
|
248
248
|
}
|
|
249
|
-
function k(
|
|
249
|
+
function k(e) {
|
|
250
250
|
return /* @__PURE__ */ c(
|
|
251
251
|
O,
|
|
252
252
|
{
|
|
253
|
-
...
|
|
253
|
+
...e,
|
|
254
254
|
className: "flex items-center gap-1 rounded-md bg-kumo-overlay px-2 py-1",
|
|
255
255
|
children: [
|
|
256
|
-
|
|
257
|
-
/* @__PURE__ */
|
|
256
|
+
e.children,
|
|
257
|
+
/* @__PURE__ */ o(U, { className: "cursor-pointer rounded-md p-1 hover:bg-kumo-fill-hover", children: /* @__PURE__ */ o(d, { size: 12, weight: "bold" }) })
|
|
258
258
|
]
|
|
259
259
|
}
|
|
260
260
|
);
|
|
261
261
|
}
|
|
262
|
-
const
|
|
262
|
+
const oe = {
|
|
263
263
|
xs: "min-h-5",
|
|
264
264
|
sm: "min-h-6.5",
|
|
265
265
|
base: "min-h-9",
|
|
266
266
|
lg: "min-h-10"
|
|
267
267
|
};
|
|
268
268
|
function S({
|
|
269
|
-
placeholder:
|
|
269
|
+
placeholder: e,
|
|
270
270
|
renderItem: i,
|
|
271
271
|
className: t,
|
|
272
272
|
inputSide: n = "right",
|
|
@@ -278,24 +278,24 @@ function S({
|
|
|
278
278
|
{
|
|
279
279
|
className: a(
|
|
280
280
|
b({ size: s }),
|
|
281
|
-
a("flex flex-col", "gap-1 p-1",
|
|
281
|
+
a("flex flex-col", "gap-1 p-1", oe[s], "h-auto"),
|
|
282
282
|
t
|
|
283
283
|
),
|
|
284
284
|
children: [
|
|
285
|
-
n === "top" && /* @__PURE__ */
|
|
285
|
+
n === "top" && /* @__PURE__ */ o(
|
|
286
286
|
p,
|
|
287
287
|
{
|
|
288
|
-
placeholder:
|
|
288
|
+
placeholder: e,
|
|
289
289
|
className: "w-full px-2 py-1 outline-none"
|
|
290
290
|
}
|
|
291
291
|
),
|
|
292
292
|
/* @__PURE__ */ c("div", { className: "flex flex-wrap gap-1", children: [
|
|
293
293
|
l !== void 0 && l.length > 0 && l.map((m) => i(m)),
|
|
294
|
-
/* @__PURE__ */
|
|
295
|
-
n === "right" && /* @__PURE__ */
|
|
294
|
+
/* @__PURE__ */ o(f, { children: (m) => l !== void 0 ? null : /* @__PURE__ */ o(V, { children: m.map((g) => i(g)) }) }),
|
|
295
|
+
n === "right" && /* @__PURE__ */ o(
|
|
296
296
|
p,
|
|
297
297
|
{
|
|
298
|
-
placeholder:
|
|
298
|
+
placeholder: e,
|
|
299
299
|
className: "min-w-[100px] flex-1 px-2 py-1 outline-none"
|
|
300
300
|
}
|
|
301
301
|
)
|
|
@@ -311,7 +311,7 @@ R.displayName = "Combobox.TriggerInput";
|
|
|
311
311
|
I.displayName = "Combobox.Item";
|
|
312
312
|
k.displayName = "Combobox.Chip";
|
|
313
313
|
S.displayName = "Combobox.TriggerMultipleWithInput";
|
|
314
|
-
const
|
|
314
|
+
const ce = Object.assign(y, {
|
|
315
315
|
// Helper components
|
|
316
316
|
Content: z,
|
|
317
317
|
TriggerValue: v,
|
|
@@ -324,13 +324,13 @@ const co = Object.assign(y, {
|
|
|
324
324
|
Input: Y,
|
|
325
325
|
Empty: Q,
|
|
326
326
|
GroupLabel: $,
|
|
327
|
-
Group:
|
|
327
|
+
Group: ee,
|
|
328
328
|
// Styled BaseUI
|
|
329
329
|
List: Z,
|
|
330
330
|
// BaseUI
|
|
331
331
|
Collection: G
|
|
332
332
|
});
|
|
333
333
|
export {
|
|
334
|
-
|
|
334
|
+
ce as C
|
|
335
335
|
};
|
|
336
|
-
//# sourceMappingURL=combobox
|
|
336
|
+
//# sourceMappingURL=combobox--ec3iibR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combobox--ec3iibR.js","sources":["../src/components/combobox/combobox.tsx"],"sourcesContent":["import { Combobox as ComboboxBase } from \"@base-ui/react/combobox\";\nimport { CaretDownIcon, CheckIcon, XIcon } from \"@phosphor-icons/react\";\nimport {\n Fragment,\n createContext,\n useContext,\n type PropsWithChildren,\n type ReactNode,\n} from \"react\";\nimport {\n inputVariants,\n KUMO_INPUT_VARIANTS,\n type KumoInputSize,\n} from \"../input/input\";\nimport { cn } from \"../../utils/cn\";\nimport { Field, type FieldErrorMatch } from \"../field/field\";\n\n/** Combobox variant definitions. */\nexport const KUMO_COMBOBOX_VARIANTS = {\n size: KUMO_INPUT_VARIANTS.size,\n inputSide: {\n right: {\n classes: \"\",\n description: \"Input positioned inline to the right of chips\",\n },\n top: {\n classes: \"\",\n description: \"Input positioned above chips\",\n },\n },\n} as const;\n\nexport const KUMO_COMBOBOX_DEFAULT_VARIANTS = {\n size: \"base\",\n inputSide: \"right\",\n} as const;\n\n// Context to pass size down to sub-components\nconst ComboboxSizeContext = createContext<KumoInputSize>(\"base\");\n\n// Derived types from KUMO_COMBOBOX_VARIANTS\nexport type KumoComboboxSize = keyof typeof KUMO_COMBOBOX_VARIANTS.size;\nexport type KumoComboboxInputSide =\n keyof typeof KUMO_COMBOBOX_VARIANTS.inputSide;\n\nexport interface KumoComboboxVariantsProps {\n /**\n * Size of the combobox trigger. Matches Input component sizes.\n * - `\"xs\"` — Extra small for compact UIs (h-5 / 20px)\n * - `\"sm\"` — Small for secondary fields (h-6.5 / 26px)\n * - `\"base\"` — Default size (h-9 / 36px)\n * - `\"lg\"` — Large for prominent fields (h-10 / 40px)\n * @default \"base\"\n */\n size?: KumoComboboxSize;\n /**\n * Position of the text input relative to chips in multi-select mode.\n * - `\"right\"` — Input inline to the right of chips\n * - `\"top\"` — Input above chips\n * @default \"right\"\n */\n inputSide?: KumoComboboxInputSide;\n}\n\nexport function comboboxVariants({\n inputSide = KUMO_COMBOBOX_DEFAULT_VARIANTS.inputSide,\n}: KumoComboboxVariantsProps = {}) {\n return cn(KUMO_COMBOBOX_VARIANTS.inputSide[inputSide].classes);\n}\n\n// Legacy type alias for backwards compatibility\nexport type ComboboxInputSide = KumoComboboxInputSide;\nexport type ComboboxSize = KumoComboboxSize;\n\nexport type ComboboxRootProps<\n Value = unknown,\n Multiple extends boolean | undefined = false,\n> = ComboboxBase.Root.Props<Value, Multiple>;\n\n/**\n * Combobox component props (simplified for documentation; the actual Root is generic).\n *\n * Combobox provides an autocomplete/typeahead input with a filterable dropdown.\n * Supports single-select, multi-select with chips, grouped items, and Field wrapper integration.\n *\n * @example\n * ```tsx\n * // Single-select with search input\n * <Combobox value={value} onValueChange={setValue} items={options}>\n * <Combobox.TriggerInput placeholder=\"Search…\" />\n * <Combobox.Content>\n * <Combobox.List>\n * {(item) => <Combobox.Item value={item}>{item.label}</Combobox.Item>}\n * </Combobox.List>\n * <Combobox.Empty>No results</Combobox.Empty>\n * </Combobox.Content>\n * </Combobox>\n *\n * // Multi-select with chips\n * <Combobox multiple items={options} label=\"Tags\">\n * <Combobox.TriggerMultipleWithInput\n * placeholder=\"Add tag…\"\n * renderItem={(item) => <Combobox.Chip value={item}>{item.label}</Combobox.Chip>}\n * />\n * <Combobox.Content>\n * <Combobox.List>\n * {(item) => <Combobox.Item value={item}>{item.label}</Combobox.Item>}\n * </Combobox.List>\n * </Combobox.Content>\n * </Combobox>\n * ```\n */\nexport interface ComboboxProps extends KumoComboboxVariantsProps {\n /** Array of items to display in the dropdown */\n items: unknown[];\n /** Currently selected value(s) */\n value?: unknown;\n /** Callback when selection changes */\n onValueChange?: (value: unknown) => void;\n /** Enable multi-select mode */\n multiple?: boolean;\n /** Combobox content (trigger, content, items) */\n children: ReactNode;\n /** Additional CSS classes */\n className?: string;\n /** Label content for the combobox (enables Field wrapper) - can be a string or any React node */\n label?: ReactNode;\n /** Whether the combobox is required */\n required?: boolean;\n /** Tooltip content to display next to the label via an info icon */\n labelTooltip?: ReactNode;\n /** Helper text displayed below the combobox */\n description?: ReactNode;\n /** Error message or validation error object */\n error?: string | { message: ReactNode; match: FieldErrorMatch };\n}\n\nfunction Root<Value, Multiple extends boolean | undefined = false>({\n label,\n required,\n labelTooltip,\n description,\n error,\n children,\n size = \"base\",\n ...props\n}: ComboboxBase.Root.Props<Value, Multiple> & {\n label?: ReactNode;\n required?: boolean;\n labelTooltip?: ReactNode;\n description?: ReactNode;\n error?: string | { message: ReactNode; match: FieldErrorMatch };\n size?: KumoComboboxSize;\n}) {\n const comboboxControl = (\n <ComboboxSizeContext.Provider value={size}>\n <ComboboxBase.Root {...props}>{children}</ComboboxBase.Root>\n </ComboboxSizeContext.Provider>\n );\n\n // Render with Field wrapper if label, description, or error are provided\n if (label) {\n return (\n <Field\n label={label}\n required={required}\n labelTooltip={labelTooltip}\n description={description}\n error={\n error\n ? typeof error === \"string\"\n ? { message: error, match: true }\n : error\n : undefined\n }\n >\n {comboboxControl}\n </Field>\n );\n }\n\n // Render bare combobox without Field wrapper\n return comboboxControl;\n}\n\nfunction Content({\n children,\n className,\n align = \"start\",\n sideOffset = 4,\n alignOffset,\n side,\n}: PropsWithChildren<{\n className?: string;\n align?: ComboboxBase.Positioner.Props[\"align\"];\n alignOffset?: ComboboxBase.Positioner.Props[\"alignOffset\"];\n side?: ComboboxBase.Positioner.Props[\"side\"];\n sideOffset?: ComboboxBase.Positioner.Props[\"sideOffset\"];\n}>) {\n return (\n <ComboboxBase.Portal>\n <ComboboxBase.Positioner\n className=\"outline-none\"\n align={align}\n sideOffset={sideOffset}\n alignOffset={alignOffset}\n side={side}\n >\n <ComboboxBase.Popup\n className={cn(\n \"flex flex-col\", // flexbox layout for sticky input + scrollable list\n \"max-h-[min(var(--available-height),24rem)] max-w-(--available-width) min-w-(--anchor-width) py-1.5\",\n \"bg-kumo-control text-kumo-default\", // background\n \"rounded-lg shadow-lg ring ring-kumo-line\", // border part\n className,\n )}\n >\n {children}\n </ComboboxBase.Popup>\n </ComboboxBase.Positioner>\n </ComboboxBase.Portal>\n );\n}\n\n// Size-dependent styles for TriggerValue icon\nconst triggerValueIconStyles: Record<\n KumoComboboxSize,\n { padding: string; iconSize: number; iconRight: string }\n> = {\n xs: { padding: \"pr-5\", iconSize: 12, iconRight: \"right-1\" },\n sm: { padding: \"pr-6\", iconSize: 14, iconRight: \"right-1.5\" },\n base: { padding: \"pr-8\", iconSize: 16, iconRight: \"right-2\" },\n lg: { padding: \"pr-10\", iconSize: 18, iconRight: \"right-3\" },\n};\n\nfunction TriggerValue({\n className,\n ...props\n}: ComboboxBase.Value.Props & { className?: string }) {\n const size = useContext(ComboboxSizeContext);\n const iconStyles = triggerValueIconStyles[size];\n\n return (\n <ComboboxBase.Trigger\n className={cn(\n inputVariants({ size }),\n \"relative flex items-center\",\n iconStyles.padding,\n className,\n )}\n >\n <ComboboxBase.Value>{props.children}</ComboboxBase.Value>\n <ComboboxBase.Icon\n className={cn(\n \"absolute top-1/2 -translate-y-1/2 flex items-center\",\n iconStyles.iconRight,\n )}\n >\n <CaretDownIcon size={iconStyles.iconSize} className=\"fill-kumo-ring\" />\n </ComboboxBase.Icon>\n </ComboboxBase.Trigger>\n );\n}\n\n// Size-dependent styles for TriggerInput icons\nconst triggerInputIconStyles: Record<\n KumoComboboxSize,\n { padding: string; iconSize: number; clearRight: string; caretRight: string }\n> = {\n xs: {\n padding: \"pr-7\",\n iconSize: 12,\n clearRight: \"right-5\",\n caretRight: \"right-1\",\n },\n sm: {\n padding: \"pr-9\",\n iconSize: 14,\n clearRight: \"right-6\",\n caretRight: \"right-1.5\",\n },\n base: {\n padding: \"pr-12\",\n iconSize: 16,\n clearRight: \"right-8\",\n caretRight: \"right-2\",\n },\n lg: {\n padding: \"pr-14\",\n iconSize: 18,\n clearRight: \"right-9\",\n caretRight: \"right-3\",\n },\n};\n\nfunction TriggerInput(props: ComboboxBase.Input.Props) {\n const size = useContext(ComboboxSizeContext);\n const iconStyles = triggerInputIconStyles[size];\n\n return (\n <div\n className={cn(\"relative inline-block w-full max-w-xs\", props.className)}\n >\n <ComboboxBase.Input\n {...props}\n className={cn(inputVariants({ size }), \"w-full\", iconStyles.padding)}\n />\n\n <ComboboxBase.Clear\n className={cn(\n \"absolute top-1/2 flex -translate-y-1/2 cursor-pointer bg-transparent p-0\",\n iconStyles.clearRight,\n )}\n >\n <XIcon size={iconStyles.iconSize} />\n </ComboboxBase.Clear>\n\n <ComboboxBase.Trigger className=\"p-0\">\n <ComboboxBase.Icon\n className={cn(\n \"absolute top-1/2 flex -translate-y-1/2 cursor-pointer\",\n iconStyles.caretRight,\n )}\n >\n <CaretDownIcon\n size={iconStyles.iconSize}\n className=\"fill-kumo-ring\"\n />\n </ComboboxBase.Icon>\n </ComboboxBase.Trigger>\n </div>\n );\n}\n\nfunction Item({ children, ...props }: ComboboxBase.Item.Props) {\n return (\n <ComboboxBase.Item\n {...props}\n className=\"group mx-1.5 grid cursor-pointer grid-cols-[1fr_16px] gap-2 rounded px-2 py-1.5 text-base data-highlighted:bg-kumo-overlay\"\n >\n <div className=\"col-start-1\">{children}</div>\n <ComboboxBase.ItemIndicator className=\"col-start-2 flex items-center\">\n <CheckIcon />\n </ComboboxBase.ItemIndicator>\n </ComboboxBase.Item>\n );\n}\n\nfunction Empty(props: ComboboxBase.Empty.Props) {\n return (\n <ComboboxBase.Empty\n {...props}\n className={cn(\n \"mx-1.5 shrink-0 px-4 py-2 text-[0.925rem] leading-4 text-kumo-subtle empty:m-0 empty:p-0\",\n )}\n children={props.children ?? \"No labels found.\"}\n />\n );\n}\n\nfunction Input(props: ComboboxBase.Input.Props) {\n return (\n <ComboboxBase.Input\n {...props}\n className={cn(\n inputVariants(),\n \"mx-1.5 w-[calc(100%-0.75rem)] shrink-0 first:mb-2\",\n props.className,\n )}\n />\n );\n}\n\nfunction List({\n className,\n ...props\n}: ComboboxBase.List.Props & { className?: string }) {\n return (\n <ComboboxBase.List\n {...props}\n className={cn(\n \"min-h-0 flex-1 overflow-y-auto overscroll-contain scroll-pt-2 scroll-pb-2\",\n className,\n )}\n />\n );\n}\n\nfunction GroupLabel(props: ComboboxBase.GroupLabel.Props) {\n return (\n <ComboboxBase.GroupLabel\n {...props}\n className={cn(\n \"mx-1.5 px-2 py-1.5 text-sm text-kumo-strong\",\n props.className,\n )}\n />\n );\n}\n\nfunction Group(props: ComboboxBase.Group.Props) {\n return (\n <ComboboxBase.Group\n {...props}\n className=\"border-t border-kumo-line mt-2 pt-2 first:border-t-0 first:mt-0 first:pt-0\"\n />\n );\n}\n\nfunction Chip(props: ComboboxBase.Chip.Props) {\n return (\n <ComboboxBase.Chip\n {...props}\n className=\"flex items-center gap-1 rounded-md bg-kumo-overlay px-2 py-1\"\n >\n {props.children}\n <ComboboxBase.ChipRemove className=\"cursor-pointer rounded-md p-1 hover:bg-kumo-fill-hover\">\n <XIcon size={12} weight=\"bold\" />\n </ComboboxBase.ChipRemove>\n </ComboboxBase.Chip>\n );\n}\n\n// Map size to min-height class for TriggerMultipleWithInput\nconst sizeToMinHeight: Record<KumoComboboxSize, string> = {\n xs: \"min-h-5\",\n sm: \"min-h-6.5\",\n base: \"min-h-9\",\n lg: \"min-h-10\",\n};\n\nfunction TriggerMultipleWithInput<ValueType>({\n placeholder,\n renderItem,\n className,\n inputSide = \"right\",\n value: controlledValue,\n}: {\n placeholder?: string;\n renderItem: (value: ValueType) => React.ReactNode;\n className?: string;\n inputSide?: \"right\" | \"top\";\n /** Optional controlled value for rendering chips (use when pre-selecting values) */\n value?: ValueType[];\n}) {\n const size = useContext(ComboboxSizeContext);\n // Determine which value to use for rendering chips\n const chipsToRender = controlledValue;\n\n return (\n <ComboboxBase.Chips\n className={cn(\n inputVariants({ size }),\n cn(\"flex flex-col\", \"gap-1 p-1\", sizeToMinHeight[size], \"h-auto\"),\n className,\n )}\n >\n {inputSide === \"top\" && (\n <ComboboxBase.Input\n placeholder={placeholder}\n className=\"w-full px-2 py-1 outline-none\"\n />\n )}\n {/* Chips container */}\n <div className=\"flex flex-wrap gap-1\">\n {/* Render chips from controlled value if provided */}\n {chipsToRender !== undefined &&\n chipsToRender.length > 0 &&\n chipsToRender.map((item) => renderItem(item))}\n {/* Also render from BaseUI's internal value for user selections */}\n <ComboboxBase.Value>\n {(internalValue: ValueType[]) => {\n // Skip rendering if using controlled value (to avoid duplicates)\n if (chipsToRender !== undefined) return null;\n return (\n <Fragment>\n {internalValue.map((item) => renderItem(item))}\n </Fragment>\n );\n }}\n </ComboboxBase.Value>\n {inputSide === \"right\" && (\n <ComboboxBase.Input\n placeholder={placeholder}\n className=\"min-w-[100px] flex-1 px-2 py-1 outline-none\"\n />\n )}\n </div>\n </ComboboxBase.Chips>\n );\n}\n\nRoot.displayName = \"Combobox.Root\";\nContent.displayName = \"Combobox.Content\";\nTriggerValue.displayName = \"Combobox.TriggerValue\";\nTriggerInput.displayName = \"Combobox.TriggerInput\";\nItem.displayName = \"Combobox.Item\";\nChip.displayName = \"Combobox.Chip\";\nTriggerMultipleWithInput.displayName = \"Combobox.TriggerMultipleWithInput\";\n\n/**\n * Combobox — autocomplete input with filterable dropdown list.\n *\n * Compound component: `Combobox` (Root), `.TriggerInput`, `.TriggerValue`,\n * `.TriggerMultipleWithInput`, `.Content`, `.Item`, `.Chip`, `.Input`,\n * `.Empty`, `.GroupLabel`, `.Group`, `.List`, `.Collection`.\n *\n * @example\n * ```tsx\n * <Combobox items={fruits} label=\"Fruit\">\n * <Combobox.TriggerInput placeholder=\"Pick a fruit…\" />\n * <Combobox.Content>\n * <Combobox.List>\n * {(item) => <Combobox.Item value={item}>{item}</Combobox.Item>}\n * </Combobox.List>\n * </Combobox.Content>\n * </Combobox>\n * ```\n *\n * @see https://base-ui.com/react/components/combobox\n */\nexport const Combobox = Object.assign(Root, {\n // Helper components\n Content,\n TriggerValue,\n TriggerInput,\n TriggerMultipleWithInput,\n\n // Slightly modified BaseUI\n Chip,\n Item,\n\n // Styled BaseUI\n Input,\n Empty,\n GroupLabel,\n Group,\n\n // Styled BaseUI\n List,\n\n // BaseUI\n Collection: ComboboxBase.Collection,\n});\n"],"names":["KUMO_INPUT_VARIANTS","ComboboxSizeContext","createContext","Root","label","required","labelTooltip","description","error","children","size","props","comboboxControl","jsx","ComboboxBase.Root","Field","Content","className","align","sideOffset","alignOffset","side","ComboboxBase.Portal","ComboboxBase.Positioner","ComboboxBase.Popup","cn","triggerValueIconStyles","TriggerValue","useContext","iconStyles","jsxs","ComboboxBase.Trigger","inputVariants","ComboboxBase.Value","ComboboxBase.Icon","CaretDownIcon","triggerInputIconStyles","TriggerInput","ComboboxBase.Input","ComboboxBase.Clear","XIcon","Item","ComboboxBase.Item","ComboboxBase.ItemIndicator","CheckIcon","Empty","ComboboxBase.Empty","Input","List","ComboboxBase.List","GroupLabel","ComboboxBase.GroupLabel","Group","ComboboxBase.Group","Chip","ComboboxBase.Chip","ComboboxBase.ChipRemove","sizeToMinHeight","TriggerMultipleWithInput","placeholder","renderItem","inputSide","controlledValue","chipsToRender","ComboboxBase.Chips","item","internalValue","Fragment","Combobox","ComboboxBase.Collection"],"mappings":"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"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as e, jsxs as p, Fragment as E } from "react/jsx-runtime";
|
|
3
3
|
import { forwardRef as K, useContext as N, createContext as v, useCallback as b, useRef as T } from "react";
|
|
4
|
-
import { CaretRightIcon as M, ArrowSquareOutIcon as H, ArrowRightIcon as _, MagnifyingGlassIcon as
|
|
5
|
-
import { S as
|
|
6
|
-
import { L as
|
|
4
|
+
import { CaretRightIcon as M, ArrowSquareOutIcon as H, ArrowRightIcon as _, MagnifyingGlassIcon as F } from "@phosphor-icons/react";
|
|
5
|
+
import { S as G } from "./surface-BIC6CXiz.js";
|
|
6
|
+
import { L as j } from "./loader-DHGMYlC6.js";
|
|
7
7
|
import { c as m } from "./cn-Bhsu1vx2.js";
|
|
8
|
-
import { a5 as U, a7 as O, aa as V, ac as w, a9 as $, a8 as q, ab as z,
|
|
8
|
+
import { a5 as U, a7 as O, aa as V, ac as w, a9 as $, a8 as q, ab as z, bk as B, ap as S, au as J, av as Q, aw as W } from "./vendor-base-ui-DN1j_aJS.js";
|
|
9
9
|
const C = v({});
|
|
10
10
|
function I({
|
|
11
11
|
open: t,
|
|
@@ -27,7 +27,7 @@ function I({
|
|
|
27
27
|
}
|
|
28
28
|
),
|
|
29
29
|
/* @__PURE__ */ e(
|
|
30
|
-
|
|
30
|
+
G,
|
|
31
31
|
{
|
|
32
32
|
as: W,
|
|
33
33
|
className: m(
|
|
@@ -89,7 +89,7 @@ function Y({
|
|
|
89
89
|
}) {
|
|
90
90
|
return /* @__PURE__ */ p("div", { className: "flex items-center gap-3 bg-kumo-base px-4 py-3", children: [
|
|
91
91
|
n ?? /* @__PURE__ */ e(
|
|
92
|
-
|
|
92
|
+
F,
|
|
93
93
|
{
|
|
94
94
|
className: "h-4 w-4 text-kumo-subtle",
|
|
95
95
|
weight: "bold"
|
|
@@ -163,7 +163,7 @@ function ne({ children: t }) {
|
|
|
163
163
|
return /* @__PURE__ */ e(V, { children: /* @__PURE__ */ e("div", { className: "p-8 text-center", children: /* @__PURE__ */ e("p", { className: "text-kumo-strong", children: t ?? "No results found" }) }) });
|
|
164
164
|
}
|
|
165
165
|
function ae({ children: t }) {
|
|
166
|
-
return /* @__PURE__ */ e("div", { className: "flex items-center justify-center p-8", children: t ?? /* @__PURE__ */ e(
|
|
166
|
+
return /* @__PURE__ */ e("div", { className: "flex items-center justify-center p-8", children: t ?? /* @__PURE__ */ e(j, { size: 24 }) });
|
|
167
167
|
}
|
|
168
168
|
function oe({ children: t }) {
|
|
169
169
|
return /* @__PURE__ */ e("div", { className: "flex items-center justify-between rounded-b-lg bg-kumo-elevated px-4 py-3 text-xs text-kumo-strong", children: t });
|
|
@@ -396,4 +396,4 @@ export {
|
|
|
396
396
|
ye as K,
|
|
397
397
|
ke as a
|
|
398
398
|
};
|
|
399
|
-
//# sourceMappingURL=command-palette-
|
|
399
|
+
//# sourceMappingURL=command-palette-B_J7o7P-.js.map
|