@epilot/spark-ui 1.0.0-alpha.4 → 1.0.0-alpha.6

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 (201) hide show
  1. package/dist/accent-colors-Ch2J0EEY.js +13 -0
  2. package/dist/accent-colors-Ch2J0EEY.js.map +1 -0
  3. package/dist/accent-colors-CjHCf8fH.cjs +18 -0
  4. package/dist/accent-colors-CjHCf8fH.cjs.map +1 -0
  5. package/dist/components/accordion.cjs +3 -3
  6. package/dist/components/accordion.cjs.map +1 -1
  7. package/dist/components/accordion.d.ts +1 -1
  8. package/dist/components/accordion.js +3 -3
  9. package/dist/components/accordion.js.map +1 -1
  10. package/dist/components/attachment.d.cts +1 -1
  11. package/dist/components/attachment.d.ts +1 -1
  12. package/dist/components/badge.cjs +12 -7
  13. package/dist/components/badge.cjs.map +1 -1
  14. package/dist/components/badge.d.cts +5 -1
  15. package/dist/components/badge.d.ts +5 -1
  16. package/dist/components/badge.js +12 -7
  17. package/dist/components/badge.js.map +1 -1
  18. package/dist/components/bar-chart.cjs +12 -9
  19. package/dist/components/bar-chart.cjs.map +1 -1
  20. package/dist/components/bar-chart.js +12 -9
  21. package/dist/components/bar-chart.js.map +1 -1
  22. package/dist/components/battery-progress-row.cjs +10 -16
  23. package/dist/components/battery-progress-row.cjs.map +1 -1
  24. package/dist/components/battery-progress-row.d.cts +1 -1
  25. package/dist/components/battery-progress-row.d.ts +2 -2
  26. package/dist/components/battery-progress-row.js +10 -16
  27. package/dist/components/battery-progress-row.js.map +1 -1
  28. package/dist/components/breadcrumbs.cjs +1 -1
  29. package/dist/components/breadcrumbs.cjs.map +1 -1
  30. package/dist/components/breadcrumbs.js +1 -1
  31. package/dist/components/breadcrumbs.js.map +1 -1
  32. package/dist/components/bubble.d.cts +1 -1
  33. package/dist/components/bubble.d.ts +1 -1
  34. package/dist/components/button.cjs +5 -2
  35. package/dist/components/button.cjs.map +1 -1
  36. package/dist/components/button.d.cts +7 -6
  37. package/dist/components/button.d.ts +7 -6
  38. package/dist/components/button.js +5 -2
  39. package/dist/components/button.js.map +1 -1
  40. package/dist/components/calendar.cjs +3 -2
  41. package/dist/components/calendar.cjs.map +1 -1
  42. package/dist/components/calendar.d.cts +5 -1
  43. package/dist/components/calendar.d.ts +5 -1
  44. package/dist/components/calendar.js +3 -2
  45. package/dist/components/calendar.js.map +1 -1
  46. package/dist/components/callout.d.cts +1 -1
  47. package/dist/components/callout.d.ts +1 -1
  48. package/dist/components/card.d.cts +1 -1
  49. package/dist/components/card.d.ts +1 -1
  50. package/dist/components/chart.cjs +1 -1
  51. package/dist/components/chart.cjs.map +1 -1
  52. package/dist/components/chart.js +1 -1
  53. package/dist/components/chart.js.map +1 -1
  54. package/dist/components/checkbox.cjs +30 -23
  55. package/dist/components/checkbox.cjs.map +1 -1
  56. package/dist/components/checkbox.d.cts +5 -1
  57. package/dist/components/checkbox.d.ts +5 -1
  58. package/dist/components/checkbox.js +30 -23
  59. package/dist/components/checkbox.js.map +1 -1
  60. package/dist/components/circular-gauge.d.ts +1 -1
  61. package/dist/components/day-of-week-picker.cjs +2 -2
  62. package/dist/components/day-of-week-picker.cjs.map +1 -1
  63. package/dist/components/day-of-week-picker.js +2 -2
  64. package/dist/components/day-of-week-picker.js.map +1 -1
  65. package/dist/components/device-card.d.ts +1 -1
  66. package/dist/components/donut-chart.cjs +3 -3
  67. package/dist/components/donut-chart.cjs.map +1 -1
  68. package/dist/components/donut-chart.js +3 -3
  69. package/dist/components/donut-chart.js.map +1 -1
  70. package/dist/components/energy-bar-chart.d.ts +1 -1
  71. package/dist/components/energy-breakdown.cjs +1 -1
  72. package/dist/components/energy-breakdown.cjs.map +1 -1
  73. package/dist/components/energy-breakdown.js +1 -1
  74. package/dist/components/energy-breakdown.js.map +1 -1
  75. package/dist/components/feed-in-hero.d.ts +1 -1
  76. package/dist/components/field.cjs +1 -1
  77. package/dist/components/field.d.cts +1 -1
  78. package/dist/components/field.d.ts +1 -1
  79. package/dist/components/field.js +1 -1
  80. package/dist/components/info-block.d.cts +1 -1
  81. package/dist/components/info-block.d.ts +1 -1
  82. package/dist/components/input-group.cjs +1 -1
  83. package/dist/components/input-group.js +1 -1
  84. package/dist/components/input-otp.cjs +1 -1
  85. package/dist/components/input-otp.js +1 -1
  86. package/dist/components/input.cjs +1 -1
  87. package/dist/components/input.d.cts +1 -1
  88. package/dist/components/input.d.ts +1 -1
  89. package/dist/components/input.js +1 -1
  90. package/dist/components/line-chart.cjs +11 -9
  91. package/dist/components/line-chart.cjs.map +1 -1
  92. package/dist/components/line-chart.js +11 -9
  93. package/dist/components/line-chart.js.map +1 -1
  94. package/dist/components/list.cjs +1 -1
  95. package/dist/components/list.cjs.map +1 -1
  96. package/dist/components/list.js +1 -1
  97. package/dist/components/list.js.map +1 -1
  98. package/dist/components/metering-row.d.ts +1 -1
  99. package/dist/components/money-saved-block.cjs +1 -1
  100. package/dist/components/money-saved-block.cjs.map +1 -1
  101. package/dist/components/money-saved-block.js +1 -1
  102. package/dist/components/money-saved-block.js.map +1 -1
  103. package/dist/components/number-flow.d.ts +1 -1
  104. package/dist/components/power-history-chart.cjs +9 -7
  105. package/dist/components/power-history-chart.cjs.map +1 -1
  106. package/dist/components/power-history-chart.js +9 -7
  107. package/dist/components/power-history-chart.js.map +1 -1
  108. package/dist/components/power-history.cjs +1 -1
  109. package/dist/components/power-history.cjs.map +1 -1
  110. package/dist/components/power-history.js +1 -1
  111. package/dist/components/power-history.js.map +1 -1
  112. package/dist/components/power-network.cjs +36 -11
  113. package/dist/components/power-network.cjs.map +1 -1
  114. package/dist/components/power-network.js +36 -11
  115. package/dist/components/power-network.js.map +1 -1
  116. package/dist/components/progress.cjs +1 -1
  117. package/dist/components/progress.cjs.map +1 -1
  118. package/dist/components/progress.js +1 -1
  119. package/dist/components/progress.js.map +1 -1
  120. package/dist/components/radio-card-group.cjs +26 -1
  121. package/dist/components/radio-card-group.cjs.map +1 -1
  122. package/dist/components/radio-card-group.js +26 -1
  123. package/dist/components/radio-card-group.js.map +1 -1
  124. package/dist/components/radio.cjs +11 -4
  125. package/dist/components/radio.cjs.map +1 -1
  126. package/dist/components/radio.d.cts +15 -3
  127. package/dist/components/radio.d.ts +15 -3
  128. package/dist/components/radio.js +11 -4
  129. package/dist/components/radio.js.map +1 -1
  130. package/dist/components/sankey-chart.cjs +4 -4
  131. package/dist/components/sankey-chart.cjs.map +1 -1
  132. package/dist/components/sankey-chart.d.ts +1 -1
  133. package/dist/components/sankey-chart.js +4 -4
  134. package/dist/components/sankey-chart.js.map +1 -1
  135. package/dist/components/schedule-list.cjs +3 -3
  136. package/dist/components/schedule-list.cjs.map +1 -1
  137. package/dist/components/schedule-list.js +3 -3
  138. package/dist/components/schedule-list.js.map +1 -1
  139. package/dist/components/segmented-control.cjs +2 -2
  140. package/dist/components/segmented-control.cjs.map +1 -1
  141. package/dist/components/segmented-control.d.cts +1 -1
  142. package/dist/components/segmented-control.d.ts +1 -1
  143. package/dist/components/segmented-control.js +2 -2
  144. package/dist/components/segmented-control.js.map +1 -1
  145. package/dist/components/select.cjs +1 -1
  146. package/dist/components/select.d.cts +1 -1
  147. package/dist/components/select.d.ts +1 -1
  148. package/dist/components/select.js +1 -1
  149. package/dist/components/series-legend.cjs +1 -1
  150. package/dist/components/series-legend.cjs.map +1 -1
  151. package/dist/components/series-legend.js +1 -1
  152. package/dist/components/series-legend.js.map +1 -1
  153. package/dist/components/slider.cjs +6 -19
  154. package/dist/components/slider.cjs.map +1 -1
  155. package/dist/components/slider.d.cts +0 -13
  156. package/dist/components/slider.d.ts +0 -13
  157. package/dist/components/slider.js +6 -19
  158. package/dist/components/slider.js.map +1 -1
  159. package/dist/components/stepper.cjs +2 -2
  160. package/dist/components/stepper.cjs.map +1 -1
  161. package/dist/components/stepper.js +2 -2
  162. package/dist/components/stepper.js.map +1 -1
  163. package/dist/components/switch.cjs +8 -3
  164. package/dist/components/switch.cjs.map +1 -1
  165. package/dist/components/switch.d.cts +9 -4
  166. package/dist/components/switch.d.ts +9 -4
  167. package/dist/components/switch.js +8 -3
  168. package/dist/components/switch.js.map +1 -1
  169. package/dist/components/tabs.cjs +4 -4
  170. package/dist/components/tabs.cjs.map +1 -1
  171. package/dist/components/tabs.js +4 -4
  172. package/dist/components/tabs.js.map +1 -1
  173. package/dist/components/theme.cjs +1 -1
  174. package/dist/components/theme.d.cts +1 -1
  175. package/dist/components/theme.d.ts +1 -1
  176. package/dist/components/theme.js +1 -1
  177. package/dist/components/time-picker.cjs +1 -1
  178. package/dist/components/time-picker.cjs.map +1 -1
  179. package/dist/components/time-picker.js +1 -1
  180. package/dist/components/time-picker.js.map +1 -1
  181. package/dist/hooks/use-reduced-motion.cjs +22 -0
  182. package/dist/hooks/use-reduced-motion.cjs.map +1 -0
  183. package/dist/hooks/use-reduced-motion.d.cts +7 -0
  184. package/dist/hooks/use-reduced-motion.d.ts +7 -0
  185. package/dist/hooks/use-reduced-motion.js +20 -0
  186. package/dist/hooks/use-reduced-motion.js.map +1 -0
  187. package/dist/{input-box-variants-Dr1K7uYE.js → input-box-variants-DcajYXvo.js} +1 -1
  188. package/dist/{input-box-variants-Dr1K7uYE.js.map → input-box-variants-DcajYXvo.js.map} +1 -1
  189. package/dist/{input-box-variants-BMDdwvqg.cjs → input-box-variants-ZCtgs-1S.cjs} +1 -1
  190. package/dist/{input-box-variants-BMDdwvqg.cjs.map → input-box-variants-ZCtgs-1S.cjs.map} +1 -1
  191. package/dist/{number-flow-DSbucQ_K.d.ts → number-flow-D9zsxH0-.d.ts} +1 -1
  192. package/dist/styles/index.css +4 -2
  193. package/dist/styles/spark-default.css +78 -0
  194. package/dist/{theme-C19BbKfO.js → theme-8PDO9E0S.js} +1 -1
  195. package/dist/{theme-C19BbKfO.js.map → theme-8PDO9E0S.js.map} +1 -1
  196. package/dist/{theme-CfFWrMEF.cjs → theme-ClRJhexF.cjs} +1 -1
  197. package/dist/{theme-CfFWrMEF.cjs.map → theme-ClRJhexF.cjs.map} +1 -1
  198. package/dist/{theme-types-DoROIXpi.d.ts → theme-types-BDdoRxXa.d.ts} +2 -3
  199. package/dist/{theme-types-r20EJfEC.d.cts → theme-types-BwSJKdsB.d.cts} +2 -3
  200. package/dist/{tones-DyCkL71h.d.ts → tones-PXJGlSpe.d.ts} +1 -1
  201. package/package.json +1 -1
@@ -20,7 +20,7 @@ function SegmentedControl({ className, styleVariant = "solid", size = "default",
20
20
  children: [/* @__PURE__ */ jsx(Tabs.Indicator, {
21
21
  "data-slot": "segmented-control-indicator",
22
22
  renderBeforeHydration: true,
23
- className: cn("pointer-events-none absolute top-[var(--active-tab-top)] left-[var(--active-tab-left)] z-0 h-[var(--active-tab-height)] w-[var(--active-tab-width)]", "rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]", "bg-gray-1 dark:bg-gray-a4", "group-data-[style=solid]/segmented:bg-(--spark-style-bg,var(--spark-9))", "shadow-[0_1px_2px_0_rgb(0_0_0/0.06),inset_0_0_0_var(--spark-style-border-width,1px)_var(--spark-style-border,transparent)]", "transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none", "[&[data-starting-style]]:transition-none")
23
+ className: cn("pointer-events-none absolute top-(--active-tab-top) left-(--active-tab-left) z-0 h-(--active-tab-height) w-(--active-tab-width)", "rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]", "bg-gray-1 dark:bg-gray-a4", "group-data-[style=solid]/segmented:bg-(--spark-style-bg,var(--spark-9))", "shadow-[0_1px_2px_0_rgb(0_0_0/0.06),inset_0_0_0_var(--spark-style-border-width,1px)_var(--spark-style-border,transparent)]", "transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none", "data-starting-style:transition-none")
24
24
  }), children]
25
25
  })
26
26
  });
@@ -29,7 +29,7 @@ function SegmentedControlItem({ className, children, ref, ...props }) {
29
29
  return /* @__PURE__ */ jsx(Tabs.Tab, {
30
30
  "data-slot": "segmented-control-item",
31
31
  ref,
32
- className: cn("relative z-10 inline-flex h-full flex-1 basis-0 cursor-pointer items-center justify-center gap-1.5 font-medium whitespace-nowrap select-none", "rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]", "text-gray-a11 transition-colors motion-reduce:transition-none", "not-data-active:hover:text-gray-12", "data-active:text-(--spark-style-fg,var(--spark-contrast))", "focus-visible:ring-2 focus-visible:outline-hidden focus-visible:ring-inset", "data-disabled:pointer-events-none data-disabled:text-gray-a8", "[&_svg]:pointer-events-none [&_svg]:shrink-0", "group-data-[size=small]/segmented:px-3 group-data-[size=small]/segmented:[--spark-icon-size:1rem] group-data-[size=small]/segmented:[&_svg:not([class*=size-])]:size-4", "group-data-[size=default]/segmented:px-3 group-data-[size=default]/segmented:[--spark-icon-size:1.25rem] group-data-[size=default]/segmented:[&_svg:not([class*=size-])]:size-5", "group-data-[size=medium]/segmented:px-4 group-data-[size=medium]/segmented:[--spark-icon-size:1.5rem] group-data-[size=medium]/segmented:[&_svg:not([class*=size-])]:size-6", className),
32
+ className: cn("relative z-10 inline-flex h-full flex-1 basis-0 cursor-pointer items-center justify-center gap-1.5 font-medium whitespace-nowrap select-none", "rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]", "text-gray-a11 transition-colors motion-reduce:transition-none", "not-data-active:hover:text-gray-12", "data-active:text-(--spark-style-fg,var(--spark-contrast))", "focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-hidden", "data-disabled:pointer-events-none data-disabled:text-gray-a8", "[&_svg]:pointer-events-none [&_svg]:shrink-0", "group-data-[size=small]/segmented:px-3 group-data-[size=small]/segmented:[--spark-icon-size:1rem] group-data-[size=small]/segmented:[&_svg:not([class*=size-])]:size-4", "group-data-[size=default]/segmented:px-3 group-data-[size=default]/segmented:[--spark-icon-size:1.25rem] group-data-[size=default]/segmented:[&_svg:not([class*=size-])]:size-5", "group-data-[size=medium]/segmented:px-4 group-data-[size=medium]/segmented:[--spark-icon-size:1.5rem] group-data-[size=medium]/segmented:[&_svg:not([class*=size-])]:size-6", className),
33
33
  ...props,
34
34
  children
35
35
  });
@@ -1 +1 @@
1
- {"version":3,"file":"segmented-control.js","names":["TabsPrimitive"],"sources":["../../src/components/segmented-control.tsx"],"sourcesContent":["'use client'\n\nimport { Tabs as TabsPrimitive } from '@base-ui/react/tabs'\nimport * as React from 'react'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\ntype SegmentedControlSize = 'small' | 'default' | 'medium'\n\ntype SegmentedControlProps = Omit<\n React.ComponentProps<typeof TabsPrimitive.Root>,\n 'orientation'\n> & {\n /** Visual weight of the selected segment, following the Spark style axis. */\n styleVariant?: Exclude<SparkStyle, 'ghost'>\n /** Control height, padding, and typography. Matches the Button size scale. */\n size?: SegmentedControlSize\n}\n\nfunction SegmentedControl({\n className,\n styleVariant = 'solid',\n size = 'default',\n children,\n ref,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n ...props\n}: SegmentedControlProps) {\n return (\n <TabsPrimitive.Root data-slot=\"segmented-control\" ref={ref} {...props}>\n <TabsPrimitive.List\n // the group's accessible name belongs on role=tablist (the List), not\n // the Root container\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n data-size={size}\n data-slot=\"segmented-control-track\"\n data-style={styleVariant}\n className={cn(\n // full-width control; segments share the width equally (flex-1 below)\n 'group/segmented relative isolate flex w-full items-stretch p-1',\n 'rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))]',\n // the track chrome follows the style: a filled groove for solid/soft, a\n // faintly-filled bordered surface, or a bare outline (all neutral — the\n // accent lives on the selected segment)\n 'data-[style=soft]:bg-gray-a3 data-[style=solid]:bg-gray-a3',\n 'data-[style=surface]:bg-gray-a2 data-[style=surface]:inset-ring data-[style=surface]:inset-ring-(--spark-style-border)',\n 'data-[style=outline]:inset-ring data-[style=outline]:inset-ring-(--spark-style-border)',\n size === 'small' && 'h-9 text-sm',\n size === 'default' && 'h-10 text-base',\n size === 'medium' && 'h-11 text-base',\n className,\n )}\n >\n {/* neutral like the switch thumb; solid alone fills with the accent below */}\n <TabsPrimitive.Indicator\n data-slot=\"segmented-control-indicator\"\n renderBeforeHydration\n className={cn(\n 'pointer-events-none absolute top-[var(--active-tab-top)] left-[var(--active-tab-left)] z-0 h-[var(--active-tab-height)] w-[var(--active-tab-width)]',\n 'rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]',\n 'bg-gray-1 dark:bg-gray-a4',\n 'group-data-[style=solid]/segmented:bg-(--spark-style-bg,var(--spark-9))',\n 'shadow-[0_1px_2px_0_rgb(0_0_0/0.06),inset_0_0_0_var(--spark-style-border-width,1px)_var(--spark-style-border,transparent)]',\n 'transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none',\n // suppress the corner-to-position slide on first mount\n '[&[data-starting-style]]:transition-none',\n )}\n />\n {children}\n </TabsPrimitive.List>\n </TabsPrimitive.Root>\n )\n}\n\ntype SegmentedControlItemProps = React.ComponentProps<typeof TabsPrimitive.Tab>\n\nfunction SegmentedControlItem({\n className,\n children,\n ref,\n ...props\n}: SegmentedControlItemProps) {\n return (\n <TabsPrimitive.Tab\n data-slot=\"segmented-control-item\"\n ref={ref}\n className={cn(\n 'relative z-10 inline-flex h-full flex-1 basis-0 cursor-pointer items-center justify-center gap-1.5 font-medium whitespace-nowrap select-none',\n 'rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]',\n 'text-gray-a11 transition-colors motion-reduce:transition-none',\n 'not-data-active:hover:text-gray-12',\n 'data-active:text-(--spark-style-fg,var(--spark-contrast))',\n // packed segments: an offset ring would collide with neighbours, so the\n // ring sits inset within each segment\n 'focus-visible:ring-2 focus-visible:outline-hidden focus-visible:ring-inset',\n 'data-disabled:pointer-events-none data-disabled:text-gray-a8',\n '[&_svg]:pointer-events-none [&_svg]:shrink-0',\n // size follows the Button scale (padding + icon size). Icon size is set\n // via --spark-icon-size (font glyphs) plus size-* (raw svg).\n 'group-data-[size=small]/segmented:px-3 group-data-[size=small]/segmented:[--spark-icon-size:1rem] group-data-[size=small]/segmented:[&_svg:not([class*=size-])]:size-4',\n 'group-data-[size=default]/segmented:px-3 group-data-[size=default]/segmented:[--spark-icon-size:1.25rem] group-data-[size=default]/segmented:[&_svg:not([class*=size-])]:size-5',\n 'group-data-[size=medium]/segmented:px-4 group-data-[size=medium]/segmented:[--spark-icon-size:1.5rem] group-data-[size=medium]/segmented:[&_svg:not([class*=size-])]:size-6',\n className,\n )}\n {...props}\n >\n {children}\n </TabsPrimitive.Tab>\n )\n}\n\nexport { SegmentedControl, SegmentedControlItem }\nexport type {\n SegmentedControlItemProps,\n SegmentedControlProps,\n SegmentedControlSize,\n}\n"],"mappings":";;;;;;;AAmBA,SAAS,iBAAiB,EACxB,WACA,eAAe,SACf,OAAO,WACP,UACA,KACA,cAAc,WACd,mBAAmB,gBACnB,GAAG,SACqB;AACxB,QACE,oBAACA,KAAc,MAAf;EAAoB,aAAU;EAAyB;EAAK,GAAI;YAC9D,qBAACA,KAAc,MAAf;GAGE,cAAY;GACZ,mBAAiB;GACjB,aAAW;GACX,aAAU;GACV,cAAY;GACZ,WAAW,GAET,kEACA,oEAIA,8DACA,0HACA,0FACA,SAAS,WAAW,eACpB,SAAS,aAAa,kBACtB,SAAS,YAAY,kBACrB,UACD;aAtBH,CAyBE,oBAACA,KAAc,WAAf;IACE,aAAU;IACV,uBAAA;IACA,WAAW,GACT,uJACA,oEACA,6BACA,2EACA,8HACA,0FAEA,2CACD;IACD,CAAA,EACD,SACkB;;EACF,CAAA;;AAMzB,SAAS,qBAAqB,EAC5B,WACA,UACA,KACA,GAAG,SACyB;AAC5B,QACE,oBAACA,KAAc,KAAf;EACE,aAAU;EACL;EACL,WAAW,GACT,gJACA,oEACA,iEACA,sCACA,6DAGA,8EACA,gEACA,gDAGA,0KACA,mLACA,+KACA,UACD;EACD,GAAI;EAEH;EACiB,CAAA"}
1
+ {"version":3,"file":"segmented-control.js","names":["TabsPrimitive"],"sources":["../../src/components/segmented-control.tsx"],"sourcesContent":["'use client'\n\nimport { Tabs as TabsPrimitive } from '@base-ui/react/tabs'\nimport * as React from 'react'\nimport type { SparkStyle } from '../lib/theme-types'\nimport { cn } from '../utils/cn'\n\ntype SegmentedControlSize = 'small' | 'default' | 'medium'\n\ntype SegmentedControlProps = Omit<\n React.ComponentProps<typeof TabsPrimitive.Root>,\n 'orientation'\n> & {\n /** Visual weight of the selected segment, following the Spark style axis. */\n styleVariant?: Exclude<SparkStyle, 'ghost'>\n /** Control height, padding, and typography. Matches the Button size scale. */\n size?: SegmentedControlSize\n}\n\nfunction SegmentedControl({\n className,\n styleVariant = 'solid',\n size = 'default',\n children,\n ref,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n ...props\n}: SegmentedControlProps) {\n return (\n <TabsPrimitive.Root data-slot=\"segmented-control\" ref={ref} {...props}>\n <TabsPrimitive.List\n // the group's accessible name belongs on role=tablist (the List), not\n // the Root container\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n data-size={size}\n data-slot=\"segmented-control-track\"\n data-style={styleVariant}\n className={cn(\n // full-width control; segments share the width equally (flex-1 below)\n 'group/segmented relative isolate flex w-full items-stretch p-1',\n 'rounded-[max(var(--spark-rounded-md),var(--spark-rounded-full))]',\n // the track chrome follows the style: a filled groove for solid/soft, a\n // faintly-filled bordered surface, or a bare outline (all neutral — the\n // accent lives on the selected segment)\n 'data-[style=soft]:bg-gray-a3 data-[style=solid]:bg-gray-a3',\n 'data-[style=surface]:bg-gray-a2 data-[style=surface]:inset-ring data-[style=surface]:inset-ring-(--spark-style-border)',\n 'data-[style=outline]:inset-ring data-[style=outline]:inset-ring-(--spark-style-border)',\n size === 'small' && 'h-9 text-sm',\n size === 'default' && 'h-10 text-base',\n size === 'medium' && 'h-11 text-base',\n className,\n )}\n >\n {/* neutral like the switch thumb; solid alone fills with the accent below */}\n <TabsPrimitive.Indicator\n data-slot=\"segmented-control-indicator\"\n renderBeforeHydration\n className={cn(\n 'pointer-events-none absolute top-(--active-tab-top) left-(--active-tab-left) z-0 h-(--active-tab-height) w-(--active-tab-width)',\n 'rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]',\n 'bg-gray-1 dark:bg-gray-a4',\n 'group-data-[style=solid]/segmented:bg-(--spark-style-bg,var(--spark-9))',\n 'shadow-[0_1px_2px_0_rgb(0_0_0/0.06),inset_0_0_0_var(--spark-style-border-width,1px)_var(--spark-style-border,transparent)]',\n 'transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none',\n // suppress the corner-to-position slide on first mount\n 'data-starting-style:transition-none',\n )}\n />\n {children}\n </TabsPrimitive.List>\n </TabsPrimitive.Root>\n )\n}\n\ntype SegmentedControlItemProps = React.ComponentProps<typeof TabsPrimitive.Tab>\n\nfunction SegmentedControlItem({\n className,\n children,\n ref,\n ...props\n}: SegmentedControlItemProps) {\n return (\n <TabsPrimitive.Tab\n data-slot=\"segmented-control-item\"\n ref={ref}\n className={cn(\n 'relative z-10 inline-flex h-full flex-1 basis-0 cursor-pointer items-center justify-center gap-1.5 font-medium whitespace-nowrap select-none',\n 'rounded-[max(var(--spark-rounded-sm),var(--spark-rounded-full))]',\n 'text-gray-a11 transition-colors motion-reduce:transition-none',\n 'not-data-active:hover:text-gray-12',\n 'data-active:text-(--spark-style-fg,var(--spark-contrast))',\n // ring-offset-1 floats the ring off the segment (a flush ring vanishes\n // on the solid indicator; a full inset box reads heavy)\n 'focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-hidden',\n 'data-disabled:pointer-events-none data-disabled:text-gray-a8',\n '[&_svg]:pointer-events-none [&_svg]:shrink-0',\n // size follows the Button scale (padding + icon size). Icon size is set\n // via --spark-icon-size (font glyphs) plus size-* (raw svg).\n 'group-data-[size=small]/segmented:px-3 group-data-[size=small]/segmented:[--spark-icon-size:1rem] group-data-[size=small]/segmented:[&_svg:not([class*=size-])]:size-4',\n 'group-data-[size=default]/segmented:px-3 group-data-[size=default]/segmented:[--spark-icon-size:1.25rem] group-data-[size=default]/segmented:[&_svg:not([class*=size-])]:size-5',\n 'group-data-[size=medium]/segmented:px-4 group-data-[size=medium]/segmented:[--spark-icon-size:1.5rem] group-data-[size=medium]/segmented:[&_svg:not([class*=size-])]:size-6',\n className,\n )}\n {...props}\n >\n {children}\n </TabsPrimitive.Tab>\n )\n}\n\nexport { SegmentedControl, SegmentedControlItem }\nexport type {\n SegmentedControlItemProps,\n SegmentedControlProps,\n SegmentedControlSize,\n}\n"],"mappings":";;;;;;;AAmBA,SAAS,iBAAiB,EACxB,WACA,eAAe,SACf,OAAO,WACP,UACA,KACA,cAAc,WACd,mBAAmB,gBACnB,GAAG,SACqB;AACxB,QACE,oBAACA,KAAc,MAAf;EAAoB,aAAU;EAAyB;EAAK,GAAI;YAC9D,qBAACA,KAAc,MAAf;GAGE,cAAY;GACZ,mBAAiB;GACjB,aAAW;GACX,aAAU;GACV,cAAY;GACZ,WAAW,GAET,kEACA,oEAIA,8DACA,0HACA,0FACA,SAAS,WAAW,eACpB,SAAS,aAAa,kBACtB,SAAS,YAAY,kBACrB,UACD;aAtBH,CAyBE,oBAACA,KAAc,WAAf;IACE,aAAU;IACV,uBAAA;IACA,WAAW,GACT,mIACA,oEACA,6BACA,2EACA,8HACA,0FAEA,sCACD;IACD,CAAA,EACD,SACkB;;EACF,CAAA;;AAMzB,SAAS,qBAAqB,EAC5B,WACA,UACA,KACA,GAAG,SACyB;AAC5B,QACE,oBAACA,KAAc,KAAf;EACE,aAAU;EACL;EACL,WAAW,GACT,gJACA,oEACA,iEACA,sCACA,6DAGA,iFACA,gEACA,gDAGA,0KACA,mLACA,+KACA,UACD;EACD,GAAI;EAEH;EACiB,CAAA"}
@@ -4,7 +4,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
4
  const require_chunk = require("../chunk-aJGBMT86.cjs");
5
5
  const require_icons_material_symbol = require("../icons/material-symbol.cjs");
6
6
  const require_components_field = require("./field.cjs");
7
- const require_input_box_variants = require("../input-box-variants-BMDdwvqg.cjs");
7
+ const require_input_box_variants = require("../input-box-variants-ZCtgs-1S.cjs");
8
8
  let react = require("react");
9
9
  react = require_chunk.__toESM(react);
10
10
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { a as SparkInputStyle } from "../theme-types-r20EJfEC.cjs";
3
+ import { i as SparkInputStyle } from "../theme-types-BwSJKdsB.cjs";
4
4
  import * as _$react_jsx_runtime0 from "react/jsx-runtime";
5
5
  import * as React$1 from "react";
6
6
  import { Select as Select$1 } from "@base-ui/react/select";
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { a as SparkInputStyle } from "../theme-types-DoROIXpi.js";
3
+ import { i as SparkInputStyle } from "../theme-types-BDdoRxXa.js";
4
4
  import * as React$1 from "react";
5
5
  import * as _$react_jsx_runtime0 from "react/jsx-runtime";
6
6
  import { Select as Select$1 } from "@base-ui/react/select";
@@ -3,7 +3,7 @@
3
3
  import { cn } from "../utils/cn.js";
4
4
  import { MaterialSymbol } from "../icons/material-symbol.js";
5
5
  import { useFieldControl } from "./field.js";
6
- import { n as boxChrome } from "../input-box-variants-Dr1K7uYE.js";
6
+ import { n as boxChrome } from "../input-box-variants-DcajYXvo.js";
7
7
  import "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  import { Select as Select$1 } from "@base-ui/react/select";
@@ -16,7 +16,7 @@ function SeriesLegend({ ariaLabel = "Filter data series", className, hiddenIds,
16
16
  onClick: () => onToggle(item.id),
17
17
  "aria-pressed": !hidden,
18
18
  "aria-label": `${item.label}, ${hidden ? "hidden" : "shown"}`,
19
- className: (0, cnfast.cn)("flex cursor-pointer items-center gap-1.5 rounded-sm text-xs text-gray-light transition-opacity hover:text-gray focus-visible:ring focus-visible:ring-offset-2 focus-visible:outline-hidden", hidden && "opacity-40"),
19
+ className: (0, cnfast.cn)("flex cursor-pointer items-center gap-1.5 rounded-sm text-xs text-gray-light transition-opacity hover:text-gray focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden", hidden && "opacity-40"),
20
20
  children: [item.marker === "dashed-line" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
21
21
  "aria-hidden": "true",
22
22
  className: "w-3 shrink-0 border-t-2 border-dashed",
@@ -1 +1 @@
1
- {"version":3,"file":"series-legend.cjs","names":[],"sources":["../../src/components/series-legend.tsx"],"sourcesContent":["import { cn } from '../utils/cn'\n\nexport interface SeriesLegendItem {\n id: string\n label: string\n /** CSS color value applied inline (e.g. `var(--orange-a9)` or `#f00`). */\n color: string\n /** Swatch shape: `dot` (default) for bar/area series, `dashed-line` for line overlays. */\n marker?: 'dot' | 'dashed-line'\n}\n\ninterface SeriesLegendProps {\n items: SeriesLegendItem[]\n hiddenIds: ReadonlySet<string>\n onToggle: (id: string) => void\n className?: string\n /** Accessible label announced for the legend group. */\n ariaLabel?: string\n}\n\nexport function SeriesLegend({\n ariaLabel = 'Filter data series',\n className,\n hiddenIds,\n items,\n onToggle,\n}: SeriesLegendProps) {\n return (\n <div\n role=\"group\"\n aria-label={ariaLabel}\n className={cn('flex flex-wrap gap-x-4 gap-y-1.5', className)}\n >\n {items.map((item) => {\n const hidden = hiddenIds.has(item.id)\n return (\n <button\n key={item.id}\n type=\"button\"\n onClick={() => onToggle(item.id)}\n aria-pressed={!hidden}\n aria-label={`${item.label}, ${hidden ? 'hidden' : 'shown'}`}\n className={cn(\n 'flex cursor-pointer items-center gap-1.5 rounded-sm text-xs text-gray-light transition-opacity hover:text-gray focus-visible:ring focus-visible:ring-offset-2 focus-visible:outline-hidden',\n hidden && 'opacity-40',\n )}\n >\n {item.marker === 'dashed-line' ? (\n <span\n aria-hidden=\"true\"\n className=\"w-3 shrink-0 border-t-2 border-dashed\"\n style={{ borderColor: item.color }}\n />\n ) : (\n <span\n aria-hidden=\"true\"\n className=\"size-2.5 shrink-0 rounded-circle\"\n style={{ backgroundColor: item.color }}\n />\n )}\n <span className={cn(hidden && 'line-through')}>{item.label}</span>\n </button>\n )\n })}\n </div>\n )\n}\n"],"mappings":";;;;;;AAoBA,SAAgB,aAAa,EAC3B,YAAY,sBACZ,WACA,WACA,OACA,YACoB;AACpB,QACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,MAAK;EACL,cAAY;EACZ,YAAA,GAAA,OAAA,IAAc,oCAAoC,UAAU;YAE3D,MAAM,KAAK,SAAS;GACnB,MAAM,SAAS,UAAU,IAAI,KAAK,GAAG;AACrC,UACE,iBAAA,GAAA,kBAAA,MAAC,UAAD;IAEE,MAAK;IACL,eAAe,SAAS,KAAK,GAAG;IAChC,gBAAc,CAAC;IACf,cAAY,GAAG,KAAK,MAAM,IAAI,SAAS,WAAW;IAClD,YAAA,GAAA,OAAA,IACE,8LACA,UAAU,aACX;cATH,CAWG,KAAK,WAAW,gBACf,iBAAA,GAAA,kBAAA,KAAC,QAAD;KACE,eAAY;KACZ,WAAU;KACV,OAAO,EAAE,aAAa,KAAK,OAAO;KAClC,CAAA,GAEF,iBAAA,GAAA,kBAAA,KAAC,QAAD;KACE,eAAY;KACZ,WAAU;KACV,OAAO,EAAE,iBAAiB,KAAK,OAAO;KACtC,CAAA,EAEJ,iBAAA,GAAA,kBAAA,KAAC,QAAD;KAAM,YAAA,GAAA,OAAA,IAAc,UAAU,eAAe;eAAG,KAAK;KAAa,CAAA,CAC3D;MAxBF,KAAK,GAwBH;IAEX;EACE,CAAA"}
1
+ {"version":3,"file":"series-legend.cjs","names":[],"sources":["../../src/components/series-legend.tsx"],"sourcesContent":["import { cn } from '../utils/cn'\n\nexport interface SeriesLegendItem {\n id: string\n label: string\n /** CSS color value applied inline (e.g. `var(--orange-a9)` or `#f00`). */\n color: string\n /** Swatch shape: `dot` (default) for bar/area series, `dashed-line` for line overlays. */\n marker?: 'dot' | 'dashed-line'\n}\n\ninterface SeriesLegendProps {\n items: SeriesLegendItem[]\n hiddenIds: ReadonlySet<string>\n onToggle: (id: string) => void\n className?: string\n /** Accessible label announced for the legend group. */\n ariaLabel?: string\n}\n\nexport function SeriesLegend({\n ariaLabel = 'Filter data series',\n className,\n hiddenIds,\n items,\n onToggle,\n}: SeriesLegendProps) {\n return (\n <div\n role=\"group\"\n aria-label={ariaLabel}\n className={cn('flex flex-wrap gap-x-4 gap-y-1.5', className)}\n >\n {items.map((item) => {\n const hidden = hiddenIds.has(item.id)\n return (\n <button\n key={item.id}\n type=\"button\"\n onClick={() => onToggle(item.id)}\n aria-pressed={!hidden}\n aria-label={`${item.label}, ${hidden ? 'hidden' : 'shown'}`}\n className={cn(\n 'flex cursor-pointer items-center gap-1.5 rounded-sm text-xs text-gray-light transition-opacity hover:text-gray focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n hidden && 'opacity-40',\n )}\n >\n {item.marker === 'dashed-line' ? (\n <span\n aria-hidden=\"true\"\n className=\"w-3 shrink-0 border-t-2 border-dashed\"\n style={{ borderColor: item.color }}\n />\n ) : (\n <span\n aria-hidden=\"true\"\n className=\"size-2.5 shrink-0 rounded-circle\"\n style={{ backgroundColor: item.color }}\n />\n )}\n <span className={cn(hidden && 'line-through')}>{item.label}</span>\n </button>\n )\n })}\n </div>\n )\n}\n"],"mappings":";;;;;;AAoBA,SAAgB,aAAa,EAC3B,YAAY,sBACZ,WACA,WACA,OACA,YACoB;AACpB,QACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,MAAK;EACL,cAAY;EACZ,YAAA,GAAA,OAAA,IAAc,oCAAoC,UAAU;YAE3D,MAAM,KAAK,SAAS;GACnB,MAAM,SAAS,UAAU,IAAI,KAAK,GAAG;AACrC,UACE,iBAAA,GAAA,kBAAA,MAAC,UAAD;IAEE,MAAK;IACL,eAAe,SAAS,KAAK,GAAG;IAChC,gBAAc,CAAC;IACf,cAAY,GAAG,KAAK,MAAM,IAAI,SAAS,WAAW;IAClD,YAAA,GAAA,OAAA,IACE,gMACA,UAAU,aACX;cATH,CAWG,KAAK,WAAW,gBACf,iBAAA,GAAA,kBAAA,KAAC,QAAD;KACE,eAAY;KACZ,WAAU;KACV,OAAO,EAAE,aAAa,KAAK,OAAO;KAClC,CAAA,GAEF,iBAAA,GAAA,kBAAA,KAAC,QAAD;KACE,eAAY;KACZ,WAAU;KACV,OAAO,EAAE,iBAAiB,KAAK,OAAO;KACtC,CAAA,EAEJ,iBAAA,GAAA,kBAAA,KAAC,QAAD;KAAM,YAAA,GAAA,OAAA,IAAc,UAAU,eAAe;eAAG,KAAK;KAAa,CAAA,CAC3D;MAxBF,KAAK,GAwBH;IAEX;EACE,CAAA"}
@@ -14,7 +14,7 @@ function SeriesLegend({ ariaLabel = "Filter data series", className, hiddenIds,
14
14
  onClick: () => onToggle(item.id),
15
15
  "aria-pressed": !hidden,
16
16
  "aria-label": `${item.label}, ${hidden ? "hidden" : "shown"}`,
17
- className: cn("flex cursor-pointer items-center gap-1.5 rounded-sm text-xs text-gray-light transition-opacity hover:text-gray focus-visible:ring focus-visible:ring-offset-2 focus-visible:outline-hidden", hidden && "opacity-40"),
17
+ className: cn("flex cursor-pointer items-center gap-1.5 rounded-sm text-xs text-gray-light transition-opacity hover:text-gray focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden", hidden && "opacity-40"),
18
18
  children: [item.marker === "dashed-line" ? /* @__PURE__ */ jsx("span", {
19
19
  "aria-hidden": "true",
20
20
  className: "w-3 shrink-0 border-t-2 border-dashed",
@@ -1 +1 @@
1
- {"version":3,"file":"series-legend.js","names":[],"sources":["../../src/components/series-legend.tsx"],"sourcesContent":["import { cn } from '../utils/cn'\n\nexport interface SeriesLegendItem {\n id: string\n label: string\n /** CSS color value applied inline (e.g. `var(--orange-a9)` or `#f00`). */\n color: string\n /** Swatch shape: `dot` (default) for bar/area series, `dashed-line` for line overlays. */\n marker?: 'dot' | 'dashed-line'\n}\n\ninterface SeriesLegendProps {\n items: SeriesLegendItem[]\n hiddenIds: ReadonlySet<string>\n onToggle: (id: string) => void\n className?: string\n /** Accessible label announced for the legend group. */\n ariaLabel?: string\n}\n\nexport function SeriesLegend({\n ariaLabel = 'Filter data series',\n className,\n hiddenIds,\n items,\n onToggle,\n}: SeriesLegendProps) {\n return (\n <div\n role=\"group\"\n aria-label={ariaLabel}\n className={cn('flex flex-wrap gap-x-4 gap-y-1.5', className)}\n >\n {items.map((item) => {\n const hidden = hiddenIds.has(item.id)\n return (\n <button\n key={item.id}\n type=\"button\"\n onClick={() => onToggle(item.id)}\n aria-pressed={!hidden}\n aria-label={`${item.label}, ${hidden ? 'hidden' : 'shown'}`}\n className={cn(\n 'flex cursor-pointer items-center gap-1.5 rounded-sm text-xs text-gray-light transition-opacity hover:text-gray focus-visible:ring focus-visible:ring-offset-2 focus-visible:outline-hidden',\n hidden && 'opacity-40',\n )}\n >\n {item.marker === 'dashed-line' ? (\n <span\n aria-hidden=\"true\"\n className=\"w-3 shrink-0 border-t-2 border-dashed\"\n style={{ borderColor: item.color }}\n />\n ) : (\n <span\n aria-hidden=\"true\"\n className=\"size-2.5 shrink-0 rounded-circle\"\n style={{ backgroundColor: item.color }}\n />\n )}\n <span className={cn(hidden && 'line-through')}>{item.label}</span>\n </button>\n )\n })}\n </div>\n )\n}\n"],"mappings":";;;;AAoBA,SAAgB,aAAa,EAC3B,YAAY,sBACZ,WACA,WACA,OACA,YACoB;AACpB,QACE,oBAAC,OAAD;EACE,MAAK;EACL,cAAY;EACZ,WAAW,GAAG,oCAAoC,UAAU;YAE3D,MAAM,KAAK,SAAS;GACnB,MAAM,SAAS,UAAU,IAAI,KAAK,GAAG;AACrC,UACE,qBAAC,UAAD;IAEE,MAAK;IACL,eAAe,SAAS,KAAK,GAAG;IAChC,gBAAc,CAAC;IACf,cAAY,GAAG,KAAK,MAAM,IAAI,SAAS,WAAW;IAClD,WAAW,GACT,8LACA,UAAU,aACX;cATH,CAWG,KAAK,WAAW,gBACf,oBAAC,QAAD;KACE,eAAY;KACZ,WAAU;KACV,OAAO,EAAE,aAAa,KAAK,OAAO;KAClC,CAAA,GAEF,oBAAC,QAAD;KACE,eAAY;KACZ,WAAU;KACV,OAAO,EAAE,iBAAiB,KAAK,OAAO;KACtC,CAAA,EAEJ,oBAAC,QAAD;KAAM,WAAW,GAAG,UAAU,eAAe;eAAG,KAAK;KAAa,CAAA,CAC3D;MAxBF,KAAK,GAwBH;IAEX;EACE,CAAA"}
1
+ {"version":3,"file":"series-legend.js","names":[],"sources":["../../src/components/series-legend.tsx"],"sourcesContent":["import { cn } from '../utils/cn'\n\nexport interface SeriesLegendItem {\n id: string\n label: string\n /** CSS color value applied inline (e.g. `var(--orange-a9)` or `#f00`). */\n color: string\n /** Swatch shape: `dot` (default) for bar/area series, `dashed-line` for line overlays. */\n marker?: 'dot' | 'dashed-line'\n}\n\ninterface SeriesLegendProps {\n items: SeriesLegendItem[]\n hiddenIds: ReadonlySet<string>\n onToggle: (id: string) => void\n className?: string\n /** Accessible label announced for the legend group. */\n ariaLabel?: string\n}\n\nexport function SeriesLegend({\n ariaLabel = 'Filter data series',\n className,\n hiddenIds,\n items,\n onToggle,\n}: SeriesLegendProps) {\n return (\n <div\n role=\"group\"\n aria-label={ariaLabel}\n className={cn('flex flex-wrap gap-x-4 gap-y-1.5', className)}\n >\n {items.map((item) => {\n const hidden = hiddenIds.has(item.id)\n return (\n <button\n key={item.id}\n type=\"button\"\n onClick={() => onToggle(item.id)}\n aria-pressed={!hidden}\n aria-label={`${item.label}, ${hidden ? 'hidden' : 'shown'}`}\n className={cn(\n 'flex cursor-pointer items-center gap-1.5 rounded-sm text-xs text-gray-light transition-opacity hover:text-gray focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden',\n hidden && 'opacity-40',\n )}\n >\n {item.marker === 'dashed-line' ? (\n <span\n aria-hidden=\"true\"\n className=\"w-3 shrink-0 border-t-2 border-dashed\"\n style={{ borderColor: item.color }}\n />\n ) : (\n <span\n aria-hidden=\"true\"\n className=\"size-2.5 shrink-0 rounded-circle\"\n style={{ backgroundColor: item.color }}\n />\n )}\n <span className={cn(hidden && 'line-through')}>{item.label}</span>\n </button>\n )\n })}\n </div>\n )\n}\n"],"mappings":";;;;AAoBA,SAAgB,aAAa,EAC3B,YAAY,sBACZ,WACA,WACA,OACA,YACoB;AACpB,QACE,oBAAC,OAAD;EACE,MAAK;EACL,cAAY;EACZ,WAAW,GAAG,oCAAoC,UAAU;YAE3D,MAAM,KAAK,SAAS;GACnB,MAAM,SAAS,UAAU,IAAI,KAAK,GAAG;AACrC,UACE,qBAAC,UAAD;IAEE,MAAK;IACL,eAAe,SAAS,KAAK,GAAG;IAChC,gBAAc,CAAC;IACf,cAAY,GAAG,KAAK,MAAM,IAAI,SAAS,WAAW;IAClD,WAAW,GACT,gMACA,UAAU,aACX;cATH,CAWG,KAAK,WAAW,gBACf,oBAAC,QAAD;KACE,eAAY;KACZ,WAAU;KACV,OAAO,EAAE,aAAa,KAAK,OAAO;KAClC,CAAA,GAEF,oBAAC,QAAD;KACE,eAAY;KACZ,WAAU;KACV,OAAO,EAAE,iBAAiB,KAAK,OAAO;KACtC,CAAA,EAEJ,oBAAC,QAAD;KAAM,WAAW,GAAG,UAAU,eAAe;eAAG,KAAK;KAAa,CAAA,CAC3D;MAxBF,KAAK,GAwBH;IAEX;EACE,CAAA"}
@@ -102,7 +102,7 @@ Slider.displayName = "Slider";
102
102
  function SliderControl({ className, ...props }) {
103
103
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_slider.Slider.Control, {
104
104
  "data-slot": "slider-control",
105
- className: (0, cnfast.cn)("relative flex min-h-6 w-full touch-none items-center select-none", "data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-40 data-[orientation=vertical]:w-6 data-[orientation=vertical]:justify-center", "data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
105
+ className: (0, cnfast.cn)("relative flex min-h-6 w-full touch-none items-center select-none", "data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-40 data-[orientation=vertical]:w-6 data-[orientation=vertical]:justify-center", "data-disabled:pointer-events-none data-disabled:opacity-50", className),
106
106
  ...props
107
107
  });
108
108
  }
@@ -111,7 +111,7 @@ SliderControl.displayName = "SliderControl";
111
111
  function SliderTrack({ className, ...props }) {
112
112
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_slider.Slider.Track, {
113
113
  "data-slot": "slider-track",
114
- className: (0, cnfast.cn)("relative h-3 w-full rounded-[var(--spark-rounded-sm)] bg-gray-a4", "data-[orientation=vertical]:h-full data-[orientation=vertical]:w-3", className),
114
+ className: (0, cnfast.cn)("relative h-3 w-full rounded-(--spark-rounded-sm) bg-gray-a4", "data-[orientation=vertical]:h-full data-[orientation=vertical]:w-3", className),
115
115
  ...props
116
116
  });
117
117
  }
@@ -120,7 +120,7 @@ SliderTrack.displayName = "SliderTrack";
120
120
  function SliderIndicator({ className, ...props }) {
121
121
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_slider.Slider.Indicator, {
122
122
  "data-slot": "slider-indicator",
123
- className: (0, cnfast.cn)("rounded-[var(--spark-rounded-sm)] bg-[var(--spark-slider-range,var(--spark-9))]", className),
123
+ className: (0, cnfast.cn)("rounded-(--spark-rounded-sm) bg-(--spark-slider-range,var(--spark-9))", "transition-[width,height,inset-inline-start] duration-150 data-dragging:transition-none motion-reduce:transition-none", className),
124
124
  ...props
125
125
  });
126
126
  }
@@ -152,34 +152,21 @@ function SliderTicks({ className, ...props }) {
152
152
  const position = min + index * step;
153
153
  const pct = (position - min) / (max - min) * 100;
154
154
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
155
- className: (0, cnfast.cn)("absolute top-1/2 size-1 -translate-x-1/2 -translate-y-1/2 rounded-full", position >= bandLow && position <= bandHigh ? "bg-[var(--spark-slider-tick-on,var(--spark-on-solid,#fff))]" : "bg-gray-a8"),
155
+ className: (0, cnfast.cn)("absolute top-1/2 size-1 -translate-x-1/2 -translate-y-1/2 rounded-full", position >= bandLow && position <= bandHigh ? "bg-(--spark-slider-tick-on,var(--spark-on-solid,#fff))" : "bg-gray-a8"),
156
156
  style: { left: `${pct}%` }
157
157
  }, index);
158
158
  })
159
159
  });
160
160
  }
161
161
  SliderTicks.displayName = "SliderTicks";
162
- /**
163
- * The grab handle — a 16px accent knob. Corners follow the [data-radius] knob
164
- * (`--spark-rounded-lg`, matching the switch thumb): a circle at medium+, a
165
- * rounded square at small, a square at none. A background-colored separator ring
166
- * lifts it off the accent-filled range and a soft drop shadow adds depth; both
167
- * ride `--tw-shadow` so `focus-visible:ring` stays free. The invisible 24px hit
168
- * area meets the WCAG 2.5.8 target minimum.
169
- */
170
162
  function SliderThumb({ className, ...props }) {
171
163
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_slider.Slider.Thumb, {
172
164
  "data-slot": "slider-thumb",
173
- className: (0, cnfast.cn)("block size-4 shrink-0 rounded-[var(--spark-rounded-lg)] bg-[var(--spark-slider-range,var(--spark-9))]", "shadow-[0_0_0_2px_var(--spark-background,#fff),0_1px_2px_0_rgb(0_0_0/0.2)]", "before:absolute before:top-1/2 before:left-1/2 before:size-6 before:-translate-x-1/2 before:-translate-y-1/2 before:content-['']", "focus-visible:ring focus-visible:ring-offset-2 focus-visible:outline-hidden", "data-[dragging]:ring data-[dragging]:ring-offset-2", "disabled:pointer-events-none", className),
165
+ className: (0, cnfast.cn)("block size-4 shrink-0 rounded-(--spark-rounded-lg) bg-(--spark-slider-range,var(--spark-9))", "shadow-[0_0_0_2px_var(--spark-background,#fff),0_1px_2px_0_rgb(0_0_0/0.2)]", "before:absolute before:top-1/2 before:left-1/2 before:size-6 before:-translate-x-1/2 before:-translate-y-1/2 before:content-['']", "outline-hidden has-[input:focus-visible]:ring-2 has-[input:focus-visible]:ring-offset-2", "data-dragging:ring-2 data-dragging:ring-offset-2", "transition-[inset-inline-start,top,box-shadow] duration-150 data-dragging:transition-none motion-reduce:transition-none", "disabled:pointer-events-none", className),
174
166
  ...props
175
167
  });
176
168
  }
177
169
  SliderThumb.displayName = "SliderThumb";
178
- /**
179
- * Read-only value readout (`<output>`). Reads Base UI's own slider context, so
180
- * it stays formatted per the Root's `format`/`locale`. Pass a render function
181
- * for custom output, e.g. `{(f) => `${f[0]} €`}`.
182
- */
183
170
  function SliderValue({ className, ...props }) {
184
171
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_base_ui_react_slider.Slider.Value, {
185
172
  "data-slot": "slider-value",
@@ -253,7 +240,7 @@ function SliderInput({ className, index = 0, unit, disabled, onFocus, onBlur, on
253
240
  if (event.key === "Enter") event.currentTarget.blur();
254
241
  onKeyDown?.(event);
255
242
  },
256
- className: (0, cnfast.cn)("w-16 bg-transparent tabular-nums outline-hidden", "rounded-[var(--spark-rounded-sm)] focus-visible:ring focus-visible:ring-offset-2", "disabled:cursor-not-allowed disabled:opacity-50", "[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"),
243
+ className: (0, cnfast.cn)("w-16 bg-transparent tabular-nums outline-hidden", "rounded-(--spark-rounded-sm) focus-visible:ring-2 focus-visible:ring-offset-2", "disabled:cursor-not-allowed disabled:opacity-50", "[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"),
257
244
  ...props
258
245
  }), unit ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
259
246
  className: "text-sm text-gray",
@@ -1 +1 @@
1
- {"version":3,"file":"slider.cjs","names":["React","BaseSlider"],"sources":["../../src/components/slider.tsx"],"sourcesContent":["import { Slider as BaseSlider } from '@base-ui/react/slider'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\n\ntype SliderValue = number | number[]\n\ntype SliderVariant = 'default' | 'ticks'\n\n// Above this many steps the tick dots become a picket fence, so `variant=\"ticks\"`\n// silently stops drawing them (the continuous rail stays).\nconst MAX_TICKS = 24\n\n// Clamp to [min, max] then snap to the step grid (origin = min), trimming float\n// noise to the step's own decimal precision. `max` is always valid even if it\n// isn't a step multiple (matches Base UI).\nfunction snapToStep(\n value: number,\n min: number,\n max: number,\n step: number,\n): number {\n const clamped = Math.min(max, Math.max(min, value))\n\n if (!(step > 0)) {\n return clamped\n }\n\n const snapped = min + Math.round((clamped - min) / step) * step\n const bounded = Math.min(max, Math.max(min, snapped))\n const decimals = (String(step).split('.')[1] ?? '').length\n\n return decimals > 0 ? Number(bounded.toFixed(decimals)) : bounded\n}\n\n/**\n * Base UI's slider context is internal-only (not re-exported from\n * `@base-ui/react/slider`), so the editable `<SliderInput>` can't read the\n * current value from it. Instead `<Slider>` owns the value (controllable) and\n * shares it through this Spark context — keeping direct-input robust against\n * Base UI internal changes and letting inputs live anywhere in the subtree.\n */\ntype SliderContextValue = {\n values: readonly number[]\n min: number\n max: number\n step: number\n disabled: boolean\n /**\n * Write one thumb's value (from a `SliderInput`). Snaps to the step grid and\n * clamps; range values are kept sorted. Fires `onValueChange` only when the\n * value actually changes. When `commit` is set it also fires `onValueCommitted`\n * — but only if the committed value differs from `commitBaseline` (the value\n * when editing began), so a plain focus→blur never emits a spurious commit.\n */\n setThumbValue: (\n index: number,\n next: number,\n options?: { commit?: boolean; commitBaseline?: number },\n ) => void\n}\n\nconst SliderContext = React.createContext<SliderContextValue | null>(null)\n\nfunction useSliderContext(part: string): SliderContextValue {\n const ctx = React.useContext(SliderContext)\n\n if (!ctx) {\n throw new Error(`<${part}> must be rendered inside <Slider>`)\n }\n\n return ctx\n}\n\ntype SliderProps<Value extends SliderValue = SliderValue> = Omit<\n React.ComponentProps<typeof BaseSlider.Root>,\n 'value' | 'defaultValue' | 'onValueChange' | 'onValueCommitted' | 'render'\n> & {\n value?: Value\n defaultValue?: Value\n // Generic over the value shape: a single `number` keeps single-thumb handlers\n // number-typed, an array keeps range handlers array-typed — so callers don't\n // widen/narrow at every call site.\n onValueChange?: (\n value: Value,\n eventDetails: BaseSlider.Root.ChangeEventDetails,\n ) => void\n onValueCommitted?: (\n value: Value,\n eventDetails: BaseSlider.Root.CommitEventDetails,\n ) => void\n /**\n * `ticks` marks each step with a small dot on the rail — light on the accent\n * fill, neutral on the unfilled rail. Needs a sensible `step`; the dots are\n * hidden when the step count is < 2 or exceeds {@link MAX_TICKS}, and (in the\n * default render) for vertical sliders. Default `default`.\n */\n variant?: SliderVariant\n}\n\n/**\n * Root. Owns the value (controlled via `value` or uncontrolled via\n * `defaultValue`) and provides the Spark context. With no children it renders\n * the default single/range track (a childless-default, matching the library's\n * `*Close` idiom); pass children to compose `SliderInput` / `SliderValue` /\n * `SliderControl` yourself.\n */\nfunction Slider<Value extends SliderValue = SliderValue>({\n className,\n children,\n value,\n defaultValue,\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n orientation = 'horizontal',\n variant = 'default',\n onValueChange,\n onValueCommitted,\n // Radix positioned thumbs edge-aligned (inset within the track at min/max);\n // Base UI defaults to center-aligned (half the thumb overflows). `edge` keeps\n // the classic look and the thumb inside the rail.\n thumbAlignment = 'edge',\n // The accessible name belongs on the thumb's nested range input, not just the\n // Root — so keep it on the Root (names the group) AND forward it to the\n // childless-default thumb(s). When you compose your own thumbs, label them.\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n ...props\n}: SliderProps<Value>) {\n const isControlled = value !== undefined\n const [uncontrolled, setUncontrolled] = React.useState<SliderValue>(\n defaultValue ?? min,\n )\n const current = (isControlled ? value : uncontrolled) as SliderValue\n const values = React.useMemo(\n () => (Array.isArray(current) ? current : [current]),\n [current],\n )\n\n // Base UI hands back `number | readonly number[]`; we forward it as the\n // caller's `Value` (the runtime shape matches what they passed in).\n const emitChange = (\n next: number | readonly number[],\n eventDetails: BaseSlider.Root.ChangeEventDetails,\n ) => {\n if (!isControlled) {\n setUncontrolled(next as SliderValue)\n }\n\n onValueChange?.(next as Value, eventDetails)\n }\n\n // The direct-input write path. Snaps + clamps; for a range it swaps one thumb\n // and re-sorts (Base UI renders from a sorted copy, so an unsorted write would\n // desync the inputs from the thumbs). Fires onValueChange only on a real\n // change; fires onValueCommitted only when the committed value moved off the\n // pre-edit baseline.\n const setThumbValue = (\n index: number,\n next: number,\n options?: { commit?: boolean; commitBaseline?: number },\n ) => {\n const snapped = snapToStep(next, min, max, step)\n const wasArray = Array.isArray(current)\n let nextValue: SliderValue\n\n if (wasArray) {\n const copy = [...(current as number[])]\n copy[index] = snapped\n copy.sort((a, b) => a - b)\n nextValue = copy\n } else {\n nextValue = snapped\n }\n\n const changed = wasArray\n ? (nextValue as number[]).some((v, i) => v !== (current as number[])[i])\n : nextValue !== current\n\n // input-driven changes have no pointer/keyboard event; Base UI's own detail\n // object isn't constructible here, so we hand the consumer a minimal one.\n const details = {\n reason: 'input-change',\n } as unknown as BaseSlider.Root.ChangeEventDetails\n\n if (changed) {\n emitChange(nextValue, details)\n }\n\n if (options?.commit) {\n const committedChanged =\n options.commitBaseline === undefined\n ? changed\n : snapped !== options.commitBaseline\n\n if (committedChanged) {\n onValueCommitted?.(\n nextValue as Value,\n details as unknown as BaseSlider.Root.CommitEventDetails,\n )\n }\n }\n }\n\n // Rebuilt each render (cheap — <Slider> only re-renders on a value change) so\n // setThumbValue always closes over the current value + latest callbacks.\n const context: SliderContextValue = {\n values,\n min,\n max,\n step,\n disabled,\n setThumbValue,\n }\n\n // ticks are horizontal-only in the default render; SliderTicks self-hides when\n // the step count isn't countable, so no density check is needed here.\n const showTicks = variant === 'ticks' && orientation === 'horizontal'\n\n return (\n <SliderContext.Provider value={context}>\n <BaseSlider.Root\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n data-slot=\"slider\"\n value={current}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n orientation={orientation}\n thumbAlignment={thumbAlignment}\n onValueChange={emitChange}\n onValueCommitted={(next, eventDetails) =>\n onValueCommitted?.(next as Value, eventDetails)\n }\n className={cn(\n 'relative flex w-full flex-col gap-2 data-[orientation=vertical]:h-full data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-row',\n className,\n )}\n {...props}\n >\n {children ?? (\n <SliderControl>\n <SliderTrack>\n <SliderIndicator />\n {showTicks ? <SliderTicks /> : null}\n {values.map((_, index) => (\n <SliderThumb\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n index={values.length > 1 ? index : undefined}\n key={index}\n />\n ))}\n </SliderTrack>\n </SliderControl>\n )}\n </BaseSlider.Root>\n </SliderContext.Provider>\n )\n}\n\nSlider.displayName = 'Slider'\n\n/**\n * The interactive, draggable surface. A pointer-press anywhere on it moves the\n * nearest thumb (Base UI's track-press), so its full band is the target — kept\n * at ≥24px tall (WCAG 2.5.8) with the thin rail centered.\n */\nfunction SliderControl({\n className,\n ...props\n}: React.ComponentProps<typeof BaseSlider.Control>) {\n return (\n <BaseSlider.Control\n data-slot=\"slider-control\"\n className={cn(\n 'relative flex min-h-6 w-full touch-none items-center select-none',\n 'data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-40 data-[orientation=vertical]:w-6 data-[orientation=vertical]:justify-center',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className,\n )}\n {...props}\n />\n )\n}\n\nSliderControl.displayName = 'SliderControl'\n\n/** The rail — the full extent, neutral at rest. Holds the Indicator + Thumb(s). */\nfunction SliderTrack({\n className,\n ...props\n}: React.ComponentProps<typeof BaseSlider.Track>) {\n return (\n <BaseSlider.Track\n data-slot=\"slider-track\"\n className={cn(\n // 12px rail so the corner radius is legible; follows the [data-radius] knob\n // (square at none → pill at large/full). no overflow-hidden: the thumb is a\n // child and would be clipped.\n 'relative h-3 w-full rounded-[var(--spark-rounded-sm)] bg-gray-a4',\n 'data-[orientation=vertical]:h-full data-[orientation=vertical]:w-3',\n className,\n )}\n {...props}\n />\n )\n}\n\nSliderTrack.displayName = 'SliderTrack'\n\n/** The filled portion (min → thumb). Accent, deepens in high-contrast. */\nfunction SliderIndicator({\n className,\n ...props\n}: React.ComponentProps<typeof BaseSlider.Indicator>) {\n return (\n <BaseSlider.Indicator\n data-slot=\"slider-indicator\"\n className={cn(\n // matches the rail's radius so the fill's corners track the knob too\n 'rounded-[var(--spark-rounded-sm)] bg-[var(--spark-slider-range,var(--spark-9))]',\n className,\n )}\n {...props}\n />\n )\n}\n\nSliderIndicator.displayName = 'SliderIndicator'\n\n/**\n * Step tick dots overlaid on the rail (shown when `variant=\"ticks\"`). A dot at\n * each interior step — light (`--spark-slider-tick-on`, on the accent fill) for\n * steps up to the value, neutral gray beyond it. The endpoints are omitted (they\n * sit under the rounded rail ends / the thumb). Self-guards: draws nothing unless\n * the step count is in `[2, MAX_TICKS]`, so it's safe to compose directly.\n * Decorative + pointer-transparent so it never blocks a track-press. (Horizontal\n * orientation.)\n */\nfunction SliderTicks({ className, ...props }: React.ComponentProps<'div'>) {\n const { min, max, step, values } = useSliderContext('SliderTicks')\n\n if (!(step > 0) || max <= min) {\n return null\n }\n\n // count the reachable step intervals (floor, so a non-dividing step still gets\n // a dot on its last reachable step); drop the final one when it lands on max.\n const intervals = Math.floor((max - min) / step)\n\n if (intervals < 2 || intervals > MAX_TICKS) {\n return null\n }\n\n const lastIsEndpoint = min + intervals * step === max\n const dotCount = lastIsEndpoint ? intervals - 1 : intervals\n\n // Active band: [min, value] for a single thumb, [low, high] for a range.\n const bandLow = values.length > 1 ? Math.min(...values) : min\n const bandHigh = values.length > 1 ? Math.max(...values) : (values[0] ?? min)\n\n return (\n <div\n aria-hidden=\"true\"\n className={cn('pointer-events-none absolute inset-0', className)}\n data-slot=\"slider-ticks\"\n {...props}\n >\n {Array.from({ length: dotCount }, (_, k) => {\n const index = k + 1 // interior steps only (skip the two endpoints)\n const position = min + index * step\n const pct = ((position - min) / (max - min)) * 100\n const filled = position >= bandLow && position <= bandHigh\n\n return (\n <span\n className={cn(\n 'absolute top-1/2 size-1 -translate-x-1/2 -translate-y-1/2 rounded-full',\n // light dot on the accent fill (flips to step-1 in HC via the token);\n // neutral gray dot on the unfilled rail.\n filled\n ? 'bg-[var(--spark-slider-tick-on,var(--spark-on-solid,#fff))]'\n : 'bg-gray-a8',\n )}\n key={index}\n style={{ left: `${pct}%` }}\n />\n )\n })}\n </div>\n )\n}\n\nSliderTicks.displayName = 'SliderTicks'\n\n/**\n * The grab handle — a 16px accent knob. Corners follow the [data-radius] knob\n * (`--spark-rounded-lg`, matching the switch thumb): a circle at medium+, a\n * rounded square at small, a square at none. A background-colored separator ring\n * lifts it off the accent-filled range and a soft drop shadow adds depth; both\n * ride `--tw-shadow` so `focus-visible:ring` stays free. The invisible 24px hit\n * area meets the WCAG 2.5.8 target minimum.\n */\nfunction SliderThumb({\n className,\n ...props\n}: React.ComponentProps<typeof BaseSlider.Thumb>) {\n return (\n <BaseSlider.Thumb\n data-slot=\"slider-thumb\"\n className={cn(\n 'block size-4 shrink-0 rounded-[var(--spark-rounded-lg)] bg-[var(--spark-slider-range,var(--spark-9))]',\n 'shadow-[0_0_0_2px_var(--spark-background,#fff),0_1px_2px_0_rgb(0_0_0/0.2)]',\n \"before:absolute before:top-1/2 before:left-1/2 before:size-6 before:-translate-x-1/2 before:-translate-y-1/2 before:content-['']\",\n 'focus-visible:ring focus-visible:ring-offset-2 focus-visible:outline-hidden',\n 'data-[dragging]:ring data-[dragging]:ring-offset-2',\n 'disabled:pointer-events-none',\n className,\n )}\n {...props}\n />\n )\n}\n\nSliderThumb.displayName = 'SliderThumb'\n\n/**\n * Read-only value readout (`<output>`). Reads Base UI's own slider context, so\n * it stays formatted per the Root's `format`/`locale`. Pass a render function\n * for custom output, e.g. `{(f) => `${f[0]} €`}`.\n */\nfunction SliderValue({\n className,\n ...props\n}: React.ComponentProps<typeof BaseSlider.Value>) {\n return (\n <BaseSlider.Value\n data-slot=\"slider-value\"\n className={cn('text-sm text-gray tabular-nums', className)}\n {...props}\n />\n )\n}\n\nSliderValue.displayName = 'SliderValue'\n\ntype SliderInputProps = Omit<\n React.ComponentProps<'input'>,\n 'value' | 'defaultValue' | 'type' | 'onChange' | 'min' | 'max' | 'step'\n> & {\n /** Which thumb this input drives on a range slider. Defaults to 0. */\n index?: number\n /** Unit rendered after the field (e.g. \"€/month\"). Consumer-supplied — no default. */\n unit?: React.ReactNode\n}\n\n/**\n * Accessible direct-input — a native number field synced to a thumb's value, so\n * a user can type an exact value instead of dragging (or in addition to it).\n * Needs an accessible name: pass `aria-label` (no built-in default — portals are\n * multi-language). While typing it live-updates the thumb only for values already\n * in range (no mid-keystroke jump to the min/max); it snaps + clamps on\n * blur/Enter. `onFocus`/`onBlur`/`onKeyDown` you pass are composed with the\n * internal handlers, not replaced.\n */\nfunction SliderInput({\n className,\n index = 0,\n unit,\n disabled,\n onFocus,\n onBlur,\n onKeyDown,\n ...props\n}: SliderInputProps) {\n const ctx = useSliderContext('SliderInput')\n const currentValue = ctx.values[index] ?? ctx.min\n const [draft, setDraft] = React.useState<string>(String(currentValue))\n const [editing, setEditing] = React.useState(false)\n // the thumb value when editing began — commit fires only if it moved off this\n const baselineRef = React.useRef(currentValue)\n\n // Keep the field in sync when the value changes elsewhere (drag/keyboard),\n // but never fight the user's in-progress typing.\n React.useEffect(() => {\n if (!editing) {\n setDraft(String(currentValue))\n }\n }, [currentValue, editing])\n\n const parseInput = (raw: string): number | null => {\n if (raw.trim() === '') {\n return null\n }\n\n const parsed = Number(raw)\n\n return Number.isNaN(parsed) ? null : parsed\n }\n\n const commit = () => {\n const parsed = parseInput(draft)\n\n if (parsed === null) {\n setDraft(String(currentValue)) // reset an empty/invalid entry\n return\n }\n\n ctx.setThumbValue(index, parsed, {\n commit: true,\n commitBaseline: baselineRef.current,\n })\n }\n\n return (\n <span\n data-slot=\"slider-input\"\n className={cn('inline-flex items-baseline gap-1', className)}\n >\n <input\n type=\"number\"\n inputMode=\"decimal\"\n min={ctx.min}\n max={ctx.max}\n step={ctx.step}\n disabled={disabled ?? ctx.disabled}\n value={editing ? draft : String(currentValue)}\n onChange={(event) => {\n const raw = event.target.value\n setDraft(raw)\n const parsed = parseInput(raw)\n\n // live-update the thumb only when the typed value is already in range,\n // so a partial entry (e.g. \"7\" en route to \"75\") doesn't snap the thumb\n // to the min mid-keystroke. Out-of-range values clamp on blur/Enter.\n if (parsed !== null && parsed >= ctx.min && parsed <= ctx.max) {\n ctx.setThumbValue(index, parsed)\n }\n }}\n onFocus={(event) => {\n baselineRef.current = ctx.values[index] ?? ctx.min\n setEditing(true)\n onFocus?.(event)\n }}\n onBlur={(event) => {\n setEditing(false)\n commit()\n onBlur?.(event)\n }}\n onKeyDown={(event) => {\n // Enter blurs, and the single onBlur commit runs — no double-commit.\n if (event.key === 'Enter') {\n event.currentTarget.blur()\n }\n\n onKeyDown?.(event)\n }}\n className={cn(\n 'w-16 bg-transparent tabular-nums outline-hidden',\n 'rounded-[var(--spark-rounded-sm)] focus-visible:ring focus-visible:ring-offset-2',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n // hide the native spinners — the slider is the primary affordance\n '[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none',\n )}\n {...props}\n />\n {unit ? (\n <span className=\"text-sm text-gray\" data-slot=\"slider-unit\">\n {unit}\n </span>\n ) : null}\n </span>\n )\n}\n\nSliderInput.displayName = 'SliderInput'\n\nexport {\n Slider,\n SliderControl,\n SliderIndicator,\n SliderInput,\n SliderThumb,\n SliderTicks,\n SliderTrack,\n SliderValue,\n}\nexport type { SliderInputProps, SliderProps, SliderVariant }\n"],"mappings":"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"}
1
+ {"version":3,"file":"slider.cjs","names":["React","BaseSlider"],"sources":["../../src/components/slider.tsx"],"sourcesContent":["import { Slider as BaseSlider } from '@base-ui/react/slider'\nimport * as React from 'react'\nimport { cn } from '../utils/cn'\n\ntype SliderValue = number | number[]\n\ntype SliderVariant = 'default' | 'ticks'\n\n// Above this many steps the tick dots become a picket fence, so `variant=\"ticks\"`\n// silently stops drawing them (the continuous rail stays).\nconst MAX_TICKS = 24\n\n// Clamp to [min, max] then snap to the step grid (origin = min), trimming float\n// noise to the step's own decimal precision. `max` is always valid even if it\n// isn't a step multiple (matches Base UI).\nfunction snapToStep(\n value: number,\n min: number,\n max: number,\n step: number,\n): number {\n const clamped = Math.min(max, Math.max(min, value))\n\n if (!(step > 0)) {\n return clamped\n }\n\n const snapped = min + Math.round((clamped - min) / step) * step\n const bounded = Math.min(max, Math.max(min, snapped))\n const decimals = (String(step).split('.')[1] ?? '').length\n\n return decimals > 0 ? Number(bounded.toFixed(decimals)) : bounded\n}\n\n/**\n * Base UI's slider context is internal-only (not re-exported from\n * `@base-ui/react/slider`), so the editable `<SliderInput>` can't read the\n * current value from it. Instead `<Slider>` owns the value (controllable) and\n * shares it through this Spark context — keeping direct-input robust against\n * Base UI internal changes and letting inputs live anywhere in the subtree.\n */\ntype SliderContextValue = {\n values: readonly number[]\n min: number\n max: number\n step: number\n disabled: boolean\n /**\n * Write one thumb's value (from a `SliderInput`). Snaps to the step grid and\n * clamps; range values are kept sorted. Fires `onValueChange` only when the\n * value actually changes. When `commit` is set it also fires `onValueCommitted`\n * — but only if the committed value differs from `commitBaseline` (the value\n * when editing began), so a plain focus→blur never emits a spurious commit.\n */\n setThumbValue: (\n index: number,\n next: number,\n options?: { commit?: boolean; commitBaseline?: number },\n ) => void\n}\n\nconst SliderContext = React.createContext<SliderContextValue | null>(null)\n\nfunction useSliderContext(part: string): SliderContextValue {\n const ctx = React.useContext(SliderContext)\n\n if (!ctx) {\n throw new Error(`<${part}> must be rendered inside <Slider>`)\n }\n\n return ctx\n}\n\ntype SliderProps<Value extends SliderValue = SliderValue> = Omit<\n React.ComponentProps<typeof BaseSlider.Root>,\n 'value' | 'defaultValue' | 'onValueChange' | 'onValueCommitted' | 'render'\n> & {\n value?: Value\n defaultValue?: Value\n // Generic over the value shape: a single `number` keeps single-thumb handlers\n // number-typed, an array keeps range handlers array-typed — so callers don't\n // widen/narrow at every call site.\n onValueChange?: (\n value: Value,\n eventDetails: BaseSlider.Root.ChangeEventDetails,\n ) => void\n onValueCommitted?: (\n value: Value,\n eventDetails: BaseSlider.Root.CommitEventDetails,\n ) => void\n /**\n * `ticks` marks each step with a small dot on the rail — light on the accent\n * fill, neutral on the unfilled rail. Needs a sensible `step`; the dots are\n * hidden when the step count is < 2 or exceeds {@link MAX_TICKS}, and (in the\n * default render) for vertical sliders. Default `default`.\n */\n variant?: SliderVariant\n}\n\n/**\n * Root. Owns the value (controlled via `value` or uncontrolled via\n * `defaultValue`) and provides the Spark context. With no children it renders\n * the default single/range track (a childless-default, matching the library's\n * `*Close` idiom); pass children to compose `SliderInput` / `SliderValue` /\n * `SliderControl` yourself.\n */\nfunction Slider<Value extends SliderValue = SliderValue>({\n className,\n children,\n value,\n defaultValue,\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n orientation = 'horizontal',\n variant = 'default',\n onValueChange,\n onValueCommitted,\n // Radix positioned thumbs edge-aligned (inset within the track at min/max);\n // Base UI defaults to center-aligned (half the thumb overflows). `edge` keeps\n // the classic look and the thumb inside the rail.\n thumbAlignment = 'edge',\n // The accessible name belongs on the thumb's nested range input, not just the\n // Root — so keep it on the Root (names the group) AND forward it to the\n // childless-default thumb(s). When you compose your own thumbs, label them.\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n ...props\n}: SliderProps<Value>) {\n const isControlled = value !== undefined\n const [uncontrolled, setUncontrolled] = React.useState<SliderValue>(\n defaultValue ?? min,\n )\n const current = (isControlled ? value : uncontrolled) as SliderValue\n const values = React.useMemo(\n () => (Array.isArray(current) ? current : [current]),\n [current],\n )\n\n // Base UI hands back `number | readonly number[]`; we forward it as the\n // caller's `Value` (the runtime shape matches what they passed in).\n const emitChange = (\n next: number | readonly number[],\n eventDetails: BaseSlider.Root.ChangeEventDetails,\n ) => {\n if (!isControlled) {\n setUncontrolled(next as SliderValue)\n }\n\n onValueChange?.(next as Value, eventDetails)\n }\n\n // The direct-input write path. Snaps + clamps; for a range it swaps one thumb\n // and re-sorts (Base UI renders from a sorted copy, so an unsorted write would\n // desync the inputs from the thumbs). Fires onValueChange only on a real\n // change; fires onValueCommitted only when the committed value moved off the\n // pre-edit baseline.\n const setThumbValue = (\n index: number,\n next: number,\n options?: { commit?: boolean; commitBaseline?: number },\n ) => {\n const snapped = snapToStep(next, min, max, step)\n const wasArray = Array.isArray(current)\n let nextValue: SliderValue\n\n if (wasArray) {\n const copy = [...(current as number[])]\n copy[index] = snapped\n copy.sort((a, b) => a - b)\n nextValue = copy\n } else {\n nextValue = snapped\n }\n\n const changed = wasArray\n ? (nextValue as number[]).some((v, i) => v !== (current as number[])[i])\n : nextValue !== current\n\n // input-driven changes have no pointer/keyboard event; Base UI's own detail\n // object isn't constructible here, so we hand the consumer a minimal one.\n const details = {\n reason: 'input-change',\n } as unknown as BaseSlider.Root.ChangeEventDetails\n\n if (changed) {\n emitChange(nextValue, details)\n }\n\n if (options?.commit) {\n const committedChanged =\n options.commitBaseline === undefined\n ? changed\n : snapped !== options.commitBaseline\n\n if (committedChanged) {\n onValueCommitted?.(\n nextValue as Value,\n details as unknown as BaseSlider.Root.CommitEventDetails,\n )\n }\n }\n }\n\n // Rebuilt each render (cheap — <Slider> only re-renders on a value change) so\n // setThumbValue always closes over the current value + latest callbacks.\n const context: SliderContextValue = {\n values,\n min,\n max,\n step,\n disabled,\n setThumbValue,\n }\n\n // ticks are horizontal-only in the default render; SliderTicks self-hides when\n // the step count isn't countable, so no density check is needed here.\n const showTicks = variant === 'ticks' && orientation === 'horizontal'\n\n return (\n <SliderContext.Provider value={context}>\n <BaseSlider.Root\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n data-slot=\"slider\"\n value={current}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n orientation={orientation}\n thumbAlignment={thumbAlignment}\n onValueChange={emitChange}\n onValueCommitted={(next, eventDetails) =>\n onValueCommitted?.(next as Value, eventDetails)\n }\n className={cn(\n 'relative flex w-full flex-col gap-2 data-[orientation=vertical]:h-full data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-row',\n className,\n )}\n {...props}\n >\n {children ?? (\n <SliderControl>\n <SliderTrack>\n <SliderIndicator />\n {showTicks ? <SliderTicks /> : null}\n {values.map((_, index) => (\n <SliderThumb\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n index={values.length > 1 ? index : undefined}\n key={index}\n />\n ))}\n </SliderTrack>\n </SliderControl>\n )}\n </BaseSlider.Root>\n </SliderContext.Provider>\n )\n}\n\nSlider.displayName = 'Slider'\n\n/**\n * The interactive, draggable surface. A pointer-press anywhere on it moves the\n * nearest thumb (Base UI's track-press), so its full band is the target — kept\n * at ≥24px tall (WCAG 2.5.8) with the thin rail centered.\n */\nfunction SliderControl({\n className,\n ...props\n}: React.ComponentProps<typeof BaseSlider.Control>) {\n return (\n <BaseSlider.Control\n data-slot=\"slider-control\"\n className={cn(\n 'relative flex min-h-6 w-full touch-none items-center select-none',\n 'data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-40 data-[orientation=vertical]:w-6 data-[orientation=vertical]:justify-center',\n 'data-disabled:pointer-events-none data-disabled:opacity-50',\n className,\n )}\n {...props}\n />\n )\n}\n\nSliderControl.displayName = 'SliderControl'\n\n/** The rail — the full extent, neutral at rest. Holds the Indicator + Thumb(s). */\nfunction SliderTrack({\n className,\n ...props\n}: React.ComponentProps<typeof BaseSlider.Track>) {\n return (\n <BaseSlider.Track\n data-slot=\"slider-track\"\n className={cn(\n // 12px rail so the corner radius is legible; follows the [data-radius] knob\n // (square at none → pill at large/full). no overflow-hidden: the thumb is a\n // child and would be clipped.\n 'relative h-3 w-full rounded-(--spark-rounded-sm) bg-gray-a4',\n 'data-[orientation=vertical]:h-full data-[orientation=vertical]:w-3',\n className,\n )}\n {...props}\n />\n )\n}\n\nSliderTrack.displayName = 'SliderTrack'\n\n/** The filled portion (min → thumb). Accent, deepens in high-contrast. */\nfunction SliderIndicator({\n className,\n ...props\n}: React.ComponentProps<typeof BaseSlider.Indicator>) {\n return (\n <BaseSlider.Indicator\n data-slot=\"slider-indicator\"\n className={cn(\n // matches the rail's radius so the fill's corners track the knob too\n 'rounded-(--spark-rounded-sm) bg-(--spark-slider-range,var(--spark-9))',\n 'transition-[width,height,inset-inline-start] duration-150 data-dragging:transition-none motion-reduce:transition-none',\n className,\n )}\n {...props}\n />\n )\n}\n\nSliderIndicator.displayName = 'SliderIndicator'\n\n/**\n * Step tick dots overlaid on the rail (shown when `variant=\"ticks\"`). A dot at\n * each interior step — light (`--spark-slider-tick-on`, on the accent fill) for\n * steps up to the value, neutral gray beyond it. The endpoints are omitted (they\n * sit under the rounded rail ends / the thumb). Self-guards: draws nothing unless\n * the step count is in `[2, MAX_TICKS]`, so it's safe to compose directly.\n * Decorative + pointer-transparent so it never blocks a track-press. (Horizontal\n * orientation.)\n */\nfunction SliderTicks({ className, ...props }: React.ComponentProps<'div'>) {\n const { min, max, step, values } = useSliderContext('SliderTicks')\n\n if (!(step > 0) || max <= min) {\n return null\n }\n\n // count the reachable step intervals (floor, so a non-dividing step still gets\n // a dot on its last reachable step); drop the final one when it lands on max.\n const intervals = Math.floor((max - min) / step)\n\n if (intervals < 2 || intervals > MAX_TICKS) {\n return null\n }\n\n const lastIsEndpoint = min + intervals * step === max\n const dotCount = lastIsEndpoint ? intervals - 1 : intervals\n\n // Active band: [min, value] for a single thumb, [low, high] for a range.\n const bandLow = values.length > 1 ? Math.min(...values) : min\n const bandHigh = values.length > 1 ? Math.max(...values) : (values[0] ?? min)\n\n return (\n <div\n aria-hidden=\"true\"\n className={cn('pointer-events-none absolute inset-0', className)}\n data-slot=\"slider-ticks\"\n {...props}\n >\n {Array.from({ length: dotCount }, (_, k) => {\n const index = k + 1 // interior steps only (skip the two endpoints)\n const position = min + index * step\n const pct = ((position - min) / (max - min)) * 100\n const filled = position >= bandLow && position <= bandHigh\n\n return (\n <span\n className={cn(\n 'absolute top-1/2 size-1 -translate-x-1/2 -translate-y-1/2 rounded-full',\n // light dot on the accent fill (flips to step-1 in HC via the token);\n // neutral gray dot on the unfilled rail.\n filled\n ? 'bg-(--spark-slider-tick-on,var(--spark-on-solid,#fff))'\n : 'bg-gray-a8',\n )}\n key={index}\n style={{ left: `${pct}%` }}\n />\n )\n })}\n </div>\n )\n}\n\nSliderTicks.displayName = 'SliderTicks'\n\nfunction SliderThumb({\n className,\n ...props\n}: React.ComponentProps<typeof BaseSlider.Thumb>) {\n return (\n <BaseSlider.Thumb\n data-slot=\"slider-thumb\"\n className={cn(\n 'block size-4 shrink-0 rounded-(--spark-rounded-lg) bg-(--spark-slider-range,var(--spark-9))',\n 'shadow-[0_0_0_2px_var(--spark-background,#fff),0_1px_2px_0_rgb(0_0_0/0.2)]',\n \"before:absolute before:top-1/2 before:left-1/2 before:size-6 before:-translate-x-1/2 before:-translate-y-1/2 before:content-['']\",\n 'outline-hidden has-[input:focus-visible]:ring-2 has-[input:focus-visible]:ring-offset-2',\n 'data-dragging:ring-2 data-dragging:ring-offset-2',\n 'transition-[inset-inline-start,top,box-shadow] duration-150 data-dragging:transition-none motion-reduce:transition-none',\n 'disabled:pointer-events-none',\n className,\n )}\n {...props}\n />\n )\n}\n\nSliderThumb.displayName = 'SliderThumb'\n\nfunction SliderValue({\n className,\n ...props\n}: React.ComponentProps<typeof BaseSlider.Value>) {\n return (\n <BaseSlider.Value\n data-slot=\"slider-value\"\n className={cn('text-sm text-gray tabular-nums', className)}\n {...props}\n />\n )\n}\n\nSliderValue.displayName = 'SliderValue'\n\ntype SliderInputProps = Omit<\n React.ComponentProps<'input'>,\n 'value' | 'defaultValue' | 'type' | 'onChange' | 'min' | 'max' | 'step'\n> & {\n /** Which thumb this input drives on a range slider. Defaults to 0. */\n index?: number\n /** Unit rendered after the field (e.g. \"€/month\"). Consumer-supplied — no default. */\n unit?: React.ReactNode\n}\n\n/**\n * Accessible direct-input — a native number field synced to a thumb's value, so\n * a user can type an exact value instead of dragging (or in addition to it).\n * Needs an accessible name: pass `aria-label` (no built-in default — portals are\n * multi-language). While typing it live-updates the thumb only for values already\n * in range (no mid-keystroke jump to the min/max); it snaps + clamps on\n * blur/Enter. `onFocus`/`onBlur`/`onKeyDown` you pass are composed with the\n * internal handlers, not replaced.\n */\nfunction SliderInput({\n className,\n index = 0,\n unit,\n disabled,\n onFocus,\n onBlur,\n onKeyDown,\n ...props\n}: SliderInputProps) {\n const ctx = useSliderContext('SliderInput')\n const currentValue = ctx.values[index] ?? ctx.min\n const [draft, setDraft] = React.useState<string>(String(currentValue))\n const [editing, setEditing] = React.useState(false)\n // the thumb value when editing began — commit fires only if it moved off this\n const baselineRef = React.useRef(currentValue)\n\n // Keep the field in sync when the value changes elsewhere (drag/keyboard),\n // but never fight the user's in-progress typing.\n React.useEffect(() => {\n if (!editing) {\n setDraft(String(currentValue))\n }\n }, [currentValue, editing])\n\n const parseInput = (raw: string): number | null => {\n if (raw.trim() === '') {\n return null\n }\n\n const parsed = Number(raw)\n\n return Number.isNaN(parsed) ? null : parsed\n }\n\n const commit = () => {\n const parsed = parseInput(draft)\n\n if (parsed === null) {\n setDraft(String(currentValue)) // reset an empty/invalid entry\n return\n }\n\n ctx.setThumbValue(index, parsed, {\n commit: true,\n commitBaseline: baselineRef.current,\n })\n }\n\n return (\n <span\n data-slot=\"slider-input\"\n className={cn('inline-flex items-baseline gap-1', className)}\n >\n <input\n type=\"number\"\n inputMode=\"decimal\"\n min={ctx.min}\n max={ctx.max}\n step={ctx.step}\n disabled={disabled ?? ctx.disabled}\n value={editing ? draft : String(currentValue)}\n onChange={(event) => {\n const raw = event.target.value\n setDraft(raw)\n const parsed = parseInput(raw)\n\n // live-update the thumb only when the typed value is already in range,\n // so a partial entry (e.g. \"7\" en route to \"75\") doesn't snap the thumb\n // to the min mid-keystroke. Out-of-range values clamp on blur/Enter.\n if (parsed !== null && parsed >= ctx.min && parsed <= ctx.max) {\n ctx.setThumbValue(index, parsed)\n }\n }}\n onFocus={(event) => {\n baselineRef.current = ctx.values[index] ?? ctx.min\n setEditing(true)\n onFocus?.(event)\n }}\n onBlur={(event) => {\n setEditing(false)\n commit()\n onBlur?.(event)\n }}\n onKeyDown={(event) => {\n // Enter blurs, and the single onBlur commit runs — no double-commit.\n if (event.key === 'Enter') {\n event.currentTarget.blur()\n }\n\n onKeyDown?.(event)\n }}\n className={cn(\n 'w-16 bg-transparent tabular-nums outline-hidden',\n 'rounded-(--spark-rounded-sm) focus-visible:ring-2 focus-visible:ring-offset-2',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n // hide the native spinners — the slider is the primary affordance\n '[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none',\n )}\n {...props}\n />\n {unit ? (\n <span className=\"text-sm text-gray\" data-slot=\"slider-unit\">\n {unit}\n </span>\n ) : null}\n </span>\n )\n}\n\nSliderInput.displayName = 'SliderInput'\n\nexport {\n Slider,\n SliderControl,\n SliderIndicator,\n SliderInput,\n SliderThumb,\n SliderTicks,\n SliderTrack,\n SliderValue,\n}\nexport type { SliderInputProps, SliderProps, SliderVariant }\n"],"mappings":"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"}
@@ -92,14 +92,6 @@ declare function SliderTicks({
92
92
  declare namespace SliderTicks {
93
93
  var displayName: string;
94
94
  }
95
- /**
96
- * The grab handle — a 16px accent knob. Corners follow the [data-radius] knob
97
- * (`--spark-rounded-lg`, matching the switch thumb): a circle at medium+, a
98
- * rounded square at small, a square at none. A background-colored separator ring
99
- * lifts it off the accent-filled range and a soft drop shadow adds depth; both
100
- * ride `--tw-shadow` so `focus-visible:ring` stays free. The invisible 24px hit
101
- * area meets the WCAG 2.5.8 target minimum.
102
- */
103
95
  declare function SliderThumb({
104
96
  className,
105
97
  ...props
@@ -107,11 +99,6 @@ declare function SliderThumb({
107
99
  declare namespace SliderThumb {
108
100
  var displayName: string;
109
101
  }
110
- /**
111
- * Read-only value readout (`<output>`). Reads Base UI's own slider context, so
112
- * it stays formatted per the Root's `format`/`locale`. Pass a render function
113
- * for custom output, e.g. `{(f) => `${f[0]} €`}`.
114
- */
115
102
  declare function SliderValue({
116
103
  className,
117
104
  ...props
@@ -92,14 +92,6 @@ declare function SliderTicks({
92
92
  declare namespace SliderTicks {
93
93
  var displayName: string;
94
94
  }
95
- /**
96
- * The grab handle — a 16px accent knob. Corners follow the [data-radius] knob
97
- * (`--spark-rounded-lg`, matching the switch thumb): a circle at medium+, a
98
- * rounded square at small, a square at none. A background-colored separator ring
99
- * lifts it off the accent-filled range and a soft drop shadow adds depth; both
100
- * ride `--tw-shadow` so `focus-visible:ring` stays free. The invisible 24px hit
101
- * area meets the WCAG 2.5.8 target minimum.
102
- */
103
95
  declare function SliderThumb({
104
96
  className,
105
97
  ...props
@@ -107,11 +99,6 @@ declare function SliderThumb({
107
99
  declare namespace SliderThumb {
108
100
  var displayName: string;
109
101
  }
110
- /**
111
- * Read-only value readout (`<output>`). Reads Base UI's own slider context, so
112
- * it stays formatted per the Root's `format`/`locale`. Pass a render function
113
- * for custom output, e.g. `{(f) => `${f[0]} €`}`.
114
- */
115
102
  declare function SliderValue({
116
103
  className,
117
104
  ...props
@@ -99,7 +99,7 @@ Slider.displayName = "Slider";
99
99
  function SliderControl({ className, ...props }) {
100
100
  return /* @__PURE__ */ jsx(Slider$1.Control, {
101
101
  "data-slot": "slider-control",
102
- className: cn("relative flex min-h-6 w-full touch-none items-center select-none", "data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-40 data-[orientation=vertical]:w-6 data-[orientation=vertical]:justify-center", "data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className),
102
+ className: cn("relative flex min-h-6 w-full touch-none items-center select-none", "data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-40 data-[orientation=vertical]:w-6 data-[orientation=vertical]:justify-center", "data-disabled:pointer-events-none data-disabled:opacity-50", className),
103
103
  ...props
104
104
  });
105
105
  }
@@ -108,7 +108,7 @@ SliderControl.displayName = "SliderControl";
108
108
  function SliderTrack({ className, ...props }) {
109
109
  return /* @__PURE__ */ jsx(Slider$1.Track, {
110
110
  "data-slot": "slider-track",
111
- className: cn("relative h-3 w-full rounded-[var(--spark-rounded-sm)] bg-gray-a4", "data-[orientation=vertical]:h-full data-[orientation=vertical]:w-3", className),
111
+ className: cn("relative h-3 w-full rounded-(--spark-rounded-sm) bg-gray-a4", "data-[orientation=vertical]:h-full data-[orientation=vertical]:w-3", className),
112
112
  ...props
113
113
  });
114
114
  }
@@ -117,7 +117,7 @@ SliderTrack.displayName = "SliderTrack";
117
117
  function SliderIndicator({ className, ...props }) {
118
118
  return /* @__PURE__ */ jsx(Slider$1.Indicator, {
119
119
  "data-slot": "slider-indicator",
120
- className: cn("rounded-[var(--spark-rounded-sm)] bg-[var(--spark-slider-range,var(--spark-9))]", className),
120
+ className: cn("rounded-(--spark-rounded-sm) bg-(--spark-slider-range,var(--spark-9))", "transition-[width,height,inset-inline-start] duration-150 data-dragging:transition-none motion-reduce:transition-none", className),
121
121
  ...props
122
122
  });
123
123
  }
@@ -149,34 +149,21 @@ function SliderTicks({ className, ...props }) {
149
149
  const position = min + index * step;
150
150
  const pct = (position - min) / (max - min) * 100;
151
151
  return /* @__PURE__ */ jsx("span", {
152
- className: cn("absolute top-1/2 size-1 -translate-x-1/2 -translate-y-1/2 rounded-full", position >= bandLow && position <= bandHigh ? "bg-[var(--spark-slider-tick-on,var(--spark-on-solid,#fff))]" : "bg-gray-a8"),
152
+ className: cn("absolute top-1/2 size-1 -translate-x-1/2 -translate-y-1/2 rounded-full", position >= bandLow && position <= bandHigh ? "bg-(--spark-slider-tick-on,var(--spark-on-solid,#fff))" : "bg-gray-a8"),
153
153
  style: { left: `${pct}%` }
154
154
  }, index);
155
155
  })
156
156
  });
157
157
  }
158
158
  SliderTicks.displayName = "SliderTicks";
159
- /**
160
- * The grab handle — a 16px accent knob. Corners follow the [data-radius] knob
161
- * (`--spark-rounded-lg`, matching the switch thumb): a circle at medium+, a
162
- * rounded square at small, a square at none. A background-colored separator ring
163
- * lifts it off the accent-filled range and a soft drop shadow adds depth; both
164
- * ride `--tw-shadow` so `focus-visible:ring` stays free. The invisible 24px hit
165
- * area meets the WCAG 2.5.8 target minimum.
166
- */
167
159
  function SliderThumb({ className, ...props }) {
168
160
  return /* @__PURE__ */ jsx(Slider$1.Thumb, {
169
161
  "data-slot": "slider-thumb",
170
- className: cn("block size-4 shrink-0 rounded-[var(--spark-rounded-lg)] bg-[var(--spark-slider-range,var(--spark-9))]", "shadow-[0_0_0_2px_var(--spark-background,#fff),0_1px_2px_0_rgb(0_0_0/0.2)]", "before:absolute before:top-1/2 before:left-1/2 before:size-6 before:-translate-x-1/2 before:-translate-y-1/2 before:content-['']", "focus-visible:ring focus-visible:ring-offset-2 focus-visible:outline-hidden", "data-[dragging]:ring data-[dragging]:ring-offset-2", "disabled:pointer-events-none", className),
162
+ className: cn("block size-4 shrink-0 rounded-(--spark-rounded-lg) bg-(--spark-slider-range,var(--spark-9))", "shadow-[0_0_0_2px_var(--spark-background,#fff),0_1px_2px_0_rgb(0_0_0/0.2)]", "before:absolute before:top-1/2 before:left-1/2 before:size-6 before:-translate-x-1/2 before:-translate-y-1/2 before:content-['']", "outline-hidden has-[input:focus-visible]:ring-2 has-[input:focus-visible]:ring-offset-2", "data-dragging:ring-2 data-dragging:ring-offset-2", "transition-[inset-inline-start,top,box-shadow] duration-150 data-dragging:transition-none motion-reduce:transition-none", "disabled:pointer-events-none", className),
171
163
  ...props
172
164
  });
173
165
  }
174
166
  SliderThumb.displayName = "SliderThumb";
175
- /**
176
- * Read-only value readout (`<output>`). Reads Base UI's own slider context, so
177
- * it stays formatted per the Root's `format`/`locale`. Pass a render function
178
- * for custom output, e.g. `{(f) => `${f[0]} €`}`.
179
- */
180
167
  function SliderValue({ className, ...props }) {
181
168
  return /* @__PURE__ */ jsx(Slider$1.Value, {
182
169
  "data-slot": "slider-value",
@@ -250,7 +237,7 @@ function SliderInput({ className, index = 0, unit, disabled, onFocus, onBlur, on
250
237
  if (event.key === "Enter") event.currentTarget.blur();
251
238
  onKeyDown?.(event);
252
239
  },
253
- className: cn("w-16 bg-transparent tabular-nums outline-hidden", "rounded-[var(--spark-rounded-sm)] focus-visible:ring focus-visible:ring-offset-2", "disabled:cursor-not-allowed disabled:opacity-50", "[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"),
240
+ className: cn("w-16 bg-transparent tabular-nums outline-hidden", "rounded-(--spark-rounded-sm) focus-visible:ring-2 focus-visible:ring-offset-2", "disabled:cursor-not-allowed disabled:opacity-50", "[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"),
254
241
  ...props
255
242
  }), unit ? /* @__PURE__ */ jsx("span", {
256
243
  className: "text-sm text-gray",