@node-edit-utils/core 2.3.1 → 2.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/node-tools/select/helpers/isInsideViewport.d.ts +1 -0
- package/dist/lib/viewport/constants.d.ts +2 -2
- package/dist/lib/viewport/label/getViewportLabelsOverlay.d.ts +1 -0
- package/dist/lib/viewport/label/helpers/getLabelPosition.d.ts +4 -0
- package/dist/lib/viewport/label/helpers/getTransformValues.d.ts +4 -0
- package/dist/lib/viewport/label/helpers/getZoomValue.d.ts +1 -0
- package/dist/lib/viewport/label/index.d.ts +4 -0
- package/dist/lib/viewport/label/isViewportLabelDragging.d.ts +2 -0
- package/dist/lib/viewport/label/refreshViewportLabels.d.ts +1 -0
- package/dist/lib/viewport/label/setupViewportLabelDrag.d.ts +1 -0
- package/dist/node-edit-utils.cjs.js +273 -32
- package/dist/node-edit-utils.esm.js +273 -32
- package/dist/node-edit-utils.umd.js +273 -32
- package/dist/node-edit-utils.umd.min.js +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/lib/canvas/createCanvasObserver.ts +14 -0
- package/src/lib/node-tools/createNodeTools.ts +12 -5
- package/src/lib/node-tools/select/helpers/isInsideViewport.ts +19 -0
- package/src/lib/node-tools/select/selectNode.ts +13 -1
- package/src/lib/node-tools/text/events/setupMutationObserver.ts +1 -0
- package/src/lib/styles/styles.css +48 -1
- package/src/lib/viewport/constants.ts +2 -2
- package/src/lib/viewport/createViewport.ts +18 -0
- package/src/lib/viewport/label/getViewportLabelsOverlay.ts +33 -0
- package/src/lib/viewport/label/helpers/getLabelPosition.ts +8 -0
- package/src/lib/viewport/label/helpers/getTransformValues.ts +8 -0
- package/src/lib/viewport/label/helpers/getZoomValue.ts +4 -0
- package/src/lib/viewport/label/index.ts +4 -0
- package/src/lib/viewport/label/isViewportLabelDragging.ts +9 -0
- package/src/lib/viewport/label/refreshViewportLabels.ts +69 -0
- package/src/lib/viewport/label/setupViewportLabelDrag.ts +98 -0
|
@@ -1,8 +1,216 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markup Canvas
|
|
3
3
|
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
-
* @version 2.3.
|
|
4
|
+
* @version 2.3.2
|
|
5
5
|
*/
|
|
6
|
+
function getScreenBounds(element) {
|
|
7
|
+
const rect = element.getBoundingClientRect();
|
|
8
|
+
return {
|
|
9
|
+
top: rect.top,
|
|
10
|
+
left: rect.left,
|
|
11
|
+
width: rect.width,
|
|
12
|
+
height: rect.height,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const getCanvasContainer = () => {
|
|
17
|
+
return document.querySelector(".canvas-container");
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const getViewportLabelsOverlay = () => {
|
|
21
|
+
const canvasContainer = getCanvasContainer();
|
|
22
|
+
const container = canvasContainer || document.body;
|
|
23
|
+
// Check if overlay already exists
|
|
24
|
+
let overlay = container.querySelector(".viewport-labels-overlay");
|
|
25
|
+
if (!overlay) {
|
|
26
|
+
// Create new SVG overlay
|
|
27
|
+
overlay = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
28
|
+
overlay.classList.add("viewport-labels-overlay");
|
|
29
|
+
// Set fixed positioning
|
|
30
|
+
overlay.style.position = "absolute";
|
|
31
|
+
overlay.style.top = "0";
|
|
32
|
+
overlay.style.left = "0";
|
|
33
|
+
overlay.style.width = "100vw";
|
|
34
|
+
overlay.style.height = "100vh";
|
|
35
|
+
overlay.style.pointerEvents = "none";
|
|
36
|
+
overlay.style.zIndex = "500";
|
|
37
|
+
const viewportWidth = document.documentElement.clientWidth || window.innerWidth;
|
|
38
|
+
const viewportHeight = document.documentElement.clientHeight || window.innerHeight;
|
|
39
|
+
overlay.setAttribute("width", viewportWidth.toString());
|
|
40
|
+
overlay.setAttribute("height", viewportHeight.toString());
|
|
41
|
+
container.appendChild(overlay);
|
|
42
|
+
}
|
|
43
|
+
return overlay;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Global flag to prevent refreshViewportLabels during drag
|
|
47
|
+
let globalIsDragging = false;
|
|
48
|
+
const isViewportLabelDragging = () => globalIsDragging;
|
|
49
|
+
const setViewportLabelDragging = (isDragging) => {
|
|
50
|
+
globalIsDragging = isDragging;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
function sendPostMessage(action, data) {
|
|
54
|
+
window.parent.postMessage({
|
|
55
|
+
source: "node-edit-utils",
|
|
56
|
+
action,
|
|
57
|
+
data,
|
|
58
|
+
timestamp: Date.now(),
|
|
59
|
+
}, "*");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const getLabelPosition = (labelGroup) => {
|
|
63
|
+
const transform = labelGroup.getAttribute("transform");
|
|
64
|
+
const match = transform?.match(/translate\((-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)\)/);
|
|
65
|
+
if (match) {
|
|
66
|
+
return { x: parseFloat(match[1]), y: parseFloat(match[2]) };
|
|
67
|
+
}
|
|
68
|
+
return { x: 0, y: 0 };
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const getTransformValues = (element) => {
|
|
72
|
+
const style = element.style.transform;
|
|
73
|
+
const match = style.match(/translate3d\((-?\d+(?:\.\d+)?)px,\s*(-?\d+(?:\.\d+)?)px,\s*(-?\d+(?:\.\d+)?)px\)/);
|
|
74
|
+
if (match) {
|
|
75
|
+
return { x: parseFloat(match[1]), y: parseFloat(match[2]) };
|
|
76
|
+
}
|
|
77
|
+
return { x: 0, y: 0 };
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const getZoomValue = () => {
|
|
81
|
+
const zoomValue = getComputedStyle(document.body).getPropertyValue("--zoom").trim();
|
|
82
|
+
return zoomValue ? parseFloat(zoomValue) : 1;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const setupViewportLabelDrag = (labelElement, viewportElement, viewportName) => {
|
|
86
|
+
let isDragging = false;
|
|
87
|
+
let startX = 0;
|
|
88
|
+
let startY = 0;
|
|
89
|
+
let initialTransform = { x: 0, y: 0 };
|
|
90
|
+
let initialLabelPosition = { x: 0, y: 0 };
|
|
91
|
+
// Get the parent group element that contains the label
|
|
92
|
+
const labelGroup = labelElement.parentElement;
|
|
93
|
+
const startDrag = (event) => {
|
|
94
|
+
event.preventDefault();
|
|
95
|
+
event.stopPropagation();
|
|
96
|
+
isDragging = true;
|
|
97
|
+
setViewportLabelDragging(true);
|
|
98
|
+
startX = event.clientX;
|
|
99
|
+
startY = event.clientY;
|
|
100
|
+
initialTransform = getTransformValues(viewportElement);
|
|
101
|
+
initialLabelPosition = getLabelPosition(labelGroup);
|
|
102
|
+
};
|
|
103
|
+
const handleDrag = (event) => {
|
|
104
|
+
if (!isDragging)
|
|
105
|
+
return;
|
|
106
|
+
const zoom = getZoomValue();
|
|
107
|
+
// Calculate mouse delta
|
|
108
|
+
const rawDeltaX = event.clientX - startX;
|
|
109
|
+
const rawDeltaY = event.clientY - startY;
|
|
110
|
+
// Adjust delta for zoom level
|
|
111
|
+
const deltaX = rawDeltaX / zoom;
|
|
112
|
+
const deltaY = rawDeltaY / zoom;
|
|
113
|
+
const newX = initialTransform.x + deltaX;
|
|
114
|
+
const newY = initialTransform.y + deltaY;
|
|
115
|
+
// Update label position with raw delta (labels are in screen space)
|
|
116
|
+
const newLabelX = initialLabelPosition.x + rawDeltaX;
|
|
117
|
+
const newLabelY = initialLabelPosition.y + rawDeltaY;
|
|
118
|
+
labelGroup.setAttribute("transform", `translate(${newLabelX}, ${newLabelY})`);
|
|
119
|
+
// Update viewport position with zoom-adjusted delta
|
|
120
|
+
viewportElement.style.transform = `translate3d(${newX}px, ${newY}px, 0)`;
|
|
121
|
+
};
|
|
122
|
+
const stopDrag = (event) => {
|
|
123
|
+
if (!isDragging)
|
|
124
|
+
return;
|
|
125
|
+
event.preventDefault();
|
|
126
|
+
event.stopPropagation();
|
|
127
|
+
isDragging = false;
|
|
128
|
+
setViewportLabelDragging(false);
|
|
129
|
+
const finalTransform = getTransformValues(viewportElement);
|
|
130
|
+
// Trigger refresh after drag completes to update highlight frame and labels
|
|
131
|
+
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
132
|
+
const nodeTools = window.nodeTools;
|
|
133
|
+
if (nodeTools?.refreshHighlightFrame) {
|
|
134
|
+
nodeTools.refreshHighlightFrame();
|
|
135
|
+
}
|
|
136
|
+
// Notify parent about the new position
|
|
137
|
+
sendPostMessage("viewport-position-changed", {
|
|
138
|
+
viewportName,
|
|
139
|
+
x: finalTransform.x,
|
|
140
|
+
y: finalTransform.y,
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
const cancelDrag = () => {
|
|
144
|
+
isDragging = false;
|
|
145
|
+
setViewportLabelDragging(false);
|
|
146
|
+
};
|
|
147
|
+
// Attach event listeners
|
|
148
|
+
labelElement.addEventListener("mousedown", startDrag);
|
|
149
|
+
document.addEventListener("mousemove", handleDrag);
|
|
150
|
+
document.addEventListener("mouseup", stopDrag);
|
|
151
|
+
window.addEventListener("blur", cancelDrag);
|
|
152
|
+
// Return cleanup function
|
|
153
|
+
return () => {
|
|
154
|
+
labelElement.removeEventListener("mousedown", startDrag);
|
|
155
|
+
document.removeEventListener("mousemove", handleDrag);
|
|
156
|
+
document.removeEventListener("mouseup", stopDrag);
|
|
157
|
+
window.removeEventListener("blur", cancelDrag);
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// Store cleanup functions for drag listeners
|
|
162
|
+
const dragCleanupFunctions = new Map();
|
|
163
|
+
const refreshViewportLabels = () => {
|
|
164
|
+
// Skip refresh if a viewport label is being dragged
|
|
165
|
+
if (isViewportLabelDragging()) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const overlay = getViewportLabelsOverlay();
|
|
169
|
+
// Update SVG dimensions to match current viewport
|
|
170
|
+
const viewportWidth = document.documentElement.clientWidth || window.innerWidth;
|
|
171
|
+
const viewportHeight = document.documentElement.clientHeight || window.innerHeight;
|
|
172
|
+
overlay.setAttribute("width", viewportWidth.toString());
|
|
173
|
+
overlay.setAttribute("height", viewportHeight.toString());
|
|
174
|
+
// Find all viewports with names
|
|
175
|
+
const viewports = document.querySelectorAll(".viewport[data-viewport-name]");
|
|
176
|
+
// Clean up existing drag listeners
|
|
177
|
+
dragCleanupFunctions.forEach((cleanup) => {
|
|
178
|
+
cleanup();
|
|
179
|
+
});
|
|
180
|
+
dragCleanupFunctions.clear();
|
|
181
|
+
// Remove existing label groups
|
|
182
|
+
const existingGroups = overlay.querySelectorAll(".viewport-label-group");
|
|
183
|
+
existingGroups.forEach((group) => {
|
|
184
|
+
group.remove();
|
|
185
|
+
});
|
|
186
|
+
// Create/update labels for each viewport
|
|
187
|
+
viewports.forEach((viewport) => {
|
|
188
|
+
const viewportElement = viewport;
|
|
189
|
+
const viewportName = viewportElement.getAttribute("data-viewport-name");
|
|
190
|
+
if (!viewportName)
|
|
191
|
+
return;
|
|
192
|
+
const bounds = getScreenBounds(viewportElement);
|
|
193
|
+
// Create group for this viewport label
|
|
194
|
+
const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
195
|
+
group.classList.add("viewport-label-group");
|
|
196
|
+
group.setAttribute("data-viewport-name", viewportName);
|
|
197
|
+
group.setAttribute("transform", `translate(${bounds.left}, ${bounds.top})`);
|
|
198
|
+
// Create text element
|
|
199
|
+
const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
|
200
|
+
text.classList.add("viewport-label-text");
|
|
201
|
+
text.setAttribute("x", "0");
|
|
202
|
+
text.setAttribute("y", "-8");
|
|
203
|
+
text.setAttribute("vector-effect", "non-scaling-stroke");
|
|
204
|
+
text.setAttribute("pointer-events", "auto");
|
|
205
|
+
text.textContent = viewportName;
|
|
206
|
+
group.appendChild(text);
|
|
207
|
+
overlay.appendChild(group);
|
|
208
|
+
// Setup drag functionality for this label
|
|
209
|
+
const cleanup = setupViewportLabelDrag(text, viewportElement, viewportName);
|
|
210
|
+
dragCleanupFunctions.set(viewportName, cleanup);
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
|
|
6
214
|
const getCanvasWindowValue = (path, canvasName = "canvas") => {
|
|
7
215
|
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
8
216
|
const canvas = window[canvasName];
|
|
@@ -32,6 +240,8 @@ function createCanvasObserver(canvasName = "canvas") {
|
|
|
32
240
|
if (nodeTools?.refreshHighlightFrame) {
|
|
33
241
|
nodeTools.refreshHighlightFrame();
|
|
34
242
|
}
|
|
243
|
+
// Refresh viewport labels
|
|
244
|
+
refreshViewportLabels();
|
|
35
245
|
});
|
|
36
246
|
observer.observe(transformLayer, {
|
|
37
247
|
attributes: true,
|
|
@@ -39,8 +249,16 @@ function createCanvasObserver(canvasName = "canvas") {
|
|
|
39
249
|
subtree: true,
|
|
40
250
|
childList: true,
|
|
41
251
|
});
|
|
252
|
+
// Handle window resize for viewport labels
|
|
253
|
+
const handleResize = () => {
|
|
254
|
+
refreshViewportLabels();
|
|
255
|
+
};
|
|
256
|
+
window.addEventListener("resize", handleResize);
|
|
257
|
+
// Initial refresh of viewport labels
|
|
258
|
+
refreshViewportLabels();
|
|
42
259
|
function disconnect() {
|
|
43
260
|
observer.disconnect();
|
|
261
|
+
window.removeEventListener("resize", handleResize);
|
|
44
262
|
}
|
|
45
263
|
return {
|
|
46
264
|
disconnect,
|
|
@@ -55,15 +273,6 @@ const connectResizeObserver = (element, handler) => {
|
|
|
55
273
|
return resizeObserver;
|
|
56
274
|
};
|
|
57
275
|
|
|
58
|
-
function sendPostMessage(action, data) {
|
|
59
|
-
window.parent.postMessage({
|
|
60
|
-
source: "node-edit-utils",
|
|
61
|
-
action,
|
|
62
|
-
data,
|
|
63
|
-
timestamp: Date.now(),
|
|
64
|
-
}, "*");
|
|
65
|
-
}
|
|
66
|
-
|
|
67
276
|
const bindToWindow = (key, value) => {
|
|
68
277
|
if (typeof window !== "undefined") {
|
|
69
278
|
// biome-ignore lint/suspicious/noExplicitAny: global window extension requires flexibility
|
|
@@ -91,10 +300,6 @@ const processPostMessage = (event, onNodeSelected) => {
|
|
|
91
300
|
}
|
|
92
301
|
};
|
|
93
302
|
|
|
94
|
-
const getCanvasContainer = () => {
|
|
95
|
-
return document.querySelector(".canvas-container");
|
|
96
|
-
};
|
|
97
|
-
|
|
98
303
|
const clearHighlightFrame = () => {
|
|
99
304
|
const canvasContainer = getCanvasContainer();
|
|
100
305
|
const container = canvasContainer || document.body;
|
|
@@ -146,6 +351,21 @@ const isInsideComponent = (element) => {
|
|
|
146
351
|
return false;
|
|
147
352
|
};
|
|
148
353
|
|
|
354
|
+
const isInsideViewport = (element) => {
|
|
355
|
+
let current = element;
|
|
356
|
+
while (current) {
|
|
357
|
+
if (current.classList.contains("viewport")) {
|
|
358
|
+
return true;
|
|
359
|
+
}
|
|
360
|
+
// Stop at node-provider to avoid checking beyond the editable area
|
|
361
|
+
if (current.getAttribute("data-role") === "node-provider") {
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
current = current.parentElement;
|
|
365
|
+
}
|
|
366
|
+
return false;
|
|
367
|
+
};
|
|
368
|
+
|
|
149
369
|
const targetSameCandidates = (cache, current) => cache.length === current.length && cache.every((el, i) => el === current[i]);
|
|
150
370
|
|
|
151
371
|
let candidateCache = [];
|
|
@@ -158,7 +378,16 @@ const selectNode = (event, nodeProvider, text) => {
|
|
|
158
378
|
const clickThrough = event.metaKey || event.ctrlKey;
|
|
159
379
|
const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()) &&
|
|
160
380
|
!element.classList.contains("select-none") &&
|
|
161
|
-
!
|
|
381
|
+
!element.classList.contains("content-layer") &&
|
|
382
|
+
!element.classList.contains("resize-handle") &&
|
|
383
|
+
!element.classList.contains("resize-presets") &&
|
|
384
|
+
!isInsideComponent(element) &&
|
|
385
|
+
isInsideViewport(element));
|
|
386
|
+
console.log("candidates", candidates);
|
|
387
|
+
if (candidates.length === 0) {
|
|
388
|
+
lastSelectedNode = null;
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
162
391
|
const editableNode = text.getEditableNode();
|
|
163
392
|
if (editableNode && candidates.includes(editableNode)) {
|
|
164
393
|
selectedNode = editableNode;
|
|
@@ -263,16 +492,6 @@ const createCornerHandles = (group, width, height, isInstance = false, isTextEdi
|
|
|
263
492
|
createCornerHandle(group, 0, height, "handle-bottom-left", isInstance, isTextEdit);
|
|
264
493
|
};
|
|
265
494
|
|
|
266
|
-
function getScreenBounds(element) {
|
|
267
|
-
const rect = element.getBoundingClientRect();
|
|
268
|
-
return {
|
|
269
|
-
top: rect.top,
|
|
270
|
-
left: rect.left,
|
|
271
|
-
width: rect.width,
|
|
272
|
-
height: rect.height,
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
|
|
276
495
|
const getComponentColor$1 = () => {
|
|
277
496
|
return getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim() || "oklch(65.6% 0.241 354.308)";
|
|
278
497
|
};
|
|
@@ -705,6 +924,7 @@ const setupMutationObserver = (node, nodeProvider, canvasName = "canvas") => {
|
|
|
705
924
|
// Accumulate mutations instead of replacing
|
|
706
925
|
pendingMutations.push(...mutations);
|
|
707
926
|
scheduleProcess();
|
|
927
|
+
console.log("refreshHighlightFrame in mutationObserver");
|
|
708
928
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
709
929
|
});
|
|
710
930
|
return () => {
|
|
@@ -842,14 +1062,15 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
842
1062
|
checkNodeExists();
|
|
843
1063
|
if (!document.contains(node))
|
|
844
1064
|
return;
|
|
1065
|
+
console.log("refreshHighlightFrame in mutationObserver 2");
|
|
845
1066
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
846
1067
|
updateHighlightFrameVisibility(node);
|
|
847
1068
|
});
|
|
848
1069
|
mutationObserver.observe(node, {
|
|
849
1070
|
attributes: true,
|
|
850
1071
|
characterData: true,
|
|
851
|
-
childList: true,
|
|
852
|
-
subtree: true,
|
|
1072
|
+
//childList: true,
|
|
1073
|
+
//subtree: true,
|
|
853
1074
|
});
|
|
854
1075
|
// Also observe parent node to catch when this node is removed
|
|
855
1076
|
const parentNode = node.parentElement;
|
|
@@ -878,15 +1099,22 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
878
1099
|
if (!document.contains(node))
|
|
879
1100
|
return; // Exit early if node was removed
|
|
880
1101
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
1102
|
+
console.log("refreshHighlightFrame in resizeObserver");
|
|
881
1103
|
updateHighlightFrameVisibility(node);
|
|
882
1104
|
});
|
|
883
1105
|
}
|
|
884
1106
|
selectedNode = node;
|
|
885
1107
|
sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
|
|
886
1108
|
highlightNode(node) ?? null;
|
|
887
|
-
if (node
|
|
888
|
-
|
|
889
|
-
|
|
1109
|
+
if (node) {
|
|
1110
|
+
highlightNode(node);
|
|
1111
|
+
if (nodeProvider) {
|
|
1112
|
+
updateHighlightFrameVisibility(node);
|
|
1113
|
+
updateHighlightFrameVisibility(node);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
else {
|
|
1117
|
+
clearHighlightFrame();
|
|
890
1118
|
}
|
|
891
1119
|
};
|
|
892
1120
|
// Setup event listener
|
|
@@ -927,8 +1155,8 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
927
1155
|
|
|
928
1156
|
const DEFAULT_WIDTH = 400;
|
|
929
1157
|
const RESIZE_CONFIG = {
|
|
930
|
-
minWidth:
|
|
931
|
-
maxWidth:
|
|
1158
|
+
minWidth: 4,
|
|
1159
|
+
maxWidth: 2560,
|
|
932
1160
|
};
|
|
933
1161
|
const RESIZE_PRESETS = [
|
|
934
1162
|
{
|
|
@@ -1079,14 +1307,27 @@ const createViewport = (container, initialWidth) => {
|
|
|
1079
1307
|
isDragging = false;
|
|
1080
1308
|
};
|
|
1081
1309
|
const removeListeners = setupEventListener(resizeHandle, startResize, handleResize, stopResize, blurResize);
|
|
1310
|
+
// Refresh viewport labels when viewport is created
|
|
1311
|
+
refreshViewportLabels();
|
|
1082
1312
|
const cleanup = () => {
|
|
1083
1313
|
isDragging = false;
|
|
1084
1314
|
removeListeners();
|
|
1085
1315
|
resizeHandle.remove();
|
|
1316
|
+
// Refresh labels after cleanup to remove this viewport's label if needed
|
|
1317
|
+
refreshViewportLabels();
|
|
1086
1318
|
};
|
|
1087
1319
|
return {
|
|
1088
1320
|
setWidth: (width) => {
|
|
1089
1321
|
updateWidth(container, width);
|
|
1322
|
+
refreshViewportLabels();
|
|
1323
|
+
// Refresh highlight frame when viewport width changes to update node positions
|
|
1324
|
+
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
1325
|
+
const nodeTools = window.nodeTools;
|
|
1326
|
+
const selectedNode = nodeTools?.getSelectedNode?.();
|
|
1327
|
+
const nodeProvider = document.querySelector('[data-role="node-provider"]');
|
|
1328
|
+
if (selectedNode && nodeProvider) {
|
|
1329
|
+
refreshHighlightFrame(selectedNode, nodeProvider);
|
|
1330
|
+
}
|
|
1090
1331
|
},
|
|
1091
1332
|
cleanup,
|
|
1092
1333
|
};
|