@node-edit-utils/core 2.1.4 → 2.1.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.1.4
4
+ * @version 2.1.6
5
5
  */
6
6
  'use strict';
7
7
 
@@ -314,7 +314,12 @@ const updateHighlightFrameVisibility = (node, nodeProvider) => {
314
314
  if (!frame)
315
315
  return;
316
316
  const hasHiddenClass = node.classList.contains("hidden") || node.classList.contains("select-none");
317
- frame.style.display = hasHiddenClass ? "none" : "";
317
+ const displayValue = hasHiddenClass ? "none" : "";
318
+ frame.style.display = displayValue;
319
+ const tagLabel = frame.querySelector(".tag-label");
320
+ if (tagLabel) {
321
+ tagLabel.style.display = displayValue;
322
+ }
318
323
  };
319
324
 
320
325
  const disableCanvasTextMode = () => {
@@ -454,6 +459,7 @@ const createNodeTools = (element) => {
454
459
  const nodeProvider = element;
455
460
  let resizeObserver = null;
456
461
  let mutationObserver = null;
462
+ let parentMutationObserver = null;
457
463
  let selectedNode = null;
458
464
  const text = nodeText();
459
465
  const throttledFrameRefresh = withRAFThrottle(refreshHighlightFrame);
@@ -467,6 +473,7 @@ const createNodeTools = (element) => {
467
473
  selectedNode = null;
468
474
  resizeObserver?.disconnect();
469
475
  mutationObserver?.disconnect();
476
+ parentMutationObserver?.disconnect();
470
477
  }
471
478
  }
472
479
  };
@@ -482,6 +489,7 @@ const createNodeTools = (element) => {
482
489
  }
483
490
  resizeObserver?.disconnect();
484
491
  mutationObserver?.disconnect();
492
+ parentMutationObserver?.disconnect();
485
493
  if (node && nodeProvider) {
486
494
  text.enableEditMode(node, nodeProvider);
487
495
  resizeObserver = connectResizeObserver(nodeProvider, () => {
@@ -493,8 +501,21 @@ const createNodeTools = (element) => {
493
501
  });
494
502
  mutationObserver.observe(node, {
495
503
  attributes: true,
496
- attributeFilter: ["class"],
504
+ subtree: true,
505
+ childList: true,
506
+ characterData: true,
497
507
  });
508
+ const parent = node.parentElement;
509
+ if (parent) {
510
+ parentMutationObserver = new MutationObserver(() => {
511
+ throttledFrameRefresh(node, nodeProvider);
512
+ updateHighlightFrameVisibility(node, nodeProvider);
513
+ });
514
+ parentMutationObserver.observe(parent, {
515
+ childList: true,
516
+ subtree: true,
517
+ });
518
+ }
498
519
  }
499
520
  selectedNode = node;
500
521
  sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
@@ -509,6 +530,7 @@ const createNodeTools = (element) => {
509
530
  removeListeners();
510
531
  resizeObserver?.disconnect();
511
532
  mutationObserver?.disconnect();
533
+ parentMutationObserver?.disconnect();
512
534
  text.blurEditMode();
513
535
  throttledFrameRefresh.cleanup();
514
536
  };
@@ -523,6 +545,7 @@ const createNodeTools = (element) => {
523
545
  selectedNode = null;
524
546
  resizeObserver?.disconnect();
525
547
  mutationObserver?.disconnect();
548
+ parentMutationObserver?.disconnect();
526
549
  },
527
550
  getEditableNode: () => text.getEditableNode(),
528
551
  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.1.4
4
+ * @version 2.1.6
5
5
  */
6
6
  // biome-ignore lint/suspicious/noExplicitAny: generic constraint requires flexibility
7
7
  function withRAFThrottle(func) {
@@ -312,7 +312,12 @@ const updateHighlightFrameVisibility = (node, nodeProvider) => {
312
312
  if (!frame)
313
313
  return;
314
314
  const hasHiddenClass = node.classList.contains("hidden") || node.classList.contains("select-none");
315
- frame.style.display = hasHiddenClass ? "none" : "";
315
+ const displayValue = hasHiddenClass ? "none" : "";
316
+ frame.style.display = displayValue;
317
+ const tagLabel = frame.querySelector(".tag-label");
318
+ if (tagLabel) {
319
+ tagLabel.style.display = displayValue;
320
+ }
316
321
  };
317
322
 
318
323
  const disableCanvasTextMode = () => {
@@ -452,6 +457,7 @@ const createNodeTools = (element) => {
452
457
  const nodeProvider = element;
453
458
  let resizeObserver = null;
454
459
  let mutationObserver = null;
460
+ let parentMutationObserver = null;
455
461
  let selectedNode = null;
456
462
  const text = nodeText();
457
463
  const throttledFrameRefresh = withRAFThrottle(refreshHighlightFrame);
@@ -465,6 +471,7 @@ const createNodeTools = (element) => {
465
471
  selectedNode = null;
466
472
  resizeObserver?.disconnect();
467
473
  mutationObserver?.disconnect();
474
+ parentMutationObserver?.disconnect();
468
475
  }
469
476
  }
470
477
  };
@@ -480,6 +487,7 @@ const createNodeTools = (element) => {
480
487
  }
481
488
  resizeObserver?.disconnect();
482
489
  mutationObserver?.disconnect();
490
+ parentMutationObserver?.disconnect();
483
491
  if (node && nodeProvider) {
484
492
  text.enableEditMode(node, nodeProvider);
485
493
  resizeObserver = connectResizeObserver(nodeProvider, () => {
@@ -491,8 +499,21 @@ const createNodeTools = (element) => {
491
499
  });
492
500
  mutationObserver.observe(node, {
493
501
  attributes: true,
494
- attributeFilter: ["class"],
502
+ subtree: true,
503
+ childList: true,
504
+ characterData: true,
495
505
  });
506
+ const parent = node.parentElement;
507
+ if (parent) {
508
+ parentMutationObserver = new MutationObserver(() => {
509
+ throttledFrameRefresh(node, nodeProvider);
510
+ updateHighlightFrameVisibility(node, nodeProvider);
511
+ });
512
+ parentMutationObserver.observe(parent, {
513
+ childList: true,
514
+ subtree: true,
515
+ });
516
+ }
496
517
  }
497
518
  selectedNode = node;
498
519
  sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
@@ -507,6 +528,7 @@ const createNodeTools = (element) => {
507
528
  removeListeners();
508
529
  resizeObserver?.disconnect();
509
530
  mutationObserver?.disconnect();
531
+ parentMutationObserver?.disconnect();
510
532
  text.blurEditMode();
511
533
  throttledFrameRefresh.cleanup();
512
534
  };
@@ -521,6 +543,7 @@ const createNodeTools = (element) => {
521
543
  selectedNode = null;
522
544
  resizeObserver?.disconnect();
523
545
  mutationObserver?.disconnect();
546
+ parentMutationObserver?.disconnect();
524
547
  },
525
548
  getEditableNode: () => text.getEditableNode(),
526
549
  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.1.4
4
+ * @version 2.1.6
5
5
  */
6
6
  (function (global, factory) {
7
7
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
@@ -318,7 +318,12 @@
318
318
  if (!frame)
319
319
  return;
320
320
  const hasHiddenClass = node.classList.contains("hidden") || node.classList.contains("select-none");
321
- frame.style.display = hasHiddenClass ? "none" : "";
321
+ const displayValue = hasHiddenClass ? "none" : "";
322
+ frame.style.display = displayValue;
323
+ const tagLabel = frame.querySelector(".tag-label");
324
+ if (tagLabel) {
325
+ tagLabel.style.display = displayValue;
326
+ }
322
327
  };
323
328
 
324
329
  const disableCanvasTextMode = () => {
@@ -458,6 +463,7 @@
458
463
  const nodeProvider = element;
459
464
  let resizeObserver = null;
460
465
  let mutationObserver = null;
466
+ let parentMutationObserver = null;
461
467
  let selectedNode = null;
462
468
  const text = nodeText();
463
469
  const throttledFrameRefresh = withRAFThrottle(refreshHighlightFrame);
@@ -471,6 +477,7 @@
471
477
  selectedNode = null;
472
478
  resizeObserver?.disconnect();
473
479
  mutationObserver?.disconnect();
480
+ parentMutationObserver?.disconnect();
474
481
  }
475
482
  }
476
483
  };
@@ -486,6 +493,7 @@
486
493
  }
487
494
  resizeObserver?.disconnect();
488
495
  mutationObserver?.disconnect();
496
+ parentMutationObserver?.disconnect();
489
497
  if (node && nodeProvider) {
490
498
  text.enableEditMode(node, nodeProvider);
491
499
  resizeObserver = connectResizeObserver(nodeProvider, () => {
@@ -497,8 +505,21 @@
497
505
  });
498
506
  mutationObserver.observe(node, {
499
507
  attributes: true,
500
- attributeFilter: ["class"],
508
+ subtree: true,
509
+ childList: true,
510
+ characterData: true,
501
511
  });
512
+ const parent = node.parentElement;
513
+ if (parent) {
514
+ parentMutationObserver = new MutationObserver(() => {
515
+ throttledFrameRefresh(node, nodeProvider);
516
+ updateHighlightFrameVisibility(node, nodeProvider);
517
+ });
518
+ parentMutationObserver.observe(parent, {
519
+ childList: true,
520
+ subtree: true,
521
+ });
522
+ }
502
523
  }
503
524
  selectedNode = node;
504
525
  sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
@@ -513,6 +534,7 @@
513
534
  removeListeners();
514
535
  resizeObserver?.disconnect();
515
536
  mutationObserver?.disconnect();
537
+ parentMutationObserver?.disconnect();
516
538
  text.blurEditMode();
517
539
  throttledFrameRefresh.cleanup();
518
540
  };
@@ -527,6 +549,7 @@
527
549
  selectedNode = null;
528
550
  resizeObserver?.disconnect();
529
551
  mutationObserver?.disconnect();
552
+ parentMutationObserver?.disconnect();
530
553
  },
531
554
  getEditableNode: () => text.getEditableNode(),
532
555
  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";function t(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 n=e=>{const t=window.canvas;return e.reduce((e,t)=>e?.[t],t)};function o(e){return e.querySelector(".highlight-frame")}const r=e=>{if(!e)return;const t=o(e);t&&t.remove()},s=["path","rect","circle","ellipse","polygon","line","polyline","text","text-noci"];let a=[],i=0;const d=(e,t)=>{let n=null;const o=e.clientX,r=e.clientY,d=e.metaKey||e.ctrlKey,l=((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"));if(t&&l.includes(t))return t;if(d)return a=[],n=l[0],n;var c,u;u=l,(c=a).length===u.length&&c.every((e,t)=>e===u[t])?i<=l.length&&i++:i=0;return n=l[l.length-1-i],a=l,n},l=(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)},a=n=>{((e,t,n,o)=>{if(e.preventDefault(),e.stopPropagation(),t&&!t.contains(e.target))return r(t),void o(null);o(d(e,n))})(n,e,o(),t)},i=e=>{"Escape"===e.key&&(e.preventDefault(),e.stopPropagation(),n?.())};return window.addEventListener("message",s),document.addEventListener("click",a),document.addEventListener("keydown",i),()=>{window.removeEventListener("message",s),document.removeEventListener("click",a),document.removeEventListener("keydown",i)}};function c(e,t){const o=e.getBoundingClientRect(),r=t.getBoundingClientRect(),s=o.top-r.top,a=o.left-r.left,i=n(["zoom","current"])??1;return{top:parseFloat((s/i).toFixed(5)),left:parseFloat((a/i).toFixed(5)),width:Math.max(4,parseFloat((o.width/i).toFixed(5))),height:parseFloat((o.height/i).toFixed(5))}}const u=(e,t)=>{const n=document.createElement("div");n.className="node-tools",t.appendChild(n),((e,t)=>{const n=document.createElement("div");n.className="tag-label",n.textContent=e.tagName.toLowerCase(),t.appendChild(n)})(e,n)},m=(e,t)=>{if(!e)return;const r=o(t);r&&r.remove();const s=((e,t)=>{const{top:o,left:r,width:s,height:a}=c(e,t),i=n(["zoom","current"])??1;document.body.style.setProperty("--zoom",i.toString()),document.body.style.setProperty("--stroke-width",(2/i).toFixed(3));const d=document.createElement("div");d.classList.add("highlight-frame"),d.style.setProperty("--frame-top",`${o}px`),d.style.setProperty("--frame-left",`${r}px`),d.style.setProperty("--frame-width",`${s}px`),d.style.setProperty("--frame-height",`${a}px`);const l=document.createElementNS("http://www.w3.org/2000/svg","svg");l.classList.add("highlight-frame-svg");const u=document.createElementNS("http://www.w3.org/2000/svg","rect");return u.setAttribute("x","0"),u.setAttribute("y","0"),u.setAttribute("width","100%"),u.setAttribute("height","100%"),u.classList.add("highlight-frame-rect"),l.appendChild(u),d.appendChild(l),d})(e,t);"true"===e.contentEditable&&s.classList.add("is-editable"),u(e,s),t.appendChild(s)},p=(e,t)=>{const r=o(t),s=n(["zoom","current"])??1;if(!r)return;s>=.3?t.style.setProperty("--tool-opacity","1"):t.style.setProperty("--tool-opacity","0");const{top:a,left:i,width:d,height:l}=c(e,t);r.style.setProperty("--frame-top",`${a}px`),r.style.setProperty("--frame-left",`${i}px`),r.style.setProperty("--frame-width",`${d}px`),r.style.setProperty("--frame-height",`${l}px`)},v=(e,t)=>{const n=o(t);if(!n)return;const r=e.classList.contains("hidden")||e.classList.contains("select-none");n.style.display=r?"none":""},h=e=>{const t=e=>{"Enter"===e.key&&(e.preventDefault(),e.stopPropagation(),(()=>{const e=window.getSelection();if(e&&e.rangeCount>0){const t=e.getRangeAt(0);t.deleteContents();const n=document.createElement("br");t.insertNode(n),t.setStartAfter(n),t.setEndAfter(n),e.removeAllRanges(),e.addRange(t)}})())};return e.addEventListener("keydown",t),()=>{e.removeEventListener("keydown",t)}},f=(e,t)=>{const n=((e,t)=>{const n=new MutationObserver(e=>{t(e)});return n.observe(e,{subtree:!0,childList:!0,characterData:!0}),n})(e,()=>{p(e,t)});return()=>n.disconnect()},y=()=>{let e=null,t=!1,o=null;const r=()=>{if(t||!e)return;t=!0;var r;(r=e).contentEditable="false",r.classList.remove("is-editable"),r.style.outline="none",(()=>{const e=n(["keyboard","disableTextEditMode"]);e?.()})(),o?.(),e=null,t=!1};return{enableEditMode:(t,s)=>{if(e===t)return;e&&e!==t&&r();const a=(e=>Array.from(e.childNodes).some(e=>e.nodeType===Node.TEXT_NODE&&e.textContent?.trim()))(t);a&&(e=t,(e=>{e.contentEditable="true",e.classList.add("is-editable"),e.style.outline="none"})(t),(()=>{const e=n(["keyboard","enableTextEditMode"]);e?.()})(),o=((e,t,n)=>{if(!t)return()=>{};e.addEventListener("blur",n);const o=h(e),r=f(e,t);return()=>{e.removeEventListener("blur",n),o(),r?.()}})(t,s,r))},blurEditMode:r,getEditableNode:()=>e,isEditing:()=>null!==e}},g=320,b=1680,w=[{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"}],E=(e,t,n)=>{const o=parseFloat(document.body.dataset.zoom||"1"),r=((e,t)=>{const n=e+Math.round(t);return Math.max(g,Math.min(b,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<w.length&&(w[n].rawValue===t?e.classList.add("is-active"):e.classList.remove("is-active"))})})(e,t)};e.createCanvasObserver=function(){const e=document.querySelector(".transform-layer");if(!e)return{disconnect:()=>{}};const o=t(()=>{(()=>{const e=n(["zoom","current"]);document.body.style.setProperty("--zoom",e.toFixed(5)),document.body.style.setProperty("--stroke-width",(2/e).toFixed(3)),document.body.dataset.zoom=e.toFixed(5),document.body.dataset.strokeWidth=(2/e).toFixed(3)})()}),r=new MutationObserver(()=>{o()});return r.observe(e,{attributes:!0,attributeOldValue:!0,subtree:!0,childList:!0}),{disconnect:function(){o.cleanup(),r.disconnect()}}},e.createNodeTools=e=>{const n=e;let o=null,s=null,a=null;const i=y(),d=t(p),c=e=>{if(a!==e){if(i.isEditing()){const t=i.getEditableNode();t&&t!==e&&i.blurEditMode()}var t,r;o?.disconnect(),s?.disconnect(),e&&n&&(i.enableEditMode(e,n),o=((e,t)=>{const n=new ResizeObserver(e=>{t(e)});return n.observe(e),n})(n,()=>{d(e,n)}),s=new MutationObserver(()=>{d(e,n),v(e,n)}),s.observe(e,{attributes:!0,attributeFilter:["class"]})),a=e,t="selectedNodeChanged",r=e?.getAttribute("data-node-id")??null,window.parent.postMessage({source:"node-edit-utils",action:t,data:r,timestamp:Date.now()},"*"),m(e,n),e&&n&&v(e,n)}},u=l(n,c,()=>{i.isEditing()&&i.blurEditMode(),a&&n&&(r(n),a=null,o?.disconnect(),s?.disconnect())},i.getEditableNode),h={selectNode:c,getSelectedNode:()=>a,refreshHighlightFrame:()=>{d(a,n)},clearSelectedNode:()=>{r(n),a=null,o?.disconnect(),s?.disconnect()},getEditableNode:()=>i.getEditableNode(),cleanup:()=>{u(),o?.disconnect(),s?.disconnect(),i.blurEditMode(),d.cleanup()}};var f,g;return f="nodeTools",g=h,"undefined"!=typeof window&&(window[f]=g),h},e.createViewport=e=>{const n=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",w.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,a=0,i=0;const d=t(t=>{if(!s)return;n&&(n.style.cursor="ew-resize");const o=E(t,a,i);x(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,a=t.clientX,i=e.offsetWidth},d,e=>{e.preventDefault(),e.stopPropagation(),n&&(n.style.cursor="default"),s=!1},()=>{s=!1});return{setWidth:t=>{x(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";function t(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 n=e=>{const t=window.canvas;return e.reduce((e,t)=>e?.[t],t)};function o(e){return e.querySelector(".highlight-frame")}const r=e=>{if(!e)return;const t=o(e);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,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,r).filter(e=>!s.includes(e.tagName.toLowerCase())&&!e.classList.contains("select-none"));if(t&&d.includes(t))return t;if(l)return i=[],n=d[0],n;var c,u;u=d,(c=i).length===u.length&&c.every((e,t)=>e===u[t])?a<=d.length&&a++:a=0;return n=d[d.length-1-a],i=d,n},d=(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(t),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)}};function c(e,t){const o=e.getBoundingClientRect(),r=t.getBoundingClientRect(),s=o.top-r.top,i=o.left-r.left,a=n(["zoom","current"])??1;return{top:parseFloat((s/a).toFixed(5)),left:parseFloat((i/a).toFixed(5)),width:Math.max(4,parseFloat((o.width/a).toFixed(5))),height:parseFloat((o.height/a).toFixed(5))}}const u=(e,t)=>{const n=document.createElement("div");n.className="node-tools",t.appendChild(n),((e,t)=>{const n=document.createElement("div");n.className="tag-label",n.textContent=e.tagName.toLowerCase(),t.appendChild(n)})(e,n)},m=(e,t)=>{if(!e)return;const r=o(t);r&&r.remove();const s=((e,t)=>{const{top:o,left:r,width:s,height:i}=c(e,t),a=n(["zoom","current"])??1;document.body.style.setProperty("--zoom",a.toString()),document.body.style.setProperty("--stroke-width",(2/a).toFixed(3));const l=document.createElement("div");l.classList.add("highlight-frame"),l.style.setProperty("--frame-top",`${o}px`),l.style.setProperty("--frame-left",`${r}px`),l.style.setProperty("--frame-width",`${s}px`),l.style.setProperty("--frame-height",`${i}px`);const d=document.createElementNS("http://www.w3.org/2000/svg","svg");d.classList.add("highlight-frame-svg");const u=document.createElementNS("http://www.w3.org/2000/svg","rect");return u.setAttribute("x","0"),u.setAttribute("y","0"),u.setAttribute("width","100%"),u.setAttribute("height","100%"),u.classList.add("highlight-frame-rect"),d.appendChild(u),l.appendChild(d),l})(e,t);"true"===e.contentEditable&&s.classList.add("is-editable"),u(e,s),t.appendChild(s)},p=(e,t)=>{const r=o(t),s=n(["zoom","current"])??1;if(!r)return;s>=.3?t.style.setProperty("--tool-opacity","1"):t.style.setProperty("--tool-opacity","0");const{top:i,left:a,width:l,height:d}=c(e,t);r.style.setProperty("--frame-top",`${i}px`),r.style.setProperty("--frame-left",`${a}px`),r.style.setProperty("--frame-width",`${l}px`),r.style.setProperty("--frame-height",`${d}px`)},v=(e,t)=>{const n=o(t);if(!n)return;const r=e.classList.contains("hidden")||e.classList.contains("select-none")?"none":"";n.style.display=r;const s=n.querySelector(".tag-label");s&&(s.style.display=r)},h=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)}},y=(e,t)=>{const n=((e,t)=>{const n=new MutationObserver(e=>{t(e)});return n.observe(e,{subtree:!0,childList:!0,characterData:!0}),n})(e,()=>{p(e,t)});return()=>n.disconnect()},f=()=>{let e=null,t=!1,o=null;const r=()=>{if(t||!e)return;t=!0;var r;(r=e).contentEditable="false",r.classList.remove("is-editable"),r.style.outline="none",(()=>{const e=n(["keyboard","disableTextEditMode"]);e?.()})(),o?.(),e=null,t=!1};return{enableEditMode:(t,s)=>{if(e===t)return;e&&e!==t&&r();const i=(e=>Array.from(e.childNodes).some(e=>e.nodeType===Node.TEXT_NODE&&e.textContent?.trim()))(t);i&&(e=t,(e=>{e.contentEditable="true",e.classList.add("is-editable"),e.style.outline="none"})(t),(()=>{const e=n(["keyboard","enableTextEditMode"]);e?.()})(),o=((e,t,n)=>{if(!t)return()=>{};e.addEventListener("blur",n);const o=h(e),r=y(e,t);return()=>{e.removeEventListener("blur",n),o(),r?.()}})(t,s,r))},blurEditMode:r,getEditableNode:()=>e,isEditing:()=>null!==e}},b=320,g=1680,w=[{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"}],E=(e,t,n)=>{const o=parseFloat(document.body.dataset.zoom||"1"),r=((e,t)=>{const n=e+Math.round(t);return Math.max(b,Math.min(g,n))})(n,(e.clientX-t)/o);return r},L=(e,t)=>{e.style.setProperty("--container-width",`${t}px`),((e,t)=>{e.querySelectorAll(".resize-preset-button").forEach((e,n)=>{n<w.length&&(w[n].rawValue===t?e.classList.add("is-active"):e.classList.remove("is-active"))})})(e,t)};e.createCanvasObserver=function(){const e=document.querySelector(".transform-layer");if(!e)return{disconnect:()=>{}};const o=t(()=>{(()=>{const e=n(["zoom","current"]);document.body.style.setProperty("--zoom",e.toFixed(5)),document.body.style.setProperty("--stroke-width",(2/e).toFixed(3)),document.body.dataset.zoom=e.toFixed(5),document.body.dataset.strokeWidth=(2/e).toFixed(3)})()}),r=new MutationObserver(()=>{o()});return r.observe(e,{attributes:!0,attributeOldValue:!0,subtree:!0,childList:!0}),{disconnect:function(){o.cleanup(),r.disconnect()}}},e.createNodeTools=e=>{const n=e;let o=null,s=null,i=null,a=null;const l=f(),c=t(p),u=e=>{if(a!==e){if(l.isEditing()){const t=l.getEditableNode();t&&t!==e&&l.blurEditMode()}if(o?.disconnect(),s?.disconnect(),i?.disconnect(),e&&n){l.enableEditMode(e,n),o=((e,t)=>{const n=new ResizeObserver(e=>{t(e)});return n.observe(e),n})(n,()=>{c(e,n)}),s=new MutationObserver(()=>{c(e,n),v(e,n)}),s.observe(e,{attributes:!0,subtree:!0,childList:!0,characterData:!0});const t=e.parentElement;t&&(i=new MutationObserver(()=>{c(e,n),v(e,n)}),i.observe(t,{childList:!0,subtree:!0}))}var t,r;a=e,t="selectedNodeChanged",r=e?.getAttribute("data-node-id")??null,window.parent.postMessage({source:"node-edit-utils",action:t,data:r,timestamp:Date.now()},"*"),m(e,n),e&&n&&v(e,n)}},h=d(n,u,()=>{l.isEditing()&&l.blurEditMode(),a&&n&&(r(n),a=null,o?.disconnect(),s?.disconnect(),i?.disconnect())},l.getEditableNode),y={selectNode:u,getSelectedNode:()=>a,refreshHighlightFrame:()=>{c(a,n)},clearSelectedNode:()=>{r(n),a=null,o?.disconnect(),s?.disconnect(),i?.disconnect()},getEditableNode:()=>l.getEditableNode(),cleanup:()=>{h(),o?.disconnect(),s?.disconnect(),i?.disconnect(),l.blurEditMode(),c.cleanup()}};var b,g;return b="nodeTools",g=y,"undefined"!=typeof window&&(window[b]=g),y},e.createViewport=e=>{const n=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",w.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,L);let s=!1,i=0,a=0;const l=t(t=>{if(!s)return;n&&(n.style.cursor="ew-resize");const o=E(t,i,a);L(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(),n&&(n.style.cursor="default"),s=!1},()=>{s=!1});return{setWidth:t=>{L(e,t)},cleanup:()=>{s=!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.1.4",
3
+ "version": "2.1.6",
4
4
  "description": "Utilities for editing nodes in a dom tree.",
5
5
  "type": "module",
6
6
  "main": "dist/node-edit-utils.cjs.js",
@@ -15,6 +15,7 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
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();
@@ -32,6 +33,7 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
32
33
 
33
34
  resizeObserver?.disconnect();
34
35
  mutationObserver?.disconnect();
36
+ parentMutationObserver?.disconnect();
35
37
  }
36
38
  }
37
39
  };
@@ -50,6 +52,7 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
50
52
 
51
53
  resizeObserver?.disconnect();
52
54
  mutationObserver?.disconnect();
55
+ parentMutationObserver?.disconnect();
53
56
 
54
57
  if (node && nodeProvider) {
55
58
  text.enableEditMode(node, nodeProvider);
@@ -65,8 +68,24 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
65
68
 
66
69
  mutationObserver.observe(node, {
67
70
  attributes: true,
68
- attributeFilter: ["class"],
71
+ subtree: true,
72
+ childList: true,
73
+ characterData: true,
69
74
  });
75
+
76
+ const parent = node.parentElement;
77
+
78
+ if (parent) {
79
+ parentMutationObserver = new MutationObserver(() => {
80
+ throttledFrameRefresh(node, nodeProvider);
81
+ updateHighlightFrameVisibility(node, nodeProvider);
82
+ });
83
+
84
+ parentMutationObserver.observe(parent, {
85
+ childList: true,
86
+ subtree: true,
87
+ });
88
+ }
70
89
  }
71
90
 
72
91
  selectedNode = node;
@@ -85,6 +104,7 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
85
104
  removeListeners();
86
105
  resizeObserver?.disconnect();
87
106
  mutationObserver?.disconnect();
107
+ parentMutationObserver?.disconnect();
88
108
 
89
109
  text.blurEditMode();
90
110
  throttledFrameRefresh.cleanup();
@@ -101,6 +121,7 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
101
121
  selectedNode = null;
102
122
  resizeObserver?.disconnect();
103
123
  mutationObserver?.disconnect();
124
+ parentMutationObserver?.disconnect();
104
125
  },
105
126
  getEditableNode: () => text.getEditableNode(),
106
127
  cleanup,
@@ -5,5 +5,12 @@ export const updateHighlightFrameVisibility = (node: HTMLElement, nodeProvider:
5
5
  if (!frame) return;
6
6
 
7
7
  const hasHiddenClass = node.classList.contains("hidden") || node.classList.contains("select-none");
8
- frame.style.display = hasHiddenClass ? "none" : "";
8
+ const displayValue = hasHiddenClass ? "none" : "";
9
+
10
+ frame.style.display = displayValue;
11
+
12
+ const tagLabel = frame.querySelector(".tag-label") as HTMLElement | null;
13
+ if (tagLabel) {
14
+ tagLabel.style.display = displayValue;
15
+ }
9
16
  };