@lamatemaga/sterling 0.1.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/server.js ADDED
@@ -0,0 +1,1666 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/server.ts
21
+ var server_exports = {};
22
+ __export(server_exports, {
23
+ AXIS_TITLE: () => AXIS_TITLE,
24
+ AxisBottom: () => AxisBottom,
25
+ AxisLeft: () => AxisLeft,
26
+ Gridlines: () => Gridlines,
27
+ SterlingBarChart: () => SterlingBarChart,
28
+ SterlingBoxPlot: () => SterlingBoxPlot,
29
+ SterlingCandlestickChart: () => SterlingCandlestickChart,
30
+ SterlingChordChart: () => SterlingChordChart,
31
+ SterlingCorrelogram: () => SterlingCorrelogram,
32
+ SterlingDendrogramChart: () => SterlingDendrogramChart,
33
+ SterlingDensity2DChart: () => SterlingDensity2DChart,
34
+ SterlingDensityChart: () => SterlingDensityChart,
35
+ SterlingDonutChart: () => SterlingDonutChart,
36
+ SterlingDumbbellChart: () => SterlingDumbbellChart,
37
+ SterlingExpressionChart: () => SterlingExpressionChart,
38
+ SterlingGeoMapChart: () => SterlingGeoMapChart,
39
+ SterlingHeatmap: () => SterlingHeatmap,
40
+ SterlingHistogram: () => SterlingHistogram,
41
+ SterlingInlineLegend: () => SterlingInlineLegend,
42
+ SterlingLineChart: () => SterlingLineChart,
43
+ SterlingLollipopChart: () => SterlingLollipopChart,
44
+ SterlingManhattanChart: () => SterlingManhattanChart,
45
+ SterlingNetworkChart: () => SterlingNetworkChart,
46
+ SterlingPieChart: () => SterlingPieChart,
47
+ SterlingRadarChart: () => SterlingRadarChart,
48
+ SterlingRidgelineChart: () => SterlingRidgelineChart,
49
+ SterlingSankeyChart: () => SterlingSankeyChart,
50
+ SterlingScatterPlot: () => SterlingScatterPlot,
51
+ SterlingSequentialSurface: () => SterlingSequentialSurface,
52
+ SterlingTreemapChart: () => SterlingTreemapChart,
53
+ SterlingVerticalBarChart: () => SterlingVerticalBarChart,
54
+ SterlingViolinPlot: () => SterlingViolinPlot,
55
+ SterlingVolcanoChart: () => SterlingVolcanoChart,
56
+ TICK: () => TICK,
57
+ TICK_LABEL: () => TICK_LABEL,
58
+ TimeAxisBottom: () => TimeAxisBottom,
59
+ axisGrid: () => axisGrid,
60
+ axisLine: () => axisLine,
61
+ axisMuted: () => axisMuted,
62
+ axisText: () => axisText,
63
+ bandCenters: () => bandCenters,
64
+ createTailwindSterlingPalette: () => createTailwindSterlingPalette,
65
+ defaultMargin: () => defaultMargin,
66
+ defineSterlingPalette: () => defineSterlingPalette,
67
+ divergentSignedColor: () => divergentSignedColor,
68
+ divergentSignedRamp: () => divergentSignedRamp,
69
+ frame: () => frame,
70
+ inferSterlingDataExport: () => inferSterlingDataExport,
71
+ kernelDensity: () => kernelDensity,
72
+ linearScale: () => linearScale,
73
+ sterlingCategorical: () => sterlingCategorical,
74
+ sterlingChartColors: () => sterlingChartColors,
75
+ sterlingColorNames: () => sterlingColorNames,
76
+ sterlingCredit: () => sterlingCredit,
77
+ sterlingDivergentColors: () => sterlingDivergentColors,
78
+ sterlingHeatColors: () => sterlingHeatColors,
79
+ sterlingLegendColors: () => sterlingLegendColors,
80
+ sterlingPaletteStyle: () => sterlingPaletteStyle,
81
+ sterlingRamp: () => sterlingRamp,
82
+ sterlingRampStops: () => sterlingRampStops,
83
+ sterlingRowsToCsv: () => sterlingRowsToCsv,
84
+ sterlingSequentialColors: () => sterlingSequentialColors,
85
+ sterlingVisualStyle: () => sterlingVisualStyle,
86
+ timeScale: () => timeScale,
87
+ tukeySummary: () => tukeySummary
88
+ });
89
+ module.exports = __toCommonJS(server_exports);
90
+
91
+ // src/palette.ts
92
+ function defineSterlingPalette(palette) {
93
+ return palette;
94
+ }
95
+ function sterlingPaletteStyle(palette) {
96
+ const variables = {};
97
+ if (!palette) return variables;
98
+ const surfaceTokens = {
99
+ paper: "paper",
100
+ plot: "surface",
101
+ plotAlt: "surface-2",
102
+ text: "text",
103
+ muted: "muted",
104
+ grid: "grid",
105
+ edge: "edge",
106
+ period: "period"
107
+ };
108
+ for (const [key, value] of Object.entries(palette.surface ?? {})) {
109
+ if (value) variables[`--sterling-${surfaceTokens[key]}`] = value;
110
+ }
111
+ const assignSeries = (name, values) => {
112
+ values?.forEach((value, index) => {
113
+ if (value) variables[`--sterling-${name}-${index + 1}`] = value;
114
+ });
115
+ };
116
+ assignSeries("cat", palette.categorical);
117
+ assignSeries("legend", palette.legend);
118
+ assignSeries("seq", palette.sequential);
119
+ assignSeries("div", palette.divergent);
120
+ assignSeries("heat", palette.heat);
121
+ palette.ramps?.forEach((ramp, familyIndex) => {
122
+ ramp.forEach((value, stopIndex) => {
123
+ if (value) variables[`--sterling-ramp-${familyIndex + 1}-${stopIndex + 1}`] = value;
124
+ });
125
+ });
126
+ return variables;
127
+ }
128
+ var sterlingCategorical = {
129
+ light: [
130
+ "#9A79E7",
131
+ "#25A08D",
132
+ "#D45AC7",
133
+ "#E4A43A",
134
+ "#5A83D7",
135
+ "#E87864",
136
+ "#96AB51",
137
+ "#536B78"
138
+ ],
139
+ dark: [
140
+ "#B69AF2",
141
+ "#5EC9AE",
142
+ "#E88BDD",
143
+ "#F2C46D",
144
+ "#86A8E8",
145
+ "#F29A88",
146
+ "#B7C974",
147
+ "#B7C8D1"
148
+ ],
149
+ print: [
150
+ "#8E68D8",
151
+ "#218C7C",
152
+ "#C653BC",
153
+ "#D39A32",
154
+ "#4F73C6",
155
+ "#DC6A55",
156
+ "#879347",
157
+ "#607986"
158
+ ]
159
+ };
160
+ var sterlingColorNames = [
161
+ "Violet",
162
+ "Teal",
163
+ "Orchid",
164
+ "Amber",
165
+ "Blue",
166
+ "Coral",
167
+ "Moss",
168
+ "Payne"
169
+ ];
170
+ var sterlingChartColors = sterlingColorNames.map(
171
+ (_, index) => `var(--sterling-cat-${index + 1})`
172
+ );
173
+ var sterlingLegendColors = sterlingColorNames.map(
174
+ (_, index) => `var(--sterling-legend-${index + 1})`
175
+ );
176
+ var sterlingDivergentColors = Array.from(
177
+ { length: 11 },
178
+ (_, index) => `var(--sterling-div-${index + 1})`
179
+ );
180
+ var sterlingSequentialColors = Array.from(
181
+ { length: 10 },
182
+ (_, index) => `var(--sterling-seq-${index + 1})`
183
+ );
184
+ var sterlingHeatColors = Array.from(
185
+ { length: 11 },
186
+ (_, index) => `var(--sterling-heat-${index + 1})`
187
+ );
188
+ var sterlingRampStops = 7;
189
+ function sterlingRamp(family, stop) {
190
+ const familyIndex = (family % sterlingColorNames.length + sterlingColorNames.length) % sterlingColorNames.length;
191
+ const clamped = Math.max(1, Math.min(sterlingRampStops, Math.round(stop)));
192
+ return `var(--sterling-ramp-${familyIndex + 1}-${clamped})`;
193
+ }
194
+
195
+ // src/SterlingLegend.tsx
196
+ var import_jsx_runtime = require("react/jsx-runtime");
197
+ function LegendMark({ shape = "circle" }) {
198
+ if (shape === "square") {
199
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "2", y: "2", width: "8", height: "8", rx: "1" });
200
+ }
201
+ if (shape === "triangle") {
202
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M 6 1 L 11 10 L 1 10 Z" });
203
+ }
204
+ if (shape === "line") {
205
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M 1 6 H 11", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" });
206
+ }
207
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "6", cy: "6", r: "4.5" });
208
+ }
209
+ function SterlingInlineLegend({
210
+ items,
211
+ locale
212
+ }) {
213
+ const parts = new Intl.ListFormat(locale, {
214
+ style: "long",
215
+ type: "conjunction"
216
+ }).formatToParts(items.map((item) => item.label));
217
+ let itemIndex = 0;
218
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sterling-inline-legend", children: parts.map((part, partIndex) => {
219
+ if (part.type !== "element") {
220
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: part.value }, `literal-${partIndex}`);
221
+ }
222
+ const item = items[itemIndex++];
223
+ const colorIndex = Math.max(0, Math.min(sterlingChartColors.length - 1, item.colorIndex ?? 0));
224
+ const style = {
225
+ "--sterling-legend-mark": item.color ?? sterlingChartColors[colorIndex],
226
+ "--sterling-legend-text": item.textColor ?? sterlingLegendColors[colorIndex]
227
+ };
228
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "sterling-inline-legend__item", style, children: [
229
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 12 12", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LegendMark, { shape: item.shape }) }),
230
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: item.label })
231
+ ] }, `${item.label}-${partIndex}`);
232
+ }) });
233
+ }
234
+
235
+ // src/charts.tsx
236
+ var import_d3_chord = require("d3-chord");
237
+ var import_d3_sankey = require("d3-sankey");
238
+ var import_d3_shape = require("d3-shape");
239
+
240
+ // src/plot.tsx
241
+ var import_d3_scale = require("d3-scale");
242
+
243
+ // src/visualStyle.ts
244
+ var sterlingVisualStyle = {
245
+ stroke: {
246
+ grid: 1,
247
+ detail: 1.5,
248
+ candle: 1.75,
249
+ mark: 2,
250
+ series: 2.25,
251
+ emphasis: 2.5,
252
+ interval: 7,
253
+ halo: 3,
254
+ ring: 44,
255
+ flowMinimum: 1
256
+ },
257
+ opacity: {
258
+ ghost: 0.04,
259
+ contour: 0.08,
260
+ surface: 0.1,
261
+ area: 0.24,
262
+ ridge: 0.34,
263
+ interval: 0.28,
264
+ relationship: 0.42,
265
+ secondaryMark: 0.66,
266
+ guide: 0.7,
267
+ signal: 0.84,
268
+ mutedMark: 0.34
269
+ }
270
+ };
271
+
272
+ // src/plot.tsx
273
+ var import_jsx_runtime2 = require("react/jsx-runtime");
274
+ var axisText = "var(--sterling-text)";
275
+ var axisMuted = "var(--sterling-muted)";
276
+ var axisGrid = "var(--sterling-grid)";
277
+ var axisLine = "var(--sterling-edge)";
278
+ var MONO = "var(--font-mono)";
279
+ var TICK = 5;
280
+ var TICK_LABEL = 11;
281
+ var AXIS_TITLE = 12;
282
+ var defaultMargin = { top: 26, right: 26, bottom: 56, left: 70 };
283
+ function frame(width, height, margin = defaultMargin) {
284
+ return {
285
+ width,
286
+ height,
287
+ x0: margin.left,
288
+ x1: width - margin.right,
289
+ y0: margin.top,
290
+ y1: height - margin.bottom
291
+ };
292
+ }
293
+ function linearScale(values, range, { zero = false, padFraction = 0.05 } = {}) {
294
+ let min = Math.min(...values);
295
+ let max = Math.max(...values);
296
+ if (!Number.isFinite(min) || !Number.isFinite(max)) {
297
+ min = 0;
298
+ max = 1;
299
+ }
300
+ if (min === max) {
301
+ const bump = Math.abs(min) || 1;
302
+ min -= bump;
303
+ max += bump;
304
+ }
305
+ if (zero) {
306
+ min = Math.min(0, min);
307
+ max = Math.max(0, max);
308
+ } else {
309
+ const pad = (max - min) * padFraction;
310
+ min -= pad;
311
+ max += pad;
312
+ }
313
+ return (0, import_d3_scale.scaleLinear)().domain([min, max]).nice().range(range);
314
+ }
315
+ function timeScale(domain, range) {
316
+ return (0, import_d3_scale.scaleTime)().domain(domain).range(range).nice();
317
+ }
318
+ function tickValues(scale, count) {
319
+ return scale.ticks(count);
320
+ }
321
+ function Gridlines({
322
+ scale,
323
+ x0,
324
+ x1,
325
+ count = 5
326
+ }) {
327
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("g", { "aria-hidden": "true", children: tickValues(scale, count).map((value) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: x0, x2: x1, y1: scale(value), y2: scale(value), stroke: axisGrid, strokeWidth: sterlingVisualStyle.stroke.grid }, value)) });
328
+ }
329
+ function AxisLeft({
330
+ scale,
331
+ x,
332
+ gridX1,
333
+ count = 5,
334
+ title,
335
+ format
336
+ }) {
337
+ const values = tickValues(scale, count);
338
+ const fmt = format ?? ((value) => scale.tickFormat(count)(value));
339
+ const [yBottom, yTop] = scale.range();
340
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
341
+ gridX1 !== void 0 ? values.map((value) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: x, x2: gridX1, y1: scale(value), y2: scale(value), stroke: axisGrid, strokeWidth: sterlingVisualStyle.stroke.grid }, `g${value}`)) : null,
342
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: x, x2: x, y1: yBottom, y2: yTop, stroke: axisLine }),
343
+ values.map((value) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
344
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: x - TICK, x2: x, y1: scale(value), y2: scale(value), stroke: axisLine }),
345
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("text", { x: x - TICK - 4, y: scale(value) + 3.6, textAnchor: "end", fill: axisMuted, fontSize: TICK_LABEL, fontFamily: MONO, children: fmt(value) })
346
+ ] }, value)),
347
+ title ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
348
+ "text",
349
+ {
350
+ transform: `translate(${x - 48} ${(yBottom + yTop) / 2}) rotate(-90)`,
351
+ textAnchor: "middle",
352
+ fill: axisMuted,
353
+ fontSize: AXIS_TITLE,
354
+ fontFamily: MONO,
355
+ children: title
356
+ }
357
+ ) : null
358
+ ] });
359
+ }
360
+ function AxisBottom({
361
+ scale,
362
+ y,
363
+ count = 6,
364
+ title,
365
+ format,
366
+ titleGap = 42
367
+ }) {
368
+ const values = tickValues(scale, count);
369
+ const fmt = format ?? ((value) => scale.tickFormat(count)(value));
370
+ const [x0, x1] = scale.range();
371
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
372
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: x0, x2: x1, y1: y, y2: y, stroke: axisLine }),
373
+ values.map((value) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
374
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: scale(value), x2: scale(value), y1: y, y2: y + TICK, stroke: axisLine }),
375
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("text", { x: scale(value), y: y + TICK + 13, textAnchor: "middle", fill: axisMuted, fontSize: TICK_LABEL, fontFamily: MONO, children: fmt(value) })
376
+ ] }, value)),
377
+ title ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("text", { x: (x0 + x1) / 2, y: y + titleGap, textAnchor: "middle", fill: axisMuted, fontSize: AXIS_TITLE, fontFamily: MONO, children: title }) : null
378
+ ] });
379
+ }
380
+ function TimeAxisBottom({
381
+ scale,
382
+ y,
383
+ title,
384
+ targetPx = 96,
385
+ titleGap = 42
386
+ }) {
387
+ const [x0, x1] = scale.range();
388
+ const count = Math.max(2, Math.round((x1 - x0) / targetPx));
389
+ const values = scale.ticks(count);
390
+ const fmt = scale.tickFormat(count);
391
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
392
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: x0, x2: x1, y1: y, y2: y, stroke: axisLine }),
393
+ values.map((value) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
394
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: scale(value), x2: scale(value), y1: y, y2: y + TICK, stroke: axisLine }),
395
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("text", { x: scale(value), y: y + TICK + 13, textAnchor: "middle", fill: axisMuted, fontSize: TICK_LABEL, fontFamily: MONO, children: fmt(value) })
396
+ ] }, +value)),
397
+ title ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("text", { x: (x0 + x1) / 2, y: y + titleGap, textAnchor: "middle", fill: axisMuted, fontSize: AXIS_TITLE, fontFamily: MONO, children: title }) : null
398
+ ] });
399
+ }
400
+ function bandCenters(count, x0, x1) {
401
+ const step = (x1 - x0) / Math.max(count, 1);
402
+ const centers = Array.from({ length: count }, (_, index) => x0 + step * (index + 0.5));
403
+ return { centers, step };
404
+ }
405
+ function divergentSignedColor(value, maxAbs) {
406
+ const stops = sterlingDivergentColors.length - 1;
407
+ const t = Math.max(0, Math.min(1, (value + maxAbs) / (2 * maxAbs)));
408
+ return sterlingDivergentColors[Math.round((1 - t) * stops)];
409
+ }
410
+ var divergentSignedRamp = [...sterlingDivergentColors].reverse();
411
+ function tukeySummary(values) {
412
+ const sorted = [...values].sort((left, right) => left - right);
413
+ const q = (p) => {
414
+ if (sorted.length === 0) return 0;
415
+ const position = (sorted.length - 1) * p;
416
+ const lower = Math.floor(position);
417
+ const upper = Math.ceil(position);
418
+ if (lower === upper) return sorted[lower];
419
+ return sorted[lower] + (sorted[upper] - sorted[lower]) * (position - lower);
420
+ };
421
+ const q1 = q(0.25);
422
+ const median = q(0.5);
423
+ const q3 = q(0.75);
424
+ const iqr = q3 - q1;
425
+ const lowerFence = q1 - 1.5 * iqr;
426
+ const upperFence = q3 + 1.5 * iqr;
427
+ const inside = sorted.filter((value) => value >= lowerFence && value <= upperFence);
428
+ const whiskerLow = inside.length ? inside[0] : q1;
429
+ const whiskerHigh = inside.length ? inside[inside.length - 1] : q3;
430
+ const outliers = sorted.filter((value) => value < lowerFence || value > upperFence);
431
+ return { q1, median, q3, iqr, whiskerLow, whiskerHigh, outliers, min: sorted[0], max: sorted[sorted.length - 1] };
432
+ }
433
+
434
+ // src/charts.tsx
435
+ var import_jsx_runtime3 = require("react/jsx-runtime");
436
+ var chartText = "var(--sterling-text)";
437
+ var chartMuted = "var(--sterling-muted)";
438
+ var chartGrid = "var(--sterling-grid)";
439
+ function SterlingBarChart({
440
+ data,
441
+ ariaLabel,
442
+ unit = "",
443
+ xLabel
444
+ }) {
445
+ const rowHeight = 46;
446
+ const top = 12;
447
+ const barHeight = 28;
448
+ const axisBottom = xLabel ? 50 : 34;
449
+ const x0 = 150;
450
+ const x1 = 684;
451
+ const height = top + data.length * rowHeight + axisBottom;
452
+ const baseline = top + data.length * rowHeight;
453
+ const x = linearScale(data.map((datum) => datum.value), [x0, x1], { zero: true });
454
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 720 ${height}`, role: "img", "aria-label": ariaLabel, children: [
455
+ x.ticks(6).map((value) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: x(value), x2: x(value), y1: top, y2: baseline, stroke: chartGrid, strokeWidth: sterlingVisualStyle.stroke.grid }, value)),
456
+ data.map((datum, index) => {
457
+ const y = top + index * rowHeight + (rowHeight - barHeight) / 2 - 6;
458
+ const width = x(datum.value) - x0;
459
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
460
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: x0 - 12, y: y + barHeight / 2 + 4, textAnchor: "end", fill: chartText, fontSize: "12", fontFamily: "var(--font-mono)", children: datum.label }),
461
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
462
+ "rect",
463
+ {
464
+ x: x0,
465
+ y,
466
+ width: Math.max(width, 2),
467
+ height: barHeight,
468
+ rx: "3",
469
+ fill: sterlingChartColors[datum.colorIndex ?? index % sterlingChartColors.length],
470
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${datum.label}: ${datum.value}${unit}` })
471
+ }
472
+ ),
473
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("text", { x: x(datum.value) + 8, y: y + barHeight / 2 + 4, fill: chartMuted, fontSize: "12", fontFamily: "var(--font-mono)", children: [
474
+ datum.value,
475
+ unit
476
+ ] })
477
+ ] }, datum.label);
478
+ }),
479
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AxisBottom, { scale: x, y: baseline, count: 6, title: xLabel, format: (value) => `${value}${unit}` })
480
+ ] });
481
+ }
482
+ function scatterMark(shape, x, y, color, key, title) {
483
+ if (shape % 3 === 1) {
484
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: x - 4.5, y: y - 4.5, width: "9", height: "9", rx: "1", fill: color, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: title }) }, key);
485
+ }
486
+ if (shape % 3 === 2) {
487
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: `M ${x} ${y - 5.5} L ${x + 5.2} ${y + 4.5} L ${x - 5.2} ${y + 4.5} Z`, fill: color, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: title }) }, key);
488
+ }
489
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: x, cy: y, r: "4.8", fill: color, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: title }) }, key);
490
+ }
491
+ function SterlingScatterPlot({
492
+ data,
493
+ ariaLabel,
494
+ xLabel,
495
+ yLabel,
496
+ showLegend = false,
497
+ zeroX = false,
498
+ zeroY = false
499
+ }) {
500
+ const groups = [...new Set(data.map((datum) => datum.group))];
501
+ const f = frame(720, 380);
502
+ const x = linearScale(data.map((datum) => datum.x), [f.x0, f.x1], { zero: zeroX });
503
+ const y = linearScale(data.map((datum) => datum.y), [f.y1, f.y0], { zero: zeroY });
504
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 ${f.width} ${f.height}`, role: "img", "aria-label": ariaLabel, children: [
505
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Gridlines, { scale: y, x0: f.x0, x1: f.x1, count: 5 }),
506
+ data.map((datum, index) => {
507
+ const groupIndex = groups.indexOf(datum.group);
508
+ return scatterMark(
509
+ groupIndex,
510
+ x(datum.x),
511
+ y(datum.y),
512
+ sterlingChartColors[groupIndex],
513
+ `${datum.group}-${index}`,
514
+ datum.label ?? `${datum.group}: ${datum.x}, ${datum.y}`
515
+ );
516
+ }),
517
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AxisLeft, { scale: y, x: f.x0, count: 5, title: yLabel }),
518
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AxisBottom, { scale: x, y: f.y1, count: 6, title: xLabel }),
519
+ showLegend ? groups.map((group, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { transform: `translate(${f.x1 - 150 + index % 2 * 92} ${f.y0 + 2 + Math.floor(index / 2) * 20})`, children: [
520
+ scatterMark(index, 0, 0, sterlingChartColors[index], `legend-${group}`, group),
521
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: "11", y: "4", fill: chartMuted, fontSize: "10.5", fontFamily: "var(--font-mono)", children: group })
522
+ ] }, group)) : null
523
+ ] });
524
+ }
525
+ function SterlingLineChart({
526
+ labels,
527
+ series,
528
+ ariaLabel,
529
+ yLabel,
530
+ xLabel,
531
+ times,
532
+ markers,
533
+ showLegend = false
534
+ }) {
535
+ const f = frame(720, 380);
536
+ const values = series.flatMap((item) => item.values);
537
+ const y = linearScale(values, [f.y1, f.y0], { zero: true });
538
+ const isTime = Array.isArray(times) && times.length === labels.length && labels.length > 1;
539
+ const time = isTime ? timeScale([times[0], times[times.length - 1]], [f.x0, f.x1]) : null;
540
+ const xAt = (index) => time ? time(new Date(times[index])) : f.x0 + index / Math.max(labels.length - 1, 1) * (f.x1 - f.x0);
541
+ const showMarkers = markers ?? labels.length <= 40;
542
+ const labelStep = Math.max(1, Math.ceil(labels.length / 8));
543
+ const lastIndex = labels.length - 1;
544
+ const showCatTick = (index) => {
545
+ if (index === lastIndex) return true;
546
+ if (index % labelStep !== 0) return false;
547
+ return lastIndex - index >= labelStep * 0.55;
548
+ };
549
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 ${f.width} ${f.height}`, role: "img", "aria-label": ariaLabel, children: [
550
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Gridlines, { scale: y, x0: f.x0, x1: f.x1, count: 5 }),
551
+ series.map((item, seriesIndex) => {
552
+ const path = item.values.map((value, index) => `${index === 0 ? "M" : "L"} ${xAt(index)} ${y(value)}`).join(" ");
553
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
554
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: path, fill: "none", stroke: sterlingChartColors[seriesIndex], strokeWidth: sterlingVisualStyle.stroke.series, strokeLinecap: "round", strokeLinejoin: "round" }),
555
+ showMarkers ? item.values.map((value, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: xAt(index), cy: y(value), r: "3.4", fill: sterlingChartColors[seriesIndex], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${item.label}, ${labels[index]}: ${value}` }) }, index)) : null
556
+ ] }, item.label);
557
+ }),
558
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AxisLeft, { scale: y, x: f.x0, count: 5, title: yLabel }),
559
+ time ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TimeAxisBottom, { scale: time, y: f.y1, title: xLabel }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
560
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: f.x0, x2: f.x1, y1: f.y1, y2: f.y1, stroke: "var(--sterling-edge)" }),
561
+ labels.map(
562
+ (label, index) => showCatTick(index) ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
563
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: xAt(index), x2: xAt(index), y1: f.y1, y2: f.y1 + 5, stroke: "var(--sterling-edge)" }),
564
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: xAt(index), y: f.y1 + 18, textAnchor: "middle", fill: chartMuted, fontSize: "11", fontFamily: "var(--font-mono)", children: label })
565
+ ] }, `${label}-${index}`) : null
566
+ ),
567
+ xLabel ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: (f.x0 + f.x1) / 2, y: f.y1 + 42, textAnchor: "middle", fill: chartMuted, fontSize: "12", fontFamily: "var(--font-mono)", children: xLabel }) : null
568
+ ] }),
569
+ showLegend ? series.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { transform: `translate(${f.x0 + 28 + index * 176} ${f.y0 - 2})`, children: [
570
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "0", x2: "22", stroke: sterlingChartColors[index], strokeWidth: sterlingVisualStyle.stroke.series }),
571
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: "30", y: "4", fill: chartMuted, fontSize: "11", fontFamily: "var(--font-mono)", children: item.label })
572
+ ] }, item.label)) : null
573
+ ] });
574
+ }
575
+ function SterlingHeatmap({
576
+ values,
577
+ rowLabels,
578
+ columnLabels,
579
+ ariaLabel,
580
+ domain,
581
+ legendTitle,
582
+ showValues = false
583
+ }) {
584
+ const flat = values.flat();
585
+ const maxAbs = domain ?? Math.max(1, Math.ceil(Math.max(...flat.map((value) => Math.abs(value))) * 10) / 10);
586
+ const width = 720;
587
+ const startX = 168;
588
+ const startY = 46;
589
+ const rightPad = 24;
590
+ const gridWidth = width - startX - rightPad;
591
+ const cellW = gridWidth / Math.max(columnLabels.length, 1);
592
+ const cellH = Math.min(cellW * 0.5, 46);
593
+ const gap = 3;
594
+ const gridHeight = cellH * rowLabels.length;
595
+ const height = startY + gridHeight + 60;
596
+ const legendWidth = Math.min(gridWidth, 340);
597
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 ${width} ${height}`, role: "img", "aria-label": ariaLabel, children: [
598
+ columnLabels.map((label, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: startX + index * cellW + cellW / 2, y: startY - 12, textAnchor: "middle", fill: chartText, fontSize: "11", fontFamily: "var(--font-mono)", children: label }, label)),
599
+ rowLabels.map((label, row) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
600
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: startX - 12, y: startY + row * cellH + cellH / 2 + 4, textAnchor: "end", fill: chartText, fontSize: "11", fontFamily: "var(--font-mono)", children: label }),
601
+ columnLabels.map((column, columnIndex) => {
602
+ const value = values[row]?.[columnIndex] ?? 0;
603
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
604
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
605
+ "rect",
606
+ {
607
+ x: startX + columnIndex * cellW,
608
+ y: startY + row * cellH,
609
+ width: cellW - gap,
610
+ height: cellH - gap,
611
+ rx: "3",
612
+ fill: divergentSignedColor(value, maxAbs),
613
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${label}, ${column}: ${value.toFixed(2)}` })
614
+ }
615
+ ),
616
+ showValues ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
617
+ "text",
618
+ {
619
+ x: startX + columnIndex * cellW + (cellW - gap) / 2,
620
+ y: startY + row * cellH + (cellH - gap) / 2 + 4,
621
+ textAnchor: "middle",
622
+ fill: Math.abs(value) > maxAbs * 0.55 ? "var(--sterling-surface)" : chartText,
623
+ fontSize: "10.5",
624
+ fontFamily: "var(--font-mono)",
625
+ children: value.toFixed(1)
626
+ }
627
+ ) : null
628
+ ] }, column);
629
+ })
630
+ ] }, label)),
631
+ legendTitle ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: startX, y: height - 38, fill: chartMuted, fontSize: "10.5", fontFamily: "var(--font-mono)", children: legendTitle }) : null,
632
+ divergentSignedRamp.map((color, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: startX + index * legendWidth / divergentSignedRamp.length, y: height - 28, width: legendWidth / divergentSignedRamp.length + 0.5, height: "13", fill: color }, `${color}-${index}`)),
633
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: startX, y: height - 5, fill: chartMuted, fontSize: "10", fontFamily: "var(--font-mono)", children: -maxAbs }),
634
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: startX + legendWidth / 2, y: height - 5, textAnchor: "middle", fill: chartMuted, fontSize: "10", fontFamily: "var(--font-mono)", children: "0" }),
635
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: startX + legendWidth, y: height - 5, textAnchor: "end", fill: chartMuted, fontSize: "10", fontFamily: "var(--font-mono)", children: `+${maxAbs}` })
636
+ ] });
637
+ }
638
+ function SterlingSequentialSurface({
639
+ values: suppliedValues,
640
+ ariaLabel,
641
+ lowLabel = "low / bajo",
642
+ highLabel = "high / alto"
643
+ }) {
644
+ const defaultRows = 10;
645
+ const defaultColumns = 18;
646
+ const generatedValues = Array.from({ length: defaultRows }, (_, row) => Array.from({ length: defaultColumns }, (_2, column) => {
647
+ const x = column / (defaultColumns - 1);
648
+ const y = row / (defaultRows - 1);
649
+ const firstPeak = Math.exp(-(((x - 0.3) / 0.19) ** 2 + ((y - 0.34) / 0.25) ** 2));
650
+ const secondPeak = 0.76 * Math.exp(-(((x - 0.72) / 0.23) ** 2 + ((y - 0.67) / 0.2) ** 2));
651
+ const saddle = 0.22 * Math.sin(x * Math.PI * 2.4) * Math.cos(y * Math.PI * 1.7);
652
+ return firstPeak + secondPeak + saddle;
653
+ }));
654
+ const values = suppliedValues?.length && suppliedValues.some((row) => row.length) ? suppliedValues : generatedValues;
655
+ const rows = values.length;
656
+ const columns = Math.max(1, ...values.map((row) => row.length));
657
+ const flat = values.flat();
658
+ const min = Math.min(...flat);
659
+ const max = Math.max(...flat);
660
+ const cellWidth = 558 / columns;
661
+ const cellHeight = 240 / Math.max(rows, 1);
662
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "sterling-chart", viewBox: "0 0 720 340", role: "img", "aria-label": ariaLabel, children: [
663
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("g", { transform: "translate(82 34)", children: values.flatMap((rowValues, row) => rowValues.map((value, column) => {
664
+ const index = Math.max(0, Math.min(sterlingHeatColors.length - 1, Math.round((value - min) / Math.max(max - min, 1) * (sterlingHeatColors.length - 1))));
665
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: column * cellWidth, y: row * cellHeight, width: cellWidth + 0.35, height: cellHeight + 0.35, fill: sterlingHeatColors[index], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `x ${column + 1}, y ${row + 1}: ${value.toFixed(2)}` }) }, `${row}-${column}`);
666
+ })) }),
667
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: "82", y: "302", fill: chartMuted, fontSize: "10", fontFamily: "var(--font-mono)", children: lowLabel }),
668
+ sterlingHeatColors.map((color, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: 152 + index * 34, y: "289", width: "34", height: "15", fill: color }, color)),
669
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: "540", y: "302", fill: chartMuted, fontSize: "10", fontFamily: "var(--font-mono)", children: highLabel })
670
+ ] });
671
+ }
672
+ function SterlingCorrelogram({
673
+ values,
674
+ labels,
675
+ ariaLabel
676
+ }) {
677
+ const cell = 67;
678
+ const startX = 112;
679
+ const startY = 34;
680
+ const size = labels.length * cell;
681
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 ${startX + size + 54} ${startY + size + 72}`, role: "img", "aria-label": ariaLabel, children: [
682
+ labels.flatMap((rowLabel, row) => labels.map((columnLabel, column) => {
683
+ const value = values[row]?.[column] ?? 0;
684
+ const color = divergentSignedColor(value, 1);
685
+ const centerX = startX + column * cell + cell / 2;
686
+ const centerY = startY + row * cell + cell / 2;
687
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
688
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: startX + column * cell, y: startY + row * cell, width: cell, height: cell, fill: "none", stroke: chartGrid }),
689
+ row === column ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: centerX, y: centerY + 4, textAnchor: "middle", fill: chartText, fontSize: "10.5", fontFamily: "var(--font-mono)", children: rowLabel }) : row > column ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
690
+ "ellipse",
691
+ {
692
+ cx: centerX,
693
+ cy: centerY,
694
+ rx: "25",
695
+ ry: Math.max(2.5, 25 * (1 - Math.abs(value))),
696
+ transform: `rotate(${value >= 0 ? -45 : 45} ${centerX} ${centerY})`,
697
+ fill: color,
698
+ fillOpacity: sterlingVisualStyle.opacity.secondaryMark,
699
+ stroke: color,
700
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${rowLabel}, ${columnLabel}: ${value.toFixed(2)}` })
701
+ }
702
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: centerX, y: centerY + 5, textAnchor: "middle", fill: Math.abs(value) >= 0.3 ? color : chartMuted, fontSize: "15", fontFamily: "var(--font-mono)", fontWeight: "700", children: value.toFixed(2) })
703
+ ] }, `${rowLabel}-${columnLabel}`);
704
+ })),
705
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: startX, y: startY + size + 41, fill: chartMuted, fontSize: "10", fontFamily: "var(--font-mono)", children: "-1" }),
706
+ divergentSignedRamp.map((color, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: startX + 28 + index * 27, y: startY + size + 27, width: "27", height: "16", fill: color }, `${color}-${index}`)),
707
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: startX + 340, y: startY + size + 41, fill: chartMuted, fontSize: "10", fontFamily: "var(--font-mono)", children: "+1" })
708
+ ] });
709
+ }
710
+ function SterlingHistogram({
711
+ values,
712
+ bins = 16,
713
+ ariaLabel,
714
+ xLabel,
715
+ yLabel
716
+ }) {
717
+ const min = Math.min(...values);
718
+ const max = Math.max(...values);
719
+ const step = Math.max((max - min) / bins, Number.EPSILON);
720
+ const counts = Array.from({ length: bins }, () => 0);
721
+ values.forEach((value) => {
722
+ counts[Math.min(bins - 1, Math.floor((value - min) / step))] += 1;
723
+ });
724
+ const top = Math.max(...counts, 1);
725
+ const f = frame(720, 380);
726
+ const x = linearScale([min, max], [f.x0, f.x1]);
727
+ const y = linearScale([0, top], [f.y1, f.y0], { zero: true });
728
+ const barWidth = x(min + step) - x(min);
729
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 ${f.width} ${f.height}`, role: "img", "aria-label": ariaLabel, children: [
730
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Gridlines, { scale: y, x0: f.x0, x1: f.x1, count: 5 }),
731
+ counts.map((count, index) => {
732
+ const lower = min + index * step;
733
+ const upper = lower + step;
734
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
735
+ "rect",
736
+ {
737
+ x: x(lower) + 1,
738
+ y: y(count),
739
+ width: Math.max(barWidth - 2, 1),
740
+ height: f.y1 - y(count),
741
+ fill: sterlingChartColors[0],
742
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${lower.toFixed(1)}-${upper.toFixed(1)}: ${count}` })
743
+ },
744
+ index
745
+ );
746
+ }),
747
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AxisLeft, { scale: y, x: f.x0, count: 5, title: yLabel, format: (value) => `${Math.round(value)}` }),
748
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AxisBottom, { scale: x, y: f.y1, count: 7, title: xLabel })
749
+ ] });
750
+ }
751
+ function SterlingBoxPlot({ groups, ariaLabel, yLabel }) {
752
+ const all = groups.flatMap((group) => group.values);
753
+ const top = 24;
754
+ const rowH = 80;
755
+ const axisBottom = 48;
756
+ const height = top + groups.length * rowH + axisBottom;
757
+ const baseline = top + groups.length * rowH + 6;
758
+ const x0 = 168;
759
+ const x1 = 690;
760
+ const x = linearScale(all, [x0, x1]);
761
+ const boxHalf = 24;
762
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 720 ${height}`, role: "img", "aria-label": ariaLabel, children: [
763
+ x.ticks(6).map((value) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: x(value), x2: x(value), y1: top, y2: baseline, stroke: chartGrid, strokeWidth: sterlingVisualStyle.stroke.grid }, value)),
764
+ groups.map((group, index) => {
765
+ const summary = tukeySummary(group.values);
766
+ const center = top + index * rowH + rowH / 2 - 4;
767
+ const color = sterlingChartColors[index];
768
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
769
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: x0 - 12, y: center + 4, textAnchor: "end", fill: chartText, fontSize: "12", fontFamily: "var(--font-mono)", children: group.label }),
770
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: x(summary.whiskerLow), x2: x(summary.q1), y1: center, y2: center, stroke: color, strokeWidth: sterlingVisualStyle.stroke.mark }),
771
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: x(summary.q3), x2: x(summary.whiskerHigh), y1: center, y2: center, stroke: color, strokeWidth: sterlingVisualStyle.stroke.mark }),
772
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: x(summary.whiskerLow), x2: x(summary.whiskerLow), y1: center - 12, y2: center + 12, stroke: color, strokeWidth: sterlingVisualStyle.stroke.mark }),
773
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: x(summary.whiskerHigh), x2: x(summary.whiskerHigh), y1: center - 12, y2: center + 12, stroke: color, strokeWidth: sterlingVisualStyle.stroke.mark }),
774
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: x(summary.q1), y: center - boxHalf, width: Math.max(x(summary.q3) - x(summary.q1), 2), height: boxHalf * 2, rx: "3", fill: color, fillOpacity: sterlingVisualStyle.opacity.interval, stroke: color, strokeWidth: sterlingVisualStyle.stroke.mark, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${group.label}: n=${group.values.length}, median ${summary.median.toFixed(2)}, IQR ${summary.q1.toFixed(2)}-${summary.q3.toFixed(2)}` }) }),
775
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: x(summary.median), x2: x(summary.median), y1: center - boxHalf, y2: center + boxHalf, stroke: color, strokeWidth: sterlingVisualStyle.stroke.emphasis }),
776
+ summary.outliers.map((value, outlierIndex) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: x(value), cy: center, r: "3.4", fill: "none", stroke: color, strokeWidth: sterlingVisualStyle.stroke.detail, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${group.label} outlier: ${value.toFixed(2)}` }) }, outlierIndex))
777
+ ] }, group.label);
778
+ }),
779
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AxisBottom, { scale: x, y: baseline, count: 6, title: yLabel })
780
+ ] });
781
+ }
782
+ function SterlingDumbbellChart({
783
+ data,
784
+ ariaLabel,
785
+ leftLabel,
786
+ rightLabel,
787
+ xLabel
788
+ }) {
789
+ const top = 56;
790
+ const rowH = 66;
791
+ const axisBottom = xLabel ? 50 : 34;
792
+ const x0 = 150;
793
+ const x1 = 660;
794
+ const height = top + data.length * rowH + axisBottom;
795
+ const baseline = top + data.length * rowH;
796
+ const x = linearScale(data.flatMap((datum) => [datum.left, datum.right]), [x0, x1], { zero: true });
797
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 720 ${height}`, role: "img", "aria-label": ariaLabel, children: [
798
+ x.ticks(6).map((value) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: x(value), x2: x(value), y1: top - 20, y2: baseline, stroke: chartGrid, strokeWidth: sterlingVisualStyle.stroke.grid }, value)),
799
+ data.map((datum, index) => {
800
+ const y = top + index * rowH + rowH / 2 - 4;
801
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
802
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: x0 - 14, y: y + 4, textAnchor: "end", fill: chartText, fontSize: "12", fontFamily: "var(--font-mono)", children: datum.label }),
803
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: x(datum.left), x2: x(datum.right), y1: y, y2: y, stroke: chartGrid, strokeWidth: sterlingVisualStyle.stroke.series, strokeLinecap: "round" }),
804
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: x(datum.left), cy: y, r: "8", fill: sterlingChartColors[0], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${datum.label}, ${leftLabel}: ${datum.left.toFixed(2)}` }) }),
805
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: x(datum.right), cy: y, r: "8", fill: sterlingChartColors[3], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${datum.label}, ${rightLabel}: ${datum.right.toFixed(2)}` }) })
806
+ ] }, datum.label);
807
+ }),
808
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AxisBottom, { scale: x, y: baseline, count: 6, title: xLabel })
809
+ ] });
810
+ }
811
+ function kernelDensity(values, steps = 64, domain) {
812
+ const min = domain?.[0] ?? Math.min(...values);
813
+ const max = domain?.[1] ?? Math.max(...values);
814
+ const mean = values.reduce((sum, value) => sum + value, 0) / values.length;
815
+ const spread = Math.sqrt(values.reduce((sum, value) => sum + (value - mean) ** 2, 0) / Math.max(values.length - 1, 1));
816
+ const bandwidth = Math.max(1.06 * spread * values.length ** -0.2, (max - min) / 100, 1e-3);
817
+ return Array.from({ length: steps }, (_, index) => {
818
+ const value = min + index / (steps - 1) * (max - min);
819
+ const density = values.reduce((sum, observation) => {
820
+ const z = (value - observation) / bandwidth;
821
+ return sum + Math.exp(-0.5 * z * z) / Math.sqrt(2 * Math.PI);
822
+ }, 0) / (values.length * bandwidth);
823
+ return { value, density };
824
+ });
825
+ }
826
+ function SterlingDensityChart({ values, ariaLabel, xLabel, yLabel }) {
827
+ const density = kernelDensity(values);
828
+ const maxDensity = Math.max(...density.map((point) => point.density), Number.EPSILON);
829
+ const f = frame(720, 380);
830
+ const x = linearScale([density[0].value, density[density.length - 1].value], [f.x0, f.x1], { padFraction: 0 });
831
+ const y = linearScale([0, maxDensity], [f.y1, f.y0], { zero: true });
832
+ const line = density.map((point, index) => `${index === 0 ? "M" : "L"} ${x(point.value)} ${y(point.density)}`).join(" ");
833
+ const area = `${line} L ${x(density[density.length - 1].value)} ${f.y1} L ${x(density[0].value)} ${f.y1} Z`;
834
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 ${f.width} ${f.height}`, role: "img", "aria-label": ariaLabel, children: [
835
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Gridlines, { scale: y, x0: f.x0, x1: f.x1, count: 5 }),
836
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: area, fill: sterlingSequentialColors[4], fillOpacity: sterlingVisualStyle.opacity.area }),
837
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: line, fill: "none", stroke: sterlingSequentialColors[7], strokeWidth: sterlingVisualStyle.stroke.series, strokeLinecap: "round", strokeLinejoin: "round" }),
838
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AxisLeft, { scale: y, x: f.x0, count: 5, title: yLabel }),
839
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AxisBottom, { scale: x, y: f.y1, count: 7, title: xLabel })
840
+ ] });
841
+ }
842
+ function SterlingViolinPlot({ groups, ariaLabel, yLabel }) {
843
+ const all = groups.flatMap((group) => group.values);
844
+ const observedMin = Math.min(...all);
845
+ const observedMax = Math.max(...all);
846
+ const bandwidthOf = (values) => {
847
+ const mean = values.reduce((sum, value) => sum + value, 0) / values.length;
848
+ const spread = Math.sqrt(values.reduce((sum, value) => sum + (value - mean) ** 2, 0) / Math.max(values.length - 1, 1));
849
+ return Math.max(1.06 * spread * values.length ** -0.2, 1e-6);
850
+ };
851
+ const maxBandwidth = Math.max(...groups.map((group) => bandwidthOf(group.values)));
852
+ const margin = Math.max((observedMax - observedMin) * 0.05, maxBandwidth * 3);
853
+ const domain = [observedMin - margin, observedMax + margin];
854
+ const f = frame(720, 390, { top: 26, right: 26, bottom: 44, left: 70 });
855
+ const y = linearScale(domain, [f.y1, f.y0], { padFraction: 0 });
856
+ const { centers } = bandCenters(groups.length, f.x0, f.x1);
857
+ const halfWidth = Math.min(46, (f.x1 - f.x0) / groups.length * 0.42);
858
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 ${f.width} ${f.height}`, role: "img", "aria-label": ariaLabel, children: [
859
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Gridlines, { scale: y, x0: f.x0, x1: f.x1, count: 5 }),
860
+ groups.map((group, groupIndex) => {
861
+ const estimate = kernelDensity(group.values, 96, domain);
862
+ const peak = Math.max(...estimate.map((point) => point.density), Number.EPSILON);
863
+ const cutoff = peak * 0.01;
864
+ const firstIndex = estimate.findIndex((point) => point.density >= cutoff);
865
+ const lastIndex = estimate.length - 1 - [...estimate].reverse().findIndex((point) => point.density >= cutoff);
866
+ const density = estimate.slice(Math.max(0, firstIndex - 1), Math.min(estimate.length - 1, lastIndex + 1) + 1);
867
+ const center = centers[groupIndex];
868
+ const right = density.map((point) => `${center + point.density / peak * halfWidth} ${y(point.value)}`);
869
+ const left = [...density].reverse().map((point) => `${center - point.density / peak * halfWidth} ${y(point.value)}`);
870
+ const path = `M ${right.join(" L ")} L ${left.join(" L ")} Z`;
871
+ const summary = tukeySummary(group.values);
872
+ const color = sterlingChartColors[groupIndex];
873
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
874
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: path, fill: color, fillOpacity: sterlingVisualStyle.opacity.area, stroke: color, strokeWidth: sterlingVisualStyle.stroke.series, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${group.label}: n=${group.values.length}, median ${summary.median.toFixed(1)}, IQR ${summary.q1.toFixed(1)}-${summary.q3.toFixed(1)}` }) }),
875
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: center, x2: center, y1: y(summary.whiskerLow), y2: y(summary.whiskerHigh), stroke: color, strokeWidth: sterlingVisualStyle.stroke.detail }),
876
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: center - 5, x2: center + 5, y1: y(summary.whiskerLow), y2: y(summary.whiskerLow), stroke: color, strokeWidth: sterlingVisualStyle.stroke.detail }),
877
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: center - 5, x2: center + 5, y1: y(summary.whiskerHigh), y2: y(summary.whiskerHigh), stroke: color, strokeWidth: sterlingVisualStyle.stroke.detail }),
878
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: center, x2: center, y1: y(summary.q3), y2: y(summary.q1), stroke: color, strokeWidth: sterlingVisualStyle.stroke.interval, strokeLinecap: "round" }),
879
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: center, cy: y(summary.median), r: "4.5", fill: "var(--sterling-surface)", stroke: color, strokeWidth: sterlingVisualStyle.stroke.emphasis }),
880
+ summary.outliers.map((value, outlierIndex) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: center, cy: y(value), r: "3", fill: "none", stroke: color, strokeWidth: sterlingVisualStyle.stroke.detail, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${group.label} outlier: ${value.toFixed(1)}` }) }, outlierIndex)),
881
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: center, y: f.y1 + 18, textAnchor: "middle", fill: chartMuted, fontSize: "10.5", fontFamily: "var(--font-mono)", children: group.label })
882
+ ] }, group.label);
883
+ }),
884
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AxisLeft, { scale: y, x: f.x0, count: 5, title: yLabel }),
885
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: f.x0, x2: f.x1, y1: f.y1, y2: f.y1, stroke: "var(--sterling-edge)" })
886
+ ] });
887
+ }
888
+ function SterlingDonutChart({ data, ariaLabel, centerLabel, centerValue }) {
889
+ const total = data.reduce((sum, datum) => sum + datum.value, 0);
890
+ const radius = 96;
891
+ const circumference = 2 * Math.PI * radius;
892
+ let offset = 0;
893
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "sterling-chart", viewBox: "0 0 720 350", role: "img", "aria-label": ariaLabel, children: [
894
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("g", { transform: "translate(360 174) rotate(-90)", children: data.map((datum, index) => {
895
+ const length = datum.value / total * circumference;
896
+ const currentOffset = offset;
897
+ offset += length;
898
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
899
+ "circle",
900
+ {
901
+ cx: "0",
902
+ cy: "0",
903
+ r: radius,
904
+ fill: "none",
905
+ stroke: sterlingChartColors[index],
906
+ strokeWidth: sterlingVisualStyle.stroke.ring,
907
+ strokeDasharray: `${length} ${circumference - length}`,
908
+ strokeDashoffset: -currentOffset,
909
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${datum.label}: ${datum.value} (${(datum.value / total * 100).toFixed(1)}%)` })
910
+ },
911
+ datum.label
912
+ );
913
+ }) }),
914
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: "360", y: "171", textAnchor: "middle", fill: chartText, fontSize: "30", fontFamily: "var(--font-display)", fontWeight: "600", children: centerValue ?? total.toLocaleString() }),
915
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: "360", y: "195", textAnchor: "middle", fill: chartMuted, fontSize: "11", fontFamily: "var(--font-mono)", children: centerLabel })
916
+ ] });
917
+ }
918
+ function SterlingLollipopChart({ data, ariaLabel, unit = "", xLabel }) {
919
+ const top = 30;
920
+ const rowH = 56;
921
+ const axisBottom = xLabel ? 50 : 34;
922
+ const x0 = 200;
923
+ const x1 = 660;
924
+ const height = top + data.length * rowH + axisBottom;
925
+ const baseline = top + data.length * rowH;
926
+ const x = linearScale(data.map((datum) => datum.value), [x0, x1], { zero: true });
927
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 720 ${height}`, role: "img", "aria-label": ariaLabel, children: [
928
+ x.ticks(6).map((value) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: x(value), x2: x(value), y1: top, y2: baseline, stroke: chartGrid, strokeWidth: sterlingVisualStyle.stroke.grid }, value)),
929
+ data.map((datum, index) => {
930
+ const y = top + index * rowH + rowH / 2 - 4;
931
+ const color = sterlingChartColors[index];
932
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
933
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: x0 - 14, y: y + 4, textAnchor: "end", fill: chartText, fontSize: "12", fontFamily: "var(--font-mono)", children: datum.label }),
934
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: x(0), x2: x(datum.value), y1: y, y2: y, stroke: color, strokeOpacity: sterlingVisualStyle.opacity.secondaryMark, strokeWidth: sterlingVisualStyle.stroke.series }),
935
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: x(datum.value), cy: y, r: "8", fill: color, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${datum.label}: ${datum.value}${unit}` }) }),
936
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("text", { x: x(datum.value) + 15, y: y + 4, fill: chartMuted, fontSize: "11", fontFamily: "var(--font-mono)", children: [
937
+ datum.value,
938
+ unit
939
+ ] })
940
+ ] }, datum.label);
941
+ }),
942
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AxisBottom, { scale: x, y: baseline, count: 6, title: xLabel, format: (value) => `${value}${unit}` })
943
+ ] });
944
+ }
945
+ function polarPoint(centerX, centerY, radius, angle) {
946
+ const radians = (angle - 90) * Math.PI / 180;
947
+ return { x: centerX + radius * Math.cos(radians), y: centerY + radius * Math.sin(radians) };
948
+ }
949
+ function pieArc(centerX, centerY, radius, startAngle, endAngle) {
950
+ const start = polarPoint(centerX, centerY, radius, endAngle);
951
+ const end = polarPoint(centerX, centerY, radius, startAngle);
952
+ return `M ${centerX} ${centerY} L ${start.x} ${start.y} A ${radius} ${radius} 0 ${endAngle - startAngle > 180 ? 1 : 0} 0 ${end.x} ${end.y} Z`;
953
+ }
954
+ function SterlingPieChart({ data, ariaLabel }) {
955
+ const total = data.reduce((sum, datum) => sum + datum.value, 0);
956
+ let angle = 0;
957
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "sterling-chart", viewBox: "0 0 720 390", role: "img", "aria-label": ariaLabel, children: data.map((datum, index) => {
958
+ const start = angle;
959
+ const end = angle + datum.value / total * 360;
960
+ angle = end;
961
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: pieArc(360, 194, 138, start, end), fill: sterlingChartColors[index], stroke: "var(--sterling-surface)", strokeWidth: sterlingVisualStyle.stroke.mark, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${datum.label}: ${datum.value.toLocaleString()} (${(datum.value / total * 100).toFixed(1)}%)` }) }, datum.label);
962
+ }) });
963
+ }
964
+ function SterlingChordChart({
965
+ rowLabels,
966
+ columnLabels,
967
+ values,
968
+ ariaLabel
969
+ }) {
970
+ const labels = [...rowLabels, ...columnLabels];
971
+ const matrix = Array.from({ length: labels.length }, () => Array(labels.length).fill(0));
972
+ values.forEach((row, rowIndex) => row.forEach((value, columnIndex) => {
973
+ matrix[rowIndex][rowLabels.length + columnIndex] = value;
974
+ matrix[rowLabels.length + columnIndex][rowIndex] = value;
975
+ }));
976
+ const chords = (0, import_d3_chord.chord)().padAngle(0.055).sortSubgroups((left, right) => right - left)(matrix);
977
+ const arcPath = (0, import_d3_shape.arc)().innerRadius(126).outerRadius(145).cornerRadius(3).startAngle((group) => group.startAngle).endAngle((group) => group.endAngle);
978
+ const ribbonPath = (0, import_d3_chord.ribbon)().radius(122);
979
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { className: "sterling-chart", viewBox: "0 0 720 420", role: "img", "aria-label": ariaLabel, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { transform: "translate(360 204)", children: [
980
+ chords.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: ribbonPath(item) ?? void 0, fill: sterlingChartColors[item.source.index], fillOpacity: sterlingVisualStyle.opacity.relationship, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${labels[item.source.index]} + ${labels[item.target.index]}: ${item.source.value}` }) }, `${item.source.index}-${item.target.index}-${index}`)),
981
+ chords.groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: arcPath(group) ?? void 0, fill: sterlingChartColors[group.index], stroke: "var(--sterling-surface)", strokeWidth: sterlingVisualStyle.stroke.mark }, group.index)),
982
+ chords.groups.map((group) => {
983
+ const angle = (group.startAngle + group.endAngle) / 2;
984
+ const x = Math.sin(angle) * 170;
985
+ const y = -Math.cos(angle) * 170;
986
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x, y: y + 4, textAnchor: x < -8 ? "end" : x > 8 ? "start" : "middle", fill: chartText, fontSize: "10", fontFamily: "var(--font-mono)", children: labels[group.index] }, `label-${group.index}`);
987
+ })
988
+ ] }) });
989
+ }
990
+ function SterlingSankeyChart({ links, ariaLabel }) {
991
+ const sources = [...new Set(links.map((link) => link.source))];
992
+ const targets = [...new Set(links.map((link) => link.target))];
993
+ const labels = [...sources, ...targets];
994
+ const graph = (0, import_d3_sankey.sankey)().nodeWidth(14).nodePadding(12).extent([[112, 36], [608, 360]])({
995
+ nodes: labels.map((name, index) => ({ name, colorIndex: index })),
996
+ links: links.map((link) => ({
997
+ source: labels.indexOf(link.source),
998
+ target: labels.indexOf(link.target),
999
+ value: link.value,
1000
+ sourceName: link.source,
1001
+ targetName: link.target,
1002
+ colorIndex: sources.indexOf(link.source)
1003
+ }))
1004
+ });
1005
+ const linkPath = (0, import_d3_sankey.sankeyLinkHorizontal)();
1006
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { className: "sterling-chart", viewBox: "0 0 720 420", role: "img", "aria-label": ariaLabel, children: [
1007
+ graph.links.map((link, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1008
+ "path",
1009
+ {
1010
+ d: linkPath(link) ?? void 0,
1011
+ fill: "none",
1012
+ stroke: sterlingChartColors[link.colorIndex],
1013
+ strokeOpacity: sterlingVisualStyle.opacity.relationship,
1014
+ strokeWidth: Math.max(sterlingVisualStyle.stroke.flowMinimum, link.width ?? sterlingVisualStyle.stroke.flowMinimum),
1015
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: `${link.sourceName} \u2192 ${link.targetName}: ${link.value}` })
1016
+ },
1017
+ `${link.sourceName}-${link.targetName}-${index}`
1018
+ )),
1019
+ graph.nodes.map((node) => {
1020
+ const x0 = node.x0 ?? 0;
1021
+ const x1 = node.x1 ?? x0;
1022
+ const y0 = node.y0 ?? 0;
1023
+ const y1 = node.y1 ?? y0;
1024
+ const sourceSide = (node.depth ?? 0) === 0;
1025
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
1026
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: x0, y: y0, width: Math.max(1, x1 - x0), height: Math.max(1, y1 - y0), rx: "2", fill: sterlingChartColors[node.colorIndex] }),
1027
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: sourceSide ? x0 - 10 : x1 + 10, y: (y0 + y1) / 2 + 4, textAnchor: sourceSide ? "end" : "start", fill: chartText, fontSize: "11", fontFamily: "var(--font-mono)", children: node.name })
1028
+ ] }, node.name);
1029
+ })
1030
+ ] });
1031
+ }
1032
+
1033
+ // src/canonicalCharts.tsx
1034
+ var import_d3_geo = require("d3-geo");
1035
+ var import_d3_hierarchy = require("d3-hierarchy");
1036
+ var import_topojson_client = require("topojson-client");
1037
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1038
+ var muted = "var(--sterling-muted)";
1039
+ var grid = "var(--sterling-grid)";
1040
+ var surface = "var(--sterling-surface)";
1041
+ var text = "var(--sterling-text)";
1042
+ function SterlingVerticalBarChart({ data, ariaLabel, yLabel, xLabel }) {
1043
+ const f = frame(720, 380, { top: 26, right: 26, bottom: 56, left: 70 });
1044
+ const y = linearScale([0, Math.max(...data.map(([, value]) => value), 1)], [f.y1, f.y0], { zero: true });
1045
+ const { centers, step } = bandCenters(data.length, f.x0, f.x1);
1046
+ const width = Math.min(70, step * 0.62);
1047
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 ${f.width} ${f.height}`, role: "img", "aria-label": ariaLabel, children: [
1048
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Gridlines, { scale: y, x0: f.x0, x1: f.x1, count: 5 }),
1049
+ data.map(([label, value], index) => {
1050
+ const cx = centers[index];
1051
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { children: [
1052
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: cx - width / 2, y: y(value), width, height: f.y1 - y(value), rx: "6", fill: sterlingChartColors[index], children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("title", { children: `${label}: ${value.toFixed(1)}` }) }),
1053
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: cx, y: y(value) - 8, textAnchor: "middle", fill: muted, fontSize: "11", fontFamily: "var(--font-mono)", children: value.toFixed(1) }),
1054
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: cx, y: f.y1 + 18, textAnchor: "middle", fill: text, fontSize: "12", fontFamily: "var(--font-mono)", children: label })
1055
+ ] }, label);
1056
+ }),
1057
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AxisLeft, { scale: y, x: f.x0, count: 5, title: yLabel }),
1058
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: f.x0, x2: f.x1, y1: f.y1, y2: f.y1, stroke: "var(--sterling-edge)" }),
1059
+ xLabel ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: (f.x0 + f.x1) / 2, y: f.y1 + 42, textAnchor: "middle", fill: muted, fontSize: "12", fontFamily: "var(--font-mono)", children: xLabel }) : null
1060
+ ] });
1061
+ }
1062
+ function SterlingCandlestickChart({ rows, ariaLabel, yLabel, xLabel }) {
1063
+ const values = rows.flatMap(([, open, high, low, close]) => [open, high, low, close]);
1064
+ const f = frame(720, 380, { top: 26, right: 26, bottom: 56, left: 70 });
1065
+ const y = linearScale(values, [f.y1, f.y0], { padFraction: 0.06 });
1066
+ const { centers, step } = bandCenters(rows.length, f.x0, f.x1);
1067
+ const bodyWidth = Math.min(15, step * 0.62);
1068
+ const rising = sterlingDivergentColors[2];
1069
+ const falling = sterlingDivergentColors[8];
1070
+ const labelStep = Math.max(1, Math.ceil(rows.length / 8));
1071
+ const lastIndex = rows.length - 1;
1072
+ const showDate = (index) => index === lastIndex || index % labelStep === 0 && lastIndex - index >= labelStep * 0.55;
1073
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 ${f.width} ${f.height}`, role: "img", "aria-label": ariaLabel, children: [
1074
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Gridlines, { scale: y, x0: f.x0, x1: f.x1, count: 5 }),
1075
+ rows.map(([date, open, high, low, close], index) => {
1076
+ const x = centers[index];
1077
+ const up = close >= open;
1078
+ const color = up ? rising : falling;
1079
+ const top = y(Math.max(open, close));
1080
+ const bottom = y(Math.min(open, close));
1081
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { children: [
1082
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("title", { children: `${date}: open ${open}, high ${high}, low ${low}, close ${close}` }),
1083
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: x, x2: x, y1: y(high), y2: y(low), stroke: color, strokeWidth: sterlingVisualStyle.stroke.candle }),
1084
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: x - bodyWidth / 2, y: top, width: bodyWidth, height: Math.max(2, bottom - top), rx: "1.5", fill: up ? color : surface, stroke: color, strokeWidth: sterlingVisualStyle.stroke.candle }),
1085
+ showDate(index) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x, y: f.y1 + 18, textAnchor: "middle", fill: muted, fontSize: "10", fontFamily: "var(--font-mono)", children: date }) : null
1086
+ ] }, date);
1087
+ }),
1088
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AxisLeft, { scale: y, x: f.x0, count: 5, title: yLabel, format: (value) => value.toFixed(0) }),
1089
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: f.x0, x2: f.x1, y1: f.y1, y2: f.y1, stroke: "var(--sterling-edge)" }),
1090
+ xLabel ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: (f.x0 + f.x1) / 2, y: f.y1 + 42, textAnchor: "middle", fill: muted, fontSize: "12", fontFamily: "var(--font-mono)", children: xLabel }) : null
1091
+ ] });
1092
+ }
1093
+ function polar(cx, cy, radius, index, count) {
1094
+ const angle = -Math.PI / 2 + index * Math.PI * 2 / count;
1095
+ return [cx + Math.cos(angle) * radius, cy + Math.sin(angle) * radius];
1096
+ }
1097
+ function SterlingRadarChart({ labels, series, domain, ariaLabel, unit = "" }) {
1098
+ const cx = 360, cy = 196, radius = 130;
1099
+ const scale = (value) => (value - domain[0]) / Math.max(domain[1] - domain[0], 1) * radius;
1100
+ const levels = [0.2, 0.4, 0.6, 0.8, 1];
1101
+ const ringValue = (level) => domain[0] + level * (domain[1] - domain[0]);
1102
+ const format = (value) => `${Number.isInteger(value) ? value : value.toFixed(1)}${unit}`;
1103
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "sterling-chart", viewBox: "0 0 720 390", role: "img", "aria-label": ariaLabel, children: [
1104
+ levels.map((level) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polygon", { points: labels.map((_, index) => polar(cx, cy, radius * level, index, labels.length).join(",")).join(" "), fill: "none", stroke: grid }, level)),
1105
+ labels.map((label, index) => {
1106
+ const [x, y] = polar(cx, cy, radius, index, labels.length);
1107
+ const [lx, ly] = polar(cx, cy, radius + 24, index, labels.length);
1108
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { children: [
1109
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: cx, y1: cy, x2: x, y2: y, stroke: grid }),
1110
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: lx, y: ly + 4, textAnchor: "middle", fill: muted, fontSize: "10", fontFamily: "var(--font-mono)", children: label })
1111
+ ] }, label);
1112
+ }),
1113
+ series.map(([name, ...values], index) => {
1114
+ const color = sterlingSequentialColors[Math.min(9, index + 2)];
1115
+ const latest = index === series.length - 1;
1116
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polygon", { points: values.map((value, axis) => polar(cx, cy, scale(value), axis, labels.length).join(",")).join(" "), fill: latest ? color : "none", fillOpacity: sterlingVisualStyle.opacity.surface, stroke: color, strokeWidth: sterlingVisualStyle.stroke.detail, strokeOpacity: latest ? 1 : sterlingVisualStyle.opacity.guide, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("title", { children: `${name}: ${values.join(", ")}` }) }, name);
1117
+ }),
1118
+ [0, ...levels].map((level) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1119
+ "text",
1120
+ {
1121
+ x: cx + 6,
1122
+ y: cy - radius * level + 3,
1123
+ fill: muted,
1124
+ fontSize: "9",
1125
+ fontFamily: "var(--font-mono)",
1126
+ stroke: surface,
1127
+ strokeWidth: sterlingVisualStyle.stroke.halo,
1128
+ paintOrder: "stroke",
1129
+ children: format(ringValue(level))
1130
+ },
1131
+ `r-${level}`
1132
+ ))
1133
+ ] });
1134
+ }
1135
+ function SterlingRidgelineChart({ groups, ariaLabel, xLabel, unit = "" }) {
1136
+ const all = groups.flatMap((group) => group.values);
1137
+ const observedMin = Math.min(...all);
1138
+ const observedMax = Math.max(...all);
1139
+ const margin = (observedMax - observedMin) * 0.08;
1140
+ const domain = [observedMin - margin, observedMax + margin];
1141
+ const x0 = 118, x1 = 664;
1142
+ const baseline = 338;
1143
+ const rowStep = (baseline - 60) / Math.max(groups.length, 1);
1144
+ const amplitude = rowStep * 1.9;
1145
+ const x = linearScale(domain, [x0, x1], { padFraction: 0 });
1146
+ const peak = Math.max(
1147
+ ...groups.map((group) => Math.max(...kernelDensity(group.values, 96, domain).map((point) => point.density))),
1148
+ Number.EPSILON
1149
+ );
1150
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "sterling-chart", viewBox: "0 0 720 390", role: "img", "aria-label": ariaLabel, children: [
1151
+ x.ticks(6).map((value) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: x(value), x2: x(value), y1: 26, y2: baseline, stroke: grid, strokeWidth: sterlingVisualStyle.stroke.grid }, value)),
1152
+ groups.map((source, index) => {
1153
+ const base = 60 + index * rowStep;
1154
+ const density = kernelDensity(source.values, 96, domain);
1155
+ const points = density.map((point) => `${x(point.value)} ${base - point.density / peak * amplitude}`);
1156
+ const color = sterlingChartColors[index % sterlingChartColors.length];
1157
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { children: [
1158
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: x0 - 12, y: base + 3, textAnchor: "end", fill: text, fontSize: "10", fontFamily: "var(--font-mono)", children: source.label }),
1159
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: `M ${x(domain[0])} ${base} L ${points.join(" L ")} L ${x(domain[1])} ${base} Z`, fill: color, fillOpacity: sterlingVisualStyle.opacity.ridge, stroke: color, strokeWidth: sterlingVisualStyle.stroke.series, strokeLinejoin: "round" })
1160
+ ] }, source.label);
1161
+ }),
1162
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AxisBottom, { scale: x, y: baseline, count: 6, title: xLabel, format: (value) => `${value}${unit}` })
1163
+ ] });
1164
+ }
1165
+ function SterlingDensity2DChart({ points, regionLabels, ariaLabel, xLabel, yLabel }) {
1166
+ const f = frame(720, 380, { top: 26, right: 26, bottom: 56, left: 74 });
1167
+ const x = linearScale(points.map((point) => point[0]), [f.x0, f.x1]);
1168
+ const y = linearScale(points.map((point) => point[1]), [f.y1, f.y0]);
1169
+ const pxX = Math.abs(x(1e3) - x(0)) / 1e3;
1170
+ const pxY = Math.abs(y(1) - y(0));
1171
+ const specs = [[4570, 71.26, 559, 0.74, 0.36], [4012, 69.71, 605, 1.02, 0.46], [4611, 71.77, 283, 1.04, -0.03], [4703, 71.23, 664, 1.35, -0.29]];
1172
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 ${f.width} ${f.height}`, role: "img", "aria-label": ariaLabel, children: [
1173
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Gridlines, { scale: y, x0: f.x0, x1: f.x1, count: 5 }),
1174
+ specs.flatMap(([meanX, meanY, sdX, sdY, correlation2], index) => [1, 0.68, 0.38].map((level) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ellipse", { cx: x(meanX), cy: y(meanY), rx: sdX * pxX * 1.7 * level, ry: sdY * pxY * 1.7 * level, transform: `rotate(${-correlation2 * 35} ${x(meanX)} ${y(meanY)})`, fill: sterlingChartColors[index], fillOpacity: sterlingVisualStyle.opacity.contour, stroke: sterlingChartColors[index], strokeWidth: sterlingVisualStyle.stroke.detail }, `${index}-${level}`))),
1175
+ points.map(([income, life, group], index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: x(income), cy: y(life), r: "4", fill: sterlingChartColors[group], fillOpacity: sterlingVisualStyle.opacity.secondaryMark, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("title", { children: `${regionLabels[group]}: ${income}, ${life}` }) }, index)),
1176
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AxisLeft, { scale: y, x: f.x0, count: 5, title: yLabel }),
1177
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AxisBottom, { scale: x, y: f.y1, count: 6, title: xLabel, format: (value) => `${(value / 1e3).toFixed(1)}k` })
1178
+ ] });
1179
+ }
1180
+ function SterlingTreemapChart({ rows, ariaLabel }) {
1181
+ const continents = [...new Set(rows.map(([continent]) => continent))];
1182
+ const rootData = {
1183
+ name: "world",
1184
+ children: continents.map((continent) => ({
1185
+ name: continent,
1186
+ continent,
1187
+ children: rows.filter(([name]) => name === continent).map(([, , country, value]) => ({ name: country, continent, value }))
1188
+ }))
1189
+ };
1190
+ const rankByCountry = /* @__PURE__ */ new Map();
1191
+ continents.forEach((continent) => {
1192
+ const list = rows.filter(([name]) => name === continent).sort((left, right) => right[3] - left[3]);
1193
+ list.forEach(([, , country], index) => rankByCountry.set(country, { rank: index, total: list.length }));
1194
+ });
1195
+ const stopFor = (country) => {
1196
+ const entry = rankByCountry.get(country);
1197
+ if (!entry || entry.total < 2) return sterlingRampStops;
1198
+ return Math.round(sterlingRampStops - entry.rank * (sterlingRampStops - 1) / (entry.total - 1));
1199
+ };
1200
+ const treeRoot = (0, import_d3_hierarchy.hierarchy)(rootData).sum((datum) => datum.value ?? 0).sort((left, right) => (right.value ?? 0) - (left.value ?? 0));
1201
+ const root = (0, import_d3_hierarchy.treemap)().tile(import_d3_hierarchy.treemapSquarify).size([680, 330]).paddingInner(3).paddingOuter(4).paddingTop((node) => node.depth === 1 ? 21 : 0).round(true)(treeRoot);
1202
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "sterling-chart", viewBox: "0 0 720 370", role: "img", "aria-label": ariaLabel, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { transform: "translate(20 20)", children: [
1203
+ root.descendants().filter((node) => node.depth === 1).map((node) => {
1204
+ const color = sterlingChartColors[continents.indexOf(node.data.name)];
1205
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { children: [
1206
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: node.x0, y: node.y0, width: node.x1 - node.x0, height: node.y1 - node.y0, rx: "3", fill: "none", stroke: color, strokeWidth: sterlingVisualStyle.stroke.detail }),
1207
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: node.x0 + 6, y: node.y0 + 13, fill: color, fontSize: "9", fontFamily: "var(--font-mono)", fontWeight: "700", children: node.data.name })
1208
+ ] }, `group-${node.data.name}`);
1209
+ }),
1210
+ root.leaves().map((leaf) => {
1211
+ const continent = leaf.data.continent ?? "";
1212
+ const width = leaf.x1 - leaf.x0;
1213
+ const height = leaf.y1 - leaf.y0;
1214
+ const fontSize = width > 120 ? 10 : 8;
1215
+ const stop = stopFor(leaf.data.name);
1216
+ const fits = width > leaf.data.name.length * fontSize * 0.62 + 10 && height > fontSize * 2.4;
1217
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { children: [
1218
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: leaf.x0, y: leaf.y0, width, height, rx: "2", fill: sterlingRamp(continents.indexOf(continent), stop), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("title", { children: `${leaf.data.name}: ${(leaf.value ?? 0).toLocaleString()}` }) }),
1219
+ fits ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: leaf.x0 + 6, y: leaf.y0 + fontSize + 5, fill: stop > sterlingRampStops / 2 ? surface : text, fontSize, fontFamily: "var(--font-mono)", children: leaf.data.name }) : null
1220
+ ] }, leaf.data.name);
1221
+ })
1222
+ ] }) });
1223
+ }
1224
+ function SterlingNetworkChart({ nodes, edges, ariaLabel }) {
1225
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "sterling-chart", viewBox: "0 0 560 300", role: "img", "aria-label": ariaLabel, children: [
1226
+ edges.map(([source, target], index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: nodes[source][1] + 42, y1: nodes[source][2], x2: nodes[target][1] + 42, y2: nodes[target][2], stroke: grid, strokeWidth: sterlingVisualStyle.stroke.detail }, index)),
1227
+ nodes.map(([name, x, y, degree, community]) => {
1228
+ const radius = 5 + (degree - 10) * 0.45;
1229
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { children: [
1230
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: x + 42, cy: y, r: radius, fill: sterlingChartColors[community], stroke: surface, strokeWidth: sterlingVisualStyle.stroke.mark, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("title", { children: `${name}: ${degree}` }) }),
1231
+ degree >= 19 || name === "Y Holtz" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: x + 42, y: y - radius - 7, textAnchor: "middle", fill: muted, fontSize: "7.5", fontFamily: "var(--font-mono)", children: name }) : null
1232
+ ] }, name);
1233
+ })
1234
+ ] });
1235
+ }
1236
+ function SterlingDendrogramChart({ labels, merge, height, order, groups, ariaLabel, yLabel, cutLabel }) {
1237
+ const leafY = 270, maximum = Math.max(...height), axisX = 78, step = (666 - axisX - 24) / (order.length - 1);
1238
+ const leafX = new Map(order.map((leaf, position) => [leaf, axisX + 12 + position * step]));
1239
+ const groupByLeaf = /* @__PURE__ */ new Map();
1240
+ groups.forEach((members, group) => members.forEach((leaf) => groupByLeaf.set(leaf, group)));
1241
+ const dist = linearScale([0, maximum], [leafY, leafY - 206], { zero: true });
1242
+ const clusters = [];
1243
+ const child = (reference) => reference < 0 ? { x: leafX.get(-reference) ?? axisX, y: leafY, members: [-reference], group: groupByLeaf.get(-reference) ?? null } : clusters[reference - 1];
1244
+ const branches = merge.map(([leftRef, rightRef], index) => {
1245
+ const left = child(leftRef), right = child(rightRef), nodeY = dist(height[index]), members = [...left.members, ...right.members], memberships = [...new Set(members.map((leaf) => groupByLeaf.get(leaf)))], group = memberships.length === 1 ? memberships[0] ?? null : null;
1246
+ clusters.push({ x: (left.x + right.x) / 2, y: nodeY, members, group });
1247
+ return { left, right, y: nodeY, group };
1248
+ });
1249
+ const cut = 0.388, cutY = dist(cut);
1250
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "sterling-chart", viewBox: "0 0 720 390", role: "img", "aria-label": ariaLabel, children: [
1251
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AxisLeft, { scale: dist, x: axisX, gridX1: 666, count: 5, title: yLabel }),
1252
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: axisX, x2: "666", y1: cutY, y2: cutY, stroke: muted, strokeDasharray: "5 5" }),
1253
+ cutLabel ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: "666", y: cutY - 6, textAnchor: "end", fill: muted, fontSize: "9", fontFamily: "var(--font-mono)", children: `${cutLabel} ${cut}` }) : null,
1254
+ groups.map((members, index) => {
1255
+ const positions = members.map((leaf) => leafX.get(leaf) ?? 0);
1256
+ const x0 = Math.min(...positions) - 9, x1 = Math.max(...positions) + 9;
1257
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: x0, y: cutY, width: x1 - x0, height: leafY - cutY + 50, rx: "6", fill: sterlingChartColors[index], fillOpacity: sterlingVisualStyle.opacity.ghost, stroke: sterlingChartColors[index], strokeWidth: sterlingVisualStyle.stroke.detail }, index);
1258
+ }),
1259
+ branches.map(({ left, right, y, group }, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { children: [
1260
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: `M ${left.x} ${left.y} V ${y}`, stroke: left.group === null ? muted : sterlingChartColors[left.group], fill: "none", strokeWidth: sterlingVisualStyle.stroke.detail }),
1261
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: `M ${right.x} ${right.y} V ${y}`, stroke: right.group === null ? muted : sterlingChartColors[right.group], fill: "none", strokeWidth: sterlingVisualStyle.stroke.detail }),
1262
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: `M ${left.x} ${y} H ${right.x}`, stroke: group === null ? muted : sterlingChartColors[group], fill: "none", strokeWidth: sterlingVisualStyle.stroke.detail })
1263
+ ] }, index)),
1264
+ order.map((leaf) => {
1265
+ const x = leafX.get(leaf) ?? 0, group = groupByLeaf.get(leaf) ?? 0;
1266
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { children: [
1267
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: x, cy: leafY, r: "3.5", fill: sterlingChartColors[group] }),
1268
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: x + 3, y: leafY + 12, transform: `rotate(50 ${x + 3} ${leafY + 12})`, fill: muted, fontSize: "7.5", fontFamily: "var(--font-mono)", children: labels[leaf - 1] })
1269
+ ] }, leaf);
1270
+ })
1271
+ ] });
1272
+ }
1273
+ function SterlingVolcanoChart({ hex, labels, ariaLabel, xLabel, yLabel }) {
1274
+ const genes = Array.from({ length: hex.length / 4 }, (_, index) => {
1275
+ const offset = index * 4;
1276
+ return [parseInt(hex.slice(offset, offset + 2), 16) / 255 * 12 - 6, parseInt(hex.slice(offset + 2, offset + 4), 16) / 255 * 5];
1277
+ });
1278
+ const f = frame(720, 380, { top: 26, right: 26, bottom: 56, left: 70 });
1279
+ const x = linearScale([-6, 6], [f.x0, f.x1], { padFraction: 0 });
1280
+ const y = linearScale([0, 5], [f.y1, f.y0], { zero: true });
1281
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 ${f.width} ${f.height}`, role: "img", "aria-label": ariaLabel, children: [
1282
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Gridlines, { scale: y, x0: f.x0, x1: f.x1, count: 5 }),
1283
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: x(0), x2: x(0), y1: f.y0, y2: f.y1, stroke: grid, strokeWidth: sterlingVisualStyle.stroke.grid }),
1284
+ [-1, 1].map((v) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: x(v), x2: x(v), y1: f.y0, y2: f.y1, stroke: sterlingChartColors[7], strokeDasharray: "5 5", strokeOpacity: sterlingVisualStyle.opacity.guide, strokeWidth: sterlingVisualStyle.stroke.grid }, v)),
1285
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: f.x0, x2: f.x1, y1: y(1.3), y2: y(1.3), stroke: sterlingChartColors[7], strokeDasharray: "5 5", strokeOpacity: sterlingVisualStyle.opacity.guide, strokeWidth: sterlingVisualStyle.stroke.grid }),
1286
+ genes.map(([effect, evidence], index) => {
1287
+ const significant = Math.abs(effect) >= 1 && evidence >= 1.3;
1288
+ const color = significant ? effect < 0 ? sterlingChartColors[2] : sterlingChartColors[1] : sterlingChartColors[7];
1289
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: x(effect), cy: y(evidence), r: significant ? 2.5 : 1.6, fill: color, fillOpacity: significant ? sterlingVisualStyle.opacity.signal : sterlingVisualStyle.opacity.mutedMark }, index);
1290
+ }),
1291
+ labels.map(([gene, effect, evidence]) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { children: [
1292
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: x(effect), cy: y(evidence), r: "4", fill: effect < 0 ? sterlingChartColors[2] : sterlingChartColors[1], stroke: surface }),
1293
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: x(effect), y: y(evidence) - 8, textAnchor: "middle", fill: text, fontSize: "8", fontFamily: "var(--font-mono)", children: gene })
1294
+ ] }, gene)),
1295
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AxisLeft, { scale: y, x: f.x0, count: 5, title: yLabel }),
1296
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AxisBottom, { scale: x, y: f.y1, count: 7, title: xLabel })
1297
+ ] });
1298
+ }
1299
+ function SterlingManhattanChart({ hex, labels, chromosomeCenters, ariaLabel, xLabel, yLabel }) {
1300
+ const points = Array.from({ length: hex.length / 8 }, (_, index) => {
1301
+ const offset = index * 8;
1302
+ return [parseInt(hex.slice(offset, offset + 4), 16) / 65535, parseInt(hex.slice(offset + 4, offset + 6), 16) / 255 * 9, parseInt(hex.slice(offset + 6, offset + 8), 16)];
1303
+ });
1304
+ const f = frame(720, 380, { top: 26, right: 26, bottom: 56, left: 70 });
1305
+ const x = (v) => f.x0 + v * (f.x1 - f.x0);
1306
+ const y = linearScale([0, 9], [f.y1, f.y0], { zero: true });
1307
+ const threshold = -Math.log10(5e-8);
1308
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "sterling-chart", viewBox: `0 0 ${f.width} ${f.height}`, role: "img", "aria-label": ariaLabel, children: [
1309
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Gridlines, { scale: y, x0: f.x0, x1: f.x1, count: 5 }),
1310
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: f.x0, x2: f.x1, y1: y(threshold), y2: y(threshold), stroke: sterlingChartColors[5], strokeDasharray: "5 5" }),
1311
+ points.map(([position, evidence, chromosome], index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: x(position), cy: y(evidence), r: evidence >= threshold ? 3 : 1.5, fill: sterlingChartColors[chromosome % 2 === 0 ? 4 : 0], fillOpacity: evidence >= threshold ? 1 : sterlingVisualStyle.opacity.secondaryMark }, index)),
1312
+ labels.slice(0, 1).map(([name, chromosome, position, evidence]) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("g", { children: [
1313
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: x(position), cy: y(evidence), r: "4", fill: sterlingChartColors[chromosome % 2 === 0 ? 4 : 0], stroke: surface }),
1314
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: x(position) + 8, y: y(evidence) - 8, fill: text, fontSize: "8", fontFamily: "var(--font-mono)", children: `chr${chromosome} \xB7 ${name}` })
1315
+ ] }, name)),
1316
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AxisLeft, { scale: y, x: f.x0, count: 5, title: yLabel }),
1317
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: f.x0, x2: f.x1, y1: f.y1, y2: f.y1, stroke: "var(--sterling-edge)" }),
1318
+ chromosomeCenters.map((position, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: x(position), y: f.y1 + 16, textAnchor: "middle", fill: muted, fontSize: "8", fontFamily: "var(--font-mono)", children: index + 1 }, index)),
1319
+ xLabel ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: (f.x0 + f.x1) / 2, y: f.y1 + 42, textAnchor: "middle", fill: muted, fontSize: "12", fontFamily: "var(--font-mono)", children: xLabel }) : null
1320
+ ] });
1321
+ }
1322
+ function correlation(left, right) {
1323
+ const lm = left.reduce((a, b) => a + b, 0) / left.length, rm = right.reduce((a, b) => a + b, 0) / right.length;
1324
+ let n = 0, ls = 0, rs = 0;
1325
+ left.forEach((value, index) => {
1326
+ const l = value - lm, r = right[index] - rm;
1327
+ n += l * r;
1328
+ ls += l * l;
1329
+ rs += r * r;
1330
+ });
1331
+ return n / Math.sqrt(ls * rs);
1332
+ }
1333
+ function clusterVectors(vectors, memberships) {
1334
+ const distances = vectors.map((left, li) => vectors.map((right, ri) => li === ri ? 0 : 1 - correlation(left, right)));
1335
+ let clusters = vectors.map((_, i) => ({ members: [i], left: null, right: null, height: 0, group: memberships[i] }));
1336
+ const meanMembership = (c) => c.members.reduce((s, m) => s + memberships[m], 0) / c.members.length;
1337
+ while (clusters.length > 1) {
1338
+ let bestLeft = 0, bestRight = 1, bestDistance = Number.POSITIVE_INFINITY;
1339
+ for (let i = 0; i < clusters.length; i += 1) {
1340
+ for (let j = i + 1; j < clusters.length; j += 1) {
1341
+ const L2 = clusters[i], R2 = clusters[j];
1342
+ const d = L2.members.reduce((sum, lm) => sum + R2.members.reduce((inner, rm) => inner + distances[lm][rm], 0), 0) / (L2.members.length * R2.members.length);
1343
+ if (d < bestDistance) {
1344
+ bestDistance = d;
1345
+ bestLeft = i;
1346
+ bestRight = j;
1347
+ }
1348
+ }
1349
+ }
1350
+ let L = clusters[bestLeft], R = clusters[bestRight];
1351
+ if (meanMembership(L) > meanMembership(R)) {
1352
+ [L, R] = [R, L];
1353
+ }
1354
+ const members = [...L.members, ...R.members];
1355
+ const groupSet = [...new Set(members.map((m) => memberships[m]))];
1356
+ const merged = { members, left: L, right: R, height: bestDistance, group: groupSet.length === 1 ? groupSet[0] : null };
1357
+ clusters = clusters.filter((_, index) => index !== bestLeft && index !== bestRight);
1358
+ clusters.push(merged);
1359
+ }
1360
+ return clusters[0];
1361
+ }
1362
+ function leafOrder(node) {
1363
+ return node.left ? [...leafOrder(node.left), ...leafOrder(node.right)] : node.members;
1364
+ }
1365
+ function SterlingExpressionChart({ hex, groups, types, ariaLabel }) {
1366
+ const columns = groups.length;
1367
+ const raw = Array.from({ length: hex.length / 2 }, (_, index) => parseInt(hex.slice(index * 2, index * 2 + 2), 16) / 255 * 5 - 2.5);
1368
+ const genes = raw.length / columns;
1369
+ const matrix = Array.from({ length: genes }, (_, row) => raw.slice(row * columns, (row + 1) * columns));
1370
+ const columnVectors = Array.from({ length: columns }, (_, column) => matrix.map((row) => row[column]));
1371
+ const tree = clusterVectors(columnVectors, groups);
1372
+ const order = leafOrder(tree);
1373
+ const cell = 9.25;
1374
+ const startX = 132;
1375
+ const startY = 86;
1376
+ const matrixSize = columns * cell;
1377
+ const columnCenter = (visible) => startX + visible * cell + cell / 2;
1378
+ const rowCenter = (visible) => startY + visible * cell + cell / 2;
1379
+ const branchColor = (node) => node.group === null ? muted : sterlingChartColors[node.group];
1380
+ const maxHeight = Math.max(tree.height, 1e-4);
1381
+ const visibleIndex = new Map(order.map((original, visible) => [original, visible]));
1382
+ const cells = order.flatMap(
1383
+ (row, visibleRow) => order.map((column, visibleColumn) => {
1384
+ const value = correlation(columnVectors[row], columnVectors[column]);
1385
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: startX + visibleColumn * cell, y: startY + visibleRow * cell, width: cell + 0.1, height: cell + 0.1, fill: divergentSignedColor(value, 1), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("title", { children: `${types[groups[row]]} \xD7 ${types[groups[column]]}: r ${value.toFixed(2)}` }) }, `${visibleRow}-${visibleColumn}`);
1386
+ })
1387
+ );
1388
+ const topAnnotations = order.map((column, visible) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: startX + visible * cell, y: "78", width: cell + 0.1, height: "5", fill: sterlingChartColors[groups[column]] }, `ta-${visible}`));
1389
+ const leftAnnotations = order.map((row, visible) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: "124", y: startY + visible * cell, width: "5", height: cell + 0.1, fill: sterlingChartColors[groups[row]] }, `la-${visible}`));
1390
+ const runs = [];
1391
+ order.forEach((column, index) => {
1392
+ const group = groups[column];
1393
+ const previous = runs[runs.length - 1];
1394
+ if (previous && previous.group === group) previous.length += 1;
1395
+ else runs.push({ group, start: index, length: 1 });
1396
+ });
1397
+ const regionFrames = runs.map(({ group, start, length }, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: startX + start * cell + 0.7, y: startY + start * cell + 0.7, width: length * cell - 1.4, height: length * cell - 1.4, fill: "none", stroke: sterlingChartColors[group], strokeWidth: sterlingVisualStyle.stroke.series }, `rf-${index}`));
1398
+ const topMarks = [];
1399
+ let topKey = 0;
1400
+ const renderTop = (node) => {
1401
+ if (!node.left) return { x: columnCenter(visibleIndex.get(node.members[0])), y: 75 };
1402
+ const l = renderTop(node.left);
1403
+ const r = renderTop(node.right);
1404
+ const y = 75 - node.height / maxHeight * 55;
1405
+ const x = (l.x + r.x) / 2;
1406
+ topMarks.push(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: `M${l.x} ${l.y} V${y}`, fill: "none", stroke: branchColor(node.left), strokeWidth: sterlingVisualStyle.stroke.grid }, `tm-${topKey++}`));
1407
+ topMarks.push(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: `M${r.x} ${r.y} V${y}`, fill: "none", stroke: branchColor(node.right), strokeWidth: sterlingVisualStyle.stroke.grid }, `tm-${topKey++}`));
1408
+ topMarks.push(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: `M${l.x} ${y} H${r.x}`, fill: "none", stroke: branchColor(node), strokeWidth: sterlingVisualStyle.stroke.grid }, `tm-${topKey++}`));
1409
+ return { x, y };
1410
+ };
1411
+ renderTop(tree);
1412
+ const leftMarks = [];
1413
+ let leftKey = 0;
1414
+ const renderLeft = (node) => {
1415
+ if (!node.left) return { x: 121, y: rowCenter(visibleIndex.get(node.members[0])) };
1416
+ const l = renderLeft(node.left);
1417
+ const r = renderLeft(node.right);
1418
+ const x = 121 - node.height / maxHeight * 78;
1419
+ const y = (l.y + r.y) / 2;
1420
+ leftMarks.push(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: `M${l.x} ${l.y} H${x}`, fill: "none", stroke: branchColor(node.left), strokeWidth: sterlingVisualStyle.stroke.grid }, `lm-${leftKey++}`));
1421
+ leftMarks.push(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: `M${r.x} ${r.y} H${x}`, fill: "none", stroke: branchColor(node.right), strokeWidth: sterlingVisualStyle.stroke.grid }, `lm-${leftKey++}`));
1422
+ leftMarks.push(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: `M${x} ${l.y} V${r.y}`, fill: "none", stroke: branchColor(node), strokeWidth: sterlingVisualStyle.stroke.grid }, `lm-${leftKey++}`));
1423
+ return { x, y };
1424
+ };
1425
+ renderLeft(tree);
1426
+ const rowLabels = order.map((row, visible) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: startX + matrixSize + 7, y: startY + visible * cell + 6.3, fill: muted, fontSize: "6", fontFamily: "var(--font-mono)", children: `${types[groups[row]]} ${row % 4 + 1}` }, `rl-${visible}`));
1427
+ const legendStops = Array.from({ length: 21 }, (_, index) => {
1428
+ const value = -1 + index / 20 * 2;
1429
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: 132 + index * 5, y: "394", width: "5.2", height: "8", fill: divergentSignedColor(value, 1) }, `ls-${index}`);
1430
+ });
1431
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "sterling-chart", viewBox: "0 0 600 416", role: "img", "aria-label": ariaLabel, children: [
1432
+ topMarks,
1433
+ leftMarks,
1434
+ topAnnotations,
1435
+ leftAnnotations,
1436
+ cells,
1437
+ regionFrames,
1438
+ rowLabels,
1439
+ legendStops,
1440
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: "126", y: "401", textAnchor: "end", fill: muted, fontSize: "6.4", fontFamily: "var(--font-mono)", children: "-1" }),
1441
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: "242", y: "401", fill: muted, fontSize: "6.4", fontFamily: "var(--font-mono)", children: "+1 r" })
1442
+ ] });
1443
+ }
1444
+ function SterlingGeoMapChart({ atlas, rows, ariaLabel }) {
1445
+ const topology = atlas;
1446
+ const collection = (0, import_topojson_client.feature)(atlas, topology.objects.states);
1447
+ const projection = (0, import_d3_geo.geoAlbersUsa)().fitSize([620, 286], collection);
1448
+ const path = (0, import_d3_geo.geoPath)(projection);
1449
+ const valueById = new Map(rows.map((row) => [row.id, row]));
1450
+ const maximum = Math.max(...rows.map((row) => row.engineers));
1451
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "sterling-chart", viewBox: "0 0 720 390", role: "img", "aria-label": ariaLabel, children: [
1452
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("g", { transform: "translate(50 18)", children: collection.features.map((state, index) => {
1453
+ const id = Number(state.id), row = valueById.get(id), value = row?.engineers ?? 0, colorIndex = Math.min(9, Math.max(0, Math.round(value / maximum * 9)));
1454
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: path(state) ?? void 0, fill: sterlingSequentialColors[colorIndex], stroke: surface, strokeWidth: sterlingVisualStyle.stroke.grid, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("title", { children: `${row?.state ?? `State ${id}`}: ${(value * 100).toFixed(2)}%` }) }, id || index);
1455
+ }) }),
1456
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: "132", y: "342", textAnchor: "end", fill: muted, fontSize: "9", fontFamily: "var(--font-mono)", children: "0%" }),
1457
+ sterlingSequentialColors.map((color, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: 142 + index * 40, y: "330", width: "40", height: "14", fill: color }, color)),
1458
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("text", { x: "552", y: "342", fill: muted, fontSize: "9", fontFamily: "var(--font-mono)", children: [
1459
+ (maximum * 100).toFixed(2),
1460
+ "%"
1461
+ ] }),
1462
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("text", { x: "360", y: "370", textAnchor: "middle", fill: muted, fontSize: "10", fontFamily: "var(--font-mono)", children: "engineers as share of population / proporci\xF3n de ingenieros" })
1463
+ ] });
1464
+ }
1465
+
1466
+ // src/dataExport.ts
1467
+ function csvCell(value) {
1468
+ if (value === null || value === void 0) return "";
1469
+ if (value instanceof Date) return value.toISOString();
1470
+ if (typeof value === "object") return JSON.stringify(value);
1471
+ return String(value);
1472
+ }
1473
+ function escapeCsvCell(value) {
1474
+ const cell = csvCell(value);
1475
+ return /[\",\n\r]/.test(cell) ? `"${cell.replace(/"/g, '""')}"` : cell;
1476
+ }
1477
+ function sterlingRowsToCsv(rows) {
1478
+ const columns = [...new Set(rows.flatMap((row) => Object.keys(row)))];
1479
+ return [
1480
+ columns.map(escapeCsvCell).join(","),
1481
+ ...rows.map((row) => columns.map((column) => escapeCsvCell(row[column])).join(","))
1482
+ ].join("\r\n");
1483
+ }
1484
+ function rowsFromArray(values) {
1485
+ return values.map((value) => {
1486
+ if (Array.isArray(value)) {
1487
+ return Object.fromEntries(value.map((cell, index) => [`value_${index + 1}`, cell]));
1488
+ }
1489
+ if (value && typeof value === "object") return value;
1490
+ return { value };
1491
+ });
1492
+ }
1493
+ function inferSterlingDataExport(props) {
1494
+ if (Array.isArray(props.data)) return { rows: rowsFromArray(props.data) };
1495
+ if (Array.isArray(props.rows)) return { rows: rowsFromArray(props.rows) };
1496
+ if (Array.isArray(props.links)) return { rows: rowsFromArray(props.links) };
1497
+ if (Array.isArray(props.points)) return { rows: rowsFromArray(props.points) };
1498
+ if (Array.isArray(props.groups)) {
1499
+ const groups = props.groups;
1500
+ if (groups.every((group) => Array.isArray(group.values))) {
1501
+ return {
1502
+ rows: groups.flatMap((group) => group.values.map((value) => ({ group: group.label, value })))
1503
+ };
1504
+ }
1505
+ }
1506
+ if (Array.isArray(props.values)) {
1507
+ const values = props.values;
1508
+ if (values.every((value) => typeof value === "number")) return { rows: values.map((value) => ({ value })) };
1509
+ if (values.every(Array.isArray)) {
1510
+ const rowLabels = Array.isArray(props.rowLabels) ? props.rowLabels : [];
1511
+ const columnLabels = Array.isArray(props.columnLabels) ? props.columnLabels : [];
1512
+ return {
1513
+ rows: values.flatMap((row, rowIndex) => row.map((value, columnIndex) => ({
1514
+ row: rowLabels[rowIndex] ?? rowIndex + 1,
1515
+ column: columnLabels[columnIndex] ?? columnIndex + 1,
1516
+ value
1517
+ })))
1518
+ };
1519
+ }
1520
+ }
1521
+ if (Array.isArray(props.series) && Array.isArray(props.labels)) {
1522
+ const labels = props.labels;
1523
+ const series = props.series;
1524
+ if (series.every((item) => Array.isArray(item.values))) {
1525
+ return {
1526
+ rows: labels.map((label, index) => Object.fromEntries([
1527
+ ["label", label],
1528
+ ...series.map((item) => [String(item.label ?? "value"), item.values[index]])
1529
+ ]))
1530
+ };
1531
+ }
1532
+ }
1533
+ if (Array.isArray(props.nodes)) return { rows: rowsFromArray(props.nodes) };
1534
+ return void 0;
1535
+ }
1536
+
1537
+ // src/editorial.tsx
1538
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1539
+ function sterlingCredit({
1540
+ author,
1541
+ productName = "Sterling",
1542
+ linkToSterling = true,
1543
+ sterlingUrl = "https://www.lamatemaga.com/sterling"
1544
+ }, locale = "en") {
1545
+ const product = linkToSterling ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("a", { className: "sterling-figure__credit-link", href: sterlingUrl, children: [
1546
+ productName,
1547
+ " \u2726"
1548
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1549
+ productName,
1550
+ " \u2726"
1551
+ ] });
1552
+ if (locale === "es") {
1553
+ return author ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1554
+ "Hecho por ",
1555
+ author,
1556
+ " con ",
1557
+ product
1558
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1559
+ "Hecho con ",
1560
+ product
1561
+ ] });
1562
+ }
1563
+ return author ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1564
+ "Made by ",
1565
+ author,
1566
+ " with ",
1567
+ product
1568
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1569
+ "Made with ",
1570
+ product
1571
+ ] });
1572
+ }
1573
+
1574
+ // src/tailwind.ts
1575
+ var orderedStops = [100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
1576
+ var rampStops = [200, 300, 400, 500, 600, 700, 800];
1577
+ function at(scale, stop, fallback) {
1578
+ return scale[stop] ?? fallback;
1579
+ }
1580
+ function createTailwindSterlingPalette({
1581
+ categorical,
1582
+ surface: surface2,
1583
+ divergent,
1584
+ heat
1585
+ }) {
1586
+ const first = categorical[0] ?? {};
1587
+ const categoricalValues = categorical.map((scale) => at(scale, 500, "currentColor"));
1588
+ return defineSterlingPalette({
1589
+ surface: surface2,
1590
+ categorical: categoricalValues,
1591
+ legend: categorical.map((scale) => at(scale, 700, at(scale, 500, "currentColor"))),
1592
+ sequential: orderedStops.map((stop) => at(first, stop, at(first, 500, "currentColor"))),
1593
+ divergent: orderedStops.map((stop) => at(divergent ?? first, stop, at(first, 500, "currentColor"))),
1594
+ heat: orderedStops.concat(950).map((stop) => at(heat ?? first, stop, at(first, 500, "currentColor"))).slice(0, 11),
1595
+ ramps: categorical.map((scale) => rampStops.map((stop) => at(scale, stop, at(scale, 500, "currentColor"))))
1596
+ });
1597
+ }
1598
+ // Annotate the CommonJS export names for ESM import in node:
1599
+ 0 && (module.exports = {
1600
+ AXIS_TITLE,
1601
+ AxisBottom,
1602
+ AxisLeft,
1603
+ Gridlines,
1604
+ SterlingBarChart,
1605
+ SterlingBoxPlot,
1606
+ SterlingCandlestickChart,
1607
+ SterlingChordChart,
1608
+ SterlingCorrelogram,
1609
+ SterlingDendrogramChart,
1610
+ SterlingDensity2DChart,
1611
+ SterlingDensityChart,
1612
+ SterlingDonutChart,
1613
+ SterlingDumbbellChart,
1614
+ SterlingExpressionChart,
1615
+ SterlingGeoMapChart,
1616
+ SterlingHeatmap,
1617
+ SterlingHistogram,
1618
+ SterlingInlineLegend,
1619
+ SterlingLineChart,
1620
+ SterlingLollipopChart,
1621
+ SterlingManhattanChart,
1622
+ SterlingNetworkChart,
1623
+ SterlingPieChart,
1624
+ SterlingRadarChart,
1625
+ SterlingRidgelineChart,
1626
+ SterlingSankeyChart,
1627
+ SterlingScatterPlot,
1628
+ SterlingSequentialSurface,
1629
+ SterlingTreemapChart,
1630
+ SterlingVerticalBarChart,
1631
+ SterlingViolinPlot,
1632
+ SterlingVolcanoChart,
1633
+ TICK,
1634
+ TICK_LABEL,
1635
+ TimeAxisBottom,
1636
+ axisGrid,
1637
+ axisLine,
1638
+ axisMuted,
1639
+ axisText,
1640
+ bandCenters,
1641
+ createTailwindSterlingPalette,
1642
+ defaultMargin,
1643
+ defineSterlingPalette,
1644
+ divergentSignedColor,
1645
+ divergentSignedRamp,
1646
+ frame,
1647
+ inferSterlingDataExport,
1648
+ kernelDensity,
1649
+ linearScale,
1650
+ sterlingCategorical,
1651
+ sterlingChartColors,
1652
+ sterlingColorNames,
1653
+ sterlingCredit,
1654
+ sterlingDivergentColors,
1655
+ sterlingHeatColors,
1656
+ sterlingLegendColors,
1657
+ sterlingPaletteStyle,
1658
+ sterlingRamp,
1659
+ sterlingRampStops,
1660
+ sterlingRowsToCsv,
1661
+ sterlingSequentialColors,
1662
+ sterlingVisualStyle,
1663
+ timeScale,
1664
+ tukeySummary
1665
+ });
1666
+ //# sourceMappingURL=server.js.map