@pixerate/editor 0.165.0 → 0.167.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.
Files changed (55) hide show
  1. package/THIRD_PARTY_NOTICES.md +11 -0
  2. package/dist/agent/index.cjs +34 -34
  3. package/dist/agent/index.js +5 -5
  4. package/dist/canvas/index.cjs +6 -6
  5. package/dist/canvas/index.js +2 -2
  6. package/dist/chart/controller.d.cts +29 -0
  7. package/dist/chart/controller.d.ts +29 -0
  8. package/dist/chart/index.cjs +352 -179
  9. package/dist/chart/index.d.cts +2 -0
  10. package/dist/chart/index.d.ts +2 -0
  11. package/dist/chart/index.js +183 -10
  12. package/dist/chart/layout-families.d.cts +15 -0
  13. package/dist/chart/layout-families.d.ts +15 -0
  14. package/dist/chart/layout-shared.d.cts +5 -0
  15. package/dist/chart/layout-shared.d.ts +5 -0
  16. package/dist/chart/maps.d.cts +43 -0
  17. package/dist/chart/maps.d.ts +43 -0
  18. package/dist/chart/race.d.cts +26 -0
  19. package/dist/chart/race.d.ts +26 -0
  20. package/dist/chart/schemas.d.cts +2 -0
  21. package/dist/chart/schemas.d.ts +2 -0
  22. package/dist/chart/spec.d.cts +1 -1
  23. package/dist/chart/spec.d.ts +1 -1
  24. package/dist/chart/types.d.cts +14 -2
  25. package/dist/chart/types.d.ts +14 -2
  26. package/dist/chart-maps/europe.d.cts +7 -0
  27. package/dist/chart-maps/europe.d.ts +7 -0
  28. package/dist/chart-maps/index.cjs +66 -0
  29. package/dist/chart-maps/index.d.cts +1 -0
  30. package/dist/chart-maps/index.d.ts +1 -0
  31. package/dist/chart-maps/index.js +66 -0
  32. package/dist/{chunk-IMRXC7OA.cjs → chunk-2F4GAZL5.cjs} +186 -96
  33. package/dist/{chunk-FEU2XVQH.js → chunk-34UCPHYO.js} +8 -2
  34. package/dist/{chunk-ODFCS7HF.cjs → chunk-E45AIIWY.cjs} +8 -8
  35. package/dist/{chunk-N7NBGT2Y.js → chunk-FKYGM35R.js} +2 -2
  36. package/dist/{chunk-64VWWR5U.cjs → chunk-GD34ICEX.cjs} +16 -16
  37. package/dist/{chunk-TVQW26AV.cjs → chunk-GTF4RYXJ.cjs} +29 -23
  38. package/dist/{chunk-V5GSY3NC.js → chunk-M52UCHVZ.js} +203 -3
  39. package/dist/{chunk-FRBRLKNQ.js → chunk-N3ACT6VJ.js} +92 -2
  40. package/dist/{chunk-CRFSQWKQ.js → chunk-OLCHKGGO.js} +7 -1
  41. package/dist/{chunk-2ZRN43IN.js → chunk-ORZF4JOO.js} +32 -4
  42. package/dist/{chunk-UVXTOZ2B.cjs → chunk-OUO3DSRT.cjs} +32 -4
  43. package/dist/{chunk-MKXK6E4O.cjs → chunk-SBAPXFPB.cjs} +51 -51
  44. package/dist/{chunk-2J5VLJHC.js → chunk-T62BRXMS.js} +3 -3
  45. package/dist/{chunk-Q25WAFTD.cjs → chunk-VKHJJUBK.cjs} +24 -18
  46. package/dist/{chunk-QO2T6KA5.cjs → chunk-WOIXNDHV.cjs} +247 -47
  47. package/dist/{chunk-X5W645RI.js → chunk-ZUPP4NKM.js} +3 -3
  48. package/dist/export/index.cjs +4 -4
  49. package/dist/export/index.js +3 -3
  50. package/dist/extensions/index.cjs +7 -7
  51. package/dist/extensions/index.js +6 -6
  52. package/dist/index.cjs +13 -13
  53. package/dist/index.js +7 -7
  54. package/package.json +11 -1
  55. package/skills/pixerate-chart/SKILL.md +36 -2
@@ -11,10 +11,10 @@ var _chunkTTCJPX4Ucjs = require('./chunk-TTCJPX4U.cjs');
11
11
 
12
12
 
13
13
 
14
- var _chunkQO2T6KA5cjs = require('./chunk-QO2T6KA5.cjs');
15
14
 
16
15
 
17
16
 
17
+ var _chunkWOIXNDHVcjs = require('./chunk-WOIXNDHV.cjs');
18
18
 
19
19
 
20
20
 
@@ -44,7 +44,10 @@ var _chunkQO2T6KA5cjs = require('./chunk-QO2T6KA5.cjs');
44
44
 
45
45
 
46
46
 
47
- var _chunkUVXTOZ2Bcjs = require('./chunk-UVXTOZ2B.cjs');
47
+
48
+
49
+
50
+ var _chunkOUO3DSRTcjs = require('./chunk-OUO3DSRT.cjs');
48
51
 
49
52
 
50
53
 
@@ -83,7 +86,7 @@ var csvField = (text) => /[",\n]|^\s|\s$/.test(text) ? `"${text.replace(/"/g, '"
83
86
  var treemapName = (name) => !name.includes('"') ? `"${name}"` : !name.includes("'") ? `'${name}'` : `"${name.replace(/"/g, "'")}"`;
84
87
  var yamlText = (text) => /^[\w][\w .,!?()/&+-]*$/.test(text) && !/:\s/.test(text) ? text : JSON.stringify(text);
85
88
  function chartMermaidFamily(spec) {
86
- const family = _chunkUVXTOZ2Bcjs.chartFamily.call(void 0, spec);
89
+ const family = _chunkOUO3DSRTcjs.chartFamily.call(void 0, spec);
87
90
  if (family === "sankey" && _optionalChain([spec, 'access', _2 => _2.links, 'optionalAccess', _3 => _3.length])) return "sankey";
88
91
  if (family === "treemap" || family === "sunburst") return "treemap";
89
92
  if (family === "pie" || family === "funnel" || family === "parliament") return "pie";
@@ -136,7 +139,7 @@ function chartToMermaid(spec, options = {}) {
136
139
  lines.push("treemap-beta");
137
140
  if (spec.title) lines.push(`title ${spec.title}`);
138
141
  const first = _nullishCoalesce(visible[0], () => ( spec.series[0]));
139
- const tree = spec.tree.length ? spec.tree : _chunkUVXTOZ2Bcjs.chartTreeFromSeries.call(void 0, spec.categories, _nullishCoalesce(_optionalChain([first, 'optionalAccess', _4 => _4.values]), () => ( [])));
142
+ const tree = spec.tree.length ? spec.tree : _chunkOUO3DSRTcjs.chartTreeFromSeries.call(void 0, spec.categories, _nullishCoalesce(_optionalChain([first, 'optionalAccess', _4 => _4.values]), () => ( [])));
140
143
  const write = (nodes, depth) => {
141
144
  for (const n of nodes) {
142
145
  const pad = ind.repeat(depth);
@@ -271,8 +274,8 @@ function chartFromMermaid(text, options = {}) {
271
274
  let title = _nullishCoalesce(frontTitle, () => ( ""));
272
275
  const categories = [];
273
276
  const series = [];
274
- const xAxis = _chunkUVXTOZ2Bcjs.defaultChartAxis.call(void 0, false);
275
- const yAxis = _chunkUVXTOZ2Bcjs.defaultChartAxis.call(void 0, true);
277
+ const xAxis = _chunkOUO3DSRTcjs.defaultChartAxis.call(void 0, false);
278
+ const yAxis = _chunkOUO3DSRTcjs.defaultChartAxis.call(void 0, true);
276
279
  const radarAxes = [];
277
280
  const pieSlices = [];
278
281
  let legendShow = true;
@@ -434,7 +437,7 @@ function chartFromMermaid(text, options = {}) {
434
437
  input.series = metaSeries.map((extra, i) => ({ ..._nullishCoalesce(base[i], () => ( {})), ..._nullishCoalesce(extra, () => ( {})) }));
435
438
  }
436
439
  }
437
- const { spec, issues: specIssues } = _chunkUVXTOZ2Bcjs.normalizeChartSpec.call(void 0, input);
440
+ const { spec, issues: specIssues } = _chunkOUO3DSRTcjs.normalizeChartSpec.call(void 0, input);
438
441
  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)." });
439
442
  return { spec, issues: [...issues, ...specIssues], family, hasMeta: !!meta };
440
443
  }
@@ -464,7 +467,7 @@ function readWholeMermaid(family, all, headerLine, partial, title, issues) {
464
467
  const tree = items.map(toNode);
465
468
  const leaf = (n) => !n.children;
466
469
  const flatOrOneLevel = tree.every(leaf) || tree.every((n) => _optionalChain([n, 'access', _18 => _18.children, 'optionalAccess', _19 => _19.every, 'call', _20 => _20(leaf)]));
467
- return { type: flatOrOneLevel ? "treemap" : "sunburst", title: name, tree, categories: tree.map((n) => n.name), series: [{ id: "series-1", name: "Values", values: tree.map(_chunkUVXTOZ2Bcjs.chartTreeTotal) }] };
470
+ return { type: flatOrOneLevel ? "treemap" : "sunburst", title: name, tree, categories: tree.map((n) => n.name), series: [{ id: "series-1", name: "Values", values: tree.map(_chunkOUO3DSRTcjs.chartTreeTotal) }] };
468
471
  }
469
472
  function findMermaidCharts(text) {
470
473
  const lines = text.replace(/^/, "").split(/\r?\n/);
@@ -509,11 +512,11 @@ function findMermaidCharts(text) {
509
512
  }
510
513
 
511
514
  // src/chart/summary.ts
512
- function summarizeChart(spec, size = { width: 640, height: 400 }, scene = _chunkQO2T6KA5cjs.layoutChart.call(void 0, spec, { ...size, selection: null })) {
515
+ function summarizeChart(spec, size = { width: 640, height: 400 }, scene = _chunkWOIXNDHVcjs.layoutChart.call(void 0, spec, { ...size, selection: null })) {
513
516
  const visible = spec.series.filter((s) => !s.hidden);
514
- const series = visible.map((s) => _chunkQO2T6KA5cjs.summarizeChartSeries.call(void 0, s, spec.categories));
515
- const colors = _chunkUVXTOZ2Bcjs.chartSpecColorsByCategory.call(void 0, spec) ? spec.categories.map((_, i) => _optionalChain([visible, 'access', _24 => _24[0], 'optionalAccess', _25 => _25.pointColors, 'optionalAccess', _26 => _26[i]]) || _chunkUVXTOZ2Bcjs.chartSliceColor.call(void 0, spec, i)) : visible.map((s) => _chunkUVXTOZ2Bcjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(s)));
516
- const check = _chunkUVXTOZ2Bcjs.checkChartColors.call(void 0, colors, { surface: scene.theme.surface.startsWith("var(") ? "#ffffff" : scene.theme.surface });
517
+ const series = visible.map((s) => _chunkWOIXNDHVcjs.summarizeChartSeries.call(void 0, s, spec.categories));
518
+ const colors = _chunkOUO3DSRTcjs.chartSpecColorsByCategory.call(void 0, spec) ? spec.categories.map((_, i) => _optionalChain([visible, 'access', _24 => _24[0], 'optionalAccess', _25 => _25.pointColors, 'optionalAccess', _26 => _26[i]]) || _chunkOUO3DSRTcjs.chartSliceColor.call(void 0, spec, i)) : visible.map((s) => _chunkOUO3DSRTcjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(s)));
519
+ const check = _chunkOUO3DSRTcjs.checkChartColors.call(void 0, colors, { surface: scene.theme.surface.startsWith("var(") ? "#ffffff" : scene.theme.surface });
517
520
  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;
518
521
  return {
519
522
  type: spec.type,
@@ -528,12 +531,12 @@ function summarizeChart(spec, size = { width: 640, height: 400 }, scene = _chunk
528
531
  description: describeChart(spec, series)
529
532
  };
530
533
  }
531
- function describeChart(spec, series = spec.series.filter((s) => !s.hidden).map((s) => _chunkQO2T6KA5cjs.summarizeChartSeries.call(void 0, s, spec.categories))) {
532
- const kind = _chunkUVXTOZ2Bcjs.CHART_TYPE_LABELS[spec.type].toLowerCase();
534
+ function describeChart(spec, series = spec.series.filter((s) => !s.hidden).map((s) => _chunkWOIXNDHVcjs.summarizeChartSeries.call(void 0, s, spec.categories))) {
535
+ const kind = _chunkOUO3DSRTcjs.CHART_TYPE_LABELS[spec.type].toLowerCase();
533
536
  const parts = [];
534
- const family = _chunkUVXTOZ2Bcjs.chartFamily.call(void 0, spec);
537
+ const family = _chunkOUO3DSRTcjs.chartFamily.call(void 0, spec);
535
538
  const format = spec.yAxis.format;
536
- const fmt = (v) => v === null ? "blank" : _chunkQO2T6KA5cjs.formatChartNumber.call(void 0, v, format);
539
+ const fmt = (v) => v === null ? "blank" : _chunkWOIXNDHVcjs.formatChartNumber.call(void 0, v, format);
537
540
  const head = spec.title ? `${spec.title}: a ${kind} chart` : `A ${kind} chart`;
538
541
  if (!series.length || series.every((s) => s.count === 0)) return `${head} with no data.`;
539
542
  if (family === "pie" || family === "funnel" || family === "treemap" || family === "sunburst") {
@@ -543,12 +546,28 @@ function describeChart(spec, series = spec.series.filter((s) => !s.hidden).map((
543
546
  parts.push(`${head} of ${s.name} across ${spec.categories.length} categories, totalling ${fmt(s.sum)}.`);
544
547
  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)}.`);
545
548
  if (spec.tree.length) {
546
- const depth = _chunkUVXTOZ2Bcjs.chartTreeDepth.call(void 0, spec.tree);
547
- const items = _chunkUVXTOZ2Bcjs.chartTreeToRows.call(void 0, spec.tree).length;
549
+ const depth = _chunkOUO3DSRTcjs.chartTreeDepth.call(void 0, spec.tree);
550
+ const items = _chunkOUO3DSRTcjs.chartTreeToRows.call(void 0, spec.tree).length;
548
551
  parts.push(`The data is grouped ${depth} level${depth === 1 ? "" : "s"} deep with ${items} item${items === 1 ? "" : "s"}.`);
549
552
  }
550
553
  return parts.join(" ");
551
554
  }
555
+ if (family === "choropleth") {
556
+ const s = spec.series.find((x) => !x.hidden);
557
+ const map = _chunkWOIXNDHVcjs.getChartMap.call(void 0, spec.map);
558
+ const matches = map ? _chunkWOIXNDHVcjs.matchChartMapRegions.call(void 0, map, spec.categories) : spec.categories.map(() => null);
559
+ const rows = spec.categories.flatMap((c, i) => matches[i] && s.values[i] !== null ? [{ name: matches[i].name, v: s.values[i] }] : []).sort((a, b) => b.v - a.v);
560
+ const missing = spec.categories.filter((_, i) => !matches[i]).length;
561
+ if (!rows.length) return `${head} of ${_nullishCoalesce(_optionalChain([map, 'optionalAccess', _27 => _27.name]), () => ( spec.map))} with no regions matched.`;
562
+ return `${head} of ${_nullishCoalesce(_optionalChain([map, 'optionalAccess', _28 => _28.name]), () => ( spec.map))} shading ${rows.length} region${rows.length === 1 ? "" : "s"} by ${s.name}: highest ${rows[0].name} (${fmt(rows[0].v)}), lowest ${rows[rows.length - 1].name} (${fmt(rows[rows.length - 1].v)}).${missing ? ` ${missing} categor${missing === 1 ? "y names" : "ies name"} no region.` : ""}`;
563
+ }
564
+ if (family === "barrace") {
565
+ const n = spec.categories.length;
566
+ const first = _chunkWOIXNDHVcjs.chartRaceRanking.call(void 0, spec, 0)[0];
567
+ const last = _chunkWOIXNDHVcjs.chartRaceRanking.call(void 0, spec, n - 1)[0];
568
+ const lead = (e, at) => e ? `${e.name} leads at ${at} with ${fmt(e.value)}` : "";
569
+ 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])}.`;
570
+ }
552
571
  if (family === "sankey") {
553
572
  if (!spec.links.length) return `${head} with no flows yet.`;
554
573
  const total = spec.links.reduce((t, l) => t + l.value, 0);
@@ -563,7 +582,7 @@ function describeChart(spec, series = spec.series.filter((s) => !s.hidden).map((
563
582
  const total = seats.reduce((t, x) => t + x.n, 0);
564
583
  const majority = _nullishCoalesce(spec.parliamentMajority, () => ( Math.floor(total / 2) + 1));
565
584
  const largest = [...seats].sort((a, b) => b.n - a.n)[0];
566
- 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])}`;
585
+ 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', _29 => _29.c])} with ${_optionalChain([largest, 'optionalAccess', _30 => _30.n])}`;
567
586
  return `${head} of ${total} seats across ${seats.length} groups: ${verdict}.`;
568
587
  }
569
588
  if (family === "slope") {
@@ -586,7 +605,7 @@ function describeChart(spec, series = spec.series.filter((s) => !s.hidden).map((
586
605
  });
587
606
  const best = [...agree].sort((x, y) => y.share - x.share);
588
607
  const pct = (v) => `${Math.round(v * 100)}%`;
589
- 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)))}).`;
608
+ return `${head} of ${spec.categories.length} questions with ${answers.length} answers from ${_optionalChain([answers, 'access', _31 => _31[0], 'optionalAccess', _32 => _32.name])} to ${_optionalChain([answers, 'access', _33 => _33[answers.length - 1], 'optionalAccess', _34 => _34.name])}. Most positive: ${_optionalChain([best, 'access', _35 => _35[0], 'optionalAccess', _36 => _36.c])} (${pct(_nullishCoalesce(_optionalChain([best, 'access', _37 => _37[0], 'optionalAccess', _38 => _38.share]), () => ( 0)))}); least: ${_optionalChain([best, 'access', _39 => _39[best.length - 1], 'optionalAccess', _40 => _40.c])} (${pct(_nullishCoalesce(_optionalChain([best, 'access', _41 => _41[best.length - 1], 'optionalAccess', _42 => _42.share]), () => ( 0)))}).`;
590
609
  }
591
610
  if (family === "waterfall") {
592
611
  const s = spec.series.find((x) => !x.hidden);
@@ -625,7 +644,7 @@ function describeChart(spec, series = spec.series.filter((s) => !s.hidden).map((
625
644
  }
626
645
  parts.push(...axes);
627
646
  for (const s of spec.series.filter((x) => !x.hidden && (x.errorBars || x.xErrorBars)).slice(0, 8)) {
628
- const bars = [s.errorBars ? _chunkUVXTOZ2Bcjs.describeChartErrorBars.call(void 0, s.errorBars) : "", s.xErrorBars ? `x ${_chunkUVXTOZ2Bcjs.describeChartErrorBars.call(void 0, s.xErrorBars)}` : ""].filter(Boolean).join(" and ");
647
+ const bars = [s.errorBars ? _chunkOUO3DSRTcjs.describeChartErrorBars.call(void 0, s.errorBars) : "", s.xErrorBars ? `x ${_chunkOUO3DSRTcjs.describeChartErrorBars.call(void 0, s.xErrorBars)}` : ""].filter(Boolean).join(" and ");
629
648
  parts.push(`${s.name} has ${bars}.`);
630
649
  }
631
650
  return parts.join(" ");
@@ -690,7 +709,7 @@ function chartSceneToSvg(scene, options = {}) {
690
709
  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>`;
691
710
  }
692
711
  function chartToSvg(spec, options) {
693
- const scene = _chunkQO2T6KA5cjs.layoutChart.call(void 0, spec, { ...options, selection: null });
712
+ const scene = _chunkWOIXNDHVcjs.layoutChart.call(void 0, spec, { ...options, selection: null });
694
713
  return chartSceneToSvg(scene, { ...options, ariaLabel: _nullishCoalesce(options.ariaLabel, () => ( (spec.title || void 0))), description: _nullishCoalesce(options.description, () => ( describeChart(spec))) });
695
714
  }
696
715
  var SVG_NS = "http://www.w3.org/2000/svg";
@@ -728,10 +747,10 @@ var CHART_LAYOUT_PRESETS = [
728
747
  ];
729
748
  function monochromeChartPalette(base, count = 6) {
730
749
  const steps = count <= 1 ? [0] : Array.from({ length: count }, (_, i) => -0.45 + 1.05 * i / (count - 1));
731
- return steps.map((t) => _chunkUVXTOZ2Bcjs.shadeChartColor.call(void 0, base, t));
750
+ return steps.map((t) => _chunkOUO3DSRTcjs.shadeChartColor.call(void 0, base, t));
732
751
  }
733
752
  var CHART_COLOR_SCHEMES = [
734
- { id: "default", label: "Default", description: "Ten distinct colours, readable on light and dark backgrounds.", palette: _chunkUVXTOZ2Bcjs.DEFAULT_CHART_PALETTE },
753
+ { id: "default", label: "Default", description: "Ten distinct colours, readable on light and dark backgrounds.", palette: _chunkOUO3DSRTcjs.DEFAULT_CHART_PALETTE },
735
754
  { 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"] },
736
755
  { id: "office", label: "Office", description: "The six accent colours of the default Office theme.", palette: ["#4472c4", "#ed7d31", "#a5a5a5", "#ffc000", "#5b9bd5", "#70ad47"] },
737
756
  { id: "warm", label: "Warm", description: "Reds, oranges and yellows.", palette: ["#b2182b", "#d6604d", "#f4a582", "#e08214", "#fdb863", "#8c510a"] },
@@ -759,7 +778,7 @@ function chartPresetPatch(options) {
759
778
 
760
779
  // src/chart/controller.ts
761
780
  function pointLists(s) {
762
- 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])];
781
+ const lists = [s.values, s.x, s.sizes, s.pointColors, s.callouts, _optionalChain([s, 'access', _43 => _43.errorBars, 'optionalAccess', _44 => _44.plus]), _optionalChain([s, 'access', _45 => _45.errorBars, 'optionalAccess', _46 => _46.minus]), _optionalChain([s, 'access', _47 => _47.xErrorBars, 'optionalAccess', _48 => _48.plus]), _optionalChain([s, 'access', _49 => _49.xErrorBars, 'optionalAccess', _50 => _50.minus])];
763
782
  return lists.filter((l) => Array.isArray(l));
764
783
  }
765
784
  function sameChartJson(a, b) {
@@ -776,6 +795,17 @@ function sameChartJson(a, b) {
776
795
  if (keys.length !== Object.keys(bo).filter((k) => bo[k] !== void 0).length) return false;
777
796
  return keys.every((k) => Object.prototype.hasOwnProperty.call(bo, k) && sameChartJson(ao[k], bo[k]));
778
797
  }
798
+ var defaultRaceTicker = {
799
+ now: () => typeof performance !== "undefined" ? performance.now() : Date.now(),
800
+ next: (step) => {
801
+ if (typeof requestAnimationFrame === "function") {
802
+ const id2 = requestAnimationFrame(() => step());
803
+ return () => cancelAnimationFrame(id2);
804
+ }
805
+ const id = setTimeout(step, 16);
806
+ return () => clearTimeout(id);
807
+ }
808
+ };
779
809
  var fail = (message, issues) => ({ ok: false, message, ...issues ? { issues } : {} });
780
810
  var ChartController = (_class = class {
781
811
 
@@ -788,20 +818,24 @@ var ChartController = (_class = class {
788
818
  __init6() {this.revision = 0}
789
819
  __init7() {this.applying = false}
790
820
 
791
- __init8() {this.listeners = /* @__PURE__ */ new Set()}
821
+
822
+ __init8() {this.raceFrame = null}
823
+ __init9() {this.raceStop = null}
824
+ __init10() {this.listeners = /* @__PURE__ */ new Set()}
792
825
 
793
826
 
794
- 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);
827
+ 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);
795
828
  this.history = _nullishCoalesce(options.history, () => ( new (0, _chunkFJ2MSI43cjs.HistoryManager)()));
796
829
  this.onChange = options.onChange;
797
- const { spec, issues } = _chunkUVXTOZ2Bcjs.normalizeChartSpec.call(void 0, _nullishCoalesce(options.spec, () => ( {})));
830
+ this.raceTicker = _nullishCoalesce(options.raceTicker, () => ( defaultRaceTicker));
831
+ const { spec, issues } = _chunkOUO3DSRTcjs.normalizeChartSpec.call(void 0, _nullishCoalesce(options.spec, () => ( {})));
798
832
  this.spec = spec;
799
833
  this.issues = issues;
800
834
  this.state = this.computeState();
801
835
  this.connect();
802
836
  }
803
837
  connect() {
804
- _optionalChain([this, 'access', _49 => _49.unsubscribeHistory, 'optionalCall', _50 => _50()]);
838
+ _optionalChain([this, 'access', _51 => _51.unsubscribeHistory, 'optionalCall', _52 => _52()]);
805
839
  this.unsubscribeHistory = this.history.subscribe((h) => {
806
840
  const s = this.state;
807
841
  if (this.applying || s.canUndo === h.canUndo && s.canRedo === h.canRedo && s.undoLabel === h.undoName && s.redoLabel === h.redoName) return;
@@ -812,9 +846,9 @@ var ChartController = (_class = class {
812
846
  // State
813
847
  // -------------------------------------------------------------------------
814
848
  /** The current snapshot (stable until the next change). */
815
- __init9() {this.getState = () => this.state}
849
+ __init11() {this.getState = () => this.state}
816
850
  /** Calls `listener` after every change. Returns an unsubscribe function. */
817
- __init10() {this.subscribe = (listener) => {
851
+ __init12() {this.subscribe = (listener) => {
818
852
  if (!this.unsubscribeHistory) this.connect();
819
853
  this.listeners.add(listener);
820
854
  return () => {
@@ -831,25 +865,27 @@ var ChartController = (_class = class {
831
865
  computeState() {
832
866
  const h = this.history.getState();
833
867
  const sel = this.selection;
834
- 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;
868
+ const seriesId = _optionalChain([sel, 'optionalAccess', _53 => _53.kind]) === "series" || _optionalChain([sel, 'optionalAccess', _54 => _54.kind]) === "point" || _optionalChain([sel, 'optionalAccess', _55 => _55.kind]) === "trendline" ? sel.seriesId : null;
835
869
  return {
836
870
  spec: this.spec,
837
871
  selection: sel,
838
872
  selectedSeries: seriesId ? _nullishCoalesce(this.spec.series.find((s) => s.id === seriesId), () => ( null)) : null,
839
- selectedIndex: _optionalChain([sel, 'optionalAccess', _54 => _54.kind]) === "point" || _optionalChain([sel, 'optionalAccess', _55 => _55.kind]) === "category" ? sel.index : null,
873
+ selectedIndex: _optionalChain([sel, 'optionalAccess', _56 => _56.kind]) === "point" || _optionalChain([sel, 'optionalAccess', _57 => _57.kind]) === "category" ? sel.index : null,
840
874
  issues: this.issues,
841
875
  gesture: this.gestureKey,
842
876
  canUndo: h.canUndo,
843
877
  canRedo: h.canRedo,
844
878
  undoLabel: h.undoName,
845
879
  redoLabel: h.redoName,
880
+ raceFrame: this.raceFrame === null ? null : Math.min(this.raceFrame, Math.max(0, this.spec.categories.length - 1)),
881
+ racePlaying: this.raceStop !== null,
846
882
  revision: this.revision
847
883
  };
848
884
  }
849
885
  notify(specChanged) {
850
886
  this.revision++;
851
887
  this.state = this.computeState();
852
- if (specChanged) _optionalChain([this, 'access', _56 => _56.onChange, 'optionalCall', _57 => _57(this.spec)]);
888
+ if (specChanged) _optionalChain([this, 'access', _58 => _58.onChange, 'optionalCall', _59 => _59(this.spec)]);
853
889
  const state = this.state;
854
890
  this.listeners.forEach((listener) => {
855
891
  try {
@@ -873,7 +909,7 @@ var ChartController = (_class = class {
873
909
  case "category":
874
910
  return sel.index < spec.categories.length ? sel : null;
875
911
  case "trendline":
876
- 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;
912
+ return _optionalChain([spec, 'access', _60 => _60.series, 'access', _61 => _61.find, 'call', _62 => _62((s) => s.id === sel.seriesId), 'optionalAccess', _63 => _63.trendlines, 'optionalAccess', _64 => _64[sel.index]]) ? sel : null;
877
913
  case "title":
878
914
  return spec.title ? sel : null;
879
915
  case "subtitle":
@@ -897,7 +933,7 @@ var ChartController = (_class = class {
897
933
  const hadIssues = this.issues.length > 0;
898
934
  this.issues = [];
899
935
  if (sameChartJson(before, next)) {
900
- const reselect = select !== void 0 && !_chunkQO2T6KA5cjs.sameChartSelection.call(void 0, this.selection, select) && !(select === null && this.selection === null);
936
+ const reselect = select !== void 0 && !_chunkWOIXNDHVcjs.sameChartSelection.call(void 0, this.selection, select) && !(select === null && this.selection === null);
901
937
  if (reselect) this.selection = select;
902
938
  if (reselect || hadIssues) this.notify(false);
903
939
  return;
@@ -920,7 +956,7 @@ var ChartController = (_class = class {
920
956
  }
921
957
  /** A copy of the spec with `edit` applied (series and categories copied as needed). */
922
958
  edited(edit) {
923
- const draft = _chunkUVXTOZ2Bcjs.cloneChartSpec.call(void 0, this.spec);
959
+ const draft = _chunkOUO3DSRTcjs.cloneChartSpec.call(void 0, this.spec);
924
960
  edit(draft);
925
961
  return draft;
926
962
  }
@@ -950,7 +986,7 @@ var ChartController = (_class = class {
950
986
  legend: patch.legend ? { ...s.legend, ...patch.legend } : s.legend,
951
987
  version: 1
952
988
  };
953
- const { spec, issues } = _chunkUVXTOZ2Bcjs.normalizeChartSpec.call(void 0, merged);
989
+ const { spec, issues } = _chunkOUO3DSRTcjs.normalizeChartSpec.call(void 0, merged);
954
990
  if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
955
991
  if (JSON.stringify(spec) === JSON.stringify(s)) return { ok: true };
956
992
  this.commit(_nullishCoalesce(options.label, () => ( updateLabel(patch))), spec);
@@ -1004,7 +1040,7 @@ var ChartController = (_class = class {
1004
1040
  const series = this.getSeries(seriesId);
1005
1041
  if (!series) return this.unknownSeries(seriesId);
1006
1042
  if (!Number.isInteger(index) || index < 0 || index >= this.spec.categories.length) return this.badIndex(index);
1007
- const parsed = _chunkUVXTOZ2Bcjs.parseChartValue.call(void 0, value);
1043
+ const parsed = _chunkOUO3DSRTcjs.parseChartValue.call(void 0, value);
1008
1044
  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.` }]);
1009
1045
  if (series.values[index] === parsed) {
1010
1046
  if (this.issues.length) {
@@ -1029,7 +1065,7 @@ var ChartController = (_class = class {
1029
1065
  if (!this.getSeries(cell.seriesId)) issues.push({ path: cell.seriesId, message: this.unknownSeries(cell.seriesId).message });
1030
1066
  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 });
1031
1067
  else {
1032
- const value = _chunkUVXTOZ2Bcjs.parseChartValue.call(void 0, cell.value);
1068
+ const value = _chunkOUO3DSRTcjs.parseChartValue.call(void 0, cell.value);
1033
1069
  if (value === void 0) issues.push({ path: `${cell.seriesId}[${cell.index}]`, message: `"${String(cell.value)}" is not a number.` });
1034
1070
  else parsed.push({ seriesId: cell.seriesId, index: cell.index, value });
1035
1071
  }
@@ -1043,12 +1079,12 @@ var ChartController = (_class = class {
1043
1079
  }
1044
1080
  /** Adds a series (values padded to the categories) and selects it. Returns its id. */
1045
1081
  addSeries(input = {}, options = {}) {
1046
- const id = input.id && !this.getSeries(input.id) ? input.id : _chunkUVXTOZ2Bcjs.uniqueChartSeriesId.call(void 0, this.spec.series);
1082
+ const id = input.id && !this.getSeries(input.id) ? input.id : _chunkOUO3DSRTcjs.uniqueChartSeriesId.call(void 0, this.spec.series);
1047
1083
  const name = _nullishCoalesce(input.name, () => ( `Series ${this.spec.series.length + 1}`));
1048
1084
  const at = Math.max(0, Math.min(this.spec.series.length, _nullishCoalesce(options.at, () => ( this.spec.series.length))));
1049
1085
  const series = [...this.spec.series];
1050
1086
  series.splice(at, 0, { ...input, id, name, values: _nullishCoalesce(input.values, () => ( [])) });
1051
- const { spec, issues } = _chunkUVXTOZ2Bcjs.normalizeChartSpec.call(void 0, { ...this.spec, series });
1087
+ const { spec, issues } = _chunkOUO3DSRTcjs.normalizeChartSpec.call(void 0, { ...this.spec, series });
1052
1088
  if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1053
1089
  this.commit(`Add series "${name}"`, spec, { kind: "series", seriesId: id });
1054
1090
  return { ok: true, id };
@@ -1068,7 +1104,7 @@ var ChartController = (_class = class {
1068
1104
  updateSeries(id, patch) {
1069
1105
  const series = this.getSeries(id);
1070
1106
  if (!series) return this.unknownSeries(id);
1071
- const next = _chunkUVXTOZ2Bcjs.cloneChartSeries.call(void 0, series);
1107
+ const next = _chunkOUO3DSRTcjs.cloneChartSeries.call(void 0, series);
1072
1108
  if (patch.name !== void 0) next.name = String(patch.name);
1073
1109
  if (patch.color === null || patch.color === "") delete next.color;
1074
1110
  else if (patch.color !== void 0) next.color = patch.color;
@@ -1088,7 +1124,7 @@ var ChartController = (_class = class {
1088
1124
  const series2 = this.spec.series.map((s) => s.id === id ? next : s);
1089
1125
  const renamed = next.name !== series.name && this.spec.highlight.includes(series.name) && !this.spec.categories.includes(series.name);
1090
1126
  const highlight = renamed ? this.spec.highlight.map((h) => h === series.name ? next.name : h) : this.spec.highlight;
1091
- const { spec, issues } = _chunkUVXTOZ2Bcjs.normalizeChartSpec.call(void 0, { ...this.spec, series: series2, highlight });
1127
+ const { spec, issues } = _chunkOUO3DSRTcjs.normalizeChartSpec.call(void 0, { ...this.spec, series: series2, highlight });
1092
1128
  if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1093
1129
  if (JSON.stringify(spec.series) === JSON.stringify(this.spec.series)) return { ok: true };
1094
1130
  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}"`;
@@ -1194,7 +1230,7 @@ var ChartController = (_class = class {
1194
1230
  const width = Math.max(...rows.map((r) => r.length));
1195
1231
  const lastSeries = column + width - 1;
1196
1232
  while (d.series.length <= lastSeries) {
1197
- const id = _chunkUVXTOZ2Bcjs.uniqueChartSeriesId.call(void 0, d.series);
1233
+ const id = _chunkOUO3DSRTcjs.uniqueChartSeriesId.call(void 0, d.series);
1198
1234
  d.series.push({ id, name: `Series ${d.series.length + 1}`, values: d.categories.map(() => null) });
1199
1235
  }
1200
1236
  const lastRow = row + rows.length - 1;
@@ -1208,7 +1244,7 @@ var ChartController = (_class = class {
1208
1244
  const index = row + r;
1209
1245
  if (col < 0) d.categories[index] = cell === null || cell === void 0 ? "" : String(cell).trim();
1210
1246
  else {
1211
- const parsed = _chunkUVXTOZ2Bcjs.parseChartValue.call(void 0, cell);
1247
+ const parsed = _chunkOUO3DSRTcjs.parseChartValue.call(void 0, cell);
1212
1248
  if (parsed === void 0) issues.push({ path: `${d.series[col].id}[${index}]`, message: `"${String(cell)}" is not a number; it was left blank.` });
1213
1249
  d.series[col].values[index] = _nullishCoalesce(parsed, () => ( null));
1214
1250
  }
@@ -1227,14 +1263,14 @@ var ChartController = (_class = class {
1227
1263
  * colours and types are kept by name.
1228
1264
  */
1229
1265
  importTable(rows, options = {}) {
1230
- const data = _chunkUVXTOZ2Bcjs.chartDataFromTable.call(void 0, rows, options);
1266
+ const data = _chunkOUO3DSRTcjs.chartDataFromTable.call(void 0, rows, options);
1231
1267
  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.");
1232
1268
  const byName = new Map(this.spec.series.map((s) => [s.name, s]));
1233
1269
  const series = data.series.map((s) => {
1234
1270
  const old = byName.get(s.name);
1235
- return { ...s, ..._optionalChain([old, 'optionalAccess', _63 => _63.color]) ? { color: old.color } : {}, ..._optionalChain([old, 'optionalAccess', _64 => _64.type]) ? { type: old.type } : {}, ...old ? { id: old.id } : {} };
1271
+ return { ...s, ..._optionalChain([old, 'optionalAccess', _65 => _65.color]) ? { color: old.color } : {}, ..._optionalChain([old, 'optionalAccess', _66 => _66.type]) ? { type: old.type } : {}, ...old ? { id: old.id } : {} };
1236
1272
  });
1237
- const { spec } = _chunkUVXTOZ2Bcjs.normalizeChartSpec.call(void 0, { ...this.spec, categories: data.categories, series, tree: [], links: [] });
1273
+ const { spec } = _chunkOUO3DSRTcjs.normalizeChartSpec.call(void 0, { ...this.spec, categories: data.categories, series, tree: [], links: [] });
1238
1274
  this.commit("Import data", spec);
1239
1275
  if (data.issues.length) {
1240
1276
  this.issues = data.issues;
@@ -1265,7 +1301,7 @@ var ChartController = (_class = class {
1265
1301
  /** Replaces the grouped data (an empty list goes back to the table, keeping the totals as values). One undo step. */
1266
1302
  setTree(tree, options = {}) {
1267
1303
  const issues = [];
1268
- const next = _chunkUVXTOZ2Bcjs.normalizeChartTree.call(void 0, tree, issues);
1304
+ const next = _chunkOUO3DSRTcjs.normalizeChartTree.call(void 0, tree, issues);
1269
1305
  if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1270
1306
  return this.update({ tree: next, links: [] }, { label: _nullishCoalesce(options.label, () => ( (next.length ? "Replace grouped data" : "Ungroup data"))) });
1271
1307
  }
@@ -1275,12 +1311,12 @@ var ChartController = (_class = class {
1275
1311
  */
1276
1312
  setTreeRows(rows, options = {}) {
1277
1313
  const issues = [];
1278
- const next = _chunkUVXTOZ2Bcjs.chartTreeFromRows.call(void 0, rows, issues);
1314
+ const next = _chunkOUO3DSRTcjs.chartTreeFromRows.call(void 0, rows, issues);
1279
1315
  if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1280
1316
  const keepColors = (list, prefix) => {
1281
1317
  for (const n of list) {
1282
- const old = _chunkUVXTOZ2Bcjs.findChartTreeNode.call(void 0, this.spec.tree, [...prefix, n.name]);
1283
- if (_optionalChain([old, 'optionalAccess', _65 => _65.color])) n.color = old.color;
1318
+ const old = _chunkOUO3DSRTcjs.findChartTreeNode.call(void 0, this.spec.tree, [...prefix, n.name]);
1319
+ if (_optionalChain([old, 'optionalAccess', _67 => _67.color])) n.color = old.color;
1284
1320
  if (n.children) keepColors(n.children, [...prefix, n.name]);
1285
1321
  }
1286
1322
  };
@@ -1290,16 +1326,16 @@ var ChartController = (_class = class {
1290
1326
  /** Replaces the data with a table of names and values (group, …, item, value); see `chartTreeFromTable`. */
1291
1327
  importTreeTable(rows, options = {}) {
1292
1328
  const issues = [];
1293
- const next = _chunkUVXTOZ2Bcjs.chartTreeFromTable.call(void 0, rows, options, issues);
1329
+ const next = _chunkOUO3DSRTcjs.chartTreeFromTable.call(void 0, rows, options, issues);
1294
1330
  if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1295
1331
  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".');
1296
1332
  return this.update({ tree: next, links: [] }, { label: "Import grouped data" });
1297
1333
  }
1298
1334
  nodeAt(path) {
1299
- const node = _chunkUVXTOZ2Bcjs.findChartTreeNode.call(void 0, this.spec.tree, path);
1335
+ const node = _chunkOUO3DSRTcjs.findChartTreeNode.call(void 0, this.spec.tree, path);
1300
1336
  if (node) return node;
1301
- const known = path.length > 1 ? _chunkUVXTOZ2Bcjs.findChartTreeNode.call(void 0, this.spec.tree, path.slice(0, -1)) : null;
1302
- const siblings = _nullishCoalesce((path.length > 1 ? _optionalChain([known, 'optionalAccess', _66 => _66.children]) : this.spec.tree), () => ( []));
1337
+ const known = path.length > 1 ? _chunkOUO3DSRTcjs.findChartTreeNode.call(void 0, this.spec.tree, path.slice(0, -1)) : null;
1338
+ const siblings = _nullishCoalesce((path.length > 1 ? _optionalChain([known, 'optionalAccess', _68 => _68.children]) : this.spec.tree), () => ( []));
1303
1339
  return fail(
1304
1340
  `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."}`
1305
1341
  );
@@ -1314,12 +1350,12 @@ var ChartController = (_class = class {
1314
1350
  siblings = group.children;
1315
1351
  }
1316
1352
  const issues = [];
1317
- const [node] = _chunkUVXTOZ2Bcjs.normalizeChartTree.call(void 0, [input], issues, "node");
1353
+ const [node] = _chunkOUO3DSRTcjs.normalizeChartTree.call(void 0, [input], issues, "node");
1318
1354
  if (!node || issues.length) return this.reject(issues.map((i) => i.message).join(" ") || "The node is not valid.", issues);
1319
1355
  if (siblings.some((n) => n.name === node.name)) return this.reject(`"${node.name}" is already there; names under one group must be unique.`);
1320
1356
  const at = Math.max(0, Math.min(siblings.length, _nullishCoalesce(options.at, () => ( siblings.length))));
1321
- const tree = _chunkUVXTOZ2Bcjs.cloneChartTree.call(void 0, this.spec.tree);
1322
- const list = parent.length ? _chunkUVXTOZ2Bcjs.findChartTreeNode.call(void 0, tree, parent).children : tree;
1357
+ const tree = _chunkOUO3DSRTcjs.cloneChartTree.call(void 0, this.spec.tree);
1358
+ const list = parent.length ? _chunkOUO3DSRTcjs.findChartTreeNode.call(void 0, tree, parent).children : tree;
1323
1359
  list.splice(at, 0, node);
1324
1360
  const result = this.update({ tree }, { label: `Add "${node.name}"` });
1325
1361
  if (!result.ok) return result;
@@ -1331,16 +1367,16 @@ var ChartController = (_class = class {
1331
1367
  if ("ok" in node) return node;
1332
1368
  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.`);
1333
1369
  const name = patch.name !== void 0 ? String(patch.name).trim() : node.name;
1334
- const siblings = (path.length > 1 ? _chunkUVXTOZ2Bcjs.findChartTreeNode.call(void 0, this.spec.tree, path.slice(0, -1)).children : this.spec.tree).filter((n) => n !== node);
1370
+ const siblings = (path.length > 1 ? _chunkOUO3DSRTcjs.findChartTreeNode.call(void 0, this.spec.tree, path.slice(0, -1)).children : this.spec.tree).filter((n) => n !== node);
1335
1371
  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.`);
1336
- const tree = _chunkUVXTOZ2Bcjs.cloneChartTree.call(void 0, this.spec.tree);
1337
- const target = _chunkUVXTOZ2Bcjs.findChartTreeNode.call(void 0, tree, path);
1372
+ const tree = _chunkOUO3DSRTcjs.cloneChartTree.call(void 0, this.spec.tree);
1373
+ const target = _chunkOUO3DSRTcjs.findChartTreeNode.call(void 0, tree, path);
1338
1374
  const merged = { ...target, name };
1339
1375
  if (patch.value !== void 0) merged.value = patch.value;
1340
1376
  if (patch.color === null) delete merged.color;
1341
1377
  else if (patch.color !== void 0) merged.color = patch.color;
1342
1378
  const issues = [];
1343
- const [checked] = _chunkUVXTOZ2Bcjs.normalizeChartTree.call(void 0, [merged], issues, "node");
1379
+ const [checked] = _chunkOUO3DSRTcjs.normalizeChartTree.call(void 0, [merged], issues, "node");
1344
1380
  if (!checked || issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1345
1381
  Object.assign(target, checked);
1346
1382
  if (patch.color === null) delete target.color;
@@ -1352,8 +1388,8 @@ var ChartController = (_class = class {
1352
1388
  removeTreeNode(path) {
1353
1389
  const node = this.nodeAt(path);
1354
1390
  if ("ok" in node) return node;
1355
- const tree = _chunkUVXTOZ2Bcjs.cloneChartTree.call(void 0, this.spec.tree);
1356
- const parent = path.length > 1 ? _chunkUVXTOZ2Bcjs.findChartTreeNode.call(void 0, tree, path.slice(0, -1)) : null;
1391
+ const tree = _chunkOUO3DSRTcjs.cloneChartTree.call(void 0, this.spec.tree);
1392
+ const parent = path.length > 1 ? _chunkOUO3DSRTcjs.findChartTreeNode.call(void 0, tree, path.slice(0, -1)) : null;
1357
1393
  const list = parent ? parent.children : tree;
1358
1394
  list.splice(
1359
1395
  list.findIndex((n) => n.name === node.name),
@@ -1374,7 +1410,7 @@ var ChartController = (_class = class {
1374
1410
  */
1375
1411
  setLinks(links, options = {}) {
1376
1412
  const issues = [];
1377
- const next = _chunkUVXTOZ2Bcjs.normalizeChartLinks.call(void 0, links, issues);
1413
+ const next = _chunkOUO3DSRTcjs.normalizeChartLinks.call(void 0, links, issues);
1378
1414
  if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1379
1415
  const used = new Set(next.flatMap((l) => [l.source, l.target]));
1380
1416
  const sankeyNodes = options.nodes ? [...options.nodes] : this.spec.sankeyNodes.filter((n) => used.has(n));
@@ -1382,7 +1418,7 @@ var ChartController = (_class = class {
1382
1418
  }
1383
1419
  /** Replaces the data with flows from a table of source, target and value columns. */
1384
1420
  importLinksTable(rows, options = {}) {
1385
- const raw = _chunkUVXTOZ2Bcjs.chartLinksFromTable.call(void 0, rows, options);
1421
+ const raw = _chunkOUO3DSRTcjs.chartLinksFromTable.call(void 0, rows, options);
1386
1422
  if (!raw.length) return this.reject('There are no flows to import: expected rows of source, target and value, e.g. "Website,Signup,120".');
1387
1423
  return this.setLinks(raw, { label: "Import flows" });
1388
1424
  }
@@ -1392,7 +1428,7 @@ var ChartController = (_class = class {
1392
1428
  }
1393
1429
  /** Adds a flow and returns its index. */
1394
1430
  addLink(link) {
1395
- 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]), () => ( "")))}` });
1431
+ const result = this.setLinks([...this.spec.links, link], { label: `Add flow ${String(_nullishCoalesce(_optionalChain([link, 'optionalAccess', _69 => _69.source]), () => ( "")))} \u2192 ${String(_nullishCoalesce(_optionalChain([link, 'optionalAccess', _70 => _70.target]), () => ( "")))}` });
1396
1432
  if (!result.ok) return result;
1397
1433
  return { ok: true, index: this.spec.links.length - 1 };
1398
1434
  }
@@ -1446,7 +1482,7 @@ var ChartController = (_class = class {
1446
1482
  /** Why a reference on `axis` at `values` cannot be drawn on this chart, or null. */
1447
1483
  referenceProblem(axis, values) {
1448
1484
  const s = this.spec;
1449
- const family = _chunkUVXTOZ2Bcjs.chartFamily.call(void 0, s);
1485
+ const family = _chunkOUO3DSRTcjs.chartFamily.call(void 0, s);
1450
1486
  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.`;
1451
1487
  if (axis === "x" && family !== "xy") return 'axis "x" needs a scatter or bubble chart with numeric x values; use "y" for the value axis.';
1452
1488
  if (axis === "y2" && (family !== "cartesian" || !s.series.some((x) => !x.hidden && x.axis === "secondary")))
@@ -1465,7 +1501,7 @@ var ChartController = (_class = class {
1465
1501
  /** Adds a reference line (a target, floor or average). Returns its index. */
1466
1502
  addReferenceLine(input) {
1467
1503
  const issues = [];
1468
- const line = _chunkUVXTOZ2Bcjs.normalizeChartReferenceLine.call(void 0, input, "referenceLine", issues);
1504
+ const line = _chunkOUO3DSRTcjs.normalizeChartReferenceLine.call(void 0, input, "referenceLine", issues);
1469
1505
  if (!line || issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1470
1506
  const problem = this.referenceProblem(line.axis, [line.value]);
1471
1507
  if (problem) return this.reject(problem);
@@ -1480,7 +1516,7 @@ var ChartController = (_class = class {
1480
1516
  const merged = { ...current, ...patch };
1481
1517
  for (const [k, v] of Object.entries(patch)) if (v === null) delete merged[k];
1482
1518
  const issues = [];
1483
- const line = _chunkUVXTOZ2Bcjs.normalizeChartReferenceLine.call(void 0, merged, "referenceLine", issues);
1519
+ const line = _chunkOUO3DSRTcjs.normalizeChartReferenceLine.call(void 0, merged, "referenceLine", issues);
1484
1520
  if (!line || issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1485
1521
  const problem = this.referenceProblem(line.axis, [line.value]);
1486
1522
  if (problem) return this.reject(problem);
@@ -1495,7 +1531,7 @@ var ChartController = (_class = class {
1495
1531
  /** Adds a reference band (a target range). Returns its index. */
1496
1532
  addReferenceBand(input) {
1497
1533
  const issues = [];
1498
- const band = _chunkUVXTOZ2Bcjs.normalizeChartReferenceBand.call(void 0, input, "referenceBand", issues);
1534
+ const band = _chunkOUO3DSRTcjs.normalizeChartReferenceBand.call(void 0, input, "referenceBand", issues);
1499
1535
  if (!band || issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1500
1536
  const problem = this.referenceProblem(band.axis, [band.from, band.to]);
1501
1537
  if (problem) return this.reject(problem);
@@ -1510,7 +1546,7 @@ var ChartController = (_class = class {
1510
1546
  const merged = { ...current, ...patch };
1511
1547
  for (const [k, v] of Object.entries(patch)) if (v === null) delete merged[k];
1512
1548
  const issues = [];
1513
- const band = _chunkUVXTOZ2Bcjs.normalizeChartReferenceBand.call(void 0, merged, "referenceBand", issues);
1549
+ const band = _chunkOUO3DSRTcjs.normalizeChartReferenceBand.call(void 0, merged, "referenceBand", issues);
1514
1550
  if (!band || issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1515
1551
  const problem = this.referenceProblem(band.axis, [band.from, band.to]);
1516
1552
  if (problem) return this.reject(problem);
@@ -1533,7 +1569,7 @@ var ChartController = (_class = class {
1533
1569
  const series = this.getSeries(seriesId);
1534
1570
  if (!series) return this.unknownSeries(seriesId);
1535
1571
  if (!Number.isInteger(index) || index < 0 || index >= this.spec.categories.length) return this.badIndex(index);
1536
- const family = _chunkUVXTOZ2Bcjs.chartFamily.call(void 0, this.spec);
1572
+ const family = _chunkOUO3DSRTcjs.chartFamily.call(void 0, this.spec);
1537
1573
  const text = label === null ? "" : String(label).trim();
1538
1574
  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.`);
1539
1575
  if (text && (series.values[index] === null || series.values[index] === void 0))
@@ -1555,12 +1591,12 @@ var ChartController = (_class = class {
1555
1591
  addTrendline(seriesId, input) {
1556
1592
  const series = this.getSeries(seriesId);
1557
1593
  if (!series) return this.unknownSeries(seriesId);
1558
- if (!_chunkQO2T6KA5cjs.chartSupportsTrendlines.call(void 0, this.spec.type, this.spec.stacking))
1594
+ if (!_chunkWOIXNDHVcjs.chartSupportsTrendlines.call(void 0, this.spec.type, this.spec.stacking))
1559
1595
  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.`);
1560
1596
  const issues = [];
1561
- const line = _chunkUVXTOZ2Bcjs.normalizeChartTrendline.call(void 0, input, "trendline", issues);
1597
+ const line = _chunkOUO3DSRTcjs.normalizeChartTrendline.call(void 0, input, "trendline", issues);
1562
1598
  if (!line || issues.length) return this.reject(issues.map((i) => i.message).join(" ") || "The trendline is not valid.", issues);
1563
- const index = _nullishCoalesce(_optionalChain([series, 'access', _69 => _69.trendlines, 'optionalAccess', _70 => _70.length]), () => ( 0));
1599
+ const index = _nullishCoalesce(_optionalChain([series, 'access', _71 => _71.trendlines, 'optionalAccess', _72 => _72.length]), () => ( 0));
1564
1600
  const next = this.edited((d) => {
1565
1601
  const s = d.series.find((x) => x.id === seriesId);
1566
1602
  s.trendlines = [..._nullishCoalesce(s.trendlines, () => ( [])), line];
@@ -1572,12 +1608,12 @@ var ChartController = (_class = class {
1572
1608
  updateTrendline(seriesId, index, patch) {
1573
1609
  const series = this.getSeries(seriesId);
1574
1610
  if (!series) return this.unknownSeries(seriesId);
1575
- const current = _optionalChain([series, 'access', _71 => _71.trendlines, 'optionalAccess', _72 => _72[index]]);
1576
- 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"}.`);
1611
+ const current = _optionalChain([series, 'access', _73 => _73.trendlines, 'optionalAccess', _74 => _74[index]]);
1612
+ if (!current) return fail(`"${series.name}" has no trendline ${index}; ${_optionalChain([series, 'access', _75 => _75.trendlines, 'optionalAccess', _76 => _76.length]) ? `expected 0 to ${series.trendlines.length - 1}` : "it has none yet"}.`);
1577
1613
  const issues = [];
1578
1614
  const merged = { ...current, ...patch };
1579
1615
  for (const [k, v] of Object.entries(patch)) if (v === null) delete merged[k];
1580
- const line = _chunkUVXTOZ2Bcjs.normalizeChartTrendline.call(void 0, merged, "trendline", issues);
1616
+ const line = _chunkOUO3DSRTcjs.normalizeChartTrendline.call(void 0, merged, "trendline", issues);
1581
1617
  if (!line || issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1582
1618
  this.commit(
1583
1619
  "Change trendline",
@@ -1590,7 +1626,7 @@ var ChartController = (_class = class {
1590
1626
  removeTrendline(seriesId, index) {
1591
1627
  const series = this.getSeries(seriesId);
1592
1628
  if (!series) return this.unknownSeries(seriesId);
1593
- if (!_optionalChain([series, 'access', _75 => _75.trendlines, 'optionalAccess', _76 => _76[index]])) return fail(`"${series.name}" has no trendline ${index}.`);
1629
+ if (!_optionalChain([series, 'access', _77 => _77.trendlines, 'optionalAccess', _78 => _78[index]])) return fail(`"${series.name}" has no trendline ${index}.`);
1594
1630
  this.commit(
1595
1631
  "Delete trendline",
1596
1632
  this.edited((d) => {
@@ -1605,25 +1641,25 @@ var ChartController = (_class = class {
1605
1641
  trendlinePoints(seriesId) {
1606
1642
  const series = this.getSeries(seriesId);
1607
1643
  if (!series) return [];
1608
- const xy = _chunkUVXTOZ2Bcjs.chartFamily.call(void 0, this.spec) === "xy";
1644
+ const xy = _chunkOUO3DSRTcjs.chartFamily.call(void 0, this.spec) === "xy";
1609
1645
  const out = [];
1610
1646
  series.values.forEach((v, i) => {
1611
- const x = xy ? _nullishCoalesce(_optionalChain([series, 'access', _77 => _77.x, 'optionalAccess', _78 => _78[i]]), () => ( (this.spec.type === "bubble" ? i + 1 : null))) : i + 1;
1647
+ const x = xy ? _nullishCoalesce(_optionalChain([series, 'access', _79 => _79.x, 'optionalAccess', _80 => _80[i]]), () => ( (this.spec.type === "bubble" ? i + 1 : null))) : i + 1;
1612
1648
  if (v !== null && x !== null && Number.isFinite(v) && Number.isFinite(x)) out.push([x, v]);
1613
1649
  });
1614
1650
  return out;
1615
1651
  }
1616
1652
  /** The fitted coefficients, R² and equation of a trendline (null for moving averages or unfittable data). */
1617
1653
  trendlineFit(seriesId, index) {
1618
- const line = _optionalChain([this, 'access', _79 => _79.getSeries, 'call', _80 => _80(seriesId), 'optionalAccess', _81 => _81.trendlines, 'optionalAccess', _82 => _82[index]]);
1654
+ const line = _optionalChain([this, 'access', _81 => _81.getSeries, 'call', _82 => _82(seriesId), 'optionalAccess', _83 => _83.trendlines, 'optionalAccess', _84 => _84[index]]);
1619
1655
  if (!line) return null;
1620
- return _chunkQO2T6KA5cjs.fitChartTrendline.call(void 0, line, this.trendlinePoints(seriesId));
1656
+ return _chunkWOIXNDHVcjs.fitChartTrendline.call(void 0, line, this.trendlinePoints(seriesId));
1621
1657
  }
1622
1658
  /** The moving-average points of a trendline (empty for other kinds). */
1623
1659
  trendlineMovingAverage(seriesId, index) {
1624
- const line = _optionalChain([this, 'access', _83 => _83.getSeries, 'call', _84 => _84(seriesId), 'optionalAccess', _85 => _85.trendlines, 'optionalAccess', _86 => _86[index]]);
1660
+ const line = _optionalChain([this, 'access', _85 => _85.getSeries, 'call', _86 => _86(seriesId), 'optionalAccess', _87 => _87.trendlines, 'optionalAccess', _88 => _88[index]]);
1625
1661
  if (!line || line.type !== "moving-average") return [];
1626
- return _chunkQO2T6KA5cjs.chartMovingAverage.call(void 0, this.trendlinePoints(seriesId), _nullishCoalesce(line.period, () => ( 2)));
1662
+ return _chunkWOIXNDHVcjs.chartMovingAverage.call(void 0, this.trendlinePoints(seriesId), _nullishCoalesce(line.period, () => ( 2)));
1627
1663
  }
1628
1664
  // -------------------------------------------------------------------------
1629
1665
  // Reshaping
@@ -1644,17 +1680,66 @@ var ChartController = (_class = class {
1644
1680
  used.add(id);
1645
1681
  return { id, name, values: s.series.map((x) => _nullishCoalesce(x.values[i], () => ( null))) };
1646
1682
  });
1647
- const { spec } = _chunkUVXTOZ2Bcjs.normalizeChartSpec.call(void 0, { ...s, categories: s.series.map((x) => x.name), series });
1683
+ const { spec } = _chunkOUO3DSRTcjs.normalizeChartSpec.call(void 0, { ...s, categories: s.series.map((x) => x.name), series });
1648
1684
  this.commit("Switch rows and columns", spec, null);
1649
1685
  return { ok: true };
1650
1686
  }
1651
1687
  // -------------------------------------------------------------------------
1652
1688
  // Selection and gestures
1653
1689
  // -------------------------------------------------------------------------
1690
+ /**
1691
+ * Shows a bar race at a moment: a category index, fractional between time points (`null`:
1692
+ * the last one). View state like the selection, so not an undo step. Stops playback.
1693
+ */
1694
+ setRaceFrame(frame) {
1695
+ const n = this.spec.categories.length;
1696
+ if (frame !== null && !(Number.isFinite(frame) && frame >= 0 && frame <= Math.max(0, n - 1)))
1697
+ 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.");
1698
+ this.stopRace();
1699
+ if (frame === this.raceFrame) return { ok: true };
1700
+ this.raceFrame = frame;
1701
+ this.notify(false);
1702
+ return { ok: true };
1703
+ }
1704
+ /**
1705
+ * Plays the bar race from the moment shown (from the start when it is at the end), moving
1706
+ * one time point every `msPerStep` (default 1000) until the last. Not an undo step.
1707
+ */
1708
+ playRace(options = {}) {
1709
+ const last = this.spec.categories.length - 1;
1710
+ if (last < 1) return fail("A race needs at least two time points (categories) to play.");
1711
+ this.stopRace();
1712
+ const per = Math.max(50, _nullishCoalesce(options.msPerStep, () => ( 1e3)));
1713
+ const from = this.raceFrame === null || this.raceFrame >= last ? 0 : this.raceFrame;
1714
+ const start = this.raceTicker.now();
1715
+ const step = () => {
1716
+ const at = Math.min(last, from + (this.raceTicker.now() - start) / per);
1717
+ this.raceFrame = at;
1718
+ if (at >= last) {
1719
+ this.raceStop = null;
1720
+ this.raceFrame = null;
1721
+ } else this.raceStop = this.raceTicker.next(step);
1722
+ this.notify(false);
1723
+ };
1724
+ this.raceFrame = from;
1725
+ this.raceStop = this.raceTicker.next(step);
1726
+ this.notify(false);
1727
+ return { ok: true };
1728
+ }
1729
+ /** Pauses bar race playback where it is. */
1730
+ pauseRace() {
1731
+ if (!this.raceStop) return;
1732
+ this.stopRace();
1733
+ this.notify(false);
1734
+ }
1735
+ stopRace() {
1736
+ _optionalChain([this, 'access', _89 => _89.raceStop, 'optionalCall', _90 => _90()]);
1737
+ this.raceStop = null;
1738
+ }
1654
1739
  /** Selects a chart element (view state; not an undo step). */
1655
1740
  select(selection) {
1656
1741
  const next = this.validSelection(selection, this.spec);
1657
- if (_chunkQO2T6KA5cjs.sameChartSelection.call(void 0, next, this.selection) || next === null && this.selection === null) return;
1742
+ if (_chunkWOIXNDHVcjs.sameChartSelection.call(void 0, next, this.selection) || next === null && this.selection === null) return;
1658
1743
  this.selection = next;
1659
1744
  this.notify(false);
1660
1745
  }
@@ -1731,14 +1816,14 @@ var ChartController = (_class = class {
1731
1816
  // -------------------------------------------------------------------------
1732
1817
  /** The spec, for saving (a copy). */
1733
1818
  toJSON() {
1734
- return _chunkUVXTOZ2Bcjs.cloneChartSpec.call(void 0, this.spec);
1819
+ return _chunkOUO3DSRTcjs.cloneChartSpec.call(void 0, this.spec);
1735
1820
  }
1736
1821
  /**
1737
1822
  * Replaces the chart without an undo step (e.g. when opening a document). Problems are
1738
1823
  * fixed with defaults and reported in `state.issues` (and returned).
1739
1824
  */
1740
1825
  load(input, options = {}) {
1741
- const { spec, issues } = _chunkUVXTOZ2Bcjs.normalizeChartSpec.call(void 0, input);
1826
+ const { spec, issues } = _chunkOUO3DSRTcjs.normalizeChartSpec.call(void 0, input);
1742
1827
  this.spec = spec;
1743
1828
  this.issues = issues;
1744
1829
  this.selection = this.validSelection(this.selection, spec);
@@ -1758,7 +1843,7 @@ var ChartController = (_class = class {
1758
1843
  * nothing changes and every problem is returned (and shown in `state.issues`).
1759
1844
  */
1760
1845
  replace(input, options = {}) {
1761
- const { spec, issues } = _chunkUVXTOZ2Bcjs.normalizeChartSpec.call(void 0, input);
1846
+ const { spec, issues } = _chunkOUO3DSRTcjs.normalizeChartSpec.call(void 0, input);
1762
1847
  if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1763
1848
  this.commit(_nullishCoalesce(options.label, () => ( "Replace chart")), spec, this.validSelection(this.selection, spec));
1764
1849
  return { ok: true };
@@ -1773,7 +1858,8 @@ var ChartController = (_class = class {
1773
1858
  }
1774
1859
  /** Stops listening to the history (reconnected by the next `subscribe`). */
1775
1860
  destroy() {
1776
- _optionalChain([this, 'access', _87 => _87.unsubscribeHistory, 'optionalCall', _88 => _88()]);
1861
+ this.stopRace();
1862
+ _optionalChain([this, 'access', _91 => _91.unsubscribeHistory, 'optionalCall', _92 => _92()]);
1777
1863
  this.unsubscribeHistory = void 0;
1778
1864
  this.listeners.clear();
1779
1865
  }
@@ -1808,6 +1894,10 @@ function updateLabel(patch) {
1808
1894
  parliamentArc: "Change hemicycle sweep",
1809
1895
  parliamentMajority: "Change majority",
1810
1896
  parliamentLabel: "Edit seat caption",
1897
+ raceTopN: "Change bars shown",
1898
+ map: "Change map",
1899
+ mapSteps: "Change colour classes",
1900
+ mapThresholds: "Change class breaks",
1811
1901
  sunburstLabel: "Edit centre caption",
1812
1902
  tree: "Replace grouped data",
1813
1903
  links: "Replace flows",
@@ -1835,7 +1925,7 @@ function layoutSparkline(values, options) {
1835
1925
  const h = Number.isFinite(options.height) ? Math.max(1, options.height) : 1;
1836
1926
  const color = _nullishCoalesce(options.color, () => ( "#4269d0"));
1837
1927
  const negative = _nullishCoalesce(options.negativeColor, () => ( "#e5484d"));
1838
- const theme = { ..._chunkUVXTOZ2Bcjs.DEFAULT_CHART_THEME, background: "transparent" };
1928
+ const theme = { ..._chunkOUO3DSRTcjs.DEFAULT_CHART_THEME, background: "transparent" };
1839
1929
  const marks = [];
1840
1930
  const scene = { width: w, height: h, plot: { x: 0, y: 0, width: w, height: h }, marks, percent: false, theme, warnings: [] };
1841
1931
  const vals = values.slice(0, MAX_POINTS).map((v) => v !== null && Number.isFinite(v) ? Math.max(-1e300, Math.min(1e300, v)) : null);
@@ -1868,7 +1958,7 @@ function layoutSparkline(values, options) {
1868
1958
  const flush = () => {
1869
1959
  if (run.length >= 2) {
1870
1960
  const pts = run.length > 4e3 ? run.filter((_, i) => i % (Math.floor(run.length / 2e3) + 1) === 0) : run;
1871
- d += pts.map(([x, y], i) => `${i ? "L" : "M"}${_chunkQO2T6KA5cjs.r2.call(void 0, x)},${_chunkQO2T6KA5cjs.r2.call(void 0, y)}`).join("");
1961
+ d += pts.map(([x, y], i) => `${i ? "L" : "M"}${_chunkWOIXNDHVcjs.r2.call(void 0, x)},${_chunkWOIXNDHVcjs.r2.call(void 0, y)}`).join("");
1872
1962
  }
1873
1963
  run = [];
1874
1964
  };