@node-edit-utils/core 2.2.8 → 2.2.9

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