@elixpo/lixsketch 5.5.19 → 5.5.20

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.
Files changed (74) hide show
  1. package/dist/react/Circle-6POZCUZD.js +9 -0
  2. package/dist/react/{CopyPaste-JMIXWUUO.js → CopyPaste-KJZ34MIP.js} +6 -5
  3. package/dist/react/{CopyPaste-JMIXWUUO.js.map → CopyPaste-KJZ34MIP.js.map} +1 -1
  4. package/dist/react/{EventDispatcher-H5EA4KZN.js → EventDispatcher-XDRQS7BD.js} +7 -6
  5. package/dist/react/{EventDispatcher-H5EA4KZN.js.map → EventDispatcher-XDRQS7BD.js.map} +1 -1
  6. package/dist/react/{Frame-VADA625S.js → Frame-QLBAVLGW.js} +3 -2
  7. package/dist/react/FreehandStroke-U6GYZOM4.js +9 -0
  8. package/dist/react/Rectangle-S7XUKWYD.js +9 -0
  9. package/dist/react/{SceneSerializer-ARTKPZVR.js → SceneSerializer-VY3HY4PF.js} +6 -5
  10. package/dist/react/{SceneSerializer-ARTKPZVR.js.map → SceneSerializer-VY3HY4PF.js.map} +1 -1
  11. package/dist/react/{Selection-YJNZRBON.js → Selection-U2AR6NQS.js} +3 -2
  12. package/dist/react/{SketchEngine-ZGYBIZG7.js → SketchEngine-ZFYUTKET.js} +14 -14
  13. package/dist/react/{ZoomPan-NYPDJBD5.js → ZoomPan-FAWA5OPS.js} +5 -1
  14. package/dist/react/ZoomPan-FAWA5OPS.js.map +7 -0
  15. package/dist/react/{chunk-73VA5ALZ.js → chunk-2I3GH65Z.js} +5 -1
  16. package/dist/react/chunk-2I3GH65Z.js.map +7 -0
  17. package/dist/react/{chunk-3VSGFP6U.js → chunk-73VLPCBC.js} +6 -2
  18. package/dist/react/chunk-73VLPCBC.js.map +7 -0
  19. package/dist/react/{chunk-CF7AK4ES.js → chunk-75G7XSZU.js} +10 -1
  20. package/dist/react/chunk-75G7XSZU.js.map +7 -0
  21. package/dist/react/{chunk-FV3EPR4L.js → chunk-7VBI7S7T.js} +10 -1
  22. package/dist/react/chunk-7VBI7S7T.js.map +7 -0
  23. package/dist/react/{chunk-XCJOF6BM.js → chunk-FETTJLCV.js} +5 -1
  24. package/dist/react/chunk-FETTJLCV.js.map +7 -0
  25. package/dist/react/chunk-PAKA6HUX.js +59 -0
  26. package/dist/react/chunk-PAKA6HUX.js.map +7 -0
  27. package/dist/react/{chunk-HKYUJUD7.js → chunk-PXFPPO3R.js} +5 -1
  28. package/dist/react/chunk-PXFPPO3R.js.map +7 -0
  29. package/dist/react/{chunk-JJTII2UQ.js → chunk-R5QXEVZ5.js} +5 -1
  30. package/dist/react/chunk-R5QXEVZ5.js.map +7 -0
  31. package/dist/react/{chunk-QYNTPZON.js → chunk-SBSM3GQD.js} +7 -3
  32. package/dist/react/chunk-SBSM3GQD.js.map +7 -0
  33. package/dist/react/{chunk-N7NZLF6P.js → chunk-TKXKJNTX.js} +5 -1
  34. package/dist/react/chunk-TKXKJNTX.js.map +7 -0
  35. package/dist/react/{codeTool-O2Z7ZXGP.js → codeTool-VBDB2ES6.js} +3 -2
  36. package/dist/react/{iconTool-AUHRLOO2.js → iconTool-5WNDHI5T.js} +3 -2
  37. package/dist/react/{imageTool-DRKDCPUV.js → imageTool-ECPMT3BL.js} +3 -2
  38. package/dist/react/index.js +2 -2
  39. package/dist/react/{textTool-UORBAAJE.js → textTool-5IJKTWVQ.js} +4 -3
  40. package/package.json +1 -1
  41. package/src/core/ScreenSpaceControls.js +60 -0
  42. package/src/core/Selection.js +7 -0
  43. package/src/core/ZoomPan.js +3 -0
  44. package/src/shapes/Circle.js +2 -0
  45. package/src/shapes/Frame.js +7 -0
  46. package/src/shapes/FreehandStroke.js +2 -0
  47. package/src/shapes/Rectangle.js +2 -0
  48. package/src/tools/codeTool.js +3 -2
  49. package/src/tools/iconTool.js +3 -1
  50. package/src/tools/imageTool.js +3 -1
  51. package/src/tools/textTool.js +3 -1
  52. package/dist/react/Circle-QQMKCKFR.js +0 -8
  53. package/dist/react/FreehandStroke-BOWDNAVC.js +0 -8
  54. package/dist/react/Rectangle-MZ6ZB6KM.js +0 -8
  55. package/dist/react/ZoomPan-NYPDJBD5.js.map +0 -7
  56. package/dist/react/chunk-3VSGFP6U.js.map +0 -7
  57. package/dist/react/chunk-73VA5ALZ.js.map +0 -7
  58. package/dist/react/chunk-CF7AK4ES.js.map +0 -7
  59. package/dist/react/chunk-FV3EPR4L.js.map +0 -7
  60. package/dist/react/chunk-HKYUJUD7.js.map +0 -7
  61. package/dist/react/chunk-JJTII2UQ.js.map +0 -7
  62. package/dist/react/chunk-N7NZLF6P.js.map +0 -7
  63. package/dist/react/chunk-QYNTPZON.js.map +0 -7
  64. package/dist/react/chunk-XCJOF6BM.js.map +0 -7
  65. /package/dist/react/{Circle-QQMKCKFR.js.map → Circle-6POZCUZD.js.map} +0 -0
  66. /package/dist/react/{Frame-VADA625S.js.map → Frame-QLBAVLGW.js.map} +0 -0
  67. /package/dist/react/{FreehandStroke-BOWDNAVC.js.map → FreehandStroke-U6GYZOM4.js.map} +0 -0
  68. /package/dist/react/{Rectangle-MZ6ZB6KM.js.map → Rectangle-S7XUKWYD.js.map} +0 -0
  69. /package/dist/react/{Selection-YJNZRBON.js.map → Selection-U2AR6NQS.js.map} +0 -0
  70. /package/dist/react/{SketchEngine-ZGYBIZG7.js.map → SketchEngine-ZFYUTKET.js.map} +0 -0
  71. /package/dist/react/{codeTool-O2Z7ZXGP.js.map → codeTool-VBDB2ES6.js.map} +0 -0
  72. /package/dist/react/{iconTool-AUHRLOO2.js.map → iconTool-5WNDHI5T.js.map} +0 -0
  73. /package/dist/react/{imageTool-DRKDCPUV.js.map → imageTool-ECPMT3BL.js.map} +0 -0
  74. /package/dist/react/{textTool-UORBAAJE.js.map → textTool-5IJKTWVQ.js.map} +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/tools/codeTool.js"],
4
+ "sourcesContent": ["/* eslint-disable */\n// Code tool event handlers - extracted from writeCode.js\nimport {\n pushCreateAction,\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\"; }\n\nlet codeTextSize = \"25px\";\nlet codeTextFont = \"lixCode\";\nlet codeTextColor = null;\nlet codeTextAlign = \"left\";\nlet codeLanguage = \"auto\";\n\nlet codeTextColorOptions = document.querySelectorAll(\".textColorSpan\");\nlet codeTextFontOptions = document.querySelectorAll(\".textFontSpan\");\nlet codeTextSizeOptions = document.querySelectorAll(\".textSizeSpan\");\nlet codeTextAlignOptions = document.querySelectorAll(\".textAlignSpan\"); \n\nlet selectedCodeBlock = null;\nlet codeSelectionBox = null;\nlet codeResizeHandles = {};\nlet codeDragOffsetX, codeDragOffsetY;\nlet isCodeDragging = false;\nlet isCodeResizing = false;\nlet currentCodeResizeHandle = null;\nlet startCodeBBox = null;\nlet startCodeFontSize = null;\nlet startCodePoint = null;\nlet isCodeRotating = false;\nlet codeRotationStartAngle = 0;\nlet codeRotationStartTransform = null;\nlet initialCodeHandlePosRelGroup = null;\nlet initialCodeGroupTx = 0;\nlet initialCodeGroupTy = 0;\n\n\n// Frame attachment variables for code blocks\nlet draggedCodeInitialFrame = null;\nlet hoveredCodeFrame = null;\n\n\nsetTextReferences(selectedCodeBlock, updateCodeSelectionFeedback, svg);\n\n\n// Convert group element to our CodeShape class\nfunction wrapCodeElement(groupElement) {\n const codeShape = new CodeShape(groupElement);\n // Double-click to edit code block (works with any tool)\n groupElement.addEventListener('dblclick', (e) => {\n e.stopPropagation();\n const codeElement = groupElement.querySelector('text');\n if (codeElement) {\n makeCodeEditable(codeElement, groupElement, e);\n }\n });\n return codeShape;\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\n\nfunction addCodeBlock(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\", \"code-group\");\n gElement.setAttribute(\"transform\", `translate(${x}, ${y})`);\n\n // Create background rectangle for code block\n let backgroundRect = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n backgroundRect.setAttribute(\"class\", \"code-background\");\n backgroundRect.setAttribute(\"x\", -10); // Padding\n backgroundRect.setAttribute(\"y\", -10); // Padding\n backgroundRect.setAttribute(\"width\", 300); // Initial width\n backgroundRect.setAttribute(\"height\", 60); // Initial height\n backgroundRect.setAttribute(\"fill\", \"#161b22\"); // GitHub dark background\n backgroundRect.setAttribute(\"stroke\", \"#30363d\");\n backgroundRect.setAttribute(\"stroke-width\", \"1\");\n backgroundRect.setAttribute(\"rx\", \"6\"); // Rounded corners\n backgroundRect.setAttribute(\"ry\", \"6\");\n gElement.appendChild(backgroundRect);\n\n // Create SVG text element\n let codeElement = document.createElementNS(\"http://www.w3.org/2000/svg\", \"text\");\n let textAlignElement = \"start\";\n if (codeTextAlign === \"center\") textAlignElement = \"middle\";\n else if (codeTextAlign === \"right\") textAlignElement = \"end\";\n\n codeElement.setAttribute(\"x\", 0);\n codeElement.setAttribute(\"y\", 0);\n codeElement.setAttribute(\"fill\", codeTextColor ?? getThemeStroke());\n codeElement.setAttribute(\"font-size\", codeTextSize);\n codeElement.setAttribute(\"font-family\", codeTextFont);\n codeElement.setAttribute(\"text-anchor\", textAlignElement);\n codeElement.setAttribute(\"cursor\", \"text\");\n codeElement.setAttribute(\"white-space\", \"pre\");\n codeElement.setAttribute(\"dominant-baseline\", \"hanging\");\n codeElement.textContent = \"\";\n\n gElement.setAttribute(\"data-x\", x);\n gElement.setAttribute(\"data-y\", y);\n codeElement.setAttribute(\"data-initial-size\", codeTextSize);\n codeElement.setAttribute(\"data-initial-font\", codeTextFont);\n codeElement.setAttribute(\"data-initial-color\", codeTextColor ?? getThemeStroke());\n codeElement.setAttribute(\"data-initial-align\", codeTextAlign);\n codeElement.setAttribute(\"data-language\", codeLanguage);\n codeElement.setAttribute(\"data-type\", \"code\");\n gElement.appendChild(codeElement);\n svg.appendChild(gElement);\n \n // Attach ID to both group and code element\n const shapeID = `code-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n gElement.setAttribute('id', shapeID);\n codeElement.setAttribute('id', `${shapeID}-code`);\n \n // Create CodeShape wrapper for frame functionality\n const codeShape = wrapCodeElement(gElement);\n \n // Add to shapes array for arrow attachment and frame functionality\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.push(codeShape);\n }\n \n pushCreateAction({\n type: 'code',\n element: codeShape,\n shapeName: 'code'\n });\n\n makeCodeEditable(codeElement, gElement);\n}\n\n// Function to update highlight.js on content change\nfunction updateSyntaxHighlighting(editor) {\n if (window.hljs) {\n window.hljs.highlightElement(editor);\n }\n}\n\nfunction adjustCodeEditorSize(editor) {\n const foreignObject = editor.closest('foreignObject');\n const codeContainer = editor.closest('.svg-code-container');\n if (!foreignObject || !codeContainer) return;\n\n const svgRect = svg.getBoundingClientRect();\n\n // Allow textarea to expand freely\n editor.style.overflow = 'visible';\n editor.style.height = 'auto';\n editor.style.width = 'auto';\n editor.style.whiteSpace = 'pre'; // No wrapping\n\n // Calculate content size\n let minContentWidth = editor.scrollWidth + (parseFloat(codeContainer.style.paddingLeft) || 0) + (parseFloat(codeContainer.style.paddingRight) || 0);\n let minContentHeight = editor.scrollHeight + (parseFloat(codeContainer.style.paddingTop) || 0) + (parseFloat(codeContainer.style.paddingBottom) || 0);\n\n // Clamp to SVG bounds\n const editorRect = editor.getBoundingClientRect();\n const maxWidth = svgRect.width - (editorRect.left - svgRect.left);\n const maxHeight = svgRect.height - (editorRect.top - svgRect.top);\n\n let newWidth = Math.min(Math.max(minContentWidth, 50), maxWidth);\n let newHeight = Math.min(Math.max(minContentHeight, 30), maxHeight);\n\n foreignObject.setAttribute('width', newWidth);\n foreignObject.setAttribute('height', newHeight);\n\n editor.style.width = `${newWidth - (parseFloat(codeContainer.style.paddingLeft) || 0) - (parseFloat(codeContainer.style.paddingRight) || 0)}px`;\n editor.style.height = `${newHeight - (parseFloat(codeContainer.style.paddingTop) || 0) - (parseFloat(codeContainer.style.paddingBottom) || 0)}px`;\n\n // Overflow only if content exceeds container\n if (editor.scrollHeight > editor.clientHeight || editor.scrollWidth > editor.clientWidth) {\n editor.style.overflow = 'auto';\n } else {\n editor.style.overflow = 'hidden';\n }\n\n if (selectedCodeBlock && selectedCodeBlock.contains(foreignObject)) {\n updateCodeSelectionFeedback();\n }\n}\n\n\nfunction makeCodeEditable(codeElement, groupElement, clickEvent = null) {\n\n if (document.querySelector(\".svg-code-editor\")) {\n return;\n }\n\n if (selectedCodeBlock) {\n deselectCodeBlock();\n }\n\n // Hide the selection feedback for the element being edited\n removeCodeSelectionFeedback();\n\n // Create a container div for the code editor\n let editorContainer = document.createElement(\"div\");\n editorContainer.className = \"svg-code-container\";\n editorContainer.style.position = \"absolute\";\n editorContainer.style.zIndex = \"10000\";\n editorContainer.style.backgroundColor = \"#161b22\";\n editorContainer.style.border = \"1px solid #30363d\";\n editorContainer.style.borderRadius = \"6px\";\n editorContainer.style.padding = \"12px\";\n editorContainer.style.fontFamily = \"monospace\";\n editorContainer.style.overflow = \"hidden\";\n editorContainer.style.minWidth = \"200px\";\n editorContainer.style.minHeight = \"40px\";\n\n // Create the actual code editor\n let input = document.createElement(\"div\");\n input.className = \"svg-code-editor\";\n input.contentEditable = true;\n input.style.outline = \"none\";\n input.style.minHeight = \"30px\";\n input.style.maxHeight = \"400px\";\n input.style.overflowY = \"auto\";\n input.style.whiteSpace = \"pre\";\n input.style.fontFamily = \"lixCode, Consolas, 'Courier New', monospace\";\n input.style.fontSize = codeElement.getAttribute(\"font-size\") || codeTextSize;\n input.style.color = \"#c9d1d9\";\n input.style.lineHeight = \"1.4\";\n input.style.tabSize = \"4\";\n input.style.background = \"transparent\";\n\n // FIXED: Use the improved text extraction\n let codeContent = extractTextFromCodeElement(codeElement);\n\n // Set initial content with plain text (no highlighting initially)\n input.textContent = codeContent;\n\n editorContainer.appendChild(input);\n\n // Position the editor\n const svgRect = svg.getBoundingClientRect();\n let left = svgRect.left, top = svgRect.top;\n if (clickEvent) {\n left += clickEvent.clientX - svgRect.left;\n top += clickEvent.clientY - svgRect.top;\n } else {\n // fallback to code block position if no click event\n let groupTransformMatrix = svg.createSVGMatrix();\n if (groupElement && groupElement.transform && groupElement.transform.baseVal) {\n const transformList = groupElement.transform.baseVal;\n if (transformList.numberOfItems > 0) {\n const consolidatedTransform = transformList.consolidate();\n if (consolidatedTransform) {\n groupTransformMatrix = consolidatedTransform.matrix;\n }\n }\n }\n const codeBBox = codeElement.getBBox();\n let pt = svg.createSVGPoint();\n pt.x = codeBBox.x - 8;\n pt.y = codeBBox.y - 8;\n let screenPt = pt.matrixTransform(groupTransformMatrix.multiply(svg.getScreenCTM()));\n left = screenPt.x + svgRect.left;\n top = screenPt.y + svgRect.top;\n }\n editorContainer.style.left = `${left}px`;\n editorContainer.style.top = `${top}px`;\n\n document.body.appendChild(editorContainer);\n\n // Auto-resize function\n const adjustSize = () => {\n const maxWidth = svgRect.width - (left - svgRect.left);\n const maxHeight = svgRect.height - (top - svgRect.top);\n\n let newWidth = Math.max(300, Math.min(input.scrollWidth + 20, maxWidth));\n let newHeight = Math.max(40, Math.min(input.scrollHeight + 20, maxHeight));\n\n editorContainer.style.width = newWidth + 'px';\n editorContainer.style.height = newHeight + 'px';\n\n if (input.scrollHeight > input.clientHeight) {\n input.style.overflowY = 'auto';\n } else {\n input.style.overflowY = 'hidden';\n }\n };\n\n adjustSize();\n\n setTimeout(() => {\n input.focus();\n // Select all content\n const range = document.createRange();\n range.selectNodeContents(input);\n const selection = window.getSelection();\n selection.removeAllRanges();\n selection.addRange(range);\n\n // Apply initial syntax highlighting after focus\n applySyntaxHighlightingImproved(input);\n }, 50);\n\n // Input handling with duplicate prevention\n let highlightingTimeout = null;\n let isHighlighting = false;\n let lastContent = input.textContent;\n\n input.addEventListener('input', function(e) {\n if (isHighlighting) return;\n\n if (highlightingTimeout) {\n clearTimeout(highlightingTimeout);\n highlightingTimeout = null;\n }\n\n const currentContent = input.textContent || input.innerText || '';\n \n if (currentContent === lastContent) return;\n\n highlightingTimeout = setTimeout(() => {\n const contentAtTimeout = input.textContent || input.innerText || '';\n if (contentAtTimeout !== lastContent && !isHighlighting) {\n applySyntaxHighlightingImproved(input);\n lastContent = contentAtTimeout;\n adjustSize();\n }\n highlightingTimeout = null;\n }, 300);\n });\n\n // Handle special keys\n input.addEventListener(\"keydown\", function (e) {\n if (e.key === \"Tab\") {\n e.preventDefault();\n document.execCommand('insertText', false, '\\t');\n } else if (e.key === \"Enter\" && e.ctrlKey) {\n e.preventDefault();\n renderCodeFromEditor(input, codeElement, true);\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n renderCodeFromEditor(input, codeElement, true);\n }\n });\n\n // Store references\n input.originalCodeElement = codeElement;\n input.codeGroup = groupElement;\n input.isHighlighting = () => isHighlighting;\n input.setHighlighting = (state) => { isHighlighting = state; };\n input.clearHighlightTimeout = () => {\n if (highlightingTimeout) {\n clearTimeout(highlightingTimeout);\n highlightingTimeout = null;\n }\n };\n\n const handleClickOutside = (event) => {\n if (!editorContainer.contains(event.target)) {\n input.clearHighlightTimeout();\n renderCodeFromEditor(input, codeElement, true);\n document.removeEventListener('pointerdown', handleClickOutside, true);\n }\n };\n document.addEventListener('pointerdown', handleClickOutside, true);\n input.handleClickOutside = handleClickOutside;\n\n groupElement.style.display = \"none\";\n}\n\n\nfunction applySyntaxHighlightingImproved(editor) {\n if (!window.hljs) {\n return;\n }\n\n // Prevent multiple highlighting processes\n if (editor.isHighlighting && editor.isHighlighting()) {\n return;\n }\n\n // Set highlighting flag\n if (editor.setHighlighting) {\n editor.setHighlighting(true);\n }\n\n try {\n // Get current cursor position more reliably\n const selection = window.getSelection();\n let cursorOffset = 0;\n let cursorNode = null;\n let cursorNodeOffset = 0;\n \n if (selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n cursorNode = range.startContainer;\n cursorNodeOffset = range.startOffset;\n \n // Calculate absolute cursor position\n cursorOffset = getCursorOffset(editor, cursorNode, cursorNodeOffset);\n }\n\n // Get the plain text content\n const code = editor.textContent || editor.innerText || '';\n \n // Only apply highlighting if content is not empty\n if (!code.trim()) {\n return;\n }\n \n // Auto-detect language and highlight\n const result = window.hljs.highlightAuto(code);\n \n // Only update if the content is actually different\n const newHTML = result.value;\n if (editor.innerHTML !== newHTML) {\n // Apply highlighted HTML\n editor.innerHTML = newHTML;\n\n // Restore cursor position more accurately\n restoreCursorPositionImproved(editor, cursorOffset);\n }\n\n // Add detected language info (optional)\n if (result.language) {\n editor.setAttribute('data-language', result.language);\n }\n } catch (error) {\n } finally {\n // Always clear the highlighting flag\n if (editor.setHighlighting) {\n editor.setHighlighting(false);\n }\n }\n}\n\n\nfunction restoreCursorPositionImproved(editor, targetOffset) {\n if (targetOffset < 0) return;\n \n try {\n const selection = window.getSelection();\n const range = document.createRange();\n \n let currentOffset = 0;\n let targetNode = null;\n let targetNodeOffset = 0;\n \n const walker = document.createTreeWalker(\n editor,\n NodeFilter.SHOW_TEXT,\n null,\n false\n );\n \n let node;\n while (node = walker.nextNode()) {\n const nodeLength = node.textContent.length;\n \n if (currentOffset + nodeLength >= targetOffset) {\n targetNode = node;\n targetNodeOffset = Math.max(0, Math.min(targetOffset - currentOffset, nodeLength));\n break;\n }\n \n currentOffset += nodeLength;\n }\n \n if (targetNode) {\n range.setStart(targetNode, targetNodeOffset);\n range.collapse(true);\n \n selection.removeAllRanges();\n selection.addRange(range);\n } else {\n // Fallback: place cursor at end\n range.selectNodeContents(editor);\n range.collapse(false);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n } catch (error) {\n // Final fallback: just focus the editor\n try {\n editor.focus();\n } catch (focusError) {\n }\n }\n}\n\n// FIXED: More accurate cursor offset calculation\nfunction getCursorOffset(container, node, offset) {\n let cursorOffset = 0;\n \n if (!node || !container.contains(node)) {\n return 0;\n }\n \n const walker = document.createTreeWalker(\n container,\n NodeFilter.SHOW_TEXT,\n null,\n false\n );\n \n let currentNode;\n while (currentNode = walker.nextNode()) {\n if (currentNode === node) {\n return cursorOffset + Math.max(0, Math.min(offset, currentNode.textContent.length));\n }\n cursorOffset += currentNode.textContent.length;\n }\n \n return cursorOffset;\n}\n\n\nfunction extractTextFromCodeElement(codeElement) {\n if (!codeElement) return \"\";\n \n let codeContent = \"\";\n const childNodes = codeElement.childNodes;\n \n // If there are no child nodes, return empty\n if (childNodes.length === 0) {\n return codeElement.textContent || \"\";\n }\n \n for (let i = 0; i < childNodes.length; i++) {\n const node = childNodes[i];\n \n if (node.nodeType === Node.TEXT_NODE) {\n // Direct text content\n codeContent += node.textContent;\n } else if (node.tagName === 'tspan') {\n // Handle tspan elements - get all text content from this tspan\n const tspanText = node.textContent || \"\";\n codeContent += tspanText;\n \n // Add newline after each tspan except the last one\n // This assumes each tspan represents a line\n if (i < childNodes.length - 1) {\n const nextNode = childNodes[i + 1];\n if (nextNode && nextNode.tagName === 'tspan') {\n codeContent += \"\\n\";\n }\n }\n }\n }\n \n // Clean up the content - replace non-breaking spaces and normalize\n return codeContent.replace(/\\u00A0/g, ' ').replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n}\n\n// FIXED: Improved renderCodeFromEditor function\nfunction renderCodeFromEditor(input, codeElement, deleteIfEmpty = false) {\n const editorContainer = input.closest('.svg-code-container');\n if (!editorContainer || !document.body.contains(editorContainer)) {\n return;\n }\n\n // Get plain text content from the contenteditable div\n // FIXED: Use textContent instead of innerHTML to avoid HTML artifacts\n const code = input.textContent || input.innerText || \"\";\n const gElement = input.codeGroup;\n\n // Clean up event listeners\n if (input.handleClickOutside) {\n document.removeEventListener('pointerdown', input.handleClickOutside, true);\n }\n\n // Clear any pending highlighting timeouts\n if (input.clearHighlightTimeout) {\n input.clearHighlightTimeout();\n }\n\n document.body.removeChild(editorContainer);\n\n if (!gElement || !codeElement) {\n return;\n }\n\n if (!gElement.parentNode) {\n if (selectedCodeBlock === gElement) {\n deselectCodeBlock();\n }\n return;\n }\n\n if (deleteIfEmpty && code.trim() === \"\") {\n // Find the CodeShape wrapper\n let codeShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n codeShape = shapes.find(shape => shape.shapeName === 'code' && shape.group === gElement);\n if (codeShape) {\n const idx = shapes.indexOf(codeShape);\n if (idx !== -1) shapes.splice(idx, 1);\n }\n }\n\n pushDeleteActionWithAttachments({\n type: 'code',\n element: codeShape || gElement,\n shapeName: 'code'\n });\n\n if (typeof cleanupAttachments === 'function') {\n cleanupAttachments(gElement);\n }\n\n svg.removeChild(gElement);\n if (selectedCodeBlock === gElement) {\n selectedCodeBlock = null;\n removeCodeSelectionFeedback();\n }\n } else {\n // FIXED: Clear existing content completely before adding new content\n while (codeElement.firstChild) {\n codeElement.removeChild(codeElement.firstChild);\n }\n\n // Reset text content to empty to ensure clean slate\n codeElement.textContent = \"\";\n\n // Apply syntax highlighting and create SVG tspans\n const storedLang = codeElement.getAttribute(\"data-language\") || \"auto\";\n const highlightedCode = applySyntaxHighlightingToSVG(code, storedLang);\n createHighlightedSVGText(highlightedCode, codeElement);\n\n // Update background rectangle to fit content\n updateCodeBackground(gElement, codeElement);\n\n gElement.style.display = 'block';\n\n // Update attached arrows after code content change\n if (typeof updateAttachedArrows === 'function') {\n updateAttachedArrows(gElement);\n }\n\n if (selectedCodeBlock === gElement) {\n setTimeout(updateCodeSelectionFeedback, 0);\n }\n }\n\n // After rendering code, switch to selection tool and auto-select\n if (gElement.parentNode) {\n if (window.__sketchStoreApi) {\n window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });\n } else {\n window.isSelectionToolActive = true;\n }\n selectCodeBlock(gElement);\n }\n}\n\n// FIXED: Improved createHighlightedSVGText function\nfunction createHighlightedSVGText(highlightResult, parentElement) {\n if (!highlightResult || !highlightResult.value) {\n return;\n }\n\n const lines = highlightResult.value.split('\\n');\n const x = parentElement.getAttribute(\"x\") || 0;\n\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 \n if (line.trim()) {\n // Create highlighted tspans for non-empty lines\n createHighlightedTspans(line, tspan, x);\n \n // If no child tspans were created (plain text), set the text content\n if (tspan.childNodes.length === 0) {\n tspan.textContent = line;\n }\n } else {\n // Empty line - add a space to maintain line height\n tspan.textContent = \" \";\n }\n \n parentElement.appendChild(tspan);\n });\n}\n\n\n\n\n\n\nfunction applySyntaxHighlightingToSVG(code, language) {\n if (!window.hljs) {\n return { value: code, language: null };\n }\n\n const lang = language || codeLanguage;\n if (lang && lang !== \"auto\") {\n try {\n return window.hljs.highlight(code, { language: lang });\n } catch (e) {\n // fallback to auto-detect\n }\n }\n return window.hljs.highlightAuto(code);\n}\n\n\nfunction applySyntaxHighlighting(editor) {\n if (!window.hljs) {\n return;\n }\n\n // Get the plain text content\n const code = editor.textContent || editor.innerText;\n \n // Auto-detect language and highlight\n const result = window.hljs.highlightAuto(code);\n \n // Store cursor position\n const selection = window.getSelection();\n let cursorPos = 0;\n if (selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n cursorPos = range.startOffset;\n }\n\n // Apply highlighted HTML\n editor.innerHTML = result.value;\n\n // Restore cursor position\n restoreCursorPosition(editor, cursorPos);\n\n // Add detected language info (optional)\n if (result.language) {\n editor.setAttribute('data-language', result.language);\n }\n}\n\nfunction restoreCursorPosition(editor, position) {\n try {\n const range = document.createRange();\n const sel = window.getSelection();\n \n let textNode = null;\n let currentPos = 0;\n \n // Find the text node at the desired position\n const walker = document.createTreeWalker(\n editor,\n NodeFilter.SHOW_TEXT,\n null,\n false\n );\n \n while (walker.nextNode()) {\n const node = walker.currentNode;\n const textLength = node.textContent.length;\n \n if (currentPos + textLength >= position) {\n textNode = node;\n break;\n }\n currentPos += textLength;\n }\n \n if (textNode) {\n range.setStart(textNode, Math.min(position - currentPos, textNode.textContent.length));\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\n }\n } catch (error) {\n }\n}\n\n\nfunction renderCode(input, codeElement, deleteIfEmpty = false) {\n if (!input || !document.body.contains(input)) {\n return;\n }\n\n const code = input.value || \"\";\n const gElement = input.codeGroup;\n\n if (input.handleClickOutside) {\n document.removeEventListener('pointerdown', input.handleClickOutside, true);\n }\n\n document.body.removeChild(input);\n\n if (!gElement || !codeElement) {\n return;\n }\n\n if (!gElement.parentNode) {\n if (selectedCodeBlock === gElement) {\n deselectCodeBlock();\n }\n return;\n }\n\n if (deleteIfEmpty && code.trim() === \"\") {\n // Find the CodeShape wrapper\n let codeShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n codeShape = shapes.find(shape => shape.shapeName === 'code' && shape.group === gElement);\n if (codeShape) {\n const idx = shapes.indexOf(codeShape);\n if (idx !== -1) shapes.splice(idx, 1);\n }\n }\n\n pushDeleteActionWithAttachments({\n type: 'code',\n element: codeShape || gElement,\n shapeName: 'code'\n });\n\n if (typeof cleanupAttachments === 'function') {\n cleanupAttachments(gElement);\n }\n\n svg.removeChild(gElement);\n if (selectedCodeBlock === gElement) {\n selectedCodeBlock = null;\n removeCodeSelectionFeedback();\n }\n } else {\n // Clear existing content\n while (codeElement.firstChild) {\n codeElement.removeChild(codeElement.firstChild);\n }\n\n // Split into lines and create tspans with syntax highlighting\n const lines = code.split(\"\\n\");\n const x = codeElement.getAttribute(\"x\") || 0;\n\n lines.forEach((line, index) => {\n if (window.hljs && line.trim()) {\n // Get syntax highlighting for the line\n const result = window.hljs.highlightAuto(line);\n createHighlightedTspans(result.value, codeElement, x, index === 0 ? \"0\" : \"1.2em\");\n } else {\n // Create plain tspan for empty lines or when hljs is not available\n let 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.replace(/\\u00A0/g, ' ') || \" \";\n codeElement.appendChild(tspan);\n }\n });\n\n // Update background rectangle to fit content\n updateCodeBackground(gElement, codeElement);\n\n gElement.style.display = 'block';\n\n // Update attached arrows after code content change\n updateAttachedArrows(gElement);\n\n if (selectedCodeBlock === gElement) {\n setTimeout(updateCodeSelectionFeedback, 0);\n }\n }\n\n // After rendering code, switch to selection tool and auto-select\n if (gElement.parentNode) {\n if (window.__sketchStoreApi) {\n window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });\n } else {\n window.isSelectionToolActive = true;\n }\n selectCodeBlock(gElement);\n }\n}\n\n\nfunction createHighlightedTspans(highlightedHtml, parentTspan, x) {\n if (!highlightedHtml || !parentTspan) return;\n \n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = highlightedHtml;\n \n // Process all nodes in the highlighted HTML\n processHighlightedNodes(tempDiv, parentTspan);\n}\n\n\n\nfunction processHighlightedNodes(node, parentTspan) {\n if (!node || !parentTspan) return;\n \n for (let child of node.childNodes) {\n if (child.nodeType === Node.TEXT_NODE) {\n // Direct text content - add to parent tspan\n if (child.textContent) {\n if (parentTspan.textContent) {\n parentTspan.textContent += child.textContent;\n } else {\n parentTspan.textContent = child.textContent;\n }\n }\n } else if (child.nodeType === Node.ELEMENT_NODE) {\n // Create a new nested tspan for styled content\n let styledTspan = document.createElementNS(\"http://www.w3.org/2000/svg\", \"tspan\");\n styledTspan.textContent = child.textContent || \"\";\n \n // Apply comprehensive syntax highlighting colors\n const className = child.className || '';\n applyHighlightColor(styledTspan, className);\n \n parentTspan.appendChild(styledTspan);\n }\n }\n}\n\n\n\nfunction applyHighlightColor(tspan, className) {\n // GitHub Dark Dimmed theme colors\n if (className.includes('hljs-keyword') || className.includes('hljs-built_in')) {\n tspan.setAttribute(\"fill\", \"#ff7b72\"); // Red (keywords)\n } else if (className.includes('hljs-string') || className.includes('hljs-template-string')) {\n tspan.setAttribute(\"fill\", \"#a5d6ff\"); // Light blue (strings)\n } else if (className.includes('hljs-comment')) {\n tspan.setAttribute(\"fill\", \"#8b949e\"); // Gray (comments)\n tspan.setAttribute(\"font-style\", \"italic\");\n } else if (className.includes('hljs-number') || className.includes('hljs-literal')) {\n tspan.setAttribute(\"fill\", \"#79c0ff\"); // Blue (numbers/literals)\n } else if (className.includes('hljs-function') || className.includes('hljs-title')) {\n tspan.setAttribute(\"fill\", \"#d2a8ff\"); // Purple (functions)\n } else if (className.includes('hljs-variable') || className.includes('hljs-name')) {\n tspan.setAttribute(\"fill\", \"#ffa657\"); // Orange (variables)\n } else if (className.includes('hljs-type') || className.includes('hljs-class')) {\n tspan.setAttribute(\"fill\", \"#f0883e\"); // Orange (types)\n } else if (className.includes('hljs-operator') || className.includes('hljs-punctuation')) {\n tspan.setAttribute(\"fill\", \"#c9d1d9\"); // Light gray (operators)\n } else if (className.includes('hljs-property') || className.includes('hljs-attribute')) {\n tspan.setAttribute(\"fill\", \"#79c0ff\"); // Blue (properties)\n } else if (className.includes('hljs-tag')) {\n tspan.setAttribute(\"fill\", \"#7ee787\"); // Green (HTML tags)\n } else if (className.includes('hljs-meta') || className.includes('hljs-doctag')) {\n tspan.setAttribute(\"fill\", \"#8b949e\"); // Gray (meta)\n } else if (className.includes('hljs-regexp')) {\n tspan.setAttribute(\"fill\", \"#a5d6ff\"); // Light blue (regex)\n } else {\n tspan.setAttribute(\"fill\", \"#c9d1d9\"); // GitHub default text color\n }\n}\n\n\nfunction createCodeSelectionFeedback(groupElement) {\n if (!groupElement) return;\n removeCodeSelectionFeedback();\n\n const backgroundRect = groupElement.querySelector('.code-background');\n if (!backgroundRect) {\n return;\n }\n\n // Use background rect dimensions for selection feedback\n const x = parseFloat(backgroundRect.getAttribute('x'));\n const y = parseFloat(backgroundRect.getAttribute('y'));\n const width = parseFloat(backgroundRect.getAttribute('width'));\n const height = parseFloat(backgroundRect.getAttribute('height'));\n\n const zoom = window.currentZoom || 1;\n const padding = 8 / zoom;\n const handleSize = 10 / zoom;\n const handleOffset = handleSize / 2;\n\n const selX = x - padding;\n const selY = y - padding;\n const selWidth = width + 2 * padding;\n const selHeight = height + 2 * padding;\n\n // Draw selection outline (polyline)\n const outlinePoints = [\n [selX, selY],\n [selX + selWidth, selY],\n [selX + selWidth, selY + selHeight],\n [selX, selY + selHeight],\n [selX, selY]\n ];\n const pointsAttr = outlinePoints.map(p => p.join(',')).join(' ');\n codeSelectionBox = document.createElementNS(\"http://www.w3.org/2000/svg\", \"polyline\");\n codeSelectionBox.setAttribute(\"class\", \"selection-box\");\n codeSelectionBox.setAttribute(\"points\", pointsAttr);\n codeSelectionBox.setAttribute(\"fill\", \"none\");\n codeSelectionBox.setAttribute(\"stroke\", \"#5B57D1\");\n codeSelectionBox.setAttribute(\"stroke-width\", \"1.5\");\n codeSelectionBox.setAttribute(\"stroke-dasharray\", \"4 2\");\n codeSelectionBox.setAttribute(\"vector-effect\", \"non-scaling-stroke\");\n codeSelectionBox.setAttribute(\"pointer-events\", \"none\");\n groupElement.appendChild(codeSelectionBox);\n\n // Add resize handles and rotation anchor (rest of the function remains the same)\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 codeResizeHandles = {};\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\", 2);\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 codeResizeHandles[handle.name] = handleRect;\n\n handleRect.addEventListener('pointerdown', (e) => {\n if (window.isSelectionToolActive) {\n e.stopPropagation();\n startCodeResize(e, handle.name);\n }\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', 2);\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 codeResizeHandles.rotate = rotationAnchor;\n\n rotationAnchor.addEventListener('pointerdown', (e) => {\n if (window.isSelectionToolActive) {\n e.stopPropagation();\n startCodeRotation(e);\n }\n });\n}\n\n\nfunction updateCodeBackground(groupElement, codeElement) {\n const backgroundRect = groupElement.querySelector('.code-background');\n if (!backgroundRect || !codeElement) return;\n\n const textBBox = codeElement.getBBox();\n const padding = 10;\n\n // Update background dimensions to fit text content\n backgroundRect.setAttribute(\"x\", textBBox.x - padding);\n backgroundRect.setAttribute(\"y\", textBBox.y - padding);\n backgroundRect.setAttribute(\"width\", textBBox.width + (padding * 2));\n backgroundRect.setAttribute(\"height\", textBBox.height + (padding * 2));\n}\n\n\nfunction updateCodeSelectionFeedback() {\n if (!selectedCodeBlock || !codeSelectionBox) return;\n\n const codeElement = selectedCodeBlock.querySelector('text');\n if (!codeElement) return;\n\n // Temporarily set display to 'block' if it was hidden to get correct bbox\n const wasHidden = selectedCodeBlock.style.display === 'none';\n if (wasHidden) selectedCodeBlock.style.display = 'block';\n\n const bbox = codeElement.getBBox(); // Fix: use codeElement, not undefined foreignObject\n\n if (wasHidden) selectedCodeBlock.style.display = 'none';\n\n if (bbox.width === 0 && bbox.height === 0 && codeElement.textContent.trim() !== \"\") {\n }\n\n const zoom = window.currentZoom || 1;\n const padding = 8 / zoom;\n const handleSize = 10 / zoom;\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 codeSelectionBox.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 = codeResizeHandles[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 = codeResizeHandles.rotate;\n if (rotationAnchor) {\n const rotationAnchorPos = { x: selX + selWidth / 2, y: selY - 30 / zoom };\n rotationAnchor.setAttribute('cx', rotationAnchorPos.x);\n rotationAnchor.setAttribute('cy', rotationAnchorPos.y);\n }\n}\n\n\n\nfunction startCodeRotation(event) {\n if (!selectedCodeBlock || event.button !== 0) return;\n event.preventDefault();\n event.stopPropagation();\n\n isCodeRotating = true;\n isCodeDragging = false;\n isCodeResizing = false;\n\n const codeElement = selectedCodeBlock.querySelector('text'); // Fix: use text element instead of foreignObject\n if (!codeElement) return;\n\n const bbox = codeElement.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 = selectedCodeBlock.transform.baseVal.consolidate();\n if (groupTransform) {\n centerPoint = centerPoint.matrixTransform(groupTransform.matrix);\n }\n\n codeRotationStartAngle = Math.atan2(mousePos.y - centerPoint.y, mousePos.x - centerPoint.x) * 180 / Math.PI;\n\n const currentTransform = selectedCodeBlock.transform.baseVal.consolidate();\n codeRotationStartTransform = currentTransform ? currentTransform.matrix : svg.createSVGMatrix();\n\n svg.style.cursor = 'grabbing';\n\n window.addEventListener('pointermove', handleCodeMouseMove); // Fix: use window instead of svg\n window.addEventListener('pointerup', handleCodeMouseUp);\n}\n\n\nfunction removeCodeSelectionFeedback() {\n if (selectedCodeBlock) {\n selectedCodeBlock.querySelectorAll(\".selection-box, .resize-handle, .rotate-anchor\").forEach(el => el.remove());\n }\n codeSelectionBox = null;\n codeResizeHandles = {};\n}\n\nfunction selectCodeBlock(groupElement) {\n if (!groupElement || !groupElement.parentNode) return;\n if (groupElement === selectedCodeBlock) return;\n\n deselectCodeBlock();\n selectedCodeBlock = groupElement;\n selectedCodeBlock.classList.add(\"selected\");\n createCodeSelectionFeedback(selectedCodeBlock);\n updateSelectedElement(selectedCodeBlock);\n\n // Update code toggle to reflect code mode\n const toggleSpans = document.querySelectorAll(\".textCodeSpan\");\n toggleSpans.forEach(el => el.classList.remove(\"selected\"));\n toggleSpans.forEach(el => {\n if (el.getAttribute(\"data-id\") === \"true\") el.classList.add(\"selected\");\n });\n // Show the text/code property panel via React bridge (pass 'code' to set code mode)\n if (window.__showSidebarForShape) window.__showSidebarForShape('code');\n}\n\nfunction deselectCodeBlock() {\n const activeEditor = document.querySelector(\".svg-code-editor[contenteditable='true']\");\n if (activeEditor) {\n let groupElement = activeEditor.originalGroup;\n if (groupElement) {\n renderCode(activeEditor, true);\n } else if (document.body.contains(activeEditor)){\n activeEditor.remove();\n }\n }\n if (selectedCodeBlock) {\n removeCodeSelectionFeedback();\n selectedCodeBlock.classList.remove(\"selected\");\n selectedCodeBlock = null;\n updateSelectedElement(null);\n }\n if (isCodeRotating) {\n isCodeRotating = false;\n codeRotationStartAngle = 0;\n codeRotationStartTransform = null;\n svg.style.cursor = 'default';\n window.removeEventListener('pointermove', handleCodeMouseMove);\n window.removeEventListener('pointerup', handleCodeMouseUp);\n }\n}\n\n\nfunction startCodeDrag(event) {\n if (!selectedCodeBlock || event.button !== 0) return;\n\n if (event.target.closest('.resize-handle')) {\n return;\n }\n\n isCodeDragging = true;\n isCodeResizing = false;\n event.preventDefault();\n\n const currentTransform = selectedCodeBlock.transform.baseVal.consolidate();\n const initialTranslateX = currentTransform ? currentTransform.matrix.e : 0;\n const initialTranslateY = currentTransform ? currentTransform.matrix.f : 0;\n\n startCodePoint = getSVGCoordinates(event);\n\n codeDragOffsetX = startCodePoint.x - initialTranslateX;\n codeDragOffsetY = startCodePoint.y - initialTranslateY;\n\n // Find the CodeShape wrapper for frame functionality\n let codeShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n codeShape = shapes.find(shape => shape.shapeName === 'code' && shape.group === selectedCodeBlock);\n }\n\n if (codeShape) {\n // Store initial frame state\n draggedCodeInitialFrame = codeShape.parentFrame || null;\n \n // Temporarily remove from frame clipping if dragging\n if (codeShape.parentFrame) {\n codeShape.parentFrame.temporarilyRemoveFromFrame(codeShape);\n }\n }\n\n svg.style.cursor = 'grabbing';\n\n window.addEventListener('pointermove', handleCodeMouseMove); // Fix: use window\n window.addEventListener('pointerup', handleCodeMouseUp); // Fix: use window\n}\n\nfunction startCodeResize(event, anchor) {\n if (!selectedCodeBlock || event.button !== 0) return;\n event.preventDefault();\n event.stopPropagation();\n\n isCodeResizing = true;\n isCodeDragging = false;\n currentCodeResizeHandle = anchor;\n\n \n const codeElement = selectedCodeBlock.querySelector('text');\n if (!codeElement) {\n isCodeResizing = false;\n return;\n }\n\n startCodeBBox = codeElement.getBBox();\n startCodeFontSize = parseFloat(codeElement.getAttribute(\"font-size\") || 25);\n if (isNaN(startCodeFontSize)) startCodeFontSize = 25;\n\n startCodePoint = getSVGCoordinates(event, selectedCodeBlock);\n\n const currentTransform = selectedCodeBlock.transform.baseVal.consolidate();\n initialCodeGroupTx = currentTransform ? currentTransform.matrix.e : 0;\n initialCodeGroupTy = currentTransform ? currentTransform.matrix.f : 0;\n\n const padding = 3;\n const startX = startCodeBBox.x - padding;\n const startY = startCodeBBox.y - padding;\n const startWidth = startCodeBBox.width + 2 * padding;\n const startHeight = startCodeBBox.height + 2 * padding;\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 initialCodeHandlePosRelGroup = { x: hx, y: hy };\n\n svg.style.cursor = codeResizeHandles[anchor]?.style.cursor || 'default';\n\n window.addEventListener('pointermove', handleCodeMouseMove); \n window.addEventListener('pointerup', handleCodeMouseUp); \n}\n\n\n\n\nconst handleCodeMouseMove = (event) => {\n if (!selectedCodeBlock) 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 (isCodeDragging) {\n const currentPoint = getSVGCoordinates(event);\n const newTranslateX = currentPoint.x - codeDragOffsetX;\n const newTranslateY = currentPoint.y - codeDragOffsetY;\n\n const currentTransform = selectedCodeBlock.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 codeElement = selectedCodeBlock.querySelector('text');\n if (codeElement) {\n const bbox = codeElement.getBBox();\n const centerX = bbox.x + bbox.width / 2;\n const centerY = bbox.y + bbox.height / 2;\n\n selectedCodeBlock.setAttribute('transform',\n `translate(${newTranslateX}, ${newTranslateY}) rotate(${angle}, ${centerX}, ${centerY})`\n );\n } else {\n selectedCodeBlock.setAttribute('transform', `translate(${newTranslateX}, ${newTranslateY})`);\n }\n } else {\n selectedCodeBlock.setAttribute('transform', `translate(${newTranslateX}, ${newTranslateY})`);\n }\n\n // Update frame containment for CodeShape wrapper\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n const codeShape = shapes.find(shape => shape.shapeName === 'code' && shape.group === selectedCodeBlock);\n if (codeShape) {\n codeShape.updateFrameContainment();\n }\n }\n\n // Update attached arrows during dragging\n updateAttachedArrows(selectedCodeBlock);\n\n } else if (isCodeResizing) {\n const codeElement = selectedCodeBlock.querySelector('text');\n if (!codeElement || !startCodeBBox || startCodeFontSize === null || !startCodePoint || !initialCodeHandlePosRelGroup) return;\n\n const currentPoint = getSVGCoordinates(event, selectedCodeBlock);\n\n const startX = startCodeBBox.x;\n const startY = startCodeBBox.y;\n const startWidth = startCodeBBox.width;\n const startHeight = startCodeBBox.height;\n\n let anchorX, anchorY;\n\n switch (currentCodeResizeHandle) {\n case 'nw':\n anchorX = startX + startWidth;\n anchorY = startY + startHeight;\n break;\n case 'ne':\n anchorX = startX;\n anchorY = startY + startHeight;\n break;\n case 'sw':\n anchorX = startX + startWidth;\n anchorY = startY;\n break;\n case 'se':\n anchorX = startX;\n anchorY = startY;\n break;\n }\n\n const newWidth = Math.abs(currentPoint.x - anchorX);\n const newHeight = Math.abs(currentPoint.y - anchorY);\n\n const chosenScale = newHeight / startHeight;\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 = startCodeFontSize * clampedScale;\n const minFontSize = 5;\n const finalFontSize = Math.max(newFontSize, minFontSize);\n\n codeElement.setAttribute(\"font-size\", `${finalFontSize}px`);\n\n const currentBBox = codeElement.getBBox();\n\n let newAnchorX, newAnchorY;\n\n switch (currentCodeResizeHandle) {\n case 'nw':\n newAnchorX = currentBBox.x + currentBBox.width;\n newAnchorY = currentBBox.y + currentBBox.height;\n break;\n case 'ne':\n newAnchorX = currentBBox.x;\n newAnchorY = currentBBox.y + currentBBox.height;\n break;\n case 'sw':\n newAnchorX = currentBBox.x + currentBBox.width;\n newAnchorY = currentBBox.y;\n break;\n case 'se':\n newAnchorX = currentBBox.x;\n newAnchorY = currentBBox.y;\n break;\n }\n\n const deltaX = anchorX - newAnchorX;\n const deltaY = anchorY - newAnchorY;\n\n const currentTransform = selectedCodeBlock.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 newGroupTx = initialCodeGroupTx + deltaX;\n const newGroupTy = initialCodeGroupTy + deltaY;\n\n const centerX = currentBBox.x + currentBBox.width / 2;\n const centerY = currentBBox.y + currentBBox.height / 2;\n\n selectedCodeBlock.setAttribute('transform',\n `translate(${newGroupTx}, ${newGroupTy}) rotate(${angle}, ${centerX}, ${centerY})`\n );\n } else {\n const newGroupTx = initialCodeGroupTx + deltaX;\n const newGroupTy = initialCodeGroupTy + deltaY;\n selectedCodeBlock.setAttribute('transform', `translate(${newGroupTx}, ${newGroupTy})`);\n }\n\n // Update background to fit new text size\n updateCodeBackground(selectedCodeBlock, codeElement);\n\n // Update attached arrows during resizing\n updateAttachedArrows(selectedCodeBlock);\n\n clearTimeout(selectedCodeBlock.updateFeedbackTimeout);\n selectedCodeBlock.updateFeedbackTimeout = setTimeout(() => {\n updateCodeSelectionFeedback();\n delete selectedCodeBlock.updateFeedbackTimeout;\n }, 0);\n\n } else if (isCodeRotating) {\n const codeElement = selectedCodeBlock.querySelector('text');\n if (!codeElement) return;\n\n const bbox = codeElement.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 = selectedCodeBlock.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 - codeRotationStartAngle;\n\n const newTransform = `translate(${codeRotationStartTransform.e}, ${codeRotationStartTransform.f}) rotate(${rotationDiff}, ${centerX}, ${centerY})`;\n selectedCodeBlock.setAttribute('transform', newTransform);\n\n // Update attached arrows during rotation\n updateAttachedArrows(selectedCodeBlock);\n\n updateCodeSelectionFeedback();\n }\n\n // Handle cursor changes for code tool\n if ((isCodeToolActive || (isTextToolActive && isTextInCodeMode)) && !isCodeDragging && !isCodeResizing && !isCodeRotating) {\n svg.style.cursor = 'text';\n \n // Frame highlighting logic for code tool\n const { x, y } = getSVGCoordinates(event);\n \n const tempCodeBounds = {\n x: x - 275, \n y: y - 30, \n width: 550,\n height: 60\n };\n \n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.forEach(frame => {\n if (frame.shapeName === 'frame') {\n if (frame.isShapeInFrame(tempCodeBounds)) {\n frame.highlightFrame();\n hoveredCodeFrame = frame;\n } else if (hoveredCodeFrame === frame) {\n frame.removeHighlight();\n hoveredCodeFrame = null;\n }\n }\n });\n }\n } else if (isSelectionToolActive && !isCodeDragging && !isCodeResizing && !isCodeRotating) {\n const targetGroup = event.target.closest('g[data-type=\"code-group\"]');\n if (targetGroup) {\n svg.style.cursor = 'move';\n } else {\n svg.style.cursor = 'default';\n }\n }\n};\n\n// Add this complete mouse up handler\nconst handleCodeMouseUp = (event) => {\n if (event.button !== 0) return;\n\n if (isCodeDragging && selectedCodeBlock) {\n const currentTransform = selectedCodeBlock.transform.baseVal.consolidate();\n if (currentTransform) {\n const finalTranslateX = currentTransform.matrix.e;\n const finalTranslateY = currentTransform.matrix.f;\n\n const initialX = parseFloat(selectedCodeBlock.getAttribute(\"data-x\")) || 0;\n const initialY = parseFloat(selectedCodeBlock.getAttribute(\"data-y\")) || 0;\n\n // Find the CodeShape wrapper for frame tracking\n let codeShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n codeShape = shapes.find(shape => shape.shapeName === 'code' && shape.group === selectedCodeBlock);\n }\n\n // Add frame information for undo tracking\n const oldPosWithFrame = {\n x: initialX,\n y: initialY,\n rotation: extractRotationFromTransform(selectedCodeBlock) || 0,\n parentFrame: draggedCodeInitialFrame\n };\n const newPosWithFrame = {\n x: finalTranslateX,\n y: finalTranslateY,\n rotation: extractRotationFromTransform(selectedCodeBlock) || 0,\n parentFrame: codeShape ? codeShape.parentFrame : 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: 'code',\n element: selectedCodeBlock,\n shapeName: 'code'\n },\n oldPosWithFrame,\n newPosWithFrame\n );\n }\n\n // Handle frame containment changes after drag\n if (codeShape) {\n const finalFrame = hoveredCodeFrame;\n \n // If shape moved to a different frame\n if (draggedCodeInitialFrame !== finalFrame) {\n // Remove from initial frame\n if (draggedCodeInitialFrame) {\n draggedCodeInitialFrame.removeShapeFromFrame(codeShape);\n }\n \n // Add to new frame\n if (finalFrame) {\n finalFrame.addShapeToFrame(codeShape);\n }\n \n // Track the frame change for undo\n if (frameChanged) {\n pushFrameAttachmentAction(finalFrame || draggedCodeInitialFrame, codeShape, \n finalFrame ? 'attach' : 'detach', draggedCodeInitialFrame);\n }\n } else if (draggedCodeInitialFrame) {\n // Shape stayed in same frame, restore clipping\n draggedCodeInitialFrame.restoreToFrame(codeShape);\n }\n }\n\n selectedCodeBlock.setAttribute(\"data-x\", finalTranslateX);\n selectedCodeBlock.setAttribute(\"data-y\", finalTranslateY);\n }\n\n draggedCodeInitialFrame = null;\n\n } else if (isCodeResizing && selectedCodeBlock) {\n const codeElement = selectedCodeBlock.querySelector('text');\n if (codeElement) {\n const finalFontSize = codeElement.getAttribute(\"font-size\");\n const initialFontSize = startCodeFontSize;\n\n const currentTransform = selectedCodeBlock.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: 'code',\n element: selectedCodeBlock,\n shapeName: 'code'\n },\n {\n x: initialCodeGroupTx,\n y: initialCodeGroupTy,\n fontSize: initialFontSize,\n rotation: extractRotationFromTransform(selectedCodeBlock) || 0\n },\n {\n x: finalTranslateX,\n y: finalTranslateY,\n fontSize: parseFloat(finalFontSize),\n rotation: extractRotationFromTransform(selectedCodeBlock) || 0\n }\n );\n\n selectedCodeBlock.setAttribute(\"data-x\", finalTranslateX);\n selectedCodeBlock.setAttribute(\"data-y\", finalTranslateY);\n }\n\n clearTimeout(selectedCodeBlock.updateFeedbackTimeout);\n updateCodeSelectionFeedback();\n }\n } else if (isCodeRotating && selectedCodeBlock) {\n const currentTransform = selectedCodeBlock.transform.baseVal.consolidate();\n if (currentTransform && codeRotationStartTransform) {\n const initialRotation = Math.atan2(codeRotationStartTransform.b, codeRotationStartTransform.a) * 180 / Math.PI;\n const finalRotation = extractRotationFromTransform(selectedCodeBlock) || 0;\n\n if (Math.abs(initialRotation - finalRotation) > 1) {\n pushTransformAction(\n {\n type: 'code',\n element: selectedCodeBlock,\n shapeName: 'code'\n },\n {\n x: codeRotationStartTransform.e,\n y: codeRotationStartTransform.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 updateCodeSelectionFeedback();\n }\n\n // Clear frame highlighting\n if (hoveredCodeFrame) {\n hoveredCodeFrame.removeHighlight();\n hoveredCodeFrame = null;\n }\n\n // Handle code deselection when clicking outside\n if (isSelectionToolActive) {\n const targetGroup = event.target.closest('g[data-type=\"code-group\"]');\n const isResizeHandle = event.target.closest('.resize-handle');\n const isRotateAnchor = event.target.closest('.rotate-anchor');\n \n // If we didn't click on code block or its controls, deselect\n if (!targetGroup && !isResizeHandle && !isRotateAnchor && selectedCodeBlock) {\n deselectCodeBlock();\n }\n }\n\n isCodeDragging = false;\n isCodeResizing = false;\n isCodeRotating = false;\n currentCodeResizeHandle = null;\n startCodePoint = null;\n startCodeBBox = null;\n startCodeFontSize = null;\n codeDragOffsetX = undefined;\n codeDragOffsetY = undefined;\n initialCodeHandlePosRelGroup = null;\n initialCodeGroupTx = 0;\n initialCodeGroupTy = 0;\n codeRotationStartAngle = 0;\n codeRotationStartTransform = null;\n\n svg.style.cursor = 'default';\n\n svg.removeEventListener('pointermove', handleCodeMouseMove);\n svg.removeEventListener('pointerup', handleCodeMouseUp);\n};\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\nconst handleCodeMouseDown = function (e) {\n if (!e.target) return;\n // Check for contenteditable code editor (new style)\n const activeContentEditor = document.querySelector(\".svg-code-editor[contenteditable='true']\");\n if (activeContentEditor) {\n const editorContainer = activeContentEditor.closest('.svg-code-container');\n if (editorContainer && editorContainer.contains(e.target)) {\n return;\n }\n let codeElement = activeContentEditor.originalCodeElement;\n if (codeElement) {\n renderCodeFromEditor(activeContentEditor, codeElement, true);\n } else if (editorContainer && document.body.contains(editorContainer)) {\n document.body.removeChild(editorContainer);\n }\n }\n // Check for textarea code editor (legacy style)\n const activeEditor = document.querySelector(\"textarea.svg-code-editor\");\n if (activeEditor && activeEditor.contains(e.target)) {\n return;\n }\n if (activeEditor && !activeEditor.contains(e.target)) {\n let codeElement = activeEditor.originalCodeElement;\n if (codeElement) {\n renderCode(activeEditor, codeElement, true);\n } else if (document.body.contains(activeEditor)){\n document.body.removeChild(activeEditor);\n }\n }\n\n const targetGroup = e.target.closest('g[data-type=\"code-group\"]');\n\n if (isSelectionToolActive && e.button === 0) {\n if (targetGroup) {\n if (e.target.closest('.resize-handle') || e.target.closest('.rotate-anchor')) {\n return; // Let resize/rotate handlers manage\n }\n \n // If clicking on the code block itself, select it and start drag\n if (targetGroup === selectedCodeBlock) {\n startCodeDrag(e);\n } else {\n selectCodeBlock(targetGroup);\n startCodeDrag(e);\n }\n } else {\n deselectCodeBlock();\n }\n\n } else if ((isCodeToolActive || isTextToolActive) && e.button === 0) {\n if (targetGroup) {\n const codeElement = targetGroup.querySelector('text');\n\n if (codeElement && (e.target.tagName === \"text\" || e.target.tagName === \"tspan\")) {\n makeCodeEditable(codeElement, targetGroup, e); // Pass click event for position\n e.stopPropagation();\n } else {\n deselectCodeBlock();\n addCodeBlock(e);\n }\n } else {\n deselectCodeBlock();\n addCodeBlock(e);\n }\n }\n};\n\n\n// updateAttachedArrows is imported from drawArrow.js\n\ncodeTextColorOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n codeTextColorOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n\n const newColor = span.getAttribute(\"data-id\");\n const oldColor = codeTextColor;\n codeTextColor = newColor;\n\n if (selectedCodeBlock) {\n const codeEditor = selectedCodeBlock.querySelector('.svg-code-editor');\n if (codeEditor) {\n const currentColor = codeEditor.style.color;\n\n if (currentColor !== newColor) {\n pushOptionsChangeAction(\n {\n type: 'code',\n element: selectedCodeBlock,\n shapeName: 'code'\n },\n {\n color: currentColor,\n font: codeEditor.style.fontFamily,\n size: codeEditor.style.fontSize,\n align: codeEditor.style.textAlign // Although mostly 'left'\n },\n {\n color: newColor,\n font: codeEditor.style.fontFamily,\n size: codeEditor.style.fontSize,\n align: codeEditor.style.textAlign\n }\n );\n }\n\n codeEditor.style.color = newColor;\n updateSyntaxHighlighting(codeEditor); // Re-highlight with new color\n }\n }\n });\n});\n\ncodeTextFontOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n codeTextFontOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n\n const newFont = span.getAttribute(\"data-id\");\n const oldFont = codeTextFont;\n codeTextFont = newFont;\n\n if (selectedCodeBlock) {\n const codeEditor = selectedCodeBlock.querySelector('.svg-code-editor');\n if (codeEditor) {\n const currentFont = codeEditor.style.fontFamily;\n\n if (currentFont !== newFont) {\n pushOptionsChangeAction(\n {\n type: 'code',\n element: selectedCodeBlock,\n shapeName: 'code'\n },\n {\n color: codeEditor.style.color,\n font: currentFont,\n size: codeEditor.style.fontSize,\n align: codeEditor.style.textAlign\n },\n {\n color: codeEditor.style.color,\n font: newFont,\n size: codeEditor.style.fontSize,\n align: codeEditor.style.textAlign\n }\n );\n }\n\n codeEditor.style.fontFamily = newFont;\n updateSyntaxHighlighting(codeEditor); // Re-highlight with new font\n setTimeout(updateCodeSelectionFeedback, 0);\n }\n }\n });\n});\n\ncodeTextSizeOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n codeTextSizeOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n\n const newSize = span.getAttribute(\"data-id\") + \"px\";\n const oldSize = codeTextSize;\n codeTextSize = newSize;\n\n if (selectedCodeBlock) {\n const codeEditor = selectedCodeBlock.querySelector('.svg-code-editor');\n if (codeEditor) {\n const currentSize = codeEditor.style.fontSize;\n\n if (currentSize !== newSize) {\n pushOptionsChangeAction(\n {\n type: 'code',\n element: selectedCodeBlock,\n shapeName: 'code'\n },\n {\n color: codeEditor.style.color,\n font: codeEditor.style.fontFamily,\n size: currentSize,\n align: codeEditor.style.textAlign\n },\n {\n color: codeEditor.style.color,\n font: codeEditor.style.fontFamily,\n size: newSize,\n align: codeEditor.style.textAlign\n }\n );\n }\n\n codeEditor.style.fontSize = newSize;\n adjustCodeEditorSize(codeEditor); // Adjust container size as font size changes\n updateSyntaxHighlighting(codeEditor); // Re-highlight with new size\n setTimeout(updateCodeSelectionFeedback, 0);\n }\n }\n });\n});\n\ncodeTextAlignOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n codeTextAlignOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n\n const newAlign = span.getAttribute(\"data-id\");\n const oldAlign = codeTextAlign;\n codeTextAlign = newAlign;\n\n if (selectedCodeBlock) {\n const codeEditor = selectedCodeBlock.querySelector('.svg-code-editor');\n if (codeEditor) {\n const currentAlign = codeEditor.style.textAlign;\n\n if (currentAlign !== newAlign) {\n pushOptionsChangeAction(\n {\n type: 'code',\n element: selectedCodeBlock,\n shapeName: 'code'\n },\n {\n color: codeEditor.style.color,\n font: codeEditor.style.fontFamily,\n size: codeEditor.style.fontSize,\n align: currentAlign\n },\n {\n color: codeEditor.style.color,\n font: codeEditor.style.fontFamily,\n size: codeEditor.style.fontSize,\n align: newAlign\n }\n );\n }\n // Code is typically left-aligned, but if user forces, apply it.\n // Note: Highlight.js might override some text-alignment styles on its own.\n codeEditor.style.textAlign = newAlign; \n setTimeout(updateCodeSelectionFeedback, 0);\n }\n }\n });\n});\n\n\n\nconst editorStyles = `\n.svg-code-container {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n border-radius: 6px;\n}\n\n.svg-code-editor {\n scrollbar-width: thin;\n scrollbar-color: #484f58 #161b22;\n}\n\n.svg-code-editor::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n}\n\n.svg-code-editor::-webkit-scrollbar-track {\n background: #161b22;\n border-radius: 6px;\n}\n\n.svg-code-editor::-webkit-scrollbar-thumb {\n background: #484f58;\n border-radius: 6px;\n}\n\n.svg-code-editor::-webkit-scrollbar-thumb:hover {\n background: #6e7681;\n}\n\n/* Language detection indicator */\n.svg-code-container::after {\n content: attr(data-language);\n position: absolute;\n top: -20px;\n right: 0;\n background: #007acc;\n color: white;\n padding: 2px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-family: monospace;\n opacity: 0.8;\n}\n`;\n\n\nif (!document.getElementById('code-editor-styles')) {\n const styleSheet = document.createElement('style');\n styleSheet.id = 'code-editor-styles';\n styleSheet.textContent = editorStyles;\n document.head.appendChild(styleSheet);\n}\n\nfunction setCodeLanguage(lang) {\n codeLanguage = lang;\n // Update selected code block's language if one is selected\n if (selectedCodeBlock) {\n const codeElement = selectedCodeBlock.querySelector('text');\n if (codeElement) {\n codeElement.setAttribute(\"data-language\", lang);\n }\n }\n}\n\nfunction getCodeLanguage() {\n return codeLanguage;\n}\n\nfunction getSelectedCodeBlock() {\n return selectedCodeBlock;\n}\n\nexport {\n handleCodeMouseDown,\n handleCodeMouseMove,\n handleCodeMouseUp,\n addCodeBlock,\n wrapCodeElement,\n selectCodeBlock,\n deselectCodeBlock,\n makeCodeEditable,\n applySyntaxHighlightingToSVG,\n createHighlightedSVGText,\n updateCodeBackground,\n extractTextFromCodeElement,\n setCodeLanguage,\n getCodeLanguage,\n getSelectedCodeBlock\n};\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,4 +1,7 @@
1
1
  "use client";
2
+ import {
3
+ registerRotationAnchor
4
+ } from "./chunk-PAKA6HUX.js";
2
5
 
3
6
  // src/shapes/Frame.js
4
7
  function getSVGCoordsFromMouse(e) {
@@ -635,6 +638,12 @@ var Frame = class {
635
638
  rotationLine.setAttribute("transform", `rotate(${this.rotation}, ${centerX}, ${centerY})`);
636
639
  }
637
640
  this.group.appendChild(rotationLine);
641
+ registerRotationAnchor(anchor, {
642
+ radius: 8,
643
+ edgeY: this.y,
644
+ line: rotationLine,
645
+ lineEnd: "2"
646
+ });
638
647
  } else {
639
648
  anchor = document.createElementNS("http://www.w3.org/2000/svg", "rect");
640
649
  anchor.setAttribute("x", position.x - anchorSize / 2);
@@ -1228,4 +1237,4 @@ var Frame = class {
1228
1237
  export {
1229
1238
  Frame
1230
1239
  };
1231
- //# sourceMappingURL=chunk-CF7AK4ES.js.map
1240
+ //# sourceMappingURL=chunk-75G7XSZU.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/shapes/Frame.js"],
4
+ "sourcesContent": ["/* eslint-disable */\n// Frame shape class - extracted from frameHolder.js\n// Depends on globals: svg, shapes, currentShape, currentZoom\n\nimport { cleanupAttachments } from '../tools/arrowTool.js';\nimport { registerRotationAnchor } from '../core/ScreenSpaceControls.js';\n\nfunction getSVGCoordsFromMouse(e) {\n const viewBox = svg.viewBox.baseVal;\n const rect = svg.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const mouseY = e.clientY - rect.top;\n const svgX = viewBox.x + (mouseX / rect.width) * viewBox.width;\n const svgY = viewBox.y + (mouseY / rect.height) * viewBox.height;\n return { x: svgX, y: svgY };\n}\n\nlet dragOldPosFrame = null;\n\nclass Frame {\n constructor(x, y, width, height, options = {}) {\n this.x = x;\n this.y = y;\n this.width = width;\n this.height = height;\n this.rotation = options.rotation || 0;\n this.frameName = options.frameName || \"Frame\";\n this.fillStyle = options.fillStyle || \"transparent\"; // 'transparent' | 'solid' | 'grid'\n this.fillColor = options.fillColor || \"#1e1e28\";\n this.gridSize = options.gridSize || 20;\n // Issue #38 follow-up: read the grid stroke from a CSS custom\n // property so the frame grid stays visible in both themes. The\n // var is defined in globals.css for both `body.canvas-mode`\n // (dark-on-light) and `body.canvas-mode.theme-dark` (light-on-dark).\n // The literal here is the dark-theme fallback for environments\n // (tests, embeds) without the canvas-mode CSS in scope.\n this.gridColor = options.gridColor || \"var(--lixsketch-grid-fine, rgba(255,255,255,0.06))\";\n this.options = {\n stroke: options.stroke || \"#555\",\n strokeWidth: options.strokeWidth || 1,\n fill: options.fill || \"transparent\",\n opacity: options.opacity || 1,\n ...options\n };\n\n this.element = null;\n this.group = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n this.isSelected = false;\n this.anchors = [];\n this.shapeName = \"frame\";\n this.shapeID = `frame-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n this.group.setAttribute('id', this.shapeID);\n\n // Create clipping group for contained shapes\n this.clipGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n this.clipPath = document.createElementNS('http://www.w3.org/2000/svg', 'clipPath');\n this.clipRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n \n // Set up clipping\n this.clipId = `clip-${this.shapeID}`;\n this.clipPath.setAttribute('id', this.clipId);\n this.clipPath.appendChild(this.clipRect);\n this.clipGroup.setAttribute('clip-path', `url(#${this.clipId})`);\n \n // Add clip path to defs\n let defs = svg.querySelector('defs');\n if (!defs) {\n defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\n svg.appendChild(defs);\n }\n defs.appendChild(this.clipPath);\n\n // Array to hold shapes inside this frame\n this.containedShapes = [];\n\n svg.appendChild(this.group);\n svg.appendChild(this.clipGroup);\n this.draw();\n this.updateClipPath();\n }\n\n draw() {\n // Clear previous elements\n while (this.group.firstChild) {\n this.group.removeChild(this.group.firstChild);\n }\n this.anchors = [];\n\n // Ensure defs exists for grid pattern\n let defs = svg.querySelector('defs');\n if (!defs) {\n defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\n svg.appendChild(defs);\n }\n\n // Determine fill based on fillStyle\n let fillValue = \"transparent\";\n if (this.fillStyle === 'solid') {\n fillValue = this.fillColor;\n } else if (this.fillStyle === 'grid') {\n // Create or update a grid pattern unique to this frame\n const patternId = `frame-grid-${this.shapeID}`;\n let pattern = defs.querySelector(`#${patternId}`);\n if (!pattern) {\n pattern = document.createElementNS('http://www.w3.org/2000/svg', 'pattern');\n pattern.setAttribute('id', patternId);\n pattern.setAttribute('patternUnits', 'userSpaceOnUse');\n defs.appendChild(pattern);\n }\n // Update pattern attributes\n pattern.setAttribute('x', this.x);\n pattern.setAttribute('y', this.y);\n pattern.setAttribute('width', this.gridSize);\n pattern.setAttribute('height', this.gridSize);\n // Clear and rebuild pattern content\n while (pattern.firstChild) pattern.removeChild(pattern.firstChild);\n // Background fill\n const bgRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n bgRect.setAttribute('width', this.gridSize);\n bgRect.setAttribute('height', this.gridSize);\n bgRect.setAttribute('fill', this.fillColor);\n pattern.appendChild(bgRect);\n // Grid lines\n const gridPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n gridPath.setAttribute('d', `M ${this.gridSize} 0 L 0 0 0 ${this.gridSize}`);\n gridPath.setAttribute('fill', 'none');\n gridPath.setAttribute('stroke', this.gridColor);\n gridPath.setAttribute('stroke-width', '0.5');\n pattern.appendChild(gridPath);\n fillValue = `url(#${patternId})`;\n }\n\n // Create the frame rectangle\n const frameRect = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n frameRect.setAttribute(\"x\", this.x);\n frameRect.setAttribute(\"y\", this.y);\n frameRect.setAttribute(\"width\", this.width);\n frameRect.setAttribute(\"height\", this.height);\n frameRect.setAttribute(\"stroke\", this.options.stroke);\n frameRect.setAttribute(\"stroke-width\", this.options.strokeWidth);\n frameRect.setAttribute(\"fill\", fillValue);\n frameRect.setAttribute(\"opacity\", this.options.opacity);\n frameRect.setAttribute(\"stroke-dasharray\", \"5,5\");\n frameRect.classList.add(\"frame-rect\");\n\n // Apply rotation\n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n frameRect.setAttribute(\"transform\", `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n }\n\n this.element = frameRect;\n this.group.appendChild(this.element);\n\n // Add label\n this.addFrameLabel();\n\n // Re-attach frame image if present\n if (this._frameImageURL) {\n this.setImageFromURL(this._frameImageURL, this._frameImageFit || 'cover');\n }\n\n // Add selection anchors if selected\n if (this.isSelected) {\n this.addAnchors();\n }\n\n // Update clip path\n this.updateClipPath();\n }\n\n updateAttachedArrows() {\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.forEach(shape => {\n if (shape.shapeName === 'arrow') {\n let needsUpdate = false;\n \n // Check if arrow is attached to this frame\n if (shape.attachedToStart && shape.attachedToStart.shape === this) {\n needsUpdate = true;\n }\n if (shape.attachedToEnd && shape.attachedToEnd.shape === this) {\n needsUpdate = true;\n }\n \n if (needsUpdate) {\n shape.updateAttachments();\n }\n }\n });\n }\n }\n\n updateClipPath() {\n // Update the clipping rectangle to match frame dimensions\n this.clipRect.setAttribute(\"x\", this.x);\n this.clipRect.setAttribute(\"y\", this.y);\n this.clipRect.setAttribute(\"width\", this.width);\n this.clipRect.setAttribute(\"height\", this.height);\n \n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n this.clipRect.setAttribute(\"transform\", `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n } else {\n this.clipRect.removeAttribute(\"transform\");\n }\n }\n\n addShapeToFrame(shape) {\n if (shape && !this.containedShapes.includes(shape)) {\n const oldFrame = shape.parentFrame;\n\n // Remove from other frames first\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.forEach(otherFrame => {\n if (otherFrame.shapeName === 'frame' && otherFrame !== this) {\n otherFrame.removeShapeFromFrame(shape);\n }\n });\n }\n\n this.containedShapes.push(shape);\n shape.parentFrame = this;\n\n // Only move to clipped group if not currently being dragged\n const el = shape.group || shape.element;\n if (el && el.parentNode && !shape.isDraggedOutTemporarily) {\n el.parentNode.removeChild(el);\n this.clipGroup.appendChild(el);\n }\n\n // For sub-frames, also move their clipGroup into our clipGroup\n if (shape.shapeName === 'frame' && shape.clipGroup) {\n if (shape.clipGroup.parentNode) {\n shape.clipGroup.parentNode.removeChild(shape.clipGroup);\n }\n this.clipGroup.appendChild(shape.clipGroup);\n }\n }\n}\n\n removeShapeFromFrame(shape) {\n const index = this.containedShapes.indexOf(shape);\n if (index > -1) {\n this.containedShapes.splice(index, 1);\n if (shape.parentFrame === this) {\n shape.parentFrame = null;\n }\n\n // Move shape's group/element back to main SVG if it's in the clipped group\n const el = shape.group || shape.element;\n if (el && el.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(el);\n svg.appendChild(el);\n }\n\n // For sub-frames, also move their clipGroup back to main SVG\n if (shape.shapeName === 'frame' && shape.clipGroup && shape.clipGroup.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(shape.clipGroup);\n svg.appendChild(shape.clipGroup);\n }\n\n delete shape.isDraggedOutTemporarily;\n }\n}\n\n // Check if a point is inside the frame bounds\n isPointInFrame(x, y) {\n // Simple bounding box check (can be enhanced for rotation)\n return x >= this.x && x <= this.x + this.width &&\n y >= this.y && y <= this.y + this.height;\n }\n\n // Check if a shape overlaps with this frame\n isShapeInFrame(shape) {\n if (!shape || shape === this) return false;\n \n const shapeX = shape.x || 0;\n const shapeY = shape.y || 0;\n const shapeWidth = shape.width || 0;\n const shapeHeight = shape.height || 0;\n \n // Check if the center of the shape is inside the frame (for better UX)\n const shapeCenterX = shapeX + shapeWidth / 2;\n const shapeCenterY = shapeY + shapeHeight / 2;\n \n return shapeCenterX >= this.x && shapeCenterX <= this.x + this.width &&\n shapeCenterY >= this.y && shapeCenterY <= this.y + this.height;\n}\n\nupdateContainedShapes(applyClipping = true) {\n // Check all shapes to see if they should be in this frame\n if (typeof shapes === 'undefined' || !Array.isArray(shapes)) return;\n shapes.forEach(shape => {\n if (shape !== this) {\n // Skip frames that are larger than or equal to this frame (prevent parent containing child loops)\n if (shape.shapeName === 'frame') {\n const shapeArea = (shape.width || 0) * (shape.height || 0);\n const thisArea = (this.width || 0) * (this.height || 0);\n if (shapeArea >= thisArea) return;\n }\n const isInFrame = this.isShapeInFrame(shape);\n const isAlreadyContained = this.containedShapes.includes(shape);\n\n if (isInFrame && !isAlreadyContained) {\n this.addShapeToFrame(shape);\n // Don't apply clipping if we're not supposed to\n if (!applyClipping) {\n const el = shape.group || shape.element;\n if (el && el.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(el);\n svg.appendChild(el);\n shape.isDraggedOutTemporarily = true;\n }\n }\n } else if (!isInFrame && isAlreadyContained) {\n this.removeShapeFromFrame(shape);\n }\n }\n });\n \n // Update clip path\n this.updateClipPath();\n}\n\nhighlightFrame() {\n if (this.element) {\n this.element.setAttribute('stroke', '#5B57D1');\n this.element.setAttribute('stroke-width', '3');\n this.element.setAttribute('opacity', '0.7');\n }\n}\n\n// Remove frame highlight\nremoveHighlight() {\n if (this.element) {\n this.element.setAttribute('stroke', this.options.stroke);\n this.element.setAttribute('stroke-width', this.options.strokeWidth);\n this.element.setAttribute('opacity', this.options.opacity);\n }\n}\n \n\nmove(dx, dy) {\n this.x += dx;\n this.y += dy;\n\n // Move all contained shapes with the frame\n this.containedShapes.forEach(shape => {\n if (shape) {\n // Mark shape as being moved by frame to prevent frame containment updates\n shape.isBeingMovedByFrame = true;\n\n // Use shape's own move method for proper handling of all shape types\n if (typeof shape.move === 'function') {\n shape.move(dx, dy);\n } else {\n shape.x += dx;\n shape.y += dy;\n }\n\n // Force redraw for shapes whose move() doesn't auto-redraw\n if (typeof shape.draw === 'function') {\n shape.draw();\n }\n\n // Update bounding box for freehand strokes\n if (typeof shape.updateBoundingBox === 'function') {\n shape.updateBoundingBox();\n }\n\n // Remove the flag after movement\n delete shape.isBeingMovedByFrame;\n }\n });\n\n // Update arrows attached to this frame\n this.updateAttachedArrows();\n\n this.draw();\n this.updateClipPath();\n}\n\n handleResizeLegacy(anchorIndex, currentPos, startPos, initialFrame) {\n // Legacy version - superseded by the handleResize below with contained shapes scaling\n const dx = currentPos.x - startPos.x;\n const dy = currentPos.y - startPos.y;\n\n switch (anchorIndex) {\n case 0: this.x = initialFrame.x + dx; this.y = initialFrame.y + dy; this.width = Math.max(10, initialFrame.width - dx); this.height = Math.max(10, initialFrame.height - dy); break;\n case 1: this.y = initialFrame.y + dy; this.height = Math.max(10, initialFrame.height - dy); break;\n case 2: this.y = initialFrame.y + dy; this.width = Math.max(10, initialFrame.width + dx); this.height = Math.max(10, initialFrame.height - dy); break;\n case 3: this.width = Math.max(10, initialFrame.width + dx); break;\n case 4: this.width = Math.max(10, initialFrame.width + dx); this.height = Math.max(10, initialFrame.height + dy); break;\n case 5: this.height = Math.max(10, initialFrame.height + dy); break;\n case 6: this.x = initialFrame.x + dx; this.width = Math.max(10, initialFrame.width - dx); this.height = Math.max(10, initialFrame.height + dy); break;\n case 7: this.x = initialFrame.x + dx; this.width = Math.max(10, initialFrame.width - dx); break;\n }\n this.updateAttachedArrows();\n this.updateContainedShapes();\n}\n destroy() {\n const isDiagramFrame = !!this._diagramType;\n\n [...this.containedShapes].forEach(shape => {\n if (isDiagramFrame) {\n // Diagram/graph frame: destroy contained shapes with the frame\n if (typeof window.cleanupAttachments === 'function') {\n window.cleanupAttachments(shape);\n }\n const el = shape.group || shape.element;\n if (el && el.parentNode) {\n el.parentNode.removeChild(el);\n }\n if (shape.shapeName === 'frame') {\n if (shape.clipGroup && shape.clipGroup.parentNode) {\n shape.clipGroup.parentNode.removeChild(shape.clipGroup);\n }\n if (shape.clipPath && shape.clipPath.parentNode) {\n shape.clipPath.parentNode.removeChild(shape.clipPath);\n }\n }\n const idx = shapes.indexOf(shape);\n if (idx > -1) {\n shapes.splice(idx, 1);\n }\n } else {\n // Regular frame: release contained shapes back to canvas\n const el = shape.group || shape.element;\n if (el) {\n if (el.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(el);\n }\n svg.appendChild(el);\n }\n if (shape.shapeName === 'frame' && shape.clipGroup) {\n if (shape.clipGroup.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(shape.clipGroup);\n }\n svg.appendChild(shape.clipGroup);\n }\n }\n shape.parentFrame = null;\n delete shape.isBeingMovedByFrame;\n });\n this.containedShapes = [];\n\n // Remove clip path\n if (this.clipPath && this.clipPath.parentNode) {\n this.clipPath.parentNode.removeChild(this.clipPath);\n }\n\n // Remove groups (clipGroup should be empty now)\n if (this.clipGroup && this.clipGroup.parentNode) {\n this.clipGroup.parentNode.removeChild(this.clipGroup);\n }\n\n if (this.group && this.group.parentNode) {\n this.group.parentNode.removeChild(this.group);\n }\n\n const index = shapes.indexOf(this);\n if (index > -1) {\n shapes.splice(index, 1);\n }\n if (currentShape === this) {\n currentShape = null;\n }\n }\n\n addFrameLabel() {\n const labelText = document.createElementNS(\"http://www.w3.org/2000/svg\", \"text\");\n labelText.setAttribute(\"x\", this.x + 5);\n labelText.setAttribute(\"y\", this.y - 10);\n labelText.setAttribute(\"font-size\", `${16 / currentZoom}px`);\n labelText.setAttribute(\"fill\", this.options.labelColor || this.options.stroke);\n labelText.setAttribute(\"font-family\", \"lixFont\");\n labelText.textContent = this.frameName || \"Frame\";\n labelText.style.cursor = \"pointer\";\n labelText.style.userSelect = \"none\";\n \n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n labelText.setAttribute(\"transform\", `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n }\n \n // Add double-click event for renaming\n labelText.addEventListener('dblclick', (e) => {\n e.stopPropagation();\n this.startLabelEdit(labelText);\n });\n \n this.group.appendChild(labelText);\n this.labelElement = labelText;\n}\n\nstartLabelEdit(labelElement) {\n // Create a foreignObject to hold an HTML input\n const foreignObject = document.createElementNS(\"http://www.w3.org/2000/svg\", \"foreignObject\");\n foreignObject.setAttribute(\"x\", this.x + 5);\n foreignObject.setAttribute(\"y\", this.y - 20);\n foreignObject.setAttribute(\"width\", Math.max(100, this.width - 10));\n foreignObject.setAttribute(\"height\", 20);\n \n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n foreignObject.setAttribute(\"transform\", `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n }\n \n // Create input element\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.value = this.frameName || \"Frame\";\n const oldName = this.frameName; // Store old name for undo\n \n input.style.cssText = `\n position: absolute;\n width: 100%;\n height: 20px;\n border: 1px solid #5B57D1;\n background: transparent;\n color: ${this.options.stroke};\n font-family: \"lixFont\";\n font-size: ${15 / currentZoom}px;\n padding: 2px 10px;\n margin: 0;\n outline: none;\n border-radius: 2px;\n box-sizing: border-box;\n `;\n \n foreignObject.appendChild(input);\n this.group.appendChild(foreignObject);\n \n // Hide the original label\n labelElement.style.display = \"none\";\n \n // Focus and select the text\n setTimeout(() => {\n input.focus();\n input.select();\n }, 10);\n \n const finishEdit = () => {\n const newName = input.value.trim() || \"Frame\";\n \n // Track name change in undo system if it actually changed\n if (newName !== oldName) {\n pushTransformAction(this, \n { \n x: this.x, \n y: this.y, \n width: this.width, \n height: this.height, \n rotation: this.rotation,\n frameName: oldName \n },\n { \n x: this.x, \n y: this.y, \n width: this.width, \n height: this.height, \n rotation: this.rotation,\n frameName: newName \n }\n );\n }\n \n this.frameName = newName;\n \n // Remove the input\n this.group.removeChild(foreignObject);\n \n // Show and update the label\n labelElement.style.display = \"block\";\n labelElement.textContent = this.frameName;\n \n this.labelElement = labelElement;\n };\n \n // Handle input events\n input.addEventListener('blur', finishEdit);\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n finishEdit();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n // Cancel edit - restore original name\n this.group.removeChild(foreignObject);\n labelElement.style.display = \"block\";\n }\n });\n \n // Prevent the input from interfering with other interactions\n input.addEventListener('pointerdown', (e) => e.stopPropagation());\n input.addEventListener('pointermove', (e) => e.stopPropagation());\n input.addEventListener('pointerup', (e) => e.stopPropagation());\n}\n selectFrame() {\n this.isSelected = true;\n this.draw();\n this._showSidebar();\n }\n\n _showSidebar() {\n // React sidebar bridge\n if (window.__showSidebarForShape) {\n window.__showSidebarForShape('frame');\n }\n\n const sidebar = document.getElementById('frameSideBar');\n const renameInput = document.getElementById('frameRenameInput');\n const resizeBtn = document.getElementById('frameResizeToFit');\n if (!sidebar) return;\n\n sidebar.classList.remove('hidden');\n\n if (renameInput) {\n renameInput.value = this.frameName || 'Frame';\n // Replace old listener by cloning\n const newInput = renameInput.cloneNode(true);\n renameInput.parentNode.replaceChild(newInput, renameInput);\n newInput.addEventListener('input', () => {\n const val = newInput.value.trim() || 'Frame';\n this.frameName = val;\n if (this.labelElement) this.labelElement.textContent = val;\n });\n newInput.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') newInput.blur();\n });\n newInput.addEventListener('pointerdown', (e) => e.stopPropagation());\n }\n\n if (resizeBtn) {\n const newBtn = resizeBtn.cloneNode(true);\n resizeBtn.parentNode.replaceChild(newBtn, resizeBtn);\n newBtn.addEventListener('click', () => this.resizeToFit());\n }\n }\n\n resizeToFit() {\n if (this.containedShapes.length === 0) return;\n\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n\n this.containedShapes.forEach(shape => {\n if (shape.shapeName === 'arrow' || shape.shapeName === 'line') {\n [shape.startPoint, shape.endPoint].filter(Boolean).forEach(p => {\n minX = Math.min(minX, p.x);\n minY = Math.min(minY, p.y);\n maxX = Math.max(maxX, p.x);\n maxY = Math.max(maxY, p.y);\n });\n } else if (typeof shape.x === 'number' && typeof shape.y === 'number') {\n const w = shape.width || 0;\n const h = shape.height || 0;\n minX = Math.min(minX, shape.x);\n minY = Math.min(minY, shape.y);\n maxX = Math.max(maxX, shape.x + w);\n maxY = Math.max(maxY, shape.y + h);\n }\n });\n\n if (!isFinite(minX)) return;\n\n const padding = 20;\n const oldState = { x: this.x, y: this.y, width: this.width, height: this.height, rotation: this.rotation };\n\n this.x = minX - padding;\n this.y = minY - padding;\n this.width = (maxX - minX) + padding * 2;\n this.height = (maxY - minY) + padding * 2;\n\n pushTransformAction(this, oldState, { x: this.x, y: this.y, width: this.width, height: this.height, rotation: this.rotation });\n this.draw();\n this.updateClipPath();\n this.updateContainedShapes();\n }\n\n removeSelection() {\n this.anchors.forEach(anchor => {\n if (anchor.parentNode) {\n anchor.parentNode.removeChild(anchor);\n }\n });\n this.anchors = [];\n this.isSelected = false;\n this.draw();\n const sidebar = document.getElementById('frameSideBar');\n if (sidebar) sidebar.classList.add('hidden');\n }\n\n addAnchors() {\n const anchorSize = 8 / currentZoom;\n const anchorStrokeWidth = 2 / currentZoom;\n\n // Calculate anchor positions (corners + midpoints + rotation handle)\n const anchorPositions = [\n { x: this.x, y: this.y, cursor: 'nw-resize', type: 'corner' }, // Top-left\n { x: this.x + this.width / 2, y: this.y, cursor: 'n-resize', type: 'edge' }, // Top-middle\n { x: this.x + this.width, y: this.y, cursor: 'ne-resize', type: 'corner' }, // Top-right\n { x: this.x + this.width, y: this.y + this.height / 2, cursor: 'e-resize', type: 'edge' }, // Right-middle\n { x: this.x + this.width, y: this.y + this.height, cursor: 'se-resize', type: 'corner' }, // Bottom-right\n { x: this.x + this.width / 2, y: this.y + this.height, cursor: 's-resize', type: 'edge' }, // Bottom-middle\n { x: this.x, y: this.y + this.height, cursor: 'sw-resize', type: 'corner' }, // Bottom-left\n { x: this.x, y: this.y + this.height / 2, cursor: 'w-resize', type: 'edge' }, // Left-middle\n ];\n\n // Add rotation handle\n const rotationHandleDistance = 30 / currentZoom;\n const rotationHandle = {\n x: this.x + this.width / 2,\n y: this.y - rotationHandleDistance,\n cursor: 'grab',\n type: 'rotation'\n };\n anchorPositions.push(rotationHandle);\n\n // Create selection outline first (behind anchors)\n const outline = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n outline.setAttribute('x', this.x);\n outline.setAttribute('y', this.y);\n outline.setAttribute('width', this.width);\n outline.setAttribute('height', this.height);\n outline.setAttribute('fill', 'none');\n outline.setAttribute('stroke', '#5B57D1');\n outline.setAttribute('stroke-width', 1.5);\n outline.setAttribute('vector-effect', 'non-scaling-stroke');\n outline.setAttribute('stroke-dasharray', '4 2');\n outline.setAttribute('style', 'pointer-events: none;');\n\n // Apply rotation to outline if needed\n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n outline.setAttribute('transform', `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n }\n\n this.group.appendChild(outline);\n this.selectionOutline = outline;\n\n anchorPositions.forEach((position, index) => {\n let anchor;\n \n if (position.type === 'rotation') {\n // Create rotation handle (circle)\n anchor = document.createElementNS(\"http://www.w3.org/2000/svg\", \"circle\");\n anchor.setAttribute(\"cx\", position.x);\n anchor.setAttribute(\"cy\", position.y);\n anchor.setAttribute(\"r\", anchorSize);\n anchor.setAttribute(\"fill\", \"#121212\"); \n anchor.setAttribute(\"stroke\", \"#5B57D1\"); \n anchor.setAttribute(\"stroke-width\", anchorStrokeWidth);\n anchor.setAttribute(\"vector-effect\", \"non-scaling-stroke\");\n\n // Add rotation line\n const rotationLine = document.createElementNS(\"http://www.w3.org/2000/svg\", \"line\");\n rotationLine.setAttribute(\"x1\", this.x + this.width / 2);\n rotationLine.setAttribute(\"y1\", this.y);\n rotationLine.setAttribute(\"x2\", position.x);\n rotationLine.setAttribute(\"y2\", position.y);\n rotationLine.setAttribute(\"stroke\", \"#5B57D1\"); \n rotationLine.setAttribute(\"stroke-width\", anchorStrokeWidth);\n rotationLine.setAttribute(\"vector-effect\", \"non-scaling-stroke\");\n\n // Apply rotation to rotation line if needed\n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n rotationLine.setAttribute('transform', `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n }\n \n this.group.appendChild(rotationLine);\n registerRotationAnchor(anchor, {\n radius: 8,\n edgeY: this.y,\n line: rotationLine,\n lineEnd: '2',\n });\n } else {\n // Create resize handle (rectangle)\n anchor = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n anchor.setAttribute(\"x\", position.x - anchorSize / 2);\n anchor.setAttribute(\"y\", position.y - anchorSize / 2);\n anchor.setAttribute(\"width\", anchorSize);\n anchor.setAttribute(\"height\", anchorSize);\n anchor.setAttribute(\"fill\", \"#121212\"); \n anchor.setAttribute(\"stroke\", \"#5B57D1\"); \n anchor.setAttribute(\"stroke-width\", anchorStrokeWidth);\n anchor.setAttribute(\"vector-effect\", \"non-scaling-stroke\");\n }\n\n // Apply rotation to anchor if needed\n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n anchor.setAttribute('transform', `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n }\n\n anchor.style.cursor = position.cursor;\n anchor.addEventListener('pointerdown', (e) => this.startAnchorDrag(e, index));\n \n this.anchors.push(anchor);\n this.group.appendChild(anchor);\n });\n }\n\n startAnchorDrag(e, index) {\n e.stopPropagation();\n e.preventDefault();\n\n // Store initial state for undo\n dragOldPosFrame = {\n x: this.x,\n y: this.y,\n width: this.width,\n height: this.height,\n rotation: this.rotation\n };\n\n const startMousePos = getSVGCoordsFromMouse(e);\n const initialFrame = {\n x: this.x,\n y: this.y,\n width: this.width,\n height: this.height,\n rotation: this.rotation\n };\n\n const onPointerMove = (event) => {\n const currentMousePos = getSVGCoordsFromMouse(event);\n \n if (index === 8) { // Rotation handle\n this.handleRotation(currentMousePos, initialFrame);\n } else {\n this.handleResize(index, currentMousePos, startMousePos, initialFrame);\n }\n \n this.draw();\n this.updateContainedShapes();\n };\n\n const onPointerUp = () => {\n if (dragOldPosFrame) {\n const newPos = {\n x: this.x,\n y: this.y,\n width: this.width,\n height: this.height,\n rotation: this.rotation\n };\n pushTransformAction(this, dragOldPosFrame, newPos);\n dragOldPosFrame = null;\n }\n \n svg.removeEventListener('pointermove', onPointerMove);\n svg.removeEventListener('pointerup', onPointerUp);\n svg.style.cursor = 'default';\n };\n\n svg.addEventListener('pointermove', onPointerMove);\n svg.addEventListener('pointerup', onPointerUp);\n }\n\n handleRotation(mousePos, initialFrame) {\n const centerX = initialFrame.x + initialFrame.width / 2;\n const centerY = initialFrame.y + initialFrame.height / 2;\n \n const angle = Math.atan2(mousePos.y - centerY, mousePos.x - centerX);\n const newRotation = (angle * 180 / Math.PI + 90) % 360;\n const angleDiff = newRotation - this.rotation;\n const angleRad = angleDiff * Math.PI / 180;\n const cosAngle = Math.cos(angleRad);\n const sinAngle = Math.sin(angleRad);\n \n // Store the rotation center for contained shapes\n const rotationCenter = { x: centerX, y: centerY };\n \n // Rotate all contained shapes around the frame's center\n this.containedShapes.forEach(shape => {\n if (!shape) return;\n \n // Mark shape as being moved by frame to prevent frame containment updates\n shape.isBeingMovedByFrame = true;\n \n switch (shape.shapeName) {\n case 'rectangle':\n case 'frame':\n case 'image':\n case 'icon':\n // Get shape's current center\n const shapeCenterX = shape.x + shape.width / 2;\n const shapeCenterY = shape.y + shape.height / 2;\n \n // Calculate relative position from rotation center\n const relativeX = shapeCenterX - rotationCenter.x;\n const relativeY = shapeCenterY - rotationCenter.y;\n \n // Apply rotation to get new center position\n const newCenterX = rotationCenter.x + (relativeX * cosAngle - relativeY * sinAngle);\n const newCenterY = rotationCenter.y + (relativeX * sinAngle + relativeY * cosAngle);\n \n // Update shape position\n shape.x = newCenterX - shape.width / 2;\n shape.y = newCenterY - shape.height / 2;\n shape.rotation = (shape.rotation || 0) + angleDiff;\n \n if (typeof shape.draw === 'function') {\n shape.draw();\n }\n break;\n \n case 'circle':\n // Get circle's center\n const circleCenterX = shape.x;\n const circleCenterY = shape.y;\n \n // Calculate relative position from rotation center\n const relativeCircleX = circleCenterX - rotationCenter.x;\n const relativeCircleY = circleCenterY - rotationCenter.y;\n \n // Apply rotation\n const newCircleCenterX = rotationCenter.x + (relativeCircleX * cosAngle - relativeCircleY * sinAngle);\n const newCircleCenterY = rotationCenter.y + (relativeCircleX * sinAngle + relativeCircleY * cosAngle);\n \n shape.x = newCircleCenterX;\n shape.y = newCircleCenterY;\n shape.rotation = (shape.rotation || 0) + angleDiff;\n \n if (typeof shape.draw === 'function') {\n shape.draw();\n }\n break;\n \n case 'line':\n case 'arrow':\n // Calculate relative positions for start and end points\n const relativeStartX = shape.startPoint.x - rotationCenter.x;\n const relativeStartY = shape.startPoint.y - rotationCenter.y;\n const relativeEndX = shape.endPoint.x - rotationCenter.x;\n const relativeEndY = shape.endPoint.y - rotationCenter.y;\n \n // Apply rotation to both points\n const newStartX = rotationCenter.x + (relativeStartX * cosAngle - relativeStartY * sinAngle);\n const newStartY = rotationCenter.y + (relativeStartX * sinAngle + relativeStartY * cosAngle);\n const newEndX = rotationCenter.x + (relativeEndX * cosAngle - relativeEndY * sinAngle);\n const newEndY = rotationCenter.y + (relativeEndX * sinAngle + relativeEndY * cosAngle);\n \n shape.startPoint.x = newStartX;\n shape.startPoint.y = newStartY;\n shape.endPoint.x = newEndX;\n shape.endPoint.y = newEndY;\n \n if (shape.shapeName === 'arrow' && shape.arrowCurved && typeof shape.initializeCurveControlPoints === 'function') {\n shape.initializeCurveControlPoints();\n }\n if (typeof shape.draw === 'function') {\n shape.draw();\n }\n break;\n \n case 'text':\n case 'code':\n // Get text/code bounds for center calculation\n const textOrCodeEl = shape.group ? (shape.group.querySelector('text') || shape.group.querySelector('foreignObject')) : null;\n if (textOrCodeEl) {\n const bbox = textOrCodeEl.getBBox();\n const transform = shape.group.transform.baseVal.consolidate();\n const matrix = transform ? transform.matrix : { e: 0, f: 0 };\n\n const textCenterX = bbox.x + matrix.e + bbox.width / 2;\n const textCenterY = bbox.y + matrix.f + bbox.height / 2;\n\n // Calculate relative position\n const relativeTextX = textCenterX - rotationCenter.x;\n const relativeTextY = textCenterY - rotationCenter.y;\n\n // Apply rotation\n const newTextCenterX = rotationCenter.x + (relativeTextX * cosAngle - relativeTextY * sinAngle);\n const newTextCenterY = rotationCenter.y + (relativeTextX * sinAngle + relativeTextY * cosAngle);\n\n // Update position\n const newTransformX = newTextCenterX - bbox.width / 2;\n const newTransformY = newTextCenterY - bbox.height / 2;\n const newShapeRotation = (shape.rotation || 0) + angleDiff;\n\n const textCenterRelativeX = bbox.width / 2;\n const textCenterRelativeY = bbox.height / 2;\n\n shape.group.setAttribute('transform',\n `translate(${newTransformX}, ${newTransformY}) rotate(${newShapeRotation}, ${textCenterRelativeX}, ${textCenterRelativeY})`\n );\n\n shape.x = newTransformX;\n shape.y = newTransformY;\n shape.rotation = newShapeRotation;\n }\n break;\n \n case 'freehandStroke':\n if (shape.points && Array.isArray(shape.points)) {\n // Rotate each point in the stroke\n shape.points = shape.points.map(point => {\n if (!Array.isArray(point) || point.length < 2) return point;\n \n const relativePointX = point[0] - rotationCenter.x;\n const relativePointY = point[1] - rotationCenter.y;\n \n const newPointX = rotationCenter.x + (relativePointX * cosAngle - relativePointY * sinAngle);\n const newPointY = rotationCenter.y + (relativePointX * sinAngle + relativePointY * cosAngle);\n \n return [newPointX, newPointY, point[2] || 0.5];\n });\n \n if (typeof shape.updateBoundingBox === 'function') {\n shape.updateBoundingBox();\n }\n if (typeof shape.draw === 'function') {\n shape.draw();\n }\n }\n break;\n }\n \n // Update arrows attached to the contained shape\n if (typeof shape.updateAttachedArrows === 'function') {\n shape.updateAttachedArrows();\n }\n \n // Remove the flag after rotation\n delete shape.isBeingMovedByFrame;\n });\n \n // Update the frame's rotation\n this.rotation = newRotation;\n \n // Update arrows attached to this frame\n this.updateAttachedArrows();\n }\n\n handleResize(anchorIndex, currentPos, startPos, initialFrame) {\n const rawDx = currentPos.x - startPos.x;\n const rawDy = currentPos.y - startPos.y;\n\n // Rotate delta to local (unrotated) space when frame is rotated\n const rad = (this.rotation || 0) * Math.PI / 180;\n const cosR = Math.cos(rad);\n const sinR = Math.sin(rad);\n const dx = rawDx * cosR + rawDy * sinR;\n const dy = -rawDx * sinR + rawDy * cosR;\n\n // Store old frame for scale calculation\n const oldX = this.x, oldY = this.y, oldW = this.width, oldH = this.height;\n\n // Compute new dimensions using local-space deltas\n let newW, newH;\n // Fixed corner relative to initial frame origin: (fixRelX, fixRelY)\n let fixRelX, fixRelY;\n\n switch (anchorIndex) {\n case 0: // Top-left\n newW = Math.max(10, initialFrame.width - dx);\n newH = Math.max(10, initialFrame.height - dy);\n fixRelX = initialFrame.width; fixRelY = initialFrame.height;\n break;\n case 1: // Top-middle\n newW = initialFrame.width;\n newH = Math.max(10, initialFrame.height - dy);\n fixRelX = 0; fixRelY = initialFrame.height;\n break;\n case 2: // Top-right\n newW = Math.max(10, initialFrame.width + dx);\n newH = Math.max(10, initialFrame.height - dy);\n fixRelX = 0; fixRelY = initialFrame.height;\n break;\n case 3: // Right-middle\n newW = Math.max(10, initialFrame.width + dx);\n newH = initialFrame.height;\n fixRelX = 0; fixRelY = 0;\n break;\n case 4: // Bottom-right\n newW = Math.max(10, initialFrame.width + dx);\n newH = Math.max(10, initialFrame.height + dy);\n fixRelX = 0; fixRelY = 0;\n break;\n case 5: // Bottom-middle\n newW = initialFrame.width;\n newH = Math.max(10, initialFrame.height + dy);\n fixRelX = 0; fixRelY = 0;\n break;\n case 6: // Bottom-left\n newW = Math.max(10, initialFrame.width - dx);\n newH = Math.max(10, initialFrame.height + dy);\n fixRelX = initialFrame.width; fixRelY = 0;\n break;\n case 7: // Left-middle\n newW = Math.max(10, initialFrame.width - dx);\n newH = initialFrame.height;\n fixRelX = initialFrame.width; fixRelY = 0;\n break;\n }\n\n // Compute new position using fixed-corner constraint\n if (this.rotation && this.rotation !== 0) {\n // Compute rotated world position of the fixed corner in the initial frame\n const iCX = initialFrame.x + initialFrame.width / 2;\n const iCY = initialFrame.y + initialFrame.height / 2;\n const odx = (initialFrame.x + fixRelX) - iCX;\n const ody = (initialFrame.y + fixRelY) - iCY;\n const fixedWorldX = iCX + odx * cosR - ody * sinR;\n const fixedWorldY = iCY + odx * sinR + ody * cosR;\n\n // Where the fixed corner sits in new rect (relative to new origin)\n const fixNewRelX = (fixRelX === 0) ? 0 : newW;\n const fixNewRelY = (fixRelY === 0) ? 0 : newH;\n\n // Solve for new origin\n const ncx = newW / 2;\n const ncy = newH / 2;\n const ndx = fixNewRelX - ncx;\n const ndy = fixNewRelY - ncy;\n const rotX = ncx + ndx * cosR - ndy * sinR;\n const rotY = ncy + ndx * sinR + ndy * cosR;\n\n this.x = fixedWorldX - rotX;\n this.y = fixedWorldY - rotY;\n } else {\n // No rotation - use simple axis-aligned position calculation\n switch (anchorIndex) {\n case 0: this.x = initialFrame.x + (initialFrame.width - newW); this.y = initialFrame.y + (initialFrame.height - newH); break;\n case 1: this.y = initialFrame.y + (initialFrame.height - newH); break;\n case 2: this.y = initialFrame.y + (initialFrame.height - newH); break;\n case 3: break;\n case 4: break;\n case 5: break;\n case 6: this.x = initialFrame.x + (initialFrame.width - newW); break;\n case 7: this.x = initialFrame.x + (initialFrame.width - newW); break;\n }\n }\n\n this.width = newW;\n this.height = newH;\n\n // Scale contained shapes proportionally so nothing falls out\n if (oldW > 0 && oldH > 0) {\n const scaleX = this.width / oldW;\n const scaleY = this.height / oldH;\n\n if (Math.abs(scaleX - 1) > 0.001 || Math.abs(scaleY - 1) > 0.001) {\n this.containedShapes.forEach(shape => {\n if (!shape) return;\n shape.isBeingMovedByFrame = true;\n\n switch (shape.shapeName) {\n case 'rectangle':\n case 'image':\n case 'icon':\n case 'code': {\n const relX = (shape.x - oldX) / oldW;\n const relY = (shape.y - oldY) / oldH;\n const relW = shape.width / oldW;\n const relH = shape.height / oldH;\n shape.x = this.x + relX * this.width;\n shape.y = this.y + relY * this.height;\n shape.width = relW * this.width;\n shape.height = relH * this.height;\n if (typeof shape.draw === 'function') shape.draw();\n break;\n }\n case 'circle': {\n const relCX = (shape.x - oldX) / oldW;\n const relCY = (shape.y - oldY) / oldH;\n shape.x = this.x + relCX * this.width;\n shape.y = this.y + relCY * this.height;\n shape.rx = (shape.rx / oldW) * this.width;\n shape.ry = (shape.ry / oldH) * this.height;\n shape.width = shape.rx * 2;\n shape.height = shape.ry * 2;\n if (typeof shape.draw === 'function') shape.draw();\n break;\n }\n case 'arrow':\n case 'line': {\n const relSX = (shape.startPoint.x - oldX) / oldW;\n const relSY = (shape.startPoint.y - oldY) / oldH;\n const relEX = (shape.endPoint.x - oldX) / oldW;\n const relEY = (shape.endPoint.y - oldY) / oldH;\n shape.startPoint.x = this.x + relSX * this.width;\n shape.startPoint.y = this.y + relSY * this.height;\n shape.endPoint.x = this.x + relEX * this.width;\n shape.endPoint.y = this.y + relEY * this.height;\n if (shape.controlPoint1) {\n const relC1X = (shape.controlPoint1.x - oldX) / oldW;\n const relC1Y = (shape.controlPoint1.y - oldY) / oldH;\n shape.controlPoint1.x = this.x + relC1X * this.width;\n shape.controlPoint1.y = this.y + relC1Y * this.height;\n }\n if (shape.controlPoint2) {\n const relC2X = (shape.controlPoint2.x - oldX) / oldW;\n const relC2Y = (shape.controlPoint2.y - oldY) / oldH;\n shape.controlPoint2.x = this.x + relC2X * this.width;\n shape.controlPoint2.y = this.y + relC2Y * this.height;\n }\n if (typeof shape.draw === 'function') shape.draw();\n break;\n }\n case 'text': {\n const tx = shape.x || 0;\n const ty = shape.y || 0;\n const relTX = (tx - oldX) / oldW;\n const relTY = (ty - oldY) / oldH;\n shape.x = this.x + relTX * this.width;\n shape.y = this.y + relTY * this.height;\n break;\n }\n case 'freehandStroke': {\n // Pie sectors are editable closed freehand polygons.\n // Scale their source points with the frame so their\n // geometry stays attached instead of being clipped\n // at its previous canvas coordinates.\n if (Array.isArray(shape.points)) {\n shape.points = shape.points.map(point => {\n if (!Array.isArray(point) || point.length < 2) return point;\n const relPX = (point[0] - oldX) / oldW;\n const relPY = (point[1] - oldY) / oldH;\n return [\n this.x + relPX * this.width,\n this.y + relPY * this.height,\n point[2] || 0.5\n ];\n });\n shape._moveOffsetX = 0;\n shape._moveOffsetY = 0;\n if (typeof shape.draw === 'function') shape.draw();\n }\n break;\n }\n }\n\n if (typeof shape.updateAttachedArrows === 'function') {\n shape.updateAttachedArrows();\n }\n delete shape.isBeingMovedByFrame;\n });\n }\n }\n\n // Update contained shapes visibility\n this.updateContainedShapes();\n }\n \n temporarilyRemoveFromFrame(shape) {\n if (shape && shape.parentFrame === this) {\n // Move shape back to main SVG temporarily (without removing from containedShapes array)\n const el = shape.group || shape.element;\n if (el && el.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(el);\n svg.appendChild(el);\n }\n shape.isDraggedOutTemporarily = true;\n }\n}\n\n// Add a method to restore clipping for a shape after drag\nrestoreToFrame(shape) {\n if (shape && shape.parentFrame === this && shape.isDraggedOutTemporarily) {\n // Move shape back to clipped group\n const el = shape.group || shape.element;\n if (el && el.parentNode === svg) {\n svg.removeChild(el);\n this.clipGroup.appendChild(el);\n }\n delete shape.isDraggedOutTemporarily;\n }\n}\n\n\n contains(viewBoxX, viewBoxY) {\n // Simple point-in-rectangle test (without rotation for now)\n return viewBoxX >= this.x && viewBoxX <= this.x + this.width &&\n viewBoxY >= this.y && viewBoxY <= this.y + this.height;\n }\n\n // Arrow attachment support (similar to other shapes)\n getAttachmentPoint(point, tolerance = 20) {\n const rect = {\n left: this.x,\n right: this.x + this.width,\n top: this.y,\n bottom: this.y + this.height\n };\n\n const distances = {\n top: Math.abs(point.y - rect.top),\n bottom: Math.abs(point.y - rect.bottom),\n left: Math.abs(point.x - rect.left),\n right: Math.abs(point.x - rect.right)\n };\n\n let closestSide = null;\n let minDistance = tolerance;\n\n for (let side in distances) {\n if (distances[side] < minDistance &&\n ((side === 'top' || side === 'bottom') && point.x >= rect.left && point.x <= rect.right) ||\n ((side === 'left' || side === 'right') && point.y >= rect.top && point.y <= rect.bottom)) {\n minDistance = distances[side];\n closestSide = side;\n }\n }\n\n if (closestSide) {\n let attachPoint;\n const offset = { x: 0, y: 0 };\n\n switch (closestSide) {\n case 'top':\n attachPoint = { x: point.x, y: rect.top };\n offset.x = point.x - (rect.left + this.width / 2);\n break;\n case 'bottom':\n attachPoint = { x: point.x, y: rect.bottom };\n offset.x = point.x - (rect.left + this.width / 2);\n break;\n case 'left':\n attachPoint = { x: rect.left, y: point.y };\n offset.y = point.y - (rect.top + this.height / 2);\n break;\n case 'right':\n attachPoint = { x: rect.right, y: point.y };\n offset.y = point.y - (rect.top + this.height / 2);\n break;\n }\n\n return { point: attachPoint, side: closestSide, offset, shape: this };\n }\n\n return null;\n }\n\n updateStyle(newOptions) {\n Object.keys(newOptions).forEach(key => newOptions[key] === undefined && delete newOptions[key]);\n this.options = { ...this.options, ...newOptions };\n this.draw();\n }\n\n destroy() {\n const isDiagramFrame = !!this._diagramType;\n\n [...this.containedShapes].forEach(shape => {\n if (isDiagramFrame) {\n // Diagram/graph frame: destroy contained shapes with the frame\n if (typeof window.cleanupAttachments === 'function') {\n window.cleanupAttachments(shape);\n }\n const el = shape.group || shape.element;\n if (el && el.parentNode) {\n el.parentNode.removeChild(el);\n }\n if (shape.shapeName === 'frame') {\n if (shape.clipGroup && shape.clipGroup.parentNode) {\n shape.clipGroup.parentNode.removeChild(shape.clipGroup);\n }\n if (shape.clipPath && shape.clipPath.parentNode) {\n shape.clipPath.parentNode.removeChild(shape.clipPath);\n }\n }\n const idx = shapes.indexOf(shape);\n if (idx > -1) {\n shapes.splice(idx, 1);\n }\n } else {\n // Regular frame: release contained shapes back to canvas\n const el = shape.group || shape.element;\n if (el) {\n if (el.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(el);\n }\n svg.appendChild(el);\n }\n if (shape.shapeName === 'frame' && shape.clipGroup) {\n if (shape.clipGroup.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(shape.clipGroup);\n }\n svg.appendChild(shape.clipGroup);\n }\n }\n shape.parentFrame = null;\n delete shape.isBeingMovedByFrame;\n });\n this.containedShapes = [];\n\n // Remove clip path\n if (this.clipPath && this.clipPath.parentNode) {\n this.clipPath.parentNode.removeChild(this.clipPath);\n }\n\n // Remove groups (clipGroup should be empty now)\n if (this.clipGroup && this.clipGroup.parentNode) {\n this.clipGroup.parentNode.removeChild(this.clipGroup);\n }\n\n if (this.group && this.group.parentNode) {\n this.group.parentNode.removeChild(this.group);\n }\n\n const index = shapes.indexOf(this);\n if (index > -1) {\n shapes.splice(index, 1);\n }\n if (currentShape === this) {\n currentShape = null;\n }\n }\n\n /**\n * Set a background image for this frame from a URL.\n * The image will fit/cover the frame dimensions.\n * @param {string} url - Image URL\n * @param {string} fit - 'cover' (default) | 'contain' | 'fill'\n */\n setImageFromURL(url, fit = 'cover') {\n if (!url) {\n // Remove existing frame image\n if (this._frameImage && this._frameImage.parentNode) {\n this._frameImage.parentNode.removeChild(this._frameImage);\n this._frameImage = null;\n }\n this._frameImageURL = null;\n return;\n }\n\n this._frameImageURL = url;\n this._frameImageFit = fit;\n\n if (!this._frameImage) {\n this._frameImage = document.createElementNS('http://www.w3.org/2000/svg', 'image');\n this._frameImage.setAttribute('pointer-events', 'none');\n }\n // Always update preserveAspectRatio when fit changes\n this._frameImage.setAttribute('preserveAspectRatio',\n fit === 'cover' ? 'xMidYMid slice' :\n fit === 'contain' ? 'xMidYMid meet' :\n fit === 'center' ? 'xMidYMid meet' : 'none'\n );\n\n this._frameImage.setAttribute('href', url);\n this._frameImage.setAttribute('x', this.x);\n this._frameImage.setAttribute('y', this.y);\n this._frameImage.setAttribute('width', this.width);\n this._frameImage.setAttribute('height', this.height);\n\n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n this._frameImage.setAttribute('transform', `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n }\n\n // Insert image right after the frame rect (below contained shapes)\n if (this._frameImage.parentNode === this.group) {\n this.group.removeChild(this._frameImage);\n }\n if (this.element && this.element.nextSibling) {\n this.group.insertBefore(this._frameImage, this.element.nextSibling);\n } else {\n this.group.appendChild(this._frameImage);\n }\n }\n\n /**\n * Update frame image position/size (called during move/resize)\n */\n _updateFrameImage() {\n if (!this._frameImage) return;\n this._frameImage.setAttribute('x', this.x);\n this._frameImage.setAttribute('y', this.y);\n this._frameImage.setAttribute('width', this.width);\n this._frameImage.setAttribute('height', this.height);\n\n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n this._frameImage.setAttribute('transform', `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n } else {\n this._frameImage.removeAttribute('transform');\n }\n }\n}\n\nexport { Frame };\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,4 +1,7 @@
1
1
  "use client";
2
+ import {
3
+ registerRotationAnchor
4
+ } from "./chunk-PAKA6HUX.js";
2
5
  import {
3
6
  calculateSnap,
4
7
  cleanupAttachments,
@@ -500,6 +503,12 @@ var MultiSelection = class {
500
503
  this.rotationLine.setAttribute("style", "pointer-events: none;");
501
504
  this.group.appendChild(this.rotationLine);
502
505
  this.group.appendChild(this.rotationAnchor);
506
+ registerRotationAnchor(this.rotationAnchor, {
507
+ radius: 8,
508
+ edgeY: y,
509
+ line: this.rotationLine,
510
+ lineEnd: "1"
511
+ });
503
512
  }
504
513
  removeControls() {
505
514
  if (this.group && this.group.parentNode) {
@@ -1659,4 +1668,4 @@ export {
1659
1668
  handleMultiSelectionMouseMove,
1660
1669
  handleMultiSelectionMouseUp
1661
1670
  };
1662
- //# sourceMappingURL=chunk-FV3EPR4L.js.map
1671
+ //# sourceMappingURL=chunk-7VBI7S7T.js.map