@pixerate/editor 0.164.0 → 0.166.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/agent/index.cjs +54 -39
- package/dist/agent/index.js +24 -9
- package/dist/animation/index.cjs +6 -5
- package/dist/animation/index.js +5 -4
- package/dist/animation-editor/index.cjs +65 -64
- package/dist/animation-editor/index.js +8 -7
- package/dist/bridge/cli.cjs +3 -3
- package/dist/bridge/cli.js +2 -2
- package/dist/bridge/index.cjs +3 -3
- package/dist/bridge/index.js +2 -2
- package/dist/canvas/index.cjs +89 -87
- package/dist/canvas/index.js +11 -9
- package/dist/chart/controller.d.cts +60 -2
- package/dist/chart/controller.d.ts +60 -2
- package/dist/chart/index.cjs +657 -163
- package/dist/chart/index.d.cts +3 -0
- package/dist/chart/index.d.ts +3 -0
- package/dist/chart/index.js +512 -18
- package/dist/chart/layout-families.d.cts +14 -0
- package/dist/chart/layout-families.d.ts +14 -0
- package/dist/chart/layout-shared.d.cts +5 -0
- package/dist/chart/layout-shared.d.ts +5 -0
- package/dist/chart/links.d.cts +34 -0
- package/dist/chart/links.d.ts +34 -0
- package/dist/chart/mermaid.d.cts +9 -6
- package/dist/chart/mermaid.d.ts +9 -6
- package/dist/chart/race.d.cts +26 -0
- package/dist/chart/race.d.ts +26 -0
- package/dist/chart/schemas.d.cts +5 -0
- package/dist/chart/schemas.d.ts +5 -0
- package/dist/chart/spec.d.cts +3 -2
- package/dist/chart/spec.d.ts +3 -2
- package/dist/chart/style.d.cts +33 -0
- package/dist/chart/style.d.ts +33 -0
- package/dist/chart/types.d.cts +28 -2
- package/dist/chart/types.d.ts +28 -2
- package/dist/{chunk-ZVNAMTFO.cjs → chunk-3FSUJIXN.cjs} +18 -174
- package/dist/{chunk-RQCMSEM5.cjs → chunk-4QUUHTGJ.cjs} +2 -2
- package/dist/{chunk-CIPIESX4.cjs → chunk-4ZC5QJE2.cjs} +3 -3
- package/dist/{chunk-S6X2QRVU.cjs → chunk-5UEFBM2M.cjs} +1 -138
- package/dist/{chunk-5FNGLV2D.js → chunk-5UNQDC3Q.js} +18 -3
- package/dist/{chunk-YSAGBIRW.cjs → chunk-6FYIFGBW.cjs} +16 -16
- package/dist/{chunk-QYZGBVNC.js → chunk-7272D3K2.js} +10 -8
- package/dist/{chunk-462WGGXX.cjs → chunk-AMX23CSN.cjs} +27 -16
- package/dist/{chunk-3VLOOO3G.js → chunk-BDIM6NVW.js} +1 -1
- package/dist/{chunk-R3P2M7HU.cjs → chunk-BPX4Z3N3.cjs} +355 -207
- package/dist/{chunk-D54JHQK2.cjs → chunk-CHLV7UFP.cjs} +51 -51
- package/dist/{chunk-OXERWBKE.js → chunk-DFCAR7AW.js} +3 -3
- package/dist/{chunk-GZ2FM3ZB.js → chunk-DKNEQX7T.js} +6 -162
- package/dist/{chunk-JCXMJUQO.cjs → chunk-EGZM52EO.cjs} +3 -3
- package/dist/{chunk-ES3UEVUT.cjs → chunk-EUIDTZNQ.cjs} +112 -110
- package/dist/{chunk-H3OEM3Q2.js → chunk-F6R67I3A.js} +1 -1
- package/dist/{chunk-3NEZJCBY.js → chunk-FR432ROA.js} +349 -201
- package/dist/chunk-HIDFL5LQ.js +484 -0
- package/dist/{chunk-22KLZZGH.cjs → chunk-HXOBOHH2.cjs} +8 -8
- package/dist/{chunk-MKTDELCD.js → chunk-I5MRJW7B.js} +1 -1
- package/dist/{chunk-SDHZG5TF.js → chunk-ILP77UD6.js} +160 -2
- package/dist/{chunk-Z4P2RBMJ.js → chunk-ITANXMZD.js} +177 -3
- package/dist/chunk-KGRZMHZB.js +204 -0
- package/dist/{chunk-SET6KJOP.js → chunk-LPIKXPBM.js} +1 -1
- package/dist/{chunk-BQWGN5WH.js → chunk-M2TPMYJE.js} +1 -1
- package/dist/{chunk-GTELFJRE.cjs → chunk-M5GLQQWG.cjs} +2 -2
- package/dist/{chunk-4VU4CP7R.js → chunk-MHLU6GRJ.js} +1 -138
- package/dist/{chunk-NZD2MZJC.cjs → chunk-MZFZSVUJ.cjs} +38 -23
- package/dist/{chunk-DAPQGA55.js → chunk-NQQDGGXY.js} +2 -2
- package/dist/chunk-O6OGNDND.js +164 -0
- package/dist/{chunk-PA3IMPPS.cjs → chunk-OVYQAYGH.cjs} +81 -81
- package/dist/{chunk-YXOW456B.js → chunk-PPEDZ5WR.js} +1 -1
- package/dist/{chunk-24M7VD6M.cjs → chunk-S4EIAIEW.cjs} +7 -7
- package/dist/{chunk-M4MIZPQI.cjs → chunk-SJ2CPTQC.cjs} +189 -15
- package/dist/{chunk-YGG7WDWT.cjs → chunk-SZWVMB3B.cjs} +24 -18
- package/dist/chunk-TFF2GTGN.cjs +153 -0
- package/dist/chunk-TTCJPX4U.cjs +204 -0
- package/dist/{chunk-SBQVEBSU.cjs → chunk-UUUTEVX6.cjs} +242 -68
- package/dist/{chunk-WI7QJA7A.cjs → chunk-UXETV2NC.cjs} +161 -3
- package/dist/{chunk-GKNEJ6EN.cjs → chunk-V5L2G22R.cjs} +321 -107
- package/dist/{chunk-TALQONZ5.js → chunk-VB2CY6EG.js} +3 -3
- package/dist/{chunk-QY4KUDMY.js → chunk-VRXXAXUT.js} +2 -2
- package/dist/chunk-VU6WQSMB.cjs +164 -0
- package/dist/{chunk-NHLYK3AX.js → chunk-XBQX76CT.js} +182 -8
- package/dist/{chunk-5AARIS3R.cjs → chunk-XCDGM7TD.cjs} +37 -37
- package/dist/{chunk-POR54B55.js → chunk-XNU45TYA.js} +7 -1
- package/dist/{chunk-EVXQNQND.js → chunk-XZB3TJ6K.js} +16 -5
- package/dist/chunk-YBAPT7NL.js +153 -0
- package/dist/{chunk-SZA42R4N.js → chunk-YUFTVNLX.js} +230 -16
- package/dist/chunk-Z2UQYMPS.cjs +484 -0
- package/dist/color/index.cjs +5 -3
- package/dist/color/index.js +12 -10
- package/dist/diagram/index.cjs +55 -243
- package/dist/diagram/index.js +12 -200
- package/dist/export/index.cjs +7 -6
- package/dist/export/index.js +6 -5
- package/dist/extensions/index.cjs +12 -9
- package/dist/extensions/index.js +11 -8
- package/dist/gradient/index.cjs +29 -27
- package/dist/gradient/index.js +6 -4
- package/dist/image-editor/index.cjs +644 -643
- package/dist/image-editor/index.js +7 -6
- package/dist/index.cjs +21 -18
- package/dist/index.js +14 -11
- package/dist/paint-editor/index.cjs +19 -18
- package/dist/paint-editor/index.js +7 -6
- package/dist/parameters/index.cjs +2 -2
- package/dist/parameters/index.js +1 -1
- package/dist/persistence/assetWrites.d.cts +22 -0
- package/dist/persistence/assetWrites.d.ts +22 -0
- package/dist/persistence/assets.d.cts +71 -0
- package/dist/persistence/assets.d.ts +71 -0
- package/dist/persistence/documentStore.d.cts +17 -1
- package/dist/persistence/documentStore.d.ts +17 -1
- package/dist/persistence/documentTools.d.cts +5 -1
- package/dist/persistence/documentTools.d.ts +5 -1
- package/dist/persistence/editorAutosave.d.cts +7 -0
- package/dist/persistence/editorAutosave.d.ts +7 -0
- package/dist/persistence/index.cjs +141 -21
- package/dist/persistence/index.js +130 -10
- package/dist/persistence/storage.d.cts +13 -1
- package/dist/persistence/storage.d.ts +13 -1
- package/dist/spreadsheet/index.cjs +3 -3
- package/dist/spreadsheet/index.js +2 -2
- package/dist/tokens/index.cjs +11 -3
- package/dist/tokens/index.d.cts +1 -0
- package/dist/tokens/index.d.ts +1 -0
- package/dist/tokens/index.js +10 -2
- package/dist/tokens/style.d.cts +36 -0
- package/dist/tokens/style.d.ts +36 -0
- package/dist/tools/index.cjs +15 -3
- package/dist/tools/index.d.cts +2 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.js +14 -2
- package/dist/tools/style-tools.d.cts +19 -0
- package/dist/tools/style-tools.d.ts +19 -0
- package/dist/tools/style.d.cts +212 -0
- package/dist/tools/style.d.ts +212 -0
- package/dist/tools/view.d.cts +6 -0
- package/dist/tools/view.d.ts +6 -0
- package/dist/typography/index.cjs +8 -6
- package/dist/typography/index.js +5 -3
- package/dist/vector/index.cjs +953 -952
- package/dist/vector/index.js +7 -6
- package/dist/video-editor/index.cjs +8 -7
- package/dist/video-editor/index.js +6 -5
- package/package.json +1 -1
- package/skills/pixerate-chart/SKILL.md +20 -2
- package/dist/chunk-ERAGQL2N.cjs +0 -68
- package/dist/chunk-KMU6QJB7.js +0 -68
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
var _chunkTTCJPX4Ucjs = require('./chunk-TTCJPX4U.cjs');
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
var _chunkSBQVEBSUcjs = require('./chunk-SBQVEBSU.cjs');
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
var _chunkUUUTEVX6cjs = require('./chunk-UUUTEVX6.cjs');
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
|
|
@@ -36,7 +37,15 @@ var _chunkSBQVEBSUcjs = require('./chunk-SBQVEBSU.cjs');
|
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
var _chunkBPX4Z3N3cjs = require('./chunk-BPX4Z3N3.cjs');
|
|
40
49
|
|
|
41
50
|
|
|
42
51
|
|
|
@@ -71,9 +80,14 @@ function splitOutside(text, sep) {
|
|
|
71
80
|
out.push(cur);
|
|
72
81
|
return out;
|
|
73
82
|
}
|
|
83
|
+
var csvField = (text) => /[",\n]|^\s|\s$/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
|
|
84
|
+
var treemapName = (name) => !name.includes('"') ? `"${name}"` : !name.includes("'") ? `'${name}'` : `"${name.replace(/"/g, "'")}"`;
|
|
85
|
+
var yamlText = (text) => /^[\w][\w .,!?()/&+-]*$/.test(text) && !/:\s/.test(text) ? text : JSON.stringify(text);
|
|
74
86
|
function chartMermaidFamily(spec) {
|
|
75
|
-
const family =
|
|
76
|
-
if (family === "
|
|
87
|
+
const family = _chunkBPX4Z3N3cjs.chartFamily.call(void 0, spec);
|
|
88
|
+
if (family === "sankey" && _optionalChain([spec, 'access', _2 => _2.links, 'optionalAccess', _3 => _3.length])) return "sankey";
|
|
89
|
+
if (family === "treemap" || family === "sunburst") return "treemap";
|
|
90
|
+
if (family === "pie" || family === "funnel" || family === "parliament") return "pie";
|
|
77
91
|
if (family === "radar") return "radar";
|
|
78
92
|
return "xychart";
|
|
79
93
|
}
|
|
@@ -114,12 +128,32 @@ function chartToMermaid(spec, options = {}) {
|
|
|
114
128
|
const visible = spec.series.filter((s) => !s.hidden);
|
|
115
129
|
const lines = [];
|
|
116
130
|
const v = (x) => x === null || !Number.isFinite(x) ? "0" : num(x);
|
|
117
|
-
|
|
131
|
+
const front = [];
|
|
132
|
+
if (family === "sankey") {
|
|
133
|
+
if (spec.title) front.push("---", `title: ${yamlText(spec.title)}`, "---");
|
|
134
|
+
lines.push("sankey-beta");
|
|
135
|
+
for (const l of spec.links) lines.push(`${csvField(l.source)},${csvField(l.target)},${num(l.value)}`);
|
|
136
|
+
} else if (family === "treemap") {
|
|
137
|
+
lines.push("treemap-beta");
|
|
138
|
+
if (spec.title) lines.push(`title ${spec.title}`);
|
|
139
|
+
const first = _nullishCoalesce(visible[0], () => ( spec.series[0]));
|
|
140
|
+
const tree = spec.tree.length ? spec.tree : _chunkBPX4Z3N3cjs.chartTreeFromSeries.call(void 0, spec.categories, _nullishCoalesce(_optionalChain([first, 'optionalAccess', _4 => _4.values]), () => ( [])));
|
|
141
|
+
const write = (nodes, depth) => {
|
|
142
|
+
for (const n of nodes) {
|
|
143
|
+
const pad = ind.repeat(depth);
|
|
144
|
+
if (n.children) {
|
|
145
|
+
lines.push(`${pad}${treemapName(n.name)}`);
|
|
146
|
+
write(n.children, depth + 1);
|
|
147
|
+
} else lines.push(`${pad}${treemapName(n.name)}: ${num(_nullishCoalesce(n.value, () => ( 0)))}`);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
write(tree, 1);
|
|
151
|
+
} else if (family === "pie") {
|
|
118
152
|
const s = _nullishCoalesce(visible[0], () => ( spec.series[0]));
|
|
119
153
|
lines.push(`pie${spec.dataLabels ? " showData" : ""}`);
|
|
120
154
|
if (spec.title) lines.push(`${ind}title ${spec.title}`);
|
|
121
155
|
spec.categories.forEach((c, i) => {
|
|
122
|
-
const value = _optionalChain([s, 'optionalAccess',
|
|
156
|
+
const value = _optionalChain([s, 'optionalAccess', _5 => _5.values, 'access', _6 => _6[i]]);
|
|
123
157
|
if (value !== null && value !== void 0 && Number.isFinite(value) && value > 0) lines.push(`${ind}${quote(c)} : ${num(value)}`);
|
|
124
158
|
});
|
|
125
159
|
} else if (family === "radar") {
|
|
@@ -160,13 +194,13 @@ function chartToMermaid(spec, options = {}) {
|
|
|
160
194
|
lines.push(`${ind}${kind} ${quote(s.name)} [${s.values.map(v).join(", ")}]`);
|
|
161
195
|
}
|
|
162
196
|
}
|
|
163
|
-
let text = `${lines.join("\n")}
|
|
197
|
+
let text = `${[...front, ...lines].join("\n")}
|
|
164
198
|
`;
|
|
165
199
|
if (options.meta !== false) {
|
|
166
200
|
const meta = metaFor(spec, text);
|
|
167
201
|
if (meta) {
|
|
168
202
|
const [header, ...rest] = lines;
|
|
169
|
-
text = `${[header, `${CHART_MERMAID_META_PREFIX}${JSON.stringify({ v: 1, ...meta })}`, ...rest].join("\n")}
|
|
203
|
+
text = `${[...front, header, `${CHART_MERMAID_META_PREFIX}${JSON.stringify({ v: 1, ...meta })}`, ...rest].join("\n")}
|
|
170
204
|
`;
|
|
171
205
|
}
|
|
172
206
|
}
|
|
@@ -202,7 +236,7 @@ function chartFromMermaid(text, options = {}) {
|
|
|
202
236
|
const all = text.replace(/^/, "").split(/\r?\n/);
|
|
203
237
|
let start = 0;
|
|
204
238
|
let frontTitle;
|
|
205
|
-
if (_optionalChain([all, 'access',
|
|
239
|
+
if (_optionalChain([all, 'access', _7 => _7[0], 'optionalAccess', _8 => _8.trim, 'call', _9 => _9()]) === "---") {
|
|
206
240
|
const end = all.findIndex((l, i) => i > 0 && l.trim() === "---");
|
|
207
241
|
if (end > 0) {
|
|
208
242
|
for (const l of all.slice(1, end)) {
|
|
@@ -223,21 +257,23 @@ function chartFromMermaid(text, options = {}) {
|
|
|
223
257
|
let m;
|
|
224
258
|
if (m = /^xychart(?:-beta)?(?:\s+(horizontal|vertical))?\s*$/i.exec(t)) {
|
|
225
259
|
family = "xychart";
|
|
226
|
-
horizontal = _optionalChain([m, 'access',
|
|
260
|
+
horizontal = _optionalChain([m, 'access', _10 => _10[1], 'optionalAccess', _11 => _11.toLowerCase, 'call', _12 => _12()]) === "horizontal";
|
|
227
261
|
} else if (m = /^pie(\s+showData)?(?:\s+title\s+(.*))?\s*$/i.exec(t)) {
|
|
228
262
|
family = "pie";
|
|
229
263
|
showData = !!m[1];
|
|
230
264
|
if (m[2]) frontTitle = m[2].trim();
|
|
231
265
|
} else if (/^radar(?:-beta)?\s*$/i.test(t)) family = "radar";
|
|
232
|
-
else
|
|
266
|
+
else if (/^sankey(?:-beta)?\s*$/i.test(t)) family = "sankey";
|
|
267
|
+
else if (/^treemap(?:-beta)?\s*$/i.test(t)) family = "treemap";
|
|
268
|
+
else issues.push({ path: "header", line: i + 1, message: `Line ${i + 1}: expected a chart header (xychart-beta, pie, radar-beta, sankey-beta or treemap-beta), got "${t.slice(0, 40)}".` });
|
|
233
269
|
headerLine = i;
|
|
234
270
|
break;
|
|
235
271
|
}
|
|
236
272
|
let title = _nullishCoalesce(frontTitle, () => ( ""));
|
|
237
273
|
const categories = [];
|
|
238
274
|
const series = [];
|
|
239
|
-
const xAxis =
|
|
240
|
-
const yAxis =
|
|
275
|
+
const xAxis = _chunkBPX4Z3N3cjs.defaultChartAxis.call(void 0, false);
|
|
276
|
+
const yAxis = _chunkBPX4Z3N3cjs.defaultChartAxis.call(void 0, true);
|
|
241
277
|
const radarAxes = [];
|
|
242
278
|
const pieSlices = [];
|
|
243
279
|
let legendShow = true;
|
|
@@ -245,6 +281,7 @@ function chartFromMermaid(text, options = {}) {
|
|
|
245
281
|
let graticule = "circle";
|
|
246
282
|
const counts = { bar: 0, line: 0 };
|
|
247
283
|
const lineIssue = (i, message) => issues.push({ path: `line ${i + 1}`, line: i + 1, message: `Line ${i + 1}: ${message}` });
|
|
284
|
+
const whole = family === "sankey" || family === "treemap";
|
|
248
285
|
for (let i = headerLine + 1; family && i < all.length; i++) {
|
|
249
286
|
const raw = all[i];
|
|
250
287
|
const t = raw.trim();
|
|
@@ -260,7 +297,7 @@ function chartFromMermaid(text, options = {}) {
|
|
|
260
297
|
}
|
|
261
298
|
continue;
|
|
262
299
|
}
|
|
263
|
-
if (t.startsWith("%%")) continue;
|
|
300
|
+
if (t.startsWith("%%") || whole) continue;
|
|
264
301
|
const isLast = i === all.length - 1 || all.slice(i + 1).every((l) => !l.trim());
|
|
265
302
|
let m;
|
|
266
303
|
if (m = /^title\s+(.+)$/i.exec(t)) {
|
|
@@ -362,7 +399,8 @@ function chartFromMermaid(text, options = {}) {
|
|
|
362
399
|
if (!(partial && isLast)) lineIssue(i, `could not read "${t.slice(0, 60)}"; it was skipped.`);
|
|
363
400
|
}
|
|
364
401
|
let input;
|
|
365
|
-
if (family
|
|
402
|
+
if (whole) input = readWholeMermaid(family, all, headerLine, partial, title, issues);
|
|
403
|
+
else if (family === "pie") {
|
|
366
404
|
input = {
|
|
367
405
|
type: "pie",
|
|
368
406
|
title,
|
|
@@ -397,19 +435,55 @@ function chartFromMermaid(text, options = {}) {
|
|
|
397
435
|
input.series = metaSeries.map((extra, i) => ({ ..._nullishCoalesce(base[i], () => ( {})), ..._nullishCoalesce(extra, () => ( {})) }));
|
|
398
436
|
}
|
|
399
437
|
}
|
|
400
|
-
const { spec, issues: specIssues } =
|
|
401
|
-
if (!family && !partial && !issues.length) issues.push({ path: "header", message: "The text is empty: expected a chart header (xychart-beta, pie or
|
|
438
|
+
const { spec, issues: specIssues } = _chunkBPX4Z3N3cjs.normalizeChartSpec.call(void 0, input);
|
|
439
|
+
if (!family && !partial && !issues.length) issues.push({ path: "header", message: "The text is empty: expected a chart header (xychart-beta, pie, radar-beta, sankey-beta or treemap-beta)." });
|
|
402
440
|
return { spec, issues: [...issues, ...specIssues], family, hasMeta: !!meta };
|
|
403
441
|
}
|
|
442
|
+
function readWholeMermaid(family, all, headerLine, partial, title, issues) {
|
|
443
|
+
const body = all.slice(headerLine).map((l) => l.trim().startsWith(CHART_MERMAID_META_PREFIX.trim()) ? "%%" : l);
|
|
444
|
+
const parse = (lines) => family === "sankey" ? _chunkTTCJPX4Ucjs.parseSankey.call(void 0, lines.join("\n")) : _chunkTTCJPX4Ucjs.parseTreemap.call(void 0, lines.join("\n"));
|
|
445
|
+
let read = parse(body);
|
|
446
|
+
if ("error" in read && partial && body.length > 1) read = parse(body.slice(0, -1));
|
|
447
|
+
const lineOf = (n) => n === void 0 ? void 0 : n + headerLine;
|
|
448
|
+
if ("error" in read) {
|
|
449
|
+
const line = lineOf(read.line);
|
|
450
|
+
if (!(partial && body.length <= 2)) issues.push({ path: family, ...line ? { line } : {}, message: line ? `Line ${line}: ${read.error}` : read.error });
|
|
451
|
+
return { type: family === "sankey" ? "sankey" : "treemap", title };
|
|
452
|
+
}
|
|
453
|
+
if (family === "sankey") {
|
|
454
|
+
const data2 = read.data;
|
|
455
|
+
return { type: "sankey", title, links: data2.links, sankeyNodes: data2.nodes, series: [{ id: "series-1", name: "Values", values: [] }] };
|
|
456
|
+
}
|
|
457
|
+
const data = read.data;
|
|
458
|
+
let items = data.items;
|
|
459
|
+
let name = _nullishCoalesce(data.title, () => ( title));
|
|
460
|
+
if (items.length === 1 && _optionalChain([items, 'access', _13 => _13[0], 'access', _14 => _14.children, 'optionalAccess', _15 => _15.length])) {
|
|
461
|
+
name ||= items[0].name;
|
|
462
|
+
items = items[0].children;
|
|
463
|
+
}
|
|
464
|
+
const toNode = (item) => _optionalChain([item, 'access', _16 => _16.children, 'optionalAccess', _17 => _17.length]) ? { name: item.name, children: item.children.map(toNode) } : { name: item.name, value: _nullishCoalesce(item.value, () => ( 0)) };
|
|
465
|
+
const tree = items.map(toNode);
|
|
466
|
+
const leaf = (n) => !n.children;
|
|
467
|
+
const flatOrOneLevel = tree.every(leaf) || tree.every((n) => _optionalChain([n, 'access', _18 => _18.children, 'optionalAccess', _19 => _19.every, 'call', _20 => _20(leaf)]));
|
|
468
|
+
return { type: flatOrOneLevel ? "treemap" : "sunburst", title: name, tree, categories: tree.map((n) => n.name), series: [{ id: "series-1", name: "Values", values: tree.map(_chunkBPX4Z3N3cjs.chartTreeTotal) }] };
|
|
469
|
+
}
|
|
404
470
|
function findMermaidCharts(text) {
|
|
405
471
|
const lines = text.replace(/^/, "").split(/\r?\n/);
|
|
406
472
|
const found = [];
|
|
407
473
|
const familyOf = (body) => {
|
|
408
|
-
|
|
474
|
+
let rows = body.split(/\r?\n/);
|
|
475
|
+
const firstRow = rows.findIndex((l) => l.trim());
|
|
476
|
+
if (_optionalChain([rows, 'access', _21 => _21[firstRow], 'optionalAccess', _22 => _22.trim, 'call', _23 => _23()]) === "---") {
|
|
477
|
+
const end = rows.findIndex((l, i) => i > firstRow && l.trim() === "---");
|
|
478
|
+
if (end > 0) rows = rows.slice(end + 1);
|
|
479
|
+
}
|
|
480
|
+
const header = rows.find((l) => l.trim() && !l.trim().startsWith("%%"));
|
|
409
481
|
if (!header) return null;
|
|
410
482
|
if (/^\s*xychart(-beta)?\b/.test(header)) return "xychart";
|
|
411
483
|
if (/^\s*pie\b/.test(header)) return "pie";
|
|
412
484
|
if (/^\s*radar(-beta)?\b/.test(header)) return "radar";
|
|
485
|
+
if (/^\s*sankey(-beta)?\s*$/.test(header)) return "sankey";
|
|
486
|
+
if (/^\s*treemap(-beta)?\s*$/.test(header)) return "treemap";
|
|
413
487
|
return null;
|
|
414
488
|
};
|
|
415
489
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -436,11 +510,11 @@ function findMermaidCharts(text) {
|
|
|
436
510
|
}
|
|
437
511
|
|
|
438
512
|
// src/chart/summary.ts
|
|
439
|
-
function summarizeChart(spec, size = { width: 640, height: 400 }, scene =
|
|
513
|
+
function summarizeChart(spec, size = { width: 640, height: 400 }, scene = _chunkUUUTEVX6cjs.layoutChart.call(void 0, spec, { ...size, selection: null })) {
|
|
440
514
|
const visible = spec.series.filter((s) => !s.hidden);
|
|
441
|
-
const series = visible.map((s) =>
|
|
442
|
-
const colors =
|
|
443
|
-
const check =
|
|
515
|
+
const series = visible.map((s) => _chunkUUUTEVX6cjs.summarizeChartSeries.call(void 0, s, spec.categories));
|
|
516
|
+
const colors = _chunkBPX4Z3N3cjs.chartSpecColorsByCategory.call(void 0, spec) ? spec.categories.map((_, i) => _optionalChain([visible, 'access', _24 => _24[0], 'optionalAccess', _25 => _25.pointColors, 'optionalAccess', _26 => _26[i]]) || _chunkBPX4Z3N3cjs.chartSliceColor.call(void 0, spec, i)) : visible.map((s) => _chunkBPX4Z3N3cjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(s)));
|
|
517
|
+
const check = _chunkBPX4Z3N3cjs.checkChartColors.call(void 0, colors, { surface: scene.theme.surface.startsWith("var(") ? "#ffffff" : scene.theme.surface });
|
|
444
518
|
const axis = (s, a) => s ? { min: s.domain[0], max: s.domain[1], ticks: [...s.ticks], ...s.logBase ? { logBase: s.logBase } : {}, ...a.reverse ? { reversed: true } : {} } : void 0;
|
|
445
519
|
return {
|
|
446
520
|
type: spec.type,
|
|
@@ -455,12 +529,12 @@ function summarizeChart(spec, size = { width: 640, height: 400 }, scene = _chunk
|
|
|
455
529
|
description: describeChart(spec, series)
|
|
456
530
|
};
|
|
457
531
|
}
|
|
458
|
-
function describeChart(spec, series = spec.series.filter((s) => !s.hidden).map((s) =>
|
|
459
|
-
const kind =
|
|
532
|
+
function describeChart(spec, series = spec.series.filter((s) => !s.hidden).map((s) => _chunkUUUTEVX6cjs.summarizeChartSeries.call(void 0, s, spec.categories))) {
|
|
533
|
+
const kind = _chunkBPX4Z3N3cjs.CHART_TYPE_LABELS[spec.type].toLowerCase();
|
|
460
534
|
const parts = [];
|
|
461
|
-
const family =
|
|
535
|
+
const family = _chunkBPX4Z3N3cjs.chartFamily.call(void 0, spec);
|
|
462
536
|
const format = spec.yAxis.format;
|
|
463
|
-
const fmt = (v) => v === null ? "blank" :
|
|
537
|
+
const fmt = (v) => v === null ? "blank" : _chunkUUUTEVX6cjs.formatChartNumber.call(void 0, v, format);
|
|
464
538
|
const head = spec.title ? `${spec.title}: a ${kind} chart` : `A ${kind} chart`;
|
|
465
539
|
if (!series.length || series.every((s) => s.count === 0)) return `${head} with no data.`;
|
|
466
540
|
if (family === "pie" || family === "funnel" || family === "treemap" || family === "sunburst") {
|
|
@@ -470,19 +544,34 @@ function describeChart(spec, series = spec.series.filter((s) => !s.hidden).map((
|
|
|
470
544
|
parts.push(`${head} of ${s.name} across ${spec.categories.length} categories, totalling ${fmt(s.sum)}.`);
|
|
471
545
|
parts.push(`The largest is ${s.maxAt} at ${fmt(s.max)}${share(s.max)}; the smallest is ${s.minAt} at ${fmt(s.min)}${share(s.min)}.`);
|
|
472
546
|
if (spec.tree.length) {
|
|
473
|
-
const depth =
|
|
474
|
-
const items =
|
|
547
|
+
const depth = _chunkBPX4Z3N3cjs.chartTreeDepth.call(void 0, spec.tree);
|
|
548
|
+
const items = _chunkBPX4Z3N3cjs.chartTreeToRows.call(void 0, spec.tree).length;
|
|
475
549
|
parts.push(`The data is grouped ${depth} level${depth === 1 ? "" : "s"} deep with ${items} item${items === 1 ? "" : "s"}.`);
|
|
476
550
|
}
|
|
477
551
|
return parts.join(" ");
|
|
478
552
|
}
|
|
553
|
+
if (family === "barrace") {
|
|
554
|
+
const n = spec.categories.length;
|
|
555
|
+
const first = _chunkUUUTEVX6cjs.chartRaceRanking.call(void 0, spec, 0)[0];
|
|
556
|
+
const last = _chunkUUUTEVX6cjs.chartRaceRanking.call(void 0, spec, n - 1)[0];
|
|
557
|
+
const lead = (e, at) => e ? `${e.name} leads at ${at} with ${fmt(e.value)}` : "";
|
|
558
|
+
return `${head} of ${series.length} names over ${n} time points (${spec.categories[0]} to ${spec.categories[n - 1]}), showing the top ${Math.min(spec.raceTopN, series.length)}. ${lead(first, spec.categories[0])}; ${lead(last, spec.categories[n - 1])}.`;
|
|
559
|
+
}
|
|
560
|
+
if (family === "sankey") {
|
|
561
|
+
if (!spec.links.length) return `${head} with no flows yet.`;
|
|
562
|
+
const total = spec.links.reduce((t, l) => t + l.value, 0);
|
|
563
|
+
const largest = [...spec.links].sort((a, b) => b.value - a.value)[0];
|
|
564
|
+
const sources = spec.sankeyNodes.filter((n) => !spec.links.some((l) => l.target === n));
|
|
565
|
+
const sinks = spec.sankeyNodes.filter((n) => !spec.links.some((l) => l.source === n));
|
|
566
|
+
return `${head} of ${spec.links.length} flows between ${spec.sankeyNodes.length} nodes, from ${sources.join(", ")} to ${sinks.join(", ")}. The largest flow is ${largest.source} \u2192 ${largest.target} (${fmt(largest.value)}); all flows add up to ${fmt(total)}.`;
|
|
567
|
+
}
|
|
479
568
|
if (family === "parliament") {
|
|
480
569
|
const s = spec.series.find((x) => !x.hidden);
|
|
481
570
|
const seats = spec.categories.map((c, i) => ({ c, n: Math.max(0, Math.round(_nullishCoalesce(s.values[i], () => ( 0)))) }));
|
|
482
571
|
const total = seats.reduce((t, x) => t + x.n, 0);
|
|
483
572
|
const majority = _nullishCoalesce(spec.parliamentMajority, () => ( Math.floor(total / 2) + 1));
|
|
484
573
|
const largest = [...seats].sort((a, b) => b.n - a.n)[0];
|
|
485
|
-
const verdict = largest && largest.n >= majority ? `${largest.c} holds a majority with ${largest.n}` : `no group reaches the majority of ${majority}; the largest is ${_optionalChain([largest, 'optionalAccess',
|
|
574
|
+
const verdict = largest && largest.n >= majority ? `${largest.c} holds a majority with ${largest.n}` : `no group reaches the majority of ${majority}; the largest is ${_optionalChain([largest, 'optionalAccess', _27 => _27.c])} with ${_optionalChain([largest, 'optionalAccess', _28 => _28.n])}`;
|
|
486
575
|
return `${head} of ${total} seats across ${seats.length} groups: ${verdict}.`;
|
|
487
576
|
}
|
|
488
577
|
if (family === "slope") {
|
|
@@ -505,7 +594,7 @@ function describeChart(spec, series = spec.series.filter((s) => !s.hidden).map((
|
|
|
505
594
|
});
|
|
506
595
|
const best = [...agree].sort((x, y) => y.share - x.share);
|
|
507
596
|
const pct = (v) => `${Math.round(v * 100)}%`;
|
|
508
|
-
return `${head} of ${spec.categories.length} questions with ${answers.length} answers from ${_optionalChain([answers, 'access',
|
|
597
|
+
return `${head} of ${spec.categories.length} questions with ${answers.length} answers from ${_optionalChain([answers, 'access', _29 => _29[0], 'optionalAccess', _30 => _30.name])} to ${_optionalChain([answers, 'access', _31 => _31[answers.length - 1], 'optionalAccess', _32 => _32.name])}. Most positive: ${_optionalChain([best, 'access', _33 => _33[0], 'optionalAccess', _34 => _34.c])} (${pct(_nullishCoalesce(_optionalChain([best, 'access', _35 => _35[0], 'optionalAccess', _36 => _36.share]), () => ( 0)))}); least: ${_optionalChain([best, 'access', _37 => _37[best.length - 1], 'optionalAccess', _38 => _38.c])} (${pct(_nullishCoalesce(_optionalChain([best, 'access', _39 => _39[best.length - 1], 'optionalAccess', _40 => _40.share]), () => ( 0)))}).`;
|
|
509
598
|
}
|
|
510
599
|
if (family === "waterfall") {
|
|
511
600
|
const s = spec.series.find((x) => !x.hidden);
|
|
@@ -544,7 +633,7 @@ function describeChart(spec, series = spec.series.filter((s) => !s.hidden).map((
|
|
|
544
633
|
}
|
|
545
634
|
parts.push(...axes);
|
|
546
635
|
for (const s of spec.series.filter((x) => !x.hidden && (x.errorBars || x.xErrorBars)).slice(0, 8)) {
|
|
547
|
-
const bars = [s.errorBars ?
|
|
636
|
+
const bars = [s.errorBars ? _chunkBPX4Z3N3cjs.describeChartErrorBars.call(void 0, s.errorBars) : "", s.xErrorBars ? `x ${_chunkBPX4Z3N3cjs.describeChartErrorBars.call(void 0, s.xErrorBars)}` : ""].filter(Boolean).join(" and ");
|
|
548
637
|
parts.push(`${s.name} has ${bars}.`);
|
|
549
638
|
}
|
|
550
639
|
return parts.join(" ");
|
|
@@ -609,7 +698,7 @@ function chartSceneToSvg(scene, options = {}) {
|
|
|
609
698
|
return `<svg xmlns="http://www.w3.org/2000/svg" width="${scene.width}" height="${scene.height}" viewBox="0 0 ${scene.width} ${scene.height}" role="img"${label ? ` aria-label="${escape(label)}"` : ""}${labelled ? ` aria-labelledby="${labelled}"` : ""}>${head}${body}</svg>`;
|
|
610
699
|
}
|
|
611
700
|
function chartToSvg(spec, options) {
|
|
612
|
-
const scene =
|
|
701
|
+
const scene = _chunkUUUTEVX6cjs.layoutChart.call(void 0, spec, { ...options, selection: null });
|
|
613
702
|
return chartSceneToSvg(scene, { ...options, ariaLabel: _nullishCoalesce(options.ariaLabel, () => ( (spec.title || void 0))), description: _nullishCoalesce(options.description, () => ( describeChart(spec))) });
|
|
614
703
|
}
|
|
615
704
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
@@ -647,10 +736,10 @@ var CHART_LAYOUT_PRESETS = [
|
|
|
647
736
|
];
|
|
648
737
|
function monochromeChartPalette(base, count = 6) {
|
|
649
738
|
const steps = count <= 1 ? [0] : Array.from({ length: count }, (_, i) => -0.45 + 1.05 * i / (count - 1));
|
|
650
|
-
return steps.map((t) =>
|
|
739
|
+
return steps.map((t) => _chunkBPX4Z3N3cjs.shadeChartColor.call(void 0, base, t));
|
|
651
740
|
}
|
|
652
741
|
var CHART_COLOR_SCHEMES = [
|
|
653
|
-
{ id: "default", label: "Default", description: "Ten distinct colours, readable on light and dark backgrounds.", palette:
|
|
742
|
+
{ id: "default", label: "Default", description: "Ten distinct colours, readable on light and dark backgrounds.", palette: _chunkBPX4Z3N3cjs.DEFAULT_CHART_PALETTE },
|
|
654
743
|
{ id: "okabe-ito", label: "Okabe\u2013Ito", description: "Eight colours chosen to stay distinct with colour-blindness.", palette: ["#e69f00", "#56b4e9", "#009e73", "#f0e442", "#0072b2", "#d55e00", "#cc79a7", "#000000"] },
|
|
655
744
|
{ id: "office", label: "Office", description: "The six accent colours of the default Office theme.", palette: ["#4472c4", "#ed7d31", "#a5a5a5", "#ffc000", "#5b9bd5", "#70ad47"] },
|
|
656
745
|
{ id: "warm", label: "Warm", description: "Reds, oranges and yellows.", palette: ["#b2182b", "#d6604d", "#f4a582", "#e08214", "#fdb863", "#8c510a"] },
|
|
@@ -678,7 +767,7 @@ function chartPresetPatch(options) {
|
|
|
678
767
|
|
|
679
768
|
// src/chart/controller.ts
|
|
680
769
|
function pointLists(s) {
|
|
681
|
-
const lists = [s.values, s.x, s.sizes, s.pointColors, s.callouts, _optionalChain([s, 'access',
|
|
770
|
+
const lists = [s.values, s.x, s.sizes, s.pointColors, s.callouts, _optionalChain([s, 'access', _41 => _41.errorBars, 'optionalAccess', _42 => _42.plus]), _optionalChain([s, 'access', _43 => _43.errorBars, 'optionalAccess', _44 => _44.minus]), _optionalChain([s, 'access', _45 => _45.xErrorBars, 'optionalAccess', _46 => _46.plus]), _optionalChain([s, 'access', _47 => _47.xErrorBars, 'optionalAccess', _48 => _48.minus])];
|
|
682
771
|
return lists.filter((l) => Array.isArray(l));
|
|
683
772
|
}
|
|
684
773
|
function sameChartJson(a, b) {
|
|
@@ -695,6 +784,17 @@ function sameChartJson(a, b) {
|
|
|
695
784
|
if (keys.length !== Object.keys(bo).filter((k) => bo[k] !== void 0).length) return false;
|
|
696
785
|
return keys.every((k) => Object.prototype.hasOwnProperty.call(bo, k) && sameChartJson(ao[k], bo[k]));
|
|
697
786
|
}
|
|
787
|
+
var defaultRaceTicker = {
|
|
788
|
+
now: () => typeof performance !== "undefined" ? performance.now() : Date.now(),
|
|
789
|
+
next: (step) => {
|
|
790
|
+
if (typeof requestAnimationFrame === "function") {
|
|
791
|
+
const id2 = requestAnimationFrame(() => step());
|
|
792
|
+
return () => cancelAnimationFrame(id2);
|
|
793
|
+
}
|
|
794
|
+
const id = setTimeout(step, 16);
|
|
795
|
+
return () => clearTimeout(id);
|
|
796
|
+
}
|
|
797
|
+
};
|
|
698
798
|
var fail = (message, issues) => ({ ok: false, message, ...issues ? { issues } : {} });
|
|
699
799
|
var ChartController = (_class = class {
|
|
700
800
|
|
|
@@ -707,20 +807,24 @@ var ChartController = (_class = class {
|
|
|
707
807
|
__init6() {this.revision = 0}
|
|
708
808
|
__init7() {this.applying = false}
|
|
709
809
|
|
|
710
|
-
__init8() {this.listeners = /* @__PURE__ */ new Set()}
|
|
711
810
|
|
|
811
|
+
__init8() {this.raceFrame = null}
|
|
812
|
+
__init9() {this.raceStop = null}
|
|
813
|
+
__init10() {this.listeners = /* @__PURE__ */ new Set()}
|
|
712
814
|
|
|
713
|
-
|
|
815
|
+
|
|
816
|
+
constructor(options = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this);_class.prototype.__init6.call(this);_class.prototype.__init7.call(this);_class.prototype.__init8.call(this);_class.prototype.__init9.call(this);_class.prototype.__init10.call(this);_class.prototype.__init11.call(this);_class.prototype.__init12.call(this);
|
|
714
817
|
this.history = _nullishCoalesce(options.history, () => ( new (0, _chunkFJ2MSI43cjs.HistoryManager)()));
|
|
715
818
|
this.onChange = options.onChange;
|
|
716
|
-
|
|
819
|
+
this.raceTicker = _nullishCoalesce(options.raceTicker, () => ( defaultRaceTicker));
|
|
820
|
+
const { spec, issues } = _chunkBPX4Z3N3cjs.normalizeChartSpec.call(void 0, _nullishCoalesce(options.spec, () => ( {})));
|
|
717
821
|
this.spec = spec;
|
|
718
822
|
this.issues = issues;
|
|
719
823
|
this.state = this.computeState();
|
|
720
824
|
this.connect();
|
|
721
825
|
}
|
|
722
826
|
connect() {
|
|
723
|
-
_optionalChain([this, 'access',
|
|
827
|
+
_optionalChain([this, 'access', _49 => _49.unsubscribeHistory, 'optionalCall', _50 => _50()]);
|
|
724
828
|
this.unsubscribeHistory = this.history.subscribe((h) => {
|
|
725
829
|
const s = this.state;
|
|
726
830
|
if (this.applying || s.canUndo === h.canUndo && s.canRedo === h.canRedo && s.undoLabel === h.undoName && s.redoLabel === h.redoName) return;
|
|
@@ -731,9 +835,9 @@ var ChartController = (_class = class {
|
|
|
731
835
|
// State
|
|
732
836
|
// -------------------------------------------------------------------------
|
|
733
837
|
/** The current snapshot (stable until the next change). */
|
|
734
|
-
|
|
838
|
+
__init11() {this.getState = () => this.state}
|
|
735
839
|
/** Calls `listener` after every change. Returns an unsubscribe function. */
|
|
736
|
-
|
|
840
|
+
__init12() {this.subscribe = (listener) => {
|
|
737
841
|
if (!this.unsubscribeHistory) this.connect();
|
|
738
842
|
this.listeners.add(listener);
|
|
739
843
|
return () => {
|
|
@@ -750,25 +854,27 @@ var ChartController = (_class = class {
|
|
|
750
854
|
computeState() {
|
|
751
855
|
const h = this.history.getState();
|
|
752
856
|
const sel = this.selection;
|
|
753
|
-
const seriesId = _optionalChain([sel, 'optionalAccess',
|
|
857
|
+
const seriesId = _optionalChain([sel, 'optionalAccess', _51 => _51.kind]) === "series" || _optionalChain([sel, 'optionalAccess', _52 => _52.kind]) === "point" || _optionalChain([sel, 'optionalAccess', _53 => _53.kind]) === "trendline" ? sel.seriesId : null;
|
|
754
858
|
return {
|
|
755
859
|
spec: this.spec,
|
|
756
860
|
selection: sel,
|
|
757
861
|
selectedSeries: seriesId ? _nullishCoalesce(this.spec.series.find((s) => s.id === seriesId), () => ( null)) : null,
|
|
758
|
-
selectedIndex: _optionalChain([sel, 'optionalAccess',
|
|
862
|
+
selectedIndex: _optionalChain([sel, 'optionalAccess', _54 => _54.kind]) === "point" || _optionalChain([sel, 'optionalAccess', _55 => _55.kind]) === "category" ? sel.index : null,
|
|
759
863
|
issues: this.issues,
|
|
760
864
|
gesture: this.gestureKey,
|
|
761
865
|
canUndo: h.canUndo,
|
|
762
866
|
canRedo: h.canRedo,
|
|
763
867
|
undoLabel: h.undoName,
|
|
764
868
|
redoLabel: h.redoName,
|
|
869
|
+
raceFrame: this.raceFrame === null ? null : Math.min(this.raceFrame, Math.max(0, this.spec.categories.length - 1)),
|
|
870
|
+
racePlaying: this.raceStop !== null,
|
|
765
871
|
revision: this.revision
|
|
766
872
|
};
|
|
767
873
|
}
|
|
768
874
|
notify(specChanged) {
|
|
769
875
|
this.revision++;
|
|
770
876
|
this.state = this.computeState();
|
|
771
|
-
if (specChanged) _optionalChain([this, 'access',
|
|
877
|
+
if (specChanged) _optionalChain([this, 'access', _56 => _56.onChange, 'optionalCall', _57 => _57(this.spec)]);
|
|
772
878
|
const state = this.state;
|
|
773
879
|
this.listeners.forEach((listener) => {
|
|
774
880
|
try {
|
|
@@ -792,7 +898,7 @@ var ChartController = (_class = class {
|
|
|
792
898
|
case "category":
|
|
793
899
|
return sel.index < spec.categories.length ? sel : null;
|
|
794
900
|
case "trendline":
|
|
795
|
-
return _optionalChain([spec, 'access',
|
|
901
|
+
return _optionalChain([spec, 'access', _58 => _58.series, 'access', _59 => _59.find, 'call', _60 => _60((s) => s.id === sel.seriesId), 'optionalAccess', _61 => _61.trendlines, 'optionalAccess', _62 => _62[sel.index]]) ? sel : null;
|
|
796
902
|
case "title":
|
|
797
903
|
return spec.title ? sel : null;
|
|
798
904
|
case "subtitle":
|
|
@@ -816,7 +922,7 @@ var ChartController = (_class = class {
|
|
|
816
922
|
const hadIssues = this.issues.length > 0;
|
|
817
923
|
this.issues = [];
|
|
818
924
|
if (sameChartJson(before, next)) {
|
|
819
|
-
const reselect = select !== void 0 && !
|
|
925
|
+
const reselect = select !== void 0 && !_chunkUUUTEVX6cjs.sameChartSelection.call(void 0, this.selection, select) && !(select === null && this.selection === null);
|
|
820
926
|
if (reselect) this.selection = select;
|
|
821
927
|
if (reselect || hadIssues) this.notify(false);
|
|
822
928
|
return;
|
|
@@ -839,7 +945,7 @@ var ChartController = (_class = class {
|
|
|
839
945
|
}
|
|
840
946
|
/** A copy of the spec with `edit` applied (series and categories copied as needed). */
|
|
841
947
|
edited(edit) {
|
|
842
|
-
const draft =
|
|
948
|
+
const draft = _chunkBPX4Z3N3cjs.cloneChartSpec.call(void 0, this.spec);
|
|
843
949
|
edit(draft);
|
|
844
950
|
return draft;
|
|
845
951
|
}
|
|
@@ -869,7 +975,7 @@ var ChartController = (_class = class {
|
|
|
869
975
|
legend: patch.legend ? { ...s.legend, ...patch.legend } : s.legend,
|
|
870
976
|
version: 1
|
|
871
977
|
};
|
|
872
|
-
const { spec, issues } =
|
|
978
|
+
const { spec, issues } = _chunkBPX4Z3N3cjs.normalizeChartSpec.call(void 0, merged);
|
|
873
979
|
if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
|
|
874
980
|
if (JSON.stringify(spec) === JSON.stringify(s)) return { ok: true };
|
|
875
981
|
this.commit(_nullishCoalesce(options.label, () => ( updateLabel(patch))), spec);
|
|
@@ -910,7 +1016,7 @@ var ChartController = (_class = class {
|
|
|
910
1016
|
* to the categories; all-or-nothing like `update`.
|
|
911
1017
|
*/
|
|
912
1018
|
setData(data, options = {}) {
|
|
913
|
-
const clear = (data.categories || data.series) && this.spec.tree.length ? { tree: [] } : {};
|
|
1019
|
+
const clear = (data.categories || data.series) && (this.spec.tree.length || this.spec.links.length) ? { tree: [], links: [] } : {};
|
|
914
1020
|
return this.update({ ...data.categories ? { categories: data.categories } : {}, ...data.series ? { series: data.series } : {}, ...clear }, { label: _nullishCoalesce(options.label, () => ( "Edit chart data")) });
|
|
915
1021
|
}
|
|
916
1022
|
/**
|
|
@@ -923,7 +1029,7 @@ var ChartController = (_class = class {
|
|
|
923
1029
|
const series = this.getSeries(seriesId);
|
|
924
1030
|
if (!series) return this.unknownSeries(seriesId);
|
|
925
1031
|
if (!Number.isInteger(index) || index < 0 || index >= this.spec.categories.length) return this.badIndex(index);
|
|
926
|
-
const parsed =
|
|
1032
|
+
const parsed = _chunkBPX4Z3N3cjs.parseChartValue.call(void 0, value);
|
|
927
1033
|
if (parsed === void 0) return this.reject(`"${String(value)}" is not a number; enter a number or leave the cell blank.`, [{ path: `${seriesId}[${index}]`, message: `"${String(value)}" is not a number.` }]);
|
|
928
1034
|
if (series.values[index] === parsed) {
|
|
929
1035
|
if (this.issues.length) {
|
|
@@ -948,7 +1054,7 @@ var ChartController = (_class = class {
|
|
|
948
1054
|
if (!this.getSeries(cell.seriesId)) issues.push({ path: cell.seriesId, message: this.unknownSeries(cell.seriesId).message });
|
|
949
1055
|
else if (!Number.isInteger(cell.index) || cell.index < 0 || cell.index >= this.spec.categories.length) issues.push({ path: `${cell.seriesId}[${cell.index}]`, message: this.badIndex(cell.index).message });
|
|
950
1056
|
else {
|
|
951
|
-
const value =
|
|
1057
|
+
const value = _chunkBPX4Z3N3cjs.parseChartValue.call(void 0, cell.value);
|
|
952
1058
|
if (value === void 0) issues.push({ path: `${cell.seriesId}[${cell.index}]`, message: `"${String(cell.value)}" is not a number.` });
|
|
953
1059
|
else parsed.push({ seriesId: cell.seriesId, index: cell.index, value });
|
|
954
1060
|
}
|
|
@@ -962,12 +1068,12 @@ var ChartController = (_class = class {
|
|
|
962
1068
|
}
|
|
963
1069
|
/** Adds a series (values padded to the categories) and selects it. Returns its id. */
|
|
964
1070
|
addSeries(input = {}, options = {}) {
|
|
965
|
-
const id = input.id && !this.getSeries(input.id) ? input.id :
|
|
1071
|
+
const id = input.id && !this.getSeries(input.id) ? input.id : _chunkBPX4Z3N3cjs.uniqueChartSeriesId.call(void 0, this.spec.series);
|
|
966
1072
|
const name = _nullishCoalesce(input.name, () => ( `Series ${this.spec.series.length + 1}`));
|
|
967
1073
|
const at = Math.max(0, Math.min(this.spec.series.length, _nullishCoalesce(options.at, () => ( this.spec.series.length))));
|
|
968
1074
|
const series = [...this.spec.series];
|
|
969
1075
|
series.splice(at, 0, { ...input, id, name, values: _nullishCoalesce(input.values, () => ( [])) });
|
|
970
|
-
const { spec, issues } =
|
|
1076
|
+
const { spec, issues } = _chunkBPX4Z3N3cjs.normalizeChartSpec.call(void 0, { ...this.spec, series });
|
|
971
1077
|
if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
|
|
972
1078
|
this.commit(`Add series "${name}"`, spec, { kind: "series", seriesId: id });
|
|
973
1079
|
return { ok: true, id };
|
|
@@ -987,7 +1093,7 @@ var ChartController = (_class = class {
|
|
|
987
1093
|
updateSeries(id, patch) {
|
|
988
1094
|
const series = this.getSeries(id);
|
|
989
1095
|
if (!series) return this.unknownSeries(id);
|
|
990
|
-
const next =
|
|
1096
|
+
const next = _chunkBPX4Z3N3cjs.cloneChartSeries.call(void 0, series);
|
|
991
1097
|
if (patch.name !== void 0) next.name = String(patch.name);
|
|
992
1098
|
if (patch.color === null || patch.color === "") delete next.color;
|
|
993
1099
|
else if (patch.color !== void 0) next.color = patch.color;
|
|
@@ -1007,7 +1113,7 @@ var ChartController = (_class = class {
|
|
|
1007
1113
|
const series2 = this.spec.series.map((s) => s.id === id ? next : s);
|
|
1008
1114
|
const renamed = next.name !== series.name && this.spec.highlight.includes(series.name) && !this.spec.categories.includes(series.name);
|
|
1009
1115
|
const highlight = renamed ? this.spec.highlight.map((h) => h === series.name ? next.name : h) : this.spec.highlight;
|
|
1010
|
-
const { spec, issues } =
|
|
1116
|
+
const { spec, issues } = _chunkBPX4Z3N3cjs.normalizeChartSpec.call(void 0, { ...this.spec, series: series2, highlight });
|
|
1011
1117
|
if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
|
|
1012
1118
|
if (JSON.stringify(spec.series) === JSON.stringify(this.spec.series)) return { ok: true };
|
|
1013
1119
|
const label = patch.hidden !== void 0 && Object.keys(patch).length === 1 ? `${patch.hidden ? "Hide" : "Show"} "${series.name}"` : patch.name !== void 0 && Object.keys(patch).length === 1 ? "Rename series" : `Change series "${series.name}"`;
|
|
@@ -1113,7 +1219,7 @@ var ChartController = (_class = class {
|
|
|
1113
1219
|
const width = Math.max(...rows.map((r) => r.length));
|
|
1114
1220
|
const lastSeries = column + width - 1;
|
|
1115
1221
|
while (d.series.length <= lastSeries) {
|
|
1116
|
-
const id =
|
|
1222
|
+
const id = _chunkBPX4Z3N3cjs.uniqueChartSeriesId.call(void 0, d.series);
|
|
1117
1223
|
d.series.push({ id, name: `Series ${d.series.length + 1}`, values: d.categories.map(() => null) });
|
|
1118
1224
|
}
|
|
1119
1225
|
const lastRow = row + rows.length - 1;
|
|
@@ -1127,7 +1233,7 @@ var ChartController = (_class = class {
|
|
|
1127
1233
|
const index = row + r;
|
|
1128
1234
|
if (col < 0) d.categories[index] = cell === null || cell === void 0 ? "" : String(cell).trim();
|
|
1129
1235
|
else {
|
|
1130
|
-
const parsed =
|
|
1236
|
+
const parsed = _chunkBPX4Z3N3cjs.parseChartValue.call(void 0, cell);
|
|
1131
1237
|
if (parsed === void 0) issues.push({ path: `${d.series[col].id}[${index}]`, message: `"${String(cell)}" is not a number; it was left blank.` });
|
|
1132
1238
|
d.series[col].values[index] = _nullishCoalesce(parsed, () => ( null));
|
|
1133
1239
|
}
|
|
@@ -1146,14 +1252,14 @@ var ChartController = (_class = class {
|
|
|
1146
1252
|
* colours and types are kept by name.
|
|
1147
1253
|
*/
|
|
1148
1254
|
importTable(rows, options = {}) {
|
|
1149
|
-
const data =
|
|
1255
|
+
const data = _chunkBPX4Z3N3cjs.chartDataFromTable.call(void 0, rows, options);
|
|
1150
1256
|
if (!data.categories.length || !data.series.length) return this.reject("There is no data to import: expected a header row and at least one row of values.");
|
|
1151
1257
|
const byName = new Map(this.spec.series.map((s) => [s.name, s]));
|
|
1152
1258
|
const series = data.series.map((s) => {
|
|
1153
1259
|
const old = byName.get(s.name);
|
|
1154
|
-
return { ...s, ..._optionalChain([old, 'optionalAccess',
|
|
1260
|
+
return { ...s, ..._optionalChain([old, 'optionalAccess', _63 => _63.color]) ? { color: old.color } : {}, ..._optionalChain([old, 'optionalAccess', _64 => _64.type]) ? { type: old.type } : {}, ...old ? { id: old.id } : {} };
|
|
1155
1261
|
});
|
|
1156
|
-
const { spec } =
|
|
1262
|
+
const { spec } = _chunkBPX4Z3N3cjs.normalizeChartSpec.call(void 0, { ...this.spec, categories: data.categories, series, tree: [], links: [] });
|
|
1157
1263
|
this.commit("Import data", spec);
|
|
1158
1264
|
if (data.issues.length) {
|
|
1159
1265
|
this.issues = data.issues;
|
|
@@ -1170,8 +1276,12 @@ var ChartController = (_class = class {
|
|
|
1170
1276
|
// -------------------------------------------------------------------------
|
|
1171
1277
|
// Grouped data (tree)
|
|
1172
1278
|
// -------------------------------------------------------------------------
|
|
1173
|
-
/** A refusal while the data is a tree (cell edits would be overwritten by
|
|
1279
|
+
/** A refusal while the data is a tree or flows (cell edits would be overwritten by their totals), else null. */
|
|
1174
1280
|
treeLocked() {
|
|
1281
|
+
if (this.spec.links.length)
|
|
1282
|
+
return this.reject(
|
|
1283
|
+
"This chart's data is flows (links): its categories are the nodes and its values how much passes through each. Change it with setLinks / the flow edits (set_chart_links, add_chart_link, update_chart_link, remove_chart_link), or replace it with new data."
|
|
1284
|
+
);
|
|
1175
1285
|
if (!this.spec.tree.length) return null;
|
|
1176
1286
|
return this.reject(
|
|
1177
1287
|
"This chart's data is grouped (a tree): its categories and values are the top-level groups and their totals. Change it with setTree / the tree node edits (set_chart_tree, add_chart_tree_node, update_chart_tree_node, remove_chart_tree_node), or replace it with new data."
|
|
@@ -1180,9 +1290,9 @@ var ChartController = (_class = class {
|
|
|
1180
1290
|
/** Replaces the grouped data (an empty list goes back to the table, keeping the totals as values). One undo step. */
|
|
1181
1291
|
setTree(tree, options = {}) {
|
|
1182
1292
|
const issues = [];
|
|
1183
|
-
const next =
|
|
1293
|
+
const next = _chunkBPX4Z3N3cjs.normalizeChartTree.call(void 0, tree, issues);
|
|
1184
1294
|
if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
|
|
1185
|
-
return this.update({ tree: next }, { label: _nullishCoalesce(options.label, () => ( (next.length ? "Replace grouped data" : "Ungroup data"))) });
|
|
1295
|
+
return this.update({ tree: next, links: [] }, { label: _nullishCoalesce(options.label, () => ( (next.length ? "Replace grouped data" : "Ungroup data"))) });
|
|
1186
1296
|
}
|
|
1187
1297
|
/**
|
|
1188
1298
|
* Replaces the grouped data from rows of names and a value (group, …, item, value), as the
|
|
@@ -1190,12 +1300,12 @@ var ChartController = (_class = class {
|
|
|
1190
1300
|
*/
|
|
1191
1301
|
setTreeRows(rows, options = {}) {
|
|
1192
1302
|
const issues = [];
|
|
1193
|
-
const next =
|
|
1303
|
+
const next = _chunkBPX4Z3N3cjs.chartTreeFromRows.call(void 0, rows, issues);
|
|
1194
1304
|
if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
|
|
1195
1305
|
const keepColors = (list, prefix) => {
|
|
1196
1306
|
for (const n of list) {
|
|
1197
|
-
const old =
|
|
1198
|
-
if (_optionalChain([old, 'optionalAccess',
|
|
1307
|
+
const old = _chunkBPX4Z3N3cjs.findChartTreeNode.call(void 0, this.spec.tree, [...prefix, n.name]);
|
|
1308
|
+
if (_optionalChain([old, 'optionalAccess', _65 => _65.color])) n.color = old.color;
|
|
1199
1309
|
if (n.children) keepColors(n.children, [...prefix, n.name]);
|
|
1200
1310
|
}
|
|
1201
1311
|
};
|
|
@@ -1205,16 +1315,16 @@ var ChartController = (_class = class {
|
|
|
1205
1315
|
/** Replaces the data with a table of names and values (group, …, item, value); see `chartTreeFromTable`. */
|
|
1206
1316
|
importTreeTable(rows, options = {}) {
|
|
1207
1317
|
const issues = [];
|
|
1208
|
-
const next =
|
|
1318
|
+
const next = _chunkBPX4Z3N3cjs.chartTreeFromTable.call(void 0, rows, options, issues);
|
|
1209
1319
|
if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
|
|
1210
1320
|
if (!next.length) return this.reject('There is no grouped data to import: expected rows of names followed by a value, e.g. "Europe,France,40".');
|
|
1211
|
-
return this.update({ tree: next }, { label: "Import grouped data" });
|
|
1321
|
+
return this.update({ tree: next, links: [] }, { label: "Import grouped data" });
|
|
1212
1322
|
}
|
|
1213
1323
|
nodeAt(path) {
|
|
1214
|
-
const node =
|
|
1324
|
+
const node = _chunkBPX4Z3N3cjs.findChartTreeNode.call(void 0, this.spec.tree, path);
|
|
1215
1325
|
if (node) return node;
|
|
1216
|
-
const known = path.length > 1 ?
|
|
1217
|
-
const siblings = _nullishCoalesce((path.length > 1 ? _optionalChain([known, 'optionalAccess',
|
|
1326
|
+
const known = path.length > 1 ? _chunkBPX4Z3N3cjs.findChartTreeNode.call(void 0, this.spec.tree, path.slice(0, -1)) : null;
|
|
1327
|
+
const siblings = _nullishCoalesce((path.length > 1 ? _optionalChain([known, 'optionalAccess', _66 => _66.children]) : this.spec.tree), () => ( []));
|
|
1218
1328
|
return fail(
|
|
1219
1329
|
`There is no node ${JSON.stringify(path)}. ${siblings.length ? `${path.length > 1 && known ? `"${known.name}" contains` : "The top level has"} ${siblings.map((n) => `"${n.name}"`).slice(0, 20).join(", ")}.` : "The chart has no grouped data yet; add nodes with add_chart_tree_node or set_chart_tree."}`
|
|
1220
1330
|
);
|
|
@@ -1229,12 +1339,12 @@ var ChartController = (_class = class {
|
|
|
1229
1339
|
siblings = group.children;
|
|
1230
1340
|
}
|
|
1231
1341
|
const issues = [];
|
|
1232
|
-
const [node] =
|
|
1342
|
+
const [node] = _chunkBPX4Z3N3cjs.normalizeChartTree.call(void 0, [input], issues, "node");
|
|
1233
1343
|
if (!node || issues.length) return this.reject(issues.map((i) => i.message).join(" ") || "The node is not valid.", issues);
|
|
1234
1344
|
if (siblings.some((n) => n.name === node.name)) return this.reject(`"${node.name}" is already there; names under one group must be unique.`);
|
|
1235
1345
|
const at = Math.max(0, Math.min(siblings.length, _nullishCoalesce(options.at, () => ( siblings.length))));
|
|
1236
|
-
const tree =
|
|
1237
|
-
const list = parent.length ?
|
|
1346
|
+
const tree = _chunkBPX4Z3N3cjs.cloneChartTree.call(void 0, this.spec.tree);
|
|
1347
|
+
const list = parent.length ? _chunkBPX4Z3N3cjs.findChartTreeNode.call(void 0, tree, parent).children : tree;
|
|
1238
1348
|
list.splice(at, 0, node);
|
|
1239
1349
|
const result = this.update({ tree }, { label: `Add "${node.name}"` });
|
|
1240
1350
|
if (!result.ok) return result;
|
|
@@ -1246,16 +1356,16 @@ var ChartController = (_class = class {
|
|
|
1246
1356
|
if ("ok" in node) return node;
|
|
1247
1357
|
if (patch.value !== void 0 && node.children) return this.reject(`"${node.name}" is a group: its value is the sum of its items. Change the items instead.`);
|
|
1248
1358
|
const name = patch.name !== void 0 ? String(patch.name).trim() : node.name;
|
|
1249
|
-
const siblings = (path.length > 1 ?
|
|
1359
|
+
const siblings = (path.length > 1 ? _chunkBPX4Z3N3cjs.findChartTreeNode.call(void 0, this.spec.tree, path.slice(0, -1)).children : this.spec.tree).filter((n) => n !== node);
|
|
1250
1360
|
if (siblings.some((n) => n.name === name)) return this.reject(`There is already a "${name}" next to "${node.name}"; names under one group must be unique.`);
|
|
1251
|
-
const tree =
|
|
1252
|
-
const target =
|
|
1361
|
+
const tree = _chunkBPX4Z3N3cjs.cloneChartTree.call(void 0, this.spec.tree);
|
|
1362
|
+
const target = _chunkBPX4Z3N3cjs.findChartTreeNode.call(void 0, tree, path);
|
|
1253
1363
|
const merged = { ...target, name };
|
|
1254
1364
|
if (patch.value !== void 0) merged.value = patch.value;
|
|
1255
1365
|
if (patch.color === null) delete merged.color;
|
|
1256
1366
|
else if (patch.color !== void 0) merged.color = patch.color;
|
|
1257
1367
|
const issues = [];
|
|
1258
|
-
const [checked] =
|
|
1368
|
+
const [checked] = _chunkBPX4Z3N3cjs.normalizeChartTree.call(void 0, [merged], issues, "node");
|
|
1259
1369
|
if (!checked || issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
|
|
1260
1370
|
Object.assign(target, checked);
|
|
1261
1371
|
if (patch.color === null) delete target.color;
|
|
@@ -1267,8 +1377,8 @@ var ChartController = (_class = class {
|
|
|
1267
1377
|
removeTreeNode(path) {
|
|
1268
1378
|
const node = this.nodeAt(path);
|
|
1269
1379
|
if ("ok" in node) return node;
|
|
1270
|
-
const tree =
|
|
1271
|
-
const parent = path.length > 1 ?
|
|
1380
|
+
const tree = _chunkBPX4Z3N3cjs.cloneChartTree.call(void 0, this.spec.tree);
|
|
1381
|
+
const parent = path.length > 1 ? _chunkBPX4Z3N3cjs.findChartTreeNode.call(void 0, tree, path.slice(0, -1)) : null;
|
|
1272
1382
|
const list = parent ? parent.children : tree;
|
|
1273
1383
|
list.splice(
|
|
1274
1384
|
list.findIndex((n) => n.name === node.name),
|
|
@@ -1281,6 +1391,56 @@ var ChartController = (_class = class {
|
|
|
1281
1391
|
return this.update({ tree }, { label: `Delete "${node.name}"` });
|
|
1282
1392
|
}
|
|
1283
1393
|
// -------------------------------------------------------------------------
|
|
1394
|
+
// Flows (links)
|
|
1395
|
+
// -------------------------------------------------------------------------
|
|
1396
|
+
/**
|
|
1397
|
+
* Replaces the flows (and, when given, the node order). An empty list goes back to the
|
|
1398
|
+
* table, keeping how much passed through each node as values. One undo step, all-or-nothing.
|
|
1399
|
+
*/
|
|
1400
|
+
setLinks(links, options = {}) {
|
|
1401
|
+
const issues = [];
|
|
1402
|
+
const next = _chunkBPX4Z3N3cjs.normalizeChartLinks.call(void 0, links, issues);
|
|
1403
|
+
if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
|
|
1404
|
+
const used = new Set(next.flatMap((l) => [l.source, l.target]));
|
|
1405
|
+
const sankeyNodes = options.nodes ? [...options.nodes] : this.spec.sankeyNodes.filter((n) => used.has(n));
|
|
1406
|
+
return this.update({ links: next, tree: [], sankeyNodes }, { label: _nullishCoalesce(options.label, () => ( (next.length ? "Replace flows" : "Remove flows"))) });
|
|
1407
|
+
}
|
|
1408
|
+
/** Replaces the data with flows from a table of source, target and value columns. */
|
|
1409
|
+
importLinksTable(rows, options = {}) {
|
|
1410
|
+
const raw = _chunkBPX4Z3N3cjs.chartLinksFromTable.call(void 0, rows, options);
|
|
1411
|
+
if (!raw.length) return this.reject('There are no flows to import: expected rows of source, target and value, e.g. "Website,Signup,120".');
|
|
1412
|
+
return this.setLinks(raw, { label: "Import flows" });
|
|
1413
|
+
}
|
|
1414
|
+
badLink(index) {
|
|
1415
|
+
const n = this.spec.links.length;
|
|
1416
|
+
return fail(`There is no flow ${index}; ${n ? `expected 0 to ${n - 1}` : "the chart has none yet"}.`);
|
|
1417
|
+
}
|
|
1418
|
+
/** Adds a flow and returns its index. */
|
|
1419
|
+
addLink(link) {
|
|
1420
|
+
const result = this.setLinks([...this.spec.links, link], { label: `Add flow ${String(_nullishCoalesce(_optionalChain([link, 'optionalAccess', _67 => _67.source]), () => ( "")))} \u2192 ${String(_nullishCoalesce(_optionalChain([link, 'optionalAccess', _68 => _68.target]), () => ( "")))}` });
|
|
1421
|
+
if (!result.ok) return result;
|
|
1422
|
+
return { ok: true, index: this.spec.links.length - 1 };
|
|
1423
|
+
}
|
|
1424
|
+
/** Changes a flow's source, target, value or colour (`color: null` goes back to the default). */
|
|
1425
|
+
updateLink(index, patch) {
|
|
1426
|
+
const current = this.spec.links[index];
|
|
1427
|
+
if (!current) return this.badLink(index);
|
|
1428
|
+
const merged = { ...current, ...patch };
|
|
1429
|
+
if (patch.color === null) delete merged.color;
|
|
1430
|
+
return this.setLinks(
|
|
1431
|
+
this.spec.links.map((l, i) => i === index ? merged : l),
|
|
1432
|
+
{ label: "Change flow" }
|
|
1433
|
+
);
|
|
1434
|
+
}
|
|
1435
|
+
removeLink(index) {
|
|
1436
|
+
const current = this.spec.links[index];
|
|
1437
|
+
if (!current) return this.badLink(index);
|
|
1438
|
+
return this.setLinks(
|
|
1439
|
+
this.spec.links.filter((_, i) => i !== index),
|
|
1440
|
+
{ label: `Delete flow ${current.source} \u2192 ${current.target}` }
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1443
|
+
// -------------------------------------------------------------------------
|
|
1284
1444
|
// Annotations
|
|
1285
1445
|
// -------------------------------------------------------------------------
|
|
1286
1446
|
/** Sets the note written under the chart ("" removes it). */
|
|
@@ -1311,7 +1471,7 @@ var ChartController = (_class = class {
|
|
|
1311
1471
|
/** Why a reference on `axis` at `values` cannot be drawn on this chart, or null. */
|
|
1312
1472
|
referenceProblem(axis, values) {
|
|
1313
1473
|
const s = this.spec;
|
|
1314
|
-
const family =
|
|
1474
|
+
const family = _chunkBPX4Z3N3cjs.chartFamily.call(void 0, s);
|
|
1315
1475
|
if (family !== "cartesian" && family !== "xy") return `Reference lines and bands are drawn on bar, line, area, scatter and bubble charts; this is a ${s.type} chart.`;
|
|
1316
1476
|
if (axis === "x" && family !== "xy") return 'axis "x" needs a scatter or bubble chart with numeric x values; use "y" for the value axis.';
|
|
1317
1477
|
if (axis === "y2" && (family !== "cartesian" || !s.series.some((x) => !x.hidden && x.axis === "secondary")))
|
|
@@ -1330,7 +1490,7 @@ var ChartController = (_class = class {
|
|
|
1330
1490
|
/** Adds a reference line (a target, floor or average). Returns its index. */
|
|
1331
1491
|
addReferenceLine(input) {
|
|
1332
1492
|
const issues = [];
|
|
1333
|
-
const line =
|
|
1493
|
+
const line = _chunkBPX4Z3N3cjs.normalizeChartReferenceLine.call(void 0, input, "referenceLine", issues);
|
|
1334
1494
|
if (!line || issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
|
|
1335
1495
|
const problem = this.referenceProblem(line.axis, [line.value]);
|
|
1336
1496
|
if (problem) return this.reject(problem);
|
|
@@ -1345,7 +1505,7 @@ var ChartController = (_class = class {
|
|
|
1345
1505
|
const merged = { ...current, ...patch };
|
|
1346
1506
|
for (const [k, v] of Object.entries(patch)) if (v === null) delete merged[k];
|
|
1347
1507
|
const issues = [];
|
|
1348
|
-
const line =
|
|
1508
|
+
const line = _chunkBPX4Z3N3cjs.normalizeChartReferenceLine.call(void 0, merged, "referenceLine", issues);
|
|
1349
1509
|
if (!line || issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
|
|
1350
1510
|
const problem = this.referenceProblem(line.axis, [line.value]);
|
|
1351
1511
|
if (problem) return this.reject(problem);
|
|
@@ -1360,7 +1520,7 @@ var ChartController = (_class = class {
|
|
|
1360
1520
|
/** Adds a reference band (a target range). Returns its index. */
|
|
1361
1521
|
addReferenceBand(input) {
|
|
1362
1522
|
const issues = [];
|
|
1363
|
-
const band =
|
|
1523
|
+
const band = _chunkBPX4Z3N3cjs.normalizeChartReferenceBand.call(void 0, input, "referenceBand", issues);
|
|
1364
1524
|
if (!band || issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
|
|
1365
1525
|
const problem = this.referenceProblem(band.axis, [band.from, band.to]);
|
|
1366
1526
|
if (problem) return this.reject(problem);
|
|
@@ -1375,7 +1535,7 @@ var ChartController = (_class = class {
|
|
|
1375
1535
|
const merged = { ...current, ...patch };
|
|
1376
1536
|
for (const [k, v] of Object.entries(patch)) if (v === null) delete merged[k];
|
|
1377
1537
|
const issues = [];
|
|
1378
|
-
const band =
|
|
1538
|
+
const band = _chunkBPX4Z3N3cjs.normalizeChartReferenceBand.call(void 0, merged, "referenceBand", issues);
|
|
1379
1539
|
if (!band || issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
|
|
1380
1540
|
const problem = this.referenceProblem(band.axis, [band.from, band.to]);
|
|
1381
1541
|
if (problem) return this.reject(problem);
|
|
@@ -1398,7 +1558,7 @@ var ChartController = (_class = class {
|
|
|
1398
1558
|
const series = this.getSeries(seriesId);
|
|
1399
1559
|
if (!series) return this.unknownSeries(seriesId);
|
|
1400
1560
|
if (!Number.isInteger(index) || index < 0 || index >= this.spec.categories.length) return this.badIndex(index);
|
|
1401
|
-
const family =
|
|
1561
|
+
const family = _chunkBPX4Z3N3cjs.chartFamily.call(void 0, this.spec);
|
|
1402
1562
|
const text = label === null ? "" : String(label).trim();
|
|
1403
1563
|
if (text && family !== "cartesian" && family !== "xy") return this.reject(`Callouts are drawn on bar, line, area, scatter and bubble charts; this is a ${this.spec.type} chart.`);
|
|
1404
1564
|
if (text && (series.values[index] === null || series.values[index] === void 0))
|
|
@@ -1420,12 +1580,12 @@ var ChartController = (_class = class {
|
|
|
1420
1580
|
addTrendline(seriesId, input) {
|
|
1421
1581
|
const series = this.getSeries(seriesId);
|
|
1422
1582
|
if (!series) return this.unknownSeries(seriesId);
|
|
1423
|
-
if (!
|
|
1583
|
+
if (!_chunkUUUTEVX6cjs.chartSupportsTrendlines.call(void 0, this.spec.type, this.spec.stacking))
|
|
1424
1584
|
return this.reject(`Trendlines need an unstacked bar, line, area, scatter or bubble chart; this is a ${this.spec.stacking !== "none" ? `${this.spec.stacking} ` : ""}${this.spec.type} chart.`);
|
|
1425
1585
|
const issues = [];
|
|
1426
|
-
const line =
|
|
1586
|
+
const line = _chunkBPX4Z3N3cjs.normalizeChartTrendline.call(void 0, input, "trendline", issues);
|
|
1427
1587
|
if (!line || issues.length) return this.reject(issues.map((i) => i.message).join(" ") || "The trendline is not valid.", issues);
|
|
1428
|
-
const index = _nullishCoalesce(_optionalChain([series, 'access',
|
|
1588
|
+
const index = _nullishCoalesce(_optionalChain([series, 'access', _69 => _69.trendlines, 'optionalAccess', _70 => _70.length]), () => ( 0));
|
|
1429
1589
|
const next = this.edited((d) => {
|
|
1430
1590
|
const s = d.series.find((x) => x.id === seriesId);
|
|
1431
1591
|
s.trendlines = [..._nullishCoalesce(s.trendlines, () => ( [])), line];
|
|
@@ -1437,12 +1597,12 @@ var ChartController = (_class = class {
|
|
|
1437
1597
|
updateTrendline(seriesId, index, patch) {
|
|
1438
1598
|
const series = this.getSeries(seriesId);
|
|
1439
1599
|
if (!series) return this.unknownSeries(seriesId);
|
|
1440
|
-
const current = _optionalChain([series, 'access',
|
|
1441
|
-
if (!current) return fail(`"${series.name}" has no trendline ${index}; ${_optionalChain([series, 'access',
|
|
1600
|
+
const current = _optionalChain([series, 'access', _71 => _71.trendlines, 'optionalAccess', _72 => _72[index]]);
|
|
1601
|
+
if (!current) return fail(`"${series.name}" has no trendline ${index}; ${_optionalChain([series, 'access', _73 => _73.trendlines, 'optionalAccess', _74 => _74.length]) ? `expected 0 to ${series.trendlines.length - 1}` : "it has none yet"}.`);
|
|
1442
1602
|
const issues = [];
|
|
1443
1603
|
const merged = { ...current, ...patch };
|
|
1444
1604
|
for (const [k, v] of Object.entries(patch)) if (v === null) delete merged[k];
|
|
1445
|
-
const line =
|
|
1605
|
+
const line = _chunkBPX4Z3N3cjs.normalizeChartTrendline.call(void 0, merged, "trendline", issues);
|
|
1446
1606
|
if (!line || issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
|
|
1447
1607
|
this.commit(
|
|
1448
1608
|
"Change trendline",
|
|
@@ -1455,7 +1615,7 @@ var ChartController = (_class = class {
|
|
|
1455
1615
|
removeTrendline(seriesId, index) {
|
|
1456
1616
|
const series = this.getSeries(seriesId);
|
|
1457
1617
|
if (!series) return this.unknownSeries(seriesId);
|
|
1458
|
-
if (!_optionalChain([series, 'access',
|
|
1618
|
+
if (!_optionalChain([series, 'access', _75 => _75.trendlines, 'optionalAccess', _76 => _76[index]])) return fail(`"${series.name}" has no trendline ${index}.`);
|
|
1459
1619
|
this.commit(
|
|
1460
1620
|
"Delete trendline",
|
|
1461
1621
|
this.edited((d) => {
|
|
@@ -1470,25 +1630,25 @@ var ChartController = (_class = class {
|
|
|
1470
1630
|
trendlinePoints(seriesId) {
|
|
1471
1631
|
const series = this.getSeries(seriesId);
|
|
1472
1632
|
if (!series) return [];
|
|
1473
|
-
const xy =
|
|
1633
|
+
const xy = _chunkBPX4Z3N3cjs.chartFamily.call(void 0, this.spec) === "xy";
|
|
1474
1634
|
const out = [];
|
|
1475
1635
|
series.values.forEach((v, i) => {
|
|
1476
|
-
const x = xy ? _nullishCoalesce(_optionalChain([series, 'access',
|
|
1636
|
+
const x = xy ? _nullishCoalesce(_optionalChain([series, 'access', _77 => _77.x, 'optionalAccess', _78 => _78[i]]), () => ( (this.spec.type === "bubble" ? i + 1 : null))) : i + 1;
|
|
1477
1637
|
if (v !== null && x !== null && Number.isFinite(v) && Number.isFinite(x)) out.push([x, v]);
|
|
1478
1638
|
});
|
|
1479
1639
|
return out;
|
|
1480
1640
|
}
|
|
1481
1641
|
/** The fitted coefficients, R² and equation of a trendline (null for moving averages or unfittable data). */
|
|
1482
1642
|
trendlineFit(seriesId, index) {
|
|
1483
|
-
const line = _optionalChain([this, 'access',
|
|
1643
|
+
const line = _optionalChain([this, 'access', _79 => _79.getSeries, 'call', _80 => _80(seriesId), 'optionalAccess', _81 => _81.trendlines, 'optionalAccess', _82 => _82[index]]);
|
|
1484
1644
|
if (!line) return null;
|
|
1485
|
-
return
|
|
1645
|
+
return _chunkUUUTEVX6cjs.fitChartTrendline.call(void 0, line, this.trendlinePoints(seriesId));
|
|
1486
1646
|
}
|
|
1487
1647
|
/** The moving-average points of a trendline (empty for other kinds). */
|
|
1488
1648
|
trendlineMovingAverage(seriesId, index) {
|
|
1489
|
-
const line = _optionalChain([this, 'access',
|
|
1649
|
+
const line = _optionalChain([this, 'access', _83 => _83.getSeries, 'call', _84 => _84(seriesId), 'optionalAccess', _85 => _85.trendlines, 'optionalAccess', _86 => _86[index]]);
|
|
1490
1650
|
if (!line || line.type !== "moving-average") return [];
|
|
1491
|
-
return
|
|
1651
|
+
return _chunkUUUTEVX6cjs.chartMovingAverage.call(void 0, this.trendlinePoints(seriesId), _nullishCoalesce(line.period, () => ( 2)));
|
|
1492
1652
|
}
|
|
1493
1653
|
// -------------------------------------------------------------------------
|
|
1494
1654
|
// Reshaping
|
|
@@ -1509,17 +1669,66 @@ var ChartController = (_class = class {
|
|
|
1509
1669
|
used.add(id);
|
|
1510
1670
|
return { id, name, values: s.series.map((x) => _nullishCoalesce(x.values[i], () => ( null))) };
|
|
1511
1671
|
});
|
|
1512
|
-
const { spec } =
|
|
1672
|
+
const { spec } = _chunkBPX4Z3N3cjs.normalizeChartSpec.call(void 0, { ...s, categories: s.series.map((x) => x.name), series });
|
|
1513
1673
|
this.commit("Switch rows and columns", spec, null);
|
|
1514
1674
|
return { ok: true };
|
|
1515
1675
|
}
|
|
1516
1676
|
// -------------------------------------------------------------------------
|
|
1517
1677
|
// Selection and gestures
|
|
1518
1678
|
// -------------------------------------------------------------------------
|
|
1679
|
+
/**
|
|
1680
|
+
* Shows a bar race at a moment: a category index, fractional between time points (`null`:
|
|
1681
|
+
* the last one). View state like the selection, so not an undo step. Stops playback.
|
|
1682
|
+
*/
|
|
1683
|
+
setRaceFrame(frame) {
|
|
1684
|
+
const n = this.spec.categories.length;
|
|
1685
|
+
if (frame !== null && !(Number.isFinite(frame) && frame >= 0 && frame <= Math.max(0, n - 1)))
|
|
1686
|
+
return fail(n ? `The race has time points 0 to ${n - 1}${n > 1 ? ` ("${this.spec.categories[0]}" to "${this.spec.categories[n - 1]}")` : ""}; got ${frame}.` : "The chart has no time points (categories) yet.");
|
|
1687
|
+
this.stopRace();
|
|
1688
|
+
if (frame === this.raceFrame) return { ok: true };
|
|
1689
|
+
this.raceFrame = frame;
|
|
1690
|
+
this.notify(false);
|
|
1691
|
+
return { ok: true };
|
|
1692
|
+
}
|
|
1693
|
+
/**
|
|
1694
|
+
* Plays the bar race from the moment shown (from the start when it is at the end), moving
|
|
1695
|
+
* one time point every `msPerStep` (default 1000) until the last. Not an undo step.
|
|
1696
|
+
*/
|
|
1697
|
+
playRace(options = {}) {
|
|
1698
|
+
const last = this.spec.categories.length - 1;
|
|
1699
|
+
if (last < 1) return fail("A race needs at least two time points (categories) to play.");
|
|
1700
|
+
this.stopRace();
|
|
1701
|
+
const per = Math.max(50, _nullishCoalesce(options.msPerStep, () => ( 1e3)));
|
|
1702
|
+
const from = this.raceFrame === null || this.raceFrame >= last ? 0 : this.raceFrame;
|
|
1703
|
+
const start = this.raceTicker.now();
|
|
1704
|
+
const step = () => {
|
|
1705
|
+
const at = Math.min(last, from + (this.raceTicker.now() - start) / per);
|
|
1706
|
+
this.raceFrame = at;
|
|
1707
|
+
if (at >= last) {
|
|
1708
|
+
this.raceStop = null;
|
|
1709
|
+
this.raceFrame = null;
|
|
1710
|
+
} else this.raceStop = this.raceTicker.next(step);
|
|
1711
|
+
this.notify(false);
|
|
1712
|
+
};
|
|
1713
|
+
this.raceFrame = from;
|
|
1714
|
+
this.raceStop = this.raceTicker.next(step);
|
|
1715
|
+
this.notify(false);
|
|
1716
|
+
return { ok: true };
|
|
1717
|
+
}
|
|
1718
|
+
/** Pauses bar race playback where it is. */
|
|
1719
|
+
pauseRace() {
|
|
1720
|
+
if (!this.raceStop) return;
|
|
1721
|
+
this.stopRace();
|
|
1722
|
+
this.notify(false);
|
|
1723
|
+
}
|
|
1724
|
+
stopRace() {
|
|
1725
|
+
_optionalChain([this, 'access', _87 => _87.raceStop, 'optionalCall', _88 => _88()]);
|
|
1726
|
+
this.raceStop = null;
|
|
1727
|
+
}
|
|
1519
1728
|
/** Selects a chart element (view state; not an undo step). */
|
|
1520
1729
|
select(selection) {
|
|
1521
1730
|
const next = this.validSelection(selection, this.spec);
|
|
1522
|
-
if (
|
|
1731
|
+
if (_chunkUUUTEVX6cjs.sameChartSelection.call(void 0, next, this.selection) || next === null && this.selection === null) return;
|
|
1523
1732
|
this.selection = next;
|
|
1524
1733
|
this.notify(false);
|
|
1525
1734
|
}
|
|
@@ -1596,14 +1805,14 @@ var ChartController = (_class = class {
|
|
|
1596
1805
|
// -------------------------------------------------------------------------
|
|
1597
1806
|
/** The spec, for saving (a copy). */
|
|
1598
1807
|
toJSON() {
|
|
1599
|
-
return
|
|
1808
|
+
return _chunkBPX4Z3N3cjs.cloneChartSpec.call(void 0, this.spec);
|
|
1600
1809
|
}
|
|
1601
1810
|
/**
|
|
1602
1811
|
* Replaces the chart without an undo step (e.g. when opening a document). Problems are
|
|
1603
1812
|
* fixed with defaults and reported in `state.issues` (and returned).
|
|
1604
1813
|
*/
|
|
1605
1814
|
load(input, options = {}) {
|
|
1606
|
-
const { spec, issues } =
|
|
1815
|
+
const { spec, issues } = _chunkBPX4Z3N3cjs.normalizeChartSpec.call(void 0, input);
|
|
1607
1816
|
this.spec = spec;
|
|
1608
1817
|
this.issues = issues;
|
|
1609
1818
|
this.selection = this.validSelection(this.selection, spec);
|
|
@@ -1623,7 +1832,7 @@ var ChartController = (_class = class {
|
|
|
1623
1832
|
* nothing changes and every problem is returned (and shown in `state.issues`).
|
|
1624
1833
|
*/
|
|
1625
1834
|
replace(input, options = {}) {
|
|
1626
|
-
const { spec, issues } =
|
|
1835
|
+
const { spec, issues } = _chunkBPX4Z3N3cjs.normalizeChartSpec.call(void 0, input);
|
|
1627
1836
|
if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
|
|
1628
1837
|
this.commit(_nullishCoalesce(options.label, () => ( "Replace chart")), spec, this.validSelection(this.selection, spec));
|
|
1629
1838
|
return { ok: true };
|
|
@@ -1638,7 +1847,8 @@ var ChartController = (_class = class {
|
|
|
1638
1847
|
}
|
|
1639
1848
|
/** Stops listening to the history (reconnected by the next `subscribe`). */
|
|
1640
1849
|
destroy() {
|
|
1641
|
-
|
|
1850
|
+
this.stopRace();
|
|
1851
|
+
_optionalChain([this, 'access', _89 => _89.unsubscribeHistory, 'optionalCall', _90 => _90()]);
|
|
1642
1852
|
this.unsubscribeHistory = void 0;
|
|
1643
1853
|
this.listeners.clear();
|
|
1644
1854
|
}
|
|
@@ -1673,8 +1883,12 @@ function updateLabel(patch) {
|
|
|
1673
1883
|
parliamentArc: "Change hemicycle sweep",
|
|
1674
1884
|
parliamentMajority: "Change majority",
|
|
1675
1885
|
parliamentLabel: "Edit seat caption",
|
|
1886
|
+
raceTopN: "Change bars shown",
|
|
1676
1887
|
sunburstLabel: "Edit centre caption",
|
|
1677
1888
|
tree: "Replace grouped data",
|
|
1889
|
+
links: "Replace flows",
|
|
1890
|
+
sankeyNodes: "Reorder nodes",
|
|
1891
|
+
sankeyLinkColor: "Change flow colours",
|
|
1678
1892
|
radarTicks: "Change radar rings",
|
|
1679
1893
|
radarGraticule: "Change radar grid",
|
|
1680
1894
|
legend: "Change legend",
|
|
@@ -1697,7 +1911,7 @@ function layoutSparkline(values, options) {
|
|
|
1697
1911
|
const h = Number.isFinite(options.height) ? Math.max(1, options.height) : 1;
|
|
1698
1912
|
const color = _nullishCoalesce(options.color, () => ( "#4269d0"));
|
|
1699
1913
|
const negative = _nullishCoalesce(options.negativeColor, () => ( "#e5484d"));
|
|
1700
|
-
const theme = { ...
|
|
1914
|
+
const theme = { ..._chunkBPX4Z3N3cjs.DEFAULT_CHART_THEME, background: "transparent" };
|
|
1701
1915
|
const marks = [];
|
|
1702
1916
|
const scene = { width: w, height: h, plot: { x: 0, y: 0, width: w, height: h }, marks, percent: false, theme, warnings: [] };
|
|
1703
1917
|
const vals = values.slice(0, MAX_POINTS).map((v) => v !== null && Number.isFinite(v) ? Math.max(-1e300, Math.min(1e300, v)) : null);
|
|
@@ -1730,7 +1944,7 @@ function layoutSparkline(values, options) {
|
|
|
1730
1944
|
const flush = () => {
|
|
1731
1945
|
if (run.length >= 2) {
|
|
1732
1946
|
const pts = run.length > 4e3 ? run.filter((_, i) => i % (Math.floor(run.length / 2e3) + 1) === 0) : run;
|
|
1733
|
-
d += pts.map(([x, y], i) => `${i ? "L" : "M"}${
|
|
1947
|
+
d += pts.map(([x, y], i) => `${i ? "L" : "M"}${_chunkUUUTEVX6cjs.r2.call(void 0, x)},${_chunkUUUTEVX6cjs.r2.call(void 0, y)}`).join("");
|
|
1734
1948
|
}
|
|
1735
1949
|
run = [];
|
|
1736
1950
|
};
|