@elixpo/lixsketch 5.5.19 → 5.5.21

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 (137) hide show
  1. package/dist/react/Circle-6POZCUZD.js +9 -0
  2. package/dist/react/{CopyPaste-JMIXWUUO.js → CopyPaste-FJN7K5LS.js} +43 -14
  3. package/dist/react/CopyPaste-FJN7K5LS.js.map +7 -0
  4. package/dist/react/{EventDispatcher-H5EA4KZN.js → EventDispatcher-O7HCQQNM.js} +14 -13
  5. package/dist/react/{EventDispatcher-H5EA4KZN.js.map → EventDispatcher-O7HCQQNM.js.map} +1 -1
  6. package/dist/react/Frame-RLSMJJSK.js +11 -0
  7. package/dist/react/FreehandStroke-U6GYZOM4.js +9 -0
  8. package/dist/react/{GraphEngine-KQXHNTZQ.js → GraphEngine-MM6ALA2N.js} +105 -148
  9. package/dist/react/{GraphEngine-KQXHNTZQ.js.map → GraphEngine-MM6ALA2N.js.map} +2 -2
  10. package/dist/react/IconShape-7OPXAKLK.js +10 -0
  11. package/dist/react/ImageShape-LRNJQCF3.js +10 -0
  12. package/dist/react/Line-WWQFBNX5.js +10 -0
  13. package/dist/react/Rectangle-S7XUKWYD.js +9 -0
  14. package/dist/react/{SceneSerializer-ARTKPZVR.js → SceneSerializer-GSJR7ZHC.js} +36 -11
  15. package/dist/react/SceneSerializer-GSJR7ZHC.js.map +7 -0
  16. package/dist/react/{Selection-YJNZRBON.js → Selection-ZL3G6IAO.js} +5 -4
  17. package/dist/react/{SketchEngine-ZGYBIZG7.js → SketchEngine-BFLHJPCG.js} +25 -25
  18. package/dist/react/{UndoRedo-BZ6W4QTV.js → UndoRedo-NL7KLR5B.js} +2 -2
  19. package/dist/react/{ZoomPan-NYPDJBD5.js → ZoomPan-FAWA5OPS.js} +5 -1
  20. package/dist/react/ZoomPan-FAWA5OPS.js.map +7 -0
  21. package/dist/react/{arrowTool-LKFSZKXC.js → arrowTool-CNVGM6RX.js} +3 -3
  22. package/dist/react/{chunk-RFHMFWVR.js → chunk-2FMFOPGW.js} +5 -6
  23. package/dist/react/{chunk-RFHMFWVR.js.map → chunk-2FMFOPGW.js.map} +2 -2
  24. package/dist/react/{chunk-QYNTPZON.js → chunk-2THKDSWW.js} +9 -5
  25. package/dist/react/chunk-2THKDSWW.js.map +7 -0
  26. package/dist/react/{chunk-JOPQ27YH.js → chunk-4BLMNGTR.js} +3 -3
  27. package/dist/react/{chunk-C62SXFBL.js → chunk-4TAS67SL.js} +23 -22
  28. package/dist/react/chunk-4TAS67SL.js.map +7 -0
  29. package/dist/react/{chunk-FV3EPR4L.js → chunk-AH4PWNEB.js} +19 -11
  30. package/dist/react/chunk-AH4PWNEB.js.map +7 -0
  31. package/dist/react/{chunk-XCJOF6BM.js → chunk-FETTJLCV.js} +5 -1
  32. package/dist/react/chunk-FETTJLCV.js.map +7 -0
  33. package/dist/react/{chunk-JJTII2UQ.js → chunk-GC3KTQDA.js} +78 -15
  34. package/dist/react/chunk-GC3KTQDA.js.map +7 -0
  35. package/dist/react/{chunk-2V7G2PLX.js → chunk-GPIYXREE.js} +3 -3
  36. package/dist/react/{chunk-3VSGFP6U.js → chunk-HFQZYCHJ.js} +8 -4
  37. package/dist/react/chunk-HFQZYCHJ.js.map +7 -0
  38. package/dist/react/{chunk-C72OHQLE.js → chunk-ILGAFR56.js} +3 -3
  39. package/dist/react/{chunk-CF7AK4ES.js → chunk-KVAQPCUH.js} +26 -3
  40. package/dist/react/chunk-KVAQPCUH.js.map +7 -0
  41. package/dist/react/{chunk-WEWMB35W.js → chunk-OFGJJKPH.js} +3 -3
  42. package/dist/react/chunk-PAKA6HUX.js +59 -0
  43. package/dist/react/chunk-PAKA6HUX.js.map +7 -0
  44. package/dist/react/{chunk-HKYUJUD7.js → chunk-PXFPPO3R.js} +5 -1
  45. package/dist/react/chunk-PXFPPO3R.js.map +7 -0
  46. package/dist/react/{chunk-6G3ITAS5.js → chunk-SZD7DKYJ.js} +18 -9
  47. package/dist/react/chunk-SZD7DKYJ.js.map +7 -0
  48. package/dist/react/{chunk-N7NZLF6P.js → chunk-TKXKJNTX.js} +5 -1
  49. package/dist/react/chunk-TKXKJNTX.js.map +7 -0
  50. package/dist/react/{chunk-MYYBFZD3.js → chunk-U3TB4KRS.js} +45 -6
  51. package/dist/react/chunk-U3TB4KRS.js.map +7 -0
  52. package/dist/react/{chunk-UQBT7F4K.js → chunk-V2QTYSBK.js} +2 -2
  53. package/dist/react/{chunk-73VA5ALZ.js → chunk-XFQECTTF.js} +48 -19
  54. package/dist/react/chunk-XFQECTTF.js.map +7 -0
  55. package/dist/react/{chunk-O64N5JPO.js → chunk-YF3TK7SC.js} +2 -2
  56. package/dist/react/{circleTool-RDOIMKKV.js → circleTool-KICNRQCI.js} +4 -4
  57. package/dist/react/{codeTool-O2Z7ZXGP.js → codeTool-NCQ73R6M.js} +5 -4
  58. package/dist/react/{frameTool-Z5ZDCX6H.js → frameTool-Y6KB67DO.js} +4 -4
  59. package/dist/react/{freehandTool-AAQCTMVM.js → freehandTool-MMULHCQ7.js} +4 -4
  60. package/dist/react/{iconTool-AUHRLOO2.js → iconTool-LSW2DYGB.js} +5 -4
  61. package/dist/react/{imageTool-DRKDCPUV.js → imageTool-2DSR32RX.js} +5 -4
  62. package/dist/react/index.js +141 -66
  63. package/dist/react/index.js.map +3 -3
  64. package/dist/react/{lineTool-XLOOZE3E.js → lineTool-N5I7IGT7.js} +4 -4
  65. package/dist/react/{rectangleTool-AEYDDJCA.js → rectangleTool-YUT7ZK2E.js} +4 -4
  66. package/dist/react/{textTool-UORBAAJE.js → textTool-IQOYPELP.js} +6 -5
  67. package/package.json +1 -1
  68. package/src/core/CopyPaste.js +34 -4
  69. package/src/core/GraphEngine.js +129 -185
  70. package/src/core/SceneSerializer.js +26 -0
  71. package/src/core/ScreenSpaceControls.js +60 -0
  72. package/src/core/Selection.js +19 -11
  73. package/src/core/UndoRedo.js +47 -3
  74. package/src/core/ZoomPan.js +3 -0
  75. package/src/react/components/canvas/MultiSelectActions.jsx +4 -1
  76. package/src/react/components/sidebars/IconSidebar.jsx +14 -23
  77. package/src/react/components/sidebars/ImageSidebar.jsx +47 -24
  78. package/src/react/store/useUIStore.js +71 -14
  79. package/src/shapes/Circle.js +2 -0
  80. package/src/shapes/Frame.js +26 -2
  81. package/src/shapes/FreehandStroke.js +2 -0
  82. package/src/shapes/IconShape.js +23 -25
  83. package/src/shapes/ImageShape.js +6 -2
  84. package/src/shapes/Rectangle.js +2 -0
  85. package/src/tools/codeTool.js +3 -2
  86. package/src/tools/frameTool.js +19 -9
  87. package/src/tools/iconTool.js +63 -26
  88. package/src/tools/imageTool.js +80 -14
  89. package/src/tools/textTool.js +3 -1
  90. package/dist/react/Circle-QQMKCKFR.js +0 -8
  91. package/dist/react/CopyPaste-JMIXWUUO.js.map +0 -7
  92. package/dist/react/Frame-VADA625S.js +0 -10
  93. package/dist/react/FreehandStroke-BOWDNAVC.js +0 -8
  94. package/dist/react/IconShape-32EYI2MA.js +0 -10
  95. package/dist/react/ImageShape-MYP2DVVH.js +0 -10
  96. package/dist/react/Line-FCCF2BOB.js +0 -10
  97. package/dist/react/Rectangle-MZ6ZB6KM.js +0 -8
  98. package/dist/react/SceneSerializer-ARTKPZVR.js.map +0 -7
  99. package/dist/react/ZoomPan-NYPDJBD5.js.map +0 -7
  100. package/dist/react/chunk-3VSGFP6U.js.map +0 -7
  101. package/dist/react/chunk-6G3ITAS5.js.map +0 -7
  102. package/dist/react/chunk-73VA5ALZ.js.map +0 -7
  103. package/dist/react/chunk-C62SXFBL.js.map +0 -7
  104. package/dist/react/chunk-CF7AK4ES.js.map +0 -7
  105. package/dist/react/chunk-FV3EPR4L.js.map +0 -7
  106. package/dist/react/chunk-HKYUJUD7.js.map +0 -7
  107. package/dist/react/chunk-JJTII2UQ.js.map +0 -7
  108. package/dist/react/chunk-MYYBFZD3.js.map +0 -7
  109. package/dist/react/chunk-N7NZLF6P.js.map +0 -7
  110. package/dist/react/chunk-QYNTPZON.js.map +0 -7
  111. package/dist/react/chunk-XCJOF6BM.js.map +0 -7
  112. /package/dist/react/{Circle-QQMKCKFR.js.map → Circle-6POZCUZD.js.map} +0 -0
  113. /package/dist/react/{Frame-VADA625S.js.map → Frame-RLSMJJSK.js.map} +0 -0
  114. /package/dist/react/{FreehandStroke-BOWDNAVC.js.map → FreehandStroke-U6GYZOM4.js.map} +0 -0
  115. /package/dist/react/{IconShape-32EYI2MA.js.map → IconShape-7OPXAKLK.js.map} +0 -0
  116. /package/dist/react/{ImageShape-MYP2DVVH.js.map → ImageShape-LRNJQCF3.js.map} +0 -0
  117. /package/dist/react/{Line-FCCF2BOB.js.map → Line-WWQFBNX5.js.map} +0 -0
  118. /package/dist/react/{Rectangle-MZ6ZB6KM.js.map → Rectangle-S7XUKWYD.js.map} +0 -0
  119. /package/dist/react/{Selection-YJNZRBON.js.map → Selection-ZL3G6IAO.js.map} +0 -0
  120. /package/dist/react/{SketchEngine-ZGYBIZG7.js.map → SketchEngine-BFLHJPCG.js.map} +0 -0
  121. /package/dist/react/{UndoRedo-BZ6W4QTV.js.map → UndoRedo-NL7KLR5B.js.map} +0 -0
  122. /package/dist/react/{arrowTool-LKFSZKXC.js.map → arrowTool-CNVGM6RX.js.map} +0 -0
  123. /package/dist/react/{chunk-JOPQ27YH.js.map → chunk-4BLMNGTR.js.map} +0 -0
  124. /package/dist/react/{chunk-2V7G2PLX.js.map → chunk-GPIYXREE.js.map} +0 -0
  125. /package/dist/react/{chunk-C72OHQLE.js.map → chunk-ILGAFR56.js.map} +0 -0
  126. /package/dist/react/{chunk-WEWMB35W.js.map → chunk-OFGJJKPH.js.map} +0 -0
  127. /package/dist/react/{chunk-UQBT7F4K.js.map → chunk-V2QTYSBK.js.map} +0 -0
  128. /package/dist/react/{chunk-O64N5JPO.js.map → chunk-YF3TK7SC.js.map} +0 -0
  129. /package/dist/react/{circleTool-RDOIMKKV.js.map → circleTool-KICNRQCI.js.map} +0 -0
  130. /package/dist/react/{codeTool-O2Z7ZXGP.js.map → codeTool-NCQ73R6M.js.map} +0 -0
  131. /package/dist/react/{frameTool-Z5ZDCX6H.js.map → frameTool-Y6KB67DO.js.map} +0 -0
  132. /package/dist/react/{freehandTool-AAQCTMVM.js.map → freehandTool-MMULHCQ7.js.map} +0 -0
  133. /package/dist/react/{iconTool-AUHRLOO2.js.map → iconTool-LSW2DYGB.js.map} +0 -0
  134. /package/dist/react/{imageTool-DRKDCPUV.js.map → imageTool-2DSR32RX.js.map} +0 -0
  135. /package/dist/react/{lineTool-XLOOZE3E.js.map → lineTool-N5I7IGT7.js.map} +0 -0
  136. /package/dist/react/{rectangleTool-AEYDDJCA.js.map → rectangleTool-YUT7ZK2E.js.map} +0 -0
  137. /package/dist/react/{textTool-UORBAAJE.js.map → textTool-IQOYPELP.js.map} +0 -0
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/tools/imageTool.js"],
4
- "sourcesContent": ["/* eslint-disable */\n// Image tool event handlers - extracted from imageTool.js\nimport { pushCreateAction, pushDeleteAction, pushTransformAction, pushFrameAttachmentAction } from '../core/UndoRedo.js';\nimport { updateAttachedArrows as updateArrowsForShape, cleanupAttachments } from './arrowTool.js';\nimport { compressImage } from '../utils/imageCompressor.js';\nimport { isAllowedImage, IMAGE_ACCEPT_ATTR } from '../utils/allowedImageTypes.js';\n\n\nlet isDraggingImage = false;\nlet imageToPlace = null;\nlet imageX = 0;\nlet imageY = 0;\nlet scaleFactor = 0.2;\nlet currentImageElement = null;\n\nlet selectedImage = null;\nlet originalX, originalY, originalWidth, originalHeight;\nlet currentAnchor = null;\nlet isDragging = false;\nlet isRotatingImage = false;\nlet dragOffsetX, dragOffsetY;\nlet startRotationMouseAngle = null;\nlet startImageRotation = null;\nlet imageRotation = 0;\nlet aspect_ratio_lock = true;\nconst minImageSize = 20;\n\n// Frame attachment variables\nlet draggedShapeInitialFrameImage = null;\nlet hoveredFrameImage = null;\n\n// Per-room image size limit: 5MB total\nconst ROOM_IMAGE_LIMIT_BYTES = 5 * 1024 * 1024;\nif (!window.__roomImageBytesUsed) window.__roomImageBytesUsed = 0;\n\n\n// Convert SVG element to our ImageShape class\nfunction wrapImageElement(element) {\n const imageShape = new ImageShape(element);\n return imageShape;\n}\n\n/**\n * Async image upload pipeline:\n * 1. Show loading indicator on the image\n * 2. Compress the image adaptively\n * 3. Get a signed upload URL from the worker\n * 4. Upload compressed image to Cloudinary\n * 5. Replace the base64 href with Cloudinary URL\n * 6. Remove loading indicator\n */\nasync function uploadImageToCloudinary(imageShape) {\n const workerUrl = window.__WORKER_URL;\n const sessionId = window.__sessionID;\n if (!workerUrl || !sessionId) return;\n\n const href = imageShape.element.getAttribute('href') || '';\n if (!href.startsWith('data:')) return; // already a URL, skip\n\n imageShape.uploadStatus = 'uploading';\n imageShape.uploadAbortController = new AbortController();\n const signal = imageShape.uploadAbortController.signal;\n\n imageShape.showUploadIndicator();\n\n try {\n // Step 1: Compress\n const compressed = await compressImage(href);\n if (signal.aborted) return;\n\n // Step 2: Get signed upload params\n const signRes = await fetch(`${workerUrl}/api/images/sign`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n sessionId,\n filename: `img_${Date.now()}`,\n }),\n signal,\n });\n if (!signRes.ok) throw new Error('Failed to get upload signature');\n const signData = await signRes.json();\n if (signal.aborted) return;\n\n // Step 3: Upload to Cloudinary\n const formData = new FormData();\n formData.append('file', compressed.blob);\n formData.append('api_key', signData.apiKey);\n formData.append('timestamp', String(signData.timestamp));\n formData.append('signature', signData.signature);\n formData.append('folder', signData.folder);\n formData.append('public_id', signData.publicId);\n\n const uploadRes = await fetch(\n `https://api.cloudinary.com/v1_1/${signData.cloudName}/image/upload`,\n { method: 'POST', body: formData, signal }\n );\n if (!uploadRes.ok) throw new Error('Cloudinary upload failed');\n const uploadData = await uploadRes.json();\n if (signal.aborted) return;\n\n // Step 4: Replace base64 with Cloudinary URL\n const cloudUrl = uploadData.secure_url || uploadData.url;\n imageShape.element.setAttribute('href', cloudUrl);\n imageShape.element.setAttribute('data-href', cloudUrl);\n imageShape.element.setAttribute('data-cloudinary-id', uploadData.public_id);\n\n // Update file size tracking with actual compressed size\n const oldSize = imageShape.element.__fileSize || 0;\n const newSize = uploadData.bytes || compressed.compressedSize;\n imageShape.element.__fileSize = newSize;\n window.__roomImageBytesUsed = Math.max(0, (window.__roomImageBytesUsed || 0) - oldSize + newSize);\n\n imageShape.uploadStatus = 'done';\n console.log(`[ImageUpload] Uploaded to Cloudinary: ${cloudUrl} (${(newSize / 1024).toFixed(1)}KB)`);\n } catch (err) {\n if (signal.aborted) {\n console.log('[ImageUpload] Upload aborted (image deleted)');\n return;\n }\n console.warn('[ImageUpload] Upload failed:', err);\n imageShape.uploadStatus = 'failed';\n } finally {\n imageShape.removeUploadIndicator();\n imageShape.uploadAbortController = null;\n }\n}\n\ndocument.getElementById(\"importImage\")?.addEventListener('click', () => {\n console.log('Import image clicked');\n isImageToolActive = true;\n console.log('isImageToolActive set to:', isImageToolActive);\n\n // Create a file input element\n const fileInput = document.createElement('input');\n fileInput.type = 'file';\n fileInput.accept = IMAGE_ACCEPT_ATTR; // Static images only \u2014 see allowedImageTypes.js\n fileInput.style.display = 'none'; // Hide the input element\n \n // Add the input to the document temporarily\n document.body.appendChild(fileInput);\n \n let fileSelected = false;\n\n // Handle file selection\n fileInput.addEventListener('change', (event) => {\n const file = event.target.files[0];\n if (file) {\n fileSelected = true;\n handleImageUpload(file);\n }\n document.body.removeChild(fileInput);\n });\n\n // Detect cancel\n const onFocus = () => {\n window.removeEventListener('focus', onFocus);\n setTimeout(() => {\n if (!fileSelected) {\n isImageToolActive = false;\n if (window.__sketchEngine?.setActiveTool) {\n window.__sketchEngine.setActiveTool('select');\n }\n if (fileInput.parentNode) {\n document.body.removeChild(fileInput);\n }\n }\n }, 300);\n };\n window.addEventListener('focus', onFocus);\n\n // Trigger the file picker\n fileInput.click();\n});\n\n\nconst loadHardcodedImage = (imagePath) => {\n console.log('Loading hardcoded image:', imagePath);\n const img = new Image();\n img.onload = () => {\n console.log('Image loaded successfully');\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n canvas.width = img.width;\n canvas.height = img.height;\n ctx.drawImage(img, 0, 0);\n imageToPlace = canvas.toDataURL();\n isDraggingImage = true;\n console.log('Image ready to place, isDraggingImage:', isDraggingImage);\n };\n img.onerror = (error) => {\n console.error('Failed to load the hardcoded image:', error);\n console.error('Image path:', imagePath);\n };\n img.src = imagePath;\n};\n\nconst handleImageUpload = async (file) => {\n if (!file || !isImageToolActive) return;\n\n // Validate file type against the canonical allowlist (avif, jpeg, jpg,\n // png, bmp, svg, webp). Animated GIF, HEIC, TIFF, video, audio, and\n // arbitrary files are rejected here.\n if (!isAllowedImage(file)) {\n console.error('Rejected file type:', file.type, file.name);\n alert('Unsupported file type. Allowed: AVIF, JPEG, PNG, BMP, SVG, WebP.');\n isImageToolActive = false;\n return;\n }\n\n // Per-room 5MB total image limit\n if (window.__roomImageBytesUsed + file.size > ROOM_IMAGE_LIMIT_BYTES) {\n const usedMB = (window.__roomImageBytesUsed / (1024 * 1024)).toFixed(2);\n const fileMB = (file.size / (1024 * 1024)).toFixed(2);\n alert(`Room image limit reached (5 MB). Used: ${usedMB} MB, this file: ${fileMB} MB. Delete some images to free space.`);\n isImageToolActive = false;\n return;\n }\n\n const maxSize = 5 * 1024 * 1024; // 5MB per file (matches room limit)\n if (file.size > maxSize) {\n console.error('File size too large');\n alert('Image file is too large. Please select an image smaller than 5 MB.');\n return;\n }\n\n console.log('Processing image file:', file.name, 'Size:', file.size, 'Type:', file.type);\n\n // Read \u2192 optionally compress \u2192 place. We compress client-side BEFORE\n // placement so that consumers without an upload pipeline (VS Code\n // extension, offline npm usage) still embed a compressed data URL\n // rather than the original. SVGs are passed through unchanged because\n // rasterizing them would destroy their vector fidelity.\n try {\n const rawDataUrl = await readFileAsDataUrl(file);\n const isSvg = (file.type || '').toLowerCase() === 'image/svg+xml'\n || (file.name || '').toLowerCase().endsWith('.svg');\n\n let placedDataUrl = rawDataUrl;\n let placedSize = file.size;\n if (!isSvg) {\n try {\n const compressed = await compressImage(rawDataUrl);\n if (compressed?.dataUrl) {\n placedDataUrl = compressed.dataUrl;\n placedSize = compressed.compressedSize || placedSize;\n }\n } catch (err) {\n console.warn('[ImageTool] Pre-placement compression failed, using raw:', err);\n }\n }\n\n window.__pendingImageFileSize = placedSize;\n imageToPlace = placedDataUrl;\n isDraggingImage = true;\n console.log('Image loaded and ready to place', { size: placedSize, isSvg });\n } catch (err) {\n console.error('Error reading file:', err);\n alert('Error reading the image file. Please try again.');\n isImageToolActive = false;\n }\n};\n\nfunction readFileAsDataUrl(file) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (e) => resolve(e.target.result);\n reader.onerror = (err) => reject(err);\n reader.readAsDataURL(file);\n });\n}\n\n// Add coordinate conversion function like in other tools\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\n// Event handler for mousemove on the SVG\nconst handleMouseMoveImage = (e) => {\n if (!isDraggingImage || !imageToPlace || !isImageToolActive) return; // Also check isImageToolActive\n\n // Get mouse coordinates relative to the SVG element\n const { x, y } = getSVGCoordsFromMouse(e);\n imageX = x;\n imageY = y;\n\n drawMiniatureImage();\n \n // Check for frame containment while placing image (but don't apply clipping yet)\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.forEach(frame => {\n if (frame.shapeName === 'frame') {\n // Create temporary image bounds for frame checking\n const tempImageBounds = {\n x: imageX - 50, // Half of miniature width\n y: imageY - 50, // Approximate half height\n width: 100,\n height: 100\n };\n \n if (frame.isShapeInFrame(tempImageBounds)) {\n frame.highlightFrame();\n hoveredFrameImage = frame;\n } else if (hoveredFrameImage === frame) {\n frame.removeHighlight();\n hoveredFrameImage = null;\n }\n }\n });\n }\n};\n\nconst drawMiniatureImage = () => {\n if (!isDraggingImage || !imageToPlace || !isImageToolActive) return; // Also check isImageToolActive\n\n const miniatureWidth = 100; // Fixed width for miniature (adjust as needed)\n getImageAspectRatio(imageToPlace)\n .then(aspectRatio => {\n const miniatureHeight = miniatureWidth * aspectRatio; // Maintain aspect ratio\n\n // Remove the previous miniature image, if it exists\n if (currentImageElement) {\n svg.removeChild(currentImageElement);\n currentImageElement = null; // Important: clear the reference\n }\n\n // Create an SVG image element for the miniature\n currentImageElement = document.createElementNS(\"http://www.w3.org/2000/svg\", \"image\");\n currentImageElement.setAttribute(\"href\", imageToPlace);\n currentImageElement.setAttribute(\"x\", imageX - miniatureWidth / 2); \n currentImageElement.setAttribute(\"y\", imageY - miniatureHeight / 2);\n currentImageElement.setAttribute(\"width\", miniatureWidth);\n currentImageElement.setAttribute(\"height\", miniatureHeight);\n currentImageElement.setAttribute(\"preserveAspectRatio\", \"xMidYMid meet\");\n\n svg.appendChild(currentImageElement);\n })\n .catch(error => {\n console.error(\"Error getting aspect ratio:\", error);\n \n });\n};\n\nfunction getImageAspectRatio(dataUrl) {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n resolve(img.height / img.width);\n };\n img.onerror = () => {\n reject(new Error('Failed to load image for aspect ratio calculation.'));\n };\n img.src = dataUrl;\n });\n}\n\n// Update the handleMouseDownImage function to create proper group structure\nconst handleMouseDownImage = async (e) => {\n if (!isDraggingImage || !imageToPlace || !isImageToolActive) {\n // Handle image selection if selection tool is active\n if (isSelectionToolActive) {\n const clickedImage = e.target.closest('image');\n if (clickedImage) {\n selectImage({ target: clickedImage, stopPropagation: () => e.stopPropagation() });\n return;\n }\n }\n return;\n }\n\n try {\n //Get aspect ratio before we clear the temporary image data.\n let aspectRatio = await getImageAspectRatio(imageToPlace);\n\n // Remove the miniature\n if (currentImageElement) {\n svg.removeChild(currentImageElement);\n currentImageElement = null;\n }\n\n // Calculate actual dimensions of the placed image\n const placedImageWidth = 200; // Adjust as needed\n const placedImageHeight = placedImageWidth * aspectRatio;\n\n // Get SVG coordinates\n const { x: placedX, y: placedY } = getSVGCoordsFromMouse(e);\n\n // Create a new SVG image element for the final image\n const finalImage = document.createElementNS(\"http://www.w3.org/2000/svg\", \"image\");\n finalImage.setAttribute(\"href\", imageToPlace);\n finalImage.setAttribute(\"x\", placedX - placedImageWidth / 2);\n finalImage.setAttribute(\"y\", placedY - placedImageHeight / 2);\n finalImage.setAttribute(\"width\", placedImageWidth);\n finalImage.setAttribute(\"height\", placedImageHeight);\n finalImage.setAttribute(\"preserveAspectRatio\", \"xMidYMid meet\");\n\n // Store data for undo/redo\n finalImage.setAttribute('data-href', imageToPlace);\n finalImage.setAttribute('data-x', placedX - placedImageWidth / 2);\n finalImage.setAttribute('data-y', placedY - placedImageHeight / 2);\n finalImage.setAttribute('data-width', placedImageWidth);\n finalImage.setAttribute('data-height', placedImageHeight);\n \n // Add arrow attachment support data attributes\n finalImage.setAttribute('type', 'image');\n finalImage.setAttribute('data-shape-x', placedX - placedImageWidth / 2);\n finalImage.setAttribute('data-shape-y', placedY - placedImageHeight / 2);\n finalImage.setAttribute('data-shape-width', placedImageWidth);\n finalImage.setAttribute('data-shape-height', placedImageHeight);\n finalImage.setAttribute('data-shape-rotation', 0);\n finalImage.shapeID = `image-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n\n // Don't add to SVG directly - let ImageShape wrapper handle it\n // svg.appendChild(finalImage);\n\n // Create ImageShape wrapper for frame functionality\n const imageShape = wrapImageElement(finalImage);\n\n // Add to shapes array for arrow attachment and frame functionality\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.push(imageShape);\n console.log('Image added to shapes array for arrow attachment and frame functionality');\n } else {\n console.warn('shapes array not found - arrows and frames may not work with images');\n }\n\n // Check for frame containment and track attachment\n const finalFrame = hoveredFrameImage;\n if (finalFrame) {\n finalFrame.addShapeToFrame(imageShape);\n // Track the attachment for undo\n pushFrameAttachmentAction(finalFrame, imageShape, 'attach', null);\n }\n\n // Add to undo stack for image creation\n pushCreateAction({\n type: 'image',\n element: imageShape,\n remove: () => {\n if (imageShape.group && imageShape.group.parentNode) {\n imageShape.group.parentNode.removeChild(imageShape.group);\n }\n // Remove from shapes array\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n const idx = shapes.indexOf(imageShape);\n if (idx !== -1) shapes.splice(idx, 1);\n }\n // Clean up arrow attachments when image is removed\n if (typeof cleanupAttachments === 'function') {\n cleanupAttachments(finalImage);\n }\n },\n restore: () => {\n svg.appendChild(imageShape.group);\n // Add back to shapes array\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n if (shapes.indexOf(imageShape) === -1) {\n shapes.push(imageShape);\n }\n }\n }\n });\n\n // Track image size for room limit\n const placedFileSize = window.__pendingImageFileSize || 0;\n finalImage.__fileSize = placedFileSize;\n window.__roomImageBytesUsed = (window.__roomImageBytesUsed || 0) + placedFileSize;\n window.__pendingImageFileSize = 0;\n\n // Add click event to the newly added image\n finalImage.addEventListener('click', selectImage);\n\n // Clear frame highlighting\n if (hoveredFrameImage) {\n hoveredFrameImage.removeHighlight();\n hoveredFrameImage = null;\n }\n\n // Auto-select the placed image and switch to selection tool\n const placedShape = imageShape;\n if (window.__sketchStoreApi) window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });\n currentShape = placedShape;\n currentShape.isSelected = true;\n placedShape.selectShape();\n\n // Fire async upload pipeline. We dispatch via window.uploadImageToCloudinary\n // so embedded hosts (e.g. blogs.elixpo) can swap in a postMessage-based\n // implementation that routes uploads through the host's media API.\n const uploader = (typeof window !== 'undefined' && window.uploadImageToCloudinary) || uploadImageToCloudinary;\n uploader(imageShape).catch(err => {\n console.warn('[ImageTool] Upload pipeline error:', err);\n });\n\n } catch (error) {\n console.error(\"Error placing image:\", error);\n isDraggingImage = false;\n imageToPlace = null;\n isImageToolActive = false; // Important: Reset the tool state.\n } finally {\n isDraggingImage = false;\n imageToPlace = null;\n isImageToolActive = false; // Important: Reset the tool state.\n }\n};\n\nconst handleMouseUpImage = (e) => {\n // Only deselect if the user actually clicked (mousedown+mouseup) on a non-image area\n // of the SVG canvas \u2014 not when the mouse just leaves to the UI\n if (isSelectionToolActive && selectedImage) {\n const clickedElement = e.target;\n const isOnSVG = clickedElement === svg || clickedElement.ownerSVGElement === svg;\n const isImageElement = clickedElement.tagName === 'image';\n const isAnchorElement = clickedElement.classList.contains('resize-anchor') ||\n clickedElement.classList.contains('rotation-anchor') ||\n clickedElement.classList.contains('selection-outline');\n\n // Only deselect if mouseup is directly on the SVG background (not on any shape/anchor)\n if (isOnSVG && !isImageElement && !isAnchorElement && clickedElement === svg && !isDragging && !isRotatingImage && !currentAnchor) {\n removeSelectionOutline();\n selectedImage = null;\n if (window.__sketchStoreApi) {\n window.__sketchStoreApi.clearSelectedShapeSidebar();\n }\n }\n }\n \n // Clear frame highlighting if placing image\n if (hoveredFrameImage) {\n hoveredFrameImage.removeHighlight();\n hoveredFrameImage = null;\n }\n};\n\nfunction selectImage(event) {\n if (!isSelectionToolActive) return;\n\n event.stopPropagation(); // Prevent click from propagating to the SVG\n\n if (selectedImage) {\n removeSelectionOutline();\n }\n\n selectedImage = event.target;\n \n // Get the current rotation from the image transform attribute\n const transform = selectedImage.getAttribute('transform');\n if (transform) {\n const rotateMatch = transform.match(/rotate\\(([^,]+)/);\n if (rotateMatch) {\n imageRotation = parseFloat(rotateMatch[1]);\n }\n } else {\n imageRotation = 0;\n }\n \n addSelectionOutline();\n\n // Store original dimensions for resizing\n originalX = parseFloat(selectedImage.getAttribute('x'));\n originalY = parseFloat(selectedImage.getAttribute('y'));\n originalWidth = parseFloat(selectedImage.getAttribute('width'));\n originalHeight = parseFloat(selectedImage.getAttribute('height'));\n\n // Add drag event listeners to the selected image\n selectedImage.addEventListener('pointerdown', startDrag);\n selectedImage.addEventListener('pointerup', stopDrag);\n selectedImage.addEventListener('pointerleave', stopDrag);\n\n // Set currentShape for sidebar + layer controls\n const imageShape = (typeof shapes !== 'undefined' && Array.isArray(shapes))\n ? shapes.find(s => s.shapeName === 'image' && s.element === selectedImage)\n : null;\n if (imageShape) {\n window.currentShape = imageShape;\n }\n if (typeof window.__showSidebarForShape === 'function') {\n window.__showSidebarForShape('image');\n }\n}\n\nfunction addSelectionOutline() {\n if (!selectedImage) return;\n\n const x = parseFloat(selectedImage.getAttribute('x'));\n const y = parseFloat(selectedImage.getAttribute('y'));\n const width = parseFloat(selectedImage.getAttribute('width'));\n const height = parseFloat(selectedImage.getAttribute('height'));\n\n const zoom = window.currentZoom || 1;\n const selectionPadding = 8 / zoom; // Padding around the selection\n const expandedX = x - selectionPadding;\n const expandedY = y - selectionPadding;\n const expandedWidth = width + 2 * selectionPadding;\n const expandedHeight = height + 2 * selectionPadding;\n\n // Create a dashed outline\n const outlinePoints = [\n [expandedX, expandedY],\n [expandedX + expandedWidth, expandedY],\n [expandedX + expandedWidth, expandedY + expandedHeight],\n [expandedX, expandedY + expandedHeight],\n [expandedX, expandedY]\n ];\n const pointsAttr = outlinePoints.map(p => p.join(',')).join(' ');\n const outline = document.createElementNS(\"http://www.w3.org/2000/svg\", \"polyline\");\n outline.setAttribute(\"points\", pointsAttr);\n outline.setAttribute(\"fill\", \"none\");\n outline.setAttribute(\"stroke\", \"#5B57D1\");\n outline.setAttribute(\"stroke-width\", 1.5);\n outline.setAttribute(\"stroke-dasharray\", \"4 2\");\n outline.setAttribute(\"style\", \"pointer-events: none;\");\n outline.setAttribute(\"class\", \"selection-outline\");\n\n // Apply the same rotation as the image\n const centerX = x + width / 2;\n const centerY = y + height / 2;\n outline.setAttribute('transform', `rotate(${imageRotation}, ${centerX}, ${centerY})`);\n\n svg.appendChild(outline);\n\n // Add resize anchors\n addResizeAnchors(expandedX, expandedY, expandedWidth, expandedHeight, centerX, centerY);\n \n // Add rotation anchor\n addRotationAnchor(expandedX, expandedY, expandedWidth, expandedHeight, centerX, centerY);\n}\n\nfunction removeSelectionOutline() {\n // Remove ALL selection outlines (querySelectorAll to prevent stacking)\n svg.querySelectorAll(\".selection-outline\").forEach(el => el.remove());\n\n // Remove resize anchors\n removeResizeAnchors();\n\n // Remove rotation anchor\n removeRotationAnchor();\n\n // Remove drag event listeners\n if (selectedImage) {\n selectedImage.removeEventListener('pointerdown', startDrag);\n selectedImage.removeEventListener('pointerup', stopDrag);\n selectedImage.removeEventListener('pointerleave', stopDrag);\n }\n}\n\nfunction addResizeAnchors(x, y, width, height, centerX, centerY) {\n const zoom = window.currentZoom || 1;\n const anchorSize = 10 / zoom;\n const anchorStrokeWidth = 2 / zoom;\n\n const positions = [\n { x: x, y: y }, // Top-left\n { x: x + width, y: y }, // Top-right\n { x: x, y: y + height }, // Bottom-left\n { x: x + width, y: y + height } // Bottom-right\n ];\n\n positions.forEach((pos, i) => {\n const anchor = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n anchor.setAttribute(\"x\", pos.x - anchorSize / 2);\n anchor.setAttribute(\"y\", pos.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 anchor.setAttribute(\"class\", \"resize-anchor\");\n anchor.style.cursor = [\"nw-resize\", \"ne-resize\", \"sw-resize\", \"se-resize\"][i];\n\n // Apply the same rotation as the image\n anchor.setAttribute('transform', `rotate(${imageRotation}, ${centerX}, ${centerY})`);\n\n svg.appendChild(anchor);\n\n // Add event listeners for resizing\n anchor.addEventListener('pointerdown', startResize);\n anchor.addEventListener('pointerup', stopResize);\n });\n}\n\nfunction addRotationAnchor(x, y, width, height, centerX, centerY) {\n const zoom = window.currentZoom || 1;\n const anchorStrokeWidth = 2 / zoom;\n const rotationAnchorPos = { x: x + width / 2, y: y - 30 / zoom };\n \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', 5 / zoom);\n rotationAnchor.setAttribute('class', 'rotation-anchor');\n rotationAnchor.setAttribute('fill', '#121212');\n rotationAnchor.setAttribute('stroke', '#5B57D1');\n rotationAnchor.setAttribute('stroke-width', anchorStrokeWidth);\n rotationAnchor.setAttribute('vector-effect', 'non-scaling-stroke');\n rotationAnchor.setAttribute('style', 'pointer-events: all;');\n \n // Apply the same rotation as the image\n rotationAnchor.setAttribute('transform', `rotate(${imageRotation}, ${centerX}, ${centerY})`);\n \n svg.appendChild(rotationAnchor);\n\n // Add event listeners for rotation\n rotationAnchor.addEventListener('pointerdown', startRotation);\n rotationAnchor.addEventListener('pointerup', stopRotation);\n \n rotationAnchor.addEventListener('mouseover', function () {\n if (!isRotatingImage && !isDragging) {\n rotationAnchor.style.cursor = 'grab';\n }\n });\n \n rotationAnchor.addEventListener('mouseout', function () {\n if (!isRotatingImage && !isDragging) {\n rotationAnchor.style.cursor = 'default';\n }\n });\n}\n\nfunction removeRotationAnchor() {\n svg.querySelectorAll(\".rotation-anchor\").forEach(el => el.remove());\n}\n\nfunction addAnchor(x, y, cursor) {\n const anchorSize = 8 / (window.currentZoom || 1);\n const anchor = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n anchor.setAttribute(\"x\", x);\n anchor.setAttribute(\"y\", y);\n anchor.setAttribute(\"width\", anchorSize);\n anchor.setAttribute(\"height\", anchorSize);\n anchor.setAttribute(\"fill\", \"white\");\n anchor.setAttribute(\"stroke\", \"black\");\n anchor.setAttribute(\"stroke-width\", \"1\");\n anchor.setAttribute(\"class\", \"resize-anchor\"); // For easy removal\n anchor.style.cursor = cursor;\n\n svg.appendChild(anchor);\n\n // Add event listeners for dragging\n anchor.addEventListener('pointerdown', startResize);\n anchor.addEventListener('pointerup', stopResize);\n\n}\n\nfunction removeResizeAnchors() {\n const anchors = svg.querySelectorAll(\".resize-anchor\");\n anchors.forEach(anchor => svg.removeChild(anchor));\n}\n\nfunction startResize(event) {\n event.preventDefault();\n event.stopPropagation();\n\n currentAnchor = event.target;\n \n // Store original values at the start of resize\n originalX = parseFloat(selectedImage.getAttribute('x'));\n originalY = parseFloat(selectedImage.getAttribute('y'));\n originalWidth = parseFloat(selectedImage.getAttribute('width'));\n originalHeight = parseFloat(selectedImage.getAttribute('height'));\n \n // Store original rotation\n const transform = selectedImage.getAttribute('transform');\n if (transform) {\n const rotateMatch = transform.match(/rotate\\(([^,]+)/);\n if (rotateMatch) {\n imageRotation = parseFloat(rotateMatch[1]);\n }\n }\n \n svg.addEventListener('pointermove', resizeImage);\n document.addEventListener('pointerup', stopResize);\n}\n\nfunction stopResize(event) {\n stopInteracting(); // Call the combined stop function\n document.removeEventListener('pointerup', stopResize); // Remove the global mouseup listener\n}\n\nfunction resizeImage(event) {\n if (!selectedImage || !currentAnchor) return;\n\n const { x: globalX, y: globalY } = getSVGCoordsFromMouse(event);\n\n // Use ORIGINAL center for consistent inverse rotation (avoids drift)\n const centerX = originalX + originalWidth / 2;\n const centerY = originalY + originalHeight / 2;\n\n // Convert mouse position to local coordinates accounting for rotation\n let localX = globalX;\n let localY = globalY;\n\n if (imageRotation !== 0) {\n const rotationRad = (imageRotation * Math.PI) / 180;\n const translatedX = globalX - centerX;\n const translatedY = globalY - centerY;\n localX = translatedX * Math.cos(-rotationRad) - translatedY * Math.sin(-rotationRad) + centerX;\n localY = translatedX * Math.sin(-rotationRad) + translatedY * Math.cos(-rotationRad) + centerY;\n }\n\n // Calculate resize deltas in local coordinate space\n let dx = localX - originalX;\n let dy = localY - originalY;\n\n let newWidth = originalWidth;\n let newHeight = originalHeight;\n let newX = originalX;\n let newY = originalY;\n const aspectRatio = originalHeight / originalWidth;\n\n // Track which corner is fixed (relative to original rect)\n let fixedRelX, fixedRelY;\n\n switch (currentAnchor.style.cursor) {\n case \"nw-resize\":\n newWidth = originalWidth - dx;\n newHeight = originalHeight - dy;\n if (aspect_ratio_lock) {\n newHeight = newWidth * aspectRatio;\n dy = originalHeight - newHeight;\n }\n newX = originalX + (originalWidth - newWidth);\n newY = originalY + (originalHeight - newHeight);\n fixedRelX = originalWidth; fixedRelY = originalHeight;\n break;\n case \"ne-resize\":\n newWidth = dx;\n newHeight = originalHeight - dy;\n if (aspect_ratio_lock) {\n newHeight = newWidth * aspectRatio;\n dy = originalHeight - newHeight;\n }\n newX = originalX;\n newY = originalY + (originalHeight - newHeight);\n fixedRelX = 0; fixedRelY = originalHeight;\n break;\n case \"sw-resize\":\n newWidth = originalWidth - dx;\n newHeight = dy;\n if (aspect_ratio_lock) {\n newHeight = newWidth * aspectRatio;\n dy = newHeight;\n }\n newX = originalX + (originalWidth - newWidth);\n newY = originalY;\n fixedRelX = originalWidth; fixedRelY = 0;\n break;\n case \"se-resize\":\n newWidth = dx;\n newHeight = dy;\n if (aspect_ratio_lock) {\n newHeight = newWidth * aspectRatio;\n }\n newX = originalX;\n newY = originalY;\n fixedRelX = 0; fixedRelY = 0;\n break;\n }\n\n // Ensure minimum size\n newWidth = Math.max(minImageSize, newWidth);\n newHeight = Math.max(minImageSize, newHeight);\n\n // Compensate for rotation center shift when rotated\n if (imageRotation !== 0) {\n const rad = (imageRotation * Math.PI) / 180;\n const cosR = Math.cos(rad);\n const sinR = Math.sin(rad);\n\n // Compute rotated world position of the fixed corner in the original rect\n const oldCX = originalX + originalWidth / 2;\n const oldCY = originalY + originalHeight / 2;\n const odx = (originalX + fixedRelX) - oldCX;\n const ody = (originalY + fixedRelY) - oldCY;\n const fixedWorldX = oldCX + odx * cosR - ody * sinR;\n const fixedWorldY = oldCY + odx * sinR + ody * cosR;\n\n // Determine where the fixed corner sits in the new rect (relative to new origin)\n const fixedNewRelX = fixedRelX === 0 ? 0 : newWidth;\n const fixedNewRelY = fixedRelY === 0 ? 0 : newHeight;\n\n // Solve for new origin so the fixed corner stays in place\n const ncx = newWidth / 2;\n const ncy = newHeight / 2;\n const ndx = fixedNewRelX - ncx;\n const ndy = fixedNewRelY - ncy;\n const rotX = ncx + ndx * cosR - ndy * sinR;\n const rotY = ncy + ndx * sinR + ndy * cosR;\n\n newX = fixedWorldX - rotX;\n newY = fixedWorldY - rotY;\n }\n\n // Apply the new dimensions and position\n selectedImage.setAttribute('width', newWidth);\n selectedImage.setAttribute('height', newHeight);\n selectedImage.setAttribute('x', newX);\n selectedImage.setAttribute('y', newY);\n\n // Update data attributes for arrow attachment\n selectedImage.setAttribute('data-shape-x', newX);\n selectedImage.setAttribute('data-shape-y', newY);\n selectedImage.setAttribute('data-shape-width', newWidth);\n selectedImage.setAttribute('data-shape-height', newHeight);\n\n // Reapply the rotation transform with the new center\n const newCenterX = newX + newWidth / 2;\n const newCenterY = newY + newHeight / 2;\n selectedImage.setAttribute('transform', `rotate(${imageRotation}, ${newCenterX}, ${newCenterY})`);\n\n // Update attached arrows during resize\n updateArrowsForShape(selectedImage);\n\n // Update the selection outline and anchors\n removeSelectionOutline();\n addSelectionOutline();\n}\n\nfunction stopRotation(event) {\n if (!isRotatingImage) return;\n stopInteracting();\n isRotatingImage = false;\n startRotationMouseAngle = null;\n startImageRotation = null;\n svg.removeEventListener('pointermove', rotateImage);\n document.removeEventListener('pointerup', stopRotation);\n svg.style.cursor = 'default';\n}\n\nfunction startDrag(event) {\n if (!isSelectionToolActive || !selectedImage) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n isDragging = true;\n \n // Store original values at the start of drag\n originalX = parseFloat(selectedImage.getAttribute('x'));\n originalY = parseFloat(selectedImage.getAttribute('y'));\n originalWidth = parseFloat(selectedImage.getAttribute('width'));\n originalHeight = parseFloat(selectedImage.getAttribute('height'));\n \n // Store original rotation\n const transform = selectedImage.getAttribute('transform');\n if (transform) {\n const rotateMatch = transform.match(/rotate\\(([^,]+)/);\n if (rotateMatch) {\n imageRotation = parseFloat(rotateMatch[1]);\n }\n }\n\n // Find the ImageShape wrapper for frame functionality\n let imageShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n imageShape = shapes.find(shape => shape.shapeName === 'image' && shape.element === selectedImage);\n }\n\n if (imageShape) {\n // Store initial frame state\n draggedShapeInitialFrameImage = imageShape.parentFrame || null;\n \n // Temporarily remove from frame clipping if dragging\n if (imageShape.parentFrame) {\n imageShape.parentFrame.temporarilyRemoveFromFrame(imageShape);\n }\n }\n\n const { x, y } = getSVGCoordsFromMouse(event);\n dragOffsetX = x - parseFloat(selectedImage.getAttribute('x'));\n dragOffsetY = y - parseFloat(selectedImage.getAttribute('y'));\n\n svg.addEventListener('pointermove', dragImage);\n document.addEventListener('pointerup', stopDrag);\n}\n\nfunction dragImage(event) {\n if (!isDragging || !selectedImage) return;\n\n const { x, y } = getSVGCoordsFromMouse(event);\n let newX = x - dragOffsetX;\n let newY = y - dragOffsetY;\n\n selectedImage.setAttribute('x', newX);\n selectedImage.setAttribute('y', newY);\n\n // Update data attributes for arrow attachment\n selectedImage.setAttribute('data-shape-x', newX);\n selectedImage.setAttribute('data-shape-y', newY);\n\n // Reapply the rotation transform with the new position\n const newCenterX = newX + parseFloat(selectedImage.getAttribute('width')) / 2;\n const newCenterY = newY + parseFloat(selectedImage.getAttribute('height')) / 2;\n selectedImage.setAttribute('transform', `rotate(${imageRotation}, ${newCenterX}, ${newCenterY})`);\n\n // Update frame containment for ImageShape wrapper\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n const imageShape = shapes.find(shape => shape.shapeName === 'image' && shape.element === selectedImage);\n if (imageShape) {\n imageShape.updateFrameContainment();\n }\n }\n\n // Update attached arrows during drag\n updateArrowsForShape(selectedImage);\n\n // Update the selection outline and anchors\n removeSelectionOutline();\n addSelectionOutline();\n}\n\nfunction stopDrag(event) {\n stopInteracting(); // Call the combined stop function\n document.removeEventListener('pointerup', stopDrag); // Remove the global mouseup listener\n}\n\nfunction startRotation(event) {\n event.preventDefault();\n event.stopPropagation();\n\n if (!selectedImage) return;\n\n isRotatingImage = true;\n \n // Get image center\n const imgX = parseFloat(selectedImage.getAttribute('x'));\n const imgY = parseFloat(selectedImage.getAttribute('y'));\n const imgWidth = parseFloat(selectedImage.getAttribute('width'));\n const imgHeight = parseFloat(selectedImage.getAttribute('height'));\n \n const centerX = imgX + imgWidth / 2;\n const centerY = imgY + imgHeight / 2;\n\n // Calculate initial mouse angle relative to image center\n const { x: mouseX, y: mouseY } = getSVGCoordsFromMouse(event);\n \n startRotationMouseAngle = Math.atan2(mouseY - centerY, mouseX - centerX) * 180 / Math.PI;\n startImageRotation = imageRotation;\n\n svg.addEventListener('pointermove', rotateImage);\n document.addEventListener('pointerup', stopRotation);\n \n svg.style.cursor = 'grabbing';\n}\n\nfunction rotateImage(event) {\n if (!isRotatingImage || !selectedImage) return;\n\n // Get image center\n const imgX = parseFloat(selectedImage.getAttribute('x'));\n const imgY = parseFloat(selectedImage.getAttribute('y'));\n const imgWidth = parseFloat(selectedImage.getAttribute('width'));\n const imgHeight = parseFloat(selectedImage.getAttribute('height'));\n \n const centerX = imgX + imgWidth / 2;\n const centerY = imgY + imgHeight / 2;\n\n // Calculate current mouse angle\n const { x: mouseX, y: mouseY } = getSVGCoordsFromMouse(event);\n \n const currentMouseAngle = Math.atan2(mouseY - centerY, mouseX - centerX) * 180 / Math.PI;\n const angleDiff = currentMouseAngle - startRotationMouseAngle;\n \n imageRotation = startImageRotation + angleDiff;\n imageRotation = imageRotation % 360;\n if (imageRotation < 0) imageRotation += 360;\n\n // Apply rotation transform\n selectedImage.setAttribute('transform', `rotate(${imageRotation}, ${centerX}, ${centerY})`);\n \n // Update data attribute for arrow attachment\n selectedImage.setAttribute('data-shape-rotation', imageRotation);\n\n // Update attached arrows during rotation\n updateArrowsForShape(selectedImage);\n\n // Update the selection outline and anchors\n removeSelectionOutline();\n addSelectionOutline();\n}\n\nfunction stopInteracting() {\n // Store transform data before stopping interaction\n if (selectedImage && (isDragging || isRotatingImage || currentAnchor)) {\n const newPos = {\n x: parseFloat(selectedImage.getAttribute('x')),\n y: parseFloat(selectedImage.getAttribute('y')),\n width: parseFloat(selectedImage.getAttribute('width')),\n height: parseFloat(selectedImage.getAttribute('height')),\n rotation: imageRotation\n };\n \n // Get the original rotation from the stored start rotation or current rotation\n let originalRotation = imageRotation;\n if (isRotatingImage && startImageRotation !== null) {\n originalRotation = startImageRotation;\n }\n \n const oldPos = {\n x: originalX,\n y: originalY,\n width: originalWidth,\n height: originalHeight,\n rotation: originalRotation\n };\n\n // Find the ImageShape wrapper for frame tracking\n let imageShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n imageShape = shapes.find(shape => shape.shapeName === 'image' && shape.element === selectedImage);\n }\n\n // Add frame information for undo tracking\n const oldPosWithFrame = {\n ...oldPos,\n parentFrame: draggedShapeInitialFrameImage\n };\n // Issue #34 bug #2: for drag, hoveredFrameImage tracks the actual\n // destination \u2014 imageShape.parentFrame is still the OLD frame here.\n // Resize / rotate don't move between frames, so fall back to the\n // shape's own parent for those.\n const newPosWithFrame = {\n ...newPos,\n parentFrame: isDragging\n ? (hoveredFrameImage || null)\n : (imageShape ? imageShape.parentFrame : null),\n };\n\n // Only push transform action if something actually changed\n const stateChanged = newPos.x !== oldPos.x || newPos.y !== oldPos.y || \n newPos.width !== oldPos.width || newPos.height !== oldPos.height ||\n newPos.rotation !== oldPos.rotation;\n const frameChanged = oldPosWithFrame.parentFrame !== newPosWithFrame.parentFrame;\n\n if (stateChanged || frameChanged) {\n pushTransformAction({\n type: 'image',\n element: selectedImage,\n restore: (pos) => {\n selectedImage.setAttribute('x', pos.x);\n selectedImage.setAttribute('y', pos.y);\n selectedImage.setAttribute('width', pos.width);\n selectedImage.setAttribute('height', pos.height);\n const centerX = pos.x + pos.width / 2;\n const centerY = pos.y + pos.height / 2;\n selectedImage.setAttribute('transform', `rotate(${pos.rotation}, ${centerX}, ${centerY})`);\n imageRotation = pos.rotation;\n \n // Update selection outline if image is selected\n if (selectedImage) {\n removeSelectionOutline();\n addSelectionOutline();\n }\n \n // Update data attributes for arrow attachment consistency\n selectedImage.setAttribute('data-shape-x', pos.x);\n selectedImage.setAttribute('data-shape-y', pos.y);\n selectedImage.setAttribute('data-shape-width', pos.width);\n selectedImage.setAttribute('data-shape-height', pos.height);\n selectedImage.setAttribute('data-shape-rotation', pos.rotation);\n \n // Update attached arrows\n updateArrowsForShape(selectedImage);\n }\n }, oldPosWithFrame, newPosWithFrame);\n }\n\n // Handle frame containment changes after drag\n if (isDragging && imageShape) {\n const finalFrame = hoveredFrameImage;\n \n // If shape moved to a different frame\n if (draggedShapeInitialFrameImage !== finalFrame) {\n // Remove from initial frame\n if (draggedShapeInitialFrameImage) {\n draggedShapeInitialFrameImage.removeShapeFromFrame(imageShape);\n }\n \n // Add to new frame\n if (finalFrame) {\n finalFrame.addShapeToFrame(imageShape);\n }\n \n // Track the frame change for undo\n if (frameChanged) {\n pushFrameAttachmentAction(finalFrame || draggedShapeInitialFrameImage, imageShape, \n finalFrame ? 'attach' : 'detach', draggedShapeInitialFrameImage);\n }\n } else if (draggedShapeInitialFrameImage) {\n // Shape stayed in same frame, restore clipping\n draggedShapeInitialFrameImage.restoreToFrame(imageShape);\n }\n }\n \n draggedShapeInitialFrameImage = null;\n }\n\n // Clear frame highlighting\n if (hoveredFrameImage) {\n hoveredFrameImage.removeHighlight();\n hoveredFrameImage = null;\n }\n\n isDragging = false;\n isRotatingImage = false;\n svg.removeEventListener('pointermove', dragImage);\n svg.removeEventListener('pointermove', resizeImage);\n svg.removeEventListener('pointermove', rotateImage);\n currentAnchor = null;\n startRotationMouseAngle = null;\n startImageRotation = null;\n\n // Update originalX, originalY, originalWidth and originalHeight after dragging/resizing is complete\n if (selectedImage) {\n originalX = parseFloat(selectedImage.getAttribute('x'));\n originalY = parseFloat(selectedImage.getAttribute('y'));\n originalWidth = parseFloat(selectedImage.getAttribute('width'));\n originalHeight = parseFloat(selectedImage.getAttribute('height'));\n \n // Update the current rotation from the image transform\n const transform = selectedImage.getAttribute('transform');\n if (transform) {\n const rotateMatch = transform.match(/rotate\\(([^,]+)/);\n if (rotateMatch) {\n imageRotation = parseFloat(rotateMatch[1]);\n }\n }\n \n // Update data attributes for arrow attachment consistency\n selectedImage.setAttribute('data-shape-x', originalX);\n selectedImage.setAttribute('data-shape-y', originalY);\n selectedImage.setAttribute('data-shape-width', originalWidth);\n selectedImage.setAttribute('data-shape-height', originalHeight);\n selectedImage.setAttribute('data-shape-rotation', imageRotation);\n \n // Update attached arrows after interaction ends\n updateArrowsForShape(selectedImage);\n }\n}\n\n// Add delete functionality for images\nfunction deleteCurrentImage() {\n if (selectedImage) {\n // Find the ImageShape wrapper\n let imageShape = (typeof shapes !== 'undefined' && Array.isArray(shapes))\n ? shapes.find(s => s.shapeName === 'image' && s.element === selectedImage)\n : null;\n\n // Abort any in-progress upload\n if (imageShape?.uploadAbortController) {\n imageShape.uploadAbortController.abort();\n imageShape.removeUploadIndicator();\n }\n\n // Release image bytes from room limit\n const freedBytes = selectedImage.__fileSize || 0;\n window.__roomImageBytesUsed = Math.max(0, (window.__roomImageBytesUsed || 0) - freedBytes);\n\n // If image is hosted on Cloudinary, delete it from storage\n const imgHref = selectedImage.getAttribute('href') || selectedImage.getAttributeNS('http://www.w3.org/1999/xlink', 'href') || '';\n if (imgHref.includes('cloudinary.com') || imgHref.includes('res.cloudinary')) {\n const match = imgHref.match(/\\/upload\\/(?:v\\d+\\/)?(lixsketch\\/.+?)(?:\\.\\w+)?$/);\n if (match) {\n const publicId = match[1];\n const workerUrl = window.__WORKER_URL;\n if (workerUrl) {\n fetch(`${workerUrl}/api/images/delete`, {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ publicId }),\n }).catch(err => console.warn('[ImageTool] Cloudinary cleanup failed:', err));\n }\n }\n }\n\n if (imageShape) {\n const idx = shapes.indexOf(imageShape);\n if (idx !== -1) shapes.splice(idx, 1);\n\n // Remove the group (which contains the image)\n if (imageShape.group && imageShape.group.parentNode) {\n imageShape.group.parentNode.removeChild(imageShape.group);\n }\n }\n \n // Fallback: if no ImageShape wrapper found, remove the image directly\n if (!imageShape && selectedImage.parentNode) {\n selectedImage.parentNode.removeChild(selectedImage);\n }\n \n // Clean up any arrow attachments before deleting\n if (typeof cleanupAttachments === 'function') {\n cleanupAttachments(selectedImage);\n }\n \n // Push delete action for undo\n if (imageShape) {\n pushDeleteAction(imageShape);\n }\n \n // Clean up selection\n removeSelectionOutline();\n selectedImage = null;\n }\n}\n\ndocument.addEventListener('keydown', (e) => {\n if (e.key === 'Delete' && selectedImage) {\n deleteCurrentImage();\n }\n});\n\n// Expose upload pipeline globally so generated/pasted images can use it\nwindow.uploadImageToCloudinary = uploadImageToCloudinary;\n\n// Window bridge: allow React UI to trigger the file picker\nwindow.openImageFilePicker = function() {\n isImageToolActive = true;\n const fileInput = document.createElement('input');\n fileInput.type = 'file';\n fileInput.accept = IMAGE_ACCEPT_ATTR;\n fileInput.style.display = 'none';\n document.body.appendChild(fileInput);\n\n let fileSelected = false;\n\n fileInput.addEventListener('change', (event) => {\n const file = event.target.files[0];\n if (file) {\n fileSelected = true;\n handleImageUpload(file);\n }\n document.body.removeChild(fileInput);\n });\n\n // Detect cancel: when focus returns to window without a file being selected\n const onFocus = () => {\n window.removeEventListener('focus', onFocus);\n // Delay to let 'change' fire first if a file was selected\n setTimeout(() => {\n if (!fileSelected) {\n // User cancelled \u2014 switch back to select tool\n isImageToolActive = false;\n if (window.__sketchEngine?.setActiveTool) {\n window.__sketchEngine.setActiveTool('select');\n }\n if (fileInput.parentNode) {\n document.body.removeChild(fileInput);\n }\n }\n }, 300);\n };\n window.addEventListener('focus', onFocus);\n\n fileInput.click();\n};\n\nexport { handleMouseDownImage, handleMouseMoveImage, handleMouseUpImage };"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/core/UndoRedo.js"],
4
- "sourcesContent": ["/* eslint-disable */\n// Undo/Redo system - copied from undoAndRedo.js\n\n// Stacks for undo/redo\nconst undoStack = [];\nconst redoStack = [];\n\n// Import references to text-related variables and functions\nlet selectedElement = null;\nlet updateSelectionFeedback = null;\nlet svg = null;\n\nfunction notifyCollaboration() {\n if (typeof window !== 'undefined' && typeof window.__collabSceneChanged === 'function') {\n window.__collabSceneChanged();\n }\n}\n\n// Function to set references from other modules\nexport function setTextReferences(element, updateFn, svgElement) {\n selectedElement = element;\n updateSelectionFeedback = updateFn;\n svg = svgElement;\n}\n\n// Function to get current selectedElement (called from other modules)\nexport function getCurrentSelectedElement() {\n return selectedElement;\n}\n\n// Function to update selectedElement reference (called from other modules)\nexport function updateSelectedElement(element) {\n selectedElement = element;\n}\n\n// Call this after creating a new shape (e.g., Rectangle)\nexport function pushCreateAction(shape) {\n undoStack.push({\n type: 'create',\n shape: shape\n });\n \n // Clear redo stack when new action is performed\n redoStack.length = 0;\n notifyCollaboration();\n}\n\nexport function pushDeleteAction(shape, meta = null) {\n // Issue #24 bug #7: when the deleted shape is a frame, the caller may\n // pass `meta.childSnapshot` \u2014 the contained shape REFERENCES at the\n // time of delete. The undo branch uses this to re-attach the children\n // when the frame is restored, instead of leaving an empty box.\n const action = { type: 'delete', shape };\n if (meta && meta.childSnapshot) action.childSnapshot = meta.childSnapshot;\n undoStack.push(action);\n\n // Clear redo stack when new action is performed\n redoStack.length = 0;\n notifyCollaboration();\n}\n\n// Enhanced delete action to clean up attached arrows\nexport function pushDeleteActionWithAttachments(shape) {\n let affectedArrows = [];\n \n // If deleting a text element, find all attached arrows\n if (shape.type === 'text' || shape.shapeName === 'text') {\n affectedArrows = shapes.filter(s => s.shapeName === 'arrow' && \n (s.attachedToStart?.shape === shape || s.attachedToEnd?.shape === shape))\n .map(arrow => ({\n arrow: arrow,\n oldAttachments: arrow.getAttachmentState(),\n oldPoints: {\n startPoint: { ...arrow.startPoint },\n endPoint: { ...arrow.endPoint }\n }\n }));\n }\n \n undoStack.push({\n type: 'delete',\n shape: shape,\n affectedArrows: affectedArrows\n });\n \n // Clear redo stack when new action is performed\n redoStack.length = 0;\n notifyCollaboration();\n}\n\nexport function pushFrameAttachmentAction(frame, shape, action, oldFrame = null) {\n undoStack.push({\n type: 'frameAttachment',\n frame: frame,\n shape: shape,\n action: action, // 'attach' or 'detach'\n oldFrame: oldFrame, // Previous frame if shape was moved between frames\n // Store shape position for potential restoration\n shapeState: {\n x: shape.x,\n y: shape.y,\n width: shape.width || 0,\n height: shape.height || 0,\n rotation: shape.rotation || 0\n }\n });\n \n // Clear redo stack when new action is performed\n redoStack.length = 0;\n notifyCollaboration();\n}\n\nexport function pushCreateActionWithAttachments(shape) {\n undoStack.push({\n type: 'create',\n shape: shape,\n // Store any arrows that might need to reattach when this is undone\n potentialAttachments: []\n });\n \n // Clear redo stack when new action is performed\n redoStack.length = 0;\n notifyCollaboration();\n}\n\nexport function pushTransformAction(shape, oldPos, newPos) {\n if (shape.shapeName === 'frame') {\n // Handle frame transformation with contained shapes\n const containedShapesStates = shape.containedShapes.map(containedShape => ({\n shape: containedShape,\n oldState: {\n x: containedShape.x - (newPos.x - oldPos.x),\n y: containedShape.y - (newPos.y - oldPos.y),\n width: containedShape.width || 0,\n height: containedShape.height || 0,\n rotation: containedShape.rotation || 0\n },\n newState: {\n x: containedShape.x,\n y: containedShape.y,\n width: containedShape.width || 0,\n height: containedShape.height || 0,\n rotation: containedShape.rotation || 0\n }\n }));\n\n undoStack.push({\n type: 'frameTransform',\n shape: shape,\n oldPos: {\n x: oldPos.x,\n y: oldPos.y,\n width: oldPos.width,\n height: oldPos.height,\n rotation: oldPos.rotation,\n frameName: oldPos.frameName || shape.frameName\n },\n newPos: {\n x: newPos.x,\n y: newPos.y,\n width: newPos.width,\n height: newPos.height,\n rotation: newPos.rotation,\n frameName: newPos.frameName || shape.frameName\n },\n containedShapes: containedShapesStates\n });\n } else if (shape.type === 'text') {\n // Enhanced text handling - also track frame attachment changes\n const currentFrame = shape.parentFrame || null;\n \n undoStack.push({\n type: 'transform',\n shape: shape,\n oldPos: {\n x: oldPos.x,\n y: oldPos.y,\n rotation: oldPos.rotation,\n fontSize: oldPos.fontSize\n },\n newPos: {\n x: newPos.x,\n y: newPos.y,\n rotation: newPos.rotation,\n fontSize: newPos.fontSize\n },\n // Track frame attachment state\n frameAttachment: {\n oldFrame: oldPos.parentFrame || null,\n newFrame: currentFrame\n },\n // Store affected arrows with their attachment states\n affectedArrows: shapes.filter(s => s.shapeName === 'arrow' && \n (s.attachedToStart?.shape === shape || s.attachedToEnd?.shape === shape))\n .map(arrow => ({\n arrow: arrow,\n oldAttachments: arrow.getAttachmentState(),\n oldPoints: {\n startPoint: { ...arrow.startPoint },\n endPoint: { ...arrow.endPoint }\n }\n }))\n });\n } else if (shape.type === 'image') {\n // Enhanced image handling - also track frame attachment changes\n const currentFrame = shape.parentFrame || null;\n \n undoStack.push({\n type: 'transform',\n shape: shape,\n oldPos: {\n x: oldPos.x,\n y: oldPos.y,\n width: oldPos.width,\n height: oldPos.height,\n rotation: oldPos.rotation\n },\n newPos: {\n x: newPos.x,\n y: newPos.y,\n width: newPos.width,\n height: newPos.height,\n rotation: newPos.rotation\n },\n // Track frame attachment state\n frameAttachment: {\n oldFrame: oldPos.parentFrame || null,\n newFrame: currentFrame\n },\n // Store affected arrows with their attachment states\n affectedArrows: shapes.filter(s => s.shapeName === 'arrow' && \n (s.attachedToStart?.shape === shape || s.attachedToEnd?.shape === shape))\n .map(arrow => ({\n arrow: arrow,\n oldAttachments: arrow.getAttachmentState(),\n oldPoints: {\n startPoint: { ...arrow.startPoint },\n endPoint: { ...arrow.endPoint }\n }\n }))\n });\n } else if (shape.shapeName === 'circle') {\n // Enhanced circle handling - also track frame attachment changes\n const currentFrame = shape.parentFrame || null;\n \n undoStack.push({\n type: 'transform',\n shape: shape,\n oldPos: {\n x: oldPos.x,\n y: oldPos.y,\n rx: oldPos.rx,\n ry: oldPos.ry,\n rotation: oldPos.rotation\n },\n newPos: {\n x: newPos.x,\n y: newPos.y,\n rx: newPos.rx,\n ry: newPos.ry,\n rotation: newPos.rotation\n },\n // Track frame attachment state\n frameAttachment: {\n oldFrame: oldPos.parentFrame || null,\n newFrame: currentFrame\n },\n // Store affected arrows with their attachment states\n affectedArrows: shapes.filter(s => s.shapeName === 'arrow' && \n (s.attachedToStart?.shape === shape || s.attachedToEnd?.shape === shape))\n .map(arrow => ({\n arrow: arrow,\n oldAttachments: arrow.getAttachmentState(),\n oldPoints: {\n startPoint: { ...arrow.startPoint },\n endPoint: { ...arrow.endPoint }\n }\n }))\n });\n } else if (shape.shapeName === \"rectangle\") {\n // Enhanced rectangle handling - also track frame attachment changes\n const currentFrame = shape.parentFrame || null;\n \n undoStack.push({\n type: 'transform',\n shape: shape,\n oldPos: { \n x: oldPos.x, \n y: oldPos.y, \n width: oldPos.width, \n height: oldPos.height, \n rotation: oldPos.rotation\n },\n newPos: { \n x: newPos.x, \n y: newPos.y, \n width: newPos.width, \n height: newPos.height, \n rotation: newPos.rotation\n },\n // Track frame attachment state\n frameAttachment: {\n oldFrame: oldPos.parentFrame || null,\n newFrame: currentFrame\n },\n // Store affected arrows with their attachment states\n affectedArrows: shapes.filter(s => s.shapeName === 'arrow' && \n (s.attachedToStart?.shape === shape || s.attachedToEnd?.shape === shape))\n .map(arrow => ({\n arrow: arrow,\n oldAttachments: arrow.getAttachmentState(),\n oldPoints: {\n startPoint: { ...arrow.startPoint },\n endPoint: { ...arrow.endPoint }\n }\n }))\n });\n } \n else if (shape.shapeName === 'line') {\n // Enhanced line handling with curve support\n const currentFrame = shape.parentFrame || null;\n \n undoStack.push({\n type: 'transform',\n shape: shape,\n oldPos: {\n startPoint: { x: oldPos.startPoint.x, y: oldPos.startPoint.y },\n endPoint: { x: oldPos.endPoint.x, y: oldPos.endPoint.y },\n controlPoint: oldPos.controlPoint ? { x: oldPos.controlPoint.x, y: oldPos.controlPoint.y } : null,\n isCurved: oldPos.isCurved || false\n },\n newPos: {\n startPoint: { x: newPos.startPoint.x, y: newPos.startPoint.y },\n endPoint: { x: newPos.endPoint.x, y: newPos.endPoint.y },\n controlPoint: newPos.controlPoint ? { x: newPos.controlPoint.x, y: newPos.controlPoint.y } : null,\n isCurved: newPos.isCurved || false\n },\n // Track frame attachment state\n frameAttachment: {\n oldFrame: oldPos.parentFrame || null,\n newFrame: currentFrame\n }\n });\n }\n else if (shape.shapeName === 'arrow') {\n // Handle arrow transform with attachment state\n undoStack.push({\n type: 'transform',\n shape: shape,\n oldPos: {\n startPoint: { x: oldPos.startPoint.x, y: oldPos.startPoint.y },\n endPoint: { x: oldPos.endPoint.x, y: oldPos.endPoint.y },\n controlPoint1: oldPos.controlPoint1 ? { x: oldPos.controlPoint1.x, y: oldPos.controlPoint1.y } : null,\n controlPoint2: oldPos.controlPoint2 ? { x: oldPos.controlPoint2.x, y: oldPos.controlPoint2.y } : null,\n attachments: oldPos.attachments || shape.getAttachmentState()\n },\n newPos: {\n startPoint: { x: newPos.startPoint.x, y: newPos.startPoint.y },\n endPoint: { x: newPos.endPoint.x, y: newPos.endPoint.y },\n controlPoint1: newPos.controlPoint1 ? { x: newPos.controlPoint1.x, y: newPos.controlPoint1.y } : null,\n controlPoint2: newPos.controlPoint2 ? { x: newPos.controlPoint2.x, y: newPos.controlPoint2.y } : null,\n attachments: newPos.attachments || shape.getAttachmentState()\n }\n });\n } \n else if (shape.type === 'icon') {\n // Enhanced icon handling - also track frame attachment changes\n const currentFrame = shape.parentFrame || null;\n \n undoStack.push({\n type: 'transform',\n shape: shape,\n oldPos: {\n x: oldPos.x,\n y: oldPos.y,\n width: oldPos.width,\n height: oldPos.height,\n rotation: oldPos.rotation\n },\n newPos: {\n x: newPos.x,\n y: newPos.y,\n width: newPos.width,\n height: newPos.height,\n rotation: newPos.rotation\n },\n // Track frame attachment state\n frameAttachment: {\n oldFrame: oldPos.parentFrame || null,\n newFrame: currentFrame\n },\n // Store affected arrows with their attachment states\n affectedArrows: shapes.filter(s => s.shapeName === 'arrow' && \n (s.attachedToStart?.shape === shape || s.attachedToEnd?.shape === shape))\n .map(arrow => ({\n arrow: arrow,\n oldAttachments: arrow.getAttachmentState(),\n oldPoints: {\n startPoint: { ...arrow.startPoint },\n endPoint: { ...arrow.endPoint }\n }\n }))\n });\n}\n else if (shape.shapeName === 'freehandStroke') {\n // Handle freehand stroke transform\n undoStack.push({\n type: 'transform',\n shape: shape,\n oldPos: {\n points: JSON.parse(JSON.stringify(oldPos.points)),\n rotation: oldPos.rotation\n },\n newPos: {\n points: JSON.parse(JSON.stringify(newPos.points)),\n rotation: newPos.rotation\n }\n });\n }\n \n // Clear redo stack when new action is performed\n redoStack.length = 0;\n notifyCollaboration();\n}\n\nexport function pushOptionsChangeAction(shape, oldOptions) {\n undoStack.push({\n type: 'optionsChange',\n shape: shape,\n oldOptions: oldOptions\n });\n \n // Clear redo stack when new action is performed\n redoStack.length = 0;\n notifyCollaboration();\n}\n\n// Issue #34 bug #4: refresh the multi-selection outline + handles so it\n// follows the reverted geometry. Without this the selection rect stays\n// pinned to the pre-undo coordinates and the user sees a ghost rect\n// floating away from the shapes it claims to wrap.\nfunction refreshSelectionAfterAction() {\n const ms = (typeof window !== 'undefined') ? window.multiSelection : null;\n if (!ms) return;\n if (typeof ms.updateControls !== 'function') return;\n if (!ms.selectedShapes || ms.selectedShapes.size === 0) return;\n try { ms.updateControls(); } catch (err) { console.warn('[UndoRedo] selection refresh failed:', err); }\n}\n\nexport function undo() {\n if (undoStack.length === 0) return;\n const action = undoStack.pop();\n try {\n if (action.type === 'frameTransform') {\n // Handle frame transformation undo\n action.shape.x = action.oldPos.x;\n action.shape.y = action.oldPos.y;\n action.shape.width = action.oldPos.width;\n action.shape.height = action.oldPos.height;\n action.shape.rotation = action.oldPos.rotation;\n action.shape.frameName = action.oldPos.frameName;\n \n // Restore contained shapes to their old positions\n action.containedShapes.forEach(shapeData => {\n const shape = shapeData.shape;\n shape.x = shapeData.oldState.x;\n shape.y = shapeData.oldState.y;\n shape.width = shapeData.oldState.width;\n shape.height = shapeData.oldState.height;\n shape.rotation = shapeData.oldState.rotation;\n \n if (typeof shape.draw === 'function') {\n shape.draw();\n }\n });\n \n action.shape.isSelected = false;\n if (typeof action.shape.removeSelection === 'function') action.shape.removeSelection();\n action.shape.draw();\n action.shape.updateClipPath();\n \n redoStack.push(action);\n return;\n }\n \n if (action.type === 'frameAttachment') {\n // Handle frame attachment/detachment undo WITHOUT calling the methods that track undo\n if (action.action === 'attach') {\n // Undo attach: manually remove shape from frame\n const frameIndex = action.frame.containedShapes.indexOf(action.shape);\n if (frameIndex > -1) {\n action.frame.containedShapes.splice(frameIndex, 1);\n action.shape.parentFrame = null;\n \n // Move shape back to main SVG\n if (action.shape.group && action.shape.group.parentNode === action.frame.clipGroup) {\n action.frame.clipGroup.removeChild(action.shape.group);\n svg.appendChild(action.shape.group);\n }\n }\n \n // If shape was moved from another frame, restore it there\n if (action.oldFrame) {\n action.oldFrame.containedShapes.push(action.shape);\n action.shape.parentFrame = action.oldFrame;\n \n // Move to old frame's clipped group\n if (action.shape.group && action.shape.group.parentNode === svg) {\n svg.removeChild(action.shape.group);\n action.oldFrame.clipGroup.appendChild(action.shape.group);\n }\n }\n } else if (action.action === 'detach') {\n // Undo detach: manually add shape back to frame\n if (!action.frame.containedShapes.includes(action.shape)) {\n action.frame.containedShapes.push(action.shape);\n action.shape.parentFrame = action.frame;\n \n // Move to frame's clipped group\n if (action.shape.group && action.shape.group.parentNode === svg) {\n svg.removeChild(action.shape.group);\n action.frame.clipGroup.appendChild(action.shape.group);\n }\n }\n }\n \n // Restore shape state\n action.shape.x = action.shapeState.x;\n action.shape.y = action.shapeState.y;\n action.shape.width = action.shapeState.width;\n action.shape.height = action.shapeState.height;\n action.shape.rotation = action.shapeState.rotation;\n \n if (typeof action.shape.draw === 'function') {\n action.shape.draw();\n }\n \n redoStack.push(action);\n return;\n }\n\n // Handle mode conversion undo (code \u2194 text)\n if (action.type === 'create' && action.shape.type === 'modeConvert') {\n // Undo: remove the new shape, restore the old shape\n const newShape = action.shape.newShape;\n const newElement = action.shape.newElement;\n const oldShape = action.shape.oldShape;\n const oldElement = action.shape.oldElement;\n\n // Remove new shape from DOM and shapes array\n if (newElement && newElement.parentNode) {\n newElement.parentNode.removeChild(newElement);\n }\n const newIdx = shapes.indexOf(newShape);\n if (newIdx !== -1) shapes.splice(newIdx, 1);\n\n // Restore old shape to DOM and shapes array\n if (svg && oldElement) {\n svg.appendChild(oldElement);\n }\n if (oldShape) {\n shapes.push(oldShape);\n }\n\n redoStack.push(action);\n return;\n }\n\n if (action.type === 'create') {\n if (action.shape.type === 'text') {\n // Handle text creation undo\n if (action.shape.element && action.shape.element.parentNode) {\n action.shape.element.parentNode.removeChild(action.shape.element);\n } else if (action.shape.parentNode) {\n action.shape.parentNode.removeChild(action.shape);\n }\n\n // Remove from shapes array\n const idx = shapes.indexOf(action.shape.element || action.shape);\n if (idx !== -1) shapes.splice(idx, 1);\n\n // Clean up any arrow attachments to this text\n if (typeof cleanupAttachments === 'function') {\n cleanupAttachments(action.shape.element || action.shape);\n }\n } else if (action.shape.type === 'image') {\n // Handle image creation undo\n action.shape.remove();\n } else if (action.shape.type === 'icon') {\n // Handle icon creation undo - call the remove method\n action.shape.remove();\n } else {\n // Handle other shape creation undo\n const idx = shapes.indexOf(action.shape);\n if (idx !== -1) shapes.splice(idx, 1);\n if (action.shape.group && action.shape.group.parentNode) {\n action.shape.group.parentNode.removeChild(action.shape.group);\n }\n \n // Handle frame cleanup\n if (action.shape.shapeName === 'frame') {\n action.shape.destroy();\n }\n }\n redoStack.push(action);\n return;\n}\n \n if (action.type === 'delete') {\n if (action.shape.type === 'text') {\n // Handle text deletion undo\n if (svg) {\n svg.appendChild(action.shape.element || action.shape);\n // Add back to shapes array\n shapes.push(action.shape.element || action.shape);\n }\n \n // Restore arrow attachments if any existed\n if (action.affectedArrows) {\n action.affectedArrows.forEach(arrowData => {\n const arrow = arrowData.arrow;\n // Restore the old attachment state\n arrow.restoreAttachmentState(arrowData.oldAttachments);\n });\n }\n } else if (action.shape.type === 'image') {\n // Handle image deletion undo\n action.shape.restore();\n } else {\n // Handle other shape deletion undo\n shapes.push(action.shape);\n if (svg) {\n svg.appendChild(action.shape.group);\n }\n\n // Issue #24 bug #7: rehydrate frame state. The delete path\n // orphaned the frame (removed <g>, clipGroup, clipPath from\n // DOM) but kept the JS object intact. Re-attach clipGroup +\n // clipPath, then re-parent every child from the snapshot via\n // addShapeToFrame. Skip children that were subsequently\n // deleted (they'll get re-added when their own delete action\n // is undone in turn).\n if (action.shape.shapeName === 'frame' && svg) {\n if (action.shape.clipGroup && !action.shape.clipGroup.parentNode) {\n svg.appendChild(action.shape.clipGroup);\n }\n if (action.shape.clipPath && !action.shape.clipPath.parentNode) {\n const defs = svg.querySelector('defs');\n if (defs) defs.appendChild(action.shape.clipPath);\n else svg.insertBefore(action.shape.clipPath, svg.firstChild);\n }\n if (action.childSnapshot && Array.isArray(action.childSnapshot)) {\n for (const child of action.childSnapshot) {\n if (!child) continue;\n if (shapes.indexOf(child) === -1) continue;\n if (typeof action.shape.addShapeToFrame === 'function') {\n action.shape.addShapeToFrame(child);\n }\n }\n }\n }\n }\n redoStack.push(action);\n return;\n }\n \n if (action.type === 'transform') {\n // Handle frame attachment changes first\n if (action.frameAttachment) {\n // Use manual frame operations to avoid undo recursion\n if (action.frameAttachment.newFrame) {\n const frameIndex = action.frameAttachment.newFrame.containedShapes.indexOf(action.shape);\n if (frameIndex > -1) {\n action.frameAttachment.newFrame.containedShapes.splice(frameIndex, 1);\n if (action.shape.group && action.shape.group.parentNode === action.frameAttachment.newFrame.clipGroup) {\n action.frameAttachment.newFrame.clipGroup.removeChild(action.shape.group);\n svg.appendChild(action.shape.group);\n }\n }\n }\n if (action.frameAttachment.oldFrame) {\n if (!action.frameAttachment.oldFrame.containedShapes.includes(action.shape)) {\n action.frameAttachment.oldFrame.containedShapes.push(action.shape);\n action.shape.parentFrame = action.frameAttachment.oldFrame;\n if (action.shape.group && action.shape.group.parentNode === svg) {\n svg.removeChild(action.shape.group);\n action.frameAttachment.oldFrame.clipGroup.appendChild(action.shape.group);\n }\n }\n } else {\n action.shape.parentFrame = null;\n }\n }\n \n if (action.shape.type === 'text') {\n // Enhanced text transform undo\n const textElement = (action.shape.element || action.shape).querySelector('text');\n if (textElement && action.oldPos.fontSize !== undefined) {\n textElement.setAttribute('font-size', action.oldPos.fontSize + 'px');\n }\n \n // Restore position and rotation\n const centerX = textElement ? textElement.getBBox().x + textElement.getBBox().width / 2 : 0;\n const centerY = textElement ? textElement.getBBox().y + textElement.getBBox().height / 2 : 0;\n \n (action.shape.element || action.shape).setAttribute('transform', \n `translate(${action.oldPos.x}, ${action.oldPos.y}) rotate(${action.oldPos.rotation}, ${centerX}, ${centerY})`\n );\n \n (action.shape.element || action.shape).setAttribute('data-x', action.oldPos.x);\n (action.shape.element || action.shape).setAttribute('data-y', action.oldPos.y);\n \n // Update attached arrows after text undo\n if (action.affectedArrows) {\n action.affectedArrows.forEach(arrowData => {\n const arrow = arrowData.arrow;\n // Restore arrow attachments to old state\n arrow.restoreAttachmentState(arrowData.oldAttachments);\n \n // Store current state for redo\n arrowData.newPoints = {\n startPoint: { ...arrow.startPoint },\n endPoint: { ...arrow.endPoint }\n };\n arrowData.newAttachments = arrow.getAttachmentState();\n });\n }\n \n // Update feedback if selected\n if (selectedElement === (action.shape.element || action.shape) && updateSelectionFeedback) {\n setTimeout(updateSelectionFeedback, 0);\n }\n } else if (action.shape.type === 'image') {\n // Enhanced image transform undo\n action.shape.restore(action.oldPos);\n \n // Update attached arrows after image undo\n if (action.affectedArrows) {\n action.affectedArrows.forEach(arrowData => {\n const arrow = arrowData.arrow;\n // Restore arrow attachments to old state\n arrow.restoreAttachmentState(arrowData.oldAttachments);\n \n // Store current state for redo\n arrowData.newPoints = {\n startPoint: { ...arrow.startPoint },\n endPoint: { ...arrow.endPoint }\n };\n arrowData.newAttachments = arrow.getAttachmentState();\n });\n }\n } else if (action.shape.shapeName === 'circle') {\n // Enhanced circle transform undo\n action.shape.x = action.oldPos.x;\n action.shape.y = action.oldPos.y;\n action.shape.rx = action.oldPos.rx;\n action.shape.ry = action.oldPos.ry;\n action.shape.rotation = action.oldPos.rotation;\n action.shape.isSelected = false;\n if (typeof action.shape.removeSelection === 'function') action.shape.removeSelection();\n action.shape.draw();\n\n // Update attached arrows after circle undo\n if (action.affectedArrows) {\n action.affectedArrows.forEach(arrowData => {\n const arrow = arrowData.arrow;\n // Restore arrow attachments to old state\n arrow.restoreAttachmentState(arrowData.oldAttachments);\n \n // Store current state for redo\n arrowData.newPoints = {\n startPoint: { ...arrow.startPoint },\n endPoint: { ...arrow.endPoint }\n };\n arrowData.newAttachments = arrow.getAttachmentState();\n });\n }\n } else if (action.shape.shapeName === 'line') {\n // Enhanced line transform undo with curve support\n action.shape.startPoint = { x: action.oldPos.startPoint.x, y: action.oldPos.startPoint.y };\n action.shape.endPoint = { x: action.oldPos.endPoint.x, y: action.oldPos.endPoint.y };\n \n // Restore curve state\n action.shape.isCurved = action.oldPos.isCurved || false;\n if (action.oldPos.controlPoint) {\n action.shape.controlPoint = { x: action.oldPos.controlPoint.x, y: action.oldPos.controlPoint.y };\n } else {\n action.shape.controlPoint = null;\n }\n \n // Handle frame attachment changes\n if (action.frameAttachment) {\n // Remove from new frame if it exists\n if (action.frameAttachment.newFrame) {\n const frameIndex = action.frameAttachment.newFrame.containedShapes.indexOf(action.shape);\n if (frameIndex > -1) {\n action.frameAttachment.newFrame.containedShapes.splice(frameIndex, 1);\n if (action.shape.group && action.shape.group.parentNode === action.frameAttachment.newFrame.clipGroup) {\n action.frameAttachment.newFrame.clipGroup.removeChild(action.shape.group);\n svg.appendChild(action.shape.group);\n }\n }\n }\n \n // Add back to old frame if it exists\n if (action.frameAttachment.oldFrame) {\n if (!action.frameAttachment.oldFrame.containedShapes.includes(action.shape)) {\n action.frameAttachment.oldFrame.containedShapes.push(action.shape);\n action.shape.parentFrame = action.frameAttachment.oldFrame;\n if (action.shape.group && action.shape.group.parentNode === svg) {\n svg.removeChild(action.shape.group);\n action.frameAttachment.oldFrame.clipGroup.appendChild(action.shape.group);\n }\n }\n } else {\n action.shape.parentFrame = null;\n }\n }\n \n action.shape.isSelected = false;\n if (typeof action.shape.removeSelection === 'function') action.shape.removeSelection();\n action.shape.draw();\n }\n else if (action.shape.shapeName === 'arrow') {\n // Enhanced arrow transform undo with attachment restoration\n action.shape.startPoint = { x: action.oldPos.startPoint.x, y: action.oldPos.startPoint.y };\n action.shape.endPoint = { x: action.oldPos.endPoint.x, y: action.oldPos.endPoint.y };\n action.shape.controlPoint1 = action.oldPos.controlPoint1 ? \n { x: action.oldPos.controlPoint1.x, y: action.oldPos.controlPoint1.y } : null;\n action.shape.controlPoint2 = action.oldPos.controlPoint2 ? \n { x: action.oldPos.controlPoint2.x, y: action.oldPos.controlPoint2.y } : null;\n \n // Restore attachment state\n if (action.oldPos.attachments) {\n action.shape.restoreAttachmentState(action.oldPos.attachments);\n } else {\n // Clear attachments if none existed before\n action.shape.attachedToStart = null;\n action.shape.attachedToEnd = null;\n }\n \n action.shape.isSelected = false;\n action.shape.draw();\n \n\n \n } \n else if (action.shape.type === 'icon') {\n \n action.shape.restore(action.oldPos);\n \n // Update attached arrows after icon undo\n if (action.affectedArrows) {\n action.affectedArrows.forEach(arrowData => {\n const arrow = arrowData.arrow;\n // Restore arrow attachments to old state\n arrow.restoreAttachmentState(arrowData.oldAttachments);\n \n // Store current state for redo\n arrowData.newPoints = {\n startPoint: { ...arrow.startPoint },\n endPoint: { ...arrow.endPoint }\n };\n arrowData.newAttachments = arrow.getAttachmentState();\n });\n }\n }\n else if (action.shape.shapeName === 'freehandStroke') {\n // Handle freehand stroke transform undo\n action.shape.points = JSON.parse(JSON.stringify(action.oldPos.points));\n action.shape.rotation = action.oldPos.rotation;\n action.shape.isSelected = false;\n if (typeof action.shape.removeSelection === 'function') action.shape.removeSelection();\n action.shape.draw();\n } else if (action.shape.shapeName === \"rectangle\") {\n action.shape.x = action.oldPos.x;\n action.shape.y = action.oldPos.y;\n action.shape.height = action.oldPos.height;\n action.shape.width = action.oldPos.width;\n action.shape.rotation = action.oldPos.rotation;\n action.shape.isSelected = false;\n if (typeof action.shape.removeSelection === 'function') action.shape.removeSelection();\n action.shape.draw();\n\n // Update attached arrows after rectangle undo\n if (action.affectedArrows) {\n action.affectedArrows.forEach(arrowData => {\n const arrow = arrowData.arrow;\n arrow.restoreAttachmentState(arrowData.oldAttachments);\n arrowData.newPoints = {\n startPoint: { ...arrow.startPoint },\n endPoint: { ...arrow.endPoint }\n };\n arrowData.newAttachments = arrow.getAttachmentState();\n });\n }\n }\n redoStack.push(action);\n return;\n }\n \n if (action.type === 'optionsChange') {\n if (action.shape.type === 'text') {\n // Handle text options change undo\n const textElement = (action.shape.element || action.shape).querySelector('text');\n if (textElement) {\n if (action.oldOptions.color) textElement.setAttribute('fill', action.oldOptions.color);\n if (action.oldOptions.font) textElement.setAttribute('font-family', action.oldOptions.font);\n if (action.oldOptions.size) textElement.setAttribute('font-size', action.oldOptions.size);\n if (action.oldOptions.align) textElement.setAttribute('text-anchor', action.oldOptions.align);\n \n // Update feedback if selected\n if (selectedElement === (action.shape.element || action.shape) && updateSelectionFeedback) {\n setTimeout(updateSelectionFeedback, 0);\n }\n }\n } else if (action.shape.shapeName === 'arrow') {\n // Handle arrow options change undo\n action.shape.options = { ...action.oldOptions };\n action.shape.arrowOutlineStyle = action.oldOptions.arrowOutlineStyle;\n action.shape.arrowHeadStyle = action.oldOptions.arrowHeadStyle;\n action.shape.arrowCurved = action.oldOptions.arrowCurved;\n action.shape.arrowCurveAmount = action.oldOptions.arrowCurveAmount;\n action.shape.draw();\n } else {\n // Handle other shape options change undo\n action.shape.options = action.oldOptions;\n action.shape.draw();\n }\n redoStack.push(action);\n return;\n }\n } finally {\n refreshSelectionAfterAction();\n notifyCollaboration();\n }\n}\n\nexport function redo() {\n if (redoStack.length === 0) return;\n const action = redoStack.pop();\n try {\n if (action.type === 'frameTransform') {\n // Handle frame transformation redo\n action.shape.x = action.newPos.x;\n action.shape.y = action.newPos.y;\n action.shape.width = action.newPos.width;\n action.shape.height = action.newPos.height;\n action.shape.rotation = action.newPos.rotation;\n action.shape.frameName = action.newPos.frameName;\n \n // Restore contained shapes to their new positions\n action.containedShapes.forEach(shapeData => {\n const shape = shapeData.shape;\n shape.x = shapeData.newState.x;\n shape.y = shapeData.newState.y;\n shape.width = shapeData.newState.width;\n shape.height = shapeData.newState.height;\n shape.rotation = shapeData.newState.rotation;\n \n if (typeof shape.draw === 'function') {\n shape.draw();\n }\n });\n \n action.shape.isSelected = false;\n if (typeof action.shape.removeSelection === 'function') action.shape.removeSelection();\n action.shape.draw();\n action.shape.updateClipPath();\n \n undoStack.push(action);\n return;\n }\n\n \n if (action.type === 'frameAttachment') {\n // Handle frame attachment/detachment redo WITHOUT calling the methods that track undo\n if (action.action === 'attach') {\n // Redo attach: manually add shape to frame\n if (action.oldFrame) {\n // Remove from old frame\n const oldFrameIndex = action.oldFrame.containedShapes.indexOf(action.shape);\n if (oldFrameIndex > -1) {\n action.oldFrame.containedShapes.splice(oldFrameIndex, 1);\n if (action.shape.group && action.shape.group.parentNode === action.oldFrame.clipGroup) {\n action.oldFrame.clipGroup.removeChild(action.shape.group);\n svg.appendChild(action.shape.group);\n }\n }\n }\n \n // Add to new frame\n if (!action.frame.containedShapes.includes(action.shape)) {\n action.frame.containedShapes.push(action.shape);\n action.shape.parentFrame = action.frame;\n \n if (action.shape.group && action.shape.group.parentNode === svg) {\n svg.removeChild(action.shape.group);\n action.frame.clipGroup.appendChild(action.shape.group);\n }\n }\n } else if (action.action === 'detach') {\n // Redo detach: manually remove shape from frame\n const frameIndex = action.frame.containedShapes.indexOf(action.shape);\n if (frameIndex > -1) {\n action.frame.containedShapes.splice(frameIndex, 1);\n action.shape.parentFrame = null;\n \n if (action.shape.group && action.shape.group.parentNode === action.frame.clipGroup) {\n action.frame.clipGroup.removeChild(action.shape.group);\n svg.appendChild(action.shape.group);\n }\n }\n }\n \n if (typeof action.shape.draw === 'function') {\n action.shape.draw();\n }\n \n undoStack.push(action);\n return;\n }\n\n // Handle mode conversion redo (code \u2194 text)\n if (action.type === 'create' && action.shape.type === 'modeConvert') {\n // Redo: remove the old shape, restore the new shape\n const newShape = action.shape.newShape;\n const newElement = action.shape.newElement;\n const oldShape = action.shape.oldShape;\n const oldElement = action.shape.oldElement;\n\n // Remove old shape from DOM and shapes array\n if (oldElement && oldElement.parentNode) {\n oldElement.parentNode.removeChild(oldElement);\n }\n const oldIdx = shapes.indexOf(oldShape);\n if (oldIdx !== -1) shapes.splice(oldIdx, 1);\n\n // Restore new shape to DOM and shapes array\n if (svg && newElement) {\n svg.appendChild(newElement);\n }\n if (newShape) {\n shapes.push(newShape);\n }\n\n undoStack.push(action);\n return;\n }\n\n if (action.type === 'create') {\n if (action.shape.type === 'text') {\n // Handle text creation redo\n if (svg) {\n svg.appendChild(action.shape.element || action.shape);\n // Add back to shapes array\n shapes.push(action.shape.element || action.shape);\n }\n }\n else if (action.shape.type === 'image') {\n // Handle image creation redo\n action.shape.restore();\n } else if (action.shape.type === 'icon') {\n // Handle icon creation redo - append the group, not the shape object\n if (svg && action.shape.group) {\n svg.appendChild(action.shape.group);\n }\n // Add back to shapes array\n if (shapes.indexOf(action.shape) === -1) {\n shapes.push(action.shape);\n }\n } else {\n // Handle other shape creation redo\n shapes.push(action.shape);\n if (svg) {\n svg.appendChild(action.shape.group);\n }\n }\n undoStack.push(action);\n return;\n}\n \n if (action.type === 'delete') {\n if (action.shape.type === 'text') {\n // Handle text deletion redo\n if ((action.shape.element || action.shape).parentNode) {\n (action.shape.element || action.shape).parentNode.removeChild(action.shape.element || action.shape);\n }\n // Remove from shapes array\n const idx = shapes.indexOf(action.shape.element || action.shape);\n if (idx !== -1) shapes.splice(idx, 1);\n \n // Clean up arrow attachments again\n if (action.affectedArrows) {\n action.affectedArrows.forEach(arrowData => {\n const arrow = arrowData.arrow;\n // Detach from the deleted text\n if (arrow.attachedToStart && arrow.attachedToStart.shape === (action.shape.element || action.shape)) {\n arrow.detachFromShape(true);\n }\n if (arrow.attachedToEnd && arrow.attachedToEnd.shape === (action.shape.element || action.shape)) {\n arrow.detachFromShape(false);\n }\n arrow.draw();\n });\n }\n }\n else if (action.shape.type === 'image') {\n // Handle image deletion redo\n action.shape.remove();\n } else {\n // Handle other shape deletion redo\n const idx = shapes.indexOf(action.shape);\n if (idx !== -1) shapes.splice(idx, 1);\n\n // Issue #24 bug #7: for a regular frame, re-orphan instead of\n // destroy() \u2014 releases children visually, detaches the frame's\n // own DOM bits, but keeps the JS object and child references\n // intact so a subsequent undo can rehydrate again.\n if (action.shape.shapeName === 'frame' && !action.shape._diagramType && action.childSnapshot) {\n for (const child of action.childSnapshot) {\n if (!child) continue;\n const el = child.group || child.element;\n if (el && svg) {\n if (action.shape.clipGroup && el.parentNode === action.shape.clipGroup) {\n action.shape.clipGroup.removeChild(el);\n }\n if (el.parentNode !== svg) svg.appendChild(el);\n }\n child.parentFrame = null;\n delete child.isBeingMovedByFrame;\n }\n action.shape.containedShapes = [];\n if (action.shape.group && action.shape.group.parentNode) action.shape.group.parentNode.removeChild(action.shape.group);\n if (action.shape.clipGroup && action.shape.clipGroup.parentNode) action.shape.clipGroup.parentNode.removeChild(action.shape.clipGroup);\n if (action.shape.clipPath && action.shape.clipPath.parentNode) action.shape.clipPath.parentNode.removeChild(action.shape.clipPath);\n } else {\n if (action.shape.group && action.shape.group.parentNode) {\n action.shape.group.parentNode.removeChild(action.shape.group);\n }\n // Diagram frame OR no snapshot \u2192 fall back to destroy().\n if (action.shape.shapeName === 'frame' && typeof action.shape.destroy === 'function') {\n action.shape.destroy();\n }\n }\n }\n undoStack.push(action);\n return;\n }\n \n if (action.type === 'transform') {\n // Handle frame attachment changes first\n if (action.frameAttachment) {\n // Use manual frame operations to avoid undo recursion\n if (action.frameAttachment.oldFrame) {\n const oldFrameIndex = action.frameAttachment.oldFrame.containedShapes.indexOf(action.shape);\n if (oldFrameIndex > -1) {\n action.frameAttachment.oldFrame.containedShapes.splice(oldFrameIndex, 1);\n if (action.shape.group && action.shape.group.parentNode === action.frameAttachment.oldFrame.clipGroup) {\n action.frameAttachment.oldFrame.clipGroup.removeChild(action.shape.group);\n svg.appendChild(action.shape.group);\n }\n }\n }\n if (action.frameAttachment.newFrame) {\n if (!action.frameAttachment.newFrame.containedShapes.includes(action.shape)) {\n action.frameAttachment.newFrame.containedShapes.push(action.shape);\n action.shape.parentFrame = action.frameAttachment.newFrame;\n if (action.shape.group && action.shape.group.parentNode === svg) {\n svg.removeChild(action.shape.group);\n action.frameAttachment.newFrame.clipGroup.appendChild(action.shape.group);\n }\n }\n } else {\n action.shape.parentFrame = null;\n }\n }\n \n if (action.shape.type === 'text') {\n // Enhanced text transform redo\n const textElement = (action.shape.element || action.shape).querySelector('text');\n if (textElement && action.newPos.fontSize !== undefined) {\n textElement.setAttribute('font-size', action.newPos.fontSize + 'px');\n }\n \n // Restore position and rotation\n const centerX = textElement ? textElement.getBBox().x + textElement.getBBox().width / 2 : 0;\n const centerY = textElement ? textElement.getBBox().y + textElement.getBBox().height / 2 : 0;\n \n (action.shape.element || action.shape).setAttribute('transform', \n `translate(${action.newPos.x}, ${action.newPos.y}) rotate(${action.newPos.rotation}, ${centerX}, ${centerY})`\n );\n \n (action.shape.element || action.shape).setAttribute('data-x', action.newPos.x);\n (action.shape.element || action.shape).setAttribute('data-y', action.newPos.y);\n \n // Update attached arrows after text redo\n if (action.affectedArrows) {\n action.affectedArrows.forEach(arrowData => {\n const arrow = arrowData.arrow;\n // Restore arrow attachments to new state\n if (arrowData.newAttachments) {\n arrow.restoreAttachmentState(arrowData.newAttachments);\n } else {\n // If no new attachments stored, recalculate based on current text position\n arrow.updateAttachments();\n }\n });\n }\n \n // Update feedback if selected\n if (selectedElement === (action.shape.element || action.shape) && updateSelectionFeedback) {\n setTimeout(updateSelectionFeedback, 0);\n }\n } else if (action.shape.type === 'image') {\n // Enhanced image transform redo\n action.shape.restore(action.newPos);\n \n // Update attached arrows after image redo\n if (action.affectedArrows) {\n action.affectedArrows.forEach(arrowData => {\n const arrow = arrowData.arrow;\n // Restore arrow attachments to new state\n if (arrowData.newAttachments) {\n arrow.restoreAttachmentState(arrowData.newAttachments);\n } else {\n // If no new attachments stored, recalculate based on current image position\n arrow.updateAttachments();\n }\n });\n }\n } else if (action.shape.shapeName === 'circle') {\n // Enhanced circle transform redo\n action.shape.x = action.newPos.x;\n action.shape.y = action.newPos.y;\n action.shape.rx = action.newPos.rx;\n action.shape.ry = action.newPos.ry;\n action.shape.rotation = action.newPos.rotation;\n action.shape.isSelected = false;\n if (typeof action.shape.removeSelection === 'function') action.shape.removeSelection();\n action.shape.draw();\n\n // Update attached arrows after circle redo\n if (action.affectedArrows) {\n action.affectedArrows.forEach(arrowData => {\n const arrow = arrowData.arrow;\n // Restore arrow attachments to new state\n if (arrowData.newAttachments) {\n arrow.restoreAttachmentState(arrowData.newAttachments);\n } else {\n // If no new attachments stored, recalculate based on current circle position\n arrow.updateAttachments();\n }\n });\n }\n } else if (action.shape.shapeName === 'line') {\n // Enhanced line transform redo with curve support\n action.shape.startPoint = { x: action.newPos.startPoint.x, y: action.newPos.startPoint.y };\n action.shape.endPoint = { x: action.newPos.endPoint.x, y: action.newPos.endPoint.y };\n \n // Restore curve state\n action.shape.isCurved = action.newPos.isCurved || false;\n if (action.newPos.controlPoint) {\n action.shape.controlPoint = { x: action.newPos.controlPoint.x, y: action.newPos.controlPoint.y };\n } else {\n action.shape.controlPoint = null;\n }\n \n // Handle frame attachment changes\n if (action.frameAttachment) {\n // Remove from old frame if it exists\n if (action.frameAttachment.oldFrame) {\n const oldFrameIndex = action.frameAttachment.oldFrame.containedShapes.indexOf(action.shape);\n if (oldFrameIndex > -1) {\n action.frameAttachment.oldFrame.containedShapes.splice(oldFrameIndex, 1);\n if (action.shape.group && action.shape.group.parentNode === action.frameAttachment.oldFrame.clipGroup) {\n action.frameAttachment.oldFrame.clipGroup.removeChild(action.shape.group);\n svg.appendChild(action.shape.group);\n }\n }\n }\n \n // Add to new frame if it exists\n if (action.frameAttachment.newFrame) {\n if (!action.frameAttachment.newFrame.containedShapes.includes(action.shape)) {\n action.frameAttachment.newFrame.containedShapes.push(action.shape);\n action.shape.parentFrame = action.frameAttachment.newFrame;\n if (action.shape.group && action.shape.group.parentNode === svg) {\n svg.removeChild(action.shape.group);\n action.frameAttachment.newFrame.clipGroup.appendChild(action.shape.group);\n }\n }\n } else {\n action.shape.parentFrame = null;\n }\n }\n \n action.shape.isSelected = false;\n if (typeof action.shape.removeSelection === 'function') action.shape.removeSelection();\n action.shape.draw();\n }\n else if (action.shape.shapeName === 'arrow') {\n // Enhanced arrow transform redo with attachment restoration\n action.shape.startPoint = { x: action.newPos.startPoint.x, y: action.newPos.startPoint.y };\n action.shape.endPoint = { x: action.newPos.endPoint.x, y: action.newPos.endPoint.y };\n action.shape.controlPoint1 = action.newPos.controlPoint1 ? \n { x: action.newPos.controlPoint1.x, y: action.newPos.controlPoint1.y } : null;\n action.shape.controlPoint2 = action.newPos.controlPoint2 ? \n { x: action.newPos.controlPoint2.x, y: action.newPos.controlPoint2.y } : null;\n \n // Restore attachment state\n if (action.newPos.attachments) {\n action.shape.restoreAttachmentState(action.newPos.attachments);\n } else {\n // Clear attachments if none should exist\n action.shape.attachedToStart = null;\n action.shape.attachedToEnd = null;\n }\n \n action.shape.isSelected = false;\n action.shape.draw();\n \n } \n else if (action.shape.type === 'icon') {\n action.shape.restore(action.newPos);\n \n // Update attached arrows after icon redo\n if (action.affectedArrows) {\n action.affectedArrows.forEach(arrowData => {\n const arrow = arrowData.arrow;\n // Restore arrow attachments to new state\n if (arrowData.newAttachments) {\n arrow.restoreAttachmentState(arrowData.newAttachments);\n } else {\n // If no new attachments stored, recalculate based on current icon position\n arrow.updateAttachments();\n }\n });\n }\n }\n else if (action.shape.shapeName === 'freehandStroke') {\n // Handle freehand stroke transform redo\n action.shape.points = JSON.parse(JSON.stringify(action.newPos.points));\n action.shape.rotation = action.newPos.rotation;\n action.shape.isSelected = false;\n if (typeof action.shape.removeSelection === 'function') action.shape.removeSelection();\n action.shape.draw();\n } else if (action.shape.shapeName === \"rectangle\") {\n // Enhanced rectangle transform redo\n action.shape.x = action.newPos.x;\n action.shape.y = action.newPos.y;\n action.shape.height = action.newPos.height;\n action.shape.width = action.newPos.width;\n action.shape.rotation = action.newPos.rotation;\n action.shape.isSelected = false;\n if (typeof action.shape.removeSelection === 'function') action.shape.removeSelection();\n action.shape.draw();\n\n // Update attached arrows after rectangle redo\n if (action.affectedArrows) {\n action.affectedArrows.forEach(arrowData => {\n const arrow = arrowData.arrow;\n // Restore arrow attachments to new state\n if (arrowData.newAttachments) {\n arrow.restoreAttachmentState(arrowData.newAttachments);\n } else {\n // If no new attachments stored, recalculate based on current rectangle position\n arrow.updateAttachments();\n }\n });\n }\n }\n undoStack.push(action);\n return;\n }\n \n if (action.type === 'optionsChange') {\n if (action.shape.type === 'text') {\n // Handle text options change redo\n const textElement = (action.shape.element || action.shape).querySelector('text');\n if (textElement) {\n if (action.newOptions.color) textElement.setAttribute('fill', action.newOptions.color);\n if (action.newOptions.font) textElement.setAttribute('font-family', action.newOptions.font);\n if (action.newOptions.size) textElement.setAttribute('font-size', action.newOptions.size);\n if (action.newOptions.align) textElement.setAttribute('text-anchor', action.newOptions.align);\n \n // Update feedback if selected\n if (selectedElement === (action.shape.element || action.shape) && updateSelectionFeedback) {\n setTimeout(updateSelectionFeedback, 0);\n }\n }\n } else if (action.shape.shapeName === 'arrow') {\n // Handle arrow options change redo - we need to get current options as newOptions\n const currentOptions = {\n ...action.shape.options,\n arrowOutlineStyle: action.shape.arrowOutlineStyle,\n arrowHeadStyle: action.shape.arrowHeadStyle,\n arrowCurved: action.shape.arrowCurved,\n arrowCurveAmount: action.shape.arrowCurveAmount\n };\n \n // Store current state for potential future undo\n action.newOptions = currentOptions;\n \n action.shape.draw();\n } else {\n // Handle other shape options change redo - we need to get current options as newOptions\n action.newOptions = action.shape.options;\n action.shape.draw();\n }\n undoStack.push(action);\n return;\n }\n } finally {\n refreshSelectionAfterAction();\n notifyCollaboration();\n }\n}\n\n// Optional: Keyboard shortcuts\ndocument.addEventListener('keydown', (e) => {\n if ((e.ctrlKey || e.metaKey) && e.key === 'z') {\n e.preventDefault();\n undo();\n }\n if ((e.ctrlKey || e.metaKey) && (e.key === 'y' || (e.shiftKey && e.key === 'z'))) {\n e.preventDefault();\n redo();\n }\n});\n\n// Attach to buttons\ndocument.getElementById('undo')?.addEventListener('click', undo);\ndocument.getElementById('redo')?.addEventListener('click', redo);\n\n// Expose globally for plain scripts\nwindow.pushCreateAction = pushCreateAction;\nwindow.pushDeleteAction = pushDeleteAction;\nwindow.pushDeleteActionWithAttachments = pushDeleteActionWithAttachments;\nwindow.pushTransformAction = pushTransformAction;\nwindow.pushOptionsChangeAction = pushOptionsChangeAction;\nwindow.pushCreateActionWithAttachments = pushCreateActionWithAttachments;\nwindow.undo = undo;\nwindow.redo = redo;\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/shapes/Circle.js"],
4
- "sourcesContent": ["/* eslint-disable */\n// Circle shape class - extracted from drawCircle.js\n// Depends on globals: svg, shapes, rough, currentShape, currentZoom, rc\n\nconst rc = rough.svg(svg);\nlet isDraggingShapeCircle = false;\nlet isResizingShapeCircle = false;\nlet isRotatingShapeCircle = false;\nlet hoveredFrameCircle = null;\nconst colorOptionsCircle = document.querySelectorAll(\".circleStrokeSpan\");\nconst backgroundColorOptionsCircle = document.querySelectorAll(\".circleBackgroundSpan\");\nconst fillStyleOptionsCircle = document.querySelectorAll(\".circleFillStyleSpan\");\nconst strokeThicknessValueCircle = document.querySelectorAll(\".circleStrokeThickSpan\");\nconst outlineStyleValueCircle = document.querySelectorAll(\".circleOutlineStyle\");\n\nclass Circle {\n constructor(x, y, rx, ry, options = {}) {\n this.x = x; \n this.y = y; \n this.rx = rx; \n this.ry = ry; \n this.options = {\n roughness: 1.5,\n stroke: \"#fff\",\n strokeWidth: 2,\n fill: \"transparent\",\n fillStyle: \"none\",\n strokeDasharray: \"\",\n ...options\n };\n this.element = null;\n this.isSelected = false;\n this.rotation = 0;\n this.group = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n this.anchors = [];\n this.rotationAnchor = null;\n this.selectionPadding = 8;\n this.selectionOutline = null;\n this.shapeName = \"circle\";\n this.shapeID = `circle-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n this.group.setAttribute('id', this.shapeID);\n\n // Frame attachment properties\n this.parentFrame = null;\n\n // Embedded label support\n this.label = options.label || '';\n this.labelElement = null;\n this.labelColor = options.labelColor || '#e0e0e0';\n this.labelFontSize = options.labelFontSize || 14;\n this._isEditingLabel = false;\n this._hitArea = null;\n this._labelBg = null;\n\n // Shading / gradient support for research paper style diagrams\n this.shadeColor = options.shadeColor || null;\n this.shadeOpacity = options.shadeOpacity !== undefined ? options.shadeOpacity : 0.15;\n this.shadeDirection = options.shadeDirection || 'bottom';\n this._shadeEllipse = null;\n this._shadeGradient = null;\n\n if(!this.group.parentNode) {\n svg.appendChild(this.group);\n }\n this._lastDrawn = {\n width: null,\n height: null,\n options: null\n };\n this._setupLabelDblClick();\n this.draw();\n }\n\n // Add width and height properties for frame compatibility\n get width() {\n return this.rx * 2;\n }\n \n set width(value) {\n this.rx = value / 2;\n }\n \n get height() {\n return this.ry * 2;\n }\n \n set height(value) {\n this.ry = value / 2;\n }\n\n draw() {\n const childrenToRemove = [];\n const preserveSet = this._skipAnchors ? new Set([...this.anchors, this.selectionOutline, this.rotationAnchor].filter(Boolean)) : null;\n for (let i = 0; i < this.group.children.length; i++) {\n const child = this.group.children[i];\n if (child !== this.element && child !== this.labelElement && child !== this._hitArea && child !== this._labelBg && child !== this._shadeEllipse) {\n if (preserveSet && preserveSet.has(child)) continue;\n childrenToRemove.push(child);\n }\n }\n childrenToRemove.forEach(child => this.group.removeChild(child));\n const optionsString = JSON.stringify(this.options);\n const isInitialDraw = this.element === null;\n const sizeChanged = this.rx !== this._lastDrawn.rx || this.ry !== this._lastDrawn.ry;\n const optionsChanged = optionsString !== this._lastDrawn.options;\n if (isInitialDraw || optionsChanged || sizeChanged) {\n if (this.element && this.element.parentNode === this.group) {\n this.group.removeChild(this.element);\n }\n\n const roughEllipse = rc.ellipse(0, 0, this.rx * 2, this.ry * 2, this.options);\n this.element = roughEllipse;\n this.group.appendChild(roughEllipse);\n\n this._lastDrawn.rx = this.rx;\n this._lastDrawn.ry = this.ry;\n this._lastDrawn.options = optionsString;\n }\n\n // Hit area for dblclick detection\n if (!this._hitArea) {\n this._hitArea = document.createElementNS('http://www.w3.org/2000/svg', 'ellipse');\n this._hitArea.setAttribute('fill', 'transparent');\n this._hitArea.setAttribute('stroke', 'none');\n this._hitArea.setAttribute('style', 'pointer-events: all;');\n this.group.insertBefore(this._hitArea, this.group.firstChild);\n }\n this._hitArea.setAttribute('cx', 0);\n this._hitArea.setAttribute('cy', 0);\n this._hitArea.setAttribute('rx', this.rx);\n this._hitArea.setAttribute('ry', this.ry);\n\n // Shading / gradient overlay\n this._updateShade();\n\n // Update embedded label\n this._updateLabelElement();\n\n this.group.setAttribute('transform', `translate(${this.x}, ${this.y}) rotate(${this.rotation}, 0, 0)`);\n if (this.isSelected) {\n if (this._skipAnchors) {\n this.updateSelectionControls();\n } else {\n this.addAnchors();\n }\n }\n if (!this.group.parentNode) {\n svg.appendChild(this.group);\n }\n }\n\n move(dx, dy) {\n this.x += dx;\n this.y += dy;\n\n // Fast path: just update the transform \u2014 no need to rebuild RoughJS element\n this.group.setAttribute('transform', `translate(${this.x}, ${this.y}) rotate(${this.rotation}, 0, 0)`);\n\n this.updateAttachedArrows();\n\n // Only update frame containment if we're actively dragging the shape itself\n // and not being moved by a parent frame\n if (isDraggingShapeCircle && !this.isBeingMovedByFrame) {\n this.updateFrameContainment();\n }\n }\n\n updateFrameContainment() {\n // Don't update if we're being moved by a frame\n if (this.isBeingMovedByFrame) return;\n \n let targetFrame = null;\n \n // Find which frame this shape is over\n shapes.forEach(shape => {\n if (shape.shapeName === 'frame' && shape.isShapeInFrame(this)) {\n targetFrame = shape;\n }\n });\n \n // If we have a parent frame and we're being dragged, temporarily remove clipping\n if (this.parentFrame && isDraggingShapeCircle) {\n this.parentFrame.temporarilyRemoveFromFrame(this);\n }\n \n // Update frame highlighting\n if (hoveredFrameCircle && hoveredFrameCircle !== targetFrame) {\n hoveredFrameCircle.removeHighlight();\n }\n \n if (targetFrame && targetFrame !== hoveredFrameCircle) {\n targetFrame.highlightFrame();\n }\n \n hoveredFrameCircle = targetFrame;\n }\n\n getRotatedCursor(direction, angle) {\n const directions = ['ns', 'nesw', 'ew', 'nwse'];\n angle = angle % 360;\n if (angle < 0) angle += 360;\n\n const baseDirectionMap = {\n '0': 'nwse', '1': 'nesw', \n '2': 'nesw', '3': 'nwse', \n '4': 'ns', '5': 'ns', \n '6': 'ew', '7': 'ew' \n };\n const baseDirection = baseDirectionMap[direction];\n let effectiveAngle = angle; \n if (baseDirection === 'nesw') {\n effectiveAngle += 45;\n } else if (baseDirection === 'ew') {\n effectiveAngle += 90;\n } else if (baseDirection === 'nwse') {\n effectiveAngle += 135;\n }\n effectiveAngle = effectiveAngle % 360;\n if (effectiveAngle < 0) effectiveAngle += 360;\n const index = Math.round(effectiveAngle / 45) % 4; \n let finalIndex;\n if (effectiveAngle >= 337.5 || effectiveAngle < 22.5) finalIndex = 0; \n else if (effectiveAngle >= 22.5 && effectiveAngle < 67.5) finalIndex = 1; \n else if (effectiveAngle >= 67.5 && effectiveAngle < 112.5) finalIndex = 2; \n else if (effectiveAngle >= 112.5 && effectiveAngle < 157.5) finalIndex = 3;\n else if (effectiveAngle >= 157.5 && effectiveAngle < 202.5) finalIndex = 0; \n else if (effectiveAngle >= 202.5 && effectiveAngle < 247.5) finalIndex = 1; \n else if (effectiveAngle >= 247.5 && effectiveAngle < 292.5) finalIndex = 2; \n else if (effectiveAngle >= 292.5 && effectiveAngle < 337.5) finalIndex = 3; \n else finalIndex = 0; \n return directions[finalIndex];\n }\n addAnchors() {\n const zoom = window.currentZoom || 1;\n const anchorSize = 10 / zoom;\n const anchorStrokeWidth = 2;\n const self = this;\n const expandedX = -this.rx - this.selectionPadding;\n const expandedY = -this.ry - this.selectionPadding; \n const expandedWidth = this.rx * 2 + 2 * this.selectionPadding;\n const expandedHeight = this.ry * 2 + 2 * this.selectionPadding;\n\n const positions = [\n { x: expandedX, y: expandedY }, \n { x: expandedX + expandedWidth, y: expandedY }, \n { x: expandedX, y: expandedY + expandedHeight }, \n { x: expandedX + expandedWidth, y: expandedY + expandedHeight }, \n { x: expandedX + expandedWidth / 2, y: expandedY }, \n { x: expandedX + expandedWidth / 2, y: expandedY + expandedHeight }, \n { x: expandedX, y: expandedHeight / 2 + expandedY }, \n { x: expandedX + expandedWidth, y: expandedHeight / 2 + expandedY } \n ];\n\n const outlinePoints = [\n [positions[0].x, positions[0].y],\n [positions[1].x, positions[1].y],\n [positions[3].x, positions[3].y],\n [positions[2].x, positions[2].y],\n [positions[0].x, positions[0].y]\n ];\n\n this.anchors.forEach(anchor => {\n if (anchor.parentNode === this.group) {\n this.group.removeChild(anchor);\n }\n });\n if (this.rotationAnchor && this.rotationAnchor.parentNode === this.group) {\n this.group.removeChild(this.rotationAnchor);\n }\n if (this.selectionOutline && this.selectionOutline.parentNode === this.group) {\n this.group.removeChild(this.selectionOutline);\n }\n\n this.anchors = [];\n const anchorDirections = {\n 0: 'nwse', \n 1: 'nesw', \n 2: 'nesw', \n 3: 'nwse', \n 4: 'ns', \n 5: 'ns', \n 6: 'ew', \n 7: 'ew' \n };\n\n positions.forEach((pos, i) => {\n const anchor = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n anchor.setAttribute('x', pos.x - anchorSize / 2);\n anchor.setAttribute('y', pos.y - anchorSize / 2);\n anchor.setAttribute('width', anchorSize);\n anchor.setAttribute('height', anchorSize);\n anchor.setAttribute('class', 'anchor');\n anchor.setAttribute('data-index', i);\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 anchor.setAttribute('style', 'pointer-events: all;');\n\n anchor.addEventListener('mouseover', function () {\n const index = this.getAttribute('data-index');\n const baseDirection = anchorDirections[index];\n const rotatedCursor = self.getRotatedCursor(index, self.rotation); \n svg.style.cursor = rotatedCursor + '-resize';\n });\n\n anchor.addEventListener('mouseout', function () {\n if (!isResizingShapeCircle && !isDraggingShapeCircle && !isRotatingShapeCircle) {\n svg.style.cursor = 'default';\n }\n });\n\n this.group.appendChild(anchor);\n this.anchors[i] = anchor;\n });\n const rotationAnchorPos = { x: expandedX + expandedWidth / 2, y: expandedY - 30 / zoom };\n this.rotationAnchor = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n this.rotationAnchor.setAttribute('cx', rotationAnchorPos.x);\n this.rotationAnchor.setAttribute('cy', rotationAnchorPos.y);\n this.rotationAnchor.setAttribute('r', 8 / zoom);\n this.rotationAnchor.setAttribute('class', 'rotate-anchor');\n this.rotationAnchor.setAttribute('fill', '#121212');\n this.rotationAnchor.setAttribute('stroke', '#5B57D1');\n this.rotationAnchor.setAttribute('stroke-width', anchorStrokeWidth);\n this.rotationAnchor.setAttribute('vector-effect', 'non-scaling-stroke');\n this.rotationAnchor.setAttribute('style', 'pointer-events: all;');\n this.group.appendChild(this.rotationAnchor);\n\n this.rotationAnchor.addEventListener('mouseover', function () {\n if (!isResizingShapeCircle && !isDraggingShapeCircle && !isRotatingShapeCircle) {\n svg.style.cursor = 'grab';\n }\n });\n this.rotationAnchor.addEventListener('mouseout', function () {\n if (!isResizingShapeCircle && !isDraggingShapeCircle && !isRotatingShapeCircle) {\n svg.style.cursor = 'default';\n }\n });\n\n const pointsAttr = outlinePoints.map(p => p.join(',')).join(' ');\n const outline = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');\n outline.setAttribute('points', pointsAttr);\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 this.group.appendChild(outline);\n this.selectionOutline = outline;\n\n disableAllSideBars();\n circleSideBar.classList.remove(\"hidden\");\n if (window.__showSidebarForShape) window.__showSidebarForShape('circle');\n this.updateSidebar();\n }\n\n updateSelectionControls() {\n if (!this.selectionOutline || this.anchors.length === 0) return;\n\n const zoom = window.currentZoom || 1;\n const anchorSize = 10 / zoom;\n const expandedX = -this.rx - this.selectionPadding;\n const expandedY = -this.ry - this.selectionPadding;\n const expandedWidth = this.rx * 2 + 2 * this.selectionPadding;\n const expandedHeight = this.ry * 2 + 2 * this.selectionPadding;\n\n const positions = [\n { x: expandedX, y: expandedY },\n { x: expandedX + expandedWidth, y: expandedY },\n { x: expandedX, y: expandedY + expandedHeight },\n { x: expandedX + expandedWidth, y: expandedY + expandedHeight },\n { x: expandedX + expandedWidth / 2, y: expandedY },\n { x: expandedX + expandedWidth / 2, y: expandedY + expandedHeight },\n { x: expandedX, y: expandedHeight / 2 + expandedY },\n { x: expandedX + expandedWidth, y: expandedHeight / 2 + expandedY }\n ];\n\n positions.forEach((pos, i) => {\n if (this.anchors[i]) {\n this.anchors[i].setAttribute('x', pos.x - anchorSize / 2);\n this.anchors[i].setAttribute('y', pos.y - anchorSize / 2);\n }\n });\n\n const outlinePoints = [\n [positions[0].x, positions[0].y],\n [positions[1].x, positions[1].y],\n [positions[3].x, positions[3].y],\n [positions[2].x, positions[2].y],\n [positions[0].x, positions[0].y]\n ];\n this.selectionOutline.setAttribute('points', outlinePoints.map(p => p.join(',')).join(' '));\n\n if (this.rotationAnchor) {\n this.rotationAnchor.setAttribute('cx', expandedX + expandedWidth / 2);\n this.rotationAnchor.setAttribute('cy', expandedY - 30 / zoom);\n }\n }\n\n removeSelection() {\n this.anchors.forEach(anchor => {\n if (anchor.parentNode === this.group) {\n this.group.removeChild(anchor);\n }\n });\n if (this.rotationAnchor && this.rotationAnchor.parentNode === this.group) {\n this.group.removeChild(this.rotationAnchor);\n }\n if (this.selectionOutline && this.selectionOutline.parentNode === this.group) {\n this.group.removeChild(this.selectionOutline);\n }\n this.anchors = [];\n this.rotationAnchor = null;\n this.selectionOutline = null;\n this.isSelected = false;\n }\n contains(x, y) {\n if (!this.element || !this.rx || !this.ry) return false;\n // Mouse coordinates are in canvas space; invert the circle's own\n // translation/rotation without mixing in the viewport CTM.\n const angle = -(this.rotation || 0) * Math.PI / 180;\n const translatedX = x - this.x;\n const translatedY = y - this.y;\n const dx = translatedX * Math.cos(angle) - translatedY * Math.sin(angle);\n const dy = translatedX * Math.sin(angle) + translatedY * Math.cos(angle);\n const rx = this.rx;\n const ry = this.ry;\n return ((dx * dx) / (rx * rx) + (dy * dy) / (ry * ry)) <= 1.05; \n }\n isNearAnchor(x, y) {\n if (!this.isSelected) return null;\n const buffer = 10 / currentZoom; // Scale buffer by zoom level\n const anchorSize = 10 / currentZoom; // Scale anchor size by zoom level\n\n // Iterate through anchors\n for (let i = 0; i < this.anchors.length; i++) {\n const anchor = this.anchors[i];\n const anchorLocalX = parseFloat(anchor.getAttribute('x')) + anchorSize / 2;\n const anchorLocalY = parseFloat(anchor.getAttribute('y')) + anchorSize / 2;\n const svgPoint = svg.createSVGPoint();\n svgPoint.x = anchorLocalX;\n svgPoint.y = anchorLocalY;\n const transformedPoint = svgPoint.matrixTransform(this.group.getCTM());\n \n const anchorLeft = transformedPoint.x - anchorSize/2 - buffer;\n const anchorRight = transformedPoint.x + anchorSize/2 + buffer;\n const anchorTop = transformedPoint.y - anchorSize/2 - buffer;\n const anchorBottom = transformedPoint.y + anchorSize/2 + buffer;\n \n if (x >= anchorLeft && x <= anchorRight && y >= anchorTop && y <= anchorBottom) {\n return { type: 'resize', index: i };\n }\n }\n\n // Check rotation anchor\n if (this.rotationAnchor) {\n const rotateAnchorLocalX = parseFloat(this.rotationAnchor.getAttribute('cx'));\n const rotateAnchorLocalY = parseFloat(this.rotationAnchor.getAttribute('cy'));\n const svgPoint = svg.createSVGPoint();\n svgPoint.x = rotateAnchorLocalX;\n svgPoint.y = rotateAnchorLocalY;\n const transformedPoint = svgPoint.matrixTransform(this.group.getCTM());\n \n const rotateAnchorRadius = parseFloat(this.rotationAnchor.getAttribute('r')) / currentZoom;\n const distSq = (x - transformedPoint.x)**2 + (y - transformedPoint.y)**2;\n if (distSq <= (rotateAnchorRadius + buffer)**2) {\n return { type: 'rotate' };\n }\n }\n\n return null;\n }\n\n updatePosition(anchorIndex, newMouseX, newMouseY) {\n const CTM = this.group.getCTM();\n if (!CTM) return;\n \n const inverseCTM = CTM.inverse();\n const svgPoint = svg.createSVGPoint();\n svgPoint.x = newMouseX;\n svgPoint.y = newMouseY;\n const transformedPoint = svgPoint.matrixTransform(inverseCTM);\n \n const dx = transformedPoint.x;\n const dy = transformedPoint.y;\n \n const MIN_RADIUS = 10;\n \n switch (anchorIndex) {\n case 0: // top-left\n case 1: // top-right\n case 2: // bottom-left\n case 3: // bottom-right\n this.rx = Math.max(Math.abs(dx), MIN_RADIUS);\n this.ry = Math.max(Math.abs(dy), MIN_RADIUS);\n break;\n \n case 4: // top-center\n case 5: // bottom-center\n this.ry = Math.max(Math.abs(dy), MIN_RADIUS);\n break;\n \n case 6: // left-center\n case 7: // right-center\n this.rx = Math.max(Math.abs(dx), MIN_RADIUS);\n break;\n }\n this.updateAttachedArrows();\n }\n updateAttachedArrows() {\n shapes.forEach(shape => {\n if (shape && shape.shapeName === 'arrow' && typeof shape.updateAttachments === 'function') {\n if ((shape.attachedToStart && shape.attachedToStart.shape === this) ||\n (shape.attachedToEnd && shape.attachedToEnd.shape === this)) {\n shape.updateAttachments();\n }\n }\n });\n }\n _updateShade() {\n if (!this.shadeColor) {\n if (this._shadeEllipse && this._shadeEllipse.parentNode === this.group) {\n this.group.removeChild(this._shadeEllipse);\n this._shadeEllipse = null;\n }\n if (this._shadeGradient && this._shadeGradient.parentNode) {\n this._shadeGradient.parentNode.removeChild(this._shadeGradient);\n this._shadeGradient = null;\n }\n return;\n }\n\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 const gradId = `shade-${this.shapeID}`;\n if (!this._shadeGradient) {\n this._shadeGradient = document.createElementNS('http://www.w3.org/2000/svg', 'radialGradient');\n this._shadeGradient.setAttribute('id', gradId);\n defs.appendChild(this._shadeGradient);\n }\n\n // Radial gradient for circles - center to edge fade\n this._shadeGradient.setAttribute('cx', '50%');\n this._shadeGradient.setAttribute('cy', '50%');\n this._shadeGradient.setAttribute('r', '50%');\n\n while (this._shadeGradient.firstChild) this._shadeGradient.removeChild(this._shadeGradient.firstChild);\n const stop1 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\n stop1.setAttribute('offset', '0%');\n stop1.setAttribute('stop-color', this.shadeColor);\n stop1.setAttribute('stop-opacity', this.shadeOpacity);\n const stop2 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\n stop2.setAttribute('offset', '100%');\n stop2.setAttribute('stop-color', this.shadeColor);\n stop2.setAttribute('stop-opacity', '0');\n this._shadeGradient.appendChild(stop1);\n this._shadeGradient.appendChild(stop2);\n\n if (!this._shadeEllipse) {\n this._shadeEllipse = document.createElementNS('http://www.w3.org/2000/svg', 'ellipse');\n this._shadeEllipse.setAttribute('pointer-events', 'none');\n }\n this._shadeEllipse.setAttribute('cx', 0);\n this._shadeEllipse.setAttribute('cy', 0);\n this._shadeEllipse.setAttribute('rx', this.rx);\n this._shadeEllipse.setAttribute('ry', this.ry);\n this._shadeEllipse.setAttribute('fill', `url(#${gradId})`);\n\n if (this._shadeEllipse.parentNode === this.group) this.group.removeChild(this._shadeEllipse);\n if (this.element && this.element.nextSibling) {\n this.group.insertBefore(this._shadeEllipse, this.element.nextSibling);\n } else {\n this.group.appendChild(this._shadeEllipse);\n }\n }\n\n _updateLabelElement() {\n if (!this.label) {\n if (this.labelElement && this.labelElement.parentNode === this.group) {\n this.group.removeChild(this.labelElement);\n this.labelElement = null;\n }\n if (this._labelBg && this._labelBg.parentNode === this.group) {\n this.group.removeChild(this._labelBg);\n this._labelBg = null;\n }\n return;\n }\n\n if (!this.labelElement) {\n this.labelElement = document.createElementNS('http://www.w3.org/2000/svg', 'text');\n this.labelElement.setAttribute('class', 'shape-label');\n this.labelElement.setAttribute('pointer-events', 'none');\n }\n\n // Circle center is at (0, 0) in local coords\n this.labelElement.setAttribute('x', 0);\n this.labelElement.setAttribute('y', 0);\n this.labelElement.setAttribute('text-anchor', 'middle');\n this.labelElement.setAttribute('dominant-baseline', 'central');\n this.labelElement.setAttribute('fill', this.labelColor);\n this.labelElement.setAttribute('font-size', this.labelFontSize);\n this.labelElement.setAttribute('font-family', 'lixFont, sans-serif');\n this.labelElement.textContent = this.label;\n\n // Background padding rect behind text (like arrows have)\n const canvasBg = window.getComputedStyle(svg).backgroundColor || '#000';\n if (!this._labelBg) {\n this._labelBg = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n this._labelBg.setAttribute('pointer-events', 'none');\n }\n this._labelBg.setAttribute('fill', canvasBg);\n const hPadding = 6;\n const vPadding = 2;\n const charWidth = this.labelFontSize * 0.6;\n const bgW = this.label.length * charWidth + hPadding * 2;\n const bgH = this.labelFontSize + vPadding * 2;\n this._labelBg.setAttribute('x', -bgW / 2);\n this._labelBg.setAttribute('y', -bgH / 2);\n this._labelBg.setAttribute('width', bgW);\n this._labelBg.setAttribute('height', bgH);\n this._labelBg.setAttribute('rx', 3);\n\n // Re-append bg then text on top\n if (this._labelBg.parentNode === this.group) this.group.removeChild(this._labelBg);\n if (this.labelElement.parentNode === this.group) this.group.removeChild(this.labelElement);\n this.group.appendChild(this._labelBg);\n this.group.appendChild(this.labelElement);\n }\n\n _setupLabelDblClick() {\n this.group.addEventListener('dblclick', (e) => {\n e.stopPropagation();\n e.preventDefault();\n this.startLabelEdit();\n });\n }\n\n startLabelEdit() {\n if (this._isEditingLabel) return;\n this._isEditingLabel = true;\n\n if (this.labelElement) {\n this.labelElement.setAttribute('visibility', 'hidden');\n }\n\n // Get shape's screen position via CTM\n const ctm = this.group.getScreenCTM();\n if (!ctm) { this._isEditingLabel = false; return; }\n\n // Map the ellipse bounding box to screen coords\n const pt1 = svg.createSVGPoint();\n pt1.x = -this.rx; pt1.y = -this.ry;\n const screenTL = pt1.matrixTransform(ctm);\n const pt2 = svg.createSVGPoint();\n pt2.x = this.rx; pt2.y = this.ry;\n const screenBR = pt2.matrixTransform(ctm);\n\n const screenW = Math.abs(screenBR.x - screenTL.x);\n const screenH = Math.abs(screenBR.y - screenTL.y);\n const screenX = Math.min(screenTL.x, screenBR.x);\n const screenY = Math.min(screenTL.y, screenBR.y);\n\n // Create HTML overlay\n const overlay = document.createElement('div');\n overlay.className = 'shape-label-editor';\n overlay.style.cssText = `\n position: fixed; z-index: 10000;\n left: ${screenX}px; top: ${screenY}px;\n width: ${screenW}px; height: ${screenH}px;\n display: flex; align-items: center; justify-content: center;\n pointer-events: auto;\n `;\n\n const canvasBg = window.getComputedStyle(svg).backgroundColor || '#000';\n const input = document.createElement('div');\n input.setAttribute('contenteditable', 'true');\n input.style.cssText = `\n max-width: ${screenW - 8}px; min-width: 30px; min-height: 20px;\n background: ${canvasBg}; border: none;\n outline: none; padding: 2px 6px;\n color: ${this.labelColor}; font-size: ${Math.max(12, this.labelFontSize * (screenW / Math.max(this.rx * 2, 1)))}px;\n font-family: lixFont, sans-serif; text-align: center;\n white-space: pre-wrap; word-break: break-word;\n cursor: text;\n `;\n if (this.label) {\n input.textContent = this.label;\n } else {\n input.innerHTML = '&nbsp;';\n }\n\n overlay.appendChild(input);\n document.body.appendChild(overlay);\n\n setTimeout(() => {\n input.focus();\n const sel = window.getSelection();\n const range = document.createRange();\n range.selectNodeContents(input);\n sel.removeAllRanges();\n sel.addRange(range);\n }, 10);\n\n const finishEdit = () => {\n const newText = input.textContent.trim().replace(/\\u00A0/g, '');\n this.label = newText;\n this._isEditingLabel = false;\n\n if (overlay.parentNode) overlay.parentNode.removeChild(overlay);\n if (this.labelElement) this.labelElement.setAttribute('visibility', 'visible');\n this.draw();\n };\n\n input.addEventListener('blur', finishEdit);\n input.addEventListener('keydown', (e) => {\n e.stopPropagation();\n if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); input.blur(); }\n if (e.key === 'Escape') { input.textContent = this.label; input.blur(); }\n });\n input.addEventListener('pointerdown', (e) => e.stopPropagation());\n input.addEventListener('pointermove', (e) => e.stopPropagation());\n input.addEventListener('pointerup', (e) => e.stopPropagation());\n }\n\n setLabel(text, color, fontSize) {\n this.label = text || '';\n if (color) this.labelColor = color;\n if (fontSize) this.labelFontSize = fontSize;\n this.draw();\n }\n\n rotate(angle) {\n angle = angle % 360;\n if (angle < 0) angle += 360;\n this.rotation = angle;\n }\n // No-op: React sidebar handles UI updates via Zustand store\n updateSidebar() {}\n\n}\n\nexport { Circle };\n"],
5
- "mappings": "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",
6
- "names": []
7
- }