@node-edit-utils/core 2.1.0 → 2.1.2

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.0
4
+ * @version 2.1.2
5
5
  */
6
6
  'use strict';
7
7
 
@@ -161,19 +161,13 @@ const selectNode = (event, editableNode) => {
161
161
  const clickX = event.clientX;
162
162
  const clickY = event.clientY;
163
163
  const clickThrough = event.metaKey || event.ctrlKey;
164
- const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()));
164
+ const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()) && !element.classList.contains("select-none"));
165
165
  if (editableNode && candidates.includes(editableNode)) {
166
- if (isLocked(editableNode)) {
167
- return null;
168
- }
169
166
  return editableNode;
170
167
  }
171
168
  if (clickThrough) {
172
169
  candidateCache = [];
173
170
  selectedNode = candidates[0];
174
- if (isLocked(selectedNode)) {
175
- return null;
176
- }
177
171
  return selectedNode;
178
172
  }
179
173
  if (targetSameCandidates(candidateCache, candidates)) {
@@ -185,9 +179,6 @@ const selectNode = (event, editableNode) => {
185
179
  const nodeIndex = candidates.length - 1 - attempt;
186
180
  selectedNode = candidates[nodeIndex];
187
181
  candidateCache = candidates;
188
- if (isLocked(selectedNode)) {
189
- return null;
190
- }
191
182
  return selectedNode;
192
183
  };
193
184
 
@@ -211,7 +202,6 @@ const setupEventListener$1 = (nodeProvider, onNodeSelected, onEscapePressed, get
211
202
  handleNodeClick(event, nodeProvider, getEditableNode(), onNodeSelected);
212
203
  };
213
204
  const documentKeydownHandler = (event) => {
214
- console.log("Esacpe Handler", event);
215
205
  if (event.key === "Escape") {
216
206
  event.preventDefault();
217
207
  event.stopPropagation();
@@ -328,6 +318,16 @@ const updateHighlightFrameVisibility = (node, nodeProvider) => {
328
318
  frame.style.display = hasHiddenClass ? "none" : "";
329
319
  };
330
320
 
321
+ const disableCanvasKeyboard = () => {
322
+ const disable = getCanvasWindowValue(["keyboard", "disable"]);
323
+ disable?.();
324
+ };
325
+
326
+ const enableCanvasKeyboard = () => {
327
+ const enable = getCanvasWindowValue(["keyboard", "enable"]);
328
+ enable?.();
329
+ };
330
+
331
331
  const insertLineBreak = () => {
332
332
  const selection = window.getSelection();
333
333
  if (selection && selection.rangeCount > 0) {
@@ -421,7 +421,7 @@ const nodeText = () => {
421
421
  if (editable) {
422
422
  editableNode = node;
423
423
  makeNodeEditable(node);
424
- //enableCanvasTextMode();
424
+ disableCanvasKeyboard();
425
425
  cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
426
426
  }
427
427
  };
@@ -438,7 +438,7 @@ const nodeText = () => {
438
438
  blurInProgress = true;
439
439
  const nodeToCleanup = editableNode;
440
440
  makeNodeNonEditable(nodeToCleanup);
441
- //disableCanvasTextMode();
441
+ enableCanvasKeyboard();
442
442
  cleanup?.();
443
443
  editableNode = null;
444
444
  blurInProgress = false;
@@ -475,7 +475,6 @@ const createNodeTools = (element) => {
475
475
  if (selectedNode === node) {
476
476
  return;
477
477
  }
478
- selectedNode = node;
479
478
  if (text.isEditing()) {
480
479
  const currentEditable = text.getEditableNode();
481
480
  if (currentEditable && currentEditable !== node) {
@@ -498,6 +497,7 @@ const createNodeTools = (element) => {
498
497
  attributeFilter: ["class"],
499
498
  });
500
499
  }
500
+ selectedNode = node;
501
501
  sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
502
502
  highlightNode(node, nodeProvider) ?? null;
503
503
  if (node && nodeProvider) {
@@ -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.0
4
+ * @version 2.1.2
5
5
  */
6
6
  // biome-ignore lint/suspicious/noExplicitAny: generic constraint requires flexibility
7
7
  function withRAFThrottle(func) {
@@ -159,19 +159,13 @@ const selectNode = (event, editableNode) => {
159
159
  const clickX = event.clientX;
160
160
  const clickY = event.clientY;
161
161
  const clickThrough = event.metaKey || event.ctrlKey;
162
- const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()));
162
+ const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()) && !element.classList.contains("select-none"));
163
163
  if (editableNode && candidates.includes(editableNode)) {
164
- if (isLocked(editableNode)) {
165
- return null;
166
- }
167
164
  return editableNode;
168
165
  }
169
166
  if (clickThrough) {
170
167
  candidateCache = [];
171
168
  selectedNode = candidates[0];
172
- if (isLocked(selectedNode)) {
173
- return null;
174
- }
175
169
  return selectedNode;
176
170
  }
177
171
  if (targetSameCandidates(candidateCache, candidates)) {
@@ -183,9 +177,6 @@ const selectNode = (event, editableNode) => {
183
177
  const nodeIndex = candidates.length - 1 - attempt;
184
178
  selectedNode = candidates[nodeIndex];
185
179
  candidateCache = candidates;
186
- if (isLocked(selectedNode)) {
187
- return null;
188
- }
189
180
  return selectedNode;
190
181
  };
191
182
 
@@ -209,7 +200,6 @@ const setupEventListener$1 = (nodeProvider, onNodeSelected, onEscapePressed, get
209
200
  handleNodeClick(event, nodeProvider, getEditableNode(), onNodeSelected);
210
201
  };
211
202
  const documentKeydownHandler = (event) => {
212
- console.log("Esacpe Handler", event);
213
203
  if (event.key === "Escape") {
214
204
  event.preventDefault();
215
205
  event.stopPropagation();
@@ -326,6 +316,16 @@ const updateHighlightFrameVisibility = (node, nodeProvider) => {
326
316
  frame.style.display = hasHiddenClass ? "none" : "";
327
317
  };
328
318
 
319
+ const disableCanvasKeyboard = () => {
320
+ const disable = getCanvasWindowValue(["keyboard", "disable"]);
321
+ disable?.();
322
+ };
323
+
324
+ const enableCanvasKeyboard = () => {
325
+ const enable = getCanvasWindowValue(["keyboard", "enable"]);
326
+ enable?.();
327
+ };
328
+
329
329
  const insertLineBreak = () => {
330
330
  const selection = window.getSelection();
331
331
  if (selection && selection.rangeCount > 0) {
@@ -419,7 +419,7 @@ const nodeText = () => {
419
419
  if (editable) {
420
420
  editableNode = node;
421
421
  makeNodeEditable(node);
422
- //enableCanvasTextMode();
422
+ disableCanvasKeyboard();
423
423
  cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
424
424
  }
425
425
  };
@@ -436,7 +436,7 @@ const nodeText = () => {
436
436
  blurInProgress = true;
437
437
  const nodeToCleanup = editableNode;
438
438
  makeNodeNonEditable(nodeToCleanup);
439
- //disableCanvasTextMode();
439
+ enableCanvasKeyboard();
440
440
  cleanup?.();
441
441
  editableNode = null;
442
442
  blurInProgress = false;
@@ -473,7 +473,6 @@ const createNodeTools = (element) => {
473
473
  if (selectedNode === node) {
474
474
  return;
475
475
  }
476
- selectedNode = node;
477
476
  if (text.isEditing()) {
478
477
  const currentEditable = text.getEditableNode();
479
478
  if (currentEditable && currentEditable !== node) {
@@ -496,6 +495,7 @@ const createNodeTools = (element) => {
496
495
  attributeFilter: ["class"],
497
496
  });
498
497
  }
498
+ selectedNode = node;
499
499
  sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
500
500
  highlightNode(node, nodeProvider) ?? null;
501
501
  if (node && nodeProvider) {
@@ -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.0
4
+ * @version 2.1.2
5
5
  */
6
6
  (function (global, factory) {
7
7
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
@@ -165,19 +165,13 @@
165
165
  const clickX = event.clientX;
166
166
  const clickY = event.clientY;
167
167
  const clickThrough = event.metaKey || event.ctrlKey;
168
- const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()));
168
+ const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()) && !element.classList.contains("select-none"));
169
169
  if (editableNode && candidates.includes(editableNode)) {
170
- if (isLocked(editableNode)) {
171
- return null;
172
- }
173
170
  return editableNode;
174
171
  }
175
172
  if (clickThrough) {
176
173
  candidateCache = [];
177
174
  selectedNode = candidates[0];
178
- if (isLocked(selectedNode)) {
179
- return null;
180
- }
181
175
  return selectedNode;
182
176
  }
183
177
  if (targetSameCandidates(candidateCache, candidates)) {
@@ -189,9 +183,6 @@
189
183
  const nodeIndex = candidates.length - 1 - attempt;
190
184
  selectedNode = candidates[nodeIndex];
191
185
  candidateCache = candidates;
192
- if (isLocked(selectedNode)) {
193
- return null;
194
- }
195
186
  return selectedNode;
196
187
  };
197
188
 
@@ -215,7 +206,6 @@
215
206
  handleNodeClick(event, nodeProvider, getEditableNode(), onNodeSelected);
216
207
  };
217
208
  const documentKeydownHandler = (event) => {
218
- console.log("Esacpe Handler", event);
219
209
  if (event.key === "Escape") {
220
210
  event.preventDefault();
221
211
  event.stopPropagation();
@@ -332,6 +322,16 @@
332
322
  frame.style.display = hasHiddenClass ? "none" : "";
333
323
  };
334
324
 
325
+ const disableCanvasKeyboard = () => {
326
+ const disable = getCanvasWindowValue(["keyboard", "disable"]);
327
+ disable?.();
328
+ };
329
+
330
+ const enableCanvasKeyboard = () => {
331
+ const enable = getCanvasWindowValue(["keyboard", "enable"]);
332
+ enable?.();
333
+ };
334
+
335
335
  const insertLineBreak = () => {
336
336
  const selection = window.getSelection();
337
337
  if (selection && selection.rangeCount > 0) {
@@ -425,7 +425,7 @@
425
425
  if (editable) {
426
426
  editableNode = node;
427
427
  makeNodeEditable(node);
428
- //enableCanvasTextMode();
428
+ disableCanvasKeyboard();
429
429
  cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
430
430
  }
431
431
  };
@@ -442,7 +442,7 @@
442
442
  blurInProgress = true;
443
443
  const nodeToCleanup = editableNode;
444
444
  makeNodeNonEditable(nodeToCleanup);
445
- //disableCanvasTextMode();
445
+ enableCanvasKeyboard();
446
446
  cleanup?.();
447
447
  editableNode = null;
448
448
  blurInProgress = false;
@@ -479,7 +479,6 @@
479
479
  if (selectedNode === node) {
480
480
  return;
481
481
  }
482
- selectedNode = node;
483
482
  if (text.isEditing()) {
484
483
  const currentEditable = text.getEditableNode();
485
484
  if (currentEditable && currentEditable !== node) {
@@ -502,6 +501,7 @@
502
501
  attributeFilter: ["class"],
503
502
  });
504
503
  }
504
+ selectedNode = node;
505
505
  sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
506
506
  highlightNode(node, nodeProvider) ?? null;
507
507
  if (node && nodeProvider) {
@@ -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)};const o=e=>e?.classList.contains("select-none")??!1;function r(e){return e.querySelector(".highlight-frame")}const s=e=>{if(!e)return;const t=r(e);t&&t.remove()},a=["path","rect","circle","ellipse","polygon","line","polyline","text","text-noci"];let i=[],l=0;const d=(e,t)=>{let n=null;const r=e.clientX,s=e.clientY,d=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})(r,s).filter(e=>!a.includes(e.tagName.toLowerCase()));if(t&&c.includes(t))return o(t)?null:t;if(d)return i=[],n=c[0],o(n)?null:n;var u,m;m=c,(u=i).length===m.length&&u.every((e,t)=>e===m[t])?l<=c.length&&l++:l=0;return n=c[c.length-1-l],i=c,o(n)?null:n},c=(e,t,n,r)=>{const a=e=>{((e,t)=>{if("application"===e.data.source&&"selectedNodeChanged"===e.data.action){const n=e.data.data,r=document.querySelector(`[data-node-id="${n}"]`);if(o(r))return void t?.(null);r&&t?.(r)}})(e,t)},i=n=>{((e,t,n,o)=>{if(e.preventDefault(),e.stopPropagation(),t&&!t.contains(e.target))return s(t),void o(null);o(d(e,n))})(n,e,r(),t)},l=e=>{console.log("Esacpe Handler",e),"Escape"===e.key&&(e.preventDefault(),e.stopPropagation(),n?.())};return window.addEventListener("message",a),document.addEventListener("click",i),document.addEventListener("keydown",l),()=>{window.removeEventListener("message",a),document.removeEventListener("click",i),document.removeEventListener("keydown",l)}};function u(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 m=(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)},p=(e,t)=>{if(!e)return;const o=r(t);o&&o.remove();const s=((e,t)=>{const{top:o,left:r,width:s,height:a}=u(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 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",`${a}px`);const d=document.createElementNS("http://www.w3.org/2000/svg","svg");d.classList.add("highlight-frame-svg");const c=document.createElementNS("http://www.w3.org/2000/svg","rect");return c.setAttribute("x","0"),c.setAttribute("y","0"),c.setAttribute("width","100%"),c.setAttribute("height","100%"),c.classList.add("highlight-frame-rect"),d.appendChild(c),l.appendChild(d),l})(e,t);"true"===e.contentEditable&&s.classList.add("is-editable"),m(e,s),t.appendChild(s)},v=(e,t)=>{const o=r(t),s=n(["zoom","current"])??1;if(!o)return;s>=.3?t.style.setProperty("--tool-opacity","1"):t.style.setProperty("--tool-opacity","0");const{top:a,left:i,width:l,height:d}=u(e,t);o.style.setProperty("--frame-top",`${a}px`),o.style.setProperty("--frame-left",`${i}px`),o.style.setProperty("--frame-width",`${l}px`),o.style.setProperty("--frame-height",`${d}px`)},h=(e,t)=>{const n=r(t);if(!n)return;const o=e.className,s=/\bhidden\b/.test(o)||e.classList.contains("select-none");n.style.display=s?"none":""},f=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,()=>{v(e,t)});return()=>n.disconnect()},g=()=>{let e=null,t=!1,n=null;const o=()=>{if(t||!e)return;t=!0;var o;(o=e).contentEditable="false",o.classList.remove("is-editable"),o.style.outline="none",n?.(),e=null,t=!1};return{enableEditMode:(t,r)=>{if(e===t)return;e&&e!==t&&o();const s=(e=>Array.from(e.childNodes).some(e=>e.nodeType===Node.TEXT_NODE&&e.textContent?.trim()))(t);s&&(e=t,(e=>{e.contentEditable="true",e.classList.add("is-editable"),e.style.outline="none"})(t),n=((e,t,n)=>{if(!t)return()=>{};e.addEventListener("blur",n);const o=f(e),r=y(e,t);return()=>{e.removeEventListener("blur",n),o(),r?.()}})(t,r,o))},blurEditMode:o,getEditableNode:()=>e,isEditing:()=>null!==e}},b=320,w=1680,E=[{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(b,Math.min(w,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<E.length&&(E[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,r=null,a=null;const i=g(),l=t(v),d=e=>{if(a!==e){if(a=e,i.isEditing()){const t=i.getEditableNode();t&&t!==e&&i.blurEditMode()}var t,s;o?.disconnect(),r?.disconnect(),e&&n&&(i.enableEditMode(e,n),o=((e,t)=>{const n=new ResizeObserver(e=>{t(e)});return n.observe(e),n})(n,()=>{l(e,n)}),r=new MutationObserver(()=>{l(e,n),h(e,n)}),r.observe(e,{attributes:!0,attributeFilter:["class"]})),t="selectedNodeChanged",s=e?.getAttribute("data-node-id")??null,window.parent.postMessage({source:"node-edit-utils",action:t,data:s,timestamp:Date.now()},"*"),p(e,n),e&&n&&h(e,n)}},u=c(n,d,()=>{i.isEditing()&&i.blurEditMode(),a&&n&&(s(n),a=null,o?.disconnect(),r?.disconnect())},i.getEditableNode),m={selectNode:d,getSelectedNode:()=>a,refreshHighlightFrame:()=>{l(a,n)},clearSelectedNode:()=>{s(n),a=null,o?.disconnect(),r?.disconnect()},getEditableNode:()=>i.getEditableNode(),cleanup:()=>{u(),o?.disconnect(),r?.disconnect(),i.blurEditMode(),l.cleanup()}};var f,y;return f="nodeTools",y=m,"undefined"!=typeof window&&(window[f]=y),m},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",E.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,a=0,i=0;const l=t(t=>{if(!s)return;n&&(n.style.cursor="ew-resize");const o=x(t,a,i);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,a=t.clientX,i=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()}}}});
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 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 a=[],n=d[0],n;var c,u;u=d,(c=a).length===u.length&&c.every((e,t)=>e===u[t])?i<=d.length&&i++:i=0;return n=d[d.length-1-i],a=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)},a=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)},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 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",`${a}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:a,left:i,width:l,height:d}=c(e,t);r.style.setProperty("--frame-top",`${a}px`),r.style.setProperty("--frame-left",`${i}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.className,s=/\bhidden\b/.test(r)||e.classList.contains("select-none");n.style.display=s?"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","enable"]);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","disable"]);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}},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},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(),l=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,()=>{l(e,n)}),s=new MutationObserver(()=>{l(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=d(n,c,()=>{i.isEditing()&&i.blurEditMode(),a&&n&&(r(n),a=null,o?.disconnect(),s?.disconnect())},i.getEditableNode),h={selectNode:c,getSelectedNode:()=>a,refreshHighlightFrame:()=>{l(a,n)},clearSelectedNode:()=>{r(n),a=null,o?.disconnect(),s?.disconnect()},getEditableNode:()=>i.getEditableNode(),cleanup:()=>{u(),o?.disconnect(),s?.disconnect(),i.blurEditMode(),l.cleanup()}};var f,b;return f="nodeTools",b=h,"undefined"!=typeof window&&(window[f]=b),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 l=t(t=>{if(!s)return;n&&(n.style.cursor="ew-resize");const o=E(t,a,i);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,a=t.clientX,i=e.offsetWidth},l,e=>{e.preventDefault(),e.stopPropagation(),n&&(n.style.cursor="default"),s=!1},()=>{s=!1});return{setWidth:t=>{x(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.0",
3
+ "version": "2.1.2",
4
4
  "description": "Utilities for editing nodes in a dom tree.",
5
5
  "type": "module",
6
6
  "main": "dist/node-edit-utils.cjs.js",
@@ -41,8 +41,6 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
41
41
  return;
42
42
  }
43
43
 
44
- selectedNode = node;
45
-
46
44
  if (text.isEditing()) {
47
45
  const currentEditable = text.getEditableNode();
48
46
  if (currentEditable && currentEditable !== node) {
@@ -71,6 +69,7 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
71
69
  });
72
70
  }
73
71
 
72
+ selectedNode = node;
74
73
  sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
75
74
  highlightNode(node, nodeProvider as HTMLElement) ?? null;
76
75
 
@@ -16,12 +16,9 @@ export const setupEventListener = (
16
16
  };
17
17
 
18
18
  const documentKeydownHandler = (event: KeyboardEvent) => {
19
- console.log("Esacpe Handler", event);
20
-
21
19
  if (event.key === "Escape") {
22
20
  event.preventDefault();
23
21
  event.stopPropagation();
24
-
25
22
  onEscapePressed?.();
26
23
  }
27
24
  };
@@ -1,6 +1,5 @@
1
1
  import { IGNORED_DOM_ELEMENTS } from "./constants";
2
2
  import { getElementsFromPoint } from "./helpers/getElementsFromPoint";
3
- import { isLocked } from "./helpers/isLocked";
4
3
  import { targetSameCandidates } from "./helpers/targetSameCandidates";
5
4
 
6
5
  let candidateCache: Element[] = [];
@@ -15,13 +14,10 @@ export const selectNode = (event: MouseEvent, editableNode: HTMLElement | null):
15
14
  const clickThrough = event.metaKey || event.ctrlKey;
16
15
 
17
16
  const candidates = getElementsFromPoint(clickX, clickY).filter(
18
- (element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase())
17
+ (element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()) && !element.classList.contains("select-none")
19
18
  );
20
19
 
21
20
  if (editableNode && candidates.includes(editableNode)) {
22
- if (isLocked(editableNode)) {
23
- return null;
24
- }
25
21
  return editableNode;
26
22
  }
27
23
 
@@ -29,9 +25,6 @@ export const selectNode = (event: MouseEvent, editableNode: HTMLElement | null):
29
25
  candidateCache = [];
30
26
 
31
27
  selectedNode = candidates[0] as HTMLElement;
32
- if (isLocked(selectedNode)) {
33
- return null;
34
- }
35
28
  return selectedNode;
36
29
  }
37
30
 
@@ -47,9 +40,5 @@ export const selectNode = (event: MouseEvent, editableNode: HTMLElement | null):
47
40
 
48
41
  candidateCache = candidates;
49
42
 
50
- if (isLocked(selectedNode)) {
51
- return null;
52
- }
53
-
54
43
  return selectedNode;
55
44
  };
@@ -1,3 +1,5 @@
1
+ import { disableCanvasKeyboard } from "../../canvas/disableCanvasKeyboard";
2
+ import { enableCanvasKeyboard } from "../../canvas/enableCanvasKeyboard";
1
3
  import { setupNodeListeners } from "./events/setupNodeListeners";
2
4
  import { hasTextContent } from "./helpers/hasTextContent";
3
5
  import { makeNodeEditable } from "./helpers/makeNodeEditable";
@@ -24,7 +26,7 @@ export const nodeText = (): NodeText => {
24
26
  editableNode = node;
25
27
 
26
28
  makeNodeEditable(node);
27
- //enableCanvasTextMode();
29
+ disableCanvasKeyboard();
28
30
 
29
31
  cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
30
32
  }
@@ -48,7 +50,7 @@ export const nodeText = (): NodeText => {
48
50
  const nodeToCleanup = editableNode;
49
51
 
50
52
  makeNodeNonEditable(nodeToCleanup);
51
- //disableCanvasTextMode();
53
+ enableCanvasKeyboard();
52
54
  cleanup?.();
53
55
 
54
56
  editableNode = null;