@krizaka/charts 0.3.0 → 0.4.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 +1 -1
- package/dist/actions-5VG352VZ.js +53 -0
- package/dist/actions-5VG352VZ.js.map +1 -0
- package/dist/bar.d.ts +3 -3
- package/dist/bar.js +7 -6
- package/dist/candlestick.d.ts +2 -2
- package/dist/candlestick.js +6 -5
- package/dist/card.d.ts +52 -0
- package/dist/card.js +19 -0
- package/dist/card.js.map +1 -0
- package/dist/{cartesian-BRhNQ3ib.d.ts → cartesian-CEY_wwe_.d.ts} +12 -2
- package/dist/chart.d.ts +2 -2
- package/dist/chart.js +5 -4
- package/dist/{chunk-BV4DBGN7.js → chunk-7W4T255Q.js} +4 -4
- package/dist/{chunk-W5ILLSPK.js → chunk-AGSSNMK5.js} +5 -5
- package/dist/{chunk-VKZZY2QD.js → chunk-FE4LUGAE.js} +5 -5
- package/dist/{chunk-ARARFMNE.js → chunk-FIQHMJZK.js} +5 -5
- package/dist/chunk-FIQHMJZK.js.map +1 -0
- package/dist/{chunk-ANUCSRUN.js → chunk-GD7TWEN3.js} +3 -3
- package/dist/chunk-GRRFPI27.js +89 -0
- package/dist/chunk-GRRFPI27.js.map +1 -0
- package/dist/{chunk-SLEJDQ3A.js → chunk-HH65IEUV.js} +3 -3
- package/dist/{chunk-OIRHLJBC.js → chunk-IJTI6VJD.js} +3 -3
- package/dist/{chunk-WVTIKOII.js → chunk-IURCLBUQ.js} +2 -2
- package/dist/{chunk-CVWSMUUB.js → chunk-JST4HJC3.js} +33 -15
- package/dist/chunk-JST4HJC3.js.map +1 -0
- package/dist/{chunk-IKQV3NSL.js → chunk-KERGFVSN.js} +3 -3
- package/dist/{chunk-XDDALY4C.js → chunk-KMQ7RANJ.js} +5 -5
- package/dist/{chunk-NCIQMRV3.js → chunk-LLUQEK5J.js} +5 -5
- package/dist/{chunk-AA5EWWYV.js → chunk-LZPZWBBY.js} +2 -2
- package/dist/{chunk-PBQV3B6O.js → chunk-MK2ZFUWM.js} +31 -16
- package/dist/chunk-MK2ZFUWM.js.map +1 -0
- package/dist/{chunk-CSSZLFLO.js → chunk-MRGMLDNS.js} +5 -5
- package/dist/{chunk-I3D7KUGN.js → chunk-NLTZWJLV.js} +3 -3
- package/dist/{chunk-PWMMXRMC.js → chunk-NV52AKHG.js} +3 -3
- package/dist/{chunk-MXLITIGU.js → chunk-NWJ5VDN7.js} +5 -5
- package/dist/{chunk-3CJHBJXA.js → chunk-OVASCEGF.js} +12 -73
- package/dist/chunk-OVASCEGF.js.map +1 -0
- package/dist/{chunk-EQLC2QVN.js → chunk-OZOAKP5F.js} +4 -4
- package/dist/chunk-OZOAKP5F.js.map +1 -0
- package/dist/{chunk-KNDHO67X.js → chunk-P2NK5L3B.js} +3 -3
- package/dist/{chunk-JTKR7ZWP.js → chunk-P6RS2L23.js} +140 -36
- package/dist/chunk-P6RS2L23.js.map +1 -0
- package/dist/{chunk-W5FX4TU3.js → chunk-PGD6SH5I.js} +30 -2
- package/dist/chunk-PGD6SH5I.js.map +1 -0
- package/dist/{chunk-4LBXEAGC.js → chunk-PWZHIGPO.js} +5 -5
- package/dist/{chunk-L2EKYWVI.js → chunk-VEOJNMPF.js} +3 -3
- package/dist/chunk-YHQFW2PR.js +71 -0
- package/dist/chunk-YHQFW2PR.js.map +1 -0
- package/dist/{chunk-C4MFZLJM.js → chunk-Z4T3JFNU.js} +2 -2
- package/dist/{chunk-EEP7PS2L.js → chunk-ZF7LVQTR.js} +3 -3
- package/dist/{context-BgYUymEO.d.ts → context-DNW7bJYw.d.ts} +19 -0
- package/dist/credits.d.ts +1 -1
- package/dist/credits.js +7 -6
- package/dist/earnings.d.ts +3 -3
- package/dist/earnings.js +8 -7
- package/dist/{frame-I7_xYGy5.d.ts → frame-B1HDNm7c.d.ts} +9 -5
- package/dist/funnel.d.ts +2 -2
- package/dist/funnel.js +6 -5
- package/dist/gauge.d.ts +2 -2
- package/dist/gauge.js +4 -3
- package/dist/geo.d.ts +2 -2
- package/dist/geo.js +5 -4
- package/dist/globe.d.ts +2 -2
- package/dist/globe.js +4 -3
- package/dist/goal.d.ts +2 -2
- package/dist/goal.js +5 -4
- package/dist/heatmap.d.ts +2 -2
- package/dist/heatmap.js +6 -5
- package/dist/index.d.ts +5 -3
- package/dist/index.js +45 -37
- package/dist/latency.d.ts +3 -3
- package/dist/latency.js +8 -7
- package/dist/line.d.ts +3 -3
- package/dist/line.js +7 -6
- package/dist/native.d.ts +19 -0
- package/dist/native.js +13 -1
- package/dist/native.js.map +1 -1
- package/dist/pie.d.ts +2 -2
- package/dist/pie.js +6 -5
- package/dist/provider.d.ts +2 -2
- package/dist/provider.js +4 -2
- package/dist/radar.d.ts +2 -2
- package/dist/radar.js +6 -5
- package/dist/sankey.d.ts +2 -2
- package/dist/sankey.js +6 -5
- package/dist/scatter.d.ts +2 -2
- package/dist/scatter.js +6 -5
- package/dist/sparkline.d.ts +2 -2
- package/dist/sparkline.js +6 -5
- package/dist/table-sheet-CQBIAV5N.js +36 -0
- package/dist/table-sheet-CQBIAV5N.js.map +1 -0
- package/dist/throughput.d.ts +3 -3
- package/dist/throughput.js +8 -7
- package/dist/ticker.d.ts +3 -3
- package/dist/ticker.js +8 -7
- package/dist/treemap.d.ts +2 -2
- package/dist/treemap.js +7 -6
- package/package.json +295 -53
- package/registry/area-chart.json +82 -12
- package/registry/bar-chart.json +82 -12
- package/registry/calendar-heatmap.json +46 -18
- package/registry/candlestick.json +46 -18
- package/registry/chart-card.json +235 -0
- package/registry/chart.json +40 -12
- package/registry/charts-provider.json +2 -2
- package/registry/earnings-chart.json +82 -12
- package/registry/examples/chart-card/before-after.d.ts +4 -0
- package/registry/examples/chart-card/before-after.js +22 -0
- package/registry/examples/chart-card/before-after.tsx +22 -0
- package/registry/examples/chart-card/jobs-activity.d.ts +4 -0
- package/registry/examples/chart-card/jobs-activity.js +20 -0
- package/registry/examples/chart-card/jobs-activity.tsx +20 -0
- package/registry/examples/chart-card/sparse-and-empty.d.ts +4 -0
- package/registry/examples/chart-card/sparse-and-empty.js +16 -0
- package/registry/examples/chart-card/sparse-and-empty.tsx +18 -0
- package/registry/examples/chart-card/usage-donut.d.ts +4 -0
- package/registry/examples/chart-card/usage-donut.js +18 -0
- package/registry/examples/chart-card/usage-donut.tsx +18 -0
- package/registry/examples/charts-provider/french-orazaka.js +1 -1
- package/registry/examples/charts-provider/french-orazaka.tsx +1 -1
- package/registry/examples/kpi-stat/dashboard-row.d.ts +4 -0
- package/registry/examples/kpi-stat/dashboard-row.js +19 -0
- package/registry/examples/kpi-stat/dashboard-row.tsx +17 -0
- package/registry/examples/kpi-stat/single.d.ts +4 -0
- package/registry/examples/kpi-stat/single.js +11 -0
- package/registry/examples/kpi-stat/single.tsx +6 -0
- package/registry/funnel.json +46 -18
- package/registry/gauge.json +42 -14
- package/registry/geo-map.json +46 -18
- package/registry/globe.json +40 -12
- package/registry/goal-progress.json +36 -8
- package/registry/heatmap.json +46 -18
- package/registry/index.json +49 -1
- package/registry/job-throughput.json +82 -12
- package/registry/kpi-stat.json +296 -0
- package/registry/latency-chart.json +82 -12
- package/registry/line-chart.json +82 -12
- package/registry/pie-chart.json +92 -36
- package/registry/price-ticker.json +82 -12
- package/registry/radar-chart.json +46 -18
- package/registry/sankey.json +46 -18
- package/registry/scatter-chart.json +46 -18
- package/registry/sparkline.json +38 -10
- package/registry/treemap.json +40 -12
- package/dist/chunk-3CJHBJXA.js.map +0 -1
- package/dist/chunk-ARARFMNE.js.map +0 -1
- package/dist/chunk-CVWSMUUB.js.map +0 -1
- package/dist/chunk-EQLC2QVN.js.map +0 -1
- package/dist/chunk-JTKR7ZWP.js.map +0 -1
- package/dist/chunk-PBQV3B6O.js.map +0 -1
- package/dist/chunk-W5FX4TU3.js.map +0 -1
- /package/dist/{chunk-BV4DBGN7.js.map → chunk-7W4T255Q.js.map} +0 -0
- /package/dist/{chunk-W5ILLSPK.js.map → chunk-AGSSNMK5.js.map} +0 -0
- /package/dist/{chunk-VKZZY2QD.js.map → chunk-FE4LUGAE.js.map} +0 -0
- /package/dist/{chunk-ANUCSRUN.js.map → chunk-GD7TWEN3.js.map} +0 -0
- /package/dist/{chunk-SLEJDQ3A.js.map → chunk-HH65IEUV.js.map} +0 -0
- /package/dist/{chunk-OIRHLJBC.js.map → chunk-IJTI6VJD.js.map} +0 -0
- /package/dist/{chunk-WVTIKOII.js.map → chunk-IURCLBUQ.js.map} +0 -0
- /package/dist/{chunk-IKQV3NSL.js.map → chunk-KERGFVSN.js.map} +0 -0
- /package/dist/{chunk-XDDALY4C.js.map → chunk-KMQ7RANJ.js.map} +0 -0
- /package/dist/{chunk-NCIQMRV3.js.map → chunk-LLUQEK5J.js.map} +0 -0
- /package/dist/{chunk-AA5EWWYV.js.map → chunk-LZPZWBBY.js.map} +0 -0
- /package/dist/{chunk-CSSZLFLO.js.map → chunk-MRGMLDNS.js.map} +0 -0
- /package/dist/{chunk-I3D7KUGN.js.map → chunk-NLTZWJLV.js.map} +0 -0
- /package/dist/{chunk-PWMMXRMC.js.map → chunk-NV52AKHG.js.map} +0 -0
- /package/dist/{chunk-MXLITIGU.js.map → chunk-NWJ5VDN7.js.map} +0 -0
- /package/dist/{chunk-KNDHO67X.js.map → chunk-P2NK5L3B.js.map} +0 -0
- /package/dist/{chunk-4LBXEAGC.js.map → chunk-PWZHIGPO.js.map} +0 -0
- /package/dist/{chunk-L2EKYWVI.js.map → chunk-VEOJNMPF.js.map} +0 -0
- /package/dist/{chunk-C4MFZLJM.js.map → chunk-Z4T3JFNU.js.map} +0 -0
- /package/dist/{chunk-EEP7PS2L.js.map → chunk-ZF7LVQTR.js.map} +0 -0
|
@@ -1,72 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
showData: "Show data",
|
|
6
|
-
hideData: "Hide data",
|
|
7
|
-
tableCaption: "{title} \u2014 data",
|
|
8
|
-
exportPng: "PNG",
|
|
9
|
-
exportSvg: "SVG",
|
|
10
|
-
exportCsv: "CSV",
|
|
11
|
-
loading: "Loading chart\u2026",
|
|
12
|
-
empty: "No data for this period yet.",
|
|
13
|
-
error: "The chart could not be loaded.",
|
|
14
|
-
keyboardHint: "Use the arrow keys to move between points, Home and End to jump to the ends.",
|
|
15
|
-
roleDescription: "chart",
|
|
16
|
-
summaryIntro: "{kind}, {count}.",
|
|
17
|
-
summarySeries: "{label}: from {first} to {last}",
|
|
18
|
-
summaryRange: "lowest {min} ({minAt}), highest {max} ({maxAt})",
|
|
19
|
-
summaryTrendUp: "up {change}",
|
|
20
|
-
summaryTrendDown: "down {change}",
|
|
21
|
-
summaryTrendFlat: "stable",
|
|
22
|
-
summaryTotal: "total {total}",
|
|
23
|
-
summaryThreshold: "{label} at {value}",
|
|
24
|
-
summaryShare: "{label} {value} ({share})",
|
|
25
|
-
summaryCorrelation: "correlation {r}",
|
|
26
|
-
summaryConversion: "{from} \u2192 {to} {rate}",
|
|
27
|
-
summaryOverall: "overall {rate}",
|
|
28
|
-
summaryPeak: "peak {value} ({at})",
|
|
29
|
-
summaryActive: "{count} with a value",
|
|
30
|
-
summaryOhlc: "opened at {open}, closed at {close}, low {low}, high {high}",
|
|
31
|
-
kinds: {
|
|
32
|
-
line: "Line chart",
|
|
33
|
-
area: "Area chart",
|
|
34
|
-
bar: "Bar chart",
|
|
35
|
-
pie: "Pie chart",
|
|
36
|
-
donut: "Donut chart",
|
|
37
|
-
gauge: "Gauge",
|
|
38
|
-
sparkline: "Sparkline",
|
|
39
|
-
radar: "Radar chart",
|
|
40
|
-
heatmap: "Heatmap",
|
|
41
|
-
calendar: "Calendar heatmap",
|
|
42
|
-
sankey: "Flow diagram",
|
|
43
|
-
funnel: "Funnel",
|
|
44
|
-
candlestick: "Candlestick chart",
|
|
45
|
-
treemap: "Treemap",
|
|
46
|
-
scatter: "Scatter chart",
|
|
47
|
-
map: "Map",
|
|
48
|
-
globe: "Globe",
|
|
49
|
-
chart: "Chart"
|
|
50
|
-
},
|
|
51
|
-
category: "Category",
|
|
52
|
-
value: "Value",
|
|
53
|
-
total: "Total",
|
|
54
|
-
noValue: "\u2014"
|
|
55
|
-
};
|
|
56
|
-
function mergeLabels(...layers) {
|
|
57
|
-
let out = DEFAULT_LABELS;
|
|
58
|
-
for (const layer of layers) {
|
|
59
|
-
if (!layer) continue;
|
|
60
|
-
out = { ...out, ...layer, kinds: { ...out.kinds, ...layer.kinds } };
|
|
61
|
-
}
|
|
62
|
-
return out;
|
|
63
|
-
}
|
|
64
|
-
function capitalize(text) {
|
|
65
|
-
return text.charAt(0).toLocaleUpperCase() + text.slice(1);
|
|
66
|
-
}
|
|
67
|
-
function fill(template, values) {
|
|
68
|
-
return template.replace(/\{(\w+)\}/g, (match, name) => name in values ? String(values[name]) : match);
|
|
69
|
-
}
|
|
2
|
+
import {
|
|
3
|
+
mergeLabels
|
|
4
|
+
} from "./chunk-GRRFPI27.js";
|
|
70
5
|
|
|
71
6
|
// src/web/context.tsx
|
|
72
7
|
import { createContext, useContext, useMemo } from "react";
|
|
@@ -88,6 +23,11 @@ function useChartSettings(own) {
|
|
|
88
23
|
[own.locale, own.brand, own.labels, shared]
|
|
89
24
|
);
|
|
90
25
|
}
|
|
26
|
+
var CardContext = createContext(null);
|
|
27
|
+
var ChartCardProvider = CardContext.Provider;
|
|
28
|
+
function useChartCard() {
|
|
29
|
+
return useContext(CardContext);
|
|
30
|
+
}
|
|
91
31
|
|
|
92
32
|
// src/core/palette.ts
|
|
93
33
|
var HUES = {
|
|
@@ -102,7 +42,7 @@ var HUES = {
|
|
|
102
42
|
};
|
|
103
43
|
var ORDERS = {
|
|
104
44
|
krizaka: ["blue", "green", "magenta", "yellow", "aqua", "orange", "violet", "red"],
|
|
105
|
-
orazaka: ["orange", "
|
|
45
|
+
orazaka: ["orange", "blue", "aqua", "yellow", "magenta", "green", "violet", "red"],
|
|
106
46
|
orochia: ["violet", "magenta", "yellow", "aqua", "orange", "blue", "green", "red"]
|
|
107
47
|
};
|
|
108
48
|
function palette(brand, mode) {
|
|
@@ -171,11 +111,10 @@ function contrast(a, b) {
|
|
|
171
111
|
}
|
|
172
112
|
|
|
173
113
|
export {
|
|
174
|
-
DEFAULT_LABELS,
|
|
175
|
-
capitalize,
|
|
176
|
-
fill,
|
|
177
114
|
ChartsProvider,
|
|
178
115
|
useChartSettings,
|
|
116
|
+
ChartCardProvider,
|
|
117
|
+
useChartCard,
|
|
179
118
|
HUES,
|
|
180
119
|
ORDERS,
|
|
181
120
|
palette,
|
|
@@ -183,4 +122,4 @@ export {
|
|
|
183
122
|
sequential,
|
|
184
123
|
contrast
|
|
185
124
|
};
|
|
186
|
-
//# sourceMappingURL=chunk-
|
|
125
|
+
//# sourceMappingURL=chunk-OVASCEGF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/web/context.tsx","../src/core/palette.ts"],"sourcesContent":["\"use client\";\n// One place for what every chart of an app shares: the locale its figures are written in, the brand its palette\n// leads with, and the words it says (translated once, from the app's catalogue). Each chart may still override them.\nimport { createContext, type ReactNode, useContext, useMemo } from \"react\";\n\nimport { type ChartLabels, type ChartLabelsInput, mergeLabels } from \"../core/labels\";\nimport type { BrandId, Locale } from \"../core/types\";\n\nexport interface ChartsSettings {\n /** The locale of every figure and date (`\"fr-FR\"`). Default `\"en-US\"`. */\n locale?: Locale;\n /**\n * The brand whose palette the charts use. Without it, a chart follows a `.brand-<id>` ancestor, else Krizaka. Set it\n * when the app loads a brand stylesheet on `:root` (`@krizaka/tokens/brands/orazaka.css`).\n */\n brand?: BrandId;\n /** The words, translated: the buttons, the states, the written summary. */\n labels?: ChartLabelsInput;\n}\n\ninterface ResolvedSettings {\n readonly locale: Locale;\n readonly brand?: BrandId;\n readonly labels: ChartLabels;\n readonly raw?: ChartLabelsInput;\n}\n\nconst DEFAULTS: ResolvedSettings = { locale: \"en-US\", labels: mergeLabels() };\nconst Context = createContext<ResolvedSettings>(DEFAULTS);\n\nexport interface ChartsProviderProps extends ChartsSettings {\n children: ReactNode;\n}\n\n/** Sets the locale, the brand and the words of every chart below it. */\nexport function ChartsProvider({ locale, brand, labels, children }: ChartsProviderProps) {\n const parent = useContext(Context);\n const value = useMemo<ResolvedSettings>(() => {\n const raw: ChartLabelsInput | undefined = labels ? { ...parent.raw, ...labels, kinds: { ...parent.raw?.kinds, ...labels.kinds } } : parent.raw;\n return { locale: locale ?? parent.locale, brand: brand ?? parent.brand, labels: mergeLabels(raw), raw };\n }, [locale, brand, labels, parent]);\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\n/** The settings of a chart: its own props over the provider's over the defaults. */\nexport function useChartSettings(own: ChartsSettings): { locale: Locale; brand?: BrandId; labels: ChartLabels } {\n const shared = useContext(Context);\n return useMemo(\n () => ({ locale: own.locale ?? shared.locale, brand: own.brand ?? shared.brand, labels: own.labels ? mergeLabels(shared.raw, own.labels) : shared.labels }),\n [own.locale, own.brand, own.labels, shared],\n );\n}\n\n/**\n * What a `ChartCard` hands the chart inside it: the heading (title, insight, description) the card shows once, and the\n * extra controls (a period switch) that sit beside the chart's actions menu. A chart outside a card has none.\n */\nexport interface ChartCardContextValue {\n readonly title?: string;\n readonly insight?: ReactNode;\n readonly description?: ReactNode;\n readonly extra?: ReactNode;\n}\n\nconst CardContext = createContext<ChartCardContextValue | null>(null);\n\nexport const ChartCardProvider = CardContext.Provider;\n\n/** The card the chart is drawn in, or null. */\nexport function useChartCard(): ChartCardContextValue | null {\n return useContext(CardContext);\n}\n","// The data palettes. One categorical set of eight hues, stepped for each theme (the dark steps are chosen for the\n// dark surface, not flipped), ordered per brand so that the first series wears the brand's own hue — Krizaka blue,\n// Orazaka orange, Orochia violet then magenta, its gradient. Every order was chosen among the ones that pass the\n// colour-vision checks (scripts/palette.test: lightness band, chroma floor, adjacent ΔE under protan/deutan ≥ 8 —\n// Orochia light 7.2, inside the 6–8 band that requires the secondary encoding every chart carries: legend, direct\n// labels, data table —, normal-vision ΔE ≥ 15, ≥ 3:1 on the surface, the first three slots distinct all-pairs).\n// A 9th series never gets a generated hue: it folds into “Other” or a second chart.\nimport type { BrandId } from \"./types\";\n\nexport type Mode = \"dark\" | \"light\";\n\n/** The eight hues, light and dark steps. */\nexport const HUES = {\n blue: { light: \"#2a78d6\", dark: \"#3987e5\" },\n orange: { light: \"#eb6834\", dark: \"#d95926\" },\n aqua: { light: \"#1baf7a\", dark: \"#199e70\" },\n yellow: { light: \"#eda100\", dark: \"#c98500\" },\n magenta: { light: \"#e87ba4\", dark: \"#d55181\" },\n green: { light: \"#008300\", dark: \"#008300\" },\n violet: { light: \"#6250d6\", dark: \"#9085e9\" },\n red: { light: \"#e34948\", dark: \"#e66767\" },\n} as const;\n\nexport type Hue = keyof typeof HUES;\n\n/** The order of the hues for each brand: slot 1 is the brand. */\nexport const ORDERS: Record<BrandId, readonly Hue[]> = {\n krizaka: [\"blue\", \"green\", \"magenta\", \"yellow\", \"aqua\", \"orange\", \"violet\", \"red\"],\n orazaka: [\"orange\", \"blue\", \"aqua\", \"yellow\", \"magenta\", \"green\", \"violet\", \"red\"],\n orochia: [\"violet\", \"magenta\", \"yellow\", \"aqua\", \"orange\", \"blue\", \"green\", \"red\"],\n};\n\n/** The categorical palette of a brand in a theme: eight hex colours, slot 1 first. */\nexport function palette(brand: BrandId, mode: Mode): string[] {\n return ORDERS[brand].map((hue) => HUES[hue][mode]);\n}\n\n/** The diverging poles (below / above the midpoint): blue ↔ red, a neutral grey between them. */\nexport const DIVERGING = {\n light: { low: HUES.blue.light, high: HUES.red.light },\n dark: { low: HUES.blue.dark, high: HUES.red.dark },\n} as const;\n\n// --- Colour arithmetic (OKLab), for the sequential ramps the canvas engine needs as plain colours. ---------------\n\ntype Rgb = [number, number, number];\n\n/** `#rrggbb`, `#rgb`, `rgb(r, g, b)` / `rgba(…)` or `rgb(r g b / a)` → [r, g, b] in 0–255; null otherwise. */\nexport function parseColor(color: string): Rgb | null {\n const hex = color.trim().match(/^#([\\da-f]{3}|[\\da-f]{6})$/i);\n if (hex) {\n const h = hex[1]!.length === 3 ? [...hex[1]!].map((c) => c + c).join(\"\") : hex[1]!;\n return [0, 2, 4].map((i) => Number.parseInt(h.slice(i, i + 2), 16)) as Rgb;\n }\n const rgb = color.trim().match(/^rgba?\\(\\s*([\\d.]+)[\\s,]+([\\d.]+)[\\s,]+([\\d.]+)/i);\n if (rgb) return [Number(rgb[1]), Number(rgb[2]), Number(rgb[3])];\n return null;\n}\n\nconst toLinear = (c: number) => {\n const v = c / 255;\n return v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;\n};\nconst fromLinear = (v: number) => {\n const c = v <= 0.0031308 ? v * 12.92 : 1.055 * v ** (1 / 2.4) - 0.055;\n return Math.round(Math.min(1, Math.max(0, c)) * 255);\n};\n\nfunction toOklab([r8, g8, b8]: Rgb): Rgb {\n const [r, g, b] = [toLinear(r8), toLinear(g8), toLinear(b8)];\n const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);\n const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);\n const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);\n return [0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s, 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s, 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s];\n}\n\nfunction fromOklab([L, a, b]: Rgb): Rgb {\n const l = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3;\n const m = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3;\n const s = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;\n return [\n fromLinear(4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s),\n fromLinear(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s),\n fromLinear(-0.0041960863 * l - 0.7034186147 * m + 1.707614031 * s),\n ];\n}\n\nconst hex = ([r, g, b]: Rgb) => `#${[r, g, b].map((c) => c.toString(16).padStart(2, \"0\")).join(\"\")}`;\n\n/** `a` → `b` at `t` (0–1), interpolated in OKLab (even steps to the eye). Unparseable colours return `b`. */\nexport function mix(a: string, b: string, t: number): string {\n const ca = parseColor(a);\n const cb = parseColor(b);\n if (!ca || !cb) return b;\n const la = toOklab(ca);\n const lb = toOklab(cb);\n return hex(fromOklab([0, 1, 2].map((i) => la[i]! + (lb[i]! - la[i]!) * t) as Rgb));\n}\n\n/**\n * A sequential ramp of `steps` colours, one hue from near the surface (`0`, “almost nothing”) to the full hue: the\n * magnitude of a heatmap, a calendar or a choropleth. The first step is still distinct from the surface.\n */\nexport function sequential(hue: string, surface: string, steps = 5): string[] {\n return Array.from({ length: steps }, (_, i) => mix(surface, hue, 0.22 + (0.78 * i) / Math.max(1, steps - 1)));\n}\n\n/** WCAG contrast ratio between two colours (for the tests and the labels drawn inside a mark). */\nexport function contrast(a: string, b: string): number {\n const lum = (c: string) => {\n const rgb = parseColor(c);\n if (!rgb) return 0;\n const [r, g, bl] = rgb.map(toLinear) as Rgb;\n return 0.2126 * r + 0.7152 * g + 0.0722 * bl;\n };\n const [hi, lo] = [lum(a), lum(b)].sort((x, y) => y - x) as [number, number];\n return (hi + 0.05) / (lo + 0.05);\n}\n"],"mappings":"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","names":["hex"]}
|
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
ChartFrame,
|
|
11
11
|
colorOf,
|
|
12
12
|
useSettings
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-P6RS2L23.js";
|
|
14
14
|
import {
|
|
15
15
|
fill
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-GRRFPI27.js";
|
|
17
17
|
|
|
18
18
|
// src/gauge/gauge.tsx
|
|
19
19
|
import { useMemo } from "react";
|
|
@@ -33,7 +33,7 @@ function Gauge(props) {
|
|
|
33
33
|
`${labels.kinds.gauge}: ${text} (${min === 0 ? "" : `${fmt(min)} \u2013 `}${fmt(max)})${zone?.label ? `, ${zone.label}` : ""}.`,
|
|
34
34
|
target ? `${fill(labels.summaryThreshold, { label: target.label, value: fmt(target.value) })}.` : ""
|
|
35
35
|
].filter(Boolean).join(" ");
|
|
36
|
-
const table = { columns: [labels.category, labels.value], rows: [[props.title, text], ["min", fmt(min)], ["max", fmt(max)], ...target ? [[target.label, fmt(target.value)]] : []] };
|
|
36
|
+
const table = { columns: [labels.category, labels.value], rows: [[props.title ?? "", text], ["min", fmt(min)], ["max", fmt(max)], ...target ? [[target.label, fmt(target.value)]] : []] };
|
|
37
37
|
const at = (v) => START + (Math.min(max, Math.max(min, v)) - min) / (max - min || 1) * (END - START);
|
|
38
38
|
return /* @__PURE__ */ jsx(ChartFrame, { kind: "gauge", frame: { ...props, dataTable: false }, defaultHeight: 180, table, summary, isEmpty: false, navigable: false, children: (width, height) => {
|
|
39
39
|
const radius = Math.max(20, Math.min(width / 2 - 12, (height - 30) / 1.58));
|
|
@@ -70,4 +70,4 @@ function Gauge(props) {
|
|
|
70
70
|
export {
|
|
71
71
|
Gauge
|
|
72
72
|
};
|
|
73
|
-
//# sourceMappingURL=chunk-
|
|
73
|
+
//# sourceMappingURL=chunk-OZOAKP5F.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/gauge/gauge.tsx"],"sourcesContent":["\"use client\";\n// One value against its range: a 240° arc, the value written in the middle, an optional target tick and coloured\n// zones (a quota that turns to warning, then danger). Plain SVG; exposed as a `meter` (value, range and its words).\nimport { useMemo } from \"react\";\n\nimport { valueFormatter } from \"../core/format\";\nimport { fill } from \"../core/labels\";\nimport { polar, strokeArcPath } from \"../core/shape\";\nimport type { Threshold, Tone, ValueFormat } from \"../core/types\";\nimport { ChartFrame, type ChartFrameProps, useSettings } from \"../web/frame\";\nimport { colorOf } from \"../web/parts\";\n\nexport interface GaugeZone {\n /** The zone runs from the previous one's end (or `min`) to this value. */\n readonly to: number;\n readonly tone: Tone;\n /** Its name, in the summary and the table (“Over quota”). */\n readonly label?: string;\n}\n\nexport interface GaugeProps extends Omit<ChartFrameProps, \"dataTable\" | \"exportable\"> {\n /** The value. */\n/** The value. */\n value: number;\n /** The start of the range. Default 0. */\n/** The start of the range. Default 0. */\n min?: number;\n /** The end of the range. Default 100. */\n/** The end of the range. Default 100. */\n max?: number;\n /** How the value is written. */\n/** How the value and the range are written. */\n format?: ValueFormat;\n /** The words under the value (“of 50 000 credits”). */\n caption?: string;\n /** A tick on the arc: the objective. */\n target?: Threshold;\n /** Coloured zones along the arc: the value takes the tone of the zone it is in. */\n zones?: readonly GaugeZone[];\n /** The tone of the value without zones. Default `\"accent\"`. */\n/** The tone of the value without zones. Default `\"accent\"`. */\n tone?: Tone;\n}\n\nconst START = (-120 * Math.PI) / 180;\nconst END = (120 * Math.PI) / 180;\n\n/** One figure against its range — credits used of a plan, a challenge's progress, a load. */\nexport function Gauge(props: GaugeProps) {\n const { value, min = 0, max = 100, format, caption, target, zones = [], tone = \"accent\" } = props;\n const { locale, labels } = useSettings(props);\n const fmt = useMemo(() => valueFormatter(format, locale, labels.noValue), [format, locale, labels.noValue]);\n const clamped = Math.min(max, Math.max(min, value));\n const ratio = max > min ? (clamped - min) / (max - min) : 0;\n const zone = zones.find((z) => clamped <= z.to) ?? zones[zones.length - 1];\n const color = colorOf(zone?.tone ?? tone, 1);\n const text = fmt(value);\n const summary = [\n `${labels.kinds.gauge}: ${text} (${min === 0 ? \"\" : `${fmt(min)} – `}${fmt(max)})${zone?.label ? `, ${zone.label}` : \"\"}.`,\n target ? `${fill(labels.summaryThreshold, { label: target.label, value: fmt(target.value) })}.` : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n const table = { columns: [labels.category, labels.value], rows: [[props.title ?? \"\", text], [\"min\", fmt(min)], [\"max\", fmt(max)], ...(target ? [[target.label, fmt(target.value)]] : [])] };\n const at = (v: number) => START + ((Math.min(max, Math.max(min, v)) - min) / (max - min || 1)) * (END - START);\n\n return (\n <ChartFrame kind=\"gauge\" frame={{ ...props, dataTable: false }} defaultHeight={180} table={table} summary={summary} isEmpty={false} navigable={false}>\n {(width, height) => {\n // The arc spans 240°: its lowest points sit at half the radius below the centre, the range labels under them.\n const radius = Math.max(20, Math.min(width / 2 - 12, (height - 30) / 1.58));\n const cx = width / 2;\n const cy = 8 + radius;\n const stroke = Math.max(8, radius * 0.16);\n let from = min;\n return (\n <div role=\"meter\" aria-label={props.title} aria-valuemin={min} aria-valuemax={max} aria-valuenow={clamped} aria-valuetext={caption ? `${text} ${caption}` : text} style={{ height: \"100%\" }}>\n <svg className=\"kzc-svg\" width={width} height={height} viewBox={`0 0 ${width} ${height}`} aria-hidden>\n <path d={strokeArcPath(cx, cy, radius, START, END)} style={{ fill: \"none\", stroke: \"var(--kz-surface-3)\", strokeWidth: stroke, strokeLinecap: \"round\" }} />\n {zones.map((z, i) => {\n const d = strokeArcPath(cx, cy, radius + stroke / 2 + 4, at(from), at(z.to));\n from = z.to;\n return <path key={i} d={d} data-tone={z.tone} style={{ fill: \"none\", stroke: \"var(--kzc-tone)\", strokeWidth: 3, opacity: 0.7 }} />;\n })}\n {ratio > 0 && (\n <path d={strokeArcPath(cx, cy, radius, START, at(clamped))} pathLength={1} className=\"kzc-line kzc-enter-line\" style={{ stroke: color, strokeWidth: stroke }} />\n )}\n {target && (\n <g data-tone={target.tone ?? \"neutral\"}>\n <line\n x1={polar(cx, cy, radius - stroke, at(target.value))[0]}\n y1={polar(cx, cy, radius - stroke, at(target.value))[1]}\n x2={polar(cx, cy, radius + stroke, at(target.value))[0]}\n y2={polar(cx, cy, radius + stroke, at(target.value))[1]}\n style={{ stroke: \"var(--kzc-text)\", strokeWidth: 2, strokeLinecap: \"round\" }}\n />\n </g>\n )}\n <text x={cx} y={cy} textAnchor=\"middle\" dominantBaseline=\"central\" className=\"kzc-strong\" style={{ fontSize: Math.max(12, Math.min(32, radius / 2.6, (radius * 1.45) / (text.length * 0.58))) }}>\n {text}\n </text>\n {caption && (\n <text x={cx} y={cy + Math.max(16, radius / 3.2)} textAnchor=\"middle\" dominantBaseline=\"central\">\n {caption}\n </text>\n )}\n <text x={polar(cx, cy, radius, START)[0]} y={polar(cx, cy, radius, START)[1] + stroke + 6} textAnchor=\"middle\">\n {fmt(min)}\n </text>\n <text x={polar(cx, cy, radius, END)[0]} y={polar(cx, cy, radius, END)[1] + stroke + 6} textAnchor=\"middle\">\n {fmt(max)}\n </text>\n </svg>\n </div>\n );\n }}\n </ChartFrame>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
LineChart
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-Z4T3JFNU.js";
|
|
5
5
|
import {
|
|
6
6
|
Kpi,
|
|
7
7
|
toneOf
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
} from "./chunk-XLLYNNC6.js";
|
|
18
18
|
import {
|
|
19
19
|
useSettings
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-P6RS2L23.js";
|
|
21
21
|
|
|
22
22
|
// src/needs/ticker.ts
|
|
23
23
|
function tickerModel(bids, opening, openedAt) {
|
|
@@ -75,4 +75,4 @@ function PriceTicker({ bids, opening, openedAt, currency, reserve, timeFormat =
|
|
|
75
75
|
export {
|
|
76
76
|
PriceTicker
|
|
77
77
|
};
|
|
78
|
-
//# sourceMappingURL=chunk-
|
|
78
|
+
//# sourceMappingURL=chunk-P2NK5L3B.js.map
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
import {
|
|
3
3
|
HUES,
|
|
4
4
|
ORDERS,
|
|
5
|
-
|
|
5
|
+
useChartCard,
|
|
6
6
|
useChartSettings
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-OVASCEGF.js";
|
|
8
|
+
import {
|
|
9
|
+
fill
|
|
10
|
+
} from "./chunk-GRRFPI27.js";
|
|
8
11
|
|
|
9
12
|
// src/web/hooks.ts
|
|
10
13
|
import { useEffect, useState, useSyncExternalStore } from "react";
|
|
@@ -89,14 +92,16 @@ function useMounted() {
|
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
// src/web/parts.tsx
|
|
92
|
-
import {
|
|
95
|
+
import { useCallback, useState as useState2 } from "react";
|
|
96
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
93
97
|
var cx = (...names) => names.filter(Boolean).join(" ");
|
|
94
98
|
var TONES = {
|
|
95
99
|
neutral: "var(--kz-text-secondary)",
|
|
96
100
|
accent: "var(--kz-accent)",
|
|
97
101
|
success: "var(--kz-success)",
|
|
98
102
|
warning: "var(--kz-warning)",
|
|
99
|
-
|
|
103
|
+
// A failure is stated, not shouted: the danger hue eased toward the muted text so a block of it stays calm.
|
|
104
|
+
danger: "color-mix(in oklab, var(--kz-danger) 78%, var(--kz-text-muted))",
|
|
100
105
|
info: "var(--kz-info)"
|
|
101
106
|
};
|
|
102
107
|
function colorOf(color, slot) {
|
|
@@ -105,19 +110,54 @@ function colorOf(color, slot) {
|
|
|
105
110
|
if (color in TONES) return TONES[color];
|
|
106
111
|
return color;
|
|
107
112
|
}
|
|
108
|
-
function Legend({ items }) {
|
|
109
|
-
if (items.length < 2) return null;
|
|
110
|
-
|
|
111
|
-
|
|
113
|
+
function Legend({ items, off, onToggle, toggleName, always }) {
|
|
114
|
+
if (items.length < 2 && !always) return null;
|
|
115
|
+
const live = items.filter((item) => !off?.has(item.label)).length;
|
|
116
|
+
return /* @__PURE__ */ jsx("ul", { className: "kzc-legend", "aria-hidden": onToggle ? void 0 : true, children: items.map((item) => {
|
|
117
|
+
const isOff = off?.has(item.label) ?? false;
|
|
118
|
+
const key = /* @__PURE__ */ jsx(
|
|
112
119
|
"span",
|
|
113
120
|
{
|
|
114
121
|
className: "kzc-key",
|
|
115
122
|
"data-shape": item.shape,
|
|
116
123
|
style: { background: item.dashed ? `repeating-linear-gradient(90deg, ${item.color} 0 4px, transparent 4px 7px)` : item.color }
|
|
117
124
|
}
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
|
|
125
|
+
);
|
|
126
|
+
const text = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
127
|
+
item.label,
|
|
128
|
+
item.detail && /* @__PURE__ */ jsx("span", { className: "kzc-legend-detail", children: item.detail })
|
|
129
|
+
] });
|
|
130
|
+
return /* @__PURE__ */ jsx("li", { children: onToggle ? /* @__PURE__ */ jsxs(
|
|
131
|
+
"button",
|
|
132
|
+
{
|
|
133
|
+
type: "button",
|
|
134
|
+
className: "kzc-chip",
|
|
135
|
+
"aria-pressed": !isOff,
|
|
136
|
+
title: toggleName?.(item.label),
|
|
137
|
+
disabled: !isOff && live <= 1,
|
|
138
|
+
onClick: () => onToggle(item.label),
|
|
139
|
+
children: [
|
|
140
|
+
key,
|
|
141
|
+
text
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
145
|
+
key,
|
|
146
|
+
text
|
|
147
|
+
] }) }, item.label);
|
|
148
|
+
}) });
|
|
149
|
+
}
|
|
150
|
+
function useToggles() {
|
|
151
|
+
const [off, setOff] = useState2(() => /* @__PURE__ */ new Set());
|
|
152
|
+
const toggle = useCallback((label) => {
|
|
153
|
+
setOff((current) => {
|
|
154
|
+
const next = new Set(current);
|
|
155
|
+
if (next.has(label)) next.delete(label);
|
|
156
|
+
else next.add(label);
|
|
157
|
+
return next;
|
|
158
|
+
});
|
|
159
|
+
}, []);
|
|
160
|
+
return { off, toggle };
|
|
121
161
|
}
|
|
122
162
|
function Tooltip({ x, y, width, title, rows, note }) {
|
|
123
163
|
const flip = x > width / 2;
|
|
@@ -152,11 +192,19 @@ var tone = (name, value) => `.kzc [data-tone=${name}]{--kzc-tone:${value}}`;
|
|
|
152
192
|
var CSS = `${PALETTE}
|
|
153
193
|
.kzc{--kzc-text:var(--kz-text-primary);--kzc-text-2:var(--kz-text-secondary);--kzc-text-3:var(--kz-text-muted);--kzc-grid:var(--kz-border-subtle);--kzc-axis:var(--kz-border-default);--kzc-surface:var(--kz-surface-1);--kzc-tone:var(--kz-text-secondary);margin:0;min-width:0;display:flex;flex-direction:column;gap:8px;color:var(--kzc-text);font-family:var(--kz-font-sans,system-ui,sans-serif);font-variant-numeric:tabular-nums}
|
|
154
194
|
${tone("neutral", "var(--kz-text-secondary)")}${tone("accent", "var(--kz-accent)")}${tone("success", "var(--kz-success)")}${tone("warning", "var(--kz-warning)")}${tone("danger", "var(--kz-danger)")}${tone("info", "var(--kz-info)")}
|
|
155
|
-
.kzc-head{display:flex;
|
|
156
|
-
.kzc-heading{display:flex;flex-direction:column;gap:2px;min-width:0}
|
|
195
|
+
.kzc-head{display:flex;align-items:flex-start;justify-content:space-between;gap:4px 12px}
|
|
196
|
+
.kzc-heading{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto}
|
|
157
197
|
.kzc-title{margin:0;font-family:var(--kz-font-display,inherit);font-size:14px;font-weight:600;line-height:20px;color:var(--kzc-text)}
|
|
198
|
+
.kzc-heading[data-insight] .kzc-title{font-family:var(--kz-font-sans,inherit);font-size:12px;line-height:16px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--kzc-text-2)}
|
|
199
|
+
.kzc-insight{margin:2px 0 0;font-family:var(--kz-font-display,inherit);font-size:20px;line-height:26px;font-weight:700;letter-spacing:-.01em;color:var(--kzc-text);font-variant-numeric:tabular-nums}
|
|
200
|
+
.kzc-note{margin:0;font-size:12px;line-height:18px;color:var(--kzc-text-2)}
|
|
158
201
|
.kzc-desc{margin:0;font-size:13px;line-height:18px;color:var(--kzc-text-2)}
|
|
159
|
-
.kzc-tools{display:flex;flex-wrap:wrap;gap:4px}
|
|
202
|
+
.kzc-tools{display:flex;flex-wrap:wrap;flex:none;align-items:center;justify-content:flex-end;gap:4px;max-width:100%}
|
|
203
|
+
.kzc-more{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;margin:-4px -4px 0 0;padding:0;border:0;border-radius:var(--kz-radius-md,8px);background:transparent;color:var(--kzc-text-2);cursor:pointer;transition:background-color .15s,color .15s}
|
|
204
|
+
.kzc-more:hover:not(:disabled){background:var(--kz-surface-2);color:var(--kzc-text)}
|
|
205
|
+
.kzc-more:disabled{cursor:default;opacity:.7}
|
|
206
|
+
.kzc-more:focus-visible{outline:2px solid var(--kz-ring);outline-offset:2px}
|
|
207
|
+
.kzc-more svg{width:18px;height:18px}
|
|
160
208
|
.kzc-btn{appearance:none;display:inline-flex;align-items:center;gap:4px;height:28px;padding:0 10px;border:1px solid var(--kz-border-default);border-radius:var(--kz-radius-md,8px);background:transparent;color:var(--kzc-text-2);font:inherit;font-size:12px;font-weight:500;cursor:pointer;transition:background-color .15s,color .15s}
|
|
161
209
|
.kzc-btn:hover{background:var(--kz-surface-2);color:var(--kzc-text)}
|
|
162
210
|
.kzc-btn:focus-visible,.kzc-plot:focus-visible{outline:2px solid var(--kz-ring);outline-offset:2px}
|
|
@@ -177,9 +225,16 @@ ${tone("neutral", "var(--kz-text-secondary)")}${tone("accent", "var(--kz-accent)
|
|
|
177
225
|
.kzc[data-active] .kzc-mark[data-dim]{opacity:.35}
|
|
178
226
|
.kzc-legend{display:flex;flex-wrap:wrap;gap:4px 14px;margin:0;padding:0;list-style:none;font-size:12px;color:var(--kzc-text-2)}
|
|
179
227
|
.kzc-legend li{display:inline-flex;align-items:center;gap:6px}
|
|
228
|
+
.kzc-legend-detail{margin-left:2px;color:var(--kzc-text-2)}
|
|
229
|
+
.kzc-chip{appearance:none;display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 10px;border:1px solid var(--kz-border-default);border-radius:999px;background:transparent;color:var(--kzc-text);font:inherit;font-size:12px;cursor:pointer;transition:background-color .15s,color .15s,border-color .15s,opacity .15s}
|
|
230
|
+
.kzc-chip:hover:not(:disabled){background:var(--kz-surface-2)}
|
|
231
|
+
.kzc-chip[aria-pressed=false]{color:var(--kzc-text-2);border-style:dashed}
|
|
232
|
+
.kzc-chip[aria-pressed=false] .kzc-key{opacity:.35}
|
|
233
|
+
.kzc-chip:disabled{cursor:default}
|
|
234
|
+
.kzc-chip:focus-visible{outline:2px solid var(--kz-ring);outline-offset:2px}
|
|
180
235
|
.kzc-key{width:10px;height:10px;border-radius:3px;flex:none}
|
|
181
236
|
.kzc-key[data-shape=line]{height:3px;border-radius:2px;width:14px}
|
|
182
|
-
.kzc-tip{position:absolute;z-index:2;pointer-events:none;min-width:140px;max-width:260px;padding:8px 10px;border:1px solid var(--kz-border-default);border-radius:var(--kz-radius-lg,10px);background:var(--kz-surface-2);color:var(--kzc-text);box-shadow:var(--kz-shadow-lg);font-size:12px;line-height:18px}
|
|
237
|
+
.kzc-tip{animation:none;position:absolute;z-index:2;pointer-events:none;min-width:140px;max-width:260px;padding:8px 10px;border:1px solid var(--kz-border-default);border-radius:var(--kz-radius-lg,10px);background:var(--kz-surface-2);color:var(--kzc-text);box-shadow:var(--kz-shadow-lg);font-size:12px;line-height:18px}
|
|
183
238
|
.kzc-tip-title{margin:0 0 4px;font-weight:600;color:var(--kzc-text)}
|
|
184
239
|
.kzc-tip-row{display:flex;align-items:center;gap:8px;margin:0}
|
|
185
240
|
.kzc-tip-row span:nth-child(2){flex:1;color:var(--kzc-text-2)}
|
|
@@ -193,7 +248,8 @@ ${tone("neutral", "var(--kz-text-secondary)")}${tone("accent", "var(--kz-accent)
|
|
|
193
248
|
.kzc-table th,.kzc-table td{padding:6px 10px;border-top:1px solid var(--kz-border-subtle);text-align:right;white-space:nowrap}
|
|
194
249
|
.kzc-table th[scope=row],.kzc-table thead th:first-child{text-align:left;font-weight:500;color:var(--kzc-text)}
|
|
195
250
|
.kzc-table thead th{position:sticky;top:0;background:var(--kz-surface-1);color:var(--kzc-text-2);font-weight:500}
|
|
196
|
-
.kzc-state{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:
|
|
251
|
+
.kzc-state{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:16px;text-align:center;font-size:13px;line-height:18px;color:var(--kzc-text-2);background:color-mix(in oklab,var(--kz-surface-2) 55%,transparent);border-radius:var(--kz-radius-lg,10px)}
|
|
252
|
+
.kzc-state svg{width:28px;height:28px;color:var(--kzc-text-3)}
|
|
197
253
|
.kzc-state[data-state=error]{color:var(--kz-danger-text,var(--kzc-text))}
|
|
198
254
|
.kzc-skeleton{position:absolute;inset:0;display:flex;align-items:flex-end;gap:6%;padding:12px 4% 24px;border-radius:var(--kz-radius-lg,10px);overflow:hidden}
|
|
199
255
|
.kzc-skeleton i{flex:1;border-radius:4px 4px 0 0;background:var(--kz-surface-2)}
|
|
@@ -205,6 +261,11 @@ ${tone("neutral", "var(--kz-text-secondary)")}${tone("accent", "var(--kz-accent)
|
|
|
205
261
|
.kzc-kpi-label{font-size:13px;color:var(--kzc-text-2)}
|
|
206
262
|
.kzc-kpi-delta{display:inline-flex;align-items:center;gap:4px;font-size:13px;font-weight:600;color:var(--kzc-text)}
|
|
207
263
|
.kzc-kpi-delta svg{width:12px;height:12px;flex:none;color:var(--kzc-tone)}
|
|
264
|
+
.kzc-kpistat{min-width:0}
|
|
265
|
+
.kzc-kpistat[data-good=down] [data-trend=up] svg{color:var(--kz-danger)}
|
|
266
|
+
.kzc-kpistat[data-good=down] [data-trend=down] svg{color:var(--kz-success)}
|
|
267
|
+
.kzc-card{min-width:0}
|
|
268
|
+
.kzc-card-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:4px 12px;margin:12px 0 0;padding-top:10px;border-top:1px solid var(--kz-border-subtle);font-size:12px;line-height:18px;color:var(--kzc-text-3)}
|
|
208
269
|
.kzc-meter{position:relative;height:10px;border-radius:999px;background:var(--kz-surface-3);overflow:hidden;--kzc-tone:var(--kz-accent)}
|
|
209
270
|
.kzc-meter>i{position:absolute;inset:0 auto 0 0;border-radius:inherit;background:var(--kzc-tone);transition:width .6s var(--kz-ease,ease-out)}
|
|
210
271
|
.kzc-meter[data-tone=warning]{--kzc-tone:var(--kz-warning)}.kzc-meter[data-tone=danger]{--kzc-tone:var(--kz-danger)}
|
|
@@ -214,9 +275,9 @@ ${tone("neutral", "var(--kz-text-secondary)")}${tone("accent", "var(--kz-accent)
|
|
|
214
275
|
.kzc-skeleton i{animation:kzc-pulse 1.6s ease-in-out infinite}
|
|
215
276
|
.kzc[data-inview] .kzc-enter-line{stroke-dasharray:1;stroke-dashoffset:1;animation:kzc-draw .9s var(--kz-ease,ease-out) forwards}
|
|
216
277
|
.kzc[data-inview] .kzc-enter-fade{opacity:0;animation:kzc-fade .6s .3s var(--kz-ease,ease-out) forwards}
|
|
217
|
-
.kzc[data-inview] .kzc-enter-grow{transform:scaleY(0);transform-box:fill-box;transform-origin:bottom;animation:kzc-grow .6s var(--kz-ease,ease-out) forwards}
|
|
278
|
+
.kzc[data-inview] .kzc-enter-grow{transform:scaleY(0);transform-box:fill-box;transform-origin:bottom;animation:kzc-grow .6s calc(min(var(--kzc-i,0),24)*22ms) var(--kz-ease,ease-out) forwards}
|
|
218
279
|
.kzc[data-inview] .kzc-enter-grow[data-negative]{transform-origin:top}
|
|
219
|
-
.kzc[data-inview] .kzc-enter-growx{transform:scaleX(0);transform-box:fill-box;transform-origin:left;animation:kzc-growx .6s var(--kz-ease,ease-out) forwards}
|
|
280
|
+
.kzc[data-inview] .kzc-enter-growx{transform:scaleX(0);transform-box:fill-box;transform-origin:left;animation:kzc-growx .6s calc(min(var(--kzc-i,0),24)*22ms) var(--kz-ease,ease-out) forwards}
|
|
220
281
|
.kzc[data-inview] .kzc-enter-growx[data-negative]{transform-origin:right}
|
|
221
282
|
.kzc[data-inview] .kzc-enter-pop{opacity:0;transform:scale(.92);transform-box:view-box;transform-origin:center;animation:kzc-pop .6s var(--kz-ease,ease-out) forwards}
|
|
222
283
|
.kzc:not([data-inview]) .kzc-enter-line,.kzc:not([data-inview]) .kzc-enter-fade,.kzc:not([data-inview]) .kzc-enter-grow,.kzc:not([data-inview]) .kzc-enter-growx,.kzc:not([data-inview]) .kzc-enter-pop{visibility:hidden}
|
|
@@ -237,7 +298,7 @@ function ChartStyles() {
|
|
|
237
298
|
}
|
|
238
299
|
|
|
239
300
|
// src/web/frame.tsx
|
|
240
|
-
import { useCallback, useId, useMemo, useRef, useState as
|
|
301
|
+
import { lazy, Suspense, useCallback as useCallback2, useId, useMemo, useRef, useState as useState3 } from "react";
|
|
241
302
|
|
|
242
303
|
// src/web/export.ts
|
|
243
304
|
function toCsv(rows) {
|
|
@@ -297,6 +358,7 @@ function svgToPng(markup, width, height, background, scale = 2) {
|
|
|
297
358
|
|
|
298
359
|
// src/web/frame.tsx
|
|
299
360
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
361
|
+
var ChartActions = lazy(() => import("./actions-5VG352VZ.js"));
|
|
300
362
|
function useSettings(frame) {
|
|
301
363
|
return useChartSettings(frame);
|
|
302
364
|
}
|
|
@@ -309,6 +371,7 @@ function ChartFrame({
|
|
|
309
371
|
isEmpty,
|
|
310
372
|
children,
|
|
311
373
|
legend,
|
|
374
|
+
note,
|
|
312
375
|
tooltip,
|
|
313
376
|
announcement,
|
|
314
377
|
handlers,
|
|
@@ -320,8 +383,12 @@ function ChartFrame({
|
|
|
320
383
|
compact,
|
|
321
384
|
pending
|
|
322
385
|
}) {
|
|
323
|
-
const
|
|
386
|
+
const card = useChartCard();
|
|
387
|
+
const { hideTitle, height = defaultHeight, loading, error, empty, summaryText, dataTable = true, exportable, actionsMenu = true, live, id, className, style } = frame;
|
|
324
388
|
const { brand, labels } = useChartSettings(frame);
|
|
389
|
+
const title = frame.title ?? card?.title ?? labels.kinds[kind];
|
|
390
|
+
const insight = frame.insight ?? card?.insight;
|
|
391
|
+
const description = frame.description ?? card?.description;
|
|
325
392
|
const uid = useId();
|
|
326
393
|
const ids = { title: `${uid}-t`, summary: `${uid}-s`, hint: `${uid}-h`, table: `${uid}-d` };
|
|
327
394
|
const ownRef = useRef(null);
|
|
@@ -331,10 +398,15 @@ function ChartFrame({
|
|
|
331
398
|
const measured = useWidth(ref);
|
|
332
399
|
const width = mounted ? measured : 0;
|
|
333
400
|
const inView = useInView(figureRef, { once: true });
|
|
334
|
-
const [showTable, setShowTable] =
|
|
335
|
-
const
|
|
401
|
+
const [showTable, setShowTable] = useState3(false);
|
|
402
|
+
const [copied, setCopied] = useState3(false);
|
|
403
|
+
const formats = useMemo(() => {
|
|
404
|
+
const all = actionsMenu ? ["csv", "png", "svg"] : ["png", "svg", "csv"];
|
|
405
|
+
if (exportable === void 0) return actionsMenu ? all : [];
|
|
406
|
+
return exportable === true ? all : exportable || [];
|
|
407
|
+
}, [exportable, actionsMenu]);
|
|
336
408
|
const state = error ? "error" : loading ? "loading" : isEmpty ? "empty" : "ready";
|
|
337
|
-
const doExport =
|
|
409
|
+
const doExport = useCallback2(
|
|
338
410
|
async (format) => {
|
|
339
411
|
if (format === "csv") {
|
|
340
412
|
download(fileName(title, "csv"), new Blob([`\uFEFF${toCsv([table.columns, ...table.rows])}`], { type: "text/csv;charset=utf-8" }));
|
|
@@ -358,6 +430,16 @@ function ChartFrame({
|
|
|
358
430
|
},
|
|
359
431
|
[exportImage, ref, table, title]
|
|
360
432
|
);
|
|
433
|
+
const doCopy = useCallback2(async () => {
|
|
434
|
+
const text = [table.columns, ...table.rows].map((row) => row.join(" ")).join("\n");
|
|
435
|
+
try {
|
|
436
|
+
await navigator.clipboard.writeText(text);
|
|
437
|
+
setCopied(true);
|
|
438
|
+
setTimeout(() => setCopied(false), 2500);
|
|
439
|
+
} catch {
|
|
440
|
+
setCopied(false);
|
|
441
|
+
}
|
|
442
|
+
}, [table]);
|
|
361
443
|
const drawWidth = width || ssrWidth || 0;
|
|
362
444
|
let plot;
|
|
363
445
|
if (state === "loading") {
|
|
@@ -368,7 +450,10 @@ function ChartFrame({
|
|
|
368
450
|
} else if (state === "error") {
|
|
369
451
|
plot = /* @__PURE__ */ jsx3("div", { className: "kzc-state", "data-state": "error", role: "alert", children: error === true ? labels.error : error });
|
|
370
452
|
} else if (state === "empty") {
|
|
371
|
-
plot = empty ?? /* @__PURE__ */
|
|
453
|
+
plot = empty ?? /* @__PURE__ */ jsxs2("div", { className: "kzc-state", "data-state": "empty", role: "status", children: [
|
|
454
|
+
/* @__PURE__ */ jsx3("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx3("path", { d: "M4 20V10M10 20V4M16 20v-7M22 20H2" }) }),
|
|
455
|
+
labels.empty
|
|
456
|
+
] });
|
|
372
457
|
} else if (drawWidth > 0) {
|
|
373
458
|
plot = children(drawWidth, height);
|
|
374
459
|
} else {
|
|
@@ -393,16 +478,26 @@ function ChartFrame({
|
|
|
393
478
|
"aria-labelledby": ids.title,
|
|
394
479
|
children: [
|
|
395
480
|
/* @__PURE__ */ jsx3(ChartStyles, {}),
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
481
|
+
(() => {
|
|
482
|
+
const tools = !compact && state !== "loading" && state !== "error";
|
|
483
|
+
const menu = actionsMenu && tools && !isEmpty && (dataTable || formats.length > 0);
|
|
484
|
+
const legacy = !actionsMenu && tools && (dataTable || formats.length > 0);
|
|
485
|
+
const visible = !hideTitle || description || insight || menu || legacy || card?.extra;
|
|
486
|
+
return /* @__PURE__ */ jsxs2("div", { className: visible ? "kzc-head" : "kzc-sr", children: [
|
|
487
|
+
/* @__PURE__ */ jsxs2("div", { className: "kzc-heading", "data-insight": insight ? "" : void 0, children: [
|
|
488
|
+
/* @__PURE__ */ jsx3("p", { id: ids.title, className: hideTitle ? "kzc-sr" : "kzc-title", children: title }),
|
|
489
|
+
insight && /* @__PURE__ */ jsx3("p", { className: "kzc-insight", children: insight }),
|
|
490
|
+
description && /* @__PURE__ */ jsx3("p", { className: "kzc-desc", children: description })
|
|
491
|
+
] }),
|
|
492
|
+
(menu || legacy || card?.extra) && /* @__PURE__ */ jsxs2("div", { className: "kzc-tools", children: [
|
|
493
|
+
card?.extra,
|
|
494
|
+
menu && mounted && /* @__PURE__ */ jsx3(Suspense, { fallback: /* @__PURE__ */ jsx3(MoreButton, { label: labels.actions }), children: /* @__PURE__ */ jsx3(ChartActions, { title, table, labels, formats, viewTable: dataTable, onExport: (format) => void doExport(format), onCopy: () => void doCopy() }) }),
|
|
495
|
+
menu && !mounted && /* @__PURE__ */ jsx3(MoreButton, { label: labels.actions }),
|
|
496
|
+
legacy && !isEmpty && dataTable && /* @__PURE__ */ jsx3("button", { type: "button", className: "kzc-btn", "aria-expanded": showTable, "aria-controls": ids.table, onClick: () => setShowTable((v) => !v), children: showTable ? labels.hideData : labels.showData }),
|
|
497
|
+
legacy && !isEmpty && formats.map((format) => /* @__PURE__ */ jsx3("button", { type: "button", className: "kzc-btn", onClick: () => void doExport(format), "aria-label": `${title} \u2014 ${format.toUpperCase()}`, children: format === "png" ? labels.exportPng : format === "svg" ? labels.exportSvg : labels.exportCsv }, format))
|
|
498
|
+
] })
|
|
499
|
+
] });
|
|
500
|
+
})(),
|
|
406
501
|
legend,
|
|
407
502
|
/* @__PURE__ */ jsxs2(
|
|
408
503
|
"div",
|
|
@@ -424,9 +519,10 @@ function ChartFrame({
|
|
|
424
519
|
]
|
|
425
520
|
}
|
|
426
521
|
),
|
|
522
|
+
ready && note && /* @__PURE__ */ jsx3("p", { className: "kzc-note", children: note }),
|
|
427
523
|
/* @__PURE__ */ jsx3("p", { id: ids.summary, className: frame.summary === "visible" ? "kzc-summary" : "kzc-sr", children: summaryText ?? summary }),
|
|
428
524
|
ready && navigable && /* @__PURE__ */ jsx3("span", { id: ids.hint, className: "kzc-sr", children: labels.keyboardHint }),
|
|
429
|
-
/* @__PURE__ */ jsx3("div", { className: "kzc-live", "aria-live": "polite", "aria-atomic": "true", children: live ? "" : announcement }),
|
|
525
|
+
/* @__PURE__ */ jsx3("div", { className: "kzc-live", "aria-live": "polite", "aria-atomic": "true", children: copied ? labels.copied : live ? "" : announcement }),
|
|
430
526
|
!isEmpty && /* @__PURE__ */ jsx3("div", { id: ids.table, className: showTable ? "kzc-table-wrap" : "kzc-sr", children: /* @__PURE__ */ jsxs2("table", { className: "kzc-table", children: [
|
|
431
527
|
/* @__PURE__ */ jsx3("caption", { children: fill(labels.tableCaption, { title }) }),
|
|
432
528
|
/* @__PURE__ */ jsx3("thead", { children: /* @__PURE__ */ jsx3("tr", { children: table.columns.map((column, i) => /* @__PURE__ */ jsx3("th", { scope: "col", children: column }, i)) }) }),
|
|
@@ -438,6 +534,13 @@ function ChartFrame({
|
|
|
438
534
|
}
|
|
439
535
|
);
|
|
440
536
|
}
|
|
537
|
+
function MoreButton({ label }) {
|
|
538
|
+
return /* @__PURE__ */ jsx3("button", { type: "button", className: "kzc-more", "aria-label": label, disabled: true, children: /* @__PURE__ */ jsxs2("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, width: "16", height: "16", children: [
|
|
539
|
+
/* @__PURE__ */ jsx3("circle", { cx: "5", cy: "12", r: "1.8" }),
|
|
540
|
+
/* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "1.8" }),
|
|
541
|
+
/* @__PURE__ */ jsx3("circle", { cx: "19", cy: "12", r: "1.8" })
|
|
542
|
+
] }) });
|
|
543
|
+
}
|
|
441
544
|
function resolveColor(color, scope) {
|
|
442
545
|
if (typeof document === "undefined") return color;
|
|
443
546
|
const probe = document.createElement("span");
|
|
@@ -457,6 +560,7 @@ export {
|
|
|
457
560
|
cx,
|
|
458
561
|
colorOf,
|
|
459
562
|
Legend,
|
|
563
|
+
useToggles,
|
|
460
564
|
Tooltip,
|
|
461
565
|
stepColor,
|
|
462
566
|
RampLegend,
|
|
@@ -465,4 +569,4 @@ export {
|
|
|
465
569
|
ChartFrame,
|
|
466
570
|
resolveColor
|
|
467
571
|
};
|
|
468
|
-
//# sourceMappingURL=chunk-
|
|
572
|
+
//# sourceMappingURL=chunk-P6RS2L23.js.map
|