pixelize-design-library 2.4.2-beta.58 → 2.4.2-beta.60
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/CHANGELOG.md +149 -5
- package/COMPONENT-GOTCHAS.md +205 -18
- package/DESIGN-GUIDE.md +43 -9
- package/dist/Components/AppSwitcher/AppSwitcher.js +5 -1
- package/dist/Components/AppSwitcher/AppSwitcherProps.d.ts +2 -0
- package/dist/Components/AppSwitcher/AppSwitcherProps.js +7 -4
- package/dist/Components/AudioRecorder/AudioRecorder.d.ts +8 -0
- package/dist/Components/AudioRecorder/AudioRecorder.js +169 -0
- package/dist/Components/AudioRecorder/AudioRecorderProps.d.ts +20 -0
- package/dist/Components/AudioRecorder/AudioRecorderProps.js +2 -0
- package/dist/Components/Breadcrumbs/Breadcrumbs.d.ts +1 -1
- package/dist/Components/Breadcrumbs/Breadcrumbs.js +33 -10
- package/dist/Components/Breadcrumbs/BreadcrumbsProps.d.ts +16 -2
- package/dist/Components/BulkSelectionBar/BulkSelectionBar.d.ts +3 -0
- package/dist/Components/BulkSelectionBar/BulkSelectionBar.js +43 -0
- package/dist/Components/BulkSelectionBar/BulkSelectionBarProps.d.ts +35 -0
- package/dist/Components/BulkSelectionBar/BulkSelectionBarProps.js +2 -0
- package/dist/Components/BulkSelectionBar/index.d.ts +2 -0
- package/dist/Components/BulkSelectionBar/index.js +8 -0
- package/dist/Components/CalendarGrid/CalendarGrid.d.ts +3 -0
- package/dist/Components/CalendarGrid/CalendarGrid.js +173 -0
- package/dist/Components/CalendarGrid/CalendarGridProps.d.ts +54 -0
- package/dist/Components/CalendarGrid/CalendarGridProps.js +2 -0
- package/dist/Components/CalendarGrid/calendarMath.d.ts +49 -0
- package/dist/Components/CalendarGrid/calendarMath.js +178 -0
- package/dist/Components/Card/Card.d.ts +3 -1
- package/dist/Components/Card/Card.js +12 -2
- package/dist/Components/Card/CardProps.d.ts +5 -1
- package/dist/Components/CircularProgress/CircularProgress.d.ts +4 -0
- package/dist/Components/CircularProgress/CircularProgress.js +39 -0
- package/dist/Components/CircularProgress/CircularProgressProps.d.ts +22 -0
- package/dist/Components/CircularProgress/CircularProgressProps.js +2 -0
- package/dist/Components/CircularProgress/arc.d.ts +12 -0
- package/dist/Components/CircularProgress/arc.js +16 -0
- package/dist/Components/Common/fieldStyles.d.ts +1 -0
- package/dist/Components/Common/fieldStyles.js +2 -1
- package/dist/Components/Drawer/Drawer.d.ts +1 -1
- package/dist/Components/Drawer/Drawer.js +4 -2
- package/dist/Components/Drawer/DrawerProps.d.ts +3 -1
- package/dist/Components/Editor/Editor.js +50 -2
- package/dist/Components/Editor/EditorFieldBar.d.ts +15 -0
- package/dist/Components/Editor/EditorFieldBar.js +19 -0
- package/dist/Components/Editor/EditorProps.d.ts +74 -1
- package/dist/Components/Editor/MakeDynamicDialog.d.ts +12 -0
- package/dist/Components/Editor/MakeDynamicDialog.js +59 -0
- package/dist/Components/Editor/editorLabels.d.ts +4 -0
- package/dist/Components/Editor/editorLabels.js +24 -0
- package/dist/Components/Editor/editorTokenStyles.d.ts +28 -0
- package/dist/Components/Editor/editorTokenStyles.js +30 -0
- package/dist/Components/Editor/editorTokens.d.ts +26 -0
- package/dist/Components/Editor/editorTokens.js +134 -0
- package/dist/Components/Editor/useEditorBridge.d.ts +40 -0
- package/dist/Components/Editor/useEditorBridge.js +141 -0
- package/dist/Components/EmptyState/EmptyState.js +2 -1
- package/dist/Components/EmptyState/EmptyStateProps.d.ts +2 -2
- package/dist/Components/FormDrawer/FormDrawer.d.ts +2 -0
- package/dist/Components/FormDrawer/FormDrawer.js +97 -0
- package/dist/Components/FormDrawer/FormDrawerProps.d.ts +55 -0
- package/dist/Components/FormDrawer/FormDrawerProps.js +2 -0
- package/dist/Components/Kbd/Kbd.d.ts +6 -0
- package/dist/Components/Kbd/Kbd.js +33 -0
- package/dist/Components/Kbd/KbdProps.d.ts +17 -0
- package/dist/Components/Kbd/KbdProps.js +2 -0
- package/dist/Components/LauncherTrigger/LauncherTrigger.d.ts +4 -0
- package/dist/Components/LauncherTrigger/LauncherTrigger.js +48 -0
- package/dist/Components/LauncherTrigger/LauncherTriggerProps.d.ts +18 -0
- package/dist/Components/LauncherTrigger/LauncherTriggerProps.js +2 -0
- package/dist/Components/Modal/Modal.d.ts +1 -1
- package/dist/Components/Modal/Modal.js +4 -2
- package/dist/Components/Modal/ModalProps.d.ts +3 -1
- package/dist/Components/Modal/warnDroppedSlotChildren.d.ts +2 -0
- package/dist/Components/Modal/warnDroppedSlotChildren.js +45 -0
- package/dist/Components/NavLauncher/NavLauncher.d.ts +3 -0
- package/dist/Components/NavLauncher/NavLauncher.js +452 -0
- package/dist/Components/NavLauncher/NavLauncherProps.d.ts +187 -0
- package/dist/Components/NavLauncher/NavLauncherProps.js +2 -0
- package/dist/Components/NavLauncher/NewTabLink.d.ts +3 -0
- package/dist/Components/NavLauncher/NewTabLink.js +14 -0
- package/dist/Components/NavLauncher/PinToggle.d.ts +3 -0
- package/dist/Components/NavLauncher/PinToggle.js +21 -0
- package/dist/Components/NavLauncher/launcherParts.d.ts +152 -0
- package/dist/Components/NavLauncher/launcherParts.js +212 -0
- package/dist/Components/NavLauncher/match.d.ts +53 -0
- package/dist/Components/NavLauncher/match.js +178 -0
- package/dist/Components/NavLauncher/revealStyles.d.ts +4 -0
- package/dist/Components/NavLauncher/revealStyles.js +19 -0
- package/dist/Components/NavigationBar/NavigationBar.d.ts +1 -1
- package/dist/Components/NavigationBar/NavigationBar.js +2 -2
- package/dist/Components/NavigationBar/NavigationBarProps.d.ts +2 -0
- package/dist/Components/PageHeader/PageHeader.d.ts +1 -1
- package/dist/Components/PageHeader/PageHeader.js +9 -2
- package/dist/Components/PageHeader/PageHeaderProps.d.ts +8 -0
- package/dist/Components/PdfViewer/PdfViewer.d.ts +21 -4
- package/dist/Components/PdfViewer/PdfViewer.js +124 -3
- package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +5 -0
- package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewerProps.d.ts +1 -1
- package/dist/Components/QueryState/QueryStateBoundary.d.ts +2 -2
- package/dist/Components/QueryState/QueryStateBoundary.js +9 -3
- package/dist/Components/QueryState/QueryStateProps.d.ts +19 -2
- package/dist/Components/Search/Search.js +2 -1
- package/dist/Components/SectionRail/SectionRail.d.ts +3 -0
- package/dist/Components/SectionRail/SectionRail.js +49 -0
- package/dist/Components/SectionRail/SectionRailProps.d.ts +23 -0
- package/dist/Components/SectionRail/SectionRailProps.js +2 -0
- package/dist/Components/SectionRail/index.d.ts +2 -0
- package/dist/Components/SectionRail/index.js +8 -0
- package/dist/Components/SegmentedControl/SegmentedControl.js +9 -14
- package/dist/Components/SegmentedControl/segmentedInk.d.ts +0 -2
- package/dist/Components/SegmentedControl/segmentedInk.js +1 -5
- package/dist/Components/SideBar/SecondaryBar.js +4 -3
- package/dist/Components/SideBar/SideBar.d.ts +1 -1
- package/dist/Components/SideBar/SideBar.js +30 -9
- package/dist/Components/SideBar/SideBarProps.d.ts +32 -0
- package/dist/Components/SideBar/components/MenuItemBox.d.ts +6 -0
- package/dist/Components/SideBar/components/MenuItemBox.js +8 -4
- package/dist/Components/SideBar/components/MenuPopoverContent.js +3 -2
- package/dist/Components/SideBar/components/OtherApps.js +2 -1
- package/dist/Components/SideBar/components/PinnedSection.d.ts +17 -0
- package/dist/Components/SideBar/components/PinnedSection.js +98 -0
- package/dist/Components/SideBar/sidebarFocus.d.ts +23 -0
- package/dist/Components/SideBar/sidebarFocus.js +20 -0
- package/dist/Components/StageProgress/StageProgress.js +2 -2
- package/dist/Components/StageProgress/StageProgressProps.d.ts +2 -0
- package/dist/Components/StageProgress/StepperStage.js +5 -2
- package/dist/Components/StatCard/StatCard.d.ts +1 -1
- package/dist/Components/StatCard/StatCard.js +6 -2
- package/dist/Components/StatCard/StatCardProps.d.ts +3 -0
- package/dist/Components/StatusTag/StatusTag.d.ts +4 -0
- package/dist/Components/StatusTag/StatusTag.js +24 -0
- package/dist/Components/StatusTag/StatusTagProps.d.ts +20 -0
- package/dist/Components/StatusTag/StatusTagProps.js +2 -0
- package/dist/Components/Table/Table.d.ts +1 -1
- package/dist/Components/Table/Table.js +6 -2
- package/dist/Components/Table/TableProps.d.ts +20 -0
- package/dist/Components/Table/components/TableBody.d.ts +1 -1
- package/dist/Components/Table/components/TableBody.js +43 -18
- package/dist/Components/Table/components/TableHeader.d.ts +1 -1
- package/dist/Components/Table/components/TableHeader.js +7 -5
- package/dist/Components/Table/components/rowDetail.d.ts +32 -0
- package/dist/Components/Table/components/rowDetail.js +20 -0
- package/dist/Components/Table/hooks/useRowExpansion.d.ts +7 -0
- package/dist/Components/Table/hooks/useRowExpansion.js +27 -0
- package/dist/Components/Tabs/Tabs.d.ts +1 -1
- package/dist/Components/Tabs/Tabs.js +15 -2
- package/dist/Components/Tabs/TabsProps.d.ts +6 -2
- package/dist/Components/Tabs/components/Tab.js +4 -33
- package/dist/Components/Tabs/components/TabLinkList.d.ts +7 -0
- package/dist/Components/Tabs/components/TabLinkList.js +34 -0
- package/dist/Components/Tabs/useTabAppearance.d.ts +17 -0
- package/dist/Components/Tabs/useTabAppearance.js +67 -0
- package/dist/Components/Tag/Tag.js +11 -1
- package/dist/Components/Tag/TagProps.d.ts +4 -0
- package/dist/Components/Tag/tagDot.d.ts +3 -0
- package/dist/Components/Tag/tagDot.js +21 -0
- package/dist/Components/WizardDialog/WizardDialog.d.ts +9 -0
- package/dist/Components/WizardDialog/WizardDialog.js +102 -0
- package/dist/Components/WizardDialog/WizardDialogProps.d.ts +48 -0
- package/dist/Components/WizardDialog/WizardDialogProps.js +2 -0
- package/dist/Components/WizardDialog/useWizardFlow.d.ts +22 -0
- package/dist/Components/WizardDialog/useWizardFlow.js +47 -0
- package/dist/Components/WizardDialog/wizardSteps.d.ts +31 -0
- package/dist/Components/WizardDialog/wizardSteps.js +40 -0
- package/dist/esm/Components/AppSwitcher/AppSwitcher.js +2 -1
- package/dist/esm/Components/AppSwitcher/AppSwitcherProps.js +5 -3
- package/dist/esm/Components/AudioRecorder/AudioRecorder.js +161 -0
- package/dist/esm/Components/AudioRecorder/AudioRecorderProps.js +1 -0
- package/dist/esm/Components/Breadcrumbs/Breadcrumbs.js +35 -12
- package/dist/esm/Components/BulkSelectionBar/BulkSelectionBar.js +38 -0
- package/dist/esm/Components/BulkSelectionBar/BulkSelectionBarProps.js +1 -0
- package/dist/esm/Components/BulkSelectionBar/index.js +1 -0
- package/dist/esm/Components/CalendarGrid/CalendarGrid.js +168 -0
- package/dist/esm/Components/CalendarGrid/CalendarGridProps.js +1 -0
- package/dist/esm/Components/CalendarGrid/calendarMath.js +155 -0
- package/dist/esm/Components/Card/Card.js +12 -2
- package/dist/esm/Components/CircularProgress/CircularProgress.js +37 -0
- package/dist/esm/Components/CircularProgress/CircularProgressProps.js +1 -0
- package/dist/esm/Components/CircularProgress/arc.js +11 -0
- package/dist/esm/Components/Common/fieldStyles.js +2 -1
- package/dist/esm/Components/Drawer/Drawer.js +4 -2
- package/dist/esm/Components/Editor/Editor.js +48 -3
- package/dist/esm/Components/Editor/EditorFieldBar.js +13 -0
- package/dist/esm/Components/Editor/MakeDynamicDialog.js +20 -0
- package/dist/esm/Components/Editor/editorLabels.js +20 -0
- package/dist/esm/Components/Editor/editorTokenStyles.js +25 -0
- package/dist/esm/Components/Editor/editorTokens.js +121 -0
- package/dist/esm/Components/Editor/useEditorBridge.js +138 -0
- package/dist/esm/Components/EmptyState/EmptyState.js +2 -1
- package/dist/esm/Components/FormDrawer/FormDrawer.js +58 -0
- package/dist/esm/Components/FormDrawer/FormDrawerProps.js +1 -0
- package/dist/esm/Components/Kbd/Kbd.js +28 -0
- package/dist/esm/Components/Kbd/KbdProps.js +1 -0
- package/dist/esm/Components/LauncherTrigger/LauncherTrigger.js +41 -0
- package/dist/esm/Components/LauncherTrigger/LauncherTriggerProps.js +1 -0
- package/dist/esm/Components/Modal/Modal.js +4 -2
- package/dist/esm/Components/Modal/warnDroppedSlotChildren.js +38 -0
- package/dist/esm/Components/NavLauncher/NavLauncher.js +413 -0
- package/dist/esm/Components/NavLauncher/NavLauncherProps.js +1 -0
- package/dist/esm/Components/NavLauncher/NewTabLink.js +11 -0
- package/dist/esm/Components/NavLauncher/PinToggle.js +18 -0
- package/dist/esm/Components/NavLauncher/launcherParts.js +187 -0
- package/dist/esm/Components/NavLauncher/match.js +172 -0
- package/dist/esm/Components/NavLauncher/revealStyles.js +15 -0
- package/dist/esm/Components/NavigationBar/NavigationBar.js +3 -3
- package/dist/esm/Components/PageHeader/PageHeader.js +9 -2
- package/dist/esm/Components/PdfViewer/PdfViewer.js +123 -2
- package/dist/esm/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +5 -0
- package/dist/esm/Components/QueryState/QueryStateBoundary.js +10 -4
- package/dist/esm/Components/Search/Search.js +3 -2
- package/dist/esm/Components/SectionRail/SectionRail.js +44 -0
- package/dist/esm/Components/SectionRail/SectionRailProps.js +1 -0
- package/dist/esm/Components/SectionRail/index.js +1 -0
- package/dist/esm/Components/SegmentedControl/SegmentedControl.js +11 -16
- package/dist/esm/Components/SegmentedControl/segmentedInk.js +0 -3
- package/dist/esm/Components/SideBar/SecondaryBar.js +4 -3
- package/dist/esm/Components/SideBar/SideBar.js +31 -10
- package/dist/esm/Components/SideBar/components/MenuItemBox.js +4 -2
- package/dist/esm/Components/SideBar/components/MenuPopoverContent.js +3 -2
- package/dist/esm/Components/SideBar/components/OtherApps.js +2 -1
- package/dist/esm/Components/SideBar/components/PinnedSection.js +92 -0
- package/dist/esm/Components/SideBar/sidebarFocus.js +15 -0
- package/dist/esm/Components/StageProgress/StageProgress.js +2 -2
- package/dist/esm/Components/StageProgress/StepperStage.js +5 -2
- package/dist/esm/Components/StatCard/StatCard.js +6 -2
- package/dist/esm/Components/StatusTag/StatusTag.js +19 -0
- package/dist/esm/Components/StatusTag/StatusTagProps.js +1 -0
- package/dist/esm/Components/Table/Table.js +7 -3
- package/dist/esm/Components/Table/components/TableBody.js +43 -18
- package/dist/esm/Components/Table/components/TableHeader.js +7 -5
- package/dist/esm/Components/Table/components/rowDetail.js +14 -0
- package/dist/esm/Components/Table/hooks/useRowExpansion.js +23 -0
- package/dist/esm/Components/Tabs/Tabs.js +15 -2
- package/dist/esm/Components/Tabs/components/Tab.js +4 -33
- package/dist/esm/Components/Tabs/components/TabLinkList.js +29 -0
- package/dist/esm/Components/Tabs/useTabAppearance.js +63 -0
- package/dist/esm/Components/Tag/Tag.js +12 -2
- package/dist/esm/Components/Tag/tagDot.js +17 -0
- package/dist/esm/Components/WizardDialog/WizardDialog.js +58 -0
- package/dist/esm/Components/WizardDialog/WizardDialogProps.js +1 -0
- package/dist/esm/Components/WizardDialog/useWizardFlow.js +44 -0
- package/dist/esm/Components/WizardDialog/wizardSteps.js +35 -0
- package/dist/esm/index.js +14 -0
- package/dist/index.d.ts +35 -6
- package/dist/index.js +38 -4
- package/package.json +1 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useTabAppearance = void 0;
|
|
4
|
+
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
5
|
+
const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
6
|
+
const outlineRung_1 = require("../../Theme/tokens/builders/outlineRung");
|
|
7
|
+
const color_1 = require("../../Theme/tokens/builders/color");
|
|
8
|
+
const motion_1 = require("../../Theme/tokens/primitives/motion");
|
|
9
|
+
const motion_2 = require("../../Theme/chakra/motion");
|
|
10
|
+
const controlSizes_1 = require("../../Theme/tokens/primitives/controlSizes");
|
|
11
|
+
const iconBox_1 = require("../Common/iconBox");
|
|
12
|
+
const tabStyles_1 = require("./tabStyles");
|
|
13
|
+
const TabsContext_1 = require("./TabsContext");
|
|
14
|
+
const useTabAppearance = (isSelected, isDisabled) => {
|
|
15
|
+
var _a, _b, _c;
|
|
16
|
+
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
17
|
+
const ctx = (0, TabsContext_1.useTabsContext)();
|
|
18
|
+
const isVertical = ctx.orientation === "vertical";
|
|
19
|
+
const isLine = ctx.variant === "line";
|
|
20
|
+
const canvas = colors.backgroundColor.main;
|
|
21
|
+
const scale = (0, tabStyles_1.scaleForColorScheme)(colors, ctx.colorScheme);
|
|
22
|
+
const style = (0, tabStyles_1.resolveTabStyle)(colors, scale, canvas, ctx.variant, isSelected);
|
|
23
|
+
const spec = controlSizes_1.BUTTON_SIZES[ctx.size];
|
|
24
|
+
// The list scrolls on both axes, so an outer ring is clipped into arcs; a negative offset draws it
|
|
25
|
+
// inside the tab, clear of its own border rather than thickening it.
|
|
26
|
+
const focusRing = {
|
|
27
|
+
outline: `1px solid ${(0, outlineRung_1.liftToContrast)(colors.primary[500],
|
|
28
|
+
// subtle/ghost fills are translucent tints; contrast has no meaning until they are flattened.
|
|
29
|
+
style.bg === "transparent" ? canvas : (0, color_1.compositeOver)(style.bg, canvas), outlineRung_1.AA_NON_TEXT)}`,
|
|
30
|
+
outlineOffset: "-2px",
|
|
31
|
+
};
|
|
32
|
+
const borderProps = ctx.variant === "outline"
|
|
33
|
+
? { border: "1px solid", borderColor: (_a = style.border) !== null && _a !== void 0 ? _a : "transparent" }
|
|
34
|
+
: isLine
|
|
35
|
+
? isVertical
|
|
36
|
+
? { borderLeft: "0.125rem solid", borderLeftColor: (_b = style.indicator) !== null && _b !== void 0 ? _b : "transparent" }
|
|
37
|
+
: { borderBottom: "0.125rem solid", borderBottomColor: (_c = style.indicator) !== null && _c !== void 0 ? _c : "transparent" }
|
|
38
|
+
: {};
|
|
39
|
+
const boxProps = {
|
|
40
|
+
display: "flex",
|
|
41
|
+
alignItems: "center",
|
|
42
|
+
justifyContent: "center",
|
|
43
|
+
gap: "0.375rem",
|
|
44
|
+
flexShrink: 0,
|
|
45
|
+
flex: ctx.isFitted ? 1 : undefined,
|
|
46
|
+
w: isVertical ? "100%" : undefined,
|
|
47
|
+
h: isVertical ? "auto" : spec.height,
|
|
48
|
+
minH: spec.height,
|
|
49
|
+
py: isVertical ? "0.5rem" : undefined,
|
|
50
|
+
px: spec.paddingX,
|
|
51
|
+
fontSize: spec.fontSize,
|
|
52
|
+
fontWeight: isSelected ? 600 : 500,
|
|
53
|
+
whiteSpace: "nowrap",
|
|
54
|
+
textDecoration: "none",
|
|
55
|
+
cursor: isDisabled ? "not-allowed" : "pointer",
|
|
56
|
+
opacity: isDisabled ? 0.5 : 1,
|
|
57
|
+
borderRadius: isLine ? "none" : "lg",
|
|
58
|
+
bg: style.bg,
|
|
59
|
+
color: style.color,
|
|
60
|
+
...borderProps,
|
|
61
|
+
transition: (0, motion_1.transitionFor)(["background-color", "color", "border-color"]),
|
|
62
|
+
sx: { _focusVisible: focusRing, [focusRing_styles_1.FOCUS_VISIBLE_OVER_STATE]: focusRing, ...(0, motion_2.reducedMotionSx)() },
|
|
63
|
+
_hover: !isDisabled ? { bg: style.hoverBg, color: style.hoverColor, textDecoration: "none" } : undefined,
|
|
64
|
+
};
|
|
65
|
+
return { ctx, colors, canvas, scale, style, iconSize: spec.iconSize, iconSx: (0, iconBox_1.iconBoxSx)(spec.iconSize), boxProps };
|
|
66
|
+
};
|
|
67
|
+
exports.useTabAppearance = useTabAppearance;
|
|
@@ -7,6 +7,7 @@ const motion_1 = require("../../Theme/tokens/primitives/motion");
|
|
|
7
7
|
const motion_2 = require("../../Theme/chakra/motion");
|
|
8
8
|
const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
9
9
|
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
10
|
+
const tagDot_1 = require("./tagDot");
|
|
10
11
|
// NOTE: the label's pill radius would slice descenders, so clipping lives on a square child.
|
|
11
12
|
const LabelText = ({ children, title }) => ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", title: title, display: "block", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", borderRadius: 0, px: "0.05em", mx: "-0.05em", children: children }));
|
|
12
13
|
const ICON_SIZE = {
|
|
@@ -15,10 +16,19 @@ const ICON_SIZE = {
|
|
|
15
16
|
md: "1em",
|
|
16
17
|
lg: "1.1em",
|
|
17
18
|
};
|
|
19
|
+
const DOT_FONT_SIZE = {
|
|
20
|
+
xs: "0.75rem",
|
|
21
|
+
sm: "0.8125rem",
|
|
22
|
+
md: "0.875rem",
|
|
23
|
+
lg: "0.9375rem",
|
|
24
|
+
};
|
|
18
25
|
/** Renders a pill-shaped status/filter chip (Chakra Tag) — not interchangeable with the raw Badge primitive's static marker. */
|
|
19
|
-
const Tag = ({ label, colorScheme = "primary", tone, variant = "subtle", size = "sm", maxW, icon, leadingIcon, onTagClick, onIconClick, isDisabled, "data-testid": testId, }) => {
|
|
26
|
+
const Tag = ({ label, colorScheme = "primary", tone, variant = "subtle", display = "chip", size = "sm", maxW, icon, leadingIcon, onTagClick, onIconClick, isDisabled, "data-testid": testId, }) => {
|
|
20
27
|
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
21
28
|
const isInteractive = !!onTagClick;
|
|
29
|
+
if (display === "dot") {
|
|
30
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { as: isInteractive ? "button" : "span", ...(isInteractive ? { type: "button", disabled: isDisabled || undefined } : {}), display: "inline-flex", alignItems: "center", gap: 2, maxW: maxW, minW: 0, borderRadius: "sm", bg: "transparent", fontSize: DOT_FONT_SIZE[size], fontWeight: 500, color: colors.text[700], cursor: isInteractive ? "pointer" : undefined, opacity: isDisabled ? 0.5 : undefined, onClick: isInteractive && !isDisabled ? onTagClick : undefined, "data-testid": testId, "data-display": "dot", "data-disabled": isDisabled || undefined, sx: isInteractive ? (0, focusRing_styles_1.focusVisibleStyles)(colors) : undefined, children: [(0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", "aria-hidden": true, boxSize: "0.5rem", flexShrink: 0, borderRadius: "full", bg: (0, tagDot_1.dotColor)(colors, tone, colorScheme) }), (0, jsx_runtime_1.jsx)(react_1.Text, { as: "span", noOfLines: 1, title: maxW ? label : undefined, children: label })] }));
|
|
31
|
+
}
|
|
22
32
|
return ((0, jsx_runtime_1.jsxs)(react_1.Tag, { size: size, variant: variant, colorScheme: tone ? tone_1.toneToColorScheme[tone] : colorScheme, borderRadius: "full", maxW: maxW, "data-testid": testId, "data-interactive": isInteractive || undefined, "data-disabled": isDisabled || undefined, "aria-disabled": isDisabled || undefined, children: [leadingIcon && (0, jsx_runtime_1.jsx)(react_1.TagLeftIcon, { as: leadingIcon, boxSize: ICON_SIZE[size], "aria-hidden": true }), isInteractive ? ((0, jsx_runtime_1.jsx)(react_1.TagLabel, { as: "button", type: "button", noOfLines: undefined, disabled: isDisabled || undefined, cursor: "pointer", onClick: isDisabled ? undefined : onTagClick, children: (0, jsx_runtime_1.jsx)(LabelText, { title: maxW ? label : undefined, children: label }) })) : ((0, jsx_runtime_1.jsx)(react_1.TagLabel, { noOfLines: undefined, children: (0, jsx_runtime_1.jsx)(LabelText, { title: maxW ? label : undefined, children: label }) })), icon &&
|
|
23
33
|
(onIconClick ? ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "button", type: "button", "aria-label": `Remove ${label}`, "data-testid": testId ? `${testId}-remove` : undefined, disabled: isDisabled || undefined, onClick: (e) => {
|
|
24
34
|
e.stopPropagation();
|
|
@@ -7,6 +7,8 @@ export type TagColorScheme = "primary" | "secondary" | "tertiary" | "gray" | "re
|
|
|
7
7
|
export type TagSize = "xs" | "sm" | "md" | "lg";
|
|
8
8
|
/** "solid" for emphasis, "outline" on dense/colored surfaces, "subtle" (default) for everyday chips. */
|
|
9
9
|
export type TagVariant = "solid" | "outline" | "subtle";
|
|
10
|
+
/** "chip" is the filled/outlined pill; "dot" is a tone dot beside plain text. */
|
|
11
|
+
export type TagDisplay = "chip" | "dot";
|
|
10
12
|
/** Props for the pill-shaped status/filter Tag chip — see Tag.tsx for interactive/icon behavior. */
|
|
11
13
|
export interface TagProps {
|
|
12
14
|
label: string;
|
|
@@ -26,6 +28,8 @@ export interface TagProps {
|
|
|
26
28
|
maxW?: BoxProps["maxW"];
|
|
27
29
|
size?: TagSize;
|
|
28
30
|
variant?: TagVariant;
|
|
31
|
+
/** "dot" renders an 8px tone dot plus plain label for quiet rows; variant and icons are ignored. Default "chip". */
|
|
32
|
+
display?: TagDisplay;
|
|
29
33
|
/** Dims the tag and disables its button(s) (native disabled); no effect on a purely static tag. */
|
|
30
34
|
isDisabled?: boolean;
|
|
31
35
|
/** Test hook on the root; the remove button gets `${"$"}{testId}-remove`. */
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dotColor = void 0;
|
|
4
|
+
const outlineRung_1 = require("../../Theme/tokens/builders/outlineRung");
|
|
5
|
+
const tone_1 = require("../../Theme/tokens/builders/tone");
|
|
6
|
+
const SCALE_KEYS = [
|
|
7
|
+
"primary", "secondary", "tertiary", "gray", "red", "orange", "yellow",
|
|
8
|
+
"green", "teal", "blue", "cyan", "purple", "pink",
|
|
9
|
+
];
|
|
10
|
+
const dotColor = (colors, tone, colorScheme) => {
|
|
11
|
+
const surfaces = [colors.background[50], colors.backgroundColor.main];
|
|
12
|
+
if (tone === "neutral")
|
|
13
|
+
return colors.textMuted;
|
|
14
|
+
const scale = tone
|
|
15
|
+
? colors.semantic[tone_1.toneToSemantic[tone]]
|
|
16
|
+
: SCALE_KEYS.includes(colorScheme)
|
|
17
|
+
? colors[colorScheme]
|
|
18
|
+
: colors.gray;
|
|
19
|
+
return surfaces.reduce((ink, surface) => (0, outlineRung_1.liftToContrast)(ink, surface), scale[500]);
|
|
20
|
+
};
|
|
21
|
+
exports.dotColor = dotColor;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { WizardDialogProps, WizardProps } from "./WizardDialogProps";
|
|
3
|
+
export { wizardTransition, firstInvalidStep, INITIAL_WIZARD_STATE } from "./wizardSteps";
|
|
4
|
+
export type { WizardAction, WizardState, StepValidator } from "./wizardSteps";
|
|
5
|
+
/** Modal wizard that owns step state: validated Continue, locked future steps, error summary, review on the last step. */
|
|
6
|
+
export declare const WizardDialog: React.FC<WizardDialogProps>;
|
|
7
|
+
/** The same wizard inline, for a full-page flow rather than a modal. */
|
|
8
|
+
export declare const Wizard: React.FC<WizardProps>;
|
|
9
|
+
export default WizardDialog;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.Wizard = exports.WizardDialog = exports.INITIAL_WIZARD_STATE = exports.firstInvalidStep = exports.wizardTransition = void 0;
|
|
40
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
41
|
+
const react_1 = require("react");
|
|
42
|
+
const react_2 = require("@chakra-ui/react");
|
|
43
|
+
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
44
|
+
const Modal_1 = __importStar(require("../Modal/Modal"));
|
|
45
|
+
const Button_1 = __importDefault(require("../Button/Button"));
|
|
46
|
+
const StageProgress_1 = __importDefault(require("../StageProgress/StageProgress"));
|
|
47
|
+
const DescriptionList_1 = __importDefault(require("../DescriptionList/DescriptionList"));
|
|
48
|
+
const useWizardFlow_1 = require("./useWizardFlow");
|
|
49
|
+
var wizardSteps_1 = require("./wizardSteps");
|
|
50
|
+
Object.defineProperty(exports, "wizardTransition", { enumerable: true, get: function () { return wizardSteps_1.wizardTransition; } });
|
|
51
|
+
Object.defineProperty(exports, "firstInvalidStep", { enumerable: true, get: function () { return wizardSteps_1.firstInvalidStep; } });
|
|
52
|
+
Object.defineProperty(exports, "INITIAL_WIZARD_STATE", { enumerable: true, get: function () { return wizardSteps_1.INITIAL_WIZARD_STATE; } });
|
|
53
|
+
const DEFAULT_LABELS = {
|
|
54
|
+
back: "Back",
|
|
55
|
+
next: "Continue",
|
|
56
|
+
finish: "Finish",
|
|
57
|
+
cancel: "Cancel",
|
|
58
|
+
stepOf: (current, total) => `Step ${current} of ${total}`,
|
|
59
|
+
fixErrors: "Fix the following to continue",
|
|
60
|
+
review: "Review",
|
|
61
|
+
};
|
|
62
|
+
const WizardBody = ({ flow, steps, labels, testId }) => {
|
|
63
|
+
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
64
|
+
const headingRef = (0, react_1.useRef)(null);
|
|
65
|
+
const previousStep = (0, react_1.useRef)(flow.step.id);
|
|
66
|
+
const reviewed = steps.filter((candidate) => candidate.summary !== undefined);
|
|
67
|
+
(0, react_1.useEffect)(() => {
|
|
68
|
+
var _a;
|
|
69
|
+
if (previousStep.current === flow.step.id)
|
|
70
|
+
return;
|
|
71
|
+
previousStep.current = flow.step.id;
|
|
72
|
+
(_a = headingRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
73
|
+
}, [flow.step.id]);
|
|
74
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 5, "data-testid": testId, "data-step": flow.step.id, children: [(0, jsx_runtime_1.jsx)(StageProgress_1.default, { variant: "stepper", size: "sm", showCheck: true, stages: steps.map((candidate, index) => ({
|
|
75
|
+
id: candidate.id,
|
|
76
|
+
label: candidate.label,
|
|
77
|
+
isDisabled: index > flow.furthest,
|
|
78
|
+
})), value: flow.step.id, onChange: (_id, _stage, index) => flow.goto(index) }), (0, jsx_runtime_1.jsxs)(react_2.Box, { children: [(0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: "xs", color: colors.textMuted, children: labels.stepOf(flow.index + 1, steps.length) }), (0, jsx_runtime_1.jsx)(react_2.Heading, { ref: headingRef, tabIndex: -1, as: "h3", fontSize: "md", fontWeight: 600, color: colors.header[900], _focus: { outline: "none" }, children: flow.step.label })] }), flow.errors.length ? ((0, jsx_runtime_1.jsxs)(react_2.Alert, { status: "error", variant: "subtle", borderRadius: "md", alignItems: "flex-start", role: "alert", "data-testid": "wizard-errors", children: [(0, jsx_runtime_1.jsx)(react_2.AlertIcon, {}), (0, jsx_runtime_1.jsxs)(react_2.Box, { children: [(0, jsx_runtime_1.jsx)(react_2.AlertTitle, { fontSize: "sm", children: labels.fixErrors }), (0, jsx_runtime_1.jsx)(react_2.AlertDescription, { fontSize: "sm", children: (0, jsx_runtime_1.jsx)(react_2.UnorderedList, { mt: 1, children: flow.errors.map((message) => ((0, jsx_runtime_1.jsx)(react_2.ListItem, { children: message }, message))) }) })] })] })) : null, (0, jsx_runtime_1.jsx)(react_2.Box, { children: flow.step.content }), flow.isLast && reviewed.length ? ((0, jsx_runtime_1.jsxs)(react_2.Box, { "data-testid": "wizard-review", children: [(0, jsx_runtime_1.jsx)(react_2.Heading, { as: "h4", fontSize: "sm", fontWeight: 600, mb: 2, color: colors.header[900], children: labels.review }), (0, jsx_runtime_1.jsx)(DescriptionList_1.default, { layout: "inline", columns: { base: 1 }, items: reviewed.map((candidate) => ({
|
|
79
|
+
label: candidate.label,
|
|
80
|
+
value: candidate.summary,
|
|
81
|
+
})) })] })) : null] }));
|
|
82
|
+
};
|
|
83
|
+
const WizardFooter = ({ flow, labels, isFinishing, onCancel }) => ((0, jsx_runtime_1.jsxs)(react_2.Flex, { w: "100%", justify: "space-between", gap: 2, wrap: "wrap", children: [onCancel ? ((0, jsx_runtime_1.jsx)(Button_1.default, { variant: "ghost", colorScheme: "gray", label: labels.cancel, onClick: onCancel, isDisabled: isFinishing, "data-testid": "wizard-cancel" })) : ((0, jsx_runtime_1.jsx)("span", {})), (0, jsx_runtime_1.jsxs)(react_2.Flex, { gap: 2, children: [!flow.isFirst ? ((0, jsx_runtime_1.jsx)(Button_1.default, { variant: "outline", colorScheme: "gray", label: labels.back, onClick: flow.back, isDisabled: isFinishing, "data-testid": "wizard-back" })) : null, flow.isLast ? ((0, jsx_runtime_1.jsx)(Button_1.default, { variant: "solid", colorScheme: "primary", label: labels.finish, onClick: flow.finish, isLoading: isFinishing, loadingText: labels.finish, "data-testid": "wizard-finish" })) : ((0, jsx_runtime_1.jsx)(Button_1.default, { variant: "solid", colorScheme: "primary", label: labels.next, onClick: flow.next, "data-testid": "wizard-next" }))] })] }));
|
|
84
|
+
/** Modal wizard that owns step state: validated Continue, locked future steps, error summary, review on the last step. */
|
|
85
|
+
const WizardDialog = ({ isOpen, onClose, title, subtitle, steps, onFinish, isFinishing = false, stepId, onStepChange, size = "3xl", labels, "data-testid": testId, }) => {
|
|
86
|
+
const flow = (0, useWizardFlow_1.useWizardFlow)({ steps, stepId, onStepChange, onFinish, resetWhen: !isOpen });
|
|
87
|
+
const resolved = { ...DEFAULT_LABELS, ...labels };
|
|
88
|
+
const guardedClose = () => {
|
|
89
|
+
if (!isFinishing)
|
|
90
|
+
onClose();
|
|
91
|
+
};
|
|
92
|
+
return ((0, jsx_runtime_1.jsxs)(Modal_1.default, { isOpen: isOpen, onClose: guardedClose, size: size, isCentered: true, scrollBehavior: "inside", title: title, subtitle: subtitle, closeOnOverlayClick: false, closeOnEsc: !isFinishing, hideCloseButton: isFinishing, children: [(0, jsx_runtime_1.jsx)(Modal_1.ModalBody, { children: (0, jsx_runtime_1.jsx)(WizardBody, { flow: flow, steps: steps, labels: resolved, testId: testId !== null && testId !== void 0 ? testId : "wizard-dialog" }) }), (0, jsx_runtime_1.jsx)(Modal_1.ModalFooter, { children: (0, jsx_runtime_1.jsx)(WizardFooter, { flow: flow, labels: resolved, isFinishing: isFinishing, onCancel: guardedClose }) })] }));
|
|
93
|
+
};
|
|
94
|
+
exports.WizardDialog = WizardDialog;
|
|
95
|
+
/** The same wizard inline, for a full-page flow rather than a modal. */
|
|
96
|
+
const Wizard = ({ steps, onFinish, isFinishing = false, stepId, onStepChange, labels, onCancel, "data-testid": testId, }) => {
|
|
97
|
+
const flow = (0, useWizardFlow_1.useWizardFlow)({ steps, stepId, onStepChange, onFinish });
|
|
98
|
+
const resolved = { ...DEFAULT_LABELS, ...labels };
|
|
99
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { direction: "column", gap: 6, children: [(0, jsx_runtime_1.jsx)(WizardBody, { flow: flow, steps: steps, labels: resolved, testId: testId !== null && testId !== void 0 ? testId : "wizard" }), (0, jsx_runtime_1.jsx)(WizardFooter, { flow: flow, labels: resolved, isFinishing: isFinishing, onCancel: onCancel })] }));
|
|
100
|
+
};
|
|
101
|
+
exports.Wizard = Wizard;
|
|
102
|
+
exports.default = exports.WizardDialog;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/** One step of a wizard: its stepper label, body, validation and review summary. */
|
|
3
|
+
export type WizardStep = {
|
|
4
|
+
id: string;
|
|
5
|
+
/** Stepper label and the heading shown above the step content. */
|
|
6
|
+
label: string;
|
|
7
|
+
content: ReactNode;
|
|
8
|
+
/** Messages that block leaving this step; [] = valid. Must be pure (runs in the reducer). */
|
|
9
|
+
validate?: () => string[];
|
|
10
|
+
/** One line shown in the review on the last step; steps without it are not reviewed. */
|
|
11
|
+
summary?: ReactNode;
|
|
12
|
+
};
|
|
13
|
+
/** Visible strings; every key falls back to its English default. */
|
|
14
|
+
export type WizardLabels = Partial<{
|
|
15
|
+
back: string;
|
|
16
|
+
next: string;
|
|
17
|
+
finish: string;
|
|
18
|
+
cancel: string;
|
|
19
|
+
stepOf: (current: number, total: number) => string;
|
|
20
|
+
fixErrors: string;
|
|
21
|
+
review: string;
|
|
22
|
+
}>;
|
|
23
|
+
/** Props for the modal wizard: Modal + stepper + per-step validation + review on the last step. */
|
|
24
|
+
export interface WizardDialogProps {
|
|
25
|
+
isOpen: boolean;
|
|
26
|
+
/** Ignored while `isFinishing`. */
|
|
27
|
+
onClose: () => void;
|
|
28
|
+
title: string;
|
|
29
|
+
subtitle?: string;
|
|
30
|
+
steps: WizardStep[];
|
|
31
|
+
/** Called after every step re-validates; a failing step is jumped to with its errors. */
|
|
32
|
+
onFinish: () => void;
|
|
33
|
+
/** Shows the Finish spinner and disables close, Esc, Back and Cancel. */
|
|
34
|
+
isFinishing?: boolean;
|
|
35
|
+
/** Controlled step; omit for uncontrolled (resets to the first step on close). */
|
|
36
|
+
stepId?: string;
|
|
37
|
+
/** Fires whenever the visible step changes, controlled or not. */
|
|
38
|
+
onStepChange?: (stepId: string) => void;
|
|
39
|
+
/** Modal width; default "3xl". */
|
|
40
|
+
size?: "lg" | "xl" | "2xl" | "3xl" | "4xl";
|
|
41
|
+
labels?: WizardLabels;
|
|
42
|
+
"data-testid"?: string;
|
|
43
|
+
}
|
|
44
|
+
/** Same flow inline (a page section, not a modal) — for full-page wizards. */
|
|
45
|
+
export interface WizardProps extends Omit<WizardDialogProps, "isOpen" | "onClose" | "title" | "subtitle" | "size"> {
|
|
46
|
+
/** Renders a Cancel button in the footer when provided. */
|
|
47
|
+
onCancel?: () => void;
|
|
48
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { WizardStep } from "./WizardDialogProps";
|
|
2
|
+
type FlowOptions = {
|
|
3
|
+
steps: WizardStep[];
|
|
4
|
+
stepId?: string;
|
|
5
|
+
onStepChange?: (stepId: string) => void;
|
|
6
|
+
onFinish: () => void;
|
|
7
|
+
resetWhen?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare function useWizardFlow({ steps, stepId, onStepChange, onFinish, resetWhen }: FlowOptions): {
|
|
10
|
+
index: number;
|
|
11
|
+
furthest: number;
|
|
12
|
+
errors: string[];
|
|
13
|
+
step: WizardStep;
|
|
14
|
+
isFirst: boolean;
|
|
15
|
+
isLast: boolean;
|
|
16
|
+
next: () => void;
|
|
17
|
+
back: () => void;
|
|
18
|
+
goto: (target: number) => void;
|
|
19
|
+
finish: () => void;
|
|
20
|
+
};
|
|
21
|
+
export type WizardFlow = ReturnType<typeof useWizardFlow>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useWizardFlow = useWizardFlow;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const wizardSteps_1 = require("./wizardSteps");
|
|
6
|
+
function useWizardFlow({ steps, stepId, onStepChange, onFinish, resetWhen }) {
|
|
7
|
+
const [state, setState] = (0, react_1.useState)(wizardSteps_1.INITIAL_WIZARD_STATE);
|
|
8
|
+
const validators = steps.map((step) => step.validate);
|
|
9
|
+
const controlledIndex = stepId === undefined ? -1 : steps.findIndex((s) => s.id === stepId);
|
|
10
|
+
const isControlled = stepId !== undefined;
|
|
11
|
+
const index = Math.min(isControlled ? Math.max(controlledIndex, 0) : state.index, Math.max(steps.length - 1, 0));
|
|
12
|
+
const furthest = Math.max(state.furthest, index);
|
|
13
|
+
(0, react_1.useEffect)(() => {
|
|
14
|
+
if (resetWhen)
|
|
15
|
+
setState(wizardSteps_1.INITIAL_WIZARD_STATE);
|
|
16
|
+
}, [resetWhen]);
|
|
17
|
+
const dispatch = (0, react_1.useCallback)((action) => {
|
|
18
|
+
const base = { ...state, index, furthest };
|
|
19
|
+
const next = (0, wizardSteps_1.wizardTransition)(base, action, validators);
|
|
20
|
+
setState(next);
|
|
21
|
+
if (next.index !== index)
|
|
22
|
+
onStepChange === null || onStepChange === void 0 ? void 0 : onStepChange(steps[next.index].id);
|
|
23
|
+
},
|
|
24
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
25
|
+
[state, index, furthest, steps, onStepChange]);
|
|
26
|
+
const finish = (0, react_1.useCallback)(() => {
|
|
27
|
+
const invalid = (0, wizardSteps_1.firstInvalidStep)(validators);
|
|
28
|
+
if (invalid) {
|
|
29
|
+
dispatch({ type: "fail", ...invalid });
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
onFinish();
|
|
33
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
34
|
+
}, [dispatch, steps, onFinish]);
|
|
35
|
+
return {
|
|
36
|
+
index,
|
|
37
|
+
furthest,
|
|
38
|
+
errors: state.errors,
|
|
39
|
+
step: steps[index],
|
|
40
|
+
isFirst: index === 0,
|
|
41
|
+
isLast: index === steps.length - 1,
|
|
42
|
+
next: () => dispatch({ type: "next" }),
|
|
43
|
+
back: () => dispatch({ type: "back" }),
|
|
44
|
+
goto: (target) => dispatch({ type: "goto", index: target }),
|
|
45
|
+
finish,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type StepValidator = () => string[];
|
|
2
|
+
/** Reducer state: current step, the furthest validly reached step, and the blocking messages. */
|
|
3
|
+
export type WizardState = {
|
|
4
|
+
index: number;
|
|
5
|
+
/** Furthest step the user has validly reached; stages beyond it stay locked. */
|
|
6
|
+
furthest: number;
|
|
7
|
+
errors: string[];
|
|
8
|
+
};
|
|
9
|
+
/** Actions `wizardTransition` understands. */
|
|
10
|
+
export type WizardAction = {
|
|
11
|
+
type: "next";
|
|
12
|
+
} | {
|
|
13
|
+
type: "back";
|
|
14
|
+
} | {
|
|
15
|
+
type: "goto";
|
|
16
|
+
index: number;
|
|
17
|
+
} | {
|
|
18
|
+
type: "fail";
|
|
19
|
+
index: number;
|
|
20
|
+
errors: string[];
|
|
21
|
+
} | {
|
|
22
|
+
type: "reset";
|
|
23
|
+
};
|
|
24
|
+
export declare const INITIAL_WIZARD_STATE: WizardState;
|
|
25
|
+
/** Pure step reducer: `next` validates the current step, `goto` only reaches steps up to `furthest`. */
|
|
26
|
+
export declare function wizardTransition(state: WizardState, action: WizardAction, validators: (StepValidator | undefined)[]): WizardState;
|
|
27
|
+
/** First step whose validator reports errors, or null when every step is valid. */
|
|
28
|
+
export declare function firstInvalidStep(validators: (StepValidator | undefined)[]): {
|
|
29
|
+
index: number;
|
|
30
|
+
errors: string[];
|
|
31
|
+
} | null;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.INITIAL_WIZARD_STATE = void 0;
|
|
4
|
+
exports.wizardTransition = wizardTransition;
|
|
5
|
+
exports.firstInvalidStep = firstInvalidStep;
|
|
6
|
+
exports.INITIAL_WIZARD_STATE = { index: 0, furthest: 0, errors: [] };
|
|
7
|
+
/** Pure step reducer: `next` validates the current step, `goto` only reaches steps up to `furthest`. */
|
|
8
|
+
function wizardTransition(state, action, validators) {
|
|
9
|
+
var _a, _b;
|
|
10
|
+
const last = validators.length - 1;
|
|
11
|
+
switch (action.type) {
|
|
12
|
+
case "next": {
|
|
13
|
+
const errors = (_b = (_a = validators[state.index]) === null || _a === void 0 ? void 0 : _a.call(validators)) !== null && _b !== void 0 ? _b : [];
|
|
14
|
+
if (errors.length)
|
|
15
|
+
return { ...state, errors };
|
|
16
|
+
const index = Math.min(state.index + 1, last);
|
|
17
|
+
return { index, furthest: Math.max(state.furthest, index), errors: [] };
|
|
18
|
+
}
|
|
19
|
+
case "back":
|
|
20
|
+
return { ...state, index: Math.max(state.index - 1, 0), errors: [] };
|
|
21
|
+
case "goto":
|
|
22
|
+
if (action.index < 0 || action.index > state.furthest)
|
|
23
|
+
return state;
|
|
24
|
+
return { ...state, index: action.index, errors: [] };
|
|
25
|
+
case "fail":
|
|
26
|
+
return { ...state, index: action.index, errors: action.errors };
|
|
27
|
+
case "reset":
|
|
28
|
+
return exports.INITIAL_WIZARD_STATE;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** First step whose validator reports errors, or null when every step is valid. */
|
|
32
|
+
function firstInvalidStep(validators) {
|
|
33
|
+
var _a, _b;
|
|
34
|
+
for (let index = 0; index < validators.length; index += 1) {
|
|
35
|
+
const errors = (_b = (_a = validators[index]) === null || _a === void 0 ? void 0 : _a.call(validators)) !== null && _b !== void 0 ? _b : [];
|
|
36
|
+
if (errors.length)
|
|
37
|
+
return { index, errors };
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
@@ -8,6 +8,7 @@ import { AA_NORMAL_TEXT } from "../../Theme/tokens/builders/accentText.js";
|
|
|
8
8
|
import { liftToContrast, neutralStep, ruleInk, AA_NON_TEXT, CHROME_RULE, MIN_PERCEPTIBLE_STEP, } from "../../Theme/tokens/builders/outlineRung.js";
|
|
9
9
|
import { listRowBackgrounds } from "../../Theme/tokens/builders/rowStates.js";
|
|
10
10
|
import { useExclusiveOverlay } from "../../Hooks/useExclusiveOverlay.js";
|
|
11
|
+
import Kbd from "../Kbd/Kbd.js";
|
|
11
12
|
import AppMark, { assignAppHues } from "./AppMark.js";
|
|
12
13
|
import { filterApps, formatShortcut, } from "./AppSwitcherProps.js";
|
|
13
14
|
import { useAppSwitcherShortcut } from "./useAppSwitcherShortcut.js";
|
|
@@ -190,7 +191,7 @@ const AppSwitcher = ({ apps, currentAppId, onSelect, onOpenChange, isSearchable,
|
|
|
190
191
|
return;
|
|
191
192
|
}
|
|
192
193
|
handlePanelKeyDown(e);
|
|
193
|
-
}, children: _jsx(Grip, { size: s.icon + 1 }) }) }), _jsx(PopoverContent, { w: width, maxW: "calc(100vw - 1.5rem)", textAlign: "start", onKeyDown: handlePanelKeyDown, bg: theme.colors.surfaceRaised, borderRadius: "xl", overflow: "hidden", boxShadow: `0 10px 30px ${theme.colors.boxShadow.default}`, _focus: { outline: "none", boxShadow: `0 10px 30px ${theme.colors.boxShadow.default}` }, children: _jsxs(PopoverBody, { p: 0, children: [_jsxs(Flex, { align: "center", gap: 2, px: 3, pt: 3, pb: showSearch ? 2 : 1, children: [_jsx(Text, { fontSize: "0.6875rem", fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: theme.colors.textMuted, children: HEADING }), _jsx(Box, { flex: "1" }), hint &&
|
|
194
|
+
}, children: _jsx(Grip, { size: s.icon + 1 }) }) }), _jsx(PopoverContent, { w: width, maxW: "calc(100vw - 1.5rem)", textAlign: "start", onKeyDown: handlePanelKeyDown, bg: theme.colors.surfaceRaised, borderRadius: "xl", overflow: "hidden", boxShadow: `0 10px 30px ${theme.colors.boxShadow.default}`, _focus: { outline: "none", boxShadow: `0 10px 30px ${theme.colors.boxShadow.default}` }, children: _jsxs(PopoverBody, { p: 0, children: [_jsxs(Flex, { align: "center", gap: 2, px: 3, pt: 3, pb: showSearch ? 2 : 1, children: [_jsx(Text, { fontSize: "0.6875rem", fontWeight: 600, letterSpacing: "0.08em", textTransform: "uppercase", color: theme.colors.textMuted, children: HEADING }), _jsx(Box, { flex: "1" }), hint && _jsx(Kbd, { size: "xs", children: hint })] }), showSearch && (_jsx(Box, { px: 3, pb: 2, children: _jsxs(InputGroup, { size: "sm", children: [_jsx(InputLeftElement, { pointerEvents: "none", children: _jsx(Search, { size: 15, color: theme.colors.textMuted }) }), _jsx(Input, { ref: searchRef, value: query, onChange: (e) => setQuery(e.target.value), placeholder: "Search apps", borderRadius: "lg", "aria-label": "Search apps", onKeyDown: (e) => {
|
|
194
195
|
if (e.key === "ArrowDown" && visible.length > 0) {
|
|
195
196
|
e.preventDefault();
|
|
196
197
|
focusItem(0);
|
|
@@ -42,12 +42,14 @@ export const matchesShortcut = (event, shortcut, isApple = typeof navigator !==
|
|
|
42
42
|
};
|
|
43
43
|
const APPLE_SYMBOLS = { mod: "⌘", cmd: "⌘", meta: "⌘", ctrl: "⌃", shift: "⇧", alt: "⌥" };
|
|
44
44
|
const OTHER_LABELS = { mod: "Ctrl", cmd: "Win", meta: "Win", ctrl: "Ctrl", shift: "Shift", alt: "Alt" };
|
|
45
|
-
|
|
45
|
+
const isAppleNow = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform);
|
|
46
|
+
/** One label per key in a chord, so a named key such as `enter` stays a single cap. */
|
|
47
|
+
export const shortcutKeys = (shortcut, isApple = isAppleNow()) => {
|
|
46
48
|
const parts = shortcut.toLowerCase().split("+").map((p) => p.trim()).filter(Boolean);
|
|
47
49
|
const table = isApple ? APPLE_SYMBOLS : OTHER_LABELS;
|
|
48
|
-
|
|
49
|
-
return isApple ? rendered.join("") : rendered.join("+");
|
|
50
|
+
return parts.map((p, i) => { var _a; return (i === parts.length - 1 ? p.toUpperCase() : ((_a = table[p]) !== null && _a !== void 0 ? _a : p.toUpperCase())); });
|
|
50
51
|
};
|
|
52
|
+
export const formatShortcut = (shortcut, isApple = isAppleNow()) => shortcutKeys(shortcut, isApple).join(isApple ? "" : "+");
|
|
51
53
|
/**
|
|
52
54
|
* Derives every app's origin from the host the consumer is already served on, so one deployment
|
|
53
55
|
* variable keeps dev, test and prod in step. An app may still carry its own `url`, which wins.
|