@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,203 @@
1
+ "use client";
2
+
3
+ import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
4
+ import type React from "react";
5
+ import { type ReactNode } from "react";
6
+ import { cn } from "../../lib";
7
+
8
+ // --- Primitives ---
9
+
10
+ export const PopoverCreateHandle: typeof PopoverPrimitive.createHandle =
11
+ PopoverPrimitive.createHandle;
12
+
13
+ export const PopoverRoot: typeof PopoverPrimitive.Root = PopoverPrimitive.Root;
14
+
15
+ export function PopoverTrigger({
16
+ className,
17
+ children,
18
+ ...props
19
+ }: PopoverPrimitive.Trigger.Props): React.ReactElement {
20
+ return (
21
+ <PopoverPrimitive.Trigger
22
+ className={className}
23
+ data-slot="popover-trigger"
24
+ {...props}
25
+ >
26
+ {children}
27
+ </PopoverPrimitive.Trigger>
28
+ );
29
+ }
30
+
31
+ export function PopoverPopup({
32
+ children,
33
+ className,
34
+ side = "bottom",
35
+ align = "center",
36
+ sideOffset = 4,
37
+ alignOffset = 0,
38
+ tooltipStyle = false,
39
+ matchTriggerWidth = false,
40
+ anchor,
41
+ portalProps,
42
+ ...props
43
+ }: PopoverPrimitive.Popup.Props & {
44
+ portalProps?: PopoverPrimitive.Portal.Props;
45
+ side?: PopoverPrimitive.Positioner.Props["side"];
46
+ align?: PopoverPrimitive.Positioner.Props["align"];
47
+ sideOffset?: PopoverPrimitive.Positioner.Props["sideOffset"];
48
+ alignOffset?: PopoverPrimitive.Positioner.Props["alignOffset"];
49
+ tooltipStyle?: boolean;
50
+ matchTriggerWidth?: boolean;
51
+ anchor?: PopoverPrimitive.Positioner.Props["anchor"];
52
+ }): React.ReactElement {
53
+ return (
54
+ <PopoverPrimitive.Portal {...portalProps}>
55
+ <PopoverPrimitive.Positioner
56
+ align={align}
57
+ alignOffset={alignOffset}
58
+ anchor={anchor}
59
+ className="z-50 h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[top,left,right,bottom,transform] data-instant:transition-none"
60
+ data-slot="popover-positioner"
61
+ side={side}
62
+ sideOffset={sideOffset}
63
+ style={matchTriggerWidth ? { width: "var(--anchor-width)" } : undefined}
64
+ >
65
+ <PopoverPrimitive.Popup
66
+ className={cn(
67
+ "relative flex h-(--popup-height,auto) origin-(--transform-origin) rounded-lg border bg-popover not-dark:bg-clip-padding text-popover-foreground shadow-lg/5 outline-none transition-[width,height,scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] has-data-[slot=calendar]:rounded-xl has-data-[slot=calendar]:before:rounded-[calc(var(--radius-xl)-1px)] data-starting-style:scale-98 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
68
+ matchTriggerWidth ? "w-full" : "w-(--popup-width,auto) max-w-72",
69
+ tooltipStyle &&
70
+ "w-fit text-balance rounded-md text-xs shadow-md/5 before:rounded-[calc(var(--radius-md)-1px)]",
71
+ className,
72
+ )}
73
+ data-slot="popover-popup"
74
+ {...props}
75
+ >
76
+ <PopoverPrimitive.Viewport
77
+ className={cn(
78
+ "relative size-full max-h-(--available-height) overflow-clip px-(--viewport-inline-padding) py-4 [--viewport-inline-padding:--spacing(4)] has-data-[slot=calendar]:p-2 data-instant:transition-none **:data-current:data-ending-style:opacity-0 **:data-current:data-starting-style:opacity-0 **:data-previous:data-ending-style:opacity-0 **:data-previous:data-starting-style:opacity-0 **:data-current:w-[calc(var(--popup-width)-2*var(--viewport-inline-padding)-2px)] **:data-previous:w-[calc(var(--popup-width)-2*var(--viewport-inline-padding)-2px)] **:data-current:opacity-100 **:data-previous:opacity-100 **:data-current:transition-opacity **:data-previous:transition-opacity",
79
+ tooltipStyle
80
+ ? "py-1 [--viewport-inline-padding:--spacing(2)]"
81
+ : "not-data-transitioning:overflow-y-auto",
82
+ )}
83
+ data-slot="popover-viewport"
84
+ >
85
+ {children}
86
+ </PopoverPrimitive.Viewport>
87
+ </PopoverPrimitive.Popup>
88
+ </PopoverPrimitive.Positioner>
89
+ </PopoverPrimitive.Portal>
90
+ );
91
+ }
92
+
93
+ export function PopoverClose({
94
+ ...props
95
+ }: PopoverPrimitive.Close.Props): React.ReactElement {
96
+ return <PopoverPrimitive.Close data-slot="popover-close" {...props} />;
97
+ }
98
+
99
+ export function PopoverTitle({
100
+ className,
101
+ ...props
102
+ }: PopoverPrimitive.Title.Props): React.ReactElement {
103
+ return (
104
+ <PopoverPrimitive.Title
105
+ className={cn("font-semibold text-lg leading-none", className)}
106
+ data-slot="popover-title"
107
+ {...props}
108
+ />
109
+ );
110
+ }
111
+
112
+ export function PopoverDescription({
113
+ className,
114
+ ...props
115
+ }: PopoverPrimitive.Description.Props): React.ReactElement {
116
+ return (
117
+ <PopoverPrimitive.Description
118
+ className={cn("text-muted-foreground text-sm", className)}
119
+ data-slot="popover-description"
120
+ {...props}
121
+ />
122
+ );
123
+ }
124
+
125
+ export { PopoverPrimitive, PopoverPopup as PopoverContent };
126
+
127
+ // --- Composite ---
128
+
129
+ type PopoverPopupOverrideProps = Omit<
130
+ React.ComponentPropsWithoutRef<typeof PopoverPopup>,
131
+ | "children"
132
+ | "side"
133
+ | "align"
134
+ | "sideOffset"
135
+ | "alignOffset"
136
+ | "tooltipStyle"
137
+ | "matchTriggerWidth"
138
+ | "anchor"
139
+ >;
140
+
141
+ interface PopoverProps extends Omit<PopoverPrimitive.Root.Props, "children"> {
142
+ trigger?: React.ReactElement;
143
+ children: ReactNode;
144
+ title?: ReactNode;
145
+ description?: ReactNode;
146
+ side?: PopoverPrimitive.Positioner.Props["side"];
147
+ align?: PopoverPrimitive.Positioner.Props["align"];
148
+ sideOffset?: PopoverPrimitive.Positioner.Props["sideOffset"];
149
+ alignOffset?: PopoverPrimitive.Positioner.Props["alignOffset"];
150
+ tooltipStyle?: boolean;
151
+ matchTriggerWidth?: boolean;
152
+ anchor?: PopoverPrimitive.Positioner.Props["anchor"];
153
+ popupClassName?: string;
154
+ triggerProps?: Omit<PopoverPrimitive.Trigger.Props, "render" | "children">;
155
+ popupProps?: PopoverPopupOverrideProps;
156
+ }
157
+
158
+ export function Popover({
159
+ trigger,
160
+ children,
161
+ title,
162
+ description,
163
+ side,
164
+ align,
165
+ sideOffset,
166
+ alignOffset,
167
+ tooltipStyle,
168
+ matchTriggerWidth,
169
+ anchor,
170
+ popupClassName,
171
+ triggerProps,
172
+ popupProps,
173
+ ...rootProps
174
+ }: PopoverProps): React.ReactElement {
175
+ return (
176
+ <PopoverRoot {...rootProps}>
177
+ {trigger !== undefined && (
178
+ <PopoverTrigger render={trigger} {...triggerProps} />
179
+ )}
180
+ <PopoverPopup
181
+ {...popupProps}
182
+ side={side}
183
+ align={align}
184
+ sideOffset={sideOffset}
185
+ alignOffset={alignOffset}
186
+ tooltipStyle={tooltipStyle}
187
+ matchTriggerWidth={matchTriggerWidth}
188
+ anchor={anchor}
189
+ className={cn(popupProps?.className, popupClassName)}
190
+ >
191
+ {(title ?? description) && (
192
+ <div className="mb-2">
193
+ {title && <PopoverTitle>{title}</PopoverTitle>}
194
+ {description && (
195
+ <PopoverDescription>{description}</PopoverDescription>
196
+ )}
197
+ </div>
198
+ )}
199
+ {children}
200
+ </PopoverPopup>
201
+ </PopoverRoot>
202
+ );
203
+ }
@@ -0,0 +1 @@
1
+ export * from "./progress";
@@ -0,0 +1,124 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { useEffect, useState } from "react";
3
+ import {
4
+ Progress,
5
+ ProgressIndicator,
6
+ ProgressLabel,
7
+ ProgressRoot,
8
+ ProgressTrack,
9
+ ProgressValue,
10
+ } from "../../components";
11
+
12
+ /**
13
+ * Progress bar built on Base UI. Renders a filled track that scales with
14
+ * `value` (0–100, or `null` for indeterminate). Supports `size` for track
15
+ * height and `variant` for indicator color. Use `ProgressRoot`, `ProgressTrack`,
16
+ * `ProgressIndicator`, `ProgressLabel`, and `ProgressValue` for full composition control.
17
+ */
18
+ const meta: Meta<typeof Progress> = {
19
+ title: "Components/Progress",
20
+ component: Progress,
21
+ args: {
22
+ value: 60,
23
+ "aria-label": "Loading",
24
+ },
25
+ };
26
+
27
+ export default meta;
28
+ type Story = StoryObj<typeof Progress>;
29
+
30
+ export const Default: Story = {};
31
+
32
+ export const Animated: Story = {
33
+ render: () => {
34
+ const [value, setValue] = useState(0);
35
+ const [status, setStatus] = useState<"loading" | "complete">("loading");
36
+
37
+ useEffect(() => {
38
+ if (status === "complete") {
39
+ const timeout = setTimeout(() => {
40
+ setValue(0);
41
+ setStatus("loading");
42
+ }, 2000);
43
+ return () => clearTimeout(timeout);
44
+ }
45
+
46
+ const interval = setInterval(() => {
47
+ setValue((prev) => {
48
+ const next = Math.min(100, prev + Math.floor(Math.random() * 20) + 5);
49
+ if (next === 100) setStatus("complete");
50
+ return next;
51
+ });
52
+ }, 800);
53
+
54
+ return () => clearInterval(interval);
55
+ }, [status]);
56
+
57
+ return (
58
+ <ProgressRoot value={value} className="w-80">
59
+ <div className="flex items-center justify-between">
60
+ <ProgressLabel>
61
+ {status === "complete" ? "Upload complete" : "Uploading files..."}
62
+ </ProgressLabel>
63
+ <ProgressValue />
64
+ </div>
65
+ <ProgressTrack>
66
+ <ProgressIndicator
67
+ variant={status === "complete" ? "success" : "default"}
68
+ />
69
+ </ProgressTrack>
70
+ </ProgressRoot>
71
+ );
72
+ },
73
+ };
74
+
75
+ export const Sizes: Story = {
76
+ render: (args) => (
77
+ <div className="flex w-80 flex-col gap-4">
78
+ <Progress {...args} size="sm" />
79
+ <Progress {...args} size="md" />
80
+ <Progress {...args} size="lg" />
81
+ </div>
82
+ ),
83
+ };
84
+
85
+ export const Success: Story = {
86
+ args: { variant: "success" },
87
+ };
88
+
89
+ export const Error: Story = {
90
+ args: { variant: "error" },
91
+ };
92
+
93
+ /**
94
+ * Combine `ProgressLabel` and `ProgressValue` with `ProgressTrack` inside
95
+ * `ProgressRoot` for labeled progress bars. `ProgressValue` renders the
96
+ * current value as formatted text using the `getAriaValueText` render prop.
97
+ */
98
+ export const WithLabel: Story = {
99
+ render: (args) => (
100
+ <ProgressRoot value={args.value} className="w-80">
101
+ <div className="flex justify-between">
102
+ <ProgressLabel>Uploading files</ProgressLabel>
103
+ <ProgressValue />
104
+ </div>
105
+ <ProgressTrack>
106
+ <ProgressIndicator />
107
+ </ProgressTrack>
108
+ </ProgressRoot>
109
+ ),
110
+ };
111
+
112
+ /**
113
+ * Use `ProgressRoot`, `ProgressTrack`, and `ProgressIndicator` directly
114
+ * for layouts that need full control over composition.
115
+ */
116
+ export const Primitive: Story = {
117
+ render: () => (
118
+ <ProgressRoot value={40} className="w-80">
119
+ <ProgressTrack size="lg">
120
+ <ProgressIndicator variant="success" />
121
+ </ProgressTrack>
122
+ </ProgressRoot>
123
+ ),
124
+ };
@@ -0,0 +1,25 @@
1
+ import { render, screen } from "@testing-library/react";
2
+ import { describe, expect, it } from "vitest";
3
+ import { Progress } from "../../components";
4
+
5
+ describe("Progress component", () => {
6
+ it("renders a progressbar", () => {
7
+ render(<Progress value={50} aria-label="Loading" />);
8
+ expect(screen.getByRole("progressbar")).toBeTruthy();
9
+ });
10
+
11
+ it("exposes the current value via aria-valuenow", () => {
12
+ render(<Progress value={75} aria-label="Loading" />);
13
+ expect(screen.getByRole("progressbar")).toHaveAttribute(
14
+ "aria-valuenow",
15
+ "75",
16
+ );
17
+ });
18
+
19
+ it("renders as indeterminate when value is null", () => {
20
+ render(<Progress value={null} aria-label="Loading" />);
21
+ expect(screen.getByRole("progressbar").hasAttribute("aria-valuenow")).toBe(
22
+ false,
23
+ );
24
+ });
25
+ });
@@ -0,0 +1,124 @@
1
+ import { Progress as ProgressPrimitive } from "@base-ui/react/progress";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+ import type * as React from "react";
4
+ import { cn } from "../../lib";
5
+
6
+ const progressTrackVariants = cva(
7
+ "block w-full overflow-hidden rounded-full bg-input",
8
+ {
9
+ variants: {
10
+ size: {
11
+ sm: "h-1",
12
+ md: "h-1.5",
13
+ lg: "h-2.5",
14
+ },
15
+ },
16
+ defaultVariants: { size: "md" },
17
+ },
18
+ );
19
+
20
+ const progressIndicatorVariants = cva("transition-all duration-500", {
21
+ variants: {
22
+ variant: {
23
+ default: "bg-primary",
24
+ success: "bg-success",
25
+ error: "bg-error",
26
+ warning: "bg-warning",
27
+ info: "bg-info",
28
+ },
29
+ },
30
+ defaultVariants: { variant: "default" },
31
+ });
32
+
33
+ export function ProgressRoot({
34
+ className,
35
+ ...props
36
+ }: ProgressPrimitive.Root.Props): React.ReactElement {
37
+ return (
38
+ <ProgressPrimitive.Root
39
+ className={cn("flex w-full flex-col gap-2", className)}
40
+ data-slot="progress"
41
+ {...props}
42
+ />
43
+ );
44
+ }
45
+
46
+ export function ProgressLabel({
47
+ className,
48
+ ...props
49
+ }: ProgressPrimitive.Label.Props): React.ReactElement {
50
+ return (
51
+ <ProgressPrimitive.Label
52
+ className={cn("font-medium text-sm", className)}
53
+ data-slot="progress-label"
54
+ {...props}
55
+ />
56
+ );
57
+ }
58
+
59
+ export function ProgressTrack({
60
+ className,
61
+ size,
62
+ ...props
63
+ }: ProgressPrimitive.Track.Props &
64
+ VariantProps<typeof progressTrackVariants>): React.ReactElement {
65
+ return (
66
+ <ProgressPrimitive.Track
67
+ className={cn(progressTrackVariants({ size }), className)}
68
+ data-slot="progress-track"
69
+ {...props}
70
+ />
71
+ );
72
+ }
73
+
74
+ export function ProgressIndicator({
75
+ className,
76
+ variant,
77
+ ...props
78
+ }: ProgressPrimitive.Indicator.Props &
79
+ VariantProps<typeof progressIndicatorVariants>): React.ReactElement {
80
+ return (
81
+ <ProgressPrimitive.Indicator
82
+ className={cn(progressIndicatorVariants({ variant }), className)}
83
+ data-slot="progress-indicator"
84
+ {...props}
85
+ />
86
+ );
87
+ }
88
+
89
+ export function ProgressValue({
90
+ className,
91
+ ...props
92
+ }: ProgressPrimitive.Value.Props): React.ReactElement {
93
+ return (
94
+ <ProgressPrimitive.Value
95
+ className={cn("text-sm tabular-nums", className)}
96
+ data-slot="progress-value"
97
+ {...props}
98
+ />
99
+ );
100
+ }
101
+
102
+ interface ProgressProps extends Omit<ProgressPrimitive.Root.Props, "children"> {
103
+ size?: VariantProps<typeof progressTrackVariants>["size"];
104
+ variant?: VariantProps<typeof progressIndicatorVariants>["variant"];
105
+ trackProps?: ProgressPrimitive.Track.Props;
106
+ indicatorProps?: ProgressPrimitive.Indicator.Props;
107
+ }
108
+
109
+ export function Progress({
110
+ size,
111
+ variant,
112
+ className,
113
+ trackProps,
114
+ indicatorProps,
115
+ ...props
116
+ }: ProgressProps): React.ReactElement {
117
+ return (
118
+ <ProgressRoot className={className} {...props}>
119
+ <ProgressTrack size={size} {...trackProps}>
120
+ <ProgressIndicator variant={variant} {...indicatorProps} />
121
+ </ProgressTrack>
122
+ </ProgressRoot>
123
+ );
124
+ }
@@ -0,0 +1 @@
1
+ export * from "./scroll-area.tsx";
@@ -0,0 +1,166 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { ScrollArea, ScrollAreaPrimitive, ScrollBar } from "./scroll-area";
3
+
4
+ const verticalItems = Array.from({ length: 24 }, (_, index) => ({
5
+ id: index + 1,
6
+ label: `Item ${index + 1}`,
7
+ description: `Scrollable content row ${index + 1}.`,
8
+ }));
9
+
10
+ const horizontalItems = Array.from({ length: 18 }, (_, index) => ({
11
+ id: index + 1,
12
+ label: `Column ${index + 1}`,
13
+ }));
14
+
15
+ /**
16
+ * Native scroll container built on Base UI with custom scrollbar styling.
17
+ *
18
+ * `scrollFade` uses viewport edge masks tied to overflow variables, so the fade
19
+ * appears only where more content exists. `scrollbarGutter` reserves room in
20
+ * the viewport to avoid layout shifts when overflow state toggles.
21
+ *
22
+ * Reference: [Scroll Area - Base UI](https://base-ui.com/react/components/scroll-area.md)
23
+ */
24
+ const meta: Meta<typeof ScrollArea> = {
25
+ title: "Components/Scroll Area",
26
+ component: ScrollArea,
27
+ parameters: { layout: "centered" },
28
+ args: {
29
+ className: "h-72 w-96 rounded-md border",
30
+ },
31
+ argTypes: {
32
+ children: { control: false },
33
+ },
34
+ };
35
+
36
+ export default meta;
37
+ type Story = StoryObj<typeof ScrollArea>;
38
+
39
+ export const Default: Story = {
40
+ render: (args) => (
41
+ <ScrollArea {...args}>
42
+ <div className="space-y-3 p-4">
43
+ {verticalItems.map((item) => (
44
+ <div key={item.id} className="rounded-md border bg-background p-3">
45
+ <p className="text-sm font-medium">{item.label}</p>
46
+ <p className="text-sm text-muted-foreground">{item.description}</p>
47
+ </div>
48
+ ))}
49
+ </div>
50
+ </ScrollArea>
51
+ ),
52
+ };
53
+
54
+ /**
55
+ * `scrollFade` masks each viewport edge based on current overflow values.
56
+ * The fade appears only on edges where hidden content remains.
57
+ */
58
+ export const ScrollFade: Story = {
59
+ args: {
60
+ scrollFade: true,
61
+ },
62
+ render: (args) => (
63
+ <ScrollArea {...args}>
64
+ <div className="space-y-3 p-4">
65
+ {verticalItems.map((item) => (
66
+ <div key={item.id} className="rounded-md border bg-background p-3">
67
+ <p className="text-sm font-medium">{item.label}</p>
68
+ <p className="text-sm text-muted-foreground">{item.description}</p>
69
+ </div>
70
+ ))}
71
+ </div>
72
+ </ScrollArea>
73
+ ),
74
+ };
75
+
76
+ export const HorizontalScroll: Story = {
77
+ render: (args) => (
78
+ <ScrollArea {...args} className="h-44 w-96 rounded-md border">
79
+ <div className="flex w-max gap-3 p-4 h-full">
80
+ {horizontalItems.map((item) => (
81
+ <div
82
+ key={item.id}
83
+ className="flex w-32 shrink-0 items-center justify-center rounded-md border bg-muted text-sm font-medium"
84
+ >
85
+ {item.label}
86
+ </div>
87
+ ))}
88
+ </div>
89
+ </ScrollArea>
90
+ ),
91
+ };
92
+
93
+ /**
94
+ * `scrollbarGutter` keeps consistent content padding when scrollbars appear.
95
+ * This prevents text and cards from shifting as overflow transitions.
96
+ */
97
+ export const ScrollbarGutter: Story = {
98
+ args: {
99
+ scrollbarGutter: true,
100
+ },
101
+ render: (args) => (
102
+ <ScrollArea {...args}>
103
+ {verticalItems.map((item) => (
104
+ <div key={item.id} className="rounded-md border bg-background p-3 m-1">
105
+ <p className="text-sm font-medium">{item.label}</p>
106
+ <p className="text-sm text-muted-foreground">{item.description}</p>
107
+ </div>
108
+ ))}
109
+ </ScrollArea>
110
+ ),
111
+ };
112
+
113
+ export const BothScrollbars: Story = {
114
+ render: (args) => (
115
+ <ScrollArea {...args} className="h-64 w-96 rounded-md border">
116
+ <div className="w-3xl space-y-3 p-4">
117
+ {verticalItems.map((item) => (
118
+ <div
119
+ key={item.id}
120
+ className="flex items-center justify-between rounded-md border bg-background p-3"
121
+ >
122
+ <p className="text-sm font-medium">{item.label}</p>
123
+ <p className="text-sm text-muted-foreground">
124
+ Extra content width for horizontal overflow
125
+ </p>
126
+ </div>
127
+ ))}
128
+ </div>
129
+ </ScrollArea>
130
+ ),
131
+ };
132
+
133
+ /**
134
+ * Direct composition with Base UI primitives for full structural control.
135
+ * Useful when the composite wrapper is not enough for custom subtree order.
136
+ *
137
+ * ```tsx
138
+ * <ScrollAreaPrimitive.Root>
139
+ * <ScrollAreaPrimitive.Viewport>{children}</ScrollAreaPrimitive.Viewport>
140
+ * <ScrollBar orientation="vertical" />
141
+ * <ScrollBar orientation="horizontal" />
142
+ * <ScrollAreaPrimitive.Corner />
143
+ * </ScrollAreaPrimitive.Root>
144
+ * ```
145
+ */
146
+ export const Primitive: Story = {
147
+ render: () => (
148
+ <ScrollAreaPrimitive.Root className="h-72 w-96 rounded-md border">
149
+ <ScrollAreaPrimitive.Viewport className="h-full rounded-[inherit] p-4">
150
+ <div className="space-y-3">
151
+ {verticalItems.map((item) => (
152
+ <div key={item.id} className="rounded-md border bg-background p-3">
153
+ <p className="text-sm font-medium">{item.label}</p>
154
+ <p className="text-sm text-muted-foreground">
155
+ {item.description}
156
+ </p>
157
+ </div>
158
+ ))}
159
+ </div>
160
+ </ScrollAreaPrimitive.Viewport>
161
+ <ScrollBar orientation="vertical" />
162
+ <ScrollBar orientation="horizontal" />
163
+ <ScrollAreaPrimitive.Corner />
164
+ </ScrollAreaPrimitive.Root>
165
+ ),
166
+ };