@node-edit-utils/core 2.3.1 → 2.3.3
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/canvas/helpers/getCanvasContainerOrBody.d.ts +1 -0
- package/dist/lib/canvas/helpers/getCanvasWindowValue.d.ts +1 -1
- package/dist/lib/helpers/adjustForZoom.d.ts +1 -0
- package/dist/lib/helpers/createDragHandler.d.ts +69 -0
- package/dist/lib/helpers/getNodeProvider.d.ts +1 -0
- package/dist/lib/helpers/getNodeTools.d.ts +2 -0
- package/dist/lib/helpers/getViewportDimensions.d.ts +4 -0
- package/dist/lib/helpers/index.d.ts +9 -1
- package/dist/lib/helpers/parseTransform.d.ts +8 -0
- package/dist/lib/helpers/toggleClass.d.ts +1 -0
- 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/helpers/selectFirstViewportNode.d.ts +5 -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 +437 -172
- package/dist/node-edit-utils.esm.js +437 -172
- package/dist/node-edit-utils.umd.js +437 -172
- 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 +16 -2
- package/src/lib/canvas/helpers/getCanvasContainerOrBody.ts +6 -0
- package/src/lib/canvas/helpers/getCanvasWindowValue.ts +2 -3
- package/src/lib/helpers/adjustForZoom.ts +4 -0
- package/src/lib/helpers/createDragHandler.ts +171 -0
- package/src/lib/helpers/getNodeProvider.ts +4 -0
- package/src/lib/helpers/getNodeTools.ts +6 -0
- package/src/lib/helpers/getViewportDimensions.ts +7 -0
- package/src/lib/helpers/index.ts +9 -1
- package/src/lib/helpers/parseTransform.ts +9 -0
- package/src/lib/helpers/toggleClass.ts +9 -0
- package/src/lib/node-tools/createNodeTools.ts +11 -5
- package/src/lib/node-tools/highlight/clearHighlightFrame.ts +2 -3
- package/src/lib/node-tools/highlight/createHighlightFrame.ts +5 -9
- package/src/lib/node-tools/highlight/createToolsContainer.ts +3 -6
- package/src/lib/node-tools/highlight/helpers/getElementBounds.ts +6 -5
- package/src/lib/node-tools/highlight/helpers/getHighlightFrameElement.ts +2 -3
- package/src/lib/node-tools/highlight/highlightNode.ts +7 -15
- package/src/lib/node-tools/highlight/refreshHighlightFrame.ts +12 -42
- package/src/lib/node-tools/highlight/updateHighlightFrameVisibility.ts +2 -3
- 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 +56 -41
- package/src/lib/viewport/label/getViewportLabelsOverlay.ts +32 -0
- package/src/lib/viewport/label/helpers/getLabelPosition.ts +6 -0
- package/src/lib/viewport/label/helpers/getTransformValues.ts +6 -0
- package/src/lib/viewport/label/helpers/getZoomValue.ts +4 -0
- package/src/lib/viewport/label/helpers/selectFirstViewportNode.ts +18 -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 +70 -0
- package/src/lib/window/bindToWindow.ts +1 -2
|
@@ -1,10 +1,312 @@
|
|
|
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.3
|
|
5
5
|
*/
|
|
6
|
+
const getNodeTools = () => {
|
|
7
|
+
return window.nodeTools;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const getViewportDimensions = () => {
|
|
11
|
+
return {
|
|
12
|
+
width: document.documentElement.clientWidth || window.innerWidth,
|
|
13
|
+
height: document.documentElement.clientHeight || window.innerHeight,
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function getScreenBounds(element) {
|
|
18
|
+
const rect = element.getBoundingClientRect();
|
|
19
|
+
return {
|
|
20
|
+
top: rect.top,
|
|
21
|
+
left: rect.left,
|
|
22
|
+
width: rect.width,
|
|
23
|
+
height: rect.height,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const getCanvasContainer = () => {
|
|
28
|
+
return document.querySelector(".canvas-container");
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const getCanvasContainerOrBody = () => {
|
|
32
|
+
return getCanvasContainer() || document.body;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const getViewportLabelsOverlay = () => {
|
|
36
|
+
const container = getCanvasContainerOrBody();
|
|
37
|
+
// Check if overlay already exists
|
|
38
|
+
let overlay = container.querySelector(".viewport-labels-overlay");
|
|
39
|
+
if (!overlay) {
|
|
40
|
+
// Create new SVG overlay
|
|
41
|
+
overlay = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
42
|
+
overlay.classList.add("viewport-labels-overlay");
|
|
43
|
+
// Set fixed positioning
|
|
44
|
+
overlay.style.position = "absolute";
|
|
45
|
+
overlay.style.top = "0";
|
|
46
|
+
overlay.style.left = "0";
|
|
47
|
+
overlay.style.width = "100vw";
|
|
48
|
+
overlay.style.height = "100vh";
|
|
49
|
+
overlay.style.pointerEvents = "none";
|
|
50
|
+
overlay.style.zIndex = "500";
|
|
51
|
+
const { width: viewportWidth, height: viewportHeight } = getViewportDimensions();
|
|
52
|
+
overlay.setAttribute("width", viewportWidth.toString());
|
|
53
|
+
overlay.setAttribute("height", viewportHeight.toString());
|
|
54
|
+
container.appendChild(overlay);
|
|
55
|
+
}
|
|
56
|
+
return overlay;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Global flag to prevent refreshViewportLabels during drag
|
|
60
|
+
let globalIsDragging = false;
|
|
61
|
+
const isViewportLabelDragging = () => globalIsDragging;
|
|
62
|
+
const setViewportLabelDragging = (isDragging) => {
|
|
63
|
+
globalIsDragging = isDragging;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Creates a reusable drag handler for mouse drag operations
|
|
68
|
+
* @param element - Element that triggers the drag (mousedown listener attached here)
|
|
69
|
+
* @param callbacks - Callbacks for drag lifecycle events
|
|
70
|
+
* @param options - Configuration options
|
|
71
|
+
* @returns Cleanup function to remove all event listeners
|
|
72
|
+
*/
|
|
73
|
+
function createDragHandler(element, callbacks, options = {}) {
|
|
74
|
+
const { preventDefault = true, stopPropagation = true } = options;
|
|
75
|
+
const state = {
|
|
76
|
+
isDragging: false,
|
|
77
|
+
hasDragged: false,
|
|
78
|
+
startX: 0,
|
|
79
|
+
startY: 0,
|
|
80
|
+
};
|
|
81
|
+
const startDrag = (event) => {
|
|
82
|
+
if (preventDefault) {
|
|
83
|
+
event.preventDefault();
|
|
84
|
+
}
|
|
85
|
+
if (stopPropagation) {
|
|
86
|
+
event.stopPropagation();
|
|
87
|
+
}
|
|
88
|
+
state.isDragging = true;
|
|
89
|
+
state.hasDragged = false;
|
|
90
|
+
state.startX = event.clientX;
|
|
91
|
+
state.startY = event.clientY;
|
|
92
|
+
callbacks.onStart?.(event, state);
|
|
93
|
+
};
|
|
94
|
+
const handleDrag = (event) => {
|
|
95
|
+
if (!state.isDragging)
|
|
96
|
+
return;
|
|
97
|
+
const deltaX = event.clientX - state.startX;
|
|
98
|
+
const deltaY = event.clientY - state.startY;
|
|
99
|
+
state.hasDragged = true;
|
|
100
|
+
callbacks.onDrag(event, {
|
|
101
|
+
...state,
|
|
102
|
+
deltaX,
|
|
103
|
+
deltaY,
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
const stopDrag = (event) => {
|
|
107
|
+
if (!state.isDragging)
|
|
108
|
+
return;
|
|
109
|
+
if (preventDefault) {
|
|
110
|
+
event.preventDefault();
|
|
111
|
+
}
|
|
112
|
+
if (stopPropagation) {
|
|
113
|
+
event.stopPropagation();
|
|
114
|
+
}
|
|
115
|
+
state.isDragging = false;
|
|
116
|
+
callbacks.onStop?.(event, state);
|
|
117
|
+
};
|
|
118
|
+
const cancelDrag = () => {
|
|
119
|
+
if (!state.isDragging)
|
|
120
|
+
return;
|
|
121
|
+
state.isDragging = false;
|
|
122
|
+
callbacks.onCancel?.(state);
|
|
123
|
+
};
|
|
124
|
+
const preventClick = (event) => {
|
|
125
|
+
if (preventDefault) {
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
}
|
|
128
|
+
if (stopPropagation) {
|
|
129
|
+
event.stopPropagation();
|
|
130
|
+
}
|
|
131
|
+
callbacks.onPreventClick?.(event, state);
|
|
132
|
+
// Reset hasDragged flag after handling the click
|
|
133
|
+
if (state.hasDragged) {
|
|
134
|
+
state.hasDragged = false;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
// Attach event listeners
|
|
138
|
+
element.addEventListener("mousedown", startDrag);
|
|
139
|
+
if (callbacks.onPreventClick) {
|
|
140
|
+
element.addEventListener("click", preventClick);
|
|
141
|
+
}
|
|
142
|
+
document.addEventListener("mousemove", handleDrag);
|
|
143
|
+
document.addEventListener("mouseup", stopDrag);
|
|
144
|
+
window.addEventListener("blur", cancelDrag);
|
|
145
|
+
// Return cleanup function
|
|
146
|
+
return () => {
|
|
147
|
+
element.removeEventListener("mousedown", startDrag);
|
|
148
|
+
if (callbacks.onPreventClick) {
|
|
149
|
+
element.removeEventListener("click", preventClick);
|
|
150
|
+
}
|
|
151
|
+
document.removeEventListener("mousemove", handleDrag);
|
|
152
|
+
document.removeEventListener("mouseup", stopDrag);
|
|
153
|
+
window.removeEventListener("blur", cancelDrag);
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function sendPostMessage(action, data) {
|
|
158
|
+
window.parent.postMessage({
|
|
159
|
+
source: "node-edit-utils",
|
|
160
|
+
action,
|
|
161
|
+
data,
|
|
162
|
+
timestamp: Date.now(),
|
|
163
|
+
}, "*");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const parseTransform3d = (transform) => {
|
|
167
|
+
const match = transform.match(/translate3d\((-?\d+(?:\.\d+)?)px,\s*(-?\d+(?:\.\d+)?)px,\s*(-?\d+(?:\.\d+)?)px\)/);
|
|
168
|
+
return match ? { x: parseFloat(match[1]), y: parseFloat(match[2]) } : { x: 0, y: 0 };
|
|
169
|
+
};
|
|
170
|
+
const parseTransform2d = (transform) => {
|
|
171
|
+
const match = transform?.match(/translate\((-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)\)/);
|
|
172
|
+
return match ? { x: parseFloat(match[1]), y: parseFloat(match[2]) } : { x: 0, y: 0 };
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const getLabelPosition = (labelGroup) => {
|
|
176
|
+
const transform = labelGroup.getAttribute("transform");
|
|
177
|
+
return parseTransform2d(transform);
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const getTransformValues = (element) => {
|
|
181
|
+
const style = element.style.transform;
|
|
182
|
+
return parseTransform3d(style);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const getZoomValue = () => {
|
|
186
|
+
const zoomValue = getComputedStyle(document.body).getPropertyValue("--zoom").trim();
|
|
187
|
+
return zoomValue ? parseFloat(zoomValue) : 1;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Selects the first child node inside a viewport element.
|
|
192
|
+
* Skips the resize-handle element if present.
|
|
193
|
+
*/
|
|
194
|
+
const selectFirstViewportNode = (viewportElement) => {
|
|
195
|
+
const firstChild = Array.from(viewportElement.children).find((child) => !child.classList.contains("resize-handle"));
|
|
196
|
+
if (firstChild) {
|
|
197
|
+
const nodeTools = getNodeTools();
|
|
198
|
+
if (nodeTools?.selectNode) {
|
|
199
|
+
nodeTools.selectNode(firstChild);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const setupViewportLabelDrag = (labelElement, viewportElement, viewportName) => {
|
|
205
|
+
// Get the parent group element that contains the label
|
|
206
|
+
const labelGroup = labelElement.parentElement;
|
|
207
|
+
// Track initial positions for calculations
|
|
208
|
+
let initialTransform = { x: 0, y: 0 };
|
|
209
|
+
let initialLabelPosition = { x: 0, y: 0 };
|
|
210
|
+
return createDragHandler(labelElement, {
|
|
211
|
+
onStart: () => {
|
|
212
|
+
setViewportLabelDragging(true);
|
|
213
|
+
initialTransform = getTransformValues(viewportElement);
|
|
214
|
+
initialLabelPosition = getLabelPosition(labelGroup);
|
|
215
|
+
selectFirstViewportNode(viewportElement);
|
|
216
|
+
},
|
|
217
|
+
onDrag: (_event, { deltaX, deltaY }) => {
|
|
218
|
+
const zoom = getZoomValue();
|
|
219
|
+
// Adjust delta for zoom level (viewport is in canvas space)
|
|
220
|
+
const deltaXZoomed = deltaX / zoom;
|
|
221
|
+
const deltaYZoomed = deltaY / zoom;
|
|
222
|
+
// Calculate new positions
|
|
223
|
+
const newX = initialTransform.x + deltaXZoomed;
|
|
224
|
+
const newY = initialTransform.y + deltaYZoomed;
|
|
225
|
+
// Update label position with raw delta (labels are in screen space)
|
|
226
|
+
const newLabelX = initialLabelPosition.x + deltaX;
|
|
227
|
+
const newLabelY = initialLabelPosition.y + deltaY;
|
|
228
|
+
labelGroup.setAttribute("transform", `translate(${newLabelX}, ${newLabelY})`);
|
|
229
|
+
// Update viewport position with zoom-adjusted delta
|
|
230
|
+
viewportElement.style.transform = `translate3d(${newX}px, ${newY}px, 0)`;
|
|
231
|
+
},
|
|
232
|
+
onStop: (_event, { hasDragged }) => {
|
|
233
|
+
setViewportLabelDragging(false);
|
|
234
|
+
// If it was a drag, handle drag completion
|
|
235
|
+
if (hasDragged) {
|
|
236
|
+
const finalTransform = getTransformValues(viewportElement);
|
|
237
|
+
// Trigger refresh after drag completes to update highlight frame and labels
|
|
238
|
+
const nodeTools = getNodeTools();
|
|
239
|
+
if (nodeTools?.refreshHighlightFrame) {
|
|
240
|
+
nodeTools.refreshHighlightFrame();
|
|
241
|
+
}
|
|
242
|
+
// Notify parent about the new position
|
|
243
|
+
sendPostMessage("viewport-position-changed", {
|
|
244
|
+
viewportName,
|
|
245
|
+
x: finalTransform.x,
|
|
246
|
+
y: finalTransform.y,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
onCancel: () => {
|
|
251
|
+
setViewportLabelDragging(false);
|
|
252
|
+
},
|
|
253
|
+
onPreventClick: () => { },
|
|
254
|
+
});
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// Store cleanup functions for drag listeners
|
|
258
|
+
const dragCleanupFunctions = new Map();
|
|
259
|
+
const refreshViewportLabels = () => {
|
|
260
|
+
// Skip refresh if a viewport label is being dragged
|
|
261
|
+
if (isViewportLabelDragging()) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
const overlay = getViewportLabelsOverlay();
|
|
265
|
+
// Update SVG dimensions to match current viewport
|
|
266
|
+
const { width: viewportWidth, height: viewportHeight } = getViewportDimensions();
|
|
267
|
+
overlay.setAttribute("width", viewportWidth.toString());
|
|
268
|
+
overlay.setAttribute("height", viewportHeight.toString());
|
|
269
|
+
// Find all viewports with names
|
|
270
|
+
const viewports = document.querySelectorAll(".viewport[data-viewport-name]");
|
|
271
|
+
// Clean up existing drag listeners
|
|
272
|
+
dragCleanupFunctions.forEach((cleanup) => {
|
|
273
|
+
cleanup();
|
|
274
|
+
});
|
|
275
|
+
dragCleanupFunctions.clear();
|
|
276
|
+
// Remove existing label groups
|
|
277
|
+
const existingGroups = overlay.querySelectorAll(".viewport-label-group");
|
|
278
|
+
existingGroups.forEach((group) => {
|
|
279
|
+
group.remove();
|
|
280
|
+
});
|
|
281
|
+
// Create/update labels for each viewport
|
|
282
|
+
viewports.forEach((viewport) => {
|
|
283
|
+
const viewportElement = viewport;
|
|
284
|
+
const viewportName = viewportElement.getAttribute("data-viewport-name");
|
|
285
|
+
if (!viewportName)
|
|
286
|
+
return;
|
|
287
|
+
const bounds = getScreenBounds(viewportElement);
|
|
288
|
+
// Create group for this viewport label
|
|
289
|
+
const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
290
|
+
group.classList.add("viewport-label-group");
|
|
291
|
+
group.setAttribute("data-viewport-name", viewportName);
|
|
292
|
+
group.setAttribute("transform", `translate(${bounds.left}, ${bounds.top})`);
|
|
293
|
+
// Create text element
|
|
294
|
+
const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
|
295
|
+
text.classList.add("viewport-label-text");
|
|
296
|
+
text.setAttribute("x", "0");
|
|
297
|
+
text.setAttribute("y", "-8");
|
|
298
|
+
text.setAttribute("vector-effect", "non-scaling-stroke");
|
|
299
|
+
text.setAttribute("pointer-events", "auto");
|
|
300
|
+
text.textContent = viewportName;
|
|
301
|
+
group.appendChild(text);
|
|
302
|
+
overlay.appendChild(group);
|
|
303
|
+
// Setup drag functionality for this label
|
|
304
|
+
const cleanup = setupViewportLabelDrag(text, viewportElement, viewportName);
|
|
305
|
+
dragCleanupFunctions.set(viewportName, cleanup);
|
|
306
|
+
});
|
|
307
|
+
};
|
|
308
|
+
|
|
6
309
|
const getCanvasWindowValue = (path, canvasName = "canvas") => {
|
|
7
|
-
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
8
310
|
const canvas = window[canvasName];
|
|
9
311
|
return path.reduce((obj, prop) => obj?.[prop], canvas);
|
|
10
312
|
};
|
|
@@ -27,11 +329,12 @@ function createCanvasObserver(canvasName = "canvas") {
|
|
|
27
329
|
const observer = new MutationObserver(() => {
|
|
28
330
|
applyCanvasState(canvasName);
|
|
29
331
|
// Refresh highlight frame (throttled via withRAFThrottle)
|
|
30
|
-
|
|
31
|
-
const nodeTools = window.nodeTools;
|
|
332
|
+
const nodeTools = getNodeTools();
|
|
32
333
|
if (nodeTools?.refreshHighlightFrame) {
|
|
33
334
|
nodeTools.refreshHighlightFrame();
|
|
34
335
|
}
|
|
336
|
+
// Refresh viewport labels
|
|
337
|
+
refreshViewportLabels();
|
|
35
338
|
});
|
|
36
339
|
observer.observe(transformLayer, {
|
|
37
340
|
attributes: true,
|
|
@@ -39,8 +342,16 @@ function createCanvasObserver(canvasName = "canvas") {
|
|
|
39
342
|
subtree: true,
|
|
40
343
|
childList: true,
|
|
41
344
|
});
|
|
345
|
+
// Handle window resize for viewport labels
|
|
346
|
+
const handleResize = () => {
|
|
347
|
+
refreshViewportLabels();
|
|
348
|
+
};
|
|
349
|
+
window.addEventListener("resize", handleResize);
|
|
350
|
+
// Initial refresh of viewport labels
|
|
351
|
+
refreshViewportLabels();
|
|
42
352
|
function disconnect() {
|
|
43
353
|
observer.disconnect();
|
|
354
|
+
window.removeEventListener("resize", handleResize);
|
|
44
355
|
}
|
|
45
356
|
return {
|
|
46
357
|
disconnect,
|
|
@@ -55,18 +366,8 @@ const connectResizeObserver = (element, handler) => {
|
|
|
55
366
|
return resizeObserver;
|
|
56
367
|
};
|
|
57
368
|
|
|
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
369
|
const bindToWindow = (key, value) => {
|
|
68
370
|
if (typeof window !== "undefined") {
|
|
69
|
-
// biome-ignore lint/suspicious/noExplicitAny: global window extension requires flexibility
|
|
70
371
|
window[key] = value;
|
|
71
372
|
}
|
|
72
373
|
};
|
|
@@ -91,13 +392,8 @@ const processPostMessage = (event, onNodeSelected) => {
|
|
|
91
392
|
}
|
|
92
393
|
};
|
|
93
394
|
|
|
94
|
-
const getCanvasContainer = () => {
|
|
95
|
-
return document.querySelector(".canvas-container");
|
|
96
|
-
};
|
|
97
|
-
|
|
98
395
|
const clearHighlightFrame = () => {
|
|
99
|
-
const
|
|
100
|
-
const container = canvasContainer || document.body;
|
|
396
|
+
const container = getCanvasContainerOrBody();
|
|
101
397
|
const frame = container.querySelector(".highlight-frame-overlay");
|
|
102
398
|
if (frame) {
|
|
103
399
|
frame.remove();
|
|
@@ -146,6 +442,21 @@ const isInsideComponent = (element) => {
|
|
|
146
442
|
return false;
|
|
147
443
|
};
|
|
148
444
|
|
|
445
|
+
const isInsideViewport = (element) => {
|
|
446
|
+
let current = element;
|
|
447
|
+
while (current) {
|
|
448
|
+
if (current.classList.contains("viewport")) {
|
|
449
|
+
return true;
|
|
450
|
+
}
|
|
451
|
+
// Stop at node-provider to avoid checking beyond the editable area
|
|
452
|
+
if (current.getAttribute("data-role") === "node-provider") {
|
|
453
|
+
break;
|
|
454
|
+
}
|
|
455
|
+
current = current.parentElement;
|
|
456
|
+
}
|
|
457
|
+
return false;
|
|
458
|
+
};
|
|
459
|
+
|
|
149
460
|
const targetSameCandidates = (cache, current) => cache.length === current.length && cache.every((el, i) => el === current[i]);
|
|
150
461
|
|
|
151
462
|
let candidateCache = [];
|
|
@@ -158,7 +469,16 @@ const selectNode = (event, nodeProvider, text) => {
|
|
|
158
469
|
const clickThrough = event.metaKey || event.ctrlKey;
|
|
159
470
|
const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()) &&
|
|
160
471
|
!element.classList.contains("select-none") &&
|
|
161
|
-
!
|
|
472
|
+
!element.classList.contains("content-layer") &&
|
|
473
|
+
!element.classList.contains("resize-handle") &&
|
|
474
|
+
!element.classList.contains("resize-presets") &&
|
|
475
|
+
!isInsideComponent(element) &&
|
|
476
|
+
isInsideViewport(element));
|
|
477
|
+
console.log("candidates", candidates);
|
|
478
|
+
if (candidates.length === 0) {
|
|
479
|
+
lastSelectedNode = null;
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
162
482
|
const editableNode = text.getEditableNode();
|
|
163
483
|
if (editableNode && candidates.includes(editableNode)) {
|
|
164
484
|
selectedNode = editableNode;
|
|
@@ -202,7 +522,7 @@ const handleNodeClick = (event, nodeProvider, text, onNodeSelected) => {
|
|
|
202
522
|
onNodeSelected(selectedNode);
|
|
203
523
|
};
|
|
204
524
|
|
|
205
|
-
const setupEventListener
|
|
525
|
+
const setupEventListener = (nodeProvider, onNodeSelected, onEscapePressed, text) => {
|
|
206
526
|
const messageHandler = (event) => {
|
|
207
527
|
processPostMessage(event, onNodeSelected);
|
|
208
528
|
};
|
|
@@ -226,6 +546,17 @@ const setupEventListener$1 = (nodeProvider, onNodeSelected, onEscapePressed, tex
|
|
|
226
546
|
};
|
|
227
547
|
};
|
|
228
548
|
|
|
549
|
+
const toggleClass = (element, className, condition) => {
|
|
550
|
+
if (!element)
|
|
551
|
+
return;
|
|
552
|
+
if (condition) {
|
|
553
|
+
element.classList.add(className);
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
element.classList.remove(className);
|
|
557
|
+
}
|
|
558
|
+
};
|
|
559
|
+
|
|
229
560
|
const isComponentInstance = (element) => {
|
|
230
561
|
return element.getAttribute("data-instance") === "true";
|
|
231
562
|
};
|
|
@@ -263,16 +594,6 @@ const createCornerHandles = (group, width, height, isInstance = false, isTextEdi
|
|
|
263
594
|
createCornerHandle(group, 0, height, "handle-bottom-left", isInstance, isTextEdit);
|
|
264
595
|
};
|
|
265
596
|
|
|
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
597
|
const getComponentColor$1 = () => {
|
|
277
598
|
return getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim() || "oklch(65.6% 0.241 354.308)";
|
|
278
599
|
};
|
|
@@ -301,8 +622,7 @@ const createHighlightFrame = (node, isInstance = false, isTextEdit = false) => {
|
|
|
301
622
|
svg.style.height = "100vh";
|
|
302
623
|
svg.style.pointerEvents = "none";
|
|
303
624
|
svg.style.zIndex = "500";
|
|
304
|
-
const viewportWidth
|
|
305
|
-
const viewportHeight = document.documentElement.clientHeight || window.innerHeight;
|
|
625
|
+
const { width: viewportWidth, height: viewportHeight } = getViewportDimensions();
|
|
306
626
|
svg.setAttribute("width", viewportWidth.toString());
|
|
307
627
|
svg.setAttribute("height", viewportHeight.toString());
|
|
308
628
|
const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
@@ -325,13 +645,8 @@ const createHighlightFrame = (node, isInstance = false, isTextEdit = false) => {
|
|
|
325
645
|
group.appendChild(rect);
|
|
326
646
|
createCornerHandles(group, minWidth, height, isInstance, isTextEdit);
|
|
327
647
|
svg.appendChild(group);
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
canvasContainer.appendChild(svg);
|
|
331
|
-
}
|
|
332
|
-
else {
|
|
333
|
-
document.body.appendChild(svg);
|
|
334
|
-
}
|
|
648
|
+
const container = getCanvasContainerOrBody();
|
|
649
|
+
container.appendChild(svg);
|
|
335
650
|
return svg;
|
|
336
651
|
};
|
|
337
652
|
|
|
@@ -368,19 +683,14 @@ const createTagLabel = (node, nodeTools) => {
|
|
|
368
683
|
const createToolsContainer = (node, highlightFrame, isInstance = false, isTextEdit = false) => {
|
|
369
684
|
const nodeTools = document.createElement("div");
|
|
370
685
|
nodeTools.className = "node-tools";
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
}
|
|
374
|
-
if (isTextEdit) {
|
|
375
|
-
nodeTools.classList.add("is-text-edit");
|
|
376
|
-
}
|
|
686
|
+
toggleClass(nodeTools, "is-instance", isInstance);
|
|
687
|
+
toggleClass(nodeTools, "is-text-edit", isTextEdit);
|
|
377
688
|
highlightFrame.appendChild(nodeTools);
|
|
378
689
|
createTagLabel(node, nodeTools);
|
|
379
690
|
};
|
|
380
691
|
|
|
381
692
|
function getHighlightFrameElement() {
|
|
382
|
-
const
|
|
383
|
-
const container = canvasContainer || document.body;
|
|
693
|
+
const container = getCanvasContainerOrBody();
|
|
384
694
|
return container.querySelector(".highlight-frame-overlay");
|
|
385
695
|
}
|
|
386
696
|
|
|
@@ -388,8 +698,8 @@ const highlightNode = (node) => {
|
|
|
388
698
|
if (!node)
|
|
389
699
|
return;
|
|
390
700
|
const existingHighlightFrame = getHighlightFrameElement();
|
|
391
|
-
const
|
|
392
|
-
const existingToolsWrapper =
|
|
701
|
+
const container = getCanvasContainerOrBody();
|
|
702
|
+
const existingToolsWrapper = container.querySelector(".highlight-frame-tools-wrapper");
|
|
393
703
|
if (existingHighlightFrame) {
|
|
394
704
|
existingHighlightFrame.remove();
|
|
395
705
|
}
|
|
@@ -408,24 +718,15 @@ const highlightNode = (node) => {
|
|
|
408
718
|
// Create tools wrapper using CSS transform (GPU-accelerated)
|
|
409
719
|
const toolsWrapper = document.createElement("div");
|
|
410
720
|
toolsWrapper.classList.add("highlight-frame-tools-wrapper");
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
}
|
|
414
|
-
if (isTextEdit) {
|
|
415
|
-
toolsWrapper.classList.add("is-text-edit");
|
|
416
|
-
}
|
|
721
|
+
toggleClass(toolsWrapper, "is-instance", isInstance);
|
|
722
|
+
toggleClass(toolsWrapper, "is-text-edit", isTextEdit);
|
|
417
723
|
toolsWrapper.style.position = "absolute";
|
|
418
724
|
toolsWrapper.style.transform = `translate(${left}px, ${bottomY}px)`;
|
|
419
725
|
toolsWrapper.style.transformOrigin = "left center";
|
|
420
726
|
toolsWrapper.style.pointerEvents = "none";
|
|
421
727
|
toolsWrapper.style.zIndex = "500";
|
|
422
728
|
createToolsContainer(node, toolsWrapper, isInstance, isTextEdit);
|
|
423
|
-
|
|
424
|
-
canvasContainer.appendChild(toolsWrapper);
|
|
425
|
-
}
|
|
426
|
-
else {
|
|
427
|
-
document.body.appendChild(toolsWrapper);
|
|
428
|
-
}
|
|
729
|
+
container.appendChild(toolsWrapper);
|
|
429
730
|
};
|
|
430
731
|
|
|
431
732
|
const getComponentColor = () => {
|
|
@@ -443,24 +744,13 @@ const refreshHighlightFrame = (node, nodeProvider, canvasName = "canvas") => {
|
|
|
443
744
|
const isTextEdit = node.contentEditable === "true";
|
|
444
745
|
// Update SVG dimensions to match current viewport (handles window resize and ensures coordinate system is correct)
|
|
445
746
|
// Use clientWidth/Height to match getBoundingClientRect() coordinate system (excludes scrollbars)
|
|
446
|
-
const viewportWidth
|
|
447
|
-
const viewportHeight = document.documentElement.clientHeight || window.innerHeight;
|
|
747
|
+
const { width: viewportWidth, height: viewportHeight } = getViewportDimensions();
|
|
448
748
|
frame.setAttribute("width", viewportWidth.toString());
|
|
449
749
|
frame.setAttribute("height", viewportHeight.toString());
|
|
450
750
|
// Update instance class
|
|
451
|
-
|
|
452
|
-
frame.classList.add("is-instance");
|
|
453
|
-
}
|
|
454
|
-
else {
|
|
455
|
-
frame.classList.remove("is-instance");
|
|
456
|
-
}
|
|
751
|
+
toggleClass(frame, "is-instance", isInstance);
|
|
457
752
|
// Update text edit class
|
|
458
|
-
|
|
459
|
-
frame.classList.add("is-text-edit");
|
|
460
|
-
}
|
|
461
|
-
else {
|
|
462
|
-
frame.classList.remove("is-text-edit");
|
|
463
|
-
}
|
|
753
|
+
toggleClass(frame, "is-text-edit", isTextEdit);
|
|
464
754
|
const group = frame.querySelector(".highlight-frame-group");
|
|
465
755
|
if (!group)
|
|
466
756
|
return;
|
|
@@ -477,8 +767,7 @@ const refreshHighlightFrame = (node, nodeProvider, canvasName = "canvas") => {
|
|
|
477
767
|
else {
|
|
478
768
|
rect.removeAttribute("stroke"); // Use CSS default
|
|
479
769
|
}
|
|
480
|
-
const
|
|
481
|
-
const container = canvasContainer || document.body;
|
|
770
|
+
const container = getCanvasContainerOrBody();
|
|
482
771
|
const toolsWrapper = container.querySelector(".highlight-frame-tools-wrapper");
|
|
483
772
|
const nodeTools = toolsWrapper?.querySelector(".node-tools");
|
|
484
773
|
const zoom = getCanvasWindowValue(["zoom", "current"], canvasName) ?? 1;
|
|
@@ -489,36 +778,10 @@ const refreshHighlightFrame = (node, nodeProvider, canvasName = "canvas") => {
|
|
|
489
778
|
const minWidth = Math.max(width, 3);
|
|
490
779
|
const bottomY = top + height;
|
|
491
780
|
// Update instance classes on tools wrapper and node tools
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
else {
|
|
497
|
-
toolsWrapper.classList.remove("is-instance");
|
|
498
|
-
}
|
|
499
|
-
// Update text edit class
|
|
500
|
-
if (isTextEdit) {
|
|
501
|
-
toolsWrapper.classList.add("is-text-edit");
|
|
502
|
-
}
|
|
503
|
-
else {
|
|
504
|
-
toolsWrapper.classList.remove("is-text-edit");
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
if (nodeTools) {
|
|
508
|
-
if (isInstance) {
|
|
509
|
-
nodeTools.classList.add("is-instance");
|
|
510
|
-
}
|
|
511
|
-
else {
|
|
512
|
-
nodeTools.classList.remove("is-instance");
|
|
513
|
-
}
|
|
514
|
-
// Update text edit class
|
|
515
|
-
if (isTextEdit) {
|
|
516
|
-
nodeTools.classList.add("is-text-edit");
|
|
517
|
-
}
|
|
518
|
-
else {
|
|
519
|
-
nodeTools.classList.remove("is-text-edit");
|
|
520
|
-
}
|
|
521
|
-
}
|
|
781
|
+
toggleClass(toolsWrapper, "is-instance", isInstance);
|
|
782
|
+
toggleClass(toolsWrapper, "is-text-edit", isTextEdit);
|
|
783
|
+
toggleClass(nodeTools, "is-instance", isInstance);
|
|
784
|
+
toggleClass(nodeTools, "is-text-edit", isTextEdit);
|
|
522
785
|
// Batch all DOM writes (single paint pass)
|
|
523
786
|
// Update group transform to move entire group (rect + handles) at once
|
|
524
787
|
group.setAttribute("transform", `translate(${left}, ${top})`);
|
|
@@ -584,8 +847,7 @@ const updateHighlightFrameVisibility = (node) => {
|
|
|
584
847
|
const displayValue = hasHiddenClass ? "none" : "";
|
|
585
848
|
// Batch DOM writes
|
|
586
849
|
frame.style.display = displayValue;
|
|
587
|
-
const
|
|
588
|
-
const container = canvasContainer || document.body;
|
|
850
|
+
const container = getCanvasContainerOrBody();
|
|
589
851
|
const toolsWrapper = container.querySelector(".highlight-frame-tools-wrapper");
|
|
590
852
|
if (toolsWrapper) {
|
|
591
853
|
toolsWrapper.style.display = displayValue;
|
|
@@ -705,6 +967,7 @@ const setupMutationObserver = (node, nodeProvider, canvasName = "canvas") => {
|
|
|
705
967
|
// Accumulate mutations instead of replacing
|
|
706
968
|
pendingMutations.push(...mutations);
|
|
707
969
|
scheduleProcess();
|
|
970
|
+
console.log("refreshHighlightFrame in mutationObserver");
|
|
708
971
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
709
972
|
});
|
|
710
973
|
return () => {
|
|
@@ -842,14 +1105,15 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
842
1105
|
checkNodeExists();
|
|
843
1106
|
if (!document.contains(node))
|
|
844
1107
|
return;
|
|
1108
|
+
console.log("refreshHighlightFrame in mutationObserver 2");
|
|
845
1109
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
846
1110
|
updateHighlightFrameVisibility(node);
|
|
847
1111
|
});
|
|
848
1112
|
mutationObserver.observe(node, {
|
|
849
1113
|
attributes: true,
|
|
850
1114
|
characterData: true,
|
|
851
|
-
childList: true,
|
|
852
|
-
subtree: true,
|
|
1115
|
+
//childList: true,
|
|
1116
|
+
//subtree: true,
|
|
853
1117
|
});
|
|
854
1118
|
// Also observe parent node to catch when this node is removed
|
|
855
1119
|
const parentNode = node.parentElement;
|
|
@@ -878,19 +1142,25 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
878
1142
|
if (!document.contains(node))
|
|
879
1143
|
return; // Exit early if node was removed
|
|
880
1144
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
1145
|
+
console.log("refreshHighlightFrame in resizeObserver");
|
|
881
1146
|
updateHighlightFrameVisibility(node);
|
|
882
1147
|
});
|
|
883
1148
|
}
|
|
884
1149
|
selectedNode = node;
|
|
885
1150
|
sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
|
|
886
1151
|
highlightNode(node) ?? null;
|
|
887
|
-
if (node
|
|
888
|
-
|
|
889
|
-
|
|
1152
|
+
if (node) {
|
|
1153
|
+
highlightNode(node);
|
|
1154
|
+
if (nodeProvider) {
|
|
1155
|
+
updateHighlightFrameVisibility(node);
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
else {
|
|
1159
|
+
clearHighlightFrame();
|
|
890
1160
|
}
|
|
891
1161
|
};
|
|
892
1162
|
// Setup event listener
|
|
893
|
-
const removeListeners = setupEventListener
|
|
1163
|
+
const removeListeners = setupEventListener(nodeProvider, selectNode, handleEscape, text);
|
|
894
1164
|
const cleanup = () => {
|
|
895
1165
|
removeListeners();
|
|
896
1166
|
resizeObserver?.disconnect();
|
|
@@ -925,10 +1195,14 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
925
1195
|
return nodeTools;
|
|
926
1196
|
};
|
|
927
1197
|
|
|
1198
|
+
const getNodeProvider = () => {
|
|
1199
|
+
return document.querySelector('[data-role="node-provider"]');
|
|
1200
|
+
};
|
|
1201
|
+
|
|
928
1202
|
const DEFAULT_WIDTH = 400;
|
|
929
1203
|
const RESIZE_CONFIG = {
|
|
930
|
-
minWidth:
|
|
931
|
-
maxWidth:
|
|
1204
|
+
minWidth: 4,
|
|
1205
|
+
maxWidth: 2560,
|
|
932
1206
|
};
|
|
933
1207
|
const RESIZE_PRESETS = [
|
|
934
1208
|
{
|
|
@@ -958,27 +1232,6 @@ const RESIZE_PRESETS = [
|
|
|
958
1232
|
},
|
|
959
1233
|
];
|
|
960
1234
|
|
|
961
|
-
const setupEventListener = (resizeHandle, startResize, handleResize, stopResize, blurResize) => {
|
|
962
|
-
const handleMouseLeave = (event) => {
|
|
963
|
-
// Check if mouse is leaving the window/document
|
|
964
|
-
if (!event.relatedTarget && (event.target === document || event.target === document.documentElement)) {
|
|
965
|
-
blurResize();
|
|
966
|
-
}
|
|
967
|
-
};
|
|
968
|
-
resizeHandle.addEventListener("mousedown", startResize);
|
|
969
|
-
document.addEventListener("mousemove", handleResize);
|
|
970
|
-
document.addEventListener("mouseup", stopResize);
|
|
971
|
-
document.addEventListener("mouseleave", handleMouseLeave);
|
|
972
|
-
window.addEventListener("blur", blurResize);
|
|
973
|
-
return () => {
|
|
974
|
-
resizeHandle.removeEventListener("mousedown", startResize);
|
|
975
|
-
document.removeEventListener("mousemove", handleResize);
|
|
976
|
-
document.removeEventListener("mouseup", stopResize);
|
|
977
|
-
document.removeEventListener("mouseleave", handleMouseLeave);
|
|
978
|
-
window.removeEventListener("blur", blurResize);
|
|
979
|
-
};
|
|
980
|
-
};
|
|
981
|
-
|
|
982
1235
|
const createResizeHandle = (container) => {
|
|
983
1236
|
const handle = document.createElement("div");
|
|
984
1237
|
handle.className = "resize-handle";
|
|
@@ -1045,48 +1298,60 @@ const createViewport = (container, initialWidth) => {
|
|
|
1045
1298
|
const width = initialWidth ?? DEFAULT_WIDTH;
|
|
1046
1299
|
container.style.setProperty("--container-width", `${width}px`);
|
|
1047
1300
|
createResizePresets(resizeHandle, container, updateWidth);
|
|
1048
|
-
|
|
1301
|
+
// Track initial values for resize calculation
|
|
1049
1302
|
let startX = 0;
|
|
1050
1303
|
let startWidth = 0;
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
const handleResize = (event) => {
|
|
1059
|
-
if (!isDragging)
|
|
1060
|
-
return;
|
|
1061
|
-
if (canvas) {
|
|
1062
|
-
canvas.style.cursor = "ew-resize";
|
|
1063
|
-
}
|
|
1064
|
-
const width = calcWidth(event, startX, startWidth);
|
|
1065
|
-
updateWidth(container, width);
|
|
1066
|
-
};
|
|
1067
|
-
const stopResize = (event) => {
|
|
1068
|
-
event.preventDefault();
|
|
1069
|
-
event.stopPropagation();
|
|
1070
|
-
if (canvas) {
|
|
1071
|
-
canvas.style.cursor = "default";
|
|
1072
|
-
}
|
|
1073
|
-
isDragging = false;
|
|
1074
|
-
};
|
|
1075
|
-
const blurResize = () => {
|
|
1076
|
-
if (canvas) {
|
|
1077
|
-
canvas.style.cursor = "default";
|
|
1304
|
+
// Handle mouse leave for resize (specific to resize use case)
|
|
1305
|
+
const handleMouseLeave = (event) => {
|
|
1306
|
+
// Check if mouse is leaving the window/document
|
|
1307
|
+
if (!event.relatedTarget && (event.target === document || event.target === document.documentElement)) {
|
|
1308
|
+
if (canvas) {
|
|
1309
|
+
canvas.style.cursor = "default";
|
|
1310
|
+
}
|
|
1078
1311
|
}
|
|
1079
|
-
isDragging = false;
|
|
1080
1312
|
};
|
|
1081
|
-
const
|
|
1313
|
+
const removeDragListeners = createDragHandler(resizeHandle, {
|
|
1314
|
+
onStart: (_event, { startX: dragStartX }) => {
|
|
1315
|
+
startX = dragStartX;
|
|
1316
|
+
startWidth = container.offsetWidth;
|
|
1317
|
+
},
|
|
1318
|
+
onDrag: (event) => {
|
|
1319
|
+
if (canvas) {
|
|
1320
|
+
canvas.style.cursor = "ew-resize";
|
|
1321
|
+
}
|
|
1322
|
+
const width = calcWidth(event, startX, startWidth);
|
|
1323
|
+
updateWidth(container, width);
|
|
1324
|
+
},
|
|
1325
|
+
onStop: () => {
|
|
1326
|
+
if (canvas) {
|
|
1327
|
+
canvas.style.cursor = "default";
|
|
1328
|
+
}
|
|
1329
|
+
},
|
|
1330
|
+
onCancel: () => {
|
|
1331
|
+
if (canvas) {
|
|
1332
|
+
canvas.style.cursor = "default";
|
|
1333
|
+
}
|
|
1334
|
+
},
|
|
1335
|
+
onPreventClick: () => { },
|
|
1336
|
+
});
|
|
1337
|
+
document.addEventListener("mouseleave", handleMouseLeave);
|
|
1338
|
+
refreshViewportLabels();
|
|
1082
1339
|
const cleanup = () => {
|
|
1083
|
-
|
|
1084
|
-
|
|
1340
|
+
removeDragListeners();
|
|
1341
|
+
document.removeEventListener("mouseleave", handleMouseLeave);
|
|
1085
1342
|
resizeHandle.remove();
|
|
1343
|
+
refreshViewportLabels();
|
|
1086
1344
|
};
|
|
1087
1345
|
return {
|
|
1088
1346
|
setWidth: (width) => {
|
|
1089
1347
|
updateWidth(container, width);
|
|
1348
|
+
refreshViewportLabels();
|
|
1349
|
+
const nodeTools = getNodeTools();
|
|
1350
|
+
const selectedNode = nodeTools?.getSelectedNode?.();
|
|
1351
|
+
const nodeProvider = getNodeProvider();
|
|
1352
|
+
if (selectedNode && nodeProvider) {
|
|
1353
|
+
refreshHighlightFrame(selectedNode, nodeProvider);
|
|
1354
|
+
}
|
|
1090
1355
|
},
|
|
1091
1356
|
cleanup,
|
|
1092
1357
|
};
|