@galaxy-io/dls 2.9.0 → 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 (101) hide show
  1. package/dist/beacons/Beacon.d.ts +1 -1
  2. package/dist/beacons/Beacon.js +12 -28
  3. package/dist/brand/GalaxyAlchemyWordmark.d.ts +4 -1
  4. package/dist/brand/GalaxyAlchemyWordmark.js +7 -1
  5. package/dist/brand/GalaxyFilamentWordmark.d.ts +5 -2
  6. package/dist/brand/GalaxyFilamentWordmark.js +9 -2
  7. package/dist/brand/GalaxyLogomark.js +3 -0
  8. package/dist/brand/PoweredBy.d.ts +27 -0
  9. package/dist/brand/PoweredBy.js +96 -0
  10. package/dist/brand/internal/svg/GalaxyFilamentWordmarkSvg.d.ts +1 -1
  11. package/dist/brand/internal/svg/GalaxyFilamentWordmarkSvg.js +2 -2
  12. package/dist/charts/Heatmap.js +25 -9
  13. package/dist/charts/Sparkline.d.ts +1 -1
  14. package/dist/charts/Sparkline.js +10 -26
  15. package/dist/charts/chartFormat.d.ts +1 -1
  16. package/dist/charts/chartFormat.js +2 -2
  17. package/dist/charts/heatmapGeometry.d.ts +14 -0
  18. package/dist/charts/heatmapGeometry.js +17 -1
  19. package/dist/chips/Chip.d.ts +2 -2
  20. package/dist/chips/Chip.js +15 -31
  21. package/dist/drawer/Drawer.d.ts +2 -2
  22. package/dist/drawer/Drawer.js +1 -1
  23. package/dist/editor/CodeEditor.d.ts +1 -1
  24. package/dist/editor/CodeEditor.js +2 -1
  25. package/dist/feedback/Alert.d.ts +36 -9
  26. package/dist/feedback/Alert.js +26 -8
  27. package/dist/feedback/ProgressBar.d.ts +4 -1
  28. package/dist/feedback/ProgressBar.js +17 -30
  29. package/dist/feedback/ProgressCircle.d.ts +1 -1
  30. package/dist/feedback/ProgressCircle.js +14 -30
  31. package/dist/hooks/useEndReached.d.ts +40 -0
  32. package/dist/hooks/useEndReached.js +69 -0
  33. package/dist/icons/Icon.d.ts +36 -8
  34. package/dist/icons/Icon.js +14 -7
  35. package/dist/inputs/CronInput.js +114 -78
  36. package/dist/inputs/DateInput.d.ts +1 -1
  37. package/dist/inputs/DateInput.js +10 -10
  38. package/dist/inputs/MultiSelectInput.d.ts +3 -1
  39. package/dist/inputs/MultiSelectInput.js +8 -3
  40. package/dist/inputs/SelectInput.d.ts +8 -1
  41. package/dist/inputs/SelectInput.js +52 -25
  42. package/dist/inputs/internal/selectAll.d.ts +11 -0
  43. package/dist/inputs/internal/selectAll.js +28 -0
  44. package/dist/json/JsonViewer.js +7 -6
  45. package/dist/layout/AppFrame.d.ts +20 -0
  46. package/dist/layout/AppFrame.js +71 -0
  47. package/dist/layout/EmptyLayout.d.ts +53 -0
  48. package/dist/layout/EmptyLayout.js +59 -0
  49. package/dist/layout/ErrorLayout.d.ts +42 -0
  50. package/dist/layout/ErrorLayout.js +60 -0
  51. package/dist/layout/PageLayout.d.ts +26 -0
  52. package/dist/layout/PageLayout.js +116 -0
  53. package/dist/layout/PendingLayout.d.ts +30 -0
  54. package/dist/layout/PendingLayout.js +57 -0
  55. package/dist/layout/internal/errorState.d.ts +14 -0
  56. package/dist/layout/internal/errorState.js +49 -0
  57. package/dist/layout/internal/region.d.ts +10 -0
  58. package/dist/layout/internal/region.js +24 -0
  59. package/dist/lists/DescriptionList.js +1 -0
  60. package/dist/menu/Menu.d.ts +2 -2
  61. package/dist/menu/Menu.js +6 -13
  62. package/dist/modal/Modal.d.ts +2 -2
  63. package/dist/modal/Modal.js +1 -1
  64. package/dist/navigation/CommandPalette.js +4 -11
  65. package/dist/navigation/SidebarNav.d.ts +5 -0
  66. package/dist/navigation/SidebarNav.js +41 -22
  67. package/dist/navigation/Topbar.js +4 -0
  68. package/dist/shapes/Circle.d.ts +1 -1
  69. package/dist/shapes/Circle.js +10 -26
  70. package/dist/shapes/Square.d.ts +1 -1
  71. package/dist/shapes/Square.js +10 -26
  72. package/dist/styles/internal/roleColor.d.ts +3 -0
  73. package/dist/styles/internal/roleColor.js +42 -0
  74. package/dist/styles/mixins.js +1 -1
  75. package/dist/styles.css +1 -1
  76. package/dist/table/InfiniteSpreadsheet.js +6 -6
  77. package/dist/table/InfiniteTable.d.ts +52 -20
  78. package/dist/table/InfiniteTable.js +3 -2
  79. package/dist/table/TableCore.d.ts +7 -1
  80. package/dist/table/TableCore.js +93 -83
  81. package/dist/table/VirtualizedInfiniteTable.d.ts +53 -21
  82. package/dist/table/VirtualizedInfiniteTable.js +7 -5
  83. package/dist/table/useInfiniteScrollSentinel.d.ts +13 -13
  84. package/dist/table/useInfiniteScrollSentinel.js +7 -51
  85. package/dist/theme/tokens/dark.js +1 -1
  86. package/dist/theme/tokens/light.js +4 -3
  87. package/dist/theme/tokens/types.d.ts +7 -7
  88. package/dist/timeline/Timeline.d.ts +1 -1
  89. package/dist/timeline/Timeline.js +6 -24
  90. package/dist/tokens.css +1 -1
  91. package/dist/utils/format.d.ts +35 -10
  92. package/dist/utils/format.js +60 -12
  93. package/dist/utils/search.d.ts +15 -0
  94. package/dist/utils/search.js +24 -0
  95. package/dist/vite/index.d.ts +16 -2
  96. package/dist/vite/index.js +28 -19
  97. package/dist/vite/internal/themeBoot.d.ts +25 -0
  98. package/dist/vite/internal/themeBoot.js +44 -0
  99. package/dist/vite/internal/wywOptions.d.ts +46 -0
  100. package/dist/vite/internal/wywOptions.js +44 -0
  101. package/package.json +34 -1
@@ -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 };
@@ -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. */
@@ -13,6 +13,22 @@ import { CHART_PALETTE_TO_HUE_MAP } from "./chartPalette.js";
13
13
  */
14
14
  /** @internal Cell corner radius: `radius.sm`. */
15
15
  var HEATMAP_CELL_RADIUS = Number.parseFloat(RADIUS.sm);
16
+ /**
17
+ * @internal The placeholder grid a loading heatmap draws when it has no rows or columns yet: a
18
+ * week of hours (7 × 24), the shape most Galaxy heatmaps take, so the frame holds its final
19
+ * proportions and reads as a heatmap while data loads.
20
+ */
21
+ var HEATMAP_LOADING_GRID = {
22
+ columns: 24,
23
+ rows: 7
24
+ };
25
+ /** @internal The loading grid's column and row keys: positional, never shown (no axes). */
26
+ function heatmapLoadingAxes() {
27
+ return {
28
+ columns: Array.from({ length: HEATMAP_LOADING_GRID.columns }, (_, index) => `c${index}`),
29
+ rows: Array.from({ length: HEATMAP_LOADING_GRID.rows }, (_, index) => `r${index}`)
30
+ };
31
+ }
16
32
  /** @internal Number of ramp steps. */
17
33
  var HEATMAP_STEP_COUNT = 5;
18
34
  /** @internal The aspect-ratio fallback is clamped to these, so cells stay near-square. */
@@ -152,4 +168,4 @@ function buildHeatmapGeometry({ cells, columns, rows, domain, plotWidth, plotHei
152
168
  return geometry;
153
169
  }
154
170
  //#endregion
155
- export { HEATMAP_CELL_RADIUS, HEATMAP_MAX_ASPECT_RATIO, HEATMAP_MIN_ASPECT_RATIO, HEATMAP_STEP_COUNT, HEATMAP_STEP_TO_TOKEN_MAP, buildHeatmapGeometry, estimateRowLabelInset, getHeatmapDomain, getHeatmapLabels, getHeatmapStep };
171
+ export { HEATMAP_CELL_RADIUS, HEATMAP_LOADING_GRID, HEATMAP_MAX_ASPECT_RATIO, HEATMAP_MIN_ASPECT_RATIO, HEATMAP_STEP_COUNT, HEATMAP_STEP_TO_TOKEN_MAP, buildHeatmapGeometry, estimateRowLabelInset, getHeatmapDomain, getHeatmapLabels, getHeatmapStep, heatmapLoadingAxes };
@@ -15,8 +15,8 @@ export declare enum ChipSize {
15
15
  X_LARGE = "X_LARGE"
16
16
  }
17
17
  /**
18
- * Color role (Constitution V-A color set; meaning only): tints the fill, the text and the border
19
- * together. Categories take `color` instead.
18
+ * Color role (AGENTS.md "Variant": color set, meaning only): tints the fill, the text and the
19
+ * border together. Categories take `color` instead.
20
20
  */
21
21
  export declare enum ChipVariant {
22
22
  /** `background.primary` fill, `text.primary`. */