@blueking/flow-canvas 0.0.1-beta.1

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 (46) hide show
  1. package/README.md +725 -0
  2. package/dist/core/apply-command.d.ts +11 -0
  3. package/dist/core/editor.d.ts +50 -0
  4. package/dist/core/errors.d.ts +6 -0
  5. package/dist/core/history.d.ts +15 -0
  6. package/dist/core/plugin-manager.d.ts +58 -0
  7. package/dist/index-BAAMFT_J.js +236 -0
  8. package/dist/index-CleU3x1v.cjs +1 -0
  9. package/dist/index-DD3pv5ZZ.cjs +21 -0
  10. package/dist/index-siYsjzl4.js +181 -0
  11. package/dist/index.cjs.js +1 -0
  12. package/dist/index.d.ts +33 -0
  13. package/dist/index.esm.js +2709 -0
  14. package/dist/plugins/clipboard.d.ts +9 -0
  15. package/dist/plugins/connection-validator.d.ts +3 -0
  16. package/dist/plugins/minimap.d.ts +7 -0
  17. package/dist/plugins/selection.d.ts +7 -0
  18. package/dist/plugins/snapline.d.ts +6 -0
  19. package/dist/runtime/canvas-api.d.ts +25 -0
  20. package/dist/runtime/canvas-runtime-core.vue.d.ts +36 -0
  21. package/dist/runtime/event-bridge.d.ts +28 -0
  22. package/dist/runtime/graph-bridge.d.ts +127 -0
  23. package/dist/runtime/overlay-manager.d.ts +4 -0
  24. package/dist/runtime/shape-registry.d.ts +8 -0
  25. package/dist/runtime/use-edge-delete-tool.d.ts +11 -0
  26. package/dist/runtime/use-node-hover.d.ts +8 -0
  27. package/dist/runtime/use-port-visibility.d.ts +15 -0
  28. package/dist/shell/canvas-layout.vue.d.ts +35 -0
  29. package/dist/shell/canvas-node-palette.vue.d.ts +10 -0
  30. package/dist/shell/canvas-toolbar.vue.d.ts +11 -0
  31. package/dist/shell/default-node.vue.d.ts +4 -0
  32. package/dist/shell/default-schema.d.ts +39 -0
  33. package/dist/shell/node-actions-toolbar.vue.d.ts +18 -0
  34. package/dist/shell/node-quick-add-popover.vue.d.ts +36 -0
  35. package/dist/shell/toolbar-items.d.ts +13 -0
  36. package/dist/style.css +1 -0
  37. package/dist/types/api.d.ts +104 -0
  38. package/dist/types/command.d.ts +160 -0
  39. package/dist/types/flow-model.d.ts +46 -0
  40. package/dist/types/history.d.ts +18 -0
  41. package/dist/types/overlay.d.ts +17 -0
  42. package/dist/types/plugin.d.ts +64 -0
  43. package/dist/types/schema.d.ts +77 -0
  44. package/dist/utils/path.d.ts +7 -0
  45. package/dist/utils/uuid.d.ts +1 -0
  46. package/package.json +55 -0
@@ -0,0 +1,2709 @@
1
+ import { ref as B, computed as z, onScopeDispose as ze, defineComponent as ie, onBeforeUnmount as Ne, createElementBlock as M, openBlock as C, normalizeStyle as we, createElementVNode as $, createVNode as Oe, createCommentVNode as O, normalizeClass as Q, Transition as je, withCtx as De, withModifiers as qe, createTextVNode as Ae, renderSlot as ce, onMounted as Ge, watch as de, createBlock as be, Fragment as se, renderList as ge, toDisplayString as ue, unref as le, resolveDynamicComponent as Ve, inject as We } from "vue";
2
+ import { Graph as Qe } from "@antv/x6";
3
+ import { register as Xe } from "@antv/x6-vue-shape";
4
+ function io() {
5
+ return {
6
+ version: "1.0",
7
+ nodes: {},
8
+ edges: {}
9
+ };
10
+ }
11
+ class K extends Error {
12
+ constructor(e) {
13
+ super(e), this.name = "CanvasConstraintError";
14
+ }
15
+ }
16
+ class Ye extends Error {
17
+ constructor(e) {
18
+ super(e), this.name = "CanvasSchemaError";
19
+ }
20
+ }
21
+ function xe(s, e, t) {
22
+ if (e.length === 0) {
23
+ if (t === void 0) return;
24
+ if (typeof t != "object" || t === null || Array.isArray(t))
25
+ throw new Error("Root value of payload/extensions/meta must be an object or undefined");
26
+ return t;
27
+ }
28
+ const o = s ? { ...s } : {};
29
+ let n = o;
30
+ for (let r = 0; r < e.length - 1; r++) {
31
+ const a = e[r], l = n[a];
32
+ l && typeof l == "object" && !Array.isArray(l) ? n[a] = { ...l } : n[a] = {}, n = n[a];
33
+ }
34
+ const i = e[e.length - 1];
35
+ return t === void 0 ? delete n[i] : n[i] = t, o;
36
+ }
37
+ function Se(s, e) {
38
+ switch (e.type) {
39
+ case "node.add":
40
+ return Ke(s, e.node);
41
+ case "node.move":
42
+ return Ze(s, e.nodeId, e.position);
43
+ case "node.remove":
44
+ return Je(s, e.nodeId);
45
+ case "node.update":
46
+ return et(s, e.nodeId, e.patch);
47
+ case "node.set-payload":
48
+ return tt(s, e.nodeId, e.path, e.value);
49
+ case "node.set-extensions":
50
+ return ot(s, e.nodeId, e.path, e.value);
51
+ case "edge.add":
52
+ return nt(s, e.edge);
53
+ case "edge.remove":
54
+ return st(s, e.edgeId);
55
+ case "edge.reconnect":
56
+ return it(s, e.edgeId, e.source, e.target);
57
+ case "edge.update":
58
+ return rt(s, e.edgeId, e.patch);
59
+ case "edge.set-payload":
60
+ return at(s, e.edgeId, e.path, e.value);
61
+ case "edge.label.update":
62
+ return lt(s, e.edgeId, e.labelId, e.patch);
63
+ case "model.set-meta":
64
+ return dt(s, e.path, e.value);
65
+ default:
66
+ throw new K(`Unknown command type: ${e.type}`);
67
+ }
68
+ }
69
+ function he(s, e) {
70
+ const t = s.nodes[e];
71
+ if (!t) throw new K(`Node "${e}" does not exist`);
72
+ return t;
73
+ }
74
+ function ve(s, e) {
75
+ const t = s.edges[e];
76
+ if (!t) throw new K(`Edge "${e}" does not exist`);
77
+ return t;
78
+ }
79
+ function fe(s, e, t) {
80
+ const o = s.nodes[e.nodeId];
81
+ if (!o)
82
+ throw new K(`${t} node "${e.nodeId}" does not exist`);
83
+ if (e.portId && o.ports && !o.ports.some((i) => i.id === e.portId))
84
+ throw new K(`${t} port "${e.portId}" not found on node "${e.nodeId}"`);
85
+ }
86
+ function ke(s, e, t) {
87
+ return { ...s, nodes: { ...s.nodes, [e]: t } };
88
+ }
89
+ function Ce(s, e, t) {
90
+ return { ...s, edges: { ...s.edges, [e]: t } };
91
+ }
92
+ function Ke(s, e) {
93
+ if (s.nodes[e.id])
94
+ throw new K(`Node id "${e.id}" already exists`);
95
+ return { ...s, nodes: { ...s.nodes, [e.id]: e } };
96
+ }
97
+ function Ze(s, e, t) {
98
+ const o = he(s, e);
99
+ return ke(s, e, { ...o, position: t });
100
+ }
101
+ function Je(s, e) {
102
+ he(s, e);
103
+ const { [e]: t, ...o } = s.nodes, n = {};
104
+ for (const [i, r] of Object.entries(s.edges))
105
+ r.source.nodeId !== e && r.target.nodeId !== e && (n[i] = r);
106
+ return { ...s, nodes: o, edges: n };
107
+ }
108
+ function et(s, e, t) {
109
+ const o = he(s, e);
110
+ return ke(s, e, { ...o, ...t, id: o.id });
111
+ }
112
+ function tt(s, e, t, o) {
113
+ const n = he(s, e), i = xe(n.payload, t, o);
114
+ return ke(s, e, { ...n, payload: i });
115
+ }
116
+ function ot(s, e, t, o) {
117
+ const n = he(s, e), i = xe(n.extensions, t, o);
118
+ return ke(s, e, { ...n, extensions: i });
119
+ }
120
+ function nt(s, e) {
121
+ if (s.edges[e.id])
122
+ throw new K(`Edge id "${e.id}" already exists`);
123
+ if (fe(s, e.source, "Source"), fe(s, e.target, "Target"), e.labels) {
124
+ const t = /* @__PURE__ */ new Set();
125
+ for (const o of e.labels) {
126
+ if (t.has(o.id))
127
+ throw new K(`Duplicate label id "${o.id}" in edge "${e.id}"`);
128
+ t.add(o.id);
129
+ }
130
+ }
131
+ return { ...s, edges: { ...s.edges, [e.id]: e } };
132
+ }
133
+ function st(s, e) {
134
+ ve(s, e);
135
+ const { [e]: t, ...o } = s.edges;
136
+ return { ...s, edges: o };
137
+ }
138
+ function it(s, e, t, o) {
139
+ const n = ve(s, e), i = t ?? n.source, r = o ?? n.target;
140
+ return fe(s, i, "Source"), fe(s, r, "Target"), Ce(s, e, { ...n, source: i, target: r });
141
+ }
142
+ function rt(s, e, t) {
143
+ const o = ve(s, e), n = { ...o, ...t, id: o.id };
144
+ return t.source && fe(s, n.source, "Source"), t.target && fe(s, n.target, "Target"), Ce(s, e, n);
145
+ }
146
+ function at(s, e, t, o) {
147
+ const n = ve(s, e), i = xe(n.payload, t, o);
148
+ return Ce(s, e, { ...n, payload: i });
149
+ }
150
+ function lt(s, e, t, o) {
151
+ const n = ve(s, e);
152
+ if (!n.labels)
153
+ throw new K(`Edge "${e}" has no labels`);
154
+ const i = n.labels.findIndex((a) => a.id === t);
155
+ if (i === -1)
156
+ throw new K(`Label "${t}" not found in edge "${e}"`);
157
+ const r = [...n.labels];
158
+ return r[i] = { ...r[i], ...o, id: t }, Ce(s, e, { ...n, labels: r });
159
+ }
160
+ function dt(s, e, t) {
161
+ const o = xe(s.meta, e, t);
162
+ return { ...s, meta: o };
163
+ }
164
+ function ct(s, e) {
165
+ const t = e?.maxHistorySize ?? 100, o = B(s), n = [], i = [], r = B(!1), a = B(!1);
166
+ function l() {
167
+ r.value = n.length > 0, a.value = i.length > 0;
168
+ }
169
+ function c(b) {
170
+ const m = o.value;
171
+ let p = m;
172
+ for (const P of b.commands)
173
+ p = Se(p, P);
174
+ return n.push({ snapshot: m, envelope: b }), n.length > t && n.shift(), i.length = 0, o.value = p, l(), p;
175
+ }
176
+ function u() {
177
+ const b = n.pop();
178
+ return b ? (i.push({ snapshot: o.value, envelope: b.envelope }), o.value = b.snapshot, l(), b.snapshot) : null;
179
+ }
180
+ function d() {
181
+ const b = i.pop();
182
+ if (!b) return null;
183
+ n.push({ snapshot: o.value, envelope: b.envelope });
184
+ let m = o.value;
185
+ for (const p of b.envelope.commands)
186
+ m = Se(m, p);
187
+ return o.value = m, l(), m;
188
+ }
189
+ function w() {
190
+ n.length = 0, i.length = 0, l();
191
+ }
192
+ function f() {
193
+ return o.value;
194
+ }
195
+ function E(b) {
196
+ o.value = b, w();
197
+ }
198
+ return {
199
+ currentFlowModel: o,
200
+ execute: c,
201
+ undo: u,
202
+ redo: d,
203
+ canUndo: r,
204
+ canRedo: a,
205
+ get undoStack() {
206
+ return n.map((b) => b.envelope);
207
+ },
208
+ get redoStack() {
209
+ return i.map((b) => b.envelope);
210
+ },
211
+ clear: w,
212
+ createSnapshot: f,
213
+ replaceFlowModel: E
214
+ };
215
+ }
216
+ function ut(s) {
217
+ return s !== null && typeof s == "object" && s.rejected === !0;
218
+ }
219
+ class ft {
220
+ plugins = [];
221
+ editorContext = null;
222
+ runtimeCtx = null;
223
+ /** 每次 attachRuntime 递增,detachRuntime 时旧 generation 的异步调用自动作废 */
224
+ runtimeVersion = 0;
225
+ install(e, t) {
226
+ this.plugins = [...e].sort((o, n) => (o.priority ?? 100) - (n.priority ?? 100)), this.editorContext = t;
227
+ for (const o of this.plugins)
228
+ o.install?.(t);
229
+ }
230
+ /**
231
+ * 挂载运行时上下文并调用各插件的 attachRuntime。
232
+ * 异步插件(如动态 import X6 插件)在 await 返回后会检查 generation,
233
+ * 若 detachRuntime 已被调用(generation 已变),则跳过 graph.use() 等操作。
234
+ */
235
+ attachRuntime(e) {
236
+ const t = ++this.runtimeVersion;
237
+ this.runtimeCtx = e;
238
+ const o = this.createSafeRuntimeContext(e, t);
239
+ for (const n of this.plugins)
240
+ n.attachRuntime?.(o);
241
+ }
242
+ /** 按安装的逆序 detach,保证后安装的插件先释放运行时资源 */
243
+ detachRuntime() {
244
+ for (const e of [...this.plugins].reverse())
245
+ e.detachRuntime?.();
246
+ this.runtimeCtx = null;
247
+ }
248
+ /**
249
+ * 为 attachRuntime 创建保护代理:graph.use() 等可能在异步回调中调用,
250
+ * 如果在 await 期间 detachRuntime 已执行,代理会将 graph 操作变为 no-op。
251
+ */
252
+ createSafeRuntimeContext(e, t) {
253
+ const o = this, n = new Proxy(e.graph, {
254
+ get(i, r, a) {
255
+ const l = Reflect.get(i, r, a);
256
+ return r === "use" && typeof l == "function" ? function(...u) {
257
+ if (o.runtimeVersion === t)
258
+ return l.apply(i, u);
259
+ } : l;
260
+ }
261
+ });
262
+ return { ...e, graph: n };
263
+ }
264
+ dispose() {
265
+ for (const e of [...this.plugins].reverse())
266
+ e.dispose?.();
267
+ this.plugins = [], this.editorContext = null, this.runtimeCtx = null;
268
+ }
269
+ transformCommand(e) {
270
+ if (!this.editorContext) return { envelope: e };
271
+ let t = e;
272
+ for (const o of this.plugins) {
273
+ if (!o.transformCommand) continue;
274
+ const n = this.createPreview(t), i = o.transformCommand(t, n, this.editorContext);
275
+ if (i === null)
276
+ return {
277
+ rejected: !0,
278
+ error: {
279
+ code: "plugin_rejected",
280
+ reason: "",
281
+ source: o.name
282
+ }
283
+ };
284
+ if (ut(i))
285
+ return {
286
+ rejected: !0,
287
+ error: {
288
+ code: i.code ?? "plugin_rejected",
289
+ reason: i.reason,
290
+ source: o.name
291
+ }
292
+ };
293
+ t = i;
294
+ }
295
+ return { envelope: t };
296
+ }
297
+ afterCommand(e, t, o) {
298
+ if (this.editorContext)
299
+ for (const n of this.plugins)
300
+ n.afterCommand?.(e, t, o, this.editorContext);
301
+ }
302
+ dispatchUiEvent(e) {
303
+ if (this.runtimeCtx)
304
+ for (const t of this.plugins)
305
+ t.onUiEvent?.(e, this.runtimeCtx);
306
+ }
307
+ dispatchSelectionChange(e) {
308
+ if (this.runtimeCtx)
309
+ for (const t of this.plugins)
310
+ t.onSelectionChange?.(e, this.runtimeCtx);
311
+ }
312
+ dispatchKeyboardShortcut(e) {
313
+ if (!this.runtimeCtx) return !1;
314
+ for (const t of this.plugins)
315
+ if (t.onKeyboardShortcut?.(e, this.runtimeCtx))
316
+ return !0;
317
+ return !1;
318
+ }
319
+ collectContextMenuItems(e) {
320
+ if (!this.runtimeCtx) return [];
321
+ const t = [];
322
+ for (const o of this.plugins) {
323
+ const n = o.onBlankContextMenu?.(e, this.runtimeCtx);
324
+ n && t.push(...n);
325
+ }
326
+ return t;
327
+ }
328
+ /** 汇聚所有插件的工具栏项,相同 id 的后注册覆盖先注册,最终按 order 排序 */
329
+ collectToolbarItems() {
330
+ if (!this.editorContext) return [];
331
+ const e = /* @__PURE__ */ new Map();
332
+ for (const t of this.plugins) {
333
+ const o = t.provideToolbarItems?.(this.editorContext);
334
+ if (o)
335
+ for (const n of o)
336
+ e.set(n.id, n);
337
+ }
338
+ return [...e.values()].sort((t, o) => (t.order ?? 0) - (o.order ?? 0));
339
+ }
340
+ /** 合并所有插件对某节点的装饰(className / borderColor / badge),后注册覆盖先注册 */
341
+ collectNodeDecorations(e) {
342
+ if (!this.editorContext) return;
343
+ let t;
344
+ for (const o of this.plugins) {
345
+ const n = o.decorateNode?.(e, this.editorContext);
346
+ n && (t = t ? { ...t, ...n } : n);
347
+ }
348
+ return t;
349
+ }
350
+ /** 合并所有插件对某边的装饰(className / strokeColor),后注册覆盖先注册 */
351
+ collectEdgeDecorations(e) {
352
+ if (!this.editorContext) return;
353
+ let t;
354
+ for (const o of this.plugins) {
355
+ const n = o.decorateEdge?.(e, this.editorContext);
356
+ n && (t = t ? { ...t, ...n } : n);
357
+ }
358
+ return t;
359
+ }
360
+ collectExtendedApi() {
361
+ if (!this.runtimeCtx) return {};
362
+ const e = {};
363
+ for (const t of this.plugins) {
364
+ const o = t.extendApi?.(this.runtimeCtx.api, this.runtimeCtx);
365
+ o && Object.assign(e, o);
366
+ }
367
+ return e;
368
+ }
369
+ /** 基于当前 FlowModel 和待执行命令序列,生成预览 FlowModel 供 transformCommand 使用 */
370
+ createPreview(e) {
371
+ const t = this.editorContext;
372
+ return {
373
+ previewFlowModel(o) {
374
+ const n = o ?? e.commands;
375
+ let i = t.flowModel.value;
376
+ for (const r of n)
377
+ i = Se(i, r);
378
+ return i;
379
+ }
380
+ };
381
+ }
382
+ }
383
+ function ro(s) {
384
+ const { initialFlowModel: e, schema: t, plugins: o = [], historyOptions: n } = s, i = ct(e, n), r = B(s.mode ?? "edit"), a = B(!1), l = B(null), c = B([]), u = {}, d = new ft();
385
+ function w(m, p, P, g = "user:toolbar") {
386
+ const v = {
387
+ id: `history-${Date.now()}`,
388
+ source: g,
389
+ label: m,
390
+ timestamp: Date.now(),
391
+ commands: []
392
+ };
393
+ d.afterCommand(v, p, P), c.value = d.collectToolbarItems(), s.onCommandResult?.({
394
+ status: "applied",
395
+ envelope: v,
396
+ flowModel: P
397
+ }), s.onFlowModelChange?.({
398
+ flowModel: P,
399
+ prevFlowModel: p,
400
+ envelope: v,
401
+ source: g
402
+ });
403
+ }
404
+ const f = {
405
+ execute: i.execute,
406
+ undo() {
407
+ const m = i.currentFlowModel.value, p = i.undo();
408
+ return p && w("撤销", m, p), p;
409
+ },
410
+ redo() {
411
+ const m = i.currentFlowModel.value, p = i.redo();
412
+ return p && w("重做", m, p), p;
413
+ },
414
+ get canUndo() {
415
+ return i.canUndo;
416
+ },
417
+ get canRedo() {
418
+ return i.canRedo;
419
+ },
420
+ get undoStack() {
421
+ return i.undoStack;
422
+ },
423
+ get redoStack() {
424
+ return i.redoStack;
425
+ },
426
+ clear: i.clear,
427
+ createSnapshot: i.createSnapshot,
428
+ replaceFlowModel(m) {
429
+ const p = i.currentFlowModel.value;
430
+ i.replaceFlowModel(m), w("替换 FlowModel", p, m, "system:replace");
431
+ }
432
+ }, E = {
433
+ flowModel: z(() => i.currentFlowModel.value),
434
+ history: f,
435
+ schema: t,
436
+ mode: r,
437
+ executeCommand: b,
438
+ replaceFlowModel(m) {
439
+ f.replaceFlowModel(m);
440
+ },
441
+ setMode(m) {
442
+ r.value = m;
443
+ },
444
+ selectionMode: a,
445
+ setSelectionMode(m) {
446
+ a.value = m;
447
+ },
448
+ api: l,
449
+ toolbarItems: c,
450
+ extendedApi: u,
451
+ _pluginManager: d
452
+ };
453
+ d.install(o, {
454
+ flowModel: E.flowModel,
455
+ history: f,
456
+ schema: t,
457
+ mode: r,
458
+ executeCommand: b
459
+ }), c.value = d.collectToolbarItems(), ze(() => {
460
+ d.dispose();
461
+ });
462
+ function b(m) {
463
+ const p = d.transformCommand(m);
464
+ if ("rejected" in p) {
465
+ const v = {
466
+ status: "rejected",
467
+ envelope: m,
468
+ error: p.error
469
+ };
470
+ return s.onCommandResult?.(v), v;
471
+ }
472
+ const P = p.envelope, g = i.currentFlowModel.value;
473
+ try {
474
+ const v = i.execute(P), N = {
475
+ status: "applied",
476
+ envelope: P,
477
+ flowModel: v
478
+ };
479
+ return d.afterCommand(P, g, v), c.value = d.collectToolbarItems(), s.onCommandResult?.(N), s.onFlowModelChange?.({
480
+ flowModel: v,
481
+ prevFlowModel: g,
482
+ envelope: P,
483
+ source: P.source
484
+ }), N;
485
+ } catch (v) {
486
+ if (v instanceof K) {
487
+ const N = {
488
+ status: "invalid",
489
+ envelope: P,
490
+ error: {
491
+ code: "constraint_violated",
492
+ reason: v.message,
493
+ source: "engine"
494
+ }
495
+ };
496
+ return s.onCommandResult?.(N), N;
497
+ }
498
+ throw v;
499
+ }
500
+ }
501
+ return E;
502
+ }
503
+ class pt {
504
+ graph;
505
+ schema;
506
+ shapeRegistry;
507
+ resolveNodeDecoration;
508
+ resolveEdgeDecoration;
509
+ resolveCanvasContext;
510
+ knownNodeIds = /* @__PURE__ */ new Set();
511
+ knownEdgeIds = /* @__PURE__ */ new Set();
512
+ syncing = !1;
513
+ prevNodeDecorationClasses = /* @__PURE__ */ new Map();
514
+ prevNodeDecorationColors = /* @__PURE__ */ new Set();
515
+ prevEdgeDecorationClasses = /* @__PURE__ */ new Map();
516
+ prevEdgeDecorationColors = /* @__PURE__ */ new Set();
517
+ highlightedNodeIds = /* @__PURE__ */ new Set();
518
+ highlightedEdgeIds = /* @__PURE__ */ new Set();
519
+ hoveredEdgeId = null;
520
+ defaultHighlightedNodeIds = /* @__PURE__ */ new Set();
521
+ defaultHighlightedEdgeIds = /* @__PURE__ */ new Set();
522
+ prevEdgeStyleIds = /* @__PURE__ */ new Set();
523
+ /** x6CellConfig 中 attrs.body 的基线值,清理时恢复而非删除 */
524
+ nodeDefaultAttrs = /* @__PURE__ */ new Map();
525
+ /** x6EdgeConfig 中 attrs.line 的基线值,清理时恢复而非删除 */
526
+ edgeDefaultAttrs = /* @__PURE__ */ new Map();
527
+ lastModel = null;
528
+ constructor(e, t, o, n, i, r) {
529
+ this.graph = e, this.schema = t, this.shapeRegistry = o, this.resolveNodeDecoration = n, this.resolveEdgeDecoration = i, this.resolveCanvasContext = r;
530
+ }
531
+ syncFlowModel(e) {
532
+ if (!this.syncing) {
533
+ this.syncing = !0, this.lastModel = e;
534
+ try {
535
+ const t = this.resolveNodes(e), o = this.resolveEdges(e);
536
+ this.syncNodes(t), this.syncEdges(o, e);
537
+ } finally {
538
+ this.syncing = !1;
539
+ }
540
+ }
541
+ }
542
+ get isSyncing() {
543
+ return this.syncing;
544
+ }
545
+ /**
546
+ * 从 x6CellConfig.attrs.body 中提取基线描边,用于管理层清理时恢复。
547
+ * 仅在节点首次创建时调用一次。
548
+ */
549
+ saveNodeDefaultAttrs(e, t) {
550
+ const n = t.x6CellConfig?.attrs?.body;
551
+ if (!n) return;
552
+ const i = {};
553
+ let r = !1;
554
+ n.stroke !== void 0 && (i.stroke = n.stroke, r = !0), n.strokeWidth !== void 0 && (i.strokeWidth = n.strokeWidth, r = !0), r && this.nodeDefaultAttrs.set(e, i);
555
+ }
556
+ /**
557
+ * 从 x6EdgeConfig.attrs.line 中提取基线描边,用于管理层清理时恢复。
558
+ */
559
+ saveEdgeDefaultAttrs(e, t) {
560
+ const n = t?.x6EdgeConfig?.attrs?.line;
561
+ if (!n) return;
562
+ const i = {};
563
+ let r = !1;
564
+ n.stroke !== void 0 && (i.stroke = n.stroke, r = !0), n.strokeWidth !== void 0 && (i.strokeWidth = n.strokeWidth, r = !0), n.strokeDasharray !== void 0 && (i.strokeDasharray = n.strokeDasharray, r = !0), r && this.edgeDefaultAttrs.set(e, i);
565
+ }
566
+ /** 恢复节点 attr 到基线值;无基线时移除。 */
567
+ restoreNodeAttr(e, t, o) {
568
+ const n = this.nodeDefaultAttrs.get(e.id)?.[o];
569
+ n !== void 0 ? e.setAttrByPath(t, n) : e.removeAttrByPath(t);
570
+ }
571
+ /** 恢复边 attr 到基线值;无基线时移除。 */
572
+ restoreEdgeAttr(e, t, o) {
573
+ const n = this.edgeDefaultAttrs.get(e.id)?.[o];
574
+ n !== void 0 ? e.setAttrByPath(t, n) : e.removeAttrByPath(t);
575
+ }
576
+ /** 让正式边接管交互式预览边时,恢复 schema 定义的端点 marker。 */
577
+ syncEdgeMarker(e, t, o) {
578
+ const i = t?.x6EdgeConfig?.attrs?.line?.[o], r = `line/${o}`;
579
+ e.removeAttrByPath(r), i !== void 0 && e.setAttrByPath(r, i);
580
+ }
581
+ dispose() {
582
+ this.knownNodeIds.clear(), this.knownEdgeIds.clear();
583
+ }
584
+ resolveNodes(e) {
585
+ const t = /* @__PURE__ */ new Map();
586
+ for (const [o, n] of Object.entries(e.nodes)) {
587
+ const i = this.schema.nodeTypes[n.type];
588
+ if (!i)
589
+ throw new Ye(
590
+ `Unknown node type "${n.type}" for node "${o}". Registered types: [${Object.keys(this.schema.nodeTypes).join(", ")}]. Register the type in CanvasSchema.nodeTypes before using it in a FlowModel.`
591
+ );
592
+ const r = this.shapeRegistry.registerNodeType(n.type, i.component), a = i.getSize(n), l = i.getPorts?.(n) ?? n.ports ?? [];
593
+ t.set(o, { model: n, definition: i, shapeName: r, size: a, ports: l });
594
+ }
595
+ return t;
596
+ }
597
+ resolveEdges(e) {
598
+ const t = /* @__PURE__ */ new Map();
599
+ for (const [o, n] of Object.entries(e.edges)) {
600
+ const i = n.type ?? this.schema.defaultEdgeType ?? "default", r = this.schema.edgeTypes?.[i];
601
+ t.set(o, { model: n, definition: r });
602
+ }
603
+ return t;
604
+ }
605
+ syncNodes(e) {
606
+ const t = new Set(e.keys());
607
+ for (const o of this.knownNodeIds)
608
+ if (!t.has(o)) {
609
+ const n = this.graph.getCellById(o);
610
+ n && this.graph.removeCell(n), this.knownNodeIds.delete(o), this.defaultHighlightedNodeIds.delete(o), this.prevNodeDecorationClasses.delete(o), this.prevNodeDecorationColors.delete(o), this.nodeDefaultAttrs.delete(o);
611
+ }
612
+ for (const [o, n] of e) {
613
+ const i = this.graph.getCellById(o);
614
+ i ? this.updateExistingNode(i, n) : this.addNewNode(o, n);
615
+ }
616
+ }
617
+ updateExistingNode(e, t) {
618
+ const { model: o, size: n, ports: i, definition: r } = t, a = e.getPosition();
619
+ (a.x !== o.position.x || a.y !== o.position.y) && e.setPosition(o.position.x, o.position.y);
620
+ const l = e.getSize();
621
+ (l.width !== n.width || l.height !== n.height) && e.setSize(n.width, n.height, { silent: !0 }), this.syncNodePorts(e, i), e.setData({ ...o }, { silent: !0 }), this.applyNodeBehavior(e, o, r), this.applyNodeHighlightAndDecoration(e, o);
622
+ }
623
+ syncNodePorts(e, t) {
624
+ const o = e.getPorts(), n = new Set(t.map((r) => r.id)), i = new Set(o.map((r) => r.id));
625
+ for (const r of o)
626
+ r.id && !n.has(r.id) && e.removePort(r.id);
627
+ for (const r of t)
628
+ i.has(r.id) || e.addPort({ id: r.id, group: r.group, ...r.x6PortConfig });
629
+ }
630
+ addNewNode(e, t) {
631
+ const { model: o, shapeName: n, size: i, ports: r, definition: a } = t, l = {
632
+ id: o.id,
633
+ shape: n,
634
+ x: o.position.x,
635
+ y: o.position.y,
636
+ width: i.width,
637
+ height: i.height,
638
+ data: { ...o },
639
+ ports: {
640
+ groups: {
641
+ top: {
642
+ position: "top",
643
+ attrs: {
644
+ circle: { r: 6, magnet: !0, fill: "#3a84ff", stroke: "#fff", strokeWidth: 1, visibility: "hidden" }
645
+ }
646
+ },
647
+ right: {
648
+ position: "right",
649
+ attrs: {
650
+ circle: { r: 6, magnet: !0, fill: "#3a84ff", stroke: "#fff", strokeWidth: 1, visibility: "hidden" }
651
+ }
652
+ },
653
+ bottom: {
654
+ position: "bottom",
655
+ attrs: {
656
+ circle: { r: 6, magnet: !0, fill: "#3a84ff", stroke: "#fff", strokeWidth: 1, visibility: "hidden" }
657
+ }
658
+ },
659
+ left: {
660
+ position: "left",
661
+ attrs: {
662
+ circle: { r: 6, magnet: !0, fill: "#3a84ff", stroke: "#fff", strokeWidth: 1, visibility: "hidden" }
663
+ }
664
+ }
665
+ },
666
+ items: r.map((u) => ({ id: u.id, group: u.group, ...u.x6PortConfig }))
667
+ },
668
+ ...a.x6CellConfig
669
+ };
670
+ this.graph.addNode(l), this.knownNodeIds.add(e), this.saveNodeDefaultAttrs(e, a);
671
+ const c = this.graph.getCellById(e);
672
+ c && (this.applyNodeBehavior(c, o, a), this.applyNodeHighlightAndDecoration(c, o));
673
+ }
674
+ /**
675
+ * 将 schema 定义的 getBehavior 映射到 X6 节点属性。
676
+ * NodeBehaviorConfig 的每个字段都映射到 X6 Cell 对应能力:
677
+ * - draggable → 是否可拖拽移动
678
+ * - selectable → 是否可被选中(注意:X6 Selection 插件也有全局控制)
679
+ * - connectable → ports 的 magnet 属性,控制是否可从该节点发起连线
680
+ * - showPorts → ports 的可见性
681
+ * - deletable → 存入 cell data,由删除操作(插件/快捷键)自行读取判断
682
+ */
683
+ applyNodeBehavior(e, t, o) {
684
+ if (!o.getBehavior) return;
685
+ const n = this.resolveCanvasContext?.();
686
+ if (!n) return;
687
+ const i = o.getBehavior(t, n);
688
+ if (i.draggable !== void 0 && e.setProp("draggable", i.draggable, { silent: !0 }), i.connectable !== void 0) {
689
+ const a = i.connectable;
690
+ for (const l of e.getPorts())
691
+ e.setPortProp(l.id, "attrs/circle/magnet", a, { silent: !0 });
692
+ }
693
+ if (i.showPorts !== void 0) {
694
+ const a = i.showPorts;
695
+ for (const l of e.getPorts())
696
+ e.setPortProp(l.id, "attrs/circle/style/visibility", a ? "visible" : "hidden", { silent: !0 });
697
+ }
698
+ const r = e.getData() ?? {};
699
+ i.deletable !== void 0 && r._deletable !== i.deletable && e.setData({ ...r, _deletable: i.deletable }, { silent: !0 }), i.selectable !== void 0 && r._selectable !== i.selectable && e.setData({ ...e.getData(), _selectable: i.selectable }, { silent: !0 });
700
+ }
701
+ syncEdges(e, t) {
702
+ const o = new Set(e.keys());
703
+ for (const n of this.knownEdgeIds)
704
+ if (!o.has(n)) {
705
+ const i = this.graph.getCellById(n);
706
+ i && this.graph.removeCell(i), this.knownEdgeIds.delete(n), this.defaultHighlightedEdgeIds.delete(n), this.prevEdgeDecorationClasses.delete(n), this.prevEdgeDecorationColors.delete(n), this.prevEdgeStyleIds.delete(n), this.edgeDefaultAttrs.delete(n);
707
+ }
708
+ for (const [n, i] of e) {
709
+ const r = this.graph.getCellById(n), { model: a, definition: l } = i;
710
+ r ? (this.updateExistingEdge(r, a, l, t), this.knownEdgeIds.has(n) || (this.knownEdgeIds.add(n), this.saveEdgeDefaultAttrs(n, l))) : this.addNewEdge(n, a, l);
711
+ }
712
+ }
713
+ /**
714
+ * 增量更新已有边的 source/target/router/connector/labels。
715
+ * X6 Edge.getSource() 返回 { cell, port } 格式,与 FlowEdgeModel 的 { nodeId, portId } 不同,
716
+ * 需要用 (currentSource as any).cell 来比较。
717
+ */
718
+ updateExistingEdge(e, t, o, n) {
719
+ const i = e.getSource(), r = e.getTarget();
720
+ if ((i.cell !== t.source.nodeId || i.port !== t.source.portId) && e.setSource({ cell: t.source.nodeId, port: t.source.portId }), (r.cell !== t.target.nodeId || r.port !== t.target.portId) && e.setTarget({ cell: t.target.nodeId, port: t.target.portId }), o?.router) {
721
+ const a = typeof o.router == "string" ? { name: o.router } : o.router;
722
+ e.setRouter(a);
723
+ }
724
+ if (o?.connector) {
725
+ const a = typeof o.connector == "string" ? { name: o.connector } : o.connector;
726
+ e.setConnector(a);
727
+ }
728
+ this.syncEdgeMarker(e, o, "sourceMarker"), this.syncEdgeMarker(e, o, "targetMarker"), this.syncEdgeLabels(e, t), e.setData({ ...t }, { silent: !0 }), this.applyEdgeStyleAndDecoration(e, t, o);
729
+ }
730
+ syncEdgeLabels(e, t) {
731
+ if (!t.labels?.length) {
732
+ e.getLabels().length > 0 && e.setLabels([]);
733
+ return;
734
+ }
735
+ const o = t.labels.map((n) => ({
736
+ attrs: {
737
+ label: { text: n.text ?? "" }
738
+ },
739
+ position: n.position != null ? { distance: n.position } : void 0
740
+ }));
741
+ e.setLabels(o);
742
+ }
743
+ addNewEdge(e, t, o) {
744
+ const n = {
745
+ id: t.id,
746
+ source: { cell: t.source.nodeId, port: t.source.portId },
747
+ target: { cell: t.target.nodeId, port: t.target.portId },
748
+ data: { ...t },
749
+ zIndex: -1
750
+ };
751
+ o?.router && (n.router = typeof o.router == "string" ? { name: o.router } : o.router), o?.connector && (n.connector = typeof o.connector == "string" ? { name: o.connector } : o.connector), o?.x6EdgeConfig && Object.assign(n, o.x6EdgeConfig), t.labels?.length && (n.labels = t.labels.map((r) => ({
752
+ attrs: { label: { text: r.text ?? "" } },
753
+ position: r.position != null ? { distance: r.position } : void 0
754
+ }))), this.graph.addEdge(n), this.knownEdgeIds.add(e), this.saveEdgeDefaultAttrs(e, o);
755
+ const i = this.graph.getCellById(e);
756
+ i && this.applyEdgeStyleAndDecoration(i, t, o);
757
+ }
758
+ /**
759
+ * 外部通知选区、高亮或 hover 变化时,重算所有边的视觉样式。
760
+ * 每条边走统一分层管道 applyEdgeStyleAndDecoration,
761
+ * 保证 defaultHighlight → schema style() → plugin decoration 的覆盖顺序。
762
+ */
763
+ refreshEdgeStyles() {
764
+ if (this.lastModel)
765
+ for (const [e, t] of Object.entries(this.lastModel.edges)) {
766
+ const o = this.graph.getCellById(e);
767
+ if (!o?.isEdge()) continue;
768
+ const n = t.type ?? this.schema.defaultEdgeType ?? "default", i = this.schema.edgeTypes?.[n];
769
+ this.applyEdgeStyleAndDecoration(o, t, i);
770
+ }
771
+ }
772
+ /**
773
+ * 重算所有节点的高亮 + 装饰视觉。
774
+ */
775
+ refreshNodeHighlights() {
776
+ if (this.lastModel)
777
+ for (const [e, t] of Object.entries(this.lastModel.nodes)) {
778
+ const o = this.graph.getCellById(e);
779
+ o?.isNode() && this.applyNodeHighlightAndDecoration(o, t);
780
+ }
781
+ }
782
+ /**
783
+ * 单节点的高亮 + 装饰统一管道。
784
+ * 所有路径(FlowModel 同步更新/新增节点/显式刷新高亮)必须走此方法。
785
+ *
786
+ * body/stroke 的分层优先级(低 → 高):
787
+ * 1. 默认高亮 (#3a84ff) — 节点在 highlightedNodeIds 中时兜底
788
+ * 2. 插件装饰 (decorateNode().borderColor) — 始终覆盖高亮
789
+ *
790
+ * 最终值 = decorationColor ?? highlightColor ?? (清除)。
791
+ * 只在"曾经设过 → 现在无值"时执行 removeAttrByPath,避免误删 X6 原始样式。
792
+ */
793
+ applyNodeHighlightAndDecoration(e, t) {
794
+ const o = this.highlightedNodeIds.has(e.id), n = this.resolveNodeDecoration?.(t), i = this.prevNodeDecorationClasses.get(e.id);
795
+ i && (this.graph.findViewByCell(e)?.container?.classList.remove(i), this.prevNodeDecorationClasses.delete(e.id)), n?.className && (this.graph.findViewByCell(e)?.container?.classList.add(n.className), this.prevNodeDecorationClasses.set(e.id, n.className));
796
+ const r = n?.borderColor, l = r ?? (o ? "#3a84ff" : void 0), c = this.prevNodeDecorationColors.has(e.id) || this.defaultHighlightedNodeIds.has(e.id);
797
+ l ? (e.setAttrByPath("body/stroke", l), e.setAttrByPath("body/strokeWidth", 2)) : c && (this.restoreNodeAttr(e, "body/stroke", "stroke"), this.restoreNodeAttr(e, "body/strokeWidth", "strokeWidth")), r ? this.prevNodeDecorationColors.add(e.id) : this.prevNodeDecorationColors.delete(e.id), o && !r ? this.defaultHighlightedNodeIds.add(e.id) : this.defaultHighlightedNodeIds.delete(e.id);
798
+ }
799
+ setHoveredEdge(e) {
800
+ this.hoveredEdgeId = e;
801
+ }
802
+ setHighlightedNodes(e) {
803
+ this.highlightedNodeIds = new Set(e);
804
+ }
805
+ setHighlightedEdges(e) {
806
+ this.highlightedEdgeIds = new Set(e);
807
+ }
808
+ /**
809
+ * 单条边的 style + highlight + decoration 统一管道。
810
+ *
811
+ * line/stroke 的分层优先级(低 → 高):
812
+ * 1. 默认高亮 (#3a84ff) — 无 style() 时的兜底
813
+ * 2. Schema style() — 接收完整 EdgeRenderState,完全控制视觉
814
+ * 3. 插件装饰 (decorateEdge().strokeColor) — 始终覆盖 style()
815
+ *
816
+ * strokeWidth / strokeDasharray 仅由 schema style() 控制,不受装饰影响。
817
+ * 最终值 = decorationStroke ?? styleStroke ?? defaultHighlightStroke ?? (清除)。
818
+ */
819
+ applyEdgeStyleAndDecoration(e, t, o) {
820
+ const n = this.highlightedEdgeIds.has(e.id), i = this.resolveEdgeDecoration?.(t), r = this.prevEdgeDecorationClasses.get(e.id);
821
+ r && (this.graph.findViewByCell(e)?.container?.classList.remove(r), this.prevEdgeDecorationClasses.delete(e.id)), i?.className && (this.graph.findViewByCell(e)?.container?.classList.add(i.className), this.prevEdgeDecorationClasses.set(e.id, i.className));
822
+ let a, l, c;
823
+ if (o?.style) {
824
+ const E = this.graph.isSelected?.(e) ?? !1, b = this.hoveredEdgeId === e.id, m = o.style(t, { selected: E, highlighted: n, hovered: b });
825
+ a = m.stroke, l = m.strokeWidth, c = m.strokeDasharray;
826
+ }
827
+ const u = !o?.style && n ? "#3a84ff" : void 0, d = i?.strokeColor, w = d ?? a ?? u, f = !!o?.style || this.prevEdgeDecorationColors.has(e.id) || this.defaultHighlightedEdgeIds.has(e.id) || this.prevEdgeStyleIds.has(e.id);
828
+ w ? e.setAttrByPath("line/stroke", w) : f && this.restoreEdgeAttr(e, "line/stroke", "stroke"), o?.style ? (this.prevEdgeStyleIds.add(e.id), l ? e.setAttrByPath("line/strokeWidth", l) : this.restoreEdgeAttr(e, "line/strokeWidth", "strokeWidth"), c ? e.setAttrByPath("line/strokeDasharray", c) : this.restoreEdgeAttr(e, "line/strokeDasharray", "strokeDasharray")) : this.prevEdgeStyleIds.has(e.id) && (this.restoreEdgeAttr(e, "line/strokeWidth", "strokeWidth"), this.restoreEdgeAttr(e, "line/strokeDasharray", "strokeDasharray"), this.prevEdgeStyleIds.delete(e.id)), d ? this.prevEdgeDecorationColors.add(e.id) : this.prevEdgeDecorationColors.delete(e.id), u ? this.defaultHighlightedEdgeIds.add(e.id) : this.defaultHighlightedEdgeIds.delete(e.id);
829
+ }
830
+ }
831
+ let gt = 0;
832
+ function L() {
833
+ const s = Date.now().toString(36), e = Math.random().toString(36).substring(2, 8);
834
+ return `${s}-${e}-${++gt}`;
835
+ }
836
+ class ht {
837
+ instanceId = L();
838
+ registeredShapes = /* @__PURE__ */ new Map();
839
+ getShapeName(e) {
840
+ let t = this.registeredShapes.get(e);
841
+ return t || (t = `flow-node-${this.instanceId}-${e}`, this.registeredShapes.set(e, t)), t;
842
+ }
843
+ registerNodeType(e, t) {
844
+ const o = this.getShapeName(e);
845
+ return Xe({
846
+ shape: o,
847
+ component: t,
848
+ width: 100,
849
+ height: 40
850
+ }), o;
851
+ }
852
+ dispose() {
853
+ this.registeredShapes.clear();
854
+ }
855
+ }
856
+ class vt {
857
+ graph;
858
+ onUiEvent;
859
+ onCommand;
860
+ flowModelRef;
861
+ disposers = [];
862
+ constructor(e, t, o, n) {
863
+ this.graph = e, this.onUiEvent = t, this.onCommand = o, this.flowModelRef = n, this.bindEvents();
864
+ }
865
+ dispose() {
866
+ for (const e of this.disposers) e();
867
+ this.disposers = [];
868
+ }
869
+ bindEvents() {
870
+ this.on("node:click", ({ node: e }) => {
871
+ this.onUiEvent({ type: "node.click", nodeId: e.id });
872
+ }), this.on("node:dblclick", ({ node: e }) => {
873
+ this.onUiEvent({ type: "node.dblclick", nodeId: e.id });
874
+ }), this.on("node:contextmenu", ({ node: e, e: t }) => {
875
+ this.onUiEvent({
876
+ type: "node.contextmenu",
877
+ nodeId: e.id,
878
+ position: { x: t.clientX, y: t.clientY }
879
+ });
880
+ }), this.on("edge:click", ({ edge: e, e: t }) => {
881
+ const n = t.target?.closest?.(".x6-edge-label");
882
+ if (n) {
883
+ const r = e.getData?.()?.labels ?? [], a = n.parentElement?.querySelectorAll(".x6-edge-label"), l = a ? Array.from(a).indexOf(n) : 0, c = r[Math.max(0, l)];
884
+ this.onUiEvent({
885
+ type: "edge.label.click",
886
+ edgeId: e.id,
887
+ labelId: c?.id ?? `label-${l}`
888
+ });
889
+ return;
890
+ }
891
+ this.onUiEvent({ type: "edge.click", edgeId: e.id });
892
+ }), this.on("blank:click", ({ e }) => {
893
+ const t = this.graph.clientToLocal(e.clientX, e.clientY);
894
+ this.onUiEvent({ type: "blank.click", position: { x: t.x, y: t.y } });
895
+ }), this.on("blank:contextmenu", ({ e }) => {
896
+ this.onUiEvent({
897
+ type: "blank.contextmenu",
898
+ position: { x: e.clientX, y: e.clientY }
899
+ });
900
+ }), this.on("node:moved", ({ node: e }) => {
901
+ const t = e.getPosition();
902
+ this.onCommand({
903
+ id: L(),
904
+ source: "user:drag",
905
+ label: "移动节点",
906
+ timestamp: Date.now(),
907
+ commands: [{ type: "node.move", nodeId: e.id, position: { x: t.x, y: t.y } }]
908
+ });
909
+ }), this.on("edge:connected", ({ edge: e, isNew: t }) => {
910
+ const o = e.getSourceCell(), n = e.getTargetCell();
911
+ if (!o || !n) return;
912
+ const i = e.getSourcePortId(), r = e.getTargetPortId(), a = e.id in this.flowModelRef.value.edges;
913
+ t && !a ? this.onCommand({
914
+ id: L(),
915
+ source: "user:drag",
916
+ label: "连线",
917
+ timestamp: Date.now(),
918
+ commands: [
919
+ {
920
+ type: "edge.add",
921
+ edge: {
922
+ id: e.id,
923
+ source: { nodeId: o.id, portId: i ?? void 0 },
924
+ target: { nodeId: n.id, portId: r ?? void 0 }
925
+ }
926
+ }
927
+ ]
928
+ }) : this.onCommand({
929
+ id: L(),
930
+ source: "user:drag",
931
+ label: "重连",
932
+ timestamp: Date.now(),
933
+ commands: [
934
+ {
935
+ type: "edge.reconnect",
936
+ edgeId: e.id,
937
+ source: { nodeId: o.id, portId: i ?? void 0 },
938
+ target: { nodeId: n.id, portId: r ?? void 0 }
939
+ }
940
+ ]
941
+ });
942
+ }), this.on("edge:change:labels", ({ edge: e, current: t }) => {
943
+ const n = e.getData?.()?.labels ?? [];
944
+ if (!n.length || !t?.length) return;
945
+ const i = [];
946
+ for (let r = 0; r < Math.min(n.length, t.length); r++) {
947
+ const a = t[r], l = n[r];
948
+ if (!l?.id) continue;
949
+ const c = typeof a.position == "object" ? a.position?.distance : a.position;
950
+ c != null && i.push({
951
+ type: "edge.label.update",
952
+ edgeId: e.id,
953
+ labelId: l.id,
954
+ patch: { position: c }
955
+ });
956
+ }
957
+ i.length && this.onCommand({
958
+ id: L(),
959
+ source: "user:drag",
960
+ label: "拖动标签",
961
+ timestamp: Date.now(),
962
+ commands: i
963
+ });
964
+ });
965
+ }
966
+ on(e, t) {
967
+ this.graph.on(e, t), this.disposers.push(() => this.graph.off(e, t));
968
+ }
969
+ }
970
+ function yt(s, e) {
971
+ const t = B(null);
972
+ function o(i) {
973
+ const r = s.getCellById(i);
974
+ if (!r || !r.isNode()) return null;
975
+ const a = r, l = a.getPosition(), c = a.getSize(), u = { x: l.x, y: l.y, width: c.width, height: c.height }, d = s.localToGraph(u);
976
+ return new DOMRect(d.x, d.y, d.width, d.height);
977
+ }
978
+ function n(i, r) {
979
+ const a = s.getCellById(i);
980
+ if (!a || !a.isNode()) return null;
981
+ const l = a, c = l.getData() ?? {}, u = c.type, f = ((u ? e.nodeTypes[u] : void 0)?.getOverlayAnchors?.(c) ?? {})[r], E = f && typeof f == "object" && "x" in f ? f : void 0, b = l.getPosition(), m = b.x + (E?.x ?? 0), p = b.y + (E?.y ?? 0), P = s.localToGraph({ x: m, y: p });
982
+ return {
983
+ x: P.x,
984
+ y: P.y
985
+ };
986
+ }
987
+ return {
988
+ overlayContainer: t,
989
+ getNodeScreenRect: o,
990
+ getAnchorScreenPosition: n
991
+ };
992
+ }
993
+ const mt = 100;
994
+ function bt({
995
+ graph: s,
996
+ overlayManager: e,
997
+ executeCommand: t,
998
+ schema: o,
999
+ flowModel: n,
1000
+ defaultInsertGap: i,
1001
+ getContextMenuItems: r,
1002
+ onHighlightChange: a,
1003
+ resolveNodeShape: l
1004
+ }) {
1005
+ let c = [], u = [], d = null, w = !1, f = null, E = !1;
1006
+ async function b() {
1007
+ if (w) return d;
1008
+ w = !0;
1009
+ try {
1010
+ const g = await import("./index-BAAMFT_J.js"), v = g.Dnd ?? g.default;
1011
+ return v ? (d = new v({
1012
+ target: s,
1013
+ scaled: !0,
1014
+ animation: !0,
1015
+ getDragNode: (N) => N.clone(),
1016
+ getDropNode: (N) => N.clone()
1017
+ }), d) : null;
1018
+ } catch {
1019
+ return console.warn("[flow-canvas] @antv/x6-plugin-dnd not available, add it to your dependencies"), null;
1020
+ }
1021
+ }
1022
+ async function m() {
1023
+ if (!E) {
1024
+ E = !0;
1025
+ try {
1026
+ const g = await import("./index-siYsjzl4.js"), v = g.Export ?? g.default;
1027
+ v && s.use(new v());
1028
+ } catch {
1029
+ console.warn("[flow-canvas] @antv/x6-plugin-export not available, add it to your dependencies");
1030
+ }
1031
+ }
1032
+ }
1033
+ const p = ({ node: g }) => {
1034
+ const v = g.getData?.();
1035
+ if (!v?._dndSessionId || v._dndSessionId !== f) return;
1036
+ f = null;
1037
+ const N = g.getPosition();
1038
+ s.removeNode(g.id);
1039
+ const { _dndSessionId: U, ...S } = v, I = S.id || L();
1040
+ t({
1041
+ id: L(),
1042
+ source: "user:drag",
1043
+ label: "拖入节点",
1044
+ timestamp: Date.now(),
1045
+ commands: [
1046
+ {
1047
+ type: "node.add",
1048
+ node: { ...S, id: I, position: { x: N.x, y: N.y } }
1049
+ }
1050
+ ]
1051
+ });
1052
+ };
1053
+ return s.on("node:added", p), {
1054
+ zoomIn() {
1055
+ s.zoom(0.1);
1056
+ },
1057
+ zoomOut() {
1058
+ s.zoom(-0.1);
1059
+ },
1060
+ zoomTo(g) {
1061
+ s.zoomTo(g);
1062
+ },
1063
+ zoomToFit() {
1064
+ s.zoomToFit({ padding: 40, maxScale: 1.5 });
1065
+ },
1066
+ getZoom() {
1067
+ return s.zoom();
1068
+ },
1069
+ centerContent() {
1070
+ s.centerContent();
1071
+ },
1072
+ scrollToOrigin() {
1073
+ s.translate(0, 0);
1074
+ },
1075
+ scrollToNode(g) {
1076
+ const v = s.getCellById(g);
1077
+ v && s.centerCell(v);
1078
+ },
1079
+ getSelection() {
1080
+ const g = s.getSelectedCells?.() ?? [];
1081
+ return {
1082
+ nodeIds: g.filter((v) => v.isNode()).map((v) => v.id),
1083
+ edgeIds: g.filter((v) => v.isEdge()).map((v) => v.id)
1084
+ };
1085
+ },
1086
+ selectNodes(g) {
1087
+ const v = g.map((N) => s.getCellById(N)).filter(Boolean);
1088
+ s.select?.(v);
1089
+ },
1090
+ selectEdges(g) {
1091
+ const v = g.map((N) => s.getCellById(N)).filter(Boolean);
1092
+ s.select?.(v);
1093
+ },
1094
+ clearSelection() {
1095
+ const g = s.getSelectedCells?.();
1096
+ g?.length && s.unselect?.(g);
1097
+ },
1098
+ registerDndSource(g, v) {
1099
+ const N = async (U) => {
1100
+ const S = await b();
1101
+ if (!S) return;
1102
+ const I = L();
1103
+ f = I;
1104
+ const j = v(), q = l?.(j.type), Y = s.createNode({
1105
+ width: q?.width ?? 154,
1106
+ height: q?.height ?? 54,
1107
+ shape: q?.shapeName ?? "rect",
1108
+ data: { ...j, _dndSessionId: I }
1109
+ });
1110
+ S.start(Y, U);
1111
+ };
1112
+ return g.addEventListener("mousedown", N), () => {
1113
+ g.removeEventListener("mousedown", N);
1114
+ };
1115
+ },
1116
+ /**
1117
+ * 通过编程方式发起连线:直接命中真实 port 元素,
1118
+ * 复用 X6 原生的连线拖拽流程与 connecting.createEdge 配置。
1119
+ */
1120
+ startConnection(g, v) {
1121
+ const N = s.getCellById(g);
1122
+ if (!N?.isNode()) return;
1123
+ const U = N, S = s.findViewByCell(U);
1124
+ if (!S) return;
1125
+ const I = S.findPortElem(v, "circle") ?? S.findPortElem(v);
1126
+ if (!I) return;
1127
+ const q = (I.matches?.("[magnet]") ? I : I.querySelector?.("[magnet]")) ?? I, Y = q.getBoundingClientRect(), oe = Y.left + Y.width / 2, Z = Y.top + Y.height / 2, X = new MouseEvent("mousedown", {
1128
+ clientX: oe,
1129
+ clientY: Z,
1130
+ button: 0,
1131
+ buttons: 1,
1132
+ bubbles: !0,
1133
+ cancelable: !0
1134
+ });
1135
+ q.dispatchEvent(X);
1136
+ },
1137
+ async exportAsImage(g) {
1138
+ await m();
1139
+ const v = s;
1140
+ return typeof v.toPNG != "function" ? (console.warn("[flow-canvas] exportAsImage requires @antv/x6-plugin-export, add it to your dependencies"), new Blob()) : new Promise((N) => {
1141
+ v.toPNG(
1142
+ (U) => {
1143
+ fetch(U).then((S) => S.blob()).then(N).catch(() => N(new Blob()));
1144
+ },
1145
+ {
1146
+ backgroundColor: g?.backgroundColor ?? "#ffffff",
1147
+ padding: g?.padding ?? 20,
1148
+ quality: g?.quality,
1149
+ copyStyles: !0
1150
+ }
1151
+ );
1152
+ });
1153
+ },
1154
+ async exportAsSVG() {
1155
+ await m();
1156
+ const g = s;
1157
+ return typeof g.toSVG != "function" ? (console.warn("[flow-canvas] exportAsSVG requires @antv/x6-plugin-export, add it to your dependencies"), "") : new Promise((v) => {
1158
+ g.toSVG((N) => v(N));
1159
+ });
1160
+ },
1161
+ highlightNodes(g) {
1162
+ c = g, a?.(c, u);
1163
+ },
1164
+ highlightEdges(g) {
1165
+ u = g, a?.(c, u);
1166
+ },
1167
+ clearHighlight() {
1168
+ c = [], u = [], a?.([], []);
1169
+ },
1170
+ overlay: e,
1171
+ getContextMenuItems(g) {
1172
+ return r?.(g) ?? [];
1173
+ },
1174
+ insertNodeToRight(g, v, N) {
1175
+ const U = n.value, S = U.nodes[g];
1176
+ if (!S)
1177
+ return {
1178
+ status: "invalid",
1179
+ envelope: { id: "", source: "user:toolbar", timestamp: Date.now(), commands: [] },
1180
+ error: { code: "constraint_violated", reason: `Source node "${g}" not found`, source: "api" }
1181
+ };
1182
+ const I = N?.gap ?? i ?? mt, j = o.nodeTypes[S.type], q = o.nodeTypes[v.type], Y = j?.getSize(S) ?? { width: 154, height: 54 }, oe = q?.getSize({ ...v, position: { x: 0, y: 0 } }) ?? {
1183
+ width: 154,
1184
+ height: 54
1185
+ }, Z = {
1186
+ x: S.position.x + Y.width + I,
1187
+ y: S.position.y + (Y.height - oe.height) / 2
1188
+ }, X = v.id || L(), ee = { ...v, id: X, position: Z }, V = [{ type: "node.add", node: ee }], pe = oe.width + I, ne = { x: Z.x, y: Z.y, width: oe.width, height: oe.height };
1189
+ for (const [J, G] of Object.entries(U.nodes)) {
1190
+ if (J === g || J === X) continue;
1191
+ const te = o.nodeTypes[G.type]?.getSize(G) ?? { width: 154, height: 54 }, H = ne.x < G.position.x + te.width && ne.x + ne.width > G.position.x, Ie = ne.y < G.position.y + te.height && ne.y + ne.height > G.position.y;
1192
+ H && Ie && V.push({
1193
+ type: "node.move",
1194
+ nodeId: J,
1195
+ position: { x: G.position.x + pe, y: G.position.y }
1196
+ });
1197
+ }
1198
+ if (N?.autoWireEdges) {
1199
+ const J = S.ports?.find((H) => H.group === "right"), G = ee.ports?.find((H) => H.group === "left"), ye = ee.ports?.find((H) => H.group === "right"), te = J ? Object.values(U.edges).find(
1200
+ (H) => H.source.nodeId === g && H.source.portId === J.id
1201
+ ) : Object.values(U.edges).find((H) => H.source.nodeId === g);
1202
+ if (te) {
1203
+ const H = te.target;
1204
+ V.push({ type: "edge.remove", edgeId: te.id }), V.push({
1205
+ type: "edge.add",
1206
+ edge: {
1207
+ id: L(),
1208
+ source: { nodeId: g, portId: J?.id },
1209
+ target: { nodeId: X, portId: G?.id }
1210
+ }
1211
+ }), V.push({
1212
+ type: "edge.add",
1213
+ edge: {
1214
+ id: L(),
1215
+ source: { nodeId: X, portId: ye?.id },
1216
+ target: H
1217
+ }
1218
+ });
1219
+ } else
1220
+ V.push({
1221
+ type: "edge.add",
1222
+ edge: {
1223
+ id: L(),
1224
+ source: { nodeId: g, portId: J?.id },
1225
+ target: { nodeId: X, portId: G?.id }
1226
+ }
1227
+ });
1228
+ }
1229
+ const Ee = {
1230
+ id: L(),
1231
+ source: N?.source ?? "user:toolbar",
1232
+ label: N?.label ?? "插入节点",
1233
+ timestamp: Date.now(),
1234
+ commands: V
1235
+ };
1236
+ return t(Ee);
1237
+ },
1238
+ onGraphEvent(g, v) {
1239
+ return s.on(g, v), () => s.off(g, v);
1240
+ },
1241
+ unsafeGetGraph() {
1242
+ return s;
1243
+ }
1244
+ };
1245
+ }
1246
+ function wt() {
1247
+ const s = B(null), e = B(!1);
1248
+ let t = null;
1249
+ function o(a) {
1250
+ t && (clearTimeout(t), t = null), s.value = a;
1251
+ }
1252
+ function n() {
1253
+ t = setTimeout(() => {
1254
+ s.value = null, t = null;
1255
+ }, 100);
1256
+ }
1257
+ function i() {
1258
+ t && (clearTimeout(t), t = null);
1259
+ }
1260
+ function r() {
1261
+ t && clearTimeout(t);
1262
+ }
1263
+ return { hoveredNodeId: s, isDraggingNode: e, enter: o, leave: n, cancelLeave: i, cleanup: r };
1264
+ }
1265
+ const Pe = 10;
1266
+ function Te(s, e) {
1267
+ const t = s.getTotalLength();
1268
+ if (t === 0) return { ...e, length: 0, totalLength: 0 };
1269
+ let o = s.getPointAtLength(0), n = 1 / 0;
1270
+ const i = 50, r = t / i;
1271
+ let a = 0;
1272
+ for (let d = 0; d <= i; d++) {
1273
+ const w = d * r, f = s.getPointAtLength(w), E = (f.x - e.x) ** 2 + (f.y - e.y) ** 2;
1274
+ E < n && (n = E, o = f, a = w);
1275
+ }
1276
+ const l = Math.max(0, a - r), c = Math.min(t, a + r), u = (c - l) / 20;
1277
+ for (let d = l; d <= c; d += u) {
1278
+ const w = s.getPointAtLength(d), f = (w.x - e.x) ** 2 + (w.y - e.y) ** 2;
1279
+ f < n && (n = f, o = w, a = d);
1280
+ }
1281
+ return { x: o.x, y: o.y, length: a, totalLength: t };
1282
+ }
1283
+ function Re(s, e) {
1284
+ return s < Pe || s > e - Pe;
1285
+ }
1286
+ function $e() {
1287
+ const s = "http://www.w3.org/2000/svg", e = document.createElementNS(s, "g");
1288
+ e.setAttribute("class", "flow-canvas-edge-delete-tool"), e.style.cursor = "pointer";
1289
+ const t = document.createElementNS(s, "rect");
1290
+ t.setAttribute("width", "20"), t.setAttribute("height", "20"), t.setAttribute("x", "-10"), t.setAttribute("y", "-10"), t.setAttribute("rx", "4"), t.setAttribute("ry", "4"), t.setAttribute("fill", "#3a84ff"), e.appendChild(t);
1291
+ const o = document.createElementNS(s, "text");
1292
+ return o.setAttribute("font-family", "flow-canvas"), o.setAttribute("font-size", "16"), o.setAttribute("fill", "#ffffff"), o.setAttribute("text-anchor", "middle"), o.setAttribute("dominant-baseline", "central"), o.textContent = "", e.appendChild(o), e;
1293
+ }
1294
+ function xt(s) {
1295
+ let e = null, t = null;
1296
+ function o(a, l) {
1297
+ i(), t = a;
1298
+ const c = s.getCellById(a);
1299
+ if (!c?.isEdge()) return;
1300
+ const u = s.findViewByCell(c);
1301
+ if (!u) return;
1302
+ const d = u.container.querySelector("path");
1303
+ if (!d) return;
1304
+ const w = s.clientToLocal(l.clientX, l.clientY), f = Te(d, w);
1305
+ if (Re(f.length, f.totalLength)) return;
1306
+ const E = $e();
1307
+ E.setAttribute("transform", `translate(${f.x}, ${f.y})`), u.container.appendChild(E), e = E;
1308
+ }
1309
+ function n(a) {
1310
+ if (!t) return;
1311
+ const l = s.getCellById(t);
1312
+ if (!l?.isEdge()) return;
1313
+ const c = s.findViewByCell(l);
1314
+ if (!c) return;
1315
+ const u = c.container.querySelector("path");
1316
+ if (!u) return;
1317
+ const d = s.clientToLocal(a.clientX, a.clientY), w = Te(u, d);
1318
+ if (Re(w.length, w.totalLength))
1319
+ e && e.setAttribute("display", "none");
1320
+ else if (e)
1321
+ e.removeAttribute("display"), e.setAttribute("transform", `translate(${w.x}, ${w.y})`);
1322
+ else {
1323
+ const f = $e();
1324
+ f.setAttribute("transform", `translate(${w.x}, ${w.y})`), c.container.appendChild(f), e = f;
1325
+ }
1326
+ }
1327
+ function i() {
1328
+ e && (e.remove(), e = null), t = null;
1329
+ }
1330
+ function r(a) {
1331
+ a === t && (e = null, t = null);
1332
+ }
1333
+ return { show: o, move: n, remove: i, handleEdgeRemoved: r };
1334
+ }
1335
+ function kt(s) {
1336
+ let e = null, t = 0;
1337
+ function o(u) {
1338
+ const d = u ? "visible" : "hidden";
1339
+ for (const w of s.getNodes())
1340
+ for (const f of w.getPorts())
1341
+ w.setPortProp(f.id, "attrs/circle/visibility", d);
1342
+ }
1343
+ function n(u) {
1344
+ if (!e)
1345
+ for (const d of u.getPorts())
1346
+ u.setPortProp(d.id, "attrs/circle/visibility", "visible");
1347
+ }
1348
+ function i(u) {
1349
+ if (!e)
1350
+ for (const d of u.getPorts())
1351
+ u.setPortProp(d.id, "attrs/circle/visibility", "hidden");
1352
+ }
1353
+ function r(u) {
1354
+ u.getTargetCell() || (e = u.id, o(!0));
1355
+ }
1356
+ function a() {
1357
+ e = null, o(!1), t = Date.now() + 300;
1358
+ }
1359
+ function l(u) {
1360
+ u === e && (e = null, o(!1));
1361
+ }
1362
+ function c() {
1363
+ return !e && Date.now() >= t;
1364
+ }
1365
+ return {
1366
+ showNodePorts: n,
1367
+ hideNodePorts: i,
1368
+ handleEdgeAdded: r,
1369
+ handleEdgeConnected: a,
1370
+ handleEdgeRemoved: l,
1371
+ canShowEdgeTool: c
1372
+ };
1373
+ }
1374
+ const Ct = { class: "flow-canvas-node-actions__bar" }, Et = /* @__PURE__ */ ie({
1375
+ __name: "node-actions-toolbar",
1376
+ props: {
1377
+ node: {},
1378
+ position: {},
1379
+ config: {},
1380
+ behavior: {}
1381
+ },
1382
+ emits: ["action"],
1383
+ setup(s, { emit: e }) {
1384
+ const t = s, o = e, n = z(() => ({
1385
+ debug: {
1386
+ visible: t.config.showDebug && t.behavior.debuggable !== !1,
1387
+ disabled: t.behavior.debugDisabled === !0
1388
+ },
1389
+ delete: {
1390
+ visible: t.config.showDelete && t.behavior.deletable !== !1,
1391
+ disabled: t.behavior.deleteDisabled === !0
1392
+ },
1393
+ copy: {
1394
+ visible: t.config.showCopy && t.behavior.copyable !== !1,
1395
+ disabled: t.behavior.copyDisabled === !0
1396
+ },
1397
+ copyInsert: {
1398
+ visible: t.config.showCopyInsert && t.behavior.copyable !== !1,
1399
+ disabled: t.behavior.copyInsertDisabled === !0
1400
+ },
1401
+ disconnect: {
1402
+ visible: t.config.showDisconnect && t.behavior.disconnectable !== !1,
1403
+ disabled: t.behavior.disconnectDisabled === !0
1404
+ }
1405
+ })), i = z(() => n.value.copy.visible || n.value.copyInsert.visible || n.value.disconnect.visible), r = B(!1);
1406
+ let a = null;
1407
+ function l() {
1408
+ a && (clearTimeout(a), a = null), r.value = !0;
1409
+ }
1410
+ function c() {
1411
+ a = setTimeout(() => {
1412
+ r.value = !1, a = null;
1413
+ }, 100);
1414
+ }
1415
+ return Ne(() => {
1416
+ a && clearTimeout(a);
1417
+ }), (u, d) => (C(), M("div", {
1418
+ class: "flow-canvas-node-actions",
1419
+ style: we({ left: `${s.position.x}px`, top: `${s.position.y}px` })
1420
+ }, [
1421
+ $("div", Ct, [
1422
+ n.value.debug.visible ? (C(), M("i", {
1423
+ key: 0,
1424
+ class: Q(["flow-canvas-icon canvas-debug flow-canvas-node-actions__icon", { "is-disabled": n.value.debug.disabled }]),
1425
+ onClick: d[0] || (d[0] = (w) => !n.value.debug.disabled && o("action", "debug", s.node.id))
1426
+ }, null, 2)) : O("", !0),
1427
+ n.value.delete.visible ? (C(), M("i", {
1428
+ key: 1,
1429
+ class: Q(["flow-canvas-icon canvas-shanchu flow-canvas-node-actions__icon", { "is-disabled": n.value.delete.disabled }]),
1430
+ onClick: d[1] || (d[1] = (w) => !n.value.delete.disabled && o("action", "delete", s.node.id))
1431
+ }, null, 2)) : O("", !0),
1432
+ i.value ? (C(), M("div", {
1433
+ key: 2,
1434
+ class: "flow-canvas-node-actions__more-wrapper",
1435
+ onMouseenter: l,
1436
+ onMouseleave: c
1437
+ }, [...d[5] || (d[5] = [
1438
+ $("i", { class: "flow-canvas-icon canvas-gengduo flow-canvas-node-actions__icon" }, null, -1)
1439
+ ])], 32)) : O("", !0)
1440
+ ]),
1441
+ Oe(je, { name: "flow-canvas-fade" }, {
1442
+ default: De(() => [
1443
+ r.value && i.value ? (C(), M("div", {
1444
+ key: 0,
1445
+ class: "flow-canvas-node-actions__dropdown",
1446
+ onMouseenter: l,
1447
+ onMouseleave: c
1448
+ }, [
1449
+ n.value.copy.visible ? (C(), M("div", {
1450
+ key: 0,
1451
+ class: Q(["flow-canvas-node-actions__dropdown-item", { "is-disabled": n.value.copy.disabled }]),
1452
+ onClick: d[2] || (d[2] = (w) => !n.value.copy.disabled && o("action", "copy", s.node.id))
1453
+ }, [...d[6] || (d[6] = [
1454
+ $("i", { class: "flow-canvas-icon canvas-copy-fuzhi-2" }, null, -1),
1455
+ $("span", null, "复制", -1)
1456
+ ])], 2)) : O("", !0),
1457
+ n.value.copyInsert.visible ? (C(), M("div", {
1458
+ key: 1,
1459
+ class: Q(["flow-canvas-node-actions__dropdown-item", { "is-disabled": n.value.copyInsert.disabled }]),
1460
+ onClick: d[3] || (d[3] = (w) => !n.value.copyInsert.disabled && o("action", "copy-insert", s.node.id))
1461
+ }, [...d[7] || (d[7] = [
1462
+ $("i", { class: "flow-canvas-icon canvas-fuzhibingcharu" }, null, -1),
1463
+ $("span", null, "复制并插入", -1)
1464
+ ])], 2)) : O("", !0),
1465
+ n.value.disconnect.visible ? (C(), M("div", {
1466
+ key: 2,
1467
+ class: Q(["flow-canvas-node-actions__dropdown-item", { "is-disabled": n.value.disconnect.disabled }]),
1468
+ onClick: d[4] || (d[4] = (w) => !n.value.disconnect.disabled && o("action", "disconnect", s.node.id))
1469
+ }, [...d[8] || (d[8] = [
1470
+ $("i", { class: "flow-canvas-icon canvas-unlock-jiebang" }, null, -1),
1471
+ $("span", null, "断开连线", -1)
1472
+ ])], 2)) : O("", !0)
1473
+ ], 32)) : O("", !0)
1474
+ ]),
1475
+ _: 1
1476
+ })
1477
+ ], 4));
1478
+ }
1479
+ }), re = (s, e) => {
1480
+ const t = s.__vccOpts || s;
1481
+ for (const [o, n] of e)
1482
+ t[o] = n;
1483
+ return t;
1484
+ }, It = /* @__PURE__ */ re(Et, [["__scopeId", "data-v-14d6590b"]]), Mt = {
1485
+ key: 0,
1486
+ class: "flow-canvas-quick-add__tooltip"
1487
+ }, St = 5, Nt = /* @__PURE__ */ ie({
1488
+ __name: "node-quick-add-popover",
1489
+ props: {
1490
+ node: {},
1491
+ portPosition: {},
1492
+ tooltipText: {}
1493
+ },
1494
+ emits: ["open", "close", "start-drag", "mouseenter", "mouseleave"],
1495
+ setup(s, { expose: e, emit: t }) {
1496
+ const o = s, n = t, i = B(), r = B(), a = B(!1), l = B(!1);
1497
+ let c = null, u = !1, d = null;
1498
+ function w(S) {
1499
+ S.preventDefault(), S.stopPropagation(), c = { x: S.clientX, y: S.clientY }, u = !1, document.addEventListener("mousemove", f), document.addEventListener("mouseup", E);
1500
+ }
1501
+ function f(S) {
1502
+ if (!c) return;
1503
+ const I = S.clientX - c.x, j = S.clientY - c.y;
1504
+ Math.sqrt(I * I + j * j) >= St && (u = !0, b(), n("start-drag", o.node.id));
1505
+ }
1506
+ function E() {
1507
+ b(), u || m(), c = null, u = !1;
1508
+ }
1509
+ function b() {
1510
+ document.removeEventListener("mousemove", f), document.removeEventListener("mouseup", E);
1511
+ }
1512
+ function m() {
1513
+ l.value ? P() : p();
1514
+ }
1515
+ function p() {
1516
+ l.value = !0, n("open", o.node.id), requestAnimationFrame(() => {
1517
+ document.addEventListener("mousedown", g);
1518
+ });
1519
+ }
1520
+ function P() {
1521
+ l.value = !1, n("close"), document.removeEventListener("mousedown", g);
1522
+ }
1523
+ function g(S) {
1524
+ const I = S.target;
1525
+ i.value?.contains(I) || r.value?.contains(I) || P();
1526
+ }
1527
+ function v() {
1528
+ l.value || n("mouseleave");
1529
+ }
1530
+ function N() {
1531
+ d && (clearTimeout(d), d = null), n("mouseenter");
1532
+ }
1533
+ function U() {
1534
+ d = setTimeout(() => {
1535
+ P(), n("mouseleave"), d = null;
1536
+ }, 150);
1537
+ }
1538
+ return Ne(() => {
1539
+ b(), d && clearTimeout(d), document.removeEventListener("mousedown", g);
1540
+ }), e({ closePopover: P }), (S, I) => (C(), M("div", {
1541
+ class: "flow-canvas-quick-add",
1542
+ style: we({ left: `${s.portPosition.x}px`, top: `${s.portPosition.y}px` }),
1543
+ onMouseenter: I[2] || (I[2] = (j) => n("mouseenter")),
1544
+ onMouseleave: v,
1545
+ onClick: I[3] || (I[3] = qe(() => {
1546
+ }, ["stop"]))
1547
+ }, [
1548
+ $("div", {
1549
+ ref_key: "btnRef",
1550
+ ref: i,
1551
+ class: Q(["flow-canvas-quick-add__btn", { "is-hovered": a.value, "is-active": l.value }]),
1552
+ onMouseenter: I[0] || (I[0] = (j) => a.value = !0),
1553
+ onMouseleave: I[1] || (I[1] = (j) => a.value = !1),
1554
+ onMousedown: w
1555
+ }, [...I[4] || (I[4] = [
1556
+ $("i", { class: "flow-canvas-icon canvas-zoom-add" }, null, -1)
1557
+ ])], 34),
1558
+ a.value && !l.value ? (C(), M("div", Mt, [...I[5] || (I[5] = [
1559
+ $("div", null, [
1560
+ $("b", null, "点击"),
1561
+ Ae(" 添加节点")
1562
+ ], -1),
1563
+ $("div", null, [
1564
+ $("b", null, "拖拽"),
1565
+ Ae(" 连接节点")
1566
+ ], -1)
1567
+ ])])) : O("", !0),
1568
+ Oe(je, { name: "flow-canvas-fade" }, {
1569
+ default: De(() => [
1570
+ l.value ? (C(), M("div", {
1571
+ key: 0,
1572
+ ref_key: "popoverRef",
1573
+ ref: r,
1574
+ class: "flow-canvas-quick-add__popover",
1575
+ onMouseenter: N,
1576
+ onMouseleave: U
1577
+ }, [
1578
+ ce(S.$slots, "default", {}, () => [
1579
+ I[6] || (I[6] = $("div", { class: "flow-canvas-quick-add__default-content" }, "节点快捷操作面板", -1))
1580
+ ], !0)
1581
+ ], 544)) : O("", !0)
1582
+ ]),
1583
+ _: 3
1584
+ })
1585
+ ], 36));
1586
+ }
1587
+ }), Dt = /* @__PURE__ */ re(Nt, [["__scopeId", "data-v-deb5af25"]]), _t = /* @__PURE__ */ ie({
1588
+ __name: "canvas-runtime-core",
1589
+ props: {
1590
+ editor: {},
1591
+ graphOptions: {},
1592
+ nodeActions: {},
1593
+ quickAdd: {}
1594
+ },
1595
+ emits: ["ui-event"],
1596
+ setup(s, { emit: e }) {
1597
+ const t = s, o = e, n = B(), i = B(), r = B();
1598
+ let a, l, c, u;
1599
+ const d = wt(), { hoveredNodeId: w, isDraggingNode: f } = d, E = d.cancelLeave, b = d.leave, m = B(null);
1600
+ let p = null;
1601
+ function P(x) {
1602
+ return v(), te(x) ? (m.value = x, !0) : (m.value = null, !1);
1603
+ }
1604
+ function g() {
1605
+ p && clearTimeout(p), p = setTimeout(() => {
1606
+ m.value = null, p = null;
1607
+ }, 150);
1608
+ }
1609
+ function v() {
1610
+ p && (clearTimeout(p), p = null);
1611
+ }
1612
+ function N() {
1613
+ v(), d.cancelLeave();
1614
+ }
1615
+ function U() {
1616
+ g(), d.leave();
1617
+ }
1618
+ let S = null, I = null, j = null;
1619
+ const q = B(0), Y = z(
1620
+ () => {
1621
+ if (q.value, !t.editor.api.value) return [];
1622
+ const x = t.editor.flowModel.value, k = t.editor.api.value.overlay, y = [];
1623
+ for (const [D, T] of Object.entries(x.nodes)) {
1624
+ const A = t.editor._pluginManager.collectNodeDecorations(T);
1625
+ if (!A?.badge) continue;
1626
+ const R = k.getNodeScreenRect(D);
1627
+ R && y.push({
1628
+ nodeId: D,
1629
+ x: R.x + R.width - 4,
1630
+ y: R.y - 8,
1631
+ badge: A.badge
1632
+ });
1633
+ }
1634
+ return y;
1635
+ }
1636
+ ), oe = z(() => {
1637
+ q.value;
1638
+ const x = w.value;
1639
+ if (!x || !t.editor.api.value) return [];
1640
+ const y = t.editor.flowModel.value.nodes[x];
1641
+ if (!y) return [];
1642
+ const D = t.editor.schema.nodeTypes[y.type];
1643
+ if (!D?.getOverlayAnchors) return [];
1644
+ const T = D.getOverlayAnchors(y), A = t.editor.api.value.overlay, R = {};
1645
+ for (const W of Object.keys(T)) {
1646
+ const ae = A.getAnchorScreenPosition(x, W);
1647
+ ae && (R[W] = ae);
1648
+ }
1649
+ return [{ node: y, screenAnchors: R }];
1650
+ }), Z = z(() => ({
1651
+ showDebug: !1,
1652
+ showDelete: !0,
1653
+ showCopy: !0,
1654
+ showCopyInsert: !0,
1655
+ showDisconnect: !0,
1656
+ insertGap: 100,
1657
+ ...t.nodeActions
1658
+ })), X = z(() => {
1659
+ q.value;
1660
+ const x = w.value;
1661
+ if (!x || f.value || !t.editor.api.value || t.editor.mode.value !== "edit") return null;
1662
+ const k = t.editor.flowModel.value, y = k.nodes[x];
1663
+ if (!y) return null;
1664
+ const D = t.editor.api.value.overlay.getNodeScreenRect(x);
1665
+ if (!D) return null;
1666
+ const A = t.editor.schema.nodeTypes[y.type]?.getBehavior?.(y, {
1667
+ api: t.editor.api.value,
1668
+ flowModel: k,
1669
+ history: t.editor.history,
1670
+ mode: t.editor.mode.value
1671
+ }) ?? {};
1672
+ return A.showActions === !1 ? null : {
1673
+ node: y,
1674
+ position: { x: D.x + D.width, y: D.y + D.height + 4 },
1675
+ behavior: A
1676
+ };
1677
+ }), ee = z(() => ({
1678
+ enabled: !0,
1679
+ tooltipText: "",
1680
+ ...t.quickAdd
1681
+ })), V = z(() => {
1682
+ if (q.value, !ee.value.enabled) return null;
1683
+ const x = m.value;
1684
+ if (!x || f.value || !t.editor.api.value || t.editor.mode.value !== "edit") return null;
1685
+ const k = t.editor.flowModel.value, y = k.nodes[x];
1686
+ if (!y) return null;
1687
+ const T = t.editor.schema.nodeTypes[y.type]?.getBehavior?.(y, {
1688
+ api: t.editor.api.value,
1689
+ flowModel: k,
1690
+ history: t.editor.history,
1691
+ mode: t.editor.mode.value
1692
+ }) ?? {};
1693
+ if (T.quickAddEnabled === !1) return null;
1694
+ const A = t.editor.api.value.overlay.getNodeScreenRect(x);
1695
+ return A ? {
1696
+ node: y,
1697
+ portPosition: { x: A.x + A.width, y: A.y + A.height / 2 },
1698
+ behavior: T
1699
+ } : null;
1700
+ }), pe = B();
1701
+ function ne(x) {
1702
+ const k = V.value;
1703
+ k && o("ui-event", {
1704
+ type: "node.quick-add",
1705
+ nodeId: x,
1706
+ position: k.portPosition
1707
+ });
1708
+ }
1709
+ function Ee(x) {
1710
+ const k = t.editor.api.value;
1711
+ k && k.startConnection(x, "right");
1712
+ }
1713
+ function J(x, k) {
1714
+ const y = t.editor.api.value;
1715
+ if (!y) return;
1716
+ const D = k.id || L(), T = { ...k, id: D };
1717
+ y.insertNodeToRight(x, T, {
1718
+ autoWireEdges: !0,
1719
+ gap: Z.value.insertGap,
1720
+ source: "user:quick-add",
1721
+ label: "快捷插入节点"
1722
+ }).status === "applied" && o("ui-event", { type: "node.action.quick-insert", sourceNodeId: x, newNodeId: D }), pe.value?.closePopover();
1723
+ }
1724
+ function G(x) {
1725
+ return {
1726
+ id: L(),
1727
+ type: x.type,
1728
+ label: x.label,
1729
+ ports: x.ports ? JSON.parse(JSON.stringify(x.ports)) : void 0,
1730
+ payload: x.payload ? JSON.parse(JSON.stringify(x.payload)) : void 0,
1731
+ extensions: x.extensions ? JSON.parse(JSON.stringify(x.extensions)) : void 0
1732
+ };
1733
+ }
1734
+ function ye(x, k) {
1735
+ const y = t.editor, D = y.api.value;
1736
+ switch (x) {
1737
+ case "delete": {
1738
+ y.executeCommand({
1739
+ id: L(),
1740
+ source: "user:toolbar",
1741
+ label: "删除节点",
1742
+ timestamp: Date.now(),
1743
+ commands: [{ type: "node.remove", nodeId: k }]
1744
+ }), o("ui-event", { type: "node.action.delete", nodeId: k }), w.value = null;
1745
+ break;
1746
+ }
1747
+ case "copy": {
1748
+ if (!D) break;
1749
+ const T = y.flowModel.value.nodes[k];
1750
+ if (!T) break;
1751
+ const A = G(T);
1752
+ D.insertNodeToRight(k, A, {
1753
+ autoWireEdges: !1,
1754
+ gap: Z.value.insertGap,
1755
+ label: "复制节点"
1756
+ }), o("ui-event", { type: "node.action.copy", sourceNodeId: k, newNodeId: A.id });
1757
+ break;
1758
+ }
1759
+ case "copy-insert": {
1760
+ if (!D) break;
1761
+ const T = y.flowModel.value.nodes[k];
1762
+ if (!T) break;
1763
+ const A = G(T);
1764
+ D.insertNodeToRight(k, A, {
1765
+ autoWireEdges: !0,
1766
+ gap: Z.value.insertGap,
1767
+ label: "复制并插入节点"
1768
+ }), o("ui-event", { type: "node.action.copy-insert", sourceNodeId: k, newNodeId: A.id });
1769
+ break;
1770
+ }
1771
+ case "disconnect": {
1772
+ const T = y.flowModel.value, A = Object.entries(T.edges).filter(([, R]) => {
1773
+ const W = R;
1774
+ return W.source.nodeId === k || W.target.nodeId === k;
1775
+ }).map(([R]) => R);
1776
+ if (A.length === 0) break;
1777
+ y.executeCommand({
1778
+ id: L(),
1779
+ source: "user:toolbar",
1780
+ label: "断开连线",
1781
+ timestamp: Date.now(),
1782
+ commands: A.map((R) => ({ type: "edge.remove", edgeId: R }))
1783
+ }), o("ui-event", { type: "node.action.disconnect", nodeId: k, edgeIds: A });
1784
+ break;
1785
+ }
1786
+ case "debug": {
1787
+ o("ui-event", { type: "node.action.debug", nodeId: k });
1788
+ break;
1789
+ }
1790
+ }
1791
+ }
1792
+ function te(x) {
1793
+ if (!ee.value.enabled || t.editor.mode.value !== "edit") return !1;
1794
+ const k = t.editor.flowModel.value, y = k.nodes[x];
1795
+ return y ? (t.editor.schema.nodeTypes[y.type]?.getBehavior?.(y, {
1796
+ api: t.editor.api.value,
1797
+ flowModel: k,
1798
+ history: t.editor.history,
1799
+ mode: t.editor.mode.value
1800
+ }) ?? {}).quickAddEnabled !== !1 : !1;
1801
+ }
1802
+ function H(x) {
1803
+ if (t.editor.mode.value !== "edit") return;
1804
+ t.editor._pluginManager.dispatchKeyboardShortcut(x) && (x.preventDefault(), x.stopPropagation());
1805
+ }
1806
+ function Ie() {
1807
+ return {
1808
+ refX: 0,
1809
+ children: [
1810
+ {
1811
+ tagName: "path",
1812
+ d: "M -16 -5 L -8 0 L -16 5 Z",
1813
+ transform: "rotate(0)"
1814
+ },
1815
+ {
1816
+ tagName: "circle",
1817
+ cx: 0,
1818
+ cy: 0,
1819
+ r: 8,
1820
+ fill: "#3a84ff",
1821
+ stroke: "#3a84ff",
1822
+ transform: "rotate(0)"
1823
+ }
1824
+ ]
1825
+ };
1826
+ }
1827
+ function He(x) {
1828
+ const k = t.editor.schema.defaultEdgeType ?? "default", y = t.editor.schema.edgeTypes?.[k], D = {
1829
+ zIndex: -1,
1830
+ attrs: {
1831
+ line: {
1832
+ stroke: "#abb5cc",
1833
+ strokeWidth: 2,
1834
+ targetMarker: { name: "block", width: 8, height: 8 }
1835
+ }
1836
+ }
1837
+ };
1838
+ y?.router && (D.router = typeof y.router == "string" ? { name: y.router } : y.router), y?.connector && (D.connector = typeof y.connector == "string" ? { name: y.connector } : y.connector), y?.x6EdgeConfig && Object.assign(D, y.x6EdgeConfig);
1839
+ const T = D.attrs ?? {}, A = T.line ?? {};
1840
+ return D.attrs = {
1841
+ ...T,
1842
+ line: {
1843
+ ...A,
1844
+ targetMarker: Ie()
1845
+ }
1846
+ }, x.createEdge(D);
1847
+ }
1848
+ return Ge(() => {
1849
+ if (!i.value) return;
1850
+ const x = /* @__PURE__ */ new Set(["model", "container"]), k = {};
1851
+ if (t.graphOptions)
1852
+ for (const [h, _] of Object.entries(t.graphOptions)) {
1853
+ if (x.has(h)) {
1854
+ console.warn(`[flow-canvas] graphOptions.${h} is managed by the engine and will be ignored`);
1855
+ continue;
1856
+ }
1857
+ k[h] = _;
1858
+ }
1859
+ a = new Qe({
1860
+ container: i.value,
1861
+ autoResize: !0,
1862
+ background: { color: "#edf2fc" },
1863
+ grid: { visible: !0, size: 20, type: "dot" },
1864
+ panning: { enabled: !0 },
1865
+ mousewheel: { enabled: !0, modifiers: ["ctrl", "meta"] },
1866
+ connecting: {
1867
+ allowBlank: !1,
1868
+ allowMulti: !0,
1869
+ allowLoop: !1,
1870
+ allowNode: !1,
1871
+ allowEdge: !1,
1872
+ highlight: !0,
1873
+ anchor: "center",
1874
+ connectionPoint: "anchor",
1875
+ snap: { radius: 30 },
1876
+ createEdge() {
1877
+ return He(this);
1878
+ }
1879
+ },
1880
+ ...k
1881
+ }), c = new ht(), l = new pt(
1882
+ a,
1883
+ t.editor.schema,
1884
+ c,
1885
+ (h) => t.editor._pluginManager.collectNodeDecorations(h),
1886
+ (h) => t.editor._pluginManager.collectEdgeDecorations(h),
1887
+ () => t.editor.api.value ? {
1888
+ api: t.editor.api.value,
1889
+ flowModel: t.editor.flowModel.value,
1890
+ history: t.editor.history,
1891
+ mode: t.editor.mode.value
1892
+ } : null
1893
+ );
1894
+ const y = yt(a, t.editor.schema);
1895
+ r.value && (y.overlayContainer.value = r.value);
1896
+ const D = bt({
1897
+ graph: a,
1898
+ overlayManager: y,
1899
+ executeCommand: (h) => t.editor.executeCommand(h),
1900
+ schema: t.editor.schema,
1901
+ flowModel: t.editor.flowModel,
1902
+ defaultInsertGap: t.nodeActions?.insertGap,
1903
+ getContextMenuItems: (h) => t.editor._pluginManager.collectContextMenuItems(h),
1904
+ onHighlightChange: (h, _) => {
1905
+ l.setHighlightedNodes(h), l.setHighlightedEdges(_), l.refreshNodeHighlights(), l.refreshEdgeStyles();
1906
+ },
1907
+ resolveNodeShape: (h) => {
1908
+ const _ = t.editor.schema.nodeTypes[h];
1909
+ if (!_) return null;
1910
+ const F = c.registerNodeType(h, _.component), me = _.getSize({ id: "", type: h, position: { x: 0, y: 0 } });
1911
+ return { shapeName: F, width: me.width, height: me.height };
1912
+ }
1913
+ });
1914
+ t.editor.api.value = D;
1915
+ const T = {
1916
+ flowModel: t.editor.flowModel,
1917
+ history: t.editor.history,
1918
+ schema: t.editor.schema,
1919
+ mode: t.editor.mode,
1920
+ executeCommand: t.editor.executeCommand,
1921
+ api: D,
1922
+ overlay: y,
1923
+ graph: a
1924
+ };
1925
+ t.editor._pluginManager.attachRuntime(T);
1926
+ const A = t.editor._pluginManager.collectExtendedApi();
1927
+ Object.assign(t.editor.extendedApi, A), u = new vt(
1928
+ a,
1929
+ (h) => {
1930
+ (h.type === "node.click" || h.type === "node.dblclick" || h.type === "node.contextmenu") && d.enter(h.nodeId), t.editor._pluginManager.dispatchUiEvent(h), o("ui-event", h);
1931
+ },
1932
+ (h) => {
1933
+ l.isSyncing || t.editor.executeCommand(h);
1934
+ },
1935
+ t.editor.flowModel
1936
+ ), S = xt(a);
1937
+ const R = kt(a), W = a, ae = (h) => {
1938
+ const _ = W.isRubberbandEnabled?.() ?? !1;
1939
+ _ && W.disableRubberband?.(), h ? a.enablePanning() : a.disablePanning(), _ && W.enableRubberband?.();
1940
+ }, Me = () => {
1941
+ q.value++;
1942
+ };
1943
+ a.on("translate", Me), a.on("scale", Me), a.on("resize", Me), a.on("node:move", () => {
1944
+ f.value = !0;
1945
+ }), a.on("node:moved", () => {
1946
+ f.value = !1;
1947
+ }), a.on("node:mouseenter", ({ node: h }) => {
1948
+ d.enter(h.id), ee.value.enabled && P(h.id) || R.showNodePorts(h);
1949
+ }), a.on("node:mouseleave", ({ node: h }) => {
1950
+ d.leave(), ee.value.enabled && m.value === h.id ? g() : R.hideNodePorts(h);
1951
+ });
1952
+ function Fe(h) {
1953
+ const _ = a.getCellById(h);
1954
+ if (!_?.isNode()) return;
1955
+ const F = _, me = !f.value && te(h);
1956
+ for (const _e of F.getPorts()) {
1957
+ const Ue = me && _e.group === "right" ? "hidden" : "visible";
1958
+ F.setPortProp(_e.id, "attrs/circle/visibility", Ue);
1959
+ }
1960
+ }
1961
+ de(
1962
+ [m, f],
1963
+ ([h], [_]) => {
1964
+ if (_ && _ !== h) {
1965
+ const F = a.getCellById(_);
1966
+ F?.isNode() && R.hideNodePorts(F);
1967
+ }
1968
+ h && Fe(h);
1969
+ },
1970
+ { flush: "sync" }
1971
+ ), a.on("edge:added", ({ edge: h }) => {
1972
+ R.handleEdgeAdded(h);
1973
+ }), a.on("edge:connected", () => {
1974
+ R.handleEdgeConnected();
1975
+ }), a.on("edge:removed", ({ edge: h }) => {
1976
+ R.handleEdgeRemoved(h.id), S.handleEdgeRemoved(h.id);
1977
+ }), a.on("selection:changed", () => {
1978
+ const h = a.getSelectedCells?.() ?? [], _ = {
1979
+ nodeIds: h.filter((F) => F.isNode()).map((F) => F.id),
1980
+ edgeIds: h.filter((F) => F.isEdge()).map((F) => F.id)
1981
+ };
1982
+ t.editor._pluginManager.dispatchSelectionChange(_), o("ui-event", {
1983
+ type: "selection.change",
1984
+ nodeIds: _.nodeIds,
1985
+ edgeIds: _.edgeIds
1986
+ }), l.refreshEdgeStyles();
1987
+ }), a.on("edge:mouseenter", ({ edge: h, e: _ }) => {
1988
+ l.setHoveredEdge(h.id), l.refreshEdgeStyles(), t.editor.mode.value === "edit" && R.canShowEdgeTool() && S.show(h.id, _);
1989
+ }), I = (h) => S.move(h), a.container.addEventListener("mousemove", I), a.on("edge:mouseleave", () => {
1990
+ l.setHoveredEdge(null), l.refreshEdgeStyles(), S.remove();
1991
+ }), a.on("edge:click", ({ edge: h, e: _ }) => {
1992
+ _.target?.closest?.(".flow-canvas-edge-delete-tool") && t.editor.mode.value === "edit" && (S.remove(), t.editor.executeCommand({
1993
+ id: L(),
1994
+ source: "user:toolbar",
1995
+ label: "删除连线",
1996
+ timestamp: Date.now(),
1997
+ commands: [{ type: "edge.remove", edgeId: h.id }]
1998
+ }));
1999
+ }), n.value?.addEventListener("keydown", H), l.syncFlowModel(t.editor.flowModel.value), de(
2000
+ () => t.editor.flowModel.value,
2001
+ (h) => l.syncFlowModel(h)
2002
+ ), de(
2003
+ () => t.editor.selectionMode.value,
2004
+ (h) => {
2005
+ if (j?.(), j = null, h) {
2006
+ ae(!1), W.enableRubberband?.();
2007
+ const _ = () => {
2008
+ a.container.removeEventListener("mouseup", _), j = null, setTimeout(() => {
2009
+ t.editor.selectionMode.value && t.editor.setSelectionMode(!1);
2010
+ }, 50);
2011
+ };
2012
+ a.container.addEventListener("mouseup", _), j = () => a.container.removeEventListener("mouseup", _);
2013
+ } else
2014
+ W.disableRubberband?.(), ae(!0);
2015
+ }
2016
+ ), de(
2017
+ () => t.editor.mode.value,
2018
+ (h) => {
2019
+ const _ = h === "edit";
2020
+ ae(!0), _ ? W.enableSelection?.() : W.disableSelection?.();
2021
+ }
2022
+ );
2023
+ }), Ne(() => {
2024
+ d.cleanup(), p && clearTimeout(p), S?.remove(), j?.(), I && a?.container?.removeEventListener("mousemove", I), n.value?.removeEventListener("keydown", H), t.editor._pluginManager.detachRuntime(), t.editor.api.value = null;
2025
+ for (const x of Object.keys(t.editor.extendedApi))
2026
+ delete t.editor.extendedApi[x];
2027
+ u?.dispose(), l?.dispose(), c?.dispose(), a?.dispose();
2028
+ }), (x, k) => (C(), M("div", {
2029
+ ref_key: "rootRef",
2030
+ ref: n,
2031
+ class: "flow-canvas-runtime-core",
2032
+ tabindex: "0"
2033
+ }, [
2034
+ $("div", {
2035
+ ref_key: "containerRef",
2036
+ ref: i,
2037
+ class: "flow-canvas-runtime-core__graph"
2038
+ }, null, 512),
2039
+ $("div", {
2040
+ ref_key: "overlayContainerRef",
2041
+ ref: r,
2042
+ class: "flow-canvas-runtime-core__overlay"
2043
+ }, [
2044
+ (C(!0), M(se, null, ge(Y.value, (y) => (C(), M("div", {
2045
+ key: `badge-${y.nodeId}`,
2046
+ class: "flow-canvas-runtime-core__badge",
2047
+ style: we({ left: `${y.x}px`, top: `${y.y}px`, backgroundColor: y.badge.color })
2048
+ }, ue(y.badge.text), 5))), 128)),
2049
+ V.value ? (C(), be(Dt, {
2050
+ key: 0,
2051
+ ref_key: "quickAddPopoverRef",
2052
+ ref: pe,
2053
+ node: V.value.node,
2054
+ "port-position": V.value.portPosition,
2055
+ "tooltip-text": ee.value.tooltipText,
2056
+ onOpen: ne,
2057
+ onStartDrag: Ee,
2058
+ onMouseenter: N,
2059
+ onMouseleave: U
2060
+ }, {
2061
+ default: De(() => [
2062
+ ce(x.$slots, "quick-add-panel", {
2063
+ node: V.value.node,
2064
+ api: s.editor.api.value,
2065
+ insertNodeToRight: (y) => J(V.value.node.id, y),
2066
+ closePopover: () => pe.value?.closePopover()
2067
+ }, void 0, !0)
2068
+ ]),
2069
+ _: 3
2070
+ }, 8, ["node", "port-position", "tooltip-text"])) : O("", !0),
2071
+ X.value ? (C(), be(It, {
2072
+ key: 1,
2073
+ node: X.value.node,
2074
+ position: X.value.position,
2075
+ config: Z.value,
2076
+ behavior: X.value.behavior,
2077
+ onAction: ye,
2078
+ onMouseenter: le(E),
2079
+ onMouseleave: le(b)
2080
+ }, null, 8, ["node", "position", "config", "behavior", "onMouseenter", "onMouseleave"])) : O("", !0),
2081
+ (C(!0), M(se, null, ge(oe.value, (y) => (C(), M("div", {
2082
+ key: y.node.id,
2083
+ class: "flow-canvas-runtime-core__node-overlay",
2084
+ onMouseenter: k[0] || (k[0] = //@ts-ignore
2085
+ (...D) => le(E) && le(E)(...D)),
2086
+ onMouseleave: k[1] || (k[1] = //@ts-ignore
2087
+ (...D) => le(b) && le(b)(...D))
2088
+ }, [
2089
+ ce(x.$slots, "node-overlay", {
2090
+ node: y.node,
2091
+ screenAnchors: y.screenAnchors,
2092
+ api: s.editor.api.value
2093
+ }, void 0, !0)
2094
+ ], 32))), 128))
2095
+ ], 512)
2096
+ ], 512));
2097
+ }
2098
+ }), ao = /* @__PURE__ */ re(_t, [["__scopeId", "data-v-bba2427b"]]), At = { class: "flow-canvas-node-palette" }, Pt = ["data-node-type"], Tt = { class: "flow-canvas-node-palette__item-label" }, Rt = /* @__PURE__ */ ie({
2099
+ __name: "canvas-node-palette",
2100
+ props: {
2101
+ editor: {},
2102
+ items: {}
2103
+ },
2104
+ setup(s) {
2105
+ const e = s, t = B(), o = z(() => e.items ? e.items : Object.keys(e.editor.schema.nodeTypes).map((n) => ({
2106
+ type: n,
2107
+ label: n.charAt(0).toUpperCase() + n.slice(1)
2108
+ })));
2109
+ return de(
2110
+ [() => e.editor.api.value, o, t],
2111
+ ([n, i, r], a, l) => {
2112
+ if (!n || !r) return;
2113
+ const c = [];
2114
+ for (const u of i) {
2115
+ const d = r.querySelector(`[data-node-type="${u.type}"]`);
2116
+ if (!d) continue;
2117
+ const w = n.registerDndSource(d, () => ({
2118
+ id: L(),
2119
+ type: u.type,
2120
+ label: u.label,
2121
+ position: { x: 0, y: 0 }
2122
+ }));
2123
+ c.push(w);
2124
+ }
2125
+ l(() => {
2126
+ for (const u of c) u();
2127
+ });
2128
+ },
2129
+ { flush: "post" }
2130
+ ), (n, i) => (C(), M("div", At, [
2131
+ $("div", {
2132
+ ref_key: "listRef",
2133
+ ref: t,
2134
+ class: "flow-canvas-node-palette__list"
2135
+ }, [
2136
+ (C(!0), M(se, null, ge(o.value, (r) => (C(), M("div", {
2137
+ key: r.type,
2138
+ class: "flow-canvas-node-palette__item",
2139
+ "data-node-type": r.type
2140
+ }, [
2141
+ r.icon ? (C(), M("i", {
2142
+ key: 0,
2143
+ class: Q([r.icon, "flow-canvas-node-palette__item-icon"])
2144
+ }, null, 2)) : O("", !0),
2145
+ $("span", Tt, ue(r.label), 1)
2146
+ ], 8, Pt))), 128))
2147
+ ], 512)
2148
+ ]));
2149
+ }
2150
+ }), $t = /* @__PURE__ */ re(Rt, [["__scopeId", "data-v-300314b7"]]), Lt = { class: "flow-canvas-layout" }, Bt = { class: "flow-canvas-layout__main" }, zt = { class: "flow-canvas-layout__content" }, Ot = {
2151
+ key: 0,
2152
+ class: "flow-canvas-layout__footer"
2153
+ }, jt = /* @__PURE__ */ ie({
2154
+ __name: "canvas-layout",
2155
+ props: {
2156
+ sidebarCollapsed: { type: Boolean, default: !1 },
2157
+ sidebarWidth: { default: 260 },
2158
+ hideSidebar: { type: Boolean, default: !1 },
2159
+ hideFooter: { type: Boolean, default: !1 },
2160
+ editor: { default: void 0 },
2161
+ paletteItems: { default: void 0 }
2162
+ },
2163
+ emits: ["update:sidebarCollapsed"],
2164
+ setup(s) {
2165
+ return (e, t) => (C(), M("div", Lt, [
2166
+ !s.hideSidebar && (e.$slots.sidebar || s.editor) ? (C(), M("aside", {
2167
+ key: 0,
2168
+ class: Q(["flow-canvas-layout__sidebar", { "is-collapsed": s.sidebarCollapsed }]),
2169
+ style: we({ width: s.sidebarCollapsed ? "0px" : `${s.sidebarWidth}px` })
2170
+ }, [
2171
+ ce(e.$slots, "sidebar", {}, () => [
2172
+ s.editor ? (C(), be($t, {
2173
+ key: 0,
2174
+ editor: s.editor,
2175
+ items: s.paletteItems
2176
+ }, null, 8, ["editor", "items"])) : O("", !0)
2177
+ ], !0)
2178
+ ], 6)) : O("", !0),
2179
+ $("div", Bt, [
2180
+ $("div", zt, [
2181
+ ce(e.$slots, "default", {}, void 0, !0)
2182
+ ]),
2183
+ !s.hideFooter && e.$slots.footer ? (C(), M("div", Ot, [
2184
+ ce(e.$slots, "footer", {}, void 0, !0)
2185
+ ])) : O("", !0)
2186
+ ])
2187
+ ]));
2188
+ }
2189
+ }), lo = /* @__PURE__ */ re(jt, [["__scopeId", "data-v-26f35b6b"]]);
2190
+ function Ht(s) {
2191
+ const e = new Set(s?.exclude), t = [
2192
+ {
2193
+ id: "undo",
2194
+ type: "undo",
2195
+ group: "history",
2196
+ icon: "flow-canvas-icon canvas-undo",
2197
+ description: "撤销",
2198
+ order: 10
2199
+ },
2200
+ {
2201
+ id: "redo",
2202
+ type: "redo",
2203
+ group: "history",
2204
+ icon: "flow-canvas-icon canvas-redo",
2205
+ description: "重做",
2206
+ order: 11
2207
+ }
2208
+ ], o = [
2209
+ {
2210
+ id: "select",
2211
+ type: "select",
2212
+ group: "tools",
2213
+ icon: "flow-canvas-icon canvas-kuangxuan",
2214
+ description: "框选",
2215
+ order: 20
2216
+ },
2217
+ {
2218
+ id: "auto-layout",
2219
+ type: "auto-layout",
2220
+ group: "tools",
2221
+ icon: "flow-canvas-icon canvas-beautify",
2222
+ description: "自动排版",
2223
+ order: 21
2224
+ },
2225
+ {
2226
+ id: "search",
2227
+ type: "search",
2228
+ group: "tools",
2229
+ icon: "flow-canvas-icon canvas-search",
2230
+ description: "搜索节点",
2231
+ order: 22
2232
+ },
2233
+ {
2234
+ id: "minimap",
2235
+ type: "minimap",
2236
+ group: "tools",
2237
+ icon: "flow-canvas-icon canvas-map",
2238
+ description: "缩略图",
2239
+ order: 23
2240
+ },
2241
+ {
2242
+ id: "export",
2243
+ type: "export",
2244
+ group: "tools",
2245
+ icon: "flow-canvas-icon canvas-xiazai",
2246
+ description: "导出为图片",
2247
+ order: 24
2248
+ }
2249
+ ], n = [
2250
+ {
2251
+ id: "zoom-out",
2252
+ type: "zoom-out",
2253
+ group: "zoom",
2254
+ icon: "flow-canvas-icon canvas-zoom-minus",
2255
+ description: "缩小画布",
2256
+ order: 30
2257
+ },
2258
+ { id: "zoom-display", type: "zoom-display", group: "zoom", order: 31 },
2259
+ {
2260
+ id: "zoom-in",
2261
+ type: "zoom-in",
2262
+ group: "zoom",
2263
+ icon: "flow-canvas-icon canvas-zoom-add",
2264
+ description: "放大画布",
2265
+ order: 32
2266
+ }
2267
+ ], i = [
2268
+ {
2269
+ id: "reset",
2270
+ type: "reset",
2271
+ group: "reset",
2272
+ icon: "flow-canvas-icon canvas-reset-1_1",
2273
+ description: "重置视图",
2274
+ order: 40
2275
+ }
2276
+ ];
2277
+ return [...[...t, ...o].filter(
2278
+ (a) => !e.has(a.type)
2279
+ ), ...n, ...i];
2280
+ }
2281
+ const Ft = { class: "flow-canvas-toolbar" }, Ut = {
2282
+ key: 0,
2283
+ class: "flow-canvas-toolbar__separator"
2284
+ }, qt = { class: "flow-canvas-toolbar__group" }, Gt = {
2285
+ key: 0,
2286
+ class: "flow-canvas-toolbar__zoom-display"
2287
+ }, Vt = ["data-description", "disabled", "onClick"], Wt = ["textContent"], Qt = /* @__PURE__ */ ie({
2288
+ __name: "canvas-toolbar",
2289
+ props: {
2290
+ items: {},
2291
+ exclude: {},
2292
+ editor: {}
2293
+ },
2294
+ setup(s) {
2295
+ const e = s, t = z(() => e.items ? e.items : Ht({ exclude: e.exclude })), o = B(1);
2296
+ let n = null;
2297
+ de(
2298
+ () => e.editor.api.value,
2299
+ (f) => {
2300
+ n?.(), n = null, f && (o.value = f.getZoom(), n = f.onGraphEvent("scale", () => {
2301
+ o.value = f.getZoom();
2302
+ }));
2303
+ },
2304
+ { immediate: !0 }
2305
+ ), ze(() => {
2306
+ n?.();
2307
+ });
2308
+ const i = z(() => `${Math.round(o.value * 100)}%`), r = z(() => e.editor.api.value ? {
2309
+ api: e.editor.api.value,
2310
+ flowModel: e.editor.flowModel.value,
2311
+ history: e.editor.history,
2312
+ mode: e.editor.mode.value
2313
+ } : null);
2314
+ function a(f) {
2315
+ return f.visible === !1 ? !1 : typeof f.visible == "function" ? r.value ? f.visible(r.value) : !1 : !0;
2316
+ }
2317
+ function l(f) {
2318
+ return f.type === "select" ? e.editor.selectionMode.value : !1;
2319
+ }
2320
+ function c(f) {
2321
+ return !r.value || f.disabled === !0 ? !0 : typeof f.disabled == "function" ? f.disabled(r.value) : f.type === "undo" ? !e.editor.history.canUndo.value : f.type === "redo" ? !e.editor.history.canRedo.value : !1;
2322
+ }
2323
+ function u(f) {
2324
+ if (!r.value || c(f)) return;
2325
+ if (f.onClick) {
2326
+ f.onClick(r.value);
2327
+ return;
2328
+ }
2329
+ const { api: E } = r.value;
2330
+ switch (f.type) {
2331
+ case "undo":
2332
+ e.editor.history.undo();
2333
+ break;
2334
+ case "redo":
2335
+ e.editor.history.redo();
2336
+ break;
2337
+ case "zoom-in":
2338
+ E.zoomIn(), o.value = E.getZoom();
2339
+ break;
2340
+ case "zoom-out":
2341
+ E.zoomOut(), o.value = E.getZoom();
2342
+ break;
2343
+ case "fit":
2344
+ E.zoomToFit();
2345
+ break;
2346
+ case "reset":
2347
+ E.zoomTo(1), E.scrollToOrigin(), o.value = 1;
2348
+ break;
2349
+ case "export":
2350
+ E.exportAsImage().then((b) => {
2351
+ const m = URL.createObjectURL(b), p = document.createElement("a");
2352
+ p.href = m, p.download = "canvas-export.png", p.click(), URL.revokeObjectURL(m);
2353
+ }).catch((b) => {
2354
+ console.warn("[flow-canvas] Export failed:", b);
2355
+ });
2356
+ break;
2357
+ case "select":
2358
+ e.editor.setSelectionMode(!e.editor.selectionMode.value);
2359
+ break;
2360
+ case "search":
2361
+ case "auto-layout":
2362
+ case "minimap":
2363
+ console.warn(`[flow-canvas] "${f.type}" toolbar item has no built-in handler. Provide an onClick callback.`);
2364
+ break;
2365
+ default:
2366
+ f.type !== "custom" && console.warn(`[flow-canvas] No default handler for toolbar type "${f.type}". Provide an onClick handler.`);
2367
+ break;
2368
+ }
2369
+ }
2370
+ const d = z(() => t.value.filter(a)), w = z(() => {
2371
+ const f = /* @__PURE__ */ new Map(), E = [];
2372
+ for (const b of d.value) {
2373
+ const m = b.group ?? "default";
2374
+ f.has(m) || (f.set(m, []), E.push(m)), f.get(m).push(b);
2375
+ }
2376
+ return E.map((b) => ({ name: b, items: f.get(b) })).filter((b) => b.items.length > 0);
2377
+ });
2378
+ return (f, E) => (C(), M("div", Ft, [
2379
+ (C(!0), M(se, null, ge(w.value, (b, m) => (C(), M(se, {
2380
+ key: b.name
2381
+ }, [
2382
+ m > 0 ? (C(), M("div", Ut)) : O("", !0),
2383
+ $("div", qt, [
2384
+ (C(!0), M(se, null, ge(b.items, (p) => (C(), M(se, {
2385
+ key: p.id
2386
+ }, [
2387
+ p.type === "zoom-display" ? (C(), M("span", Gt, ue(i.value), 1)) : (C(), M("button", {
2388
+ key: 1,
2389
+ class: Q(["flow-canvas-toolbar__btn", { "is-disabled": c(p), "is-active": l(p) }]),
2390
+ "data-description": p.description,
2391
+ disabled: c(p),
2392
+ onClick: (P) => u(p)
2393
+ }, [
2394
+ p.component ? (C(), be(Ve(p.component), { key: 0 })) : p.icon ? (C(), M("i", {
2395
+ key: 1,
2396
+ class: Q(p.icon)
2397
+ }, null, 2)) : (C(), M("span", {
2398
+ key: 2,
2399
+ class: "flow-canvas-toolbar__text",
2400
+ textContent: ue(p.text ?? p.description ?? p.id)
2401
+ }, null, 8, Wt))
2402
+ ], 10, Vt))
2403
+ ], 64))), 128))
2404
+ ])
2405
+ ], 64))), 128))
2406
+ ]));
2407
+ }
2408
+ }), co = /* @__PURE__ */ re(Qt, [["__scopeId", "data-v-ca50cd45"]]), Xt = { class: "flow-canvas-default-node__ep-label" }, Yt = {
2409
+ key: 1,
2410
+ class: "flow-canvas-default-node__diamond"
2411
+ }, Kt = {
2412
+ key: 2,
2413
+ class: "flow-canvas-default-node__task-label"
2414
+ }, Zt = /* @__PURE__ */ ie({
2415
+ __name: "default-node",
2416
+ setup(s) {
2417
+ const t = We("getNode")?.(), o = z(() => t?.getData?.() ?? null), n = z(() => o.value?.label || o.value?.type || ""), i = {
2418
+ start: "canvas-kaishi",
2419
+ end: "canvas-stop",
2420
+ "parallel-gateway": "canvas-bingxingwangguan",
2421
+ "branch-gateway": "canvas-fenzhiwangguan",
2422
+ "converge-gateway": "canvas-huijuwangguan",
2423
+ "conditional-parallel-gateway": "canvas-tiaojianbingxingwangguan"
2424
+ }, r = /* @__PURE__ */ new Set(["start", "end"]), a = /* @__PURE__ */ new Set([
2425
+ "parallel-gateway",
2426
+ "branch-gateway",
2427
+ "converge-gateway",
2428
+ "conditional-parallel-gateway"
2429
+ ]), l = z(() => {
2430
+ const u = o.value?.type ?? "";
2431
+ return r.has(u) ? "endpoint" : a.has(u) ? "gateway" : "task";
2432
+ }), c = z(() => i[o.value?.type ?? ""] ?? "");
2433
+ return (u, d) => (C(), M("div", {
2434
+ class: Q(["flow-canvas-default-node", `is-${l.value}`])
2435
+ }, [
2436
+ l.value === "endpoint" ? (C(), M(se, { key: 0 }, [
2437
+ c.value ? (C(), M("i", {
2438
+ key: 0,
2439
+ class: Q([["flow-canvas-icon", c.value], "flow-canvas-default-node__ep-icon"])
2440
+ }, null, 2)) : O("", !0),
2441
+ $("span", Xt, ue(n.value), 1)
2442
+ ], 64)) : l.value === "gateway" ? (C(), M("div", Yt, [
2443
+ c.value ? (C(), M("i", {
2444
+ key: 0,
2445
+ class: Q([["flow-canvas-icon", c.value], "flow-canvas-default-node__gw-icon"])
2446
+ }, null, 2)) : O("", !0)
2447
+ ])) : (C(), M("span", Kt, ue(n.value), 1))
2448
+ ], 2));
2449
+ }
2450
+ }), Jt = /* @__PURE__ */ re(Zt, [["__scopeId", "data-v-c88cdae7"]]), eo = {
2451
+ start: { label: "开始", icon: "flow-canvas-icon canvas-kaishi", width: 88, height: 40 },
2452
+ end: { label: "结束", icon: "flow-canvas-icon canvas-stop", width: 88, height: 40 },
2453
+ empty: { label: "空节点", icon: "flow-canvas-icon canvas-jiedi", width: 240, height: 48 },
2454
+ "parallel-gateway": { label: "并行网关", icon: "flow-canvas-icon canvas-bingxingwangguan", width: 64, height: 64 },
2455
+ "branch-gateway": { label: "分支网关", icon: "flow-canvas-icon canvas-fenzhiwangguan", width: 64, height: 64 },
2456
+ "converge-gateway": { label: "汇聚网关", icon: "flow-canvas-icon canvas-huijuwangguan", width: 64, height: 64 },
2457
+ "conditional-parallel-gateway": {
2458
+ label: "条件并行网关",
2459
+ icon: "flow-canvas-icon canvas-tiaojianbingxingwangguan",
2460
+ width: 64,
2461
+ height: 64
2462
+ }
2463
+ }, Le = (s, e) => ({
2464
+ stroke: e.hovered ? "#3a84ff" : "#abb5cc",
2465
+ strokeWidth: 2
2466
+ }), Be = {
2467
+ attrs: {
2468
+ line: {
2469
+ stroke: "#abb5cc",
2470
+ strokeWidth: 2,
2471
+ targetMarker: { name: "block", width: 8, height: 8 }
2472
+ }
2473
+ }
2474
+ }, to = {
2475
+ manhattan: {
2476
+ router: { name: "manhattan", args: { padding: 10, maxDirectionChange: 90 } },
2477
+ connector: { name: "rounded", args: { radius: 8 } },
2478
+ style: Le,
2479
+ x6EdgeConfig: Be
2480
+ },
2481
+ bezier: {
2482
+ connector: { name: "smooth" },
2483
+ style: Le,
2484
+ x6EdgeConfig: Be
2485
+ }
2486
+ };
2487
+ function uo(s) {
2488
+ const e = s?.nodeTypes ?? eo, t = {}, o = [];
2489
+ for (const [r, a] of Object.entries(e)) {
2490
+ const l = a.width ?? 150, c = a.height ?? 50;
2491
+ t[r] = {
2492
+ component: Jt,
2493
+ getSize: () => ({ width: l, height: c }),
2494
+ getPorts: () => [
2495
+ { id: "top", group: "top" },
2496
+ { id: "right", group: "right" },
2497
+ { id: "bottom", group: "bottom" },
2498
+ { id: "left", group: "left" }
2499
+ ]
2500
+ }, o.push({
2501
+ type: r,
2502
+ label: a.label ?? r,
2503
+ icon: a.icon
2504
+ });
2505
+ }
2506
+ const n = {
2507
+ ...to,
2508
+ ...s?.edgeTypes
2509
+ }, i = s?.defaultEdgeType ?? "manhattan";
2510
+ return {
2511
+ schema: { nodeTypes: t, defaultEdgeType: i, edgeTypes: n },
2512
+ paletteItems: o
2513
+ };
2514
+ }
2515
+ function fo(s) {
2516
+ return {
2517
+ name: "connection-validator",
2518
+ priority: 10,
2519
+ transformCommand(e, t, o) {
2520
+ for (const n of e.commands) {
2521
+ if (n.type !== "edge.add" && n.type !== "edge.reconnect") continue;
2522
+ const i = o.flowModel.value, r = n.type === "edge.add" ? n.edge.source.nodeId : n.source?.nodeId, a = n.type === "edge.add" ? n.edge.target.nodeId : n.target?.nodeId;
2523
+ if (!r || !a) continue;
2524
+ const l = i.nodes[r], c = i.nodes[a];
2525
+ if (!l || !c) continue;
2526
+ const u = n.type === "edge.add" ? n.edge.source.portId : n.source?.portId, d = n.type === "edge.add" ? n.edge.target.portId : n.target?.portId, w = u ? l.ports?.find((p) => p.id === u) : void 0, f = d ? c.ports?.find((p) => p.id === d) : void 0, E = n.type === "edge.reconnect" ? n.edgeId : void 0, b = Object.values(i.edges).filter((p) => p.id !== E), m = s({
2527
+ flowModel: i,
2528
+ sourceNode: l,
2529
+ targetNode: c,
2530
+ sourcePort: w,
2531
+ targetPort: f,
2532
+ existingEdges: b
2533
+ });
2534
+ if (!m.valid)
2535
+ return {
2536
+ rejected: !0,
2537
+ reason: m.reason ?? "Connection validation failed",
2538
+ code: "validation_failed"
2539
+ };
2540
+ }
2541
+ return e;
2542
+ }
2543
+ };
2544
+ }
2545
+ function po(s) {
2546
+ const { rubberband: e = !0, multiple: t = !0, movable: o = !0 } = s ?? {};
2547
+ return {
2548
+ name: "selection",
2549
+ priority: 90,
2550
+ async attachRuntime(n) {
2551
+ const { Selection: i } = await import("@antv/x6-plugin-selection");
2552
+ n.graph.use(
2553
+ new i({
2554
+ enabled: !0,
2555
+ rubberband: !1,
2556
+ multiple: t,
2557
+ movable: o,
2558
+ showNodeSelectionBox: !0,
2559
+ filter: (r) => !(r.isNode() && (!n.graph.isRubberbandEnabled?.() || (r.getData?.() ?? {})._selectable === !1))
2560
+ })
2561
+ );
2562
+ }
2563
+ };
2564
+ }
2565
+ function go(s) {
2566
+ const { tolerance: e = 10, color: t = "#3a84ff" } = s ?? {};
2567
+ let o = null;
2568
+ return {
2569
+ name: "snapline",
2570
+ priority: 90,
2571
+ async attachRuntime(n) {
2572
+ const { Snapline: i } = await import("@antv/x6-plugin-snapline");
2573
+ n.graph.use(
2574
+ new i({
2575
+ enabled: !0,
2576
+ tolerance: e,
2577
+ className: "flow-canvas-snapline"
2578
+ })
2579
+ ), o = document.createElement("style"), o.textContent = `.flow-canvas-snapline line { stroke: ${t} !important; }`, document.head.appendChild(o);
2580
+ },
2581
+ detachRuntime() {
2582
+ o?.remove(), o = null;
2583
+ }
2584
+ };
2585
+ }
2586
+ function ho(s) {
2587
+ let e = null;
2588
+ return {
2589
+ name: "minimap",
2590
+ priority: 90,
2591
+ async attachRuntime(t) {
2592
+ if (!s?.container) return;
2593
+ e = s.container;
2594
+ const { MiniMap: o } = await import("@antv/x6-plugin-minimap");
2595
+ t.graph.use(
2596
+ new o({
2597
+ container: s.container,
2598
+ width: s.width ?? 200,
2599
+ height: s.height ?? 160
2600
+ })
2601
+ );
2602
+ },
2603
+ detachRuntime() {
2604
+ e = null;
2605
+ },
2606
+ provideToolbarItems() {
2607
+ return [
2608
+ {
2609
+ id: "minimap",
2610
+ type: "minimap",
2611
+ tooltip: "小地图",
2612
+ order: 100,
2613
+ visible: !!s?.container,
2614
+ onClick() {
2615
+ if (!e) return;
2616
+ const t = e.style.display === "none";
2617
+ e.style.display = t ? "" : "none";
2618
+ }
2619
+ }
2620
+ ];
2621
+ }
2622
+ };
2623
+ }
2624
+ function vo() {
2625
+ let s = null, e = 0;
2626
+ return {
2627
+ name: "clipboard",
2628
+ priority: 90,
2629
+ onKeyboardShortcut(t, o) {
2630
+ const n = t.metaKey || t.ctrlKey;
2631
+ if (n && t.key === "c") {
2632
+ const i = o.graph.getSelectedCells?.() ?? [];
2633
+ if (!i.length) return !1;
2634
+ const r = o.flowModel.value, a = new Set(i.filter((u) => u.isNode()).map((u) => u.id)), l = [...a].map((u) => r.nodes[u]).filter(Boolean);
2635
+ if (!l.length) return !1;
2636
+ const c = Object.values(r.edges).filter(
2637
+ (u) => a.has(u.source.nodeId) && a.has(u.target.nodeId)
2638
+ );
2639
+ return s = { nodes: l, edges: c }, e = 0, !0;
2640
+ }
2641
+ if (n && t.key === "v") {
2642
+ if (!s?.nodes.length) return !1;
2643
+ e++;
2644
+ const i = e * 30, r = /* @__PURE__ */ new Map(), a = [];
2645
+ for (const l of s.nodes) {
2646
+ const c = `${l.id}_cp${L().slice(0, 6)}`;
2647
+ r.set(l.id, c), a.push({
2648
+ type: "node.add",
2649
+ node: {
2650
+ ...l,
2651
+ id: c,
2652
+ position: {
2653
+ x: l.position.x + i,
2654
+ y: l.position.y + i
2655
+ },
2656
+ payload: l.payload ? { ...l.payload } : {},
2657
+ extensions: l.extensions ? { ...l.extensions } : void 0
2658
+ }
2659
+ });
2660
+ }
2661
+ for (const l of s.edges) {
2662
+ const c = r.get(l.source.nodeId), u = r.get(l.target.nodeId);
2663
+ !c || !u || a.push({
2664
+ type: "edge.add",
2665
+ edge: {
2666
+ ...l,
2667
+ id: `${l.id}_cp${L().slice(0, 6)}`,
2668
+ source: { ...l.source, nodeId: c },
2669
+ target: { ...l.target, nodeId: u },
2670
+ labels: l.labels?.map((d) => ({ ...d, id: `${d.id}_cp${L().slice(0, 6)}` })),
2671
+ payload: l.payload ? { ...l.payload } : {}
2672
+ }
2673
+ });
2674
+ }
2675
+ return a.length && o.executeCommand({
2676
+ id: L(),
2677
+ source: "user:keyboard",
2678
+ label: "粘贴",
2679
+ timestamp: Date.now(),
2680
+ commands: a
2681
+ }), !0;
2682
+ }
2683
+ return !1;
2684
+ }
2685
+ };
2686
+ }
2687
+ export {
2688
+ K as CanvasConstraintError,
2689
+ lo as CanvasLayout,
2690
+ $t as CanvasNodePalette,
2691
+ ao as CanvasRuntime,
2692
+ Ye as CanvasSchemaError,
2693
+ co as CanvasToolbar,
2694
+ Jt as DefaultNode,
2695
+ It as NodeActionsToolbar,
2696
+ Dt as NodeQuickAddPopover,
2697
+ Se as applyCanvasCommand,
2698
+ vo as clipboardPlugin,
2699
+ fo as connectionValidatorPlugin,
2700
+ ct as createCanvasHistory,
2701
+ uo as createDefaultSchema,
2702
+ Ht as createDefaultToolbarItems,
2703
+ io as createEmptyFlowModel,
2704
+ L as generateId,
2705
+ ho as minimapPlugin,
2706
+ po as selectionPlugin,
2707
+ go as snaplinePlugin,
2708
+ ro as useCanvasEditor
2709
+ };