@cube-dev/ui-kit 0.0.0-canary-ebc4edb → 0.0.0-canary-586c588

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 (521) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/es/_internal/hooks/index.js +1 -1
  3. package/es/_internal/hooks/use-chained-callback.js +1 -1
  4. package/es/_internal/hooks/use-debounced-value.js +1 -1
  5. package/es/_internal/hooks/use-deprecation-warning.js +1 -1
  6. package/es/_internal/hooks/use-effect-once.js +1 -1
  7. package/es/_internal/hooks/use-event.js +1 -1
  8. package/es/_internal/hooks/use-is-first-render.js +1 -1
  9. package/es/_internal/hooks/use-sync-ref.js +1 -1
  10. package/es/_internal/hooks/use-timer/index.js +1 -1
  11. package/es/_internal/hooks/use-timer/timer.js +1 -1
  12. package/es/_internal/hooks/use-timer/use-timer.js +1 -1
  13. package/es/_internal/hooks/use-update-effect.js +1 -1
  14. package/es/_internal/hooks/use-warn.js +1 -1
  15. package/es/_internal/index.js +1 -1
  16. package/es/components/Block.js +1 -1
  17. package/es/components/GlobalStyles.js +1 -1
  18. package/es/components/GridProvider.js +1 -1
  19. package/es/components/HiddenInput.js +1 -1
  20. package/es/components/Item.js +1 -1
  21. package/es/components/OpenTrasition.js +1 -1
  22. package/es/components/Root.js +1 -1
  23. package/es/components/actions/Action/Action.js +1 -1
  24. package/es/components/actions/Button/Button.js +1 -1
  25. package/es/components/actions/Button/index.js +1 -1
  26. package/es/components/actions/ButtonGroup/ButtonGroup.js +1 -1
  27. package/es/components/actions/CommandMenu/CommandMenu.js +1 -1
  28. package/es/components/actions/CommandMenu/index.js +1 -1
  29. package/es/components/actions/CommandMenu/styled.js +1 -1
  30. package/es/components/actions/ItemAction/ItemAction.js +7 -2
  31. package/es/components/actions/ItemAction/index.js +1 -1
  32. package/es/components/actions/ItemButton/ItemButton.js +1 -1
  33. package/es/components/actions/ItemButton/index.js +1 -1
  34. package/es/components/actions/Link/Link.js +1 -1
  35. package/es/components/actions/Menu/Menu.js +1 -1
  36. package/es/components/actions/Menu/MenuItem.js +1 -1
  37. package/es/components/actions/Menu/MenuSection.js +1 -1
  38. package/es/components/actions/Menu/MenuTrigger.js +1 -1
  39. package/es/components/actions/Menu/SubMenuTrigger.js +1 -1
  40. package/es/components/actions/Menu/SubmenuTriggerContext.js +1 -1
  41. package/es/components/actions/Menu/context.js +1 -1
  42. package/es/components/actions/Menu/index.js +1 -1
  43. package/es/components/actions/Menu/styled.js +1 -1
  44. package/es/components/actions/index.js +1 -1
  45. package/es/components/actions/use-action.js +1 -1
  46. package/es/components/actions/use-anchored-menu.js +1 -1
  47. package/es/components/actions/use-context-menu.js +1 -1
  48. package/es/components/content/ActiveZone/ActiveZone.js +1 -1
  49. package/es/components/content/Alert/Alert.js +1 -1
  50. package/es/components/content/Alert/index.js +1 -1
  51. package/es/components/content/Alert/types.js +1 -1
  52. package/es/components/content/Alert/use-alert.js +1 -1
  53. package/es/components/content/Avatar/Avatar.js +1 -1
  54. package/es/components/content/Badge/Badge.js +1 -1
  55. package/es/components/content/Card/Card.js +1 -1
  56. package/es/components/content/Content.js +1 -1
  57. package/es/components/content/CopyPasteBlock/CopyPasteBlock.js +1 -1
  58. package/es/components/content/CopyPasteBlock/index.js +1 -1
  59. package/es/components/content/CopySnippet/CopySnippet.js +1 -1
  60. package/es/components/content/CopySnippet/index.js +1 -1
  61. package/es/components/content/Divider.js +1 -1
  62. package/es/components/content/Footer.js +1 -1
  63. package/es/components/content/Header.js +1 -1
  64. package/es/components/content/HotKeys/HotKeys.js +1 -1
  65. package/es/components/content/HotKeys/index.js +1 -1
  66. package/es/components/content/ItemBase/ItemBase.js +1 -1
  67. package/es/components/content/ItemBase/index.js +1 -1
  68. package/es/components/content/List/SectionHeading.js +1 -1
  69. package/es/components/content/List/index.js +1 -1
  70. package/es/components/content/Paragraph.js +1 -1
  71. package/es/components/content/Placeholder/Placeholder.js +1 -1
  72. package/es/components/content/PrismCode/PrismCode.js +1 -1
  73. package/es/components/content/PrismCode/prismSetup.js +1 -1
  74. package/es/components/content/PrismDiffCode/PrismDiffCode.js +1 -1
  75. package/es/components/content/Result/Result.js +1 -1
  76. package/es/components/content/Skeleton/Skeleton.js +1 -1
  77. package/es/components/content/Tag/Tag.js +1 -1
  78. package/es/components/content/Text.js +1 -1
  79. package/es/components/content/Title.js +1 -1
  80. package/es/components/fields/Checkbox/Checkbox.js +1 -1
  81. package/es/components/fields/Checkbox/CheckboxGroup.js +1 -1
  82. package/es/components/fields/Checkbox/context.js +1 -1
  83. package/es/components/fields/Checkbox/index.js +1 -1
  84. package/es/components/fields/ComboBox/ComboBox.js +717 -180
  85. package/es/components/fields/ComboBox/index.js +2 -2
  86. package/es/components/fields/DatePicker/DateInput.js +1 -1
  87. package/es/components/fields/DatePicker/DateInputBase.js +1 -1
  88. package/es/components/fields/DatePicker/DatePicker.js +1 -1
  89. package/es/components/fields/DatePicker/DatePickerButton.js +1 -1
  90. package/es/components/fields/DatePicker/DatePickerElement.js +1 -1
  91. package/es/components/fields/DatePicker/DatePickerInput.js +1 -1
  92. package/es/components/fields/DatePicker/DatePickerSegment.js +1 -1
  93. package/es/components/fields/DatePicker/DateRangePicker.js +1 -1
  94. package/es/components/fields/DatePicker/DateRangeSeparatedPicker.js +1 -1
  95. package/es/components/fields/DatePicker/TimeInput.js +1 -1
  96. package/es/components/fields/DatePicker/index.js +1 -1
  97. package/es/components/fields/DatePicker/intl.js +1 -1
  98. package/es/components/fields/DatePicker/parseDate.js +1 -1
  99. package/es/components/fields/DatePicker/props.js +1 -1
  100. package/es/components/fields/DatePicker/types.js +1 -1
  101. package/es/components/fields/DatePicker/utils.js +1 -1
  102. package/es/components/fields/FileInput/FileInput.js +1 -1
  103. package/es/components/fields/FilterListBox/FilterListBox.js +42 -47
  104. package/es/components/fields/FilterListBox/index.js +1 -1
  105. package/es/components/fields/FilterPicker/FilterPicker.js +78 -311
  106. package/es/components/fields/FilterPicker/index.js +1 -1
  107. package/es/components/fields/Input/Input.js +1 -1
  108. package/es/components/fields/Input/index.js +1 -1
  109. package/es/components/fields/LegacyComboBox/LegacyComboBox.js +290 -0
  110. package/es/components/fields/LegacyComboBox/index.js +10 -0
  111. package/es/components/fields/ListBox/ListBox.js +35 -5
  112. package/es/components/fields/ListBox/index.js +1 -1
  113. package/es/components/fields/NumberInput/NumberInput.js +1 -1
  114. package/es/components/fields/NumberInput/StepButton.js +1 -1
  115. package/es/components/fields/PasswordInput/PasswordInput.js +1 -1
  116. package/es/components/fields/RadioGroup/Radio.js +1 -1
  117. package/es/components/fields/RadioGroup/RadioGroup.js +1 -1
  118. package/es/components/fields/RadioGroup/context.js +1 -1
  119. package/es/components/fields/RadioGroup/index.js +1 -1
  120. package/es/components/fields/SearchInput/SearchInput.js +1 -1
  121. package/es/components/fields/SearchInput/index.js +1 -1
  122. package/es/components/fields/Select/Select.js +56 -50
  123. package/es/components/fields/Select/index.js +1 -1
  124. package/es/components/fields/Slider/Gradation.js +1 -1
  125. package/es/components/fields/Slider/Header.js +1 -1
  126. package/es/components/fields/Slider/RangeSlider.js +1 -1
  127. package/es/components/fields/Slider/Slider.js +1 -1
  128. package/es/components/fields/Slider/SliderBase.js +1 -1
  129. package/es/components/fields/Slider/SliderInput.js +1 -1
  130. package/es/components/fields/Slider/SliderThumb.js +1 -1
  131. package/es/components/fields/Slider/SliderTrack.js +1 -1
  132. package/es/components/fields/Slider/elements.js +1 -1
  133. package/es/components/fields/Slider/index.js +1 -1
  134. package/es/components/fields/Slider/types.js +1 -1
  135. package/es/components/fields/Switch/Switch.js +1 -1
  136. package/es/components/fields/Switch/index.js +1 -1
  137. package/es/components/fields/TextArea/TextArea.js +1 -1
  138. package/es/components/fields/TextArea/index.js +1 -1
  139. package/es/components/fields/TextInput/TextInput.js +1 -1
  140. package/es/components/fields/TextInput/TextInputBase.js +1 -1
  141. package/es/components/fields/TextInput/index.js +1 -1
  142. package/es/components/fields/TextInputMapper/TextInputMapper.js +2 -2
  143. package/es/components/fields/TextInputMapper/index.js +1 -1
  144. package/es/components/fields/index.js +2 -1
  145. package/es/components/form/FieldWrapper/FieldWrapper.js +1 -1
  146. package/es/components/form/FieldWrapper/extract-field-wrapper-props.js +1 -1
  147. package/es/components/form/FieldWrapper/index.js +1 -1
  148. package/es/components/form/FieldWrapper/types.js +1 -1
  149. package/es/components/form/Form/Field.js +1 -1
  150. package/es/components/form/Form/Form.js +1 -1
  151. package/es/components/form/Form/ResetButton/ResetButton.js +1 -1
  152. package/es/components/form/Form/ResetButton/index.js +1 -1
  153. package/es/components/form/Form/SubmitButton/SubmitButton.js +1 -1
  154. package/es/components/form/Form/SubmitButton/index.js +1 -1
  155. package/es/components/form/Form/SubmitError.js +1 -1
  156. package/es/components/form/Form/index.js +1 -1
  157. package/es/components/form/Form/types.js +1 -1
  158. package/es/components/form/Form/use-field/index.js +1 -1
  159. package/es/components/form/Form/use-field/types.js +1 -1
  160. package/es/components/form/Form/use-field/use-field-props.js +1 -1
  161. package/es/components/form/Form/use-field/use-field.js +1 -1
  162. package/es/components/form/Form/use-form.js +1 -1
  163. package/es/components/form/Form/validation.js +1 -1
  164. package/es/components/form/Label.js +1 -1
  165. package/es/components/form/index.js +1 -1
  166. package/es/components/form/wrapper.js +1 -1
  167. package/es/components/helpers/DisplayTransition/DisplayTransition.js +242 -0
  168. package/es/components/helpers/index.js +10 -0
  169. package/es/components/layout/Flex.js +1 -1
  170. package/es/components/layout/Flow.js +1 -1
  171. package/es/components/layout/Grid.js +1 -1
  172. package/es/components/layout/Panel.js +1 -1
  173. package/es/components/layout/Prefix.js +1 -1
  174. package/es/components/layout/ResizablePanel.js +1 -1
  175. package/es/components/layout/Space.js +1 -1
  176. package/es/components/layout/Suffix.js +1 -1
  177. package/es/components/navigation/LegacyTabs/LegacyTabs.js +1 -1
  178. package/es/components/organisms/FileTabs/FileTabs.js +1 -1
  179. package/es/components/organisms/StatsCard/StatsCard.js +1 -1
  180. package/es/components/other/Base64Upload/Base64Upload.js +1 -1
  181. package/es/components/other/Calendar/Calendar.js +1 -1
  182. package/es/components/other/Calendar/CalendarCell.js +1 -1
  183. package/es/components/other/Calendar/CalendarGrid.js +1 -1
  184. package/es/components/other/Calendar/RangeCalendar.js +1 -1
  185. package/es/components/other/CloudLogo/CloudLogo.js +1 -1
  186. package/es/components/overlays/AlertDialog/AlertDialog.js +1 -1
  187. package/es/components/overlays/AlertDialog/AlertDialogApiProvider.js +1 -1
  188. package/es/components/overlays/AlertDialog/AlertDialogZone.js +1 -1
  189. package/es/components/overlays/AlertDialog/index.js +1 -1
  190. package/es/components/overlays/AlertDialog/types.js +1 -1
  191. package/es/components/overlays/Dialog/Dialog.js +1 -1
  192. package/es/components/overlays/Dialog/DialogContainer.js +1 -1
  193. package/es/components/overlays/Dialog/DialogForm.js +1 -1
  194. package/es/components/overlays/Dialog/DialogTrigger.js +1 -1
  195. package/es/components/overlays/Dialog/context.js +1 -1
  196. package/es/components/overlays/Dialog/index.js +1 -1
  197. package/es/components/overlays/Dialog/use-dialog-container.js +1 -1
  198. package/es/components/overlays/Modal/Modal.js +1 -1
  199. package/es/components/overlays/Modal/OpenTransition.js +1 -1
  200. package/es/components/overlays/Modal/Overlay.js +1 -1
  201. package/es/components/overlays/Modal/Popover.js +1 -1
  202. package/es/components/overlays/Modal/Tray.js +1 -1
  203. package/es/components/overlays/Modal/Underlay.js +1 -1
  204. package/es/components/overlays/Modal/index.js +1 -1
  205. package/es/components/overlays/Modal/types.js +1 -1
  206. package/es/components/overlays/NewNotifications/Bar/FloatingNotification.js +1 -1
  207. package/es/components/overlays/NewNotifications/Bar/NotificationsBar.js +1 -1
  208. package/es/components/overlays/NewNotifications/Bar/TransitionComponent.js +1 -1
  209. package/es/components/overlays/NewNotifications/Bar/index.js +1 -1
  210. package/es/components/overlays/NewNotifications/Dialog/NotificationsDialogContext.js +1 -1
  211. package/es/components/overlays/NewNotifications/Dialog/NotificationsDialogTrigger.js +1 -1
  212. package/es/components/overlays/NewNotifications/Dialog/index.js +1 -1
  213. package/es/components/overlays/NewNotifications/Notification.js +1 -1
  214. package/es/components/overlays/NewNotifications/NotificationView/NotificationAction.js +1 -1
  215. package/es/components/overlays/NewNotifications/NotificationView/NotificationCloseButton.js +1 -1
  216. package/es/components/overlays/NewNotifications/NotificationView/NotificationDescription.js +1 -1
  217. package/es/components/overlays/NewNotifications/NotificationView/NotificationFooter.js +1 -1
  218. package/es/components/overlays/NewNotifications/NotificationView/NotificationHeader.js +1 -1
  219. package/es/components/overlays/NewNotifications/NotificationView/NotificationIcon.js +1 -1
  220. package/es/components/overlays/NewNotifications/NotificationView/NotificationProvider.js +1 -1
  221. package/es/components/overlays/NewNotifications/NotificationView/NotificationView.js +1 -1
  222. package/es/components/overlays/NewNotifications/NotificationView/index.js +1 -1
  223. package/es/components/overlays/NewNotifications/NotificationView/types.js +1 -1
  224. package/es/components/overlays/NewNotifications/NotificationsContext/NotificationsContext.js +1 -1
  225. package/es/components/overlays/NewNotifications/NotificationsContext/NotificationsProvider.js +1 -1
  226. package/es/components/overlays/NewNotifications/NotificationsContext/index.js +1 -1
  227. package/es/components/overlays/NewNotifications/NotificationsContext/use-notifications.js +1 -1
  228. package/es/components/overlays/NewNotifications/NotificationsList/NotificationsList.js +1 -1
  229. package/es/components/overlays/NewNotifications/NotificationsList/NotificationsListItem.js +1 -1
  230. package/es/components/overlays/NewNotifications/NotificationsList/index.js +1 -1
  231. package/es/components/overlays/NewNotifications/NotificationsList/types.js +1 -1
  232. package/es/components/overlays/NewNotifications/hooks/index.js +1 -1
  233. package/es/components/overlays/NewNotifications/hooks/types.js +1 -1
  234. package/es/components/overlays/NewNotifications/hooks/use-notification-list-item.js +1 -1
  235. package/es/components/overlays/NewNotifications/hooks/use-notifications-api.js +1 -1
  236. package/es/components/overlays/NewNotifications/hooks/use-notifications-list.js +1 -1
  237. package/es/components/overlays/NewNotifications/hooks/use-notifications-observer.js +1 -1
  238. package/es/components/overlays/NewNotifications/index.js +1 -1
  239. package/es/components/overlays/NewNotifications/types.js +1 -1
  240. package/es/components/overlays/Notification/Notification.js +1 -1
  241. package/es/components/overlays/OverlayWrapper.js +1 -1
  242. package/es/components/overlays/Toasts/Toast.js +1 -1
  243. package/es/components/overlays/Toasts/index.js +1 -1
  244. package/es/components/overlays/Toasts/types.js +1 -1
  245. package/es/components/overlays/Toasts/use-toasts-api.js +1 -1
  246. package/es/components/overlays/Tooltip/Tooltip.js +30 -18
  247. package/es/components/overlays/Tooltip/TooltipProvider.js +2 -2
  248. package/es/components/overlays/Tooltip/TooltipTrigger.js +25 -7
  249. package/es/components/overlays/Tooltip/context.js +1 -1
  250. package/es/components/overlays/Tooltip/index.js +1 -1
  251. package/es/components/portal/Portal.js +1 -1
  252. package/es/components/portal/PortalProvider.js +1 -1
  253. package/es/components/portal/index.js +1 -1
  254. package/es/components/portal/types.js +1 -1
  255. package/es/components/portal/usePortal.js +1 -1
  256. package/es/components/shared/InvalidIcon.js +1 -1
  257. package/es/components/shared/ValidIcon.js +1 -1
  258. package/es/components/status/LoadingAnimation/LoadingAnimation.js +1 -1
  259. package/es/components/status/LoadingAnimation/index.js +1 -1
  260. package/es/components/status/Spin/Cube.js +1 -1
  261. package/es/components/status/Spin/InternalSpinner.js +1 -1
  262. package/es/components/status/Spin/Spin.js +1 -1
  263. package/es/components/status/Spin/SpinsContainer.js +1 -1
  264. package/es/components/status/Spin/index.js +1 -1
  265. package/es/components/status/Spin/types.js +1 -1
  266. package/es/components/status/index.js +1 -1
  267. package/es/data/item-themes.js +1 -1
  268. package/es/data/themes.js +1 -1
  269. package/es/icons/AdjustmentsHorizontalIcon.js +1 -1
  270. package/es/icons/AdjustmentsIcon.js +1 -1
  271. package/es/icons/AiIcon.js +1 -1
  272. package/es/icons/AreaChartIcon.js +1 -1
  273. package/es/icons/BackwardIcon.js +1 -1
  274. package/es/icons/BarChartIcon.js +1 -1
  275. package/es/icons/BellFilledIcon.js +1 -1
  276. package/es/icons/BellIcon.js +1 -1
  277. package/es/icons/BooleanIcon.js +1 -1
  278. package/es/icons/CalendarEditIcon.js +1 -1
  279. package/es/icons/CalendarIcon.js +1 -1
  280. package/es/icons/CaretDownIcon.js +1 -1
  281. package/es/icons/CaretUpIcon.js +1 -1
  282. package/es/icons/ChartAreaStackedIcon.js +1 -1
  283. package/es/icons/ChartAreaStackedPercentageIcon.js +1 -1
  284. package/es/icons/ChartBarGroupedHorizontalIcon.js +1 -1
  285. package/es/icons/ChartBarGroupedIcon.js +1 -1
  286. package/es/icons/ChartBarHorizontalIcon.js +1 -1
  287. package/es/icons/ChartBarLineIcon.js +1 -1
  288. package/es/icons/ChartBarStackedHorizontalIcon.js +1 -1
  289. package/es/icons/ChartBarStackedIcon.js +1 -1
  290. package/es/icons/ChartBarStackedPercentageHorizontalIcon.js +1 -1
  291. package/es/icons/ChartBarStackedPercentageIcon.js +1 -1
  292. package/es/icons/ChartBoxPlot2Icon.js +1 -1
  293. package/es/icons/ChartBoxPlotIcon.js +1 -1
  294. package/es/icons/ChartBubbleIcon.js +1 -1
  295. package/es/icons/ChartDonut2Icon.js +1 -1
  296. package/es/icons/ChartFunnelIcon.js +1 -1
  297. package/es/icons/ChartHeatmapIcon.js +1 -1
  298. package/es/icons/ChartKPIIcon.js +1 -1
  299. package/es/icons/ChartPie2Icon.js +1 -1
  300. package/es/icons/ChartScatterIcon.js +1 -1
  301. package/es/icons/CheckCircleFilledIcon.js +1 -1
  302. package/es/icons/CheckCircleIcon.js +1 -1
  303. package/es/icons/CheckIcon.js +1 -1
  304. package/es/icons/CircleFilledIcon.js +1 -1
  305. package/es/icons/ClearIcon.js +1 -1
  306. package/es/icons/CloseCircleFilledIcon.js +1 -1
  307. package/es/icons/CloseCircleIcon.js +1 -1
  308. package/es/icons/CloseIcon.js +1 -1
  309. package/es/icons/CodeIcon.js +1 -1
  310. package/es/icons/CopyIcon.js +1 -1
  311. package/es/icons/CountIcon.js +1 -1
  312. package/es/icons/CubeIcon.js +1 -1
  313. package/es/icons/CubePauseIcon.js +1 -1
  314. package/es/icons/CubePlayIcon.js +1 -1
  315. package/es/icons/CurrencyDollarIcon.js +1 -1
  316. package/es/icons/DangerIcon.js +1 -1
  317. package/es/icons/DashboardIcon.js +1 -1
  318. package/es/icons/DatabaseIcon.js +1 -1
  319. package/es/icons/DecimalDecreaseIcon.js +1 -1
  320. package/es/icons/DecimalIncreaseIcon.js +1 -1
  321. package/es/icons/DirectionIcon.js +1 -1
  322. package/es/icons/DonutIcon.js +1 -1
  323. package/es/icons/DownIcon.js +1 -1
  324. package/es/icons/EditIcon.js +1 -1
  325. package/es/icons/ExclamationCircleFilledIcon.js +1 -1
  326. package/es/icons/ExclamationCircleIcon.js +1 -1
  327. package/es/icons/ExclamationIcon.js +1 -1
  328. package/es/icons/EyeIcon.js +1 -1
  329. package/es/icons/EyeInvisibleIcon.js +1 -1
  330. package/es/icons/FilterIcon.js +1 -1
  331. package/es/icons/FolderFilledIcon.js +1 -1
  332. package/es/icons/FolderIcon.js +1 -1
  333. package/es/icons/FolderOpenFilledIcon.js +1 -1
  334. package/es/icons/FolderOpenIcon.js +1 -1
  335. package/es/icons/ForwardIcon.js +1 -1
  336. package/es/icons/HierarchyIcon.js +1 -1
  337. package/es/icons/Icon.js +1 -1
  338. package/es/icons/InfoCircleIcon.js +1 -1
  339. package/es/icons/InfoIcon.js +1 -1
  340. package/es/icons/KeyIcon.js +1 -1
  341. package/es/icons/LeftIcon.js +1 -1
  342. package/es/icons/LineChartIcon.js +1 -1
  343. package/es/icons/LoadingIcon.js +1 -1
  344. package/es/icons/LockFilledIcon.js +1 -1
  345. package/es/icons/LockIcon.js +1 -1
  346. package/es/icons/MoreIcon.js +1 -1
  347. package/es/icons/NotAllowedIcon.js +1 -1
  348. package/es/icons/Number123Icon.js +1 -1
  349. package/es/icons/NumberIcon.js +1 -1
  350. package/es/icons/PauseCircleFilledIcon.js +1 -1
  351. package/es/icons/PauseCircleIcon.js +1 -1
  352. package/es/icons/PauseIcon.js +1 -1
  353. package/es/icons/PercentageIcon.js +1 -1
  354. package/es/icons/PieChartIcon.js +1 -1
  355. package/es/icons/PlayCircleIcon.js +1 -1
  356. package/es/icons/PlayIcon.js +1 -1
  357. package/es/icons/PlusIcon.js +1 -1
  358. package/es/icons/ReloadIcon.js +1 -1
  359. package/es/icons/ReportIcon.js +1 -1
  360. package/es/icons/ReturnIcon.js +1 -1
  361. package/es/icons/RightIcon.js +1 -1
  362. package/es/icons/SchemeIcon.js +1 -1
  363. package/es/icons/SearchIcon.js +1 -1
  364. package/es/icons/SettingsIcon.js +1 -1
  365. package/es/icons/ShieldFilledIcon.js +1 -1
  366. package/es/icons/ShieldIcon.js +1 -1
  367. package/es/icons/SlashIcon.js +1 -1
  368. package/es/icons/SparklesIcon.js +1 -1
  369. package/es/icons/SqlIcon.js +1 -1
  370. package/es/icons/StatsIcon.js +1 -1
  371. package/es/icons/StopIcon.js +1 -1
  372. package/es/icons/StringIcon.js +1 -1
  373. package/es/icons/SwitchIcon.js +1 -1
  374. package/es/icons/TableIcon.js +1 -1
  375. package/es/icons/ThumbsDownIcon.js +1 -1
  376. package/es/icons/ThumbsUpIcon.js +1 -1
  377. package/es/icons/ThunderboltCrossedIcon.js +1 -1
  378. package/es/icons/ThunderboltFilledIcon.js +1 -1
  379. package/es/icons/ThunderboltIcon.js +1 -1
  380. package/es/icons/TimeIcon.js +1 -1
  381. package/es/icons/UnlockIcon.js +1 -1
  382. package/es/icons/UpIcon.js +1 -1
  383. package/es/icons/UserGroupIcon.js +1 -1
  384. package/es/icons/UserIcon.js +1 -1
  385. package/es/icons/UserLockIcon.js +1 -1
  386. package/es/icons/ViewIcon.js +1 -1
  387. package/es/icons/WarningFilledIcon.js +1 -1
  388. package/es/icons/WarningIcon.js +1 -1
  389. package/es/icons/add-new-icon.js +1 -1
  390. package/es/icons/index.js +1 -1
  391. package/es/icons/wrap-icon.js +1 -1
  392. package/es/index.js +2 -1
  393. package/es/provider.js +1 -1
  394. package/es/providers/TrackingProvider.js +1 -1
  395. package/es/providers/navigation.types.js +1 -1
  396. package/es/providers/navigationAdapter.default.js +1 -1
  397. package/es/services/notification.js +1 -1
  398. package/es/shared/form.js +1 -1
  399. package/es/shared/index.js +1 -1
  400. package/es/stories/Form.legacy-stories.js +1 -1
  401. package/es/stories/FormFieldArgs.js +1 -1
  402. package/es/stories/Layout.stories.js +1 -1
  403. package/es/stories/Tasty.stories.js +1 -1
  404. package/es/stories/components/ConfirmDeletionDialogForm.js +1 -1
  405. package/es/stories/components/DialogFormApp.js +1 -1
  406. package/es/stories/components/StyledButton.js +1 -1
  407. package/es/stories/lists/baseProps.js +1 -1
  408. package/es/tasty/debug.js +1 -1
  409. package/es/tasty/index.js +1 -1
  410. package/es/tasty/injector/index.js +1 -1
  411. package/es/tasty/injector/injector.js +1 -1
  412. package/es/tasty/injector/sheet-manager.js +1 -1
  413. package/es/tasty/injector/types.js +1 -1
  414. package/es/tasty/parser/classify.js +1 -1
  415. package/es/tasty/parser/const.js +1 -1
  416. package/es/tasty/parser/lru.js +1 -1
  417. package/es/tasty/parser/parser.js +1 -1
  418. package/es/tasty/parser/tokenizer.js +1 -1
  419. package/es/tasty/parser/types.js +1 -1
  420. package/es/tasty/providers/BreakpointsProvider.js +1 -1
  421. package/es/tasty/styles/align.js +1 -1
  422. package/es/tasty/styles/border.js +1 -1
  423. package/es/tasty/styles/boxShadow.combinator.js +1 -1
  424. package/es/tasty/styles/color.js +1 -1
  425. package/es/tasty/styles/createStyle.js +1 -1
  426. package/es/tasty/styles/dimension.js +1 -1
  427. package/es/tasty/styles/display.js +1 -1
  428. package/es/tasty/styles/fade.js +1 -1
  429. package/es/tasty/styles/fill.js +1 -1
  430. package/es/tasty/styles/flow.js +1 -1
  431. package/es/tasty/styles/font.js +1 -1
  432. package/es/tasty/styles/fontStyle.js +1 -1
  433. package/es/tasty/styles/gap.js +1 -1
  434. package/es/tasty/styles/groupRadius.js +1 -1
  435. package/es/tasty/styles/height.js +1 -1
  436. package/es/tasty/styles/index.js +1 -1
  437. package/es/tasty/styles/inset.js +1 -1
  438. package/es/tasty/styles/justify.js +1 -1
  439. package/es/tasty/styles/list.js +1 -1
  440. package/es/tasty/styles/margin.js +1 -1
  441. package/es/tasty/styles/outline.js +1 -1
  442. package/es/tasty/styles/padding.js +1 -1
  443. package/es/tasty/styles/place.js +1 -1
  444. package/es/tasty/styles/predefined.js +1 -1
  445. package/es/tasty/styles/preset.js +1 -1
  446. package/es/tasty/styles/radius.js +1 -1
  447. package/es/tasty/styles/reset.js +1 -1
  448. package/es/tasty/styles/scrollbar.js +1 -1
  449. package/es/tasty/styles/shadow.js +1 -1
  450. package/es/tasty/styles/styledScrollbar.js +1 -1
  451. package/es/tasty/styles/transition.js +1 -1
  452. package/es/tasty/styles/types.js +1 -1
  453. package/es/tasty/styles/width.js +1 -1
  454. package/es/tasty/tasty.js +1 -1
  455. package/es/tasty/types.js +1 -1
  456. package/es/tasty/utils/cache-wrapper.js +1 -1
  457. package/es/tasty/utils/case-converter.js +1 -1
  458. package/es/tasty/utils/colors.js +1 -1
  459. package/es/tasty/utils/dotize.js +1 -1
  460. package/es/tasty/utils/filterBaseProps.js +1 -1
  461. package/es/tasty/utils/getDisplayName.js +1 -1
  462. package/es/tasty/utils/getModCombinations.js +1 -1
  463. package/es/tasty/utils/isDevEnv.js +1 -1
  464. package/es/tasty/utils/mergeStyles.js +1 -1
  465. package/es/tasty/utils/modAttrs.js +1 -1
  466. package/es/tasty/utils/renderStyles.js +1 -1
  467. package/es/tasty/utils/responsive.js +1 -1
  468. package/es/tasty/utils/string.js +1 -1
  469. package/es/tasty/utils/styles.js +1 -1
  470. package/es/tasty/utils/warnings.js +1 -1
  471. package/es/tokens.js +1 -1
  472. package/es/type-checks.js +1 -1
  473. package/es/utils/ResizeSensor.js +1 -1
  474. package/es/utils/modules.js +1 -1
  475. package/es/utils/promise.js +1 -1
  476. package/es/utils/random.js +1 -1
  477. package/es/utils/range.js +1 -1
  478. package/es/utils/react/Slots.js +1 -1
  479. package/es/utils/react/chain.js +1 -1
  480. package/es/utils/react/forwardRefWithGenerics.js +1 -1
  481. package/es/utils/react/index.js +2 -2
  482. package/es/utils/react/interactions.js +1 -1
  483. package/es/utils/react/isTextOnly.js +1 -1
  484. package/es/utils/react/mapProps.js +1 -1
  485. package/es/utils/react/mergeProps.js +1 -1
  486. package/es/utils/react/nullableValue.js +1 -1
  487. package/es/utils/react/sharedStore.js +1 -1
  488. package/es/utils/react/useCombinedRefs.js +11 -6
  489. package/es/utils/react/useControlledFocusVisible.js +1 -1
  490. package/es/utils/react/useEventBus.js +1 -1
  491. package/es/utils/react/useId.js +1 -1
  492. package/es/utils/react/useIsDarwin.js +1 -1
  493. package/es/utils/react/useKeySymbols.js +1 -1
  494. package/es/utils/react/useLayoutEffect.js +1 -1
  495. package/es/utils/react/useQaProps.js +1 -1
  496. package/es/utils/react/useViewportSize.js +1 -1
  497. package/es/utils/react/wrapNodeIfPlain.js +1 -1
  498. package/es/utils/transitions.js +1 -1
  499. package/es/utils/tree.js +1 -1
  500. package/es/utils/warnings.js +1 -1
  501. package/es/version.js +2 -2
  502. package/package.json +1 -1
  503. package/types/components/GridProvider.d.ts +1 -1
  504. package/types/components/fields/ComboBox/ComboBox.d.ts +91 -30
  505. package/types/components/fields/ComboBox/index.d.ts +2 -1
  506. package/types/components/fields/FilterListBox/FilterListBox.d.ts +7 -0
  507. package/types/components/fields/FilterPicker/FilterPicker.d.ts +9 -2
  508. package/types/components/fields/LegacyComboBox/LegacyComboBox.d.ts +49 -0
  509. package/types/components/fields/LegacyComboBox/index.d.ts +1 -0
  510. package/types/components/fields/ListBox/ListBox.d.ts +5 -0
  511. package/types/components/fields/Select/Select.d.ts +2 -1
  512. package/types/components/fields/index.d.ts +1 -0
  513. package/types/components/helpers/DisplayTransition/DisplayTransition.d.ts +24 -0
  514. package/types/components/helpers/index.d.ts +1 -0
  515. package/types/components/layout/Prefix.d.ts +1 -1
  516. package/types/components/layout/Suffix.d.ts +1 -1
  517. package/types/components/overlays/Tooltip/TooltipTrigger.d.ts +5 -0
  518. package/types/components/overlays/Tooltip/context.d.ts +6 -1
  519. package/types/index.d.ts +2 -0
  520. package/types/utils/react/index.d.ts +1 -1
  521. package/types/utils/react/useCombinedRefs.d.ts +3 -2
@@ -1,16 +1,16 @@
1
1
  /**
2
2
  * @license MIT
3
3
  * author: Cube Dev Team
4
- * @cube-dev/ui-kit v0.0.0-canary-ebc4edb
4
+ * @cube-dev/ui-kit v0.0.0-canary-586c588
5
5
  * Released under the MIT license.
6
6
  */
7
7
 
8
8
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
9
- import { cloneElement, forwardRef, useEffect, useMemo, } from 'react';
10
- import { useButton, useComboBox, useFilter, useHover, useOverlayPosition, } from 'react-aria';
11
- import { Section as BaseSection, useComboBoxState } from 'react-stately';
12
- import { useEvent } from '../../../_internal/index';
13
- import { CloseIcon, DownIcon, LoadingIcon } from '../../../icons';
9
+ import React, { cloneElement, forwardRef, useCallback, useEffect, useId, useMemo, useRef, useState, } from 'react';
10
+ import { useFilter, useKeyboard, useOverlay, useOverlayPosition, } from 'react-aria';
11
+ import { Section as BaseSection, Item } from 'react-stately';
12
+ import { useEvent } from '../../../_internal';
13
+ import { CloseIcon, DirectionIcon, LoadingIcon } from '../../../icons';
14
14
  import { useProviderProps } from '../../../provider';
15
15
  import { BASE_STYLES, COLOR_STYLES, extractStyles, OUTER_STYLES, tasty, } from '../../../tasty';
16
16
  import { generateRandomId } from '../../../utils/random';
@@ -19,12 +19,11 @@ import { useFocus } from '../../../utils/react/interactions';
19
19
  import { useEventBus } from '../../../utils/react/useEventBus';
20
20
  import { ItemAction } from '../../actions';
21
21
  import { useFieldProps, useFormProps, wrapWithField } from '../../form';
22
- import { Item } from '../../Item';
23
- import { OverlayWrapper } from '../../overlays/OverlayWrapper';
22
+ import { DisplayTransition } from '../../helpers';
24
23
  import { InvalidIcon } from '../../shared/InvalidIcon';
25
24
  import { ValidIcon } from '../../shared/ValidIcon';
26
- import { DEFAULT_INPUT_STYLES, INPUT_WRAPPER_STYLES } from '../index';
27
- import { ListBoxPopup } from '../Select';
25
+ import { ListBox } from '../ListBox/ListBox';
26
+ import { DEFAULT_INPUT_STYLES, INPUT_WRAPPER_STYLES, } from '../TextInput/TextInputBase';
28
27
  const ComboBoxWrapperElement = tasty({
29
28
  styles: INPUT_WRAPPER_STYLES,
30
29
  });
@@ -32,91 +31,384 @@ const InputElement = tasty({
32
31
  as: 'input',
33
32
  styles: DEFAULT_INPUT_STYLES,
34
33
  });
35
- const TriggerElement = tasty({
36
- as: 'button',
37
- type: 'neutral',
34
+ const ComboBoxOverlayElement = tasty({
35
+ qa: 'ComboBoxOverlay',
38
36
  styles: {
39
37
  display: 'grid',
40
- placeItems: 'center',
41
- placeContent: 'center',
42
- placeSelf: 'stretch',
43
- radius: '(1r - 1bw) right',
38
+ gridRows: '1sf',
39
+ width: '30x max-content 50vw',
40
+ height: 'initial max-content (50vh - $size)',
41
+ overflow: 'auto',
42
+ background: '#white',
43
+ radius: '1cr',
44
+ shadow: '0 .5x 2x #shadow',
44
45
  padding: '0',
45
- width: '3x',
46
- boxSizing: 'border-box',
47
- color: {
48
- '': '#dark-02',
49
- hovered: '#dark-02',
50
- pressed: '#purple',
51
- disabled: '#dark.30',
46
+ border: '#border',
47
+ hide: {
48
+ '': false,
49
+ hidden: true,
52
50
  },
53
- border: 'left',
54
- reset: 'button',
55
- margin: 0,
56
- fill: {
57
- '': '#dark.0',
58
- hovered: '#dark.04',
59
- pressed: '#purple.10',
60
- disabled: '#clear',
51
+ transition: 'translate $transition ease-out, scale $transition ease-out, theme $transition ease-out',
52
+ translate: {
53
+ '': '0 0',
54
+ 'open & [data-placement="top"]': '0 0',
55
+ '!open & [data-placement="top"]': '0 (10% + 1x)',
56
+ 'open & [data-placement="bottom"]': '0 0',
57
+ '!open & [data-placement="bottom"]': '0 (-10% - 1x)',
58
+ },
59
+ scale: {
60
+ '': '1 1',
61
+ '!open': '1 .9',
62
+ },
63
+ opacity: {
64
+ '': 1,
65
+ '!open': 0.001,
61
66
  },
62
- cursor: 'pointer',
63
67
  },
64
68
  });
65
69
  const PROP_STYLES = [...BASE_STYLES, ...OUTER_STYLES, ...COLOR_STYLES];
70
+ function useComboBoxState({ selectedKey, defaultSelectedKey, inputValue, comboBoxId, }) {
71
+ // Get event bus for menu synchronization
72
+ const { emit, on } = useEventBus();
73
+ // Internal state for uncontrolled mode
74
+ const [internalSelectedKey, setInternalSelectedKey] = useState(defaultSelectedKey ?? null);
75
+ const [internalInputValue, setInternalInputValue] = useState('');
76
+ const isControlledKey = selectedKey !== undefined;
77
+ const isControlledInput = inputValue !== undefined;
78
+ const effectiveSelectedKey = isControlledKey
79
+ ? selectedKey
80
+ : internalSelectedKey;
81
+ const effectiveInputValue = isControlledInput
82
+ ? inputValue
83
+ : internalInputValue;
84
+ // Popover state
85
+ const [isPopoverOpen, setIsPopoverOpen] = useState(false);
86
+ // Listen for other menus opening and close this one if needed
87
+ useEffect(() => {
88
+ const unsubscribe = on('popover:open', (data) => {
89
+ if (data.menuId !== comboBoxId && isPopoverOpen) {
90
+ setIsPopoverOpen(false);
91
+ }
92
+ });
93
+ return unsubscribe;
94
+ }, [on, comboBoxId, isPopoverOpen]);
95
+ // Emit event when this combobox opens
96
+ useEffect(() => {
97
+ if (isPopoverOpen) {
98
+ emit('popover:open', { menuId: comboBoxId });
99
+ }
100
+ }, [isPopoverOpen, emit, comboBoxId]);
101
+ return {
102
+ effectiveSelectedKey,
103
+ effectiveInputValue,
104
+ isPopoverOpen,
105
+ setIsPopoverOpen,
106
+ setInternalSelectedKey,
107
+ setInternalInputValue,
108
+ isControlledKey,
109
+ isControlledInput,
110
+ };
111
+ }
112
+ function useComboBoxFiltering({ children, effectiveInputValue, filter, }) {
113
+ const [isFilterActive, setIsFilterActive] = useState(false);
114
+ const { contains } = useFilter({ sensitivity: 'base' });
115
+ const textFilterFn = useMemo(() => (filter === false ? () => true : filter || contains), [filter, contains]);
116
+ // Filter children based on input value
117
+ const filteredChildren = useMemo(() => {
118
+ const term = effectiveInputValue.trim();
119
+ if (!isFilterActive || !term || !children) {
120
+ return children;
121
+ }
122
+ const nodeMatches = (node) => {
123
+ if (!node?.props)
124
+ return false;
125
+ const textValue = node.props.textValue ||
126
+ (typeof node.props.children === 'string' ? node.props.children : '') ||
127
+ String(node.props.children || '');
128
+ return textFilterFn(textValue, term);
129
+ };
130
+ const filterChildren = (childNodes) => {
131
+ if (!childNodes)
132
+ return null;
133
+ const childArray = Array.isArray(childNodes) ? childNodes : [childNodes];
134
+ const filteredNodes = [];
135
+ childArray.forEach((child) => {
136
+ if (!child || typeof child !== 'object') {
137
+ return;
138
+ }
139
+ if (child.type === BaseSection ||
140
+ child.type?.displayName === 'Section') {
141
+ const sectionChildren = Array.isArray(child.props.children)
142
+ ? child.props.children
143
+ : [child.props.children];
144
+ const filteredSectionChildren = sectionChildren.filter((sectionChild) => {
145
+ return (sectionChild &&
146
+ typeof sectionChild === 'object' &&
147
+ nodeMatches(sectionChild));
148
+ });
149
+ if (filteredSectionChildren.length > 0) {
150
+ filteredNodes.push(cloneElement(child, {
151
+ key: child.key,
152
+ children: filteredSectionChildren,
153
+ }));
154
+ }
155
+ }
156
+ else if (child.type === Item) {
157
+ if (nodeMatches(child)) {
158
+ filteredNodes.push(child);
159
+ }
160
+ }
161
+ else if (nodeMatches(child)) {
162
+ filteredNodes.push(child);
163
+ }
164
+ });
165
+ return filteredNodes;
166
+ };
167
+ return filterChildren(children);
168
+ }, [isFilterActive, children, effectiveInputValue, textFilterFn]);
169
+ return {
170
+ filteredChildren,
171
+ isFilterActive,
172
+ setIsFilterActive,
173
+ };
174
+ }
175
+ function useComboBoxKeyboard({ isPopoverOpen, listStateRef, hasResults, allowsCustomValue, effectiveInputValue, isClearable, onSelectionChange, onClearValue, onOpenPopover, onClosePopover, inputRef, setIsFilterActive, }) {
176
+ const { keyboardProps } = useKeyboard({
177
+ onKeyDown: (e) => {
178
+ if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
179
+ e.preventDefault();
180
+ // Open popover if closed
181
+ if (!isPopoverOpen) {
182
+ // If opening with no filtered results, disable filter to show all items
183
+ if (!hasResults) {
184
+ setIsFilterActive(false);
185
+ }
186
+ onOpenPopover();
187
+ return;
188
+ }
189
+ const listState = listStateRef.current;
190
+ if (!listState)
191
+ return;
192
+ const { selectionManager, collection, disabledKeys } = listState;
193
+ // Helper to collect visible item keys (supports sections)
194
+ const collectVisibleKeys = (nodes, out) => {
195
+ for (const node of nodes) {
196
+ if (node.type === 'item') {
197
+ if (!disabledKeys?.has(node.key)) {
198
+ out.push(node.key);
199
+ }
200
+ }
201
+ else if (node.childNodes) {
202
+ collectVisibleKeys(node.childNodes, out);
203
+ }
204
+ }
205
+ };
206
+ const visibleKeys = [];
207
+ collectVisibleKeys(collection, visibleKeys);
208
+ if (visibleKeys.length === 0)
209
+ return;
210
+ const isArrowDown = e.key === 'ArrowDown';
211
+ const currentKey = selectionManager.focusedKey;
212
+ let nextKey = null;
213
+ if (currentKey == null) {
214
+ nextKey = isArrowDown
215
+ ? visibleKeys[0]
216
+ : visibleKeys[visibleKeys.length - 1];
217
+ }
218
+ else {
219
+ const currentIndex = visibleKeys.indexOf(currentKey);
220
+ if (currentIndex !== -1) {
221
+ const newIndex = currentIndex + (isArrowDown ? 1 : -1);
222
+ if (newIndex >= 0 && newIndex < visibleKeys.length) {
223
+ nextKey = visibleKeys[newIndex];
224
+ }
225
+ }
226
+ else {
227
+ nextKey = isArrowDown
228
+ ? visibleKeys[0]
229
+ : visibleKeys[visibleKeys.length - 1];
230
+ }
231
+ }
232
+ if (nextKey != null) {
233
+ if (listState.lastFocusSourceRef) {
234
+ listState.lastFocusSourceRef.current = 'keyboard';
235
+ }
236
+ selectionManager.setFocusedKey(nextKey);
237
+ }
238
+ }
239
+ else if (e.key === 'Enter') {
240
+ if (!hasResults) {
241
+ e.preventDefault();
242
+ if (allowsCustomValue) {
243
+ const value = effectiveInputValue;
244
+ onSelectionChange(value ?? null);
245
+ }
246
+ else {
247
+ onSelectionChange(null);
248
+ }
249
+ return;
250
+ }
251
+ if (isPopoverOpen) {
252
+ const listState = listStateRef.current;
253
+ if (!listState)
254
+ return;
255
+ const keyToSelect = listState.selectionManager.focusedKey;
256
+ if (keyToSelect != null) {
257
+ e.preventDefault();
258
+ listState.selectionManager.select(keyToSelect, e);
259
+ // Ensure the popover closes even if selection stays the same
260
+ onClosePopover();
261
+ setTimeout(() => inputRef.current?.focus(), 0);
262
+ }
263
+ }
264
+ }
265
+ else if (e.key === 'Escape') {
266
+ if (isPopoverOpen) {
267
+ e.preventDefault();
268
+ onClosePopover();
269
+ inputRef.current?.focus();
270
+ }
271
+ else if (effectiveInputValue && isClearable) {
272
+ e.preventDefault();
273
+ onClearValue();
274
+ }
275
+ }
276
+ else if (e.key === 'Home' || e.key === 'End') {
277
+ if (isPopoverOpen) {
278
+ e.preventDefault();
279
+ const listState = listStateRef.current;
280
+ if (!listState)
281
+ return;
282
+ const { selectionManager, collection, disabledKeys } = listState;
283
+ // Helper to collect visible item keys (supports sections)
284
+ const collectVisibleKeys = (nodes, out) => {
285
+ for (const node of nodes) {
286
+ if (node.type === 'item') {
287
+ if (!disabledKeys?.has(node.key)) {
288
+ out.push(node.key);
289
+ }
290
+ }
291
+ else if (node.childNodes) {
292
+ collectVisibleKeys(node.childNodes, out);
293
+ }
294
+ }
295
+ };
296
+ const visibleKeys = [];
297
+ collectVisibleKeys(collection, visibleKeys);
298
+ if (visibleKeys.length === 0)
299
+ return;
300
+ const targetKey = e.key === 'Home'
301
+ ? visibleKeys[0]
302
+ : visibleKeys[visibleKeys.length - 1];
303
+ if (listState.lastFocusSourceRef) {
304
+ listState.lastFocusSourceRef.current = 'keyboard';
305
+ }
306
+ selectionManager.setFocusedKey(targetKey);
307
+ }
308
+ }
309
+ },
310
+ });
311
+ return { keyboardProps };
312
+ }
313
+ const ComboBoxInput = forwardRef(function ComboBoxInput({ inputRef, id, value, placeholder, isDisabled, isReadOnly, autoFocus, size, mods, inputStyles, keyboardProps, focusProps, onChange, onFocus, isPopoverOpen, hasResults, comboBoxId, listStateRef, isLoading, allowsCustomValue, }, ref) {
314
+ const combinedRef = useCombinedRefs(ref, inputRef);
315
+ return (_jsx(InputElement, { ref: combinedRef, qa: "Input", id: id, type: "text", value: value, placeholder: placeholder, isDisabled: isDisabled, readOnly: isReadOnly, autoFocus: autoFocus, "data-autofocus": autoFocus ? '' : undefined, onChange: onChange, onFocus: onFocus, onBlur: focusProps.onBlur, ...keyboardProps, styles: inputStyles, mods: mods, "data-size": size, role: "combobox", "aria-expanded": isPopoverOpen && hasResults, "aria-haspopup": "listbox", "aria-controls": isPopoverOpen && hasResults
316
+ ? `ComboBoxListBox-${comboBoxId}`
317
+ : undefined, "aria-activedescendant": isPopoverOpen &&
318
+ hasResults &&
319
+ listStateRef.current?.selectionManager.focusedKey != null
320
+ ? `ListBoxItem-${listStateRef.current?.selectionManager.focusedKey}`
321
+ : undefined }));
322
+ });
323
+ function ComboBoxOverlay({ isOpen, triggerRef, popoverRef, listBoxRef, direction, shouldFlip, overlayOffset, comboBoxWidth, comboBoxId, overlayStyles, listBoxStyles, optionStyles, sectionStyles, headingStyles, effectiveSelectedKey, isDisabled, disabledKeys, items, children, listStateRef, onSelectionChange, onClose, label, ariaLabel, }) {
324
+ // Overlay positioning
325
+ const { overlayProps: overlayPositionProps, placement, updatePosition, } = useOverlayPosition({
326
+ targetRef: triggerRef,
327
+ overlayRef: popoverRef,
328
+ placement: `${direction} start`,
329
+ shouldFlip,
330
+ isOpen,
331
+ offset: overlayOffset,
332
+ });
333
+ // Overlay behavior (dismiss on outside click, escape)
334
+ const { overlayProps: overlayBehaviorProps } = useOverlay({
335
+ onClose,
336
+ shouldCloseOnBlur: true,
337
+ isOpen,
338
+ isDismissable: true,
339
+ shouldCloseOnInteractOutside: (el) => {
340
+ const menuTriggerEl = el.closest('[data-popover-trigger]');
341
+ if (!menuTriggerEl)
342
+ return true;
343
+ if (menuTriggerEl === triggerRef?.current)
344
+ return true;
345
+ return false;
346
+ },
347
+ }, popoverRef);
348
+ // Update position when overlay opens
349
+ useLayoutEffect(() => {
350
+ if (isOpen) {
351
+ // Use double RAF to ensure layout is complete before positioning
352
+ requestAnimationFrame(() => {
353
+ requestAnimationFrame(() => {
354
+ updatePosition?.();
355
+ });
356
+ });
357
+ }
358
+ }, [isOpen, updatePosition]);
359
+ // Extract primary placement direction for consistent styling
360
+ const placementDirection = placement?.split(' ')[0] || direction;
361
+ return (_jsx(DisplayTransition, { exposeUnmounted: true, isShown: isOpen, children: ({ phase, isShown, ref: transitionRef }) => (_jsx(ComboBoxOverlayElement, { ...mergeProps(overlayPositionProps, overlayBehaviorProps), ref: (value) => {
362
+ transitionRef(value);
363
+ popoverRef.current = value;
364
+ }, "data-placement": placementDirection, "data-phase": phase, mods: {
365
+ open: isShown,
366
+ hidden: phase === 'unmounted',
367
+ }, styles: overlayStyles, style: {
368
+ minWidth: comboBoxWidth ? `${comboBoxWidth}px` : undefined,
369
+ ...overlayPositionProps.style,
370
+ }, children: _jsx(ListBox, { ref: listBoxRef, focusOnHover: true, disableSelectionToggle: true, id: `ComboBoxListBox-${comboBoxId}`, "aria-label": ariaLabel || (typeof label === 'string' ? label : 'Options'), selectedKey: effectiveSelectedKey, selectionMode: "single", isDisabled: isDisabled, disabledKeys: disabledKeys, shouldUseVirtualFocus: true, items: items, styles: listBoxStyles, optionStyles: optionStyles, sectionStyles: sectionStyles, headingStyles: headingStyles, stateRef: listStateRef, mods: {
371
+ popover: true,
372
+ }, onSelectionChange: onSelectionChange, children: children }) })) }));
373
+ }
374
+ // ============================================================================
375
+ // Main Component: ComboBox
376
+ // ============================================================================
66
377
  export const ComboBox = forwardRef(function ComboBox(props, ref) {
67
378
  props = useProviderProps(props);
68
379
  props = useFormProps(props);
69
380
  props = useFieldProps(props, {
70
381
  valuePropsMapper: ({ value, onChange }) => {
71
382
  return {
72
- selectedKey: !props.allowsCustomValue ? value ?? null : undefined,
73
- inputValue: props.allowsCustomValue ? value ?? '' : undefined,
74
- onInputChange(val) {
75
- if (!props.allowsCustomValue) {
76
- return;
77
- }
78
- onChange(val);
79
- },
383
+ // Form value maps to selectedKey (the committed value) in both modes
384
+ selectedKey: value ?? null,
80
385
  onSelectionChange(val) {
81
- if (val == null && props.allowsCustomValue) {
82
- return;
83
- }
386
+ // Commit selection changes to the form
84
387
  onChange(val);
85
388
  },
86
389
  };
87
390
  },
88
391
  });
89
- let { qa, label, extra, labelStyles, isRequired, necessityIndicator, validationState, icon, prefix, isDisabled, multiLine, autoFocus, wrapperRef, inputRef, triggerRef, popoverRef, listBoxRef, isLoading, loadingIndicator, overlayOffset = 8, inputStyles, optionStyles, triggerStyles, listBoxStyles, overlayStyles, wrapperStyles, suffix, hideTrigger, message, description, size = 'medium', autoComplete = 'off', direction = 'bottom', shouldFlip = true, menuTrigger = 'input', suffixPosition = 'before', loadingState, filter, styles, labelSuffix, selectedKey, defaultSelectedKey, isClearable, ...otherProps } = props;
90
- let isAsync = loadingState != null;
91
- let { contains } = useFilter({ sensitivity: 'base' });
92
- let comboBoxStateProps = {
93
- ...props,
94
- defaultFilter: filter || contains,
95
- filter: undefined,
96
- allowsEmptyCollection: isAsync,
97
- menuTrigger,
98
- };
99
- let state = useComboBoxState(comboBoxStateProps);
392
+ let { qa, label, extra, labelStyles, isRequired, necessityIndicator, validationState, id, icon, prefix, isDisabled, autoFocus, wrapperRef, inputRef, triggerRef, popoverRef, listBoxRef, isLoading, inputStyles, optionStyles, triggerStyles, listBoxStyles, overlayStyles, fieldStyles, suffix, hideTrigger, message, description, size = 'medium', direction = 'bottom', shouldFlip = true, popoverTrigger = 'input', suffixPosition = 'before', filter, styles, labelSuffix, selectedKey, defaultSelectedKey, inputValue, onInputChange, isClearable, onClear, placeholder, allowsCustomValue, shouldCommitOnBlur = true, items, children: renderChildren, sectionStyles, headingStyles, isReadOnly, overlayOffset = 8, onSelectionChange: externalOnSelectionChange, sortSelectedToTop: sortSelectedToTopProp, ...otherProps } = props;
393
+ // Generate ID for label-input linking if not provided
394
+ const generatedId = useId();
395
+ const inputId = id || generatedId;
100
396
  // Generate a unique ID for this combobox instance
101
397
  const comboBoxId = useMemo(() => generateRandomId(), []);
102
- // Get event bus for menu synchronization
103
- const { emit, on } = useEventBus();
104
- // Listen for other menus opening and close this one if needed
105
- useEffect(() => {
106
- const unsubscribe = on('popover:open', (data) => {
107
- // If another menu is opening and this combobox is open, close this one
108
- if (data.menuId !== comboBoxId && state.isOpen) {
109
- state.close();
110
- }
111
- });
112
- return unsubscribe;
113
- }, [on, comboBoxId, state]);
114
- // Emit event when this combobox opens
115
- useEffect(() => {
116
- if (state.isOpen) {
117
- emit('popover:open', { menuId: comboBoxId });
118
- }
119
- }, [state.isOpen, emit, comboBoxId]);
398
+ // State management hook
399
+ const { effectiveSelectedKey, effectiveInputValue, isPopoverOpen, setIsPopoverOpen, setInternalSelectedKey, setInternalInputValue, isControlledKey, isControlledInput, } = useComboBoxState({
400
+ selectedKey,
401
+ defaultSelectedKey,
402
+ inputValue,
403
+ comboBoxId,
404
+ });
405
+ // Track if sortSelectedToTop was explicitly provided
406
+ const sortSelectedToTopExplicit = sortSelectedToTopProp !== undefined;
407
+ // Default to true if items are provided, false otherwise
408
+ const sortSelectedToTop = sortSelectedToTopProp ?? (items ? true : false);
409
+ // Cache for sorted items array when using `items` prop
410
+ const cachedItemsOrder = useRef(null);
411
+ const selectionWhenClosed = useRef(null);
120
412
  styles = extractStyles(otherProps, PROP_STYLES, styles);
121
413
  ref = useCombinedRefs(ref);
122
414
  wrapperRef = useCombinedRefs(wrapperRef);
@@ -124,62 +416,293 @@ export const ComboBox = forwardRef(function ComboBox(props, ref) {
124
416
  triggerRef = useCombinedRefs(triggerRef);
125
417
  popoverRef = useCombinedRefs(popoverRef);
126
418
  listBoxRef = useCombinedRefs(listBoxRef);
127
- let { overlayProps, placement, updatePosition } = useOverlayPosition({
128
- targetRef: triggerRef,
129
- overlayRef: popoverRef,
130
- scrollRef: listBoxRef,
131
- placement: `${direction} end`,
132
- shouldFlip: shouldFlip,
133
- isOpen: state.isOpen,
134
- onClose: state.close,
135
- offset: overlayOffset,
419
+ // Sort items with selected on top if enabled
420
+ const getSortedItems = useCallback(() => {
421
+ if (!items)
422
+ return items;
423
+ if (!sortSelectedToTop)
424
+ return items;
425
+ // Reuse cached order if available
426
+ if (cachedItemsOrder.current) {
427
+ return cachedItemsOrder.current;
428
+ }
429
+ // Warn if explicitly requested but not supported
430
+ if (sortSelectedToTopExplicit && !items) {
431
+ console.warn('ComboBox: sortSelectedToTop only works with the items prop. ' +
432
+ 'Sorting will be skipped when using JSX children.');
433
+ return items;
434
+ }
435
+ const selectedKey = isPopoverOpen
436
+ ? effectiveSelectedKey
437
+ : selectionWhenClosed.current;
438
+ if (!selectedKey)
439
+ return items;
440
+ const itemsArray = Array.isArray(items) ? items : Array.from(items);
441
+ const selectedItem = itemsArray.find((item) => {
442
+ const key = item?.key ?? item?.id;
443
+ return key != null && String(key) === String(selectedKey);
444
+ });
445
+ if (!selectedItem)
446
+ return items;
447
+ const sorted = [
448
+ selectedItem,
449
+ ...itemsArray.filter((item) => {
450
+ const key = item?.key ?? item?.id;
451
+ return key == null || String(key) !== String(selectedKey);
452
+ }),
453
+ ];
454
+ if (isPopoverOpen) {
455
+ cachedItemsOrder.current = sorted;
456
+ }
457
+ return sorted;
458
+ }, [
459
+ items,
460
+ sortSelectedToTop,
461
+ sortSelectedToTopExplicit,
462
+ effectiveSelectedKey,
463
+ isPopoverOpen,
464
+ ]);
465
+ const sortedItems = getSortedItems();
466
+ // Preserve the original `children` (may be a render function) before we
467
+ // potentially overwrite it.
468
+ let children = renderChildren;
469
+ const renderFn = renderChildren;
470
+ if (sortedItems && typeof renderFn === 'function') {
471
+ try {
472
+ const itemsArray = Array.from(sortedItems);
473
+ children = itemsArray.map((item, idx) => {
474
+ const rendered = renderFn(item);
475
+ if (React.isValidElement(rendered) &&
476
+ rendered.key == null) {
477
+ return React.cloneElement(rendered, {
478
+ key: rendered?.key ?? item?.key ?? idx,
479
+ });
480
+ }
481
+ return rendered;
482
+ });
483
+ }
484
+ catch {
485
+ // If conversion fails, proceed with the original children
486
+ }
487
+ }
488
+ // Invalidate cached sorting whenever items change
489
+ useEffect(() => {
490
+ cachedItemsOrder.current = null;
491
+ }, [items]);
492
+ // Capture selection when popover closes
493
+ useEffect(() => {
494
+ if (!isPopoverOpen) {
495
+ selectionWhenClosed.current =
496
+ effectiveSelectedKey != null ? String(effectiveSelectedKey) : null;
497
+ cachedItemsOrder.current = null;
498
+ }
499
+ }, [isPopoverOpen, effectiveSelectedKey]);
500
+ // Filtering hook
501
+ const { filteredChildren, isFilterActive, setIsFilterActive } = useComboBoxFiltering({
502
+ children,
503
+ effectiveInputValue,
504
+ filter,
136
505
  });
137
- let { labelProps, inputProps, listBoxProps, buttonProps: triggerProps, } = useComboBox({
138
- ...comboBoxStateProps,
139
- inputRef,
140
- buttonRef: triggerRef,
141
- listBoxRef,
142
- popoverRef,
143
- menuTrigger,
144
- }, state);
145
- let { isFocused, focusProps } = useFocus({ isDisabled });
146
- let { hoverProps, isHovered } = useHover({ isDisabled });
147
- // Get props for the button based on the trigger props from useComboBox
148
- let { buttonProps, isPressed: isTriggerPressed } = useButton(triggerProps, triggerRef);
149
- let { hoverProps: triggerHoverProps, isHovered: isTriggerHovered } = useHover({ isDisabled });
150
- let { focusProps: triggerFocusProps, isFocused: isTriggerFocused } = useFocus({ isDisabled }, true);
151
- useLayoutEffect(() => {
152
- if (state.isOpen) {
153
- updatePosition();
506
+ // Freeze filtered children during close animation to prevent visual jumps
507
+ const frozenFilteredChildrenRef = useRef(null);
508
+ useEffect(() => {
509
+ // Update frozen children only when popover is open
510
+ if (isPopoverOpen) {
511
+ frozenFilteredChildrenRef.current = filteredChildren;
154
512
  }
155
- }, [state.isOpen, state.collection.size]);
513
+ }, [isPopoverOpen, filteredChildren]);
514
+ // Use frozen children during close animation, fresh children when open
515
+ const displayedFilteredChildren = isPopoverOpen
516
+ ? filteredChildren
517
+ : frozenFilteredChildrenRef.current ?? filteredChildren;
518
+ const { isFocused, focusProps } = useFocus({ isDisabled });
156
519
  let isInvalid = validationState === 'invalid';
157
520
  let validationIcon = isInvalid ? InvalidIcon : ValidIcon;
158
521
  let validation = cloneElement(validationIcon);
522
+ // Ref to access internal ListBox state
523
+ const listStateRef = useRef(null);
524
+ const focusInitAttemptsRef = useRef(0);
525
+ // Helper to get label from collection item
526
+ const getItemLabel = useCallback((key) => {
527
+ const item = listStateRef.current?.collection?.getItem(key);
528
+ return item?.textValue || String(key);
529
+ }, []);
530
+ // Selection change handler
531
+ const handleSelectionChange = useEvent((selection) => {
532
+ // Extract single key from selection (we only support single selection)
533
+ const key = Array.isArray(selection) ? selection[0] : selection;
534
+ // Update selected key
535
+ if (!isControlledKey) {
536
+ setInternalSelectedKey(key ?? null);
537
+ }
538
+ // Update input value to show selected item label
539
+ if (key != null) {
540
+ setIsFilterActive(false);
541
+ const label = getItemLabel(key);
542
+ if (!isControlledInput) {
543
+ setInternalInputValue(label);
544
+ }
545
+ onInputChange?.(label);
546
+ }
547
+ else {
548
+ // Clear input when selection is cleared
549
+ if (!isControlledInput) {
550
+ setInternalInputValue('');
551
+ }
552
+ onInputChange?.('');
553
+ setIsFilterActive(false);
554
+ }
555
+ externalOnSelectionChange?.(key);
556
+ // Close popover after selection
557
+ setIsPopoverOpen(false);
558
+ // Focus input
559
+ setTimeout(() => {
560
+ inputRef.current?.focus();
561
+ }, 0);
562
+ });
563
+ // Input change handler
564
+ const handleInputChange = useEvent((e) => {
565
+ const value = e.target.value;
566
+ // Update input value
567
+ if (!isControlledInput) {
568
+ setInternalInputValue(value);
569
+ }
570
+ onInputChange?.(value);
571
+ const trimmed = value.trim();
572
+ setIsFilterActive(trimmed.length > 0);
573
+ // Only clear selection in allowsCustomValue mode
574
+ // In normal mode, typing just filters - selection stays until explicitly changed
575
+ if (allowsCustomValue && effectiveSelectedKey != null) {
576
+ if (!isControlledKey) {
577
+ setInternalSelectedKey(null);
578
+ }
579
+ externalOnSelectionChange?.(null);
580
+ }
581
+ // Open popover based on trigger
582
+ if (popoverTrigger === 'input' && value && !isPopoverOpen) {
583
+ setIsPopoverOpen(true);
584
+ }
585
+ });
586
+ // Initialize input value from default selected key (uncontrolled mode only, one-time)
587
+ const [hasInitialized, setHasInitialized] = useState(false);
588
+ useEffect(() => {
589
+ // Only initialize once, in uncontrolled input mode, when defaultSelectedKey is provided
590
+ if (hasInitialized || isControlledInput || !defaultSelectedKey)
591
+ return;
592
+ // Wait for collection to be ready
593
+ if (!listStateRef.current?.collection)
594
+ return;
595
+ const label = getItemLabel(defaultSelectedKey);
596
+ setInternalInputValue(label);
597
+ setHasInitialized(true);
598
+ }, [
599
+ hasInitialized,
600
+ isControlledInput,
601
+ defaultSelectedKey,
602
+ getItemLabel,
603
+ children,
604
+ ]);
605
+ // Sync input value with controlled selectedKey
606
+ useEffect(() => {
607
+ // Only run when selectedKey is controlled but inputValue is uncontrolled
608
+ if (!isControlledKey || isControlledInput)
609
+ return;
610
+ // Wait for collection to be ready
611
+ if (!listStateRef.current?.collection)
612
+ return;
613
+ // Get the expected label for the current selection
614
+ const expectedLabel = effectiveSelectedKey != null ? getItemLabel(effectiveSelectedKey) : '';
615
+ // Update the input value to match the selected key's label
616
+ setInternalInputValue(expectedLabel);
617
+ }, [
618
+ isControlledKey,
619
+ isControlledInput,
620
+ effectiveSelectedKey,
621
+ getItemLabel,
622
+ children,
623
+ ]);
624
+ // Input focus handler
625
+ const handleInputFocus = useEvent((e) => {
626
+ // Call focus props handler if it exists
627
+ focusProps.onFocus?.(e);
628
+ if (popoverTrigger === 'focus' && !isPopoverOpen) {
629
+ setIsPopoverOpen(true);
630
+ }
631
+ });
632
+ // Input blur handler
633
+ const handleInputBlur = useEvent((e) => {
634
+ focusProps.onBlur?.(e);
635
+ const relatedTarget = e.relatedTarget;
636
+ // Don't do anything if focus is moving within the combobox
637
+ if (relatedTarget &&
638
+ (wrapperRef.current?.contains(relatedTarget) ||
639
+ popoverRef.current?.contains(relatedTarget))) {
640
+ return;
641
+ }
642
+ // Always disable filter on blur
643
+ setIsFilterActive(false);
644
+ // In allowsCustomValue mode with shouldCommitOnBlur, commit the input value
645
+ if (allowsCustomValue &&
646
+ shouldCommitOnBlur &&
647
+ effectiveInputValue &&
648
+ effectiveSelectedKey == null) {
649
+ externalOnSelectionChange?.(effectiveInputValue);
650
+ if (!isControlledKey) {
651
+ setInternalSelectedKey(effectiveInputValue);
652
+ }
653
+ return;
654
+ }
655
+ // Reset input to show current selection (or empty if none)
656
+ const nextValue = effectiveSelectedKey != null ? getItemLabel(effectiveSelectedKey) : '';
657
+ if (!isControlledInput) {
658
+ setInternalInputValue(nextValue);
659
+ }
660
+ onInputChange?.(nextValue);
661
+ });
159
662
  // Clear button logic
160
- let hasValue = props.allowsCustomValue
161
- ? state.inputValue !== ''
162
- : state.selectedKey != null;
163
- let showClearButton = isClearable && hasValue && !isDisabled && !props.isReadOnly;
663
+ let hasValue = allowsCustomValue
664
+ ? effectiveInputValue !== ''
665
+ : effectiveSelectedKey != null;
666
+ let showClearButton = isClearable && hasValue && !isDisabled && !isReadOnly;
667
+ const hasResults = Boolean(displayedFilteredChildren &&
668
+ (Array.isArray(displayedFilteredChildren)
669
+ ? displayedFilteredChildren.length > 0
670
+ : displayedFilteredChildren !== null));
164
671
  // Clear function
165
672
  let clearValue = useEvent(() => {
166
- // Always clear input value in state so UI resets to placeholder
167
- state.setInputValue('');
168
- // Notify external input value only when custom value mode is enabled
169
- if (props.allowsCustomValue) {
170
- props.onInputChange?.('');
673
+ // Clear input
674
+ if (!isControlledInput) {
675
+ setInternalInputValue('');
171
676
  }
172
- props.onSelectionChange?.(null);
173
- state.setSelectedKey(null);
174
- // Close the popup if it's open
175
- if (state.isOpen) {
176
- state.close();
677
+ onInputChange?.('');
678
+ // Clear selection
679
+ if (!isControlledKey) {
680
+ setInternalSelectedKey(null);
177
681
  }
178
- // Focus back to the input
682
+ externalOnSelectionChange?.(null);
683
+ // Close popover
684
+ if (isPopoverOpen) {
685
+ setIsPopoverOpen(false);
686
+ }
687
+ // Focus input
179
688
  inputRef.current?.focus();
180
- props.onClear?.();
689
+ onClear?.();
690
+ });
691
+ // Keyboard navigation hook
692
+ const { keyboardProps } = useComboBoxKeyboard({
693
+ isPopoverOpen,
694
+ listStateRef,
695
+ hasResults,
696
+ allowsCustomValue,
697
+ effectiveInputValue,
698
+ isClearable,
699
+ onSelectionChange: handleSelectionChange,
700
+ onClearValue: clearValue,
701
+ onOpenPopover: () => setIsPopoverOpen(true),
702
+ onClosePopover: () => setIsPopoverOpen(false),
703
+ inputRef,
704
+ setIsFilterActive,
181
705
  });
182
- let comboBoxWidth = wrapperRef?.current?.offsetWidth;
183
706
  if (icon) {
184
707
  icon = _jsx("div", { "data-element": "InputIcon", children: icon });
185
708
  if (prefix) {
@@ -193,7 +716,7 @@ export const ComboBox = forwardRef(function ComboBox(props, ref) {
193
716
  invalid: isInvalid,
194
717
  valid: validationState === 'valid',
195
718
  disabled: isDisabled,
196
- hovered: isHovered,
719
+ hovered: false,
197
720
  focused: isFocused,
198
721
  loading: isLoading,
199
722
  prefix: !!prefix,
@@ -203,84 +726,98 @@ export const ComboBox = forwardRef(function ComboBox(props, ref) {
203
726
  isInvalid,
204
727
  validationState,
205
728
  isDisabled,
206
- isHovered,
207
729
  isFocused,
208
730
  isLoading,
209
731
  prefix,
210
732
  showClearButton,
211
733
  ]);
212
- // If input is not full and the user presses Enter, pick the first option.
213
- let onKeyPress = useEvent((e) => {
214
- if (!props.onSelectionChange) {
215
- return;
734
+ const comboBoxWidth = wrapperRef?.current?.offsetWidth;
735
+ const shouldShowPopover = Boolean(isPopoverOpen && hasResults);
736
+ // Close popover if no results
737
+ useEffect(() => {
738
+ if (isPopoverOpen && !hasResults) {
739
+ setIsPopoverOpen(false);
216
740
  }
217
- if (e.key === 'Enter') {
218
- if (!props.allowsCustomValue) {
219
- if (state.isOpen) {
220
- // If there is a selected option then do nothing. It will be selected on Enter anyway.
221
- if (listBoxRef.current?.querySelector('li[aria-selected="true"]')) {
222
- return;
223
- }
224
- const option = [...state.collection][0]?.key;
225
- if (option && selectedKey !== option) {
226
- props.onSelectionChange?.(option);
227
- e.stopPropagation();
228
- e.preventDefault();
229
- }
741
+ }, [isPopoverOpen, hasResults]);
742
+ const ensureInitialFocus = useCallback(() => {
743
+ if (!shouldShowPopover)
744
+ return;
745
+ const listState = listStateRef.current;
746
+ if (!listState)
747
+ return;
748
+ const { selectionManager, collection, disabledKeys, lastFocusSourceRef } = listState;
749
+ if (!selectionManager || !collection)
750
+ return;
751
+ const collectFirstKey = () => {
752
+ for (const node of collection) {
753
+ if (node.type === 'item') {
754
+ if (!disabledKeys?.has(node.key))
755
+ return node.key;
230
756
  }
231
- else if (inputRef.current?.value &&
232
- ![...state.collection]
233
- .map((i) => i.textValue)
234
- .includes(inputRef.current?.value)) {
235
- // If the input value is not in the collection, we need to prevent the submitting of the form.
236
- // Also, we reset value manually.
237
- e.preventDefault();
238
- props.onSelectionChange?.(null);
757
+ else if (node.childNodes) {
758
+ for (const child of node.childNodes) {
759
+ if (child.type === 'item' && !disabledKeys?.has(child.key)) {
760
+ return child.key;
761
+ }
762
+ }
239
763
  }
240
- // If a custom value is allowed, we need to check if the input value is in the collection.
241
- }
242
- else if (props.allowsCustomValue) {
243
- const inputValue = inputRef?.current?.value;
244
- const item = [...state.collection].find((item) => item.textValue.toLowerCase() === inputValue?.toLowerCase());
245
- props.onSelectionChange?.(item ? item.key : inputRef?.current?.value ?? '');
246
764
  }
765
+ return null;
766
+ };
767
+ if (lastFocusSourceRef)
768
+ lastFocusSourceRef.current = 'keyboard';
769
+ if (selectionManager.focusedKey == null) {
770
+ const keyToFocus = effectiveSelectedKey != null ? effectiveSelectedKey : collectFirstKey();
771
+ if (keyToFocus != null)
772
+ selectionManager.setFocusedKey(keyToFocus);
247
773
  }
248
- });
249
- let onBlur = useEvent((e) => {
250
- // If the input value is not in the collection, we need to reset the value.
251
- if (!props.allowsCustomValue &&
252
- inputRef.current?.value &&
253
- ![...state.collection]
254
- .map((i) => i.textValue)
255
- .includes(inputRef.current?.value)) {
256
- props.onSelectionChange?.(null);
257
- }
258
- });
259
- useEffect(() => {
260
- inputRef.current?.addEventListener('keydown', onKeyPress, true);
261
- inputRef.current?.addEventListener('blur', onBlur, true);
262
- return () => {
263
- inputRef.current?.removeEventListener('keydown', onKeyPress, true);
264
- inputRef.current?.removeEventListener('blur', onBlur, true);
774
+ }, [shouldShowPopover, effectiveSelectedKey]);
775
+ useLayoutEffect(() => {
776
+ if (!shouldShowPopover)
777
+ return;
778
+ focusInitAttemptsRef.current = 0;
779
+ const tick = () => {
780
+ if (!shouldShowPopover)
781
+ return;
782
+ ensureInitialFocus();
783
+ focusInitAttemptsRef.current += 1;
784
+ // Try a few frames to wait for collection to mount
785
+ if (focusInitAttemptsRef.current < 8 &&
786
+ listStateRef.current?.selectionManager?.focusedKey == null) {
787
+ requestAnimationFrame(tick);
788
+ }
265
789
  };
266
- }, []);
267
- let allInputProps = useMemo(() => mergeProps(inputProps, hoverProps, focusProps), [inputProps, hoverProps, focusProps]);
268
- let comboBoxField = (_jsxs(ComboBoxWrapperElement, { ref: wrapperRef, qa: qa || 'ComboBox', mods: mods, styles: wrapperStyles, style: {
790
+ requestAnimationFrame(() => requestAnimationFrame(tick));
791
+ }, [shouldShowPopover, ensureInitialFocus]);
792
+ const comboBoxField = (_jsxs(ComboBoxWrapperElement, { ref: wrapperRef, qa: qa || 'ComboBox', mods: mods, styles: styles, style: {
269
793
  zIndex: isFocused ? 1 : 'initial',
270
- }, "data-size": size, children: [prefix ? _jsx("div", { "data-element": "Prefix", children: prefix }) : null, _jsx(InputElement, { ref: inputRef, qa: "Input", autoFocus: autoFocus, "data-autofocus": autoFocus ? '' : undefined, ...allInputProps, autoComplete: autoComplete, styles: inputStyles, mods: mods, "data-size": size }), _jsxs("div", { "data-element": "Suffix", children: [suffixPosition === 'before' ? suffix : null, validationState || isLoading ? (_jsxs(_Fragment, { children: [validationState && !isLoading ? validation : null, isLoading ? _jsx(LoadingIcon, {}) : null] })) : null, suffixPosition === 'after' ? suffix : null, showClearButton && (_jsx(ItemAction, { icon: _jsx(CloseIcon, {}), size: size, theme: validationState === 'invalid' ? 'danger' : undefined, qa: "ComboBoxClearButton", "data-no-trigger": hideTrigger ? '' : undefined, onPress: clearValue })), !hideTrigger ? (_jsx(TriggerElement, { "data-popover-trigger": true, qa: "ComboBoxTrigger", ...mergeProps(buttonProps, triggerFocusProps, triggerHoverProps), ref: triggerRef, mods: {
271
- pressed: isTriggerPressed,
272
- focused: isTriggerFocused,
273
- hovered: isTriggerHovered,
794
+ }, "data-size": size, children: [prefix ? _jsx("div", { "data-element": "Prefix", children: prefix }) : null, _jsx(ComboBoxInput, { inputRef: inputRef, id: inputId, value: effectiveInputValue, placeholder: placeholder, isDisabled: isDisabled, isReadOnly: isReadOnly, autoFocus: autoFocus, size: size, mods: mods, inputStyles: inputStyles, keyboardProps: keyboardProps, focusProps: { ...focusProps, onBlur: handleInputBlur }, isPopoverOpen: isPopoverOpen, hasResults: hasResults, comboBoxId: comboBoxId, listStateRef: listStateRef, isLoading: isLoading, allowsCustomValue: allowsCustomValue, onChange: handleInputChange, onFocus: handleInputFocus }), _jsxs("div", { "data-element": "Suffix", children: [suffixPosition === 'before' ? suffix : null, validationState || isLoading ? (_jsxs(_Fragment, { children: [validationState && !isLoading ? validation : null, isLoading ? _jsx(LoadingIcon, {}) : null] })) : null, suffixPosition === 'after' ? suffix : null, showClearButton && (_jsx(ItemAction, { icon: _jsx(CloseIcon, {}), size: size, theme: validationState === 'invalid' ? 'danger' : undefined, qa: "ComboBoxClearButton", "data-no-trigger": hideTrigger ? '' : undefined, onPress: clearValue })), !hideTrigger ? (_jsx(ItemAction, { ref: triggerRef, "data-popover-trigger": true, icon: _jsx(DirectionIcon, { to: isPopoverOpen ? 'up' : 'down' }), qa: "ComboBoxTrigger", mods: {
795
+ pressed: isPopoverOpen,
274
796
  disabled: isDisabled,
275
797
  loading: isLoading,
276
- }, "data-size": size, isDisabled: isDisabled, styles: triggerStyles, children: _jsx(DownIcon, {}) })) : null] }), _jsx(OverlayWrapper, { isOpen: state.isOpen && !isDisabled, children: _jsx(ListBoxPopup, { ...listBoxProps, shouldUseVirtualFocus: true, listBoxRef: listBoxRef, popoverRef: popoverRef, overlayProps: overlayProps, placement: placement, state: state, listBoxStyles: listBoxStyles, overlayStyles: overlayStyles, optionStyles: optionStyles, minWidth: comboBoxWidth, triggerRef: triggerRef }) })] }));
277
- return wrapWithField(comboBoxField, ref, mergeProps({ ...props, styles }, { labelProps }));
278
- });
279
- const ComboBoxSectionComponent = Object.assign(BaseSection, {
280
- displayName: 'Section',
798
+ }, "data-size": size, isDisabled: isDisabled, styles: triggerStyles, onClick: () => {
799
+ if (!isDisabled) {
800
+ const willOpen = !isPopoverOpen;
801
+ setIsPopoverOpen(willOpen);
802
+ if (willOpen) {
803
+ inputRef.current?.focus();
804
+ // If opening with no filtered results, disable filter to show all items
805
+ if (!hasResults) {
806
+ setIsFilterActive(false);
807
+ }
808
+ }
809
+ }
810
+ } })) : null] }), _jsx(ComboBoxOverlay, { isOpen: shouldShowPopover, triggerRef: wrapperRef, popoverRef: popoverRef, listBoxRef: listBoxRef, direction: direction, shouldFlip: shouldFlip, overlayOffset: overlayOffset, comboBoxWidth: comboBoxWidth, comboBoxId: comboBoxId, overlayStyles: overlayStyles, listBoxStyles: listBoxStyles, optionStyles: optionStyles, sectionStyles: sectionStyles, headingStyles: headingStyles, effectiveSelectedKey: effectiveSelectedKey, isDisabled: isDisabled, disabledKeys: props.disabledKeys, items: sortedItems, listStateRef: listStateRef, label: label, ariaLabel: props['aria-label'], onSelectionChange: handleSelectionChange, onClose: () => setIsPopoverOpen(false), children: displayedFilteredChildren })] }));
811
+ const { children: _, ...propsWithoutChildren } = props;
812
+ const finalProps = {
813
+ ...propsWithoutChildren,
814
+ styles: fieldStyles,
815
+ labelProps: { ...props.labelProps, for: inputId },
816
+ };
817
+ return wrapWithField(comboBoxField, ref, mergeProps(finalProps, {}));
281
818
  });
282
819
  ComboBox.Item = Item;
283
- ComboBox.Section = ComboBoxSectionComponent;
820
+ ComboBox.Section = BaseSection;
284
821
  Object.defineProperty(ComboBox, 'cubeInputType', {
285
822
  value: 'ComboBox',
286
823
  enumerable: false,