pixelize-design-library 2.4.2-beta.65 → 2.4.2-beta.67

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 (489) hide show
  1. package/CHANGELOG.md +447 -13
  2. package/COMPONENT-GOTCHAS.md +150 -91
  3. package/DESIGN-GUIDE.md +47 -7
  4. package/README.md +37 -3
  5. package/dist/Components/Accordion/Accordion.js +11 -8
  6. package/dist/Components/Accordion/AccordionProps.d.ts +4 -0
  7. package/dist/Components/Accordion/accordionColors.js +1 -2
  8. package/dist/Components/Apexcharts/ApexLineChart/ApexLineChart.js +1 -0
  9. package/dist/Components/Apexcharts/ApexLineChart/ApexLineChartProps.d.ts +2 -2
  10. package/dist/Components/Apexcharts/ApexPieChart/ApexPieChart.d.ts +1 -1
  11. package/dist/Components/Apexcharts/ApexPieChart/ApexPieChart.js +6 -5
  12. package/dist/Components/Apexcharts/ApexPieChart/ApexPieChartProps.d.ts +3 -1
  13. package/dist/Components/Apexcharts/ApexPieChart/pieImageTexture.d.ts +2 -0
  14. package/dist/Components/Apexcharts/ApexPieChart/pieImageTexture.js +13 -0
  15. package/dist/Components/AppSwitcher/AppSwitcher.js +6 -3
  16. package/dist/Components/AppSwitcher/AppSwitcherProps.d.ts +3 -1
  17. package/dist/Components/AppSwitcher/AppSwitcherProps.js +18 -11
  18. package/dist/Components/AppSwitcher/pixelizeSuite.d.ts +24 -0
  19. package/dist/Components/AppSwitcher/pixelizeSuite.js +71 -0
  20. package/dist/Components/AppearanceSettings/AppearanceSettings.js +3 -3
  21. package/dist/Components/AppearanceSettings/AppearanceSettingsProps.d.ts +2 -2
  22. package/dist/Components/Avatar/avatarColorway.d.ts +2 -2
  23. package/dist/Components/Avatar/avatarColorway.js +7 -6
  24. package/dist/Components/Breadcrumbs/BreadcrumbsProps.d.ts +1 -1
  25. package/dist/Components/Button/Button.styles.js +5 -2
  26. package/dist/Components/Button/ButtonProps.d.ts +2 -4
  27. package/dist/Components/ButtonGroupIcon/ButtonGroupIcon.js +3 -1
  28. package/dist/Components/CalendarGrid/CalendarGrid.js +5 -3
  29. package/dist/Components/CalendarGrid/CalendarGridProps.d.ts +1 -1
  30. package/dist/Components/Card/Card.d.ts +1 -0
  31. package/dist/Components/Card/Card.js +1 -0
  32. package/dist/Components/Checkbox/Checkbox.styles.js +3 -1
  33. package/dist/Components/CheckoutKit/selectable.d.ts +3 -1
  34. package/dist/Components/CheckoutKit/selectable.js +10 -7
  35. package/dist/Components/CheckoutKit/tonalHover.d.ts +2 -0
  36. package/dist/Components/CheckoutKit/tonalHover.js +6 -0
  37. package/dist/Components/ChoiceCard/ChoiceCard.d.ts +1 -1
  38. package/dist/Components/ChoiceCard/ChoiceCard.js +2 -1
  39. package/dist/Components/ChoiceCard/ChoiceCardProps.d.ts +6 -0
  40. package/dist/Components/Common/FieldMessage.d.ts +1 -0
  41. package/dist/Components/Common/FormLabel.d.ts +1 -1
  42. package/dist/Components/Common/FormLabel.js +4 -3
  43. package/dist/Components/Common/HelperText.d.ts +2 -2
  44. package/dist/Components/Common/HelperText.js +1 -2
  45. package/dist/Components/Common/activationKey.d.ts +5 -0
  46. package/dist/Components/Common/activationKey.js +12 -0
  47. package/dist/Components/Common/dataAttributes.d.ts +4 -0
  48. package/dist/Components/Common/fieldMessageStyles.js +2 -1
  49. package/dist/Components/Common/findSlot.d.ts +2 -0
  50. package/dist/Components/Common/findSlot.js +24 -0
  51. package/dist/Components/Common/surfaceFocusRing.d.ts +1 -0
  52. package/dist/Components/Common/surfaceFocusRing.js +7 -0
  53. package/dist/Components/ConfirmDialog/ConfirmDialog.js +17 -5
  54. package/dist/Components/ConfirmDialog/ConfirmDialogProps.d.ts +38 -10
  55. package/dist/Components/CopyButton/CopyButton.d.ts +1 -0
  56. package/dist/Components/CopyButton/CopyButton.js +3 -6
  57. package/dist/Components/CouponField/CouponField.js +5 -2
  58. package/dist/Components/CustomModulesTable/CustomModulesTable.js +3 -1
  59. package/dist/Components/DatePicker/CalendarPanel.d.ts +1 -0
  60. package/dist/Components/DatePicker/CalendarPanel.js +3 -1
  61. package/dist/Components/DatePicker/DatePicker.js +24 -26
  62. package/dist/Components/DatePicker/DatePickerProps.d.ts +8 -0
  63. package/dist/Components/DatePicker/PickerPortal.js +1 -1
  64. package/dist/Components/DatePicker/RangeDatePicker.d.ts +7 -0
  65. package/dist/Components/DatePicker/RangeDatePicker.js +10 -29
  66. package/dist/Components/DatePicker/SingleDatePicker.js +5 -21
  67. package/dist/Components/DatePicker/TimeOnlyPicker.js +2 -20
  68. package/dist/Components/DescriptionList/DescriptionList.js +1 -1
  69. package/dist/Components/DetailSections/DetailSections.js +2 -1
  70. package/dist/Components/Divider/Divider.d.ts +3 -3
  71. package/dist/Components/Divider/Divider.js +3 -3
  72. package/dist/Components/Drawer/Drawer.d.ts +2 -0
  73. package/dist/Components/Drawer/Drawer.js +23 -25
  74. package/dist/Components/Dropdown/DropDown.js +6 -21
  75. package/dist/Components/Editor/Editor.js +6 -2
  76. package/dist/Components/Editor/EditorProps.d.ts +17 -1
  77. package/dist/Components/Editor/editorLabels.js +1 -0
  78. package/dist/Components/Editor/editorTokenStyles.d.ts +8 -0
  79. package/dist/Components/Editor/editorTokenStyles.js +9 -1
  80. package/dist/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.d.ts +1 -1
  81. package/dist/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.js +9 -2
  82. package/dist/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtpProps.d.ts +15 -1
  83. package/dist/Components/EmptyState/EmptyStateProps.d.ts +21 -0
  84. package/dist/Components/EmptyState/FilteredEmptyState.d.ts +5 -0
  85. package/dist/Components/EmptyState/FilteredEmptyState.js +23 -0
  86. package/dist/Components/FieldSelectModal/FieldSelectModal.d.ts +1 -0
  87. package/dist/Components/FilePreview/FilePreview.js +7 -3
  88. package/dist/Components/FilePreview/FilePreviewProps.d.ts +2 -1
  89. package/dist/Components/FileUpload/FileUpload.js +8 -9
  90. package/dist/Components/FileUpload/FileUploadProps.d.ts +2 -2
  91. package/dist/Components/FileUploader/FileUploader.js +5 -6
  92. package/dist/Components/FilterSidebar/FilterSidebar.d.ts +7 -9
  93. package/dist/Components/FilterSidebar/FilterSidebar.js +90 -233
  94. package/dist/Components/FilterSidebar/OptionsSection.d.ts +14 -0
  95. package/dist/Components/FilterSidebar/OptionsSection.js +46 -0
  96. package/dist/Components/FilterSidebar/RangeSection.d.ts +17 -0
  97. package/dist/Components/FilterSidebar/RangeSection.js +80 -0
  98. package/dist/Components/FilterSidebar/SectionHeader.d.ts +13 -0
  99. package/dist/Components/FilterSidebar/SectionHeader.js +29 -0
  100. package/dist/Components/FilterSidebar/useStableCallback.d.ts +1 -0
  101. package/dist/Components/FilterSidebar/useStableCallback.js +12 -0
  102. package/dist/Components/Form/FormWrapper.d.ts +7 -7
  103. package/dist/Components/Form/FormWrapper.js +5 -3
  104. package/dist/Components/FormField/FormField.js +1 -1
  105. package/dist/Components/Header/Header.js +1 -1
  106. package/dist/Components/Header/HeaderActions.js +4 -2
  107. package/dist/Components/IconButton/IconButtonProps.d.ts +2 -1
  108. package/dist/Components/Input/TextInput.js +2 -2
  109. package/dist/Components/Input/TextInputProps.d.ts +3 -1
  110. package/dist/Components/KanbanBoard/AccountCard.js +1 -1
  111. package/dist/Components/KanbanBoard/KanbanBoard.d.ts +1 -1
  112. package/dist/Components/KanbanBoard/KanbanBoard.js +11 -7
  113. package/dist/Components/LauncherTrigger/LauncherTrigger.js +1 -1
  114. package/dist/Components/LazyWrapper/LazyWrapper.d.ts +2 -1
  115. package/dist/Components/LazyWrapper/LazyWrapper.js +1 -1
  116. package/dist/Components/MediaViewer/MediaViewer.js +4 -3
  117. package/dist/Components/MediaViewer/components/MediaAudioPlayer.js +5 -1
  118. package/dist/Components/MediaViewer/components/MediaImageViewer.js +19 -8
  119. package/dist/Components/MediaViewer/components/MediaScrubber.js +7 -2
  120. package/dist/Components/MediaViewer/components/MediaVideoPlayer.js +3 -1
  121. package/dist/Components/MediaViewer/components/ViewerIconButton.js +3 -1
  122. package/dist/Components/MediaViewer/hooks/useFileViewer.d.ts +1 -0
  123. package/dist/Components/MediaViewer/mediaItems.d.ts +1 -0
  124. package/dist/Components/MediaViewer/mediaItems.js +5 -0
  125. package/dist/Components/Modal/Modal.d.ts +1 -0
  126. package/dist/Components/Modal/Modal.js +7 -25
  127. package/dist/Components/Modal/warnDroppedSlotChildren.d.ts +1 -1
  128. package/dist/Components/Modal/warnDroppedSlotChildren.js +7 -3
  129. package/dist/Components/NavLauncher/LauncherTabs.js +2 -1
  130. package/dist/Components/NavLauncher/NavLauncher.js +47 -22
  131. package/dist/Components/NavLauncher/NavLauncherProps.d.ts +6 -4
  132. package/dist/Components/NavLauncher/ScopeBar.js +4 -2
  133. package/dist/Components/NavLauncher/engine/engine.js +2 -1
  134. package/dist/Components/NavLauncher/engine/fold.js +2 -1
  135. package/dist/Components/NavLauncher/launcherMotion.d.ts +19 -0
  136. package/dist/Components/NavLauncher/launcherMotion.js +15 -0
  137. package/dist/Components/NavLauncher/launcherParts.d.ts +12 -0
  138. package/dist/Components/NavLauncher/launcherParts.js +45 -11
  139. package/dist/Components/NavLauncher/searchLayout.d.ts +1 -0
  140. package/dist/Components/NavLauncher/searchLayout.js +3 -1
  141. package/dist/Components/NavLauncher/spotlightParts.d.ts +6 -2
  142. package/dist/Components/NavLauncher/spotlightParts.js +22 -9
  143. package/dist/Components/NavLauncher/useCopiedFlash.d.ts +6 -0
  144. package/dist/Components/NavLauncher/useCopiedFlash.js +21 -0
  145. package/dist/Components/NavigationBar/NavigationBar.js +6 -5
  146. package/dist/Components/NoteTextArea/NoteTextArea.js +12 -17
  147. package/dist/Components/NoteTextArea/NoteTextAreaProps.d.ts +5 -3
  148. package/dist/Components/Notification/Notification.js +19 -21
  149. package/dist/Components/Notification/NotificationProps.d.ts +1 -1
  150. package/dist/Components/NotificationBell/notificationHelpers.d.ts +16 -1
  151. package/dist/Components/NotificationBell/notificationHelpers.js +13 -7
  152. package/dist/Components/OffersList/OffersList.js +4 -2
  153. package/dist/Components/OptionChip/OptionChip.js +3 -2
  154. package/dist/Components/OptionChip/optionInk.js +4 -2
  155. package/dist/Components/OrderStatusTimeline/OrderStatusTimeline.js +2 -1
  156. package/dist/Components/OrgSwitcher/OrgSwitcher.js +13 -6
  157. package/dist/Components/OrgSwitcher/OrgSwitcherProps.d.ts +1 -1
  158. package/dist/Components/OrganizationDetails/OrganizationDetails.js +4 -7
  159. package/dist/Components/OrganizationDetails/OrganizationDetailsProps.d.ts +4 -2
  160. package/dist/Components/PdfViewer/PdfViewer.d.ts +1 -0
  161. package/dist/Components/PlanBadge/PlanBadgeProps.d.ts +1 -1
  162. package/dist/Components/PlanPill/PlanPill.js +4 -2
  163. package/dist/Components/PlanPill/PlanPillProps.d.ts +1 -1
  164. package/dist/Components/ProductCard/ProductCardAction.js +2 -1
  165. package/dist/Components/ProductCard/ProductCardSwatches.js +2 -1
  166. package/dist/Components/ProductDetails/ProductDetails.js +2 -1
  167. package/dist/Components/ProfileCard/ProfileCard.d.ts +1 -0
  168. package/dist/Components/ProfileCard/ProfileCard.js +12 -26
  169. package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +4 -2
  170. package/dist/Components/ProgressBar/ProgressBar.js +2 -1
  171. package/dist/Components/QuantityStepper/QuantityStepper.js +5 -2
  172. package/dist/Components/QueryState/QueryStateBoundary.d.ts +1 -1
  173. package/dist/Components/QueryState/QueryStateBoundary.js +5 -1
  174. package/dist/Components/QueryState/QueryStateProps.d.ts +6 -2
  175. package/dist/Components/RadioButton/RadioButton.js +2 -3
  176. package/dist/Components/RolesPermission/RolesPermission.js +12 -8
  177. package/dist/Components/ScrollToTop/ScrollToTop.d.ts +1 -0
  178. package/dist/Components/ScrollbarBox/ScrollbarBox.d.ts +4 -1
  179. package/dist/Components/ScrollbarBox/ScrollbarBox.js +10 -4
  180. package/dist/Components/SearchSelect/SearchSelect.d.ts +1 -1
  181. package/dist/Components/SearchSelect/SearchSelect.js +8 -5
  182. package/dist/Components/SearchSelect/SearchSelectProps.d.ts +3 -3
  183. package/dist/Components/SegmentedControl/SegmentedControl.d.ts +1 -1
  184. package/dist/Components/SegmentedControl/SegmentedControl.js +1 -1
  185. package/dist/Components/Select/Select.js +6 -0
  186. package/dist/Components/Select/SelectNative.d.ts +16 -0
  187. package/dist/Components/Select/SelectPopup.js +170 -63
  188. package/dist/Components/Select/SelectProps.d.ts +30 -2
  189. package/dist/Components/Select/groupedWindow.d.ts +21 -0
  190. package/dist/Components/Select/groupedWindow.js +50 -0
  191. package/dist/Components/SelectSearch/SelectSearch.d.ts +1 -1
  192. package/dist/Components/SelectSearch/SelectSearch.js +48 -38
  193. package/dist/Components/SelectSearch/SelectSearchProps.d.ts +3 -3
  194. package/dist/Components/SelectV2/SelectV2.d.ts +1 -1
  195. package/dist/Components/SelectV2/SelectV2.js +1 -1
  196. package/dist/Components/SelectV2/SelectV2Props.d.ts +3 -3
  197. package/dist/Components/SideBar/SecondaryBar.js +3 -2
  198. package/dist/Components/SideBar/components/MenuItemBox.js +3 -2
  199. package/dist/Components/SideBar/components/MenuItems.js +1 -1
  200. package/dist/Components/SideBar/components/OtherApps.js +2 -2
  201. package/dist/Components/SideBar/components/PinnedSection.js +1 -1
  202. package/dist/Components/SideBar/sidebarScale.d.ts +2 -2
  203. package/dist/Components/SideBar/sidebarScale.js +2 -2
  204. package/dist/Components/SignInActivityTable/SignInActivityTable.js +7 -2
  205. package/dist/Components/SignInActivityTable/SignInActivityTableProps.d.ts +1 -1
  206. package/dist/Components/SignInActivityTable/scrollRegionRing.d.ts +10 -0
  207. package/dist/Components/SignInActivityTable/scrollRegionRing.js +14 -0
  208. package/dist/Components/Skeletons/SkeletonProps.d.ts +5 -1
  209. package/dist/Components/Slider/Slider.d.ts +2 -0
  210. package/dist/Components/Slider/Slider.js +5 -4
  211. package/dist/Components/StageProgress/StageItem.js +2 -1
  212. package/dist/Components/StageProgress/StageProgress.js +8 -2
  213. package/dist/Components/StageProgress/StageProgressProps.d.ts +2 -0
  214. package/dist/Components/StageProgress/StepperStage.js +2 -1
  215. package/dist/Components/StickyBuyBar/StickyBuyBar.js +2 -1
  216. package/dist/Components/Table/Table.js +5 -3
  217. package/dist/Components/Table/TableProps.d.ts +1 -1
  218. package/dist/Components/Table/components/HeaderActions.js +5 -3
  219. package/dist/Components/Table/components/TableBody.js +22 -8
  220. package/dist/Components/Table/components/TableGroupRow.js +2 -1
  221. package/dist/Components/Table/components/TableHeader.js +14 -20
  222. package/dist/Components/Table/components/rowDetail.js +3 -2
  223. package/dist/Components/Table/components/rowFocusRing.d.ts +21 -0
  224. package/dist/Components/Table/components/rowFocusRing.js +20 -0
  225. package/dist/Components/Table/filters/ActiveFilters.js +6 -3
  226. package/dist/Components/Table/filters/CompactSelect.js +2 -1
  227. package/dist/Components/Table/filters/FilterDatePicker.d.ts +6 -0
  228. package/dist/Components/Table/filters/FilterDatePicker.js +61 -0
  229. package/dist/Components/Table/filters/LeftFilterPane.d.ts +1 -0
  230. package/dist/Components/Table/filters/LeftFilterPane.js +14 -6
  231. package/dist/Components/Table/hooks/useTable.js +11 -7
  232. package/dist/Components/Table/settings/ManageColumns.js +4 -3
  233. package/dist/Components/Table/settings/TableSettings.js +4 -4
  234. package/dist/Components/Tabs/Tabs.d.ts +1 -0
  235. package/dist/Components/Tabs/Tabs.js +1 -0
  236. package/dist/Components/Tabs/components/CountBadge.d.ts +1 -0
  237. package/dist/Components/Tabs/components/TabList.d.ts +1 -0
  238. package/dist/Components/Tabs/components/TabList.js +1 -0
  239. package/dist/Components/Tabs/components/TabPanel.d.ts +1 -0
  240. package/dist/Components/Tabs/components/TabPanel.js +1 -0
  241. package/dist/Components/Tabs/tabStyles.js +4 -2
  242. package/dist/Components/Tag/Tag.js +5 -4
  243. package/dist/Components/Tag/Tag.styles.js +5 -4
  244. package/dist/Components/Tag/TagProps.d.ts +4 -1
  245. package/dist/Components/Tag/tagDot.js +10 -3
  246. package/dist/Components/TagInput/TagInput.js +6 -5
  247. package/dist/Components/TagInput/TagInputProps.d.ts +15 -0
  248. package/dist/Components/TagInput/tagEntries.d.ts +7 -1
  249. package/dist/Components/TagInput/tagEntries.js +18 -5
  250. package/dist/Components/TimePicker/TimePicker.js +7 -3
  251. package/dist/Components/TimePicker/TimePickerProps.d.ts +2 -0
  252. package/dist/Components/Timeline/Timeline.js +13 -9
  253. package/dist/Components/Toaster/Toaster.js +2 -1
  254. package/dist/Components/Toggle/TableToggle.d.ts +1 -1
  255. package/dist/Components/Toggle/TableToggle.js +1 -1
  256. package/dist/Components/UpgradeButton/UpgradeButton.js +3 -2
  257. package/dist/Components/UpgradeButton/UpgradeButtonProps.d.ts +1 -1
  258. package/dist/Components/UserDetails/UserDetails.js +5 -7
  259. package/dist/Components/WishlistToggle/WishlistToggle.js +2 -1
  260. package/dist/Components/WorkspaceWindow/WorkspaceTrayPreview.js +11 -1
  261. package/dist/Components/WorkspaceWindow/WorkspaceWindow.js +3 -1
  262. package/dist/Components/WorkspaceWindow/WorkspaceWindowProps.d.ts +14 -7
  263. package/dist/Hooks/useOutsideMouseDown.d.ts +11 -0
  264. package/dist/Hooks/useOutsideMouseDown.js +30 -0
  265. package/dist/Hooks/usePreferences.js +30 -12
  266. package/dist/Hooks/useScrollableRegion.d.ts +17 -0
  267. package/dist/Hooks/useScrollableRegion.js +36 -0
  268. package/dist/Hooks/useSidebarPrefs.d.ts +1 -0
  269. package/dist/Theme/chakra/Menu.styles.d.ts +4 -0
  270. package/dist/Theme/chakra/Menu.styles.js +6 -0
  271. package/dist/Theme/chakra/componentStyles.d.ts +4 -0
  272. package/dist/Theme/chakra/componentStyles.js +1 -1
  273. package/dist/Theme/chakra/createBrandTheme.d.ts +1 -0
  274. package/dist/Theme/chakra/focusRing.styles.d.ts +1 -1
  275. package/dist/Theme/chakra/focusRing.styles.js +3 -3
  276. package/dist/Theme/chakra/paletteFromTheme.d.ts +2 -1
  277. package/dist/Theme/chakra/paletteFromTheme.js +18 -4
  278. package/dist/Theme/provider/PixelizeThemeProvider.d.ts +1 -0
  279. package/dist/Theme/provider/ThemeSwitcher.d.ts +1 -0
  280. package/dist/Theme/provider/ThemeSwitcher.js +1 -1
  281. package/dist/Theme/testing/testPalette.d.ts +1 -0
  282. package/dist/Theme/tokens/builders/buildDarkPalette.d.ts +1 -0
  283. package/dist/Theme/tokens/builders/filledSurface.js +3 -2
  284. package/dist/Theme/tokens/builders/focusRing.js +4 -1
  285. package/dist/Theme/tokens/builders/paletteScale.d.ts +2 -0
  286. package/dist/Theme/tokens/builders/paletteScale.js +10 -0
  287. package/dist/Theme/tokens/types.d.ts +1 -0
  288. package/dist/Utils/accountHandoff.d.ts +3 -0
  289. package/dist/Utils/price.d.ts +1 -0
  290. package/dist/Utils/tabular.d.ts +30 -0
  291. package/dist/Utils/tabular.js +61 -0
  292. package/dist/esm/Components/Accordion/Accordion.js +11 -8
  293. package/dist/esm/Components/Accordion/accordionColors.js +2 -3
  294. package/dist/esm/Components/Apexcharts/ApexLineChart/ApexLineChart.js +2 -1
  295. package/dist/esm/Components/Apexcharts/ApexPieChart/ApexPieChart.js +6 -5
  296. package/dist/esm/Components/Apexcharts/ApexPieChart/pieImageTexture.js +10 -0
  297. package/dist/esm/Components/AppSwitcher/AppSwitcher.js +6 -3
  298. package/dist/esm/Components/AppSwitcher/AppSwitcherProps.js +18 -11
  299. package/dist/esm/Components/AppSwitcher/pixelizeSuite.js +67 -0
  300. package/dist/esm/Components/AppearanceSettings/AppearanceSettings.js +3 -3
  301. package/dist/esm/Components/Avatar/avatarColorway.js +4 -4
  302. package/dist/esm/Components/Button/Button.styles.js +5 -2
  303. package/dist/esm/Components/ButtonGroupIcon/ButtonGroupIcon.js +3 -1
  304. package/dist/esm/Components/CalendarGrid/CalendarGrid.js +5 -3
  305. package/dist/esm/Components/Card/Card.js +1 -0
  306. package/dist/esm/Components/Checkbox/Checkbox.styles.js +3 -1
  307. package/dist/esm/Components/CheckoutKit/selectable.js +10 -7
  308. package/dist/esm/Components/CheckoutKit/tonalHover.js +2 -0
  309. package/dist/esm/Components/ChoiceCard/ChoiceCard.js +2 -1
  310. package/dist/esm/Components/Common/FormLabel.js +4 -3
  311. package/dist/esm/Components/Common/HelperText.js +1 -2
  312. package/dist/esm/Components/Common/activationKey.js +7 -0
  313. package/dist/esm/Components/Common/fieldMessageStyles.js +2 -1
  314. package/dist/esm/Components/Common/findSlot.js +17 -0
  315. package/dist/esm/Components/Common/surfaceFocusRing.js +3 -0
  316. package/dist/esm/Components/ConfirmDialog/ConfirmDialog.js +18 -6
  317. package/dist/esm/Components/CopyButton/CopyButton.js +3 -6
  318. package/dist/esm/Components/CouponField/CouponField.js +5 -2
  319. package/dist/esm/Components/CustomModulesTable/CustomModulesTable.js +3 -1
  320. package/dist/esm/Components/DatePicker/CalendarPanel.js +3 -1
  321. package/dist/esm/Components/DatePicker/DatePicker.js +25 -27
  322. package/dist/esm/Components/DatePicker/PickerPortal.js +2 -2
  323. package/dist/esm/Components/DatePicker/RangeDatePicker.js +10 -29
  324. package/dist/esm/Components/DatePicker/SingleDatePicker.js +5 -21
  325. package/dist/esm/Components/DatePicker/TimeOnlyPicker.js +2 -20
  326. package/dist/esm/Components/DescriptionList/DescriptionList.js +1 -1
  327. package/dist/esm/Components/DetailSections/DetailSections.js +2 -1
  328. package/dist/esm/Components/Divider/Divider.js +3 -3
  329. package/dist/esm/Components/Drawer/Drawer.js +19 -18
  330. package/dist/esm/Components/Dropdown/DropDown.js +7 -22
  331. package/dist/esm/Components/Editor/Editor.js +7 -3
  332. package/dist/esm/Components/Editor/editorLabels.js +1 -0
  333. package/dist/esm/Components/Editor/editorTokenStyles.js +7 -0
  334. package/dist/esm/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.js +8 -4
  335. package/dist/esm/Components/EmptyState/FilteredEmptyState.js +18 -0
  336. package/dist/esm/Components/FilePreview/FilePreview.js +8 -4
  337. package/dist/esm/Components/FileUpload/FileUpload.js +8 -9
  338. package/dist/esm/Components/FileUploader/FileUploader.js +6 -7
  339. package/dist/esm/Components/FilterSidebar/FilterSidebar.js +94 -237
  340. package/dist/esm/Components/FilterSidebar/OptionsSection.js +41 -0
  341. package/dist/esm/Components/FilterSidebar/RangeSection.js +78 -0
  342. package/dist/esm/Components/FilterSidebar/SectionHeader.js +23 -0
  343. package/dist/esm/Components/FilterSidebar/useStableCallback.js +8 -0
  344. package/dist/esm/Components/Form/FormWrapper.js +5 -3
  345. package/dist/esm/Components/FormField/FormField.js +1 -1
  346. package/dist/esm/Components/Header/Header.js +1 -1
  347. package/dist/esm/Components/Header/HeaderActions.js +6 -4
  348. package/dist/esm/Components/Input/TextInput.js +2 -2
  349. package/dist/esm/Components/KanbanBoard/AccountCard.js +1 -1
  350. package/dist/esm/Components/KanbanBoard/KanbanActions/KanbanActions.js +2 -2
  351. package/dist/esm/Components/KanbanBoard/KanbanBoard.js +11 -7
  352. package/dist/esm/Components/LauncherTrigger/LauncherTrigger.js +1 -1
  353. package/dist/esm/Components/LazyWrapper/LazyWrapper.js +1 -1
  354. package/dist/esm/Components/MediaViewer/MediaViewer.js +5 -4
  355. package/dist/esm/Components/MediaViewer/components/MediaAudioPlayer.js +5 -1
  356. package/dist/esm/Components/MediaViewer/components/MediaImageViewer.js +19 -8
  357. package/dist/esm/Components/MediaViewer/components/MediaScrubber.js +7 -2
  358. package/dist/esm/Components/MediaViewer/components/MediaVideoPlayer.js +3 -1
  359. package/dist/esm/Components/MediaViewer/components/ViewerIconButton.js +3 -1
  360. package/dist/esm/Components/MediaViewer/mediaItems.js +4 -0
  361. package/dist/esm/Components/Modal/Modal.js +2 -17
  362. package/dist/esm/Components/Modal/warnDroppedSlotChildren.js +7 -3
  363. package/dist/esm/Components/NavLauncher/LauncherTabs.js +2 -1
  364. package/dist/esm/Components/NavLauncher/NavLauncher.js +51 -26
  365. package/dist/esm/Components/NavLauncher/ScopeBar.js +4 -2
  366. package/dist/esm/Components/NavLauncher/engine/engine.js +2 -1
  367. package/dist/esm/Components/NavLauncher/engine/fold.js +2 -1
  368. package/dist/esm/Components/NavLauncher/launcherMotion.js +11 -0
  369. package/dist/esm/Components/NavLauncher/launcherParts.js +40 -8
  370. package/dist/esm/Components/NavLauncher/searchLayout.js +1 -0
  371. package/dist/esm/Components/NavLauncher/spotlightParts.js +23 -10
  372. package/dist/esm/Components/NavLauncher/useCopiedFlash.js +17 -0
  373. package/dist/esm/Components/NavigationBar/NavigationBar.js +6 -5
  374. package/dist/esm/Components/NoteTextArea/NoteTextArea.js +12 -17
  375. package/dist/esm/Components/Notification/Notification.js +20 -22
  376. package/dist/esm/Components/NotificationBell/notificationHelpers.js +12 -6
  377. package/dist/esm/Components/OffersList/OffersList.js +4 -2
  378. package/dist/esm/Components/OptionChip/OptionChip.js +3 -2
  379. package/dist/esm/Components/OptionChip/optionInk.js +4 -2
  380. package/dist/esm/Components/OrderStatusTimeline/OrderStatusTimeline.js +2 -1
  381. package/dist/esm/Components/OrgSwitcher/OrgSwitcher.js +14 -7
  382. package/dist/esm/Components/OrganizationDetails/OrganizationDetails.js +5 -8
  383. package/dist/esm/Components/PlanPill/PlanPill.js +4 -2
  384. package/dist/esm/Components/ProductCard/ProductCardAction.js +2 -1
  385. package/dist/esm/Components/ProductCard/ProductCardSwatches.js +2 -1
  386. package/dist/esm/Components/ProductDetails/ProductDetails.js +2 -1
  387. package/dist/esm/Components/ProfileCard/ProfileCard.js +6 -17
  388. package/dist/esm/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +4 -2
  389. package/dist/esm/Components/ProgressBar/ProgressBar.js +2 -1
  390. package/dist/esm/Components/QuantityStepper/QuantityStepper.js +5 -2
  391. package/dist/esm/Components/QueryState/QueryStateBoundary.js +5 -1
  392. package/dist/esm/Components/RadioButton/RadioButton.js +2 -3
  393. package/dist/esm/Components/RolesPermission/RolesPermission.js +12 -8
  394. package/dist/esm/Components/ScrollbarBox/ScrollbarBox.js +9 -3
  395. package/dist/esm/Components/SearchSelect/SearchSelect.js +8 -5
  396. package/dist/esm/Components/SegmentedControl/SegmentedControl.js +1 -1
  397. package/dist/esm/Components/Select/Select.js +6 -0
  398. package/dist/esm/Components/Select/SelectPopup.js +171 -64
  399. package/dist/esm/Components/Select/groupedWindow.js +44 -0
  400. package/dist/esm/Components/SelectSearch/SelectSearch.js +49 -39
  401. package/dist/esm/Components/SelectV2/SelectV2.js +1 -1
  402. package/dist/esm/Components/SideBar/SecondaryBar.js +3 -2
  403. package/dist/esm/Components/SideBar/components/MenuItemBox.js +3 -2
  404. package/dist/esm/Components/SideBar/components/MenuItems.js +1 -1
  405. package/dist/esm/Components/SideBar/components/OtherApps.js +2 -2
  406. package/dist/esm/Components/SideBar/components/PinnedSection.js +1 -1
  407. package/dist/esm/Components/SideBar/sidebarScale.js +2 -2
  408. package/dist/esm/Components/SignInActivityTable/SignInActivityTable.js +8 -3
  409. package/dist/esm/Components/SignInActivityTable/scrollRegionRing.js +9 -0
  410. package/dist/esm/Components/Slider/Slider.js +6 -5
  411. package/dist/esm/Components/StageProgress/StageItem.js +2 -1
  412. package/dist/esm/Components/StageProgress/StageProgress.js +8 -2
  413. package/dist/esm/Components/StageProgress/StepperStage.js +2 -1
  414. package/dist/esm/Components/StickyBuyBar/StickyBuyBar.js +2 -1
  415. package/dist/esm/Components/Table/Table.js +8 -6
  416. package/dist/esm/Components/Table/components/HeaderActions.js +7 -5
  417. package/dist/esm/Components/Table/components/TableBody.js +22 -8
  418. package/dist/esm/Components/Table/components/TableGroupRow.js +2 -1
  419. package/dist/esm/Components/Table/components/TableHeader.js +15 -21
  420. package/dist/esm/Components/Table/components/rowDetail.js +3 -2
  421. package/dist/esm/Components/Table/components/rowFocusRing.js +16 -0
  422. package/dist/esm/Components/Table/filters/ActiveFilters.js +8 -5
  423. package/dist/esm/Components/Table/filters/CompactSelect.js +2 -1
  424. package/dist/esm/Components/Table/filters/FilterDatePicker.js +20 -0
  425. package/dist/esm/Components/Table/filters/LeftFilterPane.js +14 -6
  426. package/dist/esm/Components/Table/hooks/useTable.js +11 -7
  427. package/dist/esm/Components/Table/settings/ManageColumns.js +4 -3
  428. package/dist/esm/Components/Table/settings/TableSettings.js +4 -4
  429. package/dist/esm/Components/Tabs/Tabs.js +1 -0
  430. package/dist/esm/Components/Tabs/components/TabList.js +1 -0
  431. package/dist/esm/Components/Tabs/components/TabPanel.js +1 -0
  432. package/dist/esm/Components/Tabs/tabStyles.js +5 -3
  433. package/dist/esm/Components/Tag/Tag.js +5 -4
  434. package/dist/esm/Components/Tag/Tag.styles.js +5 -4
  435. package/dist/esm/Components/Tag/tagDot.js +10 -3
  436. package/dist/esm/Components/TagInput/TagInput.js +8 -7
  437. package/dist/esm/Components/TagInput/tagEntries.js +16 -4
  438. package/dist/esm/Components/TimePicker/TimePicker.js +7 -3
  439. package/dist/esm/Components/Timeline/Timeline.js +14 -10
  440. package/dist/esm/Components/Toaster/Toaster.js +2 -1
  441. package/dist/esm/Components/Toggle/TableToggle.js +1 -1
  442. package/dist/esm/Components/UpgradeButton/UpgradeButton.js +3 -2
  443. package/dist/esm/Components/UserDetails/UserDetails.js +5 -7
  444. package/dist/esm/Components/WishlistToggle/WishlistToggle.js +2 -1
  445. package/dist/esm/Components/WorkspaceWindow/WorkspaceTrayPreview.js +12 -2
  446. package/dist/esm/Components/WorkspaceWindow/WorkspaceWindow.js +3 -1
  447. package/dist/esm/Hooks/useOutsideMouseDown.js +26 -0
  448. package/dist/esm/Hooks/usePreferences.js +30 -12
  449. package/dist/esm/Hooks/useScrollableRegion.js +33 -0
  450. package/dist/esm/Theme/chakra/Menu.styles.js +6 -0
  451. package/dist/esm/Theme/chakra/componentStyles.js +1 -1
  452. package/dist/esm/Theme/chakra/focusRing.styles.js +3 -3
  453. package/dist/esm/Theme/chakra/paletteFromTheme.js +16 -3
  454. package/dist/esm/Theme/provider/ThemeSwitcher.js +1 -1
  455. package/dist/esm/Theme/tokens/builders/filledSurface.js +3 -2
  456. package/dist/esm/Theme/tokens/builders/focusRing.js +4 -1
  457. package/dist/esm/Theme/tokens/builders/paletteScale.js +6 -0
  458. package/dist/esm/Utils/tabular.js +56 -0
  459. package/dist/esm/index.js +16 -24
  460. package/dist/index.d.ts +54 -2
  461. package/dist/index.js +33 -29
  462. package/package.json +3 -1
  463. package/dist/Components/Buttons/Buttons.d.ts +0 -3
  464. package/dist/Components/Buttons/Buttons.js +0 -9
  465. package/dist/Components/Buttons/ButtonsProps.d.ts +0 -12
  466. package/dist/Components/Common/ErrorComponent.d.ts +0 -7
  467. package/dist/Components/Common/ErrorComponent.js +0 -16
  468. package/dist/Components/Common/FormattedDescription.d.ts +0 -7
  469. package/dist/Components/Common/FormattedDescription.js +0 -62
  470. package/dist/Components/Common/Label.d.ts +0 -9
  471. package/dist/Components/Common/Label.js +0 -12
  472. package/dist/Components/Input/Input/Input.d.ts +0 -4
  473. package/dist/Components/Input/Input/Input.js +0 -75
  474. package/dist/Components/Input/Input/InputProps.d.ts +0 -24
  475. package/dist/Components/Input/Input/InputProps.js +0 -2
  476. package/dist/Components/ProductCard/productCardFixtures.d.ts +0 -7
  477. package/dist/Components/ProductCard/productCardFixtures.js +0 -61
  478. package/dist/esm/Components/Buttons/Buttons.js +0 -4
  479. package/dist/esm/Components/Common/ErrorComponent.js +0 -14
  480. package/dist/esm/Components/Common/FormattedDescription.js +0 -60
  481. package/dist/esm/Components/Common/Label.js +0 -10
  482. package/dist/esm/Components/Input/Input/Input.js +0 -37
  483. package/dist/esm/Components/Input/Input/InputProps.js +0 -1
  484. package/dist/esm/Components/ProductCard/productCardFixtures.js +0 -58
  485. package/dist/esm/services/feedback.js +0 -15
  486. package/dist/services/feedback.d.ts +0 -12
  487. package/dist/services/feedback.js +0 -18
  488. /package/dist/Components/{Buttons/ButtonsProps.js → Common/dataAttributes.js} +0 -0
  489. /package/dist/esm/Components/{Buttons/ButtonsProps.js → Common/dataAttributes.js} +0 -0
@@ -58,6 +58,7 @@ const FieldMessage_1 = __importDefault(require("../Common/FieldMessage"));
58
58
  const useExclusiveOverlay_1 = require("../../Hooks/useExclusiveOverlay");
59
59
  const FormLabel_1 = require("../Common/FormLabel");
60
60
  const Tag_1 = __importDefault(require("../Tag/Tag"));
61
+ const groupedWindow_1 = require("./groupedWindow");
61
62
  const ROW_TRANSITION = (0, motion_1.transitionFor)(["background-color", "color"]);
62
63
  const CHEVRON_TRANSITION = (0, motion_1.transitionFor)(["transform"], "base");
63
64
  const PAGE_STEP = 8;
@@ -65,6 +66,13 @@ const LOAD_MORE_THRESHOLD_PX = 8;
65
66
  const DEFAULT_MAX_VISIBLE_CHIPS = 6;
66
67
  const VIRTUAL_OVERSCAN = 4;
67
68
  const DECORATIVE_CHECKBOX_SX = { "& input": { visibility: "hidden" } };
69
+ const GROUP_HEADER_ESTIMATE_PX = 29;
70
+ const LIST_PADDING_PX = 4;
71
+ const NO_ROW = -1;
72
+ const SELECT_ALL_ROW = -2;
73
+ const CREATE_ROW = -3;
74
+ const FOOTER_ROW = -4;
75
+ const truncateLabel = (label, max) => max !== undefined && label.length > max ? `${label.slice(0, max)}…` : label;
68
76
  const asIdSet = (values) => new Set((values !== null && values !== void 0 ? values : []).map((v) => v.toString()));
69
77
  /** Regression-guarded id scheme — tickets e2e (`e2e/tests/helpers/selectV2.ts`) resolves it verbatim. */
70
78
  const optionDomId = (listboxId, id) => `${listboxId}-option-${id.toString().replace(/[^a-zA-Z0-9_-]/g, "-")}`;
@@ -76,23 +84,10 @@ const OptionRow = react_1.default.memo(function OptionRow({ option, index, listb
76
84
  const isSingleSelected = isSelected && !isMulti;
77
85
  return ((0, jsx_runtime_1.jsxs)(react_2.Box, { id: optionDomId(listboxId, option.id), "data-index": index, role: "option", "aria-selected": isSelected, "aria-disabled": option.isDisabled, onMouseEnter: () => onActivate(index), onClick: () => onSelect(option), mx: spec.mx, px: spec.px, py: spec.py, minH: spec.minH, borderRadius: "md", cursor: option.isDisabled ? "not-allowed" : "pointer", opacity: option.isDisabled ? 0.4 : 1, display: "flex", alignItems: "center", gap: spec.gap, fontSize: spec.fontSize, fontWeight: (0, optionRowInk_1.optionRowWeight)(isSingleSelected), color: (0, optionRowInk_1.optionRowInk)(theme.colors, isSingleSelected), bg: (0, optionRowInk_1.optionRowFill)(backgrounds, isActive), transition: ROW_TRANSITION, sx: (0, motion_2.reducedMotionSx)(), children: [isMulti ? ((0, jsx_runtime_1.jsx)(react_2.Checkbox, { id: `${optionDomId(listboxId, option.id)}-checkbox`, isChecked: isSelected, isDisabled: option.isDisabled, pointerEvents: "none", tabIndex: -1, sx: DECORATIVE_CHECKBOX_SX })) : null, renderOption ? ((0, jsx_runtime_1.jsx)(react_2.Box, { flex: 1, minW: 0, children: renderOption(option, { isSelected, isActive }) })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [option.icon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, children: option.icon })) : null, (0, jsx_runtime_1.jsxs)(react_2.Box, { flex: 1, minW: 0, isTruncated: true, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", isTruncated: true, children: option.label }), option.description ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "block", fontSize: spec.descriptionFontSize, color: (0, optionRowInk_1.optionRowDescriptionInk)(theme.colors), isTruncated: true, children: option.description })) : null] })] })), isSingleSelected ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.Check, size: spec.iconSize, color: theme.colors.accentText, flexShrink: 0 })) : null] }));
78
86
  });
79
- const buildGroupedRows = (options) => {
80
- const rows = [];
81
- let currentGroup;
82
- options.forEach((option, index) => {
83
- if (option.group !== currentGroup) {
84
- currentGroup = option.group;
85
- if (option.group)
86
- rows.push({ kind: "header", key: `group-${option.group}-${index}`, group: option.group });
87
- }
88
- rows.push({ kind: "option", key: option.id, option, index });
89
- });
90
- return rows;
91
- };
92
87
  /** The unified `Select`'s popup mode (`native={false}`) — absorbs SelectV2's behaviour, plus clear/create/groups/virtualization. */
93
88
  const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
94
- var _a, _b, _c, _d, _e;
95
- const { options = [], id, name, placeholder = "Select Option", label, error = false, errorMessage, helperText, isDisabled = false, isReadOnly = false, isRequired = false, isInformation = false, informationMessage, size = controlSizes_1.DEFAULT_CONTROL_SIZE, isSearchable = true, width, formControlStyle, onBlur, onFocus, renderOption, renderValue, maxMenuHeight = "16rem", defaultOpen = false, isLoading = false, loadingText = "Loading...", onLoadMore, hasMore, onSearchChange, searchValue, defaultSearchValue, searchDebounceMs = 0, filterOptions, isClearable = false, onClear, noOptionsMessage, onCreate, createLabel, virtualizeAfter, "data-testid": dataTestId, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, } = props;
89
+ var _a, _b, _c, _d, _e, _f;
90
+ const { options = [], id, name, placeholder = "Select Option", label, error = false, errorMessage, helperText, isDisabled = false, isReadOnly = false, isRequired = false, isInformation = false, informationMessage, size = controlSizes_1.DEFAULT_CONTROL_SIZE, isSearchable = true, width, formControlStyle, onBlur, onFocus, renderOption, renderValue, maxMenuHeight = "16rem", defaultOpen = false, isLoading = false, loadingText = "Loading...", onLoadMore, hasMore, onSearchChange, searchValue, defaultSearchValue, searchDebounceMs = 0, filterOptions, isClearable = false, onClear, noOptionsMessage, onCreate, createLabel, createWhen = "no-options", footerAction, searchFields, filterOption, isFieldLoading = false, rightIcon, virtualizeAfter, "data-testid": dataTestId, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, } = props;
96
91
  const theme = (0, useCustomTheme_1.useCustomTheme)();
97
92
  const { colors } = theme;
98
93
  const { isOpen, onOpen, onClose } = (0, react_2.useDisclosure)({ defaultIsOpen: defaultOpen });
@@ -109,6 +104,8 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
109
104
  const listboxId = `${ids.inputId}-listbox`;
110
105
  const filterInputId = `${listboxId}-filter`;
111
106
  const createRowId = `${listboxId}-create`;
107
+ const selectAllId = `${listboxId}-select-all`;
108
+ const footerId = `${listboxId}-footer`;
112
109
  const isInteractive = !isDisabled && !isReadOnly;
113
110
  const isValueControlled = props.value !== undefined;
114
111
  const [uncontrolledValue, setUncontrolledValue] = (0, react_1.useState)(props.defaultValue);
@@ -137,12 +134,18 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
137
134
  .filter((option) => option !== undefined);
138
135
  }, [options, selectedIds]);
139
136
  const shouldFilterLocally = filterOptions !== null && filterOptions !== void 0 ? filterOptions : !onSearchChange;
137
+ const searchesLabel = searchFields ? searchFields.includes("label") : true;
138
+ const searchesDescription = !!searchFields && searchFields.includes("description");
140
139
  const filteredOptions = (0, react_1.useMemo)(() => {
141
- if (!isSearchable || !currentSearch.trim() || !shouldFilterLocally)
140
+ const query = currentSearch.trim();
141
+ if (!isSearchable || !query || !shouldFilterLocally)
142
142
  return options;
143
- const needle = currentSearch.trim().toLowerCase();
144
- return options.filter((option) => option.label.toString().toLowerCase().includes(needle));
145
- }, [options, currentSearch, isSearchable, shouldFilterLocally]);
143
+ if (filterOption)
144
+ return options.filter((option) => filterOption(option, query));
145
+ const needle = query.toLowerCase();
146
+ return options.filter((option) => (searchesLabel && option.label.toString().toLowerCase().includes(needle)) ||
147
+ (searchesDescription && !!option.description && option.description.toLowerCase().includes(needle)));
148
+ }, [options, currentSearch, isSearchable, shouldFilterLocally, filterOption, searchesLabel, searchesDescription]);
146
149
  const hasGroups = (0, react_1.useMemo)(() => options.some((option) => option.group), [options]);
147
150
  const resetAndClose = (0, react_1.useCallback)((opts) => {
148
151
  if (props.isMulti && (opts === null || opts === void 0 ? void 0 : opts.keepOpenForMulti))
@@ -198,6 +201,29 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
198
201
  onCreate(currentSearch.trim());
199
202
  resetAndClose();
200
203
  }, [onCreate, currentSearch, resetAndClose]);
204
+ const handleFooterAction = (0, react_1.useCallback)(() => {
205
+ if (!footerAction)
206
+ return;
207
+ footerAction.onSelect(currentSearch.trim());
208
+ resetAndClose();
209
+ }, [footerAction, currentSearch, resetAndClose]);
210
+ const hasSelectAllRow = !!props.isMulti && !!props.isSelectAll;
211
+ const selectableFiltered = (0, react_1.useMemo)(() => (hasSelectAllRow ? filteredOptions.filter((option) => !option.isDisabled) : []), [hasSelectAllRow, filteredOptions]);
212
+ const showSelectAllRow = selectableFiltered.length > 0;
213
+ const allFilteredSelected = showSelectAllRow && selectableFiltered.every((o) => selectedIds.has(o.id.toString()));
214
+ const handleSelectAll = () => {
215
+ var _a;
216
+ if (!props.isMulti || !showSelectAllRow)
217
+ return;
218
+ const shown = new Set(selectableFiltered.map((option) => option.id.toString()));
219
+ const next = allFilteredSelected
220
+ ? selectedOptions.filter((selected) => !shown.has(selected.id.toString()))
221
+ : [...selectedOptions, ...selectableFiltered.filter((option) => !selectedIds.has(option.id.toString()))];
222
+ if (!isValueControlled)
223
+ setUncontrolledValue(next.map((o) => o.id));
224
+ props.onChange(next);
225
+ (_a = filterInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
226
+ };
201
227
  const handleClear = (0, react_1.useCallback)((event) => {
202
228
  event.stopPropagation();
203
229
  if (!isInteractive)
@@ -231,31 +257,50 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
231
257
  }, [isOpen, isSearchable]);
232
258
  const spec = (0, react_1.useMemo)(() => (0, optionRowSizes_1.optionRowSpec)(size), [size]);
233
259
  const maxMenuHeightPx = (0, react_1.useMemo)(() => parseRemToPx(maxMenuHeight, 256), [maxMenuHeight]);
234
- const shouldVirtualize = !!virtualizeAfter && !hasGroups && filteredOptions.length > virtualizeAfter;
260
+ const shouldVirtualize = !!virtualizeAfter && filteredOptions.length > virtualizeAfter;
235
261
  const [scrollTop, setScrollTop] = (0, react_1.useState)(0);
236
262
  // A description, an avatar or a renderOption row outgrows the spec's single-line height.
237
263
  const [rowHeightPx, setRowHeightPx] = (0, react_1.useState)(spec.virtualRowHeightPx);
264
+ const [headerHeightPx, setHeaderHeightPx] = (0, react_1.useState)(GROUP_HEADER_ESTIMATE_PX);
265
+ const selectAllLeadPx = showSelectAllRow ? rowHeightPx : 0;
266
+ const windowTop = Math.max(0, scrollTop - selectAllLeadPx);
238
267
  const visibleCount = Math.ceil(maxMenuHeightPx / rowHeightPx) + VIRTUAL_OVERSCAN * 2;
268
+ const groupedRows = (0, react_1.useMemo)(() => (hasGroups ? (0, groupedWindow_1.buildGroupedRows)(filteredOptions) : []), [hasGroups, filteredOptions]);
269
+ const groupedLayout = (0, react_1.useMemo)(() => (hasGroups && shouldVirtualize ? (0, groupedWindow_1.layoutGroupedRows)(groupedRows, headerHeightPx, rowHeightPx) : null), [hasGroups, shouldVirtualize, groupedRows, headerHeightPx, rowHeightPx]);
270
+ const groupedRange = groupedLayout
271
+ ? (0, groupedWindow_1.groupedWindow)(groupedLayout.tops, windowTop, maxMenuHeightPx, VIRTUAL_OVERSCAN)
272
+ : null;
239
273
  const startIndex = shouldVirtualize
240
- ? Math.max(0, Math.floor(scrollTop / rowHeightPx) - VIRTUAL_OVERSCAN)
274
+ ? Math.max(0, Math.floor(windowTop / rowHeightPx) - VIRTUAL_OVERSCAN)
241
275
  : 0;
242
276
  const endIndex = shouldVirtualize
243
277
  ? Math.min(filteredOptions.length, startIndex + visibleCount)
244
278
  : filteredOptions.length;
245
279
  const renderedOptions = shouldVirtualize ? filteredOptions.slice(startIndex, endIndex) : filteredOptions;
246
- const topPadPx = shouldVirtualize ? startIndex * rowHeightPx : 0;
247
- const bottomPadPx = shouldVirtualize ? (filteredOptions.length - endIndex) * rowHeightPx : 0;
280
+ const topPadPx = groupedLayout && groupedRange
281
+ ? groupedLayout.tops[groupedRange.start]
282
+ : shouldVirtualize ? startIndex * rowHeightPx : 0;
283
+ const bottomPadPx = groupedLayout && groupedRange
284
+ ? groupedLayout.tops[groupedLayout.tops.length - 1] - groupedLayout.tops[groupedRange.end]
285
+ : shouldVirtualize ? (filteredOptions.length - endIndex) * rowHeightPx : 0;
286
+ const renderedGroupedRows = groupedRange ? groupedRows.slice(groupedRange.start, groupedRange.end) : groupedRows;
248
287
  (0, react_1.useLayoutEffect)(() => {
249
- var _a;
288
+ var _a, _b;
250
289
  if (!isOpen)
251
290
  return;
252
- const row = (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('[role="option"]');
253
- if (!row)
254
- return;
255
- const measured = row.getBoundingClientRect().height;
256
- if (measured > 0 && Math.abs(measured - rowHeightPx) > 0.5)
257
- setRowHeightPx(measured);
258
- }, [isOpen, rowHeightPx, filteredOptions.length]);
291
+ const row = (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('[role="option"][data-index]');
292
+ if (row) {
293
+ const measured = row.getBoundingClientRect().height;
294
+ if (measured > 0 && Math.abs(measured - rowHeightPx) > 0.5)
295
+ setRowHeightPx(measured);
296
+ }
297
+ const header = (_b = listRef.current) === null || _b === void 0 ? void 0 : _b.querySelector("[data-group-header]");
298
+ if (header) {
299
+ const measured = header.getBoundingClientRect().height;
300
+ if (measured > 0 && Math.abs(measured - headerHeightPx) > 0.5)
301
+ setHeaderHeightPx(measured);
302
+ }
303
+ }, [isOpen, rowHeightPx, headerHeightPx, filteredOptions.length]);
259
304
  // Windowing starts mid-list, so the window must open where the user already is.
260
305
  (0, react_1.useLayoutEffect)(() => {
261
306
  var _a, _b;
@@ -264,16 +309,29 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
264
309
  wasVirtualized.current = shouldVirtualize;
265
310
  }, [shouldVirtualize]);
266
311
  (0, react_1.useEffect)(() => {
267
- var _a, _b;
268
- if (activeIndex < 0 || !listRef.current)
312
+ var _a, _b, _c, _d;
313
+ if (activeIndex === NO_ROW || !listRef.current)
269
314
  return;
270
315
  if (lastActiveIndex.current === activeIndex)
271
316
  return;
272
317
  lastActiveIndex.current = activeIndex;
273
318
  const el = listRef.current;
319
+ if (activeIndex < 0) {
320
+ const extraId = activeIndex === SELECT_ALL_ROW ? selectAllId : activeIndex === CREATE_ROW ? createRowId : footerId;
321
+ (_b = (_a = el.ownerDocument.getElementById(extraId)) === null || _a === void 0 ? void 0 : _a.scrollIntoView) === null || _b === void 0 ? void 0 : _b.call(_a, { block: "nearest" });
322
+ return;
323
+ }
274
324
  if (shouldVirtualize) {
275
- const targetTop = activeIndex * rowHeightPx;
276
- const targetBottom = targetTop + rowHeightPx;
325
+ let targetTop = activeIndex * rowHeightPx;
326
+ let targetBottom = targetTop + rowHeightPx;
327
+ const rowIndex = groupedLayout === null || groupedLayout === void 0 ? void 0 : groupedLayout.optionRows[activeIndex];
328
+ if (groupedLayout && rowIndex !== undefined) {
329
+ const startsGroup = rowIndex > 0 && groupedRows[rowIndex - 1].kind === "header";
330
+ targetTop = groupedLayout.tops[startsGroup ? rowIndex - 1 : rowIndex];
331
+ targetBottom = groupedLayout.tops[rowIndex + 1];
332
+ }
333
+ targetTop += selectAllLeadPx + LIST_PADDING_PX;
334
+ targetBottom += selectAllLeadPx + LIST_PADDING_PX;
277
335
  if (targetTop < el.scrollTop) {
278
336
  el.scrollTop = targetTop;
279
337
  setScrollTop(targetTop);
@@ -285,8 +343,8 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
285
343
  }
286
344
  return;
287
345
  }
288
- (_b = (_a = el.querySelector(`[data-index="${activeIndex}"]`)) === null || _a === void 0 ? void 0 : _a.scrollIntoView) === null || _b === void 0 ? void 0 : _b.call(_a, { block: "nearest" });
289
- }, [activeIndex, shouldVirtualize, maxMenuHeightPx, rowHeightPx]);
346
+ (_d = (_c = el.querySelector(`[data-index="${activeIndex}"]`)) === null || _c === void 0 ? void 0 : _c.scrollIntoView) === null || _d === void 0 ? void 0 : _d.call(_c, { block: "nearest" });
347
+ }, [activeIndex, shouldVirtualize, maxMenuHeightPx, rowHeightPx, groupedLayout, groupedRows, selectAllLeadPx, selectAllId, createRowId, footerId]);
290
348
  const loadMoreInFlightRef = (0, react_1.useRef)(false);
291
349
  const prevOptionsLengthRef = (0, react_1.useRef)(options.length);
292
350
  const prevIsLoadingRef = (0, react_1.useRef)(isLoading);
@@ -307,23 +365,57 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
307
365
  loadMoreInFlightRef.current = true;
308
366
  onLoadMore();
309
367
  }, [onLoadMore, hasMore, isLoading]);
368
+ const trimmedSearch = currentSearch.trim();
369
+ const hasExactMatch = (0, react_1.useMemo)(() => {
370
+ if (createWhen !== "no-exact-match" || !trimmedSearch)
371
+ return false;
372
+ const needle = trimmedSearch.toLowerCase();
373
+ return options.some((option) => option.label.toString().trim().toLowerCase() === needle);
374
+ }, [createWhen, trimmedSearch, options]);
375
+ const showCreateRow = !!onCreate &&
376
+ isSearchable &&
377
+ trimmedSearch !== "" &&
378
+ !isLoading &&
379
+ (createWhen === "no-exact-match" ? !hasExactMatch : filteredOptions.length === 0);
380
+ const isCreateImplicit = showCreateRow && filteredOptions.length === 0;
381
+ const hasFooter = !!footerAction;
382
+ const leadingStops = showSelectAllRow ? 1 : 0;
383
+ const optionsEndStop = leadingStops + filteredOptions.length - 1;
384
+ const stopCount = optionsEndStop + 1 + (showCreateRow ? 1 : 0) + (hasFooter ? 1 : 0);
385
+ const rowToStop = (row) => {
386
+ if (row === SELECT_ALL_ROW)
387
+ return showSelectAllRow ? 0 : -1;
388
+ if (row === CREATE_ROW)
389
+ return showCreateRow ? optionsEndStop + 1 : -1;
390
+ if (row === FOOTER_ROW)
391
+ return hasFooter ? stopCount - 1 : -1;
392
+ return row >= 0 && row < filteredOptions.length ? leadingStops + row : -1;
393
+ };
394
+ const stopToRow = (stop) => {
395
+ if (showSelectAllRow && stop === 0)
396
+ return SELECT_ALL_ROW;
397
+ if (stop <= optionsEndStop)
398
+ return stop - leadingStops;
399
+ return showCreateRow && stop === optionsEndStop + 1 ? CREATE_ROW : FOOTER_ROW;
400
+ };
310
401
  const moveActive = (delta) => {
311
- if (!filteredOptions.length)
402
+ if (!stopCount)
312
403
  return;
313
- const next = activeIndex + delta;
314
- if (delta > 0 && next >= filteredOptions.length) {
315
- if (canLoadMore) {
316
- triggerLoadMore();
317
- return;
318
- }
319
- setActiveIndex(0);
404
+ const current = rowToStop(activeIndex);
405
+ const next = current + delta;
406
+ const isPaging = delta > 0 && canLoadMore && filteredOptions.length > 0 && current === optionsEndStop;
407
+ if (isPaging)
408
+ triggerLoadMore();
409
+ if (delta > 0 && next >= stopCount) {
410
+ if (!isPaging)
411
+ setActiveIndex(stopToRow(0));
320
412
  return;
321
413
  }
322
414
  if (next < 0) {
323
- setActiveIndex(filteredOptions.length - 1);
415
+ setActiveIndex(stopToRow(stopCount - 1));
324
416
  return;
325
417
  }
326
- setActiveIndex(next);
418
+ setActiveIndex(stopToRow(next));
327
419
  };
328
420
  const moveActiveBy = (delta) => {
329
421
  if (!filteredOptions.length)
@@ -335,7 +427,6 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
335
427
  return;
336
428
  setActiveIndex(edge === "start" ? 0 : filteredOptions.length - 1);
337
429
  };
338
- const showCreateRow = !!onCreate && isSearchable && currentSearch.trim() !== "" && filteredOptions.length === 0 && !isLoading;
339
430
  const handleListKeyDown = (event) => {
340
431
  var _a, _b;
341
432
  const isTextInput = ((_a = event.target) === null || _a === void 0 ? void 0 : _a.tagName) === "INPUT";
@@ -371,9 +462,15 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
371
462
  case "Enter": {
372
463
  event.preventDefault();
373
464
  const activeOption = filteredOptions[activeIndex];
374
- if (activeOption)
465
+ if (activeIndex === SELECT_ALL_ROW && showSelectAllRow)
466
+ handleSelectAll();
467
+ else if (activeIndex === FOOTER_ROW && hasFooter)
468
+ handleFooterAction();
469
+ else if (activeIndex === CREATE_ROW && showCreateRow)
470
+ handleCreate();
471
+ else if (activeOption)
375
472
  handleSelect(activeOption);
376
- else if (showCreateRow)
473
+ else if (isCreateImplicit)
377
474
  handleCreate();
378
475
  break;
379
476
  }
@@ -392,7 +489,9 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
392
489
  const handleTriggerKeyDown = (event) => {
393
490
  if (!isInteractive)
394
491
  return;
395
- if (props.isMulti && !isOpen && event.key === "Backspace" && selectedOptions.length) {
492
+ if (event.target !== event.currentTarget && (event.key === "Enter" || event.key === " "))
493
+ return;
494
+ if (props.isMulti && props.isChipRemovable !== false && !isOpen && event.key === "Backspace" && selectedOptions.length) {
396
495
  event.preventDefault();
397
496
  handleSelect(selectedOptions[selectedOptions.length - 1]);
398
497
  return;
@@ -428,16 +527,22 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
428
527
  searchDebounceTimer.current = setTimeout(() => onSearchChange(nextText), searchDebounceMs);
429
528
  };
430
529
  const activeOption = filteredOptions[activeIndex];
431
- const activeDescendantId = activeOption
432
- ? optionDomId(listboxId, activeOption.id)
433
- : showCreateRow
434
- ? createRowId
435
- : undefined;
530
+ const activeDescendantId = activeIndex === SELECT_ALL_ROW && showSelectAllRow
531
+ ? selectAllId
532
+ : activeIndex === FOOTER_ROW && hasFooter
533
+ ? footerId
534
+ : activeOption
535
+ ? optionDomId(listboxId, activeOption.id)
536
+ : showCreateRow && (isCreateImplicit || activeIndex === CREATE_ROW)
537
+ ? createRowId
538
+ : undefined;
436
539
  const listScrollStyles = (0, react_1.useMemo)(() => (0, scrollbar_1.scrollbarStyles)(colors, "overlay"), [colors]);
437
540
  const rowBackgrounds = (0, react_1.useMemo)(() => (0, rowStates_1.listRowBackgrounds)(colors), [colors]);
438
541
  const showChips = !!props.isMulti && !renderValue && selectedOptions.length > 0;
439
542
  const chipSize = size === "xs" ? "xs" : "sm";
440
543
  const maxVisibleChips = props.isMulti ? ((_a = props.maxVisibleChips) !== null && _a !== void 0 ? _a : DEFAULT_MAX_VISIBLE_CHIPS) : 0;
544
+ const chipMaxLength = props.isMulti ? props.chipMaxLength : undefined;
545
+ const canRemoveChips = isInteractive && !!props.isMulti && props.isChipRemovable !== false;
441
546
  const visibleChipOptions = showChips ? selectedOptions.slice(0, maxVisibleChips) : [];
442
547
  const overflowChipCount = showChips ? selectedOptions.length - visibleChipOptions.length : 0;
443
548
  const showClear = isClearable && isInteractive && selectedOptions.length > 0;
@@ -472,15 +577,17 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
472
577
  const triggerIcon = !props.isMulti && ((_b = selectedOptions[0]) === null || _b === void 0 ? void 0 : _b.icon) ? selectedOptions[0].icon : null;
473
578
  const selectedValueIds = selectedOptions.map((option) => option.id.toString());
474
579
  const hiddenValues = !name ? [] : props.isMulti ? selectedValueIds : [(_c = selectedValueIds[0]) !== null && _c !== void 0 ? _c : ""];
475
- const groupedRows = (0, react_1.useMemo)(() => (hasGroups ? buildGroupedRows(filteredOptions) : []), [hasGroups, filteredOptions]);
476
- return ((0, jsx_runtime_1.jsxs)(react_2.FormControl, { isInvalid: error, isDisabled: isDisabled, isReadOnly: isReadOnly, style: formControlStyle, width: width, children: [label && ((0, jsx_runtime_1.jsx)(FormLabel_1.TextLabel, { label: label, id: ids.inputId, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), (0, jsx_runtime_1.jsxs)(react_2.Popover, { isOpen: isOpen, onClose: () => resetAndClose(), placement: "bottom-start", autoFocus: false, returnFocusOnClose: false, gutter: 4, children: [(0, jsx_runtime_1.jsx)(react_2.PopoverAnchor, { children: (0, jsx_runtime_1.jsxs)(react_2.Box, { as: "div", ref: mergedTriggerRef, ...ids.controlProps, role: "combobox", tabIndex: isDisabled ? -1 : 0, "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-controls": listboxId, "aria-owns": `${listboxId} ${filterInputId}`, "aria-activedescendant": activeDescendantId, "aria-disabled": isDisabled || undefined, "data-readonly": isReadOnly || undefined, "aria-required": isRequired || undefined, "aria-label": triggerAriaLabel(), "aria-labelledby": ariaLabelledBy, onClick: handleOpen, onKeyDown: handleTriggerKeyDown, display: "flex", alignItems: "center", justifyContent: "space-between", width: "100%", textAlign: "left", cursor: isDisabled ? "not-allowed" : isReadOnly ? "default" : "pointer", "data-testid": dataTestId, sx: triggerSx, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexWrap: showChips ? "wrap" : "nowrap", alignItems: "center", gap: showChips ? 1 : 1.5, minW: 0, flex: 1, isTruncated: !showChips, children: showChips ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [visibleChipOptions.map((option) => ((0, jsx_runtime_1.jsx)(Tag_1.default, { label: String(option.label), size: chipSize, variant: "subtle", icon: isInteractive ? lucide_react_1.X : undefined, onIconClick: isInteractive ? () => handleSelect(option) : undefined }, option.id))), overflowChipCount > 0 && ((0, jsx_runtime_1.jsx)(Tag_1.default, { label: `+${overflowChipCount}`, size: chipSize, variant: "subtle", colorScheme: "gray" }))] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [triggerIcon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, children: triggerIcon })) : null, (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", isTruncated: true, children: renderValue ? renderValue(selectedOptions) : defaultTriggerContent() })] })) }), showClear && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", "aria-label": "Clear selection", onClick: handleClear, display: "inline-flex", alignItems: "center", justifyContent: "center", flexShrink: 0, ml: 2, color: colors.textMuted, _hover: { color: colors.text[700] }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: controlSizes_1.CONTROL_SIZES[size].iconSize }) })), (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, ml: 2, transition: CHEVRON_TRANSITION, transform: isOpen ? "rotate(180deg)" : "rotate(0deg)", color: colors.textMuted, sx: (0, motion_2.reducedMotionSx)(), children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: controlSizes_1.CONTROL_SIZES[size].iconSize }) })] }) }), (0, jsx_runtime_1.jsx)(react_2.Portal, { children: (0, jsx_runtime_1.jsxs)(react_2.PopoverContent, { "aria-label": (_d = label !== null && label !== void 0 ? label : ariaLabel) !== null && _d !== void 0 ? _d : placeholder, width: "max-content", minWidth: triggerWidth ? `${triggerWidth}px` : undefined, maxWidth: "min(24rem, calc(100vw - 2rem))", borderRadius: "xl", boxShadow: theme.shadows.lg, overflow: "hidden", onKeyDown: handleListKeyDown, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { p: spec.mx, borderBottom: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${(0, surfaceRaised_1.raisedRule)(colors)}`, display: isSearchable ? undefined : "none", children: (0, jsx_runtime_1.jsx)(react_2.Input, { ref: filterInputRef, id: filterInputId, size: size, px: spec.px, placeholder: "Type to filter...", value: currentSearch, onChange: handleFilterChange, "aria-activedescendant": activeDescendantId, "aria-controls": listboxId, "aria-label": "Filter options", tabIndex: isSearchable ? undefined : -1 }) }), (0, jsx_runtime_1.jsxs)(react_2.Box, { id: listboxId, ref: listRef, role: "listbox", "aria-label": (_e = label !== null && label !== void 0 ? label : ariaLabel) !== null && _e !== void 0 ? _e : placeholder, "aria-multiselectable": props.isMulti || undefined, "aria-busy": isLoading || undefined, maxH: maxMenuHeight, overflowY: "auto", py: 1, sx: listScrollStyles, onScroll: handleListScroll, children: [filteredOptions.length === 0 && !isLoading && !showCreateRow && ((0, jsx_runtime_1.jsx)(react_2.Box, { mx: spec.mx, px: spec.px, py: spec.py, fontSize: spec.fontSize, color: colors.textMuted, children: noOptionsMessage !== null && noOptionsMessage !== void 0 ? noOptionsMessage : "No Options" })), showCreateRow && ((0, jsx_runtime_1.jsx)(react_2.Box, { id: createRowId, role: "option", "aria-selected": false, "data-index": -1, onClick: handleCreate, mx: spec.mx, px: spec.px, py: spec.py, minH: spec.minH, borderRadius: "md", cursor: "pointer", fontSize: spec.fontSize, fontWeight: 600, color: colors.primary[600], bg: activeDescendantId === createRowId ? rowBackgrounds.active : "transparent", children: createLabel ? createLabel(currentSearch.trim()) : `Create "${currentSearch.trim()}"` })), hasGroups
477
- ? groupedRows.map((row) => {
478
- var _a;
479
- return row.kind === "header" ? ((0, jsx_runtime_1.jsx)(react_2.Box, { mx: spec.mx, px: spec.px, pt: 2, pb: 1, fontSize: "xs-minus", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.03em", color: colors.textMuted, children: row.group }, row.key)) : ((0, jsx_runtime_1.jsx)(OptionRow, { option: row.option, index: row.index, listboxId: listboxId, isSelected: selectedIds.has(row.option.id.toString()), isActive: row.index === activeIndex, isMulti: (_a = props.isMulti) !== null && _a !== void 0 ? _a : false, theme: theme, backgrounds: rowBackgrounds, spec: spec, renderOption: renderOption, onSelect: handleSelect, onActivate: setActiveIndex }, row.key));
480
- })
580
+ return ((0, jsx_runtime_1.jsxs)(react_2.FormControl, { isInvalid: error, isDisabled: isDisabled, isReadOnly: isReadOnly, style: formControlStyle, width: width, children: [label && ((0, jsx_runtime_1.jsx)(FormLabel_1.TextLabel, { label: label, id: ids.inputId, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), (0, jsx_runtime_1.jsxs)(react_2.Popover, { isOpen: isOpen, onClose: () => resetAndClose(), placement: "bottom-start", autoFocus: false, returnFocusOnClose: false, gutter: 4, children: [(0, jsx_runtime_1.jsx)(react_2.PopoverAnchor, { children: (0, jsx_runtime_1.jsxs)(react_2.Box, { as: "div", ref: mergedTriggerRef, ...ids.controlProps, role: "combobox", tabIndex: isDisabled ? -1 : 0, "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-controls": listboxId, "aria-owns": `${listboxId} ${filterInputId}`, "aria-activedescendant": activeDescendantId, "aria-disabled": isDisabled || undefined, "aria-busy": isFieldLoading || undefined, "data-readonly": isReadOnly || undefined, "aria-required": isRequired || undefined, "aria-label": triggerAriaLabel(), "aria-labelledby": ariaLabelledBy, onClick: handleOpen, onKeyDown: handleTriggerKeyDown, display: "flex", alignItems: "center", justifyContent: "space-between", width: "100%", textAlign: "left", cursor: isDisabled ? "not-allowed" : isReadOnly ? "default" : "pointer", "data-testid": dataTestId, sx: triggerSx, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexWrap: showChips ? "wrap" : "nowrap", alignItems: "center", gap: showChips ? 1 : 1.5, minW: 0, flex: 1, isTruncated: !showChips, children: showChips ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [visibleChipOptions.map((option) => ((0, jsx_runtime_1.jsx)(Tag_1.default, { label: truncateLabel(String(option.label), chipMaxLength), size: chipSize, variant: "subtle", icon: canRemoveChips ? lucide_react_1.X : undefined, onIconClick: canRemoveChips ? () => handleSelect(option) : undefined }, option.id))), overflowChipCount > 0 && ((0, jsx_runtime_1.jsx)(Tag_1.default, { label: `+${overflowChipCount}`, size: chipSize, variant: "subtle", colorScheme: "gray" }))] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [triggerIcon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, children: triggerIcon })) : null, (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", isTruncated: true, children: renderValue ? renderValue(selectedOptions) : defaultTriggerContent() })] })) }), showClear && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", "aria-label": "Clear selection", onClick: handleClear, display: "inline-flex", alignItems: "center", justifyContent: "center", flexShrink: 0, ml: 2, color: colors.textMuted, _hover: { color: colors.text[700] }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: controlSizes_1.CONTROL_SIZES[size].iconSize }) })), isFieldLoading ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", "aria-hidden": true, display: "inline-flex", flexShrink: 0, ml: 2, children: (0, jsx_runtime_1.jsx)(react_2.Spinner, { size: "xs", label: "" }) })) : rightIcon ? ("onClick" in rightIcon && isInteractive ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", "aria-label": rightIcon.ariaLabel, onClick: (event) => {
581
+ event.stopPropagation();
582
+ rightIcon.onClick();
583
+ }, onKeyDown: (event) => event.stopPropagation(), display: "inline-flex", alignItems: "center", justifyContent: "center", flexShrink: 0, ml: 2, color: colors.textMuted, _hover: { color: colors.text[700] }, children: rightIcon.icon })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", "aria-hidden": true, display: "inline-flex", flexShrink: 0, ml: 2, color: colors.textMuted, children: rightIcon.icon }))) : ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, ml: 2, transition: CHEVRON_TRANSITION, transform: isOpen ? "rotate(180deg)" : "rotate(0deg)", color: colors.textMuted, sx: (0, motion_2.reducedMotionSx)(), children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: controlSizes_1.CONTROL_SIZES[size].iconSize }) }))] }) }), (0, jsx_runtime_1.jsx)(react_2.Portal, { children: (0, jsx_runtime_1.jsxs)(react_2.PopoverContent, { "aria-label": (_d = label !== null && label !== void 0 ? label : ariaLabel) !== null && _d !== void 0 ? _d : placeholder, width: "max-content", minWidth: triggerWidth ? `${triggerWidth}px` : undefined, maxWidth: "min(24rem, calc(100vw - 2rem))", borderRadius: "xl", boxShadow: theme.shadows.lg, overflow: "hidden", onKeyDown: handleListKeyDown, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { p: spec.mx, borderBottom: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${(0, surfaceRaised_1.raisedRule)(colors)}`, display: isSearchable ? undefined : "none", children: (0, jsx_runtime_1.jsx)(react_2.Input, { ref: filterInputRef, id: filterInputId, size: size, px: spec.px, placeholder: "Type to filter...", value: currentSearch, onChange: handleFilterChange, "aria-activedescendant": activeDescendantId, "aria-controls": listboxId, "aria-label": "Filter options", tabIndex: isSearchable ? undefined : -1 }) }), (0, jsx_runtime_1.jsxs)(react_2.Box, { id: listboxId, ref: listRef, role: "listbox", "aria-label": (_e = label !== null && label !== void 0 ? label : ariaLabel) !== null && _e !== void 0 ? _e : placeholder, "aria-multiselectable": props.isMulti || undefined, "aria-busy": isLoading || undefined, maxH: maxMenuHeight, overflowY: "auto", py: 1, sx: listScrollStyles, onScroll: handleListScroll, children: [filteredOptions.length === 0 && !isLoading && !showCreateRow && ((0, jsx_runtime_1.jsx)(react_2.Box, { mx: spec.mx, px: spec.px, py: spec.py, fontSize: spec.fontSize, color: colors.textMuted, children: noOptionsMessage !== null && noOptionsMessage !== void 0 ? noOptionsMessage : "No Options" })), showSelectAllRow && ((0, jsx_runtime_1.jsxs)(react_2.Box, { id: selectAllId, role: "option", "aria-selected": allFilteredSelected, onClick: handleSelectAll, onMouseEnter: () => setActiveIndex(SELECT_ALL_ROW), mx: spec.mx, px: spec.px, py: spec.py, minH: spec.minH, borderRadius: "md", cursor: "pointer", display: "flex", alignItems: "center", gap: spec.gap, fontSize: spec.fontSize, color: (0, optionRowInk_1.optionRowInk)(colors, false), bg: (0, optionRowInk_1.optionRowFill)(rowBackgrounds, activeIndex === SELECT_ALL_ROW), transition: ROW_TRANSITION, sx: (0, motion_2.reducedMotionSx)(), children: [(0, jsx_runtime_1.jsx)(react_2.Checkbox, { isChecked: allFilteredSelected, pointerEvents: "none", tabIndex: -1, sx: DECORATIVE_CHECKBOX_SX }), allFilteredSelected ? "Unselect All" : "Select All"] })), hasGroups
584
+ ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [topPadPx > 0 && (0, jsx_runtime_1.jsx)(react_2.Box, { height: `${topPadPx}px` }), renderedGroupedRows.map((row) => {
585
+ var _a;
586
+ return row.kind === "header" ? ((0, jsx_runtime_1.jsx)(react_2.Box, { "data-group-header": shouldVirtualize ? "" : undefined, mx: spec.mx, px: spec.px, pt: 2, pb: 1, fontSize: "xs-minus", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.03em", color: colors.textMuted, children: row.group }, row.key)) : ((0, jsx_runtime_1.jsx)(OptionRow, { option: row.option, index: row.index, listboxId: listboxId, isSelected: selectedIds.has(row.option.id.toString()), isActive: row.index === activeIndex, isMulti: (_a = props.isMulti) !== null && _a !== void 0 ? _a : false, theme: theme, backgrounds: rowBackgrounds, spec: spec, renderOption: renderOption, onSelect: handleSelect, onActivate: setActiveIndex }, row.key));
587
+ }), bottomPadPx > 0 && (0, jsx_runtime_1.jsx)(react_2.Box, { height: `${bottomPadPx}px` })] }))
481
588
  : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [topPadPx > 0 && (0, jsx_runtime_1.jsx)(react_2.Box, { height: `${topPadPx}px` }), renderedOptions.map((option, i) => {
482
589
  var _a;
483
590
  return ((0, jsx_runtime_1.jsx)(OptionRow, { option: option, index: startIndex + i, listboxId: listboxId, isSelected: selectedIds.has(option.id.toString()), isActive: startIndex + i === activeIndex, isMulti: (_a = props.isMulti) !== null && _a !== void 0 ? _a : false, theme: theme, backgrounds: rowBackgrounds, spec: spec, renderOption: renderOption, onSelect: handleSelect, onActivate: setActiveIndex }, option.id));
484
- }), bottomPadPx > 0 && (0, jsx_runtime_1.jsx)(react_2.Box, { height: `${bottomPadPx}px` })] })), isLoading && ((0, jsx_runtime_1.jsxs)(react_2.Box, { mx: spec.mx, px: spec.px, py: spec.py, display: "flex", alignItems: "center", gap: spec.gap, fontSize: spec.fontSize, color: colors.textMuted, children: [(0, jsx_runtime_1.jsx)(react_2.Spinner, { size: "xs" }), loadingText] }))] })] }) })] }), hiddenValues.map((value) => ((0, jsx_runtime_1.jsx)("input", { type: "hidden", name: name, value: value }, value))), (0, jsx_runtime_1.jsx)(FieldMessage_1.default, { error: error, errorMessage: errorMessage, helperText: helperText, helperId: ids.helperId, errorId: ids.errorId })] }));
591
+ }), bottomPadPx > 0 && (0, jsx_runtime_1.jsx)(react_2.Box, { height: `${bottomPadPx}px` })] })), showCreateRow && ((0, jsx_runtime_1.jsx)(react_2.Box, { id: createRowId, role: "option", "aria-selected": false, "data-index": -1, onClick: handleCreate, mx: spec.mx, px: spec.px, py: spec.py, minH: spec.minH, borderRadius: "md", cursor: "pointer", fontSize: spec.fontSize, fontWeight: 600, color: colors.primary[600], bg: activeDescendantId === createRowId ? rowBackgrounds.active : "transparent", children: createLabel ? createLabel(currentSearch.trim()) : `Create "${currentSearch.trim()}"` })), isLoading && ((0, jsx_runtime_1.jsxs)(react_2.Box, { mx: spec.mx, px: spec.px, py: spec.py, display: "flex", alignItems: "center", gap: spec.gap, fontSize: spec.fontSize, color: colors.textMuted, children: [(0, jsx_runtime_1.jsx)(react_2.Spinner, { size: "xs" }), loadingText] })), footerAction && ((0, jsx_runtime_1.jsx)(react_2.Box, { id: footerId, role: "option", "aria-selected": false, onClick: handleFooterAction, onMouseEnter: () => setActiveIndex(FOOTER_ROW), position: "sticky", bottom: -1, pt: 1, bg: colors.surfaceRaised, borderTop: `${borderWidths_1.BORDER_WIDTHS.hairline} solid ${(0, surfaceRaised_1.raisedRule)(colors)}`, children: (0, jsx_runtime_1.jsxs)(react_2.Box, { mx: spec.mx, px: spec.px, py: spec.py, minH: spec.minH, borderRadius: "md", cursor: "pointer", display: "flex", alignItems: "center", gap: spec.gap, fontSize: spec.fontSize, fontWeight: 500, color: colors.accentText, bg: activeIndex === FOOTER_ROW ? rowBackgrounds.active : "transparent", children: [(_f = footerAction.icon) !== null && _f !== void 0 ? _f : (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: spec.iconSize }), footerAction.label] }) }))] })] }) })] }), hiddenValues.map((value) => ((0, jsx_runtime_1.jsx)("input", { type: "hidden", name: name, value: value }, value))), (0, jsx_runtime_1.jsx)(FieldMessage_1.default, { error: error, errorMessage: errorMessage, helperText: helperText, helperId: ids.helperId, errorId: ids.errorId })] }));
485
592
  });
486
593
  exports.default = SelectPopup;
@@ -7,7 +7,7 @@ export type OptionProp = {
7
7
  label: string | number;
8
8
  /** Popup mode only — leading icon/avatar for this option's row (and the trigger, when selected). */
9
9
  icon?: ReactNode;
10
- /** Popup mode only — secondary line under the label; not matched by the search filter. */
10
+ /** Popup mode only — secondary line under the label; searched only when `searchFields` includes "description". */
11
11
  description?: string;
12
12
  /** Row is dimmed and unselectable. Native mode emits a disabled `<option>`. */
13
13
  isDisabled?: boolean;
@@ -72,6 +72,10 @@ type SelectCommonProps = {
72
72
  onSearchChange?: (query: string) => void;
73
73
  /** Debounce for `onSearchChange`, in ms. Defaults to 0 — every keystroke, matching SelectV2 today. */
74
74
  searchDebounceMs?: number;
75
+ /** Option fields the local filter matches (case-insensitive substring). Defaults to `["label"]`. Popup mode only. */
76
+ searchFields?: ("label" | "description")[];
77
+ /** Replaces the built-in substring match; receives the trimmed query and wins over `searchFields`. Popup mode only. */
78
+ filterOption?: (option: OptionProp, query: string) => boolean;
75
79
  /** Applies the local label-substring filter. Defaults to false once `onSearchChange` is set (server owns matching), true otherwise. */
76
80
  filterOptions?: boolean;
77
81
  /** Shows a clear (x) control once a value is selected. Popup mode only. */
@@ -82,6 +86,16 @@ type SelectCommonProps = {
82
86
  isLoading?: boolean;
83
87
  /** Text of the loading row. Defaults to "Loading...". Popup mode only. */
84
88
  loadingText?: string;
89
+ /** Swaps the trailing chevron for a spinner and marks the field aria-busy, even while the popup is closed. Popup mode only. */
90
+ isFieldLoading?: boolean;
91
+ /** Trailing slot replacing the chevron; with `onClick` it renders a button (so `ariaLabel` is required) that does not toggle the popup. Popup mode only. */
92
+ rightIcon?: {
93
+ icon: ReactNode;
94
+ } | {
95
+ icon: ReactNode;
96
+ onClick: () => void;
97
+ ariaLabel: string;
98
+ };
85
99
  /** Empty-list message. Native mode stringifies it (plain `<option>` text); popup mode accepts any node. */
86
100
  noOptionsMessage?: ReactNode;
87
101
  /** Fires when the list is scrolled to its end and not loading — append the next page. Popup mode only. */
@@ -99,11 +113,19 @@ type SelectCommonProps = {
99
113
  onCreate?: (label: string) => void;
100
114
  /** Overrides the default `Create "«query»"` row content. Popup mode only. */
101
115
  createLabel?: (query: string) => ReactNode;
116
+ /** When the Create row shows: only with zero matches (default), or whenever no option's label equals the query exactly. Popup mode only. */
117
+ createWhen?: "no-options" | "no-exact-match";
118
+ /** A persistent last row ("Add new…") shown whatever the filter; `onSelect` gets the trimmed query and the popup closes. Popup mode only. */
119
+ footerAction?: {
120
+ label: ReactNode;
121
+ onSelect: (query: string) => void;
122
+ icon?: ReactNode;
123
+ };
102
124
  /** Max popup height before the option list scrolls. Defaults to "16rem". Popup mode only. */
103
125
  maxMenuHeight?: string;
104
126
  /** Opens the popup on mount, for inline-edit cells. Popup mode only. */
105
127
  defaultOpen?: boolean;
106
- /** Windows the list once it holds more options than this. Off by default; ignored when any option has a `group`. */
128
+ /** Windows the list once it holds more options than this. Off by default; works with grouped options too. */
107
129
  virtualizeAfter?: number;
108
130
  };
109
131
  /** Single-select arm of `SelectFieldProps`; `isMulti` false/absent discriminates it from the multi variant. */
@@ -127,6 +149,12 @@ export type SelectMultiProps = SelectCommonProps & {
127
149
  maxVisibleChips?: number;
128
150
  /** Feeds the trigger's aria-label summary once chips collapse. Defaults to 2. */
129
151
  maxLabelsBeforeSummary?: number;
152
+ /** Truncates each chip label to this many characters, adding an ellipsis. */
153
+ chipMaxLength?: number;
154
+ /** Set false to hide the chips' remove (x) and disable Backspace-removal. Defaults to true. */
155
+ isChipRemovable?: boolean;
156
+ /** Adds a Select All / Unselect All row that toggles every enabled option the filter currently shows. */
157
+ isSelectAll?: boolean;
130
158
  };
131
159
  /** Props for the unified `Select` — a discriminated union on `isMulti` between the single and multi variants. */
132
160
  export type SelectFieldProps = SelectSingleProps | SelectMultiProps;
@@ -0,0 +1,21 @@
1
+ import type { OptionProp } from "./SelectProps";
2
+ export type GroupedRow = {
3
+ kind: "header";
4
+ key: string;
5
+ group: string;
6
+ } | {
7
+ kind: "option";
8
+ key: string | number;
9
+ option: OptionProp;
10
+ index: number;
11
+ };
12
+ export type GroupedLayout = {
13
+ tops: number[];
14
+ optionRows: number[];
15
+ };
16
+ export declare const buildGroupedRows: (options: OptionProp[]) => GroupedRow[];
17
+ export declare const layoutGroupedRows: (rows: GroupedRow[], headerPx: number, optionPx: number) => GroupedLayout;
18
+ export declare const groupedWindow: (tops: number[], scrollTop: number, viewportPx: number, overscan: number) => {
19
+ start: number;
20
+ end: number;
21
+ };
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.groupedWindow = exports.layoutGroupedRows = exports.buildGroupedRows = void 0;
4
+ const buildGroupedRows = (options) => {
5
+ const rows = [];
6
+ let currentGroup;
7
+ options.forEach((option, index) => {
8
+ if (option.group !== currentGroup) {
9
+ currentGroup = option.group;
10
+ if (option.group)
11
+ rows.push({ kind: "header", key: `group-${option.group}-${index}`, group: option.group });
12
+ }
13
+ rows.push({ kind: "option", key: option.id, option, index });
14
+ });
15
+ return rows;
16
+ };
17
+ exports.buildGroupedRows = buildGroupedRows;
18
+ const layoutGroupedRows = (rows, headerPx, optionPx) => {
19
+ const tops = new Array(rows.length + 1);
20
+ const optionRows = [];
21
+ let top = 0;
22
+ rows.forEach((row, i) => {
23
+ tops[i] = top;
24
+ if (row.kind === "option")
25
+ optionRows.push(i);
26
+ top += row.kind === "header" ? headerPx : optionPx;
27
+ });
28
+ tops[rows.length] = top;
29
+ return { tops, optionRows };
30
+ };
31
+ exports.layoutGroupedRows = layoutGroupedRows;
32
+ const firstIndex = (count, isBefore) => {
33
+ let lo = 0;
34
+ let hi = count;
35
+ while (lo < hi) {
36
+ const mid = (lo + hi) >> 1;
37
+ if (isBefore(mid))
38
+ lo = mid + 1;
39
+ else
40
+ hi = mid;
41
+ }
42
+ return lo;
43
+ };
44
+ const groupedWindow = (tops, scrollTop, viewportPx, overscan) => {
45
+ const count = tops.length - 1;
46
+ const first = firstIndex(count, (i) => tops[i + 1] <= scrollTop);
47
+ const last = firstIndex(count, (i) => tops[i] < scrollTop + viewportPx);
48
+ return { start: Math.max(0, first - overscan), end: Math.min(count, last + overscan) };
49
+ };
50
+ exports.groupedWindow = groupedWindow;
@@ -1,3 +1,3 @@
1
1
  import { SelectSearchProps } from "./SelectSearchProps";
2
- /** Prefer `Select` with `native={false}` for new work — not yet a drop-in; see select-absorption-spec.md. */
2
+ /** Prefer `Select` (`native={false}`): onOptionSelect→onChange, inputOnchange→onSearchChange, the footer row→footerAction. */
3
3
  export default function SelectSearch({ options, initialSelectedOption, onOptionSelect, inputOnchange, id, name, label, inputStyle, isOptionLoading, loadingText, boxStyle, placeholder, searchQuery, isInformation, informationMessage, rightIcon, rightElementStyle, isMultipleSelect, isRequired, onOptionMultiSelect, error, isProfile, isBottomIcon, errorMessage, helperText, size, BottomIcon, BottomText, handleBottomClick, BottomTextColor, isColorOptions, }: Readonly<SelectSearchProps>): import("react/jsx-runtime").JSX.Element;