@eifi1/ui-kit 0.48.2 → 0.49.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/README.md +26 -12
- package/dist/admin/admin-action-confirm.js +1 -1
- package/dist/admin/admin-action-confirm.js.map +1 -1
- package/dist/admin/invitations-panel.js +5 -1
- package/dist/admin/invitations-panel.js.map +1 -1
- package/dist/admin/user-roster.d.ts +11 -5
- package/dist/admin/user-roster.js +15 -4
- package/dist/admin/user-roster.js.map +1 -1
- package/dist/auth/accept-invitation.js +2 -2
- package/dist/auth/accept-invitation.js.map +1 -1
- package/dist/auth/not-found-page.js +1 -1
- package/dist/auth/not-found-page.js.map +1 -1
- package/dist/auth/reset-password-form.js +2 -2
- package/dist/auth/reset-password-form.js.map +1 -1
- package/dist/auth/verify-email.js +2 -2
- package/dist/auth/verify-email.js.map +1 -1
- package/dist/billing/plan-card.js +2 -2
- package/dist/billing/plan-card.js.map +1 -1
- package/dist/components/breadcrumbs.d.ts +19 -1
- package/dist/components/breadcrumbs.js +11 -4
- package/dist/components/breadcrumbs.js.map +1 -1
- package/dist/components/button-look.d.ts +37 -7
- package/dist/components/button-look.js +33 -6
- package/dist/components/button-look.js.map +1 -1
- package/dist/components/button.d.ts +4 -1
- package/dist/components/button.js +2 -2
- package/dist/components/button.js.map +1 -1
- package/dist/components/calendar-heatmap.js +2 -1
- package/dist/components/calendar-heatmap.js.map +1 -1
- package/dist/components/chart-edge.d.ts +10 -0
- package/dist/components/chart-edge.js +57 -0
- package/dist/components/chart-edge.js.map +1 -0
- package/dist/components/chart.js +2 -1
- package/dist/components/chart.js.map +1 -1
- package/dist/components/chip.d.ts +8 -1
- package/dist/components/chip.js +4 -1
- package/dist/components/chip.js.map +1 -1
- package/dist/components/confirm-context.d.ts +5 -0
- package/dist/components/confirm-context.js +7 -0
- package/dist/components/confirm-context.js.map +1 -0
- package/dist/components/confirm-dialog.js +3 -3
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +2 -2
- package/dist/components/danger-confirm.js +1 -1
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/data-table-fit.js +21 -3
- package/dist/components/data-table-fit.js.map +1 -1
- package/dist/components/data-table-mobile.d.ts +48 -2
- package/dist/components/data-table-mobile.js +87 -10
- package/dist/components/data-table-mobile.js.map +1 -1
- package/dist/components/data-table-row-actions.d.ts +2 -1
- package/dist/components/data-table-row-actions.js +7 -0
- package/dist/components/data-table-row-actions.js.map +1 -1
- package/dist/components/data-table-row.d.ts +1 -1
- package/dist/components/data-table-row.js.map +1 -1
- package/dist/components/data-table.d.ts +34 -1
- package/dist/components/data-table.js +34 -9
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/error-boundary.js +2 -2
- package/dist/components/error-boundary.js.map +1 -1
- package/dist/components/floating-panel.d.ts +36 -13
- package/dist/components/floating-panel.js +27 -7
- package/dist/components/floating-panel.js.map +1 -1
- package/dist/components/form-actions.d.ts +1 -1
- package/dist/components/form-actions.js +1 -1
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/icon-button.d.ts +11 -0
- package/dist/components/icon-button.js +7 -5
- package/dist/components/icon-button.js.map +1 -1
- package/dist/components/nav-pills.d.ts +8 -1
- package/dist/components/nav-pills.js +61 -38
- package/dist/components/nav-pills.js.map +1 -1
- package/dist/components/page-header-context.d.ts +8 -0
- package/dist/components/page-header-context.js +7 -0
- package/dist/components/page-header-context.js.map +1 -0
- package/dist/components/page-header.d.ts +14 -2
- package/dist/components/page-header.js +10 -1
- package/dist/components/page-header.js.map +1 -1
- package/dist/components/pie-chart.js +2 -1
- package/dist/components/pie-chart.js.map +1 -1
- package/dist/components/progress-bar.js +5 -4
- package/dist/components/progress-bar.js.map +1 -1
- package/dist/components/reauth-dialog.js +1 -1
- package/dist/components/reauth-dialog.js.map +1 -1
- package/dist/components/row-actions-labels.js +3 -1
- package/dist/components/row-actions-labels.js.map +1 -1
- package/dist/components/row-actions.d.ts +43 -9
- package/dist/components/row-actions.js +78 -15
- package/dist/components/row-actions.js.map +1 -1
- package/dist/components/section-nav.d.ts +37 -0
- package/dist/components/section-nav.js +33 -0
- package/dist/components/section-nav.js.map +1 -0
- package/dist/components/series-chart.js +8 -3
- package/dist/components/series-chart.js.map +1 -1
- package/dist/components/share-card.js +1 -1
- package/dist/components/share-card.js.map +1 -1
- package/dist/components/signature-pad.js +1 -1
- package/dist/components/signature-pad.js.map +1 -1
- package/dist/components/sparkline.js +2 -1
- package/dist/components/sparkline.js.map +1 -1
- package/dist/components/stat-tile.js +14 -7
- package/dist/components/stat-tile.js.map +1 -1
- package/dist/components/status-dot.d.ts +5 -1
- package/dist/components/status-dot.js +4 -1
- package/dist/components/status-dot.js.map +1 -1
- package/dist/components/tooltip.js +1 -1
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/translation-review-editor.js +2 -2
- package/dist/components/translation-review-editor.js.map +1 -1
- package/dist/components/translation-review.js +2 -2
- package/dist/components/translation-review.js.map +1 -1
- package/dist/components/treemap.d.ts +5 -2
- package/dist/components/treemap.js +26 -6
- package/dist/components/treemap.js.map +1 -1
- package/dist/components/use-table-state.js +37 -6
- package/dist/components/use-table-state.js.map +1 -1
- package/dist/data-table.js.map +1 -1
- package/dist/demo/demo-banner.js +1 -1
- package/dist/demo/demo-banner.js.map +1 -1
- package/dist/demo/demo-ended.js +1 -1
- package/dist/demo/demo-ended.js.map +1 -1
- package/dist/demo/demo-start.js +1 -1
- package/dist/demo/demo-start.js.map +1 -1
- package/dist/eslint/index.js +1 -1
- package/dist/feedback/feedback-inbox.js +1 -1
- package/dist/feedback/feedback-inbox.js.map +1 -1
- package/dist/hooks/use-dismiss.d.ts +9 -1
- package/dist/hooks/use-dismiss.js +25 -5
- package/dist/hooks/use-dismiss.js.map +1 -1
- package/dist/hooks/use-document-title.d.ts +14 -0
- package/dist/hooks/use-document-title.js +22 -0
- package/dist/hooks/use-document-title.js.map +1 -0
- package/dist/i18n/german.js +6 -2
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +31 -1
- package/dist/i18n/kit-labels.js +43 -2
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/en.js +6 -2
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/es.js +6 -2
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +6 -2
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +6 -2
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +6 -2
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +6 -2
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.js +2 -0
- package/dist/i18n/review.js.map +1 -1
- package/dist/i18n/shared-labels.js +1 -0
- package/dist/i18n/shared-labels.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/dist/landing/landing-actions.js +2 -2
- package/dist/landing/landing-actions.js.map +1 -1
- package/dist/landing/public-header.js +2 -2
- package/dist/landing/public-header.js.map +1 -1
- package/dist/lib/clipboard-minus.d.ts +27 -0
- package/dist/lib/clipboard-minus.js +63 -0
- package/dist/lib/clipboard-minus.js.map +1 -0
- package/dist/lib/document-title.d.ts +17 -0
- package/dist/lib/document-title.js +29 -0
- package/dist/lib/document-title.js.map +1 -0
- package/dist/lib/float-clearance.js +8 -2
- package/dist/lib/float-clearance.js.map +1 -1
- package/dist/lib/format.d.ts +35 -10
- package/dist/lib/format.js +55 -11
- package/dist/lib/format.js.map +1 -1
- package/dist/lib/minus.d.ts +22 -0
- package/dist/lib/minus.js +14 -0
- package/dist/lib/minus.js.map +1 -0
- package/dist/lib/status-tone.d.ts +30 -0
- package/dist/lib/status-tone.js +17 -0
- package/dist/lib/status-tone.js.map +1 -0
- package/dist/settings/settings-layout.js +3 -2
- package/dist/settings/settings-layout.js.map +1 -1
- package/dist/shell/account-menu-language.d.ts +1 -1
- package/dist/shell/account-menu-language.js +9 -1
- package/dist/shell/account-menu-language.js.map +1 -1
- package/dist/shell/app-shell-labels.js +2 -1
- package/dist/shell/app-shell-labels.js.map +1 -1
- package/dist/shell/app-shell.d.ts +58 -16
- package/dist/shell/app-shell.js +151 -43
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/language-code.d.ts +3 -0
- package/dist/shell/language-code.js +8 -0
- package/dist/shell/language-code.js.map +1 -0
- package/dist/shell/topbar-controls.d.ts +14 -6
- package/dist/shell/topbar-controls.js +14 -17
- package/dist/shell/topbar-controls.js.map +1 -1
- package/dist/testing/css-variables.generated.d.ts +1 -1
- package/dist/testing/css-variables.generated.js +1 -1
- package/dist/testing/css-variables.generated.js.map +1 -1
- package/dist/theme/chart-palette.d.ts +82 -15
- package/dist/theme/chart-palette.js +51 -24
- package/dist/theme/chart-palette.js.map +1 -1
- package/dist/theme/palette-presets.d.ts +9 -0
- package/dist/theme/palette-presets.js +77 -62
- package/dist/theme/palette-presets.js.map +1 -1
- package/dist/tour/tour.js +1 -1
- package/dist/tour/tour.js.map +1 -1
- package/dist/wizard/stepper-nav.d.ts +1 -1
- package/dist/wizard/stepper-nav.js +3 -3
- package/dist/wizard/stepper-nav.js.map +1 -1
- package/package.json +1 -1
- package/src/admin/admin-action-confirm.tsx +1 -1
- package/src/admin/invitations-panel.tsx +7 -3
- package/src/admin/user-roster.tsx +23 -6
- package/src/auth/accept-invitation.tsx +3 -3
- package/src/auth/not-found-page.tsx +1 -1
- package/src/auth/reset-password-form.tsx +3 -3
- package/src/auth/verify-email.tsx +3 -3
- package/src/billing/plan-card.tsx +2 -2
- package/src/components/breadcrumbs.tsx +32 -4
- package/src/components/button-look.ts +86 -15
- package/src/components/button.tsx +6 -3
- package/src/components/calendar-heatmap.tsx +2 -1
- package/src/components/chart-edge.ts +73 -0
- package/src/components/chart.tsx +3 -1
- package/src/components/chip.tsx +10 -1
- package/src/components/confirm-context.ts +7 -0
- package/src/components/confirm-dialog.tsx +3 -3
- package/src/components/danger-confirm.tsx +3 -3
- package/src/components/data-table-fit.ts +41 -6
- package/src/components/data-table-mobile.tsx +162 -11
- package/src/components/data-table-row-actions.tsx +9 -1
- package/src/components/data-table-row.tsx +2 -0
- package/src/components/data-table.tsx +82 -18
- package/src/components/error-boundary.tsx +2 -2
- package/src/components/floating-panel.tsx +67 -16
- package/src/components/form-actions.tsx +2 -2
- package/src/components/icon-button.tsx +21 -8
- package/src/components/nav-pills.tsx +29 -2
- package/src/components/page-header-context.ts +8 -0
- package/src/components/page-header.tsx +34 -2
- package/src/components/pie-chart.tsx +2 -1
- package/src/components/progress-bar.tsx +6 -3
- package/src/components/reauth-dialog.tsx +1 -1
- package/src/components/row-actions-labels.ts +2 -0
- package/src/components/row-actions.tsx +154 -33
- package/src/components/section-nav.tsx +65 -0
- package/src/components/series-chart.tsx +12 -3
- package/src/components/share-card.tsx +1 -1
- package/src/components/signature-pad.tsx +1 -1
- package/src/components/sparkline.tsx +2 -1
- package/src/components/stat-tile.tsx +19 -7
- package/src/components/status-dot.tsx +7 -1
- package/src/components/tooltip.tsx +3 -1
- package/src/components/translation-review-editor.tsx +2 -2
- package/src/components/translation-review.tsx +2 -2
- package/src/components/treemap.tsx +34 -8
- package/src/components/use-table-state.ts +63 -8
- package/src/data-table.ts +3 -3
- package/src/demo/demo-banner.tsx +1 -1
- package/src/demo/demo-ended.tsx +1 -1
- package/src/demo/demo-start.tsx +1 -1
- package/src/feedback/feedback-inbox.tsx +1 -1
- package/src/hooks/use-dismiss.ts +43 -4
- package/src/hooks/use-document-title.ts +31 -0
- package/src/i18n/german.ts +4 -0
- package/src/i18n/kit-labels.tsx +76 -1
- package/src/i18n/locales/es.ts +4 -0
- package/src/i18n/locales/fr.ts +4 -0
- package/src/i18n/locales/hu.ts +4 -0
- package/src/i18n/locales/it.ts +4 -0
- package/src/i18n/locales/zh.ts +4 -0
- package/src/i18n/review.ts +2 -0
- package/src/i18n/shared-labels.ts +1 -0
- package/src/index.ts +13 -0
- package/src/landing/landing-actions.tsx +2 -2
- package/src/landing/public-header.tsx +2 -2
- package/src/lib/clipboard-minus.ts +94 -0
- package/src/lib/document-title.ts +41 -0
- package/src/lib/float-clearance.ts +19 -3
- package/src/lib/format.ts +115 -30
- package/src/lib/minus.ts +40 -0
- package/src/lib/status-tone.ts +43 -0
- package/src/settings/settings-layout.tsx +3 -2
- package/src/shell/account-menu-language.tsx +14 -2
- package/src/shell/app-shell-labels.ts +1 -0
- package/src/shell/app-shell.tsx +291 -68
- package/src/shell/language-code.ts +5 -0
- package/src/shell/topbar-controls.tsx +35 -15
- package/src/testing/css-variables.generated.ts +6 -6
- package/src/theme/chart-palette.ts +102 -20
- package/src/theme/palette-presets.ts +121 -84
- package/src/tour/tour.tsx +1 -1
- package/src/wizard/stepper-nav.tsx +4 -4
- package/tokens.css +28 -18
|
@@ -1,23 +1,45 @@
|
|
|
1
1
|
// Chart colour system. Single source of truth lives in the design tokens
|
|
2
2
|
// (:root / .dark in tokens.css): brand = indigo, money = teal/amber/purple,
|
|
3
|
-
// chart-1..
|
|
3
|
+
// chart-1..8 = anyplot's "Imprint" hues (https://anyplot.ai/palette, 0.49 — Paul Tol
|
|
4
|
+
// "Muted" before, still selectable as the `paul-tol` preset).
|
|
4
5
|
// Returning CSS vars here makes every Recharts series theme-aware for free — the
|
|
5
6
|
// SVG fill/stroke resolves --chart-N against the current light/dark token set.
|
|
6
7
|
|
|
7
8
|
import { contrast, parseHex as parseRgbHex } from "./color";
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
/** How many categorical slots `paletteFor` cycles through: anyplot's eight hues. Amber,
|
|
11
|
+
* anyplot's ninth colour, is a semantic warning anchor and not a series slot. A preset
|
|
12
|
+
* that carries more hues (Paul Tol's nine) still writes them as `--chart-N`, but the
|
|
13
|
+
* by-index ramp wraps after eight, so the same series keeps the same colour whichever
|
|
14
|
+
* preset is active. */
|
|
15
|
+
export const PALETTE_SIZE = 8;
|
|
16
|
+
|
|
17
|
+
/** anyplot's colour-vision-deficiency-optimal order over the eight slots — the order
|
|
18
|
+
* that keeps the FIRST n series furthest apart under protan/deutan/tritan simulation.
|
|
19
|
+
* An option (`paletteFor(i, { order: "cvd" })`), not the default: the default order is
|
|
20
|
+
* anyplot's own slot order, so series 1 is always the green. */
|
|
21
|
+
export const CVD_ORDER = [0, 1, 7, 6, 4, 5, 2, 3] as const;
|
|
22
|
+
|
|
23
|
+
export interface PaletteForOptions {
|
|
24
|
+
/** `"slot"` (default): anyplot's slot order. `"cvd"`: {@link CVD_ORDER}. */
|
|
25
|
+
order?: "slot" | "cvd";
|
|
26
|
+
}
|
|
10
27
|
|
|
11
28
|
/** CVD-safe categorical colour for series `index`, as a theme-aware CSS var.
|
|
29
|
+
*
|
|
30
|
+
* The first series is always slot 0 (`--chart-1`, anyplot's green), and the ramp
|
|
31
|
+
* wraps after {@link PALETTE_SIZE}.
|
|
12
32
|
*
|
|
13
33
|
* Wraps in both directions, the way `strokeDash` does: JS `%` keeps the sign,
|
|
14
|
-
* so `-1 %
|
|
34
|
+
* so `-1 % 8` is `-1` and the plain formula named `--chart-0`, a token that does not
|
|
15
35
|
* exist — a series with no stroke at all. A fractional index is truncated, and one
|
|
16
36
|
* that is not a number (NaN, ±Infinity — an `indexOf` miss divided by something)
|
|
17
37
|
* takes the first colour rather than `var(--chart-NaN)`. */
|
|
18
|
-
export function paletteFor(index: number): string {
|
|
38
|
+
export function paletteFor(index: number, options?: PaletteForOptions): string {
|
|
19
39
|
const i = Number.isFinite(index) ? Math.trunc(index) : 0;
|
|
20
|
-
|
|
40
|
+
const position = ((i % PALETTE_SIZE) + PALETTE_SIZE) % PALETTE_SIZE;
|
|
41
|
+
const slot = options?.order === "cvd" ? CVD_ORDER[position] : position;
|
|
42
|
+
return `var(--chart-${slot + 1})`;
|
|
21
43
|
}
|
|
22
44
|
|
|
23
45
|
/** Semantic money colours, theme-aware via tokens. Pair with +/- and arrow
|
|
@@ -26,10 +48,65 @@ export const CHART_COLORS = {
|
|
|
26
48
|
income: "var(--money-income)",
|
|
27
49
|
expense: "var(--money-expense)",
|
|
28
50
|
net: "var(--money-net)",
|
|
51
|
+
neutral: "var(--money-neutral)",
|
|
29
52
|
assigned: "var(--brand)",
|
|
30
53
|
activity: "var(--money-expense)",
|
|
54
|
+
/** A generic total line — not money-coloured, the chart's neutral ink. */
|
|
55
|
+
total: "var(--chart-ink)",
|
|
56
|
+
} as const;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* What a chart draws that is NOT a series (anyplot's roles, 0.49). Two inks, which are
|
|
60
|
+
* the only chart colours that change between light and dark — the eight hues do not:
|
|
61
|
+
*
|
|
62
|
+
* - `other` / `rest` / `disabled` and confidence-`band` fills → the MUTED ink. A
|
|
63
|
+
* treemap's "rest" bucket or a pie's "Other" slice takes this instead of wrapping
|
|
64
|
+
* round to a hue the reader will match to a real series.
|
|
65
|
+
* - `total` / `baseline` / `outline` → the neutral INK.
|
|
66
|
+
*/
|
|
67
|
+
export const CHART_ROLES = {
|
|
68
|
+
other: "var(--chart-muted)",
|
|
69
|
+
rest: "var(--chart-muted)",
|
|
70
|
+
disabled: "var(--chart-muted)",
|
|
71
|
+
band: "var(--chart-muted)",
|
|
72
|
+
total: "var(--chart-ink)",
|
|
73
|
+
baseline: "var(--chart-ink)",
|
|
74
|
+
outline: "var(--chart-ink)",
|
|
31
75
|
} as const;
|
|
32
76
|
|
|
77
|
+
/** `--chart-ink` per theme, as hex (tokens.css holds the same two). */
|
|
78
|
+
export const CHART_INK_HEX = { light: "#1a1a17", dark: "#f0efe8" } as const;
|
|
79
|
+
/** `--chart-muted` per theme, as hex (tokens.css holds the same two). */
|
|
80
|
+
export const CHART_MUTED_HEX = { light: "#6b6a63", dark: "#a8a79f" } as const;
|
|
81
|
+
|
|
82
|
+
/** The 3:1 WCAG 1.4.11 asks of a filled graphical object against its surface. */
|
|
83
|
+
export const EDGE_MIN_CONTRAST = 3;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The 1px edge a FILLED mark (a bar, an area, a treemap tile) needs, or `undefined`.
|
|
87
|
+
*
|
|
88
|
+
* anyplot's answer to hues that sit under 3:1 on the ground (cyan, lime, lavender, ochre
|
|
89
|
+
* and green on cream; matte red and rose on the dark ground): outline the shape in ink,
|
|
90
|
+
* so its boundary is legible while the fill keeps the hue that identifies the series.
|
|
91
|
+
* Only those — a hue that clears 3:1 on every surface given stays unstroked, because an
|
|
92
|
+
* outline on every bar is noise.
|
|
93
|
+
*
|
|
94
|
+
* `fill` must be a measurable `#rgb`/`#rrggbb`; `surfaces` are the grounds the mark can
|
|
95
|
+
* sit on (the card and the page), and the WORST of them decides. Anything it cannot
|
|
96
|
+
* measure gets no edge rather than a guessed one.
|
|
97
|
+
*/
|
|
98
|
+
export function chartEdge(
|
|
99
|
+
fill: string,
|
|
100
|
+
surfaces: readonly string[],
|
|
101
|
+
ink: string = CHART_ROLES.outline,
|
|
102
|
+
): string | undefined {
|
|
103
|
+
if (!parseRgbHex(fill)) return undefined;
|
|
104
|
+
const measurable = surfaces.filter((s) => parseRgbHex(s));
|
|
105
|
+
if (measurable.length === 0) return undefined;
|
|
106
|
+
const worst = Math.min(...measurable.map((s) => contrast(fill, s)));
|
|
107
|
+
return worst < EDGE_MIN_CONTRAST ? ink : undefined;
|
|
108
|
+
}
|
|
109
|
+
|
|
33
110
|
// ── Raw hex stops, by theme ────────────────────────────────────────────────
|
|
34
111
|
// The heatmaps interpolate colours in JS (CSS vars can't be lerped), so they
|
|
35
112
|
// need concrete hex per theme — i.e. the same colours DEFAULT_PRESET already
|
|
@@ -42,9 +119,14 @@ export const CHART_COLORS = {
|
|
|
42
119
|
// DEFAULT_PRESET" — which is not optional: they HAD drifted, five of the six light
|
|
43
120
|
// heat stops, and the light `neutral` was still Tailwind's slate-100, a cool grey on
|
|
44
121
|
// the warm cream page this theme has used since #328.
|
|
122
|
+
//
|
|
123
|
+
// 0.49: the same eight hues in both themes — anyplot does not re-tune a hue for the dark
|
|
124
|
+
// ground, and neither does the kit any more; `chartEdge` outlines the two that fall
|
|
125
|
+
// under 3:1 there (matte red, rose) instead of lifting them into different colours.
|
|
126
|
+
const IMPRINT_HEX = ["#009e73", "#c475fd", "#4467a3", "#bd8233", "#ae3030", "#2abccd", "#954477", "#99b314"] as const;
|
|
45
127
|
export const PALETTE_HEX = {
|
|
46
|
-
light:
|
|
47
|
-
dark:
|
|
128
|
+
light: IMPRINT_HEX,
|
|
129
|
+
dark: IMPRINT_HEX,
|
|
48
130
|
} as const;
|
|
49
131
|
|
|
50
132
|
/** A heatmap's interpolation stops for one theme. Open string fields so any
|
|
@@ -59,24 +141,24 @@ export interface HeatStops {
|
|
|
59
141
|
}
|
|
60
142
|
|
|
61
143
|
/** Diverging (variance: under←0→over) and sequential (spending intensity)
|
|
62
|
-
heatmap stops, per theme
|
|
144
|
+
heatmap stops, per theme — anyplot's scales (0.49). Sequential runs anyplot green →
|
|
145
|
+
blue; diverging runs blue (under) ↔ paper/ink (0, the midpoint) ↔ matte red (over).
|
|
146
|
+
The hues are the same in both themes; only the midpoint flips with the ground. */
|
|
63
147
|
export const HEATMAP_HEX = {
|
|
64
148
|
light: {
|
|
65
|
-
neutral: "#
|
|
66
|
-
under: "#
|
|
67
|
-
over: "#
|
|
68
|
-
seqLow: "#
|
|
69
|
-
seqHigh: "#
|
|
149
|
+
neutral: "#faf8f1", // anyplot's light paper — the diverging scale's 0
|
|
150
|
+
under: "#4467a3",
|
|
151
|
+
over: "#ae3030",
|
|
152
|
+
seqLow: "#009e73",
|
|
153
|
+
seqHigh: "#4467a3",
|
|
70
154
|
empty: "rgba(148,163,184,0.14)",
|
|
71
155
|
},
|
|
72
156
|
dark: {
|
|
73
|
-
neutral: "#
|
|
74
|
-
under: "#
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
seqLow: "#3a2c14", // dim amber, sits just above the page
|
|
79
|
-
seqHigh: "#fbbf24",
|
|
157
|
+
neutral: "#1a1a17", // anyplot's ink — the diverging scale's 0 on the dark ground
|
|
158
|
+
under: "#4467a3",
|
|
159
|
+
over: "#ae3030",
|
|
160
|
+
seqLow: "#009e73",
|
|
161
|
+
seqHigh: "#4467a3",
|
|
80
162
|
empty: "rgba(148,163,184,0.10)",
|
|
81
163
|
},
|
|
82
164
|
} as const;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Appearance presets — the single source of truth for the "palette switcher"
|
|
2
2
|
// (feedback #307). Each preset is a full set of design-token values for BOTH
|
|
3
3
|
// light and dark, covering the page/surface backgrounds, the brand accent, the
|
|
4
|
-
// semantic money trio and the
|
|
4
|
+
// semantic money trio and the categorical chart palette (anyplot's eight "Imprint"
|
|
5
|
+
// hues by default since 0.49, Paul Tol's nine in `PAUL_TOL_PRESET`), plus the
|
|
5
6
|
// heatmap stops. A preset is applied at runtime by writing these as CSS custom
|
|
6
7
|
// properties onto <html> (see palette-store.ts), which instantly re-skins every
|
|
7
8
|
// token-driven surface and chart. The two heatmaps and the treemap interpolate
|
|
@@ -40,7 +41,9 @@ export interface TokenSet {
|
|
|
40
41
|
moneyExpense: string;
|
|
41
42
|
moneyNet: string;
|
|
42
43
|
moneyNeutral: string;
|
|
43
|
-
// Categorical chart series
|
|
44
|
+
// Categorical chart series, written as `--chart-1…9`. anyplot's eight "Imprint" hues by
|
|
45
|
+
// default (0.49), Paul Tol "Muted"'s nine in `PAUL_TOL_PRESET`. `paletteFor` cycles
|
|
46
|
+
// eight; a shorter ramp is repeated to fill `--chart-9` (see `applyTokenSet`).
|
|
44
47
|
chart: string[];
|
|
45
48
|
// Heatmap interpolation stops (variance diverging + spending sequential)
|
|
46
49
|
heat: HeatStops;
|
|
@@ -54,6 +57,59 @@ export interface PalettePreset {
|
|
|
54
57
|
dark: TokenSet;
|
|
55
58
|
}
|
|
56
59
|
|
|
60
|
+
// ── "Imprint" chart hues (feedback #119; the default since 0.49) ─────────────
|
|
61
|
+
// anyplot's categorical palette (https://anyplot.ai/palette), by a colleague of
|
|
62
|
+
// Marcel's. 8 hues + an amber semantic anchor, derived from Wong 2011 by a
|
|
63
|
+
// Petroff-style max-min ΔE search in CAM02-UCS with Machado 2009 CVD simulation —
|
|
64
|
+
// the same lineage as Paul Tol "Muted", one generation on, and tuned for exactly the
|
|
65
|
+
// warm cream paper our light theme uses.
|
|
66
|
+
//
|
|
67
|
+
// 0.49 (Marcel, 2026-10-22): the DEFAULT, in anyplot's slot order, eight slots — amber
|
|
68
|
+
// #DDCC77 left the pool, it is anyplot's semantic warning anchor, not a series colour.
|
|
69
|
+
// The SAME hues in both themes: 0.48 lifted matte red and rose for the dark ground
|
|
70
|
+
// (#BF413E, #A25083), which made the dark chart a different palette from the light one.
|
|
71
|
+
// anyplot answers a hue under 3:1 with a 1px ink edge instead, and so does the kit now
|
|
72
|
+
// (`chartEdge`, drawn by SeriesChart's bars and areas and by Treemap's tiles).
|
|
73
|
+
//
|
|
74
|
+
// Measured on our surfaces (CIEDE2000, Machado severity-100, 8 like-for-like slots on
|
|
75
|
+
// the cream light surface #f6ecd9) — neither palette dominates:
|
|
76
|
+
// Paul Tol Muted min-contrast 1.38 · worst-CVD ΔE00 11.8 · normal ΔE00 16.1
|
|
77
|
+
// imprint min-contrast 1.95 · worst-CVD ΔE00 7.2 · normal ΔE00 22.2
|
|
78
|
+
// i.e. imprint is punchier and has no near-invisible pale slot (Tol's #88ccee sits at
|
|
79
|
+
// 1.5:1 on cream), while Tol separates better under colour-vision deficiency — which is
|
|
80
|
+
// why `paletteFor` offers anyplot's CVD-optimal order (`{ order: "cvd" }`).
|
|
81
|
+
const IMPRINT_HUES = [
|
|
82
|
+
"#009e73", // brand green — first series, always
|
|
83
|
+
"#c475fd", // lavender — creative
|
|
84
|
+
"#4467a3", // blue — cool / info
|
|
85
|
+
"#bd8233", // ochre — earth / commodity
|
|
86
|
+
"#ae3030", // matte red — bad / loss / error
|
|
87
|
+
"#2abccd", // cyan — sky / tech-cool
|
|
88
|
+
"#954477", // rose — wellness / health
|
|
89
|
+
"#99b314", // lime — growth / nature
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
/** anyplot's scales (0.49): sequential green → blue, diverging blue (under) ↔ paper or
|
|
93
|
+
* ink (0) ↔ matte red (over). `chart-palette.ts`'s `HEATMAP_HEX` holds the same. */
|
|
94
|
+
const ANYPLOT_HEAT: Record<"light" | "dark", HeatStops> = {
|
|
95
|
+
light: {
|
|
96
|
+
neutral: "#faf8f1",
|
|
97
|
+
under: "#4467a3",
|
|
98
|
+
over: "#ae3030",
|
|
99
|
+
seqLow: "#009e73",
|
|
100
|
+
seqHigh: "#4467a3",
|
|
101
|
+
empty: "rgba(148,163,184,0.14)",
|
|
102
|
+
},
|
|
103
|
+
dark: {
|
|
104
|
+
neutral: "#1a1a17",
|
|
105
|
+
under: "#4467a3",
|
|
106
|
+
over: "#ae3030",
|
|
107
|
+
seqLow: "#009e73",
|
|
108
|
+
seqHigh: "#4467a3",
|
|
109
|
+
empty: "rgba(148,163,184,0.10)",
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
|
|
57
113
|
// The shipped default (feedback #328): SOLAR-DUSK warm light + INDIGO-NOIR deep
|
|
58
114
|
// dark surfaces — the two curated presets the user picked per mode — but with a
|
|
59
115
|
// SINGLE unified brand accent (indigo) across both modes rather than each
|
|
@@ -62,10 +118,15 @@ export interface PalettePreset {
|
|
|
62
118
|
// the dark block is Indigo Noir (already indigo). The money trio
|
|
63
119
|
// (income/expense/net) drives the chart bars and stays palette-driven so those
|
|
64
120
|
// semantic colours adapt to each mode's contrast (best practice — feedback #328).
|
|
121
|
+
//
|
|
122
|
+
// 0.49: its chart ramp and heat stops are anyplot's ("Imprint", above) — the money
|
|
123
|
+
// trio stays the kit's own (Marcel, 2026-10-22: chart income/expense/net/neutral keep
|
|
124
|
+
// the money tokens, never anyplot's green/red). The 0.48 default, the same surfaces
|
|
125
|
+
// with Paul Tol's ramp, is `PAUL_TOL_PRESET`.
|
|
65
126
|
export const DEFAULT_PRESET: PalettePreset = {
|
|
66
127
|
id: "default",
|
|
67
|
-
name: "
|
|
68
|
-
blurb: "
|
|
128
|
+
name: "Imprint",
|
|
129
|
+
blurb: "anyplot.ai chart hues · solar-dusk light · indigo-noir dark",
|
|
69
130
|
light: {
|
|
70
131
|
// Solar Dusk (light) surfaces, with the brand unified to indigo (see above).
|
|
71
132
|
bgPage: "#ede3cf",
|
|
@@ -84,15 +145,8 @@ export const DEFAULT_PRESET: PalettePreset = {
|
|
|
84
145
|
moneyExpense: "#905902",
|
|
85
146
|
moneyNet: "#7a4fa3",
|
|
86
147
|
moneyNeutral: "#6b6453",
|
|
87
|
-
chart:
|
|
88
|
-
heat:
|
|
89
|
-
neutral: "#f1e7d2",
|
|
90
|
-
under: "#0b6650",
|
|
91
|
-
over: "#9c6418",
|
|
92
|
-
seqLow: "#f6ecd0",
|
|
93
|
-
seqHigh: "#9c6418",
|
|
94
|
-
empty: "rgba(148,163,184,0.14)",
|
|
95
|
-
},
|
|
148
|
+
chart: IMPRINT_HUES,
|
|
149
|
+
heat: ANYPLOT_HEAT.light,
|
|
96
150
|
},
|
|
97
151
|
dark: {
|
|
98
152
|
// Indigo Noir (dark)
|
|
@@ -115,6 +169,36 @@ export const DEFAULT_PRESET: PalettePreset = {
|
|
|
115
169
|
moneyExpense: "#e4b035",
|
|
116
170
|
moneyNet: "#b39aef",
|
|
117
171
|
moneyNeutral: "#9aa1bd",
|
|
172
|
+
chart: IMPRINT_HUES,
|
|
173
|
+
heat: ANYPLOT_HEAT.dark,
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* The 0.48 default: the same surfaces, brand and money, with Paul Tol's "Muted" nine
|
|
180
|
+
* as the chart ramp and the teal/amber heat stops that went with it. Selectable, no
|
|
181
|
+
* longer the default (0.49). `paletteFor` cycles eight, so its ninth hue (#aa4499) is
|
|
182
|
+
* reachable only as `var(--chart-9)`.
|
|
183
|
+
*/
|
|
184
|
+
export const PAUL_TOL_PRESET: PalettePreset = {
|
|
185
|
+
id: "paul-tol",
|
|
186
|
+
name: "Paul Tol muted",
|
|
187
|
+
blurb: "Paul Tol's CVD-safe chart hues · solar-dusk light · indigo-noir dark",
|
|
188
|
+
light: {
|
|
189
|
+
...DEFAULT_PRESET.light,
|
|
190
|
+
chart: ["#332288", "#88ccee", "#44aa99", "#117733", "#999933", "#ddcc77", "#cc6677", "#882255", "#aa4499"],
|
|
191
|
+
heat: {
|
|
192
|
+
neutral: "#f1e7d2",
|
|
193
|
+
under: "#0b6650",
|
|
194
|
+
over: "#9c6418",
|
|
195
|
+
seqLow: "#f6ecd0",
|
|
196
|
+
seqHigh: "#9c6418",
|
|
197
|
+
empty: "rgba(148,163,184,0.14)",
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
dark: {
|
|
201
|
+
...DEFAULT_PRESET.dark,
|
|
118
202
|
chart: ["#7e72d6", "#9fd8f2", "#5fc4b0", "#3fa45f", "#bfbf5e", "#e8dda0", "#e08c9a", "#c25a78", "#cc78be"],
|
|
119
203
|
heat: {
|
|
120
204
|
neutral: "#363a5a",
|
|
@@ -127,73 +211,20 @@ export const DEFAULT_PRESET: PalettePreset = {
|
|
|
127
211
|
},
|
|
128
212
|
};
|
|
129
213
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
// Petroff-style max-min ΔE search in CAM02-UCS with Machado 2009 CVD simulation —
|
|
134
|
-
// the same lineage as our default Paul Tol "Muted", one generation on, and tuned
|
|
135
|
-
// for exactly the warm cream paper our light theme uses.
|
|
136
|
-
//
|
|
137
|
-
// This preset is DEFAULT_PRESET with ONLY the 9 categorical chart hues swapped;
|
|
138
|
-
// surfaces, brand and the semantic money trio stay put, because those were their
|
|
139
|
-
// own deliberate decisions (#307/#328) and are not what the palette is for. The
|
|
140
|
-
// heatmap stops likewise stay teal/amber: they encode under/over, and imprint's
|
|
141
|
-
// own diverging ramp is red↔blue, which would fight the money semantics.
|
|
142
|
-
//
|
|
143
|
-
// Measured on our surfaces (CIEDE2000, Machado severity-100, 8 like-for-like
|
|
144
|
-
// slots on the cream light surface #f6ecd9) — neither palette dominates:
|
|
145
|
-
// Paul Tol Muted min-contrast 1.38 · worst-CVD ΔE00 11.8 · normal ΔE00 16.1
|
|
146
|
-
// imprint min-contrast 1.95 · worst-CVD ΔE00 7.2 · normal ΔE00 22.2
|
|
147
|
-
// i.e. imprint is punchier and has no near-invisible pale slot (Tol's #88ccee
|
|
148
|
-
// sits at 1.5:1 on cream), while Tol separates better under colour-vision
|
|
149
|
-
// deficiency. So this ships as a CHOICE, not as a new default.
|
|
150
|
-
//
|
|
151
|
-
// The dark set keeps imprint's hues verbatim except matte-red and rose, whose
|
|
152
|
-
// lightness is lifted (oklch L 0.50→0.55) because verbatim they land at 2.67:1
|
|
153
|
-
// and 2.76:1 on our deep-indigo dark surface — under WCAG 2.1 SC 1.4.11's 3:1
|
|
154
|
-
// non-text minimum. Lifted they clear it at 3.30:1 / 3.28:1. anyplot documents
|
|
155
|
-
// the same shortfall on their own dark ground and answers it with a stroke halo;
|
|
156
|
-
// lifting keeps the fix in the token layer instead of every chart component.
|
|
157
|
-
const IMPRINT_HUES_LIGHT = [
|
|
158
|
-
"#009E73", // brand green — first series
|
|
159
|
-
"#C475FD", // lavender — creative
|
|
160
|
-
"#4467A3", // blue — cool / info
|
|
161
|
-
"#BD8233", // ochre — earth / commodity
|
|
162
|
-
"#AE3030", // matte red — bad / loss / error
|
|
163
|
-
"#2ABCCD", // cyan — sky / tech-cool
|
|
164
|
-
"#954477", // rose — wellness / health
|
|
165
|
-
"#99B314", // lime — growth / nature
|
|
166
|
-
"#DDCC77", // amber — anyplot's semantic anchor, used here as slot 9
|
|
167
|
-
];
|
|
168
|
-
const IMPRINT_HUES_DARK = [
|
|
169
|
-
"#009E73",
|
|
170
|
-
"#C475FD",
|
|
171
|
-
"#4467A3",
|
|
172
|
-
"#BD8233",
|
|
173
|
-
"#BF413E", // matte red, L-lifted for our dark surface
|
|
174
|
-
"#2ABCCD",
|
|
175
|
-
"#A25083", // rose, L-lifted for our dark surface
|
|
176
|
-
"#99B314",
|
|
177
|
-
"#DDCC77",
|
|
178
|
-
];
|
|
179
|
-
|
|
180
|
-
export const IMPRINT_PRESET: PalettePreset = {
|
|
181
|
-
id: "imprint",
|
|
182
|
-
name: "Imprint",
|
|
183
|
-
blurb: "Colourblind-safe chart hues by anyplot.ai",
|
|
184
|
-
light: { ...DEFAULT_PRESET.light, chart: IMPRINT_HUES_LIGHT },
|
|
185
|
-
dark: { ...DEFAULT_PRESET.dark, chart: IMPRINT_HUES_DARK },
|
|
186
|
-
};
|
|
214
|
+
/** @deprecated 0.49 — use `DEFAULT_PRESET` (Imprint IS the default now); removed in 0.51.
|
|
215
|
+
* A persisted `"imprint"` id resolves to it through `presetById`'s fallback. */
|
|
216
|
+
export const IMPRINT_PRESET: PalettePreset = DEFAULT_PRESET;
|
|
187
217
|
|
|
188
218
|
// The full-theme switcher from #307 stayed retired (feedback #328) — the default
|
|
189
219
|
// is still the single source of truth for surfaces, brand and money (its five
|
|
190
220
|
// alternatives are gone, see the header). What IS selectable is
|
|
191
|
-
// the categorical chart ramp (feedback #119), so
|
|
192
|
-
// set; presetById falls back to the default for any stale persisted id.
|
|
221
|
+
// the categorical chart ramp (feedback #119), so Imprint (the default) and Paul Tol are
|
|
222
|
+
// the live set; presetById falls back to the default for any stale persisted id.
|
|
193
223
|
/**
|
|
194
224
|
* The categorical chart ramp, shared by every derived preset below.
|
|
195
225
|
*
|
|
196
|
-
* Paul Tol's "Muted"
|
|
226
|
+
* The default's ramp (anyplot's eight since 0.49, Paul Tol's "Muted" before), and
|
|
227
|
+
* deliberately NOT re-derived per preset. A
|
|
197
228
|
* categorical ramp solves a different problem from a UI palette — separability among
|
|
198
229
|
* nine unknown siblings, rather than contrast against one known surface — and a set
|
|
199
230
|
* optimised against real dichromat confusion lines beats one spaced evenly by formula.
|
|
@@ -205,7 +236,7 @@ export const IMPRINT_PRESET: PalettePreset = {
|
|
|
205
236
|
* SINGLE_LIGHTNESS_MAX_SERIES — so a chart with more than four series must carry a
|
|
206
237
|
* second channel (a direct label, a pattern, a legend adjacent to the mark).
|
|
207
238
|
*/
|
|
208
|
-
const
|
|
239
|
+
const KIT_RAMP = {
|
|
209
240
|
light: DEFAULT_PRESET.light.chart,
|
|
210
241
|
dark: DEFAULT_PRESET.dark.chart,
|
|
211
242
|
} as const;
|
|
@@ -249,7 +280,7 @@ export const DERIVED_PRESETS: PalettePreset[] = [
|
|
|
249
280
|
moneyExpense: "#8e5900",
|
|
250
281
|
moneyNet: "#7356a2",
|
|
251
282
|
moneyNeutral: "#61646c",
|
|
252
|
-
chart:
|
|
283
|
+
chart: KIT_RAMP.light,
|
|
253
284
|
heat: {
|
|
254
285
|
neutral: "#dce2ef",
|
|
255
286
|
under: "#00725f",
|
|
@@ -274,7 +305,7 @@ export const DERIVED_PRESETS: PalettePreset[] = [
|
|
|
274
305
|
moneyExpense: "#b77b29",
|
|
275
306
|
moneyNet: "#9679c9",
|
|
276
307
|
moneyNeutral: "#a1a5ac",
|
|
277
|
-
chart:
|
|
308
|
+
chart: KIT_RAMP.dark,
|
|
278
309
|
heat: {
|
|
279
310
|
neutral: "#1d212b",
|
|
280
311
|
under: "#009a80",
|
|
@@ -304,7 +335,7 @@ export const DERIVED_PRESETS: PalettePreset[] = [
|
|
|
304
335
|
moneyExpense: "#8e5900",
|
|
305
336
|
moneyNet: "#7356a2",
|
|
306
337
|
moneyNeutral: "#5f6662",
|
|
307
|
-
chart:
|
|
338
|
+
chart: KIT_RAMP.light,
|
|
308
339
|
heat: {
|
|
309
340
|
neutral: "#d8e6dd",
|
|
310
341
|
under: "#00725f",
|
|
@@ -329,7 +360,7 @@ export const DERIVED_PRESETS: PalettePreset[] = [
|
|
|
329
360
|
moneyExpense: "#b87c2a",
|
|
330
361
|
moneyNet: "#977ac9",
|
|
331
362
|
moneyNeutral: "#9fa7a2",
|
|
332
|
-
chart:
|
|
363
|
+
chart: KIT_RAMP.dark,
|
|
333
364
|
heat: {
|
|
334
365
|
neutral: "#1a241e",
|
|
335
366
|
under: "#009a80",
|
|
@@ -359,7 +390,7 @@ export const DERIVED_PRESETS: PalettePreset[] = [
|
|
|
359
390
|
moneyExpense: "#8d5800",
|
|
360
391
|
moneyNet: "#7355a2",
|
|
361
392
|
moneyNeutral: "#676269",
|
|
362
|
-
chart:
|
|
393
|
+
chart: KIT_RAMP.light,
|
|
363
394
|
heat: {
|
|
364
395
|
neutral: "#e7dfea",
|
|
365
396
|
under: "#00715e",
|
|
@@ -384,7 +415,7 @@ export const DERIVED_PRESETS: PalettePreset[] = [
|
|
|
384
415
|
moneyExpense: "#b77b29",
|
|
385
416
|
moneyNet: "#9679c9",
|
|
386
417
|
moneyNeutral: "#a8a2aa",
|
|
387
|
-
chart:
|
|
418
|
+
chart: KIT_RAMP.dark,
|
|
388
419
|
heat: {
|
|
389
420
|
neutral: "#251f27",
|
|
390
421
|
under: "#009980",
|
|
@@ -414,7 +445,7 @@ export const DERIVED_PRESETS: PalettePreset[] = [
|
|
|
414
445
|
moneyExpense: "#8d5800",
|
|
415
446
|
moneyNet: "#7255a1",
|
|
416
447
|
moneyNeutral: "#616467",
|
|
417
|
-
chart:
|
|
448
|
+
chart: KIT_RAMP.light,
|
|
418
449
|
heat: {
|
|
419
450
|
neutral: "#e1e2e3",
|
|
420
451
|
under: "#00715e",
|
|
@@ -439,7 +470,7 @@ export const DERIVED_PRESETS: PalettePreset[] = [
|
|
|
439
470
|
moneyExpense: "#b77b29",
|
|
440
471
|
moneyNet: "#9679c9",
|
|
441
472
|
moneyNeutral: "#a2a5a8",
|
|
442
|
-
chart:
|
|
473
|
+
chart: KIT_RAMP.dark,
|
|
443
474
|
heat: {
|
|
444
475
|
neutral: "#212122",
|
|
445
476
|
under: "#009a80",
|
|
@@ -452,7 +483,7 @@ export const DERIVED_PRESETS: PalettePreset[] = [
|
|
|
452
483
|
},
|
|
453
484
|
];
|
|
454
485
|
|
|
455
|
-
export const PALETTES: PalettePreset[] = [DEFAULT_PRESET,
|
|
486
|
+
export const PALETTES: PalettePreset[] = [DEFAULT_PRESET, PAUL_TOL_PRESET, ...DERIVED_PRESETS];
|
|
456
487
|
|
|
457
488
|
export function presetById(id: string): PalettePreset {
|
|
458
489
|
return PALETTES.find((p) => p.id === id) ?? DEFAULT_PRESET;
|
|
@@ -508,5 +539,11 @@ export function applyTokenSet(
|
|
|
508
539
|
el.style.setProperty("--money-expense", step?.well?.moneyExpense ?? t.moneyExpense);
|
|
509
540
|
el.style.setProperty("--money-net", step?.well?.moneyNet ?? t.moneyNet);
|
|
510
541
|
el.style.setProperty("--money-neutral", step?.well?.moneyNeutral ?? t.moneyNeutral);
|
|
511
|
-
|
|
542
|
+
// All nine `--chart-N`, a shorter ramp repeated: Imprint's eight write `--chart-9` as
|
|
543
|
+
// slot 0 — what `paletteFor(8)` names — so a host addressing `var(--chart-9)` directly
|
|
544
|
+
// follows the cycle, and switching away from Paul Tol's nine leaves no stale ninth hue.
|
|
545
|
+
// An empty ramp (a `derivePalette` set) leaves whatever was there, deliberately.
|
|
546
|
+
if (t.chart.length > 0) {
|
|
547
|
+
for (let i = 0; i < 9; i++) el.style.setProperty(`--chart-${i + 1}`, t.chart[i % t.chart.length]);
|
|
548
|
+
}
|
|
512
549
|
}
|
package/src/tour/tour.tsx
CHANGED
|
@@ -891,7 +891,7 @@ function TourCard({
|
|
|
891
891
|
for this user (a guest sees no "add account" button), leaving the
|
|
892
892
|
undocumented ArrowRight key as the sole escape. */}
|
|
893
893
|
{!((step.awaitClick || step.awaitInput) && step.target && rect) && (
|
|
894
|
-
<Button variant="
|
|
894
|
+
<Button variant="accent" onClick={onNext} className={cn("px-2.5 py-1 text-xs")}>
|
|
895
895
|
{isLast ? labels.done : labels.next}
|
|
896
896
|
</Button>
|
|
897
897
|
)}
|
|
@@ -42,7 +42,7 @@ export function StepperNav<TData extends Record<string, unknown>>({
|
|
|
42
42
|
description,
|
|
43
43
|
className,
|
|
44
44
|
labels,
|
|
45
|
-
finishVariant = "
|
|
45
|
+
finishVariant = "accent",
|
|
46
46
|
finishDisabled = false,
|
|
47
47
|
finishCommit,
|
|
48
48
|
finishDisabledReason,
|
|
@@ -56,7 +56,7 @@ export function StepperNav<TData extends Record<string, unknown>>({
|
|
|
56
56
|
className?: string;
|
|
57
57
|
labels?: LabelOverride<WizardLabels>;
|
|
58
58
|
/** The Finish button's variant — `"danger"` for a destructive commit (an import
|
|
59
|
-
* that replaces what is there). Default `"
|
|
59
|
+
* that replaces what is there). Default `"accent"`. Next keeps `"accent"`. */
|
|
60
60
|
finishVariant?: ButtonVariant;
|
|
61
61
|
/** Disable Finish for a reason of the app's own, on top of the kit's gates
|
|
62
62
|
* (`canFinish`, submitting, validating). */
|
|
@@ -183,14 +183,14 @@ export function StepperNav<TData extends Record<string, unknown>>({
|
|
|
183
183
|
// The last step after a commit. Nothing to finish; Done only when the app gave
|
|
184
184
|
// an `onDone` — otherwise the step carries its own way out.
|
|
185
185
|
forwardButton = wizard.canDone ? (
|
|
186
|
-
<Button variant="
|
|
186
|
+
<Button variant="accent" data-tour="wizard-done" onClick={wizard.done} disabled={doneDisabled}>
|
|
187
187
|
{stepNextLabel ?? l.done ?? DEFAULT_WIZARD_LABELS.done}
|
|
188
188
|
</Button>
|
|
189
189
|
) : null;
|
|
190
190
|
} else {
|
|
191
191
|
forwardButton = (
|
|
192
192
|
<Button
|
|
193
|
-
variant="
|
|
193
|
+
variant="accent"
|
|
194
194
|
data-tour="wizard-next"
|
|
195
195
|
onClick={wizard.goNext}
|
|
196
196
|
disabled={wizard.nextBlocked || pending}
|
package/tokens.css
CHANGED
|
@@ -264,15 +264,23 @@ html[data-text-size="xlarge"] {
|
|
|
264
264
|
--status-pending: #1d4ed8; /* blue-700 — in flight */
|
|
265
265
|
--status-edited: #bf6800; /* solved — dirty, not yet saved */
|
|
266
266
|
--status-error: #b91c1c; /* red-700 — the save failed */
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
--chart-
|
|
274
|
-
--chart-
|
|
275
|
-
--chart-
|
|
267
|
+
/* Chart ramp: anyplot's eight "Imprint" hues (0.49, https://anyplot.ai/palette), the
|
|
268
|
+
SAME in both themes — a hue under 3:1 on the ground gets a 1px ink edge
|
|
269
|
+
(`chartEdge`) rather than a different colour. `--chart-9` repeats slot 1, where
|
|
270
|
+
`paletteFor(8)` lands. Only the two inks below change with the theme:
|
|
271
|
+
`--chart-ink` for totals, baselines and edges; `--chart-muted` for an "other" /
|
|
272
|
+
rest / disabled slice and confidence bands (`CHART_ROLES`). */
|
|
273
|
+
--chart-1: #009e73;
|
|
274
|
+
--chart-2: #c475fd;
|
|
275
|
+
--chart-3: #4467a3;
|
|
276
|
+
--chart-4: #bd8233;
|
|
277
|
+
--chart-5: #ae3030;
|
|
278
|
+
--chart-6: #2abccd;
|
|
279
|
+
--chart-7: #954477;
|
|
280
|
+
--chart-8: #99b314;
|
|
281
|
+
--chart-9: #009e73;
|
|
282
|
+
--chart-ink: #1a1a17;
|
|
283
|
+
--chart-muted: #6b6a63;
|
|
276
284
|
}
|
|
277
285
|
|
|
278
286
|
.dark {
|
|
@@ -306,15 +314,17 @@ html[data-text-size="xlarge"] {
|
|
|
306
314
|
--status-pending: #7dd3fc; /* sky-300 */
|
|
307
315
|
--status-edited: #fbbf24; /* amber-400 */
|
|
308
316
|
--status-error: #fca5a5; /* red-300 */
|
|
309
|
-
--chart-1: #
|
|
310
|
-
--chart-2: #
|
|
311
|
-
--chart-3: #
|
|
312
|
-
--chart-4: #
|
|
313
|
-
--chart-5: #
|
|
314
|
-
--chart-6: #
|
|
315
|
-
--chart-7: #
|
|
316
|
-
--chart-8: #
|
|
317
|
-
--chart-9: #
|
|
317
|
+
--chart-1: #009e73;
|
|
318
|
+
--chart-2: #c475fd;
|
|
319
|
+
--chart-3: #4467a3;
|
|
320
|
+
--chart-4: #bd8233;
|
|
321
|
+
--chart-5: #ae3030;
|
|
322
|
+
--chart-6: #2abccd;
|
|
323
|
+
--chart-7: #954477;
|
|
324
|
+
--chart-8: #99b314;
|
|
325
|
+
--chart-9: #009e73;
|
|
326
|
+
--chart-ink: #f0efe8;
|
|
327
|
+
--chart-muted: #a8a79f;
|
|
318
328
|
}
|
|
319
329
|
|
|
320
330
|
/* ── Derived surface / text roles ───────────────────────────────────────────
|