@devalok/shilp-sutra 0.49.4 → 0.50.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 (243) hide show
  1. package/AGENTS.md +12 -4
  2. package/MIGRATION.md +6 -0
  3. package/dist/_chunks/badge-group.js +12 -11
  4. package/dist/_chunks/badge-group.js.map +1 -1
  5. package/dist/_chunks/block-shell.js +1 -1
  6. package/dist/_chunks/block-shell.js.map +1 -1
  7. package/dist/_chunks/chat.js +18 -18
  8. package/dist/_chunks/chat.js.map +1 -1
  9. package/dist/_chunks/document-preview.js +1 -1
  10. package/dist/_chunks/document-preview.js.map +1 -1
  11. package/dist/_chunks/emoji-suggestion.js +1 -1
  12. package/dist/_chunks/emoji-suggestion.js.map +1 -1
  13. package/dist/_chunks/grid-lines.js +2 -2
  14. package/dist/_chunks/grid-lines.js.map +1 -1
  15. package/dist/_chunks/image-preview.js +1 -1
  16. package/dist/_chunks/image-preview.js.map +1 -1
  17. package/dist/_chunks/mention-suggestion.js +2 -2
  18. package/dist/_chunks/mention-suggestion.js.map +1 -1
  19. package/dist/_chunks/oauth-button.js +8 -8
  20. package/dist/_chunks/oauth-button.js.map +1 -1
  21. package/dist/_chunks/shared.js +2 -2
  22. package/dist/_chunks/shared.js.map +1 -1
  23. package/dist/_chunks/success.js +5 -5
  24. package/dist/_chunks/success.js.map +1 -1
  25. package/dist/_chunks/tiptap.js +3956 -1796
  26. package/dist/_chunks/tiptap.js.map +1 -1
  27. package/dist/_chunks/tooltip.js +2 -2
  28. package/dist/_chunks/tooltip.js.map +1 -1
  29. package/dist/_chunks/tree-view.js +2 -2
  30. package/dist/_chunks/tree-view.js.map +1 -1
  31. package/dist/_chunks/use-calendar.js +3 -3
  32. package/dist/_chunks/use-calendar.js.map +1 -1
  33. package/dist/ai/block-renderer.js +1 -1
  34. package/dist/ai/block-renderer.js.map +1 -1
  35. package/dist/ai/blocks/error.js +1 -1
  36. package/dist/ai/blocks/error.js.map +1 -1
  37. package/dist/ai/command-bar.js +15 -15
  38. package/dist/ai/command-bar.js.map +1 -1
  39. package/dist/ai/conversation.js +6 -6
  40. package/dist/ai/conversation.js.map +1 -1
  41. package/dist/composed/activity-feed.js +4 -4
  42. package/dist/composed/activity-feed.js.map +1 -1
  43. package/dist/composed/avatar-group.js +6 -6
  44. package/dist/composed/avatar-group.js.map +1 -1
  45. package/dist/composed/bulk-action-bar.js +1 -1
  46. package/dist/composed/bulk-action-bar.js.map +1 -1
  47. package/dist/composed/command-palette.js +12 -12
  48. package/dist/composed/command-palette.js.map +1 -1
  49. package/dist/composed/content-card.js +1 -1
  50. package/dist/composed/content-card.js.map +1 -1
  51. package/dist/composed/date-picker/index.js +17 -17
  52. package/dist/composed/date-picker/index.js.map +1 -1
  53. package/dist/composed/deadline-indicator.js +2 -2
  54. package/dist/composed/deadline-indicator.js.map +1 -1
  55. package/dist/composed/diff.d.ts +108 -0
  56. package/dist/composed/diff.d.ts.map +1 -0
  57. package/dist/composed/diff.js +1004 -0
  58. package/dist/composed/diff.js.map +1 -0
  59. package/dist/composed/emoji-picker.js +6 -6
  60. package/dist/composed/emoji-picker.js.map +1 -1
  61. package/dist/composed/empty-state.js +2 -2
  62. package/dist/composed/empty-state.js.map +1 -1
  63. package/dist/composed/error-boundary.js +6 -6
  64. package/dist/composed/error-boundary.js.map +1 -1
  65. package/dist/composed/file-preview.js +5 -5
  66. package/dist/composed/file-preview.js.map +1 -1
  67. package/dist/composed/filter-bar.js +3 -3
  68. package/dist/composed/filter-bar.js.map +1 -1
  69. package/dist/composed/form-section.js +2 -2
  70. package/dist/composed/form-section.js.map +1 -1
  71. package/dist/composed/inline-edit.d.ts +1 -1
  72. package/dist/composed/inline-edit.d.ts.map +1 -1
  73. package/dist/composed/inline-edit.js.map +1 -1
  74. package/dist/composed/loading-skeleton.js +3 -3
  75. package/dist/composed/loading-skeleton.js.map +1 -1
  76. package/dist/composed/markdown-viewer.js +11 -11
  77. package/dist/composed/markdown-viewer.js.map +1 -1
  78. package/dist/composed/master-detail.js +1 -1
  79. package/dist/composed/master-detail.js.map +1 -1
  80. package/dist/composed/member-picker.js +2 -2
  81. package/dist/composed/member-picker.js.map +1 -1
  82. package/dist/composed/multi-select-popover.js +5 -5
  83. package/dist/composed/multi-select-popover.js.map +1 -1
  84. package/dist/composed/page-header.js +3 -3
  85. package/dist/composed/page-header.js.map +1 -1
  86. package/dist/composed/page-skeletons.js +4 -4
  87. package/dist/composed/page-skeletons.js.map +1 -1
  88. package/dist/composed/priority-indicator.js +1 -1
  89. package/dist/composed/priority-indicator.js.map +1 -1
  90. package/dist/composed/responsive-modal.js +2 -2
  91. package/dist/composed/responsive-modal.js.map +1 -1
  92. package/dist/composed/rich-chat-input.js +27 -27
  93. package/dist/composed/rich-chat-input.js.map +1 -1
  94. package/dist/composed/rich-text-editor.d.ts +81 -6
  95. package/dist/composed/rich-text-editor.d.ts.map +1 -1
  96. package/dist/composed/rich-text-editor.js +365 -210
  97. package/dist/composed/rich-text-editor.js.map +1 -1
  98. package/dist/composed/schedule-view.js +4 -4
  99. package/dist/composed/schedule-view.js.map +1 -1
  100. package/dist/shell/bottom-navbar.js +4 -4
  101. package/dist/shell/bottom-navbar.js.map +1 -1
  102. package/dist/shell/notification-center.js +13 -13
  103. package/dist/shell/notification-center.js.map +1 -1
  104. package/dist/shell/notification-preferences.js +10 -10
  105. package/dist/shell/notification-preferences.js.map +1 -1
  106. package/dist/shell/sidebar.js +9 -9
  107. package/dist/shell/sidebar.js.map +1 -1
  108. package/dist/shell/top-bar.js +8 -8
  109. package/dist/shell/top-bar.js.map +1 -1
  110. package/dist/tokens/semantic.css +6 -1
  111. package/dist/tokens/typography-semantic.css +6 -6
  112. package/dist/tokens/utilities.css +8 -0
  113. package/dist/ui/accordion.js +2 -2
  114. package/dist/ui/accordion.js.map +1 -1
  115. package/dist/ui/alert-dialog.js +4 -4
  116. package/dist/ui/alert-dialog.js.map +1 -1
  117. package/dist/ui/alert.js +1 -1
  118. package/dist/ui/alert.js.map +1 -1
  119. package/dist/ui/autocomplete.d.ts.map +1 -1
  120. package/dist/ui/autocomplete.js +11 -3
  121. package/dist/ui/autocomplete.js.map +1 -1
  122. package/dist/ui/avatar.js +5 -5
  123. package/dist/ui/avatar.js.map +1 -1
  124. package/dist/ui/badge-group.d.ts +2 -6
  125. package/dist/ui/badge-group.d.ts.map +1 -1
  126. package/dist/ui/badge-indicator.d.ts +2 -6
  127. package/dist/ui/badge-indicator.d.ts.map +1 -1
  128. package/dist/ui/badge-indicator.js +19 -18
  129. package/dist/ui/badge-indicator.js.map +1 -1
  130. package/dist/ui/badge.d.ts +2 -4
  131. package/dist/ui/badge.d.ts.map +1 -1
  132. package/dist/ui/banner.js +1 -1
  133. package/dist/ui/banner.js.map +1 -1
  134. package/dist/ui/breadcrumb.js +1 -1
  135. package/dist/ui/breadcrumb.js.map +1 -1
  136. package/dist/ui/button.js +7 -7
  137. package/dist/ui/button.js.map +1 -1
  138. package/dist/ui/card.d.ts +1 -1
  139. package/dist/ui/card.js +1 -1
  140. package/dist/ui/card.js.map +1 -1
  141. package/dist/ui/charts/gauge-chart.js +2 -2
  142. package/dist/ui/charts/gauge-chart.js.map +1 -1
  143. package/dist/ui/charts/pie-chart.js +1 -1
  144. package/dist/ui/charts/pie-chart.js.map +1 -1
  145. package/dist/ui/charts/radar-chart.d.ts +19 -1
  146. package/dist/ui/charts/radar-chart.d.ts.map +1 -1
  147. package/dist/ui/charts/radar-chart.js +80 -42
  148. package/dist/ui/charts/radar-chart.js.map +1 -1
  149. package/dist/ui/code.js +2 -2
  150. package/dist/ui/code.js.map +1 -1
  151. package/dist/ui/color-input.d.ts.map +1 -1
  152. package/dist/ui/color-input.js +164 -157
  153. package/dist/ui/color-input.js.map +1 -1
  154. package/dist/ui/combobox.d.ts.map +1 -1
  155. package/dist/ui/combobox.js +143 -142
  156. package/dist/ui/combobox.js.map +1 -1
  157. package/dist/ui/context-menu.js +6 -6
  158. package/dist/ui/context-menu.js.map +1 -1
  159. package/dist/ui/data-table-body.js +1 -1
  160. package/dist/ui/data-table-body.js.map +1 -1
  161. package/dist/ui/data-table-bulk-actions.js +1 -1
  162. package/dist/ui/data-table-bulk-actions.js.map +1 -1
  163. package/dist/ui/data-table-card.js +1 -1
  164. package/dist/ui/data-table-card.js.map +1 -1
  165. package/dist/ui/data-table-header.js +1 -1
  166. package/dist/ui/data-table-header.js.map +1 -1
  167. package/dist/ui/data-table-pagination.js +3 -3
  168. package/dist/ui/data-table-pagination.js.map +1 -1
  169. package/dist/ui/data-table-toolbar.js +1 -1
  170. package/dist/ui/data-table-toolbar.js.map +1 -1
  171. package/dist/ui/data-table.js +1 -1
  172. package/dist/ui/data-table.js.map +1 -1
  173. package/dist/ui/dialog.js +2 -2
  174. package/dist/ui/dialog.js.map +1 -1
  175. package/dist/ui/dot.js +4 -4
  176. package/dist/ui/dot.js.map +1 -1
  177. package/dist/ui/dropdown-menu.js +6 -6
  178. package/dist/ui/dropdown-menu.js.map +1 -1
  179. package/dist/ui/file-upload.js +5 -5
  180. package/dist/ui/file-upload.js.map +1 -1
  181. package/dist/ui/form.js +1 -1
  182. package/dist/ui/form.js.map +1 -1
  183. package/dist/ui/input-otp.d.ts.map +1 -1
  184. package/dist/ui/input-otp.js +3 -3
  185. package/dist/ui/input-otp.js.map +1 -1
  186. package/dist/ui/input.js +8 -8
  187. package/dist/ui/input.js.map +1 -1
  188. package/dist/ui/label.js +1 -1
  189. package/dist/ui/label.js.map +1 -1
  190. package/dist/ui/lib/utils.d.ts.map +1 -1
  191. package/dist/ui/lib/utils.js +42 -13
  192. package/dist/ui/lib/utils.js.map +1 -1
  193. package/dist/ui/menubar.js +7 -7
  194. package/dist/ui/menubar.js.map +1 -1
  195. package/dist/ui/navigation-menu.js +1 -1
  196. package/dist/ui/navigation-menu.js.map +1 -1
  197. package/dist/ui/number-input.d.ts.map +1 -1
  198. package/dist/ui/number-input.js +6 -5
  199. package/dist/ui/number-input.js.map +1 -1
  200. package/dist/ui/pagination.js +1 -1
  201. package/dist/ui/pagination.js.map +1 -1
  202. package/dist/ui/progress-ring.js +3 -3
  203. package/dist/ui/progress-ring.js.map +1 -1
  204. package/dist/ui/progress.js +2 -2
  205. package/dist/ui/progress.js.map +1 -1
  206. package/dist/ui/segmented-control.js +3 -3
  207. package/dist/ui/segmented-control.js.map +1 -1
  208. package/dist/ui/select.d.ts.map +1 -1
  209. package/dist/ui/select.js +7 -6
  210. package/dist/ui/select.js.map +1 -1
  211. package/dist/ui/sheet.js +2 -2
  212. package/dist/ui/sheet.js.map +1 -1
  213. package/dist/ui/sidebar.js +7 -7
  214. package/dist/ui/sidebar.js.map +1 -1
  215. package/dist/ui/split-button.js +6 -6
  216. package/dist/ui/split-button.js.map +1 -1
  217. package/dist/ui/stat-card.d.ts +1 -1
  218. package/dist/ui/stat-card.js +7 -7
  219. package/dist/ui/stat-card.js.map +1 -1
  220. package/dist/ui/stepper.js +3 -3
  221. package/dist/ui/stepper.js.map +1 -1
  222. package/dist/ui/table.js +3 -3
  223. package/dist/ui/table.js.map +1 -1
  224. package/dist/ui/tabs.js +3 -3
  225. package/dist/ui/tabs.js.map +1 -1
  226. package/dist/ui/text.d.ts.map +1 -1
  227. package/dist/ui/text.js.map +1 -1
  228. package/dist/ui/textarea.d.ts.map +1 -1
  229. package/dist/ui/textarea.js +7 -6
  230. package/dist/ui/textarea.js.map +1 -1
  231. package/dist/ui/toast.js +11 -11
  232. package/dist/ui/toast.js.map +1 -1
  233. package/dist/ui/toggle.js +3 -3
  234. package/dist/ui/toggle.js.map +1 -1
  235. package/dist/ui/tooltip.js +1 -1
  236. package/dist/ui/tooltip.js.map +1 -1
  237. package/docs/components/composed/diff.md +50 -0
  238. package/docs/components/ui/data-table.md +2 -2
  239. package/llms.txt +2 -1
  240. package/mcp-manifest.json +147 -3
  241. package/package.json +8 -1
  242. package/skill/SKILL.md +1 -1
  243. package/skill/references/components.md +2 -1
@@ -31,7 +31,7 @@ var f = a.forwardRef(function({ action: t, tabIndex: n }, r) {
31
31
  tabIndex: n,
32
32
  children: [
33
33
  /* @__PURE__ */ o("span", {
34
- className: "text-ds-sm text-surface-fg-muted whitespace-nowrap",
34
+ className: "text-body-sm text-surface-fg-muted whitespace-nowrap",
35
35
  children: t.confirmMessage ?? "Are you sure?"
36
36
  }),
37
37
  /* @__PURE__ */ o(i, {
@@ -1 +1 @@
1
- {"version":3,"file":"bulk-action-bar.js","names":[],"sources":["../../src/composed/bulk-action-bar.tsx"],"sourcesContent":["'use client'\n\nimport { IconX } from '@tabler/icons-react'\nimport { AnimatePresence, motion } from 'framer-motion'\nimport * as React from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { Badge } from '../ui/badge'\nimport { Button } from '../ui/button'\nimport { Icon } from '../ui/icon'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { springs } from '../ui/lib/motion'\nimport { cn } from '../ui/lib/utils'\n\n// ============================================================\n// Types\n// ============================================================\n\nexport interface BulkActionBarAction {\n label: string\n icon?: IconInput\n onClick: () => void\n color?: 'accent' | 'error'\n disabled?: boolean\n /** Show inline confirmation before executing the action */\n requiresConfirmation?: boolean\n /** Custom confirmation message @default 'Are you sure?' */\n confirmMessage?: string\n}\n\nexport interface BulkActionBarProps {\n show: boolean\n count: number\n onClearSelection: () => void\n actions: BulkActionBarAction[]\n /** Total number of items available for selection */\n totalCount?: number\n /** Called when user clicks \"Select all\" */\n onSelectAll?: () => void\n className?: string\n}\n\n// ============================================================\n// ActionButton — handles inline confirmation\n// ============================================================\n\nconst ActionButton = React.forwardRef<HTMLDivElement, { action: BulkActionBarAction; tabIndex?: number }>(function ActionButton({ action, tabIndex }, ref) {\n const [confirming, setConfirming] = React.useState(false)\n\n if (confirming) {\n return (\n <motion.div\n ref={ref}\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.95 }}\n transition={springs.snappy}\n className=\"flex items-center gap-ds-02\"\n tabIndex={tabIndex}\n >\n <span className=\"text-ds-sm text-surface-fg-muted whitespace-nowrap\">\n {action.confirmMessage ?? 'Are you sure?'}\n </span>\n <Button\n variant=\"solid\"\n size=\"sm\"\n color=\"error\"\n onClick={() => {\n setConfirming(false)\n action.onClick()\n }}\n >\n Confirm\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setConfirming(false)}\n >\n Cancel\n </Button>\n </motion.div>\n )\n }\n\n return (\n <motion.div\n ref={ref}\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.95 }}\n transition={springs.snappy}\n tabIndex={tabIndex}\n >\n <Button\n variant=\"ghost\"\n size=\"sm\"\n color={action.color === 'error' ? 'error' : 'accent'}\n disabled={action.disabled}\n onClick={action.requiresConfirmation ? () => setConfirming(true) : action.onClick}\n startIcon={action.icon ?? undefined}\n tabIndex={-1}\n >\n {action.label}\n </Button>\n </motion.div>\n )\n})\n\n// ============================================================\n// BulkActionBar\n// ============================================================\n\nfunction BulkActionBar({\n show,\n count,\n onClearSelection,\n actions,\n totalCount,\n onSelectAll,\n className,\n}: BulkActionBarProps) {\n const [mounted, setMounted] = React.useState(false)\n const [focusedIndex, setFocusedIndex] = React.useState(0)\n const actionRefs = React.useRef<(HTMLDivElement | null)[]>([])\n\n // Reset focused index when actions change\n React.useEffect(() => {\n setFocusedIndex(0)\n }, [actions.length])\n\n React.useEffect(() => {\n setMounted(true)\n }, [])\n\n function handleKeyDown(e: React.KeyboardEvent) {\n if (e.key === 'Escape') {\n e.preventDefault()\n onClearSelection()\n return\n }\n\n const count = actions.length\n if (count === 0) return\n\n if (e.key === 'ArrowRight') {\n e.preventDefault()\n const next = (focusedIndex + 1) % count\n setFocusedIndex(next)\n actionRefs.current[next]?.focus()\n } else if (e.key === 'ArrowLeft') {\n e.preventDefault()\n const prev = (focusedIndex - 1 + count) % count\n setFocusedIndex(prev)\n actionRefs.current[prev]?.focus()\n } else if (e.key === 'Home') {\n e.preventDefault()\n setFocusedIndex(0)\n actionRefs.current[0]?.focus()\n } else if (e.key === 'End') {\n e.preventDefault()\n const last = count - 1\n setFocusedIndex(last)\n actionRefs.current[last]?.focus()\n }\n }\n\n if (!mounted) return null\n\n return createPortal(\n <AnimatePresence>\n {show && (\n <motion.div\n initial={{ y: 100, opacity: 0 }}\n animate={{ y: 0, opacity: 1 }}\n exit={{ y: 100, opacity: 0 }}\n transition={springs.snappy}\n className={cn(\n 'fixed bottom-ds-06 left-1/2 z-sticky -translate-x-1/2',\n 'flex items-center gap-ds-04 rounded-surface bg-surface-overlay px-ds-05 py-ds-03 shadow-floating',\n className,\n )}\n role=\"toolbar\"\n aria-label={`${count} items selected`}\n onKeyDown={handleKeyDown}\n >\n <Badge variant=\"solid\" size=\"sm\">\n {count} selected\n </Badge>\n\n {totalCount != null && totalCount > count && onSelectAll && (\n <Button variant=\"link\" size=\"xs\" onClick={onSelectAll}>\n Select all {totalCount}\n </Button>\n )}\n\n <div className=\"flex items-center gap-ds-02\">\n <AnimatePresence mode=\"popLayout\">\n {actions.map((action, i) => (\n <ActionButton\n key={action.label}\n ref={(el: HTMLDivElement | null) => { actionRefs.current[i] = el }}\n action={action}\n tabIndex={i === focusedIndex ? 0 : -1}\n />\n ))}\n </AnimatePresence>\n </div>\n\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={onClearSelection}\n aria-label=\"Clear selection\"\n >\n <Icon icon={IconX} size=\"sm\" />\n </Button>\n </motion.div>\n )}\n </AnimatePresence>,\n document.body,\n )\n}\n\nBulkActionBar.displayName = 'BulkActionBar'\n\nexport { BulkActionBar }\n"],"mappings":";;;;;;;;;;;;AA8CA,IAAM,IAAe,EAAM,WAA+E,SAAsB,EAAE,WAAQ,eAAY,GAAK;CACzJ,IAAM,CAAC,GAAY,KAAiB,EAAM,SAAS,EAAK;CAsCxD,OApCI,IAEA,kBAAC,EAAO,KAAR;EACO;EACL,SAAS;GAAE,SAAS;GAAG,OAAO;EAAK;EACnC,SAAS;GAAE,SAAS;GAAG,OAAO;EAAE;EAChC,MAAM;GAAE,SAAS;GAAG,OAAO;EAAK;EAChC,YAAY,EAAQ;EACpB,WAAU;EACA;YAPZ;GASE,kBAAC,QAAD;IAAM,WAAU;cACb,EAAO,kBAAkB;GACtB,CAAA;GACN,kBAAC,GAAD;IACE,SAAQ;IACR,MAAK;IACL,OAAM;IACN,eAAe;KAEb,AADA,EAAc,EAAK,GACnB,EAAO,QAAQ;IACjB;cACD;GAEO,CAAA;GACR,kBAAC,GAAD;IACE,SAAQ;IACR,MAAK;IACL,eAAe,EAAc,EAAK;cACnC;GAEO,CAAA;EACE;MAKd,kBAAC,EAAO,KAAR;EACO;EACL,SAAS;GAAE,SAAS;GAAG,OAAO;EAAK;EACnC,SAAS;GAAE,SAAS;GAAG,OAAO;EAAE;EAChC,MAAM;GAAE,SAAS;GAAG,OAAO;EAAK;EAChC,YAAY,EAAQ;EACV;YAEV,kBAAC,GAAD;GACE,SAAQ;GACR,MAAK;GACL,OAAO,EAAO,UAAU,UAAU,UAAU;GAC5C,UAAU,EAAO;GACjB,SAAS,EAAO,6BAA6B,EAAc,EAAI,IAAI,EAAO;GAC1E,WAAW,EAAO,QAAQ,KAAA;GAC1B,UAAU;aAET,EAAO;EACF,CAAA;CACE,CAAA;AAEhB,CAAC;AAMD,SAAS,EAAc,EACrB,SACA,UACA,qBACA,YACA,eACA,gBACA,gBACqB;CACrB,IAAM,CAAC,GAAS,KAAc,EAAM,SAAS,EAAK,GAC5C,CAAC,GAAc,KAAmB,EAAM,SAAS,CAAC,GAClD,IAAa,EAAM,OAAkC,CAAC,CAAC;CAO7D,AAJA,EAAM,gBAAgB;EACpB,EAAgB,CAAC;CACnB,GAAG,CAAC,EAAQ,MAAM,CAAC,GAEnB,EAAM,gBAAgB;EACpB,EAAW,EAAI;CACjB,GAAG,CAAC,CAAC;CAEL,SAAS,EAAc,GAAwB;EAC7C,IAAI,EAAE,QAAQ,UAAU;GAEtB,AADA,EAAE,eAAe,GACjB,EAAiB;GACjB;EACF;EAEA,IAAM,IAAQ,EAAQ;EAClB,UAAU,GAEd;OAAI,EAAE,QAAQ,cAAc;IAC1B,EAAE,eAAe;IACjB,IAAM,KAAQ,IAAe,KAAK;IAElC,AADA,EAAgB,CAAI,GACpB,EAAW,QAAQ,EAAK,EAAE,MAAM;GAClC,OAAO,IAAI,EAAE,QAAQ,aAAa;IAChC,EAAE,eAAe;IACjB,IAAM,KAAQ,IAAe,IAAI,KAAS;IAE1C,AADA,EAAgB,CAAI,GACpB,EAAW,QAAQ,EAAK,EAAE,MAAM;GAClC,OAAO,IAAI,EAAE,QAAQ,QAGnB,AAFA,EAAE,eAAe,GACjB,EAAgB,CAAC,GACjB,EAAW,QAAQ,EAAE,EAAE,MAAM;QACxB,IAAI,EAAE,QAAQ,OAAO;IAC1B,EAAE,eAAe;IACjB,IAAM,IAAO,IAAQ;IAErB,AADA,EAAgB,CAAI,GACpB,EAAW,QAAQ,EAAK,EAAE,MAAM;GAClC;;CACF;CAIA,OAFK,IAEE,EACL,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,EAAO,KAAR;EACE,SAAS;GAAE,GAAG;GAAK,SAAS;EAAE;EAC9B,SAAS;GAAE,GAAG;GAAG,SAAS;EAAE;EAC5B,MAAM;GAAE,GAAG;GAAK,SAAS;EAAE;EAC3B,YAAY,EAAQ;EACpB,WAAW,EACT,yDACA,oGACA,CACF;EACA,MAAK;EACL,cAAY,GAAG,EAAM;EACrB,WAAW;YAZb;GAcE,kBAAC,GAAD;IAAO,SAAQ;IAAQ,MAAK;cAA5B,CACG,GAAM,WACF;;GAEN,KAAc,QAAQ,IAAa,KAAS,KAC3C,kBAAC,GAAD;IAAQ,SAAQ;IAAO,MAAK;IAAK,SAAS;cAA1C,CAAuD,eACzC,CACN;;GAGV,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KAAiB,MAAK;eACnB,EAAQ,KAAK,GAAQ,MACpB,kBAAC,GAAD;MAEE,MAAM,MAA8B;OAAE,EAAW,QAAQ,KAAK;MAAG;MACzD;MACR,UAAU,MAAM,IAAe,IAAI;KACpC,GAJM,EAAO,KAIb,CACF;IACc,CAAA;GACd,CAAA;GAEL,kBAAC,GAAD;IACE,SAAQ;IACR,MAAK;IACL,SAAS;IACT,cAAW;cAEX,kBAAC,GAAD;KAAM,MAAM;KAAO,MAAK;IAAM,CAAA;GACxB,CAAA;EACE;IAEC,CAAA,GACjB,SAAS,IACX,IAtDqB;AAuDvB;AAEA,EAAc,cAAc"}
1
+ {"version":3,"file":"bulk-action-bar.js","names":[],"sources":["../../src/composed/bulk-action-bar.tsx"],"sourcesContent":["'use client'\n\nimport { IconX } from '@tabler/icons-react'\nimport { AnimatePresence, motion } from 'framer-motion'\nimport * as React from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { Badge } from '../ui/badge'\nimport { Button } from '../ui/button'\nimport { Icon } from '../ui/icon'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { springs } from '../ui/lib/motion'\nimport { cn } from '../ui/lib/utils'\n\n// ============================================================\n// Types\n// ============================================================\n\nexport interface BulkActionBarAction {\n label: string\n icon?: IconInput\n onClick: () => void\n color?: 'accent' | 'error'\n disabled?: boolean\n /** Show inline confirmation before executing the action */\n requiresConfirmation?: boolean\n /** Custom confirmation message @default 'Are you sure?' */\n confirmMessage?: string\n}\n\nexport interface BulkActionBarProps {\n show: boolean\n count: number\n onClearSelection: () => void\n actions: BulkActionBarAction[]\n /** Total number of items available for selection */\n totalCount?: number\n /** Called when user clicks \"Select all\" */\n onSelectAll?: () => void\n className?: string\n}\n\n// ============================================================\n// ActionButton — handles inline confirmation\n// ============================================================\n\nconst ActionButton = React.forwardRef<HTMLDivElement, { action: BulkActionBarAction; tabIndex?: number }>(function ActionButton({ action, tabIndex }, ref) {\n const [confirming, setConfirming] = React.useState(false)\n\n if (confirming) {\n return (\n <motion.div\n ref={ref}\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.95 }}\n transition={springs.snappy}\n className=\"flex items-center gap-ds-02\"\n tabIndex={tabIndex}\n >\n <span className=\"text-body-sm text-surface-fg-muted whitespace-nowrap\">\n {action.confirmMessage ?? 'Are you sure?'}\n </span>\n <Button\n variant=\"solid\"\n size=\"sm\"\n color=\"error\"\n onClick={() => {\n setConfirming(false)\n action.onClick()\n }}\n >\n Confirm\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setConfirming(false)}\n >\n Cancel\n </Button>\n </motion.div>\n )\n }\n\n return (\n <motion.div\n ref={ref}\n initial={{ opacity: 0, scale: 0.95 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.95 }}\n transition={springs.snappy}\n tabIndex={tabIndex}\n >\n <Button\n variant=\"ghost\"\n size=\"sm\"\n color={action.color === 'error' ? 'error' : 'accent'}\n disabled={action.disabled}\n onClick={action.requiresConfirmation ? () => setConfirming(true) : action.onClick}\n startIcon={action.icon ?? undefined}\n tabIndex={-1}\n >\n {action.label}\n </Button>\n </motion.div>\n )\n})\n\n// ============================================================\n// BulkActionBar\n// ============================================================\n\nfunction BulkActionBar({\n show,\n count,\n onClearSelection,\n actions,\n totalCount,\n onSelectAll,\n className,\n}: BulkActionBarProps) {\n const [mounted, setMounted] = React.useState(false)\n const [focusedIndex, setFocusedIndex] = React.useState(0)\n const actionRefs = React.useRef<(HTMLDivElement | null)[]>([])\n\n // Reset focused index when actions change\n React.useEffect(() => {\n setFocusedIndex(0)\n }, [actions.length])\n\n React.useEffect(() => {\n setMounted(true)\n }, [])\n\n function handleKeyDown(e: React.KeyboardEvent) {\n if (e.key === 'Escape') {\n e.preventDefault()\n onClearSelection()\n return\n }\n\n const count = actions.length\n if (count === 0) return\n\n if (e.key === 'ArrowRight') {\n e.preventDefault()\n const next = (focusedIndex + 1) % count\n setFocusedIndex(next)\n actionRefs.current[next]?.focus()\n } else if (e.key === 'ArrowLeft') {\n e.preventDefault()\n const prev = (focusedIndex - 1 + count) % count\n setFocusedIndex(prev)\n actionRefs.current[prev]?.focus()\n } else if (e.key === 'Home') {\n e.preventDefault()\n setFocusedIndex(0)\n actionRefs.current[0]?.focus()\n } else if (e.key === 'End') {\n e.preventDefault()\n const last = count - 1\n setFocusedIndex(last)\n actionRefs.current[last]?.focus()\n }\n }\n\n if (!mounted) return null\n\n return createPortal(\n <AnimatePresence>\n {show && (\n <motion.div\n initial={{ y: 100, opacity: 0 }}\n animate={{ y: 0, opacity: 1 }}\n exit={{ y: 100, opacity: 0 }}\n transition={springs.snappy}\n className={cn(\n 'fixed bottom-ds-06 left-1/2 z-sticky -translate-x-1/2',\n 'flex items-center gap-ds-04 rounded-surface bg-surface-overlay px-ds-05 py-ds-03 shadow-floating',\n className,\n )}\n role=\"toolbar\"\n aria-label={`${count} items selected`}\n onKeyDown={handleKeyDown}\n >\n <Badge variant=\"solid\" size=\"sm\">\n {count} selected\n </Badge>\n\n {totalCount != null && totalCount > count && onSelectAll && (\n <Button variant=\"link\" size=\"xs\" onClick={onSelectAll}>\n Select all {totalCount}\n </Button>\n )}\n\n <div className=\"flex items-center gap-ds-02\">\n <AnimatePresence mode=\"popLayout\">\n {actions.map((action, i) => (\n <ActionButton\n key={action.label}\n ref={(el: HTMLDivElement | null) => { actionRefs.current[i] = el }}\n action={action}\n tabIndex={i === focusedIndex ? 0 : -1}\n />\n ))}\n </AnimatePresence>\n </div>\n\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={onClearSelection}\n aria-label=\"Clear selection\"\n >\n <Icon icon={IconX} size=\"sm\" />\n </Button>\n </motion.div>\n )}\n </AnimatePresence>,\n document.body,\n )\n}\n\nBulkActionBar.displayName = 'BulkActionBar'\n\nexport { BulkActionBar }\n"],"mappings":"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"}
@@ -140,13 +140,13 @@ var b = m.forwardRef(function({ groups: b = [], placeholder: x = "Search or jump
140
140
  "aria-controls": K,
141
141
  "aria-activedescendant": X[V] ? `command-item-${G}-${X[V].id}` : void 0,
142
142
  "aria-autocomplete": "list",
143
- className: r("flex-1 bg-transparent text-ds-base text-surface-fg outline-hidden", "placeholder:text-surface-fg-subtle"),
143
+ className: r("flex-1 bg-transparent text-body-lg text-surface-fg outline-hidden", "placeholder:text-surface-fg-subtle"),
144
144
  autoComplete: "off",
145
145
  autoCorrect: "off",
146
146
  spellCheck: !1
147
147
  }),
148
148
  /* @__PURE__ */ h("kbd", {
149
- className: "hidden shrink-0 select-none rounded-control border border-surface-border-strong bg-surface-raised px-ds-02b py-ds-01 text-ds-sm font-medium text-surface-fg-subtle shadow-kbd sm:inline-flex",
149
+ className: "hidden shrink-0 select-none rounded-control border border-card-strong bg-surface-raised px-ds-02b py-ds-01 text-body-sm font-medium text-surface-fg-subtle shadow-kbd sm:inline-flex",
150
150
  children: "Esc"
151
151
  })
152
152
  ]
@@ -164,7 +164,7 @@ var b = m.forwardRef(function({ groups: b = [], placeholder: x = "Search or jump
164
164
  transition: Z,
165
165
  className: "flex items-center justify-center py-ds-07",
166
166
  children: C ?? /* @__PURE__ */ h("p", {
167
- className: "text-ds-md text-surface-fg-subtle",
167
+ className: "text-body-md text-surface-fg-subtle",
168
168
  children: S
169
169
  })
170
170
  }), Y.map((o, s) => /* @__PURE__ */ g(v.div, {
@@ -178,7 +178,7 @@ var b = m.forwardRef(function({ groups: b = [], placeholder: x = "Search or jump
178
178
  children: [/* @__PURE__ */ h("div", {
179
179
  className: "px-ds-03 pb-ds-02 pt-ds-03",
180
180
  children: /* @__PURE__ */ h("span", {
181
- className: "text-ds-xs font-semibold uppercase tracking-wider text-surface-fg-subtle",
181
+ className: "text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle",
182
182
  children: o.label
183
183
  })
184
184
  }), o.items.map((n) => {
@@ -218,17 +218,17 @@ var b = m.forwardRef(function({ groups: b = [], placeholder: x = "Search or jump
218
218
  /* @__PURE__ */ g("div", {
219
219
  className: "flex min-w-0 flex-1 flex-col",
220
220
  children: [/* @__PURE__ */ h("span", {
221
- className: "truncate text-ds-md",
221
+ className: "truncate text-body-md",
222
222
  children: n.renderLabel ? n.renderLabel(z) : n.label
223
223
  }), n.description && /* @__PURE__ */ h("span", {
224
- className: "line-clamp-1 text-ds-sm text-surface-fg-subtle",
224
+ className: "line-clamp-1 text-body-sm text-surface-fg-subtle",
225
225
  children: n.description
226
226
  })]
227
227
  }),
228
228
  n.shortcut && /* @__PURE__ */ h("span", {
229
229
  className: "flex shrink-0 items-center gap-ds-01",
230
230
  children: y(n.shortcut).map((e, t) => /* @__PURE__ */ h("kbd", {
231
- className: r("inline-flex min-w-ds-05b items-center justify-center rounded border px-ds-02b py-ds-01 text-ds-xs font-medium shadow-kbd transition-colors duration-fast-02 ease-productive-standard", s ? "bg-accent-2 text-accent-11 border-accent-6" : "bg-surface-raised text-surface-fg-subtle border-surface-border-strong"),
231
+ className: r("inline-flex min-w-ds-05b items-center justify-center rounded border px-ds-02b py-ds-01 text-body-xs font-medium shadow-kbd transition-colors duration-fast-02 ease-productive-standard", s ? "bg-accent-2 text-accent-11 border-accent-6" : "bg-surface-raised text-surface-fg-subtle border-surface-border-strong"),
232
232
  children: e === "Ctrl" || e === "ctrl" ? f(ue) : e
233
233
  }, t))
234
234
  }),
@@ -260,14 +260,14 @@ var b = m.forwardRef(function({ groups: b = [], placeholder: x = "Search or jump
260
260
  children: [e.keys === "↑↓" ? /* @__PURE__ */ g("div", {
261
261
  className: "flex items-center gap-ds-01",
262
262
  children: [/* @__PURE__ */ h("kbd", {
263
- className: "inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-surface-border-strong bg-surface-raised shadow-kbd",
263
+ className: "inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd",
264
264
  children: /* @__PURE__ */ h(i, {
265
265
  icon: ie,
266
266
  size: "xs",
267
267
  className: "text-surface-fg-subtle"
268
268
  })
269
269
  }), /* @__PURE__ */ h("kbd", {
270
- className: "inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-surface-border-strong bg-surface-raised shadow-kbd",
270
+ className: "inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd",
271
271
  children: /* @__PURE__ */ h(i, {
272
272
  icon: re,
273
273
  size: "xs",
@@ -275,17 +275,17 @@ var b = m.forwardRef(function({ groups: b = [], placeholder: x = "Search or jump
275
275
  })
276
276
  })]
277
277
  }) : e.keys === "↵" ? /* @__PURE__ */ h("kbd", {
278
- className: "inline-flex h-ds-05b items-center justify-center rounded-control border border-surface-border-strong bg-surface-raised px-ds-02b shadow-kbd",
278
+ className: "inline-flex h-ds-05b items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b shadow-kbd",
279
279
  children: /* @__PURE__ */ h(i, {
280
280
  icon: _,
281
281
  size: "xs",
282
282
  className: "text-surface-fg-subtle"
283
283
  })
284
284
  }) : /* @__PURE__ */ h("kbd", {
285
- className: "inline-flex h-ds-05b items-center justify-center rounded-control border border-surface-border-strong bg-surface-raised px-ds-02b text-ds-xs font-medium text-surface-fg-subtle shadow-kbd",
285
+ className: "inline-flex h-ds-05b items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b text-caption font-medium text-surface-fg-subtle shadow-kbd",
286
286
  children: e.keys
287
287
  }), /* @__PURE__ */ h("span", {
288
- className: "text-ds-xs text-surface-fg-subtle",
288
+ className: "text-caption text-surface-fg-subtle",
289
289
  children: e.label
290
290
  })]
291
291
  }, t))
@@ -1 +1 @@
1
- {"version":3,"file":"command-palette.js","names":[],"sources":["../../src/composed/command-palette.tsx"],"sourcesContent":["'use client'\n\n/**\n * CommandPalette -- Keyboard-driven command palette (Ctrl+K / Cmd+K).\n *\n * Adapted from Karm V2. Uses ui/Dialog as the overlay.\n * All V1 color tokens replaced with semantic design-system tokens.\n */\nimport { IconArrowDown,IconArrowUp, IconCornerDownLeft, IconSearch } from '@tabler/icons-react'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useMotion } from '../motion/motion-provider'\nimport {\n Dialog,\n DialogContentRaw,\n DialogDescription,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n} from '../ui/dialog'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { springs,tweens } from '../ui/lib/motion'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport { VisuallyHidden } from '../ui/visually-hidden'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface CommandItem {\n id: string\n /** Display label — string or ReactNode. When ReactNode, provide `filterValue` for search filtering. */\n label: string | React.ReactNode\n /** Optional description — string or ReactNode. */\n description?: string | React.ReactNode\n icon?: IconInput\n /** Keyboard shortcut hint displayed as keycap badges (e.g., \"G D\", \"Ctrl+N\"). */\n shortcut?: string\n /** Custom render override for the label. Receives the current search query for match highlighting. */\n renderLabel?: (query: string) => React.ReactNode\n /** Plain-text value used for search filtering when `label` is a ReactNode. Falls back to `label` if string. */\n filterValue?: string\n onSelect: () => void\n}\n\nexport interface CommandGroup {\n label: string\n items: CommandItem[]\n}\n\n/** A single keyboard hint shown in the footer. */\nexport interface FooterHint {\n /** Key(s) to display — rendered as text inside `<kbd>` or as an icon. */\n keys: string\n /** Human-readable label for the hint (e.g., \"Navigate\", \"Select\"). */\n label: string\n}\n\n/**\n * A searchable command palette with keyboard navigation (Ctrl+K / Cmd+K).\n * Supports grouped items, custom keybindings, controlled/uncontrolled open state,\n * and custom empty states.\n */\nexport interface CommandPaletteProps extends React.ComponentPropsWithoutRef<'div'> {\n /** Item groups displayed in the palette. Each group has a label and an array of CommandItems. */\n groups?: CommandGroup[]\n /** Placeholder text for the search input. */\n placeholder?: string\n /** Called on every search input change with the current query string. */\n onSearch?: (query: string) => void\n /** Simple text shown when no results match. Overridden by `emptyState` if provided. */\n emptyMessage?: string\n /** Full custom empty state ReactNode — overrides `emptyMessage` when provided. */\n emptyState?: React.ReactNode\n // -- Controlled/uncontrolled open state (P1 #4) --\n /** Controlled open state. */\n open?: boolean\n /** Default open state for uncontrolled usage. */\n defaultOpen?: boolean\n /** Called when the open state changes. */\n onOpenChange?: (open: boolean) => void\n // -- Keyboard shortcut customization (P1 #6) --\n /** Keybinding(s) to toggle the palette. Pass `false` to disable.\n * String format: modifier+key, e.g., 'mod+k', 'ctrl+shift+p'.\n * 'mod' maps to Meta on macOS, Ctrl otherwise. */\n keybinding?: string | string[] | false\n // -- Configurable max-height (P2 #8) --\n /** Max height of the results container. CSS value. Default '320px'. */\n maxHeight?: string | number\n // -- Custom footer hints (P2 #11) --\n /** Custom footer keyboard hints. Pass `false` to hide the footer entirely. */\n footerHints?: FooterHint[] | false\n}\n\n// -----------------------------------------------------------------------\n// Helpers\n// -----------------------------------------------------------------------\n\nimport { getIsMac, getModifierDisplay,matchesKeybinding } from '../ui/lib/keybinding'\n\n/** Get the text-searchable value from a CommandItem. */\nfunction getFilterValue(item: CommandItem): string {\n if (item.filterValue) return item.filterValue\n if (typeof item.label === 'string') return item.label\n return ''\n}\n\n/** Get the text-searchable description from a CommandItem. */\nfunction getFilterDescription(item: CommandItem): string {\n if (typeof item.description === 'string') return item.description\n return ''\n}\n\n/** Parse a shortcut string like \"G D\" or \"Ctrl+N\" into individual keycap segments. */\nfunction parseShortcutKeys(shortcut: string): string[] {\n // If it has \"+\" separator (Ctrl+Shift+N style), split on +\n if (shortcut.includes('+')) {\n return shortcut.split('+').map(s => s.trim()).filter(Boolean)\n }\n // Otherwise split on spaces (G D style)\n return shortcut.split(/\\s+/).filter(Boolean)\n}\n\n// -----------------------------------------------------------------------\n// CommandPalette\n// -----------------------------------------------------------------------\n\nconst CommandPalette = React.forwardRef<HTMLDivElement, CommandPaletteProps>(\n function CommandPalette(\n {\n groups = [],\n placeholder = 'Search or jump to...',\n onSearch,\n emptyMessage = 'No results found.',\n emptyState,\n open: openProp,\n defaultOpen,\n onOpenChange,\n keybinding = 'mod+k',\n maxHeight = '320px',\n footerHints,\n className,\n ...props\n },\n ref,\n ) {\n // -- Controlled/uncontrolled open state --\n const isControlled = openProp !== undefined\n const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false)\n const open = isControlled ? openProp : internalOpen\n\n // Use a ref for the current open value to avoid stale closures in setOpen\n const openRef = React.useRef(open)\n openRef.current = open\n\n const setOpen = React.useCallback(\n (nextOpen: boolean | ((prev: boolean) => boolean)) => {\n const resolved = typeof nextOpen === 'function' ? nextOpen(openRef.current) : nextOpen\n if (!isControlled) {\n setInternalOpen(resolved)\n }\n onOpenChange?.(resolved)\n },\n [isControlled, onOpenChange],\n )\n\n const [query, setQuery] = React.useState('')\n const [activeIndex, setActiveIndex] = React.useState(0)\n const inputRef = React.useRef<HTMLInputElement>(null)\n const listRef = React.useRef<HTMLDivElement>(null)\n const instanceId = React.useId()\n const listboxId = `command-palette-listbox-${instanceId}`\n\n // -- Reduced motion (P2 #12) --\n const { reducedMotion: isReduced } = useMotion()\n const noMotionTransition = { duration: 0 }\n\n // -- Platform detection (P2 #13) --\n const isMac = React.useMemo(() => getIsMac(), [])\n\n // Filter groups based on query\n const filteredGroups = React.useMemo(() => {\n if (!query.trim()) return groups\n const q = query.toLowerCase()\n return groups\n .map((group) => ({\n ...group,\n items: group.items.filter(\n (item) =>\n getFilterValue(item).toLowerCase().includes(q) ||\n getFilterDescription(item).toLowerCase().includes(q),\n ),\n }))\n .filter((group) => group.items.length > 0)\n }, [groups, query])\n\n const filteredItems = React.useMemo(\n () => filteredGroups.flatMap((g) => g.items),\n [filteredGroups],\n )\n\n // Global keyboard shortcut\n React.useEffect(() => {\n if (keybinding === false) return\n\n const bindings = Array.isArray(keybinding) ? keybinding : [keybinding]\n\n function handleKeyDown(e: KeyboardEvent) {\n for (const binding of bindings) {\n if (matchesKeybinding(e, binding)) {\n e.preventDefault()\n setOpen((prev) => !prev)\n return\n }\n }\n }\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [keybinding, setOpen])\n\n // Reset state when opening\n React.useEffect(() => {\n if (open) {\n setQuery('')\n setActiveIndex(0)\n requestAnimationFrame(() => {\n inputRef.current?.focus()\n })\n }\n }, [open])\n\n // Keyboard navigation inside the palette\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n setActiveIndex((prev) =>\n prev < filteredItems.length - 1 ? prev + 1 : 0,\n )\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n setActiveIndex((prev) =>\n prev > 0 ? prev - 1 : filteredItems.length - 1,\n )\n break\n }\n case 'Enter': {\n e.preventDefault()\n const item = filteredItems[activeIndex]\n if (item) {\n item.onSelect()\n setOpen(false)\n }\n break\n }\n case 'Escape': {\n e.preventDefault()\n setOpen(false)\n break\n }\n }\n }\n\n // Scroll active item into view\n React.useEffect(() => {\n const activeEl = listRef.current?.querySelector(\n `[data-command-index=\"${activeIndex}\"]`,\n )\n activeEl?.scrollIntoView({ block: 'nearest' })\n }, [activeIndex])\n\n const handleQueryChange = (value: string) => {\n setQuery(value)\n setActiveIndex(0)\n onSearch?.(value)\n }\n\n // Build a map of item id -> flat index for keyboard navigation\n const itemIndexMap = React.useMemo(() => {\n const map = new Map<string, number>()\n let idx = 0\n for (const group of filteredGroups) {\n for (const item of group.items) {\n map.set(item.id, idx++)\n }\n }\n return map\n }, [filteredGroups])\n\n // -- Resolve motion transitions --\n const springSnappy = isReduced ? noMotionTransition : springs.snappy\n const tweenFade = isReduced ? noMotionTransition : tweens.fade\n const noInit = isReduced ? { opacity: 1, scale: 1, y: 0 } : undefined\n\n // -- Resolve max height CSS value --\n const maxHeightValue = typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight\n\n // -- Resolve footer hints --\n const resolvedFooterHints: FooterHint[] | false =\n footerHints === false\n ? false\n : footerHints ?? [\n { keys: '↑↓', label: 'Navigate' },\n { keys: '↵', label: 'Select' },\n { keys: 'Esc', label: 'Close' },\n ]\n\n // Handle dialog open change (from Dialog's own close mechanisms)\n const handleDialogOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n setOpen(nextOpen)\n },\n [setOpen],\n )\n\n return (\n <Dialog open={open} onOpenChange={handleDialogOpenChange}>\n <DialogPortal>\n <DialogOverlay\n className=\"fixed inset-0 z-overlay bg-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\"\n />\n <DialogContentRaw\n ref={ref}\n {...props}\n className={cn(\n 'fixed left-1/2 top-[20%] z-modal w-full max-w-[560px] -translate-x-1/2',\n 'overflow-hidden rounded-overlay-lg bg-surface-overlay shadow-overlay',\n 'duration-moderate-02 data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[state=closed]:slide-out-to-left-1/2 data-[state=open]:slide-in-from-left-1/2',\n 'data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2',\n className,\n )}\n onKeyDown={handleKeyDown}\n >\n <VisuallyHidden>\n <DialogTitle>Command Palette</DialogTitle>\n <DialogDescription>\n Search or jump to pages, projects, tasks, and actions\n </DialogDescription>\n </VisuallyHidden>\n\n {/* Search input */}\n <div className=\"flex items-center gap-ds-04 border-b border-surface-border-strong px-ds-05 py-ds-04\">\n <motion.span\n initial={noInit ?? { opacity: 0, scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springSnappy}\n className=\"inline-flex shrink-0\"\n >\n <Icon icon={IconSearch} size=\"sm\" stroke=\"light\" className=\"text-surface-fg-subtle\" />\n </motion.span>\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => handleQueryChange(e.target.value)}\n placeholder={placeholder}\n role=\"combobox\"\n aria-expanded={true}\n aria-controls={listboxId}\n aria-activedescendant={filteredItems[activeIndex] ? `command-item-${instanceId}-${filteredItems[activeIndex].id}` : undefined}\n aria-autocomplete=\"list\"\n className={cn(\n 'flex-1 bg-transparent text-ds-base text-surface-fg outline-hidden',\n 'placeholder:text-surface-fg-subtle',\n )}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n />\n <kbd className=\"hidden shrink-0 select-none rounded-control border border-surface-border-strong bg-surface-raised px-ds-02b py-ds-01 text-ds-sm font-medium text-surface-fg-subtle shadow-kbd sm:inline-flex\">\n Esc\n </kbd>\n </div>\n\n {/* Results */}\n <div\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-label=\"Command results\"\n className=\"overflow-y-auto px-ds-03 py-ds-03\"\n style={{ maxHeight: maxHeightValue }}\n >\n {filteredGroups.length === 0 && (\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center justify-center py-ds-07\"\n >\n {emptyState ?? (\n <p className=\"text-ds-md text-surface-fg-subtle\">\n {emptyMessage}\n </p>\n )}\n </motion.div>\n )}\n\n {filteredGroups.map((group, groupIdx) => (\n <motion.div\n key={group.label}\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={isReduced ? noMotionTransition : { ...tweens.fade, delay: groupIdx * 0.06 }}\n className=\"mb-ds-02\"\n >\n <div className=\"px-ds-03 pb-ds-02 pt-ds-03\">\n <span className=\"text-ds-xs font-semibold uppercase tracking-wider text-surface-fg-subtle\">\n {group.label}\n </span>\n </div>\n\n {group.items.map((item) => {\n const itemIndex = itemIndexMap.get(item.id) ?? 0\n const isActive = itemIndex === activeIndex\n return (\n <motion.button\n key={item.id}\n id={`command-item-${instanceId}-${item.id}`}\n type=\"button\"\n role=\"option\"\n aria-selected={isActive}\n data-command-index={itemIndex}\n initial={noInit ?? { opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n transition={isReduced ? noMotionTransition : { ...springs.snappy, delay: itemIndex * 0.03 }}\n onClick={() => {\n item.onSelect()\n setOpen(false)\n }}\n onMouseEnter={() => setActiveIndex(itemIndex)}\n className={cn(\n 'flex w-full items-center gap-ds-04 rounded-surface px-ds-03 py-ds-03 text-left transition-[color,background-color] duration-fast-02 ease-productive-standard',\n isActive\n ? 'bg-surface-raised-hover text-surface-fg'\n : 'text-surface-fg-muted hover:bg-surface-raised',\n )}\n >\n {item.icon && (\n <span\n className={cn(\n '[&>svg]:h-ico-sm [&>svg]:w-ico-sm shrink-0 transition-colors duration-fast-02 ease-productive-standard',\n isActive ? 'text-accent-11' : 'text-surface-fg-subtle',\n )}\n aria-hidden=\"true\"\n >\n <IconProvider size=\"sm\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n )}\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"truncate text-ds-md\">\n {item.renderLabel ? item.renderLabel(query) : item.label}\n </span>\n {item.description && (\n <span className=\"line-clamp-1 text-ds-sm text-surface-fg-subtle\">\n {item.description}\n </span>\n )}\n </div>\n {item.shortcut && (\n <span className=\"flex shrink-0 items-center gap-ds-01\">\n {parseShortcutKeys(item.shortcut).map((key, i) => (\n <kbd\n key={i}\n className={cn(\n 'inline-flex min-w-ds-05b items-center justify-center rounded border px-ds-02b py-ds-01 text-ds-xs font-medium shadow-kbd transition-colors duration-fast-02 ease-productive-standard',\n isActive\n ? 'bg-accent-2 text-accent-11 border-accent-6'\n : 'bg-surface-raised text-surface-fg-subtle border-surface-border-strong',\n )}\n >\n {key === 'Ctrl' || key === 'ctrl' ? getModifierDisplay(isMac) : key}\n </kbd>\n ))}\n </span>\n )}\n <AnimatePresence>\n {isActive && (\n <motion.span\n initial={isReduced ? undefined : { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={isReduced ? undefined : { opacity: 0 }}\n transition={tweenFade}\n className=\"inline-flex shrink-0\"\n >\n <Icon icon={IconCornerDownLeft} size=\"sm\" stroke=\"light\" className=\"text-surface-fg-subtle\" />\n </motion.span>\n )}\n </AnimatePresence>\n </motion.button>\n )\n })}\n </motion.div>\n ))}\n </div>\n\n {/* Footer with keyboard hints */}\n {resolvedFooterHints !== false && (\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center gap-ds-05 border-t border-surface-border-strong px-ds-05 py-ds-03\"\n >\n {resolvedFooterHints.map((hint, i) => (\n <div key={i} className=\"flex items-center gap-ds-02b\">\n {hint.keys === '↑↓' ? (\n <div className=\"flex items-center gap-ds-01\">\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-surface-border-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowUp} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-surface-border-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowDown} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n </div>\n ) : hint.keys === '↵' ? (\n <kbd className=\"inline-flex h-ds-05b items-center justify-center rounded-control border border-surface-border-strong bg-surface-raised px-ds-02b shadow-kbd\">\n <Icon icon={IconCornerDownLeft} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n ) : (\n <kbd className=\"inline-flex h-ds-05b items-center justify-center rounded-control border border-surface-border-strong bg-surface-raised px-ds-02b text-ds-xs font-medium text-surface-fg-subtle shadow-kbd\">\n {hint.keys}\n </kbd>\n )}\n <span className=\"text-ds-xs text-surface-fg-subtle\">\n {hint.label}\n </span>\n </div>\n ))}\n </motion.div>\n )}\n </DialogContentRaw>\n </DialogPortal>\n </Dialog>\n )\n },\n)\n\nCommandPalette.displayName = 'CommandPalette'\n\nexport { CommandPalette }\n"],"mappings":"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"}
1
+ {"version":3,"file":"command-palette.js","names":[],"sources":["../../src/composed/command-palette.tsx"],"sourcesContent":["'use client'\n\n/**\n * CommandPalette -- Keyboard-driven command palette (Ctrl+K / Cmd+K).\n *\n * Adapted from Karm V2. Uses ui/Dialog as the overlay.\n * All V1 color tokens replaced with semantic design-system tokens.\n */\nimport { IconArrowDown,IconArrowUp, IconCornerDownLeft, IconSearch } from '@tabler/icons-react'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useMotion } from '../motion/motion-provider'\nimport {\n Dialog,\n DialogContentRaw,\n DialogDescription,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n} from '../ui/dialog'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { springs,tweens } from '../ui/lib/motion'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport { VisuallyHidden } from '../ui/visually-hidden'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface CommandItem {\n id: string\n /** Display label — string or ReactNode. When ReactNode, provide `filterValue` for search filtering. */\n label: string | React.ReactNode\n /** Optional description — string or ReactNode. */\n description?: string | React.ReactNode\n icon?: IconInput\n /** Keyboard shortcut hint displayed as keycap badges (e.g., \"G D\", \"Ctrl+N\"). */\n shortcut?: string\n /** Custom render override for the label. Receives the current search query for match highlighting. */\n renderLabel?: (query: string) => React.ReactNode\n /** Plain-text value used for search filtering when `label` is a ReactNode. Falls back to `label` if string. */\n filterValue?: string\n onSelect: () => void\n}\n\nexport interface CommandGroup {\n label: string\n items: CommandItem[]\n}\n\n/** A single keyboard hint shown in the footer. */\nexport interface FooterHint {\n /** Key(s) to display — rendered as text inside `<kbd>` or as an icon. */\n keys: string\n /** Human-readable label for the hint (e.g., \"Navigate\", \"Select\"). */\n label: string\n}\n\n/**\n * A searchable command palette with keyboard navigation (Ctrl+K / Cmd+K).\n * Supports grouped items, custom keybindings, controlled/uncontrolled open state,\n * and custom empty states.\n */\nexport interface CommandPaletteProps extends React.ComponentPropsWithoutRef<'div'> {\n /** Item groups displayed in the palette. Each group has a label and an array of CommandItems. */\n groups?: CommandGroup[]\n /** Placeholder text for the search input. */\n placeholder?: string\n /** Called on every search input change with the current query string. */\n onSearch?: (query: string) => void\n /** Simple text shown when no results match. Overridden by `emptyState` if provided. */\n emptyMessage?: string\n /** Full custom empty state ReactNode — overrides `emptyMessage` when provided. */\n emptyState?: React.ReactNode\n // -- Controlled/uncontrolled open state (P1 #4) --\n /** Controlled open state. */\n open?: boolean\n /** Default open state for uncontrolled usage. */\n defaultOpen?: boolean\n /** Called when the open state changes. */\n onOpenChange?: (open: boolean) => void\n // -- Keyboard shortcut customization (P1 #6) --\n /** Keybinding(s) to toggle the palette. Pass `false` to disable.\n * String format: modifier+key, e.g., 'mod+k', 'ctrl+shift+p'.\n * 'mod' maps to Meta on macOS, Ctrl otherwise. */\n keybinding?: string | string[] | false\n // -- Configurable max-height (P2 #8) --\n /** Max height of the results container. CSS value. Default '320px'. */\n maxHeight?: string | number\n // -- Custom footer hints (P2 #11) --\n /** Custom footer keyboard hints. Pass `false` to hide the footer entirely. */\n footerHints?: FooterHint[] | false\n}\n\n// -----------------------------------------------------------------------\n// Helpers\n// -----------------------------------------------------------------------\n\nimport { getIsMac, getModifierDisplay,matchesKeybinding } from '../ui/lib/keybinding'\n\n/** Get the text-searchable value from a CommandItem. */\nfunction getFilterValue(item: CommandItem): string {\n if (item.filterValue) return item.filterValue\n if (typeof item.label === 'string') return item.label\n return ''\n}\n\n/** Get the text-searchable description from a CommandItem. */\nfunction getFilterDescription(item: CommandItem): string {\n if (typeof item.description === 'string') return item.description\n return ''\n}\n\n/** Parse a shortcut string like \"G D\" or \"Ctrl+N\" into individual keycap segments. */\nfunction parseShortcutKeys(shortcut: string): string[] {\n // If it has \"+\" separator (Ctrl+Shift+N style), split on +\n if (shortcut.includes('+')) {\n return shortcut.split('+').map(s => s.trim()).filter(Boolean)\n }\n // Otherwise split on spaces (G D style)\n return shortcut.split(/\\s+/).filter(Boolean)\n}\n\n// -----------------------------------------------------------------------\n// CommandPalette\n// -----------------------------------------------------------------------\n\nconst CommandPalette = React.forwardRef<HTMLDivElement, CommandPaletteProps>(\n function CommandPalette(\n {\n groups = [],\n placeholder = 'Search or jump to...',\n onSearch,\n emptyMessage = 'No results found.',\n emptyState,\n open: openProp,\n defaultOpen,\n onOpenChange,\n keybinding = 'mod+k',\n maxHeight = '320px',\n footerHints,\n className,\n ...props\n },\n ref,\n ) {\n // -- Controlled/uncontrolled open state --\n const isControlled = openProp !== undefined\n const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false)\n const open = isControlled ? openProp : internalOpen\n\n // Use a ref for the current open value to avoid stale closures in setOpen\n const openRef = React.useRef(open)\n openRef.current = open\n\n const setOpen = React.useCallback(\n (nextOpen: boolean | ((prev: boolean) => boolean)) => {\n const resolved = typeof nextOpen === 'function' ? nextOpen(openRef.current) : nextOpen\n if (!isControlled) {\n setInternalOpen(resolved)\n }\n onOpenChange?.(resolved)\n },\n [isControlled, onOpenChange],\n )\n\n const [query, setQuery] = React.useState('')\n const [activeIndex, setActiveIndex] = React.useState(0)\n const inputRef = React.useRef<HTMLInputElement>(null)\n const listRef = React.useRef<HTMLDivElement>(null)\n const instanceId = React.useId()\n const listboxId = `command-palette-listbox-${instanceId}`\n\n // -- Reduced motion (P2 #12) --\n const { reducedMotion: isReduced } = useMotion()\n const noMotionTransition = { duration: 0 }\n\n // -- Platform detection (P2 #13) --\n const isMac = React.useMemo(() => getIsMac(), [])\n\n // Filter groups based on query\n const filteredGroups = React.useMemo(() => {\n if (!query.trim()) return groups\n const q = query.toLowerCase()\n return groups\n .map((group) => ({\n ...group,\n items: group.items.filter(\n (item) =>\n getFilterValue(item).toLowerCase().includes(q) ||\n getFilterDescription(item).toLowerCase().includes(q),\n ),\n }))\n .filter((group) => group.items.length > 0)\n }, [groups, query])\n\n const filteredItems = React.useMemo(\n () => filteredGroups.flatMap((g) => g.items),\n [filteredGroups],\n )\n\n // Global keyboard shortcut\n React.useEffect(() => {\n if (keybinding === false) return\n\n const bindings = Array.isArray(keybinding) ? keybinding : [keybinding]\n\n function handleKeyDown(e: KeyboardEvent) {\n for (const binding of bindings) {\n if (matchesKeybinding(e, binding)) {\n e.preventDefault()\n setOpen((prev) => !prev)\n return\n }\n }\n }\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [keybinding, setOpen])\n\n // Reset state when opening\n React.useEffect(() => {\n if (open) {\n setQuery('')\n setActiveIndex(0)\n requestAnimationFrame(() => {\n inputRef.current?.focus()\n })\n }\n }, [open])\n\n // Keyboard navigation inside the palette\n const handleKeyDown = (e: React.KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n setActiveIndex((prev) =>\n prev < filteredItems.length - 1 ? prev + 1 : 0,\n )\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n setActiveIndex((prev) =>\n prev > 0 ? prev - 1 : filteredItems.length - 1,\n )\n break\n }\n case 'Enter': {\n e.preventDefault()\n const item = filteredItems[activeIndex]\n if (item) {\n item.onSelect()\n setOpen(false)\n }\n break\n }\n case 'Escape': {\n e.preventDefault()\n setOpen(false)\n break\n }\n }\n }\n\n // Scroll active item into view\n React.useEffect(() => {\n const activeEl = listRef.current?.querySelector(\n `[data-command-index=\"${activeIndex}\"]`,\n )\n activeEl?.scrollIntoView({ block: 'nearest' })\n }, [activeIndex])\n\n const handleQueryChange = (value: string) => {\n setQuery(value)\n setActiveIndex(0)\n onSearch?.(value)\n }\n\n // Build a map of item id -> flat index for keyboard navigation\n const itemIndexMap = React.useMemo(() => {\n const map = new Map<string, number>()\n let idx = 0\n for (const group of filteredGroups) {\n for (const item of group.items) {\n map.set(item.id, idx++)\n }\n }\n return map\n }, [filteredGroups])\n\n // -- Resolve motion transitions --\n const springSnappy = isReduced ? noMotionTransition : springs.snappy\n const tweenFade = isReduced ? noMotionTransition : tweens.fade\n const noInit = isReduced ? { opacity: 1, scale: 1, y: 0 } : undefined\n\n // -- Resolve max height CSS value --\n const maxHeightValue = typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight\n\n // -- Resolve footer hints --\n const resolvedFooterHints: FooterHint[] | false =\n footerHints === false\n ? false\n : footerHints ?? [\n { keys: '↑↓', label: 'Navigate' },\n { keys: '↵', label: 'Select' },\n { keys: 'Esc', label: 'Close' },\n ]\n\n // Handle dialog open change (from Dialog's own close mechanisms)\n const handleDialogOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n setOpen(nextOpen)\n },\n [setOpen],\n )\n\n return (\n <Dialog open={open} onOpenChange={handleDialogOpenChange}>\n <DialogPortal>\n <DialogOverlay\n className=\"fixed inset-0 z-overlay bg-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\"\n />\n <DialogContentRaw\n ref={ref}\n {...props}\n className={cn(\n 'fixed left-1/2 top-[20%] z-modal w-full max-w-[560px] -translate-x-1/2',\n 'overflow-hidden rounded-overlay-lg bg-surface-overlay shadow-overlay',\n 'duration-moderate-02 data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[state=closed]:slide-out-to-left-1/2 data-[state=open]:slide-in-from-left-1/2',\n 'data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2',\n className,\n )}\n onKeyDown={handleKeyDown}\n >\n <VisuallyHidden>\n <DialogTitle>Command Palette</DialogTitle>\n <DialogDescription>\n Search or jump to pages, projects, tasks, and actions\n </DialogDescription>\n </VisuallyHidden>\n\n {/* Search input */}\n <div className=\"flex items-center gap-ds-04 border-b border-surface-border-strong px-ds-05 py-ds-04\">\n <motion.span\n initial={noInit ?? { opacity: 0, scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springSnappy}\n className=\"inline-flex shrink-0\"\n >\n <Icon icon={IconSearch} size=\"sm\" stroke=\"light\" className=\"text-surface-fg-subtle\" />\n </motion.span>\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => handleQueryChange(e.target.value)}\n placeholder={placeholder}\n role=\"combobox\"\n aria-expanded={true}\n aria-controls={listboxId}\n aria-activedescendant={filteredItems[activeIndex] ? `command-item-${instanceId}-${filteredItems[activeIndex].id}` : undefined}\n aria-autocomplete=\"list\"\n className={cn(\n 'flex-1 bg-transparent text-body-lg text-surface-fg outline-hidden',\n 'placeholder:text-surface-fg-subtle',\n )}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n />\n <kbd className=\"hidden shrink-0 select-none rounded-control border border-card-strong bg-surface-raised px-ds-02b py-ds-01 text-body-sm font-medium text-surface-fg-subtle shadow-kbd sm:inline-flex\">\n Esc\n </kbd>\n </div>\n\n {/* Results */}\n <div\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-label=\"Command results\"\n className=\"overflow-y-auto px-ds-03 py-ds-03\"\n style={{ maxHeight: maxHeightValue }}\n >\n {filteredGroups.length === 0 && (\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center justify-center py-ds-07\"\n >\n {emptyState ?? (\n <p className=\"text-body-md text-surface-fg-subtle\">\n {emptyMessage}\n </p>\n )}\n </motion.div>\n )}\n\n {filteredGroups.map((group, groupIdx) => (\n <motion.div\n key={group.label}\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={isReduced ? noMotionTransition : { ...tweens.fade, delay: groupIdx * 0.06 }}\n className=\"mb-ds-02\"\n >\n <div className=\"px-ds-03 pb-ds-02 pt-ds-03\">\n <span className=\"text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle\">\n {group.label}\n </span>\n </div>\n\n {group.items.map((item) => {\n const itemIndex = itemIndexMap.get(item.id) ?? 0\n const isActive = itemIndex === activeIndex\n return (\n <motion.button\n key={item.id}\n id={`command-item-${instanceId}-${item.id}`}\n type=\"button\"\n role=\"option\"\n aria-selected={isActive}\n data-command-index={itemIndex}\n initial={noInit ?? { opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n transition={isReduced ? noMotionTransition : { ...springs.snappy, delay: itemIndex * 0.03 }}\n onClick={() => {\n item.onSelect()\n setOpen(false)\n }}\n onMouseEnter={() => setActiveIndex(itemIndex)}\n className={cn(\n 'flex w-full items-center gap-ds-04 rounded-surface px-ds-03 py-ds-03 text-left transition-[color,background-color] duration-fast-02 ease-productive-standard',\n isActive\n ? 'bg-surface-raised-hover text-surface-fg'\n : 'text-surface-fg-muted hover:bg-surface-raised',\n )}\n >\n {item.icon && (\n <span\n className={cn(\n '[&>svg]:h-ico-sm [&>svg]:w-ico-sm shrink-0 transition-colors duration-fast-02 ease-productive-standard',\n isActive ? 'text-accent-11' : 'text-surface-fg-subtle',\n )}\n aria-hidden=\"true\"\n >\n <IconProvider size=\"sm\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n )}\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"truncate text-body-md\">\n {item.renderLabel ? item.renderLabel(query) : item.label}\n </span>\n {item.description && (\n <span className=\"line-clamp-1 text-body-sm text-surface-fg-subtle\">\n {item.description}\n </span>\n )}\n </div>\n {item.shortcut && (\n <span className=\"flex shrink-0 items-center gap-ds-01\">\n {parseShortcutKeys(item.shortcut).map((key, i) => (\n <kbd\n key={i}\n className={cn(\n 'inline-flex min-w-ds-05b items-center justify-center rounded border px-ds-02b py-ds-01 text-body-xs font-medium shadow-kbd transition-colors duration-fast-02 ease-productive-standard',\n isActive\n ? 'bg-accent-2 text-accent-11 border-accent-6'\n : 'bg-surface-raised text-surface-fg-subtle border-surface-border-strong',\n )}\n >\n {key === 'Ctrl' || key === 'ctrl' ? getModifierDisplay(isMac) : key}\n </kbd>\n ))}\n </span>\n )}\n <AnimatePresence>\n {isActive && (\n <motion.span\n initial={isReduced ? undefined : { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={isReduced ? undefined : { opacity: 0 }}\n transition={tweenFade}\n className=\"inline-flex shrink-0\"\n >\n <Icon icon={IconCornerDownLeft} size=\"sm\" stroke=\"light\" className=\"text-surface-fg-subtle\" />\n </motion.span>\n )}\n </AnimatePresence>\n </motion.button>\n )\n })}\n </motion.div>\n ))}\n </div>\n\n {/* Footer with keyboard hints */}\n {resolvedFooterHints !== false && (\n <motion.div\n initial={noInit ?? { opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={tweenFade}\n className=\"flex items-center gap-ds-05 border-t border-surface-border-strong px-ds-05 py-ds-03\"\n >\n {resolvedFooterHints.map((hint, i) => (\n <div key={i} className=\"flex items-center gap-ds-02b\">\n {hint.keys === '↑↓' ? (\n <div className=\"flex items-center gap-ds-01\">\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowUp} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n <kbd className=\"inline-flex h-ico-md w-ico-md items-center justify-center rounded border border-card-strong bg-surface-raised shadow-kbd\">\n <Icon icon={IconArrowDown} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n </div>\n ) : hint.keys === '↵' ? (\n <kbd className=\"inline-flex h-ds-05b items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b shadow-kbd\">\n <Icon icon={IconCornerDownLeft} size=\"xs\" className=\"text-surface-fg-subtle\" />\n </kbd>\n ) : (\n <kbd className=\"inline-flex h-ds-05b items-center justify-center rounded-control border border-card-strong bg-surface-raised px-ds-02b text-caption font-medium text-surface-fg-subtle shadow-kbd\">\n {hint.keys}\n </kbd>\n )}\n <span className=\"text-caption text-surface-fg-subtle\">\n {hint.label}\n </span>\n </div>\n ))}\n </motion.div>\n )}\n </DialogContentRaw>\n </DialogPortal>\n </Dialog>\n )\n },\n)\n\nCommandPalette.displayName = 'CommandPalette'\n\nexport { CommandPalette }\n"],"mappings":"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"}
@@ -46,7 +46,7 @@ var o = e("rounded-surface will-change-[box-shadow] transition-[color,background
46
46
  _ && /* @__PURE__ */ i("div", {
47
47
  className: t("flex items-center justify-between border-b border-surface-border-strong", s(n)),
48
48
  children: l ?? /* @__PURE__ */ a(r, { children: [u && /* @__PURE__ */ i("h3", {
49
- className: "text-ds-base font-semibold text-surface-fg",
49
+ className: "text-body-lg font-semibold text-surface-fg",
50
50
  children: u
51
51
  }), d && /* @__PURE__ */ i("div", {
52
52
  className: "flex items-center gap-ds-03",
@@ -1 +1 @@
1
- {"version":3,"file":"content-card.js","names":[],"sources":["../../src/composed/content-card.tsx"],"sourcesContent":["// @server-safe\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '../ui/lib/utils'\n\nconst contentCardVariants = cva(\n 'rounded-surface will-change-[box-shadow] transition-[color,background-color,border-color,box-shadow] duration-fast-02 ease-productive-standard',\n {\n variants: {\n variant: {\n default:\n 'bg-surface-raised shadow-raised hover:shadow-raised-hover',\n outline:\n 'border border-surface-border bg-transparent hover:border-surface-border-strong',\n ghost:\n 'border border-transparent bg-transparent hover:bg-surface-raised',\n },\n padding: {\n default: 'p-ds-05b',\n compact: 'p-ds-04',\n spacious: 'p-ds-06',\n none: 'p-0',\n },\n },\n defaultVariants: {\n variant: 'default',\n padding: 'default',\n },\n },\n)\n\nconst getPadding = (padding: string | null | undefined) => {\n switch (padding) {\n case 'compact': return 'px-ds-04 py-ds-03'\n case 'spacious': return 'px-ds-06 py-ds-05'\n default: return 'px-ds-05b py-ds-04'\n }\n}\n\nconst getContentPadding = (padding: string | null | undefined) => {\n switch (padding) {\n case 'compact': return 'p-ds-04'\n case 'spacious': return 'p-ds-06'\n default: return 'p-ds-05b'\n }\n}\n\nexport interface ContentCardProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof contentCardVariants> {\n header?: React.ReactNode\n headerTitle?: string\n headerActions?: React.ReactNode\n footer?: React.ReactNode\n}\n\n/**\n * @deprecated Use `Card` with `CardHeader` / `CardContent` / `CardFooter` instead.\n * `ContentCard` duplicated `Card` on the legacy per-slot-padding model; `Card` now covers\n * every feature (variants, slots, gap-model padding). `ContentCard` will be removed in the\n * next major — see MIGRATION.md.\n */\nconst ContentCard = React.forwardRef<HTMLDivElement, ContentCardProps>(\n (\n {\n variant,\n padding,\n header,\n headerTitle,\n headerActions,\n footer,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const hasHeader = header || headerTitle || headerActions\n\n return (\n <div\n ref={ref}\n className={cn(\n contentCardVariants({ variant, padding: hasHeader || footer ? 'none' : padding }),\n className,\n )}\n {...props}\n >\n {hasHeader && (\n <div\n className={cn(\n 'flex items-center justify-between border-b border-surface-border-strong',\n getPadding(padding),\n )}\n >\n {header ?? (\n <>\n {headerTitle && (\n <h3 className=\"text-ds-base font-semibold text-surface-fg\">\n {headerTitle}\n </h3>\n )}\n {headerActions && (\n <div className=\"flex items-center gap-ds-03\">{headerActions}</div>\n )}\n </>\n )}\n </div>\n )}\n\n <div\n className={cn(\n (hasHeader || footer) && getContentPadding(padding),\n )}\n >\n {children}\n </div>\n\n {footer && (\n <div\n className={cn(\n 'border-t border-surface-border-strong',\n getPadding(padding),\n )}\n >\n {footer}\n </div>\n )}\n </div>\n )\n },\n)\nContentCard.displayName = 'ContentCard'\n\nexport { ContentCard, contentCardVariants }\n"],"mappings":";;;;;AAMA,IAAM,IAAsB,EAC1B,kJACA;CACE,UAAU;EACR,SAAS;GACP,SACE;GACF,SACE;GACF,OACE;EACJ;EACA,SAAS;GACP,SAAS;GACT,SAAS;GACT,UAAU;GACV,MAAM;EACR;CACF;CACA,iBAAiB;EACf,SAAS;EACT,SAAS;CACX;AACF,CACF,GAEM,KAAc,MAAuC;CACzD,QAAQ,GAAR;EACE,KAAK,WAAW,OAAO;EACvB,KAAK,YAAY,OAAO;EACxB,SAAS,OAAO;CAClB;AACF,GAEM,KAAqB,MAAuC;CAChE,QAAQ,GAAR;EACE,KAAK,WAAW,OAAO;EACvB,KAAK,YAAY,OAAO;EACxB,SAAS,OAAO;CAClB;AACF,GAiBM,IAAc,EAAM,YAEtB,EACE,YACA,YACA,WACA,gBACA,kBACA,WACA,cACA,aACA,GAAG,KAEL,MACG;CACH,IAAM,IAAY,KAAU,KAAe;CAE3C,OACE,kBAAC,OAAD;EACO;EACL,WAAW,EACT,EAAoB;GAAE;GAAS,SAAS,KAAa,IAAS,SAAS;EAAQ,CAAC,GAChF,CACF;EACA,GAAI;YANN;GAQG,KACC,kBAAC,OAAD;IACE,WAAW,EACT,2EACA,EAAW,CAAO,CACpB;cAEC,KACC,kBAAA,GAAA,EAAA,UAAA,CACG,KACC,kBAAC,MAAD;KAAI,WAAU;eACX;IACC,CAAA,GAEL,KACC,kBAAC,OAAD;KAAK,WAAU;eAA+B;IAAmB,CAAA,CAEnE,EAAA,CAAA;GAED,CAAA;GAGP,kBAAC,OAAD;IACE,WAAW,GACR,KAAa,MAAW,EAAkB,CAAO,CACpD;IAEC;GACE,CAAA;GAEJ,KACC,kBAAC,OAAD;IACE,WAAW,EACT,yCACA,EAAW,CAAO,CACpB;cAEC;GACE,CAAA;EAEJ;;AAET,CACF;AACA,EAAY,cAAc"}
1
+ {"version":3,"file":"content-card.js","names":[],"sources":["../../src/composed/content-card.tsx"],"sourcesContent":["// @server-safe\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '../ui/lib/utils'\n\nconst contentCardVariants = cva(\n 'rounded-surface will-change-[box-shadow] transition-[color,background-color,border-color,box-shadow] duration-fast-02 ease-productive-standard',\n {\n variants: {\n variant: {\n default:\n 'bg-surface-raised shadow-raised hover:shadow-raised-hover',\n outline:\n 'border border-surface-border bg-transparent hover:border-surface-border-strong',\n ghost:\n 'border border-transparent bg-transparent hover:bg-surface-raised',\n },\n padding: {\n default: 'p-ds-05b',\n compact: 'p-ds-04',\n spacious: 'p-ds-06',\n none: 'p-0',\n },\n },\n defaultVariants: {\n variant: 'default',\n padding: 'default',\n },\n },\n)\n\nconst getPadding = (padding: string | null | undefined) => {\n switch (padding) {\n case 'compact': return 'px-ds-04 py-ds-03'\n case 'spacious': return 'px-ds-06 py-ds-05'\n default: return 'px-ds-05b py-ds-04'\n }\n}\n\nconst getContentPadding = (padding: string | null | undefined) => {\n switch (padding) {\n case 'compact': return 'p-ds-04'\n case 'spacious': return 'p-ds-06'\n default: return 'p-ds-05b'\n }\n}\n\nexport interface ContentCardProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof contentCardVariants> {\n header?: React.ReactNode\n headerTitle?: string\n headerActions?: React.ReactNode\n footer?: React.ReactNode\n}\n\n/**\n * @deprecated Use `Card` with `CardHeader` / `CardContent` / `CardFooter` instead.\n * `ContentCard` duplicated `Card` on the legacy per-slot-padding model; `Card` now covers\n * every feature (variants, slots, gap-model padding). `ContentCard` will be removed in the\n * next major — see MIGRATION.md.\n */\nconst ContentCard = React.forwardRef<HTMLDivElement, ContentCardProps>(\n (\n {\n variant,\n padding,\n header,\n headerTitle,\n headerActions,\n footer,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const hasHeader = header || headerTitle || headerActions\n\n return (\n <div\n ref={ref}\n className={cn(\n contentCardVariants({ variant, padding: hasHeader || footer ? 'none' : padding }),\n className,\n )}\n {...props}\n >\n {hasHeader && (\n <div\n className={cn(\n 'flex items-center justify-between border-b border-surface-border-strong',\n getPadding(padding),\n )}\n >\n {header ?? (\n <>\n {headerTitle && (\n <h3 className=\"text-body-lg font-semibold text-surface-fg\">\n {headerTitle}\n </h3>\n )}\n {headerActions && (\n <div className=\"flex items-center gap-ds-03\">{headerActions}</div>\n )}\n </>\n )}\n </div>\n )}\n\n <div\n className={cn(\n (hasHeader || footer) && getContentPadding(padding),\n )}\n >\n {children}\n </div>\n\n {footer && (\n <div\n className={cn(\n 'border-t border-surface-border-strong',\n getPadding(padding),\n )}\n >\n {footer}\n </div>\n )}\n </div>\n )\n },\n)\nContentCard.displayName = 'ContentCard'\n\nexport { ContentCard, contentCardVariants }\n"],"mappings":";;;;;AAMA,IAAM,IAAsB,EAC1B,kJACA;CACE,UAAU;EACR,SAAS;GACP,SACE;GACF,SACE;GACF,OACE;EACJ;EACA,SAAS;GACP,SAAS;GACT,SAAS;GACT,UAAU;GACV,MAAM;EACR;CACF;CACA,iBAAiB;EACf,SAAS;EACT,SAAS;CACX;AACF,CACF,GAEM,KAAc,MAAuC;CACzD,QAAQ,GAAR;EACE,KAAK,WAAW,OAAO;EACvB,KAAK,YAAY,OAAO;EACxB,SAAS,OAAO;CAClB;AACF,GAEM,KAAqB,MAAuC;CAChE,QAAQ,GAAR;EACE,KAAK,WAAW,OAAO;EACvB,KAAK,YAAY,OAAO;EACxB,SAAS,OAAO;CAClB;AACF,GAiBM,IAAc,EAAM,YAEtB,EACE,YACA,YACA,WACA,gBACA,kBACA,WACA,cACA,aACA,GAAG,KAEL,MACG;CACH,IAAM,IAAY,KAAU,KAAe;CAE3C,OACE,kBAAC,OAAD;EACO;EACL,WAAW,EACT,EAAoB;GAAE;GAAS,SAAS,KAAa,IAAS,SAAS;EAAQ,CAAC,GAChF,CACF;EACA,GAAI;YANN;GAQG,KACC,kBAAC,OAAD;IACE,WAAW,EACT,2EACA,EAAW,CAAO,CACpB;cAEC,KACC,kBAAA,GAAA,EAAA,UAAA,CACG,KACC,kBAAC,MAAD;KAAI,WAAU;eACX;IACC,CAAA,GAEL,KACC,kBAAC,OAAD;KAAK,WAAU;eAA+B;IAAmB,CAAA,CAEnE,EAAA,CAAA;GAED,CAAA;GAGP,kBAAC,OAAD;IACE,WAAW,GACR,KAAa,MAAW,EAAkB,CAAO,CACpD;IAEC;GACE,CAAA;GAEJ,KACC,kBAAC,OAAD;IACE,WAAW,EACT,yCACA,EAAW,CAAO,CACpB;cAEC;GACE,CAAA;EAEJ;;AAET,CACF;AACA,EAAY,cAAc"}
@@ -53,7 +53,7 @@ var k = [
53
53
  ...u,
54
54
  className: e("w-[252px]", o),
55
55
  children: [/* @__PURE__ */ c("div", {
56
- className: "text-center pb-ds-04 text-ds-md font-semibold text-surface-fg",
56
+ className: "text-center pb-ds-04 text-body-md font-semibold text-surface-fg",
57
57
  children: t
58
58
  }), /* @__PURE__ */ c("div", {
59
59
  role: "grid",
@@ -78,7 +78,7 @@ var k = [
78
78
  tabIndex: o === f ? 0 : -1,
79
79
  disabled: l || !1,
80
80
  onClick: () => !l && r(o),
81
- className: e("h-ds-sm-plus rounded-control text-ds-md transition-colors focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2", l && "opacity-action-disabled pointer-events-none cursor-not-allowed", s && "bg-accent-9 text-accent-fg", !s && !l && "hover:bg-surface-raised-hover text-surface-fg"),
81
+ className: e("h-ds-sm-plus rounded-control text-body-md transition-colors focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2", l && "opacity-action-disabled pointer-events-none cursor-not-allowed", s && "bg-accent-9 text-accent-fg", !s && !l && "hover:bg-surface-raised-hover text-surface-fg"),
82
82
  children: i
83
83
  }, i);
84
84
  })
@@ -124,7 +124,7 @@ var j = s.forwardRef(function({ currentYear: t, selectedYear: n, onYearSelect: r
124
124
  ...u,
125
125
  className: e("w-[252px]", o),
126
126
  children: [/* @__PURE__ */ l("div", {
127
- className: "text-center pb-ds-04 text-ds-md font-semibold text-surface-fg",
127
+ className: "text-center pb-ds-04 text-body-md font-semibold text-surface-fg",
128
128
  children: [
129
129
  f,
130
130
  " – ",
@@ -154,7 +154,7 @@ var j = s.forwardRef(function({ currentYear: t, selectedYear: n, onYearSelect: r
154
154
  tabIndex: i === m ? 0 : -1,
155
155
  disabled: o || !1,
156
156
  onClick: () => !o && r(t),
157
- className: e("h-ds-sm-plus rounded-control text-ds-md transition-colors focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2", o && "opacity-action-disabled pointer-events-none cursor-not-allowed", a && "bg-accent-9 text-accent-fg", !a && !o && "hover:bg-surface-raised-hover text-surface-fg"),
157
+ className: e("h-ds-sm-plus rounded-control text-body-md transition-colors focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2", o && "opacity-action-disabled pointer-events-none cursor-not-allowed", a && "bg-accent-9 text-accent-fg", !a && !o && "hover:bg-surface-raised-hover text-surface-fg"),
158
158
  children: t
159
159
  }, t);
160
160
  })
@@ -223,7 +223,7 @@ var M = s.forwardRef(function({ value: o, onChange: u, placeholder: f = "Pick a
223
223
  stroke: "light",
224
224
  className: "text-surface-fg-subtle"
225
225
  }), /* @__PURE__ */ c("span", {
226
- className: e("text-ds-md", o ? "text-surface-fg" : "text-surface-fg-subtle"),
226
+ className: e("text-body-md", o ? "text-surface-fg" : "text-surface-fg-subtle"),
227
227
  children: o ? g(o, m) : f
228
228
  })]
229
229
  })
@@ -322,7 +322,7 @@ var N = {
322
322
  let { start: e, end: t } = r.getRange();
323
323
  n(e, t);
324
324
  },
325
- className: e("h-ds-sm w-full rounded-control px-ds-03 text-left text-ds-sm", "text-surface-fg transition-colors", "hover:bg-surface-raised-hover", "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9"),
325
+ className: e("h-ds-sm w-full rounded-control px-ds-03 text-left text-body-sm", "text-surface-fg transition-colors", "hover:bg-surface-raised-hover", "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9"),
326
326
  children: r.label
327
327
  }, t) : null;
328
328
  })
@@ -425,7 +425,7 @@ var F = s.forwardRef(function({ startDate: o, endDate: u, onChange: f, placehold
425
425
  stroke: "light",
426
426
  className: "text-surface-fg-subtle"
427
427
  }), /* @__PURE__ */ c("span", {
428
- className: e("text-ds-md", I && R ? "text-surface-fg" : "text-surface-fg-subtle"),
428
+ className: e("text-body-md", I && R ? "text-surface-fg" : "text-surface-fg-subtle"),
429
429
  children: X()
430
430
  })]
431
431
  })
@@ -509,7 +509,7 @@ var R = s.forwardRef(function({ value: o, onChange: d, minDate: f, maxDate: p, d
509
509
  maxDate: p
510
510
  });
511
511
  }
512
- }, Q = "h-ds-sm rounded-control border border-surface-border-strong bg-surface-overlay px-ds-02 text-ds-md text-surface-fg transition-colors duration-fast-01 ease-productive-standard hover:border-surface-border-strong focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 cursor-pointer appearance-none";
512
+ }, Q = "h-ds-sm rounded-control border border-surface-border-strong bg-surface-overlay px-ds-02 text-body-md text-surface-fg transition-colors duration-fast-01 ease-productive-standard hover:border-surface-border-strong focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 cursor-pointer appearance-none";
513
513
  return /* @__PURE__ */ l(n, {
514
514
  open: E,
515
515
  onOpenChange: D,
@@ -527,7 +527,7 @@ var R = s.forwardRef(function({ value: o, onChange: d, minDate: f, maxDate: p, d
527
527
  stroke: "light",
528
528
  className: "text-surface-fg-subtle"
529
529
  }), /* @__PURE__ */ c("span", {
530
- className: e("text-ds-md", X ? "text-surface-fg" : "text-surface-fg-subtle"),
530
+ className: e("text-body-md", X ? "text-surface-fg" : "text-surface-fg-subtle"),
531
531
  children: X ?? v
532
532
  })]
533
533
  })
@@ -541,7 +541,7 @@ var R = s.forwardRef(function({ value: o, onChange: d, minDate: f, maxDate: p, d
541
541
  className: "flex items-center gap-ds-02 border-t border-surface-border-strong pt-ds-04",
542
542
  children: [
543
543
  /* @__PURE__ */ c("span", {
544
- className: "text-ds-xs font-semibold uppercase tracking-wider text-surface-fg-subtle",
544
+ className: "text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle",
545
545
  children: "Time"
546
546
  }),
547
547
  /* @__PURE__ */ l("select", {
@@ -558,7 +558,7 @@ var R = s.forwardRef(function({ value: o, onChange: d, minDate: f, maxDate: p, d
558
558
  }, e))]
559
559
  }),
560
560
  /* @__PURE__ */ c("span", {
561
- className: "text-ds-md font-semibold text-surface-fg-subtle",
561
+ className: "text-body-md font-semibold text-surface-fg-subtle",
562
562
  children: ":"
563
563
  }),
564
564
  /* @__PURE__ */ l("select", {
@@ -638,7 +638,7 @@ var V = s.forwardRef(function({ value: a, onChange: o, format: u = "12h", minute
638
638
  a,
639
639
  u,
640
640
  m
641
- ]), H = u === "12h" ? A : E, U = "flex flex-col gap-ds-01 overflow-y-auto max-h-[200px] px-ds-01", W = "flex h-ds-sm w-full items-center justify-center rounded-control text-ds-md transition-colors duration-fast-01 ease-productive-standard cursor-pointer", G = "bg-accent-9 text-accent-fg", K = "text-surface-fg hover:bg-surface-raised-hover";
641
+ ]), H = u === "12h" ? A : E, U = "flex flex-col gap-ds-01 overflow-y-auto max-h-[200px] px-ds-01", W = "flex h-ds-sm w-full items-center justify-center rounded-control text-body-md transition-colors duration-fast-01 ease-productive-standard cursor-pointer", G = "bg-accent-9 text-accent-fg", K = "text-surface-fg hover:bg-surface-raised-hover";
642
642
  return /* @__PURE__ */ l(n, {
643
643
  open: w,
644
644
  onOpenChange: T,
@@ -657,7 +657,7 @@ var V = s.forwardRef(function({ value: a, onChange: o, format: u = "12h", minute
657
657
  stroke: "light",
658
658
  className: "text-surface-fg-subtle"
659
659
  }), /* @__PURE__ */ c("span", {
660
- className: e("text-ds-md", V ? "text-surface-fg" : "text-surface-fg-subtle"),
660
+ className: e("text-body-md", V ? "text-surface-fg" : "text-surface-fg-subtle"),
661
661
  children: V ?? h
662
662
  })]
663
663
  })
@@ -673,7 +673,7 @@ var V = s.forwardRef(function({ value: a, onChange: o, format: u = "12h", minute
673
673
  /* @__PURE__ */ l("div", {
674
674
  className: "flex flex-col items-center gap-ds-02",
675
675
  children: [/* @__PURE__ */ c("span", {
676
- className: "text-ds-xs font-semibold uppercase tracking-wider text-surface-fg-subtle",
676
+ className: "text-caption font-medium text-surface-fg-subtle",
677
677
  children: "Hr"
678
678
  }), /* @__PURE__ */ c("div", {
679
679
  className: e(U, "min-w-ds-09"),
@@ -690,7 +690,7 @@ var V = s.forwardRef(function({ value: a, onChange: o, format: u = "12h", minute
690
690
  /* @__PURE__ */ l("div", {
691
691
  className: "flex flex-col items-center gap-ds-02",
692
692
  children: [/* @__PURE__ */ c("span", {
693
- className: "text-ds-xs font-semibold uppercase tracking-wider text-surface-fg-subtle",
693
+ className: "text-caption font-medium text-surface-fg-subtle",
694
694
  children: "Min"
695
695
  }), /* @__PURE__ */ c("div", {
696
696
  className: e(U, "min-w-ds-09"),
@@ -707,7 +707,7 @@ var V = s.forwardRef(function({ value: a, onChange: o, format: u = "12h", minute
707
707
  m && /* @__PURE__ */ l("div", {
708
708
  className: "flex flex-col items-center gap-ds-02",
709
709
  children: [/* @__PURE__ */ c("span", {
710
- className: "text-ds-xs font-semibold uppercase tracking-wider text-surface-fg-subtle",
710
+ className: "text-caption font-medium text-surface-fg-subtle",
711
711
  children: "Sec"
712
712
  }), /* @__PURE__ */ c("div", {
713
713
  className: e(U, "min-w-ds-09"),
@@ -724,7 +724,7 @@ var V = s.forwardRef(function({ value: a, onChange: o, format: u = "12h", minute
724
724
  u === "12h" && /* @__PURE__ */ l("div", {
725
725
  className: "flex flex-col items-center gap-ds-02",
726
726
  children: [/* @__PURE__ */ c("span", {
727
- className: "text-ds-xs font-semibold uppercase tracking-wider text-surface-fg-subtle",
727
+ className: "text-caption font-medium text-surface-fg-subtle",
728
728
  children: "\xA0"
729
729
  }), /* @__PURE__ */ c("div", {
730
730
  className: "flex flex-col gap-ds-01 px-ds-01",