@node-edit-utils/core 2.0.6 → 2.0.8
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.
- package/dist/lib/canvas/disableCanvasTextMode.d.ts +1 -0
- package/dist/lib/canvas/enableCanvasTextMode.d.ts +1 -0
- package/dist/node-edit-utils.cjs.js +12 -16
- package/dist/node-edit-utils.esm.js +12 -16
- package/dist/node-edit-utils.umd.js +12 -16
- package/dist/node-edit-utils.umd.min.js +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/lib/canvas/disableCanvasTextMode.ts +7 -0
- package/src/lib/canvas/enableCanvasTextMode.ts +7 -0
- package/src/lib/node-tools/createNodeTools.ts +2 -1
- package/src/lib/node-tools/events/setupEventListener.ts +3 -0
- package/src/lib/node-tools/text/nodeText.ts +4 -5
- package/src/lib/post-message/processPostMessage.ts +0 -3
- package/src/lib/styles/styles.css +61 -37
- package/src/lib/viewport/resize/updateActivePreset.ts +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const disableCanvasTextMode: () => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const enableCanvasTextMode: () => void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markup Canvas
|
|
3
3
|
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
-
* @version 2.0.
|
|
4
|
+
* @version 2.0.8
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
@@ -100,17 +100,14 @@ const bindToWindow = (key, value) => {
|
|
|
100
100
|
const processPostMessage = (event, onNodeSelected) => {
|
|
101
101
|
if (event.data.source === "markup-canvas" && event.data.canvasName === "canvas") {
|
|
102
102
|
if (event.data.action === "zoom") {
|
|
103
|
-
|
|
104
|
-
console.log("zoom", zoom);
|
|
103
|
+
event.data.data;
|
|
105
104
|
}
|
|
106
105
|
}
|
|
107
106
|
if (event.data.source === "application") {
|
|
108
107
|
if (event.data.action === "selectedNodeChanged") {
|
|
109
108
|
const nodeId = event.data.data;
|
|
110
|
-
console.log("selectedNodeChanged in node-edit-utils", nodeId);
|
|
111
109
|
const selectedNode = document.querySelector(`[data-node-id="${nodeId}"]`);
|
|
112
110
|
if (selectedNode) {
|
|
113
|
-
console.log("selectedNode", selectedNode);
|
|
114
111
|
onNodeSelected?.(selectedNode);
|
|
115
112
|
}
|
|
116
113
|
}
|
|
@@ -197,6 +194,7 @@ const setupEventListener$1 = (nodeProvider, onNodeSelected, onEscapePressed, get
|
|
|
197
194
|
handleNodeClick(event, nodeProvider, getEditableNode(), onNodeSelected);
|
|
198
195
|
};
|
|
199
196
|
const documentKeydownHandler = (event) => {
|
|
197
|
+
console.log("Esacpe Handler", event);
|
|
200
198
|
if (event.key === "Escape") {
|
|
201
199
|
event.preventDefault();
|
|
202
200
|
event.stopPropagation();
|
|
@@ -312,14 +310,14 @@ const updateHighlightFrameVisibility = (node, nodeProvider) => {
|
|
|
312
310
|
frame.style.display = hasHiddenClass ? "none" : "";
|
|
313
311
|
};
|
|
314
312
|
|
|
315
|
-
const
|
|
316
|
-
const
|
|
317
|
-
|
|
313
|
+
const disableCanvasTextMode = () => {
|
|
314
|
+
const disableTextEditMode = getCanvasWindowValue(["keyboard", "disableTextEditMode"]);
|
|
315
|
+
disableTextEditMode?.();
|
|
318
316
|
};
|
|
319
317
|
|
|
320
|
-
const
|
|
321
|
-
const
|
|
322
|
-
|
|
318
|
+
const enableCanvasTextMode = () => {
|
|
319
|
+
const enableTextEditMode = getCanvasWindowValue(["keyboard", "enableTextEditMode"]);
|
|
320
|
+
enableTextEditMode?.();
|
|
323
321
|
};
|
|
324
322
|
|
|
325
323
|
const insertLineBreak = () => {
|
|
@@ -415,7 +413,7 @@ const nodeText = () => {
|
|
|
415
413
|
if (editable) {
|
|
416
414
|
editableNode = node;
|
|
417
415
|
makeNodeEditable(node);
|
|
418
|
-
|
|
416
|
+
enableCanvasTextMode();
|
|
419
417
|
cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
|
|
420
418
|
}
|
|
421
419
|
};
|
|
@@ -432,7 +430,7 @@ const nodeText = () => {
|
|
|
432
430
|
blurInProgress = true;
|
|
433
431
|
const nodeToCleanup = editableNode;
|
|
434
432
|
makeNodeNonEditable(nodeToCleanup);
|
|
435
|
-
|
|
433
|
+
disableCanvasTextMode();
|
|
436
434
|
cleanup?.();
|
|
437
435
|
editableNode = null;
|
|
438
436
|
blurInProgress = false;
|
|
@@ -469,6 +467,7 @@ const createNodeTools = (element) => {
|
|
|
469
467
|
if (selectedNode === node) {
|
|
470
468
|
return;
|
|
471
469
|
}
|
|
470
|
+
selectedNode = node;
|
|
472
471
|
if (text.isEditing()) {
|
|
473
472
|
const currentEditable = text.getEditableNode();
|
|
474
473
|
if (currentEditable && currentEditable !== node) {
|
|
@@ -491,7 +490,6 @@ const createNodeTools = (element) => {
|
|
|
491
490
|
attributeFilter: ["class"],
|
|
492
491
|
});
|
|
493
492
|
}
|
|
494
|
-
selectedNode = node;
|
|
495
493
|
sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
|
|
496
494
|
highlightNode(node, nodeProvider) ?? null;
|
|
497
495
|
if (node && nodeProvider) {
|
|
@@ -612,9 +610,7 @@ const calcWidth = (event, startX, startWidth) => {
|
|
|
612
610
|
};
|
|
613
611
|
|
|
614
612
|
const updateActivePreset = (container, width) => {
|
|
615
|
-
console.log("updateActivePreset", width);
|
|
616
613
|
const presetButtons = container.querySelectorAll(".resize-preset-button");
|
|
617
|
-
console.log("presetButtons", presetButtons);
|
|
618
614
|
presetButtons.forEach((button, index) => {
|
|
619
615
|
if (index < RESIZE_PRESETS.length) {
|
|
620
616
|
const preset = RESIZE_PRESETS[index];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markup Canvas
|
|
3
3
|
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
-
* @version 2.0.
|
|
4
|
+
* @version 2.0.8
|
|
5
5
|
*/
|
|
6
6
|
// biome-ignore lint/suspicious/noExplicitAny: generic constraint requires flexibility
|
|
7
7
|
function withRAFThrottle(func) {
|
|
@@ -98,17 +98,14 @@ const bindToWindow = (key, value) => {
|
|
|
98
98
|
const processPostMessage = (event, onNodeSelected) => {
|
|
99
99
|
if (event.data.source === "markup-canvas" && event.data.canvasName === "canvas") {
|
|
100
100
|
if (event.data.action === "zoom") {
|
|
101
|
-
|
|
102
|
-
console.log("zoom", zoom);
|
|
101
|
+
event.data.data;
|
|
103
102
|
}
|
|
104
103
|
}
|
|
105
104
|
if (event.data.source === "application") {
|
|
106
105
|
if (event.data.action === "selectedNodeChanged") {
|
|
107
106
|
const nodeId = event.data.data;
|
|
108
|
-
console.log("selectedNodeChanged in node-edit-utils", nodeId);
|
|
109
107
|
const selectedNode = document.querySelector(`[data-node-id="${nodeId}"]`);
|
|
110
108
|
if (selectedNode) {
|
|
111
|
-
console.log("selectedNode", selectedNode);
|
|
112
109
|
onNodeSelected?.(selectedNode);
|
|
113
110
|
}
|
|
114
111
|
}
|
|
@@ -195,6 +192,7 @@ const setupEventListener$1 = (nodeProvider, onNodeSelected, onEscapePressed, get
|
|
|
195
192
|
handleNodeClick(event, nodeProvider, getEditableNode(), onNodeSelected);
|
|
196
193
|
};
|
|
197
194
|
const documentKeydownHandler = (event) => {
|
|
195
|
+
console.log("Esacpe Handler", event);
|
|
198
196
|
if (event.key === "Escape") {
|
|
199
197
|
event.preventDefault();
|
|
200
198
|
event.stopPropagation();
|
|
@@ -310,14 +308,14 @@ const updateHighlightFrameVisibility = (node, nodeProvider) => {
|
|
|
310
308
|
frame.style.display = hasHiddenClass ? "none" : "";
|
|
311
309
|
};
|
|
312
310
|
|
|
313
|
-
const
|
|
314
|
-
const
|
|
315
|
-
|
|
311
|
+
const disableCanvasTextMode = () => {
|
|
312
|
+
const disableTextEditMode = getCanvasWindowValue(["keyboard", "disableTextEditMode"]);
|
|
313
|
+
disableTextEditMode?.();
|
|
316
314
|
};
|
|
317
315
|
|
|
318
|
-
const
|
|
319
|
-
const
|
|
320
|
-
|
|
316
|
+
const enableCanvasTextMode = () => {
|
|
317
|
+
const enableTextEditMode = getCanvasWindowValue(["keyboard", "enableTextEditMode"]);
|
|
318
|
+
enableTextEditMode?.();
|
|
321
319
|
};
|
|
322
320
|
|
|
323
321
|
const insertLineBreak = () => {
|
|
@@ -413,7 +411,7 @@ const nodeText = () => {
|
|
|
413
411
|
if (editable) {
|
|
414
412
|
editableNode = node;
|
|
415
413
|
makeNodeEditable(node);
|
|
416
|
-
|
|
414
|
+
enableCanvasTextMode();
|
|
417
415
|
cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
|
|
418
416
|
}
|
|
419
417
|
};
|
|
@@ -430,7 +428,7 @@ const nodeText = () => {
|
|
|
430
428
|
blurInProgress = true;
|
|
431
429
|
const nodeToCleanup = editableNode;
|
|
432
430
|
makeNodeNonEditable(nodeToCleanup);
|
|
433
|
-
|
|
431
|
+
disableCanvasTextMode();
|
|
434
432
|
cleanup?.();
|
|
435
433
|
editableNode = null;
|
|
436
434
|
blurInProgress = false;
|
|
@@ -467,6 +465,7 @@ const createNodeTools = (element) => {
|
|
|
467
465
|
if (selectedNode === node) {
|
|
468
466
|
return;
|
|
469
467
|
}
|
|
468
|
+
selectedNode = node;
|
|
470
469
|
if (text.isEditing()) {
|
|
471
470
|
const currentEditable = text.getEditableNode();
|
|
472
471
|
if (currentEditable && currentEditable !== node) {
|
|
@@ -489,7 +488,6 @@ const createNodeTools = (element) => {
|
|
|
489
488
|
attributeFilter: ["class"],
|
|
490
489
|
});
|
|
491
490
|
}
|
|
492
|
-
selectedNode = node;
|
|
493
491
|
sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
|
|
494
492
|
highlightNode(node, nodeProvider) ?? null;
|
|
495
493
|
if (node && nodeProvider) {
|
|
@@ -610,9 +608,7 @@ const calcWidth = (event, startX, startWidth) => {
|
|
|
610
608
|
};
|
|
611
609
|
|
|
612
610
|
const updateActivePreset = (container, width) => {
|
|
613
|
-
console.log("updateActivePreset", width);
|
|
614
611
|
const presetButtons = container.querySelectorAll(".resize-preset-button");
|
|
615
|
-
console.log("presetButtons", presetButtons);
|
|
616
612
|
presetButtons.forEach((button, index) => {
|
|
617
613
|
if (index < RESIZE_PRESETS.length) {
|
|
618
614
|
const preset = RESIZE_PRESETS[index];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markup Canvas
|
|
3
3
|
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
-
* @version 2.0.
|
|
4
|
+
* @version 2.0.8
|
|
5
5
|
*/
|
|
6
6
|
(function (global, factory) {
|
|
7
7
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
@@ -104,17 +104,14 @@
|
|
|
104
104
|
const processPostMessage = (event, onNodeSelected) => {
|
|
105
105
|
if (event.data.source === "markup-canvas" && event.data.canvasName === "canvas") {
|
|
106
106
|
if (event.data.action === "zoom") {
|
|
107
|
-
|
|
108
|
-
console.log("zoom", zoom);
|
|
107
|
+
event.data.data;
|
|
109
108
|
}
|
|
110
109
|
}
|
|
111
110
|
if (event.data.source === "application") {
|
|
112
111
|
if (event.data.action === "selectedNodeChanged") {
|
|
113
112
|
const nodeId = event.data.data;
|
|
114
|
-
console.log("selectedNodeChanged in node-edit-utils", nodeId);
|
|
115
113
|
const selectedNode = document.querySelector(`[data-node-id="${nodeId}"]`);
|
|
116
114
|
if (selectedNode) {
|
|
117
|
-
console.log("selectedNode", selectedNode);
|
|
118
115
|
onNodeSelected?.(selectedNode);
|
|
119
116
|
}
|
|
120
117
|
}
|
|
@@ -201,6 +198,7 @@
|
|
|
201
198
|
handleNodeClick(event, nodeProvider, getEditableNode(), onNodeSelected);
|
|
202
199
|
};
|
|
203
200
|
const documentKeydownHandler = (event) => {
|
|
201
|
+
console.log("Esacpe Handler", event);
|
|
204
202
|
if (event.key === "Escape") {
|
|
205
203
|
event.preventDefault();
|
|
206
204
|
event.stopPropagation();
|
|
@@ -316,14 +314,14 @@
|
|
|
316
314
|
frame.style.display = hasHiddenClass ? "none" : "";
|
|
317
315
|
};
|
|
318
316
|
|
|
319
|
-
const
|
|
320
|
-
const
|
|
321
|
-
|
|
317
|
+
const disableCanvasTextMode = () => {
|
|
318
|
+
const disableTextEditMode = getCanvasWindowValue(["keyboard", "disableTextEditMode"]);
|
|
319
|
+
disableTextEditMode?.();
|
|
322
320
|
};
|
|
323
321
|
|
|
324
|
-
const
|
|
325
|
-
const
|
|
326
|
-
|
|
322
|
+
const enableCanvasTextMode = () => {
|
|
323
|
+
const enableTextEditMode = getCanvasWindowValue(["keyboard", "enableTextEditMode"]);
|
|
324
|
+
enableTextEditMode?.();
|
|
327
325
|
};
|
|
328
326
|
|
|
329
327
|
const insertLineBreak = () => {
|
|
@@ -419,7 +417,7 @@
|
|
|
419
417
|
if (editable) {
|
|
420
418
|
editableNode = node;
|
|
421
419
|
makeNodeEditable(node);
|
|
422
|
-
|
|
420
|
+
enableCanvasTextMode();
|
|
423
421
|
cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
|
|
424
422
|
}
|
|
425
423
|
};
|
|
@@ -436,7 +434,7 @@
|
|
|
436
434
|
blurInProgress = true;
|
|
437
435
|
const nodeToCleanup = editableNode;
|
|
438
436
|
makeNodeNonEditable(nodeToCleanup);
|
|
439
|
-
|
|
437
|
+
disableCanvasTextMode();
|
|
440
438
|
cleanup?.();
|
|
441
439
|
editableNode = null;
|
|
442
440
|
blurInProgress = false;
|
|
@@ -473,6 +471,7 @@
|
|
|
473
471
|
if (selectedNode === node) {
|
|
474
472
|
return;
|
|
475
473
|
}
|
|
474
|
+
selectedNode = node;
|
|
476
475
|
if (text.isEditing()) {
|
|
477
476
|
const currentEditable = text.getEditableNode();
|
|
478
477
|
if (currentEditable && currentEditable !== node) {
|
|
@@ -495,7 +494,6 @@
|
|
|
495
494
|
attributeFilter: ["class"],
|
|
496
495
|
});
|
|
497
496
|
}
|
|
498
|
-
selectedNode = node;
|
|
499
497
|
sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
|
|
500
498
|
highlightNode(node, nodeProvider) ?? null;
|
|
501
499
|
if (node && nodeProvider) {
|
|
@@ -616,9 +614,7 @@
|
|
|
616
614
|
};
|
|
617
615
|
|
|
618
616
|
const updateActivePreset = (container, width) => {
|
|
619
|
-
console.log("updateActivePreset", width);
|
|
620
617
|
const presetButtons = container.querySelectorAll(".resize-preset-button");
|
|
621
|
-
console.log("presetButtons", presetButtons);
|
|
622
618
|
presetButtons.forEach((button, index) => {
|
|
623
619
|
if (index < RESIZE_PRESETS.length) {
|
|
624
620
|
const preset = RESIZE_PRESETS[index];
|
|
@@ -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
|
|
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("markup-canvas"===e.data.source&&"canvas"===e.data.canvasName&&"zoom"===e.data.action&&e.data.data,"application"===e.data.source&&"selectedNodeChanged"===e.data.action){const n=e.data.data,o=document.querySelector(`[data-node-id="${n}"]`);o&&t?.(o)}})(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=>{console.log("Esacpe Handler",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(a=e,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"]})),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()}}}});
|
package/dist/styles.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.node-provider{::selection{background:transparent}::-moz-selection{background:transparent}::-webkit-selection{background:transparent}}.node-tools{bottom:0;display:flex;gap
|
|
1
|
+
:root{--primary-color:oklch(0.6235 0.22 294);--uncode-color:oklch(45.7% 0.24 277.023);--handle-color:oklch(55.2% 0.016 285.938);--handle-color-transparent:oklch(55.2% 0.016 285.938/0.7);--primary-color-selection:oklch(0.59 0.18 294/0.3);--text-color-white:#fff;--spacing-xs:0.25rem;--spacing-sm:0.375rem;--spacing-md:0.5rem;--spacing-lg:1.25rem;--transition-fast:0.1s ease-in-out;--transition-medium:0.2s ease-in-out;--z-index-high:10000;--z-index-medium:1000;--letter-spacing:0.02em;--font-family-primary:"Manrope",sans-serif}.node-provider{::selection{background:transparent}::-moz-selection{background:transparent}::-webkit-selection{background:transparent}}.node-tools{bottom:0;display:flex;gap:var(--spacing-xs);justify-content:center;left:0;opacity:var(--tool-opacity);padding-top:var(--spacing-xs);position:absolute;top:0;transform:scale(calc(1/var(--zoom))) translate3d(0,100%,0);transform-origin:bottom left;transition:opacity var(--transition-fast);z-index:var(--z-index-high)}.highlight-frame{font-family:var(--font-family-primary);height:var(--frame-height);left:var(--frame-left);letter-spacing:var(--letter-spacing);pointer-events:none;position:absolute;top:var(--frame-top);width:var(--frame-width);z-index:var(--z-index-medium)}.highlight-frame-svg{height:100%;left:0;overflow:visible;position:absolute;top:0;width:100%}.highlight-frame-rect{fill:none;stroke:var(--primary-color);stroke-width:var(--stroke-width)}.tag-label{align-items:center;background-color:var(--primary-color);border-radius:var(--spacing-sm);color:var(--text-color-white);display:flex;font-size:.575rem;font-weight:500;height:1rem;justify-content:center;line-height:1;padding:.5625rem var(--spacing-sm);text-transform:uppercase}.viewport{position:relative;width:var(--container-width)}.resize-handle{align-items:center;cursor:ew-resize;display:flex;height:40px;justify-content:center;opacity:0;pointer-events:auto;position:absolute;right:-12px;top:var(--spacing-lg);transform:scale(calc(1/var(--zoom)));transform-origin:top left;transition:opacity var(--transition-fast),visibility var(--transition-fast);visibility:hidden;width:12px;z-index:var(--z-index-high)}.viewport:hover .resize-handle{opacity:1;visibility:visible}.resize-handle:before{background:var(--handle-color);border-radius:4px;content:"";height:32px;position:relative;right:0;top:0;transition:transform var(--transition-medium);width:3px}.resize-handle:hover:before{transform:scaleY(1.3)}.resize-presets{display:flex;flex-direction:column;font-family:var(--font-family-primary);gap:var(--spacing-xs);left:0;letter-spacing:var(--letter-spacing);opacity:0;padding-left:var(--spacing-lg);position:absolute;top:0;transition:visibility var(--transition-fast),opacity var(--transition-fast);visibility:hidden}.resize-handle:hover .resize-presets{opacity:1;visibility:visible}.resize-preset-button{text-wrap:nowrap;backdrop-filter:blur(8px);background:var(--handle-color-transparent);border:none;border-radius:var(--spacing-md);color:var(--text-color-white);cursor:pointer;font-size:.625rem;padding:var(--spacing-xs) var(--spacing-md);text-align:left;transition:background var(--transition-fast);width:fit-content;&:hover{background:var(--handle-color)}&.is-active{background:var(--uncode-color)}}.is-editable{outline:none;user-select:text;&::selection{background:var(--primary-color-selection)}&::-moz-selection{background:var(--primary-color-selection)}&::-webkit-selection{background:var(--primary-color-selection)}}
|
package/package.json
CHANGED
|
@@ -41,6 +41,8 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
|
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
selectedNode = node;
|
|
45
|
+
|
|
44
46
|
if (text.isEditing()) {
|
|
45
47
|
const currentEditable = text.getEditableNode();
|
|
46
48
|
if (currentEditable && currentEditable !== node) {
|
|
@@ -69,7 +71,6 @@ export const createNodeTools = (element: HTMLElement | null): NodeTools => {
|
|
|
69
71
|
});
|
|
70
72
|
}
|
|
71
73
|
|
|
72
|
-
selectedNode = node;
|
|
73
74
|
sendPostMessage("selectedNodeChanged", node?.getAttribute("data-node-id") ?? null);
|
|
74
75
|
highlightNode(node, nodeProvider as HTMLElement) ?? null;
|
|
75
76
|
|
|
@@ -16,9 +16,12 @@ export const setupEventListener = (
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
const documentKeydownHandler = (event: KeyboardEvent) => {
|
|
19
|
+
console.log("Esacpe Handler", event);
|
|
20
|
+
|
|
19
21
|
if (event.key === "Escape") {
|
|
20
22
|
event.preventDefault();
|
|
21
23
|
event.stopPropagation();
|
|
24
|
+
|
|
22
25
|
onEscapePressed?.();
|
|
23
26
|
}
|
|
24
27
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { disableCanvasTextMode } from "../../canvas/disableCanvasTextMode";
|
|
2
|
+
import { enableCanvasTextMode } from "../../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
|
-
|
|
29
|
+
enableCanvasTextMode();
|
|
30
30
|
|
|
31
31
|
cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
|
|
32
32
|
}
|
|
@@ -50,8 +50,7 @@ export const nodeText = (): NodeText => {
|
|
|
50
50
|
const nodeToCleanup = editableNode;
|
|
51
51
|
|
|
52
52
|
makeNodeNonEditable(nodeToCleanup);
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
disableCanvasTextMode();
|
|
55
54
|
cleanup?.();
|
|
56
55
|
|
|
57
56
|
editableNode = null;
|
|
@@ -2,18 +2,15 @@ export const processPostMessage = (event: MessageEvent, onNodeSelected?: (node:
|
|
|
2
2
|
if (event.data.source === "markup-canvas" && event.data.canvasName === "canvas") {
|
|
3
3
|
if (event.data.action === "zoom") {
|
|
4
4
|
const zoom = event.data.data;
|
|
5
|
-
console.log("zoom", zoom);
|
|
6
5
|
}
|
|
7
6
|
}
|
|
8
7
|
|
|
9
8
|
if (event.data.source === "application") {
|
|
10
9
|
if (event.data.action === "selectedNodeChanged") {
|
|
11
10
|
const nodeId = event.data.data;
|
|
12
|
-
console.log("selectedNodeChanged in node-edit-utils", nodeId);
|
|
13
11
|
const selectedNode = document.querySelector(`[data-node-id="${nodeId}"]`);
|
|
14
12
|
|
|
15
13
|
if (selectedNode) {
|
|
16
|
-
console.log("selectedNode", selectedNode);
|
|
17
14
|
onNodeSelected?.(selectedNode as HTMLElement);
|
|
18
15
|
}
|
|
19
16
|
}
|
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--primary-color: oklch(0.6235 0.22 294);
|
|
3
|
+
--uncode-color: oklch(45.7% 0.24 277.023);
|
|
4
|
+
|
|
5
|
+
--handle-color: oklch(55.2% 0.016 285.938);
|
|
6
|
+
--handle-color-transparent: oklch(55.2% 0.016 285.938 / 0.7);
|
|
7
|
+
--primary-color-selection: oklch(0.59 0.18 294 / 0.3);
|
|
8
|
+
|
|
9
|
+
--text-color-white: white;
|
|
10
|
+
|
|
11
|
+
--spacing-xs: 0.25rem;
|
|
12
|
+
--spacing-sm: 0.375rem;
|
|
13
|
+
--spacing-md: 0.5rem;
|
|
14
|
+
--spacing-lg: 1.25rem;
|
|
15
|
+
|
|
16
|
+
--transition-fast: 0.1s ease-in-out;
|
|
17
|
+
--transition-medium: 0.2s ease-in-out;
|
|
18
|
+
|
|
19
|
+
--z-index-high: 10000;
|
|
20
|
+
--z-index-medium: 1000;
|
|
21
|
+
|
|
22
|
+
--letter-spacing: 0.02em;
|
|
23
|
+
--font-family-primary: "Manrope", sans-serif;
|
|
24
|
+
}
|
|
25
|
+
|
|
1
26
|
.node-provider {
|
|
2
27
|
::selection {
|
|
3
28
|
background: transparent;
|
|
@@ -17,13 +42,13 @@
|
|
|
17
42
|
left: 0;
|
|
18
43
|
bottom: 0;
|
|
19
44
|
top: 0;
|
|
20
|
-
gap:
|
|
21
|
-
z-index:
|
|
45
|
+
gap: var(--spacing-xs);
|
|
46
|
+
z-index: var(--z-index-high);
|
|
22
47
|
transform: scale(calc(1 / var(--zoom))) translate3d(0, 100%, 0);
|
|
23
48
|
transform-origin: bottom left;
|
|
24
|
-
transition: opacity
|
|
49
|
+
transition: opacity var(--transition-fast);
|
|
25
50
|
opacity: var(--tool-opacity);
|
|
26
|
-
padding-top:
|
|
51
|
+
padding-top: var(--spacing-xs);
|
|
27
52
|
display: flex;
|
|
28
53
|
justify-content: center;
|
|
29
54
|
}
|
|
@@ -34,11 +59,10 @@
|
|
|
34
59
|
left: var(--frame-left);
|
|
35
60
|
width: var(--frame-width);
|
|
36
61
|
height: var(--frame-height);
|
|
37
|
-
z-index:
|
|
62
|
+
z-index: var(--z-index-medium);
|
|
38
63
|
pointer-events: none;
|
|
39
|
-
font-family:
|
|
40
|
-
letter-spacing:
|
|
41
|
-
/* outline: calc(0.125em / var(--zoom)) solid oklch(62.7% 0.265 303.9); */
|
|
64
|
+
font-family: var(--font-family-primary);
|
|
65
|
+
letter-spacing: var(--letter-spacing);
|
|
42
66
|
}
|
|
43
67
|
|
|
44
68
|
.highlight-frame-svg {
|
|
@@ -52,20 +76,20 @@
|
|
|
52
76
|
|
|
53
77
|
.highlight-frame-rect {
|
|
54
78
|
fill: none;
|
|
55
|
-
stroke:
|
|
79
|
+
stroke: var(--primary-color);
|
|
56
80
|
stroke-width: var(--stroke-width);
|
|
57
81
|
}
|
|
58
82
|
|
|
59
83
|
.tag-label {
|
|
60
|
-
background-color:
|
|
61
|
-
color: white;
|
|
84
|
+
background-color: var(--primary-color);
|
|
85
|
+
color: var(--text-color-white);
|
|
62
86
|
font-size: 0.575rem;
|
|
63
87
|
font-weight: 500;
|
|
64
88
|
text-transform: uppercase;
|
|
65
|
-
height:
|
|
66
|
-
padding: 0
|
|
89
|
+
height: 1rem;
|
|
90
|
+
padding: 0.5625rem var(--spacing-sm);
|
|
67
91
|
line-height: 1;
|
|
68
|
-
border-radius:
|
|
92
|
+
border-radius: var(--spacing-sm);
|
|
69
93
|
display: flex;
|
|
70
94
|
align-items: center;
|
|
71
95
|
justify-content: center;
|
|
@@ -78,12 +102,12 @@
|
|
|
78
102
|
|
|
79
103
|
.resize-handle {
|
|
80
104
|
position: absolute;
|
|
81
|
-
top:
|
|
105
|
+
top: var(--spacing-lg);
|
|
82
106
|
right: -12px;
|
|
83
107
|
width: 12px;
|
|
84
108
|
height: 40px;
|
|
85
109
|
cursor: ew-resize;
|
|
86
|
-
z-index:
|
|
110
|
+
z-index: var(--z-index-high);
|
|
87
111
|
display: flex;
|
|
88
112
|
opacity: 0;
|
|
89
113
|
visibility: hidden;
|
|
@@ -93,8 +117,8 @@
|
|
|
93
117
|
transform: scale(calc(1 / var(--zoom)));
|
|
94
118
|
transform-origin: top left;
|
|
95
119
|
transition:
|
|
96
|
-
opacity
|
|
97
|
-
visibility
|
|
120
|
+
opacity var(--transition-fast),
|
|
121
|
+
visibility var(--transition-fast);
|
|
98
122
|
}
|
|
99
123
|
|
|
100
124
|
.viewport:hover .resize-handle {
|
|
@@ -109,9 +133,9 @@
|
|
|
109
133
|
right: 0;
|
|
110
134
|
width: 3px;
|
|
111
135
|
height: 32px;
|
|
112
|
-
background:
|
|
136
|
+
background: var(--handle-color);
|
|
113
137
|
border-radius: 4px;
|
|
114
|
-
transition: transform
|
|
138
|
+
transition: transform var(--transition-medium);
|
|
115
139
|
}
|
|
116
140
|
|
|
117
141
|
.resize-handle:hover::before {
|
|
@@ -122,17 +146,17 @@
|
|
|
122
146
|
position: absolute;
|
|
123
147
|
top: 0;
|
|
124
148
|
left: 0;
|
|
125
|
-
padding-left:
|
|
149
|
+
padding-left: var(--spacing-lg);
|
|
126
150
|
display: flex;
|
|
127
151
|
flex-direction: column;
|
|
128
|
-
gap:
|
|
152
|
+
gap: var(--spacing-xs);
|
|
129
153
|
visibility: hidden;
|
|
130
154
|
opacity: 0;
|
|
131
|
-
font-family:
|
|
132
|
-
letter-spacing:
|
|
155
|
+
font-family: var(--font-family-primary);
|
|
156
|
+
letter-spacing: var(--letter-spacing);
|
|
133
157
|
transition:
|
|
134
|
-
visibility
|
|
135
|
-
opacity
|
|
158
|
+
visibility var(--transition-fast),
|
|
159
|
+
opacity var(--transition-fast);
|
|
136
160
|
}
|
|
137
161
|
|
|
138
162
|
.resize-handle:hover .resize-presets {
|
|
@@ -141,25 +165,25 @@
|
|
|
141
165
|
}
|
|
142
166
|
|
|
143
167
|
.resize-preset-button {
|
|
144
|
-
background:
|
|
168
|
+
background: var(--handle-color-transparent);
|
|
145
169
|
border: none;
|
|
146
170
|
cursor: pointer;
|
|
147
|
-
padding:
|
|
148
|
-
border-radius:
|
|
149
|
-
font-size: 0.
|
|
171
|
+
padding: var(--spacing-xs) var(--spacing-md);
|
|
172
|
+
border-radius: var(--spacing-md);
|
|
173
|
+
font-size: 0.625rem;
|
|
150
174
|
text-wrap: nowrap;
|
|
151
175
|
text-align: left;
|
|
152
176
|
backdrop-filter: blur(8px);
|
|
153
|
-
transition: background
|
|
154
|
-
color: white;
|
|
177
|
+
transition: background var(--transition-fast);
|
|
178
|
+
color: var(--text-color-white);
|
|
155
179
|
width: fit-content;
|
|
156
180
|
|
|
157
181
|
&:hover {
|
|
158
|
-
background:
|
|
182
|
+
background: var(--handle-color);
|
|
159
183
|
}
|
|
160
184
|
|
|
161
185
|
&.is-active {
|
|
162
|
-
background:
|
|
186
|
+
background: var(--uncode-color);
|
|
163
187
|
}
|
|
164
188
|
}
|
|
165
189
|
|
|
@@ -168,14 +192,14 @@
|
|
|
168
192
|
user-select: text;
|
|
169
193
|
|
|
170
194
|
&::selection {
|
|
171
|
-
background:
|
|
195
|
+
background: var(--primary-color-selection);
|
|
172
196
|
}
|
|
173
197
|
|
|
174
198
|
&::-moz-selection {
|
|
175
|
-
background:
|
|
199
|
+
background: var(--primary-color-selection);
|
|
176
200
|
}
|
|
177
201
|
|
|
178
202
|
&::-webkit-selection {
|
|
179
|
-
background:
|
|
203
|
+
background: var(--primary-color-selection);
|
|
180
204
|
}
|
|
181
205
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { RESIZE_PRESETS } from "../constants";
|
|
2
2
|
|
|
3
3
|
export const updateActivePreset = (container: HTMLElement, width: number): void => {
|
|
4
|
-
console.log("updateActivePreset", width);
|
|
5
4
|
const presetButtons = container.querySelectorAll<HTMLButtonElement>(".resize-preset-button");
|
|
6
|
-
console.log("presetButtons", presetButtons);
|
|
7
5
|
presetButtons.forEach((button, index) => {
|
|
8
6
|
if (index < RESIZE_PRESETS.length) {
|
|
9
7
|
const preset = RESIZE_PRESETS[index];
|