@k3-universe/react-kit 0.0.41 → 0.0.42

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 (701) hide show
  1. package/.babelrc +12 -12
  2. package/.storybook/main.ts +22 -22
  3. package/.storybook/preview.ts +198 -198
  4. package/Dockerfile.storybook +43 -43
  5. package/README.md +9 -9
  6. package/biome.json +10 -10
  7. package/components.json +20 -20
  8. package/dist/index.js +32 -14
  9. package/dist/kit/builder/auth/hooks/core-hooks.d.ts.map +1 -1
  10. package/dist/kit/builder/form/components/fields/AutocompleteField.d.ts.map +1 -1
  11. package/dist/kit/builder/form/components/fields/DatePickerField.d.ts.map +1 -1
  12. package/dist/kit/builder/form/components/fields/DateRangePickerField.d.ts.map +1 -1
  13. package/dist/kit/builder/form/types.d.ts +2 -0
  14. package/dist/kit/builder/form/types.d.ts.map +1 -1
  15. package/dist/kit/components/autocomplete/Autocomplete.d.ts +2 -1
  16. package/dist/kit/components/autocomplete/Autocomplete.d.ts.map +1 -1
  17. package/dist/kit/layouts/admin/hooks/menu.d.ts.map +1 -1
  18. package/dist/kit/themes/clean-slate.css +4 -8
  19. package/dist/kit/themes/default.css +5 -9
  20. package/dist/kit/themes/minimal-modern.css +4 -8
  21. package/dist/kit/themes/spotify.css +4 -8
  22. package/package.json +1 -1
  23. package/src/index.ts +99 -99
  24. package/src/kit/builder/auth/components/Can.tsx +27 -27
  25. package/src/kit/builder/auth/components/RequireAuth.tsx +78 -78
  26. package/src/kit/builder/auth/components/ShowWhenAuthenticated.tsx +10 -10
  27. package/src/kit/builder/auth/components/ShowWhenError.tsx +10 -10
  28. package/src/kit/builder/auth/components/ShowWhenLoading.tsx +10 -10
  29. package/src/kit/builder/auth/components/ShowWhenUnauthenticated.tsx +10 -10
  30. package/src/kit/builder/auth/components/withPermission.tsx +23 -23
  31. package/src/kit/builder/auth/hooks/action-hooks.ts +34 -34
  32. package/src/kit/builder/auth/hooks/core-hooks.ts +65 -65
  33. package/src/kit/builder/auth/hooks/index.ts +4 -4
  34. package/src/kit/builder/auth/hooks/permission-hooks.ts +43 -43
  35. package/src/kit/builder/auth/hooks/token-hooks.ts +25 -25
  36. package/src/kit/builder/auth/index.ts +132 -132
  37. package/src/kit/builder/auth/providers/AuthProvider.tsx +131 -131
  38. package/src/kit/builder/auth/types/adapter-config.ts +44 -44
  39. package/src/kit/builder/auth/types/adapter.ts +132 -132
  40. package/src/kit/builder/auth/types/core.ts +27 -27
  41. package/src/kit/builder/auth/types/index.ts +9 -9
  42. package/src/kit/builder/auth/types/middleware.ts +20 -20
  43. package/src/kit/builder/auth/types/permissions.ts +23 -23
  44. package/src/kit/builder/auth/types/state.ts +16 -16
  45. package/src/kit/builder/auth/types/storage.ts +21 -21
  46. package/src/kit/builder/auth/types/token-manager.ts +9 -9
  47. package/src/kit/builder/auth/types/utils.ts +55 -55
  48. package/src/kit/builder/auth/utils/auth-adapter.ts +437 -437
  49. package/src/kit/builder/auth/utils/client-adapters/apollo-link.ts +30 -30
  50. package/src/kit/builder/auth/utils/client-adapters/axios.ts +61 -61
  51. package/src/kit/builder/auth/utils/client-adapters/fetch.ts +48 -48
  52. package/src/kit/builder/auth/utils/client-adapters/graphql.ts +60 -60
  53. package/src/kit/builder/auth/utils/client-adapters/index.ts +6 -6
  54. package/src/kit/builder/auth/utils/client-adapters/rest.ts +60 -60
  55. package/src/kit/builder/auth/utils/client-adapters/urql-exchange.ts +76 -76
  56. package/src/kit/builder/auth/utils/permission-checker.ts +150 -150
  57. package/src/kit/builder/auth/utils/storage/browser.ts +99 -99
  58. package/src/kit/builder/auth/utils/storage/cookie.ts +116 -116
  59. package/src/kit/builder/auth/utils/storage/encryption.ts +80 -80
  60. package/src/kit/builder/auth/utils/storage/env.ts +2 -2
  61. package/src/kit/builder/auth/utils/storage/factory.ts +37 -37
  62. package/src/kit/builder/auth/utils/storage/index.ts +6 -6
  63. package/src/kit/builder/auth/utils/storage/memory.ts +15 -15
  64. package/src/kit/builder/auth/utils/token-manager.ts +55 -55
  65. package/src/kit/builder/data-table/components/DataTable.tsx +547 -547
  66. package/src/kit/builder/data-table/components/DataTableColumnHeader.tsx +67 -67
  67. package/src/kit/builder/data-table/components/DataTablePagination.tsx +112 -112
  68. package/src/kit/builder/data-table/components/DataTableViewOptions.tsx +51 -51
  69. package/src/kit/builder/data-table/index.ts +6 -6
  70. package/src/kit/builder/data-table/types.ts +44 -44
  71. package/src/kit/builder/data-table/utils/dotAccessor.ts +6 -6
  72. package/src/kit/builder/dialog/index.ts +6 -6
  73. package/src/kit/builder/dialog/provider.tsx +170 -170
  74. package/src/kit/builder/form/components/FormBuilder.tsx +295 -295
  75. package/src/kit/builder/form/components/FormBuilderActions.tsx +78 -78
  76. package/src/kit/builder/form/components/FormBuilderContext.tsx +52 -52
  77. package/src/kit/builder/form/components/FormBuilderField.tsx +456 -456
  78. package/src/kit/builder/form/components/fields/ArrayField.tsx +311 -311
  79. package/src/kit/builder/form/components/fields/AutocompleteField.tsx +89 -88
  80. package/src/kit/builder/form/components/fields/CheckboxField.tsx +65 -65
  81. package/src/kit/builder/form/components/fields/DateField.tsx +26 -26
  82. package/src/kit/builder/form/components/fields/DatePickerField.tsx +31 -29
  83. package/src/kit/builder/form/components/fields/DateRangePickerField.tsx +55 -46
  84. package/src/kit/builder/form/components/fields/DateTimePickerField.tsx +38 -38
  85. package/src/kit/builder/form/components/fields/DateTimeRangePickerField.tsx +48 -48
  86. package/src/kit/builder/form/components/fields/FileField.tsx +31 -31
  87. package/src/kit/builder/form/components/fields/MonthPickerField.tsx +33 -33
  88. package/src/kit/builder/form/components/fields/MonthRangePickerField.tsx +41 -41
  89. package/src/kit/builder/form/components/fields/NumberField.tsx +20 -20
  90. package/src/kit/builder/form/components/fields/ObjectField.tsx +35 -35
  91. package/src/kit/builder/form/components/fields/RadioField.tsx +47 -47
  92. package/src/kit/builder/form/components/fields/SelectField.tsx +46 -46
  93. package/src/kit/builder/form/components/fields/SwitchField.tsx +65 -65
  94. package/src/kit/builder/form/components/fields/TextField.tsx +25 -25
  95. package/src/kit/builder/form/components/fields/TextareaField.tsx +20 -20
  96. package/src/kit/builder/form/components/fields/TimePickerField.tsx +35 -35
  97. package/src/kit/builder/form/components/fields/TimeRangePickerField.tsx +43 -43
  98. package/src/kit/builder/form/components/fields/index.ts +21 -21
  99. package/src/kit/builder/form/components/fields/types.ts +18 -18
  100. package/src/kit/builder/form/components/index.ts +3 -3
  101. package/src/kit/builder/form/components/sectionNodes.tsx +147 -147
  102. package/src/kit/builder/form/hooks/useFormBuilder.ts +451 -451
  103. package/src/kit/builder/form/index.ts +4 -4
  104. package/src/kit/builder/form/types.ts +245 -243
  105. package/src/kit/builder/form/utils/common-forms.ts +68 -68
  106. package/src/kit/builder/form/utils/dependencies.ts +56 -56
  107. package/src/kit/builder/form/utils/field-factories.ts +177 -177
  108. package/src/kit/builder/form/utils/index.ts +17 -17
  109. package/src/kit/builder/form/utils/section-factories.ts +38 -38
  110. package/src/kit/builder/form/utils/transformers.ts +100 -100
  111. package/src/kit/builder/form/utils/validations.ts +22 -22
  112. package/src/kit/builder/form/utils/validators.ts +20 -20
  113. package/src/kit/builder/page/Page.tsx +202 -202
  114. package/src/kit/builder/page/index.ts +1 -1
  115. package/src/kit/builder/section/SectionBuilder.tsx +435 -435
  116. package/src/kit/builder/section/SectionContainer.tsx +85 -85
  117. package/src/kit/builder/section/index.ts +2 -2
  118. package/src/kit/builder/section/types.ts +80 -80
  119. package/src/kit/builder/stack-dialog/context.ts +15 -15
  120. package/src/kit/builder/stack-dialog/hooks.ts +13 -13
  121. package/src/kit/builder/stack-dialog/index.ts +12 -12
  122. package/src/kit/builder/stack-dialog/provider.tsx +51 -51
  123. package/src/kit/builder/stack-dialog/renderer.tsx +36 -36
  124. package/src/kit/builder/stack-dialog/types.ts +34 -34
  125. package/src/kit/components/autocomplete/Autocomplete.tsx +671 -664
  126. package/src/kit/components/autocomplete/index.ts +3 -3
  127. package/src/kit/components/autocomplete/types.ts +27 -27
  128. package/src/kit/components/datepicker/DatePicker.tsx +173 -173
  129. package/src/kit/components/datepicker/DateRangePicker.tsx +526 -526
  130. package/src/kit/components/datepicker/index.ts +2 -2
  131. package/src/kit/components/datetimepicker/DateTimePicker.tsx +420 -420
  132. package/src/kit/components/datetimepicker/DateTimeRangePicker.tsx +676 -676
  133. package/src/kit/components/datetimepicker/index.ts +2 -2
  134. package/src/kit/components/fileuploader/FileUploader.tsx +626 -626
  135. package/src/kit/components/fileuploader/index.ts +3 -3
  136. package/src/kit/components/fileuploader/types.ts +76 -76
  137. package/src/kit/components/forminfo/FormInfoError.tsx +135 -135
  138. package/src/kit/components/forminfo/index.ts +1 -1
  139. package/src/kit/components/keyboard/Keyboard.tsx +916 -916
  140. package/src/kit/components/keyboard/index.ts +4 -4
  141. package/src/kit/components/login/Login.tsx +141 -141
  142. package/src/kit/components/login/index.ts +1 -1
  143. package/src/kit/components/monthpicker/MonthInput.tsx +131 -131
  144. package/src/kit/components/monthpicker/MonthPicker.tsx +224 -224
  145. package/src/kit/components/monthpicker/MonthRangeInput.tsx +153 -153
  146. package/src/kit/components/monthpicker/MonthRangePicker.tsx +409 -409
  147. package/src/kit/components/numpad/Numpad.tsx +377 -377
  148. package/src/kit/components/numpad/index.ts +4 -4
  149. package/src/kit/components/timepicker/TimePicker.tsx +319 -319
  150. package/src/kit/components/timepicker/TimeRangePicker.tsx +368 -368
  151. package/src/kit/components/timepicker/index.ts +2 -2
  152. package/src/kit/layouts/admin/components/AdminLayout.tsx +286 -286
  153. package/src/kit/layouts/admin/components/ThemeToggle.tsx +54 -54
  154. package/src/kit/layouts/admin/hooks/menu.ts +32 -32
  155. package/src/kit/layouts/admin/providers/AdminMenuProvider.tsx +78 -78
  156. package/src/kit/layouts/admin/types/index.ts +26 -26
  157. package/src/kit/providers/ThemeProvider.tsx +90 -90
  158. package/src/kit/themes/base.css +11 -11
  159. package/src/kit/themes/clean-slate.css +155 -155
  160. package/src/kit/themes/default.css +192 -192
  161. package/src/kit/themes/minimal-modern.css +155 -155
  162. package/src/kit/themes/spotify.css +164 -164
  163. package/src/shadcn/hooks/use-mobile.ts +21 -21
  164. package/src/shadcn/lib/utils.ts +6 -6
  165. package/src/shadcn/ui/accordion.tsx +66 -66
  166. package/src/shadcn/ui/alert-dialog.tsx +157 -157
  167. package/src/shadcn/ui/alert.tsx +66 -66
  168. package/src/shadcn/ui/aspect-ratio.tsx +11 -11
  169. package/src/shadcn/ui/avatar.tsx +53 -53
  170. package/src/shadcn/ui/badge.tsx +46 -46
  171. package/src/shadcn/ui/breadcrumb.tsx +108 -108
  172. package/src/shadcn/ui/button.tsx +59 -59
  173. package/src/shadcn/ui/calendar.tsx +217 -217
  174. package/src/shadcn/ui/card.tsx +92 -92
  175. package/src/shadcn/ui/carousel.tsx +240 -240
  176. package/src/shadcn/ui/chart.tsx +353 -353
  177. package/src/shadcn/ui/checkbox.tsx +32 -32
  178. package/src/shadcn/ui/collapsible.tsx +33 -33
  179. package/src/shadcn/ui/command.tsx +184 -184
  180. package/src/shadcn/ui/context-menu.tsx +252 -252
  181. package/src/shadcn/ui/dialog.tsx +143 -143
  182. package/src/shadcn/ui/drawer.tsx +135 -135
  183. package/src/shadcn/ui/dropdown-menu.tsx +257 -257
  184. package/src/shadcn/ui/form.tsx +168 -168
  185. package/src/shadcn/ui/hover-card.tsx +44 -44
  186. package/src/shadcn/ui/input-otp.tsx +77 -77
  187. package/src/shadcn/ui/input.tsx +21 -21
  188. package/src/shadcn/ui/label.tsx +24 -24
  189. package/src/shadcn/ui/menubar.tsx +276 -276
  190. package/src/shadcn/ui/navigation-menu.tsx +168 -168
  191. package/src/shadcn/ui/pagination.tsx +127 -127
  192. package/src/shadcn/ui/popover.tsx +48 -48
  193. package/src/shadcn/ui/progress.tsx +31 -31
  194. package/src/shadcn/ui/radio-group.tsx +45 -45
  195. package/src/shadcn/ui/resizable.tsx +56 -56
  196. package/src/shadcn/ui/scroll-area.tsx +58 -58
  197. package/src/shadcn/ui/select.tsx +185 -185
  198. package/src/shadcn/ui/separator.tsx +28 -28
  199. package/src/shadcn/ui/sheet.tsx +139 -139
  200. package/src/shadcn/ui/sidebar.tsx +726 -726
  201. package/src/shadcn/ui/skeleton.tsx +13 -13
  202. package/src/shadcn/ui/slider.tsx +63 -63
  203. package/src/shadcn/ui/sonner.tsx +25 -25
  204. package/src/shadcn/ui/switch.tsx +31 -31
  205. package/src/shadcn/ui/table.tsx +116 -116
  206. package/src/shadcn/ui/tabs.tsx +66 -66
  207. package/src/shadcn/ui/textarea.tsx +18 -18
  208. package/src/shadcn/ui/toggle-group.tsx +73 -73
  209. package/src/shadcn/ui/toggle.tsx +47 -47
  210. package/src/shadcn/ui/tooltip.tsx +61 -61
  211. package/src/stories/FileUploader.stories.tsx +185 -185
  212. package/src/stories/kit/builder/DataTable.Basic.stories.tsx +71 -71
  213. package/src/stories/kit/builder/DataTable.Filters.stories.tsx +98 -98
  214. package/src/stories/kit/builder/DataTable.Pagination.stories.tsx +73 -73
  215. package/src/stories/kit/builder/DataTable.SelectionAndActions.stories.tsx +77 -77
  216. package/src/stories/kit/builder/DataTable.Sorting.stories.tsx +67 -67
  217. package/src/stories/kit/builder/Dialog.stories.tsx +90 -90
  218. package/src/stories/kit/builder/Form.ArrayLayouts.stories.tsx +177 -177
  219. package/src/stories/kit/builder/Form.Autocomplete.stories.tsx +220 -220
  220. package/src/stories/kit/builder/Form.Basic.stories.tsx +79 -79
  221. package/src/stories/kit/builder/Form.Complex.stories.tsx +569 -569
  222. package/src/stories/kit/builder/Form.DateTime.stories.tsx +70 -70
  223. package/src/stories/kit/builder/Form.Dynamic.stories.tsx +926 -926
  224. package/src/stories/kit/builder/Form.Files.stories.tsx +136 -136
  225. package/src/stories/kit/builder/Form.MultipleFormBuilder.stories.tsx +377 -377
  226. package/src/stories/kit/builder/Form.Pickers.stories.tsx +75 -75
  227. package/src/stories/kit/builder/Form.Simple.stories.tsx +91 -91
  228. package/src/stories/kit/builder/Form.Time.stories.tsx +68 -68
  229. package/src/stories/kit/builder/Page.stories.tsx +115 -115
  230. package/src/stories/kit/builder/Section.stories.tsx +282 -282
  231. package/src/stories/kit/components/Autocomplete.stories.tsx +313 -313
  232. package/src/stories/kit/components/DatePicker.stories.tsx +195 -195
  233. package/src/stories/kit/components/DateRangePicker.stories.tsx +195 -195
  234. package/src/stories/kit/components/Keyboard.stories.tsx +263 -263
  235. package/src/stories/kit/components/Login.stories.tsx +167 -167
  236. package/src/stories/kit/components/MonthPicker.stories.tsx +100 -100
  237. package/src/stories/kit/components/MonthRangePicker.stories.tsx +117 -117
  238. package/src/stories/kit/components/Numpad.stories.tsx +195 -195
  239. package/src/stories/kit/components/TimePicker.stories.tsx +71 -71
  240. package/src/stories/kit/components/TimeRangePicker.stories.tsx +43 -43
  241. package/src/stories/kit/layouts/admin/AdminLayout.Basic.stories.tsx +118 -118
  242. package/src/stories/kit/layouts/admin/AdminLayout.Collapsible.stories.tsx +81 -81
  243. package/src/stories/kit/layouts/admin/AdminLayout.Complex.stories.tsx +251 -251
  244. package/src/stories/kit/layouts/admin/AdminLayout.CustomSidebarHeaderComponent.stories.tsx +80 -80
  245. package/src/stories/kit/layouts/admin/AdminLayout.CustomSidebarTitleAndIcon.stories.tsx +70 -70
  246. package/src/stories/kit/layouts/admin/AdminLayout.HeaderSlots.stories.tsx +87 -87
  247. package/src/stories/shadcn/ui/Accordion.stories.tsx +117 -117
  248. package/src/stories/shadcn/ui/Alert.stories.tsx +36 -36
  249. package/src/stories/shadcn/ui/AlertDialog.stories.tsx +73 -73
  250. package/src/stories/shadcn/ui/AspectRatio.stories.tsx +58 -58
  251. package/src/stories/shadcn/ui/Avatar.stories.tsx +26 -26
  252. package/src/stories/shadcn/ui/Badge.stories.tsx +28 -28
  253. package/src/stories/shadcn/ui/Breadcrumb.stories.tsx +47 -47
  254. package/src/stories/shadcn/ui/Button.stories.tsx +51 -51
  255. package/src/stories/shadcn/ui/Calendar.stories.tsx +33 -33
  256. package/src/stories/shadcn/ui/Card.stories.tsx +39 -39
  257. package/src/stories/shadcn/ui/Carousel.stories.tsx +37 -37
  258. package/src/stories/shadcn/ui/Chart.stories.tsx +72 -72
  259. package/src/stories/shadcn/ui/Checkbox.stories.tsx +64 -64
  260. package/src/stories/shadcn/ui/Collapsible.stories.tsx +40 -40
  261. package/src/stories/shadcn/ui/Command.stories.tsx +53 -53
  262. package/src/stories/shadcn/ui/ContextMenu.stories.tsx +67 -67
  263. package/src/stories/shadcn/ui/Dialog.stories.tsx +45 -45
  264. package/src/stories/shadcn/ui/Drawer.stories.tsx +49 -49
  265. package/src/stories/shadcn/ui/DropdownMenu.stories.tsx +75 -75
  266. package/src/stories/shadcn/ui/Form.stories.tsx +93 -93
  267. package/src/stories/shadcn/ui/HoverCard.stories.tsx +43 -43
  268. package/src/stories/shadcn/ui/Input.stories.tsx +41 -41
  269. package/src/stories/shadcn/ui/InputOtp.stories.tsx +39 -39
  270. package/src/stories/shadcn/ui/Label.stories.tsx +29 -29
  271. package/src/stories/shadcn/ui/Menubar.stories.tsx +87 -87
  272. package/src/stories/shadcn/ui/NavigationMenu.stories.tsx +78 -78
  273. package/src/stories/shadcn/ui/Pagination.stories.tsx +51 -51
  274. package/src/stories/shadcn/ui/Popover.stories.tsx +53 -53
  275. package/src/stories/shadcn/ui/Progress.stories.tsx +30 -30
  276. package/src/stories/shadcn/ui/RadioGroup.stories.tsx +31 -31
  277. package/src/stories/shadcn/ui/Resizable.stories.tsx +55 -55
  278. package/src/stories/shadcn/ui/ScrollArea.stories.tsx +84 -84
  279. package/src/stories/shadcn/ui/Select.stories.tsx +61 -61
  280. package/src/stories/shadcn/ui/Separator.stories.tsx +35 -35
  281. package/src/stories/shadcn/ui/Sheet.stories.tsx +48 -48
  282. package/src/stories/shadcn/ui/Sidebar.stories.tsx +131 -131
  283. package/src/stories/shadcn/ui/Skeleton.stories.tsx +23 -23
  284. package/src/stories/shadcn/ui/Slider.stories.tsx +21 -21
  285. package/src/stories/shadcn/ui/Sonner.stories.tsx +49 -49
  286. package/src/stories/shadcn/ui/Switch.stories.tsx +28 -28
  287. package/src/stories/shadcn/ui/Table.stories.tsx +374 -374
  288. package/src/stories/shadcn/ui/Tabs.stories.tsx +31 -31
  289. package/src/stories/shadcn/ui/Textarea.stories.tsx +42 -42
  290. package/src/stories/shadcn/ui/Toggle.stories.tsx +44 -44
  291. package/src/stories/shadcn/ui/ToggleGroup.stories.tsx +28 -28
  292. package/src/stories/shadcn/ui/Tooltip.stories.tsx +30 -30
  293. package/tsconfig.json +20 -20
  294. package/tsconfig.lib.json +52 -52
  295. package/tsconfig.spec.json +38 -38
  296. package/vite.config.ts +93 -93
  297. package/storybook-static/assets/Accordion.stories-KU4JBR8U.js +0 -52
  298. package/storybook-static/assets/AdminLayout-CPvVCwfY.js +0 -53
  299. package/storybook-static/assets/AdminLayout.Basic.stories-DkP2UVXe.js +0 -4
  300. package/storybook-static/assets/AdminLayout.Collapsible.stories-BuuVjtpW.js +0 -4
  301. package/storybook-static/assets/AdminLayout.Complex.stories-D-k4H0hJ.js +0 -29
  302. package/storybook-static/assets/AdminLayout.CustomSidebarHeaderComponent.stories-B_0IEDd4.js +0 -9
  303. package/storybook-static/assets/AdminLayout.CustomSidebarTitleAndIcon.stories-CvAeXUyA.js +0 -4
  304. package/storybook-static/assets/AdminLayout.HeaderSlots.stories-RBFHoSZK.js +0 -7
  305. package/storybook-static/assets/Alert.stories-DKxKtIc0.js +0 -27
  306. package/storybook-static/assets/AlertDialog.stories-BqTpZ_nG.js +0 -43
  307. package/storybook-static/assets/AspectRatio.stories-DPO9QQ5F.js +0 -22
  308. package/storybook-static/assets/Autocomplete-Cpg4CaJe.js +0 -56
  309. package/storybook-static/assets/Autocomplete.stories-CWj4G5fh.js +0 -56
  310. package/storybook-static/assets/Avatar.stories-DPhov_2g.js +0 -12
  311. package/storybook-static/assets/Badge.stories-DFKrRdXq.js +0 -12
  312. package/storybook-static/assets/Breadcrumb.stories-CTE6CZUC.js +0 -25
  313. package/storybook-static/assets/Button.stories-cbt2InL-.js +0 -26
  314. package/storybook-static/assets/Calendar.stories-DRhTw_43.js +0 -3
  315. package/storybook-static/assets/Card.stories-Isf6n_K3.js +0 -15
  316. package/storybook-static/assets/Carousel.stories-Cmg0I3fR.js +0 -15
  317. package/storybook-static/assets/Chart.stories-aQ-fNijT.js +0 -126
  318. package/storybook-static/assets/Checkbox.stories-B7YMXPDc.js +0 -12
  319. package/storybook-static/assets/Collapsible.stories-BUzl17ZZ.js +0 -18
  320. package/storybook-static/assets/Combination-BdQWAuko.js +0 -41
  321. package/storybook-static/assets/Command.stories-DzBlWQs0.js +0 -30
  322. package/storybook-static/assets/ContextMenu.stories-CJlBQyXc.js +0 -31
  323. package/storybook-static/assets/DataTable.Basic.stories-BWYKFDmK.js +0 -6
  324. package/storybook-static/assets/DataTable.Filters.stories-uZdtJk8t.js +0 -21
  325. package/storybook-static/assets/DataTable.Pagination.stories-C5N1khkp.js +0 -24
  326. package/storybook-static/assets/DataTable.SelectionAndActions.stories-FhCqZKvO.js +0 -26
  327. package/storybook-static/assets/DataTable.Sorting.stories-D-k7EtRj.js +0 -6
  328. package/storybook-static/assets/Dialog.stories-C62AF-Gx.js +0 -54
  329. package/storybook-static/assets/Dialog.stories-lrjRwOus.js +0 -18
  330. package/storybook-static/assets/Drawer.stories-CGjkdJeV.js +0 -24
  331. package/storybook-static/assets/DropdownMenu.stories-DkGClRAA.js +0 -35
  332. package/storybook-static/assets/Form.ArrayLayouts.stories-C5d_062d.js +0 -130
  333. package/storybook-static/assets/Form.Autocomplete.stories-CPZPkk4o.js +0 -142
  334. package/storybook-static/assets/Form.Basic.stories-Bhcu3-3n.js +0 -58
  335. package/storybook-static/assets/Form.Complex.stories-QnXh5a7Q.js +0 -361
  336. package/storybook-static/assets/Form.Dynamic.stories-DFW6wIuT.js +0 -502
  337. package/storybook-static/assets/Form.Simple.stories-BhJcyhbE.js +0 -53
  338. package/storybook-static/assets/Form.stories-PFNsMYxO.js +0 -3
  339. package/storybook-static/assets/FormBuilder-BQBBxo_k.js +0 -5
  340. package/storybook-static/assets/HoverCard.stories-CAlQEVn8.js +0 -21
  341. package/storybook-static/assets/Input.stories-CEhODt0V.js +0 -16
  342. package/storybook-static/assets/InputOtp.stories-DSvNP4dS.js +0 -42
  343. package/storybook-static/assets/Label.stories-B3pa8ZLY.js +0 -14
  344. package/storybook-static/assets/Login.stories-C7KQkmR_.js +0 -37
  345. package/storybook-static/assets/Menubar.stories-CHXhSHxc.js +0 -44
  346. package/storybook-static/assets/MonthPicker.stories-BnrOc4fm.js +0 -99
  347. package/storybook-static/assets/MonthRangePicker.stories-55Gk1t-7.js +0 -134
  348. package/storybook-static/assets/NavigationMenu.stories-CXoS080P.js +0 -30
  349. package/storybook-static/assets/Page.stories-GdSJgZ6-.js +0 -91
  350. package/storybook-static/assets/Pagination.stories-BEBwqH4N.js +0 -29
  351. package/storybook-static/assets/Popover.stories-BICy98Cw.js +0 -15
  352. package/storybook-static/assets/Progress.stories-DECHNOME.js +0 -8
  353. package/storybook-static/assets/RadioGroup.stories-DA7-uKfV.js +0 -16
  354. package/storybook-static/assets/Resizable.stories-B99kWkH7.js +0 -25
  355. package/storybook-static/assets/ScrollArea.stories-BqvUAXqU.js +0 -12
  356. package/storybook-static/assets/Section.stories-lFMlFBQn.js +0 -277
  357. package/storybook-static/assets/SectionBuilder-BQW705x0.js +0 -1
  358. package/storybook-static/assets/Select.stories-BsKyZ6Io.js +0 -17
  359. package/storybook-static/assets/Separator.stories-BTDOaOM2.js +0 -17
  360. package/storybook-static/assets/Sheet.stories-Cam1gR6G.js +0 -24
  361. package/storybook-static/assets/Sidebar.stories-DnOa6G7y.js +0 -106
  362. package/storybook-static/assets/Skeleton.stories-BQNIuIe5.js +0 -9
  363. package/storybook-static/assets/Slider.stories-Bslq7hjq.js +0 -6
  364. package/storybook-static/assets/Sonner.stories-D34pBBtI.js +0 -18
  365. package/storybook-static/assets/Switch.stories-Puyb1-Bx.js +0 -3
  366. package/storybook-static/assets/Table.stories-ClZxAhut.js +0 -35
  367. package/storybook-static/assets/Tabs.stories-CURNTETB.js +0 -10
  368. package/storybook-static/assets/Textarea.stories-Cf1ZBrWw.js +0 -17
  369. package/storybook-static/assets/Toggle.stories-CdMHY_bi.js +0 -3
  370. package/storybook-static/assets/ToggleGroup.stories-BM68m1dX.js +0 -13
  371. package/storybook-static/assets/Tooltip.stories-DiQv64dM.js +0 -10
  372. package/storybook-static/assets/accordion-DVgwQcnw.js +0 -1
  373. package/storybook-static/assets/alert-dialog-DCUEwpqm.js +0 -7
  374. package/storybook-static/assets/avatar-BzwOE-mi.js +0 -1
  375. package/storybook-static/assets/axe-HmUsR1st.js +0 -30
  376. package/storybook-static/assets/badge-BnQWua6u.js +0 -1
  377. package/storybook-static/assets/button-0oMkiryo.js +0 -1
  378. package/storybook-static/assets/card-BJpPOzP8.js +0 -1
  379. package/storybook-static/assets/chart-column-DZGb4ZZS.js +0 -6
  380. package/storybook-static/assets/check-B9hBGj6o.js +0 -6
  381. package/storybook-static/assets/checkbox-CyIeaWHX.js +0 -1
  382. package/storybook-static/assets/chevron-down-D_37S6il.js +0 -6
  383. package/storybook-static/assets/chevron-left-BBoN0vbI.js +0 -6
  384. package/storybook-static/assets/chevron-right-B5vIMLxK.js +0 -6
  385. package/storybook-static/assets/circle-C5Lzx6Nx.js +0 -6
  386. package/storybook-static/assets/clean-slate-D1HmMFJM.css +0 -1
  387. package/storybook-static/assets/command-Csa9p8_a.js +0 -6
  388. package/storybook-static/assets/createLucideIcon-BrHXro7t.js +0 -21
  389. package/storybook-static/assets/default-CN_Fo1GY.css +0 -1
  390. package/storybook-static/assets/dependencies-ctrV69dx.js +0 -1
  391. package/storybook-static/assets/dialog-CsnqITTn.js +0 -1
  392. package/storybook-static/assets/dropdown-menu-BWxxwPHL.js +0 -1
  393. package/storybook-static/assets/ellipsis-BRS038RR.js +0 -6
  394. package/storybook-static/assets/grip-vertical-BxXG8KNA.js +0 -6
  395. package/storybook-static/assets/iframe-C9bogcIc.css +0 -1
  396. package/storybook-static/assets/iframe-v7iAhKit.js +0 -1555
  397. package/storybook-static/assets/index-0-qMRXou.js +0 -1
  398. package/storybook-static/assets/index-AvwFFKJc.js +0 -1
  399. package/storybook-static/assets/index-BVDb4dFc.js +0 -1
  400. package/storybook-static/assets/index-B_qx7A5T.js +0 -1
  401. package/storybook-static/assets/index-BdQq_4o_.js +0 -1
  402. package/storybook-static/assets/index-BfiCOk42.js +0 -1
  403. package/storybook-static/assets/index-Bv9yk470.js +0 -1
  404. package/storybook-static/assets/index-Bw1A27Kp.js +0 -1
  405. package/storybook-static/assets/index-ByqivBWx.js +0 -1
  406. package/storybook-static/assets/index-C9Ta0ZTH.js +0 -1
  407. package/storybook-static/assets/index-CDY5kTx5.js +0 -1
  408. package/storybook-static/assets/index-CGnyVRgB.js +0 -1
  409. package/storybook-static/assets/index-CGrAONsN.js +0 -1
  410. package/storybook-static/assets/index-CWjrGFAQ.js +0 -1
  411. package/storybook-static/assets/index-CwBdPBFz.js +0 -9
  412. package/storybook-static/assets/index-D8RXF03I.js +0 -1
  413. package/storybook-static/assets/index-DLIxT4Z7.js +0 -1
  414. package/storybook-static/assets/index-DW48STyt.js +0 -1
  415. package/storybook-static/assets/index-DbaA6-o1.js +0 -1
  416. package/storybook-static/assets/index-Dph_5COR.js +0 -1
  417. package/storybook-static/assets/index-DrN5n71E.js +0 -1
  418. package/storybook-static/assets/index-Tp9IdbR8.js +0 -1
  419. package/storybook-static/assets/index-WyF3-wTE.js +0 -9
  420. package/storybook-static/assets/index-XSmPROEP.js +0 -1
  421. package/storybook-static/assets/index-Z6wF44KX.js +0 -5
  422. package/storybook-static/assets/index-_RPqOjlQ.js +0 -1
  423. package/storybook-static/assets/index-jrimW4QO.js +0 -1
  424. package/storybook-static/assets/index-nqc17SX4.js +0 -1
  425. package/storybook-static/assets/input-11YRd9gD.js +0 -1
  426. package/storybook-static/assets/jsx-runtime-D_zvdyIk.js +0 -9
  427. package/storybook-static/assets/label-Do8ODIVk.js +0 -1
  428. package/storybook-static/assets/lodash-DDwpuhPG.js +0 -73
  429. package/storybook-static/assets/matchers-7Z3WT2CE-T3xScrR7.js +0 -14
  430. package/storybook-static/assets/minimal-modern-BlYVzfQU.css +0 -1
  431. package/storybook-static/assets/popover-CcciSWAw.js +0 -1
  432. package/storybook-static/assets/preload-helper-Dp1pzeXC.js +0 -1
  433. package/storybook-static/assets/radio-group-DiJ0Y_KQ.js +0 -1
  434. package/storybook-static/assets/react-18-Cr9fq_Ip.js +0 -25
  435. package/storybook-static/assets/react-icons.esm-B_ULMmNU.js +0 -1
  436. package/storybook-static/assets/refresh-cw-BmRDhIV_.js +0 -6
  437. package/storybook-static/assets/schemas-CGNYCiJ6.js +0 -18
  438. package/storybook-static/assets/section-factories-DCCY9R35.js +0 -1
  439. package/storybook-static/assets/select-DDrkxaOg.js +0 -6
  440. package/storybook-static/assets/separator-o5SAUnaJ.js +0 -1
  441. package/storybook-static/assets/settings-2-xWGvvbG6.js +0 -6
  442. package/storybook-static/assets/sheet-C7jhU3XE.js +0 -1
  443. package/storybook-static/assets/shopping-cart-BFlrufvo.js +0 -11
  444. package/storybook-static/assets/sidebar-C8hU1Mxy.js +0 -6
  445. package/storybook-static/assets/skeleton-CjDnQs43.js +0 -1
  446. package/storybook-static/assets/spotify-CUDj7g8m.css +0 -1
  447. package/storybook-static/assets/switch-CKGRuk3u.js +0 -1
  448. package/storybook-static/assets/table-CP3vMqFn.js +0 -1
  449. package/storybook-static/assets/tabs-CopK2m3j.js +0 -1
  450. package/storybook-static/assets/textarea-Dw2vruMl.js +0 -1
  451. package/storybook-static/assets/toggle-DmHbWetf.js +0 -16
  452. package/storybook-static/assets/tooltip-_LqYEYFw.js +0 -1
  453. package/storybook-static/assets/trash-2-xdbApPby.js +0 -11
  454. package/storybook-static/assets/utils-D-KgF5mV.js +0 -1
  455. package/storybook-static/assets/x-B1a4fyWM.js +0 -6
  456. package/storybook-static/favicon-wrapper.svg +0 -46
  457. package/storybook-static/favicon.svg +0 -1
  458. package/storybook-static/iframe.html +0 -687
  459. package/storybook-static/index.d.ts +0 -64
  460. package/storybook-static/index.d.ts.map +0 -1
  461. package/storybook-static/index.html +0 -166
  462. package/storybook-static/index.json +0 -1
  463. package/storybook-static/kit/builder/data-table/components/DataTable.d.ts +0 -37
  464. package/storybook-static/kit/builder/data-table/components/DataTable.d.ts.map +0 -1
  465. package/storybook-static/kit/builder/data-table/components/DataTableColumnHeader.d.ts +0 -8
  466. package/storybook-static/kit/builder/data-table/components/DataTableColumnHeader.d.ts.map +0 -1
  467. package/storybook-static/kit/builder/data-table/components/DataTablePagination.d.ts +0 -6
  468. package/storybook-static/kit/builder/data-table/components/DataTablePagination.d.ts.map +0 -1
  469. package/storybook-static/kit/builder/data-table/components/DataTableViewOptions.d.ts +0 -5
  470. package/storybook-static/kit/builder/data-table/components/DataTableViewOptions.d.ts.map +0 -1
  471. package/storybook-static/kit/builder/data-table/index.d.ts +0 -7
  472. package/storybook-static/kit/builder/data-table/index.d.ts.map +0 -1
  473. package/storybook-static/kit/builder/data-table/types.d.ts +0 -27
  474. package/storybook-static/kit/builder/data-table/types.d.ts.map +0 -1
  475. package/storybook-static/kit/builder/data-table/utils/dotAccessor.d.ts +0 -2
  476. package/storybook-static/kit/builder/data-table/utils/dotAccessor.d.ts.map +0 -1
  477. package/storybook-static/kit/builder/dialog/index.d.ts +0 -3
  478. package/storybook-static/kit/builder/dialog/index.d.ts.map +0 -1
  479. package/storybook-static/kit/builder/dialog/provider.d.ts +0 -26
  480. package/storybook-static/kit/builder/dialog/provider.d.ts.map +0 -1
  481. package/storybook-static/kit/builder/form/components/FormBuilder.d.ts +0 -137
  482. package/storybook-static/kit/builder/form/components/FormBuilder.d.ts.map +0 -1
  483. package/storybook-static/kit/builder/form/components/FormBuilderActions.d.ts +0 -20
  484. package/storybook-static/kit/builder/form/components/FormBuilderActions.d.ts.map +0 -1
  485. package/storybook-static/kit/builder/form/components/FormBuilderField.d.ts +0 -12
  486. package/storybook-static/kit/builder/form/components/FormBuilderField.d.ts.map +0 -1
  487. package/storybook-static/kit/builder/form/components/fields/ArrayField.d.ts +0 -3
  488. package/storybook-static/kit/builder/form/components/fields/ArrayField.d.ts.map +0 -1
  489. package/storybook-static/kit/builder/form/components/fields/AutocompleteField.d.ts +0 -3
  490. package/storybook-static/kit/builder/form/components/fields/AutocompleteField.d.ts.map +0 -1
  491. package/storybook-static/kit/builder/form/components/fields/CheckboxField.d.ts +0 -3
  492. package/storybook-static/kit/builder/form/components/fields/CheckboxField.d.ts.map +0 -1
  493. package/storybook-static/kit/builder/form/components/fields/DateField.d.ts +0 -3
  494. package/storybook-static/kit/builder/form/components/fields/DateField.d.ts.map +0 -1
  495. package/storybook-static/kit/builder/form/components/fields/FileField.d.ts +0 -3
  496. package/storybook-static/kit/builder/form/components/fields/FileField.d.ts.map +0 -1
  497. package/storybook-static/kit/builder/form/components/fields/NumberField.d.ts +0 -3
  498. package/storybook-static/kit/builder/form/components/fields/NumberField.d.ts.map +0 -1
  499. package/storybook-static/kit/builder/form/components/fields/ObjectField.d.ts +0 -3
  500. package/storybook-static/kit/builder/form/components/fields/ObjectField.d.ts.map +0 -1
  501. package/storybook-static/kit/builder/form/components/fields/RadioField.d.ts +0 -3
  502. package/storybook-static/kit/builder/form/components/fields/RadioField.d.ts.map +0 -1
  503. package/storybook-static/kit/builder/form/components/fields/SelectField.d.ts +0 -3
  504. package/storybook-static/kit/builder/form/components/fields/SelectField.d.ts.map +0 -1
  505. package/storybook-static/kit/builder/form/components/fields/SwitchField.d.ts +0 -3
  506. package/storybook-static/kit/builder/form/components/fields/SwitchField.d.ts.map +0 -1
  507. package/storybook-static/kit/builder/form/components/fields/TextField.d.ts +0 -3
  508. package/storybook-static/kit/builder/form/components/fields/TextField.d.ts.map +0 -1
  509. package/storybook-static/kit/builder/form/components/fields/TextareaField.d.ts +0 -3
  510. package/storybook-static/kit/builder/form/components/fields/TextareaField.d.ts.map +0 -1
  511. package/storybook-static/kit/builder/form/components/fields/index.d.ts +0 -14
  512. package/storybook-static/kit/builder/form/components/fields/index.d.ts.map +0 -1
  513. package/storybook-static/kit/builder/form/components/fields/types.d.ts +0 -14
  514. package/storybook-static/kit/builder/form/components/fields/types.d.ts.map +0 -1
  515. package/storybook-static/kit/builder/form/components/index.d.ts +0 -4
  516. package/storybook-static/kit/builder/form/components/index.d.ts.map +0 -1
  517. package/storybook-static/kit/builder/form/index.d.ts +0 -3
  518. package/storybook-static/kit/builder/form/index.d.ts.map +0 -1
  519. package/storybook-static/kit/builder/form/utils/common-forms.d.ts +0 -7
  520. package/storybook-static/kit/builder/form/utils/common-forms.d.ts.map +0 -1
  521. package/storybook-static/kit/builder/form/utils/dependencies.d.ts +0 -41
  522. package/storybook-static/kit/builder/form/utils/dependencies.d.ts.map +0 -1
  523. package/storybook-static/kit/builder/form/utils/field-factories.d.ts +0 -23
  524. package/storybook-static/kit/builder/form/utils/field-factories.d.ts.map +0 -1
  525. package/storybook-static/kit/builder/form/utils/index.d.ts +0 -15
  526. package/storybook-static/kit/builder/form/utils/index.d.ts.map +0 -1
  527. package/storybook-static/kit/builder/form/utils/section-factories.d.ts +0 -7
  528. package/storybook-static/kit/builder/form/utils/section-factories.d.ts.map +0 -1
  529. package/storybook-static/kit/builder/form/utils/transformers.d.ts +0 -6
  530. package/storybook-static/kit/builder/form/utils/transformers.d.ts.map +0 -1
  531. package/storybook-static/kit/builder/form/utils/validations.d.ts +0 -13
  532. package/storybook-static/kit/builder/form/utils/validations.d.ts.map +0 -1
  533. package/storybook-static/kit/builder/form/utils/validators.d.ts +0 -8
  534. package/storybook-static/kit/builder/form/utils/validators.d.ts.map +0 -1
  535. package/storybook-static/kit/builder/page/Page.d.ts +0 -48
  536. package/storybook-static/kit/builder/page/Page.d.ts.map +0 -1
  537. package/storybook-static/kit/builder/page/index.d.ts +0 -2
  538. package/storybook-static/kit/builder/page/index.d.ts.map +0 -1
  539. package/storybook-static/kit/builder/section/SectionBuilder.d.ts +0 -3
  540. package/storybook-static/kit/builder/section/SectionBuilder.d.ts.map +0 -1
  541. package/storybook-static/kit/builder/section/index.d.ts +0 -3
  542. package/storybook-static/kit/builder/section/index.d.ts.map +0 -1
  543. package/storybook-static/kit/builder/section/types.d.ts +0 -70
  544. package/storybook-static/kit/builder/section/types.d.ts.map +0 -1
  545. package/storybook-static/kit/builder/stack-dialog/context.d.ts +0 -3
  546. package/storybook-static/kit/builder/stack-dialog/context.d.ts.map +0 -1
  547. package/storybook-static/kit/builder/stack-dialog/hooks.d.ts +0 -6
  548. package/storybook-static/kit/builder/stack-dialog/hooks.d.ts.map +0 -1
  549. package/storybook-static/kit/builder/stack-dialog/index.d.ts +0 -5
  550. package/storybook-static/kit/builder/stack-dialog/index.d.ts.map +0 -1
  551. package/storybook-static/kit/builder/stack-dialog/provider.d.ts +0 -3
  552. package/storybook-static/kit/builder/stack-dialog/provider.d.ts.map +0 -1
  553. package/storybook-static/kit/builder/stack-dialog/renderer.d.ts +0 -6
  554. package/storybook-static/kit/builder/stack-dialog/renderer.d.ts.map +0 -1
  555. package/storybook-static/kit/builder/stack-dialog/types.d.ts +0 -20
  556. package/storybook-static/kit/builder/stack-dialog/types.d.ts.map +0 -1
  557. package/storybook-static/kit/components/autocomplete/Autocomplete.d.ts +0 -53
  558. package/storybook-static/kit/components/autocomplete/Autocomplete.d.ts.map +0 -1
  559. package/storybook-static/kit/components/autocomplete/index.d.ts +0 -4
  560. package/storybook-static/kit/components/autocomplete/index.d.ts.map +0 -1
  561. package/storybook-static/kit/components/autocomplete/types.d.ts +0 -19
  562. package/storybook-static/kit/components/autocomplete/types.d.ts.map +0 -1
  563. package/storybook-static/kit/components/login/Login.d.ts +0 -29
  564. package/storybook-static/kit/components/login/Login.d.ts.map +0 -1
  565. package/storybook-static/kit/components/login/index.d.ts +0 -2
  566. package/storybook-static/kit/components/login/index.d.ts.map +0 -1
  567. package/storybook-static/kit/components/monthpicker/MonthPicker.d.ts +0 -32
  568. package/storybook-static/kit/components/monthpicker/MonthPicker.d.ts.map +0 -1
  569. package/storybook-static/kit/components/monthpicker/MonthRangePicker.d.ts +0 -48
  570. package/storybook-static/kit/components/monthpicker/MonthRangePicker.d.ts.map +0 -1
  571. package/storybook-static/kit/layouts/admin/components/AdminLayout.d.ts +0 -17
  572. package/storybook-static/kit/layouts/admin/components/AdminLayout.d.ts.map +0 -1
  573. package/storybook-static/kit/layouts/admin/components/ThemeToggle.d.ts +0 -5
  574. package/storybook-static/kit/layouts/admin/components/ThemeToggle.d.ts.map +0 -1
  575. package/storybook-static/kit/layouts/admin/hooks/menu.d.ts +0 -13
  576. package/storybook-static/kit/layouts/admin/hooks/menu.d.ts.map +0 -1
  577. package/storybook-static/kit/layouts/admin/providers/AdminMenuProvider.d.ts +0 -7
  578. package/storybook-static/kit/layouts/admin/providers/AdminMenuProvider.d.ts.map +0 -1
  579. package/storybook-static/kit/layouts/admin/types/index.d.ts +0 -27
  580. package/storybook-static/kit/layouts/admin/types/index.d.ts.map +0 -1
  581. package/storybook-static/kit/providers/ThemeProvider.d.ts +0 -14
  582. package/storybook-static/kit/providers/ThemeProvider.d.ts.map +0 -1
  583. package/storybook-static/nunito-sans-bold-italic.woff2 +0 -0
  584. package/storybook-static/nunito-sans-bold.woff2 +0 -0
  585. package/storybook-static/nunito-sans-italic.woff2 +0 -0
  586. package/storybook-static/nunito-sans-regular.woff2 +0 -0
  587. package/storybook-static/project.json +0 -1
  588. package/storybook-static/sb-addons/a11y-5/manager-bundle.js +0 -5
  589. package/storybook-static/sb-addons/essentials-backgrounds-1/manager-bundle.js +0 -3
  590. package/storybook-static/sb-addons/essentials-measure-2/manager-bundle.js +0 -3
  591. package/storybook-static/sb-addons/essentials-outline-3/manager-bundle.js +0 -3
  592. package/storybook-static/sb-addons/interactions-4/manager-bundle.js +0 -57
  593. package/storybook-static/sb-addons/storybook-core-server-presets-0/common-manager-bundle.js +0 -971
  594. package/storybook-static/sb-addons/storysource-6/manager-bundle.js +0 -3
  595. package/storybook-static/sb-common-assets/favicon-wrapper.svg +0 -46
  596. package/storybook-static/sb-common-assets/favicon.svg +0 -1
  597. package/storybook-static/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
  598. package/storybook-static/sb-common-assets/nunito-sans-bold.woff2 +0 -0
  599. package/storybook-static/sb-common-assets/nunito-sans-italic.woff2 +0 -0
  600. package/storybook-static/sb-common-assets/nunito-sans-regular.woff2 +0 -0
  601. package/storybook-static/sb-manager/globals-module-info.js +0 -797
  602. package/storybook-static/sb-manager/globals-runtime.js +0 -69653
  603. package/storybook-static/sb-manager/globals.js +0 -34
  604. package/storybook-static/sb-manager/runtime.js +0 -13181
  605. package/storybook-static/shadcn/hooks/use-mobile.d.ts +0 -2
  606. package/storybook-static/shadcn/hooks/use-mobile.d.ts.map +0 -1
  607. package/storybook-static/shadcn/lib/utils.d.ts +0 -3
  608. package/storybook-static/shadcn/lib/utils.d.ts.map +0 -1
  609. package/storybook-static/shadcn/ui/accordion.d.ts +0 -8
  610. package/storybook-static/shadcn/ui/accordion.d.ts.map +0 -1
  611. package/storybook-static/shadcn/ui/alert-dialog.d.ts +0 -15
  612. package/storybook-static/shadcn/ui/alert-dialog.d.ts.map +0 -1
  613. package/storybook-static/shadcn/ui/alert.d.ts +0 -10
  614. package/storybook-static/shadcn/ui/alert.d.ts.map +0 -1
  615. package/storybook-static/shadcn/ui/aspect-ratio.d.ts +0 -4
  616. package/storybook-static/shadcn/ui/aspect-ratio.d.ts.map +0 -1
  617. package/storybook-static/shadcn/ui/avatar.d.ts +0 -7
  618. package/storybook-static/shadcn/ui/avatar.d.ts.map +0 -1
  619. package/storybook-static/shadcn/ui/badge.d.ts +0 -10
  620. package/storybook-static/shadcn/ui/badge.d.ts.map +0 -1
  621. package/storybook-static/shadcn/ui/breadcrumb.d.ts +0 -12
  622. package/storybook-static/shadcn/ui/breadcrumb.d.ts.map +0 -1
  623. package/storybook-static/shadcn/ui/button.d.ts +0 -11
  624. package/storybook-static/shadcn/ui/button.d.ts.map +0 -1
  625. package/storybook-static/shadcn/ui/calendar.d.ts +0 -9
  626. package/storybook-static/shadcn/ui/calendar.d.ts.map +0 -1
  627. package/storybook-static/shadcn/ui/card.d.ts +0 -10
  628. package/storybook-static/shadcn/ui/card.d.ts.map +0 -1
  629. package/storybook-static/shadcn/ui/carousel.d.ts +0 -20
  630. package/storybook-static/shadcn/ui/carousel.d.ts.map +0 -1
  631. package/storybook-static/shadcn/ui/chart.d.ts +0 -41
  632. package/storybook-static/shadcn/ui/chart.d.ts.map +0 -1
  633. package/storybook-static/shadcn/ui/checkbox.d.ts +0 -5
  634. package/storybook-static/shadcn/ui/checkbox.d.ts.map +0 -1
  635. package/storybook-static/shadcn/ui/collapsible.d.ts +0 -6
  636. package/storybook-static/shadcn/ui/collapsible.d.ts.map +0 -1
  637. package/storybook-static/shadcn/ui/command.d.ts +0 -19
  638. package/storybook-static/shadcn/ui/command.d.ts.map +0 -1
  639. package/storybook-static/shadcn/ui/context-menu.d.ts +0 -26
  640. package/storybook-static/shadcn/ui/context-menu.d.ts.map +0 -1
  641. package/storybook-static/shadcn/ui/dialog.d.ts +0 -16
  642. package/storybook-static/shadcn/ui/dialog.d.ts.map +0 -1
  643. package/storybook-static/shadcn/ui/drawer.d.ts +0 -14
  644. package/storybook-static/shadcn/ui/drawer.d.ts.map +0 -1
  645. package/storybook-static/shadcn/ui/dropdown-menu.d.ts +0 -26
  646. package/storybook-static/shadcn/ui/dropdown-menu.d.ts.map +0 -1
  647. package/storybook-static/shadcn/ui/form.d.ts +0 -25
  648. package/storybook-static/shadcn/ui/form.d.ts.map +0 -1
  649. package/storybook-static/shadcn/ui/hover-card.d.ts +0 -7
  650. package/storybook-static/shadcn/ui/hover-card.d.ts.map +0 -1
  651. package/storybook-static/shadcn/ui/input-otp.d.ts +0 -12
  652. package/storybook-static/shadcn/ui/input-otp.d.ts.map +0 -1
  653. package/storybook-static/shadcn/ui/input.d.ts +0 -4
  654. package/storybook-static/shadcn/ui/input.d.ts.map +0 -1
  655. package/storybook-static/shadcn/ui/label.d.ts +0 -5
  656. package/storybook-static/shadcn/ui/label.d.ts.map +0 -1
  657. package/storybook-static/shadcn/ui/menubar.d.ts +0 -27
  658. package/storybook-static/shadcn/ui/menubar.d.ts.map +0 -1
  659. package/storybook-static/shadcn/ui/navigation-menu.d.ts +0 -15
  660. package/storybook-static/shadcn/ui/navigation-menu.d.ts.map +0 -1
  661. package/storybook-static/shadcn/ui/pagination.d.ts +0 -14
  662. package/storybook-static/shadcn/ui/pagination.d.ts.map +0 -1
  663. package/storybook-static/shadcn/ui/popover.d.ts +0 -8
  664. package/storybook-static/shadcn/ui/popover.d.ts.map +0 -1
  665. package/storybook-static/shadcn/ui/progress.d.ts +0 -5
  666. package/storybook-static/shadcn/ui/progress.d.ts.map +0 -1
  667. package/storybook-static/shadcn/ui/radio-group.d.ts +0 -6
  668. package/storybook-static/shadcn/ui/radio-group.d.ts.map +0 -1
  669. package/storybook-static/shadcn/ui/resizable.d.ts +0 -9
  670. package/storybook-static/shadcn/ui/resizable.d.ts.map +0 -1
  671. package/storybook-static/shadcn/ui/scroll-area.d.ts +0 -6
  672. package/storybook-static/shadcn/ui/scroll-area.d.ts.map +0 -1
  673. package/storybook-static/shadcn/ui/select.d.ts +0 -16
  674. package/storybook-static/shadcn/ui/select.d.ts.map +0 -1
  675. package/storybook-static/shadcn/ui/separator.d.ts +0 -5
  676. package/storybook-static/shadcn/ui/separator.d.ts.map +0 -1
  677. package/storybook-static/shadcn/ui/sheet.d.ts +0 -14
  678. package/storybook-static/shadcn/ui/sheet.d.ts.map +0 -1
  679. package/storybook-static/shadcn/ui/sidebar.d.ts +0 -70
  680. package/storybook-static/shadcn/ui/sidebar.d.ts.map +0 -1
  681. package/storybook-static/shadcn/ui/skeleton.d.ts +0 -3
  682. package/storybook-static/shadcn/ui/skeleton.d.ts.map +0 -1
  683. package/storybook-static/shadcn/ui/slider.d.ts +0 -5
  684. package/storybook-static/shadcn/ui/slider.d.ts.map +0 -1
  685. package/storybook-static/shadcn/ui/sonner.d.ts +0 -4
  686. package/storybook-static/shadcn/ui/sonner.d.ts.map +0 -1
  687. package/storybook-static/shadcn/ui/switch.d.ts +0 -5
  688. package/storybook-static/shadcn/ui/switch.d.ts.map +0 -1
  689. package/storybook-static/shadcn/ui/table.d.ts +0 -11
  690. package/storybook-static/shadcn/ui/table.d.ts.map +0 -1
  691. package/storybook-static/shadcn/ui/tabs.d.ts +0 -8
  692. package/storybook-static/shadcn/ui/tabs.d.ts.map +0 -1
  693. package/storybook-static/shadcn/ui/textarea.d.ts +0 -4
  694. package/storybook-static/shadcn/ui/textarea.d.ts.map +0 -1
  695. package/storybook-static/shadcn/ui/toggle-group.d.ts +0 -8
  696. package/storybook-static/shadcn/ui/toggle-group.d.ts.map +0 -1
  697. package/storybook-static/shadcn/ui/toggle.d.ts +0 -10
  698. package/storybook-static/shadcn/ui/toggle.d.ts.map +0 -1
  699. package/storybook-static/shadcn/ui/tooltip.d.ts +0 -8
  700. package/storybook-static/shadcn/ui/tooltip.d.ts.map +0 -1
  701. package/storybook-static/vite-inject-mocker-entry.js +0 -18
@@ -1,664 +1,671 @@
1
- import { useCombobox } from 'downshift';
2
- import { Check, ChevronsUpDown, Loader2, X } from 'lucide-react';
3
- import {
4
- forwardRef,
5
- ReactElement,
6
- RefAttributes,
7
- useCallback,
8
- useEffect,
9
- useImperativeHandle,
10
- useMemo,
11
- useRef,
12
- useState
13
- } from 'react';
14
- import { useDebounce } from 'use-debounce';
15
- import { cn } from '../../../shadcn/lib/utils';
16
- import { Badge } from '../../../shadcn/ui/badge';
17
- import {
18
- Popover,
19
- PopoverContent,
20
- PopoverTrigger,
21
- } from '../../../shadcn/ui/popover';
22
- import type {
23
- AutocompleteFetcher,
24
- AutocompleteFetchResult,
25
- AutocompleteMode,
26
- AutocompleteOption,
27
- } from './types';
28
-
29
- export type AutocompleteProps<T = unknown> = {
30
- mode: AutocompleteMode;
31
- options?: AutocompleteOption<T>[];
32
- fetcher?: AutocompleteFetcher<T>;
33
- fetcherFilter?: () => Record<string, string | number | boolean | null>;
34
- pageSize?: number;
35
- value?: string | number | null | Array<string | number>;
36
- onChange?: (
37
- value: string | number | null | Array<string | number>,
38
- selected: AutocompleteOption<T> | AutocompleteOption<T>[] | null,
39
- raw?: T | T[] | null,
40
- ) => void;
41
- placeholder?: string;
42
- disabled?: boolean;
43
- multiple?: boolean;
44
- className?: string;
45
- chipVariant?: 'default' | 'secondary' | 'destructive' | 'outline';
46
- chipClassName?: string;
47
- emptyText?: string;
48
- renderOption?: (
49
- option: AutocompleteOption<T>,
50
- selected: boolean,
51
- ) => React.ReactNode;
52
- defaultOpen?: boolean;
53
- defaultValue?: string | number | null | Array<string | number>;
54
- allowCustomValue?: boolean;
55
- clearable?: boolean;
56
- initialSelectedOptions?: AutocompleteOption<T> | AutocompleteOption<T>[];
57
- loadSelected?: (
58
- values: Array<string | number>,
59
- ) => Promise<AutocompleteOption<T>[]>;
60
- };
61
-
62
- const DEFAULT_PAGE_SIZE = 50;
63
-
64
- export function Autocomplete<T = unknown>({
65
- mode = 'client',
66
- options = [],
67
- fetcher,
68
- fetcherFilter,
69
- pageSize = DEFAULT_PAGE_SIZE,
70
- value: controlledValue,
71
- onChange,
72
- placeholder = 'Search or select...',
73
- disabled = false,
74
- multiple = false,
75
- className,
76
- chipVariant = 'secondary',
77
- chipClassName,
78
- emptyText = 'No results found',
79
- renderOption,
80
- defaultOpen,
81
- defaultValue,
82
- allowCustomValue = false,
83
- clearable = true,
84
- initialSelectedOptions,
85
- loadSelected,
86
- }: AutocompleteProps<T>, ref?: any) {
87
- const isMultiple = !!multiple;
88
- const isControlled = controlledValue !== undefined;
89
-
90
- // Internal value state
91
- const [internalValue, setInternalValue] = useState<
92
- string | number | null | Array<string | number>
93
- >(() => {
94
- if (defaultValue !== undefined) return defaultValue;
95
- return isMultiple ? [] : null;
96
- });
97
-
98
- const currentValue = isControlled ? controlledValue : internalValue;
99
-
100
- // Label and raw data maps
101
- const labelMapRef = useRef<Map<string | number, string>>(new Map());
102
- const rawMapRef = useRef<Map<string | number, T>>(new Map());
103
-
104
- const storeOption = useCallback((opt: AutocompleteOption<T>) => {
105
- labelMapRef.current.set(opt.value, opt.label);
106
- if (opt.raw !== undefined) {
107
- rawMapRef.current.set(opt.value, opt.raw);
108
- }
109
- }, []);
110
-
111
- // Immediately populate labels for initial values (runs once on mount)
112
- if (labelMapRef.current.size === 0 && currentValue) {
113
- const values = Array.isArray(currentValue) ? currentValue : [currentValue];
114
- // First, store initialSelectedOptions if provided
115
- if (initialSelectedOptions) {
116
- const arr = Array.isArray(initialSelectedOptions)
117
- ? initialSelectedOptions
118
- : [initialSelectedOptions];
119
- arr.forEach((opt) => {
120
- labelMapRef.current.set(opt.value, opt.label);
121
- if (opt.raw !== undefined) {
122
- rawMapRef.current.set(opt.value, opt.raw);
123
- }
124
- });
125
- }
126
- // Then look up missing values in options array
127
- values.forEach((val) => {
128
- if (!labelMapRef.current.has(val)) {
129
- const option = options.find((opt) => opt.value === val);
130
- if (option) {
131
- labelMapRef.current.set(option.value, option.label);
132
- if (option.raw !== undefined) {
133
- rawMapRef.current.set(option.value, option.raw);
134
- }
135
- }
136
- }
137
- });
138
- }
139
-
140
- // Data state
141
- const [items, setItems] = useState<AutocompleteOption<T>[]>([]);
142
- const [loading, setLoading] = useState(false);
143
- const [hasMore, setHasMore] = useState(false);
144
- const [page, setPage] = useState(1);
145
- const [searchInput, setSearchInput] = useState('');
146
- const [debouncedSearch] = useDebounce(searchInput, 300);
147
- const [clearCounter, setClearCounter] = useState(0);
148
-
149
- // Popover state
150
- const [isOpen, setIsOpen] = useState(!!defaultOpen);
151
-
152
- // Clear input in multiple mode after selection
153
- useEffect(() => {
154
- if (clearCounter >= 0) {
155
- setSearchInput('');
156
- }
157
- }, [clearCounter]);
158
-
159
- // Load data
160
- const loadData = useCallback(
161
- async (pageNum: number, search: string) => {
162
- if (mode === 'server') {
163
- if (!fetcher) return;
164
- setLoading(true);
165
- try {
166
- const res: AutocompleteFetchResult<T> = await fetcher({
167
- search,
168
- moreFilter: fetcherFilter,
169
- cursor: null,
170
- page: pageNum,
171
- pageSize,
172
- });
173
- res.items.forEach(storeOption);
174
- setItems((prev) =>
175
- pageNum === 1 ? res.items : [...prev, ...res.items],
176
- );
177
- setHasMore(!!res.hasMore);
178
- } catch (_error) {
179
- if (pageNum === 1) setItems([]);
180
- setHasMore(false);
181
- } finally {
182
- setLoading(false);
183
- }
184
- } else {
185
- // Client mode
186
- const filtered = search
187
- ? options.filter((o) =>
188
- o.label.toLowerCase().includes(search.toLowerCase()),
189
- )
190
- : options;
191
- options.forEach(storeOption);
192
- const start = (pageNum - 1) * pageSize;
193
- const slice = filtered.slice(start, start + pageSize);
194
- setItems((prev) => (pageNum === 1 ? slice : [...prev, ...slice]));
195
- setHasMore(start + pageSize < filtered.length);
196
- }
197
- },
198
- [mode, fetcher, fetcherFilter, options, pageSize, storeOption],
199
- );
200
-
201
- // Reset and load on search change
202
- useEffect(() => {
203
- if (!isOpen) return;
204
- setPage(1);
205
- loadData(1, debouncedSearch);
206
- // eslint-disable-next-line react-hooks/exhaustive-deps
207
- }, [isOpen, debouncedSearch, loadData]);
208
-
209
- // Load more pages
210
- useEffect(() => {
211
- if (!isOpen || page <= 1) return;
212
- loadData(page, debouncedSearch);
213
- // eslint-disable-next-line react-hooks/exhaustive-deps
214
- }, [isOpen, page, loadData, debouncedSearch]);
215
-
216
- // Store initial/selected options (takes precedence)
217
- useEffect(() => {
218
- if (initialSelectedOptions) {
219
- const arr = Array.isArray(initialSelectedOptions)
220
- ? initialSelectedOptions
221
- : [initialSelectedOptions];
222
- arr.forEach(storeOption);
223
- }
224
- }, [initialSelectedOptions, storeOption]);
225
-
226
- // Auto-populate missing initial options from provided options array
227
- useEffect(() => {
228
- if (
229
- !currentValue ||
230
- (Array.isArray(currentValue) && currentValue.length === 0)
231
- )
232
- return;
233
-
234
- const values = Array.isArray(currentValue) ? currentValue : [currentValue];
235
-
236
- // Only look up values that are missing (not in label map)
237
- const missingValues = values.filter((v) => !labelMapRef.current.has(v));
238
-
239
- if (missingValues.length === 0) return;
240
-
241
- // Look up missing values in the options array
242
- missingValues.forEach((val) => {
243
- const option = options.find((opt) => opt.value === val);
244
- if (option) {
245
- storeOption(option);
246
- }
247
- });
248
- }, [currentValue, options, storeOption]);
249
-
250
- // Load selected labels on mount for initial values
251
- const hasLoadedInitial = useRef(false);
252
- const [, setLabelsLoadedCounter] = useState(0);
253
-
254
- useEffect(() => {
255
- // Only run once on mount
256
- if (!loadSelected || hasLoadedInitial.current) return;
257
- if (!currentValue) return;
258
-
259
- const values = Array.isArray(currentValue) ? currentValue : [currentValue];
260
- if (values.length === 0) return;
261
-
262
- // Check if any values are missing labels
263
- const missing = values.filter((v) => !labelMapRef.current.has(v));
264
- if (missing.length === 0) {
265
- hasLoadedInitial.current = true;
266
- return;
267
- }
268
-
269
- hasLoadedInitial.current = true;
270
- let cancelled = false;
271
- loadSelected(missing)
272
- .then((opts) => {
273
- if (!cancelled && opts.length > 0) {
274
- opts.forEach(storeOption);
275
- // Only trigger re-render if we actually stored something
276
- setLabelsLoadedCounter((c) => c + 1);
277
- }
278
- // eslint-disable-next-line @typescript-eslint/no-empty-function
279
- })
280
- .catch(() => { });
281
- return () => {
282
- cancelled = true;
283
- };
284
- // eslint-disable-next-line react-hooks/exhaustive-deps
285
- }, [loadSelected, storeOption, currentValue]); // Only run once on mount - uses closure values
286
-
287
- // Load selected labels if missing when dropdown opens
288
- useEffect(() => {
289
- if (!loadSelected || !isOpen) return;
290
- const values = Array.isArray(currentValue)
291
- ? currentValue
292
- : currentValue
293
- ? [currentValue]
294
- : [];
295
- const missing = values.filter((v) => !labelMapRef.current.has(v));
296
- if (missing.length === 0) return;
297
-
298
- let cancelled = false;
299
- loadSelected(missing)
300
- .then((opts) => {
301
- if (!cancelled) opts.forEach(storeOption);
302
- // eslint-disable-next-line @typescript-eslint/no-empty-function
303
- })
304
- .catch(() => { });
305
- return () => {
306
- cancelled = true;
307
- };
308
- }, [currentValue, loadSelected, isOpen, storeOption]);
309
-
310
- // Get label helper
311
- const getLabel = useCallback((v: string | number) => {
312
- return labelMapRef.current.get(v) ?? String(v);
313
- }, []);
314
-
315
- // Selected items for display
316
- const selectedItems = useMemo(() => {
317
- if (!isMultiple) {
318
- if (
319
- currentValue === null ||
320
- currentValue === undefined ||
321
- Array.isArray(currentValue)
322
- )
323
- return [];
324
- return [
325
- {
326
- value: currentValue,
327
- label: getLabel(currentValue),
328
- raw: rawMapRef.current.get(currentValue),
329
- },
330
- ];
331
- }
332
- const values = Array.isArray(currentValue) ? currentValue : [];
333
- return values.map((v) => ({
334
- value: v,
335
- label: getLabel(v),
336
- raw: rawMapRef.current.get(v),
337
- }));
338
- // eslint-disable-next-line react-hooks/exhaustive-deps
339
- }, [currentValue, isMultiple, getLabel]); // labelsLoadedCounter triggers re-compute when loadSelected completes
340
-
341
- // Handle selection
342
- const handleSelect = useCallback(
343
- (item: AutocompleteOption<T> | null) => {
344
- if (!item) return;
345
- storeOption(item);
346
-
347
- if (isMultiple) {
348
- const values = Array.isArray(currentValue) ? currentValue : [];
349
- const exists = values.includes(item.value);
350
-
351
- // Skip if already selected (don't toggle), but still clear the search
352
- if (exists) {
353
- setClearCounter((c) => (c + 1));
354
- return;
355
- }
356
-
357
- const newValues = [...values, item.value];
358
-
359
- if (!isControlled) setInternalValue(newValues);
360
- const newOptions = newValues.map((v) => ({
361
- value: v,
362
- label: getLabel(v),
363
- raw: rawMapRef.current.get(v),
364
- }));
365
- const raws = newOptions
366
- .map((o) => o.raw)
367
- .filter((r): r is T => r !== undefined);
368
- onChange?.(newValues, newOptions, raws);
369
-
370
- // Trigger input clear
371
- setClearCounter((c) => (c + 1));
372
- } else {
373
- if (!isControlled) setInternalValue(item.value);
374
- onChange?.(item.value, item, item.raw ?? null);
375
- setIsOpen(false);
376
- }
377
- },
378
- [isMultiple, currentValue, isControlled, onChange, getLabel, storeOption],
379
- );
380
-
381
- // Handle remove chip
382
- const handleRemove = useCallback(
383
- (valueToRemove: string | number) => {
384
- const values = Array.isArray(currentValue) ? currentValue : [];
385
- const newValues = values.filter((v) => v !== valueToRemove);
386
- if (!isControlled) setInternalValue(newValues);
387
- const newOptions = newValues.map((v) => ({
388
- value: v,
389
- label: getLabel(v),
390
- raw: rawMapRef.current.get(v),
391
- }));
392
- const raws = newOptions
393
- .map((o) => o.raw)
394
- .filter((r): r is T => r !== undefined);
395
- onChange?.(newValues, newOptions, raws);
396
- },
397
- [currentValue, isControlled, onChange, getLabel],
398
- );
399
-
400
- // Handle clear
401
- const handleClear = useCallback(() => {
402
- const newValue = isMultiple ? [] : null;
403
- if (!isControlled) setInternalValue(newValue);
404
- onChange?.(newValue, isMultiple ? [] : null, isMultiple ? [] : null);
405
- setSearchInput('');
406
- }, [isMultiple, isControlled, onChange]);
407
-
408
- // Handle custom value creation
409
- const handleCreateCustom = useCallback(() => {
410
- const trimmed = searchInput.trim();
411
- if (!trimmed || !allowCustomValue) return;
412
-
413
- const newOption: AutocompleteOption<T> = { value: trimmed, label: trimmed };
414
- storeOption(newOption);
415
-
416
- if (isMultiple) {
417
- const values = Array.isArray(currentValue) ? currentValue : [];
418
- if (values.includes(trimmed)) return;
419
- const newValues = [...values, trimmed];
420
- if (!isControlled) setInternalValue(newValues);
421
- const newOptions = newValues.map((v) => ({
422
- value: v,
423
- label: getLabel(v),
424
- raw: rawMapRef.current.get(v),
425
- }));
426
- onChange?.(newValues, newOptions, []);
427
- setSearchInput('');
428
- } else {
429
- if (!isControlled) setInternalValue(trimmed);
430
- onChange?.(trimmed, newOption, null);
431
- setSearchInput('');
432
- setIsOpen(false);
433
- }
434
- }, [
435
- searchInput,
436
- allowCustomValue,
437
- isMultiple,
438
- currentValue,
439
- isControlled,
440
- onChange,
441
- getLabel,
442
- storeOption,
443
- ]);
444
-
445
- // Compute input value based on mode and state
446
- const computedInputValue = useMemo(() => {
447
- // In multiple mode or when dropdown is open, show search input
448
- if (isMultiple || isOpen) {
449
- return searchInput;
450
- }
451
- // In single mode when closed, show selected item label
452
- if (selectedItems.length > 0) {
453
- return selectedItems[0].label;
454
- }
455
- return '';
456
- }, [isMultiple, isOpen, searchInput, selectedItems]);
457
-
458
- // Downshift
459
- const { getInputProps, getItemProps, getMenuProps, highlightedIndex } =
460
- useCombobox({
461
- items,
462
- itemToString: (item) => item?.label ?? '',
463
- selectedItem: isMultiple ? null : (selectedItems[0] ?? null),
464
- onSelectedItemChange: ({ selectedItem }) => handleSelect(selectedItem),
465
- isOpen,
466
- onIsOpenChange: ({ isOpen: newIsOpen }) => setIsOpen(newIsOpen ?? false),
467
- inputValue: computedInputValue,
468
- onInputValueChange: ({ inputValue }) => setSearchInput(inputValue ?? ''),
469
- });
470
-
471
- // Refs
472
- const parentRef = useRef<HTMLDivElement>(null);
473
- const inputRef = useRef<HTMLInputElement>(null);
474
-
475
- // Stable ref callback for merging Downshift's ref with our parentRef
476
- const menuRefCallback = useCallback((node: HTMLDivElement | null) => {
477
- parentRef.current = node;
478
- }, []);
479
-
480
- const handleScroll = useCallback(() => {
481
- if (!parentRef.current || !hasMore || loading) return;
482
-
483
- const { scrollTop, scrollHeight, clientHeight } = parentRef.current;
484
- const scrolledToBottom = scrollHeight - scrollTop - clientHeight < 50;
485
-
486
- if (scrolledToBottom) {
487
- setPage((p) => p + 1);
488
- }
489
- }, [hasMore, loading]);
490
-
491
- useEffect(() => {
492
- const element = parentRef.current;
493
- if (!element) return;
494
-
495
- element.addEventListener('scroll', handleScroll);
496
- return () => element.removeEventListener('scroll', handleScroll);
497
- }, [handleScroll]);
498
-
499
- useImperativeHandle(
500
- ref,
501
- () => ({
502
- reset: handleClear,
503
- }),
504
- []
505
- );
506
-
507
- const showClearButton =
508
- clearable &&
509
- ((isMultiple && selectedItems.length > 0) ||
510
- (!isMultiple &&
511
- currentValue !== null &&
512
- currentValue !== undefined &&
513
- !Array.isArray(currentValue)));
514
-
515
- return (
516
- <Popover open={isOpen} onOpenChange={setIsOpen}>
517
- <PopoverTrigger asChild>
518
- <div
519
- className={cn(
520
- 'flex min-h-10 w-full items-center gap-2 rounded-md border border-input bg-background px-3 py-2 text-sm',
521
- 'ring-offset-background',
522
- 'focus-within:outline-none focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2',
523
- disabled && 'cursor-not-allowed opacity-50',
524
- className,
525
- )}
526
- >
527
- {isMultiple && (
528
- <div className="flex flex-wrap gap-1">
529
- {selectedItems.map((item) => (
530
- <Badge
531
- key={item.value}
532
- variant={chipVariant}
533
- className={cn('gap-1', chipClassName)}
534
- >
535
- <span className="max-w-[150px] truncate">{item.label}</span>
536
- <button
537
- type="button"
538
- onClick={(e) => {
539
- e.stopPropagation();
540
- handleRemove(item.value);
541
- }}
542
- className="rounded-sm opacity-70 hover:opacity-100"
543
- >
544
- <X className="h-3 w-3" />
545
- </button>
546
- </Badge>
547
- ))}
548
- </div>
549
- )}
550
- <input
551
- {...getInputProps({
552
- ref: inputRef,
553
- placeholder,
554
- disabled,
555
- onClick: () => {
556
- if (!isOpen) setIsOpen(true);
557
- },
558
- onKeyDown: (e) => {
559
- if (
560
- e.key === 'Enter' &&
561
- allowCustomValue &&
562
- searchInput.trim() &&
563
- items.length === 0
564
- ) {
565
- e.preventDefault();
566
- handleCreateCustom();
567
- }
568
- },
569
- })}
570
- className="flex-1 bg-transparent outline-none placeholder:text-muted-foreground min-w-[120px]"
571
- />
572
- <div className="flex items-center gap-2 shrink-0">
573
- {showClearButton && (
574
- <button
575
- type="button"
576
- onClick={(e) => {
577
- e.stopPropagation();
578
- handleClear();
579
- }}
580
- className="rounded-sm opacity-70 hover:opacity-100"
581
- >
582
- <X className="h-4 w-4" />
583
- </button>
584
- )}
585
- <ChevronsUpDown className="h-4 w-4 opacity-50" />
586
- </div>
587
- </div>
588
- </PopoverTrigger>
589
- <PopoverContent
590
- className="p-0"
591
- style={{ width: 'var(--radix-popover-trigger-width)' }}
592
- align="start"
593
- onOpenAutoFocus={(e) => e.preventDefault()}
594
- >
595
- <div
596
- {...getMenuProps({
597
- ref: menuRefCallback,
598
- })}
599
- className="max-h-[300px] overflow-auto"
600
- >
601
- {loading && items.length === 0 ? (
602
- <div className="flex items-center justify-center py-6">
603
- <Loader2 className="h-4 w-4 animate-spin mr-2" />
604
- <span className="text-sm text-muted-foreground">Loading...</span>
605
- </div>
606
- ) : items.length === 0 ? (
607
- <div className="py-6 text-center text-sm text-muted-foreground">
608
- {allowCustomValue && searchInput.trim() ? (
609
- <>Press Enter to add &quot;{searchInput.trim()}&quot;</>
610
- ) : (
611
- emptyText
612
- )}
613
- </div>
614
- ) : (
615
- items.map((item, index) => {
616
- const isSelected = isMultiple
617
- ? Array.isArray(currentValue) &&
618
- currentValue.includes(item.value)
619
- : currentValue === item.value;
620
- const isHighlighted = highlightedIndex === index;
621
-
622
- return (
623
- <div
624
- key={item.value}
625
- {...getItemProps({ item, index })}
626
- className={cn(
627
- 'flex cursor-pointer items-center justify-between px-2 py-2 text-sm outline-none transition-colors',
628
- isHighlighted && 'bg-accent text-accent-foreground',
629
- isSelected && 'font-medium',
630
- )}
631
- >
632
- <div className="flex-1 truncate">
633
- {renderOption ? renderOption(item, isSelected) : item.label}
634
- </div>
635
- {isSelected && <Check className="h-4 w-4 shrink-0" />}
636
- </div>
637
- );
638
- })
639
- )}
640
- {hasMore && items.length > 0 && (
641
- <div className="flex items-center justify-center border-t py-2">
642
- {loading ? (
643
- <>
644
- <Loader2 className="h-3 w-3 animate-spin mr-1" />
645
- <span className="text-xs text-muted-foreground">
646
- Loading more...
647
- </span>
648
- </>
649
- ) : (
650
- <span className="text-xs text-muted-foreground">
651
- Scroll for more
652
- </span>
653
- )}
654
- </div>
655
- )}
656
- </div>
657
- </PopoverContent>
658
- </Popover>
659
- );
660
- }
661
-
662
- export const ForwardedRefAutocomplete = forwardRef(Autocomplete) as <T>(props: AutocompleteProps<T> & RefAttributes<any>) => (ReactElement | null);
663
-
664
- export default Autocomplete;
1
+ import { useCombobox } from 'downshift';
2
+ import { Check, ChevronsUpDown, Loader2, X } from 'lucide-react';
3
+ import {
4
+ forwardRef,
5
+ ReactElement,
6
+ RefAttributes,
7
+ useCallback,
8
+ useEffect,
9
+ useImperativeHandle,
10
+ useMemo,
11
+ useRef,
12
+ useState
13
+ } from 'react';
14
+ import { useDebounce } from 'use-debounce';
15
+ import { cn } from '../../../shadcn/lib/utils';
16
+ import { Badge } from '../../../shadcn/ui/badge';
17
+ import {
18
+ Popover,
19
+ PopoverContent,
20
+ PopoverTrigger,
21
+ } from '../../../shadcn/ui/popover';
22
+ import type {
23
+ AutocompleteFetcher,
24
+ AutocompleteFetchResult,
25
+ AutocompleteMode,
26
+ AutocompleteOption,
27
+ } from './types';
28
+
29
+ export type AutocompleteProps<T = unknown> = {
30
+ mode: AutocompleteMode;
31
+ options?: AutocompleteOption<T>[];
32
+ fetcher?: AutocompleteFetcher<T>;
33
+ fetcherFilter?: () => Record<string, string | number | boolean | null>;
34
+ pageSize?: number;
35
+ value?: string | number | null | Array<string | number>;
36
+ onChange?: (
37
+ value: string | number | null | Array<string | number>,
38
+ selected: AutocompleteOption<T> | AutocompleteOption<T>[] | null,
39
+ raw?: T | T[] | null,
40
+ ) => void;
41
+ placeholder?: string;
42
+ disabled?: boolean;
43
+ multiple?: boolean;
44
+ className?: string;
45
+ width?: string | number;
46
+ chipVariant?: 'default' | 'secondary' | 'destructive' | 'outline';
47
+ chipClassName?: string;
48
+ emptyText?: string;
49
+ renderOption?: (
50
+ option: AutocompleteOption<T>,
51
+ selected: boolean,
52
+ ) => React.ReactNode;
53
+ defaultOpen?: boolean;
54
+ defaultValue?: string | number | null | Array<string | number>;
55
+ allowCustomValue?: boolean;
56
+ clearable?: boolean;
57
+ initialSelectedOptions?: AutocompleteOption<T> | AutocompleteOption<T>[];
58
+ loadSelected?: (
59
+ values: Array<string | number>,
60
+ ) => Promise<AutocompleteOption<T>[]>;
61
+ };
62
+
63
+ const DEFAULT_PAGE_SIZE = 50;
64
+
65
+ export function Autocomplete<T = unknown>({
66
+ mode = 'client',
67
+ options = [],
68
+ fetcher,
69
+ fetcherFilter,
70
+ pageSize = DEFAULT_PAGE_SIZE,
71
+ value: controlledValue,
72
+ onChange,
73
+ placeholder = 'Search or select...',
74
+ disabled = false,
75
+ multiple = false,
76
+ className,
77
+ width,
78
+ chipVariant = 'secondary',
79
+ chipClassName,
80
+ emptyText = 'No results found',
81
+ renderOption,
82
+ defaultOpen,
83
+ defaultValue,
84
+ allowCustomValue = false,
85
+ clearable = true,
86
+ initialSelectedOptions,
87
+ loadSelected,
88
+ }: AutocompleteProps<T>, ref?: any) {
89
+ const isMultiple = !!multiple;
90
+ const isControlled = controlledValue !== undefined;
91
+
92
+ // Internal value state
93
+ const [internalValue, setInternalValue] = useState<
94
+ string | number | null | Array<string | number>
95
+ >(() => {
96
+ if (defaultValue !== undefined) return defaultValue;
97
+ return isMultiple ? [] : null;
98
+ });
99
+
100
+ const currentValue = isControlled ? controlledValue : internalValue;
101
+
102
+ // Label and raw data maps
103
+ const labelMapRef = useRef<Map<string | number, string>>(new Map());
104
+ const rawMapRef = useRef<Map<string | number, T>>(new Map());
105
+
106
+ const storeOption = useCallback((opt: AutocompleteOption<T>) => {
107
+ labelMapRef.current.set(opt.value, opt.label);
108
+ if (opt.raw !== undefined) {
109
+ rawMapRef.current.set(opt.value, opt.raw);
110
+ }
111
+ }, []);
112
+
113
+ // Immediately populate labels for initial values (runs once on mount)
114
+ if (labelMapRef.current.size === 0 && currentValue) {
115
+ const values = Array.isArray(currentValue) ? currentValue : [currentValue];
116
+ // First, store initialSelectedOptions if provided
117
+ if (initialSelectedOptions) {
118
+ const arr = Array.isArray(initialSelectedOptions)
119
+ ? initialSelectedOptions
120
+ : [initialSelectedOptions];
121
+ arr.forEach((opt) => {
122
+ labelMapRef.current.set(opt.value, opt.label);
123
+ if (opt.raw !== undefined) {
124
+ rawMapRef.current.set(opt.value, opt.raw);
125
+ }
126
+ });
127
+ }
128
+ // Then look up missing values in options array
129
+ values.forEach((val) => {
130
+ if (!labelMapRef.current.has(val)) {
131
+ const option = options.find((opt) => opt.value === val);
132
+ if (option) {
133
+ labelMapRef.current.set(option.value, option.label);
134
+ if (option.raw !== undefined) {
135
+ rawMapRef.current.set(option.value, option.raw);
136
+ }
137
+ }
138
+ }
139
+ });
140
+ }
141
+
142
+ // Data state
143
+ const [items, setItems] = useState<AutocompleteOption<T>[]>([]);
144
+ const [loading, setLoading] = useState(false);
145
+ const [hasMore, setHasMore] = useState(false);
146
+ const [page, setPage] = useState(1);
147
+ const [searchInput, setSearchInput] = useState('');
148
+ const [debouncedSearch] = useDebounce(searchInput, 300);
149
+ const [clearCounter, setClearCounter] = useState(0);
150
+
151
+ // Popover state
152
+ const [isOpen, setIsOpen] = useState(!!defaultOpen);
153
+
154
+ // Clear input in multiple mode after selection
155
+ useEffect(() => {
156
+ if (clearCounter >= 0) {
157
+ setSearchInput('');
158
+ }
159
+ }, [clearCounter]);
160
+
161
+ // Load data
162
+ const loadData = useCallback(
163
+ async (pageNum: number, search: string) => {
164
+ if (mode === 'server') {
165
+ if (!fetcher) return;
166
+ setLoading(true);
167
+ try {
168
+ const res: AutocompleteFetchResult<T> = await fetcher({
169
+ search,
170
+ moreFilter: fetcherFilter,
171
+ cursor: null,
172
+ page: pageNum,
173
+ pageSize,
174
+ });
175
+ res.items.forEach(storeOption);
176
+ setItems((prev) =>
177
+ pageNum === 1 ? res.items : [...prev, ...res.items],
178
+ );
179
+ setHasMore(!!res.hasMore);
180
+ } catch (_error) {
181
+ if (pageNum === 1) setItems([]);
182
+ setHasMore(false);
183
+ } finally {
184
+ setLoading(false);
185
+ }
186
+ } else {
187
+ // Client mode
188
+ const filtered = search
189
+ ? options.filter((o) =>
190
+ o.label.toLowerCase().includes(search.toLowerCase()),
191
+ )
192
+ : options;
193
+ options.forEach(storeOption);
194
+ const start = (pageNum - 1) * pageSize;
195
+ const slice = filtered.slice(start, start + pageSize);
196
+ setItems((prev) => (pageNum === 1 ? slice : [...prev, ...slice]));
197
+ setHasMore(start + pageSize < filtered.length);
198
+ }
199
+ },
200
+ [mode, fetcher, fetcherFilter, options, pageSize, storeOption],
201
+ );
202
+
203
+ // Reset and load on search change
204
+ useEffect(() => {
205
+ if (!isOpen) return;
206
+ setPage(1);
207
+ loadData(1, debouncedSearch);
208
+ // eslint-disable-next-line react-hooks/exhaustive-deps
209
+ }, [isOpen, debouncedSearch, loadData]);
210
+
211
+ // Load more pages
212
+ useEffect(() => {
213
+ if (!isOpen || page <= 1) return;
214
+ loadData(page, debouncedSearch);
215
+ // eslint-disable-next-line react-hooks/exhaustive-deps
216
+ }, [isOpen, page, loadData, debouncedSearch]);
217
+
218
+ // Store initial/selected options (takes precedence)
219
+ useEffect(() => {
220
+ if (initialSelectedOptions) {
221
+ const arr = Array.isArray(initialSelectedOptions)
222
+ ? initialSelectedOptions
223
+ : [initialSelectedOptions];
224
+ arr.forEach(storeOption);
225
+ }
226
+ }, [initialSelectedOptions, storeOption]);
227
+
228
+ // Auto-populate missing initial options from provided options array
229
+ useEffect(() => {
230
+ if (
231
+ !currentValue ||
232
+ (Array.isArray(currentValue) && currentValue.length === 0)
233
+ )
234
+ return;
235
+
236
+ const values = Array.isArray(currentValue) ? currentValue : [currentValue];
237
+
238
+ // Only look up values that are missing (not in label map)
239
+ const missingValues = values.filter((v) => !labelMapRef.current.has(v));
240
+
241
+ if (missingValues.length === 0) return;
242
+
243
+ // Look up missing values in the options array
244
+ missingValues.forEach((val) => {
245
+ const option = options.find((opt) => opt.value === val);
246
+ if (option) {
247
+ storeOption(option);
248
+ }
249
+ });
250
+ }, [currentValue, options, storeOption]);
251
+
252
+ // Load selected labels on mount for initial values
253
+ const hasLoadedInitial = useRef(false);
254
+ const [, setLabelsLoadedCounter] = useState(0);
255
+
256
+ useEffect(() => {
257
+ // Only run once on mount
258
+ if (!loadSelected || hasLoadedInitial.current) return;
259
+ if (!currentValue) return;
260
+
261
+ const values = Array.isArray(currentValue) ? currentValue : [currentValue];
262
+ if (values.length === 0) return;
263
+
264
+ // Check if any values are missing labels
265
+ const missing = values.filter((v) => !labelMapRef.current.has(v));
266
+ if (missing.length === 0) {
267
+ hasLoadedInitial.current = true;
268
+ return;
269
+ }
270
+
271
+ hasLoadedInitial.current = true;
272
+ let cancelled = false;
273
+ loadSelected(missing)
274
+ .then((opts) => {
275
+ if (!cancelled && opts.length > 0) {
276
+ opts.forEach(storeOption);
277
+ // Only trigger re-render if we actually stored something
278
+ setLabelsLoadedCounter((c) => c + 1);
279
+ }
280
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
281
+ })
282
+ .catch(() => { });
283
+ return () => {
284
+ cancelled = true;
285
+ };
286
+ // eslint-disable-next-line react-hooks/exhaustive-deps
287
+ }, [loadSelected, storeOption, currentValue]); // Only run once on mount - uses closure values
288
+
289
+ // Load selected labels if missing when dropdown opens
290
+ useEffect(() => {
291
+ if (!loadSelected || !isOpen) return;
292
+ const values = Array.isArray(currentValue)
293
+ ? currentValue
294
+ : currentValue
295
+ ? [currentValue]
296
+ : [];
297
+ const missing = values.filter((v) => !labelMapRef.current.has(v));
298
+ if (missing.length === 0) return;
299
+
300
+ let cancelled = false;
301
+ loadSelected(missing)
302
+ .then((opts) => {
303
+ if (!cancelled) opts.forEach(storeOption);
304
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
305
+ })
306
+ .catch(() => { });
307
+ return () => {
308
+ cancelled = true;
309
+ };
310
+ }, [currentValue, loadSelected, isOpen, storeOption]);
311
+
312
+ // Get label helper
313
+ const getLabel = useCallback((v: string | number) => {
314
+ return labelMapRef.current.get(v) ?? String(v);
315
+ }, []);
316
+
317
+ // Selected items for display
318
+ const selectedItems = useMemo(() => {
319
+ if (!isMultiple) {
320
+ if (
321
+ currentValue === null ||
322
+ currentValue === undefined ||
323
+ Array.isArray(currentValue)
324
+ )
325
+ return [];
326
+ return [
327
+ {
328
+ value: currentValue,
329
+ label: getLabel(currentValue),
330
+ raw: rawMapRef.current.get(currentValue),
331
+ },
332
+ ];
333
+ }
334
+ const values = Array.isArray(currentValue) ? currentValue : [];
335
+ return values.map((v) => ({
336
+ value: v,
337
+ label: getLabel(v),
338
+ raw: rawMapRef.current.get(v),
339
+ }));
340
+ // eslint-disable-next-line react-hooks/exhaustive-deps
341
+ }, [currentValue, isMultiple, getLabel]); // labelsLoadedCounter triggers re-compute when loadSelected completes
342
+
343
+ // Handle selection
344
+ const handleSelect = useCallback(
345
+ (item: AutocompleteOption<T> | null) => {
346
+ if (!item) return;
347
+ storeOption(item);
348
+
349
+ if (isMultiple) {
350
+ const values = Array.isArray(currentValue) ? currentValue : [];
351
+ const exists = values.includes(item.value);
352
+
353
+ // Skip if already selected (don't toggle), but still clear the search
354
+ if (exists) {
355
+ setClearCounter((c) => (c + 1));
356
+ return;
357
+ }
358
+
359
+ const newValues = [...values, item.value];
360
+
361
+ if (!isControlled) setInternalValue(newValues);
362
+ const newOptions = newValues.map((v) => ({
363
+ value: v,
364
+ label: getLabel(v),
365
+ raw: rawMapRef.current.get(v),
366
+ }));
367
+ const raws = newOptions
368
+ .map((o) => o.raw)
369
+ .filter((r): r is T => r !== undefined);
370
+ onChange?.(newValues, newOptions, raws);
371
+
372
+ // Trigger input clear
373
+ setClearCounter((c) => (c + 1));
374
+ } else {
375
+ if (!isControlled) setInternalValue(item.value);
376
+ onChange?.(item.value, item, item.raw ?? null);
377
+ setIsOpen(false);
378
+ }
379
+ },
380
+ [isMultiple, currentValue, isControlled, onChange, getLabel, storeOption],
381
+ );
382
+
383
+ // Handle remove chip
384
+ const handleRemove = useCallback(
385
+ (valueToRemove: string | number) => {
386
+ const values = Array.isArray(currentValue) ? currentValue : [];
387
+ const newValues = values.filter((v) => v !== valueToRemove);
388
+ if (!isControlled) setInternalValue(newValues);
389
+ const newOptions = newValues.map((v) => ({
390
+ value: v,
391
+ label: getLabel(v),
392
+ raw: rawMapRef.current.get(v),
393
+ }));
394
+ const raws = newOptions
395
+ .map((o) => o.raw)
396
+ .filter((r): r is T => r !== undefined);
397
+ onChange?.(newValues, newOptions, raws);
398
+ },
399
+ [currentValue, isControlled, onChange, getLabel],
400
+ );
401
+
402
+ // Handle clear
403
+ const handleClear = useCallback(() => {
404
+ const newValue = isMultiple ? [] : null;
405
+ if (!isControlled) setInternalValue(newValue);
406
+ onChange?.(newValue, isMultiple ? [] : null, isMultiple ? [] : null);
407
+ setSearchInput('');
408
+ }, [isMultiple, isControlled, onChange]);
409
+
410
+ // Handle custom value creation
411
+ const handleCreateCustom = useCallback(() => {
412
+ const trimmed = searchInput.trim();
413
+ if (!trimmed || !allowCustomValue) return;
414
+
415
+ const newOption: AutocompleteOption<T> = { value: trimmed, label: trimmed };
416
+ storeOption(newOption);
417
+
418
+ if (isMultiple) {
419
+ const values = Array.isArray(currentValue) ? currentValue : [];
420
+ if (values.includes(trimmed)) return;
421
+ const newValues = [...values, trimmed];
422
+ if (!isControlled) setInternalValue(newValues);
423
+ const newOptions = newValues.map((v) => ({
424
+ value: v,
425
+ label: getLabel(v),
426
+ raw: rawMapRef.current.get(v),
427
+ }));
428
+ onChange?.(newValues, newOptions, []);
429
+ setSearchInput('');
430
+ } else {
431
+ if (!isControlled) setInternalValue(trimmed);
432
+ onChange?.(trimmed, newOption, null);
433
+ setSearchInput('');
434
+ setIsOpen(false);
435
+ }
436
+ }, [
437
+ searchInput,
438
+ allowCustomValue,
439
+ isMultiple,
440
+ currentValue,
441
+ isControlled,
442
+ onChange,
443
+ getLabel,
444
+ storeOption,
445
+ ]);
446
+
447
+ // Compute input value based on mode and state
448
+ const computedInputValue = useMemo(() => {
449
+ // In multiple mode or when dropdown is open, show search input
450
+ if (isMultiple || isOpen) {
451
+ return searchInput;
452
+ }
453
+ // In single mode when closed, show selected item label
454
+ if (selectedItems.length > 0) {
455
+ return selectedItems[0].label;
456
+ }
457
+ return '';
458
+ }, [isMultiple, isOpen, searchInput, selectedItems]);
459
+
460
+ // Downshift
461
+ const { getInputProps, getItemProps, getMenuProps, highlightedIndex } =
462
+ useCombobox({
463
+ items,
464
+ itemToString: (item) => item?.label ?? '',
465
+ selectedItem: isMultiple ? null : (selectedItems[0] ?? null),
466
+ onSelectedItemChange: ({ selectedItem }) => handleSelect(selectedItem),
467
+ isOpen,
468
+ onIsOpenChange: ({ isOpen: newIsOpen }) => setIsOpen(newIsOpen ?? false),
469
+ inputValue: computedInputValue,
470
+ onInputValueChange: ({ inputValue }) => setSearchInput(inputValue ?? ''),
471
+ });
472
+
473
+ // Refs
474
+ const parentRef = useRef<HTMLDivElement>(null);
475
+ const inputRef = useRef<HTMLInputElement>(null);
476
+
477
+ // Stable ref callback for merging Downshift's ref with our parentRef
478
+ const menuRefCallback = useCallback((node: HTMLDivElement | null) => {
479
+ parentRef.current = node;
480
+ }, []);
481
+
482
+ const handleScroll = useCallback(() => {
483
+ if (!parentRef.current || !hasMore || loading) return;
484
+
485
+ const { scrollTop, scrollHeight, clientHeight } = parentRef.current;
486
+ const scrolledToBottom = scrollHeight - scrollTop - clientHeight < 50;
487
+
488
+ if (scrolledToBottom) {
489
+ setPage((p) => p + 1);
490
+ }
491
+ }, [hasMore, loading]);
492
+
493
+ useEffect(() => {
494
+ const element = parentRef.current;
495
+ if (!element) return;
496
+
497
+ element.addEventListener('scroll', handleScroll);
498
+ return () => element.removeEventListener('scroll', handleScroll);
499
+ }, [handleScroll]);
500
+
501
+ useImperativeHandle(
502
+ ref,
503
+ () => ({
504
+ reset: handleClear,
505
+ }),
506
+ [handleClear]
507
+ );
508
+
509
+ const showClearButton =
510
+ clearable &&
511
+ ((isMultiple && selectedItems.length > 0) ||
512
+ (!isMultiple &&
513
+ currentValue !== null &&
514
+ currentValue !== undefined &&
515
+ !Array.isArray(currentValue)));
516
+
517
+ return (
518
+ <Popover open={isOpen} onOpenChange={setIsOpen}>
519
+ <PopoverTrigger asChild>
520
+ <div
521
+ className={cn(
522
+ 'flex min-h-10 items-center gap-2 rounded-md border border-border bg-background px-3 py-2 text-sm',
523
+ 'ring-offset-background',
524
+ 'focus-within:outline-none focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2',
525
+ disabled && 'cursor-not-allowed opacity-50',
526
+ width != null ? '' : 'w-full',
527
+ className,
528
+ )}
529
+ style={{ width }}
530
+ >
531
+ {isMultiple && (
532
+ <div className="flex flex-wrap gap-1">
533
+ {selectedItems.map((item) => (
534
+ <Badge
535
+ key={item.value}
536
+ variant={chipVariant}
537
+ className={cn('gap-1', chipClassName)}
538
+ >
539
+ <span className="max-w-[100px] truncate">{item.label}</span>
540
+ <button
541
+ type="button"
542
+ onClick={(e) => {
543
+ e.stopPropagation();
544
+ handleRemove(item.value);
545
+ }}
546
+ className="rounded-sm opacity-70 hover:opacity-100"
547
+ >
548
+ <X className="h-3 w-3" />
549
+ </button>
550
+ </Badge>
551
+ ))}
552
+ </div>
553
+ )}
554
+ <input
555
+ {...getInputProps({
556
+ ref: inputRef,
557
+ placeholder,
558
+ disabled,
559
+ onClick: () => {
560
+ if (!isOpen) setIsOpen(true);
561
+ },
562
+ onKeyDown: (e) => {
563
+ if (
564
+ e.key === 'Enter' &&
565
+ allowCustomValue &&
566
+ searchInput.trim() &&
567
+ items.length === 0
568
+ ) {
569
+ e.preventDefault();
570
+ handleCreateCustom();
571
+ }
572
+ },
573
+ })}
574
+ className={cn(
575
+ 'flex-1 bg-transparent outline-none placeholder:text-muted-foreground',
576
+ width ? 'w-full' : 'min-w-[120px]'
577
+ )}
578
+ />
579
+ <div className="flex items-center gap-2 shrink-0">
580
+ {showClearButton && (
581
+ <button
582
+ type="button"
583
+ onClick={(e) => {
584
+ e.stopPropagation();
585
+ handleClear();
586
+ }}
587
+ className="rounded-sm opacity-70 hover:opacity-100"
588
+ >
589
+ <X className="h-4 w-4" />
590
+ </button>
591
+ )}
592
+ <ChevronsUpDown className="h-4 w-4 opacity-50" />
593
+ </div>
594
+ </div>
595
+ </PopoverTrigger>
596
+ <PopoverContent
597
+ className="p-0"
598
+ style={{ width: 'var(--radix-popover-trigger-width)' }}
599
+ align="start"
600
+ onOpenAutoFocus={(e) => e.preventDefault()}
601
+ >
602
+ <div
603
+ {...getMenuProps({
604
+ ref: menuRefCallback,
605
+ })}
606
+ className="max-h-[300px] overflow-auto"
607
+ >
608
+ {loading && items.length === 0 ? (
609
+ <div className="flex items-center justify-center py-6">
610
+ <Loader2 className="h-4 w-4 animate-spin mr-2" />
611
+ <span className="text-sm text-muted-foreground">Loading...</span>
612
+ </div>
613
+ ) : items.length === 0 ? (
614
+ <div className="py-6 text-center text-sm text-muted-foreground">
615
+ {allowCustomValue && searchInput.trim() ? (
616
+ <>Press Enter to add &quot;{searchInput.trim()}&quot;</>
617
+ ) : (
618
+ emptyText
619
+ )}
620
+ </div>
621
+ ) : (
622
+ items.map((item, index) => {
623
+ const isSelected = isMultiple
624
+ ? Array.isArray(currentValue) &&
625
+ currentValue.includes(item.value)
626
+ : currentValue === item.value;
627
+ const isHighlighted = highlightedIndex === index;
628
+
629
+ return (
630
+ <div
631
+ key={item.value}
632
+ {...getItemProps({ item, index })}
633
+ className={cn(
634
+ 'flex cursor-pointer items-center justify-between px-2 py-2 text-sm outline-none transition-colors',
635
+ isHighlighted && 'bg-accent text-accent-foreground',
636
+ isSelected && 'font-medium',
637
+ )}
638
+ >
639
+ <div className="flex-1 truncate">
640
+ {renderOption ? renderOption(item, isSelected) : item.label}
641
+ </div>
642
+ {isSelected && <Check className="h-4 w-4 shrink-0" />}
643
+ </div>
644
+ );
645
+ })
646
+ )}
647
+ {hasMore && items.length > 0 && (
648
+ <div className="flex items-center justify-center border-t py-2">
649
+ {loading ? (
650
+ <>
651
+ <Loader2 className="h-3 w-3 animate-spin mr-1" />
652
+ <span className="text-xs text-muted-foreground">
653
+ Loading more...
654
+ </span>
655
+ </>
656
+ ) : (
657
+ <span className="text-xs text-muted-foreground">
658
+ Scroll for more
659
+ </span>
660
+ )}
661
+ </div>
662
+ )}
663
+ </div>
664
+ </PopoverContent>
665
+ </Popover>
666
+ );
667
+ }
668
+
669
+ export const ForwardedRefAutocomplete = forwardRef(Autocomplete) as <T>(props: AutocompleteProps<T> & RefAttributes<any>) => (ReactElement | null);
670
+
671
+ export default Autocomplete;