@pixerate/editor 0.162.0 → 0.163.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 (81) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/index.cjs +34 -34
  3. package/dist/agent/index.js +5 -5
  4. package/dist/animation-editor/index.cjs +57 -57
  5. package/dist/animation-editor/index.js +3 -3
  6. package/dist/{brushstrokeRender-Q4LI22QV.js → brushstrokeRender-7LXCU7PD.js} +2 -2
  7. package/dist/{brushstrokeRender-5WANQIG4.cjs → brushstrokeRender-VO4ZTWVA.cjs} +5 -5
  8. package/dist/canvas/index.cjs +14 -14
  9. package/dist/canvas/index.js +3 -3
  10. package/dist/chart/commands.d.cts +2 -1
  11. package/dist/chart/commands.d.ts +2 -1
  12. package/dist/chart/controller.d.cts +109 -1
  13. package/dist/chart/controller.d.ts +109 -1
  14. package/dist/chart/index.cjs +605 -130
  15. package/dist/chart/index.d.cts +1 -0
  16. package/dist/chart/index.d.ts +1 -0
  17. package/dist/chart/index.js +490 -15
  18. package/dist/chart/layout-annotations.d.cts +29 -0
  19. package/dist/chart/layout-annotations.d.ts +29 -0
  20. package/dist/chart/layout-families.d.cts +23 -0
  21. package/dist/chart/layout-families.d.ts +23 -0
  22. package/dist/chart/mermaid.d.cts +2 -1
  23. package/dist/chart/mermaid.d.ts +2 -1
  24. package/dist/chart/schemas.d.cts +13 -0
  25. package/dist/chart/schemas.d.ts +13 -0
  26. package/dist/chart/spec.d.cts +30 -5
  27. package/dist/chart/spec.d.ts +30 -5
  28. package/dist/chart/stats.d.cts +9 -1
  29. package/dist/chart/stats.d.ts +9 -1
  30. package/dist/chart/tools.d.cts +1 -1
  31. package/dist/chart/tools.d.ts +1 -1
  32. package/dist/chart/tree.d.cts +62 -0
  33. package/dist/chart/tree.d.ts +62 -0
  34. package/dist/chart/types.d.cts +77 -3
  35. package/dist/chart/types.d.ts +77 -3
  36. package/dist/{chunk-7YBDRJXT.cjs → chunk-22KLZZGH.cjs} +8 -8
  37. package/dist/{chunk-LQLZHP6F.js → chunk-36OKQDCF.js} +7 -4
  38. package/dist/{chunk-HLOKB7WW.js → chunk-3NEZJCBY.js} +366 -6
  39. package/dist/{chunk-GWV4T5NZ.js → chunk-3VLOOO3G.js} +1 -1
  40. package/dist/{chunk-3GJH2MGH.cjs → chunk-5AARIS3R.cjs} +35 -35
  41. package/dist/{chunk-EVPZ5IKN.js → chunk-5FNGLV2D.js} +65 -3
  42. package/dist/{chunk-EQ46F75O.cjs → chunk-D54JHQK2.cjs} +51 -51
  43. package/dist/{chunk-NO5QQDHZ.js → chunk-DAPQGA55.js} +2 -2
  44. package/dist/{chunk-3IHNXRUV.cjs → chunk-GKNEJ6EN.cjs} +399 -67
  45. package/dist/{chunk-236TKNUR.cjs → chunk-JCXMJUQO.cjs} +2 -2
  46. package/dist/{chunk-4NGVHHJB.cjs → chunk-NZD2MZJC.cjs} +80 -18
  47. package/dist/{chunk-CX6JLDFC.js → chunk-OXERWBKE.js} +3 -3
  48. package/dist/{chunk-32MMQYCQ.cjs → chunk-PA3IMPPS.cjs} +81 -81
  49. package/dist/{chunk-7CKPUUN4.js → chunk-POR54B55.js} +61 -10
  50. package/dist/{chunk-KGTF55R3.js → chunk-QY4KUDMY.js} +1 -1
  51. package/dist/{chunk-LL3H5XUH.cjs → chunk-R3P2M7HU.cjs} +367 -7
  52. package/dist/{chunk-HDGBM7EA.cjs → chunk-SBQVEBSU.cjs} +580 -53
  53. package/dist/{chunk-2TKHLX6H.js → chunk-SET6KJOP.js} +1 -1
  54. package/dist/{chunk-XDCFJEU7.js → chunk-SZA42R4N.js} +346 -14
  55. package/dist/{chunk-GLMP22FT.js → chunk-TALQONZ5.js} +3 -3
  56. package/dist/{chunk-GNK7SESQ.cjs → chunk-V7GWZIZK.cjs} +7 -4
  57. package/dist/{chunk-EYVVIZJ3.cjs → chunk-WTW7QRTS.cjs} +1 -1
  58. package/dist/{chunk-NA4UVVJ4.cjs → chunk-YGG7WDWT.cjs} +76 -25
  59. package/dist/{chunk-JGKCC5OF.cjs → chunk-YQ5C5BVK.cjs} +10 -9
  60. package/dist/{chunk-EY22AY6R.cjs → chunk-YSAGBIRW.cjs} +16 -16
  61. package/dist/{chunk-A5UCR2TO.js → chunk-YXKLVD56.js} +10 -9
  62. package/dist/{chunk-DTSTNRPH.js → chunk-Z4P2RBMJ.js} +536 -9
  63. package/dist/{chunk-45XXVHVG.js → chunk-ZZGPYNS2.js} +1 -1
  64. package/dist/export/index.cjs +4 -4
  65. package/dist/export/index.js +3 -3
  66. package/dist/extensions/index.cjs +7 -7
  67. package/dist/extensions/index.js +6 -6
  68. package/dist/image-editor/index.cjs +638 -638
  69. package/dist/image-editor/index.js +4 -4
  70. package/dist/index.cjs +13 -13
  71. package/dist/index.js +7 -7
  72. package/dist/paint/index.cjs +2 -2
  73. package/dist/paint/index.js +1 -1
  74. package/dist/paint-editor/index.cjs +129 -149
  75. package/dist/paint-editor/index.js +5 -25
  76. package/dist/vector/index.cjs +948 -948
  77. package/dist/vector/index.js +3 -3
  78. package/package.json +3 -3
  79. package/skills/pixerate-canvas/SKILL.md +16 -0
  80. package/skills/pixerate-chart/SKILL.md +92 -9
  81. package/skills/pixerate-paint-editor/SKILL.md +0 -2
@@ -2,12 +2,19 @@ import {
2
2
  CATEGORY_REF,
3
3
  CHART_UPDATE_PROPERTIES,
4
4
  HEIGHT,
5
+ REFERENCE_BAND_PATCH,
6
+ REFERENCE_BAND_PROPS,
7
+ REFERENCE_INDEX,
8
+ REFERENCE_LINE_PATCH,
9
+ REFERENCE_LINE_PROPS,
5
10
  SERIES_PROPS,
6
11
  SERIES_REF,
12
+ TREE_DEFS,
13
+ TREE_PATH,
7
14
  TRENDLINE_PROPS,
8
15
  VALUE,
9
16
  WIDTH
10
- } from "../chunk-EVPZ5IKN.js";
17
+ } from "../chunk-5FNGLV2D.js";
11
18
  import {
12
19
  CHART_OOXML_CONTENT_TYPE,
13
20
  CHART_OOXML_NS,
@@ -15,7 +22,7 @@ import {
15
22
  chartFormatToCode,
16
23
  chartFromOoxml,
17
24
  chartToOoxml
18
- } from "../chunk-7CKPUUN4.js";
25
+ } from "../chunk-POR54B55.js";
19
26
  import {
20
27
  CHART_COLOR_SCHEMES,
21
28
  CHART_LAYOUT_PRESETS,
@@ -37,7 +44,7 @@ import {
37
44
  monochromeChartPalette,
38
45
  sparklineToSvg,
39
46
  summarizeChart
40
- } from "../chunk-XDCFJEU7.js";
47
+ } from "../chunk-SZA42R4N.js";
41
48
  import {
42
49
  CHART_DATE_STEPS,
43
50
  MAX_CHART_DATA_LABELS,
@@ -74,9 +81,10 @@ import {
74
81
  sameChartSelection,
75
82
  snapChartValue,
76
83
  stepDecimals,
84
+ suggestChartReferences,
77
85
  summarizeChartSeries,
78
86
  trendNumberText
79
- } from "../chunk-DTSTNRPH.js";
87
+ } from "../chunk-Z4P2RBMJ.js";
80
88
  import {
81
89
  CHART_AXIS_KINDS,
82
90
  CHART_AXIS_SCALES,
@@ -86,11 +94,14 @@ import {
86
94
  CHART_ERROR_BAR_TYPES,
87
95
  CHART_LABEL_POSITIONS,
88
96
  CHART_LEGEND_POSITIONS,
97
+ CHART_LIKERT_NEUTRALS,
98
+ CHART_LIKERT_SORTS,
89
99
  CHART_MARKERS,
90
100
  CHART_NUMBER_STYLES,
91
101
  CHART_ORIENTATIONS,
92
102
  CHART_PALETTE_SHADES,
93
103
  CHART_RADAR_GRATICULES,
104
+ CHART_REFERENCE_AXES,
94
105
  CHART_SERIES_TYPES,
95
106
  CHART_STACKINGS,
96
107
  CHART_TRENDLINE_TYPES,
@@ -99,6 +110,9 @@ import {
99
110
  CSS_VARIABLE_CHART_THEME,
100
111
  DEFAULT_CHART_PALETTE,
101
112
  DEFAULT_CHART_THEME,
113
+ MAX_CHART_TREE_DEPTH,
114
+ MAX_CHART_TREE_NODES,
115
+ addChartTreeRow,
102
116
  chartColorDistance,
103
117
  chartColorInputValue,
104
118
  chartColorsByCategory,
@@ -108,6 +122,7 @@ import {
108
122
  chartErrorAmounts,
109
123
  chartErrorBarsOfType,
110
124
  chartFamily,
125
+ chartLikertColor,
111
126
  chartLuminance,
112
127
  chartPointColor,
113
128
  chartRgbToHex,
@@ -115,30 +130,47 @@ import {
115
130
  chartSeriesColor,
116
131
  chartSeriesType,
117
132
  chartSliceColor,
133
+ chartSpecColorsByCategory,
118
134
  chartTextOn,
135
+ chartTreeColumnLabels,
136
+ chartTreeDepth,
137
+ chartTreeFromRows,
138
+ chartTreeFromSeries,
139
+ chartTreeFromTable,
140
+ chartTreeToRows,
141
+ chartTreeTotal,
142
+ chartVariesColors,
119
143
  checkChartColors,
120
144
  cloneChartSeries,
121
145
  cloneChartSpec,
146
+ cloneChartTree,
122
147
  createChartSpec,
123
148
  cyclePaletteColor,
124
149
  defaultChartAxis,
125
150
  defaultChartErrorBarValue,
126
151
  describeChartErrorBars,
152
+ findChartTreeNode,
127
153
  formatChartAmountList,
128
154
  isCartesianChart,
129
155
  isXyChart,
130
156
  normalizeChartAxis,
131
157
  normalizeChartErrorBars,
158
+ normalizeChartReferenceBand,
159
+ normalizeChartReferenceLine,
132
160
  normalizeChartSpec,
161
+ normalizeChartTree,
133
162
  normalizeChartTrendline,
134
163
  normalizeChartValues,
135
164
  parseChartAmountList,
136
165
  parseChartColor,
137
166
  parseChartValue,
167
+ removeChartTreeRow,
168
+ setChartTreeRowName,
169
+ setChartTreeRowValue,
138
170
  shadeChartColor,
139
171
  simulateChartVision,
140
172
  uniqueChartSeriesId
141
- } from "../chunk-HLOKB7WW.js";
173
+ } from "../chunk-3NEZJCBY.js";
142
174
  import "../chunk-II2WIF5Z.js";
143
175
  import {
144
176
  parseCsv
@@ -367,6 +399,7 @@ function recommendForShape(shape) {
367
399
  add("donut", "Donut", "Shares of a whole with the total in the middle.");
368
400
  if (shape.points >= 5) add("treemap", "Treemap", "Compares many shares by area.");
369
401
  add("funnel", "Funnel", "Shows stages that narrow down.");
402
+ add("parliament", "Parliament", "Seats or votes per group, with the majority line.");
370
403
  }
371
404
  add("line", "Line", "Shows the values in order.");
372
405
  }
@@ -378,11 +411,13 @@ function recommendForShape(shape) {
378
411
  add("area", "Area", "Emphasises volume.");
379
412
  add("bar", "Stacked column", "Shows how the series add up.", "stacked");
380
413
  } else {
414
+ if (shape.series === 2 && shape.labelColumn) add("slope", "Slope", "Two columns per item: shows what rose and what fell between them.");
381
415
  add("bar", "Column", "Several series: clustered columns compare them per category.");
382
416
  add("bar", "Bar", "Horizontal bars fit long category names.");
383
417
  add("bar", "Stacked column", "Shows how the series add up.", "stacked");
384
418
  add("line", "Line", "Shows the series in order.");
385
419
  if (shape.points >= 3 && shape.series <= 6) add("radar", "Radar", "Compares several measures across the series.");
420
+ if (shape.nonNegative && shape.series >= 3 && shape.series <= 7) add("likert", "Likert", "Survey answers per question (columns from most negative to most positive): shows agreement against disagreement.");
386
421
  }
387
422
  return out;
388
423
  }
@@ -447,7 +482,7 @@ function createChartCommands(controller, options = {}) {
447
482
  id: `${prefix}update`,
448
483
  label: "Change Chart\u2026",
449
484
  keywords: ["chart", "title", "axis", "legend", "stack", "style", "format", "type"],
450
- description: 'Changes chart presentation as one undo step: type, titles, axes (xAxis = categories, yAxis = values, yAxis2 = secondary values; reverse, and scale "log" on value axes), legend, stacking, orientation, curve, points, data labels, palette, donut hole, bar spacing, histogram bins, waterfall total, or radar rings and grid shape. Invalid values change nothing and return why.',
485
+ description: 'Changes chart presentation as one undo step: type, titles, axes (xAxis = categories, yAxis = values, yAxis2 = secondary values; reverse, and scale "log" on value axes), legend, stacking, orientation, curve, points, data labels, palette, donut hole, bar spacing, histogram bins, waterfall total, or radar rings and grid shape, note, highlight, reference lines and bands, or colour by category (varyColors). Invalid values change nothing and return why.',
451
486
  params: object(CHART_UPDATE_PROPERTIES),
452
487
  run: (_ctx, params) => {
453
488
  check(controller.update(params));
@@ -529,7 +564,11 @@ function createChartCommands(controller, options = {}) {
529
564
  keywords: ["chart", "category", "row", "label"],
530
565
  description: "Inserts a category (gaps in every series) at `at` (default: the end).",
531
566
  params: object({ label: { type: "string", description: "Category label (default: its number)." }, at: { type: "integer", minimum: 0, description: "Index to insert at (default: the end)." } }),
532
- run: (_ctx, params = {}) => controller.addCategory(params?.label, { at: params?.at })
567
+ run: (_ctx, params = {}) => {
568
+ const result = controller.addCategory(params?.label, { at: params?.at });
569
+ check(result);
570
+ return result;
571
+ }
533
572
  },
534
573
  {
535
574
  ...base,
@@ -570,6 +609,197 @@ function createChartCommands(controller, options = {}) {
570
609
  return { trendlines: controller.getSeries(resolveSeries(params.series).id)?.trendlines ?? [] };
571
610
  }
572
611
  },
612
+ {
613
+ ...base,
614
+ id: `${prefix}addReferenceLine`,
615
+ label: "Add Reference Line\u2026",
616
+ keywords: ["chart", "target", "goal", "threshold", "average", "reference", "line", "annotation"],
617
+ description: "Draws a dashed line across the plot at one value (a target, floor or average). Returns its index.",
618
+ params: object(REFERENCE_LINE_PROPS, ["value"]),
619
+ run: (_ctx, params) => {
620
+ const result = controller.addReferenceLine(params);
621
+ check(result);
622
+ return { index: result.index, referenceLines: controller.getSpec().referenceLines };
623
+ }
624
+ },
625
+ {
626
+ ...base,
627
+ id: `${prefix}updateReferenceLine`,
628
+ label: "Change Reference Line\u2026",
629
+ keywords: ["chart", "target", "reference", "line", "annotation"],
630
+ description: "Changes a reference line by index; label, axis and color take null to remove them.",
631
+ params: object({ index: REFERENCE_INDEX("Reference line"), ...REFERENCE_LINE_PATCH }, ["index"]),
632
+ run: (_ctx, params) => {
633
+ const { index, ...patch } = params;
634
+ check(controller.updateReferenceLine(index, patch));
635
+ return { referenceLine: controller.getSpec().referenceLines[index] };
636
+ }
637
+ },
638
+ {
639
+ ...base,
640
+ id: `${prefix}removeReferenceLine`,
641
+ label: "Delete Reference Line",
642
+ keywords: ["chart", "target", "reference", "line", "remove"],
643
+ description: "Deletes a reference line by index.",
644
+ params: object({ index: REFERENCE_INDEX("Reference line") }, ["index"]),
645
+ run: (_ctx, params) => {
646
+ check(controller.removeReferenceLine(params.index));
647
+ return { referenceLines: controller.getSpec().referenceLines };
648
+ }
649
+ },
650
+ {
651
+ ...base,
652
+ id: `${prefix}addReferenceBand`,
653
+ label: "Add Reference Band\u2026",
654
+ keywords: ["chart", "target", "range", "band", "reference", "shade", "annotation"],
655
+ description: "Shades a band across the plot between two values (a target or normal range). Returns its index.",
656
+ params: object(REFERENCE_BAND_PROPS, ["from", "to"]),
657
+ run: (_ctx, params) => {
658
+ const result = controller.addReferenceBand(params);
659
+ check(result);
660
+ return { index: result.index, referenceBands: controller.getSpec().referenceBands };
661
+ }
662
+ },
663
+ {
664
+ ...base,
665
+ id: `${prefix}updateReferenceBand`,
666
+ label: "Change Reference Band\u2026",
667
+ keywords: ["chart", "range", "band", "reference", "annotation"],
668
+ description: "Changes a reference band by index; label, axis and color take null to remove them.",
669
+ params: object({ index: REFERENCE_INDEX("Reference band"), ...REFERENCE_BAND_PATCH }, ["index"]),
670
+ run: (_ctx, params) => {
671
+ const { index, ...patch } = params;
672
+ check(controller.updateReferenceBand(index, patch));
673
+ return { referenceBand: controller.getSpec().referenceBands[index] };
674
+ }
675
+ },
676
+ {
677
+ ...base,
678
+ id: `${prefix}removeReferenceBand`,
679
+ label: "Delete Reference Band",
680
+ keywords: ["chart", "range", "band", "reference", "remove"],
681
+ description: "Deletes a reference band by index.",
682
+ params: object({ index: REFERENCE_INDEX("Reference band") }, ["index"]),
683
+ run: (_ctx, params) => {
684
+ check(controller.removeReferenceBand(params.index));
685
+ return { referenceBands: controller.getSpec().referenceBands };
686
+ }
687
+ },
688
+ {
689
+ ...base,
690
+ id: `${prefix}setCallout`,
691
+ label: "Pin Label to Point\u2026",
692
+ keywords: ["chart", "callout", "annotation", "label", "note", "point"],
693
+ description: 'Pins a short label to one bar or point (label null or "" removes it).',
694
+ params: object({ series: SERIES_REF, category: CATEGORY_REF, label: { type: ["string", "null"], description: "The label (a few words), or null to remove it." } }, ["series", "category", "label"]),
695
+ run: (_ctx, params) => {
696
+ const series = resolveSeries(params.series);
697
+ const index = resolveCategory(params.category);
698
+ check(controller.setCallout(series.id, index, params.label));
699
+ return { series: series.id, index, label: controller.getSeries(series.id)?.callouts?.[index] ?? null };
700
+ }
701
+ },
702
+ {
703
+ ...base,
704
+ id: `${prefix}highlight`,
705
+ label: "Highlight\u2026",
706
+ keywords: ["chart", "highlight", "emphasise", "emphasize", "focus", "mute", "dim"],
707
+ description: "Draws the named categories and series normally and mutes the rest ([] shows everything). Unknown names change nothing.",
708
+ params: object({ names: { type: "array", items: { type: "string" }, description: "Category labels and / or series names or ids; [] clears the highlight." } }, ["names"]),
709
+ run: (_ctx, params) => {
710
+ const result = controller.setHighlight(params.names);
711
+ check(result);
712
+ const { categories, series } = result;
713
+ return { highlight: controller.getSpec().highlight, categories, series };
714
+ }
715
+ },
716
+ {
717
+ ...base,
718
+ id: `${prefix}setTree`,
719
+ label: "Replace Grouped Data\u2026",
720
+ keywords: ["chart", "tree", "hierarchy", "groups", "treemap", "sunburst", "nested"],
721
+ description: "Replaces the data with groups of items (a tree) for treemaps and sunbursts; [] goes back to plain data.",
722
+ params: { type: "object", properties: { tree: { type: "array", items: { $ref: "#/$defs/chartTreeNode" }, description: "The top-level nodes; [] removes the grouping." } }, required: ["tree"], additionalProperties: false, $defs: TREE_DEFS },
723
+ run: (_ctx, params) => {
724
+ check(controller.setTree(params.tree));
725
+ return { groups: controller.getSpec().tree.map((n) => ({ name: n.name, total: chartTreeTotal(n) })) };
726
+ }
727
+ },
728
+ {
729
+ ...base,
730
+ id: `${prefix}importTreeCsv`,
731
+ label: "Import Grouped Data from CSV\u2026",
732
+ keywords: ["chart", "tree", "hierarchy", "csv", "import", "treemap", "sunburst"],
733
+ description: "Replaces the data with grouped data from CSV / TSV: names in every column but the last (group, \u2026, item), the value in the last.",
734
+ params: object(
735
+ {
736
+ csv: { type: "string", description: "CSV or TSV text." },
737
+ header: { type: ["boolean", "string"], enum: [true, false, "auto"], description: "The first row holds column names (default auto)." }
738
+ },
739
+ ["csv"]
740
+ ),
741
+ run: (_ctx, params) => {
742
+ check(controller.importTreeTable(parseCsv(params.csv, { delimiter: params.csv.includes(" ") ? " " : "," }), { header: params.header }));
743
+ return { tree: controller.getSpec().tree };
744
+ }
745
+ },
746
+ {
747
+ ...base,
748
+ id: `${prefix}addTreeNode`,
749
+ label: "Add Item or Group\u2026",
750
+ keywords: ["chart", "tree", "group", "item", "add", "treemap", "sunburst"],
751
+ description: "Adds an item or group under a group of the grouped data ([] for the top level). Returns its path.",
752
+ params: {
753
+ type: "object",
754
+ properties: {
755
+ parent: { type: "array", items: { type: "string" }, description: "Path of the group to add to; [] or omitted for the top level." },
756
+ node: { $ref: "#/$defs/chartTreeNode", description: "The item or group to add." },
757
+ at: { type: "integer", minimum: 0, description: "Position among its siblings (default: the end)." }
758
+ },
759
+ required: ["node"],
760
+ additionalProperties: false,
761
+ $defs: TREE_DEFS
762
+ },
763
+ run: (_ctx, params) => {
764
+ const result = controller.addTreeNode(params.parent ?? [], params.node, { at: params.at });
765
+ check(result);
766
+ return { path: result.path };
767
+ }
768
+ },
769
+ {
770
+ ...base,
771
+ id: `${prefix}updateTreeNode`,
772
+ label: "Change Item or Group\u2026",
773
+ keywords: ["chart", "tree", "group", "item", "rename", "value"],
774
+ description: "Renames a node, sets an item's value or sets a node's colour (null for the palette).",
775
+ params: object(
776
+ {
777
+ path: TREE_PATH,
778
+ name: { type: "string", description: "New name." },
779
+ value: { type: "number", minimum: 0, description: "Items only: the new amount." },
780
+ color: { type: ["string", "null"], description: "CSS colour, or null for the palette colour." }
781
+ },
782
+ ["path"]
783
+ ),
784
+ run: (_ctx, params) => {
785
+ const { path, ...patch } = params;
786
+ const result = controller.updateTreeNode(path, patch);
787
+ check(result);
788
+ return { path: result.path };
789
+ }
790
+ },
791
+ {
792
+ ...base,
793
+ id: `${prefix}removeTreeNode`,
794
+ label: "Delete Item or Group",
795
+ keywords: ["chart", "tree", "group", "item", "remove", "delete"],
796
+ description: "Deletes a node of the grouped data with everything under it.",
797
+ params: object({ path: TREE_PATH }, ["path"]),
798
+ run: (_ctx, params) => {
799
+ check(controller.removeTreeNode(params.path));
800
+ return { groups: controller.getSpec().tree.map((n) => ({ name: n.name, total: chartTreeTotal(n) })) };
801
+ }
802
+ },
573
803
  {
574
804
  ...base,
575
805
  id: `${prefix}applyPreset`,
@@ -683,7 +913,7 @@ function createChartCommands(controller, options = {}) {
683
913
  run: () => {
684
914
  const s = controller.getSpec();
685
915
  const visible = s.series.filter((x) => !x.hidden);
686
- const colors = chartColorsByCategory(s.type) ? s.categories.map((_, i) => visible[0]?.pointColors?.[i] || chartSliceColor(s, i)) : visible.map((x) => chartSeriesColor(s, s.series.indexOf(x)));
916
+ const colors = chartSpecColorsByCategory(s) ? s.categories.map((_, i) => visible[0]?.pointColors?.[i] || chartSliceColor(s, i)) : visible.map((x) => chartSeriesColor(s, s.series.indexOf(x)));
687
917
  return { colors, ...checkChartColors(colors) };
688
918
  }
689
919
  },
@@ -1131,6 +1361,11 @@ function planChartToolPlayback(tool, args) {
1131
1361
  if (args.kind === "point" && typeof args.series === "string" && args.category !== void 0) return click(chartPointRef(args.series, args.category));
1132
1362
  return typeof args.kind === "string" && args.kind !== "none" ? click(control(args.kind)) : null;
1133
1363
  case "set_chart_data":
1364
+ case "set_chart_tree":
1365
+ case "import_chart_tree_csv":
1366
+ case "add_chart_tree_node":
1367
+ case "update_chart_tree_node":
1368
+ case "remove_chart_tree_node":
1134
1369
  case "import_chart_csv":
1135
1370
  case "import_chart_mermaid":
1136
1371
  case "import_chart_ooxml":
@@ -1144,6 +1379,19 @@ function planChartToolPlayback(tool, args) {
1144
1379
  case "add_chart_trendline":
1145
1380
  case "remove_chart_trendline":
1146
1381
  return click(control("trendline.add"));
1382
+ case "add_chart_reference_line":
1383
+ case "update_chart_reference_line":
1384
+ case "remove_chart_reference_line":
1385
+ return click(control("referenceLine.add"));
1386
+ case "add_chart_reference_band":
1387
+ case "update_chart_reference_band":
1388
+ case "remove_chart_reference_band":
1389
+ return click(control("referenceBand.add"));
1390
+ case "set_chart_callout":
1391
+ if (typeof args.series === "string" && (typeof args.category === "string" || typeof args.category === "number")) return [...click(chartPointRef(args.series, args.category)), ...click(control("series.callout"))];
1392
+ return click(control("series.callout"));
1393
+ case "highlight_chart":
1394
+ return click(control("highlight"));
1147
1395
  case "render_chart":
1148
1396
  return [{ type: "target", ref: { kind: "action", id: "download-png" } }];
1149
1397
  case "undo_chart":
@@ -1203,11 +1451,17 @@ function createChartToolProvider(controller, options = {}) {
1203
1451
  return index;
1204
1452
  };
1205
1453
  const table = () => chartDataToTable(spec());
1454
+ const treeTable = () => {
1455
+ const rows = chartTreeToRows(spec().tree);
1456
+ const depth = chartTreeDepth(spec().tree);
1457
+ return [[...Array.from({ length: depth }, (_, k) => k === 0 ? "Group" : k === depth - 1 ? "Item" : `Level ${k + 1}`), "Value"], ...rows.map((r) => [...r.path, ...Array(depth - r.path.length).fill(""), r.value])];
1458
+ };
1459
+ const treeSummary = () => ({ tree: spec().tree, groups: spec().tree.map((n) => ({ name: n.name, total: chartTreeTotal(n) })), depth: chartTreeDepth(spec().tree) });
1206
1460
  const Parser = () => options.DOMParser ?? globalThis.DOMParser;
1207
1461
  const getChart = {
1208
1462
  name: "get_chart",
1209
1463
  title: "Read the chart",
1210
- description: "Returns the chart spec (type, titles, axes, legend, series with ids and settings), its data as a table (header row of series names, then one row per category), the current selection, and a summary at the given size: per-series min / max / mean / trend, the axes as drawn, layout warnings (hidden labels, thinned lines), a colour check and a plain-language description. Use the series ids and category indexes it returns with the write tools.",
1464
+ description: "Returns the chart spec (type, titles, axes, legend, series with ids and settings), its data as a table (header row of series names, then one row per category), grouped data as treeTable (path of names to each item, then its value) when the chart has a tree, the current selection, and a summary at the given size: per-series min / max / mean / trend, the axes as drawn, layout warnings (hidden labels, thinned lines), a colour check and a plain-language description. Use the series ids and category indexes it returns with the write tools.",
1211
1465
  inputSchema: { type: "object", properties: { width: WIDTH, height: HEIGHT }, additionalProperties: false },
1212
1466
  annotations: { title: "Read the chart", ...READ },
1213
1467
  handler: ({ width = size.width, height = size.height }) => {
@@ -1217,6 +1471,7 @@ function createChartToolProvider(controller, options = {}) {
1217
1471
  table: table(),
1218
1472
  selection: controller.getState().selection,
1219
1473
  summary: summarizeChart(controller.toJSON(), { width, height }),
1474
+ ...spec().tree.length ? { treeTable: treeTable() } : {},
1220
1475
  issues: controller.getState().issues,
1221
1476
  ...reason ? { readOnly: reason } : {}
1222
1477
  };
@@ -1260,7 +1515,7 @@ function createChartToolProvider(controller, options = {}) {
1260
1515
  const checkColors = {
1261
1516
  name: "check_chart_colors",
1262
1517
  title: "Check chart colours",
1263
- description: "Checks that colours can be told apart with normal vision and with protanopia, deuteranopia and tritanopia (OKLab distance after simulation), and that they stand out from the background. Checks the chart's own series (or slice) colours unless colours are given. Returns the closest pair per vision, contrast ratios and problems as sentences.",
1518
+ description: "Checks whether the chart's colours are accessible: that colour-blind readers can tell them apart (protanopia, deuteranopia and tritanopia, by OKLab distance after simulation) as well as people with normal vision, and that they stand out from the background. Checks the chart's own series (or slice) colours unless colours are given. Returns the closest pair per vision, contrast ratios and problems as sentences.",
1264
1519
  inputSchema: {
1265
1520
  type: "object",
1266
1521
  properties: {
@@ -1273,7 +1528,7 @@ function createChartToolProvider(controller, options = {}) {
1273
1528
  handler: ({ colors, surface }) => {
1274
1529
  const s = spec();
1275
1530
  const visible = s.series.filter((x) => !x.hidden);
1276
- const own = chartColorsByCategory(s.type) ? s.categories.map((_, i) => visible[0]?.pointColors?.[i] || chartSliceColor(s, i)) : visible.map((x) => chartSeriesColor(s, s.series.indexOf(x)));
1531
+ const own = chartSpecColorsByCategory(s) ? s.categories.map((_, i) => visible[0]?.pointColors?.[i] || chartSliceColor(s, i)) : visible.map((x) => chartSeriesColor(s, s.series.indexOf(x)));
1277
1532
  return { colors: colors ?? own, ...checkChartColors(colors ?? own, { surface }) };
1278
1533
  }
1279
1534
  };
@@ -1341,7 +1596,7 @@ function createChartToolProvider(controller, options = {}) {
1341
1596
  const updateChart = {
1342
1597
  name: "update_chart",
1343
1598
  title: "Change chart presentation",
1344
- description: 'Changes how the chart looks, as one undo step: type, titles, axes (xAxis = categories or numeric x, yAxis = values, yAxis2 = secondary values; each can be reversed, and value axes can be logarithmic with scale "log"), legend, stacking, orientation, curve, points, data labels and their position, palette, donut hole, bar spacing, histogram bins, waterfall total, radar rings (radarTicks) and grid shape (radarGraticule). All-or-nothing: invalid values change nothing and come back as sentences. Returns the new spec.',
1599
+ description: 'Changes how the chart looks, as one undo step: type, titles, axes (xAxis = categories or numeric x, yAxis = values, yAxis2 = secondary values; each can be reversed, and value axes can be logarithmic with scale "log"), legend, stacking, orientation, curve, points, data labels and their position, palette, donut hole, bar spacing, histogram bins, waterfall total, radar rings (radarTicks) and grid shape (radarGraticule), note, highlight, reference lines and bands (whole lists), and varyColors. All-or-nothing: invalid values change nothing and come back as sentences. Returns the new spec.',
1345
1600
  inputSchema: {
1346
1601
  type: "object",
1347
1602
  properties: CHART_UPDATE_PROPERTIES,
@@ -1466,7 +1721,7 @@ function createChartToolProvider(controller, options = {}) {
1466
1721
  },
1467
1722
  annotations: { title: "Add a category", ...WRITE },
1468
1723
  handler: ({ label, at }) => {
1469
- const result = controller.addCategory(label, { at });
1724
+ const result = resolve(controller.addCategory(label, { at }));
1470
1725
  return { index: result.index, categories: spec().categories };
1471
1726
  }
1472
1727
  };
@@ -1565,6 +1820,168 @@ function createChartToolProvider(controller, options = {}) {
1565
1820
  return { series: s.id, trendlines: controller.getSeries(s.id)?.trendlines ?? [] };
1566
1821
  }
1567
1822
  };
1823
+ const referenceTools = (what) => {
1824
+ const Kind = what === "line" ? "Reference line" : "Reference band";
1825
+ const list = () => what === "line" ? spec().referenceLines : spec().referenceBands;
1826
+ const listKey = what === "line" ? "referenceLines" : "referenceBands";
1827
+ const add = {
1828
+ name: `add_chart_reference_${what}`,
1829
+ title: `Add a reference ${what}`,
1830
+ description: what === "line" ? "Draws a dashed line across the plot at one value: a target, a floor, an average (bar, line, area, scatter and bubble charts). The axis grows to keep it in view. Returns its index and the reference lines." : "Shades a band across the plot between two values: a target or normal range (bar, line, area, scatter and bubble charts), drawn under the data. The axis grows to keep it in view. Returns its index and the reference bands.",
1831
+ inputSchema: { type: "object", properties: what === "line" ? REFERENCE_LINE_PROPS : REFERENCE_BAND_PROPS, required: what === "line" ? ["value"] : ["from", "to"], additionalProperties: false },
1832
+ annotations: { title: `Add a reference ${what}`, ...WRITE },
1833
+ handler: (args) => {
1834
+ const result = resolve(what === "line" ? controller.addReferenceLine(args) : controller.addReferenceBand(args));
1835
+ return { index: result.index, [listKey]: list() };
1836
+ }
1837
+ };
1838
+ const update = {
1839
+ name: `update_chart_reference_${what}`,
1840
+ title: `Change a reference ${what}`,
1841
+ description: `Changes a reference ${what} by index (all-or-nothing); label, axis and color take null to remove them. Returns the ${what} as stored.`,
1842
+ inputSchema: { type: "object", properties: { index: REFERENCE_INDEX(Kind), ...what === "line" ? REFERENCE_LINE_PATCH : REFERENCE_BAND_PATCH }, required: ["index"], additionalProperties: false },
1843
+ annotations: { title: `Change a reference ${what}`, ...WRITE_IDEMPOTENT },
1844
+ handler: ({ index, ...patch }) => {
1845
+ if (!Object.keys(patch).length) fail2(`Nothing to change: pass at least one field besides index, e.g. {"index": ${index}, "label": "Target"}.`);
1846
+ resolve(what === "line" ? controller.updateReferenceLine(index, patch) : controller.updateReferenceBand(index, patch));
1847
+ return { index, [`reference${what === "line" ? "Line" : "Band"}`]: list()[index] };
1848
+ }
1849
+ };
1850
+ const remove = {
1851
+ name: `remove_chart_reference_${what}`,
1852
+ title: `Delete a reference ${what}`,
1853
+ description: `Deletes a reference ${what} by index; the ones after it move up one. Returns the reference ${what}s left.`,
1854
+ inputSchema: { type: "object", properties: { index: REFERENCE_INDEX(Kind) }, required: ["index"], additionalProperties: false },
1855
+ annotations: { title: `Delete a reference ${what}`, ...DESTRUCTIVE },
1856
+ handler: ({ index }) => {
1857
+ resolve(what === "line" ? controller.removeReferenceLine(index) : controller.removeReferenceBand(index));
1858
+ return { [listKey]: list() };
1859
+ }
1860
+ };
1861
+ return [add, update, remove];
1862
+ };
1863
+ const [addReferenceLine, updateReferenceLine, removeReferenceLine] = referenceTools("line");
1864
+ const [addReferenceBand, updateReferenceBand, removeReferenceBand] = referenceTools("band");
1865
+ const setCallout = {
1866
+ name: "set_chart_callout",
1867
+ title: "Pin a label to a point",
1868
+ description: 'Pins a short label to one bar or point, with a leader line, to say why it matters ("Record quarter", "Launch"); label null or "" removes it. Bar, line, area, scatter and bubble charts; the point must have a value. Selects the point and returns the series id, category index and label.',
1869
+ inputSchema: {
1870
+ type: "object",
1871
+ properties: { series: SERIES_REF, category: CATEGORY_REF, label: { type: ["string", "null"], description: "The label (keep it to a few words), or null to remove it." } },
1872
+ required: ["series", "category", "label"],
1873
+ additionalProperties: false
1874
+ },
1875
+ annotations: { title: "Pin a label to a point", ...WRITE_IDEMPOTENT },
1876
+ handler: ({ series, category, label }) => {
1877
+ const s = seriesById(series);
1878
+ const index = categoryIndex(category);
1879
+ resolve(controller.setCallout(s.id, index, label));
1880
+ return { series: s.id, index, category: spec().categories[index], label: controller.getSeries(s.id)?.callouts?.[index] ?? null };
1881
+ }
1882
+ };
1883
+ const highlight = {
1884
+ name: "highlight_chart",
1885
+ title: "Highlight categories or series",
1886
+ description: "Draws the named categories (labels) and series (names or ids) normally and mutes the rest, to draw attention to the marks the chart is about; [] shows everything again. A point stays bright when its category or its series is named. Unknown names change nothing and are reported. Returns the category indexes and series ids that matched.",
1887
+ inputSchema: {
1888
+ type: "object",
1889
+ properties: { names: { type: "array", items: { type: "string" }, description: "Category labels and / or series names or ids, exactly as get_chart shows them. [] clears the highlight." } },
1890
+ required: ["names"],
1891
+ additionalProperties: false
1892
+ },
1893
+ annotations: { title: "Highlight categories or series", ...WRITE_IDEMPOTENT },
1894
+ handler: ({ names }) => {
1895
+ const result = resolve(controller.setHighlight(names));
1896
+ const s = spec();
1897
+ return { highlight: s.highlight, categories: result.categories.map((index) => ({ index, label: s.categories[index] })), series: result.series.map((id) => ({ id, name: s.series.find((x) => x.id === id).name })) };
1898
+ }
1899
+ };
1900
+ const setTree = {
1901
+ name: "set_chart_tree",
1902
+ title: "Replace grouped data",
1903
+ description: `Replaces the chart's data with groups of items (a tree) for treemaps and sunbursts, as one undo step: items {"name", "value"} and groups {"name", "children"}, up to 6 levels, names unique among siblings. The top-level groups become the categories and their totals the first series, so other chart types draw the totals. [] goes back to plain data (the totals stay as values). Returns the tree, each group's total and the depth.`,
1904
+ inputSchema: { type: "object", properties: { tree: { type: "array", items: { $ref: "#/$defs/chartTreeNode" }, description: "The top-level nodes; [] removes the grouping." } }, required: ["tree"], additionalProperties: false, $defs: TREE_DEFS },
1905
+ annotations: { title: "Replace grouped data", ...WRITE_IDEMPOTENT },
1906
+ handler: ({ tree }) => {
1907
+ resolve(controller.setTree(tree));
1908
+ return treeSummary();
1909
+ }
1910
+ };
1911
+ const importTreeCsv = {
1912
+ name: "import_chart_tree_csv",
1913
+ title: "Import grouped data from CSV",
1914
+ description: "Replaces the data with grouped data from CSV or TSV: every column but the last holds names (group, subgroup, \u2026, item), the last holds the value. A blank group name repeats the one above, as spreadsheets lay out groups. One undo step. Returns the tree, group totals and depth.",
1915
+ inputSchema: {
1916
+ type: "object",
1917
+ properties: {
1918
+ csv: { type: "string", description: 'CSV or TSV text, e.g. "Region,Country,Customers\\nEurope,France,40\\n,Spain,25".' },
1919
+ header: { type: ["boolean", "string"], enum: [true, false, "auto"], description: "The first row holds column names (default auto: when its last cell is not a number)." }
1920
+ },
1921
+ required: ["csv"],
1922
+ additionalProperties: false
1923
+ },
1924
+ annotations: { title: "Import grouped data from CSV", ...WRITE },
1925
+ handler: ({ csv, header }) => {
1926
+ resolve(controller.importTreeTable(parseCsv(csv, { delimiter: csv.includes(" ") ? " " : "," }), { header }));
1927
+ return treeSummary();
1928
+ }
1929
+ };
1930
+ const addTreeNode = {
1931
+ name: "add_chart_tree_node",
1932
+ title: "Add an item or group",
1933
+ description: "Adds an item or a group (with children) under a group of the grouped data, or at the top level. Returns its path and its parent's new total.",
1934
+ inputSchema: {
1935
+ type: "object",
1936
+ properties: {
1937
+ parent: { type: "array", items: { type: "string" }, description: "Path of the group to add to; [] or omitted for the top level." },
1938
+ node: { $ref: "#/$defs/chartTreeNode", description: 'The item ({"name", "value"}) or group ({"name", "children"}) to add.' },
1939
+ at: { type: "integer", minimum: 0, description: "Position among its siblings (default: the end)." }
1940
+ },
1941
+ required: ["node"],
1942
+ additionalProperties: false,
1943
+ $defs: TREE_DEFS
1944
+ },
1945
+ annotations: { title: "Add an item or group", ...WRITE },
1946
+ handler: ({ parent = [], node, at }) => {
1947
+ const result = resolve(controller.addTreeNode(parent, node, { at }));
1948
+ const group = parent.length ? findChartTreeNode(spec().tree, parent) : null;
1949
+ return { path: result.path, parentTotal: group ? chartTreeTotal(group) : spec().tree.reduce((t, n) => t + chartTreeTotal(n), 0) };
1950
+ }
1951
+ };
1952
+ const updateTreeNode = {
1953
+ name: "update_chart_tree_node",
1954
+ title: "Change an item or group",
1955
+ description: "Renames a node, sets an item's value, or sets a node's colour (null goes back to the palette). Groups have no value of their own. Returns the node's path (new if renamed) and the node.",
1956
+ inputSchema: {
1957
+ type: "object",
1958
+ properties: {
1959
+ path: TREE_PATH,
1960
+ name: { type: "string", description: "New name (unique among its siblings)." },
1961
+ value: { type: "number", minimum: 0, description: "Items only: the new amount." },
1962
+ color: { type: ["string", "null"], description: "CSS colour, or null for the palette colour." }
1963
+ },
1964
+ required: ["path"],
1965
+ additionalProperties: false
1966
+ },
1967
+ annotations: { title: "Change an item or group", ...WRITE_IDEMPOTENT },
1968
+ handler: ({ path, ...patch }) => {
1969
+ if (!Object.keys(patch).length) fail2("Nothing to change: pass name, value or color with the path.");
1970
+ const result = resolve(controller.updateTreeNode(path, patch));
1971
+ return { path: result.path, node: findChartTreeNode(spec().tree, result.path) };
1972
+ }
1973
+ };
1974
+ const removeTreeNode = {
1975
+ name: "remove_chart_tree_node",
1976
+ title: "Delete an item or group",
1977
+ description: "Deletes a node of the grouped data with everything under it (a group left empty becomes an item with value 0). Returns the group totals left.",
1978
+ inputSchema: { type: "object", properties: { path: TREE_PATH }, required: ["path"], additionalProperties: false },
1979
+ annotations: { title: "Delete an item or group", ...DESTRUCTIVE },
1980
+ handler: ({ path }) => {
1981
+ resolve(controller.removeTreeNode(path));
1982
+ return { groups: treeSummary().groups };
1983
+ }
1984
+ };
1568
1985
  const applyPreset = {
1569
1986
  name: "apply_chart_preset",
1570
1987
  title: "Apply a chart style",
@@ -1731,12 +2148,45 @@ function createChartToolProvider(controller, options = {}) {
1731
2148
  }
1732
2149
  };
1733
2150
  const reads = [getChart, renderChart, checkColors, recommend, getTrendline, listPresets, exportMermaid, exportOoxml];
1734
- const writes = [updateChart, setData, setValues, addSeries, updateSeries, removeSeries, addCategory, removeCategory, importCsv, importMermaid, addTrendline, removeTrendline, applyPreset, transpose, select, drag, key, undo, redo];
2151
+ const writes = [
2152
+ updateChart,
2153
+ setData,
2154
+ setValues,
2155
+ addSeries,
2156
+ updateSeries,
2157
+ removeSeries,
2158
+ addCategory,
2159
+ removeCategory,
2160
+ importCsv,
2161
+ importMermaid,
2162
+ addTrendline,
2163
+ removeTrendline,
2164
+ addReferenceLine,
2165
+ updateReferenceLine,
2166
+ removeReferenceLine,
2167
+ addReferenceBand,
2168
+ updateReferenceBand,
2169
+ removeReferenceBand,
2170
+ setCallout,
2171
+ highlight,
2172
+ setTree,
2173
+ importTreeCsv,
2174
+ addTreeNode,
2175
+ updateTreeNode,
2176
+ removeTreeNode,
2177
+ applyPreset,
2178
+ transpose,
2179
+ select,
2180
+ drag,
2181
+ key,
2182
+ undo,
2183
+ redo
2184
+ ];
1735
2185
  return withChartPlayback({
1736
2186
  id: options.id ?? "chart",
1737
2187
  namespace: options.namespace,
1738
2188
  title: "Chart editor",
1739
- description: "One chart: its spec, data and values, series and categories, trendlines and presets, CSV, Mermaid and OOXML import, rendering and colour checks.",
2189
+ description: "One chart: its spec, data and values, series and categories, trendlines, reference lines and bands, callouts, highlight, grouped data and presets, CSV, Mermaid and OOXML import, rendering and colour checks.",
1740
2190
  skill: "pixerate-chart",
1741
2191
  tools: () => {
1742
2192
  if (readOnlyReason()) return reads;
@@ -2231,6 +2681,8 @@ export {
2231
2681
  CHART_LABEL_POSITIONS,
2232
2682
  CHART_LAYOUT_PRESETS,
2233
2683
  CHART_LEGEND_POSITIONS,
2684
+ CHART_LIKERT_NEUTRALS,
2685
+ CHART_LIKERT_SORTS,
2234
2686
  CHART_MARKERS,
2235
2687
  CHART_MERMAID_META_PREFIX,
2236
2688
  CHART_NUMBER_STYLES,
@@ -2242,6 +2694,7 @@ export {
2242
2694
  CHART_PRESENCE_COLORS,
2243
2695
  CHART_RADAR_GRATICULES,
2244
2696
  CHART_RASTER_MAX_SIZE,
2697
+ CHART_REFERENCE_AXES,
2245
2698
  CHART_SERIES_TYPES,
2246
2699
  CHART_STACKINGS,
2247
2700
  CHART_TRENDLINE_TYPES,
@@ -2257,8 +2710,11 @@ export {
2257
2710
  MAX_CHART_DATA_LABELS,
2258
2711
  MAX_CHART_LINE_POINTS,
2259
2712
  MAX_CHART_MARKERS,
2713
+ MAX_CHART_TREE_DEPTH,
2714
+ MAX_CHART_TREE_NODES,
2260
2715
  OfficeChartsError,
2261
2716
  RENDER_CHART_INSTRUCTIONS,
2717
+ addChartTreeRow,
2262
2718
  analyzeChartTable,
2263
2719
  blendChartScenes,
2264
2720
  canDragChartPoint,
@@ -2282,6 +2738,7 @@ export {
2282
2738
  chartFromTable,
2283
2739
  chartHistogram,
2284
2740
  chartHitTest,
2741
+ chartLikertColor,
2285
2742
  chartLuminance,
2286
2743
  chartMermaidFamily,
2287
2744
  chartMovingAverage,
@@ -2301,6 +2758,7 @@ export {
2301
2758
  chartSeriesColor,
2302
2759
  chartSeriesType,
2303
2760
  chartSliceColor,
2761
+ chartSpecColorsByCategory,
2304
2762
  chartSquarify,
2305
2763
  chartSupportsTrendlines,
2306
2764
  chartTextBaseline,
@@ -2309,12 +2767,21 @@ export {
2309
2767
  chartToMermaid,
2310
2768
  chartToOoxml,
2311
2769
  chartToSvg,
2770
+ chartTreeColumnLabels,
2771
+ chartTreeDepth,
2772
+ chartTreeFromRows,
2773
+ chartTreeFromSeries,
2774
+ chartTreeFromTable,
2775
+ chartTreeToRows,
2776
+ chartTreeTotal,
2312
2777
  chartTrendlineName,
2313
2778
  chartValueAtPoint,
2779
+ chartVariesColors,
2314
2780
  chartXAtPoint,
2315
2781
  checkChartColors,
2316
2782
  cloneChartSeries,
2317
2783
  cloneChartSpec,
2784
+ cloneChartTree,
2318
2785
  compileChartFormatCode,
2319
2786
  contrastingTextColor,
2320
2787
  createChartCommands,
@@ -2340,6 +2807,7 @@ export {
2340
2807
  extractOfficeCharts,
2341
2808
  extractPptxCharts,
2342
2809
  extractXlsxCharts,
2810
+ findChartTreeNode,
2343
2811
  findMermaidCharts,
2344
2812
  fitChartTrendline,
2345
2813
  formatChartAmountList,
@@ -2359,7 +2827,10 @@ export {
2359
2827
  niceStep,
2360
2828
  normalizeChartAxis,
2361
2829
  normalizeChartErrorBars,
2830
+ normalizeChartReferenceBand,
2831
+ normalizeChartReferenceLine,
2362
2832
  normalizeChartSpec,
2833
+ normalizeChartTree,
2363
2834
  normalizeChartTrendline,
2364
2835
  normalizeChartValues,
2365
2836
  parseChartAmountList,
@@ -2373,8 +2844,11 @@ export {
2373
2844
  realChartClock,
2374
2845
  recommendChartTypes,
2375
2846
  recommendForShape,
2847
+ removeChartTreeRow,
2376
2848
  resolveChartSvgPaints,
2377
2849
  sameChartSelection,
2850
+ setChartTreeRowName,
2851
+ setChartTreeRowValue,
2378
2852
  shadeChartColor,
2379
2853
  simulateChartVision,
2380
2854
  snapChartDragValue,
@@ -2382,6 +2856,7 @@ export {
2382
2856
  sparklineToSvg,
2383
2857
  startChartPointDrag,
2384
2858
  stepDecimals,
2859
+ suggestChartReferences,
2385
2860
  summarizeChart,
2386
2861
  summarizeChartSeries,
2387
2862
  trendNumberText,