cortena-ui 1.11.0 → 1.12.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.
- package/CHANGELOG.md +22 -0
- package/README.md +21 -2
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/button.d.ts +1 -1
- package/dist/components/chart/nivo-theme.js +23 -5
- package/dist/components/chart/nivo-theme.js.map +1 -1
- package/dist/components/chart/recharts-charts.js +9 -14
- package/dist/components/chart/recharts-charts.js.map +1 -1
- package/dist/components/chart/tokens.js +21 -1
- package/dist/components/chart/tokens.js.map +1 -1
- package/dist/core.d.ts +2 -1
- package/dist/index.d.ts +2 -1
- package/package.json +3 -7
- package/src/components/chart/nivo-theme.ts +23 -4
- package/src/components/chart/recharts-charts.tsx +13 -10
- package/src/components/chart/tokens.ts +19 -0
- package/src/entries/core.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,28 @@
|
|
|
3
3
|
Notable changes per release. Versions before 1.6.0 are recorded in the git log
|
|
4
4
|
and in `../../CONSUMING.md`; this file starts where the changelog does.
|
|
5
5
|
|
|
6
|
+
## 1.12.0
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
|
|
10
|
+
- **`RenderProp` is exported** from `cortena-ui/core` and the root barrel, so a
|
|
11
|
+
consumer can name the type its wrappers around `Card`, `Breadcrumb` and
|
|
12
|
+
`ButtonLink` already use (DESIGN-51).
|
|
13
|
+
- **`cortena-design` peer range is bounded** at `>=3.4.0 <4`; a future 4.x no
|
|
14
|
+
longer resolves silently (DESIGN-51).
|
|
15
|
+
- **Chart SSR fallbacks match the tokens.** The no-DOM fallbacks for
|
|
16
|
+
`--ds-radius-md` and `--ds-radius-sm` were 6 and 4; the tokens are 12 and 8,
|
|
17
|
+
so a server-rendered Nivo tooltip drew at half radius until hydration. The
|
|
18
|
+
plot margin now reads `--ds-space-2` through `plotMargin()` instead of a raw
|
|
19
|
+
8. Pixel-identical in the browser; asserted by test (DESIGN-51).
|
|
20
|
+
|
|
21
|
+
### Removed
|
|
22
|
+
|
|
23
|
+
- `@nivo/bar`, `@nivo/core`, `@nivo/line`, `@nivo/pie`, `@nivo/scatterplot`
|
|
24
|
+
as dependencies — nothing imported them; those chart types render on the
|
|
25
|
+
Recharts side. `@nivo/core` stays as a transitive of the four Nivo charts
|
|
26
|
+
that remain (DESIGN-51).
|
|
27
|
+
|
|
6
28
|
## 1.11.0
|
|
7
29
|
|
|
8
30
|
### Added
|
package/README.md
CHANGED
|
@@ -122,8 +122,9 @@ regression; `test/chart-bundle.test.tsx` says which line caused it.
|
|
|
122
122
|
`text-[color:var(--ds-foreground)]` and `text-[length:var(--ds-text-caption)]`.
|
|
123
123
|
Backgrounds, borders and radii are unambiguous and need no hint.
|
|
124
124
|
- **Tested in a real browser.** Tests assert computed pixels against the
|
|
125
|
-
token the browser resolved
|
|
126
|
-
|
|
125
|
+
token the browser resolved. A dangling `var()` paints transparent, which the
|
|
126
|
+
tests catch and jsdom cannot. Most tests pin a theme and run once; see
|
|
127
|
+
"Which tests run in both themes".
|
|
127
128
|
- **Every component appears in the guide.** `guide/sections.tsx` is the visual
|
|
128
129
|
check in light, dark and system-dark; add an entry with every variant and
|
|
129
130
|
size when adding a component.
|
|
@@ -696,6 +697,22 @@ action is shaped like A2UI's client-to-server `action`, and the catalogue is a
|
|
|
696
697
|
schema-per-component registry. Swapping the engine later is mechanical. Nothing
|
|
697
698
|
from `@a2ui/*` is installed, so `vitest.config.ts` has no entry for it.
|
|
698
699
|
|
|
700
|
+
## Which tests run in both themes
|
|
701
|
+
|
|
702
|
+
`vitest.config.ts` has two projects. **`light`** runs every file once in a
|
|
703
|
+
Chromium whose OS colour scheme is light; **`dark`** runs a second time, in a
|
|
704
|
+
dark Chromium, only the files whose name ends `.theme.test.tsx`. Tag a test with
|
|
705
|
+
that suffix when its result depends on the browser's own colour scheme — that
|
|
706
|
+
is, when it asserts a theme-dependent value while no `data-theme` attribute is
|
|
707
|
+
set, the `@media (prefers-color-scheme: dark)` branch of `tokens.css`. Nothing
|
|
708
|
+
else needs the tag: an explicit `data-theme` always beats the media query, so a
|
|
709
|
+
test that calls `setTheme("light")` or `setTheme("dark")` computes the same
|
|
710
|
+
bytes in either browser, and the `for (const theme of ["light", "dark"])` loops
|
|
711
|
+
already paint both branches and assert that they differ, inside one run. If one
|
|
712
|
+
test in a file needs the tag, move that test to a sibling `*.theme.test.tsx`
|
|
713
|
+
rather than paying for the whole file twice — six such files exist today, and
|
|
714
|
+
`pnpm test:dark` runs exactly them.
|
|
715
|
+
|
|
699
716
|
## Commands
|
|
700
717
|
|
|
701
718
|
```bash
|
|
@@ -703,6 +720,7 @@ pnpm check # types
|
|
|
703
720
|
pnpm lint:design # no literals where a token exists; no dangling var()
|
|
704
721
|
pnpm build # dist/ via tsdown (ESM + d.ts); also runs on prepack
|
|
705
722
|
pnpm test # changed-only: the suites of this package your diff affects
|
|
723
|
+
pnpm test:dark # the dark project alone: *.theme.test.tsx in dark Chromium
|
|
706
724
|
pnpm test:bundle # bundle budgets alone (builds first, then real Vite apps)
|
|
707
725
|
pnpm bundle:probe # the size table, printed, without asserting anything
|
|
708
726
|
pnpm guide # three-theme guide on a local Vite server
|
|
@@ -725,6 +743,7 @@ src/styles/index.css what consumers import after the tokens: animation
|
|
|
725
743
|
utilities and the Base UI data-attribute variants
|
|
726
744
|
scripts/bundle-probe.mjs builds a consumer app per entry and weighs it
|
|
727
745
|
test/ browser tests; setup.css is the consumer recipe verbatim
|
|
746
|
+
*.theme.test.tsx also run in a dark Chromium
|
|
728
747
|
*.test.mjs are the Node-side bundle budgets
|
|
729
748
|
guide/ Vite app: ?theme=light|dark|system frames, or all three
|
|
730
749
|
```
|
|
@@ -3,7 +3,7 @@ import { VariantProps } from "class-variance-authority";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
//#region src/components/badge.d.ts
|
|
5
5
|
declare const badgeVariants: (props?: ({
|
|
6
|
-
variant?: "default" | "success" | "warn" | "destructive" | "danger" | "info" | "warning" | "
|
|
6
|
+
variant?: "default" | "outline" | "success" | "warn" | "destructive" | "danger" | "info" | "warning" | "secondary" | "neutral" | null | undefined;
|
|
7
7
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
8
8
|
export interface BadgeProps extends React.ComponentProps<"span">, VariantProps<typeof badgeVariants> {}
|
|
9
9
|
declare function Badge({ className, variant, ...props }: BadgeProps): React.JSX.Element;
|
|
@@ -14,7 +14,7 @@ import { Button } from "@base-ui/react/button";
|
|
|
14
14
|
* rendered element, which is Base UI's equivalent.
|
|
15
15
|
*/
|
|
16
16
|
declare const buttonVariants: (props?: ({
|
|
17
|
-
variant?: "link" | "
|
|
17
|
+
variant?: "link" | "outline" | "destructive" | "primary" | "secondary" | "ghost" | "soft" | null | undefined;
|
|
18
18
|
size?: "sm" | "md" | "lg" | "icon" | "icon-sm" | null | undefined;
|
|
19
19
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
20
20
|
export interface ButtonProps extends React.ComponentProps<typeof Button>, VariantProps<typeof buttonVariants> {}
|
|
@@ -5,6 +5,24 @@ import { useChart } from "./container.js";
|
|
|
5
5
|
import { useMemo } from "react";
|
|
6
6
|
//#region src/components/chart/nivo-theme.ts
|
|
7
7
|
/**
|
|
8
|
+
* What these four sizes are when there is no DOM to read them from.
|
|
9
|
+
*
|
|
10
|
+
* `nivoTheme` runs on the server too, where `getComputedStyle` does not exist
|
|
11
|
+
* and every `tokenPx` call comes back undefined. Each number below is the
|
|
12
|
+
* pixel value its token emits at the default scale, so the server markup and
|
|
13
|
+
* the first client paint agree. `chart.test.tsx` asserts them against the
|
|
14
|
+
* live tokens, which is what stops them drifting the way the two radii had:
|
|
15
|
+
* `--ds-radius-md` is 12px and fell back to 6, `--ds-radius-sm` is 8px and
|
|
16
|
+
* fell back to 4, so every server-rendered tooltip drew half-round corners
|
|
17
|
+
* until hydration.
|
|
18
|
+
*/
|
|
19
|
+
const NIVO_SIZE_FALLBACK = {
|
|
20
|
+
captionSm: 11,
|
|
21
|
+
caption: 12,
|
|
22
|
+
radiusMd: 12,
|
|
23
|
+
radiusSm: 8
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
8
26
|
* Build the Nivo theme from the tokens, resolved on `el` (default `<html>`).
|
|
9
27
|
* Every colour is read from a `--ds-*` custom property and converted to hex,
|
|
10
28
|
* because Nivo's canvas renderer and its colour derivation cannot read
|
|
@@ -15,10 +33,10 @@ import { useMemo } from "react";
|
|
|
15
33
|
*/
|
|
16
34
|
function nivoTheme(el) {
|
|
17
35
|
const fontFamily = readToken("--ds-font-body", el) || "var(--ds-font-body)";
|
|
18
|
-
const captionSm = tokenPx("--ds-text-caption-sm", el) ??
|
|
19
|
-
const caption = tokenPx("--ds-text-caption", el) ??
|
|
20
|
-
const radiusMd = tokenPx("--ds-radius-md", el) ??
|
|
21
|
-
const radiusSm = tokenPx("--ds-radius-sm", el) ??
|
|
36
|
+
const captionSm = tokenPx("--ds-text-caption-sm", el) ?? NIVO_SIZE_FALLBACK.captionSm;
|
|
37
|
+
const caption = tokenPx("--ds-text-caption", el) ?? NIVO_SIZE_FALLBACK.caption;
|
|
38
|
+
const radiusMd = tokenPx("--ds-radius-md", el) ?? NIVO_SIZE_FALLBACK.radiusMd;
|
|
39
|
+
const radiusSm = tokenPx("--ds-radius-sm", el) ?? NIVO_SIZE_FALLBACK.radiusSm;
|
|
22
40
|
const foreground = resolveColor("--ds-foreground", el);
|
|
23
41
|
const muted = resolveColor("--ds-muted-foreground", el);
|
|
24
42
|
const border = resolveColor("--ds-border", el);
|
|
@@ -156,6 +174,6 @@ function useNivoTheme() {
|
|
|
156
174
|
return useMemo(() => nivoTheme(el), [el, version]);
|
|
157
175
|
}
|
|
158
176
|
//#endregion
|
|
159
|
-
export { nivoTheme, useNivoTheme };
|
|
177
|
+
export { NIVO_SIZE_FALLBACK, nivoTheme, useNivoTheme };
|
|
160
178
|
|
|
161
179
|
//# sourceMappingURL=nivo-theme.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nivo-theme.js","names":[],"sources":["../../../src/components/chart/nivo-theme.ts"],"sourcesContent":["\"use client\";\n\nimport { useMemo } from \"react\";\nimport { useChart } from \"./container\";\nimport { readToken, resolveColor, tokenPx, useThemeVersion } from \"./tokens\";\n\n/**\n * The Nivo theme object, typed structurally so no `@nivo/*` package is a\n * static import of this module (the Nivo packages are lazy-loaded). It is a\n * subset of `PartialTheme` from `@nivo/theming` and assignable to every\n * chart's `theme` prop.\n */\nexport interface NivoTheme {\n background: string;\n text: { fontFamily: string; fontSize: number; fill: string };\n axis: {\n domain: { line: { stroke: string; strokeWidth: number } };\n ticks: {\n line: { stroke: string; strokeWidth: number };\n text: { fill: string; fontSize: number };\n };\n legend: { text: { fill: string; fontSize: number; fontWeight: number } };\n };\n grid: { line: { stroke: string; strokeWidth: number } };\n crosshair: { line: { stroke: string; strokeWidth: number; strokeOpacity: number; strokeDasharray: string } };\n legends: {\n text: { fill: string; fontSize: number };\n title: { text: { fill: string; fontSize: number } };\n ticks: { line: { stroke: string; strokeWidth: number }; text: { fill: string; fontSize: number } };\n };\n labels: { text: { fill: string; fontSize: number; fontWeight: number } };\n dots: { text: { fill: string; fontSize: number } };\n markers: { lineColor: string; lineStrokeWidth: number; text: { fill: string; fontSize: number } };\n annotations: {\n text: { fill: string; fontSize: number; outlineWidth: number; outlineColor: string };\n link: { stroke: string; strokeWidth: number; outlineWidth: number; outlineColor: string };\n outline: { stroke: string; strokeWidth: number; outlineWidth: number; outlineColor: string };\n symbol: { fill: string; outlineWidth: number; outlineColor: string };\n };\n tooltip: {\n container: {\n background: string;\n color: string;\n fontSize: number;\n fontFamily: string;\n borderRadius: number;\n boxShadow: string;\n border: string;\n padding: string;\n };\n chip: { borderRadius: number };\n };\n}\n\n/**\n * Build the Nivo theme from the tokens, resolved on `el` (default `<html>`).\n * Every colour is read from a `--ds-*` custom property and converted to hex,\n * because Nivo's canvas renderer and its colour derivation cannot read\n * `var()`. Sizes come from the type scale with `--ds-text-caption-sm` (11px)\n * as the floor for ticks and labels.\n *\n * Moved here from cortenaweb's webchat renderer; nothing is hard-coded.\n */\nexport function nivoTheme(el?: Element | null): NivoTheme {\n const fontFamily = readToken(\"--ds-font-body\", el) || \"var(--ds-font-body)\";\n const captionSm = tokenPx(\"--ds-text-caption-sm\", el) ??
|
|
1
|
+
{"version":3,"file":"nivo-theme.js","names":[],"sources":["../../../src/components/chart/nivo-theme.ts"],"sourcesContent":["\"use client\";\n\nimport { useMemo } from \"react\";\nimport { useChart } from \"./container\";\nimport { readToken, resolveColor, tokenPx, useThemeVersion } from \"./tokens\";\n\n/**\n * The Nivo theme object, typed structurally so no `@nivo/*` package is a\n * static import of this module (the Nivo packages are lazy-loaded). It is a\n * subset of `PartialTheme` from `@nivo/theming` and assignable to every\n * chart's `theme` prop.\n */\nexport interface NivoTheme {\n background: string;\n text: { fontFamily: string; fontSize: number; fill: string };\n axis: {\n domain: { line: { stroke: string; strokeWidth: number } };\n ticks: {\n line: { stroke: string; strokeWidth: number };\n text: { fill: string; fontSize: number };\n };\n legend: { text: { fill: string; fontSize: number; fontWeight: number } };\n };\n grid: { line: { stroke: string; strokeWidth: number } };\n crosshair: { line: { stroke: string; strokeWidth: number; strokeOpacity: number; strokeDasharray: string } };\n legends: {\n text: { fill: string; fontSize: number };\n title: { text: { fill: string; fontSize: number } };\n ticks: { line: { stroke: string; strokeWidth: number }; text: { fill: string; fontSize: number } };\n };\n labels: { text: { fill: string; fontSize: number; fontWeight: number } };\n dots: { text: { fill: string; fontSize: number } };\n markers: { lineColor: string; lineStrokeWidth: number; text: { fill: string; fontSize: number } };\n annotations: {\n text: { fill: string; fontSize: number; outlineWidth: number; outlineColor: string };\n link: { stroke: string; strokeWidth: number; outlineWidth: number; outlineColor: string };\n outline: { stroke: string; strokeWidth: number; outlineWidth: number; outlineColor: string };\n symbol: { fill: string; outlineWidth: number; outlineColor: string };\n };\n tooltip: {\n container: {\n background: string;\n color: string;\n fontSize: number;\n fontFamily: string;\n borderRadius: number;\n boxShadow: string;\n border: string;\n padding: string;\n };\n chip: { borderRadius: number };\n };\n}\n\n/**\n * What these four sizes are when there is no DOM to read them from.\n *\n * `nivoTheme` runs on the server too, where `getComputedStyle` does not exist\n * and every `tokenPx` call comes back undefined. Each number below is the\n * pixel value its token emits at the default scale, so the server markup and\n * the first client paint agree. `chart.test.tsx` asserts them against the\n * live tokens, which is what stops them drifting the way the two radii had:\n * `--ds-radius-md` is 12px and fell back to 6, `--ds-radius-sm` is 8px and\n * fell back to 4, so every server-rendered tooltip drew half-round corners\n * until hydration.\n */\nexport const NIVO_SIZE_FALLBACK = {\n captionSm: 11,\n caption: 12,\n radiusMd: 12,\n radiusSm: 8,\n} as const;\n\n/**\n * Build the Nivo theme from the tokens, resolved on `el` (default `<html>`).\n * Every colour is read from a `--ds-*` custom property and converted to hex,\n * because Nivo's canvas renderer and its colour derivation cannot read\n * `var()`. Sizes come from the type scale with `--ds-text-caption-sm` (11px)\n * as the floor for ticks and labels.\n *\n * Moved here from cortenaweb's webchat renderer; nothing is hard-coded.\n */\nexport function nivoTheme(el?: Element | null): NivoTheme {\n const fontFamily = readToken(\"--ds-font-body\", el) || \"var(--ds-font-body)\";\n const captionSm = tokenPx(\"--ds-text-caption-sm\", el) ?? NIVO_SIZE_FALLBACK.captionSm;\n const caption = tokenPx(\"--ds-text-caption\", el) ?? NIVO_SIZE_FALLBACK.caption;\n const radiusMd = tokenPx(\"--ds-radius-md\", el) ?? NIVO_SIZE_FALLBACK.radiusMd;\n const radiusSm = tokenPx(\"--ds-radius-sm\", el) ?? NIVO_SIZE_FALLBACK.radiusSm;\n const foreground = resolveColor(\"--ds-foreground\", el);\n const muted = resolveColor(\"--ds-muted-foreground\", el);\n const border = resolveColor(\"--ds-border\", el);\n const borderSubtle = resolveColor(\"--ds-border-subtle\", el);\n const borderStrong = resolveColor(\"--ds-border-strong\", el);\n const popover = resolveColor(\"--ds-popover\", el);\n const popoverForeground = resolveColor(\"--ds-popover-foreground\", el);\n const card = resolveColor(\"--ds-card\", el);\n const shadow = readToken(\"--ds-shadow-md\", el) || \"var(--ds-shadow-md)\";\n const space2 = readToken(\"--ds-space-2\", el) || \"var(--ds-space-2)\";\n const space3 = readToken(\"--ds-space-3\", el) || \"var(--ds-space-3)\";\n\n return {\n background: \"transparent\",\n text: { fontFamily, fontSize: captionSm, fill: foreground },\n axis: {\n domain: { line: { stroke: border, strokeWidth: 1 } },\n ticks: {\n line: { stroke: border, strokeWidth: 1 },\n text: { fill: muted, fontSize: captionSm },\n },\n legend: { text: { fill: foreground, fontSize: caption, fontWeight: 500 } },\n },\n grid: { line: { stroke: borderSubtle, strokeWidth: 1 } },\n crosshair: { line: { stroke: borderStrong, strokeWidth: 1, strokeOpacity: 1, strokeDasharray: \"4 4\" } },\n legends: {\n text: { fill: muted, fontSize: captionSm },\n title: { text: { fill: foreground, fontSize: caption } },\n ticks: { line: { stroke: border, strokeWidth: 1 }, text: { fill: muted, fontSize: captionSm } },\n },\n labels: { text: { fill: foreground, fontSize: captionSm, fontWeight: 500 } },\n dots: { text: { fill: foreground, fontSize: captionSm } },\n markers: { lineColor: borderStrong, lineStrokeWidth: 1, text: { fill: muted, fontSize: captionSm } },\n annotations: {\n text: { fill: foreground, fontSize: captionSm, outlineWidth: 2, outlineColor: card },\n link: { stroke: borderStrong, strokeWidth: 1, outlineWidth: 2, outlineColor: card },\n outline: { stroke: borderStrong, strokeWidth: 1, outlineWidth: 2, outlineColor: card },\n symbol: { fill: foreground, outlineWidth: 2, outlineColor: card },\n },\n tooltip: {\n container: {\n background: popover,\n color: popoverForeground,\n fontSize: caption,\n fontFamily,\n borderRadius: radiusMd,\n boxShadow: shadow,\n border: `1px solid ${borderSubtle}`,\n padding: `${space2} ${space3}`,\n },\n chip: { borderRadius: radiusSm },\n },\n };\n}\n\n/**\n * The Nivo theme for the current theme, re-resolved when `data-theme` or the\n * OS scheme flips. Inside a ChartContainer the tokens are read on its element,\n * so a nested theme scope is honoured.\n */\nexport function useNivoTheme(): NivoTheme {\n const version = useThemeVersion();\n const chart = useChart();\n const el = chart?.element ?? null;\n // eslint-disable-next-line react-hooks/exhaustive-deps -- version is the cache key for the DOM read\n return useMemo(() => nivoTheme(el), [el, version]);\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
"use client";
|
|
3
|
-
import { contrastLabel, useThemeVersion } from "./tokens.js";
|
|
3
|
+
import { contrastLabel, plotMargin, useThemeVersion } from "./tokens.js";
|
|
4
4
|
import { seriesColor, useChart } from "./container.js";
|
|
5
5
|
import { toRows, toSlices } from "./data.js";
|
|
6
6
|
import { ChartLegend, ChartTooltip } from "./recharts-parts.js";
|
|
@@ -8,12 +8,6 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
8
8
|
import * as React from "react";
|
|
9
9
|
import { Area, AreaChart, Bar, BarChart, CartesianGrid, Cell, Funnel, FunnelChart, Line, LineChart, Pie, PieChart, PolarAngleAxis, PolarGrid, PolarRadiusAxis, Radar, RadarChart, Scatter, ScatterChart, XAxis, YAxis } from "recharts";
|
|
10
10
|
//#region src/components/chart/recharts-charts.tsx
|
|
11
|
-
const MARGIN = {
|
|
12
|
-
top: 8,
|
|
13
|
-
right: 8,
|
|
14
|
-
bottom: 0,
|
|
15
|
-
left: 0
|
|
16
|
-
};
|
|
17
11
|
/**
|
|
18
12
|
* Where an arc label sits, as a fraction of the way from the inner radius to
|
|
19
13
|
* the outer one. Just inside the middle of the band: the arc is widest towards
|
|
@@ -69,6 +63,7 @@ function RechartsChart({ type, data, config, indexBy, keys, stacked, legend, gri
|
|
|
69
63
|
const themeVersion = useThemeVersion();
|
|
70
64
|
const element = useChart()?.element ?? null;
|
|
71
65
|
const colourOn = React.useMemo(() => contrastLabel(element), [element, themeVersion]);
|
|
66
|
+
const margin = React.useMemo(() => plotMargin(element), [element, themeVersion]);
|
|
72
67
|
const tip = tooltip ? /* @__PURE__ */ jsx(ChartTooltip, { formatter: valueFormatter ? (value) => valueFormatter(Number(value)) : void 0 }) : null;
|
|
73
68
|
const leg = legend ? /* @__PURE__ */ jsx(ChartLegend, {}) : null;
|
|
74
69
|
switch (type) {
|
|
@@ -76,7 +71,7 @@ function RechartsChart({ type, data, config, indexBy, keys, stacked, legend, gri
|
|
|
76
71
|
const { rows, indexBy: index, keys: series } = toRows(data, indexBy, keys);
|
|
77
72
|
return /* @__PURE__ */ jsxs(BarChart, {
|
|
78
73
|
data: rows,
|
|
79
|
-
margin
|
|
74
|
+
margin,
|
|
80
75
|
children: [
|
|
81
76
|
grid ? /* @__PURE__ */ jsx(CartesianGrid, { vertical: false }) : null,
|
|
82
77
|
/* @__PURE__ */ jsx(XAxis, {
|
|
@@ -112,7 +107,7 @@ function RechartsChart({ type, data, config, indexBy, keys, stacked, legend, gri
|
|
|
112
107
|
const { rows, indexBy: index, keys: series } = toRows(data, indexBy, keys);
|
|
113
108
|
return /* @__PURE__ */ jsxs(LineChart, {
|
|
114
109
|
data: rows,
|
|
115
|
-
margin
|
|
110
|
+
margin,
|
|
116
111
|
children: [
|
|
117
112
|
grid ? /* @__PURE__ */ jsx(CartesianGrid, { vertical: false }) : null,
|
|
118
113
|
/* @__PURE__ */ jsx(XAxis, {
|
|
@@ -144,7 +139,7 @@ function RechartsChart({ type, data, config, indexBy, keys, stacked, legend, gri
|
|
|
144
139
|
const { rows, indexBy: index, keys: series } = toRows(data, indexBy, keys);
|
|
145
140
|
return /* @__PURE__ */ jsxs(AreaChart, {
|
|
146
141
|
data: rows,
|
|
147
|
-
margin
|
|
142
|
+
margin,
|
|
148
143
|
children: [
|
|
149
144
|
grid ? /* @__PURE__ */ jsx(CartesianGrid, { vertical: false }) : null,
|
|
150
145
|
/* @__PURE__ */ jsx(XAxis, {
|
|
@@ -178,7 +173,7 @@ function RechartsChart({ type, data, config, indexBy, keys, stacked, legend, gri
|
|
|
178
173
|
const slices = toSlices(data);
|
|
179
174
|
const fillOf = (i) => seriesColor(config, slices[i]?.id ?? String(i), i);
|
|
180
175
|
return /* @__PURE__ */ jsxs(PieChart, {
|
|
181
|
-
margin
|
|
176
|
+
margin,
|
|
182
177
|
children: [
|
|
183
178
|
tip,
|
|
184
179
|
leg,
|
|
@@ -200,7 +195,7 @@ function RechartsChart({ type, data, config, indexBy, keys, stacked, legend, gri
|
|
|
200
195
|
}
|
|
201
196
|
case "scatter":
|
|
202
197
|
case "scatterplot": return /* @__PURE__ */ jsxs(ScatterChart, {
|
|
203
|
-
margin
|
|
198
|
+
margin,
|
|
204
199
|
children: [
|
|
205
200
|
grid ? /* @__PURE__ */ jsx(CartesianGrid, {}) : null,
|
|
206
201
|
/* @__PURE__ */ jsx(XAxis, {
|
|
@@ -232,7 +227,7 @@ function RechartsChart({ type, data, config, indexBy, keys, stacked, legend, gri
|
|
|
232
227
|
const { rows, indexBy: index, keys: series } = toRows(data, indexBy, keys);
|
|
233
228
|
return /* @__PURE__ */ jsxs(RadarChart, {
|
|
234
229
|
data: rows,
|
|
235
|
-
margin
|
|
230
|
+
margin,
|
|
236
231
|
children: [
|
|
237
232
|
grid ? /* @__PURE__ */ jsx(PolarGrid, {}) : null,
|
|
238
233
|
/* @__PURE__ */ jsx(PolarAngleAxis, { dataKey: index }),
|
|
@@ -256,7 +251,7 @@ function RechartsChart({ type, data, config, indexBy, keys, stacked, legend, gri
|
|
|
256
251
|
case "funnel": {
|
|
257
252
|
const slices = toSlices(data);
|
|
258
253
|
return /* @__PURE__ */ jsxs(FunnelChart, {
|
|
259
|
-
margin
|
|
254
|
+
margin,
|
|
260
255
|
children: [
|
|
261
256
|
tip,
|
|
262
257
|
leg,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recharts-charts.js","names":["series"],"sources":["../../../src/components/chart/recharts-charts.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n Area,\n AreaChart,\n Bar,\n BarChart,\n CartesianGrid,\n Cell,\n Funnel,\n FunnelChart,\n Line,\n LineChart,\n Pie,\n PieChart,\n PolarAngleAxis,\n PolarGrid,\n PolarRadiusAxis,\n Radar,\n RadarChart,\n Scatter,\n ScatterChart,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport { seriesColor, useChart } from \"./container\";\nimport { ChartLegend, ChartTooltip } from \"./recharts-parts\";\nimport { toRows, toSlices } from \"./data\";\nimport { contrastLabel, useThemeVersion } from \"./tokens\";\nimport type { ChartConfig, ChartLabels, ChartRow, ChartSeries, ChartSlice, ChartType } from \"./types\";\n\nexport type RechartsType = Extract<\n ChartType,\n \"bar\" | \"line\" | \"area\" | \"pie\" | \"donut\" | \"scatter\" | \"scatterplot\" | \"radar\" | \"funnel\"\n>;\n\nexport interface RechartsRenderProps {\n type: RechartsType;\n data: unknown;\n config: ChartConfig;\n indexBy?: string;\n keys?: string[];\n stacked?: boolean;\n legend: boolean;\n grid: boolean;\n tooltip: boolean;\n /** Per-arc labels for pie and donut. Ignored by every other type. */\n labels: ChartLabels;\n valueFormatter?: (value: number) => string;\n /**\n * Entry animation. Off under `testMode`: Recharts draws pie labels only\n * once the animation has finished, so a test that asserts on them would\n * otherwise be racing the clock.\n */\n animate?: boolean;\n}\n\nconst MARGIN = { top: 8, right: 8, bottom: 0, left: 0 };\n\n/**\n * Where an arc label sits, as a fraction of the way from the inner radius to\n * the outer one. Just inside the middle of the band: the arc is widest towards\n * its outer edge, so a label pushed slightly out has more room than a centred\n * one, without ever touching the rim.\n */\nconst ARC_LABEL_RADIUS = 0.58;\n\n/**\n * Arcs smaller than this share of the whole are left unlabelled.\n *\n * Below roughly a twentieth the arc is narrower than the text it would carry,\n * so the label either overflows into its neighbours or has to be dragged\n * outside on a leader line. Leader lines on a small chart are worse than no\n * label — they collide with each other and with the legend, and the reader\n * still has to trace them. The tooltip covers the slices that fall out.\n */\nconst ARC_LABEL_MIN_FRACTION = 0.05;\n\n/**\n * What Recharts hands a `<Pie label={…}>` renderer. Every geometry field is\n * optional on its side — the same callback types the label of a chart that has\n * not measured itself yet — so each is checked before it is used rather than\n * asserted away.\n */\ninterface ArcLabelProps {\n cx?: number;\n cy?: number;\n midAngle?: number;\n innerRadius?: number;\n outerRadius?: number;\n percent?: number;\n value?: number;\n index?: number;\n}\n\n/**\n * A per-arc label, drawn inside the arc it belongs to.\n *\n * Inside rather than outside so there is nothing to collide: each label is\n * bounded by its own sector, and a sector too thin to hold one simply does not\n * get one. The text colour comes from `contrastLabel`, the same measured\n * ink-or-white choice the Nivo charts make, so a label stays legible on a pale\n * series colour and on a dark one, in either theme.\n */\nfunction arcLabel(\n labels: Exclude<ChartLabels, \"none\">,\n colourOn: (fill: string) => string,\n fillOf: (index: number) => string,\n valueFormatter?: (value: number) => string,\n) {\n return function ArcLabel({ cx, cy, midAngle, innerRadius, outerRadius, percent, value, index }: ArcLabelProps) {\n if (cx == null || cy == null || midAngle == null || innerRadius == null || outerRadius == null) return null;\n if (!(percent != null && percent >= ARC_LABEL_MIN_FRACTION)) return null;\n const radius = innerRadius + (outerRadius - innerRadius) * ARC_LABEL_RADIUS;\n // Recharts measures angles anticlockwise from the positive x-axis, SVG's y\n // grows downward, so the sine is negated to land on the drawn arc.\n const radians = (-midAngle * Math.PI) / 180;\n const text =\n labels === \"percent\"\n ? `${Math.round(percent * 100)}%`\n : (valueFormatter?.(Number(value)) ?? String(value ?? \"\"));\n return (\n <text\n data-slot=\"chart-arc-label\"\n x={cx + radius * Math.cos(radians)}\n y={cy + radius * Math.sin(radians)}\n fill={colourOn(fillOf(index ?? 0))}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className=\"pointer-events-none text-[length:var(--ds-text-caption)] font-medium tabular-nums\"\n >\n {text}\n </text>\n );\n };\n}\n\n/**\n * The Recharts side of `Chart`. Returns a chart element for the\n * ResponsiveContainer inside ChartContainer; colours come from `seriesColor`\n * (config colour or `var(--ds-viz-N)` by series index) and every other visual\n * value from the container's token styling.\n */\nexport function RechartsChart({\n type,\n data,\n config,\n indexBy,\n keys,\n stacked,\n legend,\n grid,\n tooltip,\n labels,\n valueFormatter,\n animate = true,\n}: RechartsRenderProps): React.ReactElement {\n // Arc labels sit on top of a series colour, so their ink depends on which\n // colour and on the theme. `useThemeVersion` is the cache key for that DOM\n // read; `element` scopes it to a nested theme rather than the document.\n const themeVersion = useThemeVersion();\n const element = useChart()?.element ?? null;\n // eslint-disable-next-line react-hooks/exhaustive-deps -- themeVersion is the cache key for the DOM read\n const colourOn = React.useMemo(() => contrastLabel(element), [element, themeVersion]);\n\n const tip = tooltip ? (\n <ChartTooltip\n formatter={valueFormatter ? (value: unknown) => valueFormatter(Number(value)) : undefined}\n />\n ) : null;\n const leg = legend ? <ChartLegend /> : null;\n\n switch (type) {\n case \"bar\": {\n const { rows, indexBy: index, keys: series } = toRows(data as ChartRow[] | ChartSeries[], indexBy, keys);\n return (\n <BarChart data={rows} margin={MARGIN}>\n {grid ? <CartesianGrid vertical={false} /> : null}\n <XAxis dataKey={index} tickLine={false} axisLine={false} tickMargin={8} />\n <YAxis tickLine={false} axisLine={false} tickFormatter={valueFormatter} />\n {tip}\n {leg}\n {series.map((key, i) => (\n <Bar\n key={key}\n dataKey={key}\n name={key}\n fill={seriesColor(config, key, i)}\n stackId={stacked ? \"stack\" : undefined}\n radius={stacked ? 0 : [2, 2, 0, 0]}\n maxBarSize={48}\n />\n ))}\n </BarChart>\n );\n }\n\n case \"line\": {\n const { rows, indexBy: index, keys: series } = toRows(data as ChartRow[] | ChartSeries[], indexBy, keys);\n return (\n <LineChart data={rows} margin={MARGIN}>\n {grid ? <CartesianGrid vertical={false} /> : null}\n <XAxis dataKey={index} tickLine={false} axisLine={false} tickMargin={8} />\n <YAxis tickLine={false} axisLine={false} tickFormatter={valueFormatter} />\n {tip}\n {leg}\n {series.map((key, i) => (\n <Line\n key={key}\n type=\"monotone\"\n dataKey={key}\n name={key}\n stroke={seriesColor(config, key, i)}\n strokeWidth={2}\n dot={false}\n activeDot={{ r: 4 }}\n />\n ))}\n </LineChart>\n );\n }\n\n case \"area\": {\n const { rows, indexBy: index, keys: series } = toRows(data as ChartRow[] | ChartSeries[], indexBy, keys);\n return (\n <AreaChart data={rows} margin={MARGIN}>\n {grid ? <CartesianGrid vertical={false} /> : null}\n <XAxis dataKey={index} tickLine={false} axisLine={false} tickMargin={8} />\n <YAxis tickLine={false} axisLine={false} tickFormatter={valueFormatter} />\n {tip}\n {leg}\n {series.map((key, i) => (\n <Area\n key={key}\n type=\"monotone\"\n dataKey={key}\n name={key}\n stroke={seriesColor(config, key, i)}\n fill={seriesColor(config, key, i)}\n fillOpacity={0.2}\n strokeWidth={2}\n stackId={stacked ? \"stack\" : undefined}\n />\n ))}\n </AreaChart>\n );\n }\n\n case \"pie\":\n case \"donut\": {\n const slices = toSlices(data as ChartSlice[]);\n const fillOf = (i: number) => seriesColor(config, slices[i]?.id ?? String(i), i);\n return (\n <PieChart margin={MARGIN}>\n {tip}\n {leg}\n <Pie\n data={slices}\n dataKey=\"value\"\n nameKey=\"name\"\n innerRadius={type === \"donut\" ? \"55%\" : 0}\n outerRadius=\"80%\"\n paddingAngle={type === \"donut\" ? 2 : 0}\n strokeWidth={1}\n isAnimationActive={animate}\n label={labels === \"none\" ? undefined : arcLabel(labels, colourOn, fillOf, valueFormatter)}\n // The labels are inside their arcs, so there is nothing to lead to.\n labelLine={false}\n >\n {slices.map((slice, i) => (\n <Cell key={slice.id} fill={fillOf(i)} />\n ))}\n </Pie>\n </PieChart>\n );\n }\n\n case \"scatter\":\n case \"scatterplot\": {\n const series = data as ChartSeries[];\n return (\n <ScatterChart margin={MARGIN}>\n {grid ? <CartesianGrid /> : null}\n <XAxis dataKey=\"x\" type=\"number\" name=\"x\" tickLine={false} axisLine={false} tickMargin={8} />\n <YAxis dataKey=\"y\" type=\"number\" name=\"y\" tickLine={false} axisLine={false} tickFormatter={valueFormatter} />\n {tip}\n {leg}\n {series.map((s, i) => (\n <Scatter key={String(s.id)} name={String(s.id)} data={s.data} fill={seriesColor(config, String(s.id), i)} />\n ))}\n </ScatterChart>\n );\n }\n\n case \"radar\": {\n const { rows, indexBy: index, keys: series } = toRows(data as ChartRow[] | ChartSeries[], indexBy, keys);\n return (\n <RadarChart data={rows} margin={MARGIN}>\n {grid ? <PolarGrid /> : null}\n <PolarAngleAxis dataKey={index} />\n <PolarRadiusAxis tick={false} axisLine={false} />\n {tip}\n {leg}\n {series.map((key, i) => (\n <Radar\n key={key}\n dataKey={key}\n name={key}\n stroke={seriesColor(config, key, i)}\n fill={seriesColor(config, key, i)}\n fillOpacity={0.2}\n strokeWidth={2}\n />\n ))}\n </RadarChart>\n );\n }\n\n case \"funnel\": {\n const slices = toSlices(data as ChartSlice[]);\n return (\n <FunnelChart margin={MARGIN}>\n {tip}\n {leg}\n <Funnel data={slices} dataKey=\"value\" nameKey=\"name\">\n {slices.map((slice, i) => (\n <Cell key={slice.id} fill={seriesColor(config, slice.id, i)} />\n ))}\n </Funnel>\n </FunnelChart>\n );\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"recharts-charts.js","names":["series"],"sources":["../../../src/components/chart/recharts-charts.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n Area,\n AreaChart,\n Bar,\n BarChart,\n CartesianGrid,\n Cell,\n Funnel,\n FunnelChart,\n Line,\n LineChart,\n Pie,\n PieChart,\n PolarAngleAxis,\n PolarGrid,\n PolarRadiusAxis,\n Radar,\n RadarChart,\n Scatter,\n ScatterChart,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport { seriesColor, useChart } from \"./container\";\nimport { ChartLegend, ChartTooltip } from \"./recharts-parts\";\nimport { toRows, toSlices } from \"./data\";\nimport { contrastLabel, plotMargin, useThemeVersion } from \"./tokens\";\nimport type { ChartConfig, ChartLabels, ChartRow, ChartSeries, ChartSlice, ChartType } from \"./types\";\n\nexport type RechartsType = Extract<\n ChartType,\n \"bar\" | \"line\" | \"area\" | \"pie\" | \"donut\" | \"scatter\" | \"scatterplot\" | \"radar\" | \"funnel\"\n>;\n\nexport interface RechartsRenderProps {\n type: RechartsType;\n data: unknown;\n config: ChartConfig;\n indexBy?: string;\n keys?: string[];\n stacked?: boolean;\n legend: boolean;\n grid: boolean;\n tooltip: boolean;\n /** Per-arc labels for pie and donut. Ignored by every other type. */\n labels: ChartLabels;\n valueFormatter?: (value: number) => string;\n /**\n * Entry animation. Off under `testMode`: Recharts draws pie labels only\n * once the animation has finished, so a test that asserts on them would\n * otherwise be racing the clock.\n */\n animate?: boolean;\n}\n\n/**\n * Where an arc label sits, as a fraction of the way from the inner radius to\n * the outer one. Just inside the middle of the band: the arc is widest towards\n * its outer edge, so a label pushed slightly out has more room than a centred\n * one, without ever touching the rim.\n */\nconst ARC_LABEL_RADIUS = 0.58;\n\n/**\n * Arcs smaller than this share of the whole are left unlabelled.\n *\n * Below roughly a twentieth the arc is narrower than the text it would carry,\n * so the label either overflows into its neighbours or has to be dragged\n * outside on a leader line. Leader lines on a small chart are worse than no\n * label — they collide with each other and with the legend, and the reader\n * still has to trace them. The tooltip covers the slices that fall out.\n */\nconst ARC_LABEL_MIN_FRACTION = 0.05;\n\n/**\n * What Recharts hands a `<Pie label={…}>` renderer. Every geometry field is\n * optional on its side — the same callback types the label of a chart that has\n * not measured itself yet — so each is checked before it is used rather than\n * asserted away.\n */\ninterface ArcLabelProps {\n cx?: number;\n cy?: number;\n midAngle?: number;\n innerRadius?: number;\n outerRadius?: number;\n percent?: number;\n value?: number;\n index?: number;\n}\n\n/**\n * A per-arc label, drawn inside the arc it belongs to.\n *\n * Inside rather than outside so there is nothing to collide: each label is\n * bounded by its own sector, and a sector too thin to hold one simply does not\n * get one. The text colour comes from `contrastLabel`, the same measured\n * ink-or-white choice the Nivo charts make, so a label stays legible on a pale\n * series colour and on a dark one, in either theme.\n */\nfunction arcLabel(\n labels: Exclude<ChartLabels, \"none\">,\n colourOn: (fill: string) => string,\n fillOf: (index: number) => string,\n valueFormatter?: (value: number) => string,\n) {\n return function ArcLabel({ cx, cy, midAngle, innerRadius, outerRadius, percent, value, index }: ArcLabelProps) {\n if (cx == null || cy == null || midAngle == null || innerRadius == null || outerRadius == null) return null;\n if (!(percent != null && percent >= ARC_LABEL_MIN_FRACTION)) return null;\n const radius = innerRadius + (outerRadius - innerRadius) * ARC_LABEL_RADIUS;\n // Recharts measures angles anticlockwise from the positive x-axis, SVG's y\n // grows downward, so the sine is negated to land on the drawn arc.\n const radians = (-midAngle * Math.PI) / 180;\n const text =\n labels === \"percent\"\n ? `${Math.round(percent * 100)}%`\n : (valueFormatter?.(Number(value)) ?? String(value ?? \"\"));\n return (\n <text\n data-slot=\"chart-arc-label\"\n x={cx + radius * Math.cos(radians)}\n y={cy + radius * Math.sin(radians)}\n fill={colourOn(fillOf(index ?? 0))}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className=\"pointer-events-none text-[length:var(--ds-text-caption)] font-medium tabular-nums\"\n >\n {text}\n </text>\n );\n };\n}\n\n/**\n * The Recharts side of `Chart`. Returns a chart element for the\n * ResponsiveContainer inside ChartContainer; colours come from `seriesColor`\n * (config colour or `var(--ds-viz-N)` by series index) and every other visual\n * value from the container's token styling.\n */\nexport function RechartsChart({\n type,\n data,\n config,\n indexBy,\n keys,\n stacked,\n legend,\n grid,\n tooltip,\n labels,\n valueFormatter,\n animate = true,\n}: RechartsRenderProps): React.ReactElement {\n // Arc labels sit on top of a series colour, so their ink depends on which\n // colour and on the theme. `useThemeVersion` is the cache key for that DOM\n // read; `element` scopes it to a nested theme rather than the document.\n const themeVersion = useThemeVersion();\n const element = useChart()?.element ?? null;\n // eslint-disable-next-line react-hooks/exhaustive-deps -- themeVersion is the cache key for the DOM read\n const colourOn = React.useMemo(() => contrastLabel(element), [element, themeVersion]);\n // The plot margin is `--ds-space-2`, read from the tokens like every colour\n // here rather than frozen as a number, and on the same cache key so a theme\n // or scale change re-reads it.\n // eslint-disable-next-line react-hooks/exhaustive-deps -- themeVersion is the cache key for the DOM read\n const margin = React.useMemo(() => plotMargin(element), [element, themeVersion]);\n\n const tip = tooltip ? (\n <ChartTooltip\n formatter={valueFormatter ? (value: unknown) => valueFormatter(Number(value)) : undefined}\n />\n ) : null;\n const leg = legend ? <ChartLegend /> : null;\n\n switch (type) {\n case \"bar\": {\n const { rows, indexBy: index, keys: series } = toRows(data as ChartRow[] | ChartSeries[], indexBy, keys);\n return (\n <BarChart data={rows} margin={margin}>\n {grid ? <CartesianGrid vertical={false} /> : null}\n <XAxis dataKey={index} tickLine={false} axisLine={false} tickMargin={8} />\n <YAxis tickLine={false} axisLine={false} tickFormatter={valueFormatter} />\n {tip}\n {leg}\n {series.map((key, i) => (\n <Bar\n key={key}\n dataKey={key}\n name={key}\n fill={seriesColor(config, key, i)}\n stackId={stacked ? \"stack\" : undefined}\n radius={stacked ? 0 : [2, 2, 0, 0]}\n maxBarSize={48}\n />\n ))}\n </BarChart>\n );\n }\n\n case \"line\": {\n const { rows, indexBy: index, keys: series } = toRows(data as ChartRow[] | ChartSeries[], indexBy, keys);\n return (\n <LineChart data={rows} margin={margin}>\n {grid ? <CartesianGrid vertical={false} /> : null}\n <XAxis dataKey={index} tickLine={false} axisLine={false} tickMargin={8} />\n <YAxis tickLine={false} axisLine={false} tickFormatter={valueFormatter} />\n {tip}\n {leg}\n {series.map((key, i) => (\n <Line\n key={key}\n type=\"monotone\"\n dataKey={key}\n name={key}\n stroke={seriesColor(config, key, i)}\n strokeWidth={2}\n dot={false}\n activeDot={{ r: 4 }}\n />\n ))}\n </LineChart>\n );\n }\n\n case \"area\": {\n const { rows, indexBy: index, keys: series } = toRows(data as ChartRow[] | ChartSeries[], indexBy, keys);\n return (\n <AreaChart data={rows} margin={margin}>\n {grid ? <CartesianGrid vertical={false} /> : null}\n <XAxis dataKey={index} tickLine={false} axisLine={false} tickMargin={8} />\n <YAxis tickLine={false} axisLine={false} tickFormatter={valueFormatter} />\n {tip}\n {leg}\n {series.map((key, i) => (\n <Area\n key={key}\n type=\"monotone\"\n dataKey={key}\n name={key}\n stroke={seriesColor(config, key, i)}\n fill={seriesColor(config, key, i)}\n fillOpacity={0.2}\n strokeWidth={2}\n stackId={stacked ? \"stack\" : undefined}\n />\n ))}\n </AreaChart>\n );\n }\n\n case \"pie\":\n case \"donut\": {\n const slices = toSlices(data as ChartSlice[]);\n const fillOf = (i: number) => seriesColor(config, slices[i]?.id ?? String(i), i);\n return (\n <PieChart margin={margin}>\n {tip}\n {leg}\n <Pie\n data={slices}\n dataKey=\"value\"\n nameKey=\"name\"\n innerRadius={type === \"donut\" ? \"55%\" : 0}\n outerRadius=\"80%\"\n paddingAngle={type === \"donut\" ? 2 : 0}\n strokeWidth={1}\n isAnimationActive={animate}\n label={labels === \"none\" ? undefined : arcLabel(labels, colourOn, fillOf, valueFormatter)}\n // The labels are inside their arcs, so there is nothing to lead to.\n labelLine={false}\n >\n {slices.map((slice, i) => (\n <Cell key={slice.id} fill={fillOf(i)} />\n ))}\n </Pie>\n </PieChart>\n );\n }\n\n case \"scatter\":\n case \"scatterplot\": {\n const series = data as ChartSeries[];\n return (\n <ScatterChart margin={margin}>\n {grid ? <CartesianGrid /> : null}\n <XAxis dataKey=\"x\" type=\"number\" name=\"x\" tickLine={false} axisLine={false} tickMargin={8} />\n <YAxis dataKey=\"y\" type=\"number\" name=\"y\" tickLine={false} axisLine={false} tickFormatter={valueFormatter} />\n {tip}\n {leg}\n {series.map((s, i) => (\n <Scatter key={String(s.id)} name={String(s.id)} data={s.data} fill={seriesColor(config, String(s.id), i)} />\n ))}\n </ScatterChart>\n );\n }\n\n case \"radar\": {\n const { rows, indexBy: index, keys: series } = toRows(data as ChartRow[] | ChartSeries[], indexBy, keys);\n return (\n <RadarChart data={rows} margin={margin}>\n {grid ? <PolarGrid /> : null}\n <PolarAngleAxis dataKey={index} />\n <PolarRadiusAxis tick={false} axisLine={false} />\n {tip}\n {leg}\n {series.map((key, i) => (\n <Radar\n key={key}\n dataKey={key}\n name={key}\n stroke={seriesColor(config, key, i)}\n fill={seriesColor(config, key, i)}\n fillOpacity={0.2}\n strokeWidth={2}\n />\n ))}\n </RadarChart>\n );\n }\n\n case \"funnel\": {\n const slices = toSlices(data as ChartSlice[]);\n return (\n <FunnelChart margin={margin}>\n {tip}\n {leg}\n <Funnel data={slices} dataKey=\"value\" nameKey=\"name\">\n {slices.map((slice, i) => (\n <Cell key={slice.id} fill={seriesColor(config, slice.id, i)} />\n ))}\n </Funnel>\n </FunnelChart>\n );\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -40,6 +40,26 @@ function tokenPx(name, el) {
|
|
|
40
40
|
if (raw.endsWith("rem")) return n * (Number.parseFloat(getComputedStyle(document.documentElement).fontSize) || 16);
|
|
41
41
|
return n;
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* The margin a Recharts plot is drawn with, in pixels, resolved on `el`
|
|
45
|
+
* (default `<html>`).
|
|
46
|
+
*
|
|
47
|
+
* Recharts takes a margin as numbers rather than CSS, so the token has to be
|
|
48
|
+
* read and handed over already in pixels. It is `--ds-space-2` at the top and
|
|
49
|
+
* on the right, which is what keeps the topmost y tick label and the last x
|
|
50
|
+
* tick label inside the box; the bottom and the left stay zero because the
|
|
51
|
+
* axes draw their own gutter there. Without a DOM — SSR — the fallback is the
|
|
52
|
+
* 8px that token emits at the default scale, asserted in `chart.test.tsx`.
|
|
53
|
+
*/
|
|
54
|
+
function plotMargin(el) {
|
|
55
|
+
const space2 = tokenPx("--ds-space-2", el) ?? 8;
|
|
56
|
+
return {
|
|
57
|
+
top: space2,
|
|
58
|
+
right: space2,
|
|
59
|
+
bottom: 0,
|
|
60
|
+
left: 0
|
|
61
|
+
};
|
|
62
|
+
}
|
|
43
63
|
let probe;
|
|
44
64
|
function hex2(n) {
|
|
45
65
|
return n.toString(16).padStart(2, "0");
|
|
@@ -187,6 +207,6 @@ function useThemeVersion() {
|
|
|
187
207
|
return version;
|
|
188
208
|
}
|
|
189
209
|
//#endregion
|
|
190
|
-
export { VIZ_SERIES_COUNT, chartScales, contrastLabel, isDarkSurface, piecewiseHex, readToken, resolveColor, resolveVizSeries, toHex, tokenPx, useThemeVersion, vizSeriesVars, vizVar };
|
|
210
|
+
export { VIZ_SERIES_COUNT, chartScales, contrastLabel, isDarkSurface, piecewiseHex, plotMargin, readToken, resolveColor, resolveVizSeries, toHex, tokenPx, useThemeVersion, vizSeriesVars, vizVar };
|
|
191
211
|
|
|
192
212
|
//# sourceMappingURL=tokens.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.js","names":[],"sources":["../../../src/components/chart/tokens.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { vizSeries } from \"cortena-design/tokens\";\n\n/**\n * Token plumbing for the chart engines.\n *\n * Recharts draws SVG, so it can take `var(--ds-viz-1)` verbatim and the\n * browser resolves it. Nivo cannot: its canvas renderer hands colours to a\n * 2D context, and its SVG renderer runs colours through d3-color for label and\n * border derivation, and neither understands `var()`. So every Nivo value is\n * read from the `--ds-*` custom property at runtime and handed over as a\n * concrete hex. Nothing in this file is a literal; on the server (no DOM) the\n * `var()` form is returned so SSR markup still resolves in the browser.\n */\n\n/** Number of categorical series colours the design system defines (`--ds-viz-1..n`). */\nexport const VIZ_SERIES_COUNT = vizSeries.length;\n\n/** `var(--ds-viz-N)` for a zero-based series index, wrapping past the palette. */\nexport function vizVar(index: number): string {\n const n = VIZ_SERIES_COUNT;\n return `var(--ds-viz-${(((index % n) + n) % n) + 1})`;\n}\n\n/** The categorical palette as `var()` references, in series order. */\nexport const vizSeriesVars: readonly string[] = /* @__PURE__ */ Array.from({ length: VIZ_SERIES_COUNT }, (_, i) =>\n vizVar(i),\n);\n\nfunction hasDom(): boolean {\n return typeof document !== \"undefined\" && typeof getComputedStyle === \"function\";\n}\n\n/** Read a custom property as the browser computes it on `el` (default: `<html>`). */\nexport function readToken(name: string, el?: Element | null): string {\n if (!hasDom()) return \"\";\n return getComputedStyle(el ?? document.documentElement).getPropertyValue(name).trim();\n}\n\n/** A `--ds-text-*` size (rem or px) as a pixel number, for engines that want numbers. */\nexport function tokenPx(name: string, el?: Element | null): number | undefined {\n const raw = readToken(name, el);\n if (!raw) return undefined;\n const n = Number.parseFloat(raw);\n if (Number.isNaN(n)) return undefined;\n if (raw.endsWith(\"rem\")) {\n const root = Number.parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;\n return n * root;\n }\n return n;\n}\n\nlet probe: CanvasRenderingContext2D | null | undefined;\n\nfunction hex2(n: number): string {\n return n.toString(16).padStart(2, \"0\");\n}\n\n/**\n * Convert any CSS colour the browser understands (oklch, color-mix, rgba…) to\n * `#rrggbb`, by painting it into an offscreen 2D context. Alpha is composited\n * against transparent, so translucent tokens come back opaque; chart fills\n * never use those.\n */\nexport function toHex(css: string): string | undefined {\n if (!hasDom() || !css) return undefined;\n if (probe === undefined) {\n probe = document.createElement(\"canvas\").getContext(\"2d\", { willReadFrequently: true });\n }\n if (!probe) return undefined;\n probe.clearRect(0, 0, 1, 1);\n probe.fillStyle = css;\n probe.fillRect(0, 0, 1, 1);\n const d = probe.getImageData(0, 0, 1, 1).data;\n return `#${hex2(d[0] ?? 0)}${hex2(d[1] ?? 0)}${hex2(d[2] ?? 0)}`;\n}\n\n/**\n * A token as a concrete colour. Returns hex in the browser; on the server the\n * `var()` form, which is fine for SVG markup and irrelevant for canvas.\n */\nexport function resolveColor(token: string, el?: Element | null): string {\n return toHex(readToken(token, el)) ?? `var(${token})`;\n}\n\n/** The categorical palette resolved to concrete colours, in series order. */\nexport function resolveVizSeries(el?: Element | null): string[] {\n return vizSeriesVars.map((_, i) => resolveColor(`--ds-viz-${i + 1}`, el));\n}\n\n/** Relative luminance of a `#rrggbb`, for choosing a scale direction. */\nfunction luminance(hex: string): number {\n const c = (i: number) => {\n const v = Number.parseInt(hex.slice(i, i + 2), 16) / 255;\n return v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;\n };\n return 0.2126 * c(1) + 0.7152 * c(3) + 0.0722 * c(5);\n}\n\n/**\n * A label colour that reads on a given fill: the design system's ink on light\n * fills, its white on dark ones. Nivo cells and arcs paint their labels with\n * this so a value on a deep sequential cell stays legible.\n */\nexport function contrastLabel(el?: Element | null): (fill: string) => string {\n const ink = resolveColor(\"--ds-base-text-ink\", el);\n const white = resolveColor(\"--ds-base-white\", el);\n return (fill: string) => {\n const hex = fill.startsWith(\"#\") && fill.length === 7 ? fill : toHex(fill);\n return hex && luminance(hex) < 0.3 ? white : ink;\n };\n}\n\n/** True when the resolved `--ds-background` is dark, whatever set the theme (attribute or OS). */\nexport function isDarkSurface(el?: Element | null): boolean {\n const bg = toHex(readToken(\"--ds-background\", el));\n return bg ? luminance(bg) < 0.4 : false;\n}\n\n/** Linear interpolation through a list of hex stops; `t` in [0, 1]. */\nexport function piecewiseHex(stops: string[]): (t: number) => string {\n const rgb = stops.map((h) => [1, 3, 5].map((i) => Number.parseInt(h.slice(i, i + 2), 16)));\n return (t: number) => {\n const clamped = Math.min(1, Math.max(0, Number.isNaN(t) ? 0 : t));\n const pos = clamped * (rgb.length - 1);\n const i = Math.max(0, Math.min(rgb.length - 2, Math.floor(pos)));\n const f = pos - i;\n const a = rgb[i] ?? [0, 0, 0];\n const b = rgb[i + 1] ?? a;\n const mix = (k: number) => Math.round((a[k] ?? 0) + ((b[k] ?? 0) - (a[k] ?? 0)) * f);\n return `#${hex2(mix(0))}${hex2(mix(1))}${hex2(mix(2))}`;\n };\n}\n\nexport interface ChartScales {\n /** Low → high, as concrete hex stops. */\n sequential: string[];\n /** Negative → neutral → positive, as concrete hex stops. */\n diverging: string[];\n /** Interpolators over the stops, `t` in [0, 1], for Nivo's `interpolator` configs. */\n sequentialInterpolator: (t: number) => string;\n divergingInterpolator: (t: number) => string;\n /** `n` evenly spaced sequential swatches, for quantised fills like the calendar. */\n sequentialSteps: (n: number) => string[];\n /** Fill for cells with no value. */\n empty: string;\n /** The chart's surface (`--ds-background`), for the gaps between cells and arcs. */\n surface: string;\n}\n\n/**\n * Sequential and diverging scales from the tokens.\n *\n * The token set has only the eight categorical `--ds-viz-*` colours and no\n * sequential ramp, so the sequential scale is derived from the\n * `--ds-primary-100..900` ladder: light surfaces run 100 → 700 (pale to deep),\n * dark surfaces run 900 → 400 (deep to bright), so low values sit near the\n * background in both themes. The diverging scale runs `--ds-viz-5` (rose)\n * through the theme's neutral (`--ds-neutral-200` light, `--ds-neutral-700`\n * dark) to `--ds-viz-1` (blue).\n */\nexport function chartScales(el?: Element | null): ChartScales {\n const dark = isDarkSurface(el);\n const seqTokens = dark\n ? [\"--ds-primary-900\", \"--ds-primary-800\", \"--ds-primary-600\", \"--ds-primary-400\"]\n : [\"--ds-primary-100\", \"--ds-primary-300\", \"--ds-primary-500\", \"--ds-primary-700\"];\n const sequential = seqTokens.map((t) => resolveColor(t, el));\n const diverging = [\"--ds-viz-5\", dark ? \"--ds-neutral-700\" : \"--ds-neutral-200\", \"--ds-viz-1\"].map(\n (t) => resolveColor(t, el),\n );\n const sequentialInterpolator = piecewiseHex(sequential);\n const divergingInterpolator = piecewiseHex(diverging);\n return {\n sequential,\n diverging,\n sequentialInterpolator,\n divergingInterpolator,\n sequentialSteps: (n) =>\n Array.from({ length: n }, (_, i) => sequentialInterpolator(n === 1 ? 1 : i / (n - 1))),\n empty: resolveColor(\"--ds-muted\", el),\n surface: resolveColor(\"--ds-background\", el),\n };\n}\n\n/**\n * A counter that bumps whenever the theme may have changed: the `data-theme`\n * or `class` attribute on `<html>`, or the OS colour scheme. Resolved token\n * values are memoised on it so Nivo re-reads them on a flip.\n */\nexport function useThemeVersion(): number {\n const [version, setVersion] = useState(0);\n useEffect(() => {\n if (!hasDom()) return;\n const bump = () => setVersion((v) => v + 1);\n const observer = new MutationObserver(bump);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"data-theme\", \"class\", \"style\"],\n });\n const media = window.matchMedia?.(\"(prefers-color-scheme: dark)\");\n media?.addEventListener?.(\"change\", bump);\n return () => {\n observer.disconnect();\n media?.removeEventListener?.(\"change\", bump);\n };\n }, []);\n return version;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tokens.js","names":[],"sources":["../../../src/components/chart/tokens.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { vizSeries } from \"cortena-design/tokens\";\n\n/**\n * Token plumbing for the chart engines.\n *\n * Recharts draws SVG, so it can take `var(--ds-viz-1)` verbatim and the\n * browser resolves it. Nivo cannot: its canvas renderer hands colours to a\n * 2D context, and its SVG renderer runs colours through d3-color for label and\n * border derivation, and neither understands `var()`. So every Nivo value is\n * read from the `--ds-*` custom property at runtime and handed over as a\n * concrete hex. Nothing in this file is a literal; on the server (no DOM) the\n * `var()` form is returned so SSR markup still resolves in the browser.\n */\n\n/** Number of categorical series colours the design system defines (`--ds-viz-1..n`). */\nexport const VIZ_SERIES_COUNT = vizSeries.length;\n\n/** `var(--ds-viz-N)` for a zero-based series index, wrapping past the palette. */\nexport function vizVar(index: number): string {\n const n = VIZ_SERIES_COUNT;\n return `var(--ds-viz-${(((index % n) + n) % n) + 1})`;\n}\n\n/** The categorical palette as `var()` references, in series order. */\nexport const vizSeriesVars: readonly string[] = /* @__PURE__ */ Array.from({ length: VIZ_SERIES_COUNT }, (_, i) =>\n vizVar(i),\n);\n\nfunction hasDom(): boolean {\n return typeof document !== \"undefined\" && typeof getComputedStyle === \"function\";\n}\n\n/** Read a custom property as the browser computes it on `el` (default: `<html>`). */\nexport function readToken(name: string, el?: Element | null): string {\n if (!hasDom()) return \"\";\n return getComputedStyle(el ?? document.documentElement).getPropertyValue(name).trim();\n}\n\n/** A `--ds-text-*` size (rem or px) as a pixel number, for engines that want numbers. */\nexport function tokenPx(name: string, el?: Element | null): number | undefined {\n const raw = readToken(name, el);\n if (!raw) return undefined;\n const n = Number.parseFloat(raw);\n if (Number.isNaN(n)) return undefined;\n if (raw.endsWith(\"rem\")) {\n const root = Number.parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;\n return n * root;\n }\n return n;\n}\n\n/** The plot margin in pixels when there is no DOM: what `--ds-space-2` emits. */\nexport const PLOT_MARGIN_FALLBACK = 8;\n\n/**\n * The margin a Recharts plot is drawn with, in pixels, resolved on `el`\n * (default `<html>`).\n *\n * Recharts takes a margin as numbers rather than CSS, so the token has to be\n * read and handed over already in pixels. It is `--ds-space-2` at the top and\n * on the right, which is what keeps the topmost y tick label and the last x\n * tick label inside the box; the bottom and the left stay zero because the\n * axes draw their own gutter there. Without a DOM — SSR — the fallback is the\n * 8px that token emits at the default scale, asserted in `chart.test.tsx`.\n */\nexport function plotMargin(el?: Element | null): { top: number; right: number; bottom: number; left: number } {\n const space2 = tokenPx(\"--ds-space-2\", el) ?? PLOT_MARGIN_FALLBACK;\n return { top: space2, right: space2, bottom: 0, left: 0 };\n}\n\nlet probe: CanvasRenderingContext2D | null | undefined;\n\nfunction hex2(n: number): string {\n return n.toString(16).padStart(2, \"0\");\n}\n\n/**\n * Convert any CSS colour the browser understands (oklch, color-mix, rgba…) to\n * `#rrggbb`, by painting it into an offscreen 2D context. Alpha is composited\n * against transparent, so translucent tokens come back opaque; chart fills\n * never use those.\n */\nexport function toHex(css: string): string | undefined {\n if (!hasDom() || !css) return undefined;\n if (probe === undefined) {\n probe = document.createElement(\"canvas\").getContext(\"2d\", { willReadFrequently: true });\n }\n if (!probe) return undefined;\n probe.clearRect(0, 0, 1, 1);\n probe.fillStyle = css;\n probe.fillRect(0, 0, 1, 1);\n const d = probe.getImageData(0, 0, 1, 1).data;\n return `#${hex2(d[0] ?? 0)}${hex2(d[1] ?? 0)}${hex2(d[2] ?? 0)}`;\n}\n\n/**\n * A token as a concrete colour. Returns hex in the browser; on the server the\n * `var()` form, which is fine for SVG markup and irrelevant for canvas.\n */\nexport function resolveColor(token: string, el?: Element | null): string {\n return toHex(readToken(token, el)) ?? `var(${token})`;\n}\n\n/** The categorical palette resolved to concrete colours, in series order. */\nexport function resolveVizSeries(el?: Element | null): string[] {\n return vizSeriesVars.map((_, i) => resolveColor(`--ds-viz-${i + 1}`, el));\n}\n\n/** Relative luminance of a `#rrggbb`, for choosing a scale direction. */\nfunction luminance(hex: string): number {\n const c = (i: number) => {\n const v = Number.parseInt(hex.slice(i, i + 2), 16) / 255;\n return v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;\n };\n return 0.2126 * c(1) + 0.7152 * c(3) + 0.0722 * c(5);\n}\n\n/**\n * A label colour that reads on a given fill: the design system's ink on light\n * fills, its white on dark ones. Nivo cells and arcs paint their labels with\n * this so a value on a deep sequential cell stays legible.\n */\nexport function contrastLabel(el?: Element | null): (fill: string) => string {\n const ink = resolveColor(\"--ds-base-text-ink\", el);\n const white = resolveColor(\"--ds-base-white\", el);\n return (fill: string) => {\n const hex = fill.startsWith(\"#\") && fill.length === 7 ? fill : toHex(fill);\n return hex && luminance(hex) < 0.3 ? white : ink;\n };\n}\n\n/** True when the resolved `--ds-background` is dark, whatever set the theme (attribute or OS). */\nexport function isDarkSurface(el?: Element | null): boolean {\n const bg = toHex(readToken(\"--ds-background\", el));\n return bg ? luminance(bg) < 0.4 : false;\n}\n\n/** Linear interpolation through a list of hex stops; `t` in [0, 1]. */\nexport function piecewiseHex(stops: string[]): (t: number) => string {\n const rgb = stops.map((h) => [1, 3, 5].map((i) => Number.parseInt(h.slice(i, i + 2), 16)));\n return (t: number) => {\n const clamped = Math.min(1, Math.max(0, Number.isNaN(t) ? 0 : t));\n const pos = clamped * (rgb.length - 1);\n const i = Math.max(0, Math.min(rgb.length - 2, Math.floor(pos)));\n const f = pos - i;\n const a = rgb[i] ?? [0, 0, 0];\n const b = rgb[i + 1] ?? a;\n const mix = (k: number) => Math.round((a[k] ?? 0) + ((b[k] ?? 0) - (a[k] ?? 0)) * f);\n return `#${hex2(mix(0))}${hex2(mix(1))}${hex2(mix(2))}`;\n };\n}\n\nexport interface ChartScales {\n /** Low → high, as concrete hex stops. */\n sequential: string[];\n /** Negative → neutral → positive, as concrete hex stops. */\n diverging: string[];\n /** Interpolators over the stops, `t` in [0, 1], for Nivo's `interpolator` configs. */\n sequentialInterpolator: (t: number) => string;\n divergingInterpolator: (t: number) => string;\n /** `n` evenly spaced sequential swatches, for quantised fills like the calendar. */\n sequentialSteps: (n: number) => string[];\n /** Fill for cells with no value. */\n empty: string;\n /** The chart's surface (`--ds-background`), for the gaps between cells and arcs. */\n surface: string;\n}\n\n/**\n * Sequential and diverging scales from the tokens.\n *\n * The token set has only the eight categorical `--ds-viz-*` colours and no\n * sequential ramp, so the sequential scale is derived from the\n * `--ds-primary-100..900` ladder: light surfaces run 100 → 700 (pale to deep),\n * dark surfaces run 900 → 400 (deep to bright), so low values sit near the\n * background in both themes. The diverging scale runs `--ds-viz-5` (rose)\n * through the theme's neutral (`--ds-neutral-200` light, `--ds-neutral-700`\n * dark) to `--ds-viz-1` (blue).\n */\nexport function chartScales(el?: Element | null): ChartScales {\n const dark = isDarkSurface(el);\n const seqTokens = dark\n ? [\"--ds-primary-900\", \"--ds-primary-800\", \"--ds-primary-600\", \"--ds-primary-400\"]\n : [\"--ds-primary-100\", \"--ds-primary-300\", \"--ds-primary-500\", \"--ds-primary-700\"];\n const sequential = seqTokens.map((t) => resolveColor(t, el));\n const diverging = [\"--ds-viz-5\", dark ? \"--ds-neutral-700\" : \"--ds-neutral-200\", \"--ds-viz-1\"].map(\n (t) => resolveColor(t, el),\n );\n const sequentialInterpolator = piecewiseHex(sequential);\n const divergingInterpolator = piecewiseHex(diverging);\n return {\n sequential,\n diverging,\n sequentialInterpolator,\n divergingInterpolator,\n sequentialSteps: (n) =>\n Array.from({ length: n }, (_, i) => sequentialInterpolator(n === 1 ? 1 : i / (n - 1))),\n empty: resolveColor(\"--ds-muted\", el),\n surface: resolveColor(\"--ds-background\", el),\n };\n}\n\n/**\n * A counter that bumps whenever the theme may have changed: the `data-theme`\n * or `class` attribute on `<html>`, or the OS colour scheme. Resolved token\n * values are memoised on it so Nivo re-reads them on a flip.\n */\nexport function useThemeVersion(): number {\n const [version, setVersion] = useState(0);\n useEffect(() => {\n if (!hasDom()) return;\n const bump = () => setVersion((v) => v + 1);\n const observer = new MutationObserver(bump);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"data-theme\", \"class\", \"style\"],\n });\n const media = window.matchMedia?.(\"(prefers-color-scheme: dark)\");\n media?.addEventListener?.(\"change\", bump);\n return () => {\n observer.disconnect();\n media?.removeEventListener?.(\"change\", bump);\n };\n }, []);\n return version;\n}\n"],"mappings":"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"}
|
package/dist/core.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Alert, AlertDescription, AlertIcon, AlertProps, AlertTitle, alertVarian
|
|
|
3
3
|
import { AppShell, AppShellExtension, AppShellHelp, AppShellProps, AppShellUser, BottomRightCluster, BottomRightClusterProps, BrandMark, BrandMarkProps, HelpButton, HelpButtonProps, HelpPanelSlotProps, ThemeToggle, ThemeToggleProps, documentTitle } from "./components/app-shell.js";
|
|
4
4
|
import { AuthScreen, AuthScreenBrand, AuthScreenProps, GoogleMark, LoginExtension, LoginMethod, LoginScreen, LoginScreenProps, MicrosoftMark, PasswordCredentials, httpsLogoUrl } from "./components/login-screen.js";
|
|
5
5
|
import { Badge, BadgeProps, badgeVariants } from "./components/badge.js";
|
|
6
|
+
import { RenderProp } from "./lib/render.js";
|
|
6
7
|
import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbLinkProps, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "./components/breadcrumb.js";
|
|
7
8
|
import { Button, ButtonProps, buttonVariants } from "./components/button.js";
|
|
8
9
|
import { ButtonLink, ButtonLinkProps } from "./components/button-link.js";
|
|
@@ -45,4 +46,4 @@ import { Kbd } from "./components/kbd.js";
|
|
|
45
46
|
import { Skeleton } from "./components/skeleton.js";
|
|
46
47
|
import { Tabs, TabsContent, TabsIndicator, TabsList, TabsTrigger } from "./components/tabs.js";
|
|
47
48
|
import { cn } from "./lib/cn.js";
|
|
48
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertIcon, type AlertProps, AlertTitle, AppShell, type AppShellExtension, type AppShellHelp, type AppShellProps, type AppShellUser, AuthScreen, type AuthScreenBrand, type AuthScreenProps, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, BottomRightCluster, type BottomRightClusterProps, BrandMark, type BrandMarkProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, type BreadcrumbLinkProps, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonLink, type ButtonLinkProps, type ButtonProps, Card, CardContent, CardDescription, CardFooter, CardHeader, type CardProps, CardTitle, Checkbox, type CheckboxProps, Chip, type ChipProps, Combobox, ComboboxChip, type ComboboxChipProps, ComboboxChips, type ComboboxChipsProps, ComboboxClear, ComboboxCollection, ComboboxContent, type ComboboxContentProps, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, type ComboboxInputProps, ComboboxItem, ComboboxSeparator, ComboboxStatus, ComboboxTrigger, ComboboxValue, Command, CommandDialog, type CommandDialogProps, CommandEmpty, CommandGroup, CommandInput, CommandItem, type CommandItemProps, CommandList, CommandLoading, CommandSeparator, CommandShortcut, type ConsentClient, type ConsentScope, ConsentScreen, type ConsentScreenProps, type ConsentUser, type CortenaTheme, type CortenaThemeMessage, DEFAULT_SESSION_POLICY, DEFAULT_THEME_STORAGE_KEY, Dialog, DialogBody, DialogClose, DialogContent, type DialogContentProps, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, type DropdownMenuLabelProps, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, type DropdownMenuSubTriggerProps, DropdownMenuTrigger, EmptyState, type EmptyStateProps, ErrorBanner, type ErrorBannerProps, Field, FieldContent, FieldControl, type FieldControlProps, FieldDescription, type FieldDescriptionProps, FieldError, type FieldErrorItem, type FieldErrorProps, FieldGroup, FieldLabel, type FieldLabelProps, type FieldProps, Fieldset, FieldsetLegend, type FieldsetLegendProps, type FieldsetProps, GoogleMark, HelpButton, type HelpButtonProps, type HelpPanelSlotProps, Input, type InputProps, Kbd, Label, type LabelProps, LoadingSkeleton, type LoadingSkeletonPreset, type LoadingSkeletonProps, type LoginExtension, type LoginMethod, LoginScreen, type LoginScreenProps, MicrosoftMark, PageHeader, type PageHeaderProps, type PasswordCredentials, Popover, PopoverClose, PopoverContent, type PopoverContentProps, PopoverDescription, PopoverTitle, PopoverTrigger, Progress, ProgressIndicator, ProgressLabel, type ProgressProps, ProgressTrack, ProgressValue, RadioGroup, RadioGroupItem, type RadioGroupItemProps, type RadioGroupProps, type ResolvedCortenaTheme, SESSION_CHANNEL_NAME, ScrollArea, type ScrollAreaProps, ScrollBar, SectionCard, type SectionCardProps, Segmented, type SegmentedOption, type SegmentedProps, Select, SelectContent, type SelectContentProps, SelectGroup, SelectItem, SelectLabel, type SelectProps, SelectSeparator, SelectTrigger, type SelectTriggerProps, SelectValue, Separator, type SeparatorProps, type SessionClaims, SessionExpiryDialog, type SessionExpiryDialogProps, SessionGuard, type SessionGuardMessage, type SessionGuardProps, type SessionPolicy, type SessionSignOutReason, type SessionState, type SessionTimers, type SessionToken, Sheet, SheetClose, SheetContent, type SheetContentProps, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, type SheetProps, SheetTitle, SheetTrigger, Skeleton, Spinner, type SpinnerProps, StatusDot, type StatusDotProps, type StatusDotTone, Switch, type SwitchProps, THEME_MESSAGE_TYPE, Tabs, TabsContent, TabsIndicator, TabsList, TabsTrigger, Textarea, type TextareaProps, ThemeToggle, type ThemeToggleProps, Toast, type ToastProps, Toaster, type ToasterProps, Toolbar, ToolbarEnd, type ToolbarProps, ToolbarSeparator, ToolbarStart, Tooltip, TooltipContent, type TooltipContentProps, TooltipProvider, TooltipTrigger, type UseCortenaThemeOptions, type UseCortenaThemeResult, type UseSessionGuardOptions, type UseSessionGuardResult, alertVariants, applyStoredTheme, applyTheme, badgeVariants, buttonVariants, chipVariants, cn, decodeSessionClaims, documentTitle, fieldVariants, formatCountdown, getThemeInitScript, httpsLogoUrl, inputClassName, labelVariants, readStoredTheme, sheetVariants, textareaClassName, themeFromBackground, themeFromMessage, themeInitScript, toastVariants, useComboboxFilter, useCortenaTheme, useSessionGuard, useToast };
|
|
49
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertIcon, type AlertProps, AlertTitle, AppShell, type AppShellExtension, type AppShellHelp, type AppShellProps, type AppShellUser, AuthScreen, type AuthScreenBrand, type AuthScreenProps, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, BottomRightCluster, type BottomRightClusterProps, BrandMark, type BrandMarkProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, type BreadcrumbLinkProps, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonLink, type ButtonLinkProps, type ButtonProps, Card, CardContent, CardDescription, CardFooter, CardHeader, type CardProps, CardTitle, Checkbox, type CheckboxProps, Chip, type ChipProps, Combobox, ComboboxChip, type ComboboxChipProps, ComboboxChips, type ComboboxChipsProps, ComboboxClear, ComboboxCollection, ComboboxContent, type ComboboxContentProps, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, type ComboboxInputProps, ComboboxItem, ComboboxSeparator, ComboboxStatus, ComboboxTrigger, ComboboxValue, Command, CommandDialog, type CommandDialogProps, CommandEmpty, CommandGroup, CommandInput, CommandItem, type CommandItemProps, CommandList, CommandLoading, CommandSeparator, CommandShortcut, type ConsentClient, type ConsentScope, ConsentScreen, type ConsentScreenProps, type ConsentUser, type CortenaTheme, type CortenaThemeMessage, DEFAULT_SESSION_POLICY, DEFAULT_THEME_STORAGE_KEY, Dialog, DialogBody, DialogClose, DialogContent, type DialogContentProps, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, type DropdownMenuLabelProps, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, type DropdownMenuSubTriggerProps, DropdownMenuTrigger, EmptyState, type EmptyStateProps, ErrorBanner, type ErrorBannerProps, Field, FieldContent, FieldControl, type FieldControlProps, FieldDescription, type FieldDescriptionProps, FieldError, type FieldErrorItem, type FieldErrorProps, FieldGroup, FieldLabel, type FieldLabelProps, type FieldProps, Fieldset, FieldsetLegend, type FieldsetLegendProps, type FieldsetProps, GoogleMark, HelpButton, type HelpButtonProps, type HelpPanelSlotProps, Input, type InputProps, Kbd, Label, type LabelProps, LoadingSkeleton, type LoadingSkeletonPreset, type LoadingSkeletonProps, type LoginExtension, type LoginMethod, LoginScreen, type LoginScreenProps, MicrosoftMark, PageHeader, type PageHeaderProps, type PasswordCredentials, Popover, PopoverClose, PopoverContent, type PopoverContentProps, PopoverDescription, PopoverTitle, PopoverTrigger, Progress, ProgressIndicator, ProgressLabel, type ProgressProps, ProgressTrack, ProgressValue, RadioGroup, RadioGroupItem, type RadioGroupItemProps, type RadioGroupProps, type RenderProp, type ResolvedCortenaTheme, SESSION_CHANNEL_NAME, ScrollArea, type ScrollAreaProps, ScrollBar, SectionCard, type SectionCardProps, Segmented, type SegmentedOption, type SegmentedProps, Select, SelectContent, type SelectContentProps, SelectGroup, SelectItem, SelectLabel, type SelectProps, SelectSeparator, SelectTrigger, type SelectTriggerProps, SelectValue, Separator, type SeparatorProps, type SessionClaims, SessionExpiryDialog, type SessionExpiryDialogProps, SessionGuard, type SessionGuardMessage, type SessionGuardProps, type SessionPolicy, type SessionSignOutReason, type SessionState, type SessionTimers, type SessionToken, Sheet, SheetClose, SheetContent, type SheetContentProps, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, type SheetProps, SheetTitle, SheetTrigger, Skeleton, Spinner, type SpinnerProps, StatusDot, type StatusDotProps, type StatusDotTone, Switch, type SwitchProps, THEME_MESSAGE_TYPE, Tabs, TabsContent, TabsIndicator, TabsList, TabsTrigger, Textarea, type TextareaProps, ThemeToggle, type ThemeToggleProps, Toast, type ToastProps, Toaster, type ToasterProps, Toolbar, ToolbarEnd, type ToolbarProps, ToolbarSeparator, ToolbarStart, Tooltip, TooltipContent, type TooltipContentProps, TooltipProvider, TooltipTrigger, type UseCortenaThemeOptions, type UseCortenaThemeResult, type UseSessionGuardOptions, type UseSessionGuardResult, alertVariants, applyStoredTheme, applyTheme, badgeVariants, buttonVariants, chipVariants, cn, decodeSessionClaims, documentTitle, fieldVariants, formatCountdown, getThemeInitScript, httpsLogoUrl, inputClassName, labelVariants, readStoredTheme, sheetVariants, textareaClassName, themeFromBackground, themeFromMessage, themeInitScript, toastVariants, useComboboxFilter, useCortenaTheme, useSessionGuard, useToast };
|
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ import { Alert, AlertDescription, AlertIcon, AlertProps, AlertTitle, alertVarian
|
|
|
23
23
|
import { AppShell, AppShellExtension, AppShellHelp, AppShellProps, AppShellUser, BottomRightCluster, BottomRightClusterProps, BrandMark, BrandMarkProps, HelpButton, HelpButtonProps, HelpPanelSlotProps, ThemeToggle, ThemeToggleProps, documentTitle } from "./components/app-shell.js";
|
|
24
24
|
import { AuthScreen, AuthScreenBrand, AuthScreenProps, GoogleMark, LoginExtension, LoginMethod, LoginScreen, LoginScreenProps, MicrosoftMark, PasswordCredentials, httpsLogoUrl } from "./components/login-screen.js";
|
|
25
25
|
import { Badge, BadgeProps, badgeVariants } from "./components/badge.js";
|
|
26
|
+
import { RenderProp } from "./lib/render.js";
|
|
26
27
|
import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbLinkProps, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "./components/breadcrumb.js";
|
|
27
28
|
import { Button, ButtonProps, buttonVariants } from "./components/button.js";
|
|
28
29
|
import { ButtonLink, ButtonLinkProps } from "./components/button-link.js";
|
|
@@ -91,4 +92,4 @@ import { MentionItem, MentionQuery, RichTextChip, RichTextEditor, RichTextEditor
|
|
|
91
92
|
import "./rich-text-editor.js";
|
|
92
93
|
import { SortableHandle, SortableHandleProps, SortableList, SortableListProps, SortableRenderState, SortableReorderDetails, arrayMove } from "./components/sortable-list.js";
|
|
93
94
|
import "./sortable-list.js";
|
|
94
|
-
export { type A2UIAction, type A2UIActionSpec, type A2UIBeginRendering, type A2UICatalogue, type A2UICatalogueDoc, type A2UICatalogueEntry, type A2UIChildList, type A2UIChildren, type A2UIColumn, type A2UIComponentDoc, type A2UIComponentSpec, type A2UICreateSurface, type A2UIDataBinding, type A2UIDeleteSurface, A2UIErrorCard, type A2UIExample, type A2UIFoldResult, type A2UIGroup, type A2UIMessage, type A2UIMessageInput, type A2UINodeInfo, type A2UIPropertyValue, A2UIRenderer, type A2UIRendererProps, type A2UIResolvedAction, type A2UIRow, type A2UISurface, type A2UITableSource, type A2UIUpdateComponents, type A2UIUpdateDataModel, type A2UIView, type A2UIViewProps, A2UI_CATALOGUE_ID, A2UI_DEFAULT_SURFACE_ID, A2UI_VERSION, ADMIN_ROUTES, ADMIN_ROUTE_LABELS, type Accept, Accordion, AccordionContent, AccordionItem, AccordionTrigger, type AdminEffectiveRole, type AdminErrorEnvelope, type AdminGroupRef, type AdminGroupRow, type AdminLicence, AdminLicenceScreen, AdminMatrix, type AdminMemberRow, AdminMembers, type AdminPermissionMatrix, AdminPermissions, type AdminPermissionsApi, type AdminPermissionsContextValue, type AdminPermissionsProps, AdminPermissionsProvider, type AdminPrincipal, type AdminRoleSource, AdminRoles, type AdminRoute, Alert, AlertDescription, AlertIcon, type AlertProps, AlertTitle, AppShell, type AppShellExtension, type AppShellHelp, type AppShellProps, type AppShellUser, Area, AreaChart, AuthScreen, type AuthScreenBrand, type AuthScreenProps, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, Bar, BarChart, BottomRightCluster, type BottomRightClusterProps, BrandMark, type BrandMarkProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, type BreadcrumbLinkProps, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonLink, type ButtonLinkProps, type ButtonProps, Calendar, CalendarDayButton, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, type CardProps, CardTitle, CartesianGrid, Cell, Chart, type ChartConfig, ChartContainer, type ChartContainerProps, type ChartDataFor, type ChartDay, ChartEmpty, type ChartEngine, ChartError, type ChartLabels, ChartLegend, ChartLegendContent, type ChartLegendContentProps, ChartLoading, type ChartMatrix, type ChartPoint, type ChartProps, type ChartRenderer, type ChartRow, type ChartScale, type ChartScales, type ChartSeries, type ChartSlice, ChartTooltip, ChartTooltipContent, type ChartTooltipContentProps, type ChartTree, type ChartType, Checkbox, type CheckboxProps, Chip, type ChipProps, type ClientSource, type CodeRendererProps, Combobox, ComboboxChip, type ComboboxChipProps, ComboboxChips, type ComboboxChipsProps, ComboboxClear, ComboboxCollection, ComboboxContent, type ComboboxContentProps, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, type ComboboxInputProps, ComboboxItem, ComboboxSeparator, ComboboxStatus, ComboboxTrigger, ComboboxValue, Command, CommandDialog, type CommandDialogProps, CommandEmpty, CommandGroup, CommandInput, CommandItem, type CommandItemProps, CommandList, CommandLoading, CommandSeparator, CommandShortcut, ComposedChart, type ConsentClient, type ConsentScope, ConsentScreen, type ConsentScreenProps, type ConsentUser, type CortenaTheme, type CortenaThemeMessage, DEFAULT_SESSION_POLICY, DEFAULT_THEME_STORAGE_KEY, type DataSource, DataTable, type DataTableAutoRefresh, type DataTableAutoRefreshState, type DataTableCell, type DataTableColumn, type DataTableColumnDef, DataTableColumnHeader, type DataTableColumnHeaderProps, type DataTableColumnMeta, type DataTableEditable, type DataTableEditingCell, DataTableExportMenu, type DataTableExportMenuProps, DataTableFacetedFilter, type DataTableFacetedFilterOption, type DataTableFacetedFilterProps, type DataTableFeatures, type DataTableHandle, type DataTableInstance, DataTablePagination, type DataTablePaginationMode, type DataTablePaginationProps, type DataTableProps, DataTableRefresh, type DataTableRefreshPause, type DataTableRefreshProps, type DataTableRow, type DataTableState, type DataTableTable, DataTableToolbar, type DataTableToolbarProps, DataTableView, DataTableViewOptions, type DataTableViewOptionsProps, type DataTableViewProps, DateField, type DateFieldProps, DatePicker, type DatePickerProps, DateRangePicker, type DateRangePickerProps, Dialog, DialogBody, DialogClose, DialogContent, type DialogContentProps, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DirectRoles, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, type DropdownMenuLabelProps, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, type DropdownMenuSubTriggerProps, DropdownMenuTrigger, Dropzone, type DropzoneProps, type DropzoneState, EffectiveRoles, EmptyState, type EmptyStateProps, ErrorBanner, type ErrorBannerProps, type ExportCell, type ExportSheet, Field, FieldContent, FieldControl, type FieldControlProps, FieldDescription, type FieldDescriptionProps, FieldError, type FieldErrorItem, type FieldErrorProps, FieldGroup, FieldLabel, type FieldLabelProps, type FieldProps, Fieldset, FieldsetLegend, type FieldsetLegendProps, type FieldsetProps, FileList, type FileListProps, type FileRejection, Form, FormControl, type FormControlProps, FormDescription, type FormDescriptionProps, FormField, FormItem, type FormItemProps, FormLabel, type FormLabelProps, FormMessage, type FormMessageProps, Funnel, FunnelChart, GoogleMark, HEADING_LEVELS, HelpButton, type HelpButtonProps, type HelpDocument, HelpHotkeys, type HelpHotkeysOptions, type HelpHotkeysProps, HelpPanel, type HelpPanelProps, type HelpPanelSlotConfig, type HelpPanelSlotProps, type HelpRoute, type HelpSection, type HelpSource, Input, type InputProps, type JsonSchema, Kbd, Label, LabelList, type LabelProps, Line, LineChart, LoadingSkeleton, type LoadingSkeletonPreset, type LoadingSkeletonProps, type LoginExtension, type LoginMethod, LoginScreen, type LoginScreenProps, MENTION_PROTOCOL, Markdown, type Components as MarkdownComponents, type MarkdownProps, type MarkdownSnapshot, MentionChip, type MentionChipAttributes, type MentionItem, type MentionQuery, MicrosoftMark, NIVO_TYPES, type NivoTheme, PageHeader, type PageHeaderProps, type ParsedMarkdown, type PasswordCredentials, Pie, PieChart, PolarAngleAxis, PolarGrid, PolarRadiusAxis, Popover, PopoverClose, PopoverContent, type PopoverContentProps, PopoverDescription, PopoverTitle, PopoverTrigger, Progress, ProgressIndicator, ProgressLabel, type ProgressProps, ProgressTrack, ProgressValue, RECHARTS_TYPES, Radar, RadarChart, RadioGroup, RadioGroupItem, type RadioGroupItemProps, type RadioGroupProps, RawBlock, RechartsLegend, RechartsTooltip, ReferenceLine, type ResolvedCortenaTheme, ResponsiveContainer, type RichTextChip, RichTextEditor, type RichTextEditorProps, type RichTextExtensionOptions, type RichTextExternalChange, type RichTextNode, RichTextToolbar, type RichTextToolbarProps, RoleAssignmentDialog, type RoleAssignmentDialogProps, SESSION_CHANNEL_NAME, Scatter, ScatterChart, ScrollArea, type ScrollAreaProps, ScrollBar, SectionCard, type SectionCardProps, Segmented, type SegmentedOption, type SegmentedProps, Select, SelectContent, type SelectContentProps, SelectGroup, SelectItem, SelectLabel, type SelectProps, SelectSeparator, SelectTrigger, type SelectTriggerProps, SelectValue, type SelectionActionContext, Separator, type SeparatorProps, type ServerSource, type SessionClaims, SessionExpiryDialog, type SessionExpiryDialogProps, SessionGuard, type SessionGuardMessage, type SessionGuardProps, type SessionPolicy, type SessionSignOutReason, type SessionState, type SessionTimers, type SessionToken, Sheet, SheetClose, SheetContent, type SheetContentProps, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, type SheetProps, SheetTitle, SheetTrigger, Skeleton, SortableHandle, type SortableHandleProps, SortableList, type SortableListProps, type SortableRenderState, type SortableReorderDetails, Spinner, type SpinnerProps, StatusDot, type StatusDotProps, type StatusDotTone, type SubmitHandler, Switch, type SwitchProps, THEME_MESSAGE_TYPE, type TableQuery, type TableResult, Tabs, TabsContent, TabsIndicator, TabsList, TabsTrigger, Textarea, type TextareaProps, ThemeToggle, type ThemeToggleProps, Toast, type ToastProps, Toaster, type ToasterProps, Toolbar, ToolbarEnd, type ToolbarProps, ToolbarSeparator, ToolbarStart, Tooltip, TooltipContent, type TooltipContentProps, TooltipProvider, TooltipTrigger, type UseCortenaThemeOptions, type UseCortenaThemeResult, type UseDataTableOptions, type UseFormFieldReturn, type UseFormReturn, type UseSessionGuardOptions, type UseSessionGuardResult, VIZ_SERIES_COUNT, XAxis, YAxis, adminErrorMessage, alertVariants, applyStoredTheme, applyTheme, arrayMove, badgeVariants, buttonVariants, catalogueNames, chartEngine, chartScales, chipVariants, cn, createColumnHelper, dataTableFeatures, decodeSessionClaims, defaultCatalogue, documentTitle, downloadCsv, downloadExcel, effectiveRolesOf, fieldVariants, foldMessages, formatCountdown, formatDateDefault, formatDateISO, formatDateLong, formatDateShort, formatFileSize, formatRelative, getAtPointer, getThemeInitScript, helpPanelSlot, httpDocumentUrl, httpsLogoUrl, inputClassName, isDataBinding, labelVariants, markdownSanitizeSchema, parseA2UIMessages, parseDateDefault, parseDateISO, parseHelpDocument, parseMarkdown, pointerSegments, readAction, readChildren, readComponent, readStoredTheme, resolveColor, resolveHelpTarget, resolvePointer, resolveValue, resolveVizSeries, richTextExtensions, serializeMarkdown, seriesColor, setAtPointer, sheetVariants, sourceGroupOf, textareaClassName, themeFromBackground, themeFromMessage, themeInitScript, toCsv, toHex, toSheet, toastVariants, useAdminPermissions, useChart, useComboboxFilter, useCortenaTheme, useDataTable, useForm, useFormField, useHelpHotkeys, useSessionGuard, useToast, vizSeriesVars, vizVar, zodResolver };
|
|
95
|
+
export { type A2UIAction, type A2UIActionSpec, type A2UIBeginRendering, type A2UICatalogue, type A2UICatalogueDoc, type A2UICatalogueEntry, type A2UIChildList, type A2UIChildren, type A2UIColumn, type A2UIComponentDoc, type A2UIComponentSpec, type A2UICreateSurface, type A2UIDataBinding, type A2UIDeleteSurface, A2UIErrorCard, type A2UIExample, type A2UIFoldResult, type A2UIGroup, type A2UIMessage, type A2UIMessageInput, type A2UINodeInfo, type A2UIPropertyValue, A2UIRenderer, type A2UIRendererProps, type A2UIResolvedAction, type A2UIRow, type A2UISurface, type A2UITableSource, type A2UIUpdateComponents, type A2UIUpdateDataModel, type A2UIView, type A2UIViewProps, A2UI_CATALOGUE_ID, A2UI_DEFAULT_SURFACE_ID, A2UI_VERSION, ADMIN_ROUTES, ADMIN_ROUTE_LABELS, type Accept, Accordion, AccordionContent, AccordionItem, AccordionTrigger, type AdminEffectiveRole, type AdminErrorEnvelope, type AdminGroupRef, type AdminGroupRow, type AdminLicence, AdminLicenceScreen, AdminMatrix, type AdminMemberRow, AdminMembers, type AdminPermissionMatrix, AdminPermissions, type AdminPermissionsApi, type AdminPermissionsContextValue, type AdminPermissionsProps, AdminPermissionsProvider, type AdminPrincipal, type AdminRoleSource, AdminRoles, type AdminRoute, Alert, AlertDescription, AlertIcon, type AlertProps, AlertTitle, AppShell, type AppShellExtension, type AppShellHelp, type AppShellProps, type AppShellUser, Area, AreaChart, AuthScreen, type AuthScreenBrand, type AuthScreenProps, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, Bar, BarChart, BottomRightCluster, type BottomRightClusterProps, BrandMark, type BrandMarkProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, type BreadcrumbLinkProps, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonLink, type ButtonLinkProps, type ButtonProps, Calendar, CalendarDayButton, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, type CardProps, CardTitle, CartesianGrid, Cell, Chart, type ChartConfig, ChartContainer, type ChartContainerProps, type ChartDataFor, type ChartDay, ChartEmpty, type ChartEngine, ChartError, type ChartLabels, ChartLegend, ChartLegendContent, type ChartLegendContentProps, ChartLoading, type ChartMatrix, type ChartPoint, type ChartProps, type ChartRenderer, type ChartRow, type ChartScale, type ChartScales, type ChartSeries, type ChartSlice, ChartTooltip, ChartTooltipContent, type ChartTooltipContentProps, type ChartTree, type ChartType, Checkbox, type CheckboxProps, Chip, type ChipProps, type ClientSource, type CodeRendererProps, Combobox, ComboboxChip, type ComboboxChipProps, ComboboxChips, type ComboboxChipsProps, ComboboxClear, ComboboxCollection, ComboboxContent, type ComboboxContentProps, ComboboxEmpty, ComboboxGroup, ComboboxGroupLabel, ComboboxInput, type ComboboxInputProps, ComboboxItem, ComboboxSeparator, ComboboxStatus, ComboboxTrigger, ComboboxValue, Command, CommandDialog, type CommandDialogProps, CommandEmpty, CommandGroup, CommandInput, CommandItem, type CommandItemProps, CommandList, CommandLoading, CommandSeparator, CommandShortcut, ComposedChart, type ConsentClient, type ConsentScope, ConsentScreen, type ConsentScreenProps, type ConsentUser, type CortenaTheme, type CortenaThemeMessage, DEFAULT_SESSION_POLICY, DEFAULT_THEME_STORAGE_KEY, type DataSource, DataTable, type DataTableAutoRefresh, type DataTableAutoRefreshState, type DataTableCell, type DataTableColumn, type DataTableColumnDef, DataTableColumnHeader, type DataTableColumnHeaderProps, type DataTableColumnMeta, type DataTableEditable, type DataTableEditingCell, DataTableExportMenu, type DataTableExportMenuProps, DataTableFacetedFilter, type DataTableFacetedFilterOption, type DataTableFacetedFilterProps, type DataTableFeatures, type DataTableHandle, type DataTableInstance, DataTablePagination, type DataTablePaginationMode, type DataTablePaginationProps, type DataTableProps, DataTableRefresh, type DataTableRefreshPause, type DataTableRefreshProps, type DataTableRow, type DataTableState, type DataTableTable, DataTableToolbar, type DataTableToolbarProps, DataTableView, DataTableViewOptions, type DataTableViewOptionsProps, type DataTableViewProps, DateField, type DateFieldProps, DatePicker, type DatePickerProps, DateRangePicker, type DateRangePickerProps, Dialog, DialogBody, DialogClose, DialogContent, type DialogContentProps, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DirectRoles, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, type DropdownMenuLabelProps, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, type DropdownMenuSubTriggerProps, DropdownMenuTrigger, Dropzone, type DropzoneProps, type DropzoneState, EffectiveRoles, EmptyState, type EmptyStateProps, ErrorBanner, type ErrorBannerProps, type ExportCell, type ExportSheet, Field, FieldContent, FieldControl, type FieldControlProps, FieldDescription, type FieldDescriptionProps, FieldError, type FieldErrorItem, type FieldErrorProps, FieldGroup, FieldLabel, type FieldLabelProps, type FieldProps, Fieldset, FieldsetLegend, type FieldsetLegendProps, type FieldsetProps, FileList, type FileListProps, type FileRejection, Form, FormControl, type FormControlProps, FormDescription, type FormDescriptionProps, FormField, FormItem, type FormItemProps, FormLabel, type FormLabelProps, FormMessage, type FormMessageProps, Funnel, FunnelChart, GoogleMark, HEADING_LEVELS, HelpButton, type HelpButtonProps, type HelpDocument, HelpHotkeys, type HelpHotkeysOptions, type HelpHotkeysProps, HelpPanel, type HelpPanelProps, type HelpPanelSlotConfig, type HelpPanelSlotProps, type HelpRoute, type HelpSection, type HelpSource, Input, type InputProps, type JsonSchema, Kbd, Label, LabelList, type LabelProps, Line, LineChart, LoadingSkeleton, type LoadingSkeletonPreset, type LoadingSkeletonProps, type LoginExtension, type LoginMethod, LoginScreen, type LoginScreenProps, MENTION_PROTOCOL, Markdown, type Components as MarkdownComponents, type MarkdownProps, type MarkdownSnapshot, MentionChip, type MentionChipAttributes, type MentionItem, type MentionQuery, MicrosoftMark, NIVO_TYPES, type NivoTheme, PageHeader, type PageHeaderProps, type ParsedMarkdown, type PasswordCredentials, Pie, PieChart, PolarAngleAxis, PolarGrid, PolarRadiusAxis, Popover, PopoverClose, PopoverContent, type PopoverContentProps, PopoverDescription, PopoverTitle, PopoverTrigger, Progress, ProgressIndicator, ProgressLabel, type ProgressProps, ProgressTrack, ProgressValue, RECHARTS_TYPES, Radar, RadarChart, RadioGroup, RadioGroupItem, type RadioGroupItemProps, type RadioGroupProps, RawBlock, RechartsLegend, RechartsTooltip, ReferenceLine, type RenderProp, type ResolvedCortenaTheme, ResponsiveContainer, type RichTextChip, RichTextEditor, type RichTextEditorProps, type RichTextExtensionOptions, type RichTextExternalChange, type RichTextNode, RichTextToolbar, type RichTextToolbarProps, RoleAssignmentDialog, type RoleAssignmentDialogProps, SESSION_CHANNEL_NAME, Scatter, ScatterChart, ScrollArea, type ScrollAreaProps, ScrollBar, SectionCard, type SectionCardProps, Segmented, type SegmentedOption, type SegmentedProps, Select, SelectContent, type SelectContentProps, SelectGroup, SelectItem, SelectLabel, type SelectProps, SelectSeparator, SelectTrigger, type SelectTriggerProps, SelectValue, type SelectionActionContext, Separator, type SeparatorProps, type ServerSource, type SessionClaims, SessionExpiryDialog, type SessionExpiryDialogProps, SessionGuard, type SessionGuardMessage, type SessionGuardProps, type SessionPolicy, type SessionSignOutReason, type SessionState, type SessionTimers, type SessionToken, Sheet, SheetClose, SheetContent, type SheetContentProps, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, type SheetProps, SheetTitle, SheetTrigger, Skeleton, SortableHandle, type SortableHandleProps, SortableList, type SortableListProps, type SortableRenderState, type SortableReorderDetails, Spinner, type SpinnerProps, StatusDot, type StatusDotProps, type StatusDotTone, type SubmitHandler, Switch, type SwitchProps, THEME_MESSAGE_TYPE, type TableQuery, type TableResult, Tabs, TabsContent, TabsIndicator, TabsList, TabsTrigger, Textarea, type TextareaProps, ThemeToggle, type ThemeToggleProps, Toast, type ToastProps, Toaster, type ToasterProps, Toolbar, ToolbarEnd, type ToolbarProps, ToolbarSeparator, ToolbarStart, Tooltip, TooltipContent, type TooltipContentProps, TooltipProvider, TooltipTrigger, type UseCortenaThemeOptions, type UseCortenaThemeResult, type UseDataTableOptions, type UseFormFieldReturn, type UseFormReturn, type UseSessionGuardOptions, type UseSessionGuardResult, VIZ_SERIES_COUNT, XAxis, YAxis, adminErrorMessage, alertVariants, applyStoredTheme, applyTheme, arrayMove, badgeVariants, buttonVariants, catalogueNames, chartEngine, chartScales, chipVariants, cn, createColumnHelper, dataTableFeatures, decodeSessionClaims, defaultCatalogue, documentTitle, downloadCsv, downloadExcel, effectiveRolesOf, fieldVariants, foldMessages, formatCountdown, formatDateDefault, formatDateISO, formatDateLong, formatDateShort, formatFileSize, formatRelative, getAtPointer, getThemeInitScript, helpPanelSlot, httpDocumentUrl, httpsLogoUrl, inputClassName, isDataBinding, labelVariants, markdownSanitizeSchema, parseA2UIMessages, parseDateDefault, parseDateISO, parseHelpDocument, parseMarkdown, pointerSegments, readAction, readChildren, readComponent, readStoredTheme, resolveColor, resolveHelpTarget, resolvePointer, resolveValue, resolveVizSeries, richTextExtensions, serializeMarkdown, seriesColor, setAtPointer, sheetVariants, sourceGroupOf, textareaClassName, themeFromBackground, themeFromMessage, themeInitScript, toCsv, toHex, toSheet, toastVariants, useAdminPermissions, useChart, useComboboxFilter, useCortenaTheme, useDataTable, useForm, useFormField, useHelpHotkeys, useSessionGuard, useToast, vizSeriesVars, vizVar, zodResolver };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cortena-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"description": "Cortena UI — the shared React component library for cortenaweb and every Cortena extension. shadcn over Base UI, styled entirely from cortena-design tokens.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"repository": {
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
"check": "tsc --noEmit",
|
|
72
72
|
"lint:design": "node ../../lint/cli.mjs --exempt chart-import src",
|
|
73
73
|
"test": "node ../../scripts/test-changed.mjs --package ui",
|
|
74
|
+
"test:dark": "vitest run --config vitest.config.ts --project dark",
|
|
74
75
|
"guide": "vite --config guide/vite.config.ts",
|
|
75
76
|
"guide:build": "vite build --config guide/vite.config.ts",
|
|
76
77
|
"a2ui:catalogue": "node scripts/a2ui-catalogue.mjs",
|
|
@@ -81,7 +82,7 @@
|
|
|
81
82
|
"peerDependencies": {
|
|
82
83
|
"@ag-ui/client": "^0.0.59",
|
|
83
84
|
"@tanstack/react-query": "^5.0.0",
|
|
84
|
-
"cortena-design": ">=3.4.0",
|
|
85
|
+
"cortena-design": ">=3.4.0 <4",
|
|
85
86
|
"react": "^19.0.0",
|
|
86
87
|
"react-dom": "^19.0.0",
|
|
87
88
|
"zod": "^3.25.0 || ^4.0.0"
|
|
@@ -92,13 +93,8 @@
|
|
|
92
93
|
"@dnd-kit/sortable": "^10.0.0",
|
|
93
94
|
"@dnd-kit/utilities": "^3.2.2",
|
|
94
95
|
"@hookform/resolvers": "^5.9.1",
|
|
95
|
-
"@nivo/bar": "^0.99.0",
|
|
96
96
|
"@nivo/calendar": "^0.99.0",
|
|
97
|
-
"@nivo/core": "^0.99.0",
|
|
98
97
|
"@nivo/heatmap": "^0.99.0",
|
|
99
|
-
"@nivo/line": "^0.99.0",
|
|
100
|
-
"@nivo/pie": "^0.99.0",
|
|
101
|
-
"@nivo/scatterplot": "^0.99.0",
|
|
102
98
|
"@nivo/sunburst": "^0.99.0",
|
|
103
99
|
"@nivo/treemap": "^0.99.0",
|
|
104
100
|
"@tanstack/react-table": "^9.2.4",
|
|
@@ -52,6 +52,25 @@ export interface NivoTheme {
|
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* What these four sizes are when there is no DOM to read them from.
|
|
57
|
+
*
|
|
58
|
+
* `nivoTheme` runs on the server too, where `getComputedStyle` does not exist
|
|
59
|
+
* and every `tokenPx` call comes back undefined. Each number below is the
|
|
60
|
+
* pixel value its token emits at the default scale, so the server markup and
|
|
61
|
+
* the first client paint agree. `chart.test.tsx` asserts them against the
|
|
62
|
+
* live tokens, which is what stops them drifting the way the two radii had:
|
|
63
|
+
* `--ds-radius-md` is 12px and fell back to 6, `--ds-radius-sm` is 8px and
|
|
64
|
+
* fell back to 4, so every server-rendered tooltip drew half-round corners
|
|
65
|
+
* until hydration.
|
|
66
|
+
*/
|
|
67
|
+
export const NIVO_SIZE_FALLBACK = {
|
|
68
|
+
captionSm: 11,
|
|
69
|
+
caption: 12,
|
|
70
|
+
radiusMd: 12,
|
|
71
|
+
radiusSm: 8,
|
|
72
|
+
} as const;
|
|
73
|
+
|
|
55
74
|
/**
|
|
56
75
|
* Build the Nivo theme from the tokens, resolved on `el` (default `<html>`).
|
|
57
76
|
* Every colour is read from a `--ds-*` custom property and converted to hex,
|
|
@@ -63,10 +82,10 @@ export interface NivoTheme {
|
|
|
63
82
|
*/
|
|
64
83
|
export function nivoTheme(el?: Element | null): NivoTheme {
|
|
65
84
|
const fontFamily = readToken("--ds-font-body", el) || "var(--ds-font-body)";
|
|
66
|
-
const captionSm = tokenPx("--ds-text-caption-sm", el) ??
|
|
67
|
-
const caption = tokenPx("--ds-text-caption", el) ??
|
|
68
|
-
const radiusMd = tokenPx("--ds-radius-md", el) ??
|
|
69
|
-
const radiusSm = tokenPx("--ds-radius-sm", el) ??
|
|
85
|
+
const captionSm = tokenPx("--ds-text-caption-sm", el) ?? NIVO_SIZE_FALLBACK.captionSm;
|
|
86
|
+
const caption = tokenPx("--ds-text-caption", el) ?? NIVO_SIZE_FALLBACK.caption;
|
|
87
|
+
const radiusMd = tokenPx("--ds-radius-md", el) ?? NIVO_SIZE_FALLBACK.radiusMd;
|
|
88
|
+
const radiusSm = tokenPx("--ds-radius-sm", el) ?? NIVO_SIZE_FALLBACK.radiusSm;
|
|
70
89
|
const foreground = resolveColor("--ds-foreground", el);
|
|
71
90
|
const muted = resolveColor("--ds-muted-foreground", el);
|
|
72
91
|
const border = resolveColor("--ds-border", el);
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
import { seriesColor, useChart } from "./container";
|
|
28
28
|
import { ChartLegend, ChartTooltip } from "./recharts-parts";
|
|
29
29
|
import { toRows, toSlices } from "./data";
|
|
30
|
-
import { contrastLabel, useThemeVersion } from "./tokens";
|
|
30
|
+
import { contrastLabel, plotMargin, useThemeVersion } from "./tokens";
|
|
31
31
|
import type { ChartConfig, ChartLabels, ChartRow, ChartSeries, ChartSlice, ChartType } from "./types";
|
|
32
32
|
|
|
33
33
|
export type RechartsType = Extract<
|
|
@@ -56,8 +56,6 @@ export interface RechartsRenderProps {
|
|
|
56
56
|
animate?: boolean;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
const MARGIN = { top: 8, right: 8, bottom: 0, left: 0 };
|
|
60
|
-
|
|
61
59
|
/**
|
|
62
60
|
* Where an arc label sits, as a fraction of the way from the inner radius to
|
|
63
61
|
* the outer one. Just inside the middle of the band: the arc is widest towards
|
|
@@ -163,6 +161,11 @@ export function RechartsChart({
|
|
|
163
161
|
const element = useChart()?.element ?? null;
|
|
164
162
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- themeVersion is the cache key for the DOM read
|
|
165
163
|
const colourOn = React.useMemo(() => contrastLabel(element), [element, themeVersion]);
|
|
164
|
+
// The plot margin is `--ds-space-2`, read from the tokens like every colour
|
|
165
|
+
// here rather than frozen as a number, and on the same cache key so a theme
|
|
166
|
+
// or scale change re-reads it.
|
|
167
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- themeVersion is the cache key for the DOM read
|
|
168
|
+
const margin = React.useMemo(() => plotMargin(element), [element, themeVersion]);
|
|
166
169
|
|
|
167
170
|
const tip = tooltip ? (
|
|
168
171
|
<ChartTooltip
|
|
@@ -175,7 +178,7 @@ export function RechartsChart({
|
|
|
175
178
|
case "bar": {
|
|
176
179
|
const { rows, indexBy: index, keys: series } = toRows(data as ChartRow[] | ChartSeries[], indexBy, keys);
|
|
177
180
|
return (
|
|
178
|
-
<BarChart data={rows} margin={
|
|
181
|
+
<BarChart data={rows} margin={margin}>
|
|
179
182
|
{grid ? <CartesianGrid vertical={false} /> : null}
|
|
180
183
|
<XAxis dataKey={index} tickLine={false} axisLine={false} tickMargin={8} />
|
|
181
184
|
<YAxis tickLine={false} axisLine={false} tickFormatter={valueFormatter} />
|
|
@@ -199,7 +202,7 @@ export function RechartsChart({
|
|
|
199
202
|
case "line": {
|
|
200
203
|
const { rows, indexBy: index, keys: series } = toRows(data as ChartRow[] | ChartSeries[], indexBy, keys);
|
|
201
204
|
return (
|
|
202
|
-
<LineChart data={rows} margin={
|
|
205
|
+
<LineChart data={rows} margin={margin}>
|
|
203
206
|
{grid ? <CartesianGrid vertical={false} /> : null}
|
|
204
207
|
<XAxis dataKey={index} tickLine={false} axisLine={false} tickMargin={8} />
|
|
205
208
|
<YAxis tickLine={false} axisLine={false} tickFormatter={valueFormatter} />
|
|
@@ -224,7 +227,7 @@ export function RechartsChart({
|
|
|
224
227
|
case "area": {
|
|
225
228
|
const { rows, indexBy: index, keys: series } = toRows(data as ChartRow[] | ChartSeries[], indexBy, keys);
|
|
226
229
|
return (
|
|
227
|
-
<AreaChart data={rows} margin={
|
|
230
|
+
<AreaChart data={rows} margin={margin}>
|
|
228
231
|
{grid ? <CartesianGrid vertical={false} /> : null}
|
|
229
232
|
<XAxis dataKey={index} tickLine={false} axisLine={false} tickMargin={8} />
|
|
230
233
|
<YAxis tickLine={false} axisLine={false} tickFormatter={valueFormatter} />
|
|
@@ -252,7 +255,7 @@ export function RechartsChart({
|
|
|
252
255
|
const slices = toSlices(data as ChartSlice[]);
|
|
253
256
|
const fillOf = (i: number) => seriesColor(config, slices[i]?.id ?? String(i), i);
|
|
254
257
|
return (
|
|
255
|
-
<PieChart margin={
|
|
258
|
+
<PieChart margin={margin}>
|
|
256
259
|
{tip}
|
|
257
260
|
{leg}
|
|
258
261
|
<Pie
|
|
@@ -280,7 +283,7 @@ export function RechartsChart({
|
|
|
280
283
|
case "scatterplot": {
|
|
281
284
|
const series = data as ChartSeries[];
|
|
282
285
|
return (
|
|
283
|
-
<ScatterChart margin={
|
|
286
|
+
<ScatterChart margin={margin}>
|
|
284
287
|
{grid ? <CartesianGrid /> : null}
|
|
285
288
|
<XAxis dataKey="x" type="number" name="x" tickLine={false} axisLine={false} tickMargin={8} />
|
|
286
289
|
<YAxis dataKey="y" type="number" name="y" tickLine={false} axisLine={false} tickFormatter={valueFormatter} />
|
|
@@ -296,7 +299,7 @@ export function RechartsChart({
|
|
|
296
299
|
case "radar": {
|
|
297
300
|
const { rows, indexBy: index, keys: series } = toRows(data as ChartRow[] | ChartSeries[], indexBy, keys);
|
|
298
301
|
return (
|
|
299
|
-
<RadarChart data={rows} margin={
|
|
302
|
+
<RadarChart data={rows} margin={margin}>
|
|
300
303
|
{grid ? <PolarGrid /> : null}
|
|
301
304
|
<PolarAngleAxis dataKey={index} />
|
|
302
305
|
<PolarRadiusAxis tick={false} axisLine={false} />
|
|
@@ -320,7 +323,7 @@ export function RechartsChart({
|
|
|
320
323
|
case "funnel": {
|
|
321
324
|
const slices = toSlices(data as ChartSlice[]);
|
|
322
325
|
return (
|
|
323
|
-
<FunnelChart margin={
|
|
326
|
+
<FunnelChart margin={margin}>
|
|
324
327
|
{tip}
|
|
325
328
|
{leg}
|
|
326
329
|
<Funnel data={slices} dataKey="value" nameKey="name">
|
|
@@ -52,6 +52,25 @@ export function tokenPx(name: string, el?: Element | null): number | undefined {
|
|
|
52
52
|
return n;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/** The plot margin in pixels when there is no DOM: what `--ds-space-2` emits. */
|
|
56
|
+
export const PLOT_MARGIN_FALLBACK = 8;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The margin a Recharts plot is drawn with, in pixels, resolved on `el`
|
|
60
|
+
* (default `<html>`).
|
|
61
|
+
*
|
|
62
|
+
* Recharts takes a margin as numbers rather than CSS, so the token has to be
|
|
63
|
+
* read and handed over already in pixels. It is `--ds-space-2` at the top and
|
|
64
|
+
* on the right, which is what keeps the topmost y tick label and the last x
|
|
65
|
+
* tick label inside the box; the bottom and the left stay zero because the
|
|
66
|
+
* axes draw their own gutter there. Without a DOM — SSR — the fallback is the
|
|
67
|
+
* 8px that token emits at the default scale, asserted in `chart.test.tsx`.
|
|
68
|
+
*/
|
|
69
|
+
export function plotMargin(el?: Element | null): { top: number; right: number; bottom: number; left: number } {
|
|
70
|
+
const space2 = tokenPx("--ds-space-2", el) ?? PLOT_MARGIN_FALLBACK;
|
|
71
|
+
return { top: space2, right: space2, bottom: 0, left: 0 };
|
|
72
|
+
}
|
|
73
|
+
|
|
55
74
|
let probe: CanvasRenderingContext2D | null | undefined;
|
|
56
75
|
|
|
57
76
|
function hex2(n: number): string {
|
package/src/entries/core.ts
CHANGED
|
@@ -37,6 +37,7 @@ export type { PageHeaderProps } from "@/components/page-header";
|
|
|
37
37
|
export type { PopoverContentProps } from "@/components/popover";
|
|
38
38
|
export type { ProgressProps } from "@/components/progress";
|
|
39
39
|
export type { RadioGroupItemProps, RadioGroupProps } from "@/components/radio-group";
|
|
40
|
+
export type { RenderProp } from "@/lib/render";
|
|
40
41
|
export type { ScrollAreaProps } from "@/components/scroll-area";
|
|
41
42
|
export type { SectionCardProps } from "@/components/section-card";
|
|
42
43
|
export type { SegmentedOption, SegmentedProps } from "@/components/segmented";
|