@elixpo/lixsketch 5.5.20 → 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.
- package/dist/react/{CopyPaste-KJZ34MIP.js → CopyPaste-FJN7K5LS.js} +39 -11
- package/dist/react/CopyPaste-FJN7K5LS.js.map +7 -0
- package/dist/react/{EventDispatcher-XDRQS7BD.js → EventDispatcher-O7HCQQNM.js} +13 -13
- package/dist/react/Frame-RLSMJJSK.js +11 -0
- package/dist/react/{GraphEngine-KQXHNTZQ.js → GraphEngine-MM6ALA2N.js} +105 -148
- package/dist/react/{GraphEngine-KQXHNTZQ.js.map → GraphEngine-MM6ALA2N.js.map} +2 -2
- package/dist/react/IconShape-7OPXAKLK.js +10 -0
- package/dist/react/ImageShape-LRNJQCF3.js +10 -0
- package/dist/react/Line-WWQFBNX5.js +10 -0
- package/dist/react/{SceneSerializer-VY3HY4PF.js → SceneSerializer-GSJR7ZHC.js} +32 -8
- package/dist/react/SceneSerializer-GSJR7ZHC.js.map +7 -0
- package/dist/react/{Selection-U2AR6NQS.js → Selection-ZL3G6IAO.js} +4 -4
- package/dist/react/{SketchEngine-ZFYUTKET.js → SketchEngine-BFLHJPCG.js} +21 -21
- package/dist/react/{UndoRedo-BZ6W4QTV.js → UndoRedo-NL7KLR5B.js} +2 -2
- package/dist/react/{arrowTool-LKFSZKXC.js → arrowTool-CNVGM6RX.js} +3 -3
- package/dist/react/{chunk-RFHMFWVR.js → chunk-2FMFOPGW.js} +5 -6
- package/dist/react/{chunk-RFHMFWVR.js.map → chunk-2FMFOPGW.js.map} +2 -2
- package/dist/react/{chunk-SBSM3GQD.js → chunk-2THKDSWW.js} +4 -4
- package/dist/react/{chunk-JOPQ27YH.js → chunk-4BLMNGTR.js} +3 -3
- package/dist/react/{chunk-C62SXFBL.js → chunk-4TAS67SL.js} +23 -22
- package/dist/react/chunk-4TAS67SL.js.map +7 -0
- package/dist/react/{chunk-7VBI7S7T.js → chunk-AH4PWNEB.js} +10 -11
- package/dist/react/chunk-AH4PWNEB.js.map +7 -0
- package/dist/react/{chunk-R5QXEVZ5.js → chunk-GC3KTQDA.js} +74 -15
- package/dist/react/chunk-GC3KTQDA.js.map +7 -0
- package/dist/react/{chunk-2V7G2PLX.js → chunk-GPIYXREE.js} +3 -3
- package/dist/react/{chunk-73VLPCBC.js → chunk-HFQZYCHJ.js} +3 -3
- package/dist/react/{chunk-C72OHQLE.js → chunk-ILGAFR56.js} +3 -3
- package/dist/react/{chunk-75G7XSZU.js → chunk-KVAQPCUH.js} +17 -3
- package/dist/react/chunk-KVAQPCUH.js.map +7 -0
- package/dist/react/{chunk-WEWMB35W.js → chunk-OFGJJKPH.js} +3 -3
- package/dist/react/{chunk-6G3ITAS5.js → chunk-SZD7DKYJ.js} +18 -9
- package/dist/react/chunk-SZD7DKYJ.js.map +7 -0
- package/dist/react/{chunk-MYYBFZD3.js → chunk-U3TB4KRS.js} +45 -6
- package/dist/react/chunk-U3TB4KRS.js.map +7 -0
- package/dist/react/{chunk-UQBT7F4K.js → chunk-V2QTYSBK.js} +2 -2
- package/dist/react/{chunk-2I3GH65Z.js → chunk-XFQECTTF.js} +44 -19
- package/dist/react/chunk-XFQECTTF.js.map +7 -0
- package/dist/react/{chunk-O64N5JPO.js → chunk-YF3TK7SC.js} +2 -2
- package/dist/react/{circleTool-RDOIMKKV.js → circleTool-KICNRQCI.js} +4 -4
- package/dist/react/{codeTool-VBDB2ES6.js → codeTool-NCQ73R6M.js} +4 -4
- package/dist/react/{frameTool-Z5ZDCX6H.js → frameTool-Y6KB67DO.js} +4 -4
- package/dist/react/{freehandTool-AAQCTMVM.js → freehandTool-MMULHCQ7.js} +4 -4
- package/dist/react/{iconTool-5WNDHI5T.js → iconTool-LSW2DYGB.js} +4 -4
- package/dist/react/{imageTool-ECPMT3BL.js → imageTool-2DSR32RX.js} +4 -4
- package/dist/react/index.js +141 -66
- package/dist/react/index.js.map +3 -3
- package/dist/react/{lineTool-XLOOZE3E.js → lineTool-N5I7IGT7.js} +4 -4
- package/dist/react/{rectangleTool-AEYDDJCA.js → rectangleTool-YUT7ZK2E.js} +4 -4
- package/dist/react/{textTool-5IJKTWVQ.js → textTool-IQOYPELP.js} +5 -5
- package/package.json +1 -1
- package/src/core/CopyPaste.js +34 -4
- package/src/core/GraphEngine.js +129 -185
- package/src/core/SceneSerializer.js +26 -0
- package/src/core/Selection.js +12 -11
- package/src/core/UndoRedo.js +47 -3
- package/src/react/components/canvas/MultiSelectActions.jsx +4 -1
- package/src/react/components/sidebars/IconSidebar.jsx +14 -23
- package/src/react/components/sidebars/ImageSidebar.jsx +47 -24
- package/src/react/store/useUIStore.js +71 -14
- package/src/shapes/Frame.js +19 -2
- package/src/shapes/IconShape.js +23 -25
- package/src/shapes/ImageShape.js +6 -2
- package/src/tools/frameTool.js +19 -9
- package/src/tools/iconTool.js +60 -25
- package/src/tools/imageTool.js +77 -13
- package/dist/react/CopyPaste-KJZ34MIP.js.map +0 -7
- package/dist/react/Frame-QLBAVLGW.js +0 -11
- package/dist/react/IconShape-32EYI2MA.js +0 -10
- package/dist/react/ImageShape-MYP2DVVH.js +0 -10
- package/dist/react/Line-FCCF2BOB.js +0 -10
- package/dist/react/SceneSerializer-VY3HY4PF.js.map +0 -7
- package/dist/react/chunk-2I3GH65Z.js.map +0 -7
- package/dist/react/chunk-6G3ITAS5.js.map +0 -7
- package/dist/react/chunk-75G7XSZU.js.map +0 -7
- package/dist/react/chunk-7VBI7S7T.js.map +0 -7
- package/dist/react/chunk-C62SXFBL.js.map +0 -7
- package/dist/react/chunk-MYYBFZD3.js.map +0 -7
- package/dist/react/chunk-R5QXEVZ5.js.map +0 -7
- /package/dist/react/{EventDispatcher-XDRQS7BD.js.map → EventDispatcher-O7HCQQNM.js.map} +0 -0
- /package/dist/react/{Frame-QLBAVLGW.js.map → Frame-RLSMJJSK.js.map} +0 -0
- /package/dist/react/{IconShape-32EYI2MA.js.map → IconShape-7OPXAKLK.js.map} +0 -0
- /package/dist/react/{ImageShape-MYP2DVVH.js.map → ImageShape-LRNJQCF3.js.map} +0 -0
- /package/dist/react/{Line-FCCF2BOB.js.map → Line-WWQFBNX5.js.map} +0 -0
- /package/dist/react/{Selection-U2AR6NQS.js.map → Selection-ZL3G6IAO.js.map} +0 -0
- /package/dist/react/{SketchEngine-ZFYUTKET.js.map → SketchEngine-BFLHJPCG.js.map} +0 -0
- /package/dist/react/{UndoRedo-BZ6W4QTV.js.map → UndoRedo-NL7KLR5B.js.map} +0 -0
- /package/dist/react/{arrowTool-LKFSZKXC.js.map → arrowTool-CNVGM6RX.js.map} +0 -0
- /package/dist/react/{chunk-SBSM3GQD.js.map → chunk-2THKDSWW.js.map} +0 -0
- /package/dist/react/{chunk-JOPQ27YH.js.map → chunk-4BLMNGTR.js.map} +0 -0
- /package/dist/react/{chunk-2V7G2PLX.js.map → chunk-GPIYXREE.js.map} +0 -0
- /package/dist/react/{chunk-73VLPCBC.js.map → chunk-HFQZYCHJ.js.map} +0 -0
- /package/dist/react/{chunk-C72OHQLE.js.map → chunk-ILGAFR56.js.map} +0 -0
- /package/dist/react/{chunk-WEWMB35W.js.map → chunk-OFGJJKPH.js.map} +0 -0
- /package/dist/react/{chunk-UQBT7F4K.js.map → chunk-V2QTYSBK.js.map} +0 -0
- /package/dist/react/{chunk-O64N5JPO.js.map → chunk-YF3TK7SC.js.map} +0 -0
- /package/dist/react/{circleTool-RDOIMKKV.js.map → circleTool-KICNRQCI.js.map} +0 -0
- /package/dist/react/{codeTool-VBDB2ES6.js.map → codeTool-NCQ73R6M.js.map} +0 -0
- /package/dist/react/{frameTool-Z5ZDCX6H.js.map → frameTool-Y6KB67DO.js.map} +0 -0
- /package/dist/react/{freehandTool-AAQCTMVM.js.map → freehandTool-MMULHCQ7.js.map} +0 -0
- /package/dist/react/{iconTool-5WNDHI5T.js.map → iconTool-LSW2DYGB.js.map} +0 -0
- /package/dist/react/{imageTool-ECPMT3BL.js.map → imageTool-2DSR32RX.js.map} +0 -0
- /package/dist/react/{lineTool-XLOOZE3E.js.map → lineTool-N5I7IGT7.js.map} +0 -0
- /package/dist/react/{rectangleTool-AEYDDJCA.js.map → rectangleTool-YUT7ZK2E.js.map} +0 -0
- /package/dist/react/{textTool-5IJKTWVQ.js.map → textTool-IQOYPELP.js.map} +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
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';\nimport { registerRotationAnchor } from '../core/ScreenSpaceControls.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\nif (!window.__roomImageBytesUsed) window.__roomImageBytesUsed = 0;\n\nfunction getRoomImageLimitBytes() {\n return Number(window.__roomImageLimitBytes) || 2 * 1024 * 1024;\n}\n\nfunction usesPersonalCloudinary() {\n return Boolean(window.__personalCloudinary?.connected && window.__personalCloudinary?.useForUploads);\n}\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 const roomLimit = getRoomImageLimitBytes();\n const oldSize = imageShape.element.__fileSize || 0;\n if (!usesPersonalCloudinary() && (window.__roomImageBytesUsed || 0) - oldSize + compressed.compressedSize > roomLimit) {\n throw new Error(`Room image limit reached (${Math.round(roomLimit / (1024 * 1024))} MB)`);\n }\n\n if (usesPersonalCloudinary()) {\n const personalForm = new FormData();\n personalForm.append('file', compressed.blob, `image_${Date.now()}`);\n personalForm.append('sessionId', sessionId);\n const personalResponse = await fetch('/api/images/personal-upload', {\n method: 'POST',\n body: personalForm,\n signal,\n });\n const personalData = await personalResponse.json().catch(() => ({}));\n if (!personalResponse.ok || !personalData.url) {\n throw new Error(personalData.error || 'Personal Cloudinary upload failed');\n }\n imageShape.element.setAttribute('href', personalData.url);\n imageShape.element.setAttribute('data-href', personalData.url);\n imageShape.element.setAttribute('data-cloudinary-id', personalData.publicId);\n imageShape.element.setAttribute('data-storage-provider', 'user_cloudinary');\n imageShape.element.setAttribute('data-storage-cloud-name', personalData.cloudName || '');\n imageShape.element.__fileSize = 0;\n imageShape.element.setAttribute('data-file-size', '0');\n window.__roomImageBytesUsed = Math.max(0, (window.__roomImageBytesUsed || 0) - oldSize);\n imageShape.uploadStatus = 'done';\n return;\n }\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 sizeBytes: compressed.compressedSize,\n }),\n signal,\n });\n if (!signRes.ok) {\n const errorBody = await signRes.json().catch(() => ({}));\n throw new Error(errorBody.message || 'Failed to get upload signature');\n }\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 await fetch(`${workerUrl}/api/images/complete`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n sessionId,\n publicId: uploadData.public_id || signData.publicId,\n sizeBytes: uploadData.bytes || compressed.compressedSize,\n }),\n signal,\n }).catch(() => {});\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 newSize = uploadData.bytes || compressed.compressedSize;\n imageShape.element.__fileSize = newSize;\n imageShape.element.setAttribute('data-file-size', String(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 const roomImageLimitBytes = getRoomImageLimitBytes();\n const personalStorage = usesPersonalCloudinary();\n if (!personalStorage && window.__roomImageBytesUsed + file.size > roomImageLimitBytes) {\n const usedMB = (window.__roomImageBytesUsed / (1024 * 1024)).toFixed(2);\n const fileMB = (file.size / (1024 * 1024)).toFixed(2);\n alert(`Room image limit reached (${Math.round(roomImageLimitBytes / (1024 * 1024))} MB). Used: ${usedMB} MB, this file: ${fileMB} MB. Delete some images to free space.`);\n isImageToolActive = false;\n return;\n }\n\n const maxSize = personalStorage ? 20 * 1024 * 1024 : roomImageLimitBytes;\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 ${Math.round(maxSize / (1024 * 1024))} 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 finalImage.setAttribute('data-file-size', String(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, force = false) {\n if (!isSelectionToolActive && !force) 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 registerRotationAnchor(rotationAnchor, { radius: 5, edgeY: y });\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 isPersonal = selectedImage.getAttribute('data-storage-provider') === 'user_cloudinary';\n const workerUrl = window.__WORKER_URL;\n const deleteUrl = isPersonal ? '/api/images/personal-delete' : (workerUrl ? `${workerUrl}/api/images/delete` : null);\n if (deleteUrl) {\n fetch(deleteUrl, {\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// Programmatic selection bridge used by generated vector-image shapes.\n// Keeping the selection state in this module prevents a second, divergent\n// implementation of image dragging and screen-space resize controls.\nwindow.__selectImageElement = function(element, { force = false } = {}) {\n if (!element) return;\n selectImage({ target: element, stopPropagation: () => {} }, force);\n};\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 };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
calculateSnap,
|
|
4
4
|
clearSnapGuides,
|
|
5
5
|
updateAttachedArrows
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-YF3TK7SC.js";
|
|
7
7
|
import {
|
|
8
8
|
pushCreateAction,
|
|
9
9
|
pushDeleteAction,
|
|
10
10
|
pushFrameAttachmentAction,
|
|
11
11
|
pushOptionsChangeAction,
|
|
12
12
|
pushTransformAction
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-U3TB4KRS.js";
|
|
14
14
|
|
|
15
15
|
// src/tools/freehandTool.js
|
|
16
16
|
function getThemeStroke() {
|
|
@@ -561,4 +561,4 @@ export {
|
|
|
561
561
|
handleMouseMove,
|
|
562
562
|
handleMouseUp
|
|
563
563
|
};
|
|
564
|
-
//# sourceMappingURL=chunk-
|
|
564
|
+
//# sourceMappingURL=chunk-GPIYXREE.js.map
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
cleanupAttachments,
|
|
7
7
|
updateAttachedArrows
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-YF3TK7SC.js";
|
|
9
9
|
import {
|
|
10
10
|
pushCreateAction,
|
|
11
11
|
pushDeleteActionWithAttachments,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
pushTransformAction,
|
|
15
15
|
setTextReferences,
|
|
16
16
|
updateSelectedElement
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-U3TB4KRS.js";
|
|
18
18
|
|
|
19
19
|
// src/tools/codeTool.js
|
|
20
20
|
function getThemeStroke() {
|
|
@@ -1601,4 +1601,4 @@ export {
|
|
|
1601
1601
|
getCodeLanguage,
|
|
1602
1602
|
getSelectedCodeBlock
|
|
1603
1603
|
};
|
|
1604
|
-
//# sourceMappingURL=chunk-
|
|
1604
|
+
//# sourceMappingURL=chunk-HFQZYCHJ.js.map
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import {
|
|
3
3
|
calculateSnap,
|
|
4
4
|
clearSnapGuides
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-YF3TK7SC.js";
|
|
6
6
|
import {
|
|
7
7
|
pushCreateAction,
|
|
8
8
|
pushDeleteAction,
|
|
9
9
|
pushFrameAttachmentAction,
|
|
10
10
|
pushOptionsChangeAction,
|
|
11
11
|
pushTransformAction
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-U3TB4KRS.js";
|
|
13
13
|
|
|
14
14
|
// src/tools/lineTool.js
|
|
15
15
|
function getThemeStroke() {
|
|
@@ -450,4 +450,4 @@ export {
|
|
|
450
450
|
handleMouseMove,
|
|
451
451
|
handleMouseUp
|
|
452
452
|
};
|
|
453
|
-
//# sourceMappingURL=chunk-
|
|
453
|
+
//# sourceMappingURL=chunk-ILGAFR56.js.map
|
|
@@ -395,11 +395,14 @@ var Frame = class {
|
|
|
395
395
|
labelText.textContent = this.frameName || "Frame";
|
|
396
396
|
labelText.style.cursor = "pointer";
|
|
397
397
|
labelText.style.userSelect = "none";
|
|
398
|
+
labelText.style.pointerEvents = "all";
|
|
398
399
|
if (this.rotation !== 0) {
|
|
399
400
|
const centerX = this.x + this.width / 2;
|
|
400
401
|
const centerY = this.y + this.height / 2;
|
|
401
402
|
labelText.setAttribute("transform", `rotate(${this.rotation}, ${centerX}, ${centerY})`);
|
|
402
403
|
}
|
|
404
|
+
labelText.addEventListener("pointerdown", (e) => e.stopPropagation());
|
|
405
|
+
labelText.addEventListener("click", (e) => e.stopPropagation());
|
|
403
406
|
labelText.addEventListener("dblclick", (e) => {
|
|
404
407
|
e.stopPropagation();
|
|
405
408
|
this.startLabelEdit(labelText);
|
|
@@ -408,6 +411,10 @@ var Frame = class {
|
|
|
408
411
|
this.labelElement = labelText;
|
|
409
412
|
}
|
|
410
413
|
startLabelEdit(labelElement) {
|
|
414
|
+
if (this._labelEditor) {
|
|
415
|
+
this._labelEditor.querySelector("input")?.focus();
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
411
418
|
const foreignObject = document.createElementNS("http://www.w3.org/2000/svg", "foreignObject");
|
|
412
419
|
foreignObject.setAttribute("x", this.x + 5);
|
|
413
420
|
foreignObject.setAttribute("y", this.y - 20);
|
|
@@ -439,12 +446,16 @@ var Frame = class {
|
|
|
439
446
|
`;
|
|
440
447
|
foreignObject.appendChild(input);
|
|
441
448
|
this.group.appendChild(foreignObject);
|
|
449
|
+
this._labelEditor = foreignObject;
|
|
442
450
|
labelElement.style.display = "none";
|
|
443
451
|
setTimeout(() => {
|
|
444
452
|
input.focus();
|
|
445
453
|
input.select();
|
|
446
454
|
}, 10);
|
|
455
|
+
let finished = false;
|
|
447
456
|
const finishEdit = () => {
|
|
457
|
+
if (finished) return;
|
|
458
|
+
finished = true;
|
|
448
459
|
const newName = input.value.trim() || "Frame";
|
|
449
460
|
if (newName !== oldName) {
|
|
450
461
|
pushTransformAction(
|
|
@@ -468,7 +479,8 @@ var Frame = class {
|
|
|
468
479
|
);
|
|
469
480
|
}
|
|
470
481
|
this.frameName = newName;
|
|
471
|
-
|
|
482
|
+
foreignObject.remove();
|
|
483
|
+
this._labelEditor = null;
|
|
472
484
|
labelElement.style.display = "block";
|
|
473
485
|
labelElement.textContent = this.frameName;
|
|
474
486
|
this.labelElement = labelElement;
|
|
@@ -480,7 +492,9 @@ var Frame = class {
|
|
|
480
492
|
finishEdit();
|
|
481
493
|
} else if (e.key === "Escape") {
|
|
482
494
|
e.preventDefault();
|
|
483
|
-
|
|
495
|
+
finished = true;
|
|
496
|
+
foreignObject.remove();
|
|
497
|
+
this._labelEditor = null;
|
|
484
498
|
labelElement.style.display = "block";
|
|
485
499
|
}
|
|
486
500
|
});
|
|
@@ -1237,4 +1251,4 @@ var Frame = class {
|
|
|
1237
1251
|
export {
|
|
1238
1252
|
Frame
|
|
1239
1253
|
};
|
|
1240
|
-
//# sourceMappingURL=chunk-
|
|
1254
|
+
//# sourceMappingURL=chunk-KVAQPCUH.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/shapes/Frame.js"],
|
|
4
|
+
"sourcesContent": ["/* eslint-disable */\n// Frame shape class - extracted from frameHolder.js\n// Depends on globals: svg, shapes, currentShape, currentZoom\n\nimport { cleanupAttachments } from '../tools/arrowTool.js';\nimport { registerRotationAnchor } from '../core/ScreenSpaceControls.js';\n\nfunction getSVGCoordsFromMouse(e) {\n const viewBox = svg.viewBox.baseVal;\n const rect = svg.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const mouseY = e.clientY - rect.top;\n const svgX = viewBox.x + (mouseX / rect.width) * viewBox.width;\n const svgY = viewBox.y + (mouseY / rect.height) * viewBox.height;\n return { x: svgX, y: svgY };\n}\n\nlet dragOldPosFrame = null;\n\nclass Frame {\n constructor(x, y, width, height, options = {}) {\n this.x = x;\n this.y = y;\n this.width = width;\n this.height = height;\n this.rotation = options.rotation || 0;\n this.frameName = options.frameName || \"Frame\";\n this.fillStyle = options.fillStyle || \"transparent\"; // 'transparent' | 'solid' | 'grid'\n this.fillColor = options.fillColor || \"#1e1e28\";\n this.gridSize = options.gridSize || 20;\n // Issue #38 follow-up: read the grid stroke from a CSS custom\n // property so the frame grid stays visible in both themes. The\n // var is defined in globals.css for both `body.canvas-mode`\n // (dark-on-light) and `body.canvas-mode.theme-dark` (light-on-dark).\n // The literal here is the dark-theme fallback for environments\n // (tests, embeds) without the canvas-mode CSS in scope.\n this.gridColor = options.gridColor || \"var(--lixsketch-grid-fine, rgba(255,255,255,0.06))\";\n this.options = {\n stroke: options.stroke || \"#555\",\n strokeWidth: options.strokeWidth || 1,\n fill: options.fill || \"transparent\",\n opacity: options.opacity || 1,\n ...options\n };\n\n this.element = null;\n this.group = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n this.isSelected = false;\n this.anchors = [];\n this.shapeName = \"frame\";\n this.shapeID = `frame-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n this.group.setAttribute('id', this.shapeID);\n\n // Create clipping group for contained shapes\n this.clipGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n this.clipPath = document.createElementNS('http://www.w3.org/2000/svg', 'clipPath');\n this.clipRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n \n // Set up clipping\n this.clipId = `clip-${this.shapeID}`;\n this.clipPath.setAttribute('id', this.clipId);\n this.clipPath.appendChild(this.clipRect);\n this.clipGroup.setAttribute('clip-path', `url(#${this.clipId})`);\n \n // Add clip path to defs\n let defs = svg.querySelector('defs');\n if (!defs) {\n defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\n svg.appendChild(defs);\n }\n defs.appendChild(this.clipPath);\n\n // Array to hold shapes inside this frame\n this.containedShapes = [];\n\n svg.appendChild(this.group);\n svg.appendChild(this.clipGroup);\n this.draw();\n this.updateClipPath();\n }\n\n draw() {\n // Clear previous elements\n while (this.group.firstChild) {\n this.group.removeChild(this.group.firstChild);\n }\n this.anchors = [];\n\n // Ensure defs exists for grid pattern\n let defs = svg.querySelector('defs');\n if (!defs) {\n defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\n svg.appendChild(defs);\n }\n\n // Determine fill based on fillStyle\n let fillValue = \"transparent\";\n if (this.fillStyle === 'solid') {\n fillValue = this.fillColor;\n } else if (this.fillStyle === 'grid') {\n // Create or update a grid pattern unique to this frame\n const patternId = `frame-grid-${this.shapeID}`;\n let pattern = defs.querySelector(`#${patternId}`);\n if (!pattern) {\n pattern = document.createElementNS('http://www.w3.org/2000/svg', 'pattern');\n pattern.setAttribute('id', patternId);\n pattern.setAttribute('patternUnits', 'userSpaceOnUse');\n defs.appendChild(pattern);\n }\n // Update pattern attributes\n pattern.setAttribute('x', this.x);\n pattern.setAttribute('y', this.y);\n pattern.setAttribute('width', this.gridSize);\n pattern.setAttribute('height', this.gridSize);\n // Clear and rebuild pattern content\n while (pattern.firstChild) pattern.removeChild(pattern.firstChild);\n // Background fill\n const bgRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n bgRect.setAttribute('width', this.gridSize);\n bgRect.setAttribute('height', this.gridSize);\n bgRect.setAttribute('fill', this.fillColor);\n pattern.appendChild(bgRect);\n // Grid lines\n const gridPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n gridPath.setAttribute('d', `M ${this.gridSize} 0 L 0 0 0 ${this.gridSize}`);\n gridPath.setAttribute('fill', 'none');\n gridPath.setAttribute('stroke', this.gridColor);\n gridPath.setAttribute('stroke-width', '0.5');\n pattern.appendChild(gridPath);\n fillValue = `url(#${patternId})`;\n }\n\n // Create the frame rectangle\n const frameRect = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n frameRect.setAttribute(\"x\", this.x);\n frameRect.setAttribute(\"y\", this.y);\n frameRect.setAttribute(\"width\", this.width);\n frameRect.setAttribute(\"height\", this.height);\n frameRect.setAttribute(\"stroke\", this.options.stroke);\n frameRect.setAttribute(\"stroke-width\", this.options.strokeWidth);\n frameRect.setAttribute(\"fill\", fillValue);\n frameRect.setAttribute(\"opacity\", this.options.opacity);\n frameRect.setAttribute(\"stroke-dasharray\", \"5,5\");\n frameRect.classList.add(\"frame-rect\");\n\n // Apply rotation\n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n frameRect.setAttribute(\"transform\", `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n }\n\n this.element = frameRect;\n this.group.appendChild(this.element);\n\n // Add label\n this.addFrameLabel();\n\n // Re-attach frame image if present\n if (this._frameImageURL) {\n this.setImageFromURL(this._frameImageURL, this._frameImageFit || 'cover');\n }\n\n // Add selection anchors if selected\n if (this.isSelected) {\n this.addAnchors();\n }\n\n // Update clip path\n this.updateClipPath();\n }\n\n updateAttachedArrows() {\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.forEach(shape => {\n if (shape.shapeName === 'arrow') {\n let needsUpdate = false;\n \n // Check if arrow is attached to this frame\n if (shape.attachedToStart && shape.attachedToStart.shape === this) {\n needsUpdate = true;\n }\n if (shape.attachedToEnd && shape.attachedToEnd.shape === this) {\n needsUpdate = true;\n }\n \n if (needsUpdate) {\n shape.updateAttachments();\n }\n }\n });\n }\n }\n\n updateClipPath() {\n // Update the clipping rectangle to match frame dimensions\n this.clipRect.setAttribute(\"x\", this.x);\n this.clipRect.setAttribute(\"y\", this.y);\n this.clipRect.setAttribute(\"width\", this.width);\n this.clipRect.setAttribute(\"height\", this.height);\n \n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n this.clipRect.setAttribute(\"transform\", `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n } else {\n this.clipRect.removeAttribute(\"transform\");\n }\n }\n\n addShapeToFrame(shape) {\n if (shape && !this.containedShapes.includes(shape)) {\n const oldFrame = shape.parentFrame;\n\n // Remove from other frames first\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.forEach(otherFrame => {\n if (otherFrame.shapeName === 'frame' && otherFrame !== this) {\n otherFrame.removeShapeFromFrame(shape);\n }\n });\n }\n\n this.containedShapes.push(shape);\n shape.parentFrame = this;\n\n // Only move to clipped group if not currently being dragged\n const el = shape.group || shape.element;\n if (el && el.parentNode && !shape.isDraggedOutTemporarily) {\n el.parentNode.removeChild(el);\n this.clipGroup.appendChild(el);\n }\n\n // For sub-frames, also move their clipGroup into our clipGroup\n if (shape.shapeName === 'frame' && shape.clipGroup) {\n if (shape.clipGroup.parentNode) {\n shape.clipGroup.parentNode.removeChild(shape.clipGroup);\n }\n this.clipGroup.appendChild(shape.clipGroup);\n }\n }\n}\n\n removeShapeFromFrame(shape) {\n const index = this.containedShapes.indexOf(shape);\n if (index > -1) {\n this.containedShapes.splice(index, 1);\n if (shape.parentFrame === this) {\n shape.parentFrame = null;\n }\n\n // Move shape's group/element back to main SVG if it's in the clipped group\n const el = shape.group || shape.element;\n if (el && el.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(el);\n svg.appendChild(el);\n }\n\n // For sub-frames, also move their clipGroup back to main SVG\n if (shape.shapeName === 'frame' && shape.clipGroup && shape.clipGroup.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(shape.clipGroup);\n svg.appendChild(shape.clipGroup);\n }\n\n delete shape.isDraggedOutTemporarily;\n }\n}\n\n // Check if a point is inside the frame bounds\n isPointInFrame(x, y) {\n // Simple bounding box check (can be enhanced for rotation)\n return x >= this.x && x <= this.x + this.width &&\n y >= this.y && y <= this.y + this.height;\n }\n\n // Check if a shape overlaps with this frame\n isShapeInFrame(shape) {\n if (!shape || shape === this) return false;\n \n const shapeX = shape.x || 0;\n const shapeY = shape.y || 0;\n const shapeWidth = shape.width || 0;\n const shapeHeight = shape.height || 0;\n \n // Check if the center of the shape is inside the frame (for better UX)\n const shapeCenterX = shapeX + shapeWidth / 2;\n const shapeCenterY = shapeY + shapeHeight / 2;\n \n return shapeCenterX >= this.x && shapeCenterX <= this.x + this.width &&\n shapeCenterY >= this.y && shapeCenterY <= this.y + this.height;\n}\n\nupdateContainedShapes(applyClipping = true) {\n // Check all shapes to see if they should be in this frame\n if (typeof shapes === 'undefined' || !Array.isArray(shapes)) return;\n shapes.forEach(shape => {\n if (shape !== this) {\n // Skip frames that are larger than or equal to this frame (prevent parent containing child loops)\n if (shape.shapeName === 'frame') {\n const shapeArea = (shape.width || 0) * (shape.height || 0);\n const thisArea = (this.width || 0) * (this.height || 0);\n if (shapeArea >= thisArea) return;\n }\n const isInFrame = this.isShapeInFrame(shape);\n const isAlreadyContained = this.containedShapes.includes(shape);\n\n if (isInFrame && !isAlreadyContained) {\n this.addShapeToFrame(shape);\n // Don't apply clipping if we're not supposed to\n if (!applyClipping) {\n const el = shape.group || shape.element;\n if (el && el.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(el);\n svg.appendChild(el);\n shape.isDraggedOutTemporarily = true;\n }\n }\n } else if (!isInFrame && isAlreadyContained) {\n this.removeShapeFromFrame(shape);\n }\n }\n });\n \n // Update clip path\n this.updateClipPath();\n}\n\nhighlightFrame() {\n if (this.element) {\n this.element.setAttribute('stroke', '#5B57D1');\n this.element.setAttribute('stroke-width', '3');\n this.element.setAttribute('opacity', '0.7');\n }\n}\n\n// Remove frame highlight\nremoveHighlight() {\n if (this.element) {\n this.element.setAttribute('stroke', this.options.stroke);\n this.element.setAttribute('stroke-width', this.options.strokeWidth);\n this.element.setAttribute('opacity', this.options.opacity);\n }\n}\n \n\nmove(dx, dy) {\n this.x += dx;\n this.y += dy;\n\n // Move all contained shapes with the frame\n this.containedShapes.forEach(shape => {\n if (shape) {\n // Mark shape as being moved by frame to prevent frame containment updates\n shape.isBeingMovedByFrame = true;\n\n // Use shape's own move method for proper handling of all shape types\n if (typeof shape.move === 'function') {\n shape.move(dx, dy);\n } else {\n shape.x += dx;\n shape.y += dy;\n }\n\n // Force redraw for shapes whose move() doesn't auto-redraw\n if (typeof shape.draw === 'function') {\n shape.draw();\n }\n\n // Update bounding box for freehand strokes\n if (typeof shape.updateBoundingBox === 'function') {\n shape.updateBoundingBox();\n }\n\n // Remove the flag after movement\n delete shape.isBeingMovedByFrame;\n }\n });\n\n // Update arrows attached to this frame\n this.updateAttachedArrows();\n\n this.draw();\n this.updateClipPath();\n}\n\n handleResizeLegacy(anchorIndex, currentPos, startPos, initialFrame) {\n // Legacy version - superseded by the handleResize below with contained shapes scaling\n const dx = currentPos.x - startPos.x;\n const dy = currentPos.y - startPos.y;\n\n switch (anchorIndex) {\n case 0: this.x = initialFrame.x + dx; this.y = initialFrame.y + dy; this.width = Math.max(10, initialFrame.width - dx); this.height = Math.max(10, initialFrame.height - dy); break;\n case 1: this.y = initialFrame.y + dy; this.height = Math.max(10, initialFrame.height - dy); break;\n case 2: this.y = initialFrame.y + dy; this.width = Math.max(10, initialFrame.width + dx); this.height = Math.max(10, initialFrame.height - dy); break;\n case 3: this.width = Math.max(10, initialFrame.width + dx); break;\n case 4: this.width = Math.max(10, initialFrame.width + dx); this.height = Math.max(10, initialFrame.height + dy); break;\n case 5: this.height = Math.max(10, initialFrame.height + dy); break;\n case 6: this.x = initialFrame.x + dx; this.width = Math.max(10, initialFrame.width - dx); this.height = Math.max(10, initialFrame.height + dy); break;\n case 7: this.x = initialFrame.x + dx; this.width = Math.max(10, initialFrame.width - dx); break;\n }\n this.updateAttachedArrows();\n this.updateContainedShapes();\n}\n destroy() {\n const isDiagramFrame = !!this._diagramType;\n\n [...this.containedShapes].forEach(shape => {\n if (isDiagramFrame) {\n // Diagram/graph frame: destroy contained shapes with the frame\n if (typeof window.cleanupAttachments === 'function') {\n window.cleanupAttachments(shape);\n }\n const el = shape.group || shape.element;\n if (el && el.parentNode) {\n el.parentNode.removeChild(el);\n }\n if (shape.shapeName === 'frame') {\n if (shape.clipGroup && shape.clipGroup.parentNode) {\n shape.clipGroup.parentNode.removeChild(shape.clipGroup);\n }\n if (shape.clipPath && shape.clipPath.parentNode) {\n shape.clipPath.parentNode.removeChild(shape.clipPath);\n }\n }\n const idx = shapes.indexOf(shape);\n if (idx > -1) {\n shapes.splice(idx, 1);\n }\n } else {\n // Regular frame: release contained shapes back to canvas\n const el = shape.group || shape.element;\n if (el) {\n if (el.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(el);\n }\n svg.appendChild(el);\n }\n if (shape.shapeName === 'frame' && shape.clipGroup) {\n if (shape.clipGroup.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(shape.clipGroup);\n }\n svg.appendChild(shape.clipGroup);\n }\n }\n shape.parentFrame = null;\n delete shape.isBeingMovedByFrame;\n });\n this.containedShapes = [];\n\n // Remove clip path\n if (this.clipPath && this.clipPath.parentNode) {\n this.clipPath.parentNode.removeChild(this.clipPath);\n }\n\n // Remove groups (clipGroup should be empty now)\n if (this.clipGroup && this.clipGroup.parentNode) {\n this.clipGroup.parentNode.removeChild(this.clipGroup);\n }\n\n if (this.group && this.group.parentNode) {\n this.group.parentNode.removeChild(this.group);\n }\n\n const index = shapes.indexOf(this);\n if (index > -1) {\n shapes.splice(index, 1);\n }\n if (currentShape === this) {\n currentShape = null;\n }\n }\n\n addFrameLabel() {\n const labelText = document.createElementNS(\"http://www.w3.org/2000/svg\", \"text\");\n labelText.setAttribute(\"x\", this.x + 5);\n labelText.setAttribute(\"y\", this.y - 10);\n labelText.setAttribute(\"font-size\", `${16 / currentZoom}px`);\n labelText.setAttribute(\"fill\", this.options.labelColor || this.options.stroke);\n labelText.setAttribute(\"font-family\", \"lixFont\");\n labelText.textContent = this.frameName || \"Frame\";\n labelText.style.cursor = \"pointer\";\n labelText.style.userSelect = \"none\";\n labelText.style.pointerEvents = \"all\";\n \n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n labelText.setAttribute(\"transform\", `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n }\n \n // Do not let the first click select/redraw the frame: replacing the label\n // between clicks prevents the browser from ever emitting `dblclick`.\n labelText.addEventListener('pointerdown', (e) => e.stopPropagation());\n labelText.addEventListener('click', (e) => e.stopPropagation());\n\n // Add double-click event for renaming\n labelText.addEventListener('dblclick', (e) => {\n e.stopPropagation();\n this.startLabelEdit(labelText);\n });\n \n this.group.appendChild(labelText);\n this.labelElement = labelText;\n}\n\nstartLabelEdit(labelElement) {\n if (this._labelEditor) {\n this._labelEditor.querySelector('input')?.focus();\n return;\n }\n // Create a foreignObject to hold an HTML input\n const foreignObject = document.createElementNS(\"http://www.w3.org/2000/svg\", \"foreignObject\");\n foreignObject.setAttribute(\"x\", this.x + 5);\n foreignObject.setAttribute(\"y\", this.y - 20);\n foreignObject.setAttribute(\"width\", Math.max(100, this.width - 10));\n foreignObject.setAttribute(\"height\", 20);\n \n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n foreignObject.setAttribute(\"transform\", `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n }\n \n // Create input element\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.value = this.frameName || \"Frame\";\n const oldName = this.frameName; // Store old name for undo\n \n input.style.cssText = `\n position: absolute;\n width: 100%;\n height: 20px;\n border: 1px solid #5B57D1;\n background: transparent;\n color: ${this.options.stroke};\n font-family: \"lixFont\";\n font-size: ${15 / currentZoom}px;\n padding: 2px 10px;\n margin: 0;\n outline: none;\n border-radius: 2px;\n box-sizing: border-box;\n `;\n \n foreignObject.appendChild(input);\n this.group.appendChild(foreignObject);\n this._labelEditor = foreignObject;\n \n // Hide the original label\n labelElement.style.display = \"none\";\n \n // Focus and select the text\n setTimeout(() => {\n input.focus();\n input.select();\n }, 10);\n \n let finished = false;\n const finishEdit = () => {\n if (finished) return;\n finished = true;\n const newName = input.value.trim() || \"Frame\";\n \n // Track name change in undo system if it actually changed\n if (newName !== oldName) {\n pushTransformAction(this, \n { \n x: this.x, \n y: this.y, \n width: this.width, \n height: this.height, \n rotation: this.rotation,\n frameName: oldName \n },\n { \n x: this.x, \n y: this.y, \n width: this.width, \n height: this.height, \n rotation: this.rotation,\n frameName: newName \n }\n );\n }\n \n this.frameName = newName;\n \n // Remove the input\n foreignObject.remove();\n this._labelEditor = null;\n \n // Show and update the label\n labelElement.style.display = \"block\";\n labelElement.textContent = this.frameName;\n \n this.labelElement = labelElement;\n };\n \n // Handle input events\n input.addEventListener('blur', finishEdit);\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n finishEdit();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n finished = true;\n // Cancel edit - restore original name\n foreignObject.remove();\n this._labelEditor = null;\n labelElement.style.display = \"block\";\n }\n });\n \n // Prevent the input from interfering with other interactions\n input.addEventListener('pointerdown', (e) => e.stopPropagation());\n input.addEventListener('pointermove', (e) => e.stopPropagation());\n input.addEventListener('pointerup', (e) => e.stopPropagation());\n}\n selectFrame() {\n this.isSelected = true;\n this.draw();\n this._showSidebar();\n }\n\n _showSidebar() {\n // React sidebar bridge\n if (window.__showSidebarForShape) {\n window.__showSidebarForShape('frame');\n }\n\n const sidebar = document.getElementById('frameSideBar');\n const renameInput = document.getElementById('frameRenameInput');\n const resizeBtn = document.getElementById('frameResizeToFit');\n if (!sidebar) return;\n\n sidebar.classList.remove('hidden');\n\n if (renameInput) {\n renameInput.value = this.frameName || 'Frame';\n // Replace old listener by cloning\n const newInput = renameInput.cloneNode(true);\n renameInput.parentNode.replaceChild(newInput, renameInput);\n newInput.addEventListener('input', () => {\n const val = newInput.value.trim() || 'Frame';\n this.frameName = val;\n if (this.labelElement) this.labelElement.textContent = val;\n });\n newInput.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') newInput.blur();\n });\n newInput.addEventListener('pointerdown', (e) => e.stopPropagation());\n }\n\n if (resizeBtn) {\n const newBtn = resizeBtn.cloneNode(true);\n resizeBtn.parentNode.replaceChild(newBtn, resizeBtn);\n newBtn.addEventListener('click', () => this.resizeToFit());\n }\n }\n\n resizeToFit() {\n if (this.containedShapes.length === 0) return;\n\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n\n this.containedShapes.forEach(shape => {\n if (shape.shapeName === 'arrow' || shape.shapeName === 'line') {\n [shape.startPoint, shape.endPoint].filter(Boolean).forEach(p => {\n minX = Math.min(minX, p.x);\n minY = Math.min(minY, p.y);\n maxX = Math.max(maxX, p.x);\n maxY = Math.max(maxY, p.y);\n });\n } else if (typeof shape.x === 'number' && typeof shape.y === 'number') {\n const w = shape.width || 0;\n const h = shape.height || 0;\n minX = Math.min(minX, shape.x);\n minY = Math.min(minY, shape.y);\n maxX = Math.max(maxX, shape.x + w);\n maxY = Math.max(maxY, shape.y + h);\n }\n });\n\n if (!isFinite(minX)) return;\n\n const padding = 20;\n const oldState = { x: this.x, y: this.y, width: this.width, height: this.height, rotation: this.rotation };\n\n this.x = minX - padding;\n this.y = minY - padding;\n this.width = (maxX - minX) + padding * 2;\n this.height = (maxY - minY) + padding * 2;\n\n pushTransformAction(this, oldState, { x: this.x, y: this.y, width: this.width, height: this.height, rotation: this.rotation });\n this.draw();\n this.updateClipPath();\n this.updateContainedShapes();\n }\n\n removeSelection() {\n this.anchors.forEach(anchor => {\n if (anchor.parentNode) {\n anchor.parentNode.removeChild(anchor);\n }\n });\n this.anchors = [];\n this.isSelected = false;\n this.draw();\n const sidebar = document.getElementById('frameSideBar');\n if (sidebar) sidebar.classList.add('hidden');\n }\n\n addAnchors() {\n const anchorSize = 8 / currentZoom;\n const anchorStrokeWidth = 2 / currentZoom;\n\n // Calculate anchor positions (corners + midpoints + rotation handle)\n const anchorPositions = [\n { x: this.x, y: this.y, cursor: 'nw-resize', type: 'corner' }, // Top-left\n { x: this.x + this.width / 2, y: this.y, cursor: 'n-resize', type: 'edge' }, // Top-middle\n { x: this.x + this.width, y: this.y, cursor: 'ne-resize', type: 'corner' }, // Top-right\n { x: this.x + this.width, y: this.y + this.height / 2, cursor: 'e-resize', type: 'edge' }, // Right-middle\n { x: this.x + this.width, y: this.y + this.height, cursor: 'se-resize', type: 'corner' }, // Bottom-right\n { x: this.x + this.width / 2, y: this.y + this.height, cursor: 's-resize', type: 'edge' }, // Bottom-middle\n { x: this.x, y: this.y + this.height, cursor: 'sw-resize', type: 'corner' }, // Bottom-left\n { x: this.x, y: this.y + this.height / 2, cursor: 'w-resize', type: 'edge' }, // Left-middle\n ];\n\n // Add rotation handle\n const rotationHandleDistance = 30 / currentZoom;\n const rotationHandle = {\n x: this.x + this.width / 2,\n y: this.y - rotationHandleDistance,\n cursor: 'grab',\n type: 'rotation'\n };\n anchorPositions.push(rotationHandle);\n\n // Create selection outline first (behind anchors)\n const outline = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n outline.setAttribute('x', this.x);\n outline.setAttribute('y', this.y);\n outline.setAttribute('width', this.width);\n outline.setAttribute('height', this.height);\n outline.setAttribute('fill', 'none');\n outline.setAttribute('stroke', '#5B57D1');\n outline.setAttribute('stroke-width', 1.5);\n outline.setAttribute('vector-effect', 'non-scaling-stroke');\n outline.setAttribute('stroke-dasharray', '4 2');\n outline.setAttribute('style', 'pointer-events: none;');\n\n // Apply rotation to outline if needed\n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n outline.setAttribute('transform', `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n }\n\n this.group.appendChild(outline);\n this.selectionOutline = outline;\n\n anchorPositions.forEach((position, index) => {\n let anchor;\n \n if (position.type === 'rotation') {\n // Create rotation handle (circle)\n anchor = document.createElementNS(\"http://www.w3.org/2000/svg\", \"circle\");\n anchor.setAttribute(\"cx\", position.x);\n anchor.setAttribute(\"cy\", position.y);\n anchor.setAttribute(\"r\", anchorSize);\n anchor.setAttribute(\"fill\", \"#121212\"); \n anchor.setAttribute(\"stroke\", \"#5B57D1\"); \n anchor.setAttribute(\"stroke-width\", anchorStrokeWidth);\n anchor.setAttribute(\"vector-effect\", \"non-scaling-stroke\");\n\n // Add rotation line\n const rotationLine = document.createElementNS(\"http://www.w3.org/2000/svg\", \"line\");\n rotationLine.setAttribute(\"x1\", this.x + this.width / 2);\n rotationLine.setAttribute(\"y1\", this.y);\n rotationLine.setAttribute(\"x2\", position.x);\n rotationLine.setAttribute(\"y2\", position.y);\n rotationLine.setAttribute(\"stroke\", \"#5B57D1\"); \n rotationLine.setAttribute(\"stroke-width\", anchorStrokeWidth);\n rotationLine.setAttribute(\"vector-effect\", \"non-scaling-stroke\");\n\n // Apply rotation to rotation line if needed\n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n rotationLine.setAttribute('transform', `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n }\n \n this.group.appendChild(rotationLine);\n registerRotationAnchor(anchor, {\n radius: 8,\n edgeY: this.y,\n line: rotationLine,\n lineEnd: '2',\n });\n } else {\n // Create resize handle (rectangle)\n anchor = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n anchor.setAttribute(\"x\", position.x - anchorSize / 2);\n anchor.setAttribute(\"y\", position.y - anchorSize / 2);\n anchor.setAttribute(\"width\", anchorSize);\n anchor.setAttribute(\"height\", anchorSize);\n anchor.setAttribute(\"fill\", \"#121212\"); \n anchor.setAttribute(\"stroke\", \"#5B57D1\"); \n anchor.setAttribute(\"stroke-width\", anchorStrokeWidth);\n anchor.setAttribute(\"vector-effect\", \"non-scaling-stroke\");\n }\n\n // Apply rotation to anchor if needed\n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n anchor.setAttribute('transform', `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n }\n\n anchor.style.cursor = position.cursor;\n anchor.addEventListener('pointerdown', (e) => this.startAnchorDrag(e, index));\n \n this.anchors.push(anchor);\n this.group.appendChild(anchor);\n });\n }\n\n startAnchorDrag(e, index) {\n e.stopPropagation();\n e.preventDefault();\n\n // Store initial state for undo\n dragOldPosFrame = {\n x: this.x,\n y: this.y,\n width: this.width,\n height: this.height,\n rotation: this.rotation\n };\n\n const startMousePos = getSVGCoordsFromMouse(e);\n const initialFrame = {\n x: this.x,\n y: this.y,\n width: this.width,\n height: this.height,\n rotation: this.rotation\n };\n\n const onPointerMove = (event) => {\n const currentMousePos = getSVGCoordsFromMouse(event);\n \n if (index === 8) { // Rotation handle\n this.handleRotation(currentMousePos, initialFrame);\n } else {\n this.handleResize(index, currentMousePos, startMousePos, initialFrame);\n }\n \n this.draw();\n this.updateContainedShapes();\n };\n\n const onPointerUp = () => {\n if (dragOldPosFrame) {\n const newPos = {\n x: this.x,\n y: this.y,\n width: this.width,\n height: this.height,\n rotation: this.rotation\n };\n pushTransformAction(this, dragOldPosFrame, newPos);\n dragOldPosFrame = null;\n }\n \n svg.removeEventListener('pointermove', onPointerMove);\n svg.removeEventListener('pointerup', onPointerUp);\n svg.style.cursor = 'default';\n };\n\n svg.addEventListener('pointermove', onPointerMove);\n svg.addEventListener('pointerup', onPointerUp);\n }\n\n handleRotation(mousePos, initialFrame) {\n const centerX = initialFrame.x + initialFrame.width / 2;\n const centerY = initialFrame.y + initialFrame.height / 2;\n \n const angle = Math.atan2(mousePos.y - centerY, mousePos.x - centerX);\n const newRotation = (angle * 180 / Math.PI + 90) % 360;\n const angleDiff = newRotation - this.rotation;\n const angleRad = angleDiff * Math.PI / 180;\n const cosAngle = Math.cos(angleRad);\n const sinAngle = Math.sin(angleRad);\n \n // Store the rotation center for contained shapes\n const rotationCenter = { x: centerX, y: centerY };\n \n // Rotate all contained shapes around the frame's center\n this.containedShapes.forEach(shape => {\n if (!shape) return;\n \n // Mark shape as being moved by frame to prevent frame containment updates\n shape.isBeingMovedByFrame = true;\n \n switch (shape.shapeName) {\n case 'rectangle':\n case 'frame':\n case 'image':\n case 'icon':\n // Get shape's current center\n const shapeCenterX = shape.x + shape.width / 2;\n const shapeCenterY = shape.y + shape.height / 2;\n \n // Calculate relative position from rotation center\n const relativeX = shapeCenterX - rotationCenter.x;\n const relativeY = shapeCenterY - rotationCenter.y;\n \n // Apply rotation to get new center position\n const newCenterX = rotationCenter.x + (relativeX * cosAngle - relativeY * sinAngle);\n const newCenterY = rotationCenter.y + (relativeX * sinAngle + relativeY * cosAngle);\n \n // Update shape position\n shape.x = newCenterX - shape.width / 2;\n shape.y = newCenterY - shape.height / 2;\n shape.rotation = (shape.rotation || 0) + angleDiff;\n \n if (typeof shape.draw === 'function') {\n shape.draw();\n }\n break;\n \n case 'circle':\n // Get circle's center\n const circleCenterX = shape.x;\n const circleCenterY = shape.y;\n \n // Calculate relative position from rotation center\n const relativeCircleX = circleCenterX - rotationCenter.x;\n const relativeCircleY = circleCenterY - rotationCenter.y;\n \n // Apply rotation\n const newCircleCenterX = rotationCenter.x + (relativeCircleX * cosAngle - relativeCircleY * sinAngle);\n const newCircleCenterY = rotationCenter.y + (relativeCircleX * sinAngle + relativeCircleY * cosAngle);\n \n shape.x = newCircleCenterX;\n shape.y = newCircleCenterY;\n shape.rotation = (shape.rotation || 0) + angleDiff;\n \n if (typeof shape.draw === 'function') {\n shape.draw();\n }\n break;\n \n case 'line':\n case 'arrow':\n // Calculate relative positions for start and end points\n const relativeStartX = shape.startPoint.x - rotationCenter.x;\n const relativeStartY = shape.startPoint.y - rotationCenter.y;\n const relativeEndX = shape.endPoint.x - rotationCenter.x;\n const relativeEndY = shape.endPoint.y - rotationCenter.y;\n \n // Apply rotation to both points\n const newStartX = rotationCenter.x + (relativeStartX * cosAngle - relativeStartY * sinAngle);\n const newStartY = rotationCenter.y + (relativeStartX * sinAngle + relativeStartY * cosAngle);\n const newEndX = rotationCenter.x + (relativeEndX * cosAngle - relativeEndY * sinAngle);\n const newEndY = rotationCenter.y + (relativeEndX * sinAngle + relativeEndY * cosAngle);\n \n shape.startPoint.x = newStartX;\n shape.startPoint.y = newStartY;\n shape.endPoint.x = newEndX;\n shape.endPoint.y = newEndY;\n \n if (shape.shapeName === 'arrow' && shape.arrowCurved && typeof shape.initializeCurveControlPoints === 'function') {\n shape.initializeCurveControlPoints();\n }\n if (typeof shape.draw === 'function') {\n shape.draw();\n }\n break;\n \n case 'text':\n case 'code':\n // Get text/code bounds for center calculation\n const textOrCodeEl = shape.group ? (shape.group.querySelector('text') || shape.group.querySelector('foreignObject')) : null;\n if (textOrCodeEl) {\n const bbox = textOrCodeEl.getBBox();\n const transform = shape.group.transform.baseVal.consolidate();\n const matrix = transform ? transform.matrix : { e: 0, f: 0 };\n\n const textCenterX = bbox.x + matrix.e + bbox.width / 2;\n const textCenterY = bbox.y + matrix.f + bbox.height / 2;\n\n // Calculate relative position\n const relativeTextX = textCenterX - rotationCenter.x;\n const relativeTextY = textCenterY - rotationCenter.y;\n\n // Apply rotation\n const newTextCenterX = rotationCenter.x + (relativeTextX * cosAngle - relativeTextY * sinAngle);\n const newTextCenterY = rotationCenter.y + (relativeTextX * sinAngle + relativeTextY * cosAngle);\n\n // Update position\n const newTransformX = newTextCenterX - bbox.width / 2;\n const newTransformY = newTextCenterY - bbox.height / 2;\n const newShapeRotation = (shape.rotation || 0) + angleDiff;\n\n const textCenterRelativeX = bbox.width / 2;\n const textCenterRelativeY = bbox.height / 2;\n\n shape.group.setAttribute('transform',\n `translate(${newTransformX}, ${newTransformY}) rotate(${newShapeRotation}, ${textCenterRelativeX}, ${textCenterRelativeY})`\n );\n\n shape.x = newTransformX;\n shape.y = newTransformY;\n shape.rotation = newShapeRotation;\n }\n break;\n \n case 'freehandStroke':\n if (shape.points && Array.isArray(shape.points)) {\n // Rotate each point in the stroke\n shape.points = shape.points.map(point => {\n if (!Array.isArray(point) || point.length < 2) return point;\n \n const relativePointX = point[0] - rotationCenter.x;\n const relativePointY = point[1] - rotationCenter.y;\n \n const newPointX = rotationCenter.x + (relativePointX * cosAngle - relativePointY * sinAngle);\n const newPointY = rotationCenter.y + (relativePointX * sinAngle + relativePointY * cosAngle);\n \n return [newPointX, newPointY, point[2] || 0.5];\n });\n \n if (typeof shape.updateBoundingBox === 'function') {\n shape.updateBoundingBox();\n }\n if (typeof shape.draw === 'function') {\n shape.draw();\n }\n }\n break;\n }\n \n // Update arrows attached to the contained shape\n if (typeof shape.updateAttachedArrows === 'function') {\n shape.updateAttachedArrows();\n }\n \n // Remove the flag after rotation\n delete shape.isBeingMovedByFrame;\n });\n \n // Update the frame's rotation\n this.rotation = newRotation;\n \n // Update arrows attached to this frame\n this.updateAttachedArrows();\n }\n\n handleResize(anchorIndex, currentPos, startPos, initialFrame) {\n const rawDx = currentPos.x - startPos.x;\n const rawDy = currentPos.y - startPos.y;\n\n // Rotate delta to local (unrotated) space when frame is rotated\n const rad = (this.rotation || 0) * Math.PI / 180;\n const cosR = Math.cos(rad);\n const sinR = Math.sin(rad);\n const dx = rawDx * cosR + rawDy * sinR;\n const dy = -rawDx * sinR + rawDy * cosR;\n\n // Store old frame for scale calculation\n const oldX = this.x, oldY = this.y, oldW = this.width, oldH = this.height;\n\n // Compute new dimensions using local-space deltas\n let newW, newH;\n // Fixed corner relative to initial frame origin: (fixRelX, fixRelY)\n let fixRelX, fixRelY;\n\n switch (anchorIndex) {\n case 0: // Top-left\n newW = Math.max(10, initialFrame.width - dx);\n newH = Math.max(10, initialFrame.height - dy);\n fixRelX = initialFrame.width; fixRelY = initialFrame.height;\n break;\n case 1: // Top-middle\n newW = initialFrame.width;\n newH = Math.max(10, initialFrame.height - dy);\n fixRelX = 0; fixRelY = initialFrame.height;\n break;\n case 2: // Top-right\n newW = Math.max(10, initialFrame.width + dx);\n newH = Math.max(10, initialFrame.height - dy);\n fixRelX = 0; fixRelY = initialFrame.height;\n break;\n case 3: // Right-middle\n newW = Math.max(10, initialFrame.width + dx);\n newH = initialFrame.height;\n fixRelX = 0; fixRelY = 0;\n break;\n case 4: // Bottom-right\n newW = Math.max(10, initialFrame.width + dx);\n newH = Math.max(10, initialFrame.height + dy);\n fixRelX = 0; fixRelY = 0;\n break;\n case 5: // Bottom-middle\n newW = initialFrame.width;\n newH = Math.max(10, initialFrame.height + dy);\n fixRelX = 0; fixRelY = 0;\n break;\n case 6: // Bottom-left\n newW = Math.max(10, initialFrame.width - dx);\n newH = Math.max(10, initialFrame.height + dy);\n fixRelX = initialFrame.width; fixRelY = 0;\n break;\n case 7: // Left-middle\n newW = Math.max(10, initialFrame.width - dx);\n newH = initialFrame.height;\n fixRelX = initialFrame.width; fixRelY = 0;\n break;\n }\n\n // Compute new position using fixed-corner constraint\n if (this.rotation && this.rotation !== 0) {\n // Compute rotated world position of the fixed corner in the initial frame\n const iCX = initialFrame.x + initialFrame.width / 2;\n const iCY = initialFrame.y + initialFrame.height / 2;\n const odx = (initialFrame.x + fixRelX) - iCX;\n const ody = (initialFrame.y + fixRelY) - iCY;\n const fixedWorldX = iCX + odx * cosR - ody * sinR;\n const fixedWorldY = iCY + odx * sinR + ody * cosR;\n\n // Where the fixed corner sits in new rect (relative to new origin)\n const fixNewRelX = (fixRelX === 0) ? 0 : newW;\n const fixNewRelY = (fixRelY === 0) ? 0 : newH;\n\n // Solve for new origin\n const ncx = newW / 2;\n const ncy = newH / 2;\n const ndx = fixNewRelX - ncx;\n const ndy = fixNewRelY - ncy;\n const rotX = ncx + ndx * cosR - ndy * sinR;\n const rotY = ncy + ndx * sinR + ndy * cosR;\n\n this.x = fixedWorldX - rotX;\n this.y = fixedWorldY - rotY;\n } else {\n // No rotation - use simple axis-aligned position calculation\n switch (anchorIndex) {\n case 0: this.x = initialFrame.x + (initialFrame.width - newW); this.y = initialFrame.y + (initialFrame.height - newH); break;\n case 1: this.y = initialFrame.y + (initialFrame.height - newH); break;\n case 2: this.y = initialFrame.y + (initialFrame.height - newH); break;\n case 3: break;\n case 4: break;\n case 5: break;\n case 6: this.x = initialFrame.x + (initialFrame.width - newW); break;\n case 7: this.x = initialFrame.x + (initialFrame.width - newW); break;\n }\n }\n\n this.width = newW;\n this.height = newH;\n\n // Scale contained shapes proportionally so nothing falls out\n if (oldW > 0 && oldH > 0) {\n const scaleX = this.width / oldW;\n const scaleY = this.height / oldH;\n\n if (Math.abs(scaleX - 1) > 0.001 || Math.abs(scaleY - 1) > 0.001) {\n this.containedShapes.forEach(shape => {\n if (!shape) return;\n shape.isBeingMovedByFrame = true;\n\n switch (shape.shapeName) {\n case 'rectangle':\n case 'image':\n case 'icon':\n case 'code': {\n const relX = (shape.x - oldX) / oldW;\n const relY = (shape.y - oldY) / oldH;\n const relW = shape.width / oldW;\n const relH = shape.height / oldH;\n shape.x = this.x + relX * this.width;\n shape.y = this.y + relY * this.height;\n shape.width = relW * this.width;\n shape.height = relH * this.height;\n if (typeof shape.draw === 'function') shape.draw();\n break;\n }\n case 'circle': {\n const relCX = (shape.x - oldX) / oldW;\n const relCY = (shape.y - oldY) / oldH;\n shape.x = this.x + relCX * this.width;\n shape.y = this.y + relCY * this.height;\n shape.rx = (shape.rx / oldW) * this.width;\n shape.ry = (shape.ry / oldH) * this.height;\n shape.width = shape.rx * 2;\n shape.height = shape.ry * 2;\n if (typeof shape.draw === 'function') shape.draw();\n break;\n }\n case 'arrow':\n case 'line': {\n const relSX = (shape.startPoint.x - oldX) / oldW;\n const relSY = (shape.startPoint.y - oldY) / oldH;\n const relEX = (shape.endPoint.x - oldX) / oldW;\n const relEY = (shape.endPoint.y - oldY) / oldH;\n shape.startPoint.x = this.x + relSX * this.width;\n shape.startPoint.y = this.y + relSY * this.height;\n shape.endPoint.x = this.x + relEX * this.width;\n shape.endPoint.y = this.y + relEY * this.height;\n if (shape.controlPoint1) {\n const relC1X = (shape.controlPoint1.x - oldX) / oldW;\n const relC1Y = (shape.controlPoint1.y - oldY) / oldH;\n shape.controlPoint1.x = this.x + relC1X * this.width;\n shape.controlPoint1.y = this.y + relC1Y * this.height;\n }\n if (shape.controlPoint2) {\n const relC2X = (shape.controlPoint2.x - oldX) / oldW;\n const relC2Y = (shape.controlPoint2.y - oldY) / oldH;\n shape.controlPoint2.x = this.x + relC2X * this.width;\n shape.controlPoint2.y = this.y + relC2Y * this.height;\n }\n if (typeof shape.draw === 'function') shape.draw();\n break;\n }\n case 'text': {\n const tx = shape.x || 0;\n const ty = shape.y || 0;\n const relTX = (tx - oldX) / oldW;\n const relTY = (ty - oldY) / oldH;\n shape.x = this.x + relTX * this.width;\n shape.y = this.y + relTY * this.height;\n break;\n }\n case 'freehandStroke': {\n // Pie sectors are editable closed freehand polygons.\n // Scale their source points with the frame so their\n // geometry stays attached instead of being clipped\n // at its previous canvas coordinates.\n if (Array.isArray(shape.points)) {\n shape.points = shape.points.map(point => {\n if (!Array.isArray(point) || point.length < 2) return point;\n const relPX = (point[0] - oldX) / oldW;\n const relPY = (point[1] - oldY) / oldH;\n return [\n this.x + relPX * this.width,\n this.y + relPY * this.height,\n point[2] || 0.5\n ];\n });\n shape._moveOffsetX = 0;\n shape._moveOffsetY = 0;\n if (typeof shape.draw === 'function') shape.draw();\n }\n break;\n }\n }\n\n if (typeof shape.updateAttachedArrows === 'function') {\n shape.updateAttachedArrows();\n }\n delete shape.isBeingMovedByFrame;\n });\n }\n }\n\n // Update contained shapes visibility\n this.updateContainedShapes();\n }\n \n temporarilyRemoveFromFrame(shape) {\n if (shape && shape.parentFrame === this) {\n // Move shape back to main SVG temporarily (without removing from containedShapes array)\n const el = shape.group || shape.element;\n if (el && el.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(el);\n svg.appendChild(el);\n }\n shape.isDraggedOutTemporarily = true;\n }\n}\n\n// Add a method to restore clipping for a shape after drag\nrestoreToFrame(shape) {\n if (shape && shape.parentFrame === this && shape.isDraggedOutTemporarily) {\n // Move shape back to clipped group\n const el = shape.group || shape.element;\n if (el && el.parentNode === svg) {\n svg.removeChild(el);\n this.clipGroup.appendChild(el);\n }\n delete shape.isDraggedOutTemporarily;\n }\n}\n\n\n contains(viewBoxX, viewBoxY) {\n // Simple point-in-rectangle test (without rotation for now)\n return viewBoxX >= this.x && viewBoxX <= this.x + this.width &&\n viewBoxY >= this.y && viewBoxY <= this.y + this.height;\n }\n\n // Arrow attachment support (similar to other shapes)\n getAttachmentPoint(point, tolerance = 20) {\n const rect = {\n left: this.x,\n right: this.x + this.width,\n top: this.y,\n bottom: this.y + this.height\n };\n\n const distances = {\n top: Math.abs(point.y - rect.top),\n bottom: Math.abs(point.y - rect.bottom),\n left: Math.abs(point.x - rect.left),\n right: Math.abs(point.x - rect.right)\n };\n\n let closestSide = null;\n let minDistance = tolerance;\n\n for (let side in distances) {\n if (distances[side] < minDistance &&\n ((side === 'top' || side === 'bottom') && point.x >= rect.left && point.x <= rect.right) ||\n ((side === 'left' || side === 'right') && point.y >= rect.top && point.y <= rect.bottom)) {\n minDistance = distances[side];\n closestSide = side;\n }\n }\n\n if (closestSide) {\n let attachPoint;\n const offset = { x: 0, y: 0 };\n\n switch (closestSide) {\n case 'top':\n attachPoint = { x: point.x, y: rect.top };\n offset.x = point.x - (rect.left + this.width / 2);\n break;\n case 'bottom':\n attachPoint = { x: point.x, y: rect.bottom };\n offset.x = point.x - (rect.left + this.width / 2);\n break;\n case 'left':\n attachPoint = { x: rect.left, y: point.y };\n offset.y = point.y - (rect.top + this.height / 2);\n break;\n case 'right':\n attachPoint = { x: rect.right, y: point.y };\n offset.y = point.y - (rect.top + this.height / 2);\n break;\n }\n\n return { point: attachPoint, side: closestSide, offset, shape: this };\n }\n\n return null;\n }\n\n updateStyle(newOptions) {\n Object.keys(newOptions).forEach(key => newOptions[key] === undefined && delete newOptions[key]);\n this.options = { ...this.options, ...newOptions };\n this.draw();\n }\n\n destroy() {\n const isDiagramFrame = !!this._diagramType;\n\n [...this.containedShapes].forEach(shape => {\n if (isDiagramFrame) {\n // Diagram/graph frame: destroy contained shapes with the frame\n if (typeof window.cleanupAttachments === 'function') {\n window.cleanupAttachments(shape);\n }\n const el = shape.group || shape.element;\n if (el && el.parentNode) {\n el.parentNode.removeChild(el);\n }\n if (shape.shapeName === 'frame') {\n if (shape.clipGroup && shape.clipGroup.parentNode) {\n shape.clipGroup.parentNode.removeChild(shape.clipGroup);\n }\n if (shape.clipPath && shape.clipPath.parentNode) {\n shape.clipPath.parentNode.removeChild(shape.clipPath);\n }\n }\n const idx = shapes.indexOf(shape);\n if (idx > -1) {\n shapes.splice(idx, 1);\n }\n } else {\n // Regular frame: release contained shapes back to canvas\n const el = shape.group || shape.element;\n if (el) {\n if (el.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(el);\n }\n svg.appendChild(el);\n }\n if (shape.shapeName === 'frame' && shape.clipGroup) {\n if (shape.clipGroup.parentNode === this.clipGroup) {\n this.clipGroup.removeChild(shape.clipGroup);\n }\n svg.appendChild(shape.clipGroup);\n }\n }\n shape.parentFrame = null;\n delete shape.isBeingMovedByFrame;\n });\n this.containedShapes = [];\n\n // Remove clip path\n if (this.clipPath && this.clipPath.parentNode) {\n this.clipPath.parentNode.removeChild(this.clipPath);\n }\n\n // Remove groups (clipGroup should be empty now)\n if (this.clipGroup && this.clipGroup.parentNode) {\n this.clipGroup.parentNode.removeChild(this.clipGroup);\n }\n\n if (this.group && this.group.parentNode) {\n this.group.parentNode.removeChild(this.group);\n }\n\n const index = shapes.indexOf(this);\n if (index > -1) {\n shapes.splice(index, 1);\n }\n if (currentShape === this) {\n currentShape = null;\n }\n }\n\n /**\n * Set a background image for this frame from a URL.\n * The image will fit/cover the frame dimensions.\n * @param {string} url - Image URL\n * @param {string} fit - 'cover' (default) | 'contain' | 'fill'\n */\n setImageFromURL(url, fit = 'cover') {\n if (!url) {\n // Remove existing frame image\n if (this._frameImage && this._frameImage.parentNode) {\n this._frameImage.parentNode.removeChild(this._frameImage);\n this._frameImage = null;\n }\n this._frameImageURL = null;\n return;\n }\n\n this._frameImageURL = url;\n this._frameImageFit = fit;\n\n if (!this._frameImage) {\n this._frameImage = document.createElementNS('http://www.w3.org/2000/svg', 'image');\n this._frameImage.setAttribute('pointer-events', 'none');\n }\n // Always update preserveAspectRatio when fit changes\n this._frameImage.setAttribute('preserveAspectRatio',\n fit === 'cover' ? 'xMidYMid slice' :\n fit === 'contain' ? 'xMidYMid meet' :\n fit === 'center' ? 'xMidYMid meet' : 'none'\n );\n\n this._frameImage.setAttribute('href', url);\n this._frameImage.setAttribute('x', this.x);\n this._frameImage.setAttribute('y', this.y);\n this._frameImage.setAttribute('width', this.width);\n this._frameImage.setAttribute('height', this.height);\n\n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n this._frameImage.setAttribute('transform', `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n }\n\n // Insert image right after the frame rect (below contained shapes)\n if (this._frameImage.parentNode === this.group) {\n this.group.removeChild(this._frameImage);\n }\n if (this.element && this.element.nextSibling) {\n this.group.insertBefore(this._frameImage, this.element.nextSibling);\n } else {\n this.group.appendChild(this._frameImage);\n }\n }\n\n /**\n * Update frame image position/size (called during move/resize)\n */\n _updateFrameImage() {\n if (!this._frameImage) return;\n this._frameImage.setAttribute('x', this.x);\n this._frameImage.setAttribute('y', this.y);\n this._frameImage.setAttribute('width', this.width);\n this._frameImage.setAttribute('height', this.height);\n\n if (this.rotation !== 0) {\n const centerX = this.x + this.width / 2;\n const centerY = this.y + this.height / 2;\n this._frameImage.setAttribute('transform', `rotate(${this.rotation}, ${centerX}, ${centerY})`);\n } else {\n this._frameImage.removeAttribute('transform');\n }\n }\n}\n\nexport { Frame };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
calculateSnap,
|
|
4
4
|
cleanupAttachments,
|
|
5
5
|
clearSnapGuides
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-YF3TK7SC.js";
|
|
7
7
|
import {
|
|
8
8
|
pushCreateAction,
|
|
9
9
|
pushDeleteAction,
|
|
10
10
|
pushFrameAttachmentAction,
|
|
11
11
|
pushOptionsChangeAction,
|
|
12
12
|
pushTransformAction
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-U3TB4KRS.js";
|
|
14
14
|
|
|
15
15
|
// src/tools/circleTool.js
|
|
16
16
|
function getThemeStroke() {
|
|
@@ -569,4 +569,4 @@ export {
|
|
|
569
569
|
handleMouseMove,
|
|
570
570
|
handleMouseUp
|
|
571
571
|
};
|
|
572
|
-
//# sourceMappingURL=chunk-
|
|
572
|
+
//# sourceMappingURL=chunk-OFGJJKPH.js.map
|