@boxcustodia/library 2.0.0-alpha.19 → 2.0.0-alpha.20

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 (265) hide show
  1. package/dist/components/button/button.cjs.js +1 -1
  2. package/dist/components/button/button.es.js +19 -18
  3. package/dist/components/button/components/base-button.cjs.js +1 -1
  4. package/dist/components/button/components/base-button.es.js +20 -20
  5. package/dist/components/calendar/calendar.cjs.js +1 -1
  6. package/dist/components/calendar/calendar.es.js +1 -0
  7. package/dist/components/date-picker/date-input.cjs.js +1 -1
  8. package/dist/components/date-picker/date-input.es.js +92 -75
  9. package/dist/components/date-picker/date-picker.cjs.js +1 -1
  10. package/dist/components/date-picker/date-picker.es.js +104 -95
  11. package/dist/components/date-picker/date-picker.utils.cjs.js +1 -1
  12. package/dist/components/date-picker/date-picker.utils.es.js +51 -43
  13. package/dist/components/date-picker/use-hidden-field-value.cjs.js +1 -0
  14. package/dist/components/date-picker/use-hidden-field-value.es.js +11 -0
  15. package/dist/components/menu/menu.es.js +1 -9
  16. package/dist/components/otp/otp.cjs.js +2 -0
  17. package/dist/components/otp/otp.es.js +93 -0
  18. package/dist/components/password/password.cjs.js +1 -1
  19. package/dist/components/password/password.es.js +2 -2
  20. package/dist/components/select/select.cjs.js +1 -1
  21. package/dist/components/select/select.es.js +68 -60
  22. package/dist/hooks/internal/is-apple-device.cjs.js +1 -0
  23. package/dist/hooks/internal/is-apple-device.es.js +9 -0
  24. package/dist/hooks/internal/use-latest-ref.cjs.js +1 -0
  25. package/dist/hooks/internal/use-latest-ref.es.js +11 -0
  26. package/dist/hooks/use-array/use-array.cjs.js +1 -1
  27. package/dist/hooks/use-array/use-array.es.js +54 -42
  28. package/dist/hooks/use-async/use-async.cjs.js +1 -1
  29. package/dist/hooks/use-async/use-async.es.js +53 -20
  30. package/dist/hooks/use-boolean/use-boolean.cjs.js +1 -0
  31. package/dist/hooks/use-boolean/use-boolean.es.js +25 -0
  32. package/dist/hooks/use-click-outside/use-click-outside.cjs.js +1 -1
  33. package/dist/hooks/use-click-outside/use-click-outside.es.js +26 -12
  34. package/dist/hooks/use-debounce-callback/use-debounced-callback.cjs.js +1 -1
  35. package/dist/hooks/use-debounce-callback/use-debounced-callback.es.js +27 -10
  36. package/dist/hooks/use-debounce-value/use-debounced-value.cjs.js +1 -1
  37. package/dist/hooks/use-debounce-value/use-debounced-value.es.js +7 -9
  38. package/dist/hooks/use-disclosure/use-disclosure.cjs.js +1 -1
  39. package/dist/hooks/use-disclosure/use-disclosure.es.js +21 -11
  40. package/dist/hooks/use-document-title/use-document-title.cjs.js +1 -1
  41. package/dist/hooks/use-document-title/use-document-title.es.js +14 -12
  42. package/dist/hooks/use-event-listener/use-event-listener.cjs.js +1 -1
  43. package/dist/hooks/use-event-listener/use-event-listener.es.js +17 -9
  44. package/dist/hooks/use-hotkey/use-hotkey.cjs.js +1 -1
  45. package/dist/hooks/use-hotkey/use-hotkey.es.js +30 -14
  46. package/dist/hooks/use-hotkey/utils/is-input-field.cjs.js +1 -1
  47. package/dist/hooks/use-hotkey/utils/is-input-field.es.js +4 -2
  48. package/dist/hooks/use-hotkey/utils/match-and-run.cjs.js +1 -0
  49. package/dist/hooks/use-hotkey/utils/match-and-run.es.js +12 -0
  50. package/dist/hooks/use-hotkey/utils/match-key-modifiers.cjs.js +1 -1
  51. package/dist/hooks/use-hotkey/utils/match-key-modifiers.es.js +13 -12
  52. package/dist/hooks/use-hover/use-hover.cjs.js +1 -1
  53. package/dist/hooks/use-hover/use-hover.es.js +32 -17
  54. package/dist/hooks/use-is-visible/use-is-visible.cjs.js +1 -1
  55. package/dist/hooks/use-is-visible/use-is-visible.es.js +31 -27
  56. package/dist/hooks/use-local-storage/use-local-storage.cjs.js +1 -1
  57. package/dist/hooks/use-local-storage/use-local-storage.es.js +52 -20
  58. package/dist/hooks/use-media-query/use-media-query.cjs.js +1 -1
  59. package/dist/hooks/use-media-query/use-media-query.es.js +21 -11
  60. package/dist/hooks/use-mutation/use-mutation.cjs.js +1 -1
  61. package/dist/hooks/use-mutation/use-mutation.es.js +36 -22
  62. package/dist/hooks/use-object/use-object.cjs.js +1 -1
  63. package/dist/hooks/use-object/use-object.es.js +26 -22
  64. package/dist/hooks/use-prevent-page-close/use-prevent-page-close.cjs.js +1 -0
  65. package/dist/hooks/use-prevent-page-close/use-prevent-page-close.es.js +14 -0
  66. package/dist/hooks/use-step/use-step.cjs.js +1 -1
  67. package/dist/hooks/use-step/use-step.es.js +25 -24
  68. package/dist/index.cjs.js +1 -1
  69. package/dist/index.es.js +308 -300
  70. package/dist/src/components/date-picker/date-picker.utils.d.ts +17 -0
  71. package/dist/src/components/date-picker/use-hidden-field-value.d.ts +12 -0
  72. package/dist/src/components/index.d.ts +1 -0
  73. package/dist/src/hooks/index.d.ts +2 -2
  74. package/dist/src/hooks/internal/index.d.ts +2 -0
  75. package/dist/src/hooks/internal/is-apple-device.d.ts +12 -0
  76. package/dist/src/hooks/internal/use-latest-ref.d.ts +12 -0
  77. package/dist/src/hooks/use-array/use-array.d.ts +24 -11
  78. package/dist/src/hooks/use-async/use-async.d.ts +16 -13
  79. package/dist/src/hooks/use-boolean/index.d.ts +1 -0
  80. package/dist/src/hooks/use-boolean/use-boolean.d.ts +15 -0
  81. package/dist/src/hooks/use-boolean/use-boolean.test.d.ts +1 -0
  82. package/dist/src/hooks/use-click-outside/use-click-outside.d.ts +23 -1
  83. package/dist/src/hooks/use-debounce-callback/use-debounced-callback.d.ts +19 -1
  84. package/dist/src/hooks/use-debounce-value/use-debounced-value.d.ts +10 -1
  85. package/dist/src/hooks/use-disclosure/use-disclosure.d.ts +17 -8
  86. package/dist/src/hooks/use-document-title/use-document-title.d.ts +11 -0
  87. package/dist/src/hooks/use-event-listener/use-event-listener.d.ts +18 -1
  88. package/dist/src/hooks/use-hotkey/index.d.ts +2 -1
  89. package/dist/src/hooks/use-hotkey/use-hotkey.d.ts +62 -5
  90. package/dist/src/hooks/use-hotkey/utils/index.d.ts +4 -3
  91. package/dist/src/hooks/use-hotkey/utils/is-input-field.d.ts +12 -2
  92. package/dist/src/hooks/use-hotkey/utils/is-input-field.test.d.ts +1 -0
  93. package/dist/src/hooks/use-hotkey/utils/match-and-run.d.ts +36 -0
  94. package/dist/src/hooks/use-hotkey/utils/match-and-run.test.d.ts +1 -0
  95. package/dist/src/hooks/use-hotkey/utils/match-key-modifiers.d.ts +20 -6
  96. package/dist/src/hooks/use-hotkey/utils/match-key-modifiers.test.d.ts +1 -0
  97. package/dist/src/hooks/use-hover/use-hover.d.ts +8 -4
  98. package/dist/src/hooks/use-is-visible/use-is-visible.d.ts +28 -4
  99. package/dist/src/hooks/use-local-storage/use-local-storage.d.ts +13 -2
  100. package/dist/src/hooks/use-media-query/use-media-query.d.ts +10 -1
  101. package/dist/src/hooks/use-media-query/use-media-query.test.d.ts +1 -0
  102. package/dist/src/hooks/use-mutation/use-mutation.d.ts +18 -11
  103. package/dist/src/hooks/use-object/use-object.d.ts +15 -6
  104. package/dist/src/hooks/use-prevent-page-close/index.d.ts +1 -0
  105. package/dist/src/hooks/use-prevent-page-close/use-prevent-page-close.d.ts +10 -0
  106. package/dist/src/hooks/use-prevent-page-close/use-prevent-page-close.test.d.ts +1 -0
  107. package/dist/src/hooks/use-step/use-step.d.ts +18 -11
  108. package/dist/src/utils/form.d.ts +10 -0
  109. package/package.json +1 -1
  110. package/src/components/alert-dialog/alert-dialog.test.tsx +13 -9
  111. package/src/components/auto-complete/auto-complete.test.tsx +4 -14
  112. package/src/components/avatar/avatar.test.tsx +7 -12
  113. package/src/components/button/button.test.tsx +10 -15
  114. package/src/components/button/button.tsx +14 -9
  115. package/src/components/button/components/base-button.tsx +2 -4
  116. package/src/components/calendar/calendar.test.tsx +12 -19
  117. package/src/components/calendar/calendar.tsx +4 -0
  118. package/src/components/card/card.test.tsx +4 -6
  119. package/src/components/checkbox/checkbox.test.tsx +12 -8
  120. package/src/components/checkbox-group/checkbox-group.test.tsx +7 -8
  121. package/src/components/combobox/combobox.test.tsx +24 -21
  122. package/src/components/date-picker/date-input-form.test.tsx +77 -0
  123. package/src/components/date-picker/date-input.stories.tsx +30 -18
  124. package/src/components/date-picker/date-input.tsx +77 -44
  125. package/src/components/date-picker/date-picker.stories.tsx +31 -1
  126. package/src/components/date-picker/date-picker.test.tsx +3 -13
  127. package/src/components/date-picker/date-picker.tsx +35 -16
  128. package/src/components/date-picker/date-picker.utils.test.ts +32 -14
  129. package/src/components/date-picker/date-picker.utils.ts +33 -0
  130. package/src/components/date-picker/use-date-input-popover.test.ts +3 -1
  131. package/src/components/date-picker/use-hidden-field-value.ts +23 -0
  132. package/src/components/dialog/dialog.test.tsx +10 -8
  133. package/src/components/dropzone/dropzone.test.tsx +11 -13
  134. package/src/components/empty/empty.test.tsx +4 -3
  135. package/src/components/field/field.test.tsx +12 -13
  136. package/src/components/form/form.stories.tsx +16 -1
  137. package/src/components/index.ts +1 -0
  138. package/src/components/label/label.test.tsx +3 -3
  139. package/src/components/menu/menu.tsx +1 -5
  140. package/src/components/number-input/number-input.test.tsx +6 -2
  141. package/src/components/password/password.test.tsx +20 -6
  142. package/src/components/password/password.tsx +2 -2
  143. package/src/components/popover/popover.test.tsx +4 -4
  144. package/src/components/progress/progress.test.tsx +7 -8
  145. package/src/components/radio-group/radio-group.test.tsx +17 -11
  146. package/src/components/select/select.test.tsx +10 -10
  147. package/src/components/select/select.tsx +9 -1
  148. package/src/components/stepper/stepper.stories.tsx +11 -15
  149. package/src/components/stepper/stepper.test.tsx +6 -4
  150. package/src/components/switch/switch.test.tsx +3 -3
  151. package/src/components/table/table.test.tsx +9 -3
  152. package/src/components/tabs/tabs.test.tsx +6 -2
  153. package/src/components/tag/tag.test.tsx +1 -3
  154. package/src/components/textarea/textarea.test.tsx +4 -1
  155. package/src/components/timeline/timeline.test.tsx +10 -5
  156. package/src/components/toast/toast.test.tsx +11 -14
  157. package/src/components/tooltip/tooltip.test.tsx +1 -5
  158. package/src/components/tree/tree.test.tsx +3 -1
  159. package/src/hooks/index.ts +2 -2
  160. package/src/hooks/internal/index.ts +2 -0
  161. package/src/hooks/internal/is-apple-device.test.ts +41 -0
  162. package/src/hooks/internal/is-apple-device.ts +33 -0
  163. package/src/hooks/internal/use-isomorphic-layout-effect.ts +3 -1
  164. package/src/hooks/internal/use-latest-ref.ts +21 -0
  165. package/src/hooks/use-array/use-array.stories.tsx +435 -64
  166. package/src/hooks/use-array/use-array.test.tsx +398 -15
  167. package/src/hooks/use-array/use-array.ts +105 -66
  168. package/src/hooks/use-async/use-async.stories.tsx +255 -131
  169. package/src/hooks/use-async/use-async.test.ts +397 -0
  170. package/src/hooks/use-async/use-async.ts +117 -39
  171. package/src/hooks/use-boolean/index.ts +1 -0
  172. package/src/hooks/use-boolean/use-boolean.stories.tsx +377 -0
  173. package/src/hooks/use-boolean/use-boolean.test.tsx +177 -0
  174. package/src/hooks/use-boolean/use-boolean.ts +50 -0
  175. package/src/hooks/use-click-outside/use-click-outside.stories.tsx +188 -18
  176. package/src/hooks/use-click-outside/use-click-outside.test.tsx +89 -10
  177. package/src/hooks/use-click-outside/use-click-outside.ts +62 -16
  178. package/src/hooks/use-debounce-callback/use-debounced-callback.stories.tsx +141 -41
  179. package/src/hooks/use-debounce-callback/use-debounced-callback.test.ts +217 -9
  180. package/src/hooks/use-debounce-callback/use-debounced-callback.ts +71 -11
  181. package/src/hooks/use-debounce-value/use-debounced-value.stories.tsx +247 -47
  182. package/src/hooks/use-debounce-value/use-debounced-value.test.ts +105 -10
  183. package/src/hooks/use-debounce-value/use-debounced-value.ts +19 -10
  184. package/src/hooks/use-disclosure/use-disclosure.stories.tsx +305 -14
  185. package/src/hooks/use-disclosure/use-disclosure.test.ts +198 -50
  186. package/src/hooks/use-disclosure/use-disclosure.ts +49 -29
  187. package/src/hooks/use-document-title/use-document-title.stories.tsx +54 -0
  188. package/src/hooks/use-document-title/use-document-title.test.tsx +26 -0
  189. package/src/hooks/use-document-title/{use-document-title.tsx → use-document-title.ts} +17 -3
  190. package/src/hooks/use-event-listener/use-event-listener.stories.tsx +105 -9
  191. package/src/hooks/use-event-listener/use-event-listener.test.tsx +77 -10
  192. package/src/hooks/use-event-listener/use-event-listener.ts +71 -11
  193. package/src/hooks/use-focus-trap/use-focus-trap.test.ts +31 -6
  194. package/src/hooks/use-focus-trap/use-focus-trap.ts +3 -2
  195. package/src/hooks/use-hotkey/index.ts +9 -1
  196. package/src/hooks/use-hotkey/use-hotkey.stories.tsx +279 -74
  197. package/src/hooks/use-hotkey/use-hotkey.test.tsx +286 -34
  198. package/src/hooks/use-hotkey/use-hotkey.ts +141 -17
  199. package/src/hooks/use-hotkey/utils/index.ts +8 -3
  200. package/src/hooks/use-hotkey/utils/is-input-field.test.ts +78 -0
  201. package/src/hooks/use-hotkey/utils/is-input-field.ts +31 -10
  202. package/src/hooks/use-hotkey/utils/match-and-run.test.ts +203 -0
  203. package/src/hooks/use-hotkey/utils/match-and-run.ts +62 -0
  204. package/src/hooks/use-hotkey/utils/match-key-modifiers.test.ts +65 -0
  205. package/src/hooks/use-hotkey/utils/match-key-modifiers.ts +39 -12
  206. package/src/hooks/use-hover/use-hover.stories.tsx +258 -80
  207. package/src/hooks/use-hover/use-hover.test.tsx +266 -26
  208. package/src/hooks/use-hover/use-hover.tsx +93 -28
  209. package/src/hooks/use-is-visible/use-is-visible.stories.tsx +193 -46
  210. package/src/hooks/use-is-visible/use-is-visible.test.tsx +235 -7
  211. package/src/hooks/use-is-visible/use-is-visible.ts +114 -0
  212. package/src/hooks/use-local-storage/use-local-storage.stories.tsx +129 -29
  213. package/src/hooks/use-local-storage/use-local-storage.test.ts +106 -41
  214. package/src/hooks/use-local-storage/use-local-storage.ts +100 -31
  215. package/src/hooks/use-media-query/use-media-query.stories.tsx +86 -26
  216. package/src/hooks/use-media-query/use-media-query.test.ts +132 -0
  217. package/src/hooks/use-media-query/use-media-query.ts +39 -14
  218. package/src/hooks/use-memoized-fn/use-memoized-fn.ts +0 -1
  219. package/src/hooks/use-mutation/use-mutation.stories.tsx +260 -94
  220. package/src/hooks/use-mutation/use-mutation.test.ts +359 -0
  221. package/src/hooks/use-mutation/use-mutation.ts +97 -0
  222. package/src/hooks/use-object/use-object.stories.tsx +310 -79
  223. package/src/hooks/use-object/use-object.test.tsx +235 -56
  224. package/src/hooks/use-object/use-object.ts +59 -0
  225. package/src/hooks/use-pagination/use-pagination.tsx +0 -1
  226. package/src/hooks/use-prevent-page-close/index.ts +1 -0
  227. package/src/hooks/use-prevent-page-close/use-prevent-page-close.stories.tsx +39 -0
  228. package/src/hooks/use-prevent-page-close/use-prevent-page-close.test.ts +89 -0
  229. package/src/hooks/use-prevent-page-close/use-prevent-page-close.ts +27 -0
  230. package/src/hooks/use-range-pagination/use-range-pagination.test.tsx +1 -1
  231. package/src/hooks/use-range-pagination/use-range-pagination.tsx +1 -1
  232. package/src/hooks/use-selection/use-selection.ts +0 -1
  233. package/src/hooks/use-step/use-step.stories.tsx +178 -65
  234. package/src/hooks/use-step/use-step.test.ts +178 -53
  235. package/src/hooks/use-step/use-step.ts +57 -49
  236. package/src/utils/form.test.tsx +13 -8
  237. package/src/utils/form.tsx +10 -0
  238. package/src/utils/functions/getFormData.test.ts +1 -1
  239. package/dist/hooks/use-hotkey/utils/create-hotkey-listener.cjs.js +0 -1
  240. package/dist/hooks/use-hotkey/utils/create-hotkey-listener.es.js +0 -10
  241. package/dist/hooks/use-prevent-close-window/use-prevent-close-window.cjs.js +0 -1
  242. package/dist/hooks/use-prevent-close-window/use-prevent-close-window.es.js +0 -15
  243. package/dist/hooks/use-toggle/use-toggle.cjs.js +0 -1
  244. package/dist/hooks/use-toggle/use-toggle.es.js +0 -10
  245. package/dist/src/hooks/use-hotkey/utils/create-hotkey-listener.d.ts +0 -1
  246. package/dist/src/hooks/use-prevent-close-window/index.d.ts +0 -1
  247. package/dist/src/hooks/use-prevent-close-window/use-prevent-close-window.d.ts +0 -13
  248. package/dist/src/hooks/use-toggle/index.d.ts +0 -1
  249. package/dist/src/hooks/use-toggle/use-toggle.d.ts +0 -3
  250. package/src/hooks/use-async/use-async.test.tsx +0 -68
  251. package/src/hooks/use-hotkey/utils/create-hotkey-listener.ts +0 -25
  252. package/src/hooks/use-is-visible/use-is-visible.tsx +0 -49
  253. package/src/hooks/use-mutation/use-mutation.test.tsx +0 -83
  254. package/src/hooks/use-mutation/use-mutation.tsx +0 -59
  255. package/src/hooks/use-object/use-object.tsx +0 -46
  256. package/src/hooks/use-prevent-close-window/index.ts +0 -1
  257. package/src/hooks/use-prevent-close-window/use-prevent-close-window.stories.tsx +0 -32
  258. package/src/hooks/use-prevent-close-window/use-prevent-close-window.test.ts +0 -79
  259. package/src/hooks/use-prevent-close-window/use-prevent-close-window.ts +0 -33
  260. package/src/hooks/use-toggle/index.ts +0 -1
  261. package/src/hooks/use-toggle/use-toggle.stories.tsx +0 -25
  262. package/src/hooks/use-toggle/use-toggle.test.tsx +0 -64
  263. package/src/hooks/use-toggle/use-toggle.ts +0 -14
  264. /package/dist/src/{hooks/use-prevent-close-window/use-prevent-close-window.test.d.ts → components/date-picker/date-input-form.test.d.ts} +0 -0
  265. /package/dist/src/hooks/{use-toggle/use-toggle.test.d.ts → internal/is-apple-device.test.d.ts} +0 -0
@@ -0,0 +1,23 @@
1
+ import { useEffect, useRef } from "react";
2
+ import { emitNativeInputChange } from "./date-picker.utils";
3
+
4
+ /**
5
+ * Drives a hidden Base UI `FieldControl` input from a derived form value.
6
+ *
7
+ * The input is left uncontrolled and updated imperatively so a native `input`
8
+ * event fires on every change. Base UI re-runs Field validation (and clears the
9
+ * error) only inside the control's `onChange` — never from a React `value` prop
10
+ * — so date changes coming from the calendar or the visible input must emit a
11
+ * real event for the invalid state to clear.
12
+ *
13
+ * Returns the ref to attach to the hidden input.
14
+ */
15
+ export function useHiddenFieldValue(value: string) {
16
+ const ref = useRef<HTMLInputElement>(null);
17
+
18
+ useEffect(() => {
19
+ emitNativeInputChange(ref.current, value);
20
+ }, [value]);
21
+
22
+ return ref;
23
+ }
@@ -162,9 +162,9 @@ describe("Dialog component", () => {
162
162
  <DialogPopup className="custom-popup-class">Content</DialogPopup>
163
163
  </DialogRoot>,
164
164
  );
165
- expect(
166
- document.querySelector('[data-slot="dialog-popup"]'),
167
- ).toHaveClass("custom-popup-class");
165
+ expect(document.querySelector('[data-slot="dialog-popup"]')).toHaveClass(
166
+ "custom-popup-class",
167
+ );
168
168
  });
169
169
  });
170
170
 
@@ -177,7 +177,9 @@ describe("Dialog component", () => {
177
177
  </DialogPopup>
178
178
  </DialogRoot>,
179
179
  );
180
- expect(screen.getByRole("button", { name: "Cerrar" })).toBeInTheDocument();
180
+ expect(
181
+ screen.getByRole("button", { name: "Cerrar" }),
182
+ ).toBeInTheDocument();
181
183
  });
182
184
 
183
185
  it("hides close button when hideClose is true", () => {
@@ -230,9 +232,7 @@ describe("Dialog component", () => {
230
232
  </DialogRoot>,
231
233
  );
232
234
  // Close button is wrapped in a Button with the closeButton class
233
- expect(
234
- document.querySelector(".custom-close-btn"),
235
- ).toBeInTheDocument();
235
+ expect(document.querySelector(".custom-close-btn")).toBeInTheDocument();
236
236
  });
237
237
  });
238
238
 
@@ -306,7 +306,9 @@ describe("Dialog composite", () => {
306
306
  setup({ onClose });
307
307
  click(screen.getByRole("button", { name: "Open" }));
308
308
  await waitFor(() =>
309
- expect(screen.getByRole("button", { name: "Cerrar" })).toBeInTheDocument(),
309
+ expect(
310
+ screen.getByRole("button", { name: "Cerrar" }),
311
+ ).toBeInTheDocument(),
310
312
  );
311
313
  click(screen.getByRole("button", { name: "Cerrar" }));
312
314
  await waitFor(() => expect(onClose).toHaveBeenCalledTimes(1));
@@ -16,7 +16,9 @@ import {
16
16
  describe("DropzoneRoot", () => {
17
17
  it("renders with data-slot dropzone", () => {
18
18
  render(<DropzoneRoot />);
19
- expect(document.querySelector('[data-slot="dropzone"]')).toBeInTheDocument();
19
+ expect(
20
+ document.querySelector('[data-slot="dropzone"]'),
21
+ ).toBeInTheDocument();
20
22
  });
21
23
 
22
24
  it("applies className to root div", () => {
@@ -136,15 +138,11 @@ describe("DropzoneItem", () => {
136
138
 
137
139
  it("applies className", () => {
138
140
  render(
139
- <DropzoneItem
140
- file={file}
141
- onRemove={vi.fn()}
142
- className="custom-item"
143
- />,
141
+ <DropzoneItem file={file} onRemove={vi.fn()} className="custom-item" />,
142
+ );
143
+ expect(document.querySelector('[data-slot="dropzone-item"]')).toHaveClass(
144
+ "custom-item",
144
145
  );
145
- expect(
146
- document.querySelector('[data-slot="dropzone-item"]'),
147
- ).toHaveClass("custom-item");
148
146
  });
149
147
  });
150
148
 
@@ -247,15 +245,15 @@ describe("Dropzone composite", () => {
247
245
 
248
246
  it("shows allowed extensions when provided", () => {
249
247
  render(<Dropzone allowedExtensions={["image/png", "image/jpeg"]} />);
250
- expect(
251
- screen.getByText(/Tipos permitidos/),
252
- ).toBeInTheDocument();
248
+ expect(screen.getByText(/Tipos permitidos/)).toBeInTheDocument();
253
249
  });
254
250
 
255
251
  it("does not show rejected section when showRejected is false", () => {
256
252
  render(<Dropzone showRejected={false} />);
257
253
  // No rejected items in DOM since showRejected=false (default)
258
- expect(document.querySelectorAll('[data-slot="dropzone-item"]')).toHaveLength(0);
254
+ expect(
255
+ document.querySelectorAll('[data-slot="dropzone-item"]'),
256
+ ).toHaveLength(0);
259
257
  });
260
258
 
261
259
  it("applies classNames.trigger to trigger element", () => {
@@ -168,9 +168,10 @@ describe("Empty composite", () => {
168
168
 
169
169
  it("applies iconVariant='icon' to media slot", () => {
170
170
  render(<Empty iconVariant="icon" />);
171
- expect(
172
- document.querySelector('[data-slot="empty-media"]'),
173
- ).toHaveAttribute("data-variant", "icon");
171
+ expect(document.querySelector('[data-slot="empty-media"]')).toHaveAttribute(
172
+ "data-variant",
173
+ "icon",
174
+ );
174
175
  });
175
176
 
176
177
  it("renders children alongside default slots", () => {
@@ -1,5 +1,4 @@
1
- import { render, screen } from "@testing-library/react";
2
- import { renderHook } from "@testing-library/react";
1
+ import { render, renderHook, screen } from "@testing-library/react";
3
2
  import { describe, expect, it } from "vitest";
4
3
  import {
5
4
  Field,
@@ -12,8 +11,8 @@ import {
12
11
  FieldPrimitive,
13
12
  FieldRoot,
14
13
  FieldSet,
15
- FieldValidity,
16
14
  FieldsetPrimitive,
15
+ FieldValidity,
17
16
  normalizeError,
18
17
  useFieldName,
19
18
  useIsInsideFieldRoot,
@@ -56,9 +55,7 @@ describe("useIsInsideFieldRoot", () => {
56
55
 
57
56
  it("returns true inside FieldRoot", () => {
58
57
  const { result } = renderHook(() => useIsInsideFieldRoot(), {
59
- wrapper: ({ children }) => (
60
- <FieldRoot name="test">{children}</FieldRoot>
61
- ),
58
+ wrapper: ({ children }) => <FieldRoot name="test">{children}</FieldRoot>,
62
59
  });
63
60
  expect(result.current).toBe(true);
64
61
  });
@@ -72,9 +69,7 @@ describe("useFieldName", () => {
72
69
 
73
70
  it("returns the name provided to FieldRoot", () => {
74
71
  const { result } = renderHook(() => useFieldName(), {
75
- wrapper: ({ children }) => (
76
- <FieldRoot name="email">{children}</FieldRoot>
77
- ),
72
+ wrapper: ({ children }) => <FieldRoot name="email">{children}</FieldRoot>,
78
73
  });
79
74
  expect(result.current).toBe("email");
80
75
  });
@@ -97,9 +92,9 @@ describe("FieldRoot", () => {
97
92
 
98
93
  it("does not set data-required when required is absent", () => {
99
94
  render(<FieldRoot name="x" />);
100
- expect(
101
- document.querySelector('[data-slot="field"]'),
102
- ).not.toHaveAttribute("data-required");
95
+ expect(document.querySelector('[data-slot="field"]')).not.toHaveAttribute(
96
+ "data-required",
97
+ );
103
98
  });
104
99
 
105
100
  it("forwards className", () => {
@@ -204,7 +199,11 @@ describe("Field composite", () => {
204
199
  });
205
200
 
206
201
  it("renders children", () => {
207
- render(<Field><input placeholder="ctrl" /></Field>);
202
+ render(
203
+ <Field>
204
+ <input placeholder="ctrl" />
205
+ </Field>,
206
+ );
208
207
  expect(screen.getByPlaceholderText("ctrl")).toBeInTheDocument();
209
208
  });
210
209
 
@@ -10,7 +10,7 @@ import {
10
10
  import { Button } from "../button/button";
11
11
  import { Checkbox } from "../checkbox/checkbox";
12
12
  import { Combobox } from "../combobox";
13
- import { DateInput } from "../date-picker";
13
+ import { DateInput, DatePicker } from "../date-picker";
14
14
  import { Field, FieldError, FieldLabel, FieldRoot } from "../field/field";
15
15
  import { Input } from "../input/input";
16
16
  import { NumberInput } from "../number-input";
@@ -63,6 +63,11 @@ const ROLES = [
63
63
  * Native HTML constraint validation. Each `FieldRoot` carries a `name` so Form
64
64
  * can route server errors automatically. Errors only surface after the first
65
65
  * submit attempt — no premature invalid state.
66
+ *
67
+ * Both date controls — typeable `DateInput` and popover `DatePicker` — submit an
68
+ * ISO date string (`yyyy-MM-dd`), or `""` when empty so `required` triggers
69
+ * `valueMissing`. The displayed text stays `dd/MM/yyyy`; value and display are
70
+ * separate layers.
66
71
  */
67
72
  export const Default: Story = {
68
73
  render: () => {
@@ -130,11 +135,21 @@ export const Default: Story = {
130
135
  <Field
131
136
  name="startDate"
132
137
  label="Start date"
138
+ description="Typeable input — submits yyyy-MM-dd."
133
139
  error={{ message: "Start date is required.", match: "valueMissing" }}
134
140
  >
135
141
  <DateInput required />
136
142
  </Field>
137
143
 
144
+ <Field
145
+ name="endDate"
146
+ label="End date"
147
+ description="Popover picker — submits yyyy-MM-dd."
148
+ error={{ message: "End date is required.", match: "valueMissing" }}
149
+ >
150
+ <DatePicker mode="single" required />
151
+ </Field>
152
+
138
153
  <Field
139
154
  name="notifications"
140
155
  label="Notification channels"
@@ -23,6 +23,7 @@ export * from "./label";
23
23
  export * from "./loader";
24
24
  export * from "./menu";
25
25
  export * from "./number-input";
26
+ export * from "./otp";
26
27
  export * from "./pagination";
27
28
  export * from "./password";
28
29
  export * from "./popover";
@@ -100,8 +100,8 @@ describe("Label component", () => {
100
100
  Email
101
101
  </Label>,
102
102
  );
103
- expect(
104
- screen.getByRole("button", { name: "Más información" }),
105
- ).toHaveClass("tooltip-btn-cls");
103
+ expect(screen.getByRole("button", { name: "Más información" })).toHaveClass(
104
+ "tooltip-btn-cls",
105
+ );
106
106
  });
107
107
  });
@@ -106,11 +106,7 @@ function renderItem(item: MenuItemType, index: number): React.ReactNode {
106
106
  case "radio-group": {
107
107
  const { type: _, value, onValueChange, items } = item;
108
108
  return (
109
- <MenuRadioGroup
110
- key={index}
111
- value={value}
112
- onValueChange={onValueChange}
113
- >
109
+ <MenuRadioGroup key={index} value={value} onValueChange={onValueChange}>
114
110
  {items.map((subItem, i) => renderItem(subItem, i))}
115
111
  </MenuRadioGroup>
116
112
  );
@@ -215,7 +215,9 @@ describe("NumberInput scrub primitives", () => {
215
215
  render(
216
216
  <NumberInputRoot name="amount">
217
217
  <NumberInputGroup>
218
- <NumberInputScrubArea className="scrub-cls">Drag</NumberInputScrubArea>
218
+ <NumberInputScrubArea className="scrub-cls">
219
+ Drag
220
+ </NumberInputScrubArea>
219
221
  <NumberInputInput />
220
222
  </NumberInputGroup>
221
223
  </NumberInputRoot>,
@@ -251,6 +253,8 @@ describe("NumberInput scrub primitives", () => {
251
253
  const { container } = render(
252
254
  <NumberInputCursorIcon data-testid="cursor-icon" />,
253
255
  );
254
- expect(container.querySelector("[data-testid='cursor-icon']")).toBeInTheDocument();
256
+ expect(
257
+ container.querySelector("[data-testid='cursor-icon']"),
258
+ ).toBeInTheDocument();
255
259
  });
256
260
  });
@@ -12,12 +12,17 @@ describe("Password", () => {
12
12
 
13
13
  it("renders toggle button with data-slot='password-toggle'", () => {
14
14
  render(<Password />);
15
- expect(document.querySelector('[data-slot="password-toggle"]')).toBeTruthy();
15
+ expect(
16
+ document.querySelector('[data-slot="password-toggle"]'),
17
+ ).toBeTruthy();
16
18
  });
17
19
 
18
20
  it("defaults to type='password'", () => {
19
21
  render(<Password />);
20
- expect(document.querySelector("input")).toHaveAttribute("type", "password");
22
+ expect(document.querySelector("input")).toHaveAttribute(
23
+ "type",
24
+ "password",
25
+ );
21
26
  });
22
27
  });
23
28
 
@@ -25,7 +30,9 @@ describe("Password", () => {
25
30
  it("reveals password on toggle click", async () => {
26
31
  render(<Password />);
27
32
  await userEvent.click(
28
- document.querySelector('[data-slot="password-toggle"]') as HTMLButtonElement,
33
+ document.querySelector(
34
+ '[data-slot="password-toggle"]',
35
+ ) as HTMLButtonElement,
29
36
  );
30
37
  expect(document.querySelector("input")).toHaveAttribute("type", "text");
31
38
  });
@@ -37,14 +44,19 @@ describe("Password", () => {
37
44
  ) as HTMLButtonElement;
38
45
  await userEvent.click(toggle);
39
46
  await userEvent.click(toggle);
40
- expect(document.querySelector("input")).toHaveAttribute("type", "password");
47
+ expect(document.querySelector("input")).toHaveAttribute(
48
+ "type",
49
+ "password",
50
+ );
41
51
  });
42
52
 
43
53
  it("fires onShow when revealing password", async () => {
44
54
  const onShow = vi.fn();
45
55
  render(<Password onShow={onShow} />);
46
56
  await userEvent.click(
47
- document.querySelector('[data-slot="password-toggle"]') as HTMLButtonElement,
57
+ document.querySelector(
58
+ '[data-slot="password-toggle"]',
59
+ ) as HTMLButtonElement,
48
60
  );
49
61
  expect(onShow).toHaveBeenCalledTimes(1);
50
62
  });
@@ -107,7 +119,9 @@ describe("Password", () => {
107
119
  it("renders custom hideIcon after toggle", async () => {
108
120
  render(<Password hideIcon={<span data-testid="hide-icon" />} />);
109
121
  await userEvent.click(
110
- document.querySelector('[data-slot="password-toggle"]') as HTMLButtonElement,
122
+ document.querySelector(
123
+ '[data-slot="password-toggle"]',
124
+ ) as HTMLButtonElement,
111
125
  );
112
126
  expect(screen.getByTestId("hide-icon")).toBeTruthy();
113
127
  });
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { Eye, EyeOff } from "lucide-react";
4
4
  import { type ChangeEvent, type ReactNode } from "react";
5
- import { useToggle } from "../../hooks";
5
+ import { useBoolean } from "../../hooks";
6
6
  import { cn } from "../../lib";
7
7
  import { InputPrimitive, type InputProps } from "../input/input";
8
8
 
@@ -32,7 +32,7 @@ export function Password({
32
32
  classNames,
33
33
  ...rest
34
34
  }: PasswordProps) {
35
- const [showPassword, toggleShowPassword] = useToggle(false);
35
+ const [showPassword, { toggle: toggleShowPassword }] = useBoolean(false);
36
36
 
37
37
  const handleToggle = () => {
38
38
  toggleShowPassword();
@@ -21,7 +21,9 @@ describe("Popover primitives", () => {
21
21
  <PopoverPopup>Content</PopoverPopup>
22
22
  </PopoverRoot>,
23
23
  );
24
- expect(document.querySelector('[data-slot="popover-trigger"]')).toBeTruthy();
24
+ expect(
25
+ document.querySelector('[data-slot="popover-trigger"]'),
26
+ ).toBeTruthy();
25
27
  });
26
28
 
27
29
  it("PopoverPopup renders data-slot='popover-popup' when open", () => {
@@ -125,9 +127,7 @@ describe("Popover composite", () => {
125
127
  <span data-testid="content">Content</span>
126
128
  </Popover>,
127
129
  );
128
- expect(
129
- document.querySelector('[data-slot="popover-title"]'),
130
- ).toBeNull();
130
+ expect(document.querySelector('[data-slot="popover-title"]')).toBeNull();
131
131
  });
132
132
 
133
133
  it("opens on trigger click", async () => {
@@ -58,9 +58,7 @@ describe("ProgressLabel", () => {
58
58
  <ProgressTrack />
59
59
  </ProgressRoot>,
60
60
  );
61
- expect(
62
- document.querySelector('[data-slot="progress-label"]'),
63
- ).toBeTruthy();
61
+ expect(document.querySelector('[data-slot="progress-label"]')).toBeTruthy();
64
62
  });
65
63
  });
66
64
 
@@ -74,9 +72,7 @@ describe("ProgressValue", () => {
74
72
  <ProgressValue />
75
73
  </ProgressRoot>,
76
74
  );
77
- expect(
78
- document.querySelector('[data-slot="progress-value"]'),
79
- ).toBeTruthy();
75
+ expect(document.querySelector('[data-slot="progress-value"]')).toBeTruthy();
80
76
  });
81
77
  });
82
78
 
@@ -110,7 +106,9 @@ describe("Progress indicator variants", () => {
110
106
 
111
107
  describe("Progress className", () => {
112
108
  it("applies className to root", () => {
113
- render(<Progress value={null} className="custom-root" aria-label="Loading" />);
109
+ render(
110
+ <Progress value={null} className="custom-root" aria-label="Loading" />,
111
+ );
114
112
  expect(document.querySelector('[data-slot="progress"]')).toHaveClass(
115
113
  "custom-root",
116
114
  );
@@ -120,7 +118,8 @@ describe("Progress className", () => {
120
118
  describe("Progress primitive exports", () => {
121
119
  it("exports ProgressRoot", () => expect(ProgressRoot).toBeDefined());
122
120
  it("exports ProgressTrack", () => expect(ProgressTrack).toBeDefined());
123
- it("exports ProgressIndicator", () => expect(ProgressIndicator).toBeDefined());
121
+ it("exports ProgressIndicator", () =>
122
+ expect(ProgressIndicator).toBeDefined());
124
123
  it("exports ProgressLabel", () => expect(ProgressLabel).toBeDefined());
125
124
  it("exports ProgressValue", () => expect(ProgressValue).toBeDefined());
126
125
  });
@@ -42,7 +42,9 @@ describe("RadioGroup primitives", () => {
42
42
  </RadioRoot>
43
43
  </RadioGroupRoot>,
44
44
  );
45
- expect(document.querySelector('[data-slot="radio-indicator"]')).toBeTruthy();
45
+ expect(
46
+ document.querySelector('[data-slot="radio-indicator"]'),
47
+ ).toBeTruthy();
46
48
  });
47
49
  });
48
50
 
@@ -60,9 +62,10 @@ describe("RadioGroup composite", () => {
60
62
 
61
63
  it("marks defaultValue as checked", () => {
62
64
  render(<RadioGroup items={items} defaultValue="b" />);
63
- expect(
64
- screen.getByRole("radio", { name: "Option B" }),
65
- ).toHaveAttribute("aria-checked", "true");
65
+ expect(screen.getByRole("radio", { name: "Option B" })).toHaveAttribute(
66
+ "aria-checked",
67
+ "true",
68
+ );
66
69
  });
67
70
 
68
71
  it("fires onValueChange when selection changes", async () => {
@@ -74,16 +77,17 @@ describe("RadioGroup composite", () => {
74
77
 
75
78
  it("reflects controlled value", () => {
76
79
  render(<RadioGroup items={items} value="a" onValueChange={vi.fn()} />);
77
- expect(
78
- screen.getByRole("radio", { name: "Option A" }),
79
- ).toHaveAttribute("aria-checked", "true");
80
+ expect(screen.getByRole("radio", { name: "Option A" })).toHaveAttribute(
81
+ "aria-checked",
82
+ "true",
83
+ );
80
84
  });
81
85
 
82
86
  it("disables specific item", () => {
83
87
  render(<RadioGroup items={items} />);
84
- expect(
85
- screen.getByRole("radio", { name: "Option C" }),
86
- ).toHaveAttribute("data-disabled");
88
+ expect(screen.getByRole("radio", { name: "Option C" })).toHaveAttribute(
89
+ "data-disabled",
90
+ );
87
91
  });
88
92
 
89
93
  it("disables all items when disabled prop is set", () => {
@@ -140,7 +144,9 @@ describe("RadioGroup.Legend", () => {
140
144
 
141
145
  describe("RadioGroup controlFirst", () => {
142
146
  it("applies flex-row-reverse when controlFirst=false", () => {
143
- render(<RadioGroup items={[{ value: "a", label: "A" }]} controlFirst={false} />);
147
+ render(
148
+ <RadioGroup items={[{ value: "a", label: "A" }]} controlFirst={false} />,
149
+ );
144
150
  const row = document.querySelector(".flex-row-reverse");
145
151
  expect(row).toBeTruthy();
146
152
  });
@@ -51,7 +51,11 @@ describe("Select primitives — data-slots", () => {
51
51
  });
52
52
 
53
53
  it("SelectButton renders data-slot=select-button with type=button by default", () => {
54
- render(<SelectRoot><SelectButton>Open</SelectButton></SelectRoot>);
54
+ render(
55
+ <SelectRoot>
56
+ <SelectButton>Open</SelectButton>
57
+ </SelectRoot>,
58
+ );
55
59
  const btn = slot("select-button") as HTMLButtonElement;
56
60
  expect(btn).toBeInTheDocument();
57
61
  expect(btn.type).toBe("button");
@@ -235,7 +239,9 @@ describe("Select defaultGetLabel / defaultGetId", () => {
235
239
  getId={(o) => o.code}
236
240
  />,
237
241
  );
238
- expect(screen.getByRole("option", { name: "Argentina" })).toBeInTheDocument();
242
+ expect(
243
+ screen.getByRole("option", { name: "Argentina" }),
244
+ ).toBeInTheDocument();
239
245
  });
240
246
  });
241
247
 
@@ -260,11 +266,7 @@ describe("Select disabled items", () => {
260
266
  { id: "2", name: "Blocked", blocked: true },
261
267
  ];
262
268
  render(
263
- <Select
264
- items={items}
265
- defaultOpen
266
- getDisabled={(item) => item.blocked}
267
- />,
269
+ <Select items={items} defaultOpen getDisabled={(item) => item.blocked} />,
268
270
  );
269
271
  expect(
270
272
  document.querySelector('[data-slot="select-item"][data-disabled]'),
@@ -277,9 +279,7 @@ describe("Select disabled items", () => {
277
279
  describe("Select onValueChange", () => {
278
280
  it("fires onValueChange with selected item object (single)", async () => {
279
281
  const onChange = vi.fn();
280
- render(
281
- <Select items={fruits} defaultOpen onValueChange={onChange} />,
282
- );
282
+ render(<Select items={fruits} defaultOpen onValueChange={onChange} />);
283
283
 
284
284
  await userEvent.click(screen.getByRole("option", { name: "Banana" }));
285
285
 
@@ -353,12 +353,14 @@ export function Select<TItem = unknown>(
353
353
  multiple,
354
354
  className,
355
355
  classNames,
356
+ "aria-invalid": ariaInvalid,
356
357
  ...rest
357
358
  } = allProps as SelectBaseProps<TItem> & {
358
359
  multiple?: boolean;
359
360
  onValueChange?: (value: any) => void;
360
361
  value?: any;
361
362
  defaultValue?: any;
363
+ "aria-invalid"?: React.AriaAttributes["aria-invalid"];
362
364
  };
363
365
 
364
366
  const getLabel: (item: TItem) => string = getLabelProp ?? defaultGetLabel;
@@ -410,7 +412,13 @@ export function Select<TItem = unknown>(
410
412
  onValueChange={handleChange as any}
411
413
  {...(rest as any)}
412
414
  >
413
- <SelectTrigger className={className}>
415
+ <SelectTrigger
416
+ className={className}
417
+ // Only forward `aria-invalid` when explicitly set. Base UI's Field
418
+ // integration already sets it from validity state; passing `undefined`
419
+ // here would clobber that value during prop merge and drop the error border.
420
+ {...(ariaInvalid === undefined ? {} : { "aria-invalid": ariaInvalid })}
421
+ >
414
422
  <SelectValue placeholder={placeholder} />
415
423
  </SelectTrigger>
416
424
  <SelectPopup className={classNames?.popup}>
@@ -411,13 +411,14 @@ const wizardSteps = [
411
411
 
412
412
  /**
413
413
  * Linear wizard driven by `useStep`. Note the index translation: `useStep` is
414
- * **0-indexed**, the stepper is **1-indexed**. Feed it `currentStepIndex + 1`
414
+ * **0-indexed**, the stepper is **1-indexed**. Feed it `index + 1` as `value`
415
415
  * and bridge `onValueChange` back with `goTo(value - 1)`.
416
416
  *
417
417
  * ```tsx
418
- * const { currentStepIndex, goTo, next, back } = useStep(steps);
418
+ * const [index, { goTo, next, back }] = useStep(steps.length);
419
+ * const currentStep = steps[index];
419
420
  * <Stepper
420
- * value={currentStepIndex + 1}
421
+ * value={index + 1}
421
422
  * onValueChange={(value) => goTo(value - 1)}
422
423
  * items={steps}
423
424
  * />
@@ -425,20 +426,15 @@ const wizardSteps = [
425
426
  */
426
427
  export const Wizard: Story = {
427
428
  render: () => {
428
- const {
429
- currentStepIndex,
430
- step,
431
- isFirstStep,
432
- isLastStep,
433
- next,
434
- back,
435
- goTo,
436
- } = useStep(wizardSteps);
429
+ const [index, { isFirstStep, isLastStep, next, back, goTo }] = useStep(
430
+ wizardSteps.length,
431
+ );
432
+ const currentStep = wizardSteps[index];
437
433
 
438
434
  return (
439
435
  <div className="w-[840px] space-y-6">
440
436
  <Stepper
441
- value={currentStepIndex + 1}
437
+ value={index + 1}
442
438
  onValueChange={(value) => goTo(value - 1)}
443
439
  indicators={{ completed: <CheckIcon className="size-3.5" /> }}
444
440
  items={wizardSteps.map((s) => ({
@@ -447,9 +443,9 @@ export const Wizard: Story = {
447
443
  }))}
448
444
  />
449
445
  <div className="rounded-lg border p-6">
450
- <p className="font-medium text-sm">{step.title}</p>
446
+ <p className="font-medium text-sm">{currentStep.title}</p>
451
447
  <p className="mt-1 text-muted-foreground text-sm">
452
- {step.description}
448
+ {currentStep.description}
453
449
  </p>
454
450
  </div>
455
451
  <div className="flex justify-between">
@@ -167,7 +167,9 @@ describe("Stepper data-slots", () => {
167
167
 
168
168
  it("StepperTrigger renders with data-slot='stepper-trigger'", () => {
169
169
  render(<TwoStepStepper />);
170
- expect(document.querySelector('[data-slot="stepper-trigger"]')).toBeTruthy();
170
+ expect(
171
+ document.querySelector('[data-slot="stepper-trigger"]'),
172
+ ).toBeTruthy();
171
173
  });
172
174
 
173
175
  it("StepperIndicator renders with data-slot='stepper-indicator'", () => {
@@ -329,9 +331,9 @@ describe("Stepper loading state", () => {
329
331
  </StepperNav>
330
332
  </StepperRoot>,
331
333
  );
332
- expect(document.querySelector('[data-slot="stepper-item"]')).toHaveAttribute(
333
- "data-loading",
334
- );
334
+ expect(
335
+ document.querySelector('[data-slot="stepper-item"]'),
336
+ ).toHaveAttribute("data-loading");
335
337
  });
336
338
  });
337
339