@pixerate/editor 0.162.1 → 0.164.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/agent/index.cjs +34 -34
- package/dist/agent/index.js +5 -5
- package/dist/canvas/displacement.d.cts +34 -2
- package/dist/canvas/displacement.d.ts +34 -2
- package/dist/canvas/explosion-tools.d.cts +43 -0
- package/dist/canvas/explosion-tools.d.ts +43 -0
- package/dist/canvas/explosionLayout.d.cts +50 -0
- package/dist/canvas/explosionLayout.d.ts +50 -0
- package/dist/canvas/explosionState.d.cts +52 -0
- package/dist/canvas/explosionState.d.ts +52 -0
- package/dist/canvas/index.cjs +430 -88
- package/dist/canvas/index.d.cts +3 -0
- package/dist/canvas/index.d.ts +3 -0
- package/dist/canvas/index.js +425 -83
- package/dist/canvas/types.d.cts +27 -2
- package/dist/canvas/types.d.ts +27 -2
- package/dist/chart/commands.d.cts +2 -1
- package/dist/chart/commands.d.ts +2 -1
- package/dist/chart/controller.d.cts +109 -1
- package/dist/chart/controller.d.ts +109 -1
- package/dist/chart/index.cjs +605 -130
- package/dist/chart/index.d.cts +1 -0
- package/dist/chart/index.d.ts +1 -0
- package/dist/chart/index.js +490 -15
- package/dist/chart/layout-annotations.d.cts +29 -0
- package/dist/chart/layout-annotations.d.ts +29 -0
- package/dist/chart/layout-families.d.cts +23 -0
- package/dist/chart/layout-families.d.ts +23 -0
- package/dist/chart/mermaid.d.cts +2 -1
- package/dist/chart/mermaid.d.ts +2 -1
- package/dist/chart/schemas.d.cts +13 -0
- package/dist/chart/schemas.d.ts +13 -0
- package/dist/chart/spec.d.cts +30 -5
- package/dist/chart/spec.d.ts +30 -5
- package/dist/chart/stats.d.cts +9 -1
- package/dist/chart/stats.d.ts +9 -1
- package/dist/chart/tools.d.cts +1 -1
- package/dist/chart/tools.d.ts +1 -1
- package/dist/chart/tree.d.cts +62 -0
- package/dist/chart/tree.d.ts +62 -0
- package/dist/chart/types.d.cts +77 -3
- package/dist/chart/types.d.ts +77 -3
- package/dist/{chunk-7YBDRJXT.cjs → chunk-22KLZZGH.cjs} +8 -8
- package/dist/{chunk-HLOKB7WW.js → chunk-3NEZJCBY.js} +366 -6
- package/dist/{chunk-EVPZ5IKN.js → chunk-5FNGLV2D.js} +65 -3
- package/dist/{chunk-EQ46F75O.cjs → chunk-D54JHQK2.cjs} +51 -51
- package/dist/{chunk-NO5QQDHZ.js → chunk-DAPQGA55.js} +2 -2
- package/dist/{chunk-3IHNXRUV.cjs → chunk-GKNEJ6EN.cjs} +399 -67
- package/dist/{chunk-4NGVHHJB.cjs → chunk-NZD2MZJC.cjs} +80 -18
- package/dist/{chunk-CX6JLDFC.js → chunk-OXERWBKE.js} +3 -3
- package/dist/{chunk-7CKPUUN4.js → chunk-POR54B55.js} +61 -10
- package/dist/{chunk-LL3H5XUH.cjs → chunk-R3P2M7HU.cjs} +367 -7
- package/dist/{chunk-HDGBM7EA.cjs → chunk-SBQVEBSU.cjs} +580 -53
- package/dist/{chunk-XDCFJEU7.js → chunk-SZA42R4N.js} +346 -14
- package/dist/{chunk-GLMP22FT.js → chunk-TALQONZ5.js} +3 -3
- package/dist/{chunk-NA4UVVJ4.cjs → chunk-YGG7WDWT.cjs} +76 -25
- package/dist/{chunk-EY22AY6R.cjs → chunk-YSAGBIRW.cjs} +16 -16
- package/dist/{chunk-DTSTNRPH.js → chunk-Z4P2RBMJ.js} +536 -9
- package/dist/export/index.cjs +4 -4
- package/dist/export/index.js +3 -3
- package/dist/extensions/index.cjs +7 -7
- package/dist/extensions/index.js +6 -6
- package/dist/index.cjs +13 -13
- package/dist/index.js +7 -7
- package/dist/paint-editor/index.cjs +0 -20
- package/dist/paint-editor/index.js +0 -20
- package/package.json +1 -1
- package/skills/README.md +12 -0
- package/skills/pixerate-agent-tools/SKILL.md +34 -1
- package/skills/pixerate-canvas/SKILL.md +16 -0
- package/skills/pixerate-chart/SKILL.md +41 -9
- package/skills/pixerate-image-editor/SKILL.md +2 -0
- package/skills/pixerate-paint-editor/SKILL.md +2 -0
- package/skills/pixerate-tokens/SKILL.md +5 -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) |
|
package/dist/agent/index.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
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
|
|
118
|
+
var _chunkYSAGBIRWcjs = require('../chunk-YSAGBIRW.cjs');
|
|
119
119
|
|
|
120
120
|
|
|
121
|
-
var
|
|
122
|
-
require('../chunk-
|
|
121
|
+
var _chunkGKNEJ6ENcjs = require('../chunk-GKNEJ6EN.cjs');
|
|
122
|
+
require('../chunk-SBQVEBSU.cjs');
|
|
123
123
|
|
|
124
124
|
|
|
125
125
|
|
|
126
|
-
var
|
|
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
|
-
...
|
|
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)." }, ...
|
|
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 } =
|
|
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:
|
|
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:
|
|
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 =
|
|
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:
|
|
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 =
|
|
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:
|
|
780
|
-
kind: { type: "string", enum: [...
|
|
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) =>
|
|
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 =
|
|
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]), () => (
|
|
1138
|
-
color: _nullishCoalesce(_optionalChain([config, 'optionalAccess', _45 => _45.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() &&
|
|
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
|
-
|
|
1156
|
-
if (changedMs > 0 && ranges.length) tintTimer = setTimeout(() => live() &&
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1180
|
-
if (changedMs > 0) tintTimer = setTimeout(() => live() &&
|
|
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,
|
|
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 =
|
|
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 =
|
|
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:
|
|
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 =
|
|
1506
|
+
const state = _chunkYSAGBIRWcjs.getTableActionState.call(void 0, ed, action, params);
|
|
1507
1507
|
if (state !== true) throw new Error(state);
|
|
1508
|
-
|
|
1509
|
-
const table =
|
|
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, ...
|
|
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();
|
package/dist/agent/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
CHART_UPDATE_PROPERTIES,
|
|
3
3
|
SERIES_PROPS,
|
|
4
4
|
VALUE
|
|
5
|
-
} from "../chunk-
|
|
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-
|
|
118
|
+
} from "../chunk-OXERWBKE.js";
|
|
119
119
|
import {
|
|
120
120
|
describeChart
|
|
121
|
-
} from "../chunk-
|
|
122
|
-
import "../chunk-
|
|
121
|
+
} from "../chunk-SZA42R4N.js";
|
|
122
|
+
import "../chunk-Z4P2RBMJ.js";
|
|
123
123
|
import {
|
|
124
124
|
normalizeChartSpec,
|
|
125
125
|
parseChartValue
|
|
126
|
-
} from "../chunk-
|
|
126
|
+
} from "../chunk-3NEZJCBY.js";
|
|
127
127
|
import {
|
|
128
128
|
getEditorMarkdown,
|
|
129
129
|
getEditorText
|
|
@@ -1,11 +1,30 @@
|
|
|
1
|
-
import type { CanvasEdge, CanvasNode, DirectionalDisplacementOptions, Rect, ReflowDisplacementOptions, XYPosition } from './types.cjs';
|
|
1
|
+
import type { CanvasEdge, CanvasLayoutOptions, CanvasNode, DirectionalDisplacementOptions, Rect, ReflowDisplacementOptions, XYPosition } from './types.cjs';
|
|
2
2
|
/**
|
|
3
3
|
* Calculates a bounding rectangle for a set of nodes if not provided by getNodesBounds.
|
|
4
4
|
*/
|
|
5
5
|
export declare function computeNodesBoundingBox<TNode extends CanvasNode = CanvasNode>(nodes: TNode[], defaultWidth?: number, defaultHeight?: number): Rect;
|
|
6
|
+
/** A node's size: measured, then explicit, then the defaults. */
|
|
7
|
+
export declare function nodeSizeOf<TNode extends CanvasNode = CanvasNode>(node: TNode, defaultWidth?: number, defaultHeight?: number): {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
};
|
|
6
11
|
/**
|
|
7
12
|
* Pure directional displacement calculation.
|
|
8
|
-
*
|
|
13
|
+
*
|
|
14
|
+
* Shifts surrounding nodes along an axis to clear space for a cluster of child nodes inserted
|
|
15
|
+
* next to `originNode`, and returns the new positions of the nodes that move (nothing is mutated).
|
|
16
|
+
*
|
|
17
|
+
* - `right` / `left` push nodes on that side by the cluster's width plus `gap`; Y is preserved
|
|
18
|
+
* (except for `spreadSiblingLanes` with `right`).
|
|
19
|
+
* - `up` / `down` push nodes on that side by the cluster's height plus `gap`; X is preserved.
|
|
20
|
+
* - `vertical` opens the origin's row: nodes above move up and nodes below move down by the same
|
|
21
|
+
* amount (the larger of the two clearances); X is preserved and the origin's row stays put.
|
|
22
|
+
* - `layoutMode: 'row-lane'` buckets nodes into lanes `rowSpacing` apart and rounds vertical
|
|
23
|
+
* deltas up to whole lanes.
|
|
24
|
+
* - `minY` / `maxY` keep moved rows inside a band, stacking clamped rows `rowSpacing` apart.
|
|
25
|
+
*
|
|
26
|
+
* @throws RangeError when `gap`, `rowSpacing`, `minY` or `maxY` are not finite, `rowSpacing <= 0`,
|
|
27
|
+
* or `minY > maxY`.
|
|
9
28
|
*/
|
|
10
29
|
export declare function calculateDirectionalDisplacement<TNode extends CanvasNode = CanvasNode>(params: {
|
|
11
30
|
existingNodes: TNode[];
|
|
@@ -14,6 +33,19 @@ export declare function calculateDirectionalDisplacement<TNode extends CanvasNod
|
|
|
14
33
|
getNodesBounds?: (nodes: TNode[]) => Rect;
|
|
15
34
|
options?: DirectionalDisplacementOptions;
|
|
16
35
|
}): Map<string, XYPosition>;
|
|
36
|
+
/**
|
|
37
|
+
* Hierarchical Dagre reflow displacement for an explosion: lays out the existing graph plus the
|
|
38
|
+
* child cluster, anchoring the origin node at its current position so the layout does not jump,
|
|
39
|
+
* and returns the new positions of existing nodes that move.
|
|
40
|
+
*/
|
|
41
|
+
export declare function calculateReflowDisplacement<TNode extends CanvasNode = CanvasNode, TEdge extends CanvasEdge = CanvasEdge>(params: {
|
|
42
|
+
existingNodes: TNode[];
|
|
43
|
+
existingEdges: TEdge[];
|
|
44
|
+
originNode: TNode;
|
|
45
|
+
childNodes: TNode[];
|
|
46
|
+
childEdges?: TEdge[];
|
|
47
|
+
options?: CanvasLayoutOptions;
|
|
48
|
+
}): Map<string, XYPosition>;
|
|
17
49
|
/**
|
|
18
50
|
* Calculates Dagre reflow displacement preserving the position of an anchor node.
|
|
19
51
|
*/
|
|
@@ -1,11 +1,30 @@
|
|
|
1
|
-
import type { CanvasEdge, CanvasNode, DirectionalDisplacementOptions, Rect, ReflowDisplacementOptions, XYPosition } from './types.js';
|
|
1
|
+
import type { CanvasEdge, CanvasLayoutOptions, CanvasNode, DirectionalDisplacementOptions, Rect, ReflowDisplacementOptions, XYPosition } from './types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Calculates a bounding rectangle for a set of nodes if not provided by getNodesBounds.
|
|
4
4
|
*/
|
|
5
5
|
export declare function computeNodesBoundingBox<TNode extends CanvasNode = CanvasNode>(nodes: TNode[], defaultWidth?: number, defaultHeight?: number): Rect;
|
|
6
|
+
/** A node's size: measured, then explicit, then the defaults. */
|
|
7
|
+
export declare function nodeSizeOf<TNode extends CanvasNode = CanvasNode>(node: TNode, defaultWidth?: number, defaultHeight?: number): {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
};
|
|
6
11
|
/**
|
|
7
12
|
* Pure directional displacement calculation.
|
|
8
|
-
*
|
|
13
|
+
*
|
|
14
|
+
* Shifts surrounding nodes along an axis to clear space for a cluster of child nodes inserted
|
|
15
|
+
* next to `originNode`, and returns the new positions of the nodes that move (nothing is mutated).
|
|
16
|
+
*
|
|
17
|
+
* - `right` / `left` push nodes on that side by the cluster's width plus `gap`; Y is preserved
|
|
18
|
+
* (except for `spreadSiblingLanes` with `right`).
|
|
19
|
+
* - `up` / `down` push nodes on that side by the cluster's height plus `gap`; X is preserved.
|
|
20
|
+
* - `vertical` opens the origin's row: nodes above move up and nodes below move down by the same
|
|
21
|
+
* amount (the larger of the two clearances); X is preserved and the origin's row stays put.
|
|
22
|
+
* - `layoutMode: 'row-lane'` buckets nodes into lanes `rowSpacing` apart and rounds vertical
|
|
23
|
+
* deltas up to whole lanes.
|
|
24
|
+
* - `minY` / `maxY` keep moved rows inside a band, stacking clamped rows `rowSpacing` apart.
|
|
25
|
+
*
|
|
26
|
+
* @throws RangeError when `gap`, `rowSpacing`, `minY` or `maxY` are not finite, `rowSpacing <= 0`,
|
|
27
|
+
* or `minY > maxY`.
|
|
9
28
|
*/
|
|
10
29
|
export declare function calculateDirectionalDisplacement<TNode extends CanvasNode = CanvasNode>(params: {
|
|
11
30
|
existingNodes: TNode[];
|
|
@@ -14,6 +33,19 @@ export declare function calculateDirectionalDisplacement<TNode extends CanvasNod
|
|
|
14
33
|
getNodesBounds?: (nodes: TNode[]) => Rect;
|
|
15
34
|
options?: DirectionalDisplacementOptions;
|
|
16
35
|
}): Map<string, XYPosition>;
|
|
36
|
+
/**
|
|
37
|
+
* Hierarchical Dagre reflow displacement for an explosion: lays out the existing graph plus the
|
|
38
|
+
* child cluster, anchoring the origin node at its current position so the layout does not jump,
|
|
39
|
+
* and returns the new positions of existing nodes that move.
|
|
40
|
+
*/
|
|
41
|
+
export declare function calculateReflowDisplacement<TNode extends CanvasNode = CanvasNode, TEdge extends CanvasEdge = CanvasEdge>(params: {
|
|
42
|
+
existingNodes: TNode[];
|
|
43
|
+
existingEdges: TEdge[];
|
|
44
|
+
originNode: TNode;
|
|
45
|
+
childNodes: TNode[];
|
|
46
|
+
childEdges?: TEdge[];
|
|
47
|
+
options?: CanvasLayoutOptions;
|
|
48
|
+
}): Map<string, XYPosition>;
|
|
17
49
|
/**
|
|
18
50
|
* Calculates Dagre reflow displacement preserving the position of an anchor node.
|
|
19
51
|
*/
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent tools for canvas node explosion: `list_explodable_nodes`, `explode_node` and
|
|
3
|
+
* `collapse_node`. They drive a {@link CanvasExplosionToolTarget}, which a host adapts from the
|
|
4
|
+
* declarative state (`canvasExplosionToolTarget`) or from an imperative explosion coordinator
|
|
5
|
+
* (`createCanvasExplosion` / `useCanvasExplosion`, whose `explodeNode` needs the host's children).
|
|
6
|
+
*/
|
|
7
|
+
import type { AgentToolProvider } from '../tools/registry.cjs';
|
|
8
|
+
import type { CanvasExplosionState } from './explosionState.cjs';
|
|
9
|
+
import type { CanvasNode } from './types.cjs';
|
|
10
|
+
/** What the explosion tools drive. */
|
|
11
|
+
export interface CanvasExplosionToolTarget<TNode extends CanvasNode = CanvasNode> {
|
|
12
|
+
/** The nodes on the canvas (exploded children included or not; they are only listed when explodable). */
|
|
13
|
+
getNodes: () => readonly TNode[];
|
|
14
|
+
/** Ids of the exploded nodes. */
|
|
15
|
+
exploded: () => readonly string[];
|
|
16
|
+
/** Ids of nodes whose collapse is still animating. Default none. */
|
|
17
|
+
collapsing?: () => readonly string[];
|
|
18
|
+
/** `true` when the node can explode, otherwise false or the reason it cannot. Default: every node. */
|
|
19
|
+
canExplode?: (node: TNode) => boolean | string;
|
|
20
|
+
/** Explodes a node. Return false (or throw) to refuse. */
|
|
21
|
+
explode: (nodeId: string) => void | boolean | Promise<void | boolean>;
|
|
22
|
+
/** Collapses an exploded node. Return false (or throw) to refuse. */
|
|
23
|
+
collapse: (nodeId: string) => void | boolean | Promise<void | boolean>;
|
|
24
|
+
/** Several nodes can be exploded at once. Default false: exploding one collapses the other. */
|
|
25
|
+
multiple?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/** Adapts the declarative explosion state (`createCanvasExplosionState`, `useCanvasExplosionState`) for the tools. */
|
|
28
|
+
export declare function canvasExplosionToolTarget<TNode extends CanvasNode = CanvasNode>(state: CanvasExplosionState, options: {
|
|
29
|
+
getNodes: () => readonly TNode[];
|
|
30
|
+
canExplode?: (node: TNode) => boolean | string;
|
|
31
|
+
}): CanvasExplosionToolTarget<TNode>;
|
|
32
|
+
export interface CanvasExplosionToolProviderOptions {
|
|
33
|
+
/** Provider id (unique per registry). Default `canvas-explosion`. */
|
|
34
|
+
id?: string;
|
|
35
|
+
/** Tool-name prefix (`<namespace>__<name>`); defaults to the provider id, `''` for bare names. */
|
|
36
|
+
namespace?: string;
|
|
37
|
+
/** Exploding is not allowed: `explode_node` and `collapse_node` are hidden. A string is the reason. */
|
|
38
|
+
readOnly?: boolean | string | (() => boolean | string);
|
|
39
|
+
/** Lets the tool list follow changes (e.g. the state's `subscribe`). */
|
|
40
|
+
subscribe?: (notify: () => void) => () => void;
|
|
41
|
+
}
|
|
42
|
+
/** The explosion tools for a canvas (see the module comment). */
|
|
43
|
+
export declare function createCanvasExplosionToolProvider<TNode extends CanvasNode = CanvasNode>(target: CanvasExplosionToolTarget<TNode>, options?: CanvasExplosionToolProviderOptions): AgentToolProvider;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent tools for canvas node explosion: `list_explodable_nodes`, `explode_node` and
|
|
3
|
+
* `collapse_node`. They drive a {@link CanvasExplosionToolTarget}, which a host adapts from the
|
|
4
|
+
* declarative state (`canvasExplosionToolTarget`) or from an imperative explosion coordinator
|
|
5
|
+
* (`createCanvasExplosion` / `useCanvasExplosion`, whose `explodeNode` needs the host's children).
|
|
6
|
+
*/
|
|
7
|
+
import type { AgentToolProvider } from '../tools/registry.js';
|
|
8
|
+
import type { CanvasExplosionState } from './explosionState.js';
|
|
9
|
+
import type { CanvasNode } from './types.js';
|
|
10
|
+
/** What the explosion tools drive. */
|
|
11
|
+
export interface CanvasExplosionToolTarget<TNode extends CanvasNode = CanvasNode> {
|
|
12
|
+
/** The nodes on the canvas (exploded children included or not; they are only listed when explodable). */
|
|
13
|
+
getNodes: () => readonly TNode[];
|
|
14
|
+
/** Ids of the exploded nodes. */
|
|
15
|
+
exploded: () => readonly string[];
|
|
16
|
+
/** Ids of nodes whose collapse is still animating. Default none. */
|
|
17
|
+
collapsing?: () => readonly string[];
|
|
18
|
+
/** `true` when the node can explode, otherwise false or the reason it cannot. Default: every node. */
|
|
19
|
+
canExplode?: (node: TNode) => boolean | string;
|
|
20
|
+
/** Explodes a node. Return false (or throw) to refuse. */
|
|
21
|
+
explode: (nodeId: string) => void | boolean | Promise<void | boolean>;
|
|
22
|
+
/** Collapses an exploded node. Return false (or throw) to refuse. */
|
|
23
|
+
collapse: (nodeId: string) => void | boolean | Promise<void | boolean>;
|
|
24
|
+
/** Several nodes can be exploded at once. Default false: exploding one collapses the other. */
|
|
25
|
+
multiple?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/** Adapts the declarative explosion state (`createCanvasExplosionState`, `useCanvasExplosionState`) for the tools. */
|
|
28
|
+
export declare function canvasExplosionToolTarget<TNode extends CanvasNode = CanvasNode>(state: CanvasExplosionState, options: {
|
|
29
|
+
getNodes: () => readonly TNode[];
|
|
30
|
+
canExplode?: (node: TNode) => boolean | string;
|
|
31
|
+
}): CanvasExplosionToolTarget<TNode>;
|
|
32
|
+
export interface CanvasExplosionToolProviderOptions {
|
|
33
|
+
/** Provider id (unique per registry). Default `canvas-explosion`. */
|
|
34
|
+
id?: string;
|
|
35
|
+
/** Tool-name prefix (`<namespace>__<name>`); defaults to the provider id, `''` for bare names. */
|
|
36
|
+
namespace?: string;
|
|
37
|
+
/** Exploding is not allowed: `explode_node` and `collapse_node` are hidden. A string is the reason. */
|
|
38
|
+
readOnly?: boolean | string | (() => boolean | string);
|
|
39
|
+
/** Lets the tool list follow changes (e.g. the state's `subscribe`). */
|
|
40
|
+
subscribe?: (notify: () => void) => () => void;
|
|
41
|
+
}
|
|
42
|
+
/** The explosion tools for a canvas (see the module comment). */
|
|
43
|
+
export declare function createCanvasExplosionToolProvider<TNode extends CanvasNode = CanvasNode>(target: CanvasExplosionToolTarget<TNode>, options?: CanvasExplosionToolProviderOptions): AgentToolProvider;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { CanvasEdge, CanvasLayoutOptions, CanvasNode, DirectionalDisplacementOptions, ExplosionDisplacementStrategy, Rect, XYPosition } from './types.cjs';
|
|
2
|
+
export interface ComputeCanvasExplosionLayoutParams<TNode extends CanvasNode = CanvasNode, TEdge extends CanvasEdge = CanvasEdge> {
|
|
3
|
+
/** Every node on the canvas, including the origin. Never mutated. */
|
|
4
|
+
existingNodes: TNode[];
|
|
5
|
+
/** Every edge on the canvas (only read by the `dagre` strategy). */
|
|
6
|
+
existingEdges?: TEdge[];
|
|
7
|
+
/** The node that explodes. */
|
|
8
|
+
originNode: TNode;
|
|
9
|
+
/** The child nodes at their final positions. Never mutated: the result holds copies. */
|
|
10
|
+
childNodes: TNode[];
|
|
11
|
+
/** Edges between children (or from children to existing nodes). */
|
|
12
|
+
childEdges?: TEdge[];
|
|
13
|
+
/** How existing nodes make room. Default `directional`. */
|
|
14
|
+
strategy?: ExplosionDisplacementStrategy;
|
|
15
|
+
/** Options for the `directional` strategy. */
|
|
16
|
+
options?: DirectionalDisplacementOptions;
|
|
17
|
+
/** Options for the `dagre` strategy. */
|
|
18
|
+
reflowOptions?: CanvasLayoutOptions;
|
|
19
|
+
/** Add parent-to-child edges: every child (`true` / `'all'`), the first child only, or none. Default `false`. */
|
|
20
|
+
connectParentToChildren?: boolean | 'first' | 'all';
|
|
21
|
+
/** Builds a parent-to-child edge. Default `{ id: 'explode:<parent>:<child>', source, target, type: 'default' }`. */
|
|
22
|
+
createEdge?: (sourceId: string, targetId: string) => TEdge;
|
|
23
|
+
/** Bounds of a set of nodes (e.g. the flow instance's `getNodesBounds`). Default: measured sizes. */
|
|
24
|
+
getNodesBounds?: (nodes: TNode[]) => Rect;
|
|
25
|
+
}
|
|
26
|
+
export interface CanvasExplosionLayoutResult<TNode extends CanvasNode = CanvasNode, TEdge extends CanvasEdge = CanvasEdge> {
|
|
27
|
+
/** New positions of the existing nodes that move to make room, by id. */
|
|
28
|
+
displacedPositions: Map<string, XYPosition>;
|
|
29
|
+
/** Where each displaced node was before, by id (what a collapse restores). */
|
|
30
|
+
originalPositions: Map<string, XYPosition>;
|
|
31
|
+
/** Copies of the child nodes at their final positions. */
|
|
32
|
+
childNodes: TNode[];
|
|
33
|
+
/** The child edges plus any parent-to-child edges (deduplicated). */
|
|
34
|
+
childEdges: TEdge[];
|
|
35
|
+
/** Bounds of the child cluster. */
|
|
36
|
+
childBounds: Rect;
|
|
37
|
+
/** The largest distance any displaced node moves along either axis (0 when nothing moves). */
|
|
38
|
+
totalDisplacementDelta: number;
|
|
39
|
+
}
|
|
40
|
+
/** The default id of a parent-to-child edge added by an explosion. */
|
|
41
|
+
export declare const explosionEdgeId: (sourceId: string, targetId: string) => string;
|
|
42
|
+
/**
|
|
43
|
+
* Pure explosion layout: works out where existing nodes move to make room for a child cluster
|
|
44
|
+
* and which edges the explosion adds, without touching the inputs. Feed the result to a
|
|
45
|
+
* declarative derivation (`$derived`, `useMemo`) or to an imperative graph coordinator.
|
|
46
|
+
*
|
|
47
|
+
* @throws Error when the origin is not in `existingNodes`, or a child id is already on the canvas
|
|
48
|
+
* or repeated.
|
|
49
|
+
*/
|
|
50
|
+
export declare function computeCanvasExplosionLayout<TNode extends CanvasNode = CanvasNode, TEdge extends CanvasEdge = CanvasEdge>(params: ComputeCanvasExplosionLayoutParams<TNode, TEdge>): CanvasExplosionLayoutResult<TNode, TEdge>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { CanvasEdge, CanvasLayoutOptions, CanvasNode, DirectionalDisplacementOptions, ExplosionDisplacementStrategy, Rect, XYPosition } from './types.js';
|
|
2
|
+
export interface ComputeCanvasExplosionLayoutParams<TNode extends CanvasNode = CanvasNode, TEdge extends CanvasEdge = CanvasEdge> {
|
|
3
|
+
/** Every node on the canvas, including the origin. Never mutated. */
|
|
4
|
+
existingNodes: TNode[];
|
|
5
|
+
/** Every edge on the canvas (only read by the `dagre` strategy). */
|
|
6
|
+
existingEdges?: TEdge[];
|
|
7
|
+
/** The node that explodes. */
|
|
8
|
+
originNode: TNode;
|
|
9
|
+
/** The child nodes at their final positions. Never mutated: the result holds copies. */
|
|
10
|
+
childNodes: TNode[];
|
|
11
|
+
/** Edges between children (or from children to existing nodes). */
|
|
12
|
+
childEdges?: TEdge[];
|
|
13
|
+
/** How existing nodes make room. Default `directional`. */
|
|
14
|
+
strategy?: ExplosionDisplacementStrategy;
|
|
15
|
+
/** Options for the `directional` strategy. */
|
|
16
|
+
options?: DirectionalDisplacementOptions;
|
|
17
|
+
/** Options for the `dagre` strategy. */
|
|
18
|
+
reflowOptions?: CanvasLayoutOptions;
|
|
19
|
+
/** Add parent-to-child edges: every child (`true` / `'all'`), the first child only, or none. Default `false`. */
|
|
20
|
+
connectParentToChildren?: boolean | 'first' | 'all';
|
|
21
|
+
/** Builds a parent-to-child edge. Default `{ id: 'explode:<parent>:<child>', source, target, type: 'default' }`. */
|
|
22
|
+
createEdge?: (sourceId: string, targetId: string) => TEdge;
|
|
23
|
+
/** Bounds of a set of nodes (e.g. the flow instance's `getNodesBounds`). Default: measured sizes. */
|
|
24
|
+
getNodesBounds?: (nodes: TNode[]) => Rect;
|
|
25
|
+
}
|
|
26
|
+
export interface CanvasExplosionLayoutResult<TNode extends CanvasNode = CanvasNode, TEdge extends CanvasEdge = CanvasEdge> {
|
|
27
|
+
/** New positions of the existing nodes that move to make room, by id. */
|
|
28
|
+
displacedPositions: Map<string, XYPosition>;
|
|
29
|
+
/** Where each displaced node was before, by id (what a collapse restores). */
|
|
30
|
+
originalPositions: Map<string, XYPosition>;
|
|
31
|
+
/** Copies of the child nodes at their final positions. */
|
|
32
|
+
childNodes: TNode[];
|
|
33
|
+
/** The child edges plus any parent-to-child edges (deduplicated). */
|
|
34
|
+
childEdges: TEdge[];
|
|
35
|
+
/** Bounds of the child cluster. */
|
|
36
|
+
childBounds: Rect;
|
|
37
|
+
/** The largest distance any displaced node moves along either axis (0 when nothing moves). */
|
|
38
|
+
totalDisplacementDelta: number;
|
|
39
|
+
}
|
|
40
|
+
/** The default id of a parent-to-child edge added by an explosion. */
|
|
41
|
+
export declare const explosionEdgeId: (sourceId: string, targetId: string) => string;
|
|
42
|
+
/**
|
|
43
|
+
* Pure explosion layout: works out where existing nodes move to make room for a child cluster
|
|
44
|
+
* and which edges the explosion adds, without touching the inputs. Feed the result to a
|
|
45
|
+
* declarative derivation (`$derived`, `useMemo`) or to an imperative graph coordinator.
|
|
46
|
+
*
|
|
47
|
+
* @throws Error when the origin is not in `existingNodes`, or a child id is already on the canvas
|
|
48
|
+
* or repeated.
|
|
49
|
+
*/
|
|
50
|
+
export declare function computeCanvasExplosionLayout<TNode extends CanvasNode = CanvasNode, TEdge extends CanvasEdge = CanvasEdge>(params: ComputeCanvasExplosionLayoutParams<TNode, TEdge>): CanvasExplosionLayoutResult<TNode, TEdge>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headless, framework-free state machine for canvas node explosion: which node is exploded,
|
|
3
|
+
* which is collapsing (children still mounted while a collapse animation plays), and the timer
|
|
4
|
+
* that ends the collapse. It never touches a graph or the DOM, so a declarative canvas can derive
|
|
5
|
+
* its nodes from it. The Svelte rune `createCanvasExplosionState` and the React hook
|
|
6
|
+
* `useCanvasExplosionState` wrap it.
|
|
7
|
+
*/
|
|
8
|
+
export interface CanvasExplosionStateOptions {
|
|
9
|
+
/** How long children stay rendered after a collapse starts, in ms. Default 380. `0` ends the collapse at once. */
|
|
10
|
+
collapseDurationMs?: number;
|
|
11
|
+
/** The node exploded at creation. Default none. */
|
|
12
|
+
initialActiveId?: string | null;
|
|
13
|
+
/** Called after a node explodes. */
|
|
14
|
+
onExplode?: (nodeId: string) => void;
|
|
15
|
+
/** Called when a node starts collapsing (including when exploding another node replaces it). */
|
|
16
|
+
onCollapse?: (nodeId: string) => void;
|
|
17
|
+
}
|
|
18
|
+
/** The state at one moment. A new object each time it changes, so it can be compared by identity. */
|
|
19
|
+
export interface CanvasExplosionStateSnapshot {
|
|
20
|
+
/** The exploded node, or null. */
|
|
21
|
+
readonly activeId: string | null;
|
|
22
|
+
/** The node whose collapse animation is playing, or null. */
|
|
23
|
+
readonly collapsingId: string | null;
|
|
24
|
+
}
|
|
25
|
+
export interface CanvasExplosionState extends CanvasExplosionStateSnapshot {
|
|
26
|
+
/** True while a node is exploded or collapsing (children are on screen). */
|
|
27
|
+
readonly isExplodingOrCollapsing: boolean;
|
|
28
|
+
isExploded: (nodeId: string) => boolean;
|
|
29
|
+
isCollapsing: (nodeId: string) => boolean;
|
|
30
|
+
/** True when the node's children should be rendered: it is exploded or still collapsing. */
|
|
31
|
+
shouldRenderChildren: (nodeId: string) => boolean;
|
|
32
|
+
/** Explodes a node, replacing (collapsing) any other exploded node. Returns false when it already was. */
|
|
33
|
+
explode: (nodeId: string) => boolean;
|
|
34
|
+
/** Collapses the exploded node (only if it is `nodeId`, when given). Returns false when nothing collapsed. */
|
|
35
|
+
collapse: (nodeId?: string) => boolean;
|
|
36
|
+
/** Collapses the node when it is exploded, otherwise explodes it. Returns true when it is now exploded. */
|
|
37
|
+
toggle: (nodeId: string) => boolean;
|
|
38
|
+
/** Ends a running collapse now (e.g. from an `animationend` handler) instead of waiting for the timer. */
|
|
39
|
+
finishCollapse: () => void;
|
|
40
|
+
/** Clears the collapse timer and listeners; later calls do nothing. */
|
|
41
|
+
destroy: () => void;
|
|
42
|
+
}
|
|
43
|
+
export interface CanvasExplosionStateController extends CanvasExplosionState {
|
|
44
|
+
/** The current state; the same object until something changes. */
|
|
45
|
+
getSnapshot: () => CanvasExplosionStateSnapshot;
|
|
46
|
+
/** Calls `listener` after every change; returns an unsubscribe function. */
|
|
47
|
+
subscribe: (listener: () => void) => () => void;
|
|
48
|
+
/** True after `destroy()`. */
|
|
49
|
+
readonly destroyed: boolean;
|
|
50
|
+
}
|
|
51
|
+
/** Creates the headless explosion state machine (see the module comment). */
|
|
52
|
+
export declare function createCanvasExplosionStateController(options?: CanvasExplosionStateOptions): CanvasExplosionStateController;
|