@node-edit-utils/core 2.0.4 → 2.0.6
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/highlight/updateHighlightFrameVisibility.d.ts +1 -0
- package/dist/lib/post-message/processPostMessage.d.ts +1 -0
- package/dist/node-edit-utils.cjs.js +42 -4
- package/dist/node-edit-utils.esm.js +42 -4
- package/dist/node-edit-utils.umd.js +42 -4
- package/dist/node-edit-utils.umd.min.js +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/lib/node-tools/createNodeTools.ts +24 -0
- package/src/lib/node-tools/events/setupEventListener.ts +2 -2
- package/src/lib/node-tools/highlight/updateHighlightFrameVisibility.ts +10 -0
- package/src/lib/node-tools/select/selectNode.ts +1 -1
- package/src/lib/post-message/processPostMessage.ts +21 -0
- package/src/lib/styles/styles.css +7 -2
- package/dist/lib/post-message/handlePostMessage.d.ts +0 -1
- package/src/lib/post-message/handlePostMessage.ts +0 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const updateHighlightFrameVisibility: (node: HTMLElement, nodeProvider: HTMLElement) => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const processPostMessage: (event: MessageEvent, onNodeSelected?: (node: HTMLElement | null) => void) => void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markup Canvas
|
|
3
3
|
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
-
* @version 2.0.
|
|
4
|
+
* @version 2.0.6
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
@@ -97,13 +97,24 @@ const bindToWindow = (key, value) => {
|
|
|
97
97
|
}
|
|
98
98
|
};
|
|
99
99
|
|
|
100
|
-
const
|
|
100
|
+
const processPostMessage = (event, onNodeSelected) => {
|
|
101
101
|
if (event.data.source === "markup-canvas" && event.data.canvasName === "canvas") {
|
|
102
102
|
if (event.data.action === "zoom") {
|
|
103
103
|
const zoom = event.data.data;
|
|
104
104
|
console.log("zoom", zoom);
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
|
+
if (event.data.source === "application") {
|
|
108
|
+
if (event.data.action === "selectedNodeChanged") {
|
|
109
|
+
const nodeId = event.data.data;
|
|
110
|
+
console.log("selectedNodeChanged in node-edit-utils", nodeId);
|
|
111
|
+
const selectedNode = document.querySelector(`[data-node-id="${nodeId}"]`);
|
|
112
|
+
if (selectedNode) {
|
|
113
|
+
console.log("selectedNode", selectedNode);
|
|
114
|
+
onNodeSelected?.(selectedNode);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
107
118
|
};
|
|
108
119
|
|
|
109
120
|
function getHighlightFrameElement(nodeProvider) {
|
|
@@ -145,7 +156,7 @@ const selectNode = (event, editableNode) => {
|
|
|
145
156
|
const clickX = event.clientX;
|
|
146
157
|
const clickY = event.clientY;
|
|
147
158
|
const clickThrough = event.metaKey || event.ctrlKey;
|
|
148
|
-
const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()));
|
|
159
|
+
const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()) && !element.classList.contains("select-none"));
|
|
149
160
|
if (editableNode && candidates.includes(editableNode)) {
|
|
150
161
|
return editableNode;
|
|
151
162
|
}
|
|
@@ -180,7 +191,7 @@ const handleNodeClick = (event, nodeProvider, editableNode, onNodeSelected) => {
|
|
|
180
191
|
|
|
181
192
|
const setupEventListener$1 = (nodeProvider, onNodeSelected, onEscapePressed, getEditableNode) => {
|
|
182
193
|
const messageHandler = (event) => {
|
|
183
|
-
|
|
194
|
+
processPostMessage(event, onNodeSelected);
|
|
184
195
|
};
|
|
185
196
|
const documentClickHandler = (event) => {
|
|
186
197
|
handleNodeClick(event, nodeProvider, getEditableNode(), onNodeSelected);
|
|
@@ -293,6 +304,14 @@ const refreshHighlightFrame = (node, nodeProvider) => {
|
|
|
293
304
|
frame.style.setProperty("--frame-height", `${height}px`);
|
|
294
305
|
};
|
|
295
306
|
|
|
307
|
+
const updateHighlightFrameVisibility = (node, nodeProvider) => {
|
|
308
|
+
const frame = getHighlightFrameElement(nodeProvider);
|
|
309
|
+
if (!frame)
|
|
310
|
+
return;
|
|
311
|
+
const hasHiddenClass = node.classList.contains("hidden") || node.classList.contains("select-none");
|
|
312
|
+
frame.style.display = hasHiddenClass ? "none" : "";
|
|
313
|
+
};
|
|
314
|
+
|
|
296
315
|
const disableCanvasKeyboard = () => {
|
|
297
316
|
const disable = getCanvasWindowValue(["keyboard", "disable"]);
|
|
298
317
|
disable?.();
|
|
@@ -429,6 +448,7 @@ const nodeText = () => {
|
|
|
429
448
|
const createNodeTools = (element) => {
|
|
430
449
|
const nodeProvider = element;
|
|
431
450
|
let resizeObserver = null;
|
|
451
|
+
let mutationObserver = null;
|
|
432
452
|
let selectedNode = null;
|
|
433
453
|
const text = nodeText();
|
|
434
454
|
const throttledFrameRefresh = withRAFThrottle(refreshHighlightFrame);
|
|
@@ -441,10 +461,14 @@ const createNodeTools = (element) => {
|
|
|
441
461
|
clearHighlightFrame(nodeProvider);
|
|
442
462
|
selectedNode = null;
|
|
443
463
|
resizeObserver?.disconnect();
|
|
464
|
+
mutationObserver?.disconnect();
|
|
444
465
|
}
|
|
445
466
|
}
|
|
446
467
|
};
|
|
447
468
|
const selectNode = (node) => {
|
|
469
|
+
if (selectedNode === node) {
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
448
472
|
if (text.isEditing()) {
|
|
449
473
|
const currentEditable = text.getEditableNode();
|
|
450
474
|
if (currentEditable && currentEditable !== node) {
|
|
@@ -452,21 +476,34 @@ const createNodeTools = (element) => {
|
|
|
452
476
|
}
|
|
453
477
|
}
|
|
454
478
|
resizeObserver?.disconnect();
|
|
479
|
+
mutationObserver?.disconnect();
|
|
455
480
|
if (node && nodeProvider) {
|
|
456
481
|
text.enableEditMode(node, nodeProvider);
|
|
457
482
|
resizeObserver = connectResizeObserver(nodeProvider, () => {
|
|
458
483
|
throttledFrameRefresh(node, nodeProvider);
|
|
459
484
|
});
|
|
485
|
+
mutationObserver = new MutationObserver(() => {
|
|
486
|
+
throttledFrameRefresh(node, nodeProvider);
|
|
487
|
+
updateHighlightFrameVisibility(node, nodeProvider);
|
|
488
|
+
});
|
|
489
|
+
mutationObserver.observe(node, {
|
|
490
|
+
attributes: true,
|
|
491
|
+
attributeFilter: ["class"],
|
|
492
|
+
});
|
|
460
493
|
}
|
|
461
494
|
selectedNode = node;
|
|
462
495
|
sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
|
|
463
496
|
highlightNode(node, nodeProvider) ?? null;
|
|
497
|
+
if (node && nodeProvider) {
|
|
498
|
+
updateHighlightFrameVisibility(node, nodeProvider);
|
|
499
|
+
}
|
|
464
500
|
};
|
|
465
501
|
// Setup event listener
|
|
466
502
|
const removeListeners = setupEventListener$1(nodeProvider, selectNode, handleEscape, text.getEditableNode);
|
|
467
503
|
const cleanup = () => {
|
|
468
504
|
removeListeners();
|
|
469
505
|
resizeObserver?.disconnect();
|
|
506
|
+
mutationObserver?.disconnect();
|
|
470
507
|
text.blurEditMode();
|
|
471
508
|
throttledFrameRefresh.cleanup();
|
|
472
509
|
};
|
|
@@ -480,6 +517,7 @@ const createNodeTools = (element) => {
|
|
|
480
517
|
clearHighlightFrame(nodeProvider);
|
|
481
518
|
selectedNode = null;
|
|
482
519
|
resizeObserver?.disconnect();
|
|
520
|
+
mutationObserver?.disconnect();
|
|
483
521
|
},
|
|
484
522
|
getEditableNode: () => text.getEditableNode(),
|
|
485
523
|
cleanup,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markup Canvas
|
|
3
3
|
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
-
* @version 2.0.
|
|
4
|
+
* @version 2.0.6
|
|
5
5
|
*/
|
|
6
6
|
// biome-ignore lint/suspicious/noExplicitAny: generic constraint requires flexibility
|
|
7
7
|
function withRAFThrottle(func) {
|
|
@@ -95,13 +95,24 @@ const bindToWindow = (key, value) => {
|
|
|
95
95
|
}
|
|
96
96
|
};
|
|
97
97
|
|
|
98
|
-
const
|
|
98
|
+
const processPostMessage = (event, onNodeSelected) => {
|
|
99
99
|
if (event.data.source === "markup-canvas" && event.data.canvasName === "canvas") {
|
|
100
100
|
if (event.data.action === "zoom") {
|
|
101
101
|
const zoom = event.data.data;
|
|
102
102
|
console.log("zoom", zoom);
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
|
+
if (event.data.source === "application") {
|
|
106
|
+
if (event.data.action === "selectedNodeChanged") {
|
|
107
|
+
const nodeId = event.data.data;
|
|
108
|
+
console.log("selectedNodeChanged in node-edit-utils", nodeId);
|
|
109
|
+
const selectedNode = document.querySelector(`[data-node-id="${nodeId}"]`);
|
|
110
|
+
if (selectedNode) {
|
|
111
|
+
console.log("selectedNode", selectedNode);
|
|
112
|
+
onNodeSelected?.(selectedNode);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
105
116
|
};
|
|
106
117
|
|
|
107
118
|
function getHighlightFrameElement(nodeProvider) {
|
|
@@ -143,7 +154,7 @@ const selectNode = (event, editableNode) => {
|
|
|
143
154
|
const clickX = event.clientX;
|
|
144
155
|
const clickY = event.clientY;
|
|
145
156
|
const clickThrough = event.metaKey || event.ctrlKey;
|
|
146
|
-
const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()));
|
|
157
|
+
const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()) && !element.classList.contains("select-none"));
|
|
147
158
|
if (editableNode && candidates.includes(editableNode)) {
|
|
148
159
|
return editableNode;
|
|
149
160
|
}
|
|
@@ -178,7 +189,7 @@ const handleNodeClick = (event, nodeProvider, editableNode, onNodeSelected) => {
|
|
|
178
189
|
|
|
179
190
|
const setupEventListener$1 = (nodeProvider, onNodeSelected, onEscapePressed, getEditableNode) => {
|
|
180
191
|
const messageHandler = (event) => {
|
|
181
|
-
|
|
192
|
+
processPostMessage(event, onNodeSelected);
|
|
182
193
|
};
|
|
183
194
|
const documentClickHandler = (event) => {
|
|
184
195
|
handleNodeClick(event, nodeProvider, getEditableNode(), onNodeSelected);
|
|
@@ -291,6 +302,14 @@ const refreshHighlightFrame = (node, nodeProvider) => {
|
|
|
291
302
|
frame.style.setProperty("--frame-height", `${height}px`);
|
|
292
303
|
};
|
|
293
304
|
|
|
305
|
+
const updateHighlightFrameVisibility = (node, nodeProvider) => {
|
|
306
|
+
const frame = getHighlightFrameElement(nodeProvider);
|
|
307
|
+
if (!frame)
|
|
308
|
+
return;
|
|
309
|
+
const hasHiddenClass = node.classList.contains("hidden") || node.classList.contains("select-none");
|
|
310
|
+
frame.style.display = hasHiddenClass ? "none" : "";
|
|
311
|
+
};
|
|
312
|
+
|
|
294
313
|
const disableCanvasKeyboard = () => {
|
|
295
314
|
const disable = getCanvasWindowValue(["keyboard", "disable"]);
|
|
296
315
|
disable?.();
|
|
@@ -427,6 +446,7 @@ const nodeText = () => {
|
|
|
427
446
|
const createNodeTools = (element) => {
|
|
428
447
|
const nodeProvider = element;
|
|
429
448
|
let resizeObserver = null;
|
|
449
|
+
let mutationObserver = null;
|
|
430
450
|
let selectedNode = null;
|
|
431
451
|
const text = nodeText();
|
|
432
452
|
const throttledFrameRefresh = withRAFThrottle(refreshHighlightFrame);
|
|
@@ -439,10 +459,14 @@ const createNodeTools = (element) => {
|
|
|
439
459
|
clearHighlightFrame(nodeProvider);
|
|
440
460
|
selectedNode = null;
|
|
441
461
|
resizeObserver?.disconnect();
|
|
462
|
+
mutationObserver?.disconnect();
|
|
442
463
|
}
|
|
443
464
|
}
|
|
444
465
|
};
|
|
445
466
|
const selectNode = (node) => {
|
|
467
|
+
if (selectedNode === node) {
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
446
470
|
if (text.isEditing()) {
|
|
447
471
|
const currentEditable = text.getEditableNode();
|
|
448
472
|
if (currentEditable && currentEditable !== node) {
|
|
@@ -450,21 +474,34 @@ const createNodeTools = (element) => {
|
|
|
450
474
|
}
|
|
451
475
|
}
|
|
452
476
|
resizeObserver?.disconnect();
|
|
477
|
+
mutationObserver?.disconnect();
|
|
453
478
|
if (node && nodeProvider) {
|
|
454
479
|
text.enableEditMode(node, nodeProvider);
|
|
455
480
|
resizeObserver = connectResizeObserver(nodeProvider, () => {
|
|
456
481
|
throttledFrameRefresh(node, nodeProvider);
|
|
457
482
|
});
|
|
483
|
+
mutationObserver = new MutationObserver(() => {
|
|
484
|
+
throttledFrameRefresh(node, nodeProvider);
|
|
485
|
+
updateHighlightFrameVisibility(node, nodeProvider);
|
|
486
|
+
});
|
|
487
|
+
mutationObserver.observe(node, {
|
|
488
|
+
attributes: true,
|
|
489
|
+
attributeFilter: ["class"],
|
|
490
|
+
});
|
|
458
491
|
}
|
|
459
492
|
selectedNode = node;
|
|
460
493
|
sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
|
|
461
494
|
highlightNode(node, nodeProvider) ?? null;
|
|
495
|
+
if (node && nodeProvider) {
|
|
496
|
+
updateHighlightFrameVisibility(node, nodeProvider);
|
|
497
|
+
}
|
|
462
498
|
};
|
|
463
499
|
// Setup event listener
|
|
464
500
|
const removeListeners = setupEventListener$1(nodeProvider, selectNode, handleEscape, text.getEditableNode);
|
|
465
501
|
const cleanup = () => {
|
|
466
502
|
removeListeners();
|
|
467
503
|
resizeObserver?.disconnect();
|
|
504
|
+
mutationObserver?.disconnect();
|
|
468
505
|
text.blurEditMode();
|
|
469
506
|
throttledFrameRefresh.cleanup();
|
|
470
507
|
};
|
|
@@ -478,6 +515,7 @@ const createNodeTools = (element) => {
|
|
|
478
515
|
clearHighlightFrame(nodeProvider);
|
|
479
516
|
selectedNode = null;
|
|
480
517
|
resizeObserver?.disconnect();
|
|
518
|
+
mutationObserver?.disconnect();
|
|
481
519
|
},
|
|
482
520
|
getEditableNode: () => text.getEditableNode(),
|
|
483
521
|
cleanup,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markup Canvas
|
|
3
3
|
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
-
* @version 2.0.
|
|
4
|
+
* @version 2.0.6
|
|
5
5
|
*/
|
|
6
6
|
(function (global, factory) {
|
|
7
7
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
@@ -101,13 +101,24 @@
|
|
|
101
101
|
}
|
|
102
102
|
};
|
|
103
103
|
|
|
104
|
-
const
|
|
104
|
+
const processPostMessage = (event, onNodeSelected) => {
|
|
105
105
|
if (event.data.source === "markup-canvas" && event.data.canvasName === "canvas") {
|
|
106
106
|
if (event.data.action === "zoom") {
|
|
107
107
|
const zoom = event.data.data;
|
|
108
108
|
console.log("zoom", zoom);
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
+
if (event.data.source === "application") {
|
|
112
|
+
if (event.data.action === "selectedNodeChanged") {
|
|
113
|
+
const nodeId = event.data.data;
|
|
114
|
+
console.log("selectedNodeChanged in node-edit-utils", nodeId);
|
|
115
|
+
const selectedNode = document.querySelector(`[data-node-id="${nodeId}"]`);
|
|
116
|
+
if (selectedNode) {
|
|
117
|
+
console.log("selectedNode", selectedNode);
|
|
118
|
+
onNodeSelected?.(selectedNode);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
111
122
|
};
|
|
112
123
|
|
|
113
124
|
function getHighlightFrameElement(nodeProvider) {
|
|
@@ -149,7 +160,7 @@
|
|
|
149
160
|
const clickX = event.clientX;
|
|
150
161
|
const clickY = event.clientY;
|
|
151
162
|
const clickThrough = event.metaKey || event.ctrlKey;
|
|
152
|
-
const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()));
|
|
163
|
+
const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()) && !element.classList.contains("select-none"));
|
|
153
164
|
if (editableNode && candidates.includes(editableNode)) {
|
|
154
165
|
return editableNode;
|
|
155
166
|
}
|
|
@@ -184,7 +195,7 @@
|
|
|
184
195
|
|
|
185
196
|
const setupEventListener$1 = (nodeProvider, onNodeSelected, onEscapePressed, getEditableNode) => {
|
|
186
197
|
const messageHandler = (event) => {
|
|
187
|
-
|
|
198
|
+
processPostMessage(event, onNodeSelected);
|
|
188
199
|
};
|
|
189
200
|
const documentClickHandler = (event) => {
|
|
190
201
|
handleNodeClick(event, nodeProvider, getEditableNode(), onNodeSelected);
|
|
@@ -297,6 +308,14 @@
|
|
|
297
308
|
frame.style.setProperty("--frame-height", `${height}px`);
|
|
298
309
|
};
|
|
299
310
|
|
|
311
|
+
const updateHighlightFrameVisibility = (node, nodeProvider) => {
|
|
312
|
+
const frame = getHighlightFrameElement(nodeProvider);
|
|
313
|
+
if (!frame)
|
|
314
|
+
return;
|
|
315
|
+
const hasHiddenClass = node.classList.contains("hidden") || node.classList.contains("select-none");
|
|
316
|
+
frame.style.display = hasHiddenClass ? "none" : "";
|
|
317
|
+
};
|
|
318
|
+
|
|
300
319
|
const disableCanvasKeyboard = () => {
|
|
301
320
|
const disable = getCanvasWindowValue(["keyboard", "disable"]);
|
|
302
321
|
disable?.();
|
|
@@ -433,6 +452,7 @@
|
|
|
433
452
|
const createNodeTools = (element) => {
|
|
434
453
|
const nodeProvider = element;
|
|
435
454
|
let resizeObserver = null;
|
|
455
|
+
let mutationObserver = null;
|
|
436
456
|
let selectedNode = null;
|
|
437
457
|
const text = nodeText();
|
|
438
458
|
const throttledFrameRefresh = withRAFThrottle(refreshHighlightFrame);
|
|
@@ -445,10 +465,14 @@
|
|
|
445
465
|
clearHighlightFrame(nodeProvider);
|
|
446
466
|
selectedNode = null;
|
|
447
467
|
resizeObserver?.disconnect();
|
|
468
|
+
mutationObserver?.disconnect();
|
|
448
469
|
}
|
|
449
470
|
}
|
|
450
471
|
};
|
|
451
472
|
const selectNode = (node) => {
|
|
473
|
+
if (selectedNode === node) {
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
452
476
|
if (text.isEditing()) {
|
|
453
477
|
const currentEditable = text.getEditableNode();
|
|
454
478
|
if (currentEditable && currentEditable !== node) {
|
|
@@ -456,21 +480,34 @@
|
|
|
456
480
|
}
|
|
457
481
|
}
|
|
458
482
|
resizeObserver?.disconnect();
|
|
483
|
+
mutationObserver?.disconnect();
|
|
459
484
|
if (node && nodeProvider) {
|
|
460
485
|
text.enableEditMode(node, nodeProvider);
|
|
461
486
|
resizeObserver = connectResizeObserver(nodeProvider, () => {
|
|
462
487
|
throttledFrameRefresh(node, nodeProvider);
|
|
463
488
|
});
|
|
489
|
+
mutationObserver = new MutationObserver(() => {
|
|
490
|
+
throttledFrameRefresh(node, nodeProvider);
|
|
491
|
+
updateHighlightFrameVisibility(node, nodeProvider);
|
|
492
|
+
});
|
|
493
|
+
mutationObserver.observe(node, {
|
|
494
|
+
attributes: true,
|
|
495
|
+
attributeFilter: ["class"],
|
|
496
|
+
});
|
|
464
497
|
}
|
|
465
498
|
selectedNode = node;
|
|
466
499
|
sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
|
|
467
500
|
highlightNode(node, nodeProvider) ?? null;
|
|
501
|
+
if (node && nodeProvider) {
|
|
502
|
+
updateHighlightFrameVisibility(node, nodeProvider);
|
|
503
|
+
}
|
|
468
504
|
};
|
|
469
505
|
// Setup event listener
|
|
470
506
|
const removeListeners = setupEventListener$1(nodeProvider, selectNode, handleEscape, text.getEditableNode);
|
|
471
507
|
const cleanup = () => {
|
|
472
508
|
removeListeners();
|
|
473
509
|
resizeObserver?.disconnect();
|
|
510
|
+
mutationObserver?.disconnect();
|
|
474
511
|
text.blurEditMode();
|
|
475
512
|
throttledFrameRefresh.cleanup();
|
|
476
513
|
};
|
|
@@ -484,6 +521,7 @@
|
|
|
484
521
|
clearHighlightFrame(nodeProvider);
|
|
485
522
|
selectedNode = null;
|
|
486
523
|
resizeObserver?.disconnect();
|
|
524
|
+
mutationObserver?.disconnect();
|
|
487
525
|
},
|
|
488
526
|
getEditableNode: () => text.getEditableNode(),
|
|
489
527
|
cleanup,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).MarkupCanvas={})}(this,function(e){"use strict";function t(e){let t=null,n=null;const o=(...o)=>{n=o,null===t&&(t=requestAnimationFrame(()=>{n&&e(...n),t=null,n=null}))};return o.cleanup=()=>{null!==t&&(cancelAnimationFrame(t),t=null,n=null)},o}const n=e=>{const t=window.canvas;return e.reduce((e,t)=>e?.[t],t)};function o(e){return e.querySelector(".highlight-frame")}const r=e=>{if(!e)return;const t=o(e);t&&t.remove()},s=["path","rect","circle","ellipse","polygon","line","polyline","text","text-noci"];let a=[],i=0;const l=(e,t)=>{let n=null;const o=e.clientX,r=e.clientY,l=e.metaKey||e.ctrlKey,d=((e,t)=>{const n=document.elementsFromPoint(e,t);return Array.from(n).reduce((e,t)=>e.found?e:"node-provider"===t.getAttribute("data-role")?(e.found=!0,e):(e.elements.push(t),e),{elements:[],found:!1}).elements})(o,r).filter(e=>!s.includes(e.tagName.toLowerCase()));if(t&&d.includes(t))return t;if(l)return a=[],n=d[0],n;var c,u;u=d,(c=a).length===u.length&&c.every((e,t)=>e===u[t])?i<=d.length&&i++:i=0;return n=d[d.length-1-i],a=d,n},d=(e,t,n,o)=>{const s=e=>{(e=>{if("markup-canvas"===e.data.source&&"canvas"===e.data.canvasName&&"zoom"===e.data.action){const t=e.data.data;console.log("zoom",t)}})(e)},a=n=>{((e,t,n,o)=>{if(e.preventDefault(),e.stopPropagation(),t&&!t.contains(e.target))return r(t),void o(null);o(l(e,n))})(n,e,o(),t)},i=e=>{"Escape"===e.key&&(e.preventDefault(),e.stopPropagation(),n?.())};return window.addEventListener("message",s),document.addEventListener("click",a),document.addEventListener("keydown",i),()=>{window.removeEventListener("message",s),document.removeEventListener("click",a),document.removeEventListener("keydown",i)}};function c(e,t){const o=e.getBoundingClientRect(),r=t.getBoundingClientRect(),s=o.top-r.top,a=o.left-r.left,i=n(["zoom","current"])??1;return{top:parseFloat((s/i).toFixed(5)),left:parseFloat((a/i).toFixed(5)),width:Math.max(4,parseFloat((o.width/i).toFixed(5))),height:parseFloat((o.height/i).toFixed(5))}}const u=(e,t)=>{const n=document.createElement("div");n.className="node-tools",t.appendChild(n),((e,t)=>{const n=document.createElement("div");n.className="tag-label",n.textContent=e.tagName.toLowerCase(),t.appendChild(n)})(e,n)},m=(e,t)=>{if(!e)return;const r=o(t);r&&r.remove();const s=((e,t)=>{const{top:o,left:r,width:s,height:a}=c(e,t),i=n(["zoom","current"])??1;document.body.style.setProperty("--zoom",i.toString()),document.body.style.setProperty("--stroke-width",(2/i).toFixed(3));const l=document.createElement("div");l.classList.add("highlight-frame"),l.style.setProperty("--frame-top",`${o}px`),l.style.setProperty("--frame-left",`${r}px`),l.style.setProperty("--frame-width",`${s}px`),l.style.setProperty("--frame-height",`${a}px`);const d=document.createElementNS("http://www.w3.org/2000/svg","svg");d.classList.add("highlight-frame-svg");const u=document.createElementNS("http://www.w3.org/2000/svg","rect");return u.setAttribute("x","0"),u.setAttribute("y","0"),u.setAttribute("width","100%"),u.setAttribute("height","100%"),u.classList.add("highlight-frame-rect"),d.appendChild(u),l.appendChild(d),l})(e,t);"true"===e.contentEditable&&s.classList.add("is-editable"),u(e,s),t.appendChild(s)},p=(e,t)=>{const r=o(t),s=n(["zoom","current"])??1;if(!r)return;s>=.3?t.style.setProperty("--tool-opacity","1"):t.style.setProperty("--tool-opacity","0");const{top:a,left:i,width:l,height:d}=c(e,t);r.style.setProperty("--frame-top",`${a}px`),r.style.setProperty("--frame-left",`${i}px`),r.style.setProperty("--frame-width",`${l}px`),r.style.setProperty("--frame-height",`${d}px`)},v=e=>{const t=e=>{"Enter"===e.key&&(e.preventDefault(),e.stopPropagation(),(()=>{const e=window.getSelection();if(e&&e.rangeCount>0){const t=e.getRangeAt(0);t.deleteContents();const n=document.createElement("br");t.insertNode(n),t.setStartAfter(n),t.setEndAfter(n),e.removeAllRanges(),e.addRange(t)}})())};return e.addEventListener("keydown",t),()=>{e.removeEventListener("keydown",t)}},
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).MarkupCanvas={})}(this,function(e){"use strict";function t(e){let t=null,n=null;const o=(...o)=>{n=o,null===t&&(t=requestAnimationFrame(()=>{n&&e(...n),t=null,n=null}))};return o.cleanup=()=>{null!==t&&(cancelAnimationFrame(t),t=null,n=null)},o}const n=e=>{const t=window.canvas;return e.reduce((e,t)=>e?.[t],t)};function o(e){return e.querySelector(".highlight-frame")}const r=e=>{if(!e)return;const t=o(e);t&&t.remove()},s=["path","rect","circle","ellipse","polygon","line","polyline","text","text-noci"];let a=[],i=0;const l=(e,t)=>{let n=null;const o=e.clientX,r=e.clientY,l=e.metaKey||e.ctrlKey,d=((e,t)=>{const n=document.elementsFromPoint(e,t);return Array.from(n).reduce((e,t)=>e.found?e:"node-provider"===t.getAttribute("data-role")?(e.found=!0,e):(e.elements.push(t),e),{elements:[],found:!1}).elements})(o,r).filter(e=>!s.includes(e.tagName.toLowerCase())&&!e.classList.contains("select-none"));if(t&&d.includes(t))return t;if(l)return a=[],n=d[0],n;var c,u;u=d,(c=a).length===u.length&&c.every((e,t)=>e===u[t])?i<=d.length&&i++:i=0;return n=d[d.length-1-i],a=d,n},d=(e,t,n,o)=>{const s=e=>{((e,t)=>{if("markup-canvas"===e.data.source&&"canvas"===e.data.canvasName&&"zoom"===e.data.action){const t=e.data.data;console.log("zoom",t)}if("application"===e.data.source&&"selectedNodeChanged"===e.data.action){const n=e.data.data;console.log("selectedNodeChanged in node-edit-utils",n);const o=document.querySelector(`[data-node-id="${n}"]`);o&&(console.log("selectedNode",o),t?.(o))}})(e,t)},a=n=>{((e,t,n,o)=>{if(e.preventDefault(),e.stopPropagation(),t&&!t.contains(e.target))return r(t),void o(null);o(l(e,n))})(n,e,o(),t)},i=e=>{"Escape"===e.key&&(e.preventDefault(),e.stopPropagation(),n?.())};return window.addEventListener("message",s),document.addEventListener("click",a),document.addEventListener("keydown",i),()=>{window.removeEventListener("message",s),document.removeEventListener("click",a),document.removeEventListener("keydown",i)}};function c(e,t){const o=e.getBoundingClientRect(),r=t.getBoundingClientRect(),s=o.top-r.top,a=o.left-r.left,i=n(["zoom","current"])??1;return{top:parseFloat((s/i).toFixed(5)),left:parseFloat((a/i).toFixed(5)),width:Math.max(4,parseFloat((o.width/i).toFixed(5))),height:parseFloat((o.height/i).toFixed(5))}}const u=(e,t)=>{const n=document.createElement("div");n.className="node-tools",t.appendChild(n),((e,t)=>{const n=document.createElement("div");n.className="tag-label",n.textContent=e.tagName.toLowerCase(),t.appendChild(n)})(e,n)},m=(e,t)=>{if(!e)return;const r=o(t);r&&r.remove();const s=((e,t)=>{const{top:o,left:r,width:s,height:a}=c(e,t),i=n(["zoom","current"])??1;document.body.style.setProperty("--zoom",i.toString()),document.body.style.setProperty("--stroke-width",(2/i).toFixed(3));const l=document.createElement("div");l.classList.add("highlight-frame"),l.style.setProperty("--frame-top",`${o}px`),l.style.setProperty("--frame-left",`${r}px`),l.style.setProperty("--frame-width",`${s}px`),l.style.setProperty("--frame-height",`${a}px`);const d=document.createElementNS("http://www.w3.org/2000/svg","svg");d.classList.add("highlight-frame-svg");const u=document.createElementNS("http://www.w3.org/2000/svg","rect");return u.setAttribute("x","0"),u.setAttribute("y","0"),u.setAttribute("width","100%"),u.setAttribute("height","100%"),u.classList.add("highlight-frame-rect"),d.appendChild(u),l.appendChild(d),l})(e,t);"true"===e.contentEditable&&s.classList.add("is-editable"),u(e,s),t.appendChild(s)},p=(e,t)=>{const r=o(t),s=n(["zoom","current"])??1;if(!r)return;s>=.3?t.style.setProperty("--tool-opacity","1"):t.style.setProperty("--tool-opacity","0");const{top:a,left:i,width:l,height:d}=c(e,t);r.style.setProperty("--frame-top",`${a}px`),r.style.setProperty("--frame-left",`${i}px`),r.style.setProperty("--frame-width",`${l}px`),r.style.setProperty("--frame-height",`${d}px`)},v=(e,t)=>{const n=o(t);if(!n)return;const r=e.classList.contains("hidden")||e.classList.contains("select-none");n.style.display=r?"none":""},h=e=>{const t=e=>{"Enter"===e.key&&(e.preventDefault(),e.stopPropagation(),(()=>{const e=window.getSelection();if(e&&e.rangeCount>0){const t=e.getRangeAt(0);t.deleteContents();const n=document.createElement("br");t.insertNode(n),t.setStartAfter(n),t.setEndAfter(n),e.removeAllRanges(),e.addRange(t)}})())};return e.addEventListener("keydown",t),()=>{e.removeEventListener("keydown",t)}},f=(e,t)=>{const n=((e,t)=>{const n=new MutationObserver(e=>{t(e)});return n.observe(e,{subtree:!0,childList:!0,characterData:!0}),n})(e,()=>{p(e,t)});return()=>n.disconnect()},y=()=>{let e=null,t=!1,o=null;const r=()=>{if(t||!e)return;t=!0;var r;(r=e).contentEditable="false",r.classList.remove("is-editable"),r.style.outline="none",(()=>{const e=n(["keyboard","enable"]);e?.()})(),o?.(),e=null,t=!1};return{enableEditMode:(t,s)=>{if(e===t)return;e&&e!==t&&r();const a=(e=>Array.from(e.childNodes).some(e=>e.nodeType===Node.TEXT_NODE&&e.textContent?.trim()))(t);a&&(e=t,(e=>{e.contentEditable="true",e.classList.add("is-editable"),e.style.outline="none"})(t),(()=>{const e=n(["keyboard","disable"]);e?.()})(),o=((e,t,n)=>{if(!t)return()=>{};e.addEventListener("blur",n);const o=h(e),r=f(e,t);return()=>{e.removeEventListener("blur",n),o(),r?.()}})(t,s,r))},blurEditMode:r,getEditableNode:()=>e,isEditing:()=>null!==e}},g=320,b=1680,w=[{name:"Mobile",rawValue:390,value:"320px"},{name:"Tablet Portrait",rawValue:768,value:"768px"},{name:"Tablet Landscape",rawValue:1024,value:"1024px"},{name:"Notebook",rawValue:1280,value:"1280px"},{name:"Desktop",rawValue:1680,value:"1680px"}],E=(e,t,n)=>{const o=parseFloat(document.body.dataset.zoom||"1"),r=((e,t)=>{const n=e+Math.round(t);return Math.max(g,Math.min(b,n))})(n,(e.clientX-t)/o);return r},x=(e,t)=>{e.style.setProperty("--container-width",`${t}px`),((e,t)=>{console.log("updateActivePreset",t);const n=e.querySelectorAll(".resize-preset-button");console.log("presetButtons",n),n.forEach((e,n)=>{n<w.length&&(w[n].rawValue===t?e.classList.add("is-active"):e.classList.remove("is-active"))})})(e,t)};e.createCanvasObserver=function(){const e=document.querySelector(".transform-layer");if(!e)return{disconnect:()=>{}};const o=t(()=>{(()=>{const e=n(["zoom","current"]);document.body.style.setProperty("--zoom",e.toFixed(5)),document.body.style.setProperty("--stroke-width",(2/e).toFixed(3)),document.body.dataset.zoom=e.toFixed(5),document.body.dataset.strokeWidth=(2/e).toFixed(3)})()}),r=new MutationObserver(()=>{o()});return r.observe(e,{attributes:!0,attributeOldValue:!0,subtree:!0,childList:!0}),{disconnect:function(){o.cleanup(),r.disconnect()}}},e.createNodeTools=e=>{const n=e;let o=null,s=null,a=null;const i=y(),l=t(p),c=e=>{if(a!==e){if(i.isEditing()){const t=i.getEditableNode();t&&t!==e&&i.blurEditMode()}var t,r;o?.disconnect(),s?.disconnect(),e&&n&&(i.enableEditMode(e,n),o=((e,t)=>{const n=new ResizeObserver(e=>{t(e)});return n.observe(e),n})(n,()=>{l(e,n)}),s=new MutationObserver(()=>{l(e,n),v(e,n)}),s.observe(e,{attributes:!0,attributeFilter:["class"]})),a=e,t="selectedNodeChanged",r=e?.getAttribute("data-node-id")??null,window.parent.postMessage({source:"node-edit-utils",action:t,data:r,timestamp:Date.now()},"*"),m(e,n),e&&n&&v(e,n)}},u=d(n,c,()=>{i.isEditing()&&i.blurEditMode(),a&&n&&(r(n),a=null,o?.disconnect(),s?.disconnect())},i.getEditableNode),h={selectNode:c,getSelectedNode:()=>a,refreshHighlightFrame:()=>{l(a,n)},clearSelectedNode:()=>{r(n),a=null,o?.disconnect(),s?.disconnect()},getEditableNode:()=>i.getEditableNode(),cleanup:()=>{u(),o?.disconnect(),s?.disconnect(),i.blurEditMode(),l.cleanup()}};var f,g;return f="nodeTools",g=h,"undefined"!=typeof window&&(window[f]=g),h},e.createViewport=e=>{const n=document.querySelector(".canvas-container"),o=e.querySelector(".resize-handle");o&&o.remove();const r=(e=>{const t=document.createElement("div");return t.className="resize-handle",e.appendChild(t),t})(e);e.style.setProperty("--container-width","400px"),((e,t,n)=>{const o=document.createElement("div");o.className="resize-presets",w.forEach(e=>{const r=document.createElement("button");r.textContent=e.name,r.className="resize-preset-button",r.addEventListener("click",()=>{n(t,e.rawValue)}),o.appendChild(r)}),e.appendChild(o)})(r,e,x);let s=!1,a=0,i=0;const l=t(t=>{if(!s)return;n&&(n.style.cursor="ew-resize");const o=E(t,a,i);x(e,o)}),d=((e,t,n,o,r)=>(e.addEventListener("mousedown",t),document.addEventListener("mousemove",n),document.addEventListener("mouseup",o),window.addEventListener("blur",r),()=>{e.removeEventListener("mousedown",t),document.removeEventListener("mousemove",n),document.removeEventListener("mouseup",o),window.removeEventListener("blur",r)}))(r,t=>{t.preventDefault(),t.stopPropagation(),s=!0,a=t.clientX,i=e.offsetWidth},l,e=>{e.preventDefault(),e.stopPropagation(),n&&(n.style.cursor="default"),s=!1},()=>{s=!1});return{setWidth:t=>{x(e,t)},cleanup:()=>{s=!1,l?.cleanup(),d(),r.remove()}}}});
|
package/dist/styles.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.node-provider{::selection{background:transparent}::-moz-selection{background:transparent}::-webkit-selection{background:transparent}}.node-tools{bottom:0;display:flex;gap:.25rem;justify-content:center;left:0;opacity:var(--tool-opacity);padding-top:.25rem;position:absolute;transform:scale(calc(1/var(--zoom))) translate3d(0,100%,0);transform-origin:bottom left;transition:opacity .1s ease;z-index:10000}.highlight-frame{height:var(--frame-height);left:var(--frame-left);pointer-events:none;position:absolute;top:var(--frame-top);width:var(--frame-width);z-index:1000}.highlight-frame-svg{height:100%;left:0;overflow:visible;position:absolute;top:0;width:100%}.highlight-frame-rect{fill:none;stroke:oklch(
|
|
1
|
+
.node-provider{::selection{background:transparent}::-moz-selection{background:transparent}::-webkit-selection{background:transparent}}.node-tools{bottom:0;display:flex;gap:.25rem;justify-content:center;left:0;opacity:var(--tool-opacity);padding-top:.25rem;position:absolute;top:0;transform:scale(calc(1/var(--zoom))) translate3d(0,100%,0);transform-origin:bottom left;transition:opacity .1s ease;z-index:10000}.highlight-frame{font-family:Manrope,sans-serif;height:var(--frame-height);left:var(--frame-left);letter-spacing:.02em;pointer-events:none;position:absolute;top:var(--frame-top);width:var(--frame-width);z-index:1000}.highlight-frame-svg{height:100%;left:0;overflow:visible;position:absolute;top:0;width:100%}.highlight-frame-rect{fill:none;stroke:oklch(45.7% .24 277.023);stroke-width:var(--stroke-width)}.tag-label{align-items:center;background-color:oklch(45.7% .24 277.023);border-radius:.375rem;color:#fff;display:flex;font-size:.575rem;font-weight:500;height:1.25rem;justify-content:center;line-height:1;padding:0 .375rem;text-transform:uppercase}.viewport{position:relative;width:var(--container-width)}.resize-handle{align-items:center;cursor:ew-resize;display:flex;height:40px;justify-content:center;opacity:0;pointer-events:auto;position:absolute;right:-12px;top:1.25rem;transform:scale(calc(1/var(--zoom)));transform-origin:top left;transition:opacity .1s ease-in-out,visibility .1s ease-in-out;visibility:hidden;width:12px;z-index:10000}.viewport:hover .resize-handle{opacity:1;visibility:visible}.resize-handle:before{background:oklch(55.2% .016 285.938);border-radius:4px;content:"";height:32px;position:relative;right:0;top:0;transition:transform .2s ease-in-out;width:3px}.resize-handle:hover:before{transform:scaleY(1.3)}.resize-presets{display:flex;flex-direction:column;font-family:Manrope,sans-serif;gap:.25rem;left:0;letter-spacing:.02em;opacity:0;padding-left:1.25rem;position:absolute;top:0;transition:visibility .1s ease-in-out,opacity .1s ease-in-out;visibility:hidden}.resize-handle:hover .resize-presets{opacity:1;visibility:visible}.resize-preset-button{text-wrap:nowrap;backdrop-filter:blur(8px);background:oklch(55.2% .016 285.938/.7);border:none;border-radius:.5rem;color:#fff;cursor:pointer;font-size:.6875rem;padding:.25rem .5rem;text-align:left;transition:background .1s ease-in-out;width:fit-content;&:hover{background:oklch(55.2% .016 285.938/1)}&.is-active{background:oklch(45.7% .24 277.023)}}.is-editable{outline:none;user-select:text;&::selection{background:oklch(62.7% .265 303.9/.3)}&::-moz-selection{background:oklch(62.7% .265 303.9/.3)}&::-webkit-selection{background:oklch(62.7% .265 303.9/.3)}}
|
package/package.json
CHANGED
|
@@ -6,6 +6,7 @@ import { setupEventListener } from "./events/setupEventListener";
|
|
|
6
6
|
import { clearHighlightFrame } from "./highlight/clearHighlightFrame";
|
|
7
7
|
import { highlightNode } from "./highlight/highlightNode";
|
|
8
8
|
import { refreshHighlightFrame } from "./highlight/refreshHighlightFrame";
|
|
9
|
+
import { updateHighlightFrameVisibility } from "./highlight/updateHighlightFrameVisibility";
|
|
9
10
|
import { nodeText } from "./text/nodeText";
|
|
10
11
|
import type { NodeTools } from "./types";
|
|
11
12
|
|
|
@@ -13,6 +14,7 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
|
|
|
13
14
|
const nodeProvider = element;
|
|
14
15
|
|
|
15
16
|
let resizeObserver: ResizeObserver | null = null;
|
|
17
|
+
let mutationObserver: MutationObserver | null = null;
|
|
16
18
|
let selectedNode: HTMLElement | null = null;
|
|
17
19
|
|
|
18
20
|
const text = nodeText();
|
|
@@ -29,11 +31,16 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
|
|
|
29
31
|
selectedNode = null;
|
|
30
32
|
|
|
31
33
|
resizeObserver?.disconnect();
|
|
34
|
+
mutationObserver?.disconnect();
|
|
32
35
|
}
|
|
33
36
|
}
|
|
34
37
|
};
|
|
35
38
|
|
|
36
39
|
const selectNode = (node: HTMLElement | null): void => {
|
|
40
|
+
if (selectedNode === node) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
37
44
|
if (text.isEditing()) {
|
|
38
45
|
const currentEditable = text.getEditableNode();
|
|
39
46
|
if (currentEditable && currentEditable !== node) {
|
|
@@ -42,6 +49,7 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
|
|
|
42
49
|
}
|
|
43
50
|
|
|
44
51
|
resizeObserver?.disconnect();
|
|
52
|
+
mutationObserver?.disconnect();
|
|
45
53
|
|
|
46
54
|
if (node && nodeProvider) {
|
|
47
55
|
text.enableEditMode(node, nodeProvider);
|
|
@@ -49,11 +57,25 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
|
|
|
49
57
|
resizeObserver = connectResizeObserver(nodeProvider, () => {
|
|
50
58
|
throttledFrameRefresh(node, nodeProvider);
|
|
51
59
|
});
|
|
60
|
+
|
|
61
|
+
mutationObserver = new MutationObserver(() => {
|
|
62
|
+
throttledFrameRefresh(node, nodeProvider);
|
|
63
|
+
updateHighlightFrameVisibility(node, nodeProvider);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
mutationObserver.observe(node, {
|
|
67
|
+
attributes: true,
|
|
68
|
+
attributeFilter: ["class"],
|
|
69
|
+
});
|
|
52
70
|
}
|
|
53
71
|
|
|
54
72
|
selectedNode = node;
|
|
55
73
|
sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
|
|
56
74
|
highlightNode(node, nodeProvider as HTMLElement) ?? null;
|
|
75
|
+
|
|
76
|
+
if (node && nodeProvider) {
|
|
77
|
+
updateHighlightFrameVisibility(node, nodeProvider);
|
|
78
|
+
}
|
|
57
79
|
};
|
|
58
80
|
|
|
59
81
|
// Setup event listener
|
|
@@ -62,6 +84,7 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
|
|
|
62
84
|
const cleanup = (): void => {
|
|
63
85
|
removeListeners();
|
|
64
86
|
resizeObserver?.disconnect();
|
|
87
|
+
mutationObserver?.disconnect();
|
|
65
88
|
|
|
66
89
|
text.blurEditMode();
|
|
67
90
|
throttledFrameRefresh.cleanup();
|
|
@@ -77,6 +100,7 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
|
|
|
77
100
|
clearHighlightFrame(nodeProvider);
|
|
78
101
|
selectedNode = null;
|
|
79
102
|
resizeObserver?.disconnect();
|
|
103
|
+
mutationObserver?.disconnect();
|
|
80
104
|
},
|
|
81
105
|
getEditableNode: () => text.getEditableNode(),
|
|
82
106
|
cleanup,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { processPostMessage } from "@/lib/post-message/processPostMessage";
|
|
2
2
|
import { handleNodeClick } from "./click/handleNodeClick";
|
|
3
3
|
|
|
4
4
|
export const setupEventListener = (
|
|
@@ -8,7 +8,7 @@ export const setupEventListener = (
|
|
|
8
8
|
getEditableNode: () => HTMLElement | null
|
|
9
9
|
): (() => void) => {
|
|
10
10
|
const messageHandler = (event: MessageEvent) => {
|
|
11
|
-
|
|
11
|
+
processPostMessage(event, onNodeSelected);
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
const documentClickHandler = (event: MouseEvent) => {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getHighlightFrameElement } from "./helpers/getHighlightFrameElement";
|
|
2
|
+
|
|
3
|
+
export const updateHighlightFrameVisibility = (node: HTMLElement, nodeProvider: HTMLElement): void => {
|
|
4
|
+
const frame = getHighlightFrameElement(nodeProvider);
|
|
5
|
+
if (!frame) return;
|
|
6
|
+
|
|
7
|
+
const hasHiddenClass = node.classList.contains("hidden") || node.classList.contains("select-none");
|
|
8
|
+
frame.style.display = hasHiddenClass ? "none" : "";
|
|
9
|
+
};
|
|
10
|
+
|
|
@@ -14,7 +14,7 @@ export const selectNode = (event: MouseEvent, editableNode: HTMLElement | null):
|
|
|
14
14
|
const clickThrough = event.metaKey || event.ctrlKey;
|
|
15
15
|
|
|
16
16
|
const candidates = getElementsFromPoint(clickX, clickY).filter(
|
|
17
|
-
(element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase())
|
|
17
|
+
(element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()) && !element.classList.contains("select-none")
|
|
18
18
|
);
|
|
19
19
|
|
|
20
20
|
if (editableNode && candidates.includes(editableNode)) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const processPostMessage = (event: MessageEvent, onNodeSelected?: (node: HTMLElement | null) => void) => {
|
|
2
|
+
if (event.data.source === "markup-canvas" && event.data.canvasName === "canvas") {
|
|
3
|
+
if (event.data.action === "zoom") {
|
|
4
|
+
const zoom = event.data.data;
|
|
5
|
+
console.log("zoom", zoom);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (event.data.source === "application") {
|
|
10
|
+
if (event.data.action === "selectedNodeChanged") {
|
|
11
|
+
const nodeId = event.data.data;
|
|
12
|
+
console.log("selectedNodeChanged in node-edit-utils", nodeId);
|
|
13
|
+
const selectedNode = document.querySelector(`[data-node-id="${nodeId}"]`);
|
|
14
|
+
|
|
15
|
+
if (selectedNode) {
|
|
16
|
+
console.log("selectedNode", selectedNode);
|
|
17
|
+
onNodeSelected?.(selectedNode as HTMLElement);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
};
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
position: absolute;
|
|
17
17
|
left: 0;
|
|
18
18
|
bottom: 0;
|
|
19
|
+
top: 0;
|
|
19
20
|
gap: 0.25rem;
|
|
20
21
|
z-index: 10000;
|
|
21
22
|
transform: scale(calc(1 / var(--zoom))) translate3d(0, 100%, 0);
|
|
@@ -35,6 +36,8 @@
|
|
|
35
36
|
height: var(--frame-height);
|
|
36
37
|
z-index: 1000;
|
|
37
38
|
pointer-events: none;
|
|
39
|
+
font-family: "Manrope", sans-serif;
|
|
40
|
+
letter-spacing: 0.02em;
|
|
38
41
|
/* outline: calc(0.125em / var(--zoom)) solid oklch(62.7% 0.265 303.9); */
|
|
39
42
|
}
|
|
40
43
|
|
|
@@ -49,12 +52,12 @@
|
|
|
49
52
|
|
|
50
53
|
.highlight-frame-rect {
|
|
51
54
|
fill: none;
|
|
52
|
-
stroke: oklch(
|
|
55
|
+
stroke: oklch(45.7% 0.24 277.023);
|
|
53
56
|
stroke-width: var(--stroke-width);
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
.tag-label {
|
|
57
|
-
background-color: oklch(
|
|
60
|
+
background-color: oklch(45.7% 0.24 277.023);
|
|
58
61
|
color: white;
|
|
59
62
|
font-size: 0.575rem;
|
|
60
63
|
font-weight: 500;
|
|
@@ -125,6 +128,8 @@
|
|
|
125
128
|
gap: 0.25rem;
|
|
126
129
|
visibility: hidden;
|
|
127
130
|
opacity: 0;
|
|
131
|
+
font-family: "Manrope", sans-serif;
|
|
132
|
+
letter-spacing: 0.02em;
|
|
128
133
|
transition:
|
|
129
134
|
visibility 0.1s ease-in-out,
|
|
130
135
|
opacity 0.1s ease-in-out;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const handlePostMessage: (event: MessageEvent) => void;
|