@elixpo/lixsketch 5.5.8 → 5.5.10
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/react/{CopyPaste-4CKJRHJ3.js → CopyPaste-SA72NDFN.js} +2 -2
- package/dist/react/{EventDispatcher-FP2RHJGG.js → EventDispatcher-BZQRHROG.js} +7 -7
- package/dist/react/{SceneSerializer-4U4B24JM.js → SceneSerializer-ZPHV6IUP.js} +2 -2
- package/dist/react/{SketchEngine-WYUPJWK4.js → SketchEngine-BCRJ62CV.js} +11 -7
- package/dist/react/SketchEngine-BCRJ62CV.js.map +7 -0
- package/dist/react/TextShape-U6ZZKB35.js +8 -0
- package/dist/react/{chunk-QXFBG7OM.js → chunk-42O6W7DF.js} +18 -1
- package/dist/react/chunk-42O6W7DF.js.map +7 -0
- package/dist/react/{chunk-TUMWA4YF.js → chunk-5QIT2WBE.js} +21 -113
- package/dist/react/chunk-5QIT2WBE.js.map +7 -0
- package/dist/react/index.js +3 -3
- package/dist/react/index.js.map +1 -1
- package/dist/react/{textTool-QVKV45VD.js → textTool-HY5NMM7H.js} +2 -2
- package/package.json +1 -1
- package/src/SketchEngine.js +11 -7
- package/src/react/components/sidebars/TextSidebar.jsx +1 -1
- package/src/shapes/TextShape.js +19 -0
- package/src/tools/textTool.js +25 -155
- package/dist/react/SketchEngine-WYUPJWK4.js.map +0 -7
- package/dist/react/TextShape-54ZJ66E3.js +0 -8
- package/dist/react/chunk-QXFBG7OM.js.map +0 -7
- package/dist/react/chunk-TUMWA4YF.js.map +0 -7
- /package/dist/react/{CopyPaste-4CKJRHJ3.js.map → CopyPaste-SA72NDFN.js.map} +0 -0
- /package/dist/react/{EventDispatcher-FP2RHJGG.js.map → EventDispatcher-BZQRHROG.js.map} +0 -0
- /package/dist/react/{SceneSerializer-4U4B24JM.js.map → SceneSerializer-ZPHV6IUP.js.map} +0 -0
- /package/dist/react/{TextShape-54ZJ66E3.js.map → TextShape-U6ZZKB35.js.map} +0 -0
- /package/dist/react/{textTool-QVKV45VD.js.map → textTool-HY5NMM7H.js.map} +0 -0
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
handleTextMouseMove,
|
|
7
7
|
handleTextMouseUp,
|
|
8
8
|
updateCodeToggleForShape
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-5QIT2WBE.js";
|
|
10
10
|
import "./chunk-LHRTXNVE.js";
|
|
11
11
|
import "./chunk-BZE4CEBG.js";
|
|
12
12
|
import "./chunk-L5OARZJ7.js";
|
|
@@ -18,4 +18,4 @@ export {
|
|
|
18
18
|
handleTextMouseUp,
|
|
19
19
|
updateCodeToggleForShape
|
|
20
20
|
};
|
|
21
|
-
//# sourceMappingURL=textTool-
|
|
21
|
+
//# sourceMappingURL=textTool-HY5NMM7H.js.map
|
package/package.json
CHANGED
package/src/SketchEngine.js
CHANGED
|
@@ -57,6 +57,7 @@ class SketchEngine {
|
|
|
57
57
|
// Core SVG reference
|
|
58
58
|
window.svg = this.svg;
|
|
59
59
|
window.freehandCanvas = this.svg;
|
|
60
|
+
window.__sketchInteractionReady = false;
|
|
60
61
|
|
|
61
62
|
// RoughJS from npm
|
|
62
63
|
window.rough = rough;
|
|
@@ -238,13 +239,6 @@ class SketchEngine {
|
|
|
238
239
|
Frame, FreehandStroke
|
|
239
240
|
};
|
|
240
241
|
|
|
241
|
-
// Expose restore as soon as the shape constructors are ready.
|
|
242
|
-
// Tool handlers, AI/graph renderers, and LixScript are not needed
|
|
243
|
-
// to deserialize a cached scene, so keeping the serializer behind
|
|
244
|
-
// those chunks unnecessarily delayed first canvas paint.
|
|
245
|
-
const sceneSerializer = await import('./core/SceneSerializer.js');
|
|
246
|
-
if (sceneSerializer.initSceneSerializer) sceneSerializer.initSceneSerializer();
|
|
247
|
-
|
|
248
242
|
// Import tool handlers (they run top-level code that reads globals)
|
|
249
243
|
const [
|
|
250
244
|
rectangleTool, circleTool, arrowTool, lineTool,
|
|
@@ -295,6 +289,14 @@ class SketchEngine {
|
|
|
295
289
|
if (eventDispatcher.initEventDispatcher) {
|
|
296
290
|
eventDispatcher.initEventDispatcher(this.svg);
|
|
297
291
|
}
|
|
292
|
+
window.__sketchInteractionReady = true;
|
|
293
|
+
|
|
294
|
+
// Restore only after pointer handlers are bound. This still keeps
|
|
295
|
+
// first canvas paint ahead of optional AI/graph/LixScript chunks,
|
|
296
|
+
// while guaranteeing every visible restored shape is immediately
|
|
297
|
+
// selectable and draggable.
|
|
298
|
+
const sceneSerializer = await import('./core/SceneSerializer.js');
|
|
299
|
+
if (sceneSerializer.initSceneSerializer) sceneSerializer.initSceneSerializer();
|
|
298
300
|
|
|
299
301
|
// Import standalone tools
|
|
300
302
|
await Promise.all([
|
|
@@ -473,6 +475,8 @@ class SketchEngine {
|
|
|
473
475
|
window.shapes = [];
|
|
474
476
|
window.currentShape = null;
|
|
475
477
|
window.lastMousePos = null;
|
|
478
|
+
window.__sketchInteractionReady = false;
|
|
479
|
+
delete window.__sceneSerializer;
|
|
476
480
|
this._modules = {};
|
|
477
481
|
this._initialized = false;
|
|
478
482
|
console.log('[SketchEngine] Cleaned up');
|
|
@@ -27,7 +27,7 @@ export default function TextSidebar() {
|
|
|
27
27
|
const activeTool = useSketchStore((s) => s.activeTool)
|
|
28
28
|
const selectedShapeSidebar = useSketchStore((s) => s.selectedShapeSidebar)
|
|
29
29
|
const [textColor, setTextColor] = useState('#fff')
|
|
30
|
-
const [fontSize, setFontSize] = useState('
|
|
30
|
+
const [fontSize, setFontSize] = useState('S')
|
|
31
31
|
const [font, setFont] = useState('lixFont')
|
|
32
32
|
const [codeMode, setCodeMode] = useState(false)
|
|
33
33
|
const [language, setLanguage] = useState('javascript')
|
package/src/shapes/TextShape.js
CHANGED
|
@@ -25,9 +25,28 @@ function updateSelectionFeedback() {}
|
|
|
25
25
|
function deselectElement() { selectedElement = null; }
|
|
26
26
|
function selectElement(el) { selectedElement = el; }
|
|
27
27
|
|
|
28
|
+
function removeLegacySoftWrap(groupElement) {
|
|
29
|
+
const textElement = groupElement.querySelector('text');
|
|
30
|
+
if (!textElement || !textElement.hasAttribute('data-wrap-width')) return;
|
|
31
|
+
const source = textElement.getAttribute('data-wrap-source');
|
|
32
|
+
if (source === null) return;
|
|
33
|
+
|
|
34
|
+
while (textElement.firstChild) textElement.removeChild(textElement.firstChild);
|
|
35
|
+
const x = textElement.getAttribute('x') || 0;
|
|
36
|
+
source.split('\n').forEach((line, index) => {
|
|
37
|
+
const tspan = textElement.ownerDocument.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
|
38
|
+
tspan.setAttribute('x', x);
|
|
39
|
+
tspan.setAttribute('dy', index === 0 ? '0' : '1.2em');
|
|
40
|
+
tspan.textContent = line || ' ';
|
|
41
|
+
textElement.appendChild(tspan);
|
|
42
|
+
});
|
|
43
|
+
textElement.removeAttribute('data-wrap-width');
|
|
44
|
+
}
|
|
45
|
+
|
|
28
46
|
class TextShape {
|
|
29
47
|
constructor(groupElement) {
|
|
30
48
|
this.group = groupElement;
|
|
49
|
+
removeLegacySoftWrap(groupElement);
|
|
31
50
|
this.shapeName = 'text';
|
|
32
51
|
this.shapeID = groupElement.getAttribute('id') || `text-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;
|
|
33
52
|
|
package/src/tools/textTool.js
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
getSelectedCodeBlock
|
|
28
28
|
} from './codeTool.js';
|
|
29
29
|
|
|
30
|
-
let textSize = "
|
|
30
|
+
let textSize = "20px";
|
|
31
31
|
let textFont = "lixFont";
|
|
32
32
|
let textColor = null;
|
|
33
33
|
let textAlign = "left";
|
|
@@ -193,11 +193,11 @@ function makeTextEditable(textElement, groupElement) {
|
|
|
193
193
|
|
|
194
194
|
let input = document.createElement("textarea");
|
|
195
195
|
input.className = "svg-text-editor";
|
|
196
|
+
input.setAttribute("aria-label", "Edit canvas text");
|
|
197
|
+
input.setAttribute("data-editing", "true");
|
|
196
198
|
|
|
197
|
-
//
|
|
198
|
-
//
|
|
199
|
-
// original line breaks instead of the auto-wrap output. Falls back
|
|
200
|
-
// to tspan-concatenation for legacy text shapes.
|
|
199
|
+
// Prefer the persisted source so re-opening the editor preserves only
|
|
200
|
+
// the line breaks the user explicitly inserted with Shift+Enter.
|
|
201
201
|
let textContent = '';
|
|
202
202
|
const storedSource = textElement.getAttribute('data-wrap-source');
|
|
203
203
|
if (storedSource !== null && storedSource !== '') {
|
|
@@ -222,12 +222,10 @@ function makeTextEditable(textElement, groupElement) {
|
|
|
222
222
|
input.style.boxSizing = "border-box";
|
|
223
223
|
input.style.overflow = "hidden";
|
|
224
224
|
input.style.resize = "none";
|
|
225
|
-
input.style.whiteSpace = "pre
|
|
225
|
+
input.style.whiteSpace = "pre";
|
|
226
226
|
input.style.minHeight = "1.2em";
|
|
227
227
|
input.style.zIndex = "10000";
|
|
228
228
|
|
|
229
|
-
const svgRect = svg.getBoundingClientRect();
|
|
230
|
-
|
|
231
229
|
// Use the group element's own screenCTM which includes group transform + SVG viewBox transform
|
|
232
230
|
const textBBox = textElement.getBBox();
|
|
233
231
|
let pt = svg.createSVGPoint();
|
|
@@ -241,17 +239,15 @@ function makeTextEditable(textElement, groupElement) {
|
|
|
241
239
|
input.style.top = `${screenPt.y}px`;
|
|
242
240
|
|
|
243
241
|
const svgZoomFactor = svg.getScreenCTM() ? svg.getScreenCTM().a : 1;
|
|
244
|
-
const screenWidth = textBBox.width * svgZoomFactor;
|
|
245
|
-
|
|
246
242
|
input.style.width = "auto";
|
|
247
243
|
input.style.height = "auto";
|
|
248
244
|
|
|
249
|
-
const currentFontSize = textElement.getAttribute("font-size") || "
|
|
245
|
+
const currentFontSize = textElement.getAttribute("font-size") || "20px";
|
|
250
246
|
const currentFontFamily = textElement.getAttribute("font-family") || "lixFont";
|
|
251
247
|
const currentFill = textElement.getAttribute("fill") || "#fff";
|
|
252
248
|
const currentAnchor = textElement.getAttribute("text-anchor") || "start";
|
|
253
249
|
// Scale font-size by zoom so the textarea matches what the user sees on canvas
|
|
254
|
-
const rawSize = parseFloat(currentFontSize) ||
|
|
250
|
+
const rawSize = parseFloat(currentFontSize) || 20;
|
|
255
251
|
const scaledFontSize = `${rawSize * svgZoomFactor}px`;
|
|
256
252
|
|
|
257
253
|
input.style.minWidth = "150px";
|
|
@@ -259,51 +255,31 @@ function makeTextEditable(textElement, groupElement) {
|
|
|
259
255
|
input.style.width = "auto";
|
|
260
256
|
input.style.height = "auto";
|
|
261
257
|
input.style.overflow = "visible";
|
|
262
|
-
input.style.whiteSpace = "pre
|
|
263
|
-
input.style.wordBreak = "
|
|
258
|
+
input.style.whiteSpace = "pre";
|
|
259
|
+
input.style.wordBreak = "normal";
|
|
260
|
+
input.style.overflowWrap = "normal";
|
|
264
261
|
input.style.fontSize = scaledFontSize;
|
|
265
262
|
input.style.fontFamily = currentFontFamily;
|
|
266
263
|
input.style.color = currentFill;
|
|
267
264
|
input.style.lineHeight = "1.2em";
|
|
268
265
|
input.style.textAlign = currentAnchor === "middle" ? "center" : currentAnchor === "end" ? "right" : "left";
|
|
269
266
|
input.style.backgroundColor = "transparent";
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
// the new light canvas. Read the active theme so the dashes stay
|
|
273
|
-
// visible in both modes.
|
|
274
|
-
const _isDark = typeof document !== 'undefined'
|
|
275
|
-
&& document.body
|
|
276
|
-
&& document.body.classList.contains('theme-dark');
|
|
277
|
-
input.style.border = _isDark
|
|
278
|
-
? "1px dashed rgba(255,255,255,0.55)"
|
|
279
|
-
: "1px dashed rgba(40,40,60,0.45)";
|
|
280
|
-
input.style.borderRadius = "3px";
|
|
267
|
+
input.style.border = "none";
|
|
268
|
+
input.style.boxShadow = "none";
|
|
281
269
|
input.style.outline = "none";
|
|
282
270
|
document.body.appendChild(input);
|
|
283
271
|
|
|
284
272
|
const adjustHeight = () => {
|
|
285
273
|
input.style.height = 'auto';
|
|
286
274
|
input.style.height = input.scrollHeight + 'px';
|
|
287
|
-
|
|
288
|
-
if (input.scrollHeight > maxHeight) {
|
|
289
|
-
input.style.height = maxHeight + 'px';
|
|
290
|
-
input.style.overflowY = 'auto';
|
|
291
|
-
} else {
|
|
292
|
-
input.style.overflowY = 'hidden';
|
|
293
|
-
}
|
|
275
|
+
input.style.overflowY = 'hidden';
|
|
294
276
|
};
|
|
295
277
|
|
|
296
278
|
const adjustWidth = () => {
|
|
297
279
|
input.style.width = 'auto';
|
|
298
|
-
const maxWidth = svgRect.width - (screenPt.x);
|
|
299
280
|
const contentWidth = Math.max(input.scrollWidth, 150);
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
input.style.overflowX = 'auto';
|
|
303
|
-
} else {
|
|
304
|
-
input.style.width = contentWidth + 'px';
|
|
305
|
-
input.style.overflowX = 'hidden';
|
|
306
|
-
}
|
|
281
|
+
input.style.width = contentWidth + 'px';
|
|
282
|
+
input.style.overflowX = 'hidden';
|
|
307
283
|
};
|
|
308
284
|
adjustHeight();
|
|
309
285
|
adjustWidth();
|
|
@@ -345,58 +321,12 @@ function makeTextEditable(textElement, groupElement) {
|
|
|
345
321
|
groupElement.style.display = "none";
|
|
346
322
|
}
|
|
347
323
|
|
|
348
|
-
/**
|
|
349
|
-
|
|
350
|
-
*
|
|
351
|
-
* `paint(textElement, source, wrapWidth)` renders the user-typed `source`
|
|
352
|
-
* string into tspans, soft-wrapping any line that exceeds `wrapWidth`
|
|
353
|
-
* pixels (in SVG units). `wrapWidth = null | 0` falls back to the old
|
|
354
|
-
* "explicit newlines only" behaviour so existing text shapes that have
|
|
355
|
-
* never been width-resized look identical.
|
|
356
|
-
*
|
|
357
|
-
* The raw `source` is persisted on the element as `data-wrap-source`
|
|
358
|
-
* so subsequent edits (textarea re-open) and serialisation can rebuild
|
|
359
|
-
* the original content even after auto-wrap inserted line breaks.
|
|
360
|
-
*/
|
|
361
|
-
function measureSegment(text, refTextElement) {
|
|
362
|
-
if (!text) return 0;
|
|
363
|
-
const NS = 'http://www.w3.org/2000/svg';
|
|
364
|
-
const probe = document.createElementNS(NS, 'tspan');
|
|
365
|
-
probe.textContent = text;
|
|
366
|
-
refTextElement.appendChild(probe);
|
|
367
|
-
let width = 0;
|
|
368
|
-
try { width = probe.getComputedTextLength(); } catch {}
|
|
369
|
-
refTextElement.removeChild(probe);
|
|
370
|
-
return width;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
function paintTextContent(textElement, source, wrapWidth) {
|
|
324
|
+
/** Render only explicit editor line breaks; text never soft-wraps. */
|
|
325
|
+
function paintTextContent(textElement, source) {
|
|
374
326
|
while (textElement.firstChild) textElement.removeChild(textElement.firstChild);
|
|
375
327
|
const x = textElement.getAttribute('x') || 0;
|
|
376
328
|
const NS = 'http://www.w3.org/2000/svg';
|
|
377
|
-
const
|
|
378
|
-
const finalLines = [];
|
|
379
|
-
|
|
380
|
-
for (const paragraph of paragraphs) {
|
|
381
|
-
const para = paragraph.replace(/ /g, ' ');
|
|
382
|
-
if (!wrapWidth || wrapWidth <= 0) {
|
|
383
|
-
finalLines.push(para || ' ');
|
|
384
|
-
continue;
|
|
385
|
-
}
|
|
386
|
-
// Word-wrap the paragraph against wrapWidth.
|
|
387
|
-
const words = para.split(/(\s+)/); // keep separators so spacing survives
|
|
388
|
-
let cur = '';
|
|
389
|
-
for (const token of words) {
|
|
390
|
-
const candidate = cur + token;
|
|
391
|
-
if (measureSegment(candidate, textElement) > wrapWidth && cur.trim().length > 0) {
|
|
392
|
-
finalLines.push(cur);
|
|
393
|
-
cur = token.replace(/^\s+/, ''); // drop the leading break-space
|
|
394
|
-
} else {
|
|
395
|
-
cur = candidate;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
finalLines.push(cur.length ? cur : ' ');
|
|
399
|
-
}
|
|
329
|
+
const finalLines = (source || '').split('\n').map((line) => line.replace(/ /g, ' '));
|
|
400
330
|
|
|
401
331
|
finalLines.forEach((line, i) => {
|
|
402
332
|
const tspan = document.createElementNS(NS, 'tspan');
|
|
@@ -407,21 +337,6 @@ function paintTextContent(textElement, source, wrapWidth) {
|
|
|
407
337
|
});
|
|
408
338
|
}
|
|
409
339
|
|
|
410
|
-
function getWrapSource(textElement) {
|
|
411
|
-
const stored = textElement.getAttribute('data-wrap-source');
|
|
412
|
-
if (stored !== null && stored !== '') return stored;
|
|
413
|
-
// Fallback: rebuild from existing tspans (legacy text shapes without
|
|
414
|
-
// the attribute). Join each tspan as a paragraph.
|
|
415
|
-
const tspans = textElement.querySelectorAll('tspan');
|
|
416
|
-
if (tspans.length === 0) return textElement.textContent || '';
|
|
417
|
-
return Array.from(tspans).map((t) => (t.textContent || '').replace(/ /g, ' ')).join('\n');
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
function getWrapWidth(textElement) {
|
|
421
|
-
const v = parseFloat(textElement.getAttribute('data-wrap-width') || '');
|
|
422
|
-
return Number.isFinite(v) && v > 0 ? v : 0;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
340
|
function renderText(input, textElement, deleteIfEmpty = false) {
|
|
426
341
|
if (!input || !document.body.contains(input)) {
|
|
427
342
|
return;
|
|
@@ -479,13 +394,12 @@ function renderText(input, textElement, deleteIfEmpty = false) {
|
|
|
479
394
|
removeSelectionFeedback();
|
|
480
395
|
}
|
|
481
396
|
} else {
|
|
482
|
-
// Persist
|
|
483
|
-
//
|
|
484
|
-
// ones. Then call the shared paint helper \u2014 it falls back to the
|
|
485
|
-
// legacy "explicit newlines only" path when no wrap-width is set.
|
|
397
|
+
// Persist and render only the user's explicit Shift+Enter line
|
|
398
|
+
// breaks. Long lines remain long on the infinite canvas.
|
|
486
399
|
const cleanSource = text.replace(/\u00A0/g, ' ');
|
|
487
400
|
textElement.setAttribute('data-wrap-source', cleanSource);
|
|
488
|
-
|
|
401
|
+
textElement.removeAttribute('data-wrap-width');
|
|
402
|
+
paintTextContent(textElement, cleanSource);
|
|
489
403
|
|
|
490
404
|
gElement.style.display = 'block';
|
|
491
405
|
|
|
@@ -547,18 +461,13 @@ function createSelectionFeedback(groupElement) {
|
|
|
547
461
|
selectionBox.setAttribute("pointer-events", "none");
|
|
548
462
|
groupElement.appendChild(selectionBox);
|
|
549
463
|
|
|
550
|
-
//
|
|
551
|
-
//
|
|
552
|
-
// element; the paint helper re-flows tspans so the text wraps into
|
|
553
|
-
// multiple lines. Corner anchors keep their font-size scaling
|
|
554
|
-
// behaviour.
|
|
464
|
+
// Corner anchors scale font size. Width handles are intentionally
|
|
465
|
+
// omitted because text width is content-driven and never soft-wraps.
|
|
555
466
|
const handlesData = [
|
|
556
467
|
{ name: 'nw', x: selX, y: selY, cursor: 'nwse-resize' },
|
|
557
468
|
{ name: 'ne', x: selX + selWidth, y: selY, cursor: 'nesw-resize' },
|
|
558
469
|
{ name: 'sw', x: selX, y: selY + selHeight, cursor: 'nesw-resize' },
|
|
559
470
|
{ name: 'se', x: selX + selWidth, y: selY + selHeight, cursor: 'nwse-resize' },
|
|
560
|
-
{ name: 'e', x: selX + selWidth, y: selY + selHeight / 2, cursor: 'ew-resize' },
|
|
561
|
-
{ name: 'w', x: selX, y: selY + selHeight / 2, cursor: 'ew-resize' },
|
|
562
471
|
];
|
|
563
472
|
|
|
564
473
|
resizeHandles = {};
|
|
@@ -664,10 +573,6 @@ function updateSelectionFeedback() {
|
|
|
664
573
|
{ name: 'ne', x: selX + selWidth, y: selY },
|
|
665
574
|
{ name: 'sw', x: selX, y: selY + selHeight },
|
|
666
575
|
{ name: 'se', x: selX + selWidth, y: selY + selHeight },
|
|
667
|
-
// Issue #48 bug #5: keep E/W midpoint handles aligned with the
|
|
668
|
-
// resize so they follow the box as it scales.
|
|
669
|
-
{ name: 'e', x: selX + selWidth, y: selY + selHeight / 2 },
|
|
670
|
-
{ name: 'w', x: selX, y: selY + selHeight / 2 },
|
|
671
576
|
];
|
|
672
577
|
|
|
673
578
|
handlesData.forEach(handle => {
|
|
@@ -959,7 +864,6 @@ const handleMouseMove = (event) => {
|
|
|
959
864
|
const startHeight = startBBox.height;
|
|
960
865
|
|
|
961
866
|
let anchorX, anchorY;
|
|
962
|
-
const isEdgeWidth = currentResizeHandle === 'e' || currentResizeHandle === 'w';
|
|
963
867
|
|
|
964
868
|
switch (currentResizeHandle) {
|
|
965
869
|
case 'nw':
|
|
@@ -978,34 +882,8 @@ const handleMouseMove = (event) => {
|
|
|
978
882
|
anchorX = startX;
|
|
979
883
|
anchorY = startY;
|
|
980
884
|
break;
|
|
981
|
-
case 'e':
|
|
982
|
-
anchorX = startX;
|
|
983
|
-
anchorY = startY + startHeight / 2;
|
|
984
|
-
break;
|
|
985
|
-
case 'w':
|
|
986
|
-
anchorX = startX + startWidth;
|
|
987
|
-
anchorY = startY + startHeight / 2;
|
|
988
|
-
break;
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
// Issue #48 phase D follow-up: E/W now drives TRUE word-wrap.
|
|
992
|
-
// The drag distance becomes the wrap-width target; we re-paint
|
|
993
|
-
// the text with the new width and short-circuit the font-size
|
|
994
|
-
// scaling path that the corners use.
|
|
995
|
-
if (isEdgeWidth) {
|
|
996
|
-
const newWrap = Math.abs(currentPoint.x - anchorX);
|
|
997
|
-
const minWrap = startFontSize * 2; // at least ~one short word wide
|
|
998
|
-
const clampedWrap = Math.max(minWrap, newWrap);
|
|
999
|
-
textElement.setAttribute('data-wrap-width', String(clampedWrap));
|
|
1000
|
-
const source = getWrapSource(textElement);
|
|
1001
|
-
paintTextContent(textElement, source, clampedWrap);
|
|
1002
|
-
if (typeof updateSelectionFeedback === 'function') {
|
|
1003
|
-
setTimeout(updateSelectionFeedback, 0);
|
|
1004
|
-
}
|
|
1005
|
-
return;
|
|
1006
885
|
}
|
|
1007
886
|
|
|
1008
|
-
const newWidth = Math.abs(currentPoint.x - anchorX);
|
|
1009
887
|
const newHeight = Math.abs(currentPoint.y - anchorY);
|
|
1010
888
|
const chosenScale = newHeight / startHeight;
|
|
1011
889
|
|
|
@@ -1040,14 +918,6 @@ const handleMouseMove = (event) => {
|
|
|
1040
918
|
newAnchorX = currentBBox.x;
|
|
1041
919
|
newAnchorY = currentBBox.y;
|
|
1042
920
|
break;
|
|
1043
|
-
case 'e':
|
|
1044
|
-
newAnchorX = currentBBox.x;
|
|
1045
|
-
newAnchorY = currentBBox.y + currentBBox.height / 2;
|
|
1046
|
-
break;
|
|
1047
|
-
case 'w':
|
|
1048
|
-
newAnchorX = currentBBox.x + currentBBox.width;
|
|
1049
|
-
newAnchorY = currentBBox.y + currentBBox.height / 2;
|
|
1050
|
-
break;
|
|
1051
921
|
}
|
|
1052
922
|
|
|
1053
923
|
const deltaX = anchorX - newAnchorX;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/SketchEngine.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable */\n/**\n * SketchEngine - Main engine entry point\n *\n * Initializes the SVG canvas, sets up global state (including RoughJS from npm),\n * then dynamically imports all tool and shape modules.\n *\n * IMPORTANT: All globals must be set BEFORE importing modules, because many\n * modules run code at the top level (e.g. `const rc = rough.svg(svg)`) that\n * depends on these globals existing.\n */\n\nimport rough from 'roughjs';\n\nclass SketchEngine {\n constructor(svgElement, options = {}) {\n if (!svgElement || svgElement.tagName !== 'svg') {\n throw new Error('SketchEngine requires an SVG element');\n }\n\n this.svg = svgElement;\n // Prevent default touch scrolling/gestures on the canvas to allow for custom pointer events\n this.svg.style.touchAction = 'none';\n\n this.options = {\n initialZoom: 1,\n minZoom: 0.4,\n maxZoom: 30,\n ...options\n };\n\n // Event callback for framework consumers (React, Vue, vanilla, VS Code, etc.)\n this.onEvent = options.onEvent || (() => {});\n\n // Public API surfaces (populated after init)\n this.scene = null;\n this.shapes = null;\n\n this._modules = {};\n this._initialized = false;\n }\n\n /**\n * Emit an event to the consumer callback.\n * @param {string} type - Event type (e.g. 'sidebar:select', 'zoom:change')\n * @param {*} data - Event payload\n */\n emit(type, data) {\n try { this.onEvent(type, data); } catch (e) { console.warn('[SketchEngine] onEvent error:', e); }\n }\n\n /**\n * Set up all the global variables that the tool/shape modules depend on.\n * Must be called BEFORE any module imports.\n */\n _initGlobals() {\n // Core SVG reference\n window.svg = this.svg;\n window.freehandCanvas = this.svg;\n\n // RoughJS from npm\n window.rough = rough;\n window.roughCanvas = rough.svg(this.svg);\n window.roughGenerator = window.roughCanvas.generator;\n\n // Shape storage\n window.shapes = window.shapes || [];\n window.currentShape = window.currentShape || null;\n window.lastMousePos = window.lastMousePos || null;\n\n // Zoom state\n window.currentZoom = this.options.initialZoom;\n window.minScale = this.options.minZoom;\n window.maxScale = this.options.maxZoom;\n window.minZoom = this.options.minZoom;\n window.maxZoom = this.options.maxZoom;\n\n // ViewBox state\n window.currentViewBox = window.currentViewBox || {\n x: 0, y: 0,\n width: window.innerWidth,\n height: window.innerHeight\n };\n\n // Tool activation flags\n window.isPaintToolActive = false;\n window.isTextToolActive = false;\n window.isCircleToolActive = false;\n window.isSquareToolActive = false;\n window.isLaserToolActive = false;\n window.isEraserToolActive = false;\n window.isImageToolActive = false;\n window.isArrowToolActive = false;\n window.isLineToolActive = false;\n window.isSelectionToolActive = true;\n window.isPanningToolActive = false;\n window.isFrameToolActive = false;\n window.isIconToolActive = false;\n window.isCodeToolActive = false;\n window.isTextInCodeMode = false;\n\n // Pan state\n window.isPanning = false;\n window.panStart = null;\n window.startCanvasX = 0;\n window.startCanvasY = 0;\n\n // Transform state\n window.currentMatrix = new DOMMatrix();\n window.currentTranslation = { x: 0, y: 0 };\n\n // Action type constants\n window.ACTION_CREATE = 'create';\n window.ACTION_DELETE = 'delete';\n window.ACTION_MODIFY = 'modify';\n window.ACTION_PASTE = 'paste';\n\n // History stacks\n window.historyStack = window.historyStack || [];\n window.redoStack = window.redoStack || [];\n\n // Sidebar element stubs \u2014 React sidebars handle UI, but legacy code\n // queries these at top level. Provide dummy elements so it doesn't crash.\n const dummyEl = document.createElement('div');\n dummyEl.classList.add('hidden');\n window.paintBrushSideBar = document.getElementById('paintBrushToolBar') || dummyEl;\n window.lineSideBar = document.getElementById('lineSideBar') || dummyEl;\n window.squareSideBar = document.getElementById('squareSideBar') || dummyEl;\n window.circleSideBar = document.getElementById('circleSideBar') || dummyEl;\n window.arrowSideBar = document.getElementById('arrowSideBar') || dummyEl;\n window.textSideBar = document.getElementById('textToolBar') || dummyEl;\n window.frameSideBar = document.getElementById('frameSideBar') || dummyEl;\n\n // Zoom control element refs\n window.zoomInBtn = document.getElementById('zoomIn') || dummyEl;\n window.zoomOutBtn = document.getElementById('zoomOut') || dummyEl;\n window.zoomPercentSpan = document.getElementById('zoomPercent') || dummyEl;\n\n // Container\n window.container = document.querySelector('.container') || document.body;\n\n // Sidebar control \u2014 bridge legacy code to consumer UI\n const engine = this;\n window.disableAllSideBars = function() {\n // Hide all legacy sidebar elements\n [window.paintBrushSideBar, window.lineSideBar, window.squareSideBar,\n window.circleSideBar, window.arrowSideBar, window.textSideBar, window.frameSideBar\n ].forEach(el => { if (el) el.classList.add('hidden'); });\n // Notify consumer via onEvent + legacy bridge\n engine.emit('sidebar:clear');\n if (window.__sketchStoreApi) {\n window.__sketchStoreApi.clearSelectedShapeSidebar();\n }\n };\n\n // toolExtraPopup \u2014 legacy UI function, no-op in React\n window.toolExtraPopup = window.toolExtraPopup || function() {};\n\n // updateUndoRedoButtons \u2014 legacy UI function, no-op in React\n window.updateUndoRedoButtons = window.updateUndoRedoButtons || function() {};\n\n // Bridge for shape selection -> consumer UI\n // Maps shape.shapeName to the sidebar key\n window.__showSidebarForShape = function(shapeName) {\n const sidebarMap = {\n 'rectangle': 'rectangle',\n 'circle': 'circle',\n 'arrow': 'arrow',\n 'line': 'line',\n 'freehandStroke': 'paintbrush',\n 'text': 'text',\n 'code': 'text',\n 'frame': 'frame',\n 'image': 'image',\n };\n const sidebar = sidebarMap[shapeName];\n // Emit to consumer callback\n engine.emit('sidebar:select', { sidebar, shapeName });\n // Legacy bridge for React\n if (sidebar && window.__sketchStoreApi) {\n window.__sketchStoreApi.setSelectedShapeSidebar(sidebar);\n }\n window.__selectedShapeIsCode = (shapeName === 'code');\n if (window.__onCodeModeChanged) window.__onCodeModeChanged(shapeName === 'code');\n };\n }\n\n /**\n * Initialize engine: set globals first, then import modules.\n */\n async init() {\n if (this._initialized) return;\n\n // CRITICAL: Set up ALL globals BEFORE importing modules\n this._initGlobals();\n\n try {\n // Import shape classes first\n const [\n { Rectangle },\n { Circle },\n { Arrow },\n { Line },\n { TextShape },\n { CodeShape },\n { ImageShape },\n { IconShape },\n { Frame },\n { FreehandStroke }\n ] = await Promise.all([\n import('./shapes/Rectangle.js'),\n import('./shapes/Circle.js'),\n import('./shapes/Arrow.js'),\n import('./shapes/Line.js'),\n import('./shapes/TextShape.js'),\n import('./shapes/CodeShape.js'),\n import('./shapes/ImageShape.js'),\n import('./shapes/IconShape.js'),\n import('./shapes/Frame.js'),\n import('./shapes/FreehandStroke.js')\n ]);\n\n // Expose shape classes globally\n window.Rectangle = Rectangle;\n window.Circle = Circle;\n window.Arrow = Arrow;\n window.Line = Line;\n window.TextShape = TextShape;\n window.CodeShape = CodeShape;\n window.ImageShape = ImageShape;\n window.IconShape = IconShape;\n window.Frame = Frame;\n window.FreehandStroke = FreehandStroke;\n\n this._modules.shapes = {\n Rectangle, Circle, Arrow, Line,\n TextShape, CodeShape, ImageShape, IconShape,\n Frame, FreehandStroke\n };\n\n // Expose restore as soon as the shape constructors are ready.\n // Tool handlers, AI/graph renderers, and LixScript are not needed\n // to deserialize a cached scene, so keeping the serializer behind\n // those chunks unnecessarily delayed first canvas paint.\n const sceneSerializer = await import('./core/SceneSerializer.js');\n if (sceneSerializer.initSceneSerializer) sceneSerializer.initSceneSerializer();\n\n // Import tool handlers (they run top-level code that reads globals)\n const [\n rectangleTool, circleTool, arrowTool, lineTool,\n textTool, codeTool, imageTool, iconTool,\n frameTool, freehandTool\n ] = await Promise.all([\n import('./tools/rectangleTool.js'),\n import('./tools/circleTool.js'),\n import('./tools/arrowTool.js'),\n import('./tools/lineTool.js'),\n import('./tools/textTool.js'),\n import('./tools/codeTool.js'),\n import('./tools/imageTool.js'),\n import('./tools/iconTool.js'),\n import('./tools/frameTool.js'),\n import('./tools/freehandTool.js')\n ]);\n\n this._modules.tools = {\n rectangleTool, circleTool, arrowTool, lineTool,\n textTool, codeTool, imageTool, iconTool,\n frameTool, freehandTool\n };\n\n // Import core modules (EventDispatcher attaches SVG listeners at top level)\n const [\n eventDispatcher, undoRedo, selection,\n zoomPan, copyPaste, eraserTrail,\n resizeShapes, resizeCode\n ] = await Promise.all([\n import('./core/EventDispatcher.js'),\n import('./core/UndoRedo.js'),\n import('./core/Selection.js'),\n import('./core/ZoomPan.js'),\n import('./core/CopyPaste.js'),\n import('./core/EraserTrail.js'),\n import('./core/ResizeShapes.js'),\n import('./core/ResizeCode.js')\n ]);\n\n this._modules.core = {\n eventDispatcher, undoRedo, selection,\n zoomPan, copyPaste, eraserTrail,\n resizeShapes, resizeCode\n };\n\n // Re-bind event listeners to the current SVG element\n if (eventDispatcher.initEventDispatcher) {\n eventDispatcher.initEventDispatcher(this.svg);\n }\n\n // Import standalone tools\n await Promise.all([\n import('./tools/eraserTool.js'),\n import('./tools/laserTool.js')\n ]);\n\n // Expose key functions globally\n if (undoRedo.undo) window.undo = undoRedo.undo;\n if (undoRedo.redo) window.redo = undoRedo.redo;\n if (undoRedo.pushCreateAction) window.pushCreateAction = undoRedo.pushCreateAction;\n if (undoRedo.pushDeleteAction) window.pushDeleteAction = undoRedo.pushDeleteAction;\n if (selection.multiSelection) window.multiSelection = selection.multiSelection;\n if (selection.clearAllSelections) window.clearAllSelections = selection.clearAllSelections;\n\n // Initialize centralized copy/paste system\n if (copyPaste.initCopyPaste) copyPaste.initCopyPaste();\n\n // Initialize AI renderer bridge\n const aiRenderer = await import('./core/AIRenderer.js');\n if (aiRenderer.initAIRenderer) aiRenderer.initAIRenderer();\n\n // Initialize graph engine bridge\n const graphEngine = await import('./core/GraphEngine.js');\n if (graphEngine.initGraphEngine) graphEngine.initGraphEngine();\n\n // Initialize layer ordering\n const layerOrder = await import('./core/LayerOrder.js');\n if (layerOrder.initLayerOrder) layerOrder.initLayerOrder();\n\n // Initialize LixScript programmatic diagram engine\n const lixScript = await import('./core/LixScriptParser.js');\n if (lixScript.initLixScriptBridge) lixScript.initLixScriptBridge();\n\n // \u2500\u2500 Public API surfaces \u2500\u2500\n\n // Scene operations (save, load, export, etc.)\n this.scene = window.__sceneSerializer || {\n save: sceneSerializer.saveScene,\n load: sceneSerializer.loadScene,\n download: sceneSerializer.downloadScene,\n upload: sceneSerializer.uploadScene,\n exportPNG: sceneSerializer.exportAsPNG,\n exportPDF: sceneSerializer.exportAsPDF,\n copyAsPNG: sceneSerializer.copyAsPNG,\n copyAsSVG: sceneSerializer.copyAsSVG,\n reset: sceneSerializer.resetCanvas,\n findText: sceneSerializer.findTextOnCanvas,\n };\n\n // Shape array reference\n this.shapes = window.shapes;\n\n // Undo/redo\n this.undo = undoRedo.undo || (() => {});\n this.redo = undoRedo.redo || (() => {});\n\n // LixScript execution\n this.lixscript = {\n parse: lixScript.parseLixScript || (() => null),\n execute: lixScript.executeLixScript || (lixScript.parseLixScript ? (code) => {\n const parsed = lixScript.parseLixScript(code);\n if (parsed && lixScript.resolveShapeRefs) lixScript.resolveShapeRefs(parsed);\n return parsed;\n } : (() => null)),\n };\n\n // Store module refs for advanced consumers\n this._modules.sceneSerializer = sceneSerializer;\n this._modules.lixScript = lixScript;\n\n this._initialized = true;\n console.log('[SketchEngine] Initialized successfully');\n } catch (err) {\n console.error('[SketchEngine] Initialization failed:', err);\n throw err;\n }\n }\n\n /**\n * Sync tool flags from Zustand activeTool value.\n */\n setActiveTool(toolName) {\n // Deselect current shape when switching tools\n if (window.currentShape && typeof window.currentShape.removeSelection === 'function') {\n window.currentShape.removeSelection();\n window.currentShape = null;\n }\n if (typeof window.clearAllSelections === 'function') {\n window.clearAllSelections();\n }\n if (typeof window.disableAllSideBars === 'function') {\n window.disableAllSideBars();\n }\n\n // Force cleanup eraser trail when switching tools\n if (typeof window.forceCleanupEraserTrail === 'function') {\n window.forceCleanupEraserTrail();\n }\n // Clean up any lingering icon miniature/drag state\n if (typeof window.__cleanupIconTool === 'function') {\n window.__cleanupIconTool();\n }\n\n window.isPaintToolActive = false;\n window.isSquareToolActive = false;\n window.isCircleToolActive = false;\n window.isArrowToolActive = false;\n window.isTextToolActive = false;\n window.isLaserToolActive = false;\n window.isLineToolActive = false;\n window.isEraserToolActive = false;\n window.isSelectionToolActive = false;\n window.isImageToolActive = false;\n window.isPanningToolActive = false;\n window.isFrameToolActive = false;\n window.isIconToolActive = false;\n window.isCodeToolActive = false;\n\n const flagMap = {\n select: 'isSelectionToolActive',\n pan: 'isPanningToolActive',\n rectangle: 'isSquareToolActive',\n circle: 'isCircleToolActive',\n line: 'isLineToolActive',\n arrow: 'isArrowToolActive',\n freehand: 'isPaintToolActive',\n text: 'isTextToolActive',\n code: 'isCodeToolActive',\n eraser: 'isEraserToolActive',\n laser: 'isLaserToolActive',\n image: 'isImageToolActive',\n frame: 'isFrameToolActive',\n icon: 'isIconToolActive',\n };\n\n const flag = flagMap[toolName];\n if (flag) window[flag] = true;\n\n if (toolName === 'text' && window.isTextInCodeMode) {\n window.isCodeToolActive = true;\n }\n\n // Show image source picker when image tool is activated\n if (toolName === 'image' && window.__showImageSourcePicker) {\n window.__showImageSourcePicker();\n }\n\n // Set appropriate cursor for the active tool\n const cursorMap = {\n select: 'default',\n pan: 'grab',\n rectangle: 'crosshair',\n circle: 'crosshair',\n line: 'crosshair',\n arrow: 'crosshair',\n freehand: 'crosshair',\n text: 'crosshair',\n code: 'crosshair',\n eraser: 'crosshair',\n laser: 'crosshair',\n image: 'crosshair',\n frame: 'crosshair',\n icon: 'crosshair',\n };\n if (this.svg) {\n this.svg.style.cursor = cursorMap[toolName] || 'default';\n }\n }\n\n cleanup() {\n // Remove event listeners from the SVG element\n if (this._modules.core?.eventDispatcher?.cleanupEventDispatcher) {\n this._modules.core.eventDispatcher.cleanupEventDispatcher();\n }\n window.shapes = [];\n window.currentShape = null;\n window.lastMousePos = null;\n this._modules = {};\n this._initialized = false;\n console.log('[SketchEngine] Cleaned up');\n }\n}\n\nexport { SketchEngine };\nexport default SketchEngine;\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/shapes/TextShape.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable */\n// TextShape class - extracted from writeText.js\n// Depends on globals: svg, shapes, currentShape\n\nfunction extractRotationFromTransform(el) {\n const t = el.getAttribute(\"transform\") || \"\";\n const m = t.match(/rotate\\(([^,)]+)/);\n return m ? parseFloat(m[1]) : 0;\n}\nfunction updateAttachedArrows(wrapper) {\n if (!wrapper || typeof shapes === \"undefined\") return;\n shapes.forEach(s => {\n if (s && s.shapeName === \"arrow\" && typeof s.updateAttachments === \"function\") {\n if ((s.attachedToStart && s.attachedToStart.shape === wrapper) ||\n (s.attachedToEnd && s.attachedToEnd.shape === wrapper)) {\n s.updateAttachments();\n }\n }\n });\n}\nlet isDragging = false;\nlet hoveredFrameText = null;\nlet selectedElement = null;\nfunction updateSelectionFeedback() {}\nfunction deselectElement() { selectedElement = null; }\nfunction selectElement(el) { selectedElement = el; }\n\nclass TextShape {\n constructor(groupElement) {\n this.group = groupElement;\n this.shapeName = 'text';\n this.shapeID = groupElement.getAttribute('id') || `text-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n \n // Frame attachment properties\n this.parentFrame = null;\n \n // Update group attributes \u2014 ensure data-type is set for textTool interaction\n this.group.setAttribute('type', 'text');\n this.group.setAttribute('data-type', 'text-group');\n this.group.shapeName = 'text';\n this.group.shapeID = this.shapeID;\n }\n \n // Position and dimension properties for frame compatibility\n get x() {\n const transform = this.group.transform.baseVal.consolidate();\n return transform ? transform.matrix.e : parseFloat(this.group.getAttribute('data-x')) || 0;\n }\n \n set x(value) {\n const transform = this.group.transform.baseVal.consolidate();\n const currentY = transform ? transform.matrix.f : parseFloat(this.group.getAttribute('data-y')) || 0;\n const rotation = extractRotationFromTransform(this.group) || 0;\n const textElement = this.group.querySelector('text');\n if (textElement) {\n const bbox = textElement.getBBox();\n const centerX = bbox.x + bbox.width / 2;\n const centerY = bbox.y + bbox.height / 2;\n this.group.setAttribute('transform', `translate(${value}, ${currentY}) rotate(${rotation}, ${centerX}, ${centerY})`);\n } else {\n this.group.setAttribute('transform', `translate(${value}, ${currentY})`);\n }\n this.group.setAttribute('data-x', value);\n }\n \n get y() {\n const transform = this.group.transform.baseVal.consolidate();\n return transform ? transform.matrix.f : parseFloat(this.group.getAttribute('data-y')) || 0;\n }\n \n set y(value) {\n const transform = this.group.transform.baseVal.consolidate();\n const currentX = transform ? transform.matrix.e : parseFloat(this.group.getAttribute('data-x')) || 0;\n const rotation = extractRotationFromTransform(this.group) || 0;\n const textElement = this.group.querySelector('text');\n if (textElement) {\n const bbox = textElement.getBBox();\n const centerX = bbox.x + bbox.width / 2;\n const centerY = bbox.y + bbox.height / 2;\n this.group.setAttribute('transform', `translate(${currentX}, ${value}) rotate(${rotation}, ${centerX}, ${centerY})`);\n } else {\n this.group.setAttribute('transform', `translate(${currentX}, ${value})`);\n }\n this.group.setAttribute('data-y', value);\n }\n \n get width() {\n const textElement = this.group.querySelector('text');\n if (textElement) {\n return textElement.getBBox().width;\n }\n return 0;\n }\n \n set width(value) {\n // Text width is determined by content and font size, not directly settable\n // This is here for frame compatibility but doesn't change the text\n }\n \n get height() {\n const textElement = this.group.querySelector('text');\n if (textElement) {\n return textElement.getBBox().height;\n }\n return 0;\n }\n \n set height(value) {\n // Text height is determined by content and font size, not directly settable\n // This is here for frame compatibility but doesn't change the text\n }\n \n get rotation() {\n return extractRotationFromTransform(this.group) || 0;\n }\n \n set rotation(value) {\n const currentTransform = this.group.transform.baseVal.consolidate();\n const currentX = currentTransform ? currentTransform.matrix.e : 0;\n const currentY = currentTransform ? currentTransform.matrix.f : 0;\n const textElement = this.group.querySelector('text');\n if (textElement) {\n const bbox = textElement.getBBox();\n const centerX = bbox.x + bbox.width / 2;\n const centerY = bbox.y + bbox.height / 2;\n this.group.setAttribute('transform', `translate(${currentX}, ${currentY}) rotate(${value}, ${centerX}, ${centerY})`);\n }\n }\n\n move(dx, dy) {\n const currentTransform = this.group.transform.baseVal.consolidate();\n const currentX = currentTransform ? currentTransform.matrix.e : 0;\n const currentY = currentTransform ? currentTransform.matrix.f : 0;\n\n this.x = currentX + dx;\n this.y = currentY + dy;\n\n // Only update frame containment if we're actively dragging the shape itself\n // and not being moved by a parent frame\n if (isDragging && !this.isBeingMovedByFrame) {\n this.updateFrameContainment();\n }\n\n this.updateAttachedArrows();\n }\n\n updateAttachedArrows() {\n updateAttachedArrows(this);\n }\n\n updateFrameContainment() {\n // Don't update if we're being moved by a frame\n if (this.isBeingMovedByFrame) return;\n \n let targetFrame = null;\n \n // Find which frame this shape is over\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.forEach(shape => {\n if (shape.shapeName === 'frame' && shape.isShapeInFrame(this)) {\n targetFrame = shape;\n }\n });\n }\n \n // If we have a parent frame and we're being dragged, temporarily remove clipping\n if (this.parentFrame && isDragging) {\n this.parentFrame.temporarilyRemoveFromFrame(this);\n }\n \n // Update frame highlighting\n if (hoveredFrameText && hoveredFrameText !== targetFrame) {\n hoveredFrameText.removeHighlight();\n }\n \n if (targetFrame && targetFrame !== hoveredFrameText) {\n targetFrame.highlightFrame();\n }\n \n hoveredFrameText = targetFrame;\n }\n\n contains(x, y) {\n const textElement = this.group.querySelector('text');\n if (!textElement || typeof textElement.getBBox !== 'function') return false;\n\n let bbox;\n try { bbox = textElement.getBBox(); } catch { return false; }\n const padding = 8; // Selection padding\n\n const CTM = this.group.getCTM();\n if (!CTM) return false;\n \n const inverseCTM = CTM.inverse();\n const svgPoint = svg.createSVGPoint();\n svgPoint.x = x;\n svgPoint.y = y;\n const transformedPoint = svgPoint.matrixTransform(inverseCTM);\n \n return transformedPoint.x >= bbox.x - padding && \n transformedPoint.x <= bbox.x + bbox.width + padding &&\n transformedPoint.y >= bbox.y - padding && \n transformedPoint.y <= bbox.y + bbox.height + padding;\n }\n\n // Add draw method for consistency with other shapes\n draw() {\n // Text doesn't need redrawing like other shapes, but we need this method for consistency\n if (selectedElement === this.group) {\n updateSelectionFeedback();\n }\n }\n\n // Add methods for frame compatibility\n removeSelection() {\n if (selectedElement === this.group) {\n deselectElement();\n }\n }\n\n selectShape() {\n // Use the real textTool selectElement (with selection feedback) if available\n if (typeof window !== 'undefined' && window.__selectTextElement) {\n window.__selectTextElement(this.group);\n } else {\n selectElement(this.group);\n }\n }\n}\n\nexport { TextShape };\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|