@boxcustodia/library 2.0.0-alpha.10 → 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 (352) hide show
  1. package/dist/index.cjs.js +70 -70
  2. package/dist/index.css +2 -0
  3. package/dist/index.d.ts +420 -272
  4. package/dist/index.es.js +34448 -27816
  5. package/dist/theme.css +1 -1
  6. package/package.json +11 -6
  7. package/src/__doc__/Changelog.mdx +6 -0
  8. package/src/__doc__/Components.mdx +73 -0
  9. package/src/__doc__/Examples.tsx +69 -0
  10. package/src/__doc__/Icons.mdx +41 -0
  11. package/src/__doc__/Intro.mdx +138 -0
  12. package/src/__doc__/MCP.mdx +71 -0
  13. package/src/__doc__/Migration.mdx +475 -0
  14. package/src/__doc__/Theme.mdx +132 -0
  15. package/src/__doc__/Types.mdx +252 -0
  16. package/src/components/alert/alert.stories.tsx +142 -0
  17. package/src/components/alert/alert.tsx +109 -0
  18. package/src/components/alert/index.ts +7 -0
  19. package/src/components/alert-dialog/alert-dialog.stories.tsx +173 -0
  20. package/src/components/alert-dialog/alert-dialog.test.tsx +49 -0
  21. package/src/components/alert-dialog/alert-dialog.tsx +265 -0
  22. package/src/components/alert-dialog/index.ts +1 -0
  23. package/src/components/auto-complete/auto-complete-primitives.tsx +155 -0
  24. package/src/components/auto-complete/auto-complete.stories.tsx +241 -0
  25. package/src/components/auto-complete/auto-complete.tsx +82 -0
  26. package/src/components/auto-complete/index.ts +2 -0
  27. package/src/components/avatar/avatar.stories.tsx +84 -0
  28. package/src/components/avatar/avatar.test.tsx +61 -0
  29. package/src/components/avatar/avatar.tsx +104 -0
  30. package/src/components/avatar/index.ts +1 -0
  31. package/src/components/background-image/background-image.stories.tsx +21 -0
  32. package/src/components/background-image/background-image.test.tsx +29 -0
  33. package/src/components/background-image/background-image.tsx +23 -0
  34. package/src/components/background-image/index.ts +1 -0
  35. package/src/components/button/button.stories.tsx +396 -0
  36. package/src/components/button/button.test.tsx +58 -0
  37. package/src/components/button/button.tsx +31 -0
  38. package/src/components/button/button.variants.ts +44 -0
  39. package/src/components/button/components/base-button.tsx +86 -0
  40. package/src/components/button/components/loader-overlay.tsx +21 -0
  41. package/src/components/button/components/loading-icon.tsx +47 -0
  42. package/src/components/button/index.ts +3 -0
  43. package/src/components/calendar/calendar.model.ts +86 -0
  44. package/src/components/calendar/calendar.stories.tsx +155 -0
  45. package/src/components/calendar/calendar.test.tsx +12 -0
  46. package/src/components/calendar/calendar.tsx +185 -0
  47. package/src/components/calendar/components/calendar-navigation.tsx +141 -0
  48. package/src/components/calendar/components/day.tsx +61 -0
  49. package/src/components/calendar/components/decade-view.tsx +45 -0
  50. package/src/components/calendar/components/index.ts +6 -0
  51. package/src/components/calendar/components/month-view.tsx +58 -0
  52. package/src/components/calendar/components/week-days.tsx +27 -0
  53. package/src/components/calendar/components/year-view.tsx +29 -0
  54. package/src/components/calendar/hooks/index.ts +4 -0
  55. package/src/components/calendar/hooks/use-calendar-navigation.ts +79 -0
  56. package/src/components/calendar/hooks/use-calendar.ts +90 -0
  57. package/src/components/calendar/hooks/use-multiple-calendar.ts +34 -0
  58. package/src/components/calendar/hooks/use-range-calendar.ts +91 -0
  59. package/src/components/calendar/hooks/use-single-calendar.ts +18 -0
  60. package/src/components/calendar/index.ts +1 -0
  61. package/src/components/calendar/utils/typeguards.ts +7 -0
  62. package/src/components/card/card.stories.tsx +116 -0
  63. package/src/components/card/card.tsx +74 -0
  64. package/src/components/card/index.ts +1 -0
  65. package/src/components/center/center.stories.tsx +81 -0
  66. package/src/components/center/center.tsx +24 -0
  67. package/src/components/center/index.ts +1 -0
  68. package/src/components/checkbox/checkbox.stories.tsx +307 -0
  69. package/src/components/checkbox/checkbox.tsx +273 -0
  70. package/src/components/checkbox/index.ts +1 -0
  71. package/src/components/checkbox-group/checkbox-group.stories.tsx +104 -0
  72. package/src/components/checkbox-group/checkbox-group.tsx +16 -0
  73. package/src/components/checkbox-group/index.ts +1 -0
  74. package/src/components/combobox/combobox.stories.tsx +339 -0
  75. package/src/components/combobox/combobox.tsx +892 -0
  76. package/src/components/combobox/index.ts +1 -0
  77. package/src/components/date-picker/date-input.stories.tsx +158 -0
  78. package/src/components/date-picker/date-input.tsx +163 -0
  79. package/src/components/date-picker/date-picker.model.ts +90 -0
  80. package/src/components/date-picker/date-picker.stories.tsx +200 -0
  81. package/src/components/date-picker/date-picker.test.tsx +23 -0
  82. package/src/components/date-picker/date-picker.tsx +298 -0
  83. package/src/components/date-picker/date-picker.utils.ts +260 -0
  84. package/src/components/date-picker/index.ts +3 -0
  85. package/src/components/date-picker/use-date-input-popover.ts +48 -0
  86. package/src/components/date-picker/use-date-input.ts +125 -0
  87. package/src/components/dialog/dialog.stories.tsx +171 -0
  88. package/src/components/dialog/dialog.test.tsx +68 -0
  89. package/src/components/dialog/dialog.tsx +277 -0
  90. package/src/components/dialog/index.ts +1 -0
  91. package/src/components/divider/divider.stories.tsx +70 -0
  92. package/src/components/divider/divider.test.tsx +22 -0
  93. package/src/components/divider/divider.tsx +23 -0
  94. package/src/components/divider/index.ts +1 -0
  95. package/src/components/dropzone/dropzone.stories.tsx +210 -0
  96. package/src/components/dropzone/dropzone.tsx +154 -0
  97. package/src/components/dropzone/file-types.ts +64 -0
  98. package/src/components/dropzone/index.ts +3 -0
  99. package/src/components/dropzone/upload-primitives.tsx +310 -0
  100. package/src/components/dropzone/use-dropzone.ts +122 -0
  101. package/src/components/empty-state/empty-state.stories.tsx +56 -0
  102. package/src/components/empty-state/empty-state.tsx +39 -0
  103. package/src/components/empty-state/index.ts +1 -0
  104. package/src/components/field/field.stories.tsx +223 -0
  105. package/src/components/field/field.tsx +229 -0
  106. package/src/components/field/index.ts +1 -0
  107. package/src/components/form/form.stories.tsx +594 -0
  108. package/src/components/form/form.tsx +30 -0
  109. package/src/components/form/index.ts +1 -0
  110. package/src/components/heading/heading.stories.tsx +74 -0
  111. package/src/components/heading/heading.tsx +28 -0
  112. package/src/components/heading/heading.variants.ts +27 -0
  113. package/src/components/heading/index.ts +1 -0
  114. package/src/components/index.ts +46 -0
  115. package/src/components/input/index.ts +1 -0
  116. package/src/components/input/input.stories.tsx +104 -0
  117. package/src/components/input/input.tsx +75 -0
  118. package/src/components/kbd/index.ts +1 -0
  119. package/src/components/kbd/kbd.stories.tsx +40 -0
  120. package/src/components/kbd/kbd.tsx +31 -0
  121. package/src/components/kbd/kbd.variants.ts +26 -0
  122. package/src/components/label/index.ts +1 -0
  123. package/src/components/label/label.stories.tsx +68 -0
  124. package/src/components/label/label.test.tsx +61 -0
  125. package/src/components/label/label.tsx +62 -0
  126. package/src/components/loader/index.ts +1 -0
  127. package/src/components/loader/loader.stories.tsx +60 -0
  128. package/src/components/loader/loader.test.tsx +26 -0
  129. package/src/components/loader/loader.tsx +60 -0
  130. package/src/components/menu/index.ts +2 -0
  131. package/src/components/menu/menu-primitives.tsx +248 -0
  132. package/src/components/menu/menu.stories.tsx +203 -0
  133. package/src/components/menu/menu.tsx +100 -0
  134. package/src/components/menu/util/render-menu-item.tsx +54 -0
  135. package/src/components/multi-select/hooks/use-multi-select.ts +66 -0
  136. package/src/components/multi-select/index.ts +1 -0
  137. package/src/components/multi-select/multi-select.stories.tsx +294 -0
  138. package/src/components/multi-select/multi-select.tsx +300 -0
  139. package/src/components/multi-select/multi-select.variants.ts +22 -0
  140. package/src/components/number-input/index.ts +1 -0
  141. package/src/components/number-input/number-input.stories.tsx +209 -0
  142. package/src/components/number-input/number-input.test.tsx +87 -0
  143. package/src/components/number-input/number-input.tsx +230 -0
  144. package/src/components/pagination/components/pagination-option.tsx +27 -0
  145. package/src/components/pagination/index.ts +1 -0
  146. package/src/components/pagination/pagination.stories.tsx +80 -0
  147. package/src/components/pagination/pagination.test.tsx +76 -0
  148. package/src/components/pagination/pagination.tsx +102 -0
  149. package/src/components/password/index.ts +1 -0
  150. package/src/components/password/password.stories.tsx +104 -0
  151. package/src/components/password/password.tsx +71 -0
  152. package/src/components/popover/index.ts +1 -0
  153. package/src/components/popover/popover.stories.tsx +213 -0
  154. package/src/components/popover/popover.tsx +203 -0
  155. package/src/components/progress/index.ts +1 -0
  156. package/src/components/progress/progress.stories.tsx +124 -0
  157. package/src/components/progress/progress.test.tsx +25 -0
  158. package/src/components/progress/progress.tsx +124 -0
  159. package/src/components/scroll-area/index.ts +1 -0
  160. package/src/components/scroll-area/scroll-area.stories.tsx +166 -0
  161. package/src/components/scroll-area/scroll-area.tsx +64 -0
  162. package/src/components/select/index.ts +1 -0
  163. package/src/components/select/select.stories.tsx +253 -0
  164. package/src/components/select/select.tsx +430 -0
  165. package/src/components/show/index.ts +1 -0
  166. package/src/components/show/show.stories.tsx +197 -0
  167. package/src/components/show/show.test.tsx +41 -0
  168. package/src/components/show/show.tsx +16 -0
  169. package/src/components/skeleton/index.ts +1 -0
  170. package/src/components/skeleton/skeleton.stories.tsx +36 -0
  171. package/src/components/skeleton/skeleton.test.tsx +14 -0
  172. package/src/components/skeleton/skeleton.tsx +15 -0
  173. package/src/components/stack/index.ts +1 -0
  174. package/src/components/stack/stack.stories.tsx +194 -0
  175. package/src/components/stack/stack.tsx +52 -0
  176. package/src/components/stepper/Stepper.tsx +190 -0
  177. package/src/components/stepper/context/stepper-context.tsx +11 -0
  178. package/src/components/stepper/index.ts +1 -0
  179. package/src/components/stepper/stepper.stories.tsx +130 -0
  180. package/src/components/stepper/stepper.test.tsx +91 -0
  181. package/src/components/switch/index.ts +1 -0
  182. package/src/components/switch/switch.stories.tsx +122 -0
  183. package/src/components/switch/switch.test.tsx +30 -0
  184. package/src/components/switch/switch.tsx +86 -0
  185. package/src/components/table/index.ts +3 -0
  186. package/src/components/table/table-primitives.tsx +122 -0
  187. package/src/components/table/table.model.ts +20 -0
  188. package/src/components/table/table.stories.tsx +169 -0
  189. package/src/components/table/table.test.tsx +91 -0
  190. package/src/components/table/table.tsx +109 -0
  191. package/src/components/table-pagination/index.ts +2 -0
  192. package/src/components/table-pagination/table-pagination.model.ts +2 -0
  193. package/src/components/table-pagination/table-pagination.stories.tsx +23 -0
  194. package/src/components/table-pagination/table-pagination.test.tsx +32 -0
  195. package/src/components/table-pagination/table-pagination.tsx +108 -0
  196. package/src/components/tabs/context/tabs-context.tsx +14 -0
  197. package/src/components/tabs/index.ts +1 -0
  198. package/src/components/tabs/tabs.stories.tsx +182 -0
  199. package/src/components/tabs/tabs.test.tsx +61 -0
  200. package/src/components/tabs/tabs.tsx +175 -0
  201. package/src/components/tag/index.ts +2 -0
  202. package/src/components/tag/tag.stories.tsx +170 -0
  203. package/src/components/tag/tag.test.tsx +18 -0
  204. package/src/components/tag/tag.tsx +99 -0
  205. package/src/components/tag/tag.variants.ts +31 -0
  206. package/src/components/textarea/index.ts +1 -0
  207. package/src/components/textarea/textarea.stories.tsx +73 -0
  208. package/src/components/textarea/textarea.tsx +105 -0
  209. package/src/components/timeline/index.ts +1 -0
  210. package/src/components/timeline/timeline-status.ts +5 -0
  211. package/src/components/timeline/timeline.stories.tsx +84 -0
  212. package/src/components/timeline/timeline.tsx +147 -0
  213. package/src/components/toast/index.ts +1 -0
  214. package/src/components/toast/toast.stories.tsx +392 -0
  215. package/src/components/toast/toast.test.tsx +50 -0
  216. package/src/components/toast/toast.tsx +411 -0
  217. package/src/components/tooltip/index.ts +1 -0
  218. package/src/components/tooltip/tooltip.stories.tsx +226 -0
  219. package/src/components/tooltip/tooltip.test.tsx +46 -0
  220. package/src/components/tooltip/tooltip.tsx +171 -0
  221. package/src/components/tree/hooks/use-controllable-tree-state.ts +80 -0
  222. package/src/components/tree/index.ts +2 -0
  223. package/src/components/tree/tree-primitives.tsx +126 -0
  224. package/src/components/tree/tree.stories.tsx +468 -0
  225. package/src/components/tree/tree.tsx +42 -0
  226. package/src/hooks/index.ts +26 -0
  227. package/src/hooks/useArray/__doc__/useArray.stories.tsx +100 -0
  228. package/src/hooks/useArray/__test__/useArray.test.tsx +88 -0
  229. package/src/hooks/useArray/index.ts +1 -0
  230. package/src/hooks/useArray/useArray.ts +76 -0
  231. package/src/hooks/useAsync/__doc__/useAsync.stories.tsx +149 -0
  232. package/src/hooks/useAsync/__test__/useAsync.test.tsx +68 -0
  233. package/src/hooks/useAsync/index.ts +1 -0
  234. package/src/hooks/useAsync/useAsync.ts +58 -0
  235. package/src/hooks/useClickOutside/__doc__/useClickOutside.stories.tsx +40 -0
  236. package/src/hooks/useClickOutside/__test__/useClickOutside.test.tsx +33 -0
  237. package/src/hooks/useClickOutside/index.ts +1 -0
  238. package/src/hooks/useClickOutside/useClickOutside.ts +26 -0
  239. package/src/hooks/useClipboard/__doc__/useClipboard.stories.tsx +45 -0
  240. package/src/hooks/useClipboard/__test__/useClipboard.test.tsx +19 -0
  241. package/src/hooks/useClipboard/index.ts +1 -0
  242. package/src/hooks/useClipboard/useClipboard.tsx +28 -0
  243. package/src/hooks/useDebounceCallback/__doc__/useDebouncedCallback.stories.tsx +84 -0
  244. package/src/hooks/useDebounceCallback/index.ts +1 -0
  245. package/src/hooks/useDebounceCallback/useDebouncedCallback.ts +23 -0
  246. package/src/hooks/useDebounceValue/__doc__/useDebouncedValue.stories.tsx +75 -0
  247. package/src/hooks/useDebounceValue/index.ts +1 -0
  248. package/src/hooks/useDebounceValue/useDebouncedValue.ts +17 -0
  249. package/src/hooks/useDisclosure/__doc__/useDisclosure.stories.tsx +39 -0
  250. package/src/hooks/useDisclosure/__test__/useDisclosure.test.ts +43 -0
  251. package/src/hooks/useDisclosure/index.ts +1 -0
  252. package/src/hooks/useDisclosure/useDisclosure.ts +37 -0
  253. package/src/hooks/useDocumentTitle/__doc__/useDocumentTitle.stories.tsx +26 -0
  254. package/src/hooks/useDocumentTitle/index.ts +1 -0
  255. package/src/hooks/useDocumentTitle/useDocumentTitle.tsx +11 -0
  256. package/src/hooks/useEventListener/__doc__/useEventListener.stories.tsx +28 -0
  257. package/src/hooks/useEventListener/__test__/useEventListener.test.tsx +26 -0
  258. package/src/hooks/useEventListener/index.ts +1 -0
  259. package/src/hooks/useEventListener/useEventListener.ts +25 -0
  260. package/src/hooks/useFocusTrap/__doc__/useFocusTrap.stories.tsx +37 -0
  261. package/src/hooks/useFocusTrap/index.ts +1 -0
  262. package/src/hooks/useFocusTrap/scopeTab.ts +38 -0
  263. package/src/hooks/useFocusTrap/tabbable.ts +70 -0
  264. package/src/hooks/useFocusTrap/useFocusTrap.ts +78 -0
  265. package/src/hooks/useHotkey/__docs__/useHotkey.stories.tsx +116 -0
  266. package/src/hooks/useHotkey/__test__/useHotkey.test.tsx +105 -0
  267. package/src/hooks/useHotkey/__utils__/create-hotkey-listener.ts +25 -0
  268. package/src/hooks/useHotkey/__utils__/index.ts +3 -0
  269. package/src/hooks/useHotkey/__utils__/is-input-field.ts +14 -0
  270. package/src/hooks/useHotkey/__utils__/match-key-modifiers.ts +25 -0
  271. package/src/hooks/useHotkey/index.ts +1 -0
  272. package/src/hooks/useHotkey/useHotkey.ts +34 -0
  273. package/src/hooks/useHover/__doc__/useHover.stories.tsx +41 -0
  274. package/src/hooks/useHover/__test__/useHover.test.tsx +45 -0
  275. package/src/hooks/useHover/index.ts +1 -0
  276. package/src/hooks/useHover/useHover.tsx +40 -0
  277. package/src/hooks/useIsVisible/__doc__/useIsVisible.stories.tsx +60 -0
  278. package/src/hooks/useIsVisible/index.ts +1 -0
  279. package/src/hooks/useIsVisible/useIsVisible.tsx +50 -0
  280. package/src/hooks/useLocalStorage/__doc__/useLocalStorage.stories.tsx +86 -0
  281. package/src/hooks/useLocalStorage/__test__/useLocalStorage.test.ts +85 -0
  282. package/src/hooks/useLocalStorage/index.ts +1 -0
  283. package/src/hooks/useLocalStorage/useLocalStorage.ts +57 -0
  284. package/src/hooks/useMediaQuery/__doc__/useMediaQuery.stories.tsx +39 -0
  285. package/src/hooks/useMediaQuery/index.ts +1 -0
  286. package/src/hooks/useMediaQuery/useMediaQuery.ts +22 -0
  287. package/src/hooks/useMemoizedFn/index.ts +1 -0
  288. package/src/hooks/useMemoizedFn/useMemoizedFn.ts +32 -0
  289. package/src/hooks/useMutation/__doc__/useMutation.stories.tsx +111 -0
  290. package/src/hooks/useMutation/__test__/useMutation.test.tsx +83 -0
  291. package/src/hooks/useMutation/index.ts +1 -0
  292. package/src/hooks/useMutation/useMutation.tsx +60 -0
  293. package/src/hooks/useObject/__doc__/useObject.stories.tsx +119 -0
  294. package/src/hooks/useObject/__test__/useObject.test.tsx +87 -0
  295. package/src/hooks/useObject/index.ts +1 -0
  296. package/src/hooks/useObject/useObject.tsx +48 -0
  297. package/src/hooks/usePagination/__doc__/usePagination.stories.tsx +72 -0
  298. package/src/hooks/usePagination/__test__/usePagination.test.tsx +98 -0
  299. package/src/hooks/usePagination/index.ts +2 -0
  300. package/src/hooks/usePagination/usePagination.tsx +74 -0
  301. package/src/hooks/usePortal/__doc__/usePortal.stories.tsx +19 -0
  302. package/src/hooks/usePortal/__test__/usePortal.test.tsx +20 -0
  303. package/src/hooks/usePortal/index.ts +1 -0
  304. package/src/hooks/usePortal/usePortal.ts +40 -0
  305. package/src/hooks/usePreventCloseWindow/__doc__/usePreventCloseWindow.stories.tsx +32 -0
  306. package/src/hooks/usePreventCloseWindow/index.ts +1 -0
  307. package/src/hooks/usePreventCloseWindow/usePreventCloseWindow.ts +33 -0
  308. package/src/hooks/useRangePagination/__test__/useRangePagination.test.tsx +63 -0
  309. package/src/hooks/useRangePagination/index.ts +2 -0
  310. package/src/hooks/useRangePagination/useRangePagination.tsx +72 -0
  311. package/src/hooks/useSelection/__doc__/useSelection.stories.tsx +140 -0
  312. package/src/hooks/useSelection/__test__/useSelection.test.tsx +57 -0
  313. package/src/hooks/useSelection/index.ts +1 -0
  314. package/src/hooks/useSelection/useSelection.ts +121 -0
  315. package/src/hooks/useStep/__doc__/useStep.stories.tsx +98 -0
  316. package/src/hooks/useStep/__test__/useStep.test.ts +51 -0
  317. package/src/hooks/useStep/index.ts +1 -0
  318. package/src/hooks/useStep/useStep.ts +57 -0
  319. package/src/hooks/useToggle/__doc__/useToggle.stories.tsx +25 -0
  320. package/src/hooks/useToggle/__test__/useToggle.test.tsx +43 -0
  321. package/src/hooks/useToggle/index.ts +1 -0
  322. package/src/hooks/useToggle/useToggle.ts +16 -0
  323. package/src/index.ts +6 -0
  324. package/src/lib/cn.ts +8 -0
  325. package/src/lib/index.ts +1 -0
  326. package/src/models/Generic.model.ts +67 -0
  327. package/src/models/index.ts +1 -0
  328. package/src/providers/index.ts +2 -0
  329. package/src/providers/library-provider.tsx +44 -0
  330. package/src/providers/theme/ThemeProvider.tsx +25 -0
  331. package/src/providers/theme/index.ts +3 -0
  332. package/src/providers/theme/types.ts +11 -0
  333. package/src/providers/theme/useThemeProps.ts +25 -0
  334. package/src/stores/theme.store.ts +31 -0
  335. package/src/styles/components.css +4 -0
  336. package/src/styles/index.css +2 -0
  337. package/src/styles/library.css +2 -0
  338. package/src/styles/theme.css +232 -0
  339. package/src/utils/dates/parseDateRange.utility.ts +39 -0
  340. package/src/utils/form.tsx +91 -0
  341. package/src/utils/functions/createSafeContext.ts +17 -0
  342. package/src/utils/functions/ensureReactElement.tsx +30 -0
  343. package/src/utils/functions/getFormData.ts +19 -0
  344. package/src/utils/functions/index.ts +4 -0
  345. package/src/utils/functions/mergeRefs.ts +18 -0
  346. package/src/utils/index.ts +3 -0
  347. package/src/utils/strings/extractInitials.utility.ts +10 -0
  348. package/src/utils/strings/index.ts +1 -0
  349. package/src/utils/tests/click.ts +3 -0
  350. package/src/utils/tests/index.ts +2 -0
  351. package/src/utils/tests/keyboard.ts +21 -0
  352. package/src/utils/tests/type.ts +6 -0
@@ -0,0 +1,241 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import {
3
+ Archive,
4
+ Calendar,
5
+ FlameKindling,
6
+ Github,
7
+ Mail,
8
+ Settings,
9
+ Slack,
10
+ TicketPercent,
11
+ User,
12
+ UserPlus,
13
+ } from "lucide-react";
14
+ import React, { useState } from "react";
15
+ import {
16
+ AutoComplete,
17
+ AutoCompleteDialog,
18
+ AutoCompleteEmpty,
19
+ AutoCompleteGroup,
20
+ AutoCompleteInput,
21
+ AutoCompleteItem,
22
+ AutoCompleteList,
23
+ AutoCompleteRoot,
24
+ AutoCompleteSeparator,
25
+ AutoCompleteShortcut,
26
+ Button,
27
+ MenuContent,
28
+ MenuGroup,
29
+ MenuRoot,
30
+ MenuSub,
31
+ MenuSubContent,
32
+ MenuSubTrigger,
33
+ MenuTrigger,
34
+ Popover,
35
+ } from "../../components";
36
+ import { useHotkey } from "../../hooks";
37
+
38
+ const meta: Meta<typeof AutoComplete> = {
39
+ title: "Data entry/AutoComplete",
40
+ component: AutoComplete,
41
+ };
42
+
43
+ export default meta;
44
+ type Story = StoryObj<typeof AutoComplete>;
45
+
46
+ const items = [
47
+ { value: "apple", label: "Apple" },
48
+ { value: "banana", label: "Banana" },
49
+ { value: "cherry", label: "Cherry" },
50
+ ];
51
+
52
+ export const Default: Story = {
53
+ args: {
54
+ items: items,
55
+ onSelect: console.log,
56
+ placeholder: "Search fruits",
57
+ },
58
+ };
59
+
60
+ /**
61
+ * Componente primitive AutoComplete que permite construir un campo de búsqueda con sugerencias.
62
+ * Filtra y ordena los elementos de una lista de sugerencias.
63
+ * ## Estructura
64
+ * ```tsx
65
+ * <AutocompleteRoot>
66
+ * <AutocompleteInput placeholder="Buscar..." />
67
+ * <AutocompleteList>
68
+ * <AutocompleteEmpty>No Se Encontraron Resultados</AutocompleteEmpty>
69
+ * <AutocompleteGroup>
70
+ * <AutocompleteItem>Calendario</AutocompleteItem>
71
+ * <AutocompleteItem>Eventos</AutocompleteItem>
72
+ * <AutocompleteItem>Archivados</AutocompleteItem>
73
+ * </AutocompleteGroup>
74
+ * </AutocompleteList>
75
+ * </AutocompleteRoot>
76
+ * ```
77
+ * */
78
+ export const Primitive: Story = {
79
+ render: () => {
80
+ return (
81
+ <AutoCompleteRoot className="border border-input">
82
+ <AutoCompleteInput placeholder="Buscar..." />
83
+ <AutoCompleteList>
84
+ <AutoCompleteEmpty>No se encontraron resultados</AutoCompleteEmpty>
85
+ <AutoCompleteGroup>
86
+ <AutoCompleteItem>Calendario</AutoCompleteItem>
87
+ <AutoCompleteItem>Eventos</AutoCompleteItem>
88
+ <AutoCompleteItem>Archivados</AutoCompleteItem>
89
+ </AutoCompleteGroup>
90
+ <AutoCompleteSeparator />
91
+ </AutoCompleteList>
92
+ </AutoCompleteRoot>
93
+ );
94
+ },
95
+ };
96
+
97
+ export const Dialog: Story = {
98
+ render: () => {
99
+ const [open, setOpen] = React.useState(false);
100
+ useHotkey("shift+/", () => setOpen((open) => !open), {
101
+ ignoreInputFields: false,
102
+ });
103
+
104
+ return (
105
+ <>
106
+ <p className="text-sm flex items-center gap-x-2">
107
+ Presiona
108
+ <kbd className="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100">
109
+ /
110
+ </kbd>
111
+ para abrir el diálogo de comandos.
112
+ </p>
113
+ <AutoCompleteDialog open={open} onOpenChange={setOpen}>
114
+ <AutoCompleteInput placeholder="Busca una vista o escribe un comando..." />
115
+ <AutoCompleteList>
116
+ <AutoCompleteEmpty>No se encontraron resultados</AutoCompleteEmpty>
117
+ <AutoCompleteGroup heading="Sugerencias">
118
+ <AutoCompleteItem onSelect={(value) => console.log(value)}>
119
+ <Calendar />
120
+ <span>Calendario</span>
121
+ </AutoCompleteItem>
122
+ <AutoCompleteItem>
123
+ <TicketPercent />
124
+ <span>Eventos</span>
125
+ </AutoCompleteItem>
126
+ <AutoCompleteItem>
127
+ <Archive />
128
+ <span>Archivados</span>
129
+ </AutoCompleteItem>
130
+ </AutoCompleteGroup>
131
+ <AutoCompleteSeparator />
132
+ <AutoCompleteGroup heading="Configuraciones">
133
+ <AutoCompleteItem>
134
+ <User />
135
+ <span>Mi perfil</span>
136
+ <AutoCompleteShortcut>P</AutoCompleteShortcut>
137
+ </AutoCompleteItem>
138
+ <AutoCompleteItem>
139
+ <Settings />
140
+ <span>Configuración</span>
141
+ <AutoCompleteShortcut>C</AutoCompleteShortcut>
142
+ </AutoCompleteItem>
143
+ </AutoCompleteGroup>
144
+ </AutoCompleteList>
145
+ </AutoCompleteDialog>
146
+ </>
147
+ );
148
+ },
149
+ };
150
+
151
+ export const SearchableMenu = {
152
+ name: "Menu",
153
+ render: () => {
154
+ const [open, setOpen] = useState(false);
155
+
156
+ return (
157
+ <MenuRoot open={open} onOpenChange={setOpen}>
158
+ <MenuTrigger asChild>
159
+ <Button variant="outline">Open</Button>
160
+ </MenuTrigger>
161
+ <MenuContent className="w-56">
162
+ <MenuSub>
163
+ <MenuSubTrigger>
164
+ <UserPlus className="mr-2 h-4 w-4" />
165
+ Añadir usuario
166
+ </MenuSubTrigger>
167
+ <MenuGroup>
168
+ <MenuSubContent>
169
+ <AutoCompleteRoot>
170
+ <AutoCompleteInput placeholder="Buscar..." autoFocus={true} />
171
+ <AutoCompleteList>
172
+ <AutoCompleteEmpty>No hay resultados</AutoCompleteEmpty>
173
+ <AutoCompleteGroup heading="Medio de notificación">
174
+ <AutoCompleteItem>
175
+ <Mail />
176
+ Correo electrónico
177
+ </AutoCompleteItem>
178
+ <AutoCompleteItem>
179
+ <Slack />
180
+ Slack
181
+ </AutoCompleteItem>
182
+ <AutoCompleteItem>
183
+ <Github />
184
+ Github
185
+ </AutoCompleteItem>
186
+ <AutoCompleteItem>
187
+ <FlameKindling />
188
+ Señal de humo
189
+ </AutoCompleteItem>
190
+ </AutoCompleteGroup>
191
+ </AutoCompleteList>
192
+ </AutoCompleteRoot>
193
+ </MenuSubContent>
194
+ </MenuGroup>
195
+ </MenuSub>
196
+ </MenuContent>
197
+ </MenuRoot>
198
+ );
199
+ },
200
+ };
201
+
202
+ export const SearchablePopover = {
203
+ name: "Popover",
204
+ render: () => {
205
+ return (
206
+ <Popover
207
+ trigger={
208
+ <Button>
209
+ <UserPlus className="mr-2 h-4 w-4" />
210
+ Añadir usuario
211
+ </Button>
212
+ }
213
+ >
214
+ <AutoCompleteRoot>
215
+ <AutoCompleteInput placeholder="Buscar..." autoFocus={true} />
216
+ <AutoCompleteList>
217
+ <AutoCompleteEmpty>No hay resultados</AutoCompleteEmpty>
218
+ <AutoCompleteGroup heading="Medio de notificación">
219
+ <AutoCompleteItem>
220
+ <Mail />
221
+ Correo electrónico
222
+ </AutoCompleteItem>
223
+ <AutoCompleteItem>
224
+ <Slack />
225
+ Slack
226
+ </AutoCompleteItem>
227
+ <AutoCompleteItem>
228
+ <Github />
229
+ Github
230
+ </AutoCompleteItem>
231
+ <AutoCompleteItem>
232
+ <FlameKindling />
233
+ Señal de humo
234
+ </AutoCompleteItem>
235
+ </AutoCompleteGroup>
236
+ </AutoCompleteList>
237
+ </AutoCompleteRoot>
238
+ </Popover>
239
+ );
240
+ },
241
+ };
@@ -0,0 +1,82 @@
1
+ import { ComponentProps } from "react";
2
+ import { ClassName } from "@/models";
3
+ import {
4
+ AutoCompleteEmpty,
5
+ AutoCompleteInput,
6
+ AutoCompleteItem,
7
+ AutoCompleteList,
8
+ AutoCompleteRoot,
9
+ AutoCompleteShortcut,
10
+ } from "../../components";
11
+
12
+ interface AutoCompleteItem {
13
+ value: string;
14
+ label: string;
15
+ shortcut?: string;
16
+ }
17
+
18
+ interface ExtendedProps {
19
+ containerClassName: ClassName;
20
+ inputClassName: ClassName;
21
+ listClassName: ClassName;
22
+ itemClassName: ClassName;
23
+ emptyClassName: ClassName;
24
+ containerProps: ComponentProps<typeof AutoCompleteRoot>;
25
+ inputProps: ComponentProps<typeof AutoCompleteInput>;
26
+ listProps: ComponentProps<typeof AutoCompleteList>;
27
+ itemProps: ComponentProps<typeof AutoCompleteItem>;
28
+ emptyProps: ComponentProps<typeof AutoCompleteEmpty>;
29
+ }
30
+
31
+ interface Props extends ExtendedProps {
32
+ items: AutoCompleteItem[];
33
+ placeholder?: string;
34
+ emptyMessage?: string;
35
+ onSelect?: (value: AutoCompleteItem["value"], item: AutoCompleteItem) => any;
36
+ }
37
+
38
+ export const AutoComplete = ({
39
+ items,
40
+ placeholder = "Buscar...",
41
+ emptyMessage = "No se encontraron resultados",
42
+ onSelect,
43
+ containerClassName,
44
+ containerProps,
45
+ inputClassName,
46
+ inputProps,
47
+ listClassName,
48
+ listProps,
49
+ itemClassName,
50
+ itemProps,
51
+ emptyClassName,
52
+ emptyProps,
53
+ }: Props) => {
54
+ return (
55
+ <AutoCompleteRoot className={containerClassName} {...containerProps}>
56
+ <AutoCompleteInput
57
+ placeholder={placeholder}
58
+ className={inputClassName}
59
+ {...inputProps}
60
+ />
61
+ <AutoCompleteList className={listClassName} {...listProps}>
62
+ {(items as AutoCompleteItem[]).map((item) => (
63
+ <AutoCompleteItem
64
+ className={itemClassName}
65
+ key={item.value}
66
+ onSelect={() => onSelect?.(item.value, item)}
67
+ {...itemProps}
68
+ >
69
+ {item.label}
70
+ {item.shortcut && (
71
+ <AutoCompleteShortcut>{item.shortcut}</AutoCompleteShortcut>
72
+ )}
73
+ </AutoCompleteItem>
74
+ ))}
75
+ </AutoCompleteList>
76
+
77
+ <AutoCompleteEmpty className={emptyClassName} {...emptyProps}>
78
+ {emptyMessage}
79
+ </AutoCompleteEmpty>
80
+ </AutoCompleteRoot>
81
+ );
82
+ };
@@ -0,0 +1,2 @@
1
+ export * from "./auto-complete";
2
+ export * from "./auto-complete-primitives";
@@ -0,0 +1,84 @@
1
+ import { faker } from "@faker-js/faker";
2
+ import type { Meta, StoryObj } from "@storybook/react-vite";
3
+ import { User } from "lucide-react";
4
+ import { action } from "storybook/actions";
5
+ import {
6
+ Avatar,
7
+ AvatarFallback,
8
+ AvatarImage,
9
+ AvatarRoot,
10
+ } from "../../components";
11
+
12
+ /**
13
+ * Displays a user's profile image with automatic fallback to text initials derived from `alt`.
14
+ * Built on Base UI Avatar — image loading and fallback visibility are handled natively.
15
+ * Use `delay` to defer the fallback appearance and avoid a flash during image load.
16
+ * Exposes `AvatarRoot`, `AvatarImage`, `AvatarFallback` primitives for custom compositions.
17
+ */
18
+ const meta: Meta<typeof Avatar> = {
19
+ title: "components/Avatar",
20
+ component: Avatar,
21
+ args: {
22
+ alt: faker.person.fullName(),
23
+ src: faker.image.avatar(),
24
+ delay: 1000,
25
+ },
26
+ } satisfies Meta<typeof Avatar>;
27
+
28
+ export default meta;
29
+ type Story = StoryObj<typeof meta>;
30
+
31
+ export const Default: Story = {};
32
+
33
+ /**
34
+ * When `src` is empty or the image fails to load, initials are extracted from `alt` automatically.
35
+ */
36
+ export const FallbackText: Story = {
37
+ args: {
38
+ src: "",
39
+ },
40
+ };
41
+
42
+ export const CustomFallback: Story = {
43
+ args: {
44
+ src: "",
45
+ fallback: <User />,
46
+ },
47
+ };
48
+
49
+ export const Sizes: Story = {
50
+ render: (args) => (
51
+ <div className="flex items-center gap-4">
52
+ <Avatar {...args} size="xs" />
53
+ <Avatar {...args} size="sm" />
54
+ <Avatar {...args} size="md" />
55
+ <Avatar {...args} size="lg" />
56
+ <Avatar {...args} size="xl" />
57
+ </div>
58
+ ),
59
+ };
60
+
61
+ export const Shapes: Story = {
62
+ render: (args) => (
63
+ <div className="flex items-center gap-4">
64
+ <Avatar {...args} shape="circle" />
65
+ <Avatar {...args} shape="square" />
66
+ </div>
67
+ ),
68
+ };
69
+
70
+ export const Primitive: Story = {
71
+ render: () => (
72
+ <AvatarRoot shape="square" size="lg">
73
+ <AvatarImage src={faker.image.avatar()} alt="John Doe" />
74
+ <AvatarFallback delay={1000}>JD</AvatarFallback>
75
+ </AvatarRoot>
76
+ ),
77
+ };
78
+
79
+ export const Clickable: Story = {
80
+ args: {
81
+ onClick: action("avatar:click"),
82
+ className: "cursor-pointer",
83
+ },
84
+ };
@@ -0,0 +1,61 @@
1
+ import { render, screen } from "@testing-library/react";
2
+ import { describe, expect, it } from "vitest";
3
+ import { Avatar } from "../../components";
4
+ import { extractInitials } from "../../utils";
5
+
6
+ describe("Avatar component", () => {
7
+ const personName = "lorem ipsum";
8
+ const imageSrc = "https://i.pravatar.cc/300";
9
+
10
+ it("renders correctly", () => {
11
+ render(<Avatar alt={personName} src={imageSrc} />);
12
+ const image = screen.getByRole("img");
13
+
14
+ expect(image).toBeInTheDocument();
15
+ expect(image).toHaveAttribute("alt", personName);
16
+ expect(image).toHaveAttribute("src", imageSrc);
17
+ });
18
+
19
+ it("renders correctly without src", () => {
20
+ render(<Avatar alt={personName} src="" />);
21
+ const nameInitials = extractInitials(personName);
22
+
23
+ const image = screen.queryByRole("img");
24
+ const fallbackText = screen.getByText(nameInitials);
25
+
26
+ expect(image).not.toBeInTheDocument();
27
+ expect(fallbackText).toBeInTheDocument();
28
+ });
29
+
30
+ it("renders correctly with onError", () => {
31
+ render(<Avatar alt={personName} src="" />);
32
+
33
+ const nameInitials = extractInitials(personName);
34
+ const image = screen.queryByRole("img");
35
+ const fallbackText = screen.getByText(nameInitials);
36
+
37
+ expect(image).not.toBeInTheDocument();
38
+ expect(fallbackText).toBeInTheDocument();
39
+ });
40
+
41
+ it("renders correctly with imageProps", () => {
42
+ const testClassName = "test-class";
43
+ render(
44
+ <Avatar
45
+ alt={personName}
46
+ src={imageSrc}
47
+ imageProps={{ className: testClassName }}
48
+ />,
49
+ );
50
+
51
+ const image = screen.getByRole("img");
52
+ expect(image).toHaveClass(testClassName);
53
+ });
54
+
55
+ it("renders correctly with size variants", () => {
56
+ render(<Avatar alt={personName} src={imageSrc} size="sm" />);
57
+ const avatar = screen.getByRole("img").parentElement;
58
+
59
+ expect(avatar).toHaveClass("w-8 h-8");
60
+ });
61
+ });
@@ -0,0 +1,104 @@
1
+ import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+ import { type ReactNode } from "react";
4
+ import { cn } from "../../lib";
5
+ import { extractInitials } from "../../utils";
6
+
7
+ const avatarVariants = cva(
8
+ "overflow-hidden aspect-square bg-muted grid place-items-center font-semibold shrink-0 select-none",
9
+ {
10
+ variants: {
11
+ shape: {
12
+ circle: "rounded-full",
13
+ square: "rounded-xl",
14
+ },
15
+ size: {
16
+ xs: "size-6 text-[10px]",
17
+ sm: "size-8 text-xs",
18
+ md: "size-10 text-sm",
19
+ lg: "size-14 text-base",
20
+ xl: "size-20 text-xl",
21
+ },
22
+ },
23
+ defaultVariants: {
24
+ shape: "circle",
25
+ size: "md",
26
+ },
27
+ },
28
+ );
29
+
30
+ export function AvatarRoot({
31
+ className,
32
+ shape,
33
+ size,
34
+ ...props
35
+ }: AvatarPrimitive.Root.Props & VariantProps<typeof avatarVariants>) {
36
+ return (
37
+ <AvatarPrimitive.Root
38
+ className={cn(avatarVariants({ shape, size }), className)}
39
+ data-slot="avatar"
40
+ {...props}
41
+ />
42
+ );
43
+ }
44
+
45
+ export function AvatarImage({
46
+ className,
47
+ ...props
48
+ }: AvatarPrimitive.Image.Props) {
49
+ return (
50
+ <AvatarPrimitive.Image
51
+ className={cn("size-full object-cover", className)}
52
+ data-slot="avatar-image"
53
+ {...props}
54
+ />
55
+ );
56
+ }
57
+
58
+ export function AvatarFallback({
59
+ className,
60
+ ...props
61
+ }: AvatarPrimitive.Fallback.Props) {
62
+ return (
63
+ <AvatarPrimitive.Fallback
64
+ className={cn("flex size-full items-center justify-center", className)}
65
+ data-slot="avatar-fallback"
66
+ {...props}
67
+ />
68
+ );
69
+ }
70
+
71
+ interface AvatarProps extends Omit<AvatarPrimitive.Root.Props, "children"> {
72
+ src?: string;
73
+ alt: string;
74
+ fallback?: ReactNode;
75
+ delay?: AvatarPrimitive.Fallback.Props["delay"];
76
+ shape?: VariantProps<typeof avatarVariants>["shape"];
77
+ size?: VariantProps<typeof avatarVariants>["size"];
78
+ imageProps?: AvatarPrimitive.Image.Props;
79
+ fallbackProps?: AvatarPrimitive.Fallback.Props;
80
+ }
81
+
82
+ export function Avatar({
83
+ src,
84
+ alt,
85
+ fallback,
86
+ delay,
87
+ shape,
88
+ size,
89
+ className,
90
+ imageProps,
91
+ fallbackProps,
92
+ ...props
93
+ }: AvatarProps) {
94
+ return (
95
+ <AvatarRoot shape={shape} size={size} className={className} {...props}>
96
+ <AvatarImage src={src} alt={alt} {...imageProps} />
97
+ <AvatarFallback delay={delay} {...fallbackProps}>
98
+ {fallback ?? extractInitials(alt)}
99
+ </AvatarFallback>
100
+ </AvatarRoot>
101
+ );
102
+ }
103
+
104
+ export { AvatarPrimitive };
@@ -0,0 +1 @@
1
+ export * from "./avatar";
@@ -0,0 +1,21 @@
1
+ import { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { BackgroundImage } from "../../components";
3
+
4
+ /**
5
+ * Componente que facilita el manejo de imágenes de fondo.
6
+ */
7
+ const meta: Meta<typeof BackgroundImage> = {
8
+ title: "Others/BackgroundImage",
9
+ component: BackgroundImage,
10
+ args: {
11
+ src: "https://m.media-amazon.com/images/I/81PgpygKwdL._AC_UF894,1000_QL80_.jpg",
12
+ children:
13
+ "Lorem Ipsum es simplemente el texto de relleno de las imprentas y archivos de texto. Lorem Ipsum ha sido el texto de relleno estándar de las industrias desde el año 1500, cuando un impresor (N. del T. persona que se dedica a la imprenta)",
14
+ className: "text-white w-[400px] h-[200px] rounded p-4",
15
+ },
16
+ };
17
+
18
+ export default meta;
19
+ type Story = StoryObj<typeof meta>;
20
+
21
+ export const Default: Story = {};
@@ -0,0 +1,29 @@
1
+ import { render, screen } from "@testing-library/react";
2
+ import { describe, expect, it } from "vitest";
3
+ import { BackgroundImage } from ".";
4
+
5
+ describe("BackgroundImage component", () => {
6
+ const imageSrc = "https://source.unsplash.com/random";
7
+
8
+ it("should render the background image", () => {
9
+ render(<BackgroundImage src={imageSrc} data-testid="container" />);
10
+ const container = screen.getByTestId("container");
11
+
12
+ expect(container).toBeInTheDocument();
13
+ expect(container).toHaveStyle({
14
+ backgroundImage: `url(${imageSrc})`,
15
+ });
16
+ });
17
+
18
+ it("should render the children", () => {
19
+ const text = "Lorem Ipsum";
20
+ render(
21
+ <BackgroundImage src={imageSrc}>
22
+ <p>{text}</p>
23
+ </BackgroundImage>,
24
+ );
25
+ const paragraph = screen.getByText(text);
26
+
27
+ expect(paragraph).toBeInTheDocument();
28
+ });
29
+ });
@@ -0,0 +1,23 @@
1
+ import { HTMLProps } from "react";
2
+ import { cn } from "../../lib";
3
+
4
+ interface Props extends HTMLProps<HTMLDivElement> {
5
+ /**
6
+ * La URL de la imagen
7
+ */
8
+ src: string;
9
+ }
10
+
11
+ export const BackgroundImage = ({ src, ...props }: Props) => {
12
+ return (
13
+ <div
14
+ {...props}
15
+ data-slot="background-image"
16
+ className={cn("w-full block bg-cover bg-center", props.className)}
17
+ style={{
18
+ ...props.style,
19
+ backgroundImage: `url(${src})`,
20
+ }}
21
+ />
22
+ );
23
+ };
@@ -0,0 +1 @@
1
+ export * from "./background-image";