@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,58 @@
1
+ import {
2
+ eachDayOfInterval,
3
+ endOfMonth,
4
+ endOfWeek,
5
+ startOfWeek,
6
+ } from "date-fns";
7
+ import { useMemo } from "react";
8
+ import { ClassName } from "@/models";
9
+ import { Day, DayProps } from "./day";
10
+ import { WeekDays, WeekDaysProps } from "./week-days";
11
+
12
+ type MonthViewProps = {
13
+ navigationDate: Date;
14
+ disabled?: (date: Date) => boolean;
15
+ dayClassName?: ClassName;
16
+ dayProps?: DayProps;
17
+ weekDaysClassName?: ClassName;
18
+ weekDaysProps?: WeekDaysProps;
19
+ };
20
+
21
+ const MonthView = ({
22
+ navigationDate,
23
+ disabled,
24
+ weekDaysClassName,
25
+ weekDaysProps,
26
+ dayClassName,
27
+ dayProps,
28
+ }: MonthViewProps) => {
29
+ const getMonthInterval = (): Date[] =>
30
+ eachDayOfInterval({
31
+ start: startOfWeek(navigationDate, { weekStartsOn: 1 }),
32
+ end: endOfWeek(endOfMonth(navigationDate), { weekStartsOn: 1 }),
33
+ });
34
+ const days = useMemo(getMonthInterval, [navigationDate]);
35
+
36
+ return (
37
+ <>
38
+ <WeekDays className={weekDaysClassName} {...weekDaysProps} />
39
+ <div
40
+ className="grid grid-cols-7 mt-2 text-sm"
41
+ data-slot="calendar-month-view"
42
+ >
43
+ {days.map((day: Date, index: number) => (
44
+ <Day
45
+ key={index}
46
+ day={day}
47
+ className={dayClassName}
48
+ {...dayProps}
49
+ navigationDate={navigationDate}
50
+ disabled={disabled?.(day)}
51
+ />
52
+ ))}
53
+ </div>
54
+ </>
55
+ );
56
+ };
57
+
58
+ export { MonthView, type MonthViewProps };
@@ -0,0 +1,27 @@
1
+ import { at } from "lodash";
2
+ import { HTMLProps } from "react";
3
+ import { cn } from "../../../lib";
4
+ import { weeksDays } from "../calendar.model";
5
+
6
+ type WeekDaysProps = HTMLProps<HTMLDivElement>;
7
+
8
+ const WeekDays = (props: WeekDaysProps) => {
9
+ return (
10
+ <div
11
+ {...props}
12
+ className={cn(
13
+ "grid grid-cols-7 font-semibold mt-2 text-xs leading-6 text-center py-1 bg-blue-bell/40 select-none",
14
+ props.className,
15
+ )}
16
+ data-slot="calendar-week-days"
17
+ >
18
+ {weeksDays.map((day: string) => (
19
+ <abbr key={day} aria-label={day} data-slot="calendar-week-day">
20
+ {at(day, 0)}
21
+ </abbr>
22
+ ))}
23
+ </div>
24
+ );
25
+ };
26
+
27
+ export { WeekDays, type WeekDaysProps };
@@ -0,0 +1,29 @@
1
+ import { format, setMonth } from "date-fns";
2
+ import { Button } from "../../../components";
3
+ import { monthNames, ViewProps } from "../calendar.model";
4
+
5
+ const YearView = ({ value, onChange }: ViewProps) => {
6
+ const selectMonth = (month: number): void => {
7
+ const newDate = setMonth(value, month);
8
+ onChange(newDate);
9
+ };
10
+
11
+ return (
12
+ <div className="grid grid-cols-3 grow" data-slot="calendar-year-view">
13
+ {monthNames.map((month) => (
14
+ <Button
15
+ type="button"
16
+ className="h-full rounded"
17
+ onClick={() => selectMonth(monthNames.indexOf(month))}
18
+ key={month}
19
+ variant="ghost"
20
+ data-slot="calendar-year-view-month"
21
+ >
22
+ <abbr aria-label={`${month} ${format(value, "yyyy")}`}>{month}</abbr>
23
+ </Button>
24
+ ))}
25
+ </div>
26
+ );
27
+ };
28
+
29
+ export { YearView, type ViewProps as YearViewProps };
@@ -0,0 +1,4 @@
1
+ export { default as useCalendar } from "./use-calendar";
2
+ export { default as useCalendarNavigation } from "./use-calendar-navigation";
3
+ export { default as useRangeCalendar } from "./use-range-calendar";
4
+ export { default as useSingleCalendar } from "./use-single-calendar";
@@ -0,0 +1,79 @@
1
+ import { addMonths, addYears, format, parse, startOfToday } from "date-fns";
2
+ import { useMemo, useState } from "react";
3
+ import { DateSingle } from "../calendar.model";
4
+
5
+ function useCalendarNavigation(value: DateSingle = startOfToday()) {
6
+ const [date, setDate] = useState({
7
+ month: format(value || startOfToday(), "MM"),
8
+ year: format(value || startOfToday(), "yyyy"),
9
+ });
10
+
11
+ const navigationDate: Date = useMemo(
12
+ () => parse(`${date.month}-${date.year}`, "MM-yyyy", new Date()),
13
+ [date],
14
+ );
15
+
16
+ const setMonth = (newDate: Date): void => {
17
+ setDate({
18
+ ...date,
19
+ month: format(newDate, "MM"),
20
+ });
21
+ };
22
+
23
+ const setYear = (newDate: Date): void => {
24
+ setDate({
25
+ ...date,
26
+ year: format(newDate, "yyyy"),
27
+ });
28
+ };
29
+
30
+ const previousMonth = (): void => {
31
+ const previousMonthDate = addMonths(navigationDate, -1);
32
+ setDate({
33
+ month: format(previousMonthDate, "MM"),
34
+ year: format(previousMonthDate, "yyyy"),
35
+ });
36
+ };
37
+
38
+ const nextMonth = (): void => {
39
+ const nextMonthDate = addMonths(navigationDate, 1);
40
+ setDate({
41
+ month: format(nextMonthDate, "MM"),
42
+ year: format(nextMonthDate, "yyyy"),
43
+ });
44
+ };
45
+
46
+ const previousYear = (): void => {
47
+ const firstDayPreviousYear = addYears(navigationDate, -1);
48
+ setYear(firstDayPreviousYear);
49
+ };
50
+
51
+ const nextYear = (): void => {
52
+ const firstDayNextYear = addYears(navigationDate, 1);
53
+ setYear(firstDayNextYear);
54
+ };
55
+
56
+ const previousDecade = (): void => {
57
+ const firstDayPreviousDecade = addYears(navigationDate, -10);
58
+ setYear(firstDayPreviousDecade);
59
+ };
60
+
61
+ const nextDecade = (): void => {
62
+ const firstDayNextDecade = addYears(navigationDate, 10);
63
+ setYear(firstDayNextDecade);
64
+ };
65
+
66
+ return {
67
+ navigationDate,
68
+ setMonth,
69
+ setYear,
70
+ previousMonth,
71
+ nextMonth,
72
+ previousYear,
73
+ nextYear,
74
+ previousDecade,
75
+ nextDecade,
76
+ };
77
+ }
78
+
79
+ export default useCalendarNavigation;
@@ -0,0 +1,90 @@
1
+ import { useControllableState } from "@radix-ui/react-use-controllable-state";
2
+ import { isDate } from "date-fns";
3
+ import { isArray } from "lodash";
4
+ import { createContext } from "react";
5
+ import {
6
+ CalendarModeProps,
7
+ CalendarState,
8
+ DateMatcher,
9
+ Mode,
10
+ } from "../calendar.model";
11
+ import { isDateRange } from "../utils/typeguards";
12
+ import useMultipleCalendar from "./use-multiple-calendar";
13
+ import useRangeCalendar from "./use-range-calendar";
14
+ import useSingleCalendar from "./use-single-calendar";
15
+
16
+ export const CalendarContext = createContext<CalendarState>({
17
+ defaultStartDate: new Date(),
18
+ mode: "single",
19
+ isSingleMode: false,
20
+ isRangeMode: false,
21
+ selected: null,
22
+ selectDate: () => {},
23
+ isSelected: () => false,
24
+ isFirstDayFromRange: () => false,
25
+ isLastDayFromRange: () => false,
26
+ isInRange: () => false,
27
+ });
28
+
29
+ function useCalendar<T extends Mode>(props: CalendarModeProps<T>) {
30
+ const { mode, value, defaultValue, onChange, disabled } = props;
31
+ const isSingleMode = mode === "single";
32
+ const isRangeMode = mode === "range";
33
+ const isMultipleMode = mode === "multiple";
34
+
35
+ const [selected = null, setSelected] = useControllableState<DateMatcher>({
36
+ prop: value,
37
+ onChange: onChange as any,
38
+ defaultProp: defaultValue as any,
39
+ });
40
+
41
+ const { selectSingleDate, isSingleSelected } = useSingleCalendar(
42
+ isDate(selected) ? selected : undefined,
43
+ setSelected,
44
+ );
45
+
46
+ const { selectRangeDate, isInRange, ...range } = useRangeCalendar(
47
+ isDateRange(selected) ? selected : undefined,
48
+ setSelected,
49
+ disabled,
50
+ );
51
+
52
+ const { selectMultipleDate, isMultipleSelected } = useMultipleCalendar(
53
+ isArray(selected) ? selected : undefined,
54
+ setSelected,
55
+ );
56
+
57
+ const selectDate = (date: Date): void => {
58
+ if (isSingleMode) return selectSingleDate(date);
59
+ if (isRangeMode) return selectRangeDate(date);
60
+ if (isMultipleMode) return selectMultipleDate(date);
61
+ };
62
+
63
+ const isSelected = (day: Date): boolean => {
64
+ if (isSingleMode) return isSingleSelected(day);
65
+ if (isRangeMode) return isInRange(day);
66
+ if (isMultipleMode) return isMultipleSelected(day);
67
+ return false;
68
+ };
69
+
70
+ const getDefaultStartDate = (): Date => {
71
+ if (isDate(selected)) return selected;
72
+ if (isArray(selected)) return selected[0];
73
+ if (isDateRange(selected) && selected.start) return selected.start;
74
+ return new Date();
75
+ };
76
+
77
+ return {
78
+ defaultStartDate: getDefaultStartDate(),
79
+ isSingleMode,
80
+ isRangeMode,
81
+ selected,
82
+ isSelected,
83
+ selectDate,
84
+ isInRange,
85
+ mode,
86
+ ...range,
87
+ };
88
+ }
89
+
90
+ export default useCalendar;
@@ -0,0 +1,34 @@
1
+ import { isSameDay } from "date-fns";
2
+ import { findIndex, isArray } from "lodash";
3
+ import { DateMultiple } from "../calendar.model";
4
+
5
+ function useMultipleCalendar(
6
+ selected: DateMultiple | undefined,
7
+ setSelected: (dates: DateMultiple) => void,
8
+ ) {
9
+ const selectMultipleDate = (date: Date): void => {
10
+ if (!selected) return setSelected([date]);
11
+
12
+ const index = findIndex(selected, (stateDate: Date) =>
13
+ isSameDay(stateDate, date),
14
+ );
15
+
16
+ if (index === -1) return setSelected([...selected, date]);
17
+
18
+ const newSelected = [
19
+ ...selected.slice(0, index),
20
+ ...selected.slice(index + 1),
21
+ ];
22
+ setSelected(newSelected);
23
+ };
24
+
25
+ const isMultipleSelected = (day: Date): boolean =>
26
+ isArray(selected) && selected.some((date: Date) => isSameDay(date, day));
27
+
28
+ return {
29
+ selectMultipleDate,
30
+ isMultipleSelected,
31
+ };
32
+ }
33
+
34
+ export default useMultipleCalendar;
@@ -0,0 +1,91 @@
1
+ import {
2
+ eachDayOfInterval,
3
+ isBefore,
4
+ isSameDay,
5
+ isWithinInterval,
6
+ startOfDay,
7
+ } from "date-fns";
8
+ import { DateRange, DateSingle } from "../calendar.model";
9
+ import { isDateRange } from "../utils/typeguards";
10
+
11
+ function useRangeCalendar(
12
+ selected: DateRange | undefined,
13
+ // FIX: remove any
14
+ setSelected: any,
15
+ disabled?: (date: Date) => boolean,
16
+ ) {
17
+ const selectRangeDate = (date: Date): void => {
18
+ const firstDateSelected = selected?.start;
19
+ if (firstDateSelected) {
20
+ const { start, end } = selected;
21
+ const isEndBeforeStart = isBefore(date, start!);
22
+ const isNewRange = start && end;
23
+
24
+ if (isEndBeforeStart || isNewRange) {
25
+ setSelected({ start: date, end: undefined });
26
+ return;
27
+ }
28
+
29
+ if (hasDisabledDateInRange(start, date)) return;
30
+
31
+ setSelected({
32
+ start,
33
+ end: date,
34
+ });
35
+ } else {
36
+ setSelected({ start: date, end: undefined });
37
+ }
38
+ };
39
+
40
+ const hasDisabledDateInRange = (
41
+ start: DateSingle,
42
+ end: DateSingle,
43
+ ): boolean => {
44
+ if (!disabled) return false;
45
+ if (!start || !end) return false;
46
+ const interval = eachDayOfInterval({ start: startOfDay(start), end: end });
47
+ const hasDisabled = interval.some((date) => disabled(date));
48
+ return hasDisabled;
49
+ };
50
+
51
+ const isInRange = (day: Date): boolean => {
52
+ if (!isDateRange(selected)) return false;
53
+ if (!selected) return false;
54
+
55
+ const { start, end } = selected;
56
+
57
+ const isOnlyStartSelected = start && !end;
58
+ if (isOnlyStartSelected) {
59
+ return isSameDay(day, start);
60
+ }
61
+
62
+ if (!start || !end) return false;
63
+ return isWithinInterval(day, {
64
+ start: startOfDay(start),
65
+ end: startOfDay(end),
66
+ });
67
+ };
68
+
69
+ const isFirstDayFromRange = (day: Date): boolean => {
70
+ if (!selected) return false;
71
+ if (!isDateRange(selected)) return false;
72
+ if (!selected.start) return false;
73
+ return isSameDay(day, selected.start);
74
+ };
75
+
76
+ const isLastDayFromRange = (day: Date): boolean => {
77
+ if (!selected) return false;
78
+ if (!isDateRange(selected)) return false;
79
+ if (!selected.end) return false;
80
+ return isSameDay(day, selected.end);
81
+ };
82
+
83
+ return {
84
+ selectRangeDate,
85
+ isInRange,
86
+ isFirstDayFromRange,
87
+ isLastDayFromRange,
88
+ };
89
+ }
90
+
91
+ export default useRangeCalendar;
@@ -0,0 +1,18 @@
1
+ import { isDate, isSameDay } from "date-fns";
2
+ import { DateSingle } from "../calendar.model";
3
+
4
+ function useSingleCalendar(selected: DateSingle | undefined, setSelected: any) {
5
+ const selectSingleDate = (date: Date): void => {
6
+ setSelected(date);
7
+ };
8
+
9
+ const isSingleSelected = (day: Date): boolean =>
10
+ isDate(selected) && isSameDay(day, selected);
11
+
12
+ return {
13
+ selectSingleDate,
14
+ isSingleSelected,
15
+ };
16
+ }
17
+
18
+ export default useSingleCalendar;
@@ -0,0 +1 @@
1
+ export * from "./calendar";
@@ -0,0 +1,7 @@
1
+ import { DateRange } from "../calendar.model";
2
+
3
+ export function isDateRange(value: unknown): value is DateRange {
4
+ return Boolean(
5
+ value && typeof value === "object" && "start" in value && "end" in value,
6
+ );
7
+ }
@@ -0,0 +1,116 @@
1
+ import { faker } from "@faker-js/faker";
2
+ import { Meta, StoryObj } from "@storybook/react-vite";
3
+ import { ComponentType } from "react";
4
+ import {
5
+ Button,
6
+ Card,
7
+ CardContent,
8
+ CardDescription,
9
+ CardFooter,
10
+ CardHeader,
11
+ CardTitle,
12
+ } from "../../components";
13
+
14
+ /**
15
+ * El componente Card es un contenedor versátil que permite organizar y presentar contenido
16
+ * de manera estructurada y visualmente atractiva.
17
+ *
18
+ * ### Características principales
19
+ * - Diseño modular y flexible
20
+ * - Soporte para encabezados, contenido y pie de página
21
+ * - Personalizable a través de className
22
+ * - Ideal para mostrar información, productos, artículos, etc.
23
+ *
24
+ * ### Estructura básica
25
+ * ```tsx
26
+ * <Card>
27
+ * <CardHeader>
28
+ * <CardTitle>Título del Card</CardTitle>
29
+ * <CardDescription>Descripción opcional</CardDescription>
30
+ * </CardHeader>
31
+ * <CardContent>
32
+ * Contenido principal
33
+ * </CardContent>
34
+ * <CardFooter>
35
+ * Acciones o contenido adicional
36
+ * </CardFooter>
37
+ * </Card>
38
+ * ```
39
+ */
40
+ const meta: Meta<typeof Card> = {
41
+ title: "data display/Card",
42
+ component: Card,
43
+ tags: ["autodocs"],
44
+ subcomponents: {
45
+ CardHeader: CardHeader as ComponentType<unknown>,
46
+ CardTitle: CardTitle as ComponentType<unknown>,
47
+ CardDescription: CardDescription as ComponentType<unknown>,
48
+ CardContent: CardContent as ComponentType<unknown>,
49
+ CardFooter: CardFooter as ComponentType<unknown>,
50
+ },
51
+ };
52
+
53
+ export default meta;
54
+
55
+ type Story = StoryObj<typeof Card>;
56
+
57
+ /**
58
+ * Ejemplo básico de un Card con todos sus componentes.
59
+ * Muestra la estructura típica con encabezado, contenido y pie de página.
60
+ */
61
+ export const Default: Story = {
62
+ render: () => (
63
+ <Card className="w-[350px] shadow-md rounded-lg">
64
+ <CardHeader className="p-4">
65
+ <CardTitle className="text-2xl">
66
+ How to Improve Your Productivity
67
+ </CardTitle>
68
+ <CardDescription className="text-sm">By Jane Doe</CardDescription>
69
+ </CardHeader>
70
+ <CardContent className="p-4">
71
+ <p className="text-gray-700 text-base">
72
+ Discover the best strategies and tools to boost your productivity in
73
+ work and life. Learn how to manage your time effectively and stay
74
+ focused on what really matters.
75
+ </p>
76
+ </CardContent>
77
+ <CardFooter className="px-4 py-3 flex justify-between">
78
+ <Button variant="outline">Read More</Button>
79
+ <Button className="bg-blue-600 text-white">Save</Button>
80
+ </CardFooter>
81
+ </Card>
82
+ ),
83
+ };
84
+
85
+ /**
86
+ * Ejemplo de Card con imagen y diseño de producto.
87
+ * Demuestra cómo integrar elementos multimedia y crear layouts más complejos.
88
+ */
89
+ export const Media: Story = {
90
+ render: () => (
91
+ <Card className="w-[350px] shadow-lg rounded-lg overflow-hidden">
92
+ <img
93
+ src={faker.image.url()}
94
+ alt="Featured Product"
95
+ className="w-full h-[150px] object-cover"
96
+ />
97
+ <CardContent className="p-4">
98
+ <CardTitle className="text-xl font-bold text-gray-900">
99
+ Villa Luxury
100
+ </CardTitle>
101
+ <CardDescription className="text-sm text-gray-600">
102
+ Escapa a esta luxuriosa aldea con vistas maravillosas del océano y
103
+ piscina privada.
104
+ </CardDescription>
105
+ <div className="flex items-center mt-4">
106
+ <span className="text-2xl font-semibold text-gray-900">$750</span>
107
+ <span className="ml-2 text-sm text-gray-500">/ noche</span>
108
+ </div>
109
+ </CardContent>
110
+ <CardFooter className="px-4 py-3 bg-gray-100 flex justify-between">
111
+ <Button variant="outline">Detalle</Button>
112
+ <Button className="bg-blue-600 text-white">Comprar</Button>
113
+ </CardFooter>
114
+ </Card>
115
+ ),
116
+ };
@@ -0,0 +1,74 @@
1
+ import React from "react";
2
+ import { cn } from "../../lib";
3
+
4
+ export const Card = ({
5
+ className,
6
+ ...props
7
+ }: React.HTMLAttributes<HTMLDivElement>) => (
8
+ <div
9
+ className={cn(
10
+ "rounded-lg border bg-card text-card-foreground shadow-sm",
11
+ className,
12
+ )}
13
+ {...props}
14
+ data-slot="card"
15
+ />
16
+ );
17
+
18
+ export const CardHeader = ({
19
+ className,
20
+ ...props
21
+ }: React.HTMLAttributes<HTMLDivElement>) => (
22
+ <div
23
+ className={cn("flex flex-col space-y-1 p-6", className)}
24
+ {...props}
25
+ data-slot="card-header"
26
+ />
27
+ );
28
+
29
+ export const CardTitle = ({
30
+ className,
31
+ ...props
32
+ }: React.HTMLAttributes<HTMLHeadingElement>) => (
33
+ <h3
34
+ className={cn(
35
+ "text-2xl font-semibold leading-none tracking-tight",
36
+ className,
37
+ )}
38
+ {...props}
39
+ data-slot="card-title"
40
+ />
41
+ );
42
+
43
+ export const CardDescription = ({
44
+ className,
45
+ ...props
46
+ }: React.HTMLAttributes<HTMLParagraphElement>) => (
47
+ <p
48
+ className={cn("text-sm text-muted-foreground", className)}
49
+ {...props}
50
+ data-slot="card-description"
51
+ />
52
+ );
53
+
54
+ export const CardContent = ({
55
+ className,
56
+ ...props
57
+ }: React.HTMLAttributes<HTMLDivElement>) => (
58
+ <div
59
+ className={cn("p-6 pt-0", className)}
60
+ {...props}
61
+ data-slot="card-content"
62
+ />
63
+ );
64
+
65
+ export const CardFooter = ({
66
+ className,
67
+ ...props
68
+ }: React.HTMLAttributes<HTMLDivElement>) => (
69
+ <div
70
+ className={cn("flex items-center p-6 pt-0", className)}
71
+ {...props}
72
+ data-slot="card-footer"
73
+ />
74
+ );
@@ -0,0 +1 @@
1
+ export * from "./card";