@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,6 +1,7 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ import { asChildStyleAttributes } from "../../utils/asChild.js";
2
3
  import { Steps, useSteps as useArkSteps } from '@ark-ui/react/steps';
3
- import { Check } from 'lucide-react';
4
+ import { Check } from "../../utils/icons.js";
4
5
  // Creates a controlled steps state machine for RootProvider.
5
6
  export function useSteps(props) {
6
7
  return useArkSteps({ orientation: 'vertical', ...props });
@@ -10,7 +11,7 @@ export { useStepsContext } from '@ark-ui/react/steps';
10
11
  // Reads the state of the nearest Steps item.
11
12
  export { useStepsItemContext } from '@ark-ui/react/steps';
12
13
  /**
13
- * 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.
14
+ * 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.
14
15
  *
15
16
  * @example Complete composition
16
17
  * import { Button, Stepper } from '@central-ui/react'
@@ -39,16 +40,12 @@ export { useStepsItemContext } from '@ark-ui/react/steps';
39
40
  * <Stepper.Content index={1}>Check everything.</Stepper.Content>
40
41
  * <Stepper.CompletedContent>Done.</Stepper.CompletedContent>
41
42
  * <div className="flex gap-2">
42
- * <Stepper.PreviousHandler>
43
- * <Button.default variant="secondary" size="small">
44
- * Previous
45
- * </Button.default>
46
- * </Stepper.PreviousHandler>
47
- * <Stepper.NextHandler>
43
+ * <Stepper.PreviousButton>Previous</Stepper.PreviousButton>
44
+ * <Stepper.NextButton asChild>
48
45
  * <Button.default variant="primary" size="small">
49
46
  * Next
50
47
  * </Button.default>
51
- * </Stepper.NextHandler>
48
+ * </Stepper.NextButton>
52
49
  * </div>
53
50
  * </div>
54
51
  * </div>
@@ -65,15 +62,18 @@ export { useStepsItemContext } from '@ark-ui/react/steps';
65
62
  * </Stepper.Root>
66
63
  */
67
64
  export function Root({ children, className, orientation = 'vertical', ...props }) {
65
+ // className is left out, since Root renders no element of its own to receive it
68
66
  return (_jsx(Steps.Root, { ...props, orientation: orientation, asChild: true, children: _jsx(_Fragment, { children: children }) }));
69
67
  }
70
- /** Behavior only: give your child control this action. Style the child itself; this wrapper has no preset appearance or disableStyle prop. */
71
- export function NextHandler({ children, ...props }) {
72
- return (_jsx(Steps.NextTrigger, { ...props, asChild: true, children: children }));
68
+ /** 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. */
69
+ export function NextButton({ asChild, disableStyle, ...props }) {
70
+ const styleAttributes = asChildStyleAttributes({ asChild, component: 'stepper-nextbutton', disableStyle });
71
+ return _jsx(Steps.NextTrigger, { ...props, asChild: asChild, ...styleAttributes });
73
72
  }
74
- /** Behavior only: give your child control this action. Style the child itself; this wrapper has no preset appearance or disableStyle prop. */
75
- export function PreviousHandler({ children, ...props }) {
76
- return (_jsx(Steps.PrevTrigger, { ...props, asChild: true, children: children }));
73
+ /** 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. */
74
+ export function PreviousButton({ asChild, disableStyle, ...props }) {
75
+ const styleAttributes = asChildStyleAttributes({ asChild, component: 'stepper-previousbutton', disableStyle });
76
+ return _jsx(Steps.PrevTrigger, { ...props, asChild: asChild, ...styleAttributes });
77
77
  }
78
78
  export function List({ disableStyle, className, ...props }) {
79
79
  return (_jsx(Steps.List, { "data-component": "stepper-list", "data-style-disabled": disableStyle ? '' : undefined, className: className, ...props }));
@@ -97,4 +97,3 @@ export function CompletedContent({ disableStyle, className, ...props }) {
97
97
  export function OpenButton({ disableStyle, className, ...props }) {
98
98
  return (_jsx(Steps.Trigger, { "data-component": "stepper-openbutton", "data-style-disabled": disableStyle ? '' : undefined, className: className, ...props }));
99
99
  }
100
- //# sourceMappingURL=index.js.map
@@ -1,11 +1,11 @@
1
1
  import type { StyleProps } from '../../types/Style.ts';
2
2
  import { Switch as BaseSwitch } from '@base-ui/react/switch';
3
- import type { ReactNode } from 'react';
3
+ import type { ComponentProps, ReactNode } from 'react';
4
+ import type { ValidationProps } from '../../types/Validation.ts';
5
+ import type { ValidationMessageChildren } from '../../utils/Validation.ts';
4
6
  type CoreKeys = 'checked' | 'defaultChecked' | 'onCheckedChange' | 'disabled' | 'readOnly' | 'required' | 'name' | 'value' | 'uncheckedValue' | 'form' | 'id' | 'inputRef';
5
- export type RootProps = Pick<BaseSwitch.Root.Props, CoreKeys> & {
7
+ export type RootProps = Pick<BaseSwitch.Root.Props, CoreKeys> & ValidationProps & {
6
8
  children: ReactNode;
7
- /** Choose the visual tone. This does not validate data or show/hide feedback messages. */
8
- tone?: 'neutral' | 'valid' | 'invalid';
9
9
  };
10
10
  /**
11
11
  * Keep Button, Indicator, and Label in the same Root. Indicator follows the checked state automatically; do not add a second boolean just for its position.
@@ -37,7 +37,7 @@ export type RootProps = Pick<BaseSwitch.Root.Props, CoreKeys> & {
37
37
  * </Switch.Container>
38
38
  * </Switch.Root>
39
39
  */
40
- export declare function Root({ children, tone, checked, defaultChecked, onCheckedChange, id, ...props }: RootProps): import("react").JSX.Element;
40
+ export declare function Root({ children, validation, checked, defaultChecked, onCheckedChange, id, ...props }: RootProps): import("react").JSX.Element;
41
41
  export declare const Container: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
42
42
  export declare const Button: import("react").ForwardRefExoticComponent<Omit<Omit<import("@base-ui/react").SwitchRootProps, "className" | "render" | "nativeButton" | CoreKeys> & {
43
43
  className?: string;
@@ -49,9 +49,11 @@ export declare const Indicator: import("react").ForwardRefExoticComponent<Omit<O
49
49
  /** Labels the associated control automatically. Supply the visible text; do not wire a second label association. */
50
50
  export declare const Label: import("react").ForwardRefExoticComponent<Omit<Omit<import("react").DetailedHTMLProps<import("react").LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, "htmlFor"> & StyleProps, "ref"> & import("react").RefAttributes<HTMLLabelElement>>;
51
51
  export declare const Description: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
52
- /** You decide when to show this feedback. Changing tone does not validate data or render the message for you. */
53
- export declare const Error: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
54
- /** You decide when to show this feedback. Changing tone does not validate data or render the message for you. */
55
- export declare const Success: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
52
+ type MessageProps = Omit<ComponentProps<'div'>, 'children'> & StyleProps & {
53
+ children?: ValidationMessageChildren;
54
+ };
55
+ /** 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. */
56
+ export declare const Error: import("react").ForwardRefExoticComponent<Omit<MessageProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
57
+ /** 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. */
58
+ export declare const Success: import("react").ForwardRefExoticComponent<Omit<MessageProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
56
59
  export {};
57
- //# sourceMappingURL=index.d.ts.map
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Switch as BaseSwitch } from '@base-ui/react/switch';
3
3
  import { createContext, forwardRef, useContext, useEffect, useId, useState, } from 'react';
4
- import { ToneProvider, useToneContext } from "../../utils/Tone.js";
4
+ import { readValidation, validationAttributes, validationMessageContent } from "../../utils/Validation.js";
5
5
  /**
6
6
  * Keep Button, Indicator, and Label in the same Root. Indicator follows the checked state automatically; do not add a second boolean just for its position.
7
7
  *
@@ -32,31 +32,36 @@ import { ToneProvider, useToneContext } from "../../utils/Tone.js";
32
32
  * </Switch.Container>
33
33
  * </Switch.Root>
34
34
  */
35
- export function Root({ children, tone = 'neutral', checked, defaultChecked = false, onCheckedChange, id, ...props }) {
36
- const generatedId = useId();
37
- const [messageIds, setMessageIds] = useState([]);
35
+ export function Root({ children, validation, checked, defaultChecked = false, onCheckedChange, id, ...props }) {
36
+ //1. Holding the checked state when nothing controls it from outside
38
37
  const [checkedInternalState, setCheckedInternalState] = useState(defaultChecked);
38
+ //2. Holding the ids of Description, Error and Success, so Button announces them to screen readers through aria-describedby
39
+ const [messageIds, setMessageIds] = useState([]);
40
+ //3. Sharing Base UI's props with Button, apart from what only the parts need
41
+ const generatedId = useId();
39
42
  return (_jsx(SwitchContext.Provider, { value: {
43
+ coreProps: {
44
+ ...props,
45
+ id: id ?? generatedId,
46
+ checked: checked ?? checkedInternalState,
47
+ onCheckedChange: (next, details) => {
48
+ onCheckedChange?.(next, details);
49
+ if (!details.isCanceled)
50
+ setCheckedInternalState(next);
51
+ },
52
+ },
40
53
  messageIds,
41
54
  setMessageIds,
42
- ...props,
43
- id: id ?? generatedId,
44
- checked: checked ?? checkedInternalState,
45
- onCheckedChange: (next, details) => {
46
- onCheckedChange?.(next, details);
47
- if (!details.isCanceled)
48
- setCheckedInternalState(next);
49
- },
50
- }, children: _jsx(ToneProvider, { value: tone, children: children }) }));
55
+ validation: readValidation(validation),
56
+ }, children: children }));
51
57
  }
52
58
  export const Container = /* @__PURE__ */ forwardRef(function Container({ disableStyle, className, ...props }, ref) {
53
59
  return (_jsx("div", { ...props, ref: ref, "data-component": "switch-container", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
54
60
  });
55
61
  export const Button = /* @__PURE__ */ forwardRef(function Button({ disableStyle, className, ...props }, ref) {
56
- const { messageIds, setMessageIds, ...context } = useSwitchContext();
57
- const tone = useToneContext();
58
- return (_jsx(BaseSwitch.Root, { ...props, ...context, "aria-invalid": tone === 'invalid' || props['aria-invalid'] || undefined, "aria-describedby": [props['aria-describedby'], ...messageIds].filter(Boolean).join(' ') ||
59
- undefined, ref: ref, "data-tone": tone, "data-component": "switch-button", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
62
+ const context = useSwitchContext();
63
+ return (_jsx(BaseSwitch.Root, { ...props, ...context.coreProps, "aria-invalid": context.validation.state === 'error' || props['aria-invalid'] || undefined, "aria-describedby": [props['aria-describedby'], ...context.messageIds].filter(Boolean).join(' ') ||
64
+ undefined, ref: ref, ...validationAttributes(context.validation), "data-component": "switch-button", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
60
65
  });
61
66
  /** 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. */
62
67
  export const Indicator = /* @__PURE__ */ forwardRef(function Indicator({ disableStyle, className, ...props }, ref) {
@@ -65,21 +70,32 @@ export const Indicator = /* @__PURE__ */ forwardRef(function Indicator({ disable
65
70
  /** Labels the associated control automatically. Supply the visible text; do not wire a second label association. */
66
71
  export const Label = /* @__PURE__ */ forwardRef(function Label({ disableStyle, className, ...props }, ref) {
67
72
  const context = useSwitchContext();
68
- return (_jsx("label", { ...props, ref: ref, htmlFor: context.id, "data-disabled": context.disabled ? '' : undefined, "data-component": "switch-label", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
73
+ return (_jsx("label", { ...props, ref: ref, htmlFor: context.coreProps.id, "data-disabled": context.coreProps.disabled ? '' : undefined, "data-component": "switch-label", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
69
74
  });
70
75
  export const Description = /* @__PURE__ */ forwardRef(function Description({ disableStyle, className, id, ...props }, ref) {
71
76
  const messageId = useMessageId(id);
72
77
  return (_jsx("div", { id: messageId, ...props, ref: ref, "data-component": "switch-description", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
73
78
  });
74
- /** You decide when to show this feedback. Changing tone does not validate data or render the message for you. */
75
- export const Error = /* @__PURE__ */ forwardRef(function Error({ disableStyle, className, id, ...props }, ref) {
76
- const messageId = useMessageId(id);
77
- return (_jsx("div", { id: messageId, ...props, ref: ref, role: "alert", "aria-atomic": "true", "data-component": "switch-error", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
79
+ /** 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. */
80
+ export const Error = /* @__PURE__ */ forwardRef(function Error({ children, ...props }, ref) {
81
+ const context = useSwitchContext();
82
+ const content = validationMessageContent(context.validation, 'error', children);
83
+ if (content === undefined)
84
+ return null;
85
+ return _jsx(Message, { ...props, ref: ref, role: "alert", component: "switch-error", children: content });
78
86
  });
79
- /** You decide when to show this feedback. Changing tone does not validate data or render the message for you. */
80
- export const Success = /* @__PURE__ */ forwardRef(function Success({ disableStyle, className, id, ...props }, ref) {
87
+ /** 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. */
88
+ export const Success = /* @__PURE__ */ forwardRef(function Success({ children, ...props }, ref) {
89
+ const context = useSwitchContext();
90
+ const content = validationMessageContent(context.validation, 'success', children);
91
+ if (content === undefined)
92
+ return null;
93
+ return _jsx(Message, { ...props, ref: ref, role: "status", component: "switch-success", children: content });
94
+ });
95
+ // The shared body of Error and Success, mounted only while they show, so only visible messages describe the switch
96
+ const Message = /* @__PURE__ */ forwardRef(function Message({ disableStyle, className, id, component, ...props }, ref) {
81
97
  const messageId = useMessageId(id);
82
- return (_jsx("div", { id: messageId, ...props, ref: ref, role: "status", "aria-atomic": "true", "data-component": "switch-success", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
98
+ return _jsx("div", { "aria-atomic": "true", ...props, id: messageId, ref: ref, "data-component": component, "data-style-disabled": disableStyle ? '' : undefined, className: className });
83
99
  });
84
100
  const SwitchContext = /* @__PURE__ */ createContext(null);
85
101
  function useSwitchContext() {
@@ -88,14 +104,14 @@ function useSwitchContext() {
88
104
  throw new globalThis.Error('Switch parts must be inside Switch.Root');
89
105
  return context;
90
106
  }
107
+ // Registering a message part's id in Button's aria-describedby while the part is mounted
91
108
  function useMessageId(id) {
92
109
  const generatedId = useId();
93
110
  const messageId = id ?? generatedId;
94
- const { setMessageIds } = useSwitchContext();
111
+ const context = useSwitchContext();
95
112
  useEffect(() => {
96
- setMessageIds((current) => [...current, messageId]);
97
- return () => setMessageIds((current) => current.filter((value) => value !== messageId));
98
- }, [messageId, setMessageIds]);
113
+ context.setMessageIds((current) => [...current, messageId]);
114
+ return () => context.setMessageIds((current) => current.filter((value) => value !== messageId));
115
+ }, [messageId, context.setMessageIds]);
99
116
  return messageId;
100
117
  }
101
- //# sourceMappingURL=index.js.map
@@ -94,8 +94,9 @@ export declare function Head({ disableStyle, className, ...props }: ComponentPro
94
94
  export declare const Body: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLTableSectionElement> & HTMLAttributes<HTMLTableSectionElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLTableSectionElement>>;
95
95
  export declare const Row: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLTableRowElement> & HTMLAttributes<HTMLTableRowElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLTableRowElement>>;
96
96
  export declare function HeadCell({ disableStyle, className, ...props }: ComponentProps<'th'> & StyleProps): import("react").JSX.Element;
97
+ /** Already styled as text: write plain text directly inside it, without a wrapping text element. Add your own elements only when the content needs more than plain text, like an avatar next to a name or a lighter secondary line. */
97
98
  export declare function Cell({ disableStyle, className, ...props }: ComponentProps<'td'> & StyleProps): import("react").JSX.Element;
98
- export declare function Empty({ disableStyle, className, children, ...props }: ComponentProps<'div'> & StyleProps): import("react").JSX.Element;
99
+ export declare function Empty({ disableStyle, className, ...props }: ComponentProps<'div'> & StyleProps): import("react").JSX.Element;
99
100
  export declare function EmptyBody({ disableStyle, className, ...props }: ComponentProps<'div'> & StyleProps): import("react").JSX.Element;
100
101
  export declare function EmptyTitle({ disableStyle, className, ...props }: HTMLAttributes<HTMLParagraphElement> & StyleProps): import("react").JSX.Element;
101
102
  export declare function EmptyDescription({ disableStyle, className, ...props }: ComponentProps<'p'> & StyleProps): import("react").JSX.Element;
@@ -105,6 +106,5 @@ export declare function EmptyIcon({ disableStyle, children, className, ...props
105
106
  /** Supply the decorative icon; the wrapper forwards the relevant state and preserves its classes. */
106
107
  children: ReactElement<ComponentProps<'svg'>>;
107
108
  }) & StyleProps): ReactElement<import("react").SVGProps<SVGSVGElement>, string | import("react").JSXElementConstructor<any>>;
108
- export declare function EmptyActionsList({ disableStyle, className, children, ...props }: ComponentProps<'div'> & StyleProps): import("react").JSX.Element;
109
+ export declare function EmptyActionsList({ disableStyle, className, ...props }: ComponentProps<'div'> & StyleProps): import("react").JSX.Element;
109
110
  export {};
110
- //# sourceMappingURL=index.d.ts.map
@@ -83,15 +83,16 @@ function usePinning() {
83
83
  * </Table.Root>
84
84
  */
85
85
  export function Root({ pinning, children, }) {
86
- const { scrollRef, edges, update } = useScrollEdges();
86
+ const scrollEdges = useScrollEdges();
87
+ // Pinning only while the pinned column would otherwise scroll out of view
87
88
  const activePinning = (() => {
88
- if (pinning === 'first' && edges.passedFirst)
89
+ if (pinning === 'first' && scrollEdges.edges.passedFirst)
89
90
  return 'first';
90
- if (pinning === 'last' && edges.hiddenLast)
91
+ if (pinning === 'last' && scrollEdges.edges.hiddenLast)
91
92
  return 'last';
92
93
  return null;
93
94
  })();
94
- return (_jsx(PinningContext.Provider, { value: { pinning: activePinning, scrollRef, update }, children: children }));
95
+ return (_jsx(PinningContext.Provider, { value: { pinning: activePinning, scrollRef: scrollEdges.scrollRef, update: scrollEdges.update }, children: children }));
95
96
  }
96
97
  function useScrollEdges() {
97
98
  const scrollRef = useRef(null);
@@ -104,6 +105,7 @@ function useScrollEdges() {
104
105
  scrollArea.scrollLeft >
105
106
  1,
106
107
  };
108
+ // Keeping the same state when nothing changed, so scrolling doesn't re-render on every pixel
107
109
  setEdges((current) => current.passedFirst === next.passedFirst &&
108
110
  current.hiddenLast === next.hiddenLast
109
111
  ? current
@@ -133,9 +135,9 @@ export function SurfaceFooter({ disableStyle, className, ...props }) {
133
135
  return (_jsx("div", { ...props, "data-component": "table-surfacefooter", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
134
136
  }
135
137
  export function ScrollArea({ disableStyle, className, onScroll, style, ...props }) {
136
- const { scrollRef, update } = useContext(PinningContext);
137
- return (_jsx("div", { ...props, ref: scrollRef, style: { ...style, overflowX: 'auto' }, onScroll: (event) => {
138
- update(event.currentTarget);
138
+ const pinning = useContext(PinningContext);
139
+ return (_jsx("div", { ...props, ref: pinning.scrollRef, style: { ...style, overflowX: 'auto' }, onScroll: (event) => {
140
+ pinning.update(event.currentTarget);
139
141
  onScroll?.(event);
140
142
  }, "data-component": "table-scrollarea", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
141
143
  }
@@ -173,12 +175,13 @@ export function HeadCell({ disableStyle, className, ...props }) {
173
175
  const pinning = usePinning();
174
176
  return (_jsx("th", { ...props, "data-pinning": pinning, "data-component": "table-headcell", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
175
177
  }
178
+ /** Already styled as text: write plain text directly inside it, without a wrapping text element. Add your own elements only when the content needs more than plain text, like an avatar next to a name or a lighter secondary line. */
176
179
  export function Cell({ disableStyle, className, ...props }) {
177
180
  const pinning = usePinning();
178
181
  return (_jsx("td", { ...props, "data-pinning": pinning, "data-component": "table-cell", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
179
182
  }
180
- export function Empty({ disableStyle, className, children, ...props }) {
181
- return (_jsx("div", { "data-component": "table-empty", "data-style-disabled": disableStyle ? '' : undefined, className: className, ...props, children: children }));
183
+ export function Empty({ disableStyle, className, ...props }) {
184
+ return (_jsx("div", { "data-component": "table-empty", "data-style-disabled": disableStyle ? '' : undefined, className: className, ...props }));
182
185
  }
183
186
  export function EmptyBody({ disableStyle, className, ...props }) {
184
187
  return (_jsx("div", { ...props, "data-component": "table-emptybody", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
@@ -195,7 +198,6 @@ export function EmptyImage({ disableStyle, className, ...props }) {
195
198
  /** Supply the decorative icon as a child. Its classes are preserved; interaction belongs to the surrounding control. */
196
199
  export function EmptyIcon({ disableStyle, children, className, ...props }) {
197
200
  return cloneElement(children, {
198
- ...children.props,
199
201
  ...props,
200
202
  ...{
201
203
  'data-component': 'table-emptyicon',
@@ -205,7 +207,6 @@ export function EmptyIcon({ disableStyle, children, className, ...props }) {
205
207
  strokeWidth: props.strokeWidth ?? children.props.strokeWidth ?? 1.5,
206
208
  });
207
209
  }
208
- export function EmptyActionsList({ disableStyle, className, children, ...props }) {
209
- return (_jsx("div", { "data-component": "table-emptyactionslist", "data-style-disabled": disableStyle ? '' : undefined, className: className, ...props, children: children }));
210
+ export function EmptyActionsList({ disableStyle, className, ...props }) {
211
+ return (_jsx("div", { "data-component": "table-emptyactionslist", "data-style-disabled": disableStyle ? '' : undefined, className: className, ...props }));
210
212
  }
211
- //# sourceMappingURL=index.js.map
@@ -64,4 +64,3 @@ export declare const Indicator: import("react").ForwardRefExoticComponent<Omit<O
64
64
  export declare const Content: import("react").ForwardRefExoticComponent<Omit<Omit<import("@base-ui/react").TabsPanelProps, "className"> & {
65
65
  className?: string;
66
66
  } & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
67
- //# sourceMappingURL=index.d.ts.map
@@ -66,7 +66,7 @@ export const Icon = /* @__PURE__ */ forwardRef(function Icon({ disableStyle, chi
66
66
  'data-component': 'tabs-icon',
67
67
  'data-style-disabled': disableStyle ? '' : undefined,
68
68
  },
69
- className: twMerge(children?.props.className, className),
69
+ className: twMerge(children.props.className, className),
70
70
  });
71
71
  });
72
72
  export const Indicator = /* @__PURE__ */ forwardRef(function Indicator({ disableStyle, className, ...props }, ref) {
@@ -75,4 +75,3 @@ export const Indicator = /* @__PURE__ */ forwardRef(function Indicator({ disable
75
75
  export const Content = /* @__PURE__ */ forwardRef(function Content({ disableStyle, className, ...props }, ref) {
76
76
  return (_jsx(BaseTabs.Panel, { ...props, ref: ref, "data-component": "tabs-content", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
77
77
  });
78
- //# sourceMappingURL=index.js.map
@@ -2,10 +2,12 @@ import type { StyleProps } from '../../types/Style.ts';
2
2
  import { Input as BaseInput } from '@base-ui/react/input';
3
3
  import type { SVGIconProps } from '../../types/Icon.ts';
4
4
  import type { ComponentProps, ReactElement, ReactNode } from 'react';
5
+ import type { Validation } from '../../types/Validation.ts';
6
+ import type { ValidationMessageChildren } from '../../utils/Validation.ts';
5
7
  export type RootProps = Pick<ComponentProps<'textarea'>, 'id' | 'name' | 'form' | 'value' | 'defaultValue' | 'disabled' | 'readOnly' | 'required'> & Pick<BaseInput.Props, 'onValueChange'> & {
6
8
  children?: ReactNode;
7
- /** Choose the visual tone. This does not validate data or show/hide feedback messages. */
8
- tone?: 'neutral' | 'valid' | 'invalid';
9
+ /** The field's validation state, with an optional message: `'error'` styles it as invalid, `['error', 'Email is required']` also shows that message in Error. Same for `'success'` and Success. Omit it for a neutral field. */
10
+ validation?: Validation;
9
11
  };
10
12
  /**
11
13
  * Keep value, name, and validation configuration on Root. Textarea is the editable control inside TextareaGroup. Optional Addon parts hold your supporting text or actions; they do not implement submission.
@@ -40,22 +42,23 @@ export type RootProps = Pick<ComponentProps<'textarea'>, 'id' | 'name' | 'form'
40
42
  * )
41
43
  * }
42
44
  */
43
- export declare function Root({ children, id, tone, value, defaultValue, onValueChange, disabled, readOnly, required, ...coreProps }: RootProps): import("react").JSX.Element;
45
+ export declare function Root({ children, id, validation, value, defaultValue, onValueChange, disabled, readOnly, required, ...coreProps }: RootProps): import("react").JSX.Element;
44
46
  export type TextareaProps = Omit<ComponentProps<'textarea'>, keyof Pick<RootProps, 'id' | 'name' | 'form' | 'value' | 'defaultValue' | 'onValueChange' | 'disabled' | 'readOnly' | 'required'>> & {
45
47
  className?: string;
46
48
  } & StyleProps;
47
- export declare const Textarea: import("react").ForwardRefExoticComponent<Omit<Omit<import("react").DetailedHTMLProps<import("react").TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>, "form" | "defaultValue" | "id" | "name" | "disabled" | "value" | "onValueChange" | "required" | "readOnly"> & {
48
- className?: string;
49
- } & StyleProps, "ref"> & import("react").RefAttributes<HTMLTextAreaElement>>;
49
+ export declare const Textarea: import("react").ForwardRefExoticComponent<Omit<TextareaProps, "ref"> & import("react").RefAttributes<HTMLTextAreaElement>>;
50
50
  export declare const TextareaGroup: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
51
51
  export declare const Container: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
52
52
  /** Labels the associated control automatically. Supply the visible text; do not wire a second label association. */
53
53
  export declare const Label: import("react").ForwardRefExoticComponent<Omit<Omit<import("react").DetailedHTMLProps<import("react").LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, "htmlFor"> & StyleProps, "ref"> & import("react").RefAttributes<HTMLLabelElement>>;
54
54
  export declare const Description: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
55
- /** You decide when to show this feedback. Changing tone does not validate data or render the message for you. */
56
- export declare const Error: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
57
- /** You decide when to show this feedback. Changing tone does not validate data or render the message for you. */
58
- export declare const Success: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
55
+ type MessageProps = Omit<ComponentProps<'div'>, 'children'> & StyleProps & {
56
+ children?: ValidationMessageChildren;
57
+ };
58
+ /** 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. */
59
+ export declare const Error: import("react").ForwardRefExoticComponent<Omit<MessageProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
60
+ /** 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. */
61
+ export declare const Success: import("react").ForwardRefExoticComponent<Omit<MessageProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
59
62
  export declare const Addon: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLDivElement> & import("react").HTMLAttributes<HTMLDivElement> & {
60
63
  /** Choose the preset appearance; this does not add action behavior. */
61
64
  variant?: "normal" | "emphasized";
@@ -69,4 +72,4 @@ export declare function AddonIcon({ disableStyle, children, className, ...props
69
72
  export declare const AddonButton: import("react").ForwardRefExoticComponent<Omit<import("react").ClassAttributes<HTMLButtonElement> & import("react").ButtonHTMLAttributes<HTMLButtonElement> & StyleProps, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
70
73
  /** Built-in icon; no children needed. Use it inside its matching control. */
71
74
  export declare const AddonLoadingIcon: import("react").ForwardRefExoticComponent<Omit<Omit<SVGIconProps, "children"> & StyleProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
72
- //# sourceMappingURL=index.d.ts.map
75
+ export {};
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Input as BaseInput } from '@base-ui/react/input';
3
- import { LoaderCircle } from 'lucide-react';
3
+ import { LoaderCircle } from "../../utils/icons.js";
4
4
  import { useRef } from 'react';
5
5
  import { useForwardClickToInput } from "../../utils/useForwardClickToInput.js";
6
6
  import { cloneElement, createContext, forwardRef, useContext, useEffect, useId, useState, } from 'react';
7
7
  import { twMerge } from 'tailwind-merge';
8
- import { ToneProvider, useToneContext } from "../../utils/Tone.js";
8
+ import { readValidation, validationAttributes, validationMessageContent } from "../../utils/Validation.js";
9
9
  /**
10
10
  * Keep value, name, and validation configuration on Root. Textarea is the editable control inside TextareaGroup. Optional Addon parts hold your supporting text or actions; they do not implement submission.
11
11
  *
@@ -39,12 +39,11 @@ import { ToneProvider, useToneContext } from "../../utils/Tone.js";
39
39
  * )
40
40
  * }
41
41
  */
42
- export function Root({ children, id, tone = 'neutral', value, defaultValue, onValueChange, disabled = false, readOnly = false, required = false, ...coreProps }) {
42
+ export function Root({ children, id, validation, value, defaultValue, onValueChange, disabled = false, readOnly = false, required = false, ...coreProps }) {
43
43
  const generatedId = useId();
44
44
  const [valueInternalState, setValueInternalState] = useState(defaultValue ?? '');
45
- const [connections, setConnections] = useState({
46
- descriptionIds: [],
47
- });
45
+ // Holding the ids of Description, Error and Success, so the control announces them to screen readers through aria-describedby
46
+ const [describedByIds, setDescribedByIds] = useState([]);
48
47
  return (_jsx(InputContext.Provider, { value: {
49
48
  inputId: id ?? generatedId,
50
49
  disabled,
@@ -56,24 +55,20 @@ export function Root({ children, id, tone = 'neutral', value, defaultValue, onVa
56
55
  controlled: value !== undefined,
57
56
  onValueChange,
58
57
  coreProps,
59
- connections,
60
- setConnections,
61
- }, children: _jsx(ToneProvider, { value: tone, children: children }) }));
58
+ describedByIds,
59
+ setDescribedByIds,
60
+ validation: readValidation(validation),
61
+ }, children: children }));
62
62
  }
63
- export const Textarea = /* @__PURE__ */ forwardRef(function Textarea({ disableStyle, className, onChange, 'aria-describedby': describedBy, ...props }, ref) {
63
+ export const Textarea = /* @__PURE__ */ forwardRef(function Textarea({ disableStyle, className, 'aria-describedby': describedBy, ...props }, ref) {
64
64
  const context = useInputContext();
65
- const tone = useToneContext();
66
65
  const inputRef = useRef(null);
66
+ // Resetting the internal value when the surrounding html form resets, since the control is always controlled by Root's value
67
67
  useEffect(() => {
68
68
  const form = inputRef.current?.form;
69
69
  if (!form || context.controlled)
70
70
  return;
71
- const reset = (event) => {
72
- queueMicrotask(() => {
73
- if (!event.defaultPrevented)
74
- context.setValueInternalState(context.defaultValue ?? '');
75
- });
76
- };
71
+ const reset = (event) => queueMicrotask(() => !event.defaultPrevented && context.setValueInternalState(context.defaultValue ?? ''));
77
72
  form.addEventListener('reset', reset);
78
73
  return () => form.removeEventListener('reset', reset);
79
74
  }, [
@@ -82,7 +77,7 @@ export const Textarea = /* @__PURE__ */ forwardRef(function Textarea({ disableSt
82
77
  context.setValueInternalState,
83
78
  context.coreProps.form,
84
79
  ]);
85
- return (_jsx(BaseInput, { ...context.coreProps, render: _jsx("textarea", { ...props, onChange: onChange }), id: context.inputId, disabled: context.disabled, readOnly: context.readOnly, required: context.required, value: context.value, "data-tone": tone, "aria-invalid": tone === 'invalid' || props['aria-invalid'] || undefined, "aria-describedby": [describedBy, ...context.connections.descriptionIds]
80
+ return (_jsx(BaseInput, { ...context.coreProps, render: _jsx("textarea", { ...props }), id: context.inputId, disabled: context.disabled, readOnly: context.readOnly, required: context.required, value: context.value, ...validationAttributes(context.validation), "aria-invalid": context.validation.state === 'error' || props['aria-invalid'] || undefined, "aria-describedby": [describedBy, ...context.describedByIds]
86
81
  .filter(Boolean)
87
82
  .join(' ') || undefined, ref: (element) => {
88
83
  inputRef.current = element;
@@ -110,13 +105,6 @@ export const Label = /* @__PURE__ */ forwardRef(function Label({ disableStyle, c
110
105
  const context = useInputContext();
111
106
  const labelId = id ?? context.inputId + '-label';
112
107
  const attributes = usePartAttributes();
113
- useEffect(() => {
114
- context.setConnections((current) => ({ ...current, labelId }));
115
- return () => context.setConnections((current) => ({
116
- ...current,
117
- labelId: current.labelId === labelId ? undefined : current.labelId,
118
- }));
119
- }, [labelId, context.setConnections]);
120
108
  return (_jsx("label", { ...attributes, ...props, id: labelId, ref: ref, htmlFor: context.inputId, "data-component": "textarea-label", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
121
109
  });
122
110
  export const Description = /* @__PURE__ */ forwardRef(function Description({ disableStyle, className, id, ...props }, ref) {
@@ -124,17 +112,27 @@ export const Description = /* @__PURE__ */ forwardRef(function Description({ dis
124
112
  const attributes = usePartAttributes();
125
113
  return (_jsx("div", { ...attributes, ...props, id: messageId, ref: ref, "data-component": "textarea-description", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
126
114
  });
127
- /** You decide when to show this feedback. Changing tone does not validate data or render the message for you. */
128
- export const Error = /* @__PURE__ */ forwardRef(function Error({ disableStyle, className, id, ...props }, ref) {
129
- const messageId = useMessageId(id);
130
- const attributes = usePartAttributes();
131
- return (_jsx("div", { role: "alert", "aria-atomic": "true", ...attributes, ...props, id: messageId, ref: ref, "data-component": "textarea-error", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
115
+ /** 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. */
116
+ export const Error = /* @__PURE__ */ forwardRef(function Error({ children, ...props }, ref) {
117
+ const context = useInputContext();
118
+ const content = validationMessageContent(context.validation, 'error', children);
119
+ if (content === undefined)
120
+ return null;
121
+ return _jsx(Message, { ...props, ref: ref, role: "alert", component: "textarea-error", children: content });
132
122
  });
133
- /** You decide when to show this feedback. Changing tone does not validate data or render the message for you. */
134
- export const Success = /* @__PURE__ */ forwardRef(function Success({ disableStyle, className, id, ...props }, ref) {
123
+ /** 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. */
124
+ export const Success = /* @__PURE__ */ forwardRef(function Success({ children, ...props }, ref) {
125
+ const context = useInputContext();
126
+ const content = validationMessageContent(context.validation, 'success', children);
127
+ if (content === undefined)
128
+ return null;
129
+ return _jsx(Message, { ...props, ref: ref, role: "status", component: "textarea-success", children: content });
130
+ });
131
+ // The shared body of Error and Success, mounted only while they show, so only visible messages describe the textarea
132
+ const Message = /* @__PURE__ */ forwardRef(function Message({ disableStyle, className, id, component, ...props }, ref) {
135
133
  const messageId = useMessageId(id);
136
134
  const attributes = usePartAttributes();
137
- return (_jsx("div", { role: "status", "aria-atomic": "true", ...attributes, ...props, id: messageId, ref: ref, "data-component": "textarea-success", "data-style-disabled": disableStyle ? '' : undefined, className: className }));
135
+ return _jsx("div", { "aria-atomic": "true", ...attributes, ...props, id: messageId, ref: ref, "data-component": component, "data-style-disabled": disableStyle ? '' : undefined, className: className });
138
136
  });
139
137
  export const Addon = /* @__PURE__ */ forwardRef(function Addon({ disableStyle, className, variant = 'normal', ...props }, ref) {
140
138
  const attributes = usePartAttributes();
@@ -178,28 +176,21 @@ function useInputContext() {
178
176
  }
179
177
  function usePartAttributes() {
180
178
  const context = useInputContext();
181
- const tone = useToneContext();
182
179
  return {
183
180
  'data-disabled': context.disabled ? '' : undefined,
184
181
  'data-readonly': context.readOnly ? '' : undefined,
185
182
  'data-required': context.required ? '' : undefined,
186
- 'data-tone': tone,
183
+ ...validationAttributes(context.validation),
187
184
  };
188
185
  }
186
+ // Registering a message part's id in the control's aria-describedby while the part is mounted
189
187
  function useMessageId(id) {
188
+ const context = useInputContext();
190
189
  const generatedId = useId();
191
190
  const messageId = id ?? generatedId;
192
- const context = useInputContext();
193
191
  useEffect(() => {
194
- context.setConnections((current) => ({
195
- ...current,
196
- descriptionIds: [...current.descriptionIds, messageId],
197
- }));
198
- return () => context.setConnections((current) => ({
199
- ...current,
200
- descriptionIds: current.descriptionIds.filter((id) => id !== messageId),
201
- }));
202
- }, [messageId, context.setConnections]);
192
+ context.setDescribedByIds((current) => [...current, messageId]);
193
+ return () => context.setDescribedByIds((current) => current.filter((currentId) => currentId !== messageId));
194
+ }, [messageId, context.setDescribedByIds]);
203
195
  return messageId;
204
196
  }
205
- //# sourceMappingURL=index.js.map
@@ -2,6 +2,9 @@ import type { StyleProps } from '../../types/Style.ts';
2
2
  import type { ComponentProps, HTMLAttributes, ReactElement } from 'react';
3
3
  /**
4
4
  * Adds preset styling to one link child without rendering a wrapper or handling navigation.
5
+ * Use it for a link presented as text, like "Read the guide" or "Create account" inside a
6
+ * sentence. To make a whole item clickable (a card, a list row), use your router's bare Link
7
+ * directly instead, without TextLink.
5
8
  * Pass a native anchor or your router's Link; put the destination and navigation props
6
9
  * on that child. Custom link components must forward className, style, and data-*
7
10
  * attributes to their anchor. Supply one element, not text, a fragment, or a list.
@@ -36,4 +39,3 @@ export default function TextLink({ disableStyle, children, className, style, ...
36
39
  */
37
40
  children: ReactElement<ComponentProps<'a'>>;
38
41
  }): ReactElement<import("react").DetailedHTMLProps<import("react").AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, string | import("react").JSXElementConstructor<any>>;
39
- //# sourceMappingURL=index.d.ts.map