@node-edit-utils/core 2.1.1 → 2.1.3

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.1
4
+ * @version 2.1.3
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,14 +318,14 @@ const updateHighlightFrameVisibility = (node, nodeProvider) => {
328
318
  frame.style.display = hasHiddenClass ? "none" : "";
329
319
  };
330
320
 
331
- const disableCanvasKeyboard = () => {
332
- const disable = getCanvasWindowValue(["keyboard", "disable"]);
333
- disable?.();
321
+ const disableCanvasTextMode = () => {
322
+ const disableTextEditMode = getCanvasWindowValue(["keyboard", "disableTextEditMode"]);
323
+ disableTextEditMode?.();
334
324
  };
335
325
 
336
- const enableCanvasKeyboard = () => {
337
- const enable = getCanvasWindowValue(["keyboard", "enable"]);
338
- enable?.();
326
+ const enableCanvasTextMode = () => {
327
+ const enableTextEditMode = getCanvasWindowValue(["keyboard", "enableTextEditMode"]);
328
+ enableTextEditMode?.();
339
329
  };
340
330
 
341
331
  const insertLineBreak = () => {
@@ -431,7 +421,7 @@ const nodeText = () => {
431
421
  if (editable) {
432
422
  editableNode = node;
433
423
  makeNodeEditable(node);
434
- disableCanvasKeyboard();
424
+ enableCanvasTextMode();
435
425
  cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
436
426
  }
437
427
  };
@@ -448,7 +438,7 @@ const nodeText = () => {
448
438
  blurInProgress = true;
449
439
  const nodeToCleanup = editableNode;
450
440
  makeNodeNonEditable(nodeToCleanup);
451
- enableCanvasKeyboard();
441
+ disableCanvasTextMode();
452
442
  cleanup?.();
453
443
  editableNode = null;
454
444
  blurInProgress = false;
@@ -485,7 +475,6 @@ const createNodeTools = (element) => {
485
475
  if (selectedNode === node) {
486
476
  return;
487
477
  }
488
- selectedNode = node;
489
478
  if (text.isEditing()) {
490
479
  const currentEditable = text.getEditableNode();
491
480
  if (currentEditable && currentEditable !== node) {
@@ -508,6 +497,7 @@ const createNodeTools = (element) => {
508
497
  attributeFilter: ["class"],
509
498
  });
510
499
  }
500
+ selectedNode = node;
511
501
  sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
512
502
  highlightNode(node, nodeProvider) ?? null;
513
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.1
4
+ * @version 2.1.3
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,14 +316,14 @@ const updateHighlightFrameVisibility = (node, nodeProvider) => {
326
316
  frame.style.display = hasHiddenClass ? "none" : "";
327
317
  };
328
318
 
329
- const disableCanvasKeyboard = () => {
330
- const disable = getCanvasWindowValue(["keyboard", "disable"]);
331
- disable?.();
319
+ const disableCanvasTextMode = () => {
320
+ const disableTextEditMode = getCanvasWindowValue(["keyboard", "disableTextEditMode"]);
321
+ disableTextEditMode?.();
332
322
  };
333
323
 
334
- const enableCanvasKeyboard = () => {
335
- const enable = getCanvasWindowValue(["keyboard", "enable"]);
336
- enable?.();
324
+ const enableCanvasTextMode = () => {
325
+ const enableTextEditMode = getCanvasWindowValue(["keyboard", "enableTextEditMode"]);
326
+ enableTextEditMode?.();
337
327
  };
338
328
 
339
329
  const insertLineBreak = () => {
@@ -429,7 +419,7 @@ const nodeText = () => {
429
419
  if (editable) {
430
420
  editableNode = node;
431
421
  makeNodeEditable(node);
432
- disableCanvasKeyboard();
422
+ enableCanvasTextMode();
433
423
  cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
434
424
  }
435
425
  };
@@ -446,7 +436,7 @@ const nodeText = () => {
446
436
  blurInProgress = true;
447
437
  const nodeToCleanup = editableNode;
448
438
  makeNodeNonEditable(nodeToCleanup);
449
- enableCanvasKeyboard();
439
+ disableCanvasTextMode();
450
440
  cleanup?.();
451
441
  editableNode = null;
452
442
  blurInProgress = false;
@@ -483,7 +473,6 @@ const createNodeTools = (element) => {
483
473
  if (selectedNode === node) {
484
474
  return;
485
475
  }
486
- selectedNode = node;
487
476
  if (text.isEditing()) {
488
477
  const currentEditable = text.getEditableNode();
489
478
  if (currentEditable && currentEditable !== node) {
@@ -506,6 +495,7 @@ const createNodeTools = (element) => {
506
495
  attributeFilter: ["class"],
507
496
  });
508
497
  }
498
+ selectedNode = node;
509
499
  sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
510
500
  highlightNode(node, nodeProvider) ?? null;
511
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.1
4
+ * @version 2.1.3
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,14 +322,14 @@
332
322
  frame.style.display = hasHiddenClass ? "none" : "";
333
323
  };
334
324
 
335
- const disableCanvasKeyboard = () => {
336
- const disable = getCanvasWindowValue(["keyboard", "disable"]);
337
- disable?.();
325
+ const disableCanvasTextMode = () => {
326
+ const disableTextEditMode = getCanvasWindowValue(["keyboard", "disableTextEditMode"]);
327
+ disableTextEditMode?.();
338
328
  };
339
329
 
340
- const enableCanvasKeyboard = () => {
341
- const enable = getCanvasWindowValue(["keyboard", "enable"]);
342
- enable?.();
330
+ const enableCanvasTextMode = () => {
331
+ const enableTextEditMode = getCanvasWindowValue(["keyboard", "enableTextEditMode"]);
332
+ enableTextEditMode?.();
343
333
  };
344
334
 
345
335
  const insertLineBreak = () => {
@@ -435,7 +425,7 @@
435
425
  if (editable) {
436
426
  editableNode = node;
437
427
  makeNodeEditable(node);
438
- disableCanvasKeyboard();
428
+ enableCanvasTextMode();
439
429
  cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
440
430
  }
441
431
  };
@@ -452,7 +442,7 @@
452
442
  blurInProgress = true;
453
443
  const nodeToCleanup = editableNode;
454
444
  makeNodeNonEditable(nodeToCleanup);
455
- enableCanvasKeyboard();
445
+ disableCanvasTextMode();
456
446
  cleanup?.();
457
447
  editableNode = null;
458
448
  blurInProgress = false;
@@ -489,7 +479,6 @@
489
479
  if (selectedNode === node) {
490
480
  return;
491
481
  }
492
- selectedNode = node;
493
482
  if (text.isEditing()) {
494
483
  const currentEditable = text.getEditableNode();
495
484
  if (currentEditable && currentEditable !== node) {
@@ -512,6 +501,7 @@
512
501
  attributeFilter: ["class"],
513
502
  });
514
503
  }
504
+ selectedNode = node;
515
505
  sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
516
506
  highlightNode(node, nodeProvider) ?? null;
517
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,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=f(e),r=y(e,t);return()=>{e.removeEventListener("blur",n),o(),r?.()}})(t,s,r))},blurEditMode:r,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 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.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","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}},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(),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,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 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()}}}});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-edit-utils/core",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
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,5 +1,5 @@
1
- import { disableCanvasKeyboard } from "../../canvas/disableCanvasKeyboard";
2
- import { enableCanvasKeyboard } from "../../canvas/enableCanvasKeyboard";
1
+ import { disableCanvasTextMode } from "@/lib/canvas/disableCanvasTextMode";
2
+ import { enableCanvasTextMode } from "@/lib/canvas/enableCanvasTextMode";
3
3
  import { setupNodeListeners } from "./events/setupNodeListeners";
4
4
  import { hasTextContent } from "./helpers/hasTextContent";
5
5
  import { makeNodeEditable } from "./helpers/makeNodeEditable";
@@ -26,7 +26,7 @@ export const nodeText = (): NodeText => {
26
26
  editableNode = node;
27
27
 
28
28
  makeNodeEditable(node);
29
- disableCanvasKeyboard();
29
+ enableCanvasTextMode();
30
30
 
31
31
  cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
32
32
  }
@@ -50,7 +50,7 @@ export const nodeText = (): NodeText => {
50
50
  const nodeToCleanup = editableNode;
51
51
 
52
52
  makeNodeNonEditable(nodeToCleanup);
53
- enableCanvasKeyboard();
53
+ disableCanvasTextMode();
54
54
  cleanup?.();
55
55
 
56
56
  editableNode = null;