@keboola/design 11.6.1 → 12.0.0

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 (365) hide show
  1. package/AGENTS.md +50 -9
  2. package/CHANGELOG.md +241 -0
  3. package/COMPONENT-API.md +337 -288
  4. package/README.md +12 -2
  5. package/dist/{AIKit-CQxVwyAk.js → AIKit-BD4r7ff-.js} +807 -199
  6. package/dist/AIKit-BD4r7ff-.js.map +1 -0
  7. package/dist/{Alert-C4Y9IwMI.js → Alert-UI-CIs-1.js} +16 -16
  8. package/dist/Alert-UI-CIs-1.js.map +1 -0
  9. package/dist/{AlertModal-BGJdaRRj.js → AlertModal-Th2khjPi.js} +5 -5
  10. package/dist/AlertModal-Th2khjPi.js.map +1 -0
  11. package/dist/{AppShell-DRgJxpXW.js → AppShell-WSQabK8r.js} +15 -52
  12. package/dist/AppShell-WSQabK8r.js.map +1 -0
  13. package/dist/{AutoSaveTextarea-BeuWuszr.js → AutoSaveTextarea-C5iIr2Ts.js} +2 -2
  14. package/dist/{AutoSaveTextarea-BeuWuszr.js.map → AutoSaveTextarea-C5iIr2Ts.js.map} +1 -1
  15. package/dist/{Badge-o5jURtpB.js → Badge-DIjhwPvh.js} +4 -9
  16. package/dist/Badge-DIjhwPvh.js.map +1 -0
  17. package/dist/{BrandEditor-CS9P4r2p.js → BrandEditor-BU23Vl8V.js} +7 -7
  18. package/dist/{BrandEditor-CS9P4r2p.js.map → BrandEditor-BU23Vl8V.js.map} +1 -1
  19. package/dist/{BrandLogo-CoKBk4MI.js → BrandLogo-CKpVSZb6.js} +4 -4
  20. package/dist/BrandLogo-CKpVSZb6.js.map +1 -0
  21. package/dist/{Breadcrumb-D1id7YXd.js → Breadcrumb-p9HtMLCc.js} +8 -14
  22. package/dist/Breadcrumb-p9HtMLCc.js.map +1 -0
  23. package/dist/{Button-DsRrU5F1.js → Button-Ca4Q3VJU.js} +31 -13
  24. package/dist/Button-Ca4Q3VJU.js.map +1 -0
  25. package/dist/{Calendar-cG5NIJ4O.js → Calendar-DFtmZzbF.js} +99 -99
  26. package/dist/Calendar-DFtmZzbF.js.map +1 -0
  27. package/dist/{Card-Dyo7055Q.js → Card-Cr9MBNHu.js} +4 -4
  28. package/dist/Card-Cr9MBNHu.js.map +1 -0
  29. package/dist/{Checkbox-Bqr6zXcW.js → Checkbox-8yIIgY7g.js} +4 -4
  30. package/dist/Checkbox-8yIIgY7g.js.map +1 -0
  31. package/dist/{Clipboard-C2YBRfD8.js → Clipboard-_xf6hMDD.js} +2 -2
  32. package/dist/{Clipboard-C2YBRfD8.js.map → Clipboard-_xf6hMDD.js.map} +1 -1
  33. package/dist/{ClipboardButton-CrljClL1.js → ClipboardButton-DHa1trtI.js} +4 -4
  34. package/dist/{ClipboardButton-CrljClL1.js.map → ClipboardButton-DHa1trtI.js.map} +1 -1
  35. package/dist/{CodeEditor-C9AS8Ch0.js → CodeEditor-BSo-oLFG.js} +55 -165
  36. package/dist/CodeEditor-BSo-oLFG.js.map +1 -0
  37. package/dist/{ColorInput-Dg87lKcR.js → ColorInput-DSMqrs2-.js} +12 -27
  38. package/dist/ColorInput-DSMqrs2-.js.map +1 -0
  39. package/dist/{ColorModeSwitch-CsWLiTBX.js → ColorModeSwitch-D7EuWyJz.js} +7 -17
  40. package/dist/ColorModeSwitch-D7EuWyJz.js.map +1 -0
  41. package/dist/Combobox-CxRAYOBt.js +1069 -0
  42. package/dist/Combobox-CxRAYOBt.js.map +1 -0
  43. package/dist/{Command-CqxoI_De.js → Command-BU_cVurn.js} +4 -4
  44. package/dist/{Command-CqxoI_De.js.map → Command-BU_cVurn.js.map} +1 -1
  45. package/dist/{CopyField-Rx9HPTbJ.js → CopyField-6_c-NdLO.js} +17 -53
  46. package/dist/{CopyField-Rx9HPTbJ.js.map → CopyField-6_c-NdLO.js.map} +1 -1
  47. package/dist/{DateInput-DpifECUQ.js → DateInput-DyEErfJf.js} +6 -6
  48. package/dist/{DateInput-DpifECUQ.js.map → DateInput-DyEErfJf.js.map} +1 -1
  49. package/dist/{DatePicker-nA8YdE84.js → DatePicker-CtSa9b3V.js} +3 -3
  50. package/dist/{DatePicker-nA8YdE84.js.map → DatePicker-CtSa9b3V.js.map} +1 -1
  51. package/dist/{DateRangeInput-9MIw7P6L.js → DateRangeInput-Dg7-VUd9.js} +10 -14
  52. package/dist/DateRangeInput-Dg7-VUd9.js.map +1 -0
  53. package/dist/{DateRangePicker-DjSUFjh4.js → DateRangePicker-BoPnh4aH.js} +9 -13
  54. package/dist/DateRangePicker-BoPnh4aH.js.map +1 -0
  55. package/dist/DiffView-ppTIzh2h.js.map +1 -1
  56. package/dist/{DropdownMenu-CASr-jgl.js → DropdownMenu-gRM-A8qU.js} +11 -6
  57. package/dist/DropdownMenu-gRM-A8qU.js.map +1 -0
  58. package/dist/{FieldItem-DtPTzNef.js → FieldItem-2wMXQ0Qw.js} +12 -25
  59. package/dist/FieldItem-2wMXQ0Qw.js.map +1 -0
  60. package/dist/{FieldItem-vhIJW4pj.d.ts → FieldItem-CPN1xjN5.d.ts} +11 -25
  61. package/dist/{FileUpload-DYQCTGjU.js → FileUpload-C83tXuE2.js} +11 -16
  62. package/dist/{FileUpload-DYQCTGjU.js.map → FileUpload-C83tXuE2.js.map} +1 -1
  63. package/dist/{Form-DAaatlBk.js → Form-95rVLfX8.js} +15 -23
  64. package/dist/{Form-DAaatlBk.js.map → Form-95rVLfX8.js.map} +1 -1
  65. package/dist/{FormGroup-Bl8JmnzJ.js → FormGroup-CmNiAtU6.js} +11 -17
  66. package/dist/FormGroup-CmNiAtU6.js.map +1 -0
  67. package/dist/{FullScreenModal-CN9nAs72.js → FullScreenModal-CD7mYeTz.js} +15 -29
  68. package/dist/FullScreenModal-CD7mYeTz.js.map +1 -0
  69. package/dist/{HoverCard-B9ZMJxjn.js → HoverCard-B8OKu9XZ.js} +2 -2
  70. package/dist/{HoverCard-B9ZMJxjn.js.map → HoverCard-B8OKu9XZ.js.map} +1 -1
  71. package/dist/{InputGroup-DcZRlVnN.js → InputGroup-B4QOPxHl.js} +12 -13
  72. package/dist/InputGroup-B4QOPxHl.js.map +1 -0
  73. package/dist/{Kbd-D1Azcc4g.js → Kbd-J4n1J6i4.js} +23 -13
  74. package/dist/Kbd-J4n1J6i4.js.map +1 -0
  75. package/dist/{MarkedText-DNGEUVWc.js → MarkedText-DlmlJO0u.js} +2 -2
  76. package/dist/{MarkedText-DNGEUVWc.js.map → MarkedText-DlmlJO0u.js.map} +1 -1
  77. package/dist/{MermaidDiagram-CujFxVzk.js → MermaidDiagram-BQvz6bhv.js} +16 -34
  78. package/dist/MermaidDiagram-BQvz6bhv.js.map +1 -0
  79. package/dist/{Modal-Coj-H02o.js → Modal-Driyqs_N.js} +17 -34
  80. package/dist/Modal-Driyqs_N.js.map +1 -0
  81. package/dist/{ModalTitle-C76ke2eo.js → ModalTitle-BxopkIoQ.js} +3 -3
  82. package/dist/ModalTitle-BxopkIoQ.js.map +1 -0
  83. package/dist/{MultiActionButtonGroup-CNNoBQbv.js → MultiActionButtonGroup-BPnmzBtw.js} +3 -3
  84. package/dist/{MultiActionButtonGroup-CNNoBQbv.js.map → MultiActionButtonGroup-BPnmzBtw.js.map} +1 -1
  85. package/dist/{Navbar-Liy1TPI7.js → Navbar-B_DNpv5s.js} +9 -13
  86. package/dist/{Navbar-Liy1TPI7.js.map → Navbar-B_DNpv5s.js.map} +1 -1
  87. package/dist/{OtpInput-CbbymqYs.js → OtpInput-I8B8Vjdl.js} +2 -2
  88. package/dist/{OtpInput-CbbymqYs.js.map → OtpInput-I8B8Vjdl.js.map} +1 -1
  89. package/dist/{PageHeader-Q3IpCnQd.js → PageHeader-CgfyXpf1.js} +13 -26
  90. package/dist/PageHeader-CgfyXpf1.js.map +1 -0
  91. package/dist/{PageLayout-DSVM-ASz.js → PageLayout-DiAAILuS.js} +12 -20
  92. package/dist/PageLayout-DiAAILuS.js.map +1 -0
  93. package/dist/{PageToolbar-BKVJiDAL.js → PageToolbar-DOAtAnfL.js} +12 -42
  94. package/dist/PageToolbar-DOAtAnfL.js.map +1 -0
  95. package/dist/{Pagination-C_b7Xhey.js → Pagination-LaSg-5cl.js} +3 -3
  96. package/dist/{Pagination-C_b7Xhey.js.map → Pagination-LaSg-5cl.js.map} +1 -1
  97. package/dist/{Popconfirm-5pBzT_HQ.js → Popconfirm-SLz0zodk.js} +3 -3
  98. package/dist/{Popconfirm-5pBzT_HQ.js.map → Popconfirm-SLz0zodk.js.map} +1 -1
  99. package/dist/{Popover-BEbQrC_P.js → Popover-CEk915I1.js} +4 -3
  100. package/dist/Popover-CEk915I1.js.map +1 -0
  101. package/dist/{RadioGroup-CUBsuP7r.js → RadioGroup-CBPRLRN0.js} +4 -4
  102. package/dist/{RadioGroup-CUBsuP7r.js.map → RadioGroup-CBPRLRN0.js.map} +1 -1
  103. package/dist/{Search-DVpJuzr9.js → Search-DmkQo716.js} +3 -3
  104. package/dist/{Search-DVpJuzr9.js.map → Search-DmkQo716.js.map} +1 -1
  105. package/dist/{SearchInput-Q85p8Ews.js → SearchInput-CEfQDNl3.js} +8 -13
  106. package/dist/SearchInput-CEfQDNl3.js.map +1 -0
  107. package/dist/{SectionNav-mpmSM3OC.js → SectionNav-B_qf0AXi.js} +10 -42
  108. package/dist/SectionNav-B_qf0AXi.js.map +1 -0
  109. package/dist/{Select-DV3Hak_l.js → Select-ByRvkZ3D.js} +8 -11
  110. package/dist/{Select-DV3Hak_l.js.map → Select-ByRvkZ3D.js.map} +1 -1
  111. package/dist/{Sheet-Chf0kX1E.js → Sheet-C-yXk5Da.js} +5 -9
  112. package/dist/Sheet-C-yXk5Da.js.map +1 -0
  113. package/dist/{Sidebar-CTWsHZhF.js → Sidebar-Ds0E6PbR.js} +181 -33
  114. package/dist/Sidebar-Ds0E6PbR.js.map +1 -0
  115. package/dist/{Slider-Bv0B6lI0.js → Slider-DWdu9NuM.js} +3 -3
  116. package/dist/{Slider-Bv0B6lI0.js.map → Slider-DWdu9NuM.js.map} +1 -1
  117. package/dist/{Stepper-C8sm9ZFM.js → Stepper-BLkLhfnd.js} +6 -9
  118. package/dist/{Stepper-C8sm9ZFM.js.map → Stepper-BLkLhfnd.js.map} +1 -1
  119. package/dist/{Switch-B0WdGSjz.js → Switch-DZvNePOm.js} +2 -2
  120. package/dist/{Switch-B0WdGSjz.js.map → Switch-DZvNePOm.js.map} +1 -1
  121. package/dist/{Table-CvYuTuNU.js → Table-BaVT5Tkn.js} +6 -11
  122. package/dist/{Table-CvYuTuNU.js.map → Table-BaVT5Tkn.js.map} +1 -1
  123. package/dist/{Tabs-eB974xJf.js → Tabs-Dt9oLYHC.js} +3 -3
  124. package/dist/{Tabs-eB974xJf.js.map → Tabs-Dt9oLYHC.js.map} +1 -1
  125. package/dist/{TextInput-DiEMxVF6.js → TextInput-CDG2XpBl.js} +12 -15
  126. package/dist/TextInput-CDG2XpBl.js.map +1 -0
  127. package/dist/{ThemeProvider-BI6JWBdJ.js → ThemeProvider-DXsxFg1U.js} +13 -31
  128. package/dist/ThemeProvider-DXsxFg1U.js.map +1 -0
  129. package/dist/{TimePicker-BGeqc-Ed.js → TimePicker-CDGYrRxi.js} +2 -2
  130. package/dist/{TimePicker-BGeqc-Ed.js.map → TimePicker-CDGYrRxi.js.map} +1 -1
  131. package/dist/{Timeline-BG5Xogxh.js → Timeline-B-I6sb0M.js} +2 -2
  132. package/dist/{Timeline-BG5Xogxh.js.map → Timeline-B-I6sb0M.js.map} +1 -1
  133. package/dist/{Toast-Dr6Uw7ao.js → Toast-PfQf3vj-.js} +2 -2
  134. package/dist/{Toast-Dr6Uw7ao.js.map → Toast-PfQf3vj-.js.map} +1 -1
  135. package/dist/{Workbench-UR2FBC7I.js → Workbench-DmZzpkj7.js} +2 -2
  136. package/dist/{Workbench-UR2FBC7I.js.map → Workbench-DmZzpkj7.js.map} +1 -1
  137. package/dist/{ZoomableSvg-U_VH3QRO.js → ZoomableSvg-BzXVfgnI.js} +5 -19
  138. package/dist/ZoomableSvg-BzXVfgnI.js.map +1 -0
  139. package/dist/charts.d.ts +21 -52
  140. package/dist/charts.js +13 -39
  141. package/dist/charts.js.map +1 -1
  142. package/dist/{context-D7X470dy.js → context-U293r3v-.js} +5 -9
  143. package/dist/context-U293r3v-.js.map +1 -0
  144. package/dist/editors.d.ts +27 -124
  145. package/dist/editors.js +29 -71
  146. package/dist/editors.js.map +1 -1
  147. package/dist/{findLiteralMatches-BGBw8Vbl.js → findLiteralMatches-DgGLzyG0.js} +8 -20
  148. package/dist/findLiteralMatches-DgGLzyG0.js.map +1 -0
  149. package/dist/flint.d.ts +3 -6
  150. package/dist/flint.js +31 -80
  151. package/dist/flint.js.map +1 -1
  152. package/dist/{icons-Cek151jC.js → icons-wcA70iQx.js} +105 -2
  153. package/dist/icons-wcA70iQx.js.map +1 -0
  154. package/dist/icons.d.ts +2 -2
  155. package/dist/icons.js +2 -2
  156. package/dist/{index-m-kQEWiY.d.ts → index-B7k-09i1.d.ts} +14 -2
  157. package/dist/index.d.ts +1461 -1809
  158. package/dist/index.js +70 -67
  159. package/dist/internal/blocks/AIKit.js +2 -2
  160. package/dist/internal/blocks/AppShell.js +1 -1
  161. package/dist/internal/blocks/AuthLayout.js +7 -27
  162. package/dist/internal/blocks/AuthLayout.js.map +1 -1
  163. package/dist/internal/blocks/AutoSaveTextarea.js +1 -1
  164. package/dist/internal/blocks/BrandEditor.js +1 -1
  165. package/dist/internal/blocks/ChartPanel.js +4 -8
  166. package/dist/internal/blocks/ChartPanel.js.map +1 -1
  167. package/dist/internal/blocks/ChipEditor.js +129 -0
  168. package/dist/internal/blocks/ChipEditor.js.map +1 -0
  169. package/dist/internal/blocks/ClipboardButton.js +1 -1
  170. package/dist/internal/blocks/ColorInput.js +1 -1
  171. package/dist/internal/blocks/ColorModeSwitch.js +1 -1
  172. package/dist/internal/blocks/Command.js +1 -1
  173. package/dist/internal/blocks/CopyField.js +1 -1
  174. package/dist/internal/blocks/DashboardHero.js +4 -7
  175. package/dist/internal/blocks/DashboardHero.js.map +1 -1
  176. package/dist/internal/blocks/DateInput.js +1 -1
  177. package/dist/internal/blocks/DateRangeInput.js +1 -1
  178. package/dist/internal/blocks/EmptyConfigurationActionCard.js +1 -1
  179. package/dist/internal/blocks/EmptyState.js +5 -9
  180. package/dist/internal/blocks/EmptyState.js.map +1 -1
  181. package/dist/internal/blocks/ErrorState.js +5 -9
  182. package/dist/internal/blocks/ErrorState.js.map +1 -1
  183. package/dist/internal/blocks/ExportMenu.js +6 -10
  184. package/dist/internal/blocks/ExportMenu.js.map +1 -1
  185. package/dist/internal/blocks/Form/connectors/ComboboxField.js +40 -0
  186. package/dist/internal/blocks/Form/connectors/ComboboxField.js.map +1 -0
  187. package/dist/internal/blocks/Form/connectors/MultiComboboxField.js +5 -22
  188. package/dist/internal/blocks/Form/connectors/MultiComboboxField.js.map +1 -1
  189. package/dist/internal/blocks/Form.js +1 -1
  190. package/dist/internal/blocks/FormGroup.js +1 -1
  191. package/dist/internal/blocks/GoogleButton.js +1 -1
  192. package/dist/internal/blocks/MicrosoftButton.js +1 -1
  193. package/dist/internal/blocks/MultiActionButtonGroup.js +1 -1
  194. package/dist/internal/blocks/MultiCombobox.js +162 -165
  195. package/dist/internal/blocks/MultiCombobox.js.map +1 -1
  196. package/dist/internal/blocks/NumberInput.js +1 -1
  197. package/dist/internal/blocks/OtpInput.js +1 -1
  198. package/dist/internal/blocks/PageHeader.js +1 -1
  199. package/dist/internal/blocks/PageLayout.js +1 -1
  200. package/dist/internal/blocks/PageToolbar.js +1 -1
  201. package/dist/internal/blocks/PasswordInput.js +4 -4
  202. package/dist/internal/blocks/PasswordInput.js.map +1 -1
  203. package/dist/internal/blocks/SearchInput.js +1 -1
  204. package/dist/internal/blocks/SearchInputWithNavigation.js +4 -4
  205. package/dist/internal/blocks/SectionNav.js +1 -1
  206. package/dist/internal/blocks/SplitButton.js +3 -3
  207. package/dist/internal/blocks/StatCard.js +4 -8
  208. package/dist/internal/blocks/StatCard.js.map +1 -1
  209. package/dist/internal/blocks/TextInput.js +1 -1
  210. package/dist/internal/blocks/Textarea.js +2 -2
  211. package/dist/internal/blocks/TimeInput.js +5 -5
  212. package/dist/internal/blocks/TimeInput.js.map +1 -1
  213. package/dist/internal/components/Alert.js +1 -1
  214. package/dist/internal/components/AlertModal.js +1 -1
  215. package/dist/internal/components/Avatar.js +1 -1
  216. package/dist/internal/components/Badge.js +1 -1
  217. package/dist/internal/components/BrandLogo.js +1 -1
  218. package/dist/internal/components/Breadcrumb.js +1 -1
  219. package/dist/internal/components/Button.js +1 -1
  220. package/dist/internal/components/ButtonGroup.js.map +1 -1
  221. package/dist/internal/components/Calendar.js +1 -1
  222. package/dist/internal/components/Card.js +1 -1
  223. package/dist/internal/components/Checkbox.js +1 -1
  224. package/dist/internal/components/Clipboard.js +1 -1
  225. package/dist/internal/components/CollapsiblePanel.js +2 -2
  226. package/dist/internal/components/Combobox.js +2 -2
  227. package/dist/internal/components/DatePicker.js +1 -1
  228. package/dist/internal/components/DateRangePicker.js +1 -1
  229. package/dist/internal/components/DropdownMenu.js +1 -1
  230. package/dist/internal/components/FileUpload.js +1 -1
  231. package/dist/internal/components/FullScreenModal.js +1 -1
  232. package/dist/internal/components/HoverCard.js +1 -1
  233. package/dist/internal/components/InputGroup.js +1 -1
  234. package/dist/internal/components/Kbd.js +1 -1
  235. package/dist/internal/components/MarkedText.js +1 -1
  236. package/dist/internal/components/MergeEditor/ConflictStatus/ConflictStatusIndicator.js +1 -1
  237. package/dist/internal/components/Modal.js +1 -1
  238. package/dist/internal/components/Navbar.js +1 -1
  239. package/dist/internal/components/Pagination.js +1 -1
  240. package/dist/internal/components/PanelWithDetails.js +1 -1
  241. package/dist/internal/components/Popconfirm.js +1 -1
  242. package/dist/internal/components/Popover.js +1 -1
  243. package/dist/internal/components/RadioGroup.js +1 -1
  244. package/dist/internal/components/Search.js +1 -1
  245. package/dist/internal/components/Select.js +1 -1
  246. package/dist/internal/components/Separator.js.map +1 -1
  247. package/dist/internal/components/Sheet.js +1 -1
  248. package/dist/internal/components/Sidebar.js +1 -1
  249. package/dist/internal/components/Skeleton/Skeleton.js +5 -9
  250. package/dist/internal/components/Skeleton/Skeleton.js.map +1 -1
  251. package/dist/internal/components/Slider.js +1 -1
  252. package/dist/internal/components/SpotlightBackdrop.js +3 -8
  253. package/dist/internal/components/SpotlightBackdrop.js.map +1 -1
  254. package/dist/internal/components/StatusDot.js +60 -0
  255. package/dist/internal/components/StatusDot.js.map +1 -0
  256. package/dist/internal/components/Stepper.js +1 -1
  257. package/dist/internal/components/Switch.js +1 -1
  258. package/dist/internal/components/Table.js +1 -1
  259. package/dist/internal/components/Tabs.js +1 -1
  260. package/dist/internal/components/ThemeProvider.js +3 -3
  261. package/dist/internal/components/TimePicker.js +1 -1
  262. package/dist/internal/components/Timeline.js +1 -1
  263. package/dist/internal/components/Toast.js +2 -2
  264. package/dist/internal/components/Tooltip.js +2 -2
  265. package/dist/internal/components/Truncated.js +4 -8
  266. package/dist/internal/components/Truncated.js.map +1 -1
  267. package/dist/internal/components/Workbench.js +1 -1
  268. package/dist/internal/components/ZoomableSvg.js +1 -1
  269. package/dist/internal/hooks/useScrollbarPosition.js +1 -1
  270. package/dist/internal/hooks/useStableCallback.js +4 -13
  271. package/dist/internal/hooks/useStableCallback.js.map +1 -1
  272. package/dist/internal/utils/mergeRefs.js +27 -9
  273. package/dist/internal/utils/mergeRefs.js.map +1 -1
  274. package/dist/internal/utils.js +3 -3
  275. package/dist/markdown-editor.d.ts +15 -37
  276. package/dist/markdown-editor.js +17 -23
  277. package/dist/markdown-editor.js.map +1 -1
  278. package/dist/mermaid.d.ts +4 -6
  279. package/dist/mermaid.js +1 -1
  280. package/dist/rjsf.d.ts +9 -19
  281. package/dist/rjsf.js +44 -84
  282. package/dist/rjsf.js.map +1 -1
  283. package/dist/{styles-BAFscjSV.js → styles-gzcjOyKv.js} +6 -6
  284. package/dist/styles-gzcjOyKv.js.map +1 -0
  285. package/dist/styles.css +1 -1
  286. package/dist/svgTransforms-Dw2hRA-i.js +51 -0
  287. package/dist/svgTransforms-Dw2hRA-i.js.map +1 -0
  288. package/dist/testing.d.ts +3 -10
  289. package/dist/testing.js +5 -12
  290. package/dist/testing.js.map +1 -1
  291. package/dist/themeTokens-7DEab0kp.js +31 -0
  292. package/dist/themeTokens-7DEab0kp.js.map +1 -0
  293. package/dist/{toast-DIC0iNRf.js → toast-CyXEdaCZ.js} +3 -3
  294. package/dist/toast-CyXEdaCZ.js.map +1 -0
  295. package/dist/{themeScopeContext-D7fSyb06.js → useColorSchemeState-Cw4MCXUs.js} +14 -14
  296. package/dist/useColorSchemeState-Cw4MCXUs.js.map +1 -0
  297. package/dist/{useControllableState-M6494mCT.js → useControllableState-CUYXMsfz.js} +3 -7
  298. package/dist/useControllableState-CUYXMsfz.js.map +1 -0
  299. package/dist/useElement-D-RjrGa4.js +21 -0
  300. package/dist/useElement-D-RjrGa4.js.map +1 -0
  301. package/dist/useThemeAttributes-B199Regy.js +67 -0
  302. package/dist/useThemeAttributes-B199Regy.js.map +1 -0
  303. package/dist/{utils-DnkrFYqY.js → utils-Bd28bWgm.js} +53 -20
  304. package/dist/utils-Bd28bWgm.js.map +1 -0
  305. package/dist/vega.d.ts +8 -30
  306. package/dist/vega.js +5 -13
  307. package/dist/vega.js.map +1 -1
  308. package/dist/{vegaTheme-CSvFEMBl.js → vegaTheme-VQMWTlBw.js} +7 -21
  309. package/dist/vegaTheme-VQMWTlBw.js.map +1 -0
  310. package/package.json +11 -9
  311. package/src/styles.css +120 -14
  312. package/src/theme.css +126 -6
  313. package/dist/AIKit-CQxVwyAk.js.map +0 -1
  314. package/dist/Alert-C4Y9IwMI.js.map +0 -1
  315. package/dist/AlertModal-BGJdaRRj.js.map +0 -1
  316. package/dist/AppShell-DRgJxpXW.js.map +0 -1
  317. package/dist/Badge-o5jURtpB.js.map +0 -1
  318. package/dist/BrandLogo-CoKBk4MI.js.map +0 -1
  319. package/dist/Breadcrumb-D1id7YXd.js.map +0 -1
  320. package/dist/Button-DsRrU5F1.js.map +0 -1
  321. package/dist/Calendar-cG5NIJ4O.js.map +0 -1
  322. package/dist/Card-Dyo7055Q.js.map +0 -1
  323. package/dist/Checkbox-Bqr6zXcW.js.map +0 -1
  324. package/dist/CodeEditor-C9AS8Ch0.js.map +0 -1
  325. package/dist/ColorInput-Dg87lKcR.js.map +0 -1
  326. package/dist/ColorModeSwitch-CsWLiTBX.js.map +0 -1
  327. package/dist/Combobox-BfanUAqY.js +0 -619
  328. package/dist/Combobox-BfanUAqY.js.map +0 -1
  329. package/dist/DateRangeInput-9MIw7P6L.js.map +0 -1
  330. package/dist/DateRangePicker-DjSUFjh4.js.map +0 -1
  331. package/dist/DropdownMenu-CASr-jgl.js.map +0 -1
  332. package/dist/FieldItem-DtPTzNef.js.map +0 -1
  333. package/dist/FormGroup-Bl8JmnzJ.js.map +0 -1
  334. package/dist/FullScreenModal-CN9nAs72.js.map +0 -1
  335. package/dist/InputGroup-DcZRlVnN.js.map +0 -1
  336. package/dist/Kbd-D1Azcc4g.js.map +0 -1
  337. package/dist/MermaidDiagram-CujFxVzk.js.map +0 -1
  338. package/dist/Modal-Coj-H02o.js.map +0 -1
  339. package/dist/ModalTitle-C76ke2eo.js.map +0 -1
  340. package/dist/PageHeader-Q3IpCnQd.js.map +0 -1
  341. package/dist/PageLayout-DSVM-ASz.js.map +0 -1
  342. package/dist/PageToolbar-BKVJiDAL.js.map +0 -1
  343. package/dist/Popover-BEbQrC_P.js.map +0 -1
  344. package/dist/SearchInput-Q85p8Ews.js.map +0 -1
  345. package/dist/SectionNav-mpmSM3OC.js.map +0 -1
  346. package/dist/Sheet-Chf0kX1E.js.map +0 -1
  347. package/dist/Sidebar-CTWsHZhF.js.map +0 -1
  348. package/dist/TextInput-DiEMxVF6.js.map +0 -1
  349. package/dist/ThemeProvider-BI6JWBdJ.js.map +0 -1
  350. package/dist/ZoomableSvg-U_VH3QRO.js.map +0 -1
  351. package/dist/context-D7X470dy.js.map +0 -1
  352. package/dist/findLiteralMatches-BGBw8Vbl.js.map +0 -1
  353. package/dist/icons-Cek151jC.js.map +0 -1
  354. package/dist/styles-BAFscjSV.js.map +0 -1
  355. package/dist/svgTransforms-CJAYPk7o.js +0 -81
  356. package/dist/svgTransforms-CJAYPk7o.js.map +0 -1
  357. package/dist/themeScopeContext-D7fSyb06.js.map +0 -1
  358. package/dist/themeTokens-qP1-55O7.js +0 -119
  359. package/dist/themeTokens-qP1-55O7.js.map +0 -1
  360. package/dist/toast-DIC0iNRf.js.map +0 -1
  361. package/dist/useControllableState-M6494mCT.js.map +0 -1
  362. package/dist/useElement-DkF6esWL.js +0 -15
  363. package/dist/useElement-DkF6esWL.js.map +0 -1
  364. package/dist/utils-DnkrFYqY.js.map +0 -1
  365. package/dist/vegaTheme-CSvFEMBl.js.map +0 -1
@@ -0,0 +1,1069 @@
1
+ import { cn } from "./classNames-BzrkDnOD.js";
2
+ import { noop } from "./utils-Bd28bWgm.js";
3
+ import { useArgoDesign } from "./context-U293r3v-.js";
4
+ import { Check, ChevronDown, ChevronRight, Loader2, Minus, Plus, X } from "./icons-wcA70iQx.js";
5
+ import { useStableCallback } from "./internal/hooks/useStableCallback.js";
6
+ import { InputGroup } from "./InputGroup-B4QOPxHl.js";
7
+ import { Badge } from "./Badge-DIjhwPvh.js";
8
+ import { useElement } from "./useElement-D-RjrGa4.js";
9
+ import { Fragment, createContext, isValidElement, use, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
10
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
11
+ import { Combobox } from "@base-ui/react/combobox";
12
+ import { DismissableLayer } from "@radix-ui/react-dismissable-layer";
13
+ import { measureElement, observeElementRect, useVirtualizer } from "@tanstack/react-virtual";
14
+ //#region src/components/Combobox/blankValues.ts
15
+ /**
16
+ * The two blank strings a Storage filter predicates on, in list order.
17
+ *
18
+ * - Hand it to `items` where the blanks are the whole list — a value field whose other entries the
19
+ * user types. {@link withBlankValues} is for offering them ahead of a list that already exists.
20
+ */
21
+ const BLANK_VALUES = ["", " "];
22
+ const BLANK_LABELS = {
23
+ "": "[empty string]",
24
+ " ": "[space character]"
25
+ };
26
+ /**
27
+ * A string as a row or a chip shows it — named when its text is blank, itself otherwise.
28
+ *
29
+ * - Exported so an `itemToLabel` / `itemToChipLabel` / `itemToSelectedLabel` / `renderChips`
30
+ * override can keep the default naming instead of retyping the labels.
31
+ * - The two blank values get their own labels; any other whitespace-only string (a tab, a run of
32
+ * spaces) falls back to a generic one, so two different ones read alike.
33
+ * - Identity is unaffected — `toLabel` keys items off the raw string.
34
+ */
35
+ const namedLabel = (text) => text.trim() === "" ? BLANK_LABELS[text] ?? "[whitespace]" : text;
36
+ /**
37
+ * `values` with both blank values offered ahead of them, and duplicates collapsed.
38
+ *
39
+ * - The dedupe matters where the list is the distinct values of a Storage column: it can already
40
+ * hold a blank, and two `Object.is`-equal rows both report `aria-selected` and toggle each other.
41
+ * - First occurrence wins, so the order of the values is otherwise preserved.
42
+ * - String items only — the seven Storage filters this serves are all string-valued.
43
+ */
44
+ const withBlankValues = (values) => [.../* @__PURE__ */ new Set([...BLANK_VALUES, ...values])];
45
+ //#endregion
46
+ //#region src/components/Combobox/ComboboxChip.tsx
47
+ /**
48
+ * Keeps a chip's keyboard handling off its content's.
49
+ *
50
+ * - Base UI's chip `preventDefault`s Enter/Space, cancelling a nested link or button.
51
+ * - Capture phase, so the chip's own bubble handler never runs.
52
+ * - Target-guarded, so the chip's own keys (Backspace, Delete, arrows) still reach it.
53
+ */
54
+ const stopNestedKeyDown = (event) => {
55
+ if (event.target !== event.currentTarget) event.stopPropagation();
56
+ };
57
+ /**
58
+ * One removable chip in a `MultiCombobox`'s `renderChips` slot or `Combobox.Chips`.
59
+ *
60
+ * - Position is identity: Base UI removes by index, so render one per `value` entry, in order.
61
+ * - A non-removable chip is a plain `Badge`: a chip would shift the removal index.
62
+ */
63
+ const ComboboxChip = ({ children, color, variant }) => {
64
+ const renderArgo = useArgoDesign();
65
+ return /* @__PURE__ */ jsxs(Combobox.Chip, {
66
+ render: /* @__PURE__ */ jsx(Badge.Root, {
67
+ color,
68
+ variant: variant ?? (renderArgo ? "pill" : "default"),
69
+ className: "tw:max-w-40"
70
+ }),
71
+ onKeyDownCapture: stopNestedKeyDown,
72
+ children: [/* @__PURE__ */ jsx(Badge.Label, { children }), /* @__PURE__ */ jsx(Badge.Addon, {
73
+ variant: "inline",
74
+ align: "inline-end",
75
+ children: /* @__PURE__ */ jsx(Combobox.ChipRemove, { render: /* @__PURE__ */ jsx(Badge.Button, {
76
+ "aria-label": "Remove value",
77
+ children: /* @__PURE__ */ jsx(X, { className: "tw:size-3" })
78
+ }) })
79
+ })]
80
+ });
81
+ };
82
+ //#endregion
83
+ //#region src/components/Combobox/utils.ts
84
+ const isPlainObject = (item) => item !== null && typeof item === "object";
85
+ const isNumber = (item) => typeof item === "number";
86
+ const isString = (item) => typeof item === "string";
87
+ const isLabeledItem = (item) => isPlainObject(item) && Reflect.has(item, "label") && Reflect.has(item, "value");
88
+ const isInternalItem = (item) => isLabeledItem(item) && "__marker" in item;
89
+ const isSelectAllItem = (item) => isInternalItem(item) && item.__marker === "selectAll";
90
+ const isCreatableItem = (item) => {
91
+ return isInternalItem(item) && item.__marker === "creatable";
92
+ };
93
+ const isGroupHeaderItem = (item) => isInternalItem(item) && item.__marker === "groupHeader";
94
+ const isGroupItem = (itemOrGroup) => itemOrGroup !== null && typeof itemOrGroup === "object" && Reflect.has(itemOrGroup, "items");
95
+ const isGroupItems = (items) => {
96
+ if (!Array.isArray(items)) return false;
97
+ if (items.length === 0) return false;
98
+ return isGroupItem(items[0]);
99
+ };
100
+ /** The options of a list, its groups flattened. */
101
+ const flatItems = (list) => {
102
+ const items = [];
103
+ for (const entry of list) if (!isGroupItem(entry)) items.push(entry);
104
+ else for (const item of entry.items) items.push(item);
105
+ return items;
106
+ };
107
+ /** The create row and Select All: each is drawn outside any group, even in a grouped list. */
108
+ const isLooseItem = (item) => isCreatableItem(item) || isSelectAllItem(item);
109
+ /**
110
+ * `items` as entries of `list`: one group without a label in a grouped list, else themselves.
111
+ *
112
+ * - Base UI reads the first entry to tell a grouped list, so every entry has to match it.
113
+ * - The group never reaches `groupToLabel`: {@link isEntriesGroup} tells it apart.
114
+ */
115
+ const toEntries = (list, items) => isGroupItems(list) ? [{
116
+ __marker: "entries",
117
+ items
118
+ }] : items;
119
+ /** A group {@link toEntries} made; Base UI's filter keeps the marker, as it spreads each group. */
120
+ const isEntriesGroup = (entry) => isGroupItem(entry) && Reflect.get(entry, "__marker") === "entries";
121
+ /**
122
+ * Node a list row and a chip show for an item.
123
+ *
124
+ * - Names a blank string, so a row or chip never renders as nothing; {@link toLabel} does not.
125
+ * - A non-string `label` (a JSX node) passes through.
126
+ */
127
+ const defaultItemToLabel = (item) => {
128
+ if (isNumber(item)) return item;
129
+ if (isString(item)) return namedLabel(item);
130
+ if (!isLabeledItem(item)) throw new Error("Combobox: Item does not have a `label` field. Pass `itemToLabel` for custom item shapes.");
131
+ return isString(item.label) ? namedLabel(item.label) : item.label;
132
+ };
133
+ /**
134
+ * The node a row or a chip shows for an item when the caller passes no `itemToLabel`.
135
+ *
136
+ * - Names a blank `itemToStringLabel` result, which would otherwise render as nothing.
137
+ * - Falls back to the item's own string: Base UI reports the outgoing selection for one render
138
+ * after `items` and `itemToStringLabel` change together.
139
+ */
140
+ const defaultRowLabel = (itemToStringLabel) => itemToStringLabel ? (item) => namedLabel(itemToStringLabel(item) ?? toLabel(item)) : defaultItemToLabel;
141
+ /**
142
+ * Display string for an item — mirrors Base UI's default.
143
+ *
144
+ * - Also the default search text and the closed `Combobox`'s input value.
145
+ * - Does not name blank strings: `''` may mean "nothing selected", and must keep the placeholder.
146
+ * - A labelled item with neither a label nor a value reads as `''`, like the string item `''`.
147
+ * - Naming lives in {@link defaultItemToLabel}, read only by rows and chips.
148
+ */
149
+ const toLabel = (item) => {
150
+ if (isString(item)) return item;
151
+ if (isLabeledItem(item)) return item.label || item.value || "";
152
+ return String(item);
153
+ };
154
+ /** Equality key for an item — prefers `.value`. */
155
+ const toValueKey = (item) => {
156
+ if (isString(item)) return item;
157
+ if (isLabeledItem(item)) return item.value || item.label || "";
158
+ return String(item);
159
+ };
160
+ const defaultItemToIcon = (item) => isLabeledItem(item) ? item.icon : void 0;
161
+ const defaultItemToDisabled = (item) => isLabeledItem(item) ? item.disabled ?? false : false;
162
+ /** A group's `label`, as `Select` renders it; one that is not a node reads as none. */
163
+ const defaultGroupToLabel = (group) => {
164
+ const label = Reflect.get(group, "label");
165
+ return isString(label) || isNumber(label) || isValidElement(label) ? label : void 0;
166
+ };
167
+ const selectAllItem = {
168
+ __marker: "selectAll",
169
+ value: "__select_all__",
170
+ label: "Select All"
171
+ };
172
+ /** Row for the group at `index` — keyed by position, like its collapse state. */
173
+ const createGroupHeaderItem = (index) => ({
174
+ __marker: "groupHeader",
175
+ value: `__group_${index}__`,
176
+ label: ""
177
+ });
178
+ const createCreatableItem = (query) => ({
179
+ __marker: "creatable",
180
+ value: query,
181
+ label: query
182
+ });
183
+ /**
184
+ * Item-equality predicate for a Base UI combobox root.
185
+ *
186
+ * - A sentinel equals a sentinel by marker and value key (the create row is rebuilt per keystroke).
187
+ * - A sentinel never equals a real item.
188
+ * - Real items use the caller's predicate, else `Object.is`.
189
+ */
190
+ const toItemEquality = (isItemEqualToValue) => (a, b) => {
191
+ if (isInternalItem(a) || isInternalItem(b)) return isInternalItem(a) && isInternalItem(b) && a.__marker === b.__marker && toValueKey(a) === toValueKey(b);
192
+ return isItemEqualToValue?.(a, b) ?? Object.is(a, b);
193
+ };
194
+ /**
195
+ * {@link toItemEquality} with a stable identity.
196
+ *
197
+ * - Base UI lists the comparer in an effect's deps; a new one per render re-renders every row.
198
+ */
199
+ const useItemEquality = (isItemEqualToValue) => useMemo(() => toItemEquality(isItemEqualToValue), [isItemEqualToValue]);
200
+ /** `itemToStringValue` that also reads the create row, whose value is its query. */
201
+ const withCreatableStringValue = (itemToStringValue, allowCreate) => !allowCreate || !itemToStringValue ? itemToStringValue : (item) => isCreatableItem(item) ? item.value : itemToStringValue(item);
202
+ /** {@link withCreatableStringValue} with a stable identity. */
203
+ const useCreatableStringValue = (itemToStringValue, allowCreate) => useMemo(() => withCreatableStringValue(itemToStringValue, allowCreate), [itemToStringValue, allowCreate]);
204
+ const defaultToCreateValue = (query, value, queryToCreateValue) => {
205
+ if (queryToCreateValue) return queryToCreateValue(query);
206
+ if (value === void 0) return query;
207
+ if (isString(value)) return query;
208
+ if (isLabeledItem(value)) return {
209
+ value: query,
210
+ label: query
211
+ };
212
+ throw new Error("Combobox: Cannot infer item shape for `allowCreate`. Pass `queryToCreateValue` for custom item shapes.");
213
+ };
214
+ const defaultQueryToCreateLabel = (query) => `Create "${query}"`;
215
+ //#endregion
216
+ //#region src/components/Combobox/ComboboxChips.tsx
217
+ const ComboboxChips = ({ maxVisible = 3, itemToChipLabel = defaultItemToLabel, itemToChipColor, pinnedChipLabels, variant = "pill", children }) => /* @__PURE__ */ jsx(Combobox.Value, { children: (rawValues) => {
218
+ const values = rawValues.filter((value) => !isInternalItem(value));
219
+ if (children) return children(values);
220
+ const visible = values.slice(0, maxVisible);
221
+ const overflow = values.slice(maxVisible);
222
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
223
+ pinnedChipLabels?.map((label, index) => /* @__PURE__ */ jsx(Badge, {
224
+ className: "tw:max-w-40",
225
+ variant,
226
+ children: label
227
+ }, index)),
228
+ visible.map((value, index) => /* @__PURE__ */ jsx(ComboboxChip, {
229
+ color: itemToChipColor?.(value),
230
+ variant,
231
+ children: itemToChipLabel(value)
232
+ }, index)),
233
+ overflow.length > 0 && /* @__PURE__ */ jsx(Badge.Root, {
234
+ variant: "pill",
235
+ children: /* @__PURE__ */ jsxs(Badge.Label, { children: ["+", overflow.length] })
236
+ })
237
+ ] });
238
+ } });
239
+ //#endregion
240
+ //#region src/components/Combobox/ComboboxClearButton.tsx
241
+ /** The button that clears the selection. */
242
+ const ComboboxClearButton = ({ disabled }) => /* @__PURE__ */ jsx(InputGroup.Button, {
243
+ asChild: true,
244
+ "aria-label": "Clear",
245
+ disabled,
246
+ children: /* @__PURE__ */ jsx(Combobox.Clear, { children: /* @__PURE__ */ jsx(X, { className: "tw:size-4" }) })
247
+ });
248
+ //#endregion
249
+ //#region src/components/Combobox/ComboboxContent.tsx
250
+ const ComboboxContent = ({ ref, align = "start", side = "bottom", sideOffset = 4, alignOffset, anchor, container, className, children, ...popupProps }) => {
251
+ const effectiveVariant = useArgoDesign() ? "argo" : "default";
252
+ return /* @__PURE__ */ jsx(Combobox.Portal, {
253
+ container,
254
+ children: /* @__PURE__ */ jsx(DismissableLayer, {
255
+ asChild: true,
256
+ children: /* @__PURE__ */ jsx(Combobox.Positioner, {
257
+ align,
258
+ side,
259
+ sideOffset,
260
+ alignOffset,
261
+ anchor,
262
+ className: "tw:isolate tw:z-[1055] tailwindcss-preflight",
263
+ children: /* @__PURE__ */ jsx(Combobox.Popup, {
264
+ ref,
265
+ "data-chips": !!anchor,
266
+ "data-variant": effectiveVariant,
267
+ className: cn("tw:!pointer-events-auto", "tw:group/combobox-content", "tw:relative", "tw:flex tw:flex-col tw:overflow-hidden", "tw:max-h-[var(--available-height)]", "tw:w-[var(--anchor-width)]", "tw:max-w-[var(--available-width)]", "tw:origin-[var(--transform-origin)]", "tw:data-[chips=true]:min-w-[var(--anchor-width)]", "tw:rounded-lg", "tw:data-[variant=default]:rounded", "tw:bg-popover", "tw:text-popover-foreground", "tw:shadow-md", "tw:ring-1", "tw:ring-foreground/10", "tw:duration-100", "data-open:animate-in", "data-open:fade-in-0", "data-open:zoom-in-95", "data-closed:animate-out", "data-closed:fade-out-0", "data-closed:zoom-out-95", "tw:data-[side=bottom]:slide-in-from-top-2", "tw:data-[side=top]:slide-in-from-bottom-2", "tw:data-[side=left]:slide-in-from-right-2", "tw:data-[side=right]:slide-in-from-left-2", "tw:data-[side=inline-start]:slide-in-from-right-2", "tw:data-[side=inline-end]:slide-in-from-left-2", className),
268
+ ...popupProps,
269
+ children
270
+ })
271
+ })
272
+ })
273
+ });
274
+ };
275
+ //#endregion
276
+ //#region src/components/Combobox/ComboboxEmpty.tsx
277
+ const ComboboxEmpty = ({ ref, className, ...props }) => /* @__PURE__ */ jsx(Combobox.Empty, {
278
+ ref,
279
+ className: cn("tw:hidden", "tw:group-data-[empty]/combobox-content:flex", "tw:justify-center", "tw:items-center", "tw:text-center", "tw:px-2", "tw:text-muted-foreground", "tw:py-6", className),
280
+ ...props
281
+ });
282
+ //#endregion
283
+ //#region src/components/Combobox/ComboboxInput.tsx
284
+ const ComboboxInput = ({ ref, ...props }) => /* @__PURE__ */ jsx(Combobox.Input, {
285
+ ...props,
286
+ ref,
287
+ render: /* @__PURE__ */ jsx(InputGroup.Input, {})
288
+ });
289
+ //#endregion
290
+ //#region src/components/Combobox/ComboboxInputGroup.tsx
291
+ const ComboboxInputGroup = ({ ref, state, variant, sizing, focusVariant, className, ...props }) => /* @__PURE__ */ jsx(Combobox.InputGroup, {
292
+ ...props,
293
+ ref,
294
+ render: /* @__PURE__ */ jsx(InputGroup, {
295
+ state,
296
+ variant,
297
+ focusVariant,
298
+ sizing,
299
+ className
300
+ })
301
+ });
302
+ //#endregion
303
+ //#region src/components/Combobox/ComboboxItemIndicator.tsx
304
+ const ComboboxItemIndicator = ({ ref, className, variant = "check", ...props }) => {
305
+ if (variant === "checkbox") return /* @__PURE__ */ jsx(Combobox.ItemIndicator, {
306
+ ref,
307
+ keepMounted: true,
308
+ className: cn("tw:group/combobox-item-indicator", "tw:inline-flex", "tw:items-center", "tw:justify-center", "tw:size-4", "tw:shrink-0", "tw:rounded", "tw:border", "tw:border-input", "tw:bg-background", "tw:data-[selected]:bg-primary", "tw:data-[selected]:border-primary", className),
309
+ ...props,
310
+ children: /* @__PURE__ */ jsx(Check, { className: cn("tw:hidden", "tw:size-3", "tw:stroke-[4px]", "tw:!text-primary-foreground", "tw:group-data-[selected]/combobox-item-indicator:block") })
311
+ });
312
+ return /* @__PURE__ */ jsx(Combobox.ItemIndicator, {
313
+ ...props,
314
+ ref,
315
+ className: cn("tw:pointer-events-none", "tw:absolute", "tw:right-2", "tw:group-data-[variant=default]/combobox-content:right-4", "tw:size-4", "tw:group-data-[highlighted]/combobox-item:text-accent-foreground", "tw:group-data-[variant=default]/combobox-content:group-data-[highlighted]/combobox-item:text-secondary-foreground", className),
316
+ render: /* @__PURE__ */ jsx(Check, {})
317
+ });
318
+ };
319
+ //#endregion
320
+ //#region src/components/Combobox/virtualList.ts
321
+ /** Above this many options, `virtualized="auto"` windows the list. */
322
+ const VIRTUALIZE_THRESHOLD = 30;
323
+ /**
324
+ * The position a windowed list gives each option it renders.
325
+ *
326
+ * - `index` is the option's place in Base UI's flat filtered list, which keyboard navigation counts.
327
+ * - `aria-setsize` / `aria-posinset` keep the set's length known while most options are out of the DOM.
328
+ * - `undefined` outside a windowed list, so a fully rendered list keeps its markup.
329
+ */
330
+ const VirtualRowContext = createContext(void 0);
331
+ /**
332
+ * Whether a combobox windows its list, and what ties Base UI's highlight to the window.
333
+ *
334
+ * - `'auto'` counts options, not groups, so a list of a few large groups windows too.
335
+ * - `onItemHighlighted` scrolls a row the keyboard reached into view; a pointer is over its row.
336
+ * - `ref` goes to `ComboboxVirtualList`.
337
+ */
338
+ const useVirtualList = (items, virtualized) => {
339
+ const ref = useRef(null);
340
+ const count = isGroupItems(items) ? items.reduce((sum, group) => sum + group.items.length, 0) : items.length;
341
+ return {
342
+ enabled: virtualized === "auto" ? count > VIRTUALIZE_THRESHOLD : virtualized,
343
+ ref,
344
+ onItemHighlighted: ({ reason, index }) => {
345
+ if (reason !== "pointer") ref.current?.scrollToItem(index);
346
+ }
347
+ };
348
+ };
349
+ //#endregion
350
+ //#region src/components/Combobox/ComboboxItem.tsx
351
+ const ComboboxItem = ({ ref, className, children, icon, indicator: variant = "check", ...props }) => /* @__PURE__ */ jsxs(Combobox.Item, {
352
+ ...props,
353
+ ...use(VirtualRowContext),
354
+ ref,
355
+ "data-slot": "combobox-item",
356
+ className: cn("tw:group/combobox-item", "tw:relative", "tw:flex", "tw:flex-1", "tw:items-center", "tw:gap-2", "tw:py-2", "tw:px-2", "tw:group-data-[variant=default]/combobox-content:px-4", "tw:rounded-lg", "tw:group-data-[variant=default]/combobox-content:rounded-none", "tw:text-sm", "tw:select-none", "tw:cursor-default", "tw:outline-hidden", "tw:data-[highlighted]:bg-accent", "tw:group-data-[variant=default]/combobox-content:data-[highlighted]:bg-secondary", "tw:data-[highlighted]:text-accent-foreground", "tw:group-data-[variant=default]/combobox-content:data-[highlighted]:text-secondary-foreground", "tw:data-disabled:pointer-events-none", "tw:data-disabled:opacity-50", "tw:[&_svg]:pointer-events-none", "tw:[&_svg]:shrink-0", "tw:[&_svg]:text-muted-foreground", "tw:[&_svg:not([class*='size-'])]:size-4", className),
357
+ children: [
358
+ variant !== "none" && /* @__PURE__ */ jsx(ComboboxItemIndicator, { variant }),
359
+ icon,
360
+ /* @__PURE__ */ jsx("span", {
361
+ className: "tw:truncate",
362
+ children
363
+ })
364
+ ]
365
+ });
366
+ //#endregion
367
+ //#region src/components/Combobox/ComboboxList.tsx
368
+ const ComboboxList = ({ ref, className, ...props }) => /* @__PURE__ */ jsx(Combobox.List, {
369
+ ref,
370
+ className: cn("tw:no-scrollbar", "tw:scroll-py-1", "tw:overflow-y-auto", "tw:overscroll-contain", "tw:min-h-0", "tw:flex-1", "tw:p-2", "tw:data-[empty]:p-0", "tw:group-data-[variant=default]/combobox-content:p-0", className),
371
+ ...props
372
+ });
373
+ //#endregion
374
+ //#region src/components/Combobox/ComboboxOpenButton.tsx
375
+ /**
376
+ * The button that opens the popup: a chevron, or a spinner while the options are loading.
377
+ *
378
+ * - The spinner swaps in for the icon inside the one button, which costs the control no width, so
379
+ * the input keeps its room whether or not a request is in flight.
380
+ * - The button keeps opening the popup while loading, so a list that already has items stays
381
+ * reachable.
382
+ */
383
+ const ComboboxOpenButton = ({ disabled, isLoading }) => /* @__PURE__ */ jsx(InputGroup.Button, {
384
+ disabled,
385
+ asChild: true,
386
+ "aria-label": "Open combobox",
387
+ children: /* @__PURE__ */ jsx(Combobox.Trigger, { children: isLoading ? /* @__PURE__ */ jsx(Loader2, { className: "tw:size-4 tw:animate-spin" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "tw:size-4" }) })
388
+ });
389
+ //#endregion
390
+ //#region src/components/Combobox/Group/ComboboxGroupHeader.tsx
391
+ /** Indent of a header's children (chevron + gap); the legacy variant pads its rows wider. */
392
+ const GROUP_CHILD_INDENT = "tw:pl-8 tw:group-data-[variant=default]/combobox-content:pl-10";
393
+ /**
394
+ * A group's own row, standing for the whole group.
395
+ *
396
+ * - Keyboard-navigable like any other row.
397
+ * - The chevron toggles by pointer; `ArrowRight` / `ArrowLeft` are handled by the owning control.
398
+ */
399
+ const ComboboxGroupHeader = ({ value, children, expanded, onToggle, checked, indicator = "check", disabled }) => {
400
+ const toggleFromChevron = (event) => {
401
+ event.stopPropagation();
402
+ onToggle();
403
+ };
404
+ return /* @__PURE__ */ jsx(ComboboxItem, {
405
+ value,
406
+ disabled,
407
+ "aria-description": expanded === void 0 ? void 0 : expanded ? "Expanded" : "Collapsed",
408
+ ...checked !== void 0 && { "aria-selected": checked === true },
409
+ indicator: "none",
410
+ className: "tw:font-medium",
411
+ onClick: checked !== void 0 ? void 0 : (event) => {
412
+ event.preventBaseUIHandler();
413
+ onToggle();
414
+ },
415
+ icon: /* @__PURE__ */ jsxs(Fragment$1, { children: [expanded !== void 0 && /* @__PURE__ */ jsx("span", {
416
+ "aria-hidden": true,
417
+ "data-slot": "combobox-group-toggle",
418
+ className: "tw:inline-flex tw:shrink-0",
419
+ onClick: toggleFromChevron,
420
+ children: /* @__PURE__ */ jsx(ChevronRight, { className: cn("tw:transition-transform", expanded && "tw:rotate-90") })
421
+ }), checked !== void 0 && /* @__PURE__ */ jsx(GroupIndicator, {
422
+ checked,
423
+ variant: indicator
424
+ })] }),
425
+ children
426
+ });
427
+ };
428
+ /**
429
+ * A group row's selection mark: all, some, or none.
430
+ *
431
+ * - Base UI's indicator is binary, so the row draws its own.
432
+ * - `checkbox` matches the children's leading box; `check` their trailing mark.
433
+ */
434
+ const GroupIndicator = ({ checked, variant }) => {
435
+ const Mark = checked === "mixed" ? Minus : Check;
436
+ if (variant === "checkbox") return /* @__PURE__ */ jsx("span", {
437
+ "aria-hidden": true,
438
+ "data-checked": checked,
439
+ className: cn("tw:inline-flex tw:size-4 tw:shrink-0 tw:items-center tw:justify-center", "tw:rounded tw:border tw:border-input tw:bg-background", checked !== false && "tw:border-primary tw:bg-primary"),
440
+ children: checked !== false && /* @__PURE__ */ jsx(Mark, { className: "tw:size-3 tw:stroke-[4px] tw:!text-primary-foreground" })
441
+ });
442
+ if (checked === false) return null;
443
+ return /* @__PURE__ */ jsx(Mark, {
444
+ "aria-hidden": true,
445
+ className: cn("tw:pointer-events-none tw:absolute tw:right-2 tw:size-4", "tw:group-data-[variant=default]/combobox-content:right-4", "tw:group-data-[highlighted]/combobox-item:text-accent-foreground", "tw:group-data-[variant=default]/combobox-content:group-data-[highlighted]/combobox-item:text-secondary-foreground")
446
+ });
447
+ };
448
+ //#endregion
449
+ //#region src/components/Combobox/Group/ComboboxGroup.tsx
450
+ const ComboboxGroup = ({ ref, className, children, ...props }) => /* @__PURE__ */ jsx(Combobox.Group, {
451
+ ref,
452
+ className: cn("tw:flex tw:flex-col tw:gap-0.5", className),
453
+ ...props,
454
+ children
455
+ });
456
+ //#endregion
457
+ //#region src/components/Combobox/Group/ComboboxGroupLabel.tsx
458
+ const ComboboxGroupLabel = ({ ref, className, ...props }) => /* @__PURE__ */ jsx(Combobox.GroupLabel, {
459
+ ...props,
460
+ ref,
461
+ className: cn("tw:px-2", "tw:py-1.5", "tw:text-xs", "tw:font-medium", "tw:leading-none", "tw:text-muted-foreground", "tw:group-data-[variant=default]/combobox-content:uppercase", "tw:group-data-[variant=default]/combobox-content:font-semibold", "tw:group-data-[variant=default]/combobox-content:tracking-wider", "tw:group-data-[variant=default]/combobox-content:text-[11px]", "tw:group-data-[variant=default]/combobox-content:text-black", "tw:group-data-[variant=default]/combobox-content:pt-2", "tw:group-data-[variant=default]/combobox-content:px-4", className)
462
+ });
463
+ //#endregion
464
+ //#region src/components/Combobox/Group/ComboboxCollection.tsx
465
+ const ComboboxCollection = ({ ...props }) => /* @__PURE__ */ jsx(Combobox.Collection, {
466
+ "data-slot": "combobox-collection",
467
+ ...props
468
+ });
469
+ //#endregion
470
+ //#region src/components/Combobox/ComboboxFullList.tsx
471
+ /** A Base UI collection child whose rows are keyed by position, as React matches unkeyed ones. */
472
+ const keyed = (render) => (entry, index) => /* @__PURE__ */ jsx(Fragment, { children: render(entry) }, index);
473
+ /** A combobox list that renders every row; `ComboboxVirtualList` renders only those in view. */
474
+ const ComboboxFullList = ({ renderItem, renderGroupItem, groupToLabel }) => {
475
+ const renderEntry = (entry) => {
476
+ if (!isGroupItem(entry)) return renderItem(entry);
477
+ const [lead] = entry.items;
478
+ if (isLooseItem(lead)) return renderItem(lead);
479
+ const label = groupToLabel?.(entry);
480
+ return /* @__PURE__ */ jsxs(ComboboxGroup, {
481
+ items: entry.items,
482
+ children: [label && /* @__PURE__ */ jsx(ComboboxGroupLabel, { children: label }), /* @__PURE__ */ jsx(ComboboxCollection, { children: keyed(renderGroupItem) })]
483
+ });
484
+ };
485
+ return /* @__PURE__ */ jsx(ComboboxList, { children: keyed(renderEntry) });
486
+ };
487
+ //#endregion
488
+ //#region src/components/Combobox/ComboboxLoadingEmpty.tsx
489
+ /**
490
+ * What the empty slot says while the options are loading, in place of the `empty` node.
491
+ *
492
+ * - `Combobox.Empty` is a polite live region, so the switch to this text and back to `empty` once
493
+ * the request settles is announced.
494
+ * - Base UI renders the slot only while the list has nothing to show, so a list that already has
495
+ * items keeps showing them.
496
+ */
497
+ const ComboboxLoadingEmpty = () => /* @__PURE__ */ jsxs("span", {
498
+ className: "tw:inline-flex tw:items-center tw:gap-2",
499
+ children: [/* @__PURE__ */ jsx(Loader2, { className: "tw:size-4 tw:animate-spin" }), "Loading…"]
500
+ });
501
+ //#endregion
502
+ //#region src/components/Combobox/ComboboxVirtualList.tsx
503
+ /** Rows rendered past each edge of the viewport, so a fast scroll does not paint blank. */
504
+ const OVERSCAN = 12;
505
+ const kindOf = (row) => row.type === "label" ? "label" : row.padded ? "padded" : "plain";
506
+ /**
507
+ * Base UI's filtered entries as one row per option or group label, in list order.
508
+ *
509
+ * - A group whose lone item is the create row or Select All stays outside any group, as the fully
510
+ * rendered list draws it.
511
+ * - `aria-setsize` counts the options sharing a parent, as a browser does for a rendered list.
512
+ */
513
+ const toRows = (entries, groupToLabel) => {
514
+ const rows = [];
515
+ const rowOfItem = [];
516
+ const labels = /* @__PURE__ */ new Map();
517
+ const push = (item, row) => {
518
+ rows.push({
519
+ type: "item",
520
+ item,
521
+ index: rowOfItem.length,
522
+ ...row
523
+ });
524
+ rowOfItem.push(rows.length - 1);
525
+ };
526
+ if (!isGroupItems(entries)) {
527
+ const items = entries.filter((entry) => !isGroupItem(entry));
528
+ items.forEach((item, i) => push(item, {
529
+ padded: false,
530
+ setSize: items.length,
531
+ posInSet: i + 1
532
+ }));
533
+ return {
534
+ rows,
535
+ rowOfItem,
536
+ labels
537
+ };
538
+ }
539
+ const isLoose = (group) => isLooseItem(group.items[0]);
540
+ const looseCount = entries.filter(isLoose).length;
541
+ let loosePosition = 0;
542
+ entries.forEach((entry, groupIndex) => {
543
+ if (isLoose(entry)) {
544
+ for (const item of entry.items) push(item, {
545
+ padded: false,
546
+ setSize: looseCount,
547
+ posInSet: ++loosePosition
548
+ });
549
+ return;
550
+ }
551
+ const group = `group-${groupIndex}`;
552
+ const label = groupToLabel?.(entry);
553
+ if (label) {
554
+ labels.set(group, label);
555
+ rows.push({
556
+ type: "label",
557
+ group,
558
+ padded: false
559
+ });
560
+ }
561
+ entry.items.forEach((item, i) => push(item, {
562
+ group,
563
+ padded: Boolean(label) || i > 0,
564
+ setSize: entry.items.length,
565
+ posInSet: i + 1
566
+ }));
567
+ });
568
+ return {
569
+ rows,
570
+ rowOfItem,
571
+ labels
572
+ };
573
+ };
574
+ /**
575
+ * A combobox list that puts only the rows in view into the DOM.
576
+ *
577
+ * - Lists what Base UI filtered, so search and keyboard navigation cover every option.
578
+ * - A group keeps its `role="group"` wrapper, and its name while its label row is out of view.
579
+ * - Rows keep their own height; a row not yet rendered is estimated from those that were.
580
+ */
581
+ const ComboboxVirtualList = ({ renderItem, renderGroupItem, groupToLabel, ref }) => {
582
+ const [listElement, attachList] = useElement();
583
+ const scrollMargin = useMemo(() => listElement ? Number.parseFloat(getComputedStyle(listElement).paddingTop) || 0 : 0, [listElement]);
584
+ const filteredItems = Combobox.useFilteredItems();
585
+ const { rows, rowOfItem, labels } = useMemo(() => toRows(filteredItems, groupToLabel), [filteredItems, groupToLabel]);
586
+ const sizesRef = useRef({});
587
+ const [rem] = useState(() => Number.parseFloat(getComputedStyle(document.documentElement).fontSize) || 0);
588
+ const virtualizer = useVirtualizer({
589
+ count: rows.length,
590
+ getScrollElement: () => listElement,
591
+ estimateSize: (index) => {
592
+ const row = rows[index];
593
+ const measured = sizesRef.current;
594
+ return (row && measured[kindOf(row)]) ?? measured.plain ?? measured.padded ?? rem;
595
+ },
596
+ measureElement: (element, entry, instance) => {
597
+ const size = measureElement(element, entry, instance);
598
+ const row = rows[instance.indexFromElement(element)];
599
+ if (row) {
600
+ const kind = kindOf(row);
601
+ sizesRef.current[kind] = Math.min(sizesRef.current[kind] ?? size, size);
602
+ }
603
+ return size;
604
+ },
605
+ observeElementRect: (instance, callback) => observeElementRect(instance, (rect) => callback({
606
+ ...rect,
607
+ height: Math.min(rect.height, instance.targetWindow?.innerHeight ?? rect.height)
608
+ })),
609
+ overscan: OVERSCAN,
610
+ scrollMargin
611
+ });
612
+ useImperativeHandle(ref, () => ({ scrollToItem: (index) => {
613
+ const row = rowOfItem[index];
614
+ if (row !== void 0) virtualizer.scrollToIndex(row, { align: "auto" });
615
+ } }));
616
+ const segments = [];
617
+ for (const virtualItem of virtualizer.getVirtualItems()) {
618
+ const group = rows[virtualItem.index]?.group;
619
+ const last = segments.at(-1);
620
+ if (group !== void 0 && last?.group === group) last.items.push(virtualItem);
621
+ else segments.push({
622
+ group,
623
+ start: virtualItem.start,
624
+ items: [virtualItem]
625
+ });
626
+ }
627
+ const placeAt = (start) => ({
628
+ position: "absolute",
629
+ top: 0,
630
+ left: 0,
631
+ width: "100%",
632
+ transform: `translateY(${start - scrollMargin}px)`
633
+ });
634
+ const renderRow = ({ key, index, start }) => {
635
+ const row = rows[index];
636
+ if (!row) return null;
637
+ return /* @__PURE__ */ jsx("div", {
638
+ "data-index": index,
639
+ ref: virtualizer.measureElement,
640
+ className: row.padded ? "tw:pt-0.5" : void 0,
641
+ style: row.group === void 0 ? placeAt(start) : void 0,
642
+ children: row.type === "label" ? /* @__PURE__ */ jsx(ComboboxGroupLabel, { children: labels.get(row.group ?? "") }) : /* @__PURE__ */ jsx(VirtualRowContext, {
643
+ value: {
644
+ index: row.index,
645
+ "aria-setsize": row.setSize,
646
+ "aria-posinset": row.posInSet
647
+ },
648
+ children: row.group === void 0 ? renderItem(row.item) : renderGroupItem(row.item)
649
+ })
650
+ }, key);
651
+ };
652
+ return /* @__PURE__ */ jsx(ComboboxList, {
653
+ ref: attachList,
654
+ children: /* @__PURE__ */ jsx("div", {
655
+ style: {
656
+ position: "relative",
657
+ width: "100%",
658
+ height: `${virtualizer.getTotalSize()}px`
659
+ },
660
+ children: segments.flatMap(({ group, start, items }) => {
661
+ if (group === void 0) return items.map(renderRow);
662
+ const label = labels.get(group);
663
+ const labelInView = items.some((item) => rows[item.index]?.type === "label");
664
+ return /* @__PURE__ */ jsxs(ComboboxGroup, {
665
+ className: "tw:gap-0",
666
+ style: placeAt(start),
667
+ children: [label && !labelInView && /* @__PURE__ */ jsx(ComboboxGroupLabel, {
668
+ className: "tw:sr-only",
669
+ children: label
670
+ }), items.map(renderRow)]
671
+ }, group);
672
+ })
673
+ })
674
+ });
675
+ };
676
+ //#endregion
677
+ //#region src/components/Combobox/ComboboxOptions.tsx
678
+ /**
679
+ * What a combobox popup lists: every row, the empty slot, and the loading text in it.
680
+ *
681
+ * - The list is windowed while `virtualized`, fully rendered otherwise.
682
+ */
683
+ const ComboboxOptions = ({ isLoading, empty, virtualized, listRef, groupHeaders, groupToLabel, indicator, itemToLabel, itemToIcon, itemToDisabled, createLabel, groupRowState }) => {
684
+ const renderItem = (item, className) => {
685
+ if (isSelectAllItem(item)) return /* @__PURE__ */ jsx(ComboboxItem, {
686
+ value: item,
687
+ indicator: "checkbox",
688
+ children: item.label
689
+ });
690
+ if (isCreatableItem(item)) return /* @__PURE__ */ jsx(ComboboxItem, {
691
+ value: item,
692
+ icon: /* @__PURE__ */ jsx(Plus, {}),
693
+ children: createLabel(item.value)
694
+ });
695
+ return /* @__PURE__ */ jsx(ComboboxItem, {
696
+ value: item,
697
+ indicator,
698
+ icon: itemToIcon(item),
699
+ disabled: itemToDisabled(item),
700
+ className,
701
+ children: itemToLabel(item)
702
+ });
703
+ };
704
+ const renderGroupItem = (item) => {
705
+ const header = groupHeaders.headerOf(item);
706
+ if (!header) return renderItem(item, groupHeaders.collapsible ? GROUP_CHILD_INDENT : void 0);
707
+ const state = groupRowState?.(item);
708
+ return /* @__PURE__ */ jsx(ComboboxGroupHeader, {
709
+ value: item,
710
+ expanded: groupHeaders.collapsible ? !header.collapsed : void 0,
711
+ onToggle: () => groupHeaders.toggle(header.index),
712
+ checked: state?.checked,
713
+ indicator,
714
+ disabled: state?.disabled ?? false,
715
+ children: groupToLabel(header.group)
716
+ });
717
+ };
718
+ const labelOfGroup = useCallback((group) => isEntriesGroup(group) ? void 0 : groupToLabel(group), [groupToLabel]);
719
+ const listProps = {
720
+ renderItem,
721
+ renderGroupItem,
722
+ groupToLabel: groupHeaders.enabled ? void 0 : labelOfGroup
723
+ };
724
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ComboboxEmpty, { children: isLoading ? /* @__PURE__ */ jsx(ComboboxLoadingEmpty, {}) : empty }), virtualized ? /* @__PURE__ */ jsx(ComboboxVirtualList, {
725
+ ref: listRef,
726
+ ...listProps
727
+ }) : /* @__PURE__ */ jsx(ComboboxFullList, { ...listProps })] });
728
+ };
729
+ //#endregion
730
+ //#region src/components/Combobox/ComboboxRoot.tsx
731
+ const ComboboxRoot = (props) => /* @__PURE__ */ jsx(Combobox.Root, { ...props });
732
+ //#endregion
733
+ //#region src/components/Combobox/ComboboxSeparator.tsx
734
+ const ComboboxSeparator = ({ ref, className, ...props }) => /* @__PURE__ */ jsx(Combobox.Separator, {
735
+ ref,
736
+ className: cn("tw:mx-2 tw:my-1 tw:h-px tw:bg-border", className),
737
+ ...props
738
+ });
739
+ //#endregion
740
+ //#region src/components/Combobox/createdItems.ts
741
+ /**
742
+ * `list` followed by the values `allowCreate` minted, as entries of it; stable while both are.
743
+ *
744
+ * - Listed so a created value stays pickable: Base UI drops a value missing from `items`.
745
+ */
746
+ const useWithCreated = (list, created) => useMemo(() => created.length === 0 ? list : [...list, ...toEntries(list, created)], [list, created]);
747
+ //#endregion
748
+ //#region src/components/Combobox/groupHeaders.ts
749
+ /**
750
+ * Gives each group a row (rendered with `ComboboxGroupHeader`) and collapses groups on request.
751
+ *
752
+ * - The row is the group's first item, so Base UI navigates, filters and presses it.
753
+ * - A collapsed group hands Base UI only its row: Base UI never filters an empty query.
754
+ * - A query shows every match regardless of collapse; a row shows only while its group matches.
755
+ * - Collapse state is keyed by a group's position in `items`.
756
+ */
757
+ const useGroupHeaders = ({ items, collapsible, selectable, query, matches, groupToValue, isItemEqualToValue }) => {
758
+ const [collapsedIndexes, setCollapsedIndexes] = useState(() => /* @__PURE__ */ new Set());
759
+ const highlightedRef = useRef(void 0);
760
+ const enabled = (collapsible || selectable) && isGroupItems(items);
761
+ const headers = /* @__PURE__ */ new Map();
762
+ const listItems = !enabled ? items : items.map((group, index) => {
763
+ const collapsed = collapsible && query === "" && collapsedIndexes.has(index);
764
+ const matching = query === "" ? group.items : group.items.filter(matches);
765
+ const row = groupToValue ? groupToValue(group) : createGroupHeaderItem(index);
766
+ headers.set(row, {
767
+ group,
768
+ index,
769
+ collapsed,
770
+ matching
771
+ });
772
+ return {
773
+ ...group,
774
+ items: collapsed ? [row] : [row, ...group.items]
775
+ };
776
+ });
777
+ const toggle = (index) => setCollapsedIndexes((prev) => {
778
+ const next = new Set(prev);
779
+ if (!next.delete(index)) next.add(index);
780
+ return next;
781
+ });
782
+ const headerOf = (item) => headers.get(item);
783
+ const highlightedHeader = () => {
784
+ const item = highlightedRef.current;
785
+ if (item === void 0) return void 0;
786
+ const header = headers.get(item);
787
+ if (header) return header;
788
+ for (const [row, entry] of headers) if (isItemEqualToValue(row, item)) return entry;
789
+ };
790
+ return {
791
+ enabled,
792
+ /** `items` with group rows added and collapsed groups' items removed. */
793
+ items: listItems,
794
+ collapsible,
795
+ headerOf,
796
+ toggle,
797
+ /** `filter` verdict for a group row (matches while its group does); `undefined` otherwise. */
798
+ filterHeader: (item) => {
799
+ const header = headerOf(item);
800
+ return header ? header.matching.length > 0 : void 0;
801
+ },
802
+ /** For the root's `onItemHighlighted`: which row the keyboard would toggle. */
803
+ onItemHighlighted: (item) => {
804
+ highlightedRef.current = item;
805
+ },
806
+ /** For the root's `onOpenChange`: a closed popup has no highlighted row to toggle. */
807
+ onOpenChange: (open) => {
808
+ if (!open) highlightedRef.current = void 0;
809
+ },
810
+ /**
811
+ * For the input's `onKeyDown`: `ArrowRight` / `ArrowLeft` expand / collapse the highlighted row.
812
+ * Only without a query; also stops Base UI moving to the chips.
813
+ */
814
+ onInputKeyDown: (event) => {
815
+ if (!collapsible || query !== "") return;
816
+ if (event.key !== "ArrowRight" && event.key !== "ArrowLeft") return;
817
+ const header = highlightedHeader();
818
+ if (!header) return;
819
+ event.preventDefault();
820
+ event.preventBaseUIHandler();
821
+ if (header.collapsed === (event.key === "ArrowRight")) toggle(header.index);
822
+ }
823
+ };
824
+ };
825
+ //#endregion
826
+ //#region src/components/Combobox/query.ts
827
+ /**
828
+ * The text a combobox's input takes, with `inputValueSanitizer` applied to what the user typed.
829
+ *
830
+ * - `input-change` is the only reason carrying typed text. Every other one carries text the
831
+ * control itself put there — an item's label, or the empty string a clear leaves — which a
832
+ * sanitizer aimed at typed characters would mangle.
833
+ * - A sanitizer sees the whole text on every keystroke, so it has to rewrite rather than drop:
834
+ * one calling `trim()` swallows the space before the next word.
835
+ */
836
+ const sanitizeTypedInput = (next, reason, sanitizer) => reason === "input-change" ? sanitizer?.(next) ?? next : next;
837
+ /**
838
+ * Reports the query the list filters by to the control's owner.
839
+ *
840
+ * - Fires from an effect rather than the input handler because `query` is derived: in `Combobox`
841
+ * a selection showing its own label empties it without a keystroke, so the handler never sees
842
+ * every value it takes.
843
+ * - The mount render reports too, so an owner fetching on the query needs no first fetch of its
844
+ * own.
845
+ */
846
+ const useQueryReporter = (query, onQueryChange) => {
847
+ const report = useStableCallback(onQueryChange ?? noop);
848
+ useEffect(() => {
849
+ report(query);
850
+ }, [query, report]);
851
+ };
852
+ //#endregion
853
+ //#region src/components/Combobox/Combobox.tsx
854
+ const acceptAll = () => true;
855
+ const NO_ITEMS = [];
856
+ const Combobox$1 = ({ items: _itemsProp, value, defaultValue, onValueChange, itemToStringLabel: itemToStringLabelProp, itemToStringValue, disabled, filter, inputRef, onOpenChangeComplete, isItemEqualToValue: isItemEqualToValueProp, variant, sizing, focusVariant, state, placeholder, allowClear = true, id, name, onBlur, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, "aria-required": ariaRequired, className, empty = "No items", isLoading = false, indicator, prefix, virtualized = false, inputValueSanitizer, onQueryChange, allowCreate, queryToCreateValue, queryToCreateLabel = defaultQueryToCreateLabel, canCreate, itemToDisabled = defaultItemToDisabled, itemToLabel: itemToLabelProp, itemToIcon = defaultItemToIcon, itemToSelectedLabel, groupToLabel = defaultGroupToLabel, collapsibleGroups = false, groupToValue }) => {
857
+ /** An item's string identity: input text, default search subject, accessible value. */
858
+ const labelOf = useCallback((item) => itemToStringLabelProp?.(item) ?? toLabel(item), [itemToStringLabelProp]);
859
+ const itemToLabel = itemToLabelProp ?? defaultRowLabel(itemToStringLabelProp);
860
+ const [typedText, setTypedText] = useState(null);
861
+ const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue ?? null);
862
+ const selectedItem = value !== void 0 ? value : uncontrolledValue;
863
+ const selectedLabel = selectedItem == null ? null : labelOf(selectedItem);
864
+ const isShowingSelection = selectedLabel !== null && (typedText === null || typedText === selectedLabel);
865
+ const inputValue = typedText ?? selectedLabel ?? "";
866
+ const selectedNode = itemToSelectedLabel && selectedItem != null && isShowingSelection ? itemToSelectedLabel(selectedItem) : null;
867
+ const query = (isShowingSelection ? "" : typedText ?? "").trim();
868
+ const queryLower = query.toLowerCase();
869
+ useQueryReporter(query, onQueryChange);
870
+ const busy = isLoading || void 0;
871
+ const itemsProp = _itemsProp ?? NO_ITEMS;
872
+ const sampleItem = flatItems(itemsProp)[0];
873
+ const isItemEqualToValue = useItemEquality(isItemEqualToValueProp);
874
+ const [createdItems, setCreatedItems] = useState([]);
875
+ const [createdItem] = createdItems;
876
+ const itemsHoldCreated = useMemo(() => createdItem !== void 0 && flatItems(itemsProp).some((listed) => isItemEqualToValue(listed, createdItem)), [
877
+ createdItem,
878
+ itemsProp,
879
+ isItemEqualToValue
880
+ ]);
881
+ const created = createdItem !== void 0 && !itemsHoldCreated && selectedItem != null && isItemEqualToValue(createdItem, selectedItem) ? createdItems : NO_ITEMS;
882
+ const itemToStringLabel = useCallback((value) => {
883
+ if (isCreatableItem(value)) return value.value;
884
+ if (isGroupHeaderItem(value)) return value.label;
885
+ return labelOf(value);
886
+ }, [labelOf]);
887
+ const { contains } = Combobox.useFilter();
888
+ const itemFilter = filter ?? contains;
889
+ const groupHeaders = useGroupHeaders({
890
+ items: itemsProp,
891
+ collapsible: collapsibleGroups,
892
+ selectable: groupToValue !== void 0,
893
+ query,
894
+ matches: (item) => itemFilter(item, query, itemToStringLabel),
895
+ groupToValue,
896
+ isItemEqualToValue
897
+ });
898
+ const allItems = useWithCreated(itemsProp, created);
899
+ const listItems = useWithCreated(groupHeaders.items, created);
900
+ const showCreateRow = (() => {
901
+ if (!allowCreate || disabled || !query) return false;
902
+ return !flatItems(allItems).some((item) => labelOf(item).toLowerCase() === queryLower) && (!canCreate || canCreate(query));
903
+ })();
904
+ const items = useMemo(() => showCreateRow ? [...listItems, ...toEntries(listItems, [createCreatableItem(query)])] : listItems, [
905
+ showCreateRow,
906
+ listItems,
907
+ query
908
+ ]);
909
+ const filterHeader = groupHeaders.enabled ? groupHeaders.filterHeader : void 0;
910
+ const queryFilter = useMemo(() => {
911
+ if (filterHeader) return (item, query, itemToString) => filterHeader(item) ?? (isCreatableItem(item) || itemFilter(item, query, itemToString));
912
+ if (!allowCreate || !filter) return filter;
913
+ return (item, query, itemToString) => isCreatableItem(item) || filter(item, query, itemToString);
914
+ }, [
915
+ filterHeader,
916
+ allowCreate,
917
+ filter,
918
+ itemFilter
919
+ ]);
920
+ const wrappedFilter = isShowingSelection ? acceptAll : queryFilter;
921
+ const wrappedItemToStringValue = useCreatableStringValue(itemToStringValue, allowCreate);
922
+ const handleInputValueChange = (next, { reason }) => {
923
+ if (reason !== "input-change") {
924
+ setTypedText(null);
925
+ return;
926
+ }
927
+ const typed = inputValueSanitizer?.(next) ?? next;
928
+ setTypedText(typed === "" || typed.trim() !== "" ? typed : null);
929
+ };
930
+ const handleOpenChange = (open) => {
931
+ if (!open) setTypedText(null);
932
+ groupHeaders.onOpenChange(open);
933
+ };
934
+ const handleOnValueChange = (next, event) => {
935
+ if (isCreatableItem(next)) {
936
+ const newValue = defaultToCreateValue(next.value, sampleItem, queryToCreateValue);
937
+ setCreatedItems([newValue]);
938
+ setUncontrolledValue(newValue);
939
+ onValueChange?.(newValue, event);
940
+ return;
941
+ }
942
+ setUncontrolledValue(next);
943
+ onValueChange?.(next, event);
944
+ };
945
+ const virtualList = useVirtualList(allItems, virtualized);
946
+ const comboboxInput = /* @__PURE__ */ jsx(ComboboxInput, {
947
+ id,
948
+ name,
949
+ onBlur,
950
+ "aria-label": ariaLabel,
951
+ "aria-labelledby": ariaLabelledBy,
952
+ "aria-describedby": ariaDescribedBy,
953
+ "aria-invalid": ariaInvalid,
954
+ "aria-required": ariaRequired,
955
+ "aria-busy": busy,
956
+ placeholder,
957
+ disabled,
958
+ onKeyDown: groupHeaders.onInputKeyDown,
959
+ className: cn(selectedNode != null && "tw:text-transparent tw:caret-foreground tw:selection:bg-transparent")
960
+ });
961
+ return /* @__PURE__ */ jsxs(Combobox.Root, {
962
+ items,
963
+ autoHighlight: true,
964
+ value,
965
+ defaultValue,
966
+ filter: wrappedFilter,
967
+ onValueChange: handleOnValueChange,
968
+ itemToStringLabel,
969
+ isItemEqualToValue,
970
+ itemToStringValue: wrappedItemToStringValue,
971
+ onOpenChange: handleOpenChange,
972
+ onOpenChangeComplete,
973
+ disabled,
974
+ inputRef,
975
+ inputValue,
976
+ onInputValueChange: handleInputValueChange,
977
+ virtualized: virtualList.enabled,
978
+ onItemHighlighted: (item, details) => {
979
+ groupHeaders.onItemHighlighted(item);
980
+ virtualList.onItemHighlighted(details);
981
+ },
982
+ children: [/* @__PURE__ */ jsxs(ComboboxInputGroup, {
983
+ variant,
984
+ sizing,
985
+ state,
986
+ focusVariant,
987
+ className,
988
+ children: [itemToSelectedLabel != null ? /* @__PURE__ */ jsxs("div", {
989
+ className: "tw:relative tw:flex tw:min-w-0 tw:flex-1",
990
+ children: [(prefix != null || selectedNode != null) && /* @__PURE__ */ jsxs(InputGroup.Addon, {
991
+ align: "inline-start",
992
+ className: cn(selectedNode != null && "tw:pointer-events-none tw:absolute tw:inset-y-0 tw:left-0 tw:max-w-full tw:overflow-hidden"),
993
+ children: [prefix, selectedNode]
994
+ }), comboboxInput]
995
+ }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [prefix != null && /* @__PURE__ */ jsx(InputGroup.Addon, {
996
+ align: "inline-start",
997
+ children: prefix
998
+ }), comboboxInput] }), /* @__PURE__ */ jsxs(InputGroup.Addon, {
999
+ align: "inline-end",
1000
+ children: [allowClear && /* @__PURE__ */ jsx(ComboboxClearButton, { disabled }), /* @__PURE__ */ jsx(ComboboxOpenButton, {
1001
+ disabled,
1002
+ isLoading
1003
+ })]
1004
+ })]
1005
+ }), /* @__PURE__ */ jsx(ComboboxContent, { children: /* @__PURE__ */ jsx(ComboboxOptions, {
1006
+ isLoading,
1007
+ empty,
1008
+ virtualized: virtualList.enabled,
1009
+ listRef: virtualList.ref,
1010
+ groupHeaders,
1011
+ groupToLabel,
1012
+ indicator,
1013
+ itemToLabel: (item) => itemToLabel(item, query),
1014
+ itemToIcon,
1015
+ itemToDisabled,
1016
+ createLabel: queryToCreateLabel,
1017
+ groupRowState: groupToValue ? (row) => ({
1018
+ checked: selectedItem != null && isItemEqualToValue(row, selectedItem),
1019
+ disabled: itemToDisabled(row)
1020
+ }) : void 0
1021
+ }) })]
1022
+ });
1023
+ };
1024
+ Combobox$1.Root = ComboboxRoot;
1025
+ Combobox$1.InputGroup = ComboboxInputGroup;
1026
+ Combobox$1.Input = ComboboxInput;
1027
+ Combobox$1.Content = ComboboxContent;
1028
+ Combobox$1.List = ComboboxList;
1029
+ Combobox$1.Item = ComboboxItem;
1030
+ Combobox$1.Empty = ComboboxEmpty;
1031
+ Combobox$1.Value = Combobox.Value;
1032
+ Combobox$1.Separator = ComboboxSeparator;
1033
+ Combobox$1.Group = ComboboxGroup;
1034
+ Combobox$1.GroupLabel = ComboboxGroupLabel;
1035
+ Combobox$1.GroupList = ComboboxCollection;
1036
+ Combobox$1.Chips = ComboboxChips;
1037
+ Combobox$1.Chip = ComboboxChip;
1038
+ //#endregion
1039
+ //#region src/components/Combobox/matchByWords.ts
1040
+ const toWords = (query) => query.toLowerCase().split(/\s+/).filter(Boolean);
1041
+ const isFilled = (text) => text !== null && text !== void 0 && text !== "";
1042
+ const isTextList = (texts) => Array.isArray(texts);
1043
+ /**
1044
+ * Whether every word of `query` occurs in some of `texts`, ignoring case.
1045
+ *
1046
+ * - Words match by containment, across texts, in any order; an empty query matches everything.
1047
+ * - Plain lowercased `includes`, not `Intl.Collator`: `Muller` does not find `Müller`.
1048
+ * - Not interchangeable with kbc-ui's own `matchByWords` (single-space split, keeps empty texts).
1049
+ * - A `filter` for when the searchable text is not the label; else use {@link filterByWords}.
1050
+ */
1051
+ const matchByWords = (texts, query) => {
1052
+ const words = toWords(query);
1053
+ if (words.length === 0) return true;
1054
+ const haystacks = (isTextList(texts) ? texts : [texts]).filter(isFilled).map((text) => String(text).toLowerCase());
1055
+ return words.every((word) => haystacks.some((haystack) => haystack.includes(word)));
1056
+ };
1057
+ /**
1058
+ * `filter` matching the item's displayed label word by word: `filter={filterByWords}`.
1059
+ *
1060
+ * - Generic, so it keeps the combobox's item type inference.
1061
+ * - Label: `itemToStringLabel` if passed, else the item's `label`, `value`, or string form.
1062
+ * - Only the label is searched, by design: never match what the user cannot see.
1063
+ * - Close over {@link matchByWords} to search other fields.
1064
+ */
1065
+ const filterByWords = (item, query, itemToString) => matchByWords(itemToString?.(item) ?? toLabel(item), query);
1066
+ //#endregion
1067
+ export { BLANK_VALUES, Combobox$1 as Combobox, ComboboxClearButton, ComboboxOpenButton, ComboboxOptions, createCreatableItem, defaultGroupToLabel, defaultItemToDisabled, defaultItemToIcon, defaultQueryToCreateLabel, defaultRowLabel, defaultToCreateValue, filterByWords, flatItems, isCreatableItem, isGroupHeaderItem, isSelectAllItem, matchByWords, namedLabel, sanitizeTypedInput, selectAllItem, toEntries, toLabel, useCreatableStringValue, useGroupHeaders, useItemEquality, useQueryReporter, useVirtualList, useWithCreated, withBlankValues };
1068
+
1069
+ //# sourceMappingURL=Combobox-CxRAYOBt.js.map