pixelize-design-library 2.4.2-beta.5 → 2.4.2

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 (136) hide show
  1. package/dist/Components/Button/Button.d.ts +2 -2
  2. package/dist/Components/Button/Button.js +3 -3
  3. package/dist/Components/Button/Button.styles.js +29 -3
  4. package/dist/Components/Button/ButtonProps.d.ts +6 -1
  5. package/dist/Components/ButtonGroupIcon/ButtonGroupIcon.js +1 -1
  6. package/dist/Components/Card/Card.d.ts +1 -1
  7. package/dist/Components/Card/Card.js +2 -2
  8. package/dist/Components/Card/CardProps.d.ts +0 -1
  9. package/dist/Components/Checkbox/Checkbox.js +1 -1
  10. package/dist/Components/Checkbox/Checkbox.styles.js +2 -0
  11. package/dist/Components/DatePicker/RangeDatePicker.js +1 -1
  12. package/dist/Components/DatePicker/SingleDatePicker.js +1 -1
  13. package/dist/Components/FileUpload/FileUpload.js +3 -2
  14. package/dist/Components/FileUpload/FileUploadProps.d.ts +3 -1
  15. package/dist/Components/FileUpload/constants.js +1 -0
  16. package/dist/Components/FilterSidebar/FilterSidebar.js +2 -2
  17. package/dist/Components/Form/FormWrapper.js +1 -1
  18. package/dist/Components/Input/TextInput.styles.js +6 -8
  19. package/dist/Components/InputTextArea/InputTextArea.style.js +5 -4
  20. package/dist/Components/NavigationBar/NavigationBar.js +3 -3
  21. package/dist/Components/NoteTextArea/NoteTextArea.js +5 -3
  22. package/dist/Components/NumberInput/NumberInput.js +3 -1
  23. package/dist/Components/NumberInput/NumberInput.styles.js +5 -4
  24. package/dist/Components/Primitives/Primitives.d.ts +6 -0
  25. package/dist/Components/Primitives/Primitives.js +113 -0
  26. package/dist/Components/ProfileCard/ProfileCard.js +1 -1
  27. package/dist/Components/RadioButton/RadioButton.js +1 -1
  28. package/dist/Components/Search/Search.js +2 -2
  29. package/dist/Components/SearchSelect/SearchSelect.js +2 -1
  30. package/dist/Components/Select/Select.d.ts +1 -1
  31. package/dist/Components/Select/Select.js +4 -2
  32. package/dist/Components/Select/Select.styles.js +2 -1
  33. package/dist/Components/Select/SelectProps.d.ts +3 -0
  34. package/dist/Components/SelectSearch/SelectSearch.js +1 -1
  35. package/dist/Components/SelectV2/SelectV2.js +3 -2
  36. package/dist/Components/SideBar/SecondaryBar.js +1 -1
  37. package/dist/Components/SideBar/SideBar.js +1 -1
  38. package/dist/Components/Table/Table.d.ts +1 -1
  39. package/dist/Components/Table/Table.js +10 -4
  40. package/dist/Components/Table/TableProps.d.ts +4 -0
  41. package/dist/Components/Table/components/Pagination.js +1 -1
  42. package/dist/Components/Table/components/TableActions.js +2 -2
  43. package/dist/Components/Table/components/TableBody.js +40 -11
  44. package/dist/Components/Table/components/TableGroupRow.js +1 -1
  45. package/dist/Components/Table/components/TableHeader.js +21 -8
  46. package/dist/Components/Table/components/TableSearch.js +1 -1
  47. package/dist/Components/Table/settings/ManageColumns.js +1 -1
  48. package/dist/Components/Table/settings/TableSettings.js +2 -2
  49. package/dist/Components/Table/variants/TableVariantContext.d.ts +4 -0
  50. package/dist/Components/Table/variants/TableVariantContext.js +17 -0
  51. package/dist/Components/Table/variants/classic.d.ts +6 -0
  52. package/dist/Components/Table/variants/classic.js +47 -0
  53. package/dist/Components/Table/variants/index.d.ts +7 -0
  54. package/dist/Components/Table/variants/index.js +27 -0
  55. package/dist/Components/Table/variants/pillInk.d.ts +6 -0
  56. package/dist/Components/Table/variants/pillInk.js +21 -0
  57. package/dist/Components/Table/variants/studio.d.ts +6 -0
  58. package/dist/Components/Table/variants/studio.js +50 -0
  59. package/dist/Components/Table/variants/tokens.d.ts +49 -0
  60. package/dist/Components/Table/variants/tokens.js +2 -0
  61. package/dist/Components/Trail/TrailWorks.js +1 -1
  62. package/dist/Theme/chakra/Menu.styles.d.ts +2 -0
  63. package/dist/Theme/chakra/Menu.styles.js +5 -3
  64. package/dist/Theme/chakra/Popover.styles.d.ts +3 -0
  65. package/dist/Theme/chakra/Popover.styles.js +5 -1
  66. package/dist/Theme/chakra/componentStyles.d.ts +5 -0
  67. package/dist/Theme/provider/ThemeSwitcher.js +5 -2
  68. package/dist/Theme/tokens/builders/chartColorsFromTheme.js +1 -1
  69. package/dist/Theme/tokens/builders/index.d.ts +1 -0
  70. package/dist/Theme/tokens/builders/index.js +1 -0
  71. package/dist/Theme/tokens/builders/outlineRung.d.ts +27 -3
  72. package/dist/Theme/tokens/builders/outlineRung.js +55 -5
  73. package/dist/Theme/tokens/builders/placeholderInk.d.ts +19 -0
  74. package/dist/Theme/tokens/builders/placeholderInk.js +35 -0
  75. package/dist/Theme/tokens/builders/resolvedRungs.d.ts +5 -1
  76. package/dist/Theme/tokens/builders/resolvedRungs.js +7 -2
  77. package/dist/Theme/tokens/builders/surfaceRungs.d.ts +5 -2
  78. package/dist/Theme/tokens/builders/surfaceRungs.js +19 -9
  79. package/dist/esm/Components/Button/Button.js +4 -4
  80. package/dist/esm/Components/Button/Button.styles.js +29 -3
  81. package/dist/esm/Components/ButtonGroupIcon/ButtonGroupIcon.js +1 -1
  82. package/dist/esm/Components/Card/Card.js +2 -2
  83. package/dist/esm/Components/Checkbox/Checkbox.js +1 -1
  84. package/dist/esm/Components/Checkbox/Checkbox.styles.js +2 -0
  85. package/dist/esm/Components/DatePicker/RangeDatePicker.js +1 -1
  86. package/dist/esm/Components/DatePicker/SingleDatePicker.js +1 -1
  87. package/dist/esm/Components/FileUpload/FileUpload.js +4 -3
  88. package/dist/esm/Components/FileUpload/constants.js +1 -0
  89. package/dist/esm/Components/FilterSidebar/FilterSidebar.js +2 -2
  90. package/dist/esm/Components/Form/FormWrapper.js +1 -1
  91. package/dist/esm/Components/Input/TextInput.styles.js +6 -8
  92. package/dist/esm/Components/InputTextArea/InputTextArea.style.js +5 -4
  93. package/dist/esm/Components/NavigationBar/NavigationBar.js +3 -3
  94. package/dist/esm/Components/NoteTextArea/NoteTextArea.js +5 -3
  95. package/dist/esm/Components/NumberInput/NumberInput.js +4 -2
  96. package/dist/esm/Components/NumberInput/NumberInput.styles.js +5 -4
  97. package/dist/esm/Components/Primitives/Primitives.js +6 -0
  98. package/dist/esm/Components/ProfileCard/ProfileCard.js +1 -1
  99. package/dist/esm/Components/RadioButton/RadioButton.js +1 -1
  100. package/dist/esm/Components/Search/Search.js +2 -2
  101. package/dist/esm/Components/SearchSelect/SearchSelect.js +2 -1
  102. package/dist/esm/Components/Select/Select.js +5 -3
  103. package/dist/esm/Components/Select/Select.styles.js +2 -1
  104. package/dist/esm/Components/SelectSearch/SelectSearch.js +1 -1
  105. package/dist/esm/Components/SelectV2/SelectV2.js +3 -2
  106. package/dist/esm/Components/SideBar/SecondaryBar.js +1 -1
  107. package/dist/esm/Components/SideBar/SideBar.js +1 -1
  108. package/dist/esm/Components/Table/Table.js +10 -4
  109. package/dist/esm/Components/Table/components/Pagination.js +1 -1
  110. package/dist/esm/Components/Table/components/TableActions.js +2 -2
  111. package/dist/esm/Components/Table/components/TableBody.js +41 -12
  112. package/dist/esm/Components/Table/components/TableGroupRow.js +1 -1
  113. package/dist/esm/Components/Table/components/TableHeader.js +21 -8
  114. package/dist/esm/Components/Table/components/TableSearch.js +1 -1
  115. package/dist/esm/Components/Table/settings/ManageColumns.js +1 -1
  116. package/dist/esm/Components/Table/settings/TableSettings.js +2 -2
  117. package/dist/esm/Components/Table/variants/TableVariantContext.js +13 -0
  118. package/dist/esm/Components/Table/variants/classic.js +43 -0
  119. package/dist/esm/Components/Table/variants/index.js +9 -0
  120. package/dist/esm/Components/Table/variants/pillInk.js +18 -0
  121. package/dist/esm/Components/Table/variants/studio.js +46 -0
  122. package/dist/esm/Components/Table/variants/tokens.js +1 -0
  123. package/dist/esm/Components/Trail/TrailWorks.js +1 -1
  124. package/dist/esm/Theme/chakra/Menu.styles.js +5 -3
  125. package/dist/esm/Theme/chakra/Popover.styles.js +5 -1
  126. package/dist/esm/Theme/provider/ThemeSwitcher.js +5 -2
  127. package/dist/esm/Theme/tokens/builders/chartColorsFromTheme.js +1 -1
  128. package/dist/esm/Theme/tokens/builders/index.js +1 -0
  129. package/dist/esm/Theme/tokens/builders/outlineRung.js +52 -4
  130. package/dist/esm/Theme/tokens/builders/placeholderInk.js +29 -0
  131. package/dist/esm/Theme/tokens/builders/resolvedRungs.js +7 -2
  132. package/dist/esm/Theme/tokens/builders/surfaceRungs.js +20 -10
  133. package/dist/esm/index.js +2 -0
  134. package/dist/index.d.ts +4 -1
  135. package/dist/index.js +9 -1
  136. package/package.json +4 -2
@@ -21,8 +21,12 @@ const baseStyle = definePartsStyle(({ theme }) => {
21
21
  content: {
22
22
  [$popperBg.variable]: colors.backgroundColor.light,
23
23
  bg: $popperBg.reference,
24
- [$arrowShadowColor.variable]: colors.border[200],
24
+ [$arrowShadowColor.variable]: colors.boxborder[200],
25
25
  color: colors.text[900],
26
+ // Matches Menu: a CHROME_RULE-weight edge, not Chakra's gray.200 hard edge.
27
+ borderWidth: "1px",
28
+ borderStyle: "solid",
29
+ borderColor: colors.boxborder[200],
26
30
  },
27
31
  };
28
32
  });
@@ -73,6 +73,8 @@ export declare const componentStyles: {
73
73
  [x: string]: string;
74
74
  bg: string;
75
75
  color: string;
76
+ borderWidth: string;
77
+ borderStyle: string;
76
78
  borderColor: string;
77
79
  };
78
80
  item: {
@@ -143,6 +145,9 @@ export declare const componentStyles: {
143
145
  [x: string]: string;
144
146
  bg: string;
145
147
  color: string;
148
+ borderWidth: string;
149
+ borderStyle: string;
150
+ borderColor: string;
146
151
  };
147
152
  }) | undefined;
148
153
  sizes?: {
@@ -26,7 +26,10 @@ const toBrandLabel = (brand) => brand.charAt(0).toUpperCase() + brand.slice(1);
26
26
  * regardless of which brand/mode is currently active.
27
27
  */
28
28
  const brandSwatchColor = (brand) => index_1.brandThemes[brand].light.colors.primary[500];
29
- const BrandSwatch = ({ brand }) => ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-block", w: "0.625rem", h: "0.625rem", borderRadius: "full", bg: brandSwatchColor(brand), border: "1px solid", borderColor: "whiteAlpha.300", flexShrink: 0 }));
29
+ const BrandSwatch = ({ brand }) => {
30
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
31
+ return ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", display: "inline-block", w: "0.625rem", h: "0.625rem", borderRadius: "full", bg: brandSwatchColor(brand), border: "1px solid", borderColor: colors.boxborder[200], flexShrink: 0 }));
32
+ };
30
33
  /**
31
34
  * Palette values already differ per color mode (`brandThemes[brand].light|dark`), so tokens
32
35
  * are read straight from the active theme — no `useColorModeValue` pairing needed here.
@@ -39,7 +42,7 @@ const useSwitcherColors = () => {
39
42
  activeColor: colors.primary[500],
40
43
  mutedColor: colors.text[600],
41
44
  hoverBg: colors.gray[100],
42
- borderColor: colors.border[200],
45
+ borderColor: colors.boxborder[200],
43
46
  // NOTE: menuBg lives in Menu.styles.ts — re-pushing it via `sx` flickers on every render.
44
47
  menuColor: colors.text[900],
45
48
  };
@@ -34,7 +34,7 @@ function chartInk(colors) {
34
34
  surface,
35
35
  text: colors.text[900],
36
36
  muted: colors.text[500],
37
- grid: colors.border[500],
37
+ grid: colors.boxborder[200],
38
38
  axis: colors.text[500],
39
39
  tooltipBg: colors.backgroundColor.secondary,
40
40
  };
@@ -5,3 +5,4 @@ export * from "./chartColorsFromTheme";
5
5
  export * from "./color";
6
6
  export * from "./scrollbar";
7
7
  export * from "./gradientInk";
8
+ export * from "./placeholderInk";
@@ -21,3 +21,4 @@ __exportStar(require("./chartColorsFromTheme"), exports);
21
21
  __exportStar(require("./color"), exports);
22
22
  __exportStar(require("./scrollbar"), exports);
23
23
  __exportStar(require("./gradientInk"), exports);
24
+ __exportStar(require("./placeholderInk"), exports);
@@ -7,6 +7,22 @@ import type { PaletteProps } from "../types";
7
7
  export declare const MIN_PERCEPTIBLE_STEP = 1.15;
8
8
  /** WCAG 1.4.11 — a control outline is a UI component boundary, held to 3:1. */
9
9
  export declare const AA_NON_TEXT = 3;
10
+ /**
11
+ * Resting chrome — card, popover and field outlines — settles here, not at `AA_NON_TEXT`.
12
+ * At 3:1 a container border is text-weight and the UI reads as a wireframe; every mainstream
13
+ * system draws this line far lighter (Tailwind gray-200 1.24, Chakra gray.200 1.30, Material
14
+ * outline-variant 1.61). 1.4.11 asks that a control be identifiable, not that its resting
15
+ * border carry the whole job: the fill, the label and the focus ring do that, and the focus
16
+ * ring is still held to `AA_NON_TEXT`.
17
+ */
18
+ export declare const CHROME_BORDER = 1.5;
19
+ export declare const CHROME_RULE = 1.31;
20
+ /**
21
+ * A rule is decorative, so it has a ceiling and no floor: soften it until the surface it reads
22
+ * hardest against sits at `target`, and leave a already-fainter rung alone. Never `settleAcross`
23
+ * here — that clears a floor on EVERY surface, so one tinted surface drags the rule darker.
24
+ */
25
+ export declare function ruleInk(hex: string, surfaces: readonly string[], target: number): string;
10
26
  /**
11
27
  * Walks a hex toward `target` contrast against `backdrop`, keeping hue and saturation.
12
28
  * Direction is DERIVED from the backdrop, never passed: a mode argument here was redundant
@@ -21,9 +37,10 @@ export declare function liftToContrast(hex: string, backdrop: string, target?: n
21
37
  export declare function softenToContrast(hex: string, backdrop: string, target: number): string;
22
38
  /**
23
39
  * `boxborder[500]` is the rung every control outline reads (Checkbox, SearchSelect, the date
24
- * pickers, the editor's inputs). It was authored as a decorative value measured 1.30-2.56:1
25
- * across brands, so those controls rendered effectively borderless in BOTH modes. Resolved here
26
- * rather than hand-pinned per brand: a copied hex goes stale the moment a canvas moves.
40
+ * pickers, the editor's inputs). Settled onto `CHROME_BORDER` lifted when a brand authored it
41
+ * invisibly pale, softened when it overshoots. It was previously lifted to `AA_NON_TEXT`, which
42
+ * shipped 3.85-4.95:1 outlines: a text-weight box around every card and popover.
43
+ * Resolved here rather than hand-pinned per brand: a copied hex goes stale the moment a canvas moves.
27
44
  *
28
45
  * `border[*]` is deliberately untouched — that ramp draws table gridlines, which are decorative
29
46
  * and outside 1.4.11.
@@ -38,3 +55,10 @@ export declare function withOutlineRung(palette: PaletteProps): PaletteProps;
38
55
  * its OWN list background, not necessarily the page canvas.
39
56
  */
40
57
  export declare function resolveHoverTint(seed: string, restSurface: string): string;
58
+ /**
59
+ * Settles ink into `target` against EVERY surface at once. Softening one step can change which
60
+ * surface is hardest, so resolving against a single pre-computed "hardest" one lands under the
61
+ * floor on another — that is how radiant and rosewood ended up with an invisible outline on
62
+ * their muted surface.
63
+ */
64
+ export declare function settleAcross(hex: string, surfaces: readonly string[], target: number): string;
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AA_NON_TEXT = exports.MIN_PERCEPTIBLE_STEP = void 0;
3
+ exports.CHROME_RULE = exports.CHROME_BORDER = exports.AA_NON_TEXT = exports.MIN_PERCEPTIBLE_STEP = void 0;
4
+ exports.ruleInk = ruleInk;
4
5
  exports.liftToContrast = liftToContrast;
5
6
  exports.softenToContrast = softenToContrast;
6
7
  exports.withOutlineRung = withOutlineRung;
7
8
  exports.resolveHoverTint = resolveHoverTint;
9
+ exports.settleAcross = settleAcross;
8
10
  const color_1 = require("./color");
9
11
  /**
10
12
  * The floor a hover/active state's step off its own resting surface must clear to be seen at
@@ -14,6 +16,29 @@ const color_1 = require("./color");
14
16
  exports.MIN_PERCEPTIBLE_STEP = 1.15;
15
17
  /** WCAG 1.4.11 — a control outline is a UI component boundary, held to 3:1. */
16
18
  exports.AA_NON_TEXT = 3;
19
+ /**
20
+ * Resting chrome — card, popover and field outlines — settles here, not at `AA_NON_TEXT`.
21
+ * At 3:1 a container border is text-weight and the UI reads as a wireframe; every mainstream
22
+ * system draws this line far lighter (Tailwind gray-200 1.24, Chakra gray.200 1.30, Material
23
+ * outline-variant 1.61). 1.4.11 asks that a control be identifiable, not that its resting
24
+ * border carry the whole job: the fill, the label and the focus ring do that, and the focus
25
+ * ring is still held to `AA_NON_TEXT`.
26
+ */
27
+ exports.CHROME_BORDER = 1.5;
28
+ // The resting rule between two surfaces — a card edge, a divider, a menu outline. Lighter than
29
+ // CHROME_BORDER, which outlines a control the user acts on.
30
+ exports.CHROME_RULE = 1.31;
31
+ /**
32
+ * A rule is decorative, so it has a ceiling and no floor: soften it until the surface it reads
33
+ * hardest against sits at `target`, and leave a already-fainter rung alone. Never `settleAcross`
34
+ * here — that clears a floor on EVERY surface, so one tinted surface drags the rule darker.
35
+ */
36
+ function ruleInk(hex, surfaces, target) {
37
+ const loudest = surfaces.reduce((worst, s) => (0, color_1.contrastRatio)(hex, s) > (0, color_1.contrastRatio)(hex, worst) ? s : worst);
38
+ return (0, color_1.contrastRatio)(hex, loudest) > target
39
+ ? softenToContrast(hex, loudest, target)
40
+ : hex;
41
+ }
17
42
  /**
18
43
  * Walks a hex toward `target` contrast against `backdrop`, keeping hue and saturation.
19
44
  * Direction is DERIVED from the backdrop, never passed: a mode argument here was redundant
@@ -57,9 +82,10 @@ function softenToContrast(hex, backdrop, target) {
57
82
  }
58
83
  /**
59
84
  * `boxborder[500]` is the rung every control outline reads (Checkbox, SearchSelect, the date
60
- * pickers, the editor's inputs). It was authored as a decorative value measured 1.30-2.56:1
61
- * across brands, so those controls rendered effectively borderless in BOTH modes. Resolved here
62
- * rather than hand-pinned per brand: a copied hex goes stale the moment a canvas moves.
85
+ * pickers, the editor's inputs). Settled onto `CHROME_BORDER` lifted when a brand authored it
86
+ * invisibly pale, softened when it overshoots. It was previously lifted to `AA_NON_TEXT`, which
87
+ * shipped 3.85-4.95:1 outlines: a text-weight box around every card and popover.
88
+ * Resolved here rather than hand-pinned per brand: a copied hex goes stale the moment a canvas moves.
63
89
  *
64
90
  * `border[*]` is deliberately untouched — that ramp draws table gridlines, which are decorative
65
91
  * and outside 1.4.11.
@@ -72,7 +98,9 @@ function withOutlineRung(palette) {
72
98
  (0, color_1.contrastRatio)(current, palette.background[50])
73
99
  ? palette.backgroundColor.main
74
100
  : palette.background[50];
75
- const resolved = liftToContrast(current, backdrop);
101
+ const resolved = (0, color_1.contrastRatio)(current, backdrop) > exports.CHROME_BORDER
102
+ ? softenToContrast(current, backdrop, exports.CHROME_BORDER)
103
+ : liftToContrast(current, backdrop, exports.CHROME_BORDER);
76
104
  if (resolved === current)
77
105
  return palette;
78
106
  return { ...palette, boxborder: { ...palette.boxborder, 500: resolved } };
@@ -88,3 +116,25 @@ function withOutlineRung(palette) {
88
116
  function resolveHoverTint(seed, restSurface) {
89
117
  return liftToContrast(seed, restSurface, exports.MIN_PERCEPTIBLE_STEP);
90
118
  }
119
+ /**
120
+ * Settles ink into `target` against EVERY surface at once. Softening one step can change which
121
+ * surface is hardest, so resolving against a single pre-computed "hardest" one lands under the
122
+ * floor on another — that is how radiant and rosewood ended up with an invisible outline on
123
+ * their muted surface.
124
+ */
125
+ function settleAcross(hex, surfaces, target) {
126
+ const clearsAll = (c) => surfaces.every((s) => (0, color_1.contrastRatio)(c, s) >= target);
127
+ if (!clearsAll(hex)) {
128
+ return surfaces.reduce((ink, s) => liftToContrast(ink, s, target), hex);
129
+ }
130
+ const { s: sat, l: start } = (0, color_1.hexToHsl)(hex);
131
+ const toward = (0, color_1.relativeLuminance)(surfaces[0]) < 0.5 ? -1 : 1;
132
+ let settled = hex;
133
+ for (let l = start; l > 0 && l < 100; l += toward) {
134
+ const next = (0, color_1.withLightness)(hex, l, sat);
135
+ if (!clearsAll(next))
136
+ break;
137
+ settled = next;
138
+ }
139
+ return settled;
140
+ }
@@ -0,0 +1,19 @@
1
+ import type { PaletteProps } from "../types";
2
+ /** A field always renders on at least one surface — the first is the reference backdrop. */
3
+ export type FieldSurfaces = readonly [string, ...string[]];
4
+ /**
5
+ * The hint ink for a field: the brand's authored rung settled onto `PLACEHOLDER_TEXT` against the
6
+ * hardest surface a field can land on — lifted when it falls short, softened when it overshoots.
7
+ *
8
+ * Settled rather than floored because the authored rungs measured 3.96-7.73:1 across the brands,
9
+ * and anything much past the floor reads as a field already typed into. The floor is the look:
10
+ * one hint weight for every brand in both modes, instead of a per-brand accident.
11
+ */
12
+ export declare const placeholderInkOn: (palette: PaletteProps, surfaces: FieldSurfaces) => string;
13
+ /**
14
+ * Every surface an ENABLED field renders on. Disabled fields are deliberately absent — 1.4.3
15
+ * exempts them, and folding their dimmer fill in here would darken the hint on every other field.
16
+ */
17
+ export declare const fieldSurfaces: (palette: PaletteProps) => FieldSurfaces;
18
+ /** The hint ink every field in this library reads. Takes no backdrop: see `fieldSurfaces`. */
19
+ export declare const placeholderInk: (palette: PaletteProps) => string;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.placeholderInk = exports.fieldSurfaces = exports.placeholderInkOn = void 0;
4
+ const color_1 = require("./color");
5
+ const outlineRung_1 = require("./outlineRung");
6
+ const surfaceRungs_1 = require("./surfaceRungs");
7
+ /**
8
+ * The hint ink for a field: the brand's authored rung settled onto `PLACEHOLDER_TEXT` against the
9
+ * hardest surface a field can land on — lifted when it falls short, softened when it overshoots.
10
+ *
11
+ * Settled rather than floored because the authored rungs measured 3.96-7.73:1 across the brands,
12
+ * and anything much past the floor reads as a field already typed into. The floor is the look:
13
+ * one hint weight for every brand in both modes, instead of a per-brand accident.
14
+ */
15
+ const placeholderInkOn = (palette, surfaces) => {
16
+ const rung = palette.placeholder[500];
17
+ const hardest = surfaces.reduce((worst, s) => (0, color_1.contrastRatio)(rung, s) < (0, color_1.contrastRatio)(rung, worst) ? s : worst);
18
+ return (0, color_1.contrastRatio)(rung, hardest) > surfaceRungs_1.PLACEHOLDER_TEXT
19
+ ? (0, outlineRung_1.softenToContrast)(rung, hardest, surfaceRungs_1.PLACEHOLDER_TEXT)
20
+ : (0, outlineRung_1.liftToContrast)(rung, hardest, surfaceRungs_1.PLACEHOLDER_TEXT);
21
+ };
22
+ exports.placeholderInkOn = placeholderInkOn;
23
+ /**
24
+ * Every surface an ENABLED field renders on. Disabled fields are deliberately absent — 1.4.3
25
+ * exempts them, and folding their dimmer fill in here would darken the hint on every other field.
26
+ */
27
+ const fieldSurfaces = (palette) => [
28
+ palette.gray[50],
29
+ palette.background[50],
30
+ palette.backgroundColor.main,
31
+ ];
32
+ exports.fieldSurfaces = fieldSurfaces;
33
+ /** The hint ink every field in this library reads. Takes no backdrop: see `fieldSurfaces`. */
34
+ const placeholderInk = (palette) => (0, exports.placeholderInkOn)(palette, (0, exports.fieldSurfaces)(palette));
35
+ exports.placeholderInk = placeholderInk;
@@ -1,6 +1,10 @@
1
1
  import { AA_NON_TEXT } from "./outlineRung";
2
2
  import type { PaletteProps } from "../types";
3
- /** Placeholder text measured 4.32:1 on a card for 8 of 9 brands — text, so held to 4.5:1. */
3
+ /**
4
+ * A hint is floored at 3:1, not 4.5:1. Held to body-text contrast it stopped reading as a hint —
5
+ * an empty field looked like one already typed into — and the published library ships this rung
6
+ * as the brand authored it. See CHROME-CONSISTENCY.md.
7
+ */
4
8
  export declare function withPlaceholderRung(palette: PaletteProps): PaletteProps;
5
9
  /** The hover row is a SURFACE, so it steps away from the ink rather than the ink moving. */
6
10
  export declare function withTableHoverRung(palette: PaletteProps): PaletteProps;
@@ -6,9 +6,14 @@ exports.withTableHoverRung = withTableHoverRung;
6
6
  const outlineRung_1 = require("./outlineRung");
7
7
  Object.defineProperty(exports, "AA_NON_TEXT", { enumerable: true, get: function () { return outlineRung_1.AA_NON_TEXT; } });
8
8
  const accentText_1 = require("./accentText");
9
- /** Placeholder text measured 4.32:1 on a card for 8 of 9 brands — text, so held to 4.5:1. */
9
+ const surfaceRungs_1 = require("./surfaceRungs");
10
+ /**
11
+ * A hint is floored at 3:1, not 4.5:1. Held to body-text contrast it stopped reading as a hint —
12
+ * an empty field looked like one already typed into — and the published library ships this rung
13
+ * as the brand authored it. See CHROME-CONSISTENCY.md.
14
+ */
10
15
  function withPlaceholderRung(palette) {
11
- const resolved = (0, outlineRung_1.liftToContrast)(palette.placeholder[500], palette.background[50], accentText_1.AA_NORMAL_TEXT);
16
+ const resolved = (0, outlineRung_1.liftToContrast)(palette.placeholder[500], palette.background[50], surfaceRungs_1.PLACEHOLDER_TEXT);
12
17
  if (resolved === palette.placeholder[500])
13
18
  return palette;
14
19
  return { ...palette, placeholder: { ...palette.placeholder, 500: resolved } };
@@ -1,6 +1,9 @@
1
1
  import type { PaletteProps } from "../types";
2
- /** Clear of the 4.5 gate, but well under body text so a hint never reads as a value. */
3
- export declare const PLACEHOLDER_TEXT = 5;
2
+ /**
3
+ * A hint is held to the non-text floor, not the body-text one. Deliberate: at 4.5 an empty field
4
+ * reads as one already typed into. See CHROME-CONSISTENCY.md.
5
+ */
6
+ export declare const PLACEHOLDER_TEXT = 3;
4
7
  export declare const namedSurfaces: (palette: PaletteProps) => string[];
5
8
  /** The surface an ink is closest to — clearing it clears every other one. */
6
9
  export declare const hardestSurface: (ink: string, surfaces: string[]) => string;
@@ -6,8 +6,11 @@ const color_1 = require("./color");
6
6
  const outlineRung_1 = require("./outlineRung");
7
7
  const accentText_1 = require("./accentText");
8
8
  const semanticText_1 = require("./semanticText");
9
- /** Clear of the 4.5 gate, but well under body text so a hint never reads as a value. */
10
- exports.PLACEHOLDER_TEXT = 5;
9
+ /**
10
+ * A hint is held to the non-text floor, not the body-text one. Deliberate: at 4.5 an empty field
11
+ * reads as one already typed into. See CHROME-CONSISTENCY.md.
12
+ */
13
+ exports.PLACEHOLDER_TEXT = outlineRung_1.AA_NON_TEXT;
11
14
  const namedSurfaces = (palette) => [
12
15
  ...Object.values(palette.backgroundColor),
13
16
  palette.background[50],
@@ -21,7 +24,8 @@ exports.hardestSurface = hardestSurface;
21
24
  function withSurfaceRungs(palette) {
22
25
  const surfaces = (0, exports.namedSurfaces)(palette);
23
26
  const lift = (ink, target) => (0, outlineRung_1.liftToContrast)(ink, (0, exports.hardestSurface)(ink, surfaces), target);
24
- const soften = (ink, target) => (0, outlineRung_1.softenToContrast)(ink, (0, exports.hardestSurface)(ink, surfaces), target);
27
+ const settle = (ink, target) => (0, outlineRung_1.settleAcross)(ink, surfaces, target);
28
+ const rule = (ink) => (0, outlineRung_1.ruleInk)(ink, [palette.backgroundColor.main, palette.background[50]], outlineRung_1.CHROME_RULE);
25
29
  const semanticText = semanticText_1.SEMANTIC_TONES.reduce((acc, tone) => {
26
30
  acc[tone] = lift(palette.semanticText[tone], accentText_1.AA_NORMAL_TEXT);
27
31
  return acc;
@@ -33,12 +37,18 @@ function withSurfaceRungs(palette) {
33
37
  semanticText,
34
38
  text: { ...palette.text, 500: lift(palette.text[500], accentText_1.AA_NORMAL_TEXT) },
35
39
  header: { ...palette.header, 500: lift(palette.header[500], accentText_1.AA_NORMAL_TEXT) },
36
- // Placeholder must stay legible without reading as a filled value: the ramp delivered
37
- // 6.85:1, level with `textMuted`, so it is settled back down to just clear of AA.
38
- placeholder: {
39
- ...palette.placeholder,
40
- 500: soften(lift(palette.placeholder[500], accentText_1.AA_NORMAL_TEXT), exports.PLACEHOLDER_TEXT),
40
+ // `placeholder` is deliberately absent: the brand authors that rung and the published
41
+ // library ships it untouched. Its floor is enforced in `placeholderInk`, against the
42
+ // surfaces a FIELD renders on — not `table.hover`, which no field sits on.
43
+ // Settled, not lifted: this rung already passed through `withOutlineRung`, and lifting it
44
+ // again here to AA_NON_TEXT is what shipped 3.85-4.95:1 outlines. See CHROME_BORDER.
45
+ boxborder: {
46
+ ...palette.boxborder,
47
+ 200: rule(palette.boxborder[200]),
48
+ 500: settle(palette.boxborder[500], outlineRung_1.CHROME_BORDER),
41
49
  },
42
- boxborder: { ...palette.boxborder, 500: lift(palette.boxborder[500], outlineRung_1.AA_NON_TEXT) },
50
+ // The 200 rung of both ramps is the same job under two names; settle them together or an
51
+ // app picking `border` gets a heavier rule than one picking `boxborder`.
52
+ border: { ...palette.border, 200: rule(palette.border[200]) },
43
53
  };
44
54
  }
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { memo } from "react";
2
+ import { forwardRef, memo } from "react";
3
3
  import { Button as ChakraButton } from "@chakra-ui/react";
4
- function Button({ label, children, onClick, opacity, variant = "solid", leftIcon, rightIcon, size, isDisabled = false, isLoading = false, loadingText = "Loading", type, width, sx, colorScheme, ref, border, borderRadius, onMouseEnter, onMouseLeave, ...aria }) {
5
- return (_jsx(ChakraButton, { ...aria, type: type, onClick: onClick, width: width || "fit-content", variant: variant, size: size, isLoading: isLoading, isDisabled: isDisabled, loadingText: loadingText, leftIcon: leftIcon, rightIcon: rightIcon, ref: ref, colorScheme: colorScheme, sx: sx, opacity: opacity, border: border, borderRadius: borderRadius, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: children !== null && children !== void 0 ? children : label }));
6
- }
4
+ const Button = forwardRef(function Button({ label, children, onClick, opacity, variant = "solid", leftIcon, rightIcon, size, isDisabled = false, isLoading = false, loadingText = "Loading", type, width, w, sx, colorScheme, border, borderRadius, onMouseEnter, onMouseLeave, ...aria }, ref) {
5
+ return (_jsx(ChakraButton, { ...aria, type: type, onClick: onClick, width: width || w || "fit-content", variant: variant, size: size, isLoading: isLoading, isDisabled: isDisabled, loadingText: loadingText, leftIcon: leftIcon, rightIcon: rightIcon, ref: ref, colorScheme: colorScheme, sx: sx, opacity: opacity, border: border, borderRadius: borderRadius, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: children !== null && children !== void 0 ? children : label }));
6
+ });
7
7
  export default memo(Button);
@@ -1,4 +1,5 @@
1
1
  import { accentTextOnCanvas, isDarkCanvas, onFilled } from "../../Theme/tokens/builders/accentText.js";
2
+ import { contrastRatio } from "../../Theme/tokens/builders/color.js";
2
3
  import { resolveGradient, gradientCss } from "../../Theme/tokens/builders/gradientInk.js";
3
4
  /**
4
5
  * Outline/ghost/link text sits ON the canvas, so it needs a rung that stays readable there —
@@ -27,9 +28,34 @@ const onCanvasHoverBg = (theme, colorScheme, step) => {
27
28
  * ~3.2 contrast.
28
29
  */
29
30
  const FILL_STEP_RUNGS = { light: [600, 700], dark: [400, 300] };
31
+ const RUNGS = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900];
32
+ const AA_NORMAL_TEXT = 4.5;
33
+ // Semantic scales (red/green) carry no opacity ramp; brand scales do and keep their own [500].
34
+ const solidRung = (theme, colorScheme) => {
35
+ const scale = theme.colors[colorScheme];
36
+ const white = theme.colors.white;
37
+ if ("opacity" in scale)
38
+ return 500;
39
+ if (contrastRatio(scale[500], white) >= AA_NORMAL_TEXT)
40
+ return 500;
41
+ const passing = RUNGS.filter((r) => scale[r] && contrastRatio(scale[r], white) >= AA_NORMAL_TEXT);
42
+ if (!passing.length)
43
+ return 500;
44
+ return passing.reduce((a, b) => contrastRatio(scale[a], white) <= contrastRatio(scale[b], white) ? a : b);
45
+ };
46
+ const steppedRung = (theme, base, step) => {
47
+ const dir = isDarkCanvas(theme.colors.backgroundColor.main) ? -100 : 100;
48
+ return Math.min(900, Math.max(50, base + dir * step));
49
+ };
30
50
  const darkerFill = (theme, colorScheme, step) => {
31
- const mode = isDarkCanvas(theme.colors.backgroundColor.main) ? "dark" : "light";
32
- return theme.colors[colorScheme][FILL_STEP_RUNGS[mode][step]];
51
+ var _a;
52
+ const scale = theme.colors[colorScheme];
53
+ const base = solidRung(theme, colorScheme);
54
+ if (base === 500) {
55
+ const mode = isDarkCanvas(theme.colors.backgroundColor.main) ? "dark" : "light";
56
+ return scale[FILL_STEP_RUNGS[mode][step]];
57
+ }
58
+ return (_a = scale[steppedRung(theme, base, step === 0 ? 1 : 2)]) !== null && _a !== void 0 ? _a : scale[base];
33
59
  };
34
60
  /** Label for the solid variant's filled bg — derived from THAT fill, since hover/active swap it. */
35
61
  const labelFor = (theme, fill) => onFilled(fill, theme.colors.white, theme.colors.black);
@@ -46,7 +72,7 @@ export const Button = {
46
72
  }),
47
73
  variants: {
48
74
  solid: ({ theme, colorScheme = "primary" }) => {
49
- const fill = theme.colors[colorScheme][500];
75
+ const fill = theme.colors[colorScheme][solidRung(theme, colorScheme)];
50
76
  const hoverFill = darkerFill(theme, colorScheme, 0);
51
77
  const activeFill = darkerFill(theme, colorScheme, 1);
52
78
  const hoverLabel = labelFor(theme, hoverFill);
@@ -69,7 +69,7 @@ rightIconDropdown, menulistStyle, menuItemStyle, isLoading, divider = true, left
69
69
  // this theme-swap app never triggers) — our `bg` prop above only recolors the list
70
70
  // itself, not the inherited var, so items fell back to white until hover/focus (which
71
71
  // our own sx already overrides). Setting the var here fixes the rest state too.
72
- sx: { "--menu-bg": theme.colors.backgroundColor.light }, border: "1px solid", borderColor: theme.colors.boxborder[500], borderRadius: "xl", boxShadow: "lg", py: "0.375rem", minW: "12rem", overflow: "hidden", children: dropdownOptions === null || dropdownOptions === void 0 ? void 0 : dropdownOptions.map((option, index) => (_jsxs(MenuItem, { onClick: (event) => handleMenuClick(event, option), style: menuItemStyle, sx: {
72
+ sx: { "--menu-bg": theme.colors.backgroundColor.light }, borderRadius: "xl", boxShadow: "lg", py: "0.375rem", minW: "12rem", overflow: "hidden", children: dropdownOptions === null || dropdownOptions === void 0 ? void 0 : dropdownOptions.map((option, index) => (_jsxs(MenuItem, { onClick: (event) => handleMenuClick(event, option), style: menuItemStyle, sx: {
73
73
  display: "flex",
74
74
  alignItems: "center",
75
75
  gap: "0.5rem",
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Card as ChakraCard } from "@chakra-ui/react";
3
- export default function Card({ key, maxW, align, variant, direction, justify, children, size, color, overflow, sx, }) {
4
- return (_jsx(ChakraCard, { maxW: maxW, align: align, variant: variant, direction: direction, justify: justify, size: size, overflow: overflow, colorScheme: color, p: 4, sx: sx, children: children }, key));
3
+ export default function Card({ maxW, align, variant, direction, justify, children, size, color, overflow, sx, }) {
4
+ return (_jsx(ChakraCard, { maxW: maxW, align: align, variant: variant, direction: direction, justify: justify, size: size, overflow: overflow, colorScheme: color, p: 4, sx: sx, children: children }));
5
5
  }
@@ -21,7 +21,7 @@ export default function CheckBox({ label, labelFontSize, showLabelTooltip, label
21
21
  ...labelSx,
22
22
  }
23
23
  : { ...labelSx };
24
- return (_jsxs(_Fragment, { children: [_jsx(ChakraCheckbox, { ...aria, onClick: onClick, spacing: spacing !== null && spacing !== void 0 ? spacing : "0.5rem", isInvalid: isInvalid, colorScheme: color, iconColor: iconColor, iconSize: iconSize, isChecked: isChecked, isIndeterminate: isIndeterminate, onChange: onChange, isDisabled: isDisabled, size: size, value: value, defaultChecked: defaultChecked, borderColor: theme.colors.gray[500], display: "flex", alignItems: "center", sx: {
24
+ return (_jsxs(_Fragment, { children: [_jsx(ChakraCheckbox, { ...aria, onClick: onClick, spacing: spacing !== null && spacing !== void 0 ? spacing : "0.5rem", isInvalid: isInvalid, colorScheme: color, iconColor: iconColor, iconSize: iconSize, isChecked: isChecked, isIndeterminate: isIndeterminate, onChange: onChange, isDisabled: isDisabled, size: size, value: value, defaultChecked: defaultChecked, borderColor: theme.colors.boxborder[500], display: "flex", alignItems: "center", sx: {
25
25
  ...sx,
26
26
  ".chakra-checkbox__control": { w: controlSize, h: controlSize },
27
27
  }, children: label && (showLabelTooltip ? (_jsx(ToolTip, { label: labelTooltip !== null && labelTooltip !== void 0 ? labelTooltip : label, hasArrow: true, placement: "top", fontSize: "0.75rem", children: _jsx(Box, { as: "span", sx: clampStyles, fontSize: labelFontSize !== null && labelFontSize !== void 0 ? labelFontSize : "0.8125rem", color: theme.colors.text[700], fontWeight: 500, ml: 0, children: label }) })) : (_jsx(Box, { as: "span", sx: clampStyles, fontSize: labelFontSize !== null && labelFontSize !== void 0 ? labelFontSize : "0.8125rem", color: theme.colors.text[700], fontWeight: 500, ml: 0, children: label }))) }), error && _jsx(ErrorMessage, { errorMessage: errorMessage }), helperText && !error && _jsx(HelperText, { helperText: helperText })] }));
@@ -15,6 +15,8 @@ export const Checkbox = {
15
15
  height: "1.25rem",
16
16
  borderWidth: "1.6px",
17
17
  borderRadius: "base",
18
+ // Without a resting colour Chakra falls back to its own gray.500.
19
+ borderColor: theme.colors.boxborder[500],
18
20
  transition: "background 0.15s, border-color 0.15s, box-shadow 0.15s",
19
21
  _disabled: {
20
22
  bg: theme.colors.background[50],
@@ -172,7 +172,7 @@ export const RangeDatePicker = (props) => {
172
172
  : `0 0 0 1px ${theme.colors.primary[500]}`,
173
173
  }, _hover: {
174
174
  borderColor: error ? theme.colors.semanticText.error : undefined,
175
- }, cursor: "pointer" }), _jsx(InputRightElement, { height: "100%", display: "flex", alignItems: "center", pointerEvents: "auto", style: { cursor: "pointer" }, onClick: () => (isOpen ? onClose() : handleOpen()), children: _jsx(Box, { as: "span", sx: calendarIconWrapperSx, children: _jsx(CalendarIcon, { size: calendarIconPx, color: theme.colors.textMuted }) }) })] }) }) }), _jsx(PopoverContent, { w: "18rem", maxW: "18rem", p: 3, ref: popoverRef, boxShadow: "lg", borderRadius: "xl", border: "1px solid", borderColor: theme.colors.boxborder[500], bg: theme.colors.background[50], children: _jsxs(PopoverBody, { p: 0, children: [_jsx(Box, { display: "flex", flexWrap: "wrap", gap: 2, mb: 3, children: presets.map((p) => (_jsx(Button, { size: "xs", variant: "outline", colorScheme: "gray", sx: { flex: "1 1 auto" }, onClick: () => {
175
+ }, cursor: "pointer" }), _jsx(InputRightElement, { height: "100%", display: "flex", alignItems: "center", pointerEvents: "auto", style: { cursor: "pointer" }, onClick: () => (isOpen ? onClose() : handleOpen()), children: _jsx(Box, { as: "span", sx: calendarIconWrapperSx, children: _jsx(CalendarIcon, { size: calendarIconPx, color: theme.colors.textMuted }) }) })] }) }) }), _jsx(PopoverContent, { w: "18rem", maxW: "18rem", p: 3, ref: popoverRef, boxShadow: "lg", borderRadius: "xl", bg: theme.colors.background[50], children: _jsxs(PopoverBody, { p: 0, children: [_jsx(Box, { display: "flex", flexWrap: "wrap", gap: 2, mb: 3, children: presets.map((p) => (_jsx(Button, { size: "xs", variant: "outline", colorScheme: "gray", sx: { flex: "1 1 auto" }, onClick: () => {
176
176
  const [from, to] = p.getRange();
177
177
  applyPreset(from, to);
178
178
  }, children: p.label }, p.label))) }), _jsx(CalendarPanel, { currentMonth: currentMonth, setCurrentMonth: (updater) => setCurrentMonthState((prev) => updater(prev)), today: today, isRange: true, tempDate: null, tempRangeStart: tempRangeStart, tempRangeEnd: tempRangeEnd, hoveredDate: hoveredDate, onDayHover: setHoveredDate, isSameDay: isSameDay, isBefore: isBefore, isAfter: isAfter, minDate: minDate, maxDate: maxDate, disablePastDates: disablePastDates, disableFutureDates: disableFutureDates, disableToday: disableToday, onDaySelect: handleDaySelect }), formatHasTime && (_jsxs(Box, { mt: 3, display: "grid", gridTemplateColumns: "1fr", gap: 2, children: [_jsxs(Box, { children: [_jsx(Box, { fontSize: "xs", color: theme.colors.textMuted, mb: 1, children: "Start time" }), shouldUseSelectTimePicker ? (_jsx(TimePicker, { date: startTimeBaseDate, onChange: (updated) => {
@@ -956,7 +956,7 @@ export const SingleDatePicker = (props) => {
956
956
  else {
957
957
  onClose();
958
958
  }
959
- }, style: { cursor: "pointer" }, children: _jsx(Box, { as: "span", sx: calendarIconWrapperSx, children: _jsx(CalendarIcon, { size: calendarIconPx, color: theme.colors.textMuted }) }) })] }) }) }), _jsx(PopoverContent, { width: "auto", p: 3, ref: popoverRef, boxShadow: "lg", borderRadius: "xl", border: "1px solid", borderColor: theme.colors.boxborder[500], bg: theme.colors.background[50], children: _jsxs(PopoverBody, { p: 0, children: [showDate && (_jsx(CalendarPanel, { currentMonth: currentMonth, setCurrentMonth: (updater) => setCurrentMonth((prev) => updater(prev)), today: today, isRange: false, tempDate: tempDate, tempRangeStart: null, tempRangeEnd: null, isSameDay: isSameDay, isBefore: isBefore, isAfter: isAfter, minDate: minDate, maxDate: maxDate, disablePastDates: disablePastDates, disableFutureDates: disableFutureDates, disableToday: disableToday, onDaySelect: handleDaySelect })), showTime && (_jsx(Box, { mt: showDate ? 3 : 0, children: resolvedPickerType === "time" ? (_jsx(TimePickerInput, { value: tempDate, onChange: (updatedDate) => {
959
+ }, style: { cursor: "pointer" }, children: _jsx(Box, { as: "span", sx: calendarIconWrapperSx, children: _jsx(CalendarIcon, { size: calendarIconPx, color: theme.colors.textMuted }) }) })] }) }) }), _jsx(PopoverContent, { width: "auto", p: 3, ref: popoverRef, boxShadow: "lg", borderRadius: "xl", bg: theme.colors.background[50], children: _jsxs(PopoverBody, { p: 0, children: [showDate && (_jsx(CalendarPanel, { currentMonth: currentMonth, setCurrentMonth: (updater) => setCurrentMonth((prev) => updater(prev)), today: today, isRange: false, tempDate: tempDate, tempRangeStart: null, tempRangeEnd: null, isSameDay: isSameDay, isBefore: isBefore, isAfter: isAfter, minDate: minDate, maxDate: maxDate, disablePastDates: disablePastDates, disableFutureDates: disableFutureDates, disableToday: disableToday, onDaySelect: handleDaySelect })), showTime && (_jsx(Box, { mt: showDate ? 3 : 0, children: resolvedPickerType === "time" ? (_jsx(TimePickerInput, { value: tempDate, onChange: (updatedDate) => {
960
960
  setTempDate(updatedDate);
961
961
  setInputValue(updatedDate ? format(updatedDate, resolvedDateFormat) : "");
962
962
  setIsTyping(false);
@@ -1,13 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import React, { useCallback } from "react";
3
- import { Box, Text, VStack, Icon, List, ListItem, ListIcon, CloseButton, HStack, Progress, useDisclosure, Image, } from "@chakra-ui/react";
3
+ import { Box, Text, Stack, VStack, Icon, List, ListItem, ListIcon, CloseButton, HStack, Progress, useDisclosure, Image, } from "@chakra-ui/react";
4
4
  import { useDropzone } from "react-dropzone";
5
5
  import { Upload, FileText, Eye } from "lucide-react";
6
6
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
7
7
  import { accentTextOnCanvas } from "../../Theme/tokens/builders/accentText.js";
8
8
  import { mimeMap, toMB } from "./constants.js";
9
9
  import Modal, { ModalBody, ModalHeader } from "../Modal/Modal.js";
10
- const FileUpload = ({ onFilesUploaded, uploadedFiles, onRemoveFile, acceptTypes = [".jpg", ".png"], maxSizeKB = 5, maxFiles = undefined, progress = {}, }) => {
10
+ const FileUpload = ({ onFilesUploaded, uploadedFiles, onRemoveFile, acceptTypes = [".jpg", ".png"], maxSizeKB = 5, maxFiles = undefined, progress = {}, size = "md", inputAriaLabel = "Upload files", }) => {
11
+ const compact = size === "sm";
11
12
  const { colors, radii } = useCustomTheme();
12
13
  const { isOpen, onOpen, onClose } = useDisclosure();
13
14
  const [previewUrl, setPreviewUrl] = React.useState(null);
@@ -53,7 +54,7 @@ const FileUpload = ({ onFilesUploaded, uploadedFiles, onRemoveFile, acceptTypes
53
54
  setErrors(messages);
54
55
  },
55
56
  });
56
- return (_jsxs(_Fragment, { children: [_jsxs(VStack, { spacing: 4, align: "stretch", children: [_jsxs(Box, { ...getRootProps(), border: "2px dashed", borderColor: border, borderRadius: "md", p: 10, textAlign: "center", bg: bg, cursor: "pointer", transition: "all 0.2s", _hover: { bg: colors.gray[100] }, position: "relative", children: [_jsx("input", { ...getInputProps() }), _jsxs(VStack, { spacing: 2, children: [_jsx(Icon, { as: Upload, boxSize: 6 }), _jsx(Text, { fontWeight: "medium", children: "Drag and drop files here" }), _jsxs(Text, { fontSize: "sm", color: colors.textMuted, children: [acceptTypes.join(", "), " up to ", toMB(maxSizeKB), " ", maxFiles ? `- ${maxFiles} file(s) max` : ""] })] })] }), errors.length > 0 && (_jsx(Box, { children: errors.map((err, idx) => (_jsx(Text, { fontSize: "sm", color: colors.semanticText.error, children: err }, idx))) })), uploadedFiles.length > 0 && (_jsxs(Box, { children: [_jsx(Box, { display: "flex", alignItems: "center", gap: 2, children: _jsx(Text, { fontFamily: "open-sans, sans-serif", fontWeight: 600, fontSize: 14, lineHeight: "100%", letterSpacing: "4%", textTransform: "uppercase", py: 4, children: "Uploaded Files" }) }), _jsx(List, { spacing: 2, children: uploadedFiles.map((file, index) => (_jsxs(Box, { borderWidth: "0.063rem", borderRadius: "md", px: 3, py: 2, bg: colors.background[50], children: [_jsxs(ListItem, { display: "flex", justifyContent: "space-between", alignItems: "center", children: [_jsxs(HStack, { spacing: 3, flex: "1", children: [file.type.startsWith("image/") ? (_jsxs(Box, { boxSize: "2.5rem", cursor: "pointer", position: "relative", _hover: {
57
+ return (_jsxs(_Fragment, { children: [_jsxs(VStack, { spacing: 4, align: "stretch", children: [_jsxs(Box, { ...getRootProps(), border: "2px dashed", borderColor: border, borderRadius: "md", p: compact ? 3 : 10, textAlign: "center", bg: bg, cursor: "pointer", transition: "all 0.2s", _hover: { bg: colors.gray[100] }, position: "relative", children: [_jsx("input", { ...getInputProps({ "aria-label": inputAriaLabel }) }), _jsxs(Stack, { direction: compact ? "row" : "column", spacing: compact ? 3 : 2, align: "center", justify: "center", children: [_jsx(Icon, { as: Upload, boxSize: compact ? 4 : 6 }), _jsxs(Stack, { spacing: 0, align: compact ? "start" : "center", children: [_jsx(Text, { fontWeight: "medium", fontSize: compact ? "sm" : "md", color: colors.textMuted, children: "Drag and drop files here" }), _jsxs(Text, { fontSize: compact ? "xs" : "sm", color: colors.textMuted, children: [acceptTypes.join(", "), " up to ", toMB(maxSizeKB), " ", maxFiles ? `- ${maxFiles} file(s) max` : ""] })] })] })] }), errors.length > 0 && (_jsx(Box, { children: errors.map((err, idx) => (_jsx(Text, { fontSize: "sm", color: colors.semanticText.error, children: err }, idx))) })), uploadedFiles.length > 0 && (_jsxs(Box, { children: [_jsx(Box, { display: "flex", alignItems: "center", gap: 2, children: _jsx(Text, { fontFamily: "open-sans, sans-serif", fontWeight: 600, fontSize: 14, lineHeight: "100%", letterSpacing: "4%", textTransform: "uppercase", py: 4, children: "Uploaded Files" }) }), _jsx(List, { spacing: 2, children: uploadedFiles.map((file, index) => (_jsxs(Box, { borderWidth: "0.063rem", borderRadius: "md", px: 3, py: 2, bg: colors.background[50], children: [_jsxs(ListItem, { display: "flex", justifyContent: "space-between", alignItems: "center", children: [_jsxs(HStack, { spacing: 3, flex: "1", children: [file.type.startsWith("image/") ? (_jsxs(Box, { boxSize: "2.5rem", cursor: "pointer", position: "relative", _hover: {
57
58
  ".hover-icon": {
58
59
  opacity: 1,
59
60
  bg: colors.secondary.opacity[16],
@@ -13,6 +13,7 @@ export const mimeMap = {
13
13
  '.ppt': 'application/vnd.ms-powerpoint',
14
14
  '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
15
15
  '.txt': 'text/plain',
16
+ '.csv': 'text/csv',
16
17
  '.mp4': 'video/mp4',
17
18
  '.mov': 'video/quicktime',
18
19
  '.mp3': 'audio/mpeg',
@@ -144,13 +144,13 @@ panelPadding = 3, clearAllButton = true, onClearAllHandler,
144
144
  pointerEvents: 'none', // Allow clicks to pass through track
145
145
  zIndex: 3,
146
146
  margin: 0,
147
- } })] }), _jsxs(SimpleGrid, { columns: 2, spacing: 2, pt: 2, w: "full", children: [_jsxs(Popover, { isOpen: openPrice.id === section.id && openPrice.target === "min", onClose: () => setOpenPrice({}), placement: "bottom-start", closeOnBlur: true, children: [_jsx(PopoverTrigger, { children: _jsx(Flex, { borderWidth: "0", borderRadius: "md", alignItems: "center", px: 3, py: 2, bg: theme.colors.gray[50], borderColor: theme.colors.gray[300], cursor: "pointer", onClick: () => setOpenPrice({ id: section.id, target: "min" }), gap: 2, overflow: "hidden", children: _jsx(Box, { ml: "auto", children: _jsxs(Text, { fontSize: "12px", color: theme.colors.text[500], whiteSpace: "nowrap", children: [currentMin, range.unit ? ` ${range.unit}` : ""] }) }) }) }), _jsx(Portal, { children: _jsx(PopoverContent, { width: "6rem", p: 0, zIndex: 1600, bg: theme.colors.background[50], children: _jsx(PopoverBody, { p: 0, children: _jsx(VStack, { align: "stretch", spacing: 0, maxH: "12rem", overflowY: "auto", children: values.map((v) => (_jsxs(Flex, { px: 2, py: 1, align: "center", justify: "space-between", cursor: "pointer", bg: currentMin === v ? theme.colors.red[50] : theme.colors.background[50], borderLeftWidth: currentMin === v ? 3 : 0, borderLeftStyle: "solid", borderLeftColor: currentMin === v ? theme.colors.red[400] : "transparent", _hover: { bg: hoverBg }, onClick: () => {
147
+ } })] }), _jsxs(SimpleGrid, { columns: 2, spacing: 2, pt: 2, w: "full", children: [_jsxs(Popover, { isOpen: openPrice.id === section.id && openPrice.target === "min", onClose: () => setOpenPrice({}), placement: "bottom-start", closeOnBlur: true, children: [_jsx(PopoverTrigger, { children: _jsx(Flex, { borderWidth: "0", borderRadius: "md", alignItems: "center", px: 3, py: 2, bg: theme.colors.gray[50], borderColor: theme.colors.boxborder[500], cursor: "pointer", onClick: () => setOpenPrice({ id: section.id, target: "min" }), gap: 2, overflow: "hidden", children: _jsx(Box, { ml: "auto", children: _jsxs(Text, { fontSize: "12px", color: theme.colors.text[500], whiteSpace: "nowrap", children: [currentMin, range.unit ? ` ${range.unit}` : ""] }) }) }) }), _jsx(Portal, { children: _jsx(PopoverContent, { width: "6rem", p: 0, zIndex: 1600, bg: theme.colors.background[50], children: _jsx(PopoverBody, { p: 0, children: _jsx(VStack, { align: "stretch", spacing: 0, maxH: "12rem", overflowY: "auto", children: values.map((v) => (_jsxs(Flex, { px: 2, py: 1, align: "center", justify: "space-between", cursor: "pointer", bg: currentMin === v ? theme.colors.red[50] : theme.colors.background[50], borderLeftWidth: currentMin === v ? 3 : 0, borderLeftStyle: "solid", borderLeftColor: currentMin === v ? theme.colors.red[400] : "transparent", _hover: { bg: hoverBg }, onClick: () => {
148
148
  const min = v;
149
149
  const max = currentMax;
150
150
  const nextVal = [Math.min(min, max), Math.max(min, max)];
151
151
  setInternalSelected((prev) => { const next = { ...prev, [section.id]: nextVal }; onChange === null || onChange === void 0 ? void 0 : onChange(next); return next; });
152
152
  setOpenPrice({});
153
- }, children: [_jsxs(Text, { fontSize: "sm", color: theme.colors.gray[800], children: [v, range.unit ? ` ${range.unit}` : ""] }), currentMin === v ? (_jsx(Box, { bg: theme.colors.red[100], borderRadius: "full", p: 1, display: "flex", alignItems: "center", children: _jsx(Check, { size: 9, color: onFilled(theme.colors.red[100], theme.colors.white, theme.colors.black) }) })) : null] }, `min-${v}`))) }) }) }) })] }), _jsxs(Popover, { isOpen: openPrice.id === section.id && openPrice.target === "max", onClose: () => setOpenPrice({}), placement: "bottom-start", closeOnBlur: true, children: [_jsx(PopoverTrigger, { children: _jsx(Flex, { borderWidth: "0", borderRadius: "md", alignItems: "center", px: 3, py: 2, bg: theme.colors.gray[50], borderColor: theme.colors.gray[300], cursor: "pointer", onClick: () => setOpenPrice({ id: section.id, target: "max" }), gap: 2, overflow: "hidden", children: _jsx(Box, { ml: "auto", children: _jsxs(Text, { fontSize: "12px", color: theme.colors.text[500], whiteSpace: "nowrap", children: [currentMax, range.unit ? ` ${range.unit}` : ""] }) }) }) }), _jsx(PopoverContent, { width: "6rem", p: 0, bg: theme.colors.background[50], children: _jsx(PopoverBody, { p: 0, children: _jsx(VStack, { align: "stretch", spacing: 0, maxH: "12rem", overflowY: "auto", children: values.map((v) => (_jsxs(Flex, { px: 2, py: 1, align: "center", justify: "space-between", cursor: "pointer", bg: currentMax === v ? theme.colors.red[50] : theme.colors.background[50], borderLeftWidth: currentMax === v ? 3 : 0, borderLeftStyle: "solid", borderLeftColor: currentMax === v ? theme.colors.red[400] : "transparent", _hover: { bg: hoverBg }, onClick: () => {
153
+ }, children: [_jsxs(Text, { fontSize: "sm", color: theme.colors.gray[800], children: [v, range.unit ? ` ${range.unit}` : ""] }), currentMin === v ? (_jsx(Box, { bg: theme.colors.red[100], borderRadius: "full", p: 1, display: "flex", alignItems: "center", children: _jsx(Check, { size: 9, color: onFilled(theme.colors.red[100], theme.colors.white, theme.colors.black) }) })) : null] }, `min-${v}`))) }) }) }) })] }), _jsxs(Popover, { isOpen: openPrice.id === section.id && openPrice.target === "max", onClose: () => setOpenPrice({}), placement: "bottom-start", closeOnBlur: true, children: [_jsx(PopoverTrigger, { children: _jsx(Flex, { borderWidth: "0", borderRadius: "md", alignItems: "center", px: 3, py: 2, bg: theme.colors.gray[50], borderColor: theme.colors.boxborder[500], cursor: "pointer", onClick: () => setOpenPrice({ id: section.id, target: "max" }), gap: 2, overflow: "hidden", children: _jsx(Box, { ml: "auto", children: _jsxs(Text, { fontSize: "12px", color: theme.colors.text[500], whiteSpace: "nowrap", children: [currentMax, range.unit ? ` ${range.unit}` : ""] }) }) }) }), _jsx(PopoverContent, { width: "6rem", p: 0, bg: theme.colors.background[50], children: _jsx(PopoverBody, { p: 0, children: _jsx(VStack, { align: "stretch", spacing: 0, maxH: "12rem", overflowY: "auto", children: values.map((v) => (_jsxs(Flex, { px: 2, py: 1, align: "center", justify: "space-between", cursor: "pointer", bg: currentMax === v ? theme.colors.red[50] : theme.colors.background[50], borderLeftWidth: currentMax === v ? 3 : 0, borderLeftStyle: "solid", borderLeftColor: currentMax === v ? theme.colors.red[400] : "transparent", _hover: { bg: hoverBg }, onClick: () => {
154
154
  const max = v;
155
155
  const min = currentMin;
156
156
  const nextVal = [Math.min(min, max), Math.max(min, max)];
@@ -3,6 +3,6 @@ import { Box, Icon } from "@chakra-ui/react";
3
3
  import { useCustomTheme } from "../../Theme/useCustomTheme.js";
4
4
  const FormWrapper = ({ icon, text, children, }) => {
5
5
  const { colors } = useCustomTheme();
6
- return (_jsxs(Box, { children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, mb: 2, children: [icon && _jsx(Icon, { as: icon, size: "1rem", color: colors.header[500] }), text && (_jsx(Box, { fontFamily: "open-sans, sans-serif", fontWeight: 600, fontSize: 12, lineHeight: "100%", letterSpacing: "4%", textTransform: "uppercase", color: colors.header[500], children: text }))] }), _jsx(Box, { borderRadius: "base", bg: colors.background[50], border: `0.075rem solid ${colors.border[500]}`, boxShadow: `0 0.063rem 0.125rem 0 ${colors.boxShadow.primary}`, p: "1.5rem", children: children })] }));
6
+ return (_jsxs(Box, { children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, mb: 2, children: [icon && _jsx(Icon, { as: icon, size: "1rem", color: colors.header[500] }), text && (_jsx(Box, { fontFamily: "open-sans, sans-serif", fontWeight: 600, fontSize: 12, lineHeight: "100%", letterSpacing: "4%", textTransform: "uppercase", color: colors.header[500], children: text }))] }), _jsx(Box, { borderRadius: "base", bg: colors.background[50], border: `0.075rem solid ${colors.boxborder[200]}`, boxShadow: `0 0.063rem 0.125rem 0 ${colors.boxShadow.primary}`, p: "1.5rem", children: children })] }));
7
7
  };
8
8
  export default FormWrapper;