@elixpo/lixsketch 5.5.21 → 5.5.23
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-FJN7K5LS.js → CopyPaste-5OWPTCQ5.js} +6 -2
- package/dist/react/CopyPaste-5OWPTCQ5.js.map +7 -0
- package/dist/react/{EventDispatcher-O7HCQQNM.js → EventDispatcher-GKNO2KSL.js} +2 -2
- package/dist/react/{ImageShape-LRNJQCF3.js → ImageShape-T7UEHP4A.js} +2 -2
- package/dist/react/{SceneSerializer-GSJR7ZHC.js → SceneSerializer-RDISX4X7.js} +6 -2
- package/dist/react/SceneSerializer-RDISX4X7.js.map +7 -0
- package/dist/react/{SketchEngine-BFLHJPCG.js → SketchEngine-OB6ZW3B6.js} +6 -6
- package/dist/react/{chunk-2FMFOPGW.js → chunk-EDSKEM6E.js} +66 -1
- package/dist/react/chunk-EDSKEM6E.js.map +7 -0
- package/dist/react/{chunk-2THKDSWW.js → chunk-ETAAQUUV.js} +91 -61
- package/dist/react/chunk-ETAAQUUV.js.map +7 -0
- package/dist/react/index.js +2 -2
- package/dist/react/{textTool-IQOYPELP.js → textTool-JMTX7OVT.js} +2 -2
- package/package.json +1 -1
- package/src/core/CopyPaste.js +4 -0
- package/src/core/SceneSerializer.js +4 -0
- package/src/shapes/ImageShape.js +73 -2
- package/src/tools/textTool.js +95 -67
- package/dist/react/CopyPaste-FJN7K5LS.js.map +0 -7
- package/dist/react/SceneSerializer-GSJR7ZHC.js.map +0 -7
- package/dist/react/chunk-2FMFOPGW.js.map +0 -7
- package/dist/react/chunk-2THKDSWW.js.map +0 -7
- /package/dist/react/{EventDispatcher-O7HCQQNM.js.map → EventDispatcher-GKNO2KSL.js.map} +0 -0
- /package/dist/react/{ImageShape-LRNJQCF3.js.map → ImageShape-T7UEHP4A.js.map} +0 -0
- /package/dist/react/{SketchEngine-BFLHJPCG.js.map → SketchEngine-OB6ZW3B6.js.map} +0 -0
- /package/dist/react/{textTool-IQOYPELP.js.map → textTool-JMTX7OVT.js.map} +0 -0
|
@@ -56,6 +56,10 @@ var isRotating = false;
|
|
|
56
56
|
var rotationStartAngle = 0;
|
|
57
57
|
var rotationStartTransform = null;
|
|
58
58
|
var initialHandlePosRelGroup = null;
|
|
59
|
+
var initialFixedHandlePosRelGroup = null;
|
|
60
|
+
var resizePointerOffsetScreen = null;
|
|
61
|
+
var resizePadding = 0;
|
|
62
|
+
var initialGroupMatrix = null;
|
|
59
63
|
var initialGroupTx = 0;
|
|
60
64
|
var initialGroupTy = 0;
|
|
61
65
|
var initialInverseScreenCTM = null;
|
|
@@ -397,6 +401,7 @@ function createSelectionFeedback(groupElement) {
|
|
|
397
401
|
handleRect.addEventListener("pointerdown", (e) => {
|
|
398
402
|
if (window.isSelectionToolActive) {
|
|
399
403
|
e.stopPropagation();
|
|
404
|
+
handleRect.setPointerCapture?.(e.pointerId);
|
|
400
405
|
startResize(e, handle.name);
|
|
401
406
|
}
|
|
402
407
|
});
|
|
@@ -611,13 +616,22 @@ function startResize(event, anchor) {
|
|
|
611
616
|
const groupScreenCTM = selectedElement.getScreenCTM();
|
|
612
617
|
initialInverseScreenCTM = groupScreenCTM ? groupScreenCTM.inverse() : null;
|
|
613
618
|
const currentTransform = selectedElement.transform.baseVal.consolidate();
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
619
|
+
const matrix = currentTransform?.matrix;
|
|
620
|
+
initialGroupMatrix = matrix ? {
|
|
621
|
+
a: matrix.a,
|
|
622
|
+
b: matrix.b,
|
|
623
|
+
c: matrix.c,
|
|
624
|
+
d: matrix.d,
|
|
625
|
+
e: matrix.e,
|
|
626
|
+
f: matrix.f
|
|
627
|
+
} : { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 };
|
|
628
|
+
initialGroupTx = initialGroupMatrix.e;
|
|
629
|
+
initialGroupTy = initialGroupMatrix.f;
|
|
630
|
+
resizePadding = 8 / (window.currentZoom || 1);
|
|
631
|
+
const startX = startBBox.x - resizePadding;
|
|
632
|
+
const startY = startBBox.y - resizePadding;
|
|
633
|
+
const startWidth = startBBox.width + 2 * resizePadding;
|
|
634
|
+
const startHeight = startBBox.height + 2 * resizePadding;
|
|
621
635
|
let hx = startX;
|
|
622
636
|
let hy = startY;
|
|
623
637
|
if (anchor.includes("e")) {
|
|
@@ -627,6 +641,23 @@ function startResize(event, anchor) {
|
|
|
627
641
|
hy = startY + startHeight;
|
|
628
642
|
}
|
|
629
643
|
initialHandlePosRelGroup = { x: hx, y: hy };
|
|
644
|
+
let fx = startX + startWidth;
|
|
645
|
+
let fy = startY + startHeight;
|
|
646
|
+
if (anchor.includes("e")) {
|
|
647
|
+
fx = startX;
|
|
648
|
+
}
|
|
649
|
+
if (anchor.includes("s")) {
|
|
650
|
+
fy = startY;
|
|
651
|
+
}
|
|
652
|
+
initialFixedHandlePosRelGroup = { x: fx, y: fy };
|
|
653
|
+
const handlePoint = svg.createSVGPoint();
|
|
654
|
+
handlePoint.x = hx;
|
|
655
|
+
handlePoint.y = hy;
|
|
656
|
+
const handleScreen = groupScreenCTM ? handlePoint.matrixTransform(groupScreenCTM) : { x: event.clientX, y: event.clientY };
|
|
657
|
+
resizePointerOffsetScreen = {
|
|
658
|
+
x: event.clientX - handleScreen.x,
|
|
659
|
+
y: event.clientY - handleScreen.y
|
|
660
|
+
};
|
|
630
661
|
svg.style.cursor = resizeHandles[anchor]?.style.cursor || "default";
|
|
631
662
|
svg.addEventListener("pointermove", handleMouseMove);
|
|
632
663
|
svg.addEventListener("pointerup", handleMouseUp);
|
|
@@ -671,41 +702,27 @@ var handleMouseMove = (event) => {
|
|
|
671
702
|
updateAttachedArrows(selectedElement);
|
|
672
703
|
} else if (isResizing) {
|
|
673
704
|
const textElement = selectedElement.querySelector("text");
|
|
674
|
-
if (!textElement || !startBBox || startFontSize === null || !startPoint || !initialHandlePosRelGroup) return;
|
|
705
|
+
if (!textElement || !startBBox || startFontSize === null || !startPoint || !initialHandlePosRelGroup || !initialFixedHandlePosRelGroup || !initialGroupMatrix) return;
|
|
675
706
|
let currentPoint;
|
|
676
707
|
if (initialInverseScreenCTM) {
|
|
677
708
|
const pt = svg.createSVGPoint();
|
|
678
|
-
pt.x = event.clientX;
|
|
679
|
-
pt.y = event.clientY;
|
|
709
|
+
pt.x = event.clientX - (resizePointerOffsetScreen?.x || 0);
|
|
710
|
+
pt.y = event.clientY - (resizePointerOffsetScreen?.y || 0);
|
|
680
711
|
currentPoint = pt.matrixTransform(initialInverseScreenCTM);
|
|
681
712
|
} else {
|
|
682
|
-
currentPoint = getSVGCoordinates(
|
|
713
|
+
currentPoint = getSVGCoordinates({
|
|
714
|
+
clientX: event.clientX - (resizePointerOffsetScreen?.x || 0),
|
|
715
|
+
clientY: event.clientY - (resizePointerOffsetScreen?.y || 0)
|
|
716
|
+
}, selectedElement);
|
|
683
717
|
}
|
|
684
|
-
const startX = startBBox.x;
|
|
685
|
-
const startY = startBBox.y;
|
|
686
718
|
const startWidth = startBBox.width;
|
|
687
719
|
const startHeight = startBBox.height;
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
case "ne":
|
|
695
|
-
anchorX = startX;
|
|
696
|
-
anchorY = startY + startHeight;
|
|
697
|
-
break;
|
|
698
|
-
case "sw":
|
|
699
|
-
anchorX = startX + startWidth;
|
|
700
|
-
anchorY = startY;
|
|
701
|
-
break;
|
|
702
|
-
case "se":
|
|
703
|
-
anchorX = startX;
|
|
704
|
-
anchorY = startY;
|
|
705
|
-
break;
|
|
706
|
-
}
|
|
707
|
-
const newHeight = Math.abs(currentPoint.y - anchorY);
|
|
708
|
-
const chosenScale = newHeight / startHeight;
|
|
720
|
+
const directionX = currentResizeHandle.includes("e") ? 1 : -1;
|
|
721
|
+
const directionY = currentResizeHandle.includes("s") ? 1 : -1;
|
|
722
|
+
const desiredWidth = directionX * (currentPoint.x - initialFixedHandlePosRelGroup.x) - 2 * resizePadding;
|
|
723
|
+
const desiredHeight = directionY * (currentPoint.y - initialFixedHandlePosRelGroup.y) - 2 * resizePadding;
|
|
724
|
+
const denominator = startWidth * startWidth + startHeight * startHeight;
|
|
725
|
+
const chosenScale = denominator > 0 ? (startWidth * desiredWidth + startHeight * desiredHeight) / denominator : 1;
|
|
709
726
|
const minScale = 0.1;
|
|
710
727
|
const maxScale = 10;
|
|
711
728
|
const clampedScale = Math.max(minScale, Math.min(chosenScale, maxScale));
|
|
@@ -717,40 +734,49 @@ var handleMouseMove = (event) => {
|
|
|
717
734
|
let newAnchorX, newAnchorY;
|
|
718
735
|
switch (currentResizeHandle) {
|
|
719
736
|
case "nw":
|
|
720
|
-
newAnchorX = currentBBox.x + currentBBox.width;
|
|
721
|
-
newAnchorY = currentBBox.y + currentBBox.height;
|
|
737
|
+
newAnchorX = currentBBox.x + currentBBox.width + resizePadding;
|
|
738
|
+
newAnchorY = currentBBox.y + currentBBox.height + resizePadding;
|
|
722
739
|
break;
|
|
723
740
|
case "ne":
|
|
724
|
-
newAnchorX = currentBBox.x;
|
|
725
|
-
newAnchorY = currentBBox.y + currentBBox.height;
|
|
741
|
+
newAnchorX = currentBBox.x - resizePadding;
|
|
742
|
+
newAnchorY = currentBBox.y + currentBBox.height + resizePadding;
|
|
726
743
|
break;
|
|
727
744
|
case "sw":
|
|
728
|
-
newAnchorX = currentBBox.x + currentBBox.width;
|
|
729
|
-
newAnchorY = currentBBox.y;
|
|
745
|
+
newAnchorX = currentBBox.x + currentBBox.width + resizePadding;
|
|
746
|
+
newAnchorY = currentBBox.y - resizePadding;
|
|
730
747
|
break;
|
|
731
748
|
case "se":
|
|
732
|
-
newAnchorX = currentBBox.x;
|
|
733
|
-
newAnchorY = currentBBox.y;
|
|
749
|
+
newAnchorX = currentBBox.x - resizePadding;
|
|
750
|
+
newAnchorY = currentBBox.y - resizePadding;
|
|
734
751
|
break;
|
|
735
752
|
}
|
|
736
|
-
const deltaX =
|
|
737
|
-
const deltaY =
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
const
|
|
752
|
-
const
|
|
753
|
-
|
|
753
|
+
const deltaX = initialFixedHandlePosRelGroup.x - newAnchorX;
|
|
754
|
+
const deltaY = initialFixedHandlePosRelGroup.y - newAnchorY;
|
|
755
|
+
let newGroupTx = initialGroupMatrix.e + initialGroupMatrix.a * deltaX + initialGroupMatrix.c * deltaY;
|
|
756
|
+
let newGroupTy = initialGroupMatrix.f + initialGroupMatrix.b * deltaX + initialGroupMatrix.d * deltaY;
|
|
757
|
+
const matrixTransform = () => `matrix(${initialGroupMatrix.a} ${initialGroupMatrix.b} ${initialGroupMatrix.c} ${initialGroupMatrix.d} ${newGroupTx} ${newGroupTy})`;
|
|
758
|
+
selectedElement.setAttribute("transform", matrixTransform());
|
|
759
|
+
const draggedX = currentBBox.x + (currentResizeHandle.includes("e") ? currentBBox.width + resizePadding : -resizePadding);
|
|
760
|
+
const draggedY = currentBBox.y + (currentResizeHandle.includes("s") ? currentBBox.height + resizePadding : -resizePadding);
|
|
761
|
+
const draggedPoint = svg.createSVGPoint();
|
|
762
|
+
draggedPoint.x = draggedX;
|
|
763
|
+
draggedPoint.y = draggedY;
|
|
764
|
+
const resizedScreenCTM = selectedElement.getScreenCTM();
|
|
765
|
+
const parentScreenCTM = selectedElement.parentNode?.getScreenCTM?.();
|
|
766
|
+
if (resizedScreenCTM && parentScreenCTM) {
|
|
767
|
+
const actualScreen = draggedPoint.matrixTransform(resizedScreenCTM);
|
|
768
|
+
const parentInverse = parentScreenCTM.inverse();
|
|
769
|
+
const targetScreenPoint = svg.createSVGPoint();
|
|
770
|
+
targetScreenPoint.x = event.clientX - (resizePointerOffsetScreen?.x || 0);
|
|
771
|
+
targetScreenPoint.y = event.clientY - (resizePointerOffsetScreen?.y || 0);
|
|
772
|
+
const actualScreenPoint = svg.createSVGPoint();
|
|
773
|
+
actualScreenPoint.x = actualScreen.x;
|
|
774
|
+
actualScreenPoint.y = actualScreen.y;
|
|
775
|
+
const targetParent = targetScreenPoint.matrixTransform(parentInverse);
|
|
776
|
+
const actualParent = actualScreenPoint.matrixTransform(parentInverse);
|
|
777
|
+
newGroupTx += targetParent.x - actualParent.x;
|
|
778
|
+
newGroupTy += targetParent.y - actualParent.y;
|
|
779
|
+
selectedElement.setAttribute("transform", matrixTransform());
|
|
754
780
|
}
|
|
755
781
|
updateAttachedArrows(selectedElement);
|
|
756
782
|
clearTimeout(selectedElement.updateFeedbackTimeout);
|
|
@@ -918,6 +944,10 @@ var handleMouseUp = (event) => {
|
|
|
918
944
|
dragOffsetX = void 0;
|
|
919
945
|
dragOffsetY = void 0;
|
|
920
946
|
initialHandlePosRelGroup = null;
|
|
947
|
+
initialFixedHandlePosRelGroup = null;
|
|
948
|
+
resizePointerOffsetScreen = null;
|
|
949
|
+
resizePadding = 0;
|
|
950
|
+
initialGroupMatrix = null;
|
|
921
951
|
initialGroupTx = 0;
|
|
922
952
|
initialGroupTy = 0;
|
|
923
953
|
rotationStartAngle = 0;
|
|
@@ -1486,4 +1516,4 @@ export {
|
|
|
1486
1516
|
handleTextMouseUp,
|
|
1487
1517
|
updateCodeToggleForShape
|
|
1488
1518
|
};
|
|
1489
|
-
//# sourceMappingURL=chunk-
|
|
1519
|
+
//# sourceMappingURL=chunk-ETAAQUUV.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/tools/textTool.js"],
|
|
4
|
+
"sourcesContent": ["/* eslint-disable */\n// Text tool event handlers - extracted from writeText.js\nimport {\n pushCreateAction,\n pushDeleteAction,\n pushDeleteActionWithAttachments,\n pushTransformAction,\n pushOptionsChangeAction,\n pushFrameAttachmentAction,\n setTextReferences,\n updateSelectedElement\n} from '../core/UndoRedo.js';\nimport { cleanupAttachments, updateAttachedArrows } from './arrowTool.js';\nimport { registerRotationAnchor } from '../core/ScreenSpaceControls.js';\n\nfunction getThemeStroke() { if (typeof document === \"undefined\") return \"#fff\"; return document.body && document.body.classList.contains(\"theme-dark\") ? \"#fff\" : \"#1a1a2e\"; }\nimport {\n addCodeBlock,\n wrapCodeElement,\n selectCodeBlock,\n deselectCodeBlock,\n applySyntaxHighlightingToSVG,\n createHighlightedSVGText,\n updateCodeBackground,\n extractTextFromCodeElement,\n setCodeLanguage,\n getCodeLanguage,\n getSelectedCodeBlock\n} from './codeTool.js';\n\nlet textSize = \"20px\";\nlet textFont = \"lixFont\";\nlet textColor = null;\nlet textAlign = \"left\";\n\nlet textColorOptions = document.querySelectorAll(\".textColorSpan\");\nlet textFontOptions = document.querySelectorAll(\".textFontSpan\");\nlet textSizeOptions = document.querySelectorAll(\".textSizeSpan\");\nlet textAlignOptions = document.querySelectorAll(\".textAlignSpan\");\n\nlet selectedElement = null;\nlet selectionBox = null;\nlet resizeHandles = {};\nlet dragOffsetX, dragOffsetY;\nlet isDragging = false;\nlet isResizing = false;\nlet currentResizeHandle = null;\nlet startBBox = null;\nlet startFontSize = null;\nlet startPoint = null;\nlet isRotating = false;\nlet rotationStartAngle = 0;\nlet rotationStartTransform = null;\nlet initialHandlePosRelGroup = null;\nlet initialFixedHandlePosRelGroup = null;\nlet resizePointerOffsetScreen = null;\nlet resizePadding = 0;\nlet initialGroupMatrix = null;\nlet initialGroupTx = 0;\nlet initialGroupTy = 0;\nlet initialInverseScreenCTM = null;\n\n// Frame attachment variables\nlet draggedShapeInitialFrameText = null;\nlet hoveredFrameText = null;\n\nsetTextReferences(selectedElement, updateSelectionFeedback, svg);\n\n\nfunction switchToSelectionTool() {\n if (window.__sketchStoreApi) {\n window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });\n } else {\n window.isSelectionToolActive = true;\n }\n}\n\n\n// Convert group element to our TextShape class\nfunction wrapTextElement(groupElement) {\n const textShape = new TextShape(groupElement);\n return textShape;\n}\n\nfunction getSVGCoordinates(event, element = svg) {\n if (!svg || !svg.createSVGPoint) {\n console.error(\"SVG element or createSVGPoint method not available.\");\n return { x: 0, y: 0 };\n }\n let pt = svg.createSVGPoint();\n pt.x = event.clientX;\n pt.y = event.clientY;\n\n try {\n let screenCTM = (element && typeof element.getScreenCTM === 'function' && element.getScreenCTM()) || svg.getScreenCTM();\n if (!screenCTM) {\n console.error(\"Could not get Screen CTM.\");\n return { x: event.clientX, y: event.clientY };\n }\n let svgPoint = pt.matrixTransform(screenCTM.inverse());\n return {\n x: svgPoint.x,\n y: svgPoint.y,\n };\n } catch (error) {\n console.error(\"Error getting SVG coordinates:\", error);\n return { x: event.clientX, y: event.clientY };\n }\n}\n\nfunction addText(event) {\n let { x, y } = getSVGCoordinates(event);\n\n let gElement = document.createElementNS(\"http://www.w3.org/2000/svg\", \"g\");\n gElement.setAttribute(\"data-type\", \"text-group\");\n gElement.setAttribute(\"transform\", `translate(${x}, ${y})`);\n\n let textElement = document.createElementNS(\n \"http://www.w3.org/2000/svg\",\n \"text\"\n );\n let textAlignElement = \"start\";\n if (textAlign === \"center\") textAlignElement = \"middle\";\n else if (textAlign === \"right\") textAlignElement = \"end\";\n\n textElement.setAttribute(\"x\", 0);\n textElement.setAttribute(\"y\", 0);\n textElement.setAttribute(\"fill\", textColor ?? getThemeStroke());\n textElement.setAttribute(\"font-size\", textSize);\n textElement.setAttribute(\"font-family\", textFont);\n textElement.setAttribute(\"text-anchor\", textAlignElement);\n textElement.setAttribute(\"cursor\", \"default\");\n textElement.setAttribute(\"white-space\", \"pre\");\n textElement.setAttribute(\"dominant-baseline\", \"hanging\");\n // Issue #48 bugs #1 / #3: reverted the previous `bounding-box` hit\n // area (introduced for #34 #5b) \u2014 extending the text's hit zone to\n // its full bbox meant the negative space between glyphs and around\n // the text was stealing clicks from shapes drawn ON TOP of the text\n // (drag a rect over text \u2192 text intercepts; select text then click a\n // different shape elsewhere \u2192 click lands in text's invisible bbox\n // and the text stays selected). Default `painted` only fires on\n // glyph pixels, which restores the expected pass-through. Trade-off:\n // empty-padding clicks no longer select the text \u2014 the user has to\n // click on the letters.\n textElement.setAttribute(\"pointer-events\", \"painted\");\n textElement.textContent = \"\";\n\n gElement.setAttribute(\"data-x\", x);\n gElement.setAttribute(\"data-y\", y);\n textElement.setAttribute(\"data-initial-size\", textSize);\n textElement.setAttribute(\"data-initial-font\", textFont);\n textElement.setAttribute(\"data-initial-color\", textColor ?? getThemeStroke());\n textElement.setAttribute(\"data-initial-align\", textAlign);\n textElement.setAttribute(\"data-type\", \"text\");\n gElement.appendChild(textElement);\n svg.appendChild(gElement);\n \n // Attach ID to both group and text element\n const shapeID = `text-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n gElement.setAttribute('id', shapeID);\n textElement.setAttribute('id', `${shapeID}-text`);\n \n // Create TextShape wrapper for frame functionality\n const textShape = wrapTextElement(gElement);\n \n // Add to shapes array for arrow attachment and frame functionality\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.push(textShape);\n }\n \n pushCreateAction({\n type: 'text',\n element: textShape,\n shapeName: 'text'\n });\n\n // Check if text was created inside a frame and add it\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.forEach(shape => {\n if (shape.shapeName === 'frame' && shape.isShapeInFrame(textShape)) {\n shape.addShapeToFrame(textShape);\n }\n });\n }\n\n makeTextEditable(textElement, gElement);\n}\n\nfunction makeTextEditable(textElement, groupElement) {\n\n if (document.querySelector(\"textarea.svg-text-editor\")) {\n return;\n }\n\n if (selectedElement) {\n deselectElement();\n }\n\n let input = document.createElement(\"textarea\");\n input.className = \"svg-text-editor\";\n input.setAttribute(\"aria-label\", \"Edit canvas text\");\n input.setAttribute(\"data-editing\", \"true\");\n\n // Prefer the persisted source so re-opening the editor preserves only\n // the line breaks the user explicitly inserted with Shift+Enter.\n let textContent = '';\n const storedSource = textElement.getAttribute('data-wrap-source');\n if (storedSource !== null && storedSource !== '') {\n textContent = storedSource.replace(/ /g, '\\u00A0');\n } else {\n const tspans = textElement.querySelectorAll('tspan');\n if (tspans.length > 0) {\n tspans.forEach((tspan, index) => {\n textContent += tspan.textContent.replace(/ /g, '\\u00A0');\n if (index < tspans.length - 1) textContent += '\\n';\n });\n } else {\n textContent = textElement.textContent.replace(/ /g, '\\u00A0');\n }\n }\n\n input.value = textContent;\n input.style.position = \"fixed\";\n input.style.outline = \"none\";\n input.style.padding = \"1px\";\n input.style.margin = \"0\";\n input.style.boxSizing = \"border-box\";\n input.style.overflow = \"hidden\";\n input.style.resize = \"none\";\n input.style.whiteSpace = \"pre\";\n input.style.minHeight = \"1.2em\";\n input.style.zIndex = \"10000\";\n\n const currentFontSize = textElement.getAttribute(\"font-size\") || \"20px\";\n const currentFontFamily = textElement.getAttribute(\"font-family\") || \"lixFont\";\n const currentFill = textElement.getAttribute(\"fill\") || \"#fff\";\n const currentAnchor = textElement.getAttribute(\"text-anchor\") || \"start\";\n\n // Anchor the HTML editor to the SVG text origin, transformed into viewport\n // coordinates. A newly-created <text> is empty, so getBoundingClientRect()\n // reports the SVG's top-left corner instead of the clicked canvas point.\n // The CTM remains valid for empty text and also accounts for pan, zoom,\n // split-view cropping, and frame transforms.\n const groupCTM = groupElement.getScreenCTM() || svg.getScreenCTM();\n const textOrigin = svg.createSVGPoint();\n textOrigin.x = parseFloat(textElement.getAttribute(\"x\")) || 0;\n textOrigin.y = parseFloat(textElement.getAttribute(\"y\")) || 0;\n const screenOrigin = groupCTM\n ? textOrigin.matrixTransform(groupCTM)\n : { x: 0, y: 0 };\n const anchorTranslateX = currentAnchor === \"middle\" ? \"-50%\" : currentAnchor === \"end\" ? \"-100%\" : \"0\";\n\n input.style.left = `${screenOrigin.x}px`;\n input.style.top = `${screenOrigin.y}px`;\n input.style.transform = `translateX(${anchorTranslateX})`;\n input.style.transformOrigin = \"top left\";\n\n const svgZoomFactor = groupCTM ? Math.hypot(groupCTM.a, groupCTM.b) : 1;\n input.style.width = \"auto\";\n input.style.height = \"auto\";\n\n // Scale font-size by zoom so the textarea matches what the user sees on canvas\n const rawSize = parseFloat(currentFontSize) || 20;\n const scaledFontSize = `${rawSize * svgZoomFactor}px`;\n\n input.style.minWidth = \"150px\";\n input.style.minHeight = \"1.5em\";\n input.style.width = \"auto\";\n input.style.height = \"auto\";\n input.style.overflow = \"visible\";\n input.style.whiteSpace = \"pre\";\n input.style.wordBreak = \"normal\";\n input.style.overflowWrap = \"normal\";\n input.style.fontSize = scaledFontSize;\n input.style.fontFamily = currentFontFamily;\n input.style.color = currentFill;\n input.style.lineHeight = \"1.2em\";\n input.style.textAlign = currentAnchor === \"middle\" ? \"center\" : currentAnchor === \"end\" ? \"right\" : \"left\";\n input.style.backgroundColor = \"transparent\";\n input.style.border = \"none\";\n input.style.boxShadow = \"none\";\n input.style.outline = \"none\";\n document.body.appendChild(input);\n\n const adjustHeight = () => {\n input.style.height = 'auto';\n input.style.height = input.scrollHeight + 'px';\n input.style.overflowY = 'hidden';\n };\n\n const adjustWidth = () => {\n input.style.width = 'auto';\n const contentWidth = Math.max(input.scrollWidth, 150);\n input.style.width = contentWidth + 'px';\n input.style.overflowX = 'hidden';\n };\n adjustHeight();\n adjustWidth();\n\n setTimeout(() => {\n input.focus();\n input.select();\n }, 50);\n\n input.addEventListener('input', adjustHeight);\n input.addEventListener('input', adjustWidth);\n\n input.addEventListener(\"keydown\", function (e) {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n renderText(input, textElement, true);\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n renderText(input, textElement, true);\n }\n });\n\n input.originalTextElement = textElement;\n input.textGroup = groupElement;\n\n const handleClickOutside = (event) => {\n if (!input.contains(event.target)) {\n renderText(input, textElement, true);\n document.removeEventListener('pointerdown', handleClickOutside, true);\n }\n };\n document.addEventListener('pointerdown', handleClickOutside, true);\n input.handleClickOutside = handleClickOutside;\n\n // Set text cursor on the element during edit mode\n const textEl = groupElement.querySelector('text');\n if (textEl) textEl.setAttribute(\"cursor\", \"text\");\n\n groupElement.style.display = \"none\";\n}\n\n/** Render only explicit editor line breaks; text never soft-wraps. */\nfunction paintTextContent(textElement, source) {\n while (textElement.firstChild) textElement.removeChild(textElement.firstChild);\n const x = textElement.getAttribute('x') || 0;\n const NS = 'http://www.w3.org/2000/svg';\n const finalLines = (source || '').split('\\n').map((line) => line.replace(/\u00A0/g, ' '));\n\n finalLines.forEach((line, i) => {\n const tspan = document.createElementNS(NS, 'tspan');\n tspan.setAttribute('x', x);\n tspan.setAttribute('dy', i === 0 ? '0' : '1.2em');\n tspan.textContent = line.length ? line : ' ';\n textElement.appendChild(tspan);\n });\n}\n\nfunction renderText(input, textElement, deleteIfEmpty = false) {\n if (!input || !document.body.contains(input)) {\n return;\n }\n\n const text = input.value || \"\";\n const gElement = input.textGroup;\n\n if (input.handleClickOutside) {\n document.removeEventListener('pointerdown', input.handleClickOutside, true);\n }\n\n document.body.removeChild(input);\n\n // Reset cursor back to default after edit mode ends\n if (textElement) textElement.setAttribute(\"cursor\", \"default\");\n\n if (!gElement || !textElement) {\n return;\n }\n\n if (!gElement.parentNode) {\n if (selectedElement === gElement) {\n deselectElement();\n }\n return;\n }\n\n if (deleteIfEmpty && text.trim() === \"\") {\n // Find the TextShape wrapper\n let textShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n textShape = shapes.find(shape => shape.shapeName === 'text' && shape.group === gElement);\n if (textShape) {\n const idx = shapes.indexOf(textShape);\n if (idx !== -1) shapes.splice(idx, 1);\n }\n }\n\n // Use enhanced delete action for text with arrow attachments\n pushDeleteActionWithAttachments({\n type: 'text',\n element: textShape || gElement,\n shapeName: 'text'\n });\n\n // Clean up any arrow attachments before deleting\n if (typeof cleanupAttachments === 'function') {\n cleanupAttachments(gElement);\n }\n\n svg.removeChild(gElement);\n if (selectedElement === gElement) {\n selectedElement = null;\n removeSelectionFeedback();\n }\n } else {\n // Persist and render only the user's explicit Shift+Enter line\n // breaks. Long lines remain long on the infinite canvas.\n const cleanSource = text.replace(/\\u00A0/g, ' ');\n textElement.setAttribute('data-wrap-source', cleanSource);\n textElement.removeAttribute('data-wrap-width');\n paintTextContent(textElement, cleanSource);\n\n gElement.style.display = 'block';\n\n // Update attached arrows after text content change\n updateAttachedArrows(gElement);\n\n if (selectedElement === gElement) {\n setTimeout(updateSelectionFeedback, 0);\n }\n }\n\n // After rendering text, switch to selection tool and auto-select\n if (gElement.parentNode) {\n switchToSelectionTool();\n // Defer selection so the tool switch (async React state) completes first\n requestAnimationFrame(() => selectElement(gElement));\n }\n}\n\nfunction createSelectionFeedback(groupElement) {\n if (!groupElement) return;\n removeSelectionFeedback();\n\n const textElement = groupElement.querySelector('text');\n if (!textElement) {\n return;\n }\n\n const bbox = textElement.getBBox();\n\n const zoom = window.currentZoom || 1;\n const padding = 8 / zoom;\n const handleSize = 10 / zoom;\n const handleOffset = handleSize / 2;\n const anchorStrokeWidth = 2;\n\n const selX = bbox.x - padding;\n const selY = bbox.y - padding;\n const selWidth = bbox.width + 2 * padding;\n const selHeight = bbox.height + 2 * padding;\n\n const outlinePoints = [\n [selX, selY],\n [selX + selWidth, selY],\n [selX + selWidth, selY + selHeight],\n [selX, selY + selHeight],\n [selX, selY]\n ];\n\n const pointsAttr = outlinePoints.map(p => p.join(',')).join(' ');\n selectionBox = document.createElementNS(\"http://www.w3.org/2000/svg\", \"polyline\");\n selectionBox.setAttribute(\"class\", \"selection-box\");\n selectionBox.setAttribute(\"points\", pointsAttr);\n selectionBox.setAttribute(\"fill\", \"none\");\n selectionBox.setAttribute(\"stroke\", \"#5B57D1\");\n selectionBox.setAttribute(\"stroke-width\", \"1.5\");\n selectionBox.setAttribute(\"stroke-dasharray\", `${4 / zoom} ${2 / zoom}`);\n selectionBox.setAttribute(\"vector-effect\", \"non-scaling-stroke\");\n selectionBox.setAttribute(\"pointer-events\", \"none\");\n groupElement.appendChild(selectionBox);\n\n // Corner anchors scale font size. Width handles are intentionally\n // omitted because text width is content-driven and never soft-wraps.\n const handlesData = [\n { name: 'nw', x: selX, y: selY, cursor: 'nwse-resize' },\n { name: 'ne', x: selX + selWidth, y: selY, cursor: 'nesw-resize' },\n { name: 'sw', x: selX, y: selY + selHeight, cursor: 'nesw-resize' },\n { name: 'se', x: selX + selWidth, y: selY + selHeight, cursor: 'nwse-resize' },\n ];\n\n resizeHandles = {};\n handlesData.forEach(handle => {\n const handleRect = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n handleRect.setAttribute(\"class\", `resize-handle resize-handle-${handle.name}`);\n handleRect.setAttribute(\"x\", handle.x - handleOffset);\n handleRect.setAttribute(\"y\", handle.y - handleOffset);\n handleRect.setAttribute(\"width\", handleSize);\n handleRect.setAttribute(\"height\", handleSize);\n handleRect.setAttribute(\"fill\", \"#121212\");\n handleRect.setAttribute(\"stroke\", \"#5B57D1\");\n handleRect.setAttribute(\"stroke-width\", anchorStrokeWidth);\n handleRect.setAttribute(\"vector-effect\", \"non-scaling-stroke\");\n handleRect.style.cursor = handle.cursor;\n handleRect.setAttribute(\"data-anchor\", handle.name);\n groupElement.appendChild(handleRect);\n resizeHandles[handle.name] = handleRect;\n\n handleRect.addEventListener('pointerdown', (e) => {\n if (window.isSelectionToolActive) {\n e.stopPropagation();\n handleRect.setPointerCapture?.(e.pointerId);\n startResize(e, handle.name);\n }\n });\n });\n\n const rotationAnchorPos = { x: selX + selWidth / 2, y: selY - 30 };\n const rotationAnchor = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n rotationAnchor.setAttribute('cx', rotationAnchorPos.x);\n rotationAnchor.setAttribute('cy', rotationAnchorPos.y);\n rotationAnchor.setAttribute('r', 8);\n rotationAnchor.setAttribute('class', 'rotate-anchor');\n rotationAnchor.setAttribute('fill', '#121212');\n rotationAnchor.setAttribute('stroke', '#5B57D1');\n rotationAnchor.setAttribute('stroke-width', anchorStrokeWidth);\n rotationAnchor.setAttribute('vector-effect', 'non-scaling-stroke');\n rotationAnchor.style.cursor = 'grab';\n rotationAnchor.setAttribute('pointer-events', 'all');\n groupElement.appendChild(rotationAnchor);\n registerRotationAnchor(rotationAnchor, { radius: 8, edgeY: selY });\n\n resizeHandles.rotate = rotationAnchor;\n\n rotationAnchor.addEventListener('pointerdown', (e) => {\n if (window.isSelectionToolActive) {\n e.stopPropagation();\n startRotation(e);\n }\n });\n\n rotationAnchor.addEventListener('mouseover', function() {\n if (!isResizing && !isDragging) {\n this.style.cursor = 'grab';\n }\n });\n\n rotationAnchor.addEventListener('mouseout', function() {\n if (!isResizing && !isDragging) {\n this.style.cursor = 'default';\n }\n });\n}\n\nfunction updateSelectionFeedback() {\n if (!selectedElement || !selectionBox) return;\n\n const textElement = selectedElement.querySelector('text');\n if (!textElement) return;\n\n const wasHidden = selectedElement.style.display === 'none';\n if (wasHidden) selectedElement.style.display = 'block';\n\n const bbox = textElement.getBBox();\n\n if (wasHidden) selectedElement.style.display = 'none';\n\n if (bbox.width === 0 && bbox.height === 0 && textElement.textContent.trim() !== \"\") {\n }\n\n const zoom2 = window.currentZoom || 1;\n const padding = 8 / zoom2;\n const handleSize = 10 / zoom2;\n const handleOffset = handleSize / 2;\n\n const selX = bbox.x - padding;\n const selY = bbox.y - padding;\n const selWidth = Math.max(bbox.width + 2 * padding, handleSize);\n const selHeight = Math.max(bbox.height + 2 * padding, handleSize);\n\n const outlinePoints = [\n [selX, selY],\n [selX + selWidth, selY],\n [selX + selWidth, selY + selHeight],\n [selX, selY + selHeight],\n [selX, selY]\n ];\n\n const pointsAttr = outlinePoints.map(p => p.join(',')).join(' ');\n selectionBox.setAttribute(\"points\", pointsAttr);\n\n const handlesData = [\n { name: 'nw', x: selX, y: selY },\n { name: 'ne', x: selX + selWidth, y: selY },\n { name: 'sw', x: selX, y: selY + selHeight },\n { name: 'se', x: selX + selWidth, y: selY + selHeight },\n ];\n\n handlesData.forEach(handle => {\n const handleRect = resizeHandles[handle.name];\n if (handleRect) {\n handleRect.setAttribute(\"x\", handle.x - handleOffset);\n handleRect.setAttribute(\"y\", handle.y - handleOffset);\n }\n });\n\n const rotationAnchor = resizeHandles.rotate;\n if (rotationAnchor) {\n const rotationAnchorPos = { x: selX + selWidth / 2, y: selY - 30 / zoom2 };\n rotationAnchor.setAttribute('cx', rotationAnchorPos.x);\n rotationAnchor.setAttribute('cy', rotationAnchorPos.y);\n }\n}\n\nfunction startRotation(event) {\n if (!selectedElement || event.button !== 0) return;\n event.preventDefault();\n event.stopPropagation();\n\n isRotating = true;\n isDragging = false;\n isResizing = false;\n\n const textElement = selectedElement.querySelector('text');\n if (!textElement) return;\n\n const bbox = textElement.getBBox();\n const centerX = bbox.x + bbox.width / 2;\n const centerY = bbox.y + bbox.height / 2;\n\n const mousePos = getSVGCoordinates(event);\n\n let centerPoint = svg.createSVGPoint();\n centerPoint.x = centerX;\n centerPoint.y = centerY;\n\n const groupTransform = selectedElement.transform.baseVal.consolidate();\n if (groupTransform) {\n centerPoint = centerPoint.matrixTransform(groupTransform.matrix);\n }\n\n rotationStartAngle = Math.atan2(mousePos.y - centerPoint.y, mousePos.x - centerPoint.x) * 180 / Math.PI;\n\n const currentTransform = selectedElement.transform.baseVal.consolidate();\n rotationStartTransform = currentTransform ? currentTransform.matrix : svg.createSVGMatrix();\n\n svg.style.cursor = 'grabbing';\n\n window.addEventListener('pointermove', handleMouseMove);\n window.addEventListener('pointerup', handleMouseUp);\n}\n\nfunction removeSelectionFeedback(element) {\n const target = element || selectedElement;\n if (target) {\n target.querySelectorAll(\".selection-box, .resize-handle, .rotate-anchor\").forEach(el => el.remove());\n }\n // Also clean up any orphaned selection elements in all text groups\n svg.querySelectorAll('g[data-type=\"text-group\"] .selection-box, g[data-type=\"text-group\"] .resize-handle, g[data-type=\"text-group\"] .rotate-anchor').forEach(el => el.remove());\n\n selectionBox = null;\n resizeHandles = {};\n}\n\nfunction selectElement(groupElement) {\n if (!groupElement || !groupElement.parentNode) return;\n if (groupElement === selectedElement) return;\n\n deselectElement();\n selectedElement = groupElement;\n selectedElement.classList.add(\"selected\");\n createSelectionFeedback(selectedElement);\n\n updateSelectedElement(selectedElement);\n updateCodeToggleForShape('text');\n\n // Update global currentShape so EventDispatcher can route to other tools later\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n const wrapper = shapes.find(s => s.element === groupElement || s.group === groupElement);\n if (wrapper) {\n currentShape = wrapper;\n }\n }\n\n // Show text property panel when text is selected\n if (window.__showSidebarForShape) window.__showSidebarForShape('text');\n}\n\nfunction deselectElement() {\n const activeEditor = document.querySelector(\"textarea.svg-text-editor\");\n if (activeEditor) {\n let textElement = activeEditor.originalTextElement;\n if (textElement) {\n renderText(activeEditor, textElement, true);\n } else if (document.body.contains(activeEditor)) {\n document.body.removeChild(activeEditor);\n }\n }\n\n if (selectedElement) {\n removeSelectionFeedback();\n selectedElement.classList.remove(\"selected\");\n selectedElement = null;\n\n updateSelectedElement(null);\n\n // Clear global currentShape if it was a text shape\n if (currentShape && (currentShape.shapeName === 'text' || currentShape.shapeName === 'code')) {\n currentShape = null;\n }\n\n // Hide text property panel if we're in selection mode (not text tool)\n if (isSelectionToolActive) {\n textSideBar.classList.add(\"hidden\");\n }\n }\n\n if (isRotating) {\n isRotating = false;\n rotationStartAngle = 0;\n rotationStartTransform = null;\n svg.style.cursor = 'default';\n\n window.removeEventListener('pointermove', handleMouseMove);\n window.removeEventListener('pointerup', handleMouseUp);\n }\n}\n\nfunction startDrag(event) {\n if (!selectedElement || event.button !== 0) return;\n\n if (event.target.closest('.resize-handle')) {\n return;\n }\n\n isDragging = true;\n isResizing = false;\n event.preventDefault();\n\n const currentTransform = selectedElement.transform.baseVal.consolidate();\n const initialTranslateX = currentTransform ? currentTransform.matrix.e : 0;\n const initialTranslateY = currentTransform ? currentTransform.matrix.f : 0;\n\n startPoint = getSVGCoordinates(event);\n\n dragOffsetX = startPoint.x - initialTranslateX;\n dragOffsetY = startPoint.y - initialTranslateY;\n\n // Find the TextShape wrapper for frame functionality\n let textShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n textShape = shapes.find(shape => shape.shapeName === 'text' && shape.group === selectedElement);\n }\n\n if (textShape) {\n // Store initial frame state\n draggedShapeInitialFrameText = textShape.parentFrame || null;\n \n // Temporarily remove from frame clipping if dragging\n if (textShape.parentFrame) {\n textShape.parentFrame.temporarilyRemoveFromFrame(textShape);\n }\n }\n\n svg.style.cursor = 'grabbing';\n\n svg.addEventListener('pointermove', handleMouseMove);\n svg.addEventListener('pointerup', handleMouseUp);\n}\n\nfunction startResize(event, anchor) {\n if (!selectedElement || event.button !== 0) return;\n event.preventDefault();\n event.stopPropagation();\n\n isResizing = true;\n isDragging = false;\n currentResizeHandle = anchor;\n\n const textElement = selectedElement.querySelector('text');\n if (!textElement) {\n isResizing = false;\n return;\n }\n\n startBBox = textElement.getBBox();\n startFontSize = parseFloat(textElement.getAttribute(\"font-size\") || 30);\n if (isNaN(startFontSize)) startFontSize = 30;\n\n startPoint = getSVGCoordinates(event, selectedElement);\n\n // Freeze the group's screen CTM at resize start so mouse\u2192local mapping stays stable\n const groupScreenCTM = selectedElement.getScreenCTM();\n initialInverseScreenCTM = groupScreenCTM ? groupScreenCTM.inverse() : null;\n\n const currentTransform = selectedElement.transform.baseVal.consolidate();\n const matrix = currentTransform?.matrix;\n initialGroupMatrix = matrix ? {\n a: matrix.a, b: matrix.b, c: matrix.c,\n d: matrix.d, e: matrix.e, f: matrix.f,\n } : { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 };\n initialGroupTx = initialGroupMatrix.e;\n initialGroupTy = initialGroupMatrix.f;\n\n resizePadding = 8 / (window.currentZoom || 1);\n const startX = startBBox.x - resizePadding;\n const startY = startBBox.y - resizePadding;\n const startWidth = startBBox.width + 2 * resizePadding;\n const startHeight = startBBox.height + 2 * resizePadding;\n\n let hx = startX;\n let hy = startY;\n if (anchor.includes('e')) { hx = startX + startWidth; }\n if (anchor.includes('s')) { hy = startY + startHeight; }\n initialHandlePosRelGroup = { x: hx, y: hy };\n\n let fx = startX + startWidth;\n let fy = startY + startHeight;\n if (anchor.includes('e')) { fx = startX; }\n if (anchor.includes('s')) { fy = startY; }\n initialFixedHandlePosRelGroup = { x: fx, y: fy };\n\n const handlePoint = svg.createSVGPoint();\n handlePoint.x = hx;\n handlePoint.y = hy;\n const handleScreen = groupScreenCTM\n ? handlePoint.matrixTransform(groupScreenCTM)\n : { x: event.clientX, y: event.clientY };\n resizePointerOffsetScreen = {\n x: event.clientX - handleScreen.x,\n y: event.clientY - handleScreen.y,\n };\n\n svg.style.cursor = resizeHandles[anchor]?.style.cursor || 'default';\n\n svg.addEventListener('pointermove', handleMouseMove);\n svg.addEventListener('pointerup', handleMouseUp);\n}\n\n\nconst handleMouseMove = (event) => {\n if (!selectedElement) return;\n event.preventDefault();\n\n // Keep lastMousePos in screen coordinates for other functions\n const svgRect = svg.getBoundingClientRect();\n lastMousePos = {\n x: event.clientX - svgRect.left, \n y: event.clientY - svgRect.top\n };\n\n if (isDragging) {\n const currentPoint = getSVGCoordinates(event);\n const newTranslateX = currentPoint.x - dragOffsetX;\n const newTranslateY = currentPoint.y - dragOffsetY;\n\n const currentTransform = selectedElement.transform.baseVal.consolidate();\n if (currentTransform) {\n const matrix = currentTransform.matrix;\n const angle = Math.atan2(matrix.b, matrix.a) * 180 / Math.PI;\n\n const textElement = selectedElement.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\n selectedElement.setAttribute('transform',\n `translate(${newTranslateX}, ${newTranslateY}) rotate(${angle}, ${centerX}, ${centerY})`\n );\n } else {\n selectedElement.setAttribute('transform', `translate(${newTranslateX}, ${newTranslateY})`);\n }\n } else {\n selectedElement.setAttribute('transform', `translate(${newTranslateX}, ${newTranslateY})`);\n }\n\n // Update frame containment for TextShape wrapper\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n const textShape = shapes.find(shape => shape.shapeName === 'text' && shape.group === selectedElement);\n if (textShape) {\n textShape.updateFrameContainment();\n }\n }\n\n // Update attached arrows during dragging\n updateAttachedArrows(selectedElement);\n\n } else if (isResizing) {\n const textElement = selectedElement.querySelector('text');\n if (!textElement || !startBBox || startFontSize === null || !startPoint ||\n !initialHandlePosRelGroup || !initialFixedHandlePosRelGroup || !initialGroupMatrix) return;\n\n // Use the frozen initial CTM so the mapping doesn't shift as we change the group transform\n let currentPoint;\n if (initialInverseScreenCTM) {\n const pt = svg.createSVGPoint();\n pt.x = event.clientX - (resizePointerOffsetScreen?.x || 0);\n pt.y = event.clientY - (resizePointerOffsetScreen?.y || 0);\n currentPoint = pt.matrixTransform(initialInverseScreenCTM);\n } else {\n currentPoint = getSVGCoordinates({\n clientX: event.clientX - (resizePointerOffsetScreen?.x || 0),\n clientY: event.clientY - (resizePointerOffsetScreen?.y || 0),\n }, selectedElement);\n }\n\n const startWidth = startBBox.width;\n const startHeight = startBBox.height;\n const directionX = currentResizeHandle.includes('e') ? 1 : -1;\n const directionY = currentResizeHandle.includes('s') ? 1 : -1;\n const desiredWidth = directionX * (currentPoint.x - initialFixedHandlePosRelGroup.x) - 2 * resizePadding;\n const desiredHeight = directionY * (currentPoint.y - initialFixedHandlePosRelGroup.y) - 2 * resizePadding;\n const denominator = startWidth * startWidth + startHeight * startHeight;\n const chosenScale = denominator > 0\n ? (startWidth * desiredWidth + startHeight * desiredHeight) / denominator\n : 1;\n\n const minScale = 0.1;\n const maxScale = 10.0;\n const clampedScale = Math.max(minScale, Math.min(chosenScale, maxScale));\n\n const newFontSize = startFontSize * clampedScale;\n const minFontSize = 5;\n const finalFontSize = Math.max(newFontSize, minFontSize);\n\n textElement.setAttribute(\"font-size\", `${finalFontSize}px`);\n\n const currentBBox = textElement.getBBox();\n\n let newAnchorX, newAnchorY;\n\n switch (currentResizeHandle) {\n case 'nw':\n newAnchorX = currentBBox.x + currentBBox.width + resizePadding;\n newAnchorY = currentBBox.y + currentBBox.height + resizePadding;\n break;\n case 'ne':\n newAnchorX = currentBBox.x - resizePadding;\n newAnchorY = currentBBox.y + currentBBox.height + resizePadding;\n break;\n case 'sw':\n newAnchorX = currentBBox.x + currentBBox.width + resizePadding;\n newAnchorY = currentBBox.y - resizePadding;\n break;\n case 'se':\n newAnchorX = currentBBox.x - resizePadding;\n newAnchorY = currentBBox.y - resizePadding;\n break;\n }\n\n const deltaX = initialFixedHandlePosRelGroup.x - newAnchorX;\n const deltaY = initialFixedHandlePosRelGroup.y - newAnchorY;\n let newGroupTx = initialGroupMatrix.e + initialGroupMatrix.a * deltaX + initialGroupMatrix.c * deltaY;\n let newGroupTy = initialGroupMatrix.f + initialGroupMatrix.b * deltaX + initialGroupMatrix.d * deltaY;\n const matrixTransform = () => `matrix(${initialGroupMatrix.a} ${initialGroupMatrix.b} ${initialGroupMatrix.c} ${initialGroupMatrix.d} ${newGroupTx} ${newGroupTy})`;\n selectedElement.setAttribute('transform', matrixTransform());\n\n // Uniform font scaling cannot satisfy arbitrary x/y pointer movement\n // while also keeping the opposite corner perfectly fixed. Prefer the\n // user's dragged corner: correct the residual in parent coordinates so\n // the handle stays under the exact grab point at every zoom/rotation.\n const draggedX = currentBBox.x + (currentResizeHandle.includes('e') ? currentBBox.width + resizePadding : -resizePadding);\n const draggedY = currentBBox.y + (currentResizeHandle.includes('s') ? currentBBox.height + resizePadding : -resizePadding);\n const draggedPoint = svg.createSVGPoint();\n draggedPoint.x = draggedX;\n draggedPoint.y = draggedY;\n const resizedScreenCTM = selectedElement.getScreenCTM();\n const parentScreenCTM = selectedElement.parentNode?.getScreenCTM?.();\n if (resizedScreenCTM && parentScreenCTM) {\n const actualScreen = draggedPoint.matrixTransform(resizedScreenCTM);\n const parentInverse = parentScreenCTM.inverse();\n const targetScreenPoint = svg.createSVGPoint();\n targetScreenPoint.x = event.clientX - (resizePointerOffsetScreen?.x || 0);\n targetScreenPoint.y = event.clientY - (resizePointerOffsetScreen?.y || 0);\n const actualScreenPoint = svg.createSVGPoint();\n actualScreenPoint.x = actualScreen.x;\n actualScreenPoint.y = actualScreen.y;\n const targetParent = targetScreenPoint.matrixTransform(parentInverse);\n const actualParent = actualScreenPoint.matrixTransform(parentInverse);\n newGroupTx += targetParent.x - actualParent.x;\n newGroupTy += targetParent.y - actualParent.y;\n selectedElement.setAttribute('transform', matrixTransform());\n }\n\n // Update attached arrows during resizing\n updateAttachedArrows(selectedElement);\n\n clearTimeout(selectedElement.updateFeedbackTimeout);\n selectedElement.updateFeedbackTimeout = setTimeout(() => {\n updateSelectionFeedback();\n delete selectedElement.updateFeedbackTimeout;\n }, 0);\n\n } else if (isRotating) {\n const textElement = selectedElement.querySelector('text');\n if (!textElement) return;\n\n const bbox = textElement.getBBox();\n const centerX = bbox.x + bbox.width / 2;\n const centerY = bbox.y + bbox.height / 2;\n\n const mousePos = getSVGCoordinates(event);\n\n let centerPoint = svg.createSVGPoint();\n centerPoint.x = centerX;\n centerPoint.y = centerY;\n\n const groupTransform = selectedElement.transform.baseVal.consolidate();\n if (groupTransform) {\n centerPoint = centerPoint.matrixTransform(groupTransform.matrix);\n }\n\n const currentAngle = Math.atan2(mousePos.y - centerPoint.y, mousePos.x - centerPoint.x) * 180 / Math.PI;\n\n const rotationDiff = currentAngle - rotationStartAngle;\n\n const newTransform = `translate(${rotationStartTransform.e}, ${rotationStartTransform.f}) rotate(${rotationDiff}, ${centerX}, ${centerY})`;\n selectedElement.setAttribute('transform', newTransform);\n\n // Update attached arrows during rotation\n updateAttachedArrows(selectedElement);\n\n updateSelectionFeedback();\n }\n};\n\n\n\nconst handleMouseUp = (event) => {\n if (event.button !== 0) return;\n\n if (isDragging && selectedElement) {\n const currentTransform = selectedElement.transform.baseVal.consolidate();\n if (currentTransform) {\n const finalTranslateX = currentTransform.matrix.e;\n const finalTranslateY = currentTransform.matrix.f;\n\n const initialX = parseFloat(selectedElement.getAttribute(\"data-x\")) || 0;\n const initialY = parseFloat(selectedElement.getAttribute(\"data-y\")) || 0;\n\n // Find the TextShape wrapper for frame tracking\n let textShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n textShape = shapes.find(shape => shape.shapeName === 'text' && shape.group === selectedElement);\n }\n\n // Add frame information for undo tracking\n const oldPosWithFrame = {\n x: initialX,\n y: initialY,\n rotation: extractRotationFromTransform(selectedElement) || 0,\n parentFrame: draggedShapeInitialFrameText\n };\n // Issue #34 bug #2: hoveredFrameText is the actual destination\n // tracked during drag \u2014 textShape.parentFrame is still the OLD\n // frame at this point.\n const newPosWithFrame = {\n x: finalTranslateX,\n y: finalTranslateY,\n rotation: extractRotationFromTransform(selectedElement) || 0,\n parentFrame: hoveredFrameText || null,\n };\n\n const stateChanged = initialX !== finalTranslateX || initialY !== finalTranslateY;\n const frameChanged = oldPosWithFrame.parentFrame !== newPosWithFrame.parentFrame;\n\n if (stateChanged || frameChanged) {\n pushTransformAction(\n {\n type: 'text',\n element: selectedElement,\n shapeName: 'text'\n },\n oldPosWithFrame,\n newPosWithFrame\n );\n }\n\n // Handle frame containment changes after drag\n if (textShape) {\n const finalFrame = hoveredFrameText;\n \n // If shape moved to a different frame\n if (draggedShapeInitialFrameText !== finalFrame) {\n // Remove from initial frame\n if (draggedShapeInitialFrameText) {\n draggedShapeInitialFrameText.removeShapeFromFrame(textShape);\n }\n \n // Add to new frame\n if (finalFrame) {\n finalFrame.addShapeToFrame(textShape);\n }\n \n // Track the frame change for undo\n if (frameChanged) {\n pushFrameAttachmentAction(finalFrame || draggedShapeInitialFrameText, textShape, \n finalFrame ? 'attach' : 'detach', draggedShapeInitialFrameText);\n }\n } else if (draggedShapeInitialFrameText) {\n // Shape stayed in same frame, restore clipping\n draggedShapeInitialFrameText.restoreToFrame(textShape);\n }\n }\n\n selectedElement.setAttribute(\"data-x\", finalTranslateX);\n selectedElement.setAttribute(\"data-y\", finalTranslateY);\n }\n\n draggedShapeInitialFrameText = null;\n\n } else if (isResizing && selectedElement) {\n const textElement = selectedElement.querySelector('text');\n if (textElement) {\n const finalFontSize = textElement.getAttribute(\"font-size\");\n const initialFontSize = startFontSize;\n\n const currentTransform = selectedElement.transform.baseVal.consolidate();\n if (currentTransform && initialFontSize !== parseFloat(finalFontSize)) {\n const finalTranslateX = currentTransform.matrix.e;\n const finalTranslateY = currentTransform.matrix.f;\n\n pushTransformAction(\n {\n type: 'text',\n element: selectedElement,\n shapeName: 'text'\n },\n {\n x: initialGroupTx,\n y: initialGroupTy,\n fontSize: initialFontSize,\n rotation: extractRotationFromTransform(selectedElement) || 0\n },\n {\n x: finalTranslateX,\n y: finalTranslateY,\n fontSize: parseFloat(finalFontSize),\n rotation: extractRotationFromTransform(selectedElement) || 0\n }\n );\n\n selectedElement.setAttribute(\"data-x\", finalTranslateX);\n selectedElement.setAttribute(\"data-y\", finalTranslateY);\n }\n\n clearTimeout(selectedElement.updateFeedbackTimeout);\n updateSelectionFeedback();\n }\n } else if (isRotating && selectedElement) {\n const currentTransform = selectedElement.transform.baseVal.consolidate();\n if (currentTransform && rotationStartTransform) {\n const initialRotation = Math.atan2(rotationStartTransform.b, rotationStartTransform.a) * 180 / Math.PI;\n const finalRotation = extractRotationFromTransform(selectedElement) || 0;\n\n if (Math.abs(initialRotation - finalRotation) > 1) {\n pushTransformAction(\n {\n type: 'text',\n element: selectedElement,\n shapeName: 'text'\n },\n {\n x: rotationStartTransform.e,\n y: rotationStartTransform.f,\n rotation: initialRotation\n },\n {\n x: currentTransform.matrix.e,\n y: currentTransform.matrix.f,\n rotation: finalRotation\n }\n );\n }\n\n }\n updateSelectionFeedback();\n }\n\n // Clear frame highlighting\n if (hoveredFrameText) {\n hoveredFrameText.removeHighlight();\n hoveredFrameText = null;\n }\n\n isDragging = false;\n isResizing = false;\n isRotating = false;\n currentResizeHandle = null;\n startPoint = null;\n startBBox = null;\n startFontSize = null;\n dragOffsetX = undefined;\n dragOffsetY = undefined;\n initialHandlePosRelGroup = null;\n initialFixedHandlePosRelGroup = null;\n resizePointerOffsetScreen = null;\n resizePadding = 0;\n initialGroupMatrix = null;\n initialGroupTx = 0;\n initialGroupTy = 0;\n rotationStartAngle = 0;\n rotationStartTransform = null;\n\n // Restore cursor based on context - keep pointer if over selected text\n svg.style.cursor = isSelectionToolActive ? 'default' : (isTextToolActive ? 'text' : 'default');\n\n // Ensure selection feedback is refreshed after transforms\n if (selectedElement) {\n setTimeout(updateSelectionFeedback, 0);\n }\n\n svg.removeEventListener('pointermove', handleMouseMove);\n svg.removeEventListener('pointerup', handleMouseUp);\n window.removeEventListener('pointermove', handleMouseMove);\n window.removeEventListener('pointerup', handleMouseUp);\n};\n\nfunction extractRotationFromTransform(element) {\n const currentTransform = element.transform.baseVal.consolidate();\n if (currentTransform) {\n const matrix = currentTransform.matrix;\n return Math.atan2(matrix.b, matrix.a) * 180 / Math.PI;\n }\n return 0;\n}\n\n// EXPORTED EVENT HANDLERS\nconst handleTextMouseDown = function (e) {\n if (!e.target) return;\n const activeEditor = document.querySelector(\"textarea.svg-text-editor\");\n if (activeEditor && activeEditor.contains(e.target)) {\n return;\n }\n if (activeEditor && !activeEditor.contains(e.target)) {\n let textElement = activeEditor.originalTextElement;\n if (textElement) {\n // renderText switches to selection tool and auto-selects the text as a side effect.\n // Return early so we don't continue with stale tool state.\n renderText(activeEditor, textElement, true);\n return;\n } else if (document.body.contains(activeEditor)){\n document.body.removeChild(activeEditor);\n }\n }\n\n const targetGroup = e.target.closest('g[data-type=\"text-group\"]');\n\n if (isSelectionToolActive && e.button === 0) {\n if (targetGroup) {\n if (e.target.closest('.resize-handle')) {\n return;\n }\n\n // Double-click on selected text: enter edit mode\n if (e.detail >= 2 && targetGroup === selectedElement) {\n enterEditMode(targetGroup);\n e.stopPropagation();\n return;\n }\n\n if (targetGroup === selectedElement) {\n startDrag(e);\n } else {\n selectElement(targetGroup);\n startDrag(e);\n }\n } else {\n deselectElement();\n }\n\n } else if (isTextToolActive && e.button === 0) {\n if (targetGroup) {\n // Double-click: enter edit mode\n if (e.detail >= 2) {\n let textEl = targetGroup.querySelector('text');\n if (textEl) {\n makeTextEditable(textEl, targetGroup);\n e.stopPropagation();\n return;\n }\n }\n // Single-click: select and drag (same as selection tool behavior)\n if (targetGroup === selectedElement) {\n startDrag(e);\n } else {\n selectElement(targetGroup);\n startDrag(e);\n }\n } else {\n deselectElement();\n addText(e);\n }\n }\n};\n\nfunction enterEditMode(groupElement) {\n const textEl = groupElement.querySelector('text');\n if (!textEl) return;\n\n // Switch to text tool with property panel (go through store to clear other flags)\n if (window.__sketchStoreApi) {\n window.__sketchStoreApi.setActiveTool('text');\n } else {\n window.isTextToolActive = true;\n window.isSelectionToolActive = false;\n }\n toolExtraPopup();\n\n // Deselect (removes selection feedback) then open editor\n deselectElement();\n makeTextEditable(textEl, groupElement);\n}\n\nconst handleTextMouseMove = function (e) {\n // Keep lastMousePos in screen coordinates for other functions\n const svgRect = svg.getBoundingClientRect();\n lastMousePos = {\n x: e.clientX - svgRect.left, \n y: e.clientY - svgRect.top\n };\n\n // Handle cursor changes for text tool\n if (isTextToolActive) {\n const targetGroup = e.target?.closest?.('g[data-type=\"text-group\"]');\n if (targetGroup) {\n svg.style.cursor = 'pointer';\n } else {\n svg.style.cursor = 'crosshair';\n }\n } else if (isSelectionToolActive) {\n const targetGroup = e.target?.closest?.('g[data-type=\"text-group\"]');\n if (targetGroup) {\n svg.style.cursor = 'default';\n }\n }\n\n // Check for frame containment while creating text\n if (isTextToolActive && !isDragging && !isResizing && !isRotating) {\n // Get current mouse position for frame highlighting preview\n const { x, y } = getSVGCoordinates(e);\n \n // Create temporary text bounds for frame checking\n const tempTextBounds = {\n x: x - 50,\n y: y - 20,\n width: 100,\n height: 40\n };\n \n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.forEach(frame => {\n if (frame.shapeName === 'frame') {\n if (frame.isShapeInFrame(tempTextBounds)) {\n frame.highlightFrame();\n hoveredFrameText = frame;\n } else if (hoveredFrameText === frame) {\n frame.removeHighlight();\n hoveredFrameText = null;\n }\n }\n });\n }\n }\n};\n\nconst handleTextMouseUp = function (e) {\n // Clear frame highlighting when done with text tool operations\n if (hoveredFrameText) {\n hoveredFrameText.removeHighlight();\n hoveredFrameText = null;\n }\n};\n\n// updateAttachedArrows is imported from drawArrow.js\n\n\ntextColorOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n textColorOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n\n const newColor = span.getAttribute(\"data-id\");\n const oldColor = textColor;\n textColor = newColor;\n\n if (selectedElement) {\n const textElement = selectedElement.querySelector('text');\n if (textElement) {\n const currentColor = textElement.getAttribute('fill');\n\n if (currentColor !== newColor) {\n pushOptionsChangeAction(\n {\n type: 'text',\n element: selectedElement,\n shapeName: 'text'\n },\n {\n color: currentColor,\n font: textElement.getAttribute('font-family'),\n size: textElement.getAttribute('font-size'),\n align: textElement.getAttribute('text-anchor')\n },\n {\n color: newColor,\n font: textElement.getAttribute('font-family'),\n size: textElement.getAttribute('font-size'),\n align: textElement.getAttribute('text-anchor')\n }\n );\n }\n\n textElement.setAttribute('fill', newColor);\n }\n }\n });\n});\n\ntextFontOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n textFontOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n\n const newFont = span.getAttribute(\"data-id\");\n const oldFont = textFont;\n textFont = newFont;\n\n if (selectedElement) {\n const textElement = selectedElement.querySelector('text');\n if (textElement) {\n const currentFont = textElement.getAttribute('font-family');\n\n if (currentFont !== newFont) {\n pushOptionsChangeAction(\n {\n type: 'text',\n element: selectedElement,\n shapeName: 'text'\n },\n {\n color: textElement.getAttribute('fill'),\n font: currentFont,\n size: textElement.getAttribute('font-size'),\n align: textElement.getAttribute('text-anchor')\n },\n {\n color: textElement.getAttribute('fill'),\n font: newFont,\n size: textElement.getAttribute('font-size'),\n align: textElement.getAttribute('text-anchor')\n }\n );\n }\n\n textElement.setAttribute('font-family', newFont);\n setTimeout(updateSelectionFeedback, 0);\n }\n }\n });\n});\n\ntextSizeOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n textSizeOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n\n const newSize = span.getAttribute(\"data-id\") + \"px\";\n const oldSize = textSize;\n textSize = newSize;\n\n if (selectedElement) {\n const textElement = selectedElement.querySelector('text');\n if (textElement) {\n const currentSize = textElement.getAttribute('font-size');\n\n if (currentSize !== newSize) {\n pushOptionsChangeAction(\n {\n type: 'text',\n element: selectedElement,\n shapeName: 'text'\n },\n {\n color: textElement.getAttribute('fill'),\n font: textElement.getAttribute('font-family'),\n size: currentSize,\n align: textElement.getAttribute('text-anchor')\n },\n {\n color: textElement.getAttribute('fill'),\n font: textElement.getAttribute('font-family'),\n size: newSize,\n align: textElement.getAttribute('text-anchor')\n }\n );\n }\n\n textElement.setAttribute('font-size', newSize);\n setTimeout(updateSelectionFeedback, 0);\n }\n }\n });\n});\n\ntextAlignOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n textAlignOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n\n const newAlign = span.getAttribute(\"data-id\");\n const oldAlign = textAlign;\n textAlign = newAlign;\n\n if (selectedElement) {\n const textElement = selectedElement.querySelector('text');\n if (textElement) {\n const currentAnchor = textElement.getAttribute('text-anchor');\n let newAnchor = 'start';\n if (newAlign === 'center') newAnchor = 'middle';\n else if (newAlign === 'right') newAnchor = 'end';\n\n if (currentAnchor !== newAnchor) {\n pushOptionsChangeAction(\n {\n type: 'text',\n element: selectedElement,\n shapeName: 'text'\n },\n {\n color: textElement.getAttribute('fill'),\n font: textElement.getAttribute('font-family'),\n size: textElement.getAttribute('font-size'),\n align: currentAnchor\n },\n {\n color: textElement.getAttribute('fill'),\n font: textElement.getAttribute('font-family'),\n size: textElement.getAttribute('font-size'),\n align: newAnchor\n }\n );\n }\n\n textElement.setAttribute('text-anchor', newAnchor);\n setTimeout(updateSelectionFeedback, 0);\n }\n }\n });\n});\n\n\n// --- Code/Text Toggle Handler ---\nconst textCodeOptions = document.querySelectorAll(\".textCodeSpan\");\nconst languageSelector = document.getElementById(\"textLanguageSelector\");\nconst codeLanguageSelect = document.getElementById(\"codeLanguageSelect\");\n\ntextCodeOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n textCodeOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n\n const isCodeMode = span.getAttribute(\"data-id\") === \"true\";\n isTextInCodeMode = isCodeMode;\n\n // Show/hide language selector\n if (languageSelector) {\n languageSelector.classList.toggle(\"hidden\", !isCodeMode);\n }\n\n // Update tool flags\n if (isTextToolActive) {\n isCodeToolActive = isCodeMode;\n }\n\n // If a shape is selected, convert it\n if (isCodeMode && selectedElement) {\n // Convert text \u2192 code\n convertTextToCode(selectedElement);\n } else if (!isCodeMode && getSelectedCodeBlock()) {\n // Convert code \u2192 text\n convertCodeToText(getSelectedCodeBlock());\n }\n });\n});\n\n// Language selector handler\nif (codeLanguageSelect) {\n codeLanguageSelect.addEventListener(\"change\", (event) => {\n const lang = event.target.value;\n setCodeLanguage(lang);\n\n // If a code block is selected, re-highlight it with the new language\n const selectedCode = getSelectedCodeBlock();\n if (selectedCode) {\n const codeElement = selectedCode.querySelector('text');\n if (codeElement) {\n codeElement.setAttribute(\"data-language\", lang);\n // Re-render with new language highlighting\n const content = extractTextFromCodeElement(codeElement);\n while (codeElement.firstChild) {\n codeElement.removeChild(codeElement.firstChild);\n }\n const highlighted = applySyntaxHighlightingToSVG(content, lang);\n createHighlightedSVGText(highlighted, codeElement);\n updateCodeBackground(selectedCode, codeElement);\n }\n }\n });\n}\n\nfunction convertTextToCode(textGroupElement) {\n const textElement = textGroupElement.querySelector('text');\n if (!textElement) return;\n\n // Get text content\n let textContent = \"\";\n const tspans = textElement.querySelectorAll('tspan');\n if (tspans.length > 0) {\n tspans.forEach((tspan, index) => {\n textContent += tspan.textContent;\n if (index < tspans.length - 1) textContent += \"\\n\";\n });\n } else {\n textContent = textElement.textContent || \"\";\n }\n\n // Get position from transform\n const currentTransform = textGroupElement.transform.baseVal.consolidate();\n const tx = currentTransform ? currentTransform.matrix.e : 0;\n const ty = currentTransform ? currentTransform.matrix.f : 0;\n const fontSize = textElement.getAttribute('font-size') || \"25px\";\n const color = textElement.getAttribute('fill') || \"#fff\";\n\n // Find and remove old TextShape from shapes array\n let oldTextShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n oldTextShape = shapes.find(s => s.shapeName === 'text' && s.group === textGroupElement);\n if (oldTextShape) {\n const idx = shapes.indexOf(oldTextShape);\n if (idx !== -1) shapes.splice(idx, 1);\n }\n }\n\n // Deselect current text\n deselectElement();\n\n // Remove old text group from SVG\n if (textGroupElement.parentNode) {\n textGroupElement.parentNode.removeChild(textGroupElement);\n }\n\n // Create new code block\n const gElement = document.createElementNS(\"http://www.w3.org/2000/svg\", \"g\");\n gElement.setAttribute(\"data-type\", \"code-group\");\n gElement.setAttribute(\"transform\", `translate(${tx}, ${ty})`);\n\n const backgroundRect = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n backgroundRect.setAttribute(\"class\", \"code-background\");\n backgroundRect.setAttribute(\"x\", -10);\n backgroundRect.setAttribute(\"y\", -10);\n backgroundRect.setAttribute(\"width\", 300);\n backgroundRect.setAttribute(\"height\", 60);\n backgroundRect.setAttribute(\"fill\", \"#161b22\");\n backgroundRect.setAttribute(\"stroke\", \"#30363d\");\n backgroundRect.setAttribute(\"stroke-width\", \"1\");\n backgroundRect.setAttribute(\"rx\", \"6\");\n backgroundRect.setAttribute(\"ry\", \"6\");\n gElement.appendChild(backgroundRect);\n\n const codeElement = document.createElementNS(\"http://www.w3.org/2000/svg\", \"text\");\n codeElement.setAttribute(\"x\", 0);\n codeElement.setAttribute(\"y\", 0);\n codeElement.setAttribute(\"fill\", color);\n codeElement.setAttribute(\"font-size\", fontSize);\n codeElement.setAttribute(\"font-family\", \"lixCode\");\n codeElement.setAttribute(\"text-anchor\", \"start\");\n codeElement.setAttribute(\"cursor\", \"default\");\n codeElement.setAttribute(\"white-space\", \"pre\");\n codeElement.setAttribute(\"dominant-baseline\", \"hanging\");\n codeElement.setAttribute(\"data-language\", getCodeLanguage());\n codeElement.setAttribute(\"data-type\", \"code\");\n\n const shapeID = `code-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n gElement.setAttribute(\"id\", shapeID);\n gElement.setAttribute(\"data-x\", tx);\n gElement.setAttribute(\"data-y\", ty);\n codeElement.setAttribute(\"id\", `${shapeID}-code`);\n gElement.appendChild(codeElement);\n svg.appendChild(gElement);\n\n // Apply syntax highlighting and add content\n if (textContent.trim()) {\n const lang = getCodeLanguage();\n const highlighted = applySyntaxHighlightingToSVG(textContent, lang);\n createHighlightedSVGText(highlighted, codeElement);\n updateCodeBackground(gElement, codeElement);\n }\n\n // Create CodeShape wrapper\n const codeShape = wrapCodeElement(gElement);\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.push(codeShape);\n }\n\n // Push undo action for mode conversion\n pushModeConvertAction(oldTextShape, textGroupElement, 'text', codeShape, gElement, 'code');\n\n // Select the new code block\n selectCodeBlock(gElement);\n}\n\nfunction convertCodeToText(codeGroupElement) {\n const codeElement = codeGroupElement.querySelector('text');\n if (!codeElement) return;\n\n // Get text content\n const textContent = extractTextFromCodeElement(codeElement);\n\n // Get position from transform\n const currentTransform = codeGroupElement.transform.baseVal.consolidate();\n const tx = currentTransform ? currentTransform.matrix.e : 0;\n const ty = currentTransform ? currentTransform.matrix.f : 0;\n const fontSize = codeElement.getAttribute('font-size') || \"30px\";\n const color = codeElement.getAttribute('fill') || \"#fff\";\n\n // Find and remove old CodeShape from shapes array\n let oldCodeShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n oldCodeShape = shapes.find(s => s.shapeName === 'code' && s.group === codeGroupElement);\n if (oldCodeShape) {\n const idx = shapes.indexOf(oldCodeShape);\n if (idx !== -1) shapes.splice(idx, 1);\n }\n }\n\n // Deselect current code block\n deselectCodeBlock();\n\n // Remove old code group from SVG\n if (codeGroupElement.parentNode) {\n codeGroupElement.parentNode.removeChild(codeGroupElement);\n }\n\n // Create new text shape\n const gElement = document.createElementNS(\"http://www.w3.org/2000/svg\", \"g\");\n gElement.setAttribute(\"data-type\", \"text-group\");\n gElement.setAttribute(\"transform\", `translate(${tx}, ${ty})`);\n\n const textElement = document.createElementNS(\"http://www.w3.org/2000/svg\", \"text\");\n textElement.setAttribute(\"x\", 0);\n textElement.setAttribute(\"y\", 0);\n textElement.setAttribute(\"fill\", color);\n textElement.setAttribute(\"font-size\", fontSize);\n textElement.setAttribute(\"font-family\", textFont);\n textElement.setAttribute(\"text-anchor\", \"start\");\n textElement.setAttribute(\"cursor\", \"default\");\n textElement.setAttribute(\"white-space\", \"pre\");\n textElement.setAttribute(\"dominant-baseline\", \"hanging\");\n textElement.setAttribute(\"data-type\", \"text\");\n\n const shapeID = `text-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n gElement.setAttribute(\"id\", shapeID);\n gElement.setAttribute(\"data-x\", tx);\n gElement.setAttribute(\"data-y\", ty);\n textElement.setAttribute(\"id\", `${shapeID}-text`);\n gElement.appendChild(textElement);\n svg.appendChild(gElement);\n\n // Add text content as tspans\n if (textContent.trim()) {\n const lines = textContent.split(\"\\n\");\n const x = textElement.getAttribute(\"x\") || 0;\n lines.forEach((line, index) => {\n const tspan = document.createElementNS(\"http://www.w3.org/2000/svg\", \"tspan\");\n tspan.setAttribute(\"x\", x);\n tspan.setAttribute(\"dy\", index === 0 ? \"0\" : \"1.2em\");\n tspan.textContent = line || \" \";\n textElement.appendChild(tspan);\n });\n }\n\n // Create TextShape wrapper\n const textShape = wrapTextElement(gElement);\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.push(textShape);\n }\n\n // Push undo action for mode conversion\n pushModeConvertAction(oldCodeShape, codeGroupElement, 'code', textShape, gElement, 'text');\n\n // Select the new text shape\n selectElement(gElement);\n}\n\nfunction pushModeConvertAction(oldShape, oldElement, oldType, newShape, newElement, newType) {\n pushCreateAction({\n type: 'modeConvert',\n oldShape: oldShape,\n oldElement: oldElement,\n oldType: oldType,\n newShape: newShape,\n newElement: newElement,\n newType: newType,\n element: newShape,\n shapeName: newType\n });\n}\n\n// Update toggle state when a shape is selected\nfunction updateCodeToggleForShape(shapeName) {\n const isCode = shapeName === 'code';\n textCodeOptions.forEach(el => el.classList.remove(\"selected\"));\n textCodeOptions.forEach(el => {\n if ((el.getAttribute(\"data-id\") === \"true\") === isCode) {\n el.classList.add(\"selected\");\n }\n });\n if (languageSelector) {\n languageSelector.classList.toggle(\"hidden\", !isCode);\n }\n // Update the language dropdown to match the selected code block\n if (isCode && codeLanguageSelect) {\n const selectedCode = getSelectedCodeBlock();\n if (selectedCode) {\n const codeEl = selectedCode.querySelector('text');\n const lang = codeEl?.getAttribute(\"data-language\") || \"auto\";\n codeLanguageSelect.value = lang;\n }\n }\n}\n\n// React sidebar bridge \u2014 update currently selected text/code shape\nwindow.updateSelectedTextStyle = function(changes) {\n const el = selectedElement || (window.currentShape && window.currentShape.shapeName === 'text' ? window.currentShape.group : null);\n if (!el) return;\n const textElement = el.querySelector('text');\n if (!textElement) return;\n\n if (changes.color) {\n textElement.setAttribute('fill', changes.color);\n textColor = changes.color;\n }\n if (changes.font) {\n textElement.setAttribute('font-family', changes.font);\n textFont = changes.font;\n }\n if (changes.fontSize) {\n textElement.setAttribute('font-size', changes.fontSize);\n textSize = changes.fontSize;\n }\n};\n\n// Expose select/deselect for external callers (Selection.js, TextShape.selectShape)\nwindow.__deselectTextElement = deselectElement;\nwindow.__selectTextElement = selectElement;\n\n// React sidebar bridge \u2014 text \u2194 code conversion\nwindow.__convertTextToCode = function() {\n if (selectedElement && selectedElement.getAttribute('data-type') === 'text-group') {\n convertTextToCode(selectedElement);\n }\n};\nwindow.__convertCodeToText = function() {\n // Try codeTool's selectedCodeBlock first, then check textTool's selectedElement\n let codeBlock = getSelectedCodeBlock();\n if (!codeBlock && selectedElement && selectedElement.getAttribute('data-type') === 'code-group') {\n codeBlock = selectedElement;\n }\n if (codeBlock) {\n convertCodeToText(codeBlock);\n }\n};\nwindow.__setCodeLanguage = function(lang) {\n setCodeLanguage(lang);\n // Re-highlight selected code block with new language\n const selectedCode = getSelectedCodeBlock();\n if (selectedCode) {\n const codeElement = selectedCode.querySelector('text');\n if (codeElement) {\n codeElement.setAttribute('data-language', lang);\n const textContent = extractTextFromCodeElement(codeElement);\n // Clear and re-highlight\n while (codeElement.firstChild) codeElement.removeChild(codeElement.firstChild);\n const highlighted = applySyntaxHighlightingToSVG(textContent, lang);\n createHighlightedSVGText(highlighted, codeElement);\n updateCodeBackground(selectedCode, codeElement);\n }\n }\n};\n\nexport { handleTextMouseDown, handleTextMouseMove, handleTextMouseUp, updateCodeToggleForShape, deselectElement as deselectTextElement, enterEditMode };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/react/index.js
CHANGED
|
@@ -528,7 +528,7 @@ function useSketchEngine(svgRef, ready = true) {
|
|
|
528
528
|
setZoom: (zoom) => useSketchStore_default.setState({ zoom }),
|
|
529
529
|
getState: () => useSketchStore_default.getState()
|
|
530
530
|
};
|
|
531
|
-
const { SketchEngine } = await import("./SketchEngine-
|
|
531
|
+
const { SketchEngine } = await import("./SketchEngine-OB6ZW3B6.js");
|
|
532
532
|
if (cancelled) return;
|
|
533
533
|
const engine = new SketchEngine(svgRef.current);
|
|
534
534
|
await engine.init();
|
|
@@ -4788,7 +4788,7 @@ var _saveScene = null;
|
|
|
4788
4788
|
var _loadScene = null;
|
|
4789
4789
|
async function ensureSceneSerializer() {
|
|
4790
4790
|
if (_saveScene && _loadScene) return;
|
|
4791
|
-
const m = await import("./SceneSerializer-
|
|
4791
|
+
const m = await import("./SceneSerializer-RDISX4X7.js");
|
|
4792
4792
|
_saveScene = m.saveScene;
|
|
4793
4793
|
_loadScene = m.loadScene;
|
|
4794
4794
|
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
handleTextMouseMove,
|
|
7
7
|
handleTextMouseUp,
|
|
8
8
|
updateCodeToggleForShape
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-ETAAQUUV.js";
|
|
10
10
|
import "./chunk-HFQZYCHJ.js";
|
|
11
11
|
import "./chunk-PAKA6HUX.js";
|
|
12
12
|
import "./chunk-YF3TK7SC.js";
|
|
@@ -19,4 +19,4 @@ export {
|
|
|
19
19
|
handleTextMouseUp,
|
|
20
20
|
updateCodeToggleForShape
|
|
21
21
|
};
|
|
22
|
-
//# sourceMappingURL=textTool-
|
|
22
|
+
//# sourceMappingURL=textTool-JMTX7OVT.js.map
|
package/package.json
CHANGED
package/src/core/CopyPaste.js
CHANGED
|
@@ -150,6 +150,8 @@ function serializeShape(shape) {
|
|
|
150
150
|
href: el.getAttribute('href') || el.getAttributeNS('http://www.w3.org/1999/xlink', 'href') || '',
|
|
151
151
|
storageProvider: el.getAttribute('data-storage-provider') || null,
|
|
152
152
|
storageCloudName: el.getAttribute('data-storage-cloud-name') || null,
|
|
153
|
+
aiGenerated: el.getAttribute('data-ai-generated') === 'true',
|
|
154
|
+
aiModel: el.getAttribute('data-ai-model') || null,
|
|
153
155
|
frameType: shape._frameType || null,
|
|
154
156
|
graphData: shape._frameType === 'graph' && shape._graphData
|
|
155
157
|
? cloneOptions(shape._graphData)
|
|
@@ -391,6 +393,8 @@ function createShapeFromData(data, offsetX, offsetY) {
|
|
|
391
393
|
imgEl.setAttribute('style', 'cursor: pointer;');
|
|
392
394
|
if (data.storageProvider) imgEl.setAttribute('data-storage-provider', data.storageProvider);
|
|
393
395
|
if (data.storageCloudName) imgEl.setAttribute('data-storage-cloud-name', data.storageCloudName);
|
|
396
|
+
if (data.aiGenerated) imgEl.setAttribute('data-ai-generated', 'true');
|
|
397
|
+
if (data.aiModel) imgEl.setAttribute('data-ai-model', data.aiModel);
|
|
394
398
|
|
|
395
399
|
// ImageShape constructor moves element into a group and appends to svg
|
|
396
400
|
svgEl.appendChild(imgEl);
|
|
@@ -184,6 +184,8 @@ function serializeShape(shape) {
|
|
|
184
184
|
cloudinaryId: el.getAttribute('data-cloudinary-id') || null,
|
|
185
185
|
storageProvider: el.getAttribute('data-storage-provider') || 'platform_cloudinary',
|
|
186
186
|
storageCloudName: el.getAttribute('data-storage-cloud-name') || null,
|
|
187
|
+
aiGenerated: el.getAttribute('data-ai-generated') === 'true',
|
|
188
|
+
aiModel: el.getAttribute('data-ai-model') || null,
|
|
187
189
|
frameType: shape._frameType || null,
|
|
188
190
|
graphData: shape._frameType === 'graph' && shape._graphData
|
|
189
191
|
? cloneOptions(shape._graphData)
|
|
@@ -316,6 +318,8 @@ function deserializeShape(data) {
|
|
|
316
318
|
if (data.cloudinaryId) imgEl.setAttribute('data-cloudinary-id', data.cloudinaryId);
|
|
317
319
|
if (data.storageProvider) imgEl.setAttribute('data-storage-provider', data.storageProvider);
|
|
318
320
|
if (data.storageCloudName) imgEl.setAttribute('data-storage-cloud-name', data.storageCloudName);
|
|
321
|
+
if (data.aiGenerated) imgEl.setAttribute('data-ai-generated', 'true');
|
|
322
|
+
if (data.aiModel) imgEl.setAttribute('data-ai-model', data.aiModel);
|
|
319
323
|
svgEl.appendChild(imgEl);
|
|
320
324
|
const shape = new ImageShape(imgEl);
|
|
321
325
|
if (data.rotation) shape.rotation = data.rotation;
|