dishui 0.0.49 → 0.0.50

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 (52) hide show
  1. package/dist/components/pro/Flow/Flow.js +419 -407
  2. package/dist/components/pro/Flow/Flow.js.map +1 -1
  3. package/dist/components/pro/Flow/archify/build.d.ts +74 -0
  4. package/dist/components/pro/Flow/archify/build.js +103 -0
  5. package/dist/components/pro/Flow/archify/build.js.map +1 -0
  6. package/dist/components/pro/Flow/archify/convert.d.ts +14 -0
  7. package/dist/components/pro/Flow/archify/convert.js +534 -0
  8. package/dist/components/pro/Flow/archify/convert.js.map +1 -0
  9. package/dist/components/pro/Flow/archify/index.d.ts +12 -0
  10. package/dist/components/pro/Flow/archify/palette.d.ts +64 -0
  11. package/dist/components/pro/Flow/archify/palette.js +112 -0
  12. package/dist/components/pro/Flow/archify/palette.js.map +1 -0
  13. package/dist/components/pro/Flow/archify/presets.d.ts +26 -0
  14. package/dist/components/pro/Flow/archify/presets.js +43 -0
  15. package/dist/components/pro/Flow/archify/presets.js.map +1 -0
  16. package/dist/components/pro/Flow/archify/spec.d.ts +283 -0
  17. package/dist/components/pro/Flow/archify/spec.js +10 -0
  18. package/dist/components/pro/Flow/archify/spec.js.map +1 -0
  19. package/dist/components/pro/Flow/constants.js +14 -0
  20. package/dist/components/pro/Flow/constants.js.map +1 -1
  21. package/dist/components/pro/Flow/hooks/useClipboard.d.ts +5 -0
  22. package/dist/components/pro/Flow/hooks/useClipboard.js +129 -73
  23. package/dist/components/pro/Flow/hooks/useClipboard.js.map +1 -1
  24. package/dist/components/pro/Flow/hooks/useFlowImportExport.d.ts +1 -0
  25. package/dist/components/pro/Flow/hooks/useFlowImportExport.js +108 -93
  26. package/dist/components/pro/Flow/hooks/useFlowImportExport.js.map +1 -1
  27. package/dist/components/pro/Flow/hooks/useKeyboardShortcuts.d.ts +1 -0
  28. package/dist/components/pro/Flow/hooks/useKeyboardShortcuts.js +7 -7
  29. package/dist/components/pro/Flow/hooks/useKeyboardShortcuts.js.map +1 -1
  30. package/dist/components/pro/Flow/index.d.ts +2 -0
  31. package/dist/components/pro/Flow/nodes/DataNodeView.d.ts +4 -1
  32. package/dist/components/pro/Flow/nodes/DataNodeView.js +127 -115
  33. package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -1
  34. package/dist/components/pro/Flow/nodes/MediaContent.js +72 -67
  35. package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
  36. package/dist/components/pro/Flow/nodes/NodeRenderer.d.ts +5 -0
  37. package/dist/components/pro/Flow/nodes/NodeRenderer.js +216 -115
  38. package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
  39. package/dist/components/pro/Flow/panels/FlowToolbar.js +208 -169
  40. package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
  41. package/dist/components/pro/Flow/panels/InspectorPanel.js +602 -369
  42. package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
  43. package/dist/components/pro/Flow/panels/ShapePalette.js +50 -39
  44. package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
  45. package/dist/components/pro/Flow/panels/toolbarIcons.d.ts +1 -0
  46. package/dist/components/pro/Flow/panels/toolbarIcons.js +36 -8
  47. package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
  48. package/dist/components/pro/Flow/types.d.ts +30 -0
  49. package/dist/components/pro/Flow/types.js.map +1 -1
  50. package/dist/dishui.css +1 -1
  51. package/dist/flow.js +73 -56
  52. package/package.json +18 -17
@@ -1,66 +1,137 @@
1
- import { resolveThemeColor as m } from "../utils/themeColor.js";
2
- import { drawRoundRectBorder as T, shapeDrawers as S } from "./shapes.js";
3
- import { createNodeText as I, formatIconLabel as N, normalizeIconLabelPlacement as A, updateNodeText as L } from "./NodeText.js";
4
- import { createHandleGraphics as z, getHandlePositions as W, updateHandleGraphics as H } from "./NodeHandles.js";
5
- import { getFlipScale as B, getRotationRad as G } from "./nodeUtils.js";
6
- import { getIconTexture as P, subscribeIconTextureReady as D } from "./svgIconTexture.js";
7
- import { Container as R, Graphics as M, Sprite as F, Text as V } from "pixi.js";
8
- var K = class {
1
+ import { resolveThemeColor as u } from "../utils/themeColor.js";
2
+ import { drawRoundRectBorder as E, shapeDrawers as G } from "./shapes.js";
3
+ import { createNodeText as V, formatIconLabel as $, normalizeIconLabelPlacement as j, updateNodeText as q } from "./NodeText.js";
4
+ import { createHandleGraphics as J, getHandlePositions as X, updateHandleGraphics as K } from "./NodeHandles.js";
5
+ import { getFlipScale as Q, getRotationRad as U } from "./nodeUtils.js";
6
+ import { getIconTexture as Z, subscribeIconTextureReady as tt } from "./svgIconTexture.js";
7
+ import { Container as L, Graphics as B, Sprite as et, Text as F } from "pixi.js";
8
+ function st(o, t, n, p, f) {
9
+ const s = 6 + p / 2, e = t - 6 - p / 2, i = t / 2, r = 6 + f / 2, a = n - 6 - f / 2, h = n / 2;
10
+ switch (o) {
11
+ case "top":
12
+ return {
13
+ x: i,
14
+ y: r
15
+ };
16
+ case "bottom":
17
+ return {
18
+ x: i,
19
+ y: a
20
+ };
21
+ case "left":
22
+ return {
23
+ x: s,
24
+ y: h
25
+ };
26
+ case "right":
27
+ return {
28
+ x: e,
29
+ y: h
30
+ };
31
+ case "top-left":
32
+ return {
33
+ x: s,
34
+ y: r
35
+ };
36
+ case "top-right":
37
+ return {
38
+ x: e,
39
+ y: r
40
+ };
41
+ case "bottom-left":
42
+ return {
43
+ x: s,
44
+ y: a
45
+ };
46
+ case "bottom-right":
47
+ return {
48
+ x: e,
49
+ y: a
50
+ };
51
+ default:
52
+ return {
53
+ x: i,
54
+ y: h
55
+ };
56
+ }
57
+ }
58
+ var ct = class {
9
59
  world;
10
60
  nodeLayer;
11
61
  nodes = /* @__PURE__ */ new Map();
12
62
  _dynamicOffset = 0;
13
63
  _unsubscribeTextureReady;
14
- advanceAnimation(s) {
15
- this._dynamicOffset = (this._dynamicOffset + s * 0.06) % 1e3;
64
+ advanceAnimation(o) {
65
+ this._dynamicOffset = (this._dynamicOffset + o * 0.06) % 1e3;
16
66
  }
17
- constructor(s) {
18
- this.world = s, this.nodeLayer = new R({
67
+ constructor(o) {
68
+ this.world = o, this.nodeLayer = new L({
19
69
  label: "nodes",
20
70
  sortableChildren: !0
21
- }), this.world.addChild(this.nodeLayer), this._unsubscribeTextureReady = D(() => this._resync?.());
71
+ }), this.world.addChild(this.nodeLayer), this._unsubscribeTextureReady = tt(() => this._resync?.());
22
72
  }
23
73
  _resync = null;
24
- sync(s, t, l, c, d) {
25
- const r = /* @__PURE__ */ new Set();
26
- this._resync = () => this.sync(s, t, l, c, d);
27
- const i = c ?? (() => {
28
- const e = s.filter((h) => h.type === "animAnchor").sort((h, o) => (h.data.animIndex ?? 0) - (o.data.animIndex ?? 0)), a = /* @__PURE__ */ new Map();
29
- return e.forEach((h, o) => a.set(h.id, o + 1)), a;
74
+ sync(o, t, n, p, f) {
75
+ const l = /* @__PURE__ */ new Set();
76
+ this._resync = () => this.sync(o, t, n, p, f);
77
+ const s = p ?? (() => {
78
+ const e = o.filter((r) => r.type === "animAnchor").sort((r, a) => (r.data.animIndex ?? 0) - (a.data.animIndex ?? 0)), i = /* @__PURE__ */ new Map();
79
+ return e.forEach((r, a) => i.set(r.id, a + 1)), i;
30
80
  })();
31
- for (const e of s) {
32
- r.add(e.id);
33
- let a = this.nodes.get(e.id);
34
- a || (a = this._createNode(e), this.nodes.set(e.id, a)), this._updateNode(a, e, t.has(e.id), l === e.id, i.get(e.id), d);
81
+ for (const e of o) {
82
+ l.add(e.id);
83
+ let i = this.nodes.get(e.id);
84
+ i || (i = this._createNode(e), this.nodes.set(e.id, i)), this._updateNode(i, e, t.has(e.id), n === e.id, s.get(e.id), f);
35
85
  }
36
- for (const [e, a] of this.nodes) r.has(e) || (this.nodeLayer.removeChild(a.container), a.container.destroy({ children: !0 }), this.nodes.delete(e));
86
+ for (const [e, i] of this.nodes) l.has(e) || (this.nodeLayer.removeChild(i.container), i.container.destroy({ children: !0 }), this.nodes.delete(e));
37
87
  }
38
- getNodeContainer(s) {
39
- return this.nodes.get(s);
88
+ getNodeContainer(o) {
89
+ return this.nodes.get(o);
40
90
  }
41
91
  getAllNodeContainers() {
42
92
  return [...this.nodes.values()];
43
93
  }
44
- _createNode(s) {
45
- const t = new R({ label: `node-${s.id}` });
94
+ _createNode(o) {
95
+ const t = new L({ label: `node-${o.id}` });
46
96
  t.eventMode = "static", t.cursor = "pointer";
47
- const l = new R({ label: "svg-transform" });
48
- t.addChild(l);
49
- const c = new M();
50
- c.label = "sub-canvas-glow", t.addChild(c);
51
- const d = new M();
52
- d.label = "shape", t.addChild(d);
53
- const r = new F();
54
- r.label = "svg-icon", r.anchor.set(0.5, 0.5), r.visible = !1, t.addChild(r);
55
- const i = I({
56
- label: s.data.label,
57
- color: m(s.data.labelColor ?? s.data.color, "#111827"),
58
- fontSize: s.data.fontSize,
59
- width: s.width,
60
- height: s.height
97
+ const n = new L({ label: "svg-transform" });
98
+ t.addChild(n);
99
+ const p = new B();
100
+ p.label = "sub-canvas-glow", t.addChild(p);
101
+ const f = new B();
102
+ f.label = "shape", t.addChild(f);
103
+ const l = new et();
104
+ l.label = "svg-icon", l.anchor.set(0.5, 0.5), l.visible = !1, t.addChild(l);
105
+ const s = V({
106
+ label: o.data.label,
107
+ color: u(o.data.labelColor ?? o.data.color, "#111827"),
108
+ fontSize: o.data.fontSize,
109
+ width: o.width,
110
+ height: o.height
111
+ });
112
+ t.addChild(s);
113
+ const e = new F({
114
+ text: "",
115
+ style: {
116
+ fontFamily: "system-ui, -apple-system, sans-serif",
117
+ fontSize: 11,
118
+ fill: "#94a3b8",
119
+ align: "center"
120
+ }
61
121
  });
62
- t.addChild(i);
63
- const e = W(s.width, s.height), a = z(t, e, !1), h = new V({
122
+ e.label = "node-subtext", e.anchor.set(0.5, 0.5), e.visible = !1, t.addChild(e);
123
+ const i = new B();
124
+ i.label = "node-tag-bg", i.visible = !1, t.addChild(i);
125
+ const r = new F({
126
+ text: "",
127
+ style: {
128
+ fontFamily: "system-ui, -apple-system, sans-serif",
129
+ fontSize: 9,
130
+ fill: "#cbd5e1"
131
+ }
132
+ });
133
+ r.label = "node-tag-text", r.anchor.set(0.5, 0.5), r.visible = !1, t.addChild(r);
134
+ const a = X(o.width, o.height), h = J(t, a, !1), g = new F({
64
135
  text: "",
65
136
  style: {
66
137
  fontFamily: "system-ui, sans-serif",
@@ -69,120 +140,150 @@ var K = class {
69
140
  fontWeight: "700"
70
141
  }
71
142
  });
72
- return h.label = "anim-badge", h.anchor.set(0.5, 0.5), h.visible = !1, t.addChild(h), this.nodeLayer.addChild(t), {
143
+ return g.label = "anim-badge", g.anchor.set(0.5, 0.5), g.visible = !1, t.addChild(g), this.nodeLayer.addChild(t), {
73
144
  container: t,
74
- shape: d,
75
- svgTransform: l,
76
- icon: r,
77
- text: i,
78
- animBadge: h,
79
- handles: a,
80
- handleDefs: e,
81
- nodeId: s.id,
82
- subCanvasGlow: c
145
+ shape: f,
146
+ svgTransform: n,
147
+ icon: l,
148
+ text: s,
149
+ subtext: e,
150
+ tagBg: i,
151
+ tagText: r,
152
+ animBadge: g,
153
+ handles: h,
154
+ handleDefs: a,
155
+ nodeId: o.id,
156
+ subCanvasGlow: p
83
157
  };
84
158
  }
85
- _updateNode(s, t, l, c, d, r) {
86
- const { container: i, svgTransform: e, shape: a, icon: h, text: o, animBadge: b, handles: g, subCanvasGlow: y } = s, w = t.type === "shapeSvg", x = G(t.data), u = B(t.data);
87
- i.zIndex = t.zIndex ?? 0, w ? (a.parent !== e && e.addChild(a), h.parent !== e && e.addChild(h), g.parent !== e && e.addChild(g), i.position.set(t.position.x, t.position.y), i.rotation = 0, i.scale.set(1, 1), i.pivot.set(0, 0), e.position.set(t.width / 2, t.height / 2), e.pivot.set(t.width / 2, t.height / 2), e.rotation = x, e.scale.set(u.sx, u.sy)) : (a.parent !== i && i.addChildAt(a, Math.min(2, i.children.length)), h.parent !== i && i.addChild(h), g.parent !== i && i.addChild(g), e.rotation = 0, e.scale.set(1, 1), i.position.set(t.position.x, t.position.y), i.rotation = x, i.scale.set(u.sx, u.sy), x !== 0 || u.sx < 0 || u.sy < 0 ? (i.pivot.set(t.width / 2, t.height / 2), i.position.set(t.position.x + t.width / 2, t.position.y + t.height / 2)) : i.pivot.set(0, 0));
88
- const _ = t.type === "mediaNode", v = t.type === "animAnchor";
89
- if (a.clear(), a.alpha = 1, w) this._updateSvgNode(s, t, l);
90
- else if (_) {
91
- h.visible = !1;
92
- const f = t.data.fill && t.data.fill !== "transparent" ? m(t.data.fill, "#ffffff") : "#ffffff", n = t.data.borderStyle === "none", p = l ? "#3b82f6" : m(t.data.stroke, "#374151"), k = l ? Math.max(t.data.strokeWidth, 2) : t.data.strokeWidth;
93
- S.shapeRoundRect(a, {
159
+ _updateNode(o, t, n, p, f, l) {
160
+ const { container: s, svgTransform: e, shape: i, icon: r, text: a, subtext: h, tagBg: g, tagText: y, animBadge: v, handles: m, subCanvasGlow: T } = o, C = t.type === "shapeSvg", M = U(t.data), x = Q(t.data);
161
+ s.zIndex = t.zIndex ?? 0, C ? (i.parent !== e && e.addChild(i), r.parent !== e && e.addChild(r), m.parent !== e && e.addChild(m), s.position.set(t.position.x, t.position.y), s.rotation = 0, s.scale.set(1, 1), s.pivot.set(0, 0), e.position.set(t.width / 2, t.height / 2), e.pivot.set(t.width / 2, t.height / 2), e.rotation = M, e.scale.set(x.sx, x.sy)) : (i.parent !== s && s.addChildAt(i, Math.min(2, s.children.length)), r.parent !== s && s.addChild(r), m.parent !== s && s.addChild(m), e.rotation = 0, e.scale.set(1, 1), s.position.set(t.position.x, t.position.y), s.rotation = M, s.scale.set(x.sx, x.sy), M !== 0 || x.sx < 0 || x.sy < 0 ? (s.pivot.set(t.width / 2, t.height / 2), s.position.set(t.position.x + t.width / 2, t.position.y + t.height / 2)) : s.pivot.set(0, 0));
162
+ const O = t.type === "mediaNode", S = t.type === "animAnchor";
163
+ let W = !0;
164
+ if (i.clear(), i.alpha = 1, C) this._updateSvgNode(o, t, n);
165
+ else if (O) {
166
+ r.visible = !1;
167
+ const d = t.data.fill && t.data.fill !== "transparent" ? u(t.data.fill, "#ffffff") : "#ffffff", c = t.data.borderStyle === "none", b = n ? "#3b82f6" : u(t.data.stroke, "#374151"), w = n ? Math.max(t.data.strokeWidth, 2) : t.data.strokeWidth;
168
+ G.shapeRoundRect(i, {
94
169
  width: t.width,
95
170
  height: t.height,
96
- fill: f,
97
- stroke: p,
98
- strokeWidth: k,
99
- borderStyle: l && n ? "solid" : t.data.borderStyle,
171
+ fill: d,
172
+ stroke: b,
173
+ strokeWidth: w,
174
+ borderStyle: n && c ? "solid" : t.data.borderStyle,
100
175
  dashOffset: this._dynamicOffset
101
176
  });
102
- } else if (v) {
103
- h.visible = !1;
104
- const f = "#8b5cf6", n = r?.presentation ?? !1, p = n ? (r?.presentationAnchorVisible ?? !1) && r?.presentationAnchorId === t.id : r?.showAnchors ?? !0;
105
- p && (a.alpha = n ? 0.48 : 0.9, S.shapeRoundRect(a, {
177
+ } else if (S) {
178
+ r.visible = !1;
179
+ const d = "#8b5cf6", c = l?.presentation ?? !1;
180
+ W = c ? (l?.presentationAnchorVisible ?? !1) && l?.presentationAnchorId === t.id : l?.showAnchors ?? !0, W && (i.alpha = c ? 0.48 : 0.9, G.shapeRoundRect(i, {
106
181
  width: t.width,
107
182
  height: t.height,
108
183
  fill: "transparent",
109
- stroke: l && !n ? "#3b82f6" : f,
110
- strokeWidth: l && !n ? 2.5 : 1.5,
184
+ stroke: n && !c ? "#3b82f6" : d,
185
+ strokeWidth: n && !c ? 2.5 : 1.5,
111
186
  borderStyle: "dashed"
112
- }), a.circle(0, 0, n ? 11 : 13).fill({ color: l && !n ? "#3b82f6" : f })), b.text = String(d ?? ""), b.alpha = n ? 0.7 : 1, b.visible = p, b.position.set(0, 0);
187
+ }), i.circle(0, 0, c ? 11 : 13).fill({ color: n && !c ? "#3b82f6" : d })), v.text = String(f ?? ""), v.alpha = c ? 0.7 : 1, v.visible = W, v.position.set(0, 0);
113
188
  } else {
114
- h.visible = !1;
115
- const f = S[t.type] ?? S.shapeRect, n = t.data.borderStyle === "none";
116
- f(a, {
189
+ r.visible = !1;
190
+ const d = G[t.type] ?? G.shapeRect, c = t.data.borderStyle === "none";
191
+ d(i, {
117
192
  width: t.width,
118
193
  height: t.height,
119
- fill: m(t.data.fill, "#ffffff"),
120
- stroke: l ? "#3b82f6" : m(t.data.stroke, "#374151"),
121
- strokeWidth: l ? Math.max(t.data.strokeWidth, 2) : t.data.strokeWidth,
122
- borderStyle: l && n ? "solid" : t.data.borderStyle,
194
+ fill: u(t.data.fill, "#ffffff"),
195
+ stroke: n ? "#3b82f6" : u(t.data.stroke, "#374151"),
196
+ strokeWidth: n ? Math.max(t.data.strokeWidth, 2) : t.data.strokeWidth,
197
+ borderStyle: n && c ? "solid" : t.data.borderStyle,
123
198
  dashOffset: this._dynamicOffset
124
199
  });
125
200
  }
126
- if (v || (b.visible = !1), y.clear(), t.data.childCanvasId) {
127
- const n = t.width + 8, p = t.height + 8, k = 0.5 + 0.3 * Math.sin(this._dynamicOffset * 8e-3);
128
- y.roundRect(-4, -4, n, p, 6), y.stroke({
201
+ if (S || (v.visible = !1), T.clear(), t.data.childCanvasId) {
202
+ const c = t.width + 8, b = t.height + 8, w = 0.5 + 0.3 * Math.sin(this._dynamicOffset * 8e-3);
203
+ T.roundRect(-4, -4, c, b, 6), T.stroke({
129
204
  color: 9133302,
130
205
  width: 2.5,
131
- alpha: k
132
- }), y.roundRect(-6, -6, n + 4, p + 4, 8), y.stroke({
206
+ alpha: w
207
+ }), T.roundRect(-6, -6, c + 4, b + 4, 8), T.stroke({
133
208
  color: 9133302,
134
209
  width: 1,
135
- alpha: k * 0.4
210
+ alpha: w * 0.4
136
211
  });
137
212
  }
138
- const C = A(t.data.labelPlacement), O = t.data.labelColor ?? (w ? "theme:base-content" : t.data.color);
139
- if (L(o, {
140
- label: _ || v ? "" : w ? N(t.data.label, C) : t.data.label,
141
- color: m(O, "#111827"),
213
+ const z = j(t.data.labelPlacement), Y = t.data.labelColor ?? (C ? "theme:base-content" : t.data.color);
214
+ q(a, {
215
+ label: O ? "" : C ? $(t.data.label, z) : t.data.label,
216
+ color: u(Y, "#111827"),
142
217
  fontSize: t.data.fontSize,
143
218
  width: t.width,
144
219
  height: t.height
145
- }), o.visible = !_ && !v, t.type === "shapeCorner") {
146
- const f = Math.min(t.width, t.height) * 0.4;
147
- o.position.set((f + t.width) / 2, (f + t.height) / 2);
148
- } else if (w) {
149
- const n = o.width / 2, p = o.height / 2;
150
- C === "top" ? o.position.set(t.width / 2, -4 - p) : C === "bottom" ? o.position.set(t.width / 2, t.height + 4 + p) : C === "left" ? o.position.set(-4 - n, t.height / 2) : C === "right" ? o.position.set(t.width + 4 + n, t.height / 2) : o.position.set(t.width / 2, t.height / 2), o.position.x += t.data.labelOffsetX ?? 0, o.position.y += t.data.labelOffsetY ?? 0;
220
+ }), a.visible = !O && (!S || W);
221
+ const H = !C && !O && (!S || W), P = H ? (t.data.sublabel ?? "").trim() : "", I = P.length > 0;
222
+ if (t.type === "shapeCorner") {
223
+ const d = Math.min(t.width, t.height) * 0.4;
224
+ a.position.set((d + t.width) / 2, (d + t.height) / 2);
225
+ } else if (C) {
226
+ const c = a.width / 2, b = a.height / 2;
227
+ z === "top" ? a.position.set(t.width / 2, -4 - b) : z === "bottom" ? a.position.set(t.width / 2, t.height + 4 + b) : z === "left" ? a.position.set(-4 - c, t.height / 2) : z === "right" ? a.position.set(t.width + 4 + c, t.height / 2) : a.position.set(t.width / 2, t.height / 2), a.position.x += t.data.labelOffsetX ?? 0, a.position.y += t.data.labelOffsetY ?? 0;
228
+ } else if (!O) {
229
+ const c = Math.max(9, t.data.fontSize - 3);
230
+ if (I) {
231
+ const R = h.style;
232
+ R.fill = u(t.data.sublabelColor ?? "#94a3b8", "#94a3b8"), R.fontSize = c, h.text = P, h.anchor.set(0.5, 0.5), h.visible = !0, h.rotation = -M, h.scale.set(x.sx, x.sy);
233
+ }
234
+ a.anchor.set(0.5, 0.5);
235
+ const b = a.height + (I ? 3 + h.height : 0), w = Math.max(a.width, I ? h.width : 0), _ = t.data.isGroup || t.type === "flowGroup" || t.type === "geometryGroup", k = st(t.data.textPlacement ?? (S || _ ? "top" : "center"), t.width, t.height, w, b), N = k.x + (t.data.labelOffsetX ?? 0), A = k.y + (t.data.labelOffsetY ?? 0);
236
+ a.position.set(N, A - b / 2 + a.height / 2), I && h.position.set(N, A + b / 2 - h.height / 2);
151
237
  }
152
- if (w ? (o.rotation = 0, o.scale.set(1, 1)) : (o.rotation = -x, o.scale.set(u.sx, u.sy)), g.visible = (c || l) && !(v && r?.presentation), g.visible) {
153
- const f = W(t.width, t.height);
154
- s.handleDefs = f, H(g, f);
238
+ I || (h.visible = !1), C ? (a.rotation = 0, a.scale.set(1, 1)) : (a.rotation = -M, a.scale.set(x.sx, x.sy));
239
+ const D = H ? (t.data.tag ?? "").trim() : "";
240
+ if (D) {
241
+ y.text = D, y.visible = !0;
242
+ const d = 5, c = 2, b = y.width + d * 2, w = y.height + c * 2, _ = 6, k = t.data.tagPlacement ?? "top-right", N = k === "top-left" || k === "bottom-left" ? _ : t.width - b - _, A = k === "top-left" || k === "top-right" ? _ : t.height - w - _, R = u(t.data.tagColor ?? t.data.stroke, "#334155");
243
+ g.clear(), g.roundRect(N, A, b, w, 3).fill({
244
+ color: R,
245
+ alpha: 0.18
246
+ }).stroke({
247
+ color: R,
248
+ width: 1,
249
+ alpha: 0.55
250
+ }), g.visible = !0, y.style.fill = R, y.position.set(N + b / 2, A + w / 2), y.rotation = 0, y.scale.set(1, 1);
251
+ } else
252
+ g.visible = !1, y.visible = !1;
253
+ if (m.visible = (p || n) && !(S && l?.presentation), m.visible) {
254
+ const d = X(t.width, t.height);
255
+ o.handleDefs = d, K(m, d);
155
256
  }
156
257
  }
157
- _updateSvgNode(s, t, l) {
158
- const { shape: c, icon: d } = s, { width: r, height: i, data: e } = t, a = e.iconBox ?? !1, h = e.borderStyle ?? (a ? "solid" : "none"), o = h === "none", b = Math.min(8, r * 0.12, i * 0.12);
159
- e.fill && e.fill !== "transparent" && (a || !o) && c.roundRect(0, 0, r, i, b).fill({ color: m(e.fill, "#ffffff") }), !o && e.stroke && e.stroke !== "transparent" && e.strokeWidth > 0 && T(c, {
160
- width: r,
161
- height: i,
258
+ _updateSvgNode(o, t, n) {
259
+ const { shape: p, icon: f } = o, { width: l, height: s, data: e } = t, i = e.iconBox ?? !1, r = e.borderStyle ?? (i ? "solid" : "none"), a = r === "none", h = Math.min(8, l * 0.12, s * 0.12);
260
+ e.fill && e.fill !== "transparent" && (i || !a) && p.roundRect(0, 0, l, s, h).fill({ color: u(e.fill, "#ffffff") }), !a && e.stroke && e.stroke !== "transparent" && e.strokeWidth > 0 && E(p, {
261
+ width: l,
262
+ height: s,
162
263
  fill: "transparent",
163
- stroke: m(e.stroke, "#374151"),
264
+ stroke: u(e.stroke, "#374151"),
164
265
  strokeWidth: e.strokeWidth,
165
- borderStyle: h,
266
+ borderStyle: r,
166
267
  dashOffset: this._dynamicOffset
167
- }, b), l && c.roundRect(0, 0, r, i, b).stroke({
268
+ }, h), n && p.roundRect(0, 0, l, s, h).stroke({
168
269
  color: "#3b82f6",
169
270
  width: Math.max(e.strokeWidth, 2)
170
271
  });
171
- const g = m(e.color, "#334155") || "#334155", y = P(e.svgId ?? "", g);
272
+ const g = u(e.color, "#334155") || "#334155", y = Z(e.svgId ?? "", g);
172
273
  if (y) {
173
- d.texture = y, d.visible = !0;
174
- const w = a ? Math.min(r, i) * 0.18 : 2, x = Math.max(4, Math.min(r, i) - w * 2);
175
- d.width = x, d.height = x, d.position.set(r / 2, i / 2);
176
- } else d.visible = !1;
274
+ f.texture = y, f.visible = !0;
275
+ const v = i ? Math.min(l, s) * 0.18 : 2, m = Math.max(4, Math.min(l, s) - v * 2);
276
+ f.width = m, f.height = m, f.position.set(l / 2, s / 2);
277
+ } else f.visible = !1;
177
278
  }
178
279
  destroy() {
179
280
  this._unsubscribeTextureReady(), this._resync = null;
180
- for (const [, s] of this.nodes) s.container.destroy({ children: !0 });
281
+ for (const [, o] of this.nodes) o.container.destroy({ children: !0 });
181
282
  this.nodes.clear(), this.nodeLayer.destroy({ children: !0 });
182
283
  }
183
284
  };
184
285
  export {
185
- K as NodeRenderer
286
+ ct as NodeRenderer
186
287
  };
187
288
 
188
289
  //# sourceMappingURL=NodeRenderer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NodeRenderer.js","names":[],"sources":["../../../../../src/components/pro/Flow/nodes/NodeRenderer.ts"],"sourcesContent":["import { Container, Graphics, Text, Sprite } from 'pixi.js';\nimport type { FlowNode } from '../types';\nimport { drawRoundRectBorder, shapeDrawers, type ShapeDrawOptions } from './shapes';\nimport { createNodeText, formatIconLabel, normalizeIconLabelPlacement, updateNodeText } from './NodeText';\nimport { getHandlePositions, createHandleGraphics, updateHandleGraphics, type HandleDef } from './NodeHandles';\nimport { getRotationRad, getFlipScale } from './nodeUtils';\nimport { getIconTexture, subscribeIconTextureReady } from './svgIconTexture';\nimport { resolveThemeColor } from '../utils/themeColor';\n\nexport interface NodeContainer {\n container: Container;\n shape: Graphics;\n /** Rotated/flipped visual content for SVG icon stamps. */\n svgTransform: Container;\n icon: Sprite;\n text: Text;\n /** Sequence badge shown on `animAnchor` nodes. */\n animBadge: Text;\n handles: Graphics;\n handleDefs: HandleDef[];\n nodeId: string;\n subCanvasGlow: Graphics;\n}\n\n/**\n * Manages PixiJS display objects for all nodes on the current canvas.\n * Syncs from FlowNode[] data → PixiJS scene graph.\n */\nexport class NodeRenderer {\n private world: Container;\n private nodeLayer: Container;\n private nodes = new Map<string, NodeContainer>();\n private _dynamicOffset = 0;\n private _unsubscribeTextureReady: () => void;\n\n /** Call once per frame to advance the dynamic dash animation. */\n advanceAnimation(deltaMs: number): void {\n this._dynamicOffset = (this._dynamicOffset + deltaMs * 0.06) % 1000;\n }\n\n constructor(world: Container) {\n this.world = world;\n this.nodeLayer = new Container({ label: 'nodes', sortableChildren: true });\n this.world.addChild(this.nodeLayer);\n this._unsubscribeTextureReady = subscribeIconTextureReady(() => this._resync?.());\n }\n\n private _resync: (() => void) | null = null;\n\n /**\n * Reconcile PixiJS containers with the current node data.\n * Creates new containers, updates existing, removes stale.\n */\n sync(\n flowNodes: FlowNode[],\n selectedIds: Set<string>,\n hoveredId: string | null,\n animSeqMap?: Map<string, number>,\n options?: {\n showAnchors?: boolean;\n presentation?: boolean;\n presentationAnchorId?: string;\n presentationAnchorVisible?: boolean;\n },\n ): void {\n const seen = new Set<string>();\n this._resync = () => this.sync(flowNodes, selectedIds, hoveredId, animSeqMap, options);\n\n // Animation-anchor display sequence (1-based). When a global map is\n // provided (document-wide, shared across sub-canvases) it is used directly;\n // otherwise derive a per-canvas order from stable creation index.\n const seqOf = animSeqMap ?? (() => {\n const anchors = flowNodes\n .filter((n) => n.type === 'animAnchor')\n .sort((a, b) => (a.data.animIndex ?? 0) - (b.data.animIndex ?? 0));\n const m = new Map<string, number>();\n anchors.forEach((n, i) => m.set(n.id, i + 1));\n return m;\n })();\n\n for (const node of flowNodes) {\n seen.add(node.id);\n let nc = this.nodes.get(node.id);\n if (!nc) {\n nc = this._createNode(node);\n this.nodes.set(node.id, nc);\n }\n this._updateNode(\n nc,\n node,\n selectedIds.has(node.id),\n hoveredId === node.id,\n seqOf.get(node.id),\n options,\n );\n }\n\n // Remove nodes no longer in data\n for (const [id, nc] of this.nodes) {\n if (!seen.has(id)) {\n this.nodeLayer.removeChild(nc.container);\n nc.container.destroy({ children: true });\n this.nodes.delete(id);\n }\n }\n }\n\n getNodeContainer(id: string): NodeContainer | undefined {\n return this.nodes.get(id);\n }\n\n getAllNodeContainers(): NodeContainer[] {\n return [...this.nodes.values()];\n }\n\n private _createNode(node: FlowNode): NodeContainer {\n const container = new Container({ label: `node-${node.id}` });\n container.eventMode = 'static';\n container.cursor = 'pointer';\n\n const svgTransform = new Container({ label: 'svg-transform' });\n container.addChild(svgTransform);\n\n const subCanvasGlow = new Graphics();\n subCanvasGlow.label = 'sub-canvas-glow';\n container.addChild(subCanvasGlow);\n\n const shape = new Graphics();\n shape.label = 'shape';\n container.addChild(shape);\n\n const icon = new Sprite();\n icon.label = 'svg-icon';\n icon.anchor.set(0.5, 0.5);\n icon.visible = false;\n container.addChild(icon);\n\n const text = createNodeText({\n label: node.data.label,\n color: resolveThemeColor(node.data.labelColor ?? node.data.color, '#111827'),\n fontSize: node.data.fontSize,\n width: node.width,\n height: node.height,\n });\n container.addChild(text);\n\n const handleDefs = getHandlePositions(node.width, node.height);\n const handles = createHandleGraphics(container, handleDefs, false);\n\n // Sequence badge for animation anchors (top-left corner).\n const animBadge = new Text({\n text: '',\n style: { fontFamily: 'system-ui, sans-serif', fontSize: 13, fill: '#ffffff', fontWeight: '700' },\n });\n animBadge.label = 'anim-badge';\n animBadge.anchor.set(0.5, 0.5);\n animBadge.visible = false;\n container.addChild(animBadge);\n\n this.nodeLayer.addChild(container);\n\n return { container, shape, svgTransform, icon, text, animBadge, handles, handleDefs, nodeId: node.id, subCanvasGlow };\n }\n\n private _updateNode(\n nc: NodeContainer,\n node: FlowNode,\n selected: boolean,\n hovered: boolean,\n animSeq?: number,\n options?: {\n showAnchors?: boolean;\n presentation?: boolean;\n presentationAnchorId?: string;\n presentationAnchorVisible?: boolean;\n },\n ): void {\n const { container, svgTransform, shape, icon, text, animBadge, handles, subCanvasGlow } = nc;\n\n const isSvg = node.type === 'shapeSvg';\n const rad = getRotationRad(node.data);\n const flip = getFlipScale(node.data);\n\n container.zIndex = node.zIndex ?? 0;\n if (isSvg) {\n // Keep the label in the untransformed root. Only the icon box, icon and\n // connection handles rotate/flip around the node center.\n if (shape.parent !== svgTransform) svgTransform.addChild(shape);\n if (icon.parent !== svgTransform) svgTransform.addChild(icon);\n if (handles.parent !== svgTransform) svgTransform.addChild(handles);\n container.position.set(node.position.x, node.position.y);\n container.rotation = 0;\n container.scale.set(1, 1);\n container.pivot.set(0, 0);\n svgTransform.position.set(node.width / 2, node.height / 2);\n svgTransform.pivot.set(node.width / 2, node.height / 2);\n svgTransform.rotation = rad;\n svgTransform.scale.set(flip.sx, flip.sy);\n } else {\n if (shape.parent !== container) container.addChildAt(shape, Math.min(2, container.children.length));\n if (icon.parent !== container) container.addChild(icon);\n if (handles.parent !== container) container.addChild(handles);\n svgTransform.rotation = 0;\n svgTransform.scale.set(1, 1);\n container.position.set(node.position.x, node.position.y);\n container.rotation = rad;\n container.scale.set(flip.sx, flip.sy);\n if (rad !== 0 || flip.sx < 0 || flip.sy < 0) {\n container.pivot.set(node.width / 2, node.height / 2);\n container.position.set(node.position.x + node.width / 2, node.position.y + node.height / 2);\n } else {\n container.pivot.set(0, 0);\n }\n }\n\n const isMedia = node.type === 'mediaNode';\n const isAnchor = node.type === 'animAnchor';\n\n // Redraw shape\n shape.clear();\n shape.alpha = 1;\n if (isSvg) {\n this._updateSvgNode(nc, node, selected);\n } else if (isMedia) {\n // Media nodes render their content in a synced DOM overlay; PixiJS only\n // draws the frame (background + border) beneath the overlay.\n icon.visible = false;\n const r = 6;\n const fill = node.data.fill && node.data.fill !== 'transparent' ? resolveThemeColor(node.data.fill, '#ffffff') : '#ffffff';\n const borderHidden = node.data.borderStyle === 'none';\n const strokeColor = selected ? '#3b82f6' : resolveThemeColor(node.data.stroke, '#374151');\n const strokeW = selected ? Math.max(node.data.strokeWidth, 2) : node.data.strokeWidth;\n shapeDrawers.shapeRoundRect(shape, {\n width: node.width,\n height: node.height,\n fill,\n stroke: strokeColor,\n strokeWidth: strokeW,\n borderStyle: selected && borderHidden ? 'solid' : node.data.borderStyle,\n dashOffset: this._dynamicOffset,\n });\n } else if (isAnchor) {\n // Animation anchors are globally visible/hidden in editing mode. During\n // presentation the current frame remains as a subtle dashed overlay.\n icon.visible = false;\n const accent = '#8b5cf6';\n const presentation = options?.presentation ?? false;\n const anchorVisible = presentation\n ? (options?.presentationAnchorVisible ?? false) && options?.presentationAnchorId === node.id\n : (options?.showAnchors ?? true);\n if (anchorVisible) {\n shape.alpha = presentation ? 0.48 : 0.9;\n shapeDrawers.shapeRoundRect(shape, {\n width: node.width,\n height: node.height,\n fill: 'transparent',\n stroke: selected && !presentation ? '#3b82f6' : accent,\n strokeWidth: selected && !presentation ? 2.5 : 1.5,\n borderStyle: 'dashed',\n });\n shape.circle(0, 0, presentation ? 11 : 13).fill({\n color: selected && !presentation ? '#3b82f6' : accent,\n });\n }\n animBadge.text = String(animSeq ?? '');\n animBadge.alpha = presentation ? 0.7 : 1;\n animBadge.visible = anchorVisible;\n animBadge.position.set(0, 0);\n } else {\n icon.visible = false;\n const drawFn = shapeDrawers[node.type] ?? shapeDrawers.shapeRect;\n const borderHidden = node.data.borderStyle === 'none';\n const opts: ShapeDrawOptions = {\n width: node.width,\n height: node.height,\n fill: resolveThemeColor(node.data.fill, '#ffffff'),\n stroke: selected ? '#3b82f6' : resolveThemeColor(node.data.stroke, '#374151'),\n strokeWidth: selected ? Math.max(node.data.strokeWidth, 2) : node.data.strokeWidth,\n borderStyle: (selected && borderHidden) ? 'solid' : node.data.borderStyle,\n dashOffset: this._dynamicOffset,\n };\n drawFn(shape, opts);\n }\n if (!isAnchor) animBadge.visible = false;\n\n // Sub-canvas glow indicator\n subCanvasGlow.clear();\n if (node.data.childCanvasId) {\n const pad = 4;\n const w = node.width + pad * 2;\n const h = node.height + pad * 2;\n const pulse = 0.5 + 0.3 * Math.sin(this._dynamicOffset * 0.008);\n subCanvasGlow.roundRect(-pad, -pad, w, h, 6);\n subCanvasGlow.stroke({ color: 0x8b5cf6, width: 2.5, alpha: pulse });\n subCanvasGlow.roundRect(-pad - 2, -pad - 2, w + 4, h + 4, 8);\n subCanvasGlow.stroke({ color: 0x8b5cf6, width: 1, alpha: pulse * 0.4 });\n }\n\n // Text: counter-rotate and counter-flip so it stays upright\n const iconLabelPlacement = normalizeIconLabelPlacement(node.data.labelPlacement);\n // SVG-icon labels default to the theme font color (so they read on any\n // theme) even when the icon body uses a brand color; other node types fall\n // back to the node's own text color.\n const labelColor = node.data.labelColor\n ?? (isSvg ? 'theme:base-content' : node.data.color);\n updateNodeText(text, {\n label: isMedia || isAnchor\n ? ''\n : isSvg\n ? formatIconLabel(node.data.label, iconLabelPlacement)\n : node.data.label,\n color: resolveThemeColor(labelColor, '#111827'),\n fontSize: node.data.fontSize,\n width: node.width,\n height: node.height,\n });\n text.visible = !isMedia && !isAnchor;\n\n if (node.type === 'shapeCorner') {\n const half = Math.min(node.width, node.height) * 0.4;\n text.position.set((half + node.width) / 2, (half + node.height) / 2);\n } else if (isSvg) {\n const gap = 4;\n const halfTextWidth = text.width / 2;\n const halfTextHeight = text.height / 2;\n if (iconLabelPlacement === 'top') {\n text.position.set(node.width / 2, -gap - halfTextHeight);\n } else if (iconLabelPlacement === 'bottom') {\n text.position.set(node.width / 2, node.height + gap + halfTextHeight);\n } else if (iconLabelPlacement === 'left') {\n text.position.set(-gap - halfTextWidth, node.height / 2);\n } else if (iconLabelPlacement === 'right') {\n text.position.set(node.width + gap + halfTextWidth, node.height / 2);\n } else {\n text.position.set(node.width / 2, node.height / 2);\n }\n text.position.x += node.data.labelOffsetX ?? 0;\n text.position.y += node.data.labelOffsetY ?? 0;\n }\n\n if (isSvg) {\n text.rotation = 0;\n text.scale.set(1, 1);\n } else {\n text.rotation = -rad;\n text.scale.set(flip.sx, flip.sy);\n }\n\n // Handles visibility\n handles.visible = (hovered || selected) && !(isAnchor && options?.presentation);\n if (handles.visible) {\n const defs = getHandlePositions(node.width, node.height);\n nc.handleDefs = defs;\n updateHandleGraphics(handles, defs);\n }\n }\n\n /**\n * Draw an SVG-stamp node: optional bordered box + centered icon sprite.\n * The icon texture is rasterized lazily; a redraw is requested when ready.\n */\n private _updateSvgNode(nc: NodeContainer, node: FlowNode, selected: boolean): void {\n const { shape, icon } = nc;\n const { width, height, data } = node;\n\n // Render the configured icon box independently from the solid selection\n // outline. Otherwise selecting an icon makes dotted/dashed borders appear\n // solid and hides whether the chosen border style is actually applied.\n const showBox = data.iconBox ?? false;\n const borderStyle = data.borderStyle ?? (showBox ? 'solid' : 'none');\n const borderHidden = borderStyle === 'none';\n const r = Math.min(8, width * 0.12, height * 0.12);\n if (data.fill && data.fill !== 'transparent' && (showBox || !borderHidden)) {\n shape.roundRect(0, 0, width, height, r).fill({ color: resolveThemeColor(data.fill, '#ffffff') });\n }\n if (!borderHidden && data.stroke && data.stroke !== 'transparent' && data.strokeWidth > 0) {\n drawRoundRectBorder(shape, {\n width,\n height,\n fill: 'transparent',\n stroke: resolveThemeColor(data.stroke, '#374151'),\n strokeWidth: data.strokeWidth,\n borderStyle,\n dashOffset: this._dynamicOffset,\n }, r);\n }\n if (selected) {\n shape.roundRect(0, 0, width, height, r).stroke({\n color: '#3b82f6',\n width: Math.max(data.strokeWidth, 2),\n });\n }\n\n // Icon sprite: fit within the box with padding, centered. The texture is\n // rasterized lazily; because the ticker re-runs sync every frame, it will\n // be picked up automatically once cached.\n const iconColor = resolveThemeColor(data.color, '#334155') || '#334155';\n const tex = getIconTexture(data.svgId ?? '', iconColor);\n if (tex) {\n icon.texture = tex;\n icon.visible = true;\n const pad = showBox ? Math.min(width, height) * 0.18 : 2;\n const box = Math.max(4, Math.min(width, height) - pad * 2);\n icon.width = box;\n icon.height = box;\n icon.position.set(width / 2, height / 2);\n } else {\n icon.visible = false;\n }\n }\n\n destroy(): void {\n this._unsubscribeTextureReady();\n this._resync = null;\n for (const [, nc] of this.nodes) {\n nc.container.destroy({ children: true });\n }\n this.nodes.clear();\n this.nodeLayer.destroy({ children: true });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"NodeRenderer.js","names":[],"sources":["../../../../../src/components/pro/Flow/nodes/NodeRenderer.ts"],"sourcesContent":["import { Container, Graphics, Text, Sprite, TextStyle } from 'pixi.js';\nimport type { FlowNode, FlowTextPlacement } from '../types';\nimport { drawRoundRectBorder, shapeDrawers, type ShapeDrawOptions } from './shapes';\nimport { createNodeText, formatIconLabel, normalizeIconLabelPlacement, updateNodeText } from './NodeText';\nimport { getHandlePositions, createHandleGraphics, updateHandleGraphics, type HandleDef } from './NodeHandles';\nimport { getRotationRad, getFlipScale } from './nodeUtils';\nimport { getIconTexture, subscribeIconTextureReady } from './svgIconTexture';\nimport { resolveThemeColor } from '../utils/themeColor';\n\n/**\n * Resolve the center point of a text block (title + optional sublabel) inside a\n * node of the given size, for a 9-way placement. Non-center placements pull the\n * block against the corresponding edge/corner with a small inset.\n */\nfunction resolveTextBlockCenter(\n placement: FlowTextPlacement,\n nodeW: number,\n nodeH: number,\n blockW: number,\n blockH: number,\n): { x: number; y: number } {\n const inset = 6;\n const left = inset + blockW / 2;\n const right = nodeW - inset - blockW / 2;\n const cx = nodeW / 2;\n const top = inset + blockH / 2;\n const bottom = nodeH - inset - blockH / 2;\n const cy = nodeH / 2;\n switch (placement) {\n case 'top': return { x: cx, y: top };\n case 'bottom': return { x: cx, y: bottom };\n case 'left': return { x: left, y: cy };\n case 'right': return { x: right, y: cy };\n case 'top-left': return { x: left, y: top };\n case 'top-right': return { x: right, y: top };\n case 'bottom-left': return { x: left, y: bottom };\n case 'bottom-right': return { x: right, y: bottom };\n case 'center':\n default:\n return { x: cx, y: cy };\n }\n}\n\nexport interface NodeContainer {\n container: Container;\n shape: Graphics;\n /** Rotated/flipped visual content for SVG icon stamps. */\n svgTransform: Container;\n icon: Sprite;\n text: Text;\n /** Optional muted second line (Archify card sublabel). */\n subtext: Text;\n /** Optional top-right pill background + label (Archify card tag). */\n tagBg: Graphics;\n tagText: Text;\n /** Sequence badge shown on `animAnchor` nodes. */\n animBadge: Text;\n handles: Graphics;\n handleDefs: HandleDef[];\n nodeId: string;\n subCanvasGlow: Graphics;\n}\n\n/**\n * Manages PixiJS display objects for all nodes on the current canvas.\n * Syncs from FlowNode[] data → PixiJS scene graph.\n */\nexport class NodeRenderer {\n private world: Container;\n private nodeLayer: Container;\n private nodes = new Map<string, NodeContainer>();\n private _dynamicOffset = 0;\n private _unsubscribeTextureReady: () => void;\n\n /** Call once per frame to advance the dynamic dash animation. */\n advanceAnimation(deltaMs: number): void {\n this._dynamicOffset = (this._dynamicOffset + deltaMs * 0.06) % 1000;\n }\n\n constructor(world: Container) {\n this.world = world;\n this.nodeLayer = new Container({ label: 'nodes', sortableChildren: true });\n this.world.addChild(this.nodeLayer);\n this._unsubscribeTextureReady = subscribeIconTextureReady(() => this._resync?.());\n }\n\n private _resync: (() => void) | null = null;\n\n /**\n * Reconcile PixiJS containers with the current node data.\n * Creates new containers, updates existing, removes stale.\n */\n sync(\n flowNodes: FlowNode[],\n selectedIds: Set<string>,\n hoveredId: string | null,\n animSeqMap?: Map<string, number>,\n options?: {\n showAnchors?: boolean;\n presentation?: boolean;\n presentationAnchorId?: string;\n presentationAnchorVisible?: boolean;\n },\n ): void {\n const seen = new Set<string>();\n this._resync = () => this.sync(flowNodes, selectedIds, hoveredId, animSeqMap, options);\n\n // Animation-anchor display sequence (1-based). When a global map is\n // provided (document-wide, shared across sub-canvases) it is used directly;\n // otherwise derive a per-canvas order from stable creation index.\n const seqOf = animSeqMap ?? (() => {\n const anchors = flowNodes\n .filter((n) => n.type === 'animAnchor')\n .sort((a, b) => (a.data.animIndex ?? 0) - (b.data.animIndex ?? 0));\n const m = new Map<string, number>();\n anchors.forEach((n, i) => m.set(n.id, i + 1));\n return m;\n })();\n\n for (const node of flowNodes) {\n seen.add(node.id);\n let nc = this.nodes.get(node.id);\n if (!nc) {\n nc = this._createNode(node);\n this.nodes.set(node.id, nc);\n }\n this._updateNode(\n nc,\n node,\n selectedIds.has(node.id),\n hoveredId === node.id,\n seqOf.get(node.id),\n options,\n );\n }\n\n // Remove nodes no longer in data\n for (const [id, nc] of this.nodes) {\n if (!seen.has(id)) {\n this.nodeLayer.removeChild(nc.container);\n nc.container.destroy({ children: true });\n this.nodes.delete(id);\n }\n }\n }\n\n getNodeContainer(id: string): NodeContainer | undefined {\n return this.nodes.get(id);\n }\n\n getAllNodeContainers(): NodeContainer[] {\n return [...this.nodes.values()];\n }\n\n private _createNode(node: FlowNode): NodeContainer {\n const container = new Container({ label: `node-${node.id}` });\n container.eventMode = 'static';\n container.cursor = 'pointer';\n\n const svgTransform = new Container({ label: 'svg-transform' });\n container.addChild(svgTransform);\n\n const subCanvasGlow = new Graphics();\n subCanvasGlow.label = 'sub-canvas-glow';\n container.addChild(subCanvasGlow);\n\n const shape = new Graphics();\n shape.label = 'shape';\n container.addChild(shape);\n\n const icon = new Sprite();\n icon.label = 'svg-icon';\n icon.anchor.set(0.5, 0.5);\n icon.visible = false;\n container.addChild(icon);\n\n const text = createNodeText({\n label: node.data.label,\n color: resolveThemeColor(node.data.labelColor ?? node.data.color, '#111827'),\n fontSize: node.data.fontSize,\n width: node.width,\n height: node.height,\n });\n container.addChild(text);\n\n // Optional muted second line (Archify card sublabel).\n const subtext = new Text({\n text: '',\n style: {\n fontFamily: 'system-ui, -apple-system, sans-serif',\n fontSize: 11,\n fill: '#94a3b8',\n align: 'center',\n },\n });\n subtext.label = 'node-subtext';\n subtext.anchor.set(0.5, 0.5);\n subtext.visible = false;\n container.addChild(subtext);\n\n // Optional top-right pill (Archify card tag).\n const tagBg = new Graphics();\n tagBg.label = 'node-tag-bg';\n tagBg.visible = false;\n container.addChild(tagBg);\n const tagText = new Text({\n text: '',\n style: {\n fontFamily: 'system-ui, -apple-system, sans-serif',\n fontSize: 9,\n fill: '#cbd5e1',\n },\n });\n tagText.label = 'node-tag-text';\n tagText.anchor.set(0.5, 0.5);\n tagText.visible = false;\n container.addChild(tagText);\n\n const handleDefs = getHandlePositions(node.width, node.height);\n const handles = createHandleGraphics(container, handleDefs, false);\n\n // Sequence badge for animation anchors (top-left corner).\n const animBadge = new Text({\n text: '',\n style: { fontFamily: 'system-ui, sans-serif', fontSize: 13, fill: '#ffffff', fontWeight: '700' },\n });\n animBadge.label = 'anim-badge';\n animBadge.anchor.set(0.5, 0.5);\n animBadge.visible = false;\n container.addChild(animBadge);\n\n this.nodeLayer.addChild(container);\n\n return { container, shape, svgTransform, icon, text, subtext, tagBg, tagText, animBadge, handles, handleDefs, nodeId: node.id, subCanvasGlow };\n }\n\n private _updateNode(\n nc: NodeContainer,\n node: FlowNode,\n selected: boolean,\n hovered: boolean,\n animSeq?: number,\n options?: {\n showAnchors?: boolean;\n presentation?: boolean;\n presentationAnchorId?: string;\n presentationAnchorVisible?: boolean;\n },\n ): void {\n const { container, svgTransform, shape, icon, text, subtext, tagBg, tagText, animBadge, handles, subCanvasGlow } = nc;\n\n const isSvg = node.type === 'shapeSvg';\n const rad = getRotationRad(node.data);\n const flip = getFlipScale(node.data);\n\n container.zIndex = node.zIndex ?? 0;\n if (isSvg) {\n // Keep the label in the untransformed root. Only the icon box, icon and\n // connection handles rotate/flip around the node center.\n if (shape.parent !== svgTransform) svgTransform.addChild(shape);\n if (icon.parent !== svgTransform) svgTransform.addChild(icon);\n if (handles.parent !== svgTransform) svgTransform.addChild(handles);\n container.position.set(node.position.x, node.position.y);\n container.rotation = 0;\n container.scale.set(1, 1);\n container.pivot.set(0, 0);\n svgTransform.position.set(node.width / 2, node.height / 2);\n svgTransform.pivot.set(node.width / 2, node.height / 2);\n svgTransform.rotation = rad;\n svgTransform.scale.set(flip.sx, flip.sy);\n } else {\n if (shape.parent !== container) container.addChildAt(shape, Math.min(2, container.children.length));\n if (icon.parent !== container) container.addChild(icon);\n if (handles.parent !== container) container.addChild(handles);\n svgTransform.rotation = 0;\n svgTransform.scale.set(1, 1);\n container.position.set(node.position.x, node.position.y);\n container.rotation = rad;\n container.scale.set(flip.sx, flip.sy);\n if (rad !== 0 || flip.sx < 0 || flip.sy < 0) {\n container.pivot.set(node.width / 2, node.height / 2);\n container.position.set(node.position.x + node.width / 2, node.position.y + node.height / 2);\n } else {\n container.pivot.set(0, 0);\n }\n }\n\n const isMedia = node.type === 'mediaNode';\n const isAnchor = node.type === 'animAnchor';\n // Anchors only show their label/badge when the anchor itself is visible.\n let anchorVisible = true;\n\n // Redraw shape\n shape.clear();\n shape.alpha = 1;\n if (isSvg) {\n this._updateSvgNode(nc, node, selected);\n } else if (isMedia) {\n // Media nodes render their content in a synced DOM overlay; PixiJS only\n // draws the frame (background + border) beneath the overlay.\n icon.visible = false;\n const r = 6;\n const fill = node.data.fill && node.data.fill !== 'transparent' ? resolveThemeColor(node.data.fill, '#ffffff') : '#ffffff';\n const borderHidden = node.data.borderStyle === 'none';\n const strokeColor = selected ? '#3b82f6' : resolveThemeColor(node.data.stroke, '#374151');\n const strokeW = selected ? Math.max(node.data.strokeWidth, 2) : node.data.strokeWidth;\n shapeDrawers.shapeRoundRect(shape, {\n width: node.width,\n height: node.height,\n fill,\n stroke: strokeColor,\n strokeWidth: strokeW,\n borderStyle: selected && borderHidden ? 'solid' : node.data.borderStyle,\n dashOffset: this._dynamicOffset,\n });\n } else if (isAnchor) {\n // Animation anchors are globally visible/hidden in editing mode. During\n // presentation the current frame remains as a subtle dashed overlay.\n icon.visible = false;\n const accent = '#8b5cf6';\n const presentation = options?.presentation ?? false;\n anchorVisible = presentation\n ? (options?.presentationAnchorVisible ?? false) && options?.presentationAnchorId === node.id\n : (options?.showAnchors ?? true);\n if (anchorVisible) {\n shape.alpha = presentation ? 0.48 : 0.9;\n shapeDrawers.shapeRoundRect(shape, {\n width: node.width,\n height: node.height,\n fill: 'transparent',\n stroke: selected && !presentation ? '#3b82f6' : accent,\n strokeWidth: selected && !presentation ? 2.5 : 1.5,\n borderStyle: 'dashed',\n });\n shape.circle(0, 0, presentation ? 11 : 13).fill({\n color: selected && !presentation ? '#3b82f6' : accent,\n });\n }\n animBadge.text = String(animSeq ?? '');\n animBadge.alpha = presentation ? 0.7 : 1;\n animBadge.visible = anchorVisible;\n animBadge.position.set(0, 0);\n } else {\n icon.visible = false;\n const drawFn = shapeDrawers[node.type] ?? shapeDrawers.shapeRect;\n const borderHidden = node.data.borderStyle === 'none';\n const opts: ShapeDrawOptions = {\n width: node.width,\n height: node.height,\n fill: resolveThemeColor(node.data.fill, '#ffffff'),\n stroke: selected ? '#3b82f6' : resolveThemeColor(node.data.stroke, '#374151'),\n strokeWidth: selected ? Math.max(node.data.strokeWidth, 2) : node.data.strokeWidth,\n borderStyle: (selected && borderHidden) ? 'solid' : node.data.borderStyle,\n dashOffset: this._dynamicOffset,\n };\n drawFn(shape, opts);\n }\n if (!isAnchor) animBadge.visible = false;\n\n // Sub-canvas glow indicator\n subCanvasGlow.clear();\n if (node.data.childCanvasId) {\n const pad = 4;\n const w = node.width + pad * 2;\n const h = node.height + pad * 2;\n const pulse = 0.5 + 0.3 * Math.sin(this._dynamicOffset * 0.008);\n subCanvasGlow.roundRect(-pad, -pad, w, h, 6);\n subCanvasGlow.stroke({ color: 0x8b5cf6, width: 2.5, alpha: pulse });\n subCanvasGlow.roundRect(-pad - 2, -pad - 2, w + 4, h + 4, 8);\n subCanvasGlow.stroke({ color: 0x8b5cf6, width: 1, alpha: pulse * 0.4 });\n }\n\n // Text: counter-rotate and counter-flip so it stays upright\n const iconLabelPlacement = normalizeIconLabelPlacement(node.data.labelPlacement);\n // SVG-icon labels default to the theme font color (so they read on any\n // theme) even when the icon body uses a brand color; other node types fall\n // back to the node's own text color.\n const labelColor = node.data.labelColor\n ?? (isSvg ? 'theme:base-content' : node.data.color);\n updateNodeText(text, {\n label: isMedia\n ? ''\n : isSvg\n ? formatIconLabel(node.data.label, iconLabelPlacement)\n : node.data.label,\n color: resolveThemeColor(labelColor, '#111827'),\n fontSize: node.data.fontSize,\n width: node.width,\n height: node.height,\n });\n text.visible = !isMedia && (!isAnchor || anchorVisible);\n\n // Card extras: muted sublabel line + tag pill. Available on ordinary\n // shapes, group frames, and (when shown) animation anchors.\n const showExtras = !isSvg && !isMedia && (!isAnchor || anchorVisible);\n const sublabel = showExtras ? (node.data.sublabel ?? '').trim() : '';\n const hasSub = sublabel.length > 0;\n\n if (node.type === 'shapeCorner') {\n const half = Math.min(node.width, node.height) * 0.4;\n text.position.set((half + node.width) / 2, (half + node.height) / 2);\n } else if (isSvg) {\n const gap = 4;\n const halfTextWidth = text.width / 2;\n const halfTextHeight = text.height / 2;\n if (iconLabelPlacement === 'top') {\n text.position.set(node.width / 2, -gap - halfTextHeight);\n } else if (iconLabelPlacement === 'bottom') {\n text.position.set(node.width / 2, node.height + gap + halfTextHeight);\n } else if (iconLabelPlacement === 'left') {\n text.position.set(-gap - halfTextWidth, node.height / 2);\n } else if (iconLabelPlacement === 'right') {\n text.position.set(node.width + gap + halfTextWidth, node.height / 2);\n } else {\n text.position.set(node.width / 2, node.height / 2);\n }\n text.position.x += node.data.labelOffsetX ?? 0;\n text.position.y += node.data.labelOffsetY ?? 0;\n } else if (!isMedia) {\n // Ordinary shapes, group frames, and anchors: 9-way text placement, with\n // an optional sublabel line stacked beneath the title. Both lines stay\n // center-anchored; only the block's center point moves per placement.\n const gap = 3;\n const subFont = Math.max(9, node.data.fontSize - 3);\n if (hasSub) {\n const s = subtext.style as TextStyle;\n s.fill = resolveThemeColor(node.data.sublabelColor ?? '#94a3b8', '#94a3b8');\n s.fontSize = subFont;\n subtext.text = sublabel;\n subtext.anchor.set(0.5, 0.5);\n subtext.visible = true;\n subtext.rotation = -rad;\n subtext.scale.set(flip.sx, flip.sy);\n }\n text.anchor.set(0.5, 0.5);\n const blockH = text.height + (hasSub ? gap + subtext.height : 0);\n const blockW = Math.max(text.width, hasSub ? subtext.width : 0);\n // Anchors and group frames default their text to the top band; ordinary\n // shapes default to centered.\n const isGroupFrame = node.data.isGroup || node.type === 'flowGroup' || node.type === 'geometryGroup';\n const placement = node.data.textPlacement ?? (isAnchor || isGroupFrame ? 'top' : 'center');\n const c = resolveTextBlockCenter(\n placement,\n node.width,\n node.height,\n blockW,\n blockH,\n );\n const bx = c.x + (node.data.labelOffsetX ?? 0);\n const by = c.y + (node.data.labelOffsetY ?? 0);\n text.position.set(bx, by - blockH / 2 + text.height / 2);\n if (hasSub) subtext.position.set(bx, by + blockH / 2 - subtext.height / 2);\n }\n if (!hasSub) subtext.visible = false;\n\n if (isSvg) {\n text.rotation = 0;\n text.scale.set(1, 1);\n } else {\n text.rotation = -rad;\n text.scale.set(flip.sx, flip.sy);\n }\n\n // Tag pill: placed in one of four corners with its own color.\n const tag = showExtras ? (node.data.tag ?? '').trim() : '';\n if (tag) {\n tagText.text = tag;\n tagText.visible = true;\n const padX = 5;\n const padY = 2;\n const tw = tagText.width + padX * 2;\n const th = tagText.height + padY * 2;\n const margin = 6;\n const placement = node.data.tagPlacement ?? 'top-right';\n const tx = placement === 'top-left' || placement === 'bottom-left'\n ? margin\n : node.width - tw - margin;\n const ty = placement === 'top-left' || placement === 'top-right'\n ? margin\n : node.height - th - margin;\n const tagColor = resolveThemeColor(node.data.tagColor ?? node.data.stroke, '#334155');\n tagBg.clear();\n tagBg\n .roundRect(tx, ty, tw, th, 3)\n .fill({ color: tagColor, alpha: 0.18 })\n .stroke({ color: tagColor, width: 1, alpha: 0.55 });\n tagBg.visible = true;\n (tagText.style as TextStyle).fill = tagColor;\n tagText.position.set(tx + tw / 2, ty + th / 2);\n tagText.rotation = 0;\n tagText.scale.set(1, 1);\n } else {\n tagBg.visible = false;\n tagText.visible = false;\n }\n\n // Handles visibility\n handles.visible = (hovered || selected) && !(isAnchor && options?.presentation);\n if (handles.visible) {\n const defs = getHandlePositions(node.width, node.height);\n nc.handleDefs = defs;\n updateHandleGraphics(handles, defs);\n }\n }\n\n /**\n * Draw an SVG-stamp node: optional bordered box + centered icon sprite.\n * The icon texture is rasterized lazily; a redraw is requested when ready.\n */\n private _updateSvgNode(nc: NodeContainer, node: FlowNode, selected: boolean): void {\n const { shape, icon } = nc;\n const { width, height, data } = node;\n\n // Render the configured icon box independently from the solid selection\n // outline. Otherwise selecting an icon makes dotted/dashed borders appear\n // solid and hides whether the chosen border style is actually applied.\n const showBox = data.iconBox ?? false;\n const borderStyle = data.borderStyle ?? (showBox ? 'solid' : 'none');\n const borderHidden = borderStyle === 'none';\n const r = Math.min(8, width * 0.12, height * 0.12);\n if (data.fill && data.fill !== 'transparent' && (showBox || !borderHidden)) {\n shape.roundRect(0, 0, width, height, r).fill({ color: resolveThemeColor(data.fill, '#ffffff') });\n }\n if (!borderHidden && data.stroke && data.stroke !== 'transparent' && data.strokeWidth > 0) {\n drawRoundRectBorder(shape, {\n width,\n height,\n fill: 'transparent',\n stroke: resolveThemeColor(data.stroke, '#374151'),\n strokeWidth: data.strokeWidth,\n borderStyle,\n dashOffset: this._dynamicOffset,\n }, r);\n }\n if (selected) {\n shape.roundRect(0, 0, width, height, r).stroke({\n color: '#3b82f6',\n width: Math.max(data.strokeWidth, 2),\n });\n }\n\n // Icon sprite: fit within the box with padding, centered. The texture is\n // rasterized lazily; because the ticker re-runs sync every frame, it will\n // be picked up automatically once cached.\n const iconColor = resolveThemeColor(data.color, '#334155') || '#334155';\n const tex = getIconTexture(data.svgId ?? '', iconColor);\n if (tex) {\n icon.texture = tex;\n icon.visible = true;\n const pad = showBox ? Math.min(width, height) * 0.18 : 2;\n const box = Math.max(4, Math.min(width, height) - pad * 2);\n icon.width = box;\n icon.height = box;\n icon.position.set(width / 2, height / 2);\n } else {\n icon.visible = false;\n }\n }\n\n destroy(): void {\n this._unsubscribeTextureReady();\n this._resync = null;\n for (const [, nc] of this.nodes) {\n nc.container.destroy({ children: true });\n }\n this.nodes.clear();\n this.nodeLayer.destroy({ children: true });\n }\n}\n"],"mappings":"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"}