@galaxy-io/dls 2.8.1 → 2.10.0

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 (106) hide show
  1. package/README.md +2 -2
  2. package/dist/beacons/Beacon.d.ts +1 -1
  3. package/dist/beacons/Beacon.js +12 -28
  4. package/dist/brand/GalaxyAlchemyWordmark.d.ts +4 -1
  5. package/dist/brand/GalaxyAlchemyWordmark.js +7 -1
  6. package/dist/brand/GalaxyFilamentWordmark.d.ts +5 -2
  7. package/dist/brand/GalaxyFilamentWordmark.js +9 -2
  8. package/dist/brand/GalaxyLogomark.js +3 -0
  9. package/dist/brand/PoweredBy.d.ts +27 -0
  10. package/dist/brand/PoweredBy.js +96 -0
  11. package/dist/brand/internal/svg/GalaxyAlchemyWordmarkSvg.d.ts +1 -1
  12. package/dist/brand/internal/svg/GalaxyAlchemyWordmarkSvg.js +34 -8
  13. package/dist/brand/internal/svg/GalaxyFilamentWordmarkSvg.d.ts +1 -1
  14. package/dist/brand/internal/svg/GalaxyFilamentWordmarkSvg.js +2 -2
  15. package/dist/charts/Heatmap.js +25 -9
  16. package/dist/charts/Sparkline.d.ts +1 -1
  17. package/dist/charts/Sparkline.js +10 -26
  18. package/dist/charts/chartFormat.d.ts +1 -1
  19. package/dist/charts/chartFormat.js +2 -2
  20. package/dist/charts/heatmapGeometry.d.ts +14 -0
  21. package/dist/charts/heatmapGeometry.js +17 -1
  22. package/dist/chips/Chip.d.ts +2 -2
  23. package/dist/chips/Chip.js +15 -31
  24. package/dist/drawer/Drawer.d.ts +2 -2
  25. package/dist/drawer/Drawer.js +1 -1
  26. package/dist/editor/CodeEditor.d.ts +1 -1
  27. package/dist/editor/CodeEditor.js +2 -1
  28. package/dist/feedback/Alert.d.ts +36 -9
  29. package/dist/feedback/Alert.js +26 -8
  30. package/dist/feedback/ProgressBar.d.ts +4 -1
  31. package/dist/feedback/ProgressBar.js +17 -30
  32. package/dist/feedback/ProgressCircle.d.ts +1 -1
  33. package/dist/feedback/ProgressCircle.js +14 -30
  34. package/dist/hooks/useEndReached.d.ts +40 -0
  35. package/dist/hooks/useEndReached.js +69 -0
  36. package/dist/icons/Icon.d.ts +36 -8
  37. package/dist/icons/Icon.js +14 -7
  38. package/dist/inputs/CronInput.js +114 -78
  39. package/dist/inputs/DateInput.d.ts +1 -1
  40. package/dist/inputs/DateInput.js +10 -10
  41. package/dist/inputs/MultiSelectInput.d.ts +3 -1
  42. package/dist/inputs/MultiSelectInput.js +8 -3
  43. package/dist/inputs/SelectInput.d.ts +8 -1
  44. package/dist/inputs/SelectInput.js +52 -25
  45. package/dist/inputs/internal/selectAll.d.ts +11 -0
  46. package/dist/inputs/internal/selectAll.js +28 -0
  47. package/dist/json/JsonViewer.js +7 -6
  48. package/dist/layout/AppFrame.d.ts +20 -0
  49. package/dist/layout/AppFrame.js +71 -0
  50. package/dist/layout/EmptyLayout.d.ts +53 -0
  51. package/dist/layout/EmptyLayout.js +59 -0
  52. package/dist/layout/ErrorLayout.d.ts +42 -0
  53. package/dist/layout/ErrorLayout.js +60 -0
  54. package/dist/layout/PageLayout.d.ts +26 -0
  55. package/dist/layout/PageLayout.js +116 -0
  56. package/dist/layout/PendingLayout.d.ts +30 -0
  57. package/dist/layout/PendingLayout.js +57 -0
  58. package/dist/layout/internal/errorState.d.ts +14 -0
  59. package/dist/layout/internal/errorState.js +49 -0
  60. package/dist/layout/internal/region.d.ts +10 -0
  61. package/dist/layout/internal/region.js +24 -0
  62. package/dist/lists/DescriptionList.js +1 -0
  63. package/dist/menu/Menu.d.ts +2 -2
  64. package/dist/menu/Menu.js +6 -13
  65. package/dist/modal/Modal.d.ts +2 -2
  66. package/dist/modal/Modal.js +1 -1
  67. package/dist/navigation/CommandPalette.js +4 -11
  68. package/dist/navigation/SidebarNav.d.ts +5 -0
  69. package/dist/navigation/SidebarNav.js +41 -22
  70. package/dist/navigation/Topbar.js +4 -0
  71. package/dist/shapes/Circle.d.ts +1 -1
  72. package/dist/shapes/Circle.js +10 -26
  73. package/dist/shapes/Square.d.ts +1 -1
  74. package/dist/shapes/Square.js +10 -26
  75. package/dist/styles/internal/roleColor.d.ts +3 -0
  76. package/dist/styles/internal/roleColor.js +42 -0
  77. package/dist/styles/mixins.js +1 -1
  78. package/dist/styles.css +1 -1
  79. package/dist/table/InfiniteSpreadsheet.js +6 -6
  80. package/dist/table/InfiniteTable.d.ts +57 -18
  81. package/dist/table/InfiniteTable.js +5 -3
  82. package/dist/table/TableCore.d.ts +11 -2
  83. package/dist/table/TableCore.js +108 -87
  84. package/dist/table/VirtualizedInfiniteTable.d.ts +58 -19
  85. package/dist/table/VirtualizedInfiniteTable.js +9 -6
  86. package/dist/table/useInfiniteScrollSentinel.d.ts +13 -13
  87. package/dist/table/useInfiniteScrollSentinel.js +7 -51
  88. package/dist/table/useTableColumnLayout.d.ts +8 -2
  89. package/dist/table/useTableColumnLayout.js +36 -13
  90. package/dist/theme/tokens/dark.js +1 -1
  91. package/dist/theme/tokens/light.js +4 -3
  92. package/dist/theme/tokens/types.d.ts +7 -7
  93. package/dist/timeline/Timeline.d.ts +1 -1
  94. package/dist/timeline/Timeline.js +6 -24
  95. package/dist/tokens.css +1 -1
  96. package/dist/utils/format.d.ts +35 -10
  97. package/dist/utils/format.js +60 -12
  98. package/dist/utils/search.d.ts +15 -0
  99. package/dist/utils/search.js +24 -0
  100. package/dist/vite/index.d.ts +16 -2
  101. package/dist/vite/index.js +28 -19
  102. package/dist/vite/internal/themeBoot.d.ts +25 -0
  103. package/dist/vite/internal/themeBoot.js +44 -0
  104. package/dist/vite/internal/wywOptions.d.ts +46 -0
  105. package/dist/vite/internal/wywOptions.js +44 -0
  106. package/package.json +34 -1
package/README.md CHANGED
@@ -14,7 +14,7 @@ Node ≥ 22, React 18 or 19, ESM. Heavy single-component libraries (charts, tabl
14
14
 
15
15
  ## Quick start
16
16
 
17
- A new app in one command: Vite with the DLS Linaria preset, Biome with the DLS rules, the three stylesheets, `GalaxyProvider`, and a working app frame with routing, a command palette and four pages on sample data.
17
+ A new app in one command: Vite with the DLS Linaria preset, Biome with the DLS rules, the three stylesheets, `GalaxyProvider`, and a thin Filament-shaped app: file routes, ConnectRPC queries on a mock transport, the frame and two pages.
18
18
 
19
19
  ```bash
20
20
  pnpm create @galaxy-io/galaxy-app my-app
@@ -78,7 +78,7 @@ The codemod rewrites everything mechanical and marks the rest with `@dls-migrate
78
78
 
79
79
  ## Claude skill
80
80
 
81
- [`skills/galaxy-ui`](./skills/galaxy-ui/SKILL.md) teaches Claude to design and build Galaxy UIs with this package: the workflow, the brand rules, the component decision tables, tokens, patterns and complete screen recipes. Its examples are type-checked against this repository (`pnpm skill:check`).
81
+ [`skills/galaxy-ui`](./skills/galaxy-ui/SKILL.md) teaches Claude to design, build and structure Galaxy apps with this package: the app architecture `create-galaxy-app` scaffolds (stack, files and naming, routing and URL state, the ConnectRPC data layer and mocks, screen shells, forms, mountable modules), the brand rules, the component decision tables, tokens, patterns and complete screen recipes. Its DLS examples are type-checked against this repository (`pnpm skill:check`).
82
82
 
83
83
  - **Claude Code:** copy the folder into your skills directory: `cp -R skills/galaxy-ui ~/.claude/skills/` (or a project's `.claude/skills/`).
84
84
  - **Claude apps:** run `pnpm skill:pack` and upload `dist-skill/galaxy-ui.zip` as a skill (Settings → Capabilities → Skills).
@@ -13,7 +13,7 @@ export declare enum BeaconSize {
13
13
  /** 10px, beside `body_lg` (20px line); a label is `body_lg` with an 8px gap. */
14
14
  X_LARGE = "X_LARGE"
15
15
  }
16
- /** Dot color role (Constitution V-A color set). Neutral steps resolve to `color.text.*`; statuses fill with `color.mark.<status>` and label with `color.text.<status>`. */
16
+ /** Dot color role (AGENTS.md "Variant": color set). Neutral steps resolve to `color.text.*`; statuses fill with `color.mark.<status>` and label with `color.text.<status>`. */
17
17
  export declare enum BeaconVariant {
18
18
  /** `text.primary`. The default (1.x `BASE` / `PRIMARY`). */
19
19
  PRIMARY = "PRIMARY",
@@ -1,4 +1,5 @@
1
1
  import Text, { TextSize, TextVariant } from "../text/Text.js";
2
+ import { ROLE_COLOR_TO_CSS_MAP } from "../styles/internal/roleColor.js";
2
3
  /* empty css */
3
4
  import { styled } from "@linaria/react";
4
5
  import { forwardRef } from "react";
@@ -46,7 +47,7 @@ var BeaconSize = /* @__PURE__ */ function(BeaconSize) {
46
47
  BeaconSize["X_LARGE"] = "X_LARGE";
47
48
  return BeaconSize;
48
49
  }({});
49
- /** Dot color role (Constitution V-A color set). Neutral steps resolve to `color.text.*`; statuses fill with `color.mark.<status>` and label with `color.text.<status>`. */
50
+ /** Dot color role (AGENTS.md "Variant": color set). Neutral steps resolve to `color.text.*`; statuses fill with `color.mark.<status>` and label with `color.text.<status>`. */
50
51
  var BeaconVariant = /* @__PURE__ */ function(BeaconVariant) {
51
52
  /** `text.primary`. The default (1.x `BASE` / `PRIMARY`). */
52
53
  BeaconVariant["PRIMARY"] = "PRIMARY";
@@ -102,7 +103,7 @@ var BEACON_SIZE_TO_GAP_CSS_MAP = {
102
103
  ["LARGE"]: "gx-Beacon-LARGE-lpeaf5b",
103
104
  ["X_LARGE"]: "gx-Beacon-X_LARGE-xoex4vi"
104
105
  };
105
- /** The label's type step per rung (Constitution III-A.4). */
106
+ /** The label's type step per rung (AGENTS.md "Control rungs"). */
106
107
  var BEACON_SIZE_TO_TEXT_SIZE_MAP = {
107
108
  ["X_SMALL"]: TextSize.CAPTION,
108
109
  ["SMALL"]: TextSize.BODY_SM,
@@ -124,38 +125,21 @@ var BEACON_VARIANT_TO_CSS_MAP = {
124
125
  ["WARNING"]: "gx-Beacon-WARNING-w1d27vzd",
125
126
  ["ERROR"]: "gx-Beacon-ERROR-eshtlvu"
126
127
  };
127
- /** Categorical `color`: the label `text.<family>`, the dot `mark.<family>`, the way a status variant renders. */
128
- var BEACON_COLOR_TO_CSS_MAP = {
129
- success: "gx-Beacon-success-s1nxs4in",
130
- warning: "gx-Beacon-warning-w1dc3rbq",
131
- error: "gx-Beacon-error-edasyys",
132
- red: "gx-Beacon-red-r1rjlf72",
133
- orange: "gx-Beacon-orange-ofhdj80",
134
- amber: "gx-Beacon-amber-a1lpbbc5",
135
- yellow: "gx-Beacon-yellow-y1wxkqi6",
136
- lime: "gx-Beacon-lime-l9ukjzr",
137
- green: "gx-Beacon-green-g1be6eig",
138
- emerald: "gx-Beacon-emerald-emvjtgh",
139
- teal: "gx-Beacon-teal-tkh8tqf",
140
- cyan: "gx-Beacon-cyan-c1e21vro",
141
- sky: "gx-Beacon-sky-sxwnre2",
142
- blue: "gx-Beacon-blue-b1qbmqgn",
143
- indigo: "gx-Beacon-indigo-idn9ked",
144
- violet: "gx-Beacon-violet-v1tc1xnc",
145
- purple: "gx-Beacon-purple-pgzv1cm",
146
- fuchsia: "gx-Beacon-fuchsia-f1marsuc",
147
- pink: "gx-Beacon-pink-p1ikfn3f",
148
- rose: "gx-Beacon-rose-romuo8"
149
- };
128
+ /**
129
+ * Categorical `color`: the label `text.<family>`, the dot `mark.<family>`, the way a status variant
130
+ * renders. Reads the shared `--gx-role-*` variables `ROLE_COLOR_TO_CSS_MAP` sets per family, so the
131
+ * twenty families are written once (`styles/internal/roleColor`).
132
+ */
133
+ var BEACON_COLOR_CSS = "gx-Beacon-BEACON_COLOR_CSS-b1nxs4in";
150
134
  /** Declared after the variant and color maps so `hex` wins over them: the label and the dot both take it. */
151
- var HEX_CSS = "gx-Beacon-HEX_CSS-h14k32og";
135
+ var HEX_CSS = "gx-Beacon-HEX_CSS-h1dc3rbq";
152
136
  /**
153
137
  * One pulse every thirteen `duration.base` steps (1.95s, the 1.x 2s default), linear, forever: the
154
138
  * ring, in the dot's fill, grows from the dot's edge to 2.5× while it fades from 0.5 to 0. Paint-only (`transform`), so
155
139
  * the line box never moves. The keyframes are global, so the name is `gx-` prefixed.
156
140
  * `REDUCED_MOTION` stops it and the ring falls back to its resting `opacity: 0`.
157
141
  */
158
- var PULSE_CSS = "gx-Beacon-PULSE_CSS-p88byx5";
142
+ var PULSE_CSS = "gx-Beacon-PULSE_CSS-pdasyys";
159
143
  /**
160
144
  * A status dot, alone or with its `label`; its color is a role (`variant`), a category (`color`) or
161
145
  * data (`hex`), and it can pulse.
@@ -163,7 +147,7 @@ var PULSE_CSS = "gx-Beacon-PULSE_CSS-p88byx5";
163
147
  var Beacon = forwardRef(function Beacon({ label, size = "MEDIUM", variant = "PRIMARY", color, hex, isPulse = false, ariaLabel, id, className, style, ...rest }, ref) {
164
148
  const variables = {};
165
149
  if (hex !== void 0) variables["--gx-beacon-hex"] = hex;
166
- const colorCss = cx(color !== void 0 ? BEACON_COLOR_TO_CSS_MAP[color] : BEACON_VARIANT_TO_CSS_MAP[variant], hex !== void 0 && HEX_CSS);
150
+ const colorCss = cx(color !== void 0 ? cx(ROLE_COLOR_TO_CSS_MAP[color], BEACON_COLOR_CSS) : BEACON_VARIANT_TO_CSS_MAP[variant], hex !== void 0 && HEX_CSS);
167
151
  if (label) return /* @__PURE__ */ jsxs(LabeledRoot, {
168
152
  ...rest,
169
153
  ref,
@@ -26,6 +26,9 @@ export interface GalaxyAlchemyWordmarkProps extends AriaAttributes {
26
26
  /** Inline style on the `<svg>`. */
27
27
  style?: CSSProperties;
28
28
  }
29
- /** Alchemy's product wordmark, painted `text.primary`. Labelled "Alchemy" unless `ariaLabel=""`. */
29
+ /**
30
+ * Alchemy's product wordmark, painted `text.primary`. Labelled "Alchemy" unless `ariaLabel=""`.
31
+ * Never beside a logomark.
32
+ */
30
33
  declare const GalaxyAlchemyWordmark: import("react").ForwardRefExoticComponent<GalaxyAlchemyWordmarkProps & import("react").RefAttributes<SVGSVGElement>>;
31
34
  export default GalaxyAlchemyWordmark;
@@ -9,13 +9,19 @@ import { cx } from "@linaria/core";
9
9
  * It behaves exactly like `GalaxyWordmark`: it paints `text.primary`, reads only CSS variables,
10
10
  * and is SSR-safe.
11
11
  *
12
+ * It always stands alone: never set it beside `GalaxyLogomark` (or any logomark). The product
13
+ * wordmark is the whole logo; only `GalaxyWordmark` pairs with the mark.
14
+ *
12
15
  * The artwork is `src/brand/assets/galaxy-alchemy-wordmark.svg`, compiled by `pnpm assets` into
13
16
  * the private `GalaxyAlchemyWordmarkSvg`; the aspect ratio comes from its
14
17
  * `GALAXY_ALCHEMY_WORDMARK_VIEW_BOX`.
15
18
  */
16
19
  /** Width ÷ height of the artwork, from its viewBox. */
17
20
  var GALAXY_ALCHEMY_WORDMARK_ASPECT_RATIO = GALAXY_ALCHEMY_WORDMARK_VIEW_BOX.width / GALAXY_ALCHEMY_WORDMARK_VIEW_BOX.height;
18
- /** Alchemy's product wordmark, painted `text.primary`. Labelled "Alchemy" unless `ariaLabel=""`. */
21
+ /**
22
+ * Alchemy's product wordmark, painted `text.primary`. Labelled "Alchemy" unless `ariaLabel=""`.
23
+ * Never beside a logomark.
24
+ */
19
25
  var GalaxyAlchemyWordmark = forwardRef(function GalaxyAlchemyWordmark({ size = 20, isInverse = false, ariaLabel = "Alchemy", id, className, style, ...rest }, ref) {
20
26
  const aria = brandMarkAriaProps(ariaLabel);
21
27
  return /* @__PURE__ */ jsx(GalaxyAlchemyWordmarkSvg, {
@@ -1,7 +1,7 @@
1
1
  import { type AriaAttributes, type CSSProperties } from "react";
2
2
  export interface GalaxyFilamentWordmarkProps extends AriaAttributes {
3
3
  /**
4
- * Height of the wordmark in px. The width follows the aspect ratio (≈ 3.76 × height).
4
+ * Height of the letters in px: the artwork is cropped to its ink, so `size` is the cap-to-baseline height with no empty band (like `GalaxyAlchemyWordmark`). The width follows the aspect ratio (≈ 4.07 × height).
5
5
  * @default 20
6
6
  */
7
7
  size?: number;
@@ -25,6 +25,9 @@ export interface GalaxyFilamentWordmarkProps extends AriaAttributes {
25
25
  /** Inline style on the `<svg>`. */
26
26
  style?: CSSProperties;
27
27
  }
28
- /** Filament's product wordmark, painted `text.primary`. Labelled "Filament" unless `ariaLabel=""`. */
28
+ /**
29
+ * Filament's product wordmark, painted `text.primary`. Labelled "Filament" unless `ariaLabel=""`.
30
+ * Never beside a logomark.
31
+ */
29
32
  declare const GalaxyFilamentWordmark: import("react").ForwardRefExoticComponent<GalaxyFilamentWordmarkProps & import("react").RefAttributes<SVGSVGElement>>;
30
33
  export default GalaxyFilamentWordmark;
@@ -9,13 +9,20 @@ import { cx } from "@linaria/core";
9
9
  * inline SVG. It behaves exactly like `GalaxyWordmark`: it paints `text.primary`, reads only CSS
10
10
  * variables, and is SSR-safe.
11
11
  *
12
+ * It always stands alone: never set it beside `GalaxyLogomark` (or any logomark). The product
13
+ * wordmark is the whole logo; only `GalaxyWordmark` pairs with the mark.
14
+ *
12
15
  * The artwork is `src/brand/assets/galaxy-filament-wordmark.svg`, compiled by `pnpm assets` into
13
16
  * the private `GalaxyFilamentWordmarkSvg`; the aspect ratio comes from its
14
- * `GALAXY_FILAMENT_WORDMARK_VIEW_BOX`.
17
+ * `GALAXY_FILAMENT_WORDMARK_VIEW_BOX`. The viewBox is cropped to the ink (`0 91 4513 1109`), so a
18
+ * `size` is the letters' height and no caller needs an ink-ratio correction (DLS 2.10).
15
19
  */
16
20
  /** Width ÷ height of the artwork, from its viewBox. */
17
21
  var GALAXY_FILAMENT_WORDMARK_ASPECT_RATIO = GALAXY_FILAMENT_WORDMARK_VIEW_BOX.width / GALAXY_FILAMENT_WORDMARK_VIEW_BOX.height;
18
- /** Filament's product wordmark, painted `text.primary`. Labelled "Filament" unless `ariaLabel=""`. */
22
+ /**
23
+ * Filament's product wordmark, painted `text.primary`. Labelled "Filament" unless `ariaLabel=""`.
24
+ * Never beside a logomark.
25
+ */
19
26
  var GalaxyFilamentWordmark = forwardRef(function GalaxyFilamentWordmark({ size = 20, isInverse = false, ariaLabel = "Filament", id, className, style, ...rest }, ref) {
20
27
  const aria = brandMarkAriaProps(ariaLabel);
21
28
  return /* @__PURE__ */ jsx(GalaxyFilamentWordmarkSvg, {
@@ -9,6 +9,9 @@ import { cx } from "@linaria/core";
9
9
  * monochrome fill (`color.solid.primary.background`, which is `text.primary`: the 1.x look). Color
10
10
  * is CSS (`fill="currentColor"`), so it is SSR-safe and a theme switch needs no re-render.
11
11
  *
12
+ * It pairs only with `GalaxyWordmark`. The product wordmarks (`GalaxyFilamentWordmark`,
13
+ * `GalaxyAlchemyWordmark`) stand alone: never set the mark beside them.
14
+ *
12
15
  * The artwork is `src/brand/assets/galaxy-logomark.svg`, compiled by `pnpm assets` into the private
13
16
  * `GalaxyLogomarkSvg`; this component only names, sizes and colors it.
14
17
  */
@@ -0,0 +1,27 @@
1
+ import { type AriaAttributes, type CSSProperties } from "react";
2
+ /** The product whose wordmark the credit shows. */
3
+ export declare enum PoweredByWordmark {
4
+ /** `GalaxyFilamentWordmark`. */
5
+ FILAMENT = "FILAMENT",
6
+ /** `GalaxyAlchemyWordmark`. */
7
+ ALCHEMY = "ALCHEMY"
8
+ }
9
+ export interface PoweredByProps extends AriaAttributes {
10
+ /** The product wordmark. An enum, not a node, so the wordmark always stands alone (never beside a logomark). */
11
+ wordmark: PoweredByWordmark;
12
+ /** The product's site. Opens in a new tab (`target="_blank"`, `rel="noopener noreferrer"`). */
13
+ href: string;
14
+ /** The link's name ("Powered by Filament"); " (opens in a new tab)" is appended. The wordmark itself is decorative. */
15
+ ariaLabel: string;
16
+ /** DOM id on the `<a>`. */
17
+ id?: string;
18
+ /** Any `data-*` attribute, forwarded to the `<a>`. */
19
+ [dataAttribute: `data-${string}`]: string | number | boolean | undefined;
20
+ /** Extra class on the `<a>`. */
21
+ className?: string;
22
+ /** Inline style on the `<a>`; only for setting CSS custom properties. */
23
+ style?: CSSProperties;
24
+ }
25
+ /** The sidebar credit: "Powered by" and a product wordmark, linking to the product in a new tab. */
26
+ declare const PoweredBy: import("react").ForwardRefExoticComponent<PoweredByProps & import("react").RefAttributes<HTMLAnchorElement>>;
27
+ export default PoweredBy;
@@ -0,0 +1,96 @@
1
+ import Text, { TextSize, TextVariant } from "../text/Text.js";
2
+ import GalaxyAlchemyWordmark from "./GalaxyAlchemyWordmark.js";
3
+ import GalaxyFilamentWordmark from "./GalaxyFilamentWordmark.js";
4
+ /* empty css */
5
+ import { styled } from "@linaria/react";
6
+ import { forwardRef } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ //#region src/brand/PoweredBy.tsx
9
+ /**
10
+ * The credit at the foot of a Galaxy module's sidebar: "Powered by" and the product wordmark, as
11
+ * one link that opens the product's site in a new tab. A 40px row (tall enough to centre on the
12
+ * Galaxy host's 24px theme toggle beside it) with `body_sm` tertiary text and the wordmark sized so
13
+ * every product reads at the same x-height (Filament 15px, Alchemy 12px); its accessible name is
14
+ * `ariaLabel` plus " (opens in a new tab)".
15
+ *
16
+ * `wordmark` is an enum of the product wordmarks, never a node: a product wordmark always stands
17
+ * alone (AGENTS.md "Marks"), so no logomark can be passed in. There is no trailing arrow either
18
+ * (`Link isExternal` would draw one after the logo); the new tab is in the name.
19
+ *
20
+ * Hover is a monochrome step on the mark, `text.tertiary` to `text.secondary`, the DLS's own hover
21
+ * idiom (a color change, never opacity). Focus is the `FOCUS_RING`. Not a nav destination
22
+ * (`NavItem`), not a body link (`Link`).
23
+ */
24
+ /** The product whose wordmark the credit shows. */
25
+ var PoweredByWordmark = /* @__PURE__ */ function(PoweredByWordmark) {
26
+ /** `GalaxyFilamentWordmark`. */
27
+ PoweredByWordmark["FILAMENT"] = "FILAMENT";
28
+ /** `GalaxyAlchemyWordmark`. */
29
+ PoweredByWordmark["ALCHEMY"] = "ALCHEMY";
30
+ return PoweredByWordmark;
31
+ }({});
32
+ /**
33
+ * Each wordmark's `size` (its full letter height), chosen so the products read at the same optical
34
+ * size: their lowercase bodies (x-heights) match, not their boxes. Filament's x-height is 527 of
35
+ * its 1109 units, so 15px gives 7.1px, about the `body_sm` text beside it. Alchemy's is 151 of
36
+ * 252, with tall ascenders and a descender around a heavy body, so at 15px its letters were 26%
37
+ * larger; 12px gives a 7.2px x-height and a width (58px) next to Filament's (61px). Measured from
38
+ * the artwork (Mitch, 2026-10-10: "alchemy feels a bit too big").
39
+ */
40
+ var POWERED_BY_WORDMARK_TO_SIZE_PX_MAP = {
41
+ ["FILAMENT"]: 15,
42
+ ["ALCHEMY"]: 12
43
+ };
44
+ /** What is appended to the name, as `Link isExternal` does. */
45
+ var NEW_TAB_SUFFIX = " (opens in a new tab)";
46
+ /**
47
+ * The row: 40px (32 + 8), 8px in from the sides like a `NavItem`'s content, the text and the mark
48
+ * 8px apart on one centre line. The radius gives the focus ring its corners.
49
+ */
50
+ var Root = /*#__PURE__*/ styled("a")({
51
+ name: "Root",
52
+ class: "gx-PoweredBy-r1hilrad",
53
+ propsAsIs: false
54
+ });
55
+ /**
56
+ * The mark's color: `text.tertiary` at rest, `text.secondary` while the row is hovered. The mark
57
+ * already transitions `color` on `duration.fast`. Declared in this module, whose CSS follows the
58
+ * wordmarks' (it imports them), so it wins over their `text.primary`.
59
+ */
60
+ var MARK_CSS = "gx-PoweredBy-MARK_CSS-m1s356ob";
61
+ /** The wordmark component per product: both take a px `size`, an `ariaLabel` and a class. */
62
+ var POWERED_BY_WORDMARK_TO_COMPONENT_MAP = {
63
+ ["FILAMENT"]: GalaxyFilamentWordmark,
64
+ ["ALCHEMY"]: GalaxyAlchemyWordmark
65
+ };
66
+ /** "Powered by" never wraps or shrinks: the row is short and the mark follows it. */
67
+ var LABEL_CSS = "gx-PoweredBy-LABEL_CSS-l1ez0mfr";
68
+ /** The sidebar credit: "Powered by" and a product wordmark, linking to the product in a new tab. */
69
+ var PoweredBy = forwardRef(function PoweredBy({ wordmark, href, ariaLabel, id, className, style, ...rest }, ref) {
70
+ const Wordmark = POWERED_BY_WORDMARK_TO_COMPONENT_MAP[wordmark];
71
+ return /* @__PURE__ */ jsxs(Root, {
72
+ "aria-label": `${ariaLabel}${NEW_TAB_SUFFIX}`,
73
+ ...rest,
74
+ ref,
75
+ id,
76
+ href,
77
+ target: "_blank",
78
+ rel: "noopener noreferrer",
79
+ className,
80
+ style,
81
+ children: [/* @__PURE__ */ jsx(Text, {
82
+ as: "span",
83
+ size: TextSize.BODY_SM,
84
+ variant: TextVariant.TERTIARY,
85
+ className: LABEL_CSS,
86
+ children: "Powered by"
87
+ }), /* @__PURE__ */ jsx(Wordmark, {
88
+ size: POWERED_BY_WORDMARK_TO_SIZE_PX_MAP[wordmark],
89
+ ariaLabel: "",
90
+ className: MARK_CSS
91
+ })]
92
+ });
93
+ });
94
+ PoweredBy.displayName = "PoweredBy";
95
+ //#endregion
96
+ export { PoweredByWordmark, PoweredBy as default };
@@ -8,6 +8,6 @@ declare const GalaxyAlchemyWordmarkSvg: import("react").ForwardRefExoticComponen
8
8
  export default GalaxyAlchemyWordmarkSvg;
9
9
  /** @internal The artwork's viewBox; the public mark derives its width as `size × width / height`. */
10
10
  export declare const GALAXY_ALCHEMY_WORDMARK_VIEW_BOX: {
11
- readonly width: 697;
11
+ readonly width: 1210;
12
12
  readonly height: 252;
13
13
  };
@@ -1,5 +1,5 @@
1
1
  import { forwardRef } from "react";
2
- import { jsx } from "react/jsx-runtime";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  //#region src/brand/internal/svg/GalaxyAlchemyWordmarkSvg.tsx
4
4
  /**
5
5
  * @internal Generated by `pnpm assets` from `src/brand/assets/galaxy-alchemy-wordmark.svg`.
@@ -7,22 +7,48 @@ import { jsx } from "react/jsx-runtime";
7
7
  * root has no size; the public mark that renders this sets both.
8
8
  */
9
9
  var GalaxyAlchemyWordmarkSvg = forwardRef(function GalaxyAlchemyWordmarkSvg(props, ref) {
10
- return /* @__PURE__ */ jsx("svg", {
11
- viewBox: "0 0 697 252",
10
+ return /* @__PURE__ */ jsxs("svg", {
11
+ viewBox: "0 0 1210 252",
12
12
  fill: "currentColor",
13
13
  xmlns: "http://www.w3.org/2000/svg",
14
14
  ref,
15
15
  ...props,
16
- children: /* @__PURE__ */ jsx("path", {
17
- d: "M46.56 188.16C-1.52588e-05 184.08 16.8 64.5601 70.56 77.28C75.6 78.48 81.36 83.04 84.24 91.92C93.12 67.92 122.16 72.96 126.24 82.8C115.92 94.8 115.2 124.56 116.4 138C118.32 157.2 128.64 142.8 132.96 117.36C133.68 113.52 143.28 114.48 142.32 119.28C136.8 147.36 130.8 187.92 109.68 187.92C82.8 187.92 83.52 152.16 83.52 140.88C83.52 139.92 82.08 139.92 82.08 140.88C78.96 158.16 72.96 190.56 46.56 188.16ZM71.76 93.6C61.2 94.3199 52.32 140.16 58.56 145.44C66 151.44 79.2 92.88 71.76 93.6ZM198.219 37.2C170.859 38.64 167.259 107.28 169.419 138C170.859 157.2 179.259 142.8 183.099 117.36C183.579 113.52 194.139 114.48 193.179 119.28C188.139 147.36 186.699 186.72 162.219 187.92C135.099 189.36 129.819 150.48 130.539 111.12C131.019 78.48 134.619 45.84 139.419 33.84C151.179 3.35999 196.539 8.40002 198.219 37.2ZM213.855 186.96C190.335 183.84 177.135 156.24 179.055 129.36C180.975 103.2 197.775 77.76 224.655 75.6C254.175 73.4399 260.895 101.28 257.055 114.96C250.095 139.92 218.655 135.6 222.015 110.16C223.215 101.52 229.935 95.28 236.895 96.72C235.935 90.24 229.455 91.2 226.575 93.36C211.695 104.16 214.335 138.72 230.175 143.04C246.975 147.36 260.175 126.24 261.855 117.6C262.575 113.52 271.935 115.44 271.215 119.52C267.615 137.04 253.455 192.48 213.855 186.96ZM325.474 38.16C304.834 43.4401 297.154 71.76 294.514 104.16C294.274 104.64 294.994 104.88 295.234 104.16C303.154 83.04 315.634 74.88 329.074 76.5601C342.994 78.24 351.634 87.12 353.314 98.16C355.954 118.8 345.394 146.64 353.554 148.32C357.634 149.04 363.394 135.36 366.514 117.36C367.234 113.52 376.834 114.48 375.874 119.28C370.354 147.36 362.434 186.96 340.114 187.92C288.994 190.32 323.074 103.92 317.794 100.32C307.714 93.12 298.834 148.08 302.914 177.36C304.834 192.72 263.314 194.88 262.354 180C260.434 149.28 256.114 71.28 267.154 36.96C279.394 0 326.674 7.91998 325.474 38.16ZM401.691 188.16C374.811 187.2 360.891 155.52 362.811 127.68C364.731 101.04 380.811 75.6 406.971 75.36C424.491 75.12 440.091 88.5601 434.571 114.48C430.011 137.52 410.571 144.96 402.411 132.72C401.931 132 401.211 131.28 401.451 132.24C401.691 142.56 410.811 149.76 418.251 149.28C429.051 148.56 436.731 135.84 440.331 117.84C441.051 114.72 449.211 115.92 448.731 119.28C446.091 144.24 435.291 189.6 401.691 188.16ZM412.011 91.2C405.771 94.08 400.971 116.16 403.611 118.56C409.371 123.6 420.651 86.88 412.011 91.2ZM473.587 104.16C481.267 81.6 493.987 76.08 507.427 76.5601C519.667 76.8 527.587 84.72 530.707 93.6C544.148 67.6801 580.388 73.4399 583.747 98.16C586.388 118.8 575.828 146.64 584.227 148.32C588.068 149.04 593.828 135.36 596.948 117.36C597.667 113.52 607.268 114.48 606.307 119.28C600.787 147.36 593.107 186.96 570.547 187.92C519.427 190.32 553.508 103.92 548.227 100.32C538.147 93.12 528.787 140.64 534.547 175.92C536.707 190.56 494.227 196.32 492.547 177.36C488.707 130.32 502.387 104.4 497.107 101.52C486.547 95.04 475.027 141.36 480.547 176.64C483.188 192 444.067 195.6 440.707 180.96C437.347 164.64 435.667 119.52 441.427 84.96C442.147 70.8 477.908 72 475.987 89.28C475.027 94.8 473.347 97.92 472.867 104.16C472.867 104.64 473.587 104.88 473.587 104.16ZM694.247 82.8C667.847 100.8 696.887 160.08 686.567 208.32C681.287 232.56 659.447 251.76 633.287 247.68C613.367 244.56 597.527 224.64 603.527 200.88C611.207 213.12 629.927 215.76 640.487 201.36C650.327 187.92 655.847 160.32 651.767 137.28C651.527 136.56 650.327 136.8 650.087 137.52C647.927 155.28 640.967 190.56 614.327 188.16C578.807 185.04 588.407 122.4 604.967 80.64C609.767 68.4 642.887 74.88 635.927 91.4399C627.527 111.36 621.047 140.88 626.567 145.44C628.967 147.36 631.847 142.32 634.727 134.88C642.167 114.24 642.887 77.52 670.727 74.16C680.807 72.72 691.367 75.84 694.247 82.8Z",
18
- fill: "currentColor"
19
- })
16
+ children: [
17
+ /* @__PURE__ */ jsx("path", {
18
+ d: "M916.725 201.365H873.342C866.329 201.374 860.638 195.691 860.638 188.678V125.367C860.335 116.982 853.684 111.063 846.064 110.76C837.789 110.432 831.028 116.039 830.203 124.601C830.169 124.98 830.161 125.359 830.161 125.746V188.678C830.153 195.691 824.461 201.382 817.448 201.374H774.057C767.044 201.374 761.361 195.682 761.361 188.661V62.6878C761.37 55.6748 767.061 49.9919 774.074 49.9919H1016C1023.01 49.9919 1028.7 55.6832 1028.71 62.6962L1028.72 188.686C1028.72 195.699 1023.04 201.391 1016.02 201.391H972.627C965.614 201.391 959.931 195.699 959.931 188.686V126.116C960.049 117.756 953.651 111.501 946.166 110.828C938.151 110.103 931.433 114.911 929.716 122.858C929.53 123.709 929.454 124.584 929.454 125.451L929.438 188.678C929.438 195.691 923.755 201.374 916.742 201.374L916.725 201.365Z",
19
+ fill: "currentColor"
20
+ }),
21
+ /* @__PURE__ */ jsx("path", {
22
+ d: "M1197.29 251.298L1054.64 251.332C1047.64 251.332 1041.95 245.658 1041.94 238.653L1041.91 214.103C1041.9 207.082 1047.58 201.382 1054.6 201.382H1127.38C1134.1 201.475 1139.12 197.812 1140.26 191.717C1141.33 185.967 1137.89 178.828 1131.2 177.573L1052.26 162.764C1046.25 161.636 1041.91 156.391 1041.91 150.279L1041.92 62.6962C1041.92 55.6832 1047.61 50.0004 1054.63 50.0004H1098.01C1105.02 50.0004 1110.71 55.6832 1110.71 62.7046V112.511C1111.05 121.612 1117.93 127.699 1126.36 127.623C1134.78 127.548 1141.27 120.871 1141.19 111.686L1141.22 62.7046C1141.22 55.6916 1146.91 50.0088 1153.91 50.0088H1197.3C1204.31 50.0088 1210 55.6916 1210 62.7046V238.619C1210 245.632 1204.31 251.315 1197.3 251.324L1197.29 251.298Z",
23
+ fill: "currentColor"
24
+ }),
25
+ /* @__PURE__ */ jsx("path", {
26
+ d: "M554.102 201.382H510.719C503.706 201.382 498.023 195.691 498.023 188.678L497.99 124.997C497.99 123.464 497.737 121.932 497.173 120.509C494.622 114.069 488.594 110.297 481.817 110.895C474.021 111.585 467.774 117.546 467.521 126.032V188.678C467.521 195.691 461.83 201.382 454.817 201.382H411.619C404.606 201.374 398.924 195.691 398.924 188.678V12.7463C398.924 5.73332 404.615 0.0420837 411.628 0.0420837H454.826C461.839 0.0420837 467.521 5.71648 467.53 12.7295L467.547 33.6254C467.496 42.0949 473.036 48.5102 481.43 49.8656C482.011 49.9582 482.6 49.9835 483.189 49.9835H554.094C561.107 49.9835 566.798 55.6663 566.798 62.6877V188.678C566.798 195.691 561.107 201.382 554.094 201.382H554.102Z",
27
+ fill: "currentColor"
28
+ }),
29
+ /* @__PURE__ */ jsx("path", {
30
+ d: "M659.811 156.618L735.397 156.635C742.41 156.635 748.101 162.326 748.092 169.339V188.678C748.084 195.691 742.393 201.374 735.38 201.374H592.712C585.699 201.374 580.007 195.682 580.007 188.669V62.6962C580.007 55.6832 585.69 49.992 592.712 49.992H735.38C742.393 49.9835 748.084 55.6663 748.084 62.6794V122.74C748.084 129.753 742.401 135.445 735.388 135.445H659.525C658.363 135.436 657.201 135.562 656.09 135.908C651.274 137.423 648.656 141.725 648.892 146.6C649.161 152.207 653.488 156.618 659.811 156.618ZM679.436 92.5583C679.436 84.1225 672.583 77.2863 664.13 77.2863C655.677 77.2863 648.824 84.1225 648.824 92.5583C648.824 100.994 655.677 107.83 664.13 107.83C672.583 107.83 679.436 100.994 679.436 92.5583Z",
31
+ fill: "currentColor"
32
+ }),
33
+ /* @__PURE__ */ jsx("path", {
34
+ d: "M73.0584 201.146C32.9756 201.037 2.10318 170.308 0.208912 130.94C-1.11287 111.77 3.82066 93.6528 15.4894 78.305C29.9448 60.12 51.3879 50.1603 74.919 50.1182L155.27 49.9835C162.291 49.9751 167.991 55.6579 167.991 62.6878V188.669C167.991 195.699 162.291 201.391 155.261 201.374L73.05 201.146H73.0584ZM99.132 125.662C99.132 117.302 92.3379 110.524 83.961 110.524C75.5841 110.524 68.79 117.302 68.79 125.662C68.79 134.022 75.5841 140.799 83.961 140.799C92.3379 140.799 99.132 134.022 99.132 125.662Z",
35
+ fill: "currentColor"
36
+ }),
37
+ /* @__PURE__ */ jsx("path", {
38
+ d: "M347.155 140.631L375.519 140.681C382.523 140.69 388.198 146.381 388.198 153.385V188.678C388.181 195.691 382.498 201.374 375.485 201.374H275.973C268.96 201.374 263.269 195.682 263.269 188.669V62.6878C263.269 55.6748 268.96 49.9835 275.973 49.9835H375.485C382.498 49.9835 388.181 55.6663 388.189 62.6793V97.9549C388.206 104.959 382.532 110.651 375.527 110.659L346.785 110.71C338.198 111.147 332.094 117.689 332.018 125.628C331.942 133.567 337.995 140.605 347.164 140.622L347.155 140.631Z",
39
+ fill: "currentColor"
40
+ }),
41
+ /* @__PURE__ */ jsx("path", {
42
+ d: "M237.245 0H193.854C186.838 0 181.15 5.68789 181.15 12.7042V188.703C181.15 195.719 186.838 201.407 193.854 201.407H237.245C244.262 201.407 249.95 195.719 249.95 188.703V12.7042C249.95 5.68789 244.262 0 237.245 0Z",
43
+ fill: "currentColor"
44
+ })
45
+ ]
20
46
  });
21
47
  });
22
48
  GalaxyAlchemyWordmarkSvg.displayName = "GalaxyAlchemyWordmarkSvg";
23
49
  /** @internal The artwork's viewBox; the public mark derives its width as `size × width / height`. */
24
50
  var GALAXY_ALCHEMY_WORDMARK_VIEW_BOX = {
25
- width: 697,
51
+ width: 1210,
26
52
  height: 252
27
53
  };
28
54
  //#endregion
@@ -9,5 +9,5 @@ export default GalaxyFilamentWordmarkSvg;
9
9
  /** @internal The artwork's viewBox; the public mark derives its width as `size × width / height`. */
10
10
  export declare const GALAXY_FILAMENT_WORDMARK_VIEW_BOX: {
11
11
  readonly width: 4513;
12
- readonly height: 1200;
12
+ readonly height: 1109;
13
13
  };
@@ -9,7 +9,7 @@ import { jsx } from "react/jsx-runtime";
9
9
  var GalaxyFilamentWordmarkSvg = forwardRef(function GalaxyFilamentWordmarkSvg(props, ref) {
10
10
  return /* @__PURE__ */ jsx("svg", {
11
11
  xmlns: "http://www.w3.org/2000/svg",
12
- viewBox: "0 0 4513 1200",
12
+ viewBox: "0 91 4513 1109",
13
13
  fill: "currentColor",
14
14
  ref,
15
15
  ...props,
@@ -20,7 +20,7 @@ GalaxyFilamentWordmarkSvg.displayName = "GalaxyFilamentWordmarkSvg";
20
20
  /** @internal The artwork's viewBox; the public mark derives its width as `size × width / height`. */
21
21
  var GALAXY_FILAMENT_WORDMARK_VIEW_BOX = {
22
22
  width: 4513,
23
- height: 1200
23
+ height: 1109
24
24
  };
25
25
  //#endregion
26
26
  export { GALAXY_FILAMENT_WORDMARK_VIEW_BOX, GalaxyFilamentWordmarkSvg as default };
@@ -13,7 +13,7 @@ import { formatChartValue } from "./chartFormat.js";
13
13
  import { useChartDimensions } from "./useChartDimensions.js";
14
14
  import { useChartFormatters } from "./useChartFormatters.js";
15
15
  import { useChartInteraction } from "./useChartInteraction.js";
16
- import { HEATMAP_CELL_RADIUS, HEATMAP_STEP_TO_TOKEN_MAP, buildHeatmapGeometry, estimateRowLabelInset, getHeatmapDomain, getHeatmapLabels } from "./heatmapGeometry.js";
16
+ import { HEATMAP_CELL_RADIUS, HEATMAP_STEP_TO_TOKEN_MAP, buildHeatmapGeometry, estimateRowLabelInset, getHeatmapDomain, getHeatmapLabels, heatmapLoadingAxes } from "./heatmapGeometry.js";
17
17
  /* empty css */
18
18
  import { styled } from "@linaria/react";
19
19
  import { forwardRef, useCallback, useMemo, useRef } from "react";
@@ -117,8 +117,17 @@ var Heatmap = forwardRef(function Heatmap(props, ref) {
117
117
  domainMax
118
118
  ]);
119
119
  const ramp = HEATMAP_STEP_TO_TOKEN_MAP[color];
120
+ const isPlaceholder = isLoading && (columns.length === 0 || rows.length === 0);
121
+ const { columns: gridColumns, rows: gridRows } = useMemo(() => isPlaceholder ? heatmapLoadingAxes() : {
122
+ columns,
123
+ rows
124
+ }, [
125
+ isPlaceholder,
126
+ columns,
127
+ rows
128
+ ]);
120
129
  const formattedRows = useMemo(() => rows.map(formatLabel), [rows, formatLabel]);
121
- const insetLeft = useMemo(() => estimateRowLabelInset(formattedRows), [formattedRows]);
130
+ const insetLeft = useMemo(() => isPlaceholder ? PLOT_INSET_RIGHT : estimateRowLabelInset(formattedRows), [isPlaceholder, formattedRows]);
122
131
  const dimensions = useChartDimensions(plotRef, useMemo(() => ({
123
132
  top: PLOT_INSET_TOP,
124
133
  right: PLOT_INSET_RIGHT,
@@ -128,15 +137,15 @@ var Heatmap = forwardRef(function Heatmap(props, ref) {
128
137
  const { plotWidth, plotHeight } = dimensions;
129
138
  const geometry = useMemo(() => buildHeatmapGeometry({
130
139
  cells,
131
- columns,
132
- rows,
140
+ columns: gridColumns,
141
+ rows: gridRows,
133
142
  domain,
134
143
  plotWidth,
135
144
  plotHeight
136
145
  }), [
137
146
  cells,
138
- columns,
139
- rows,
147
+ gridColumns,
148
+ gridRows,
140
149
  domain,
141
150
  plotWidth,
142
151
  plotHeight
@@ -229,7 +238,7 @@ var Heatmap = forwardRef(function Heatmap(props, ref) {
229
238
  ]);
230
239
  const passedAriaLabel = typeof rest["aria-label"] === "string" ? rest["aria-label"] : void 0;
231
240
  const resolvedAriaLabel = ariaLabel ?? passedAriaLabel ?? `Heatmap, ${columns.length} columns by ${rows.length} rows`;
232
- const aspectRatio = clamp(columns.length / Math.max(1, rows.length), 1, 4);
241
+ const aspectRatio = clamp(gridColumns.length / Math.max(1, gridRows.length), 1, 4);
233
242
  return /* @__PURE__ */ jsx(ChartFrame, {
234
243
  rootRef: ref,
235
244
  plotRef,
@@ -243,7 +252,7 @@ var Heatmap = forwardRef(function Heatmap(props, ref) {
243
252
  categoryCount: cellCount,
244
253
  ariaLabel: resolvedAriaLabel,
245
254
  aspectRatio,
246
- axes: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ChartCategoryAxis, {
255
+ axes: isPlaceholder ? null : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ChartCategoryAxis, {
247
256
  labels: columns,
248
257
  positions: geometry.columnPositions,
249
258
  step: geometry.columnStep,
@@ -283,7 +292,14 @@ var Heatmap = forwardRef(function Heatmap(props, ref) {
283
292
  hasEmpty: geometry.hasEmptyCells,
284
293
  inset: insetLeft
285
294
  }),
286
- children: geometry.cells.map((cell, index) => {
295
+ children: isPlaceholder ? geometry.cells.map((cell) => /* @__PURE__ */ jsx("rect", {
296
+ x: cell.x,
297
+ y: cell.y,
298
+ width: cell.width,
299
+ height: cell.height,
300
+ rx: HEATMAP_CELL_RADIUS,
301
+ className: HEATMAP_EMPTY_CELL_CSS
302
+ }, cell.id)) : geometry.cells.map((cell, index) => {
287
303
  let state = interaction.getMarkState({
288
304
  categoryIndex: index,
289
305
  seriesKey: cell.row
@@ -14,7 +14,7 @@ export declare enum SparklineSize {
14
14
  /** 40px tall, 160px wide. */
15
15
  X_LARGE = "X_LARGE"
16
16
  }
17
- /** Color role (Constitution V-A color set; subset). */
17
+ /** Color role (AGENTS.md "Variant": color set, subset). */
18
18
  export declare enum SparklineVariant {
19
19
  /** `text.primary`. */
20
20
  PRIMARY = "PRIMARY",
@@ -1,3 +1,4 @@
1
+ import { ROLE_COLOR_TO_CSS_MAP } from "../styles/internal/roleColor.js";
1
2
  import { ChartCurve } from "./types.js";
2
3
  import { buildLinePath } from "./lineChartGeometry.js";
3
4
  import { layoutBars } from "./barChartGeometry.js";
@@ -37,7 +38,7 @@ var SparklineSize = /* @__PURE__ */ function(SparklineSize) {
37
38
  SparklineSize["X_LARGE"] = "X_LARGE";
38
39
  return SparklineSize;
39
40
  }({});
40
- /** Color role (Constitution V-A color set; subset). */
41
+ /** Color role (AGENTS.md "Variant": color set, subset). */
41
42
  var SparklineVariant = /* @__PURE__ */ function(SparklineVariant) {
42
43
  /** `text.primary`. */
43
44
  SparklineVariant["PRIMARY"] = "PRIMARY";
@@ -110,31 +111,14 @@ var SPARKLINE_VARIANT_TO_CSS_MAP = {
110
111
  ["WARNING"]: "gx-Sparkline-WARNING-w12wppjx",
111
112
  ["ERROR"]: "gx-Sparkline-ERROR-e1vjlz3y"
112
113
  };
113
- /** Categorical `color`: `mark.<family>`, the way a status variant renders. */
114
- var SPARKLINE_COLOR_TO_CSS_MAP = {
115
- success: "gx-Sparkline-success-s1g1xl1p",
116
- warning: "gx-Sparkline-warning-w1jau8rz",
117
- error: "gx-Sparkline-error-e1oe0nww",
118
- red: "gx-Sparkline-red-r927tvl",
119
- orange: "gx-Sparkline-orange-o17vquw4",
120
- amber: "gx-Sparkline-amber-a1dzgnla",
121
- yellow: "gx-Sparkline-yellow-y11hl6v6",
122
- lime: "gx-Sparkline-lime-l1dtbnvn",
123
- green: "gx-Sparkline-green-g1hj4qmv",
124
- emerald: "gx-Sparkline-emerald-e157jvnt",
125
- teal: "gx-Sparkline-teal-t14oiqli",
126
- cyan: "gx-Sparkline-cyan-czvb5wf",
127
- sky: "gx-Sparkline-sky-s1rblyi3",
128
- blue: "gx-Sparkline-blue-b1lhbciw",
129
- indigo: "gx-Sparkline-indigo-i1l7cy0y",
130
- violet: "gx-Sparkline-violet-vpfz7ft",
131
- purple: "gx-Sparkline-purple-p14stz7g",
132
- fuchsia: "gx-Sparkline-fuchsia-f41c05i",
133
- pink: "gx-Sparkline-pink-psamfb6",
134
- rose: "gx-Sparkline-rose-r3yynzk"
135
- };
114
+ /**
115
+ * Categorical `color`: `mark.<family>`, the way a status variant renders. Reads the shared
116
+ * `--gx-role-*` variables `ROLE_COLOR_TO_CSS_MAP` sets per family, so the twenty families are
117
+ * written once (`styles/internal/roleColor`).
118
+ */
119
+ var SPARKLINE_COLOR_CSS = "gx-Sparkline-SPARKLINE_COLOR_CSS-s1g1xl1p";
136
120
  /** Declared after the variant and color maps so `hex` wins over them. */
137
- var HEX_CSS = "gx-Sparkline-HEX_CSS-hhfwv7i";
121
+ var HEX_CSS = "gx-Sparkline-HEX_CSS-h1jau8rz";
138
122
  /** A finite reading, or `null` for a gap. */
139
123
  var toReading = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
140
124
  /** The vertical range: the override where given, else the mark's default from the readings. */
@@ -228,7 +212,7 @@ var Sparkline = forwardRef(function Sparkline({ data, mark = "LINE", variant = "
228
212
  ...accessibility,
229
213
  ref,
230
214
  id,
231
- className: cx(SPARKLINE_SIZE_TO_CSS_MAP[size], color !== void 0 ? SPARKLINE_COLOR_TO_CSS_MAP[color] : SPARKLINE_VARIANT_TO_CSS_MAP[variant], hex !== void 0 && HEX_CSS, fillWidth && FILL_WIDTH_CSS, className),
215
+ className: cx(SPARKLINE_SIZE_TO_CSS_MAP[size], color !== void 0 ? cx(ROLE_COLOR_TO_CSS_MAP[color], SPARKLINE_COLOR_CSS) : SPARKLINE_VARIANT_TO_CSS_MAP[variant], hex !== void 0 && HEX_CSS, fillWidth && FILL_WIDTH_CSS, className),
232
216
  style: {
233
217
  ...variables,
234
218
  ...style
@@ -1,5 +1,5 @@
1
1
  import type { ChartLabelFormatter, ChartValueFormatter } from "./types.js";
2
- /** @internal How a gap (a `null` reading) renders in the tooltip. */
2
+ /** @internal How a gap (a `null` reading) renders in the tooltip: the shared `EMPTY_VALUE`. */
3
3
  export declare const CHART_NULL_VALUE = "\u2014";
4
4
  /** @internal The default value formatter: grouped, at most two fraction digits. */
5
5
  export declare const DEFAULT_CHART_VALUE_FORMATTER: ChartValueFormatter;
@@ -5,7 +5,7 @@ import { formatNumber } from "../utils/format.js";
5
5
  * ticks, tooltip rows and announcements cannot drift apart. Built on `utils/format` (en-US by
6
6
  * default, so the server and the client agree).
7
7
  */
8
- /** @internal How a gap (a `null` reading) renders in the tooltip. */
8
+ /** @internal How a gap (a `null` reading) renders in the tooltip: the shared `EMPTY_VALUE`. */
9
9
  var CHART_NULL_VALUE = "—";
10
10
  /** @internal The default value formatter: grouped, at most two fraction digits. */
11
11
  var DEFAULT_CHART_VALUE_FORMATTER = (value) => formatNumber(value, { precision: 2 });
@@ -21,7 +21,7 @@ function resolveLabelFormatter(labelFormatter) {
21
21
  }
22
22
  /** @internal Formats a reading, rendering a gap or a non-finite value as "—". */
23
23
  function formatChartValue(value, formatter) {
24
- return value === null || !Number.isFinite(value) ? "—" : formatter(value);
24
+ return value === null || !Number.isFinite(value) ? CHART_NULL_VALUE : formatter(value);
25
25
  }
26
26
  //#endregion
27
27
  export { CHART_NULL_VALUE, DEFAULT_CHART_LABEL_FORMATTER, DEFAULT_CHART_VALUE_FORMATTER, formatChartValue, resolveLabelFormatter, resolveValueFormatter };
@@ -1,6 +1,20 @@
1
1
  import { ChartPalette } from "./types.js";
2
2
  /** @internal Cell corner radius: `radius.sm`. */
3
3
  export declare const HEATMAP_CELL_RADIUS: number;
4
+ /**
5
+ * @internal The placeholder grid a loading heatmap draws when it has no rows or columns yet: a
6
+ * week of hours (7 × 24), the shape most Galaxy heatmaps take, so the frame holds its final
7
+ * proportions and reads as a heatmap while data loads.
8
+ */
9
+ export declare const HEATMAP_LOADING_GRID: {
10
+ readonly columns: 24;
11
+ readonly rows: 7;
12
+ };
13
+ /** @internal The loading grid's column and row keys: positional, never shown (no axes). */
14
+ export declare function heatmapLoadingAxes(): {
15
+ columns: string[];
16
+ rows: string[];
17
+ };
4
18
  /** @internal Number of ramp steps. */
5
19
  export declare const HEATMAP_STEP_COUNT = 5;
6
20
  /** @internal The aspect-ratio fallback is clamped to these, so cells stay near-square. */