pixelize-design-library 2.4.2-beta.32 → 2.4.2-beta.33

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.
Files changed (50) hide show
  1. package/README.md +21 -0
  2. package/dist/Components/Button/Button.styles.js +9 -8
  3. package/dist/Components/Card/PaymentCard/PaymentCard.js +14 -5
  4. package/dist/Components/Common/ErrorComponent.js +6 -5
  5. package/dist/Components/DatePicker/CalendarPanel.js +6 -7
  6. package/dist/Components/FilePreview/FilePreview.js +2 -1
  7. package/dist/Components/KanbanBoard/KanbanActions/KanbanActions.js +1 -2
  8. package/dist/Components/OrganizationDetails/OrganizationDetails.js +3 -2
  9. package/dist/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +4 -3
  10. package/dist/Components/ScrollToTop/ScrollToTop.js +3 -3
  11. package/dist/Components/SelectSearch/SelectSearch.js +1 -1
  12. package/dist/Components/SideBar/SideBar.js +4 -2
  13. package/dist/Components/StageProgress/StageProgressProps.js +6 -4
  14. package/dist/Components/Table/Table.js +2 -3
  15. package/dist/Components/Table/filters/LeftFilterPane.js +1 -1
  16. package/dist/Components/Tag/Tag.styles.js +13 -9
  17. package/dist/Theme/chakra/componentStyles.js +16 -9
  18. package/dist/Theme/chakra/createBrandTheme.js +15 -9
  19. package/dist/Theme/tokens/builders/filledSurface.d.ts +29 -0
  20. package/dist/Theme/tokens/builders/filledSurface.js +74 -0
  21. package/dist/Utils/table.js +5 -2
  22. package/dist/esm/Components/Button/Button.styles.js +10 -9
  23. package/dist/esm/Components/Card/PaymentCard/PaymentCard.js +14 -5
  24. package/dist/esm/Components/Common/ErrorComponent.js +6 -5
  25. package/dist/esm/Components/DatePicker/CalendarPanel.js +6 -7
  26. package/dist/esm/Components/FilePreview/FilePreview.js +2 -1
  27. package/dist/esm/Components/KanbanBoard/KanbanActions/KanbanActions.js +1 -2
  28. package/dist/esm/Components/OrganizationDetails/OrganizationDetails.js +4 -3
  29. package/dist/esm/Components/ProfilePhotoViewer/ProfilePhotoViewer.js +5 -4
  30. package/dist/esm/Components/ScrollToTop/ScrollToTop.js +3 -3
  31. package/dist/esm/Components/SelectSearch/SelectSearch.js +1 -1
  32. package/dist/esm/Components/SideBar/SideBar.js +4 -2
  33. package/dist/esm/Components/StageProgress/StageProgressProps.js +7 -5
  34. package/dist/esm/Components/Table/Table.js +2 -3
  35. package/dist/esm/Components/Table/filters/LeftFilterPane.js +1 -1
  36. package/dist/esm/Components/Tag/Tag.styles.js +14 -10
  37. package/dist/esm/Theme/chakra/componentStyles.js +16 -9
  38. package/dist/esm/Theme/chakra/createBrandTheme.js +15 -9
  39. package/dist/esm/Theme/tokens/builders/filledSurface.js +67 -0
  40. package/dist/esm/Utils/table.js +5 -2
  41. package/dist/esm/index.js +3 -0
  42. package/dist/index.d.ts +2 -0
  43. package/dist/index.js +8 -1
  44. package/package.json +1 -1
  45. package/dist/Theme/tokens/builders/scrollShadow.d.ts +0 -2
  46. package/dist/Theme/tokens/builders/scrollShadow.js +0 -16
  47. package/dist/Theme/tokens/builders/solidFillRung.d.ts +0 -4
  48. package/dist/Theme/tokens/builders/solidFillRung.js +0 -33
  49. package/dist/esm/Theme/tokens/builders/scrollShadow.js +0 -13
  50. package/dist/esm/Theme/tokens/builders/solidFillRung.js +0 -28
@@ -8,7 +8,7 @@ const react_1 = require("@chakra-ui/react");
8
8
  const common_web_1 = __importDefault(require("./common.web"));
9
9
  const fonts_web_1 = __importDefault(require("./fonts.web"));
10
10
  const componentStyles_1 = require("./componentStyles");
11
- const accentText_1 = require("../tokens/builders/accentText");
11
+ const filledSurface_1 = require("../tokens/builders/filledSurface");
12
12
  const scrollbar_1 = require("../tokens/builders/scrollbar");
13
13
  const focusRing_styles_1 = require("./focusRing.styles");
14
14
  /**
@@ -88,14 +88,20 @@ const createBrandTheme = (palette, options = {}) => {
88
88
  // selecting text anywhere (e.g. a table cell) shows a stray white/lavender patch on
89
89
  // the dark canvas. Brand it instead, with WCAG-safe ink via the same `onFilled` math
90
90
  // used for buttons/badges.
91
- "::selection": {
92
- background: palette.primary[500],
93
- color: (0, accentText_1.onFilled)(palette.primary[500], palette.white, palette.black),
94
- },
95
- "::-moz-selection": {
96
- background: palette.primary[500],
97
- color: (0, accentText_1.onFilled)(palette.primary[500], palette.white, palette.black),
98
- },
91
+ "::selection": (() => {
92
+ const solid = (0, filledSurface_1.resolveFilledSurface)(palette.primary, palette);
93
+ return {
94
+ background: solid.fill,
95
+ color: solid.color,
96
+ };
97
+ })(),
98
+ "::-moz-selection": (() => {
99
+ const solid = (0, filledSurface_1.resolveFilledSurface)(palette.primary, palette);
100
+ return {
101
+ background: solid.fill,
102
+ color: solid.color,
103
+ };
104
+ })(),
99
105
  // `color-scheme: dark` gives WebKit/Blink a dark scrollbar by default, but it's the
100
106
  // OS's generic dark gray, not brand-aware.
101
107
  ...(0, scrollbar_1.globalScrollbarStyles)(palette),
@@ -0,0 +1,29 @@
1
+ import type { ColorScale, PaletteProps } from "../types";
2
+ /** Resolved fill + ink for a solid surface, including hover/active steps. */
3
+ export type FilledSurface = {
4
+ rung: keyof ColorScale;
5
+ fill: string;
6
+ color: string;
7
+ hoverRung: keyof ColorScale;
8
+ hoverFill: string;
9
+ hoverColor: string;
10
+ activeRung: keyof ColorScale;
11
+ activeFill: string;
12
+ activeColor: string;
13
+ };
14
+ /**
15
+ * Lightest rung on `scale` that still carries `white` at WCAG AA. Prefers [500] when it already
16
+ * passes; otherwise walks toward darker rungs. Used for solid fills on buttons, tags, badges and
17
+ * table status pills so consumers never get black ink on a saturated fill when white is achievable.
18
+ */
19
+ export declare const solidFillRung: (scale: ColorScale, white: string) => keyof ColorScale;
20
+ /** Hover (step 0) or active (step 1) fill rung, one step darker than `solidFillRung`. */
21
+ export declare const darkerFillRung: (scale: ColorScale, canvas: string, white: string, step: 0 | 1) => keyof ColorScale;
22
+ /** Label ink for a specific fill swatch — always `onFilled`, exported for style configs. */
23
+ export declare const labelOnFill: (fill: string, white: string, black: string) => string;
24
+ /**
25
+ * Consumer-facing helper: given any `ColorScale` (primary, red, semantic.error, …), return the
26
+ * fill rung and matching ink for solid / hover / active states. Use this whenever you paint a
27
+ * `bg` from a scale — never pair `scale[500]` with `onFilled` or `colors.white` by hand.
28
+ */
29
+ export declare const resolveFilledSurface: (scale: ColorScale, colors: Pick<PaletteProps, "white" | "black" | "backgroundColor">) => FilledSurface;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveFilledSurface = exports.labelOnFill = exports.darkerFillRung = exports.solidFillRung = void 0;
4
+ const color_1 = require("./color");
5
+ const accentText_1 = require("./accentText");
6
+ const RUNGS = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900];
7
+ /**
8
+ * The rung one/two steps DARKER than the accent — what a filled button's hover/active needs so its
9
+ * white label stays legible.
10
+ *
11
+ * Every dark scale runs dark -> light across 50 -> 900 (brand scales are rebuilt that way, utility
12
+ * hues are reversed), the mirror of light mode. So "darker than [500]" is [600]/[700] in light but
13
+ * [400]/[300] in dark.
14
+ */
15
+ const FILL_STEP_RUNGS = { light: [600, 700], dark: [400, 300] };
16
+ /**
17
+ * Lightest rung on `scale` that still carries `white` at WCAG AA. Prefers [500] when it already
18
+ * passes; otherwise walks toward darker rungs. Used for solid fills on buttons, tags, badges and
19
+ * table status pills so consumers never get black ink on a saturated fill when white is achievable.
20
+ */
21
+ const solidFillRung = (scale, white) => {
22
+ if ((0, color_1.contrastRatio)(scale[500], white) >= accentText_1.AA_NORMAL_TEXT)
23
+ return 500;
24
+ const passing = RUNGS.filter((r) => scale[r] && (0, color_1.contrastRatio)(scale[r], white) >= accentText_1.AA_NORMAL_TEXT);
25
+ if (!passing.length)
26
+ return 500;
27
+ return passing.reduce((a, b) => (0, color_1.contrastRatio)(scale[a], white) <= (0, color_1.contrastRatio)(scale[b], white) ? a : b);
28
+ };
29
+ exports.solidFillRung = solidFillRung;
30
+ const steppedRung = (base, canvas, step) => {
31
+ const dir = (0, accentText_1.isDarkCanvas)(canvas) ? -100 : 100;
32
+ return Math.min(900, Math.max(50, base + dir * step));
33
+ };
34
+ /** Hover (step 0) or active (step 1) fill rung, one step darker than `solidFillRung`. */
35
+ const darkerFillRung = (scale, canvas, white, step) => {
36
+ const base = (0, exports.solidFillRung)(scale, white);
37
+ if (base === 500) {
38
+ const mode = (0, accentText_1.isDarkCanvas)(canvas) ? "dark" : "light";
39
+ return FILL_STEP_RUNGS[mode][step];
40
+ }
41
+ const stepped = steppedRung(base, canvas, step === 0 ? 1 : 2);
42
+ return stepped;
43
+ };
44
+ exports.darkerFillRung = darkerFillRung;
45
+ /** Label ink for a specific fill swatch — always `onFilled`, exported for style configs. */
46
+ const labelOnFill = (fill, white, black) => (0, accentText_1.onFilled)(fill, white, black);
47
+ exports.labelOnFill = labelOnFill;
48
+ /**
49
+ * Consumer-facing helper: given any `ColorScale` (primary, red, semantic.error, …), return the
50
+ * fill rung and matching ink for solid / hover / active states. Use this whenever you paint a
51
+ * `bg` from a scale — never pair `scale[500]` with `onFilled` or `colors.white` by hand.
52
+ */
53
+ const resolveFilledSurface = (scale, colors) => {
54
+ const { white, black, backgroundColor } = colors;
55
+ const canvas = backgroundColor.main;
56
+ const rung = (0, exports.solidFillRung)(scale, white);
57
+ const fill = scale[rung];
58
+ const hoverRung = (0, exports.darkerFillRung)(scale, canvas, white, 0);
59
+ const hoverFill = scale[hoverRung];
60
+ const activeRung = (0, exports.darkerFillRung)(scale, canvas, white, 1);
61
+ const activeFill = scale[activeRung];
62
+ return {
63
+ rung,
64
+ fill,
65
+ color: (0, exports.labelOnFill)(fill, white, black),
66
+ hoverRung,
67
+ hoverFill,
68
+ hoverColor: (0, exports.labelOnFill)(hoverFill, white, black),
69
+ activeRung,
70
+ activeFill,
71
+ activeColor: (0, exports.labelOnFill)(activeFill, white, black),
72
+ };
73
+ };
74
+ exports.resolveFilledSurface = resolveFilledSurface;
@@ -45,6 +45,7 @@ exports.useDebounce = useDebounce;
45
45
  exports.globalSearchFilter = globalSearchFilter;
46
46
  const react_1 = __importStar(require("react"));
47
47
  const accentText_1 = require("../Theme/tokens/builders/accentText");
48
+ const filledSurface_1 = require("../Theme/tokens/builders/filledSurface");
48
49
  const statusTone_1 = require("../Theme/tokens/builders/statusTone");
49
50
  // Built once, not per comparison: sorting 10k rows runs this ~130k times, and constructing a
50
51
  // collator is orders of magnitude dearer than using one.
@@ -117,11 +118,13 @@ function buildTablePalette(theme) {
117
118
  ];
118
119
  return scales.map((scale) => {
119
120
  const tone = (0, statusTone_1.resolveStatusTone)(scale, mode);
121
+ const solidRung = (0, filledSurface_1.solidFillRung)(scale, c.white);
122
+ const solid = scale[solidRung];
120
123
  return {
121
- solid: scale[500],
124
+ solid,
122
125
  soft: tone.bg,
123
126
  text: tone.fg,
124
- onSolid: (0, accentText_1.onFilled)(scale[500], c.white, c.black),
127
+ onSolid: (0, filledSurface_1.labelOnFill)(solid, c.white, c.black),
125
128
  };
126
129
  });
127
130
  }
@@ -1,5 +1,5 @@
1
- import { accentTextOnCanvas, isDarkCanvas, onFilled } from "../../Theme/tokens/builders/accentText.js";
2
- import { solidRung, darkerFillRung } from "../../Theme/tokens/builders/solidFillRung.js";
1
+ import { accentTextOnCanvas } from "../../Theme/tokens/builders/accentText.js";
2
+ import { darkerFillRung, labelOnFill, solidFillRung, } from "../../Theme/tokens/builders/filledSurface.js";
3
3
  import { resolveGradient, gradientCss } from "../../Theme/tokens/builders/gradientInk.js";
4
4
  import { focusVisibleStyles } from "../../Theme/chakra/focusRing.styles.js";
5
5
  /**
@@ -19,14 +19,15 @@ const onCanvasHoverBg = (theme, colorScheme, step) => {
19
19
  const scale = theme.colors[colorScheme];
20
20
  return "opacity" in scale ? scale.opacity[step] : scale[50];
21
21
  };
22
- const buttonSolidRung = (theme, colorScheme) => solidRung(theme.colors[colorScheme], theme.colors.white);
22
+ const swatch = (theme, colorScheme) => theme.colors[colorScheme];
23
+ const solidRung = (theme, colorScheme) => solidFillRung(swatch(theme, colorScheme), theme.colors.white);
23
24
  const darkerFill = (theme, colorScheme, step) => {
24
- const scale = theme.colors[colorScheme];
25
- const isDark = isDarkCanvas(theme.colors.backgroundColor.main);
26
- return scale[darkerFillRung(scale, theme.colors.white, isDark, step)];
25
+ const scale = swatch(theme, colorScheme);
26
+ const rung = darkerFillRung(scale, theme.colors.backgroundColor.main, theme.colors.white, step);
27
+ return scale[rung];
27
28
  };
28
29
  /** Label for the solid variant's filled bg — derived from THAT fill, since hover/active swap it. */
29
- const labelFor = (theme, fill) => onFilled(fill, theme.colors.white, theme.colors.black);
30
+ const labelFor = (theme, fill) => labelOnFill(fill, theme.colors.white, theme.colors.black);
30
31
  /**
31
32
  * The two-tone `:focus-visible` ring, from the palette's derived `focusRing` pair.
32
33
  *
@@ -52,7 +53,7 @@ export const Button = {
52
53
  }),
53
54
  variants: {
54
55
  solid: ({ theme, colorScheme = "primary" }) => {
55
- const fill = theme.colors[colorScheme][buttonSolidRung(theme, colorScheme)];
56
+ const fill = theme.colors[colorScheme][solidRung(theme, colorScheme)];
56
57
  const hoverFill = darkerFill(theme, colorScheme, 0);
57
58
  const activeFill = darkerFill(theme, colorScheme, 1);
58
59
  const hoverLabel = labelFor(theme, hoverFill);
@@ -86,7 +87,7 @@ export const Button = {
86
87
  },
87
88
  outline: ({ theme, colorScheme = "primary" }) => {
88
89
  // Same rung as `solid`'s fill, not raw [500] — keeps hover bg AA-safe for white text.
89
- const hoverFill = theme.colors[colorScheme][buttonSolidRung(theme, colorScheme)];
90
+ const hoverFill = theme.colors[colorScheme][solidRung(theme, colorScheme)];
90
91
  const activeFill = darkerFill(theme, colorScheme, 0);
91
92
  const ink = onCanvasText(theme, colorScheme);
92
93
  return {
@@ -2,18 +2,24 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
2
2
  import { Box, Badge, Flex, GridItem, Heading, Icon, Text, VStack, Skeleton, SkeletonText, } from "@chakra-ui/react";
3
3
  import { Check } from "lucide-react";
4
4
  import { useCustomTheme } from "../../../Theme/useCustomTheme.js";
5
- import { onFilled } from "../../../Theme/tokens/builders/accentText.js";
5
+ import { resolveFilledSurface } from "../../../Theme/tokens/builders/filledSurface.js";
6
6
  import Button from "../../Button/Button.js";
7
7
  const getCardStyles = (isActive, isNextUpgrade, popular, theme) => {
8
- const withOnButtonColor = (styles) => ({
9
- ...styles,
10
- onButtonColor: onFilled(styles.buttonColor, theme.colors.white, theme.colors.black),
11
- });
8
+ const withOnButtonColor = (styles) => {
9
+ const scale = theme.colors[styles.buttonScale];
10
+ const solid = resolveFilledSurface(scale, theme.colors);
11
+ return {
12
+ ...styles,
13
+ buttonColor: solid.fill,
14
+ onButtonColor: solid.color,
15
+ };
16
+ };
12
17
  if (isActive) {
13
18
  return withOnButtonColor({
14
19
  badgeText: "Active Plan",
15
20
  badgeColor: `0.125rem solid ${theme.colors.green[500]}`,
16
21
  buttonColor: theme.colors.green[500],
22
+ buttonScale: "green",
17
23
  buttonColor50: theme.colors.green[50],
18
24
  colorScheme: "green",
19
25
  });
@@ -23,6 +29,7 @@ const getCardStyles = (isActive, isNextUpgrade, popular, theme) => {
23
29
  badgeText: "Upgrade Your Plan",
24
30
  badgeColor: `0.125rem solid ${theme.colors.primary[500]}`,
25
31
  buttonColor: theme.colors.primary[500],
32
+ buttonScale: "primary",
26
33
  buttonColor50: theme.colors.primary[50],
27
34
  colorScheme: "primary",
28
35
  });
@@ -32,6 +39,7 @@ const getCardStyles = (isActive, isNextUpgrade, popular, theme) => {
32
39
  badgeText: "Most Popular",
33
40
  badgeColor: `0.125rem solid ${theme.colors.primary[500]}`,
34
41
  buttonColor: theme.colors.primary[500],
42
+ buttonScale: "primary",
35
43
  buttonColor50: theme.colors.primary[50],
36
44
  colorScheme: "primary",
37
45
  });
@@ -40,6 +48,7 @@ const getCardStyles = (isActive, isNextUpgrade, popular, theme) => {
40
48
  badgeText: "",
41
49
  badgeColor: "",
42
50
  buttonColor: theme.colors.primary[500],
51
+ buttonScale: "primary",
43
52
  buttonColor50: theme.colors.primary[50],
44
53
  colorScheme: "primary",
45
54
  });
@@ -1,12 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { HStack, Text } from "@chakra-ui/react";
3
3
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
4
- import { onFilled } from "../../Theme/tokens/builders/accentText.js";
4
+ import { resolveFilledSurface } from "../../Theme/tokens/builders/filledSurface.js";
5
5
  const ErrorComponent = ({ error, errorClassName, }) => {
6
6
  const { colors } = useCustomTheme();
7
- const errorFill = colors.semanticText.error;
8
- // errorFill is ink, not a fill tuned to carry a mark — pick the mark's ink structurally.
9
- const markInk = onFilled(errorFill, colors.white, colors.black);
10
- return (_jsxs(HStack, { as: "p", align: "flex-start", spacing: 1, mt: 1, fontSize: "sm", color: errorFill, className: errorClassName, children: [_jsxs("svg", { width: "12", height: "12", viewBox: "0 0 100 100", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": true, children: [_jsx("circle", { cx: "50", cy: "50", r: "50", fill: errorFill }), _jsx("rect", { x: "46", y: "40", width: "8", height: "30", rx: "2", fill: markInk }), _jsx("circle", { cx: "50", cy: "28", r: "4", fill: markInk })] }), _jsx(Text, { as: "span", children: error })] }));
7
+ const errorText = colors.semanticText.error;
8
+ const errorSolid = resolveFilledSurface(colors.semantic.error, colors);
9
+ const errorFill = errorSolid.fill;
10
+ const markInk = errorSolid.color;
11
+ return (_jsxs(HStack, { as: "p", align: "flex-start", spacing: 1, mt: 1, fontSize: "sm", color: errorText, className: errorClassName, children: [_jsxs("svg", { width: "12", height: "12", viewBox: "0 0 100 100", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": true, children: [_jsx("circle", { cx: "50", cy: "50", r: "50", fill: errorFill }), _jsx("rect", { x: "46", y: "40", width: "8", height: "30", rx: "2", fill: markInk }), _jsx("circle", { cx: "50", cy: "28", r: "4", fill: markInk })] }), _jsx(Text, { as: "span", children: error })] }));
11
12
  };
12
13
  export default ErrorComponent;
@@ -4,7 +4,7 @@ import { format, startOfMonth, endOfMonth, startOfWeek, endOfWeek, addDays } fro
4
4
  import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
5
5
  import Button from "../Button/Button.js";
6
6
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
7
- import { onFilled } from "../../Theme/tokens/builders/accentText.js";
7
+ import { resolveFilledSurface } from "../../Theme/tokens/builders/filledSurface.js";
8
8
  import { DAY_CLASS, dayAccessibleName, dayStateClassName, resolveDayStateVisual, } from "./dayStates.js";
9
9
  export const CalendarPanel = ({ currentMonth, setCurrentMonth, today, isRange, tempDate, tempRangeStart, tempRangeEnd, isSameDay, isBefore, isAfter, minDate, maxDate, disablePastDates, disableFutureDates, disableToday, onDaySelect, hoveredDate, onDayHover, renderWeekdays, dayStates, renderDayContent, }) => {
10
10
  const theme = useCustomTheme();
@@ -95,16 +95,15 @@ export const CalendarPanel = ({ currentMonth, setCurrentMonth, today, isRange, t
95
95
  // Solid fill (selected/range-endpoint) needs the ink checked against that
96
96
  // specific fill — `primary[500]` doesn't reliably clear AA for white text on
97
97
  // every brand/mode (same gap the solid Button variant already accounts for).
98
- const solidFill = theme.colors.primary[500];
99
- const solidHoverFill = theme.colors.primary[600];
98
+ const primarySolid = resolveFilledSurface(theme.colors.primary, theme.colors);
99
+ const solidFill = primarySolid.fill;
100
+ const solidHoverFill = primarySolid.hoverFill;
100
101
  const circleColor = circleSolid
101
- ? onFilled(solidFill, theme.colors.white, theme.colors.black)
102
+ ? primarySolid.color
102
103
  : isInCurrentMonth
103
104
  ? theme.colors.text[700]
104
105
  : theme.colors.gray[400];
105
- const circleHoverColor = circleSolid
106
- ? onFilled(solidHoverFill, theme.colors.white, theme.colors.black)
107
- : circleColor;
106
+ const circleHoverColor = circleSolid ? primarySolid.hoverColor : circleColor;
108
107
  const circleBorder = circleSolid
109
108
  ? "1px solid transparent"
110
109
  : isTentativeEnd
@@ -4,6 +4,7 @@ import { Box, Flex, IconButton, Image, Modal, ModalBody, ModalCloseButton, Modal
4
4
  import { motion } from "framer-motion";
5
5
  import { Download, Eye, FileQuestion, Minus, Plus, RotateCw, } from "lucide-react";
6
6
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
7
+ import { labelOnFill, solidFillRung } from "../../Theme/tokens/builders/filledSurface.js";
7
8
  import ToolTip from "../ToolTip/ToolTip.js";
8
9
  const MotionContent = motion(ModalContent);
9
10
  const inferKind = (url, fileName) => {
@@ -56,7 +57,7 @@ export const FilePreview = ({ isOpen, onClose, fileUrl, fileName, fileType, hide
56
57
  if (kind === "video") {
57
58
  return (_jsx(Box, { as: "video", src: fileUrl, controls: true, width: "100%", borderRadius: "lg" }));
58
59
  }
59
- return (_jsxs(Flex, { direction: "column", align: "center", justify: "center", py: 12, gap: 3, children: [_jsx(FileQuestion, { size: 48, color: theme.colors.textMuted }), _jsx(Text, { color: theme.colors.textMuted, fontSize: "sm", children: "Preview isn't available for this file type." }), !hideDownload && (_jsxs(Flex, { as: "button", align: "center", gap: 2, px: 4, py: 2, borderRadius: "lg", bg: theme.colors.primary[500], color: theme.colors.onPrimary, fontSize: "sm", fontWeight: 500, onClick: () => downloadFile(fileUrl, fileName), children: [_jsx(Download, { size: 16 }), " Download file"] }))] }));
60
+ return (_jsxs(Flex, { direction: "column", align: "center", justify: "center", py: 12, gap: 3, children: [_jsx(FileQuestion, { size: 48, color: theme.colors.textMuted }), _jsx(Text, { color: theme.colors.textMuted, fontSize: "sm", children: "Preview isn't available for this file type." }), !hideDownload && (_jsxs(Flex, { as: "button", align: "center", gap: 2, px: 4, py: 2, borderRadius: "lg", bg: theme.colors.primary[solidFillRung(theme.colors.primary, theme.colors.white)], color: labelOnFill(theme.colors.primary[solidFillRung(theme.colors.primary, theme.colors.white)], theme.colors.white, theme.colors.black), fontSize: "sm", fontWeight: 500, onClick: () => downloadFile(fileUrl, fileName), children: [_jsx(Download, { size: 16 }), " Download file"] }))] }));
60
61
  };
61
62
  return (_jsxs(Modal, { isOpen: isOpen, onClose: handleClose, size: size, isCentered: true, children: [_jsx(ModalOverlay, { bg: "blackAlpha.600", backdropFilter: "blur(4px)" }), _jsxs(MotionContent
62
63
  // Chakra's default Modal drives its bg off `--modal-bg`, which flips to
@@ -4,10 +4,9 @@ import Select from "../../Select/Select.js";
4
4
  import { CirclePlus, SquarePen } from "lucide-react";
5
5
  import VeritcalDivider from "../../Divider/Divider.js";
6
6
  import { useCustomTheme } from "../../../Theme/useCustomTheme.js";
7
- import { onFilled } from "../../../Theme/tokens/builders/accentText.js";
8
7
  import Button from "../../Button/Button.js";
9
8
  const KanbanActions = ({ options, onSelectChange, onEdit, onCreate, }) => {
10
9
  const { colors } = useCustomTheme();
11
- return (_jsxs(Box, { display: "flex", alignItems: "center", gap: "0.625rem", children: [_jsx(Select, { options: options, placeholder: "Filter by Status", width: "12.5rem", onChange: (option) => onSelectChange && onSelectChange(option) }), _jsxs(Box, { display: "flex", alignItems: "center", gap: "0.5rem", children: [_jsx(Button, { size: "sm", variant: "ghost", leftIcon: _jsx(SquarePen, { size: 20, color: colors.text[500] }), onClick: () => onEdit === null || onEdit === void 0 ? void 0 : onEdit(), children: "Edit Layout" }), _jsx(VeritcalDivider, {}), _jsx(Button, { size: "sm", variant: "solid", leftIcon: _jsx(CirclePlus, { size: 20, color: onFilled(colors.primary[500], colors.white, colors.black) }), onClick: () => onCreate === null || onCreate === void 0 ? void 0 : onCreate(), children: "Create New" })] })] }));
10
+ return (_jsxs(Box, { display: "flex", alignItems: "center", gap: "0.625rem", children: [_jsx(Select, { options: options, placeholder: "Filter by Status", width: "12.5rem", onChange: (option) => onSelectChange && onSelectChange(option) }), _jsxs(Box, { display: "flex", alignItems: "center", gap: "0.5rem", children: [_jsx(Button, { size: "sm", variant: "ghost", leftIcon: _jsx(SquarePen, { size: 20, color: colors.text[500] }), onClick: () => onEdit === null || onEdit === void 0 ? void 0 : onEdit(), children: "Edit Layout" }), _jsx(VeritcalDivider, {}), _jsx(Button, { size: "sm", variant: "solid", leftIcon: _jsx(CirclePlus, { size: 20 }), onClick: () => onCreate === null || onCreate === void 0 ? void 0 : onCreate(), children: "Create New" })] })] }));
12
11
  };
13
12
  export default KanbanActions;
@@ -3,7 +3,8 @@ import { useMemo, useState } from "react";
3
3
  import { Avatar, Badge, Box, Flex, Heading, HStack, IconButton, Input, Skeleton, SkeletonText, Spinner, Text, Tooltip, VStack, } from "@chakra-ui/react";
4
4
  import { ArrowLeft, Building2, Check, CheckCircle2, Crown, Globe, Mail, Pencil, Plus, Trash2, Users, X, } from "lucide-react";
5
5
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
6
- import { accentTextOnCanvas, isDarkCanvas, onFilled } from "../../Theme/tokens/builders/accentText.js";
6
+ import { accentTextOnCanvas, isDarkCanvas } from "../../Theme/tokens/builders/accentText.js";
7
+ import { resolveFilledSurface } from "../../Theme/tokens/builders/filledSurface.js";
7
8
  import { resolveStatusTone } from "../../Theme/tokens/builders/statusTone.js";
8
9
  import Button from "../Button/Button.js";
9
10
  import EmptyState from "../EmptyState/EmptyState.js";
@@ -67,7 +68,7 @@ const OrganizationDetails = ({ activeOrganizations, invitedOrganizations, isLoad
67
68
  const pageBg = colors.backgroundColor.main;
68
69
  const primary50 = colors.primary[50];
69
70
  const primary100 = colors.primary[100];
70
- const primary500 = colors.primary[500];
71
+ const primarySolid = resolveFilledSurface(colors.primary, colors);
71
72
  const onPrimary50 = accentTextOnCanvas(colors.primary, colors.primary[50]);
72
73
  const cardSx = {
73
74
  backgroundColor: surface,
@@ -153,7 +154,7 @@ const OrganizationDetails = ({ activeOrganizations, invitedOrganizations, isLoad
153
154
  width: "100%",
154
155
  };
155
156
  const hasOrganizations = activeOrganizations.length > 0 || invitedOrganizations.length > 0;
156
- return (_jsxs(Box, { backgroundColor: pageBg, minHeight: "100%", p: { base: 2, md: 3 }, children: [_jsxs(Flex, { ...cardSx, px: 3, py: 2.5, mb: 3, alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", gap: 3, bgGradient: `linear(135deg, ${primary50} 0%, ${primary100} 100%)`, children: [_jsxs(Flex, { alignItems: "center", gap: 3, children: [onBack && (_jsx(IconButton, { "aria-label": "Go back", icon: _jsx(ArrowLeft, { size: 18 }), variant: "ghost", size: "sm", color: subtle, onClick: onBack })), _jsx(Flex, { align: "center", justify: "center", boxSize: "36px", borderRadius: "full", bg: primary500, color: onFilled(primary500, colors.white, colors.black), children: _jsx(Building2, { size: 18 }) }), _jsxs(Box, { children: [_jsxs(HStack, { spacing: 2, children: [_jsx(Heading, { size: "sm", color: heading, fontWeight: 700, children: userName
157
+ return (_jsxs(Box, { backgroundColor: pageBg, minHeight: "100%", p: { base: 2, md: 3 }, children: [_jsxs(Flex, { ...cardSx, px: 3, py: 2.5, mb: 3, alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", gap: 3, bgGradient: `linear(135deg, ${primary50} 0%, ${primary100} 100%)`, children: [_jsxs(Flex, { alignItems: "center", gap: 3, children: [onBack && (_jsx(IconButton, { "aria-label": "Go back", icon: _jsx(ArrowLeft, { size: 18 }), variant: "ghost", size: "sm", color: subtle, onClick: onBack })), _jsx(Flex, { align: "center", justify: "center", boxSize: "36px", borderRadius: "full", bg: primarySolid.fill, color: primarySolid.color, children: _jsx(Building2, { size: 18 }) }), _jsxs(Box, { children: [_jsxs(HStack, { spacing: 2, children: [_jsx(Heading, { size: "sm", color: heading, fontWeight: 700, children: userName
157
158
  ? `${labels.greeting.replace(/User!?/, "")}${userName}!`.trim()
158
159
  : labels.greeting }), _jsx(Avatar, { size: "xs", name: userName, src: userAvatarUrl })] }), _jsx(Text, { fontSize: "xs", color: subtle, mt: 0.5, children: labels.manageSubtitle })] })] }), _jsx(Button, { label: labels.createNewOrganization, onClick: () => setCreateOpen(true), leftIcon: _jsx(Plus, { size: 16 }), colorScheme: "primary", size: "sm" })] }), isLoading ? (_jsx(Box, { ...gridSx, children: Array.from({ length: 6 }).map((_, idx) => (_jsxs(Box, { ...cardSx, p: 3, children: [_jsx(Skeleton, { boxSize: "36px", borderRadius: "lg", mb: 2 }), _jsx(SkeletonText, { noOfLines: 2, spacing: 2 })] }, idx))) })) : !hasOrganizations ? (_jsx(EmptyState, { icon: Building2, title: labels.noOrganizationsTitle, description: labels.noOrganizationsDescription, minH: "40vh", action: _jsx(Button, { label: labels.createOrganization, onClick: () => setCreateOpen(true), leftIcon: _jsx(Plus, { size: 16 }), colorScheme: "primary", size: "sm" }) })) : (_jsxs(VStack, { align: "stretch", spacing: 4, children: [activeOrganizations.length > 0 && (_jsxs(Box, { children: [_jsxs(Flex, { align: "center", gap: 2, mb: 2, children: [_jsx(Users, { size: 16, color: colors.accentText }), _jsx(Heading, { size: "sm", color: heading, fontWeight: 600, children: labels.activeOrganizations }), sectionBadge(activeOrganizations.length, "blue")] }), _jsx(Box, { ...gridSx, children: activeOrganizations.map(renderActiveCard) })] })), invitedOrganizations.length > 0 && (_jsxs(Box, { children: [_jsxs(Flex, { align: "center", gap: 2, mb: 2, children: [_jsx(Mail, { size: 16, color: colors.semanticText.warning }), _jsx(Heading, { size: "sm", color: heading, fontWeight: 600, children: labels.invitedOrganizations }), sectionBadge(invitedOrganizations.length, "yellow")] }), _jsx(Box, { ...gridSx, children: invitedOrganizations.map(renderInvitedCard) })] }))] })), footerSlot, _jsx(CreateOrgModal, { isOpen: isCreateOpen, onClose: () => setCreateOpen(false), isLoading: isCreating, onSubmit: async (values) => {
159
160
  await (onCreateOrganization === null || onCreateOrganization === void 0 ? void 0 : onCreateOrganization(values));
@@ -3,7 +3,8 @@ import { useRef, useState } from "react";
3
3
  import { Box, Image, IconButton, Input, Text, Tooltip, HStack, } from "@chakra-ui/react";
4
4
  import { Eye, FileText, SquarePen, User } from "lucide-react";
5
5
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
6
- import { accentTextOnCanvas, onFilled } from "../../Theme/tokens/builders/accentText.js";
6
+ import { accentTextOnCanvas } from "../../Theme/tokens/builders/accentText.js";
7
+ import { labelOnFill, solidFillRung } from "../../Theme/tokens/builders/filledSurface.js";
7
8
  export default function ProfilePhotoViewer({ photoUrl, onPhotoChange, imageWidth = "100px", imageAlt = "Profile Photo", imageObjectFit = "cover", imageBorderRadius = "full", editIconSize = "sm", editIconPositionRight = "0px", editIconPositionBottom = "0px", isRound = true, boxStyle, isEditable = false, isView = false, style, handleIsView, fallbackText, revealOnHover = true, }) {
8
9
  var _a, _b, _c, _d, _e;
9
10
  const [photo, setPhoto] = useState(photoUrl);
@@ -57,14 +58,14 @@ export default function ProfilePhotoViewer({ photoUrl, onPhotoChange, imageWidth
57
58
  "&:hover .ppv-media": {
58
59
  boxShadow: `0 0 0 0.1875rem ${c.primary.opacity[24]}`,
59
60
  },
60
- }, children: [_jsx(Box, { className: "ppv-media", borderRadius: imageBorderRadius, transition: "box-shadow 0.2s ease", children: renderMedia() }), hasActions && (_jsxs(_Fragment, { children: [_jsx(Box, { className: "ppv-overlay", position: "absolute", inset: 0, borderRadius: imageBorderRadius, bg: "blackAlpha.300", opacity: 0, transition: "opacity 0.2s ease", pointerEvents: "none" }), _jsxs(HStack, { className: "ppv-actions", position: "absolute", right: editIconPositionRight, bottom: editIconPositionBottom, transform: "translate(-15%, -15%)", spacing: 1.5, opacity: revealOnHover ? 0 : 1, transition: "opacity 0.2s ease", children: [isEditable && (_jsx(Tooltip, { label: "Edit", "aria-label": "Edit", hasArrow: true, children: _jsx(IconButton, { icon: _jsx(SquarePen, { size: 14 }), isRound: isRound, size: editIconSize, onClick: handleClick, "aria-label": "Edit photo", bg: c.primary[500], color: onFilled(c.primary[500], c.white, c.black), border: `0.125rem solid ${c.background[50]}`, boxShadow: (_b = theme.shadows) === null || _b === void 0 ? void 0 : _b.md, style: style, transition: "transform 0.2s ease, background 0.2s ease, box-shadow 0.2s ease", _hover: {
61
+ }, children: [_jsx(Box, { className: "ppv-media", borderRadius: imageBorderRadius, transition: "box-shadow 0.2s ease", children: renderMedia() }), hasActions && (_jsxs(_Fragment, { children: [_jsx(Box, { className: "ppv-overlay", position: "absolute", inset: 0, borderRadius: imageBorderRadius, bg: "blackAlpha.300", opacity: 0, transition: "opacity 0.2s ease", pointerEvents: "none" }), _jsxs(HStack, { className: "ppv-actions", position: "absolute", right: editIconPositionRight, bottom: editIconPositionBottom, transform: "translate(-15%, -15%)", spacing: 1.5, opacity: revealOnHover ? 0 : 1, transition: "opacity 0.2s ease", children: [isEditable && (_jsx(Tooltip, { label: "Edit", "aria-label": "Edit", hasArrow: true, children: _jsx(IconButton, { icon: _jsx(SquarePen, { size: 14 }), isRound: isRound, size: editIconSize, onClick: handleClick, "aria-label": "Edit photo", bg: c.primary[solidFillRung(c.primary, c.white)], color: labelOnFill(c.primary[solidFillRung(c.primary, c.white)], c.white, c.black), border: `0.125rem solid ${c.background[50]}`, boxShadow: (_b = theme.shadows) === null || _b === void 0 ? void 0 : _b.md, style: style, transition: "transform 0.2s ease, background 0.2s ease, box-shadow 0.2s ease", _hover: {
61
62
  bg: c.primary[600],
62
- color: onFilled(c.primary[600], c.white, c.black),
63
+ color: labelOnFill(c.primary[600], c.white, c.black),
63
64
  transform: "scale(1.1)",
64
65
  boxShadow: (_c = theme.shadows) === null || _c === void 0 ? void 0 : _c.lg,
65
66
  }, _active: {
66
67
  bg: c.primary[700],
67
- color: onFilled(c.primary[700], c.white, c.black),
68
+ color: labelOnFill(c.primary[700], c.white, c.black),
68
69
  } }) })), isView && (_jsx(Tooltip, { label: "View", "aria-label": "View", hasArrow: true, children: _jsx(IconButton, { icon: _jsx(Eye, { size: 14 }), isRound: isRound, size: editIconSize, onClick: handleIsView, "aria-label": "View photo", bg: c.background[50], color: c.text[700], border: `0.063rem solid ${border}`, boxShadow: (_d = theme.shadows) === null || _d === void 0 ? void 0 : _d.md, style: style, transition: "transform 0.2s ease, background 0.2s ease, box-shadow 0.2s ease", _hover: {
69
70
  bg: c.gray[50],
70
71
  color: accentTextOnCanvas(c.primary, c.gray[50]),
@@ -5,7 +5,7 @@ import { ChevronUp } from "lucide-react";
5
5
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
6
6
  import ToolTip from "../ToolTip/ToolTip.js";
7
7
  import { rafThrottle } from "../../Utils/rafThrottle.js";
8
- import { onFilled } from "../../Theme/tokens/builders/accentText.js";
8
+ import { labelOnFill, solidFillRung } from "../../Theme/tokens/builders/filledSurface.js";
9
9
  const ScrollToTop = ({ children, tooltipLabel = "Scroll to top", threshold = 300, duration = 600, useWindow = false, bottom = "2rem", right = "2rem", }) => {
10
10
  const [visible, setVisible] = useState(false);
11
11
  const anchorRef = useRef(null);
@@ -58,9 +58,9 @@ const ScrollToTop = ({ children, tooltipLabel = "Scroll to top", threshold = 300
58
58
  };
59
59
  // eslint-disable-next-line react-hooks/exhaustive-deps
60
60
  }, [useWindow, threshold]);
61
- return (_jsxs(Box, { ref: anchorRef, position: "relative", children: [children, _jsx(ToolTip, { label: tooltipLabel, placement: "left", children: _jsx(Box, { as: "button", type: "button", onClick: scrollToTop, "aria-label": tooltipLabel, border: "none", position: "fixed", bottom: bottom, right: right, zIndex: 1000, display: "flex", alignItems: "center", justifyContent: "center", boxSize: "44px", borderRadius: "full", cursor: "pointer", bg: theme.colors.primary[500], color: theme.colors.onPrimary, boxShadow: "md", opacity: visible ? 1 : 0, transform: visible ? "translateY(0) scale(1)" : "translateY(16px) scale(0.85)", pointerEvents: visible ? "auto" : "none", transition: "all 0.25s cubic-bezier(0.16, 1, 0.3, 1)", _hover: {
61
+ return (_jsxs(Box, { ref: anchorRef, position: "relative", children: [children, _jsx(ToolTip, { label: tooltipLabel, placement: "left", children: _jsx(Box, { as: "button", type: "button", onClick: scrollToTop, "aria-label": tooltipLabel, border: "none", position: "fixed", bottom: bottom, right: right, zIndex: 1000, display: "flex", alignItems: "center", justifyContent: "center", boxSize: "44px", borderRadius: "full", cursor: "pointer", bg: theme.colors.primary[solidFillRung(theme.colors.primary, theme.colors.white)], color: labelOnFill(theme.colors.primary[solidFillRung(theme.colors.primary, theme.colors.white)], theme.colors.white, theme.colors.black), boxShadow: "md", opacity: visible ? 1 : 0, transform: visible ? "translateY(0) scale(1)" : "translateY(16px) scale(0.85)", pointerEvents: visible ? "auto" : "none", transition: "all 0.25s cubic-bezier(0.16, 1, 0.3, 1)", _hover: {
62
62
  bg: theme.colors.primary[600],
63
- color: onFilled(theme.colors.primary[600], theme.colors.white, theme.colors.black),
63
+ color: labelOnFill(theme.colors.primary[600], theme.colors.white, theme.colors.black),
64
64
  transform: "translateY(-2px) scale(1.05)",
65
65
  boxShadow: "lg",
66
66
  }, _active: { transform: "scale(0.95)" }, children: _jsx(ChevronUp, { size: 24, strokeWidth: 2.5 }) }) })] }));
@@ -243,7 +243,7 @@ BottomIcon = false, BottomText, handleBottomClick, BottomTextColor, isColorOptio
243
243
  document.removeEventListener("mousedown", handleClickOutside);
244
244
  };
245
245
  }, [isOpen]);
246
- return (_jsx(_Fragment, { children: _jsx(FormControl, { isInvalid: error, children: _jsxs(Box, { display: "flex", flexDirection: "column", position: "relative", sx: boxStyle, children: [label && (_jsx(TextLabel, { label: label, id: id, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), isMultipleSelect && selectedOptions.length > 0 && (_jsx(HStack, { spacing: 2, mb: 2, children: selectedOptions.map((option) => (_jsxs(Tag, { size: "md", borderRadius: "full", variant: "solid", sx: { backgroundColor: theme.colors.primary[500] }, children: [_jsx(TagLabel, { width: "50px", children: option.label }), _jsx(TagCloseButton, { onClick: () => handleRemoveOption(option) })] }, option.id))) })), _jsxs(InputGroup, { children: [_jsx(Input, { ref: inputRef, variant: "outline", borderRadius: FIELD_RADIUS, value: inputValue ? inputValue : "", onClick: () => setIsOpen(true), onFocus: () => {
246
+ return (_jsx(_Fragment, { children: _jsx(FormControl, { isInvalid: error, children: _jsxs(Box, { display: "flex", flexDirection: "column", position: "relative", sx: boxStyle, children: [label && (_jsx(TextLabel, { label: label, id: id, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), isMultipleSelect && selectedOptions.length > 0 && (_jsx(HStack, { spacing: 2, mb: 2, children: selectedOptions.map((option) => (_jsxs(Tag, { size: "md", borderRadius: "full", variant: "solid", colorScheme: "primary", children: [_jsx(TagLabel, { width: "50px", children: option.label }), _jsx(TagCloseButton, { onClick: () => handleRemoveOption(option) })] }, option.id))) })), _jsxs(InputGroup, { children: [_jsx(Input, { ref: inputRef, variant: "outline", borderRadius: FIELD_RADIUS, value: inputValue ? inputValue : "", onClick: () => setIsOpen(true), onFocus: () => {
247
247
  if (skipNextInputFocusOpen.current) {
248
248
  skipNextInputFocusOpen.current = false;
249
249
  return;
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { useEffect, 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 { onFilled } from "../../Theme/tokens/builders/accentText.js";
5
+ import { labelOnFill, solidFillRung } from "../../Theme/tokens/builders/filledSurface.js";
6
6
  import { getSidebarActiveAccent } from "./sidebarAccentColors.js";
7
7
  import { FlexCss, HEADER_HEIGHT } from "../../Constants/Sidebar.js";
8
8
  import { ArrowLeftToLine, ArrowRightToLine, ChevronLeft, Maximize2, MoreVertical, PanelLeft, Plus, X } from "lucide-react";
@@ -27,7 +27,9 @@ const SidebarHeader = ({ logo, companyName, companySubtitle, toggle, isLoading,
27
27
  if (isLoading) {
28
28
  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: "md", 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: "md", startColor: theme.colors.sidebar.background[400], endColor: theme.colors.sidebar.background[300] }), _jsx(Skeleton, { h: "1.25rem", w: "60%", borderRadius: "md", startColor: theme.colors.sidebar.background[400], endColor: theme.colors.sidebar.background[300] })] })) }));
29
29
  }
30
- const logoNode = logo ? (_jsx(Image, { borderRadius: "md", boxSize: "1.75rem", src: logo, alt: "Company Logo", flexShrink: 0, cursor: toggle ? "pointer" : undefined, onClick: toggle ? onToggle : undefined })) : (_jsx(Box, { bg: theme.colors.primary[500], color: onFilled(theme.colors.primary[500], theme.colors.white, theme.colors.black), borderRadius: "md", boxSize: "1.75rem", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: "bold", flexShrink: 0, cursor: toggle ? "pointer" : undefined, onClick: toggle ? onToggle : undefined, children: _jsx(DefaultLogo, {}) }));
30
+ const primaryFillRung = solidFillRung(theme.colors.primary, theme.colors.white);
31
+ const primaryFill = theme.colors.primary[primaryFillRung];
32
+ const logoNode = logo ? (_jsx(Image, { borderRadius: "md", 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: "md", boxSize: "1.75rem", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: "bold", flexShrink: 0, cursor: toggle ? "pointer" : undefined, onClick: toggle ? onToggle : undefined, children: _jsx(DefaultLogo, {}) }));
31
33
  return (_jsxs(Flex, { h: HEADER_HEIGHT, w: "100%", alignItems: "center", justifyContent: toggle ? "center" : "flex-start", gap: "8px", px: toggle ? "8px" : "10px", borderBottom: "1px solid", borderColor: "whiteAlpha.100", minW: 0, overflow: "hidden", flexShrink: 0, children: [logoNode, !toggle && (_jsxs(Box, { flex: "1", minW: 0, children: [_jsx(OverflowTooltipText, { placement: "right", fontWeight: 600, fontSize: "12.5px", textAlign: "left", color: theme.colors.white, lineHeight: "1.3", as: "p", width: "100%", children: companyName !== null && companyName !== void 0 ? companyName : "" }), companySubtitle && (_jsx(Text, { fontSize: "10px", 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: "base", bg: "whiteAlpha.100", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0, _hover: { bg: "whiteAlpha.300" }, transition: "background 0.15s", children: overlay ? (_jsx(X, { size: 15, color: theme.colors.sidebar.mutedIcon })) : (_jsx(ChevronLeft, { size: 14, color: theme.colors.sidebar.mutedIcon })) }))] }));
32
34
  };
33
35
  const SkeletonMenuRow = ({ toggle }) => {
@@ -1,14 +1,16 @@
1
- import { accentTextOnCanvas, onFilled } from "../../Theme/tokens/builders/accentText.js";
1
+ import { accentTextOnCanvas } from "../../Theme/tokens/builders/accentText.js";
2
+ import { resolveFilledSurface } from "../../Theme/tokens/builders/filledSurface.js";
2
3
  /** Exhaustive by construction: a new scheme that maps nowhere is a compile error. */
3
4
  const scaleFor = (colors, scheme) => scheme === "primary" || scheme === "secondary" || scheme === "tertiary"
4
5
  ? colors[scheme]
5
6
  : colors.semantic[scheme];
6
7
  /** Resolve a chevron palette for a given color scheme from the theme. */
7
8
  export const resolveStagePalette = (theme, colorScheme = "primary") => {
8
- const { gray, white, black } = theme.colors;
9
+ const { gray } = theme.colors;
9
10
  const scale = scaleFor(theme.colors, colorScheme);
10
- const strong = scale[500];
11
- const onStrong = onFilled(strong, white, black);
11
+ const solid = resolveFilledSurface(scale, theme.colors);
12
+ const strong = solid.fill;
13
+ const onStrong = solid.color;
12
14
  const soft = scale[100];
13
15
  // A fixed [700] fails AA against [100] for some hues (orange 3.30, borderline green 3.58) —
14
16
  // walk the scale's own rungs against this specific tint instead.
@@ -18,7 +20,7 @@ export const resolveStagePalette = (theme, colorScheme = "primary") => {
18
20
  softText,
19
21
  strong,
20
22
  onStrong,
21
- hover: scale[600],
23
+ hover: solid.hoverFill,
22
24
  muted: gray[100],
23
25
  mutedText: gray[500],
24
26
  };
@@ -7,12 +7,12 @@ import LeftFilterPane from "./filters/LeftFilterPane.js";
7
7
  import { TABLE_VARIANTS } from "./variants/index.js";
8
8
  import { TableVariantProvider } from "./variants/TableVariantContext.js";
9
9
  import { isDarkCanvas } from "../../Theme/tokens/builders/accentText.js";
10
+ import { labelOnFill, solidFillRung } from "../../Theme/tokens/builders/filledSurface.js";
10
11
  import Pagination from "./components/Pagination.js";
11
12
  import TableHeader from "./components/TableHeader.js";
12
13
  import TableBody from "./components/TableBody.js";
13
14
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
14
15
  import { scrollbarStyles, SCROLLBAR_WIDTH } from "../../Theme/tokens/builders/scrollbar.js";
15
- import { scrollShadowStyles } from "../../Theme/tokens/builders/scrollShadow.js";
16
16
  import useTable from "./hooks/useTable.js";
17
17
  import { searchAndSortData, SortMultiColumnData, groupRows, buildTablePalette, pickTableColor } from "../../Utils/table.js";
18
18
  import { useGetPreferences, useSavePreferences, } from "../../Hooks/usePreferences.js";
@@ -365,7 +365,7 @@ export default function Table({ data, columns, onSelection, isLoading, isCheckbo
365
365
  // Square children poked past the rounded border, leaving a gap at each corner.
366
366
  overflow: "hidden", children: [filterSidebar && filterMode === "modal" && (_jsxs(Modal, { isOpen: isFilterModalOpen, onClose: onFilterModalClose, size: "4xl", scrollBehavior: "inside", children: [_jsx(ModalOverlay, {}), _jsxs(ModalContent, { bg: theme.colors.background[50], 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: (_c = filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.sidebarOptions) !== null && _c !== void 0 ? _c : [], 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: controlsHeight + tableMaxH }, minHeight: (filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.isFilterSidebar) ? "32rem" : "auto", children: _jsx(LeftFilterPane, { height: controlsHeight + tableMaxH, 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: 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: controlsHeight, gap: 3, flexWrap: "nowrap", bg: theme.colors.background[50], borderBottom: `0.063rem solid ${theme.colors.boxborder[200]}`, children: [filterSidebar && (_jsxs(_Fragment, { children: [_jsx(ToolTip, { label: "Filter", placement: "top", children: _jsxs(Box, { position: "relative", display: "inline-block", children: [_jsx(Icon, { as: Filter, transform: "scaleX(-1)", cursor: "pointer", boxSize: 4, color: sidebarActiveCount > 0 ? theme.colors.accentText : theme.colors.text[500], onClick: filterMode === "modal" ? onFilterModalOpen : filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.filterSidebarToggle, _hover: {
367
367
  color: theme.colors.accentText,
368
- } }), sidebarActiveCount > 0 && (_jsx(Box, { position: "absolute", top: "-6px", right: "-10px", bg: theme.colors.primary[500], color: theme.colors.onPrimary, borderRadius: "full", p: "1px", cursor: "pointer", onClick: (e) => {
368
+ } }), sidebarActiveCount > 0 && (_jsx(Box, { position: "absolute", top: "-6px", right: "-10px", bg: theme.colors.primary[solidFillRung(theme.colors.primary, theme.colors.white)], color: labelOnFill(theme.colors.primary[solidFillRung(theme.colors.primary, theme.colors.white)], theme.colors.white, theme.colors.black), borderRadius: "full", p: "1px", cursor: "pointer", onClick: (e) => {
369
369
  var _a;
370
370
  e.stopPropagation();
371
371
  if (filterSidebar === null || filterSidebar === void 0 ? void 0 : filterSidebar.onClearAllHandler) {
@@ -394,7 +394,6 @@ export default function Table({ data, columns, onSelection, isLoading, isCheckbo
394
394
  }, children: _jsx(RefreshCw, { size: 16 }) }) })] })), headerActions && (_jsxs(_Fragment, { children: [_jsx(VeritcalDivider, {}), _jsx(HeaderActions, { actions: headerActions, selections: selection })] })), _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, { columns: columns, currentPage: currentPage, setCurrentPage: setCurrentPage, rowsPerPage: rowsPerPage, pages: pages, paginationText: tablePaginationText, handlePageSizeChange: handlePageSizeChange, dataLength: tableData.length, isServerPagination: isServerPagination, paginationSelectOptions: paginationSelectOptions, isVisiblity: true }) })), (isPagination || isServerPagination) && !isGrouped && !canInfinite && isCompactHeader && tableData.length > 0 && (_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: {
395
395
  color: theme.colors.accentText,
396
396
  }, onClick: () => setIsPaginationPopoverOpen((open) => !open) }) }), _jsx(Portal, { children: _jsx(PopoverContent, { maxW: "22rem", p: 2, zIndex: 1600, bg: theme.colors.background[50], boxShadow: "lg", children: _jsx(PopoverBody, { p: 0, children: _jsx(Pagination, { columns: columns, currentPage: currentPage, setCurrentPage: setCurrentPage, rowsPerPage: rowsPerPage, pages: pages, paginationText: tablePaginationText, handlePageSizeChange: handlePageSizeChange, dataLength: tableData.length, isServerPagination: isServerPagination, paginationSelectOptions: paginationSelectOptions, isVisiblity: true }) }) }) })] }))] })] }), _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: {
397
- ...scrollShadowStyles(theme.colors.background[50]),
398
397
  ...scrollbarStyles(theme.colors),
399
398
  // Compact rows hide the horizontal bar until hover to keep the row height.
400
399
  '&::-webkit-scrollbar': {
@@ -168,6 +168,6 @@ const LeftFilterPane = ({ title = "Filter", height = 300, sections, selected: se
168
168
  }
169
169
  return filteredSections.map((sec) => (_jsxs(Box, { children: [_jsx(Box, { px: 3, py: 2, borderBottom: "1px solid", borderColor: theme.colors.boxborder[200], children: _jsx(SectionLabel, { label: sec.label, theme: theme }) }), _jsx(Box, { px: 3, pt: 2, pb: 1, children: _jsx(SectionContent, { sec: sec, ...sectionContentProps }) })] }, sec.id)));
170
170
  };
171
- return (_jsxs(Box, { width: filterMode === "modal" ? "100%" : "180px", height: filterMode === "modal" ? "100%" : height, minHeight: "32rem", bg: theme.colors.background[50], borderRight: "1px solid", borderColor: theme.colors.boxborder[200], borderRadius: "md", overflow: "hidden", display: "flex", flexDirection: "column", marginBottom: filterMode === "modal" && hasActiveFilters ? '3.5rem' : 0, children: [_jsx(Box, { p: 3, borderBottom: "1px solid", borderColor: theme.colors.boxborder[200], children: !isSearching ? (_jsxs(Flex, { align: "center", justify: "space-between", children: [_jsx(Text, { fontWeight: "semibold", fontSize: "sm", children: title }), _jsx(IconButton, { "aria-label": "Search filters", icon: _jsx(Icon, { as: Search, transform: "scaleX(-1)", boxSize: 4 }), variant: "unstyled", minW: "auto", h: "auto", display: "flex", cursor: "pointer", color: theme.colors.text[500], onClick: () => setIsSearching(true), mr: filterMode === "modal" ? 8 : 2, mt: filterMode === "modal" ? -1 : 0 })] })) : (_jsx(motion.div, { ref: searchRef, initial: { opacity: 0, x: 40 }, animate: { opacity: 1, x: 0 }, transition: { type: "tween", duration: 0.2 }, children: _jsxs(InputGroup, { size: "sm", children: [_jsx(InputLeftElement, { pointerEvents: "none", children: _jsx(Search, { size: 16, color: theme.colors.text[500] }) }), _jsx(Input, { placeholder: "Search", value: search, onChange: (e) => setSearch(e.target.value), autoFocus: true }), search.length > 0 && (_jsx(InputRightElement, { children: _jsx(IconButton, { "aria-label": "Clear", size: "xs", variant: "ghost", icon: _jsx(X, { size: 14 }), onClick: () => { setSearch(""); setIsSearching(false); } }) }))] }) })) }), _jsx(Box, { flex: "1", overflowY: "auto", children: renderSections() }), hasActiveFilters && (_jsxs(HStack, { px: 2, py: 1, borderTop: "1px solid", borderColor: theme.colors.boxborder[200], spacing: 2, position: filterMode === "modal" ? "absolute" : "relative", bottom: 0, left: 0, right: 0, bg: theme.colors.background[50], children: [_jsx(Button, { flex: 1, variant: "outline", size: "sm", onClick: handleClear, fontSize: "xs", colorScheme: "red", children: "Clear All" }), _jsx(Button, { flex: 1, colorScheme: "primary", color: theme.colors.onPrimary, size: "sm", onClick: handleApply, fontSize: "xs", isLoading: isApplyLoading, children: "Apply" })] }))] }));
171
+ return (_jsxs(Box, { width: filterMode === "modal" ? "100%" : "180px", height: filterMode === "modal" ? "100%" : height, minHeight: "32rem", bg: theme.colors.background[50], borderRight: "1px solid", borderColor: theme.colors.boxborder[200], borderRadius: "md", overflow: "hidden", display: "flex", flexDirection: "column", marginBottom: filterMode === "modal" && hasActiveFilters ? '3.5rem' : 0, children: [_jsx(Box, { p: 3, borderBottom: "1px solid", borderColor: theme.colors.boxborder[200], children: !isSearching ? (_jsxs(Flex, { align: "center", justify: "space-between", children: [_jsx(Text, { fontWeight: "semibold", fontSize: "sm", children: title }), _jsx(IconButton, { "aria-label": "Search filters", icon: _jsx(Icon, { as: Search, transform: "scaleX(-1)", boxSize: 4 }), variant: "unstyled", minW: "auto", h: "auto", display: "flex", cursor: "pointer", color: theme.colors.text[500], onClick: () => setIsSearching(true), mr: filterMode === "modal" ? 8 : 2, mt: filterMode === "modal" ? -1 : 0 })] })) : (_jsx(motion.div, { ref: searchRef, initial: { opacity: 0, x: 40 }, animate: { opacity: 1, x: 0 }, transition: { type: "tween", duration: 0.2 }, children: _jsxs(InputGroup, { size: "sm", children: [_jsx(InputLeftElement, { pointerEvents: "none", children: _jsx(Search, { size: 16, color: theme.colors.text[500] }) }), _jsx(Input, { placeholder: "Search", value: search, onChange: (e) => setSearch(e.target.value), autoFocus: true }), search.length > 0 && (_jsx(InputRightElement, { children: _jsx(IconButton, { "aria-label": "Clear", size: "xs", variant: "ghost", icon: _jsx(X, { size: 14 }), onClick: () => { setSearch(""); setIsSearching(false); } }) }))] }) })) }), _jsx(Box, { flex: "1", overflowY: "auto", children: renderSections() }), hasActiveFilters && (_jsxs(HStack, { px: 2, py: 1, borderTop: "1px solid", borderColor: theme.colors.boxborder[200], spacing: 2, position: filterMode === "modal" ? "absolute" : "relative", bottom: 0, left: 0, right: 0, bg: theme.colors.background[50], children: [_jsx(Button, { flex: 1, variant: "outline", size: "sm", onClick: handleClear, fontSize: "xs", colorScheme: "red", children: "Clear All" }), _jsx(Button, { flex: 1, colorScheme: "primary", size: "sm", onClick: handleApply, fontSize: "xs", isLoading: isApplyLoading, children: "Apply" })] }))] }));
172
172
  };
173
173
  export default LeftFilterPane;