@node-edit-utils/core 2.2.1 → 2.2.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/createCanvasObserver.d.ts +1 -1
- package/dist/lib/canvas/disableCanvasKeyboard.d.ts +1 -1
- package/dist/lib/canvas/disableCanvasTextMode.d.ts +1 -1
- package/dist/lib/canvas/enableCanvasKeyboard.d.ts +1 -1
- package/dist/lib/canvas/enableCanvasTextMode.d.ts +1 -1
- package/dist/lib/canvas/helpers/applyCanvasState.d.ts +1 -1
- package/dist/lib/canvas/helpers/getCanvasWindowValue.d.ts +1 -1
- package/dist/lib/node-tools/createNodeTools.d.ts +1 -1
- package/dist/lib/node-tools/highlight/helpers/getElementBounds.d.ts +1 -1
- package/dist/lib/node-tools/highlight/refreshHighlightFrame.d.ts +1 -1
- package/dist/lib/node-tools/text/events/setupMutationObserver.d.ts +1 -1
- package/dist/lib/node-tools/text/events/setupNodeListeners.d.ts +1 -1
- package/dist/lib/node-tools/text/nodeText.d.ts +1 -1
- package/dist/node-edit-utils.cjs.js +27 -27
- package/dist/node-edit-utils.esm.js +27 -27
- package/dist/node-edit-utils.umd.js +27 -27
- package/dist/node-edit-utils.umd.min.js +1 -1
- package/package.json +1 -1
- package/src/lib/canvas/createCanvasObserver.ts +2 -2
- package/src/lib/canvas/disableCanvasKeyboard.ts +2 -2
- package/src/lib/canvas/disableCanvasTextMode.ts +2 -2
- package/src/lib/canvas/enableCanvasKeyboard.ts +2 -2
- package/src/lib/canvas/enableCanvasTextMode.ts +2 -2
- package/src/lib/canvas/helpers/applyCanvasState.ts +2 -2
- package/src/lib/canvas/helpers/getCanvasWindowValue.ts +2 -2
- package/src/lib/node-tools/createNodeTools.ts +6 -6
- package/src/lib/node-tools/highlight/helpers/getElementBounds.ts +3 -2
- package/src/lib/node-tools/highlight/refreshHighlightFrame.ts +2 -2
- package/src/lib/node-tools/text/events/setupMutationObserver.ts +2 -2
- package/src/lib/node-tools/text/events/setupNodeListeners.ts +2 -2
- package/src/lib/node-tools/text/nodeText.ts +4 -4
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { CanvasObserver } from "./types";
|
|
2
|
-
export declare function createCanvasObserver(): CanvasObserver;
|
|
2
|
+
export declare function createCanvasObserver(canvasName?: string): CanvasObserver;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const disableCanvasKeyboard: () => void;
|
|
1
|
+
export declare const disableCanvasKeyboard: (canvasName?: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const disableCanvasTextMode: () => void;
|
|
1
|
+
export declare const disableCanvasTextMode: (canvasName?: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const enableCanvasKeyboard: () => void;
|
|
1
|
+
export declare const enableCanvasKeyboard: (canvasName?: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const enableCanvasTextMode: () => void;
|
|
1
|
+
export declare const enableCanvasTextMode: (canvasName?: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const applyCanvasState: () => void;
|
|
1
|
+
export declare const applyCanvasState: (canvasName?: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const getCanvasWindowValue: (path: string[]) => any;
|
|
1
|
+
export declare const getCanvasWindowValue: (path: string[], canvasName?: string) => any;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { NodeTools } from "./types";
|
|
2
|
-
export declare const createNodeTools: (element: HTMLElement | null) => NodeTools;
|
|
2
|
+
export declare const createNodeTools: (element: HTMLElement | null, canvasName?: string) => NodeTools;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const refreshHighlightFrame: (node: HTMLElement, nodeProvider: HTMLElement) => void;
|
|
1
|
+
export declare const refreshHighlightFrame: (node: HTMLElement, nodeProvider: HTMLElement, canvasName?: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const setupMutationObserver: (node: HTMLElement, nodeProvider: HTMLElement) => (() => void) | undefined;
|
|
1
|
+
export declare const setupMutationObserver: (node: HTMLElement, nodeProvider: HTMLElement, canvasName?: string) => (() => void) | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const setupNodeListeners: (node: HTMLElement, nodeProvider: HTMLElement | null, blur: () => void) => (() => void);
|
|
1
|
+
export declare const setupNodeListeners: (node: HTMLElement, nodeProvider: HTMLElement | null, blur: () => void, canvasName?: string) => (() => void);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { NodeText } from "./types";
|
|
2
|
-
export declare const nodeText: () => NodeText;
|
|
2
|
+
export declare const nodeText: (canvasName?: string) => NodeText;
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markup Canvas
|
|
3
3
|
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
-
* @version 2.2.
|
|
4
|
+
* @version 2.2.3
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
const getCanvasWindowValue = (path) => {
|
|
8
|
+
const getCanvasWindowValue = (path, canvasName = "canvas") => {
|
|
9
9
|
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
10
|
-
const canvas = window
|
|
10
|
+
const canvas = window[canvasName];
|
|
11
11
|
return path.reduce((obj, prop) => obj?.[prop], canvas);
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
const applyCanvasState = () => {
|
|
15
|
-
const zoom = getCanvasWindowValue(["zoom", "current"]);
|
|
14
|
+
const applyCanvasState = (canvasName = "canvas") => {
|
|
15
|
+
const zoom = getCanvasWindowValue(["zoom", "current"], canvasName) ?? 1;
|
|
16
16
|
document.body.style.setProperty("--zoom", zoom.toFixed(5));
|
|
17
17
|
document.body.style.setProperty("--stroke-width", (2 / zoom).toFixed(3));
|
|
18
18
|
document.body.dataset.zoom = zoom.toFixed(5);
|
|
19
19
|
document.body.dataset.strokeWidth = (2 / zoom).toFixed(3);
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
function createCanvasObserver() {
|
|
22
|
+
function createCanvasObserver(canvasName = "canvas") {
|
|
23
23
|
const transformLayer = document.querySelector(".transform-layer");
|
|
24
24
|
if (!transformLayer) {
|
|
25
25
|
return {
|
|
@@ -27,7 +27,7 @@ function createCanvasObserver() {
|
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
const observer = new MutationObserver(() => {
|
|
30
|
-
applyCanvasState();
|
|
30
|
+
applyCanvasState(canvasName);
|
|
31
31
|
// Refresh highlight frame (throttled via withRAFThrottle)
|
|
32
32
|
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
33
33
|
const nodeTools = window.nodeTools;
|
|
@@ -374,7 +374,7 @@ const highlightNode = (node) => {
|
|
|
374
374
|
const getComponentColor = () => {
|
|
375
375
|
return getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim() || "oklch(65.6% 0.241 354.308)";
|
|
376
376
|
};
|
|
377
|
-
const refreshHighlightFrame = (node, nodeProvider) => {
|
|
377
|
+
const refreshHighlightFrame = (node, nodeProvider, canvasName = "canvas") => {
|
|
378
378
|
// Batch all DOM reads first (single layout pass)
|
|
379
379
|
const frame = getHighlightFrameElement();
|
|
380
380
|
if (!frame)
|
|
@@ -408,7 +408,7 @@ const refreshHighlightFrame = (node, nodeProvider) => {
|
|
|
408
408
|
}
|
|
409
409
|
const toolsWrapper = document.body.querySelector(".highlight-frame-tools-wrapper");
|
|
410
410
|
const nodeTools = toolsWrapper?.querySelector(".node-tools");
|
|
411
|
-
const zoom = getCanvasWindowValue(["zoom", "current"]) ?? 1;
|
|
411
|
+
const zoom = getCanvasWindowValue(["zoom", "current"], canvasName) ?? 1;
|
|
412
412
|
const bounds = getScreenBounds(node);
|
|
413
413
|
// Calculate all values before any DOM writes
|
|
414
414
|
const { top, left, width, height } = bounds;
|
|
@@ -496,13 +496,13 @@ const updateHighlightFrameVisibility = (node) => {
|
|
|
496
496
|
}
|
|
497
497
|
};
|
|
498
498
|
|
|
499
|
-
const disableCanvasTextMode = () => {
|
|
500
|
-
const disableTextEditMode = getCanvasWindowValue(["keyboard", "disableTextEditMode"]);
|
|
499
|
+
const disableCanvasTextMode = (canvasName = "canvas") => {
|
|
500
|
+
const disableTextEditMode = getCanvasWindowValue(["keyboard", "disableTextEditMode"], canvasName);
|
|
501
501
|
disableTextEditMode?.();
|
|
502
502
|
};
|
|
503
503
|
|
|
504
|
-
const enableCanvasTextMode = () => {
|
|
505
|
-
const enableTextEditMode = getCanvasWindowValue(["keyboard", "enableTextEditMode"]);
|
|
504
|
+
const enableCanvasTextMode = (canvasName = "canvas") => {
|
|
505
|
+
const enableTextEditMode = getCanvasWindowValue(["keyboard", "enableTextEditMode"], canvasName);
|
|
506
506
|
enableTextEditMode?.();
|
|
507
507
|
};
|
|
508
508
|
|
|
@@ -547,20 +547,20 @@ const connectMutationObserver = (element, handler) => {
|
|
|
547
547
|
return mutationObserver;
|
|
548
548
|
};
|
|
549
549
|
|
|
550
|
-
const setupMutationObserver = (node, nodeProvider) => {
|
|
550
|
+
const setupMutationObserver = (node, nodeProvider, canvasName = "canvas") => {
|
|
551
551
|
const mutationObserver = connectMutationObserver(node, () => {
|
|
552
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
552
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
553
553
|
});
|
|
554
554
|
return () => mutationObserver.disconnect();
|
|
555
555
|
};
|
|
556
556
|
|
|
557
|
-
const setupNodeListeners = (node, nodeProvider, blur) => {
|
|
557
|
+
const setupNodeListeners = (node, nodeProvider, blur, canvasName = "canvas") => {
|
|
558
558
|
if (!nodeProvider) {
|
|
559
559
|
return () => { };
|
|
560
560
|
}
|
|
561
561
|
node.addEventListener("blur", blur);
|
|
562
562
|
const keydownCleanup = setupKeydownHandler(node);
|
|
563
|
-
const mutationCleanup = setupMutationObserver(node, nodeProvider);
|
|
563
|
+
const mutationCleanup = setupMutationObserver(node, nodeProvider, canvasName);
|
|
564
564
|
return () => {
|
|
565
565
|
node.removeEventListener("blur", blur);
|
|
566
566
|
keydownCleanup();
|
|
@@ -584,7 +584,7 @@ const makeNodeNonEditable = (node) => {
|
|
|
584
584
|
node.style.outline = "none";
|
|
585
585
|
};
|
|
586
586
|
|
|
587
|
-
const nodeText = () => {
|
|
587
|
+
const nodeText = (canvasName = "canvas") => {
|
|
588
588
|
let editableNode = null;
|
|
589
589
|
let blurInProgress = false;
|
|
590
590
|
let cleanup = null;
|
|
@@ -599,8 +599,8 @@ const nodeText = () => {
|
|
|
599
599
|
if (editable) {
|
|
600
600
|
editableNode = node;
|
|
601
601
|
makeNodeEditable(node);
|
|
602
|
-
enableCanvasTextMode();
|
|
603
|
-
cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
|
|
602
|
+
enableCanvasTextMode(canvasName);
|
|
603
|
+
cleanup = setupNodeListeners(node, nodeProvider, blurEditMode, canvasName);
|
|
604
604
|
}
|
|
605
605
|
};
|
|
606
606
|
const getEditableNode = () => {
|
|
@@ -616,7 +616,7 @@ const nodeText = () => {
|
|
|
616
616
|
blurInProgress = true;
|
|
617
617
|
const nodeToCleanup = editableNode;
|
|
618
618
|
makeNodeNonEditable(nodeToCleanup);
|
|
619
|
-
disableCanvasTextMode();
|
|
619
|
+
disableCanvasTextMode(canvasName);
|
|
620
620
|
cleanup?.();
|
|
621
621
|
editableNode = null;
|
|
622
622
|
blurInProgress = false;
|
|
@@ -629,15 +629,15 @@ const nodeText = () => {
|
|
|
629
629
|
};
|
|
630
630
|
};
|
|
631
631
|
|
|
632
|
-
const createNodeTools = (element) => {
|
|
632
|
+
const createNodeTools = (element, canvasName = "canvas") => {
|
|
633
633
|
const nodeProvider = element;
|
|
634
634
|
let resizeObserver = null;
|
|
635
635
|
let mutationObserver = null;
|
|
636
636
|
let selectedNode = null;
|
|
637
|
-
const text = nodeText();
|
|
637
|
+
const text = nodeText(canvasName);
|
|
638
638
|
// Combined throttled function for refresh + visibility update
|
|
639
639
|
const throttledRefreshAndVisibility = withRAFThrottle((node, nodeProvider) => {
|
|
640
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
640
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
641
641
|
updateHighlightFrameVisibility(node);
|
|
642
642
|
});
|
|
643
643
|
const handleEscape = () => {
|
|
@@ -670,7 +670,7 @@ const createNodeTools = (element) => {
|
|
|
670
670
|
mutationObserver = new MutationObserver(() => {
|
|
671
671
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
672
672
|
console.log("mutationObserver", node);
|
|
673
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
673
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
674
674
|
updateHighlightFrameVisibility(node);
|
|
675
675
|
});
|
|
676
676
|
mutationObserver.observe(node, {
|
|
@@ -680,7 +680,7 @@ const createNodeTools = (element) => {
|
|
|
680
680
|
resizeObserver = connectResizeObserver(node, () => {
|
|
681
681
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
682
682
|
console.log("resizeObserver", node);
|
|
683
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
683
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
684
684
|
updateHighlightFrameVisibility(node);
|
|
685
685
|
});
|
|
686
686
|
}
|
|
@@ -707,7 +707,7 @@ const createNodeTools = (element) => {
|
|
|
707
707
|
if (selectedNode && nodeProvider) {
|
|
708
708
|
// Call directly (not throttled) since this is typically called from already-throttled contexts
|
|
709
709
|
// to avoid double RAF
|
|
710
|
-
refreshHighlightFrame(selectedNode, nodeProvider);
|
|
710
|
+
refreshHighlightFrame(selectedNode, nodeProvider, canvasName);
|
|
711
711
|
updateHighlightFrameVisibility(selectedNode);
|
|
712
712
|
}
|
|
713
713
|
},
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markup Canvas
|
|
3
3
|
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
-
* @version 2.2.
|
|
4
|
+
* @version 2.2.3
|
|
5
5
|
*/
|
|
6
|
-
const getCanvasWindowValue = (path) => {
|
|
6
|
+
const getCanvasWindowValue = (path, canvasName = "canvas") => {
|
|
7
7
|
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
8
|
-
const canvas = window
|
|
8
|
+
const canvas = window[canvasName];
|
|
9
9
|
return path.reduce((obj, prop) => obj?.[prop], canvas);
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
const applyCanvasState = () => {
|
|
13
|
-
const zoom = getCanvasWindowValue(["zoom", "current"]);
|
|
12
|
+
const applyCanvasState = (canvasName = "canvas") => {
|
|
13
|
+
const zoom = getCanvasWindowValue(["zoom", "current"], canvasName) ?? 1;
|
|
14
14
|
document.body.style.setProperty("--zoom", zoom.toFixed(5));
|
|
15
15
|
document.body.style.setProperty("--stroke-width", (2 / zoom).toFixed(3));
|
|
16
16
|
document.body.dataset.zoom = zoom.toFixed(5);
|
|
17
17
|
document.body.dataset.strokeWidth = (2 / zoom).toFixed(3);
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
function createCanvasObserver() {
|
|
20
|
+
function createCanvasObserver(canvasName = "canvas") {
|
|
21
21
|
const transformLayer = document.querySelector(".transform-layer");
|
|
22
22
|
if (!transformLayer) {
|
|
23
23
|
return {
|
|
@@ -25,7 +25,7 @@ function createCanvasObserver() {
|
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
const observer = new MutationObserver(() => {
|
|
28
|
-
applyCanvasState();
|
|
28
|
+
applyCanvasState(canvasName);
|
|
29
29
|
// Refresh highlight frame (throttled via withRAFThrottle)
|
|
30
30
|
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
31
31
|
const nodeTools = window.nodeTools;
|
|
@@ -372,7 +372,7 @@ const highlightNode = (node) => {
|
|
|
372
372
|
const getComponentColor = () => {
|
|
373
373
|
return getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim() || "oklch(65.6% 0.241 354.308)";
|
|
374
374
|
};
|
|
375
|
-
const refreshHighlightFrame = (node, nodeProvider) => {
|
|
375
|
+
const refreshHighlightFrame = (node, nodeProvider, canvasName = "canvas") => {
|
|
376
376
|
// Batch all DOM reads first (single layout pass)
|
|
377
377
|
const frame = getHighlightFrameElement();
|
|
378
378
|
if (!frame)
|
|
@@ -406,7 +406,7 @@ const refreshHighlightFrame = (node, nodeProvider) => {
|
|
|
406
406
|
}
|
|
407
407
|
const toolsWrapper = document.body.querySelector(".highlight-frame-tools-wrapper");
|
|
408
408
|
const nodeTools = toolsWrapper?.querySelector(".node-tools");
|
|
409
|
-
const zoom = getCanvasWindowValue(["zoom", "current"]) ?? 1;
|
|
409
|
+
const zoom = getCanvasWindowValue(["zoom", "current"], canvasName) ?? 1;
|
|
410
410
|
const bounds = getScreenBounds(node);
|
|
411
411
|
// Calculate all values before any DOM writes
|
|
412
412
|
const { top, left, width, height } = bounds;
|
|
@@ -494,13 +494,13 @@ const updateHighlightFrameVisibility = (node) => {
|
|
|
494
494
|
}
|
|
495
495
|
};
|
|
496
496
|
|
|
497
|
-
const disableCanvasTextMode = () => {
|
|
498
|
-
const disableTextEditMode = getCanvasWindowValue(["keyboard", "disableTextEditMode"]);
|
|
497
|
+
const disableCanvasTextMode = (canvasName = "canvas") => {
|
|
498
|
+
const disableTextEditMode = getCanvasWindowValue(["keyboard", "disableTextEditMode"], canvasName);
|
|
499
499
|
disableTextEditMode?.();
|
|
500
500
|
};
|
|
501
501
|
|
|
502
|
-
const enableCanvasTextMode = () => {
|
|
503
|
-
const enableTextEditMode = getCanvasWindowValue(["keyboard", "enableTextEditMode"]);
|
|
502
|
+
const enableCanvasTextMode = (canvasName = "canvas") => {
|
|
503
|
+
const enableTextEditMode = getCanvasWindowValue(["keyboard", "enableTextEditMode"], canvasName);
|
|
504
504
|
enableTextEditMode?.();
|
|
505
505
|
};
|
|
506
506
|
|
|
@@ -545,20 +545,20 @@ const connectMutationObserver = (element, handler) => {
|
|
|
545
545
|
return mutationObserver;
|
|
546
546
|
};
|
|
547
547
|
|
|
548
|
-
const setupMutationObserver = (node, nodeProvider) => {
|
|
548
|
+
const setupMutationObserver = (node, nodeProvider, canvasName = "canvas") => {
|
|
549
549
|
const mutationObserver = connectMutationObserver(node, () => {
|
|
550
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
550
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
551
551
|
});
|
|
552
552
|
return () => mutationObserver.disconnect();
|
|
553
553
|
};
|
|
554
554
|
|
|
555
|
-
const setupNodeListeners = (node, nodeProvider, blur) => {
|
|
555
|
+
const setupNodeListeners = (node, nodeProvider, blur, canvasName = "canvas") => {
|
|
556
556
|
if (!nodeProvider) {
|
|
557
557
|
return () => { };
|
|
558
558
|
}
|
|
559
559
|
node.addEventListener("blur", blur);
|
|
560
560
|
const keydownCleanup = setupKeydownHandler(node);
|
|
561
|
-
const mutationCleanup = setupMutationObserver(node, nodeProvider);
|
|
561
|
+
const mutationCleanup = setupMutationObserver(node, nodeProvider, canvasName);
|
|
562
562
|
return () => {
|
|
563
563
|
node.removeEventListener("blur", blur);
|
|
564
564
|
keydownCleanup();
|
|
@@ -582,7 +582,7 @@ const makeNodeNonEditable = (node) => {
|
|
|
582
582
|
node.style.outline = "none";
|
|
583
583
|
};
|
|
584
584
|
|
|
585
|
-
const nodeText = () => {
|
|
585
|
+
const nodeText = (canvasName = "canvas") => {
|
|
586
586
|
let editableNode = null;
|
|
587
587
|
let blurInProgress = false;
|
|
588
588
|
let cleanup = null;
|
|
@@ -597,8 +597,8 @@ const nodeText = () => {
|
|
|
597
597
|
if (editable) {
|
|
598
598
|
editableNode = node;
|
|
599
599
|
makeNodeEditable(node);
|
|
600
|
-
enableCanvasTextMode();
|
|
601
|
-
cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
|
|
600
|
+
enableCanvasTextMode(canvasName);
|
|
601
|
+
cleanup = setupNodeListeners(node, nodeProvider, blurEditMode, canvasName);
|
|
602
602
|
}
|
|
603
603
|
};
|
|
604
604
|
const getEditableNode = () => {
|
|
@@ -614,7 +614,7 @@ const nodeText = () => {
|
|
|
614
614
|
blurInProgress = true;
|
|
615
615
|
const nodeToCleanup = editableNode;
|
|
616
616
|
makeNodeNonEditable(nodeToCleanup);
|
|
617
|
-
disableCanvasTextMode();
|
|
617
|
+
disableCanvasTextMode(canvasName);
|
|
618
618
|
cleanup?.();
|
|
619
619
|
editableNode = null;
|
|
620
620
|
blurInProgress = false;
|
|
@@ -627,15 +627,15 @@ const nodeText = () => {
|
|
|
627
627
|
};
|
|
628
628
|
};
|
|
629
629
|
|
|
630
|
-
const createNodeTools = (element) => {
|
|
630
|
+
const createNodeTools = (element, canvasName = "canvas") => {
|
|
631
631
|
const nodeProvider = element;
|
|
632
632
|
let resizeObserver = null;
|
|
633
633
|
let mutationObserver = null;
|
|
634
634
|
let selectedNode = null;
|
|
635
|
-
const text = nodeText();
|
|
635
|
+
const text = nodeText(canvasName);
|
|
636
636
|
// Combined throttled function for refresh + visibility update
|
|
637
637
|
const throttledRefreshAndVisibility = withRAFThrottle((node, nodeProvider) => {
|
|
638
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
638
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
639
639
|
updateHighlightFrameVisibility(node);
|
|
640
640
|
});
|
|
641
641
|
const handleEscape = () => {
|
|
@@ -668,7 +668,7 @@ const createNodeTools = (element) => {
|
|
|
668
668
|
mutationObserver = new MutationObserver(() => {
|
|
669
669
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
670
670
|
console.log("mutationObserver", node);
|
|
671
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
671
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
672
672
|
updateHighlightFrameVisibility(node);
|
|
673
673
|
});
|
|
674
674
|
mutationObserver.observe(node, {
|
|
@@ -678,7 +678,7 @@ const createNodeTools = (element) => {
|
|
|
678
678
|
resizeObserver = connectResizeObserver(node, () => {
|
|
679
679
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
680
680
|
console.log("resizeObserver", node);
|
|
681
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
681
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
682
682
|
updateHighlightFrameVisibility(node);
|
|
683
683
|
});
|
|
684
684
|
}
|
|
@@ -705,7 +705,7 @@ const createNodeTools = (element) => {
|
|
|
705
705
|
if (selectedNode && nodeProvider) {
|
|
706
706
|
// Call directly (not throttled) since this is typically called from already-throttled contexts
|
|
707
707
|
// to avoid double RAF
|
|
708
|
-
refreshHighlightFrame(selectedNode, nodeProvider);
|
|
708
|
+
refreshHighlightFrame(selectedNode, nodeProvider, canvasName);
|
|
709
709
|
updateHighlightFrameVisibility(selectedNode);
|
|
710
710
|
}
|
|
711
711
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markup Canvas
|
|
3
3
|
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
-
* @version 2.2.
|
|
4
|
+
* @version 2.2.3
|
|
5
5
|
*/
|
|
6
6
|
(function (global, factory) {
|
|
7
7
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
@@ -9,21 +9,21 @@
|
|
|
9
9
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.MarkupCanvas = {}));
|
|
10
10
|
})(this, (function (exports) { 'use strict';
|
|
11
11
|
|
|
12
|
-
const getCanvasWindowValue = (path) => {
|
|
12
|
+
const getCanvasWindowValue = (path, canvasName = "canvas") => {
|
|
13
13
|
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
14
|
-
const canvas = window
|
|
14
|
+
const canvas = window[canvasName];
|
|
15
15
|
return path.reduce((obj, prop) => obj?.[prop], canvas);
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
const applyCanvasState = () => {
|
|
19
|
-
const zoom = getCanvasWindowValue(["zoom", "current"]);
|
|
18
|
+
const applyCanvasState = (canvasName = "canvas") => {
|
|
19
|
+
const zoom = getCanvasWindowValue(["zoom", "current"], canvasName) ?? 1;
|
|
20
20
|
document.body.style.setProperty("--zoom", zoom.toFixed(5));
|
|
21
21
|
document.body.style.setProperty("--stroke-width", (2 / zoom).toFixed(3));
|
|
22
22
|
document.body.dataset.zoom = zoom.toFixed(5);
|
|
23
23
|
document.body.dataset.strokeWidth = (2 / zoom).toFixed(3);
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
function createCanvasObserver() {
|
|
26
|
+
function createCanvasObserver(canvasName = "canvas") {
|
|
27
27
|
const transformLayer = document.querySelector(".transform-layer");
|
|
28
28
|
if (!transformLayer) {
|
|
29
29
|
return {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
const observer = new MutationObserver(() => {
|
|
34
|
-
applyCanvasState();
|
|
34
|
+
applyCanvasState(canvasName);
|
|
35
35
|
// Refresh highlight frame (throttled via withRAFThrottle)
|
|
36
36
|
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
37
37
|
const nodeTools = window.nodeTools;
|
|
@@ -378,7 +378,7 @@
|
|
|
378
378
|
const getComponentColor = () => {
|
|
379
379
|
return getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim() || "oklch(65.6% 0.241 354.308)";
|
|
380
380
|
};
|
|
381
|
-
const refreshHighlightFrame = (node, nodeProvider) => {
|
|
381
|
+
const refreshHighlightFrame = (node, nodeProvider, canvasName = "canvas") => {
|
|
382
382
|
// Batch all DOM reads first (single layout pass)
|
|
383
383
|
const frame = getHighlightFrameElement();
|
|
384
384
|
if (!frame)
|
|
@@ -412,7 +412,7 @@
|
|
|
412
412
|
}
|
|
413
413
|
const toolsWrapper = document.body.querySelector(".highlight-frame-tools-wrapper");
|
|
414
414
|
const nodeTools = toolsWrapper?.querySelector(".node-tools");
|
|
415
|
-
const zoom = getCanvasWindowValue(["zoom", "current"]) ?? 1;
|
|
415
|
+
const zoom = getCanvasWindowValue(["zoom", "current"], canvasName) ?? 1;
|
|
416
416
|
const bounds = getScreenBounds(node);
|
|
417
417
|
// Calculate all values before any DOM writes
|
|
418
418
|
const { top, left, width, height } = bounds;
|
|
@@ -500,13 +500,13 @@
|
|
|
500
500
|
}
|
|
501
501
|
};
|
|
502
502
|
|
|
503
|
-
const disableCanvasTextMode = () => {
|
|
504
|
-
const disableTextEditMode = getCanvasWindowValue(["keyboard", "disableTextEditMode"]);
|
|
503
|
+
const disableCanvasTextMode = (canvasName = "canvas") => {
|
|
504
|
+
const disableTextEditMode = getCanvasWindowValue(["keyboard", "disableTextEditMode"], canvasName);
|
|
505
505
|
disableTextEditMode?.();
|
|
506
506
|
};
|
|
507
507
|
|
|
508
|
-
const enableCanvasTextMode = () => {
|
|
509
|
-
const enableTextEditMode = getCanvasWindowValue(["keyboard", "enableTextEditMode"]);
|
|
508
|
+
const enableCanvasTextMode = (canvasName = "canvas") => {
|
|
509
|
+
const enableTextEditMode = getCanvasWindowValue(["keyboard", "enableTextEditMode"], canvasName);
|
|
510
510
|
enableTextEditMode?.();
|
|
511
511
|
};
|
|
512
512
|
|
|
@@ -551,20 +551,20 @@
|
|
|
551
551
|
return mutationObserver;
|
|
552
552
|
};
|
|
553
553
|
|
|
554
|
-
const setupMutationObserver = (node, nodeProvider) => {
|
|
554
|
+
const setupMutationObserver = (node, nodeProvider, canvasName = "canvas") => {
|
|
555
555
|
const mutationObserver = connectMutationObserver(node, () => {
|
|
556
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
556
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
557
557
|
});
|
|
558
558
|
return () => mutationObserver.disconnect();
|
|
559
559
|
};
|
|
560
560
|
|
|
561
|
-
const setupNodeListeners = (node, nodeProvider, blur) => {
|
|
561
|
+
const setupNodeListeners = (node, nodeProvider, blur, canvasName = "canvas") => {
|
|
562
562
|
if (!nodeProvider) {
|
|
563
563
|
return () => { };
|
|
564
564
|
}
|
|
565
565
|
node.addEventListener("blur", blur);
|
|
566
566
|
const keydownCleanup = setupKeydownHandler(node);
|
|
567
|
-
const mutationCleanup = setupMutationObserver(node, nodeProvider);
|
|
567
|
+
const mutationCleanup = setupMutationObserver(node, nodeProvider, canvasName);
|
|
568
568
|
return () => {
|
|
569
569
|
node.removeEventListener("blur", blur);
|
|
570
570
|
keydownCleanup();
|
|
@@ -588,7 +588,7 @@
|
|
|
588
588
|
node.style.outline = "none";
|
|
589
589
|
};
|
|
590
590
|
|
|
591
|
-
const nodeText = () => {
|
|
591
|
+
const nodeText = (canvasName = "canvas") => {
|
|
592
592
|
let editableNode = null;
|
|
593
593
|
let blurInProgress = false;
|
|
594
594
|
let cleanup = null;
|
|
@@ -603,8 +603,8 @@
|
|
|
603
603
|
if (editable) {
|
|
604
604
|
editableNode = node;
|
|
605
605
|
makeNodeEditable(node);
|
|
606
|
-
enableCanvasTextMode();
|
|
607
|
-
cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
|
|
606
|
+
enableCanvasTextMode(canvasName);
|
|
607
|
+
cleanup = setupNodeListeners(node, nodeProvider, blurEditMode, canvasName);
|
|
608
608
|
}
|
|
609
609
|
};
|
|
610
610
|
const getEditableNode = () => {
|
|
@@ -620,7 +620,7 @@
|
|
|
620
620
|
blurInProgress = true;
|
|
621
621
|
const nodeToCleanup = editableNode;
|
|
622
622
|
makeNodeNonEditable(nodeToCleanup);
|
|
623
|
-
disableCanvasTextMode();
|
|
623
|
+
disableCanvasTextMode(canvasName);
|
|
624
624
|
cleanup?.();
|
|
625
625
|
editableNode = null;
|
|
626
626
|
blurInProgress = false;
|
|
@@ -633,15 +633,15 @@
|
|
|
633
633
|
};
|
|
634
634
|
};
|
|
635
635
|
|
|
636
|
-
const createNodeTools = (element) => {
|
|
636
|
+
const createNodeTools = (element, canvasName = "canvas") => {
|
|
637
637
|
const nodeProvider = element;
|
|
638
638
|
let resizeObserver = null;
|
|
639
639
|
let mutationObserver = null;
|
|
640
640
|
let selectedNode = null;
|
|
641
|
-
const text = nodeText();
|
|
641
|
+
const text = nodeText(canvasName);
|
|
642
642
|
// Combined throttled function for refresh + visibility update
|
|
643
643
|
const throttledRefreshAndVisibility = withRAFThrottle((node, nodeProvider) => {
|
|
644
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
644
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
645
645
|
updateHighlightFrameVisibility(node);
|
|
646
646
|
});
|
|
647
647
|
const handleEscape = () => {
|
|
@@ -674,7 +674,7 @@
|
|
|
674
674
|
mutationObserver = new MutationObserver(() => {
|
|
675
675
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
676
676
|
console.log("mutationObserver", node);
|
|
677
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
677
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
678
678
|
updateHighlightFrameVisibility(node);
|
|
679
679
|
});
|
|
680
680
|
mutationObserver.observe(node, {
|
|
@@ -684,7 +684,7 @@
|
|
|
684
684
|
resizeObserver = connectResizeObserver(node, () => {
|
|
685
685
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
686
686
|
console.log("resizeObserver", node);
|
|
687
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
687
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
688
688
|
updateHighlightFrameVisibility(node);
|
|
689
689
|
});
|
|
690
690
|
}
|
|
@@ -711,7 +711,7 @@
|
|
|
711
711
|
if (selectedNode && nodeProvider) {
|
|
712
712
|
// Call directly (not throttled) since this is typically called from already-throttled contexts
|
|
713
713
|
// to avoid double RAF
|
|
714
|
-
refreshHighlightFrame(selectedNode, nodeProvider);
|
|
714
|
+
refreshHighlightFrame(selectedNode, nodeProvider, canvasName);
|
|
715
715
|
updateHighlightFrameVisibility(selectedNode);
|
|
716
716
|
}
|
|
717
717
|
},
|
|
@@ -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";const t=e=>{const t=window.canvas;return e.reduce((e,t)=>e?.[t],t)};function n(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 o=()=>{const e=document.body.querySelector(".highlight-frame-overlay");e&&e.remove();const t=document.body.querySelector(".highlight-frame-tools-wrapper");t&&t.remove()},r=["path","rect","circle","ellipse","polygon","line","polyline","text","text-noci"];let i=[],s=0;const l=(e,t)=>{let n=null;const o=e.clientX,l=e.clientY,a=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,l).filter(e=>!r.includes(e.tagName.toLowerCase())&&!e.classList.contains("select-none")&&!(e=>{let t=e.parentElement;for(;t;){if("true"===t.getAttribute("data-instance"))return!0;if("node-provider"===t.getAttribute("data-role"))break;t=t.parentElement}return!1})(e));if(t&&d.includes(t))return t;if(a)return i=[],n=d[0],n;var c,u;u=d,(c=i).length===u.length&&c.every((e,t)=>e===u[t])?s<=d.length&&s++:s=0;return n=d[d.length-1-s],i=d,n},a=(e,t,n,r)=>{const i=e=>{((e,t)=>{if("application"===e.data.source&&"selectedNodeChanged"===e.data.action){const o=e.data.data,r=document.querySelector(`[data-node-id="${o}"]`);if(n=r,n?.classList.contains("select-none"))return void t?.(null);r&&t?.(r)}var n})(e,t)},s=n=>{((e,t,n,r)=>{if(e.preventDefault(),e.stopPropagation(),t&&!t.contains(e.target))return o(),void r(null);r(l(e,n))})(n,e,r(),t)},a=e=>{"Escape"===e.key&&(e.preventDefault(),e.stopPropagation(),n?.())};return window.addEventListener("message",i),document.addEventListener("click",s),document.addEventListener("keydown",a),()=>{window.removeEventListener("message",i),document.removeEventListener("click",s),document.removeEventListener("keydown",a)}},d=e=>"true"===e.getAttribute("data-instance"),c=(e,t,n,o,r=!1)=>{const i=document.createElementNS("http://www.w3.org/2000/svg","rect");return i.setAttribute("x",(t-3).toString()),i.setAttribute("y",(n-3).toString()),i.setAttribute("width",6..toString()),i.setAttribute("height",6..toString()),i.setAttribute("vector-effect","non-scaling-stroke"),i.classList.add("highlight-frame-handle",o),r&&i.setAttribute("stroke",getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim()||"oklch(65.6% 0.241 354.308)"),e.appendChild(i),i};function u(e){const t=e.getBoundingClientRect();return{top:t.top,left:t.left,width:t.width,height:t.height}}const m=(e,t=!1)=>{const{top:n,left:o,width:r,height:i}=u(e),s=document.createElementNS("http://www.w3.org/2000/svg","svg");s.classList.add("highlight-frame-overlay"),t&&s.classList.add("is-instance"),s.setAttribute("data-node-id",e.getAttribute("data-node-id")||""),s.style.position="fixed",s.style.top="0",s.style.left="0",s.style.width="100vw",s.style.height="100vh",s.style.pointerEvents="none",s.style.zIndex="5000";const l=document.documentElement.clientWidth||window.innerWidth,a=document.documentElement.clientHeight||window.innerHeight;s.setAttribute("width",l.toString()),s.setAttribute("height",a.toString());const d=document.createElementNS("http://www.w3.org/2000/svg","g");d.classList.add("highlight-frame-group"),d.setAttribute("transform",`translate(${o}, ${n})`);const m=document.createElementNS("http://www.w3.org/2000/svg","rect");return m.setAttribute("x","0"),m.setAttribute("y","0"),m.setAttribute("width",r.toString()),m.setAttribute("height",i.toString()),m.setAttribute("vector-effect","non-scaling-stroke"),m.classList.add("highlight-frame-rect"),t&&m.setAttribute("stroke",getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim()||"oklch(65.6% 0.241 354.308)"),d.appendChild(m),((e,t,n,o=!1)=>{c(e,0,0,"handle-top-left",o),c(e,t,0,"handle-top-right",o),c(e,t,n,"handle-bottom-right",o),c(e,0,n,"handle-bottom-left",o)})(d,r,i,t),s.appendChild(d),document.body.appendChild(s),s},h=(e,t,n=!1)=>{const o=document.createElement("div");o.className="node-tools",n&&o.classList.add("is-instance"),t.appendChild(o),((e,t)=>{const n=document.createElement("div");n.className="tag-label",n.textContent=e.tagName.toLowerCase(),t.appendChild(n)})(e,o)};function g(){return document.body.querySelector(".highlight-frame-overlay")}const p=()=>getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim()||"oklch(65.6% 0.241 354.308)",b=(e,n)=>{const o=g();if(!o)return;const r=d(e),i=document.documentElement.clientWidth||window.innerWidth,s=document.documentElement.clientHeight||window.innerHeight;o.setAttribute("width",i.toString()),o.setAttribute("height",s.toString()),r?o.classList.add("is-instance"):o.classList.remove("is-instance");const l=o.querySelector(".highlight-frame-group");if(!l)return;const a=l.querySelector("rect");if(!a)return;r?a.setAttribute("stroke",p()):a.removeAttribute("stroke");const c=document.body.querySelector(".highlight-frame-tools-wrapper"),m=c?.querySelector(".node-tools"),h=t(["zoom","current"])??1,b=u(e),{top:y,left:v,width:f,height:w}=b,E=y+w;c&&(r?c.classList.add("is-instance"):c.classList.remove("is-instance")),m&&(r?m.classList.add("is-instance"):m.classList.remove("is-instance")),l.setAttribute("transform",`translate(${v}, ${y})`),a.setAttribute("width",f.toString()),a.setAttribute("height",w.toString());const S=l.querySelector(".handle-top-left"),A=l.querySelector(".handle-top-right"),L=l.querySelector(".handle-bottom-right"),x=l.querySelector(".handle-bottom-left");[S,A,L,x].forEach(e=>{e&&(r?e.setAttribute("stroke",p()):e.removeAttribute("stroke"))}),S&&(S.setAttribute("x",(-3).toString()),S.setAttribute("y",(-3).toString())),A&&(A.setAttribute("x",(f-3).toString()),A.setAttribute("y",(-3).toString())),L&&(L.setAttribute("x",(f-3).toString()),L.setAttribute("y",(w-3).toString())),x&&(x.setAttribute("x",(-3).toString()),x.setAttribute("y",(w-3).toString())),c&&(c.style.left=`${v}px`,c.style.top=`${E}px`),h<=10?n.style.setProperty("--tool-opacity","1"):n.style.setProperty("--tool-opacity","0")},y=e=>{const t=g();if(!t)return;const n=e.classList.contains("hidden")||e.classList.contains("select-none")?"none":"";t.style.display=n;const o=document.body.querySelector(".highlight-frame-tools-wrapper");o&&(o.style.display=n)},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)}},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,()=>{b(e,t)});return()=>n.disconnect()},w=()=>{let e=null,n=!1,o=null;const r=()=>{if(n||!e)return;n=!0;var r;(r=e).contentEditable="false",r.classList.remove("is-editable"),r.style.outline="none",(()=>{const e=t(["keyboard","disableTextEditMode"]);e?.()})(),o?.(),e=null,n=!1};return{enableEditMode:(n,i)=>{if(e===n)return;e&&e!==n&&r();const s=(e=>Array.from(e.childNodes).some(e=>e.nodeType===Node.TEXT_NODE&&e.textContent?.trim()))(n);s&&(e=n,(e=>{e.contentEditable="true",e.classList.add("is-editable"),e.style.outline="none"})(n),(()=>{const e=t(["keyboard","enableTextEditMode"]);e?.()})(),o=((e,t,n)=>{if(!t)return()=>{};e.addEventListener("blur",n);const o=v(e),r=f(e,t);return()=>{e.removeEventListener("blur",n),o(),r?.()}})(n,i,r))},blurEditMode:r,getEditableNode:()=>e,isEditing:()=>null!==e}},E=320,S=1680,A=[{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"}],L=(e,t,n)=>{const o=parseFloat(document.body.dataset.zoom||"1"),r=((e,t)=>{const n=e+Math.round(t);return Math.max(E,Math.min(S,n))})(n,(e.clientX-t)/o);return r},x=(e,t)=>{e.style.setProperty("--container-width",`${t}px`),((e,t)=>{e.querySelectorAll(".resize-preset-button").forEach((e,n)=>{n<A.length&&(A[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 n=new MutationObserver(()=>{(()=>{const e=t(["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)})();const e=window.nodeTools;e?.refreshHighlightFrame&&e.refreshHighlightFrame()});return n.observe(e,{attributes:!0,attributeOldValue:!0,subtree:!0,childList:!0}),{disconnect:function(){n.disconnect()}}},e.createNodeTools=e=>{const t=e;let r=null,i=null,s=null;const l=w(),c=n((e,t)=>{b(e,t),y(e)}),p=e=>{if(s!==e){if(l.isEditing()){const t=l.getEditableNode();t&&t!==e&&l.blurEditMode()}var n,o;r?.disconnect(),i?.disconnect(),e&&t&&(l.enableEditMode(e,t),i=new MutationObserver(()=>{console.log("mutationObserver",e),b(e,t),y(e)}),i.observe(e,{attributes:!0,characterData:!0}),r=((e,t)=>{const n=new ResizeObserver(e=>{t(e)});return n.observe(e),n})(e,()=>{console.log("resizeObserver",e),b(e,t),y(e)})),s=e,n="selectedNodeChanged",o=e?.getAttribute("data-node-id")??null,window.parent.postMessage({source:"node-edit-utils",action:n,data:o,timestamp:Date.now()},"*"),(e=>{if(!e)return;const t=g(),n=document.body.querySelector(".highlight-frame-tools-wrapper");t&&t.remove(),n&&n.remove();const o=d(e),r=m(e,o);"true"===e.contentEditable&&r.classList.add("is-editable");const{left:i,top:s,height:l}=u(e),a=s+l,c=document.createElement("div");c.classList.add("highlight-frame-tools-wrapper"),o&&c.classList.add("is-instance"),c.style.position="fixed",c.style.left=`${i}px`,c.style.top=`${a}px`,c.style.transform="translateX(-50%)",c.style.transformOrigin="center",c.style.pointerEvents="none",c.style.zIndex="5000",h(e,c,o),document.body.appendChild(c)})(e),e&&t&&y(e)}},v=a(t,p,()=>{l.isEditing()&&l.blurEditMode(),s&&t&&(o(),s=null,r?.disconnect(),i?.disconnect())},l.getEditableNode),f={selectNode:p,getSelectedNode:()=>s,refreshHighlightFrame:()=>{s&&t&&(b(s,t),y(s))},clearSelectedNode:()=>{o(),s=null,r?.disconnect(),i?.disconnect()},getEditableNode:()=>l.getEditableNode(),cleanup:()=>{v(),r?.disconnect(),i?.disconnect(),l.blurEditMode(),c.cleanup()}};var E,S;return E="nodeTools",S=f,"undefined"!=typeof window&&(window[E]=S),f},e.createViewport=e=>{const t=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",A.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 i=!1,s=0,l=0;const a=n(n=>{if(!i)return;t&&(t.style.cursor="ew-resize");const o=L(n,s,l);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(),i=!0,s=t.clientX,l=e.offsetWidth},a,e=>{e.preventDefault(),e.stopPropagation(),t&&(t.style.cursor="default"),i=!1},()=>{i=!1});return{setWidth:t=>{x(e,t)},cleanup:()=>{i=!1,a?.cleanup(),d(),r.remove()}}}});
|
|
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";const t=(e,t="canvas")=>{const n=window[t];return e.reduce((e,t)=>e?.[t],n)};function n(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 o=()=>{const e=document.body.querySelector(".highlight-frame-overlay");e&&e.remove();const t=document.body.querySelector(".highlight-frame-tools-wrapper");t&&t.remove()},r=["path","rect","circle","ellipse","polygon","line","polyline","text","text-noci"];let s=[],i=0;const a=(e,t)=>{let n=null;const o=e.clientX,a=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,a).filter(e=>!r.includes(e.tagName.toLowerCase())&&!e.classList.contains("select-none")&&!(e=>{let t=e.parentElement;for(;t;){if("true"===t.getAttribute("data-instance"))return!0;if("node-provider"===t.getAttribute("data-role"))break;t=t.parentElement}return!1})(e));if(t&&d.includes(t))return t;if(l)return s=[],n=d[0],n;var c,u;u=d,(c=s).length===u.length&&c.every((e,t)=>e===u[t])?i<=d.length&&i++:i=0;return n=d[d.length-1-i],s=d,n},l=(e,t,n,r)=>{const s=e=>{((e,t)=>{if("application"===e.data.source&&"selectedNodeChanged"===e.data.action){const o=e.data.data,r=document.querySelector(`[data-node-id="${o}"]`);if(n=r,n?.classList.contains("select-none"))return void t?.(null);r&&t?.(r)}var n})(e,t)},i=n=>{((e,t,n,r)=>{if(e.preventDefault(),e.stopPropagation(),t&&!t.contains(e.target))return o(),void r(null);r(a(e,n))})(n,e,r(),t)},l=e=>{"Escape"===e.key&&(e.preventDefault(),e.stopPropagation(),n?.())};return window.addEventListener("message",s),document.addEventListener("click",i),document.addEventListener("keydown",l),()=>{window.removeEventListener("message",s),document.removeEventListener("click",i),document.removeEventListener("keydown",l)}},d=e=>"true"===e.getAttribute("data-instance"),c=(e,t,n,o,r=!1)=>{const s=document.createElementNS("http://www.w3.org/2000/svg","rect");return s.setAttribute("x",(t-3).toString()),s.setAttribute("y",(n-3).toString()),s.setAttribute("width",6..toString()),s.setAttribute("height",6..toString()),s.setAttribute("vector-effect","non-scaling-stroke"),s.classList.add("highlight-frame-handle",o),r&&s.setAttribute("stroke",getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim()||"oklch(65.6% 0.241 354.308)"),e.appendChild(s),s};function u(e){const t=e.getBoundingClientRect();return{top:t.top,left:t.left,width:t.width,height:t.height}}const m=(e,t=!1)=>{const{top:n,left:o,width:r,height:s}=u(e),i=document.createElementNS("http://www.w3.org/2000/svg","svg");i.classList.add("highlight-frame-overlay"),t&&i.classList.add("is-instance"),i.setAttribute("data-node-id",e.getAttribute("data-node-id")||""),i.style.position="fixed",i.style.top="0",i.style.left="0",i.style.width="100vw",i.style.height="100vh",i.style.pointerEvents="none",i.style.zIndex="5000";const a=document.documentElement.clientWidth||window.innerWidth,l=document.documentElement.clientHeight||window.innerHeight;i.setAttribute("width",a.toString()),i.setAttribute("height",l.toString());const d=document.createElementNS("http://www.w3.org/2000/svg","g");d.classList.add("highlight-frame-group"),d.setAttribute("transform",`translate(${o}, ${n})`);const m=document.createElementNS("http://www.w3.org/2000/svg","rect");return m.setAttribute("x","0"),m.setAttribute("y","0"),m.setAttribute("width",r.toString()),m.setAttribute("height",s.toString()),m.setAttribute("vector-effect","non-scaling-stroke"),m.classList.add("highlight-frame-rect"),t&&m.setAttribute("stroke",getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim()||"oklch(65.6% 0.241 354.308)"),d.appendChild(m),((e,t,n,o=!1)=>{c(e,0,0,"handle-top-left",o),c(e,t,0,"handle-top-right",o),c(e,t,n,"handle-bottom-right",o),c(e,0,n,"handle-bottom-left",o)})(d,r,s,t),i.appendChild(d),document.body.appendChild(i),i},h=(e,t,n=!1)=>{const o=document.createElement("div");o.className="node-tools",n&&o.classList.add("is-instance"),t.appendChild(o),((e,t)=>{const n=document.createElement("div");n.className="tag-label",n.textContent=e.tagName.toLowerCase(),t.appendChild(n)})(e,o)};function g(){return document.body.querySelector(".highlight-frame-overlay")}const p=()=>getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim()||"oklch(65.6% 0.241 354.308)",b=(e,n,o="canvas")=>{const r=g();if(!r)return;const s=d(e),i=document.documentElement.clientWidth||window.innerWidth,a=document.documentElement.clientHeight||window.innerHeight;r.setAttribute("width",i.toString()),r.setAttribute("height",a.toString()),s?r.classList.add("is-instance"):r.classList.remove("is-instance");const l=r.querySelector(".highlight-frame-group");if(!l)return;const c=l.querySelector("rect");if(!c)return;s?c.setAttribute("stroke",p()):c.removeAttribute("stroke");const m=document.body.querySelector(".highlight-frame-tools-wrapper"),h=m?.querySelector(".node-tools"),b=t(["zoom","current"],o)??1,v=u(e),{top:y,left:f,width:w,height:E}=v,S=y+E;m&&(s?m.classList.add("is-instance"):m.classList.remove("is-instance")),h&&(s?h.classList.add("is-instance"):h.classList.remove("is-instance")),l.setAttribute("transform",`translate(${f}, ${y})`),c.setAttribute("width",w.toString()),c.setAttribute("height",E.toString());const A=l.querySelector(".handle-top-left"),L=l.querySelector(".handle-top-right"),x=l.querySelector(".handle-bottom-right"),k=l.querySelector(".handle-bottom-left");[A,L,x,k].forEach(e=>{e&&(s?e.setAttribute("stroke",p()):e.removeAttribute("stroke"))}),A&&(A.setAttribute("x",(-3).toString()),A.setAttribute("y",(-3).toString())),L&&(L.setAttribute("x",(w-3).toString()),L.setAttribute("y",(-3).toString())),x&&(x.setAttribute("x",(w-3).toString()),x.setAttribute("y",(E-3).toString())),k&&(k.setAttribute("x",(-3).toString()),k.setAttribute("y",(E-3).toString())),m&&(m.style.left=`${f}px`,m.style.top=`${S}px`),b<=10?n.style.setProperty("--tool-opacity","1"):n.style.setProperty("--tool-opacity","0")},v=e=>{const t=g();if(!t)return;const n=e.classList.contains("hidden")||e.classList.contains("select-none")?"none":"";t.style.display=n;const o=document.body.querySelector(".highlight-frame-tools-wrapper");o&&(o.style.display=n)},y=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,n="canvas")=>{const o=((e,t)=>{const n=new MutationObserver(e=>{t(e)});return n.observe(e,{subtree:!0,childList:!0,characterData:!0}),n})(e,()=>{b(e,t,n)});return()=>o.disconnect()},w=(e="canvas")=>{let n=null,o=!1,r=null;const s=()=>{if(o||!n)return;o=!0;var s;(s=n).contentEditable="false",s.classList.remove("is-editable"),s.style.outline="none",((e="canvas")=>{const n=t(["keyboard","disableTextEditMode"],e);n?.()})(e),r?.(),n=null,o=!1};return{enableEditMode:(o,i)=>{if(n===o)return;n&&n!==o&&s();const a=(e=>Array.from(e.childNodes).some(e=>e.nodeType===Node.TEXT_NODE&&e.textContent?.trim()))(o);a&&(n=o,(e=>{e.contentEditable="true",e.classList.add("is-editable"),e.style.outline="none"})(o),((e="canvas")=>{const n=t(["keyboard","enableTextEditMode"],e);n?.()})(e),r=((e,t,n,o="canvas")=>{if(!t)return()=>{};e.addEventListener("blur",n);const r=y(e),s=f(e,t,o);return()=>{e.removeEventListener("blur",n),r(),s?.()}})(o,i,s,e))},blurEditMode:s,getEditableNode:()=>n,isEditing:()=>null!==n}},E=320,S=1680,A=[{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"}],L=(e,t,n)=>{const o=parseFloat(document.body.dataset.zoom||"1"),r=((e,t)=>{const n=e+Math.round(t);return Math.max(E,Math.min(S,n))})(n,(e.clientX-t)/o);return r},x=(e,t)=>{e.style.setProperty("--container-width",`${t}px`),((e,t)=>{e.querySelectorAll(".resize-preset-button").forEach((e,n)=>{n<A.length&&(A[n].rawValue===t?e.classList.add("is-active"):e.classList.remove("is-active"))})})(e,t)};e.createCanvasObserver=function(e="canvas"){const n=document.querySelector(".transform-layer");if(!n)return{disconnect:()=>{}};const o=new MutationObserver(()=>{((e="canvas")=>{const n=t(["zoom","current"],e)??1;document.body.style.setProperty("--zoom",n.toFixed(5)),document.body.style.setProperty("--stroke-width",(2/n).toFixed(3)),document.body.dataset.zoom=n.toFixed(5),document.body.dataset.strokeWidth=(2/n).toFixed(3)})(e);const n=window.nodeTools;n?.refreshHighlightFrame&&n.refreshHighlightFrame()});return o.observe(n,{attributes:!0,attributeOldValue:!0,subtree:!0,childList:!0}),{disconnect:function(){o.disconnect()}}},e.createNodeTools=(e,t="canvas")=>{const r=e;let s=null,i=null,a=null;const c=w(t),p=n((e,n)=>{b(e,n,t),v(e)}),y=e=>{if(a!==e){if(c.isEditing()){const t=c.getEditableNode();t&&t!==e&&c.blurEditMode()}var n,o;s?.disconnect(),i?.disconnect(),e&&r&&(c.enableEditMode(e,r),i=new MutationObserver(()=>{console.log("mutationObserver",e),b(e,r,t),v(e)}),i.observe(e,{attributes:!0,characterData:!0}),s=((e,t)=>{const n=new ResizeObserver(e=>{t(e)});return n.observe(e),n})(e,()=>{console.log("resizeObserver",e),b(e,r,t),v(e)})),a=e,n="selectedNodeChanged",o=e?.getAttribute("data-node-id")??null,window.parent.postMessage({source:"node-edit-utils",action:n,data:o,timestamp:Date.now()},"*"),(e=>{if(!e)return;const t=g(),n=document.body.querySelector(".highlight-frame-tools-wrapper");t&&t.remove(),n&&n.remove();const o=d(e),r=m(e,o);"true"===e.contentEditable&&r.classList.add("is-editable");const{left:s,top:i,height:a}=u(e),l=i+a,c=document.createElement("div");c.classList.add("highlight-frame-tools-wrapper"),o&&c.classList.add("is-instance"),c.style.position="fixed",c.style.left=`${s}px`,c.style.top=`${l}px`,c.style.transform="translateX(-50%)",c.style.transformOrigin="center",c.style.pointerEvents="none",c.style.zIndex="5000",h(e,c,o),document.body.appendChild(c)})(e),e&&r&&v(e)}},f=l(r,y,()=>{c.isEditing()&&c.blurEditMode(),a&&r&&(o(),a=null,s?.disconnect(),i?.disconnect())},c.getEditableNode),E={selectNode:y,getSelectedNode:()=>a,refreshHighlightFrame:()=>{a&&r&&(b(a,r,t),v(a))},clearSelectedNode:()=>{o(),a=null,s?.disconnect(),i?.disconnect()},getEditableNode:()=>c.getEditableNode(),cleanup:()=>{f(),s?.disconnect(),i?.disconnect(),c.blurEditMode(),p.cleanup()}};var S,A;return S="nodeTools",A=E,"undefined"!=typeof window&&(window[S]=A),E},e.createViewport=e=>{const t=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",A.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,i=0,a=0;const l=n(n=>{if(!s)return;t&&(t.style.cursor="ew-resize");const o=L(n,i,a);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,i=t.clientX,a=e.offsetWidth},l,e=>{e.preventDefault(),e.stopPropagation(),t&&(t.style.cursor="default"),s=!1},()=>{s=!1});return{setWidth:t=>{x(e,t)},cleanup:()=>{s=!1,l?.cleanup(),d(),r.remove()}}}});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { applyCanvasState } from "./helpers/applyCanvasState";
|
|
2
2
|
import type { CanvasObserver } from "./types";
|
|
3
3
|
|
|
4
|
-
export function createCanvasObserver(): CanvasObserver {
|
|
4
|
+
export function createCanvasObserver(canvasName: string = "canvas"): CanvasObserver {
|
|
5
5
|
const transformLayer = document.querySelector(".transform-layer");
|
|
6
6
|
|
|
7
7
|
if (!transformLayer) {
|
|
@@ -11,7 +11,7 @@ export function createCanvasObserver(): CanvasObserver {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
const observer = new MutationObserver(() => {
|
|
14
|
-
applyCanvasState();
|
|
14
|
+
applyCanvasState(canvasName);
|
|
15
15
|
|
|
16
16
|
// Refresh highlight frame (throttled via withRAFThrottle)
|
|
17
17
|
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getCanvasWindowValue } from "@/lib/canvas/helpers/getCanvasWindowValue";
|
|
2
2
|
|
|
3
|
-
export const disableCanvasKeyboard = () => {
|
|
4
|
-
const disable = getCanvasWindowValue(["keyboard", "disable"]);
|
|
3
|
+
export const disableCanvasKeyboard = (canvasName: string = "canvas") => {
|
|
4
|
+
const disable = getCanvasWindowValue(["keyboard", "disable"], canvasName);
|
|
5
5
|
|
|
6
6
|
disable?.();
|
|
7
7
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getCanvasWindowValue } from "@/lib/canvas/helpers/getCanvasWindowValue";
|
|
2
2
|
|
|
3
|
-
export const disableCanvasTextMode = () => {
|
|
4
|
-
const disableTextEditMode = getCanvasWindowValue(["keyboard", "disableTextEditMode"]);
|
|
3
|
+
export const disableCanvasTextMode = (canvasName: string = "canvas") => {
|
|
4
|
+
const disableTextEditMode = getCanvasWindowValue(["keyboard", "disableTextEditMode"], canvasName);
|
|
5
5
|
|
|
6
6
|
disableTextEditMode?.();
|
|
7
7
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getCanvasWindowValue } from "@/lib/canvas/helpers/getCanvasWindowValue";
|
|
2
2
|
|
|
3
|
-
export const enableCanvasKeyboard = () => {
|
|
4
|
-
const enable = getCanvasWindowValue(["keyboard", "enable"]);
|
|
3
|
+
export const enableCanvasKeyboard = (canvasName: string = "canvas") => {
|
|
4
|
+
const enable = getCanvasWindowValue(["keyboard", "enable"], canvasName);
|
|
5
5
|
|
|
6
6
|
enable?.();
|
|
7
7
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getCanvasWindowValue } from "@/lib/canvas/helpers/getCanvasWindowValue";
|
|
2
2
|
|
|
3
|
-
export const enableCanvasTextMode = () => {
|
|
4
|
-
const enableTextEditMode = getCanvasWindowValue(["keyboard", "enableTextEditMode"]);
|
|
3
|
+
export const enableCanvasTextMode = (canvasName: string = "canvas") => {
|
|
4
|
+
const enableTextEditMode = getCanvasWindowValue(["keyboard", "enableTextEditMode"], canvasName);
|
|
5
5
|
|
|
6
6
|
enableTextEditMode?.();
|
|
7
7
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getCanvasWindowValue } from "./getCanvasWindowValue";
|
|
2
2
|
|
|
3
|
-
export const applyCanvasState = () => {
|
|
4
|
-
const zoom: number = getCanvasWindowValue(["zoom", "current"]);
|
|
3
|
+
export const applyCanvasState = (canvasName: string = "canvas") => {
|
|
4
|
+
const zoom: number = getCanvasWindowValue(["zoom", "current"], canvasName) ?? 1;
|
|
5
5
|
|
|
6
6
|
document.body.style.setProperty("--zoom", zoom.toFixed(5));
|
|
7
7
|
document.body.style.setProperty("--stroke-width", (2 / zoom).toFixed(3));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export const getCanvasWindowValue = (path: string[]) => {
|
|
1
|
+
export const getCanvasWindowValue = (path: string[], canvasName: string = "canvas") => {
|
|
2
2
|
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
3
|
-
const canvas = (window as any)
|
|
3
|
+
const canvas = (window as any)[canvasName];
|
|
4
4
|
return path.reduce((obj, prop) => obj?.[prop], canvas);
|
|
5
5
|
};
|
|
@@ -10,18 +10,18 @@ import { updateHighlightFrameVisibility } from "./highlight/updateHighlightFrame
|
|
|
10
10
|
import { nodeText } from "./text/nodeText";
|
|
11
11
|
import type { NodeTools } from "./types";
|
|
12
12
|
|
|
13
|
-
export const createNodeTools = (element: HTMLElement | null): NodeTools => {
|
|
13
|
+
export const createNodeTools = (element: HTMLElement | null, canvasName: string = "canvas"): NodeTools => {
|
|
14
14
|
const nodeProvider = element;
|
|
15
15
|
|
|
16
16
|
let resizeObserver: ResizeObserver | null = null;
|
|
17
17
|
let mutationObserver: MutationObserver | null = null;
|
|
18
18
|
let selectedNode: HTMLElement | null = null;
|
|
19
19
|
|
|
20
|
-
const text = nodeText();
|
|
20
|
+
const text = nodeText(canvasName);
|
|
21
21
|
|
|
22
22
|
// Combined throttled function for refresh + visibility update
|
|
23
23
|
const throttledRefreshAndVisibility = withRAFThrottle((node: HTMLElement, nodeProvider: HTMLElement) => {
|
|
24
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
24
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
25
25
|
updateHighlightFrameVisibility(node);
|
|
26
26
|
});
|
|
27
27
|
|
|
@@ -62,7 +62,7 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
|
|
|
62
62
|
mutationObserver = new MutationObserver(() => {
|
|
63
63
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
64
64
|
console.log("mutationObserver", node);
|
|
65
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
65
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
66
66
|
updateHighlightFrameVisibility(node);
|
|
67
67
|
});
|
|
68
68
|
|
|
@@ -74,7 +74,7 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
|
|
|
74
74
|
resizeObserver = connectResizeObserver(node, () => {
|
|
75
75
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
76
76
|
console.log("resizeObserver", node);
|
|
77
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
77
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
78
78
|
updateHighlightFrameVisibility(node);
|
|
79
79
|
});
|
|
80
80
|
}
|
|
@@ -107,7 +107,7 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
|
|
|
107
107
|
if (selectedNode && nodeProvider) {
|
|
108
108
|
// Call directly (not throttled) since this is typically called from already-throttled contexts
|
|
109
109
|
// to avoid double RAF
|
|
110
|
-
refreshHighlightFrame(selectedNode, nodeProvider);
|
|
110
|
+
refreshHighlightFrame(selectedNode, nodeProvider, canvasName);
|
|
111
111
|
updateHighlightFrameVisibility(selectedNode);
|
|
112
112
|
}
|
|
113
113
|
},
|
|
@@ -2,7 +2,8 @@ import { getCanvasWindowValue } from "@/lib/canvas/helpers/getCanvasWindowValue"
|
|
|
2
2
|
|
|
3
3
|
export function getElementBounds(
|
|
4
4
|
element: Element,
|
|
5
|
-
nodeProvider: HTMLElement
|
|
5
|
+
nodeProvider: HTMLElement,
|
|
6
|
+
canvasName: string = "canvas"
|
|
6
7
|
): {
|
|
7
8
|
top: number;
|
|
8
9
|
left: number;
|
|
@@ -15,7 +16,7 @@ export function getElementBounds(
|
|
|
15
16
|
const relativeTop = elementRect.top - componentRootRect.top;
|
|
16
17
|
const relativeLeft = elementRect.left - componentRootRect.left;
|
|
17
18
|
|
|
18
|
-
const zoom = getCanvasWindowValue(["zoom", "current"]) ?? 1;
|
|
19
|
+
const zoom = getCanvasWindowValue(["zoom", "current"], canvasName) ?? 1;
|
|
19
20
|
|
|
20
21
|
const top = parseFloat((relativeTop / zoom).toFixed(5));
|
|
21
22
|
const left = parseFloat((relativeLeft / zoom).toFixed(5));
|
|
@@ -7,7 +7,7 @@ const getComponentColor = (): string => {
|
|
|
7
7
|
return getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim() || "oklch(65.6% 0.241 354.308)";
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
export const refreshHighlightFrame = (node: HTMLElement, nodeProvider: HTMLElement) => {
|
|
10
|
+
export const refreshHighlightFrame = (node: HTMLElement, nodeProvider: HTMLElement, canvasName: string = "canvas") => {
|
|
11
11
|
// Batch all DOM reads first (single layout pass)
|
|
12
12
|
const frame = getHighlightFrameElement();
|
|
13
13
|
if (!frame) return;
|
|
@@ -44,7 +44,7 @@ export const refreshHighlightFrame = (node: HTMLElement, nodeProvider: HTMLEleme
|
|
|
44
44
|
const toolsWrapper = document.body.querySelector(".highlight-frame-tools-wrapper") as HTMLElement | null;
|
|
45
45
|
const nodeTools = toolsWrapper?.querySelector(".node-tools") as HTMLElement | null;
|
|
46
46
|
|
|
47
|
-
const zoom = getCanvasWindowValue(["zoom", "current"]) ?? 1;
|
|
47
|
+
const zoom = getCanvasWindowValue(["zoom", "current"], canvasName) ?? 1;
|
|
48
48
|
const bounds = getScreenBounds(node);
|
|
49
49
|
|
|
50
50
|
// Calculate all values before any DOM writes
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { connectMutationObserver } from "../../../helpers/observer/connectMutationObserver";
|
|
2
2
|
import { refreshHighlightFrame } from "../../highlight/refreshHighlightFrame";
|
|
3
3
|
|
|
4
|
-
export const setupMutationObserver = (node: HTMLElement, nodeProvider: HTMLElement): (() => void) | undefined => {
|
|
4
|
+
export const setupMutationObserver = (node: HTMLElement, nodeProvider: HTMLElement, canvasName: string = "canvas"): (() => void) | undefined => {
|
|
5
5
|
const mutationObserver = connectMutationObserver(node, () => {
|
|
6
|
-
refreshHighlightFrame(node, nodeProvider);
|
|
6
|
+
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
return () => mutationObserver.disconnect();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { setupKeydownHandler } from "./setupKeydownHandler";
|
|
2
2
|
import { setupMutationObserver } from "./setupMutationObserver";
|
|
3
3
|
|
|
4
|
-
export const setupNodeListeners = (node: HTMLElement, nodeProvider: HTMLElement | null, blur: () => void): (() => void) => {
|
|
4
|
+
export const setupNodeListeners = (node: HTMLElement, nodeProvider: HTMLElement | null, blur: () => void, canvasName: string = "canvas"): (() => void) => {
|
|
5
5
|
if (!nodeProvider) {
|
|
6
6
|
return () => {};
|
|
7
7
|
}
|
|
@@ -10,7 +10,7 @@ export const setupNodeListeners = (node: HTMLElement, nodeProvider: HTMLElement
|
|
|
10
10
|
|
|
11
11
|
const keydownCleanup = setupKeydownHandler(node);
|
|
12
12
|
|
|
13
|
-
const mutationCleanup = setupMutationObserver(node, nodeProvider);
|
|
13
|
+
const mutationCleanup = setupMutationObserver(node, nodeProvider, canvasName);
|
|
14
14
|
|
|
15
15
|
return () => {
|
|
16
16
|
node.removeEventListener("blur", blur);
|
|
@@ -6,7 +6,7 @@ import { makeNodeEditable } from "./helpers/makeNodeEditable";
|
|
|
6
6
|
import { makeNodeNonEditable } from "./helpers/makeNodeNonEditable";
|
|
7
7
|
import type { NodeText } from "./types";
|
|
8
8
|
|
|
9
|
-
export const nodeText = (): NodeText => {
|
|
9
|
+
export const nodeText = (canvasName: string = "canvas"): NodeText => {
|
|
10
10
|
let editableNode: HTMLElement | null = null;
|
|
11
11
|
let blurInProgress: boolean = false;
|
|
12
12
|
let cleanup: (() => void) | null = null;
|
|
@@ -26,9 +26,9 @@ export const nodeText = (): NodeText => {
|
|
|
26
26
|
editableNode = node;
|
|
27
27
|
|
|
28
28
|
makeNodeEditable(node);
|
|
29
|
-
enableCanvasTextMode();
|
|
29
|
+
enableCanvasTextMode(canvasName);
|
|
30
30
|
|
|
31
|
-
cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
|
|
31
|
+
cleanup = setupNodeListeners(node, nodeProvider, blurEditMode, canvasName);
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
34
|
|
|
@@ -50,7 +50,7 @@ export const nodeText = (): NodeText => {
|
|
|
50
50
|
const nodeToCleanup = editableNode;
|
|
51
51
|
|
|
52
52
|
makeNodeNonEditable(nodeToCleanup);
|
|
53
|
-
disableCanvasTextMode();
|
|
53
|
+
disableCanvasTextMode(canvasName);
|
|
54
54
|
cleanup?.();
|
|
55
55
|
|
|
56
56
|
editableNode = null;
|