dishui 0.0.64 → 0.0.65

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 (177) hide show
  1. package/dist/components/Badge/index.js +12 -9
  2. package/dist/components/Badge/index.js.map +1 -1
  3. package/dist/components/Button/index.js +43 -40
  4. package/dist/components/Button/index.js.map +1 -1
  5. package/dist/components/Card/index.d.ts +11 -0
  6. package/dist/components/Card/index.js +62 -37
  7. package/dist/components/Card/index.js.map +1 -1
  8. package/dist/components/Chart/Chart.js.map +1 -1
  9. package/dist/components/Checkbox/index.js +32 -30
  10. package/dist/components/Checkbox/index.js.map +1 -1
  11. package/dist/components/Demo/index.js.map +1 -1
  12. package/dist/components/EmptyState/index.d.ts +4 -1
  13. package/dist/components/EmptyState/index.js +3 -3
  14. package/dist/components/EmptyState/index.js.map +1 -1
  15. package/dist/components/FileUploader/DropZone.js.map +1 -1
  16. package/dist/components/FileUploader/FileItem.js.map +1 -1
  17. package/dist/components/FileUploader/FileUploader.js.map +1 -1
  18. package/dist/components/FileUploader/UploadQueue.js.map +1 -1
  19. package/dist/components/Input/index.js +30 -30
  20. package/dist/components/Input/index.js.map +1 -1
  21. package/dist/components/Label/index.js +41 -40
  22. package/dist/components/Label/index.js.map +1 -1
  23. package/dist/components/List/index.js +47 -32
  24. package/dist/components/List/index.js.map +1 -1
  25. package/dist/components/Markdown/Markdown.js +61 -57
  26. package/dist/components/Markdown/Markdown.js.map +1 -1
  27. package/dist/components/Markdown/markdownComponents.js +49 -49
  28. package/dist/components/Markdown/markdownComponents.js.map +1 -1
  29. package/dist/components/Modal/index.d.ts +7 -3
  30. package/dist/components/Modal/index.js +77 -65
  31. package/dist/components/Modal/index.js.map +1 -1
  32. package/dist/components/Page/index.d.ts +58 -0
  33. package/dist/components/Page/index.js +74 -0
  34. package/dist/components/Page/index.js.map +1 -0
  35. package/dist/components/PageHeader/index.js.map +1 -1
  36. package/dist/components/Select/index.js +0 -3
  37. package/dist/components/Select/index.js.map +1 -1
  38. package/dist/components/SidebarToggleButton/index.js.map +1 -1
  39. package/dist/components/StatCard/index.d.ts +3 -1
  40. package/dist/components/StatCard/index.js +39 -11
  41. package/dist/components/StatCard/index.js.map +1 -1
  42. package/dist/components/Table/index.js +103 -85
  43. package/dist/components/Table/index.js.map +1 -1
  44. package/dist/components/Tabs/index.d.ts +19 -5
  45. package/dist/components/Tabs/index.js +32 -13
  46. package/dist/components/Tabs/index.js.map +1 -1
  47. package/dist/components/Tree/Tree.js.map +1 -1
  48. package/dist/components/pro/ArticleContextMenu/index.js.map +1 -1
  49. package/dist/components/pro/ArticleControl/ArticleControl2.js.map +1 -1
  50. package/dist/components/pro/CodeEditor/editors/CodeEditor.js +141 -134
  51. package/dist/components/pro/CodeEditor/editors/CodeEditor.js.map +1 -1
  52. package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js +81 -78
  53. package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
  54. package/dist/components/pro/CodeEditor/panels/FootnotePanel.js.map +1 -1
  55. package/dist/components/pro/CodeEditor/panels/HistoryPanel.js.map +1 -1
  56. package/dist/components/pro/CodeEditor/panels/OutlinePanel.js.map +1 -1
  57. package/dist/components/pro/CodeEditor/panels/TableOfContentsPanel.js.map +1 -1
  58. package/dist/components/pro/CodeEditor/panels/VariablePanel.js.map +1 -1
  59. package/dist/components/pro/CodeEditor/themes.js +59 -59
  60. package/dist/components/pro/CodeEditor/themes.js.map +1 -1
  61. package/dist/components/pro/DataTable/DataTable.js +49 -48
  62. package/dist/components/pro/DataTable/DataTable.js.map +1 -1
  63. package/dist/components/pro/DataTable/Filters.js +42 -42
  64. package/dist/components/pro/DataTable/Filters.js.map +1 -1
  65. package/dist/components/pro/DataTable/PivotPanel.js.map +1 -1
  66. package/dist/components/pro/DataTable/PivotView.js +35 -32
  67. package/dist/components/pro/DataTable/PivotView.js.map +1 -1
  68. package/dist/components/pro/DataTable/components/BulkActions.js.map +1 -1
  69. package/dist/components/pro/DataTable/components/ColumnSelector.js.map +1 -1
  70. package/dist/components/pro/DataTable/components/FilterBar.js.map +1 -1
  71. package/dist/components/pro/DataTable/components/TableBody.js.map +1 -1
  72. package/dist/components/pro/DataTable/components/TableHeader.js.map +1 -1
  73. package/dist/components/pro/DataTable/components/TablePagination.js.map +1 -1
  74. package/dist/components/pro/DataTable/components/TableToolbar.js.map +1 -1
  75. package/dist/components/pro/DataTable/pivotExtension.js.map +1 -1
  76. package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
  77. package/dist/components/pro/DataTable/tanstack-table.js +37 -37
  78. package/dist/components/pro/DataTable/tanstack-table.js.map +1 -1
  79. package/dist/components/pro/FileExplorer/Breadcrumb.js +53 -53
  80. package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
  81. package/dist/components/pro/FileExplorer/CreateDialog.js.map +1 -1
  82. package/dist/components/pro/FileExplorer/FileExplorer.js.map +1 -1
  83. package/dist/components/pro/FileExplorer/FileIcon.js +22 -22
  84. package/dist/components/pro/FileExplorer/FileIcon.js.map +1 -1
  85. package/dist/components/pro/FileExplorer/GridView.js.map +1 -1
  86. package/dist/components/pro/FileExplorer/ListView.js.map +1 -1
  87. package/dist/components/pro/FileExplorer/Toolbar.js.map +1 -1
  88. package/dist/components/pro/Flow/Flow.js +496 -494
  89. package/dist/components/pro/Flow/Flow.js.map +1 -1
  90. package/dist/components/pro/Flow/FlowCanvas.js +916 -917
  91. package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
  92. package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
  93. package/dist/components/pro/Flow/edges/EdgeRenderer.js +59 -59
  94. package/dist/components/pro/Flow/edges/EdgeRenderer.js.map +1 -1
  95. package/dist/components/pro/Flow/hooks/useClipboard.js.map +1 -1
  96. package/dist/components/pro/Flow/hooks/useDeleteSelection.js.map +1 -1
  97. package/dist/components/pro/Flow/hooks/useEdgeMutations.js.map +1 -1
  98. package/dist/components/pro/Flow/hooks/useLayoutActions.js +9 -11
  99. package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
  100. package/dist/components/pro/Flow/hooks/useLineMutations.js.map +1 -1
  101. package/dist/components/pro/Flow/hooks/useMindMap.js.map +1 -1
  102. package/dist/components/pro/Flow/hooks/useNodeMutations.js.map +1 -1
  103. package/dist/components/pro/Flow/lines/FreehandTool.js +9 -9
  104. package/dist/components/pro/Flow/lines/FreehandTool.js.map +1 -1
  105. package/dist/components/pro/Flow/lines/LineRenderer.js +5 -5
  106. package/dist/components/pro/Flow/lines/LineRenderer.js.map +1 -1
  107. package/dist/components/pro/Flow/nodes/DataNodeView.js +113 -93
  108. package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -1
  109. package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
  110. package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
  111. package/dist/components/pro/Flow/nodes/Model3DView.js +1 -1
  112. package/dist/components/pro/Flow/nodes/Model3DView.js.map +1 -1
  113. package/dist/components/pro/Flow/nodes/NodeRenderer.js +118 -118
  114. package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
  115. package/dist/components/pro/Flow/nodes/dataUtils.js.map +1 -1
  116. package/dist/components/pro/Flow/nodes/shapes.js +1 -3
  117. package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
  118. package/dist/components/pro/Flow/panels/AIPanel.js.map +1 -1
  119. package/dist/components/pro/Flow/panels/Breadcrumb.js.map +1 -1
  120. package/dist/components/pro/Flow/panels/ContextMenu.js.map +1 -1
  121. package/dist/components/pro/Flow/panels/DataInspectorSection.js.map +1 -1
  122. package/dist/components/pro/Flow/panels/ExpandableTextarea.js.map +1 -1
  123. package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
  124. package/dist/components/pro/Flow/panels/FlowToolbar.js +97 -97
  125. package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
  126. package/dist/components/pro/Flow/panels/InspectorPanel.js +57 -57
  127. package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
  128. package/dist/components/pro/Flow/panels/OutlinePanel.js +26 -22
  129. package/dist/components/pro/Flow/panels/OutlinePanel.js.map +1 -1
  130. package/dist/components/pro/Flow/panels/PresentationMode.js +18 -16
  131. package/dist/components/pro/Flow/panels/PresentationMode.js.map +1 -1
  132. package/dist/components/pro/Flow/panels/ProjectTitle.js.map +1 -1
  133. package/dist/components/pro/Flow/panels/ShapePalette.js +109 -104
  134. package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
  135. package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
  136. package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
  137. package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
  138. package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
  139. package/dist/components/pro/RichTextEditor/CommentDialog.js.map +1 -1
  140. package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
  141. package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
  142. package/dist/components/pro/RichTextEditor/ContextMenu.js.map +1 -1
  143. package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
  144. package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
  145. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
  146. package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
  147. package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
  148. package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
  149. package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
  150. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
  151. package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
  152. package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
  153. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
  154. package/dist/contexts/AppContext.js.map +1 -1
  155. package/dist/dishui.css +1 -1
  156. package/dist/hooks/useTableColumns.js +7 -8
  157. package/dist/hooks/useTableColumns.js.map +1 -1
  158. package/dist/index.d.ts +2 -0
  159. package/dist/index.js +227 -221
  160. package/dist/layouts/MainLayout.js +22 -22
  161. package/dist/layouts/MainLayout.js.map +1 -1
  162. package/dist/layouts/Navbar.js.map +1 -1
  163. package/dist/layouts/Sidebar.js +94 -73
  164. package/dist/layouts/Sidebar.js.map +1 -1
  165. package/dist/layouts/headbar/Headbar.js.map +1 -1
  166. package/dist/layouts/headbar/HeadbarLangSwitcher.js.map +1 -1
  167. package/dist/layouts/headbar/HeadbarSearch.js.map +1 -1
  168. package/dist/layouts/headbar/HeadbarThemeSwitcher.js +11 -11
  169. package/dist/layouts/headbar/HeadbarThemeSwitcher.js.map +1 -1
  170. package/dist/layouts/headbar/HeadbarTitle.js.map +1 -1
  171. package/dist/utils/i18n.js +10 -10
  172. package/dist/utils/i18n.js.map +1 -1
  173. package/dist/utils/menu.js.map +1 -1
  174. package/dist/utils/routerBuilder.js +17 -15
  175. package/dist/utils/routerBuilder.js.map +1 -1
  176. package/dist/utils/themes.js.map +1 -1
  177. package/package.json +7 -7
@@ -1,18 +1,18 @@
1
1
  import { resolveThemeColor as u } from "../utils/themeColor.js";
2
- import { drawBorderSides as Q, drawRoundRectBorder as it, hasBorderSideOverrides as U, shapeDrawers as H } from "./shapes.js";
2
+ import { drawBorderSides as Q, drawRoundRectBorder as it, hasBorderSideOverrides as U, shapeDrawers as A } from "./shapes.js";
3
3
  import { createNodeText as st, formatIconLabel as at, normalizeIconLabelPlacement as ot, updateNodeText as rt } from "./NodeText.js";
4
4
  import { createHandleGraphics as lt, getHandlePositions as Z, updateHandleGraphics as ht } from "./NodeHandles.js";
5
5
  import { getFlipScale as nt, getRotationRad as ct } from "./nodeUtils.js";
6
6
  import { getSvgIcon as ft } from "./svgIcons.js";
7
7
  import { getIconTexture as tt, subscribeIconTextureReady as dt } from "./svgIconTexture.js";
8
- import { Container as Y, Graphics as E, Sprite as et, Text as V } from "pixi.js";
9
- function pt(o, t, r, b, p) {
10
- const a = 6 + b / 2, e = t - 6 - b / 2, s = t / 2, l = 6 + p / 2, i = r - 6 - p / 2, c = r / 2;
8
+ import { Container as E, Graphics as V, Sprite as et, Text as X } from "pixi.js";
9
+ function pt(o, t, l, b, p) {
10
+ const a = 6 + b / 2, e = t - 6 - b / 2, s = t / 2, h = 6 + p / 2, i = l - 6 - p / 2, d = l / 2;
11
11
  switch (o) {
12
12
  case "top":
13
13
  return {
14
14
  x: s,
15
- y: l
15
+ y: h
16
16
  };
17
17
  case "bottom":
18
18
  return {
@@ -22,22 +22,22 @@ function pt(o, t, r, b, p) {
22
22
  case "left":
23
23
  return {
24
24
  x: a,
25
- y: c
25
+ y: d
26
26
  };
27
27
  case "right":
28
28
  return {
29
29
  x: e,
30
- y: c
30
+ y: d
31
31
  };
32
32
  case "top-left":
33
33
  return {
34
34
  x: a,
35
- y: l
35
+ y: h
36
36
  };
37
37
  case "top-right":
38
38
  return {
39
39
  x: e,
40
- y: l
40
+ y: h
41
41
  };
42
42
  case "bottom-left":
43
43
  return {
@@ -52,7 +52,7 @@ function pt(o, t, r, b, p) {
52
52
  default:
53
53
  return {
54
54
  x: s,
55
- y: c
55
+ y: d
56
56
  };
57
57
  }
58
58
  }
@@ -66,23 +66,23 @@ var St = class {
66
66
  this._dynamicOffset = (this._dynamicOffset + o * 0.06) % 1e3;
67
67
  }
68
68
  constructor(o) {
69
- this.world = o, this.nodeLayer = new Y({
69
+ this.world = o, this.nodeLayer = new E({
70
70
  label: "nodes",
71
71
  sortableChildren: !0
72
72
  }), this.world.addChild(this.nodeLayer), this._unsubscribeTextureReady = dt(() => this._resync?.());
73
73
  }
74
74
  _resync = null;
75
- sync(o, t, r, b, p) {
75
+ sync(o, t, l, b, p) {
76
76
  const n = /* @__PURE__ */ new Set();
77
- this._resync = () => this.sync(o, t, r, b, p);
77
+ this._resync = () => this.sync(o, t, l, b, p);
78
78
  const a = b ?? (() => {
79
- const e = o.filter((l) => l.type === "animAnchor").sort((l, i) => (l.data.animIndex ?? 0) - (i.data.animIndex ?? 0)), s = /* @__PURE__ */ new Map();
80
- return e.forEach((l, i) => s.set(l.id, i + 1)), s;
79
+ const e = o.filter((h) => h.type === "animAnchor").sort((h, i) => (h.data.animIndex ?? 0) - (i.data.animIndex ?? 0)), s = /* @__PURE__ */ new Map();
80
+ return e.forEach((h, i) => s.set(h.id, i + 1)), s;
81
81
  })();
82
82
  for (const e of o) {
83
83
  n.add(e.id);
84
84
  let s = this.nodes.get(e.id);
85
- s || (s = this._createNode(e), this.nodes.set(e.id, s)), this._updateNode(s, e, t.has(e.id), r === e.id, a.get(e.id), p);
85
+ s || (s = this._createNode(e), this.nodes.set(e.id, s)), this._updateNode(s, e, t.has(e.id), l === e.id, a.get(e.id), p);
86
86
  }
87
87
  for (const [e, s] of this.nodes) n.has(e) || (this.nodeLayer.removeChild(s.container), s.container.destroy({ children: !0 }), this.nodes.delete(e));
88
88
  }
@@ -93,13 +93,13 @@ var St = class {
93
93
  return [...this.nodes.values()];
94
94
  }
95
95
  _createNode(o) {
96
- const t = new Y({ label: `node-${o.id}` });
96
+ const t = new E({ label: `node-${o.id}` });
97
97
  t.eventMode = "static", t.cursor = "pointer";
98
- const r = new Y({ label: "svg-transform" });
99
- t.addChild(r);
100
- const b = new E();
98
+ const l = new E({ label: "svg-transform" });
99
+ t.addChild(l);
100
+ const b = new V();
101
101
  b.label = "sub-canvas-glow", t.addChild(b);
102
- const p = new E();
102
+ const p = new V();
103
103
  p.label = "shape", t.addChild(p);
104
104
  const n = new et();
105
105
  n.label = "svg-icon", n.anchor.set(0.5, 0.5), n.visible = !1, t.addChild(n);
@@ -113,7 +113,7 @@ var St = class {
113
113
  t.addChild(a);
114
114
  const e = new et();
115
115
  e.label = "node-title-icon", e.anchor.set(0.5, 0.5), e.visible = !1, t.addChild(e);
116
- const s = new V({
116
+ const s = new X({
117
117
  text: "",
118
118
  style: {
119
119
  fontFamily: "system-ui, -apple-system, sans-serif",
@@ -123,9 +123,9 @@ var St = class {
123
123
  }
124
124
  });
125
125
  s.label = "node-subtext", s.anchor.set(0.5, 0.5), s.visible = !1, t.addChild(s);
126
- const l = new E();
127
- l.label = "node-tag-bg", l.visible = !1, t.addChild(l);
128
- const i = new V({
126
+ const h = new V();
127
+ h.label = "node-tag-bg", h.visible = !1, t.addChild(h);
128
+ const i = new X({
129
129
  text: "",
130
130
  style: {
131
131
  fontFamily: "system-ui, -apple-system, sans-serif",
@@ -134,7 +134,7 @@ var St = class {
134
134
  }
135
135
  });
136
136
  i.label = "node-tag-text", i.anchor.set(0.5, 0.5), i.visible = !1, t.addChild(i);
137
- const c = Z(o.width, o.height), g = lt(t, c, !1), m = new V({
137
+ const d = Z(o.width, o.height), g = lt(t, d, !1), y = new X({
138
138
  text: "",
139
139
  style: {
140
140
  fontFamily: "system-ui, sans-serif",
@@ -143,166 +143,166 @@ var St = class {
143
143
  fontWeight: "700"
144
144
  }
145
145
  });
146
- return m.label = "anim-badge", m.anchor.set(0.5, 0.5), m.visible = !1, t.addChild(m), this.nodeLayer.addChild(t), {
146
+ return y.label = "anim-badge", y.anchor.set(0.5, 0.5), y.visible = !1, t.addChild(y), this.nodeLayer.addChild(t), {
147
147
  container: t,
148
148
  shape: p,
149
- svgTransform: r,
149
+ svgTransform: l,
150
150
  icon: n,
151
151
  text: a,
152
152
  titleIcon: e,
153
153
  subtext: s,
154
- tagBg: l,
154
+ tagBg: h,
155
155
  tagText: i,
156
- animBadge: m,
156
+ animBadge: y,
157
157
  handles: g,
158
- handleDefs: c,
158
+ handleDefs: d,
159
159
  nodeId: o.id,
160
160
  subCanvasGlow: b
161
161
  };
162
162
  }
163
- _updateNode(o, t, r, b, p, n) {
164
- const { container: a, svgTransform: e, shape: s, icon: l, text: i, titleIcon: c, subtext: g, tagBg: m, tagText: v, animBadge: C, handles: k, subCanvasGlow: z } = o, I = t.type === "shapeSvg", M = ct(t.data), w = nt(t.data);
165
- a.zIndex = t.zIndex ?? 0, I ? (s.parent !== e && e.addChild(s), l.parent !== e && e.addChild(l), k.parent !== e && e.addChild(k), a.position.set(t.position.x, t.position.y), a.rotation = 0, a.scale.set(1, 1), a.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(w.sx, w.sy)) : (s.parent !== a && a.addChildAt(s, Math.min(2, a.children.length)), l.parent !== a && a.addChild(l), k.parent !== a && a.addChild(k), e.rotation = 0, e.scale.set(1, 1), a.position.set(t.position.x, t.position.y), a.rotation = M, a.scale.set(w.sx, w.sy), M !== 0 || w.sx < 0 || w.sy < 0 ? (a.pivot.set(t.width / 2, t.height / 2), a.position.set(t.position.x + t.width / 2, t.position.y + t.height / 2)) : a.pivot.set(0, 0));
166
- const B = t.type === "mediaNode", O = t.type === "animAnchor";
167
- let G = !0;
168
- if (s.clear(), s.alpha = 1, I) this._updateSvgNode(o, t, r);
169
- else if (B) {
170
- l.visible = !1;
171
- const f = 6, h = t.data.fill && t.data.fill !== "transparent" ? u(t.data.fill, "#ffffff") : "#ffffff", d = t.data.borderStyle === "none", y = U(t.data, t.type), x = r ? "#3b82f6" : u(t.data.stroke, "#374151"), S = r ? Math.max(t.data.strokeWidth, 2) : t.data.strokeWidth;
172
- if (H.shapeRoundRect(s, {
163
+ _updateNode(o, t, l, b, p, n) {
164
+ const { container: a, svgTransform: e, shape: s, icon: h, text: i, titleIcon: d, subtext: g, tagBg: y, tagText: x, animBadge: S, handles: k, subCanvasGlow: T } = o, I = t.type === "shapeSvg", M = ct(t.data), w = nt(t.data);
165
+ a.zIndex = t.zIndex ?? 0, I ? (s.parent !== e && e.addChild(s), h.parent !== e && e.addChild(h), k.parent !== e && e.addChild(k), a.position.set(t.position.x, t.position.y), a.rotation = 0, a.scale.set(1, 1), a.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(w.sx, w.sy)) : (s.parent !== a && a.addChildAt(s, Math.min(2, a.children.length)), h.parent !== a && a.addChild(h), k.parent !== a && a.addChild(k), e.rotation = 0, e.scale.set(1, 1), a.position.set(t.position.x, t.position.y), a.rotation = M, a.scale.set(w.sx, w.sy), M !== 0 || w.sx < 0 || w.sy < 0 ? (a.pivot.set(t.width / 2, t.height / 2), a.position.set(t.position.x + t.width / 2, t.position.y + t.height / 2)) : a.pivot.set(0, 0));
166
+ const z = t.type === "mediaNode", O = t.type === "animAnchor";
167
+ let B = !0;
168
+ if (s.clear(), s.alpha = 1, I) this._updateSvgNode(o, t, l);
169
+ else if (z) {
170
+ h.visible = !1;
171
+ const c = 6, r = t.data.fill && t.data.fill !== "transparent" ? u(t.data.fill, "#ffffff") : "#ffffff", f = t.data.borderStyle === "none", m = U(t.data, t.type), v = l ? "#3b82f6" : u(t.data.stroke, "#374151"), C = l ? Math.max(t.data.strokeWidth, 2) : t.data.strokeWidth;
172
+ if (A.shapeRoundRect(s, {
173
173
  width: t.width,
174
174
  height: t.height,
175
- fill: h,
176
- stroke: y ? "transparent" : x,
177
- strokeWidth: S,
178
- borderStyle: r && d ? "solid" : t.data.borderStyle,
175
+ fill: r,
176
+ stroke: m ? "transparent" : v,
177
+ strokeWidth: C,
178
+ borderStyle: l && f ? "solid" : t.data.borderStyle,
179
179
  dashOffset: this._dynamicOffset
180
- }), y) {
181
- const T = u(t.data.stroke, "#374151");
182
- r && s.roundRect(0, 0, t.width, t.height, f).stroke({
180
+ }), m) {
181
+ const R = u(t.data.stroke, "#374151");
182
+ l && s.roundRect(0, 0, t.width, t.height, c).stroke({
183
183
  color: "#3b82f6",
184
184
  width: Math.max(t.data.strokeWidth, 2)
185
- }), Q(s, "mediaNode", t.width, t.height, t.data.borderSides, T, t.data.strokeWidth, d ? void 0 : t.data.borderStyle, this._dynamicOffset);
185
+ }), Q(s, "mediaNode", t.width, t.height, t.data.borderSides, R, t.data.strokeWidth, f ? void 0 : t.data.borderStyle, this._dynamicOffset);
186
186
  }
187
187
  } else if (O) {
188
- l.visible = !1;
189
- const f = "#8b5cf6", h = n?.presentation ?? !1;
190
- G = h ? (n?.presentationAnchorVisible ?? !1) && n?.presentationAnchorId === t.id : n?.showAnchors ?? !0, G && (s.alpha = h ? 0.48 : 0.9, H.shapeRoundRect(s, {
188
+ h.visible = !1;
189
+ const c = "#8b5cf6", r = n?.presentation ?? !1;
190
+ B = r ? (n?.presentationAnchorVisible ?? !1) && n?.presentationAnchorId === t.id : n?.showAnchors ?? !0, B && (s.alpha = r ? 0.48 : 0.9, A.shapeRoundRect(s, {
191
191
  width: t.width,
192
192
  height: t.height,
193
193
  fill: "transparent",
194
- stroke: r && !h ? "#3b82f6" : f,
195
- strokeWidth: r && !h ? 2.5 : 1.5,
194
+ stroke: l && !r ? "#3b82f6" : c,
195
+ strokeWidth: l && !r ? 2.5 : 1.5,
196
196
  borderStyle: "dashed"
197
- }), s.circle(0, 0, h ? 11 : 13).fill({ color: r && !h ? "#3b82f6" : f })), C.text = String(p ?? ""), C.alpha = h ? 0.7 : 1, C.visible = G, C.position.set(0, 0);
197
+ }), s.circle(0, 0, r ? 11 : 13).fill({ color: l && !r ? "#3b82f6" : c })), S.text = String(p ?? ""), S.alpha = r ? 0.7 : 1, S.visible = B, S.position.set(0, 0);
198
198
  } else {
199
- l.visible = !1;
200
- const f = H[t.type] ?? H.shapeRect, h = U(t.data, t.type), d = t.data.borderStyle === "none", y = u(t.data.stroke, "#374151");
201
- if (f(s, {
199
+ h.visible = !1;
200
+ const c = A[t.type] ?? A.shapeRect, r = U(t.data, t.type), f = t.data.borderStyle === "none", m = u(t.data.stroke, "#374151");
201
+ if (c(s, {
202
202
  width: t.width,
203
203
  height: t.height,
204
204
  fill: u(t.data.fill, "#ffffff"),
205
- stroke: h ? "transparent" : r ? "#3b82f6" : y,
206
- strokeWidth: r ? Math.max(t.data.strokeWidth, 2) : t.data.strokeWidth,
207
- borderStyle: r && d ? "solid" : t.data.borderStyle,
205
+ stroke: r ? "transparent" : l ? "#3b82f6" : m,
206
+ strokeWidth: l ? Math.max(t.data.strokeWidth, 2) : t.data.strokeWidth,
207
+ borderStyle: l && f ? "solid" : t.data.borderStyle,
208
208
  dashOffset: this._dynamicOffset
209
- }), h) {
210
- if (r) {
211
- const S = t.type === "shapeRect" ? 0 : Math.min(12, t.width * 0.1, t.height * 0.1);
212
- s.roundRect(0, 0, t.width, t.height, S).stroke({
209
+ }), r) {
210
+ if (l) {
211
+ const C = t.type === "shapeRect" ? 0 : Math.min(12, t.width * 0.1, t.height * 0.1);
212
+ s.roundRect(0, 0, t.width, t.height, C).stroke({
213
213
  color: "#3b82f6",
214
214
  width: Math.max(t.data.strokeWidth, 2)
215
215
  });
216
216
  }
217
- const x = r && d ? "solid" : t.data.borderStyle;
218
- Q(s, t.type, t.width, t.height, t.data.borderSides, y, t.data.strokeWidth, x, this._dynamicOffset);
217
+ const v = l && f ? "solid" : t.data.borderStyle;
218
+ Q(s, t.type, t.width, t.height, t.data.borderSides, m, t.data.strokeWidth, v, this._dynamicOffset);
219
219
  }
220
220
  }
221
- if (O || (C.visible = !1), z.clear(), t.data.childCanvasId) {
222
- const h = t.width + 8, d = t.height + 8, y = 0.5 + 0.3 * Math.sin(this._dynamicOffset * 8e-3);
223
- z.roundRect(-4, -4, h, d, 6), z.stroke({
221
+ if (O || (S.visible = !1), T.clear(), t.data.childCanvasId) {
222
+ const c = t.width + 8, r = t.height + 8, f = 0.5 + 0.3 * Math.sin(this._dynamicOffset * 8e-3);
223
+ T.roundRect(-4, -4, c, r, 6), T.stroke({
224
224
  color: 9133302,
225
225
  width: 2.5,
226
- alpha: y
227
- }), z.roundRect(-6, -6, h + 4, d + 4, 8), z.stroke({
226
+ alpha: f
227
+ }), T.roundRect(-6, -6, c + 4, r + 4, 8), T.stroke({
228
228
  color: 9133302,
229
229
  width: 1,
230
- alpha: y * 0.4
230
+ alpha: f * 0.4
231
231
  });
232
232
  }
233
- const N = ot(t.data.labelPlacement), $ = t.data.labelColor ?? (I ? "theme:base-content" : t.data.color);
233
+ const G = ot(t.data.labelPlacement), Y = t.data.labelColor ?? (I ? "theme:base-content" : t.data.color);
234
234
  rt(i, {
235
- label: B ? "" : I ? at(t.data.label, N) : t.data.label,
236
- color: u($, "#111827"),
235
+ label: z ? "" : I ? at(t.data.label, G) : t.data.label,
236
+ color: u(Y, "#111827"),
237
237
  fontSize: t.data.fontSize,
238
238
  width: t.width,
239
239
  height: t.height
240
- }), i.visible = !B && (!O || G);
241
- const P = !I && !B && (!O || G), j = P ? (t.data.sublabel ?? "").trim() : "", L = j.length > 0, D = P ? (t.data.titleIcon ?? "").trim() : "", X = 6, W = Math.max(8, t.data.titleIconSize ?? Math.round(t.data.fontSize * 1.15)), q = W / 96;
242
- if (D.length > 0) {
243
- const f = ft(D)?.brandColor ?? $, h = tt(D, u(t.data.titleIconColor ?? f, "#111827") || "#111827");
244
- h ? (c.texture = h, c.visible = !0) : c.visible = !1;
245
- } else c.visible = !1;
240
+ }), i.visible = !z && (!O || B);
241
+ const F = !I && !z && (!O || B), $ = F ? (t.data.sublabel ?? "").trim() : "", N = $.length > 0, H = F ? (t.data.titleIcon ?? "").trim() : "", P = 6, W = Math.max(8, t.data.titleIconSize ?? Math.round(t.data.fontSize * 1.15)), j = W / 96;
242
+ if (H.length > 0) {
243
+ const c = ft(H)?.brandColor ?? Y, r = u(t.data.titleIconColor ?? c, "#111827") || "#111827", f = tt(H, r);
244
+ f ? (d.texture = f, d.visible = !0) : d.visible = !1;
245
+ } else d.visible = !1;
246
246
  if (t.type === "shapeCorner") {
247
- c.visible = !1;
248
- const f = Math.min(t.width, t.height) * 0.4;
249
- i.position.set((f + t.width) / 2, (f + t.height) / 2);
247
+ d.visible = !1;
248
+ const c = Math.min(t.width, t.height) * 0.4;
249
+ i.position.set((c + t.width) / 2, (c + t.height) / 2);
250
250
  } else if (I) {
251
- const h = i.width / 2, d = i.height / 2;
252
- N === "top" ? i.position.set(t.width / 2, -4 - d) : N === "bottom" ? i.position.set(t.width / 2, t.height + 4 + d) : N === "left" ? i.position.set(-4 - h, t.height / 2) : N === "right" ? i.position.set(t.width + 4 + h, t.height / 2) : i.position.set(t.width / 2, t.height / 2), i.position.x += t.data.labelOffsetX ?? 0, i.position.y += t.data.labelOffsetY ?? 0;
253
- } else if (!B) {
254
- const h = Math.max(9, t.data.fontSize - 3);
255
- if (L) {
251
+ const r = i.width / 2, f = i.height / 2;
252
+ G === "top" ? i.position.set(t.width / 2, -4 - f) : G === "bottom" ? i.position.set(t.width / 2, t.height + 4 + f) : G === "left" ? i.position.set(-4 - r, t.height / 2) : G === "right" ? i.position.set(t.width + 4 + r, t.height / 2) : i.position.set(t.width / 2, t.height / 2), i.position.x += t.data.labelOffsetX ?? 0, i.position.y += t.data.labelOffsetY ?? 0;
253
+ } else if (!z) {
254
+ const r = Math.max(9, t.data.fontSize - 3);
255
+ if (N) {
256
256
  const _ = g.style;
257
- _.fill = u(t.data.sublabelColor ?? "#94a3b8", "#94a3b8"), _.fontSize = h, g.text = j, g.anchor.set(0.5, 0.5), g.visible = !0, g.rotation = -M, g.scale.set(w.sx, w.sy);
257
+ _.fill = u(t.data.sublabelColor ?? "#94a3b8", "#94a3b8"), _.fontSize = r, g.text = $, g.anchor.set(0.5, 0.5), g.visible = !0, g.rotation = -M, g.scale.set(w.sx, w.sy);
258
258
  }
259
259
  i.anchor.set(0.5, 0.5);
260
- const d = c.visible, y = i.width + (d ? W + X : 0), x = Math.max(i.height, d ? W : 0) + (L ? 3 + g.height : 0), S = Math.max(y, L ? g.width : 0), T = t.data.isGroup || t.type === "flowGroup" || t.type === "geometryGroup", A = pt(t.data.textPlacement ?? (O || T ? "top" : "center"), t.width, t.height, S, x), R = A.x + (t.data.labelOffsetX ?? 0), K = A.y + (t.data.labelOffsetY ?? 0), F = K - x / 2 + i.height / 2;
261
- if (d) {
262
- const _ = R - y / 2;
263
- (t.data.titleIconSide ?? "left") === "right" ? (i.position.set(_ + i.width / 2, F), c.position.set(_ + i.width + X + W / 2, F)) : (c.position.set(_ + W / 2, F), i.position.set(_ + W + X + i.width / 2, F));
264
- } else i.position.set(R, F);
265
- L && g.position.set(R, K + x / 2 - g.height / 2);
260
+ const f = d.visible, m = i.width + (f ? W + P : 0), v = Math.max(i.height, f ? W : 0) + (N ? 3 + g.height : 0), C = Math.max(m, N ? g.width : 0), R = t.data.isGroup || t.type === "flowGroup" || t.type === "geometryGroup", J = pt(t.data.textPlacement ?? (O || R ? "top" : "center"), t.width, t.height, C, v), D = J.x + (t.data.labelOffsetX ?? 0), K = J.y + (t.data.labelOffsetY ?? 0), L = K - v / 2 + i.height / 2;
261
+ if (f) {
262
+ const _ = D - m / 2;
263
+ (t.data.titleIconSide ?? "left") === "right" ? (i.position.set(_ + i.width / 2, L), d.position.set(_ + i.width + P + W / 2, L)) : (d.position.set(_ + W / 2, L), i.position.set(_ + W + P + i.width / 2, L));
264
+ } else i.position.set(D, L);
265
+ N && g.position.set(D, K + v / 2 - g.height / 2);
266
266
  }
267
- L || (g.visible = !1), I ? (i.rotation = 0, i.scale.set(1, 1)) : (i.rotation = -M, i.scale.set(w.sx, w.sy), c.rotation = -M, c.scale.set(q * w.sx, q * w.sy));
268
- const J = P ? (t.data.tag ?? "").trim() : "";
269
- if (J) {
270
- v.text = J, v.visible = !0;
271
- const f = 5, h = 2, d = v.width + f * 2, y = v.height + h * 2, x = 6, S = t.data.tagPlacement ?? "top-right", T = S === "top-left" || S === "bottom-left" ? x : t.width - d - x, A = S === "top-left" || S === "top-right" ? x : t.height - y - x, R = u(t.data.tagColor ?? t.data.stroke, "#334155");
272
- m.clear(), m.roundRect(T, A, d, y, 3).fill({
267
+ N || (g.visible = !1), I ? (i.rotation = 0, i.scale.set(1, 1)) : (i.rotation = -M, i.scale.set(w.sx, w.sy), d.rotation = -M, d.scale.set(j * w.sx, j * w.sy));
268
+ const q = F ? (t.data.tag ?? "").trim() : "";
269
+ if (q) {
270
+ x.text = q, x.visible = !0;
271
+ const c = x.width + 10, r = x.height + 4, f = 6, m = t.data.tagPlacement ?? "top-right", v = m === "top-left" || m === "bottom-left" ? f : t.width - c - f, C = m === "top-left" || m === "top-right" ? f : t.height - r - f, R = u(t.data.tagColor ?? t.data.stroke, "#334155");
272
+ y.clear(), y.roundRect(v, C, c, r, 3).fill({
273
273
  color: R,
274
274
  alpha: 0.18
275
275
  }).stroke({
276
276
  color: R,
277
277
  width: 1,
278
278
  alpha: 0.55
279
- }), m.visible = !0, v.style.fill = R, v.position.set(T + d / 2, A + y / 2), v.rotation = 0, v.scale.set(1, 1);
279
+ }), y.visible = !0, x.style.fill = R, x.position.set(v + c / 2, C + r / 2), x.rotation = 0, x.scale.set(1, 1);
280
280
  } else
281
- m.visible = !1, v.visible = !1;
282
- if (k.visible = (b || r) && !(O && n?.presentation), k.visible) {
283
- const f = Z(t.width, t.height);
284
- o.handleDefs = f, ht(k, f);
281
+ y.visible = !1, x.visible = !1;
282
+ if (k.visible = (b || l) && !(O && n?.presentation), k.visible) {
283
+ const c = Z(t.width, t.height);
284
+ o.handleDefs = c, ht(k, c);
285
285
  }
286
286
  }
287
- _updateSvgNode(o, t, r) {
288
- const { shape: b, icon: p } = o, { width: n, height: a, data: e } = t, s = e.iconBox ?? !1, l = e.borderStyle ?? (s ? "solid" : "none"), i = l === "none", c = Math.min(8, n * 0.12, a * 0.12);
289
- e.fill && e.fill !== "transparent" && (s || !i) && b.roundRect(0, 0, n, a, c).fill({ color: u(e.fill, "#ffffff") }), !i && e.stroke && e.stroke !== "transparent" && e.strokeWidth > 0 && it(b, {
287
+ _updateSvgNode(o, t, l) {
288
+ const { shape: b, icon: p } = o, { width: n, height: a, data: e } = t, s = e.iconBox ?? !1, h = e.borderStyle ?? (s ? "solid" : "none"), i = h === "none", d = Math.min(8, n * 0.12, a * 0.12);
289
+ e.fill && e.fill !== "transparent" && (s || !i) && b.roundRect(0, 0, n, a, d).fill({ color: u(e.fill, "#ffffff") }), !i && e.stroke && e.stroke !== "transparent" && e.strokeWidth > 0 && it(b, {
290
290
  width: n,
291
291
  height: a,
292
292
  fill: "transparent",
293
293
  stroke: u(e.stroke, "#374151"),
294
294
  strokeWidth: e.strokeWidth,
295
- borderStyle: l,
295
+ borderStyle: h,
296
296
  dashOffset: this._dynamicOffset
297
- }, c), r && b.roundRect(0, 0, n, a, c).stroke({
297
+ }, d), l && b.roundRect(0, 0, n, a, d).stroke({
298
298
  color: "#3b82f6",
299
299
  width: Math.max(e.strokeWidth, 2)
300
300
  });
301
- const g = u(e.color, "#334155") || "#334155", m = tt(e.svgId ?? "", g);
302
- if (m) {
303
- p.texture = m, p.visible = !0;
304
- const v = s ? Math.min(n, a) * 0.18 : 2, C = Math.max(4, Math.min(n, a) - v * 2);
305
- p.width = C, p.height = C, p.position.set(n / 2, a / 2);
301
+ const g = u(e.color, "#334155") || "#334155", y = tt(e.svgId ?? "", g);
302
+ if (y) {
303
+ p.texture = y, p.visible = !0;
304
+ const x = s ? Math.min(n, a) * 0.18 : 2, S = Math.max(4, Math.min(n, a) - x * 2);
305
+ p.width = S, p.height = S, p.position.set(n / 2, a / 2);
306
306
  } else p.visible = !1;
307
307
  }
308
308
  destroy() {
@@ -1 +1 @@
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, hasBorderSideOverrides, drawBorderSides, 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, ICON_TEXTURE_SIZE } from './svgIconTexture';\nimport { getSvgIcon } from './svgIcons';\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 registry glyph rendered beside the title text (left/right). */\n titleIcon: Sprite;\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 glyph beside the title (lazy-rasterized registry texture).\n const titleIcon = new Sprite();\n titleIcon.label = 'node-title-icon';\n titleIcon.anchor.set(0.5, 0.5);\n titleIcon.visible = false;\n container.addChild(titleIcon);\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, titleIcon, 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, titleIcon, 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 perSideBorders = hasBorderSideOverrides(node.data, node.type);\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: perSideBorders ? 'transparent' : strokeColor,\n strokeWidth: strokeW,\n borderStyle: selected && borderHidden ? 'solid' : node.data.borderStyle,\n dashOffset: this._dynamicOffset,\n });\n if (perSideBorders) {\n // Independent sides replace the full outline; the selection ring is\n // drawn separately so selection stays visible.\n const stroke = resolveThemeColor(node.data.stroke, '#374151');\n if (selected) {\n shape.roundRect(0, 0, node.width, node.height, r).stroke({ color: '#3b82f6', width: Math.max(node.data.strokeWidth, 2) });\n }\n drawBorderSides(shape, 'mediaNode', node.width, node.height, node.data.borderSides, stroke, node.data.strokeWidth, borderHidden ? undefined : node.data.borderStyle, 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 // Independent per-side borders (top/right/bottom/left) replace the full\n // outline for shapes with four well-defined sides; the drawer then only\n // fills and the sides are stroked separately below.\n const perSideBorders = hasBorderSideOverrides(node.data, node.type);\n const borderHidden = node.data.borderStyle === 'none';\n const baseStroke = resolveThemeColor(node.data.stroke, '#374151');\n const opts: ShapeDrawOptions = {\n width: node.width,\n height: node.height,\n fill: resolveThemeColor(node.data.fill, '#ffffff'),\n stroke: perSideBorders ? 'transparent' : (selected ? '#3b82f6' : baseStroke),\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 if (perSideBorders) {\n if (selected) {\n const r = node.type === 'shapeRect' ? 0 : Math.min(12, node.width * 0.1, node.height * 0.1);\n shape.roundRect(0, 0, node.width, node.height, r).stroke({ color: '#3b82f6', width: Math.max(node.data.strokeWidth, 2) });\n }\n const style = (selected && borderHidden) ? 'solid' : node.data.borderStyle;\n drawBorderSides(shape, node.type, node.width, node.height, node.data.borderSides, baseStroke, node.data.strokeWidth, style, this._dynamicOffset);\n }\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 // Title icon: optional registry glyph beside the title text. Ordinary\n // shapes, group frames and (visible) anchors only — SVG stamps already are\n // an icon, and media nodes render their own overlay.\n const titleIconId = showExtras ? (node.data.titleIcon ?? '').trim() : '';\n const titleIconGap = 6;\n const titleIconSize = Math.max(8, node.data.titleIconSize ?? Math.round(node.data.fontSize * 1.15));\n const titleIconScale = titleIconSize / ICON_TEXTURE_SIZE;\n const hasTitleIcon = titleIconId.length > 0;\n if (hasTitleIcon) {\n // Default tint keeps each icon's own identity: brand icons (languages /\n // frameworks) use their authentic brandColor, everything else follows the\n // title color (a theme token, so it tracks theme switches). An explicit\n // `titleIconColor` always wins.\n const fallbackTint = getSvgIcon(titleIconId)?.brandColor ?? labelColor;\n const tint = resolveThemeColor(node.data.titleIconColor ?? fallbackTint, '#111827') || '#111827';\n const tex = getIconTexture(titleIconId, tint);\n if (tex) {\n titleIcon.texture = tex;\n titleIcon.visible = true;\n } else {\n titleIcon.visible = false;\n }\n } else {\n titleIcon.visible = false;\n }\n\n if (node.type === 'shapeCorner') {\n titleIcon.visible = false;\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 // Title + optional icon form a horizontally centered group; a sublabel\n // (when present) stays centered under the whole block.\n const iconInBlock = titleIcon.visible;\n const titleGroupW = text.width + (iconInBlock ? titleIconSize + titleIconGap : 0);\n const blockH = Math.max(text.height, iconInBlock ? titleIconSize : 0) + (hasSub ? gap + subtext.height : 0);\n const blockW = Math.max(titleGroupW, 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 const titleCy = by - blockH / 2 + text.height / 2;\n if (iconInBlock) {\n const groupLeft = bx - titleGroupW / 2;\n if ((node.data.titleIconSide ?? 'left') === 'right') {\n text.position.set(groupLeft + text.width / 2, titleCy);\n titleIcon.position.set(groupLeft + text.width + titleIconGap + titleIconSize / 2, titleCy);\n } else {\n titleIcon.position.set(groupLeft + titleIconSize / 2, titleCy);\n text.position.set(groupLeft + titleIconSize + titleIconGap + text.width / 2, titleCy);\n }\n } else {\n text.position.set(bx, titleCy);\n }\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 // Keep the glyph upright and mirrored with the title, like the text.\n // Scale (not width/height — those are scale setters in disguise and the\n // write here would clobber them) is derived from the texture's natural\n // raster size so `titleIconSize` stays authoritative.\n titleIcon.rotation = -rad;\n titleIcon.scale.set(titleIconScale * flip.sx, titleIconScale * 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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"}
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, hasBorderSideOverrides, drawBorderSides, 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, ICON_TEXTURE_SIZE } from './svgIconTexture';\nimport { getSvgIcon } from './svgIcons';\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 registry glyph rendered beside the title text (left/right). */\n titleIcon: Sprite;\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 glyph beside the title (lazy-rasterized registry texture).\n const titleIcon = new Sprite();\n titleIcon.label = 'node-title-icon';\n titleIcon.anchor.set(0.5, 0.5);\n titleIcon.visible = false;\n container.addChild(titleIcon);\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, titleIcon, 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, titleIcon, 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 perSideBorders = hasBorderSideOverrides(node.data, node.type);\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: perSideBorders ? 'transparent' : strokeColor,\n strokeWidth: strokeW,\n borderStyle: selected && borderHidden ? 'solid' : node.data.borderStyle,\n dashOffset: this._dynamicOffset,\n });\n if (perSideBorders) {\n // Independent sides replace the full outline; the selection ring is\n // drawn separately so selection stays visible.\n const stroke = resolveThemeColor(node.data.stroke, '#374151');\n if (selected) {\n shape.roundRect(0, 0, node.width, node.height, r).stroke({ color: '#3b82f6', width: Math.max(node.data.strokeWidth, 2) });\n }\n drawBorderSides(shape, 'mediaNode', node.width, node.height, node.data.borderSides, stroke, node.data.strokeWidth, borderHidden ? undefined : node.data.borderStyle, 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 // Independent per-side borders (top/right/bottom/left) replace the full\n // outline for shapes with four well-defined sides; the drawer then only\n // fills and the sides are stroked separately below.\n const perSideBorders = hasBorderSideOverrides(node.data, node.type);\n const borderHidden = node.data.borderStyle === 'none';\n const baseStroke = resolveThemeColor(node.data.stroke, '#374151');\n const opts: ShapeDrawOptions = {\n width: node.width,\n height: node.height,\n fill: resolveThemeColor(node.data.fill, '#ffffff'),\n stroke: perSideBorders ? 'transparent' : (selected ? '#3b82f6' : baseStroke),\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 if (perSideBorders) {\n if (selected) {\n const r = node.type === 'shapeRect' ? 0 : Math.min(12, node.width * 0.1, node.height * 0.1);\n shape.roundRect(0, 0, node.width, node.height, r).stroke({ color: '#3b82f6', width: Math.max(node.data.strokeWidth, 2) });\n }\n const style = (selected && borderHidden) ? 'solid' : node.data.borderStyle;\n drawBorderSides(shape, node.type, node.width, node.height, node.data.borderSides, baseStroke, node.data.strokeWidth, style, this._dynamicOffset);\n }\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 // Title icon: optional registry glyph beside the title text. Ordinary\n // shapes, group frames and (visible) anchors only — SVG stamps already are\n // an icon, and media nodes render their own overlay.\n const titleIconId = showExtras ? (node.data.titleIcon ?? '').trim() : '';\n const titleIconGap = 6;\n const titleIconSize = Math.max(8, node.data.titleIconSize ?? Math.round(node.data.fontSize * 1.15));\n const titleIconScale = titleIconSize / ICON_TEXTURE_SIZE;\n const hasTitleIcon = titleIconId.length > 0;\n if (hasTitleIcon) {\n // Default tint keeps each icon's own identity: brand icons (languages /\n // frameworks) use their authentic brandColor, everything else follows the\n // title color (a theme token, so it tracks theme switches). An explicit\n // `titleIconColor` always wins.\n const fallbackTint = getSvgIcon(titleIconId)?.brandColor ?? labelColor;\n const tint = resolveThemeColor(node.data.titleIconColor ?? fallbackTint, '#111827') || '#111827';\n const tex = getIconTexture(titleIconId, tint);\n if (tex) {\n titleIcon.texture = tex;\n titleIcon.visible = true;\n } else {\n titleIcon.visible = false;\n }\n } else {\n titleIcon.visible = false;\n }\n\n if (node.type === 'shapeCorner') {\n titleIcon.visible = false;\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 // Title + optional icon form a horizontally centered group; a sublabel\n // (when present) stays centered under the whole block.\n const iconInBlock = titleIcon.visible;\n const titleGroupW = text.width + (iconInBlock ? titleIconSize + titleIconGap : 0);\n const blockH = Math.max(text.height, iconInBlock ? titleIconSize : 0) + (hasSub ? gap + subtext.height : 0);\n const blockW = Math.max(titleGroupW, 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 const titleCy = by - blockH / 2 + text.height / 2;\n if (iconInBlock) {\n const groupLeft = bx - titleGroupW / 2;\n if ((node.data.titleIconSide ?? 'left') === 'right') {\n text.position.set(groupLeft + text.width / 2, titleCy);\n titleIcon.position.set(groupLeft + text.width + titleIconGap + titleIconSize / 2, titleCy);\n } else {\n titleIcon.position.set(groupLeft + titleIconSize / 2, titleCy);\n text.position.set(groupLeft + titleIconSize + titleIconGap + text.width / 2, titleCy);\n }\n } else {\n text.position.set(bx, titleCy);\n }\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 // Keep the glyph upright and mirrored with the title, like the text.\n // Scale (not width/height — those are scale setters in disguise and the\n // write here would clobber them) is derived from the texture's natural\n // raster size so `titleIconSize` stays authoritative.\n titleIcon.rotation = -rad;\n titleIcon.scale.set(titleIconScale * flip.sx, titleIconScale * 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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"}