pixelize-design-library 2.4.2-beta.64 → 2.4.2-beta.66

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 (517) hide show
  1. package/CHANGELOG.md +520 -21
  2. package/COMPONENT-GOTCHAS.md +187 -95
  3. package/DESIGN-GUIDE.md +54 -10
  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 +4 -1
  56. package/dist/Components/CopyButton/CopyButton.js +5 -8
  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 +3 -1
  73. package/dist/Components/Drawer/Drawer.js +28 -26
  74. package/dist/Components/Drawer/DrawerProps.d.ts +4 -0
  75. package/dist/Components/Dropdown/DropDown.js +6 -21
  76. package/dist/Components/Editor/Editor.js +6 -2
  77. package/dist/Components/Editor/EditorProps.d.ts +17 -1
  78. package/dist/Components/Editor/editorLabels.js +1 -0
  79. package/dist/Components/Editor/editorTokenStyles.d.ts +8 -0
  80. package/dist/Components/Editor/editorTokenStyles.js +9 -1
  81. package/dist/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.d.ts +1 -1
  82. package/dist/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.js +9 -2
  83. package/dist/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtpProps.d.ts +15 -1
  84. package/dist/Components/EmptyState/EmptyStateProps.d.ts +21 -0
  85. package/dist/Components/EmptyState/FilteredEmptyState.d.ts +5 -0
  86. package/dist/Components/EmptyState/FilteredEmptyState.js +23 -0
  87. package/dist/Components/FieldSelectModal/FieldSelectModal.d.ts +1 -0
  88. package/dist/Components/FilePreview/FilePreview.js +7 -3
  89. package/dist/Components/FilePreview/FilePreviewProps.d.ts +2 -1
  90. package/dist/Components/FileUpload/FileUpload.js +8 -9
  91. package/dist/Components/FileUpload/FileUploadProps.d.ts +2 -2
  92. package/dist/Components/FileUploader/FileUploader.js +5 -6
  93. package/dist/Components/FilterSidebar/FilterSidebar.d.ts +7 -9
  94. package/dist/Components/FilterSidebar/FilterSidebar.js +90 -233
  95. package/dist/Components/FilterSidebar/OptionsSection.d.ts +14 -0
  96. package/dist/Components/FilterSidebar/OptionsSection.js +46 -0
  97. package/dist/Components/FilterSidebar/RangeSection.d.ts +17 -0
  98. package/dist/Components/FilterSidebar/RangeSection.js +80 -0
  99. package/dist/Components/FilterSidebar/SectionHeader.d.ts +13 -0
  100. package/dist/Components/FilterSidebar/SectionHeader.js +29 -0
  101. package/dist/Components/FilterSidebar/useStableCallback.d.ts +1 -0
  102. package/dist/Components/FilterSidebar/useStableCallback.js +12 -0
  103. package/dist/Components/Form/FormWrapper.d.ts +7 -7
  104. package/dist/Components/Form/FormWrapper.js +5 -3
  105. package/dist/Components/FormDrawer/FormDrawer.d.ts +1 -1
  106. package/dist/Components/FormDrawer/FormDrawer.js +3 -3
  107. package/dist/Components/FormDrawer/FormDrawerProps.d.ts +2 -0
  108. package/dist/Components/FormField/FormField.js +1 -1
  109. package/dist/Components/Header/Header.js +1 -1
  110. package/dist/Components/Header/HeaderActions.js +4 -2
  111. package/dist/Components/IconButton/IconButtonProps.d.ts +2 -1
  112. package/dist/Components/Input/TextInput.js +2 -2
  113. package/dist/Components/Input/TextInputProps.d.ts +3 -1
  114. package/dist/Components/KanbanBoard/AccountCard.js +1 -1
  115. package/dist/Components/KanbanBoard/KanbanBoard.d.ts +1 -1
  116. package/dist/Components/KanbanBoard/KanbanBoard.js +11 -7
  117. package/dist/Components/LauncherTrigger/LauncherTrigger.js +1 -1
  118. package/dist/Components/LazyWrapper/LazyWrapper.d.ts +2 -1
  119. package/dist/Components/LazyWrapper/LazyWrapper.js +1 -1
  120. package/dist/Components/MediaViewer/MediaViewer.js +4 -3
  121. package/dist/Components/MediaViewer/components/MediaAudioPlayer.js +5 -1
  122. package/dist/Components/MediaViewer/components/MediaImageViewer.js +19 -8
  123. package/dist/Components/MediaViewer/components/MediaScrubber.js +7 -2
  124. package/dist/Components/MediaViewer/components/MediaVideoPlayer.js +3 -1
  125. package/dist/Components/MediaViewer/components/ViewerIconButton.js +3 -1
  126. package/dist/Components/MediaViewer/hooks/useFileViewer.d.ts +1 -0
  127. package/dist/Components/MediaViewer/mediaItems.d.ts +1 -0
  128. package/dist/Components/MediaViewer/mediaItems.js +5 -0
  129. package/dist/Components/Modal/Modal.d.ts +1 -0
  130. package/dist/Components/Modal/Modal.js +7 -25
  131. package/dist/Components/Modal/dialogNaming.d.ts +8 -0
  132. package/dist/Components/Modal/dialogNaming.js +21 -0
  133. package/dist/Components/Modal/warnDroppedSlotChildren.d.ts +1 -1
  134. package/dist/Components/Modal/warnDroppedSlotChildren.js +7 -3
  135. package/dist/Components/NavLauncher/LauncherTabs.js +4 -3
  136. package/dist/Components/NavLauncher/NavLauncher.d.ts +1 -1
  137. package/dist/Components/NavLauncher/NavLauncher.js +288 -56
  138. package/dist/Components/NavLauncher/NavLauncherProps.d.ts +83 -5
  139. package/dist/Components/NavLauncher/ScopeBar.d.ts +14 -0
  140. package/dist/Components/NavLauncher/ScopeBar.js +139 -0
  141. package/dist/Components/NavLauncher/engine/distance.d.ts +4 -0
  142. package/dist/Components/NavLauncher/engine/distance.js +41 -0
  143. package/dist/Components/NavLauncher/engine/engine.d.ts +84 -0
  144. package/dist/Components/NavLauncher/engine/engine.js +472 -0
  145. package/dist/Components/NavLauncher/engine/fold.d.ts +15 -0
  146. package/dist/Components/NavLauncher/engine/fold.js +84 -0
  147. package/dist/Components/NavLauncher/engine/index.d.ts +21 -0
  148. package/dist/Components/NavLauncher/engine/index.js +17 -0
  149. package/dist/Components/NavLauncher/launcherParts.d.ts +14 -0
  150. package/dist/Components/NavLauncher/launcherParts.js +51 -13
  151. package/dist/Components/NavLauncher/match.d.ts +13 -2
  152. package/dist/Components/NavLauncher/match.js +26 -12
  153. package/dist/Components/NavLauncher/searchLayout.d.ts +61 -0
  154. package/dist/Components/NavLauncher/searchLayout.js +110 -0
  155. package/dist/Components/NavLauncher/spotlight.d.ts +39 -0
  156. package/dist/Components/NavLauncher/spotlight.js +202 -0
  157. package/dist/Components/NavLauncher/spotlightParts.d.ts +53 -0
  158. package/dist/Components/NavLauncher/spotlightParts.js +121 -0
  159. package/dist/Components/NavLauncher/useCopiedFlash.d.ts +6 -0
  160. package/dist/Components/NavLauncher/useCopiedFlash.js +21 -0
  161. package/dist/Components/NavigationBar/NavigationBar.js +6 -5
  162. package/dist/Components/NoteTextArea/NoteTextArea.js +12 -17
  163. package/dist/Components/NoteTextArea/NoteTextAreaProps.d.ts +5 -3
  164. package/dist/Components/Notification/Notification.js +19 -21
  165. package/dist/Components/Notification/NotificationProps.d.ts +1 -1
  166. package/dist/Components/NotificationBell/notificationHelpers.d.ts +16 -1
  167. package/dist/Components/NotificationBell/notificationHelpers.js +13 -7
  168. package/dist/Components/OffersList/OffersList.js +4 -2
  169. package/dist/Components/OptionChip/OptionChip.js +3 -2
  170. package/dist/Components/OptionChip/optionInk.js +4 -2
  171. package/dist/Components/OrderStatusTimeline/OrderStatusTimeline.js +2 -1
  172. package/dist/Components/OrgSwitcher/OrgSwitcher.js +13 -6
  173. package/dist/Components/OrgSwitcher/OrgSwitcherProps.d.ts +1 -1
  174. package/dist/Components/OrganizationDetails/OrganizationDetails.js +4 -7
  175. package/dist/Components/OrganizationDetails/OrganizationDetailsProps.d.ts +4 -2
  176. package/dist/Components/PdfViewer/PdfViewer.d.ts +1 -0
  177. package/dist/Components/PlanBadge/PlanBadgeProps.d.ts +1 -1
  178. package/dist/Components/PlanPill/PlanPill.js +4 -2
  179. package/dist/Components/PlanPill/PlanPillProps.d.ts +1 -1
  180. package/dist/Components/ProductCard/ProductCardAction.js +2 -1
  181. package/dist/Components/ProductCard/ProductCardSwatches.js +2 -1
  182. package/dist/Components/ProductDetails/ProductDetails.js +2 -1
  183. package/dist/Components/ProfileCard/ProfileCard.d.ts +1 -0
  184. package/dist/Components/ProfileCard/ProfileCard.js +12 -26
  185. package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +4 -2
  186. package/dist/Components/ProgressBar/ProgressBar.js +2 -1
  187. package/dist/Components/QuantityStepper/QuantityStepper.js +5 -2
  188. package/dist/Components/QueryState/QueryStateBoundary.d.ts +1 -1
  189. package/dist/Components/QueryState/QueryStateBoundary.js +5 -1
  190. package/dist/Components/QueryState/QueryStateProps.d.ts +6 -2
  191. package/dist/Components/RadioButton/RadioButton.js +2 -3
  192. package/dist/Components/RolesPermission/RolesPermission.js +12 -8
  193. package/dist/Components/ScrollToTop/ScrollToTop.d.ts +1 -0
  194. package/dist/Components/ScrollbarBox/ScrollbarBox.d.ts +4 -1
  195. package/dist/Components/ScrollbarBox/ScrollbarBox.js +10 -4
  196. package/dist/Components/SearchSelect/SearchSelect.d.ts +1 -1
  197. package/dist/Components/SearchSelect/SearchSelect.js +8 -5
  198. package/dist/Components/SearchSelect/SearchSelectProps.d.ts +3 -3
  199. package/dist/Components/SegmentedControl/SegmentedControl.d.ts +1 -1
  200. package/dist/Components/SegmentedControl/SegmentedControl.js +1 -1
  201. package/dist/Components/Select/Select.js +6 -0
  202. package/dist/Components/Select/SelectNative.d.ts +16 -0
  203. package/dist/Components/Select/SelectPopup.js +170 -63
  204. package/dist/Components/Select/SelectProps.d.ts +30 -2
  205. package/dist/Components/Select/groupedWindow.d.ts +21 -0
  206. package/dist/Components/Select/groupedWindow.js +50 -0
  207. package/dist/Components/SelectSearch/SelectSearch.d.ts +1 -1
  208. package/dist/Components/SelectSearch/SelectSearch.js +48 -38
  209. package/dist/Components/SelectSearch/SelectSearchProps.d.ts +3 -3
  210. package/dist/Components/SelectV2/SelectV2.d.ts +1 -1
  211. package/dist/Components/SelectV2/SelectV2.js +1 -1
  212. package/dist/Components/SelectV2/SelectV2Props.d.ts +3 -3
  213. package/dist/Components/SideBar/SecondaryBar.js +3 -2
  214. package/dist/Components/SideBar/components/MenuItemBox.js +3 -2
  215. package/dist/Components/SideBar/components/MenuItems.js +1 -1
  216. package/dist/Components/SideBar/components/OtherApps.js +2 -2
  217. package/dist/Components/SideBar/components/PinnedSection.js +1 -1
  218. package/dist/Components/SideBar/sidebarScale.d.ts +2 -2
  219. package/dist/Components/SideBar/sidebarScale.js +2 -2
  220. package/dist/Components/SignInActivityTable/SignInActivityTable.js +7 -2
  221. package/dist/Components/SignInActivityTable/SignInActivityTableProps.d.ts +1 -1
  222. package/dist/Components/SignInActivityTable/scrollRegionRing.d.ts +10 -0
  223. package/dist/Components/SignInActivityTable/scrollRegionRing.js +14 -0
  224. package/dist/Components/Skeletons/SkeletonProps.d.ts +5 -1
  225. package/dist/Components/Slider/Slider.d.ts +2 -0
  226. package/dist/Components/Slider/Slider.js +5 -4
  227. package/dist/Components/StageProgress/StageItem.js +2 -1
  228. package/dist/Components/StageProgress/StageProgress.js +8 -2
  229. package/dist/Components/StageProgress/StageProgressProps.d.ts +2 -0
  230. package/dist/Components/StageProgress/StepperStage.js +2 -1
  231. package/dist/Components/StickyBuyBar/StickyBuyBar.js +2 -1
  232. package/dist/Components/Table/Table.js +5 -3
  233. package/dist/Components/Table/components/HeaderActions.js +5 -3
  234. package/dist/Components/Table/components/TableBody.js +13 -8
  235. package/dist/Components/Table/components/TableGroupRow.js +2 -1
  236. package/dist/Components/Table/components/TableHeader.js +17 -21
  237. package/dist/Components/Table/components/TableLoading.js +8 -2
  238. package/dist/Components/Table/components/rowDetail.js +3 -2
  239. package/dist/Components/Table/filters/ActiveFilters.js +6 -3
  240. package/dist/Components/Table/filters/CompactSelect.js +2 -1
  241. package/dist/Components/Table/filters/FilterDatePicker.d.ts +6 -0
  242. package/dist/Components/Table/filters/FilterDatePicker.js +61 -0
  243. package/dist/Components/Table/filters/LeftFilterPane.d.ts +1 -0
  244. package/dist/Components/Table/filters/LeftFilterPane.js +14 -6
  245. package/dist/Components/Table/hooks/useTable.js +11 -7
  246. package/dist/Components/Table/settings/ManageColumns.js +4 -3
  247. package/dist/Components/Table/settings/TableSettings.js +4 -4
  248. package/dist/Components/Tabs/Tabs.d.ts +1 -0
  249. package/dist/Components/Tabs/Tabs.js +1 -0
  250. package/dist/Components/Tabs/components/CountBadge.d.ts +1 -0
  251. package/dist/Components/Tabs/components/TabList.d.ts +1 -0
  252. package/dist/Components/Tabs/components/TabList.js +1 -0
  253. package/dist/Components/Tabs/components/TabPanel.d.ts +1 -0
  254. package/dist/Components/Tabs/components/TabPanel.js +1 -0
  255. package/dist/Components/Tabs/tabStyles.js +4 -2
  256. package/dist/Components/Tag/Tag.js +5 -4
  257. package/dist/Components/Tag/Tag.styles.js +5 -4
  258. package/dist/Components/Tag/TagProps.d.ts +4 -1
  259. package/dist/Components/Tag/tagDot.js +10 -3
  260. package/dist/Components/TagInput/TagInput.js +6 -5
  261. package/dist/Components/TagInput/TagInputProps.d.ts +15 -0
  262. package/dist/Components/TagInput/tagEntries.d.ts +7 -1
  263. package/dist/Components/TagInput/tagEntries.js +18 -5
  264. package/dist/Components/TimePicker/TimePicker.js +7 -3
  265. package/dist/Components/TimePicker/TimePickerProps.d.ts +2 -0
  266. package/dist/Components/Timeline/Timeline.js +13 -9
  267. package/dist/Components/Toaster/Toaster.js +2 -1
  268. package/dist/Components/Toggle/TableToggle.d.ts +1 -1
  269. package/dist/Components/Toggle/TableToggle.js +1 -1
  270. package/dist/Components/UpgradeButton/UpgradeButton.js +3 -2
  271. package/dist/Components/UpgradeButton/UpgradeButtonProps.d.ts +1 -1
  272. package/dist/Components/UserDetails/UserDetails.js +5 -7
  273. package/dist/Components/WishlistToggle/WishlistToggle.js +2 -1
  274. package/dist/Components/WizardDialog/WizardDialog.d.ts +1 -1
  275. package/dist/Components/WizardDialog/WizardDialog.js +15 -3
  276. package/dist/Components/WizardDialog/WizardDialogProps.d.ts +5 -3
  277. package/dist/Components/WorkspaceWindow/WorkspaceTrayPreview.js +11 -1
  278. package/dist/Components/WorkspaceWindow/WorkspaceWindow.js +6 -3
  279. package/dist/Components/WorkspaceWindow/WorkspaceWindowProps.d.ts +16 -15
  280. package/dist/Hooks/useOutsideMouseDown.d.ts +11 -0
  281. package/dist/Hooks/useOutsideMouseDown.js +30 -0
  282. package/dist/Hooks/usePreferences.js +30 -12
  283. package/dist/Hooks/useScrollableRegion.d.ts +17 -0
  284. package/dist/Hooks/useScrollableRegion.js +36 -0
  285. package/dist/Hooks/useSidebarPrefs.d.ts +1 -0
  286. package/dist/Theme/chakra/Menu.styles.d.ts +4 -0
  287. package/dist/Theme/chakra/Menu.styles.js +6 -0
  288. package/dist/Theme/chakra/componentStyles.d.ts +4 -0
  289. package/dist/Theme/chakra/componentStyles.js +1 -1
  290. package/dist/Theme/chakra/createBrandTheme.d.ts +1 -0
  291. package/dist/Theme/chakra/focusRing.styles.d.ts +1 -1
  292. package/dist/Theme/chakra/focusRing.styles.js +3 -3
  293. package/dist/Theme/chakra/paletteFromTheme.d.ts +2 -1
  294. package/dist/Theme/chakra/paletteFromTheme.js +18 -4
  295. package/dist/Theme/chakra/ringShadow.d.ts +3 -0
  296. package/dist/Theme/chakra/ringShadow.js +7 -0
  297. package/dist/Theme/provider/PixelizeThemeProvider.d.ts +1 -0
  298. package/dist/Theme/provider/ThemeSwitcher.d.ts +1 -0
  299. package/dist/Theme/provider/ThemeSwitcher.js +1 -1
  300. package/dist/Theme/testing/testPalette.d.ts +1 -0
  301. package/dist/Theme/tokens/builders/buildDarkPalette.d.ts +2 -1
  302. package/dist/Theme/tokens/builders/buildDarkPalette.js +5 -5
  303. package/dist/Theme/tokens/builders/filledSurface.js +3 -2
  304. package/dist/Theme/tokens/builders/focusRing.js +4 -1
  305. package/dist/Theme/tokens/builders/paletteScale.d.ts +2 -0
  306. package/dist/Theme/tokens/builders/paletteScale.js +10 -0
  307. package/dist/Theme/tokens/types.d.ts +1 -0
  308. package/dist/Utils/accountHandoff.d.ts +3 -0
  309. package/dist/Utils/price.d.ts +1 -0
  310. package/dist/Utils/tabular.d.ts +30 -0
  311. package/dist/Utils/tabular.js +61 -0
  312. package/dist/esm/Components/Accordion/Accordion.js +11 -8
  313. package/dist/esm/Components/Accordion/accordionColors.js +2 -3
  314. package/dist/esm/Components/Apexcharts/ApexLineChart/ApexLineChart.js +2 -1
  315. package/dist/esm/Components/Apexcharts/ApexPieChart/ApexPieChart.js +6 -5
  316. package/dist/esm/Components/Apexcharts/ApexPieChart/pieImageTexture.js +10 -0
  317. package/dist/esm/Components/AppSwitcher/AppSwitcher.js +6 -3
  318. package/dist/esm/Components/AppSwitcher/AppSwitcherProps.js +18 -11
  319. package/dist/esm/Components/AppSwitcher/pixelizeSuite.js +67 -0
  320. package/dist/esm/Components/AppearanceSettings/AppearanceSettings.js +3 -3
  321. package/dist/esm/Components/Avatar/avatarColorway.js +4 -4
  322. package/dist/esm/Components/Button/Button.styles.js +5 -2
  323. package/dist/esm/Components/ButtonGroupIcon/ButtonGroupIcon.js +3 -1
  324. package/dist/esm/Components/CalendarGrid/CalendarGrid.js +5 -3
  325. package/dist/esm/Components/Card/Card.js +1 -0
  326. package/dist/esm/Components/Checkbox/Checkbox.styles.js +3 -1
  327. package/dist/esm/Components/CheckoutKit/selectable.js +10 -7
  328. package/dist/esm/Components/CheckoutKit/tonalHover.js +2 -0
  329. package/dist/esm/Components/ChoiceCard/ChoiceCard.js +2 -1
  330. package/dist/esm/Components/Common/FormLabel.js +4 -3
  331. package/dist/esm/Components/Common/HelperText.js +1 -2
  332. package/dist/esm/Components/Common/activationKey.js +7 -0
  333. package/dist/esm/Components/Common/fieldMessageStyles.js +2 -1
  334. package/dist/esm/Components/Common/findSlot.js +17 -0
  335. package/dist/esm/Components/Common/surfaceFocusRing.js +3 -0
  336. package/dist/esm/Components/ConfirmDialog/ConfirmDialog.js +18 -6
  337. package/dist/esm/Components/CopyButton/CopyButton.js +5 -8
  338. package/dist/esm/Components/CouponField/CouponField.js +5 -2
  339. package/dist/esm/Components/CustomModulesTable/CustomModulesTable.js +3 -1
  340. package/dist/esm/Components/DatePicker/CalendarPanel.js +3 -1
  341. package/dist/esm/Components/DatePicker/DatePicker.js +25 -27
  342. package/dist/esm/Components/DatePicker/PickerPortal.js +2 -2
  343. package/dist/esm/Components/DatePicker/RangeDatePicker.js +10 -29
  344. package/dist/esm/Components/DatePicker/SingleDatePicker.js +5 -21
  345. package/dist/esm/Components/DatePicker/TimeOnlyPicker.js +2 -20
  346. package/dist/esm/Components/DescriptionList/DescriptionList.js +1 -1
  347. package/dist/esm/Components/DetailSections/DetailSections.js +2 -1
  348. package/dist/esm/Components/Divider/Divider.js +3 -3
  349. package/dist/esm/Components/Drawer/Drawer.js +24 -19
  350. package/dist/esm/Components/Dropdown/DropDown.js +7 -22
  351. package/dist/esm/Components/Editor/Editor.js +7 -3
  352. package/dist/esm/Components/Editor/editorLabels.js +1 -0
  353. package/dist/esm/Components/Editor/editorTokenStyles.js +7 -0
  354. package/dist/esm/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.js +8 -4
  355. package/dist/esm/Components/EmptyState/FilteredEmptyState.js +18 -0
  356. package/dist/esm/Components/FilePreview/FilePreview.js +8 -4
  357. package/dist/esm/Components/FileUpload/FileUpload.js +8 -9
  358. package/dist/esm/Components/FileUploader/FileUploader.js +6 -7
  359. package/dist/esm/Components/FilterSidebar/FilterSidebar.js +94 -237
  360. package/dist/esm/Components/FilterSidebar/OptionsSection.js +41 -0
  361. package/dist/esm/Components/FilterSidebar/RangeSection.js +78 -0
  362. package/dist/esm/Components/FilterSidebar/SectionHeader.js +23 -0
  363. package/dist/esm/Components/FilterSidebar/useStableCallback.js +8 -0
  364. package/dist/esm/Components/Form/FormWrapper.js +5 -3
  365. package/dist/esm/Components/FormDrawer/FormDrawer.js +3 -3
  366. package/dist/esm/Components/FormField/FormField.js +1 -1
  367. package/dist/esm/Components/Header/Header.js +1 -1
  368. package/dist/esm/Components/Header/HeaderActions.js +6 -4
  369. package/dist/esm/Components/Input/TextInput.js +2 -2
  370. package/dist/esm/Components/KanbanBoard/AccountCard.js +1 -1
  371. package/dist/esm/Components/KanbanBoard/KanbanActions/KanbanActions.js +2 -2
  372. package/dist/esm/Components/KanbanBoard/KanbanBoard.js +11 -7
  373. package/dist/esm/Components/LauncherTrigger/LauncherTrigger.js +1 -1
  374. package/dist/esm/Components/LazyWrapper/LazyWrapper.js +1 -1
  375. package/dist/esm/Components/MediaViewer/MediaViewer.js +5 -4
  376. package/dist/esm/Components/MediaViewer/components/MediaAudioPlayer.js +5 -1
  377. package/dist/esm/Components/MediaViewer/components/MediaImageViewer.js +19 -8
  378. package/dist/esm/Components/MediaViewer/components/MediaScrubber.js +7 -2
  379. package/dist/esm/Components/MediaViewer/components/MediaVideoPlayer.js +3 -1
  380. package/dist/esm/Components/MediaViewer/components/ViewerIconButton.js +3 -1
  381. package/dist/esm/Components/MediaViewer/mediaItems.js +4 -0
  382. package/dist/esm/Components/Modal/Modal.js +2 -17
  383. package/dist/esm/Components/Modal/dialogNaming.js +18 -0
  384. package/dist/esm/Components/Modal/warnDroppedSlotChildren.js +7 -3
  385. package/dist/esm/Components/NavLauncher/LauncherTabs.js +4 -3
  386. package/dist/esm/Components/NavLauncher/NavLauncher.js +291 -59
  387. package/dist/esm/Components/NavLauncher/ScopeBar.js +136 -0
  388. package/dist/esm/Components/NavLauncher/engine/distance.js +37 -0
  389. package/dist/esm/Components/NavLauncher/engine/engine.js +459 -0
  390. package/dist/esm/Components/NavLauncher/engine/fold.js +75 -0
  391. package/dist/esm/Components/NavLauncher/engine/index.js +14 -0
  392. package/dist/esm/Components/NavLauncher/launcherParts.js +46 -10
  393. package/dist/esm/Components/NavLauncher/match.js +25 -12
  394. package/dist/esm/Components/NavLauncher/searchLayout.js +101 -0
  395. package/dist/esm/Components/NavLauncher/spotlight.js +194 -0
  396. package/dist/esm/Components/NavLauncher/spotlightParts.js +108 -0
  397. package/dist/esm/Components/NavLauncher/useCopiedFlash.js +17 -0
  398. package/dist/esm/Components/NavigationBar/NavigationBar.js +6 -5
  399. package/dist/esm/Components/NoteTextArea/NoteTextArea.js +12 -17
  400. package/dist/esm/Components/Notification/Notification.js +20 -22
  401. package/dist/esm/Components/NotificationBell/notificationHelpers.js +12 -6
  402. package/dist/esm/Components/OffersList/OffersList.js +4 -2
  403. package/dist/esm/Components/OptionChip/OptionChip.js +3 -2
  404. package/dist/esm/Components/OptionChip/optionInk.js +4 -2
  405. package/dist/esm/Components/OrderStatusTimeline/OrderStatusTimeline.js +2 -1
  406. package/dist/esm/Components/OrgSwitcher/OrgSwitcher.js +14 -7
  407. package/dist/esm/Components/OrganizationDetails/OrganizationDetails.js +5 -8
  408. package/dist/esm/Components/PlanPill/PlanPill.js +4 -2
  409. package/dist/esm/Components/ProductCard/ProductCardAction.js +2 -1
  410. package/dist/esm/Components/ProductCard/ProductCardSwatches.js +2 -1
  411. package/dist/esm/Components/ProductDetails/ProductDetails.js +2 -1
  412. package/dist/esm/Components/ProfileCard/ProfileCard.js +6 -17
  413. package/dist/esm/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +4 -2
  414. package/dist/esm/Components/ProgressBar/ProgressBar.js +2 -1
  415. package/dist/esm/Components/QuantityStepper/QuantityStepper.js +5 -2
  416. package/dist/esm/Components/QueryState/QueryStateBoundary.js +5 -1
  417. package/dist/esm/Components/RadioButton/RadioButton.js +2 -3
  418. package/dist/esm/Components/RolesPermission/RolesPermission.js +12 -8
  419. package/dist/esm/Components/ScrollbarBox/ScrollbarBox.js +9 -3
  420. package/dist/esm/Components/SearchSelect/SearchSelect.js +8 -5
  421. package/dist/esm/Components/SegmentedControl/SegmentedControl.js +1 -1
  422. package/dist/esm/Components/Select/Select.js +6 -0
  423. package/dist/esm/Components/Select/SelectPopup.js +171 -64
  424. package/dist/esm/Components/Select/groupedWindow.js +44 -0
  425. package/dist/esm/Components/SelectSearch/SelectSearch.js +49 -39
  426. package/dist/esm/Components/SelectV2/SelectV2.js +1 -1
  427. package/dist/esm/Components/SideBar/SecondaryBar.js +3 -2
  428. package/dist/esm/Components/SideBar/components/MenuItemBox.js +3 -2
  429. package/dist/esm/Components/SideBar/components/MenuItems.js +1 -1
  430. package/dist/esm/Components/SideBar/components/OtherApps.js +2 -2
  431. package/dist/esm/Components/SideBar/components/PinnedSection.js +1 -1
  432. package/dist/esm/Components/SideBar/sidebarScale.js +2 -2
  433. package/dist/esm/Components/SignInActivityTable/SignInActivityTable.js +8 -3
  434. package/dist/esm/Components/SignInActivityTable/scrollRegionRing.js +9 -0
  435. package/dist/esm/Components/Slider/Slider.js +6 -5
  436. package/dist/esm/Components/StageProgress/StageItem.js +2 -1
  437. package/dist/esm/Components/StageProgress/StageProgress.js +8 -2
  438. package/dist/esm/Components/StageProgress/StepperStage.js +2 -1
  439. package/dist/esm/Components/StickyBuyBar/StickyBuyBar.js +2 -1
  440. package/dist/esm/Components/Table/Table.js +8 -6
  441. package/dist/esm/Components/Table/components/HeaderActions.js +7 -5
  442. package/dist/esm/Components/Table/components/TableBody.js +13 -8
  443. package/dist/esm/Components/Table/components/TableGroupRow.js +2 -1
  444. package/dist/esm/Components/Table/components/TableHeader.js +19 -23
  445. package/dist/esm/Components/Table/components/TableLoading.js +6 -3
  446. package/dist/esm/Components/Table/components/rowDetail.js +3 -2
  447. package/dist/esm/Components/Table/filters/ActiveFilters.js +8 -5
  448. package/dist/esm/Components/Table/filters/CompactSelect.js +2 -1
  449. package/dist/esm/Components/Table/filters/FilterDatePicker.js +20 -0
  450. package/dist/esm/Components/Table/filters/LeftFilterPane.js +14 -6
  451. package/dist/esm/Components/Table/hooks/useTable.js +11 -7
  452. package/dist/esm/Components/Table/settings/ManageColumns.js +4 -3
  453. package/dist/esm/Components/Table/settings/TableSettings.js +4 -4
  454. package/dist/esm/Components/Tabs/Tabs.js +1 -0
  455. package/dist/esm/Components/Tabs/components/TabList.js +1 -0
  456. package/dist/esm/Components/Tabs/components/TabPanel.js +1 -0
  457. package/dist/esm/Components/Tabs/tabStyles.js +5 -3
  458. package/dist/esm/Components/Tag/Tag.js +5 -4
  459. package/dist/esm/Components/Tag/Tag.styles.js +5 -4
  460. package/dist/esm/Components/Tag/tagDot.js +10 -3
  461. package/dist/esm/Components/TagInput/TagInput.js +8 -7
  462. package/dist/esm/Components/TagInput/tagEntries.js +16 -4
  463. package/dist/esm/Components/TimePicker/TimePicker.js +7 -3
  464. package/dist/esm/Components/Timeline/Timeline.js +14 -10
  465. package/dist/esm/Components/Toaster/Toaster.js +2 -1
  466. package/dist/esm/Components/Toggle/TableToggle.js +1 -1
  467. package/dist/esm/Components/UpgradeButton/UpgradeButton.js +3 -2
  468. package/dist/esm/Components/UserDetails/UserDetails.js +5 -7
  469. package/dist/esm/Components/WishlistToggle/WishlistToggle.js +2 -1
  470. package/dist/esm/Components/WizardDialog/WizardDialog.js +15 -3
  471. package/dist/esm/Components/WorkspaceWindow/WorkspaceTrayPreview.js +12 -2
  472. package/dist/esm/Components/WorkspaceWindow/WorkspaceWindow.js +7 -4
  473. package/dist/esm/Hooks/useOutsideMouseDown.js +26 -0
  474. package/dist/esm/Hooks/usePreferences.js +30 -12
  475. package/dist/esm/Hooks/useScrollableRegion.js +33 -0
  476. package/dist/esm/Theme/chakra/Menu.styles.js +6 -0
  477. package/dist/esm/Theme/chakra/componentStyles.js +1 -1
  478. package/dist/esm/Theme/chakra/focusRing.styles.js +3 -3
  479. package/dist/esm/Theme/chakra/paletteFromTheme.js +16 -3
  480. package/dist/esm/Theme/chakra/ringShadow.js +3 -0
  481. package/dist/esm/Theme/provider/ThemeSwitcher.js +1 -1
  482. package/dist/esm/Theme/tokens/builders/buildDarkPalette.js +5 -5
  483. package/dist/esm/Theme/tokens/builders/filledSurface.js +3 -2
  484. package/dist/esm/Theme/tokens/builders/focusRing.js +4 -1
  485. package/dist/esm/Theme/tokens/builders/paletteScale.js +6 -0
  486. package/dist/esm/Utils/tabular.js +56 -0
  487. package/dist/esm/index.js +18 -25
  488. package/dist/index.d.ts +59 -5
  489. package/dist/index.js +36 -29
  490. package/package.json +3 -1
  491. package/dist/Components/Buttons/Buttons.d.ts +0 -3
  492. package/dist/Components/Buttons/Buttons.js +0 -9
  493. package/dist/Components/Buttons/ButtonsProps.d.ts +0 -12
  494. package/dist/Components/Common/ErrorComponent.d.ts +0 -7
  495. package/dist/Components/Common/ErrorComponent.js +0 -16
  496. package/dist/Components/Common/FormattedDescription.d.ts +0 -7
  497. package/dist/Components/Common/FormattedDescription.js +0 -62
  498. package/dist/Components/Common/Label.d.ts +0 -9
  499. package/dist/Components/Common/Label.js +0 -12
  500. package/dist/Components/Input/Input/Input.d.ts +0 -4
  501. package/dist/Components/Input/Input/Input.js +0 -75
  502. package/dist/Components/Input/Input/InputProps.d.ts +0 -24
  503. package/dist/Components/Input/Input/InputProps.js +0 -2
  504. package/dist/Components/ProductCard/productCardFixtures.d.ts +0 -7
  505. package/dist/Components/ProductCard/productCardFixtures.js +0 -61
  506. package/dist/esm/Components/Buttons/Buttons.js +0 -4
  507. package/dist/esm/Components/Common/ErrorComponent.js +0 -14
  508. package/dist/esm/Components/Common/FormattedDescription.js +0 -60
  509. package/dist/esm/Components/Common/Label.js +0 -10
  510. package/dist/esm/Components/Input/Input/Input.js +0 -37
  511. package/dist/esm/Components/Input/Input/InputProps.js +0 -1
  512. package/dist/esm/Components/ProductCard/productCardFixtures.js +0 -58
  513. package/dist/esm/services/feedback.js +0 -15
  514. package/dist/services/feedback.d.ts +0 -12
  515. package/dist/services/feedback.js +0 -18
  516. /package/dist/Components/{Buttons/ButtonsProps.js → Common/dataAttributes.js} +0 -0
  517. /package/dist/esm/Components/{Buttons/ButtonsProps.js → Common/dataAttributes.js} +0 -0
@@ -11,6 +11,7 @@ import { motionTransition, transitionFor } from "../../Theme/tokens/primitives/m
11
11
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
12
12
  import { resolveSoftTone } from "../../Theme/tokens/builders/tone.js";
13
13
  import { compositeOver } from "../../Theme/tokens/builders/color.js";
14
+ import { BORDER_WIDTHS } from "../../Theme/tokens/primitives/borderWidths.js";
14
15
  const ToasterContext = createContext(undefined);
15
16
  const shrink = keyframes `
16
17
  from { transform: scaleX(1); }
@@ -36,7 +37,7 @@ function ToastCard({ onClose, title, description, actions, isClosable, duration,
36
37
  , {
37
38
  // The single live-region root: an explicit aria-live here, on the card's own
38
39
  // root, keeps errors from being announced a second time by a duplicate wrapper.
39
- role: isUrgent ? "alert" : undefined, "aria-live": isUrgent ? "assertive" : undefined, initial: { opacity: 0, x: 24 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: 24, transition: TOAST_EXIT }, transition: TOAST_ENTER, onHoverStart: () => setPaused(true), onHoverEnd: () => setPaused(false), position: "relative", bg: c.surfaceRaised, border: `0.0625rem solid ${c.boxborder[200]}`, boxShadow: "md", borderRadius: "xl", overflow: "hidden", minW: "22.5rem", maxW: "26rem", sx: {
40
+ role: isUrgent ? "alert" : undefined, "aria-live": isUrgent ? "assertive" : undefined, initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0, transition: TOAST_EXIT }, transition: TOAST_ENTER, onHoverStart: () => setPaused(true), onHoverEnd: () => setPaused(false), position: "relative", bg: c.surfaceRaised, border: `${BORDER_WIDTHS.hairline} solid ${c.boxborder[200]}`, boxShadow: "md", borderRadius: "xl", overflow: "hidden", minW: "22.5rem", maxW: "26rem", sx: {
40
41
  isolation: "isolate",
41
42
  transition: transitionFor(["box-shadow"]),
42
43
  _hover: { boxShadow: "lg" },
@@ -14,7 +14,7 @@ const TRACK_HEIGHT = BUTTON_SIZES.sm.height;
14
14
  const SEGMENT_HEIGHT = `calc(${TRACK_HEIGHT} - 0.25rem)`;
15
15
  const INK_TRANSITION = transitionFor(["color"], "base");
16
16
  const PILL_TRANSITION = transitionFor(["transform", "width"], "base", "out");
17
- /** Two icon-only IconButtons (Grid/List), aria-pressed marks the active one; shares variant with SegmentedControl (see MODULE.md). */
17
+ /** Two icon-only IconButtons (Grid/List), aria-pressed marks the active one; shares variant with SegmentedControl. */
18
18
  const TableToggle = ({ value, onChange, variant = "default" }) => {
19
19
  const theme = useCustomTheme();
20
20
  const { colors } = theme;
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Flex, Spinner, Text } from "@chakra-ui/react";
3
3
  import { Sparkles } from "lucide-react";
4
4
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
5
+ import { DISABLED_OPACITY } from "../../Theme/tokens/primitives/states.js";
5
6
  import { resolveGradient } from "../../Theme/tokens/builders/gradientInk.js";
6
7
  import { contrastRatio } from "../../Theme/tokens/builders/color.js";
7
8
  import { AA_NON_TEXT } from "../../Theme/tokens/builders/outlineRung.js";
@@ -45,7 +46,7 @@ const UpgradeButton = ({ label, mobileLabel, subtitle, icon = Sparkles, iconColo
45
46
  const g = `linear-gradient(135deg, ${resolved.from} 0%, ${resolved.to} 100%)`;
46
47
  const gReversed = `linear-gradient(135deg, ${resolved.to} 0%, ${resolved.from} 100%)`;
47
48
  const hasMobile = !!mobileLabel && mobileLabel !== label;
48
- return (_jsxs(Box, { as: "button", type: "button", "aria-label": ariaLabel || label, onClick: blocked ? undefined : onClick, disabled: isDisabled, position: "relative", cursor: blocked ? "default" : "pointer", opacity: isDisabled ? 0.6 : 1, px: { base: s.px === "20px" ? "14px" : s.px, md: s.px }, py: s.py, bgImage: g, color: ink, borderRadius: s.radius, fontWeight: 700, textAlign: "center", overflow: "hidden", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", transition: "transform 0.3s ease, box-shadow 0.3s ease, background-image 0.3s ease", _hover: blocked
49
+ return (_jsxs(Box, { as: "button", type: "button", "aria-label": ariaLabel, onClick: blocked ? undefined : onClick, disabled: isDisabled, position: "relative", cursor: blocked ? "default" : "pointer", opacity: isDisabled ? DISABLED_OPACITY : 1, px: { base: s.px === "20px" ? "14px" : s.px, md: s.px }, py: s.py, bgImage: g, color: ink, borderRadius: s.radius, fontWeight: 700, textAlign: "center", overflow: "hidden", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", transition: "transform 0.3s ease, box-shadow 0.3s ease, background-image 0.3s ease", _hover: blocked
49
50
  ? undefined
50
51
  : {
51
52
  transform: "translateY(-2px)",
@@ -69,6 +70,6 @@ const UpgradeButton = ({ label, mobileLabel, subtitle, icon = Sparkles, iconColo
69
70
  },
70
71
  ...reducedMotionSx({ "&::before": { transition: "none" } }),
71
72
  }
72
- : { ...focusVisibleStyles(c), ...reducedMotionSx() }, children: [_jsxs(Flex, { align: "center", gap: "6px", maxW: maxLabelWidth, overflow: "hidden", whiteSpace: "nowrap", zIndex: 1, children: [_jsx(Text, { as: "span", fontSize: s.font, overflow: "hidden", textOverflow: "ellipsis", display: hasMobile ? { base: "none", md: "block" } : "block", children: label }), hasMobile && (_jsx(Text, { as: "span", fontSize: s.font, overflow: "hidden", textOverflow: "ellipsis", display: { base: "block", md: "none" }, children: mobileLabel })), isLoading ? (_jsx(Spinner, { size: "xs", thickness: "1.5px", color: resolvedIconColor })) : (Icon && _jsx(Icon, { size: s.icon, color: resolvedIconColor, style: { flexShrink: 0 } }))] }), subtitle && (_jsx(Text, { as: "span", mt: "1px", fontSize: s.sub, fontWeight: 700, color: ink, maxW: maxLabelWidth, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", zIndex: 1, children: subtitle }))] }));
73
+ : { ...focusVisibleStyles(c), ...reducedMotionSx() }, children: [_jsxs(Flex, { align: "center", gap: "6px", maxW: maxLabelWidth, overflow: "hidden", whiteSpace: "nowrap", zIndex: 1, children: [_jsx(Text, { as: "span", fontSize: s.font, overflow: "hidden", textOverflow: "ellipsis", display: hasMobile ? { base: "none", md: "block" } : "block", children: label }), hasMobile && (_jsx(Text, { as: "span", fontSize: s.font, overflow: "hidden", textOverflow: "ellipsis", display: { base: "block", md: "none" }, children: mobileLabel })), isLoading ? (_jsx(Spinner, { size: "xs", thickness: "1.5px", color: resolvedIconColor, label: "" })) : (Icon && _jsx(Icon, { size: s.icon, color: resolvedIconColor, style: { flexShrink: 0 } }))] }), subtitle && (_jsx(Text, { as: "span", mt: "1px", fontSize: s.sub, fontWeight: 700, color: ink, maxW: maxLabelWidth, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", zIndex: 1, children: subtitle }))] }));
73
74
  };
74
75
  export default UpgradeButton;
@@ -14,6 +14,9 @@ import PersonChip from "../PersonChip/PersonChip.js";
14
14
  import AddUserModal from "./AddUserModal.js";
15
15
  import ChangeRoleModal from "./ChangeRoleModal.js";
16
16
  import DeactivateConfirmModal from "./DeactivateConfirmModal.js";
17
+ import { transitionFor } from "../../Theme/tokens/primitives/motion.js";
18
+ import { onActivationKey } from "../Common/activationKey.js";
19
+ const BACKGROUND_TRANSITION = transitionFor(["background"]);
17
20
  const DEFAULT_LABELS = {
18
21
  teamMembers: "Team Members",
19
22
  refreshList: "Refresh list",
@@ -79,12 +82,7 @@ const UserDetails = ({ users, selectedUser, selectedUserId, roleOptions = [], ca
79
82
  background: isSelected
80
83
  ? rowBackgrounds.selectedActive
81
84
  : rowBackgrounds.active,
82
- }, transition: "background 0.15s ease", borderRadius: "lg", position: "relative", role: "button", tabIndex: 0, "aria-current": isSelected ? true : undefined, _focusVisible: focusVisibleRing(colors), onClick: () => onSelectUser === null || onSelectUser === void 0 ? void 0 : onSelectUser(user), onKeyDown: (e) => {
83
- if (e.key !== "Enter" && e.key !== " ")
84
- return;
85
- e.preventDefault();
86
- onSelectUser === null || onSelectUser === void 0 ? void 0 : onSelectUser(user);
87
- }, children: [isSelected && (_jsx(Box, { position: "absolute", left: 0, top: "20%", bottom: "20%", width: "3px", borderRadius: "full", bg: colors.primary[500] })), _jsx(PersonChip, { size: "sm", name: `${user.firstName} ${user.lastName}`, imageUrl: user.profile, secondary: user.email }), renderStatusBadge(user.isActive)] }, user.id));
85
+ }, transition: BACKGROUND_TRANSITION, borderRadius: "lg", position: "relative", role: "button", tabIndex: 0, "aria-current": isSelected ? true : undefined, _focusVisible: focusVisibleRing(colors), onClick: () => onSelectUser === null || onSelectUser === void 0 ? void 0 : onSelectUser(user), onKeyDown: onActivationKey(() => onSelectUser === null || onSelectUser === void 0 ? void 0 : onSelectUser(user)), children: [isSelected && (_jsx(Box, { position: "absolute", left: 0, top: "20%", bottom: "20%", width: "3px", borderRadius: "full", bg: colors.primary[500] })), _jsx(PersonChip, { size: "sm", name: `${user.firstName} ${user.lastName}`, imageUrl: user.profile, secondary: user.email }), renderStatusBadge(user.isActive)] }, user.id));
88
86
  }) })) })] }), _jsxs(Box, { flex: 1, backgroundColor: surface, borderRadius: "xl", boxShadow: "sm", border: "1px solid", borderColor: border, display: "flex", flexDirection: "column", order: { base: 1, lg: 2 }, overflow: "hidden", children: [_jsxs(Flex, { justifyContent: "space-between", alignItems: "center", px: 4, py: 3, borderBottom: "1px solid", borderColor: border, children: [_jsx(Heading, { size: "sm", fontWeight: 600, color: heading, children: selectedUser ? labels.userDetails : labels.selectTeamMember }), canManageUsers && (_jsx(Button, { size: "sm", colorScheme: "primary", fontSize: "xs", leftIcon: _jsx(UserPlus, { size: 15 }), onClick: onAddUserOpen, children: labels.addUser }))] }), _jsx(Box, { flex: 1, overflowY: "auto", tabIndex: 0, role: "region", "aria-label": selectedUser ? labels.userDetails : labels.selectTeamMember, children: isUsersLoading ? (_jsxs(VStack, { spacing: 4, p: 4, align: "stretch", children: [_jsxs(Flex, { align: "center", gap: 4, children: [_jsx(SkeletonCircle, { size: "16" }), _jsxs(Box, { flex: 1, children: [_jsx(Skeleton, { height: "18px", width: "50%", mb: 2 }), _jsx(Skeleton, { height: "12px", width: "35%" })] })] }), Array.from({ length: 4 }).map((_, idx) => (_jsxs(Box, { w: "100%", children: [_jsx(Skeleton, { height: "12px", width: "30%", mb: 2 }), _jsx(Skeleton, { height: "10px", width: "80%" })] }, idx)))] })) : selectedUser ? (_jsxs(_Fragment, { children: [_jsxs(Flex, { direction: { base: "column", md: "row" }, alignItems: { base: "flex-start", md: "center" }, justifyContent: "space-between", gap: 4, p: 4, borderBottom: "1px solid", borderColor: border, children: [_jsxs(Flex, { alignItems: "center", gap: 4, children: [_jsxs(Box, { position: "relative", children: [_jsx(Avatar, { size: "lg", name: selectedUser.name, src: selectedUser.profilePhoto }), selectedUser.isCurrent && (_jsx(Badge, { position: "absolute", bottom: -1, right: -1, colorScheme: "blue", variant: "solid", fontSize: "xs", borderRadius: "full", px: 2, py: 0.5, boxShadow: "sm", textTransform: "none", children: labels.you }))] }), _jsxs(Box, { children: [_jsx(Heading, { size: "md", mb: 1, color: heading, children: selectedUser.name }), _jsx(Text, { fontSize: "sm", color: muted, mb: 2, children: selectedUser.role }), _jsxs(HStack, { spacing: 2, children: [renderStatusBadge(selectedUser.isActive), selectedUser.isPending && (_jsx(Badge, { variant: "subtle", borderRadius: "full", px: 2, py: 0.5, fontSize: "xs", fontWeight: 600, colorScheme: "orange", textTransform: "none", children: labels.pendingInvitation }))] })] })] }), canManageUsers &&
89
87
  !selectedUser.isSuperAdmin && (_jsxs(HStack, { spacing: 2, flexWrap: "wrap", children: [!selectedUser.isCurrent && !selectedUser.isActive && (_jsx(Button, { size: "xs", variant: "outline", colorScheme: "blue", fontSize: "xs", leftIcon: _jsx(Send, { size: 13 }), isLoading: isInviteLoading, onClick: () => selectedUser.userId != null &&
90
88
  (onReinvite === null || onReinvite === void 0 ? void 0 : onReinvite(selectedUser.userId)), children: labels.resendInvitation })), _jsx(Button, { size: "xs", variant: "outline", colorScheme: "gray", fontSize: "xs", leftIcon: _jsx(Shield, { size: 13 }), onClick: () => {
@@ -102,7 +100,7 @@ const UserDetails = ({ users, selectedUser, selectedUserId, roleOptions = [], ca
102
100
  const Icon = (_a = detail.icon) !== null && _a !== void 0 ? _a : UserRound;
103
101
  return (_jsxs(React.Fragment, { children: [_jsxs(Flex, { gap: 3, px: 3, py: 2.5, _hover: {
104
102
  bg: resolveHoverTint(colors.gray[50], surface),
105
- }, alignItems: "center", transition: "background 0.15s ease", children: [_jsx(Flex, { align: "center", justify: "center", boxSize: "30px", bg: detailTile, borderRadius: "lg", color: accentTextOnCanvas(colors.primary, detailTile), flexShrink: 0, children: _jsx(Icon, { size: 15 }) }), _jsx(Box, { minWidth: "110px", children: _jsx(Text, { fontSize: "xs", fontWeight: 600, color: muted, children: detail.label }) }), _jsx(Box, { flex: 1, children: _jsx(Text, { fontSize: "sm", color: heading, fontWeight: 500, children: detail.value }) })] }), index < selectedUser.details.length - 1 && (_jsx(Divider, { borderColor: border }))] }, index));
103
+ }, alignItems: "center", transition: BACKGROUND_TRANSITION, children: [_jsx(Flex, { align: "center", justify: "center", boxSize: "30px", bg: detailTile, borderRadius: "lg", color: accentTextOnCanvas(colors.primary, detailTile), flexShrink: 0, children: _jsx(Icon, { size: 15 }) }), _jsx(Box, { minWidth: "110px", children: _jsx(Text, { fontSize: "xs", fontWeight: 600, color: muted, children: detail.label }) }), _jsx(Box, { flex: 1, children: _jsx(Text, { fontSize: "sm", color: heading, fontWeight: 500, children: detail.value }) })] }), index < selectedUser.details.length - 1 && (_jsx(Divider, { borderColor: border }))] }, index));
106
104
  }) })] })] })) : (_jsx(EmptyState, { icon: UserRound, title: labels.selectTeamMember, description: labels.noUserSelected, minH: "300px" })) })] }), _jsx(AddUserModal, { isOpen: isAddUserOpen, onClose: onAddUserClose, roleOptions: roleOptions, isLoading: isAddUserLoading, onSubmit: async (values) => {
107
105
  await (onAddUserSubmit === null || onAddUserSubmit === void 0 ? void 0 : onAddUserSubmit(values));
108
106
  onAddUserClose();
@@ -10,6 +10,7 @@ import { reducedMotionSx, usePrefersReducedMotion } from "../../Theme/chakra/mot
10
10
  import { focusVisibleRing } from "../../Theme/chakra/focusRing.styles.js";
11
11
  import { resolveFilledSurface } from "../../Theme/tokens/builders/filledSurface.js";
12
12
  import { overlayScrim } from "../../Theme/tokens/builders/scrim.js";
13
+ import { tonalHover } from "../CheckoutKit/tonalHover.js";
13
14
  const HIT_PX = { sm: 32, md: 44, lg: 48 };
14
15
  const POP_MS = 320;
15
16
  const pop = keyframes `
@@ -46,7 +47,7 @@ const WishlistToggle = ({ selected, defaultSelected = false, onSelectedChange, s
46
47
  const ink = on ? colors.semanticText.error : variant === "soft" ? colors.header[900] : colors.textMuted;
47
48
  return {
48
49
  bg: variant === "soft" ? colors.background[100] : colors.transparent,
49
- hoverBg: variant === "soft" ? colors.background[200] : colors.background[100],
50
+ hoverBg: variant === "soft" ? tonalHover(colors) : tonalHover(colors, colors.background[50], colors.background[100]),
50
51
  color: ink,
51
52
  };
52
53
  })();
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useId, useRef } from "react";
3
3
  import { Alert, AlertDescription, AlertIcon, AlertTitle, Box, Flex, Heading, ListItem, Text, UnorderedList, } from "@chakra-ui/react";
4
4
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
5
+ import { raisedRule } from "../../Theme/tokens/builders/surfaceRaised.js";
5
6
  import Modal, { ModalBody, ModalFooter } from "../Modal/Modal.js";
6
7
  import Button from "../Button/Button.js";
7
8
  import StageProgress from "../StageProgress/StageProgress.js";
@@ -44,15 +45,26 @@ const WizardFooter = ({ flow, labels, isFinishing, finishDisabled, finishBlocked
44
45
  const reason = finishDisabled && !isFinishing ? finishBlockedReason : undefined;
45
46
  return (_jsxs(Flex, { w: "100%", justify: "space-between", gap: 2, wrap: "wrap", children: [onCancel ? (_jsx(Button, { variant: "ghost", colorScheme: "gray", label: labels.cancel, onClick: onCancel, isDisabled: isFinishing, "data-testid": "wizard-cancel" })) : (_jsx("span", {})), _jsxs(Flex, { gap: 2, align: reason ? "center" : undefined, children: [!flow.isFirst ? (_jsx(Button, { variant: "outline", colorScheme: "gray", label: labels.back, onClick: flow.back, isDisabled: isFinishing, "data-testid": "wizard-back" })) : null, flow.isLast && reason ? (_jsx(Text, { id: reasonId, fontSize: "xs", color: colors.textMuted, "data-testid": "wizard-finish-reason", children: reason })) : null, flow.isLast ? (_jsx(Button, { variant: "solid", colorScheme: "primary", label: labels.finish, onClick: flow.finish, isLoading: isFinishing, isDisabled: finishDisabled, "aria-describedby": reason ? reasonId : undefined, loadingText: labels.finish, "data-testid": "wizard-finish" })) : (_jsx(Button, { variant: "solid", colorScheme: "primary", label: labels.next, onClick: flow.next, "data-testid": "wizard-next" }))] })] }));
46
47
  };
47
- /** Modal wizard that owns step state: validated Continue, locked future steps, error summary, review on the last step. */
48
- export const WizardDialog = ({ isOpen, onClose, title, subtitle, steps, onFinish, isFinishing = false, finishDisabled = false, finishBlockedReason, stepId, onStepChange, size = "3xl", labels, "data-testid": testId, }) => {
48
+ const WizardInlineFrame = ({ title, subtitle, testId, footer, children }) => {
49
+ const { colors } = useCustomTheme();
50
+ return (_jsxs(Flex, { direction: "column", gap: 4, "data-testid": testId, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h2", fontSize: "md", fontWeight: 600, color: colors.header[900], children: title }), subtitle ? (_jsx(Text, { mt: 0.5, fontSize: "sm", color: colors.textMuted, children: subtitle })) : null] }), children, _jsx(Box, { position: "sticky", bottom: 0, pt: 3, borderTopWidth: "1px", borderColor: raisedRule(colors), bg: colors.surfaceRaised, children: footer })] }));
51
+ };
52
+ /** Wizard that owns step state: validated Continue, locked future steps, error summary, review on the last step. A Modal by default; `chrome="inline"` draws it in place. */
53
+ export const WizardDialog = ({ isOpen, onClose, title, subtitle, steps, onFinish, isFinishing = false, finishDisabled = false, finishBlockedReason, stepId, onStepChange, size = "3xl", chrome = "modal", labels, "data-testid": testId, }) => {
49
54
  const flow = useWizardFlow({ steps, stepId, onStepChange, onFinish, resetWhen: !isOpen });
50
55
  const resolved = { ...DEFAULT_LABELS, ...labels };
51
56
  const guardedClose = () => {
52
57
  if (!isFinishing)
53
58
  onClose();
54
59
  };
55
- return (_jsxs(Modal, { isOpen: isOpen, onClose: guardedClose, size: size, isCentered: true, scrollBehavior: "inside", title: title, subtitle: subtitle, closeOnOverlayClick: false, closeOnEsc: !isFinishing, hideCloseButton: isFinishing, children: [_jsx(ModalBody, { children: _jsx(WizardBody, { flow: flow, steps: steps, labels: resolved, testId: testId !== null && testId !== void 0 ? testId : "wizard-dialog" }) }), _jsx(ModalFooter, { children: _jsx(WizardFooter, { flow: flow, labels: resolved, isFinishing: isFinishing, finishDisabled: finishDisabled, finishBlockedReason: finishBlockedReason, onCancel: guardedClose }) })] }));
60
+ const body = (_jsx(WizardBody, { flow: flow, steps: steps, labels: resolved, testId: testId !== null && testId !== void 0 ? testId : "wizard-dialog" }));
61
+ const footer = (_jsx(WizardFooter, { flow: flow, labels: resolved, isFinishing: isFinishing, finishDisabled: finishDisabled, finishBlockedReason: finishBlockedReason, onCancel: guardedClose }));
62
+ if (chrome === "inline") {
63
+ if (!isOpen)
64
+ return null;
65
+ return (_jsx(WizardInlineFrame, { title: title, subtitle: subtitle, testId: testId ? `${testId}-inline` : "wizard-inline", footer: footer, children: body }));
66
+ }
67
+ return (_jsxs(Modal, { isOpen: isOpen, onClose: guardedClose, size: size, isCentered: true, scrollBehavior: "inside", title: title, subtitle: subtitle, closeOnOverlayClick: false, closeOnEsc: !isFinishing, hideCloseButton: isFinishing, children: [_jsx(ModalBody, { children: body }), _jsx(ModalFooter, { children: footer })] }));
56
68
  };
57
69
  /** The same wizard inline, for a full-page flow rather than a modal. */
58
70
  export const Wizard = ({ steps, onFinish, isFinishing = false, finishDisabled = false, finishBlockedReason, stepId, onStepChange, labels, onCancel, "data-testid": testId, }) => {
@@ -1,8 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useRef, useState } from "react";
2
+ import { useCallback, useEffect, useId, useRef, useState } from "react";
3
3
  import { Box } from "@chakra-ui/react";
4
4
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
5
5
  import zIndices from "../../Theme/tokens/primitives/zIndices.js";
6
+ import { raisedRule } from "../../Theme/tokens/builders/surfaceRaised.js";
6
7
  const PLACEMENT_STYLE = {
7
8
  "top-end": { bottom: "100%", right: 0, marginBottom: "6px" },
8
9
  "top-start": { bottom: "100%", left: 0, marginBottom: "6px" },
@@ -12,6 +13,7 @@ const PLACEMENT_STYLE = {
12
13
  // Presentational, app-agnostic hover-preview (intent-safe: open delay, close grace, Escape dismisses).
13
14
  export default function WorkspaceTrayPreview({ children, preview, enabled = true, openDelayMs = 350, closeDelayMs = 200, placement = "top-end", onOpenChange, width = "340px", testId = "workspace-tray-preview", }) {
14
15
  const theme = useCustomTheme();
16
+ const cardId = useId();
15
17
  const [open, setOpen] = useState(false);
16
18
  const openTimer = useRef(null);
17
19
  const closeTimer = useRef(null);
@@ -69,7 +71,15 @@ export default function WorkspaceTrayPreview({ children, preview, enabled = true
69
71
  e.stopPropagation();
70
72
  closeNow();
71
73
  }
72
- }, children: [children, open && (_jsx(Box, { position: "absolute", ...PLACEMENT_STYLE[placement], w: typeof width === "number" ? `${width}px` : width, maxW: "min(360px, calc(100vw - 2rem))", bg: theme.colors.surfaceRaised, borderWidth: "1px", borderColor: theme.colors.boxborder[200], borderRadius: "lg", boxShadow: "xl", zIndex: zIndices.popover, pointerEvents: "auto", p: 3, textAlign: "left", color: theme.colors.text[700], cursor: "default", onMouseEnter: clearCloseTimer, onMouseLeave: scheduleClose, "data-testid": testId, children: typeof preview === "function"
74
+ }, children: [typeof children === "function"
75
+ ? children({
76
+ triggerProps: {
77
+ "aria-expanded": open,
78
+ "aria-controls": open ? cardId : undefined,
79
+ "aria-describedby": open ? cardId : undefined,
80
+ },
81
+ })
82
+ : children, open && (_jsx(Box, { id: cardId, position: "absolute", ...PLACEMENT_STYLE[placement], w: typeof width === "number" ? `${width}px` : width, maxW: "min(360px, calc(100vw - 2rem))", bg: theme.colors.surfaceRaised, borderWidth: "1px", borderColor: raisedRule(theme.colors), borderRadius: "lg", boxShadow: "xl", zIndex: zIndices.popover, pointerEvents: "auto", p: 3, textAlign: "left", color: theme.colors.text[700], cursor: "default", "data-testid": testId, children: typeof preview === "function"
73
83
  ? preview({ close: closeNow })
74
84
  : preview }))] }));
75
85
  }
@@ -1,10 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Flex, HStack, IconButton, Modal, ModalContent, ModalOverlay, Portal, Text, useModalContext, } from "@chakra-ui/react";
3
- import { useEffect } from "react";
3
+ import { Fragment, useEffect } from "react";
4
4
  import { ExternalLink, Minus, X } from "lucide-react";
5
5
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
6
6
  import zIndices from "../../Theme/tokens/primitives/zIndices.js";
7
7
  import { accentTextOnCanvas } from "../../Theme/tokens/builders/accentText.js";
8
+ import { bandOn } from "../../Theme/tokens/builders/planeStep.js";
9
+ import { raisedRule } from "../../Theme/tokens/builders/surfaceRaised.js";
8
10
  // NOTE: no maximize/restore toggle (removed by product decision); onMedium/onMaximize stay as deprecated no-ops.
9
11
  const WINDOW_SIZE = { maxW: "88rem", h: "92vh" };
10
12
  const WindowTitle = ({ testId, color, children }) => {
@@ -32,7 +34,7 @@ export default function WorkspaceWindow({ title, state, children, onMinimize, on
32
34
  onMouseDown: (e) => {
33
35
  if (e.target === e.currentTarget)
34
36
  onOverlayClick === null || onOverlayClick === void 0 ? void 0 : onOverlayClick();
35
- }, "data-testid": `${testId}-backdrop`, children: _jsxs(Box, { bg: theme.colors.surfaceRaised, borderRadius: "xl", boxShadow: "2xl", overflow: "hidden", w: "100%", maxW: size.maxW, h: size.h, display: "flex", flexDirection: "column", "data-testid": testId, "data-window-state": state, children: [_jsxs(Flex, { align: "center", justify: "space-between", px: 3, py: 2, borderBottomWidth: "1px", borderColor: theme.colors.boxborder[200], bg: theme.colors.background[100], flexShrink: 0, children: [_jsx(WindowTitle, { testId: testId, color: theme.colors.text[700], children: title }), _jsxs(HStack, { spacing: 1, children: [headerActions, onOpenFullPage ? (_jsx(IconButton, { "aria-label": (_a = labels === null || labels === void 0 ? void 0 : labels.openFullPage) !== null && _a !== void 0 ? _a : "Open full page", size: "xs", variant: "ghost", icon: _jsx(ExternalLink, { size: 14 }), onClick: onOpenFullPage, "data-testid": `${testId}-fullpage` })) : null, onMinimize ? (_jsx(IconButton, { "aria-label": (_b = labels === null || labels === void 0 ? void 0 : labels.minimize) !== null && _b !== void 0 ? _b : "Minimize", size: "xs", variant: "ghost", icon: _jsx(Minus, { size: 15 }), onClick: onMinimize, "data-testid": `${testId}-minimize` })) : null, onClose ? (_jsx(IconButton, { "aria-label": (_c = labels === null || labels === void 0 ? void 0 : labels.close) !== null && _c !== void 0 ? _c : "Close", size: "xs", variant: "ghost", colorScheme: "red", icon: _jsx(X, { size: 15 }), onClick: onClose, "data-testid": `${testId}-close` })) : null] })] }), _jsx(Box, { flex: "1", overflow: "auto", px: { base: 3, md: 5 }, py: 4, children: children })] }) })] }));
37
+ }, "data-testid": `${testId}-backdrop`, children: _jsxs(Box, { bg: theme.colors.surfaceRaised, borderRadius: "xl", boxShadow: "2xl", overflow: "hidden", w: "100%", maxW: size.maxW, h: size.h, display: "flex", flexDirection: "column", "data-testid": testId, "data-window-state": state, children: [_jsxs(Flex, { align: "center", justify: "space-between", px: 3, py: 2, borderBottomWidth: "1px", borderColor: raisedRule(theme.colors), bg: bandOn(theme.colors.background[100], theme.colors.surfaceRaised), flexShrink: 0, children: [_jsx(WindowTitle, { testId: testId, color: theme.colors.text[700], children: title }), _jsxs(HStack, { spacing: 1, children: [headerActions, onOpenFullPage ? (_jsx(IconButton, { "aria-label": (_a = labels === null || labels === void 0 ? void 0 : labels.openFullPage) !== null && _a !== void 0 ? _a : "Open full page", size: "xs", variant: "ghost", icon: _jsx(ExternalLink, { size: 14 }), onClick: onOpenFullPage, "data-testid": `${testId}-fullpage` })) : null, onMinimize ? (_jsx(IconButton, { "aria-label": (_b = labels === null || labels === void 0 ? void 0 : labels.minimize) !== null && _b !== void 0 ? _b : "Minimize", size: "xs", variant: "ghost", icon: _jsx(Minus, { size: 15 }), onClick: onMinimize, "data-testid": `${testId}-minimize` })) : null, onClose ? (_jsx(IconButton, { "aria-label": (_c = labels === null || labels === void 0 ? void 0 : labels.close) !== null && _c !== void 0 ? _c : "Close", size: "xs", variant: "ghost", colorScheme: "red", icon: _jsx(X, { size: 15 }), onClick: onClose, "data-testid": `${testId}-close` })) : null] })] }), _jsx(Box, { flex: "1", overflow: "auto", px: { base: 3, md: 5 }, py: 4, children: children })] }) })] }));
36
38
  }
37
39
  const cssLength = (value) => (typeof value === "number" ? `${value}px` : value);
38
40
  // Portalled above modal overlays; aria-live keeps Chakra's modal aria-hidden off it, data-no-focus-lock keeps the focus trap off it.
@@ -52,9 +54,10 @@ export function WorkspaceTray({ items, onRestore, onClose, testId = "workspace-t
52
54
  restore: () => onRestore === null || onRestore === void 0 ? void 0 : onRestore(item.id),
53
55
  close: () => onClose === null || onClose === void 0 ? void 0 : onClose(item.id),
54
56
  };
57
+ const pill = (_jsxs(HStack, { spacing: 1, pl: 3, pr: 1, py: 1, borderRadius: "full", bg: theme.colors.primary[100], color: ink, boxShadow: "md", borderWidth: "1px", borderColor: theme.colors.primary[200], "data-testid": `${testId}-pill`, children: [item.isDirty ? (_jsx(Box, { role: "img", "aria-label": dirtyLabel, boxSize: "0.5rem", borderRadius: "full", bg: "currentColor", flexShrink: 0, "data-testid": `${testId}-dirty` })) : null, _jsxs(Box, { as: "button", type: "button", fontSize: "sm", onClick: api.restore, "data-testid": `${testId}-restore`, maxW: "16rem", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: [item.title, item.subtitle ? (_jsx(Box, { as: "span", fontWeight: 400, ml: 1.5, children: item.subtitle })) : null] }), onClose ? (_jsx(IconButton, { "aria-label": closeLabel ? closeLabel(item) : "Close", size: "xs", variant: "ghost", borderRadius: "full", minW: "auto", h: "auto", p: 1, color: "inherit", icon: _jsx(X, { size: 13 }), onClick: api.close, "data-testid": `${testId}-close` })) : null] }));
55
58
  if (renderItem) {
56
- return _jsx(Box, { children: renderItem(item, api) }, item.id);
59
+ return _jsx(Box, { children: renderItem(item, api, pill) }, item.id);
57
60
  }
58
- return (_jsxs(HStack, { spacing: 1, pl: 3, pr: 1, py: 1, borderRadius: "full", bg: theme.colors.primary[100], color: ink, boxShadow: "md", borderWidth: "1px", borderColor: theme.colors.primary[200], "data-testid": `${testId}-pill`, children: [item.isDirty ? (_jsx(Box, { role: "img", "aria-label": dirtyLabel, boxSize: "0.5rem", borderRadius: "full", bg: "currentColor", flexShrink: 0, "data-testid": `${testId}-dirty` })) : null, _jsxs(Box, { as: "button", type: "button", fontSize: "sm", onClick: api.restore, "data-testid": `${testId}-restore`, maxW: "16rem", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", children: [item.title, item.subtitle ? (_jsx(Box, { as: "span", fontWeight: 400, ml: 1.5, children: item.subtitle })) : null] }), onClose ? (_jsx(IconButton, { "aria-label": closeLabel ? closeLabel(item) : "Close", size: "xs", variant: "ghost", borderRadius: "full", minW: "auto", h: "auto", p: 1, color: "inherit", icon: _jsx(X, { size: 13 }), onClick: api.close, "data-testid": `${testId}-close` })) : null] }, item.id));
61
+ return _jsx(Fragment, { children: pill }, item.id);
59
62
  }) }) }));
60
63
  }
@@ -0,0 +1,26 @@
1
+ import { useEffect, useRef } from "react";
2
+ /** Calls `onOutside` for a document `mousedown` outside every ref; a null ref contains nothing. Unlike Chakra's `useOutsideClick` it never waits for `mouseup`. */
3
+ export const useOutsideMouseDown = (refs, onOutside, { enabled = true, capture = false, includeClick = false } = {}) => {
4
+ const latest = useRef({ refs, onOutside });
5
+ useEffect(() => {
6
+ latest.current = { refs, onOutside };
7
+ });
8
+ useEffect(() => {
9
+ if (!enabled)
10
+ return;
11
+ const handle = (event) => {
12
+ const target = event.target;
13
+ if (latest.current.refs.some((ref) => { var _a; return (_a = ref.current) === null || _a === void 0 ? void 0 : _a.contains(target); }))
14
+ return;
15
+ latest.current.onOutside(event);
16
+ };
17
+ document.addEventListener("mousedown", handle, capture);
18
+ if (includeClick)
19
+ document.addEventListener("click", handle, capture);
20
+ return () => {
21
+ document.removeEventListener("mousedown", handle, capture);
22
+ if (includeClick)
23
+ document.removeEventListener("click", handle, capture);
24
+ };
25
+ }, [enabled, capture, includeClick]);
26
+ };
@@ -16,28 +16,45 @@ const constructUrl = ({ baseUrl, key, page, name, orgId }) => {
16
16
  const queryString = params.toString();
17
17
  return `${baseUrl}${queryString ? `?${queryString}` : ""}`;
18
18
  };
19
+ const NO_PREFERENCES = [];
19
20
  const useGetPreferences = ({ baseUrl = "", key = "", page = "", name = "", authToken = "", orgId = "", }) => {
20
- const [preferences, setPreferences] = useState([]);
21
- // NOTE: must start true — KanbanBoard's hydration effect reads this before this hook's mount effect runs.
22
- const [loading, setLoading] = useState(() => Boolean(baseUrl));
21
+ const url = baseUrl ? constructUrl({ baseUrl, key, page, name, orgId }) : "";
22
+ const requestKey = url ? JSON.stringify([url, authToken]) : "";
23
+ const [settled, setSettled] = useState({
24
+ requestKey: "",
25
+ preferences: NO_PREFERENCES,
26
+ });
23
27
  useEffect(() => {
24
- if (!baseUrl) {
28
+ if (!url) {
25
29
  return;
26
30
  }
27
- setLoading(true);
28
- const url = constructUrl({ baseUrl, key, page, name, orgId });
31
+ let cancelled = false;
29
32
  fetch(url, {
30
33
  headers: {
31
34
  Authorization: authToken,
32
35
  },
33
36
  })
34
37
  .then((response) => response.json())
35
- .then((data) => setPreferences(data))
36
- .catch((error) => console.error(error))
37
- .finally(() => setLoading(false));
38
- /* eslint-disable */
39
- }, [baseUrl]);
40
- return { preferences, loading };
38
+ .then((data) => {
39
+ if (!cancelled)
40
+ setSettled({ requestKey, preferences: data });
41
+ })
42
+ .catch((error) => {
43
+ if (cancelled)
44
+ return;
45
+ console.error(error);
46
+ setSettled({ requestKey, preferences: NO_PREFERENCES });
47
+ });
48
+ return () => {
49
+ cancelled = true;
50
+ };
51
+ }, [url, authToken, requestKey]);
52
+ const isSettled = settled.requestKey === requestKey;
53
+ return {
54
+ preferences: isSettled ? settled.preferences : NO_PREFERENCES,
55
+ // NOTE: derived so KanbanBoard never reads a stale loading=false, on mount or re-key.
56
+ loading: Boolean(baseUrl) && !isSettled,
57
+ };
41
58
  };
42
59
  const useSavePreferences = ({ baseUrl = "", key = "", page = "", name = "", authToken = "", orgId = "", }) => {
43
60
  const [loading, setLoading] = useState(false);
@@ -55,6 +72,7 @@ const useSavePreferences = ({ baseUrl = "", key = "", page = "", name = "", auth
55
72
  body: JSON.stringify({ key, page, name, json: data }),
56
73
  })
57
74
  .then((r) => r.json())
75
+ .then(() => setError(null))
58
76
  .catch((e) => setError(e))
59
77
  .finally(() => setLoading(false));
60
78
  }, [baseUrl, orgId, authToken, key, page, name]);
@@ -0,0 +1,33 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import { observeResize } from "./sharedResizeObserver.js";
3
+ const FOCUSABLE_CONTENT = 'a[href], area[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), summary, iframe, [contenteditable]:not([contenteditable="false"]), [tabindex]:not([tabindex="-1"])';
4
+ const USER_SCROLLABLE = /auto|scroll/;
5
+ const SLACK_PX = 1;
6
+ const needsFocusStop = (el) => {
7
+ const { overflowX, overflowY } = getComputedStyle(el);
8
+ const scrollsX = USER_SCROLLABLE.test(overflowX) && el.scrollWidth > el.clientWidth + SLACK_PX;
9
+ const scrollsY = USER_SCROLLABLE.test(overflowY) && el.scrollHeight > el.clientHeight + SLACK_PX;
10
+ return (scrollsX || scrollsY) && !el.querySelector(FOCUSABLE_CONTENT);
11
+ };
12
+ export function useScrollableRegion({ label, labelledBy, keepRole = false, } = {}) {
13
+ const [element, setElement] = useState(null);
14
+ const [isStop, setIsStop] = useState(false);
15
+ const measure = useCallback(() => setIsStop(element !== null && needsFocusStop(element)), [element]);
16
+ useEffect(() => {
17
+ if (!element)
18
+ return undefined;
19
+ return observeResize(element, measure);
20
+ }, [element, measure]);
21
+ // NOTE: also runs after every commit; an equal state bails out, so no loop.
22
+ useEffect(measure);
23
+ const named = Boolean(label || labelledBy);
24
+ const props = isStop
25
+ ? {
26
+ tabIndex: 0,
27
+ role: named && !keepRole ? "region" : undefined,
28
+ "aria-label": label,
29
+ "aria-labelledby": labelledBy,
30
+ }
31
+ : {};
32
+ return { ref: setElement, props };
33
+ }
@@ -5,6 +5,8 @@ import { optionRowInk, optionRowWeight } from "../../Components/Select/optionRow
5
5
  import { OPTION_ROW_SIZES, OPTION_ROW_RADIUS } from "../tokens/primitives/optionRowSizes.js";
6
6
  import { paletteOf } from "./paletteFromTheme.js";
7
7
  import { POPUP_SURFACE } from "./overlay.styles.js";
8
+ import { isDarkCanvas } from "../tokens/builders/accentText.js";
9
+ import { raisedRule } from "../tokens/builders/surfaceRaised.js";
8
10
  const itemRowSpec = OPTION_ROW_SIZES.sm;
9
11
  const { defineMultiStyleConfig, definePartsStyle } = createMultiStyleConfigHelpers(menuAnatomy.keys);
10
12
  const $bg = cssVar("menu-bg");
@@ -25,6 +27,10 @@ const baseStyle = definePartsStyle(({ theme }) => {
25
27
  borderColor: colors.boxborder[200],
26
28
  ...POPUP_SURFACE,
27
29
  },
30
+ divider: {
31
+ borderColor: raisedRule(colors),
32
+ ...(isDarkCanvas(colors.surfaceRaised) && { opacity: 1 }),
33
+ },
28
34
  item: {
29
35
  color: optionRowInk(colors, false),
30
36
  minH: itemRowSpec.minH,
@@ -74,7 +74,7 @@ const Badge = {
74
74
  size: "sm",
75
75
  },
76
76
  };
77
- // NOTE: fixes Chakra's FormErrorMessage/Icon hardcoding red.500 — same AA gap as our ErrorComponent.
77
+ // NOTE: fixes Chakra's FormErrorMessage/Icon hardcoding red.500, which misses AA on the canvas.
78
78
  const FormError = {
79
79
  baseStyle: ({ theme }) => {
80
80
  const palette = paletteOf(theme);
@@ -6,9 +6,9 @@ export const FOCUS_RING_WIDTH = 4;
6
6
  // NOTE: a box-shadow, not an outline — drawn outside the border box so it never resizes the control.
7
7
  export const focusRingShadow = (colors) => `0 0 0 ${FOCUS_HALO_WIDTH}px ${colors.focusRing.halo}, ` +
8
8
  `0 0 0 ${FOCUS_RING_WIDTH}px ${colors.focusRing.ring}`;
9
- /** For controls whose rounded shell clips overflow: the same halo and ring, drawn inside the border box. */
10
- export const insetFocusRingShadow = (colors) => `inset 0 0 0 ${FOCUS_HALO_WIDTH}px ${colors.focusRing.halo}, ` +
11
- `inset 0 0 0 ${FOCUS_RING_WIDTH}px ${colors.focusRing.ring}`;
9
+ /** For controls whose shell clips overflow: ring on the edge, halo inside, so an opaque child leaves the ring. */
10
+ export const insetFocusRingShadow = (colors) => `inset 0 0 0 ${FOCUS_RING_WIDTH - FOCUS_HALO_WIDTH}px ${colors.focusRing.ring}, ` +
11
+ `inset 0 0 0 ${FOCUS_RING_WIDTH}px ${colors.focusRing.halo}`;
12
12
  // NOTE: stacked pseudo-classes raise specificity above Chakra's _hover, so a hovered+focused button keeps its ring.
13
13
  export const FOCUS_VISIBLE_OVER_STATE = "&:hover:focus-visible, &:active:focus-visible, &[data-active]:focus-visible";
14
14
  // NOTE: transparent outline isn't decorative — forced-colors mode drops box-shadow but repaints an outline.
@@ -1,6 +1,19 @@
1
1
  import { assertPixelizePalette } from "../assertPalette.js";
2
+ import { scaleNamed } from "../tokens/builders/paletteScale.js";
2
3
  /** Chakra hands style functions an untyped theme; this is the boundary that makes it typed. */
3
4
  export const paletteOf = (theme) => assertPixelizePalette(theme);
4
- const asScale = (value) => typeof value === "object" && value !== null ? value : undefined;
5
- // NOTE: colorScheme is consumer-supplied and can name a built-in we never themed — unknowns resolve to gray.
6
- export const scaleFor = (palette, colorScheme) => { var _a; return (_a = asScale(palette[colorScheme])) !== null && _a !== void 0 ? _a : palette.gray; };
5
+ const warned = new Set();
6
+ export const warnUnknownColorScheme = (colorScheme) => {
7
+ if (process.env.NODE_ENV === "production" || warned.has(colorScheme))
8
+ return;
9
+ warned.add(colorScheme);
10
+ console.warn(`[pixelize-design-library] colorScheme "${colorScheme}" is not a themed colour scale; using the fallback scale.`);
11
+ };
12
+ // NOTE: colorScheme is consumer-supplied and can name a built-in we never themed — unknowns use the fallback.
13
+ export const scaleFor = (palette, colorScheme, fallback = palette.gray) => {
14
+ const scale = scaleNamed(palette, colorScheme);
15
+ if (scale)
16
+ return scale;
17
+ warnUnknownColorScheme(colorScheme);
18
+ return fallback;
19
+ };
@@ -0,0 +1,3 @@
1
+ import { BORDER_WIDTHS } from "../tokens/primitives/borderWidths.js";
2
+ /** A stroke drawn inside the border box as a box-shadow, so it never costs layout. */
3
+ export const insetRingShadow = (color, width = "hairline") => `inset 0 0 0 ${BORDER_WIDTHS[width]} ${color}`;
@@ -78,7 +78,7 @@ const SegmentedVariant = ({ size, label, showBrandPicker, }) => {
78
78
  const isSelected = mode === value;
79
79
  return (_jsx(Button, { ref: (node) => {
80
80
  optionRefs.current[index] = node;
81
- }, role: "radio", "aria-checked": isSelected, "aria-label": optionLabel, onClick: () => setMode(value), onKeyDown: (event) => handleKeyDown(event, index), size: SIZES[size].control, variant: "ghost", borderRadius: "full", bg: isSelected ? activeBg : "transparent", color: isSelected ? activeColor : mutedColor, boxShadow: isSelected ? "sm" : "none", _hover: { color: activeColor }, _focusVisible: { outline: "2px solid transparent", outlineOffset: "2px" }, children: _jsx(Icon, { size: SIZES[size].icon, "aria-hidden": true }) }, value));
81
+ }, role: "radio", "aria-checked": isSelected, "aria-label": optionLabel, tabIndex: isSelected ? 0 : -1, onClick: () => setMode(value), onKeyDown: (event) => handleKeyDown(event, index), size: SIZES[size].control, variant: "ghost", borderRadius: "full", bg: isSelected ? activeBg : "transparent", color: isSelected ? activeColor : mutedColor, boxShadow: isSelected ? "sm" : "none", _hover: { color: activeColor }, _focusVisible: { outline: "2px solid transparent", outlineOffset: "2px" }, children: _jsx(Icon, { size: SIZES[size].icon, "aria-hidden": true }) }, value));
82
82
  }), showBrandPicker && _jsx(BrandMenu, { size: size })] }));
83
83
  };
84
84
  const MenuVariant = ({ size, label, showBrandPicker, }) => {
@@ -143,7 +143,8 @@ const NAMED_SURFACE_L = {
143
143
  accent: 17,
144
144
  muted: 18,
145
145
  };
146
- const SURFACE_SAT = { lifted: 14, flat: 0 };
146
+ // NOTE: surfaces are hue-neutral on every brand; brand hue stays on accents, ink and rules.
147
+ const SURFACE_SAT = 0;
147
148
  const TEXT_SAT = 12;
148
149
  const PLACEHOLDER_SAT = 10;
149
150
  const BORDER_SAT = 12;
@@ -174,16 +175,15 @@ const cardPlane = (canvas, white, planes) => {
174
175
  export function buildDarkPalette(light, { planes = "lifted" } = {}) {
175
176
  const hueSource = light.primary[500];
176
177
  const { h } = hexToHsl(hueSource);
177
- const surfaceSat = SURFACE_SAT[planes];
178
178
  const namedSurfaces = Object.fromEntries(Object.entries(NAMED_SURFACE_L).map(([key, l]) => [
179
179
  key,
180
- hslToHex({ h, s: surfaceSat, l }),
180
+ hslToHex({ h, s: SURFACE_SAT, l }),
181
181
  ]));
182
182
  const white = light.white;
183
183
  const { card, rise, tableHover } = cardPlane(namedSurfaces.main, white, planes);
184
184
  const primary = liftBrand(light.primary, white);
185
185
  const background = {
186
- ...fromTargets(hueSource, raise(SURFACE_TARGETS, BACKGROUND_FILLS, rise), surfaceSat),
186
+ ...fromTargets(hueSource, raise(SURFACE_TARGETS, BACKGROUND_FILLS, rise), SURFACE_SAT),
187
187
  50: card,
188
188
  };
189
189
  const semantic = {
@@ -223,7 +223,7 @@ export function buildDarkPalette(light, { planes = "lifted" } = {}) {
223
223
  border: dividerRamp,
224
224
  boxborder: dividerRamp,
225
225
  table: {
226
- hover: fromTargets(hueSource, tableHover, surfaceSat),
226
+ hover: fromTargets(hueSource, tableHover, SURFACE_SAT),
227
227
  },
228
228
  disabled: fromTargets(hueSource, DISABLED_TARGETS, DISABLED_SAT),
229
229
  accentText: pickAccentText(primary, namedSurfaces.main),
@@ -37,8 +37,9 @@ export const solidFillRung = (scale, white, canvas) => {
37
37
  return rungAwayFromCanvas(scale, canvas);
38
38
  };
39
39
  const steppedRung = (base, canvas, step) => {
40
- const dir = isDarkCanvas(canvas) ? -100 : 100;
41
- return Math.min(900, Math.max(50, base + dir * step));
40
+ const dir = isDarkCanvas(canvas) ? -1 : 1;
41
+ const index = RUNGS.indexOf(base) + dir * step;
42
+ return RUNGS[Math.min(RUNGS.length - 1, Math.max(0, index))];
42
43
  };
43
44
  const steppedTowardBase = (from, base) => RUNGS[RUNGS.indexOf(from) + (from > base ? -1 : 1)];
44
45
  /**
@@ -1,5 +1,6 @@
1
1
  import { contrastRatio, hexToHsl, withLightness } from "./color.js";
2
2
  import { AA_NON_TEXT } from "./outlineRung.js";
3
+ import { bandOn } from "./planeStep.js";
3
4
  /** Same lightness granularity `buildDarkPalette` walks its accents at. */
4
5
  const LIGHTNESS_STEP = 0.5;
5
6
  // NOTE: not settleAcross — a ring squeezed between a light canvas and a dark fill needs the closest color that clears both, not a per-surface lift.
@@ -21,10 +22,12 @@ export function settleBetween(hex, backdrops, target = AA_NON_TEXT) {
21
22
  const worst = (candidate) => Math.min(...backdrops.map((backdrop) => contrastRatio(candidate, backdrop)));
22
23
  return worst(ends[0]) >= worst(ends[1]) ? ends[0] : ends[1];
23
24
  }
24
- // NOTE: only canvas + card surface — including the fill or every named surface leaves no solvable hue.
25
+ // NOTE: canvas, card and the table header band — including the fill or every named surface leaves no solvable hue.
25
26
  export const focusRingBackdrops = (source) => [
26
27
  source.backgroundColor.main,
27
28
  source.background[50],
29
+ source.backgroundColor.tableHeader,
30
+ bandOn(source.backgroundColor.tableHeader, source.background[50]),
28
31
  ];
29
32
  // NOTE: replaces Chakra's stock ring (a fixed blue that measured under 2:1 on every brand).
30
33
  export const buildFocusRing = (source) => {
@@ -0,0 +1,6 @@
1
+ const isColorScale = (value) => typeof value === "object" && value !== null && "500" in value;
2
+ export const scaleNamed = (colors, name) => {
3
+ const entries = colors;
4
+ const value = entries[name];
5
+ return isColorScale(value) ? value : undefined;
6
+ };
@@ -0,0 +1,56 @@
1
+ const NEEDS_QUOTES = /[",\r\n]/;
2
+ const FORMULA_TRIGGER = /^[=+\-@\t\r]/;
3
+ const PLAIN_NUMBER = /^[+-]?(?:\d[\d,]*(?:\.\d*)?|\.\d+)%?$/;
4
+ const BOM = "";
5
+ const RESERVED_FILE_CHARS = /[\\/:*?"<>|\p{Cc}]/gu;
6
+ const MAX_FILE_NAME = 80;
7
+ const REVOKE_DELAY_MS = 1000;
8
+ const quote = (text) => (NEEDS_QUOTES.test(text) ? `"${text.replace(/"/g, '""')}"` : text);
9
+ const looksLikeFormula = (text) => FORMULA_TRIGGER.test(text) && !PLAIN_NUMBER.test(text);
10
+ function cellText(value, escapeFormulas) {
11
+ if (value === null || value === undefined)
12
+ return "";
13
+ if (typeof value === "number")
14
+ return Number.isFinite(value) ? String(value) : "";
15
+ const text = String(value);
16
+ if (typeof value !== "string" || !escapeFormulas)
17
+ return text;
18
+ return looksLikeFormula(text) ? `'${text}` : text;
19
+ }
20
+ function readCell(row, column) {
21
+ const field = row[column.key];
22
+ const format = column.format;
23
+ return format === undefined ? field : format(field, row);
24
+ }
25
+ /** RFC 4180 CSV: header line, then one CRLF-separated line per row. */
26
+ export function toCsv(rows, columns, { bom = false } = {}) {
27
+ if (columns.length === 0)
28
+ return "";
29
+ const lines = [columns.map((column) => quote(column.header)).join(",")];
30
+ for (const row of rows) {
31
+ lines.push(columns.map((column) => quote(cellText(readCell(row, column), column.escapeFormulas !== false))).join(","));
32
+ }
33
+ return (bom ? BOM : "") + lines.join("\r\n");
34
+ }
35
+ /** Replaces path and reserved characters with `-`; caps at 80 characters, keeping the extension. */
36
+ export function safeFileName(fileName) {
37
+ const cleaned = fileName.replace(RESERVED_FILE_CHARS, "-").trim().replace(/^[.\s]+/, "");
38
+ if (cleaned === "")
39
+ return "export";
40
+ if (cleaned.length <= MAX_FILE_NAME)
41
+ return cleaned;
42
+ const dot = cleaned.lastIndexOf(".");
43
+ const extension = dot > 0 && cleaned.length - dot <= 8 ? cleaned.slice(dot) : "";
44
+ return cleaned.slice(0, MAX_FILE_NAME - extension.length).replace(/[\uD800-\uDBFF]$/, "") + extension;
45
+ }
46
+ /** Saves `blob` as `safeFileName(fileName)`, then revokes its object URL. */
47
+ export function downloadBlob(blob, fileName) {
48
+ const url = URL.createObjectURL(blob);
49
+ const link = document.createElement("a");
50
+ link.href = url;
51
+ link.download = safeFileName(fileName);
52
+ document.body.appendChild(link);
53
+ link.click();
54
+ link.remove();
55
+ setTimeout(() => URL.revokeObjectURL(url), REVOKE_DELAY_MS);
56
+ }