@k3-universe/react-kit 0.0.9 → 0.0.11

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 (524) hide show
  1. package/dist/index.js +18167 -15061
  2. package/dist/kit/builder/form/components/FormBuilder.d.ts +46 -14
  3. package/dist/kit/builder/form/components/FormBuilder.d.ts.map +1 -1
  4. package/dist/kit/builder/form/components/FormBuilderField.d.ts.map +1 -1
  5. package/dist/kit/builder/form/components/fields/AutocompleteField.d.ts.map +1 -1
  6. package/dist/kit/builder/form/components/fields/DatePickerField.d.ts +3 -0
  7. package/dist/kit/builder/form/components/fields/DatePickerField.d.ts.map +1 -0
  8. package/dist/kit/builder/form/components/fields/DateRangePickerField.d.ts +3 -0
  9. package/dist/kit/builder/form/components/fields/DateRangePickerField.d.ts.map +1 -0
  10. package/dist/kit/builder/form/components/fields/DateTimePickerField.d.ts +4 -0
  11. package/dist/kit/builder/form/components/fields/DateTimePickerField.d.ts.map +1 -0
  12. package/dist/kit/builder/form/components/fields/DateTimeRangePickerField.d.ts +4 -0
  13. package/dist/kit/builder/form/components/fields/DateTimeRangePickerField.d.ts.map +1 -0
  14. package/dist/kit/builder/form/components/fields/MonthPickerField.d.ts +3 -0
  15. package/dist/kit/builder/form/components/fields/MonthPickerField.d.ts.map +1 -0
  16. package/dist/kit/builder/form/components/fields/MonthRangePickerField.d.ts +3 -0
  17. package/dist/kit/builder/form/components/fields/MonthRangePickerField.d.ts.map +1 -0
  18. package/dist/kit/builder/form/components/fields/TimePickerField.d.ts +4 -0
  19. package/dist/kit/builder/form/components/fields/TimePickerField.d.ts.map +1 -0
  20. package/dist/kit/builder/form/components/fields/TimeRangePickerField.d.ts +4 -0
  21. package/dist/kit/builder/form/components/fields/TimeRangePickerField.d.ts.map +1 -0
  22. package/dist/kit/builder/form/components/fields/index.d.ts +8 -0
  23. package/dist/kit/builder/form/components/fields/index.d.ts.map +1 -1
  24. package/dist/kit/builder/section/SectionBuilder.d.ts.map +1 -1
  25. package/dist/kit/builder/section/types.d.ts +12 -1
  26. package/dist/kit/builder/section/types.d.ts.map +1 -1
  27. package/dist/kit/builder/stack-dialog/context.d.ts +3 -0
  28. package/dist/kit/builder/stack-dialog/context.d.ts.map +1 -0
  29. package/dist/kit/builder/stack-dialog/hooks.d.ts +6 -0
  30. package/dist/kit/builder/stack-dialog/hooks.d.ts.map +1 -0
  31. package/dist/kit/builder/stack-dialog/index.d.ts +5 -0
  32. package/dist/kit/builder/stack-dialog/index.d.ts.map +1 -0
  33. package/dist/kit/builder/stack-dialog/provider.d.ts +3 -0
  34. package/dist/kit/builder/stack-dialog/provider.d.ts.map +1 -0
  35. package/dist/kit/builder/stack-dialog/renderer.d.ts +6 -0
  36. package/dist/kit/builder/stack-dialog/renderer.d.ts.map +1 -0
  37. package/dist/kit/builder/stack-dialog/types.d.ts +20 -0
  38. package/dist/kit/builder/stack-dialog/types.d.ts.map +1 -0
  39. package/dist/kit/components/autocomplete/Autocomplete.d.ts +35 -3
  40. package/dist/kit/components/autocomplete/Autocomplete.d.ts.map +1 -1
  41. package/dist/kit/components/autocomplete/index.d.ts +1 -0
  42. package/dist/kit/components/autocomplete/index.d.ts.map +1 -1
  43. package/dist/kit/components/datepicker/DatePicker.d.ts +27 -0
  44. package/dist/kit/components/datepicker/DatePicker.d.ts.map +1 -0
  45. package/dist/kit/components/datepicker/DateRangePicker.d.ts +41 -0
  46. package/dist/kit/components/datepicker/DateRangePicker.d.ts.map +1 -0
  47. package/dist/kit/components/datetimepicker/DateTimePicker.d.ts +32 -0
  48. package/dist/kit/components/datetimepicker/DateTimePicker.d.ts.map +1 -0
  49. package/dist/kit/components/datetimepicker/DateTimeRangePicker.d.ts +39 -0
  50. package/dist/kit/components/datetimepicker/DateTimeRangePicker.d.ts.map +1 -0
  51. package/dist/kit/components/datetimepicker/index.d.ts +5 -0
  52. package/dist/kit/components/datetimepicker/index.d.ts.map +1 -0
  53. package/dist/kit/components/monthpicker/MonthInput.d.ts +26 -0
  54. package/dist/kit/components/monthpicker/MonthInput.d.ts.map +1 -0
  55. package/dist/kit/components/monthpicker/MonthPicker.d.ts +32 -0
  56. package/dist/kit/components/monthpicker/MonthPicker.d.ts.map +1 -0
  57. package/dist/kit/components/monthpicker/MonthRangeInput.d.ts +31 -0
  58. package/dist/kit/components/monthpicker/MonthRangeInput.d.ts.map +1 -0
  59. package/dist/kit/components/monthpicker/MonthRangePicker.d.ts +48 -0
  60. package/dist/kit/components/monthpicker/MonthRangePicker.d.ts.map +1 -0
  61. package/dist/kit/components/timepicker/TimePicker.d.ts +26 -0
  62. package/dist/kit/components/timepicker/TimePicker.d.ts.map +1 -0
  63. package/dist/kit/components/timepicker/TimeRangePicker.d.ts +31 -0
  64. package/dist/kit/components/timepicker/TimeRangePicker.d.ts.map +1 -0
  65. package/dist/kit/components/timepicker/index.d.ts +5 -0
  66. package/dist/kit/components/timepicker/index.d.ts.map +1 -0
  67. package/dist/kit/themes/clean-slate.css +181 -1
  68. package/dist/kit/themes/default.css +181 -1
  69. package/dist/kit/themes/minimal-modern.css +181 -1
  70. package/dist/kit/themes/spotify.css +181 -1
  71. package/package.json +1 -1
  72. package/src/kit/builder/form/components/FormBuilder.tsx +380 -145
  73. package/src/kit/builder/form/components/FormBuilderField.tsx +100 -3
  74. package/src/kit/builder/form/components/fields/AutocompleteField.tsx +29 -1
  75. package/src/kit/builder/form/components/fields/DatePickerField.tsx +24 -0
  76. package/src/kit/builder/form/components/fields/DateRangePickerField.tsx +41 -0
  77. package/src/kit/builder/form/components/fields/DateTimePickerField.tsx +33 -0
  78. package/src/kit/builder/form/components/fields/DateTimeRangePickerField.tsx +42 -0
  79. package/src/kit/builder/form/components/fields/MonthPickerField.tsx +26 -0
  80. package/src/kit/builder/form/components/fields/MonthRangePickerField.tsx +35 -0
  81. package/src/kit/builder/form/components/fields/TimePickerField.tsx +30 -0
  82. package/src/kit/builder/form/components/fields/TimeRangePickerField.tsx +37 -0
  83. package/src/kit/builder/form/components/fields/index.ts +8 -0
  84. package/src/kit/builder/section/SectionBuilder.tsx +24 -2
  85. package/src/kit/builder/section/types.ts +15 -1
  86. package/src/kit/builder/stack-dialog/context.ts +9 -0
  87. package/src/kit/builder/stack-dialog/hooks.ts +11 -0
  88. package/src/kit/builder/stack-dialog/index.ts +13 -0
  89. package/src/kit/builder/stack-dialog/provider.tsx +55 -0
  90. package/src/kit/builder/stack-dialog/renderer.tsx +33 -0
  91. package/src/kit/builder/stack-dialog/types.ts +22 -0
  92. package/src/kit/components/autocomplete/Autocomplete.tsx +783 -233
  93. package/src/kit/components/autocomplete/index.ts +1 -0
  94. package/src/kit/components/datepicker/DatePicker.tsx +149 -0
  95. package/src/kit/components/datepicker/DateRangePicker.tsx +454 -0
  96. package/src/kit/components/datetimepicker/DateTimePicker.tsx +314 -0
  97. package/src/kit/components/datetimepicker/DateTimeRangePicker.tsx +486 -0
  98. package/src/kit/components/datetimepicker/index.ts +3 -0
  99. package/src/kit/components/monthpicker/MonthInput.tsx +122 -0
  100. package/src/kit/components/monthpicker/MonthPicker.tsx +223 -0
  101. package/src/kit/components/monthpicker/MonthRangeInput.tsx +132 -0
  102. package/src/kit/components/monthpicker/MonthRangePicker.tsx +407 -0
  103. package/src/kit/components/timepicker/TimePicker.tsx +311 -0
  104. package/src/kit/components/timepicker/TimeRangePicker.tsx +291 -0
  105. package/src/kit/components/timepicker/index.ts +3 -0
  106. package/src/stories/kit/builder/Form.Autocomplete.stories.tsx +210 -0
  107. package/src/stories/kit/builder/Form.Complex.stories.tsx +101 -0
  108. package/src/stories/kit/builder/Form.DateTime.stories.tsx +66 -0
  109. package/src/stories/kit/builder/Form.Dynamic.stories.tsx +149 -0
  110. package/src/stories/kit/builder/Form.Pickers.stories.tsx +71 -0
  111. package/src/stories/kit/builder/Form.Time.stories.tsx +64 -0
  112. package/src/stories/kit/builder/Section.stories.tsx +58 -2
  113. package/src/stories/kit/components/Autocomplete.stories.tsx +27 -0
  114. package/src/stories/kit/components/DatePicker.stories.tsx +128 -0
  115. package/src/stories/kit/components/DateRangePicker.stories.tsx +154 -0
  116. package/src/stories/kit/components/MonthPicker.stories.tsx +80 -0
  117. package/src/stories/kit/components/MonthRangePicker.stories.tsx +98 -0
  118. package/src/stories/kit/components/TimePicker.stories.tsx +69 -0
  119. package/src/stories/kit/components/TimeRangePicker.stories.tsx +37 -0
  120. package/storybook-static/assets/Accordion.stories-KU4JBR8U.js +52 -0
  121. package/storybook-static/assets/AdminLayout-CPvVCwfY.js +53 -0
  122. package/storybook-static/assets/AdminLayout.Basic.stories-DkP2UVXe.js +4 -0
  123. package/storybook-static/assets/AdminLayout.Collapsible.stories-BuuVjtpW.js +4 -0
  124. package/storybook-static/assets/AdminLayout.Complex.stories-D-k4H0hJ.js +29 -0
  125. package/storybook-static/assets/AdminLayout.CustomSidebarHeaderComponent.stories-B_0IEDd4.js +9 -0
  126. package/storybook-static/assets/AdminLayout.CustomSidebarTitleAndIcon.stories-CvAeXUyA.js +4 -0
  127. package/storybook-static/assets/AdminLayout.HeaderSlots.stories-RBFHoSZK.js +7 -0
  128. package/storybook-static/assets/Alert.stories-DKxKtIc0.js +27 -0
  129. package/storybook-static/assets/AlertDialog.stories-BqTpZ_nG.js +43 -0
  130. package/storybook-static/assets/AspectRatio.stories-DPO9QQ5F.js +22 -0
  131. package/storybook-static/assets/Autocomplete-Cpg4CaJe.js +56 -0
  132. package/storybook-static/assets/Autocomplete.stories-CWj4G5fh.js +56 -0
  133. package/storybook-static/assets/Avatar.stories-DPhov_2g.js +12 -0
  134. package/storybook-static/assets/Badge.stories-DFKrRdXq.js +12 -0
  135. package/storybook-static/assets/Breadcrumb.stories-CTE6CZUC.js +25 -0
  136. package/storybook-static/assets/Button.stories-cbt2InL-.js +26 -0
  137. package/storybook-static/assets/Calendar.stories-DRhTw_43.js +3 -0
  138. package/storybook-static/assets/Card.stories-Isf6n_K3.js +15 -0
  139. package/storybook-static/assets/Carousel.stories-Cmg0I3fR.js +15 -0
  140. package/storybook-static/assets/Chart.stories-aQ-fNijT.js +126 -0
  141. package/storybook-static/assets/Checkbox.stories-B7YMXPDc.js +12 -0
  142. package/storybook-static/assets/Collapsible.stories-BUzl17ZZ.js +18 -0
  143. package/storybook-static/assets/Combination-BdQWAuko.js +41 -0
  144. package/storybook-static/assets/Command.stories-DzBlWQs0.js +30 -0
  145. package/storybook-static/assets/ContextMenu.stories-CJlBQyXc.js +31 -0
  146. package/storybook-static/assets/DataTable.Basic.stories-BWYKFDmK.js +6 -0
  147. package/storybook-static/assets/DataTable.Filters.stories-uZdtJk8t.js +21 -0
  148. package/storybook-static/assets/DataTable.Pagination.stories-C5N1khkp.js +24 -0
  149. package/storybook-static/assets/DataTable.SelectionAndActions.stories-FhCqZKvO.js +26 -0
  150. package/storybook-static/assets/DataTable.Sorting.stories-D-k7EtRj.js +6 -0
  151. package/storybook-static/assets/Dialog.stories-C62AF-Gx.js +54 -0
  152. package/storybook-static/assets/Dialog.stories-lrjRwOus.js +18 -0
  153. package/storybook-static/assets/Drawer.stories-CGjkdJeV.js +24 -0
  154. package/storybook-static/assets/DropdownMenu.stories-DkGClRAA.js +35 -0
  155. package/storybook-static/assets/Form.ArrayLayouts.stories-C5d_062d.js +130 -0
  156. package/storybook-static/assets/Form.Autocomplete.stories-CPZPkk4o.js +142 -0
  157. package/storybook-static/assets/Form.Basic.stories-Bhcu3-3n.js +58 -0
  158. package/storybook-static/assets/Form.Complex.stories-QnXh5a7Q.js +361 -0
  159. package/storybook-static/assets/Form.Dynamic.stories-DFW6wIuT.js +502 -0
  160. package/storybook-static/assets/Form.Simple.stories-BhJcyhbE.js +53 -0
  161. package/storybook-static/assets/Form.stories-PFNsMYxO.js +3 -0
  162. package/storybook-static/assets/FormBuilder-BQBBxo_k.js +5 -0
  163. package/storybook-static/assets/HoverCard.stories-CAlQEVn8.js +21 -0
  164. package/storybook-static/assets/Input.stories-CEhODt0V.js +16 -0
  165. package/storybook-static/assets/InputOtp.stories-DSvNP4dS.js +42 -0
  166. package/storybook-static/assets/Label.stories-B3pa8ZLY.js +14 -0
  167. package/storybook-static/assets/Login.stories-C7KQkmR_.js +37 -0
  168. package/storybook-static/assets/Menubar.stories-CHXhSHxc.js +44 -0
  169. package/storybook-static/assets/MonthPicker.stories-BnrOc4fm.js +99 -0
  170. package/storybook-static/assets/MonthRangePicker.stories-55Gk1t-7.js +134 -0
  171. package/storybook-static/assets/NavigationMenu.stories-CXoS080P.js +30 -0
  172. package/storybook-static/assets/Page.stories-GdSJgZ6-.js +91 -0
  173. package/storybook-static/assets/Pagination.stories-BEBwqH4N.js +29 -0
  174. package/storybook-static/assets/Popover.stories-BICy98Cw.js +15 -0
  175. package/storybook-static/assets/Progress.stories-DECHNOME.js +8 -0
  176. package/storybook-static/assets/RadioGroup.stories-DA7-uKfV.js +16 -0
  177. package/storybook-static/assets/Resizable.stories-B99kWkH7.js +25 -0
  178. package/storybook-static/assets/ScrollArea.stories-BqvUAXqU.js +12 -0
  179. package/storybook-static/assets/Section.stories-lFMlFBQn.js +277 -0
  180. package/storybook-static/assets/SectionBuilder-BQW705x0.js +1 -0
  181. package/storybook-static/assets/Select.stories-BsKyZ6Io.js +17 -0
  182. package/storybook-static/assets/Separator.stories-BTDOaOM2.js +17 -0
  183. package/storybook-static/assets/Sheet.stories-Cam1gR6G.js +24 -0
  184. package/storybook-static/assets/Sidebar.stories-DnOa6G7y.js +106 -0
  185. package/storybook-static/assets/Skeleton.stories-BQNIuIe5.js +9 -0
  186. package/storybook-static/assets/Slider.stories-Bslq7hjq.js +6 -0
  187. package/storybook-static/assets/Sonner.stories-D34pBBtI.js +18 -0
  188. package/storybook-static/assets/Switch.stories-Puyb1-Bx.js +3 -0
  189. package/storybook-static/assets/Table.stories-ClZxAhut.js +35 -0
  190. package/storybook-static/assets/Tabs.stories-CURNTETB.js +10 -0
  191. package/storybook-static/assets/Textarea.stories-Cf1ZBrWw.js +17 -0
  192. package/storybook-static/assets/Toggle.stories-CdMHY_bi.js +3 -0
  193. package/storybook-static/assets/ToggleGroup.stories-BM68m1dX.js +13 -0
  194. package/storybook-static/assets/Tooltip.stories-DiQv64dM.js +10 -0
  195. package/storybook-static/assets/accordion-DVgwQcnw.js +1 -0
  196. package/storybook-static/assets/alert-dialog-DCUEwpqm.js +7 -0
  197. package/storybook-static/assets/avatar-BzwOE-mi.js +1 -0
  198. package/storybook-static/assets/axe-HmUsR1st.js +30 -0
  199. package/storybook-static/assets/badge-BnQWua6u.js +1 -0
  200. package/storybook-static/assets/button-0oMkiryo.js +1 -0
  201. package/storybook-static/assets/card-BJpPOzP8.js +1 -0
  202. package/storybook-static/assets/chart-column-DZGb4ZZS.js +6 -0
  203. package/storybook-static/assets/check-B9hBGj6o.js +6 -0
  204. package/storybook-static/assets/checkbox-CyIeaWHX.js +1 -0
  205. package/storybook-static/assets/chevron-down-D_37S6il.js +6 -0
  206. package/storybook-static/assets/chevron-left-BBoN0vbI.js +6 -0
  207. package/storybook-static/assets/chevron-right-B5vIMLxK.js +6 -0
  208. package/storybook-static/assets/circle-C5Lzx6Nx.js +6 -0
  209. package/storybook-static/assets/clean-slate-D1HmMFJM.css +1 -0
  210. package/storybook-static/assets/command-Csa9p8_a.js +6 -0
  211. package/storybook-static/assets/createLucideIcon-BrHXro7t.js +21 -0
  212. package/storybook-static/assets/default-CN_Fo1GY.css +1 -0
  213. package/storybook-static/assets/dependencies-ctrV69dx.js +1 -0
  214. package/storybook-static/assets/dialog-CsnqITTn.js +1 -0
  215. package/storybook-static/assets/dropdown-menu-BWxxwPHL.js +1 -0
  216. package/storybook-static/assets/ellipsis-BRS038RR.js +6 -0
  217. package/storybook-static/assets/grip-vertical-BxXG8KNA.js +6 -0
  218. package/storybook-static/assets/iframe-C9bogcIc.css +1 -0
  219. package/storybook-static/assets/iframe-v7iAhKit.js +1555 -0
  220. package/storybook-static/assets/index-0-qMRXou.js +1 -0
  221. package/storybook-static/assets/index-AvwFFKJc.js +1 -0
  222. package/storybook-static/assets/index-BVDb4dFc.js +1 -0
  223. package/storybook-static/assets/index-B_qx7A5T.js +1 -0
  224. package/storybook-static/assets/index-BdQq_4o_.js +1 -0
  225. package/storybook-static/assets/index-BfiCOk42.js +1 -0
  226. package/storybook-static/assets/index-Bv9yk470.js +1 -0
  227. package/storybook-static/assets/index-Bw1A27Kp.js +1 -0
  228. package/storybook-static/assets/index-ByqivBWx.js +1 -0
  229. package/storybook-static/assets/index-C9Ta0ZTH.js +1 -0
  230. package/storybook-static/assets/index-CDY5kTx5.js +1 -0
  231. package/storybook-static/assets/index-CGnyVRgB.js +1 -0
  232. package/storybook-static/assets/index-CGrAONsN.js +1 -0
  233. package/storybook-static/assets/index-CWjrGFAQ.js +1 -0
  234. package/storybook-static/assets/index-CwBdPBFz.js +9 -0
  235. package/storybook-static/assets/index-D8RXF03I.js +1 -0
  236. package/storybook-static/assets/index-DLIxT4Z7.js +1 -0
  237. package/storybook-static/assets/index-DW48STyt.js +1 -0
  238. package/storybook-static/assets/index-DbaA6-o1.js +1 -0
  239. package/storybook-static/assets/index-Dph_5COR.js +1 -0
  240. package/storybook-static/assets/index-DrN5n71E.js +1 -0
  241. package/storybook-static/assets/index-Tp9IdbR8.js +1 -0
  242. package/storybook-static/assets/index-WyF3-wTE.js +9 -0
  243. package/storybook-static/assets/index-XSmPROEP.js +1 -0
  244. package/storybook-static/assets/index-Z6wF44KX.js +5 -0
  245. package/storybook-static/assets/index-_RPqOjlQ.js +1 -0
  246. package/storybook-static/assets/index-jrimW4QO.js +1 -0
  247. package/storybook-static/assets/index-nqc17SX4.js +1 -0
  248. package/storybook-static/assets/input-11YRd9gD.js +1 -0
  249. package/storybook-static/assets/jsx-runtime-D_zvdyIk.js +9 -0
  250. package/storybook-static/assets/label-Do8ODIVk.js +1 -0
  251. package/storybook-static/assets/lodash-DDwpuhPG.js +73 -0
  252. package/storybook-static/assets/matchers-7Z3WT2CE-T3xScrR7.js +14 -0
  253. package/storybook-static/assets/minimal-modern-BlYVzfQU.css +1 -0
  254. package/storybook-static/assets/popover-CcciSWAw.js +1 -0
  255. package/storybook-static/assets/preload-helper-Dp1pzeXC.js +1 -0
  256. package/storybook-static/assets/radio-group-DiJ0Y_KQ.js +1 -0
  257. package/storybook-static/assets/react-18-Cr9fq_Ip.js +25 -0
  258. package/storybook-static/assets/react-icons.esm-B_ULMmNU.js +1 -0
  259. package/storybook-static/assets/refresh-cw-BmRDhIV_.js +6 -0
  260. package/storybook-static/assets/schemas-CGNYCiJ6.js +18 -0
  261. package/storybook-static/assets/section-factories-DCCY9R35.js +1 -0
  262. package/storybook-static/assets/select-DDrkxaOg.js +6 -0
  263. package/storybook-static/assets/separator-o5SAUnaJ.js +1 -0
  264. package/storybook-static/assets/settings-2-xWGvvbG6.js +6 -0
  265. package/storybook-static/assets/sheet-C7jhU3XE.js +1 -0
  266. package/storybook-static/assets/shopping-cart-BFlrufvo.js +11 -0
  267. package/storybook-static/assets/sidebar-C8hU1Mxy.js +6 -0
  268. package/storybook-static/assets/skeleton-CjDnQs43.js +1 -0
  269. package/storybook-static/assets/spotify-CUDj7g8m.css +1 -0
  270. package/storybook-static/assets/switch-CKGRuk3u.js +1 -0
  271. package/storybook-static/assets/table-CP3vMqFn.js +1 -0
  272. package/storybook-static/assets/tabs-CopK2m3j.js +1 -0
  273. package/storybook-static/assets/textarea-Dw2vruMl.js +1 -0
  274. package/storybook-static/assets/toggle-DmHbWetf.js +16 -0
  275. package/storybook-static/assets/tooltip-_LqYEYFw.js +1 -0
  276. package/storybook-static/assets/trash-2-xdbApPby.js +11 -0
  277. package/storybook-static/assets/utils-D-KgF5mV.js +1 -0
  278. package/storybook-static/assets/x-B1a4fyWM.js +6 -0
  279. package/storybook-static/favicon-wrapper.svg +46 -0
  280. package/storybook-static/favicon.svg +1 -0
  281. package/storybook-static/iframe.html +687 -0
  282. package/storybook-static/index.d.ts +64 -0
  283. package/storybook-static/index.d.ts.map +1 -0
  284. package/storybook-static/index.html +166 -0
  285. package/storybook-static/index.json +1 -0
  286. package/storybook-static/kit/builder/data-table/components/DataTable.d.ts +37 -0
  287. package/storybook-static/kit/builder/data-table/components/DataTable.d.ts.map +1 -0
  288. package/storybook-static/kit/builder/data-table/components/DataTableColumnHeader.d.ts +8 -0
  289. package/storybook-static/kit/builder/data-table/components/DataTableColumnHeader.d.ts.map +1 -0
  290. package/storybook-static/kit/builder/data-table/components/DataTablePagination.d.ts +6 -0
  291. package/storybook-static/kit/builder/data-table/components/DataTablePagination.d.ts.map +1 -0
  292. package/storybook-static/kit/builder/data-table/components/DataTableViewOptions.d.ts +5 -0
  293. package/storybook-static/kit/builder/data-table/components/DataTableViewOptions.d.ts.map +1 -0
  294. package/storybook-static/kit/builder/data-table/index.d.ts +7 -0
  295. package/storybook-static/kit/builder/data-table/index.d.ts.map +1 -0
  296. package/storybook-static/kit/builder/data-table/types.d.ts +27 -0
  297. package/storybook-static/kit/builder/data-table/types.d.ts.map +1 -0
  298. package/storybook-static/kit/builder/data-table/utils/dotAccessor.d.ts +2 -0
  299. package/storybook-static/kit/builder/data-table/utils/dotAccessor.d.ts.map +1 -0
  300. package/storybook-static/kit/builder/dialog/index.d.ts +3 -0
  301. package/storybook-static/kit/builder/dialog/index.d.ts.map +1 -0
  302. package/storybook-static/kit/builder/dialog/provider.d.ts +26 -0
  303. package/storybook-static/kit/builder/dialog/provider.d.ts.map +1 -0
  304. package/storybook-static/kit/builder/form/components/FormBuilder.d.ts +137 -0
  305. package/storybook-static/kit/builder/form/components/FormBuilder.d.ts.map +1 -0
  306. package/storybook-static/kit/builder/form/components/FormBuilderActions.d.ts +20 -0
  307. package/storybook-static/kit/builder/form/components/FormBuilderActions.d.ts.map +1 -0
  308. package/storybook-static/kit/builder/form/components/FormBuilderField.d.ts +12 -0
  309. package/storybook-static/kit/builder/form/components/FormBuilderField.d.ts.map +1 -0
  310. package/storybook-static/kit/builder/form/components/fields/ArrayField.d.ts +3 -0
  311. package/storybook-static/kit/builder/form/components/fields/ArrayField.d.ts.map +1 -0
  312. package/storybook-static/kit/builder/form/components/fields/AutocompleteField.d.ts +3 -0
  313. package/storybook-static/kit/builder/form/components/fields/AutocompleteField.d.ts.map +1 -0
  314. package/storybook-static/kit/builder/form/components/fields/CheckboxField.d.ts +3 -0
  315. package/storybook-static/kit/builder/form/components/fields/CheckboxField.d.ts.map +1 -0
  316. package/storybook-static/kit/builder/form/components/fields/DateField.d.ts +3 -0
  317. package/storybook-static/kit/builder/form/components/fields/DateField.d.ts.map +1 -0
  318. package/storybook-static/kit/builder/form/components/fields/FileField.d.ts +3 -0
  319. package/storybook-static/kit/builder/form/components/fields/FileField.d.ts.map +1 -0
  320. package/storybook-static/kit/builder/form/components/fields/NumberField.d.ts +3 -0
  321. package/storybook-static/kit/builder/form/components/fields/NumberField.d.ts.map +1 -0
  322. package/storybook-static/kit/builder/form/components/fields/ObjectField.d.ts +3 -0
  323. package/storybook-static/kit/builder/form/components/fields/ObjectField.d.ts.map +1 -0
  324. package/storybook-static/kit/builder/form/components/fields/RadioField.d.ts +3 -0
  325. package/storybook-static/kit/builder/form/components/fields/RadioField.d.ts.map +1 -0
  326. package/storybook-static/kit/builder/form/components/fields/SelectField.d.ts +3 -0
  327. package/storybook-static/kit/builder/form/components/fields/SelectField.d.ts.map +1 -0
  328. package/storybook-static/kit/builder/form/components/fields/SwitchField.d.ts +3 -0
  329. package/storybook-static/kit/builder/form/components/fields/SwitchField.d.ts.map +1 -0
  330. package/storybook-static/kit/builder/form/components/fields/TextField.d.ts +3 -0
  331. package/storybook-static/kit/builder/form/components/fields/TextField.d.ts.map +1 -0
  332. package/storybook-static/kit/builder/form/components/fields/TextareaField.d.ts +3 -0
  333. package/storybook-static/kit/builder/form/components/fields/TextareaField.d.ts.map +1 -0
  334. package/storybook-static/kit/builder/form/components/fields/index.d.ts +14 -0
  335. package/storybook-static/kit/builder/form/components/fields/index.d.ts.map +1 -0
  336. package/storybook-static/kit/builder/form/components/fields/types.d.ts +14 -0
  337. package/storybook-static/kit/builder/form/components/fields/types.d.ts.map +1 -0
  338. package/storybook-static/kit/builder/form/components/index.d.ts +4 -0
  339. package/storybook-static/kit/builder/form/components/index.d.ts.map +1 -0
  340. package/storybook-static/kit/builder/form/index.d.ts +3 -0
  341. package/storybook-static/kit/builder/form/index.d.ts.map +1 -0
  342. package/storybook-static/kit/builder/form/utils/common-forms.d.ts +7 -0
  343. package/storybook-static/kit/builder/form/utils/common-forms.d.ts.map +1 -0
  344. package/storybook-static/kit/builder/form/utils/dependencies.d.ts +41 -0
  345. package/storybook-static/kit/builder/form/utils/dependencies.d.ts.map +1 -0
  346. package/storybook-static/kit/builder/form/utils/field-factories.d.ts +23 -0
  347. package/storybook-static/kit/builder/form/utils/field-factories.d.ts.map +1 -0
  348. package/storybook-static/kit/builder/form/utils/index.d.ts +15 -0
  349. package/storybook-static/kit/builder/form/utils/index.d.ts.map +1 -0
  350. package/storybook-static/kit/builder/form/utils/section-factories.d.ts +7 -0
  351. package/storybook-static/kit/builder/form/utils/section-factories.d.ts.map +1 -0
  352. package/storybook-static/kit/builder/form/utils/transformers.d.ts +6 -0
  353. package/storybook-static/kit/builder/form/utils/transformers.d.ts.map +1 -0
  354. package/storybook-static/kit/builder/form/utils/validations.d.ts +13 -0
  355. package/storybook-static/kit/builder/form/utils/validations.d.ts.map +1 -0
  356. package/storybook-static/kit/builder/form/utils/validators.d.ts +8 -0
  357. package/storybook-static/kit/builder/form/utils/validators.d.ts.map +1 -0
  358. package/storybook-static/kit/builder/page/Page.d.ts +48 -0
  359. package/storybook-static/kit/builder/page/Page.d.ts.map +1 -0
  360. package/storybook-static/kit/builder/page/index.d.ts +2 -0
  361. package/storybook-static/kit/builder/page/index.d.ts.map +1 -0
  362. package/storybook-static/kit/builder/section/SectionBuilder.d.ts +3 -0
  363. package/storybook-static/kit/builder/section/SectionBuilder.d.ts.map +1 -0
  364. package/storybook-static/kit/builder/section/index.d.ts +3 -0
  365. package/storybook-static/kit/builder/section/index.d.ts.map +1 -0
  366. package/storybook-static/kit/builder/section/types.d.ts +70 -0
  367. package/storybook-static/kit/builder/section/types.d.ts.map +1 -0
  368. package/storybook-static/kit/builder/stack-dialog/context.d.ts +3 -0
  369. package/storybook-static/kit/builder/stack-dialog/context.d.ts.map +1 -0
  370. package/storybook-static/kit/builder/stack-dialog/hooks.d.ts +6 -0
  371. package/storybook-static/kit/builder/stack-dialog/hooks.d.ts.map +1 -0
  372. package/storybook-static/kit/builder/stack-dialog/index.d.ts +5 -0
  373. package/storybook-static/kit/builder/stack-dialog/index.d.ts.map +1 -0
  374. package/storybook-static/kit/builder/stack-dialog/provider.d.ts +3 -0
  375. package/storybook-static/kit/builder/stack-dialog/provider.d.ts.map +1 -0
  376. package/storybook-static/kit/builder/stack-dialog/renderer.d.ts +6 -0
  377. package/storybook-static/kit/builder/stack-dialog/renderer.d.ts.map +1 -0
  378. package/storybook-static/kit/builder/stack-dialog/types.d.ts +20 -0
  379. package/storybook-static/kit/builder/stack-dialog/types.d.ts.map +1 -0
  380. package/storybook-static/kit/components/autocomplete/Autocomplete.d.ts +53 -0
  381. package/storybook-static/kit/components/autocomplete/Autocomplete.d.ts.map +1 -0
  382. package/storybook-static/kit/components/autocomplete/index.d.ts +4 -0
  383. package/storybook-static/kit/components/autocomplete/index.d.ts.map +1 -0
  384. package/storybook-static/kit/components/autocomplete/types.d.ts +19 -0
  385. package/storybook-static/kit/components/autocomplete/types.d.ts.map +1 -0
  386. package/storybook-static/kit/components/login/Login.d.ts +29 -0
  387. package/storybook-static/kit/components/login/Login.d.ts.map +1 -0
  388. package/storybook-static/kit/components/login/index.d.ts +2 -0
  389. package/storybook-static/kit/components/login/index.d.ts.map +1 -0
  390. package/storybook-static/kit/components/monthpicker/MonthPicker.d.ts +32 -0
  391. package/storybook-static/kit/components/monthpicker/MonthPicker.d.ts.map +1 -0
  392. package/storybook-static/kit/components/monthpicker/MonthRangePicker.d.ts +48 -0
  393. package/storybook-static/kit/components/monthpicker/MonthRangePicker.d.ts.map +1 -0
  394. package/storybook-static/kit/layouts/admin/components/AdminLayout.d.ts +17 -0
  395. package/storybook-static/kit/layouts/admin/components/AdminLayout.d.ts.map +1 -0
  396. package/storybook-static/kit/layouts/admin/components/ThemeToggle.d.ts +5 -0
  397. package/storybook-static/kit/layouts/admin/components/ThemeToggle.d.ts.map +1 -0
  398. package/storybook-static/kit/layouts/admin/hooks/menu.d.ts +13 -0
  399. package/storybook-static/kit/layouts/admin/hooks/menu.d.ts.map +1 -0
  400. package/storybook-static/kit/layouts/admin/providers/AdminMenuProvider.d.ts +7 -0
  401. package/storybook-static/kit/layouts/admin/providers/AdminMenuProvider.d.ts.map +1 -0
  402. package/storybook-static/kit/layouts/admin/types/index.d.ts +27 -0
  403. package/storybook-static/kit/layouts/admin/types/index.d.ts.map +1 -0
  404. package/storybook-static/kit/providers/ThemeProvider.d.ts +14 -0
  405. package/storybook-static/kit/providers/ThemeProvider.d.ts.map +1 -0
  406. package/storybook-static/nunito-sans-bold-italic.woff2 +0 -0
  407. package/storybook-static/nunito-sans-bold.woff2 +0 -0
  408. package/storybook-static/nunito-sans-italic.woff2 +0 -0
  409. package/storybook-static/nunito-sans-regular.woff2 +0 -0
  410. package/storybook-static/project.json +1 -0
  411. package/storybook-static/sb-addons/a11y-5/manager-bundle.js +5 -0
  412. package/storybook-static/sb-addons/essentials-backgrounds-1/manager-bundle.js +3 -0
  413. package/storybook-static/sb-addons/essentials-measure-2/manager-bundle.js +3 -0
  414. package/storybook-static/sb-addons/essentials-outline-3/manager-bundle.js +3 -0
  415. package/storybook-static/sb-addons/interactions-4/manager-bundle.js +57 -0
  416. package/storybook-static/sb-addons/storybook-core-server-presets-0/common-manager-bundle.js +971 -0
  417. package/storybook-static/sb-addons/storysource-6/manager-bundle.js +3 -0
  418. package/storybook-static/sb-common-assets/favicon-wrapper.svg +46 -0
  419. package/storybook-static/sb-common-assets/favicon.svg +1 -0
  420. package/storybook-static/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
  421. package/storybook-static/sb-common-assets/nunito-sans-bold.woff2 +0 -0
  422. package/storybook-static/sb-common-assets/nunito-sans-italic.woff2 +0 -0
  423. package/storybook-static/sb-common-assets/nunito-sans-regular.woff2 +0 -0
  424. package/storybook-static/sb-manager/globals-module-info.js +797 -0
  425. package/storybook-static/sb-manager/globals-runtime.js +69653 -0
  426. package/storybook-static/sb-manager/globals.js +34 -0
  427. package/storybook-static/sb-manager/runtime.js +13181 -0
  428. package/storybook-static/shadcn/hooks/use-mobile.d.ts +2 -0
  429. package/storybook-static/shadcn/hooks/use-mobile.d.ts.map +1 -0
  430. package/storybook-static/shadcn/lib/utils.d.ts +3 -0
  431. package/storybook-static/shadcn/lib/utils.d.ts.map +1 -0
  432. package/storybook-static/shadcn/ui/accordion.d.ts +8 -0
  433. package/storybook-static/shadcn/ui/accordion.d.ts.map +1 -0
  434. package/storybook-static/shadcn/ui/alert-dialog.d.ts +15 -0
  435. package/storybook-static/shadcn/ui/alert-dialog.d.ts.map +1 -0
  436. package/storybook-static/shadcn/ui/alert.d.ts +10 -0
  437. package/storybook-static/shadcn/ui/alert.d.ts.map +1 -0
  438. package/storybook-static/shadcn/ui/aspect-ratio.d.ts +4 -0
  439. package/storybook-static/shadcn/ui/aspect-ratio.d.ts.map +1 -0
  440. package/storybook-static/shadcn/ui/avatar.d.ts +7 -0
  441. package/storybook-static/shadcn/ui/avatar.d.ts.map +1 -0
  442. package/storybook-static/shadcn/ui/badge.d.ts +10 -0
  443. package/storybook-static/shadcn/ui/badge.d.ts.map +1 -0
  444. package/storybook-static/shadcn/ui/breadcrumb.d.ts +12 -0
  445. package/storybook-static/shadcn/ui/breadcrumb.d.ts.map +1 -0
  446. package/storybook-static/shadcn/ui/button.d.ts +11 -0
  447. package/storybook-static/shadcn/ui/button.d.ts.map +1 -0
  448. package/storybook-static/shadcn/ui/calendar.d.ts +9 -0
  449. package/storybook-static/shadcn/ui/calendar.d.ts.map +1 -0
  450. package/storybook-static/shadcn/ui/card.d.ts +10 -0
  451. package/storybook-static/shadcn/ui/card.d.ts.map +1 -0
  452. package/storybook-static/shadcn/ui/carousel.d.ts +20 -0
  453. package/storybook-static/shadcn/ui/carousel.d.ts.map +1 -0
  454. package/storybook-static/shadcn/ui/chart.d.ts +41 -0
  455. package/storybook-static/shadcn/ui/chart.d.ts.map +1 -0
  456. package/storybook-static/shadcn/ui/checkbox.d.ts +5 -0
  457. package/storybook-static/shadcn/ui/checkbox.d.ts.map +1 -0
  458. package/storybook-static/shadcn/ui/collapsible.d.ts +6 -0
  459. package/storybook-static/shadcn/ui/collapsible.d.ts.map +1 -0
  460. package/storybook-static/shadcn/ui/command.d.ts +19 -0
  461. package/storybook-static/shadcn/ui/command.d.ts.map +1 -0
  462. package/storybook-static/shadcn/ui/context-menu.d.ts +26 -0
  463. package/storybook-static/shadcn/ui/context-menu.d.ts.map +1 -0
  464. package/storybook-static/shadcn/ui/dialog.d.ts +16 -0
  465. package/storybook-static/shadcn/ui/dialog.d.ts.map +1 -0
  466. package/storybook-static/shadcn/ui/drawer.d.ts +14 -0
  467. package/storybook-static/shadcn/ui/drawer.d.ts.map +1 -0
  468. package/storybook-static/shadcn/ui/dropdown-menu.d.ts +26 -0
  469. package/storybook-static/shadcn/ui/dropdown-menu.d.ts.map +1 -0
  470. package/storybook-static/shadcn/ui/form.d.ts +25 -0
  471. package/storybook-static/shadcn/ui/form.d.ts.map +1 -0
  472. package/storybook-static/shadcn/ui/hover-card.d.ts +7 -0
  473. package/storybook-static/shadcn/ui/hover-card.d.ts.map +1 -0
  474. package/storybook-static/shadcn/ui/input-otp.d.ts +12 -0
  475. package/storybook-static/shadcn/ui/input-otp.d.ts.map +1 -0
  476. package/storybook-static/shadcn/ui/input.d.ts +4 -0
  477. package/storybook-static/shadcn/ui/input.d.ts.map +1 -0
  478. package/storybook-static/shadcn/ui/label.d.ts +5 -0
  479. package/storybook-static/shadcn/ui/label.d.ts.map +1 -0
  480. package/storybook-static/shadcn/ui/menubar.d.ts +27 -0
  481. package/storybook-static/shadcn/ui/menubar.d.ts.map +1 -0
  482. package/storybook-static/shadcn/ui/navigation-menu.d.ts +15 -0
  483. package/storybook-static/shadcn/ui/navigation-menu.d.ts.map +1 -0
  484. package/storybook-static/shadcn/ui/pagination.d.ts +14 -0
  485. package/storybook-static/shadcn/ui/pagination.d.ts.map +1 -0
  486. package/storybook-static/shadcn/ui/popover.d.ts +8 -0
  487. package/storybook-static/shadcn/ui/popover.d.ts.map +1 -0
  488. package/storybook-static/shadcn/ui/progress.d.ts +5 -0
  489. package/storybook-static/shadcn/ui/progress.d.ts.map +1 -0
  490. package/storybook-static/shadcn/ui/radio-group.d.ts +6 -0
  491. package/storybook-static/shadcn/ui/radio-group.d.ts.map +1 -0
  492. package/storybook-static/shadcn/ui/resizable.d.ts +9 -0
  493. package/storybook-static/shadcn/ui/resizable.d.ts.map +1 -0
  494. package/storybook-static/shadcn/ui/scroll-area.d.ts +6 -0
  495. package/storybook-static/shadcn/ui/scroll-area.d.ts.map +1 -0
  496. package/storybook-static/shadcn/ui/select.d.ts +16 -0
  497. package/storybook-static/shadcn/ui/select.d.ts.map +1 -0
  498. package/storybook-static/shadcn/ui/separator.d.ts +5 -0
  499. package/storybook-static/shadcn/ui/separator.d.ts.map +1 -0
  500. package/storybook-static/shadcn/ui/sheet.d.ts +14 -0
  501. package/storybook-static/shadcn/ui/sheet.d.ts.map +1 -0
  502. package/storybook-static/shadcn/ui/sidebar.d.ts +70 -0
  503. package/storybook-static/shadcn/ui/sidebar.d.ts.map +1 -0
  504. package/storybook-static/shadcn/ui/skeleton.d.ts +3 -0
  505. package/storybook-static/shadcn/ui/skeleton.d.ts.map +1 -0
  506. package/storybook-static/shadcn/ui/slider.d.ts +5 -0
  507. package/storybook-static/shadcn/ui/slider.d.ts.map +1 -0
  508. package/storybook-static/shadcn/ui/sonner.d.ts +4 -0
  509. package/storybook-static/shadcn/ui/sonner.d.ts.map +1 -0
  510. package/storybook-static/shadcn/ui/switch.d.ts +5 -0
  511. package/storybook-static/shadcn/ui/switch.d.ts.map +1 -0
  512. package/storybook-static/shadcn/ui/table.d.ts +11 -0
  513. package/storybook-static/shadcn/ui/table.d.ts.map +1 -0
  514. package/storybook-static/shadcn/ui/tabs.d.ts +8 -0
  515. package/storybook-static/shadcn/ui/tabs.d.ts.map +1 -0
  516. package/storybook-static/shadcn/ui/textarea.d.ts +4 -0
  517. package/storybook-static/shadcn/ui/textarea.d.ts.map +1 -0
  518. package/storybook-static/shadcn/ui/toggle-group.d.ts +8 -0
  519. package/storybook-static/shadcn/ui/toggle-group.d.ts.map +1 -0
  520. package/storybook-static/shadcn/ui/toggle.d.ts +10 -0
  521. package/storybook-static/shadcn/ui/toggle.d.ts.map +1 -0
  522. package/storybook-static/shadcn/ui/tooltip.d.ts +8 -0
  523. package/storybook-static/shadcn/ui/tooltip.d.ts.map +1 -0
  524. package/storybook-static/vite-inject-mocker-entry.js +18 -0
@@ -1,247 +1,797 @@
1
- import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
- import { cn } from '../../../shadcn/lib/utils';
3
- import { Popover, PopoverContent, PopoverTrigger } from '../../../shadcn/ui/popover';
1
+ import type React from "react";
4
2
  import {
5
- Command,
6
- CommandEmpty,
7
- CommandGroup,
8
- CommandInput,
9
- CommandItem,
10
- CommandList,
11
- CommandSeparator,
12
- } from '../../../shadcn/ui/command';
13
- import { ChevronsUpDown, Check, Loader2 } from 'lucide-react';
14
- import { Button } from '../../../shadcn/ui/button';
3
+ useCallback,
4
+ useEffect,
5
+ useMemo,
6
+ useRef,
7
+ useState,
8
+ useId,
9
+ } from "react";
10
+ import { cn } from "../../../shadcn/lib/utils";
11
+ import {
12
+ Popover,
13
+ PopoverContent,
14
+ PopoverTrigger,
15
+ } from "../../../shadcn/ui/popover";
16
+ import {
17
+ Command,
18
+ CommandEmpty,
19
+ CommandGroup,
20
+ CommandInput,
21
+ CommandItem,
22
+ CommandList,
23
+ CommandSeparator,
24
+ } from "../../../shadcn/ui/command";
25
+ import { ChevronsUpDown, Check, Loader2, X } from "lucide-react";
26
+ import { Badge } from "../../../shadcn/ui/badge";
15
27
  import type {
16
- AutocompleteFetcher,
17
- AutocompleteMode,
18
- AutocompleteOption,
19
- AutocompleteFetchResult,
20
- } from './types';
21
- import { useDebounce } from 'use-debounce';
28
+ AutocompleteFetcher,
29
+ AutocompleteMode,
30
+ AutocompleteOption,
31
+ AutocompleteFetchResult,
32
+ } from "./types";
33
+ import { useDebounce } from "use-debounce";
22
34
 
23
35
  export type AutocompleteProps = {
24
- mode: AutocompleteMode
25
- options?: AutocompleteOption[]
26
- fetcher?: AutocompleteFetcher
27
- pageSize?: number
28
- value?: string | number | null
29
- onChange?: (value: string | number | null, option: AutocompleteOption | null) => void
30
- placeholder?: string
31
- disabled?: boolean
32
- className?: string
33
- emptyText?: string
34
- renderOption?: (option: AutocompleteOption, selected: boolean) => React.ReactNode
35
- searchPlaceholder?: string
36
- /** Controls initial open state; component is uncontrolled otherwise */
37
- defaultOpen?: boolean
38
- }
36
+ mode: AutocompleteMode;
37
+ options?: AutocompleteOption[];
38
+ fetcher?: AutocompleteFetcher;
39
+ pageSize?: number;
40
+ /**
41
+ * Value can be a single primitive or an array when `multiple` is true
42
+ */
43
+ value?: string | number | null | Array<string | number>;
44
+ /**
45
+ * onChange returns a single value + option in single mode, or an array of values + options in multiple mode
46
+ */
47
+ onChange?: (
48
+ value: string | number | null | Array<string | number>,
49
+ option: AutocompleteOption | AutocompleteOption[] | null,
50
+ ) => void;
51
+ /** Enable selecting multiple values (shows chips) */
52
+ multiple?: boolean;
53
+ /** Placeholder shown when nothing is selected */
54
+ placeholder?: string;
55
+ disabled?: boolean;
56
+ className?: string;
57
+ emptyText?: string;
58
+ renderOption?: (
59
+ option: AutocompleteOption,
60
+ selected: boolean,
61
+ ) => React.ReactNode;
62
+ searchPlaceholder?: string;
63
+ /** Controls initial open state; component is uncontrolled otherwise */
64
+ defaultOpen?: boolean;
65
+ /** Initial value when component is uncontrolled */
66
+ defaultValue?: string | number | null | Array<string | number>;
67
+ /** Allow entering custom values not present in options (useful for tagging) */
68
+ allowCustomValue?: boolean;
69
+ /**
70
+ * Chip visual style for multiple selection. Uses shadcn Badge variants.
71
+ * default | secondary | destructive | outline
72
+ */
73
+ chipVariant?: "default" | "secondary" | "destructive" | "outline";
74
+ /** Additional className for each chip */
75
+ chipClassName?: string;
76
+ /** Show a clear button when a selection exists */
77
+ clearable?: boolean;
78
+ /**
79
+ * Optional: seed selected labels for edit pages. These options are only used to populate the
80
+ * internal label map so labels render correctly when values are prefilled.
81
+ */
82
+ initialSelectedOptions?: AutocompleteOption | AutocompleteOption[] | null;
83
+ /**
84
+ * Optional: load labels/options for a list of values whose labels are unknown.
85
+ * Useful for edit pages in server mode when only values are available.
86
+ */
87
+ loadSelected?: (values: Array<string | number>) => Promise<AutocompleteOption[]>;
88
+ };
39
89
 
40
90
  const DEFAULT_PAGE_SIZE = 20;
41
91
 
42
92
  const EMPTY_OPTIONS: AutocompleteOption[] = [];
43
93
 
44
94
  export function Autocomplete({
45
- mode,
46
- options = EMPTY_OPTIONS,
47
- fetcher,
48
- pageSize = DEFAULT_PAGE_SIZE,
49
- value: controlledValue,
50
- onChange,
51
- placeholder = 'Select...',
52
- disabled,
53
- className,
54
- emptyText = 'No results found',
55
- renderOption,
56
- searchPlaceholder = 'Search...',
57
- defaultOpen,
95
+ mode,
96
+ options = EMPTY_OPTIONS,
97
+ fetcher,
98
+ pageSize = DEFAULT_PAGE_SIZE,
99
+ value: controlledValue,
100
+ onChange,
101
+ multiple = false,
102
+ placeholder = "Select...",
103
+ disabled,
104
+ className,
105
+ emptyText = "No results found",
106
+ renderOption,
107
+ searchPlaceholder = "Search...",
108
+ defaultOpen,
109
+ defaultValue,
110
+ allowCustomValue = false,
111
+ chipVariant = "secondary",
112
+ chipClassName,
113
+ clearable = true,
114
+ initialSelectedOptions,
115
+ loadSelected,
58
116
  }: AutocompleteProps) {
59
- const [open, setOpen] = useState<boolean>(!!defaultOpen);
60
- const [search, setSearch] = useState('');
61
- const [debouncedSearch] = useDebounce(search, 250);
62
-
63
- // Selection
64
- const [value, setValue] = useState<string | number | null>(controlledValue ?? null);
65
- useEffect(() => {
66
- if (controlledValue !== undefined) setValue(controlledValue);
67
- }, [controlledValue]);
68
-
69
- const handleSelect = useCallback(
70
- (next: AutocompleteOption) => {
71
- const newValue = next.value;
72
- if (controlledValue === undefined) setValue(newValue);
73
- onChange?.(newValue, next);
74
- setOpen(false);
75
- },
76
- [controlledValue, onChange],
77
- );
78
-
79
- // Data state (shared for both modes)
80
- const [items, setItems] = useState<AutocompleteOption[]>([]);
81
- const [loading, setLoading] = useState(false);
82
- const [hasMore, setHasMore] = useState(false);
83
- const [nextCursor, setNextCursor] = useState<string | number | null | undefined>(undefined);
84
- const [page, setPage] = useState(1);
85
-
86
- const resetData = useCallback(() => {
87
- setItems([]);
88
- setHasMore(false);
89
- setNextCursor(undefined);
90
- setPage(1);
91
- }, []);
92
-
93
- // Load data
94
- const load = useCallback(async () => {
95
- if (mode === 'server') {
96
- if (!fetcher) return;
97
- setLoading(true);
98
- try {
99
- const res: AutocompleteFetchResult = await fetcher({
100
- search: debouncedSearch,
101
- cursor: nextCursor ?? null,
102
- page,
103
- pageSize,
104
- });
105
- setItems(prev => (page === 1 ? res.items : [...prev, ...res.items]));
106
- setHasMore(!!res.hasMore);
107
- setNextCursor(res.nextCursor);
108
- } finally {
109
- setLoading(false);
110
- }
111
- } else {
112
- // client mode: filter and paginate locally
113
- setLoading(true);
114
- try {
115
- const filtered = debouncedSearch
116
- ? options.filter(o =>
117
- o.label.toLowerCase().includes(debouncedSearch.toLowerCase()),
118
- )
119
- : options;
120
- const start = (page - 1) * pageSize;
121
- const slice = filtered.slice(start, start + pageSize);
122
- setItems(prev => (page === 1 ? slice : [...prev, ...slice]));
123
- setHasMore(start + pageSize < filtered.length);
124
- setNextCursor(undefined);
125
- } finally {
126
- setLoading(false);
127
- }
128
- }
129
- }, [mode, fetcher, debouncedSearch, nextCursor, page, pageSize, options]);
130
-
131
- // Reset and load on open/search change
132
- useEffect(() => {
133
- if (!open) return;
134
- resetData();
135
- // Load first page
136
- const t = window.setTimeout(() => {
137
- void load();
138
- }, 0);
139
- return () => window.clearTimeout(t);
140
- }, [open, debouncedSearch, mode]);
141
-
142
- // Infinite scroll
143
- const listRef = useRef<HTMLDivElement | null>(null);
144
- const onListScroll = useCallback(() => {
145
- const el = listRef.current;
146
- if (!el || loading) return;
147
- const nearBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 24;
148
- if (nearBottom && hasMore) {
149
- setPage(p => p + 1);
150
- }
151
- }, [loading, hasMore]);
152
-
153
- useEffect(() => {
154
- if (!open) return;
155
-
156
- load();
157
- }, [page]);
158
-
159
- // Selected label
160
- const selectedOption = useMemo(() => items.find(i => i.value === value), [items, value]);
161
-
162
- // Ensure selected label when item not in current page (server mode)
163
- const displayedLabel = useMemo(() => {
164
- if (selectedOption) return selectedOption.label;
165
- if (mode === 'client') {
166
- const found = options.find(i => i.value === value);
167
- return found?.label ?? placeholder;
168
- }
169
- return placeholder;
170
- }, [mode, options, selectedOption, value, placeholder]);
171
-
172
- return (
173
- <Popover open={open} onOpenChange={setOpen}>
174
- <PopoverTrigger asChild>
175
- <Button
176
- type="button"
177
- variant="outline"
178
- role="combobox"
179
- aria-expanded={open}
180
- className={cn('w-full justify-between', className)}
181
- disabled={disabled}
182
- >
183
- <span className={cn('truncate', !value && 'text-muted-foreground')}>{displayedLabel}</span>
184
- <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
185
- </Button>
186
- </PopoverTrigger>
187
- <PopoverContent className="w-[--radix-popover-trigger-width] p-0" align="start">
188
- <Command shouldFilter={false} className="w-full">
189
- <div className="p-2">
190
- <CommandInput
191
- value={search}
192
- onValueChange={setSearch}
193
- placeholder={searchPlaceholder}
194
- autoFocus
195
- />
196
- </div>
197
- <CommandList className="max-h-56 overflow-auto" ref={listRef} onScroll={onListScroll}>
198
- {loading && items.length === 0 ? (
199
- <div className="flex items-center justify-center py-6 text-sm text-muted-foreground">
200
- <Loader2 className="mr-2 h-4 w-4 animate-spin" /> Loading
201
- </div>
202
- ) : null}
203
- <CommandEmpty>{emptyText}</CommandEmpty>
204
- {items.length > 0 ? (
205
- <CommandGroup>
206
- {items.map((item) => {
207
- const selected = item.value === value;
208
- return (
209
- <CommandItem
210
- key={`${item.value}`}
211
- value={`${item.label}`}
212
- onSelect={() => handleSelect(item)}
213
- className="flex items-center justify-between"
214
- >
215
- <div className="min-w-0 truncate">
216
- {renderOption ? renderOption(item, selected) : item.label}
217
- </div>
218
- {selected ? (
219
- <Check className="h-4 w-4" />
220
- ) : null}
221
- </CommandItem>
222
- );
223
- })}
224
- </CommandGroup>
225
- ) : null}
226
- {hasMore ? (
227
- <>
228
- <CommandSeparator />
229
- <div className="flex items-center justify-center py-2 text-xs text-muted-foreground">
230
- {loading ? (
231
- <>
232
- <Loader2 className="mr-1 h-3 w-3 animate-spin" /> Loading more
233
- </>
234
- ) : (
235
- 'Scroll to load more'
236
- )}
237
- </div>
238
- </>
239
- ) : null}
240
- </CommandList>
241
- </Command>
242
- </PopoverContent>
243
- </Popover>
244
- );
117
+ const [open, setOpen] = useState<boolean>(!!defaultOpen);
118
+ const [search, setSearch] = useState("");
119
+ const [debouncedSearch] = useDebounce(search, 250);
120
+ const listId = useId();
121
+
122
+ // Selection
123
+ const isMultiple = !!multiple;
124
+ const [value, setValue] = useState<
125
+ string | number | null | Array<string | number>
126
+ >(() => {
127
+ if (controlledValue !== undefined) return controlledValue;
128
+ if (defaultValue !== undefined) return defaultValue;
129
+ return isMultiple ? [] : null;
130
+ });
131
+ useEffect(() => {
132
+ if (controlledValue !== undefined) setValue(controlledValue);
133
+ }, [controlledValue]);
134
+
135
+ // Keep a map of value -> label to ensure we can render chips/labels even if the option
136
+ // is not present in the current page (especially in server mode or for custom values)
137
+ const labelMapRef = useRef<Map<string | number, string>>(new Map());
138
+ const addToLabelMap = useCallback((opt: AutocompleteOption) => {
139
+ labelMapRef.current.set(opt.value, opt.label);
140
+ }, []);
141
+ // Tick to force re-render when labels hydrate via async
142
+ const [labelTick, setLabelTick] = useState(0);
143
+ const getLabel = useCallback(
144
+ (v: string | number) =>
145
+ labelMapRef.current.get(v) ??
146
+ options.find((o) => o.value === v)?.label ??
147
+ (loadSelected ? "Loading..." : String(v)),
148
+ [options, loadSelected],
149
+ );
150
+
151
+ const handleSelect = useCallback(
152
+ (next: AutocompleteOption) => {
153
+ addToLabelMap(next);
154
+ if (isMultiple) {
155
+ const prevValues = Array.isArray(value) ? value : [];
156
+ const exists = prevValues.some((v) => v === next.value);
157
+ const newValues = exists
158
+ ? prevValues.filter((v) => v !== next.value)
159
+ : [...prevValues, next.value];
160
+
161
+ if (controlledValue === undefined) setValue(newValues);
162
+ const selectedOptions: AutocompleteOption[] = newValues.map((v) => ({
163
+ value: v,
164
+ label: getLabel(v),
165
+ }));
166
+ onChange?.(newValues, selectedOptions);
167
+ // Keep open for multi-select
168
+ } else {
169
+ const newValue = next.value;
170
+ if (controlledValue === undefined) setValue(newValue);
171
+ onChange?.(newValue, next);
172
+ setOpen(false);
173
+ }
174
+ },
175
+ [addToLabelMap, controlledValue, getLabel, isMultiple, onChange, value],
176
+ );
177
+
178
+ // Data state (shared for both modes)
179
+ const [items, setItems] = useState<AutocompleteOption[]>([]);
180
+ const [loading, setLoading] = useState(false);
181
+ const [hasMore, setHasMore] = useState(false);
182
+ const [nextCursor, setNextCursor] = useState<
183
+ string | number | null | undefined
184
+ >(undefined);
185
+ const [page, setPage] = useState(1);
186
+
187
+ const resetData = useCallback(() => {
188
+ setItems([]);
189
+ setHasMore(false);
190
+ setNextCursor(undefined);
191
+ setPage(1);
192
+ }, []);
193
+
194
+ // Load data
195
+ const load = useCallback(async () => {
196
+ if (mode === "server") {
197
+ if (!fetcher) return;
198
+ setLoading(true);
199
+ try {
200
+ const res: AutocompleteFetchResult = await fetcher({
201
+ search: debouncedSearch,
202
+ cursor: nextCursor ?? null,
203
+ page,
204
+ pageSize,
205
+ });
206
+ setItems((prev) => (page === 1 ? res.items : [...prev, ...res.items]));
207
+ setHasMore(!!res.hasMore);
208
+ setNextCursor(res.nextCursor);
209
+ } finally {
210
+ setLoading(false);
211
+ }
212
+ } else {
213
+ // client mode: filter and paginate locally
214
+ setLoading(true);
215
+ try {
216
+ const filtered = debouncedSearch
217
+ ? options.filter((o) =>
218
+ o.label.toLowerCase().includes(debouncedSearch.toLowerCase()),
219
+ )
220
+ : options;
221
+ const start = (page - 1) * pageSize;
222
+ const slice = filtered.slice(start, start + pageSize);
223
+ setItems((prev) => (page === 1 ? slice : [...prev, ...slice]));
224
+ setHasMore(start + pageSize < filtered.length);
225
+ setNextCursor(undefined);
226
+ } finally {
227
+ setLoading(false);
228
+ }
229
+ }
230
+ }, [mode, fetcher, debouncedSearch, nextCursor, page, pageSize, options]);
231
+
232
+ // Keep a ref to latest load() to avoid stale closures
233
+ const loadRef = useRef(load);
234
+ useEffect(() => {
235
+ loadRef.current = load;
236
+ }, [load]);
237
+
238
+ // Reset and load on open/search change (do NOT depend on load to avoid resets during pagination)
239
+ useEffect(() => {
240
+ if (!open) return;
241
+ // Reference debouncedSearch to intentionally re-run on search changes
242
+ void debouncedSearch;
243
+ resetData();
244
+ const t = window.setTimeout(() => {
245
+ void loadRef.current();
246
+ }, 0);
247
+ return () => window.clearTimeout(t);
248
+ }, [open, debouncedSearch, resetData]);
249
+
250
+ // Load subsequent pages when page changes (>1)
251
+ useEffect(() => {
252
+ if (!open) return;
253
+ if (page <= 1) return;
254
+ void loadRef.current();
255
+ }, [open, page]);
256
+
257
+ // Infinite scroll
258
+ const listRef = useRef<HTMLDivElement | null>(null);
259
+ const onListScroll = useCallback(() => {
260
+ const el = listRef.current;
261
+ if (!el || loading) return;
262
+ const nearBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 24;
263
+ if (nearBottom && hasMore) {
264
+ setPage((p) => p + 1);
265
+ }
266
+ }, [loading, hasMore]);
267
+
268
+ // Prime label map from loaded items and static options
269
+ useEffect(() => {
270
+ items.forEach(addToLabelMap);
271
+ }, [items, addToLabelMap]);
272
+ useEffect(() => {
273
+ options.forEach(addToLabelMap);
274
+ }, [options, addToLabelMap]);
275
+ // Seed label map from explicitly provided initialSelectedOptions
276
+ useEffect(() => {
277
+ if (!initialSelectedOptions) return;
278
+ const arr = Array.isArray(initialSelectedOptions)
279
+ ? initialSelectedOptions
280
+ : [initialSelectedOptions];
281
+ arr.forEach(addToLabelMap);
282
+ setLabelTick((t) => t + 1);
283
+ }, [initialSelectedOptions, addToLabelMap]);
284
+
285
+ // Resolve labels for current values if missing and a resolver is provided
286
+ useEffect(() => {
287
+ if (!loadSelected) return;
288
+ const curValues: Array<string | number> = Array.isArray(value)
289
+ ? (isMultiple ? (value as Array<string | number>) : [])
290
+ : value !== null && value !== undefined
291
+ ? [value as string | number]
292
+ : [];
293
+ if (curValues.length === 0) return;
294
+ const missing = curValues.filter(
295
+ (v) => !labelMapRef.current.has(v) && !options.some((o) => o.value === v),
296
+ );
297
+ if (missing.length === 0) return;
298
+ let cancelled = false;
299
+ loadSelected(missing)
300
+ .then((opts) => {
301
+ if (cancelled) return;
302
+ opts.forEach(addToLabelMap);
303
+ setLabelTick((t) => t + 1);
304
+ })
305
+ .catch(() => {
306
+ /* swallow resolver errors */
307
+ });
308
+ return () => {
309
+ cancelled = true;
310
+ };
311
+ // include options so we don't resolve when already present
312
+ }, [value, isMultiple, loadSelected, options, addToLabelMap]);
313
+
314
+ // Selected label
315
+ const selectedOption = useMemo(() => {
316
+ if (isMultiple || Array.isArray(value)) return undefined;
317
+ return items.find((i) => i.value === value);
318
+ }, [isMultiple, items, value]);
319
+
320
+ // Ensure selected label when item not in current page (server mode)
321
+ // biome-ignore lint/correctness/useExhaustiveDependencies: labelTick intentionally triggers recompute when labelMap hydrates
322
+ const displayedLabel = useMemo(() => {
323
+ if (isMultiple || Array.isArray(value)) return placeholder;
324
+ if (selectedOption) return selectedOption.label;
325
+ const v = value;
326
+ if (v !== null && v !== undefined && !Array.isArray(v)) {
327
+ const mapped = labelMapRef.current.get(v);
328
+ if (mapped) return mapped;
329
+ if (mode === "client") {
330
+ const found = options.find((i) => i.value === v);
331
+ return found?.label ?? placeholder;
332
+ }
333
+ }
334
+ return placeholder;
335
+ }, [isMultiple, mode, options, selectedOption, value, placeholder, labelTick]);
336
+
337
+
338
+ const selectedValues: Array<string | number> = useMemo(
339
+ () => (isMultiple && Array.isArray(value) ? value : []),
340
+ [isMultiple, value],
341
+ );
342
+ // biome-ignore lint/correctness/useExhaustiveDependencies: labelTick intentionally triggers recompute when labelMap hydrates
343
+ const selectedOptionsMulti: AutocompleteOption[] = useMemo(
344
+ () => selectedValues.map((v) => ({ value: v, label: getLabel(v) })),
345
+ [getLabel, selectedValues, labelTick],
346
+ );
347
+
348
+ const handleClear = useCallback(() => {
349
+ if (isMultiple) {
350
+ if (controlledValue === undefined) setValue([]);
351
+ onChange?.([], []);
352
+ } else {
353
+ if (controlledValue === undefined) setValue(null);
354
+ onChange?.(null, null);
355
+ }
356
+ }, [controlledValue, isMultiple, onChange]);
357
+
358
+ // Helper: add custom value from current search
359
+ const addCustomValue = useCallback(
360
+ (text: string) => {
361
+ const t = text.trim();
362
+ if (!t) return;
363
+ const created: AutocompleteOption = { value: t, label: t };
364
+ addToLabelMap(created);
365
+ if (isMultiple) {
366
+ const prevValues = Array.isArray(value) ? value : [];
367
+ const exists = prevValues.some((v) => v === created.value);
368
+ const newValues = exists ? prevValues : [...prevValues, created.value];
369
+ if (controlledValue === undefined) setValue(newValues);
370
+ const newOptions = newValues.map((v) => ({
371
+ value: v,
372
+ label: getLabel(v),
373
+ }));
374
+ onChange?.(newValues, newOptions);
375
+ setSearch("");
376
+ } else {
377
+ if (controlledValue === undefined) setValue(created.value);
378
+ onChange?.(created.value, created);
379
+ setSearch("");
380
+ setOpen(false);
381
+ }
382
+ },
383
+ [addToLabelMap, controlledValue, getLabel, isMultiple, onChange, value],
384
+ );
385
+
386
+ const inlineInputRef = useRef<HTMLInputElement | null>(null);
387
+ const canOpen = useMemo(() => {
388
+ // When purely tagging (no static options and no fetcher) in client mode with multi+allowCustomValue,
389
+ // we do not show the dropdown; user types inline.
390
+ const pureTagging =
391
+ isMultiple &&
392
+ allowCustomValue &&
393
+ mode === "client" &&
394
+ options.length === 0 &&
395
+ !fetcher;
396
+ return !pureTagging;
397
+ }, [allowCustomValue, fetcher, isMultiple, mode, options.length]);
398
+ useEffect(() => {
399
+ if (!canOpen && open) setOpen(false);
400
+ }, [canOpen, open]);
401
+
402
+ return (
403
+ <Popover open={open} onOpenChange={setOpen}>
404
+ {canOpen ? (
405
+ <PopoverTrigger asChild>
406
+ <div
407
+ // biome-ignore lint/a11y/useSemanticElements: <explanation>
408
+ role="combobox"
409
+ aria-expanded={open}
410
+ aria-controls={listId}
411
+ tabIndex={disabled ? -1 : 0}
412
+ aria-disabled={disabled || undefined}
413
+ className={cn(
414
+ "w-full inline-flex items-center justify-between rounded-md border bg-background px-3 py-2 text-sm shadow-sm transition-colors",
415
+ "hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
416
+ disabled && "opacity-50 pointer-events-none",
417
+ className,
418
+ )}
419
+ onKeyDown={(e) => {
420
+ if (disabled || !canOpen) return;
421
+ if (e.target instanceof HTMLInputElement) return; // let input handle keys
422
+ if (e.key === "Enter" || e.key === " ") {
423
+ e.preventDefault();
424
+ setOpen((v) => !v);
425
+ }
426
+ }}
427
+ >
428
+ {isMultiple ? (
429
+ <div
430
+ className={cn(
431
+ "flex min-w-0 flex-1 flex-wrap items-center gap-1 text-left",
432
+ )}
433
+ >
434
+ {selectedOptionsMulti.length > 0
435
+ ? selectedOptionsMulti.map((opt) => (
436
+ <Badge
437
+ key={`${opt.value}`}
438
+ variant={chipVariant}
439
+ className={cn("pr-1", chipClassName)}
440
+ >
441
+ <span className="truncate max-w-[10rem]">
442
+ {opt.label}
443
+ </span>
444
+ <button
445
+ type="button"
446
+ aria-label={`Remove ${opt.label}`}
447
+ className="ml-1 inline-flex items-center rounded-sm hover:bg-black/5 dark:hover:bg-white/10"
448
+ onMouseDown={(e) => {
449
+ e.preventDefault();
450
+ e.stopPropagation();
451
+ }}
452
+ onClick={(e) => {
453
+ e.preventDefault();
454
+ e.stopPropagation();
455
+ const prevValues = Array.isArray(value)
456
+ ? value
457
+ : [];
458
+ const newValues = prevValues.filter(
459
+ (v) => v !== opt.value,
460
+ );
461
+ if (controlledValue === undefined)
462
+ setValue(newValues);
463
+ const newOptions = newValues.map((v) => ({
464
+ value: v,
465
+ label: getLabel(v),
466
+ }));
467
+ onChange?.(newValues, newOptions);
468
+ }}
469
+ >
470
+ <X className="h-3 w-3" />
471
+ </button>
472
+ </Badge>
473
+ ))
474
+ : null}
475
+ {allowCustomValue ? (
476
+ <input
477
+ ref={inlineInputRef}
478
+ value={search}
479
+ onChange={(e) => setSearch(e.target.value)}
480
+ placeholder={
481
+ selectedOptionsMulti.length === 0
482
+ ? placeholder
483
+ : undefined
484
+ }
485
+ className="flex-1 min-w-[8ch] bg-transparent outline-none text-sm placeholder:text-muted-foreground"
486
+ onKeyDown={(e) => {
487
+ if (e.key === "Enter" || e.key === ",") {
488
+ e.preventDefault();
489
+ addCustomValue(search);
490
+ } else if (
491
+ e.key === "Backspace" &&
492
+ search === "" &&
493
+ selectedOptionsMulti.length > 0
494
+ ) {
495
+ // Remove last chip when input is empty
496
+ const prevValues = Array.isArray(value) ? value : [];
497
+ const newValues = prevValues.slice(0, -1);
498
+ if (controlledValue === undefined) setValue(newValues);
499
+ const newOptions = newValues.map((v) => ({
500
+ value: v,
501
+ label: getLabel(v),
502
+ }));
503
+ onChange?.(newValues, newOptions);
504
+ }
505
+ }}
506
+ />
507
+ ) : null}
508
+ {selectedOptionsMulti.length === 0 && !allowCustomValue ? (
509
+ <span className="truncate text-muted-foreground">
510
+ {placeholder}
511
+ </span>
512
+ ) : null}
513
+ </div>
514
+ ) : (
515
+ <span
516
+ className={cn(
517
+ "truncate",
518
+ (!value || Array.isArray(value)) && "text-muted-foreground",
519
+ )}
520
+ >
521
+ {displayedLabel}
522
+ </span>
523
+ )}
524
+ {clearable &&
525
+ ((isMultiple && selectedOptionsMulti.length > 0) ||
526
+ (!isMultiple &&
527
+ value !== null &&
528
+ value !== undefined &&
529
+ !Array.isArray(value))) ? (
530
+ <button
531
+ type="button"
532
+ aria-label="Clear selection"
533
+ className="ml-2 inline-flex items-center rounded-sm p-1 hover:bg-black/5 dark:hover:bg-white/10"
534
+ onMouseDown={(e) => {
535
+ e.preventDefault();
536
+ e.stopPropagation();
537
+ }}
538
+ onClick={(e) => {
539
+ e.preventDefault();
540
+ e.stopPropagation();
541
+ handleClear();
542
+ }}
543
+ onKeyDown={(e) => {
544
+ if (e.key === "Enter" || e.key === " ") {
545
+ e.preventDefault();
546
+ e.stopPropagation();
547
+ handleClear();
548
+ }
549
+ }}
550
+ >
551
+ <X className="h-4 w-4 opacity-60" />
552
+ </button>
553
+ ) : null}
554
+ <ChevronsUpDown
555
+ className={cn(
556
+ "ml-2 h-4 w-4 shrink-0 opacity-50",
557
+ !canOpen && "hidden",
558
+ )}
559
+ />
560
+ </div>
561
+ </PopoverTrigger>
562
+ ) : (
563
+ <div
564
+ // biome-ignore lint/a11y/useSemanticElements: <explanation>
565
+ role="combobox"
566
+ aria-expanded={open}
567
+ aria-controls={listId}
568
+ tabIndex={disabled ? -1 : 0}
569
+ aria-disabled={disabled || undefined}
570
+ className={cn(
571
+ "w-full inline-flex items-center justify-between rounded-md border bg-background px-3 py-2 text-sm shadow-sm transition-colors",
572
+ "hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
573
+ disabled && "opacity-50 pointer-events-none",
574
+ className,
575
+ )}
576
+ onKeyDown={(_e) => {
577
+ if (disabled || canOpen) return;
578
+ // Do not toggle popover; handle inline input only
579
+ }}
580
+ >
581
+ {isMultiple ? (
582
+ <div
583
+ className={cn(
584
+ "flex min-w-0 flex-1 flex-wrap items-center gap-1 text-left",
585
+ )}
586
+ >
587
+ {selectedOptionsMulti.length > 0
588
+ ? selectedOptionsMulti.map((opt) => (
589
+ <Badge
590
+ key={`${opt.value}`}
591
+ variant={chipVariant}
592
+ className={cn("pr-1", chipClassName)}
593
+ >
594
+ <span className="truncate max-w-[10rem]">
595
+ {opt.label}
596
+ </span>
597
+ <button
598
+ type="button"
599
+ aria-label={`Remove ${opt.label}`}
600
+ className="ml-1 inline-flex items-center rounded-sm hover:bg-black/5 dark:hover:bg-white/10"
601
+ onMouseDown={(e) => {
602
+ e.preventDefault();
603
+ e.stopPropagation();
604
+ }}
605
+ onClick={(e) => {
606
+ e.preventDefault();
607
+ e.stopPropagation();
608
+ const prevValues = Array.isArray(value) ? value : [];
609
+ const newValues = prevValues.filter(
610
+ (v) => v !== opt.value,
611
+ );
612
+ if (controlledValue === undefined)
613
+ setValue(newValues);
614
+ const newOptions = newValues.map((v) => ({
615
+ value: v,
616
+ label: getLabel(v),
617
+ }));
618
+ onChange?.(newValues, newOptions);
619
+ }}
620
+ >
621
+ <X className="h-3 w-3" />
622
+ </button>
623
+ </Badge>
624
+ ))
625
+ : null}
626
+ {allowCustomValue ? (
627
+ <input
628
+ ref={inlineInputRef}
629
+ value={search}
630
+ onChange={(e) => setSearch(e.target.value)}
631
+ placeholder={
632
+ selectedOptionsMulti.length === 0 ? placeholder : undefined
633
+ }
634
+ className="flex-1 min-w-[8ch] bg-transparent outline-none text-sm placeholder:text-muted-foreground"
635
+ onKeyDown={(e) => {
636
+ if (e.key === "Enter" || e.key === ",") {
637
+ e.preventDefault();
638
+ addCustomValue(search);
639
+ } else if (
640
+ e.key === "Backspace" &&
641
+ search === "" &&
642
+ selectedOptionsMulti.length > 0
643
+ ) {
644
+ const prevValues = Array.isArray(value) ? value : [];
645
+ const newValues = prevValues.slice(0, -1);
646
+ if (controlledValue === undefined) setValue(newValues);
647
+ const newOptions = newValues.map((v) => ({
648
+ value: v,
649
+ label: getLabel(v),
650
+ }));
651
+ onChange?.(newValues, newOptions);
652
+ }
653
+ }}
654
+ />
655
+ ) : null}
656
+ {selectedOptionsMulti.length === 0 && !allowCustomValue ? (
657
+ <span className="truncate text-muted-foreground">
658
+ {placeholder}
659
+ </span>
660
+ ) : null}
661
+ </div>
662
+ ) : (
663
+ <span
664
+ className={cn(
665
+ "truncate",
666
+ (!value || Array.isArray(value)) && "text-muted-foreground",
667
+ )}
668
+ >
669
+ {displayedLabel}
670
+ </span>
671
+ )}
672
+ {clearable &&
673
+ ((isMultiple && selectedOptionsMulti.length > 0) ||
674
+ (!isMultiple &&
675
+ value !== null &&
676
+ value !== undefined &&
677
+ !Array.isArray(value))) ? (
678
+ <button
679
+ type="button"
680
+ aria-label="Clear selection"
681
+ className="ml-2 inline-flex items-center rounded-sm p-1 hover:bg-black/5 dark:hover:bg-white/10"
682
+ onMouseDown={(e) => {
683
+ e.preventDefault();
684
+ e.stopPropagation();
685
+ }}
686
+ onClick={(e) => {
687
+ e.preventDefault();
688
+ e.stopPropagation();
689
+ handleClear();
690
+ }}
691
+ onKeyDown={(e) => {
692
+ if (e.key === "Enter" || e.key === " ") {
693
+ e.preventDefault();
694
+ e.stopPropagation();
695
+ handleClear();
696
+ }
697
+ }}
698
+ >
699
+ <X className="h-4 w-4 opacity-60" />
700
+ </button>
701
+ ) : null}
702
+ <ChevronsUpDown
703
+ className={cn(
704
+ "ml-2 h-4 w-4 shrink-0 opacity-50",
705
+ !canOpen && "hidden",
706
+ )}
707
+ />
708
+ </div>
709
+ )}
710
+ {canOpen ? (
711
+ <PopoverContent
712
+ className="w-[--radix-popover-trigger-width] p-0"
713
+ align="start"
714
+ >
715
+ <Command shouldFilter={false} className="w-full">
716
+ <div className="p-2">
717
+ <CommandInput
718
+ value={search}
719
+ onValueChange={setSearch}
720
+ placeholder={searchPlaceholder}
721
+ autoFocus
722
+ onKeyDown={(e) => {
723
+ if (e.key === "Enter" && allowCustomValue && search.trim()) {
724
+ e.preventDefault();
725
+ addCustomValue(search);
726
+ }
727
+ }}
728
+ />
729
+ </div>
730
+ <CommandList
731
+ id={listId}
732
+ className="max-h-56 overflow-auto"
733
+ ref={listRef}
734
+ onScroll={onListScroll}
735
+ >
736
+ {loading && items.length === 0 ? (
737
+ <div className="flex items-center justify-center py-6 text-sm text-muted-foreground">
738
+ <Loader2 className="mr-2 h-4 w-4 animate-spin" /> Loading
739
+ </div>
740
+ ) : null}
741
+ <CommandEmpty>
742
+ {allowCustomValue && search.trim() ? (
743
+ <span>Press Enter to add "{search.trim()}"</span>
744
+ ) : (
745
+ emptyText
746
+ )}
747
+ </CommandEmpty>
748
+ {items.length > 0 ? (
749
+ <CommandGroup>
750
+ {items.map((item) => {
751
+ const selected = isMultiple
752
+ ? Array.isArray(value)
753
+ ? value.includes(item.value)
754
+ : false
755
+ : item.value === value;
756
+ return (
757
+ <CommandItem
758
+ key={`${item.value}`}
759
+ value={`${item.label}`}
760
+ onSelect={() => handleSelect(item)}
761
+ className="flex items-center justify-between"
762
+ >
763
+ <div className="min-w-0 truncate">
764
+ {renderOption
765
+ ? renderOption(item, selected)
766
+ : item.label}
767
+ </div>
768
+ {selected ? <Check className="h-4 w-4" /> : null}
769
+ </CommandItem>
770
+ );
771
+ })}
772
+ </CommandGroup>
773
+ ) : null}
774
+ {hasMore ? (
775
+ <>
776
+ <CommandSeparator />
777
+ <div className="flex items-center justify-center py-2 text-xs text-muted-foreground">
778
+ {loading ? (
779
+ <>
780
+ <Loader2 className="mr-1 h-3 w-3 animate-spin" />{" "}
781
+ Loading more
782
+ </>
783
+ ) : (
784
+ "Scroll to load more"
785
+ )}
786
+ </div>
787
+ </>
788
+ ) : null}
789
+ </CommandList>
790
+ </Command>
791
+ </PopoverContent>
792
+ ) : null}
793
+ </Popover>
794
+ );
245
795
  }
246
796
 
247
797
  export default Autocomplete;