@devalok/shilp-sutra 0.55.1 → 0.57.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 (270) hide show
  1. package/BREAKING.json +13 -0
  2. package/MIGRATION.md +163 -0
  3. package/README.md +16 -1
  4. package/dist/_chunks/badge-group.js +92 -78
  5. package/dist/_chunks/badge-group.js.map +1 -1
  6. package/dist/_chunks/chat.js +91 -75
  7. package/dist/_chunks/chat.js.map +1 -1
  8. package/dist/_chunks/document-preview.js +1 -1
  9. package/dist/_chunks/document-preview.js.map +1 -1
  10. package/dist/_chunks/emoji-suggestion.js +32 -30
  11. package/dist/_chunks/emoji-suggestion.js.map +1 -1
  12. package/dist/_chunks/mention-suggestion.js +36 -35
  13. package/dist/_chunks/mention-suggestion.js.map +1 -1
  14. package/dist/_chunks/oauth-button.js +1 -1
  15. package/dist/_chunks/oauth-button.js.map +1 -1
  16. package/dist/_chunks/primitives-internal.js +437 -537
  17. package/dist/_chunks/primitives-internal.js.map +1 -1
  18. package/dist/_chunks/success.js +2 -2
  19. package/dist/_chunks/success.js.map +1 -1
  20. package/dist/_chunks/tree-view.js +1 -1
  21. package/dist/_chunks/tree-view.js.map +1 -1
  22. package/dist/_chunks/use-calendar.js +4 -4
  23. package/dist/_chunks/use-calendar.js.map +1 -1
  24. package/dist/ai/blocks/text.js +1 -1
  25. package/dist/ai/blocks/text.js.map +1 -1
  26. package/dist/ai/command-bar.js +9 -9
  27. package/dist/ai/command-bar.js.map +1 -1
  28. package/dist/ai/conversation.js +2 -2
  29. package/dist/ai/conversation.js.map +1 -1
  30. package/dist/composed/activity-feed.js +1 -1
  31. package/dist/composed/activity-feed.js.map +1 -1
  32. package/dist/composed/avatar-group.d.ts +7 -2
  33. package/dist/composed/avatar-group.d.ts.map +1 -1
  34. package/dist/composed/avatar-group.js +3 -3
  35. package/dist/composed/avatar-group.js.map +1 -1
  36. package/dist/composed/command-palette.js +7 -7
  37. package/dist/composed/command-palette.js.map +1 -1
  38. package/dist/composed/content-card.js +20 -20
  39. package/dist/composed/content-card.js.map +1 -1
  40. package/dist/composed/date-picker/index.js +4 -4
  41. package/dist/composed/date-picker/index.js.map +1 -1
  42. package/dist/composed/diff.d.ts +23 -2
  43. package/dist/composed/diff.d.ts.map +1 -1
  44. package/dist/composed/diff.js +341 -260
  45. package/dist/composed/diff.js.map +1 -1
  46. package/dist/composed/emoji-picker.js +3 -3
  47. package/dist/composed/emoji-picker.js.map +1 -1
  48. package/dist/composed/error-boundary.js +2 -2
  49. package/dist/composed/error-boundary.js.map +1 -1
  50. package/dist/composed/extensions/emoji-node.js +8 -7
  51. package/dist/composed/extensions/emoji-node.js.map +1 -1
  52. package/dist/composed/file-preview.js +1 -1
  53. package/dist/composed/file-preview.js.map +1 -1
  54. package/dist/composed/filter-bar.js +1 -1
  55. package/dist/composed/filter-bar.js.map +1 -1
  56. package/dist/composed/inline-edit.js +1 -1
  57. package/dist/composed/inline-edit.js.map +1 -1
  58. package/dist/composed/loading-skeleton.js +3 -3
  59. package/dist/composed/loading-skeleton.js.map +1 -1
  60. package/dist/composed/master-detail.js +1 -1
  61. package/dist/composed/master-detail.js.map +1 -1
  62. package/dist/composed/member-picker.js +1 -1
  63. package/dist/composed/member-picker.js.map +1 -1
  64. package/dist/composed/multi-select-popover.js +1 -1
  65. package/dist/composed/multi-select-popover.js.map +1 -1
  66. package/dist/composed/page-skeletons.js +4 -4
  67. package/dist/composed/page-skeletons.js.map +1 -1
  68. package/dist/composed/responsive-modal.js +1 -1
  69. package/dist/composed/responsive-modal.js.map +1 -1
  70. package/dist/composed/rich-chat-input.js +549 -540
  71. package/dist/composed/rich-chat-input.js.map +1 -1
  72. package/dist/composed/rich-text-editor.js +206 -198
  73. package/dist/composed/rich-text-editor.js.map +1 -1
  74. package/dist/composed/schedule-view.js +5 -5
  75. package/dist/composed/schedule-view.js.map +1 -1
  76. package/dist/hooks/index.d.ts +1 -0
  77. package/dist/hooks/index.d.ts.map +1 -1
  78. package/dist/hooks/index.js +4 -3
  79. package/dist/hooks/use-container-size.d.ts +18 -0
  80. package/dist/hooks/use-container-size.d.ts.map +1 -0
  81. package/dist/hooks/use-container-size.js +28 -0
  82. package/dist/hooks/use-container-size.js.map +1 -0
  83. package/dist/shell/app-shell.d.ts +101 -0
  84. package/dist/shell/app-shell.d.ts.map +1 -0
  85. package/dist/shell/app-shell.js +76 -0
  86. package/dist/shell/app-shell.js.map +1 -0
  87. package/dist/shell/bottom-navbar.js +2 -2
  88. package/dist/shell/bottom-navbar.js.map +1 -1
  89. package/dist/shell/index.d.ts +1 -0
  90. package/dist/shell/index.d.ts.map +1 -1
  91. package/dist/shell/index.js +6 -5
  92. package/dist/shell/notification-center.js +4 -4
  93. package/dist/shell/notification-center.js.map +1 -1
  94. package/dist/shell/notification-preferences.js +1 -1
  95. package/dist/shell/notification-preferences.js.map +1 -1
  96. package/dist/shell/top-bar.js +7 -7
  97. package/dist/shell/top-bar.js.map +1 -1
  98. package/dist/tokens/generate-scale.d.ts +49 -0
  99. package/dist/tokens/generate-scale.d.ts.map +1 -1
  100. package/dist/tokens/primitives.css +29 -26
  101. package/dist/tokens/semantic.css +98 -39
  102. package/dist/tokens/variants.css +1 -1
  103. package/dist/ui/accordion.js +1 -1
  104. package/dist/ui/accordion.js.map +1 -1
  105. package/dist/ui/alert-dialog.js +1 -1
  106. package/dist/ui/alert-dialog.js.map +1 -1
  107. package/dist/ui/alert.d.ts.map +1 -1
  108. package/dist/ui/alert.js +36 -36
  109. package/dist/ui/alert.js.map +1 -1
  110. package/dist/ui/avatar.js +44 -44
  111. package/dist/ui/avatar.js.map +1 -1
  112. package/dist/ui/badge-indicator.js +1 -1
  113. package/dist/ui/badge-indicator.js.map +1 -1
  114. package/dist/ui/badge.d.ts +47 -33
  115. package/dist/ui/badge.d.ts.map +1 -1
  116. package/dist/ui/banner.js +26 -26
  117. package/dist/ui/banner.js.map +1 -1
  118. package/dist/ui/button.js +35 -35
  119. package/dist/ui/button.js.map +1 -1
  120. package/dist/ui/card.js +42 -42
  121. package/dist/ui/card.js.map +1 -1
  122. package/dist/ui/chat/date-separator.d.ts +8 -1
  123. package/dist/ui/chat/date-separator.d.ts.map +1 -1
  124. package/dist/ui/checkbox.js +1 -1
  125. package/dist/ui/checkbox.js.map +1 -1
  126. package/dist/ui/code.js +2 -2
  127. package/dist/ui/code.js.map +1 -1
  128. package/dist/ui/color-input.js +3 -3
  129. package/dist/ui/color-input.js.map +1 -1
  130. package/dist/ui/combobox.js +139 -139
  131. package/dist/ui/combobox.js.map +1 -1
  132. package/dist/ui/context-menu.js +4 -4
  133. package/dist/ui/context-menu.js.map +1 -1
  134. package/dist/ui/data-table-body.d.ts +3 -1
  135. package/dist/ui/data-table-body.d.ts.map +1 -1
  136. package/dist/ui/data-table-body.js +93 -92
  137. package/dist/ui/data-table-body.js.map +1 -1
  138. package/dist/ui/data-table-bulk-actions.d.ts +7 -1
  139. package/dist/ui/data-table-bulk-actions.d.ts.map +1 -1
  140. package/dist/ui/data-table-bulk-actions.js +14 -8
  141. package/dist/ui/data-table-bulk-actions.js.map +1 -1
  142. package/dist/ui/data-table-card.d.ts.map +1 -1
  143. package/dist/ui/data-table-card.js +66 -47
  144. package/dist/ui/data-table-card.js.map +1 -1
  145. package/dist/ui/data-table-context.d.ts +4 -0
  146. package/dist/ui/data-table-context.d.ts.map +1 -1
  147. package/dist/ui/data-table-context.js.map +1 -1
  148. package/dist/ui/data-table-header.d.ts.map +1 -1
  149. package/dist/ui/data-table-header.js +18 -15
  150. package/dist/ui/data-table-header.js.map +1 -1
  151. package/dist/ui/data-table-pagination.js +3 -3
  152. package/dist/ui/data-table-pagination.js.map +1 -1
  153. package/dist/ui/data-table-toolbar.d.ts +11 -1
  154. package/dist/ui/data-table-toolbar.d.ts.map +1 -1
  155. package/dist/ui/data-table-toolbar.js +7 -7
  156. package/dist/ui/data-table-toolbar.js.map +1 -1
  157. package/dist/ui/data-table.d.ts +52 -5
  158. package/dist/ui/data-table.d.ts.map +1 -1
  159. package/dist/ui/data-table.js +181 -169
  160. package/dist/ui/data-table.js.map +1 -1
  161. package/dist/ui/dialog.js +1 -1
  162. package/dist/ui/dialog.js.map +1 -1
  163. package/dist/ui/dot.js +13 -13
  164. package/dist/ui/dot.js.map +1 -1
  165. package/dist/ui/dropdown-menu.js +4 -4
  166. package/dist/ui/dropdown-menu.js.map +1 -1
  167. package/dist/ui/file-upload.js +3 -3
  168. package/dist/ui/file-upload.js.map +1 -1
  169. package/dist/ui/input-otp.js +1 -1
  170. package/dist/ui/input-otp.js.map +1 -1
  171. package/dist/ui/input.js +30 -30
  172. package/dist/ui/input.js.map +1 -1
  173. package/dist/ui/lib/utils.js +2 -1
  174. package/dist/ui/lib/utils.js.map +1 -1
  175. package/dist/ui/menubar.js +5 -5
  176. package/dist/ui/menubar.js.map +1 -1
  177. package/dist/ui/navigation-menu.js +1 -1
  178. package/dist/ui/navigation-menu.js.map +1 -1
  179. package/dist/ui/number-input.js +36 -36
  180. package/dist/ui/number-input.js.map +1 -1
  181. package/dist/ui/pagination.js +1 -1
  182. package/dist/ui/pagination.js.map +1 -1
  183. package/dist/ui/progress-ring.js +2 -2
  184. package/dist/ui/progress-ring.js.map +1 -1
  185. package/dist/ui/progress.d.ts.map +1 -1
  186. package/dist/ui/progress.js +66 -62
  187. package/dist/ui/progress.js.map +1 -1
  188. package/dist/ui/radio.js +1 -1
  189. package/dist/ui/radio.js.map +1 -1
  190. package/dist/ui/select.js +61 -61
  191. package/dist/ui/select.js.map +1 -1
  192. package/dist/ui/sheet.js +47 -47
  193. package/dist/ui/sheet.js.map +1 -1
  194. package/dist/ui/sidebar.js +132 -132
  195. package/dist/ui/sidebar.js.map +1 -1
  196. package/dist/ui/skeleton.js +39 -39
  197. package/dist/ui/slider.js +18 -18
  198. package/dist/ui/slider.js.map +1 -1
  199. package/dist/ui/split-button.js +3 -3
  200. package/dist/ui/split-button.js.map +1 -1
  201. package/dist/ui/stat-card.js +1 -1
  202. package/dist/ui/stat-card.js.map +1 -1
  203. package/dist/ui/stepper.js +2 -2
  204. package/dist/ui/stepper.js.map +1 -1
  205. package/dist/ui/surface.d.ts.map +1 -1
  206. package/dist/ui/surface.js +11 -11
  207. package/dist/ui/surface.js.map +1 -1
  208. package/dist/ui/switch.js +1 -1
  209. package/dist/ui/switch.js.map +1 -1
  210. package/dist/ui/table.js +1 -1
  211. package/dist/ui/table.js.map +1 -1
  212. package/dist/ui/tabs.d.ts.map +1 -1
  213. package/dist/ui/tabs.js +48 -48
  214. package/dist/ui/tabs.js.map +1 -1
  215. package/dist/ui/text.js +8 -8
  216. package/dist/ui/textarea.js +17 -17
  217. package/dist/ui/textarea.js.map +1 -1
  218. package/dist/ui/toast.js +1 -1
  219. package/dist/ui/toast.js.map +1 -1
  220. package/dist/ui/toggle.js +15 -15
  221. package/dist/ui/toggle.js.map +1 -1
  222. package/docs/components/composed/avatar-group.md +4 -4
  223. package/docs/components/composed/diff.md +10 -2
  224. package/docs/components/composed/schedule-view.md +1 -1
  225. package/docs/components/shell/app-shell.md +132 -0
  226. package/docs/components/ui/avatar.md +1 -1
  227. package/docs/components/ui/button.md +1 -1
  228. package/docs/components/ui/chat.md +7 -1
  229. package/docs/components/ui/color-swatch.md +1 -1
  230. package/docs/components/ui/data-table-toolbar.md +6 -2
  231. package/docs/components/ui/data-table.md +41 -7
  232. package/docs/components/ui/dot.md +1 -1
  233. package/docs/components/ui/progress.md +1 -0
  234. package/docs/components/ui/surface.md +3 -3
  235. package/docs/components/ui/table.md +2 -2
  236. package/docs/recipes/install-astro.md +3 -2
  237. package/docs/recipes/install-next-app-router.md +3 -2
  238. package/docs/recipes/install-remix.md +3 -2
  239. package/docs/recipes/install-tanstack-start.md +3 -2
  240. package/docs/recipes/install-vite.md +3 -2
  241. package/docs/recipes/troubleshoot.md +26 -5
  242. package/llms.txt +2 -1
  243. package/make-kit/Guidelines.md +2 -2
  244. package/make-kit/components/button.md +1 -1
  245. package/make-kit/components/card.md +6 -6
  246. package/make-kit/components/surface.md +4 -4
  247. package/make-kit/foundations/color.md +4 -4
  248. package/make-kit/foundations/dark-mode.md +1 -1
  249. package/make-kit/foundations/radius.md +1 -1
  250. package/make-kit/foundations/surfaces.md +9 -9
  251. package/mcp-manifest.json +373 -34
  252. package/package.json +43 -13
  253. package/skill/SKILL.md +12 -6
  254. package/skill/references/components.md +2 -1
  255. package/skill/references/setup-astro.md +3 -2
  256. package/skill/references/setup-next-app-router.md +3 -2
  257. package/skill/references/setup-remix.md +3 -2
  258. package/skill/references/setup-tanstack-start.md +3 -2
  259. package/skill/references/setup-vite.md +3 -2
  260. package/skill/references/troubleshoot.md +26 -5
  261. package/dist/_chunks/tiptap.js +0 -18809
  262. package/dist/_chunks/tiptap.js.map +0 -1
  263. package/dist/_chunks/vendor-utils.js +0 -1766
  264. package/dist/_chunks/vendor-utils.js.map +0 -1
  265. package/dist/primitives/react-toast.d.ts +0 -120
  266. package/dist/ui/charts/_internal/scales.d.ts +0 -5
  267. package/dist/ui/charts/_internal/scales.d.ts.map +0 -1
  268. package/dist/ui/lib/slot.d.ts +0 -8
  269. package/dist/ui/lib/slot.d.ts.map +0 -1
  270. package/scripts/welcome.mjs +0 -312
@@ -1 +1 @@
1
- {"version":3,"file":"card.js","names":[],"sources":["../../src/ui/card.tsx"],"sourcesContent":["'use client'\n\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { motionProps, springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\n// Bundlers (Vite, Next.js, webpack) define process.env.NODE_ENV; guard for raw ESM.\ndeclare const process: { env: { NODE_ENV?: string } } | undefined\n\ntype CardSize = 'sm' | 'md' | 'lg'\n\nconst cardVariants = cva(\n // Gap model, variable-driven: `size` sets --card-spacing / --card-gap once on the\n // container; the container reads them for its vertical edge (py) and inter-slot\n // rhythm (gap), slots read the same variables for their horizontal inset (px), and\n // CardAction/CardBleed read them for corner offsets / negative margins. One variable\n // pair is the whole size system — override it with a single arbitrary property\n // (`[--card-spacing:var(--spacing-ds-07)]`) and every part follows.\n // No per-slot py, no pt-0, no per-element margins — adding/removing a slot can't\n // unbalance the bottom edge (make-kit rule: shadow ring is the edge, gap is the rhythm).\n // `relative` establishes the positioning context for <CardAction> corner slots.\n 'relative flex text-surface-fg rounded-surface transition-shadow duration-fast-02 ease-productive-standard',\n {\n variants: {\n variant: {\n // Tonal (default): depth from a surface-tone shift + a whisper hairline in the\n // surface's own colour (`border-card`), NO shadow — the DS-wide anti-slop edge\n // (Setu tonal-elevation). The `color` prop overrides the hairline colour to paint\n // a deliberate accent/status edge.\n default: 'bg-surface-raised border border-card shadow-none',\n // Elevation-led: the shadow's own ring is the edge (make-kit rule #6 — no\n // border+shadow double-edge). Reach for it when a card should visibly pop\n // (a dragged tile, a spotlight panel). border-transparent keeps `color` paintable.\n elevated: 'bg-surface-raised border border-transparent shadow-raised-hover',\n // Border-led, strong: a firmly visible edge, no shadow.\n outline: 'bg-transparent border border-surface-border-strong shadow-none',\n flat: 'bg-surface-raised border-none shadow-none',\n },\n color: {\n default: '',\n accent: 'border-accent-7',\n error: 'border-error-7',\n success: 'border-success-7',\n warning: 'border-warning-7',\n info: 'border-info-7',\n neutral: '',\n },\n // size only assigns the two variables; the orientation axis decides where\n // they're consumed (container in vertical, <CardSection> in horizontal).\n size: {\n sm: '[--card-spacing:var(--spacing-ds-05)] [--card-gap:var(--spacing-ds-03)]',\n md: '[--card-spacing:var(--spacing-ds-05b)] [--card-gap:var(--spacing-ds-04)]',\n lg: '[--card-spacing:var(--spacing-ds-06)] [--card-gap:var(--spacing-ds-05)]',\n },\n // vertical: the container owns py + gap (the default gap model).\n // horizontal: the container is a padding-less row; a <CardSection> child\n // re-establishes py + gap for the text column while a media pane owns an edge.\n orientation: {\n vertical: 'flex-col py-(--card-spacing) gap-(--card-gap)',\n horizontal: 'flex-row items-stretch',\n },\n },\n defaultVariants: { variant: 'default', color: 'default', size: 'md', orientation: 'vertical' },\n },\n)\n\n/**\n * Props for Card — a general-purpose content container with 4 elevation/style variants and\n * an optional interactive hover state.\n *\n * **Variants (tonal, elevation-led, or border-led — never border+shadow together):** `default`\n * (tonal — surface shift + `border-card` hairline, no shadow) | `elevated` (shadow-raised-hover,\n * no border — use when a card should visibly pop) | `outline` (strong visible border, no shadow) |\n * `flat` (filled background, no edge). The shadow tokens carry their own 1px ring, so `elevated`\n * needs no explicit border (make-kit rule #6).\n *\n * **Composition:** Use sub-components `<CardHeader>`, `<CardTitle>`, `<CardDescription>`,\n * `<CardContent>`, and `<CardFooter>` for consistent internal spacing. Text content must live\n * inside a slot — raw text as a direct child gets no horizontal inset (direct children span the\n * full card width by design, which is what makes full-width dividers and bands free).\n *\n * **Spacing:** `size` sets `--card-spacing` / `--card-gap` once; container, slots, `CardAction`,\n * and `CardBleed` all read the same pair. Retune a card with a single override:\n * `className=\"[--card-spacing:var(--spacing-ds-07)]\"`.\n *\n * **Interactive:** Pass `interactive` to enable hover shadow lift and pointer cursor —\n * useful for clickable cards in grids.\n *\n * @example\n * // Standard content card with header and body:\n * <Card>\n * <CardHeader>\n * <CardTitle>Project Alpha</CardTitle>\n * <CardDescription>Last updated 2 hours ago</CardDescription>\n * </CardHeader>\n * <CardContent>\n * <p>Sprint 4 is in progress with 12 open tasks.</p>\n * </CardContent>\n * </Card>\n *\n * @example\n * // Full-bleed cover image + edge-to-edge divider:\n * <Card>\n * <CardBleed side=\"top\"><img src={cover} alt=\"\" /></CardBleed>\n * <CardHeader><CardTitle>Muhurat launch site</CardTitle></CardHeader>\n * <Separator />\n * <CardFooter><Badge color=\"success\">On track</Badge></CardFooter>\n * </Card>\n *\n * @example\n * // Horizontal media card — media pane owns the left edge, CardSection restores rhythm:\n * <Card orientation=\"horizontal\">\n * <div className=\"w-32 shrink-0 rounded-l-surface overflow-hidden\">\n * <img src={thumb} alt=\"\" className=\"h-full w-full object-cover\" />\n * </div>\n * <CardSection>\n * <CardHeader><CardTitle>Field notes</CardTitle></CardHeader>\n * <CardFooter>edited yesterday</CardFooter>\n * </CardSection>\n * </Card>\n *\n * @example\n * // Flat card for a sidebar panel section (no shadow):\n * <Card variant=\"flat\">\n * <CardContent>\n * <p className=\"text-surface-fg-muted text-body-sm\">No recent activity</p>\n * </CardContent>\n * </Card>\n */\nexport interface CardProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n VariantProps<typeof cardVariants> {\n interactive?: boolean\n}\n\nexport type { CardSize }\n\nconst Card = React.forwardRef<HTMLDivElement, CardProps>(\n ({ className, variant, color, size, orientation, interactive, children, ...props }, ref) => {\n if (typeof process !== 'undefined' && process?.env.NODE_ENV !== 'production') {\n warnOnUnwrappedTextChildren(children)\n }\n const classes = cn(\n cardVariants({ variant, color, size, orientation }),\n interactive && 'hover:shadow-raised-hover cursor-pointer transition-shadow duration-fast-02 ease-productive-standard',\n className,\n )\n\n if (interactive) {\n return (\n <motion.div\n ref={ref}\n whileHover={{ y: -3 }}\n whileTap={{ scale: 0.98 }}\n transition={springs.snappy}\n className={classes}\n {...motionProps(props)}\n >\n {children}\n </motion.div>\n )\n }\n\n return (\n <div ref={ref} className={classes} {...props}>\n {children}\n </div>\n )\n },\n)\nCard.displayName = 'Card'\n\nconst CardHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col gap-ds-02b px-(--card-spacing) [&>:first-child]:mt-0 [&>:last-child]:mb-0',\n className,\n )}\n {...props}\n />\n))\nCardHeader.displayName = 'CardHeader'\n\nconst CardTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('font-sans font-semibold leading-ds-none tracking-normal text-surface-fg', className)}\n {...props}\n />\n))\nCardTitle.displayName = 'CardTitle'\n\nconst CardDescription = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('text-body-md text-surface-fg-muted', className)}\n {...props}\n />\n))\nCardDescription.displayName = 'CardDescription'\n\nconst CardContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n // Reset first/last child margins so a raw <p>/<h*>'s UA margin can't leak\n // past the slot onto the container's gap-model padding (the bottom-heavy bug).\n 'px-(--card-spacing) [&>:first-child]:mt-0 [&>:last-child]:mb-0',\n className,\n )}\n {...props}\n />\n))\nCardContent.displayName = 'CardContent'\n\nconst CardFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center gap-ds-03 px-(--card-spacing)', className)}\n {...props}\n />\n))\nCardFooter.displayName = 'CardFooter'\n\n/**\n * A vertical stack that re-establishes the card's padding + gap rhythm — the text column\n * of a `<Card orientation=\"horizontal\">`. Reads the same `--card-spacing` / `--card-gap`\n * variables the container sets, so the horizontal card's content column matches a vertical\n * card of the same `size` exactly.\n */\nconst CardSection = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex min-w-0 flex-1 flex-col py-(--card-spacing) gap-(--card-gap)', className)}\n {...props}\n />\n))\nCardSection.displayName = 'CardSection'\n\ntype CardBleedSide = 'x' | 'top' | 'bottom' | 'y' | 'all'\n\nconst bleedSideClasses: Record<CardBleedSide, string> = {\n // Inside a slot: escape the slot's horizontal inset.\n x: '-mx-(--card-spacing)',\n // As a direct child: escape the container's vertical edge (direct children are\n // already full-width — never add `x` bleed to a direct child, it would overflow).\n top: '-mt-(--card-spacing) rounded-t-surface overflow-hidden',\n bottom: '-mb-(--card-spacing) rounded-b-surface overflow-hidden',\n y: '-my-(--card-spacing) rounded-surface overflow-hidden',\n // Inside a slot, escaping every edge (e.g. an image-only card body).\n all: '-my-(--card-spacing) -mx-(--card-spacing) rounded-surface overflow-hidden',\n}\n\nexport interface CardBleedProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Which card padding to negate. `top`/`bottom`/`y` are for direct children of Card\n * (full-bleed media, edge bands) and inherit the card's corner radius; `x`/`all` are\n * for content INSIDE a slot that needs to escape the slot's horizontal inset.\n * Direct children of Card already span its full width — don't use `x`/`all` there.\n * @default 'x'\n */\n side?: CardBleedSide\n}\n\n/**\n * Escape hatch from the card's padding — the shilp-sutra equivalent of Radix Themes'\n * `Inset` / Polaris `Bleed`. Negates the same `--card-spacing` variable the padding\n * reads, so it stays exact across sizes and overrides.\n *\n * @example\n * // Cover image touching the card's top + side edges:\n * <Card>\n * <CardBleed side=\"top\"><img src={cover} alt=\"\" /></CardBleed>\n * <CardHeader><CardTitle>Project</CardTitle></CardHeader>\n * </Card>\n *\n * @example\n * // A tinted band inside CardContent, running edge-to-edge:\n * <CardContent>\n * <CardBleed><div className=\"bg-accent-2 px-(--card-spacing) py-ds-03\">Heads up…</div></CardBleed>\n * </CardContent>\n */\nconst CardBleed = React.forwardRef<HTMLDivElement, CardBleedProps>(\n ({ className, side = 'x', ...props }, ref) => (\n <div ref={ref} className={cn(bleedSideClasses[side], className)} {...props} />\n ),\n)\nCardBleed.displayName = 'CardBleed'\n\ntype CardActionPlacement = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'\n\n// Corner inset reads --card-spacing so an action's edge lines up with the slot\n// content edge at every size.\nconst cornerPositions: Record<CardActionPlacement, string> = {\n 'top-right': 'top-(--card-spacing) right-(--card-spacing)',\n 'top-left': 'top-(--card-spacing) left-(--card-spacing)',\n 'bottom-right': 'bottom-(--card-spacing) right-(--card-spacing)',\n 'bottom-left': 'bottom-(--card-spacing) left-(--card-spacing)',\n}\n\nexport interface CardActionProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Which corner the action sits in. @default 'top-right' */\n placement?: CardActionPlacement\n /**\n * Pull the action a step toward its corner (`-m-ds-02`) so an icon button's GLYPH —\n * not its padding box — aligns to the content-edge line. Use for ghost/icon buttons\n * placed in a corner; leave off for badges/text where the padding box is the edge.\n */\n tuck?: boolean\n}\n\n/**\n * An absolutely-positioned corner slot for a Card — a menu/icon button, a status badge,\n * an overflow action. The Card is `relative`, so this pins to one of its four corners\n * with an inset that matches the card's content padding.\n *\n * @example\n * <Card>\n * <CardAction><IconButton aria-label=\"More\" icon={<IconDots />} variant=\"ghost\" tuck /></CardAction>\n * <CardHeader><CardTitle>Project Alpha</CardTitle></CardHeader>\n * </Card>\n *\n * @example\n * // Accent status badge in the top-right:\n * <Card>\n * <CardAction><Badge color=\"accent\" size=\"xs\">LIVE</Badge></CardAction>\n * ...\n * </Card>\n */\nconst CardAction = React.forwardRef<HTMLDivElement, CardActionProps>(\n ({ className, placement = 'top-right', tuck, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'absolute z-[1] flex items-center gap-ds-02',\n cornerPositions[placement],\n tuck && '-m-ds-02',\n className,\n )}\n {...props}\n />\n ),\n)\nCardAction.displayName = 'CardAction'\n\n// Text-shaped tags that almost certainly expected a slot's horizontal inset.\n// Structural tags (div, section, img, table, hr…) are legitimate full-width direct\n// children, so they stay silent.\nconst TEXTUAL_TAGS = new Set(['p', 'span', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'a', 'label', 'small', 'strong', 'em'])\nlet warnedUnwrappedText = false\n\nfunction warnOnUnwrappedTextChildren(children: React.ReactNode): void {\n if (warnedUnwrappedText) return\n React.Children.forEach(children, (child) => {\n const isBareText = typeof child === 'string' && child.trim() !== ''\n const isTextualTag =\n React.isValidElement(child) &&\n typeof child.type === 'string' &&\n TEXTUAL_TAGS.has(child.type)\n if (isBareText || isTextualTag) {\n warnedUnwrappedText = true\n console.warn(\n '[shilp-sutra] <Card> received text content as a direct child. Direct children span the full card width and get no horizontal inset — wrap text in <CardContent> (or <CardHeader>/<CardFooter>). See the Card docs, \"Composition\".',\n )\n }\n })\n}\n\nexport { Card, CardAction, CardBleed, CardContent, CardDescription, CardFooter, CardHeader, CardSection, CardTitle, cardVariants }\nexport type { CardActionPlacement, CardBleedSide }\n"],"mappings":"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"}
1
+ {"version":3,"file":"card.js","names":[],"sources":["../../src/ui/card.tsx"],"sourcesContent":["'use client'\n\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { motionProps, springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\n// Bundlers (Vite, Next.js, webpack) define process.env.NODE_ENV; guard for raw ESM.\ndeclare const process: { env: { NODE_ENV?: string } } | undefined\n\ntype CardSize = 'sm' | 'md' | 'lg'\n\nconst cardVariants = cva(\n // Gap model, variable-driven: `size` sets --card-spacing / --card-gap once on the\n // container; the container reads them for its vertical edge (py) and inter-slot\n // rhythm (gap), slots read the same variables for their horizontal inset (px), and\n // CardAction/CardBleed read them for corner offsets / negative margins. One variable\n // pair is the whole size system — override it with a single arbitrary property\n // (`[--card-spacing:var(--spacing-ds-07)]`) and every part follows.\n // No per-slot py, no pt-0, no per-element margins — adding/removing a slot can't\n // unbalance the bottom edge (make-kit rule: shadow ring is the edge, gap is the rhythm).\n // `relative` establishes the positioning context for <CardAction> corner slots.\n 'relative flex text-surface-fg rounded-surface transition-shadow duration-fast-02 ease-productive-standard',\n {\n variants: {\n variant: {\n // Tonal (default): depth from a surface-tone shift + a whisper hairline in the\n // surface's own colour (`border-card`), NO shadow — the DS-wide anti-slop edge\n // (Setu tonal-elevation). The `color` prop overrides the hairline colour to paint\n // a deliberate accent/status edge.\n default: 'bg-surface-panel border border-card shadow-none',\n // Elevation-led: the shadow's own ring is the edge (make-kit rule #6 — no\n // border+shadow double-edge). Reach for it when a card should visibly pop\n // (a dragged tile, a spotlight panel). border-transparent keeps `color` paintable.\n elevated: 'bg-surface-panel border border-transparent shadow-raised-hover',\n // Border-led, strong: a firmly visible edge, no shadow.\n outline: 'bg-transparent border border-surface-border-strong shadow-none',\n flat: 'bg-surface-panel border-none shadow-none',\n },\n color: {\n default: '',\n accent: 'border-accent-7',\n error: 'border-error-7',\n success: 'border-success-7',\n warning: 'border-warning-7',\n info: 'border-info-7',\n neutral: '',\n },\n // size only assigns the two variables; the orientation axis decides where\n // they're consumed (container in vertical, <CardSection> in horizontal).\n size: {\n sm: '[--card-spacing:var(--spacing-ds-05)] [--card-gap:var(--spacing-ds-03)]',\n md: '[--card-spacing:var(--spacing-ds-05b)] [--card-gap:var(--spacing-ds-04)]',\n lg: '[--card-spacing:var(--spacing-ds-06)] [--card-gap:var(--spacing-ds-05)]',\n },\n // vertical: the container owns py + gap (the default gap model).\n // horizontal: the container is a padding-less row; a <CardSection> child\n // re-establishes py + gap for the text column while a media pane owns an edge.\n orientation: {\n vertical: 'flex-col py-(--card-spacing) gap-(--card-gap)',\n horizontal: 'flex-row items-stretch',\n },\n },\n defaultVariants: { variant: 'default', color: 'default', size: 'md', orientation: 'vertical' },\n },\n)\n\n/**\n * Props for Card — a general-purpose content container with 4 elevation/style variants and\n * an optional interactive hover state.\n *\n * **Variants (tonal, elevation-led, or border-led — never border+shadow together):** `default`\n * (tonal — surface shift + `border-card` hairline, no shadow) | `elevated` (shadow-raised-hover,\n * no border — use when a card should visibly pop) | `outline` (strong visible border, no shadow) |\n * `flat` (filled background, no edge). The shadow tokens carry their own 1px ring, so `elevated`\n * needs no explicit border (make-kit rule #6).\n *\n * **Composition:** Use sub-components `<CardHeader>`, `<CardTitle>`, `<CardDescription>`,\n * `<CardContent>`, and `<CardFooter>` for consistent internal spacing. Text content must live\n * inside a slot — raw text as a direct child gets no horizontal inset (direct children span the\n * full card width by design, which is what makes full-width dividers and bands free).\n *\n * **Spacing:** `size` sets `--card-spacing` / `--card-gap` once; container, slots, `CardAction`,\n * and `CardBleed` all read the same pair. Retune a card with a single override:\n * `className=\"[--card-spacing:var(--spacing-ds-07)]\"`.\n *\n * **Interactive:** Pass `interactive` to enable hover shadow lift and pointer cursor —\n * useful for clickable cards in grids.\n *\n * @example\n * // Standard content card with header and body:\n * <Card>\n * <CardHeader>\n * <CardTitle>Project Alpha</CardTitle>\n * <CardDescription>Last updated 2 hours ago</CardDescription>\n * </CardHeader>\n * <CardContent>\n * <p>Sprint 4 is in progress with 12 open tasks.</p>\n * </CardContent>\n * </Card>\n *\n * @example\n * // Full-bleed cover image + edge-to-edge divider:\n * <Card>\n * <CardBleed side=\"top\"><img src={cover} alt=\"\" /></CardBleed>\n * <CardHeader><CardTitle>Muhurat launch site</CardTitle></CardHeader>\n * <Separator />\n * <CardFooter><Badge color=\"success\">On track</Badge></CardFooter>\n * </Card>\n *\n * @example\n * // Horizontal media card — media pane owns the left edge, CardSection restores rhythm:\n * <Card orientation=\"horizontal\">\n * <div className=\"w-32 shrink-0 rounded-l-surface overflow-hidden\">\n * <img src={thumb} alt=\"\" className=\"h-full w-full object-cover\" />\n * </div>\n * <CardSection>\n * <CardHeader><CardTitle>Field notes</CardTitle></CardHeader>\n * <CardFooter>edited yesterday</CardFooter>\n * </CardSection>\n * </Card>\n *\n * @example\n * // Flat card for a sidebar panel section (no shadow):\n * <Card variant=\"flat\">\n * <CardContent>\n * <p className=\"text-surface-fg-muted text-body-sm\">No recent activity</p>\n * </CardContent>\n * </Card>\n */\nexport interface CardProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n VariantProps<typeof cardVariants> {\n interactive?: boolean\n}\n\nexport type { CardSize }\n\nconst Card = React.forwardRef<HTMLDivElement, CardProps>(\n ({ className, variant, color, size, orientation, interactive, children, ...props }, ref) => {\n if (typeof process !== 'undefined' && process?.env.NODE_ENV !== 'production') {\n warnOnUnwrappedTextChildren(children)\n }\n const classes = cn(\n cardVariants({ variant, color, size, orientation }),\n interactive && 'hover:bg-surface-panel-hover cursor-pointer transition-colors duration-fast-02 ease-productive-standard',\n className,\n )\n\n if (interactive) {\n return (\n <motion.div\n ref={ref}\n whileHover={{ y: -3 }}\n whileTap={{ scale: 0.98 }}\n transition={springs.snappy}\n className={classes}\n {...motionProps(props)}\n >\n {children}\n </motion.div>\n )\n }\n\n return (\n <div ref={ref} className={classes} {...props}>\n {children}\n </div>\n )\n },\n)\nCard.displayName = 'Card'\n\nconst CardHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col gap-ds-02b px-(--card-spacing) [&>:first-child]:mt-0 [&>:last-child]:mb-0',\n className,\n )}\n {...props}\n />\n))\nCardHeader.displayName = 'CardHeader'\n\nconst CardTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('font-sans font-semibold leading-ds-none tracking-normal text-surface-fg', className)}\n {...props}\n />\n))\nCardTitle.displayName = 'CardTitle'\n\nconst CardDescription = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('text-body-md text-surface-fg-muted', className)}\n {...props}\n />\n))\nCardDescription.displayName = 'CardDescription'\n\nconst CardContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n // Reset first/last child margins so a raw <p>/<h*>'s UA margin can't leak\n // past the slot onto the container's gap-model padding (the bottom-heavy bug).\n 'px-(--card-spacing) [&>:first-child]:mt-0 [&>:last-child]:mb-0',\n className,\n )}\n {...props}\n />\n))\nCardContent.displayName = 'CardContent'\n\nconst CardFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center gap-ds-03 px-(--card-spacing)', className)}\n {...props}\n />\n))\nCardFooter.displayName = 'CardFooter'\n\n/**\n * A vertical stack that re-establishes the card's padding + gap rhythm — the text column\n * of a `<Card orientation=\"horizontal\">`. Reads the same `--card-spacing` / `--card-gap`\n * variables the container sets, so the horizontal card's content column matches a vertical\n * card of the same `size` exactly.\n */\nconst CardSection = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex min-w-0 flex-1 flex-col py-(--card-spacing) gap-(--card-gap)', className)}\n {...props}\n />\n))\nCardSection.displayName = 'CardSection'\n\ntype CardBleedSide = 'x' | 'top' | 'bottom' | 'y' | 'all'\n\nconst bleedSideClasses: Record<CardBleedSide, string> = {\n // Inside a slot: escape the slot's horizontal inset.\n x: '-mx-(--card-spacing)',\n // As a direct child: escape the container's vertical edge (direct children are\n // already full-width — never add `x` bleed to a direct child, it would overflow).\n top: '-mt-(--card-spacing) rounded-t-surface overflow-hidden',\n bottom: '-mb-(--card-spacing) rounded-b-surface overflow-hidden',\n y: '-my-(--card-spacing) rounded-surface overflow-hidden',\n // Inside a slot, escaping every edge (e.g. an image-only card body).\n all: '-my-(--card-spacing) -mx-(--card-spacing) rounded-surface overflow-hidden',\n}\n\nexport interface CardBleedProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Which card padding to negate. `top`/`bottom`/`y` are for direct children of Card\n * (full-bleed media, edge bands) and inherit the card's corner radius; `x`/`all` are\n * for content INSIDE a slot that needs to escape the slot's horizontal inset.\n * Direct children of Card already span its full width — don't use `x`/`all` there.\n * @default 'x'\n */\n side?: CardBleedSide\n}\n\n/**\n * Escape hatch from the card's padding — the shilp-sutra equivalent of Radix Themes'\n * `Inset` / Polaris `Bleed`. Negates the same `--card-spacing` variable the padding\n * reads, so it stays exact across sizes and overrides.\n *\n * @example\n * // Cover image touching the card's top + side edges:\n * <Card>\n * <CardBleed side=\"top\"><img src={cover} alt=\"\" /></CardBleed>\n * <CardHeader><CardTitle>Project</CardTitle></CardHeader>\n * </Card>\n *\n * @example\n * // A tinted band inside CardContent, running edge-to-edge:\n * <CardContent>\n * <CardBleed><div className=\"bg-accent-2 px-(--card-spacing) py-ds-03\">Heads up…</div></CardBleed>\n * </CardContent>\n */\nconst CardBleed = React.forwardRef<HTMLDivElement, CardBleedProps>(\n ({ className, side = 'x', ...props }, ref) => (\n <div ref={ref} className={cn(bleedSideClasses[side], className)} {...props} />\n ),\n)\nCardBleed.displayName = 'CardBleed'\n\ntype CardActionPlacement = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'\n\n// Corner inset reads --card-spacing so an action's edge lines up with the slot\n// content edge at every size.\nconst cornerPositions: Record<CardActionPlacement, string> = {\n 'top-right': 'top-(--card-spacing) right-(--card-spacing)',\n 'top-left': 'top-(--card-spacing) left-(--card-spacing)',\n 'bottom-right': 'bottom-(--card-spacing) right-(--card-spacing)',\n 'bottom-left': 'bottom-(--card-spacing) left-(--card-spacing)',\n}\n\nexport interface CardActionProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Which corner the action sits in. @default 'top-right' */\n placement?: CardActionPlacement\n /**\n * Pull the action a step toward its corner (`-m-ds-02`) so an icon button's GLYPH —\n * not its padding box — aligns to the content-edge line. Use for ghost/icon buttons\n * placed in a corner; leave off for badges/text where the padding box is the edge.\n */\n tuck?: boolean\n}\n\n/**\n * An absolutely-positioned corner slot for a Card — a menu/icon button, a status badge,\n * an overflow action. The Card is `relative`, so this pins to one of its four corners\n * with an inset that matches the card's content padding.\n *\n * @example\n * <Card>\n * <CardAction><IconButton aria-label=\"More\" icon={<IconDots />} variant=\"ghost\" tuck /></CardAction>\n * <CardHeader><CardTitle>Project Alpha</CardTitle></CardHeader>\n * </Card>\n *\n * @example\n * // Accent status badge in the top-right:\n * <Card>\n * <CardAction><Badge color=\"accent\" size=\"xs\">LIVE</Badge></CardAction>\n * ...\n * </Card>\n */\nconst CardAction = React.forwardRef<HTMLDivElement, CardActionProps>(\n ({ className, placement = 'top-right', tuck, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'absolute z-[1] flex items-center gap-ds-02',\n cornerPositions[placement],\n tuck && '-m-ds-02',\n className,\n )}\n {...props}\n />\n ),\n)\nCardAction.displayName = 'CardAction'\n\n// Text-shaped tags that almost certainly expected a slot's horizontal inset.\n// Structural tags (div, section, img, table, hr…) are legitimate full-width direct\n// children, so they stay silent.\nconst TEXTUAL_TAGS = new Set(['p', 'span', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'a', 'label', 'small', 'strong', 'em'])\nlet warnedUnwrappedText = false\n\nfunction warnOnUnwrappedTextChildren(children: React.ReactNode): void {\n if (warnedUnwrappedText) return\n React.Children.forEach(children, (child) => {\n const isBareText = typeof child === 'string' && child.trim() !== ''\n const isTextualTag =\n React.isValidElement(child) &&\n typeof child.type === 'string' &&\n TEXTUAL_TAGS.has(child.type)\n if (isBareText || isTextualTag) {\n warnedUnwrappedText = true\n console.warn(\n '[shilp-sutra] <Card> received text content as a direct child. Direct children span the full card width and get no horizontal inset — wrap text in <CardContent> (or <CardHeader>/<CardFooter>). See the Card docs, \"Composition\".',\n )\n }\n })\n}\n\nexport { Card, CardAction, CardBleed, CardContent, CardDescription, CardFooter, CardHeader, CardSection, CardTitle, cardVariants }\nexport type { CardActionPlacement, CardBleedSide }\n"],"mappings":"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"}
@@ -3,8 +3,15 @@ export interface DateSeparatorProps {
3
3
  date: Date | string;
4
4
  format?: (date: Date) => string;
5
5
  className?: string;
6
+ /** BCP 47 locale for the default label's month name. @default 'en-US' */
7
+ locale?: string;
8
+ /**
9
+ * IANA time zone used for the "Today"/"Yesterday" day-boundary comparison
10
+ * and for formatting. Defaults to the browser's local time zone.
11
+ */
12
+ timeZone?: string;
6
13
  }
7
- declare function DateSeparator({ date, format, className }: DateSeparatorProps): React.JSX.Element;
14
+ declare function DateSeparator({ date, format, className, locale, timeZone }: DateSeparatorProps): React.JSX.Element;
8
15
  declare namespace DateSeparator {
9
16
  var displayName: string;
10
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"date-separator.d.ts","sourceRoot":"","sources":["../../../src/ui/chat/date-separator.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,IAAI,GAAG,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAsBD,iBAAS,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,kBAAkB,qBAarE;kBAbQ,aAAa;;;AAgBtB,OAAO,EAAE,aAAa,EAAE,CAAA"}
1
+ {"version":3,"file":"date-separator.d.ts","sourceRoot":"","sources":["../../../src/ui/chat/date-separator.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,IAAI,GAAG,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAkCD,iBAAS,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAgB,EAAE,QAAQ,EAAE,EAAE,kBAAkB,qBAajG;kBAbQ,aAAa;;;AAgBtB,OAAO,EAAE,aAAa,EAAE,CAAA"}
@@ -29,7 +29,7 @@ var u = {
29
29
  checked: S || h ? k : void 0,
30
30
  defaultChecked: !S && !h ? y : void 0,
31
31
  onCheckedChange: j,
32
- className: t("touch-target peer flex items-center justify-center shrink-0 rounded-control-inner", d[g], "border border-surface-border-strong", "bg-surface-raised-hover", "transition-colors duration-fast-01 ease-productive-standard", "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2", "disabled:cursor-not-allowed disabled:opacity-action-disabled", "data-[state=unchecked]:hover:border-accent-7 data-[state=unchecked]:hover:bg-surface-raised-active", "data-[state=checked]:bg-accent-9 data-[state=checked]:border-accent-7 data-[state=checked]:text-accent-fg", "data-[state=indeterminate]:bg-accent-9 data-[state=indeterminate]:border-accent-7 data-[state=indeterminate]:text-accent-fg", E && u[E], p),
32
+ className: t("touch-target peer flex items-center justify-center shrink-0 rounded-control-inner", d[g], "border border-surface-border-interactive", "bg-surface-panel-hover", "transition-colors duration-fast-01 ease-productive-standard", "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2", "disabled:cursor-not-allowed disabled:opacity-action-disabled", "data-[state=unchecked]:hover:border-accent-7 data-[state=unchecked]:hover:bg-surface-panel-active", "data-[state=checked]:bg-accent-9 data-[state=checked]:border-accent-7 data-[state=checked]:text-accent-fg", "data-[state=indeterminate]:bg-accent-9 data-[state=indeterminate]:border-accent-7 data-[state=indeterminate]:text-accent-fg", E && u[E], p),
33
33
  "aria-invalid": E === "error" || void 0,
34
34
  "aria-describedby": D,
35
35
  "aria-required": O || void 0,
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.js","names":[],"sources":["../../src/ui/checkbox.tsx"],"sourcesContent":["'use client'\n\nimport * as CheckboxPrimitive from '@primitives/react-checkbox'\nimport { AnimatePresence, motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useFormField } from './form'\nimport { type FieldState, resolveFieldState } from './lib/field-state'\nimport { durations } from './lib/motion'\nimport { cn } from './lib/utils'\n\n/** Border + background tint per validation state (checked state uses accent regardless). */\nconst stateTintClasses: Record<Exclude<FieldState, 'default'>, string> = {\n error: 'border-error-7 bg-error-3',\n warning: 'border-warning-7 bg-warning-3',\n success: 'border-success-7 bg-success-3',\n}\n\n/**\n * Props for Checkbox — a Radix-powered accessible checkbox with error state styling and\n * an indeterminate state for \"select all\" row controls.\n *\n * **Indeterminate:** Pass `indeterminate={true}` to show the \"−\" dash (overrides `checked`).\n * This is correct for \"select all\" headers when only some rows are selected.\n *\n * **Controlled:** Use `checked` + `onCheckedChange` for controlled usage.\n * `onCheckedChange` receives `true | false | 'indeterminate'` from Radix.\n *\n * @example\n * // Basic controlled checkbox:\n * <Checkbox checked={agreed} onCheckedChange={(v) => setAgreed(v === true)} />\n *\n * @example\n * // Error state when required checkbox is not checked:\n * <Checkbox state={!termsAccepted ? 'error' : 'default'} checked={termsAccepted} onCheckedChange={(v) => setTerms(v === true)} />\n *\n * @example\n * // \"Select all\" checkbox with indeterminate state:\n * <Checkbox\n * indeterminate={someSelected && !allSelected}\n * checked={allSelected}\n * onCheckedChange={(v) => toggleAll(v === true)}\n * />\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface CheckboxProps extends React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> {\n /** Validation/feedback state. `'error'` also sets `aria-invalid`. Inherited from `FormField` when omitted. */\n state?: FieldState\n indeterminate?: boolean\n /** Control size — `sm` (20px), `md` (24px, default, WCAG compliant), `lg` (28px). */\n size?: 'sm' | 'md' | 'lg'\n}\n\nconst checkboxSizeClasses = {\n sm: 'h-5 w-5',\n md: 'h-6 w-6',\n lg: 'h-7 w-7',\n} as const\n\nconst checkboxIconClasses = {\n sm: 'h-[14px] w-[14px]',\n md: 'h-[18px] w-[18px]',\n lg: 'h-5 w-5',\n} as const\n\nconst Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n CheckboxProps\n>(({ className, state: stateProp, indeterminate, size = 'md', checked, onCheckedChange, defaultChecked, ...props }, ref) => {\n // Track internal state so AnimatePresence works for both controlled & uncontrolled usage\n const isControlled = checked !== undefined\n const [internalChecked, setInternalChecked] = React.useState<boolean | 'indeterminate'>(\n indeterminate ? 'indeterminate' : (defaultChecked ? true : false),\n )\n\n const fieldCtx = useFormField()\n const state = resolveFieldState(stateProp, fieldCtx.state)\n const ariaDescribedBy = props['aria-describedby'] ?? fieldCtx.helperTextId\n const ariaRequired = props['aria-required'] ?? fieldCtx.required\n\n const actualChecked = indeterminate ? 'indeterminate' : (isControlled ? checked : internalChecked)\n const isActive = actualChecked === true || actualChecked === 'indeterminate'\n\n const handleCheckedChange = React.useCallback(\n (value: boolean | 'indeterminate') => {\n if (!isControlled) setInternalChecked(value)\n onCheckedChange?.(value)\n },\n [isControlled, onCheckedChange],\n )\n\n return (\n <CheckboxPrimitive.Root\n ref={ref}\n checked={isControlled || indeterminate ? actualChecked : undefined}\n defaultChecked={!isControlled && !indeterminate ? defaultChecked : undefined}\n onCheckedChange={handleCheckedChange}\n className={cn(\n 'touch-target peer flex items-center justify-center shrink-0 rounded-control-inner',\n checkboxSizeClasses[size],\n 'border border-surface-border-strong',\n 'bg-surface-raised-hover',\n 'transition-colors duration-fast-01 ease-productive-standard',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2',\n 'disabled:cursor-not-allowed disabled:opacity-action-disabled',\n 'data-[state=unchecked]:hover:border-accent-7 data-[state=unchecked]:hover:bg-surface-raised-active',\n 'data-[state=checked]:bg-accent-9 data-[state=checked]:border-accent-7 data-[state=checked]:text-accent-fg',\n 'data-[state=indeterminate]:bg-accent-9 data-[state=indeterminate]:border-accent-7 data-[state=indeterminate]:text-accent-fg',\n state && stateTintClasses[state],\n className,\n )}\n aria-invalid={state === 'error' || undefined}\n aria-describedby={ariaDescribedBy}\n aria-required={ariaRequired || undefined}\n {...props}\n // Explicit id wins; otherwise adopt FormField's inputId so <Label htmlFor>\n // resolves. Without this the label renders, points at nothing, and the\n // control has NO accessible name — a screen reader announces an unnamed\n // checkbox even though the consumer wrote FormField + Label correctly.\n id={props.id ?? fieldCtx.inputId}\n >\n <AnimatePresence>\n {isActive && (\n <CheckboxPrimitive.Indicator forceMount asChild>\n <motion.span\n className=\"flex items-center justify-center text-current\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: durations.fast01 }}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n className={checkboxIconClasses[size]}\n >\n {actualChecked === 'indeterminate' ? (\n <motion.line\n x1=\"4\"\n y1=\"8\"\n x2=\"12\"\n y2=\"8\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n exit={{ pathLength: 0 }}\n transition={{ duration: durations.moderate02, ease: 'easeOut' }}\n />\n ) : (\n <motion.path\n d=\"M3.5 8.5l3 3 6-6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"none\"\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n exit={{ pathLength: 0 }}\n transition={{ duration: durations.moderate02, ease: 'easeOut' }}\n />\n )}\n </svg>\n </motion.span>\n </CheckboxPrimitive.Indicator>\n )}\n </AnimatePresence>\n </CheckboxPrimitive.Root>\n )\n})\nCheckbox.displayName = CheckboxPrimitive.Root.displayName\n\nexport { Checkbox }\n"],"mappings":";;;;;;;;;;AAYA,IAAM,IAAmE;CACvE,OAAO;CACP,SAAS;CACT,SAAS;AACX,GAqCM,IAAsB;CAC1B,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAEM,IAAsB;CAC1B,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAEM,IAAW,EAAM,YAGpB,EAAE,cAAW,OAAO,GAAW,kBAAe,UAAO,MAAM,YAAS,oBAAiB,mBAAgB,GAAG,KAAS,MAAQ;CAE1H,IAAM,IAAe,MAAY,KAAA,GAC3B,CAAC,GAAiB,KAAsB,EAAM,SAClD,IAAgB,kBAAmB,GACrC,GAEM,IAAW,EAAa,GACxB,IAAQ,EAAkB,GAAW,EAAS,KAAK,GACnD,IAAkB,EAAM,uBAAuB,EAAS,cACxD,IAAe,EAAM,oBAAoB,EAAS,UAElD,IAAgB,IAAgB,kBAAmB,IAAe,IAAU,GAC5E,IAAW,MAAkB,MAAQ,MAAkB,iBAEvD,IAAsB,EAAM,aAC/B,MAAqC;EAEpC,AADK,KAAc,EAAmB,CAAK,GAC3C,IAAkB,CAAK;CACzB,GACA,CAAC,GAAc,CAAe,CAChC;CAEA,OACE,kBAAC,GAAD;EACO;EACL,SAAS,KAAgB,IAAgB,IAAgB,KAAA;EACzD,gBAAgB,CAAC,KAAgB,CAAC,IAAgB,IAAiB,KAAA;EACnE,iBAAiB;EACjB,WAAW,EACT,qFACA,EAAoB,IACpB,uCACA,2BACA,+DACA,6GACA,gEACA,sGACA,6GACA,+HACA,KAAS,EAAiB,IAC1B,CACF;EACA,gBAAc,MAAU,WAAW,KAAA;EACnC,oBAAkB;EAClB,iBAAe,KAAgB,KAAA;EAC/B,GAAI;EAKJ,IAAI,EAAM,MAAM,EAAS;YAEzB,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,GAAD;GAA6B,YAAA;GAAW,SAAA;aACtC,kBAAC,EAAO,MAAR;IACE,WAAU;IACV,SAAS,EAAE,SAAS,EAAE;IACtB,SAAS,EAAE,SAAS,EAAE;IACtB,MAAM,EAAE,SAAS,EAAE;IACnB,YAAY,EAAE,UAAU,EAAU,OAAO;cAEzC,kBAAC,OAAD;KACE,OAAM;KACN,QAAO;KACP,SAAQ;KACR,MAAK;KACL,WAAW,EAAoB;eAE9B,MAAkB,kBACjB,kBAAC,EAAO,MAAR;MACE,IAAG;MACH,IAAG;MACH,IAAG;MACH,IAAG;MACH,QAAO;MACP,aAAY;MACZ,eAAc;MACd,SAAS,EAAE,YAAY,EAAE;MACzB,SAAS,EAAE,YAAY,EAAE;MACzB,MAAM,EAAE,YAAY,EAAE;MACtB,YAAY;OAAE,UAAU,EAAU;OAAY,MAAM;MAAU;KAC/D,CAAA,IAED,kBAAC,EAAO,MAAR;MACE,GAAE;MACF,QAAO;MACP,aAAY;MACZ,eAAc;MACd,gBAAe;MACf,MAAK;MACL,SAAS,EAAE,YAAY,EAAE;MACzB,SAAS,EAAE,YAAY,EAAE;MACzB,MAAM,EAAE,YAAY,EAAE;MACtB,YAAY;OAAE,UAAU,EAAU;OAAY,MAAM;MAAU;KAC/D,CAAA;IAEA,CAAA;GACM,CAAA;EACc,CAAA,EAEhB,CAAA;CACK,CAAA;AAE5B,CAAC;AACD,EAAS,cAAA,EAAqC"}
1
+ {"version":3,"file":"checkbox.js","names":[],"sources":["../../src/ui/checkbox.tsx"],"sourcesContent":["'use client'\n\nimport * as CheckboxPrimitive from '@primitives/react-checkbox'\nimport { AnimatePresence, motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useFormField } from './form'\nimport { type FieldState, resolveFieldState } from './lib/field-state'\nimport { durations } from './lib/motion'\nimport { cn } from './lib/utils'\n\n/** Border + background tint per validation state (checked state uses accent regardless). */\nconst stateTintClasses: Record<Exclude<FieldState, 'default'>, string> = {\n error: 'border-error-7 bg-error-3',\n warning: 'border-warning-7 bg-warning-3',\n success: 'border-success-7 bg-success-3',\n}\n\n/**\n * Props for Checkbox — a Radix-powered accessible checkbox with error state styling and\n * an indeterminate state for \"select all\" row controls.\n *\n * **Indeterminate:** Pass `indeterminate={true}` to show the \"−\" dash (overrides `checked`).\n * This is correct for \"select all\" headers when only some rows are selected.\n *\n * **Controlled:** Use `checked` + `onCheckedChange` for controlled usage.\n * `onCheckedChange` receives `true | false | 'indeterminate'` from Radix.\n *\n * @example\n * // Basic controlled checkbox:\n * <Checkbox checked={agreed} onCheckedChange={(v) => setAgreed(v === true)} />\n *\n * @example\n * // Error state when required checkbox is not checked:\n * <Checkbox state={!termsAccepted ? 'error' : 'default'} checked={termsAccepted} onCheckedChange={(v) => setTerms(v === true)} />\n *\n * @example\n * // \"Select all\" checkbox with indeterminate state:\n * <Checkbox\n * indeterminate={someSelected && !allSelected}\n * checked={allSelected}\n * onCheckedChange={(v) => toggleAll(v === true)}\n * />\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface CheckboxProps extends React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> {\n /** Validation/feedback state. `'error'` also sets `aria-invalid`. Inherited from `FormField` when omitted. */\n state?: FieldState\n indeterminate?: boolean\n /** Control size — `sm` (20px), `md` (24px, default, WCAG compliant), `lg` (28px). */\n size?: 'sm' | 'md' | 'lg'\n}\n\nconst checkboxSizeClasses = {\n sm: 'h-5 w-5',\n md: 'h-6 w-6',\n lg: 'h-7 w-7',\n} as const\n\nconst checkboxIconClasses = {\n sm: 'h-[14px] w-[14px]',\n md: 'h-[18px] w-[18px]',\n lg: 'h-5 w-5',\n} as const\n\nconst Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n CheckboxProps\n>(({ className, state: stateProp, indeterminate, size = 'md', checked, onCheckedChange, defaultChecked, ...props }, ref) => {\n // Track internal state so AnimatePresence works for both controlled & uncontrolled usage\n const isControlled = checked !== undefined\n const [internalChecked, setInternalChecked] = React.useState<boolean | 'indeterminate'>(\n indeterminate ? 'indeterminate' : (defaultChecked ? true : false),\n )\n\n const fieldCtx = useFormField()\n const state = resolveFieldState(stateProp, fieldCtx.state)\n const ariaDescribedBy = props['aria-describedby'] ?? fieldCtx.helperTextId\n const ariaRequired = props['aria-required'] ?? fieldCtx.required\n\n const actualChecked = indeterminate ? 'indeterminate' : (isControlled ? checked : internalChecked)\n const isActive = actualChecked === true || actualChecked === 'indeterminate'\n\n const handleCheckedChange = React.useCallback(\n (value: boolean | 'indeterminate') => {\n if (!isControlled) setInternalChecked(value)\n onCheckedChange?.(value)\n },\n [isControlled, onCheckedChange],\n )\n\n return (\n <CheckboxPrimitive.Root\n ref={ref}\n checked={isControlled || indeterminate ? actualChecked : undefined}\n defaultChecked={!isControlled && !indeterminate ? defaultChecked : undefined}\n onCheckedChange={handleCheckedChange}\n className={cn(\n 'touch-target peer flex items-center justify-center shrink-0 rounded-control-inner',\n checkboxSizeClasses[size],\n 'border border-surface-border-interactive',\n 'bg-surface-panel-hover',\n 'transition-colors duration-fast-01 ease-productive-standard',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2',\n 'disabled:cursor-not-allowed disabled:opacity-action-disabled',\n 'data-[state=unchecked]:hover:border-accent-7 data-[state=unchecked]:hover:bg-surface-panel-active',\n 'data-[state=checked]:bg-accent-9 data-[state=checked]:border-accent-7 data-[state=checked]:text-accent-fg',\n 'data-[state=indeterminate]:bg-accent-9 data-[state=indeterminate]:border-accent-7 data-[state=indeterminate]:text-accent-fg',\n state && stateTintClasses[state],\n className,\n )}\n aria-invalid={state === 'error' || undefined}\n aria-describedby={ariaDescribedBy}\n aria-required={ariaRequired || undefined}\n {...props}\n // Explicit id wins; otherwise adopt FormField's inputId so <Label htmlFor>\n // resolves. Without this the label renders, points at nothing, and the\n // control has NO accessible name — a screen reader announces an unnamed\n // checkbox even though the consumer wrote FormField + Label correctly.\n id={props.id ?? fieldCtx.inputId}\n >\n <AnimatePresence>\n {isActive && (\n <CheckboxPrimitive.Indicator forceMount asChild>\n <motion.span\n className=\"flex items-center justify-center text-current\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: durations.fast01 }}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n className={checkboxIconClasses[size]}\n >\n {actualChecked === 'indeterminate' ? (\n <motion.line\n x1=\"4\"\n y1=\"8\"\n x2=\"12\"\n y2=\"8\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n exit={{ pathLength: 0 }}\n transition={{ duration: durations.moderate02, ease: 'easeOut' }}\n />\n ) : (\n <motion.path\n d=\"M3.5 8.5l3 3 6-6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"none\"\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n exit={{ pathLength: 0 }}\n transition={{ duration: durations.moderate02, ease: 'easeOut' }}\n />\n )}\n </svg>\n </motion.span>\n </CheckboxPrimitive.Indicator>\n )}\n </AnimatePresence>\n </CheckboxPrimitive.Root>\n )\n})\nCheckbox.displayName = CheckboxPrimitive.Root.displayName\n\nexport { Checkbox }\n"],"mappings":";;;;;;;;;;AAYA,IAAM,IAAmE;CACvE,OAAO;CACP,SAAS;CACT,SAAS;AACX,GAqCM,IAAsB;CAC1B,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAEM,IAAsB;CAC1B,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAEM,IAAW,EAAM,YAGpB,EAAE,cAAW,OAAO,GAAW,kBAAe,UAAO,MAAM,YAAS,oBAAiB,mBAAgB,GAAG,KAAS,MAAQ;CAE1H,IAAM,IAAe,MAAY,KAAA,GAC3B,CAAC,GAAiB,KAAsB,EAAM,SAClD,IAAgB,kBAAmB,GACrC,GAEM,IAAW,EAAa,GACxB,IAAQ,EAAkB,GAAW,EAAS,KAAK,GACnD,IAAkB,EAAM,uBAAuB,EAAS,cACxD,IAAe,EAAM,oBAAoB,EAAS,UAElD,IAAgB,IAAgB,kBAAmB,IAAe,IAAU,GAC5E,IAAW,MAAkB,MAAQ,MAAkB,iBAEvD,IAAsB,EAAM,aAC/B,MAAqC;EAEpC,AADK,KAAc,EAAmB,CAAK,GAC3C,IAAkB,CAAK;CACzB,GACA,CAAC,GAAc,CAAe,CAChC;CAEA,OACE,kBAAC,GAAD;EACO;EACL,SAAS,KAAgB,IAAgB,IAAgB,KAAA;EACzD,gBAAgB,CAAC,KAAgB,CAAC,IAAgB,IAAiB,KAAA;EACnE,iBAAiB;EACjB,WAAW,EACT,qFACA,EAAoB,IACpB,4CACA,0BACA,+DACA,6GACA,gEACA,qGACA,6GACA,+HACA,KAAS,EAAiB,IAC1B,CACF;EACA,gBAAc,MAAU,WAAW,KAAA;EACnC,oBAAkB;EAClB,iBAAe,KAAgB,KAAA;EAC/B,GAAI;EAKJ,IAAI,EAAM,MAAM,EAAS;YAEzB,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,GAAD;GAA6B,YAAA;GAAW,SAAA;aACtC,kBAAC,EAAO,MAAR;IACE,WAAU;IACV,SAAS,EAAE,SAAS,EAAE;IACtB,SAAS,EAAE,SAAS,EAAE;IACtB,MAAM,EAAE,SAAS,EAAE;IACnB,YAAY,EAAE,UAAU,EAAU,OAAO;cAEzC,kBAAC,OAAD;KACE,OAAM;KACN,QAAO;KACP,SAAQ;KACR,MAAK;KACL,WAAW,EAAoB;eAE9B,MAAkB,kBACjB,kBAAC,EAAO,MAAR;MACE,IAAG;MACH,IAAG;MACH,IAAG;MACH,IAAG;MACH,QAAO;MACP,aAAY;MACZ,eAAc;MACd,SAAS,EAAE,YAAY,EAAE;MACzB,SAAS,EAAE,YAAY,EAAE;MACzB,MAAM,EAAE,YAAY,EAAE;MACtB,YAAY;OAAE,UAAU,EAAU;OAAY,MAAM;MAAU;KAC/D,CAAA,IAED,kBAAC,EAAO,MAAR;MACE,GAAE;MACF,QAAO;MACP,aAAY;MACZ,eAAc;MACd,gBAAe;MACf,MAAK;MACL,SAAS,EAAE,YAAY,EAAE;MACzB,SAAS,EAAE,YAAY,EAAE;MACzB,MAAM,EAAE,YAAY,EAAE;MACtB,YAAY;OAAE,UAAU,EAAU;OAAY,MAAM;MAAU;KAC/D,CAAA;IAEA,CAAA;GACM,CAAA;EACc,CAAA,EAEhB,CAAA;CACK,CAAA;AAE5B,CAAC;AACD,EAAS,cAAA,EAAqC"}
package/dist/ui/code.js CHANGED
@@ -4,12 +4,12 @@ import { jsx as n } from "react/jsx-runtime";
4
4
  //#region src/ui/code.tsx
5
5
  var r = t.forwardRef(({ className: t, variant: r = "inline", children: i, ...a }, o) => r === "block" ? /* @__PURE__ */ n("pre", {
6
6
  ref: o,
7
- className: e("overflow-x-auto rounded-surface border border-card-strong bg-surface-raised p-ds-05 font-mono text-body-sm leading-ds-relaxed text-surface-fg", t),
7
+ className: e("overflow-x-auto rounded-surface border border-card-strong bg-surface-panel p-ds-05 font-mono text-body-sm leading-ds-relaxed text-surface-fg", t),
8
8
  ...a,
9
9
  children: /* @__PURE__ */ n("code", { children: i })
10
10
  }) : /* @__PURE__ */ n("code", {
11
11
  ref: o,
12
- className: e("rounded-control-inner bg-surface-raised-hover border border-card px-ds-02 py-ds-01 font-mono text-body-sm text-surface-fg", t),
12
+ className: e("rounded-control-inner bg-surface-panel-hover border border-card px-ds-02 py-ds-01 font-mono text-body-sm text-surface-fg", t),
13
13
  ...a,
14
14
  children: i
15
15
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"code.js","names":[],"sources":["../../src/ui/code.tsx"],"sourcesContent":["// @server-safe\nimport * as React from 'react'\n\nimport { cn } from './lib/utils'\n\n/**\n * Props for Code — a typography component that renders either inline `<code>` or block `<pre><code>`\n * monospace text, styled with the design system's layer tokens.\n *\n * **`variant` options:**\n * - `\"inline\"` (default) — renders as `<code>` with a subtle layer-03 background, suitable for\n * short snippets within prose (e.g. \"Use the `onClick` prop to...\").\n * - `\"block\"` — renders as `<pre>` with a bordered, padded, horizontally-scrollable block for\n * multi-line code samples.\n *\n * @example\n * // Inline code reference in documentation:\n * <p>Pass <Code>loading={true}</Code> to show the spinner.</p>\n *\n * @example\n * // Block code sample (e.g. in a README or docs page):\n * <Code variant=\"block\">{`const greeting = \"Hello, world!\"\\nconsole.log(greeting)`}</Code>\n *\n * @example\n * // Inline API key display:\n * <p>Your API key: <Code>sk-dev-abc123xyz</Code></p>\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface CodeProps extends React.HTMLAttributes<HTMLElement> {\n variant?: 'inline' | 'block'\n}\n\nconst Code = React.forwardRef<HTMLPreElement | HTMLElement, CodeProps>(\n ({ className, variant = 'inline', children, ...props }, ref) => {\n if (variant === 'block') {\n return (\n <pre\n ref={ref as React.Ref<HTMLPreElement>}\n className={cn(\n 'overflow-x-auto rounded-surface border border-card-strong bg-surface-raised p-ds-05 font-mono text-body-sm leading-ds-relaxed text-surface-fg',\n className,\n )}\n {...props}\n >\n <code>{children}</code>\n </pre>\n )\n }\n\n return (\n <code\n ref={ref}\n className={cn(\n 'rounded-control-inner bg-surface-raised-hover border border-card px-ds-02 py-ds-01 font-mono text-body-sm text-surface-fg',\n className,\n )}\n {...props}\n >\n {children}\n </code>\n )\n },\n)\nCode.displayName = 'Code'\n\nexport { Code }\n"],"mappings":";;;;AAgCA,IAAM,IAAO,EAAM,YAChB,EAAE,cAAW,aAAU,UAAU,aAAU,GAAG,KAAS,MAClD,MAAY,UAEZ,kBAAC,OAAD;CACO;CACL,WAAW,EACT,iJACA,CACF;CACA,GAAI;WAEJ,kBAAC,QAAD,EAAO,YAAe,CAAA;AACnB,CAAA,IAKP,kBAAC,QAAD;CACO;CACL,WAAW,EACT,6HACA,CACF;CACA,GAAI;CAEH;AACG,CAAA,CAGZ;AACA,EAAK,cAAc"}
1
+ {"version":3,"file":"code.js","names":[],"sources":["../../src/ui/code.tsx"],"sourcesContent":["// @server-safe\nimport * as React from 'react'\n\nimport { cn } from './lib/utils'\n\n/**\n * Props for Code — a typography component that renders either inline `<code>` or block `<pre><code>`\n * monospace text, styled with the design system's layer tokens.\n *\n * **`variant` options:**\n * - `\"inline\"` (default) — renders as `<code>` with a subtle layer-03 background, suitable for\n * short snippets within prose (e.g. \"Use the `onClick` prop to...\").\n * - `\"block\"` — renders as `<pre>` with a bordered, padded, horizontally-scrollable block for\n * multi-line code samples.\n *\n * @example\n * // Inline code reference in documentation:\n * <p>Pass <Code>loading={true}</Code> to show the spinner.</p>\n *\n * @example\n * // Block code sample (e.g. in a README or docs page):\n * <Code variant=\"block\">{`const greeting = \"Hello, world!\"\\nconsole.log(greeting)`}</Code>\n *\n * @example\n * // Inline API key display:\n * <p>Your API key: <Code>sk-dev-abc123xyz</Code></p>\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface CodeProps extends React.HTMLAttributes<HTMLElement> {\n variant?: 'inline' | 'block'\n}\n\nconst Code = React.forwardRef<HTMLPreElement | HTMLElement, CodeProps>(\n ({ className, variant = 'inline', children, ...props }, ref) => {\n if (variant === 'block') {\n return (\n <pre\n ref={ref as React.Ref<HTMLPreElement>}\n className={cn(\n 'overflow-x-auto rounded-surface border border-card-strong bg-surface-panel p-ds-05 font-mono text-body-sm leading-ds-relaxed text-surface-fg',\n className,\n )}\n {...props}\n >\n <code>{children}</code>\n </pre>\n )\n }\n\n return (\n <code\n ref={ref}\n className={cn(\n 'rounded-control-inner bg-surface-panel-hover border border-card px-ds-02 py-ds-01 font-mono text-body-sm text-surface-fg',\n className,\n )}\n {...props}\n >\n {children}\n </code>\n )\n },\n)\nCode.displayName = 'Code'\n\nexport { Code }\n"],"mappings":";;;;AAgCA,IAAM,IAAO,EAAM,YAChB,EAAE,cAAW,aAAU,UAAU,aAAU,GAAG,KAAS,MAClD,MAAY,UAEZ,kBAAC,OAAD;CACO;CACL,WAAW,EACT,gJACA,CACF;CACA,GAAI;WAEJ,kBAAC,QAAD,EAAO,YAAe,CAAA;AACnB,CAAA,IAKP,kBAAC,QAAD;CACO;CACL,WAAW,EACT,4HACA,CACF;CACA,GAAI;CAEH;AACG,CAAA,CAGZ;AACA,EAAK,cAAc"}
@@ -123,7 +123,7 @@ function _({ label: e, value: t, onChange: r, onBlur: i, disabled: a, maxLength:
123
123
  onChange: (e) => r(e.target.value),
124
124
  onBlur: i,
125
125
  maxLength: o,
126
- className: n("h-ds-xs-plus w-full rounded-control-inner border border-surface-border bg-surface-overlay px-ds-02 font-mono text-body-sm text-surface-fg transition-colors", "focus:border-accent-7 focus:outline-hidden focus:ring-1 focus:ring-accent-9", a && "cursor-not-allowed opacity-50")
126
+ className: n("h-ds-xs-plus w-full rounded-control-inner border border-surface-border-interactive bg-surface-overlay px-ds-02 font-mono text-body-sm text-surface-fg transition-colors", "focus:border-accent-7 focus:outline-hidden focus:ring-1 focus:ring-accent-9", a && "cursor-not-allowed opacity-50")
127
127
  })]
128
128
  })]
129
129
  });
@@ -202,7 +202,7 @@ var v = c.forwardRef(({ value: v = "#000000", onChange: y, presets: b, disabled:
202
202
  }) : /* @__PURE__ */ u(f.button, {
203
203
  type: "button",
204
204
  disabled: x,
205
- className: n("group relative flex items-center overflow-hidden rounded-control border border-surface-border-strong", "hover:border-accent-7 focus:border-accent-7 focus:outline-hidden focus:ring-1 focus:ring-accent-9", x && "cursor-not-allowed opacity-50"),
205
+ className: n("group relative flex items-center overflow-hidden rounded-control border border-surface-border-interactive", "hover:border-accent-7 focus:border-accent-7 focus:outline-hidden focus:ring-1 focus:ring-accent-9", x && "cursor-not-allowed opacity-50"),
206
206
  whileHover: { scale: 1.02 },
207
207
  whileTap: { scale: .98 },
208
208
  transition: t.snappy,
@@ -412,7 +412,7 @@ var v = c.forwardRef(({ value: v = "#000000", onChange: y, presets: b, disabled:
412
412
  ...t.bouncy,
413
413
  delay: r * .02
414
414
  },
415
- className: n("h-6 w-6 rounded-control-inner border", i ? "border-accent-7 ring-2 ring-accent-9/30" : "border-surface-border hover:border-surface-border-strong", x && "cursor-not-allowed opacity-50"),
415
+ className: n("h-6 w-6 rounded-control-inner border", i ? "border-accent-7 ring-2 ring-accent-9/30" : "border-surface-border-interactive hover:border-surface-border-interactive-strong", x && "cursor-not-allowed opacity-50"),
416
416
  style: { backgroundColor: e.hex },
417
417
  title: e.label,
418
418
  "aria-label": `${e.label}: ${e.hex}`
@@ -1 +1 @@
1
- {"version":3,"file":"color-input.js","names":[],"sources":["../../src/ui/color-input.tsx"],"sourcesContent":["'use client'\n\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\nimport { HexColorPicker } from 'react-colorful'\n\nimport { useFormField } from './form'\nimport { durations,springs } from './lib/motion'\nimport { cn } from './lib/utils'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from './popover'\n\n// ── Color conversion helpers ──\n\nfunction hexToRgb(hex: string): { r: number; g: number; b: number } | null {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex)\n if (!m) return null\n const n = parseInt(m[1], 16)\n return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 }\n}\n\nfunction rgbToHex(r: number, g: number, b: number): string {\n return '#' + [r, g, b].map((v) => Math.max(0, Math.min(255, Math.round(v))).toString(16).padStart(2, '0')).join('')\n}\n\nfunction hexToHsl(hex: string): { h: number; s: number; l: number } | null {\n const rgb = hexToRgb(hex)\n if (!rgb) return null\n const r = rgb.r / 255, g = rgb.g / 255, b = rgb.b / 255\n const max = Math.max(r, g, b), min = Math.min(r, g, b)\n const l = (max + min) / 2\n if (max === min) return { h: 0, s: 0, l: Math.round(l * 100) }\n const d = max - min\n const s = l > 0.5 ? d / (2 - max - min) : d / (max - min)\n let h = 0\n if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6\n else if (max === g) h = ((b - r) / d + 2) / 6\n else h = ((r - g) / d + 4) / 6\n return { h: Math.round(h * 360), s: Math.round(s * 100), l: Math.round(l * 100) }\n}\n\nfunction hslToHex(h: number, s: number, l: number): string {\n const sn = s / 100, ln = l / 100\n const a = sn * Math.min(ln, 1 - ln)\n const f = (n: number) => {\n const k = (n + h / 30) % 12\n const c = ln - a * Math.max(Math.min(k - 3, 9 - k, 1), -1)\n return Math.round(255 * c)\n }\n return rgbToHex(f(0), f(8), f(4))\n}\n\n// ── Named color presets ──\n// Brand spectrum derived from our OKLCH scales (step-9), spanning the wheel —\n// intentional and on-brand, NOT the raw framework palette. Led by red, not indigo.\n\nconst NAMED_PRESETS: { hex: string; label: string }[] = [\n { hex: '#C53637', label: 'Red' },\n { hex: '#BE5A0A', label: 'Orange' },\n { hex: '#DF911A', label: 'Amber' },\n { hex: '#308639', label: 'Green' },\n { hex: '#118659', label: 'Emerald' },\n { hex: '#11846E', label: 'Teal' },\n { hex: '#028A9B', label: 'Cyan' },\n { hex: '#1479B0', label: 'Blue' },\n { hex: '#7D5FAD', label: 'Purple' },\n { hex: '#C22D6D', label: 'Pink' },\n]\n\n// ── Contrast helper ──\n\nfunction isLightColor(hex: string): boolean {\n const rgb = hexToRgb(hex)\n if (!rgb) return false\n // Relative luminance (sRGB)\n const [r, g, b] = [rgb.r, rgb.g, rgb.b].map((c) => {\n const s = c / 255\n return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4)\n })\n return 0.2126 * r + 0.7152 * g + 0.0722 * b > 0.4\n}\n\n// ── Format mode type ──\n\ntype ColorFormat = 'hex' | 'rgb' | 'hsl'\n\n// ── Props ──\n\nexport interface ColorInputProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Current color value (hex string, e.g. \"#d33163\") */\n value?: string\n /** Called when the color changes */\n onChange?: (value: string) => void\n /** Preset color swatches. Defaults to 10 named colors. Pass `false` to hide. */\n presets?: { hex: string; label: string }[] | string[] | false\n /** Whether the input is disabled */\n disabled?: boolean\n /** Show the interactive color picker. Default: true. */\n showPicker?: boolean\n /** Default format for the input fields. Default: 'hex'. */\n defaultFormat?: ColorFormat\n /** Popover alignment. Default: 'start'. */\n align?: 'start' | 'center' | 'end'\n /**\n * Trigger style variant.\n * - `default`: Swatch bleeds to left edge + hex text\n * - `inline`: Entire trigger is the selected color with hex text overlaid\n */\n variant?: 'default' | 'inline'\n}\n\n// ── Small format input ──\n\nfunction FormatInput({\n label,\n value,\n onChange,\n onBlur,\n disabled,\n maxLength = 3,\n prefix,\n className,\n id,\n}: {\n label: string\n value: string\n onChange: (v: string) => void\n onBlur?: () => void\n disabled?: boolean\n maxLength?: number\n prefix?: string\n className?: string\n id: string\n}) {\n return (\n <div className={cn('flex flex-col gap-ds-01', className)}>\n <label htmlFor={id} className=\"text-label-xs font-medium uppercase tracking-wider text-surface-fg-muted\">\n {label}\n </label>\n <div className=\"flex items-center\">\n {prefix && (\n <span className=\"text-body-sm text-surface-fg-muted\">{prefix}</span>\n )}\n <input\n id={id}\n type=\"text\"\n value={value}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n maxLength={maxLength}\n className={cn(\n 'h-ds-xs-plus w-full rounded-control-inner border border-surface-border bg-surface-overlay px-ds-02 font-mono text-body-sm text-surface-fg transition-colors',\n 'focus:border-accent-7 focus:outline-hidden focus:ring-1 focus:ring-accent-9',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n />\n </div>\n </div>\n )\n}\n\n// ── Main component ──\n\nconst ColorInput = React.forwardRef<HTMLDivElement, ColorInputProps>(\n ({\n value = '#000000',\n onChange,\n presets,\n disabled = false,\n showPicker = true,\n defaultFormat = 'hex',\n align = 'start',\n variant = 'default',\n className,\n id: externalId,\n ...props\n }, ref) => {\n const [format, setFormat] = React.useState<ColorFormat>(defaultFormat)\n const [open, setOpen] = React.useState(false)\n const instanceId = React.useId()\n const fieldCtx = useFormField()\n // Explicit id wins; otherwise adopt FormField's inputId so <Label htmlFor> resolves\n // onto the (labelable) trigger button. The root is a <div>, which can't be a label target.\n const triggerId = externalId ?? fieldCtx.inputId\n\n // Internal color state — syncs with prop, allows uncontrolled use\n const [internalColor, setInternalColor] = React.useState(value)\n // Draft state for the hex field so in-progress (<6 char) typing isn't clobbered\n // by re-renders off internalColor. null = show the committed color.\n const [hexDraft, setHexDraft] = React.useState<string | null>(null)\n React.useEffect(() => { setInternalColor(value); setHexDraft(null) }, [value])\n\n // Track color when popover opened (for reset) + undo history\n const [openColor, setOpenColor] = React.useState(value)\n const [undoStack, setUndoStack] = React.useState<string[]>([])\n // Track whether current change is from continuous drag (skip undo push)\n const isDragging = React.useRef(false)\n\n const handleOpenChange = (isOpen: boolean) => {\n if (disabled) return\n if (isOpen) {\n setOpenColor(internalColor)\n setUndoStack([])\n }\n setHexDraft(null)\n setOpen(isOpen)\n }\n\n // Discrete change (preset click, field commit) — pushes to undo\n const handleDiscreteChange = (newValue: string) => {\n if (disabled) return\n const normalized = newValue.startsWith('#') ? newValue : `#${newValue}`\n const hex = normalized.toLowerCase()\n setUndoStack((prev) => {\n if (prev[prev.length - 1] === internalColor) return prev\n return [...prev.slice(-19), internalColor]\n })\n setInternalColor(hex)\n setHexDraft(null)\n onChange?.(hex)\n }\n\n // Continuous change (picker drag) — updates color but only pushes undo on drag start\n const handleChange = (newValue: string) => {\n if (disabled) return\n const normalized = newValue.startsWith('#') ? newValue : `#${newValue}`\n const hex = normalized.toLowerCase()\n if (!isDragging.current) {\n // First change in a drag sequence — push current color to undo\n isDragging.current = true\n setUndoStack((prev) => {\n if (prev[prev.length - 1] === internalColor) return prev\n return [...prev.slice(-19), internalColor]\n })\n }\n setInternalColor(hex)\n onChange?.(hex)\n }\n\n // Called when picker drag ends\n const handlePickerChangeComplete = () => {\n isDragging.current = false\n }\n\n const handleUndo = () => {\n if (undoStack.length === 0) return\n const prev = undoStack[undoStack.length - 1]\n setUndoStack((s) => s.slice(0, -1))\n setInternalColor(prev)\n onChange?.(prev)\n }\n\n const handleReset = () => {\n setInternalColor(openColor)\n onChange?.(openColor)\n setUndoStack([])\n }\n\n // Resolve presets\n const resolvedPresets = presets === false\n ? []\n : presets\n ? presets.map((p) =>\n typeof p === 'string' ? { hex: p, label: p } : p\n )\n : NAMED_PRESETS\n\n // Parsed color values — use internal state\n const rgb = hexToRgb(internalColor)\n const hsl = hexToHsl(internalColor)\n\n // RGB field handlers (clamped 0-255)\n const handleRgbChange = (channel: 'r' | 'g' | 'b', v: string) => {\n if (!rgb) return\n const num = parseInt(v, 10)\n if (isNaN(num)) return\n const clamped = Math.max(0, Math.min(255, num))\n handleDiscreteChange(rgbToHex(\n channel === 'r' ? clamped : rgb.r,\n channel === 'g' ? clamped : rgb.g,\n channel === 'b' ? clamped : rgb.b,\n ))\n }\n\n // HSL field handlers (H: 0-360, S/L: 0-100)\n const handleHslChange = (channel: 'h' | 's' | 'l', v: string) => {\n if (!hsl) return\n const num = parseInt(v, 10)\n if (isNaN(num)) return\n const max = channel === 'h' ? 360 : 100\n const clamped = Math.max(0, Math.min(max, num))\n handleDiscreteChange(hslToHex(\n channel === 'h' ? clamped : hsl.h,\n channel === 's' ? clamped : hsl.s,\n channel === 'l' ? clamped : hsl.l,\n ))\n }\n\n const formats: ColorFormat[] = ['hex', 'rgb', 'hsl']\n\n return (\n <div ref={ref} className={cn('inline-flex flex-col', className)} {...props}>\n <Popover open={open} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n {variant === 'inline' ? (\n <motion.button\n type=\"button\"\n disabled={disabled}\n className={cn(\n 'group flex items-center justify-center rounded-control px-ds-04 py-ds-02 font-mono text-body-sm font-medium',\n 'focus:outline-hidden focus:ring-2 focus:ring-accent-9 focus:ring-offset-2 focus:ring-offset-surface-base',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n animate={{\n backgroundColor: internalColor,\n color: isLightColor(internalColor) ? 'rgba(0,0,0,0.8)' : 'rgba(255,255,255,0.95)',\n }}\n whileHover={{ y: -1, boxShadow: '0 4px 12px rgba(0,0,0,0.12)' }}\n whileTap={{ scale: 0.97 }}\n transition={springs.smooth}\n id={triggerId}\n aria-describedby={fieldCtx.helperTextId}\n aria-invalid={fieldCtx.state === 'error' || undefined}\n // Inside a FormField, let the visible <Label> name the trigger; else describe it.\n aria-label={fieldCtx.inputId ? undefined : `Color picker: ${internalColor}`}\n >\n {internalColor.toUpperCase()}\n </motion.button>\n ) : (\n <motion.button\n type=\"button\"\n disabled={disabled}\n className={cn(\n 'group relative flex items-center overflow-hidden rounded-control border border-surface-border-strong',\n 'hover:border-accent-7 focus:border-accent-7 focus:outline-hidden focus:ring-1 focus:ring-accent-9',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n whileHover={{ scale: 1.02 }}\n whileTap={{ scale: 0.98 }}\n transition={springs.snappy}\n id={triggerId}\n aria-describedby={fieldCtx.helperTextId}\n aria-invalid={fieldCtx.state === 'error' || undefined}\n // Inside a FormField, let the visible <Label> name the trigger; else describe it.\n aria-label={fieldCtx.inputId ? undefined : `Color picker: ${internalColor}`}\n >\n {/* Gradient background: color → surface */}\n <motion.span\n className=\"absolute inset-0\"\n animate={{\n background: `linear-gradient(to right, ${internalColor} 0%, ${internalColor} 35%, transparent 70%)`,\n }}\n /* Between durations.moderate02 (0.24) and durations.slow01 (0.4) — gradient lerp feel */\n transition={{ duration: 0.3 }}\n />\n <span className=\"absolute inset-0 bg-surface-overlay/60\" style={{\n maskImage: 'linear-gradient(to right, transparent 0%, black 40%)',\n WebkitMaskImage: 'linear-gradient(to right, transparent 0%, black 40%)',\n }} />\n {/* Hex value */}\n <span className=\"relative z-10 py-ds-02 pl-6 pr-ds-03 font-mono text-body-sm text-surface-fg\">\n {internalColor.toUpperCase()}\n </span>\n </motion.button>\n )}\n </PopoverTrigger>\n\n <PopoverContent\n role=\"dialog\"\n aria-label=\"Color picker\"\n align={align}\n sideOffset={8}\n className=\"w-[272px] rounded-overlay-lg bg-surface-overlay p-0 shadow-floating\"\n >\n <div className=\"flex flex-col\">\n {/* Interactive picker */}\n {showPicker && (\n <div className=\"p-ds-04 pb-ds-03\" onPointerUp={handlePickerChangeComplete} onPointerLeave={handlePickerChangeComplete}>\n <HexColorPicker\n color={internalColor}\n onChange={handleChange}\n className=\"w-full!\"\n style={{ height: 160 }}\n />\n </div>\n )}\n\n {/* Format inputs */}\n <div className=\"border-t border-surface-border px-ds-04 py-ds-03\">\n {/* Format switcher */}\n <div className=\"mb-ds-03 flex items-center gap-ds-01\">\n {formats.map((f) => (\n <button\n key={f}\n type=\"button\"\n onClick={() => setFormat(f)}\n className={cn(\n 'relative min-h-6 rounded-control-inner px-ds-02 py-px text-label-xs font-semibold uppercase tracking-wider transition-colors',\n format === f\n ? 'text-accent-11'\n : 'text-surface-fg-muted hover:text-surface-fg',\n )}\n >\n {format === f && (\n <motion.span\n layoutId={`color-input-format-pill-${instanceId}`}\n className=\"absolute inset-0 rounded-control-inner bg-accent-3\"\n transition={springs.snappy}\n />\n )}\n <span className=\"relative z-10\">{f}</span>\n </button>\n ))}\n </div>\n\n {/* Format fields — animated swap */}\n <AnimatePresence mode=\"wait\">\n {format === 'hex' && (\n <motion.div\n key=\"hex\"\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -4 }}\n transition={{ duration: durations.moderate01 }}\n className=\"flex gap-ds-02\"\n >\n <FormatInput\n id={`${instanceId}-hex`}\n label=\"Hex\"\n value={hexDraft ?? internalColor.replace('#', '').toUpperCase()}\n onChange={(v) => {\n const clean = v.replace(/[^0-9a-fA-F]/g, '').slice(0, 6)\n setHexDraft(clean.toUpperCase())\n if (clean.length === 6) handleDiscreteChange(`#${clean}`)\n }}\n onBlur={() => {\n // Drop any incomplete draft; display falls back to the\n // committed color. A complete value already committed onChange.\n setHexDraft(null)\n }}\n disabled={disabled}\n maxLength={6}\n prefix=\"#\"\n className=\"flex-1\"\n />\n </motion.div>\n )}\n\n {format === 'rgb' && rgb && (\n <motion.div\n key=\"rgb\"\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -4 }}\n transition={{ duration: durations.moderate01 }}\n className=\"flex gap-ds-02\"\n >\n <FormatInput id={`${instanceId}-r`} label=\"R\" value={String(rgb.r)} onChange={(v) => handleRgbChange('r', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-g`} label=\"G\" value={String(rgb.g)} onChange={(v) => handleRgbChange('g', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-b`} label=\"B\" value={String(rgb.b)} onChange={(v) => handleRgbChange('b', v)} disabled={disabled} className=\"flex-1\" />\n </motion.div>\n )}\n\n {format === 'hsl' && hsl && (\n <motion.div\n key=\"hsl\"\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -4 }}\n transition={{ duration: durations.moderate01 }}\n className=\"flex gap-ds-02\"\n >\n <FormatInput id={`${instanceId}-h`} label=\"H\" value={String(hsl.h)} onChange={(v) => handleHslChange('h', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-s`} label=\"S\" value={String(hsl.s)} onChange={(v) => handleHslChange('s', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-l`} label=\"L\" value={String(hsl.l)} onChange={(v) => handleHslChange('l', v)} disabled={disabled} className=\"flex-1\" />\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n\n {/* Preset swatches */}\n {resolvedPresets.length > 0 && (\n <div className=\"border-t border-surface-border px-ds-04 py-ds-03\">\n <div className=\"flex flex-wrap gap-ds-02\">\n {resolvedPresets.map((preset, i) => {\n const isSelected = internalColor.toLowerCase() === preset.hex.toLowerCase()\n return (\n <motion.button\n key={preset.hex}\n type=\"button\"\n disabled={disabled}\n onClick={() => handleDiscreteChange(preset.hex)}\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{ opacity: 1, scale: isSelected ? 1.15 : 1 }}\n whileHover={{ scale: isSelected ? 1.15 : 1.1 }}\n whileTap={{ scale: 0.9 }}\n transition={{ ...springs.bouncy, delay: i * 0.02 }}\n className={cn(\n 'h-6 w-6 rounded-control-inner border',\n isSelected\n ? 'border-accent-7 ring-2 ring-accent-9/30'\n : 'border-surface-border hover:border-surface-border-strong',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n style={{ backgroundColor: preset.hex }}\n title={preset.label}\n aria-label={`${preset.label}: ${preset.hex}`}\n />\n )\n })}\n </div>\n </div>\n )}\n\n {/* Reset / Undo footer */}\n {(undoStack.length > 0 || internalColor !== openColor) && (\n <motion.div\n initial={{ opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: 'auto' }}\n exit={{ opacity: 0, height: 0 }}\n className=\"flex items-center gap-ds-02 border-t border-surface-border px-ds-04 py-ds-02\"\n >\n {/* Original color preview */}\n <span\n className=\"h-4 w-4 shrink-0 rounded-pill border border-surface-border\"\n style={{ backgroundColor: openColor }}\n title={`Original: ${openColor}`}\n />\n <span className=\"text-caption text-surface-fg-muted\">\n {openColor.toUpperCase()}\n </span>\n <span className=\"flex-1\" />\n {undoStack.length > 0 && (\n <button\n type=\"button\"\n onClick={handleUndo}\n className=\"min-h-6 rounded-control-inner px-ds-02 py-px text-caption font-medium text-surface-fg-muted transition-colors hover:text-surface-fg\"\n >\n Undo\n </button>\n )}\n {internalColor !== openColor && (\n <button\n type=\"button\"\n onClick={handleReset}\n className=\"min-h-6 rounded-control-inner px-ds-02 py-px text-caption font-medium text-surface-fg-muted transition-colors hover:text-error-11\"\n >\n Reset\n </button>\n )}\n </motion.div>\n )}\n </div>\n </PopoverContent>\n </Popover>\n </div>\n )\n },\n)\nColorInput.displayName = 'ColorInput'\n\nexport { ColorInput }\n"],"mappings":";;;;;;;;;;AAiBA,SAAS,EAAS,GAAyD;CACzE,IAAM,IAAI,qBAAqB,KAAK,CAAG;CACvC,IAAI,CAAC,GAAG,OAAO;CACf,IAAM,IAAI,SAAS,EAAE,IAAI,EAAE;CAC3B,OAAO;EAAE,GAAI,KAAK,KAAM;EAAK,GAAI,KAAK,IAAK;EAAK,GAAG,IAAI;CAAI;AAC7D;AAEA,SAAS,EAAS,GAAW,GAAW,GAAmB;CACzD,OAAO,MAAM;EAAC;EAAG;EAAG;CAAC,CAAC,CAAC,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;AACpH;AAEA,SAAS,EAAS,GAAyD;CACzE,IAAM,IAAM,EAAS,CAAG;CACxB,IAAI,CAAC,GAAK,OAAO;CACjB,IAAM,IAAI,EAAI,IAAI,KAAK,IAAI,EAAI,IAAI,KAAK,IAAI,EAAI,IAAI,KAC9C,IAAM,KAAK,IAAI,GAAG,GAAG,CAAC,GAAG,IAAM,KAAK,IAAI,GAAG,GAAG,CAAC,GAC/C,KAAK,IAAM,KAAO;CACxB,IAAI,MAAQ,GAAK,OAAO;EAAE,GAAG;EAAG,GAAG;EAAG,GAAG,KAAK,MAAM,IAAI,GAAG;CAAE;CAC7D,IAAM,IAAI,IAAM,GACV,IAAI,IAAI,KAAM,KAAK,IAAI,IAAM,KAAO,KAAK,IAAM,IACjD,IAAI;CAIR,OAHA,AAEK,IAFD,MAAQ,MAAS,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,MAAM,IAC5C,MAAQ,MAAS,IAAI,KAAK,IAAI,KAAK,MACjC,IAAI,KAAK,IAAI,KAAK,GACtB;EAAE,GAAG,KAAK,MAAM,IAAI,GAAG;EAAG,GAAG,KAAK,MAAM,IAAI,GAAG;EAAG,GAAG,KAAK,MAAM,IAAI,GAAG;CAAE;AAClF;AAEA,SAAS,EAAS,GAAW,GAAW,GAAmB;CACzD,IAAM,IAAK,IAAI,KAAK,IAAK,IAAI,KACvB,IAAI,IAAK,KAAK,IAAI,GAAI,IAAI,CAAE,GAC5B,KAAK,MAAc;EACvB,IAAM,KAAK,IAAI,IAAI,MAAM,IACnB,IAAI,IAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE;EACzD,OAAO,KAAK,MAAM,MAAM,CAAC;CAC3B;CACA,OAAO,EAAS,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;AAClC;AAMA,IAAM,KAAkD;CACtD;EAAE,KAAK;EAAW,OAAO;CAAM;CAC/B;EAAE,KAAK;EAAW,OAAO;CAAS;CAClC;EAAE,KAAK;EAAW,OAAO;CAAQ;CACjC;EAAE,KAAK;EAAW,OAAO;CAAQ;CACjC;EAAE,KAAK;EAAW,OAAO;CAAU;CACnC;EAAE,KAAK;EAAW,OAAO;CAAO;CAChC;EAAE,KAAK;EAAW,OAAO;CAAO;CAChC;EAAE,KAAK;EAAW,OAAO;CAAO;CAChC;EAAE,KAAK;EAAW,OAAO;CAAS;CAClC;EAAE,KAAK;EAAW,OAAO;CAAO;AAClC;AAIA,SAAS,GAAa,GAAsB;CAC1C,IAAM,IAAM,EAAS,CAAG;CACxB,IAAI,CAAC,GAAK,OAAO;CAEjB,IAAM,CAAC,GAAG,GAAG,KAAK;EAAC,EAAI;EAAG,EAAI;EAAG,EAAI;CAAC,CAAC,CAAC,KAAK,MAAM;EACjD,IAAM,IAAI,IAAI;EACd,OAAO,KAAK,SAAU,IAAI,UAAkB,IAAI,QAAS,UAAO;CAClE,CAAC;CACD,OAAO,QAAS,IAAI,QAAS,IAAI,QAAS,IAAI;AAChD;AAiCA,SAAS,EAAY,EACnB,UACA,UACA,aACA,WACA,aACA,eAAY,GACZ,WACA,cACA,SAWC;CACD,OACE,kBAAC,OAAD;EAAK,WAAW,EAAG,2BAA2B,CAAS;YAAvD,CACE,kBAAC,SAAD;GAAO,SAAS;GAAI,WAAU;aAC3B;EACI,CAAA,GACP,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,KACC,kBAAC,QAAD;IAAM,WAAU;cAAsC;GAAa,CAAA,GAErE,kBAAC,SAAD;IACM;IACJ,MAAK;IACE;IACG;IACV,WAAW,MAAM,EAAS,EAAE,OAAO,KAAK;IAChC;IACG;IACX,WAAW,EACT,+JACA,+EACA,KAAY,+BACd;GACD,CAAA,CACE;IACF;;AAET;AAIA,IAAM,IAAa,EAAM,YACtB,EACC,WAAQ,WACR,aACA,YACA,cAAW,IACX,gBAAa,IACb,mBAAgB,OAChB,YAAQ,SACR,cAAU,WACV,cACA,IAAI,IACJ,GAAG,KACF,MAAQ;CACT,IAAM,CAAC,GAAQ,KAAa,EAAM,SAAsB,CAAa,GAC/D,CAAC,GAAM,KAAW,EAAM,SAAS,EAAK,GACtC,IAAa,EAAM,MAAM,GACzB,IAAW,EAAa,GAGxB,IAAY,MAAc,EAAS,SAGnC,CAAC,GAAe,KAAoB,EAAM,SAAS,CAAK,GAGxD,CAAC,GAAU,KAAe,EAAM,SAAwB,IAAI;CAClE,EAAM,gBAAgB;EAA2B,AAAzB,EAAiB,CAAK,GAAG,EAAY,IAAI;CAAE,GAAG,CAAC,CAAK,CAAC;CAG7E,IAAM,CAAC,GAAW,KAAgB,EAAM,SAAS,CAAK,GAChD,CAAC,GAAW,KAAgB,EAAM,SAAmB,CAAC,CAAC,GAEvD,IAAa,EAAM,OAAO,EAAK,GAE/B,KAAoB,MAAoB;EACxC,MACA,MACF,EAAa,CAAa,GAC1B,EAAa,CAAC,CAAC,IAEjB,EAAY,IAAI,GAChB,EAAQ,CAAM;CAChB,GAGM,KAAwB,MAAqB;EACjD,IAAI,GAAU;EAEd,IAAM,KADa,EAAS,WAAW,GAAG,IAAI,IAAW,IAAI,IAAA,CACtC,YAAY;EAOnC,AANA,GAAc,MACR,EAAK,EAAK,SAAS,OAAO,IAAsB,IAC7C,CAAC,GAAG,EAAK,MAAM,GAAG,GAAG,CAAa,CAC1C,GACD,EAAiB,CAAG,GACpB,EAAY,IAAI,GAChB,IAAW,CAAG;CAChB,GAGM,KAAgB,MAAqB;EACzC,IAAI,GAAU;EAEd,IAAM,KADa,EAAS,WAAW,GAAG,IAAI,IAAW,IAAI,IAAA,CACtC,YAAY;EAUnC,AATK,EAAW,YAEd,EAAW,UAAU,IACrB,GAAc,MACR,EAAK,EAAK,SAAS,OAAO,IAAsB,IAC7C,CAAC,GAAG,EAAK,MAAM,GAAG,GAAG,CAAa,CAC1C,IAEH,EAAiB,CAAG,GACpB,IAAW,CAAG;CAChB,GAGM,UAAmC;EACvC,EAAW,UAAU;CACvB,GAEM,UAAmB;EACvB,IAAI,EAAU,WAAW,GAAG;EAC5B,IAAM,IAAO,EAAU,EAAU,SAAS;EAG1C,AAFA,GAAc,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,GAClC,EAAiB,CAAI,GACrB,IAAW,CAAI;CACjB,GAEM,UAAoB;EAGxB,AAFA,EAAiB,CAAS,GAC1B,IAAW,CAAS,GACpB,EAAa,CAAC,CAAC;CACjB,GAGM,IAAkB,MAAY,KAChC,CAAC,IACD,IACE,EAAQ,KAAK,MACX,OAAO,KAAM,WAAW;EAAE,KAAK;EAAG,OAAO;CAAE,IAAI,CACjD,IACA,IAGA,IAAM,EAAS,CAAa,GAC5B,IAAM,EAAS,CAAa,GAG5B,KAAmB,GAA0B,MAAc;EAC/D,IAAI,CAAC,GAAK;EACV,IAAM,IAAM,SAAS,GAAG,EAAE;EAC1B,IAAI,MAAM,CAAG,GAAG;EAChB,IAAM,IAAU,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,CAAG,CAAC;EAC9C,EAAqB,EACnB,MAAY,MAAM,IAAU,EAAI,GAChC,MAAY,MAAM,IAAU,EAAI,GAChC,MAAY,MAAM,IAAU,EAAI,CAClC,CAAC;CACH,GAGM,KAAmB,GAA0B,MAAc;EAC/D,IAAI,CAAC,GAAK;EACV,IAAM,IAAM,SAAS,GAAG,EAAE;EAC1B,IAAI,MAAM,CAAG,GAAG;EAEhB,IAAM,IAAU,KAAK,IAAI,GAAG,KAAK,IADrB,MAAY,MAAM,MAAM,KACM,CAAG,CAAC;EAC9C,EAAqB,EACnB,MAAY,MAAM,IAAU,EAAI,GAChC,MAAY,MAAM,IAAU,EAAI,GAChC,MAAY,MAAM,IAAU,EAAI,CAClC,CAAC;CACH,GAEM,KAAyB;EAAC;EAAO;EAAO;CAAK;CAEnD,OACE,kBAAC,OAAD;EAAU;EAAK,WAAW,EAAG,wBAAwB,CAAS;EAAG,GAAI;YACnE,kBAAC,GAAD;GAAe;GAAM,cAAc;aAAnC,CACE,kBAAC,GAAD;IAAgB,SAAA;cACb,OAAY,WACX,kBAAC,EAAO,QAAR;KACE,MAAK;KACK;KACV,WAAW,EACT,+GACA,4GACA,KAAY,+BACd;KACA,SAAS;MACP,iBAAiB;MACjB,OAAO,GAAa,CAAa,IAAI,oBAAoB;KAC3D;KACA,YAAY;MAAE,GAAG;MAAI,WAAW;KAA8B;KAC9D,UAAU,EAAE,OAAO,IAAK;KACxB,YAAY,EAAQ;KACpB,IAAI;KACJ,oBAAkB,EAAS;KAC3B,gBAAc,EAAS,UAAU,WAAW,KAAA;KAE5C,cAAY,EAAS,UAAU,KAAA,IAAY,iBAAiB;eAE3D,EAAc,YAAY;IACd,CAAA,IAEf,kBAAC,EAAO,QAAR;KACE,MAAK;KACK;KACV,WAAW,EACT,wGACA,qGACA,KAAY,+BACd;KACA,YAAY,EAAE,OAAO,KAAK;KAC1B,UAAU,EAAE,OAAO,IAAK;KACxB,YAAY,EAAQ;KACpB,IAAI;KACJ,oBAAkB,EAAS;KAC3B,gBAAc,EAAS,UAAU,WAAW,KAAA;KAE5C,cAAY,EAAS,UAAU,KAAA,IAAY,iBAAiB;eAf9D;MAkBE,kBAAC,EAAO,MAAR;OACE,WAAU;OACV,SAAS,EACP,YAAY,6BAA6B,EAAc,OAAO,EAAc,wBAC9E;OAEA,YAAY,EAAE,UAAU,GAAI;MAC7B,CAAA;MACD,kBAAC,QAAD;OAAM,WAAU;OAAyC,OAAO;QAC9D,WAAW;QACX,iBAAiB;OACnB;MAAI,CAAA;MAEJ,kBAAC,QAAD;OAAM,WAAU;iBACb,EAAc,YAAY;MACvB,CAAA;KACO;;GAEH,CAAA,GAEhB,kBAAC,GAAD;IACE,MAAK;IACL,cAAW;IACJ;IACP,YAAY;IACZ,WAAU;cAEV,kBAAC,OAAD;KAAK,WAAU;eAAf;MAEG,KACC,kBAAC,OAAD;OAAK,WAAU;OAAmB,aAAa;OAA4B,gBAAgB;iBACzF,kBAAC,GAAD;QACE,OAAO;QACP,UAAU;QACV,WAAU;QACV,OAAO,EAAE,QAAQ,IAAI;OACtB,CAAA;MACE,CAAA;MAIP,kBAAC,OAAD;OAAK,WAAU;iBAAf,CAEE,kBAAC,OAAD;QAAK,WAAU;kBACZ,GAAQ,KAAK,MACZ,kBAAC,UAAD;SAEE,MAAK;SACL,eAAe,EAAU,CAAC;SAC1B,WAAW,EACT,gIACA,MAAW,IACP,mBACA,6CACN;mBATF,CAWG,MAAW,KACV,kBAAC,EAAO,MAAR;UACE,UAAU,2BAA2B;UACrC,WAAU;UACV,YAAY,EAAQ;SACrB,CAAA,GAEH,kBAAC,QAAD;UAAM,WAAU;oBAAiB;SAAQ,CAAA,CACnC;WAlBD,CAkBC,CACT;OACE,CAAA,GAGL,kBAAC,GAAD;QAAiB,MAAK;kBAAtB;SACG,MAAW,SACV,kBAAC,EAAO,KAAR;UAEE,SAAS;WAAE,SAAS;WAAG,GAAG;UAAE;UAC5B,SAAS;WAAE,SAAS;WAAG,GAAG;UAAE;UAC5B,MAAM;WAAE,SAAS;WAAG,GAAG;UAAG;UAC1B,YAAY,EAAE,UAAU,EAAU,WAAW;UAC7C,WAAU;oBAEV,kBAAC,GAAD;WACE,IAAI,GAAG,EAAW;WAClB,OAAM;WACN,OAAO,KAAY,EAAc,QAAQ,KAAK,EAAE,CAAC,CAAC,YAAY;WAC9D,WAAW,MAAM;YACf,IAAM,IAAQ,EAAE,QAAQ,iBAAiB,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC;YAEvD,AADA,EAAY,EAAM,YAAY,CAAC,GAC3B,EAAM,WAAW,KAAG,EAAqB,IAAI,GAAO;WAC1D;WACA,cAAc;YAGZ,EAAY,IAAI;WAClB;WACU;WACV,WAAW;WACX,QAAO;WACP,WAAU;UACX,CAAA;SACS,GA1BN,KA0BM;SAGb,MAAW,SAAS,KACnB,kBAAC,EAAO,KAAR;UAEE,SAAS;WAAE,SAAS;WAAG,GAAG;UAAE;UAC5B,SAAS;WAAE,SAAS;WAAG,GAAG;UAAE;UAC5B,MAAM;WAAE,SAAS;WAAG,GAAG;UAAG;UAC1B,YAAY,EAAE,UAAU,EAAU,WAAW;UAC7C,WAAU;oBANZ;WAQE,kBAAC,GAAD;YAAa,IAAI,GAAG,EAAW;YAAK,OAAM;YAAI,OAAO,OAAO,EAAI,CAAC;YAAG,WAAW,MAAM,EAAgB,KAAK,CAAC;YAAa;YAAU,WAAU;WAAU,CAAA;WACtJ,kBAAC,GAAD;YAAa,IAAI,GAAG,EAAW;YAAK,OAAM;YAAI,OAAO,OAAO,EAAI,CAAC;YAAG,WAAW,MAAM,EAAgB,KAAK,CAAC;YAAa;YAAU,WAAU;WAAU,CAAA;WACtJ,kBAAC,GAAD;YAAa,IAAI,GAAG,EAAW;YAAK,OAAM;YAAI,OAAO,OAAO,EAAI,CAAC;YAAG,WAAW,MAAM,EAAgB,KAAK,CAAC;YAAa;YAAU,WAAU;WAAU,CAAA;UAC5I;YAVN,KAUM;SAGb,MAAW,SAAS,KACnB,kBAAC,EAAO,KAAR;UAEE,SAAS;WAAE,SAAS;WAAG,GAAG;UAAE;UAC5B,SAAS;WAAE,SAAS;WAAG,GAAG;UAAE;UAC5B,MAAM;WAAE,SAAS;WAAG,GAAG;UAAG;UAC1B,YAAY,EAAE,UAAU,EAAU,WAAW;UAC7C,WAAU;oBANZ;WAQE,kBAAC,GAAD;YAAa,IAAI,GAAG,EAAW;YAAK,OAAM;YAAI,OAAO,OAAO,EAAI,CAAC;YAAG,WAAW,MAAM,EAAgB,KAAK,CAAC;YAAa;YAAU,WAAU;WAAU,CAAA;WACtJ,kBAAC,GAAD;YAAa,IAAI,GAAG,EAAW;YAAK,OAAM;YAAI,OAAO,OAAO,EAAI,CAAC;YAAG,WAAW,MAAM,EAAgB,KAAK,CAAC;YAAa;YAAU,WAAU;WAAU,CAAA;WACtJ,kBAAC,GAAD;YAAa,IAAI,GAAG,EAAW;YAAK,OAAM;YAAI,OAAO,OAAO,EAAI,CAAC;YAAG,WAAW,MAAM,EAAgB,KAAK,CAAC;YAAa;YAAU,WAAU;WAAU,CAAA;UAC5I;YAVN,KAUM;QAEC;SACd;;MAGJ,EAAgB,SAAS,KACxB,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,OAAD;QAAK,WAAU;kBACZ,EAAgB,KAAK,GAAQ,MAAM;SAClC,IAAM,IAAa,EAAc,YAAY,MAAM,EAAO,IAAI,YAAY;SAC1E,OACE,kBAAC,EAAO,QAAR;UAEE,MAAK;UACK;UACV,eAAe,EAAqB,EAAO,GAAG;UAC9C,SAAS;WAAE,SAAS;WAAG,OAAO;UAAI;UAClC,SAAS;WAAE,SAAS;WAAG,OAAO,IAAa,OAAO;UAAE;UACpD,YAAY,EAAE,OAAO,IAAa,OAAO,IAAI;UAC7C,UAAU,EAAE,OAAO,GAAI;UACvB,YAAY;WAAE,GAAG,EAAQ;WAAQ,OAAO,IAAI;UAAK;UACjD,WAAW,EACT,wCACA,IACI,4CACA,4DACJ,KAAY,+BACd;UACA,OAAO,EAAE,iBAAiB,EAAO,IAAI;UACrC,OAAO,EAAO;UACd,cAAY,GAAG,EAAO,MAAM,IAAI,EAAO;SACxC,GAnBM,EAAO,GAmBb;QAEL,CAAC;OACE,CAAA;MACF,CAAA;OAIL,EAAU,SAAS,KAAK,MAAkB,MAC1C,kBAAC,EAAO,KAAR;OACE,SAAS;QAAE,SAAS;QAAG,QAAQ;OAAE;OACjC,SAAS;QAAE,SAAS;QAAG,QAAQ;OAAO;OACtC,MAAM;QAAE,SAAS;QAAG,QAAQ;OAAE;OAC9B,WAAU;iBAJZ;QAOE,kBAAC,QAAD;SACE,WAAU;SACV,OAAO,EAAE,iBAAiB,EAAU;SACpC,OAAO,aAAa;QACrB,CAAA;QACD,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAU,YAAY;QACnB,CAAA;QACN,kBAAC,QAAD,EAAM,WAAU,SAAU,CAAA;QACzB,EAAU,SAAS,KAClB,kBAAC,UAAD;SACE,MAAK;SACL,SAAS;SACT,WAAU;mBACX;QAEO,CAAA;QAET,MAAkB,KACjB,kBAAC,UAAD;SACE,MAAK;SACL,SAAS;SACT,WAAU;mBACX;QAEO,CAAA;OAEA;;KAEX;;GACS,CAAA,CACT;;CACN,CAAA;AAET,CACF;AACA,EAAW,cAAc"}
1
+ {"version":3,"file":"color-input.js","names":[],"sources":["../../src/ui/color-input.tsx"],"sourcesContent":["'use client'\n\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\nimport { HexColorPicker } from 'react-colorful'\n\nimport { useFormField } from './form'\nimport { durations,springs } from './lib/motion'\nimport { cn } from './lib/utils'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from './popover'\n\n// ── Color conversion helpers ──\n\nfunction hexToRgb(hex: string): { r: number; g: number; b: number } | null {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex)\n if (!m) return null\n const n = parseInt(m[1], 16)\n return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 }\n}\n\nfunction rgbToHex(r: number, g: number, b: number): string {\n return '#' + [r, g, b].map((v) => Math.max(0, Math.min(255, Math.round(v))).toString(16).padStart(2, '0')).join('')\n}\n\nfunction hexToHsl(hex: string): { h: number; s: number; l: number } | null {\n const rgb = hexToRgb(hex)\n if (!rgb) return null\n const r = rgb.r / 255, g = rgb.g / 255, b = rgb.b / 255\n const max = Math.max(r, g, b), min = Math.min(r, g, b)\n const l = (max + min) / 2\n if (max === min) return { h: 0, s: 0, l: Math.round(l * 100) }\n const d = max - min\n const s = l > 0.5 ? d / (2 - max - min) : d / (max - min)\n let h = 0\n if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6\n else if (max === g) h = ((b - r) / d + 2) / 6\n else h = ((r - g) / d + 4) / 6\n return { h: Math.round(h * 360), s: Math.round(s * 100), l: Math.round(l * 100) }\n}\n\nfunction hslToHex(h: number, s: number, l: number): string {\n const sn = s / 100, ln = l / 100\n const a = sn * Math.min(ln, 1 - ln)\n const f = (n: number) => {\n const k = (n + h / 30) % 12\n const c = ln - a * Math.max(Math.min(k - 3, 9 - k, 1), -1)\n return Math.round(255 * c)\n }\n return rgbToHex(f(0), f(8), f(4))\n}\n\n// ── Named color presets ──\n// Brand spectrum derived from our OKLCH scales (step-9), spanning the wheel —\n// intentional and on-brand, NOT the raw framework palette. Led by red, not indigo.\n\nconst NAMED_PRESETS: { hex: string; label: string }[] = [\n { hex: '#C53637', label: 'Red' },\n { hex: '#BE5A0A', label: 'Orange' },\n { hex: '#DF911A', label: 'Amber' },\n { hex: '#308639', label: 'Green' },\n { hex: '#118659', label: 'Emerald' },\n { hex: '#11846E', label: 'Teal' },\n { hex: '#028A9B', label: 'Cyan' },\n { hex: '#1479B0', label: 'Blue' },\n { hex: '#7D5FAD', label: 'Purple' },\n { hex: '#C22D6D', label: 'Pink' },\n]\n\n// ── Contrast helper ──\n\nfunction isLightColor(hex: string): boolean {\n const rgb = hexToRgb(hex)\n if (!rgb) return false\n // Relative luminance (sRGB)\n const [r, g, b] = [rgb.r, rgb.g, rgb.b].map((c) => {\n const s = c / 255\n return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4)\n })\n return 0.2126 * r + 0.7152 * g + 0.0722 * b > 0.4\n}\n\n// ── Format mode type ──\n\ntype ColorFormat = 'hex' | 'rgb' | 'hsl'\n\n// ── Props ──\n\nexport interface ColorInputProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Current color value (hex string, e.g. \"#d33163\") */\n value?: string\n /** Called when the color changes */\n onChange?: (value: string) => void\n /** Preset color swatches. Defaults to 10 named colors. Pass `false` to hide. */\n presets?: { hex: string; label: string }[] | string[] | false\n /** Whether the input is disabled */\n disabled?: boolean\n /** Show the interactive color picker. Default: true. */\n showPicker?: boolean\n /** Default format for the input fields. Default: 'hex'. */\n defaultFormat?: ColorFormat\n /** Popover alignment. Default: 'start'. */\n align?: 'start' | 'center' | 'end'\n /**\n * Trigger style variant.\n * - `default`: Swatch bleeds to left edge + hex text\n * - `inline`: Entire trigger is the selected color with hex text overlaid\n */\n variant?: 'default' | 'inline'\n}\n\n// ── Small format input ──\n\nfunction FormatInput({\n label,\n value,\n onChange,\n onBlur,\n disabled,\n maxLength = 3,\n prefix,\n className,\n id,\n}: {\n label: string\n value: string\n onChange: (v: string) => void\n onBlur?: () => void\n disabled?: boolean\n maxLength?: number\n prefix?: string\n className?: string\n id: string\n}) {\n return (\n <div className={cn('flex flex-col gap-ds-01', className)}>\n <label htmlFor={id} className=\"text-label-xs font-medium uppercase tracking-wider text-surface-fg-muted\">\n {label}\n </label>\n <div className=\"flex items-center\">\n {prefix && (\n <span className=\"text-body-sm text-surface-fg-muted\">{prefix}</span>\n )}\n <input\n id={id}\n type=\"text\"\n value={value}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n maxLength={maxLength}\n className={cn(\n 'h-ds-xs-plus w-full rounded-control-inner border border-surface-border-interactive bg-surface-overlay px-ds-02 font-mono text-body-sm text-surface-fg transition-colors',\n 'focus:border-accent-7 focus:outline-hidden focus:ring-1 focus:ring-accent-9',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n />\n </div>\n </div>\n )\n}\n\n// ── Main component ──\n\nconst ColorInput = React.forwardRef<HTMLDivElement, ColorInputProps>(\n ({\n value = '#000000',\n onChange,\n presets,\n disabled = false,\n showPicker = true,\n defaultFormat = 'hex',\n align = 'start',\n variant = 'default',\n className,\n id: externalId,\n ...props\n }, ref) => {\n const [format, setFormat] = React.useState<ColorFormat>(defaultFormat)\n const [open, setOpen] = React.useState(false)\n const instanceId = React.useId()\n const fieldCtx = useFormField()\n // Explicit id wins; otherwise adopt FormField's inputId so <Label htmlFor> resolves\n // onto the (labelable) trigger button. The root is a <div>, which can't be a label target.\n const triggerId = externalId ?? fieldCtx.inputId\n\n // Internal color state — syncs with prop, allows uncontrolled use\n const [internalColor, setInternalColor] = React.useState(value)\n // Draft state for the hex field so in-progress (<6 char) typing isn't clobbered\n // by re-renders off internalColor. null = show the committed color.\n const [hexDraft, setHexDraft] = React.useState<string | null>(null)\n React.useEffect(() => { setInternalColor(value); setHexDraft(null) }, [value])\n\n // Track color when popover opened (for reset) + undo history\n const [openColor, setOpenColor] = React.useState(value)\n const [undoStack, setUndoStack] = React.useState<string[]>([])\n // Track whether current change is from continuous drag (skip undo push)\n const isDragging = React.useRef(false)\n\n const handleOpenChange = (isOpen: boolean) => {\n if (disabled) return\n if (isOpen) {\n setOpenColor(internalColor)\n setUndoStack([])\n }\n setHexDraft(null)\n setOpen(isOpen)\n }\n\n // Discrete change (preset click, field commit) — pushes to undo\n const handleDiscreteChange = (newValue: string) => {\n if (disabled) return\n const normalized = newValue.startsWith('#') ? newValue : `#${newValue}`\n const hex = normalized.toLowerCase()\n setUndoStack((prev) => {\n if (prev[prev.length - 1] === internalColor) return prev\n return [...prev.slice(-19), internalColor]\n })\n setInternalColor(hex)\n setHexDraft(null)\n onChange?.(hex)\n }\n\n // Continuous change (picker drag) — updates color but only pushes undo on drag start\n const handleChange = (newValue: string) => {\n if (disabled) return\n const normalized = newValue.startsWith('#') ? newValue : `#${newValue}`\n const hex = normalized.toLowerCase()\n if (!isDragging.current) {\n // First change in a drag sequence — push current color to undo\n isDragging.current = true\n setUndoStack((prev) => {\n if (prev[prev.length - 1] === internalColor) return prev\n return [...prev.slice(-19), internalColor]\n })\n }\n setInternalColor(hex)\n onChange?.(hex)\n }\n\n // Called when picker drag ends\n const handlePickerChangeComplete = () => {\n isDragging.current = false\n }\n\n const handleUndo = () => {\n if (undoStack.length === 0) return\n const prev = undoStack[undoStack.length - 1]\n setUndoStack((s) => s.slice(0, -1))\n setInternalColor(prev)\n onChange?.(prev)\n }\n\n const handleReset = () => {\n setInternalColor(openColor)\n onChange?.(openColor)\n setUndoStack([])\n }\n\n // Resolve presets\n const resolvedPresets = presets === false\n ? []\n : presets\n ? presets.map((p) =>\n typeof p === 'string' ? { hex: p, label: p } : p\n )\n : NAMED_PRESETS\n\n // Parsed color values — use internal state\n const rgb = hexToRgb(internalColor)\n const hsl = hexToHsl(internalColor)\n\n // RGB field handlers (clamped 0-255)\n const handleRgbChange = (channel: 'r' | 'g' | 'b', v: string) => {\n if (!rgb) return\n const num = parseInt(v, 10)\n if (isNaN(num)) return\n const clamped = Math.max(0, Math.min(255, num))\n handleDiscreteChange(rgbToHex(\n channel === 'r' ? clamped : rgb.r,\n channel === 'g' ? clamped : rgb.g,\n channel === 'b' ? clamped : rgb.b,\n ))\n }\n\n // HSL field handlers (H: 0-360, S/L: 0-100)\n const handleHslChange = (channel: 'h' | 's' | 'l', v: string) => {\n if (!hsl) return\n const num = parseInt(v, 10)\n if (isNaN(num)) return\n const max = channel === 'h' ? 360 : 100\n const clamped = Math.max(0, Math.min(max, num))\n handleDiscreteChange(hslToHex(\n channel === 'h' ? clamped : hsl.h,\n channel === 's' ? clamped : hsl.s,\n channel === 'l' ? clamped : hsl.l,\n ))\n }\n\n const formats: ColorFormat[] = ['hex', 'rgb', 'hsl']\n\n return (\n <div ref={ref} className={cn('inline-flex flex-col', className)} {...props}>\n <Popover open={open} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n {variant === 'inline' ? (\n <motion.button\n type=\"button\"\n disabled={disabled}\n className={cn(\n 'group flex items-center justify-center rounded-control px-ds-04 py-ds-02 font-mono text-body-sm font-medium',\n 'focus:outline-hidden focus:ring-2 focus:ring-accent-9 focus:ring-offset-2 focus:ring-offset-surface-base',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n animate={{\n backgroundColor: internalColor,\n color: isLightColor(internalColor) ? 'rgba(0,0,0,0.8)' : 'rgba(255,255,255,0.95)',\n }}\n whileHover={{ y: -1, boxShadow: '0 4px 12px rgba(0,0,0,0.12)' }}\n whileTap={{ scale: 0.97 }}\n transition={springs.smooth}\n id={triggerId}\n aria-describedby={fieldCtx.helperTextId}\n aria-invalid={fieldCtx.state === 'error' || undefined}\n // Inside a FormField, let the visible <Label> name the trigger; else describe it.\n aria-label={fieldCtx.inputId ? undefined : `Color picker: ${internalColor}`}\n >\n {internalColor.toUpperCase()}\n </motion.button>\n ) : (\n <motion.button\n type=\"button\"\n disabled={disabled}\n className={cn(\n 'group relative flex items-center overflow-hidden rounded-control border border-surface-border-interactive',\n 'hover:border-accent-7 focus:border-accent-7 focus:outline-hidden focus:ring-1 focus:ring-accent-9',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n whileHover={{ scale: 1.02 }}\n whileTap={{ scale: 0.98 }}\n transition={springs.snappy}\n id={triggerId}\n aria-describedby={fieldCtx.helperTextId}\n aria-invalid={fieldCtx.state === 'error' || undefined}\n // Inside a FormField, let the visible <Label> name the trigger; else describe it.\n aria-label={fieldCtx.inputId ? undefined : `Color picker: ${internalColor}`}\n >\n {/* Gradient background: color → surface */}\n <motion.span\n className=\"absolute inset-0\"\n animate={{\n background: `linear-gradient(to right, ${internalColor} 0%, ${internalColor} 35%, transparent 70%)`,\n }}\n /* Between durations.moderate02 (0.24) and durations.slow01 (0.4) — gradient lerp feel */\n transition={{ duration: 0.3 }}\n />\n <span className=\"absolute inset-0 bg-surface-overlay/60\" style={{\n maskImage: 'linear-gradient(to right, transparent 0%, black 40%)',\n WebkitMaskImage: 'linear-gradient(to right, transparent 0%, black 40%)',\n }} />\n {/* Hex value */}\n <span className=\"relative z-10 py-ds-02 pl-6 pr-ds-03 font-mono text-body-sm text-surface-fg\">\n {internalColor.toUpperCase()}\n </span>\n </motion.button>\n )}\n </PopoverTrigger>\n\n <PopoverContent\n role=\"dialog\"\n aria-label=\"Color picker\"\n align={align}\n sideOffset={8}\n className=\"w-[272px] rounded-overlay-lg bg-surface-overlay p-0 shadow-floating\"\n >\n <div className=\"flex flex-col\">\n {/* Interactive picker */}\n {showPicker && (\n <div className=\"p-ds-04 pb-ds-03\" onPointerUp={handlePickerChangeComplete} onPointerLeave={handlePickerChangeComplete}>\n <HexColorPicker\n color={internalColor}\n onChange={handleChange}\n className=\"w-full!\"\n style={{ height: 160 }}\n />\n </div>\n )}\n\n {/* Format inputs */}\n <div className=\"border-t border-surface-border px-ds-04 py-ds-03\">\n {/* Format switcher */}\n <div className=\"mb-ds-03 flex items-center gap-ds-01\">\n {formats.map((f) => (\n <button\n key={f}\n type=\"button\"\n onClick={() => setFormat(f)}\n className={cn(\n 'relative min-h-6 rounded-control-inner px-ds-02 py-px text-label-xs font-semibold uppercase tracking-wider transition-colors',\n format === f\n ? 'text-accent-11'\n : 'text-surface-fg-muted hover:text-surface-fg',\n )}\n >\n {format === f && (\n <motion.span\n layoutId={`color-input-format-pill-${instanceId}`}\n className=\"absolute inset-0 rounded-control-inner bg-accent-3\"\n transition={springs.snappy}\n />\n )}\n <span className=\"relative z-10\">{f}</span>\n </button>\n ))}\n </div>\n\n {/* Format fields — animated swap */}\n <AnimatePresence mode=\"wait\">\n {format === 'hex' && (\n <motion.div\n key=\"hex\"\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -4 }}\n transition={{ duration: durations.moderate01 }}\n className=\"flex gap-ds-02\"\n >\n <FormatInput\n id={`${instanceId}-hex`}\n label=\"Hex\"\n value={hexDraft ?? internalColor.replace('#', '').toUpperCase()}\n onChange={(v) => {\n const clean = v.replace(/[^0-9a-fA-F]/g, '').slice(0, 6)\n setHexDraft(clean.toUpperCase())\n if (clean.length === 6) handleDiscreteChange(`#${clean}`)\n }}\n onBlur={() => {\n // Drop any incomplete draft; display falls back to the\n // committed color. A complete value already committed onChange.\n setHexDraft(null)\n }}\n disabled={disabled}\n maxLength={6}\n prefix=\"#\"\n className=\"flex-1\"\n />\n </motion.div>\n )}\n\n {format === 'rgb' && rgb && (\n <motion.div\n key=\"rgb\"\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -4 }}\n transition={{ duration: durations.moderate01 }}\n className=\"flex gap-ds-02\"\n >\n <FormatInput id={`${instanceId}-r`} label=\"R\" value={String(rgb.r)} onChange={(v) => handleRgbChange('r', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-g`} label=\"G\" value={String(rgb.g)} onChange={(v) => handleRgbChange('g', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-b`} label=\"B\" value={String(rgb.b)} onChange={(v) => handleRgbChange('b', v)} disabled={disabled} className=\"flex-1\" />\n </motion.div>\n )}\n\n {format === 'hsl' && hsl && (\n <motion.div\n key=\"hsl\"\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -4 }}\n transition={{ duration: durations.moderate01 }}\n className=\"flex gap-ds-02\"\n >\n <FormatInput id={`${instanceId}-h`} label=\"H\" value={String(hsl.h)} onChange={(v) => handleHslChange('h', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-s`} label=\"S\" value={String(hsl.s)} onChange={(v) => handleHslChange('s', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-l`} label=\"L\" value={String(hsl.l)} onChange={(v) => handleHslChange('l', v)} disabled={disabled} className=\"flex-1\" />\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n\n {/* Preset swatches */}\n {resolvedPresets.length > 0 && (\n <div className=\"border-t border-surface-border px-ds-04 py-ds-03\">\n <div className=\"flex flex-wrap gap-ds-02\">\n {resolvedPresets.map((preset, i) => {\n const isSelected = internalColor.toLowerCase() === preset.hex.toLowerCase()\n return (\n <motion.button\n key={preset.hex}\n type=\"button\"\n disabled={disabled}\n onClick={() => handleDiscreteChange(preset.hex)}\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{ opacity: 1, scale: isSelected ? 1.15 : 1 }}\n whileHover={{ scale: isSelected ? 1.15 : 1.1 }}\n whileTap={{ scale: 0.9 }}\n transition={{ ...springs.bouncy, delay: i * 0.02 }}\n className={cn(\n 'h-6 w-6 rounded-control-inner border',\n isSelected\n ? 'border-accent-7 ring-2 ring-accent-9/30'\n : 'border-surface-border-interactive hover:border-surface-border-interactive-strong',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n style={{ backgroundColor: preset.hex }}\n title={preset.label}\n aria-label={`${preset.label}: ${preset.hex}`}\n />\n )\n })}\n </div>\n </div>\n )}\n\n {/* Reset / Undo footer */}\n {(undoStack.length > 0 || internalColor !== openColor) && (\n <motion.div\n initial={{ opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: 'auto' }}\n exit={{ opacity: 0, height: 0 }}\n className=\"flex items-center gap-ds-02 border-t border-surface-border px-ds-04 py-ds-02\"\n >\n {/* Original color preview */}\n <span\n className=\"h-4 w-4 shrink-0 rounded-pill border border-surface-border\"\n style={{ backgroundColor: openColor }}\n title={`Original: ${openColor}`}\n />\n <span className=\"text-caption text-surface-fg-muted\">\n {openColor.toUpperCase()}\n </span>\n <span className=\"flex-1\" />\n {undoStack.length > 0 && (\n <button\n type=\"button\"\n onClick={handleUndo}\n className=\"min-h-6 rounded-control-inner px-ds-02 py-px text-caption font-medium text-surface-fg-muted transition-colors hover:text-surface-fg\"\n >\n Undo\n </button>\n )}\n {internalColor !== openColor && (\n <button\n type=\"button\"\n onClick={handleReset}\n className=\"min-h-6 rounded-control-inner px-ds-02 py-px text-caption font-medium text-surface-fg-muted transition-colors hover:text-error-11\"\n >\n Reset\n </button>\n )}\n </motion.div>\n )}\n </div>\n </PopoverContent>\n </Popover>\n </div>\n )\n },\n)\nColorInput.displayName = 'ColorInput'\n\nexport { ColorInput }\n"],"mappings":"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"}