@boxcustodia/library 2.0.0-alpha.11 → 2.0.0-alpha.13

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 (352) hide show
  1. package/dist/index.cjs.js +38 -38
  2. package/dist/index.css +1 -1
  3. package/dist/index.d.ts +28 -29
  4. package/dist/index.es.js +6804 -6792
  5. package/package.json +4 -3
  6. package/src/__doc__/Changelog.mdx +6 -0
  7. package/src/__doc__/Components.mdx +73 -0
  8. package/src/__doc__/Examples.tsx +69 -0
  9. package/src/__doc__/Icons.mdx +41 -0
  10. package/src/__doc__/Intro.mdx +138 -0
  11. package/src/__doc__/MCP.mdx +71 -0
  12. package/src/__doc__/Migration.mdx +451 -0
  13. package/src/__doc__/Theme.mdx +132 -0
  14. package/src/__doc__/Types.mdx +252 -0
  15. package/src/components/alert/alert.stories.tsx +142 -0
  16. package/src/components/alert/alert.tsx +109 -0
  17. package/src/components/alert/index.ts +7 -0
  18. package/src/components/alert-dialog/alert-dialog.stories.tsx +173 -0
  19. package/src/components/alert-dialog/alert-dialog.test.tsx +49 -0
  20. package/src/components/alert-dialog/alert-dialog.tsx +265 -0
  21. package/src/components/alert-dialog/index.ts +1 -0
  22. package/src/components/auto-complete/auto-complete-primitives.tsx +155 -0
  23. package/src/components/auto-complete/auto-complete.stories.tsx +241 -0
  24. package/src/components/auto-complete/auto-complete.tsx +82 -0
  25. package/src/components/auto-complete/index.ts +2 -0
  26. package/src/components/avatar/avatar.stories.tsx +84 -0
  27. package/src/components/avatar/avatar.test.tsx +61 -0
  28. package/src/components/avatar/avatar.tsx +104 -0
  29. package/src/components/avatar/index.ts +1 -0
  30. package/src/components/background-image/background-image.stories.tsx +21 -0
  31. package/src/components/background-image/background-image.test.tsx +29 -0
  32. package/src/components/background-image/background-image.tsx +23 -0
  33. package/src/components/background-image/index.ts +1 -0
  34. package/src/components/button/button.stories.tsx +396 -0
  35. package/src/components/button/button.test.tsx +58 -0
  36. package/src/components/button/button.tsx +31 -0
  37. package/src/components/button/button.variants.ts +44 -0
  38. package/src/components/button/components/base-button.tsx +86 -0
  39. package/src/components/button/components/loader-overlay.tsx +21 -0
  40. package/src/components/button/components/loading-icon.tsx +47 -0
  41. package/src/components/button/index.ts +3 -0
  42. package/src/components/calendar/calendar.model.ts +86 -0
  43. package/src/components/calendar/calendar.stories.tsx +155 -0
  44. package/src/components/calendar/calendar.test.tsx +12 -0
  45. package/src/components/calendar/calendar.tsx +185 -0
  46. package/src/components/calendar/components/calendar-navigation.tsx +141 -0
  47. package/src/components/calendar/components/day.tsx +61 -0
  48. package/src/components/calendar/components/decade-view.tsx +45 -0
  49. package/src/components/calendar/components/index.ts +6 -0
  50. package/src/components/calendar/components/month-view.tsx +58 -0
  51. package/src/components/calendar/components/week-days.tsx +27 -0
  52. package/src/components/calendar/components/year-view.tsx +29 -0
  53. package/src/components/calendar/hooks/index.ts +4 -0
  54. package/src/components/calendar/hooks/use-calendar-navigation.ts +79 -0
  55. package/src/components/calendar/hooks/use-calendar.ts +90 -0
  56. package/src/components/calendar/hooks/use-multiple-calendar.ts +34 -0
  57. package/src/components/calendar/hooks/use-range-calendar.ts +91 -0
  58. package/src/components/calendar/hooks/use-single-calendar.ts +18 -0
  59. package/src/components/calendar/index.ts +1 -0
  60. package/src/components/calendar/utils/typeguards.ts +7 -0
  61. package/src/components/card/card.stories.tsx +116 -0
  62. package/src/components/card/card.tsx +74 -0
  63. package/src/components/card/index.ts +1 -0
  64. package/src/components/center/center.stories.tsx +81 -0
  65. package/src/components/center/center.tsx +24 -0
  66. package/src/components/center/index.ts +1 -0
  67. package/src/components/checkbox/checkbox.stories.tsx +307 -0
  68. package/src/components/checkbox/checkbox.tsx +273 -0
  69. package/src/components/checkbox/index.ts +1 -0
  70. package/src/components/checkbox-group/checkbox-group.stories.tsx +104 -0
  71. package/src/components/checkbox-group/checkbox-group.tsx +16 -0
  72. package/src/components/checkbox-group/index.ts +1 -0
  73. package/src/components/combobox/combobox.stories.tsx +339 -0
  74. package/src/components/combobox/combobox.tsx +898 -0
  75. package/src/components/combobox/index.ts +1 -0
  76. package/src/components/date-picker/date-input.stories.tsx +158 -0
  77. package/src/components/date-picker/date-input.tsx +163 -0
  78. package/src/components/date-picker/date-picker.model.ts +90 -0
  79. package/src/components/date-picker/date-picker.stories.tsx +200 -0
  80. package/src/components/date-picker/date-picker.test.tsx +23 -0
  81. package/src/components/date-picker/date-picker.tsx +298 -0
  82. package/src/components/date-picker/date-picker.utils.ts +260 -0
  83. package/src/components/date-picker/index.ts +3 -0
  84. package/src/components/date-picker/use-date-input-popover.ts +48 -0
  85. package/src/components/date-picker/use-date-input.ts +125 -0
  86. package/src/components/dialog/dialog.stories.tsx +171 -0
  87. package/src/components/dialog/dialog.test.tsx +68 -0
  88. package/src/components/dialog/dialog.tsx +277 -0
  89. package/src/components/dialog/index.ts +1 -0
  90. package/src/components/divider/divider.stories.tsx +139 -0
  91. package/src/components/divider/divider.test.tsx +22 -0
  92. package/src/components/divider/divider.tsx +23 -0
  93. package/src/components/divider/index.ts +1 -0
  94. package/src/components/dropzone/dropzone.stories.tsx +210 -0
  95. package/src/components/dropzone/dropzone.tsx +154 -0
  96. package/src/components/dropzone/file-types.ts +64 -0
  97. package/src/components/dropzone/index.ts +3 -0
  98. package/src/components/dropzone/upload-primitives.tsx +310 -0
  99. package/src/components/dropzone/use-dropzone.ts +122 -0
  100. package/src/components/empty-state/empty-state.stories.tsx +56 -0
  101. package/src/components/empty-state/empty-state.tsx +39 -0
  102. package/src/components/empty-state/index.ts +1 -0
  103. package/src/components/field/field.stories.tsx +223 -0
  104. package/src/components/field/field.tsx +229 -0
  105. package/src/components/field/index.ts +1 -0
  106. package/src/components/form/form.stories.tsx +594 -0
  107. package/src/components/form/form.tsx +30 -0
  108. package/src/components/form/index.ts +1 -0
  109. package/src/components/heading/heading.stories.tsx +74 -0
  110. package/src/components/heading/heading.tsx +28 -0
  111. package/src/components/heading/heading.variants.ts +27 -0
  112. package/src/components/heading/index.ts +1 -0
  113. package/src/components/index.ts +46 -0
  114. package/src/components/input/index.ts +1 -0
  115. package/src/components/input/input.stories.tsx +104 -0
  116. package/src/components/input/input.tsx +75 -0
  117. package/src/components/kbd/index.ts +1 -0
  118. package/src/components/kbd/kbd.stories.tsx +40 -0
  119. package/src/components/kbd/kbd.tsx +31 -0
  120. package/src/components/kbd/kbd.variants.ts +26 -0
  121. package/src/components/label/index.ts +1 -0
  122. package/src/components/label/label.stories.tsx +68 -0
  123. package/src/components/label/label.test.tsx +61 -0
  124. package/src/components/label/label.tsx +62 -0
  125. package/src/components/loader/index.ts +1 -0
  126. package/src/components/loader/loader.stories.tsx +60 -0
  127. package/src/components/loader/loader.test.tsx +26 -0
  128. package/src/components/loader/loader.tsx +60 -0
  129. package/src/components/menu/index.ts +2 -0
  130. package/src/components/menu/menu-primitives.tsx +248 -0
  131. package/src/components/menu/menu.stories.tsx +203 -0
  132. package/src/components/menu/menu.tsx +100 -0
  133. package/src/components/menu/util/render-menu-item.tsx +54 -0
  134. package/src/components/multi-select/hooks/use-multi-select.ts +66 -0
  135. package/src/components/multi-select/index.ts +1 -0
  136. package/src/components/multi-select/multi-select.stories.tsx +294 -0
  137. package/src/components/multi-select/multi-select.tsx +300 -0
  138. package/src/components/multi-select/multi-select.variants.ts +22 -0
  139. package/src/components/number-input/index.ts +1 -0
  140. package/src/components/number-input/number-input.stories.tsx +209 -0
  141. package/src/components/number-input/number-input.test.tsx +87 -0
  142. package/src/components/number-input/number-input.tsx +232 -0
  143. package/src/components/pagination/components/pagination-option.tsx +27 -0
  144. package/src/components/pagination/index.ts +1 -0
  145. package/src/components/pagination/pagination.stories.tsx +80 -0
  146. package/src/components/pagination/pagination.test.tsx +76 -0
  147. package/src/components/pagination/pagination.tsx +102 -0
  148. package/src/components/password/index.ts +1 -0
  149. package/src/components/password/password.stories.tsx +104 -0
  150. package/src/components/password/password.tsx +75 -0
  151. package/src/components/popover/index.ts +1 -0
  152. package/src/components/popover/popover.stories.tsx +213 -0
  153. package/src/components/popover/popover.tsx +203 -0
  154. package/src/components/progress/index.ts +1 -0
  155. package/src/components/progress/progress.stories.tsx +124 -0
  156. package/src/components/progress/progress.test.tsx +25 -0
  157. package/src/components/progress/progress.tsx +124 -0
  158. package/src/components/scroll-area/index.ts +1 -0
  159. package/src/components/scroll-area/scroll-area.stories.tsx +166 -0
  160. package/src/components/scroll-area/scroll-area.tsx +64 -0
  161. package/src/components/select/index.ts +1 -0
  162. package/src/components/select/select.stories.tsx +253 -0
  163. package/src/components/select/select.tsx +430 -0
  164. package/src/components/show/index.ts +1 -0
  165. package/src/components/show/show.stories.tsx +197 -0
  166. package/src/components/show/show.test.tsx +41 -0
  167. package/src/components/show/show.tsx +16 -0
  168. package/src/components/skeleton/index.ts +1 -0
  169. package/src/components/skeleton/skeleton.stories.tsx +36 -0
  170. package/src/components/skeleton/skeleton.test.tsx +14 -0
  171. package/src/components/skeleton/skeleton.tsx +15 -0
  172. package/src/components/stack/index.ts +1 -0
  173. package/src/components/stack/stack.stories.tsx +194 -0
  174. package/src/components/stack/stack.tsx +52 -0
  175. package/src/components/stepper/Stepper.tsx +190 -0
  176. package/src/components/stepper/context/stepper-context.tsx +11 -0
  177. package/src/components/stepper/index.ts +1 -0
  178. package/src/components/stepper/stepper.stories.tsx +130 -0
  179. package/src/components/stepper/stepper.test.tsx +91 -0
  180. package/src/components/switch/index.ts +1 -0
  181. package/src/components/switch/switch.stories.tsx +122 -0
  182. package/src/components/switch/switch.test.tsx +30 -0
  183. package/src/components/switch/switch.tsx +86 -0
  184. package/src/components/table/index.ts +3 -0
  185. package/src/components/table/table-primitives.tsx +122 -0
  186. package/src/components/table/table.model.ts +20 -0
  187. package/src/components/table/table.stories.tsx +169 -0
  188. package/src/components/table/table.test.tsx +91 -0
  189. package/src/components/table/table.tsx +109 -0
  190. package/src/components/table-pagination/index.ts +2 -0
  191. package/src/components/table-pagination/table-pagination.model.ts +2 -0
  192. package/src/components/table-pagination/table-pagination.stories.tsx +23 -0
  193. package/src/components/table-pagination/table-pagination.test.tsx +32 -0
  194. package/src/components/table-pagination/table-pagination.tsx +108 -0
  195. package/src/components/tabs/context/tabs-context.tsx +14 -0
  196. package/src/components/tabs/index.ts +1 -0
  197. package/src/components/tabs/tabs.stories.tsx +182 -0
  198. package/src/components/tabs/tabs.test.tsx +61 -0
  199. package/src/components/tabs/tabs.tsx +175 -0
  200. package/src/components/tag/index.ts +2 -0
  201. package/src/components/tag/tag.stories.tsx +170 -0
  202. package/src/components/tag/tag.test.tsx +18 -0
  203. package/src/components/tag/tag.tsx +99 -0
  204. package/src/components/tag/tag.variants.ts +31 -0
  205. package/src/components/textarea/index.ts +1 -0
  206. package/src/components/textarea/textarea.stories.tsx +73 -0
  207. package/src/components/textarea/textarea.tsx +105 -0
  208. package/src/components/timeline/index.ts +1 -0
  209. package/src/components/timeline/timeline-status.ts +5 -0
  210. package/src/components/timeline/timeline.stories.tsx +84 -0
  211. package/src/components/timeline/timeline.tsx +147 -0
  212. package/src/components/toast/index.ts +1 -0
  213. package/src/components/toast/toast.stories.tsx +392 -0
  214. package/src/components/toast/toast.test.tsx +50 -0
  215. package/src/components/toast/toast.tsx +411 -0
  216. package/src/components/tooltip/index.ts +1 -0
  217. package/src/components/tooltip/tooltip.stories.tsx +226 -0
  218. package/src/components/tooltip/tooltip.test.tsx +46 -0
  219. package/src/components/tooltip/tooltip.tsx +171 -0
  220. package/src/components/tree/hooks/use-controllable-tree-state.ts +80 -0
  221. package/src/components/tree/index.ts +2 -0
  222. package/src/components/tree/tree-primitives.tsx +126 -0
  223. package/src/components/tree/tree.stories.tsx +468 -0
  224. package/src/components/tree/tree.tsx +42 -0
  225. package/src/hooks/index.ts +26 -0
  226. package/src/hooks/useArray/__doc__/useArray.stories.tsx +100 -0
  227. package/src/hooks/useArray/__test__/useArray.test.tsx +88 -0
  228. package/src/hooks/useArray/index.ts +1 -0
  229. package/src/hooks/useArray/useArray.ts +76 -0
  230. package/src/hooks/useAsync/__doc__/useAsync.stories.tsx +149 -0
  231. package/src/hooks/useAsync/__test__/useAsync.test.tsx +68 -0
  232. package/src/hooks/useAsync/index.ts +1 -0
  233. package/src/hooks/useAsync/useAsync.ts +58 -0
  234. package/src/hooks/useClickOutside/__doc__/useClickOutside.stories.tsx +40 -0
  235. package/src/hooks/useClickOutside/__test__/useClickOutside.test.tsx +33 -0
  236. package/src/hooks/useClickOutside/index.ts +1 -0
  237. package/src/hooks/useClickOutside/useClickOutside.ts +26 -0
  238. package/src/hooks/useClipboard/__doc__/useClipboard.stories.tsx +45 -0
  239. package/src/hooks/useClipboard/__test__/useClipboard.test.tsx +19 -0
  240. package/src/hooks/useClipboard/index.ts +1 -0
  241. package/src/hooks/useClipboard/useClipboard.tsx +28 -0
  242. package/src/hooks/useDebounceCallback/__doc__/useDebouncedCallback.stories.tsx +84 -0
  243. package/src/hooks/useDebounceCallback/index.ts +1 -0
  244. package/src/hooks/useDebounceCallback/useDebouncedCallback.ts +23 -0
  245. package/src/hooks/useDebounceValue/__doc__/useDebouncedValue.stories.tsx +75 -0
  246. package/src/hooks/useDebounceValue/index.ts +1 -0
  247. package/src/hooks/useDebounceValue/useDebouncedValue.ts +17 -0
  248. package/src/hooks/useDisclosure/__doc__/useDisclosure.stories.tsx +39 -0
  249. package/src/hooks/useDisclosure/__test__/useDisclosure.test.ts +43 -0
  250. package/src/hooks/useDisclosure/index.ts +1 -0
  251. package/src/hooks/useDisclosure/useDisclosure.ts +37 -0
  252. package/src/hooks/useDocumentTitle/__doc__/useDocumentTitle.stories.tsx +26 -0
  253. package/src/hooks/useDocumentTitle/index.ts +1 -0
  254. package/src/hooks/useDocumentTitle/useDocumentTitle.tsx +11 -0
  255. package/src/hooks/useEventListener/__doc__/useEventListener.stories.tsx +28 -0
  256. package/src/hooks/useEventListener/__test__/useEventListener.test.tsx +26 -0
  257. package/src/hooks/useEventListener/index.ts +1 -0
  258. package/src/hooks/useEventListener/useEventListener.ts +25 -0
  259. package/src/hooks/useFocusTrap/__doc__/useFocusTrap.stories.tsx +37 -0
  260. package/src/hooks/useFocusTrap/index.ts +1 -0
  261. package/src/hooks/useFocusTrap/scopeTab.ts +38 -0
  262. package/src/hooks/useFocusTrap/tabbable.ts +70 -0
  263. package/src/hooks/useFocusTrap/useFocusTrap.ts +78 -0
  264. package/src/hooks/useHotkey/__docs__/useHotkey.stories.tsx +116 -0
  265. package/src/hooks/useHotkey/__test__/useHotkey.test.tsx +105 -0
  266. package/src/hooks/useHotkey/__utils__/create-hotkey-listener.ts +25 -0
  267. package/src/hooks/useHotkey/__utils__/index.ts +3 -0
  268. package/src/hooks/useHotkey/__utils__/is-input-field.ts +14 -0
  269. package/src/hooks/useHotkey/__utils__/match-key-modifiers.ts +25 -0
  270. package/src/hooks/useHotkey/index.ts +1 -0
  271. package/src/hooks/useHotkey/useHotkey.ts +34 -0
  272. package/src/hooks/useHover/__doc__/useHover.stories.tsx +41 -0
  273. package/src/hooks/useHover/__test__/useHover.test.tsx +45 -0
  274. package/src/hooks/useHover/index.ts +1 -0
  275. package/src/hooks/useHover/useHover.tsx +40 -0
  276. package/src/hooks/useIsVisible/__doc__/useIsVisible.stories.tsx +60 -0
  277. package/src/hooks/useIsVisible/index.ts +1 -0
  278. package/src/hooks/useIsVisible/useIsVisible.tsx +50 -0
  279. package/src/hooks/useLocalStorage/__doc__/useLocalStorage.stories.tsx +86 -0
  280. package/src/hooks/useLocalStorage/__test__/useLocalStorage.test.ts +85 -0
  281. package/src/hooks/useLocalStorage/index.ts +1 -0
  282. package/src/hooks/useLocalStorage/useLocalStorage.ts +57 -0
  283. package/src/hooks/useMediaQuery/__doc__/useMediaQuery.stories.tsx +39 -0
  284. package/src/hooks/useMediaQuery/index.ts +1 -0
  285. package/src/hooks/useMediaQuery/useMediaQuery.ts +22 -0
  286. package/src/hooks/useMemoizedFn/index.ts +1 -0
  287. package/src/hooks/useMemoizedFn/useMemoizedFn.ts +32 -0
  288. package/src/hooks/useMutation/__doc__/useMutation.stories.tsx +111 -0
  289. package/src/hooks/useMutation/__test__/useMutation.test.tsx +83 -0
  290. package/src/hooks/useMutation/index.ts +1 -0
  291. package/src/hooks/useMutation/useMutation.tsx +60 -0
  292. package/src/hooks/useObject/__doc__/useObject.stories.tsx +119 -0
  293. package/src/hooks/useObject/__test__/useObject.test.tsx +87 -0
  294. package/src/hooks/useObject/index.ts +1 -0
  295. package/src/hooks/useObject/useObject.tsx +48 -0
  296. package/src/hooks/usePagination/__doc__/usePagination.stories.tsx +72 -0
  297. package/src/hooks/usePagination/__test__/usePagination.test.tsx +98 -0
  298. package/src/hooks/usePagination/index.ts +2 -0
  299. package/src/hooks/usePagination/usePagination.tsx +74 -0
  300. package/src/hooks/usePortal/__doc__/usePortal.stories.tsx +19 -0
  301. package/src/hooks/usePortal/__test__/usePortal.test.tsx +20 -0
  302. package/src/hooks/usePortal/index.ts +1 -0
  303. package/src/hooks/usePortal/usePortal.ts +40 -0
  304. package/src/hooks/usePreventCloseWindow/__doc__/usePreventCloseWindow.stories.tsx +32 -0
  305. package/src/hooks/usePreventCloseWindow/index.ts +1 -0
  306. package/src/hooks/usePreventCloseWindow/usePreventCloseWindow.ts +33 -0
  307. package/src/hooks/useRangePagination/__test__/useRangePagination.test.tsx +63 -0
  308. package/src/hooks/useRangePagination/index.ts +2 -0
  309. package/src/hooks/useRangePagination/useRangePagination.tsx +72 -0
  310. package/src/hooks/useSelection/__doc__/useSelection.stories.tsx +140 -0
  311. package/src/hooks/useSelection/__test__/useSelection.test.tsx +57 -0
  312. package/src/hooks/useSelection/index.ts +1 -0
  313. package/src/hooks/useSelection/useSelection.ts +121 -0
  314. package/src/hooks/useStep/__doc__/useStep.stories.tsx +98 -0
  315. package/src/hooks/useStep/__test__/useStep.test.ts +51 -0
  316. package/src/hooks/useStep/index.ts +1 -0
  317. package/src/hooks/useStep/useStep.ts +57 -0
  318. package/src/hooks/useToggle/__doc__/useToggle.stories.tsx +25 -0
  319. package/src/hooks/useToggle/__test__/useToggle.test.tsx +43 -0
  320. package/src/hooks/useToggle/index.ts +1 -0
  321. package/src/hooks/useToggle/useToggle.ts +16 -0
  322. package/src/index.ts +6 -0
  323. package/src/lib/cn.ts +8 -0
  324. package/src/lib/index.ts +1 -0
  325. package/src/models/Generic.model.ts +67 -0
  326. package/src/models/index.ts +1 -0
  327. package/src/providers/index.ts +2 -0
  328. package/src/providers/library-provider.tsx +44 -0
  329. package/src/providers/theme/ThemeProvider.tsx +25 -0
  330. package/src/providers/theme/index.ts +3 -0
  331. package/src/providers/theme/types.ts +11 -0
  332. package/src/providers/theme/useThemeProps.ts +25 -0
  333. package/src/stores/theme.store.ts +31 -0
  334. package/src/styles/components.css +4 -0
  335. package/src/styles/index.css +2 -0
  336. package/src/styles/library.css +2 -0
  337. package/src/styles/theme.css +232 -0
  338. package/src/utils/dates/parseDateRange.utility.ts +39 -0
  339. package/src/utils/form.tsx +91 -0
  340. package/src/utils/functions/createSafeContext.ts +17 -0
  341. package/src/utils/functions/ensureReactElement.tsx +30 -0
  342. package/src/utils/functions/getFormData.ts +19 -0
  343. package/src/utils/functions/index.ts +4 -0
  344. package/src/utils/functions/mergeRefs.ts +18 -0
  345. package/src/utils/index.ts +3 -0
  346. package/src/utils/strings/extractInitials.utility.ts +10 -0
  347. package/src/utils/strings/index.ts +1 -0
  348. package/src/utils/tests/click.ts +3 -0
  349. package/src/utils/tests/index.ts +2 -0
  350. package/src/utils/tests/keyboard.ts +21 -0
  351. package/src/utils/tests/type.ts +6 -0
  352. package/dist/components.css +0 -2
@@ -0,0 +1,36 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { Skeleton } from "./skeleton";
3
+
4
+ /**
5
+ * Loading placeholder that fills the space of the expected content.
6
+ * Fully composable — apply size, shape, and spacing directly via `className`.
7
+ * Conditionally render it yourself; `Skeleton` does not manage loading state.
8
+ */
9
+ const meta: Meta<typeof Skeleton> = {
10
+ title: "Components/Skeleton",
11
+ component: Skeleton,
12
+ args: {
13
+ className: "h-4 w-[200px]",
14
+ },
15
+ };
16
+
17
+ export default meta;
18
+ type Story = StoryObj<typeof meta>;
19
+
20
+ export const Default: Story = {};
21
+
22
+ /**
23
+ * Compose multiple skeletons to sketch the loading state of a complex layout.
24
+ * Each skeleton maps 1:1 to a piece of real content it replaces.
25
+ */
26
+ export const Composition: Story = {
27
+ render: () => (
28
+ <div className="flex items-center gap-4">
29
+ <Skeleton className="size-10 shrink-0 rounded-full" />
30
+ <div className="flex flex-col gap-2">
31
+ <Skeleton className="h-4 w-[150px]" />
32
+ <Skeleton className="h-4 w-[100px]" />
33
+ </div>
34
+ </div>
35
+ ),
36
+ };
@@ -0,0 +1,14 @@
1
+ import { render, screen } from "@testing-library/react";
2
+ import { describe, expect, it } from "vitest";
3
+ import { Skeleton } from "../../components";
4
+
5
+ describe("Skeleton component", () => {
6
+ const testId = "skeleton";
7
+
8
+ it("should render correctly", () => {
9
+ render(<Skeleton data-testid={testId} />);
10
+ const skeleton = screen.getByTestId(testId);
11
+
12
+ expect(skeleton).toBeInTheDocument();
13
+ });
14
+ });
@@ -0,0 +1,15 @@
1
+ import type { ComponentProps } from "react";
2
+ import { cn } from "../../lib";
3
+
4
+ export function Skeleton({ className, ...props }: ComponentProps<"div">) {
5
+ return (
6
+ <div
7
+ className={cn(
8
+ "animate-skeleton rounded-sm [--skeleton-highlight:--alpha(var(--color-white)/64%)] [background:linear-gradient(120deg,transparent_40%,var(--skeleton-highlight),transparent_60%)_var(--color-muted)_0_0/200%_100%_fixed] dark:[--skeleton-highlight:--alpha(var(--color-white)/4%)]",
9
+ className,
10
+ )}
11
+ data-slot="skeleton"
12
+ {...props}
13
+ />
14
+ );
15
+ }
@@ -0,0 +1 @@
1
+ export * from "./stack";
@@ -0,0 +1,194 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { Avatar } from "../avatar";
3
+ import { Button } from "../button";
4
+ import { Input } from "../input";
5
+ import { Label } from "../label";
6
+ import { Stack } from ".";
7
+
8
+ /**
9
+ * Layout primitive that composes children along a horizontal or vertical axis using flexbox.
10
+ * Supports polymorphic rendering via `as` for semantic HTML (ul, nav, section, etc.).
11
+ * `reverse` inverts the flex direction without exposing raw CSS values.
12
+ * `grow` makes the container fill available space (`flex: 1`).
13
+ */
14
+ const meta: Meta<typeof Stack> = {
15
+ title: "Components/Stack",
16
+ component: Stack,
17
+ args: {
18
+ gap: 8,
19
+ },
20
+ };
21
+
22
+ export default meta;
23
+ type Story = StoryObj<typeof Stack>;
24
+
25
+ export const Default: Story = {
26
+ args: {
27
+ align: "center",
28
+ },
29
+ render: (args) => (
30
+ <Stack {...args}>
31
+ <Avatar src="https://i.pravatar.cc/150?img=12" alt="Sara Lane" />
32
+ <span className="font-semibold text-lg">Sara Lane</span>
33
+ </Stack>
34
+ ),
35
+ };
36
+
37
+ export const Vertical: Story = {
38
+ args: {
39
+ direction: "vertical",
40
+ },
41
+ render: (args) => (
42
+ <Stack {...args}>
43
+ <Label>Username</Label>
44
+ <Input type="text" placeholder="Enter your username" />
45
+ </Stack>
46
+ ),
47
+ };
48
+
49
+ /**
50
+ * `reverse` flips the axis direction without needing to know the underlying CSS value
51
+ * (`row-reverse` or `column-reverse`).
52
+ */
53
+ export const Reverse: Story = {
54
+ render: () => (
55
+ <Stack direction="vertical" gap={16}>
56
+ <Stack align="center" gap={8}>
57
+ <span className="text-sm text-muted-foreground w-24">horizontal</span>
58
+ <Stack gap={8}>
59
+ <Button>First</Button>
60
+ <Button variant="secondary">Second</Button>
61
+ <Button variant="outline">Third</Button>
62
+ </Stack>
63
+ </Stack>
64
+ <Stack align="center" gap={8}>
65
+ <span className="text-sm text-muted-foreground w-24">reverse</span>
66
+ <Stack reverse gap={8}>
67
+ <Button>First</Button>
68
+ <Button variant="secondary">Second</Button>
69
+ <Button variant="outline">Third</Button>
70
+ </Stack>
71
+ </Stack>
72
+ </Stack>
73
+ ),
74
+ };
75
+
76
+ /**
77
+ * `wrap` enables `flex-wrap` so children overflow onto the next line instead of shrinking.
78
+ * Useful for tag lists, badge groups, and responsive card grids.
79
+ */
80
+ export const Wrap: Story = {
81
+ render: () => (
82
+ <Stack wrap="wrap" gap={8} className="max-w-[300px]">
83
+ {Array.from({ length: 10 }, (_, i) => (
84
+ <Button key={i} variant="outline" size="sm">
85
+ Tag {i + 1}
86
+ </Button>
87
+ ))}
88
+ </Stack>
89
+ ),
90
+ };
91
+
92
+ /**
93
+ * `grow` applies `flex: 1` to the Stack, making it fill the remaining space of its parent.
94
+ * Useful for sidebars, split panes, and full-height layouts.
95
+ */
96
+ export const Grow: Story = {
97
+ render: () => (
98
+ <Stack className="h-[120px] border rounded p-2">
99
+ <div className="w-16 bg-muted rounded flex items-center justify-center text-xs">
100
+ Fixed
101
+ </div>
102
+ <Stack
103
+ grow
104
+ direction="vertical"
105
+ gap={4}
106
+ className="bg-muted/40 rounded p-2"
107
+ >
108
+ <span className="text-xs font-medium">Grows to fill</span>
109
+ <span className="text-xs text-muted-foreground">flex: 1</span>
110
+ </Stack>
111
+ </Stack>
112
+ ),
113
+ };
114
+
115
+ /**
116
+ * `as` renders the Stack as a different HTML element for semantic markup.
117
+ * Children of a `ul` stack should be `li` elements.
118
+ */
119
+ export const As: Story = {
120
+ render: () => (
121
+ <Stack as="ul" direction="vertical" gap={4} className="list-none p-0 m-0">
122
+ <li>Item one</li>
123
+ <li>Item two</li>
124
+ <li>Item three</li>
125
+ </Stack>
126
+ ),
127
+ };
128
+
129
+ export const Justify: Story = {
130
+ render: () => (
131
+ <Stack direction="vertical" gap={12}>
132
+ {(
133
+ [
134
+ "flex-start",
135
+ "center",
136
+ "flex-end",
137
+ "space-between",
138
+ "space-evenly",
139
+ ] as const
140
+ ).map((value) => (
141
+ <Stack key={value} direction="vertical" gap={4}>
142
+ <span className="text-xs text-muted-foreground">{value}</span>
143
+ <Stack justify={value} className="border rounded p-2">
144
+ <Button size="sm">A</Button>
145
+ <Button size="sm" variant="secondary">
146
+ B
147
+ </Button>
148
+ </Stack>
149
+ </Stack>
150
+ ))}
151
+ </Stack>
152
+ ),
153
+ };
154
+
155
+ export const Align: Story = {
156
+ render: () => (
157
+ <Stack direction="vertical" gap={12} className="w-fit">
158
+ {(["flex-start", "center", "flex-end"] as const).map((value) => (
159
+ <Stack key={value} direction="vertical" gap={4}>
160
+ <span className="text-xs text-muted-foreground">{value}</span>
161
+ <Stack align={value} className="border rounded p-2 h-20">
162
+ <Button size="sm">A</Button>
163
+ <Button size="sm" variant="secondary">
164
+ B
165
+ </Button>
166
+ </Stack>
167
+ </Stack>
168
+ ))}
169
+ </Stack>
170
+ ),
171
+ };
172
+
173
+ export const Nested: Story = {
174
+ args: {
175
+ align: "center",
176
+ gap: 16,
177
+ },
178
+ render: (args) => (
179
+ <Stack {...args}>
180
+ <Avatar
181
+ className="w-16 h-16"
182
+ src="https://i.pravatar.cc/150?img=12"
183
+ alt="Sara Lane"
184
+ />
185
+ <Stack direction="vertical" gap={4}>
186
+ <span className="font-semibold text-lg">Sara Lane</span>
187
+ <span className="text-sm text-muted-foreground max-w-[360px]">
188
+ Senior product designer with 8 years of experience building design
189
+ systems and component libraries for cross-functional teams.
190
+ </span>
191
+ </Stack>
192
+ </Stack>
193
+ ),
194
+ };
@@ -0,0 +1,52 @@
1
+ import { ComponentProps, CSSProperties, ElementType } from "react";
2
+ import { cn } from "../../lib";
3
+
4
+ interface StackProps extends ComponentProps<"div"> {
5
+ as?: ElementType;
6
+ inline?: boolean;
7
+ direction?: "horizontal" | "vertical";
8
+ reverse?: boolean;
9
+ justify?: CSSProperties["justifyContent"];
10
+ align?: CSSProperties["alignItems"];
11
+ gap?: CSSProperties["gap"];
12
+ wrap?: CSSProperties["flexWrap"];
13
+ grow?: boolean;
14
+ }
15
+
16
+ export const Stack = ({
17
+ as: Tag = "div",
18
+ inline = false,
19
+ direction = "horizontal",
20
+ reverse = false,
21
+ justify,
22
+ align,
23
+ gap = 8,
24
+ wrap,
25
+ grow = false,
26
+ className,
27
+ style,
28
+ ...props
29
+ }: StackProps) => {
30
+ const flexDirection =
31
+ `${direction === "vertical" ? "column" : "row"}${reverse ? "-reverse" : ""}` as CSSProperties["flexDirection"];
32
+
33
+ return (
34
+ <Tag
35
+ className={cn(
36
+ inline ? "inline-flex" : "flex",
37
+ grow && "flex-1",
38
+ className,
39
+ )}
40
+ style={{
41
+ flexDirection,
42
+ justifyContent: justify,
43
+ alignItems: align,
44
+ gap,
45
+ flexWrap: wrap,
46
+ ...style,
47
+ }}
48
+ data-slot="stack"
49
+ {...props}
50
+ />
51
+ );
52
+ };
@@ -0,0 +1,190 @@
1
+ import { useControllableState } from "@radix-ui/react-use-controllable-state";
2
+ import { HTMLProps, ReactNode } from "react";
3
+ import { ClassNameValue } from "tailwind-merge";
4
+ import { ClassName } from "@/models";
5
+ import { cn } from "../../lib";
6
+ import {
7
+ StepperContextProvider,
8
+ useStepperContext,
9
+ } from "./context/stepper-context";
10
+
11
+ interface StepperItemProps {
12
+ indicator?: ReactNode;
13
+ title: ReactNode;
14
+ content?: ReactNode;
15
+ disabled?: boolean;
16
+ }
17
+
18
+ interface StepperProps extends Omit<HTMLProps<HTMLDivElement>, "onChange"> {
19
+ items?: StepperItemProps[];
20
+ current?: number;
21
+ onChange?: (index: number) => void;
22
+ className?: ClassName;
23
+ classNameList?: ClassName;
24
+ classNameItem?: ClassName;
25
+ classNameButton?: ClassName;
26
+ classNameIndicator?: ClassName;
27
+ classNameContent?: ClassName;
28
+ }
29
+ export function Stepper({
30
+ items = [],
31
+ current,
32
+ onChange,
33
+ className,
34
+ classNameList,
35
+ classNameItem,
36
+ classNameButton,
37
+ classNameIndicator,
38
+ classNameContent,
39
+ }: StepperProps) {
40
+ return (
41
+ <StepperContainer
42
+ className={className}
43
+ current={current}
44
+ onChange={onChange}
45
+ >
46
+ <StepperList className={classNameList}>
47
+ {items?.map((item, i) => (
48
+ <StepperTrigger
49
+ key={i}
50
+ value={i}
51
+ title={item?.title}
52
+ indicator={item?.indicator}
53
+ classNameItem={classNameItem}
54
+ classNameButton={classNameButton}
55
+ classNameIndicator={classNameIndicator}
56
+ />
57
+ ))}
58
+ </StepperList>
59
+
60
+ {items?.map((item, i) => (
61
+ <StepperContent className={classNameContent} key={i} value={i}>
62
+ {item?.content}
63
+ </StepperContent>
64
+ ))}
65
+ </StepperContainer>
66
+ );
67
+ }
68
+
69
+ interface StepperContainerProps
70
+ extends Omit<HTMLProps<HTMLDivElement>, "onChange"> {
71
+ current?: number;
72
+ onChange?: (index: number) => void;
73
+ className?: ClassName;
74
+ }
75
+ export function StepperContainer({
76
+ current: prop,
77
+ onChange,
78
+ className,
79
+ ...props
80
+ }: StepperContainerProps) {
81
+ const [activeStep = 0, setActiveStep] = useControllableState<number>({
82
+ prop,
83
+ onChange,
84
+ defaultProp: 0,
85
+ });
86
+ return (
87
+ <StepperContextProvider value={{ activeStep, setActiveStep }}>
88
+ <div
89
+ data-slot="stepper"
90
+ className={cn(
91
+ "flex flex-col items-center w-full transition-all ease-in delay-150",
92
+ className,
93
+ )}
94
+ {...props}
95
+ />
96
+ </StepperContextProvider>
97
+ );
98
+ }
99
+
100
+ interface StepperListProps extends HTMLProps<HTMLUListElement> {}
101
+ export function StepperList({
102
+ children,
103
+ className,
104
+ ...props
105
+ }: StepperListProps) {
106
+ return (
107
+ <ul
108
+ data-slot="stepper-list"
109
+ className={cn(
110
+ "flex flex-col sm:flex-row sm:gap-0 gap-4 items-center w-full text-xs font-medium text-gray-900 sm:text-base mb-8",
111
+ className,
112
+ )}
113
+ {...props}
114
+ >
115
+ {children}
116
+ </ul>
117
+ );
118
+ }
119
+
120
+ interface StepperTriggerProps {
121
+ indicator?: ReactNode;
122
+ title: ReactNode;
123
+ value: number;
124
+ disabled?: boolean;
125
+ classNameItem?: ClassNameValue;
126
+ classNameButton?: ClassNameValue;
127
+ classNameIndicator?: ClassNameValue;
128
+ }
129
+ export function StepperTrigger({
130
+ disabled,
131
+ value,
132
+ title,
133
+ indicator,
134
+ classNameItem,
135
+ classNameButton,
136
+ classNameIndicator,
137
+ }: StepperTriggerProps) {
138
+ const { activeStep, setActiveStep } = useStepperContext();
139
+ return (
140
+ <li
141
+ data-slot="stepper-trigger"
142
+ className={cn(
143
+ "flex relative text-primary transition-all ease-in delay-150",
144
+ "last:w-full last:sm:w-auto last:after:hidden",
145
+ `w-full after:content-[''] sm:after:w-full after:h-full after:w-0.5 sm:after:h-0.5 ${activeStep > value ? "after:bg-primary" : "after:bg-gray-300"} after:inline-block after:absolute after:top-5 sm:after:top-5 after:left-4 sm:after:left-10`,
146
+ classNameItem,
147
+ )}
148
+ >
149
+ <button
150
+ onClick={() => !disabled && setActiveStep(value)}
151
+ className={cn(
152
+ "z-10 flex items-center justify-center sm:flex-col gap-3 flex-row whitespace-nowrap cursor-pointer group transition-color ease-in delay-150",
153
+ activeStep >= value ? "text-primary" : "text-gray-500",
154
+ disabled && "cursor-not-allowed",
155
+ classNameButton,
156
+ )}
157
+ >
158
+ <span
159
+ data-slot="stepper-trigger-indicator"
160
+ className={cn(
161
+ "flex items-center transition-all overflow-hidden ease-in justify-center group-hover:scale-105 sm:w-10 sm:h-10 mx-auto text-sm border-2 rounded-full w-8 h-8",
162
+ activeStep > value &&
163
+ "bg-primary border-primary text-primary-foreground",
164
+ activeStep === value && "bg-gray-100 text-primary border-primary",
165
+ activeStep < value && "bg-white text-gray-500 border-input",
166
+ disabled && "text-gray-300",
167
+ classNameIndicator,
168
+ )}
169
+ >
170
+ {activeStep > value ? "✓" : indicator || value + 1}
171
+ </span>
172
+ {title}
173
+ </button>
174
+ </li>
175
+ );
176
+ }
177
+
178
+ interface StepperContentProps extends HTMLProps<HTMLDivElement> {
179
+ value: number;
180
+ }
181
+ export function StepperContent({
182
+ value,
183
+ className = "w-full",
184
+ ...props
185
+ }: StepperContentProps) {
186
+ const { activeStep } = useStepperContext();
187
+ const isActiveStep = activeStep === value;
188
+ if (!isActiveStep) return null;
189
+ return <div data-slot="stepper-content" className={className} {...props} />;
190
+ }
@@ -0,0 +1,11 @@
1
+ import { createSafeContext } from "../../../utils";
2
+
3
+ interface StepperContextProps {
4
+ activeStep: number;
5
+ setActiveStep: (index: number) => void;
6
+ }
7
+
8
+ export const [useStepperContext, StepperContextProvider] =
9
+ createSafeContext<StepperContextProps>();
10
+
11
+ export type { StepperContextProps };
@@ -0,0 +1 @@
1
+ export * from "./Stepper";
@@ -0,0 +1,130 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { RectangleEllipsis, Settings, User } from "lucide-react";
3
+ import {
4
+ Button,
5
+ Input,
6
+ Stepper,
7
+ StepperContainer,
8
+ StepperContent,
9
+ StepperList,
10
+ StepperTrigger,
11
+ } from "../../components";
12
+ import { useStep } from "../../hooks";
13
+
14
+ const meta: Meta<typeof Stepper> = {
15
+ title: "Data display/Stepper",
16
+ component: Stepper,
17
+ args: {},
18
+ };
19
+
20
+ export default meta;
21
+ type Story = StoryObj<typeof Stepper>;
22
+
23
+ const AccountStep = () => {
24
+ return (
25
+ <>
26
+ <Input name="name" />
27
+ <Input name="lastname" />
28
+ </>
29
+ );
30
+ };
31
+
32
+ const PasswordStep = () => {
33
+ return (
34
+ <>
35
+ <Input name="password" type="password" />
36
+ <Input name="confirmation" type="password" />
37
+ </>
38
+ );
39
+ };
40
+
41
+ const FileStep = () => {
42
+ return (
43
+ <>
44
+ <Input name="file" type="file" />
45
+ </>
46
+ );
47
+ };
48
+
49
+ const steps = [
50
+ { title: "Cuenta", content: <AccountStep />, indicator: <User /> },
51
+ { title: "Configuracón", content: <FileStep />, indicator: <Settings /> },
52
+ {
53
+ title: "Contraseña",
54
+ content: <PasswordStep />,
55
+ indicator: <RectangleEllipsis />,
56
+ },
57
+ ];
58
+
59
+ export const Default: Story = {
60
+ render: () => {
61
+ return <Stepper items={steps} />;
62
+ },
63
+ };
64
+
65
+ export const Disabled: Story = {
66
+ render: () => {
67
+ return (
68
+ <Stepper
69
+ items={[
70
+ { title: "Cuenta", content: <AccountStep /> },
71
+ { title: "Configuracón", content: <FileStep /> },
72
+ { title: "Contraseña", content: <PasswordStep />, disabled: true },
73
+ ]}
74
+ />
75
+ );
76
+ },
77
+ };
78
+
79
+ /**
80
+ * Se puede utilizar el hook `useStep` para facilitar el manejo de estado y validaciones
81
+ */
82
+ export const Steps: Story = {
83
+ render: () => {
84
+ const { currentStepIndex, isFirstStep, isLastStep, next, back, goTo } =
85
+ useStep(steps);
86
+
87
+ return (
88
+ <div>
89
+ <Stepper
90
+ items={steps}
91
+ current={currentStepIndex}
92
+ onChange={(step: number) => goTo(step)}
93
+ />
94
+ <div className="flex justify-end gap-x-2 mt-2">
95
+ <Button variant="ghost" disabled={isFirstStep} onClick={back}>
96
+ Prev
97
+ </Button>
98
+ <Button disabled={isLastStep} onClick={next}>
99
+ Next
100
+ </Button>
101
+ </div>
102
+ </div>
103
+ );
104
+ },
105
+ };
106
+
107
+ export const StepperWithPrimitives: Story = {
108
+ render: () => {
109
+ return (
110
+ <StepperContainer>
111
+ <StepperList>
112
+ {steps?.map((item, i) => (
113
+ <StepperTrigger
114
+ key={i}
115
+ value={i}
116
+ title={item?.title}
117
+ indicator={item?.indicator}
118
+ />
119
+ ))}
120
+ </StepperList>
121
+
122
+ {steps?.map((item, i) => (
123
+ <StepperContent key={i} value={i}>
124
+ {item?.content}
125
+ </StepperContent>
126
+ ))}
127
+ </StepperContainer>
128
+ );
129
+ },
130
+ };