pixelize-design-library 2.4.2-beta.44 → 2.4.2-beta.46
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 +75 -0
- package/COMPONENT-GOTCHAS.md +58 -1
- package/dist/Components/Common/fieldStyles.d.ts +1 -1
- package/dist/Components/Common/fieldStyles.js +4 -4
- package/dist/Components/DatePicker/CalendarPanel.js +2 -5
- package/dist/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.js +2 -4
- package/dist/Components/FilterSidebar/FilterSidebar.js +2 -1
- package/dist/Components/Header/HeaderActions.d.ts +2 -0
- package/dist/Components/Header/HeaderActions.js +2 -2
- package/dist/Components/Input/TextInput.styles.js +1 -1
- package/dist/Components/KanbanBoard/KanbanActions/KanbanActions.js +1 -1
- package/dist/Components/KanbanBoard/KanbanBoardProps.d.ts +2 -0
- package/dist/Components/MultiSelect/MultiSelect.d.ts +1 -1
- package/dist/Components/MultiSelect/MultiSelect.js +23 -12
- package/dist/Components/MultiSelect/MultiSelectProps.d.ts +2 -0
- package/dist/Components/NotificationBell/notificationHelpers.d.ts +5 -2
- package/dist/Components/NotificationBell/notificationHelpers.js +13 -4
- package/dist/Components/PinInput/PinInput.js +2 -4
- package/dist/Components/SearchSelect/SearchSelect.js +1 -1
- package/dist/Components/SegmentedControl/SegmentedControl.d.ts +1 -1
- package/dist/Components/SegmentedControl/SegmentedControl.js +33 -16
- package/dist/Components/SegmentedControl/SegmentedControlProps.d.ts +2 -0
- package/dist/Components/SegmentedControl/segmentedInk.d.ts +11 -0
- package/dist/Components/SegmentedControl/segmentedInk.js +27 -0
- package/dist/Components/Select/SelectPopup.js +13 -4
- package/dist/Components/Select/optionRowInk.d.ts +3 -0
- package/dist/Components/Select/optionRowInk.js +6 -0
- package/dist/Components/SideBar/SecondaryBar.js +5 -4
- package/dist/Components/SideBar/SideBar.js +6 -5
- package/dist/Components/SideBar/SideBarProps.d.ts +2 -0
- package/dist/Components/SideBar/components/MenuItemBox.js +5 -4
- package/dist/Components/SideBar/components/MenuItems.js +1 -1
- package/dist/Components/SideBar/components/MenuPopoverContent.js +4 -3
- package/dist/Components/SideBar/sidebarScale.d.ts +15 -0
- package/dist/Components/SideBar/sidebarScale.js +18 -0
- package/dist/Components/Switch/Switch.d.ts +2 -2
- package/dist/Components/Switch/Switch.js +3 -3
- package/dist/Components/Switch/SwitchProps.d.ts +2 -0
- package/dist/Components/Table/components/Pagination.d.ts +1 -1
- package/dist/Components/Table/components/Pagination.js +12 -4
- package/dist/Components/Table/filters/SelectOperationControls.js +9 -1
- package/dist/Components/Table/filters/TextOperationControls.js +8 -1
- package/dist/Components/Table/hooks/useTable.d.ts +2 -1
- package/dist/Components/Table/hooks/useTable.js +5 -3
- package/dist/Components/Tabs/components/Tab.js +11 -1
- package/dist/Theme/chakra/focusRing.styles.d.ts +17 -1
- package/dist/Theme/chakra/focusRing.styles.js +16 -1
- package/dist/Theme/provider/ThemeSwitcher.js +15 -8
- package/dist/esm/Components/Common/fieldStyles.js +5 -5
- package/dist/esm/Components/DatePicker/CalendarPanel.js +2 -5
- package/dist/esm/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.js +2 -4
- package/dist/esm/Components/FilterSidebar/FilterSidebar.js +2 -1
- package/dist/esm/Components/Header/HeaderActions.js +2 -2
- package/dist/esm/Components/Input/TextInput.styles.js +2 -2
- package/dist/esm/Components/KanbanBoard/KanbanActions/KanbanActions.js +1 -1
- package/dist/esm/Components/MultiSelect/MultiSelect.js +23 -12
- package/dist/esm/Components/NotificationBell/notificationHelpers.js +13 -4
- package/dist/esm/Components/PinInput/PinInput.js +2 -4
- package/dist/esm/Components/SearchSelect/SearchSelect.js +1 -1
- package/dist/esm/Components/SegmentedControl/SegmentedControl.js +32 -15
- package/dist/esm/Components/SegmentedControl/segmentedInk.js +20 -0
- package/dist/esm/Components/Select/SelectPopup.js +14 -5
- package/dist/esm/Components/Select/optionRowInk.js +2 -0
- package/dist/esm/Components/SideBar/SecondaryBar.js +5 -4
- package/dist/esm/Components/SideBar/SideBar.js +6 -5
- package/dist/esm/Components/SideBar/components/MenuItemBox.js +5 -4
- package/dist/esm/Components/SideBar/components/MenuItems.js +1 -1
- package/dist/esm/Components/SideBar/components/MenuPopoverContent.js +4 -3
- package/dist/esm/Components/SideBar/sidebarScale.js +15 -0
- package/dist/esm/Components/Switch/Switch.js +3 -3
- package/dist/esm/Components/Table/components/Pagination.js +13 -5
- package/dist/esm/Components/Table/filters/SelectOperationControls.js +8 -3
- package/dist/esm/Components/Table/filters/TextOperationControls.js +6 -2
- package/dist/esm/Components/Table/hooks/useTable.js +4 -3
- package/dist/esm/Components/Tabs/components/Tab.js +12 -2
- package/dist/esm/Theme/chakra/focusRing.styles.js +13 -0
- package/dist/esm/Theme/provider/ThemeSwitcher.js +16 -9
- package/package.json +1 -1
|
@@ -5,7 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.default = SegmentedControl;
|
|
7
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
-
const react_1 = require("
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const react_2 = require("@chakra-ui/react");
|
|
9
10
|
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
10
11
|
const filledSurface_1 = require("../../Theme/tokens/builders/filledSurface");
|
|
11
12
|
const controlSizes_1 = require("../../Theme/tokens/primitives/controlSizes");
|
|
@@ -14,9 +15,9 @@ const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
|
14
15
|
const motion_2 = require("../../Theme/chakra/motion");
|
|
15
16
|
const accentText_1 = require("../../Theme/tokens/builders/accentText");
|
|
16
17
|
const outlineRung_1 = require("../../Theme/tokens/builders/outlineRung");
|
|
17
|
-
const color_1 = require("../../Theme/tokens/builders/color");
|
|
18
18
|
const Tag_1 = __importDefault(require("../Tag/Tag"));
|
|
19
19
|
const useSlidingPill_1 = require("./useSlidingPill");
|
|
20
|
+
const segmentedInk_1 = require("./segmentedInk");
|
|
20
21
|
const TRACK_PADDING = "0.125rem";
|
|
21
22
|
const UNDERLINE_WIDTH = "0.0625rem";
|
|
22
23
|
const SLIDE = (0, motion_1.transitionFor)(["transform", "width"], "base");
|
|
@@ -24,21 +25,33 @@ const MAX_COUNT = 99;
|
|
|
24
25
|
const COUNT_TAG_SIZE = { sm: "xs", md: "sm", lg: "md" };
|
|
25
26
|
const formatCount = (count) => (count > MAX_COUNT ? `${MAX_COUNT}+` : `${count}`);
|
|
26
27
|
/** Renders role="radiogroup" of role="radio" buttons with roving tabindex, not a native form radio group; shares variant with Toggle/TableToggle (see MODULE.md). */
|
|
27
|
-
function SegmentedControl({ options, value, onChange, size = "sm", isFullWidth = false, variant = "default", "aria-label": ariaLabel, }) {
|
|
28
|
-
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
28
|
+
function SegmentedControl({ options, value, onChange, size = "sm", isFullWidth = false, variant = "default", surface, "aria-label": ariaLabel, }) {
|
|
29
|
+
const { colors, radii } = (0, useCustomTheme_1.useCustomTheme)();
|
|
29
30
|
const control = controlSizes_1.CONTROL_SIZES[size];
|
|
30
31
|
const isBrandSlide = variant === "brandSlide";
|
|
31
32
|
const isUnderlineSlide = variant === "underlineSlide";
|
|
32
33
|
const hasIndicator = isBrandSlide || isUnderlineSlide;
|
|
33
34
|
const brandFill = (0, filledSurface_1.resolveFilledSurface)(colors.primary, colors);
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
? (0, color_1.compositeOver)(colors.primary.opacity[8], colors.backgroundColor.main)
|
|
39
|
-
: colors.background[600];
|
|
40
|
-
const restInk = (0, outlineRung_1.liftToContrast)(colors.text[600], trackSurface, accentText_1.AA_NORMAL_TEXT);
|
|
35
|
+
const trackSurface = (0, segmentedInk_1.segmentedTrackSurface)(variant, colors, surface);
|
|
36
|
+
const restInk = (0, segmentedInk_1.segmentedRestInk)(colors, trackSurface);
|
|
37
|
+
const selectedInk = (0, outlineRung_1.liftToContrast)(colors.accentText, trackSurface, accentText_1.AA_NORMAL_TEXT);
|
|
38
|
+
const hoverInk = (0, outlineRung_1.liftToContrast)(colors.text[900], trackSurface, accentText_1.AA_NORMAL_TEXT);
|
|
41
39
|
const segmentH = `calc(${control.height} - ${isUnderlineSlide ? UNDERLINE_WIDTH : `2 * ${TRACK_PADDING}`})`;
|
|
40
|
+
// Concentric: an inset child keeping the parent's radius bulges at the corners.
|
|
41
|
+
const innerRadius = isUnderlineSlide ? "none" : `calc(${radii.lg} - ${TRACK_PADDING})`;
|
|
42
|
+
const focusShadow = (0, segmentedInk_1.segmentedFocusShadow)(colors, trackSurface);
|
|
43
|
+
// Inset, never a border: a border consumes the content box and the absolute pill stops centring.
|
|
44
|
+
const plateEdge = isBrandSlide
|
|
45
|
+
? `inset 0 0 0 1px ${(0, segmentedInk_1.segmentedPlateEdge)(colors, surface)}`
|
|
46
|
+
: undefined;
|
|
47
|
+
// The transparent outline replaces the UA ring and is what Windows high-contrast repaints.
|
|
48
|
+
const segmentFocus = {
|
|
49
|
+
outline: "2px solid transparent",
|
|
50
|
+
outlineOffset: "2px",
|
|
51
|
+
// underlineSlide has no track chrome to carry the indicator, so there the segment wears it.
|
|
52
|
+
...(isUnderlineSlide ? { boxShadow: focusShadow } : {}),
|
|
53
|
+
};
|
|
54
|
+
const [showFocus, setShowFocus] = (0, react_1.useState)(false);
|
|
42
55
|
const selectedIndex = options.findIndex((o) => o.value === value);
|
|
43
56
|
const enabled = options.reduce((acc, o, i) => (o.isDisabled ? acc : [...acc, i]), []);
|
|
44
57
|
// WAI-APG: with nothing selected, the first enabled segment owns the tab stop.
|
|
@@ -77,11 +90,11 @@ function SegmentedControl({ options, value, onChange, size = "sm", isFullWidth =
|
|
|
77
90
|
selectAt(enabled[enabled.length - 1]);
|
|
78
91
|
}
|
|
79
92
|
};
|
|
80
|
-
return ((0, jsx_runtime_1.jsxs)(
|
|
93
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { ref: trackRef, role: "radiogroup", "aria-label": ariaLabel, onKeyDown: handleKeyDown, onFocus: (event) => setShowFocus(event.target.matches(":focus-visible")), onBlur: () => setShowFocus(false), boxShadow: showFocus && !isUnderlineSlide ? focusShadow : plateEdge, position: "relative", display: "inline-flex", align: "center", gap: isUnderlineSlide ? "0" : TRACK_PADDING, p: isUnderlineSlide ? "0" : TRACK_PADDING, h: control.height, boxSizing: "border-box", borderRadius: isUnderlineSlide ? "none" : "lg", borderBottom: isUnderlineSlide ? `${UNDERLINE_WIDTH} solid ${colors.boxborder[200]}` : undefined, bg: isUnderlineSlide ? "transparent" : trackSurface, w: isFullWidth ? "100%" : "fit-content", minW: "max-content", children: [isBrandSlide && pill && ((0, jsx_runtime_1.jsx)(react_2.Box, { "aria-hidden": "true", position: "absolute", top: TRACK_PADDING, left: 0, h: segmentH, w: `${pill.width}px`, borderRadius: innerRadius, bg: brandFill.fill, boxShadow: `0 0.125rem 0.5rem ${colors.boxShadow.primary}`, transform: `translateX(${pill.left}px)`, transition: SLIDE, sx: (0, motion_2.reducedMotionSx)() })), isUnderlineSlide && pill && ((0, jsx_runtime_1.jsx)(react_2.Box, { "aria-hidden": "true", position: "absolute", bottom: "-0.0625rem", left: 0, h: "0.125rem", w: `${pill.width}px`, borderRadius: "full", bg: colors.primary[500], transform: `translateX(${pill.left}px)`, transition: SLIDE, sx: (0, motion_2.reducedMotionSx)() })), options.map((option, index) => {
|
|
81
94
|
const isSelected = option.value === value;
|
|
82
|
-
return ((0, jsx_runtime_1.jsxs)(
|
|
95
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Box, { as: "button", type: "button", ref: (node) => {
|
|
83
96
|
refs.current[index] = node;
|
|
84
|
-
}, role: "radio", "aria-checked": isSelected, disabled: option.isDisabled, tabIndex: index === tabIndex ? 0 : -1, onClick: () => onChange(option.value), position: "relative", zIndex: 1, display: "inline-flex", alignItems: "center", justifyContent: "center", gap: "0.375rem", flex: isFullWidth ? "1" : undefined, h: segmentH, px: control.paddingX, borderRadius:
|
|
97
|
+
}, role: "radio", "aria-checked": isSelected, disabled: option.isDisabled, tabIndex: index === tabIndex ? 0 : -1, onClick: () => onChange(option.value), position: "relative", zIndex: 1, display: "inline-flex", alignItems: "center", justifyContent: "center", gap: "0.375rem", flex: isFullWidth ? "1" : undefined, h: segmentH, px: control.paddingX, borderRadius: innerRadius, borderWidth: "1px", borderStyle: "solid", borderColor: hasIndicator
|
|
85
98
|
? "transparent"
|
|
86
99
|
: isSelected
|
|
87
100
|
? colors.primary.opacity[32]
|
|
@@ -90,7 +103,11 @@ function SegmentedControl({ options, value, onChange, size = "sm", isFullWidth =
|
|
|
90
103
|
? brandFill.color
|
|
91
104
|
: restInk
|
|
92
105
|
: isSelected
|
|
93
|
-
?
|
|
94
|
-
: restInk, fontSize: control.fontSize, fontWeight: isSelected ? 600 : 500, whiteSpace: "nowrap", opacity: option.isDisabled ? 0.5 : 1, cursor: option.isDisabled ? "not-allowed" : "pointer", transition: (0, motion_1.transitionFor)(["color"]), _hover: option.isDisabled || isSelected ? undefined : { color:
|
|
106
|
+
? selectedInk
|
|
107
|
+
: restInk, fontSize: control.fontSize, fontWeight: isSelected ? 600 : 500, whiteSpace: "nowrap", opacity: option.isDisabled ? 0.5 : 1, cursor: option.isDisabled ? "not-allowed" : "pointer", transition: (0, motion_1.transitionFor)(["color"]), _hover: option.isDisabled || isSelected ? undefined : { color: hoverInk }, sx: {
|
|
108
|
+
_focusVisible: segmentFocus,
|
|
109
|
+
[focusRing_styles_1.FOCUS_VISIBLE_OVER_STATE]: segmentFocus,
|
|
110
|
+
...(0, motion_2.reducedMotionSx)(),
|
|
111
|
+
}, children: [option.icon, option.label, option.count != null && ((0, jsx_runtime_1.jsx)(Tag_1.default, { label: formatCount(option.count), size: COUNT_TAG_SIZE[size], variant: "subtle", colorScheme: "gray" }))] }, option.value));
|
|
95
112
|
})] }));
|
|
96
113
|
}
|
|
@@ -27,5 +27,7 @@ export type SegmentedControlProps<T extends string = string> = {
|
|
|
27
27
|
isFullWidth?: boolean;
|
|
28
28
|
/** brandSlide = primary view switcher; underlineSlide = dense toolbars/headers. */
|
|
29
29
|
variant?: SegmentedControlVariant;
|
|
30
|
+
/** Background this sits on. Optional: the track is opaque on any backdrop; pass it only to aim the plate's hairline edge at the real backdrop. */
|
|
31
|
+
surface?: string;
|
|
30
32
|
"aria-label": string;
|
|
31
33
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PaletteProps } from "../../Theme/tokens/types";
|
|
2
|
+
import type { SegmentedControlVariant } from "./SegmentedControlProps";
|
|
3
|
+
/** The surface a segment's label really sits on. */
|
|
4
|
+
export declare const segmentedTrackSurface: (variant: SegmentedControlVariant, colors: PaletteProps, surface?: string) => string;
|
|
5
|
+
/** Unselected label ink, lifted to AA against the track it is drawn on. */
|
|
6
|
+
export declare const segmentedRestInk: (colors: PaletteProps, trackSurface: string) => string;
|
|
7
|
+
/** A radiogroup is one tab stop, so the group wears the ring: a brand hairline plus the field bloom. */
|
|
8
|
+
export declare const segmentedFocusShadow: (colors: PaletteProps, trackSurface: string) => string;
|
|
9
|
+
/** The plate can match its backdrop's lightness, so its edge carries the boundary.
|
|
10
|
+
* Drawn inset by the caller: a real border consumes the content box and decentres the sliding pill. */
|
|
11
|
+
export declare const segmentedPlateEdge: (colors: PaletteProps, surface?: string) => string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.segmentedPlateEdge = exports.segmentedFocusShadow = exports.segmentedRestInk = exports.segmentedTrackSurface = void 0;
|
|
4
|
+
const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
5
|
+
const outlineRung_1 = require("../../Theme/tokens/builders/outlineRung");
|
|
6
|
+
const accentText_1 = require("../../Theme/tokens/builders/accentText");
|
|
7
|
+
/** The surface a segment's label really sits on. */
|
|
8
|
+
const segmentedTrackSurface = (variant, colors, surface) => {
|
|
9
|
+
if (variant === "underlineSlide")
|
|
10
|
+
return surface !== null && surface !== void 0 ? surface : colors.backgroundColor.main;
|
|
11
|
+
// brandSlide paints an opaque plate on every backdrop: a tint composites into an unknown
|
|
12
|
+
// parent, so its ink was derived from a canvas the control was not actually on.
|
|
13
|
+
if (variant === "brandSlide")
|
|
14
|
+
return colors.surfaceRaised;
|
|
15
|
+
return colors.background[600];
|
|
16
|
+
};
|
|
17
|
+
exports.segmentedTrackSurface = segmentedTrackSurface;
|
|
18
|
+
/** Unselected label ink, lifted to AA against the track it is drawn on. */
|
|
19
|
+
const segmentedRestInk = (colors, trackSurface) => (0, outlineRung_1.liftToContrast)(colors.text[600], trackSurface, accentText_1.AA_NORMAL_TEXT);
|
|
20
|
+
exports.segmentedRestInk = segmentedRestInk;
|
|
21
|
+
/** A radiogroup is one tab stop, so the group wears the ring: a brand hairline plus the field bloom. */
|
|
22
|
+
const segmentedFocusShadow = (colors, trackSurface) => `inset 0 0 0 1px ${(0, outlineRung_1.liftToContrast)(colors.primary[500], trackSurface, outlineRung_1.AA_NON_TEXT)}, ${(0, focusRing_styles_1.focusGlowShadow)(colors)}`;
|
|
23
|
+
exports.segmentedFocusShadow = segmentedFocusShadow;
|
|
24
|
+
/** The plate can match its backdrop's lightness, so its edge carries the boundary.
|
|
25
|
+
* Drawn inset by the caller: a real border consumes the content box and decentres the sliding pill. */
|
|
26
|
+
const segmentedPlateEdge = (colors, surface) => (0, outlineRung_1.liftToContrast)(colors.boxborder[500], surface !== null && surface !== void 0 ? surface : colors.backgroundColor.main, outlineRung_1.AA_NON_TEXT);
|
|
27
|
+
exports.segmentedPlateEdge = segmentedPlateEdge;
|
|
@@ -41,12 +41,13 @@ const react_1 = __importStar(require("react"));
|
|
|
41
41
|
const react_2 = require("@chakra-ui/react");
|
|
42
42
|
const lucide_react_1 = require("lucide-react");
|
|
43
43
|
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
44
|
+
const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
44
45
|
const rowStates_1 = require("../../Theme/tokens/builders/rowStates");
|
|
46
|
+
const optionRowInk_1 = require("./optionRowInk");
|
|
45
47
|
const scrollbar_1 = require("../../Theme/tokens/builders/scrollbar");
|
|
46
48
|
const controlSizes_1 = require("../../Theme/tokens/primitives/controlSizes");
|
|
47
49
|
const motion_1 = require("../../Theme/tokens/primitives/motion");
|
|
48
50
|
const motion_2 = require("../../Theme/chakra/motion");
|
|
49
|
-
const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
|
|
50
51
|
const fieldStyles_1 = require("../Common/fieldStyles");
|
|
51
52
|
const useFieldIds_1 = require("../Common/useFieldIds");
|
|
52
53
|
const FieldMessage_1 = __importDefault(require("../Common/FieldMessage"));
|
|
@@ -80,7 +81,7 @@ const OptionRow = react_1.default.memo(function OptionRow({ option, index, listb
|
|
|
80
81
|
const isSingleSelected = isSelected && !isMulti;
|
|
81
82
|
const selectedBg = isActive ? backgrounds.selectedActive : backgrounds.selected;
|
|
82
83
|
const restBg = isActive ? backgrounds.active : "transparent";
|
|
83
|
-
return ((0, jsx_runtime_1.jsxs)(react_2.Box, { id: optionDomId(listboxId, option.id), "data-index": index, role: "option", "aria-selected": isSelected, "aria-disabled": option.isDisabled, onMouseEnter: () => onActivate(index), onClick: () => onSelect(option), mx: 1.5, px: 2.5, py: 1.5, borderRadius: "md", cursor: option.isDisabled ? "not-allowed" : "pointer", opacity: option.isDisabled ? 0.4 : 1, display: "flex", alignItems: "center", gap: 2, fontSize: "0.8125rem", fontWeight: isSingleSelected ? 600 : 400, color:
|
|
84
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Box, { id: optionDomId(listboxId, option.id), "data-index": index, role: "option", "aria-selected": isSelected, "aria-disabled": option.isDisabled, onMouseEnter: () => onActivate(index), onClick: () => onSelect(option), mx: 1.5, px: 2.5, py: 1.5, borderRadius: "md", cursor: option.isDisabled ? "not-allowed" : "pointer", opacity: option.isDisabled ? 0.4 : 1, display: "flex", alignItems: "center", gap: 2, fontSize: "0.8125rem", fontWeight: isSingleSelected ? 600 : 400, color: (0, optionRowInk_1.optionRowInk)(theme.colors, isSingleSelected), bg: isSingleSelected ? selectedBg : restBg, transition: ROW_TRANSITION, sx: (0, motion_2.reducedMotionSx)(), children: [isMulti ? ((0, jsx_runtime_1.jsx)(react_2.Checkbox, { id: `${optionDomId(listboxId, option.id)}-checkbox`, isChecked: isSelected, isDisabled: option.isDisabled, pointerEvents: "none", tabIndex: -1 })) : null, renderOption ? ((0, jsx_runtime_1.jsx)(react_2.Box, { flex: 1, minW: 0, children: renderOption(option, { isSelected, isActive }) })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [option.icon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, children: option.icon })) : null, (0, jsx_runtime_1.jsxs)(react_2.Box, { flex: 1, minW: 0, isTruncated: true, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", isTruncated: true, children: option.label }), option.description ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "block", fontSize: "0.75rem", color: theme.colors.textMuted, isTruncated: true, children: option.description })) : null] })] })), isSingleSelected ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: lucide_react_1.Check, size: 16, color: theme.colors.accentText, flexShrink: 0 })) : null] }));
|
|
84
85
|
});
|
|
85
86
|
const buildGroupedRows = (options) => {
|
|
86
87
|
const rows = [];
|
|
@@ -108,6 +109,7 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
|
|
|
108
109
|
const mergedTriggerRef = (0, react_2.useMergeRefs)(triggerRef, ref);
|
|
109
110
|
const filterInputRef = (0, react_1.useRef)(null);
|
|
110
111
|
const listRef = (0, react_1.useRef)(null);
|
|
112
|
+
const [triggerWidth, setTriggerWidth] = (0, react_1.useState)(0);
|
|
111
113
|
const ids = (0, useFieldIds_1.useFieldIds)(id, { error, errorMessage, helperText });
|
|
112
114
|
const listboxId = `${ids.inputId}-listbox`;
|
|
113
115
|
const filterInputId = `${listboxId}-filter`;
|
|
@@ -200,6 +202,13 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
|
|
|
200
202
|
},
|
|
201
203
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
202
204
|
[isInteractive, props.isMulti, props.onChange, isValueControlled, onClear]);
|
|
205
|
+
// The panel grows past the trigger to fit long labels, so it cannot inherit the anchor width.
|
|
206
|
+
(0, react_1.useEffect)(() => {
|
|
207
|
+
const node = triggerRef.current;
|
|
208
|
+
if (!isOpen || !node)
|
|
209
|
+
return;
|
|
210
|
+
setTriggerWidth(node.getBoundingClientRect().width);
|
|
211
|
+
}, [isOpen]);
|
|
203
212
|
(0, react_1.useEffect)(() => {
|
|
204
213
|
if (!isOpen || !isSearchable)
|
|
205
214
|
return;
|
|
@@ -375,7 +384,7 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
|
|
|
375
384
|
...chipTriggerSizeStyles(size, showChips, chipSize),
|
|
376
385
|
...(selectedOptions.length ? {} : { color: colors.textMuted }),
|
|
377
386
|
...(isOpen
|
|
378
|
-
? { borderColor: error ? colors.semanticText.error : colors.primary[500], boxShadow: (0, focusRing_styles_1.
|
|
387
|
+
? { borderColor: error ? colors.semanticText.error : colors.primary[500], boxShadow: (0, focusRing_styles_1.focusGlowShadow)(colors) }
|
|
379
388
|
: {}),
|
|
380
389
|
...(0, motion_2.reducedMotionSx)(),
|
|
381
390
|
}), [colors, size, showChips, chipSize, selectedOptions.length, isOpen, error]);
|
|
@@ -402,7 +411,7 @@ const SelectPopup = (0, react_1.forwardRef)(function SelectPopup(props, ref) {
|
|
|
402
411
|
const selectedValueIds = selectedOptions.map((option) => option.id.toString());
|
|
403
412
|
const hiddenValues = !name ? [] : props.isMulti ? selectedValueIds : [(_c = selectedValueIds[0]) !== null && _c !== void 0 ? _c : ""];
|
|
404
413
|
const groupedRows = (0, react_1.useMemo)(() => (hasGroups ? buildGroupedRows(filteredOptions) : []), [hasGroups, filteredOptions]);
|
|
405
|
-
return ((0, jsx_runtime_1.jsxs)(react_2.FormControl, { isInvalid: error, isDisabled: isDisabled, isReadOnly: isReadOnly, style: formControlStyle, width: width, children: [label && ((0, jsx_runtime_1.jsx)(FormLabel_1.TextLabel, { label: label, id: ids.inputId, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), (0, jsx_runtime_1.jsxs)(react_2.Popover, { isOpen: isOpen, onClose: () => resetAndClose(), placement: "bottom-start",
|
|
414
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.FormControl, { isInvalid: error, isDisabled: isDisabled, isReadOnly: isReadOnly, style: formControlStyle, width: width, children: [label && ((0, jsx_runtime_1.jsx)(FormLabel_1.TextLabel, { label: label, id: ids.inputId, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), (0, jsx_runtime_1.jsxs)(react_2.Popover, { isOpen: isOpen, onClose: () => resetAndClose(), placement: "bottom-start", autoFocus: false, returnFocusOnClose: false, gutter: 4, children: [(0, jsx_runtime_1.jsx)(react_2.PopoverAnchor, { children: (0, jsx_runtime_1.jsxs)(react_2.Box, { as: "div", ref: mergedTriggerRef, ...ids.controlProps, role: "combobox", tabIndex: isDisabled ? -1 : 0, "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-controls": listboxId, "aria-owns": `${listboxId} ${filterInputId}`, "aria-activedescendant": activeDescendantId, "aria-disabled": isDisabled || undefined, "data-readonly": isReadOnly || undefined, "aria-required": isRequired || undefined, "aria-label": triggerAriaLabel(), "aria-labelledby": ariaLabelledBy, onClick: handleOpen, onKeyDown: handleTriggerKeyDown, display: "flex", alignItems: "center", justifyContent: "space-between", width: "100%", textAlign: "left", cursor: isDisabled ? "not-allowed" : isReadOnly ? "default" : "pointer", "data-testid": dataTestId, sx: triggerSx, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexWrap: showChips ? "wrap" : "nowrap", alignItems: "center", gap: showChips ? 1 : 1.5, minW: 0, flex: 1, isTruncated: !showChips, children: showChips ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [visibleChipOptions.map((option) => ((0, jsx_runtime_1.jsx)(Tag_1.default, { label: String(option.label), size: chipSize, variant: "subtle", icon: isInteractive ? lucide_react_1.X : undefined, onIconClick: isInteractive ? () => handleSelect(option) : undefined }, option.id))), overflowChipCount > 0 && ((0, jsx_runtime_1.jsx)(Tag_1.default, { label: `+${overflowChipCount}`, size: chipSize, variant: "subtle", colorScheme: "gray" }))] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [triggerIcon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, children: triggerIcon })) : null, (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", isTruncated: true, children: renderValue ? renderValue(selectedOptions) : defaultTriggerContent() })] })) }), showClear && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", "aria-label": "Clear selection", onClick: handleClear, display: "inline-flex", alignItems: "center", justifyContent: "center", flexShrink: 0, ml: 2, color: colors.textMuted, _hover: { color: colors.text[700] }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { size: controlSizes_1.CONTROL_SIZES[size].iconSize }) })), (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-flex", flexShrink: 0, ml: 2, transition: CHEVRON_TRANSITION, transform: isOpen ? "rotate(180deg)" : "rotate(0deg)", color: colors.textMuted, sx: (0, motion_2.reducedMotionSx)(), children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronDown, { size: controlSizes_1.CONTROL_SIZES[size].iconSize }) })] }) }), (0, jsx_runtime_1.jsx)(react_2.Portal, { children: (0, jsx_runtime_1.jsxs)(react_2.PopoverContent, { width: "max-content", minWidth: triggerWidth ? `${triggerWidth}px` : undefined, maxWidth: "min(24rem, calc(100vw - 2rem))", borderRadius: "xl", boxShadow: theme.shadows.lg, overflow: "hidden", onKeyDown: handleListKeyDown, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { p: 2, borderBottom: `0.063rem solid ${colors.boxborder[200]}`, display: isSearchable ? undefined : "none", children: (0, jsx_runtime_1.jsx)(react_2.Input, { ref: filterInputRef, id: filterInputId, size: "sm", placeholder: "Type to filter...", value: currentSearch, onChange: handleFilterChange, "aria-activedescendant": activeDescendantId, "aria-controls": listboxId, "aria-label": "Filter options", tabIndex: isSearchable ? undefined : -1 }) }), (0, jsx_runtime_1.jsxs)(react_2.Box, { id: listboxId, ref: listRef, role: "listbox", "aria-label": (_d = label !== null && label !== void 0 ? label : ariaLabel) !== null && _d !== void 0 ? _d : placeholder, "aria-multiselectable": props.isMulti || undefined, "aria-busy": isLoading || undefined, maxH: maxMenuHeight, overflowY: "auto", py: 1, sx: listScrollStyles, onScroll: handleListScroll, children: [filteredOptions.length === 0 && !isLoading && !showCreateRow && ((0, jsx_runtime_1.jsx)(react_2.Box, { px: 3, py: 2, fontSize: "0.8125rem", color: colors.textMuted, children: noOptionsMessage !== null && noOptionsMessage !== void 0 ? noOptionsMessage : "No Options" })), showCreateRow && ((0, jsx_runtime_1.jsx)(react_2.Box, { id: createRowId, role: "option", "aria-selected": false, "data-index": -1, onClick: handleCreate, mx: 1.5, px: 2.5, py: 1.5, borderRadius: "md", cursor: "pointer", fontSize: "0.8125rem", fontWeight: 600, color: colors.primary[600], bg: activeDescendantId === createRowId ? rowBackgrounds.active : "transparent", children: createLabel ? createLabel(currentSearch.trim()) : `Create "${currentSearch.trim()}"` })), hasGroups
|
|
406
415
|
? groupedRows.map((row) => {
|
|
407
416
|
var _a;
|
|
408
417
|
return row.kind === "header" ? ((0, jsx_runtime_1.jsx)(react_2.Box, { px: 3, pt: 2, pb: 1, fontSize: "0.6875rem", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.03em", color: colors.textMuted, children: row.group }, row.key)) : ((0, jsx_runtime_1.jsx)(OptionRow, { option: row.option, index: row.index, listboxId: listboxId, isSelected: selectedIds.has(row.option.id.toString()), isActive: row.index === activeIndex, isMulti: (_a = props.isMulti) !== null && _a !== void 0 ? _a : false, theme: theme, backgrounds: rowBackgrounds, renderOption: renderOption, onSelect: handleSelect, onActivate: setActiveIndex }, row.key));
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.optionRowInk = void 0;
|
|
4
|
+
/** Selection is carried by weight and a trailing brand check, so the label itself stays neutral. */
|
|
5
|
+
const optionRowInk = (colors, isSingleSelected) => isSingleSelected ? colors.text[900] : colors.text[700];
|
|
6
|
+
exports.optionRowInk = optionRowInk;
|
|
@@ -18,6 +18,7 @@ const tone_1 = require("../../Theme/tokens/builders/tone");
|
|
|
18
18
|
const sidebarAccent_1 = require("../../Theme/tokens/builders/sidebarAccent");
|
|
19
19
|
const paletteFromTheme_1 = require("../../Theme/chakra/paletteFromTheme");
|
|
20
20
|
const viewportHeight_1 = require("../../Theme/tokens/builders/viewportHeight");
|
|
21
|
+
const sidebarScale_1 = require("./sidebarScale");
|
|
21
22
|
const softBadge = (colors, colorScheme, surface) => {
|
|
22
23
|
const tone = (0, tone_1.resolveSoftTone)(colors, (0, paletteFromTheme_1.scaleFor)(colors, colorScheme), surface);
|
|
23
24
|
return { bg: tone.bg, color: tone.fg };
|
|
@@ -46,7 +47,7 @@ const CollapsedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
|
|
|
46
47
|
e.preventDefault();
|
|
47
48
|
if (!(0, menuDisabled_1.menuDisabled)(item))
|
|
48
49
|
onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick(item);
|
|
49
|
-
}, bg: isActive ? "whiteAlpha.300" : "transparent", transition: "background 0.12s", children: (0, jsx_runtime_1.jsxs)(react_2.Box, { position: "relative", display: "flex", alignItems: "center", children: [(0, jsx_runtime_1.jsx)(react_2.Icon, { as: item.icon, fontSize:
|
|
50
|
+
}, bg: isActive ? "whiteAlpha.300" : "transparent", transition: "background 0.12s", children: (0, jsx_runtime_1.jsxs)(react_2.Box, { position: "relative", display: "flex", alignItems: "center", children: [(0, jsx_runtime_1.jsx)(react_2.Icon, { as: item.icon, fontSize: sidebarScale_1.SIDEBAR_ROW.iconSize, color: isActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), badgeVal != null && ((0, jsx_runtime_1.jsx)(react_2.Box, { position: "absolute", top: "0", right: "0", w: "0.375rem", h: "0.375rem", borderRadius: "full", bg: theme.colors.red[400] }))] }) }) }), (0, jsx_runtime_1.jsx)(react_2.Portal, { children: (0, jsx_runtime_1.jsx)(react_2.PopoverContent, { borderRadius: "lg", bg: theme.colors.sidebar.elevated, boxShadow: "lg", minW: "10rem", maxW: "14rem", py: "0.125rem", ml: "-0.5rem", cursor: (0, menuDisabled_1.menuDisabled)(item) ? "not-allowed" : "pointer", zIndex: 1500, color: theme.colors.white, border: 'none', children: (0, jsx_runtime_1.jsx)(react_2.PopoverBody, { p: 3, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, justify: "space-between", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, flex: "1", minW: 0, children: [(0, jsx_runtime_1.jsx)(react_2.Icon, { as: item.icon, fontSize: "md", flexShrink: 0 }), (0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", maxWidth: "100%", fontSize: itemFontSize, fontWeight: "medium", as: "p", children: item.title })] }), badgeVal != null && ((0, jsx_runtime_1.jsx)(react_2.Badge, { ...softBadge(theme.colors, colorScheme, (0, sidebarAccent_1.sidebarRowPeak)(theme.colors.sidebar.elevated)), fontSize: "xs", variant: variant, borderRadius: radius, children: badgeVal }))] }) }) }) })] }));
|
|
50
51
|
};
|
|
51
52
|
const ExpandedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
|
|
52
53
|
var _a;
|
|
@@ -59,14 +60,14 @@ const ExpandedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
|
|
|
59
60
|
e.preventDefault();
|
|
60
61
|
if (!(0, menuDisabled_1.menuDisabled)(item))
|
|
61
62
|
onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick(item);
|
|
62
|
-
}, borderLeft: "2px solid", borderLeftColor: isActive ? theme.colors.sidebar.activeIcon : "transparent", transition: "background 0.12s", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, flex: "1", minW: 0, overflow: "hidden", children: [(0, jsx_runtime_1.jsx)(react_2.Icon, { as: item.icon, fontSize:
|
|
63
|
+
}, borderLeft: "2px solid", borderLeftColor: isActive ? theme.colors.sidebar.activeIcon : "transparent", transition: "background 0.12s", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, flex: "1", minW: 0, overflow: "hidden", children: [(0, jsx_runtime_1.jsx)(react_2.Icon, { as: item.icon, fontSize: sidebarScale_1.SIDEBAR_ROW.iconSize, flexShrink: 0, color: isActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), (0, jsx_runtime_1.jsx)(react_2.Box, { flex: "1", minW: 0, children: (0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", maxWidth: "100%", fontSize: itemFontSize, fontWeight: isActive ? 600 : 500, color: isActive ? activeAccent.label : theme.colors.white, _groupHover: isActive ? undefined : { color: theme.colors.white }, as: "p", children: item.title }) })] }), badgeVal != null && ((0, jsx_runtime_1.jsx)(react_2.Badge, { ...softBadge(theme.colors, colorScheme, (0, sidebarAccent_1.sidebarRowPeak)(theme.colors.sidebar.background[500])), fontSize: "xs", variant: variant, borderRadius: radius, children: badgeVal }))] }));
|
|
63
64
|
};
|
|
64
|
-
const SecondaryBar = ({ items = [], defaultCollapsed = true, collapsedWidth = "3.5rem", expandedWidth = "10rem", headerFontSize =
|
|
65
|
+
const SecondaryBar = ({ items = [], defaultCollapsed = true, collapsedWidth = "3.5rem", expandedWidth = "10rem", headerFontSize = sidebarScale_1.SIDEBAR_ROW.fontSize, itemFontSize = sidebarScale_1.SIDEBAR_ROW.fontSize, selected, onItemClick, title, icon, }) => {
|
|
65
66
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
66
67
|
const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
|
|
67
68
|
const [collapsed, setCollapsed] = (0, react_1.useState)(defaultCollapsed);
|
|
68
69
|
const width = collapsed ? collapsedWidth : expandedWidth;
|
|
69
|
-
return ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "nav", "aria-label": title ? `${title} navigation` : "Secondary navigation", transition: (0, motion_1.transitionFor)(["width"], "base"), pos: "sticky", top: 0, sx: viewportHeight_1.fullViewportHeight, w: width, bg: theme.colors.sidebar.background[500], borderLeft: "1px solid", borderColor: theme.colors.sidebar.divider, boxShadow: theme.shadows.md, zIndex: 1, children: (0, jsx_runtime_1.jsxs)(react_2.VStack, { align: "stretch", spacing: 0, h: "100%", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", justify: collapsed ? "center" : "space-between", px: collapsed ? 0 : "10px", gap: "7px", h: Sidebar_1.HEADER_HEIGHT, overflow: "hidden", borderBottom: "1px solid", borderColor: theme.colors.sidebar.divider, flexShrink: 0, children: [!collapsed && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [icon && ((0, jsx_runtime_1.jsx)(react_2.Icon, { as: icon, fontSize:
|
|
70
|
+
return ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "nav", "aria-label": title ? `${title} navigation` : "Secondary navigation", transition: (0, motion_1.transitionFor)(["width"], "base"), pos: "sticky", top: 0, sx: viewportHeight_1.fullViewportHeight, w: width, bg: theme.colors.sidebar.background[500], borderLeft: "1px solid", borderColor: theme.colors.sidebar.divider, boxShadow: theme.shadows.md, zIndex: 1, children: (0, jsx_runtime_1.jsxs)(react_2.VStack, { align: "stretch", spacing: 0, h: "100%", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", justify: collapsed ? "center" : "space-between", px: collapsed ? 0 : "10px", gap: "7px", h: Sidebar_1.HEADER_HEIGHT, overflow: "hidden", borderBottom: "1px solid", borderColor: theme.colors.sidebar.divider, flexShrink: 0, children: [!collapsed && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [icon && ((0, jsx_runtime_1.jsx)(react_2.Icon, { as: icon, fontSize: sidebarScale_1.SIDEBAR_ROW.iconSize, color: activeAccent.icon, flexShrink: 0 })), (0, jsx_runtime_1.jsx)(react_2.Box, { flex: "1", minW: 0, children: (0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", maxWidth: "100%", fontSize: headerFontSize, fontWeight: 600, color: theme.colors.white, as: "p", children: title !== null && title !== void 0 ? title : "" }) })] })), (0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", "aria-label": collapsed ? "Expand navigation panel" : "Collapse navigation panel", "aria-expanded": !collapsed, border: "none", bg: "transparent", w: "24px", h: "24px", borderRadius: "lg", display: "flex", alignItems: "center", justifyContent: "center", cursor: "pointer", flexShrink: 0, onClick: () => setCollapsed((c) => !c), _hover: { bg: "whiteAlpha.100" }, transition: "background 0.15s", children: collapsed ? ((0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: title !== null && title !== void 0 ? title : "", placement: "right", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { size: 13, color: theme.colors.sidebar.mutedIcon }) })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { size: 13, color: theme.colors.sidebar.mutedIcon })) })] }), (0, jsx_runtime_1.jsx)(react_2.Box, { id: "secondary-scroll-container", flex: "1", minH: 0, overflowY: "auto", overflowX: "hidden", py: 2, px: "6px", children: items.map((item) => {
|
|
70
71
|
var _a;
|
|
71
72
|
const isActive = String(selected) === String(item.id) ||
|
|
72
73
|
String(selected) === String(item.title);
|
|
@@ -32,6 +32,7 @@ const defaultLogo_1 = __importDefault(require("../../Assets/defaultLogo"));
|
|
|
32
32
|
const OverflowTooltipText_1 = __importDefault(require("./components/OverflowTooltipText"));
|
|
33
33
|
const SecondaryBar_1 = __importDefault(require("./SecondaryBar"));
|
|
34
34
|
const OtherApps_1 = __importDefault(require("./components/OtherApps"));
|
|
35
|
+
const sidebarScale_1 = require("./sidebarScale");
|
|
35
36
|
const viewportHeight_1 = require("../../Theme/tokens/builders/viewportHeight");
|
|
36
37
|
const SidebarHeader = ({ logo, companyName, companySubtitle, toggle, isLoading, onToggle, overlay, onClose, }) => {
|
|
37
38
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
@@ -41,7 +42,7 @@ const SidebarHeader = ({ logo, companyName, companySubtitle, toggle, isLoading,
|
|
|
41
42
|
const primaryFillRung = (0, filledSurface_1.solidFillRung)(theme.colors.primary, theme.colors.white);
|
|
42
43
|
const primaryFill = theme.colors.primary[primaryFillRung];
|
|
43
44
|
const logoNode = logo ? ((0, jsx_runtime_1.jsx)(react_2.Image, { borderRadius: "lg", boxSize: "1.75rem", src: logo, alt: "Company Logo", flexShrink: 0, cursor: toggle ? "pointer" : undefined, onClick: toggle ? onToggle : undefined })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { bg: primaryFill, color: (0, filledSurface_1.labelOnFill)(primaryFill, theme.colors.white, theme.colors.black), borderRadius: "lg", boxSize: "1.75rem", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: "bold", flexShrink: 0, cursor: toggle ? "pointer" : undefined, onClick: toggle ? onToggle : undefined, children: (0, jsx_runtime_1.jsx)(defaultLogo_1.default, {}) }));
|
|
44
|
-
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { h: Sidebar_1.HEADER_HEIGHT, w: "100%", alignItems: "center", justifyContent: toggle ? "center" : "flex-start", gap: 2, px: toggle ? "8px" : "10px", borderBottom: "1px solid", borderColor: theme.colors.sidebar.divider, minW: 0, overflow: "hidden", flexShrink: 0, children: [logoNode, !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, children: [(0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", fontWeight: 600, fontSize:
|
|
45
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { h: Sidebar_1.HEADER_HEIGHT, w: "100%", alignItems: "center", justifyContent: toggle ? "center" : "flex-start", gap: 2, px: toggle ? "8px" : "10px", borderBottom: "1px solid", borderColor: theme.colors.sidebar.divider, minW: 0, overflow: "hidden", flexShrink: 0, children: [logoNode, !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, children: [(0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", fontWeight: 600, fontSize: sidebarScale_1.SIDEBAR_CHROME.titleFontSize, textAlign: "left", color: theme.colors.white, lineHeight: "1.3", as: "p", width: "100%", children: companyName !== null && companyName !== void 0 ? companyName : "" }), companySubtitle && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: sidebarScale_1.SIDEBAR_CHROME.metaFontSize, color: theme.colors.sidebar.mutedLabel, lineHeight: "1.3", isTruncated: true, children: companySubtitle }))] })), !toggle && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", onClick: overlay ? onClose : onToggle, "aria-label": overlay ? "Close menu" : "Collapse sidebar", w: "22px", h: "22px", borderRadius: "lg", bg: "whiteAlpha.100", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, position: "relative", _hover: { bg: "whiteAlpha.300" }, transition: "background 0.15s", sx: {
|
|
45
46
|
"&::after": {
|
|
46
47
|
content: '""',
|
|
47
48
|
position: "absolute",
|
|
@@ -60,7 +61,7 @@ const SkeletonMenuRow = ({ toggle }) => {
|
|
|
60
61
|
const AddNewButton = ({ toggle, onClick, overlay }) => {
|
|
61
62
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
62
63
|
const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
|
|
63
|
-
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", "data-group": "", "aria-label": "Add New", alignItems: "center", gap: "9px", px: "10px", py: overlay ? "11px" : "7px", borderRadius: "lg", cursor: "pointer", border: "none", bg: "transparent", w: "100%", mb: "2px", justifyContent: toggle ? "center" : "flex-start", _hover: { backgroundColor: "whiteAlpha.100" }, transition: "background 0.12s", onClick: onClick, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { w: "18px", h: "18px", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 16, color: activeAccent.icon }) }), !toggle && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize:
|
|
64
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", "data-group": "", "aria-label": "Add New", alignItems: "center", gap: "9px", px: "10px", py: overlay ? "11px" : "7px", borderRadius: "lg", cursor: "pointer", border: "none", bg: "transparent", w: "100%", mb: "2px", justifyContent: toggle ? "center" : "flex-start", _hover: { backgroundColor: "whiteAlpha.100" }, transition: "background 0.12s", onClick: onClick, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { w: "18px", h: "18px", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 16, color: activeAccent.icon }) }), !toggle && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, color: theme.colors.white, fontWeight: "medium", children: "Add New" }))] }));
|
|
64
65
|
};
|
|
65
66
|
const deriveInitials = (user) => {
|
|
66
67
|
if (user.initials)
|
|
@@ -75,14 +76,14 @@ const deriveInitials = (user) => {
|
|
|
75
76
|
const UserFooter = ({ user, toggle, overlay }) => {
|
|
76
77
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
77
78
|
const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
|
|
78
|
-
const avatar = user.avatarUrl ? ((0, jsx_runtime_1.jsx)(react_2.Image, { src: user.avatarUrl, alt: user.name, boxSize: "26px", borderRadius: "full", objectFit: "cover", flexShrink: 0 })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { boxSize: "26px", borderRadius: "full", bg: theme.colors.primary.opacity[32], color: activeAccent.label, display: "flex", alignItems: "center", justifyContent: "center", fontSize:
|
|
79
|
-
return ((0, jsx_runtime_1.jsx)(react_2.Box, { borderTop: "1px solid", borderColor: theme.colors.sidebar.divider, py: 2, px: "6px", flexShrink: 0, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", onClick: user.onClick, align: "center", gap: 2, px: 2, py: overlay ? "10px" : "6px", w: "100%", borderRadius: "lg", cursor: "pointer", bg: "transparent", border: "none", justify: toggle ? "center" : "flex-start", _hover: { bg: "whiteAlpha.100" }, transition: "background 0.12s", children: [avatar, !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, textAlign: "left", children: [(0, jsx_runtime_1.jsx)(react_2.Text, { fontSize:
|
|
79
|
+
const avatar = user.avatarUrl ? ((0, jsx_runtime_1.jsx)(react_2.Image, { src: user.avatarUrl, alt: user.name, boxSize: "26px", borderRadius: "full", objectFit: "cover", flexShrink: 0 })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { boxSize: "26px", borderRadius: "full", bg: theme.colors.primary.opacity[32], color: activeAccent.label, display: "flex", alignItems: "center", justifyContent: "center", fontSize: sidebarScale_1.SIDEBAR_CHROME.metaFontSize, fontWeight: 600, flexShrink: 0, children: deriveInitials(user) }));
|
|
80
|
+
return ((0, jsx_runtime_1.jsx)(react_2.Box, { borderTop: "1px solid", borderColor: theme.colors.sidebar.divider, py: 2, px: "6px", flexShrink: 0, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", onClick: user.onClick, align: "center", gap: 2, px: 2, py: overlay ? "10px" : "6px", w: "100%", borderRadius: "lg", cursor: "pointer", bg: "transparent", border: "none", justify: toggle ? "center" : "flex-start", _hover: { bg: "whiteAlpha.100" }, transition: "background 0.12s", children: [avatar, !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, textAlign: "left", children: [(0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: sidebarScale_1.SIDEBAR_CHROME.labelFontSize, fontWeight: 500, color: theme.colors.white, isTruncated: true, children: user.name }), user.role && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: sidebarScale_1.SIDEBAR_CHROME.metaFontSize, color: theme.colors.sidebar.mutedLabel, isTruncated: true, children: user.role }))] })), !toggle && (0, jsx_runtime_1.jsx)(lucide_react_1.MoreVertical, { size: 14, color: theme.colors.sidebar.mutedIcon })] }) }));
|
|
80
81
|
};
|
|
81
82
|
// Footer "cell" — one segment of the Collapse | Hide/Show control.
|
|
82
83
|
const ControlCell = ({ onClick, ariaLabel, label, accent, children }) => {
|
|
83
84
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
84
85
|
const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
|
|
85
|
-
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", "aria-label": ariaLabel, flex: "1", minW: 0, alignItems: "center", justifyContent: "center", gap: "7px", px: "10px", py: "14px", cursor: "pointer", border: "none", bg: accent ? "whiteAlpha.300" : "transparent", onClick: onClick, _hover: { bg: accent ? "whiteAlpha.400" : "whiteAlpha.200" }, transition: "background 0.15s", children: [children, label && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize:
|
|
86
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", "aria-label": ariaLabel, flex: "1", minW: 0, alignItems: "center", justifyContent: "center", gap: "7px", px: "10px", py: "14px", cursor: "pointer", border: "none", bg: accent ? "whiteAlpha.300" : "transparent", onClick: onClick, _hover: { bg: accent ? "whiteAlpha.400" : "whiteAlpha.200" }, transition: "background 0.15s", children: [children, label && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: sidebarScale_1.SIDEBAR_CHROME.labelFontSize, color: accent ? activeAccent.label : theme.colors.sidebar.mutedLabel, fontWeight: "medium", children: label }))] }));
|
|
86
87
|
};
|
|
87
88
|
// Collapse (mini-rail) sits next to the Hide/Show navbar-mode toggle. In the
|
|
88
89
|
// desktop mobile-nav overlay only "Show" (return to the docked sidebar) is shown;
|
|
@@ -100,7 +100,9 @@ export type SecondaryBarProps = {
|
|
|
100
100
|
collapsedWidth?: string | number;
|
|
101
101
|
/** Defaults to "10rem". */
|
|
102
102
|
expandedWidth?: string | number;
|
|
103
|
+
/** Drill-down title size. Defaults to the shared sidebar row size (13px). */
|
|
103
104
|
headerFontSize?: string;
|
|
105
|
+
/** Row label size. Defaults to the shared sidebar row size (13px). */
|
|
104
106
|
itemFontSize?: string;
|
|
105
107
|
/** Matched by string equality against either the item's id or title, whichever matches. */
|
|
106
108
|
selected?: string | number | null;
|
|
@@ -16,6 +16,7 @@ const sidebarAccent_1 = require("../../../Theme/tokens/builders/sidebarAccent");
|
|
|
16
16
|
const paletteFromTheme_1 = require("../../../Theme/chakra/paletteFromTheme");
|
|
17
17
|
const TextTruncation_1 = __importDefault(require("./TextTruncation"));
|
|
18
18
|
const sidebarId_1 = require("../sidebarId");
|
|
19
|
+
const sidebarScale_1 = require("../sidebarScale");
|
|
19
20
|
/**
|
|
20
21
|
* These rows are real `<a href>`s now, so the browser's own gestures have to keep working —
|
|
21
22
|
* cmd/ctrl-click for a new tab, shift for a window, middle-click. Only a plain left click is
|
|
@@ -34,7 +35,7 @@ const MenuItemBox = ({ menu, activeMenu, toggle, handleClick, isOpen, onToggle,
|
|
|
34
35
|
const isBlocked = (0, menuDisabled_1.menuDisabled)(menu) || locked;
|
|
35
36
|
const hasSubMenu = !!(subMenu === null || subMenu === void 0 ? void 0 : subMenu.length);
|
|
36
37
|
const submenuPanelId = `submenu-${reactId}`;
|
|
37
|
-
const rowHeight = overlay ?
|
|
38
|
+
const rowHeight = overlay ? sidebarScale_1.SIDEBAR_ROW.overlayHeight : sidebarScale_1.SIDEBAR_ROW.height;
|
|
38
39
|
// A submenu parent only expands, so it is a button; every other row navigates.
|
|
39
40
|
// Cast: Chakra narrows `as` unions to their *shared* props, which drops `href`.
|
|
40
41
|
const rowAs = (hasSubMenu ? "button" : "a");
|
|
@@ -94,7 +95,7 @@ const MenuItemBox = ({ menu, activeMenu, toggle, handleClick, isOpen, onToggle,
|
|
|
94
95
|
// open={isOpen}
|
|
95
96
|
, {
|
|
96
97
|
// open={isOpen}
|
|
97
|
-
fontSize:
|
|
98
|
+
fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, lineHeight: "1", flex: "1", color: isAnyActive ? activeAccent.label : theme.colors.white, fontWeight: isAnyActive ? 600 : 500, _groupHover: isAnyActive ? undefined : { color: theme.colors.white }, children: title }))] }), !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: "0.375rem", children: [(() => {
|
|
98
99
|
var _a, _b, _c;
|
|
99
100
|
const value = badgeValue;
|
|
100
101
|
if (value == null)
|
|
@@ -127,13 +128,13 @@ const MenuItemBox = ({ menu, activeMenu, toggle, handleClick, isOpen, onToggle,
|
|
|
127
128
|
var _a, _b, _c;
|
|
128
129
|
const isSubActive = activeMenu === sub.id;
|
|
129
130
|
const isSubBlocked = (0, menuDisabled_1.menuDisabled)(sub) || sub.locked;
|
|
130
|
-
return ((0, jsx_runtime_1.jsxs)(react_2.Box, { as: "a", href: (_a = sub.url) !== null && _a !== void 0 ? _a : "#", "data-group": "", "aria-current": isSubActive ? "page" : undefined, "aria-disabled": isSubBlocked ? true : undefined, textDecoration: "none", h:
|
|
131
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Box, { as: "a", href: (_a = sub.url) !== null && _a !== void 0 ? _a : "#", "data-group": "", "aria-current": isSubActive ? "page" : undefined, "aria-disabled": isSubBlocked ? true : undefined, textDecoration: "none", h: sidebarScale_1.SIDEBAR_ROW.subHeight, pl: "30px", pr: "10px", borderRadius: "lg", fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, backgroundColor: "transparent", _hover: { backgroundColor: "whiteAlpha.100" }, opacity: isSubBlocked ? 0.6 : 1, cursor: isSubBlocked ? "not-allowed" : "pointer", pointerEvents: isSubBlocked ? "none" : "auto", onClick: (e) => {
|
|
131
132
|
if (sub.url && isBrowserNavigationGesture(e))
|
|
132
133
|
return;
|
|
133
134
|
e.preventDefault();
|
|
134
135
|
if (!isSubBlocked)
|
|
135
136
|
handleClick === null || handleClick === void 0 ? void 0 : handleClick(sub);
|
|
136
|
-
}, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, transition: "background 0.12s", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: "9px", overflow: "hidden", flex: "1", children: [sub.icon ? ((0, jsx_runtime_1.jsx)(react_2.Icon, { as: sub.icon, fontSize:
|
|
137
|
+
}, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, transition: "background 0.12s", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: "9px", overflow: "hidden", flex: "1", children: [sub.icon ? ((0, jsx_runtime_1.jsx)(react_2.Icon, { as: sub.icon, fontSize: sidebarScale_1.SIDEBAR_ROW.iconSize, flexShrink: 0, color: isSubActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { w: "5px", h: "5px", borderRadius: "full", flexShrink: 0, bg: isSubActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isSubActive ? undefined : { bg: theme.colors.white }, transition: "background 0.12s" })), (0, jsx_runtime_1.jsx)(TextTruncation_1.default, { fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, fontWeight: isSubActive ? 600 : 500, lineHeight: "1",
|
|
137
138
|
// open={isOpen}
|
|
138
139
|
color: isSubActive ? theme.colors.white : theme.colors.sidebar.mutedLabel, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, children: sub.title })] }), sub.locked ? ((0, jsx_runtime_1.jsx)(react_2.Icon, { as: lucide_react_1.LockKeyhole, fontSize: "md", color: theme.colors.sidebar.mutedIcon })) : (() => {
|
|
139
140
|
var _a, _b, _c, _d;
|
|
@@ -148,7 +148,7 @@ const MenuItems = ({ menus, activeMenu, handleMenuClick, toggle, selectedSubMenu
|
|
|
148
148
|
lastGroup = menu.group;
|
|
149
149
|
groupCount += 1;
|
|
150
150
|
}
|
|
151
|
-
return ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [showGroup && !isFirstGroup && ((0, jsx_runtime_1.jsx)(react_2.Box, { h: "1px", bg: theme.colors.sidebar.divider, mx: 2, my: "5px" })), showGroup && !toggle && ((0, jsx_runtime_1.jsx)(react_2.Box, { "aria-hidden": "true", px: "10px", pt: "10px", pb: "3px", fontSize: "9.5px", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.1em", color: theme.colors.sidebar.mutedLabel, whiteSpace: "nowrap", overflow: "hidden", children: menu.group })), (0, jsx_runtime_1.jsx)(MenuItemBox_1.default, { menu: menu, activeMenu: activeMenu, toggle: toggle, handleClick: handleMenuClick, selectedSubMenu: selectedSubMenu, isOpen: openMenuId === menu.id, onToggle: handleToggle, overlay: overlay })] }, `${String((_c = (_b = (_a = menu.id) !== null && _a !== void 0 ? _a : menu.url) !== null && _b !== void 0 ? _b : menu.title) !== null && _c !== void 0 ? _c : idx)}-${idx}`));
|
|
151
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [showGroup && !isFirstGroup && ((0, jsx_runtime_1.jsx)(react_2.Box, { h: "1px", bg: theme.colors.sidebar.divider, mx: 2, my: overlay ? "3px" : "5px" })), showGroup && !toggle && ((0, jsx_runtime_1.jsx)(react_2.Box, { "aria-hidden": "true", px: "10px", pt: overlay ? "6px" : "10px", pb: "3px", fontSize: "9.5px", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.1em", color: theme.colors.sidebar.mutedLabel, whiteSpace: "nowrap", overflow: "hidden", children: menu.group })), (0, jsx_runtime_1.jsx)(MenuItemBox_1.default, { menu: menu, activeMenu: activeMenu, toggle: toggle, handleClick: handleMenuClick, selectedSubMenu: selectedSubMenu, isOpen: openMenuId === menu.id, onToggle: handleToggle, overlay: overlay })] }, `${String((_c = (_b = (_a = menu.id) !== null && _a !== void 0 ? _a : menu.url) !== null && _b !== void 0 ? _b : menu.title) !== null && _c !== void 0 ? _c : idx)}-${idx}`));
|
|
152
152
|
}) }));
|
|
153
153
|
};
|
|
154
154
|
exports.default = MenuItems;
|
|
@@ -13,6 +13,7 @@ const tone_1 = require("../../../Theme/tokens/builders/tone");
|
|
|
13
13
|
const sidebarAccent_1 = require("../../../Theme/tokens/builders/sidebarAccent");
|
|
14
14
|
const paletteFromTheme_1 = require("../../../Theme/chakra/paletteFromTheme");
|
|
15
15
|
const TextTruncation_1 = __importDefault(require("./TextTruncation"));
|
|
16
|
+
const sidebarScale_1 = require("../sidebarScale");
|
|
16
17
|
const MenuPopoverContent = ({ menu, handleMenuClick, activeMenu, }) => {
|
|
17
18
|
var _a;
|
|
18
19
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
@@ -27,7 +28,7 @@ const MenuPopoverContent = ({ menu, handleMenuClick, activeMenu, }) => {
|
|
|
27
28
|
if (!isBlocked)
|
|
28
29
|
handleMenuClick === null || handleMenuClick === void 0 ? void 0 : handleMenuClick(menu);
|
|
29
30
|
}
|
|
30
|
-
}, cursor: !hasSubMenu ? (isBlocked ? "not-allowed" : "pointer") : "default", "aria-disabled": !hasSubMenu && isBlocked ? true : undefined, children: [(0, jsx_runtime_1.jsx)(react_1.Icon, { as: icon, fontSize: "md", flexShrink: 0, color: !hasSubMenu && isParentActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon }), (0, jsx_runtime_1.jsx)(TextTruncation_1.default, { fontWeight: 600, fontSize:
|
|
31
|
+
}, cursor: !hasSubMenu ? (isBlocked ? "not-allowed" : "pointer") : "default", "aria-disabled": !hasSubMenu && isBlocked ? true : undefined, children: [(0, jsx_runtime_1.jsx)(react_1.Icon, { as: icon, fontSize: "md", flexShrink: 0, color: !hasSubMenu && isParentActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon }), (0, jsx_runtime_1.jsx)(TextTruncation_1.default, { fontWeight: 600, fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, flex: "1", color: theme.colors.white, children: title }), (() => {
|
|
31
32
|
var _a, _b, _c, _d;
|
|
32
33
|
const cfg = typeof badge === "object" && badge !== null
|
|
33
34
|
? badge
|
|
@@ -48,10 +49,10 @@ const MenuPopoverContent = ({ menu, handleMenuClick, activeMenu, }) => {
|
|
|
48
49
|
e.preventDefault();
|
|
49
50
|
if (!isSubBlocked)
|
|
50
51
|
handleMenuClick === null || handleMenuClick === void 0 ? void 0 : handleMenuClick(sub);
|
|
51
|
-
}, px: 2, h:
|
|
52
|
+
}, px: 2, h: sidebarScale_1.SIDEBAR_ROW.subHeight, mb: "2px", borderRadius: "lg", align: "center", justify: "space-between", gap: 2, borderLeft: "2px solid", borderLeftColor: isSubActive ? theme.colors.sidebar.activeIcon : "transparent", bg: isSubActive ? "whiteAlpha.300" : "transparent", _hover: {
|
|
52
53
|
bg: !isSubBlocked ? "whiteAlpha.100" : "transparent",
|
|
53
54
|
cursor: !isSubBlocked ? "pointer" : "not-allowed",
|
|
54
|
-
}, opacity: isSubBlocked ? 0.5 : 1, pointerEvents: isSubBlocked ? "none" : "auto", transition: "background 0.12s", children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { align: "center", gap: "9px", overflow: "hidden", flex: "1", children: [(0, jsx_runtime_1.jsx)(react_1.Icon, { as: sub.icon, fontSize:
|
|
55
|
+
}, opacity: isSubBlocked ? 0.5 : 1, pointerEvents: isSubBlocked ? "none" : "auto", transition: "background 0.12s", children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { align: "center", gap: "9px", overflow: "hidden", flex: "1", children: [(0, jsx_runtime_1.jsx)(react_1.Icon, { as: sub.icon, fontSize: sidebarScale_1.SIDEBAR_ROW.iconSize, flexShrink: 0, color: isSubActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), (0, jsx_runtime_1.jsx)(TextTruncation_1.default, { fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, fontWeight: isSubActive ? 600 : 500, flex: 1, color: isSubActive ? activeAccent.label : theme.colors.white, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, children: sub.title })] }), sub.locked ? ((0, jsx_runtime_1.jsx)(react_1.Icon, { as: lucide_react_1.LockKeyhole, fontSize: "md", color: theme.colors.sidebar.mutedIcon })) : (() => {
|
|
55
56
|
var _a, _b, _c, _d;
|
|
56
57
|
const cfg = typeof sub.badge === "object" && sub.badge !== null
|
|
57
58
|
? sub.badge
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** One type and row scale for the whole sidebar — rail, submenu, flyout, secondary bar and chrome. */
|
|
2
|
+
export declare const SIDEBAR_ROW: {
|
|
3
|
+
readonly height: "32px";
|
|
4
|
+
/** Rail row in the mobile overlay — the WCAG 2.5.5 touch target. */
|
|
5
|
+
readonly overlayHeight: "44px";
|
|
6
|
+
readonly subHeight: "28px";
|
|
7
|
+
readonly fontSize: "13px";
|
|
8
|
+
readonly iconSize: "1rem";
|
|
9
|
+
};
|
|
10
|
+
/** Header/footer text around the rows; every row itself uses SIDEBAR_ROW.fontSize. */
|
|
11
|
+
export declare const SIDEBAR_CHROME: {
|
|
12
|
+
readonly titleFontSize: "12.5px";
|
|
13
|
+
readonly labelFontSize: "11.5px";
|
|
14
|
+
readonly metaFontSize: "10px";
|
|
15
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SIDEBAR_CHROME = exports.SIDEBAR_ROW = void 0;
|
|
4
|
+
/** One type and row scale for the whole sidebar — rail, submenu, flyout, secondary bar and chrome. */
|
|
5
|
+
exports.SIDEBAR_ROW = {
|
|
6
|
+
height: "32px",
|
|
7
|
+
/** Rail row in the mobile overlay — the WCAG 2.5.5 touch target. */
|
|
8
|
+
overlayHeight: "44px",
|
|
9
|
+
subHeight: "28px",
|
|
10
|
+
fontSize: "13px",
|
|
11
|
+
iconSize: "1rem",
|
|
12
|
+
};
|
|
13
|
+
/** Header/footer text around the rows; every row itself uses SIDEBAR_ROW.fontSize. */
|
|
14
|
+
exports.SIDEBAR_CHROME = {
|
|
15
|
+
titleFontSize: "12.5px",
|
|
16
|
+
labelFontSize: "11.5px",
|
|
17
|
+
metaFontSize: "10px",
|
|
18
|
+
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { SwitchProps } from "./SwitchProps";
|
|
2
|
-
/** @deprecated Use `SegmentedControl` — Switch
|
|
3
|
-
export default function Switch({ leftText, rightText, leftIcon, rightIcon, onSwitchToggle, switchActive, "aria-label": ariaLabel, }: SwitchProps): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
/** @deprecated Use `SegmentedControl` — Switch renders it at 12.5rem, growing when the labels need it. */
|
|
3
|
+
export default function Switch({ leftText, rightText, leftIcon, rightIcon, onSwitchToggle, switchActive, surface, "aria-label": ariaLabel, }: SwitchProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -7,11 +7,11 @@ exports.default = Switch;
|
|
|
7
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
8
|
const react_1 = require("@chakra-ui/react");
|
|
9
9
|
const SegmentedControl_1 = __importDefault(require("../SegmentedControl/SegmentedControl"));
|
|
10
|
-
/** @deprecated Use `SegmentedControl` — Switch
|
|
11
|
-
function Switch({ leftText, rightText, leftIcon, rightIcon, onSwitchToggle, switchActive, "aria-label": ariaLabel, }) {
|
|
10
|
+
/** @deprecated Use `SegmentedControl` — Switch renders it at 12.5rem, growing when the labels need it. */
|
|
11
|
+
function Switch({ leftText, rightText, leftIcon, rightIcon, onSwitchToggle, switchActive, surface, "aria-label": ariaLabel, }) {
|
|
12
12
|
const options = [
|
|
13
13
|
{ value: "left", label: leftText, icon: leftIcon },
|
|
14
14
|
{ value: "right", label: rightText, icon: rightIcon },
|
|
15
15
|
];
|
|
16
|
-
return ((0, jsx_runtime_1.jsx)(react_1.Box, { w: "12.5rem", children: (0, jsx_runtime_1.jsx)(SegmentedControl_1.default, { options: options, value: switchActive, onChange: onSwitchToggle, variant: "brandSlide", isFullWidth: true, "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : `${leftText} or ${rightText}` }) }));
|
|
16
|
+
return ((0, jsx_runtime_1.jsx)(react_1.Box, { w: "fit-content", minW: "12.5rem", children: (0, jsx_runtime_1.jsx)(SegmentedControl_1.default, { options: options, value: switchActive, onChange: onSwitchToggle, variant: "brandSlide", surface: surface, isFullWidth: true, "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : `${leftText} or ${rightText}` }) }));
|
|
17
17
|
}
|
|
@@ -8,6 +8,8 @@ export type SwitchProps = {
|
|
|
8
8
|
onSwitchToggle: (value: "left" | "right") => void;
|
|
9
9
|
/** Controlled selected side; the pill only moves when this changes. */
|
|
10
10
|
switchActive: "left" | "right";
|
|
11
|
+
/** Background this sits on. Optional: the track is opaque on any backdrop; pass it only to aim the plate's hairline edge at the real backdrop. */
|
|
12
|
+
surface?: string;
|
|
11
13
|
/** Names the radiogroup; pass it, as there is no visible group label. */
|
|
12
14
|
"aria-label"?: string;
|
|
13
15
|
};
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { TableProps } from "../TableProps";
|
|
3
3
|
type PaginationProps = Pick<TableProps, "paginationSelectOptions"> & {
|
|
4
4
|
paginationText: string;
|
|
5
|
-
handlePageSizeChange: (
|
|
5
|
+
handlePageSizeChange: (size: number) => void;
|
|
6
6
|
rowsPerPage: number;
|
|
7
7
|
currentPage: number;
|
|
8
8
|
pages: number;
|