@central-ui/react 0.1.2 → 0.3.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 (287) hide show
  1. package/LICENSE +49 -0
  2. package/dist/components/accordion/index.d.ts +4 -3
  3. package/dist/components/accordion/index.js +7 -4
  4. package/dist/components/autocomplete/index.d.ts +23 -30
  5. package/dist/components/autocomplete/index.js +81 -56
  6. package/dist/components/avatar/index.d.ts +1 -2
  7. package/dist/components/avatar/index.js +0 -1
  8. package/dist/components/badge/index.d.ts +0 -1
  9. package/dist/components/badge/index.js +2 -2
  10. package/dist/components/banner/index.d.ts +1 -1
  11. package/dist/components/banner/index.js +23 -25
  12. package/dist/components/barchart/index.d.ts +106 -0
  13. package/dist/components/barchart/index.js +122 -0
  14. package/dist/components/breadcrumb/index.d.ts +0 -1
  15. package/dist/components/breadcrumb/index.js +6 -7
  16. package/dist/components/button/index.d.ts +2 -3
  17. package/dist/components/button/index.js +11 -12
  18. package/dist/components/card/index.d.ts +0 -1
  19. package/dist/components/card/index.js +0 -1
  20. package/dist/components/carousel/index.d.ts +169 -0
  21. package/dist/components/carousel/index.js +299 -0
  22. package/dist/components/checkbox/index.d.ts +13 -11
  23. package/dist/components/checkbox/index.js +51 -31
  24. package/dist/components/chip/index.d.ts +1 -1
  25. package/dist/components/chip/index.js +2 -3
  26. package/dist/components/combobox/index.d.ts +33 -49
  27. package/dist/components/combobox/index.js +102 -70
  28. package/dist/components/datepicker/index.d.ts +18 -31
  29. package/dist/components/datepicker/index.js +81 -99
  30. package/dist/components/dialog/index.d.ts +14 -27
  31. package/dist/components/dialog/index.js +17 -18
  32. package/dist/components/divider/index.d.ts +0 -1
  33. package/dist/components/divider/index.js +0 -1
  34. package/dist/components/donutchart/index.d.ts +100 -0
  35. package/dist/components/donutchart/index.js +178 -0
  36. package/dist/components/drawer/index.d.ts +12 -21
  37. package/dist/components/drawer/index.js +34 -36
  38. package/dist/components/empty/index.d.ts +3 -3
  39. package/dist/components/empty/index.js +4 -5
  40. package/dist/components/exception/index.d.ts +86 -0
  41. package/dist/components/exception/index.js +116 -0
  42. package/dist/components/fileupload/index.d.ts +4 -9
  43. package/dist/components/fileupload/index.js +26 -38
  44. package/dist/components/form/index.d.ts +0 -1
  45. package/dist/components/form/index.js +0 -1
  46. package/dist/components/horizontalbarchart/index.d.ts +120 -0
  47. package/dist/components/horizontalbarchart/index.js +193 -0
  48. package/dist/components/input/index.d.ts +22 -22
  49. package/dist/components/input/index.js +76 -105
  50. package/dist/components/linechart/index.d.ts +114 -0
  51. package/dist/components/linechart/index.js +139 -0
  52. package/dist/components/menu/index.d.ts +9 -11
  53. package/dist/components/menu/index.js +42 -39
  54. package/dist/components/metric/index.d.ts +0 -1
  55. package/dist/components/metric/index.js +0 -1
  56. package/dist/components/numberinput/index.d.ts +14 -21
  57. package/dist/components/numberinput/index.js +40 -53
  58. package/dist/components/otpinput/index.d.ts +14 -9
  59. package/dist/components/otpinput/index.js +25 -18
  60. package/dist/components/page/index.d.ts +0 -1
  61. package/dist/components/page/index.js +1 -3
  62. package/dist/components/passwordinput/index.d.ts +14 -11
  63. package/dist/components/passwordinput/index.js +36 -45
  64. package/dist/components/popover/index.d.ts +21 -19
  65. package/dist/components/popover/index.js +34 -15
  66. package/dist/components/radio/index.d.ts +13 -9
  67. package/dist/components/radio/index.js +69 -60
  68. package/dist/components/ratinginput/index.d.ts +13 -8
  69. package/dist/components/ratinginput/index.js +37 -17
  70. package/dist/components/select/index.d.ts +30 -30
  71. package/dist/components/select/index.js +80 -41
  72. package/dist/components/skeleton/index.d.ts +0 -1
  73. package/dist/components/skeleton/index.js +0 -1
  74. package/dist/components/slider/index.d.ts +14 -9
  75. package/dist/components/slider/index.js +64 -63
  76. package/dist/components/spinner/index.d.ts +1 -2
  77. package/dist/components/spinner/index.js +2 -3
  78. package/dist/components/splitter/index.d.ts +1 -2
  79. package/dist/components/splitter/index.js +5 -6
  80. package/dist/components/stepper/index.d.ts +8 -20
  81. package/dist/components/stepper/index.js +15 -16
  82. package/dist/components/switch/index.d.ts +12 -10
  83. package/dist/components/switch/index.js +46 -30
  84. package/dist/components/table/index.d.ts +3 -3
  85. package/dist/components/table/index.js +14 -13
  86. package/dist/components/tabs/index.d.ts +0 -1
  87. package/dist/components/tabs/index.js +1 -2
  88. package/dist/components/textarea/index.d.ts +14 -11
  89. package/dist/components/textarea/index.js +37 -46
  90. package/dist/components/textlink/index.d.ts +3 -1
  91. package/dist/components/textlink/index.js +4 -1
  92. package/dist/components/toast/index.d.ts +8 -14
  93. package/dist/components/toast/index.js +48 -48
  94. package/dist/components/toggle/index.d.ts +0 -1
  95. package/dist/components/toggle/index.js +17 -24
  96. package/dist/components/tooltip/index.d.ts +11 -13
  97. package/dist/components/tooltip/index.js +12 -9
  98. package/dist/components/tour/index.d.ts +154 -0
  99. package/dist/components/tour/index.js +280 -0
  100. package/dist/index.d.ts +7 -2
  101. package/dist/index.js +7 -1
  102. package/dist/types/Icon.d.ts +0 -1
  103. package/dist/types/Icon.js +0 -1
  104. package/dist/types/Style.d.ts +0 -1
  105. package/dist/types/Style.js +0 -1
  106. package/dist/types/Validation.d.ts +12 -0
  107. package/dist/types/Validation.js +1 -0
  108. package/dist/utils/ArkStateToDataAttributes.d.ts +0 -1
  109. package/dist/utils/ArkStateToDataAttributes.js +0 -1
  110. package/dist/utils/Validation.d.ts +14 -0
  111. package/dist/utils/Validation.js +23 -0
  112. package/dist/utils/asChild.d.ts +41 -0
  113. package/dist/utils/asChild.js +15 -0
  114. package/dist/utils/icons.d.ts +24 -0
  115. package/dist/utils/icons.js +160 -0
  116. package/dist/utils/useForwardClickToInput.d.ts +0 -1
  117. package/dist/utils/useForwardClickToInput.js +0 -1
  118. package/dist/utils/virtualization/useVirtualizedAutocomplete.d.ts +0 -1
  119. package/dist/utils/virtualization/useVirtualizedAutocomplete.js +0 -1
  120. package/dist/utils/virtualization/useVirtualizedCombobox.d.ts +0 -1
  121. package/dist/utils/virtualization/useVirtualizedCombobox.js +0 -1
  122. package/dist/utils/virtualization/useVirtualizedTable.d.ts +0 -1
  123. package/dist/utils/virtualization/useVirtualizedTable.js +0 -1
  124. package/package.json +14 -11
  125. package/src/presets/shopify-polaris/shopify-polaris-autocomplete.css +2 -2
  126. package/src/presets/shopify-polaris/shopify-polaris-barchart.css +64 -0
  127. package/src/presets/shopify-polaris/shopify-polaris-carousel.css +62 -0
  128. package/src/presets/shopify-polaris/shopify-polaris-checkbox.css +2 -2
  129. package/src/presets/shopify-polaris/shopify-polaris-combobox.css +2 -2
  130. package/src/presets/shopify-polaris/shopify-polaris-datepicker.css +4 -4
  131. package/src/presets/shopify-polaris/shopify-polaris-dialog.css +16 -0
  132. package/src/presets/shopify-polaris/shopify-polaris-donutchart.css +172 -0
  133. package/src/presets/shopify-polaris/shopify-polaris-drawer.css +16 -0
  134. package/src/presets/shopify-polaris/shopify-polaris-exception.css +40 -0
  135. package/src/presets/shopify-polaris/shopify-polaris-fileupload.css +1 -1
  136. package/src/presets/shopify-polaris/shopify-polaris-horizontalbarchart.css +60 -0
  137. package/src/presets/shopify-polaris/shopify-polaris-input.css +2 -2
  138. package/src/presets/shopify-polaris/shopify-polaris-linechart.css +68 -0
  139. package/src/presets/shopify-polaris/shopify-polaris-menu.css +16 -0
  140. package/src/presets/shopify-polaris/shopify-polaris-numberinput.css +2 -2
  141. package/src/presets/shopify-polaris/shopify-polaris-otpinput.css +2 -2
  142. package/src/presets/shopify-polaris/shopify-polaris-passwordinput.css +2 -2
  143. package/src/presets/shopify-polaris/shopify-polaris-popover.css +29 -0
  144. package/src/presets/shopify-polaris/shopify-polaris-radio.css +2 -2
  145. package/src/presets/shopify-polaris/shopify-polaris-ratinginput.css +2 -2
  146. package/src/presets/shopify-polaris/shopify-polaris-select.css +2 -2
  147. package/src/presets/shopify-polaris/shopify-polaris-slider.css +2 -2
  148. package/src/presets/shopify-polaris/shopify-polaris-stepper.css +16 -0
  149. package/src/presets/shopify-polaris/shopify-polaris-switch.css +2 -2
  150. package/src/presets/shopify-polaris/shopify-polaris-textarea.css +2 -2
  151. package/src/presets/shopify-polaris/shopify-polaris-tooltip.css +16 -0
  152. package/src/presets/shopify-polaris/shopify-polaris.css +6 -0
  153. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-autocomplete.css +2 -2
  154. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-barchart.css +64 -0
  155. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-carousel.css +55 -0
  156. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-checkbox.css +2 -2
  157. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-combobox.css +2 -2
  158. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-datepicker.css +2 -2
  159. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-dialog.css +9 -0
  160. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-donutchart.css +172 -0
  161. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-drawer.css +9 -0
  162. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-exception.css +40 -0
  163. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-fileupload.css +1 -1
  164. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-horizontalbarchart.css +60 -0
  165. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-input.css +2 -2
  166. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-linechart.css +68 -0
  167. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-menu.css +9 -0
  168. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-numberinput.css +2 -2
  169. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-otpinput.css +2 -2
  170. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-passwordinput.css +2 -2
  171. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-popover.css +22 -0
  172. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-radio.css +2 -2
  173. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-ratinginput.css +2 -2
  174. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-slider.css +2 -2
  175. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-stepper.css +9 -0
  176. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-switch.css +2 -2
  177. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-textarea.css +2 -2
  178. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy-tooltip.css +9 -0
  179. package/src/presets/shopify-polaris-legacy/shopify-polaris-legacy.css +6 -0
  180. package/dist/components/accordion/index.d.ts.map +0 -1
  181. package/dist/components/accordion/index.js.map +0 -1
  182. package/dist/components/autocomplete/index.d.ts.map +0 -1
  183. package/dist/components/autocomplete/index.js.map +0 -1
  184. package/dist/components/avatar/index.d.ts.map +0 -1
  185. package/dist/components/avatar/index.js.map +0 -1
  186. package/dist/components/badge/index.d.ts.map +0 -1
  187. package/dist/components/badge/index.js.map +0 -1
  188. package/dist/components/banner/index.d.ts.map +0 -1
  189. package/dist/components/banner/index.js.map +0 -1
  190. package/dist/components/breadcrumb/index.d.ts.map +0 -1
  191. package/dist/components/breadcrumb/index.js.map +0 -1
  192. package/dist/components/button/index.d.ts.map +0 -1
  193. package/dist/components/button/index.js.map +0 -1
  194. package/dist/components/card/index.d.ts.map +0 -1
  195. package/dist/components/card/index.js.map +0 -1
  196. package/dist/components/checkbox/index.d.ts.map +0 -1
  197. package/dist/components/checkbox/index.js.map +0 -1
  198. package/dist/components/chip/index.d.ts.map +0 -1
  199. package/dist/components/chip/index.js.map +0 -1
  200. package/dist/components/combobox/index.d.ts.map +0 -1
  201. package/dist/components/combobox/index.js.map +0 -1
  202. package/dist/components/datepicker/index.d.ts.map +0 -1
  203. package/dist/components/datepicker/index.js.map +0 -1
  204. package/dist/components/dialog/index.d.ts.map +0 -1
  205. package/dist/components/dialog/index.js.map +0 -1
  206. package/dist/components/divider/index.d.ts.map +0 -1
  207. package/dist/components/divider/index.js.map +0 -1
  208. package/dist/components/drawer/index.d.ts.map +0 -1
  209. package/dist/components/drawer/index.js.map +0 -1
  210. package/dist/components/empty/index.d.ts.map +0 -1
  211. package/dist/components/empty/index.js.map +0 -1
  212. package/dist/components/fileupload/index.d.ts.map +0 -1
  213. package/dist/components/fileupload/index.js.map +0 -1
  214. package/dist/components/form/index.d.ts.map +0 -1
  215. package/dist/components/form/index.js.map +0 -1
  216. package/dist/components/input/index.d.ts.map +0 -1
  217. package/dist/components/input/index.js.map +0 -1
  218. package/dist/components/menu/index.d.ts.map +0 -1
  219. package/dist/components/menu/index.js.map +0 -1
  220. package/dist/components/metric/index.d.ts.map +0 -1
  221. package/dist/components/metric/index.js.map +0 -1
  222. package/dist/components/numberinput/index.d.ts.map +0 -1
  223. package/dist/components/numberinput/index.js.map +0 -1
  224. package/dist/components/otpinput/index.d.ts.map +0 -1
  225. package/dist/components/otpinput/index.js.map +0 -1
  226. package/dist/components/page/index.d.ts.map +0 -1
  227. package/dist/components/page/index.js.map +0 -1
  228. package/dist/components/passwordinput/index.d.ts.map +0 -1
  229. package/dist/components/passwordinput/index.js.map +0 -1
  230. package/dist/components/popover/index.d.ts.map +0 -1
  231. package/dist/components/popover/index.js.map +0 -1
  232. package/dist/components/radio/index.d.ts.map +0 -1
  233. package/dist/components/radio/index.js.map +0 -1
  234. package/dist/components/ratinginput/index.d.ts.map +0 -1
  235. package/dist/components/ratinginput/index.js.map +0 -1
  236. package/dist/components/select/index.d.ts.map +0 -1
  237. package/dist/components/select/index.js.map +0 -1
  238. package/dist/components/skeleton/index.d.ts.map +0 -1
  239. package/dist/components/skeleton/index.js.map +0 -1
  240. package/dist/components/slider/index.d.ts.map +0 -1
  241. package/dist/components/slider/index.js.map +0 -1
  242. package/dist/components/spinner/index.d.ts.map +0 -1
  243. package/dist/components/spinner/index.js.map +0 -1
  244. package/dist/components/splitter/index.d.ts.map +0 -1
  245. package/dist/components/splitter/index.js.map +0 -1
  246. package/dist/components/stepper/index.d.ts.map +0 -1
  247. package/dist/components/stepper/index.js.map +0 -1
  248. package/dist/components/switch/index.d.ts.map +0 -1
  249. package/dist/components/switch/index.js.map +0 -1
  250. package/dist/components/table/index.d.ts.map +0 -1
  251. package/dist/components/table/index.js.map +0 -1
  252. package/dist/components/tabs/index.d.ts.map +0 -1
  253. package/dist/components/tabs/index.js.map +0 -1
  254. package/dist/components/textarea/index.d.ts.map +0 -1
  255. package/dist/components/textarea/index.js.map +0 -1
  256. package/dist/components/textlink/index.d.ts.map +0 -1
  257. package/dist/components/textlink/index.js.map +0 -1
  258. package/dist/components/toast/index.d.ts.map +0 -1
  259. package/dist/components/toast/index.js.map +0 -1
  260. package/dist/components/toggle/index.d.ts.map +0 -1
  261. package/dist/components/toggle/index.js.map +0 -1
  262. package/dist/components/tooltip/index.d.ts.map +0 -1
  263. package/dist/components/tooltip/index.js.map +0 -1
  264. package/dist/index.d.ts.map +0 -1
  265. package/dist/index.js.map +0 -1
  266. package/dist/types/Icon.d.ts.map +0 -1
  267. package/dist/types/Icon.js.map +0 -1
  268. package/dist/types/Style.d.ts.map +0 -1
  269. package/dist/types/Style.js.map +0 -1
  270. package/dist/types/Tone.d.ts +0 -4
  271. package/dist/types/Tone.d.ts.map +0 -1
  272. package/dist/types/Tone.js +0 -2
  273. package/dist/types/Tone.js.map +0 -1
  274. package/dist/utils/ArkStateToDataAttributes.d.ts.map +0 -1
  275. package/dist/utils/ArkStateToDataAttributes.js.map +0 -1
  276. package/dist/utils/Tone.d.ts +0 -3
  277. package/dist/utils/Tone.d.ts.map +0 -1
  278. package/dist/utils/Tone.js +0 -7
  279. package/dist/utils/Tone.js.map +0 -1
  280. package/dist/utils/useForwardClickToInput.d.ts.map +0 -1
  281. package/dist/utils/useForwardClickToInput.js.map +0 -1
  282. package/dist/utils/virtualization/useVirtualizedAutocomplete.d.ts.map +0 -1
  283. package/dist/utils/virtualization/useVirtualizedAutocomplete.js.map +0 -1
  284. package/dist/utils/virtualization/useVirtualizedCombobox.d.ts.map +0 -1
  285. package/dist/utils/virtualization/useVirtualizedCombobox.js.map +0 -1
  286. package/dist/utils/virtualization/useVirtualizedTable.d.ts.map +0 -1
  287. package/dist/utils/virtualization/useVirtualizedTable.js.map +0 -1
@@ -1,8 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { asChildRendering } from "../../utils/asChild.js";
2
3
  import { Select as BaseSelect } from '@base-ui/react/select';
3
- import { Check, ChevronDown, ChevronUp, ChevronsUpDown } from 'lucide-react';
4
- import { cloneElement, createContext, forwardRef, useContext, useId, useState, } from 'react';
5
- import { ToneProvider, useToneContext } from "../../utils/Tone.js";
4
+ import { Check, ChevronDown, ChevronUp, ChevronsUpDown } from "../../utils/icons.js";
5
+ import { cloneElement, createContext, forwardRef, useContext, useEffect, useId, useState, } from 'react';
6
+ import { twMerge } from 'tailwind-merge';
7
+ import { readValidation, validationAttributes, validationMessageContent } from "../../utils/Validation.js";
6
8
  /**
7
9
  * Prepare groups in items. A flat-looking list is one group with an empty label and no GroupLabel; keep Group around ItemsList. OpenButtonValue already formats the selection: omit children unless a custom display is needed. Keep ScrollArea → GroupsList → Group → ItemsList → Item in Popup.
8
10
  *
@@ -88,22 +90,29 @@ import { ToneProvider, useToneContext } from "../../utils/Tone.js";
88
90
  * }
89
91
  * </Select.Root>
90
92
  */
91
- export function Root({ children, items, id, tone = 'neutral', open, defaultOpen = false, onOpenChange, ...props }) {
93
+ export function Root({ children, items, id, validation, defaultOpen = false, onOpenChange, ...props }) {
94
+ //1. Tracking the open state even when uncontrolled, so parts can carry data-open
95
+ const [openInternalState, setOpenInternalState] = useState(defaultOpen);
96
+ //2. Holding the ids of Description, Error and Success, so OpenButton announces them to screen readers through aria-describedby
97
+ const [describedByIds, setDescribedByIds] = useState([]);
98
+ //3. Sharing everything with the parts
92
99
  const generatedId = useId();
93
100
  const inputId = id ?? generatedId;
94
- const [openInternalState, setOpenInternalState] = useState(defaultOpen);
95
- return (_jsx(BaseSelect.Root, { ...props, items: items, id: inputId, open: open, defaultOpen: defaultOpen, isItemEqualToValue: (item, selected) => item.value === selected.value, onOpenChange: (nextOpen, details) => {
101
+ return (_jsx(BaseSelect.Root, { ...props, items: items, id: inputId, defaultOpen: defaultOpen, isItemEqualToValue: (item, selected) => item.value === selected.value, onOpenChange: (nextOpen, details) => {
96
102
  onOpenChange?.(nextOpen, details);
97
103
  if (!details.isCanceled)
98
104
  setOpenInternalState(nextOpen);
99
105
  }, children: _jsx(SelectContext.Provider, { value: {
100
106
  inputId,
101
107
  groups: items,
102
- open: open ?? openInternalState,
108
+ open: props.open ?? openInternalState,
103
109
  disabled: props.disabled ?? false,
104
110
  readOnly: props.readOnly ?? false,
105
111
  required: props.required ?? false,
106
- }, children: _jsx(ToneProvider, { value: tone, children: children }) }) }));
112
+ validation: readValidation(validation),
113
+ describedByIds,
114
+ setDescribedByIds,
115
+ }, children: children }) }));
107
116
  }
108
117
  export const Container = /* @__PURE__ */ forwardRef(function Container({ disableStyle, className, ...props }, ref) {
109
118
  return (_jsx("div", { ...props, ref: ref, "data-component": "select-container", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
@@ -117,14 +126,14 @@ export const Value = BaseSelect.Value;
117
126
  export function OpenButtonValue({ disableStyle, className, ...props }) {
118
127
  return (_jsx(BaseSelect.Value, { ...props, "data-component": "select-openbuttonvalue", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
119
128
  }
120
- export const ScrollArea = /* @__PURE__ */ forwardRef(function ScrollArea({ disableStyle, className, style, ...props }, ref) {
121
- return (_jsx(BaseSelect.List, { ...props, ref: ref, style: style, "data-component": "select-scrollarea", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
129
+ export const ScrollArea = /* @__PURE__ */ forwardRef(function ScrollArea({ disableStyle, className, ...props }, ref) {
130
+ return (_jsx(BaseSelect.List, { ...props, ref: ref, "data-component": "select-scrollarea", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
122
131
  });
123
132
  /** Let this list render the groups. Manually annotate its children callback with Select.GroupType<typeof rootItems>, using the SAME items variable passed to Root. */
124
- export function GroupsList({ disableStyle, children, className, style, ...props }) {
125
- const { groups } = useSelectContext();
126
- return (_jsx("div", { ...props, style: style, "data-component": "select-groupslist", "data-style-disabled": disableStyle ? '' : undefined, className: className, children: typeof children === 'function'
127
- ? groups.map((group, index) => children(group, index))
133
+ export function GroupsList({ disableStyle, children, className, ...props }) {
134
+ const context = useSelectContext();
135
+ return (_jsx("div", { ...props, "data-component": "select-groupslist", "data-style-disabled": disableStyle ? '' : undefined, className: className, children: typeof children === 'function'
136
+ ? context.groups.map((group, index) => children(group, index))
128
137
  : children }));
129
138
  }
130
139
  /** Let this list render the surrounding group. Manually annotate its callback with Select.ItemType<typeof rootItems>, using the SAME items variable passed to Root. */
@@ -151,13 +160,11 @@ export function Popup({ disableStyle, container, anchor, positionMethod, side =
151
160
  export const Arrow = /* @__PURE__ */ forwardRef(function Arrow({ disableStyle, className, style, ...props }, ref) {
152
161
  return (_jsxs(BaseSelect.Arrow, { style: style, render: _jsx("svg", { ...props, ref: ref, "aria-hidden": true, width: "20", height: "10", viewBox: "0 0 20 10" }), "data-component": "select-arrow", "data-style-disabled": disableStyle ? '' : undefined, className: className, children: [_jsx("path", { d: "M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z", "data-component": "select-arrow-1" }), _jsx("path", { d: "M8.99542 1.85876C9.75604 1.17425 10.9106 1.17422 11.6713 1.85878L16.5281 6.22989C17.0789 6.72568 17.7938 7.00001 18.5349 7.00001L15.89 7L11.0023 2.60207C10.622 2.2598 10.0447 2.2598 9.66436 2.60207L4.77734 7L2.13171 7.00001C2.87284 7.00001 3.58774 6.72568 4.13861 6.22989L8.99542 1.85876Z", "data-component": "select-arrow-2" }), _jsx("path", { d: "M10.3333 3.34539L5.47654 7.71648C4.55842 8.54279 3.36693 9 2.13172 9H0V8H2.13172C3.11989 8 4.07308 7.63423 4.80758 6.97318L9.66437 2.60207C10.0447 2.25979 10.622 2.2598 11.0023 2.60207L15.8591 6.97318C16.5936 7.63423 17.5468 8 18.5349 8H20V9H18.5349C17.2998 9 16.1083 8.54278 15.1901 7.71648L10.3333 3.34539Z", "data-component": "select-arrow-3" })] }));
153
162
  });
154
- /** Behavior only: give your child control this action. Style the child itself; this wrapper has no preset appearance or disableStyle prop. */
155
- export const PopupOpenHandler = /* @__PURE__ */ forwardRef(function PopupOpenHandler({ children, ...props }, ref) {
156
- return _jsx(BaseSelect.Trigger, { ...props, ref: ref, render: children });
157
- });
158
- export const OpenButton = /* @__PURE__ */ forwardRef(function OpenButton({ disableStyle, className, ...props }, ref) {
159
- const tone = useToneContext();
160
- return (_jsx(BaseSelect.Trigger, { "data-tone": tone, ...props, ref: ref, "data-component": "select-openbutton", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
163
+ /** Opens the select. Pass asChild to make your own button the trigger instead, like a "Sort" Button. */
164
+ export const OpenButton = /* @__PURE__ */ forwardRef(function OpenButton({ asChild, disableStyle, children, 'aria-describedby': describedBy, ...props }, ref) {
165
+ const context = useSelectContext();
166
+ const rendering = asChildRendering({ asChild, children, component: 'select-openbutton', disableStyle });
167
+ return _jsx(BaseSelect.Trigger, { ...validationAttributes(context.validation), "aria-invalid": context.validation.state === 'error' || props['aria-invalid'] || undefined, "aria-describedby": [describedBy, ...context.describedByIds].filter(Boolean).join(' ') || undefined, ...props, ref: ref, ...rendering });
161
168
  });
162
169
  /** Omit for an unlabeled/flat-looking group; keep the Group wrapper. Supply the heading only when grouping should be visible. */
163
170
  export const GroupLabel = /* @__PURE__ */ forwardRef(function GroupLabel({ disableStyle, className, ...props }, ref) {
@@ -169,24 +176,46 @@ export const Separator = /* @__PURE__ */ forwardRef(function Separator({ disable
169
176
  export const ItemText = /* @__PURE__ */ forwardRef(function ItemText({ disableStyle, className, ...props }, ref) {
170
177
  return (_jsx(BaseSelect.ItemText, { ...props, ref: ref, "data-component": "select-itemtext", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
171
178
  });
172
- export const Description = /* @__PURE__ */ forwardRef(function Description({ disableStyle, className, ...props }, ref) {
179
+ export const Description = /* @__PURE__ */ forwardRef(function Description({ disableStyle, className, id, ...props }, ref) {
180
+ const describedById = useDescribedById(id);
173
181
  const attributes = usePartAttributes();
174
- return (_jsx("div", { ...attributes, ...props, ref: ref, "data-component": "select-description", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
182
+ return (_jsx("div", { ...attributes, ...props, id: describedById, ref: ref, "data-component": "select-description", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
175
183
  });
176
- /** You decide when to show this feedback. Changing tone does not validate data or render the message for you. */
177
- export const Error = /* @__PURE__ */ forwardRef(function Error({ disableStyle, className, ...props }, ref) {
178
- const attributes = usePartAttributes();
179
- return (_jsx("div", { role: "alert", "aria-atomic": "true", ...attributes, ...props, ref: ref, "data-component": "select-error", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
184
+ /** Shows itself only while Root's validation is `'error'`: with no children it shows the message from `['error', message]`, a function children formats that message, and other children replace it. */
185
+ export const Error = /* @__PURE__ */ forwardRef(function Error({ children, ...props }, ref) {
186
+ const context = useSelectContext();
187
+ const content = validationMessageContent(context.validation, 'error', children);
188
+ if (content === undefined)
189
+ return null;
190
+ return _jsx(Message, { ...props, ref: ref, role: "alert", component: "select-error", children: content });
191
+ });
192
+ /** Shows itself only while Root's validation is `'success'`: with no children it shows the message from `['success', message]`, a function children formats that message, and other children replace it. */
193
+ export const Success = /* @__PURE__ */ forwardRef(function Success({ children, ...props }, ref) {
194
+ const context = useSelectContext();
195
+ const content = validationMessageContent(context.validation, 'success', children);
196
+ if (content === undefined)
197
+ return null;
198
+ return _jsx(Message, { ...props, ref: ref, role: "status", component: "select-success", children: content });
180
199
  });
181
- /** You decide when to show this feedback. Changing tone does not validate data or render the message for you. */
182
- export const Success = /* @__PURE__ */ forwardRef(function Success({ disableStyle, className, ...props }, ref) {
200
+ // The shared body of Error and Success, mounted only while they show, so only visible messages describe the select
201
+ const Message = /* @__PURE__ */ forwardRef(function Message({ disableStyle, className, id, component, ...props }, ref) {
202
+ const describedById = useDescribedById(id);
183
203
  const attributes = usePartAttributes();
184
- return (_jsx("div", { role: "status", "aria-atomic": "true", ...attributes, ...props, ref: ref, "data-component": "select-success", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
204
+ return _jsx("div", { "aria-atomic": "true", ...attributes, ...props, id: describedById, ref: ref, "data-component": component, "data-style-disabled": disableStyle ? '' : undefined, className: className });
185
205
  });
186
- /** Built-in icon; no children needed. Use it inside its matching control. */
187
- export const OpenButtonIcon = /* @__PURE__ */ forwardRef(function OpenButtonIcon({ disableStyle, className, strokeWidth = 1.5, ...props }, ref) {
206
+ /** Built-in icon. Use it inside its matching control. Omit children for the supplied default icon; pass an icon only to replace it. Defaults to strokeWidth 1.5. */
207
+ export const OpenButtonIcon = /* @__PURE__ */ forwardRef(function OpenButtonIcon({ disableStyle, className, strokeWidth, children, ...props }, ref) {
188
208
  const attributes = usePartAttributes();
189
- return (_jsx(ChevronsUpDown, { ...attributes, "aria-hidden": true, ...props, ref: ref, strokeWidth: strokeWidth, "data-component": "select-openbuttonicon", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
209
+ return cloneElement(children ?? _jsx(ChevronsUpDown, {}), {
210
+ ...attributes,
211
+ 'aria-hidden': true,
212
+ ...props,
213
+ ref,
214
+ strokeWidth: strokeWidth ?? children?.props.strokeWidth ?? 1.5,
215
+ 'data-component': 'select-openbuttonicon',
216
+ 'data-style-disabled': disableStyle ? '' : undefined,
217
+ className: twMerge(children?.props.className, className),
218
+ });
190
219
  });
191
220
  /** Tracks the surrounding item state automatically. Keep it mounted; do not add your own visibility condition. Use the supplied default visual unless customization is needed. */
192
221
  export const ItemIndicator = /* @__PURE__ */ forwardRef(function ItemIndicator({ disableStyle, children, keepMounted, ...props }, ref) {
@@ -220,15 +249,25 @@ function useSelectContext() {
220
249
  throw new globalThis.Error('Select parts must be inside Select.Root');
221
250
  return context;
222
251
  }
252
+ // The state attributes every part carries, so presets can style any part from Root's state
223
253
  function usePartAttributes() {
224
- const { open, disabled, readOnly, required } = useSelectContext();
225
- const tone = useToneContext();
254
+ const context = useSelectContext();
226
255
  return {
227
- 'data-open': open ? '' : undefined,
228
- 'data-disabled': disabled ? '' : undefined,
229
- 'data-readonly': readOnly ? '' : undefined,
230
- 'data-required': required ? '' : undefined,
231
- 'data-tone': tone,
256
+ 'data-open': context.open ? '' : undefined,
257
+ 'data-disabled': context.disabled ? '' : undefined,
258
+ 'data-readonly': context.readOnly ? '' : undefined,
259
+ 'data-required': context.required ? '' : undefined,
260
+ ...validationAttributes(context.validation),
232
261
  };
233
262
  }
234
- //# sourceMappingURL=index.js.map
263
+ // Registering a part's id in OpenButton's aria-describedby while the part is mounted
264
+ function useDescribedById(id) {
265
+ const context = useSelectContext();
266
+ const generatedId = useId();
267
+ const describedById = id ?? generatedId;
268
+ useEffect(() => {
269
+ context.setDescribedByIds((current) => [...current, describedById]);
270
+ return () => context.setDescribedByIds((current) => current.filter((currentId) => currentId !== describedById));
271
+ }, [describedById, context.setDescribedByIds]);
272
+ return describedById;
273
+ }
@@ -16,4 +16,3 @@ import type { HTMLAttributes } from 'react';
16
16
  * }
17
17
  */
18
18
  export default function Skeleton({ disableStyle, className, ...props }: HTMLAttributes<HTMLDivElement> & StyleProps): import("react").JSX.Element;
19
- //# sourceMappingURL=index.d.ts.map
@@ -17,4 +17,3 @@ import { jsx as _jsx } from "react/jsx-runtime";
17
17
  export default function Skeleton({ disableStyle, className, ...props }) {
18
18
  return (_jsx("div", { "data-component": "skeleton-skeleton", "data-style-disabled": disableStyle ? '' : undefined, className: className, ...props }));
19
19
  }
20
- //# sourceMappingURL=index.js.map
@@ -1,9 +1,11 @@
1
1
  import type { StyleProps } from '../../types/Style.ts';
2
2
  import { Slider as BaseSlider } from '@base-ui/react/slider';
3
- import type { ReactNode } from 'react';
3
+ import type { ComponentProps, ReactNode } from 'react';
4
+ import type { Validation } from '../../types/Validation.ts';
5
+ import type { ValidationMessageChildren } from '../../utils/Validation.ts';
4
6
  export type RootProps<Value extends number | readonly number[] = number | readonly number[]> = Omit<BaseSlider.Root.Props<Value>, 'render' | 'className'> & {
5
- /** Choose the visual tone. This does not validate data or show/hide feedback messages. */
6
- tone?: 'neutral' | 'valid' | 'invalid';
7
+ /** The slider's validation state, with an optional message: `'error'` styles it as invalid, `['error', 'Pick at least 10']` also shows that message in Error. Same for `'success'` and Success. Omit it for a neutral slider. */
8
+ validation?: Validation;
7
9
  };
8
10
  /**
9
11
  * Configure bounds and value on Root. Keep Track inside TrackGroup, then Indicator and indexed DragHandles inside Track. One handle adjusts a single value; a range needs a handle for each end. MarksList/Mark are optional labels, not interactive handles.
@@ -37,7 +39,7 @@ export type RootProps<Value extends number | readonly number[] = number | readon
37
39
  * <Slider.DragHandle index={1} aria-label="Maximum" />
38
40
  * </Slider.Track>
39
41
  */
40
- export declare function Root<Value extends number | readonly number[]>({ children, tone, ...props }: RootProps<Value>): import("react").JSX.Element;
42
+ export declare function Root<Value extends number | readonly number[]>({ children, validation, ...props }: RootProps<Value>): import("react").JSX.Element;
41
43
  export declare const Container: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
42
44
  export declare const Label: import("react").ForwardRefExoticComponent<Omit<Omit<import("@base-ui/react").SliderLabelProps, "className"> & {
43
45
  className?: string;
@@ -65,8 +67,11 @@ export declare const Mark: import("react").ForwardRefExoticComponent<Omit<import
65
67
  value: number;
66
68
  } & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
67
69
  export declare const Description: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
68
- /** You decide when to show this feedback. Changing tone does not validate data or render the message for you. */
69
- export declare const Error: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
70
- /** You decide when to show this feedback. Changing tone does not validate data or render the message for you. */
71
- export declare const Success: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
72
- //# sourceMappingURL=index.d.ts.map
70
+ type MessageProps = Omit<ComponentProps<'div'>, 'children'> & StyleProps & {
71
+ children?: ValidationMessageChildren;
72
+ };
73
+ /** Shows itself only while Root's validation is `'error'`: with no children it shows the message from `['error', message]`, a function children formats that message, and other children replace it. */
74
+ export declare const Error: import("react").ForwardRefExoticComponent<Omit<MessageProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
75
+ /** Shows itself only while Root's validation is `'success'`: with no children it shows the message from `['success', message]`, a function children formats that message, and other children replace it. */
76
+ export declare const Success: import("react").ForwardRefExoticComponent<Omit<MessageProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
77
+ export {};
@@ -2,7 +2,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
2
2
  import { Slider as BaseSlider } from '@base-ui/react/slider';
3
3
  import { useDirection } from '@base-ui/react/direction-provider';
4
4
  import { Fragment as ReactFragment, createContext, useCallback, forwardRef, useContext, useEffect, useId, useState, } from 'react';
5
- import { ToneProvider, useToneContext } from "../../utils/Tone.js";
5
+ import { readValidation, validationAttributes, validationMessageContent } from "../../utils/Validation.js";
6
6
  /**
7
7
  * Configure bounds and value on Root. Keep Track inside TrackGroup, then Indicator and indexed DragHandles inside Track. One handle adjusts a single value; a range needs a handle for each end. MarksList/Mark are optional labels, not interactive handles.
8
8
  *
@@ -35,18 +35,17 @@ import { ToneProvider, useToneContext } from "../../utils/Tone.js";
35
35
  * <Slider.DragHandle index={1} aria-label="Maximum" />
36
36
  * </Slider.Track>
37
37
  */
38
- export function Root({ children, tone = 'neutral', ...props }) {
38
+ export function Root({ children, validation, ...props }) {
39
39
  const [messageIds, setMessageIds] = useState([]);
40
- return (_jsx(ToneProvider, { value: tone, children: _jsx(BaseSlider.Root, { ...props, render: (rootProps, state) => {
41
- const { children, ...elementProps } = rootProps;
42
- return (_jsx(SliderContext.Provider, { value: { elementProps, state, messageIds, setMessageIds }, children: _jsx(_Fragment, { children: children }) }));
43
- }, children: children }) }));
40
+ return (_jsx(BaseSlider.Root, { ...props, render: (rootProps, state) => {
41
+ const { children, ...elementProps } = rootProps;
42
+ return (_jsx(SliderContext.Provider, { value: { elementProps, state, messageIds, setMessageIds, validation: readValidation(validation) }, children: _jsx(_Fragment, { children: children }) }));
43
+ }, children: children }));
44
44
  }
45
45
  export const Container = /* @__PURE__ */ forwardRef(function Container({ disableStyle, ...props }, ref) {
46
46
  const context = useSliderContext();
47
- const tone = useToneContext();
48
47
  const { ref: nativeRef, ...nativeProps } = context.elementProps;
49
- return (_jsx("div", { ...nativeProps, ...props, ref: useRootRef(nativeRef, ref), "data-tone": tone, "data-component": "slider-container", "data-style-disabled": disableStyle ? '' : undefined, className: props.className }));
48
+ return (_jsx("div", { ...nativeProps, ...props, ref: useRootRef(nativeRef, ref), ...validationAttributes(context.validation), "data-component": "slider-container", "data-style-disabled": disableStyle ? '' : undefined, className: props.className }));
50
49
  });
51
50
  export const Label = /* @__PURE__ */ forwardRef(function Label({ disableStyle, className, ...props }, ref) {
52
51
  return (_jsx(BaseSlider.Label, { ...props, ref: ref, "data-component": "slider-label", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
@@ -61,53 +60,60 @@ export const Track = /* @__PURE__ */ forwardRef(function Track({ disableStyle, c
61
60
  return (_jsx(BaseSlider.Track, { ...props, ref: ref, "data-component": "slider-track", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
62
61
  });
63
62
  export const Indicator = /* @__PURE__ */ forwardRef(function Indicator({ disableStyle, className, ...props }, ref) {
64
- const tone = useToneContext();
65
- return (_jsx(BaseSlider.Indicator, { ...props, ref: ref, "data-tone": tone, "data-component": "slider-indicator", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
63
+ const context = useSliderContext();
64
+ return (_jsx(BaseSlider.Indicator, { ...props, ref: ref, ...validationAttributes(context.validation), "data-component": "slider-indicator", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
66
65
  });
67
66
  export const DragHandle = /* @__PURE__ */ forwardRef(function DragHandle({ disableStyle, className, ...props }, ref) {
68
- const { messageIds } = useSliderContext();
69
- return (_jsx(BaseSlider.Thumb, { ...props, ref: ref, "aria-describedby": [props['aria-describedby'], ...messageIds].filter(Boolean).join(' ') ||
67
+ const context = useSliderContext();
68
+ return (_jsx(BaseSlider.Thumb, { ...props, ref: ref, "aria-invalid": context.validation.state === 'error' || props['aria-invalid'] || undefined, "aria-describedby": [props['aria-describedby'], ...context.messageIds].filter(Boolean).join(' ') ||
70
69
  undefined, "data-component": "slider-draghandle", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
71
70
  });
72
71
  export const MarksList = /* @__PURE__ */ forwardRef(function MarksList({ disableStyle, children, className, ...props }, ref) {
73
- const { state } = useSliderContext();
74
- const count = Math.floor(Number(((state.max - state.min) / state.step).toPrecision(15))) +
72
+ const context = useSliderContext();
73
+ const count = Math.floor(Number(((context.state.max - context.state.min) / context.state.step).toPrecision(15))) +
75
74
  1;
76
- return (_jsx("div", { ...props, ref: ref, "aria-hidden": true, "data-orientation": state.orientation, "data-component": "slider-markslist", "data-style-disabled": disableStyle ? '' : undefined, className: className, children: Array.from({ length: count }, (_, index) => {
77
- const value = Number((state.min + index * state.step).toPrecision(15));
75
+ return (_jsx("div", { ...props, ref: ref, "aria-hidden": true, "data-orientation": context.state.orientation, "data-component": "slider-markslist", "data-style-disabled": disableStyle ? '' : undefined, className: className, children: Array.from({ length: count }, (_, index) => {
76
+ const value = Number((context.state.min + index * context.state.step).toPrecision(15));
78
77
  return _jsx(ReactFragment, { children: children(value) }, value);
79
78
  }) }));
80
79
  });
81
80
  export const Mark = /* @__PURE__ */ forwardRef(function Mark({ disableStyle, value, children, className, style, ...props }, ref) {
82
- const { state } = useSliderContext();
81
+ const context = useSliderContext();
83
82
  const direction = useDirection();
84
- const percent = ((value - state.min) / (state.max - state.min)) * 100;
85
- return (_jsxs("div", { ...props, ref: ref, "aria-hidden": true, dir: direction, "data-orientation": state.orientation, style: {
86
- ...(state.orientation === 'vertical'
83
+ const percent = ((value - context.state.min) / (context.state.max - context.state.min)) * 100;
84
+ return (_jsxs("div", { ...props, ref: ref, "aria-hidden": true, dir: direction, "data-orientation": context.state.orientation, style: {
85
+ ...(context.state.orientation === 'vertical'
87
86
  ? { bottom: percent + '%' }
88
87
  : { insetInlineStart: percent + '%' }),
89
88
  ...style,
90
- }, "data-component": "slider-mark", "data-style-disabled": disableStyle ? '' : undefined, className: className, children: [_jsx("span", { "data-component": "slider-mark-1", "data-orientation": state.orientation }), children != null && (_jsx("span", { "data-orientation": state.orientation, "data-component": "slider-mark-2", children: children }))] }));
89
+ }, "data-component": "slider-mark", "data-style-disabled": disableStyle ? '' : undefined, className: className, children: [_jsx("span", { "data-component": "slider-mark-1", "data-orientation": context.state.orientation }), children != null && (_jsx("span", { "data-orientation": context.state.orientation, "data-component": "slider-mark-2", children: children }))] }));
91
90
  });
92
91
  export const Description = /* @__PURE__ */ forwardRef(function Description({ disableStyle, className, id, ...props }, ref) {
93
92
  const messageId = useMessageId(id);
94
93
  const context = useSliderContext();
95
- const tone = useToneContext();
96
- return (_jsx("div", { ...props, ref: ref, id: messageId, "data-disabled": context.state.disabled ? '' : undefined, "data-tone": tone, "data-component": "slider-description", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
94
+ return (_jsx("div", { ...props, ref: ref, id: messageId, "data-disabled": context.state.disabled ? '' : undefined, ...validationAttributes(context.validation), "data-component": "slider-description", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
97
95
  });
98
- /** You decide when to show this feedback. Changing tone does not validate data or render the message for you. */
99
- export const Error = /* @__PURE__ */ forwardRef(function Error({ disableStyle, className, id, ...props }, ref) {
100
- const messageId = useMessageId(id);
96
+ /** Shows itself only while Root's validation is `'error'`: with no children it shows the message from `['error', message]`, a function children formats that message, and other children replace it. */
97
+ export const Error = /* @__PURE__ */ forwardRef(function Error({ children, ...props }, ref) {
98
+ const context = useSliderContext();
99
+ const content = validationMessageContent(context.validation, 'error', children);
100
+ if (content === undefined)
101
+ return null;
102
+ return _jsx(Message, { ...props, ref: ref, role: "alert", component: "slider-error", children: content });
103
+ });
104
+ /** Shows itself only while Root's validation is `'success'`: with no children it shows the message from `['success', message]`, a function children formats that message, and other children replace it. */
105
+ export const Success = /* @__PURE__ */ forwardRef(function Success({ children, ...props }, ref) {
101
106
  const context = useSliderContext();
102
- const tone = useToneContext();
103
- return (_jsx("div", { role: "alert", "aria-atomic": "true", ...props, ref: ref, id: messageId, "data-disabled": context.state.disabled ? '' : undefined, "data-tone": tone, "data-component": "slider-error", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
107
+ const content = validationMessageContent(context.validation, 'success', children);
108
+ if (content === undefined)
109
+ return null;
110
+ return _jsx(Message, { ...props, ref: ref, role: "status", component: "slider-success", children: content });
104
111
  });
105
- /** You decide when to show this feedback. Changing tone does not validate data or render the message for you. */
106
- export const Success = /* @__PURE__ */ forwardRef(function Success({ disableStyle, className, id, ...props }, ref) {
112
+ // The shared body of Error and Success, mounted only while they show, so only visible messages describe the slider
113
+ const Message = /* @__PURE__ */ forwardRef(function Message({ disableStyle, className, id, component, ...props }, ref) {
107
114
  const messageId = useMessageId(id);
108
115
  const context = useSliderContext();
109
- const tone = useToneContext();
110
- return (_jsx("div", { role: "status", "aria-atomic": "true", ...props, ref: ref, id: messageId, "data-disabled": context.state.disabled ? '' : undefined, "data-tone": tone, "data-component": "slider-success", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
116
+ return _jsx("div", { "aria-atomic": "true", ...props, ref: ref, id: messageId, "data-disabled": context.state.disabled ? '' : undefined, ...validationAttributes(context.validation), "data-component": component, "data-style-disabled": disableStyle ? '' : undefined, className: className });
111
117
  });
112
118
  const SliderContext = /* @__PURE__ */ createContext(null);
113
119
  function useSliderContext() {
@@ -119,41 +125,36 @@ function useSliderContext() {
119
125
  function useMessageId(id) {
120
126
  const generatedId = useId();
121
127
  const messageId = id ?? generatedId;
122
- const { setMessageIds } = useSliderContext();
128
+ const context = useSliderContext();
123
129
  useEffect(() => {
124
- setMessageIds((current) => [...current, messageId]);
125
- return () => setMessageIds((current) => current.filter((value) => value !== messageId));
126
- }, [messageId, setMessageIds]);
130
+ context.setMessageIds((current) => [...current, messageId]);
131
+ return () => context.setMessageIds((current) => current.filter((value) => value !== messageId));
132
+ }, [messageId, context.setMessageIds]);
127
133
  return messageId;
128
134
  }
135
+ // Merging Base UI's ref with the consumer's one onto the same element
129
136
  function useRootRef(nativeRef, forwardedRef) {
130
137
  return useCallback((element) => {
131
- const nativeCleanup = typeof nativeRef === 'function'
132
- ? nativeRef(element)
133
- : nativeRef
134
- ? ((nativeRef.current = element), undefined)
135
- : undefined;
136
- const forwardedCleanup = typeof forwardedRef === 'function'
137
- ? forwardedRef(element)
138
- : forwardedRef
139
- ? ((forwardedRef.current = element), undefined)
140
- : undefined;
141
- if (typeof nativeCleanup === 'function' ||
142
- typeof forwardedCleanup === 'function')
143
- return () => {
144
- if (typeof nativeCleanup === 'function')
145
- nativeCleanup();
146
- else if (typeof nativeRef === 'function')
147
- nativeRef(null);
148
- else if (nativeRef)
149
- nativeRef.current = null;
150
- if (typeof forwardedCleanup === 'function')
151
- forwardedCleanup();
152
- else if (typeof forwardedRef === 'function')
153
- forwardedRef(null);
154
- else if (forwardedRef)
155
- forwardedRef.current = null;
156
- };
138
+ const refs = [nativeRef, forwardedRef];
139
+ //1. Setting both refs, keeping the cleanups that callback refs may return
140
+ const cleanups = refs.map((ref) => {
141
+ if (typeof ref === 'function')
142
+ return ref(element);
143
+ if (ref)
144
+ ref.current = element;
145
+ return undefined;
146
+ });
147
+ //2. Returning a cleanup only when a ref asked for one, since React then stops calling refs with null itself
148
+ if (!cleanups.some((cleanup) => typeof cleanup === 'function'))
149
+ return;
150
+ return () => refs.forEach((ref, index) => {
151
+ const cleanup = cleanups[index];
152
+ if (typeof cleanup === 'function')
153
+ return cleanup();
154
+ if (typeof ref === 'function')
155
+ return ref(null);
156
+ if (ref)
157
+ ref.current = null;
158
+ });
157
159
  }, [nativeRef, forwardedRef]);
158
160
  }
159
- //# sourceMappingURL=index.js.map
@@ -10,5 +10,4 @@ import type { SVGIconProps } from '../../types/Icon.ts';
10
10
  * return <Spinner.Spinner />
11
11
  * }
12
12
  */
13
- export declare function Spinner({ disableStyle, className, ...props }: SVGIconProps & StyleProps): import("react").JSX.Element;
14
- //# sourceMappingURL=index.d.ts.map
13
+ export declare function Spinner({ disableStyle, className, children, ...props }: SVGIconProps & StyleProps): import("react").JSX.Element;
@@ -9,7 +9,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
9
  * return <Spinner.Spinner />
10
10
  * }
11
11
  */
12
- export function Spinner({ disableStyle, className, ...props }) {
13
- return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", "data-component": "spinner-spinner", "data-style-disabled": disableStyle ? '' : undefined, className: className, strokeWidth: 3, ...props, children: [_jsx("circle", { cx: 12, cy: 12, r: 10, "data-component": "spinner-track" }), _jsx("circle", { cx: 12, cy: 12, r: 10, pathLength: 1, "data-component": "spinner-indicator" }), props.children] }));
12
+ export function Spinner({ disableStyle, className, children, ...props }) {
13
+ return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", "data-component": "spinner-spinner", "data-style-disabled": disableStyle ? '' : undefined, className: className, strokeWidth: 3, ...props, children: [_jsx("circle", { cx: 12, cy: 12, r: 10, "data-component": "spinner-track" }), _jsx("circle", { cx: 12, cy: 12, r: 10, pathLength: 1, "data-component": "spinner-indicator" }), children] }));
14
14
  }
15
- //# sourceMappingURL=index.js.map
@@ -42,8 +42,7 @@ export type RootProps = Pick<GroupProps, CoreKeys> & {
42
42
  */
43
43
  export declare function Root({ children, orientation, ...props }: RootProps): import("react").JSX.Element;
44
44
  export type ContentListProps = Omit<GroupProps, CoreKeys> & StyleProps;
45
- export declare function ContentList({ disableStyle, className, ...props }: ContentListProps & StyleProps): import("react").JSX.Element;
45
+ export declare function ContentList({ disableStyle, className, ...props }: ContentListProps): import("react").JSX.Element;
46
46
  export declare function Content({ disableStyle, className, ...props }: PanelProps & StyleProps): import("react").JSX.Element;
47
47
  export declare function Separator({ disableStyle, className, ...props }: SeparatorProps & StyleProps): import("react").JSX.Element;
48
48
  export declare function Handle({ disableStyle, className, children, ...props }: ComponentProps<'div'> & StyleProps): import("react").JSX.Element;
49
- //# sourceMappingURL=index.d.ts.map
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Group as ResizableGroup, Panel as ResizablePanel, Separator as ResizableSeparator, } from 'react-resizable-panels';
3
3
  import { createContext, useContext } from 'react';
4
- import { GripVertical } from 'lucide-react';
4
+ import { GripVertical } from "../../utils/icons.js";
5
5
  export { useGroupRef, useGroupCallbackRef, usePanelRef, usePanelCallbackRef, } from 'react-resizable-panels';
6
6
  // Only configuration lives here. ContentList renders the measured native Group.
7
7
  /**
@@ -49,13 +49,13 @@ export function Content({ disableStyle, className, ...props }) {
49
49
  return (_jsx(ResizablePanel, { ...props, "data-component": "splitter-content", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
50
50
  }
51
51
  export function Separator({ disableStyle, className, ...props }) {
52
- const { orientation } = useSplitterContext();
53
- return (_jsx(ResizableSeparator, { ...props, "data-orientation": orientation, "data-component": "splitter-separator", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
52
+ const context = useSplitterContext();
53
+ return (_jsx(ResizableSeparator, { ...props, "data-orientation": context.orientation, "data-component": "splitter-separator", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
54
54
  }
55
55
  // Native Separator explicitly supports children for a custom grip; all resize behavior stays native.
56
56
  export function Handle({ disableStyle, className, children = (_jsx(GripVertical, { "data-component": "splitter-handle-1", strokeWidth: 2, "aria-hidden": true })), ...props }) {
57
- const { orientation } = useSplitterContext();
58
- return (_jsx("div", { ...props, "data-orientation": orientation, "data-component": "splitter-handle", "data-style-disabled": disableStyle ? '' : undefined, className: className, children: children }));
57
+ const context = useSplitterContext();
58
+ return (_jsx("div", { ...props, "data-orientation": context.orientation, "data-component": "splitter-handle", "data-style-disabled": disableStyle ? '' : undefined, className: className, children: children }));
59
59
  }
60
60
  const SplitterContext = /* @__PURE__ */ createContext(null);
61
61
  function useSplitterContext() {
@@ -64,4 +64,3 @@ function useSplitterContext() {
64
64
  throw new Error('Splitter parts must be inside Splitter.Root');
65
65
  return context;
66
66
  }
67
- //# sourceMappingURL=index.js.map
@@ -1,12 +1,11 @@
1
1
  import type { StyleProps } from '../../types/Style.ts';
2
2
  import type { UseStepsProps } from '@ark-ui/react/steps';
3
3
  import { Steps } from '@ark-ui/react/steps';
4
- import type { ReactElement } from 'react';
5
4
  export declare function useSteps(props: UseStepsProps): import("@ark-ui/react/steps").UseStepsReturn;
6
5
  export { useStepsContext } from '@ark-ui/react/steps';
7
6
  export { useStepsItemContext } from '@ark-ui/react/steps';
8
7
  /**
9
- * Root owns the active step. Keep each Item in List with its index, and match Content indices to those items. NextHandler/PreviousHandler supply navigation to your buttons. Indicator reflects progress automatically; CompletedContent is shown after the last step.
8
+ * Root owns the active step. Keep each Item in List with its index, and match Content indices to those items. NextButton/PreviousButton navigate between steps; pass asChild to give their behavior to your own buttons instead. Indicator reflects progress automatically; CompletedContent is shown after the last step.
10
9
  *
11
10
  * @example Complete composition
12
11
  * import { Button, Stepper } from '@central-ui/react'
@@ -35,16 +34,12 @@ export { useStepsItemContext } from '@ark-ui/react/steps';
35
34
  * <Stepper.Content index={1}>Check everything.</Stepper.Content>
36
35
  * <Stepper.CompletedContent>Done.</Stepper.CompletedContent>
37
36
  * <div className="flex gap-2">
38
- * <Stepper.PreviousHandler>
39
- * <Button.default variant="secondary" size="small">
40
- * Previous
41
- * </Button.default>
42
- * </Stepper.PreviousHandler>
43
- * <Stepper.NextHandler>
37
+ * <Stepper.PreviousButton>Previous</Stepper.PreviousButton>
38
+ * <Stepper.NextButton asChild>
44
39
  * <Button.default variant="primary" size="small">
45
40
  * Next
46
41
  * </Button.default>
47
- * </Stepper.NextHandler>
42
+ * </Stepper.NextButton>
48
43
  * </div>
49
44
  * </div>
50
45
  * </div>
@@ -61,16 +56,10 @@ export { useStepsItemContext } from '@ark-ui/react/steps';
61
56
  * </Stepper.Root>
62
57
  */
63
58
  export declare function Root({ children, className, orientation, ...props }: Omit<Steps.RootProps, 'asChild'>): import("react").JSX.Element;
64
- /** Behavior only: give your child control this action. Style the child itself; this wrapper has no preset appearance or disableStyle prop. */
65
- export declare function NextHandler({ children, ...props }: Omit<Steps.NextTriggerProps, 'asChild' | 'children'> & {
66
- /** Supply your own accessible control. It receives the behavior; its own className owns the appearance. */
67
- children: ReactElement;
68
- }): import("react").JSX.Element;
69
- /** Behavior only: give your child control this action. Style the child itself; this wrapper has no preset appearance or disableStyle prop. */
70
- export declare function PreviousHandler({ children, ...props }: Omit<Steps.PrevTriggerProps, 'asChild' | 'children'> & {
71
- /** Supply your own accessible control. It receives the behavior; its own className owns the appearance. */
72
- children: ReactElement;
73
- }): import("react").JSX.Element;
59
+ /** Moves to the next step. Pass asChild to give this behavior to your own button, like a "Continue" Button; it keeps the state data attributes but none of this part's styling. */
60
+ export declare function NextButton({ asChild, disableStyle, ...props }: Steps.NextTriggerProps & StyleProps): import("react").JSX.Element;
61
+ /** Moves to the previous step. Pass asChild to give this behavior to your own button, like a "Back" Button; it keeps the state data attributes but none of this part's styling. */
62
+ export declare function PreviousButton({ asChild, disableStyle, ...props }: Steps.PrevTriggerProps & StyleProps): import("react").JSX.Element;
74
63
  export declare function List({ disableStyle, className, ...props }: Steps.ListProps & StyleProps): import("react").JSX.Element;
75
64
  export declare function Item({ disableStyle, className, ...props }: Steps.ItemProps & StyleProps): import("react").JSX.Element;
76
65
  /** Tracks the surrounding item state automatically. Keep it mounted; do not add your own visibility condition. Use the supplied default visual unless customization is needed. */
@@ -79,4 +68,3 @@ export declare function Separator({ disableStyle, className, ...props }: Steps.S
79
68
  export declare function Content({ disableStyle, className, ...props }: Steps.ContentProps & StyleProps): import("react").JSX.Element;
80
69
  export declare function CompletedContent({ disableStyle, className, ...props }: Steps.CompletedContentProps & StyleProps): import("react").JSX.Element;
81
70
  export declare function OpenButton({ disableStyle, className, ...props }: Steps.TriggerProps & StyleProps): import("react").JSX.Element;
82
- //# sourceMappingURL=index.d.ts.map