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.
- package/dist/Components/Accordion/Accordion.js +5 -3
- package/dist/Components/AppSwitcher/AppMark.d.ts +19 -0
- package/dist/Components/AppSwitcher/AppMark.js +62 -0
- package/dist/Components/AppSwitcher/AppSwitcher.d.ts +4 -0
- package/dist/Components/AppSwitcher/AppSwitcher.js +315 -0
- package/dist/Components/AppSwitcher/AppSwitcherProps.d.ts +64 -0
- package/dist/Components/AppSwitcher/AppSwitcherProps.js +86 -0
- package/dist/Components/AppSwitcher/useAppSwitcherShortcut.d.ts +3 -0
- package/dist/Components/AppSwitcher/useAppSwitcherShortcut.js +31 -0
- package/dist/Components/AppearanceSettings/AppearanceSettings.js +2 -1
- package/dist/Components/Button/Button.d.ts +2 -2
- package/dist/Components/Button/Button.js +4 -3
- package/dist/Components/Button/Button.styles.js +39 -25
- package/dist/Components/Button/ButtonProps.d.ts +6 -1
- package/dist/Components/ButtonGroupIcon/ButtonGroupIcon.js +6 -6
- package/dist/Components/Card/Card.d.ts +1 -1
- package/dist/Components/Card/Card.js +2 -2
- package/dist/Components/Card/CardProps.d.ts +0 -1
- package/dist/Components/Card/PaymentCard/PaymentCard.js +7 -7
- package/dist/Components/Checkbox/Checkbox.js +1 -1
- package/dist/Components/Checkbox/Checkbox.styles.js +12 -7
- package/dist/Components/Common/fieldStyles.js +1 -1
- package/dist/Components/CopyButton/CopyButton.js +6 -2
- package/dist/Components/CustomModulesTable/EditModuleModal.js +1 -1
- package/dist/Components/DatePicker/CalendarPanel.d.ts +5 -0
- package/dist/Components/DatePicker/CalendarPanel.js +24 -5
- package/dist/Components/DatePicker/DatePickerProps.d.ts +21 -0
- package/dist/Components/DatePicker/RangeDatePicker.js +4 -4
- package/dist/Components/DatePicker/SingleDatePicker.js +2 -2
- package/dist/Components/DatePicker/TimeOnlyPicker.js +1 -1
- package/dist/Components/DatePicker/dayStates.d.ts +56 -0
- package/dist/Components/DatePicker/dayStates.js +87 -0
- package/dist/Components/Dropdown/DropDown.js +7 -15
- package/dist/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.js +1 -1
- package/dist/Components/EmptyState/EmptyState.js +2 -1
- package/dist/Components/FilePreview/FilePreview.js +1 -1
- package/dist/Components/FileUpload/FileUpload.js +5 -4
- package/dist/Components/FileUpload/FileUploadProps.d.ts +3 -1
- package/dist/Components/FileUpload/constants.js +1 -0
- package/dist/Components/FilterSidebar/FilterSidebar.js +4 -4
- package/dist/Components/FilterSidebar/filterHoverStyle.d.ts +0 -9
- package/dist/Components/FilterSidebar/filterHoverStyle.js +4 -10
- package/dist/Components/Form/FormWrapper.js +1 -1
- package/dist/Components/Header/components/mobileMenu.js +12 -3
- package/dist/Components/Input/TextInput.styles.js +6 -4
- package/dist/Components/InputTextArea/InputTextArea.style.js +5 -4
- package/dist/Components/KanbanBoard/KanbanBoard.js +5 -45
- package/dist/Components/LimitReachedModal/LimitReachedModal.js +4 -5
- package/dist/Components/Loading/Loading.js +15 -14
- package/dist/Components/MultiSelect/MultiSelect.js +1 -1
- package/dist/Components/NavigationBar/NavigationBar.js +3 -3
- package/dist/Components/NoteTextArea/NoteTextArea.js +9 -4
- package/dist/Components/NumberInput/NumberInput.js +3 -1
- package/dist/Components/NumberInput/NumberInput.styles.js +5 -4
- package/dist/Components/OrgSwitcher/OrgSwitcher.js +2 -2
- package/dist/Components/PdfViewer/PdfViewer.js +6 -1
- package/dist/Components/PinInput/PinInput.js +1 -1
- package/dist/Components/PlanPill/PlanPill.js +5 -5
- package/dist/Components/PlanPill/planPillGradient.d.ts +2 -14
- package/dist/Components/PlanPill/planPillGradient.js +3 -15
- package/dist/Components/Primitives/Primitives.d.ts +6 -0
- package/dist/Components/Primitives/Primitives.js +113 -0
- package/dist/Components/ProductCard/ProductPrice.js +1 -1
- package/dist/Components/ProductCard/ProductReview.js +6 -1
- package/dist/Components/ProductCard/ProductTags.js +1 -1
- package/dist/Components/ProfileCard/ProfileCard.js +1 -1
- package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +1 -1
- package/dist/Components/RadioButton/RadioButton.js +3 -2
- package/dist/Components/Reorder/Reorder.js +1 -1
- package/dist/Components/ScrollToTop/ScrollToTop.js +2 -0
- package/dist/Components/ScrollbarBox/ScrollbarBox.d.ts +13 -0
- package/dist/Components/ScrollbarBox/ScrollbarBox.js +11 -0
- package/dist/Components/Search/Search.js +2 -2
- package/dist/Components/SearchSelect/SearchSelect.js +14 -9
- package/dist/Components/SegmentedControl/SegmentedControl.d.ts +2 -0
- package/dist/Components/SegmentedControl/SegmentedControl.js +58 -0
- package/dist/Components/SegmentedControl/SegmentedControlProps.d.ts +16 -0
- package/dist/Components/SegmentedControl/SegmentedControlProps.js +2 -0
- package/dist/Components/Select/Select.d.ts +1 -1
- package/dist/Components/Select/Select.js +4 -2
- package/dist/Components/Select/Select.styles.js +3 -2
- package/dist/Components/Select/SelectProps.d.ts +3 -0
- package/dist/Components/SelectSearch/SelectSearch.js +7 -4
- package/dist/Components/SelectV2/SelectV2.js +18 -14
- package/dist/Components/SideBar/SecondaryBar.js +1 -1
- package/dist/Components/SideBar/SideBar.js +1 -1
- package/dist/Components/SideBar/components/MenuPopoverContent.js +2 -2
- package/dist/Components/Slider/Slider.js +8 -1
- package/dist/Components/StageProgress/StageProgress.js +2 -9
- package/dist/Components/StageProgress/StepperStage.js +2 -2
- package/dist/Components/Table/Table.d.ts +1 -1
- package/dist/Components/Table/Table.js +17 -24
- package/dist/Components/Table/TableProps.d.ts +4 -0
- package/dist/Components/Table/components/Pagination.js +1 -1
- package/dist/Components/Table/components/TableActions.js +2 -2
- package/dist/Components/Table/components/TableBody.js +41 -12
- package/dist/Components/Table/components/TableGroupRow.js +1 -1
- package/dist/Components/Table/components/TableHeader.js +21 -8
- package/dist/Components/Table/components/TableSearch.js +1 -1
- package/dist/Components/Table/filters/ActiveFilters.js +2 -18
- package/dist/Components/Table/settings/ManageColumns.js +4 -17
- package/dist/Components/Table/settings/TableSettings.js +5 -11
- package/dist/Components/Table/variants/TableVariantContext.d.ts +4 -0
- package/dist/Components/Table/variants/TableVariantContext.js +17 -0
- package/dist/Components/Table/variants/classic.d.ts +6 -0
- package/dist/Components/Table/variants/classic.js +47 -0
- package/dist/Components/Table/variants/index.d.ts +7 -0
- package/dist/Components/Table/variants/index.js +27 -0
- package/dist/Components/Table/variants/pillInk.d.ts +6 -0
- package/dist/Components/Table/variants/pillInk.js +21 -0
- package/dist/Components/Table/variants/studio.d.ts +6 -0
- package/dist/Components/Table/variants/studio.js +50 -0
- package/dist/Components/Table/variants/tokens.d.ts +49 -0
- package/dist/Components/Table/variants/tokens.js +2 -0
- package/dist/Components/Tag/Tag.styles.js +9 -8
- package/dist/Components/Timeline/Timeline.js +2 -2
- package/dist/Components/Toaster/Toaster.js +1 -1
- package/dist/Components/Toggle/TableToggle.js +11 -7
- package/dist/Components/ToggleSwitch/ToggleSwitch.d.ts +2 -0
- package/dist/Components/ToggleSwitch/ToggleSwitch.js +18 -0
- package/dist/Components/ToggleSwitch/ToggleSwitchProps.d.ts +11 -0
- package/dist/Components/ToggleSwitch/ToggleSwitchProps.js +2 -0
- package/dist/Components/ToolTip/ToolTip.js +6 -6
- package/dist/Components/ToolTip/ToolTipProps.d.ts +3 -1
- package/dist/Components/Trail/TrailWorks.js +1 -1
- package/dist/Components/UpgradeButton/UpgradeButton.js +3 -3
- package/dist/Constants/Sidebar.js +3 -2
- package/dist/Theme/assertPalette.d.ts +1 -1
- package/dist/Theme/assertPalette.js +3 -2
- package/dist/Theme/chakra/Menu.styles.d.ts +3 -0
- package/dist/Theme/chakra/Menu.styles.js +5 -0
- package/dist/Theme/chakra/Popover.styles.d.ts +3 -0
- package/dist/Theme/chakra/Popover.styles.js +5 -1
- package/dist/Theme/chakra/componentStyles.d.ts +6 -0
- package/dist/Theme/chakra/componentStyles.js +5 -5
- package/dist/Theme/chakra/createBrandTheme.js +10 -16
- package/dist/Theme/chakra/focusRing.styles.d.ts +52 -0
- package/dist/Theme/chakra/focusRing.styles.js +46 -0
- package/dist/Theme/provider/ThemeSwitcher.js +5 -2
- package/dist/Theme/tokens/brands/index.js +6 -1
- package/dist/Theme/tokens/brands/zinc/palette.dark.d.ts +1 -0
- package/dist/Theme/tokens/builders/buildDarkPalette.js +6 -1
- package/dist/Theme/tokens/builders/chartColorsFromTheme.js +1 -1
- package/dist/Theme/tokens/builders/focusRing.d.ts +52 -0
- package/dist/Theme/tokens/builders/focusRing.js +92 -0
- package/dist/Theme/tokens/builders/gradientInk.d.ts +22 -0
- package/dist/Theme/tokens/builders/gradientInk.js +28 -0
- package/dist/Theme/tokens/builders/index.d.ts +4 -0
- package/dist/Theme/tokens/builders/index.js +4 -0
- package/dist/Theme/tokens/builders/outlineRung.d.ts +46 -3
- package/dist/Theme/tokens/builders/outlineRung.js +101 -5
- package/dist/Theme/tokens/builders/placeholderInk.d.ts +19 -0
- package/dist/Theme/tokens/builders/placeholderInk.js +35 -0
- package/dist/Theme/tokens/builders/resolvedRungs.d.ts +5 -1
- package/dist/Theme/tokens/builders/resolvedRungs.js +7 -2
- package/dist/Theme/tokens/builders/rowStates.d.ts +13 -0
- package/dist/Theme/tokens/builders/rowStates.js +19 -0
- package/dist/Theme/tokens/builders/scrollbar.d.ts +12 -0
- package/dist/Theme/tokens/builders/scrollbar.js +57 -0
- package/dist/Theme/tokens/builders/solidFillRung.d.ts +4 -0
- package/dist/Theme/tokens/builders/solidFillRung.js +33 -0
- package/dist/Theme/tokens/builders/surfaceRungs.d.ts +5 -0
- package/dist/Theme/tokens/builders/surfaceRungs.js +20 -5
- package/dist/Theme/tokens/types.d.ts +21 -1
- package/dist/esm/Components/Accordion/Accordion.js +5 -3
- package/dist/esm/Components/AppSwitcher/AppMark.js +56 -0
- package/dist/esm/Components/AppSwitcher/AppSwitcher.js +280 -0
- package/dist/esm/Components/AppSwitcher/AppSwitcherProps.js +78 -0
- package/dist/esm/Components/AppSwitcher/useAppSwitcherShortcut.js +27 -0
- package/dist/esm/Components/AppearanceSettings/AppearanceSettings.js +2 -1
- package/dist/esm/Components/Button/Button.js +5 -4
- package/dist/esm/Components/Button/Button.styles.js +40 -26
- package/dist/esm/Components/ButtonGroupIcon/ButtonGroupIcon.js +6 -6
- package/dist/esm/Components/Card/Card.js +2 -2
- package/dist/esm/Components/Card/PaymentCard/PaymentCard.js +7 -7
- package/dist/esm/Components/Checkbox/Checkbox.js +1 -1
- package/dist/esm/Components/Checkbox/Checkbox.styles.js +13 -8
- package/dist/esm/Components/Common/fieldStyles.js +1 -1
- package/dist/esm/Components/CopyButton/CopyButton.js +7 -3
- package/dist/esm/Components/CustomModulesTable/EditModuleModal.js +1 -1
- package/dist/esm/Components/DatePicker/CalendarPanel.js +24 -5
- package/dist/esm/Components/DatePicker/RangeDatePicker.js +4 -4
- package/dist/esm/Components/DatePicker/SingleDatePicker.js +2 -2
- package/dist/esm/Components/DatePicker/TimeOnlyPicker.js +1 -1
- package/dist/esm/Components/DatePicker/dayStates.js +79 -0
- package/dist/esm/Components/Dropdown/DropDown.js +7 -15
- package/dist/esm/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.js +1 -1
- package/dist/esm/Components/EmptyState/EmptyState.js +2 -1
- package/dist/esm/Components/FilePreview/FilePreview.js +1 -1
- package/dist/esm/Components/FileUpload/FileUpload.js +6 -5
- package/dist/esm/Components/FileUpload/constants.js +1 -0
- package/dist/esm/Components/FilterSidebar/FilterSidebar.js +4 -4
- package/dist/esm/Components/FilterSidebar/filterHoverStyle.js +4 -10
- package/dist/esm/Components/Form/FormWrapper.js +1 -1
- package/dist/esm/Components/Header/components/mobileMenu.js +12 -3
- package/dist/esm/Components/Input/TextInput.styles.js +6 -4
- package/dist/esm/Components/InputTextArea/InputTextArea.style.js +5 -4
- package/dist/esm/Components/KanbanBoard/KanbanBoard.js +5 -45
- package/dist/esm/Components/LimitReachedModal/LimitReachedModal.js +4 -5
- package/dist/esm/Components/Loading/Loading.js +12 -11
- package/dist/esm/Components/MultiSelect/MultiSelect.js +1 -1
- package/dist/esm/Components/NavigationBar/NavigationBar.js +3 -3
- package/dist/esm/Components/NoteTextArea/NoteTextArea.js +9 -4
- package/dist/esm/Components/NumberInput/NumberInput.js +4 -2
- package/dist/esm/Components/NumberInput/NumberInput.styles.js +5 -4
- package/dist/esm/Components/OrgSwitcher/OrgSwitcher.js +2 -2
- package/dist/esm/Components/PdfViewer/PdfViewer.js +6 -1
- package/dist/esm/Components/PinInput/PinInput.js +1 -1
- package/dist/esm/Components/PlanPill/PlanPill.js +6 -6
- package/dist/esm/Components/PlanPill/planPillGradient.js +3 -15
- package/dist/esm/Components/Primitives/Primitives.js +6 -0
- package/dist/esm/Components/ProductCard/ProductPrice.js +1 -1
- package/dist/esm/Components/ProductCard/ProductReview.js +6 -1
- package/dist/esm/Components/ProductCard/ProductTags.js +1 -1
- package/dist/esm/Components/ProfileCard/ProfileCard.js +1 -1
- package/dist/esm/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +1 -1
- package/dist/esm/Components/RadioButton/RadioButton.js +3 -2
- package/dist/esm/Components/Reorder/Reorder.js +1 -1
- package/dist/esm/Components/ScrollToTop/ScrollToTop.js +2 -0
- package/dist/esm/Components/ScrollbarBox/ScrollbarBox.js +9 -0
- package/dist/esm/Components/Search/Search.js +2 -2
- package/dist/esm/Components/SearchSelect/SearchSelect.js +14 -9
- package/dist/esm/Components/SegmentedControl/SegmentedControl.js +55 -0
- package/dist/esm/Components/SegmentedControl/SegmentedControlProps.js +1 -0
- package/dist/esm/Components/Select/Select.js +5 -3
- package/dist/esm/Components/Select/Select.styles.js +3 -2
- package/dist/esm/Components/SelectSearch/SelectSearch.js +7 -4
- package/dist/esm/Components/SelectV2/SelectV2.js +18 -14
- package/dist/esm/Components/SideBar/SecondaryBar.js +1 -1
- package/dist/esm/Components/SideBar/SideBar.js +1 -1
- package/dist/esm/Components/SideBar/components/MenuPopoverContent.js +2 -2
- package/dist/esm/Components/Slider/Slider.js +8 -1
- package/dist/esm/Components/StageProgress/StageProgress.js +2 -9
- package/dist/esm/Components/StageProgress/StepperStage.js +2 -2
- package/dist/esm/Components/Table/Table.js +17 -24
- package/dist/esm/Components/Table/components/Pagination.js +1 -1
- package/dist/esm/Components/Table/components/TableActions.js +2 -2
- package/dist/esm/Components/Table/components/TableBody.js +42 -13
- package/dist/esm/Components/Table/components/TableGroupRow.js +1 -1
- package/dist/esm/Components/Table/components/TableHeader.js +21 -8
- package/dist/esm/Components/Table/components/TableSearch.js +1 -1
- package/dist/esm/Components/Table/filters/ActiveFilters.js +2 -18
- package/dist/esm/Components/Table/settings/ManageColumns.js +4 -17
- package/dist/esm/Components/Table/settings/TableSettings.js +5 -11
- package/dist/esm/Components/Table/variants/TableVariantContext.js +13 -0
- package/dist/esm/Components/Table/variants/classic.js +43 -0
- package/dist/esm/Components/Table/variants/index.js +9 -0
- package/dist/esm/Components/Table/variants/pillInk.js +18 -0
- package/dist/esm/Components/Table/variants/studio.js +46 -0
- package/dist/esm/Components/Table/variants/tokens.js +1 -0
- package/dist/esm/Components/Tag/Tag.styles.js +10 -9
- package/dist/esm/Components/Timeline/Timeline.js +2 -2
- package/dist/esm/Components/Toaster/Toaster.js +1 -1
- package/dist/esm/Components/Toggle/TableToggle.js +11 -7
- package/dist/esm/Components/ToggleSwitch/ToggleSwitch.js +15 -0
- package/dist/esm/Components/ToggleSwitch/ToggleSwitchProps.js +1 -0
- package/dist/esm/Components/ToolTip/ToolTip.js +6 -6
- package/dist/esm/Components/Trail/TrailWorks.js +1 -1
- package/dist/esm/Components/UpgradeButton/UpgradeButton.js +3 -3
- package/dist/esm/Constants/Sidebar.js +3 -2
- package/dist/esm/Theme/assertPalette.js +3 -2
- package/dist/esm/Theme/chakra/Menu.styles.js +5 -0
- package/dist/esm/Theme/chakra/Popover.styles.js +5 -1
- package/dist/esm/Theme/chakra/componentStyles.js +5 -5
- package/dist/esm/Theme/chakra/createBrandTheme.js +10 -16
- package/dist/esm/Theme/chakra/focusRing.styles.js +40 -0
- package/dist/esm/Theme/provider/ThemeSwitcher.js +5 -2
- package/dist/esm/Theme/tokens/brands/index.js +6 -1
- package/dist/esm/Theme/tokens/builders/buildDarkPalette.js +6 -1
- package/dist/esm/Theme/tokens/builders/chartColorsFromTheme.js +1 -1
- package/dist/esm/Theme/tokens/builders/focusRing.js +85 -0
- package/dist/esm/Theme/tokens/builders/gradientInk.js +22 -0
- package/dist/esm/Theme/tokens/builders/index.js +4 -0
- package/dist/esm/Theme/tokens/builders/outlineRung.js +96 -4
- package/dist/esm/Theme/tokens/builders/placeholderInk.js +29 -0
- package/dist/esm/Theme/tokens/builders/resolvedRungs.js +7 -2
- package/dist/esm/Theme/tokens/builders/rowStates.js +15 -0
- package/dist/esm/Theme/tokens/builders/scrollbar.js +52 -0
- package/dist/esm/Theme/tokens/builders/solidFillRung.js +28 -0
- package/dist/esm/Theme/tokens/builders/surfaceRungs.js +20 -5
- package/dist/esm/index.js +24 -1
- package/dist/index.d.ts +27 -3
- package/dist/index.js +64 -4
- 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[
|
|
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,
|
|
5
|
-
|
|
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
|
|
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
|
|
31
|
-
|
|
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
|
-
|
|
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][
|
|
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
|
-
|
|
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:
|
|
85
|
-
color:
|
|
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:
|
|
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:
|
|
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 =
|
|
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:
|
|
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 {
|
|
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 =
|
|
51
|
-
const gradientInk =
|
|
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 },
|
|
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[
|
|
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({
|
|
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 }
|
|
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.
|
|
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
|
-
//
|
|
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 ${
|
|
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:
|
|
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[
|
|
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
|
-
|
|
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[
|
|
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[
|
|
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
|
-
|
|
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[
|
|
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
|
-
|
|
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") }
|
|
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()));
|