@node-edit-utils/core 2.2.8 → 2.2.9
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/node-edit-utils.cjs.js +67 -32
- package/dist/node-edit-utils.esm.js +67 -32
- package/dist/node-edit-utils.umd.js +67 -32
- package/dist/node-edit-utils.umd.min.js +1 -1
- package/package.json +1 -1
- package/src/lib/node-tools/text/events/setupMutationObserver.ts +42 -6
- package/src/lib/node-tools/text/helpers/handleTextChange.ts +2 -0
|
@@ -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.9
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
@@ -645,32 +645,6 @@ const connectMutationObserver = (element, handler) => {
|
|
|
645
645
|
return mutationObserver;
|
|
646
646
|
};
|
|
647
647
|
|
|
648
|
-
// biome-ignore lint/suspicious/noExplicitAny: generic constraint requires flexibility
|
|
649
|
-
function withRAFThrottle(func) {
|
|
650
|
-
let rafId = null;
|
|
651
|
-
let lastArgs = null;
|
|
652
|
-
const throttled = (...args) => {
|
|
653
|
-
lastArgs = args;
|
|
654
|
-
if (rafId === null) {
|
|
655
|
-
rafId = requestAnimationFrame(() => {
|
|
656
|
-
if (lastArgs) {
|
|
657
|
-
func(...lastArgs);
|
|
658
|
-
}
|
|
659
|
-
rafId = null;
|
|
660
|
-
lastArgs = null;
|
|
661
|
-
});
|
|
662
|
-
}
|
|
663
|
-
};
|
|
664
|
-
throttled.cleanup = () => {
|
|
665
|
-
if (rafId !== null) {
|
|
666
|
-
cancelAnimationFrame(rafId);
|
|
667
|
-
rafId = null;
|
|
668
|
-
lastArgs = null;
|
|
669
|
-
}
|
|
670
|
-
};
|
|
671
|
-
return throttled;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
648
|
const handleTextChange = (node, mutations) => {
|
|
675
649
|
// Check if any mutation is a text content change
|
|
676
650
|
const hasTextChange = mutations.some((mutation) => {
|
|
@@ -684,6 +658,7 @@ const handleTextChange = (node, mutations) => {
|
|
|
684
658
|
const textContent = node.textContent ?? "";
|
|
685
659
|
// Get the node ID
|
|
686
660
|
const nodeId = node.getAttribute("data-node-id");
|
|
661
|
+
console.log("textContentChanged", nodeId, textContent);
|
|
687
662
|
// Send postMessage with the text change
|
|
688
663
|
sendPostMessage("textContentChanged", {
|
|
689
664
|
nodeId,
|
|
@@ -692,16 +667,50 @@ const handleTextChange = (node, mutations) => {
|
|
|
692
667
|
};
|
|
693
668
|
|
|
694
669
|
const setupMutationObserver = (node, nodeProvider, canvasName = "canvas") => {
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
670
|
+
// Accumulate mutations instead of replacing them
|
|
671
|
+
let pendingMutations = [];
|
|
672
|
+
let rafId1 = null;
|
|
673
|
+
let rafId2 = null;
|
|
674
|
+
const processMutations = () => {
|
|
675
|
+
if (pendingMutations.length > 0) {
|
|
676
|
+
const mutationsToProcess = [...pendingMutations];
|
|
677
|
+
pendingMutations = [];
|
|
678
|
+
handleTextChange(node, mutationsToProcess);
|
|
679
|
+
}
|
|
680
|
+
};
|
|
681
|
+
const scheduleProcess = () => {
|
|
682
|
+
if (rafId1 === null) {
|
|
683
|
+
rafId1 = requestAnimationFrame(() => {
|
|
684
|
+
// First RAF: let browser complete layout
|
|
685
|
+
rafId2 = requestAnimationFrame(() => {
|
|
686
|
+
// Second RAF: read textContent after layout is complete
|
|
687
|
+
processMutations();
|
|
688
|
+
rafId1 = null;
|
|
689
|
+
rafId2 = null;
|
|
690
|
+
});
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
const cleanup = () => {
|
|
695
|
+
if (rafId1 !== null) {
|
|
696
|
+
cancelAnimationFrame(rafId1);
|
|
697
|
+
rafId1 = null;
|
|
698
|
+
}
|
|
699
|
+
if (rafId2 !== null) {
|
|
700
|
+
cancelAnimationFrame(rafId2);
|
|
701
|
+
rafId2 = null;
|
|
702
|
+
}
|
|
703
|
+
pendingMutations = [];
|
|
704
|
+
};
|
|
698
705
|
const mutationObserver = connectMutationObserver(node, (mutations) => {
|
|
699
|
-
|
|
706
|
+
// Accumulate mutations instead of replacing
|
|
707
|
+
pendingMutations.push(...mutations);
|
|
708
|
+
scheduleProcess();
|
|
700
709
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
701
710
|
});
|
|
702
711
|
return () => {
|
|
703
712
|
mutationObserver.disconnect();
|
|
704
|
-
|
|
713
|
+
cleanup();
|
|
705
714
|
};
|
|
706
715
|
};
|
|
707
716
|
|
|
@@ -915,6 +924,32 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
915
924
|
return nodeTools;
|
|
916
925
|
};
|
|
917
926
|
|
|
927
|
+
// biome-ignore lint/suspicious/noExplicitAny: generic constraint requires flexibility
|
|
928
|
+
function withRAFThrottle(func) {
|
|
929
|
+
let rafId = null;
|
|
930
|
+
let lastArgs = null;
|
|
931
|
+
const throttled = (...args) => {
|
|
932
|
+
lastArgs = args;
|
|
933
|
+
if (rafId === null) {
|
|
934
|
+
rafId = requestAnimationFrame(() => {
|
|
935
|
+
if (lastArgs) {
|
|
936
|
+
func(...lastArgs);
|
|
937
|
+
}
|
|
938
|
+
rafId = null;
|
|
939
|
+
lastArgs = null;
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
};
|
|
943
|
+
throttled.cleanup = () => {
|
|
944
|
+
if (rafId !== null) {
|
|
945
|
+
cancelAnimationFrame(rafId);
|
|
946
|
+
rafId = null;
|
|
947
|
+
lastArgs = null;
|
|
948
|
+
}
|
|
949
|
+
};
|
|
950
|
+
return throttled;
|
|
951
|
+
}
|
|
952
|
+
|
|
918
953
|
const DEFAULT_WIDTH = 400;
|
|
919
954
|
const RESIZE_CONFIG = {
|
|
920
955
|
minWidth: 320,
|
|
@@ -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.9
|
|
5
5
|
*/
|
|
6
6
|
const getCanvasWindowValue = (path, canvasName = "canvas") => {
|
|
7
7
|
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
@@ -643,32 +643,6 @@ const connectMutationObserver = (element, handler) => {
|
|
|
643
643
|
return mutationObserver;
|
|
644
644
|
};
|
|
645
645
|
|
|
646
|
-
// biome-ignore lint/suspicious/noExplicitAny: generic constraint requires flexibility
|
|
647
|
-
function withRAFThrottle(func) {
|
|
648
|
-
let rafId = null;
|
|
649
|
-
let lastArgs = null;
|
|
650
|
-
const throttled = (...args) => {
|
|
651
|
-
lastArgs = args;
|
|
652
|
-
if (rafId === null) {
|
|
653
|
-
rafId = requestAnimationFrame(() => {
|
|
654
|
-
if (lastArgs) {
|
|
655
|
-
func(...lastArgs);
|
|
656
|
-
}
|
|
657
|
-
rafId = null;
|
|
658
|
-
lastArgs = null;
|
|
659
|
-
});
|
|
660
|
-
}
|
|
661
|
-
};
|
|
662
|
-
throttled.cleanup = () => {
|
|
663
|
-
if (rafId !== null) {
|
|
664
|
-
cancelAnimationFrame(rafId);
|
|
665
|
-
rafId = null;
|
|
666
|
-
lastArgs = null;
|
|
667
|
-
}
|
|
668
|
-
};
|
|
669
|
-
return throttled;
|
|
670
|
-
}
|
|
671
|
-
|
|
672
646
|
const handleTextChange = (node, mutations) => {
|
|
673
647
|
// Check if any mutation is a text content change
|
|
674
648
|
const hasTextChange = mutations.some((mutation) => {
|
|
@@ -682,6 +656,7 @@ const handleTextChange = (node, mutations) => {
|
|
|
682
656
|
const textContent = node.textContent ?? "";
|
|
683
657
|
// Get the node ID
|
|
684
658
|
const nodeId = node.getAttribute("data-node-id");
|
|
659
|
+
console.log("textContentChanged", nodeId, textContent);
|
|
685
660
|
// Send postMessage with the text change
|
|
686
661
|
sendPostMessage("textContentChanged", {
|
|
687
662
|
nodeId,
|
|
@@ -690,16 +665,50 @@ const handleTextChange = (node, mutations) => {
|
|
|
690
665
|
};
|
|
691
666
|
|
|
692
667
|
const setupMutationObserver = (node, nodeProvider, canvasName = "canvas") => {
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
668
|
+
// Accumulate mutations instead of replacing them
|
|
669
|
+
let pendingMutations = [];
|
|
670
|
+
let rafId1 = null;
|
|
671
|
+
let rafId2 = null;
|
|
672
|
+
const processMutations = () => {
|
|
673
|
+
if (pendingMutations.length > 0) {
|
|
674
|
+
const mutationsToProcess = [...pendingMutations];
|
|
675
|
+
pendingMutations = [];
|
|
676
|
+
handleTextChange(node, mutationsToProcess);
|
|
677
|
+
}
|
|
678
|
+
};
|
|
679
|
+
const scheduleProcess = () => {
|
|
680
|
+
if (rafId1 === null) {
|
|
681
|
+
rafId1 = requestAnimationFrame(() => {
|
|
682
|
+
// First RAF: let browser complete layout
|
|
683
|
+
rafId2 = requestAnimationFrame(() => {
|
|
684
|
+
// Second RAF: read textContent after layout is complete
|
|
685
|
+
processMutations();
|
|
686
|
+
rafId1 = null;
|
|
687
|
+
rafId2 = null;
|
|
688
|
+
});
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
const cleanup = () => {
|
|
693
|
+
if (rafId1 !== null) {
|
|
694
|
+
cancelAnimationFrame(rafId1);
|
|
695
|
+
rafId1 = null;
|
|
696
|
+
}
|
|
697
|
+
if (rafId2 !== null) {
|
|
698
|
+
cancelAnimationFrame(rafId2);
|
|
699
|
+
rafId2 = null;
|
|
700
|
+
}
|
|
701
|
+
pendingMutations = [];
|
|
702
|
+
};
|
|
696
703
|
const mutationObserver = connectMutationObserver(node, (mutations) => {
|
|
697
|
-
|
|
704
|
+
// Accumulate mutations instead of replacing
|
|
705
|
+
pendingMutations.push(...mutations);
|
|
706
|
+
scheduleProcess();
|
|
698
707
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
699
708
|
});
|
|
700
709
|
return () => {
|
|
701
710
|
mutationObserver.disconnect();
|
|
702
|
-
|
|
711
|
+
cleanup();
|
|
703
712
|
};
|
|
704
713
|
};
|
|
705
714
|
|
|
@@ -913,6 +922,32 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
913
922
|
return nodeTools;
|
|
914
923
|
};
|
|
915
924
|
|
|
925
|
+
// biome-ignore lint/suspicious/noExplicitAny: generic constraint requires flexibility
|
|
926
|
+
function withRAFThrottle(func) {
|
|
927
|
+
let rafId = null;
|
|
928
|
+
let lastArgs = null;
|
|
929
|
+
const throttled = (...args) => {
|
|
930
|
+
lastArgs = args;
|
|
931
|
+
if (rafId === null) {
|
|
932
|
+
rafId = requestAnimationFrame(() => {
|
|
933
|
+
if (lastArgs) {
|
|
934
|
+
func(...lastArgs);
|
|
935
|
+
}
|
|
936
|
+
rafId = null;
|
|
937
|
+
lastArgs = null;
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
};
|
|
941
|
+
throttled.cleanup = () => {
|
|
942
|
+
if (rafId !== null) {
|
|
943
|
+
cancelAnimationFrame(rafId);
|
|
944
|
+
rafId = null;
|
|
945
|
+
lastArgs = null;
|
|
946
|
+
}
|
|
947
|
+
};
|
|
948
|
+
return throttled;
|
|
949
|
+
}
|
|
950
|
+
|
|
916
951
|
const DEFAULT_WIDTH = 400;
|
|
917
952
|
const RESIZE_CONFIG = {
|
|
918
953
|
minWidth: 320,
|
|
@@ -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.9
|
|
5
5
|
*/
|
|
6
6
|
(function (global, factory) {
|
|
7
7
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
@@ -649,32 +649,6 @@
|
|
|
649
649
|
return mutationObserver;
|
|
650
650
|
};
|
|
651
651
|
|
|
652
|
-
// biome-ignore lint/suspicious/noExplicitAny: generic constraint requires flexibility
|
|
653
|
-
function withRAFThrottle(func) {
|
|
654
|
-
let rafId = null;
|
|
655
|
-
let lastArgs = null;
|
|
656
|
-
const throttled = (...args) => {
|
|
657
|
-
lastArgs = args;
|
|
658
|
-
if (rafId === null) {
|
|
659
|
-
rafId = requestAnimationFrame(() => {
|
|
660
|
-
if (lastArgs) {
|
|
661
|
-
func(...lastArgs);
|
|
662
|
-
}
|
|
663
|
-
rafId = null;
|
|
664
|
-
lastArgs = null;
|
|
665
|
-
});
|
|
666
|
-
}
|
|
667
|
-
};
|
|
668
|
-
throttled.cleanup = () => {
|
|
669
|
-
if (rafId !== null) {
|
|
670
|
-
cancelAnimationFrame(rafId);
|
|
671
|
-
rafId = null;
|
|
672
|
-
lastArgs = null;
|
|
673
|
-
}
|
|
674
|
-
};
|
|
675
|
-
return throttled;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
652
|
const handleTextChange = (node, mutations) => {
|
|
679
653
|
// Check if any mutation is a text content change
|
|
680
654
|
const hasTextChange = mutations.some((mutation) => {
|
|
@@ -688,6 +662,7 @@
|
|
|
688
662
|
const textContent = node.textContent ?? "";
|
|
689
663
|
// Get the node ID
|
|
690
664
|
const nodeId = node.getAttribute("data-node-id");
|
|
665
|
+
console.log("textContentChanged", nodeId, textContent);
|
|
691
666
|
// Send postMessage with the text change
|
|
692
667
|
sendPostMessage("textContentChanged", {
|
|
693
668
|
nodeId,
|
|
@@ -696,16 +671,50 @@
|
|
|
696
671
|
};
|
|
697
672
|
|
|
698
673
|
const setupMutationObserver = (node, nodeProvider, canvasName = "canvas") => {
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
674
|
+
// Accumulate mutations instead of replacing them
|
|
675
|
+
let pendingMutations = [];
|
|
676
|
+
let rafId1 = null;
|
|
677
|
+
let rafId2 = null;
|
|
678
|
+
const processMutations = () => {
|
|
679
|
+
if (pendingMutations.length > 0) {
|
|
680
|
+
const mutationsToProcess = [...pendingMutations];
|
|
681
|
+
pendingMutations = [];
|
|
682
|
+
handleTextChange(node, mutationsToProcess);
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
const scheduleProcess = () => {
|
|
686
|
+
if (rafId1 === null) {
|
|
687
|
+
rafId1 = requestAnimationFrame(() => {
|
|
688
|
+
// First RAF: let browser complete layout
|
|
689
|
+
rafId2 = requestAnimationFrame(() => {
|
|
690
|
+
// Second RAF: read textContent after layout is complete
|
|
691
|
+
processMutations();
|
|
692
|
+
rafId1 = null;
|
|
693
|
+
rafId2 = null;
|
|
694
|
+
});
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
const cleanup = () => {
|
|
699
|
+
if (rafId1 !== null) {
|
|
700
|
+
cancelAnimationFrame(rafId1);
|
|
701
|
+
rafId1 = null;
|
|
702
|
+
}
|
|
703
|
+
if (rafId2 !== null) {
|
|
704
|
+
cancelAnimationFrame(rafId2);
|
|
705
|
+
rafId2 = null;
|
|
706
|
+
}
|
|
707
|
+
pendingMutations = [];
|
|
708
|
+
};
|
|
702
709
|
const mutationObserver = connectMutationObserver(node, (mutations) => {
|
|
703
|
-
|
|
710
|
+
// Accumulate mutations instead of replacing
|
|
711
|
+
pendingMutations.push(...mutations);
|
|
712
|
+
scheduleProcess();
|
|
704
713
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
705
714
|
});
|
|
706
715
|
return () => {
|
|
707
716
|
mutationObserver.disconnect();
|
|
708
|
-
|
|
717
|
+
cleanup();
|
|
709
718
|
};
|
|
710
719
|
};
|
|
711
720
|
|
|
@@ -919,6 +928,32 @@
|
|
|
919
928
|
return nodeTools;
|
|
920
929
|
};
|
|
921
930
|
|
|
931
|
+
// biome-ignore lint/suspicious/noExplicitAny: generic constraint requires flexibility
|
|
932
|
+
function withRAFThrottle(func) {
|
|
933
|
+
let rafId = null;
|
|
934
|
+
let lastArgs = null;
|
|
935
|
+
const throttled = (...args) => {
|
|
936
|
+
lastArgs = args;
|
|
937
|
+
if (rafId === null) {
|
|
938
|
+
rafId = requestAnimationFrame(() => {
|
|
939
|
+
if (lastArgs) {
|
|
940
|
+
func(...lastArgs);
|
|
941
|
+
}
|
|
942
|
+
rafId = null;
|
|
943
|
+
lastArgs = null;
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
};
|
|
947
|
+
throttled.cleanup = () => {
|
|
948
|
+
if (rafId !== null) {
|
|
949
|
+
cancelAnimationFrame(rafId);
|
|
950
|
+
rafId = null;
|
|
951
|
+
lastArgs = null;
|
|
952
|
+
}
|
|
953
|
+
};
|
|
954
|
+
return throttled;
|
|
955
|
+
}
|
|
956
|
+
|
|
922
957
|
const DEFAULT_WIDTH = 400;
|
|
923
958
|
const RESIZE_CONFIG = {
|
|
924
959
|
minWidth: 320,
|
|
@@ -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,t="canvas")=>{const n=window[t];return e.reduce((e,t)=>e?.[t],n)};function n(e,t){window.parent.postMessage({source:"node-edit-utils",action:e,data:t,timestamp:Date.now()},"*")}const o=()=>document.querySelector(".canvas-container"),r=()=>{const e=o()||document.body,t=e.querySelector(".highlight-frame-overlay");t&&t.remove();const n=e.querySelector(".highlight-frame-tools-wrapper");n&&n.remove()},s=(e,t,n)=>{e&&t&&n.enableEditMode(e,t)},i=["path","rect","circle","ellipse","polygon","line","polyline","text","text-noci"];let a=[],d=0,l=null;const c=(e,t,n)=>{let o=null;const r=e.clientX,c=e.clientY,u=e.metaKey||e.ctrlKey,m=((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})(r,c).filter(e=>!i.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)),h=n.getEditableNode();if(h&&m.includes(h))return o=h,l=o,o;if(u)return a=[],o=m[0],l&&l===o&&s(o,t,n),l=o,o;var g,p;p=m,(g=a).length===p.length&&g.every((e,t)=>e===p[t])?d<=m.length-2&&d++:d=0;return o=m[m.length-1-d],a=m,l&&l===o&&s(o,t,n),l=o,o},u=(e,t,n,o)=>{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,o)=>{if(e.preventDefault(),e.stopPropagation(),t&&!t.contains(e.target))return r(),void o(null);o(c(e,t,n))})(n,e,o,t)},a=e=>{"Escape"===e.key&&(e.preventDefault(),e.stopPropagation(),n?.())};return window.addEventListener("message",s),document.addEventListener("click",i),document.addEventListener("keydown",a),()=>{window.removeEventListener("message",s),document.removeEventListener("click",i),document.removeEventListener("keydown",a)}},m=e=>"true"===e.getAttribute("data-instance"),h=(e,t,n,o,r=!1,s=!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)"):s&&i.setAttribute("stroke",getComputedStyle(document.documentElement).getPropertyValue("--text-edit-color").trim()||"oklch(62.3% 0.214 259.815)"),e.appendChild(i),i};function g(e){const t=e.getBoundingClientRect();return{top:t.top,left:t.left,width:t.width,height:t.height}}const p=(e,t=!1,n=!1)=>{const{top:r,left:s,width:i,height:a}=g(e),d=Math.max(i,3),l=document.createElementNS("http://www.w3.org/2000/svg","svg");l.classList.add("highlight-frame-overlay"),t&&l.classList.add("is-instance"),n&&l.classList.add("is-text-edit"),l.setAttribute("data-node-id",e.getAttribute("data-node-id")||""),l.style.position="absolute",l.style.top="0",l.style.left="0",l.style.width="100vw",l.style.height="100vh",l.style.pointerEvents="none",l.style.zIndex="500";const c=document.documentElement.clientWidth||window.innerWidth,u=document.documentElement.clientHeight||window.innerHeight;l.setAttribute("width",c.toString()),l.setAttribute("height",u.toString());const m=document.createElementNS("http://www.w3.org/2000/svg","g");m.classList.add("highlight-frame-group"),m.setAttribute("transform",`translate(${s}, ${r})`);const p=document.createElementNS("http://www.w3.org/2000/svg","rect");p.setAttribute("x","0"),p.setAttribute("y","0"),p.setAttribute("width",d.toString()),p.setAttribute("height",a.toString()),p.setAttribute("vector-effect","non-scaling-stroke"),p.classList.add("highlight-frame-rect"),t?p.setAttribute("stroke",getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim()||"oklch(65.6% 0.241 354.308)"):n&&p.setAttribute("stroke",getComputedStyle(document.documentElement).getPropertyValue("--text-edit-color").trim()||"oklch(62.3% 0.214 259.815)"),m.appendChild(p),((e,t,n,o=!1,r=!1)=>{h(e,0,0,"handle-top-left",o,r),h(e,t,0,"handle-top-right",o,r),h(e,t,n,"handle-bottom-right",o,r),h(e,0,n,"handle-bottom-left",o,r)})(m,d,a,t,n),l.appendChild(m);const b=o();return b?b.appendChild(l):document.body.appendChild(l),l},b={div:"Container",h1:"Heading 1",h2:"Heading 2",h3:"Heading 3",h4:"Heading 4",h5:"Heading 5",h6:"Heading 6",p:"Text",li:"List Item",ul:"Unordered List",ol:"Ordered List",img:"Image",a:"Link"},v=(e,t,n=!1,o=!1)=>{const r=document.createElement("div");r.className="node-tools",n&&r.classList.add("is-instance"),o&&r.classList.add("is-text-edit"),t.appendChild(r),((e,t)=>{const n=document.createElement("div");n.className="tag-label";const o=e.getAttribute("data-instance-name"),r=e.tagName.toLowerCase(),s=o||b[r]||r;var i;n.textContent=(i=s)?i.charAt(0).toUpperCase()+i.slice(1):i,t.appendChild(n)})(e,r)};function y(){return(o()||document.body).querySelector(".highlight-frame-overlay")}const f=()=>getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim()||"oklch(65.6% 0.241 354.308)",w=()=>getComputedStyle(document.documentElement).getPropertyValue("--text-edit-color").trim()||"oklch(62.3% 0.214 259.815)",E=(e,n,r="canvas")=>{const s=y();if(!s)return;const i=m(e),a="true"===e.contentEditable,d=document.documentElement.clientWidth||window.innerWidth,l=document.documentElement.clientHeight||window.innerHeight;s.setAttribute("width",d.toString()),s.setAttribute("height",l.toString()),i?s.classList.add("is-instance"):s.classList.remove("is-instance"),a?s.classList.add("is-text-edit"):s.classList.remove("is-text-edit");const c=s.querySelector(".highlight-frame-group");if(!c)return;const u=c.querySelector("rect");if(!u)return;i?u.setAttribute("stroke",f()):a?u.setAttribute("stroke",w()):u.removeAttribute("stroke");const h=(o()||document.body).querySelector(".highlight-frame-tools-wrapper"),p=h?.querySelector(".node-tools"),b=t(["zoom","current"],r)??1,v=g(e),{top:E,left:L,width:A,height:S}=v,x=Math.max(A,3),C=E+S;h&&(i?h.classList.add("is-instance"):h.classList.remove("is-instance"),a?h.classList.add("is-text-edit"):h.classList.remove("is-text-edit")),p&&(i?p.classList.add("is-instance"):p.classList.remove("is-instance"),a?p.classList.add("is-text-edit"):p.classList.remove("is-text-edit")),c.setAttribute("transform",`translate(${L}, ${E})`),u.setAttribute("width",x.toString()),u.setAttribute("height",S.toString());const k=c.querySelector(".handle-top-left"),N=c.querySelector(".handle-top-right"),q=c.querySelector(".handle-bottom-right"),M=c.querySelector(".handle-bottom-left");[k,N,q,M].forEach(e=>{e&&(i?e.setAttribute("stroke",f()):a?e.setAttribute("stroke",w()):e.removeAttribute("stroke"))}),k&&(k.setAttribute("x",(-3).toString()),k.setAttribute("y",(-3).toString())),N&&(N.setAttribute("x",(x-3).toString()),N.setAttribute("y",(-3).toString())),q&&(q.setAttribute("x",(x-3).toString()),q.setAttribute("y",(S-3).toString())),M&&(M.setAttribute("x",(-3).toString()),M.setAttribute("y",(S-3).toString())),h&&(h.style.transform=`translate(${L}px, ${C}px)`),b<=10?n.style.setProperty("--tool-opacity","1"):n.style.setProperty("--tool-opacity","0")},L=e=>{const t=y();if(!t)return;const n=e.classList.contains("hidden")||e.classList.contains("select-none")?"none":"";t.style.display=n;const r=(o()||document.body).querySelector(".highlight-frame-tools-wrapper");r&&(r.style.display=n)},A=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)}};function S(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 x=(e,t,o="canvas")=>{const r=S(t=>{((e,t)=>{if(!t.some(e=>"characterData"===e.type||"childList"===e.type&&(e.addedNodes.length>0||e.removedNodes.length>0)))return;const o=e.textContent??"";n("textContentChanged",{nodeId:e.getAttribute("data-node-id"),textContent:o})})(e,t)}),s=((e,t)=>{const n=new MutationObserver(e=>{t(e)});return n.observe(e,{subtree:!0,childList:!0,characterData:!0}),n})(e,n=>{r(n),E(e,t,o)});return()=>{s.disconnect(),r.cleanup()}},C=(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=A(e),s=x(e,t,o);return()=>{e.removeEventListener("blur",n),r(),s?.()}})(o,i,s,e))},blurEditMode:s,getEditableNode:()=>n,isEditing:()=>null!==n}},k=320,N=1680,q=[{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"}],M=(e,t,n)=>{const o=parseFloat(document.body.dataset.zoom||"1"),r=((e,t)=>{const n=e+Math.round(t);return Math.max(k,Math.min(N,n))})(n,(e.clientX-t)/o);return r},P=(e,t)=>{e.style.setProperty("--container-width",`${t}px`),((e,t)=>{e.querySelectorAll(".resize-preset-button").forEach((e,n)=>{n<q.length&&(q[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 s=e;let i=null,a=null,d=null,l=null;const c=C(t),h=e=>{if(l!==e){if(c.isEditing()){const t=c.getEditableNode();t&&t!==e&&c.blurEditMode()}if(i?.disconnect(),a?.disconnect(),d?.disconnect(),e&&s){const o=()=>{if(!document.contains(e))return r(),l=null,i?.disconnect(),a?.disconnect(),d?.disconnect(),void n("selectedNodeChanged",null)};a=new MutationObserver(()=>{o(),document.contains(e)&&(E(e,s,t),L(e))}),a.observe(e,{attributes:!0,characterData:!0,childList:!0,subtree:!0});const c=e.parentElement;c&&(d=new MutationObserver(t=>{for(const n of t)if("childList"===n.type)for(const t of Array.from(n.removedNodes))if(t===e||t instanceof Node&&t.contains(e))return void o()}),d.observe(c,{childList:!0,subtree:!1})),i=((e,t)=>{const n=new ResizeObserver(e=>{t(e)});return n.observe(e),n})(e,()=>{o(),document.contains(e)&&(E(e,s,t),L(e))})}l=e,n("selectedNodeChanged",e?.getAttribute("data-node-id")??null),(e=>{if(!e)return;const t=y(),n=o(),r=n?.querySelector(".highlight-frame-tools-wrapper")||document.body.querySelector(".highlight-frame-tools-wrapper");t&&t.remove(),r&&r.remove();const s=m(e),i="true"===e.contentEditable,a=p(e,s,i);"true"===e.contentEditable&&a.classList.add("is-editable");const{left:d,top:l,height:c}=g(e),u=l+c,h=document.createElement("div");h.classList.add("highlight-frame-tools-wrapper"),s&&h.classList.add("is-instance"),i&&h.classList.add("is-text-edit"),h.style.position="absolute",h.style.transform=`translate(${d}px, ${u}px)`,h.style.transformOrigin="left center",h.style.pointerEvents="none",h.style.zIndex="500",v(e,h,s,i),n?n.appendChild(h):document.body.appendChild(h)})(e),e&&s&&(L(e),L(e))}},b=u(s,h,()=>{c.isEditing()&&c.blurEditMode(),l&&s&&(r(),l=null,i?.disconnect(),a?.disconnect(),d?.disconnect())},c),f={selectNode:h,getSelectedNode:()=>l,refreshHighlightFrame:()=>{l&&s&&(E(l,s,t),L(l))},clearSelectedNode:()=>{r(),l=null,i?.disconnect(),a?.disconnect(),d?.disconnect()},getEditableNode:()=>c.getEditableNode(),cleanup:()=>{b(),i?.disconnect(),a?.disconnect(),d?.disconnect(),c.blurEditMode(),r(),l=null,n("selectedNodeChanged",null)}};var w,A;return w="nodeTools",A=f,"undefined"!=typeof window&&(window[w]=A),f},e.createViewport=e=>{const t=o(),n=e.querySelector(".resize-handle");n&&n.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",q.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,P);let s=!1,i=0,a=0;const d=S(n=>{if(!s)return;t&&(t.style.cursor="ew-resize");const o=M(n,i,a);P(e,o)}),l=((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},d,e=>{e.preventDefault(),e.stopPropagation(),t&&(t.style.cursor="default"),s=!1},()=>{s=!1});return{setWidth:t=>{P(e,t)},cleanup:()=>{s=!1,d?.cleanup(),l(),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,t){window.parent.postMessage({source:"node-edit-utils",action:e,data:t,timestamp:Date.now()},"*")}const o=()=>document.querySelector(".canvas-container"),r=()=>{const e=o()||document.body,t=e.querySelector(".highlight-frame-overlay");t&&t.remove();const n=e.querySelector(".highlight-frame-tools-wrapper");n&&n.remove()},i=(e,t,n)=>{e&&t&&n.enableEditMode(e,t)},s=["path","rect","circle","ellipse","polygon","line","polyline","text","text-noci"];let a=[],l=0,d=null;const c=(e,t,n)=>{let o=null;const r=e.clientX,c=e.clientY,u=e.metaKey||e.ctrlKey,m=((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})(r,c).filter(e=>!s.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)),h=n.getEditableNode();if(h&&m.includes(h))return o=h,d=o,o;if(u)return a=[],o=m[0],d&&d===o&&i(o,t,n),d=o,o;var g,p;p=m,(g=a).length===p.length&&g.every((e,t)=>e===p[t])?l<=m.length-2&&l++:l=0;return o=m[m.length-1-l],a=m,d&&d===o&&i(o,t,n),d=o,o},u=(e,t,n,o)=>{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,o)=>{if(e.preventDefault(),e.stopPropagation(),t&&!t.contains(e.target))return r(),void o(null);o(c(e,t,n))})(n,e,o,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)}},m=e=>"true"===e.getAttribute("data-instance"),h=(e,t,n,o,r=!1,i=!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)"):i&&s.setAttribute("stroke",getComputedStyle(document.documentElement).getPropertyValue("--text-edit-color").trim()||"oklch(62.3% 0.214 259.815)"),e.appendChild(s),s};function g(e){const t=e.getBoundingClientRect();return{top:t.top,left:t.left,width:t.width,height:t.height}}const p=(e,t=!1,n=!1)=>{const{top:r,left:i,width:s,height:a}=g(e),l=Math.max(s,3),d=document.createElementNS("http://www.w3.org/2000/svg","svg");d.classList.add("highlight-frame-overlay"),t&&d.classList.add("is-instance"),n&&d.classList.add("is-text-edit"),d.setAttribute("data-node-id",e.getAttribute("data-node-id")||""),d.style.position="absolute",d.style.top="0",d.style.left="0",d.style.width="100vw",d.style.height="100vh",d.style.pointerEvents="none",d.style.zIndex="500";const c=document.documentElement.clientWidth||window.innerWidth,u=document.documentElement.clientHeight||window.innerHeight;d.setAttribute("width",c.toString()),d.setAttribute("height",u.toString());const m=document.createElementNS("http://www.w3.org/2000/svg","g");m.classList.add("highlight-frame-group"),m.setAttribute("transform",`translate(${i}, ${r})`);const p=document.createElementNS("http://www.w3.org/2000/svg","rect");p.setAttribute("x","0"),p.setAttribute("y","0"),p.setAttribute("width",l.toString()),p.setAttribute("height",a.toString()),p.setAttribute("vector-effect","non-scaling-stroke"),p.classList.add("highlight-frame-rect"),t?p.setAttribute("stroke",getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim()||"oklch(65.6% 0.241 354.308)"):n&&p.setAttribute("stroke",getComputedStyle(document.documentElement).getPropertyValue("--text-edit-color").trim()||"oklch(62.3% 0.214 259.815)"),m.appendChild(p),((e,t,n,o=!1,r=!1)=>{h(e,0,0,"handle-top-left",o,r),h(e,t,0,"handle-top-right",o,r),h(e,t,n,"handle-bottom-right",o,r),h(e,0,n,"handle-bottom-left",o,r)})(m,l,a,t,n),d.appendChild(m);const b=o();return b?b.appendChild(d):document.body.appendChild(d),d},b={div:"Container",h1:"Heading 1",h2:"Heading 2",h3:"Heading 3",h4:"Heading 4",h5:"Heading 5",h6:"Heading 6",p:"Text",li:"List Item",ul:"Unordered List",ol:"Ordered List",img:"Image",a:"Link"},v=(e,t,n=!1,o=!1)=>{const r=document.createElement("div");r.className="node-tools",n&&r.classList.add("is-instance"),o&&r.classList.add("is-text-edit"),t.appendChild(r),((e,t)=>{const n=document.createElement("div");n.className="tag-label";const o=e.getAttribute("data-instance-name"),r=e.tagName.toLowerCase(),i=o||b[r]||r;var s;n.textContent=(s=i)?s.charAt(0).toUpperCase()+s.slice(1):s,t.appendChild(n)})(e,r)};function y(){return(o()||document.body).querySelector(".highlight-frame-overlay")}const f=()=>getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim()||"oklch(65.6% 0.241 354.308)",w=()=>getComputedStyle(document.documentElement).getPropertyValue("--text-edit-color").trim()||"oklch(62.3% 0.214 259.815)",E=(e,n,r="canvas")=>{const i=y();if(!i)return;const s=m(e),a="true"===e.contentEditable,l=document.documentElement.clientWidth||window.innerWidth,d=document.documentElement.clientHeight||window.innerHeight;i.setAttribute("width",l.toString()),i.setAttribute("height",d.toString()),s?i.classList.add("is-instance"):i.classList.remove("is-instance"),a?i.classList.add("is-text-edit"):i.classList.remove("is-text-edit");const c=i.querySelector(".highlight-frame-group");if(!c)return;const u=c.querySelector("rect");if(!u)return;s?u.setAttribute("stroke",f()):a?u.setAttribute("stroke",w()):u.removeAttribute("stroke");const h=(o()||document.body).querySelector(".highlight-frame-tools-wrapper"),p=h?.querySelector(".node-tools"),b=t(["zoom","current"],r)??1,v=g(e),{top:E,left:L,width:A,height:x}=v,S=Math.max(A,3),C=E+x;h&&(s?h.classList.add("is-instance"):h.classList.remove("is-instance"),a?h.classList.add("is-text-edit"):h.classList.remove("is-text-edit")),p&&(s?p.classList.add("is-instance"):p.classList.remove("is-instance"),a?p.classList.add("is-text-edit"):p.classList.remove("is-text-edit")),c.setAttribute("transform",`translate(${L}, ${E})`),u.setAttribute("width",S.toString()),u.setAttribute("height",x.toString());const k=c.querySelector(".handle-top-left"),N=c.querySelector(".handle-top-right"),q=c.querySelector(".handle-bottom-right"),M=c.querySelector(".handle-bottom-left");[k,N,q,M].forEach(e=>{e&&(s?e.setAttribute("stroke",f()):a?e.setAttribute("stroke",w()):e.removeAttribute("stroke"))}),k&&(k.setAttribute("x",(-3).toString()),k.setAttribute("y",(-3).toString())),N&&(N.setAttribute("x",(S-3).toString()),N.setAttribute("y",(-3).toString())),q&&(q.setAttribute("x",(S-3).toString()),q.setAttribute("y",(x-3).toString())),M&&(M.setAttribute("x",(-3).toString()),M.setAttribute("y",(x-3).toString())),h&&(h.style.transform=`translate(${L}px, ${C}px)`),b<=10?n.style.setProperty("--tool-opacity","1"):n.style.setProperty("--tool-opacity","0")},L=e=>{const t=y();if(!t)return;const n=e.classList.contains("hidden")||e.classList.contains("select-none")?"none":"";t.style.display=n;const r=(o()||document.body).querySelector(".highlight-frame-tools-wrapper");r&&(r.style.display=n)},A=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)}},x=(e,t,o="canvas")=>{let r=[],i=null,s=null;const a=()=>{if(r.length>0){const t=[...r];r=[],((e,t)=>{if(!t.some(e=>"characterData"===e.type||"childList"===e.type&&(e.addedNodes.length>0||e.removedNodes.length>0)))return;const o=e.textContent??"",r=e.getAttribute("data-node-id");console.log("textContentChanged",r,o),n("textContentChanged",{nodeId:r,textContent:o})})(e,t)}},l=((e,t)=>{const n=new MutationObserver(e=>{t(e)});return n.observe(e,{subtree:!0,childList:!0,characterData:!0}),n})(e,n=>{r.push(...n),null===i&&(i=requestAnimationFrame(()=>{s=requestAnimationFrame(()=>{a(),i=null,s=null})})),E(e,t,o)});return()=>{l.disconnect(),null!==i&&(cancelAnimationFrame(i),i=null),null!==s&&(cancelAnimationFrame(s),s=null),r=[]}},S=(e="canvas")=>{let n=null,o=!1,r=null;const i=()=>{if(o||!n)return;o=!0;var i;(i=n).contentEditable="false",i.classList.remove("is-editable"),i.style.outline="none",((e="canvas")=>{const n=t(["keyboard","disableTextEditMode"],e);n?.()})(e),r?.(),n=null,o=!1};return{enableEditMode:(o,s)=>{if(n===o)return;n&&n!==o&&i();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=A(e),i=x(e,t,o);return()=>{e.removeEventListener("blur",n),r(),i?.()}})(o,s,i,e))},blurEditMode:i,getEditableNode:()=>n,isEditing:()=>null!==n}};const C=320,k=1680,N=[{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"}],q=(e,t,n)=>{const o=parseFloat(document.body.dataset.zoom||"1"),r=((e,t)=>{const n=e+Math.round(t);return Math.max(C,Math.min(k,n))})(n,(e.clientX-t)/o);return r},M=(e,t)=>{e.style.setProperty("--container-width",`${t}px`),((e,t)=>{e.querySelectorAll(".resize-preset-button").forEach((e,n)=>{n<N.length&&(N[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 i=e;let s=null,a=null,l=null,d=null;const c=S(t),h=e=>{if(d!==e){if(c.isEditing()){const t=c.getEditableNode();t&&t!==e&&c.blurEditMode()}if(s?.disconnect(),a?.disconnect(),l?.disconnect(),e&&i){const o=()=>{if(!document.contains(e))return r(),d=null,s?.disconnect(),a?.disconnect(),l?.disconnect(),void n("selectedNodeChanged",null)};a=new MutationObserver(()=>{o(),document.contains(e)&&(E(e,i,t),L(e))}),a.observe(e,{attributes:!0,characterData:!0,childList:!0,subtree:!0});const c=e.parentElement;c&&(l=new MutationObserver(t=>{for(const n of t)if("childList"===n.type)for(const t of Array.from(n.removedNodes))if(t===e||t instanceof Node&&t.contains(e))return void o()}),l.observe(c,{childList:!0,subtree:!1})),s=((e,t)=>{const n=new ResizeObserver(e=>{t(e)});return n.observe(e),n})(e,()=>{o(),document.contains(e)&&(E(e,i,t),L(e))})}d=e,n("selectedNodeChanged",e?.getAttribute("data-node-id")??null),(e=>{if(!e)return;const t=y(),n=o(),r=n?.querySelector(".highlight-frame-tools-wrapper")||document.body.querySelector(".highlight-frame-tools-wrapper");t&&t.remove(),r&&r.remove();const i=m(e),s="true"===e.contentEditable,a=p(e,i,s);"true"===e.contentEditable&&a.classList.add("is-editable");const{left:l,top:d,height:c}=g(e),u=d+c,h=document.createElement("div");h.classList.add("highlight-frame-tools-wrapper"),i&&h.classList.add("is-instance"),s&&h.classList.add("is-text-edit"),h.style.position="absolute",h.style.transform=`translate(${l}px, ${u}px)`,h.style.transformOrigin="left center",h.style.pointerEvents="none",h.style.zIndex="500",v(e,h,i,s),n?n.appendChild(h):document.body.appendChild(h)})(e),e&&i&&(L(e),L(e))}},b=u(i,h,()=>{c.isEditing()&&c.blurEditMode(),d&&i&&(r(),d=null,s?.disconnect(),a?.disconnect(),l?.disconnect())},c),f={selectNode:h,getSelectedNode:()=>d,refreshHighlightFrame:()=>{d&&i&&(E(d,i,t),L(d))},clearSelectedNode:()=>{r(),d=null,s?.disconnect(),a?.disconnect(),l?.disconnect()},getEditableNode:()=>c.getEditableNode(),cleanup:()=>{b(),s?.disconnect(),a?.disconnect(),l?.disconnect(),c.blurEditMode(),r(),d=null,n("selectedNodeChanged",null)}};var w,A;return w="nodeTools",A=f,"undefined"!=typeof window&&(window[w]=A),f},e.createViewport=e=>{const t=o(),n=e.querySelector(".resize-handle");n&&n.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",N.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,M);let i=!1,s=0,a=0;const l=function(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}(n=>{if(!i)return;t&&(t.style.cursor="ew-resize");const o=q(n,s,a);M(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,a=e.offsetWidth},l,e=>{e.preventDefault(),e.stopPropagation(),t&&(t.style.cursor="default"),i=!1},()=>{i=!1});return{setWidth:t=>{M(e,t)},cleanup:()=>{i=!1,l?.cleanup(),d(),r.remove()}}}});
|
package/package.json
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { connectMutationObserver } from "../../../helpers/observer/connectMutationObserver";
|
|
2
|
-
import { withRAFThrottle } from "../../../helpers/withRAF";
|
|
3
2
|
import { refreshHighlightFrame } from "../../highlight/refreshHighlightFrame";
|
|
4
3
|
import { handleTextChange } from "../helpers/handleTextChange";
|
|
5
4
|
|
|
@@ -8,17 +7,54 @@ export const setupMutationObserver = (
|
|
|
8
7
|
nodeProvider: HTMLElement,
|
|
9
8
|
canvasName: string = "canvas"
|
|
10
9
|
): (() => void) | undefined => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
// Accumulate mutations instead of replacing them
|
|
11
|
+
let pendingMutations: MutationRecord[] = [];
|
|
12
|
+
let rafId1: number | null = null;
|
|
13
|
+
let rafId2: number | null = null;
|
|
14
|
+
|
|
15
|
+
const processMutations = () => {
|
|
16
|
+
if (pendingMutations.length > 0) {
|
|
17
|
+
const mutationsToProcess = [...pendingMutations];
|
|
18
|
+
pendingMutations = [];
|
|
19
|
+
handleTextChange(node, mutationsToProcess);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const scheduleProcess = () => {
|
|
24
|
+
if (rafId1 === null) {
|
|
25
|
+
rafId1 = requestAnimationFrame(() => {
|
|
26
|
+
// First RAF: let browser complete layout
|
|
27
|
+
rafId2 = requestAnimationFrame(() => {
|
|
28
|
+
// Second RAF: read textContent after layout is complete
|
|
29
|
+
processMutations();
|
|
30
|
+
rafId1 = null;
|
|
31
|
+
rafId2 = null;
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const cleanup = () => {
|
|
38
|
+
if (rafId1 !== null) {
|
|
39
|
+
cancelAnimationFrame(rafId1);
|
|
40
|
+
rafId1 = null;
|
|
41
|
+
}
|
|
42
|
+
if (rafId2 !== null) {
|
|
43
|
+
cancelAnimationFrame(rafId2);
|
|
44
|
+
rafId2 = null;
|
|
45
|
+
}
|
|
46
|
+
pendingMutations = [];
|
|
47
|
+
};
|
|
14
48
|
|
|
15
49
|
const mutationObserver = connectMutationObserver(node, (mutations) => {
|
|
16
|
-
|
|
50
|
+
// Accumulate mutations instead of replacing
|
|
51
|
+
pendingMutations.push(...mutations);
|
|
52
|
+
scheduleProcess();
|
|
17
53
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
18
54
|
});
|
|
19
55
|
|
|
20
56
|
return () => {
|
|
21
57
|
mutationObserver.disconnect();
|
|
22
|
-
|
|
58
|
+
cleanup();
|
|
23
59
|
};
|
|
24
60
|
};
|
|
@@ -19,6 +19,8 @@ export const handleTextChange = (node: HTMLElement, mutations: MutationRecord[])
|
|
|
19
19
|
// Get the node ID
|
|
20
20
|
const nodeId = node.getAttribute("data-node-id");
|
|
21
21
|
|
|
22
|
+
console.log("textContentChanged", nodeId, textContent);
|
|
23
|
+
|
|
22
24
|
// Send postMessage with the text change
|
|
23
25
|
sendPostMessage("textContentChanged", {
|
|
24
26
|
nodeId,
|