@hjmds/design-contracts 1.20.0 → 1.21.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/dist/authoring-tools.d.ts +38 -0
- package/dist/authoring-tools.d.ts.map +1 -0
- package/dist/authoring-tools.js +35 -0
- package/dist/authoring-tools.js.map +1 -0
- package/dist/behaviors.d.ts +33 -3
- package/dist/behaviors.d.ts.map +1 -1
- package/dist/behaviors.js +2 -0
- package/dist/behaviors.js.map +1 -1
- package/dist/calendar.d.ts +9 -1
- package/dist/calendar.d.ts.map +1 -1
- package/dist/calendar.js +4 -2
- package/dist/calendar.js.map +1 -1
- package/dist/catalog.d.ts +129 -2
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +6 -2
- package/dist/catalog.js.map +1 -1
- package/dist/chart.d.ts +398 -0
- package/dist/chart.d.ts.map +1 -0
- package/dist/chart.js +414 -0
- package/dist/chart.js.map +1 -0
- package/dist/collection-editing.d.ts +38 -0
- package/dist/collection-editing.d.ts.map +1 -0
- package/dist/collection-editing.js +53 -0
- package/dist/collection-editing.js.map +1 -0
- package/dist/communication.d.ts +29 -0
- package/dist/communication.d.ts.map +1 -0
- package/dist/communication.js +11 -0
- package/dist/communication.js.map +1 -0
- package/dist/component-definitions.d.ts +1 -0
- package/dist/component-definitions.d.ts.map +1 -1
- package/dist/component-definitions.js +1 -0
- package/dist/component-definitions.js.map +1 -1
- package/dist/data-table.d.ts +229 -5
- package/dist/data-table.d.ts.map +1 -1
- package/dist/data-table.js +242 -6
- package/dist/data-table.js.map +1 -1
- package/dist/data-workflows.d.ts +70 -0
- package/dist/data-workflows.d.ts.map +1 -0
- package/dist/data-workflows.js +109 -0
- package/dist/data-workflows.js.map +1 -0
- package/dist/dataviz.d.ts +7 -6
- package/dist/dataviz.d.ts.map +1 -1
- package/dist/dataviz.js +7 -6
- package/dist/dataviz.js.map +1 -1
- package/dist/gooey-navigation.d.ts +7 -0
- package/dist/gooey-navigation.d.ts.map +1 -1
- package/dist/gooey-navigation.js +10 -0
- package/dist/gooey-navigation.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/media-transport.d.ts +16 -0
- package/dist/media-transport.d.ts.map +1 -0
- package/dist/media-transport.js +17 -0
- package/dist/media-transport.js.map +1 -0
- package/dist/recipes.d.ts +1 -0
- package/dist/recipes.d.ts.map +1 -1
- package/dist/recipes.js +1 -0
- package/dist/recipes.js.map +1 -1
- package/dist/showcase.d.ts.map +1 -1
- package/dist/showcase.js +3 -1
- package/dist/showcase.js.map +1 -1
- package/dist/social-compositions.d.ts +19 -0
- package/dist/social-compositions.d.ts.map +1 -0
- package/dist/social-compositions.js +33 -0
- package/dist/social-compositions.js.map +1 -0
- package/dist/streaming-answer.d.ts +18 -0
- package/dist/streaming-answer.d.ts.map +1 -0
- package/dist/streaming-answer.js +61 -0
- package/dist/streaming-answer.js.map +1 -0
- package/dist/task-controls.d.ts +31 -0
- package/dist/task-controls.d.ts.map +1 -0
- package/dist/task-controls.js +25 -0
- package/dist/task-controls.js.map +1 -0
- package/dist/toggle-feedback.d.ts +22 -0
- package/dist/toggle-feedback.d.ts.map +1 -0
- package/dist/toggle-feedback.js +32 -0
- package/dist/toggle-feedback.js.map +1 -0
- package/dist/transfer-task.d.ts +13 -0
- package/dist/transfer-task.d.ts.map +1 -0
- package/dist/transfer-task.js +13 -0
- package/dist/transfer-task.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/docs/authoring-tools.md +31 -0
- package/docs/calendar.md +3 -1
- package/docs/catalog-freeze.json +5 -0
- package/docs/chart.md +206 -0
- package/docs/collection-editing.md +83 -0
- package/docs/communication.md +35 -0
- package/docs/data-table.md +56 -6
- package/docs/data-workflows.md +26 -0
- package/docs/generated/component-maturity.md +6 -5
- package/docs/generated/renderer-evidence.json +95 -5
- package/docs/generated/renderer-evidence.md +6 -3
- package/docs/generated/showcase-manifest.json +66 -3
- package/docs/gooey-navigation.md +20 -0
- package/docs/library-gap-analysis.md +4 -2
- package/docs/media-transport.md +37 -0
- package/docs/social-compositions.md +51 -0
- package/docs/streaming-answer.md +57 -0
- package/docs/task-controls.md +38 -0
- package/docs/toggle-feedback.md +56 -0
- package/docs/transfer-task.md +33 -0
- package/docs/usage/README.md +15 -4
- package/docs/usage/components/activity-chip.md +2 -2
- package/docs/usage/components/button.md +39 -0
- package/docs/usage/components/calendar.md +4 -2
- package/docs/usage/components/chart.md +277 -0
- package/docs/usage/components/data-table.md +92 -18
- package/docs/usage/components/screen-layout.md +3 -1
- package/docs/usage/components/tabs.md +25 -0
- package/docs/usage/components/toast.md +1 -1
- package/docs/usage/compositions/action-feedback.md +18 -2
- package/docs/usage/compositions/activity-status.md +2 -2
- package/docs/usage/compositions/authoring-tools.md +90 -0
- package/docs/usage/compositions/collection-editing.md +110 -0
- package/docs/usage/compositions/communication.md +100 -0
- package/docs/usage/compositions/data-workflows.md +91 -0
- package/docs/usage/compositions/media-transport.md +87 -0
- package/docs/usage/compositions/social-compositions.md +91 -0
- package/docs/usage/compositions/streaming-answer.md +97 -0
- package/docs/usage/compositions/task-controls.md +93 -0
- package/docs/usage/compositions/toggle-feedback.md +84 -0
- package/docs/usage/compositions/transfer-task.md +86 -0
- package/docs/usage/compositions/web-additions.md +2 -2
- package/docs/usage/screens/common-shell.md +4 -0
- package/package.json +67 -1
package/dist/chart.js
ADDED
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
import { datavizChromeTokens } from "./dataviz.js";
|
|
2
|
+
import { radius, spacing, stroke } from "./foundations.js";
|
|
3
|
+
export const chartRecipe = {
|
|
4
|
+
heights: { sparkline: 28, compact: 128, regular: 180, tall: 240 },
|
|
5
|
+
insets: {
|
|
6
|
+
plot: { top: spacing.lg, right: spacing.xs, bottom: spacing.xs, left: spacing.xs },
|
|
7
|
+
axis: { top: spacing.md, right: spacing.xs, bottom: spacing.lg, left: 36 },
|
|
8
|
+
},
|
|
9
|
+
line: { strokeWidth: 2.4, pointRadius: 4.5, focusHaloRadius: 9, focusHaloOpacity: 0.25 },
|
|
10
|
+
area: { topOpacity: 0.32, bottomOpacity: 0 },
|
|
11
|
+
bar: { radius: radius.sm / 2, maxWidth: 28, bandPadding: 0.36, groupGap: 2, restOpacity: 0.4 },
|
|
12
|
+
pie: { donutRatio: 0.62, padAngle: 0.012, minLabelPercent: 4 },
|
|
13
|
+
radar: { levels: 4, strokeWidth: 2, fillOpacity: 0.22, labelOffset: spacing.sm },
|
|
14
|
+
scatter: { radius: 5, focusRadius: 8 },
|
|
15
|
+
sparkline: { width: 72, height: 28, strokeWidth: 1.8, padding: 2 },
|
|
16
|
+
cursor: { strokeWidth: stroke.subtle, dash: [2, 3] },
|
|
17
|
+
reference: { dash: [2, 4] },
|
|
18
|
+
chrome: datavizChromeTokens,
|
|
19
|
+
};
|
|
20
|
+
// ---------------------------------------------------------------------------------------------
|
|
21
|
+
// Validation
|
|
22
|
+
// ---------------------------------------------------------------------------------------------
|
|
23
|
+
export function validateChartSeries(categories, series) {
|
|
24
|
+
if (series.length === 0)
|
|
25
|
+
throw new TypeError("Chart needs at least one series");
|
|
26
|
+
const ids = new Set();
|
|
27
|
+
for (const item of series) {
|
|
28
|
+
if (!item.id.trim())
|
|
29
|
+
throw new TypeError("Chart series id must not be empty");
|
|
30
|
+
if (ids.has(item.id))
|
|
31
|
+
throw new TypeError(`Duplicate chart series id: ${item.id}`);
|
|
32
|
+
ids.add(item.id);
|
|
33
|
+
if (!item.label.trim())
|
|
34
|
+
throw new TypeError(`Chart series "${item.id}" label must not be empty`);
|
|
35
|
+
if (item.values.length !== categories.length) {
|
|
36
|
+
throw new RangeError(`Chart series "${item.id}" has ${item.values.length} values for ${categories.length} categories`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export const isChartNumber = (value) => typeof value === "number" && Number.isFinite(value);
|
|
41
|
+
// ---------------------------------------------------------------------------------------------
|
|
42
|
+
// Scales and ticks
|
|
43
|
+
// ---------------------------------------------------------------------------------------------
|
|
44
|
+
/** "Nice" step (1, 2, 2.5, 5 × 10^n) so axis labels read like 0/25/50 rather than 0/23.7/47.4. */
|
|
45
|
+
export function niceStep(span, count) {
|
|
46
|
+
if (!(span > 0) || count < 1)
|
|
47
|
+
return 1;
|
|
48
|
+
const raw = span / count, power = 10 ** Math.floor(Math.log10(raw)), ratio = raw / power;
|
|
49
|
+
const nice = ratio <= 1 ? 1 : ratio <= 2 ? 2 : ratio <= 2.5 ? 2.5 : ratio <= 5 ? 5 : 10;
|
|
50
|
+
return nice * power;
|
|
51
|
+
}
|
|
52
|
+
export function niceTicks(min, max, count = 4) {
|
|
53
|
+
if (!Number.isFinite(min) || !Number.isFinite(max))
|
|
54
|
+
return [];
|
|
55
|
+
if (min === max)
|
|
56
|
+
return [min];
|
|
57
|
+
const step = niceStep(max - min, count), start = Math.ceil(min / step - 1e-9) * step;
|
|
58
|
+
const ticks = [];
|
|
59
|
+
for (let tick = start; tick <= max + step * 1e-9; tick += step)
|
|
60
|
+
ticks.push(Number(tick.toPrecision(12)));
|
|
61
|
+
return ticks;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Value domain. Lines zoom to the observed range (stock charts) unless `includeZero`; bars always
|
|
65
|
+
* include zero so heights compare honestly. `padding` widens a flat series so it is not drawn on an edge.
|
|
66
|
+
*/
|
|
67
|
+
export function resolveChartDomain(values, { domain, includeZero = false, nice = false, padding = 0 } = {}) {
|
|
68
|
+
if (domain)
|
|
69
|
+
return domain;
|
|
70
|
+
const observed = values.filter(isChartNumber);
|
|
71
|
+
if (!observed.length)
|
|
72
|
+
return [0, 1];
|
|
73
|
+
let min = Math.min(...observed), max = Math.max(...observed);
|
|
74
|
+
if (includeZero) {
|
|
75
|
+
min = Math.min(0, min);
|
|
76
|
+
max = Math.max(0, max);
|
|
77
|
+
}
|
|
78
|
+
if (min === max) {
|
|
79
|
+
const pad = Math.abs(min) * 0.1 || 1;
|
|
80
|
+
min -= pad;
|
|
81
|
+
max += pad;
|
|
82
|
+
}
|
|
83
|
+
if (padding > 0) {
|
|
84
|
+
const pad = (max - min) * padding;
|
|
85
|
+
if (!(includeZero && min === 0))
|
|
86
|
+
min -= pad;
|
|
87
|
+
max += pad;
|
|
88
|
+
}
|
|
89
|
+
if (nice) {
|
|
90
|
+
const step = niceStep(max - min, 4);
|
|
91
|
+
min = Math.floor(min / step) * step;
|
|
92
|
+
max = Math.ceil(max / step) * step;
|
|
93
|
+
}
|
|
94
|
+
return [min, max];
|
|
95
|
+
}
|
|
96
|
+
/** Linear scale from value domain to pixel range; `invert` puts the minimum at the top (ranks, ERA). */
|
|
97
|
+
export function scaleLinear(domain, range, invert = false) {
|
|
98
|
+
const [d0, d1] = domain, [r0, r1] = invert ? [range[1], range[0]] : range, span = d1 - d0;
|
|
99
|
+
return value => span === 0 ? (r0 + r1) / 2 : r0 + (value - d0) / span * (r1 - r0);
|
|
100
|
+
}
|
|
101
|
+
export function scaleBand(count, range, padding = chartRecipe.bar.bandPadding) {
|
|
102
|
+
const length = range[1] - range[0], step = count > 0 ? length / count : 0, bandwidth = step * (1 - padding);
|
|
103
|
+
return { step, bandwidth, start: index => range[0] + index * step + (step - bandwidth) / 2, center: index => range[0] + index * step + step / 2 };
|
|
104
|
+
}
|
|
105
|
+
/** Evenly spaced x positions for line/area categories (first and last on the plot edges). */
|
|
106
|
+
export function pointPositions(count, range) {
|
|
107
|
+
if (count <= 1)
|
|
108
|
+
return [Math.round((range[0] + range[1]) / 2)];
|
|
109
|
+
const step = (range[1] - range[0]) / (count - 1);
|
|
110
|
+
return Array.from({ length: count }, (_, i) => range[0] + i * step);
|
|
111
|
+
}
|
|
112
|
+
// ---------------------------------------------------------------------------------------------
|
|
113
|
+
// Paths
|
|
114
|
+
// ---------------------------------------------------------------------------------------------
|
|
115
|
+
const fixed = (value) => Number(value.toFixed(2));
|
|
116
|
+
/** Monotone-X cubic (Fritsch–Carlson): smooth without overshooting the data, like d3.curveMonotoneX. */
|
|
117
|
+
function monotoneTangents(points) {
|
|
118
|
+
const n = points.length, slopes = [], tangents = new Array(n).fill(0);
|
|
119
|
+
for (let i = 0; i < n - 1; i++)
|
|
120
|
+
slopes.push((points[i + 1].y - points[i].y) / ((points[i + 1].x - points[i].x) || 1));
|
|
121
|
+
tangents[0] = slopes[0] ?? 0;
|
|
122
|
+
tangents[n - 1] = slopes[n - 2] ?? 0;
|
|
123
|
+
for (let i = 1; i < n - 1; i++)
|
|
124
|
+
tangents[i] = slopes[i - 1] * slopes[i] <= 0 ? 0 : (slopes[i - 1] + slopes[i]) / 2;
|
|
125
|
+
for (let i = 0; i < n - 1; i++) {
|
|
126
|
+
if (slopes[i] === 0) {
|
|
127
|
+
tangents[i] = 0;
|
|
128
|
+
tangents[i + 1] = 0;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const a = tangents[i] / slopes[i], b = tangents[i + 1] / slopes[i], h = a * a + b * b;
|
|
132
|
+
if (h > 9) {
|
|
133
|
+
const t = 3 / Math.sqrt(h);
|
|
134
|
+
tangents[i] = t * a * slopes[i];
|
|
135
|
+
tangents[i + 1] = t * b * slopes[i];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return tangents;
|
|
139
|
+
}
|
|
140
|
+
export function linePath(points, curve = "linear") {
|
|
141
|
+
if (!points.length)
|
|
142
|
+
return "";
|
|
143
|
+
const head = `M${fixed(points[0].x)},${fixed(points[0].y)}`;
|
|
144
|
+
if (points.length === 1)
|
|
145
|
+
return head;
|
|
146
|
+
if (curve === "step")
|
|
147
|
+
return head + points.slice(1).map((p, i) => `H${fixed((points[i].x + p.x) / 2)}V${fixed(p.y)}H${fixed(p.x)}`).join("");
|
|
148
|
+
if (curve === "monotone" && points.length > 2) {
|
|
149
|
+
const t = monotoneTangents(points);
|
|
150
|
+
return head + points.slice(1).map((p, i) => {
|
|
151
|
+
const a = points[i], dx = (p.x - a.x) / 3;
|
|
152
|
+
return `C${fixed(a.x + dx)},${fixed(a.y + dx * t[i])} ${fixed(p.x - dx)},${fixed(p.y - dx * t[i + 1])} ${fixed(p.x)},${fixed(p.y)}`;
|
|
153
|
+
}).join("");
|
|
154
|
+
}
|
|
155
|
+
return head + points.slice(1).map(p => `L${fixed(p.x)},${fixed(p.y)}`).join("");
|
|
156
|
+
}
|
|
157
|
+
/** Closed area under a line down to `floor` (or between two edges for stacked areas via `lower`). */
|
|
158
|
+
export function areaPath(points, floor, curve = "linear", lower) {
|
|
159
|
+
if (points.length < 2)
|
|
160
|
+
return "";
|
|
161
|
+
const top = linePath(points, curve);
|
|
162
|
+
if (lower && lower.length === points.length) {
|
|
163
|
+
const back = linePath([...lower].reverse(), curve).replace(/^M/, "L");
|
|
164
|
+
return `${top}${back}Z`;
|
|
165
|
+
}
|
|
166
|
+
return `${top}L${fixed(points.at(-1).x)},${fixed(floor)}L${fixed(points[0].x)},${fixed(floor)}Z`;
|
|
167
|
+
}
|
|
168
|
+
/** Splits a series at missing values: a skipped month is a gap, never an interpolated trend. */
|
|
169
|
+
export function splitSegments(plots) {
|
|
170
|
+
const segments = [];
|
|
171
|
+
let current = [];
|
|
172
|
+
for (const plot of plots) {
|
|
173
|
+
if (plot === null) {
|
|
174
|
+
if (current.length)
|
|
175
|
+
segments.push(current);
|
|
176
|
+
current = [];
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
current.push(plot);
|
|
180
|
+
}
|
|
181
|
+
if (current.length)
|
|
182
|
+
segments.push(current);
|
|
183
|
+
return segments;
|
|
184
|
+
}
|
|
185
|
+
export function resolveLineGeometry({ categories, series, width, height, insets = chartRecipe.insets.plot, invert = false, stacked = false, ...domainOptions }) {
|
|
186
|
+
validateChartSeries(categories, series);
|
|
187
|
+
const plot = { left: insets.left, right: width - insets.right, top: insets.top, bottom: height - insets.bottom };
|
|
188
|
+
const totals = stacked ? stackValues(series) : null;
|
|
189
|
+
const domainValues = totals ? totals.flatMap(row => row.map(cell => cell?.[1] ?? null)) : series.flatMap(item => item.values);
|
|
190
|
+
const domain = resolveChartDomain(domainValues, { includeZero: stacked || domainOptions.includeZero, ...domainOptions });
|
|
191
|
+
const y = scaleLinear(domain, [plot.bottom, plot.top], invert);
|
|
192
|
+
const xs = pointPositions(categories.length, [plot.left, plot.right]);
|
|
193
|
+
const plots = series.map((item, s) => item.values.map((value, i) => {
|
|
194
|
+
const top = totals ? totals[s][i]?.[1] : value;
|
|
195
|
+
return isChartNumber(value) && isChartNumber(top) ? { index: i, seriesIndex: s, x: xs[i], y: y(top), value } : null;
|
|
196
|
+
}));
|
|
197
|
+
const lower = totals ? series.map((_, s) => categories.map((__, i) => { const cell = totals[s][i]; return cell ? { index: i, seriesIndex: s, x: xs[i], y: y(cell[0]), value: cell[0] } : null; })) : null;
|
|
198
|
+
return { plot, domain, ticks: niceTicks(domain[0], domain[1], 4), xs, y, plots, lower };
|
|
199
|
+
}
|
|
200
|
+
/** Cumulative [lower, upper] per series per category; missing values do not add to the stack. */
|
|
201
|
+
export function stackValues(series) {
|
|
202
|
+
const length = series[0]?.values.length ?? 0, positive = new Array(length).fill(0), negative = new Array(length).fill(0);
|
|
203
|
+
return series.map(item => item.values.map((value, i) => {
|
|
204
|
+
if (!isChartNumber(value))
|
|
205
|
+
return null;
|
|
206
|
+
const base = value >= 0 ? positive[i] : negative[i], top = base + value;
|
|
207
|
+
if (value >= 0)
|
|
208
|
+
positive[i] = top;
|
|
209
|
+
else
|
|
210
|
+
negative[i] = top;
|
|
211
|
+
return [base, top];
|
|
212
|
+
}));
|
|
213
|
+
}
|
|
214
|
+
export function resolveBarGeometry({ categories, series, width, height, insets = chartRecipe.insets.plot, orientation = "vertical", layout = "grouped", ...domainOptions }) {
|
|
215
|
+
validateChartSeries(categories, series);
|
|
216
|
+
const plot = { left: insets.left, right: width - insets.right, top: insets.top, bottom: height - insets.bottom };
|
|
217
|
+
const stacks = layout === "stacked" ? stackValues(series) : null;
|
|
218
|
+
const values = stacks ? stacks.flatMap(row => row.flatMap(cell => cell ? [cell[0], cell[1]] : [])) : series.flatMap(item => item.values);
|
|
219
|
+
const domain = resolveChartDomain(values, { includeZero: true, ...domainOptions });
|
|
220
|
+
const vertical = orientation === "vertical";
|
|
221
|
+
const valueScale = vertical ? scaleLinear(domain, [plot.bottom, plot.top]) : scaleLinear(domain, [plot.left, plot.right]);
|
|
222
|
+
const band = scaleBand(categories.length, vertical ? [plot.left, plot.right] : [plot.top, plot.bottom]);
|
|
223
|
+
const thickness = Math.min(chartRecipe.bar.maxWidth * (layout === "grouped" ? series.length : 1), band.bandwidth);
|
|
224
|
+
const each = layout === "grouped" ? Math.max(1, (thickness - chartRecipe.bar.groupGap * (series.length - 1)) / series.length) : thickness;
|
|
225
|
+
const bars = [];
|
|
226
|
+
series.forEach((item, s) => item.values.forEach((value, i) => {
|
|
227
|
+
if (!isChartNumber(value))
|
|
228
|
+
return;
|
|
229
|
+
const [from, to] = stacks ? stacks[s][i] : [0, value];
|
|
230
|
+
const a = valueScale(from), b = valueScale(to);
|
|
231
|
+
const offset = band.center(i) - thickness / 2 + (layout === "grouped" ? s * (each + chartRecipe.bar.groupGap) : 0);
|
|
232
|
+
bars.push(vertical
|
|
233
|
+
? { index: i, seriesIndex: s, value, x: offset, y: Math.min(a, b), width: each, height: Math.max(1, Math.abs(a - b)) }
|
|
234
|
+
: { index: i, seriesIndex: s, value, x: Math.min(a, b), y: offset, width: Math.max(1, Math.abs(a - b)), height: each });
|
|
235
|
+
}));
|
|
236
|
+
return { plot, domain, ticks: niceTicks(domain[0], domain[1], 4), bars, centers: categories.map((_, i) => band.center(i)), value: valueScale };
|
|
237
|
+
}
|
|
238
|
+
const polar = (cx, cy, r, angle) => ({ x: cx + r * Math.sin(angle), y: cy - r * Math.cos(angle) });
|
|
239
|
+
/** Annular sector from 12 o'clock clockwise. `innerRadius` 0 draws a pie wedge. */
|
|
240
|
+
export function arcPath(cx, cy, outerRadius, innerRadius, startAngle, endAngle) {
|
|
241
|
+
const sweep = endAngle - startAngle;
|
|
242
|
+
if (sweep >= Math.PI * 2 - 1e-6) {
|
|
243
|
+
// A full circle cannot be one arc command; draw two halves.
|
|
244
|
+
const mid = startAngle + Math.PI;
|
|
245
|
+
return arcPath(cx, cy, outerRadius, innerRadius, startAngle, mid) + arcPath(cx, cy, outerRadius, innerRadius, mid, endAngle);
|
|
246
|
+
}
|
|
247
|
+
const large = sweep > Math.PI ? 1 : 0;
|
|
248
|
+
const o0 = polar(cx, cy, outerRadius, startAngle), o1 = polar(cx, cy, outerRadius, endAngle);
|
|
249
|
+
if (innerRadius <= 0)
|
|
250
|
+
return `M${fixed(cx)},${fixed(cy)}L${fixed(o0.x)},${fixed(o0.y)}A${fixed(outerRadius)},${fixed(outerRadius)} 0 ${large} 1 ${fixed(o1.x)},${fixed(o1.y)}Z`;
|
|
251
|
+
const i1 = polar(cx, cy, innerRadius, endAngle), i0 = polar(cx, cy, innerRadius, startAngle);
|
|
252
|
+
return `M${fixed(o0.x)},${fixed(o0.y)}A${fixed(outerRadius)},${fixed(outerRadius)} 0 ${large} 1 ${fixed(o1.x)},${fixed(o1.y)}L${fixed(i1.x)},${fixed(i1.y)}A${fixed(innerRadius)},${fixed(innerRadius)} 0 ${large} 0 ${fixed(i0.x)},${fixed(i0.y)}Z`;
|
|
253
|
+
}
|
|
254
|
+
/** Negative and missing values are excluded: a share of a whole cannot be negative. */
|
|
255
|
+
export function resolvePieGeometry(values, { cx, cy, radius: outer, innerRadius = 0, padAngle = chartRecipe.pie.padAngle }) {
|
|
256
|
+
const total = values.reduce((sum, value) => sum + (isChartNumber(value) && value > 0 ? value : 0), 0);
|
|
257
|
+
if (total <= 0)
|
|
258
|
+
return [];
|
|
259
|
+
let angle = 0;
|
|
260
|
+
const slices = [];
|
|
261
|
+
values.forEach((value, index) => {
|
|
262
|
+
if (!isChartNumber(value) || value <= 0)
|
|
263
|
+
return;
|
|
264
|
+
const sweep = value / total * Math.PI * 2, pad = slices.length || sweep < Math.PI * 2 ? Math.min(padAngle, sweep / 4) : 0;
|
|
265
|
+
const start = angle + pad / 2, end = angle + sweep - pad / 2, mid = (start + end) / 2;
|
|
266
|
+
slices.push({ index, value, percent: value / total * 100, startAngle: start, endAngle: end, path: arcPath(cx, cy, outer, innerRadius, start, end), centroid: polar(cx, cy, innerRadius > 0 ? (outer + innerRadius) / 2 : outer * 0.62, mid) });
|
|
267
|
+
angle += sweep;
|
|
268
|
+
});
|
|
269
|
+
return slices;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Radar (spider) chart. All axes share one domain (0..max by default) because the products'
|
|
273
|
+
* ratings are on one 0–100 scale; per-axis scales would make the polygon area meaningless.
|
|
274
|
+
*/
|
|
275
|
+
export function resolveRadarGeometry({ categories, series, cx, cy, radius: outer, domain, levels = chartRecipe.radar.levels, labelOffset = chartRecipe.radar.labelOffset }) {
|
|
276
|
+
validateChartSeries(categories, series);
|
|
277
|
+
if (categories.length < 3)
|
|
278
|
+
throw new RangeError("Radar chart needs at least three axes");
|
|
279
|
+
const [min, max] = domain ?? [0, Math.max(...series.flatMap(item => item.values.filter(isChartNumber)), 1)];
|
|
280
|
+
const step = Math.PI * 2 / categories.length;
|
|
281
|
+
const axes = categories.map((label, index) => {
|
|
282
|
+
const angle = index * step, end = polar(cx, cy, outer, angle), labelAt = polar(cx, cy, outer + labelOffset, angle);
|
|
283
|
+
const sin = Math.sin(angle);
|
|
284
|
+
return { index, label, angle, end, labelAt, anchor: Math.abs(sin) < 0.2 ? "middle" : sin > 0 ? "start" : "end" };
|
|
285
|
+
});
|
|
286
|
+
const rings = Array.from({ length: levels }, (_, level) => {
|
|
287
|
+
const r = outer * (level + 1) / levels;
|
|
288
|
+
return axes.map((axis, i) => { const p = polar(cx, cy, r, axis.angle); return `${i ? "L" : "M"}${fixed(p.x)},${fixed(p.y)}`; }).join("") + "Z";
|
|
289
|
+
});
|
|
290
|
+
const polygons = series.map((item, seriesIndex) => {
|
|
291
|
+
const points = axes.map(axis => {
|
|
292
|
+
const value = item.values[axis.index] ?? null;
|
|
293
|
+
const ratio = isChartNumber(value) ? Math.max(0, Math.min(1, (value - min) / ((max - min) || 1))) : 0;
|
|
294
|
+
return { ...polar(cx, cy, outer * ratio, axis.angle), index: axis.index, value: isChartNumber(value) ? value : null };
|
|
295
|
+
});
|
|
296
|
+
return { seriesIndex, points, path: points.map((p, i) => `${i ? "L" : "M"}${fixed(p.x)},${fixed(p.y)}`).join("") + "Z" };
|
|
297
|
+
});
|
|
298
|
+
return { axes, rings, polygons };
|
|
299
|
+
}
|
|
300
|
+
export function resolveScatterGeometry({ points, width, height, insets = chartRecipe.insets.axis, xDomain, yDomain }) {
|
|
301
|
+
const plot = { left: insets.left, right: width - insets.right, top: insets.top, bottom: height - insets.bottom };
|
|
302
|
+
const xd = resolveChartDomain(points.map(p => p.x), { domain: xDomain, padding: 0.06 }), yd = resolveChartDomain(points.map(p => p.y), { domain: yDomain, padding: 0.06 });
|
|
303
|
+
const sx = scaleLinear(xd, [plot.left, plot.right]), sy = scaleLinear(yd, [plot.bottom, plot.top]);
|
|
304
|
+
return { plot, xDomain: xd, yDomain: yd, xTicks: niceTicks(xd[0], xd[1], 4), yTicks: niceTicks(yd[0], yd[1], 4), points: points.map(p => ({ ...p, px: sx(p.x), py: sy(p.y) })) };
|
|
305
|
+
}
|
|
306
|
+
// ---------------------------------------------------------------------------------------------
|
|
307
|
+
// Focus (scrub / press) and accessibility
|
|
308
|
+
// ---------------------------------------------------------------------------------------------
|
|
309
|
+
/** Category index whose x is closest to a pointer x, among categories that have any value. */
|
|
310
|
+
export function nearestChartIndex(xs, x, available) {
|
|
311
|
+
const candidates = available ?? xs.map((_, i) => i);
|
|
312
|
+
let best = null, distance = Infinity;
|
|
313
|
+
for (const index of candidates) {
|
|
314
|
+
const d = Math.abs(xs[index] - x);
|
|
315
|
+
if (d < distance) {
|
|
316
|
+
distance = d;
|
|
317
|
+
best = index;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return best;
|
|
321
|
+
}
|
|
322
|
+
export function nearestScatterPoint(points, x, y, maxDistance = 32) {
|
|
323
|
+
let best = null, distance = maxDistance * maxDistance;
|
|
324
|
+
points.forEach((p, i) => { const d = (p.px - x) ** 2 + (p.py - y) ** 2; if (d <= distance) {
|
|
325
|
+
distance = d;
|
|
326
|
+
best = i;
|
|
327
|
+
} });
|
|
328
|
+
return best;
|
|
329
|
+
}
|
|
330
|
+
/** Adjustable-role step (VoiceOver swipe, arrow keys) over observed indices only. */
|
|
331
|
+
export function stepChartIndex(available, current, direction) {
|
|
332
|
+
if (!available.length)
|
|
333
|
+
return null;
|
|
334
|
+
if (current === null)
|
|
335
|
+
return direction > 0 ? available[0] : available.at(-1);
|
|
336
|
+
const position = available.indexOf(current);
|
|
337
|
+
return available[Math.min(available.length - 1, Math.max(0, (position < 0 ? 0 : position) + direction))];
|
|
338
|
+
}
|
|
339
|
+
export function observedIndices(series) {
|
|
340
|
+
const length = series[0]?.values.length ?? 0;
|
|
341
|
+
return Array.from({ length }, (_, i) => i).filter(i => series.some(item => isChartNumber(item.values[i])));
|
|
342
|
+
}
|
|
343
|
+
/** Index of the highest and lowest observation of one series (stock-chart high/low markers). */
|
|
344
|
+
export function seriesExtremes(values) {
|
|
345
|
+
let max = -1, min = -1;
|
|
346
|
+
values.forEach((value, i) => {
|
|
347
|
+
if (!isChartNumber(value))
|
|
348
|
+
return;
|
|
349
|
+
if (max < 0 || value > values[max])
|
|
350
|
+
max = i;
|
|
351
|
+
if (min < 0 || value < values[min])
|
|
352
|
+
min = i;
|
|
353
|
+
});
|
|
354
|
+
return max < 0 ? null : { max, min };
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Text alternative for an image-like chart: every category's values in order, product-formatted.
|
|
358
|
+
* Products pass localized `format`; HJM never formats numbers into a language itself.
|
|
359
|
+
*/
|
|
360
|
+
export function describeChart(categories, series, format, missing) {
|
|
361
|
+
return series.map(item => `${item.label}: ${categories.map((category, i) => { const v = item.values[i]; return `${category} ${isChartNumber(v) ? format(v) : missing}`; }).join(", ")}`).join(". ");
|
|
362
|
+
}
|
|
363
|
+
export const chartBehavior = {
|
|
364
|
+
controlled: ["focusIndex"],
|
|
365
|
+
inputs: ["categories", "series", "kind", "orientation", "layout", "domain", "invert", "curve"],
|
|
366
|
+
events: ["onFocusChange"],
|
|
367
|
+
configuration: { curve: ["linear", "monotone", "step"], orientation: ["vertical", "horizontal"], layout: ["grouped", "stacked"] },
|
|
368
|
+
defaults: { curve: "linear", orientation: "vertical", layout: "grouped" },
|
|
369
|
+
stateAxes: { value: ["focused", "scrubbing"], content: ["idle", "empty"] },
|
|
370
|
+
web: { roles: ["img", "slider"], keyboard: ["ArrowLeft", "ArrowRight", "Home", "End"], focus: "native" },
|
|
371
|
+
native: { roles: ["adjustable", "image"], states: [], actions: ["increment", "decrement"] },
|
|
372
|
+
scenarios: [
|
|
373
|
+
"missing-values-split-the-line-instead-of-drawing-zero",
|
|
374
|
+
"bars-and-stacks-always-include-a-zero-baseline",
|
|
375
|
+
"inverted-scale-puts-the-best-rank-on-top",
|
|
376
|
+
"scrubbing-reports-the-focused-index-and-releasing-restores-the-latest",
|
|
377
|
+
"the-focused-point-is-reachable-without-a-drag-via-adjustable-or-arrow-keys",
|
|
378
|
+
"series-colors-come-from-the-product-or-the-dataviz-palette-never-status-colors",
|
|
379
|
+
"every-chart-exposes-a-product-formatted-text-alternative",
|
|
380
|
+
"radar-axes-share-one-domain",
|
|
381
|
+
"pie-slices-ignore-negative-and-missing-values",
|
|
382
|
+
],
|
|
383
|
+
};
|
|
384
|
+
/** Excluding a slice changes the denominator; selecting one only emphasizes it (Lucian 097). */
|
|
385
|
+
export function resolvePieVisibility(data, excludedIds = []) {
|
|
386
|
+
const ids = new Set(data.map(datum => datum.id)), excluded = new Set(excludedIds);
|
|
387
|
+
if (ids.size !== data.length || data.some(datum => !datum.id.trim()))
|
|
388
|
+
throw new TypeError("Pie data requires distinct nonempty ids");
|
|
389
|
+
if (excluded.size !== excludedIds.length || excludedIds.some(id => !ids.has(id)))
|
|
390
|
+
throw new TypeError("Excluded pie ids must be distinct known ids");
|
|
391
|
+
// Keep the existing geometry contract: negative/nonfinite/missing values never enter a share.
|
|
392
|
+
const values = data.map(datum => excluded.has(datum.id) || !isChartNumber(datum.value) || datum.value < 0 ? null : datum.value);
|
|
393
|
+
const total = values.reduce((sum, value) => sum + (value ?? 0), 0);
|
|
394
|
+
if (!Number.isFinite(total))
|
|
395
|
+
throw new RangeError("Pie total must be finite");
|
|
396
|
+
return { values, total, includedCount: data.length - excluded.size, observedCount: values.filter(value => value !== null).length };
|
|
397
|
+
}
|
|
398
|
+
/** Match both actual polyline vertices before period morphing. Union knots preserve
|
|
399
|
+
* every observation for linear paths; work is bounded by the caller for large data. */
|
|
400
|
+
export function prepareChartLineMorph(from, to) {
|
|
401
|
+
if (from.length < 2 || to.length < 2)
|
|
402
|
+
return null;
|
|
403
|
+
const knots = [...new Set([...from.map((_, i) => i / (from.length - 1)), ...to.map((_, i) => i / (to.length - 1))])].sort((a, b) => a - b);
|
|
404
|
+
const sample = (points, position) => {
|
|
405
|
+
const index = position * (points.length - 1), start = Math.floor(index), end = Math.min(points.length - 1, start + 1), t = index - start;
|
|
406
|
+
return { x: points[start].x + (points[end].x - points[start].x) * t, y: points[start].y + (points[end].y - points[start].y) * t };
|
|
407
|
+
};
|
|
408
|
+
const first = knots.map(k => sample(from, k)), last = knots.map(k => sample(to, k));
|
|
409
|
+
return (progress) => {
|
|
410
|
+
const t = Math.max(0, Math.min(1, progress));
|
|
411
|
+
return first.map((point, i) => ({ x: point.x + (last[i].x - point.x) * t, y: point.y + (last[i].y - point.y) * t }));
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
//# sourceMappingURL=chart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart.js","sourceRoot":"","sources":["../src/chart.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BehaviorContract } from \"./behaviors.js\";\nimport { datavizChromeTokens } from \"./dataviz.js\";\nimport { radius, spacing, stroke } from \"./foundations.js\";\n\n/**\n * Chart geometry contract (2026-10-14, user request: \"absorb the well-known chart libraries into our\n * system\"). Until 1.20 HJM only shipped dataviz *tokens* and delegated drawing to product libraries\n * (see docs/chart.md for the earlier decision). Products then rebuilt the same scrubbing line chart,\n * bars, and stat tables separately (Yajalal's StockChart/RecordTable), so drawing moves into HJM.\n *\n * Everything here is renderer-neutral math: both the Web (SVG DOM) and Native (react-native-svg)\n * renderers receive the same coordinates, paths and accessibility summaries and only paint them.\n * The public shapes were studied from — not copied from — these MIT/ISC libraries:\n * - react-native-wagmi-charts: line + cursor crosshair, price/datetime text driven by the focused index\n * - victory-native (XL): CartesianChart x/y keys, chart press state, rounded bars, domain padding\n * - react-native-gifted-charts: bar/line/pie/radar props (focus on press, stacked bars, donut center)\n * - Recharts: series/category data model, stacking, nice ticks, radar polar grid\n * - d3-shape / d3-scale: monotone-X cubic curve (Fritsch–Carlson) and \"nice\" tick steps (algorithms\n * re-derived here; no source is vendored)\n */\n\nexport type ChartValue = number | null;\n\nexport type ChartSeries = Readonly<{\n id: string;\n /** Visible legend text and the series' accessible name. Product-localized. */\n label: string;\n /** One value per category; `null` is a missing observation (drawn as a gap, never as zero). */\n values: readonly ChartValue[];\n /** Product-owned series color; renderers fall back to the dataviz series palette by index. */\n color?: string;\n}>;\n\nexport type ChartInsets = Readonly<{ top: number; right: number; bottom: number; left: number }>;\nexport type ChartCurve = \"linear\" | \"monotone\" | \"step\";\nexport type ChartOrientation = \"vertical\" | \"horizontal\";\nexport type ChartBarLayout = \"grouped\" | \"stacked\";\n\nexport type ChartPlot = Readonly<{ index: number; seriesIndex: number; x: number; y: number; value: number }>;\n\nexport const chartRecipe = {\n heights: { sparkline: 28, compact: 128, regular: 180, tall: 240 },\n insets: {\n plot: { top: spacing.lg, right: spacing.xs, bottom: spacing.xs, left: spacing.xs },\n axis: { top: spacing.md, right: spacing.xs, bottom: spacing.lg, left: 36 },\n },\n line: { strokeWidth: 2.4, pointRadius: 4.5, focusHaloRadius: 9, focusHaloOpacity: 0.25 },\n area: { topOpacity: 0.32, bottomOpacity: 0 },\n bar: { radius: radius.sm / 2, maxWidth: 28, bandPadding: 0.36, groupGap: 2, restOpacity: 0.4 },\n pie: { donutRatio: 0.62, padAngle: 0.012, minLabelPercent: 4 },\n radar: { levels: 4, strokeWidth: 2, fillOpacity: 0.22, labelOffset: spacing.sm },\n scatter: { radius: 5, focusRadius: 8 },\n sparkline: { width: 72, height: 28, strokeWidth: 1.8, padding: 2 },\n cursor: { strokeWidth: stroke.subtle, dash: [2, 3] as const },\n reference: { dash: [2, 4] as const },\n chrome: datavizChromeTokens,\n} as const;\n\n// ---------------------------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------------------------\n\nexport function validateChartSeries(categories: readonly string[], series: readonly ChartSeries[]): void {\n if (series.length === 0) throw new TypeError(\"Chart needs at least one series\");\n const ids = new Set<string>();\n for (const item of series) {\n if (!item.id.trim()) throw new TypeError(\"Chart series id must not be empty\");\n if (ids.has(item.id)) throw new TypeError(`Duplicate chart series id: ${item.id}`);\n ids.add(item.id);\n if (!item.label.trim()) throw new TypeError(`Chart series \"${item.id}\" label must not be empty`);\n if (item.values.length !== categories.length) {\n throw new RangeError(`Chart series \"${item.id}\" has ${item.values.length} values for ${categories.length} categories`);\n }\n }\n}\n\nexport const isChartNumber = (value: ChartValue | undefined): value is number => typeof value === \"number\" && Number.isFinite(value);\n\n// ---------------------------------------------------------------------------------------------\n// Scales and ticks\n// ---------------------------------------------------------------------------------------------\n\n/** \"Nice\" step (1, 2, 2.5, 5 × 10^n) so axis labels read like 0/25/50 rather than 0/23.7/47.4. */\nexport function niceStep(span: number, count: number): number {\n if (!(span > 0) || count < 1) return 1;\n const raw = span / count, power = 10 ** Math.floor(Math.log10(raw)), ratio = raw / power;\n const nice = ratio <= 1 ? 1 : ratio <= 2 ? 2 : ratio <= 2.5 ? 2.5 : ratio <= 5 ? 5 : 10;\n return nice * power;\n}\n\nexport function niceTicks(min: number, max: number, count = 4): number[] {\n if (!Number.isFinite(min) || !Number.isFinite(max)) return [];\n if (min === max) return [min];\n const step = niceStep(max - min, count), start = Math.ceil(min / step - 1e-9) * step;\n const ticks: number[] = [];\n for (let tick = start; tick <= max + step * 1e-9; tick += step) ticks.push(Number(tick.toPrecision(12)));\n return ticks;\n}\n\nexport type ChartDomainOptions = Readonly<{ domain?: readonly [number, number] | undefined; includeZero?: boolean | undefined; nice?: boolean | undefined; padding?: number | undefined }>;\n/**\n * Value domain. Lines zoom to the observed range (stock charts) unless `includeZero`; bars always\n * include zero so heights compare honestly. `padding` widens a flat series so it is not drawn on an edge.\n */\nexport function resolveChartDomain(values: readonly ChartValue[], { domain, includeZero = false, nice = false, padding = 0 }: ChartDomainOptions = {}): readonly [number, number] {\n if (domain) return domain;\n const observed = values.filter(isChartNumber);\n if (!observed.length) return [0, 1];\n let min = Math.min(...observed), max = Math.max(...observed);\n if (includeZero) { min = Math.min(0, min); max = Math.max(0, max); }\n if (min === max) { const pad = Math.abs(min) * 0.1 || 1; min -= pad; max += pad; }\n if (padding > 0) { const pad = (max - min) * padding; if (!(includeZero && min === 0)) min -= pad; max += pad; }\n if (nice) { const step = niceStep(max - min, 4); min = Math.floor(min / step) * step; max = Math.ceil(max / step) * step; }\n return [min, max];\n}\n\n/** Linear scale from value domain to pixel range; `invert` puts the minimum at the top (ranks, ERA). */\nexport function scaleLinear(domain: readonly [number, number], range: readonly [number, number], invert = false): (value: number) => number {\n const [d0, d1] = domain, [r0, r1] = invert ? [range[1], range[0]] : range, span = d1 - d0;\n return value => span === 0 ? (r0 + r1) / 2 : r0 + (value - d0) / span * (r1 - r0);\n}\n\nexport type ChartBand = Readonly<{ step: number; bandwidth: number; start(index: number): number; center(index: number): number }>;\nexport function scaleBand(count: number, range: readonly [number, number], padding: number = chartRecipe.bar.bandPadding): ChartBand {\n const length = range[1] - range[0], step = count > 0 ? length / count : 0, bandwidth = step * (1 - padding);\n return { step, bandwidth, start: index => range[0] + index * step + (step - bandwidth) / 2, center: index => range[0] + index * step + step / 2 };\n}\n\n/** Evenly spaced x positions for line/area categories (first and last on the plot edges). */\nexport function pointPositions(count: number, range: readonly [number, number]): number[] {\n if (count <= 1) return [Math.round((range[0] + range[1]) / 2)];\n const step = (range[1] - range[0]) / (count - 1);\n return Array.from({ length: count }, (_, i) => range[0] + i * step);\n}\n\n// ---------------------------------------------------------------------------------------------\n// Paths\n// ---------------------------------------------------------------------------------------------\n\nconst fixed = (value: number) => Number(value.toFixed(2));\ntype XY = Readonly<{ x: number; y: number }>;\n\n/** Monotone-X cubic (Fritsch–Carlson): smooth without overshooting the data, like d3.curveMonotoneX. */\nfunction monotoneTangents(points: readonly XY[]): number[] {\n const n = points.length, slopes: number[] = [], tangents: number[] = new Array(n).fill(0);\n for (let i = 0; i < n - 1; i++) slopes.push((points[i + 1]!.y - points[i]!.y) / ((points[i + 1]!.x - points[i]!.x) || 1));\n tangents[0] = slopes[0] ?? 0; tangents[n - 1] = slopes[n - 2] ?? 0;\n for (let i = 1; i < n - 1; i++) tangents[i] = slopes[i - 1]! * slopes[i]! <= 0 ? 0 : (slopes[i - 1]! + slopes[i]!) / 2;\n for (let i = 0; i < n - 1; i++) {\n if (slopes[i] === 0) { tangents[i] = 0; tangents[i + 1] = 0; continue; }\n const a = tangents[i]! / slopes[i]!, b = tangents[i + 1]! / slopes[i]!, h = a * a + b * b;\n if (h > 9) { const t = 3 / Math.sqrt(h); tangents[i] = t * a * slopes[i]!; tangents[i + 1] = t * b * slopes[i]!; }\n }\n return tangents;\n}\n\nexport function linePath(points: readonly XY[], curve: ChartCurve = \"linear\"): string {\n if (!points.length) return \"\";\n const head = `M${fixed(points[0]!.x)},${fixed(points[0]!.y)}`;\n if (points.length === 1) return head;\n if (curve === \"step\") return head + points.slice(1).map((p, i) => `H${fixed((points[i]!.x + p.x) / 2)}V${fixed(p.y)}H${fixed(p.x)}`).join(\"\");\n if (curve === \"monotone\" && points.length > 2) {\n const t = monotoneTangents(points);\n return head + points.slice(1).map((p, i) => {\n const a = points[i]!, dx = (p.x - a.x) / 3;\n return `C${fixed(a.x + dx)},${fixed(a.y + dx * t[i]!)} ${fixed(p.x - dx)},${fixed(p.y - dx * t[i + 1]!)} ${fixed(p.x)},${fixed(p.y)}`;\n }).join(\"\");\n }\n return head + points.slice(1).map(p => `L${fixed(p.x)},${fixed(p.y)}`).join(\"\");\n}\n\n/** Closed area under a line down to `floor` (or between two edges for stacked areas via `lower`). */\nexport function areaPath(points: readonly XY[], floor: number, curve: ChartCurve = \"linear\", lower?: readonly XY[]): string {\n if (points.length < 2) return \"\";\n const top = linePath(points, curve);\n if (lower && lower.length === points.length) {\n const back = linePath([...lower].reverse(), curve).replace(/^M/, \"L\");\n return `${top}${back}Z`;\n }\n return `${top}L${fixed(points.at(-1)!.x)},${fixed(floor)}L${fixed(points[0]!.x)},${fixed(floor)}Z`;\n}\n\n/** Splits a series at missing values: a skipped month is a gap, never an interpolated trend. */\nexport function splitSegments<T extends { value: number } | null>(plots: readonly T[]): Exclude<T, null>[][] {\n const segments: Exclude<T, null>[][] = [];\n let current: Exclude<T, null>[] = [];\n for (const plot of plots) {\n if (plot === null) { if (current.length) segments.push(current); current = []; continue; }\n current.push(plot as Exclude<T, null>);\n }\n if (current.length) segments.push(current);\n return segments;\n}\n\n// ---------------------------------------------------------------------------------------------\n// Cartesian: line / area\n// ---------------------------------------------------------------------------------------------\n\nexport type LineGeometryInput = Readonly<{\n categories: readonly string[];\n series: readonly ChartSeries[];\n width: number;\n height: number;\n insets?: ChartInsets;\n invert?: boolean;\n stacked?: boolean;\n} & ChartDomainOptions>;\n\nexport type LineGeometry = Readonly<{\n plot: Readonly<{ left: number; right: number; top: number; bottom: number }>;\n domain: readonly [number, number];\n ticks: readonly number[];\n xs: readonly number[];\n y(value: number): number;\n /** Per series, per category: the plotted point or null for a gap. */\n plots: readonly (readonly (ChartPlot | null)[])[];\n /** Stacked areas: the lower edge per series (previous cumulative). */\n lower: readonly (readonly (ChartPlot | null)[])[] | null;\n}>;\n\nexport function resolveLineGeometry({ categories, series, width, height, insets = chartRecipe.insets.plot, invert = false, stacked = false, ...domainOptions }: LineGeometryInput): LineGeometry {\n validateChartSeries(categories, series);\n const plot = { left: insets.left, right: width - insets.right, top: insets.top, bottom: height - insets.bottom };\n const totals = stacked ? stackValues(series) : null;\n const domainValues = totals ? totals.flatMap(row => row.map(cell => cell?.[1] ?? null)) : series.flatMap(item => item.values);\n const domain = resolveChartDomain(domainValues, { includeZero: stacked || domainOptions.includeZero, ...domainOptions });\n const y = scaleLinear(domain, [plot.bottom, plot.top], invert);\n const xs = pointPositions(categories.length, [plot.left, plot.right]);\n const plots = series.map((item, s) => item.values.map((value, i) => {\n const top = totals ? totals[s]![i]?.[1] : value;\n return isChartNumber(value) && isChartNumber(top) ? { index: i, seriesIndex: s, x: xs[i]!, y: y(top), value } : null;\n }));\n const lower = totals ? series.map((_, s) => categories.map((__, i) => { const cell = totals[s]![i]; return cell ? { index: i, seriesIndex: s, x: xs[i]!, y: y(cell[0]), value: cell[0] } : null; })) : null;\n return { plot, domain, ticks: niceTicks(domain[0], domain[1], 4), xs, y, plots, lower };\n}\n\n/** Cumulative [lower, upper] per series per category; missing values do not add to the stack. */\nexport function stackValues(series: readonly ChartSeries[]): (readonly [number, number] | null)[][] {\n const length = series[0]?.values.length ?? 0, positive = new Array<number>(length).fill(0), negative = new Array<number>(length).fill(0);\n return series.map(item => item.values.map((value, i) => {\n if (!isChartNumber(value)) return null;\n const base = value >= 0 ? positive[i]! : negative[i]!, top = base + value;\n if (value >= 0) positive[i] = top; else negative[i] = top;\n return [base, top] as const;\n }));\n}\n\n// ---------------------------------------------------------------------------------------------\n// Cartesian: bars\n// ---------------------------------------------------------------------------------------------\n\nexport type ChartBar = Readonly<{ index: number; seriesIndex: number; value: number; x: number; y: number; width: number; height: number }>;\nexport type BarGeometryInput = Readonly<{\n categories: readonly string[];\n series: readonly ChartSeries[];\n width: number;\n height: number;\n insets?: ChartInsets;\n orientation?: ChartOrientation;\n layout?: ChartBarLayout;\n} & ChartDomainOptions>;\nexport type BarGeometry = Readonly<{\n plot: Readonly<{ left: number; right: number; top: number; bottom: number }>;\n domain: readonly [number, number];\n ticks: readonly number[];\n bars: readonly ChartBar[];\n /** Category band centers along the category axis (x for vertical, y for horizontal). */\n centers: readonly number[];\n value(value: number): number;\n}>;\n\nexport function resolveBarGeometry({ categories, series, width, height, insets = chartRecipe.insets.plot, orientation = \"vertical\", layout = \"grouped\", ...domainOptions }: BarGeometryInput): BarGeometry {\n validateChartSeries(categories, series);\n const plot = { left: insets.left, right: width - insets.right, top: insets.top, bottom: height - insets.bottom };\n const stacks = layout === \"stacked\" ? stackValues(series) : null;\n const values = stacks ? stacks.flatMap(row => row.flatMap(cell => cell ? [cell[0], cell[1]] : [])) : series.flatMap(item => item.values);\n const domain = resolveChartDomain(values, { includeZero: true, ...domainOptions });\n const vertical = orientation === \"vertical\";\n const valueScale = vertical ? scaleLinear(domain, [plot.bottom, plot.top]) : scaleLinear(domain, [plot.left, plot.right]);\n const band = scaleBand(categories.length, vertical ? [plot.left, plot.right] : [plot.top, plot.bottom]);\n const thickness = Math.min(chartRecipe.bar.maxWidth * (layout === \"grouped\" ? series.length : 1), band.bandwidth);\n const each = layout === \"grouped\" ? Math.max(1, (thickness - chartRecipe.bar.groupGap * (series.length - 1)) / series.length) : thickness;\n const bars: ChartBar[] = [];\n series.forEach((item, s) => item.values.forEach((value, i) => {\n if (!isChartNumber(value)) return;\n const [from, to] = stacks ? stacks[s]![i]! : [0, value];\n const a = valueScale(from), b = valueScale(to);\n const offset = band.center(i) - thickness / 2 + (layout === \"grouped\" ? s * (each + chartRecipe.bar.groupGap) : 0);\n bars.push(vertical\n ? { index: i, seriesIndex: s, value, x: offset, y: Math.min(a, b), width: each, height: Math.max(1, Math.abs(a - b)) }\n : { index: i, seriesIndex: s, value, x: Math.min(a, b), y: offset, width: Math.max(1, Math.abs(a - b)), height: each });\n }));\n return { plot, domain, ticks: niceTicks(domain[0], domain[1], 4), bars, centers: categories.map((_, i) => band.center(i)), value: valueScale };\n}\n\n// ---------------------------------------------------------------------------------------------\n// Polar: pie / donut / radar\n// ---------------------------------------------------------------------------------------------\n\nexport type PieSlice = Readonly<{ index: number; value: number; percent: number; startAngle: number; endAngle: number; path: string; centroid: XY }>;\nconst polar = (cx: number, cy: number, r: number, angle: number): XY => ({ x: cx + r * Math.sin(angle), y: cy - r * Math.cos(angle) });\n\n/** Annular sector from 12 o'clock clockwise. `innerRadius` 0 draws a pie wedge. */\nexport function arcPath(cx: number, cy: number, outerRadius: number, innerRadius: number, startAngle: number, endAngle: number): string {\n const sweep = endAngle - startAngle;\n if (sweep >= Math.PI * 2 - 1e-6) {\n // A full circle cannot be one arc command; draw two halves.\n const mid = startAngle + Math.PI;\n return arcPath(cx, cy, outerRadius, innerRadius, startAngle, mid) + arcPath(cx, cy, outerRadius, innerRadius, mid, endAngle);\n }\n const large = sweep > Math.PI ? 1 : 0;\n const o0 = polar(cx, cy, outerRadius, startAngle), o1 = polar(cx, cy, outerRadius, endAngle);\n if (innerRadius <= 0) return `M${fixed(cx)},${fixed(cy)}L${fixed(o0.x)},${fixed(o0.y)}A${fixed(outerRadius)},${fixed(outerRadius)} 0 ${large} 1 ${fixed(o1.x)},${fixed(o1.y)}Z`;\n const i1 = polar(cx, cy, innerRadius, endAngle), i0 = polar(cx, cy, innerRadius, startAngle);\n return `M${fixed(o0.x)},${fixed(o0.y)}A${fixed(outerRadius)},${fixed(outerRadius)} 0 ${large} 1 ${fixed(o1.x)},${fixed(o1.y)}L${fixed(i1.x)},${fixed(i1.y)}A${fixed(innerRadius)},${fixed(innerRadius)} 0 ${large} 0 ${fixed(i0.x)},${fixed(i0.y)}Z`;\n}\n\n/** Negative and missing values are excluded: a share of a whole cannot be negative. */\nexport function resolvePieGeometry(values: readonly ChartValue[], { cx, cy, radius: outer, innerRadius = 0, padAngle = chartRecipe.pie.padAngle }: Readonly<{ cx: number; cy: number; radius: number; innerRadius?: number; padAngle?: number }>): PieSlice[] {\n const total = values.reduce<number>((sum, value) => sum + (isChartNumber(value) && value > 0 ? value : 0), 0);\n if (total <= 0) return [];\n let angle = 0;\n const slices: PieSlice[] = [];\n values.forEach((value, index) => {\n if (!isChartNumber(value) || value <= 0) return;\n const sweep = value / total * Math.PI * 2, pad = slices.length || sweep < Math.PI * 2 ? Math.min(padAngle, sweep / 4) : 0;\n const start = angle + pad / 2, end = angle + sweep - pad / 2, mid = (start + end) / 2;\n slices.push({ index, value, percent: value / total * 100, startAngle: start, endAngle: end, path: arcPath(cx, cy, outer, innerRadius, start, end), centroid: polar(cx, cy, innerRadius > 0 ? (outer + innerRadius) / 2 : outer * 0.62, mid) });\n angle += sweep;\n });\n return slices;\n}\n\nexport type RadarAxis = Readonly<{ index: number; label: string; angle: number; end: XY; labelAt: XY; anchor: \"start\" | \"middle\" | \"end\" }>;\nexport type RadarGeometry = Readonly<{ axes: readonly RadarAxis[]; rings: readonly string[]; polygons: readonly Readonly<{ seriesIndex: number; path: string; points: readonly (XY & { index: number; value: number | null })[] }>[] }>;\n/**\n * Radar (spider) chart. All axes share one domain (0..max by default) because the products'\n * ratings are on one 0–100 scale; per-axis scales would make the polygon area meaningless.\n */\nexport function resolveRadarGeometry({ categories, series, cx, cy, radius: outer, domain, levels = chartRecipe.radar.levels, labelOffset = chartRecipe.radar.labelOffset }: Readonly<{ categories: readonly string[]; series: readonly ChartSeries[]; cx: number; cy: number; radius: number; domain?: readonly [number, number]; levels?: number; labelOffset?: number }>): RadarGeometry {\n validateChartSeries(categories, series);\n if (categories.length < 3) throw new RangeError(\"Radar chart needs at least three axes\");\n const [min, max] = domain ?? [0, Math.max(...series.flatMap(item => item.values.filter(isChartNumber)), 1)];\n const step = Math.PI * 2 / categories.length;\n const axes = categories.map((label, index) => {\n const angle = index * step, end = polar(cx, cy, outer, angle), labelAt = polar(cx, cy, outer + labelOffset, angle);\n const sin = Math.sin(angle);\n return { index, label, angle, end, labelAt, anchor: Math.abs(sin) < 0.2 ? \"middle\" as const : sin > 0 ? \"start\" as const : \"end\" as const };\n });\n const rings = Array.from({ length: levels }, (_, level) => {\n const r = outer * (level + 1) / levels;\n return axes.map((axis, i) => { const p = polar(cx, cy, r, axis.angle); return `${i ? \"L\" : \"M\"}${fixed(p.x)},${fixed(p.y)}`; }).join(\"\") + \"Z\";\n });\n const polygons = series.map((item, seriesIndex) => {\n const points = axes.map(axis => {\n const value = item.values[axis.index] ?? null;\n const ratio = isChartNumber(value) ? Math.max(0, Math.min(1, (value - min) / ((max - min) || 1))) : 0;\n return { ...polar(cx, cy, outer * ratio, axis.angle), index: axis.index, value: isChartNumber(value) ? value : null };\n });\n return { seriesIndex, points, path: points.map((p, i) => `${i ? \"L\" : \"M\"}${fixed(p.x)},${fixed(p.y)}`).join(\"\") + \"Z\" };\n });\n return { axes, rings, polygons };\n}\n\n// ---------------------------------------------------------------------------------------------\n// Scatter\n// ---------------------------------------------------------------------------------------------\n\nexport type ScatterDatum = Readonly<{ id: string; label: string; x: number; y: number; seriesIndex?: number }>;\nexport type ScatterGeometry = Readonly<{\n plot: Readonly<{ left: number; right: number; top: number; bottom: number }>;\n xDomain: readonly [number, number]; yDomain: readonly [number, number];\n xTicks: readonly number[]; yTicks: readonly number[];\n points: readonly (ScatterDatum & { px: number; py: number })[];\n}>;\nexport function resolveScatterGeometry({ points, width, height, insets = chartRecipe.insets.axis, xDomain, yDomain }: Readonly<{ points: readonly ScatterDatum[]; width: number; height: number; insets?: ChartInsets; xDomain?: readonly [number, number]; yDomain?: readonly [number, number] }>): ScatterGeometry {\n const plot = { left: insets.left, right: width - insets.right, top: insets.top, bottom: height - insets.bottom };\n const xd = resolveChartDomain(points.map(p => p.x), { domain: xDomain, padding: 0.06 }), yd = resolveChartDomain(points.map(p => p.y), { domain: yDomain, padding: 0.06 });\n const sx = scaleLinear(xd, [plot.left, plot.right]), sy = scaleLinear(yd, [plot.bottom, plot.top]);\n return { plot, xDomain: xd, yDomain: yd, xTicks: niceTicks(xd[0], xd[1], 4), yTicks: niceTicks(yd[0], yd[1], 4), points: points.map(p => ({ ...p, px: sx(p.x), py: sy(p.y) })) };\n}\n\n// ---------------------------------------------------------------------------------------------\n// Focus (scrub / press) and accessibility\n// ---------------------------------------------------------------------------------------------\n\n/** Category index whose x is closest to a pointer x, among categories that have any value. */\nexport function nearestChartIndex(xs: readonly number[], x: number, available?: readonly number[]): number | null {\n const candidates = available ?? xs.map((_, i) => i);\n let best: number | null = null, distance = Infinity;\n for (const index of candidates) {\n const d = Math.abs(xs[index]! - x);\n if (d < distance) { distance = d; best = index; }\n }\n return best;\n}\nexport function nearestScatterPoint(points: readonly Readonly<{ px: number; py: number }>[], x: number, y: number, maxDistance = 32): number | null {\n let best: number | null = null, distance = maxDistance * maxDistance;\n points.forEach((p, i) => { const d = (p.px - x) ** 2 + (p.py - y) ** 2; if (d <= distance) { distance = d; best = i; } });\n return best;\n}\n/** Adjustable-role step (VoiceOver swipe, arrow keys) over observed indices only. */\nexport function stepChartIndex(available: readonly number[], current: number | null, direction: 1 | -1): number | null {\n if (!available.length) return null;\n if (current === null) return direction > 0 ? available[0]! : available.at(-1)!;\n const position = available.indexOf(current);\n return available[Math.min(available.length - 1, Math.max(0, (position < 0 ? 0 : position) + direction))]!;\n}\nexport function observedIndices(series: readonly ChartSeries[]): number[] {\n const length = series[0]?.values.length ?? 0;\n return Array.from({ length }, (_, i) => i).filter(i => series.some(item => isChartNumber(item.values[i])));\n}\n/** Index of the highest and lowest observation of one series (stock-chart high/low markers). */\nexport function seriesExtremes(values: readonly ChartValue[]): Readonly<{ max: number; min: number }> | null {\n let max = -1, min = -1;\n values.forEach((value, i) => {\n if (!isChartNumber(value)) return;\n if (max < 0 || value > values[max]!) max = i;\n if (min < 0 || value < values[min]!) min = i;\n });\n return max < 0 ? null : { max, min };\n}\n\n/**\n * Text alternative for an image-like chart: every category's values in order, product-formatted.\n * Products pass localized `format`; HJM never formats numbers into a language itself.\n */\nexport function describeChart(categories: readonly string[], series: readonly ChartSeries[], format: (value: number) => string, missing: string): string {\n return series.map(item => `${item.label}: ${categories.map((category, i) => { const v = item.values[i]; return `${category} ${isChartNumber(v) ? format(v) : missing}`; }).join(\", \")}`).join(\". \");\n}\n\nexport const chartBehavior = {\n controlled: [\"focusIndex\"],\n inputs: [\"categories\", \"series\", \"kind\", \"orientation\", \"layout\", \"domain\", \"invert\", \"curve\"],\n events: [\"onFocusChange\"],\n configuration: { curve: [\"linear\", \"monotone\", \"step\"], orientation: [\"vertical\", \"horizontal\"], layout: [\"grouped\", \"stacked\"] },\n defaults: { curve: \"linear\", orientation: \"vertical\", layout: \"grouped\" },\n stateAxes: { value: [\"focused\", \"scrubbing\"], content: [\"idle\", \"empty\"] },\n web: { roles: [\"img\", \"slider\"], keyboard: [\"ArrowLeft\", \"ArrowRight\", \"Home\", \"End\"], focus: \"native\" },\n native: { roles: [\"adjustable\", \"image\"], states: [], actions: [\"increment\", \"decrement\"] },\n scenarios: [\n \"missing-values-split-the-line-instead-of-drawing-zero\",\n \"bars-and-stacks-always-include-a-zero-baseline\",\n \"inverted-scale-puts-the-best-rank-on-top\",\n \"scrubbing-reports-the-focused-index-and-releasing-restores-the-latest\",\n \"the-focused-point-is-reachable-without-a-drag-via-adjustable-or-arrow-keys\",\n \"series-colors-come-from-the-product-or-the-dataviz-palette-never-status-colors\",\n \"every-chart-exposes-a-product-formatted-text-alternative\",\n \"radar-axes-share-one-domain\",\n \"pie-slices-ignore-negative-and-missing-values\",\n ],\n} as const satisfies BehaviorContract;\n\n/** Excluding a slice changes the denominator; selecting one only emphasizes it (Lucian 097). */\nexport function resolvePieVisibility(data: readonly Readonly<{ id: string; value: number | null }>[], excludedIds: readonly string[] = []) {\n const ids = new Set(data.map(datum => datum.id)), excluded = new Set(excludedIds);\n if (ids.size !== data.length || data.some(datum => !datum.id.trim())) throw new TypeError(\"Pie data requires distinct nonempty ids\");\n if (excluded.size !== excludedIds.length || excludedIds.some(id => !ids.has(id))) throw new TypeError(\"Excluded pie ids must be distinct known ids\");\n // Keep the existing geometry contract: negative/nonfinite/missing values never enter a share.\n const values = data.map(datum => excluded.has(datum.id) || !isChartNumber(datum.value) || datum.value < 0 ? null : datum.value);\n const total = values.reduce<number>((sum, value) => sum + (value ?? 0), 0);\n if (!Number.isFinite(total)) throw new RangeError(\"Pie total must be finite\");\n return { values, total, includedCount: data.length - excluded.size, observedCount: values.filter(value => value !== null).length };\n}\nexport type PieVisibilitySummary = ReturnType<typeof resolvePieVisibility>;\n\n/** Match both actual polyline vertices before period morphing. Union knots preserve\n * every observation for linear paths; work is bounded by the caller for large data. */\nexport function prepareChartLineMorph(from: readonly XY[], to: readonly XY[]) {\n if (from.length < 2 || to.length < 2) return null;\n const knots = [...new Set([...from.map((_, i) => i / (from.length - 1)), ...to.map((_, i) => i / (to.length - 1))])].sort((a, b) => a - b);\n const sample = (points: readonly XY[], position: number): XY => {\n const index = position * (points.length - 1), start = Math.floor(index), end = Math.min(points.length - 1, start + 1), t = index - start;\n return { x: points[start]!.x + (points[end]!.x - points[start]!.x) * t, y: points[start]!.y + (points[end]!.y - points[start]!.y) * t };\n };\n const first = knots.map(k => sample(from, k)), last = knots.map(k => sample(to, k));\n return (progress: number): XY[] => {\n const t = Math.max(0, Math.min(1, progress));\n return first.map((point, i) => ({ x: point.x + (last[i]!.x - point.x) * t, y: point.y + (last[i]!.y - point.y) * t }));\n };\n}\n"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lucian #033/#092/#131/#144/#178 informed these compositions, not their demo state engines.
|
|
3
|
+
* Reuse FieldGroup, ActionSession and controlled table columns; products own data and persistence.
|
|
4
|
+
*/
|
|
5
|
+
export declare const collectionEditingRecipe: {
|
|
6
|
+
readonly gap: "md";
|
|
7
|
+
readonly actionGap: "sm";
|
|
8
|
+
};
|
|
9
|
+
export type ColumnSetting = Readonly<{
|
|
10
|
+
id: string;
|
|
11
|
+
label: string;
|
|
12
|
+
visible: boolean;
|
|
13
|
+
locked?: boolean;
|
|
14
|
+
}>;
|
|
15
|
+
export type FilterRecoveryOption = Readonly<{
|
|
16
|
+
id: string;
|
|
17
|
+
label: string;
|
|
18
|
+
resultCount: number;
|
|
19
|
+
}>;
|
|
20
|
+
export type SelectionAction = Readonly<{
|
|
21
|
+
id: string;
|
|
22
|
+
label: string;
|
|
23
|
+
destructive?: boolean;
|
|
24
|
+
}>;
|
|
25
|
+
export type FocusTarget = {
|
|
26
|
+
focus(): void;
|
|
27
|
+
};
|
|
28
|
+
export declare function assertDistinctIds(items: readonly Readonly<{
|
|
29
|
+
id: string;
|
|
30
|
+
}>[]): void;
|
|
31
|
+
/** A mutation gets its own immutable scope; a later selection never changes an in-flight request. */
|
|
32
|
+
export declare function snapshotSelection(ids: readonly string[]): readonly string[];
|
|
33
|
+
/** Focus the next surviving row, then the preceding row, then the add action. */
|
|
34
|
+
export declare function focusAfterRemoval(ids: readonly string[], removed: string, disabledIds?: readonly string[]): string | undefined;
|
|
35
|
+
export declare function recoverableFilters(options: readonly FilterRecoveryOption[]): readonly FilterRecoveryOption[];
|
|
36
|
+
/** Locked columns are barriers: a visibility/order UI must not silently move a fixed column. */
|
|
37
|
+
export declare function changeColumnSettings(columns: readonly ColumnSetting[], id: string, action: "toggle" | "earlier" | "later"): readonly ColumnSetting[];
|
|
38
|
+
//# sourceMappingURL=collection-editing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection-editing.d.ts","sourceRoot":"","sources":["../src/collection-editing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,uBAAuB;;;CAA0C,CAAC;AAC/E,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AACxG,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAChG,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAC7F,MAAM,MAAM,WAAW,GAAG;IAAE,KAAK,IAAI,IAAI,CAAA;CAAE,CAAC;AAE5C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,QAAQ,CAAC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,GAAG,IAAI,CAMlF;AAED,qGAAqG;AACrG,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,CAG3E;AAED,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAE,SAAS,MAAM,EAAO,GAAG,MAAM,GAAG,SAAS,CAKlI;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,SAAS,oBAAoB,EAAE,GAAG,SAAS,oBAAoB,EAAE,CAM5G;AAED,gGAAgG;AAChG,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,aAAa,EAAE,CAapJ"}
|