pixelize-design-library 2.4.2-beta.52 → 2.4.2-beta.54
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 +36 -0
- package/COMPONENT-GOTCHAS.md +36 -2
- package/dist/Components/Input/PhoneNumberInput.js +1 -1
- package/dist/Components/Input/PhoneNumberInputProps.d.ts +1 -0
- package/dist/Components/SideBar/SecondaryBar.js +4 -2
- package/dist/Components/SideBar/SideBar.js +14 -8
- package/dist/Components/SideBar/components/MenuItemBox.js +9 -5
- package/dist/Components/SideBar/components/MenuPopoverContent.js +5 -3
- package/dist/Components/SideBar/components/OtherApps.js +1 -1
- package/dist/Components/Table/Table.js +16 -4
- package/dist/Components/Table/TableProps.d.ts +1 -1
- package/dist/Components/Table/components/rowMetrics.d.ts +1 -0
- package/dist/Components/Table/components/rowMetrics.js +2 -1
- package/dist/Constants/Sidebar.js +3 -3
- package/dist/Theme/tokens/builders/sidebarAccent.js +4 -2
- package/dist/esm/Components/Input/PhoneNumberInput.js +1 -1
- package/dist/esm/Components/SideBar/SecondaryBar.js +6 -4
- package/dist/esm/Components/SideBar/SideBar.js +14 -8
- package/dist/esm/Components/SideBar/components/MenuItemBox.js +9 -5
- package/dist/esm/Components/SideBar/components/MenuPopoverContent.js +6 -4
- package/dist/esm/Components/SideBar/components/OtherApps.js +1 -1
- package/dist/esm/Components/Table/Table.js +17 -5
- package/dist/esm/Components/Table/components/rowMetrics.js +1 -0
- package/dist/esm/Constants/Sidebar.js +3 -3
- package/dist/esm/Theme/tokens/builders/sidebarAccent.js +5 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -53,6 +53,7 @@ next major.
|
|
|
53
53
|
`SelectSearch`, `Search`, `Dropdown`, `SegmentedControl`, `Tabs`, `TableToggle` and the
|
|
54
54
|
`DatePicker` family all grow together and still line up side by side. `sm` is the default size,
|
|
55
55
|
so most call sites gain 6px of height without passing anything.
|
|
56
|
+
- **`PhoneNumberInput` defaults to `size="sm"`, not `md`.** It was the one field still defaulting to `md`, so in a form it stood 4px taller than the `TextInput`s around it. Pass `size="md"` to keep the old height.
|
|
56
57
|
- **Option rows follow the scale: 24/30/34/40px → 26/32/36/40px** in `Select`, `SelectV2`,
|
|
57
58
|
`SearchSelect`, `SelectSearch`, `Dropdown`, table filter selects and Chakra `MenuItem` — always
|
|
58
59
|
6px inside the trigger that opens them (4px at `lg`).
|
|
@@ -80,6 +81,41 @@ next major.
|
|
|
80
81
|
|
|
81
82
|
### Fixed
|
|
82
83
|
|
|
84
|
+
- **`SideBar`'s nav scrollbar thumb was the brand `primary` color.** Every other scrollbar in the
|
|
85
|
+
library reads a neutral chrome token; the sidebar's hand-rolled CSS (`Constants/Sidebar.ts`) was
|
|
86
|
+
the one place still reaching for `primary[500]`/`primary[700]`. It now reads
|
|
87
|
+
`sidebar.mutedIcon`/`mutedLabel` — contrast-resolved against the rail, not brand-colored.
|
|
88
|
+
- **`SideBar` follow-up UI audit — six more fixes, no behavior/prop changes.** `SecondaryBar`'s own
|
|
89
|
+
scroll panel had no scrollbar styling (fell through to the page's default) and a hardcoded,
|
|
90
|
+
collision-prone id — now matches `SideBar`'s own generated-id + `cssForScrollBar` pattern. The
|
|
91
|
+
collapsed-rail badge dot (`red[400]`) is now `sidebar.semanticText.error`, so it stays legible in
|
|
92
|
+
both modes instead of drifting. Six `whiteAlpha.100` hover/rest fills (header collapse button,
|
|
93
|
+
Add New, user footer, inline submenu row, app switcher cell, `SecondaryBar`'s collapse toggle)
|
|
94
|
+
were below the sidebar's own perceptible-step floor — bumped to `.200`, matching every other row.
|
|
95
|
+
The collapsed-flyout submenu showed Chakra's built-in "?" glyph for a sub-item with no `icon`; it
|
|
96
|
+
now draws the same dot the always-visible inline submenu already used. Hovering an *active* flyout
|
|
97
|
+
row got lighter-then-darker instead of lighter-then-lighter — fixed to the same `.300`→`.400` step
|
|
98
|
+
every other active row uses. The default (no `logo`/`avatarUrl`) header logo tile and footer
|
|
99
|
+
avatar initials painted a raw `primary` fill that measured ~1:1 against the rail — invisible — on
|
|
100
|
+
zinc, skyline and storefront; both now use the same rail-safe surface/ink pairing the active-row
|
|
101
|
+
accent already resolves against.
|
|
102
|
+
- **`SideBar` audit round 2 — muted-chrome contrast, inline-submenu consistency, demo previews.**
|
|
103
|
+
`sidebar.mutedIcon`/`mutedLabel` cleared AA against the bare rail and `elevated` but not against
|
|
104
|
+
a whiteAlpha hover/active overlay on top of either — now resolved with `settleAcross` against
|
|
105
|
+
both surfaces at once, gated by new `paletteContrast.test.ts` cases across 9 brands x 2 modes.
|
|
106
|
+
The expanded rail's always-visible inline submenu (`MenuItemBox.tsx`) now matches the
|
|
107
|
+
fill+accent-bar+`activeAccent.label` pattern the top-level row and the collapsed-flyout submenu
|
|
108
|
+
already use for an active item, instead of only swapping label color. Demo-only: the playground's
|
|
109
|
+
docked-sidebar previews (`src/Pages/demo.sidebar.tsx`) rendered blank below the `lg` breakpoint
|
|
110
|
+
because `SideBar` reads the real `window` width, not the preview box's — now shows a
|
|
111
|
+
"widen the window" fallback there instead; the secondary-bar demo's panel was also widened so its
|
|
112
|
+
drill-down chevron isn't clipped.
|
|
113
|
+
- **`Table` clipped its last row(s) whenever a cell wrapped to more than one line.** The container
|
|
114
|
+
height was computed as `rows × density height + header`, assuming every row is exactly one line —
|
|
115
|
+
wrapped text (long values, multi-column data) rendered taller than that, and the box clipped it
|
|
116
|
+
behind a scrollbar even with empty space left on the page. Tables at or under the row-count cap
|
|
117
|
+
(`maxVisibleRows`, default 10) now grow to fit their real content instead; larger lists keep the
|
|
118
|
+
exact capped/scrolling height and virtualize as before, so nothing changes for big record counts.
|
|
83
119
|
- **Icons beside a field are centred at every size and height.** A lone right-hand icon in
|
|
84
120
|
`TextInput` (an `inputRightIcon`, the clear button or the password toggle) sat flush against the
|
|
85
121
|
border while the left one was inset; both now mirror at 6/9/12/15px. `SelectSearch`'s `rightIcon`
|
package/COMPONENT-GOTCHAS.md
CHANGED
|
@@ -330,6 +330,7 @@ not enough when the overlay sits inside a transition wrapper — the wrapper kee
|
|
|
330
330
|
| `SettingsSection` | New optional `action` slot, right of the title/description on the header row — additive, nothing changes without it | — |
|
|
331
331
|
| `Button` / `Buttons` | Icon-only buttons are square. `Buttons` (plural) is themed instead of hardcoded purple | — |
|
|
332
332
|
| `ProgressBar` | Fill lifted to ≥ 3:1 on its track — green/orange/blue/cyan are visibly darker in light mode | — |
|
|
333
|
+
| `PhoneNumberInput` | Default `size` `md` → `sm`, so it matches the `TextInput`s beside it | `size="md"` |
|
|
333
334
|
| `PhoneNumberInput` / `PinInput` / `NoteTextArea` | `ref` now attaches; labels bound; PIN digits grouped and named | — |
|
|
334
335
|
| `RangeDatePicker` | Outside click keeps a fully picked range (was discarded) | — |
|
|
335
336
|
| `FilePreview` / `ContactForm` | Radius `2xl` → `xl` | — |
|
|
@@ -1410,12 +1411,45 @@ properties first, or doesn't support the pseudo-elements at all, fell back to th
|
|
|
1410
1411
|
scrollbar: a plain bar with no relation to the dark sidebar theme, showing up the moment a nav list
|
|
1411
1412
|
(enough sections/items) overflowed the viewport. Fixed by switching to the already-written
|
|
1412
1413
|
`cssForScrollBar(theme)` (same file), which sets `scrollbarWidth`/`scrollbarColor` **and** the
|
|
1413
|
-
webkit pseudo-elements, themed to `sidebar.background[500]` / `
|
|
1414
|
-
`FlexCss` is removed — `cssForScrollBar` is now the only scrollbar treatment
|
|
1414
|
+
webkit pseudo-elements, themed to `sidebar.background[500]` / `sidebar.mutedIcon`/`mutedLabel`,
|
|
1415
|
+
hidden until hover. `FlexCss` is removed — `cssForScrollBar` is now the only scrollbar treatment
|
|
1416
|
+
the SideBar uses. (2026-09-29: the thumb was briefly brand `primary[500]`/`[700]` — since fixed to
|
|
1417
|
+
the neutral tokens shown above; `SecondaryBar`'s own scroll panel got the same styling and a
|
|
1418
|
+
duplicate-id fix in the same pass.)
|
|
1415
1419
|
|
|
1416
1420
|
**Apply:** nothing to do. If a nav list is long enough to scroll, the bar now stays invisible until
|
|
1417
1421
|
hovered, in the sidebar's own colors, on every engine — not just Chromium.
|
|
1418
1422
|
|
|
1423
|
+
### `SideBar` contrast pass — badge dot, hover fills, missing-icon fallback, default avatar/logo (2026-09-29) — fixed
|
|
1424
|
+
|
|
1425
|
+
A themed-UI audit found six real defects, none of them behavior changes: the collapsed-rail
|
|
1426
|
+
notification dot (`red[400]`) is now `sidebar.semanticText.error`, which stays legible against the
|
|
1427
|
+
rail in both modes instead of drifting; six `whiteAlpha.100` hover/rest fills that sat below the
|
|
1428
|
+
sidebar's own perceptible-step floor are now `whiteAlpha.200`, matching every other row's hover;
|
|
1429
|
+
the collapsed-flyout submenu (`MenuPopoverContent`) no longer shows Chakra's built-in "?" glyph for
|
|
1430
|
+
a sub-item with no `icon` — it draws the same small dot the always-visible inline submenu already
|
|
1431
|
+
used; hovering an *active* flyout row no longer gets visibly lighter-then-darker (it now steps
|
|
1432
|
+
`.300` -> `.400`, like every other active row); and the default (no `logo`/`avatarUrl`) header logo
|
|
1433
|
+
tile and footer avatar initials no longer paint a raw `primary` fill, which was within ~1:1 of the
|
|
1434
|
+
rail — invisible — on zinc, skyline and storefront.
|
|
1435
|
+
|
|
1436
|
+
**Apply:** nothing to do — same props, same markup, visuals only. If you rendered a `SideBar` or
|
|
1437
|
+
`SecondaryBar` with a screenshot baseline captured before 2026-09-29, expect the badge dot color,
|
|
1438
|
+
some hover states, and the default logo/avatar tile to look different.
|
|
1439
|
+
|
|
1440
|
+
### `SideBar` contrast pass round 2 — muted icon/label under a hover fill, inline-submenu state (2026-09-29) — fixed
|
|
1441
|
+
|
|
1442
|
+
A follow-up audit found `sidebar.mutedIcon`/`mutedLabel` could dip under WCAG AA when sitting on
|
|
1443
|
+
top of an active or hovered row (the whiteAlpha overlay steps), even though the same token cleared
|
|
1444
|
+
AA against the bare rail — the token was never resolved against that combined surface. Also, the
|
|
1445
|
+
expanded rail's always-visible inline submenu only swapped an active row's label to white with no
|
|
1446
|
+
fill or accent bar, unlike every other active row in the family (top-level rows, the
|
|
1447
|
+
collapsed-flyout submenu). Both fixed with no prop or markup changes.
|
|
1448
|
+
|
|
1449
|
+
**Apply:** nothing to do — same props, visuals only. Expect a muted icon/label under a hover/active
|
|
1450
|
+
row to read slightly lighter than before on some brands, and an active inline-submenu item to now
|
|
1451
|
+
show a fill and left accent bar matching the rest of the sidebar's active-row styling.
|
|
1452
|
+
|
|
1419
1453
|
### `KanbanBoard`'s `permissions.isViewable: false` hides everything, including header actions
|
|
1420
1454
|
|
|
1421
1455
|
Not just the columns — the select/edit/create header bar disappears too, since the whole component
|
|
@@ -21,7 +21,7 @@ const getFlagEmoji = (countryCode) => {
|
|
|
21
21
|
const sizeToPt = { xs: 2, sm: -1, md: 2, lg: 4 };
|
|
22
22
|
const sizeToWidth = { xs: "3.5rem", sm: "3.8rem", md: "4rem", lg: "4rem" };
|
|
23
23
|
/** Country-code-aware phone field with a flag/dial-code prefix; `ref` forwards to the number `<input>`. */
|
|
24
|
-
const PhoneNumberInput = (0, react_1.forwardRef)(function PhoneNumberInput({ size = "
|
|
24
|
+
const PhoneNumberInput = (0, react_1.forwardRef)(function PhoneNumberInput({ size = "sm", value, codeValueReturn = true, country, countries, placeholder = "Enter phone number", onChange, inputId, selectId, error, errorMessage, helperText, label, id, width = "100%", isInformation, informationMessage, isRequired, onBlur, onFocus, isReadOnly, height, autoComplete, showCountrySelect = true, name, minW, maxW, countrySelectAriaLabel = "Country code", ...rest }, ref) {
|
|
25
25
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
26
26
|
const ids = (0, useFieldIds_1.useFieldIds)(inputId !== null && inputId !== void 0 ? inputId : id, { error, errorMessage, helperText });
|
|
27
27
|
const getCountryTelCode = (0, react_1.useCallback)((countryCode) => {
|
|
@@ -10,6 +10,7 @@ export type PhoneNumberInputProps = {
|
|
|
10
10
|
label?: string;
|
|
11
11
|
/** Falls back to an auto-generated id (shared with `inputId` when that's omitted too), so the label is always bound. */
|
|
12
12
|
id?: string;
|
|
13
|
+
/** Control-scale height: "xs" | "sm" | "md" | "lg" (30 / 38 / 42 / 48px). Defaults to "sm", like TextInput, so it lines up in a form. */
|
|
13
14
|
size?: string;
|
|
14
15
|
value?: string;
|
|
15
16
|
codeValueReturn?: boolean;
|
|
@@ -14,6 +14,7 @@ const lucide_react_1 = require("lucide-react");
|
|
|
14
14
|
const OverflowTooltipText_1 = __importDefault(require("./components/OverflowTooltipText"));
|
|
15
15
|
const ToolTip_1 = __importDefault(require("../ToolTip/ToolTip"));
|
|
16
16
|
const Sidebar_1 = require("../../Constants/Sidebar");
|
|
17
|
+
const sidebarId_1 = require("./sidebarId");
|
|
17
18
|
const tone_1 = require("../../Theme/tokens/builders/tone");
|
|
18
19
|
const sidebarAccent_1 = require("../../Theme/tokens/builders/sidebarAccent");
|
|
19
20
|
const paletteFromTheme_1 = require("../../Theme/chakra/paletteFromTheme");
|
|
@@ -47,7 +48,7 @@ const CollapsedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
|
|
|
47
48
|
e.preventDefault();
|
|
48
49
|
if (!(0, menuDisabled_1.menuDisabled)(item))
|
|
49
50
|
onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick(item);
|
|
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.
|
|
51
|
+
}, 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.sidebar.semanticText.error }))] }) }) }), (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 }))] }) }) }) })] }));
|
|
51
52
|
};
|
|
52
53
|
const ExpandedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
|
|
53
54
|
var _a;
|
|
@@ -65,9 +66,10 @@ const ExpandedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
|
|
|
65
66
|
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, }) => {
|
|
66
67
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
67
68
|
const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
|
|
69
|
+
const scrollContainerId = (0, sidebarId_1.sanitizeId)((0, react_1.useId)());
|
|
68
70
|
const [collapsed, setCollapsed] = (0, react_1.useState)(defaultCollapsed);
|
|
69
71
|
const width = collapsed ? collapsedWidth : expandedWidth;
|
|
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.
|
|
72
|
+
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.200" }, 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: scrollContainerId, flex: "1", minH: 0, overflowY: "auto", overflowX: "hidden", py: 2, px: "6px", sx: (0, Sidebar_1.cssForScrollBar)(theme), children: items.map((item) => {
|
|
71
73
|
var _a;
|
|
72
74
|
const isActive = String(selected) === String(item.id) ||
|
|
73
75
|
String(selected) === String(item.title);
|
|
@@ -8,7 +8,6 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
8
8
|
const react_1 = require("react");
|
|
9
9
|
const react_2 = require("@chakra-ui/react");
|
|
10
10
|
const useCustomTheme_1 = require("../../Theme/useCustomTheme");
|
|
11
|
-
const filledSurface_1 = require("../../Theme/tokens/builders/filledSurface");
|
|
12
11
|
const sidebarAccentColors_1 = require("./sidebarAccentColors");
|
|
13
12
|
const sidebarId_1 = require("./sidebarId");
|
|
14
13
|
const Sidebar_1 = require("../../Constants/Sidebar");
|
|
@@ -36,13 +35,18 @@ const sidebarScale_1 = require("./sidebarScale");
|
|
|
36
35
|
const viewportHeight_1 = require("../../Theme/tokens/builders/viewportHeight");
|
|
37
36
|
const SidebarHeader = ({ logo, companyName, companySubtitle, toggle, isLoading, onToggle, overlay, onClose, }) => {
|
|
38
37
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
38
|
+
const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
|
|
39
39
|
if (isLoading) {
|
|
40
40
|
return ((0, jsx_runtime_1.jsx)(react_2.Box, { w: "100%", px: toggle ? 2 : 4, py: 2, h: Sidebar_1.HEADER_HEIGHT, display: "flex", alignItems: "center", flexShrink: 0, children: toggle ? ((0, jsx_runtime_1.jsx)(react_2.Flex, { align: "center", gap: 4, justifyContent: "center", w: "100%", children: (0, jsx_runtime_1.jsx)(react_2.Skeleton, { w: "28px", h: "28px", borderRadius: "lg", startColor: theme.colors.sidebar.background[400], endColor: theme.colors.sidebar.background[300] }) })) : ((0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 3, w: "100%", children: [(0, jsx_runtime_1.jsx)(react_2.Skeleton, { w: "28px", h: "28px", borderRadius: "lg", startColor: theme.colors.sidebar.background[400], endColor: theme.colors.sidebar.background[300] }), (0, jsx_runtime_1.jsx)(react_2.Skeleton, { h: "1.25rem", w: "60%", borderRadius: "lg", startColor: theme.colors.sidebar.background[400], endColor: theme.colors.sidebar.background[300] })] })) }));
|
|
41
41
|
}
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
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
|
|
43
|
+
// Rail-safe pairing, not a raw primary fill: primary[500] equals the rail itself on
|
|
44
|
+
// some brands (zinc), making the tile disappear. See THEME-CONTRACT.md sidebar rules.
|
|
45
|
+
, {
|
|
46
|
+
// Rail-safe pairing, not a raw primary fill: primary[500] equals the rail itself on
|
|
47
|
+
// some brands (zinc), making the tile disappear. See THEME-CONTRACT.md sidebar rules.
|
|
48
|
+
bg: theme.colors.sidebar.activeBg, color: activeAccent.label, 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, {}) }));
|
|
49
|
+
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.200", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, position: "relative", _hover: { bg: "whiteAlpha.300" }, transition: "background 0.15s", sx: {
|
|
46
50
|
"&::after": {
|
|
47
51
|
content: '""',
|
|
48
52
|
position: "absolute",
|
|
@@ -61,7 +65,7 @@ const SkeletonMenuRow = ({ toggle }) => {
|
|
|
61
65
|
const AddNewButton = ({ toggle, onClick, overlay }) => {
|
|
62
66
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
63
67
|
const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
|
|
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.
|
|
68
|
+
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.200" }, 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" }))] }));
|
|
65
69
|
};
|
|
66
70
|
const deriveInitials = (user) => {
|
|
67
71
|
if (user.initials)
|
|
@@ -76,8 +80,10 @@ const deriveInitials = (user) => {
|
|
|
76
80
|
const UserFooter = ({ user, toggle, overlay }) => {
|
|
77
81
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
78
82
|
const activeAccent = (0, sidebarAccentColors_1.getSidebarActiveAccent)(theme.colors);
|
|
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",
|
|
80
|
-
|
|
83
|
+
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",
|
|
84
|
+
// Same rail-safe pairing as the logo tile — primary.opacity[32] was invisible on zinc/skyline.
|
|
85
|
+
bg: theme.colors.sidebar.activeBg, color: activeAccent.label, display: "flex", alignItems: "center", justifyContent: "center", fontSize: sidebarScale_1.SIDEBAR_CHROME.metaFontSize, fontWeight: 600, flexShrink: 0, children: deriveInitials(user) }));
|
|
86
|
+
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.200" }, 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 })] }) }));
|
|
81
87
|
};
|
|
82
88
|
// Footer "cell" — one segment of the Collapse | Hide/Show control.
|
|
83
89
|
const ControlCell = ({ onClick, ariaLabel, label, accent, children }) => {
|
|
@@ -91,7 +91,7 @@ const MenuItemBox = ({ menu, activeMenu, toggle, handleClick, isOpen, onToggle,
|
|
|
91
91
|
opacity: isBlocked ? 0.6 : 1,
|
|
92
92
|
transition: "background 0.12s",
|
|
93
93
|
};
|
|
94
|
-
const buttonContent = ((0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: "9px", justify: toggle ? "center" : "space-between", w: "100%", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: "9px", overflow: "hidden", 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: icon, fontSize: "md", verticalAlign: "middle", color: isAnyActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isAnyActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), toggle && (badgeValue != null || hasSubmenuBadge) && ((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.
|
|
94
|
+
const buttonContent = ((0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: "9px", justify: toggle ? "center" : "space-between", w: "100%", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: "9px", overflow: "hidden", 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: icon, fontSize: "md", verticalAlign: "middle", color: isAnyActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isAnyActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), toggle && (badgeValue != null || hasSubmenuBadge) && ((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.sidebar.semanticText.error }))] }), !toggle && ((0, jsx_runtime_1.jsx)(TextTruncation_1.default
|
|
95
95
|
// open={isOpen}
|
|
96
96
|
, {
|
|
97
97
|
// open={isOpen}
|
|
@@ -128,15 +128,19 @@ const MenuItemBox = ({ menu, activeMenu, toggle, handleClick, isOpen, onToggle,
|
|
|
128
128
|
var _a, _b, _c;
|
|
129
129
|
const isSubActive = activeMenu === sub.id;
|
|
130
130
|
const isSubBlocked = (0, menuDisabled_1.menuDisabled)(sub) || sub.locked;
|
|
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: "
|
|
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: "28px", pr: "10px", borderRadius: "lg", fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, borderLeft: "2px solid", borderLeftColor: isSubActive ? theme.colors.sidebar.activeIcon : "transparent", backgroundColor: isSubActive ? "whiteAlpha.300" : "transparent", _hover: {
|
|
132
|
+
backgroundColor: isSubBlocked
|
|
133
|
+
? "transparent"
|
|
134
|
+
: isSubActive
|
|
135
|
+
? "whiteAlpha.400"
|
|
136
|
+
: "whiteAlpha.200",
|
|
137
|
+
}, opacity: isSubBlocked ? 0.6 : 1, cursor: isSubBlocked ? "not-allowed" : "pointer", pointerEvents: isSubBlocked ? "none" : "auto", onClick: (e) => {
|
|
132
138
|
if (sub.url && isBrowserNavigationGesture(e))
|
|
133
139
|
return;
|
|
134
140
|
e.preventDefault();
|
|
135
141
|
if (!isSubBlocked)
|
|
136
142
|
handleClick === null || handleClick === void 0 ? void 0 : handleClick(sub);
|
|
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",
|
|
138
|
-
// open={isOpen}
|
|
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 })) : (() => {
|
|
143
|
+
}, 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", color: isSubActive ? activeAccent.label : 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 })) : (() => {
|
|
140
144
|
var _a, _b, _c, _d;
|
|
141
145
|
const subCfg = typeof sub.badge === "object" && sub.badge !== null
|
|
142
146
|
? sub.badge
|
|
@@ -22,7 +22,9 @@ const MenuPopoverContent = ({ menu, handleMenuClick, activeMenu, }) => {
|
|
|
22
22
|
const isBlocked = (0, menuDisabled_1.menuDisabled)(menu) || locked;
|
|
23
23
|
const hasSubMenu = !!(subMenu === null || subMenu === void 0 ? void 0 : subMenu.length);
|
|
24
24
|
const isParentActive = activeMenu === menu.id;
|
|
25
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { as: (hasSubMenu ? "div" : "a"), href: hasSubMenu ? undefined : (_a = menu.url) !== null && _a !== void 0 ? _a : "#", "aria-current": !hasSubMenu && isParentActive ? "page" : undefined, textDecoration: "none", align: "center", gap: 2, px: 2, h: "32px", mb: hasSubMenu ? "4px" : 0, borderBottom: hasSubMenu ? "1px solid" : undefined, borderColor: hasSubMenu ? theme.colors.sidebar.divider : undefined, borderRadius: hasSubMenu ? "none" : "lg", bg: !hasSubMenu && isParentActive ? "whiteAlpha.300" : "transparent", _hover: !hasSubMenu && !isBlocked
|
|
25
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { as: (hasSubMenu ? "div" : "a"), href: hasSubMenu ? undefined : (_a = menu.url) !== null && _a !== void 0 ? _a : "#", "aria-current": !hasSubMenu && isParentActive ? "page" : undefined, textDecoration: "none", align: "center", gap: 2, px: 2, h: "32px", mb: hasSubMenu ? "4px" : 0, borderBottom: hasSubMenu ? "1px solid" : undefined, borderColor: hasSubMenu ? theme.colors.sidebar.divider : undefined, borderRadius: hasSubMenu ? "none" : "lg", bg: !hasSubMenu && isParentActive ? "whiteAlpha.300" : "transparent", _hover: !hasSubMenu && !isBlocked
|
|
26
|
+
? { bg: isParentActive ? "whiteAlpha.400" : "whiteAlpha.200" }
|
|
27
|
+
: undefined, onClick: (e) => {
|
|
26
28
|
if (!hasSubMenu) {
|
|
27
29
|
e.preventDefault();
|
|
28
30
|
if (!isBlocked)
|
|
@@ -50,9 +52,9 @@ const MenuPopoverContent = ({ menu, handleMenuClick, activeMenu, }) => {
|
|
|
50
52
|
if (!isSubBlocked)
|
|
51
53
|
handleMenuClick === null || handleMenuClick === void 0 ? void 0 : handleMenuClick(sub);
|
|
52
54
|
}, 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: {
|
|
53
|
-
bg:
|
|
55
|
+
bg: isSubBlocked ? "transparent" : isSubActive ? "whiteAlpha.400" : "whiteAlpha.200",
|
|
54
56
|
cursor: !isSubBlocked ? "pointer" : "not-allowed",
|
|
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 })) : (() => {
|
|
57
|
+
}, 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: [sub.icon ? ((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)(react_1.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, 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 })) : (() => {
|
|
56
58
|
var _a, _b, _c, _d;
|
|
57
59
|
const cfg = typeof sub.badge === "object" && sub.badge !== null
|
|
58
60
|
? sub.badge
|
|
@@ -12,7 +12,7 @@ const OtherApps = ({ toggle, otherApps }) => {
|
|
|
12
12
|
return ((0, jsx_runtime_1.jsx)(react_1.Box, { display: "flex", alignItems: "center", justifyContent: "center", color: theme.colors.sidebar.mutedIcon, fontSize: "15px", flexShrink: 0, children: (_a = app.icon) !== null && _a !== void 0 ? _a : ((0, jsx_runtime_1.jsx)(react_1.Box, { w: "0.5rem", h: "0.5rem", borderRadius: "full", bg: app.color, boxShadow: `0 0 5px ${app.color}`, flexShrink: 0 })) }));
|
|
13
13
|
};
|
|
14
14
|
// Grid cell: icon on top, truncated label below (label hidden when collapsed).
|
|
15
|
-
const appCell = (app) => ((0, jsx_runtime_1.jsxs)(react_1.Flex, { as: "button", type: "button", direction: "column", align: "center", justify: "center", gap: "3px", px: "2px", py: "6px", borderRadius: "lg", cursor: "pointer", border: "none", bg: "transparent", w: "100%", _hover: { backgroundColor: "whiteAlpha.
|
|
15
|
+
const appCell = (app) => ((0, jsx_runtime_1.jsxs)(react_1.Flex, { as: "button", type: "button", direction: "column", align: "center", justify: "center", gap: "3px", px: "2px", py: "6px", borderRadius: "lg", cursor: "pointer", border: "none", bg: "transparent", w: "100%", _hover: { backgroundColor: "whiteAlpha.200" }, transition: "background 0.12s", onClick: app.onClick, children: [appIcon(app), !toggle && ((0, jsx_runtime_1.jsx)(react_1.Text, { fontSize: "9.5px", color: theme.colors.sidebar.mutedLabel, textAlign: "center", maxW: "44px", isTruncated: true, children: app.name }))] }));
|
|
16
16
|
const flyoutBody = (app) => {
|
|
17
17
|
var _a;
|
|
18
18
|
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { alignItems: "center", gap: 2, mb: 1, onClick: app.onClick, children: [(_a = app.icon) !== null && _a !== void 0 ? _a : ((0, jsx_runtime_1.jsx)(react_1.Box, { w: "0.5rem", h: "0.5rem", borderRadius: "full", bg: app.color, boxShadow: `0 0 5px ${app.color}`, flexShrink: 0 })), (0, jsx_runtime_1.jsx)(react_1.Text, { fontSize: "sm", fontWeight: 700, color: theme.colors.white, children: app.name })] }), app.description && ((0, jsx_runtime_1.jsx)(react_1.Text, { fontSize: "xs", color: theme.colors.sidebar.mutedLabel, children: app.description }))] }));
|
|
@@ -318,9 +318,21 @@ function Table({ data, columns, onSelection, isLoading, isCheckbox = false, free
|
|
|
318
318
|
rowsHeight += ((_c = renderGroups === null || renderGroups === void 0 ? void 0 : renderGroups.length) !== null && _c !== void 0 ? _c : 1) * rowMetrics_1.GROUP_HEADER_HEIGHT;
|
|
319
319
|
if (isEmptyState)
|
|
320
320
|
rowsHeight = Math.max(rowsHeight, headerHeight + rowMetrics_1.EMPTY_STATE_HEIGHT);
|
|
321
|
-
const dynamicMaxH = Math.min(
|
|
321
|
+
const dynamicMaxH = Math.min(rowMetrics_1.MAX_TABLE_HEIGHT, rowsHeight);
|
|
322
322
|
const fittedMaxH = autoFitViewport ? Math.min(dynamicMaxH, viewportAvailableH) : dynamicMaxH;
|
|
323
|
-
const
|
|
323
|
+
const formulaMaxH = typeof tableMaxHeight === "number" ? tableMaxHeight : (isCompactRows ? rowsHeight + 8 : fittedMaxH);
|
|
324
|
+
// NOTE: wrapped cell content can exceed the per-row estimate; when the row count is
|
|
325
|
+
// within the display cap (explicit maxVisibleRows, else the default 10), size naturally
|
|
326
|
+
// instead of clipping. `visibleRowsCount` isn't used here — minRows defaults to
|
|
327
|
+
// actualRows, which would make this true for any row count.
|
|
328
|
+
const rawMaxRows = typeof maxVisibleRows === "number" ? maxVisibleRows : (actualRows === 0 ? 1 : 10);
|
|
329
|
+
const showsAllRows = actualRows <= rawMaxRows;
|
|
330
|
+
const useNaturalHeight = typeof tableMaxHeight !== "number" && showsAllRows && !isTableLoading && !canInfinite &&
|
|
331
|
+
!(filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar);
|
|
332
|
+
const tableMinH = useNaturalHeight ? formulaMaxH : undefined;
|
|
333
|
+
const tableMaxH = useNaturalHeight
|
|
334
|
+
? (autoFitViewport ? viewportAvailableH : undefined)
|
|
335
|
+
: formulaMaxH;
|
|
324
336
|
const isCompactHeader = (0, react_2.useBreakpointValue)({ base: true, md: true, lg: false });
|
|
325
337
|
(0, react_1.useEffect)(() => {
|
|
326
338
|
if (!isCompactHeader) {
|
|
@@ -371,7 +383,7 @@ function Table({ data, columns, onSelection, isLoading, isCheckbox = false, free
|
|
|
371
383
|
from { transform: rotate(0deg); }
|
|
372
384
|
to { transform: rotate(360deg); }
|
|
373
385
|
}
|
|
374
|
-
` }), (0, jsx_runtime_1.jsxs)(react_2.Box, { bg: theme.colors.background[50], border: `0.063rem solid ${theme.colors.boxborder[200]}`, borderRadius: "xl", overflow: "hidden", children: [filterSidebar && filterMode === "modal" && ((0, jsx_runtime_1.jsxs)(react_2.Modal, { isOpen: isFilterModalOpen, onClose: onFilterModalClose, size: "4xl", scrollBehavior: "inside", children: [(0, jsx_runtime_1.jsx)(react_2.ModalOverlay, {}), (0, jsx_runtime_1.jsxs)(react_2.ModalContent, { bg: theme.colors.surfaceRaised, my: 0, top: "10%", position: "fixed", left: "auto", right: "auto", children: [(0, jsx_runtime_1.jsx)(react_2.ModalCloseButton, { size: "sm" }), (0, jsx_runtime_1.jsx)(react_2.ModalBody, { p: 0, children: (0, jsx_runtime_1.jsx)(LeftFilterPane_1.default, { theme: theme, sections: (_d = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.sidebarOptions) !== null && _d !== void 0 ? _d : [], selected: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.selected, onApply: (sel) => { var _a; (_a = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.onApply) === null || _a === void 0 ? void 0 : _a.call(filterSidebar, sel); onFilterModalClose(); }, onClear: () => { var _a; (_a = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.onClearAllHandler) === null || _a === void 0 ? void 0 : _a.call(filterSidebar); }, isApplyLoading: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isApplyLoading, filterMode: filterMode }) })] })] })), (0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "start", children: [filterMode === "sidebar" && ((0, jsx_runtime_1.jsx)(MotionBox, { "data-testid": "filter-sidebar-pane", initial: { width: 0 }, animate: { width: (filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar) ? 180 : 0 }, transition: { type: "tween", duration: 0.5 }, overflow: "hidden", flexShrink: 0, borderRight: (filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar) ? "1px solid" : "none", borderColor: theme.colors.boxborder[200], style: { height: rowMetrics_1.TOOLBAR_HEIGHT +
|
|
386
|
+
` }), (0, jsx_runtime_1.jsxs)(react_2.Box, { bg: theme.colors.background[50], border: `0.063rem solid ${theme.colors.boxborder[200]}`, borderRadius: "xl", overflow: "hidden", children: [filterSidebar && filterMode === "modal" && ((0, jsx_runtime_1.jsxs)(react_2.Modal, { isOpen: isFilterModalOpen, onClose: onFilterModalClose, size: "4xl", scrollBehavior: "inside", children: [(0, jsx_runtime_1.jsx)(react_2.ModalOverlay, {}), (0, jsx_runtime_1.jsxs)(react_2.ModalContent, { bg: theme.colors.surfaceRaised, my: 0, top: "10%", position: "fixed", left: "auto", right: "auto", children: [(0, jsx_runtime_1.jsx)(react_2.ModalCloseButton, { size: "sm" }), (0, jsx_runtime_1.jsx)(react_2.ModalBody, { p: 0, children: (0, jsx_runtime_1.jsx)(LeftFilterPane_1.default, { theme: theme, sections: (_d = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.sidebarOptions) !== null && _d !== void 0 ? _d : [], selected: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.selected, onApply: (sel) => { var _a; (_a = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.onApply) === null || _a === void 0 ? void 0 : _a.call(filterSidebar, sel); onFilterModalClose(); }, onClear: () => { var _a; (_a = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.onClearAllHandler) === null || _a === void 0 ? void 0 : _a.call(filterSidebar); }, isApplyLoading: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isApplyLoading, filterMode: filterMode }) })] })] })), (0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "start", children: [filterMode === "sidebar" && ((0, jsx_runtime_1.jsx)(MotionBox, { "data-testid": "filter-sidebar-pane", initial: { width: 0 }, animate: { width: (filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar) ? 180 : 0 }, transition: { type: "tween", duration: 0.5 }, overflow: "hidden", flexShrink: 0, borderRight: (filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar) ? "1px solid" : "none", borderColor: theme.colors.boxborder[200], style: { height: rowMetrics_1.TOOLBAR_HEIGHT + formulaMaxH }, minHeight: (filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar) ? "32rem" : "auto", children: (0, jsx_runtime_1.jsx)(LeftFilterPane_1.default, { height: rowMetrics_1.TOOLBAR_HEIGHT + formulaMaxH, theme: theme, sections: (_e = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.sidebarOptions) !== null && _e !== void 0 ? _e : [], selected: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.selected, onApply: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.onApply, onClear: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.onClearAllHandler, isApplyLoading: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isApplyLoading, filterMode: filterMode }) })), (0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, children: [(0, jsx_runtime_1.jsxs)(react_2.Box, { display: "flex", alignItems: "center", justifyContent: "space-between", px: 3, py: 0, height: `${rowMetrics_1.TOOLBAR_HEIGHT}px`, gap: 3, flexWrap: "nowrap", bg: theme.colors.background[50], borderBottom: `0.063rem solid ${theme.colors.boxborder[200]}`, children: [[
|
|
375
387
|
filterSidebar && ((0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: "Filter", placement: "top", children: (0, jsx_runtime_1.jsxs)(react_2.Box, { position: "relative", display: "inline-block", children: [(0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", "aria-label": "Filter", "aria-haspopup": filterMode === "modal" ? "dialog" : undefined, "aria-expanded": filterMode === "modal"
|
|
376
388
|
? isFilterModalOpen
|
|
377
389
|
: !!(filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar), display: "inline-flex", alignItems: "center", justifyContent: "center", p: 0, bg: "transparent", border: "none", borderRadius: "md", cursor: "pointer", onClick: filterMode === "modal" ? onFilterModalOpen : filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.filterSidebarToggle, _hover: {
|
|
@@ -407,7 +419,7 @@ function Table({ data, columns, onSelection, isLoading, isCheckbox = false, free
|
|
|
407
419
|
.filter(Boolean)
|
|
408
420
|
.flatMap((tool, i) => (i === 0 ? [tool] : [(0, jsx_runtime_1.jsx)(Divider_1.default, {}, `divider-${i}`), tool])), (0, jsx_runtime_1.jsx)(ActiveFilters_1.default, { columns: columnsList, columnsSearch: columnsSearch, setColumnsSearch: setColumnsSearch }), (0, jsx_runtime_1.jsxs)(react_2.Box, { ml: "auto", display: "flex", alignItems: "center", gap: 2, children: [groupLoadMoreActive && loadMorePosition === "top" && (groupLoadMoreCaption || canGroupLoadMore) && ((0, jsx_runtime_1.jsxs)(react_2.Box, { display: "flex", alignItems: "center", gap: 2, flex: "0 0 auto", children: [groupLoadMoreCaption && ((0, jsx_runtime_1.jsx)(react_2.Box, { fontSize: "0.75rem", color: theme.colors.text[500], whiteSpace: "nowrap", children: groupLoadMoreCaption })), canGroupLoadMore && ((0, jsx_runtime_1.jsx)(Button_1.default, { size: "xs", variant: "outline", colorScheme: "gray", isLoading: isLoadingMore, loadingText: loadMoreText, onClick: handleGroupLoadMore, label: loadMoreText }))] })), (isPagination || isServerPagination) && !isGrouped && !canInfinite && !isCompactHeader && ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(Pagination_1.default, { currentPage: currentPage, setCurrentPage: setCurrentPage, rowsPerPage: rowsPerPage, pages: pages, paginationText: tablePaginationText, handlePageSizeChange: handlePageSizeChange, dataLength: tableData.length, isServerPagination: isServerPagination, paginationSelectOptions: paginationSelectOptions }) })), (isPagination || isServerPagination) && !isGrouped && !canInfinite && isCompactHeader && ((0, jsx_runtime_1.jsxs)(react_2.Popover, { isOpen: isPaginationPopoverOpen, onClose: () => setIsPaginationPopoverOpen(false), placement: "bottom-end", children: [(0, jsx_runtime_1.jsx)(react_2.PopoverTrigger, { children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "Pagination", size: "sm", variant: "ghost", icon: (0, jsx_runtime_1.jsx)(lucide_react_1.EllipsisVertical, { size: 18 }), color: theme.colors.text[500], _hover: {
|
|
409
421
|
color: theme.colors.accentText,
|
|
410
|
-
}, onClick: () => setIsPaginationPopoverOpen((open) => !open) }) }), (0, jsx_runtime_1.jsx)(react_2.Portal, { children: (0, jsx_runtime_1.jsx)(react_2.PopoverContent, { maxW: "22rem", p: 2, zIndex: 1600, bg: theme.colors.surfaceRaised, boxShadow: "lg", children: (0, jsx_runtime_1.jsx)(react_2.PopoverBody, { p: 0, children: (0, jsx_runtime_1.jsx)(Pagination_1.default, { currentPage: currentPage, setCurrentPage: setCurrentPage, rowsPerPage: rowsPerPage, pages: pages, paginationText: tablePaginationText, handlePageSizeChange: handlePageSizeChange, dataLength: tableData.length, isServerPagination: isServerPagination, paginationSelectOptions: paginationSelectOptions }) }) }) })] }))] })] }), (0, jsx_runtime_1.jsxs)(react_2.TableContainer, { ref: tableContainerRef, position: "relative", h: isTableLoading ? tableMaxH : undefined, maxH: !isTableLoading ? tableMaxH : undefined, pb: isTableLoading ? 0 : compactScrollbarPadding, overflowY: isCompactRows ? "hidden" : "auto", overflowX: "auto", sx: {
|
|
422
|
+
}, onClick: () => setIsPaginationPopoverOpen((open) => !open) }) }), (0, jsx_runtime_1.jsx)(react_2.Portal, { children: (0, jsx_runtime_1.jsx)(react_2.PopoverContent, { maxW: "22rem", p: 2, zIndex: 1600, bg: theme.colors.surfaceRaised, boxShadow: "lg", children: (0, jsx_runtime_1.jsx)(react_2.PopoverBody, { p: 0, children: (0, jsx_runtime_1.jsx)(Pagination_1.default, { currentPage: currentPage, setCurrentPage: setCurrentPage, rowsPerPage: rowsPerPage, pages: pages, paginationText: tablePaginationText, handlePageSizeChange: handlePageSizeChange, dataLength: tableData.length, isServerPagination: isServerPagination, paginationSelectOptions: paginationSelectOptions }) }) }) })] }))] })] }), (0, jsx_runtime_1.jsxs)(react_2.TableContainer, { ref: tableContainerRef, position: "relative", h: isTableLoading ? tableMaxH : undefined, minH: !isTableLoading ? tableMinH : undefined, maxH: !isTableLoading ? tableMaxH : undefined, pb: isTableLoading ? 0 : compactScrollbarPadding, overflowY: isCompactRows ? "hidden" : "auto", overflowX: "auto", sx: {
|
|
411
423
|
...(0, scrollShadow_1.scrollShadowStyles)(theme.colors.background[50]),
|
|
412
424
|
...(0, scrollbar_1.scrollbarStyles)(theme.colors),
|
|
413
425
|
// Compact rows hide the horizontal bar until hover to keep the row height.
|
|
@@ -94,7 +94,7 @@ export type TableProps = {
|
|
|
94
94
|
tableMaxHeight?: number;
|
|
95
95
|
/** Floors the auto-computed row count used for sizing only — doesn't add rows or affect pagination. */
|
|
96
96
|
minVisibleRows?: number;
|
|
97
|
-
/**
|
|
97
|
+
/** Row count above which height is capped and scrolls; at or under it the table grows to fit every row, even wrapped ones. Ignored once tableMaxHeight is set. */
|
|
98
98
|
maxVisibleRows?: number;
|
|
99
99
|
/** Further clamps computed height to remaining viewport space below the table, recalculated on resize; ignored once tableMaxHeight is set. */
|
|
100
100
|
autoFitViewport?: boolean;
|
|
@@ -6,5 +6,6 @@ export declare const DENSITY_ROWS: Record<TableDensity, {
|
|
|
6
6
|
export declare const TOOLBAR_HEIGHT = 45;
|
|
7
7
|
export declare const GROUP_HEADER_HEIGHT = 42;
|
|
8
8
|
export declare const EMPTY_STATE_HEIGHT = 200;
|
|
9
|
+
export declare const MAX_TABLE_HEIGHT = 500;
|
|
9
10
|
export declare const rowHeightFor: (density: TableDensity | undefined) => number;
|
|
10
11
|
export declare const pxOf: (length: string) => number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.pxOf = exports.rowHeightFor = exports.EMPTY_STATE_HEIGHT = exports.GROUP_HEADER_HEIGHT = exports.TOOLBAR_HEIGHT = exports.DENSITY_ROWS = void 0;
|
|
3
|
+
exports.pxOf = exports.rowHeightFor = exports.MAX_TABLE_HEIGHT = exports.EMPTY_STATE_HEIGHT = exports.GROUP_HEADER_HEIGHT = exports.TOOLBAR_HEIGHT = exports.DENSITY_ROWS = void 0;
|
|
4
4
|
exports.DENSITY_ROWS = {
|
|
5
5
|
compact: { height: 32, py: "0.125rem" },
|
|
6
6
|
normal: { height: 40, py: "0.5rem" },
|
|
@@ -9,6 +9,7 @@ exports.DENSITY_ROWS = {
|
|
|
9
9
|
exports.TOOLBAR_HEIGHT = 45;
|
|
10
10
|
exports.GROUP_HEADER_HEIGHT = 42;
|
|
11
11
|
exports.EMPTY_STATE_HEIGHT = 200;
|
|
12
|
+
exports.MAX_TABLE_HEIGHT = 500;
|
|
12
13
|
const rowHeightFor = (density) => exports.DENSITY_ROWS[density !== null && density !== void 0 ? density : "normal"].height;
|
|
13
14
|
exports.rowHeightFor = rowHeightFor;
|
|
14
15
|
const pxOf = (length) => parseFloat(length);
|
|
@@ -15,15 +15,15 @@ const cssForScrollBar = (theme) => ({
|
|
|
15
15
|
borderRadius: "0.5rem",
|
|
16
16
|
},
|
|
17
17
|
"&:hover::-webkit-scrollbar-thumb": {
|
|
18
|
-
background: theme.colors.
|
|
18
|
+
background: theme.colors.sidebar.mutedIcon,
|
|
19
19
|
},
|
|
20
20
|
"&:hover::-webkit-scrollbar-thumb:hover": {
|
|
21
|
-
background: theme.colors.
|
|
21
|
+
background: theme.colors.sidebar.mutedLabel,
|
|
22
22
|
},
|
|
23
23
|
scrollbarWidth: "none",
|
|
24
24
|
"&:hover": {
|
|
25
25
|
scrollbarWidth: "thin",
|
|
26
|
-
scrollbarColor: `${theme.colors.
|
|
26
|
+
scrollbarColor: `${theme.colors.sidebar.mutedIcon} ${theme.colors.sidebar.background[500]}`,
|
|
27
27
|
},
|
|
28
28
|
});
|
|
29
29
|
exports.cssForScrollBar = cssForScrollBar;
|
|
@@ -25,13 +25,15 @@ exports.sidebarDivider = sidebarDivider;
|
|
|
25
25
|
const buildSidebarTokens = (background, lightPrimary, semantic) => {
|
|
26
26
|
const surface = (0, exports.sidebarActiveSurface)(background);
|
|
27
27
|
const elevated = (0, outlineRung_1.resolveHoverTint)(background[500], background[500]);
|
|
28
|
+
// Muted chrome must clear contrast on the bare rail AND the lightest row-hover overlay.
|
|
29
|
+
const rowPeak = (0, exports.sidebarRowPeak)(elevated);
|
|
28
30
|
return {
|
|
29
31
|
background,
|
|
30
32
|
elevated,
|
|
31
33
|
activeIcon: (0, outlineRung_1.liftToContrast)(lightPrimary[300], surface, outlineRung_1.AA_NON_TEXT),
|
|
32
34
|
activeLabel: (0, outlineRung_1.liftToContrast)(lightPrimary[100], surface, exports.AA_NORMAL_TEXT),
|
|
33
|
-
mutedIcon: (0, outlineRung_1.
|
|
34
|
-
mutedLabel: (0, outlineRung_1.
|
|
35
|
+
mutedIcon: (0, outlineRung_1.settleAcross)(background[300], [elevated, rowPeak], outlineRung_1.AA_NON_TEXT),
|
|
36
|
+
mutedLabel: (0, outlineRung_1.settleAcross)(background[100], [elevated, rowPeak], exports.AA_NORMAL_TEXT),
|
|
35
37
|
semanticText: (0, semanticText_1.buildSemanticText)(semantic, elevated),
|
|
36
38
|
hoverBg: (0, exports.sidebarHoverSurface)(background),
|
|
37
39
|
activeBg: surface,
|
|
@@ -16,7 +16,7 @@ const getFlagEmoji = (countryCode) => {
|
|
|
16
16
|
const sizeToPt = { xs: 2, sm: -1, md: 2, lg: 4 };
|
|
17
17
|
const sizeToWidth = { xs: "3.5rem", sm: "3.8rem", md: "4rem", lg: "4rem" };
|
|
18
18
|
/** Country-code-aware phone field with a flag/dial-code prefix; `ref` forwards to the number `<input>`. */
|
|
19
|
-
const PhoneNumberInput = forwardRef(function PhoneNumberInput({ size = "
|
|
19
|
+
const PhoneNumberInput = forwardRef(function PhoneNumberInput({ size = "sm", value, codeValueReturn = true, country, countries, placeholder = "Enter phone number", onChange, inputId, selectId, error, errorMessage, helperText, label, id, width = "100%", isInformation, informationMessage, isRequired, onBlur, onFocus, isReadOnly, height, autoComplete, showCountrySelect = true, name, minW, maxW, countrySelectAriaLabel = "Country code", ...rest }, ref) {
|
|
20
20
|
const theme = useCustomTheme();
|
|
21
21
|
const ids = useFieldIds(inputId !== null && inputId !== void 0 ? inputId : id, { error, errorMessage, helperText });
|
|
22
22
|
const getCountryTelCode = useCallback((countryCode) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from "react";
|
|
2
|
+
import { useId, useState } from "react";
|
|
3
3
|
import { Box, Flex, Icon, VStack, Badge, Popover, PopoverTrigger, PopoverContent, PopoverBody, Portal, } from "@chakra-ui/react";
|
|
4
4
|
import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
5
5
|
import { getSidebarActiveAccent } from "./sidebarAccentColors.js";
|
|
@@ -8,7 +8,8 @@ import { menuDisabled } from "./menuDisabled.js";
|
|
|
8
8
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
9
9
|
import OverflowTooltipText from "./components/OverflowTooltipText.js";
|
|
10
10
|
import ToolTip from "../ToolTip/ToolTip.js";
|
|
11
|
-
import { HEADER_HEIGHT } from "../../Constants/Sidebar.js";
|
|
11
|
+
import { cssForScrollBar, HEADER_HEIGHT } from "../../Constants/Sidebar.js";
|
|
12
|
+
import { sanitizeId } from "./sidebarId.js";
|
|
12
13
|
import { resolveSoftTone } from "../../Theme/tokens/builders/tone.js";
|
|
13
14
|
import { sidebarRowPeak } from "../../Theme/tokens/builders/sidebarAccent.js";
|
|
14
15
|
import { scaleFor } from "../../Theme/chakra/paletteFromTheme.js";
|
|
@@ -42,7 +43,7 @@ const CollapsedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
|
|
|
42
43
|
e.preventDefault();
|
|
43
44
|
if (!menuDisabled(item))
|
|
44
45
|
onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick(item);
|
|
45
|
-
}, bg: isActive ? "whiteAlpha.300" : "transparent", transition: "background 0.12s", children: _jsxs(Box, { position: "relative", display: "flex", alignItems: "center", children: [_jsx(Icon, { as: item.icon, fontSize: SIDEBAR_ROW.iconSize, color: isActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), badgeVal != null && (_jsx(Box, { position: "absolute", top: "0", right: "0", w: "0.375rem", h: "0.375rem", borderRadius: "full", bg: theme.colors.
|
|
46
|
+
}, bg: isActive ? "whiteAlpha.300" : "transparent", transition: "background 0.12s", children: _jsxs(Box, { position: "relative", display: "flex", alignItems: "center", children: [_jsx(Icon, { as: item.icon, fontSize: SIDEBAR_ROW.iconSize, color: isActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), badgeVal != null && (_jsx(Box, { position: "absolute", top: "0", right: "0", w: "0.375rem", h: "0.375rem", borderRadius: "full", bg: theme.colors.sidebar.semanticText.error }))] }) }) }), _jsx(Portal, { children: _jsx(PopoverContent, { borderRadius: "lg", bg: theme.colors.sidebar.elevated, boxShadow: "lg", minW: "10rem", maxW: "14rem", py: "0.125rem", ml: "-0.5rem", cursor: menuDisabled(item) ? "not-allowed" : "pointer", zIndex: 1500, color: theme.colors.white, border: 'none', children: _jsx(PopoverBody, { p: 3, children: _jsxs(Flex, { align: "center", gap: 2, justify: "space-between", children: [_jsxs(Flex, { align: "center", gap: 2, flex: "1", minW: 0, children: [_jsx(Icon, { as: item.icon, fontSize: "md", flexShrink: 0 }), _jsx(OverflowTooltipText, { placement: "right", maxWidth: "100%", fontSize: itemFontSize, fontWeight: "medium", as: "p", children: item.title })] }), badgeVal != null && (_jsx(Badge, { ...softBadge(theme.colors, colorScheme, sidebarRowPeak(theme.colors.sidebar.elevated)), fontSize: "xs", variant: variant, borderRadius: radius, children: badgeVal }))] }) }) }) })] }));
|
|
46
47
|
};
|
|
47
48
|
const ExpandedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
|
|
48
49
|
var _a;
|
|
@@ -60,9 +61,10 @@ const ExpandedItem = ({ item, isActive, itemFontSize, onItemClick }) => {
|
|
|
60
61
|
const SecondaryBar = ({ items = [], defaultCollapsed = true, collapsedWidth = "3.5rem", expandedWidth = "10rem", headerFontSize = SIDEBAR_ROW.fontSize, itemFontSize = SIDEBAR_ROW.fontSize, selected, onItemClick, title, icon, }) => {
|
|
61
62
|
const theme = useCustomTheme();
|
|
62
63
|
const activeAccent = getSidebarActiveAccent(theme.colors);
|
|
64
|
+
const scrollContainerId = sanitizeId(useId());
|
|
63
65
|
const [collapsed, setCollapsed] = useState(defaultCollapsed);
|
|
64
66
|
const width = collapsed ? collapsedWidth : expandedWidth;
|
|
65
|
-
return (_jsx(Box, { as: "nav", "aria-label": title ? `${title} navigation` : "Secondary navigation", transition: transitionFor(["width"], "base"), pos: "sticky", top: 0, sx: fullViewportHeight, w: width, bg: theme.colors.sidebar.background[500], borderLeft: "1px solid", borderColor: theme.colors.sidebar.divider, boxShadow: theme.shadows.md, zIndex: 1, children: _jsxs(VStack, { align: "stretch", spacing: 0, h: "100%", children: [_jsxs(Flex, { align: "center", justify: collapsed ? "center" : "space-between", px: collapsed ? 0 : "10px", gap: "7px", h: HEADER_HEIGHT, overflow: "hidden", borderBottom: "1px solid", borderColor: theme.colors.sidebar.divider, flexShrink: 0, children: [!collapsed && (_jsxs(_Fragment, { children: [icon && (_jsx(Icon, { as: icon, fontSize: SIDEBAR_ROW.iconSize, color: activeAccent.icon, flexShrink: 0 })), _jsx(Box, { flex: "1", minW: 0, children: _jsx(OverflowTooltipText, { placement: "right", maxWidth: "100%", fontSize: headerFontSize, fontWeight: 600, color: theme.colors.white, as: "p", children: title !== null && title !== void 0 ? title : "" }) })] })), _jsx(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.
|
|
67
|
+
return (_jsx(Box, { as: "nav", "aria-label": title ? `${title} navigation` : "Secondary navigation", transition: transitionFor(["width"], "base"), pos: "sticky", top: 0, sx: fullViewportHeight, w: width, bg: theme.colors.sidebar.background[500], borderLeft: "1px solid", borderColor: theme.colors.sidebar.divider, boxShadow: theme.shadows.md, zIndex: 1, children: _jsxs(VStack, { align: "stretch", spacing: 0, h: "100%", children: [_jsxs(Flex, { align: "center", justify: collapsed ? "center" : "space-between", px: collapsed ? 0 : "10px", gap: "7px", h: HEADER_HEIGHT, overflow: "hidden", borderBottom: "1px solid", borderColor: theme.colors.sidebar.divider, flexShrink: 0, children: [!collapsed && (_jsxs(_Fragment, { children: [icon && (_jsx(Icon, { as: icon, fontSize: SIDEBAR_ROW.iconSize, color: activeAccent.icon, flexShrink: 0 })), _jsx(Box, { flex: "1", minW: 0, children: _jsx(OverflowTooltipText, { placement: "right", maxWidth: "100%", fontSize: headerFontSize, fontWeight: 600, color: theme.colors.white, as: "p", children: title !== null && title !== void 0 ? title : "" }) })] })), _jsx(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.200" }, transition: "background 0.15s", children: collapsed ? (_jsx(ToolTip, { label: title !== null && title !== void 0 ? title : "", placement: "right", children: _jsx(ChevronRight, { size: 13, color: theme.colors.sidebar.mutedIcon }) })) : (_jsx(ChevronLeft, { size: 13, color: theme.colors.sidebar.mutedIcon })) })] }), _jsx(Box, { id: scrollContainerId, flex: "1", minH: 0, overflowY: "auto", overflowX: "hidden", py: 2, px: "6px", sx: cssForScrollBar(theme), children: items.map((item) => {
|
|
66
68
|
var _a;
|
|
67
69
|
const isActive = String(selected) === String(item.id) ||
|
|
68
70
|
String(selected) === String(item.title);
|
|
@@ -2,7 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { useEffect, useId, useRef, useState } from "react";
|
|
3
3
|
import { Flex, Text, Image, Box, Skeleton, useBreakpointValue } from "@chakra-ui/react";
|
|
4
4
|
import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
5
|
-
import { labelOnFill, solidFillRung } from "../../Theme/tokens/builders/filledSurface.js";
|
|
6
5
|
import { getSidebarActiveAccent } from "./sidebarAccentColors.js";
|
|
7
6
|
import { sanitizeId } from "./sidebarId.js";
|
|
8
7
|
import { cssForScrollBar, HEADER_HEIGHT } from "../../Constants/Sidebar.js";
|
|
@@ -30,13 +29,18 @@ import { SIDEBAR_CHROME, SIDEBAR_ROW } from "./sidebarScale.js";
|
|
|
30
29
|
import { fullViewportHeight } from "../../Theme/tokens/builders/viewportHeight.js";
|
|
31
30
|
const SidebarHeader = ({ logo, companyName, companySubtitle, toggle, isLoading, onToggle, overlay, onClose, }) => {
|
|
32
31
|
const theme = useCustomTheme();
|
|
32
|
+
const activeAccent = getSidebarActiveAccent(theme.colors);
|
|
33
33
|
if (isLoading) {
|
|
34
34
|
return (_jsx(Box, { w: "100%", px: toggle ? 2 : 4, py: 2, h: HEADER_HEIGHT, display: "flex", alignItems: "center", flexShrink: 0, children: toggle ? (_jsx(Flex, { align: "center", gap: 4, justifyContent: "center", w: "100%", children: _jsx(Skeleton, { w: "28px", h: "28px", borderRadius: "lg", startColor: theme.colors.sidebar.background[400], endColor: theme.colors.sidebar.background[300] }) })) : (_jsxs(Flex, { align: "center", gap: 3, w: "100%", children: [_jsx(Skeleton, { w: "28px", h: "28px", borderRadius: "lg", startColor: theme.colors.sidebar.background[400], endColor: theme.colors.sidebar.background[300] }), _jsx(Skeleton, { h: "1.25rem", w: "60%", borderRadius: "lg", startColor: theme.colors.sidebar.background[400], endColor: theme.colors.sidebar.background[300] })] })) }));
|
|
35
35
|
}
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
const logoNode = logo ? (_jsx(Image, { borderRadius: "lg", boxSize: "1.75rem", src: logo, alt: "Company Logo", flexShrink: 0, cursor: toggle ? "pointer" : undefined, onClick: toggle ? onToggle : undefined })) : (_jsx(Box
|
|
37
|
+
// Rail-safe pairing, not a raw primary fill: primary[500] equals the rail itself on
|
|
38
|
+
// some brands (zinc), making the tile disappear. See THEME-CONTRACT.md sidebar rules.
|
|
39
|
+
, {
|
|
40
|
+
// Rail-safe pairing, not a raw primary fill: primary[500] equals the rail itself on
|
|
41
|
+
// some brands (zinc), making the tile disappear. See THEME-CONTRACT.md sidebar rules.
|
|
42
|
+
bg: theme.colors.sidebar.activeBg, color: activeAccent.label, borderRadius: "lg", boxSize: "1.75rem", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: "bold", flexShrink: 0, cursor: toggle ? "pointer" : undefined, onClick: toggle ? onToggle : undefined, children: _jsx(DefaultLogo, {}) }));
|
|
43
|
+
return (_jsxs(Flex, { h: 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 && (_jsxs(Box, { flex: "1", minW: 0, children: [_jsx(OverflowTooltipText, { placement: "right", fontWeight: 600, fontSize: SIDEBAR_CHROME.titleFontSize, textAlign: "left", color: theme.colors.white, lineHeight: "1.3", as: "p", width: "100%", children: companyName !== null && companyName !== void 0 ? companyName : "" }), companySubtitle && (_jsx(Text, { fontSize: SIDEBAR_CHROME.metaFontSize, color: theme.colors.sidebar.mutedLabel, lineHeight: "1.3", isTruncated: true, children: companySubtitle }))] })), !toggle && (_jsx(Box, { as: "button", type: "button", onClick: overlay ? onClose : onToggle, "aria-label": overlay ? "Close menu" : "Collapse sidebar", w: "22px", h: "22px", borderRadius: "lg", bg: "whiteAlpha.200", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, position: "relative", _hover: { bg: "whiteAlpha.300" }, transition: "background 0.15s", sx: {
|
|
40
44
|
"&::after": {
|
|
41
45
|
content: '""',
|
|
42
46
|
position: "absolute",
|
|
@@ -55,7 +59,7 @@ const SkeletonMenuRow = ({ toggle }) => {
|
|
|
55
59
|
const AddNewButton = ({ toggle, onClick, overlay }) => {
|
|
56
60
|
const theme = useCustomTheme();
|
|
57
61
|
const activeAccent = getSidebarActiveAccent(theme.colors);
|
|
58
|
-
return (_jsxs(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.
|
|
62
|
+
return (_jsxs(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.200" }, transition: "background 0.12s", onClick: onClick, children: [_jsx(Box, { w: "18px", h: "18px", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: _jsx(Plus, { size: 16, color: activeAccent.icon }) }), !toggle && (_jsx(Text, { fontSize: SIDEBAR_ROW.fontSize, color: theme.colors.white, fontWeight: "medium", children: "Add New" }))] }));
|
|
59
63
|
};
|
|
60
64
|
const deriveInitials = (user) => {
|
|
61
65
|
if (user.initials)
|
|
@@ -70,8 +74,10 @@ const deriveInitials = (user) => {
|
|
|
70
74
|
const UserFooter = ({ user, toggle, overlay }) => {
|
|
71
75
|
const theme = useCustomTheme();
|
|
72
76
|
const activeAccent = getSidebarActiveAccent(theme.colors);
|
|
73
|
-
const avatar = user.avatarUrl ? (_jsx(Image, { src: user.avatarUrl, alt: user.name, boxSize: "26px", borderRadius: "full", objectFit: "cover", flexShrink: 0 })) : (_jsx(Box, { boxSize: "26px", borderRadius: "full",
|
|
74
|
-
|
|
77
|
+
const avatar = user.avatarUrl ? (_jsx(Image, { src: user.avatarUrl, alt: user.name, boxSize: "26px", borderRadius: "full", objectFit: "cover", flexShrink: 0 })) : (_jsx(Box, { boxSize: "26px", borderRadius: "full",
|
|
78
|
+
// Same rail-safe pairing as the logo tile — primary.opacity[32] was invisible on zinc/skyline.
|
|
79
|
+
bg: theme.colors.sidebar.activeBg, color: activeAccent.label, display: "flex", alignItems: "center", justifyContent: "center", fontSize: SIDEBAR_CHROME.metaFontSize, fontWeight: 600, flexShrink: 0, children: deriveInitials(user) }));
|
|
80
|
+
return (_jsx(Box, { borderTop: "1px solid", borderColor: theme.colors.sidebar.divider, py: 2, px: "6px", flexShrink: 0, children: _jsxs(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.200" }, transition: "background 0.12s", children: [avatar, !toggle && (_jsxs(Box, { flex: "1", minW: 0, textAlign: "left", children: [_jsx(Text, { fontSize: SIDEBAR_CHROME.labelFontSize, fontWeight: 500, color: theme.colors.white, isTruncated: true, children: user.name }), user.role && (_jsx(Text, { fontSize: SIDEBAR_CHROME.metaFontSize, color: theme.colors.sidebar.mutedLabel, isTruncated: true, children: user.role }))] })), !toggle && _jsx(MoreVertical, { size: 14, color: theme.colors.sidebar.mutedIcon })] }) }));
|
|
75
81
|
};
|
|
76
82
|
// Footer "cell" — one segment of the Collapse | Hide/Show control.
|
|
77
83
|
const ControlCell = ({ onClick, ariaLabel, label, accent, children }) => {
|
|
@@ -86,7 +86,7 @@ const MenuItemBox = ({ menu, activeMenu, toggle, handleClick, isOpen, onToggle,
|
|
|
86
86
|
opacity: isBlocked ? 0.6 : 1,
|
|
87
87
|
transition: "background 0.12s",
|
|
88
88
|
};
|
|
89
|
-
const buttonContent = (_jsxs(Flex, { align: "center", gap: "9px", justify: toggle ? "center" : "space-between", w: "100%", children: [_jsxs(Flex, { align: "center", gap: "9px", overflow: "hidden", children: [_jsxs(Box, { position: "relative", display: "flex", alignItems: "center", children: [_jsx(Icon, { as: icon, fontSize: "md", verticalAlign: "middle", color: isAnyActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isAnyActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), toggle && (badgeValue != null || hasSubmenuBadge) && (_jsx(Box, { position: "absolute", top: "0", right: "0", w: "0.375rem", h: "0.375rem", borderRadius: "full", bg: theme.colors.
|
|
89
|
+
const buttonContent = (_jsxs(Flex, { align: "center", gap: "9px", justify: toggle ? "center" : "space-between", w: "100%", children: [_jsxs(Flex, { align: "center", gap: "9px", overflow: "hidden", children: [_jsxs(Box, { position: "relative", display: "flex", alignItems: "center", children: [_jsx(Icon, { as: icon, fontSize: "md", verticalAlign: "middle", color: isAnyActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isAnyActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), toggle && (badgeValue != null || hasSubmenuBadge) && (_jsx(Box, { position: "absolute", top: "0", right: "0", w: "0.375rem", h: "0.375rem", borderRadius: "full", bg: theme.colors.sidebar.semanticText.error }))] }), !toggle && (_jsx(TruncatedTextWithTooltip
|
|
90
90
|
// open={isOpen}
|
|
91
91
|
, {
|
|
92
92
|
// open={isOpen}
|
|
@@ -123,15 +123,19 @@ const MenuItemBox = ({ menu, activeMenu, toggle, handleClick, isOpen, onToggle,
|
|
|
123
123
|
var _a, _b, _c;
|
|
124
124
|
const isSubActive = activeMenu === sub.id;
|
|
125
125
|
const isSubBlocked = menuDisabled(sub) || sub.locked;
|
|
126
|
-
return (_jsxs(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: SIDEBAR_ROW.subHeight, pl: "
|
|
126
|
+
return (_jsxs(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: SIDEBAR_ROW.subHeight, pl: "28px", pr: "10px", borderRadius: "lg", fontSize: SIDEBAR_ROW.fontSize, borderLeft: "2px solid", borderLeftColor: isSubActive ? theme.colors.sidebar.activeIcon : "transparent", backgroundColor: isSubActive ? "whiteAlpha.300" : "transparent", _hover: {
|
|
127
|
+
backgroundColor: isSubBlocked
|
|
128
|
+
? "transparent"
|
|
129
|
+
: isSubActive
|
|
130
|
+
? "whiteAlpha.400"
|
|
131
|
+
: "whiteAlpha.200",
|
|
132
|
+
}, opacity: isSubBlocked ? 0.6 : 1, cursor: isSubBlocked ? "not-allowed" : "pointer", pointerEvents: isSubBlocked ? "none" : "auto", onClick: (e) => {
|
|
127
133
|
if (sub.url && isBrowserNavigationGesture(e))
|
|
128
134
|
return;
|
|
129
135
|
e.preventDefault();
|
|
130
136
|
if (!isSubBlocked)
|
|
131
137
|
handleClick === null || handleClick === void 0 ? void 0 : handleClick(sub);
|
|
132
|
-
}, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, transition: "background 0.12s", children: [_jsxs(Flex, { align: "center", gap: "9px", overflow: "hidden", flex: "1", children: [sub.icon ? (_jsx(Icon, { as: sub.icon, fontSize: SIDEBAR_ROW.iconSize, flexShrink: 0, color: isSubActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" })) : (_jsx(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" })), _jsx(TruncatedTextWithTooltip, { fontSize: SIDEBAR_ROW.fontSize, fontWeight: isSubActive ? 600 : 500, lineHeight: "1",
|
|
133
|
-
// open={isOpen}
|
|
134
|
-
color: isSubActive ? theme.colors.white : theme.colors.sidebar.mutedLabel, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, children: sub.title })] }), sub.locked ? (_jsx(Icon, { as: LockKeyhole, fontSize: "md", color: theme.colors.sidebar.mutedIcon })) : (() => {
|
|
138
|
+
}, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, transition: "background 0.12s", children: [_jsxs(Flex, { align: "center", gap: "9px", overflow: "hidden", flex: "1", children: [sub.icon ? (_jsx(Icon, { as: sub.icon, fontSize: SIDEBAR_ROW.iconSize, flexShrink: 0, color: isSubActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" })) : (_jsx(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" })), _jsx(TruncatedTextWithTooltip, { fontSize: SIDEBAR_ROW.fontSize, fontWeight: isSubActive ? 600 : 500, lineHeight: "1", color: isSubActive ? activeAccent.label : theme.colors.sidebar.mutedLabel, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, children: sub.title })] }), sub.locked ? (_jsx(Icon, { as: LockKeyhole, fontSize: "md", color: theme.colors.sidebar.mutedIcon })) : (() => {
|
|
135
139
|
var _a, _b, _c, _d;
|
|
136
140
|
const subCfg = typeof sub.badge === "object" && sub.badge !== null
|
|
137
141
|
? sub.badge
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { Icon, Flex, Badge } from "@chakra-ui/react";
|
|
2
|
+
import { Icon, Flex, Badge, Box } from "@chakra-ui/react";
|
|
3
3
|
import { LockKeyhole } from "lucide-react";
|
|
4
4
|
import { menuDisabled } from "../menuDisabled.js";
|
|
5
5
|
import { useCustomTheme } from "../../../Theme/useCustomTheme.js";
|
|
@@ -17,7 +17,9 @@ const MenuPopoverContent = ({ menu, handleMenuClick, activeMenu, }) => {
|
|
|
17
17
|
const isBlocked = menuDisabled(menu) || locked;
|
|
18
18
|
const hasSubMenu = !!(subMenu === null || subMenu === void 0 ? void 0 : subMenu.length);
|
|
19
19
|
const isParentActive = activeMenu === menu.id;
|
|
20
|
-
return (_jsxs(_Fragment, { children: [_jsxs(Flex, { as: (hasSubMenu ? "div" : "a"), href: hasSubMenu ? undefined : (_a = menu.url) !== null && _a !== void 0 ? _a : "#", "aria-current": !hasSubMenu && isParentActive ? "page" : undefined, textDecoration: "none", align: "center", gap: 2, px: 2, h: "32px", mb: hasSubMenu ? "4px" : 0, borderBottom: hasSubMenu ? "1px solid" : undefined, borderColor: hasSubMenu ? theme.colors.sidebar.divider : undefined, borderRadius: hasSubMenu ? "none" : "lg", bg: !hasSubMenu && isParentActive ? "whiteAlpha.300" : "transparent", _hover: !hasSubMenu && !isBlocked
|
|
20
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Flex, { as: (hasSubMenu ? "div" : "a"), href: hasSubMenu ? undefined : (_a = menu.url) !== null && _a !== void 0 ? _a : "#", "aria-current": !hasSubMenu && isParentActive ? "page" : undefined, textDecoration: "none", align: "center", gap: 2, px: 2, h: "32px", mb: hasSubMenu ? "4px" : 0, borderBottom: hasSubMenu ? "1px solid" : undefined, borderColor: hasSubMenu ? theme.colors.sidebar.divider : undefined, borderRadius: hasSubMenu ? "none" : "lg", bg: !hasSubMenu && isParentActive ? "whiteAlpha.300" : "transparent", _hover: !hasSubMenu && !isBlocked
|
|
21
|
+
? { bg: isParentActive ? "whiteAlpha.400" : "whiteAlpha.200" }
|
|
22
|
+
: undefined, onClick: (e) => {
|
|
21
23
|
if (!hasSubMenu) {
|
|
22
24
|
e.preventDefault();
|
|
23
25
|
if (!isBlocked)
|
|
@@ -45,9 +47,9 @@ const MenuPopoverContent = ({ menu, handleMenuClick, activeMenu, }) => {
|
|
|
45
47
|
if (!isSubBlocked)
|
|
46
48
|
handleMenuClick === null || handleMenuClick === void 0 ? void 0 : handleMenuClick(sub);
|
|
47
49
|
}, px: 2, h: 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: {
|
|
48
|
-
bg:
|
|
50
|
+
bg: isSubBlocked ? "transparent" : isSubActive ? "whiteAlpha.400" : "whiteAlpha.200",
|
|
49
51
|
cursor: !isSubBlocked ? "pointer" : "not-allowed",
|
|
50
|
-
}, opacity: isSubBlocked ? 0.5 : 1, pointerEvents: isSubBlocked ? "none" : "auto", transition: "background 0.12s", children: [_jsxs(Flex, { align: "center", gap: "9px", overflow: "hidden", flex: "1", children: [_jsx(Icon, { as: sub.icon, fontSize: SIDEBAR_ROW.iconSize, flexShrink: 0, color: isSubActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" }), _jsx(TruncatedTextWithTooltip, { fontSize: 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 ? (_jsx(Icon, { as: LockKeyhole, fontSize: "md", color: theme.colors.sidebar.mutedIcon })) : (() => {
|
|
52
|
+
}, opacity: isSubBlocked ? 0.5 : 1, pointerEvents: isSubBlocked ? "none" : "auto", transition: "background 0.12s", children: [_jsxs(Flex, { align: "center", gap: "9px", overflow: "hidden", flex: "1", children: [sub.icon ? (_jsx(Icon, { as: sub.icon, fontSize: SIDEBAR_ROW.iconSize, flexShrink: 0, color: isSubActive ? activeAccent.icon : theme.colors.sidebar.mutedIcon, _groupHover: isSubActive ? undefined : { color: theme.colors.white }, transition: "color 0.12s" })) : (_jsx(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" })), _jsx(TruncatedTextWithTooltip, { fontSize: 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 ? (_jsx(Icon, { as: LockKeyhole, fontSize: "md", color: theme.colors.sidebar.mutedIcon })) : (() => {
|
|
51
53
|
var _a, _b, _c, _d;
|
|
52
54
|
const cfg = typeof sub.badge === "object" && sub.badge !== null
|
|
53
55
|
? sub.badge
|
|
@@ -10,7 +10,7 @@ const OtherApps = ({ toggle, otherApps }) => {
|
|
|
10
10
|
return (_jsx(Box, { display: "flex", alignItems: "center", justifyContent: "center", color: theme.colors.sidebar.mutedIcon, fontSize: "15px", flexShrink: 0, children: (_a = app.icon) !== null && _a !== void 0 ? _a : (_jsx(Box, { w: "0.5rem", h: "0.5rem", borderRadius: "full", bg: app.color, boxShadow: `0 0 5px ${app.color}`, flexShrink: 0 })) }));
|
|
11
11
|
};
|
|
12
12
|
// Grid cell: icon on top, truncated label below (label hidden when collapsed).
|
|
13
|
-
const appCell = (app) => (_jsxs(Flex, { as: "button", type: "button", direction: "column", align: "center", justify: "center", gap: "3px", px: "2px", py: "6px", borderRadius: "lg", cursor: "pointer", border: "none", bg: "transparent", w: "100%", _hover: { backgroundColor: "whiteAlpha.
|
|
13
|
+
const appCell = (app) => (_jsxs(Flex, { as: "button", type: "button", direction: "column", align: "center", justify: "center", gap: "3px", px: "2px", py: "6px", borderRadius: "lg", cursor: "pointer", border: "none", bg: "transparent", w: "100%", _hover: { backgroundColor: "whiteAlpha.200" }, transition: "background 0.12s", onClick: app.onClick, children: [appIcon(app), !toggle && (_jsx(Text, { fontSize: "9.5px", color: theme.colors.sidebar.mutedLabel, textAlign: "center", maxW: "44px", isTruncated: true, children: app.name }))] }));
|
|
14
14
|
const flyoutBody = (app) => {
|
|
15
15
|
var _a;
|
|
16
16
|
return (_jsxs(_Fragment, { children: [_jsxs(Flex, { alignItems: "center", gap: 2, mb: 1, onClick: app.onClick, children: [(_a = app.icon) !== null && _a !== void 0 ? _a : (_jsx(Box, { w: "0.5rem", h: "0.5rem", borderRadius: "full", bg: app.color, boxShadow: `0 0 5px ${app.color}`, flexShrink: 0 })), _jsx(Text, { fontSize: "sm", fontWeight: 700, color: theme.colors.white, children: app.name })] }), app.description && (_jsx(Text, { fontSize: "xs", color: theme.colors.sidebar.mutedLabel, children: app.description }))] }));
|
|
@@ -15,7 +15,7 @@ import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
|
15
15
|
import { transitionFor } from "../../Theme/tokens/primitives/motion.js";
|
|
16
16
|
import { reducedMotionSx } from "../../Theme/chakra/motion.js";
|
|
17
17
|
import { focusVisibleStyles } from "../../Theme/chakra/focusRing.styles.js";
|
|
18
|
-
import { DENSITY_ROWS, EMPTY_STATE_HEIGHT, GROUP_HEADER_HEIGHT, TOOLBAR_HEIGHT, pxOf, rowHeightFor } from "./components/rowMetrics.js";
|
|
18
|
+
import { DENSITY_ROWS, EMPTY_STATE_HEIGHT, GROUP_HEADER_HEIGHT, MAX_TABLE_HEIGHT, TOOLBAR_HEIGHT, pxOf, rowHeightFor } from "./components/rowMetrics.js";
|
|
19
19
|
import { scrollbarStyles, SCROLLBAR_WIDTH } from "../../Theme/tokens/builders/scrollbar.js";
|
|
20
20
|
import { scrollShadowStyles } from "../../Theme/tokens/builders/scrollShadow.js";
|
|
21
21
|
import useTable from "./hooks/useTable.js";
|
|
@@ -312,9 +312,21 @@ export default function Table({ data, columns, onSelection, isLoading, isCheckbo
|
|
|
312
312
|
rowsHeight += ((_c = renderGroups === null || renderGroups === void 0 ? void 0 : renderGroups.length) !== null && _c !== void 0 ? _c : 1) * GROUP_HEADER_HEIGHT;
|
|
313
313
|
if (isEmptyState)
|
|
314
314
|
rowsHeight = Math.max(rowsHeight, headerHeight + EMPTY_STATE_HEIGHT);
|
|
315
|
-
const dynamicMaxH = Math.min(
|
|
315
|
+
const dynamicMaxH = Math.min(MAX_TABLE_HEIGHT, rowsHeight);
|
|
316
316
|
const fittedMaxH = autoFitViewport ? Math.min(dynamicMaxH, viewportAvailableH) : dynamicMaxH;
|
|
317
|
-
const
|
|
317
|
+
const formulaMaxH = typeof tableMaxHeight === "number" ? tableMaxHeight : (isCompactRows ? rowsHeight + 8 : fittedMaxH);
|
|
318
|
+
// NOTE: wrapped cell content can exceed the per-row estimate; when the row count is
|
|
319
|
+
// within the display cap (explicit maxVisibleRows, else the default 10), size naturally
|
|
320
|
+
// instead of clipping. `visibleRowsCount` isn't used here — minRows defaults to
|
|
321
|
+
// actualRows, which would make this true for any row count.
|
|
322
|
+
const rawMaxRows = typeof maxVisibleRows === "number" ? maxVisibleRows : (actualRows === 0 ? 1 : 10);
|
|
323
|
+
const showsAllRows = actualRows <= rawMaxRows;
|
|
324
|
+
const useNaturalHeight = typeof tableMaxHeight !== "number" && showsAllRows && !isTableLoading && !canInfinite &&
|
|
325
|
+
!(filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar);
|
|
326
|
+
const tableMinH = useNaturalHeight ? formulaMaxH : undefined;
|
|
327
|
+
const tableMaxH = useNaturalHeight
|
|
328
|
+
? (autoFitViewport ? viewportAvailableH : undefined)
|
|
329
|
+
: formulaMaxH;
|
|
318
330
|
const isCompactHeader = useBreakpointValue({ base: true, md: true, lg: false });
|
|
319
331
|
useEffect(() => {
|
|
320
332
|
if (!isCompactHeader) {
|
|
@@ -365,7 +377,7 @@ export default function Table({ data, columns, onSelection, isLoading, isCheckbo
|
|
|
365
377
|
from { transform: rotate(0deg); }
|
|
366
378
|
to { transform: rotate(360deg); }
|
|
367
379
|
}
|
|
368
|
-
` }), _jsxs(Box, { bg: theme.colors.background[50], border: `0.063rem solid ${theme.colors.boxborder[200]}`, borderRadius: "xl", overflow: "hidden", children: [filterSidebar && filterMode === "modal" && (_jsxs(Modal, { isOpen: isFilterModalOpen, onClose: onFilterModalClose, size: "4xl", scrollBehavior: "inside", children: [_jsx(ModalOverlay, {}), _jsxs(ModalContent, { bg: theme.colors.surfaceRaised, my: 0, top: "10%", position: "fixed", left: "auto", right: "auto", children: [_jsx(ModalCloseButton, { size: "sm" }), _jsx(ModalBody, { p: 0, children: _jsx(LeftFilterPane, { theme: theme, sections: (_d = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.sidebarOptions) !== null && _d !== void 0 ? _d : [], selected: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.selected, onApply: (sel) => { var _a; (_a = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.onApply) === null || _a === void 0 ? void 0 : _a.call(filterSidebar, sel); onFilterModalClose(); }, onClear: () => { var _a; (_a = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.onClearAllHandler) === null || _a === void 0 ? void 0 : _a.call(filterSidebar); }, isApplyLoading: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isApplyLoading, filterMode: filterMode }) })] })] })), _jsxs(Flex, { align: "start", children: [filterMode === "sidebar" && (_jsx(MotionBox, { "data-testid": "filter-sidebar-pane", initial: { width: 0 }, animate: { width: (filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar) ? 180 : 0 }, transition: { type: "tween", duration: 0.5 }, overflow: "hidden", flexShrink: 0, borderRight: (filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar) ? "1px solid" : "none", borderColor: theme.colors.boxborder[200], style: { height: TOOLBAR_HEIGHT +
|
|
380
|
+
` }), _jsxs(Box, { bg: theme.colors.background[50], border: `0.063rem solid ${theme.colors.boxborder[200]}`, borderRadius: "xl", overflow: "hidden", children: [filterSidebar && filterMode === "modal" && (_jsxs(Modal, { isOpen: isFilterModalOpen, onClose: onFilterModalClose, size: "4xl", scrollBehavior: "inside", children: [_jsx(ModalOverlay, {}), _jsxs(ModalContent, { bg: theme.colors.surfaceRaised, my: 0, top: "10%", position: "fixed", left: "auto", right: "auto", children: [_jsx(ModalCloseButton, { size: "sm" }), _jsx(ModalBody, { p: 0, children: _jsx(LeftFilterPane, { theme: theme, sections: (_d = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.sidebarOptions) !== null && _d !== void 0 ? _d : [], selected: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.selected, onApply: (sel) => { var _a; (_a = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.onApply) === null || _a === void 0 ? void 0 : _a.call(filterSidebar, sel); onFilterModalClose(); }, onClear: () => { var _a; (_a = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.onClearAllHandler) === null || _a === void 0 ? void 0 : _a.call(filterSidebar); }, isApplyLoading: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isApplyLoading, filterMode: filterMode }) })] })] })), _jsxs(Flex, { align: "start", children: [filterMode === "sidebar" && (_jsx(MotionBox, { "data-testid": "filter-sidebar-pane", initial: { width: 0 }, animate: { width: (filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar) ? 180 : 0 }, transition: { type: "tween", duration: 0.5 }, overflow: "hidden", flexShrink: 0, borderRight: (filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar) ? "1px solid" : "none", borderColor: theme.colors.boxborder[200], style: { height: TOOLBAR_HEIGHT + formulaMaxH }, minHeight: (filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar) ? "32rem" : "auto", children: _jsx(LeftFilterPane, { height: TOOLBAR_HEIGHT + formulaMaxH, theme: theme, sections: (_e = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.sidebarOptions) !== null && _e !== void 0 ? _e : [], selected: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.selected, onApply: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.onApply, onClear: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.onClearAllHandler, isApplyLoading: filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isApplyLoading, filterMode: filterMode }) })), _jsxs(Box, { flex: "1", minW: 0, children: [_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", px: 3, py: 0, height: `${TOOLBAR_HEIGHT}px`, gap: 3, flexWrap: "nowrap", bg: theme.colors.background[50], borderBottom: `0.063rem solid ${theme.colors.boxborder[200]}`, children: [[
|
|
369
381
|
filterSidebar && (_jsx(ToolTip, { label: "Filter", placement: "top", children: _jsxs(Box, { position: "relative", display: "inline-block", children: [_jsx(Box, { as: "button", type: "button", "aria-label": "Filter", "aria-haspopup": filterMode === "modal" ? "dialog" : undefined, "aria-expanded": filterMode === "modal"
|
|
370
382
|
? isFilterModalOpen
|
|
371
383
|
: !!(filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar), display: "inline-flex", alignItems: "center", justifyContent: "center", p: 0, bg: "transparent", border: "none", borderRadius: "md", cursor: "pointer", onClick: filterMode === "modal" ? onFilterModalOpen : filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.filterSidebarToggle, _hover: {
|
|
@@ -401,7 +413,7 @@ export default function Table({ data, columns, onSelection, isLoading, isCheckbo
|
|
|
401
413
|
.filter(Boolean)
|
|
402
414
|
.flatMap((tool, i) => (i === 0 ? [tool] : [_jsx(VeritcalDivider, {}, `divider-${i}`), tool])), _jsx(ActiveFilters, { columns: columnsList, columnsSearch: columnsSearch, setColumnsSearch: setColumnsSearch }), _jsxs(Box, { ml: "auto", display: "flex", alignItems: "center", gap: 2, children: [groupLoadMoreActive && loadMorePosition === "top" && (groupLoadMoreCaption || canGroupLoadMore) && (_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, flex: "0 0 auto", children: [groupLoadMoreCaption && (_jsx(Box, { fontSize: "0.75rem", color: theme.colors.text[500], whiteSpace: "nowrap", children: groupLoadMoreCaption })), canGroupLoadMore && (_jsx(Button, { size: "xs", variant: "outline", colorScheme: "gray", isLoading: isLoadingMore, loadingText: loadMoreText, onClick: handleGroupLoadMore, label: loadMoreText }))] })), (isPagination || isServerPagination) && !isGrouped && !canInfinite && !isCompactHeader && (_jsx("div", { children: _jsx(Pagination, { currentPage: currentPage, setCurrentPage: setCurrentPage, rowsPerPage: rowsPerPage, pages: pages, paginationText: tablePaginationText, handlePageSizeChange: handlePageSizeChange, dataLength: tableData.length, isServerPagination: isServerPagination, paginationSelectOptions: paginationSelectOptions }) })), (isPagination || isServerPagination) && !isGrouped && !canInfinite && isCompactHeader && (_jsxs(Popover, { isOpen: isPaginationPopoverOpen, onClose: () => setIsPaginationPopoverOpen(false), placement: "bottom-end", children: [_jsx(PopoverTrigger, { children: _jsx(IconButton, { "aria-label": "Pagination", size: "sm", variant: "ghost", icon: _jsx(EllipsisVertical, { size: 18 }), color: theme.colors.text[500], _hover: {
|
|
403
415
|
color: theme.colors.accentText,
|
|
404
|
-
}, onClick: () => setIsPaginationPopoverOpen((open) => !open) }) }), _jsx(Portal, { children: _jsx(PopoverContent, { maxW: "22rem", p: 2, zIndex: 1600, bg: theme.colors.surfaceRaised, boxShadow: "lg", children: _jsx(PopoverBody, { p: 0, children: _jsx(Pagination, { currentPage: currentPage, setCurrentPage: setCurrentPage, rowsPerPage: rowsPerPage, pages: pages, paginationText: tablePaginationText, handlePageSizeChange: handlePageSizeChange, dataLength: tableData.length, isServerPagination: isServerPagination, paginationSelectOptions: paginationSelectOptions }) }) }) })] }))] })] }), _jsxs(TableContainer, { ref: tableContainerRef, position: "relative", h: isTableLoading ? tableMaxH : undefined, maxH: !isTableLoading ? tableMaxH : undefined, pb: isTableLoading ? 0 : compactScrollbarPadding, overflowY: isCompactRows ? "hidden" : "auto", overflowX: "auto", sx: {
|
|
416
|
+
}, onClick: () => setIsPaginationPopoverOpen((open) => !open) }) }), _jsx(Portal, { children: _jsx(PopoverContent, { maxW: "22rem", p: 2, zIndex: 1600, bg: theme.colors.surfaceRaised, boxShadow: "lg", children: _jsx(PopoverBody, { p: 0, children: _jsx(Pagination, { currentPage: currentPage, setCurrentPage: setCurrentPage, rowsPerPage: rowsPerPage, pages: pages, paginationText: tablePaginationText, handlePageSizeChange: handlePageSizeChange, dataLength: tableData.length, isServerPagination: isServerPagination, paginationSelectOptions: paginationSelectOptions }) }) }) })] }))] })] }), _jsxs(TableContainer, { ref: tableContainerRef, position: "relative", h: isTableLoading ? tableMaxH : undefined, minH: !isTableLoading ? tableMinH : undefined, maxH: !isTableLoading ? tableMaxH : undefined, pb: isTableLoading ? 0 : compactScrollbarPadding, overflowY: isCompactRows ? "hidden" : "auto", overflowX: "auto", sx: {
|
|
405
417
|
...scrollShadowStyles(theme.colors.background[50]),
|
|
406
418
|
...scrollbarStyles(theme.colors),
|
|
407
419
|
// Compact rows hide the horizontal bar until hover to keep the row height.
|
|
@@ -6,5 +6,6 @@ export const DENSITY_ROWS = {
|
|
|
6
6
|
export const TOOLBAR_HEIGHT = 45;
|
|
7
7
|
export const GROUP_HEADER_HEIGHT = 42;
|
|
8
8
|
export const EMPTY_STATE_HEIGHT = 200;
|
|
9
|
+
export const MAX_TABLE_HEIGHT = 500;
|
|
9
10
|
export const rowHeightFor = (density) => DENSITY_ROWS[density !== null && density !== void 0 ? density : "normal"].height;
|
|
10
11
|
export const pxOf = (length) => parseFloat(length);
|
|
@@ -12,14 +12,14 @@ export const cssForScrollBar = (theme) => ({
|
|
|
12
12
|
borderRadius: "0.5rem",
|
|
13
13
|
},
|
|
14
14
|
"&:hover::-webkit-scrollbar-thumb": {
|
|
15
|
-
background: theme.colors.
|
|
15
|
+
background: theme.colors.sidebar.mutedIcon,
|
|
16
16
|
},
|
|
17
17
|
"&:hover::-webkit-scrollbar-thumb:hover": {
|
|
18
|
-
background: theme.colors.
|
|
18
|
+
background: theme.colors.sidebar.mutedLabel,
|
|
19
19
|
},
|
|
20
20
|
scrollbarWidth: "none",
|
|
21
21
|
"&:hover": {
|
|
22
22
|
scrollbarWidth: "thin",
|
|
23
|
-
scrollbarColor: `${theme.colors.
|
|
23
|
+
scrollbarColor: `${theme.colors.sidebar.mutedIcon} ${theme.colors.sidebar.background[500]}`,
|
|
24
24
|
},
|
|
25
25
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { compositeOver } from "./color.js";
|
|
2
|
-
import { liftToContrast, resolveHoverTint, AA_NON_TEXT } from "./outlineRung.js";
|
|
2
|
+
import { liftToContrast, resolveHoverTint, settleAcross, AA_NON_TEXT } from "./outlineRung.js";
|
|
3
3
|
import { buildSemanticText } from "./semanticText.js";
|
|
4
4
|
/** WCAG 1.4.3 — the active label is normal-size text. */
|
|
5
5
|
export const AA_NORMAL_TEXT = 4.5;
|
|
@@ -18,13 +18,15 @@ export const sidebarDivider = (background) => resolveHoverTint(compositeOver(DIV
|
|
|
18
18
|
export const buildSidebarTokens = (background, lightPrimary, semantic) => {
|
|
19
19
|
const surface = sidebarActiveSurface(background);
|
|
20
20
|
const elevated = resolveHoverTint(background[500], background[500]);
|
|
21
|
+
// Muted chrome must clear contrast on the bare rail AND the lightest row-hover overlay.
|
|
22
|
+
const rowPeak = sidebarRowPeak(elevated);
|
|
21
23
|
return {
|
|
22
24
|
background,
|
|
23
25
|
elevated,
|
|
24
26
|
activeIcon: liftToContrast(lightPrimary[300], surface, AA_NON_TEXT),
|
|
25
27
|
activeLabel: liftToContrast(lightPrimary[100], surface, AA_NORMAL_TEXT),
|
|
26
|
-
mutedIcon:
|
|
27
|
-
mutedLabel:
|
|
28
|
+
mutedIcon: settleAcross(background[300], [elevated, rowPeak], AA_NON_TEXT),
|
|
29
|
+
mutedLabel: settleAcross(background[100], [elevated, rowPeak], AA_NORMAL_TEXT),
|
|
28
30
|
semanticText: buildSemanticText(semantic, elevated),
|
|
29
31
|
hoverBg: sidebarHoverSurface(background),
|
|
30
32
|
activeBg: surface,
|
package/package.json
CHANGED