@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.
Files changed (179) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/ai/component-registry.json +21 -32
  3. package/ai/component-registry.md +66 -60
  4. package/ai/schemas.ts +2 -2
  5. package/dist/.build-complete +1 -1
  6. package/dist/ai/schemas.js +1 -2
  7. package/dist/ai/schemas.js.map +1 -1
  8. package/dist/checkbox-ZiHzIOCx.js +220 -0
  9. package/dist/checkbox-ZiHzIOCx.js.map +1 -0
  10. package/dist/{clipboard-text-DbvIaZ3g.js → clipboard-text-DXs1GdOt.js} +3 -3
  11. package/dist/{clipboard-text-DbvIaZ3g.js.map → clipboard-text-DXs1GdOt.js.map} +1 -1
  12. package/dist/code.js +62 -62
  13. package/dist/code.js.map +1 -1
  14. package/dist/{collapsible-OBNkTO48.js → collapsible-C3LJ1dfZ.js} +13 -11
  15. package/dist/collapsible-C3LJ1dfZ.js.map +1 -0
  16. package/dist/{combobox-CJqgoue6.js → combobox--ec3iibR.js} +63 -63
  17. package/dist/combobox--ec3iibR.js.map +1 -0
  18. package/dist/{command-palette-xctZ--ZT.js → command-palette-B_J7o7P-.js} +8 -8
  19. package/dist/{command-palette-xctZ--ZT.js.map → command-palette-B_J7o7P-.js.map} +1 -1
  20. package/dist/components/checkbox.js +1 -1
  21. package/dist/components/clipboard-text.js +1 -1
  22. package/dist/components/collapsible.js +1 -1
  23. package/dist/components/combobox.js +1 -1
  24. package/dist/components/command-palette.js +1 -1
  25. package/dist/components/dialog.js +1 -1
  26. package/dist/components/dropdown.js +1 -1
  27. package/dist/components/field.js +1 -1
  28. package/dist/components/flow.js +1857 -1803
  29. package/dist/components/flow.js.map +1 -1
  30. package/dist/components/input.js +3 -3
  31. package/dist/components/label.js +1 -1
  32. package/dist/components/link.js +1 -1
  33. package/dist/components/menubar.js +1 -1
  34. package/dist/components/meter.js +1 -1
  35. package/dist/components/pagination.js +1 -1
  36. package/dist/components/popover.js +1 -1
  37. package/dist/components/radio.js +1 -1
  38. package/dist/components/select.js +1 -1
  39. package/dist/components/sensitive-input.js +1 -1
  40. package/dist/components/switch.js +1 -1
  41. package/dist/components/table.js +1 -1
  42. package/dist/components/tabs.js +1 -1
  43. package/dist/components/toast.js +2 -2
  44. package/dist/components/tooltip.js +1 -1
  45. package/dist/{dialog-1pa-ezdL.js → dialog-DGaQTZVR.js} +2 -2
  46. package/dist/{dialog-1pa-ezdL.js.map → dialog-DGaQTZVR.js.map} +1 -1
  47. package/dist/{dropdown-BXg01-8j.js → dropdown-DBfVqi0v.js} +74 -75
  48. package/dist/dropdown-DBfVqi0v.js.map +1 -0
  49. package/dist/{field-BYaOyOtJ.js → field-CQmGKOVZ.js} +7 -7
  50. package/dist/{field-BYaOyOtJ.js.map → field-CQmGKOVZ.js.map} +1 -1
  51. package/dist/index.js +28 -28
  52. package/dist/{input-area-C3ddZhEo.js → input-area-BgpN8siO.js} +3 -3
  53. package/dist/{input-area-C3ddZhEo.js.map → input-area-BgpN8siO.js.map} +1 -1
  54. package/dist/{input-BXn3ElmF.js → input-gGpJCiT7.js} +3 -3
  55. package/dist/{input-BXn3ElmF.js.map → input-gGpJCiT7.js.map} +1 -1
  56. package/dist/{input-group-BiUKE2TR.js → input-group-DwPPwJEW.js} +2 -2
  57. package/dist/{input-group-BiUKE2TR.js.map → input-group-DwPPwJEW.js.map} +1 -1
  58. package/dist/label-hoE9-Nzo.js +62 -0
  59. package/dist/label-hoE9-Nzo.js.map +1 -0
  60. package/dist/{link-CfCaX9Ks.js → link-BFszrye7.js} +20 -14
  61. package/dist/link-BFszrye7.js.map +1 -0
  62. package/dist/{menubar-be9R8bE-.js → menubar-DF-6twXU.js} +2 -2
  63. package/dist/{menubar-be9R8bE-.js.map → menubar-DF-6twXU.js.map} +1 -1
  64. package/dist/{meter-CCpXrH8B.js → meter-CP6NBKRN.js} +2 -2
  65. package/dist/{meter-CCpXrH8B.js.map → meter-CP6NBKRN.js.map} +1 -1
  66. package/dist/{pagination-CaHm6TKa.js → pagination-BWkeDEqb.js} +44 -40
  67. package/dist/pagination-BWkeDEqb.js.map +1 -0
  68. package/dist/{popover-CHafAVT6.js → popover-B5CWcu7v.js} +2 -2
  69. package/dist/{popover-CHafAVT6.js.map → popover-B5CWcu7v.js.map} +1 -1
  70. package/dist/primitives/accordion.js +1 -1
  71. package/dist/primitives/alert-dialog.js +1 -1
  72. package/dist/primitives/autocomplete.js +1 -1
  73. package/dist/primitives/avatar.js +1 -1
  74. package/dist/primitives/button.js +1 -1
  75. package/dist/primitives/checkbox-group.js +1 -1
  76. package/dist/primitives/checkbox.js +1 -1
  77. package/dist/primitives/collapsible.js +1 -1
  78. package/dist/primitives/combobox.js +1 -1
  79. package/dist/primitives/context-menu.js +1 -1
  80. package/dist/primitives/csp-provider.js +1 -1
  81. package/dist/primitives/dialog.js +1 -1
  82. package/dist/primitives/direction-provider.js +1 -1
  83. package/dist/primitives/drawer.js +1 -1
  84. package/dist/primitives/field.js +1 -1
  85. package/dist/primitives/fieldset.js +1 -1
  86. package/dist/primitives/form.js +1 -1
  87. package/dist/primitives/input.js +1 -1
  88. package/dist/primitives/menu.js +1 -1
  89. package/dist/primitives/menubar.js +1 -1
  90. package/dist/primitives/meter.js +1 -1
  91. package/dist/primitives/navigation-menu.js +1 -1
  92. package/dist/primitives/number-field.js +1 -1
  93. package/dist/primitives/popover.js +1 -1
  94. package/dist/primitives/preview-card.js +1 -1
  95. package/dist/primitives/progress.js +1 -1
  96. package/dist/primitives/radio-group.js +1 -1
  97. package/dist/primitives/radio.js +1 -1
  98. package/dist/primitives/scroll-area.js +1 -1
  99. package/dist/primitives/select.js +1 -1
  100. package/dist/primitives/separator.js +1 -1
  101. package/dist/primitives/slider.js +1 -1
  102. package/dist/primitives/switch.js +1 -1
  103. package/dist/primitives/tabs.js +1 -1
  104. package/dist/primitives/toast.js +1 -1
  105. package/dist/primitives/toggle-group.js +1 -1
  106. package/dist/primitives/toggle.js +1 -1
  107. package/dist/primitives/toolbar.js +1 -1
  108. package/dist/primitives/tooltip.js +1 -1
  109. package/dist/primitives.js +1 -1
  110. package/dist/{radio-DZ1uS-zK.js → radio-BQTXNBkS.js} +6 -6
  111. package/dist/radio-BQTXNBkS.js.map +1 -0
  112. package/dist/scripts/theme-generator/config.js +1 -1
  113. package/dist/scripts/theme-generator/config.js.map +1 -1
  114. package/dist/scripts/theme-generator/generate-css.d.ts.map +1 -1
  115. package/dist/select-BWUNPPHQ.js +123 -0
  116. package/dist/select-BWUNPPHQ.js.map +1 -0
  117. package/dist/{sensitive-input-CI-gtdfw.js → sensitive-input-A6Kw7URa.js} +4 -4
  118. package/dist/{sensitive-input-CI-gtdfw.js.map → sensitive-input-A6Kw7URa.js.map} +1 -1
  119. package/dist/src/code/code-highlighted.d.ts.map +1 -1
  120. package/dist/src/components/collapsible/collapsible.d.ts.map +1 -1
  121. package/dist/src/components/dropdown/dropdown.d.ts.map +1 -1
  122. package/dist/src/components/flow/connectors.d.ts +4 -0
  123. package/dist/src/components/flow/connectors.d.ts.map +1 -1
  124. package/dist/src/components/flow/diagram.d.ts +27 -2
  125. package/dist/src/components/flow/diagram.d.ts.map +1 -1
  126. package/dist/src/components/flow/node.d.ts +6 -1
  127. package/dist/src/components/flow/node.d.ts.map +1 -1
  128. package/dist/src/components/flow/parallel.d.ts.map +1 -1
  129. package/dist/src/components/flow/use-children.d.ts +12 -1
  130. package/dist/src/components/flow/use-children.d.ts.map +1 -1
  131. package/dist/src/components/label/label.d.ts.map +1 -1
  132. package/dist/src/components/link/link.d.ts +2 -2
  133. package/dist/src/components/link/link.d.ts.map +1 -1
  134. package/dist/src/components/pagination/pagination.d.ts.map +1 -1
  135. package/dist/src/components/radio/radio.d.ts.map +1 -1
  136. package/dist/src/components/select/select.d.ts +29 -6
  137. package/dist/src/components/select/select.d.ts.map +1 -1
  138. package/dist/src/components/switch/switch.d.ts.map +1 -1
  139. package/dist/src/components/tabs/tabs.d.ts +6 -2
  140. package/dist/src/components/tabs/tabs.d.ts.map +1 -1
  141. package/dist/src/components/toast/toast.d.ts +1 -0
  142. package/dist/src/components/toast/toast.d.ts.map +1 -1
  143. package/dist/src/components/tooltip/tooltip.d.ts.map +1 -1
  144. package/dist/styles/kumo-binding.css +19 -0
  145. package/dist/styles/kumo-standalone.css +1 -1
  146. package/dist/styles/theme-fedramp.css +13 -0
  147. package/dist/styles/theme-kumo.css +77 -1
  148. package/dist/{switch-BxnAwAse.js → switch-CmUFBiJv.js} +4 -4
  149. package/dist/switch-CmUFBiJv.js.map +1 -0
  150. package/dist/{table-CdcsAm5X.js → table-CbU4Oe3o.js} +2 -2
  151. package/dist/{table-CdcsAm5X.js.map → table-CbU4Oe3o.js.map} +1 -1
  152. package/dist/{tabs-Cf12PXHz.js → tabs-uLzHh6SR.js} +14 -13
  153. package/dist/tabs-uLzHh6SR.js.map +1 -0
  154. package/dist/{toast-BzvG5cpW.js → toast-B-d56fkl.js} +124 -92
  155. package/dist/toast-B-d56fkl.js.map +1 -0
  156. package/dist/{tooltip-2KqOpTj0.js → tooltip-C7p2iJ0y.js} +24 -18
  157. package/dist/tooltip-C7p2iJ0y.js.map +1 -0
  158. package/dist/{vendor-base-ui-DvXlzG7n.js → vendor-base-ui-DN1j_aJS.js} +50 -49
  159. package/dist/{vendor-base-ui-DvXlzG7n.js.map → vendor-base-ui-DN1j_aJS.js.map} +1 -1
  160. package/package.json +3 -1
  161. package/scripts/theme-generator/config.ts +1 -1
  162. package/scripts/theme-generator/generate-css.test.ts +30 -0
  163. package/scripts/theme-generator/generate-css.ts +104 -6
  164. package/dist/checkbox-z5gO1lL8.js +0 -224
  165. package/dist/checkbox-z5gO1lL8.js.map +0 -1
  166. package/dist/collapsible-OBNkTO48.js.map +0 -1
  167. package/dist/combobox-CJqgoue6.js.map +0 -1
  168. package/dist/dropdown-BXg01-8j.js.map +0 -1
  169. package/dist/label-ByOtGj7z.js +0 -58
  170. package/dist/label-ByOtGj7z.js.map +0 -1
  171. package/dist/link-CfCaX9Ks.js.map +0 -1
  172. package/dist/pagination-CaHm6TKa.js.map +0 -1
  173. package/dist/radio-DZ1uS-zK.js.map +0 -1
  174. package/dist/select-BXZAlFAV.js +0 -113
  175. package/dist/select-BXZAlFAV.js.map +0 -1
  176. package/dist/switch-BxnAwAse.js.map +0 -1
  177. package/dist/tabs-Cf12PXHz.js.map +0 -1
  178. package/dist/toast-BzvG5cpW.js.map +0 -1
  179. 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 l } from "react/jsx-runtime";
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 f } from "react";
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 b(e = {}) {
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: i, className: n }, c) => {
14
- const s = u(), m = f(() => {
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: b(),
26
+ className: f(),
25
27
  onClick: m,
26
28
  children: [
27
29
  e,
28
30
  " ",
29
- /* @__PURE__ */ l(
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__ */ l(
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
- n
46
+ i
45
47
  ),
46
- children: i
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-OBNkTO48.js.map
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 e, jsxs as c } from "react/jsx-runtime";
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-BXn3ElmF.js";
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-BYaOyOtJ.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-DvXlzG7n.js";
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: o,
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__ */ e(h.Provider, { value: l, children: /* @__PURE__ */ e(L, { ...m, children: s }) });
22
- return o ? /* @__PURE__ */ e(
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: o,
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: o,
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__ */ e(H, { children: /* @__PURE__ */ e(
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__ */ e(
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: o
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: o,
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
- o
87
+ e
88
88
  ),
89
89
  children: [
90
- /* @__PURE__ */ e(f, { children: i.children }),
91
- /* @__PURE__ */ e(
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__ */ e(x, { size: n.iconSize, className: "fill-kumo-ring" })
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(o) {
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", o.className),
136
+ className: a("relative inline-block w-full max-w-xs", e.className),
137
137
  children: [
138
- /* @__PURE__ */ e(
138
+ /* @__PURE__ */ o(
139
139
  p,
140
140
  {
141
- ...o,
141
+ ...e,
142
142
  className: a(b({ size: i }), "w-full", t.padding)
143
143
  }
144
144
  ),
145
- /* @__PURE__ */ e(
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__ */ e(d, { size: t.iconSize })
152
+ children: /* @__PURE__ */ o(d, { size: t.iconSize })
153
153
  }
154
154
  ),
155
- /* @__PURE__ */ e(C, { className: "p-0", children: /* @__PURE__ */ e(
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__ */ e(
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: o, ...i }) {
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__ */ e("div", { className: "col-start-1", children: o }),
183
- /* @__PURE__ */ e(K, { className: "col-start-2 flex items-center", children: /* @__PURE__ */ e(w, {}) })
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(o) {
189
- return /* @__PURE__ */ e(
188
+ function Q(e) {
189
+ return /* @__PURE__ */ o(
190
190
  A,
191
191
  {
192
- ...o,
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: o.children ?? "No labels found."
196
+ children: e.children ?? "No labels found."
197
197
  }
198
198
  );
199
199
  }
200
- function Y(o) {
201
- return /* @__PURE__ */ e(
200
+ function Y(e) {
201
+ return /* @__PURE__ */ o(
202
202
  p,
203
203
  {
204
- ...o,
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
- o.className
208
+ e.className
209
209
  )
210
210
  }
211
211
  );
212
212
  }
213
213
  function Z({
214
- className: o,
214
+ className: e,
215
215
  ...i
216
216
  }) {
217
- return /* @__PURE__ */ e(
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
- o
223
+ e
224
224
  )
225
225
  }
226
226
  );
227
227
  }
228
- function $(o) {
229
- return /* @__PURE__ */ e(
228
+ function $(e) {
229
+ return /* @__PURE__ */ o(
230
230
  _,
231
231
  {
232
- ...o,
232
+ ...e,
233
233
  className: a(
234
234
  "mx-1.5 px-2 py-1.5 text-sm text-kumo-strong",
235
- o.className
235
+ e.className
236
236
  )
237
237
  }
238
238
  );
239
239
  }
240
- function oo(o) {
241
- return /* @__PURE__ */ e(
240
+ function ee(e) {
241
+ return /* @__PURE__ */ o(
242
242
  F,
243
243
  {
244
- ...o,
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(o) {
249
+ function k(e) {
250
250
  return /* @__PURE__ */ c(
251
251
  O,
252
252
  {
253
- ...o,
253
+ ...e,
254
254
  className: "flex items-center gap-1 rounded-md bg-kumo-overlay px-2 py-1",
255
255
  children: [
256
- o.children,
257
- /* @__PURE__ */ e(U, { className: "cursor-pointer rounded-md p-1 hover:bg-kumo-fill-hover", children: /* @__PURE__ */ e(d, { size: 12, weight: "bold" }) })
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 eo = {
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: o,
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", eo[s], "h-auto"),
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__ */ e(
285
+ n === "top" && /* @__PURE__ */ o(
286
286
  p,
287
287
  {
288
- placeholder: o,
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__ */ e(f, { children: (m) => l !== void 0 ? null : /* @__PURE__ */ e(V, { children: m.map((g) => i(g)) }) }),
295
- n === "right" && /* @__PURE__ */ e(
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: o,
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 co = Object.assign(y, {
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: oo,
327
+ Group: ee,
328
328
  // Styled BaseUI
329
329
  List: Z,
330
330
  // BaseUI
331
331
  Collection: G
332
332
  });
333
333
  export {
334
- co as C
334
+ ce as C
335
335
  };
336
- //# sourceMappingURL=combobox-CJqgoue6.js.map
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 j } from "@phosphor-icons/react";
5
- import { S as F } from "./surface-BIC6CXiz.js";
6
- import { L as G } from "./loader-DHGMYlC6.js";
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, bj as B, ap as S, au as J, av as Q, aw as W } from "./vendor-base-ui-DvXlzG7n.js";
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
- F,
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
- j,
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(G, { size: 24 }) });
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-xctZ--ZT.js.map
399
+ //# sourceMappingURL=command-palette-B_J7o7P-.js.map