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

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 (349) hide show
  1. package/dist/index.css +1 -1
  2. package/package.json +4 -3
  3. package/src/__doc__/Changelog.mdx +6 -0
  4. package/src/__doc__/Components.mdx +73 -0
  5. package/src/__doc__/Examples.tsx +69 -0
  6. package/src/__doc__/Icons.mdx +41 -0
  7. package/src/__doc__/Intro.mdx +138 -0
  8. package/src/__doc__/MCP.mdx +71 -0
  9. package/src/__doc__/Migration.mdx +475 -0
  10. package/src/__doc__/Theme.mdx +132 -0
  11. package/src/__doc__/Types.mdx +252 -0
  12. package/src/components/alert/alert.stories.tsx +142 -0
  13. package/src/components/alert/alert.tsx +109 -0
  14. package/src/components/alert/index.ts +7 -0
  15. package/src/components/alert-dialog/alert-dialog.stories.tsx +173 -0
  16. package/src/components/alert-dialog/alert-dialog.test.tsx +49 -0
  17. package/src/components/alert-dialog/alert-dialog.tsx +265 -0
  18. package/src/components/alert-dialog/index.ts +1 -0
  19. package/src/components/auto-complete/auto-complete-primitives.tsx +155 -0
  20. package/src/components/auto-complete/auto-complete.stories.tsx +241 -0
  21. package/src/components/auto-complete/auto-complete.tsx +82 -0
  22. package/src/components/auto-complete/index.ts +2 -0
  23. package/src/components/avatar/avatar.stories.tsx +84 -0
  24. package/src/components/avatar/avatar.test.tsx +61 -0
  25. package/src/components/avatar/avatar.tsx +104 -0
  26. package/src/components/avatar/index.ts +1 -0
  27. package/src/components/background-image/background-image.stories.tsx +21 -0
  28. package/src/components/background-image/background-image.test.tsx +29 -0
  29. package/src/components/background-image/background-image.tsx +23 -0
  30. package/src/components/background-image/index.ts +1 -0
  31. package/src/components/button/button.stories.tsx +396 -0
  32. package/src/components/button/button.test.tsx +58 -0
  33. package/src/components/button/button.tsx +31 -0
  34. package/src/components/button/button.variants.ts +44 -0
  35. package/src/components/button/components/base-button.tsx +86 -0
  36. package/src/components/button/components/loader-overlay.tsx +21 -0
  37. package/src/components/button/components/loading-icon.tsx +47 -0
  38. package/src/components/button/index.ts +3 -0
  39. package/src/components/calendar/calendar.model.ts +86 -0
  40. package/src/components/calendar/calendar.stories.tsx +155 -0
  41. package/src/components/calendar/calendar.test.tsx +12 -0
  42. package/src/components/calendar/calendar.tsx +185 -0
  43. package/src/components/calendar/components/calendar-navigation.tsx +141 -0
  44. package/src/components/calendar/components/day.tsx +61 -0
  45. package/src/components/calendar/components/decade-view.tsx +45 -0
  46. package/src/components/calendar/components/index.ts +6 -0
  47. package/src/components/calendar/components/month-view.tsx +58 -0
  48. package/src/components/calendar/components/week-days.tsx +27 -0
  49. package/src/components/calendar/components/year-view.tsx +29 -0
  50. package/src/components/calendar/hooks/index.ts +4 -0
  51. package/src/components/calendar/hooks/use-calendar-navigation.ts +79 -0
  52. package/src/components/calendar/hooks/use-calendar.ts +90 -0
  53. package/src/components/calendar/hooks/use-multiple-calendar.ts +34 -0
  54. package/src/components/calendar/hooks/use-range-calendar.ts +91 -0
  55. package/src/components/calendar/hooks/use-single-calendar.ts +18 -0
  56. package/src/components/calendar/index.ts +1 -0
  57. package/src/components/calendar/utils/typeguards.ts +7 -0
  58. package/src/components/card/card.stories.tsx +116 -0
  59. package/src/components/card/card.tsx +74 -0
  60. package/src/components/card/index.ts +1 -0
  61. package/src/components/center/center.stories.tsx +81 -0
  62. package/src/components/center/center.tsx +24 -0
  63. package/src/components/center/index.ts +1 -0
  64. package/src/components/checkbox/checkbox.stories.tsx +307 -0
  65. package/src/components/checkbox/checkbox.tsx +273 -0
  66. package/src/components/checkbox/index.ts +1 -0
  67. package/src/components/checkbox-group/checkbox-group.stories.tsx +104 -0
  68. package/src/components/checkbox-group/checkbox-group.tsx +16 -0
  69. package/src/components/checkbox-group/index.ts +1 -0
  70. package/src/components/combobox/combobox.stories.tsx +339 -0
  71. package/src/components/combobox/combobox.tsx +892 -0
  72. package/src/components/combobox/index.ts +1 -0
  73. package/src/components/date-picker/date-input.stories.tsx +158 -0
  74. package/src/components/date-picker/date-input.tsx +163 -0
  75. package/src/components/date-picker/date-picker.model.ts +90 -0
  76. package/src/components/date-picker/date-picker.stories.tsx +200 -0
  77. package/src/components/date-picker/date-picker.test.tsx +23 -0
  78. package/src/components/date-picker/date-picker.tsx +298 -0
  79. package/src/components/date-picker/date-picker.utils.ts +260 -0
  80. package/src/components/date-picker/index.ts +3 -0
  81. package/src/components/date-picker/use-date-input-popover.ts +48 -0
  82. package/src/components/date-picker/use-date-input.ts +125 -0
  83. package/src/components/dialog/dialog.stories.tsx +171 -0
  84. package/src/components/dialog/dialog.test.tsx +68 -0
  85. package/src/components/dialog/dialog.tsx +277 -0
  86. package/src/components/dialog/index.ts +1 -0
  87. package/src/components/divider/divider.stories.tsx +70 -0
  88. package/src/components/divider/divider.test.tsx +22 -0
  89. package/src/components/divider/divider.tsx +23 -0
  90. package/src/components/divider/index.ts +1 -0
  91. package/src/components/dropzone/dropzone.stories.tsx +210 -0
  92. package/src/components/dropzone/dropzone.tsx +154 -0
  93. package/src/components/dropzone/file-types.ts +64 -0
  94. package/src/components/dropzone/index.ts +3 -0
  95. package/src/components/dropzone/upload-primitives.tsx +310 -0
  96. package/src/components/dropzone/use-dropzone.ts +122 -0
  97. package/src/components/empty-state/empty-state.stories.tsx +56 -0
  98. package/src/components/empty-state/empty-state.tsx +39 -0
  99. package/src/components/empty-state/index.ts +1 -0
  100. package/src/components/field/field.stories.tsx +223 -0
  101. package/src/components/field/field.tsx +229 -0
  102. package/src/components/field/index.ts +1 -0
  103. package/src/components/form/form.stories.tsx +594 -0
  104. package/src/components/form/form.tsx +30 -0
  105. package/src/components/form/index.ts +1 -0
  106. package/src/components/heading/heading.stories.tsx +74 -0
  107. package/src/components/heading/heading.tsx +28 -0
  108. package/src/components/heading/heading.variants.ts +27 -0
  109. package/src/components/heading/index.ts +1 -0
  110. package/src/components/index.ts +46 -0
  111. package/src/components/input/index.ts +1 -0
  112. package/src/components/input/input.stories.tsx +104 -0
  113. package/src/components/input/input.tsx +75 -0
  114. package/src/components/kbd/index.ts +1 -0
  115. package/src/components/kbd/kbd.stories.tsx +40 -0
  116. package/src/components/kbd/kbd.tsx +31 -0
  117. package/src/components/kbd/kbd.variants.ts +26 -0
  118. package/src/components/label/index.ts +1 -0
  119. package/src/components/label/label.stories.tsx +68 -0
  120. package/src/components/label/label.test.tsx +61 -0
  121. package/src/components/label/label.tsx +62 -0
  122. package/src/components/loader/index.ts +1 -0
  123. package/src/components/loader/loader.stories.tsx +60 -0
  124. package/src/components/loader/loader.test.tsx +26 -0
  125. package/src/components/loader/loader.tsx +60 -0
  126. package/src/components/menu/index.ts +2 -0
  127. package/src/components/menu/menu-primitives.tsx +248 -0
  128. package/src/components/menu/menu.stories.tsx +203 -0
  129. package/src/components/menu/menu.tsx +100 -0
  130. package/src/components/menu/util/render-menu-item.tsx +54 -0
  131. package/src/components/multi-select/hooks/use-multi-select.ts +66 -0
  132. package/src/components/multi-select/index.ts +1 -0
  133. package/src/components/multi-select/multi-select.stories.tsx +294 -0
  134. package/src/components/multi-select/multi-select.tsx +300 -0
  135. package/src/components/multi-select/multi-select.variants.ts +22 -0
  136. package/src/components/number-input/index.ts +1 -0
  137. package/src/components/number-input/number-input.stories.tsx +209 -0
  138. package/src/components/number-input/number-input.test.tsx +87 -0
  139. package/src/components/number-input/number-input.tsx +230 -0
  140. package/src/components/pagination/components/pagination-option.tsx +27 -0
  141. package/src/components/pagination/index.ts +1 -0
  142. package/src/components/pagination/pagination.stories.tsx +80 -0
  143. package/src/components/pagination/pagination.test.tsx +76 -0
  144. package/src/components/pagination/pagination.tsx +102 -0
  145. package/src/components/password/index.ts +1 -0
  146. package/src/components/password/password.stories.tsx +104 -0
  147. package/src/components/password/password.tsx +71 -0
  148. package/src/components/popover/index.ts +1 -0
  149. package/src/components/popover/popover.stories.tsx +213 -0
  150. package/src/components/popover/popover.tsx +203 -0
  151. package/src/components/progress/index.ts +1 -0
  152. package/src/components/progress/progress.stories.tsx +124 -0
  153. package/src/components/progress/progress.test.tsx +25 -0
  154. package/src/components/progress/progress.tsx +124 -0
  155. package/src/components/scroll-area/index.ts +1 -0
  156. package/src/components/scroll-area/scroll-area.stories.tsx +166 -0
  157. package/src/components/scroll-area/scroll-area.tsx +64 -0
  158. package/src/components/select/index.ts +1 -0
  159. package/src/components/select/select.stories.tsx +253 -0
  160. package/src/components/select/select.tsx +430 -0
  161. package/src/components/show/index.ts +1 -0
  162. package/src/components/show/show.stories.tsx +197 -0
  163. package/src/components/show/show.test.tsx +41 -0
  164. package/src/components/show/show.tsx +16 -0
  165. package/src/components/skeleton/index.ts +1 -0
  166. package/src/components/skeleton/skeleton.stories.tsx +36 -0
  167. package/src/components/skeleton/skeleton.test.tsx +14 -0
  168. package/src/components/skeleton/skeleton.tsx +15 -0
  169. package/src/components/stack/index.ts +1 -0
  170. package/src/components/stack/stack.stories.tsx +194 -0
  171. package/src/components/stack/stack.tsx +52 -0
  172. package/src/components/stepper/Stepper.tsx +190 -0
  173. package/src/components/stepper/context/stepper-context.tsx +11 -0
  174. package/src/components/stepper/index.ts +1 -0
  175. package/src/components/stepper/stepper.stories.tsx +130 -0
  176. package/src/components/stepper/stepper.test.tsx +91 -0
  177. package/src/components/switch/index.ts +1 -0
  178. package/src/components/switch/switch.stories.tsx +122 -0
  179. package/src/components/switch/switch.test.tsx +30 -0
  180. package/src/components/switch/switch.tsx +86 -0
  181. package/src/components/table/index.ts +3 -0
  182. package/src/components/table/table-primitives.tsx +122 -0
  183. package/src/components/table/table.model.ts +20 -0
  184. package/src/components/table/table.stories.tsx +169 -0
  185. package/src/components/table/table.test.tsx +91 -0
  186. package/src/components/table/table.tsx +109 -0
  187. package/src/components/table-pagination/index.ts +2 -0
  188. package/src/components/table-pagination/table-pagination.model.ts +2 -0
  189. package/src/components/table-pagination/table-pagination.stories.tsx +23 -0
  190. package/src/components/table-pagination/table-pagination.test.tsx +32 -0
  191. package/src/components/table-pagination/table-pagination.tsx +108 -0
  192. package/src/components/tabs/context/tabs-context.tsx +14 -0
  193. package/src/components/tabs/index.ts +1 -0
  194. package/src/components/tabs/tabs.stories.tsx +182 -0
  195. package/src/components/tabs/tabs.test.tsx +61 -0
  196. package/src/components/tabs/tabs.tsx +175 -0
  197. package/src/components/tag/index.ts +2 -0
  198. package/src/components/tag/tag.stories.tsx +170 -0
  199. package/src/components/tag/tag.test.tsx +18 -0
  200. package/src/components/tag/tag.tsx +99 -0
  201. package/src/components/tag/tag.variants.ts +31 -0
  202. package/src/components/textarea/index.ts +1 -0
  203. package/src/components/textarea/textarea.stories.tsx +73 -0
  204. package/src/components/textarea/textarea.tsx +105 -0
  205. package/src/components/timeline/index.ts +1 -0
  206. package/src/components/timeline/timeline-status.ts +5 -0
  207. package/src/components/timeline/timeline.stories.tsx +84 -0
  208. package/src/components/timeline/timeline.tsx +147 -0
  209. package/src/components/toast/index.ts +1 -0
  210. package/src/components/toast/toast.stories.tsx +392 -0
  211. package/src/components/toast/toast.test.tsx +50 -0
  212. package/src/components/toast/toast.tsx +411 -0
  213. package/src/components/tooltip/index.ts +1 -0
  214. package/src/components/tooltip/tooltip.stories.tsx +226 -0
  215. package/src/components/tooltip/tooltip.test.tsx +46 -0
  216. package/src/components/tooltip/tooltip.tsx +171 -0
  217. package/src/components/tree/hooks/use-controllable-tree-state.ts +80 -0
  218. package/src/components/tree/index.ts +2 -0
  219. package/src/components/tree/tree-primitives.tsx +126 -0
  220. package/src/components/tree/tree.stories.tsx +468 -0
  221. package/src/components/tree/tree.tsx +42 -0
  222. package/src/hooks/index.ts +26 -0
  223. package/src/hooks/useArray/__doc__/useArray.stories.tsx +100 -0
  224. package/src/hooks/useArray/__test__/useArray.test.tsx +88 -0
  225. package/src/hooks/useArray/index.ts +1 -0
  226. package/src/hooks/useArray/useArray.ts +76 -0
  227. package/src/hooks/useAsync/__doc__/useAsync.stories.tsx +149 -0
  228. package/src/hooks/useAsync/__test__/useAsync.test.tsx +68 -0
  229. package/src/hooks/useAsync/index.ts +1 -0
  230. package/src/hooks/useAsync/useAsync.ts +58 -0
  231. package/src/hooks/useClickOutside/__doc__/useClickOutside.stories.tsx +40 -0
  232. package/src/hooks/useClickOutside/__test__/useClickOutside.test.tsx +33 -0
  233. package/src/hooks/useClickOutside/index.ts +1 -0
  234. package/src/hooks/useClickOutside/useClickOutside.ts +26 -0
  235. package/src/hooks/useClipboard/__doc__/useClipboard.stories.tsx +45 -0
  236. package/src/hooks/useClipboard/__test__/useClipboard.test.tsx +19 -0
  237. package/src/hooks/useClipboard/index.ts +1 -0
  238. package/src/hooks/useClipboard/useClipboard.tsx +28 -0
  239. package/src/hooks/useDebounceCallback/__doc__/useDebouncedCallback.stories.tsx +84 -0
  240. package/src/hooks/useDebounceCallback/index.ts +1 -0
  241. package/src/hooks/useDebounceCallback/useDebouncedCallback.ts +23 -0
  242. package/src/hooks/useDebounceValue/__doc__/useDebouncedValue.stories.tsx +75 -0
  243. package/src/hooks/useDebounceValue/index.ts +1 -0
  244. package/src/hooks/useDebounceValue/useDebouncedValue.ts +17 -0
  245. package/src/hooks/useDisclosure/__doc__/useDisclosure.stories.tsx +39 -0
  246. package/src/hooks/useDisclosure/__test__/useDisclosure.test.ts +43 -0
  247. package/src/hooks/useDisclosure/index.ts +1 -0
  248. package/src/hooks/useDisclosure/useDisclosure.ts +37 -0
  249. package/src/hooks/useDocumentTitle/__doc__/useDocumentTitle.stories.tsx +26 -0
  250. package/src/hooks/useDocumentTitle/index.ts +1 -0
  251. package/src/hooks/useDocumentTitle/useDocumentTitle.tsx +11 -0
  252. package/src/hooks/useEventListener/__doc__/useEventListener.stories.tsx +28 -0
  253. package/src/hooks/useEventListener/__test__/useEventListener.test.tsx +26 -0
  254. package/src/hooks/useEventListener/index.ts +1 -0
  255. package/src/hooks/useEventListener/useEventListener.ts +25 -0
  256. package/src/hooks/useFocusTrap/__doc__/useFocusTrap.stories.tsx +37 -0
  257. package/src/hooks/useFocusTrap/index.ts +1 -0
  258. package/src/hooks/useFocusTrap/scopeTab.ts +38 -0
  259. package/src/hooks/useFocusTrap/tabbable.ts +70 -0
  260. package/src/hooks/useFocusTrap/useFocusTrap.ts +78 -0
  261. package/src/hooks/useHotkey/__docs__/useHotkey.stories.tsx +116 -0
  262. package/src/hooks/useHotkey/__test__/useHotkey.test.tsx +105 -0
  263. package/src/hooks/useHotkey/__utils__/create-hotkey-listener.ts +25 -0
  264. package/src/hooks/useHotkey/__utils__/index.ts +3 -0
  265. package/src/hooks/useHotkey/__utils__/is-input-field.ts +14 -0
  266. package/src/hooks/useHotkey/__utils__/match-key-modifiers.ts +25 -0
  267. package/src/hooks/useHotkey/index.ts +1 -0
  268. package/src/hooks/useHotkey/useHotkey.ts +34 -0
  269. package/src/hooks/useHover/__doc__/useHover.stories.tsx +41 -0
  270. package/src/hooks/useHover/__test__/useHover.test.tsx +45 -0
  271. package/src/hooks/useHover/index.ts +1 -0
  272. package/src/hooks/useHover/useHover.tsx +40 -0
  273. package/src/hooks/useIsVisible/__doc__/useIsVisible.stories.tsx +60 -0
  274. package/src/hooks/useIsVisible/index.ts +1 -0
  275. package/src/hooks/useIsVisible/useIsVisible.tsx +50 -0
  276. package/src/hooks/useLocalStorage/__doc__/useLocalStorage.stories.tsx +86 -0
  277. package/src/hooks/useLocalStorage/__test__/useLocalStorage.test.ts +85 -0
  278. package/src/hooks/useLocalStorage/index.ts +1 -0
  279. package/src/hooks/useLocalStorage/useLocalStorage.ts +57 -0
  280. package/src/hooks/useMediaQuery/__doc__/useMediaQuery.stories.tsx +39 -0
  281. package/src/hooks/useMediaQuery/index.ts +1 -0
  282. package/src/hooks/useMediaQuery/useMediaQuery.ts +22 -0
  283. package/src/hooks/useMemoizedFn/index.ts +1 -0
  284. package/src/hooks/useMemoizedFn/useMemoizedFn.ts +32 -0
  285. package/src/hooks/useMutation/__doc__/useMutation.stories.tsx +111 -0
  286. package/src/hooks/useMutation/__test__/useMutation.test.tsx +83 -0
  287. package/src/hooks/useMutation/index.ts +1 -0
  288. package/src/hooks/useMutation/useMutation.tsx +60 -0
  289. package/src/hooks/useObject/__doc__/useObject.stories.tsx +119 -0
  290. package/src/hooks/useObject/__test__/useObject.test.tsx +87 -0
  291. package/src/hooks/useObject/index.ts +1 -0
  292. package/src/hooks/useObject/useObject.tsx +48 -0
  293. package/src/hooks/usePagination/__doc__/usePagination.stories.tsx +72 -0
  294. package/src/hooks/usePagination/__test__/usePagination.test.tsx +98 -0
  295. package/src/hooks/usePagination/index.ts +2 -0
  296. package/src/hooks/usePagination/usePagination.tsx +74 -0
  297. package/src/hooks/usePortal/__doc__/usePortal.stories.tsx +19 -0
  298. package/src/hooks/usePortal/__test__/usePortal.test.tsx +20 -0
  299. package/src/hooks/usePortal/index.ts +1 -0
  300. package/src/hooks/usePortal/usePortal.ts +40 -0
  301. package/src/hooks/usePreventCloseWindow/__doc__/usePreventCloseWindow.stories.tsx +32 -0
  302. package/src/hooks/usePreventCloseWindow/index.ts +1 -0
  303. package/src/hooks/usePreventCloseWindow/usePreventCloseWindow.ts +33 -0
  304. package/src/hooks/useRangePagination/__test__/useRangePagination.test.tsx +63 -0
  305. package/src/hooks/useRangePagination/index.ts +2 -0
  306. package/src/hooks/useRangePagination/useRangePagination.tsx +72 -0
  307. package/src/hooks/useSelection/__doc__/useSelection.stories.tsx +140 -0
  308. package/src/hooks/useSelection/__test__/useSelection.test.tsx +57 -0
  309. package/src/hooks/useSelection/index.ts +1 -0
  310. package/src/hooks/useSelection/useSelection.ts +121 -0
  311. package/src/hooks/useStep/__doc__/useStep.stories.tsx +98 -0
  312. package/src/hooks/useStep/__test__/useStep.test.ts +51 -0
  313. package/src/hooks/useStep/index.ts +1 -0
  314. package/src/hooks/useStep/useStep.ts +57 -0
  315. package/src/hooks/useToggle/__doc__/useToggle.stories.tsx +25 -0
  316. package/src/hooks/useToggle/__test__/useToggle.test.tsx +43 -0
  317. package/src/hooks/useToggle/index.ts +1 -0
  318. package/src/hooks/useToggle/useToggle.ts +16 -0
  319. package/src/index.ts +6 -0
  320. package/src/lib/cn.ts +8 -0
  321. package/src/lib/index.ts +1 -0
  322. package/src/models/Generic.model.ts +67 -0
  323. package/src/models/index.ts +1 -0
  324. package/src/providers/index.ts +2 -0
  325. package/src/providers/library-provider.tsx +44 -0
  326. package/src/providers/theme/ThemeProvider.tsx +25 -0
  327. package/src/providers/theme/index.ts +3 -0
  328. package/src/providers/theme/types.ts +11 -0
  329. package/src/providers/theme/useThemeProps.ts +25 -0
  330. package/src/stores/theme.store.ts +31 -0
  331. package/src/styles/components.css +4 -0
  332. package/src/styles/index.css +2 -0
  333. package/src/styles/library.css +2 -0
  334. package/src/styles/theme.css +232 -0
  335. package/src/utils/dates/parseDateRange.utility.ts +39 -0
  336. package/src/utils/form.tsx +91 -0
  337. package/src/utils/functions/createSafeContext.ts +17 -0
  338. package/src/utils/functions/ensureReactElement.tsx +30 -0
  339. package/src/utils/functions/getFormData.ts +19 -0
  340. package/src/utils/functions/index.ts +4 -0
  341. package/src/utils/functions/mergeRefs.ts +18 -0
  342. package/src/utils/index.ts +3 -0
  343. package/src/utils/strings/extractInitials.utility.ts +10 -0
  344. package/src/utils/strings/index.ts +1 -0
  345. package/src/utils/tests/click.ts +3 -0
  346. package/src/utils/tests/index.ts +2 -0
  347. package/src/utils/tests/keyboard.ts +21 -0
  348. package/src/utils/tests/type.ts +6 -0
  349. package/dist/components.css +0 -2
@@ -0,0 +1,43 @@
1
+ import { act, renderHook, waitFor } from "@testing-library/react";
2
+ import { describe, expect, it } from "vitest";
3
+ import useToggle from "../useToggle";
4
+
5
+ describe("useToggle hook", () => {
6
+ it("should be defined", () => {
7
+ const { result } = renderHook(useToggle);
8
+ const [state, toggle] = result.current;
9
+
10
+ expect(state).toBe(false);
11
+ expect(typeof toggle).toBe("function");
12
+ });
13
+
14
+ it("should toggle", () => {
15
+ const { result } = renderHook(useToggle);
16
+ const [state, toggle] = result.current;
17
+
18
+ expect(state).toBe(false);
19
+
20
+ act(() => toggle());
21
+ waitFor(() => {
22
+ expect(state).toBe(true);
23
+ });
24
+
25
+ act(() => toggle());
26
+ waitFor(() => {
27
+ expect(state).toBe(false);
28
+ });
29
+ });
30
+
31
+ it("should force new state", () => {
32
+ const { result } = renderHook(useToggle);
33
+ const [state, toggle] = result.current;
34
+
35
+ expect(state).toBe(false);
36
+
37
+ act(() => toggle(false));
38
+
39
+ waitFor(() => {
40
+ expect(state).toBe(false);
41
+ });
42
+ });
43
+ });
@@ -0,0 +1 @@
1
+ export { default as useToggle } from "./useToggle";
@@ -0,0 +1,16 @@
1
+ import { useState } from "react";
2
+
3
+ type Return = [boolean, (newValue?: boolean) => void];
4
+
5
+ function useToggle(initialValue = false): Return {
6
+ const [value, setValue] = useState<boolean>(initialValue);
7
+
8
+ const toggle = (newValue?: boolean): void => {
9
+ const isUndefined = newValue === undefined;
10
+ setValue(isUndefined ? !value : newValue);
11
+ };
12
+
13
+ return [value, toggle] as const;
14
+ }
15
+
16
+ export default useToggle;
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from "./components";
2
+ export * from "./hooks";
3
+ export * from "./lib";
4
+ export * from "./models";
5
+ export * from "./providers";
6
+ export * from "./utils";
package/src/lib/cn.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { type ClassValue, clsx } from "clsx";
2
+ import { extendTailwindMerge } from "tailwind-merge";
3
+
4
+ export const twMerge = extendTailwindMerge({});
5
+
6
+ export function cn(...args: ClassValue[]) {
7
+ return twMerge(clsx(args));
8
+ }
@@ -0,0 +1 @@
1
+ export * from "./cn";
@@ -0,0 +1,67 @@
1
+ import {
2
+ Dispatch,
3
+ HTMLProps,
4
+ MutableRefObject,
5
+ ReactElement,
6
+ ReactNode,
7
+ SetStateAction,
8
+ } from "react";
9
+
10
+ export interface Option<TValue = string> {
11
+ label: string;
12
+ value: TValue;
13
+ disabled?: boolean;
14
+ }
15
+
16
+ export type ClassName = string | undefined;
17
+
18
+ export type ClickEvent = React.MouseEvent<HTMLButtonElement, MouseEvent>;
19
+
20
+ export type ControllableState<T> = {
21
+ value?: T;
22
+ defaultValue?: T;
23
+ onChange?: (state: T) => void;
24
+ };
25
+
26
+ export type Controllable<C, T extends NonNullable<unknown>> = OverrideProps<
27
+ HTMLProps<C>,
28
+ ControllableState<T>
29
+ >;
30
+
31
+ export type MaybeRef<T> = T | MutableRefObject<T>;
32
+
33
+ export type ArrayUnion<V, T extends ReadonlyArray<V>> = T[number];
34
+
35
+ export type ValuesUnion<T extends Record<string, any>> = T[keyof T];
36
+
37
+ export type GenericObject<T = any> = { [key: string]: T };
38
+
39
+ export type Nullable<T> = T | null;
40
+
41
+ export type Maybe<T> = T | undefined | null;
42
+
43
+ export type SetState<T> = Dispatch<SetStateAction<T>>;
44
+
45
+ export type State<T> = [T, SetState<T>];
46
+
47
+ export type ID = string | number;
48
+
49
+ export type OverrideProps<T, TOverridden> = Omit<T, keyof TOverridden> &
50
+ TOverridden;
51
+
52
+ export type SafeOmit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
53
+
54
+ export type AtLeastOne<T> = [T, ...T[]];
55
+
56
+ export type Loose<T> = T | (string & {});
57
+
58
+ export type Renderable<T> = ReactNode | ((props: T) => ReactElement);
59
+
60
+ export type BaseEntity = {
61
+ id: string;
62
+ createdAt: Date;
63
+ };
64
+
65
+ export type Entity<T> = {
66
+ [K in keyof T]: T[K];
67
+ } & BaseEntity;
@@ -0,0 +1 @@
1
+ export * from "./Generic.model";
@@ -0,0 +1,2 @@
1
+ export * from "./library-provider";
2
+ export * from "./theme";
@@ -0,0 +1,44 @@
1
+ import { Tooltip as TooltipBase } from "@base-ui/react/tooltip";
2
+ import type { ComponentPropsWithoutRef, ReactNode } from "react";
3
+ import {
4
+ ToastProvider,
5
+ type ToastProviderProps,
6
+ } from "../components/toast/toast";
7
+ import { TooltipProvider } from "../components/tooltip/tooltip";
8
+
9
+ export type LibraryProviderProps = {
10
+ children: ReactNode;
11
+ /**
12
+ * Delay in ms before a tooltip opens when no other tooltip is already visible.
13
+ * Once a tooltip is open, subsequent ones open instantly until the cursor leaves.
14
+ * @default 600
15
+ */
16
+ tooltipDelay?: ComponentPropsWithoutRef<typeof TooltipBase.Provider>["delay"];
17
+ } & Omit<ToastProviderProps, "children">;
18
+
19
+ /**
20
+ * Single provider that wires up all library infrastructure.
21
+ * Wrap your app once — no other providers needed.
22
+ *
23
+ * Includes:
24
+ * - `TooltipProvider` — shared hover intent and delay grouping across all tooltips
25
+ * - `ToastProvider` — enables `toast.*` imperative API from anywhere
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * <LibraryProvider tooltipDelay={400}>
30
+ * <App />
31
+ * </LibraryProvider>
32
+ * ```
33
+ */
34
+ export function LibraryProvider({
35
+ children,
36
+ tooltipDelay,
37
+ ...toastProps
38
+ }: LibraryProviderProps) {
39
+ return (
40
+ <TooltipProvider delay={tooltipDelay}>
41
+ <ToastProvider {...toastProps}>{children}</ToastProvider>
42
+ </TooltipProvider>
43
+ );
44
+ }
@@ -0,0 +1,25 @@
1
+ import { createContext, ReactNode, useContext } from "react";
2
+ import { Theme } from "./types";
3
+
4
+ const defaultTheme: Theme = {};
5
+
6
+ const ThemeContext = createContext<{ theme: Theme }>({ theme: defaultTheme });
7
+
8
+ export const useTheme = () => {
9
+ const context = useContext(ThemeContext);
10
+ return context;
11
+ };
12
+
13
+ type ThemeProviderProps = {
14
+ children: ReactNode;
15
+ theme?: Theme;
16
+ };
17
+
18
+ export const ThemeProvider = ({
19
+ children,
20
+ theme = defaultTheme,
21
+ }: ThemeProviderProps) => {
22
+ return (
23
+ <ThemeContext.Provider value={{ theme }}>{children}</ThemeContext.Provider>
24
+ );
25
+ };
@@ -0,0 +1,3 @@
1
+ export * from "./ThemeProvider";
2
+ export * from "./types";
3
+ export * from "./useThemeProps";
@@ -0,0 +1,11 @@
1
+ import { ComponentProps } from "react";
2
+ import { Button } from "../../components/button/button";
3
+ import { Input } from "../../components/input/input";
4
+
5
+ type ThemeProps<T, TOverridden> = Partial<Omit<T, keyof TOverridden>>;
6
+ type PropsWithoutValue<T> = Omit<T, "value" | "onChange" | "defaultValue">;
7
+
8
+ export type Theme = {
9
+ Button?: ThemeProps<ComponentProps<typeof Button>, "asChild" | "loading">;
10
+ Input?: Partial<PropsWithoutValue<ComponentProps<typeof Input>>>;
11
+ };
@@ -0,0 +1,25 @@
1
+ import { useTheme } from "../../providers/theme/ThemeProvider";
2
+ import { Theme } from "../../providers/theme/types";
3
+
4
+ /**
5
+ * Hook que permite obtener y combinar las propiedades de un componente con las del tema.
6
+ *
7
+ * El orden de prioridad de las propiedades es:
8
+ * 1. Props pasadas directamente al componente
9
+ * 2. Props definidas en el ThemeProvider
10
+ * 3. Props por defecto del componente
11
+ */
12
+ export const useThemeProps = <TComponent extends keyof Theme, TProps>(
13
+ componentName: TComponent,
14
+ props: TProps,
15
+ defaultProps: Partial<TProps> = {},
16
+ ): TProps => {
17
+ const { theme } = useTheme();
18
+ const themeProps = theme[componentName] || {};
19
+
20
+ return {
21
+ ...defaultProps,
22
+ ...themeProps,
23
+ ...props,
24
+ } as TProps;
25
+ };
@@ -0,0 +1,31 @@
1
+ import { createStore, type StoreApi } from "zustand";
2
+ import { Theme } from "../providers/theme/types";
3
+
4
+ interface ThemeStore {
5
+ theme: Theme;
6
+ setTheme: (theme: Theme) => void;
7
+ getComponentProps: <TComponent extends keyof Theme, TProps>(
8
+ componentName: TComponent,
9
+ props: TProps,
10
+ defaultProps?: Partial<TProps>,
11
+ ) => TProps;
12
+ }
13
+
14
+ export type ThemeStoreApi = StoreApi<ThemeStore>;
15
+
16
+ const createThemeStore = (initTheme: Theme = {}) => {
17
+ return createStore<ThemeStore>()((set, get) => ({
18
+ theme: initTheme,
19
+ setTheme: (theme) => set({ theme }),
20
+ getComponentProps: (componentName, props, defaultProps = {}) => {
21
+ const themeProps = get().theme[componentName] || {};
22
+ return {
23
+ ...defaultProps,
24
+ ...themeProps,
25
+ ...props,
26
+ };
27
+ },
28
+ }));
29
+ };
30
+
31
+ export { createThemeStore };
@@ -0,0 +1,4 @@
1
+ @import "tailwindcss/utilities";
2
+ @import "tw-animate-css";
3
+ @import "./theme.css";
4
+ @source "../";
@@ -0,0 +1,2 @@
1
+ @import "tailwindcss";
2
+ @import "./theme.css";
@@ -0,0 +1,2 @@
1
+ @import "./theme.css";
2
+ @source "../src";
@@ -0,0 +1,232 @@
1
+ @import "tw-animate-css";
2
+ @custom-variant open (&[data-state="open"]);
3
+ @custom-variant closed (&[data-state="closed"]);
4
+ @custom-variant invalid (&[aria-invalid="true"]);
5
+
6
+ @theme {
7
+ --color-background: oklch(100% 0 0);
8
+ --color-foreground: oklch(13.63% 0.036 259.2);
9
+
10
+ --color-popover: oklch(100% 0 0);
11
+ --color-popover-foreground: oklch(13.63% 0.036 259.2);
12
+
13
+ --color-primary: oklch(59.5% 0.195 270.48);
14
+ --color-primary-foreground: oklch(100% 0 0);
15
+
16
+ --color-secondary: oklch(96.83% 0.007 247.9);
17
+ --color-secondary-foreground: oklch(20.77% 0.04 265.75);
18
+
19
+ --color-muted: oklch(96.83% 0.007 247.9);
20
+ --color-muted-foreground: oklch(55.44% 0.041 257.42);
21
+
22
+ --color-accent: oklch(96.74% 0.001 286.38);
23
+ --color-accent-foreground: oklch(19.06% 0.003 247.96);
24
+
25
+ --color-error: oklch(63.68% 0.208 25.33);
26
+ --color-error-foreground: oklch(98.42% 0.003 247.86);
27
+
28
+ --color-success: oklch(70.1% 0.146 156.33);
29
+ --color-success-foreground: oklch(98.42% 0.003 247.86);
30
+
31
+ --color-warning: oklch(79.65% 0.16 70.08);
32
+ --color-warning-foreground: oklch(17.97% 0.034 59.63);
33
+
34
+ --color-info: oklch(62.8% 0.152 237.57);
35
+ --color-info-foreground: oklch(98.42% 0.003 247.86);
36
+
37
+ --animate-toast-bump: toast-bump 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
38
+ --animate-skeleton: skeleton 1.5s linear infinite;
39
+
40
+ --color-input: oklch(76.68% 0 0);
41
+ --color-checkbox: var(--color-primary);
42
+ --color-ring: oklch(13.63% 0.036 259.2);
43
+
44
+ --radius: 0.5rem;
45
+ --radius-sm: calc(var(--radius) - 4px);
46
+ --radius-md: calc(var(--radius) - 2px);
47
+ --radius-lg: calc(var(--radius));
48
+ --radius-xl: calc(var(--radius) + 4px);
49
+ --radius-tag: 0.375rem;
50
+ --radius-checkbox: 0.25rem;
51
+
52
+ --icon-size: 1rem;
53
+
54
+ --z-overlay: 50;
55
+ --z-float: 60;
56
+ --z-toast: 70;
57
+ }
58
+ /* Tooltip enter animation — @starting-style is more reliable than data-[starting-style]
59
+ because it guarantees the browser paints the initial state before the transition fires,
60
+ avoiding the "no animation" issue caused by lost repaint frames. */
61
+ @starting-style {
62
+ [data-slot="tooltip-popup"] {
63
+ scale: 0.98;
64
+ opacity: 0;
65
+ }
66
+ }
67
+
68
+ @layer base {
69
+ #root {
70
+ isolation: isolate;
71
+ }
72
+
73
+ body {
74
+ background-color: var(--color-background);
75
+ color: var(--color-foreground);
76
+ }
77
+ * {
78
+ box-sizing: border-box;
79
+ margin: 0;
80
+ padding: 0;
81
+ }
82
+ *,
83
+ ::after,
84
+ ::before,
85
+ ::backdrop,
86
+ ::file-selector-button {
87
+ border-color: var(--color-gray-200, currentColor);
88
+ }
89
+
90
+ input:disabled,
91
+ button:disabled,
92
+ textarea:disabled,
93
+ select:disabled,
94
+ [data-disabled="true"] {
95
+ pointer-events: none;
96
+ opacity: 0.5;
97
+ }
98
+ button:not(:disabled),
99
+ [role="button"]:not(:disabled) {
100
+ cursor: pointer;
101
+ }
102
+
103
+ .field-error {
104
+ border-color: var(--color-error);
105
+ }
106
+
107
+ .lucide {
108
+ width: var(--icon-size);
109
+ height: var(--icon-size);
110
+ }
111
+
112
+ @keyframes pulse {
113
+ 0%,
114
+ 100% {
115
+ opacity: 1;
116
+ }
117
+ 50% {
118
+ opacity: 0.9;
119
+ }
120
+ }
121
+
122
+ @keyframes fadeIn {
123
+ from {
124
+ opacity: 0;
125
+ }
126
+ to {
127
+ opacity: 1;
128
+ }
129
+ }
130
+
131
+ /* Btn loader */
132
+ .btn-loader-enter,
133
+ .btn-loader-exit {
134
+ overflow: hidden;
135
+ }
136
+
137
+ .btn-loader-enter {
138
+ width: 0;
139
+ opacity: 0;
140
+ }
141
+
142
+ .btn-loader-enter-active {
143
+ width: var(--icon-size);
144
+ opacity: 1;
145
+ transition:
146
+ width 0.3s ease,
147
+ opacity 0.3s ease;
148
+ }
149
+
150
+ .btn-loader-exit {
151
+ width: var(--icon-size);
152
+ opacity: 1;
153
+ }
154
+
155
+ .btn-loader-exit-active {
156
+ width: 0;
157
+ opacity: 0;
158
+ transition:
159
+ width 0.15s ease,
160
+ opacity 0.25s ease;
161
+ }
162
+
163
+ /* Fade */
164
+ .fade-enter {
165
+ opacity: 0;
166
+ transform: scale(0.8);
167
+ }
168
+
169
+ .fade-enter-active {
170
+ opacity: 1;
171
+ transform: scale(1);
172
+ transition:
173
+ opacity 0.1s ease,
174
+ transform 0.1s ease;
175
+ }
176
+
177
+ .fade-exit {
178
+ opacity: 1;
179
+ transform: scale(1);
180
+ }
181
+
182
+ .fade-exit-active {
183
+ opacity: 0;
184
+ transform: scale(0.8);
185
+ transition:
186
+ opacity 0.2s ease,
187
+ transform 0.2s ease;
188
+ }
189
+
190
+ @keyframes skeleton {
191
+ to {
192
+ background-position: -200% 0;
193
+ }
194
+ }
195
+
196
+ @keyframes toast-bump {
197
+ 0%,
198
+ 100% {
199
+ transform: scale(1);
200
+ }
201
+ 40% {
202
+ transform: scale(1.03);
203
+ }
204
+ }
205
+
206
+ .numberInput {
207
+ /* Chrome, Safari, Edge, Opera */
208
+ &::-webkit-outer-spin-button,
209
+ &::-webkit-inner-spin-button {
210
+ -webkit-appearance: none;
211
+ margin: -1;
212
+ }
213
+
214
+ /* Firefox */
215
+ &[type="number"] {
216
+ -moz-appearance: textfield;
217
+ }
218
+ }
219
+
220
+ .space-y-6 > :not([hidden]) ~ :not([hidden]) {
221
+ margin-top: 1.5rem;
222
+ }
223
+ .space-y-4 > :not([hidden]) ~ :not([hidden]) {
224
+ margin-top: 1rem;
225
+ }
226
+ .space-y-2 > :not([hidden]) ~ :not([hidden]) {
227
+ margin-top: 0.5rem;
228
+ }
229
+ .space-y-1 > :not([hidden]) ~ :not([hidden]) {
230
+ margin-top: 0.275rem;
231
+ }
232
+ }
@@ -0,0 +1,39 @@
1
+ import { isDate, parse } from "date-fns";
2
+ import { DateRange } from "../../components";
3
+
4
+ /**
5
+ * @typedef {Object} DateRange
6
+ * @property {Date} start - The start date of the range.
7
+ * @property {Date} end - The end date of the range.
8
+ */
9
+
10
+ /**
11
+ * Parses a date range string in the format "DD/MM/YYYY - DD/MM/YYYY" and returns an object with start and end dates.
12
+ *
13
+ * @param {string} dateRange - The date range string to parse.
14
+ * @returns {DateRange} An object containing the start and end dates.
15
+ * @throws Will throw an error if the input string is not in the expected format or the dates are invalid.
16
+ */
17
+ export const parseDateRange = (dateRange: string): DateRange => {
18
+ if (typeof dateRange !== "string") {
19
+ throw new Error("The date range must be a string.");
20
+ }
21
+
22
+ const parts = dateRange.split(" - ");
23
+ if (parts.length !== 2) {
24
+ throw new Error('The date range format must be "DD/MM/YYYY - DD/MM/YYYY".');
25
+ }
26
+
27
+ const [startDateString, endDateString] = parts;
28
+
29
+ const dateFormat = "dd/MM/yyyy";
30
+
31
+ const start = parse(startDateString, dateFormat, new Date());
32
+ const end = parse(endDateString, dateFormat, new Date());
33
+
34
+ if (!isDate(start) || !isDate(end)) {
35
+ throw new Error("One or both of the dates are invalid.");
36
+ }
37
+
38
+ return { start, end };
39
+ };
@@ -0,0 +1,91 @@
1
+ // @ts-nocheck
2
+ // biome-ignore-all lint: utility wrappers require flexible typings
3
+ import { zodResolver } from "@hookform/resolvers/zod";
4
+ import type { ComponentProps, ReactNode } from "react";
5
+ import {
6
+ type ControllerRenderProps,
7
+ type FieldValues,
8
+ FormProvider,
9
+ type Path,
10
+ type RegisterOptions,
11
+ useForm as rhfUseForm,
12
+ type SubmitHandler,
13
+ type UseFormProps,
14
+ type UseFormReturn,
15
+ useController,
16
+ } from "react-hook-form";
17
+ import type { z } from "zod";
18
+
19
+ import { Field, type FieldProps } from "../components/field";
20
+ import { Form as LibraryForm } from "../components/form";
21
+
22
+ // ── useForm ───────────────────────────────────────────────────────────────────
23
+
24
+ export function useForm<T extends FieldValues = FieldValues>(
25
+ schema: z.ZodType<T>,
26
+ options?: Partial<UseFormProps<T>>,
27
+ ): UseFormReturn<T> {
28
+ return rhfUseForm<T>({
29
+ ...options,
30
+ resolver: zodResolver(schema),
31
+ });
32
+ }
33
+
34
+ // ── Form ──────────────────────────────────────────────────────────────────────
35
+
36
+ type FormProps<T extends FieldValues> = {
37
+ form: UseFormReturn<T>;
38
+ onSubmit: SubmitHandler<T>;
39
+ children: ReactNode;
40
+ } & Omit<ComponentProps<typeof LibraryForm>, "onSubmit" | "onFormSubmit">;
41
+
42
+ export function Form<T extends FieldValues>({
43
+ form,
44
+ onSubmit,
45
+ children,
46
+ ...props
47
+ }: FormProps<T>) {
48
+ return (
49
+ <FormProvider {...form}>
50
+ <LibraryForm
51
+ onFormSubmit={(event) => {
52
+ form.handleSubmit(onSubmit)(event);
53
+ }}
54
+ {...props}
55
+ >
56
+ {children}
57
+ </LibraryForm>
58
+ </FormProvider>
59
+ );
60
+ }
61
+
62
+ // ── FormField ─────────────────────────────────────────────────────────────────
63
+
64
+ export type FormFieldRenderProps<
65
+ T extends FieldValues = FieldValues,
66
+ TName extends Path<T> = Path<T>,
67
+ > = ControllerRenderProps<T, TName> & {
68
+ invalid: boolean;
69
+ };
70
+
71
+ type FormFieldProps<
72
+ T extends FieldValues = FieldValues,
73
+ TName extends Path<T> = Path<T>,
74
+ > = Omit<FieldProps, "children" | "error"> & {
75
+ name: TName;
76
+ rules?: RegisterOptions;
77
+ render: (field: FormFieldRenderProps<T, TName>) => ReactNode;
78
+ };
79
+
80
+ export function FormField<
81
+ T extends FieldValues = FieldValues,
82
+ TName extends Path<T> = Path<T>,
83
+ >({ name, rules, render, ...fieldProps }: FormFieldProps<T, TName>) {
84
+ const { field, fieldState } = useController<T, TName>({ name, rules });
85
+
86
+ return (
87
+ <Field {...fieldProps} error={fieldState.error?.message}>
88
+ {render({ ...field, invalid: fieldState.invalid })}
89
+ </Field>
90
+ );
91
+ }