@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":"number-input.js","names":[],"sources":["../../src/ui/number-input.tsx"],"sourcesContent":["'use client'\n\nimport { IconMinus, IconPlus } from '@tabler/icons-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { useFormField } from './form'\nimport { Icon } from './icon'\nimport type { IconSize } from './icon-context'\nimport { type FieldState, resolveFieldState } from './lib/field-state'\nimport { cn } from './lib/utils'\n\n/** @deprecated Use `FieldState` — the shared control-state type. Kept as an alias. */\nexport type NumberInputState = FieldState\n\nconst numberInputWrapperVariants = cva(\n 'flex items-center justify-between rounded-control border border-surface-border-strong',\n {\n variants: {\n size: {\n xs: 'h-ds-xs-plus',\n sm: 'h-ds-sm',\n md: 'h-ds-md',\n lg: 'h-ds-lg',\n },\n },\n defaultVariants: { size: 'md' },\n },\n)\n\nexport type NumberInputSize = NonNullable<VariantProps<typeof numberInputWrapperVariants>['size']>\n\n/** Maps size to stepper button dimensions */\nconst buttonSizeMap: Record<NonNullable<NumberInputSize>, string> = {\n xs: 'h-[22px] w-[22px]',\n sm: 'h-ds-sm w-ds-sm',\n md: 'h-ds-sm w-ds-sm',\n lg: 'h-ds-md w-ds-md',\n}\n\n/** Maps size to Icon component size */\nconst iconSizeMap: Record<NonNullable<NumberInputSize>, IconSize> = {\n xs: 'xs',\n sm: 'sm',\n md: 'sm',\n lg: 'md',\n}\n\n/** Maps size to input text and width classes */\nconst inputSizeMap: Record<NonNullable<NumberInputSize>, string> = {\n xs: 'text-body-sm w-ds-06b',\n sm: 'text-body-sm w-ds-sm-plus',\n md: 'text-body-md w-ds-sm-plus',\n lg: 'text-body-md w-ds-md',\n}\n\n/** Maps state to border color classes */\nconst stateColorMap: Record<NonNullable<NumberInputState>, string> = {\n default: '',\n error: 'border-error-7',\n warning: 'border-warning-7',\n success: 'border-success-7',\n}\n\n/**\n * Props for NumberInput — a stepper control with \"−\" and \"+\" buttons flanking a numeric input,\n * clamped between `min` and `max`. The decrement/increment buttons are disabled when bounds are reached.\n *\n * **Controlled only:** Pass `value` + `onValueChange` for controlled usage. Uncontrolled usage is\n * possible but the buttons won't update the displayed value without `onValueChange`.\n *\n * **Step:** The `step` prop controls how much each button press increments/decrements (default 1).\n * Direct text input is also clamped to `[min, max]` on change.\n *\n * **Sizes:** `xs` (28px) | `sm` (32px) | `md` (40px, default) | `lg` (48px)\n *\n * **Validation states:** `state=\"error\"` colors the border red.\n * Use with `<FormField>` to show helper text below the input.\n *\n * @example\n * // Quantity selector with 1–99 range:\n * <NumberInput value={qty} onValueChange={setQty} min={1} max={99} />\n *\n * @example\n * // Rating input (1–10, step 1):\n * <NumberInput value={rating} onValueChange={setRating} min={1} max={10} />\n *\n * @example\n * // Fine-grained opacity control (0–100, step 5):\n * <NumberInput value={opacity} onValueChange={setOpacity} min={0} max={100} step={5} />\n *\n * @example\n * // Disabled number display (read-only-like):\n * <NumberInput value={autoCalcValue} onValueChange={() => {}} disabled />\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface NumberInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type' | 'size'> {\n value?: number\n onValueChange?: (value: number) => void\n min?: number\n max?: number\n step?: number\n /** Size of the number input. Controls height, button sizes, text size. */\n size?: NumberInputSize\n /** Validation state controlling border color. */\n state?: FieldState\n}\n\nconst NumberInput = React.forwardRef<HTMLInputElement, NumberInputProps>(\n (\n {\n value = 0,\n onValueChange,\n min = Number.MIN_SAFE_INTEGER,\n max = Number.MAX_SAFE_INTEGER,\n step = 1,\n disabled = false,\n className,\n size: sizeProp = 'md',\n state: stateProp,\n 'aria-label': ariaLabelProp,\n ...rest\n },\n ref,\n ) => {\n const size = sizeProp ?? 'md'\n const fieldCtx = useFormField()\n // If no explicit aria-label and not inside a FormField (no id to associate with Label),\n // provide a sensible default\n const ariaLabel = ariaLabelProp ?? (rest.id || fieldCtx.helperTextId ? undefined : 'Numeric value')\n\n // Merge FormField context — explicit props always win (shared precedence)\n const state = resolveFieldState(stateProp, fieldCtx.state) ?? 'default'\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const raw = e.target.value.trim()\n if (raw === '' || raw === '-') {\n onValueChange?.(min >= 0 ? min : 0)\n return\n }\n const parsed = Number(raw)\n if (Number.isNaN(parsed)) return\n const clamped = Math.min(Math.max(parsed, min), max)\n onValueChange?.(clamped)\n }\n\n const handleIncrement = (e: React.MouseEvent<HTMLButtonElement>) => {\n e.preventDefault() // Prevent form submission\n const newValue = value + step\n if (newValue <= max) {\n onValueChange?.(newValue)\n }\n }\n\n const handleDecrement = (e: React.MouseEvent<HTMLButtonElement>) => {\n e.preventDefault() // Prevent form submission\n const newValue = value - step\n if (newValue >= min) {\n onValueChange?.(newValue)\n }\n }\n\n const resolvedButtonSize = buttonSizeMap[size]\n const resolvedIconSize = iconSizeMap[size]\n const resolvedInputSize = inputSizeMap[size]\n\n return (\n <div\n className={cn(\n numberInputWrapperVariants({ size }),\n stateColorMap[state],\n className,\n )}\n >\n <button\n type=\"button\"\n onClick={handleDecrement}\n disabled={disabled || value <= min}\n aria-label=\"Decrease value\"\n title=\"Decrease\"\n className={cn(\n 'flex items-center justify-center border-0 rounded-control-inner text-surface-fg-subtle hover:bg-surface-raised-hover hover:text-surface-fg-muted active:scale-90 transition-[color,background-color,transform] duration-fast-01 ease-productive-standard disabled:opacity-action-disabled disabled:pointer-events-none',\n resolvedButtonSize,\n )}\n >\n <Icon icon={IconMinus} size={resolvedIconSize} />\n </button>\n\n <input\n ref={ref}\n type=\"number\"\n value={value}\n onChange={handleInputChange}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n aria-label={ariaLabel}\n aria-invalid={state === 'error' || undefined}\n aria-describedby={rest['aria-describedby'] ?? fieldCtx.helperTextId}\n className={cn(\n 'bg-transparent font-semibold border-0 text-center text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none',\n resolvedInputSize,\n )}\n {...rest}\n // Explicit id wins; otherwise adopt FormField's inputId so <Label htmlFor> resolves.\n id={rest.id ?? fieldCtx.inputId}\n />\n\n <button\n type=\"button\"\n onClick={handleIncrement}\n disabled={disabled || value >= max}\n aria-label=\"Increase value\"\n title=\"Increase\"\n className={cn(\n 'flex items-center justify-center border-0 rounded-control-inner text-surface-fg-subtle hover:bg-surface-raised-hover hover:text-surface-fg-muted active:scale-90 transition-[color,background-color,transform] duration-fast-01 ease-productive-standard disabled:opacity-action-disabled disabled:pointer-events-none',\n resolvedButtonSize,\n )}\n >\n <Icon icon={IconPlus} size={resolvedIconSize} />\n </button>\n </div>\n )\n },\n)\nNumberInput.displayName = 'NumberInput'\n\nexport { NumberInput, numberInputWrapperVariants }\n"],"mappings":";;;;;;;;;;AAeA,IAAM,IAA6B,EACjC,yFACA;CACE,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;CACN,EACF;CACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CACF,GAKM,IAA8D;CAClE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAGM,IAA8D;CAClE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAGM,IAA6D;CACjE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAGM,IAA+D;CACnE,SAAS;CACT,OAAO;CACP,SAAS;CACT,SAAS;AACX,GA8CM,IAAc,EAAM,YAEtB,EACE,WAAQ,GACR,kBACA,SAAM,gBACN,sBACA,UAAO,GACP,cAAW,IACX,cACA,MAAM,IAAW,MACjB,OAAO,GACP,cAAc,GACd,GAAG,KAEL,MACG;CACH,IAAM,IAAO,KAAY,MACnB,IAAW,EAAa,GAGxB,IAAY,MAAkB,EAAK,MAAM,EAAS,eAAe,KAAA,IAAY,kBAG7E,IAAQ,EAAkB,GAAW,EAAS,KAAK,KAAK,WAExD,KAAqB,MAA2C;EACpE,IAAM,IAAM,EAAE,OAAO,MAAM,KAAK;EAChC,IAAI,MAAQ,MAAM,MAAQ,KAAK;GAC7B,IAAgB,KAAO,IAAI,IAAM,CAAC;GAClC;EACF;EACA,IAAM,IAAS,OAAO,CAAG;EACrB,OAAO,MAAM,CAAM,KAEvB,IADgB,KAAK,IAAI,KAAK,IAAI,GAAQ,CAAG,GAAG,CAChC,CAAO;CACzB,GAEM,KAAmB,MAA2C;EAClE,EAAE,eAAe;EACjB,IAAM,IAAW,IAAQ;EACzB,AAAI,KAAY,KACd,IAAgB,CAAQ;CAE5B,GAEM,KAAmB,MAA2C;EAClE,EAAE,eAAe;EACjB,IAAM,IAAW,IAAQ;EACzB,AAAI,KAAY,KACd,IAAgB,CAAQ;CAE5B,GAEM,IAAqB,EAAc,IACnC,IAAmB,EAAY,IAC/B,IAAoB,EAAa;CAEvC,OACE,kBAAC,OAAD;EACE,WAAW,EACT,EAA2B,EAAE,QAAK,CAAC,GACnC,EAAc,IACd,CACF;YALF;GAOE,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,UAAU,KAAY,KAAS;IAC/B,cAAW;IACX,OAAM;IACN,WAAW,EACT,0TACA,CACF;cAEA,kBAAC,GAAD;KAAM,MAAM;KAAW,MAAM;IAAmB,CAAA;GAC1C,CAAA;GAER,kBAAC,SAAD;IACO;IACL,MAAK;IACE;IACP,UAAU;IACL;IACA;IACC;IACI;IACV,cAAY;IACZ,gBAAc,MAAU,WAAW,KAAA;IACnC,oBAAkB,EAAK,uBAAuB,EAAS;IACvD,WAAW,EACT,8QACA,CACF;IACA,GAAI;IAEJ,IAAI,EAAK,MAAM,EAAS;GACzB,CAAA;GAED,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,UAAU,KAAY,KAAS;IAC/B,cAAW;IACX,OAAM;IACN,WAAW,EACT,0TACA,CACF;cAEA,kBAAC,GAAD;KAAM,MAAM;KAAU,MAAM;IAAmB,CAAA;GACzC,CAAA;EACL;;AAET,CACF;AACA,EAAY,cAAc"}
1
+ {"version":3,"file":"number-input.js","names":[],"sources":["../../src/ui/number-input.tsx"],"sourcesContent":["'use client'\n\nimport { IconMinus, IconPlus } from '@tabler/icons-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { useFormField } from './form'\nimport { Icon } from './icon'\nimport type { IconSize } from './icon-context'\nimport { type FieldState, resolveFieldState } from './lib/field-state'\nimport { cn } from './lib/utils'\n\n/** @deprecated Use `FieldState` — the shared control-state type. Kept as an alias. */\nexport type NumberInputState = FieldState\n\nconst numberInputWrapperVariants = cva(\n 'flex items-center justify-between rounded-control border border-surface-border-interactive',\n {\n variants: {\n size: {\n xs: 'h-ds-xs-plus',\n sm: 'h-ds-sm',\n md: 'h-ds-md',\n lg: 'h-ds-lg',\n },\n },\n defaultVariants: { size: 'md' },\n },\n)\n\nexport type NumberInputSize = NonNullable<VariantProps<typeof numberInputWrapperVariants>['size']>\n\n/** Maps size to stepper button dimensions */\nconst buttonSizeMap: Record<NonNullable<NumberInputSize>, string> = {\n xs: 'h-[22px] w-[22px]',\n sm: 'h-ds-sm w-ds-sm',\n md: 'h-ds-sm w-ds-sm',\n lg: 'h-ds-md w-ds-md',\n}\n\n/** Maps size to Icon component size */\nconst iconSizeMap: Record<NonNullable<NumberInputSize>, IconSize> = {\n xs: 'xs',\n sm: 'sm',\n md: 'sm',\n lg: 'md',\n}\n\n/** Maps size to input text and width classes */\nconst inputSizeMap: Record<NonNullable<NumberInputSize>, string> = {\n xs: 'text-body-sm w-ds-06b',\n sm: 'text-body-sm w-ds-sm-plus',\n md: 'text-body-md w-ds-sm-plus',\n lg: 'text-body-md w-ds-md',\n}\n\n/** Maps state to border color classes */\nconst stateColorMap: Record<NonNullable<NumberInputState>, string> = {\n default: '',\n error: 'border-error-7',\n warning: 'border-warning-7',\n success: 'border-success-7',\n}\n\n/**\n * Props for NumberInput — a stepper control with \"−\" and \"+\" buttons flanking a numeric input,\n * clamped between `min` and `max`. The decrement/increment buttons are disabled when bounds are reached.\n *\n * **Controlled only:** Pass `value` + `onValueChange` for controlled usage. Uncontrolled usage is\n * possible but the buttons won't update the displayed value without `onValueChange`.\n *\n * **Step:** The `step` prop controls how much each button press increments/decrements (default 1).\n * Direct text input is also clamped to `[min, max]` on change.\n *\n * **Sizes:** `xs` (28px) | `sm` (32px) | `md` (40px, default) | `lg` (48px)\n *\n * **Validation states:** `state=\"error\"` colors the border red.\n * Use with `<FormField>` to show helper text below the input.\n *\n * @example\n * // Quantity selector with 1–99 range:\n * <NumberInput value={qty} onValueChange={setQty} min={1} max={99} />\n *\n * @example\n * // Rating input (1–10, step 1):\n * <NumberInput value={rating} onValueChange={setRating} min={1} max={10} />\n *\n * @example\n * // Fine-grained opacity control (0–100, step 5):\n * <NumberInput value={opacity} onValueChange={setOpacity} min={0} max={100} step={5} />\n *\n * @example\n * // Disabled number display (read-only-like):\n * <NumberInput value={autoCalcValue} onValueChange={() => {}} disabled />\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface NumberInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type' | 'size'> {\n value?: number\n onValueChange?: (value: number) => void\n min?: number\n max?: number\n step?: number\n /** Size of the number input. Controls height, button sizes, text size. */\n size?: NumberInputSize\n /** Validation state controlling border color. */\n state?: FieldState\n}\n\nconst NumberInput = React.forwardRef<HTMLInputElement, NumberInputProps>(\n (\n {\n value = 0,\n onValueChange,\n min = Number.MIN_SAFE_INTEGER,\n max = Number.MAX_SAFE_INTEGER,\n step = 1,\n disabled = false,\n className,\n size: sizeProp = 'md',\n state: stateProp,\n 'aria-label': ariaLabelProp,\n ...rest\n },\n ref,\n ) => {\n const size = sizeProp ?? 'md'\n const fieldCtx = useFormField()\n // If no explicit aria-label and not inside a FormField (no id to associate with Label),\n // provide a sensible default\n const ariaLabel = ariaLabelProp ?? (rest.id || fieldCtx.helperTextId ? undefined : 'Numeric value')\n\n // Merge FormField context — explicit props always win (shared precedence)\n const state = resolveFieldState(stateProp, fieldCtx.state) ?? 'default'\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const raw = e.target.value.trim()\n if (raw === '' || raw === '-') {\n onValueChange?.(min >= 0 ? min : 0)\n return\n }\n const parsed = Number(raw)\n if (Number.isNaN(parsed)) return\n const clamped = Math.min(Math.max(parsed, min), max)\n onValueChange?.(clamped)\n }\n\n const handleIncrement = (e: React.MouseEvent<HTMLButtonElement>) => {\n e.preventDefault() // Prevent form submission\n const newValue = value + step\n if (newValue <= max) {\n onValueChange?.(newValue)\n }\n }\n\n const handleDecrement = (e: React.MouseEvent<HTMLButtonElement>) => {\n e.preventDefault() // Prevent form submission\n const newValue = value - step\n if (newValue >= min) {\n onValueChange?.(newValue)\n }\n }\n\n const resolvedButtonSize = buttonSizeMap[size]\n const resolvedIconSize = iconSizeMap[size]\n const resolvedInputSize = inputSizeMap[size]\n\n return (\n <div\n className={cn(\n numberInputWrapperVariants({ size }),\n stateColorMap[state],\n className,\n )}\n >\n <button\n type=\"button\"\n onClick={handleDecrement}\n disabled={disabled || value <= min}\n aria-label=\"Decrease value\"\n title=\"Decrease\"\n className={cn(\n 'flex items-center justify-center border-0 rounded-control-inner text-surface-fg-subtle hover:bg-surface-panel-hover hover:text-surface-fg-muted active:scale-90 transition-[color,background-color,transform] duration-fast-01 ease-productive-standard disabled:opacity-action-disabled disabled:pointer-events-none',\n resolvedButtonSize,\n )}\n >\n <Icon icon={IconMinus} size={resolvedIconSize} />\n </button>\n\n <input\n ref={ref}\n type=\"number\"\n value={value}\n onChange={handleInputChange}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n aria-label={ariaLabel}\n aria-invalid={state === 'error' || undefined}\n aria-describedby={rest['aria-describedby'] ?? fieldCtx.helperTextId}\n className={cn(\n 'bg-transparent font-semibold border-0 text-center text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none',\n resolvedInputSize,\n )}\n {...rest}\n // Explicit id wins; otherwise adopt FormField's inputId so <Label htmlFor> resolves.\n id={rest.id ?? fieldCtx.inputId}\n />\n\n <button\n type=\"button\"\n onClick={handleIncrement}\n disabled={disabled || value >= max}\n aria-label=\"Increase value\"\n title=\"Increase\"\n className={cn(\n 'flex items-center justify-center border-0 rounded-control-inner text-surface-fg-subtle hover:bg-surface-panel-hover hover:text-surface-fg-muted active:scale-90 transition-[color,background-color,transform] duration-fast-01 ease-productive-standard disabled:opacity-action-disabled disabled:pointer-events-none',\n resolvedButtonSize,\n )}\n >\n <Icon icon={IconPlus} size={resolvedIconSize} />\n </button>\n </div>\n )\n },\n)\nNumberInput.displayName = 'NumberInput'\n\nexport { NumberInput, numberInputWrapperVariants }\n"],"mappings":";;;;;;;;;;AAeA,IAAM,IAA6B,EACjC,8FACA;CACE,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;CACN,EACF;CACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CACF,GAKM,IAA8D;CAClE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAGM,IAA8D;CAClE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAGM,IAA6D;CACjE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAGM,IAA+D;CACnE,SAAS;CACT,OAAO;CACP,SAAS;CACT,SAAS;AACX,GA8CM,IAAc,EAAM,YAEtB,EACE,WAAQ,GACR,kBACA,SAAM,gBACN,sBACA,UAAO,GACP,cAAW,IACX,cACA,MAAM,IAAW,MACjB,OAAO,GACP,cAAc,GACd,GAAG,KAEL,MACG;CACH,IAAM,IAAO,KAAY,MACnB,IAAW,EAAa,GAGxB,IAAY,MAAkB,EAAK,MAAM,EAAS,eAAe,KAAA,IAAY,kBAG7E,IAAQ,EAAkB,GAAW,EAAS,KAAK,KAAK,WAExD,KAAqB,MAA2C;EACpE,IAAM,IAAM,EAAE,OAAO,MAAM,KAAK;EAChC,IAAI,MAAQ,MAAM,MAAQ,KAAK;GAC7B,IAAgB,KAAO,IAAI,IAAM,CAAC;GAClC;EACF;EACA,IAAM,IAAS,OAAO,CAAG;EACrB,OAAO,MAAM,CAAM,KAEvB,IADgB,KAAK,IAAI,KAAK,IAAI,GAAQ,CAAG,GAAG,CAChC,CAAO;CACzB,GAEM,KAAmB,MAA2C;EAClE,EAAE,eAAe;EACjB,IAAM,IAAW,IAAQ;EACzB,AAAI,KAAY,KACd,IAAgB,CAAQ;CAE5B,GAEM,KAAmB,MAA2C;EAClE,EAAE,eAAe;EACjB,IAAM,IAAW,IAAQ;EACzB,AAAI,KAAY,KACd,IAAgB,CAAQ;CAE5B,GAEM,IAAqB,EAAc,IACnC,IAAmB,EAAY,IAC/B,IAAoB,EAAa;CAEvC,OACE,kBAAC,OAAD;EACE,WAAW,EACT,EAA2B,EAAE,QAAK,CAAC,GACnC,EAAc,IACd,CACF;YALF;GAOE,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,UAAU,KAAY,KAAS;IAC/B,cAAW;IACX,OAAM;IACN,WAAW,EACT,yTACA,CACF;cAEA,kBAAC,GAAD;KAAM,MAAM;KAAW,MAAM;IAAmB,CAAA;GAC1C,CAAA;GAER,kBAAC,SAAD;IACO;IACL,MAAK;IACE;IACP,UAAU;IACL;IACA;IACC;IACI;IACV,cAAY;IACZ,gBAAc,MAAU,WAAW,KAAA;IACnC,oBAAkB,EAAK,uBAAuB,EAAS;IACvD,WAAW,EACT,8QACA,CACF;IACA,GAAI;IAEJ,IAAI,EAAK,MAAM,EAAS;GACzB,CAAA;GAED,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,UAAU,KAAY,KAAS;IAC/B,cAAW;IACX,OAAM;IACN,WAAW,EACT,yTACA,CACF;cAEA,kBAAC,GAAD;KAAM,MAAM;KAAU,MAAM;IAAmB,CAAA;GACzC,CAAA;EACL;;AAET,CACF;AACA,EAAY,cAAc"}
@@ -29,7 +29,7 @@ d.displayName = "PaginationItem";
29
29
  var f = r.forwardRef(({ className: n, isActive: r = !1, asChild: a = !1, ...o }, s) => /* @__PURE__ */ i(a ? e : "button", {
30
30
  ref: s,
31
31
  "aria-current": r ? "page" : void 0,
32
- className: t("inline-flex items-center justify-center h-ds-sm-plus w-ds-sm-plus rounded-control text-body-md font-medium tabular-nums transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-action-disabled active:scale-95", r ? "bg-accent-9 text-accent-fg" : "hover:bg-surface-raised-hover text-surface-fg", n),
32
+ className: t("inline-flex items-center justify-center h-ds-sm-plus w-ds-sm-plus rounded-control text-body-md font-medium tabular-nums transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-action-disabled active:scale-95", r ? "bg-accent-9 text-accent-fg" : "hover:bg-surface-panel-hover text-surface-fg", n),
33
33
  ...o
34
34
  }));
35
35
  f.displayName = "PaginationLink";
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.js","names":[],"sources":["../../src/ui/pagination.tsx"],"sourcesContent":["'use client'\n\nimport { Slot } from '@primitives/react-slot'\nimport { IconChevronLeft, IconChevronRight, IconDots } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { Icon } from './icon'\nimport { cn } from './lib/utils'\n\nconst PaginationRoot = React.forwardRef<\n HTMLElement,\n React.ComponentPropsWithoutRef<'nav'>\n>(({ className, ...props }, ref) => (\n <nav\n ref={ref}\n role=\"navigation\"\n aria-label=\"pagination\"\n className={cn('mx-auto flex w-full justify-center', className)}\n {...props}\n />\n))\nPaginationRoot.displayName = 'PaginationRoot'\n\nconst PaginationContent = React.forwardRef<\n HTMLUListElement,\n React.ComponentPropsWithoutRef<'ul'>\n>(({ className, ...props }, ref) => (\n <ul\n ref={ref}\n className={cn('flex flex-row items-center gap-ds-02', className)}\n {...props}\n />\n))\nPaginationContent.displayName = 'PaginationContent'\n\nconst PaginationItem = React.forwardRef<\n HTMLLIElement,\n React.ComponentPropsWithoutRef<'li'>\n>(({ className, ...props }, ref) => (\n <li ref={ref} className={cn('', className)} {...props} />\n))\nPaginationItem.displayName = 'PaginationItem'\n\n/**\n * Props for PaginationLink — a single page number button in a pagination row.\n * When `isActive` is true, the button gets the brand interactive fill and `aria-current=\"page\"`.\n *\n * @example\n * // Active page button:\n * <PaginationLink isActive onClick={() => goToPage(3)}>3</PaginationLink>\n *\n * @example\n * // Render as a Next.js Link via asChild:\n * <PaginationLink asChild isActive={currentPage === 5}>\n * <Link href=\"/posts?page=5\">5</Link>\n * </PaginationLink>\n */\nexport interface PaginationLinkProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n isActive?: boolean\n asChild?: boolean\n}\n\nconst PaginationLink = React.forwardRef<HTMLButtonElement, PaginationLinkProps>(\n ({ className, isActive = false, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button'\n return (\n <Comp\n ref={ref}\n aria-current={isActive ? 'page' : undefined}\n className={cn(\n 'inline-flex items-center justify-center h-ds-sm-plus w-ds-sm-plus rounded-control text-body-md font-medium tabular-nums transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-action-disabled active:scale-95',\n isActive\n ? 'bg-accent-9 text-accent-fg'\n : 'hover:bg-surface-raised-hover text-surface-fg',\n className,\n )}\n {...props}\n />\n )\n },\n)\nPaginationLink.displayName = 'PaginationLink'\n\nconst PaginationPrevious = React.forwardRef<\n HTMLButtonElement,\n PaginationLinkProps\n>(({ className, ...props }, ref) => (\n <PaginationLink\n ref={ref}\n aria-label=\"Go to previous page\"\n className={cn('w-auto gap-ds-02 pl-ds-03 pr-ds-04', className)}\n {...props}\n >\n <Icon icon={IconChevronLeft} size=\"sm\" />\n <span>Previous</span>\n </PaginationLink>\n))\nPaginationPrevious.displayName = 'PaginationPrevious'\n\nconst PaginationNext = React.forwardRef<\n HTMLButtonElement,\n PaginationLinkProps\n>(({ className, ...props }, ref) => (\n <PaginationLink\n ref={ref}\n aria-label=\"Go to next page\"\n className={cn('w-auto gap-ds-02 pl-ds-04 pr-ds-03', className)}\n {...props}\n >\n <span>Next</span>\n <Icon icon={IconChevronRight} size=\"sm\" />\n </PaginationLink>\n))\nPaginationNext.displayName = 'PaginationNext'\n\nconst PaginationEllipsis = React.forwardRef<\n HTMLSpanElement,\n React.ComponentPropsWithoutRef<'span'>\n>(({ className, ...props }, ref) => (\n <span\n ref={ref}\n aria-hidden=\"true\"\n className={cn(\n 'flex h-ds-sm-plus w-ds-sm-plus items-center justify-center text-surface-fg-muted',\n className,\n )}\n {...props}\n >\n <Icon icon={IconDots} size=\"sm\" />\n <span className=\"sr-only\">More pages</span>\n </span>\n))\nPaginationEllipsis.displayName = 'PaginationEllipsis'\n\n/* ------------------------------------------------------------------ */\n/* generatePagination helper */\n/* ------------------------------------------------------------------ */\n\ntype PageItem = number | 'ellipsis'\n\n/**\n * Pure function that builds an array of page numbers and ellipsis markers.\n * Always shows first and last page, plus `siblingCount` pages around `current`.\n *\n * @example generatePagination(5, 10, 1) → [1, 'ellipsis', 4, 5, 6, 'ellipsis', 10]\n */\nfunction generatePagination(\n current: number,\n total: number,\n siblingCount: number,\n): PageItem[] {\n // When total pages fit without any ellipsis\n const totalSlots = siblingCount * 2 + 5 // first + last + current + 2*siblings + 2 ellipsis slots\n if (total <= totalSlots) {\n return Array.from({ length: total }, (_, i) => i + 1)\n }\n\n const leftSibling = Math.max(current - siblingCount, 1)\n const rightSibling = Math.min(current + siblingCount, total)\n\n const showLeftEllipsis = leftSibling > 2\n const showRightEllipsis = rightSibling < total - 1\n\n if (!showLeftEllipsis && showRightEllipsis) {\n // e.g. [1, 2, 3, 4, 5, '...', 10]\n const leftCount = siblingCount * 2 + 3\n const leftPages = Array.from({ length: leftCount }, (_, i) => i + 1)\n return [...leftPages, 'ellipsis', total]\n }\n\n if (showLeftEllipsis && !showRightEllipsis) {\n // e.g. [1, '...', 6, 7, 8, 9, 10]\n const rightCount = siblingCount * 2 + 3\n const rightPages = Array.from(\n { length: rightCount },\n (_, i) => total - rightCount + 1 + i,\n )\n return [1, 'ellipsis', ...rightPages]\n }\n\n // Both ellipses: [1, '...', 4, 5, 6, '...', 10]\n const middlePages = Array.from(\n { length: rightSibling - leftSibling + 1 },\n (_, i) => leftSibling + i,\n )\n return [1, 'ellipsis', ...middlePages, 'ellipsis', total]\n}\n\n/* ------------------------------------------------------------------ */\n/* PaginationNav — controlled convenience wrapper */\n/* ------------------------------------------------------------------ */\n\n/**\n * Props for PaginationNav — a fully self-contained controlled pagination component that renders\n * Previous / page numbers (with ellipsis) / Next — using `generatePagination` internally.\n *\n * **1-indexed:** `currentPage` starts at 1 (not 0). `onPageChange` also receives 1-indexed values.\n *\n * **`siblingCount`:** Number of page buttons shown on each side of the current page (default 1).\n * A wider `siblingCount` shows more page buttons before switching to ellipsis.\n *\n * @example\n * // Basic controlled pagination:\n * <PaginationNav\n * totalPages={24}\n * currentPage={currentPage}\n * onPageChange={setCurrentPage}\n * />\n *\n * @example\n * // Wider sibling range for a results grid (shows more page context):\n * <PaginationNav\n * totalPages={100}\n * currentPage={currentPage}\n * onPageChange={setCurrentPage}\n * siblingCount={2}\n * />\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface PaginationNavProps\n extends React.HTMLAttributes<HTMLElement> {\n /** Total number of pages */\n totalPages: number\n /** Current active page (1-indexed) */\n currentPage: number\n /** Called when the user requests a different page */\n onPageChange: (page: number) => void\n /** Number of sibling page buttons shown on each side of the current page (default: 1) */\n siblingCount?: number\n}\n\nconst PaginationNav = React.forwardRef<HTMLElement, PaginationNavProps>(\n (\n {\n totalPages,\n currentPage,\n onPageChange,\n siblingCount = 1,\n className,\n ...props\n },\n ref,\n ) => {\n const pages = generatePagination(currentPage, totalPages, siblingCount)\n\n return (\n <PaginationRoot ref={ref} className={className} {...props}>\n <PaginationContent>\n <PaginationItem>\n <PaginationPrevious\n onClick={() => onPageChange(Math.max(1, currentPage - 1))}\n disabled={currentPage <= 1}\n />\n </PaginationItem>\n\n {pages.map((page, i) =>\n page === 'ellipsis' ? (\n <PaginationItem key={`e${i}`}>\n <PaginationEllipsis />\n </PaginationItem>\n ) : (\n <PaginationItem key={page}>\n <PaginationLink\n isActive={page === currentPage}\n onClick={() => onPageChange(page)}\n >\n {page}\n </PaginationLink>\n </PaginationItem>\n ),\n )}\n\n <PaginationItem>\n <PaginationNext\n onClick={() =>\n onPageChange(Math.min(totalPages, currentPage + 1))\n }\n disabled={currentPage >= totalPages}\n />\n </PaginationItem>\n </PaginationContent>\n </PaginationRoot>\n )\n },\n)\nPaginationNav.displayName = 'PaginationNav'\n\nexport {\n generatePagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n PaginationLink,\n PaginationNav,\n PaginationNext,\n PaginationPrevious,\n PaginationRoot,\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pagination.js","names":[],"sources":["../../src/ui/pagination.tsx"],"sourcesContent":["'use client'\n\nimport { Slot } from '@primitives/react-slot'\nimport { IconChevronLeft, IconChevronRight, IconDots } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { Icon } from './icon'\nimport { cn } from './lib/utils'\n\nconst PaginationRoot = React.forwardRef<\n HTMLElement,\n React.ComponentPropsWithoutRef<'nav'>\n>(({ className, ...props }, ref) => (\n <nav\n ref={ref}\n role=\"navigation\"\n aria-label=\"pagination\"\n className={cn('mx-auto flex w-full justify-center', className)}\n {...props}\n />\n))\nPaginationRoot.displayName = 'PaginationRoot'\n\nconst PaginationContent = React.forwardRef<\n HTMLUListElement,\n React.ComponentPropsWithoutRef<'ul'>\n>(({ className, ...props }, ref) => (\n <ul\n ref={ref}\n className={cn('flex flex-row items-center gap-ds-02', className)}\n {...props}\n />\n))\nPaginationContent.displayName = 'PaginationContent'\n\nconst PaginationItem = React.forwardRef<\n HTMLLIElement,\n React.ComponentPropsWithoutRef<'li'>\n>(({ className, ...props }, ref) => (\n <li ref={ref} className={cn('', className)} {...props} />\n))\nPaginationItem.displayName = 'PaginationItem'\n\n/**\n * Props for PaginationLink — a single page number button in a pagination row.\n * When `isActive` is true, the button gets the brand interactive fill and `aria-current=\"page\"`.\n *\n * @example\n * // Active page button:\n * <PaginationLink isActive onClick={() => goToPage(3)}>3</PaginationLink>\n *\n * @example\n * // Render as a Next.js Link via asChild:\n * <PaginationLink asChild isActive={currentPage === 5}>\n * <Link href=\"/posts?page=5\">5</Link>\n * </PaginationLink>\n */\nexport interface PaginationLinkProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n isActive?: boolean\n asChild?: boolean\n}\n\nconst PaginationLink = React.forwardRef<HTMLButtonElement, PaginationLinkProps>(\n ({ className, isActive = false, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button'\n return (\n <Comp\n ref={ref}\n aria-current={isActive ? 'page' : undefined}\n className={cn(\n 'inline-flex items-center justify-center h-ds-sm-plus w-ds-sm-plus rounded-control text-body-md font-medium tabular-nums transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-action-disabled active:scale-95',\n isActive\n ? 'bg-accent-9 text-accent-fg'\n : 'hover:bg-surface-panel-hover text-surface-fg',\n className,\n )}\n {...props}\n />\n )\n },\n)\nPaginationLink.displayName = 'PaginationLink'\n\nconst PaginationPrevious = React.forwardRef<\n HTMLButtonElement,\n PaginationLinkProps\n>(({ className, ...props }, ref) => (\n <PaginationLink\n ref={ref}\n aria-label=\"Go to previous page\"\n className={cn('w-auto gap-ds-02 pl-ds-03 pr-ds-04', className)}\n {...props}\n >\n <Icon icon={IconChevronLeft} size=\"sm\" />\n <span>Previous</span>\n </PaginationLink>\n))\nPaginationPrevious.displayName = 'PaginationPrevious'\n\nconst PaginationNext = React.forwardRef<\n HTMLButtonElement,\n PaginationLinkProps\n>(({ className, ...props }, ref) => (\n <PaginationLink\n ref={ref}\n aria-label=\"Go to next page\"\n className={cn('w-auto gap-ds-02 pl-ds-04 pr-ds-03', className)}\n {...props}\n >\n <span>Next</span>\n <Icon icon={IconChevronRight} size=\"sm\" />\n </PaginationLink>\n))\nPaginationNext.displayName = 'PaginationNext'\n\nconst PaginationEllipsis = React.forwardRef<\n HTMLSpanElement,\n React.ComponentPropsWithoutRef<'span'>\n>(({ className, ...props }, ref) => (\n <span\n ref={ref}\n aria-hidden=\"true\"\n className={cn(\n 'flex h-ds-sm-plus w-ds-sm-plus items-center justify-center text-surface-fg-muted',\n className,\n )}\n {...props}\n >\n <Icon icon={IconDots} size=\"sm\" />\n <span className=\"sr-only\">More pages</span>\n </span>\n))\nPaginationEllipsis.displayName = 'PaginationEllipsis'\n\n/* ------------------------------------------------------------------ */\n/* generatePagination helper */\n/* ------------------------------------------------------------------ */\n\ntype PageItem = number | 'ellipsis'\n\n/**\n * Pure function that builds an array of page numbers and ellipsis markers.\n * Always shows first and last page, plus `siblingCount` pages around `current`.\n *\n * @example generatePagination(5, 10, 1) → [1, 'ellipsis', 4, 5, 6, 'ellipsis', 10]\n */\nfunction generatePagination(\n current: number,\n total: number,\n siblingCount: number,\n): PageItem[] {\n // When total pages fit without any ellipsis\n const totalSlots = siblingCount * 2 + 5 // first + last + current + 2*siblings + 2 ellipsis slots\n if (total <= totalSlots) {\n return Array.from({ length: total }, (_, i) => i + 1)\n }\n\n const leftSibling = Math.max(current - siblingCount, 1)\n const rightSibling = Math.min(current + siblingCount, total)\n\n const showLeftEllipsis = leftSibling > 2\n const showRightEllipsis = rightSibling < total - 1\n\n if (!showLeftEllipsis && showRightEllipsis) {\n // e.g. [1, 2, 3, 4, 5, '...', 10]\n const leftCount = siblingCount * 2 + 3\n const leftPages = Array.from({ length: leftCount }, (_, i) => i + 1)\n return [...leftPages, 'ellipsis', total]\n }\n\n if (showLeftEllipsis && !showRightEllipsis) {\n // e.g. [1, '...', 6, 7, 8, 9, 10]\n const rightCount = siblingCount * 2 + 3\n const rightPages = Array.from(\n { length: rightCount },\n (_, i) => total - rightCount + 1 + i,\n )\n return [1, 'ellipsis', ...rightPages]\n }\n\n // Both ellipses: [1, '...', 4, 5, 6, '...', 10]\n const middlePages = Array.from(\n { length: rightSibling - leftSibling + 1 },\n (_, i) => leftSibling + i,\n )\n return [1, 'ellipsis', ...middlePages, 'ellipsis', total]\n}\n\n/* ------------------------------------------------------------------ */\n/* PaginationNav — controlled convenience wrapper */\n/* ------------------------------------------------------------------ */\n\n/**\n * Props for PaginationNav — a fully self-contained controlled pagination component that renders\n * Previous / page numbers (with ellipsis) / Next — using `generatePagination` internally.\n *\n * **1-indexed:** `currentPage` starts at 1 (not 0). `onPageChange` also receives 1-indexed values.\n *\n * **`siblingCount`:** Number of page buttons shown on each side of the current page (default 1).\n * A wider `siblingCount` shows more page buttons before switching to ellipsis.\n *\n * @example\n * // Basic controlled pagination:\n * <PaginationNav\n * totalPages={24}\n * currentPage={currentPage}\n * onPageChange={setCurrentPage}\n * />\n *\n * @example\n * // Wider sibling range for a results grid (shows more page context):\n * <PaginationNav\n * totalPages={100}\n * currentPage={currentPage}\n * onPageChange={setCurrentPage}\n * siblingCount={2}\n * />\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface PaginationNavProps\n extends React.HTMLAttributes<HTMLElement> {\n /** Total number of pages */\n totalPages: number\n /** Current active page (1-indexed) */\n currentPage: number\n /** Called when the user requests a different page */\n onPageChange: (page: number) => void\n /** Number of sibling page buttons shown on each side of the current page (default: 1) */\n siblingCount?: number\n}\n\nconst PaginationNav = React.forwardRef<HTMLElement, PaginationNavProps>(\n (\n {\n totalPages,\n currentPage,\n onPageChange,\n siblingCount = 1,\n className,\n ...props\n },\n ref,\n ) => {\n const pages = generatePagination(currentPage, totalPages, siblingCount)\n\n return (\n <PaginationRoot ref={ref} className={className} {...props}>\n <PaginationContent>\n <PaginationItem>\n <PaginationPrevious\n onClick={() => onPageChange(Math.max(1, currentPage - 1))}\n disabled={currentPage <= 1}\n />\n </PaginationItem>\n\n {pages.map((page, i) =>\n page === 'ellipsis' ? (\n <PaginationItem key={`e${i}`}>\n <PaginationEllipsis />\n </PaginationItem>\n ) : (\n <PaginationItem key={page}>\n <PaginationLink\n isActive={page === currentPage}\n onClick={() => onPageChange(page)}\n >\n {page}\n </PaginationLink>\n </PaginationItem>\n ),\n )}\n\n <PaginationItem>\n <PaginationNext\n onClick={() =>\n onPageChange(Math.min(totalPages, currentPage + 1))\n }\n disabled={currentPage >= totalPages}\n />\n </PaginationItem>\n </PaginationContent>\n </PaginationRoot>\n )\n },\n)\nPaginationNav.displayName = 'PaginationNav'\n\nexport {\n generatePagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n PaginationLink,\n PaginationNav,\n PaginationNext,\n PaginationPrevious,\n PaginationRoot,\n}\n"],"mappings":"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"}
@@ -61,7 +61,7 @@ var u = {
61
61
  cy: D,
62
62
  r: C,
63
63
  fill: "none",
64
- stroke: "var(--color-surface-raised-hover)",
64
+ stroke: "var(--color-surface-panel-hover)",
65
65
  strokeWidth: S.strokeWidth
66
66
  }),
67
67
  /* @__PURE__ */ r(o.circle, {
@@ -110,7 +110,7 @@ var p = n.forwardRef(({ rings: a, size: s = "md", className: l, ...f }, p) => {
110
110
  cy: g,
111
111
  r: s,
112
112
  fill: "none",
113
- stroke: "var(--color-surface-raised-hover)",
113
+ stroke: "var(--color-surface-panel-hover)",
114
114
  strokeWidth: h.strokeWidth
115
115
  }), /* @__PURE__ */ r(o.circle, {
116
116
  cx: g,
@@ -1 +1 @@
1
- {"version":3,"file":"progress-ring.js","names":[],"sources":["../../src/ui/progress-ring.tsx"],"sourcesContent":["'use client'\n\nimport { animate, motion, useMotionValue, useReducedMotion,useTransform } from 'framer-motion'\nimport * as React from 'react'\n\nimport { springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\nconst colorMap: Record<string, string> = {\n default: 'var(--color-accent-9)',\n success: 'var(--color-success-9)',\n warning: 'var(--color-warning-9)',\n error: 'var(--color-error-9)',\n info: 'var(--color-info-9)',\n}\n\nconst sizeConfig = {\n sm: { size: 32, strokeWidth: 3, fontSize: 'text-body-xs' },\n md: { size: 48, strokeWidth: 3.5, fontSize: 'text-body-sm' },\n lg: { size: 64, strokeWidth: 4, fontSize: 'text-body-md' },\n} as const\n\n/**\n * A circular progress indicator with optional label and animated fill.\n *\n * @example\n * <ProgressRing value={75} />\n * <ProgressRing value={3} max={12} size=\"lg\" color=\"warning\" showValue />\n */\nexport interface ProgressRingProps extends Omit<React.SVGAttributes<SVGSVGElement>, 'color'> {\n /** Current progress value */\n value: number\n /** Maximum value @default 100 */\n max?: number\n /** @default 'md' */\n size?: 'sm' | 'md' | 'lg'\n /** @default 'default' */\n color?: 'default' | 'success' | 'warning' | 'error' | 'info'\n /** Show percentage text in center */\n showValue?: boolean\n /** Accessible label */\n label?: string\n}\n\nconst ProgressRing = React.forwardRef<SVGSVGElement, ProgressRingProps>(\n ({ value, max = 100, size = 'md', color = 'default', showValue = false, label, className, ...props }, ref) => {\n const prefersReducedMotion = useReducedMotion()\n const config = sizeConfig[size]\n const radius = (config.size - config.strokeWidth) / 2\n const circumference = 2 * Math.PI * radius\n const progress = Math.min(Math.max(value / max, 0), 1)\n const offset = circumference * (1 - progress)\n const center = config.size / 2\n const percentage = Math.round(progress * 100)\n\n // Animated counter — drives from 0 → target percentage in sync with the ring fill\n const motionVal = useMotionValue(0)\n const displayValue = useTransform(motionVal, (v) => `${Math.round(v)}%`)\n\n React.useEffect(() => {\n const controls = animate(motionVal, progress * 100, prefersReducedMotion\n ? { type: 'tween', duration: 0 }\n /* Intentionally slower than springs.gentle (200/25/0.8) for smooth ring fill */\n : { stiffness: 100, damping: 30, type: 'spring' },\n )\n return () => controls.stop()\n }, [progress, motionVal, prefersReducedMotion])\n\n return (\n <svg\n ref={ref}\n width={config.size}\n height={config.size}\n viewBox={`0 0 ${config.size} ${config.size}`}\n role=\"progressbar\"\n aria-valuenow={value}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-label={label ?? `${percentage}% progress`}\n className={cn('shrink-0', className)}\n {...props}\n >\n {/* Track */}\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke=\"var(--color-surface-raised-hover)\"\n strokeWidth={config.strokeWidth}\n />\n {/* Value */}\n <motion.circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke={colorMap[color]}\n strokeWidth={config.strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n initial={{ strokeDashoffset: circumference }}\n animate={{ strokeDashoffset: offset }}\n transition={prefersReducedMotion ? { duration: 0 } : springs.smooth}\n transform={`rotate(-90 ${center} ${center})`}\n />\n {showValue && (\n <motion.text\n x={center}\n y={center}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className={cn(config.fontSize, 'fill-surface-fg font-sans font-semibold')}\n >\n {displayValue}\n </motion.text>\n )}\n </svg>\n )\n },\n)\nProgressRing.displayName = 'ProgressRing'\n\n/**\n * Multi-ring progress display (Activity Ring style).\n *\n * @example\n * <MultiProgressRing rings={[\n * { value: 80, color: 'error', label: 'Move' },\n * { value: 60, color: 'success', label: 'Exercise' },\n * ]} size=\"lg\" />\n */\nexport interface MultiProgressRingProps extends Omit<React.SVGAttributes<SVGSVGElement>, 'color'> {\n rings: Array<{\n value: number\n max?: number\n color?: 'default' | 'success' | 'warning' | 'error' | 'info'\n label?: string\n }>\n /** @default 'md' */\n size?: 'sm' | 'md' | 'lg'\n}\n\nconst MultiProgressRing = React.forwardRef<SVGSVGElement, MultiProgressRingProps>(\n ({ rings, size = 'md', className, ...props }, ref) => {\n const prefersReducedMotion = useReducedMotion()\n const config = sizeConfig[size]\n const center = config.size / 2\n const gap = config.strokeWidth + 2\n\n return (\n <svg\n ref={ref}\n width={config.size}\n height={config.size}\n viewBox={`0 0 ${config.size} ${config.size}`}\n role=\"group\"\n aria-label=\"Progress rings\"\n className={cn('shrink-0', className)}\n {...props}\n >\n {rings.map((ring, i) => {\n const radius = (config.size - config.strokeWidth) / 2 - i * gap\n if (radius <= 0) return null\n const circumference = 2 * Math.PI * radius\n const progress = Math.min(Math.max((ring.value) / (ring.max ?? 100), 0), 1)\n const offset = circumference * (1 - progress)\n\n return (\n <React.Fragment key={i}>\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke=\"var(--color-surface-raised-hover)\"\n strokeWidth={config.strokeWidth}\n />\n <motion.circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke={colorMap[ring.color ?? 'default']}\n strokeWidth={config.strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n initial={{ strokeDashoffset: circumference }}\n animate={{ strokeDashoffset: offset }}\n transition={prefersReducedMotion ? { duration: 0 } : springs.smooth}\n transform={`rotate(-90 ${center} ${center})`}\n />\n </React.Fragment>\n )\n })}\n </svg>\n )\n },\n)\nMultiProgressRing.displayName = 'MultiProgressRing'\n\nexport { MultiProgressRing,ProgressRing }\n"],"mappings":"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"}
1
+ {"version":3,"file":"progress-ring.js","names":[],"sources":["../../src/ui/progress-ring.tsx"],"sourcesContent":["'use client'\n\nimport { animate, motion, useMotionValue, useReducedMotion,useTransform } from 'framer-motion'\nimport * as React from 'react'\n\nimport { springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\nconst colorMap: Record<string, string> = {\n default: 'var(--color-accent-9)',\n success: 'var(--color-success-9)',\n warning: 'var(--color-warning-9)',\n error: 'var(--color-error-9)',\n info: 'var(--color-info-9)',\n}\n\nconst sizeConfig = {\n sm: { size: 32, strokeWidth: 3, fontSize: 'text-body-xs' },\n md: { size: 48, strokeWidth: 3.5, fontSize: 'text-body-sm' },\n lg: { size: 64, strokeWidth: 4, fontSize: 'text-body-md' },\n} as const\n\n/**\n * A circular progress indicator with optional label and animated fill.\n *\n * @example\n * <ProgressRing value={75} />\n * <ProgressRing value={3} max={12} size=\"lg\" color=\"warning\" showValue />\n */\nexport interface ProgressRingProps extends Omit<React.SVGAttributes<SVGSVGElement>, 'color'> {\n /** Current progress value */\n value: number\n /** Maximum value @default 100 */\n max?: number\n /** @default 'md' */\n size?: 'sm' | 'md' | 'lg'\n /** @default 'default' */\n color?: 'default' | 'success' | 'warning' | 'error' | 'info'\n /** Show percentage text in center */\n showValue?: boolean\n /** Accessible label */\n label?: string\n}\n\nconst ProgressRing = React.forwardRef<SVGSVGElement, ProgressRingProps>(\n ({ value, max = 100, size = 'md', color = 'default', showValue = false, label, className, ...props }, ref) => {\n const prefersReducedMotion = useReducedMotion()\n const config = sizeConfig[size]\n const radius = (config.size - config.strokeWidth) / 2\n const circumference = 2 * Math.PI * radius\n const progress = Math.min(Math.max(value / max, 0), 1)\n const offset = circumference * (1 - progress)\n const center = config.size / 2\n const percentage = Math.round(progress * 100)\n\n // Animated counter — drives from 0 → target percentage in sync with the ring fill\n const motionVal = useMotionValue(0)\n const displayValue = useTransform(motionVal, (v) => `${Math.round(v)}%`)\n\n React.useEffect(() => {\n const controls = animate(motionVal, progress * 100, prefersReducedMotion\n ? { type: 'tween', duration: 0 }\n /* Intentionally slower than springs.gentle (200/25/0.8) for smooth ring fill */\n : { stiffness: 100, damping: 30, type: 'spring' },\n )\n return () => controls.stop()\n }, [progress, motionVal, prefersReducedMotion])\n\n return (\n <svg\n ref={ref}\n width={config.size}\n height={config.size}\n viewBox={`0 0 ${config.size} ${config.size}`}\n role=\"progressbar\"\n aria-valuenow={value}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-label={label ?? `${percentage}% progress`}\n className={cn('shrink-0', className)}\n {...props}\n >\n {/* Track */}\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke=\"var(--color-surface-panel-hover)\"\n strokeWidth={config.strokeWidth}\n />\n {/* Value */}\n <motion.circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke={colorMap[color]}\n strokeWidth={config.strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n initial={{ strokeDashoffset: circumference }}\n animate={{ strokeDashoffset: offset }}\n transition={prefersReducedMotion ? { duration: 0 } : springs.smooth}\n transform={`rotate(-90 ${center} ${center})`}\n />\n {showValue && (\n <motion.text\n x={center}\n y={center}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className={cn(config.fontSize, 'fill-surface-fg font-sans font-semibold')}\n >\n {displayValue}\n </motion.text>\n )}\n </svg>\n )\n },\n)\nProgressRing.displayName = 'ProgressRing'\n\n/**\n * Multi-ring progress display (Activity Ring style).\n *\n * @example\n * <MultiProgressRing rings={[\n * { value: 80, color: 'error', label: 'Move' },\n * { value: 60, color: 'success', label: 'Exercise' },\n * ]} size=\"lg\" />\n */\nexport interface MultiProgressRingProps extends Omit<React.SVGAttributes<SVGSVGElement>, 'color'> {\n rings: Array<{\n value: number\n max?: number\n color?: 'default' | 'success' | 'warning' | 'error' | 'info'\n label?: string\n }>\n /** @default 'md' */\n size?: 'sm' | 'md' | 'lg'\n}\n\nconst MultiProgressRing = React.forwardRef<SVGSVGElement, MultiProgressRingProps>(\n ({ rings, size = 'md', className, ...props }, ref) => {\n const prefersReducedMotion = useReducedMotion()\n const config = sizeConfig[size]\n const center = config.size / 2\n const gap = config.strokeWidth + 2\n\n return (\n <svg\n ref={ref}\n width={config.size}\n height={config.size}\n viewBox={`0 0 ${config.size} ${config.size}`}\n role=\"group\"\n aria-label=\"Progress rings\"\n className={cn('shrink-0', className)}\n {...props}\n >\n {rings.map((ring, i) => {\n const radius = (config.size - config.strokeWidth) / 2 - i * gap\n if (radius <= 0) return null\n const circumference = 2 * Math.PI * radius\n const progress = Math.min(Math.max((ring.value) / (ring.max ?? 100), 0), 1)\n const offset = circumference * (1 - progress)\n\n return (\n <React.Fragment key={i}>\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke=\"var(--color-surface-panel-hover)\"\n strokeWidth={config.strokeWidth}\n />\n <motion.circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n stroke={colorMap[ring.color ?? 'default']}\n strokeWidth={config.strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n initial={{ strokeDashoffset: circumference }}\n animate={{ strokeDashoffset: offset }}\n transition={prefersReducedMotion ? { duration: 0 } : springs.smooth}\n transform={`rotate(-90 ${center} ${center})`}\n />\n </React.Fragment>\n )\n })}\n </svg>\n )\n },\n)\nMultiProgressRing.displayName = 'MultiProgressRing'\n\nexport { MultiProgressRing,ProgressRing }\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/ui/progress.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/ui/progress.tsx"],"names":[],"mappings":"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"}
@@ -1,13 +1,13 @@
1
1
  "use client";
2
2
  import { springs as e } from "./lib/motion.js";
3
- import { cva as t } from "../_chunks/vendor-utils.js";
4
- import { cn as n } from "./lib/utils.js";
5
- import { Root as r } from "../_chunks/primitives/react-progress.js";
6
- import * as i from "react";
7
- import { jsx as a, jsxs as o } from "react/jsx-runtime";
8
- import { motion as s } from "framer-motion";
3
+ import { cn as t } from "./lib/utils.js";
4
+ import { Root as n } from "../_chunks/primitives/react-progress.js";
5
+ import * as r from "react";
6
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
7
+ import { motion as o } from "framer-motion";
8
+ import { cva as s } from "class-variance-authority";
9
9
  //#region src/ui/progress.tsx
10
- var c = t("relative w-full overflow-hidden rounded-pill bg-surface-raised", {
10
+ var c = s("relative w-full overflow-hidden rounded-pill bg-surface-panel", {
11
11
  variants: { size: {
12
12
  sm: "h-1",
13
13
  md: "h-2",
@@ -19,132 +19,136 @@ var c = t("relative w-full overflow-hidden rounded-pill bg-surface-raised", {
19
19
  success: "bg-success-9",
20
20
  warning: "bg-warning-9",
21
21
  error: "bg-error-9"
22
- }, u = t("h-full transition-[width] duration-moderate-02 ease-expressive-standard", {
22
+ }, u = s("h-full transition-[width] duration-moderate-02 ease-expressive-standard", {
23
23
  variants: { color: l },
24
24
  defaultVariants: { color: "accent" }
25
25
  });
26
26
  function d(e) {
27
27
  return e == null ? "accent" : e > 100 ? "error" : e >= 85 ? "success" : e >= 60 ? "warning" : "accent";
28
28
  }
29
- var f = (e, t) => Math.max(0, Math.min(100, e / t * 100)), p = i.createContext(null);
29
+ var f = (e, t) => Math.max(0, Math.min(100, e / t * 100)), p = r.createContext(null);
30
30
  function m(e) {
31
- let t = i.useContext(p);
31
+ let t = r.useContext(p);
32
32
  if (!t) throw Error(`<Progress.${e}> must be rendered inside <Progress.Root>.`);
33
33
  return t;
34
34
  }
35
- var h = i.forwardRef(({ value: e = null, max: t = 100, size: r = "md", className: o, children: s, ...c }, l) => {
36
- let u = i.useMemo(() => ({
35
+ var h = r.forwardRef(({ value: e = null, max: n = 100, size: a = "md", className: o, children: s, ...c }, l) => {
36
+ let u = r.useMemo(() => ({
37
37
  value: e,
38
- max: t,
39
- size: r,
38
+ max: n,
39
+ size: a,
40
40
  indeterminate: e == null
41
41
  }), [
42
42
  e,
43
- t,
44
- r
43
+ n,
44
+ a
45
45
  ]);
46
- return /* @__PURE__ */ a(p.Provider, {
46
+ return /* @__PURE__ */ i(p.Provider, {
47
47
  value: u,
48
- children: /* @__PURE__ */ a("div", {
48
+ children: /* @__PURE__ */ i("div", {
49
49
  ref: l,
50
- className: n("flex w-full items-center gap-ds-03", o),
50
+ className: t("flex w-full items-center gap-ds-03", o),
51
51
  ...c,
52
52
  children: s
53
53
  })
54
54
  });
55
55
  });
56
56
  h.displayName = "Progress.Root";
57
- var g = i.forwardRef(({ className: e, children: t, ...i }, o) => {
57
+ var g = r.forwardRef(({ className: e, children: r, ...a }, o) => {
58
58
  let { value: s, max: l, size: u, indeterminate: d } = m("Track");
59
- return /* @__PURE__ */ a(r, {
59
+ return /* @__PURE__ */ i(n, {
60
60
  ref: o,
61
61
  value: d ? null : s,
62
62
  max: l,
63
- className: n(c({ size: u }), "flex-1", e),
64
- ...i,
65
- children: t
63
+ className: t(c({ size: u }), "flex-1", e),
64
+ ...a,
65
+ children: r
66
66
  });
67
67
  });
68
68
  g.displayName = "Progress.Track";
69
- var _ = i.forwardRef(({ color: t, autoColor: r, className: i, ...o }, c) => {
70
- let { value: l, max: p, indeterminate: h } = m("Indicator"), g = t ?? (r === !1 ? "accent" : d(l));
71
- return h ? /* @__PURE__ */ a("div", {
69
+ var _ = r.forwardRef(({ color: n, autoColor: r, className: a, ...s }, c) => {
70
+ let { value: l, max: p, indeterminate: h } = m("Indicator"), g = n ?? (r === !1 ? "accent" : d(l));
71
+ return h ? /* @__PURE__ */ i("div", {
72
72
  ref: c,
73
- className: n(u({ color: g }), "w-2/5 animate-progress-indeterminate motion-reduce:animate-none", i),
74
- ...o
75
- }) : /* @__PURE__ */ a(s.div, {
73
+ className: t(u({ color: g }), "w-2/5 animate-progress-indeterminate motion-reduce:animate-none", a),
74
+ ...s
75
+ }) : /* @__PURE__ */ i(o.div, {
76
76
  ref: c,
77
- className: n(u({ color: g }), "transition-colors", i),
77
+ className: t(u({ color: g }), "transition-colors", a),
78
78
  initial: !1,
79
79
  animate: { width: `${f(l ?? 0, p)}%` },
80
80
  transition: e.smooth,
81
- ...o
81
+ ...s
82
82
  });
83
83
  });
84
84
  _.displayName = "Progress.Indicator";
85
- var v = i.forwardRef(({ value: e, color: t = "accent", className: r, style: i, ...o }, s) => {
85
+ var v = r.forwardRef(({ value: e, color: n = "accent", className: r, style: a, ...o }, s) => {
86
86
  let { max: c } = m("Segment");
87
- return /* @__PURE__ */ a("div", {
87
+ return /* @__PURE__ */ i("div", {
88
88
  ref: s,
89
89
  "aria-hidden": "true",
90
- className: n("h-full first:rounded-l-pill last:rounded-r-pill", l[t], r),
90
+ className: t("h-full first:rounded-l-pill last:rounded-r-pill", l[n], r),
91
91
  style: {
92
92
  width: `${f(e, c)}%`,
93
- ...i
93
+ ...a
94
94
  },
95
95
  ...o
96
96
  });
97
97
  });
98
98
  v.displayName = "Progress.Segment";
99
- var y = i.forwardRef(({ className: e, ...t }, r) => (m("Label"), /* @__PURE__ */ a("span", {
99
+ var y = r.forwardRef(({ className: e, ...n }, r) => (m("Label"), /* @__PURE__ */ i("span", {
100
100
  ref: r,
101
- className: n("shrink-0 text-body-sm font-medium text-surface-fg", e),
102
- ...t
101
+ className: t("shrink-0 text-body-sm font-medium text-surface-fg", e),
102
+ ...n
103
103
  })));
104
104
  y.displayName = "Progress.Label";
105
- var b = i.forwardRef(({ className: e, format: t, children: r, ...i }, o) => {
105
+ var b = r.forwardRef(({ className: e, format: n, children: r, ...a }, o) => {
106
106
  let { value: s, max: c, indeterminate: l } = m("Value"), u = l ? 0 : f(s ?? 0, c);
107
- return /* @__PURE__ */ a("span", {
107
+ return /* @__PURE__ */ i("span", {
108
108
  ref: o,
109
- className: n("shrink-0 text-caption text-surface-fg-muted tabular-nums", e),
110
- ...i,
111
- children: r ?? (l ? "" : t ? t(u, s, c) : `${Math.round(u)}%`)
109
+ className: t("shrink-0 text-caption text-surface-fg-muted tabular-nums", e),
110
+ ...a,
111
+ children: r ?? (l ? "" : n ? n(u, s, c) : `${Math.round(u)}%`)
112
112
  });
113
113
  });
114
114
  b.displayName = "Progress.Value";
115
- var x = i.forwardRef(({ value: e = null, max: t = 100, size: r, color: s, autoColor: c, label: l, showValue: u, segments: d, trackClassName: f, indicatorClassName: p, className: m, "aria-label": x, "aria-labelledby": S, ...C }, w) => {
116
- let T = i.useId(), E = l != null;
117
- return /* @__PURE__ */ o(h, {
118
- ref: w,
115
+ var x = !1;
116
+ function S() {
117
+ x || typeof process > "u" || process.env.NODE_ENV === "production" || (x = !0, console.warn("[shilp-sutra] <Progress> has no accessible name, so it announces as just \"progressbar\" with a percentage. Pass `label` (renders visible text and wires aria-labelledby) or `aria-label` if the bar must stay unlabelled visually. Example: <Progress value={72} label=\"Storage used\" /> or <Progress value={72} aria-label=\"Upload progress\" />."));
118
+ }
119
+ var C = r.forwardRef(({ value: e = null, max: n = 100, size: o, color: s, autoColor: c, label: l, showValue: u, segments: d, trackClassName: f, indicatorClassName: p, className: m, "aria-label": x, "aria-labelledby": C, ...w }, T) => {
120
+ let E = r.useId(), D = l != null;
121
+ return !D && !x && !C && S(), /* @__PURE__ */ a(h, {
122
+ ref: T,
119
123
  value: e,
120
- max: t,
121
- size: r ?? "md",
124
+ max: n,
125
+ size: o ?? "md",
122
126
  className: m,
123
- ...C,
127
+ ...w,
124
128
  children: [
125
- E && /* @__PURE__ */ a(y, {
126
- id: T,
129
+ D && /* @__PURE__ */ i(y, {
130
+ id: E,
127
131
  children: l
128
132
  }),
129
- /* @__PURE__ */ a(g, {
133
+ /* @__PURE__ */ i(g, {
130
134
  "aria-label": x,
131
- "aria-labelledby": S ?? (E ? T : void 0),
132
- className: n(d && "flex", f),
133
- children: d ? d.map((e, t) => /* @__PURE__ */ a(v, {
135
+ "aria-labelledby": C ?? (D ? E : void 0),
136
+ className: t(d && "flex", f),
137
+ children: d ? d.map((e, t) => /* @__PURE__ */ i(v, {
134
138
  value: e.value,
135
139
  color: e.color
136
- }, t)) : /* @__PURE__ */ a(_, {
140
+ }, t)) : /* @__PURE__ */ i(_, {
137
141
  color: s,
138
142
  autoColor: c,
139
143
  className: p
140
144
  })
141
145
  }),
142
- u && e != null && /* @__PURE__ */ a(b, {})
146
+ u && e != null && /* @__PURE__ */ i(b, {})
143
147
  ]
144
148
  });
145
149
  });
146
- x.displayName = "Progress";
147
- var S = Object.assign(x, {
150
+ C.displayName = "Progress";
151
+ var w = Object.assign(C, {
148
152
  Root: h,
149
153
  Track: g,
150
154
  Indicator: _,
@@ -153,4 +157,4 @@ var S = Object.assign(x, {
153
157
  Value: b
154
158
  });
155
159
  //#endregion
156
- export { S as Progress, _ as ProgressIndicator, y as ProgressLabel, h as ProgressRoot, v as ProgressSegment, g as ProgressTrack, b as ProgressValue, u as progressIndicatorVariants, c as progressTrackVariants };
160
+ export { w as Progress, _ as ProgressIndicator, y as ProgressLabel, h as ProgressRoot, v as ProgressSegment, g as ProgressTrack, b as ProgressValue, u as progressIndicatorVariants, c as progressTrackVariants };
@@ -1 +1 @@
1
- {"version":3,"file":"progress.js","names":[],"sources":["../../src/ui/progress.tsx"],"sourcesContent":["'use client'\n\nimport * as ProgressPrimitive from '@primitives/react-progress'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\n/* ---------------------------------------------------------------------------\n * Progress — a linear progress bar.\n *\n * Two ways to use it:\n * 1. Smart all-in-one `<Progress value={70} />` — covers the common cases\n * (value, size, color, label, %-value, auto-color, indeterminate, segments).\n * 2. Compound parts `<Progress.Root>/<Progress.Track>/<Progress.Indicator>` etc.\n * — full layout control, borrowed from Ark UI / Chakra's structure, with\n * Mantine-style `<Progress.Segment>` for multi-colour bars.\n *\n * The compound parts share a context so `value`/`max`/`size` are set once on\n * `Root` and read by Track/Indicator/Segment/Value.\n * ------------------------------------------------------------------------ */\n\nexport type ProgressSize = 'sm' | 'md' | 'lg'\nexport type ProgressColor = 'accent' | 'success' | 'warning' | 'error'\n\nexport const progressTrackVariants = cva(\n 'relative w-full overflow-hidden rounded-pill bg-surface-raised',\n {\n variants: { size: { sm: 'h-1', md: 'h-2', lg: 'h-3' } },\n defaultVariants: { size: 'md' },\n },\n)\n\nconst COLOR_FILL: Record<ProgressColor, string> = {\n accent: 'bg-accent-9',\n success: 'bg-success-9',\n warning: 'bg-warning-9',\n error: 'bg-error-9',\n}\n\nexport const progressIndicatorVariants = cva(\n 'h-full transition-[width] duration-moderate-02 ease-expressive-standard',\n {\n variants: { color: COLOR_FILL },\n defaultVariants: { color: 'accent' },\n },\n)\n\n/** Auto-color by value: 0–59 accent, 60–84 warning, 85–100 success, >100 error. */\nfunction autoColorFor(value: number | null | undefined): ProgressColor {\n if (value == null) return 'accent'\n if (value > 100) return 'error'\n if (value >= 85) return 'success'\n if (value >= 60) return 'warning'\n return 'accent'\n}\n\nconst clampPct = (value: number, max: number) =>\n Math.max(0, Math.min(100, (value / max) * 100))\n\n/* ---------------------------------------------------------------------------\n * Context — set once on Root, read by Track / Indicator / Segment / Value.\n * ------------------------------------------------------------------------ */\n\ninterface ProgressContextValue {\n value: number | null\n max: number\n size: ProgressSize\n indeterminate: boolean\n}\n\nconst ProgressContext = React.createContext<ProgressContextValue | null>(null)\n\nfunction useProgressContext(part: string): ProgressContextValue {\n const ctx = React.useContext(ProgressContext)\n if (!ctx) {\n throw new Error(`<Progress.${part}> must be rendered inside <Progress.Root>.`)\n }\n return ctx\n}\n\n/* ---------------------------------------------------------------------------\n * Progress.Root — layout container + context. NOT the progressbar itself\n * (that's Track) so labels/value can sit outside the bar (Ark UI model).\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressRootProps extends React.HTMLAttributes<HTMLDivElement> {\n /** 0–max. Omit (or null) for an indeterminate bar. */\n value?: number | null\n /** Scale maximum. @default 100 */\n max?: number\n /** Track thickness. @default 'md' */\n size?: ProgressSize\n}\n\nconst ProgressRoot = React.forwardRef<HTMLDivElement, ProgressRootProps>(\n ({ value = null, max = 100, size = 'md', className, children, ...props }, ref) => {\n const ctx = React.useMemo<ProgressContextValue>(\n () => ({ value, max, size, indeterminate: value == null }),\n [value, max, size],\n )\n return (\n <ProgressContext.Provider value={ctx}>\n <div ref={ref} className={cn('flex w-full items-center gap-ds-03', className)} {...props}>\n {children}\n </div>\n </ProgressContext.Provider>\n )\n },\n)\nProgressRoot.displayName = 'Progress.Root'\n\n/* ---------------------------------------------------------------------------\n * Progress.Track — the aria progressbar + track visual. Holds Indicator/Segment.\n * ------------------------------------------------------------------------ */\n\nexport type ProgressTrackProps = React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n\nconst ProgressTrack = React.forwardRef<\n React.ElementRef<typeof ProgressPrimitive.Root>,\n ProgressTrackProps\n>(({ className, children, ...props }, ref) => {\n const { value, max, size, indeterminate } = useProgressContext('Track')\n // Accessible name comes from the consumer's aria-label / aria-labelledby (spread\n // via ...props) — no auto-wiring, so a Track never carries a dangling reference.\n return (\n <ProgressPrimitive.Root\n ref={ref}\n value={indeterminate ? null : value}\n max={max}\n className={cn(progressTrackVariants({ size }), 'flex-1', className)}\n {...props}\n >\n {children}\n </ProgressPrimitive.Root>\n )\n})\nProgressTrack.displayName = 'Progress.Track'\n\n/* ---------------------------------------------------------------------------\n * Progress.Indicator — single fill. Determinate width from context, or the\n * indeterminate sweep animation when Root has no value.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressIndicatorProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Fill colour. Omit to auto-colour by value. */\n color?: ProgressColor\n /** Force auto-colour even when `color` is unset. @default true when color unset */\n autoColor?: boolean\n}\n\nconst ProgressIndicator = React.forwardRef<HTMLDivElement, ProgressIndicatorProps>(\n ({ color, autoColor, className, ...props }, ref) => {\n const { value, max, indeterminate } = useProgressContext('Indicator')\n const resolved = color ?? (autoColor !== false ? autoColorFor(value) : 'accent')\n\n if (indeterminate) {\n return (\n <div\n ref={ref}\n className={cn(\n progressIndicatorVariants({ color: resolved }),\n 'w-2/5 animate-progress-indeterminate motion-reduce:animate-none',\n className,\n )}\n {...props}\n />\n )\n }\n return (\n <motion.div\n ref={ref}\n className={cn(progressIndicatorVariants({ color: resolved }), 'transition-colors', className)}\n initial={false}\n animate={{ width: `${clampPct(value ?? 0, max)}%` }}\n transition={springs.smooth}\n {...(props as React.ComponentProps<typeof motion.div>)}\n />\n )\n },\n)\nProgressIndicator.displayName = 'Progress.Indicator'\n\n/* ---------------------------------------------------------------------------\n * Progress.Segment — one slice of a multi-segment bar (Mantine-style). Place\n * several inside a Track. Widths are each segment's value as a % of max.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressSegmentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** This segment's portion of `max`. */\n value: number\n color?: ProgressColor\n}\n\nconst ProgressSegment = React.forwardRef<HTMLDivElement, ProgressSegmentProps>(\n ({ value, color = 'accent', className, style, ...props }, ref) => {\n const { max } = useProgressContext('Segment')\n return (\n <div\n ref={ref}\n aria-hidden=\"true\"\n className={cn('h-full first:rounded-l-pill last:rounded-r-pill', COLOR_FILL[color], className)}\n style={{ width: `${clampPct(value, max)}%`, ...style }}\n {...props}\n />\n )\n },\n)\nProgressSegment.displayName = 'Progress.Segment'\n\n/* ---------------------------------------------------------------------------\n * Progress.Label — descriptive text, associated with the bar via aria.\n * ------------------------------------------------------------------------ */\n\nexport type ProgressLabelProps = React.HTMLAttributes<HTMLSpanElement>\n\nconst ProgressLabel = React.forwardRef<HTMLSpanElement, ProgressLabelProps>(\n ({ className, ...props }, ref) => {\n useProgressContext('Label')\n return (\n <span\n ref={ref}\n className={cn('shrink-0 text-body-sm font-medium text-surface-fg', className)}\n {...props}\n />\n )\n },\n)\nProgressLabel.displayName = 'Progress.Label'\n\n/* ---------------------------------------------------------------------------\n * Progress.Value — the \"{n}%\" readout. Custom content via children or `format`.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressValueProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'children'> {\n /** Format the percentage. Default: `${round(pct)}%`. */\n format?: (pct: number, value: number | null, max: number) => React.ReactNode\n children?: React.ReactNode\n}\n\nconst ProgressValue = React.forwardRef<HTMLSpanElement, ProgressValueProps>(\n ({ className, format, children, ...props }, ref) => {\n const { value, max, indeterminate } = useProgressContext('Value')\n const pct = indeterminate ? 0 : clampPct(value ?? 0, max)\n return (\n <span\n ref={ref}\n className={cn('shrink-0 text-caption text-surface-fg-muted tabular-nums', className)}\n {...props}\n >\n {children ?? (indeterminate ? '' : format ? format(pct, value, max) : `${Math.round(pct)}%`)}\n </span>\n )\n },\n)\nProgressValue.displayName = 'Progress.Value'\n\n/* ---------------------------------------------------------------------------\n * Progress — smart all-in-one. Composes the parts for the common cases.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n VariantProps<typeof progressTrackVariants> {\n /** 0–max. Omit (or null) for an indeterminate bar. */\n value?: number | null\n max?: number\n /** Fill colour. Omit + set `autoColor` to colour by value. */\n color?: ProgressColor\n /** Auto-colour the fill by value (0–59 accent · 60–84 warning · 85–100 success · >100 error). @default false */\n autoColor?: boolean\n /** Descriptive label rendered before the bar. */\n label?: React.ReactNode\n /** Show the `{n}%` readout after the bar. */\n showValue?: boolean\n /** Multi-segment bar: each slice is `value` (portion of max) + `color`. Overrides the single indicator. */\n segments?: Array<{ value: number; color?: ProgressColor }>\n /** Class for the Track element. */\n trackClassName?: string\n /** Class for the single Indicator (ignored when `segments` is set). */\n indicatorClassName?: string\n}\n\nconst ProgressBase = React.forwardRef<HTMLDivElement, ProgressProps>(\n (\n {\n value = null, max = 100, size, color, autoColor, label, showValue, segments,\n trackClassName, indicatorClassName, className,\n 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, ...props\n },\n ref,\n ) => {\n const labelId = React.useId()\n const hasLabel = label != null\n return (\n <ProgressRoot ref={ref} value={value} max={max} size={size ?? 'md'} className={className} {...props}>\n {hasLabel && <ProgressLabel id={labelId}>{label}</ProgressLabel>}\n <ProgressTrack\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby ?? (hasLabel ? labelId : undefined)}\n className={cn(segments && 'flex', trackClassName)}\n >\n {segments\n ? segments.map((s, i) => <ProgressSegment key={i} value={s.value} color={s.color} />)\n : <ProgressIndicator color={color} autoColor={autoColor} className={indicatorClassName} />}\n </ProgressTrack>\n {showValue && value != null && <ProgressValue />}\n </ProgressRoot>\n )\n },\n)\nProgressBase.displayName = 'Progress'\n\nconst Progress = Object.assign(ProgressBase, {\n Root: ProgressRoot,\n Track: ProgressTrack,\n Indicator: ProgressIndicator,\n Segment: ProgressSegment,\n Label: ProgressLabel,\n Value: ProgressValue,\n})\n\nexport {\n Progress,\n ProgressIndicator,\n ProgressLabel,\n ProgressRoot,\n ProgressSegment,\n ProgressTrack,\n ProgressValue,\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"progress.js","names":[],"sources":["../../src/ui/progress.tsx"],"sourcesContent":["'use client'\n\nimport * as ProgressPrimitive from '@primitives/react-progress'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { 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\n/* ---------------------------------------------------------------------------\n * Progress — a linear progress bar.\n *\n * Two ways to use it:\n * 1. Smart all-in-one `<Progress value={70} />` — covers the common cases\n * (value, size, color, label, %-value, auto-color, indeterminate, segments).\n * 2. Compound parts `<Progress.Root>/<Progress.Track>/<Progress.Indicator>` etc.\n * — full layout control, borrowed from Ark UI / Chakra's structure, with\n * Mantine-style `<Progress.Segment>` for multi-colour bars.\n *\n * The compound parts share a context so `value`/`max`/`size` are set once on\n * `Root` and read by Track/Indicator/Segment/Value.\n * ------------------------------------------------------------------------ */\n\nexport type ProgressSize = 'sm' | 'md' | 'lg'\nexport type ProgressColor = 'accent' | 'success' | 'warning' | 'error'\n\nexport const progressTrackVariants = cva(\n 'relative w-full overflow-hidden rounded-pill bg-surface-panel',\n {\n variants: { size: { sm: 'h-1', md: 'h-2', lg: 'h-3' } },\n defaultVariants: { size: 'md' },\n },\n)\n\nconst COLOR_FILL: Record<ProgressColor, string> = {\n accent: 'bg-accent-9',\n success: 'bg-success-9',\n warning: 'bg-warning-9',\n error: 'bg-error-9',\n}\n\nexport const progressIndicatorVariants = cva(\n 'h-full transition-[width] duration-moderate-02 ease-expressive-standard',\n {\n variants: { color: COLOR_FILL },\n defaultVariants: { color: 'accent' },\n },\n)\n\n/** Auto-color by value: 0–59 accent, 60–84 warning, 85–100 success, >100 error. */\nfunction autoColorFor(value: number | null | undefined): ProgressColor {\n if (value == null) return 'accent'\n if (value > 100) return 'error'\n if (value >= 85) return 'success'\n if (value >= 60) return 'warning'\n return 'accent'\n}\n\nconst clampPct = (value: number, max: number) =>\n Math.max(0, Math.min(100, (value / max) * 100))\n\n/* ---------------------------------------------------------------------------\n * Context — set once on Root, read by Track / Indicator / Segment / Value.\n * ------------------------------------------------------------------------ */\n\ninterface ProgressContextValue {\n value: number | null\n max: number\n size: ProgressSize\n indeterminate: boolean\n}\n\nconst ProgressContext = React.createContext<ProgressContextValue | null>(null)\n\nfunction useProgressContext(part: string): ProgressContextValue {\n const ctx = React.useContext(ProgressContext)\n if (!ctx) {\n throw new Error(`<Progress.${part}> must be rendered inside <Progress.Root>.`)\n }\n return ctx\n}\n\n/* ---------------------------------------------------------------------------\n * Progress.Root — layout container + context. NOT the progressbar itself\n * (that's Track) so labels/value can sit outside the bar (Ark UI model).\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressRootProps extends React.HTMLAttributes<HTMLDivElement> {\n /** 0–max. Omit (or null) for an indeterminate bar. */\n value?: number | null\n /** Scale maximum. @default 100 */\n max?: number\n /** Track thickness. @default 'md' */\n size?: ProgressSize\n}\n\nconst ProgressRoot = React.forwardRef<HTMLDivElement, ProgressRootProps>(\n ({ value = null, max = 100, size = 'md', className, children, ...props }, ref) => {\n const ctx = React.useMemo<ProgressContextValue>(\n () => ({ value, max, size, indeterminate: value == null }),\n [value, max, size],\n )\n return (\n <ProgressContext.Provider value={ctx}>\n <div ref={ref} className={cn('flex w-full items-center gap-ds-03', className)} {...props}>\n {children}\n </div>\n </ProgressContext.Provider>\n )\n },\n)\nProgressRoot.displayName = 'Progress.Root'\n\n/* ---------------------------------------------------------------------------\n * Progress.Track — the aria progressbar + track visual. Holds Indicator/Segment.\n * ------------------------------------------------------------------------ */\n\nexport type ProgressTrackProps = React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n\nconst ProgressTrack = React.forwardRef<\n React.ElementRef<typeof ProgressPrimitive.Root>,\n ProgressTrackProps\n>(({ className, children, ...props }, ref) => {\n const { value, max, size, indeterminate } = useProgressContext('Track')\n // Accessible name comes from the consumer's aria-label / aria-labelledby (spread\n // via ...props) — no auto-wiring, so a Track never carries a dangling reference.\n return (\n <ProgressPrimitive.Root\n ref={ref}\n value={indeterminate ? null : value}\n max={max}\n className={cn(progressTrackVariants({ size }), 'flex-1', className)}\n {...props}\n >\n {children}\n </ProgressPrimitive.Root>\n )\n})\nProgressTrack.displayName = 'Progress.Track'\n\n/* ---------------------------------------------------------------------------\n * Progress.Indicator — single fill. Determinate width from context, or the\n * indeterminate sweep animation when Root has no value.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressIndicatorProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Fill colour. Omit to auto-colour by value. */\n color?: ProgressColor\n /** Force auto-colour even when `color` is unset. @default true when color unset */\n autoColor?: boolean\n}\n\nconst ProgressIndicator = React.forwardRef<HTMLDivElement, ProgressIndicatorProps>(\n ({ color, autoColor, className, ...props }, ref) => {\n const { value, max, indeterminate } = useProgressContext('Indicator')\n const resolved = color ?? (autoColor !== false ? autoColorFor(value) : 'accent')\n\n if (indeterminate) {\n return (\n <div\n ref={ref}\n className={cn(\n progressIndicatorVariants({ color: resolved }),\n 'w-2/5 animate-progress-indeterminate motion-reduce:animate-none',\n className,\n )}\n {...props}\n />\n )\n }\n return (\n <motion.div\n ref={ref}\n className={cn(progressIndicatorVariants({ color: resolved }), 'transition-colors', className)}\n initial={false}\n animate={{ width: `${clampPct(value ?? 0, max)}%` }}\n transition={springs.smooth}\n {...(props as React.ComponentProps<typeof motion.div>)}\n />\n )\n },\n)\nProgressIndicator.displayName = 'Progress.Indicator'\n\n/* ---------------------------------------------------------------------------\n * Progress.Segment — one slice of a multi-segment bar (Mantine-style). Place\n * several inside a Track. Widths are each segment's value as a % of max.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressSegmentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** This segment's portion of `max`. */\n value: number\n color?: ProgressColor\n}\n\nconst ProgressSegment = React.forwardRef<HTMLDivElement, ProgressSegmentProps>(\n ({ value, color = 'accent', className, style, ...props }, ref) => {\n const { max } = useProgressContext('Segment')\n return (\n <div\n ref={ref}\n aria-hidden=\"true\"\n className={cn('h-full first:rounded-l-pill last:rounded-r-pill', COLOR_FILL[color], className)}\n style={{ width: `${clampPct(value, max)}%`, ...style }}\n {...props}\n />\n )\n },\n)\nProgressSegment.displayName = 'Progress.Segment'\n\n/* ---------------------------------------------------------------------------\n * Progress.Label — descriptive text, associated with the bar via aria.\n * ------------------------------------------------------------------------ */\n\nexport type ProgressLabelProps = React.HTMLAttributes<HTMLSpanElement>\n\nconst ProgressLabel = React.forwardRef<HTMLSpanElement, ProgressLabelProps>(\n ({ className, ...props }, ref) => {\n useProgressContext('Label')\n return (\n <span\n ref={ref}\n className={cn('shrink-0 text-body-sm font-medium text-surface-fg', className)}\n {...props}\n />\n )\n },\n)\nProgressLabel.displayName = 'Progress.Label'\n\n/* ---------------------------------------------------------------------------\n * Progress.Value — the \"{n}%\" readout. Custom content via children or `format`.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressValueProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'children'> {\n /** Format the percentage. Default: `${round(pct)}%`. */\n format?: (pct: number, value: number | null, max: number) => React.ReactNode\n children?: React.ReactNode\n}\n\nconst ProgressValue = React.forwardRef<HTMLSpanElement, ProgressValueProps>(\n ({ className, format, children, ...props }, ref) => {\n const { value, max, indeterminate } = useProgressContext('Value')\n const pct = indeterminate ? 0 : clampPct(value ?? 0, max)\n return (\n <span\n ref={ref}\n className={cn('shrink-0 text-caption text-surface-fg-muted tabular-nums', className)}\n {...props}\n >\n {children ?? (indeterminate ? '' : format ? format(pct, value, max) : `${Math.round(pct)}%`)}\n </span>\n )\n },\n)\nProgressValue.displayName = 'Progress.Value'\n\n/* ---------------------------------------------------------------------------\n * Progress — smart all-in-one. Composes the parts for the common cases.\n * ------------------------------------------------------------------------ */\n\nexport interface ProgressProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color'>,\n VariantProps<typeof progressTrackVariants> {\n /** 0–max. Omit (or null) for an indeterminate bar. */\n value?: number | null\n max?: number\n /** Fill colour. Omit + set `autoColor` to colour by value. */\n color?: ProgressColor\n /** Auto-colour the fill by value (0–59 accent · 60–84 warning · 85–100 success · >100 error). @default false */\n autoColor?: boolean\n /** Descriptive label rendered before the bar. */\n label?: React.ReactNode\n /** Show the `{n}%` readout after the bar. */\n showValue?: boolean\n /** Multi-segment bar: each slice is `value` (portion of max) + `color`. Overrides the single indicator. */\n segments?: Array<{ value: number; color?: ProgressColor }>\n /** Class for the Track element. */\n trackClassName?: string\n /** Class for the single Indicator (ignored when `segments` is set). */\n indicatorClassName?: string\n}\n\n/**\n * `role=\"progressbar\"` with no accessible name announces as just \"progressbar,\n * 72%\" — the value is already carried by `aria-valuenow`, so what a screen\n * reader is missing is WHAT is progressing.\n *\n * This warns rather than auto-generating a name on purpose. A generated default\n * (\"Progress\", or \"Progress: 72%\") would silence the Lighthouse audit while\n * leaving the announcement just as uninformative, which is worse than the\n * current state: the bar looks labelled and nobody fixes it. Only the consumer\n * knows what the bar measures.\n *\n * Latched at module scope so a bar that re-renders on every value tick logs\n * once, not once per frame — same pattern as Card's unwrapped-text warning.\n */\nlet warnedMissingProgressName = false\n\nfunction warnOnMissingAccessibleName(): void {\n if (warnedMissingProgressName) return\n if (typeof process === 'undefined' || process?.env?.NODE_ENV === 'production') return\n warnedMissingProgressName = true\n console.warn(\n '[shilp-sutra] <Progress> has no accessible name, so it announces as just \"progressbar\" with a percentage. ' +\n 'Pass `label` (renders visible text and wires aria-labelledby) or `aria-label` if the bar must stay unlabelled visually. ' +\n 'Example: <Progress value={72} label=\"Storage used\" /> or <Progress value={72} aria-label=\"Upload progress\" />.',\n )\n}\n\nconst ProgressBase = React.forwardRef<HTMLDivElement, ProgressProps>(\n (\n {\n value = null, max = 100, size, color, autoColor, label, showValue, segments,\n trackClassName, indicatorClassName, className,\n 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, ...props\n },\n ref,\n ) => {\n const labelId = React.useId()\n const hasLabel = label != null\n if (!hasLabel && !ariaLabel && !ariaLabelledby) warnOnMissingAccessibleName()\n return (\n <ProgressRoot ref={ref} value={value} max={max} size={size ?? 'md'} className={className} {...props}>\n {hasLabel && <ProgressLabel id={labelId}>{label}</ProgressLabel>}\n <ProgressTrack\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby ?? (hasLabel ? labelId : undefined)}\n className={cn(segments && 'flex', trackClassName)}\n >\n {segments\n ? segments.map((s, i) => <ProgressSegment key={i} value={s.value} color={s.color} />)\n : <ProgressIndicator color={color} autoColor={autoColor} className={indicatorClassName} />}\n </ProgressTrack>\n {showValue && value != null && <ProgressValue />}\n </ProgressRoot>\n )\n },\n)\nProgressBase.displayName = 'Progress'\n\nconst Progress = Object.assign(ProgressBase, {\n Root: ProgressRoot,\n Track: ProgressTrack,\n Indicator: ProgressIndicator,\n Segment: ProgressSegment,\n Label: ProgressLabel,\n Value: ProgressValue,\n})\n\nexport {\n Progress,\n ProgressIndicator,\n ProgressLabel,\n ProgressRoot,\n ProgressSegment,\n ProgressTrack,\n ProgressValue,\n}\n"],"mappings":"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"}
package/dist/ui/radio.js CHANGED
@@ -40,7 +40,7 @@ var m = {
40
40
  let g = s.useContext(d);
41
41
  return /* @__PURE__ */ c(a, {
42
42
  ref: p,
43
- className: t("touch-target aspect-square rounded-pill", m[r], "border border-surface-border-strong bg-surface-raised-hover", "transition-colors duration-fast-01", "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", "hover:border-accent-7 hover:bg-surface-raised-active", "data-[state=checked]:border-accent-7", g && f[g], n),
43
+ className: t("touch-target aspect-square rounded-pill", m[r], "border border-surface-border-interactive bg-surface-panel-hover", "transition-colors duration-fast-01", "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", "hover:border-accent-7 hover:bg-surface-panel-active", "data-[state=checked]:border-accent-7", g && f[g], n),
44
44
  ...o,
45
45
  children: /* @__PURE__ */ c(i, {
46
46
  asChild: !0,
@@ -1 +1 @@
1
- {"version":3,"file":"radio.js","names":[],"sources":["../../src/ui/radio.tsx"],"sourcesContent":["'use client'\n\nimport * as RadioGroupPrimitive from '@primitives/react-radio-group'\nimport { IconCircle } from '@tabler/icons-react'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useFormField } from './form'\nimport { type FieldState, resolveFieldState } from './lib/field-state'\nimport { springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\n// Thread the group's resolved state to items so they show the matching border tint.\nconst RadioStateContext = React.createContext<Exclude<FieldState, 'default'> | undefined>(undefined)\n\n/** Border tint per validation state, applied to each item. */\nconst stateBorderClasses: Record<Exclude<FieldState, 'default'>, string> = {\n error: 'border-error-7',\n warning: 'border-warning-7',\n success: 'border-success-7',\n}\n\nexport interface RadioGroupProps extends React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root> {\n /** Validation/feedback state for the whole group. `'error'` also sets `aria-invalid`. Inherited from `FormField` when omitted. */\n state?: FieldState\n}\n\nconst RadioGroup = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Root>,\n RadioGroupProps\n>(({ className, state: stateProp, ...props }, ref) => {\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 return (\n <RadioStateContext.Provider value={state}>\n <RadioGroupPrimitive.Root\n className={cn('grid gap-ds-03', className)}\n aria-invalid={state === 'error' || undefined}\n aria-describedby={ariaDescribedBy}\n aria-required={ariaRequired || undefined}\n {...props}\n ref={ref}\n />\n </RadioStateContext.Provider>\n )\n})\nRadioGroup.displayName = RadioGroupPrimitive.Root.displayName\n\nexport interface RadioGroupItemProps extends React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item> {\n /** Control size — `sm` (20px), `md` (24px, default, WCAG compliant), `lg` (28px). */\n size?: 'sm' | 'md' | 'lg'\n}\n\nconst radioSizeClasses = {\n sm: 'h-5 w-5',\n md: 'h-6 w-6',\n lg: 'h-7 w-7',\n} as const\n\nconst radioIndicatorClasses = {\n sm: 'h-1.5 w-1.5',\n md: 'h-ds-03 w-ds-03',\n lg: 'h-2.5 w-2.5',\n} as const\n\nconst RadioGroupItem = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Item>,\n RadioGroupItemProps\n>(({ className, size = 'md', ...props }, ref) => {\n const state = React.useContext(RadioStateContext)\n return (\n <RadioGroupPrimitive.Item\n ref={ref}\n className={cn(\n 'touch-target aspect-square rounded-pill',\n radioSizeClasses[size],\n 'border border-surface-border-strong bg-surface-raised-hover',\n 'transition-colors duration-fast-01',\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 'hover:border-accent-7 hover:bg-surface-raised-active',\n 'data-[state=checked]:border-accent-7',\n state && stateBorderClasses[state],\n className,\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator asChild className=\"flex items-center justify-center\">\n <motion.span\n className=\"flex items-center justify-center\"\n initial={{ scale: 0 }}\n animate={{ scale: 1 }}\n transition={springs.snappy}\n >\n <IconCircle className={cn(radioIndicatorClasses[size], 'fill-accent-9 text-accent-11')} />\n </motion.span>\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n )\n})\nRadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName\n\nexport { RadioGroup, RadioGroupItem }\n"],"mappings":";;;;;;;;;;;AAaA,IAAM,IAAoB,EAAM,cAA0D,KAAA,CAAS,GAG7F,IAAqE;CACzE,OAAO;CACP,SAAS;CACT,SAAS;AACX,GAOM,IAAa,EAAM,YAGtB,EAAE,cAAW,OAAO,GAAW,GAAG,KAAS,MAAQ;CACpD,IAAM,IAAW,EAAa,GACxB,IAAQ,EAAkB,GAAW,EAAS,KAAK,GACnD,IAAkB,EAAM,uBAAuB,EAAS,cACxD,IAAe,EAAM,oBAAoB,EAAS;CAExD,OACE,kBAAC,EAAkB,UAAnB;EAA4B,OAAO;YACjC,kBAAC,GAAD;GACE,WAAW,EAAG,kBAAkB,CAAS;GACzC,gBAAc,MAAU,WAAW,KAAA;GACnC,oBAAkB;GAClB,iBAAe,KAAgB,KAAA;GAC/B,GAAI;GACC;EACN,CAAA;CACyB,CAAA;AAEhC,CAAC;AACD,EAAW,cAAA,EAAuC;AAOlD,IAAM,IAAmB;CACvB,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAEM,IAAwB;CAC5B,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAEM,IAAiB,EAAM,YAG1B,EAAE,cAAW,UAAO,MAAM,GAAG,KAAS,MAAQ;CAC/C,IAAM,IAAQ,EAAM,WAAW,CAAiB;CAChD,OACE,kBAAC,GAAD;EACO;EACL,WAAW,EACT,2CACA,EAAiB,IACjB,+DACA,sCACA,6GACA,gEACA,wDACA,wCACA,KAAS,EAAmB,IAC5B,CACF;EACA,GAAI;YAEJ,kBAAC,GAAD;GAA+B,SAAA;GAAQ,WAAU;aAC/C,kBAAC,EAAO,MAAR;IACE,WAAU;IACV,SAAS,EAAE,OAAO,EAAE;IACpB,SAAS,EAAE,OAAO,EAAE;IACpB,YAAY,EAAQ;cAEpB,kBAAC,GAAD,EAAY,WAAW,EAAG,EAAsB,IAAO,8BAA8B,EAAI,CAAA;GAC9E,CAAA;EACgB,CAAA;CACP,CAAA;AAE9B,CAAC;AACD,EAAe,cAAA,EAAuC"}
1
+ {"version":3,"file":"radio.js","names":[],"sources":["../../src/ui/radio.tsx"],"sourcesContent":["'use client'\n\nimport * as RadioGroupPrimitive from '@primitives/react-radio-group'\nimport { IconCircle } from '@tabler/icons-react'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useFormField } from './form'\nimport { type FieldState, resolveFieldState } from './lib/field-state'\nimport { springs } from './lib/motion'\nimport { cn } from './lib/utils'\n\n// Thread the group's resolved state to items so they show the matching border tint.\nconst RadioStateContext = React.createContext<Exclude<FieldState, 'default'> | undefined>(undefined)\n\n/** Border tint per validation state, applied to each item. */\nconst stateBorderClasses: Record<Exclude<FieldState, 'default'>, string> = {\n error: 'border-error-7',\n warning: 'border-warning-7',\n success: 'border-success-7',\n}\n\nexport interface RadioGroupProps extends React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root> {\n /** Validation/feedback state for the whole group. `'error'` also sets `aria-invalid`. Inherited from `FormField` when omitted. */\n state?: FieldState\n}\n\nconst RadioGroup = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Root>,\n RadioGroupProps\n>(({ className, state: stateProp, ...props }, ref) => {\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 return (\n <RadioStateContext.Provider value={state}>\n <RadioGroupPrimitive.Root\n className={cn('grid gap-ds-03', className)}\n aria-invalid={state === 'error' || undefined}\n aria-describedby={ariaDescribedBy}\n aria-required={ariaRequired || undefined}\n {...props}\n ref={ref}\n />\n </RadioStateContext.Provider>\n )\n})\nRadioGroup.displayName = RadioGroupPrimitive.Root.displayName\n\nexport interface RadioGroupItemProps extends React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item> {\n /** Control size — `sm` (20px), `md` (24px, default, WCAG compliant), `lg` (28px). */\n size?: 'sm' | 'md' | 'lg'\n}\n\nconst radioSizeClasses = {\n sm: 'h-5 w-5',\n md: 'h-6 w-6',\n lg: 'h-7 w-7',\n} as const\n\nconst radioIndicatorClasses = {\n sm: 'h-1.5 w-1.5',\n md: 'h-ds-03 w-ds-03',\n lg: 'h-2.5 w-2.5',\n} as const\n\nconst RadioGroupItem = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Item>,\n RadioGroupItemProps\n>(({ className, size = 'md', ...props }, ref) => {\n const state = React.useContext(RadioStateContext)\n return (\n <RadioGroupPrimitive.Item\n ref={ref}\n className={cn(\n 'touch-target aspect-square rounded-pill',\n radioSizeClasses[size],\n 'border border-surface-border-interactive bg-surface-panel-hover',\n 'transition-colors duration-fast-01',\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 'hover:border-accent-7 hover:bg-surface-panel-active',\n 'data-[state=checked]:border-accent-7',\n state && stateBorderClasses[state],\n className,\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator asChild className=\"flex items-center justify-center\">\n <motion.span\n className=\"flex items-center justify-center\"\n initial={{ scale: 0 }}\n animate={{ scale: 1 }}\n transition={springs.snappy}\n >\n <IconCircle className={cn(radioIndicatorClasses[size], 'fill-accent-9 text-accent-11')} />\n </motion.span>\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n )\n})\nRadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName\n\nexport { RadioGroup, RadioGroupItem }\n"],"mappings":";;;;;;;;;;;AAaA,IAAM,IAAoB,EAAM,cAA0D,KAAA,CAAS,GAG7F,IAAqE;CACzE,OAAO;CACP,SAAS;CACT,SAAS;AACX,GAOM,IAAa,EAAM,YAGtB,EAAE,cAAW,OAAO,GAAW,GAAG,KAAS,MAAQ;CACpD,IAAM,IAAW,EAAa,GACxB,IAAQ,EAAkB,GAAW,EAAS,KAAK,GACnD,IAAkB,EAAM,uBAAuB,EAAS,cACxD,IAAe,EAAM,oBAAoB,EAAS;CAExD,OACE,kBAAC,EAAkB,UAAnB;EAA4B,OAAO;YACjC,kBAAC,GAAD;GACE,WAAW,EAAG,kBAAkB,CAAS;GACzC,gBAAc,MAAU,WAAW,KAAA;GACnC,oBAAkB;GAClB,iBAAe,KAAgB,KAAA;GAC/B,GAAI;GACC;EACN,CAAA;CACyB,CAAA;AAEhC,CAAC;AACD,EAAW,cAAA,EAAuC;AAOlD,IAAM,IAAmB;CACvB,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAEM,IAAwB;CAC5B,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAEM,IAAiB,EAAM,YAG1B,EAAE,cAAW,UAAO,MAAM,GAAG,KAAS,MAAQ;CAC/C,IAAM,IAAQ,EAAM,WAAW,CAAiB;CAChD,OACE,kBAAC,GAAD;EACO;EACL,WAAW,EACT,2CACA,EAAiB,IACjB,mEACA,sCACA,6GACA,gEACA,uDACA,wCACA,KAAS,EAAmB,IAC5B,CACF;EACA,GAAI;YAEJ,kBAAC,GAAD;GAA+B,SAAA;GAAQ,WAAU;aAC/C,kBAAC,EAAO,MAAR;IACE,WAAU;IACV,SAAS,EAAE,OAAO,EAAE;IACpB,SAAS,EAAE,OAAO,EAAE;IACpB,YAAY,EAAQ;cAEpB,kBAAC,GAAD,EAAY,WAAW,EAAG,EAAsB,IAAO,8BAA8B,EAAI,CAAA;GAC9E,CAAA;EACgB,CAAA;CACP,CAAA;AAE9B,CAAC;AACD,EAAe,cAAA,EAAuC"}