@node-edit-utils/core 2.2.3 → 2.2.5
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.
|
@@ -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.5
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
@@ -633,6 +633,7 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
633
633
|
const nodeProvider = element;
|
|
634
634
|
let resizeObserver = null;
|
|
635
635
|
let mutationObserver = null;
|
|
636
|
+
let parentMutationObserver = null;
|
|
636
637
|
let selectedNode = null;
|
|
637
638
|
const text = nodeText(canvasName);
|
|
638
639
|
// Combined throttled function for refresh + visibility update
|
|
@@ -650,6 +651,7 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
650
651
|
selectedNode = null;
|
|
651
652
|
resizeObserver?.disconnect();
|
|
652
653
|
mutationObserver?.disconnect();
|
|
654
|
+
parentMutationObserver?.disconnect();
|
|
653
655
|
}
|
|
654
656
|
}
|
|
655
657
|
};
|
|
@@ -665,9 +667,26 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
665
667
|
}
|
|
666
668
|
resizeObserver?.disconnect();
|
|
667
669
|
mutationObserver?.disconnect();
|
|
670
|
+
parentMutationObserver?.disconnect();
|
|
668
671
|
if (node && nodeProvider) {
|
|
669
672
|
text.enableEditMode(node, nodeProvider);
|
|
673
|
+
// Check if node is still in DOM and handle cleanup if removed
|
|
674
|
+
const checkNodeExists = () => {
|
|
675
|
+
if (!document.contains(node)) {
|
|
676
|
+
// Node was removed from DOM, clear highlight and cleanup
|
|
677
|
+
clearHighlightFrame();
|
|
678
|
+
selectedNode = null;
|
|
679
|
+
resizeObserver?.disconnect();
|
|
680
|
+
mutationObserver?.disconnect();
|
|
681
|
+
parentMutationObserver?.disconnect();
|
|
682
|
+
sendPostMessage("selectedNodeChanged", null);
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
};
|
|
670
686
|
mutationObserver = new MutationObserver(() => {
|
|
687
|
+
checkNodeExists();
|
|
688
|
+
if (!document.contains(node))
|
|
689
|
+
return; // Exit early if node was removed
|
|
671
690
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
672
691
|
console.log("mutationObserver", node);
|
|
673
692
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
@@ -676,8 +695,35 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
676
695
|
mutationObserver.observe(node, {
|
|
677
696
|
attributes: true,
|
|
678
697
|
characterData: true,
|
|
698
|
+
childList: true,
|
|
699
|
+
subtree: true,
|
|
679
700
|
});
|
|
701
|
+
// Also observe parent node to catch when this node is removed
|
|
702
|
+
const parentNode = node.parentElement;
|
|
703
|
+
if (parentNode) {
|
|
704
|
+
parentMutationObserver = new MutationObserver((mutations) => {
|
|
705
|
+
// Check if the selected node was removed
|
|
706
|
+
for (const mutation of mutations) {
|
|
707
|
+
if (mutation.type === "childList") {
|
|
708
|
+
for (const removedNode of Array.from(mutation.removedNodes)) {
|
|
709
|
+
// Check if the removed node is the selected node, or if the selected node is contained within the removed subtree
|
|
710
|
+
if (removedNode === node || (removedNode instanceof Node && removedNode.contains(node))) {
|
|
711
|
+
checkNodeExists();
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
});
|
|
718
|
+
parentMutationObserver.observe(parentNode, {
|
|
719
|
+
childList: true,
|
|
720
|
+
subtree: false, // Only direct children to avoid too many callbacks
|
|
721
|
+
});
|
|
722
|
+
}
|
|
680
723
|
resizeObserver = connectResizeObserver(node, () => {
|
|
724
|
+
checkNodeExists();
|
|
725
|
+
if (!document.contains(node))
|
|
726
|
+
return; // Exit early if node was removed
|
|
681
727
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
682
728
|
console.log("resizeObserver", node);
|
|
683
729
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
@@ -697,6 +743,7 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
697
743
|
removeListeners();
|
|
698
744
|
resizeObserver?.disconnect();
|
|
699
745
|
mutationObserver?.disconnect();
|
|
746
|
+
parentMutationObserver?.disconnect();
|
|
700
747
|
text.blurEditMode();
|
|
701
748
|
throttledRefreshAndVisibility.cleanup();
|
|
702
749
|
};
|
|
@@ -705,8 +752,6 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
705
752
|
getSelectedNode: () => selectedNode,
|
|
706
753
|
refreshHighlightFrame: () => {
|
|
707
754
|
if (selectedNode && nodeProvider) {
|
|
708
|
-
// Call directly (not throttled) since this is typically called from already-throttled contexts
|
|
709
|
-
// to avoid double RAF
|
|
710
755
|
refreshHighlightFrame(selectedNode, nodeProvider, canvasName);
|
|
711
756
|
updateHighlightFrameVisibility(selectedNode);
|
|
712
757
|
}
|
|
@@ -716,6 +761,7 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
716
761
|
selectedNode = null;
|
|
717
762
|
resizeObserver?.disconnect();
|
|
718
763
|
mutationObserver?.disconnect();
|
|
764
|
+
parentMutationObserver?.disconnect();
|
|
719
765
|
},
|
|
720
766
|
getEditableNode: () => text.getEditableNode(),
|
|
721
767
|
cleanup,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markup Canvas
|
|
3
3
|
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
-
* @version 2.2.
|
|
4
|
+
* @version 2.2.5
|
|
5
5
|
*/
|
|
6
6
|
const getCanvasWindowValue = (path, canvasName = "canvas") => {
|
|
7
7
|
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
@@ -631,6 +631,7 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
631
631
|
const nodeProvider = element;
|
|
632
632
|
let resizeObserver = null;
|
|
633
633
|
let mutationObserver = null;
|
|
634
|
+
let parentMutationObserver = null;
|
|
634
635
|
let selectedNode = null;
|
|
635
636
|
const text = nodeText(canvasName);
|
|
636
637
|
// Combined throttled function for refresh + visibility update
|
|
@@ -648,6 +649,7 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
648
649
|
selectedNode = null;
|
|
649
650
|
resizeObserver?.disconnect();
|
|
650
651
|
mutationObserver?.disconnect();
|
|
652
|
+
parentMutationObserver?.disconnect();
|
|
651
653
|
}
|
|
652
654
|
}
|
|
653
655
|
};
|
|
@@ -663,9 +665,26 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
663
665
|
}
|
|
664
666
|
resizeObserver?.disconnect();
|
|
665
667
|
mutationObserver?.disconnect();
|
|
668
|
+
parentMutationObserver?.disconnect();
|
|
666
669
|
if (node && nodeProvider) {
|
|
667
670
|
text.enableEditMode(node, nodeProvider);
|
|
671
|
+
// Check if node is still in DOM and handle cleanup if removed
|
|
672
|
+
const checkNodeExists = () => {
|
|
673
|
+
if (!document.contains(node)) {
|
|
674
|
+
// Node was removed from DOM, clear highlight and cleanup
|
|
675
|
+
clearHighlightFrame();
|
|
676
|
+
selectedNode = null;
|
|
677
|
+
resizeObserver?.disconnect();
|
|
678
|
+
mutationObserver?.disconnect();
|
|
679
|
+
parentMutationObserver?.disconnect();
|
|
680
|
+
sendPostMessage("selectedNodeChanged", null);
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
};
|
|
668
684
|
mutationObserver = new MutationObserver(() => {
|
|
685
|
+
checkNodeExists();
|
|
686
|
+
if (!document.contains(node))
|
|
687
|
+
return; // Exit early if node was removed
|
|
669
688
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
670
689
|
console.log("mutationObserver", node);
|
|
671
690
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
@@ -674,8 +693,35 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
674
693
|
mutationObserver.observe(node, {
|
|
675
694
|
attributes: true,
|
|
676
695
|
characterData: true,
|
|
696
|
+
childList: true,
|
|
697
|
+
subtree: true,
|
|
677
698
|
});
|
|
699
|
+
// Also observe parent node to catch when this node is removed
|
|
700
|
+
const parentNode = node.parentElement;
|
|
701
|
+
if (parentNode) {
|
|
702
|
+
parentMutationObserver = new MutationObserver((mutations) => {
|
|
703
|
+
// Check if the selected node was removed
|
|
704
|
+
for (const mutation of mutations) {
|
|
705
|
+
if (mutation.type === "childList") {
|
|
706
|
+
for (const removedNode of Array.from(mutation.removedNodes)) {
|
|
707
|
+
// Check if the removed node is the selected node, or if the selected node is contained within the removed subtree
|
|
708
|
+
if (removedNode === node || (removedNode instanceof Node && removedNode.contains(node))) {
|
|
709
|
+
checkNodeExists();
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
parentMutationObserver.observe(parentNode, {
|
|
717
|
+
childList: true,
|
|
718
|
+
subtree: false, // Only direct children to avoid too many callbacks
|
|
719
|
+
});
|
|
720
|
+
}
|
|
678
721
|
resizeObserver = connectResizeObserver(node, () => {
|
|
722
|
+
checkNodeExists();
|
|
723
|
+
if (!document.contains(node))
|
|
724
|
+
return; // Exit early if node was removed
|
|
679
725
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
680
726
|
console.log("resizeObserver", node);
|
|
681
727
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
@@ -695,6 +741,7 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
695
741
|
removeListeners();
|
|
696
742
|
resizeObserver?.disconnect();
|
|
697
743
|
mutationObserver?.disconnect();
|
|
744
|
+
parentMutationObserver?.disconnect();
|
|
698
745
|
text.blurEditMode();
|
|
699
746
|
throttledRefreshAndVisibility.cleanup();
|
|
700
747
|
};
|
|
@@ -703,8 +750,6 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
703
750
|
getSelectedNode: () => selectedNode,
|
|
704
751
|
refreshHighlightFrame: () => {
|
|
705
752
|
if (selectedNode && nodeProvider) {
|
|
706
|
-
// Call directly (not throttled) since this is typically called from already-throttled contexts
|
|
707
|
-
// to avoid double RAF
|
|
708
753
|
refreshHighlightFrame(selectedNode, nodeProvider, canvasName);
|
|
709
754
|
updateHighlightFrameVisibility(selectedNode);
|
|
710
755
|
}
|
|
@@ -714,6 +759,7 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
714
759
|
selectedNode = null;
|
|
715
760
|
resizeObserver?.disconnect();
|
|
716
761
|
mutationObserver?.disconnect();
|
|
762
|
+
parentMutationObserver?.disconnect();
|
|
717
763
|
},
|
|
718
764
|
getEditableNode: () => text.getEditableNode(),
|
|
719
765
|
cleanup,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markup Canvas
|
|
3
3
|
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
-
* @version 2.2.
|
|
4
|
+
* @version 2.2.5
|
|
5
5
|
*/
|
|
6
6
|
(function (global, factory) {
|
|
7
7
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
@@ -637,6 +637,7 @@
|
|
|
637
637
|
const nodeProvider = element;
|
|
638
638
|
let resizeObserver = null;
|
|
639
639
|
let mutationObserver = null;
|
|
640
|
+
let parentMutationObserver = null;
|
|
640
641
|
let selectedNode = null;
|
|
641
642
|
const text = nodeText(canvasName);
|
|
642
643
|
// Combined throttled function for refresh + visibility update
|
|
@@ -654,6 +655,7 @@
|
|
|
654
655
|
selectedNode = null;
|
|
655
656
|
resizeObserver?.disconnect();
|
|
656
657
|
mutationObserver?.disconnect();
|
|
658
|
+
parentMutationObserver?.disconnect();
|
|
657
659
|
}
|
|
658
660
|
}
|
|
659
661
|
};
|
|
@@ -669,9 +671,26 @@
|
|
|
669
671
|
}
|
|
670
672
|
resizeObserver?.disconnect();
|
|
671
673
|
mutationObserver?.disconnect();
|
|
674
|
+
parentMutationObserver?.disconnect();
|
|
672
675
|
if (node && nodeProvider) {
|
|
673
676
|
text.enableEditMode(node, nodeProvider);
|
|
677
|
+
// Check if node is still in DOM and handle cleanup if removed
|
|
678
|
+
const checkNodeExists = () => {
|
|
679
|
+
if (!document.contains(node)) {
|
|
680
|
+
// Node was removed from DOM, clear highlight and cleanup
|
|
681
|
+
clearHighlightFrame();
|
|
682
|
+
selectedNode = null;
|
|
683
|
+
resizeObserver?.disconnect();
|
|
684
|
+
mutationObserver?.disconnect();
|
|
685
|
+
parentMutationObserver?.disconnect();
|
|
686
|
+
sendPostMessage("selectedNodeChanged", null);
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
};
|
|
674
690
|
mutationObserver = new MutationObserver(() => {
|
|
691
|
+
checkNodeExists();
|
|
692
|
+
if (!document.contains(node))
|
|
693
|
+
return; // Exit early if node was removed
|
|
675
694
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
676
695
|
console.log("mutationObserver", node);
|
|
677
696
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
@@ -680,8 +699,35 @@
|
|
|
680
699
|
mutationObserver.observe(node, {
|
|
681
700
|
attributes: true,
|
|
682
701
|
characterData: true,
|
|
702
|
+
childList: true,
|
|
703
|
+
subtree: true,
|
|
683
704
|
});
|
|
705
|
+
// Also observe parent node to catch when this node is removed
|
|
706
|
+
const parentNode = node.parentElement;
|
|
707
|
+
if (parentNode) {
|
|
708
|
+
parentMutationObserver = new MutationObserver((mutations) => {
|
|
709
|
+
// Check if the selected node was removed
|
|
710
|
+
for (const mutation of mutations) {
|
|
711
|
+
if (mutation.type === "childList") {
|
|
712
|
+
for (const removedNode of Array.from(mutation.removedNodes)) {
|
|
713
|
+
// Check if the removed node is the selected node, or if the selected node is contained within the removed subtree
|
|
714
|
+
if (removedNode === node || (removedNode instanceof Node && removedNode.contains(node))) {
|
|
715
|
+
checkNodeExists();
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
});
|
|
722
|
+
parentMutationObserver.observe(parentNode, {
|
|
723
|
+
childList: true,
|
|
724
|
+
subtree: false, // Only direct children to avoid too many callbacks
|
|
725
|
+
});
|
|
726
|
+
}
|
|
684
727
|
resizeObserver = connectResizeObserver(node, () => {
|
|
728
|
+
checkNodeExists();
|
|
729
|
+
if (!document.contains(node))
|
|
730
|
+
return; // Exit early if node was removed
|
|
685
731
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
686
732
|
console.log("resizeObserver", node);
|
|
687
733
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
@@ -701,6 +747,7 @@
|
|
|
701
747
|
removeListeners();
|
|
702
748
|
resizeObserver?.disconnect();
|
|
703
749
|
mutationObserver?.disconnect();
|
|
750
|
+
parentMutationObserver?.disconnect();
|
|
704
751
|
text.blurEditMode();
|
|
705
752
|
throttledRefreshAndVisibility.cleanup();
|
|
706
753
|
};
|
|
@@ -709,8 +756,6 @@
|
|
|
709
756
|
getSelectedNode: () => selectedNode,
|
|
710
757
|
refreshHighlightFrame: () => {
|
|
711
758
|
if (selectedNode && nodeProvider) {
|
|
712
|
-
// Call directly (not throttled) since this is typically called from already-throttled contexts
|
|
713
|
-
// to avoid double RAF
|
|
714
759
|
refreshHighlightFrame(selectedNode, nodeProvider, canvasName);
|
|
715
760
|
updateHighlightFrameVisibility(selectedNode);
|
|
716
761
|
}
|
|
@@ -720,6 +765,7 @@
|
|
|
720
765
|
selectedNode = null;
|
|
721
766
|
resizeObserver?.disconnect();
|
|
722
767
|
mutationObserver?.disconnect();
|
|
768
|
+
parentMutationObserver?.disconnect();
|
|
723
769
|
},
|
|
724
770
|
getEditableNode: () => text.getEditableNode(),
|
|
725
771
|
cleanup,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).MarkupCanvas={})}(this,function(e){"use strict";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()}}}});
|
|
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}function o(e,t){window.parent.postMessage({source:"node-edit-utils",action:e,data:t,timestamp:Date.now()},"*")}const r=()=>{const e=document.body.querySelector(".highlight-frame-overlay");e&&e.remove();const t=document.body.querySelector(".highlight-frame-tools-wrapper");t&&t.remove()},s=["path","rect","circle","ellipse","polygon","line","polyline","text","text-noci"];let i=[],a=0;const l=(e,t)=>{let n=null;const o=e.clientX,r=e.clientY,l=e.metaKey||e.ctrlKey,c=((e,t)=>{const n=document.elementsFromPoint(e,t);return Array.from(n).reduce((e,t)=>e.found?e:"node-provider"===t.getAttribute("data-role")?(e.found=!0,e):(e.elements.push(t),e),{elements:[],found:!1}).elements})(o,r).filter(e=>!s.includes(e.tagName.toLowerCase())&&!e.classList.contains("select-none")&&!(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&&c.includes(t))return t;if(l)return i=[],n=c[0],n;var d,u;u=c,(d=i).length===u.length&&d.every((e,t)=>e===u[t])?a<=c.length&&a++:a=0;return n=c[c.length-1-a],i=c,n},c=(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(l(e,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)}},d=e=>"true"===e.getAttribute("data-instance"),u=(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 m(e){const t=e.getBoundingClientRect();return{top:t.top,left:t.left,width:t.width,height:t.height}}const h=(e,t=!1)=>{const{top:n,left:o,width:r,height:s}=m(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 c=document.createElementNS("http://www.w3.org/2000/svg","g");c.classList.add("highlight-frame-group"),c.setAttribute("transform",`translate(${o}, ${n})`);const d=document.createElementNS("http://www.w3.org/2000/svg","rect");return d.setAttribute("x","0"),d.setAttribute("y","0"),d.setAttribute("width",r.toString()),d.setAttribute("height",s.toString()),d.setAttribute("vector-effect","non-scaling-stroke"),d.classList.add("highlight-frame-rect"),t&&d.setAttribute("stroke",getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim()||"oklch(65.6% 0.241 354.308)"),c.appendChild(d),((e,t,n,o=!1)=>{u(e,0,0,"handle-top-left",o),u(e,t,0,"handle-top-right",o),u(e,t,n,"handle-bottom-right",o),u(e,0,n,"handle-bottom-left",o)})(c,r,s,t),i.appendChild(c),document.body.appendChild(i),i},g=(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 p(){return document.body.querySelector(".highlight-frame-overlay")}const b=()=>getComputedStyle(document.documentElement).getPropertyValue("--component-color").trim()||"oklch(65.6% 0.241 354.308)",v=(e,n,o="canvas")=>{const r=p();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",b()):c.removeAttribute("stroke");const u=document.body.querySelector(".highlight-frame-tools-wrapper"),h=u?.querySelector(".node-tools"),g=t(["zoom","current"],o)??1,v=m(e),{top:f,left:y,width:w,height:E}=v,L=f+E;u&&(s?u.classList.add("is-instance"):u.classList.remove("is-instance")),h&&(s?h.classList.add("is-instance"):h.classList.remove("is-instance")),l.setAttribute("transform",`translate(${y}, ${f})`),c.setAttribute("width",w.toString()),c.setAttribute("height",E.toString());const A=l.querySelector(".handle-top-left"),S=l.querySelector(".handle-top-right"),x=l.querySelector(".handle-bottom-right"),N=l.querySelector(".handle-bottom-left");[A,S,x,N].forEach(e=>{e&&(s?e.setAttribute("stroke",b()):e.removeAttribute("stroke"))}),A&&(A.setAttribute("x",(-3).toString()),A.setAttribute("y",(-3).toString())),S&&(S.setAttribute("x",(w-3).toString()),S.setAttribute("y",(-3).toString())),x&&(x.setAttribute("x",(w-3).toString()),x.setAttribute("y",(E-3).toString())),N&&(N.setAttribute("x",(-3).toString()),N.setAttribute("y",(E-3).toString())),u&&(u.style.left=`${y}px`,u.style.top=`${L}px`),g<=10?n.style.setProperty("--tool-opacity","1"):n.style.setProperty("--tool-opacity","0")},f=e=>{const t=p();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)}},w=(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,()=>{v(e,t,n)});return()=>o.disconnect()},E=(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=w(e,t,o);return()=>{e.removeEventListener("blur",n),r(),s?.()}})(o,i,s,e))},blurEditMode:s,getEditableNode:()=>n,isEditing:()=>null!==n}},L=320,A=1680,S=[{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"}],x=(e,t,n)=>{const o=parseFloat(document.body.dataset.zoom||"1"),r=((e,t)=>{const n=e+Math.round(t);return Math.max(L,Math.min(A,n))})(n,(e.clientX-t)/o);return r},N=(e,t)=>{e.style.setProperty("--container-width",`${t}px`),((e,t)=>{e.querySelectorAll(".resize-preset-button").forEach((e,n)=>{n<S.length&&(S[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,l=null,u=null;const b=E(t),y=n((e,n)=>{v(e,n,t),f(e)}),w=e=>{if(u!==e){if(b.isEditing()){const t=b.getEditableNode();t&&t!==e&&b.blurEditMode()}if(i?.disconnect(),a?.disconnect(),l?.disconnect(),e&&s){b.enableEditMode(e,s);const n=()=>{if(!document.contains(e))return r(),u=null,i?.disconnect(),a?.disconnect(),l?.disconnect(),void o("selectedNodeChanged",null)};a=new MutationObserver(()=>{n(),document.contains(e)&&(console.log("mutationObserver",e),v(e,s,t),f(e))}),a.observe(e,{attributes:!0,characterData:!0,childList:!0,subtree:!0});const c=e.parentElement;c&&(l=new MutationObserver(t=>{for(const o of t)if("childList"===o.type)for(const t of Array.from(o.removedNodes))if(t===e||t instanceof Node&&t.contains(e))return void n()}),l.observe(c,{childList:!0,subtree:!1})),i=((e,t)=>{const n=new ResizeObserver(e=>{t(e)});return n.observe(e),n})(e,()=>{n(),document.contains(e)&&(console.log("resizeObserver",e),v(e,s,t),f(e))})}u=e,o("selectedNodeChanged",e?.getAttribute("data-node-id")??null),(e=>{if(!e)return;const t=p(),n=document.body.querySelector(".highlight-frame-tools-wrapper");t&&t.remove(),n&&n.remove();const o=d(e),r=h(e,o);"true"===e.contentEditable&&r.classList.add("is-editable");const{left:s,top:i,height:a}=m(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",g(e,c,o),document.body.appendChild(c)})(e),e&&s&&f(e)}},L=c(s,w,()=>{b.isEditing()&&b.blurEditMode(),u&&s&&(r(),u=null,i?.disconnect(),a?.disconnect(),l?.disconnect())},b.getEditableNode),A={selectNode:w,getSelectedNode:()=>u,refreshHighlightFrame:()=>{u&&s&&(v(u,s,t),f(u))},clearSelectedNode:()=>{r(),u=null,i?.disconnect(),a?.disconnect(),l?.disconnect()},getEditableNode:()=>b.getEditableNode(),cleanup:()=>{L(),i?.disconnect(),a?.disconnect(),l?.disconnect(),b.blurEditMode(),y.cleanup()}};var S,x;return S="nodeTools",x=A,"undefined"!=typeof window&&(window[S]=x),A},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",S.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,N);let s=!1,i=0,a=0;const l=n(n=>{if(!s)return;t&&(t.style.cursor="ew-resize");const o=x(n,i,a);N(e,o)}),c=((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=>{N(e,t)},cleanup:()=>{s=!1,l?.cleanup(),c(),r.remove()}}}});
|
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@ export const createNodeTools = (element: HTMLElement | null, canvasName: string
|
|
|
15
15
|
|
|
16
16
|
let resizeObserver: ResizeObserver | null = null;
|
|
17
17
|
let mutationObserver: MutationObserver | null = null;
|
|
18
|
+
let parentMutationObserver: MutationObserver | null = null;
|
|
18
19
|
let selectedNode: HTMLElement | null = null;
|
|
19
20
|
|
|
20
21
|
const text = nodeText(canvasName);
|
|
@@ -37,6 +38,7 @@ export const createNodeTools = (element: HTMLElement | null, canvasName: string
|
|
|
37
38
|
|
|
38
39
|
resizeObserver?.disconnect();
|
|
39
40
|
mutationObserver?.disconnect();
|
|
41
|
+
parentMutationObserver?.disconnect();
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
};
|
|
@@ -55,11 +57,29 @@ export const createNodeTools = (element: HTMLElement | null, canvasName: string
|
|
|
55
57
|
|
|
56
58
|
resizeObserver?.disconnect();
|
|
57
59
|
mutationObserver?.disconnect();
|
|
60
|
+
parentMutationObserver?.disconnect();
|
|
58
61
|
|
|
59
62
|
if (node && nodeProvider) {
|
|
60
63
|
text.enableEditMode(node, nodeProvider);
|
|
61
64
|
|
|
65
|
+
// Check if node is still in DOM and handle cleanup if removed
|
|
66
|
+
const checkNodeExists = (): void => {
|
|
67
|
+
if (!document.contains(node)) {
|
|
68
|
+
// Node was removed from DOM, clear highlight and cleanup
|
|
69
|
+
clearHighlightFrame();
|
|
70
|
+
selectedNode = null;
|
|
71
|
+
resizeObserver?.disconnect();
|
|
72
|
+
mutationObserver?.disconnect();
|
|
73
|
+
parentMutationObserver?.disconnect();
|
|
74
|
+
sendPostMessage("selectedNodeChanged", null);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
62
79
|
mutationObserver = new MutationObserver(() => {
|
|
80
|
+
checkNodeExists();
|
|
81
|
+
if (!document.contains(node)) return; // Exit early if node was removed
|
|
82
|
+
|
|
63
83
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
64
84
|
console.log("mutationObserver", node);
|
|
65
85
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
@@ -69,9 +89,38 @@ export const createNodeTools = (element: HTMLElement | null, canvasName: string
|
|
|
69
89
|
mutationObserver.observe(node, {
|
|
70
90
|
attributes: true,
|
|
71
91
|
characterData: true,
|
|
92
|
+
childList: true,
|
|
93
|
+
subtree: true,
|
|
72
94
|
});
|
|
73
95
|
|
|
96
|
+
// Also observe parent node to catch when this node is removed
|
|
97
|
+
const parentNode = node.parentElement;
|
|
98
|
+
if (parentNode) {
|
|
99
|
+
parentMutationObserver = new MutationObserver((mutations) => {
|
|
100
|
+
// Check if the selected node was removed
|
|
101
|
+
for (const mutation of mutations) {
|
|
102
|
+
if (mutation.type === "childList") {
|
|
103
|
+
for (const removedNode of Array.from(mutation.removedNodes)) {
|
|
104
|
+
// Check if the removed node is the selected node, or if the selected node is contained within the removed subtree
|
|
105
|
+
if (removedNode === node || (removedNode instanceof Node && removedNode.contains(node))) {
|
|
106
|
+
checkNodeExists();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
parentMutationObserver.observe(parentNode, {
|
|
115
|
+
childList: true,
|
|
116
|
+
subtree: false, // Only direct children to avoid too many callbacks
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
74
120
|
resizeObserver = connectResizeObserver(node, () => {
|
|
121
|
+
checkNodeExists();
|
|
122
|
+
if (!document.contains(node)) return; // Exit early if node was removed
|
|
123
|
+
|
|
75
124
|
// throttledRefreshAndVisibility(node, nodeProvider);
|
|
76
125
|
console.log("resizeObserver", node);
|
|
77
126
|
refreshHighlightFrame(node, nodeProvider, canvasName);
|
|
@@ -95,6 +144,7 @@ export const createNodeTools = (element: HTMLElement | null, canvasName: string
|
|
|
95
144
|
removeListeners();
|
|
96
145
|
resizeObserver?.disconnect();
|
|
97
146
|
mutationObserver?.disconnect();
|
|
147
|
+
parentMutationObserver?.disconnect();
|
|
98
148
|
|
|
99
149
|
text.blurEditMode();
|
|
100
150
|
throttledRefreshAndVisibility.cleanup();
|
|
@@ -105,8 +155,6 @@ export const createNodeTools = (element: HTMLElement | null, canvasName: string
|
|
|
105
155
|
getSelectedNode: () => selectedNode,
|
|
106
156
|
refreshHighlightFrame: () => {
|
|
107
157
|
if (selectedNode && nodeProvider) {
|
|
108
|
-
// Call directly (not throttled) since this is typically called from already-throttled contexts
|
|
109
|
-
// to avoid double RAF
|
|
110
158
|
refreshHighlightFrame(selectedNode, nodeProvider, canvasName);
|
|
111
159
|
updateHighlightFrameVisibility(selectedNode);
|
|
112
160
|
}
|
|
@@ -116,6 +164,7 @@ export const createNodeTools = (element: HTMLElement | null, canvasName: string
|
|
|
116
164
|
selectedNode = null;
|
|
117
165
|
resizeObserver?.disconnect();
|
|
118
166
|
mutationObserver?.disconnect();
|
|
167
|
+
parentMutationObserver?.disconnect();
|
|
119
168
|
},
|
|
120
169
|
getEditableNode: () => text.getEditableNode(),
|
|
121
170
|
cleanup,
|