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 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`
@@ -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]` / `primary[500]`, hidden until hover.
1414
- `FlexCss` is removed — `cssForScrollBar` is now the only scrollbar treatment the SideBar uses.
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 = "md", 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) {
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.red[400] }))] }) }) }), (0, jsx_runtime_1.jsx)(react_2.Portal, { children: (0, jsx_runtime_1.jsx)(react_2.PopoverContent, { borderRadius: "lg", bg: theme.colors.sidebar.elevated, boxShadow: "lg", minW: "10rem", maxW: "14rem", py: "0.125rem", ml: "-0.5rem", cursor: (0, menuDisabled_1.menuDisabled)(item) ? "not-allowed" : "pointer", zIndex: 1500, color: theme.colors.white, border: 'none', children: (0, jsx_runtime_1.jsx)(react_2.PopoverBody, { p: 3, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, justify: "space-between", children: [(0, jsx_runtime_1.jsxs)(react_2.Flex, { align: "center", gap: 2, flex: "1", minW: 0, children: [(0, jsx_runtime_1.jsx)(react_2.Icon, { as: item.icon, fontSize: "md", flexShrink: 0 }), (0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", maxWidth: "100%", fontSize: itemFontSize, fontWeight: "medium", as: "p", children: item.title })] }), badgeVal != null && ((0, jsx_runtime_1.jsx)(react_2.Badge, { ...softBadge(theme.colors, colorScheme, (0, sidebarAccent_1.sidebarRowPeak)(theme.colors.sidebar.elevated)), fontSize: "xs", variant: variant, borderRadius: radius, children: badgeVal }))] }) }) }) })] }));
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.100" }, transition: "background 0.15s", children: collapsed ? ((0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: title !== null && title !== void 0 ? title : "", placement: "right", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { size: 13, color: theme.colors.sidebar.mutedIcon }) })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, { size: 13, color: theme.colors.sidebar.mutedIcon })) })] }), (0, jsx_runtime_1.jsx)(react_2.Box, { id: "secondary-scroll-container", flex: "1", minH: 0, overflowY: "auto", overflowX: "hidden", py: 2, px: "6px", children: items.map((item) => {
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 primaryFillRung = (0, filledSurface_1.solidFillRung)(theme.colors.primary, theme.colors.white);
43
- const primaryFill = theme.colors.primary[primaryFillRung];
44
- const logoNode = logo ? ((0, jsx_runtime_1.jsx)(react_2.Image, { borderRadius: "lg", boxSize: "1.75rem", src: logo, alt: "Company Logo", flexShrink: 0, cursor: toggle ? "pointer" : undefined, onClick: toggle ? onToggle : undefined })) : ((0, jsx_runtime_1.jsx)(react_2.Box, { bg: primaryFill, color: (0, filledSurface_1.labelOnFill)(primaryFill, theme.colors.white, theme.colors.black), borderRadius: "lg", boxSize: "1.75rem", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: "bold", flexShrink: 0, cursor: toggle ? "pointer" : undefined, onClick: toggle ? onToggle : undefined, children: (0, jsx_runtime_1.jsx)(defaultLogo_1.default, {}) }));
45
- return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { h: Sidebar_1.HEADER_HEIGHT, w: "100%", alignItems: "center", justifyContent: toggle ? "center" : "flex-start", gap: 2, px: toggle ? "8px" : "10px", borderBottom: "1px solid", borderColor: theme.colors.sidebar.divider, minW: 0, overflow: "hidden", flexShrink: 0, children: [logoNode, !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, children: [(0, jsx_runtime_1.jsx)(OverflowTooltipText_1.default, { placement: "right", fontWeight: 600, fontSize: sidebarScale_1.SIDEBAR_CHROME.titleFontSize, textAlign: "left", color: theme.colors.white, lineHeight: "1.3", as: "p", width: "100%", children: companyName !== null && companyName !== void 0 ? companyName : "" }), companySubtitle && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: sidebarScale_1.SIDEBAR_CHROME.metaFontSize, color: theme.colors.sidebar.mutedLabel, lineHeight: "1.3", isTruncated: true, children: companySubtitle }))] })), !toggle && ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "button", type: "button", onClick: overlay ? onClose : onToggle, "aria-label": overlay ? "Close menu" : "Collapse sidebar", w: "22px", h: "22px", borderRadius: "lg", bg: "whiteAlpha.100", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, position: "relative", _hover: { bg: "whiteAlpha.300" }, transition: "background 0.15s", sx: {
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.100" }, transition: "background 0.12s", onClick: onClick, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { w: "18px", h: "18px", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { size: 16, color: activeAccent.icon }) }), !toggle && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, color: theme.colors.white, fontWeight: "medium", children: "Add New" }))] }));
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", bg: theme.colors.primary.opacity[32], color: activeAccent.label, display: "flex", alignItems: "center", justifyContent: "center", fontSize: sidebarScale_1.SIDEBAR_CHROME.metaFontSize, fontWeight: 600, flexShrink: 0, children: deriveInitials(user) }));
80
- return ((0, jsx_runtime_1.jsx)(react_2.Box, { borderTop: "1px solid", borderColor: theme.colors.sidebar.divider, py: 2, px: "6px", flexShrink: 0, children: (0, jsx_runtime_1.jsxs)(react_2.Flex, { as: "button", type: "button", onClick: user.onClick, align: "center", gap: 2, px: 2, py: overlay ? "10px" : "6px", w: "100%", borderRadius: "lg", cursor: "pointer", bg: "transparent", border: "none", justify: toggle ? "center" : "flex-start", _hover: { bg: "whiteAlpha.100" }, transition: "background 0.12s", children: [avatar, !toggle && ((0, jsx_runtime_1.jsxs)(react_2.Box, { flex: "1", minW: 0, textAlign: "left", children: [(0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: sidebarScale_1.SIDEBAR_CHROME.labelFontSize, fontWeight: 500, color: theme.colors.white, isTruncated: true, children: user.name }), user.role && ((0, jsx_runtime_1.jsx)(react_2.Text, { fontSize: sidebarScale_1.SIDEBAR_CHROME.metaFontSize, color: theme.colors.sidebar.mutedLabel, isTruncated: true, children: user.role }))] })), !toggle && (0, jsx_runtime_1.jsx)(lucide_react_1.MoreVertical, { size: 14, color: theme.colors.sidebar.mutedIcon })] }) }));
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.red[400] }))] }), !toggle && ((0, jsx_runtime_1.jsx)(TextTruncation_1.default
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: "30px", pr: "10px", borderRadius: "lg", fontSize: sidebarScale_1.SIDEBAR_ROW.fontSize, backgroundColor: "transparent", _hover: { backgroundColor: "whiteAlpha.100" }, opacity: isSubBlocked ? 0.6 : 1, cursor: isSubBlocked ? "not-allowed" : "pointer", pointerEvents: isSubBlocked ? "none" : "auto", onClick: (e) => {
131
+ 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 ? { bg: "whiteAlpha.100" } : undefined, onClick: (e) => {
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: !isSubBlocked ? "whiteAlpha.100" : "transparent",
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.100" }, 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 }))] }));
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(500, rowsHeight);
321
+ const dynamicMaxH = Math.min(rowMetrics_1.MAX_TABLE_HEIGHT, rowsHeight);
322
322
  const fittedMaxH = autoFitViewport ? Math.min(dynamicMaxH, viewportAvailableH) : dynamicMaxH;
323
- const tableMaxH = typeof tableMaxHeight === "number" ? tableMaxHeight : (isCompactRows ? rowsHeight + 8 : fittedMaxH);
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 + tableMaxH }, 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 + tableMaxH, 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: [[
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
- /** Caps the auto-computed row count used for sizing (paired with minVisibleRows); ignored once tableMaxHeight is set. */
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.primary[500],
18
+ background: theme.colors.sidebar.mutedIcon,
19
19
  },
20
20
  "&:hover::-webkit-scrollbar-thumb:hover": {
21
- background: theme.colors.primary[700],
21
+ background: theme.colors.sidebar.mutedLabel,
22
22
  },
23
23
  scrollbarWidth: "none",
24
24
  "&:hover": {
25
25
  scrollbarWidth: "thin",
26
- scrollbarColor: `${theme.colors.primary[500]} ${theme.colors.sidebar.background[500]}`,
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.liftToContrast)(background[300], elevated, outlineRung_1.AA_NON_TEXT),
34
- mutedLabel: (0, outlineRung_1.liftToContrast)(background[100], elevated, exports.AA_NORMAL_TEXT),
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 = "md", 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) {
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.red[400] }))] }) }) }), _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
+ }, 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.100" }, 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: "secondary-scroll-container", flex: "1", minH: 0, overflowY: "auto", overflowX: "hidden", py: 2, px: "6px", children: items.map((item) => {
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 primaryFillRung = solidFillRung(theme.colors.primary, theme.colors.white);
37
- const primaryFill = theme.colors.primary[primaryFillRung];
38
- 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, { bg: primaryFill, color: labelOnFill(primaryFill, theme.colors.white, theme.colors.black), borderRadius: "lg", boxSize: "1.75rem", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: "bold", flexShrink: 0, cursor: toggle ? "pointer" : undefined, onClick: toggle ? onToggle : undefined, children: _jsx(DefaultLogo, {}) }));
39
- 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.100", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, position: "relative", _hover: { bg: "whiteAlpha.300" }, transition: "background 0.15s", sx: {
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.100" }, 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" }))] }));
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", bg: theme.colors.primary.opacity[32], color: activeAccent.label, display: "flex", alignItems: "center", justifyContent: "center", fontSize: SIDEBAR_CHROME.metaFontSize, fontWeight: 600, flexShrink: 0, children: deriveInitials(user) }));
74
- 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.100" }, 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 })] }) }));
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.red[400] }))] }), !toggle && (_jsx(TruncatedTextWithTooltip
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: "30px", pr: "10px", borderRadius: "lg", fontSize: SIDEBAR_ROW.fontSize, backgroundColor: "transparent", _hover: { backgroundColor: "whiteAlpha.100" }, opacity: isSubBlocked ? 0.6 : 1, cursor: isSubBlocked ? "not-allowed" : "pointer", pointerEvents: isSubBlocked ? "none" : "auto", onClick: (e) => {
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 ? { bg: "whiteAlpha.100" } : undefined, onClick: (e) => {
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: !isSubBlocked ? "whiteAlpha.100" : "transparent",
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.100" }, 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 }))] }));
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(500, rowsHeight);
315
+ const dynamicMaxH = Math.min(MAX_TABLE_HEIGHT, rowsHeight);
316
316
  const fittedMaxH = autoFitViewport ? Math.min(dynamicMaxH, viewportAvailableH) : dynamicMaxH;
317
- const tableMaxH = typeof tableMaxHeight === "number" ? tableMaxHeight : (isCompactRows ? rowsHeight + 8 : fittedMaxH);
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 + tableMaxH }, minHeight: (filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar) ? "32rem" : "auto", children: _jsx(LeftFilterPane, { height: TOOLBAR_HEIGHT + tableMaxH, 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: [[
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.primary[500],
15
+ background: theme.colors.sidebar.mutedIcon,
16
16
  },
17
17
  "&:hover::-webkit-scrollbar-thumb:hover": {
18
- background: theme.colors.primary[700],
18
+ background: theme.colors.sidebar.mutedLabel,
19
19
  },
20
20
  scrollbarWidth: "none",
21
21
  "&:hover": {
22
22
  scrollbarWidth: "thin",
23
- scrollbarColor: `${theme.colors.primary[500]} ${theme.colors.sidebar.background[500]}`,
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: liftToContrast(background[300], elevated, AA_NON_TEXT),
27
- mutedLabel: liftToContrast(background[100], elevated, AA_NORMAL_TEXT),
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixelize-design-library",
3
- "version": "2.4.2-beta.52",
3
+ "version": "2.4.2-beta.54",
4
4
  "description": "React component library for Pixelize apps: themeable Chakra-based components, design tokens and light/dark brand theming.",
5
5
  "keywords": [
6
6
  "react",