@elixpo/lixsketch 5.5.20 → 5.5.22
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-5OWPTCQ5.js} +43 -11
- package/dist/react/CopyPaste-5OWPTCQ5.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-T7UEHP4A.js +10 -0
- package/dist/react/Line-WWQFBNX5.js +10 -0
- package/dist/react/{SceneSerializer-VY3HY4PF.js → SceneSerializer-RDISX4X7.js} +36 -8
- package/dist/react/SceneSerializer-RDISX4X7.js.map +7 -0
- package/dist/react/{Selection-U2AR6NQS.js → Selection-ZL3G6IAO.js} +4 -4
- package/dist/react/{SketchEngine-ZFYUTKET.js → SketchEngine-MYKRKRJG.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-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-RFHMFWVR.js → chunk-EDSKEM6E.js} +70 -6
- package/dist/react/chunk-EDSKEM6E.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 +38 -4
- package/src/core/GraphEngine.js +129 -185
- package/src/core/SceneSerializer.js +30 -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 +79 -4
- 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/chunk-RFHMFWVR.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-T7UEHP4A.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-MYKRKRJG.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/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
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
pushCreateAction,
|
|
4
4
|
pushDeleteAction,
|
|
5
|
+
pushFrameAttachmentAction,
|
|
5
6
|
pushTransformAction
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-U3TB4KRS.js";
|
|
7
8
|
|
|
8
9
|
// src/tools/frameTool.js
|
|
9
10
|
var currentFrame = null;
|
|
@@ -118,8 +119,11 @@ var handleMouseUp = (e) => {
|
|
|
118
119
|
currentFrame = null;
|
|
119
120
|
currentShape = null;
|
|
120
121
|
} else {
|
|
121
|
-
pushCreateAction(currentFrame);
|
|
122
122
|
currentFrame.updateContainedShapes(true);
|
|
123
|
+
pushCreateAction(currentFrame, {
|
|
124
|
+
frameCreation: true,
|
|
125
|
+
containedShapes: [...currentFrame.containedShapes]
|
|
126
|
+
});
|
|
123
127
|
const placedFrame = currentFrame;
|
|
124
128
|
if (window.__sketchStoreApi) {
|
|
125
129
|
window.__sketchStoreApi.setActiveTool("select", { afterDraw: true });
|
|
@@ -148,13 +152,18 @@ var handleMouseUp = (e) => {
|
|
|
148
152
|
if (!isDragging) {
|
|
149
153
|
shapes.forEach((shape) => {
|
|
150
154
|
if (shape.shapeName !== "frame" && !shape.parentFrame) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
155
|
+
let targetFrame = null;
|
|
156
|
+
for (let i = shapes.length - 1; i >= 0; i--) {
|
|
157
|
+
const frame = shapes[i];
|
|
158
|
+
if (frame.shapeName === "frame" && frame.isShapeInFrame(shape)) {
|
|
159
|
+
targetFrame = frame;
|
|
160
|
+
break;
|
|
156
161
|
}
|
|
157
|
-
}
|
|
162
|
+
}
|
|
163
|
+
if (targetFrame) {
|
|
164
|
+
targetFrame.addShapeToFrame(shape);
|
|
165
|
+
pushFrameAttachmentAction(targetFrame, shape, "attach", null);
|
|
166
|
+
}
|
|
158
167
|
}
|
|
159
168
|
});
|
|
160
169
|
}
|
|
@@ -232,4 +241,4 @@ export {
|
|
|
232
241
|
handleMouseMove,
|
|
233
242
|
handleMouseUp
|
|
234
243
|
};
|
|
235
|
-
//# sourceMappingURL=chunk-
|
|
244
|
+
//# sourceMappingURL=chunk-SZD7DKYJ.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/tools/frameTool.js"],
|
|
4
|
+
"sourcesContent": ["/* eslint-disable */\n// Frame tool event handlers - extracted from frameHolder.js\nimport { pushCreateAction, pushDeleteAction, pushTransformAction, pushFrameAttachmentAction } from '../core/UndoRedo.js';\nimport { updateAttachedArrows, cleanupAttachments } from './arrowTool.js';\n\nlet currentFrame = null;\nlet isResizing = false;\nlet isDragging = false;\nlet activeAnchor = null;\nlet isDrawingFrame = false;\nlet frameStrokeColor = \"#888\";\nlet frameStrokeThickness = 2;\nlet frameFillColor = \"transparent\";\nlet frameOpacity = 1;\nlet startX, startY;\nlet dragOldPosFrame = null;\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\n\n// Event handlers for frame tool\nconst handleMouseDown = (e) => {\n if (!isFrameToolActive && !isSelectionToolActive) return;\n\n const { x, y } = getSVGCoordsFromMouse(e);\n\n if (isFrameToolActive) {\n isDrawingFrame = true;\n startX = x;\n startY = y;\n currentFrame = new Frame(x, y, 0, 0, {\n stroke: frameStrokeColor,\n strokeWidth: frameStrokeThickness,\n fill: frameFillColor,\n opacity: frameOpacity\n });\n shapes.push(currentFrame);\n currentShape = currentFrame;\n } else if (isSelectionToolActive) {\n // Handle frame selection \u2014 but first check if a contained shape was clicked\n for (let i = shapes.length - 1; i >= 0; i--) {\n if (shapes[i].shapeName === 'frame' && shapes[i].contains(x, y)) {\n const clickedFrame = shapes[i];\n\n // Check if click is on a shape inside this frame \u2014 let shape handlers deal with it\n let clickedContainedShape = false;\n if (clickedFrame.containedShapes && clickedFrame.containedShapes.length > 0) {\n for (let j = clickedFrame.containedShapes.length - 1; j >= 0; j--) {\n const inner = clickedFrame.containedShapes[j];\n if (inner.contains && inner.contains(x, y)) {\n clickedContainedShape = true;\n break;\n }\n }\n }\n // If a contained shape was clicked, don't select the frame \u2014\n // and crucially, clear `currentShape` so the EventDispatcher's\n // `if (handled && prevShape && !currentShape) handled=false` gate\n // triggers and the dispatcher falls through to shape-specific\n // handlers. Without this clear, the dispatcher returns with\n // `handled=true` and the child shape is never selected (Issue\n // #22, bug #2).\n if (clickedContainedShape) {\n if (currentShape && currentShape.shapeName === 'frame'\n && typeof currentShape.removeSelection === 'function') {\n currentShape.removeSelection();\n }\n currentShape = null;\n return;\n }\n\n if (currentShape && currentShape !== clickedFrame) {\n currentShape.removeSelection();\n }\n currentShape = clickedFrame;\n currentShape.selectFrame();\n\n // Check for anchor interaction\n const anchorIndex = typeof currentShape.isNearAnchor === 'function' ? currentShape.isNearAnchor(x, y) : null;\n if (anchorIndex !== null) {\n activeAnchor = anchorIndex;\n isResizing = true;\n } else {\n isDragging = true;\n startX = x;\n startY = y;\n dragOldPosFrame = {\n x: currentShape.x,\n y: currentShape.y,\n width: currentShape.width,\n height: currentShape.height,\n rotation: currentShape.rotation\n };\n }\n return;\n }\n }\n\n // If no frame was clicked, deselect current\n if (currentShape && currentShape.shapeName === 'frame') {\n currentShape.removeSelection();\n currentShape = null;\n }\n }\n};\n\n const handleMouseMove = (e) => {\n const { x, y } = getSVGCoordsFromMouse(e);\n\n if (isDrawingFrame && currentFrame) {\n const width = Math.abs(x - startX);\n const height = Math.abs(y - startY);\n currentFrame.x = Math.min(startX, x);\n currentFrame.y = Math.min(startY, y);\n currentFrame.width = width;\n currentFrame.height = height;\n currentFrame.draw();\n } else if (isDragging && currentShape && currentShape.shapeName === 'frame') {\n const dx = x - startX;\n const dy = y - startY;\n \n // Use the frame's move method which properly handles contained shapes\n currentShape.move(dx, dy);\n \n startX = x;\n startY = y;\n }\n};\n\n const handleMouseUp = (e) => {\n if (isDrawingFrame && currentFrame) {\n // Check if frame is too small\n if (currentFrame.width < 10 || currentFrame.height < 10) {\n currentFrame.destroy();\n currentFrame = null;\n currentShape = null;\n } else {\n // Check for shapes that should be contained in the new frame\n currentFrame.updateContainedShapes(true); // Apply clipping immediately for new frames\n pushCreateAction(currentFrame, {\n frameCreation: true,\n containedShapes: [...currentFrame.containedShapes]\n });\n\n // Auto-select the new frame and switch to selection tool\n const placedFrame = currentFrame;\n if (window.__sketchStoreApi) {\n window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });\n } else {\n window.isSelectionToolActive = true;\n }\n currentShape = placedFrame;\n placedFrame.selectFrame();\n }\n isDrawingFrame = false;\n }\n\n if (isDragging && dragOldPosFrame && currentShape) {\n const newPos = {\n x: currentShape.x,\n y: currentShape.y,\n width: currentShape.width,\n height: currentShape.height,\n rotation: currentShape.rotation\n };\n pushTransformAction(currentShape, dragOldPosFrame, newPos);\n dragOldPosFrame = null;\n \n // Update frame containment after moving frame (but don't re-move contained shapes)\n if (currentShape.shapeName === 'frame') {\n currentShape.updateClipPath();\n }\n }\n\n // Only check frame containment for shapes that aren't already in frames.\n // Record this fallback attachment too; individual shape tools normally do\n // it themselves, but restored/imported shapes can reach this path.\n if (!isDragging) {\n shapes.forEach(shape => {\n if (shape.shapeName !== 'frame' && !shape.parentFrame) {\n let targetFrame = null;\n for (let i = shapes.length - 1; i >= 0; i--) {\n const frame = shapes[i];\n if (frame.shapeName === 'frame' && frame.isShapeInFrame(shape)) {\n targetFrame = frame;\n break;\n }\n }\n if (targetFrame) {\n targetFrame.addShapeToFrame(shape);\n pushFrameAttachmentAction(targetFrame, shape, 'attach', null);\n }\n }\n });\n }\n\n isDrawingFrame = false;\n isDragging = false;\n isResizing = false;\n activeAnchor = null;\n svg.style.cursor = 'default';\n};\n\nFrame.prototype.isNearAnchor = function(x, y) {\n const anchorSize = 10 / currentZoom;\n \n // Define anchor positions\n const anchorPositions = [\n { x: this.x, y: this.y },\n { x: this.x + this.width / 2, y: this.y },\n { x: this.x + this.width, y: this.y },\n { x: this.x + this.width, y: this.y + this.height / 2 },\n { x: this.x + this.width, y: this.y + this.height },\n { x: this.x + this.width / 2, y: this.y + this.height },\n { x: this.x, y: this.y + this.height },\n { x: this.x, y: this.y + this.height / 2 },\n { x: this.x + this.width / 2, y: this.y - 30 / currentZoom } // Rotation handle\n ];\n\n for (let i = 0; i < anchorPositions.length; i++) {\n const pos = anchorPositions[i];\n const distance = Math.sqrt((x - pos.x) ** 2 + (y - pos.y) ** 2);\n if (distance <= anchorSize) {\n return i;\n }\n }\n return null;\n};\n\n// Delete functionality\nfunction deleteCurrentFrame() {\n if (currentShape && currentShape.shapeName === 'frame') {\n const frame = currentShape;\n const isDiagramFrame = !!frame._diagramType;\n\n // Issue #24 bug #7: regular frame \u2192 orphan children + snapshot\n // (mirrors deleteSelectedShapes / EngineShortcuts).\n let childSnapshot = null;\n if (!isDiagramFrame) {\n childSnapshot = [...(frame.containedShapes || [])];\n for (const child of childSnapshot) {\n if (!child || child === frame) continue;\n const el = child.group || child.element;\n if (el) {\n if (frame.clipGroup && el.parentNode === frame.clipGroup) frame.clipGroup.removeChild(el);\n if (window.svg && el.parentNode !== window.svg) window.svg.appendChild(el);\n }\n child.parentFrame = null;\n delete child.isBeingMovedByFrame;\n }\n frame.containedShapes = [];\n }\n\n const idx = shapes.indexOf(frame);\n if (idx !== -1) shapes.splice(idx, 1);\n\n if (!isDiagramFrame) {\n if (frame.group && frame.group.parentNode) frame.group.parentNode.removeChild(frame.group);\n if (frame.clipGroup && frame.clipGroup.parentNode) frame.clipGroup.parentNode.removeChild(frame.clipGroup);\n if (frame.clipPath && frame.clipPath.parentNode) frame.clipPath.parentNode.removeChild(frame.clipPath);\n } else if (frame.group && frame.group.parentNode) {\n frame.group.parentNode.removeChild(frame.group);\n }\n\n if (childSnapshot) pushDeleteAction(frame, { childSnapshot });\n else pushDeleteAction(frame);\n currentShape = null;\n }\n}\n\ndocument.addEventListener('keydown', (e) => {\n if (e.key === 'Delete' && currentShape && currentShape.shapeName === 'frame') {\n deleteCurrentFrame();\n }\n});\n\nwindow.Frame = Frame;\n\nexport {\n handleMouseDown as handleMouseDownFrame,\n handleMouseMove as handleMouseMoveFrame,\n handleMouseUp as handleMouseUpFrame\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -22,11 +22,17 @@ function getCurrentSelectedElement() {
|
|
|
22
22
|
function updateSelectedElement(element) {
|
|
23
23
|
selectedElement = element;
|
|
24
24
|
}
|
|
25
|
-
function pushCreateAction(shape) {
|
|
26
|
-
|
|
25
|
+
function pushCreateAction(shape, meta = null) {
|
|
26
|
+
const action = {
|
|
27
27
|
type: "create",
|
|
28
28
|
shape
|
|
29
|
-
}
|
|
29
|
+
};
|
|
30
|
+
if (meta?.frameCreation && shape?.shapeName === "frame") {
|
|
31
|
+
action.frameCreation = true;
|
|
32
|
+
action.containedShapes = [...meta.containedShapes || shape.containedShapes || []];
|
|
33
|
+
action.shapeIndex = Array.isArray(shapes) ? shapes.indexOf(shape) : -1;
|
|
34
|
+
}
|
|
35
|
+
undoStack.push(action);
|
|
30
36
|
redoStack.length = 0;
|
|
31
37
|
notifyCollaboration();
|
|
32
38
|
}
|
|
@@ -464,7 +470,20 @@ function undo() {
|
|
|
464
470
|
return;
|
|
465
471
|
}
|
|
466
472
|
if (action.type === "create") {
|
|
467
|
-
if (action.shape.
|
|
473
|
+
if (action.frameCreation && action.shape.shapeName === "frame") {
|
|
474
|
+
for (const child of action.containedShapes || []) {
|
|
475
|
+
if (child?.parentFrame === action.shape) action.shape.removeShapeFromFrame(child);
|
|
476
|
+
}
|
|
477
|
+
if (currentShape === action.shape) {
|
|
478
|
+
action.shape.removeSelection?.();
|
|
479
|
+
currentShape = null;
|
|
480
|
+
}
|
|
481
|
+
const idx = shapes.indexOf(action.shape);
|
|
482
|
+
if (idx !== -1) shapes.splice(idx, 1);
|
|
483
|
+
action.shape.group?.remove();
|
|
484
|
+
action.shape.clipGroup?.remove();
|
|
485
|
+
action.shape.clipPath?.remove();
|
|
486
|
+
} else if (action.shape.type === "text") {
|
|
468
487
|
if (action.shape.element && action.shape.element.parentNode) {
|
|
469
488
|
action.shape.element.parentNode.removeChild(action.shape.element);
|
|
470
489
|
} else if (action.shape.parentNode) {
|
|
@@ -828,7 +847,27 @@ function redo() {
|
|
|
828
847
|
return;
|
|
829
848
|
}
|
|
830
849
|
if (action.type === "create") {
|
|
831
|
-
if (action.shape.
|
|
850
|
+
if (action.frameCreation && action.shape.shapeName === "frame") {
|
|
851
|
+
const frame = action.shape;
|
|
852
|
+
let defs = svg?.querySelector("defs");
|
|
853
|
+
if (!defs && svg) {
|
|
854
|
+
defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
|
|
855
|
+
svg.appendChild(defs);
|
|
856
|
+
}
|
|
857
|
+
if (defs && frame.clipPath && !frame.clipPath.parentNode) defs.appendChild(frame.clipPath);
|
|
858
|
+
if (svg && frame.group && !frame.group.parentNode) svg.appendChild(frame.group);
|
|
859
|
+
if (svg && frame.clipGroup && !frame.clipGroup.parentNode) svg.appendChild(frame.clipGroup);
|
|
860
|
+
if (shapes.indexOf(frame) === -1) {
|
|
861
|
+
const index = action.shapeIndex >= 0 ? Math.min(action.shapeIndex, shapes.length) : shapes.length;
|
|
862
|
+
shapes.splice(index, 0, frame);
|
|
863
|
+
}
|
|
864
|
+
frame.containedShapes = [];
|
|
865
|
+
frame.draw();
|
|
866
|
+
frame.updateClipPath();
|
|
867
|
+
for (const child of action.containedShapes || []) {
|
|
868
|
+
if (child && shapes.includes(child)) frame.addShapeToFrame(child);
|
|
869
|
+
}
|
|
870
|
+
} else if (action.shape.type === "text") {
|
|
832
871
|
if (svg) {
|
|
833
872
|
svg.appendChild(action.shape.element || action.shape);
|
|
834
873
|
shapes.push(action.shape.element || action.shape);
|
|
@@ -1145,4 +1184,4 @@ export {
|
|
|
1145
1184
|
undo,
|
|
1146
1185
|
redo
|
|
1147
1186
|
};
|
|
1148
|
-
//# sourceMappingURL=chunk-
|
|
1187
|
+
//# sourceMappingURL=chunk-U3TB4KRS.js.map
|