@elixpo/lixsketch 5.4.7 → 5.5.0
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/AIRenderer-M4LMJ66J.js +1105 -0
- package/dist/react/AIRenderer-M4LMJ66J.js.map +7 -0
- package/dist/react/Arrow-BJDAXPMH.js +8 -0
- package/dist/react/Arrow-BJDAXPMH.js.map +7 -0
- package/dist/react/Circle-KPG7TKIX.js +8 -0
- package/dist/react/Circle-KPG7TKIX.js.map +7 -0
- package/dist/react/CodeShape-K4DIZAIV.js +8 -0
- package/dist/react/CodeShape-K4DIZAIV.js.map +7 -0
- package/dist/react/CopyPaste-4CKJRHJ3.js +569 -0
- package/dist/react/CopyPaste-4CKJRHJ3.js.map +7 -0
- package/dist/react/EraserTrail-PA6IQLQN.js +20 -0
- package/dist/react/EraserTrail-PA6IQLQN.js.map +7 -0
- package/dist/react/EventDispatcher-SRFH6LQZ.js +463 -0
- package/dist/react/EventDispatcher-SRFH6LQZ.js.map +7 -0
- package/dist/react/Frame-6UR5XPAX.js +10 -0
- package/dist/react/Frame-6UR5XPAX.js.map +7 -0
- package/dist/react/FreehandStroke-CK24NUT3.js +8 -0
- package/dist/react/FreehandStroke-CK24NUT3.js.map +7 -0
- package/dist/react/GraphEngine-QE5B2PMR.js +340 -0
- package/dist/react/GraphEngine-QE5B2PMR.js.map +7 -0
- package/dist/react/GraphMathParser-2WMTY4IE.js +10 -0
- package/dist/react/GraphMathParser-2WMTY4IE.js.map +7 -0
- package/dist/react/IconShape-KMIA6T2H.js +10 -0
- package/dist/react/IconShape-KMIA6T2H.js.map +7 -0
- package/dist/react/ImageShape-CHHGBXUQ.js +10 -0
- package/dist/react/ImageShape-CHHGBXUQ.js.map +7 -0
- package/dist/react/LayerOrder-XCHF4MSS.js +66 -0
- package/dist/react/LayerOrder-XCHF4MSS.js.map +7 -0
- package/dist/react/Line-2KOQEEGA.js +10 -0
- package/dist/react/Line-2KOQEEGA.js.map +7 -0
- package/dist/react/LixScriptParser-JYWJX375.js +1033 -0
- package/dist/react/LixScriptParser-JYWJX375.js.map +7 -0
- package/dist/react/MermaidFlowchartRenderer-4QBAZ5MB.js +412 -0
- package/dist/react/MermaidFlowchartRenderer-4QBAZ5MB.js.map +7 -0
- package/dist/react/MermaidSequenceParser-UKG2NSZY.js +8 -0
- package/dist/react/MermaidSequenceParser-UKG2NSZY.js.map +7 -0
- package/dist/react/MermaidSequenceRenderer-HPLHY5II.js +387 -0
- package/dist/react/MermaidSequenceRenderer-HPLHY5II.js.map +7 -0
- package/dist/react/Rectangle-6FE7RN6W.js +8 -0
- package/dist/react/Rectangle-6FE7RN6W.js.map +7 -0
- package/dist/react/ResizeCode-WAMDTKSW.js +2 -0
- package/dist/react/ResizeCode-WAMDTKSW.js.map +7 -0
- package/dist/react/ResizeShapes-LKEQTITP.js +250 -0
- package/dist/react/ResizeShapes-LKEQTITP.js.map +7 -0
- package/dist/react/SceneSerializer-4U4B24JM.js +739 -0
- package/dist/react/SceneSerializer-4U4B24JM.js.map +7 -0
- package/dist/react/Selection-VVUHY5YJ.js +34 -0
- package/dist/react/Selection-VVUHY5YJ.js.map +7 -0
- package/dist/react/SketchEngine-YA4RG3KX.js +413 -0
- package/dist/react/SketchEngine-YA4RG3KX.js.map +7 -0
- package/dist/react/TextShape-54ZJ66E3.js +8 -0
- package/dist/react/TextShape-54ZJ66E3.js.map +7 -0
- package/dist/react/UndoRedo-M2JZUBKN.js +30 -0
- package/dist/react/UndoRedo-M2JZUBKN.js.map +7 -0
- package/dist/react/ZoomPan-U3TXC5AJ.js +186 -0
- package/dist/react/ZoomPan-U3TXC5AJ.js.map +7 -0
- package/dist/react/arrowTool-CWEMIRXK.js +17 -0
- package/dist/react/arrowTool-CWEMIRXK.js.map +7 -0
- package/dist/react/boxicons-5JNJQPUP.woff +0 -0
- package/dist/react/boxicons-6NVWQSCQ.eot +0 -0
- package/dist/react/boxicons-AQ5N6WP7.woff2 +0 -0
- package/dist/react/boxicons-GDR4JU3X.ttf +0 -0
- package/dist/react/boxicons-NNFHLMOR.svg +1660 -0
- package/dist/react/chunk-2OQXI7QB.js +564 -0
- package/dist/react/chunk-2OQXI7QB.js.map +7 -0
- package/dist/react/chunk-5OUBTHHO.js +187 -0
- package/dist/react/chunk-5OUBTHHO.js.map +7 -0
- package/dist/react/chunk-6PFXZKL2.js +628 -0
- package/dist/react/chunk-6PFXZKL2.js.map +7 -0
- package/dist/react/chunk-6SFNWGGZ.js +453 -0
- package/dist/react/chunk-6SFNWGGZ.js.map +7 -0
- package/dist/react/chunk-7TZSIR6V.js +210 -0
- package/dist/react/chunk-7TZSIR6V.js.map +7 -0
- package/dist/react/chunk-AJAZC37E.js +662 -0
- package/dist/react/chunk-AJAZC37E.js.map +7 -0
- package/dist/react/chunk-BU4D2WYQ.js +1213 -0
- package/dist/react/chunk-BU4D2WYQ.js.map +7 -0
- package/dist/react/chunk-BZE4CEBG.js +747 -0
- package/dist/react/chunk-BZE4CEBG.js.map +7 -0
- package/dist/react/chunk-CB2RANCB.js +212 -0
- package/dist/react/chunk-CB2RANCB.js.map +7 -0
- package/dist/react/chunk-DNAG7ML6.js +128 -0
- package/dist/react/chunk-DNAG7ML6.js.map +7 -0
- package/dist/react/chunk-HZWLPXFN.js +198 -0
- package/dist/react/chunk-HZWLPXFN.js.map +7 -0
- package/dist/react/chunk-I6HCCIXB.js +572 -0
- package/dist/react/chunk-I6HCCIXB.js.map +7 -0
- package/dist/react/chunk-IZ5OGWGW.js +235 -0
- package/dist/react/chunk-IZ5OGWGW.js.map +7 -0
- package/dist/react/chunk-JJCJNLNN.js +1490 -0
- package/dist/react/chunk-JJCJNLNN.js.map +7 -0
- package/dist/react/chunk-JQ3IRFDP.js +222 -0
- package/dist/react/chunk-JQ3IRFDP.js.map +7 -0
- package/dist/react/chunk-L5OARZJ7.js +1134 -0
- package/dist/react/chunk-L5OARZJ7.js.map +7 -0
- package/dist/react/chunk-LHRTXNVE.js +1600 -0
- package/dist/react/chunk-LHRTXNVE.js.map +7 -0
- package/dist/react/chunk-Q2GA4MBZ.js +1653 -0
- package/dist/react/chunk-Q2GA4MBZ.js.map +7 -0
- package/dist/react/chunk-QNSE5BAY.js +519 -0
- package/dist/react/chunk-QNSE5BAY.js.map +7 -0
- package/dist/react/chunk-QXFBG7OM.js +191 -0
- package/dist/react/chunk-QXFBG7OM.js.map +7 -0
- package/dist/react/chunk-T6ZVV5ZO.js +714 -0
- package/dist/react/chunk-T6ZVV5ZO.js.map +7 -0
- package/dist/react/chunk-URB6MY46.js +974 -0
- package/dist/react/chunk-URB6MY46.js.map +7 -0
- package/dist/react/chunk-VN62KLOC.js +931 -0
- package/dist/react/chunk-VN62KLOC.js.map +7 -0
- package/dist/react/chunk-VQVEPJSA.js +158 -0
- package/dist/react/chunk-VQVEPJSA.js.map +7 -0
- package/dist/react/chunk-XISEAGBV.js +1632 -0
- package/dist/react/chunk-XISEAGBV.js.map +7 -0
- package/dist/react/chunk-YKJUBFHE.js +575 -0
- package/dist/react/chunk-YKJUBFHE.js.map +7 -0
- package/dist/react/circleTool-NUATSEI2.js +14 -0
- package/dist/react/circleTool-NUATSEI2.js.map +7 -0
- package/dist/react/codeTool-MHCB2FNB.js +38 -0
- package/dist/react/codeTool-MHCB2FNB.js.map +7 -0
- package/dist/react/eraserTool-2GS2LQCS.js +103 -0
- package/dist/react/eraserTool-2GS2LQCS.js.map +7 -0
- package/dist/react/frameTool-PWVKKXSP.js +14 -0
- package/dist/react/frameTool-PWVKKXSP.js.map +7 -0
- package/dist/react/freehandTool-SLYGASVP.js +14 -0
- package/dist/react/freehandTool-SLYGASVP.js.map +7 -0
- package/dist/react/iconTool-GPZ7O7NH.js +18 -0
- package/dist/react/iconTool-GPZ7O7NH.js.map +7 -0
- package/dist/react/imageTool-D5R4XGEU.js +15 -0
- package/dist/react/imageTool-D5R4XGEU.js.map +7 -0
- package/dist/react/index.js +5342 -0
- package/dist/react/index.js.map +7 -0
- package/dist/react/laserTool-XVMV63AV.js +239 -0
- package/dist/react/laserTool-XVMV63AV.js.map +7 -0
- package/dist/react/lineTool-WNI5EMZ5.js +14 -0
- package/dist/react/lineTool-WNI5EMZ5.js.map +7 -0
- package/dist/react/lixCode-OJMVUXXI.ttf +0 -0
- package/dist/react/lixDefault-JEAPAUJL.ttf +0 -0
- package/dist/react/lixFancy-BPXYM5CQ.ttf +0 -0
- package/dist/react/lixFont-CPKEUDVM.woff2 +0 -0
- package/dist/react/rectangleTool-U7DZ6ZTA.js +14 -0
- package/dist/react/rectangleTool-U7DZ6ZTA.js.map +7 -0
- package/dist/react/styles.css +6627 -0
- package/dist/react/textTool-M7S6F3VC.js +21 -0
- package/dist/react/textTool-M7S6F3VC.js.map +7 -0
- package/package.json +39 -5
- package/src/EngineShortcuts.js +83 -27
- package/src/core/AIRenderer.js +30 -18
- package/src/core/GraphEngine.js +64 -41
- package/src/core/MermaidFlowchartRenderer.js +153 -88
- package/src/core/MermaidSequenceRenderer.js +168 -93
- package/src/core/SceneSerializer.js +86 -2
- package/src/core/Selection.js +119 -19
- package/src/core/UndoRedo.js +82 -15
- package/src/core/ZoomPan.js +15 -5
- package/src/index.js +14 -1
- package/src/react/LixSketchCanvas.jsx +347 -0
- package/src/react/components/AppMenu.jsx +475 -0
- package/src/react/components/Footer.jsx +85 -0
- package/src/react/components/Toolbar.jsx +140 -0
- package/src/react/components/canvas/CanvasLoadingOverlay.jsx +76 -0
- package/src/react/components/canvas/ContextMenu.jsx +466 -0
- package/src/react/components/canvas/FindBar.jsx +177 -0
- package/src/react/components/canvas/ImageSourcePicker.jsx +133 -0
- package/src/react/components/canvas/MultiSelectActions.jsx +120 -0
- package/src/react/components/canvas/SVGCanvas.jsx +145 -0
- package/src/react/components/canvas/SaveStatusIndicator.jsx +29 -0
- package/src/react/components/modals/CanvasPropertiesModal.jsx +358 -0
- package/src/react/components/modals/CommandPalette.jsx +307 -0
- package/src/react/components/modals/ExportImageModal.jsx +287 -0
- package/src/react/components/modals/GraphModal.jsx +174 -0
- package/src/react/components/modals/HelpModal.jsx +208 -0
- package/src/react/components/modals/LixScriptModal.jsx +130 -0
- package/src/react/components/modals/ShortcutsModal.jsx +125 -0
- package/src/react/components/sidebars/ArrowSidebar.jsx +173 -0
- package/src/react/components/sidebars/CircleSidebar.jsx +134 -0
- package/src/react/components/sidebars/FrameSidebar.jsx +263 -0
- package/src/react/components/sidebars/IconSidebar.jsx +279 -0
- package/src/react/components/sidebars/ImageSidebar.jsx +69 -0
- package/src/react/components/sidebars/LineSidebar.jsx +109 -0
- package/src/react/components/sidebars/PaintbrushSidebar.jsx +119 -0
- package/src/react/components/sidebars/RectangleSidebar.jsx +165 -0
- package/src/react/components/sidebars/ShapeSidebar.jsx +130 -0
- package/src/react/components/sidebars/TextSidebar.jsx +174 -0
- package/src/react/hooks/inertStores.js +58 -0
- package/src/react/hooks/useSketchEngine.js +76 -0
- package/src/react/hooks/useTranslation.js +92 -0
- package/src/react/index.js +41 -0
- package/src/react/store/useSketchStore.js +234 -0
- package/src/react/store/useUIStore.js +196 -0
- package/src/react/styles/arrowSidebar.css +263 -0
- package/src/react/styles/canvasStroke.css +47 -0
- package/src/react/styles/canvasTools.css +769 -0
- package/src/react/styles/circleSidebar.css +206 -0
- package/src/react/styles/fonts/fonts.css +29 -0
- package/src/react/styles/fonts/lixCode.ttf +0 -0
- package/src/react/styles/fonts/lixDefault.ttf +0 -0
- package/src/react/styles/fonts/lixDocs.ttf +0 -0
- package/src/react/styles/fonts/lixFancy.ttf +0 -0
- package/src/react/styles/fonts/lixFont.woff2 +0 -0
- package/src/react/styles/lineSidebar.css +207 -0
- package/src/react/styles/paintbrushSidebar.css +247 -0
- package/src/react/styles/squareSidebar.css +206 -0
- package/src/react/styles/writeText.css +149 -0
- package/src/react/styles.css +175 -0
- package/src/react/toolsEnum.js +20 -0
- package/src/react/utils/toast.js +18 -0
- package/src/shapes/Frame.js +7 -1
- package/src/shapes/Line.js +11 -5
- package/src/tools/arrowTool.js +30 -4
- package/src/tools/circleTool.js +33 -9
- package/src/tools/codeTool.js +5 -3
- package/src/tools/frameTool.js +47 -7
- package/src/tools/freehandTool.js +12 -4
- package/src/tools/iconTool.js +7 -1
- package/src/tools/imageTool.js +7 -1
- package/src/tools/lineTool.js +27 -3
- package/src/tools/rectangleTool.js +45 -8
- package/src/tools/textTool.js +23 -6
package/src/tools/arrowTool.js
CHANGED
|
@@ -4,13 +4,15 @@ import { pushCreateAction, pushDeleteAction, pushOptionsChangeAction, pushTransf
|
|
|
4
4
|
import { calculateSnap, clearSnapGuides } from '../core/SnapGuides.js';
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
function getThemeStroke() { if (typeof document === "undefined") return "#fff"; return document.body && document.body.classList.contains("theme-dark") ? "#fff" : "#1a1a2e"; }
|
|
8
|
+
|
|
7
9
|
let arrowStartX, arrowStartY;
|
|
8
10
|
let currentArrow = null;
|
|
9
11
|
let isResizing = false;
|
|
10
12
|
let isDragging = false;
|
|
11
13
|
let activeAnchor = null;
|
|
12
14
|
let isDrawingArrow = false;
|
|
13
|
-
let arrowStrokeColor =
|
|
15
|
+
let arrowStrokeColor = null;
|
|
14
16
|
let arrowStrokeThickness = 2;
|
|
15
17
|
let arrowOutlineStyle = "solid";
|
|
16
18
|
let arrowCurved = "straight";
|
|
@@ -68,7 +70,7 @@ const handleMouseDown = (e) => {
|
|
|
68
70
|
if (isArrowToolActive) {
|
|
69
71
|
isDrawingArrow = true;
|
|
70
72
|
currentArrow = new Arrow({ x, y }, { x, y }, {
|
|
71
|
-
stroke: arrowStrokeColor,
|
|
73
|
+
stroke: arrowStrokeColor ?? getThemeStroke(),
|
|
72
74
|
strokeWidth: arrowStrokeThickness,
|
|
73
75
|
arrowOutlineStyle: arrowOutlineStyle,
|
|
74
76
|
arrowHeadStyle: arrowHeadStyle,
|
|
@@ -226,6 +228,27 @@ const handleMouseMove = (e) => {
|
|
|
226
228
|
startX = x;
|
|
227
229
|
startY = y;
|
|
228
230
|
|
|
231
|
+
// Issue #24 bug #4: track containing frame during drag of an
|
|
232
|
+
// existing arrow so mouseUp re-parents correctly. Without this
|
|
233
|
+
// hoveredFrameArrow stays null and the arrow is detached the
|
|
234
|
+
// moment the user nudges it inside its own parent frame.
|
|
235
|
+
let newHover = null;
|
|
236
|
+
for (const f of shapes) {
|
|
237
|
+
if (f.shapeName !== 'frame') continue;
|
|
238
|
+
if (f === currentShape) continue;
|
|
239
|
+
if (typeof f.isShapeInFrame === 'function' && f.isShapeInFrame(currentShape)) {
|
|
240
|
+
newHover = f;
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (hoveredFrameArrow && hoveredFrameArrow !== newHover && typeof hoveredFrameArrow.removeHighlight === 'function') {
|
|
245
|
+
hoveredFrameArrow.removeHighlight();
|
|
246
|
+
}
|
|
247
|
+
if (newHover && newHover !== hoveredFrameArrow && typeof newHover.highlightFrame === 'function') {
|
|
248
|
+
newHover.highlightFrame();
|
|
249
|
+
}
|
|
250
|
+
hoveredFrameArrow = newHover;
|
|
251
|
+
|
|
229
252
|
// Snap guides
|
|
230
253
|
if (window.__sketchStoreApi && window.__sketchStoreApi.getState().snapToObjects) {
|
|
231
254
|
const snap = calculateSnap(currentShape, e.shiftKey, e.clientX, e.clientY);
|
|
@@ -319,10 +342,13 @@ if (isDrawingArrow && currentArrow) {
|
|
|
319
342
|
}
|
|
320
343
|
|
|
321
344
|
if (isDragging && dragOldPosArrow && currentShape) {
|
|
345
|
+
// Issue #34 bug #2: containment transfer happens later in this block,
|
|
346
|
+
// so currentShape.parentFrame is still the OLD frame here. hoveredFrameArrow
|
|
347
|
+
// tracks the actual destination during mousemove — use that as the truth.
|
|
322
348
|
const newPos = {
|
|
323
349
|
startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },
|
|
324
350
|
endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },
|
|
325
|
-
parentFrame:
|
|
351
|
+
parentFrame: hoveredFrameArrow || null,
|
|
326
352
|
};
|
|
327
353
|
const oldPos = {
|
|
328
354
|
...dragOldPosArrow,
|
|
@@ -578,4 +604,4 @@ export {
|
|
|
578
604
|
handleMouseUp as handleMouseUpArrow,
|
|
579
605
|
cleanupAttachments,
|
|
580
606
|
updateAttachedArrows
|
|
581
|
-
};
|
|
607
|
+
};
|
package/src/tools/circleTool.js
CHANGED
|
@@ -4,6 +4,8 @@ import { pushCreateAction, pushDeleteAction, pushOptionsChangeAction, pushTransf
|
|
|
4
4
|
import { cleanupAttachments } from './arrowTool.js';
|
|
5
5
|
import { calculateSnap, clearSnapGuides } from '../core/SnapGuides.js';
|
|
6
6
|
|
|
7
|
+
function getThemeStroke() { if (typeof document === "undefined") return "#fff"; return document.body && document.body.classList.contains("theme-dark") ? "#fff" : "#1a1a2e"; }
|
|
8
|
+
|
|
7
9
|
let isDrawingCircle = false;
|
|
8
10
|
let isDraggingShapeCircle = false;
|
|
9
11
|
let isResizingShapeCircle = false;
|
|
@@ -16,7 +18,7 @@ const rc = rough.svg(svg);
|
|
|
16
18
|
let startX, startY;
|
|
17
19
|
|
|
18
20
|
|
|
19
|
-
let circleStrokecolor =
|
|
21
|
+
let circleStrokecolor = null;
|
|
20
22
|
let circleBackgroundColor = "transparent";
|
|
21
23
|
let circleFillStyleValue = "none";
|
|
22
24
|
let circleStrokeThicknes = 2;
|
|
@@ -83,7 +85,7 @@ const handleMouseDown = (e) => {
|
|
|
83
85
|
disableAllSideBars();
|
|
84
86
|
}
|
|
85
87
|
let initialOptions = {
|
|
86
|
-
stroke: circleStrokecolor,
|
|
88
|
+
stroke: circleStrokecolor ?? getThemeStroke(),
|
|
87
89
|
fill: circleBackgroundColor,
|
|
88
90
|
fillStyle: circleFillStyleValue,
|
|
89
91
|
strokeWidth: circleStrokeThicknes,
|
|
@@ -261,6 +263,25 @@ const handleMouseMove = (e) => {
|
|
|
261
263
|
} else {
|
|
262
264
|
clearSnapGuides();
|
|
263
265
|
}
|
|
266
|
+
|
|
267
|
+
// Issue #24 bug #4: track containing frame during drag (see same
|
|
268
|
+
// block in rectangleTool for the rationale).
|
|
269
|
+
let newHover = null;
|
|
270
|
+
for (const f of shapes) {
|
|
271
|
+
if (f.shapeName !== 'frame') continue;
|
|
272
|
+
if (f === currentShape) continue;
|
|
273
|
+
if (typeof f.isShapeInFrame === 'function' && f.isShapeInFrame(currentShape)) {
|
|
274
|
+
newHover = f;
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (hoveredFrameCircle && hoveredFrameCircle !== newHover && typeof hoveredFrameCircle.removeHighlight === 'function') {
|
|
279
|
+
hoveredFrameCircle.removeHighlight();
|
|
280
|
+
}
|
|
281
|
+
if (newHover && newHover !== hoveredFrameCircle && typeof newHover.highlightFrame === 'function') {
|
|
282
|
+
newHover.highlightFrame();
|
|
283
|
+
}
|
|
284
|
+
hoveredFrameCircle = newHover;
|
|
264
285
|
}
|
|
265
286
|
|
|
266
287
|
else if(isResizingShapeCircle && currentShape && currentShape.isSelected)
|
|
@@ -374,13 +395,16 @@ const handleMouseUp = (e) => {
|
|
|
374
395
|
}
|
|
375
396
|
|
|
376
397
|
if((isDraggingShapeCircle || isResizingShapeCircle || isRotatingShapeCircle) && dragOldPosCircle && currentShape) {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
398
|
+
// Issue #34 bug #2: see rectangleTool — record the hovered frame
|
|
399
|
+
// as the destination, not the stale `parentFrame` (containment
|
|
400
|
+
// transfer happens later in this handler).
|
|
401
|
+
const newPos = {
|
|
402
|
+
x: currentShape.x,
|
|
403
|
+
y: currentShape.y,
|
|
404
|
+
rx: currentShape.rx,
|
|
405
|
+
ry: currentShape.ry,
|
|
382
406
|
rotation: currentShape.rotation,
|
|
383
|
-
parentFrame: currentShape.parentFrame
|
|
407
|
+
parentFrame: isDraggingShapeCircle ? (hoveredFrameCircle || null) : currentShape.parentFrame,
|
|
384
408
|
};
|
|
385
409
|
const oldPos = {
|
|
386
410
|
...dragOldPosCircle,
|
|
@@ -616,4 +640,4 @@ export {
|
|
|
616
640
|
handleMouseDown as handleMouseDownCircle,
|
|
617
641
|
handleMouseMove as handleMouseMoveCircle,
|
|
618
642
|
handleMouseUp as handleMouseUpCircle,
|
|
619
|
-
}
|
|
643
|
+
}
|
package/src/tools/codeTool.js
CHANGED
|
@@ -11,9 +11,11 @@ import {
|
|
|
11
11
|
} from '../core/UndoRedo.js';
|
|
12
12
|
import { cleanupAttachments, updateAttachedArrows } from './arrowTool.js';
|
|
13
13
|
|
|
14
|
+
function getThemeStroke() { if (typeof document === "undefined") return "#fff"; return document.body && document.body.classList.contains("theme-dark") ? "#fff" : "#1a1a2e"; }
|
|
15
|
+
|
|
14
16
|
let codeTextSize = "25px";
|
|
15
17
|
let codeTextFont = "lixCode";
|
|
16
|
-
let codeTextColor =
|
|
18
|
+
let codeTextColor = null;
|
|
17
19
|
let codeTextAlign = "left";
|
|
18
20
|
let codeLanguage = "auto";
|
|
19
21
|
|
|
@@ -118,7 +120,7 @@ function addCodeBlock(event) {
|
|
|
118
120
|
|
|
119
121
|
codeElement.setAttribute("x", 0);
|
|
120
122
|
codeElement.setAttribute("y", 0);
|
|
121
|
-
codeElement.setAttribute("fill", codeTextColor);
|
|
123
|
+
codeElement.setAttribute("fill", codeTextColor ?? getThemeStroke());
|
|
122
124
|
codeElement.setAttribute("font-size", codeTextSize);
|
|
123
125
|
codeElement.setAttribute("font-family", codeTextFont);
|
|
124
126
|
codeElement.setAttribute("text-anchor", textAlignElement);
|
|
@@ -131,7 +133,7 @@ function addCodeBlock(event) {
|
|
|
131
133
|
gElement.setAttribute("data-y", y);
|
|
132
134
|
codeElement.setAttribute("data-initial-size", codeTextSize);
|
|
133
135
|
codeElement.setAttribute("data-initial-font", codeTextFont);
|
|
134
|
-
codeElement.setAttribute("data-initial-color", codeTextColor);
|
|
136
|
+
codeElement.setAttribute("data-initial-color", codeTextColor ?? getThemeStroke());
|
|
135
137
|
codeElement.setAttribute("data-initial-align", codeTextAlign);
|
|
136
138
|
codeElement.setAttribute("data-language", codeLanguage);
|
|
137
139
|
codeElement.setAttribute("data-type", "code");
|
package/src/tools/frameTool.js
CHANGED
|
@@ -61,9 +61,21 @@ const handleMouseDown = (e) => {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
-
// If a contained shape was clicked, don't select the frame —
|
|
65
|
-
//
|
|
66
|
-
if (
|
|
64
|
+
// If a contained shape was clicked, don't select the frame —
|
|
65
|
+
// and crucially, clear `currentShape` so the EventDispatcher's
|
|
66
|
+
// `if (handled && prevShape && !currentShape) handled=false` gate
|
|
67
|
+
// triggers and the dispatcher falls through to shape-specific
|
|
68
|
+
// handlers. Without this clear, the dispatcher returns with
|
|
69
|
+
// `handled=true` and the child shape is never selected (Issue
|
|
70
|
+
// #22, bug #2).
|
|
71
|
+
if (clickedContainedShape) {
|
|
72
|
+
if (currentShape && currentShape.shapeName === 'frame'
|
|
73
|
+
&& typeof currentShape.removeSelection === 'function') {
|
|
74
|
+
currentShape.removeSelection();
|
|
75
|
+
}
|
|
76
|
+
currentShape = null;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
67
79
|
|
|
68
80
|
if (currentShape && currentShape !== clickedFrame) {
|
|
69
81
|
currentShape.removeSelection();
|
|
@@ -216,12 +228,40 @@ Frame.prototype.isNearAnchor = function(x, y) {
|
|
|
216
228
|
// Delete functionality
|
|
217
229
|
function deleteCurrentFrame() {
|
|
218
230
|
if (currentShape && currentShape.shapeName === 'frame') {
|
|
219
|
-
const
|
|
231
|
+
const frame = currentShape;
|
|
232
|
+
const isDiagramFrame = !!frame._diagramType;
|
|
233
|
+
|
|
234
|
+
// Issue #24 bug #7: regular frame → orphan children + snapshot
|
|
235
|
+
// (mirrors deleteSelectedShapes / EngineShortcuts).
|
|
236
|
+
let childSnapshot = null;
|
|
237
|
+
if (!isDiagramFrame) {
|
|
238
|
+
childSnapshot = [...(frame.containedShapes || [])];
|
|
239
|
+
for (const child of childSnapshot) {
|
|
240
|
+
if (!child || child === frame) continue;
|
|
241
|
+
const el = child.group || child.element;
|
|
242
|
+
if (el) {
|
|
243
|
+
if (frame.clipGroup && el.parentNode === frame.clipGroup) frame.clipGroup.removeChild(el);
|
|
244
|
+
if (window.svg && el.parentNode !== window.svg) window.svg.appendChild(el);
|
|
245
|
+
}
|
|
246
|
+
child.parentFrame = null;
|
|
247
|
+
delete child.isBeingMovedByFrame;
|
|
248
|
+
}
|
|
249
|
+
frame.containedShapes = [];
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const idx = shapes.indexOf(frame);
|
|
220
253
|
if (idx !== -1) shapes.splice(idx, 1);
|
|
221
|
-
|
|
222
|
-
|
|
254
|
+
|
|
255
|
+
if (!isDiagramFrame) {
|
|
256
|
+
if (frame.group && frame.group.parentNode) frame.group.parentNode.removeChild(frame.group);
|
|
257
|
+
if (frame.clipGroup && frame.clipGroup.parentNode) frame.clipGroup.parentNode.removeChild(frame.clipGroup);
|
|
258
|
+
if (frame.clipPath && frame.clipPath.parentNode) frame.clipPath.parentNode.removeChild(frame.clipPath);
|
|
259
|
+
} else if (frame.group && frame.group.parentNode) {
|
|
260
|
+
frame.group.parentNode.removeChild(frame.group);
|
|
223
261
|
}
|
|
224
|
-
|
|
262
|
+
|
|
263
|
+
if (childSnapshot) pushDeleteAction(frame, { childSnapshot });
|
|
264
|
+
else pushDeleteAction(frame);
|
|
225
265
|
currentShape = null;
|
|
226
266
|
}
|
|
227
267
|
}
|
|
@@ -4,6 +4,8 @@ import { pushCreateAction, pushDeleteAction, pushOptionsChangeAction, pushTransf
|
|
|
4
4
|
import { updateAttachedArrows as updateArrowsForShape, cleanupAttachments } from './arrowTool.js';
|
|
5
5
|
import { calculateSnap, clearSnapGuides } from '../core/SnapGuides.js';
|
|
6
6
|
|
|
7
|
+
function getThemeStroke() { if (typeof document === "undefined") return "#fff"; return document.body && document.body.classList.contains("theme-dark") ? "#fff" : "#1a1a2e"; }
|
|
8
|
+
|
|
7
9
|
// Expose updateArrowsForShape globally so FreehandStroke.updateAttachedArrows() can call it
|
|
8
10
|
// (FreehandStroke.js is a separate module and cannot import freehandTool's local bindings)
|
|
9
11
|
window.__updateArrowsForShape = updateArrowsForShape;
|
|
@@ -13,7 +15,7 @@ const strokeThicknesses = document.querySelectorAll(".strokeThickness span");
|
|
|
13
15
|
const strokeStyles = document.querySelectorAll(".strokeStyleSpan");
|
|
14
16
|
const strokeTapers = document.querySelectorAll(".strokeTaperSpan");
|
|
15
17
|
const strokeRoughnesses = document.querySelectorAll(".strokeRoughnessSpan");
|
|
16
|
-
let strokeColor =
|
|
18
|
+
let strokeColor = null;
|
|
17
19
|
let strokeThickness = 2;
|
|
18
20
|
let strokeStyleValue = "solid";
|
|
19
21
|
let strokeThinning = 0;
|
|
@@ -140,7 +142,7 @@ function handleMouseDown(e) {
|
|
|
140
142
|
lastTime = Date.now();
|
|
141
143
|
|
|
142
144
|
currentStroke = new FreehandStroke(points, {
|
|
143
|
-
stroke: strokeColor,
|
|
145
|
+
stroke: strokeColor ?? getThemeStroke(),
|
|
144
146
|
strokeWidth: strokeThickness
|
|
145
147
|
});
|
|
146
148
|
|
|
@@ -411,9 +413,15 @@ function handleMouseUp(e) {
|
|
|
411
413
|
...dragOldPosStroke,
|
|
412
414
|
parentFrame: draggedShapeInitialFrameStroke
|
|
413
415
|
};
|
|
416
|
+
// Issue #34 bug #2: for drag, hoveredFrameStroke is the actual
|
|
417
|
+
// destination — currentShape.parentFrame at this point is still
|
|
418
|
+
// the OLD frame. Resize / rotate don't track hover, fall back to
|
|
419
|
+
// the shape's own parent.
|
|
414
420
|
const newPosForUndo = {
|
|
415
421
|
...newPos,
|
|
416
|
-
parentFrame:
|
|
422
|
+
parentFrame: isDraggingStroke
|
|
423
|
+
? (hoveredFrameStroke || null)
|
|
424
|
+
: currentShape.parentFrame,
|
|
417
425
|
};
|
|
418
426
|
|
|
419
427
|
const frameChanged = oldPos.parentFrame !== newPosForUndo.parentFrame;
|
|
@@ -659,4 +667,4 @@ export
|
|
|
659
667
|
handleMouseDown as handleFreehandMouseDown,
|
|
660
668
|
handleMouseMove as handleFreehandMouseMove,
|
|
661
669
|
handleMouseUp as handleFreehandMouseUp,
|
|
662
|
-
}
|
|
670
|
+
}
|
package/src/tools/iconTool.js
CHANGED
|
@@ -1008,9 +1008,15 @@ function stopInteracting() {
|
|
|
1008
1008
|
...oldPos,
|
|
1009
1009
|
parentFrame: draggedShapeInitialFrameIcon
|
|
1010
1010
|
};
|
|
1011
|
+
// Issue #34 bug #2: for drag, hoveredFrameIcon tracks the actual
|
|
1012
|
+
// destination — currentShape.parentFrame is still the OLD frame.
|
|
1013
|
+
// Resize / rotate don't track hover, so fall back to whatever the
|
|
1014
|
+
// shape itself reports (parent doesn't change for those gestures).
|
|
1011
1015
|
const newPosWithFrame = {
|
|
1012
1016
|
...newPos,
|
|
1013
|
-
parentFrame:
|
|
1017
|
+
parentFrame: isDragging
|
|
1018
|
+
? (hoveredFrameIcon || null)
|
|
1019
|
+
: (iconShape ? iconShape.parentFrame : null),
|
|
1014
1020
|
};
|
|
1015
1021
|
|
|
1016
1022
|
const stateChanged = newPos.x !== oldPos.x || newPos.y !== oldPos.y ||
|
package/src/tools/imageTool.js
CHANGED
|
@@ -1117,9 +1117,15 @@ function stopInteracting() {
|
|
|
1117
1117
|
...oldPos,
|
|
1118
1118
|
parentFrame: draggedShapeInitialFrameImage
|
|
1119
1119
|
};
|
|
1120
|
+
// Issue #34 bug #2: for drag, hoveredFrameImage tracks the actual
|
|
1121
|
+
// destination — imageShape.parentFrame is still the OLD frame here.
|
|
1122
|
+
// Resize / rotate don't move between frames, so fall back to the
|
|
1123
|
+
// shape's own parent for those.
|
|
1120
1124
|
const newPosWithFrame = {
|
|
1121
1125
|
...newPos,
|
|
1122
|
-
parentFrame:
|
|
1126
|
+
parentFrame: isDragging
|
|
1127
|
+
? (hoveredFrameImage || null)
|
|
1128
|
+
: (imageShape ? imageShape.parentFrame : null),
|
|
1123
1129
|
};
|
|
1124
1130
|
|
|
1125
1131
|
// Only push transform action if something actually changed
|
package/src/tools/lineTool.js
CHANGED
|
@@ -4,12 +4,14 @@ import { pushCreateAction, pushDeleteAction, pushOptionsChangeAction, pushTransf
|
|
|
4
4
|
import { updateAttachedArrows as updateArrowsForShape, cleanupAttachments } from './arrowTool.js';
|
|
5
5
|
import { calculateSnap, clearSnapGuides } from '../core/SnapGuides.js';
|
|
6
6
|
|
|
7
|
+
function getThemeStroke() { if (typeof document === "undefined") return "#fff"; return document.body && document.body.classList.contains("theme-dark") ? "#fff" : "#1a1a2e"; }
|
|
8
|
+
|
|
7
9
|
let isDrawingLine = false;
|
|
8
10
|
let currentLine = null;
|
|
9
11
|
let lineStartX = 0;
|
|
10
12
|
let lineStartY = 0;
|
|
11
13
|
let currentLineGroup = null;
|
|
12
|
-
let lineColor =
|
|
14
|
+
let lineColor = null;
|
|
13
15
|
let lineStrokeWidth = 3;
|
|
14
16
|
let lineStrokeStyle = "solid";
|
|
15
17
|
let lineEdgeType = 1;
|
|
@@ -71,7 +73,7 @@ const handleMouseDown = (e) => {
|
|
|
71
73
|
{ x, y },
|
|
72
74
|
{ x, y },
|
|
73
75
|
{
|
|
74
|
-
stroke: lineColor,
|
|
76
|
+
stroke: lineColor ?? getThemeStroke(),
|
|
75
77
|
strokeWidth: lineStrokeWidth,
|
|
76
78
|
roughness: lineSktetchRate,
|
|
77
79
|
bowing: lineEdgeType,
|
|
@@ -238,6 +240,26 @@ const handleMouseMove = (e) => {
|
|
|
238
240
|
startX = x;
|
|
239
241
|
startY = y;
|
|
240
242
|
|
|
243
|
+
// Issue #24 bug #4: track containing frame during existing-line
|
|
244
|
+
// drag so mouseUp re-parents from current geometry, not from a
|
|
245
|
+
// stale hoveredFrameLine.
|
|
246
|
+
let newHover = null;
|
|
247
|
+
for (const f of shapes) {
|
|
248
|
+
if (f.shapeName !== 'frame') continue;
|
|
249
|
+
if (f === currentShape) continue;
|
|
250
|
+
if (typeof f.isShapeInFrame === 'function' && f.isShapeInFrame(currentShape)) {
|
|
251
|
+
newHover = f;
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (hoveredFrameLine && hoveredFrameLine !== newHover && typeof hoveredFrameLine.removeHighlight === 'function') {
|
|
256
|
+
hoveredFrameLine.removeHighlight();
|
|
257
|
+
}
|
|
258
|
+
if (newHover && newHover !== hoveredFrameLine && typeof newHover.highlightFrame === 'function') {
|
|
259
|
+
newHover.highlightFrame();
|
|
260
|
+
}
|
|
261
|
+
hoveredFrameLine = newHover;
|
|
262
|
+
|
|
241
263
|
// Snap guides
|
|
242
264
|
if (window.__sketchStoreApi && window.__sketchStoreApi.getState().snapToObjects) {
|
|
243
265
|
const snap = calculateSnap(currentShape, e.shiftKey, e.clientX, e.clientY);
|
|
@@ -299,11 +321,13 @@ const handleMouseUp = (e) => {
|
|
|
299
321
|
}
|
|
300
322
|
|
|
301
323
|
if (isDraggingLine && dragOldPosLine && currentShape) {
|
|
324
|
+
// Issue #34 bug #2: use hoveredFrameLine (actual destination) instead
|
|
325
|
+
// of the stale parentFrame — containment transfer hasn't happened yet.
|
|
302
326
|
const newPos = {
|
|
303
327
|
startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },
|
|
304
328
|
endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },
|
|
305
329
|
controlPoint: currentShape.controlPoint ? { x: currentShape.controlPoint.x, y: currentShape.controlPoint.y } : null,
|
|
306
|
-
parentFrame:
|
|
330
|
+
parentFrame: hoveredFrameLine || null,
|
|
307
331
|
};
|
|
308
332
|
const oldPos = {
|
|
309
333
|
...dragOldPosLine,
|
|
@@ -16,7 +16,16 @@ let startRotationMouseAngleSquare = 0;
|
|
|
16
16
|
let startShapeRotationSquare = 0;
|
|
17
17
|
const rc = rough.svg(svg);
|
|
18
18
|
let startX, startY;
|
|
19
|
-
|
|
19
|
+
// Issue #38 follow-up: null sentinel means "use theme default at draw
|
|
20
|
+
// time". The legacy `"#fff"` literal was invisible on the light canvas;
|
|
21
|
+
// reading the body's `theme-dark` class lets the same code produce a
|
|
22
|
+
// readable stroke in either mode. As soon as the user picks a colour
|
|
23
|
+
// from the sidebar this var holds that value verbatim.
|
|
24
|
+
function getThemeStroke() {
|
|
25
|
+
if (typeof document === 'undefined') return '#fff';
|
|
26
|
+
return document.body && document.body.classList.contains('theme-dark') ? '#fff' : '#1a1a2e';
|
|
27
|
+
}
|
|
28
|
+
let squareStrokecolor = null;
|
|
20
29
|
let squareBackgroundColor = "transparent";
|
|
21
30
|
let squareFillStyleValue = "none";
|
|
22
31
|
let squareStrokeThicknes = 2;
|
|
@@ -76,7 +85,7 @@ const handleMouseDownRect = (e) => {
|
|
|
76
85
|
}
|
|
77
86
|
|
|
78
87
|
let initialOptions = {
|
|
79
|
-
stroke: squareStrokecolor,
|
|
88
|
+
stroke: squareStrokecolor ?? getThemeStroke(),
|
|
80
89
|
fill: squareBackgroundColor,
|
|
81
90
|
fillStyle: squareFillStyleValue,
|
|
82
91
|
strokeWidth: squareStrokeThicknes,
|
|
@@ -241,6 +250,28 @@ const handleMouseMoveRect = (e) => {
|
|
|
241
250
|
} else {
|
|
242
251
|
clearSnapGuides();
|
|
243
252
|
}
|
|
253
|
+
|
|
254
|
+
// Issue #24 bug #4: track the actual containing frame at every
|
|
255
|
+
// move so the mouseUp logic re-parents correctly. Without this
|
|
256
|
+
// hoveredFrame stays at null for existing-shape drags and the
|
|
257
|
+
// shape is detached the moment the user nudges it by 1 px inside
|
|
258
|
+
// its own parent frame.
|
|
259
|
+
let newHover = null;
|
|
260
|
+
for (const f of shapes) {
|
|
261
|
+
if (f.shapeName !== 'frame') continue;
|
|
262
|
+
if (f === currentShape) continue;
|
|
263
|
+
if (typeof f.isShapeInFrame === 'function' && f.isShapeInFrame(currentShape)) {
|
|
264
|
+
newHover = f;
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (hoveredFrame && hoveredFrame !== newHover && typeof hoveredFrame.removeHighlight === 'function') {
|
|
269
|
+
hoveredFrame.removeHighlight();
|
|
270
|
+
}
|
|
271
|
+
if (newHover && newHover !== hoveredFrame && typeof newHover.highlightFrame === 'function') {
|
|
272
|
+
newHover.highlightFrame();
|
|
273
|
+
}
|
|
274
|
+
hoveredFrame = newHover;
|
|
244
275
|
} else if (isResizingShapeSquare && currentShape && currentShape.isSelected && resizingAnchorIndexSquare !== null) {
|
|
245
276
|
currentShape.updatePosition(resizingAnchorIndexSquare, mouseX, mouseY);
|
|
246
277
|
currentShape._skipAnchors = true;
|
|
@@ -341,13 +372,19 @@ const handleMouseUpRect = (e) => {
|
|
|
341
372
|
}
|
|
342
373
|
|
|
343
374
|
if ((isDraggingShapeSquare || isResizingShapeSquare || isRotatingShapeSquare) && dragOldPosSquare && currentShape) {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
375
|
+
// Issue #34 bug #2: for drag operations the actual frame transfer
|
|
376
|
+
// happens AFTER this mouseUp block — so `currentShape.parentFrame`
|
|
377
|
+
// at this point still points at the OLD frame. Use the hovered
|
|
378
|
+
// frame (tracked during mousemove) as the authoritative new
|
|
379
|
+
// destination instead, so the undo action records a real
|
|
380
|
+
// attachment delta and Ctrl+Z re-attaches the shape correctly.
|
|
381
|
+
const newPos = {
|
|
382
|
+
x: currentShape.x,
|
|
383
|
+
y: currentShape.y,
|
|
384
|
+
width: currentShape.width,
|
|
385
|
+
height: currentShape.height,
|
|
349
386
|
rotation: currentShape.rotation,
|
|
350
|
-
parentFrame: currentShape.parentFrame
|
|
387
|
+
parentFrame: isDraggingShapeSquare ? (hoveredFrame || null) : currentShape.parentFrame,
|
|
351
388
|
};
|
|
352
389
|
const oldPos = {
|
|
353
390
|
...dragOldPosSquare,
|
package/src/tools/textTool.js
CHANGED
|
@@ -11,6 +11,8 @@ import {
|
|
|
11
11
|
updateSelectedElement
|
|
12
12
|
} from '../core/UndoRedo.js';
|
|
13
13
|
import { cleanupAttachments, updateAttachedArrows } from './arrowTool.js';
|
|
14
|
+
|
|
15
|
+
function getThemeStroke() { if (typeof document === "undefined") return "#fff"; return document.body && document.body.classList.contains("theme-dark") ? "#fff" : "#1a1a2e"; }
|
|
14
16
|
import {
|
|
15
17
|
addCodeBlock,
|
|
16
18
|
wrapCodeElement,
|
|
@@ -27,7 +29,7 @@ import {
|
|
|
27
29
|
|
|
28
30
|
let textSize = "30px";
|
|
29
31
|
let textFont = "lixFont";
|
|
30
|
-
let textColor =
|
|
32
|
+
let textColor = null;
|
|
31
33
|
let textAlign = "left";
|
|
32
34
|
|
|
33
35
|
let textColorOptions = document.querySelectorAll(".textColorSpan");
|
|
@@ -118,20 +120,27 @@ function addText(event) {
|
|
|
118
120
|
|
|
119
121
|
textElement.setAttribute("x", 0);
|
|
120
122
|
textElement.setAttribute("y", 0);
|
|
121
|
-
textElement.setAttribute("fill", textColor);
|
|
123
|
+
textElement.setAttribute("fill", textColor ?? getThemeStroke());
|
|
122
124
|
textElement.setAttribute("font-size", textSize);
|
|
123
125
|
textElement.setAttribute("font-family", textFont);
|
|
124
126
|
textElement.setAttribute("text-anchor", textAlignElement);
|
|
125
127
|
textElement.setAttribute("cursor", "default");
|
|
126
128
|
textElement.setAttribute("white-space", "pre");
|
|
127
129
|
textElement.setAttribute("dominant-baseline", "hanging");
|
|
130
|
+
// Issue #34 bug #5b: SVG <text> only fires pointer events on the
|
|
131
|
+
// painted glyphs by default — so a click between letters or in the
|
|
132
|
+
// padding around the text never bubbles to the <g> and the selection
|
|
133
|
+
// tool can't pick the shape up. `bounding-box` extends the hit area
|
|
134
|
+
// to the entire bounding box (SVG 2; supported in Chromium/WebKit/
|
|
135
|
+
// Firefox), which is what every other shape tool relies on.
|
|
136
|
+
textElement.setAttribute("pointer-events", "bounding-box");
|
|
128
137
|
textElement.textContent = "";
|
|
129
138
|
|
|
130
139
|
gElement.setAttribute("data-x", x);
|
|
131
140
|
gElement.setAttribute("data-y", y);
|
|
132
141
|
textElement.setAttribute("data-initial-size", textSize);
|
|
133
142
|
textElement.setAttribute("data-initial-font", textFont);
|
|
134
|
-
textElement.setAttribute("data-initial-color", textColor);
|
|
143
|
+
textElement.setAttribute("data-initial-color", textColor ?? getThemeStroke());
|
|
135
144
|
textElement.setAttribute("data-initial-align", textAlign);
|
|
136
145
|
textElement.setAttribute("data-type", "text");
|
|
137
146
|
gElement.appendChild(textElement);
|
|
@@ -247,7 +256,12 @@ function makeTextEditable(textElement, groupElement) {
|
|
|
247
256
|
input.style.lineHeight = "1.2em";
|
|
248
257
|
input.style.textAlign = currentAnchor === "middle" ? "center" : currentAnchor === "end" ? "right" : "left";
|
|
249
258
|
input.style.backgroundColor = "transparent";
|
|
250
|
-
|
|
259
|
+
// Issue #34 bug #5a: dashed creation outline that grows with the
|
|
260
|
+
// text — same visual cue the frame tool uses while drawing. Inset
|
|
261
|
+
// padding-box border so the dashes follow the textarea size as the
|
|
262
|
+
// user types instead of clipping behind the glyphs.
|
|
263
|
+
input.style.border = "1px dashed rgba(255,255,255,0.55)";
|
|
264
|
+
input.style.borderRadius = "3px";
|
|
251
265
|
input.style.outline = "none";
|
|
252
266
|
document.body.appendChild(input);
|
|
253
267
|
|
|
@@ -1001,11 +1015,14 @@ const handleMouseUp = (event) => {
|
|
|
1001
1015
|
rotation: extractRotationFromTransform(selectedElement) || 0,
|
|
1002
1016
|
parentFrame: draggedShapeInitialFrameText
|
|
1003
1017
|
};
|
|
1018
|
+
// Issue #34 bug #2: hoveredFrameText is the actual destination
|
|
1019
|
+
// tracked during drag — textShape.parentFrame is still the OLD
|
|
1020
|
+
// frame at this point.
|
|
1004
1021
|
const newPosWithFrame = {
|
|
1005
1022
|
x: finalTranslateX,
|
|
1006
1023
|
y: finalTranslateY,
|
|
1007
1024
|
rotation: extractRotationFromTransform(selectedElement) || 0,
|
|
1008
|
-
parentFrame:
|
|
1025
|
+
parentFrame: hoveredFrameText || null,
|
|
1009
1026
|
};
|
|
1010
1027
|
|
|
1011
1028
|
const stateChanged = initialX !== finalTranslateX || initialY !== finalTranslateY;
|
|
@@ -1837,4 +1854,4 @@ window.__setCodeLanguage = function(lang) {
|
|
|
1837
1854
|
}
|
|
1838
1855
|
};
|
|
1839
1856
|
|
|
1840
|
-
export { handleTextMouseDown, handleTextMouseMove, handleTextMouseUp, updateCodeToggleForShape, deselectElement as deselectTextElement, enterEditMode };
|
|
1857
|
+
export { handleTextMouseDown, handleTextMouseMove, handleTextMouseUp, updateCodeToggleForShape, deselectElement as deselectTextElement, enterEditMode };
|