pixelize-design-library 2.4.2-beta.3 → 2.4.2-beta.31

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 (284) hide show
  1. package/dist/Components/Accordion/Accordion.js +5 -3
  2. package/dist/Components/AppSwitcher/AppMark.d.ts +19 -0
  3. package/dist/Components/AppSwitcher/AppMark.js +62 -0
  4. package/dist/Components/AppSwitcher/AppSwitcher.d.ts +4 -0
  5. package/dist/Components/AppSwitcher/AppSwitcher.js +315 -0
  6. package/dist/Components/AppSwitcher/AppSwitcherProps.d.ts +64 -0
  7. package/dist/Components/AppSwitcher/AppSwitcherProps.js +86 -0
  8. package/dist/Components/AppSwitcher/useAppSwitcherShortcut.d.ts +3 -0
  9. package/dist/Components/AppSwitcher/useAppSwitcherShortcut.js +31 -0
  10. package/dist/Components/AppearanceSettings/AppearanceSettings.js +2 -1
  11. package/dist/Components/Button/Button.d.ts +2 -2
  12. package/dist/Components/Button/Button.js +4 -3
  13. package/dist/Components/Button/Button.styles.js +39 -25
  14. package/dist/Components/Button/ButtonProps.d.ts +6 -1
  15. package/dist/Components/ButtonGroupIcon/ButtonGroupIcon.js +6 -6
  16. package/dist/Components/Card/Card.d.ts +1 -1
  17. package/dist/Components/Card/Card.js +2 -2
  18. package/dist/Components/Card/CardProps.d.ts +0 -1
  19. package/dist/Components/Card/PaymentCard/PaymentCard.js +7 -7
  20. package/dist/Components/Checkbox/Checkbox.js +1 -1
  21. package/dist/Components/Checkbox/Checkbox.styles.js +12 -7
  22. package/dist/Components/Common/fieldStyles.js +1 -1
  23. package/dist/Components/CopyButton/CopyButton.js +6 -2
  24. package/dist/Components/CustomModulesTable/EditModuleModal.js +1 -1
  25. package/dist/Components/DatePicker/CalendarPanel.d.ts +5 -0
  26. package/dist/Components/DatePicker/CalendarPanel.js +24 -5
  27. package/dist/Components/DatePicker/DatePickerProps.d.ts +21 -0
  28. package/dist/Components/DatePicker/RangeDatePicker.js +4 -4
  29. package/dist/Components/DatePicker/SingleDatePicker.js +2 -2
  30. package/dist/Components/DatePicker/TimeOnlyPicker.js +1 -1
  31. package/dist/Components/DatePicker/dayStates.d.ts +56 -0
  32. package/dist/Components/DatePicker/dayStates.js +87 -0
  33. package/dist/Components/Dropdown/DropDown.js +7 -15
  34. package/dist/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.js +1 -1
  35. package/dist/Components/EmptyState/EmptyState.js +2 -1
  36. package/dist/Components/FilePreview/FilePreview.js +1 -1
  37. package/dist/Components/FileUpload/FileUpload.js +5 -4
  38. package/dist/Components/FileUpload/FileUploadProps.d.ts +3 -1
  39. package/dist/Components/FileUpload/constants.js +1 -0
  40. package/dist/Components/FilterSidebar/FilterSidebar.js +4 -4
  41. package/dist/Components/FilterSidebar/filterHoverStyle.d.ts +0 -9
  42. package/dist/Components/FilterSidebar/filterHoverStyle.js +4 -10
  43. package/dist/Components/Form/FormWrapper.js +1 -1
  44. package/dist/Components/Header/components/mobileMenu.js +12 -3
  45. package/dist/Components/Input/TextInput.styles.js +6 -4
  46. package/dist/Components/InputTextArea/InputTextArea.style.js +5 -4
  47. package/dist/Components/KanbanBoard/KanbanBoard.js +5 -45
  48. package/dist/Components/LimitReachedModal/LimitReachedModal.js +4 -5
  49. package/dist/Components/Loading/Loading.js +15 -14
  50. package/dist/Components/MultiSelect/MultiSelect.js +1 -1
  51. package/dist/Components/NavigationBar/NavigationBar.js +3 -3
  52. package/dist/Components/NoteTextArea/NoteTextArea.js +9 -4
  53. package/dist/Components/NumberInput/NumberInput.js +3 -1
  54. package/dist/Components/NumberInput/NumberInput.styles.js +5 -4
  55. package/dist/Components/OrgSwitcher/OrgSwitcher.js +2 -2
  56. package/dist/Components/PdfViewer/PdfViewer.js +6 -1
  57. package/dist/Components/PinInput/PinInput.js +1 -1
  58. package/dist/Components/PlanPill/PlanPill.js +5 -5
  59. package/dist/Components/PlanPill/planPillGradient.d.ts +2 -14
  60. package/dist/Components/PlanPill/planPillGradient.js +3 -15
  61. package/dist/Components/Primitives/Primitives.d.ts +6 -0
  62. package/dist/Components/Primitives/Primitives.js +113 -0
  63. package/dist/Components/ProductCard/ProductPrice.js +1 -1
  64. package/dist/Components/ProductCard/ProductReview.js +6 -1
  65. package/dist/Components/ProductCard/ProductTags.js +1 -1
  66. package/dist/Components/ProfileCard/ProfileCard.js +1 -1
  67. package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +1 -1
  68. package/dist/Components/RadioButton/RadioButton.js +3 -2
  69. package/dist/Components/Reorder/Reorder.js +1 -1
  70. package/dist/Components/ScrollToTop/ScrollToTop.js +2 -0
  71. package/dist/Components/ScrollbarBox/ScrollbarBox.d.ts +13 -0
  72. package/dist/Components/ScrollbarBox/ScrollbarBox.js +11 -0
  73. package/dist/Components/Search/Search.js +2 -2
  74. package/dist/Components/SearchSelect/SearchSelect.js +14 -9
  75. package/dist/Components/SegmentedControl/SegmentedControl.d.ts +2 -0
  76. package/dist/Components/SegmentedControl/SegmentedControl.js +58 -0
  77. package/dist/Components/SegmentedControl/SegmentedControlProps.d.ts +16 -0
  78. package/dist/Components/SegmentedControl/SegmentedControlProps.js +2 -0
  79. package/dist/Components/Select/Select.d.ts +1 -1
  80. package/dist/Components/Select/Select.js +4 -2
  81. package/dist/Components/Select/Select.styles.js +3 -2
  82. package/dist/Components/Select/SelectProps.d.ts +3 -0
  83. package/dist/Components/SelectSearch/SelectSearch.js +7 -4
  84. package/dist/Components/SelectV2/SelectV2.js +18 -14
  85. package/dist/Components/SideBar/SecondaryBar.js +1 -1
  86. package/dist/Components/SideBar/SideBar.js +1 -1
  87. package/dist/Components/SideBar/components/MenuPopoverContent.js +2 -2
  88. package/dist/Components/Slider/Slider.js +8 -1
  89. package/dist/Components/StageProgress/StageProgress.js +2 -9
  90. package/dist/Components/StageProgress/StepperStage.js +2 -2
  91. package/dist/Components/Table/Table.d.ts +1 -1
  92. package/dist/Components/Table/Table.js +17 -24
  93. package/dist/Components/Table/TableProps.d.ts +4 -0
  94. package/dist/Components/Table/components/Pagination.js +1 -1
  95. package/dist/Components/Table/components/TableActions.js +2 -2
  96. package/dist/Components/Table/components/TableBody.js +41 -12
  97. package/dist/Components/Table/components/TableGroupRow.js +1 -1
  98. package/dist/Components/Table/components/TableHeader.js +21 -8
  99. package/dist/Components/Table/components/TableSearch.js +1 -1
  100. package/dist/Components/Table/filters/ActiveFilters.js +2 -18
  101. package/dist/Components/Table/settings/ManageColumns.js +4 -17
  102. package/dist/Components/Table/settings/TableSettings.js +5 -11
  103. package/dist/Components/Table/variants/TableVariantContext.d.ts +4 -0
  104. package/dist/Components/Table/variants/TableVariantContext.js +17 -0
  105. package/dist/Components/Table/variants/classic.d.ts +6 -0
  106. package/dist/Components/Table/variants/classic.js +47 -0
  107. package/dist/Components/Table/variants/index.d.ts +7 -0
  108. package/dist/Components/Table/variants/index.js +27 -0
  109. package/dist/Components/Table/variants/pillInk.d.ts +6 -0
  110. package/dist/Components/Table/variants/pillInk.js +21 -0
  111. package/dist/Components/Table/variants/studio.d.ts +6 -0
  112. package/dist/Components/Table/variants/studio.js +50 -0
  113. package/dist/Components/Table/variants/tokens.d.ts +49 -0
  114. package/dist/Components/Table/variants/tokens.js +2 -0
  115. package/dist/Components/Tag/Tag.styles.js +9 -8
  116. package/dist/Components/Timeline/Timeline.js +2 -2
  117. package/dist/Components/Toaster/Toaster.js +1 -1
  118. package/dist/Components/Toggle/TableToggle.js +11 -7
  119. package/dist/Components/ToggleSwitch/ToggleSwitch.d.ts +2 -0
  120. package/dist/Components/ToggleSwitch/ToggleSwitch.js +18 -0
  121. package/dist/Components/ToggleSwitch/ToggleSwitchProps.d.ts +11 -0
  122. package/dist/Components/ToggleSwitch/ToggleSwitchProps.js +2 -0
  123. package/dist/Components/ToolTip/ToolTip.js +6 -6
  124. package/dist/Components/ToolTip/ToolTipProps.d.ts +3 -1
  125. package/dist/Components/Trail/TrailWorks.js +1 -1
  126. package/dist/Components/UpgradeButton/UpgradeButton.js +3 -3
  127. package/dist/Constants/Sidebar.js +3 -2
  128. package/dist/Theme/assertPalette.d.ts +1 -1
  129. package/dist/Theme/assertPalette.js +3 -2
  130. package/dist/Theme/chakra/Menu.styles.d.ts +3 -0
  131. package/dist/Theme/chakra/Menu.styles.js +5 -0
  132. package/dist/Theme/chakra/Popover.styles.d.ts +3 -0
  133. package/dist/Theme/chakra/Popover.styles.js +5 -1
  134. package/dist/Theme/chakra/componentStyles.d.ts +6 -0
  135. package/dist/Theme/chakra/componentStyles.js +5 -5
  136. package/dist/Theme/chakra/createBrandTheme.js +10 -16
  137. package/dist/Theme/chakra/focusRing.styles.d.ts +52 -0
  138. package/dist/Theme/chakra/focusRing.styles.js +46 -0
  139. package/dist/Theme/provider/ThemeSwitcher.js +5 -2
  140. package/dist/Theme/tokens/brands/index.js +6 -1
  141. package/dist/Theme/tokens/brands/zinc/palette.dark.d.ts +1 -0
  142. package/dist/Theme/tokens/builders/buildDarkPalette.js +6 -1
  143. package/dist/Theme/tokens/builders/chartColorsFromTheme.js +1 -1
  144. package/dist/Theme/tokens/builders/focusRing.d.ts +52 -0
  145. package/dist/Theme/tokens/builders/focusRing.js +92 -0
  146. package/dist/Theme/tokens/builders/gradientInk.d.ts +22 -0
  147. package/dist/Theme/tokens/builders/gradientInk.js +28 -0
  148. package/dist/Theme/tokens/builders/index.d.ts +4 -0
  149. package/dist/Theme/tokens/builders/index.js +4 -0
  150. package/dist/Theme/tokens/builders/outlineRung.d.ts +46 -3
  151. package/dist/Theme/tokens/builders/outlineRung.js +101 -5
  152. package/dist/Theme/tokens/builders/placeholderInk.d.ts +19 -0
  153. package/dist/Theme/tokens/builders/placeholderInk.js +35 -0
  154. package/dist/Theme/tokens/builders/resolvedRungs.d.ts +5 -1
  155. package/dist/Theme/tokens/builders/resolvedRungs.js +7 -2
  156. package/dist/Theme/tokens/builders/rowStates.d.ts +13 -0
  157. package/dist/Theme/tokens/builders/rowStates.js +19 -0
  158. package/dist/Theme/tokens/builders/scrollbar.d.ts +12 -0
  159. package/dist/Theme/tokens/builders/scrollbar.js +57 -0
  160. package/dist/Theme/tokens/builders/solidFillRung.d.ts +4 -0
  161. package/dist/Theme/tokens/builders/solidFillRung.js +33 -0
  162. package/dist/Theme/tokens/builders/surfaceRungs.d.ts +5 -0
  163. package/dist/Theme/tokens/builders/surfaceRungs.js +20 -5
  164. package/dist/Theme/tokens/types.d.ts +21 -1
  165. package/dist/esm/Components/Accordion/Accordion.js +5 -3
  166. package/dist/esm/Components/AppSwitcher/AppMark.js +56 -0
  167. package/dist/esm/Components/AppSwitcher/AppSwitcher.js +280 -0
  168. package/dist/esm/Components/AppSwitcher/AppSwitcherProps.js +78 -0
  169. package/dist/esm/Components/AppSwitcher/useAppSwitcherShortcut.js +27 -0
  170. package/dist/esm/Components/AppearanceSettings/AppearanceSettings.js +2 -1
  171. package/dist/esm/Components/Button/Button.js +5 -4
  172. package/dist/esm/Components/Button/Button.styles.js +40 -26
  173. package/dist/esm/Components/ButtonGroupIcon/ButtonGroupIcon.js +6 -6
  174. package/dist/esm/Components/Card/Card.js +2 -2
  175. package/dist/esm/Components/Card/PaymentCard/PaymentCard.js +7 -7
  176. package/dist/esm/Components/Checkbox/Checkbox.js +1 -1
  177. package/dist/esm/Components/Checkbox/Checkbox.styles.js +13 -8
  178. package/dist/esm/Components/Common/fieldStyles.js +1 -1
  179. package/dist/esm/Components/CopyButton/CopyButton.js +7 -3
  180. package/dist/esm/Components/CustomModulesTable/EditModuleModal.js +1 -1
  181. package/dist/esm/Components/DatePicker/CalendarPanel.js +24 -5
  182. package/dist/esm/Components/DatePicker/RangeDatePicker.js +4 -4
  183. package/dist/esm/Components/DatePicker/SingleDatePicker.js +2 -2
  184. package/dist/esm/Components/DatePicker/TimeOnlyPicker.js +1 -1
  185. package/dist/esm/Components/DatePicker/dayStates.js +79 -0
  186. package/dist/esm/Components/Dropdown/DropDown.js +7 -15
  187. package/dist/esm/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.js +1 -1
  188. package/dist/esm/Components/EmptyState/EmptyState.js +2 -1
  189. package/dist/esm/Components/FilePreview/FilePreview.js +1 -1
  190. package/dist/esm/Components/FileUpload/FileUpload.js +6 -5
  191. package/dist/esm/Components/FileUpload/constants.js +1 -0
  192. package/dist/esm/Components/FilterSidebar/FilterSidebar.js +4 -4
  193. package/dist/esm/Components/FilterSidebar/filterHoverStyle.js +4 -10
  194. package/dist/esm/Components/Form/FormWrapper.js +1 -1
  195. package/dist/esm/Components/Header/components/mobileMenu.js +12 -3
  196. package/dist/esm/Components/Input/TextInput.styles.js +6 -4
  197. package/dist/esm/Components/InputTextArea/InputTextArea.style.js +5 -4
  198. package/dist/esm/Components/KanbanBoard/KanbanBoard.js +5 -45
  199. package/dist/esm/Components/LimitReachedModal/LimitReachedModal.js +4 -5
  200. package/dist/esm/Components/Loading/Loading.js +12 -11
  201. package/dist/esm/Components/MultiSelect/MultiSelect.js +1 -1
  202. package/dist/esm/Components/NavigationBar/NavigationBar.js +3 -3
  203. package/dist/esm/Components/NoteTextArea/NoteTextArea.js +9 -4
  204. package/dist/esm/Components/NumberInput/NumberInput.js +4 -2
  205. package/dist/esm/Components/NumberInput/NumberInput.styles.js +5 -4
  206. package/dist/esm/Components/OrgSwitcher/OrgSwitcher.js +2 -2
  207. package/dist/esm/Components/PdfViewer/PdfViewer.js +6 -1
  208. package/dist/esm/Components/PinInput/PinInput.js +1 -1
  209. package/dist/esm/Components/PlanPill/PlanPill.js +6 -6
  210. package/dist/esm/Components/PlanPill/planPillGradient.js +3 -15
  211. package/dist/esm/Components/Primitives/Primitives.js +6 -0
  212. package/dist/esm/Components/ProductCard/ProductPrice.js +1 -1
  213. package/dist/esm/Components/ProductCard/ProductReview.js +6 -1
  214. package/dist/esm/Components/ProductCard/ProductTags.js +1 -1
  215. package/dist/esm/Components/ProfileCard/ProfileCard.js +1 -1
  216. package/dist/esm/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +1 -1
  217. package/dist/esm/Components/RadioButton/RadioButton.js +3 -2
  218. package/dist/esm/Components/Reorder/Reorder.js +1 -1
  219. package/dist/esm/Components/ScrollToTop/ScrollToTop.js +2 -0
  220. package/dist/esm/Components/ScrollbarBox/ScrollbarBox.js +9 -0
  221. package/dist/esm/Components/Search/Search.js +2 -2
  222. package/dist/esm/Components/SearchSelect/SearchSelect.js +14 -9
  223. package/dist/esm/Components/SegmentedControl/SegmentedControl.js +55 -0
  224. package/dist/esm/Components/SegmentedControl/SegmentedControlProps.js +1 -0
  225. package/dist/esm/Components/Select/Select.js +5 -3
  226. package/dist/esm/Components/Select/Select.styles.js +3 -2
  227. package/dist/esm/Components/SelectSearch/SelectSearch.js +7 -4
  228. package/dist/esm/Components/SelectV2/SelectV2.js +18 -14
  229. package/dist/esm/Components/SideBar/SecondaryBar.js +1 -1
  230. package/dist/esm/Components/SideBar/SideBar.js +1 -1
  231. package/dist/esm/Components/SideBar/components/MenuPopoverContent.js +2 -2
  232. package/dist/esm/Components/Slider/Slider.js +8 -1
  233. package/dist/esm/Components/StageProgress/StageProgress.js +2 -9
  234. package/dist/esm/Components/StageProgress/StepperStage.js +2 -2
  235. package/dist/esm/Components/Table/Table.js +17 -24
  236. package/dist/esm/Components/Table/components/Pagination.js +1 -1
  237. package/dist/esm/Components/Table/components/TableActions.js +2 -2
  238. package/dist/esm/Components/Table/components/TableBody.js +42 -13
  239. package/dist/esm/Components/Table/components/TableGroupRow.js +1 -1
  240. package/dist/esm/Components/Table/components/TableHeader.js +21 -8
  241. package/dist/esm/Components/Table/components/TableSearch.js +1 -1
  242. package/dist/esm/Components/Table/filters/ActiveFilters.js +2 -18
  243. package/dist/esm/Components/Table/settings/ManageColumns.js +4 -17
  244. package/dist/esm/Components/Table/settings/TableSettings.js +5 -11
  245. package/dist/esm/Components/Table/variants/TableVariantContext.js +13 -0
  246. package/dist/esm/Components/Table/variants/classic.js +43 -0
  247. package/dist/esm/Components/Table/variants/index.js +9 -0
  248. package/dist/esm/Components/Table/variants/pillInk.js +18 -0
  249. package/dist/esm/Components/Table/variants/studio.js +46 -0
  250. package/dist/esm/Components/Table/variants/tokens.js +1 -0
  251. package/dist/esm/Components/Tag/Tag.styles.js +10 -9
  252. package/dist/esm/Components/Timeline/Timeline.js +2 -2
  253. package/dist/esm/Components/Toaster/Toaster.js +1 -1
  254. package/dist/esm/Components/Toggle/TableToggle.js +11 -7
  255. package/dist/esm/Components/ToggleSwitch/ToggleSwitch.js +15 -0
  256. package/dist/esm/Components/ToggleSwitch/ToggleSwitchProps.js +1 -0
  257. package/dist/esm/Components/ToolTip/ToolTip.js +6 -6
  258. package/dist/esm/Components/Trail/TrailWorks.js +1 -1
  259. package/dist/esm/Components/UpgradeButton/UpgradeButton.js +3 -3
  260. package/dist/esm/Constants/Sidebar.js +3 -2
  261. package/dist/esm/Theme/assertPalette.js +3 -2
  262. package/dist/esm/Theme/chakra/Menu.styles.js +5 -0
  263. package/dist/esm/Theme/chakra/Popover.styles.js +5 -1
  264. package/dist/esm/Theme/chakra/componentStyles.js +5 -5
  265. package/dist/esm/Theme/chakra/createBrandTheme.js +10 -16
  266. package/dist/esm/Theme/chakra/focusRing.styles.js +40 -0
  267. package/dist/esm/Theme/provider/ThemeSwitcher.js +5 -2
  268. package/dist/esm/Theme/tokens/brands/index.js +6 -1
  269. package/dist/esm/Theme/tokens/builders/buildDarkPalette.js +6 -1
  270. package/dist/esm/Theme/tokens/builders/chartColorsFromTheme.js +1 -1
  271. package/dist/esm/Theme/tokens/builders/focusRing.js +85 -0
  272. package/dist/esm/Theme/tokens/builders/gradientInk.js +22 -0
  273. package/dist/esm/Theme/tokens/builders/index.js +4 -0
  274. package/dist/esm/Theme/tokens/builders/outlineRung.js +96 -4
  275. package/dist/esm/Theme/tokens/builders/placeholderInk.js +29 -0
  276. package/dist/esm/Theme/tokens/builders/resolvedRungs.js +7 -2
  277. package/dist/esm/Theme/tokens/builders/rowStates.js +15 -0
  278. package/dist/esm/Theme/tokens/builders/scrollbar.js +52 -0
  279. package/dist/esm/Theme/tokens/builders/solidFillRung.js +28 -0
  280. package/dist/esm/Theme/tokens/builders/surfaceRungs.js +20 -5
  281. package/dist/esm/index.js +24 -1
  282. package/dist/index.d.ts +27 -3
  283. package/dist/index.js +64 -4
  284. package/package.json +8 -2
@@ -0,0 +1,78 @@
1
+ const NON_WORD = /[^\p{L}\p{N}]+/u;
2
+ /** Up to two initials, so a mark stays legible without an icon. */
3
+ export const appInitials = (name) => {
4
+ const words = name.trim().split(NON_WORD).filter(Boolean);
5
+ if (words.length === 0)
6
+ return "?";
7
+ if (words.length === 1)
8
+ return words[0].slice(0, 2).toUpperCase();
9
+ return (words[0][0] + words[1][0]).toUpperCase();
10
+ };
11
+ export const filterApps = (apps, query) => {
12
+ const q = query.trim().toLowerCase();
13
+ if (!q)
14
+ return apps;
15
+ return apps.filter((app) => {
16
+ var _a, _b;
17
+ return [app.name, (_a = app.description) !== null && _a !== void 0 ? _a : "", ...((_b = app.keywords) !== null && _b !== void 0 ? _b : [])]
18
+ .join(" ")
19
+ .toLowerCase()
20
+ .includes(q);
21
+ });
22
+ };
23
+ /** "mod" is Cmd on Apple platforms and Ctrl everywhere else. */
24
+ export const matchesShortcut = (event, shortcut, isApple = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform)) => {
25
+ const parts = shortcut.toLowerCase().split("+").map((p) => p.trim()).filter(Boolean);
26
+ if (parts.length === 0)
27
+ return false;
28
+ const key = parts[parts.length - 1];
29
+ const mods = new Set(parts.slice(0, -1));
30
+ const wantsMod = mods.has("mod");
31
+ const wantsCtrl = mods.has("ctrl") || (wantsMod && !isApple);
32
+ const wantsMeta = mods.has("cmd") || mods.has("meta") || (wantsMod && isApple);
33
+ if (event.ctrlKey !== wantsCtrl)
34
+ return false;
35
+ if (event.metaKey !== wantsMeta)
36
+ return false;
37
+ if (event.shiftKey !== mods.has("shift"))
38
+ return false;
39
+ if (event.altKey !== mods.has("alt"))
40
+ return false;
41
+ return event.key.toLowerCase() === key;
42
+ };
43
+ const APPLE_SYMBOLS = { mod: "⌘", cmd: "⌘", meta: "⌘", ctrl: "⌃", shift: "⇧", alt: "⌥" };
44
+ const OTHER_LABELS = { mod: "Ctrl", cmd: "Win", meta: "Win", ctrl: "Ctrl", shift: "Shift", alt: "Alt" };
45
+ export const formatShortcut = (shortcut, isApple = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform)) => {
46
+ const parts = shortcut.toLowerCase().split("+").map((p) => p.trim()).filter(Boolean);
47
+ const table = isApple ? APPLE_SYMBOLS : OTHER_LABELS;
48
+ const rendered = parts.map((p, i) => { var _a; return i === parts.length - 1 ? p.toUpperCase() : ((_a = table[p]) !== null && _a !== void 0 ? _a : p.toUpperCase()); });
49
+ return isApple ? rendered.join("") : rendered.join("+");
50
+ };
51
+ /**
52
+ * Derives every app's origin from the host the consumer is already served on, so one deployment
53
+ * variable keeps dev, test and prod in step. An app may still carry its own `url`, which wins.
54
+ */
55
+ export const buildSuiteApps = (apps, { baseUrl, baseSubdomain }) => {
56
+ let base;
57
+ try {
58
+ base = new URL(baseUrl.trim());
59
+ }
60
+ catch {
61
+ throw new Error(`[AppSwitcher] buildSuiteApps: baseUrl ${JSON.stringify(baseUrl)} is not an absolute URL.`);
62
+ }
63
+ const labels = base.hostname.split(".");
64
+ const at = labels.indexOf(baseSubdomain);
65
+ return apps.map(({ subdomain, url, ...app }) => {
66
+ if (url)
67
+ return { ...app, url: url.trim() };
68
+ // Without the label there is nothing to swap, and every app would silently share one origin.
69
+ if (at === -1) {
70
+ throw new Error(`[AppSwitcher] buildSuiteApps: ${JSON.stringify(baseSubdomain)} is not a label in ` +
71
+ `"${base.hostname}", so ${JSON.stringify(app.name)} has no derivable url. ` +
72
+ `Give that app an explicit url, or pass a baseUrl that contains the label.`);
73
+ }
74
+ const next = new URL(base.toString());
75
+ next.hostname = labels.map((l, i) => (i === at ? subdomain : l)).join(".");
76
+ return { ...app, url: next.origin };
77
+ });
78
+ };
@@ -0,0 +1,27 @@
1
+ import { useEffect } from "react";
2
+ import { matchesShortcut } from "./AppSwitcherProps.js";
3
+ const isTypingTarget = (target) => {
4
+ if (!(target instanceof HTMLElement))
5
+ return false;
6
+ if (target.isContentEditable)
7
+ return true;
8
+ return ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName);
9
+ };
10
+ /** Fires `onTrigger` on the shortcut. Inert when `shortcut` is null, and never in SSR. */
11
+ export const useAppSwitcherShortcut = (shortcut, onTrigger, enabled = true) => {
12
+ useEffect(() => {
13
+ if (!shortcut || !enabled || typeof window === "undefined")
14
+ return undefined;
15
+ const handler = (event) => {
16
+ if (event.defaultPrevented || isTypingTarget(event.target))
17
+ return;
18
+ if (!matchesShortcut(event, shortcut))
19
+ return;
20
+ event.preventDefault();
21
+ onTrigger();
22
+ };
23
+ window.addEventListener("keydown", handler);
24
+ return () => window.removeEventListener("keydown", handler);
25
+ }, [shortcut, enabled, onTrigger]);
26
+ };
27
+ export default useAppSwitcherShortcut;
@@ -5,13 +5,14 @@ import { ThemesList } from "../../Theme/index.js";
5
5
  import { ThemeSwitcher } from "../../Theme/provider/index.js";
6
6
  import { FONT_SIZE_OPTIONS } from "../../Theme/provider/fontSize.js";
7
7
  import { lightPalettes } from "../../Theme/tokens/brands/index.js";
8
+ import { CHROME_RULE, ruleInk } from "../../Theme/tokens/builders/outlineRung.js";
8
9
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
9
10
  import SelectV2 from "../SelectV2/SelectV2.js";
10
11
  const FieldLabel = ({ children }) => {
11
12
  const { colors } = useCustomTheme();
12
13
  return (_jsx(Text, { fontSize: "sm", fontWeight: "medium", color: colors.textMuted, mb: 2, children: children }));
13
14
  };
14
- const brandSwatch = (name, colors) => (_jsx(Box, { w: "14px", h: "14px", borderRadius: "full", bg: lightPalettes[name].primary[500], border: "1px solid", borderColor: colors.boxborder[500] }));
15
+ const brandSwatch = (name, colors) => (_jsx(Box, { w: "14px", h: "14px", borderRadius: "full", bg: lightPalettes[name].primary[500], border: "1px solid", borderColor: ruleInk(colors.boxborder[200], [colors.backgroundColor.light, colors.backgroundColor.tertiary], CHROME_RULE) }));
15
16
  export const AppearanceSettings = ({ brand, fontSize, onBrandChange, onFontSizeChange, showBrand = true, showColorMode = true, showFontSize = true, size = "sm", labels, }) => {
16
17
  var _a, _b, _c;
17
18
  const { colors } = useCustomTheme();
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { memo } from "react";
2
+ import { forwardRef, memo } from "react";
3
3
  import { Button as ChakraButton } from "@chakra-ui/react";
4
- function Button({ label, children, onClick, opacity, variant = "solid", leftIcon, rightIcon, size, isDisabled = false, isLoading = false, loadingText = "Loading", type, width, sx, colorScheme, ref, border, borderRadius, onMouseEnter, onMouseLeave, ...aria }) {
5
- return (_jsx(ChakraButton, { ...aria, type: type, onClick: onClick, width: width || "fit-content", variant: variant, size: size, isLoading: isLoading, isDisabled: isDisabled, loadingText: loadingText, leftIcon: leftIcon, rightIcon: rightIcon, ref: ref, colorScheme: colorScheme, sx: sx, opacity: opacity, border: border, borderRadius: borderRadius, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: children !== null && children !== void 0 ? children : label }));
6
- }
4
+ const Button = forwardRef(function Button({ label, children, onClick, opacity, variant = "solid", leftIcon, rightIcon, size, isDisabled = false, isLoading = false, loadingText = "Loading", type, width, w, sx, colorScheme, border, borderRadius, onMouseEnter, onMouseLeave, ...aria }, ref) {
5
+ const isIconOnly = !children && !label && !!(leftIcon || rightIcon);
6
+ return (_jsx(ChakraButton, { ...aria, type: type, onClick: onClick, width: width || w || "fit-content", variant: variant, size: size, isLoading: isLoading, isDisabled: isDisabled, loadingText: loadingText, leftIcon: leftIcon, rightIcon: rightIcon, iconSpacing: isIconOnly ? 0 : undefined, ref: ref, colorScheme: colorScheme, sx: sx, opacity: opacity, border: border, borderRadius: borderRadius, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: children !== null && children !== void 0 ? children : label }));
7
+ });
7
8
  export default memo(Button);
@@ -1,4 +1,7 @@
1
- import { accentTextOnCanvas, isDarkCanvas, onFilled, onGradient } from "../../Theme/tokens/builders/accentText.js";
1
+ import { accentTextOnCanvas, isDarkCanvas, onFilled } from "../../Theme/tokens/builders/accentText.js";
2
+ import { solidRung, darkerFillRung } from "../../Theme/tokens/builders/solidFillRung.js";
3
+ import { resolveGradient, gradientCss } from "../../Theme/tokens/builders/gradientInk.js";
4
+ import { focusVisibleStyles } from "../../Theme/chakra/focusRing.styles.js";
2
5
  /**
3
6
  * Outline/ghost/link text sits ON the canvas, so it needs a rung that stays readable there —
4
7
  * `[500]` is pinned dark enough to carry a white label on the solid variant and measures only
@@ -16,24 +19,27 @@ const onCanvasHoverBg = (theme, colorScheme, step) => {
16
19
  const scale = theme.colors[colorScheme];
17
20
  return "opacity" in scale ? scale.opacity[step] : scale[50];
18
21
  };
19
- /**
20
- * The rung one/two steps DARKER than the accent — what a filled button's hover/active needs so its
21
- * white label stays legible.
22
- *
23
- * Every dark scale runs dark -> light across 50 -> 900 (brand scales are rebuilt that way, utility
24
- * hues are reversed), the mirror of light mode. So "darker than [500]" is [600]/[700] in light but
25
- * [400]/[300] in dark. Hardcoding [600] would hand the label a LIGHTER fill in dark and drop it to
26
- * ~3.2 contrast.
27
- */
28
- const FILL_STEP_RUNGS = { light: [600, 700], dark: [400, 300] };
22
+ const buttonSolidRung = (theme, colorScheme) => solidRung(theme.colors[colorScheme], theme.colors.white);
29
23
  const darkerFill = (theme, colorScheme, step) => {
30
- const mode = isDarkCanvas(theme.colors.backgroundColor.main) ? "dark" : "light";
31
- return theme.colors[colorScheme][FILL_STEP_RUNGS[mode][step]];
24
+ const scale = theme.colors[colorScheme];
25
+ const isDark = isDarkCanvas(theme.colors.backgroundColor.main);
26
+ return scale[darkerFillRung(scale, theme.colors.white, isDark, step)];
32
27
  };
33
28
  /** Label for the solid variant's filled bg — derived from THAT fill, since hover/active swap it. */
34
29
  const labelFor = (theme, fill) => onFilled(fill, theme.colors.white, theme.colors.black);
30
+ /**
31
+ * The two-tone `:focus-visible` ring, from the palette's derived `focusRing` pair.
32
+ *
33
+ * Every variant spreads this. Before it, none of them defined `_focusVisible` at all, so every
34
+ * button in every consuming app fell through to Chakra's stock `shadows.outline` — one fixed blue
35
+ * that measured 1.83:1 on the canvas and 1.38:1 on a primary fill, failing WCAG 1.4.11 (3:1) on
36
+ * all nine brands. `focusRing.test.ts` is the gate that keeps this true.
37
+ */
38
+ const focusRing = (theme) => focusVisibleStyles(theme.colors);
35
39
  export const Button = {
36
- baseStyle: () => ({
40
+ // The ring is repeated on every variant below AND here, so a variant name this file does not
41
+ // define (a consumer's own, or an `IconButton` falling through) still gets an indicator.
42
+ baseStyle: ({ theme }) => ({
37
43
  borderRadius: "lg",
38
44
  fontWeight: 500,
39
45
  fontSize: "1rem",
@@ -42,10 +48,11 @@ export const Button = {
42
48
  opacity: 0.6,
43
49
  cursor: "not-allowed",
44
50
  },
51
+ ...focusRing(theme),
45
52
  }),
46
53
  variants: {
47
54
  solid: ({ theme, colorScheme = "primary" }) => {
48
- const fill = theme.colors[colorScheme][500];
55
+ const fill = theme.colors[colorScheme][buttonSolidRung(theme, colorScheme)];
49
56
  const hoverFill = darkerFill(theme, colorScheme, 0);
50
57
  const activeFill = darkerFill(theme, colorScheme, 1);
51
58
  const hoverLabel = labelFor(theme, hoverFill);
@@ -74,25 +81,26 @@ export const Button = {
74
81
  color: hoverLabel,
75
82
  },
76
83
  },
84
+ ...focusRing(theme),
77
85
  };
78
86
  },
79
87
  outline: ({ theme, colorScheme = "primary" }) => {
80
- const hoverFill = theme.colors[colorScheme][500];
88
+ // Same rung as `solid`'s fill, not raw [500] — keeps hover bg AA-safe for white text.
89
+ const hoverFill = theme.colors[colorScheme][buttonSolidRung(theme, colorScheme)];
81
90
  const activeFill = darkerFill(theme, colorScheme, 0);
91
+ const ink = onCanvasText(theme, colorScheme);
82
92
  return {
83
93
  border: "0.1rem solid",
84
- borderColor: theme.colors[colorScheme][500],
85
- color: onCanvasText(theme, colorScheme),
94
+ borderColor: ink,
95
+ color: ink,
86
96
  bg: "transparent",
87
97
  _hover: {
88
98
  bg: hoverFill,
89
99
  borderColor: activeFill,
90
- // Was a hardcoded `theme.colors.white` — fails AA for any colorScheme whose [500]
91
- // doesn't clear white contrast (e.g. emerald/rosewood primary in dark, 3.38/3.46).
92
100
  color: labelFor(theme, hoverFill),
93
101
  _disabled: {
94
102
  // bg: theme.colors[colorScheme][500],
95
- color: onCanvasText(theme, colorScheme),
103
+ color: ink,
96
104
  },
97
105
  },
98
106
  _active: {
@@ -101,8 +109,9 @@ export const Button = {
101
109
  },
102
110
  _loading: {
103
111
  // bg: theme.colors[colorScheme][500],
104
- color: onCanvasText(theme, colorScheme),
112
+ color: ink,
105
113
  },
114
+ ...focusRing(theme),
106
115
  };
107
116
  },
108
117
  ghost: ({ theme, colorScheme = "primary" }) => ({
@@ -115,6 +124,7 @@ export const Button = {
115
124
  _active: {
116
125
  bg: onCanvasHoverBg(theme, colorScheme, 24),
117
126
  },
127
+ ...focusRing(theme),
118
128
  }),
119
129
  link: ({ theme, colorScheme = "primary" }) => ({
120
130
  color: onCanvasText(theme, colorScheme),
@@ -127,22 +137,25 @@ export const Button = {
127
137
  _active: {
128
138
  color: onCanvasText(theme, colorScheme),
129
139
  },
140
+ ...focusRing(theme),
130
141
  }),
131
- unstyled: () => ({
142
+ // `unstyled` drops the fill, not the affordance: a focus indicator is not styling.
143
+ unstyled: ({ theme }) => ({
132
144
  bg: "transparent",
133
145
  color: "inherit",
134
146
  _hover: {
135
147
  bg: "transparent",
136
148
  },
149
+ ...focusRing(theme),
137
150
  }),
138
151
  // Theme-based two-tone gradient: each theme defines its own `gradient` {from,to} pair.
139
152
  // Ignores colorScheme; hover/active shift brightness so it works for any pair.
140
153
  gradient: ({ theme }) => {
141
- const g = theme.colors.gradient;
142
- const bg = `linear-gradient(135deg, ${g.from} 0%, ${g.to} 100%)`;
154
+ const g = resolveGradient(theme.colors.gradient, theme.colors.white, theme.colors.black);
155
+ const bg = gradientCss(g);
143
156
  return {
144
157
  bgImage: bg,
145
- color: onGradient(g.from, g.to, theme.colors.white, theme.colors.black),
158
+ color: g.ink,
146
159
  border: "none",
147
160
  _hover: {
148
161
  bgImage: bg,
@@ -160,6 +173,7 @@ export const Button = {
160
173
  filter: "brightness(0.92)",
161
174
  _hover: { bgImage: bg, filter: "brightness(0.92)" },
162
175
  },
176
+ ...focusRing(theme),
163
177
  };
164
178
  },
165
179
  },
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState, useRef, useEffect } from "react";
3
3
  import { Box, Button, ButtonGroup, IconButton, Menu, MenuButton, MenuItem, MenuList, Tooltip, } from "@chakra-ui/react";
4
4
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
5
- import { onGradient } from "../../Theme/tokens/builders/accentText.js";
5
+ import { resolveGradient, gradientCss } from "../../Theme/tokens/builders/gradientInk.js";
6
6
  import { hexToRgb } from "../../Theme/tokens/builders/color.js";
7
7
  import { rafThrottle } from "../../Utils/rafThrottle.js";
8
8
  export default function ButtonGroupIcon({ leftIcon, rightIcon, onLeftIconClick, onRightIconClick, buttonText, onButtonClick, onButtongroupClick, size, variant, color, buttonGroupStyle, buttonGroupLeftIconStyle, buttonGroupRightIconStyle, buttonStyle, onBlurLeftIcon, onBlurRightIcon, dropdownOptions, // New prop for dropdown options
@@ -46,9 +46,9 @@ rightIconDropdown, menulistStyle, menuItemStyle, isLoading, divider = true, left
46
46
  // keep the segments transparent (so it doesn't restart per button/icon), with a
47
47
  // translucent-white hover overlay for per-segment feedback.
48
48
  const isGradient = variant === "gradient";
49
- const gradientStops = theme.colors.gradient;
50
- const gradientBg = `linear-gradient(135deg, ${gradientStops.from} 0%, ${gradientStops.to} 100%)`;
51
- const gradientInk = onGradient(gradientStops.from, gradientStops.to, theme.colors.white, theme.colors.black);
49
+ const gradientStops = resolveGradient(theme.colors.gradient, theme.colors.white, theme.colors.black);
50
+ const gradientBg = gradientCss(gradientStops);
51
+ const gradientInk = gradientStops.ink;
52
52
  const whiteRgb = hexToRgb(theme.colors.white);
53
53
  const whiteOverlay = (alpha) => `rgba(${whiteRgb.r}, ${whiteRgb.g}, ${whiteRgb.b}, ${alpha})`;
54
54
  const gradientItemSx = isGradient
@@ -69,7 +69,7 @@ rightIconDropdown, menulistStyle, menuItemStyle, isLoading, divider = true, left
69
69
  // this theme-swap app never triggers) — our `bg` prop above only recolors the list
70
70
  // itself, not the inherited var, so items fell back to white until hover/focus (which
71
71
  // our own sx already overrides). Setting the var here fixes the rest state too.
72
- sx: { "--menu-bg": theme.colors.backgroundColor.light }, border: "1px solid", borderColor: theme.colors.boxborder[500], borderRadius: "xl", boxShadow: "lg", py: "0.375rem", minW: "12rem", overflow: "hidden", children: dropdownOptions === null || dropdownOptions === void 0 ? void 0 : dropdownOptions.map((option, index) => (_jsxs(MenuItem, { onClick: (event) => handleMenuClick(event, option), style: menuItemStyle, sx: {
72
+ sx: { "--menu-bg": theme.colors.backgroundColor.light }, borderRadius: "xl", boxShadow: "lg", py: "0.375rem", minW: "12rem", overflow: "hidden", children: dropdownOptions === null || dropdownOptions === void 0 ? void 0 : dropdownOptions.map((option, index) => (_jsxs(MenuItem, { onClick: (event) => handleMenuClick(event, option), style: menuItemStyle, sx: {
73
73
  display: "flex",
74
74
  alignItems: "center",
75
75
  gap: "0.5rem",
@@ -87,7 +87,7 @@ rightIconDropdown, menulistStyle, menuItemStyle, isLoading, divider = true, left
87
87
  mx: 0,
88
88
  borderRadius: "none",
89
89
  borderBottom: "1px solid",
90
- borderColor: theme.colors.boxborder[300],
90
+ borderColor: theme.colors.boxborder[200],
91
91
  }
92
92
  : {}),
93
93
  _hover: { bg: theme.colors.primary[50], color: theme.colors.primary[700] },
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Card as ChakraCard } from "@chakra-ui/react";
3
- export default function Card({ key, maxW, align, variant, direction, justify, children, size, color, overflow, sx, }) {
4
- return (_jsx(ChakraCard, { maxW: maxW, align: align, variant: variant, direction: direction, justify: justify, size: size, overflow: overflow, colorScheme: color, p: 4, sx: sx, children: children }, key));
3
+ export default function Card({ maxW, align, variant, direction, justify, children, size, color, overflow, sx, }) {
4
+ return (_jsx(ChakraCard, { maxW: maxW, align: align, variant: variant, direction: direction, justify: justify, size: size, overflow: overflow, colorScheme: color, p: 4, sx: sx, children: children }));
5
5
  }
@@ -15,6 +15,7 @@ const getCardStyles = (isActive, isNextUpgrade, popular, theme) => {
15
15
  badgeColor: `0.125rem solid ${theme.colors.green[500]}`,
16
16
  buttonColor: theme.colors.green[500],
17
17
  buttonColor50: theme.colors.green[50],
18
+ colorScheme: "green",
18
19
  });
19
20
  }
20
21
  if (isNextUpgrade) {
@@ -23,6 +24,7 @@ const getCardStyles = (isActive, isNextUpgrade, popular, theme) => {
23
24
  badgeColor: `0.125rem solid ${theme.colors.primary[500]}`,
24
25
  buttonColor: theme.colors.primary[500],
25
26
  buttonColor50: theme.colors.primary[50],
27
+ colorScheme: "primary",
26
28
  });
27
29
  }
28
30
  if (popular) {
@@ -31,6 +33,7 @@ const getCardStyles = (isActive, isNextUpgrade, popular, theme) => {
31
33
  badgeColor: `0.125rem solid ${theme.colors.primary[500]}`,
32
34
  buttonColor: theme.colors.primary[500],
33
35
  buttonColor50: theme.colors.primary[50],
36
+ colorScheme: "primary",
34
37
  });
35
38
  }
36
39
  return withOnButtonColor({
@@ -38,17 +41,14 @@ const getCardStyles = (isActive, isNextUpgrade, popular, theme) => {
38
41
  badgeColor: "",
39
42
  buttonColor: theme.colors.primary[500],
40
43
  buttonColor50: theme.colors.primary[50],
44
+ colorScheme: "primary",
41
45
  });
42
46
  };
43
47
  const PaymentCard = ({ plan, isActive = false, isNextUpgrade = false, billingCycle, onSelect, onHover, buttonLoading, isLoading = false, isRenewal = false, }) => {
44
48
  const theme = useCustomTheme();
45
- const { badgeText, badgeColor, buttonColor, buttonColor50, onButtonColor } = getCardStyles(isActive, isNextUpgrade, !!plan.popular, theme);
49
+ const { badgeText, badgeColor, buttonColor, buttonColor50, onButtonColor, colorScheme } = getCardStyles(isActive, isNextUpgrade, !!plan.popular, theme);
46
50
  const variantStyles = plan.buttonVariant === "outline"
47
- ? {
48
- borderColor: buttonColor,
49
- color: buttonColor,
50
- _hover: { bg: buttonColor50 },
51
- }
51
+ ? {}
52
52
  : {
53
53
  bg: buttonColor,
54
54
  color: onButtonColor,
@@ -60,6 +60,6 @@ const PaymentCard = ({ plan, isActive = false, isNextUpgrade = false, billingCyc
60
60
  // 🔹 Actual Card Content
61
61
  _jsxs(_Fragment, { children: [badgeText && (_jsx(Badge, { position: "absolute", top: "-0.75rem", left: "50%", transform: "translateX(-50%)", bg: buttonColor, color: onButtonColor, fontSize: "sm", px: 4, py: 1, borderRadius: "full", children: badgeText })), _jsxs(Box, { textAlign: "center", mb: 6, children: [_jsx(Flex, { justify: "center", align: "center", w: "3.125rem", h: "3.125rem", borderRadius: "lg", bg: buttonColor50, color: buttonColor, mx: "auto", mb: 4, children: plan.icon }), _jsx(Heading, { as: "h3", size: "lg", mb: 4, color: theme.colors.gray[800], children: plan.name }), (plan.yearlyPrice !== 0 || plan.monthlyPrice !== 0) && (_jsxs(Heading, { as: "h4", size: "2xl", mb: 1, color: theme.colors.gray[800], display: "flex", justifyContent: "center", children: [_jsx(Box, { fontSize: "1.5rem", children: "\u20B9" }), billingCycle === "yearly"
62
62
  ? plan.yearlyPrice
63
- : plan.monthlyPrice, _jsxs(Box, { display: "flex", flexDirection: "column", justifyContent: "end", ml: 1, children: [_jsx(Text, { fontSize: "0.9rem", fontWeight: "normal", color: theme.colors.gray[600], children: plan.billing }), _jsx(Text, { fontSize: "0.7rem", fontWeight: "normal", color: theme.colors.gray[600], children: plan.tax })] })] })), plan.priceDescription && (_jsx(Text, { color: theme.colors.green[800], mt: 2, children: plan === null || plan === void 0 ? void 0 : plan.priceDescription })), _jsx(Text, { color: theme.colors.gray[600], mt: 2, children: plan.description })] }), ((!isActive && plan.buttonText) || isRenewal) && (_jsx(Button, { isLoading: plan.plan_id === buttonLoading, loadingText: plan.buttonLoadingText, width: "full", variant: plan.buttonVariant, size: "lg", onClick: () => onSelect === null || onSelect === void 0 ? void 0 : onSelect(plan.plan_id), onMouseEnter: () => onHover === null || onHover === void 0 ? void 0 : onHover(plan.plan_id, "button", true), onMouseLeave: () => onHover === null || onHover === void 0 ? void 0 : onHover(plan.plan_id, "button", false), ...variantStyles, children: plan.buttonText })), _jsx(VStack, { align: "start", spacing: 3, mt: 6, children: plan.features.map((feature, i) => (_jsxs(Flex, { align: "center", children: [_jsx(Icon, { as: Check, color: theme.colors.green[500], mr: 2 }), _jsx(Text, { fontSize: "sm", children: feature })] }, i))) })] })) }) }));
63
+ : plan.monthlyPrice, _jsxs(Box, { display: "flex", flexDirection: "column", justifyContent: "end", ml: 1, children: [_jsx(Text, { fontSize: "0.9rem", fontWeight: "normal", color: theme.colors.gray[600], children: plan.billing }), _jsx(Text, { fontSize: "0.7rem", fontWeight: "normal", color: theme.colors.gray[600], children: plan.tax })] })] })), plan.priceDescription && (_jsx(Text, { color: theme.colors.green[800], mt: 2, children: plan === null || plan === void 0 ? void 0 : plan.priceDescription })), _jsx(Text, { color: theme.colors.gray[600], mt: 2, children: plan.description })] }), ((!isActive && plan.buttonText) || isRenewal) && (_jsx(Button, { isLoading: plan.plan_id === buttonLoading, loadingText: plan.buttonLoadingText, width: "full", variant: plan.buttonVariant, colorScheme: colorScheme, size: "lg", onClick: () => onSelect === null || onSelect === void 0 ? void 0 : onSelect(plan.plan_id), onMouseEnter: () => onHover === null || onHover === void 0 ? void 0 : onHover(plan.plan_id, "button", true), onMouseLeave: () => onHover === null || onHover === void 0 ? void 0 : onHover(plan.plan_id, "button", false), ...variantStyles, children: plan.buttonText })), _jsx(VStack, { align: "start", spacing: 3, mt: 6, children: plan.features.map((feature, i) => (_jsxs(Flex, { align: "center", children: [_jsx(Icon, { as: Check, color: theme.colors.green[500], mr: 2 }), _jsx(Text, { fontSize: "sm", children: feature })] }, i))) })] })) }) }));
64
64
  };
65
65
  export default PaymentCard;
@@ -21,7 +21,7 @@ export default function CheckBox({ label, labelFontSize, showLabelTooltip, label
21
21
  ...labelSx,
22
22
  }
23
23
  : { ...labelSx };
24
- return (_jsxs(_Fragment, { children: [_jsx(ChakraCheckbox, { ...aria, onClick: onClick, spacing: spacing !== null && spacing !== void 0 ? spacing : "0.5rem", isInvalid: isInvalid, colorScheme: color, iconColor: iconColor, iconSize: iconSize, isChecked: isChecked, isIndeterminate: isIndeterminate, onChange: onChange, isDisabled: isDisabled, size: size, value: value, defaultChecked: defaultChecked, borderColor: theme.colors.gray[500], display: "flex", alignItems: "center", sx: {
24
+ return (_jsxs(_Fragment, { children: [_jsx(ChakraCheckbox, { ...aria, onClick: onClick, spacing: spacing !== null && spacing !== void 0 ? spacing : "0.5rem", isInvalid: isInvalid, colorScheme: color, iconColor: iconColor, iconSize: iconSize, isChecked: isChecked, isIndeterminate: isIndeterminate, onChange: onChange, isDisabled: isDisabled, size: size, value: value, defaultChecked: defaultChecked, borderColor: theme.colors.boxborder[500], display: "flex", alignItems: "center", sx: {
25
25
  ...sx,
26
26
  ".chakra-checkbox__control": { w: controlSize, h: controlSize },
27
27
  }, children: label && (showLabelTooltip ? (_jsx(ToolTip, { label: labelTooltip !== null && labelTooltip !== void 0 ? labelTooltip : label, hasArrow: true, placement: "top", fontSize: "0.75rem", children: _jsx(Box, { as: "span", sx: clampStyles, fontSize: labelFontSize !== null && labelFontSize !== void 0 ? labelFontSize : "0.8125rem", color: theme.colors.text[700], fontWeight: 500, ml: 0, children: label }) })) : (_jsx(Box, { as: "span", sx: clampStyles, fontSize: labelFontSize !== null && labelFontSize !== void 0 ? labelFontSize : "0.8125rem", color: theme.colors.text[700], fontWeight: 500, ml: 0, children: label }))) }), error && _jsx(ErrorMessage, { errorMessage: errorMessage }), helperText && !error && _jsx(HelperText, { helperText: helperText })] }));
@@ -1,20 +1,22 @@
1
- import { resolveHoverTint } from "../../Theme/tokens/builders/outlineRung.js";
1
+ import { AA_NON_TEXT, liftToContrast, resolveHoverTint } from "../../Theme/tokens/builders/outlineRung.js";
2
+ import { onFilled } from "../../Theme/tokens/builders/accentText.js";
2
3
  export const Checkbox = {
3
4
  baseStyle: ({ theme, colorScheme = "primary" }) => {
4
5
  var _a;
5
6
  const palette = (_a = theme.colors[colorScheme]) !== null && _a !== void 0 ? _a : theme.colors.primary;
6
- // A browser probe found the checked checkbox's hover repeating its own resting `[600]` fill.
7
- // Chakra's stock control also carries a checked-hover at `_checked._hover` (this override
8
- // nests the other way, `_hover._checked`) — two different key paths landing on the same
9
- // selector, so whichever one the cascade picks must still differ from resting. Setting both
10
- // paths to the same lifted value removes that ambiguity outright.
7
+ // Both `_checked._hover` and `_hover._checked` paths get the same lifted value.
11
8
  const hoverChecked = resolveHoverTint(palette[600], palette[600]);
9
+ const checkedIcon = onFilled(palette[600], theme.colors.white, theme.colors.black);
10
+ const hoverCheckedIcon = onFilled(hoverChecked, theme.colors.white, theme.colors.black);
11
+ const focusRing = liftToContrast(palette[300], theme.colors.backgroundColor.main, AA_NON_TEXT);
12
12
  return {
13
13
  control: {
14
14
  width: "1.25rem",
15
15
  height: "1.25rem",
16
16
  borderWidth: "1.6px",
17
17
  borderRadius: "base",
18
+ // Without a resting colour Chakra falls back to its own gray.500.
19
+ borderColor: theme.colors.boxborder[500],
18
20
  transition: "background 0.15s, border-color 0.15s, box-shadow 0.15s",
19
21
  _disabled: {
20
22
  bg: theme.colors.background[50],
@@ -49,7 +51,7 @@ export const Checkbox = {
49
51
  },
50
52
  },
51
53
  _focus: {
52
- boxShadow: `0 0 0 2px ${palette[300]}`,
54
+ boxShadow: `0 0 0 2px ${focusRing}`,
53
55
  borderColor: palette[500],
54
56
  },
55
57
  _active: {
@@ -58,7 +60,10 @@ export const Checkbox = {
58
60
  },
59
61
  },
60
62
  icon: {
61
- color: theme.colors.background[50],
63
+ color: checkedIcon,
64
+ _hover: {
65
+ color: hoverCheckedIcon,
66
+ },
62
67
  },
63
68
  };
64
69
  },
@@ -11,7 +11,7 @@ export const FIELD_TRANSITION = "border-color 0.2s, box-shadow 0.2s";
11
11
  export const getFieldStateStyles = (theme, { error = false, focused = false } = {}) => {
12
12
  // [800], not [500]: WCAG 1.4.11 needs >=3.0 for a control boundary against any named surface
13
13
  // up to `muted` (lightest); [500] fails there, [800] clears all with margin.
14
- const idleBorder = theme.colors.boxborder[800];
14
+ const idleBorder = theme.colors.boxborder[500];
15
15
  const primary = theme.colors.primary[500];
16
16
  const errorColor = theme.colors.semanticText.error;
17
17
  const ringPrimary = theme.colors.boxShadow.primary;
@@ -3,7 +3,8 @@ import { useEffect, useRef, useState } from "react";
3
3
  import { Box, Flex, IconButton, Text } from "@chakra-ui/react";
4
4
  import { Check, Copy } from "lucide-react";
5
5
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
6
- import { accentTextOnCanvas } from "../../Theme/tokens/builders/accentText.js";
6
+ import { accentTextOnCanvas, AA_NORMAL_TEXT } from "../../Theme/tokens/builders/accentText.js";
7
+ import { liftToContrast } from "../../Theme/tokens/builders/outlineRung.js";
7
8
  import ToolTip from "../ToolTip/ToolTip.js";
8
9
  const CopyButton = ({ value, variant = "icon", label = "Copy", copiedLabel = "Copied!", tooltip = "Copy", feedbackDuration = 1500, iconSize = 16, size = "sm", onCopy, }) => {
9
10
  const theme = useCustomTheme();
@@ -29,12 +30,15 @@ const CopyButton = ({ value, variant = "icon", label = "Copy", copiedLabel = "Co
29
30
  const accent = accentTextOnCanvas(theme.colors.primary, theme.colors.backgroundColor.main);
30
31
  const success = theme.colors.semanticText.success;
31
32
  if (variant === "menu-item") {
32
- return (_jsxs(Flex, { align: "center", gap: "0.5rem", px: "12px", py: "8px", width: "100%", cursor: "pointer", borderRadius: "md", transition: "background 0.15s ease", _hover: { bg: theme.colors.gray[100] }, onClick: handleCopy, children: [copied ? _jsx(Check, { size: iconSize, color: success }) : _jsx(Copy, { size: iconSize, color: accent }), _jsx(Box, { fontSize: "14px", fontWeight: 500, color: copied ? success : accent, children: copied ? copiedLabel : label })] }));
33
+ // Ink also sits on the row's own hover fill (gray[100]), not just the canvas resolve against it.
34
+ const hoverAccent = accentTextOnCanvas(theme.colors.primary, theme.colors.gray[100]);
35
+ const hoverSuccess = liftToContrast(theme.colors.semantic.success[500], theme.colors.gray[100], AA_NORMAL_TEXT);
36
+ return (_jsxs(Flex, { align: "center", gap: "0.5rem", px: "12px", py: "8px", width: "100%", cursor: "pointer", borderRadius: "md", transition: "background 0.15s ease", _hover: { bg: theme.colors.gray[100] }, onClick: handleCopy, children: [copied ? (_jsx(Check, { size: iconSize, color: hoverSuccess })) : (_jsx(Copy, { size: iconSize, color: hoverAccent })), _jsx(Box, { fontSize: "14px", fontWeight: 500, color: copied ? hoverSuccess : hoverAccent, children: copied ? copiedLabel : label })] }));
33
37
  }
34
38
  if (variant === "button") {
35
39
  return (_jsxs(Flex, { as: "button", align: "center", gap: "6px", px: "12px", py: "6px", borderRadius: "lg", border: "1px solid",
36
40
  // [800], not [500]: a real control boundary needs >=3:1 on every surface up to `muted`.
37
- borderColor: copied ? success : theme.colors.boxborder[800], bg: "transparent", color: copied ? success : theme.colors.gray[700], fontSize: "14px", fontWeight: 500, transition: "all 0.15s ease", _hover: { borderColor: accent, color: accent }, onClick: handleCopy, children: [copied ? _jsx(Check, { size: iconSize }) : _jsx(Copy, { size: iconSize }), _jsx(Text, { children: copied ? copiedLabel : label })] }));
41
+ borderColor: copied ? success : theme.colors.boxborder[500], bg: "transparent", color: copied ? success : theme.colors.gray[700], fontSize: "14px", fontWeight: 500, transition: "all 0.15s ease", _hover: { borderColor: accent, color: accent }, onClick: handleCopy, children: [copied ? _jsx(Check, { size: iconSize }) : _jsx(Copy, { size: iconSize }), _jsx(Text, { children: copied ? copiedLabel : label })] }));
38
42
  }
39
43
  return (_jsx(ToolTip, { label: copied ? copiedLabel : tooltip, placement: "top", children: _jsx(IconButton, { "aria-label": tooltip, size: size, variant: "ghost", onClick: handleCopy, color: copied ? success : theme.colors.gray[500], _hover: { color: accent, bg: theme.colors.primary[50] }, icon: copied ? _jsx(Check, { size: iconSize }) : _jsx(Copy, { size: iconSize }) }) }));
40
44
  };
@@ -14,6 +14,6 @@ const EditModuleModal = ({ isOpen, onClose, initialName, isLoading, onSubmit, la
14
14
  // [200] is the decorative divider rung (~1.2:1, correct for the ModalHeader border
15
15
  // above) — a real control's resting outline needs 1.4.11's 3:1, which is what every
16
16
  // other input in this library (TextInput, NumberInput, DatePicker) reads from [800].
17
- borderColor: colors.boxborder[800], mb: 5 }), _jsxs(HStack, { justifyContent: "flex-end", spacing: 3, children: [_jsx(Button, { label: labels.cancel, onClick: onClose, variant: "outline", colorScheme: "gray", size: "sm" }), _jsx(Button, { label: labels.update, onClick: () => onSubmit(name.trim()), colorScheme: "primary", size: "sm", isLoading: isLoading, isDisabled: !name.trim() })] })] })] })] }));
17
+ borderColor: colors.boxborder[500], mb: 5 }), _jsxs(HStack, { justifyContent: "flex-end", spacing: 3, children: [_jsx(Button, { label: labels.cancel, onClick: onClose, variant: "outline", colorScheme: "gray", size: "sm" }), _jsx(Button, { label: labels.update, onClick: () => onSubmit(name.trim()), colorScheme: "primary", size: "sm", isLoading: isLoading, isDisabled: !name.trim() })] })] })] })] }));
18
18
  };
19
19
  export default EditModuleModal;
@@ -5,7 +5,8 @@ import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
5
5
  import Button from "../Button/Button.js";
6
6
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
7
7
  import { onFilled } from "../../Theme/tokens/builders/accentText.js";
8
- export const CalendarPanel = ({ currentMonth, setCurrentMonth, today, isRange, tempDate, tempRangeStart, tempRangeEnd, isSameDay, isBefore, isAfter, minDate, maxDate, disablePastDates, disableFutureDates, disableToday, onDaySelect, hoveredDate, onDayHover, renderWeekdays, }) => {
8
+ import { DAY_CLASS, dayAccessibleName, dayStateClassName, resolveDayStateVisual, } from "./dayStates.js";
9
+ export const CalendarPanel = ({ currentMonth, setCurrentMonth, today, isRange, tempDate, tempRangeStart, tempRangeEnd, isSameDay, isBefore, isAfter, minDate, maxDate, disablePastDates, disableFutureDates, disableToday, onDaySelect, hoveredDate, onDayHover, renderWeekdays, dayStates, renderDayContent, }) => {
9
10
  const theme = useCustomTheme();
10
11
  const rangeBg = theme.colors.primary.opacity[16];
11
12
  const isViewingCurrentMonth = currentMonth.getFullYear() === today.getFullYear() &&
@@ -20,7 +21,7 @@ export const CalendarPanel = ({ currentMonth, setCurrentMonth, today, isRange, t
20
21
  const hasRange = !!(rangeStart && rangeEnd && !isSameDay(rangeStart, rangeEnd));
21
22
  const selectStyles = {
22
23
  border: "1px solid",
23
- // boxborder[500] is the control-outline rung the sibling pickers already use; boxborder[300]
24
+ // boxborder[500] is the control-outline rung the sibling pickers already use; boxborder[200]
24
25
  // is decorative and measured 1.85:1 on the dark canvas — the select read as borderless.
25
26
  borderColor: theme.colors.boxborder[500],
26
27
  borderRadius: "md",
@@ -45,6 +46,7 @@ export const CalendarPanel = ({ currentMonth, setCurrentMonth, today, isRange, t
45
46
  },
46
47
  };
47
48
  const renderDays = () => {
49
+ var _a;
48
50
  const monthStart = startOfMonth(currentMonth);
49
51
  const monthEnd = endOfMonth(currentMonth);
50
52
  const startDate = startOfWeek(monthStart);
@@ -63,12 +65,17 @@ export const CalendarPanel = ({ currentMonth, setCurrentMonth, today, isRange, t
63
65
  const isSelected = !!(!isRange && tempDate && isSameDay(thisDay, tempDate));
64
66
  const isTentativeEnd = isEnd && isTentative;
65
67
  const circleSolid = !!(isSelected || (isRange && isStart) || (isEnd && !isTentative));
68
+ // Marking is not disabling: only the `disabled` state key blocks selection, and only
69
+ // because the caller asked for it by name.
70
+ const states = (_a = dayStates === null || dayStates === void 0 ? void 0 : dayStates(thisDay)) !== null && _a !== void 0 ? _a : [];
71
+ const stateVisual = states.length ? resolveDayStateVisual(states, theme.colors) : null;
66
72
  const disabled = !isInCurrentMonth ||
67
73
  !!(minDate && isBefore(thisDay, minDate)) ||
68
74
  !!(maxDate && isAfter(thisDay, maxDate)) ||
69
75
  !!(disablePastDates && isBefore(thisDay, today) && !isSameDay(thisDay, today)) ||
70
76
  !!(disableFutureDates && isAfter(thisDay, today) && !isSameDay(thisDay, today)) ||
71
- !!(disableToday && isToday);
77
+ !!(disableToday && isToday) ||
78
+ !!(stateVisual === null || stateVisual === void 0 ? void 0 : stateVisual.blocksSelection);
72
79
  // Connected range band painted on the cell background; start/end use a
73
80
  // half gradient so the band meets the solid day circle cleanly.
74
81
  let cellBg;
@@ -82,6 +89,9 @@ export const CalendarPanel = ({ currentMonth, setCurrentMonth, today, isRange, t
82
89
  else if (isEnd)
83
90
  cellBg = `linear-gradient(to right, ${rangeBg} 50%, transparent 50%)`;
84
91
  }
92
+ // Selection feedback outranks a state tint — the band is what tells the user what they picked.
93
+ if (!cellBg && (stateVisual === null || stateVisual === void 0 ? void 0 : stateVisual.cellBg))
94
+ cellBg = stateVisual.cellBg;
85
95
  // Solid fill (selected/range-endpoint) needs the ink checked against that
86
96
  // specific fill — `primary[500]` doesn't reliably clear AA for white text on
87
97
  // every brand/mode (same gap the solid Button variant already accounts for).
@@ -102,11 +112,20 @@ export const CalendarPanel = ({ currentMonth, setCurrentMonth, today, isRange, t
102
112
  : isToday
103
113
  ? `1px solid ${theme.colors.primary[300]}`
104
114
  : "1px solid transparent";
105
- days.push(_jsx(Box, { h: "2rem", display: "flex", alignItems: "center", justifyContent: "center", style: cellBg ? { background: cellBg } : undefined, children: _jsx(Box, { as: "button", type: "button", disabled: disabled, onClick: () => !disabled && onDaySelect(new Date(thisDay)), onMouseEnter: () => !disabled && (onDayHover === null || onDayHover === void 0 ? void 0 : onDayHover(new Date(thisDay))), w: "1.75rem", h: "1.75rem", borderRadius: "full", display: "flex", alignItems: "center", justifyContent: "center", fontSize: "0.8125rem", fontWeight: circleSolid ? 600 : 500, lineHeight: "1", cursor: disabled ? "not-allowed" : "pointer", bg: circleSolid ? solidFill : "transparent", color: circleColor, border: circleBorder, transition: "background 0.12s, color 0.12s", _hover: disabled
115
+ // A filled circle owns its own ink (checked against that fill by `onFilled`), so a state
116
+ // never repaints a selected day — it would undo that contrast guarantee.
117
+ const dayColor = !circleSolid && (stateVisual === null || stateVisual === void 0 ? void 0 : stateVisual.color) ? stateVisual.color : circleColor;
118
+ const dayBorder = !circleSolid && (stateVisual === null || stateVisual === void 0 ? void 0 : stateVisual.border) ? stateVisual.border : circleBorder;
119
+ const customContent = renderDayContent ? renderDayContent(thisDay, states) : null;
120
+ const markerColor = customContent == null && (stateVisual === null || stateVisual === void 0 ? void 0 : stateVisual.markerColor) ? stateVisual.markerColor : null;
121
+ const hasDayOverlay = customContent != null || markerColor != null;
122
+ days.push(_jsx(Box, { h: "2rem", display: "flex", alignItems: "center", justifyContent: "center", style: cellBg ? { background: cellBg } : undefined, children: _jsxs(Box, { as: "button", type: "button", disabled: disabled, className: dayStates ? dayStateClassName(states) : undefined, "aria-label": dayStates ? dayAccessibleName(format(thisDay, "d MMMM yyyy"), states) : undefined, onClick: () => !disabled && onDaySelect(new Date(thisDay)), onMouseEnter: () => !disabled && (onDayHover === null || onDayHover === void 0 ? void 0 : onDayHover(new Date(thisDay))), position: hasDayOverlay ? "relative" : undefined, w: "1.75rem", h: "1.75rem", borderRadius: "full", display: "flex", alignItems: "center", justifyContent: "center", fontSize: "0.8125rem", fontWeight: circleSolid ? 600 : 500, lineHeight: "1", cursor: disabled ? "not-allowed" : "pointer", bg: circleSolid ? solidFill : "transparent", color: dayColor, textDecoration: (stateVisual === null || stateVisual === void 0 ? void 0 : stateVisual.strikethrough) ? "line-through" : undefined, border: dayBorder, transition: "background 0.12s, color 0.12s", _hover: disabled
106
123
  ? {}
107
124
  : circleSolid
108
125
  ? { bg: solidHoverFill, color: circleHoverColor }
109
- : { bg: rangeBg }, children: format(thisDay, "d") }) }, thisDay.toString()));
126
+ : { bg: rangeBg }, children: [format(thisDay, "d"), hasDayOverlay && (_jsx(Box, { as: "span", className: `${DAY_CLASS}__content`, position: "absolute", left: 0, right: 0, bottom: "0.0625rem", display: "flex", alignItems: "flex-end", justifyContent: "center", lineHeight: "1", fontSize: "0.5rem",
127
+ // The overlay is decoration: clicks belong to the day button under it.
128
+ pointerEvents: "none", children: customContent !== null && customContent !== void 0 ? customContent : (_jsx(Box, { as: "span", className: `${DAY_CLASS}__marker`, w: "0.25rem", h: "0.25rem", borderRadius: "full", bg: markerColor })) }))] }) }, thisDay.toString()));
110
129
  day = addDays(day, 1);
111
130
  }
112
131
  rows.push(_jsx(Grid, { templateColumns: "repeat(7, 1fr)", gap: 0, children: days }, day.toString()));