@pixerate/editor 0.162.1 → 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 (57) 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/canvas/index.cjs +6 -6
  5. package/dist/canvas/index.js +2 -2
  6. package/dist/chart/commands.d.cts +2 -1
  7. package/dist/chart/commands.d.ts +2 -1
  8. package/dist/chart/controller.d.cts +109 -1
  9. package/dist/chart/controller.d.ts +109 -1
  10. package/dist/chart/index.cjs +605 -130
  11. package/dist/chart/index.d.cts +1 -0
  12. package/dist/chart/index.d.ts +1 -0
  13. package/dist/chart/index.js +490 -15
  14. package/dist/chart/layout-annotations.d.cts +29 -0
  15. package/dist/chart/layout-annotations.d.ts +29 -0
  16. package/dist/chart/layout-families.d.cts +23 -0
  17. package/dist/chart/layout-families.d.ts +23 -0
  18. package/dist/chart/mermaid.d.cts +2 -1
  19. package/dist/chart/mermaid.d.ts +2 -1
  20. package/dist/chart/schemas.d.cts +13 -0
  21. package/dist/chart/schemas.d.ts +13 -0
  22. package/dist/chart/spec.d.cts +30 -5
  23. package/dist/chart/spec.d.ts +30 -5
  24. package/dist/chart/stats.d.cts +9 -1
  25. package/dist/chart/stats.d.ts +9 -1
  26. package/dist/chart/tools.d.cts +1 -1
  27. package/dist/chart/tools.d.ts +1 -1
  28. package/dist/chart/tree.d.cts +62 -0
  29. package/dist/chart/tree.d.ts +62 -0
  30. package/dist/chart/types.d.cts +77 -3
  31. package/dist/chart/types.d.ts +77 -3
  32. package/dist/{chunk-7YBDRJXT.cjs → chunk-22KLZZGH.cjs} +8 -8
  33. package/dist/{chunk-HLOKB7WW.js → chunk-3NEZJCBY.js} +366 -6
  34. package/dist/{chunk-EVPZ5IKN.js → chunk-5FNGLV2D.js} +65 -3
  35. package/dist/{chunk-EQ46F75O.cjs → chunk-D54JHQK2.cjs} +51 -51
  36. package/dist/{chunk-NO5QQDHZ.js → chunk-DAPQGA55.js} +2 -2
  37. package/dist/{chunk-3IHNXRUV.cjs → chunk-GKNEJ6EN.cjs} +399 -67
  38. package/dist/{chunk-4NGVHHJB.cjs → chunk-NZD2MZJC.cjs} +80 -18
  39. package/dist/{chunk-CX6JLDFC.js → chunk-OXERWBKE.js} +3 -3
  40. package/dist/{chunk-7CKPUUN4.js → chunk-POR54B55.js} +61 -10
  41. package/dist/{chunk-LL3H5XUH.cjs → chunk-R3P2M7HU.cjs} +367 -7
  42. package/dist/{chunk-HDGBM7EA.cjs → chunk-SBQVEBSU.cjs} +580 -53
  43. package/dist/{chunk-XDCFJEU7.js → chunk-SZA42R4N.js} +346 -14
  44. package/dist/{chunk-GLMP22FT.js → chunk-TALQONZ5.js} +3 -3
  45. package/dist/{chunk-NA4UVVJ4.cjs → chunk-YGG7WDWT.cjs} +76 -25
  46. package/dist/{chunk-EY22AY6R.cjs → chunk-YSAGBIRW.cjs} +16 -16
  47. package/dist/{chunk-DTSTNRPH.js → chunk-Z4P2RBMJ.js} +536 -9
  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/dist/paint-editor/index.cjs +0 -20
  55. package/dist/paint-editor/index.js +0 -20
  56. package/package.json +1 -1
  57. package/skills/pixerate-canvas/SKILL.md +16 -0
package/README.md CHANGED
@@ -473,7 +473,7 @@ Each module is also available as a subpath import:
473
473
  | `@pixerate/editor/spreadsheet` | `SpreadsheetController`, formula parser/evaluator and dependency graph, formula function registry (`registerFormulaFunction`, `listFormulaFunctions`, `searchFormulaFunctions`, `getFormulaSignature`) and autocomplete helpers (`getFormulaHints`, `applyFormulaSuggestion`) |
474
474
  | `@pixerate/editor/image-editor` | `ImageEditorController` and Canvas 2D renderer: crop, adjustments, annotations, depth masks, selections and layer masks, and AI hooks. Needs a DOM/canvas environment (the selection algorithms themselves are pure). |
475
475
  | `@pixerate/editor/animation` | The keyframe model without canvas nodes: `AnimationTrack` / `AnimationKeyframe`, easing (`resolveEasing`, `evaluateEasing`, `cubicBezierAt`, `springAt`, presets, `parseCssEasing`, `easingToCss`), `evaluateTrack`, `interpolateAnimationValue`, `normalizeKeyframes`, OKLab colour mixing, `AnimationPlayer` and the `Clock` / `ManualClock` / `realClock` time sources (no third-party imports) |
476
- | `@pixerate/editor/canvas` | Node-graph layout (needs the optional `@dagrejs/dagre` peer), placement, trajectories, displacement, clipboard and streaming layout helpers, and node keyframe animation (re-exports everything in `/animation`) |
476
+ | `@pixerate/editor/canvas` | Node-graph layout (needs the optional `@dagrejs/dagre` peer), placement, trajectories, displacement, node explosion (pure layout, headless explode / collapse state and agent tools), clipboard and streaming layout helpers, and node keyframe animation (re-exports everything in `/animation`) |
477
477
  | `@pixerate/editor/agent` | MCP tool schemas, a planner for agent-driven canvas edits, and the dynamic `ToolRegistry` with editor/spreadsheet tool providers |
478
478
  | `@pixerate/editor/tools` | `ToolRegistry`, tool types, `validateJsonSchema` and the static MCP tool definitions, without TipTap or dagre (no third-party imports) |
479
479
  | `@pixerate/editor/commands` | `CommandRegistry`, `ShortcutMap`, palette ranking, `createCommandToolProvider` and built-in history / arrange / spreadsheet commands (no third-party imports) |
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- var _chunk4NGVHHJBcjs = require('../chunk-4NGVHHJB.cjs');
5
+ var _chunkNZD2MZJCcjs = require('../chunk-NZD2MZJC.cjs');
6
6
 
7
7
 
8
8
  var _chunkGLQQ2VILcjs = require('../chunk-GLQQ2VIL.cjs');
@@ -115,15 +115,15 @@ var _chunkN2FGYZ4Qcjs = require('../chunk-N2FGYZ4Q.cjs');
115
115
 
116
116
 
117
117
 
118
- var _chunkEY22AY6Rcjs = require('../chunk-EY22AY6R.cjs');
118
+ var _chunkYSAGBIRWcjs = require('../chunk-YSAGBIRW.cjs');
119
119
 
120
120
 
121
- var _chunk3IHNXRUVcjs = require('../chunk-3IHNXRUV.cjs');
122
- require('../chunk-HDGBM7EA.cjs');
121
+ var _chunkGKNEJ6ENcjs = require('../chunk-GKNEJ6EN.cjs');
122
+ require('../chunk-SBQVEBSU.cjs');
123
123
 
124
124
 
125
125
 
126
- var _chunkLL3H5XUHcjs = require('../chunk-LL3H5XUH.cjs');
126
+ var _chunkR3P2M7HUcjs = require('../chunk-R3P2M7HU.cjs');
127
127
 
128
128
 
129
129
 
@@ -624,14 +624,14 @@ var SIZE_WIDTH = {
624
624
  };
625
625
  var SIZE_HEIGHT = { type: "number", minimum: 50, maximum: 4096, description: "Height in pixels (default 320)." };
626
626
  var SPEC_PROPERTIES = {
627
- ..._chunk4NGVHHJBcjs.CHART_UPDATE_PROPERTIES,
627
+ ..._chunkNZD2MZJCcjs.CHART_UPDATE_PROPERTIES,
628
628
  categories: { type: "array", items: { type: "string" }, description: "Category labels in order (x axis labels, or pie slices)." },
629
629
  series: {
630
630
  type: "array",
631
631
  description: "The series, each with one value per category (padded with gaps).",
632
632
  items: {
633
633
  type: "object",
634
- properties: { id: { type: "string", description: "Stable id (default: from the name)." }, ..._chunk4NGVHHJBcjs.SERIES_PROPS },
634
+ properties: { id: { type: "string", description: "Stable id (default: from the name)." }, ..._chunkNZD2MZJCcjs.SERIES_PROPS },
635
635
  required: ["name", "values"],
636
636
  additionalProperties: false
637
637
  }
@@ -642,7 +642,7 @@ function cleanSeries(series) {
642
642
  return series.map((s) => s && typeof s === "object" ? Object.fromEntries(Object.entries(s).filter(([, v]) => v !== null)) : s);
643
643
  }
644
644
  function checkedSpec(input) {
645
- const { spec, issues } = _chunkLL3H5XUHcjs.normalizeChartSpec.call(void 0, { ...input, ...input.series !== void 0 ? { series: cleanSeries(input.series) } : {} });
645
+ const { spec, issues } = _chunkR3P2M7HUcjs.normalizeChartSpec.call(void 0, { ...input, ...input.series !== void 0 ? { series: cleanSeries(input.series) } : {} });
646
646
  if (issues.length) throw new Error(`The chart was not changed: ${issues.map((i) => i.message).join(" ")}`);
647
647
  return spec;
648
648
  }
@@ -657,14 +657,14 @@ function describe(chart, includeSpec) {
657
657
  series: spec.series.map((s) => ({ id: s.id, name: s.name })),
658
658
  width: _nullishCoalesce(node.attrs.width, () => ( null)),
659
659
  height: node.attrs.height,
660
- description: _chunk3IHNXRUVcjs.describeChart.call(void 0, spec),
660
+ description: _chunkGKNEJ6ENcjs.describeChart.call(void 0, spec),
661
661
  ...includeSpec ? { spec } : {}
662
662
  };
663
663
  }
664
664
  function sparklines(doc) {
665
665
  const found = [];
666
666
  doc.descendants((node, pos) => {
667
- if (node.type.name === "sparkline") found.push({ pos, kind: node.attrs.kind, values: node.attrs.values, label: _chunkEY22AY6Rcjs.sparklineLabel.call(void 0, node) });
667
+ if (node.type.name === "sparkline") found.push({ pos, kind: node.attrs.kind, values: node.attrs.values, label: _chunkYSAGBIRWcjs.sparklineLabel.call(void 0, node) });
668
668
  });
669
669
  return found;
670
670
  }
@@ -675,7 +675,7 @@ function checkPosition(editor, at) {
675
675
  function createDocumentChartTools(editor) {
676
676
  const chartType = () => editor().schema.nodes.chart;
677
677
  const findChart = (args) => {
678
- const charts = _chunkEY22AY6Rcjs.getDocumentCharts.call(void 0, editor().state.doc);
678
+ const charts = _chunkYSAGBIRWcjs.getDocumentCharts.call(void 0, editor().state.doc);
679
679
  const list = charts.map((c) => `"${c.id}" at ${c.pos}`).join(", ") || "none; add one with insert_chart";
680
680
  if (args.chartId !== void 0) {
681
681
  const chart = charts.find((c) => c.id === args.chartId);
@@ -702,7 +702,7 @@ function createDocumentChartTools(editor) {
702
702
  annotations: { title: "List charts in the document", ...READ },
703
703
  handler: ({ includeSpec = false }) => {
704
704
  const doc = editor().state.doc;
705
- return { charts: _chunkEY22AY6Rcjs.getDocumentCharts.call(void 0, doc).map((c) => describe(c, includeSpec)), sparklines: editor().schema.nodes.sparkline ? sparklines(doc) : [] };
705
+ return { charts: _chunkYSAGBIRWcjs.getDocumentCharts.call(void 0, doc).map((c) => describe(c, includeSpec)), sparklines: editor().schema.nodes.sparkline ? sparklines(doc) : [] };
706
706
  }
707
707
  };
708
708
  const insertChart = {
@@ -729,7 +729,7 @@ function createDocumentChartTools(editor) {
729
729
  const node = { type: "chart", attrs: { id, spec, width, ...height !== void 0 ? { height } : {} } };
730
730
  const chain = ed.chain().command(({ tr }) => (_history.closeHistory.call(void 0, tr), true));
731
731
  const ok = (at !== void 0 ? chain.insertContentAt(at, node) : chain.insertContent(node)).run();
732
- const chart = _chunkEY22AY6Rcjs.getDocumentCharts.call(void 0, ed.state.doc).find((c) => c.id === id);
732
+ const chart = _chunkYSAGBIRWcjs.getDocumentCharts.call(void 0, ed.state.doc).find((c) => c.id === id);
733
733
  if (!ok || !chart) throw new Error(`A chart cannot go at ${_nullishCoalesce(at, () => ( ed.state.selection.from))}; pass a position between blocks or inside a paragraph.`);
734
734
  return { id: chart.id, pos: chart.pos, spec: chart.spec, width: chart.node.attrs.width, height: chart.node.attrs.height };
735
735
  }
@@ -776,8 +776,8 @@ function createDocumentChartTools(editor) {
776
776
  inputSchema: {
777
777
  type: "object",
778
778
  properties: {
779
- values: { type: "array", items: _chunk4NGVHHJBcjs.VALUE, minItems: 1, maxItems: _chunkEY22AY6Rcjs.MAX_SPARKLINE_VALUES, description: "Values in order (null for a gap)." },
780
- kind: { type: "string", enum: [..._chunkEY22AY6Rcjs.SPARKLINE_KINDS], description: "line (default), column, or win-loss (sign only)." },
779
+ values: { type: "array", items: _chunkNZD2MZJCcjs.VALUE, minItems: 1, maxItems: _chunkYSAGBIRWcjs.MAX_SPARKLINE_VALUES, description: "Values in order (null for a gap)." },
780
+ kind: { type: "string", enum: [..._chunkYSAGBIRWcjs.SPARKLINE_KINDS], description: "line (default), column, or win-loss (sign only)." },
781
781
  at: { type: "integer", minimum: 0, description: "Document position inside a paragraph (default: the selection)." },
782
782
  width: { type: "number", minimum: 4, maximum: 1e3, description: "Width in pixels (default 80)." },
783
783
  height: { type: "number", minimum: 4, maximum: 200, description: "Height in pixels (default 18)." },
@@ -791,12 +791,12 @@ function createDocumentChartTools(editor) {
791
791
  handler: ({ values, kind = "line", at, width = 80, height = 18, color = null, label = null }) => {
792
792
  const ed = editor();
793
793
  checkPosition(ed, at);
794
- const parsed = values.map((v) => _chunkLL3H5XUHcjs.parseChartValue.call(void 0, v));
794
+ const parsed = values.map((v) => _chunkR3P2M7HUcjs.parseChartValue.call(void 0, v));
795
795
  const bad = parsed.findIndex((v) => v === void 0);
796
796
  if (bad >= 0) throw new Error(`values[${bad}] ("${String(values[bad])}") is not a number; pass numbers, numeric text or null. Nothing was inserted.`);
797
797
  const pos = _nullishCoalesce(at, () => ( ed.state.selection.from));
798
798
  if (!ed.state.doc.resolve(pos).parent.inlineContent) throw new Error(`Position ${pos} is between blocks; a sparkline goes inside a paragraph (use a position from get_text {blocks: true}).`);
799
- const stored = _chunkEY22AY6Rcjs.normalizeSparklineValues.call(void 0, parsed);
799
+ const stored = _chunkYSAGBIRWcjs.normalizeSparklineValues.call(void 0, parsed);
800
800
  ed.chain().command(({ tr }) => (_history.closeHistory.call(void 0, tr), true)).insertContentAt(pos, { type: "sparkline", attrs: { values: stored, kind, width, height, color, label } }).run();
801
801
  return { pos, kind, values: stored };
802
802
  }
@@ -1134,8 +1134,8 @@ function createTextPresence(editor, providerId, option) {
1134
1134
  const config = option === false ? null : option === true || option === void 0 ? {} : option;
1135
1135
  const caret = {
1136
1136
  id: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _43 => _43.id]), () => ( providerId)),
1137
- name: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _44 => _44.name]), () => ( _chunkEY22AY6Rcjs.DEFAULT_AGENT_CARET_NAME)),
1138
- color: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _45 => _45.color]), () => ( _chunkEY22AY6Rcjs.DEFAULT_AGENT_CARET_COLOR))
1137
+ name: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _44 => _44.name]), () => ( _chunkYSAGBIRWcjs.DEFAULT_AGENT_CARET_NAME)),
1138
+ color: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _45 => _45.color]), () => ( _chunkYSAGBIRWcjs.DEFAULT_AGENT_CARET_COLOR))
1139
1139
  };
1140
1140
  const typing = !_optionalChain([config, 'optionalAccess', _46 => _46.typing]) ? null : config.typing === true ? {} : config.typing;
1141
1141
  const idleMs = _nullishCoalesce(_optionalChain([config, 'optionalAccess', _47 => _47.idleMs]), () => ( 12e3));
@@ -1148,19 +1148,19 @@ function createTextPresence(editor, providerId, option) {
1148
1148
  };
1149
1149
  const touch = () => {
1150
1150
  clearTimeout(idleTimer);
1151
- if (idleMs > 0) idleTimer = setTimeout(() => live() && _chunkEY22AY6Rcjs.clearAgentCaret.call(void 0, live(), caret.id), idleMs);
1151
+ if (idleMs > 0) idleTimer = setTimeout(() => live() && _chunkYSAGBIRWcjs.clearAgentCaret.call(void 0, live(), caret.id), idleMs);
1152
1152
  };
1153
1153
  const tint = (ed, ranges) => {
1154
1154
  clearTimeout(tintTimer);
1155
- _chunkEY22AY6Rcjs.markAgentChanges.call(void 0, ed, caret.id, ranges);
1156
- if (changedMs > 0 && ranges.length) tintTimer = setTimeout(() => live() && _chunkEY22AY6Rcjs.markAgentChanges.call(void 0, live(), caret.id, []), changedMs);
1155
+ _chunkYSAGBIRWcjs.markAgentChanges.call(void 0, ed, caret.id, ranges);
1156
+ if (changedMs > 0 && ranges.length) tintTimer = setTimeout(() => live() && _chunkYSAGBIRWcjs.markAgentChanges.call(void 0, live(), caret.id, []), changedMs);
1157
1157
  };
1158
1158
  return {
1159
1159
  /** Puts the caret at `head`, selecting from `anchor`. */
1160
1160
  show(anchor, head = anchor) {
1161
1161
  const ed = live();
1162
1162
  if (!ed) return;
1163
- _chunkEY22AY6Rcjs.setAgentCaret.call(void 0, ed, { ...caret, from: anchor, to: head });
1163
+ _chunkYSAGBIRWcjs.setAgentCaret.call(void 0, ed, { ...caret, from: anchor, to: head });
1164
1164
  touch();
1165
1165
  },
1166
1166
  /** Shows the caret after ranges just changed by a tool, tinting them. */
@@ -1168,7 +1168,7 @@ function createTextPresence(editor, providerId, option) {
1168
1168
  const ed = live();
1169
1169
  if (!ed || !ranges.length) return;
1170
1170
  const last = ranges[ranges.length - 1];
1171
- _chunkEY22AY6Rcjs.setAgentCaret.call(void 0, ed, { ...caret, from: last.to });
1171
+ _chunkYSAGBIRWcjs.setAgentCaret.call(void 0, ed, { ...caret, from: last.to });
1172
1172
  tint(ed, ranges);
1173
1173
  touch();
1174
1174
  },
@@ -1176,12 +1176,12 @@ function createTextPresence(editor, providerId, option) {
1176
1176
  async write(ed, from, to, text, signal) {
1177
1177
  if (live() && typing) {
1178
1178
  clearTimeout(tintTimer);
1179
- const range2 = await _chunkEY22AY6Rcjs.typeAgentText.call(void 0, ed, { ...typing, from, to, text, caret, signal });
1180
- if (changedMs > 0) tintTimer = setTimeout(() => live() && _chunkEY22AY6Rcjs.markAgentChanges.call(void 0, live(), caret.id, []), changedMs);
1179
+ const range2 = await _chunkYSAGBIRWcjs.typeAgentText.call(void 0, ed, { ...typing, from, to, text, caret, signal });
1180
+ if (changedMs > 0) tintTimer = setTimeout(() => live() && _chunkYSAGBIRWcjs.markAgentChanges.call(void 0, live(), caret.id, []), changedMs);
1181
1181
  touch();
1182
1182
  return range2;
1183
1183
  }
1184
- const tr = _history.closeHistory.call(void 0, _chunkEY22AY6Rcjs.replaceWithTextTransaction.call(void 0, ed.state, from, to, text));
1184
+ const tr = _history.closeHistory.call(void 0, _chunkYSAGBIRWcjs.replaceWithTextTransaction.call(void 0, ed.state, from, to, text));
1185
1185
  const end = tr.mapping.map(to, 1);
1186
1186
  const range = { from: Math.min(tr.mapping.map(from, -1), end), to: end };
1187
1187
  ed.view.dispatch(tr.scrollIntoView());
@@ -1210,7 +1210,7 @@ function findMatches(editor, query, args, replacement) {
1210
1210
  wholeWord: !!args.wholeWord,
1211
1211
  ...args.regex ? { regex: true } : { literal: true }
1212
1212
  };
1213
- const result = _chunkEY22AY6Rcjs.searchDocument.call(void 0, editor.state.doc, query, options, replacement !== void 0 ? { replacement } : {});
1213
+ const result = _chunkYSAGBIRWcjs.searchDocument.call(void 0, editor.state.doc, query, options, replacement !== void 0 ? { replacement } : {});
1214
1214
  if (result.error) throw new Error(`Invalid search pattern: ${result.error.message}`);
1215
1215
  return { matches: result.matches, truncated: result.truncated };
1216
1216
  }
@@ -1372,7 +1372,7 @@ function createRichTextToolProvider(target, options) {
1372
1372
  replacement: String(replace).replace(/\r\n?|\n/g, "\r")
1373
1373
  }));
1374
1374
  const tr = _history.closeHistory.call(void 0, ed.state.tr);
1375
- const ends = _chunkEY22AY6Rcjs.applyReplacements.call(void 0, tr, chosen);
1375
+ const ends = _chunkYSAGBIRWcjs.applyReplacements.call(void 0, tr, chosen);
1376
1376
  ed.view.dispatch(tr.scrollIntoView());
1377
1377
  const ranges = chosen.map((m, i) => ({ from: tr.mapping.map(m.from, -1), to: ends[i] }));
1378
1378
  presence.changed(ranges.filter((r) => r.from < r.to));
@@ -1473,7 +1473,7 @@ function createRichTextToolProvider(target, options) {
1473
1473
  inputSchema: {
1474
1474
  type: "object",
1475
1475
  properties: {
1476
- operation: { type: "string", enum: _chunkEY22AY6Rcjs.TABLE_ACTIONS.map((a) => a.action), description: "Table operation." },
1476
+ operation: { type: "string", enum: _chunkYSAGBIRWcjs.TABLE_ACTIONS.map((a) => a.action), description: "Table operation." },
1477
1477
  at: { type: "integer", minimum: 0, description: "Document position to place the cursor first (e.g. inside a cell)." },
1478
1478
  rows: { type: "integer", minimum: 1, maximum: 100, description: "insertTable: rows (default 3)." },
1479
1479
  cols: { type: "integer", minimum: 1, maximum: 50, description: "insertTable: columns (default 3)." },
@@ -1503,10 +1503,10 @@ function createRichTextToolProvider(target, options) {
1503
1503
  ed.view.dispatch(ed.state.tr.setSelection(_state.TextSelection.near(ed.state.doc.resolve(at))));
1504
1504
  }
1505
1505
  const action = operation;
1506
- const state = _chunkEY22AY6Rcjs.getTableActionState.call(void 0, ed, action, params);
1506
+ const state = _chunkYSAGBIRWcjs.getTableActionState.call(void 0, ed, action, params);
1507
1507
  if (state !== true) throw new Error(state);
1508
- _chunkEY22AY6Rcjs.runTableAction.call(void 0, ed, action, params);
1509
- const table = _chunkEY22AY6Rcjs.getTableState.call(void 0, ed);
1508
+ _chunkYSAGBIRWcjs.runTableAction.call(void 0, ed, action, params);
1509
+ const table = _chunkYSAGBIRWcjs.getTableState.call(void 0, ed);
1510
1510
  return {
1511
1511
  operation,
1512
1512
  table: table.inTable ? { rows: table.rows, columns: table.columns, row: table.row, column: table.column } : null,
@@ -1525,7 +1525,7 @@ function createRichTextToolProvider(target, options) {
1525
1525
  if (!ed || ed.isDestroyed) return [];
1526
1526
  if (!ed.isEditable) return [getText, findText, ...charts.read()];
1527
1527
  const tools = [getText, findText, insertText, replaceText, replaceRange, replaceSelection, setSelection, ...formatting.tools(ed)];
1528
- return [...tools, ..._chunkEY22AY6Rcjs.isTableEnabled.call(void 0, ed) ? [editTable] : [], ...charts.read(), ...charts.write().map(withCaret)];
1528
+ return [...tools, ..._chunkYSAGBIRWcjs.isTableEnabled.call(void 0, ed) ? [editTable] : [], ...charts.read(), ...charts.write().map(withCaret)];
1529
1529
  },
1530
1530
  subscribe: (notify) => {
1531
1531
  const ed = editor();
@@ -2,7 +2,7 @@ import {
2
2
  CHART_UPDATE_PROPERTIES,
3
3
  SERIES_PROPS,
4
4
  VALUE
5
- } from "../chunk-EVPZ5IKN.js";
5
+ } from "../chunk-5FNGLV2D.js";
6
6
  import {
7
7
  hasVariantCommands
8
8
  } from "../chunk-3TNA7JKI.js";
@@ -115,15 +115,15 @@ import {
115
115
  setAgentCaret,
116
116
  sparklineLabel,
117
117
  typeAgentText
118
- } from "../chunk-CX6JLDFC.js";
118
+ } from "../chunk-OXERWBKE.js";
119
119
  import {
120
120
  describeChart
121
- } from "../chunk-XDCFJEU7.js";
122
- import "../chunk-DTSTNRPH.js";
121
+ } from "../chunk-SZA42R4N.js";
122
+ import "../chunk-Z4P2RBMJ.js";
123
123
  import {
124
124
  normalizeChartSpec,
125
125
  parseChartValue
126
- } from "../chunk-HLOKB7WW.js";
126
+ } from "../chunk-3NEZJCBY.js";
127
127
  import {
128
128
  getEditorMarkdown,
129
129
  getEditorText
@@ -113,10 +113,10 @@ var _chunkPY4GWSE2cjs = require('../chunk-PY4GWSE2.cjs');
113
113
  var _chunkN2FGYZ4Qcjs = require('../chunk-N2FGYZ4Q.cjs');
114
114
 
115
115
 
116
- var _chunkHDGBM7EAcjs = require('../chunk-HDGBM7EA.cjs');
116
+ var _chunkSBQVEBSUcjs = require('../chunk-SBQVEBSU.cjs');
117
117
 
118
118
 
119
- var _chunkLL3H5XUHcjs = require('../chunk-LL3H5XUH.cjs');
119
+ var _chunkR3P2M7HUcjs = require('../chunk-R3P2M7HU.cjs');
120
120
  require('../chunk-55AKPTLM.cjs');
121
121
 
122
122
 
@@ -8871,7 +8871,7 @@ function xyChartSpec(graph, palette) {
8871
8871
  );
8872
8872
  }
8873
8873
  const bars = graph.nodes.some((n3) => n3.shape === "bar");
8874
- return _chunkLL3H5XUHcjs.createChartSpec.call(void 0, {
8874
+ return _chunkR3P2M7HUcjs.createChartSpec.call(void 0, {
8875
8875
  type: bars ? "bar" : "line",
8876
8876
  title: _nullishCoalesce(graph.title, () => ( "")),
8877
8877
  categories,
@@ -8885,7 +8885,7 @@ function xyChartSpec(graph, palette) {
8885
8885
  }
8886
8886
  function radarChartSpec(graph, palette) {
8887
8887
  const data = _nullishCoalesce(graph.data, () => ( {}));
8888
- return _chunkLL3H5XUHcjs.createChartSpec.call(void 0, {
8888
+ return _chunkR3P2M7HUcjs.createChartSpec.call(void 0, {
8889
8889
  type: "radar",
8890
8890
  title: _nullishCoalesce(graph.title, () => ( "")),
8891
8891
  categories: Array.isArray(data.axes) ? data.axes.map(String) : [],
@@ -8933,12 +8933,12 @@ function translatePath(d, dx, dy) {
8933
8933
  }
8934
8934
  var xyChartScene = ({ graph, theme }) => {
8935
8935
  const box = _chunkZVNAMTFOcjs.XY_CHART_BOX;
8936
- const scene = _chunkHDGBM7EAcjs.layoutChart.call(void 0, xyChartSpec(graph, theme.palette), { width: box.width, height: box.height, theme: chartTheme(theme) });
8936
+ const scene = _chunkSBQVEBSUcjs.layoutChart.call(void 0, xyChartSpec(graph, theme.palette), { width: box.width, height: box.height, theme: chartTheme(theme) });
8937
8937
  return toDiagramMarks(scene.marks, box.x, box.y);
8938
8938
  };
8939
8939
  var radarScene = ({ graph, theme }) => {
8940
8940
  const box = _chunkZVNAMTFOcjs.RADAR_CHART_BOX;
8941
- const scene = _chunkHDGBM7EAcjs.layoutChart.call(void 0, radarChartSpec(graph, theme.palette), { width: box.width, height: box.height, theme: chartTheme(theme) });
8941
+ const scene = _chunkSBQVEBSUcjs.layoutChart.call(void 0, radarChartSpec(graph, theme.palette), { width: box.width, height: box.height, theme: chartTheme(theme) });
8942
8942
  return toDiagramMarks(scene.marks, box.x, box.y);
8943
8943
  };
8944
8944
 
@@ -113,10 +113,10 @@ import {
113
113
  } from "../chunk-5ED73EC6.js";
114
114
  import {
115
115
  layoutChart
116
- } from "../chunk-DTSTNRPH.js";
116
+ } from "../chunk-Z4P2RBMJ.js";
117
117
  import {
118
118
  createChartSpec
119
- } from "../chunk-HLOKB7WW.js";
119
+ } from "../chunk-3NEZJCBY.js";
120
120
  import "../chunk-II2WIF5Z.js";
121
121
  import {
122
122
  PathOpsError,
@@ -10,7 +10,8 @@ export interface ChartCommandOptions {
10
10
  }
11
11
  /**
12
12
  * Palette and agent commands for a chart: describe, update presentation, replace data, set
13
- * values, add / remove series, categories and trendlines, apply presets, switch rows and
13
+ * values, add / remove series, categories, trendlines and reference lines and bands, pin
14
+ * callouts, highlight, apply presets, switch rows and
14
15
  * columns, import CSV or Mermaid, export SVG, Mermaid or Office XML, recommend types and
15
16
  * check colours. Register them in a `CommandRegistry` and agents get them through
16
17
  * `createCommandToolProvider`; `createChartToolProvider` offers the same operations as
@@ -10,7 +10,8 @@ export interface ChartCommandOptions {
10
10
  }
11
11
  /**
12
12
  * Palette and agent commands for a chart: describe, update presentation, replace data, set
13
- * values, add / remove series, categories and trendlines, apply presets, switch rows and
13
+ * values, add / remove series, categories, trendlines and reference lines and bands, pin
14
+ * callouts, highlight, apply presets, switch rows and
14
15
  * columns, import CSV or Mermaid, export SVG, Mermaid or Office XML, recommend types and
15
16
  * check colours. Register them in a `CommandRegistry` and agents get them through
16
17
  * `createCommandToolProvider`; `createChartToolProvider` offers the same operations as
@@ -1,7 +1,8 @@
1
1
  import { HistoryManager } from '../history/HistoryManager.cjs';
2
2
  import { type ChartTrendFit } from './trend.cjs';
3
+ import { type ChartTreeRow } from './tree.cjs';
3
4
  import { type ChartTableOptions } from './spec.cjs';
4
- import type { ChartAxis, ChartIssue, ChartCurve, ChartErrorBars, ChartLegend, ChartMarker, ChartNumberFormat, ChartSelection, ChartSeries, ChartSeriesType, ChartSpec, ChartTrendline, ChartType } from './types.cjs';
5
+ import type { ChartAxis, ChartIssue, ChartCurve, ChartErrorBars, ChartLegend, ChartMarker, ChartNumberFormat, ChartReferenceBand, ChartReferenceLine, ChartSelection, ChartSeries, ChartSeriesType, ChartSpec, ChartTrendline, ChartType } from './types.cjs';
5
6
  export interface ChartControllerOptions {
6
7
  /** Starting chart (any partial or saved spec; problems are reported in `state.issues`). */
7
8
  spec?: Partial<ChartSpec> | unknown;
@@ -54,6 +55,7 @@ export interface ChartSeriesInput {
54
55
  x?: readonly unknown[];
55
56
  sizes?: readonly unknown[];
56
57
  pointColors?: readonly (string | null)[];
58
+ callouts?: readonly (string | null)[];
57
59
  marker?: ChartMarker;
58
60
  curve?: ChartCurve;
59
61
  dataLabels?: boolean;
@@ -74,6 +76,8 @@ export interface ChartSeriesPatch {
74
76
  x?: readonly unknown[] | null;
75
77
  sizes?: readonly unknown[] | null;
76
78
  pointColors?: readonly (string | null)[] | null;
79
+ /** One label per category (null: none); `null` removes them all. */
80
+ callouts?: readonly (string | null)[] | null;
77
81
  marker?: ChartMarker | null;
78
82
  curve?: ChartCurve | null;
79
83
  dataLabels?: boolean | null;
@@ -188,6 +192,9 @@ export declare class ChartController {
188
192
  }): {
189
193
  ok: true;
190
194
  index: number;
195
+ } | {
196
+ ok: false;
197
+ message: string;
191
198
  };
192
199
  removeCategory(index: number): ChartActionResult;
193
200
  renameCategory(index: number, label: string): ChartActionResult;
@@ -213,6 +220,107 @@ export declare class ChartController {
213
220
  }): ChartActionResult & {
214
221
  issues?: ChartIssue[];
215
222
  };
223
+ /** A refusal while the data is a tree (cell edits would be overwritten by its totals), else null. */
224
+ private treeLocked;
225
+ /** Replaces the grouped data (an empty list goes back to the table, keeping the totals as values). One undo step. */
226
+ setTree(tree: unknown, options?: ChartEditOptions): ChartActionResult;
227
+ /**
228
+ * Replaces the grouped data from rows of names and a value (group, …, item, value), as the
229
+ * data grid edits it; colours of nodes whose path is unchanged are kept. All-or-nothing.
230
+ */
231
+ setTreeRows(rows: readonly ChartTreeRow[] | readonly {
232
+ path: readonly unknown[];
233
+ value: unknown;
234
+ }[], options?: ChartEditOptions): ChartActionResult;
235
+ /** Replaces the data with a table of names and values (group, …, item, value); see `chartTreeFromTable`. */
236
+ importTreeTable(rows: ReadonlyArray<ReadonlyArray<unknown>>, options?: {
237
+ header?: boolean | 'auto';
238
+ }): ChartActionResult;
239
+ private nodeAt;
240
+ /** Adds a node under the group at `parent` ([] for the top level) at `at` (default: the end). Returns its path. */
241
+ addTreeNode(parent: readonly string[], input: {
242
+ name: string;
243
+ value?: number;
244
+ color?: string;
245
+ children?: unknown[];
246
+ }, options?: {
247
+ at?: number;
248
+ }): {
249
+ ok: true;
250
+ path: string[];
251
+ } | {
252
+ ok: false;
253
+ message: string;
254
+ issues?: ChartIssue[];
255
+ };
256
+ /** Renames, revalues (items only) or recolours a node; `color: null` goes back to the palette. Returns its path. */
257
+ updateTreeNode(path: readonly string[], patch: {
258
+ name?: string;
259
+ value?: number;
260
+ color?: string | null;
261
+ }): {
262
+ ok: true;
263
+ path: string[];
264
+ } | {
265
+ ok: false;
266
+ message: string;
267
+ issues?: ChartIssue[];
268
+ };
269
+ /** Removes a node (with everything under it). A group left empty becomes an item with value 0. */
270
+ removeTreeNode(path: readonly string[]): ChartActionResult;
271
+ /** Sets the note written under the chart ("" removes it). */
272
+ setNote(note: string): ChartActionResult;
273
+ /**
274
+ * Draws the named categories (labels) and series (names or ids) normally and mutes the
275
+ * rest; an empty list shows everything. Unknown names change nothing. Returns the category
276
+ * indexes and series ids that matched.
277
+ */
278
+ setHighlight(names: readonly string[]): {
279
+ ok: true;
280
+ categories: number[];
281
+ series: string[];
282
+ } | {
283
+ ok: false;
284
+ message: string;
285
+ issues?: ChartIssue[];
286
+ };
287
+ /** Why a reference on `axis` at `values` cannot be drawn on this chart, or null. */
288
+ private referenceProblem;
289
+ private editReferences;
290
+ /** Adds a reference line (a target, floor or average). Returns its index. */
291
+ addReferenceLine(input: ChartReferenceLine): {
292
+ ok: true;
293
+ index: number;
294
+ } | {
295
+ ok: false;
296
+ message: string;
297
+ issues?: ChartIssue[];
298
+ };
299
+ /** Changes a reference line (all-or-nothing); `null` removes its label, colour or axis. */
300
+ updateReferenceLine(index: number, patch: {
301
+ [K in keyof ChartReferenceLine]?: ChartReferenceLine[K] | null;
302
+ }): ChartActionResult;
303
+ removeReferenceLine(index: number): ChartActionResult;
304
+ /** Adds a reference band (a target range). Returns its index. */
305
+ addReferenceBand(input: ChartReferenceBand): {
306
+ ok: true;
307
+ index: number;
308
+ } | {
309
+ ok: false;
310
+ message: string;
311
+ issues?: ChartIssue[];
312
+ };
313
+ /** Changes a reference band (all-or-nothing); `null` removes its label, colour or axis. */
314
+ updateReferenceBand(index: number, patch: {
315
+ [K in keyof ChartReferenceBand]?: ChartReferenceBand[K] | null;
316
+ }): ChartActionResult;
317
+ removeReferenceBand(index: number): ChartActionResult;
318
+ private noReference;
319
+ /**
320
+ * Pins a label to one bar or point (`null` or "" removes it) and selects the point. The
321
+ * point must have a value, on a bar, line, area, scatter or bubble chart.
322
+ */
323
+ setCallout(seriesId: string, index: number, label: string | null): ChartActionResult;
216
324
  /** Adds a trendline to a series and selects it. Returns its index (and the fit, when it can be computed). */
217
325
  addTrendline(seriesId: string, input: ChartTrendline): {
218
326
  ok: true;
@@ -1,7 +1,8 @@
1
1
  import { HistoryManager } from '../history/HistoryManager.js';
2
2
  import { type ChartTrendFit } from './trend.js';
3
+ import { type ChartTreeRow } from './tree.js';
3
4
  import { type ChartTableOptions } from './spec.js';
4
- import type { ChartAxis, ChartIssue, ChartCurve, ChartErrorBars, ChartLegend, ChartMarker, ChartNumberFormat, ChartSelection, ChartSeries, ChartSeriesType, ChartSpec, ChartTrendline, ChartType } from './types.js';
5
+ import type { ChartAxis, ChartIssue, ChartCurve, ChartErrorBars, ChartLegend, ChartMarker, ChartNumberFormat, ChartReferenceBand, ChartReferenceLine, ChartSelection, ChartSeries, ChartSeriesType, ChartSpec, ChartTrendline, ChartType } from './types.js';
5
6
  export interface ChartControllerOptions {
6
7
  /** Starting chart (any partial or saved spec; problems are reported in `state.issues`). */
7
8
  spec?: Partial<ChartSpec> | unknown;
@@ -54,6 +55,7 @@ export interface ChartSeriesInput {
54
55
  x?: readonly unknown[];
55
56
  sizes?: readonly unknown[];
56
57
  pointColors?: readonly (string | null)[];
58
+ callouts?: readonly (string | null)[];
57
59
  marker?: ChartMarker;
58
60
  curve?: ChartCurve;
59
61
  dataLabels?: boolean;
@@ -74,6 +76,8 @@ export interface ChartSeriesPatch {
74
76
  x?: readonly unknown[] | null;
75
77
  sizes?: readonly unknown[] | null;
76
78
  pointColors?: readonly (string | null)[] | null;
79
+ /** One label per category (null: none); `null` removes them all. */
80
+ callouts?: readonly (string | null)[] | null;
77
81
  marker?: ChartMarker | null;
78
82
  curve?: ChartCurve | null;
79
83
  dataLabels?: boolean | null;
@@ -188,6 +192,9 @@ export declare class ChartController {
188
192
  }): {
189
193
  ok: true;
190
194
  index: number;
195
+ } | {
196
+ ok: false;
197
+ message: string;
191
198
  };
192
199
  removeCategory(index: number): ChartActionResult;
193
200
  renameCategory(index: number, label: string): ChartActionResult;
@@ -213,6 +220,107 @@ export declare class ChartController {
213
220
  }): ChartActionResult & {
214
221
  issues?: ChartIssue[];
215
222
  };
223
+ /** A refusal while the data is a tree (cell edits would be overwritten by its totals), else null. */
224
+ private treeLocked;
225
+ /** Replaces the grouped data (an empty list goes back to the table, keeping the totals as values). One undo step. */
226
+ setTree(tree: unknown, options?: ChartEditOptions): ChartActionResult;
227
+ /**
228
+ * Replaces the grouped data from rows of names and a value (group, …, item, value), as the
229
+ * data grid edits it; colours of nodes whose path is unchanged are kept. All-or-nothing.
230
+ */
231
+ setTreeRows(rows: readonly ChartTreeRow[] | readonly {
232
+ path: readonly unknown[];
233
+ value: unknown;
234
+ }[], options?: ChartEditOptions): ChartActionResult;
235
+ /** Replaces the data with a table of names and values (group, …, item, value); see `chartTreeFromTable`. */
236
+ importTreeTable(rows: ReadonlyArray<ReadonlyArray<unknown>>, options?: {
237
+ header?: boolean | 'auto';
238
+ }): ChartActionResult;
239
+ private nodeAt;
240
+ /** Adds a node under the group at `parent` ([] for the top level) at `at` (default: the end). Returns its path. */
241
+ addTreeNode(parent: readonly string[], input: {
242
+ name: string;
243
+ value?: number;
244
+ color?: string;
245
+ children?: unknown[];
246
+ }, options?: {
247
+ at?: number;
248
+ }): {
249
+ ok: true;
250
+ path: string[];
251
+ } | {
252
+ ok: false;
253
+ message: string;
254
+ issues?: ChartIssue[];
255
+ };
256
+ /** Renames, revalues (items only) or recolours a node; `color: null` goes back to the palette. Returns its path. */
257
+ updateTreeNode(path: readonly string[], patch: {
258
+ name?: string;
259
+ value?: number;
260
+ color?: string | null;
261
+ }): {
262
+ ok: true;
263
+ path: string[];
264
+ } | {
265
+ ok: false;
266
+ message: string;
267
+ issues?: ChartIssue[];
268
+ };
269
+ /** Removes a node (with everything under it). A group left empty becomes an item with value 0. */
270
+ removeTreeNode(path: readonly string[]): ChartActionResult;
271
+ /** Sets the note written under the chart ("" removes it). */
272
+ setNote(note: string): ChartActionResult;
273
+ /**
274
+ * Draws the named categories (labels) and series (names or ids) normally and mutes the
275
+ * rest; an empty list shows everything. Unknown names change nothing. Returns the category
276
+ * indexes and series ids that matched.
277
+ */
278
+ setHighlight(names: readonly string[]): {
279
+ ok: true;
280
+ categories: number[];
281
+ series: string[];
282
+ } | {
283
+ ok: false;
284
+ message: string;
285
+ issues?: ChartIssue[];
286
+ };
287
+ /** Why a reference on `axis` at `values` cannot be drawn on this chart, or null. */
288
+ private referenceProblem;
289
+ private editReferences;
290
+ /** Adds a reference line (a target, floor or average). Returns its index. */
291
+ addReferenceLine(input: ChartReferenceLine): {
292
+ ok: true;
293
+ index: number;
294
+ } | {
295
+ ok: false;
296
+ message: string;
297
+ issues?: ChartIssue[];
298
+ };
299
+ /** Changes a reference line (all-or-nothing); `null` removes its label, colour or axis. */
300
+ updateReferenceLine(index: number, patch: {
301
+ [K in keyof ChartReferenceLine]?: ChartReferenceLine[K] | null;
302
+ }): ChartActionResult;
303
+ removeReferenceLine(index: number): ChartActionResult;
304
+ /** Adds a reference band (a target range). Returns its index. */
305
+ addReferenceBand(input: ChartReferenceBand): {
306
+ ok: true;
307
+ index: number;
308
+ } | {
309
+ ok: false;
310
+ message: string;
311
+ issues?: ChartIssue[];
312
+ };
313
+ /** Changes a reference band (all-or-nothing); `null` removes its label, colour or axis. */
314
+ updateReferenceBand(index: number, patch: {
315
+ [K in keyof ChartReferenceBand]?: ChartReferenceBand[K] | null;
316
+ }): ChartActionResult;
317
+ removeReferenceBand(index: number): ChartActionResult;
318
+ private noReference;
319
+ /**
320
+ * Pins a label to one bar or point (`null` or "" removes it) and selects the point. The
321
+ * point must have a value, on a bar, line, area, scatter or bubble chart.
322
+ */
323
+ setCallout(seriesId: string, index: number, label: string | null): ChartActionResult;
216
324
  /** Adds a trendline to a series and selects it. Returns its index (and the fit, when it can be computed). */
217
325
  addTrendline(seriesId: string, input: ChartTrendline): {
218
326
  ok: true;