@pixerate/editor 0.156.0 → 0.157.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 (34) hide show
  1. package/dist/agent/index.cjs +34 -34
  2. package/dist/agent/index.js +5 -5
  3. package/dist/canvas/index.cjs +6 -6
  4. package/dist/canvas/index.js +2 -2
  5. package/dist/chart/index.cjs +90 -88
  6. package/dist/chart/index.js +9 -7
  7. package/dist/chart/spec.d.cts +2 -1
  8. package/dist/chart/spec.d.ts +2 -1
  9. package/dist/chart/types.d.cts +5 -0
  10. package/dist/chart/types.d.ts +5 -0
  11. package/dist/{chunk-2WDZI6QD.cjs → chunk-4T44CJ5K.cjs} +15 -15
  12. package/dist/{chunk-XTU6QO2W.cjs → chunk-4YWAEV4W.cjs} +36 -27
  13. package/dist/{chunk-4YQKRHMI.cjs → chunk-57JLBGJ5.cjs} +8 -8
  14. package/dist/{chunk-SVINJIGK.js → chunk-5QBRAIVK.js} +3 -3
  15. package/dist/{chunk-R3PECGTQ.cjs → chunk-6LUYFHHN.cjs} +51 -51
  16. package/dist/{chunk-ML2II3Y3.cjs → chunk-AKDWAWSY.cjs} +58 -46
  17. package/dist/{chunk-EQ4SF4X4.js → chunk-DBIVICAO.js} +1 -1
  18. package/dist/{chunk-SUVZJ2CP.js → chunk-H5XX4KHB.js} +11 -1
  19. package/dist/{chunk-37RLSNQ3.js → chunk-Q6PA362P.js} +2 -2
  20. package/dist/{chunk-DSZCDNTM.js → chunk-R3QY7PPL.js} +11 -2
  21. package/dist/{chunk-4RF2H3N3.js → chunk-SSCL7QQ4.js} +15 -3
  22. package/dist/{chunk-TLMRGLQQ.cjs → chunk-TVO6W2Q6.cjs} +20 -17
  23. package/dist/{chunk-EIUTJPEL.js → chunk-UM3RPYC5.js} +5 -2
  24. package/dist/{chunk-I4AHLP7F.cjs → chunk-WPPJH6X4.cjs} +12 -2
  25. package/dist/{chunk-RZJCYJWO.cjs → chunk-XNQ5EFB4.cjs} +16 -16
  26. package/dist/{chunk-R6HNWN7B.js → chunk-YABNLNY7.js} +3 -3
  27. package/dist/export/index.cjs +4 -4
  28. package/dist/export/index.js +3 -3
  29. package/dist/extensions/index.cjs +7 -7
  30. package/dist/extensions/index.js +6 -6
  31. package/dist/index.cjs +13 -13
  32. package/dist/index.js +7 -7
  33. package/package.json +1 -1
  34. package/skills/pixerate-chart/SKILL.md +4 -1
@@ -7,7 +7,7 @@
7
7
 
8
8
 
9
9
 
10
- var _chunkXTU6QO2Wcjs = require('./chunk-XTU6QO2W.cjs');
10
+ var _chunk4YWAEV4Wcjs = require('./chunk-4YWAEV4W.cjs');
11
11
 
12
12
 
13
13
 
@@ -27,7 +27,7 @@ var _chunkXTU6QO2Wcjs = require('./chunk-XTU6QO2W.cjs');
27
27
 
28
28
 
29
29
 
30
- var _chunkI4AHLP7Fcjs = require('./chunk-I4AHLP7F.cjs');
30
+ var _chunkWPPJH6X4cjs = require('./chunk-WPPJH6X4.cjs');
31
31
 
32
32
 
33
33
 
@@ -63,7 +63,7 @@ function splitOutside(text, sep) {
63
63
  return out;
64
64
  }
65
65
  function chartMermaidFamily(spec) {
66
- const family = _chunkI4AHLP7Fcjs.chartFamily.call(void 0, spec);
66
+ const family = _chunkWPPJH6X4cjs.chartFamily.call(void 0, spec);
67
67
  if (family === "pie" || family === "funnel" || family === "treemap") return "pie";
68
68
  if (family === "radar") return "radar";
69
69
  return "xychart";
@@ -126,6 +126,8 @@ function chartToMermaid(spec, options = {}) {
126
126
  }
127
127
  if (spec.yAxis.max !== null) lines.push(`${ind}max ${num(spec.yAxis.max)}`);
128
128
  if (spec.yAxis.min !== null) lines.push(`${ind}min ${num(spec.yAxis.min)}`);
129
+ if (spec.radarTicks !== null) lines.push(`${ind}ticks ${spec.radarTicks}`);
130
+ if (spec.radarGraticule === "polygon") lines.push(`${ind}graticule polygon`);
129
131
  if (!spec.legend.show) lines.push(`${ind}showLegend false`);
130
132
  } else {
131
133
  lines.push(`xychart-beta${spec.orientation === "horizontal" ? " horizontal" : ""}`);
@@ -225,11 +227,13 @@ function chartFromMermaid(text, options = {}) {
225
227
  let title = _nullishCoalesce(frontTitle, () => ( ""));
226
228
  const categories = [];
227
229
  const series = [];
228
- const xAxis = _chunkI4AHLP7Fcjs.defaultChartAxis.call(void 0, false);
229
- const yAxis = _chunkI4AHLP7Fcjs.defaultChartAxis.call(void 0, true);
230
+ const xAxis = _chunkWPPJH6X4cjs.defaultChartAxis.call(void 0, false);
231
+ const yAxis = _chunkWPPJH6X4cjs.defaultChartAxis.call(void 0, true);
230
232
  const radarAxes = [];
231
233
  const pieSlices = [];
232
234
  let legendShow = true;
235
+ let radarTicks = null;
236
+ let graticule = "circle";
233
237
  const counts = { bar: 0, line: 0 };
234
238
  const lineIssue = (i, message) => issues.push({ path: `line ${i + 1}`, line: i + 1, message: `Line ${i + 1}: ${message}` });
235
239
  for (let i = headerLine + 1; family && i < all.length; i++) {
@@ -337,6 +341,12 @@ function chartFromMermaid(text, options = {}) {
337
341
  if (m[1] === "max") yAxis.max = Number(m[2]);
338
342
  else if (m[1] === "min") yAxis.min = Number(m[2]);
339
343
  else if (m[1] === "showLegend") legendShow = m[2] !== "false";
344
+ else if (m[1] === "ticks") {
345
+ const n = Number(m[2]);
346
+ if (Number.isFinite(n) && n >= 1) radarTicks = Math.min(50, Math.round(n));
347
+ else lineIssue(i, `expected ticks to be a number of rings (1 or more), got "${m[2]}".`);
348
+ } else if (m[2] === "circle" || m[2] === "polygon") graticule = m[2];
349
+ else lineIssue(i, `expected graticule circle or polygon, got "${m[2]}".`);
340
350
  continue;
341
351
  }
342
352
  }
@@ -352,7 +362,7 @@ function chartFromMermaid(text, options = {}) {
352
362
  series: [{ id: "series-1", name: title || "Values", values: pieSlices.map((s) => s.value) }]
353
363
  };
354
364
  } else if (family === "radar") {
355
- input = { type: "radar", title, categories: radarAxes.map((a) => a.label), series, yAxis, legend: { show: legendShow, position: "bottom" } };
365
+ input = { type: "radar", title, categories: radarAxes.map((a) => a.label), series, yAxis, legend: { show: legendShow, position: "bottom" }, radarTicks, radarGraticule: graticule };
356
366
  } else {
357
367
  const allBar = series.length > 0 && series.every((s) => s.type === "bar");
358
368
  const allLine = series.length > 0 && series.every((s) => s.type === "line");
@@ -378,7 +388,7 @@ function chartFromMermaid(text, options = {}) {
378
388
  input.series = metaSeries.map((extra, i) => ({ ..._nullishCoalesce(base[i], () => ( {})), ..._nullishCoalesce(extra, () => ( {})) }));
379
389
  }
380
390
  }
381
- const { spec, issues: specIssues } = _chunkI4AHLP7Fcjs.normalizeChartSpec.call(void 0, input);
391
+ const { spec, issues: specIssues } = _chunkWPPJH6X4cjs.normalizeChartSpec.call(void 0, input);
382
392
  if (!family && !partial && !issues.length) issues.push({ path: "header", message: "The text is empty: expected a chart header (xychart-beta, pie or radar-beta)." });
383
393
  return { spec, issues: [...issues, ...specIssues], family, hasMeta: !!meta };
384
394
  }
@@ -417,11 +427,11 @@ function findMermaidCharts(text) {
417
427
  }
418
428
 
419
429
  // src/chart/summary.ts
420
- function summarizeChart(spec, size = { width: 640, height: 400 }, scene = _chunkXTU6QO2Wcjs.layoutChart.call(void 0, spec, { ...size, selection: null })) {
430
+ function summarizeChart(spec, size = { width: 640, height: 400 }, scene = _chunk4YWAEV4Wcjs.layoutChart.call(void 0, spec, { ...size, selection: null })) {
421
431
  const visible = spec.series.filter((s) => !s.hidden);
422
- const series = visible.map((s) => _chunkXTU6QO2Wcjs.summarizeChartSeries.call(void 0, s, spec.categories));
423
- const colors = _chunkI4AHLP7Fcjs.chartColorsByCategory.call(void 0, spec.type) ? spec.categories.map((_, i) => _optionalChain([visible, 'access', _10 => _10[0], 'optionalAccess', _11 => _11.pointColors, 'optionalAccess', _12 => _12[i]]) || _chunkI4AHLP7Fcjs.chartSliceColor.call(void 0, spec, i)) : visible.map((s) => _chunkI4AHLP7Fcjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(s)));
424
- const check = _chunkI4AHLP7Fcjs.checkChartColors.call(void 0, colors, { surface: scene.theme.surface.startsWith("var(") ? "#ffffff" : scene.theme.surface });
432
+ const series = visible.map((s) => _chunk4YWAEV4Wcjs.summarizeChartSeries.call(void 0, s, spec.categories));
433
+ const colors = _chunkWPPJH6X4cjs.chartColorsByCategory.call(void 0, spec.type) ? spec.categories.map((_, i) => _optionalChain([visible, 'access', _10 => _10[0], 'optionalAccess', _11 => _11.pointColors, 'optionalAccess', _12 => _12[i]]) || _chunkWPPJH6X4cjs.chartSliceColor.call(void 0, spec, i)) : visible.map((s) => _chunkWPPJH6X4cjs.chartSeriesColor.call(void 0, spec, spec.series.indexOf(s)));
434
+ const check = _chunkWPPJH6X4cjs.checkChartColors.call(void 0, colors, { surface: scene.theme.surface.startsWith("var(") ? "#ffffff" : scene.theme.surface });
425
435
  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;
426
436
  return {
427
437
  type: spec.type,
@@ -436,12 +446,12 @@ function summarizeChart(spec, size = { width: 640, height: 400 }, scene = _chunk
436
446
  description: describeChart(spec, series)
437
447
  };
438
448
  }
439
- function describeChart(spec, series = spec.series.filter((s) => !s.hidden).map((s) => _chunkXTU6QO2Wcjs.summarizeChartSeries.call(void 0, s, spec.categories))) {
440
- const kind = _chunkI4AHLP7Fcjs.CHART_TYPE_LABELS[spec.type].toLowerCase();
449
+ function describeChart(spec, series = spec.series.filter((s) => !s.hidden).map((s) => _chunk4YWAEV4Wcjs.summarizeChartSeries.call(void 0, s, spec.categories))) {
450
+ const kind = _chunkWPPJH6X4cjs.CHART_TYPE_LABELS[spec.type].toLowerCase();
441
451
  const parts = [];
442
- const family = _chunkI4AHLP7Fcjs.chartFamily.call(void 0, spec);
452
+ const family = _chunkWPPJH6X4cjs.chartFamily.call(void 0, spec);
443
453
  const format = spec.yAxis.format;
444
- const fmt = (v) => v === null ? "blank" : _chunkXTU6QO2Wcjs.formatChartNumber.call(void 0, v, format);
454
+ const fmt = (v) => v === null ? "blank" : _chunk4YWAEV4Wcjs.formatChartNumber.call(void 0, v, format);
445
455
  const head = spec.title ? `${spec.title}: a ${kind} chart` : `A ${kind} chart`;
446
456
  if (!series.length || series.every((s) => s.count === 0)) return `${head} with no data.`;
447
457
  if (family === "pie" || family === "funnel" || family === "treemap") {
@@ -489,7 +499,7 @@ function describeChart(spec, series = spec.series.filter((s) => !s.hidden).map((
489
499
  }
490
500
  parts.push(...axes);
491
501
  for (const s of spec.series.filter((x) => !x.hidden && (x.errorBars || x.xErrorBars)).slice(0, 8)) {
492
- const bars = [s.errorBars ? _chunkI4AHLP7Fcjs.describeChartErrorBars.call(void 0, s.errorBars) : "", s.xErrorBars ? `x ${_chunkI4AHLP7Fcjs.describeChartErrorBars.call(void 0, s.xErrorBars)}` : ""].filter(Boolean).join(" and ");
502
+ const bars = [s.errorBars ? _chunkWPPJH6X4cjs.describeChartErrorBars.call(void 0, s.errorBars) : "", s.xErrorBars ? `x ${_chunkWPPJH6X4cjs.describeChartErrorBars.call(void 0, s.xErrorBars)}` : ""].filter(Boolean).join(" and ");
493
503
  parts.push(`${s.name} has ${bars}.`);
494
504
  }
495
505
  return parts.join(" ");
@@ -554,7 +564,7 @@ function chartSceneToSvg(scene, options = {}) {
554
564
  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>`;
555
565
  }
556
566
  function chartToSvg(spec, options) {
557
- const scene = _chunkXTU6QO2Wcjs.layoutChart.call(void 0, spec, { ...options, selection: null });
567
+ const scene = _chunk4YWAEV4Wcjs.layoutChart.call(void 0, spec, { ...options, selection: null });
558
568
  return chartSceneToSvg(scene, { ...options, ariaLabel: _nullishCoalesce(options.ariaLabel, () => ( (spec.title || void 0))), description: _nullishCoalesce(options.description, () => ( describeChart(spec))) });
559
569
  }
560
570
  var SVG_NS = "http://www.w3.org/2000/svg";
@@ -592,10 +602,10 @@ var CHART_LAYOUT_PRESETS = [
592
602
  ];
593
603
  function monochromeChartPalette(base, count = 6) {
594
604
  const steps = count <= 1 ? [0] : Array.from({ length: count }, (_, i) => -0.45 + 1.05 * i / (count - 1));
595
- return steps.map((t) => _chunkI4AHLP7Fcjs.shadeChartColor.call(void 0, base, t));
605
+ return steps.map((t) => _chunkWPPJH6X4cjs.shadeChartColor.call(void 0, base, t));
596
606
  }
597
607
  var CHART_COLOR_SCHEMES = [
598
- { id: "default", label: "Default", description: "Ten distinct colours, readable on light and dark backgrounds.", palette: _chunkI4AHLP7Fcjs.DEFAULT_CHART_PALETTE },
608
+ { id: "default", label: "Default", description: "Ten distinct colours, readable on light and dark backgrounds.", palette: _chunkWPPJH6X4cjs.DEFAULT_CHART_PALETTE },
599
609
  { 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"] },
600
610
  { id: "office", label: "Office", description: "The six accent colours of the default Office theme.", palette: ["#4472c4", "#ed7d31", "#a5a5a5", "#ffc000", "#5b9bd5", "#70ad47"] },
601
611
  { id: "warm", label: "Warm", description: "Reds, oranges and yellows.", palette: ["#b2182b", "#d6604d", "#f4a582", "#e08214", "#fdb863", "#8c510a"] },
@@ -654,7 +664,7 @@ var ChartController = (_class = class {
654
664
  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);
655
665
  this.history = _nullishCoalesce(options.history, () => ( new (0, _chunkFJ2MSI43cjs.HistoryManager)()));
656
666
  this.onChange = options.onChange;
657
- const { spec, issues } = _chunkI4AHLP7Fcjs.normalizeChartSpec.call(void 0, _nullishCoalesce(options.spec, () => ( {})));
667
+ const { spec, issues } = _chunkWPPJH6X4cjs.normalizeChartSpec.call(void 0, _nullishCoalesce(options.spec, () => ( {})));
658
668
  this.spec = spec;
659
669
  this.issues = issues;
660
670
  this.state = this.computeState();
@@ -757,7 +767,7 @@ var ChartController = (_class = class {
757
767
  const hadIssues = this.issues.length > 0;
758
768
  this.issues = [];
759
769
  if (sameChartJson(before, next)) {
760
- const reselect = select !== void 0 && !_chunkXTU6QO2Wcjs.sameChartSelection.call(void 0, this.selection, select) && !(select === null && this.selection === null);
770
+ const reselect = select !== void 0 && !_chunk4YWAEV4Wcjs.sameChartSelection.call(void 0, this.selection, select) && !(select === null && this.selection === null);
761
771
  if (reselect) this.selection = select;
762
772
  if (reselect || hadIssues) this.notify(false);
763
773
  return;
@@ -780,7 +790,7 @@ var ChartController = (_class = class {
780
790
  }
781
791
  /** A copy of the spec with `edit` applied (series and categories copied as needed). */
782
792
  edited(edit) {
783
- const draft = _chunkI4AHLP7Fcjs.cloneChartSpec.call(void 0, this.spec);
793
+ const draft = _chunkWPPJH6X4cjs.cloneChartSpec.call(void 0, this.spec);
784
794
  edit(draft);
785
795
  return draft;
786
796
  }
@@ -810,7 +820,7 @@ var ChartController = (_class = class {
810
820
  legend: patch.legend ? { ...s.legend, ...patch.legend } : s.legend,
811
821
  version: 1
812
822
  };
813
- const { spec, issues } = _chunkI4AHLP7Fcjs.normalizeChartSpec.call(void 0, merged);
823
+ const { spec, issues } = _chunkWPPJH6X4cjs.normalizeChartSpec.call(void 0, merged);
814
824
  if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
815
825
  if (JSON.stringify(spec) === JSON.stringify(s)) return { ok: true };
816
826
  this.commit(_nullishCoalesce(options.label, () => ( updateLabel(patch))), spec);
@@ -861,7 +871,7 @@ var ChartController = (_class = class {
861
871
  const series = this.getSeries(seriesId);
862
872
  if (!series) return this.unknownSeries(seriesId);
863
873
  if (!Number.isInteger(index) || index < 0 || index >= this.spec.categories.length) return this.badIndex(index);
864
- const parsed = _chunkI4AHLP7Fcjs.parseChartValue.call(void 0, value);
874
+ const parsed = _chunkWPPJH6X4cjs.parseChartValue.call(void 0, value);
865
875
  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.` }]);
866
876
  if (series.values[index] === parsed) {
867
877
  if (this.issues.length) {
@@ -884,7 +894,7 @@ var ChartController = (_class = class {
884
894
  if (!this.getSeries(cell.seriesId)) issues.push({ path: cell.seriesId, message: this.unknownSeries(cell.seriesId).message });
885
895
  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 });
886
896
  else {
887
- const value = _chunkI4AHLP7Fcjs.parseChartValue.call(void 0, cell.value);
897
+ const value = _chunkWPPJH6X4cjs.parseChartValue.call(void 0, cell.value);
888
898
  if (value === void 0) issues.push({ path: `${cell.seriesId}[${cell.index}]`, message: `"${String(cell.value)}" is not a number.` });
889
899
  else parsed.push({ seriesId: cell.seriesId, index: cell.index, value });
890
900
  }
@@ -898,12 +908,12 @@ var ChartController = (_class = class {
898
908
  }
899
909
  /** Adds a series (values padded to the categories) and selects it. Returns its id. */
900
910
  addSeries(input = {}, options = {}) {
901
- const id = input.id && !this.getSeries(input.id) ? input.id : _chunkI4AHLP7Fcjs.uniqueChartSeriesId.call(void 0, this.spec.series);
911
+ const id = input.id && !this.getSeries(input.id) ? input.id : _chunkWPPJH6X4cjs.uniqueChartSeriesId.call(void 0, this.spec.series);
902
912
  const name = _nullishCoalesce(input.name, () => ( `Series ${this.spec.series.length + 1}`));
903
913
  const at = Math.max(0, Math.min(this.spec.series.length, _nullishCoalesce(options.at, () => ( this.spec.series.length))));
904
914
  const series = [...this.spec.series];
905
915
  series.splice(at, 0, { ...input, id, name, values: _nullishCoalesce(input.values, () => ( [])) });
906
- const { spec, issues } = _chunkI4AHLP7Fcjs.normalizeChartSpec.call(void 0, { ...this.spec, series });
916
+ const { spec, issues } = _chunkWPPJH6X4cjs.normalizeChartSpec.call(void 0, { ...this.spec, series });
907
917
  if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
908
918
  this.commit(`Add series "${name}"`, spec, { kind: "series", seriesId: id });
909
919
  return { ok: true, id };
@@ -922,7 +932,7 @@ var ChartController = (_class = class {
922
932
  updateSeries(id, patch) {
923
933
  const series = this.getSeries(id);
924
934
  if (!series) return this.unknownSeries(id);
925
- const next = _chunkI4AHLP7Fcjs.cloneChartSeries.call(void 0, series);
935
+ const next = _chunkWPPJH6X4cjs.cloneChartSeries.call(void 0, series);
926
936
  if (patch.name !== void 0) next.name = String(patch.name);
927
937
  if (patch.color === null || patch.color === "") delete next.color;
928
938
  else if (patch.color !== void 0) next.color = patch.color;
@@ -940,7 +950,7 @@ var ChartController = (_class = class {
940
950
  }
941
951
  if (next.axis === "primary") delete next.axis;
942
952
  const series2 = this.spec.series.map((s) => s.id === id ? next : s);
943
- const { spec, issues } = _chunkI4AHLP7Fcjs.normalizeChartSpec.call(void 0, { ...this.spec, series: series2 });
953
+ const { spec, issues } = _chunkWPPJH6X4cjs.normalizeChartSpec.call(void 0, { ...this.spec, series: series2 });
944
954
  if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
945
955
  if (JSON.stringify(spec.series) === JSON.stringify(this.spec.series)) return { ok: true };
946
956
  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}"`;
@@ -1033,7 +1043,7 @@ var ChartController = (_class = class {
1033
1043
  const width = Math.max(...rows.map((r) => r.length));
1034
1044
  const lastSeries = column + width - 1;
1035
1045
  while (d.series.length <= lastSeries) {
1036
- const id = _chunkI4AHLP7Fcjs.uniqueChartSeriesId.call(void 0, d.series);
1046
+ const id = _chunkWPPJH6X4cjs.uniqueChartSeriesId.call(void 0, d.series);
1037
1047
  d.series.push({ id, name: `Series ${d.series.length + 1}`, values: d.categories.map(() => null) });
1038
1048
  }
1039
1049
  const lastRow = row + rows.length - 1;
@@ -1047,7 +1057,7 @@ var ChartController = (_class = class {
1047
1057
  const index = row + r;
1048
1058
  if (col < 0) d.categories[index] = cell === null || cell === void 0 ? "" : String(cell).trim();
1049
1059
  else {
1050
- const parsed = _chunkI4AHLP7Fcjs.parseChartValue.call(void 0, cell);
1060
+ const parsed = _chunkWPPJH6X4cjs.parseChartValue.call(void 0, cell);
1051
1061
  if (parsed === void 0) issues.push({ path: `${d.series[col].id}[${index}]`, message: `"${String(cell)}" is not a number; it was left blank.` });
1052
1062
  d.series[col].values[index] = _nullishCoalesce(parsed, () => ( null));
1053
1063
  }
@@ -1066,14 +1076,14 @@ var ChartController = (_class = class {
1066
1076
  * colours and types are kept by name.
1067
1077
  */
1068
1078
  importTable(rows, options = {}) {
1069
- const data = _chunkI4AHLP7Fcjs.chartDataFromTable.call(void 0, rows, options);
1079
+ const data = _chunkWPPJH6X4cjs.chartDataFromTable.call(void 0, rows, options);
1070
1080
  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.");
1071
1081
  const byName = new Map(this.spec.series.map((s) => [s.name, s]));
1072
1082
  const series = data.series.map((s) => {
1073
1083
  const old = byName.get(s.name);
1074
1084
  return { ...s, ..._optionalChain([old, 'optionalAccess', _27 => _27.color]) ? { color: old.color } : {}, ..._optionalChain([old, 'optionalAccess', _28 => _28.type]) ? { type: old.type } : {}, ...old ? { id: old.id } : {} };
1075
1085
  });
1076
- const { spec } = _chunkI4AHLP7Fcjs.normalizeChartSpec.call(void 0, { ...this.spec, categories: data.categories, series });
1086
+ const { spec } = _chunkWPPJH6X4cjs.normalizeChartSpec.call(void 0, { ...this.spec, categories: data.categories, series });
1077
1087
  this.commit("Import data", spec);
1078
1088
  if (data.issues.length) {
1079
1089
  this.issues = data.issues;
@@ -1094,10 +1104,10 @@ var ChartController = (_class = class {
1094
1104
  addTrendline(seriesId, input) {
1095
1105
  const series = this.getSeries(seriesId);
1096
1106
  if (!series) return this.unknownSeries(seriesId);
1097
- if (!_chunkXTU6QO2Wcjs.chartSupportsTrendlines.call(void 0, this.spec.type, this.spec.stacking))
1107
+ if (!_chunk4YWAEV4Wcjs.chartSupportsTrendlines.call(void 0, this.spec.type, this.spec.stacking))
1098
1108
  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.`);
1099
1109
  const issues = [];
1100
- const line = _chunkI4AHLP7Fcjs.normalizeChartTrendline.call(void 0, input, "trendline", issues);
1110
+ const line = _chunkWPPJH6X4cjs.normalizeChartTrendline.call(void 0, input, "trendline", issues);
1101
1111
  if (!line || issues.length) return this.reject(issues.map((i) => i.message).join(" ") || "The trendline is not valid.", issues);
1102
1112
  const index = _nullishCoalesce(_optionalChain([series, 'access', _29 => _29.trendlines, 'optionalAccess', _30 => _30.length]), () => ( 0));
1103
1113
  const next = this.edited((d) => {
@@ -1116,7 +1126,7 @@ var ChartController = (_class = class {
1116
1126
  const issues = [];
1117
1127
  const merged = { ...current, ...patch };
1118
1128
  for (const [k, v] of Object.entries(patch)) if (v === null) delete merged[k];
1119
- const line = _chunkI4AHLP7Fcjs.normalizeChartTrendline.call(void 0, merged, "trendline", issues);
1129
+ const line = _chunkWPPJH6X4cjs.normalizeChartTrendline.call(void 0, merged, "trendline", issues);
1120
1130
  if (!line || issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1121
1131
  this.commit(
1122
1132
  "Change trendline",
@@ -1144,7 +1154,7 @@ var ChartController = (_class = class {
1144
1154
  trendlinePoints(seriesId) {
1145
1155
  const series = this.getSeries(seriesId);
1146
1156
  if (!series) return [];
1147
- const xy = _chunkI4AHLP7Fcjs.chartFamily.call(void 0, this.spec) === "xy";
1157
+ const xy = _chunkWPPJH6X4cjs.chartFamily.call(void 0, this.spec) === "xy";
1148
1158
  const out = [];
1149
1159
  series.values.forEach((v, i) => {
1150
1160
  const x = xy ? _nullishCoalesce(_optionalChain([series, 'access', _37 => _37.x, 'optionalAccess', _38 => _38[i]]), () => ( (this.spec.type === "bubble" ? i + 1 : null))) : i + 1;
@@ -1156,13 +1166,13 @@ var ChartController = (_class = class {
1156
1166
  trendlineFit(seriesId, index) {
1157
1167
  const line = _optionalChain([this, 'access', _39 => _39.getSeries, 'call', _40 => _40(seriesId), 'optionalAccess', _41 => _41.trendlines, 'optionalAccess', _42 => _42[index]]);
1158
1168
  if (!line) return null;
1159
- return _chunkXTU6QO2Wcjs.fitChartTrendline.call(void 0, line, this.trendlinePoints(seriesId));
1169
+ return _chunk4YWAEV4Wcjs.fitChartTrendline.call(void 0, line, this.trendlinePoints(seriesId));
1160
1170
  }
1161
1171
  /** The moving-average points of a trendline (empty for other kinds). */
1162
1172
  trendlineMovingAverage(seriesId, index) {
1163
1173
  const line = _optionalChain([this, 'access', _43 => _43.getSeries, 'call', _44 => _44(seriesId), 'optionalAccess', _45 => _45.trendlines, 'optionalAccess', _46 => _46[index]]);
1164
1174
  if (!line || line.type !== "moving-average") return [];
1165
- return _chunkXTU6QO2Wcjs.chartMovingAverage.call(void 0, this.trendlinePoints(seriesId), _nullishCoalesce(line.period, () => ( 2)));
1175
+ return _chunk4YWAEV4Wcjs.chartMovingAverage.call(void 0, this.trendlinePoints(seriesId), _nullishCoalesce(line.period, () => ( 2)));
1166
1176
  }
1167
1177
  // -------------------------------------------------------------------------
1168
1178
  // Reshaping
@@ -1181,7 +1191,7 @@ var ChartController = (_class = class {
1181
1191
  used.add(id);
1182
1192
  return { id, name, values: s.series.map((x) => _nullishCoalesce(x.values[i], () => ( null))) };
1183
1193
  });
1184
- const { spec } = _chunkI4AHLP7Fcjs.normalizeChartSpec.call(void 0, { ...s, categories: s.series.map((x) => x.name), series });
1194
+ const { spec } = _chunkWPPJH6X4cjs.normalizeChartSpec.call(void 0, { ...s, categories: s.series.map((x) => x.name), series });
1185
1195
  this.commit("Switch rows and columns", spec, null);
1186
1196
  return { ok: true };
1187
1197
  }
@@ -1191,7 +1201,7 @@ var ChartController = (_class = class {
1191
1201
  /** Selects a chart element (view state; not an undo step). */
1192
1202
  select(selection) {
1193
1203
  const next = this.validSelection(selection, this.spec);
1194
- if (_chunkXTU6QO2Wcjs.sameChartSelection.call(void 0, next, this.selection) || next === null && this.selection === null) return;
1204
+ if (_chunk4YWAEV4Wcjs.sameChartSelection.call(void 0, next, this.selection) || next === null && this.selection === null) return;
1195
1205
  this.selection = next;
1196
1206
  this.notify(false);
1197
1207
  }
@@ -1266,14 +1276,14 @@ var ChartController = (_class = class {
1266
1276
  // -------------------------------------------------------------------------
1267
1277
  /** The spec, for saving (a copy). */
1268
1278
  toJSON() {
1269
- return _chunkI4AHLP7Fcjs.cloneChartSpec.call(void 0, this.spec);
1279
+ return _chunkWPPJH6X4cjs.cloneChartSpec.call(void 0, this.spec);
1270
1280
  }
1271
1281
  /**
1272
1282
  * Replaces the chart without an undo step (e.g. when opening a document). Problems are
1273
1283
  * fixed with defaults and reported in `state.issues` (and returned).
1274
1284
  */
1275
1285
  load(input, options = {}) {
1276
- const { spec, issues } = _chunkI4AHLP7Fcjs.normalizeChartSpec.call(void 0, input);
1286
+ const { spec, issues } = _chunkWPPJH6X4cjs.normalizeChartSpec.call(void 0, input);
1277
1287
  this.spec = spec;
1278
1288
  this.issues = issues;
1279
1289
  this.selection = this.validSelection(this.selection, spec);
@@ -1293,7 +1303,7 @@ var ChartController = (_class = class {
1293
1303
  * nothing changes and every problem is returned (and shown in `state.issues`).
1294
1304
  */
1295
1305
  replace(input, options = {}) {
1296
- const { spec, issues } = _chunkI4AHLP7Fcjs.normalizeChartSpec.call(void 0, input);
1306
+ const { spec, issues } = _chunkWPPJH6X4cjs.normalizeChartSpec.call(void 0, input);
1297
1307
  if (issues.length) return this.reject(issues.map((i) => i.message).join(" "), issues);
1298
1308
  this.commit(_nullishCoalesce(options.label, () => ( "Replace chart")), spec, this.validSelection(this.selection, spec));
1299
1309
  return { ok: true };
@@ -1333,6 +1343,8 @@ function updateLabel(patch) {
1333
1343
  overlap: "Change bar overlap",
1334
1344
  bins: "Change histogram bins",
1335
1345
  showTotal: "Toggle waterfall total",
1346
+ radarTicks: "Change radar rings",
1347
+ radarGraticule: "Change radar grid",
1336
1348
  legend: "Change legend",
1337
1349
  stacking: "Change stacking",
1338
1350
  orientation: "Change orientation",
@@ -1353,7 +1365,7 @@ function layoutSparkline(values, options) {
1353
1365
  const h = Number.isFinite(options.height) ? Math.max(1, options.height) : 1;
1354
1366
  const color = _nullishCoalesce(options.color, () => ( "#4269d0"));
1355
1367
  const negative = _nullishCoalesce(options.negativeColor, () => ( "#e5484d"));
1356
- const theme = { ..._chunkI4AHLP7Fcjs.DEFAULT_CHART_THEME, background: "transparent" };
1368
+ const theme = { ..._chunkWPPJH6X4cjs.DEFAULT_CHART_THEME, background: "transparent" };
1357
1369
  const marks = [];
1358
1370
  const scene = { width: w, height: h, plot: { x: 0, y: 0, width: w, height: h }, marks, percent: false, theme, warnings: [] };
1359
1371
  const vals = values.slice(0, MAX_POINTS).map((v) => v !== null && Number.isFinite(v) ? Math.max(-1e300, Math.min(1e300, v)) : null);
@@ -1386,7 +1398,7 @@ function layoutSparkline(values, options) {
1386
1398
  const flush = () => {
1387
1399
  if (run.length >= 2) {
1388
1400
  const pts = run.length > 4e3 ? run.filter((_, i) => i % (Math.floor(run.length / 2e3) + 1) === 0) : run;
1389
- d += pts.map(([x, y], i) => `${i ? "L" : "M"}${_chunkXTU6QO2Wcjs.r2.call(void 0, x)},${_chunkXTU6QO2Wcjs.r2.call(void 0, y)}`).join("");
1401
+ d += pts.map(([x, y], i) => `${i ? "L" : "M"}${_chunk4YWAEV4Wcjs.r2.call(void 0, x)},${_chunk4YWAEV4Wcjs.r2.call(void 0, y)}`).join("");
1390
1402
  }
1391
1403
  run = [];
1392
1404
  };
@@ -6,7 +6,7 @@ import {
6
6
  isCartesianChart,
7
7
  normalizeChartSpec,
8
8
  parseChartColor
9
- } from "./chunk-SUVZJ2CP.js";
9
+ } from "./chunk-H5XX4KHB.js";
10
10
 
11
11
  // src/chart/ooxml.ts
12
12
  var CHART_OOXML_NS = "http://schemas.openxmlformats.org/drawingml/2006/chart";
@@ -231,6 +231,7 @@ var CHART_AXIS_SCALES = ["linear", "log"];
231
231
  var CHART_SERIES_TYPES = ["bar", "line", "area", "scatter"];
232
232
  var CHART_STACKINGS = ["none", "stacked", "percent"];
233
233
  var CHART_CURVES = ["linear", "smooth", "step"];
234
+ var CHART_RADAR_GRATICULES = ["polygon", "circle"];
234
235
  var CHART_ORIENTATIONS = ["vertical", "horizontal"];
235
236
  var CHART_LEGEND_POSITIONS = ["top", "bottom", "left", "right"];
236
237
  var CHART_NUMBER_STYLES = ["number", "percent", "currency", "compact"];
@@ -652,6 +653,12 @@ function normalizeChartSpec(input) {
652
653
  if (Number.isInteger(b) && b >= 1 && b <= 500) bins = b;
653
654
  else issues.push({ path: "bins", message: "bins must be a whole number from 1 to 500, or null for automatic." });
654
655
  }
656
+ let radarTicks = null;
657
+ if (value.radarTicks !== void 0 && value.radarTicks !== null) {
658
+ const t = Number(value.radarTicks);
659
+ if (Number.isInteger(t) && t >= 1 && t <= 50) radarTicks = t;
660
+ else issues.push({ path: "radarTicks", message: "radarTicks must be a whole number from 1 to 50, or null for round-number rings." });
661
+ }
655
662
  const spec = {
656
663
  version: 1,
657
664
  type,
@@ -674,7 +681,9 @@ function normalizeChartSpec(input) {
674
681
  gapWidth,
675
682
  overlap,
676
683
  bins,
677
- showTotal: flag(value.showTotal, true, "showTotal", issues)
684
+ showTotal: flag(value.showTotal, true, "showTotal", issues),
685
+ radarTicks,
686
+ radarGraticule: pick(value.radarGraticule, CHART_RADAR_GRATICULES, "polygon", "radarGraticule", issues)
678
687
  };
679
688
  if (spec.stacking === "percent")
680
689
  for (const name of ["yAxis", "yAxis2"]) {
@@ -793,6 +802,7 @@ export {
793
802
  CHART_SERIES_TYPES,
794
803
  CHART_STACKINGS,
795
804
  CHART_CURVES,
805
+ CHART_RADAR_GRATICULES,
796
806
  CHART_ORIENTATIONS,
797
807
  CHART_LEGEND_POSITIONS,
798
808
  CHART_NUMBER_STYLES,
@@ -11,10 +11,10 @@ import {
11
11
  CHART_OOXML_NS,
12
12
  CHART_OOXML_RELATIONSHIP,
13
13
  chartToOoxml
14
- } from "./chunk-EQ4SF4X4.js";
14
+ } from "./chunk-DBIVICAO.js";
15
15
  import {
16
16
  normalizeChartSpec
17
- } from "./chunk-SUVZJ2CP.js";
17
+ } from "./chunk-H5XX4KHB.js";
18
18
 
19
19
  // src/export/images.ts
20
20
  var DOCX_IMAGE_TYPES = {
@@ -7,7 +7,7 @@ import {
7
7
  chartSeriesColor,
8
8
  chartSeriesType,
9
9
  chartSliceColor
10
- } from "./chunk-SUVZJ2CP.js";
10
+ } from "./chunk-H5XX4KHB.js";
11
11
  import {
12
12
  NumberFormat
13
13
  } from "./chunk-II2WIF5Z.js";
@@ -1580,7 +1580,12 @@ function layoutRadar(ctx, area, visible) {
1580
1580
  let hi = -Infinity;
1581
1581
  for (const s of visible) for (const v of s.values) if (v !== null && Number.isFinite(v)) lo = Math.min(lo, v), hi = Math.max(hi, v);
1582
1582
  if (!Number.isFinite(hi)) hi = 1;
1583
- const scale = axisScale(lo, hi, radius, spec.yAxis, ctx.options.valueDomain);
1583
+ let scale = axisScale(lo, hi, radius, spec.yAxis, ctx.options.valueDomain);
1584
+ if (spec.radarTicks !== null && spec.yAxis.scale !== "log") {
1585
+ const n2 = spec.radarTicks;
1586
+ const step = (scale.max - scale.min) / n2;
1587
+ scale = { ...scale, step, ticks: Array.from({ length: n2 + 1 }, (_, k) => Number((scale.min + step * k).toPrecision(12))) };
1588
+ }
1584
1589
  const rOf = (v) => linearMap(Math.min(scale.max, Math.max(scale.min, v)), [scale.min, scale.max], [0, radius]);
1585
1590
  const angle = (i) => i / n * Math.PI * 2;
1586
1591
  const at = (i, r) => [cx + r * Math.sin(angle(i)), cy - r * Math.cos(angle(i))];
@@ -1589,6 +1594,10 @@ function layoutRadar(ctx, area, visible) {
1589
1594
  scale.ticks.forEach((t, k) => {
1590
1595
  const r = rOf(t);
1591
1596
  if (r <= 0) return;
1597
+ if (spec.radarGraticule === "circle") {
1598
+ marks.push({ kind: "circle", key: `grid-ring-${k}`, role: "grid", cx, cy, r, fill: "none", stroke: theme.grid, strokeWidth: 1 });
1599
+ return;
1600
+ }
1592
1601
  const d = Array.from({ length: n }, (_, i) => at(i, r)).map(([x, y], i) => `${i ? "L" : "M"}${r2(x)},${r2(y)}`).join("") + "Z";
1593
1602
  marks.push({ kind: "path", key: `grid-ring-${k}`, role: "grid", d, fill: "none", stroke: theme.grid, strokeWidth: 1 });
1594
1603
  });
@@ -7,7 +7,7 @@ import {
7
7
  r2,
8
8
  sameChartSelection,
9
9
  summarizeChartSeries
10
- } from "./chunk-DSZCDNTM.js";
10
+ } from "./chunk-R3QY7PPL.js";
11
11
  import {
12
12
  CHART_TYPE_LABELS,
13
13
  DEFAULT_CHART_PALETTE,
@@ -27,7 +27,7 @@ import {
27
27
  parseChartValue,
28
28
  shadeChartColor,
29
29
  uniqueChartSeriesId
30
- } from "./chunk-SUVZJ2CP.js";
30
+ } from "./chunk-H5XX4KHB.js";
31
31
  import {
32
32
  parseCsv,
33
33
  parseTsv
@@ -126,6 +126,8 @@ function chartToMermaid(spec, options = {}) {
126
126
  }
127
127
  if (spec.yAxis.max !== null) lines.push(`${ind}max ${num(spec.yAxis.max)}`);
128
128
  if (spec.yAxis.min !== null) lines.push(`${ind}min ${num(spec.yAxis.min)}`);
129
+ if (spec.radarTicks !== null) lines.push(`${ind}ticks ${spec.radarTicks}`);
130
+ if (spec.radarGraticule === "polygon") lines.push(`${ind}graticule polygon`);
129
131
  if (!spec.legend.show) lines.push(`${ind}showLegend false`);
130
132
  } else {
131
133
  lines.push(`xychart-beta${spec.orientation === "horizontal" ? " horizontal" : ""}`);
@@ -230,6 +232,8 @@ function chartFromMermaid(text, options = {}) {
230
232
  const radarAxes = [];
231
233
  const pieSlices = [];
232
234
  let legendShow = true;
235
+ let radarTicks = null;
236
+ let graticule = "circle";
233
237
  const counts = { bar: 0, line: 0 };
234
238
  const lineIssue = (i, message) => issues.push({ path: `line ${i + 1}`, line: i + 1, message: `Line ${i + 1}: ${message}` });
235
239
  for (let i = headerLine + 1; family && i < all.length; i++) {
@@ -337,6 +341,12 @@ function chartFromMermaid(text, options = {}) {
337
341
  if (m[1] === "max") yAxis.max = Number(m[2]);
338
342
  else if (m[1] === "min") yAxis.min = Number(m[2]);
339
343
  else if (m[1] === "showLegend") legendShow = m[2] !== "false";
344
+ else if (m[1] === "ticks") {
345
+ const n = Number(m[2]);
346
+ if (Number.isFinite(n) && n >= 1) radarTicks = Math.min(50, Math.round(n));
347
+ else lineIssue(i, `expected ticks to be a number of rings (1 or more), got "${m[2]}".`);
348
+ } else if (m[2] === "circle" || m[2] === "polygon") graticule = m[2];
349
+ else lineIssue(i, `expected graticule circle or polygon, got "${m[2]}".`);
340
350
  continue;
341
351
  }
342
352
  }
@@ -352,7 +362,7 @@ function chartFromMermaid(text, options = {}) {
352
362
  series: [{ id: "series-1", name: title || "Values", values: pieSlices.map((s) => s.value) }]
353
363
  };
354
364
  } else if (family === "radar") {
355
- input = { type: "radar", title, categories: radarAxes.map((a) => a.label), series, yAxis, legend: { show: legendShow, position: "bottom" } };
365
+ input = { type: "radar", title, categories: radarAxes.map((a) => a.label), series, yAxis, legend: { show: legendShow, position: "bottom" }, radarTicks, radarGraticule: graticule };
356
366
  } else {
357
367
  const allBar = series.length > 0 && series.every((s) => s.type === "bar");
358
368
  const allLine = series.length > 0 && series.every((s) => s.type === "line");
@@ -1333,6 +1343,8 @@ function updateLabel(patch) {
1333
1343
  overlap: "Change bar overlap",
1334
1344
  bins: "Change histogram bins",
1335
1345
  showTotal: "Toggle waterfall total",
1346
+ radarTicks: "Change radar rings",
1347
+ radarGraticule: "Change radar grid",
1336
1348
  legend: "Change legend",
1337
1349
  stacking: "Change stacking",
1338
1350
  orientation: "Change orientation",