@node-edit-utils/core 2.2.4 → 2.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -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.6
|
|
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,16 +743,19 @@ 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();
|
|
749
|
+
// Clear highlight frame and reset selected node
|
|
750
|
+
clearHighlightFrame();
|
|
751
|
+
selectedNode = null;
|
|
752
|
+
sendPostMessage("selectedNodeChanged", null);
|
|
702
753
|
};
|
|
703
754
|
const nodeTools = {
|
|
704
755
|
selectNode,
|
|
705
756
|
getSelectedNode: () => selectedNode,
|
|
706
757
|
refreshHighlightFrame: () => {
|
|
707
758
|
if (selectedNode && nodeProvider) {
|
|
708
|
-
// Call directly (not throttled) since this is typically called from already-throttled contexts
|
|
709
|
-
// to avoid double RAF
|
|
710
759
|
refreshHighlightFrame(selectedNode, nodeProvider, canvasName);
|
|
711
760
|
updateHighlightFrameVisibility(selectedNode);
|
|
712
761
|
}
|
|
@@ -716,6 +765,7 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
716
765
|
selectedNode = null;
|
|
717
766
|
resizeObserver?.disconnect();
|
|
718
767
|
mutationObserver?.disconnect();
|
|
768
|
+
parentMutationObserver?.disconnect();
|
|
719
769
|
},
|
|
720
770
|
getEditableNode: () => text.getEditableNode(),
|
|
721
771
|
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.6
|
|
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,16 +741,19 @@ 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();
|
|
747
|
+
// Clear highlight frame and reset selected node
|
|
748
|
+
clearHighlightFrame();
|
|
749
|
+
selectedNode = null;
|
|
750
|
+
sendPostMessage("selectedNodeChanged", null);
|
|
700
751
|
};
|
|
701
752
|
const nodeTools = {
|
|
702
753
|
selectNode,
|
|
703
754
|
getSelectedNode: () => selectedNode,
|
|
704
755
|
refreshHighlightFrame: () => {
|
|
705
756
|
if (selectedNode && nodeProvider) {
|
|
706
|
-
// Call directly (not throttled) since this is typically called from already-throttled contexts
|
|
707
|
-
// to avoid double RAF
|
|
708
757
|
refreshHighlightFrame(selectedNode, nodeProvider, canvasName);
|
|
709
758
|
updateHighlightFrameVisibility(selectedNode);
|
|
710
759
|
}
|
|
@@ -714,6 +763,7 @@ const createNodeTools = (element, canvasName = "canvas") => {
|
|
|
714
763
|
selectedNode = null;
|
|
715
764
|
resizeObserver?.disconnect();
|
|
716
765
|
mutationObserver?.disconnect();
|
|
766
|
+
parentMutationObserver?.disconnect();
|
|
717
767
|
},
|
|
718
768
|
getEditableNode: () => text.getEditableNode(),
|
|
719
769
|
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.6
|
|
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,16 +747,19 @@
|
|
|
701
747
|
removeListeners();
|
|
702
748
|
resizeObserver?.disconnect();
|
|
703
749
|
mutationObserver?.disconnect();
|
|
750
|
+
parentMutationObserver?.disconnect();
|
|
704
751
|
text.blurEditMode();
|
|
705
752
|
throttledRefreshAndVisibility.cleanup();
|
|
753
|
+
// Clear highlight frame and reset selected node
|
|
754
|
+
clearHighlightFrame();
|
|
755
|
+
selectedNode = null;
|
|
756
|
+
sendPostMessage("selectedNodeChanged", null);
|
|
706
757
|
};
|
|
707
758
|
const nodeTools = {
|
|
708
759
|
selectNode,
|
|
709
760
|
getSelectedNode: () => selectedNode,
|
|
710
761
|
refreshHighlightFrame: () => {
|
|
711
762
|
if (selectedNode && nodeProvider) {
|
|
712
|
-
// Call directly (not throttled) since this is typically called from already-throttled contexts
|
|
713
|
-
// to avoid double RAF
|
|
714
763
|
refreshHighlightFrame(selectedNode, nodeProvider, canvasName);
|
|
715
764
|
updateHighlightFrameVisibility(selectedNode);
|
|
716
765
|
}
|
|
@@ -720,6 +769,7 @@
|
|
|
720
769
|
selectedNode = null;
|
|
721
770
|
resizeObserver?.disconnect();
|
|
722
771
|
mutationObserver?.disconnect();
|
|
772
|
+
parentMutationObserver?.disconnect();
|
|
723
773
|
},
|
|
724
774
|
getEditableNode: () => text.getEditableNode(),
|
|
725
775
|
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(),r(),u=null,o("selectedNodeChanged",null)}};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,9 +144,15 @@ 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();
|
|
151
|
+
|
|
152
|
+
// Clear highlight frame and reset selected node
|
|
153
|
+
clearHighlightFrame();
|
|
154
|
+
selectedNode = null;
|
|
155
|
+
sendPostMessage("selectedNodeChanged", null);
|
|
101
156
|
};
|
|
102
157
|
|
|
103
158
|
const nodeTools: NodeTools = {
|
|
@@ -105,8 +160,6 @@ export const createNodeTools = (element: HTMLElement | null, canvasName: string
|
|
|
105
160
|
getSelectedNode: () => selectedNode,
|
|
106
161
|
refreshHighlightFrame: () => {
|
|
107
162
|
if (selectedNode && nodeProvider) {
|
|
108
|
-
// Call directly (not throttled) since this is typically called from already-throttled contexts
|
|
109
|
-
// to avoid double RAF
|
|
110
163
|
refreshHighlightFrame(selectedNode, nodeProvider, canvasName);
|
|
111
164
|
updateHighlightFrameVisibility(selectedNode);
|
|
112
165
|
}
|
|
@@ -116,6 +169,7 @@ export const createNodeTools = (element: HTMLElement | null, canvasName: string
|
|
|
116
169
|
selectedNode = null;
|
|
117
170
|
resizeObserver?.disconnect();
|
|
118
171
|
mutationObserver?.disconnect();
|
|
172
|
+
parentMutationObserver?.disconnect();
|
|
119
173
|
},
|
|
120
174
|
getEditableNode: () => text.getEditableNode(),
|
|
121
175
|
cleanup,
|