@node-edit-utils/core 1.2.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.
- package/README.md +268 -0
- package/dist/index.d.ts +6 -0
- package/dist/lib/canvas/createCanvasObserver.d.ts +2 -0
- package/dist/lib/canvas/disableCanvasKeyboard.d.ts +1 -0
- package/dist/lib/canvas/enableCanvasKeyboard.d.ts +1 -0
- package/dist/lib/canvas/helpers/applyCanvasState.d.ts +1 -0
- package/dist/lib/canvas/helpers/getCanvasContainer.d.ts +1 -0
- package/dist/lib/canvas/helpers/getCanvasWindowValue.d.ts +1 -0
- package/dist/lib/helpers/index.d.ts +1 -0
- package/dist/lib/helpers/observer/connectMutationObserver.d.ts +1 -0
- package/dist/lib/helpers/observer/connectResizeObserver.d.ts +1 -0
- package/dist/lib/helpers/withRAF.d.ts +4 -0
- package/dist/lib/node-tools/createNodeTools.d.ts +2 -0
- package/dist/lib/node-tools/events/click/handleNodeClick.d.ts +1 -0
- package/dist/lib/node-tools/events/setupEventListener.d.ts +1 -0
- package/dist/lib/node-tools/highlight/clearHighlightFrame.d.ts +1 -0
- package/dist/lib/node-tools/highlight/createHighlightFrame.d.ts +1 -0
- package/dist/lib/node-tools/highlight/createTagLabel.d.ts +1 -0
- package/dist/lib/node-tools/highlight/createToolsContainer.d.ts +1 -0
- package/dist/lib/node-tools/highlight/helpers/getElementBounds.d.ts +6 -0
- package/dist/lib/node-tools/highlight/helpers/getHighlightFrameElement.d.ts +1 -0
- package/dist/lib/node-tools/highlight/highlightNode.d.ts +1 -0
- package/dist/lib/node-tools/highlight/refreshHighlightFrame.d.ts +1 -0
- package/dist/lib/node-tools/select/constants.d.ts +1 -0
- package/dist/lib/node-tools/select/helpers/getElementsFromPoint.d.ts +1 -0
- package/dist/lib/node-tools/select/helpers/targetSameCandidates.d.ts +1 -0
- package/dist/lib/node-tools/select/selectNode.d.ts +1 -0
- package/dist/lib/node-tools/text/events/setupKeydownHandler.d.ts +1 -0
- package/dist/lib/node-tools/text/events/setupMutationObserver.d.ts +1 -0
- package/dist/lib/node-tools/text/events/setupNodeListeners.d.ts +1 -0
- package/dist/lib/node-tools/text/helpers/hasTextContent.d.ts +1 -0
- package/dist/lib/node-tools/text/helpers/insertLineBreak.d.ts +1 -0
- package/dist/lib/node-tools/text/helpers/makeNodeEditable.d.ts +1 -0
- package/dist/lib/node-tools/text/helpers/makeNodeNonEditable.d.ts +1 -0
- package/dist/lib/node-tools/text/nodeText.d.ts +2 -0
- package/dist/lib/post-message/handlePostMessage.d.ts +1 -0
- package/dist/lib/post-message/sendPostMessage.d.ts +1 -0
- package/dist/lib/viewport/constants.d.ts +5 -0
- package/dist/lib/viewport/createViewport.d.ts +2 -0
- package/dist/lib/viewport/events/setupEventListener.d.ts +1 -0
- package/dist/lib/viewport/resize/createResizeHandle.d.ts +1 -0
- package/dist/lib/viewport/width/calcConstrainedWidth.d.ts +1 -0
- package/dist/lib/viewport/width/calcWidth.d.ts +1 -0
- package/dist/lib/viewport/width/updateWidth.d.ts +1 -0
- package/dist/lib/window/bindToWindow.d.ts +1 -0
- package/dist/node-edit-utils.cjs.js +588 -0
- package/dist/node-edit-utils.esm.js +584 -0
- package/dist/node-edit-utils.umd.js +594 -0
- package/dist/node-edit-utils.umd.min.js +1 -0
- package/dist/styles.css +1 -0
- package/dist/umd.d.ts +1 -0
- package/package.json +65 -0
- package/src/index.ts +9 -0
- package/src/lib/canvas/createCanvasObserver.ts +37 -0
- package/src/lib/canvas/disableCanvasKeyboard.ts +7 -0
- package/src/lib/canvas/enableCanvasKeyboard.ts +7 -0
- package/src/lib/canvas/helpers/applyCanvasState.ts +11 -0
- package/src/lib/canvas/helpers/getCanvasContainer.ts +3 -0
- package/src/lib/canvas/helpers/getCanvasWindowValue.ts +5 -0
- package/src/lib/canvas/types.d.ts +3 -0
- package/src/lib/helpers/index.ts +1 -0
- package/src/lib/helpers/observer/connectMutationObserver.ts +12 -0
- package/src/lib/helpers/observer/connectResizeObserver.ts +8 -0
- package/src/lib/helpers/withRAF.ts +39 -0
- package/src/lib/node-tools/createNodeTools.ts +88 -0
- package/src/lib/node-tools/events/click/handleNodeClick.ts +21 -0
- package/src/lib/node-tools/events/setupEventListener.ts +35 -0
- package/src/lib/node-tools/highlight/clearHighlightFrame.ts +12 -0
- package/src/lib/node-tools/highlight/createHighlightFrame.ts +37 -0
- package/src/lib/node-tools/highlight/createTagLabel.ts +7 -0
- package/src/lib/node-tools/highlight/createToolsContainer.ts +10 -0
- package/src/lib/node-tools/highlight/helpers/getElementBounds.ts +31 -0
- package/src/lib/node-tools/highlight/helpers/getHighlightFrameElement.ts +5 -0
- package/src/lib/node-tools/highlight/highlightNode.ts +23 -0
- package/src/lib/node-tools/highlight/refreshHighlightFrame.ts +23 -0
- package/src/lib/node-tools/select/constants.ts +1 -0
- package/src/lib/node-tools/select/helpers/getElementsFromPoint.ts +16 -0
- package/src/lib/node-tools/select/helpers/targetSameCandidates.ts +2 -0
- package/src/lib/node-tools/select/selectNode.ts +44 -0
- package/src/lib/node-tools/text/events/setupKeydownHandler.ts +18 -0
- package/src/lib/node-tools/text/events/setupMutationObserver.ts +10 -0
- package/src/lib/node-tools/text/events/setupNodeListeners.ts +20 -0
- package/src/lib/node-tools/text/helpers/hasTextContent.ts +3 -0
- package/src/lib/node-tools/text/helpers/insertLineBreak.ts +17 -0
- package/src/lib/node-tools/text/helpers/makeNodeEditable.ts +5 -0
- package/src/lib/node-tools/text/helpers/makeNodeNonEditable.ts +5 -0
- package/src/lib/node-tools/text/nodeText.ts +67 -0
- package/src/lib/node-tools/text/types.d.ts +6 -0
- package/src/lib/node-tools/types.d.ts +12 -0
- package/src/lib/post-message/handlePostMessage.ts +8 -0
- package/src/lib/post-message/sendPostMessage.ts +11 -0
- package/src/lib/styles/styles.css +133 -0
- package/src/lib/viewport/constants.ts +6 -0
- package/src/lib/viewport/createViewport.ts +70 -0
- package/src/lib/viewport/events/setupEventListener.ts +20 -0
- package/src/lib/viewport/resize/createResizeHandle.ts +9 -0
- package/src/lib/viewport/types.d.ts +8 -0
- package/src/lib/viewport/width/calcConstrainedWidth.ts +6 -0
- package/src/lib/viewport/width/calcWidth.ts +9 -0
- package/src/lib/viewport/width/updateWidth.ts +3 -0
- package/src/lib/window/bindToWindow.ts +6 -0
- package/src/umd.ts +1 -0
|
@@ -0,0 +1,594 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markup Canvas
|
|
3
|
+
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
+
* @version 1.2.2
|
|
5
|
+
*/
|
|
6
|
+
(function (global, factory) {
|
|
7
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
8
|
+
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
9
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.MarkupCanvas = {}));
|
|
10
|
+
})(this, (function (exports) { 'use strict';
|
|
11
|
+
|
|
12
|
+
// biome-ignore lint/suspicious/noExplicitAny: generic constraint requires flexibility
|
|
13
|
+
function withRAFThrottle(func) {
|
|
14
|
+
let rafId = null;
|
|
15
|
+
let lastArgs = null;
|
|
16
|
+
const throttled = (...args) => {
|
|
17
|
+
lastArgs = args;
|
|
18
|
+
if (rafId === null) {
|
|
19
|
+
rafId = requestAnimationFrame(() => {
|
|
20
|
+
if (lastArgs) {
|
|
21
|
+
func(...lastArgs);
|
|
22
|
+
}
|
|
23
|
+
rafId = null;
|
|
24
|
+
lastArgs = null;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
throttled.cleanup = () => {
|
|
29
|
+
if (rafId !== null) {
|
|
30
|
+
cancelAnimationFrame(rafId);
|
|
31
|
+
rafId = null;
|
|
32
|
+
lastArgs = null;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
return throttled;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const getCanvasWindowValue = (path) => {
|
|
39
|
+
// biome-ignore lint/suspicious/noExplicitAny: global window extension
|
|
40
|
+
const canvas = window.canvas;
|
|
41
|
+
return path.reduce((obj, prop) => obj?.[prop], canvas);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const applyCanvasState = () => {
|
|
45
|
+
const zoom = getCanvasWindowValue(["zoom", "current"]);
|
|
46
|
+
document.body.style.setProperty("--zoom", zoom.toFixed(5));
|
|
47
|
+
document.body.style.setProperty("--stroke-width", (2 / zoom).toFixed(3));
|
|
48
|
+
document.body.dataset.zoom = zoom.toFixed(5);
|
|
49
|
+
document.body.dataset.strokeWidth = (2 / zoom).toFixed(3);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
function createCanvasObserver() {
|
|
53
|
+
const transformLayer = document.querySelector(".transform-layer");
|
|
54
|
+
if (!transformLayer) {
|
|
55
|
+
return {
|
|
56
|
+
disconnect: () => { },
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const throttledUpdate = withRAFThrottle(() => {
|
|
60
|
+
applyCanvasState();
|
|
61
|
+
});
|
|
62
|
+
const observer = new MutationObserver(() => {
|
|
63
|
+
throttledUpdate();
|
|
64
|
+
});
|
|
65
|
+
observer.observe(transformLayer, {
|
|
66
|
+
attributes: true,
|
|
67
|
+
attributeOldValue: true,
|
|
68
|
+
subtree: true,
|
|
69
|
+
childList: true,
|
|
70
|
+
});
|
|
71
|
+
function disconnect() {
|
|
72
|
+
throttledUpdate.cleanup();
|
|
73
|
+
observer.disconnect();
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
disconnect,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const connectResizeObserver = (element, handler) => {
|
|
81
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
82
|
+
handler(entries);
|
|
83
|
+
});
|
|
84
|
+
resizeObserver.observe(element);
|
|
85
|
+
return resizeObserver;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
function sendPostMessage(action, data) {
|
|
89
|
+
window.parent.postMessage({
|
|
90
|
+
source: "node-edit-utils",
|
|
91
|
+
action,
|
|
92
|
+
data,
|
|
93
|
+
timestamp: Date.now(),
|
|
94
|
+
}, "*");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const bindToWindow = (key, value) => {
|
|
98
|
+
if (typeof window !== "undefined") {
|
|
99
|
+
// biome-ignore lint/suspicious/noExplicitAny: global window extension requires flexibility
|
|
100
|
+
window[key] = value;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const handlePostMessage = (event) => {
|
|
105
|
+
if (event.data.source === "markup-canvas" && event.data.canvasName === "canvas") {
|
|
106
|
+
if (event.data.action === "zoom") {
|
|
107
|
+
const zoom = event.data.data;
|
|
108
|
+
console.log("zoom", zoom);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
function getHighlightFrameElement(nodeProvider) {
|
|
114
|
+
return nodeProvider.querySelector(".highlight-frame");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const clearHighlightFrame = (nodeProvider) => {
|
|
118
|
+
if (!nodeProvider) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const highlightFrame = getHighlightFrameElement(nodeProvider);
|
|
122
|
+
if (highlightFrame) {
|
|
123
|
+
highlightFrame.remove();
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const IGNORED_DOM_ELEMENTS = ["path", "rect", "circle", "ellipse", "polygon", "line", "polyline", "text", "text-noci"];
|
|
128
|
+
|
|
129
|
+
const getElementsFromPoint = (clickX, clickY) => {
|
|
130
|
+
const elements = document.elementsFromPoint(clickX, clickY);
|
|
131
|
+
return Array.from(elements).reduce((acc, el) => {
|
|
132
|
+
if (acc.found)
|
|
133
|
+
return acc;
|
|
134
|
+
if (el.getAttribute("data-role") === "node-provider") {
|
|
135
|
+
acc.found = true;
|
|
136
|
+
return acc;
|
|
137
|
+
}
|
|
138
|
+
acc.elements.push(el);
|
|
139
|
+
return acc;
|
|
140
|
+
}, { elements: [], found: false }).elements;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const targetSameCandidates = (cache, current) => cache.length === current.length && cache.every((el, i) => el === current[i]);
|
|
144
|
+
|
|
145
|
+
let candidateCache = [];
|
|
146
|
+
let attempt = 0;
|
|
147
|
+
const selectNode = (event, editableNode) => {
|
|
148
|
+
let selectedNode = null;
|
|
149
|
+
const clickX = event.clientX;
|
|
150
|
+
const clickY = event.clientY;
|
|
151
|
+
const clickThrough = event.metaKey || event.ctrlKey;
|
|
152
|
+
const candidates = getElementsFromPoint(clickX, clickY).filter((element) => !IGNORED_DOM_ELEMENTS.includes(element.tagName.toLowerCase()));
|
|
153
|
+
if (editableNode && candidates.includes(editableNode)) {
|
|
154
|
+
return editableNode;
|
|
155
|
+
}
|
|
156
|
+
if (clickThrough) {
|
|
157
|
+
candidateCache = [];
|
|
158
|
+
selectedNode = candidates[0];
|
|
159
|
+
return selectedNode;
|
|
160
|
+
}
|
|
161
|
+
if (targetSameCandidates(candidateCache, candidates)) {
|
|
162
|
+
attempt <= candidates.length && attempt++;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
attempt = 0;
|
|
166
|
+
}
|
|
167
|
+
const nodeIndex = candidates.length - 1 - attempt;
|
|
168
|
+
selectedNode = candidates[nodeIndex];
|
|
169
|
+
candidateCache = candidates;
|
|
170
|
+
return selectedNode;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const handleNodeClick = (event, nodeProvider, editableNode, onNodeSelected) => {
|
|
174
|
+
event.preventDefault();
|
|
175
|
+
event.stopPropagation();
|
|
176
|
+
if (nodeProvider && !nodeProvider.contains(event.target)) {
|
|
177
|
+
clearHighlightFrame(nodeProvider);
|
|
178
|
+
onNodeSelected(null);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const selectedNode = selectNode(event, editableNode);
|
|
182
|
+
onNodeSelected(selectedNode);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const setupEventListener$1 = (nodeProvider, onNodeSelected, onEscapePressed, getEditableNode) => {
|
|
186
|
+
const messageHandler = (event) => {
|
|
187
|
+
handlePostMessage(event);
|
|
188
|
+
};
|
|
189
|
+
const documentClickHandler = (event) => {
|
|
190
|
+
handleNodeClick(event, nodeProvider, getEditableNode(), onNodeSelected);
|
|
191
|
+
};
|
|
192
|
+
const documentKeydownHandler = (event) => {
|
|
193
|
+
if (event.key === "Escape") {
|
|
194
|
+
event.preventDefault();
|
|
195
|
+
event.stopPropagation();
|
|
196
|
+
onEscapePressed?.();
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
window.addEventListener("message", messageHandler);
|
|
200
|
+
document.addEventListener("click", documentClickHandler);
|
|
201
|
+
document.addEventListener("keydown", documentKeydownHandler);
|
|
202
|
+
return () => {
|
|
203
|
+
window.removeEventListener("message", messageHandler);
|
|
204
|
+
document.removeEventListener("click", documentClickHandler);
|
|
205
|
+
document.removeEventListener("keydown", documentKeydownHandler);
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
function getElementBounds(element, nodeProvider) {
|
|
210
|
+
const elementRect = element.getBoundingClientRect();
|
|
211
|
+
const componentRootRect = nodeProvider.getBoundingClientRect();
|
|
212
|
+
const relativeTop = elementRect.top - componentRootRect.top;
|
|
213
|
+
const relativeLeft = elementRect.left - componentRootRect.left;
|
|
214
|
+
const zoom = getCanvasWindowValue(["zoom", "current"]) ?? 1;
|
|
215
|
+
const top = parseFloat((relativeTop / zoom).toFixed(5));
|
|
216
|
+
const left = parseFloat((relativeLeft / zoom).toFixed(5));
|
|
217
|
+
const width = Math.max(4, parseFloat((elementRect.width / zoom).toFixed(5)));
|
|
218
|
+
const height = parseFloat((elementRect.height / zoom).toFixed(5));
|
|
219
|
+
return {
|
|
220
|
+
top,
|
|
221
|
+
left,
|
|
222
|
+
width,
|
|
223
|
+
height,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const createHighlightFrame = (node, nodeProvider) => {
|
|
228
|
+
const { top, left, width, height } = getElementBounds(node, nodeProvider);
|
|
229
|
+
const zoom = getCanvasWindowValue(["zoom", "current"]) ?? 1;
|
|
230
|
+
document.body.style.setProperty("--zoom", zoom.toString());
|
|
231
|
+
document.body.style.setProperty("--stroke-width", (2 / zoom).toFixed(3));
|
|
232
|
+
const frame = document.createElement("div");
|
|
233
|
+
frame.classList.add("highlight-frame");
|
|
234
|
+
frame.style.setProperty("--frame-top", `${top}px`);
|
|
235
|
+
frame.style.setProperty("--frame-left", `${left}px`);
|
|
236
|
+
frame.style.setProperty("--frame-width", `${width}px`);
|
|
237
|
+
frame.style.setProperty("--frame-height", `${height}px`);
|
|
238
|
+
// Create SVG overlay for outline
|
|
239
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
240
|
+
svg.classList.add("highlight-frame-svg");
|
|
241
|
+
const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
242
|
+
rect.setAttribute("x", "0");
|
|
243
|
+
rect.setAttribute("y", "0");
|
|
244
|
+
rect.setAttribute("width", "100%");
|
|
245
|
+
rect.setAttribute("height", "100%");
|
|
246
|
+
rect.classList.add("highlight-frame-rect");
|
|
247
|
+
svg.appendChild(rect);
|
|
248
|
+
frame.appendChild(svg);
|
|
249
|
+
const highlightFrame = frame;
|
|
250
|
+
return highlightFrame;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
const createTagLabel = (node, nodeTools) => {
|
|
254
|
+
const tagLabel = document.createElement("div");
|
|
255
|
+
tagLabel.className = "tag-label";
|
|
256
|
+
tagLabel.textContent = node.tagName.toLowerCase();
|
|
257
|
+
nodeTools.appendChild(tagLabel);
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
const createToolsContainer = (node, highlightFrame) => {
|
|
261
|
+
const nodeTools = document.createElement("div");
|
|
262
|
+
nodeTools.className = "node-tools";
|
|
263
|
+
highlightFrame.appendChild(nodeTools);
|
|
264
|
+
createTagLabel(node, nodeTools);
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const highlightNode = (node, nodeProvider) => {
|
|
268
|
+
if (!node)
|
|
269
|
+
return;
|
|
270
|
+
const existingHighlightFrame = getHighlightFrameElement(nodeProvider);
|
|
271
|
+
if (existingHighlightFrame) {
|
|
272
|
+
existingHighlightFrame.remove();
|
|
273
|
+
}
|
|
274
|
+
const highlightFrame = createHighlightFrame(node, nodeProvider);
|
|
275
|
+
if (node.contentEditable === "true") {
|
|
276
|
+
highlightFrame.classList.add("is-editable");
|
|
277
|
+
}
|
|
278
|
+
createToolsContainer(node, highlightFrame);
|
|
279
|
+
nodeProvider.appendChild(highlightFrame);
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
const refreshHighlightFrame = (node, nodeProvider) => {
|
|
283
|
+
const frame = getHighlightFrameElement(nodeProvider);
|
|
284
|
+
const zoom = getCanvasWindowValue(["zoom", "current"]) ?? 1;
|
|
285
|
+
if (!frame)
|
|
286
|
+
return;
|
|
287
|
+
if (zoom >= 0.3) {
|
|
288
|
+
nodeProvider.style.setProperty("--tool-opacity", `1`);
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
nodeProvider.style.setProperty("--tool-opacity", `0`);
|
|
292
|
+
}
|
|
293
|
+
const { top, left, width, height } = getElementBounds(node, nodeProvider);
|
|
294
|
+
frame.style.setProperty("--frame-top", `${top}px`);
|
|
295
|
+
frame.style.setProperty("--frame-left", `${left}px`);
|
|
296
|
+
frame.style.setProperty("--frame-width", `${width}px`);
|
|
297
|
+
frame.style.setProperty("--frame-height", `${height}px`);
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const disableCanvasKeyboard = () => {
|
|
301
|
+
const disable = getCanvasWindowValue(["keyboard", "disable"]);
|
|
302
|
+
disable?.();
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const enableCanvasKeyboard = () => {
|
|
306
|
+
const enable = getCanvasWindowValue(["keyboard", "enable"]);
|
|
307
|
+
enable?.();
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
const insertLineBreak = () => {
|
|
311
|
+
const selection = window.getSelection();
|
|
312
|
+
if (selection && selection.rangeCount > 0) {
|
|
313
|
+
const range = selection.getRangeAt(0);
|
|
314
|
+
range.deleteContents();
|
|
315
|
+
const br = document.createElement("br");
|
|
316
|
+
range.insertNode(br);
|
|
317
|
+
// Move cursor after the br
|
|
318
|
+
range.setStartAfter(br);
|
|
319
|
+
range.setEndAfter(br);
|
|
320
|
+
selection.removeAllRanges();
|
|
321
|
+
selection.addRange(range);
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const setupKeydownHandler = (node) => {
|
|
326
|
+
const keydownHandler = (event) => {
|
|
327
|
+
if (event.key === "Enter") {
|
|
328
|
+
event.preventDefault();
|
|
329
|
+
event.stopPropagation();
|
|
330
|
+
insertLineBreak();
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
node.addEventListener("keydown", keydownHandler);
|
|
334
|
+
return () => {
|
|
335
|
+
node.removeEventListener("keydown", keydownHandler);
|
|
336
|
+
};
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
const connectMutationObserver = (element, handler) => {
|
|
340
|
+
const mutationObserver = new MutationObserver((mutations) => {
|
|
341
|
+
handler(mutations);
|
|
342
|
+
});
|
|
343
|
+
mutationObserver.observe(element, {
|
|
344
|
+
subtree: true,
|
|
345
|
+
childList: true,
|
|
346
|
+
characterData: true,
|
|
347
|
+
});
|
|
348
|
+
return mutationObserver;
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
const setupMutationObserver = (node, nodeProvider) => {
|
|
352
|
+
const mutationObserver = connectMutationObserver(node, () => {
|
|
353
|
+
refreshHighlightFrame(node, nodeProvider);
|
|
354
|
+
});
|
|
355
|
+
return mutationObserver.disconnect;
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
const setupNodeListeners = (node, nodeProvider, blur) => {
|
|
359
|
+
if (!nodeProvider) {
|
|
360
|
+
return () => { };
|
|
361
|
+
}
|
|
362
|
+
node.addEventListener("blur", blur);
|
|
363
|
+
const keydownCleanup = setupKeydownHandler(node);
|
|
364
|
+
const mutationCleanup = setupMutationObserver(node, nodeProvider);
|
|
365
|
+
return () => {
|
|
366
|
+
node.removeEventListener("blur", blur);
|
|
367
|
+
keydownCleanup();
|
|
368
|
+
mutationCleanup?.();
|
|
369
|
+
};
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
const hasTextContent = (node) => {
|
|
373
|
+
return Array.from(node.childNodes).some((child) => child.nodeType === Node.TEXT_NODE && child.textContent?.trim());
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
const makeNodeEditable = (node) => {
|
|
377
|
+
node.contentEditable = "true";
|
|
378
|
+
node.classList.add("is-editable");
|
|
379
|
+
node.style.outline = "none";
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
const makeNodeNonEditable = (node) => {
|
|
383
|
+
node.contentEditable = "false";
|
|
384
|
+
node.classList.remove("is-editable");
|
|
385
|
+
node.style.outline = "none";
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
const nodeText = () => {
|
|
389
|
+
let editableNode = null;
|
|
390
|
+
let blurInProgress = false;
|
|
391
|
+
let cleanup = null;
|
|
392
|
+
const enableEditMode = (node, nodeProvider) => {
|
|
393
|
+
if (editableNode === node) {
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
if (editableNode && editableNode !== node) {
|
|
397
|
+
blurEditMode();
|
|
398
|
+
}
|
|
399
|
+
const editable = hasTextContent(node);
|
|
400
|
+
if (editable) {
|
|
401
|
+
editableNode = node;
|
|
402
|
+
makeNodeEditable(node);
|
|
403
|
+
disableCanvasKeyboard();
|
|
404
|
+
cleanup = setupNodeListeners(node, nodeProvider, blurEditMode);
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
const getEditableNode = () => {
|
|
408
|
+
return editableNode;
|
|
409
|
+
};
|
|
410
|
+
const isEditing = () => {
|
|
411
|
+
return editableNode !== null;
|
|
412
|
+
};
|
|
413
|
+
const blurEditMode = () => {
|
|
414
|
+
if (blurInProgress || !editableNode) {
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
blurInProgress = true;
|
|
418
|
+
const nodeToCleanup = editableNode;
|
|
419
|
+
makeNodeNonEditable(nodeToCleanup);
|
|
420
|
+
enableCanvasKeyboard();
|
|
421
|
+
cleanup?.();
|
|
422
|
+
editableNode = null;
|
|
423
|
+
blurInProgress = false;
|
|
424
|
+
};
|
|
425
|
+
return {
|
|
426
|
+
enableEditMode,
|
|
427
|
+
blurEditMode,
|
|
428
|
+
getEditableNode,
|
|
429
|
+
isEditing,
|
|
430
|
+
};
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
const createNodeTools = (element) => {
|
|
434
|
+
const nodeProvider = element;
|
|
435
|
+
let resizeObserver = null;
|
|
436
|
+
let selectedNode = null;
|
|
437
|
+
const text = nodeText();
|
|
438
|
+
const throttledFrameRefresh = withRAFThrottle(refreshHighlightFrame);
|
|
439
|
+
const handleEscape = () => {
|
|
440
|
+
if (text.isEditing()) {
|
|
441
|
+
text.blurEditMode();
|
|
442
|
+
}
|
|
443
|
+
if (selectedNode) {
|
|
444
|
+
if (nodeProvider) {
|
|
445
|
+
clearHighlightFrame(nodeProvider);
|
|
446
|
+
selectedNode = null;
|
|
447
|
+
resizeObserver?.disconnect();
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
const selectNode = (node) => {
|
|
452
|
+
if (text.isEditing()) {
|
|
453
|
+
const currentEditable = text.getEditableNode();
|
|
454
|
+
if (currentEditable && currentEditable !== node) {
|
|
455
|
+
text.blurEditMode();
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
resizeObserver?.disconnect();
|
|
459
|
+
if (node && nodeProvider) {
|
|
460
|
+
text.enableEditMode(node, nodeProvider);
|
|
461
|
+
resizeObserver = connectResizeObserver(nodeProvider, () => {
|
|
462
|
+
throttledFrameRefresh(node, nodeProvider);
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
selectedNode = node;
|
|
466
|
+
sendPostMessage("selectedNodeChanged", node?.getAttribute("data-layer-id") ?? null);
|
|
467
|
+
highlightNode(node, nodeProvider) ?? null;
|
|
468
|
+
};
|
|
469
|
+
// Setup event listener
|
|
470
|
+
const removeListeners = setupEventListener$1(nodeProvider, selectNode, handleEscape, text.getEditableNode);
|
|
471
|
+
const cleanup = () => {
|
|
472
|
+
removeListeners();
|
|
473
|
+
resizeObserver?.disconnect();
|
|
474
|
+
text.blurEditMode();
|
|
475
|
+
throttledFrameRefresh.cleanup();
|
|
476
|
+
};
|
|
477
|
+
const nodeTools = {
|
|
478
|
+
selectNode,
|
|
479
|
+
getSelectedNode: () => selectedNode,
|
|
480
|
+
refreshHighlightFrame: () => {
|
|
481
|
+
throttledFrameRefresh(selectedNode, nodeProvider);
|
|
482
|
+
},
|
|
483
|
+
clearSelectedNode: () => {
|
|
484
|
+
clearHighlightFrame(nodeProvider);
|
|
485
|
+
selectedNode = null;
|
|
486
|
+
resizeObserver?.disconnect();
|
|
487
|
+
},
|
|
488
|
+
getEditableNode: () => text.getEditableNode(),
|
|
489
|
+
cleanup,
|
|
490
|
+
};
|
|
491
|
+
bindToWindow("nodeTools", nodeTools);
|
|
492
|
+
return nodeTools;
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
const getCanvasContainer = () => {
|
|
496
|
+
return document.querySelector(".canvas-container");
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
const DEFAULT_WIDTH = 400;
|
|
500
|
+
const RESIZE_CONFIG = {
|
|
501
|
+
minWidth: 320,
|
|
502
|
+
maxWidth: 1680,
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
const setupEventListener = (resizeHandle, startResize, handleResize, stopResize, blurResize) => {
|
|
506
|
+
resizeHandle.addEventListener("mousedown", startResize);
|
|
507
|
+
document.addEventListener("mousemove", handleResize);
|
|
508
|
+
document.addEventListener("mouseup", stopResize);
|
|
509
|
+
window.addEventListener("blur", blurResize);
|
|
510
|
+
return () => {
|
|
511
|
+
resizeHandle.removeEventListener("mousedown", startResize);
|
|
512
|
+
document.removeEventListener("mousemove", handleResize);
|
|
513
|
+
document.removeEventListener("mouseup", stopResize);
|
|
514
|
+
window.removeEventListener("blur", blurResize);
|
|
515
|
+
};
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
const createResizeHandle = (container) => {
|
|
519
|
+
const handle = document.createElement("div");
|
|
520
|
+
handle.className = "component-resize-handle resize-handle";
|
|
521
|
+
container.appendChild(handle);
|
|
522
|
+
return handle;
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
const calcConstrainedWidth = (startWidth, deltaX) => {
|
|
526
|
+
const newWidth = startWidth + Math.round(deltaX);
|
|
527
|
+
return Math.max(RESIZE_CONFIG.minWidth, Math.min(RESIZE_CONFIG.maxWidth, newWidth));
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
const calcWidth = (event, startX, startWidth) => {
|
|
531
|
+
const zoom = parseFloat(document.body.dataset.zoom || "1");
|
|
532
|
+
const deltaX = (event.clientX - startX) / zoom;
|
|
533
|
+
const width = calcConstrainedWidth(startWidth, deltaX);
|
|
534
|
+
return width;
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
const updateWidth = (container, width) => {
|
|
538
|
+
container.style.setProperty("--container-width", `${width}px`);
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
const createViewport = (container) => {
|
|
542
|
+
const canvas = getCanvasContainer();
|
|
543
|
+
const resizeHandle = createResizeHandle(container);
|
|
544
|
+
container.style.setProperty("--container-width", `${DEFAULT_WIDTH}px`);
|
|
545
|
+
let isDragging = false;
|
|
546
|
+
let startX = 0;
|
|
547
|
+
let startWidth = 0;
|
|
548
|
+
const startResize = (event) => {
|
|
549
|
+
event.preventDefault();
|
|
550
|
+
event.stopPropagation();
|
|
551
|
+
isDragging = true;
|
|
552
|
+
startX = event.clientX;
|
|
553
|
+
startWidth = container.offsetWidth;
|
|
554
|
+
};
|
|
555
|
+
const handleResize = (event) => {
|
|
556
|
+
if (!isDragging)
|
|
557
|
+
return;
|
|
558
|
+
if (canvas) {
|
|
559
|
+
canvas.style.cursor = "ew-resize";
|
|
560
|
+
}
|
|
561
|
+
const width = calcWidth(event, startX, startWidth);
|
|
562
|
+
updateWidth(container, width);
|
|
563
|
+
};
|
|
564
|
+
const throttledHandleResize = withRAFThrottle(handleResize);
|
|
565
|
+
const stopResize = (event) => {
|
|
566
|
+
event.preventDefault();
|
|
567
|
+
event.stopPropagation();
|
|
568
|
+
if (canvas) {
|
|
569
|
+
canvas.style.cursor = "default";
|
|
570
|
+
}
|
|
571
|
+
isDragging = false;
|
|
572
|
+
};
|
|
573
|
+
const blurResize = () => {
|
|
574
|
+
isDragging = false;
|
|
575
|
+
};
|
|
576
|
+
const removeListeners = setupEventListener(resizeHandle, startResize, throttledHandleResize, stopResize, blurResize);
|
|
577
|
+
const cleanup = () => {
|
|
578
|
+
isDragging = false;
|
|
579
|
+
throttledHandleResize?.cleanup();
|
|
580
|
+
removeListeners();
|
|
581
|
+
};
|
|
582
|
+
return {
|
|
583
|
+
setWidth: (width) => {
|
|
584
|
+
updateWidth(container, width);
|
|
585
|
+
},
|
|
586
|
+
cleanup,
|
|
587
|
+
};
|
|
588
|
+
};
|
|
589
|
+
|
|
590
|
+
exports.createCanvasObserver = createCanvasObserver;
|
|
591
|
+
exports.createNodeTools = createNodeTools;
|
|
592
|
+
exports.createViewport = createViewport;
|
|
593
|
+
|
|
594
|
+
}));
|
|
@@ -0,0 +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 i=[],d=0;const a=(e,t)=>{let n=null;const o=e.clientX,r=e.clientY,a=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()));if(t&&l.includes(t))return t;if(a)return i=[],n=l[0],n;var c,u;u=l,(c=i).length===u.length&&c.every((e,t)=>e===u[t])?d<=l.length&&d++:d=0;return n=l[l.length-1-d],i=l,n},l=(e,t,n,o)=>{const s=e=>{(e=>{if("markup-canvas"===e.data.source&&"canvas"===e.data.canvasName&&"zoom"===e.data.action){const t=e.data.data;console.log("zoom",t)}})(e)},i=n=>{((e,t,n,o)=>{if(e.preventDefault(),e.stopPropagation(),t&&!t.contains(e.target))return r(t),void o(null);o(a(e,n))})(n,e,o(),t)},d=e=>{"Escape"===e.key&&(e.preventDefault(),e.stopPropagation(),n?.())};return window.addEventListener("message",s),document.addEventListener("click",i),document.addEventListener("keydown",d),()=>{window.removeEventListener("message",s),document.removeEventListener("click",i),document.removeEventListener("keydown",d)}};function c(e,t){const o=e.getBoundingClientRect(),r=t.getBoundingClientRect(),s=o.top-r.top,i=o.left-r.left,d=n(["zoom","current"])??1;return{top:parseFloat((s/d).toFixed(5)),left:parseFloat((i/d).toFixed(5)),width:Math.max(4,parseFloat((o.width/d).toFixed(5))),height:parseFloat((o.height/d).toFixed(5))}}const u=(e,t)=>{const n=document.createElement("div");n.className="node-tools",t.appendChild(n),((e,t)=>{const n=document.createElement("div");n.className="tag-label",n.textContent=e.tagName.toLowerCase(),t.appendChild(n)})(e,n)},m=(e,t)=>{if(!e)return;const r=o(t);r&&r.remove();const s=((e,t)=>{const{top:o,left:r,width:s,height:i}=c(e,t),d=n(["zoom","current"])??1;document.body.style.setProperty("--zoom",d.toString()),document.body.style.setProperty("--stroke-width",(2/d).toFixed(3));const a=document.createElement("div");a.classList.add("highlight-frame"),a.style.setProperty("--frame-top",`${o}px`),a.style.setProperty("--frame-left",`${r}px`),a.style.setProperty("--frame-width",`${s}px`),a.style.setProperty("--frame-height",`${i}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),a.appendChild(l),a})(e,t);"true"===e.contentEditable&&s.classList.add("is-editable"),u(e,s),t.appendChild(s)},p=(e,t)=>{const r=o(t),s=n(["zoom","current"])??1;if(!r)return;s>=.3?t.style.setProperty("--tool-opacity","1"):t.style.setProperty("--tool-opacity","0");const{top:i,left:d,width:a,height:l}=c(e,t);r.style.setProperty("--frame-top",`${i}px`),r.style.setProperty("--frame-left",`${d}px`),r.style.setProperty("--frame-width",`${a}px`),r.style.setProperty("--frame-height",`${l}px`)},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)=>((e,t)=>{const n=new MutationObserver(e=>{t(e)});return n.observe(e,{subtree:!0,childList:!0,characterData:!0}),n})(e,()=>{p(e,t)}).disconnect,h=()=>{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 i=(e=>Array.from(e.childNodes).some(e=>e.nodeType===Node.TEXT_NODE&&e.textContent?.trim()))(t);i&&(e=t,(e=>{e.contentEditable="true",e.classList.add("is-editable"),e.style.outline="none"})(t),(()=>{const e=n(["keyboard","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}},v=320,g=1680,b=(e,t,n)=>{const o=parseFloat(document.body.dataset.zoom||"1"),r=((e,t)=>{const n=e+Math.round(t);return Math.max(v,Math.min(g,n))})(n,(e.clientX-t)/o);return r},w=(e,t)=>{e.style.setProperty("--container-width",`${t}px`)};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;const i=h(),d=t(p),a=e=>{if(i.isEditing()){const t=i.getEditableNode();t&&t!==e&&i.blurEditMode()}var t,r;o?.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=e,t="selectedNodeChanged",r=e?.getAttribute("data-layer-id")??null,window.parent.postMessage({source:"node-edit-utils",action:t,data:r,timestamp:Date.now()},"*"),m(e,n)},c=l(n,a,()=>{i.isEditing()&&i.blurEditMode(),s&&n&&(r(n),s=null,o?.disconnect())},i.getEditableNode),u={selectNode:a,getSelectedNode:()=>s,refreshHighlightFrame:()=>{d(s,n)},clearSelectedNode:()=>{r(n),s=null,o?.disconnect()},getEditableNode:()=>i.getEditableNode(),cleanup:()=>{c(),o?.disconnect(),i.blurEditMode(),d.cleanup()}};var f,y;return f="nodeTools",y=u,"undefined"!=typeof window&&(window[f]=y),u},e.createViewport=e=>{const n=document.querySelector(".canvas-container"),o=(e=>{const t=document.createElement("div");return t.className="component-resize-handle resize-handle",e.appendChild(t),t})(e);e.style.setProperty("--container-width","400px");let r=!1,s=0,i=0;const d=t(t=>{if(!r)return;n&&(n.style.cursor="ew-resize");const o=b(t,s,i);w(e,o)}),a=((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)}))(o,t=>{t.preventDefault(),t.stopPropagation(),r=!0,s=t.clientX,i=e.offsetWidth},d,e=>{e.preventDefault(),e.stopPropagation(),n&&(n.style.cursor="default"),r=!1},()=>{r=!1});return{setWidth:t=>{w(e,t)},cleanup:()=>{r=!1,d?.cleanup(),a()}}}});
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.node-provider{::selection{background:transparent}::-moz-selection{background:transparent}::-webkit-selection{background:transparent}}.node-tools{bottom:0;display:flex;gap:.25rem;justify-content:center;left:0;opacity:var(--tool-opacity);padding-top:.25rem;position:absolute;transform:scale(calc(1/var(--zoom))) translate3d(0,100%,0);transform-origin:bottom left;transition:transform 25ms ease,opacity .1s ease;z-index:10000}.highlight-frame{height:var(--frame-height);left:var(--frame-left);pointer-events:none;position:absolute;top:var(--frame-top);width:var(--frame-width);z-index:1000}.highlight-frame-svg{height:100%;left:0;overflow:visible;position:absolute;top:0;width:100%}.highlight-frame-rect{fill:none;stroke:oklch(62.7% .265 303.9);stroke-width:var(--stroke-width)}.tag-label{align-items:center;background-color:oklch(62.7% .265 303.9);border-radius:.375rem;color:#fff;display:flex;font-size:.575rem;font-weight:500;height:1.25rem;justify-content:center;line-height:1;padding:0 .375rem;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:1.25rem;transform:scale(calc(1/var(--zoom)));transform-origin:top left;transition:transform 25ms ease,opacity .2s ease-in-out;width:12px;z-index:10000}.viewport:hover .resize-handle{opacity:1}.resize-handle:before{background:oklch(55.2% .016 285.938);border-radius:4px;content:"";height:32px;position:relative;right:0;top:0;transition:transform .2s ease-in-out;width:3px}.resize-handle:hover:before{transform:scaleY(1.3)}.is-editable{outline:none;user-select:text;&::selection{background:oklch(62.7% .265 303.9/.3)}&::-moz-selection{background:oklch(62.7% .265 303.9/.3)}&::-webkit-selection{background:oklch(62.7% .265 303.9/.3)}}
|
package/dist/umd.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./index";
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@node-edit-utils/core",
|
|
3
|
+
"version": "1.2.2",
|
|
4
|
+
"description": "Utilities for editing nodes in a dom tree.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/node-edit-utils.cjs.js",
|
|
7
|
+
"module": "dist/node-edit-utils.esm.js",
|
|
8
|
+
"browser": "dist/node-edit-utils.umd.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/",
|
|
12
|
+
"src/",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/node-edit-utils.esm.js",
|
|
19
|
+
"require": "./dist/node-edit-utils.cjs.js"
|
|
20
|
+
},
|
|
21
|
+
"./styles.css": "./dist/styles.css"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "rollup -c",
|
|
25
|
+
"dev": "rollup -c -w",
|
|
26
|
+
"clean": "rm -rf dist",
|
|
27
|
+
"lint": "biome check .",
|
|
28
|
+
"format": "biome format --write .",
|
|
29
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"zoom",
|
|
33
|
+
"pan",
|
|
34
|
+
"canvas",
|
|
35
|
+
"transform",
|
|
36
|
+
"interactive",
|
|
37
|
+
"html",
|
|
38
|
+
"dom"
|
|
39
|
+
],
|
|
40
|
+
"author": "Fritz Benning <mail@fritzbenning.de>",
|
|
41
|
+
"license": "CC-BY-NC-4.0",
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@biomejs/biome": "2.3.0",
|
|
44
|
+
"@rollup/plugin-alias": "^5.1.1",
|
|
45
|
+
"@rollup/plugin-commonjs": "^28.0.9",
|
|
46
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
47
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
48
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
49
|
+
"glob": "^11.0.3",
|
|
50
|
+
"rollup": "^4.52.5",
|
|
51
|
+
"rollup-plugin-postcss": "^4.0.2",
|
|
52
|
+
"tslib": "^2.8.1",
|
|
53
|
+
"ttypescript": "^1.5.15",
|
|
54
|
+
"typescript": "^5.9.3",
|
|
55
|
+
"typescript-transform-paths": "^3.5.5"
|
|
56
|
+
},
|
|
57
|
+
"repository": {
|
|
58
|
+
"type": "git",
|
|
59
|
+
"url": "https://github.com/fritzbenning/node-edit-utils"
|
|
60
|
+
},
|
|
61
|
+
"bugs": {
|
|
62
|
+
"url": "https://github.com/fritzbenning/node-edit-utils/issues"
|
|
63
|
+
},
|
|
64
|
+
"homepage": "https://github.com/fritzbenning/node-edit-utils#readme"
|
|
65
|
+
}
|