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