@elixpo/lixsketch 5.6.9 → 5.6.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/react/{CopyPaste-PPDS3AD6.js → CopyPaste-N4U2NTQT.js} +5 -5
  2. package/dist/react/{EventDispatcher-UV7LFSAS.js → EventDispatcher-J657SDW4.js} +12 -12
  3. package/dist/react/{EventDispatcher-UV7LFSAS.js.map → EventDispatcher-J657SDW4.js.map} +1 -1
  4. package/dist/react/{Frame-DELCMYV6.js → Frame-NHPESH4Y.js} +2 -2
  5. package/dist/react/IconShape-RN5HJDUF.js +10 -0
  6. package/dist/react/ImageShape-L7U64AVP.js +10 -0
  7. package/dist/react/Line-LPRTGPUQ.js +10 -0
  8. package/dist/react/{SceneSerializer-H6KMQCO2.js → SceneSerializer-Y6QABGZY.js} +5 -5
  9. package/dist/react/{Selection-CFWRGVKH.js → Selection-GCZWCNAR.js} +3 -3
  10. package/dist/react/{SketchEngine-UFLZJQXS.js → SketchEngine-PCMCE63L.js} +19 -19
  11. package/dist/react/{arrowTool-DO327FKU.js → arrowTool-UN3TNJFP.js} +2 -2
  12. package/dist/react/{chunk-O7KXLFZN.js → chunk-3FCIBY54.js} +2 -2
  13. package/dist/react/{chunk-6LWUR7XB.js → chunk-3PFVMNDJ.js} +3 -3
  14. package/dist/react/{chunk-6LWUR7XB.js.map → chunk-3PFVMNDJ.js.map} +1 -1
  15. package/dist/react/{chunk-2ALS5JGS.js → chunk-5XGQ3CMT.js} +2 -2
  16. package/dist/react/{chunk-KZBKYHZO.js → chunk-7NHZYKYB.js} +3 -3
  17. package/dist/react/{chunk-KZBKYHZO.js.map → chunk-7NHZYKYB.js.map} +1 -1
  18. package/dist/react/{chunk-I7TVGJFF.js → chunk-7WXEWDRL.js} +3 -3
  19. package/dist/react/{chunk-I7TVGJFF.js.map → chunk-7WXEWDRL.js.map} +1 -1
  20. package/dist/react/{chunk-CGMUXYPJ.js → chunk-JVHZVV5U.js} +3 -3
  21. package/dist/react/{chunk-CGMUXYPJ.js.map → chunk-JVHZVV5U.js.map} +1 -1
  22. package/dist/react/{chunk-37PF7FG2.js → chunk-KACRJ6AJ.js} +2 -2
  23. package/dist/react/{chunk-X5ENBMGL.js → chunk-KXLNEFN5.js} +2 -2
  24. package/dist/react/{chunk-X5ENBMGL.js.map → chunk-KXLNEFN5.js.map} +1 -1
  25. package/dist/react/{chunk-DODPOWNX.js → chunk-P5476S5I.js} +3 -3
  26. package/dist/react/{chunk-DODPOWNX.js.map → chunk-P5476S5I.js.map} +1 -1
  27. package/dist/react/{chunk-BOZEDUAF.js → chunk-TAJ5E6KI.js} +3 -3
  28. package/dist/react/chunk-TAJ5E6KI.js.map +7 -0
  29. package/dist/react/{chunk-KC26KJW4.js → chunk-UERV53R7.js} +2 -2
  30. package/dist/react/{chunk-7DD2JRBC.js → chunk-ULZW5PXM.js} +2 -2
  31. package/dist/react/{chunk-RK3NVAER.js → chunk-YHQ4ZAJQ.js} +4 -4
  32. package/dist/react/{chunk-RK3NVAER.js.map → chunk-YHQ4ZAJQ.js.map} +1 -1
  33. package/dist/react/{circleTool-NK4RVDAR.js → circleTool-YDTQDGYX.js} +3 -3
  34. package/dist/react/{codeTool-3WF4HEOW.js → codeTool-U6SYKHHD.js} +3 -3
  35. package/dist/react/{frameTool-VCNV2NG2.js → frameTool-VRI7OODN.js} +2 -2
  36. package/dist/react/{freehandTool-TBAOD46K.js → freehandTool-2ICCQHVY.js} +3 -3
  37. package/dist/react/{iconTool-65JCAKYF.js → iconTool-32D5NJ4I.js} +3 -3
  38. package/dist/react/{imageTool-UQZUBOK2.js → imageTool-Z6Y4OXBG.js} +3 -3
  39. package/dist/react/index.js +21 -9
  40. package/dist/react/index.js.map +2 -2
  41. package/dist/react/{lineTool-762KBYOM.js → lineTool-BUWVQ666.js} +3 -3
  42. package/dist/react/{rectangleTool-IQK3HZK6.js → rectangleTool-NJYG6Y6L.js} +3 -3
  43. package/dist/react/styles.css +4 -0
  44. package/dist/react/{textTool-ITG2SBJK.js → textTool-CIJCF4Z3.js} +4 -4
  45. package/package.json +1 -1
  46. package/src/react/components/sidebars/TextSidebar.jsx +10 -4
  47. package/src/react/store/useUIStore.js +1 -1
  48. package/src/react/styles.css +13 -0
  49. package/src/react/utils/canvasBackgrounds.js +11 -2
  50. package/src/shapes/Line.js +2 -2
  51. package/src/tools/arrowTool.js +1 -1
  52. package/src/tools/circleTool.js +1 -1
  53. package/src/tools/codeTool.js +1 -1
  54. package/src/tools/freehandTool.js +1 -1
  55. package/src/tools/lineTool.js +1 -1
  56. package/src/tools/rectangleTool.js +1 -1
  57. package/src/tools/shapeRecognitionTool.js +1 -1
  58. package/src/tools/textTool.js +1 -1
  59. package/dist/react/IconShape-PZHMZSLR.js +0 -10
  60. package/dist/react/ImageShape-ZMBZARRI.js +0 -10
  61. package/dist/react/Line-VPVPL6ET.js +0 -10
  62. package/dist/react/chunk-BOZEDUAF.js.map +0 -7
  63. /package/dist/react/{CopyPaste-PPDS3AD6.js.map → CopyPaste-N4U2NTQT.js.map} +0 -0
  64. /package/dist/react/{Frame-DELCMYV6.js.map → Frame-NHPESH4Y.js.map} +0 -0
  65. /package/dist/react/{IconShape-PZHMZSLR.js.map → IconShape-RN5HJDUF.js.map} +0 -0
  66. /package/dist/react/{ImageShape-ZMBZARRI.js.map → ImageShape-L7U64AVP.js.map} +0 -0
  67. /package/dist/react/{Line-VPVPL6ET.js.map → Line-LPRTGPUQ.js.map} +0 -0
  68. /package/dist/react/{SceneSerializer-H6KMQCO2.js.map → SceneSerializer-Y6QABGZY.js.map} +0 -0
  69. /package/dist/react/{Selection-CFWRGVKH.js.map → Selection-GCZWCNAR.js.map} +0 -0
  70. /package/dist/react/{SketchEngine-UFLZJQXS.js.map → SketchEngine-PCMCE63L.js.map} +0 -0
  71. /package/dist/react/{arrowTool-DO327FKU.js.map → arrowTool-UN3TNJFP.js.map} +0 -0
  72. /package/dist/react/{chunk-O7KXLFZN.js.map → chunk-3FCIBY54.js.map} +0 -0
  73. /package/dist/react/{chunk-2ALS5JGS.js.map → chunk-5XGQ3CMT.js.map} +0 -0
  74. /package/dist/react/{chunk-37PF7FG2.js.map → chunk-KACRJ6AJ.js.map} +0 -0
  75. /package/dist/react/{chunk-KC26KJW4.js.map → chunk-UERV53R7.js.map} +0 -0
  76. /package/dist/react/{chunk-7DD2JRBC.js.map → chunk-ULZW5PXM.js.map} +0 -0
  77. /package/dist/react/{circleTool-NK4RVDAR.js.map → circleTool-YDTQDGYX.js.map} +0 -0
  78. /package/dist/react/{codeTool-3WF4HEOW.js.map → codeTool-U6SYKHHD.js.map} +0 -0
  79. /package/dist/react/{frameTool-VCNV2NG2.js.map → frameTool-VRI7OODN.js.map} +0 -0
  80. /package/dist/react/{freehandTool-TBAOD46K.js.map → freehandTool-2ICCQHVY.js.map} +0 -0
  81. /package/dist/react/{iconTool-65JCAKYF.js.map → iconTool-32D5NJ4I.js.map} +0 -0
  82. /package/dist/react/{imageTool-UQZUBOK2.js.map → imageTool-Z6Y4OXBG.js.map} +0 -0
  83. /package/dist/react/{lineTool-762KBYOM.js.map → lineTool-BUWVQ666.js.map} +0 -0
  84. /package/dist/react/{rectangleTool-IQK3HZK6.js.map → rectangleTool-NJYG6Y6L.js.map} +0 -0
  85. /package/dist/react/{textTool-ITG2SBJK.js.map → textTool-CIJCF4Z3.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/tools/rectangleTool.js"],
4
- "sourcesContent": ["/* eslint-disable */\n// Rectangle tool event handlers - extracted from drawSquare.js\n// Depends on globals: svg, shapes, currentShape, rough, currentZoom, lastMousePos\n// Depends on globals: isSquareToolActive, isSelectionToolActive\n// Depends on globals: squareSideBar, disableAllSideBars\nimport { pushCreateAction, pushDeleteAction, pushOptionsChangeAction, pushTransformAction, pushFrameAttachmentAction } from '../core/UndoRedo.js';\nimport { cleanupAttachments } from './arrowTool.js';\nimport { calculateSnap, clearSnapGuides } from '../core/SnapGuides.js';\n\nlet isDrawingSquare = false;\nlet isDraggingShapeSquare = false;\nlet isResizingShapeSquare = false;\nlet isRotatingShapeSquare = false;\nlet resizingAnchorIndexSquare = null;\nlet startRotationMouseAngleSquare = 0;\nlet startShapeRotationSquare = 0;\nconst rc = rough.svg(svg); \nlet startX, startY;\n// Issue #38 follow-up: null sentinel means \"use theme default at draw\n// time\". The legacy `\"#fff\"` literal was invisible on the light canvas;\n// reading the body's `theme-dark` class lets the same code produce a\n// readable stroke in either mode. As soon as the user picks a colour\n// from the sidebar this var holds that value verbatim.\nfunction getThemeStroke() {\n if (typeof document === 'undefined') return '#fff';\n return document.body && document.body.classList.contains('theme-dark') ? '#fff' : '#1a1a2e';\n}\nlet squareStrokecolor = null;\nlet squareBackgroundColor = \"transparent\";\nlet squareFillStyleValue = \"none\";\nlet squareStrokeThicknes = 2;\nlet squareOutlineStyle = \"solid\";\nlet dragOldPosSquare = null;\nlet draggedShapeInitialFrame = null;\nlet hoveredFrame = null;\n\nlet SquarecolorOptions = document.querySelectorAll(\".squareStrokeSpan\");\nlet backgroundColorOptionsSquare = document.querySelectorAll(\".squareBackgroundSpan\");\nlet fillStyleOptions = document.querySelectorAll(\".squareFillStyleSpan\");\nlet squareStrokeThicknessValue = document.querySelectorAll(\".squareStrokeThickSpan\");\nlet squareOutlineStyleValue = document.querySelectorAll(\".squareOutlineStyle\");\n\n\n\nfunction getSVGCoordsFromMouse(e) {\n // Use the SVG's current viewBox to map mouse to SVG coordinates\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\nfunction deleteCurrentShape() {\n if (currentShape && currentShape.shapeName === 'rectangle') {\n const idx = shapes.indexOf(currentShape);\n if (idx !== -1) shapes.splice(idx, 1);\n \n // Clean up any arrow attachments before deleting\n cleanupAttachments(currentShape);\n \n if (currentShape.group.parentNode) {\n currentShape.group.parentNode.removeChild(currentShape.group);\n }\n pushDeleteAction(currentShape);\n currentShape = null;\n disableAllSideBars();\n }\n}\n\n// --- Main event handlers ---\nconst handleMouseDownRect = (e) => {\n const { x: mouseX, y: mouseY } = getSVGCoordsFromMouse(e);\n if (isSquareToolActive) {\n startX = mouseX;\n startY = mouseY;\n isDrawingSquare = true;\n\n if (currentShape) {\n currentShape.removeSelection();\n currentShape = null;\n disableAllSideBars();\n }\n\n let initialOptions = {\n stroke: squareStrokecolor ?? getThemeStroke(),\n fill: squareBackgroundColor,\n fillStyle: squareFillStyleValue,\n strokeWidth: squareStrokeThicknes,\n };\n if (squareOutlineStyle === \"dashed\") {\n initialOptions.strokeDasharray = \"10,10\";\n } else if (squareOutlineStyle === \"dotted\") {\n initialOptions.strokeDasharray = \"2,8\";\n } else {\n initialOptions.strokeDasharray = \"\";\n }\n\n currentShape = new Rectangle(startX, startY, 0, 0, initialOptions);\n currentShape.setDrawingState(true);\n\n } else if (isSelectionToolActive) {\n let clickedOnShape = false;\n if (currentShape && currentShape.shapeName === 'rectangle' && currentShape.isSelected) {\n const anchorInfo = currentShape.isNearAnchor(mouseX, mouseY);\n if (anchorInfo) {\n dragOldPosSquare = { x: currentShape.x, y: currentShape.y, width: currentShape.width, height: currentShape.height, rotation: currentShape.rotation };\n if (anchorInfo.type === 'resize') {\n isResizingShapeSquare = true;\n resizingAnchorIndexSquare = anchorInfo.index;\n } else if (anchorInfo.type === 'rotate') {\n isRotatingShapeSquare = true;\n\n const centerX = currentShape.x + currentShape.width / 2;\n const centerY = currentShape.y + currentShape.height / 2;\n startRotationMouseAngleSquare = Math.atan2(mouseY - centerY, mouseX - centerX) * 180 / Math.PI;\n startShapeRotationSquare = currentShape.rotation;\n }\n clickedOnShape = true;\n } else if (currentShape.contains(mouseX, mouseY)) {\n isDraggingShapeSquare = true;\n dragOldPosSquare = { x: currentShape.x, y: currentShape.y, width: currentShape.width, height: currentShape.height, rotation: currentShape.rotation };\n \n // Store initial frame state\n draggedShapeInitialFrame = currentShape.parentFrame || null;\n \n // Temporarily remove from frame clipping if dragging\n if (currentShape.parentFrame) {\n currentShape.parentFrame.temporarilyRemoveFromFrame(currentShape);\n }\n \n startX = mouseX; \n startY = mouseY;\n clickedOnShape = true;\n }\n }\n\n if (!clickedOnShape) {\n let shapeToSelect = null;\n for (let i = shapes.length - 1; i >= 0; i--) {\n const shape = shapes[i];\n if (shape.shapeName === 'rectangle' && shape.contains(mouseX, mouseY)) {\n shapeToSelect = shape;\n break; \n }\n }\n if (currentShape && currentShape !== shapeToSelect) {\n currentShape.removeSelection();\n currentShape = null;\n disableAllSideBars();\n }\n if (shapeToSelect) {\n currentShape = shapeToSelect;\n currentShape.isSelected = true;\n currentShape.draw(); \n isDraggingShapeSquare = true; \n dragOldPosSquare = { x: currentShape.x, y: currentShape.y, width: currentShape.width, height: currentShape.height, rotation: currentShape.rotation };\n \n // Store initial frame state\n draggedShapeInitialFrame = currentShape.parentFrame || null;\n \n // Temporarily remove from frame clipping if dragging\n if (currentShape.parentFrame) {\n currentShape.parentFrame.temporarilyRemoveFromFrame(currentShape);\n }\n \n startX = mouseX; \n startY = mouseY;\n clickedOnShape = true; \n }\n }\n if (!clickedOnShape && currentShape) {\n currentShape.removeSelection();\n currentShape = null;\n disableAllSideBars();\n }\n }\n};\n\n\nconst handleMouseMoveRect = (e) => {\n const { x: mouseX, y: mouseY } = getSVGCoordsFromMouse(e);\n const svgRect = svg.getBoundingClientRect();\n lastMousePos = {\n x: e.clientX - svgRect.left, \n y: e.clientY - svgRect.top\n };\n\n if (isDrawingSquare && isSquareToolActive && currentShape) {\n let width = mouseX - startX;\n let height = mouseY - startY;\n currentShape.x = width < 0 ? startX + width : startX;\n currentShape.y = height < 0 ? startY + height : startY;\n currentShape.width = Math.abs(width);\n currentShape.height = Math.abs(height);\n \n // Force update the element size while drawing (but use cached rough element)\n if (currentShape.element && currentShape.width > 0 && currentShape.height > 0) {\n // Remove old element\n if (currentShape.element.parentNode === currentShape.group) {\n currentShape.group.removeChild(currentShape.element);\n }\n \n // Create new rough element with current size\n const roughRect = rc.rectangle(0, 0, currentShape.width, currentShape.height, currentShape.options);\n currentShape.element = roughRect;\n currentShape.group.appendChild(roughRect);\n }\n \n // Update transform\n const rotateCenterX = currentShape.width / 2;\n const rotateCenterY = currentShape.height / 2;\n currentShape.group.setAttribute('transform', `translate(${currentShape.x}, ${currentShape.y}) rotate(${currentShape.rotation}, ${rotateCenterX}, ${rotateCenterY})`);\n \n // Check for frame containment while drawing\n shapes.forEach(frame => {\n if (frame.shapeName === 'frame') {\n if (frame.isShapeInFrame(currentShape)) {\n frame.highlightFrame();\n hoveredFrame = frame;\n } else if (hoveredFrame === frame) {\n frame.removeHighlight();\n hoveredFrame = null;\n }\n }\n });\n \n } else if (isDraggingShapeSquare && currentShape && currentShape.isSelected) {\n let dx = mouseX - startX;\n let dy = mouseY - startY;\n currentShape.move(dx, dy);\n startX = mouseX;\n startY = mouseY;\n // Snap guides\n if (window.__sketchStoreApi && window.__sketchStoreApi.getState().snapToObjects) {\n const snap = calculateSnap(currentShape, e.shiftKey, e.clientX, e.clientY);\n if (snap.dx || snap.dy) {\n currentShape.move(snap.dx, snap.dy);\n }\n } else {\n clearSnapGuides();\n }\n\n // Issue #24 bug #4: track the actual containing frame at every\n // move so the mouseUp logic re-parents correctly. Without this\n // hoveredFrame stays at null for existing-shape drags and the\n // shape is detached the moment the user nudges it by 1 px inside\n // its own parent frame.\n let newHover = null;\n for (const f of shapes) {\n if (f.shapeName !== 'frame') continue;\n if (f === currentShape) continue;\n if (typeof f.isShapeInFrame === 'function' && f.isShapeInFrame(currentShape)) {\n newHover = f;\n break;\n }\n }\n if (hoveredFrame && hoveredFrame !== newHover && typeof hoveredFrame.removeHighlight === 'function') {\n hoveredFrame.removeHighlight();\n }\n if (newHover && newHover !== hoveredFrame && typeof newHover.highlightFrame === 'function') {\n newHover.highlightFrame();\n }\n hoveredFrame = newHover;\n } else if (isResizingShapeSquare && currentShape && currentShape.isSelected && resizingAnchorIndexSquare !== null) {\n currentShape.updatePosition(resizingAnchorIndexSquare, mouseX, mouseY);\n currentShape._skipAnchors = true;\n currentShape.draw();\n currentShape._skipAnchors = false;\n } else if (isRotatingShapeSquare && currentShape && currentShape.isSelected) {\n const centerX = currentShape.x + currentShape.width / 2;\n const centerY = currentShape.y + currentShape.height / 2;\n const currentRotationMouseAngle = Math.atan2(mouseY - centerY, mouseX - centerX) * 180 / Math.PI;\n const angleDiff = currentRotationMouseAngle - startRotationMouseAngleSquare;\n let newRotation = startShapeRotationSquare + angleDiff;\n const snapAngle = 15;\n if (e.shiftKey) {\n newRotation = Math.round(newRotation / snapAngle) * snapAngle;\n }\n currentShape.rotate(newRotation);\n currentShape._skipAnchors = true;\n currentShape.draw();\n currentShape._skipAnchors = false;\n svg.style.cursor = 'grabbing'; \n } else if (isSelectionToolActive && !isDrawingSquare && currentShape && currentShape.isSelected) {\n const anchorInfo = currentShape.isNearAnchor(mouseX, mouseY);\n if (anchorInfo) {\n if (anchorInfo.type === 'resize') {\n const baseDirection = anchorInfo.index; \n const rotatedCursor = currentShape.getRotatedCursor(baseDirection, currentShape.rotation);\n svg.style.cursor = rotatedCursor + '-resize';\n } else if (anchorInfo.type === 'rotate') {\n svg.style.cursor = 'grab';\n }\n } else if (currentShape.contains(mouseX, mouseY)) {\n svg.style.cursor = 'move';\n } else {\n svg.style.cursor = 'default';\n }\n } else if (isSelectionToolActive && !isDrawingSquare && !isDraggingShapeSquare && !isResizingShapeSquare && !isRotatingShapeSquare) {\n let hoveredShape = null;\n for (let i = shapes.length - 1; i >= 0; i--) {\n const shape = shapes[i];\n if (shape.shapeName === 'rectangle' && shape.contains(mouseX, mouseY)) {\n hoveredShape = shape;\n break;\n }\n }\n if (hoveredShape) {\n svg.style.cursor = 'pointer';\n } else {\n svg.style.cursor = 'default'; \n }\n }\n};\n\n \nconst handleMouseUpRect = (e) => {\n if (isDrawingSquare && currentShape) {\n currentShape.setDrawingState(false);\n if (currentShape.width === 0 || currentShape.height === 0) {\n if (currentShape.group.parentNode) {\n currentShape.group.parentNode.removeChild(currentShape.group);\n }\n currentShape = null;\n } else {\n currentShape.draw();\n shapes.push(currentShape);\n pushCreateAction(currentShape);\n\n // Check for frame containment and track attachment\n const finalFrame = hoveredFrame;\n if (finalFrame) {\n finalFrame.addShapeToFrame(currentShape);\n // Track the attachment for undo\n pushFrameAttachmentAction(finalFrame, currentShape, 'attach', null);\n }\n\n // Auto-select the drawn shape and switch to selection tool\n const drawnShape = currentShape;\n if (window.__sketchStoreApi) window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });\n currentShape = drawnShape;\n currentShape.isSelected = true;\n if (typeof currentShape.addAnchors === 'function') {\n currentShape.addAnchors();\n }\n }\n \n // Clear frame highlighting\n if (hoveredFrame) {\n hoveredFrame.removeHighlight();\n hoveredFrame = null;\n }\n }\n\n if ((isDraggingShapeSquare || isResizingShapeSquare || isRotatingShapeSquare) && dragOldPosSquare && currentShape) {\n // Issue #34 bug #2: for drag operations the actual frame transfer\n // happens AFTER this mouseUp block \u2014 so `currentShape.parentFrame`\n // at this point still points at the OLD frame. Use the hovered\n // frame (tracked during mousemove) as the authoritative new\n // destination instead, so the undo action records a real\n // attachment delta and Ctrl+Z re-attaches the shape correctly.\n const newPos = {\n x: currentShape.x,\n y: currentShape.y,\n width: currentShape.width,\n height: currentShape.height,\n rotation: currentShape.rotation,\n parentFrame: isDraggingShapeSquare ? (hoveredFrame || null) : currentShape.parentFrame,\n };\n const oldPos = {\n ...dragOldPosSquare,\n parentFrame: draggedShapeInitialFrame\n };\n \n const stateChanged = oldPos.x !== newPos.x || oldPos.y !== newPos.y ||\n oldPos.width !== newPos.width || oldPos.height !== newPos.height ||\n oldPos.rotation !== newPos.rotation;\n\n const frameChanged = oldPos.parentFrame !== newPos.parentFrame;\n\n if (stateChanged || frameChanged) {\n pushTransformAction(currentShape, oldPos, newPos);\n }\n \n // Handle frame containment changes after drag\n if (isDraggingShapeSquare) {\n const finalFrame = hoveredFrame;\n \n // If shape moved to a different frame\n if (draggedShapeInitialFrame !== finalFrame) {\n // Remove from initial frame\n if (draggedShapeInitialFrame) {\n draggedShapeInitialFrame.removeShapeFromFrame(currentShape);\n }\n \n // Add to new frame\n if (finalFrame) {\n finalFrame.addShapeToFrame(currentShape);\n }\n \n // Track the frame change for undo\n if (frameChanged) {\n pushFrameAttachmentAction(finalFrame || draggedShapeInitialFrame, currentShape, \n finalFrame ? 'attach' : 'detach', draggedShapeInitialFrame);\n }\n } else if (draggedShapeInitialFrame) {\n // Shape stayed in same frame, restore clipping\n draggedShapeInitialFrame.restoreToFrame(currentShape);\n }\n }\n \n dragOldPosSquare = null;\n draggedShapeInitialFrame = null;\n }\n \n // Clear frame highlighting\n if (hoveredFrame) {\n hoveredFrame.removeHighlight();\n hoveredFrame = null;\n }\n\n isDrawingSquare = false;\n isDraggingShapeSquare = false;\n isResizingShapeSquare = false;\n isRotatingShapeSquare = false;\n resizingAnchorIndexSquare = null;\n startRotationMouseAngleSquare = 0;\n startShapeRotationSquare = 0;\n clearSnapGuides();\n svg.style.cursor = 'default';\n};\n\nSquarecolorOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n if (currentShape && currentShape.shapeName === 'rectangle' && currentShape.isSelected) {\n pushOptionsChangeAction(currentShape, { ...currentShape.options }); \n squareStrokecolor = span.getAttribute(\"data-id\"); \n currentShape.options.stroke = squareStrokecolor; \n currentShape.draw();\n currentShape.updateSidebar(); \n } else {\n squareStrokecolor = span.getAttribute(\"data-id\");\n }\n SquarecolorOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\"); \n });\n});\n\nbackgroundColorOptionsSquare.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n if (currentShape && currentShape.shapeName === 'rectangle' && currentShape.isSelected) {\n pushOptionsChangeAction(currentShape, { ...currentShape.options });\n squareBackgroundColor = span.getAttribute(\"data-id\");\n currentShape.options.fill = squareBackgroundColor;\n currentShape.draw();\n currentShape.updateSidebar();\n } else {\n squareBackgroundColor = span.getAttribute(\"data-id\");\n }\n backgroundColorOptionsSquare.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n });\n});\n\nfillStyleOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation()\n if (currentShape && currentShape.shapeName === 'rectangle' && currentShape.isSelected) {\n pushOptionsChangeAction(currentShape, { ...currentShape.options });\n squareFillStyleValue = span.getAttribute(\"data-id\");\n currentShape.options.fillStyle = squareFillStyleValue;\n currentShape.draw();\n currentShape.updateSidebar();\n } else {\n squareFillStyleValue = span.getAttribute(\"data-id\");\n }\n fillStyleOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n });\n});\n\nsquareStrokeThicknessValue.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation()\n if (currentShape && currentShape.shapeName === 'rectangle' && currentShape.isSelected) {\n pushOptionsChangeAction(currentShape, { ...currentShape.options });\n squareStrokeThicknes = parseInt(span.getAttribute(\"data-id\"));\n currentShape.options.strokeWidth = squareStrokeThicknes;\n currentShape.draw();\n currentShape.updateSidebar();\n } else {\n squareStrokeThicknes = parseInt(span.getAttribute(\"data-id\"));\n }\n squareStrokeThicknessValue.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n });\n});\n\nsquareOutlineStyleValue.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n if (currentShape && currentShape.shapeName === 'rectangle' && currentShape.isSelected) {\n pushOptionsChangeAction(currentShape, { ...currentShape.options });\n squareOutlineStyle = span.getAttribute(\"data-id\");\n if (squareOutlineStyle === \"dashed\") {\n currentShape.options.strokeDasharray = \"10,10\";\n } else if (squareOutlineStyle === \"dotted\") {\n currentShape.options.strokeDasharray = \"2,8\";\n } else {\n currentShape.options.strokeDasharray = \"\";\n }\n currentShape.draw();\n currentShape.updateSidebar();\n } else {\n squareOutlineStyle = span.getAttribute(\"data-id\");\n }\n squareOutlineStyleValue.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n });\n});\n\nwindow.Rectangle = Rectangle;\n\n// Bridge rectangle tool settings to React sidebar\nwindow.rectToolSettings = {\n get strokeColor() { return squareStrokecolor; },\n set strokeColor(v) { squareStrokecolor = v; },\n get bgColor() { return squareBackgroundColor; },\n set bgColor(v) { squareBackgroundColor = v; },\n get fillStyle() { return squareFillStyleValue; },\n set fillStyle(v) { squareFillStyleValue = v; },\n get strokeWidth() { return squareStrokeThicknes; },\n set strokeWidth(v) { squareStrokeThicknes = v; },\n get outlineStyle() { return squareOutlineStyle; },\n set outlineStyle(v) { squareOutlineStyle = v; },\n};\nwindow.updateSelectedRectStyle = function(changes) {\n if (currentShape && currentShape.shapeName === 'rectangle' && currentShape.isSelected) {\n pushOptionsChangeAction(currentShape, { ...currentShape.options });\n if (changes.stroke !== undefined) { squareStrokecolor = changes.stroke; currentShape.options.stroke = changes.stroke; }\n if (changes.fill !== undefined) { squareBackgroundColor = changes.fill; currentShape.options.fill = changes.fill; }\n if (changes.fillStyle !== undefined) { squareFillStyleValue = changes.fillStyle; currentShape.options.fillStyle = changes.fillStyle; }\n if (changes.strokeWidth !== undefined) { squareStrokeThicknes = changes.strokeWidth; currentShape.options.strokeWidth = changes.strokeWidth; }\n if (changes.outlineStyle !== undefined) {\n squareOutlineStyle = changes.outlineStyle;\n if (changes.outlineStyle === \"dashed\") currentShape.options.strokeDasharray = \"10,10\";\n else if (changes.outlineStyle === \"dotted\") currentShape.options.strokeDasharray = \"2,8\";\n else currentShape.options.strokeDasharray = \"\";\n }\n currentShape.draw();\n } else {\n if (changes.stroke !== undefined) squareStrokecolor = changes.stroke;\n if (changes.fill !== undefined) squareBackgroundColor = changes.fill;\n if (changes.fillStyle !== undefined) squareFillStyleValue = changes.fillStyle;\n if (changes.strokeWidth !== undefined) squareStrokeThicknes = changes.strokeWidth;\n if (changes.outlineStyle !== undefined) squareOutlineStyle = changes.outlineStyle;\n }\n};\n\nexport { handleMouseDownRect, handleMouseMoveRect, handleMouseUpRect };\n"],
4
+ "sourcesContent": ["/* eslint-disable */\n// Rectangle tool event handlers - extracted from drawSquare.js\n// Depends on globals: svg, shapes, currentShape, rough, currentZoom, lastMousePos\n// Depends on globals: isSquareToolActive, isSelectionToolActive\n// Depends on globals: squareSideBar, disableAllSideBars\nimport { pushCreateAction, pushDeleteAction, pushOptionsChangeAction, pushTransformAction, pushFrameAttachmentAction } from '../core/UndoRedo.js';\nimport { cleanupAttachments } from './arrowTool.js';\nimport { calculateSnap, clearSnapGuides } from '../core/SnapGuides.js';\n\nlet isDrawingSquare = false;\nlet isDraggingShapeSquare = false;\nlet isResizingShapeSquare = false;\nlet isRotatingShapeSquare = false;\nlet resizingAnchorIndexSquare = null;\nlet startRotationMouseAngleSquare = 0;\nlet startShapeRotationSquare = 0;\nconst rc = rough.svg(svg); \nlet startX, startY;\n// Issue #38 follow-up: null sentinel means \"use theme default at draw\n// time\". The legacy `\"#fff\"` literal was invisible on the light canvas;\n// reading the body's `theme-dark` class lets the same code produce a\n// readable stroke in either mode. As soon as the user picks a colour\n// from the sidebar this var holds that value verbatim.\nfunction getThemeStroke() {\n if (typeof document === 'undefined') return '#fff';\n return document.body && document.body.classList.contains('theme-dark') ? '#fff' : '#000000';\n}\nlet squareStrokecolor = null;\nlet squareBackgroundColor = \"transparent\";\nlet squareFillStyleValue = \"none\";\nlet squareStrokeThicknes = 2;\nlet squareOutlineStyle = \"solid\";\nlet dragOldPosSquare = null;\nlet draggedShapeInitialFrame = null;\nlet hoveredFrame = null;\n\nlet SquarecolorOptions = document.querySelectorAll(\".squareStrokeSpan\");\nlet backgroundColorOptionsSquare = document.querySelectorAll(\".squareBackgroundSpan\");\nlet fillStyleOptions = document.querySelectorAll(\".squareFillStyleSpan\");\nlet squareStrokeThicknessValue = document.querySelectorAll(\".squareStrokeThickSpan\");\nlet squareOutlineStyleValue = document.querySelectorAll(\".squareOutlineStyle\");\n\n\n\nfunction getSVGCoordsFromMouse(e) {\n // Use the SVG's current viewBox to map mouse to SVG coordinates\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\nfunction deleteCurrentShape() {\n if (currentShape && currentShape.shapeName === 'rectangle') {\n const idx = shapes.indexOf(currentShape);\n if (idx !== -1) shapes.splice(idx, 1);\n \n // Clean up any arrow attachments before deleting\n cleanupAttachments(currentShape);\n \n if (currentShape.group.parentNode) {\n currentShape.group.parentNode.removeChild(currentShape.group);\n }\n pushDeleteAction(currentShape);\n currentShape = null;\n disableAllSideBars();\n }\n}\n\n// --- Main event handlers ---\nconst handleMouseDownRect = (e) => {\n const { x: mouseX, y: mouseY } = getSVGCoordsFromMouse(e);\n if (isSquareToolActive) {\n startX = mouseX;\n startY = mouseY;\n isDrawingSquare = true;\n\n if (currentShape) {\n currentShape.removeSelection();\n currentShape = null;\n disableAllSideBars();\n }\n\n let initialOptions = {\n stroke: squareStrokecolor ?? getThemeStroke(),\n fill: squareBackgroundColor,\n fillStyle: squareFillStyleValue,\n strokeWidth: squareStrokeThicknes,\n };\n if (squareOutlineStyle === \"dashed\") {\n initialOptions.strokeDasharray = \"10,10\";\n } else if (squareOutlineStyle === \"dotted\") {\n initialOptions.strokeDasharray = \"2,8\";\n } else {\n initialOptions.strokeDasharray = \"\";\n }\n\n currentShape = new Rectangle(startX, startY, 0, 0, initialOptions);\n currentShape.setDrawingState(true);\n\n } else if (isSelectionToolActive) {\n let clickedOnShape = false;\n if (currentShape && currentShape.shapeName === 'rectangle' && currentShape.isSelected) {\n const anchorInfo = currentShape.isNearAnchor(mouseX, mouseY);\n if (anchorInfo) {\n dragOldPosSquare = { x: currentShape.x, y: currentShape.y, width: currentShape.width, height: currentShape.height, rotation: currentShape.rotation };\n if (anchorInfo.type === 'resize') {\n isResizingShapeSquare = true;\n resizingAnchorIndexSquare = anchorInfo.index;\n } else if (anchorInfo.type === 'rotate') {\n isRotatingShapeSquare = true;\n\n const centerX = currentShape.x + currentShape.width / 2;\n const centerY = currentShape.y + currentShape.height / 2;\n startRotationMouseAngleSquare = Math.atan2(mouseY - centerY, mouseX - centerX) * 180 / Math.PI;\n startShapeRotationSquare = currentShape.rotation;\n }\n clickedOnShape = true;\n } else if (currentShape.contains(mouseX, mouseY)) {\n isDraggingShapeSquare = true;\n dragOldPosSquare = { x: currentShape.x, y: currentShape.y, width: currentShape.width, height: currentShape.height, rotation: currentShape.rotation };\n \n // Store initial frame state\n draggedShapeInitialFrame = currentShape.parentFrame || null;\n \n // Temporarily remove from frame clipping if dragging\n if (currentShape.parentFrame) {\n currentShape.parentFrame.temporarilyRemoveFromFrame(currentShape);\n }\n \n startX = mouseX; \n startY = mouseY;\n clickedOnShape = true;\n }\n }\n\n if (!clickedOnShape) {\n let shapeToSelect = null;\n for (let i = shapes.length - 1; i >= 0; i--) {\n const shape = shapes[i];\n if (shape.shapeName === 'rectangle' && shape.contains(mouseX, mouseY)) {\n shapeToSelect = shape;\n break; \n }\n }\n if (currentShape && currentShape !== shapeToSelect) {\n currentShape.removeSelection();\n currentShape = null;\n disableAllSideBars();\n }\n if (shapeToSelect) {\n currentShape = shapeToSelect;\n currentShape.isSelected = true;\n currentShape.draw(); \n isDraggingShapeSquare = true; \n dragOldPosSquare = { x: currentShape.x, y: currentShape.y, width: currentShape.width, height: currentShape.height, rotation: currentShape.rotation };\n \n // Store initial frame state\n draggedShapeInitialFrame = currentShape.parentFrame || null;\n \n // Temporarily remove from frame clipping if dragging\n if (currentShape.parentFrame) {\n currentShape.parentFrame.temporarilyRemoveFromFrame(currentShape);\n }\n \n startX = mouseX; \n startY = mouseY;\n clickedOnShape = true; \n }\n }\n if (!clickedOnShape && currentShape) {\n currentShape.removeSelection();\n currentShape = null;\n disableAllSideBars();\n }\n }\n};\n\n\nconst handleMouseMoveRect = (e) => {\n const { x: mouseX, y: mouseY } = getSVGCoordsFromMouse(e);\n const svgRect = svg.getBoundingClientRect();\n lastMousePos = {\n x: e.clientX - svgRect.left, \n y: e.clientY - svgRect.top\n };\n\n if (isDrawingSquare && isSquareToolActive && currentShape) {\n let width = mouseX - startX;\n let height = mouseY - startY;\n currentShape.x = width < 0 ? startX + width : startX;\n currentShape.y = height < 0 ? startY + height : startY;\n currentShape.width = Math.abs(width);\n currentShape.height = Math.abs(height);\n \n // Force update the element size while drawing (but use cached rough element)\n if (currentShape.element && currentShape.width > 0 && currentShape.height > 0) {\n // Remove old element\n if (currentShape.element.parentNode === currentShape.group) {\n currentShape.group.removeChild(currentShape.element);\n }\n \n // Create new rough element with current size\n const roughRect = rc.rectangle(0, 0, currentShape.width, currentShape.height, currentShape.options);\n currentShape.element = roughRect;\n currentShape.group.appendChild(roughRect);\n }\n \n // Update transform\n const rotateCenterX = currentShape.width / 2;\n const rotateCenterY = currentShape.height / 2;\n currentShape.group.setAttribute('transform', `translate(${currentShape.x}, ${currentShape.y}) rotate(${currentShape.rotation}, ${rotateCenterX}, ${rotateCenterY})`);\n \n // Check for frame containment while drawing\n shapes.forEach(frame => {\n if (frame.shapeName === 'frame') {\n if (frame.isShapeInFrame(currentShape)) {\n frame.highlightFrame();\n hoveredFrame = frame;\n } else if (hoveredFrame === frame) {\n frame.removeHighlight();\n hoveredFrame = null;\n }\n }\n });\n \n } else if (isDraggingShapeSquare && currentShape && currentShape.isSelected) {\n let dx = mouseX - startX;\n let dy = mouseY - startY;\n currentShape.move(dx, dy);\n startX = mouseX;\n startY = mouseY;\n // Snap guides\n if (window.__sketchStoreApi && window.__sketchStoreApi.getState().snapToObjects) {\n const snap = calculateSnap(currentShape, e.shiftKey, e.clientX, e.clientY);\n if (snap.dx || snap.dy) {\n currentShape.move(snap.dx, snap.dy);\n }\n } else {\n clearSnapGuides();\n }\n\n // Issue #24 bug #4: track the actual containing frame at every\n // move so the mouseUp logic re-parents correctly. Without this\n // hoveredFrame stays at null for existing-shape drags and the\n // shape is detached the moment the user nudges it by 1 px inside\n // its own parent frame.\n let newHover = null;\n for (const f of shapes) {\n if (f.shapeName !== 'frame') continue;\n if (f === currentShape) continue;\n if (typeof f.isShapeInFrame === 'function' && f.isShapeInFrame(currentShape)) {\n newHover = f;\n break;\n }\n }\n if (hoveredFrame && hoveredFrame !== newHover && typeof hoveredFrame.removeHighlight === 'function') {\n hoveredFrame.removeHighlight();\n }\n if (newHover && newHover !== hoveredFrame && typeof newHover.highlightFrame === 'function') {\n newHover.highlightFrame();\n }\n hoveredFrame = newHover;\n } else if (isResizingShapeSquare && currentShape && currentShape.isSelected && resizingAnchorIndexSquare !== null) {\n currentShape.updatePosition(resizingAnchorIndexSquare, mouseX, mouseY);\n currentShape._skipAnchors = true;\n currentShape.draw();\n currentShape._skipAnchors = false;\n } else if (isRotatingShapeSquare && currentShape && currentShape.isSelected) {\n const centerX = currentShape.x + currentShape.width / 2;\n const centerY = currentShape.y + currentShape.height / 2;\n const currentRotationMouseAngle = Math.atan2(mouseY - centerY, mouseX - centerX) * 180 / Math.PI;\n const angleDiff = currentRotationMouseAngle - startRotationMouseAngleSquare;\n let newRotation = startShapeRotationSquare + angleDiff;\n const snapAngle = 15;\n if (e.shiftKey) {\n newRotation = Math.round(newRotation / snapAngle) * snapAngle;\n }\n currentShape.rotate(newRotation);\n currentShape._skipAnchors = true;\n currentShape.draw();\n currentShape._skipAnchors = false;\n svg.style.cursor = 'grabbing'; \n } else if (isSelectionToolActive && !isDrawingSquare && currentShape && currentShape.isSelected) {\n const anchorInfo = currentShape.isNearAnchor(mouseX, mouseY);\n if (anchorInfo) {\n if (anchorInfo.type === 'resize') {\n const baseDirection = anchorInfo.index; \n const rotatedCursor = currentShape.getRotatedCursor(baseDirection, currentShape.rotation);\n svg.style.cursor = rotatedCursor + '-resize';\n } else if (anchorInfo.type === 'rotate') {\n svg.style.cursor = 'grab';\n }\n } else if (currentShape.contains(mouseX, mouseY)) {\n svg.style.cursor = 'move';\n } else {\n svg.style.cursor = 'default';\n }\n } else if (isSelectionToolActive && !isDrawingSquare && !isDraggingShapeSquare && !isResizingShapeSquare && !isRotatingShapeSquare) {\n let hoveredShape = null;\n for (let i = shapes.length - 1; i >= 0; i--) {\n const shape = shapes[i];\n if (shape.shapeName === 'rectangle' && shape.contains(mouseX, mouseY)) {\n hoveredShape = shape;\n break;\n }\n }\n if (hoveredShape) {\n svg.style.cursor = 'pointer';\n } else {\n svg.style.cursor = 'default'; \n }\n }\n};\n\n \nconst handleMouseUpRect = (e) => {\n if (isDrawingSquare && currentShape) {\n currentShape.setDrawingState(false);\n if (currentShape.width === 0 || currentShape.height === 0) {\n if (currentShape.group.parentNode) {\n currentShape.group.parentNode.removeChild(currentShape.group);\n }\n currentShape = null;\n } else {\n currentShape.draw();\n shapes.push(currentShape);\n pushCreateAction(currentShape);\n\n // Check for frame containment and track attachment\n const finalFrame = hoveredFrame;\n if (finalFrame) {\n finalFrame.addShapeToFrame(currentShape);\n // Track the attachment for undo\n pushFrameAttachmentAction(finalFrame, currentShape, 'attach', null);\n }\n\n // Auto-select the drawn shape and switch to selection tool\n const drawnShape = currentShape;\n if (window.__sketchStoreApi) window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });\n currentShape = drawnShape;\n currentShape.isSelected = true;\n if (typeof currentShape.addAnchors === 'function') {\n currentShape.addAnchors();\n }\n }\n \n // Clear frame highlighting\n if (hoveredFrame) {\n hoveredFrame.removeHighlight();\n hoveredFrame = null;\n }\n }\n\n if ((isDraggingShapeSquare || isResizingShapeSquare || isRotatingShapeSquare) && dragOldPosSquare && currentShape) {\n // Issue #34 bug #2: for drag operations the actual frame transfer\n // happens AFTER this mouseUp block \u2014 so `currentShape.parentFrame`\n // at this point still points at the OLD frame. Use the hovered\n // frame (tracked during mousemove) as the authoritative new\n // destination instead, so the undo action records a real\n // attachment delta and Ctrl+Z re-attaches the shape correctly.\n const newPos = {\n x: currentShape.x,\n y: currentShape.y,\n width: currentShape.width,\n height: currentShape.height,\n rotation: currentShape.rotation,\n parentFrame: isDraggingShapeSquare ? (hoveredFrame || null) : currentShape.parentFrame,\n };\n const oldPos = {\n ...dragOldPosSquare,\n parentFrame: draggedShapeInitialFrame\n };\n \n const stateChanged = oldPos.x !== newPos.x || oldPos.y !== newPos.y ||\n oldPos.width !== newPos.width || oldPos.height !== newPos.height ||\n oldPos.rotation !== newPos.rotation;\n\n const frameChanged = oldPos.parentFrame !== newPos.parentFrame;\n\n if (stateChanged || frameChanged) {\n pushTransformAction(currentShape, oldPos, newPos);\n }\n \n // Handle frame containment changes after drag\n if (isDraggingShapeSquare) {\n const finalFrame = hoveredFrame;\n \n // If shape moved to a different frame\n if (draggedShapeInitialFrame !== finalFrame) {\n // Remove from initial frame\n if (draggedShapeInitialFrame) {\n draggedShapeInitialFrame.removeShapeFromFrame(currentShape);\n }\n \n // Add to new frame\n if (finalFrame) {\n finalFrame.addShapeToFrame(currentShape);\n }\n \n // Track the frame change for undo\n if (frameChanged) {\n pushFrameAttachmentAction(finalFrame || draggedShapeInitialFrame, currentShape, \n finalFrame ? 'attach' : 'detach', draggedShapeInitialFrame);\n }\n } else if (draggedShapeInitialFrame) {\n // Shape stayed in same frame, restore clipping\n draggedShapeInitialFrame.restoreToFrame(currentShape);\n }\n }\n \n dragOldPosSquare = null;\n draggedShapeInitialFrame = null;\n }\n \n // Clear frame highlighting\n if (hoveredFrame) {\n hoveredFrame.removeHighlight();\n hoveredFrame = null;\n }\n\n isDrawingSquare = false;\n isDraggingShapeSquare = false;\n isResizingShapeSquare = false;\n isRotatingShapeSquare = false;\n resizingAnchorIndexSquare = null;\n startRotationMouseAngleSquare = 0;\n startShapeRotationSquare = 0;\n clearSnapGuides();\n svg.style.cursor = 'default';\n};\n\nSquarecolorOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n if (currentShape && currentShape.shapeName === 'rectangle' && currentShape.isSelected) {\n pushOptionsChangeAction(currentShape, { ...currentShape.options }); \n squareStrokecolor = span.getAttribute(\"data-id\"); \n currentShape.options.stroke = squareStrokecolor; \n currentShape.draw();\n currentShape.updateSidebar(); \n } else {\n squareStrokecolor = span.getAttribute(\"data-id\");\n }\n SquarecolorOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\"); \n });\n});\n\nbackgroundColorOptionsSquare.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n if (currentShape && currentShape.shapeName === 'rectangle' && currentShape.isSelected) {\n pushOptionsChangeAction(currentShape, { ...currentShape.options });\n squareBackgroundColor = span.getAttribute(\"data-id\");\n currentShape.options.fill = squareBackgroundColor;\n currentShape.draw();\n currentShape.updateSidebar();\n } else {\n squareBackgroundColor = span.getAttribute(\"data-id\");\n }\n backgroundColorOptionsSquare.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n });\n});\n\nfillStyleOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation()\n if (currentShape && currentShape.shapeName === 'rectangle' && currentShape.isSelected) {\n pushOptionsChangeAction(currentShape, { ...currentShape.options });\n squareFillStyleValue = span.getAttribute(\"data-id\");\n currentShape.options.fillStyle = squareFillStyleValue;\n currentShape.draw();\n currentShape.updateSidebar();\n } else {\n squareFillStyleValue = span.getAttribute(\"data-id\");\n }\n fillStyleOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n });\n});\n\nsquareStrokeThicknessValue.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation()\n if (currentShape && currentShape.shapeName === 'rectangle' && currentShape.isSelected) {\n pushOptionsChangeAction(currentShape, { ...currentShape.options });\n squareStrokeThicknes = parseInt(span.getAttribute(\"data-id\"));\n currentShape.options.strokeWidth = squareStrokeThicknes;\n currentShape.draw();\n currentShape.updateSidebar();\n } else {\n squareStrokeThicknes = parseInt(span.getAttribute(\"data-id\"));\n }\n squareStrokeThicknessValue.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n });\n});\n\nsquareOutlineStyleValue.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n if (currentShape && currentShape.shapeName === 'rectangle' && currentShape.isSelected) {\n pushOptionsChangeAction(currentShape, { ...currentShape.options });\n squareOutlineStyle = span.getAttribute(\"data-id\");\n if (squareOutlineStyle === \"dashed\") {\n currentShape.options.strokeDasharray = \"10,10\";\n } else if (squareOutlineStyle === \"dotted\") {\n currentShape.options.strokeDasharray = \"2,8\";\n } else {\n currentShape.options.strokeDasharray = \"\";\n }\n currentShape.draw();\n currentShape.updateSidebar();\n } else {\n squareOutlineStyle = span.getAttribute(\"data-id\");\n }\n squareOutlineStyleValue.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n });\n});\n\nwindow.Rectangle = Rectangle;\n\n// Bridge rectangle tool settings to React sidebar\nwindow.rectToolSettings = {\n get strokeColor() { return squareStrokecolor; },\n set strokeColor(v) { squareStrokecolor = v; },\n get bgColor() { return squareBackgroundColor; },\n set bgColor(v) { squareBackgroundColor = v; },\n get fillStyle() { return squareFillStyleValue; },\n set fillStyle(v) { squareFillStyleValue = v; },\n get strokeWidth() { return squareStrokeThicknes; },\n set strokeWidth(v) { squareStrokeThicknes = v; },\n get outlineStyle() { return squareOutlineStyle; },\n set outlineStyle(v) { squareOutlineStyle = v; },\n};\nwindow.updateSelectedRectStyle = function(changes) {\n if (currentShape && currentShape.shapeName === 'rectangle' && currentShape.isSelected) {\n pushOptionsChangeAction(currentShape, { ...currentShape.options });\n if (changes.stroke !== undefined) { squareStrokecolor = changes.stroke; currentShape.options.stroke = changes.stroke; }\n if (changes.fill !== undefined) { squareBackgroundColor = changes.fill; currentShape.options.fill = changes.fill; }\n if (changes.fillStyle !== undefined) { squareFillStyleValue = changes.fillStyle; currentShape.options.fillStyle = changes.fillStyle; }\n if (changes.strokeWidth !== undefined) { squareStrokeThicknes = changes.strokeWidth; currentShape.options.strokeWidth = changes.strokeWidth; }\n if (changes.outlineStyle !== undefined) {\n squareOutlineStyle = changes.outlineStyle;\n if (changes.outlineStyle === \"dashed\") currentShape.options.strokeDasharray = \"10,10\";\n else if (changes.outlineStyle === \"dotted\") currentShape.options.strokeDasharray = \"2,8\";\n else currentShape.options.strokeDasharray = \"\";\n }\n currentShape.draw();\n } else {\n if (changes.stroke !== undefined) squareStrokecolor = changes.stroke;\n if (changes.fill !== undefined) squareBackgroundColor = changes.fill;\n if (changes.fillStyle !== undefined) squareFillStyleValue = changes.fillStyle;\n if (changes.strokeWidth !== undefined) squareStrokeThicknes = changes.strokeWidth;\n if (changes.outlineStyle !== undefined) squareOutlineStyle = changes.outlineStyle;\n }\n};\n\nexport { handleMouseDownRect, handleMouseMoveRect, handleMouseUpRect };\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  calculateSnap,
4
4
  clearSnapGuides
5
- } from "./chunk-X5ENBMGL.js";
5
+ } from "./chunk-KXLNEFN5.js";
6
6
  import {
7
7
  pushCreateAction,
8
8
  pushDeleteAction,
@@ -14,7 +14,7 @@ import {
14
14
  // src/tools/lineTool.js
15
15
  function getThemeStroke() {
16
16
  if (typeof document === "undefined") return "#fff";
17
- return document.body && document.body.classList.contains("theme-dark") ? "#fff" : "#1a1a2e";
17
+ return document.body && document.body.classList.contains("theme-dark") ? "#fff" : "#000000";
18
18
  }
19
19
  var isDrawingLine = false;
20
20
  var currentLine = null;
@@ -450,4 +450,4 @@ export {
450
450
  handleMouseMove,
451
451
  handleMouseUp
452
452
  };
453
- //# sourceMappingURL=chunk-CGMUXYPJ.js.map
453
+ //# sourceMappingURL=chunk-JVHZVV5U.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/tools/lineTool.js"],
4
- "sourcesContent": ["/* eslint-disable */\n// Line tool event handlers - extracted from lineTool.js\nimport { pushCreateAction, pushDeleteAction, pushOptionsChangeAction, pushTransformAction, pushFrameAttachmentAction } from '../core/UndoRedo.js';\nimport { updateAttachedArrows as updateArrowsForShape, cleanupAttachments } from './arrowTool.js';\nimport { calculateSnap, clearSnapGuides } from '../core/SnapGuides.js';\n\nfunction getThemeStroke() { if (typeof document === \"undefined\") return \"#fff\"; return document.body && document.body.classList.contains(\"theme-dark\") ? \"#fff\" : \"#1a1a2e\"; }\n\nlet isDrawingLine = false;\nlet currentLine = null;\nlet lineStartX = 0; \nlet lineStartY = 0; \nlet currentLineGroup = null; \nlet lineColor = null;\nlet lineStrokeWidth = 3;\nlet lineStrokeStyle = \"solid\";\nlet lineEdgeType = 1;\nlet lineSktetchRate = 3;\n\nlet isDraggingLine = false;\nlet dragOldPosLine = null;\nlet copiedShapeData = null;\nlet draggedShapeInitialFrameLine = null;\nlet hoveredFrameLine = null;\n\nlet startX, startY;\n\nlet lineColorOptions = document.querySelectorAll(\".lineColor > span\");\nlet lineThicknessOptions = document.querySelectorAll(\".lineThicknessSpan\");\nlet lineOutlineOptions = document.querySelectorAll(\".lineStyleSpan\");\nlet lineSlopeOptions = document.querySelectorAll(\".lineSlopeSpan\");\nlet lineEdgeOptions = document.querySelectorAll(\".lineEdgeSpan\");\n\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// Add delete functionality\nfunction deleteCurrentShape() {\n if (currentShape && currentShape.shapeName === 'line') {\n const idx = shapes.indexOf(currentShape);\n if (idx !== -1) shapes.splice(idx, 1);\n if (currentShape.group.parentNode) {\n currentShape.group.parentNode.removeChild(currentShape.group);\n }\n pushDeleteAction(currentShape);\n currentShape = null;\n disableAllSideBars();\n }\n}\n\ndocument.addEventListener('keydown', (e) => {\n if (e.key === 'Delete' && currentShape && currentShape.shapeName === 'line') {\n deleteCurrentShape();\n }\n});\n\nconst handleMouseDown = (e) => {\n if (!isLineToolActive && !isSelectionToolActive) return;\n\n const { x, y } = getSVGCoordsFromMouse(e);\n\n if (isLineToolActive) {\n isDrawingLine = true;\n currentLine = new Line(\n { x, y },\n { x, y },\n {\n stroke: lineColor ?? getThemeStroke(),\n strokeWidth: lineStrokeWidth,\n roughness: lineSktetchRate,\n bowing: lineEdgeType,\n strokeDasharray: lineStrokeStyle === \"dashed\" ? \"5,5\" : (lineStrokeStyle === \"dotted\" ? \"2,12\" : \"\")\n }\n );\n currentLine.isBeingDrawn = true;\n shapes.push(currentLine);\n currentShape = currentLine;\n } else if (isSelectionToolActive) {\n let clickedOnShape = false;\n \n // Check if clicking on current selected line\n if (currentShape && currentShape.shapeName === 'line' && currentShape.isSelected) {\n const anchorInfo = currentShape.isNearAnchor(x, y);\n \n if (anchorInfo && anchorInfo.type === 'anchor') {\n clickedOnShape = true;\n // Start anchor drag\n dragOldPosLine = {\n startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },\n endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },\n controlPoint: currentShape.controlPoint ? { x: currentShape.controlPoint.x, y: currentShape.controlPoint.y } : null,\n isCurved: currentShape.isCurved,\n parentFrame: currentShape.parentFrame\n };\n \n const anchorIndex = anchorInfo.index;\n \n const onPointerMove = (event) => {\n const { x: newX, y: newY } = getSVGCoordsFromMouse(event);\n currentShape.updatePosition(anchorIndex, newX, newY);\n };\n \n const onPointerUp = () => {\n if (dragOldPosLine) {\n const newPos = {\n startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },\n endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },\n controlPoint: currentShape.controlPoint ? { x: currentShape.controlPoint.x, y: currentShape.controlPoint.y } : null,\n isCurved: currentShape.isCurved,\n parentFrame: currentShape.parentFrame\n };\n pushTransformAction(currentShape, dragOldPosLine, newPos);\n dragOldPosLine = null;\n }\n svg.removeEventListener('pointermove', onPointerMove);\n svg.removeEventListener('pointerup', onPointerUp);\n };\n \n svg.addEventListener('pointermove', onPointerMove);\n svg.addEventListener('pointerup', onPointerUp);\n \n // Prevent default to stop any other drag behavior\n e.preventDefault();\n e.stopPropagation();\n \n } else if (currentShape.contains(x, y)) {\n // Dragging the line itself (not anchors)\n isDraggingLine = true;\n dragOldPosLine = {\n startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },\n endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },\n controlPoint: currentShape.controlPoint ? { x: currentShape.controlPoint.x, y: currentShape.controlPoint.y } : null,\n isCurved: currentShape.isCurved,\n parentFrame: currentShape.parentFrame\n };\n \n // Store initial frame state\n draggedShapeInitialFrameLine = currentShape.parentFrame || null;\n \n // Temporarily remove from frame clipping if dragging\n if (currentShape.parentFrame) {\n currentShape.parentFrame.temporarilyRemoveFromFrame(currentShape);\n }\n \n startX = x;\n startY = y;\n clickedOnShape = true;\n }\n }\n\n // If not clicking on selected shape, check for other shapes\n if (!clickedOnShape) {\n let shapeToSelect = null;\n for (let i = shapes.length - 1; i >= 0; i--) {\n const shape = shapes[i];\n if (shape instanceof Line && shape.contains(x, y)) {\n shapeToSelect = shape;\n break;\n }\n }\n\n if (currentShape && currentShape !== shapeToSelect) {\n currentShape.removeSelection();\n currentShape = null;\n }\n\n if (shapeToSelect) {\n currentShape = shapeToSelect;\n currentShape.selectLine();\n clickedOnShape = true;\n }\n }\n\n if (!clickedOnShape && currentShape) {\n currentShape.removeSelection();\n currentShape = null;\n }\n }\n};\n// Update clone function to remove rotation property\nfunction cloneLineData(line) {\n return {\n startPoint: { x: line.startPoint.x, y: line.startPoint.y },\n endPoint: { x: line.endPoint.x, y: line.endPoint.y },\n controlPoint: line.controlPoint ? { x: line.controlPoint.x, y: line.controlPoint.y } : null,\n isCurved: line.isCurved || false,\n parentFrame: line.parentFrame,\n options: cloneOptions(line.options)\n };\n}\n\nconst handleMouseMove = (e) => {\n const { x, y } = getSVGCoordsFromMouse(e);\n \n // Keep lastMousePos in screen coordinates for other functions\n const svgRect = svg.getBoundingClientRect();\n lastMousePos = {\n x: e.clientX - svgRect.left, \n y: e.clientY - svgRect.top\n };\n \n if (isDrawingLine && currentLine) {\n let endX = x, endY = y;\n if (e.shiftKey) {\n const dx = x - currentLine.startPoint.x;\n const dy = y - currentLine.startPoint.y;\n const angle = Math.atan2(dy, dx);\n const snapAngle = Math.round(angle / (Math.PI / 4)) * (Math.PI / 4);\n const dist = Math.sqrt(dx * dx + dy * dy);\n endX = currentLine.startPoint.x + dist * Math.cos(snapAngle);\n endY = currentLine.startPoint.y + dist * Math.sin(snapAngle);\n }\n currentLine.endPoint = { x: endX, y: endY };\n currentLine.draw();\n \n // Check for frame containment while drawing (but don't apply clipping yet)\n shapes.forEach(frame => {\n if (frame.shapeName === 'frame') {\n if (frame.isShapeInFrame(currentLine)) {\n frame.highlightFrame();\n hoveredFrameLine = frame;\n } else if (hoveredFrameLine === frame) {\n frame.removeHighlight();\n hoveredFrameLine = null;\n }\n }\n });\n } else if (isDraggingLine && currentShape && currentShape.isSelected) {\n const dx = x - startX;\n const dy = y - startY;\n currentShape.move(dx, dy);\n startX = x;\n startY = y;\n\n // Issue #24 bug #4: track containing frame during existing-line\n // drag so mouseUp re-parents from current geometry, not from a\n // stale hoveredFrameLine.\n let newHover = null;\n for (const f of shapes) {\n if (f.shapeName !== 'frame') continue;\n if (f === currentShape) continue;\n if (typeof f.isShapeInFrame === 'function' && f.isShapeInFrame(currentShape)) {\n newHover = f;\n break;\n }\n }\n if (hoveredFrameLine && hoveredFrameLine !== newHover && typeof hoveredFrameLine.removeHighlight === 'function') {\n hoveredFrameLine.removeHighlight();\n }\n if (newHover && newHover !== hoveredFrameLine && typeof newHover.highlightFrame === 'function') {\n newHover.highlightFrame();\n }\n hoveredFrameLine = newHover;\n\n // Snap guides\n if (window.__sketchStoreApi && window.__sketchStoreApi.getState().snapToObjects) {\n const snap = calculateSnap(currentShape, e.shiftKey, e.clientX, e.clientY);\n if (snap.dx || snap.dy) {\n currentShape.move(snap.dx, snap.dy);\n }\n } else {\n clearSnapGuides();\n }\n }\n};\n\nconst handleMouseUp = (e) => {\n if (isDrawingLine) {\n isDrawingLine = false;\n \n // Check if line is too small\n const dx = currentLine.endPoint.x - currentLine.startPoint.x;\n const dy = currentLine.endPoint.y - currentLine.startPoint.y;\n const lengthSq = dx * dx + dy * dy;\n \n if (lengthSq < (5 / currentZoom) ** 2) {\n shapes.pop();\n if (currentLine.group.parentNode) {\n currentLine.group.parentNode.removeChild(currentLine.group);\n }\n currentLine = null;\n currentShape = null;\n } else {\n // Finalize: apply roughness now that drawing is done\n currentLine.isBeingDrawn = false;\n currentLine.draw();\n\n // Push create action for undo/redo\n pushCreateAction(currentLine);\n\n // Check for frame containment and track attachment\n const finalFrame = hoveredFrameLine;\n if (finalFrame) {\n finalFrame.addShapeToFrame(currentLine);\n // Track the attachment for undo\n pushFrameAttachmentAction(finalFrame, currentLine, 'attach', null);\n }\n\n // Auto-select the drawn line and switch to selection tool\n const drawnLine = currentLine;\n if (window.__sketchStoreApi) window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });\n currentShape = drawnLine;\n drawnLine.selectLine();\n }\n \n // Clear frame highlighting\n if (hoveredFrameLine) {\n hoveredFrameLine.removeHighlight();\n hoveredFrameLine = null;\n }\n \n currentLine = null;\n }\n \n if (isDraggingLine && dragOldPosLine && currentShape) {\n // Issue #34 bug #2: use hoveredFrameLine (actual destination) instead\n // of the stale parentFrame \u2014 containment transfer hasn't happened yet.\n const newPos = {\n startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },\n endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },\n controlPoint: currentShape.controlPoint ? { x: currentShape.controlPoint.x, y: currentShape.controlPoint.y } : null,\n parentFrame: hoveredFrameLine || null,\n };\n const oldPos = {\n ...dragOldPosLine,\n parentFrame: draggedShapeInitialFrameLine\n };\n \n const stateChanged = dragOldPosLine.startPoint.x !== newPos.startPoint.x || \n dragOldPosLine.startPoint.y !== newPos.startPoint.y ||\n dragOldPosLine.endPoint.x !== newPos.endPoint.x || \n dragOldPosLine.endPoint.y !== newPos.endPoint.y;\n\n const frameChanged = oldPos.parentFrame !== newPos.parentFrame;\n \n if (stateChanged || frameChanged) {\n pushTransformAction(currentShape, oldPos, newPos);\n }\n \n // Handle frame containment changes after drag\n if (isDraggingLine) {\n const finalFrame = hoveredFrameLine;\n \n // If shape moved to a different frame\n if (draggedShapeInitialFrameLine !== finalFrame) {\n // Remove from initial frame\n if (draggedShapeInitialFrameLine) {\n draggedShapeInitialFrameLine.removeShapeFromFrame(currentShape);\n }\n \n // Add to new frame\n if (finalFrame) {\n finalFrame.addShapeToFrame(currentShape);\n }\n \n // Track the frame change for undo\n if (frameChanged) {\n pushFrameAttachmentAction(finalFrame || draggedShapeInitialFrameLine, currentShape, \n finalFrame ? 'attach' : 'detach', draggedShapeInitialFrameLine);\n }\n } else if (draggedShapeInitialFrameLine) {\n // Shape stayed in same frame, restore clipping\n draggedShapeInitialFrameLine.restoreToFrame(currentShape);\n }\n }\n \n dragOldPosLine = null;\n draggedShapeInitialFrameLine = null;\n }\n \n // Clear frame highlighting\n if (hoveredFrameLine) {\n hoveredFrameLine.removeHighlight();\n hoveredFrameLine = null;\n }\n \n clearSnapGuides();\n isDraggingLine = false;\n};\n\n// --- Event Handlers ---\n\n// --- Style Option Event Listeners ---\nlineColorOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n lineColorOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n \n if (currentShape instanceof Line && currentShape.isSelected) {\n const oldOptions = {...currentShape.options};\n currentShape.options.stroke = span.getAttribute(\"data-id\");\n currentShape.draw();\n pushOptionsChangeAction(currentShape, oldOptions);\n } else {\n lineColor = span.getAttribute(\"data-id\");\n }\n });\n});\n\nlineThicknessOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n lineThicknessOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n \n if (currentShape instanceof Line && currentShape.isSelected) {\n const oldOptions = {...currentShape.options};\n currentShape.options.strokeWidth = parseInt(span.getAttribute(\"data-id\"));\n currentShape.draw();\n pushOptionsChangeAction(currentShape, oldOptions);\n } else {\n lineStrokeWidth = parseInt(span.getAttribute(\"data-id\"));\n }\n });\n});\n\nlineOutlineOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n lineOutlineOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n \n if (currentShape instanceof Line && currentShape.isSelected) {\n const oldOptions = {...currentShape.options};\n const style = span.getAttribute(\"data-id\");\n currentShape.options.strokeDasharray = \n style === \"dashed\" ? \"5,5\" : \n (style === \"dotted\" ? \"2,12\" : \"\");\n currentShape.draw();\n pushOptionsChangeAction(currentShape, oldOptions);\n } else {\n lineStrokeStyle = span.getAttribute(\"data-id\");\n }\n });\n});\n\nlineSlopeOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n lineSlopeOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n \n if (currentShape instanceof Line && currentShape.isSelected) {\n const oldOptions = {...currentShape.options};\n currentShape.options.roughness = parseFloat(span.getAttribute(\"data-id\"));\n currentShape.draw();\n pushOptionsChangeAction(currentShape, oldOptions);\n } else {\n lineSktetchRate = parseFloat(span.getAttribute(\"data-id\"));\n }\n });\n});\n\nlineEdgeOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n lineEdgeOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n \n if (currentShape instanceof Line && currentShape.isSelected) {\n const oldOptions = {...currentShape.options};\n currentShape.options.bowing = parseFloat(span.getAttribute(\"data-id\"));\n currentShape.draw();\n pushOptionsChangeAction(currentShape, oldOptions);\n } else {\n lineEdgeType = parseFloat(span.getAttribute(\"data-id\"));\n }\n });\n});\n\n// Add copy/paste functionality\nfunction cloneOptions(options) {\n return JSON.parse(JSON.stringify(options));\n}\n\nwindow.Line = Line;\n\n// Bridge line tool settings to React sidebar\nwindow.lineToolSettings = {\n get strokeColor() { return lineColor; },\n set strokeColor(v) { lineColor = v; },\n get strokeWidth() { return lineStrokeWidth; },\n set strokeWidth(v) { lineStrokeWidth = v; },\n get strokeStyle() { return lineStrokeStyle; },\n set strokeStyle(v) { lineStrokeStyle = v; },\n get sloppiness() { return lineSktetchRate; },\n set sloppiness(v) { lineSktetchRate = v; },\n get edge() { return lineEdgeType; },\n set edge(v) { lineEdgeType = v; },\n};\nwindow.updateSelectedLineStyle = function(changes) {\n if (currentShape instanceof Line && currentShape.isSelected) {\n const oldOptions = {...currentShape.options};\n if (changes.stroke !== undefined) { lineColor = changes.stroke; currentShape.options.stroke = changes.stroke; }\n if (changes.strokeWidth !== undefined) { lineStrokeWidth = changes.strokeWidth; currentShape.options.strokeWidth = changes.strokeWidth; }\n if (changes.strokeStyle !== undefined) {\n lineStrokeStyle = changes.strokeStyle;\n currentShape.options.strokeDasharray = changes.strokeStyle === \"dashed\" ? \"5,5\" : (changes.strokeStyle === \"dotted\" ? \"2,12\" : \"\");\n }\n if (changes.sloppiness !== undefined) { lineSktetchRate = changes.sloppiness; currentShape.options.roughness = changes.sloppiness; }\n if (changes.edge !== undefined) { lineEdgeType = changes.edge; currentShape.options.bowing = changes.edge; }\n currentShape.draw();\n pushOptionsChangeAction(currentShape, oldOptions);\n } else {\n if (changes.stroke !== undefined) lineColor = changes.stroke;\n if (changes.strokeWidth !== undefined) lineStrokeWidth = changes.strokeWidth;\n if (changes.strokeStyle !== undefined) lineStrokeStyle = changes.strokeStyle;\n if (changes.sloppiness !== undefined) lineSktetchRate = changes.sloppiness;\n if (changes.edge !== undefined) lineEdgeType = changes.edge;\n }\n};\n\nexport {\n handleMouseDown as handleMouseDownLine,\n handleMouseMove as handleMouseMoveLine,\n handleMouseUp as handleMouseUpLine,\n};\n"],
4
+ "sourcesContent": ["/* eslint-disable */\n// Line tool event handlers - extracted from lineTool.js\nimport { pushCreateAction, pushDeleteAction, pushOptionsChangeAction, pushTransformAction, pushFrameAttachmentAction } from '../core/UndoRedo.js';\nimport { updateAttachedArrows as updateArrowsForShape, cleanupAttachments } from './arrowTool.js';\nimport { calculateSnap, clearSnapGuides } from '../core/SnapGuides.js';\n\nfunction getThemeStroke() { if (typeof document === \"undefined\") return \"#fff\"; return document.body && document.body.classList.contains(\"theme-dark\") ? \"#fff\" : \"#000000\"; }\n\nlet isDrawingLine = false;\nlet currentLine = null;\nlet lineStartX = 0; \nlet lineStartY = 0; \nlet currentLineGroup = null; \nlet lineColor = null;\nlet lineStrokeWidth = 3;\nlet lineStrokeStyle = \"solid\";\nlet lineEdgeType = 1;\nlet lineSktetchRate = 3;\n\nlet isDraggingLine = false;\nlet dragOldPosLine = null;\nlet copiedShapeData = null;\nlet draggedShapeInitialFrameLine = null;\nlet hoveredFrameLine = null;\n\nlet startX, startY;\n\nlet lineColorOptions = document.querySelectorAll(\".lineColor > span\");\nlet lineThicknessOptions = document.querySelectorAll(\".lineThicknessSpan\");\nlet lineOutlineOptions = document.querySelectorAll(\".lineStyleSpan\");\nlet lineSlopeOptions = document.querySelectorAll(\".lineSlopeSpan\");\nlet lineEdgeOptions = document.querySelectorAll(\".lineEdgeSpan\");\n\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// Add delete functionality\nfunction deleteCurrentShape() {\n if (currentShape && currentShape.shapeName === 'line') {\n const idx = shapes.indexOf(currentShape);\n if (idx !== -1) shapes.splice(idx, 1);\n if (currentShape.group.parentNode) {\n currentShape.group.parentNode.removeChild(currentShape.group);\n }\n pushDeleteAction(currentShape);\n currentShape = null;\n disableAllSideBars();\n }\n}\n\ndocument.addEventListener('keydown', (e) => {\n if (e.key === 'Delete' && currentShape && currentShape.shapeName === 'line') {\n deleteCurrentShape();\n }\n});\n\nconst handleMouseDown = (e) => {\n if (!isLineToolActive && !isSelectionToolActive) return;\n\n const { x, y } = getSVGCoordsFromMouse(e);\n\n if (isLineToolActive) {\n isDrawingLine = true;\n currentLine = new Line(\n { x, y },\n { x, y },\n {\n stroke: lineColor ?? getThemeStroke(),\n strokeWidth: lineStrokeWidth,\n roughness: lineSktetchRate,\n bowing: lineEdgeType,\n strokeDasharray: lineStrokeStyle === \"dashed\" ? \"5,5\" : (lineStrokeStyle === \"dotted\" ? \"2,12\" : \"\")\n }\n );\n currentLine.isBeingDrawn = true;\n shapes.push(currentLine);\n currentShape = currentLine;\n } else if (isSelectionToolActive) {\n let clickedOnShape = false;\n \n // Check if clicking on current selected line\n if (currentShape && currentShape.shapeName === 'line' && currentShape.isSelected) {\n const anchorInfo = currentShape.isNearAnchor(x, y);\n \n if (anchorInfo && anchorInfo.type === 'anchor') {\n clickedOnShape = true;\n // Start anchor drag\n dragOldPosLine = {\n startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },\n endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },\n controlPoint: currentShape.controlPoint ? { x: currentShape.controlPoint.x, y: currentShape.controlPoint.y } : null,\n isCurved: currentShape.isCurved,\n parentFrame: currentShape.parentFrame\n };\n \n const anchorIndex = anchorInfo.index;\n \n const onPointerMove = (event) => {\n const { x: newX, y: newY } = getSVGCoordsFromMouse(event);\n currentShape.updatePosition(anchorIndex, newX, newY);\n };\n \n const onPointerUp = () => {\n if (dragOldPosLine) {\n const newPos = {\n startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },\n endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },\n controlPoint: currentShape.controlPoint ? { x: currentShape.controlPoint.x, y: currentShape.controlPoint.y } : null,\n isCurved: currentShape.isCurved,\n parentFrame: currentShape.parentFrame\n };\n pushTransformAction(currentShape, dragOldPosLine, newPos);\n dragOldPosLine = null;\n }\n svg.removeEventListener('pointermove', onPointerMove);\n svg.removeEventListener('pointerup', onPointerUp);\n };\n \n svg.addEventListener('pointermove', onPointerMove);\n svg.addEventListener('pointerup', onPointerUp);\n \n // Prevent default to stop any other drag behavior\n e.preventDefault();\n e.stopPropagation();\n \n } else if (currentShape.contains(x, y)) {\n // Dragging the line itself (not anchors)\n isDraggingLine = true;\n dragOldPosLine = {\n startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },\n endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },\n controlPoint: currentShape.controlPoint ? { x: currentShape.controlPoint.x, y: currentShape.controlPoint.y } : null,\n isCurved: currentShape.isCurved,\n parentFrame: currentShape.parentFrame\n };\n \n // Store initial frame state\n draggedShapeInitialFrameLine = currentShape.parentFrame || null;\n \n // Temporarily remove from frame clipping if dragging\n if (currentShape.parentFrame) {\n currentShape.parentFrame.temporarilyRemoveFromFrame(currentShape);\n }\n \n startX = x;\n startY = y;\n clickedOnShape = true;\n }\n }\n\n // If not clicking on selected shape, check for other shapes\n if (!clickedOnShape) {\n let shapeToSelect = null;\n for (let i = shapes.length - 1; i >= 0; i--) {\n const shape = shapes[i];\n if (shape instanceof Line && shape.contains(x, y)) {\n shapeToSelect = shape;\n break;\n }\n }\n\n if (currentShape && currentShape !== shapeToSelect) {\n currentShape.removeSelection();\n currentShape = null;\n }\n\n if (shapeToSelect) {\n currentShape = shapeToSelect;\n currentShape.selectLine();\n clickedOnShape = true;\n }\n }\n\n if (!clickedOnShape && currentShape) {\n currentShape.removeSelection();\n currentShape = null;\n }\n }\n};\n// Update clone function to remove rotation property\nfunction cloneLineData(line) {\n return {\n startPoint: { x: line.startPoint.x, y: line.startPoint.y },\n endPoint: { x: line.endPoint.x, y: line.endPoint.y },\n controlPoint: line.controlPoint ? { x: line.controlPoint.x, y: line.controlPoint.y } : null,\n isCurved: line.isCurved || false,\n parentFrame: line.parentFrame,\n options: cloneOptions(line.options)\n };\n}\n\nconst handleMouseMove = (e) => {\n const { x, y } = getSVGCoordsFromMouse(e);\n \n // Keep lastMousePos in screen coordinates for other functions\n const svgRect = svg.getBoundingClientRect();\n lastMousePos = {\n x: e.clientX - svgRect.left, \n y: e.clientY - svgRect.top\n };\n \n if (isDrawingLine && currentLine) {\n let endX = x, endY = y;\n if (e.shiftKey) {\n const dx = x - currentLine.startPoint.x;\n const dy = y - currentLine.startPoint.y;\n const angle = Math.atan2(dy, dx);\n const snapAngle = Math.round(angle / (Math.PI / 4)) * (Math.PI / 4);\n const dist = Math.sqrt(dx * dx + dy * dy);\n endX = currentLine.startPoint.x + dist * Math.cos(snapAngle);\n endY = currentLine.startPoint.y + dist * Math.sin(snapAngle);\n }\n currentLine.endPoint = { x: endX, y: endY };\n currentLine.draw();\n \n // Check for frame containment while drawing (but don't apply clipping yet)\n shapes.forEach(frame => {\n if (frame.shapeName === 'frame') {\n if (frame.isShapeInFrame(currentLine)) {\n frame.highlightFrame();\n hoveredFrameLine = frame;\n } else if (hoveredFrameLine === frame) {\n frame.removeHighlight();\n hoveredFrameLine = null;\n }\n }\n });\n } else if (isDraggingLine && currentShape && currentShape.isSelected) {\n const dx = x - startX;\n const dy = y - startY;\n currentShape.move(dx, dy);\n startX = x;\n startY = y;\n\n // Issue #24 bug #4: track containing frame during existing-line\n // drag so mouseUp re-parents from current geometry, not from a\n // stale hoveredFrameLine.\n let newHover = null;\n for (const f of shapes) {\n if (f.shapeName !== 'frame') continue;\n if (f === currentShape) continue;\n if (typeof f.isShapeInFrame === 'function' && f.isShapeInFrame(currentShape)) {\n newHover = f;\n break;\n }\n }\n if (hoveredFrameLine && hoveredFrameLine !== newHover && typeof hoveredFrameLine.removeHighlight === 'function') {\n hoveredFrameLine.removeHighlight();\n }\n if (newHover && newHover !== hoveredFrameLine && typeof newHover.highlightFrame === 'function') {\n newHover.highlightFrame();\n }\n hoveredFrameLine = newHover;\n\n // Snap guides\n if (window.__sketchStoreApi && window.__sketchStoreApi.getState().snapToObjects) {\n const snap = calculateSnap(currentShape, e.shiftKey, e.clientX, e.clientY);\n if (snap.dx || snap.dy) {\n currentShape.move(snap.dx, snap.dy);\n }\n } else {\n clearSnapGuides();\n }\n }\n};\n\nconst handleMouseUp = (e) => {\n if (isDrawingLine) {\n isDrawingLine = false;\n \n // Check if line is too small\n const dx = currentLine.endPoint.x - currentLine.startPoint.x;\n const dy = currentLine.endPoint.y - currentLine.startPoint.y;\n const lengthSq = dx * dx + dy * dy;\n \n if (lengthSq < (5 / currentZoom) ** 2) {\n shapes.pop();\n if (currentLine.group.parentNode) {\n currentLine.group.parentNode.removeChild(currentLine.group);\n }\n currentLine = null;\n currentShape = null;\n } else {\n // Finalize: apply roughness now that drawing is done\n currentLine.isBeingDrawn = false;\n currentLine.draw();\n\n // Push create action for undo/redo\n pushCreateAction(currentLine);\n\n // Check for frame containment and track attachment\n const finalFrame = hoveredFrameLine;\n if (finalFrame) {\n finalFrame.addShapeToFrame(currentLine);\n // Track the attachment for undo\n pushFrameAttachmentAction(finalFrame, currentLine, 'attach', null);\n }\n\n // Auto-select the drawn line and switch to selection tool\n const drawnLine = currentLine;\n if (window.__sketchStoreApi) window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });\n currentShape = drawnLine;\n drawnLine.selectLine();\n }\n \n // Clear frame highlighting\n if (hoveredFrameLine) {\n hoveredFrameLine.removeHighlight();\n hoveredFrameLine = null;\n }\n \n currentLine = null;\n }\n \n if (isDraggingLine && dragOldPosLine && currentShape) {\n // Issue #34 bug #2: use hoveredFrameLine (actual destination) instead\n // of the stale parentFrame \u2014 containment transfer hasn't happened yet.\n const newPos = {\n startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },\n endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },\n controlPoint: currentShape.controlPoint ? { x: currentShape.controlPoint.x, y: currentShape.controlPoint.y } : null,\n parentFrame: hoveredFrameLine || null,\n };\n const oldPos = {\n ...dragOldPosLine,\n parentFrame: draggedShapeInitialFrameLine\n };\n \n const stateChanged = dragOldPosLine.startPoint.x !== newPos.startPoint.x || \n dragOldPosLine.startPoint.y !== newPos.startPoint.y ||\n dragOldPosLine.endPoint.x !== newPos.endPoint.x || \n dragOldPosLine.endPoint.y !== newPos.endPoint.y;\n\n const frameChanged = oldPos.parentFrame !== newPos.parentFrame;\n \n if (stateChanged || frameChanged) {\n pushTransformAction(currentShape, oldPos, newPos);\n }\n \n // Handle frame containment changes after drag\n if (isDraggingLine) {\n const finalFrame = hoveredFrameLine;\n \n // If shape moved to a different frame\n if (draggedShapeInitialFrameLine !== finalFrame) {\n // Remove from initial frame\n if (draggedShapeInitialFrameLine) {\n draggedShapeInitialFrameLine.removeShapeFromFrame(currentShape);\n }\n \n // Add to new frame\n if (finalFrame) {\n finalFrame.addShapeToFrame(currentShape);\n }\n \n // Track the frame change for undo\n if (frameChanged) {\n pushFrameAttachmentAction(finalFrame || draggedShapeInitialFrameLine, currentShape, \n finalFrame ? 'attach' : 'detach', draggedShapeInitialFrameLine);\n }\n } else if (draggedShapeInitialFrameLine) {\n // Shape stayed in same frame, restore clipping\n draggedShapeInitialFrameLine.restoreToFrame(currentShape);\n }\n }\n \n dragOldPosLine = null;\n draggedShapeInitialFrameLine = null;\n }\n \n // Clear frame highlighting\n if (hoveredFrameLine) {\n hoveredFrameLine.removeHighlight();\n hoveredFrameLine = null;\n }\n \n clearSnapGuides();\n isDraggingLine = false;\n};\n\n// --- Event Handlers ---\n\n// --- Style Option Event Listeners ---\nlineColorOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n lineColorOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n \n if (currentShape instanceof Line && currentShape.isSelected) {\n const oldOptions = {...currentShape.options};\n currentShape.options.stroke = span.getAttribute(\"data-id\");\n currentShape.draw();\n pushOptionsChangeAction(currentShape, oldOptions);\n } else {\n lineColor = span.getAttribute(\"data-id\");\n }\n });\n});\n\nlineThicknessOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n lineThicknessOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n \n if (currentShape instanceof Line && currentShape.isSelected) {\n const oldOptions = {...currentShape.options};\n currentShape.options.strokeWidth = parseInt(span.getAttribute(\"data-id\"));\n currentShape.draw();\n pushOptionsChangeAction(currentShape, oldOptions);\n } else {\n lineStrokeWidth = parseInt(span.getAttribute(\"data-id\"));\n }\n });\n});\n\nlineOutlineOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n lineOutlineOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n \n if (currentShape instanceof Line && currentShape.isSelected) {\n const oldOptions = {...currentShape.options};\n const style = span.getAttribute(\"data-id\");\n currentShape.options.strokeDasharray = \n style === \"dashed\" ? \"5,5\" : \n (style === \"dotted\" ? \"2,12\" : \"\");\n currentShape.draw();\n pushOptionsChangeAction(currentShape, oldOptions);\n } else {\n lineStrokeStyle = span.getAttribute(\"data-id\");\n }\n });\n});\n\nlineSlopeOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n lineSlopeOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n \n if (currentShape instanceof Line && currentShape.isSelected) {\n const oldOptions = {...currentShape.options};\n currentShape.options.roughness = parseFloat(span.getAttribute(\"data-id\"));\n currentShape.draw();\n pushOptionsChangeAction(currentShape, oldOptions);\n } else {\n lineSktetchRate = parseFloat(span.getAttribute(\"data-id\"));\n }\n });\n});\n\nlineEdgeOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n lineEdgeOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n \n if (currentShape instanceof Line && currentShape.isSelected) {\n const oldOptions = {...currentShape.options};\n currentShape.options.bowing = parseFloat(span.getAttribute(\"data-id\"));\n currentShape.draw();\n pushOptionsChangeAction(currentShape, oldOptions);\n } else {\n lineEdgeType = parseFloat(span.getAttribute(\"data-id\"));\n }\n });\n});\n\n// Add copy/paste functionality\nfunction cloneOptions(options) {\n return JSON.parse(JSON.stringify(options));\n}\n\nwindow.Line = Line;\n\n// Bridge line tool settings to React sidebar\nwindow.lineToolSettings = {\n get strokeColor() { return lineColor; },\n set strokeColor(v) { lineColor = v; },\n get strokeWidth() { return lineStrokeWidth; },\n set strokeWidth(v) { lineStrokeWidth = v; },\n get strokeStyle() { return lineStrokeStyle; },\n set strokeStyle(v) { lineStrokeStyle = v; },\n get sloppiness() { return lineSktetchRate; },\n set sloppiness(v) { lineSktetchRate = v; },\n get edge() { return lineEdgeType; },\n set edge(v) { lineEdgeType = v; },\n};\nwindow.updateSelectedLineStyle = function(changes) {\n if (currentShape instanceof Line && currentShape.isSelected) {\n const oldOptions = {...currentShape.options};\n if (changes.stroke !== undefined) { lineColor = changes.stroke; currentShape.options.stroke = changes.stroke; }\n if (changes.strokeWidth !== undefined) { lineStrokeWidth = changes.strokeWidth; currentShape.options.strokeWidth = changes.strokeWidth; }\n if (changes.strokeStyle !== undefined) {\n lineStrokeStyle = changes.strokeStyle;\n currentShape.options.strokeDasharray = changes.strokeStyle === \"dashed\" ? \"5,5\" : (changes.strokeStyle === \"dotted\" ? \"2,12\" : \"\");\n }\n if (changes.sloppiness !== undefined) { lineSktetchRate = changes.sloppiness; currentShape.options.roughness = changes.sloppiness; }\n if (changes.edge !== undefined) { lineEdgeType = changes.edge; currentShape.options.bowing = changes.edge; }\n currentShape.draw();\n pushOptionsChangeAction(currentShape, oldOptions);\n } else {\n if (changes.stroke !== undefined) lineColor = changes.stroke;\n if (changes.strokeWidth !== undefined) lineStrokeWidth = changes.strokeWidth;\n if (changes.strokeStyle !== undefined) lineStrokeStyle = changes.strokeStyle;\n if (changes.sloppiness !== undefined) lineSktetchRate = changes.sloppiness;\n if (changes.edge !== undefined) lineEdgeType = changes.edge;\n }\n};\n\nexport {\n handleMouseDown as handleMouseDownLine,\n handleMouseMove as handleMouseMoveLine,\n handleMouseUp as handleMouseUpLine,\n};\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  cleanupAttachments,
12
12
  updateAttachedArrows
13
- } from "./chunk-X5ENBMGL.js";
13
+ } from "./chunk-KXLNEFN5.js";
14
14
  import {
15
15
  pushCreateAction,
16
16
  pushDeleteAction,
@@ -1038,4 +1038,4 @@ export {
1038
1038
  handleMouseDownImage,
1039
1039
  handleMouseUpImage
1040
1040
  };
1041
- //# sourceMappingURL=chunk-37PF7FG2.js.map
1041
+ //# sourceMappingURL=chunk-KACRJ6AJ.js.map
@@ -230,7 +230,7 @@ function clearSnapGuides() {
230
230
  // src/tools/arrowTool.js
231
231
  function getThemeStroke() {
232
232
  if (typeof document === "undefined") return "#fff";
233
- return document.body && document.body.classList.contains("theme-dark") ? "#fff" : "#1a1a2e";
233
+ return document.body && document.body.classList.contains("theme-dark") ? "#fff" : "#000000";
234
234
  }
235
235
  var currentArrow = null;
236
236
  var isResizing = false;
@@ -744,4 +744,4 @@ export {
744
744
  updateAttachedArrows,
745
745
  cleanupAttachments
746
746
  };
747
- //# sourceMappingURL=chunk-X5ENBMGL.js.map
747
+ //# sourceMappingURL=chunk-KXLNEFN5.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/core/SnapGuides.js", "../../src/tools/arrowTool.js"],
4
- "sourcesContent": ["/**\n * SnapGuides - Shows thin red alignment guides when moving shapes\n * to help users align shapes with each other and the viewport.\n */\n\nconst SNAP_THRESHOLD = 6; // pixels \u2014 how close before snapping\nconst BREAK_THRESHOLD = 12; // pixels \u2014 how far mouse must move to break free\nconst GUIDE_COLOR = '#ff4444';\nconst GUIDE_WIDTH = 1;\n\nlet guideLayer = null;\n\n// Track active snaps so we can implement break-out\nlet activeSnapX = null; // { guideValue, mouseAtSnap }\nlet activeSnapY = null;\n\nfunction ensureGuideLayer() {\n if (guideLayer && guideLayer.parentNode) return guideLayer;\n const svg = window.svg;\n if (!svg) return null;\n\n guideLayer = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n guideLayer.setAttribute('id', 'snap-guides');\n guideLayer.setAttribute('pointer-events', 'none');\n svg.appendChild(guideLayer);\n return guideLayer;\n}\n\nfunction clearGuides() {\n if (guideLayer) {\n while (guideLayer.firstChild) guideLayer.removeChild(guideLayer.firstChild);\n }\n}\n\nfunction drawGuide(x1, y1, x2, y2) {\n const layer = ensureGuideLayer();\n if (!layer) return;\n\n const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n line.setAttribute('x1', x1);\n line.setAttribute('y1', y1);\n line.setAttribute('x2', x2);\n line.setAttribute('y2', y2);\n line.setAttribute('stroke', GUIDE_COLOR);\n line.setAttribute('stroke-width', GUIDE_WIDTH);\n line.setAttribute('stroke-dasharray', '4 2');\n layer.appendChild(line);\n}\n\n/**\n * Get the bounding box of a shape in canvas coordinates\n */\nfunction getShapeBounds(shape) {\n if (!shape) return null;\n\n const name = shape.shapeName;\n if (name === 'rectangle' || name === 'frame') {\n return {\n left: shape.x,\n top: shape.y,\n right: shape.x + shape.width,\n bottom: shape.y + shape.height,\n cx: shape.x + shape.width / 2,\n cy: shape.y + shape.height / 2,\n };\n }\n if (name === 'circle') {\n return {\n left: shape.x - shape.rx,\n top: shape.y - shape.ry,\n right: shape.x + shape.rx,\n bottom: shape.y + shape.ry,\n cx: shape.x,\n cy: shape.y,\n };\n }\n if (name === 'text' || name === 'code' || name === 'image' || name === 'icon') {\n const el = shape.group || shape.element;\n if (!el) return null;\n const bbox = el.getBBox();\n return {\n left: bbox.x,\n top: bbox.y,\n right: bbox.x + bbox.width,\n bottom: bbox.y + bbox.height,\n cx: bbox.x + bbox.width / 2,\n cy: bbox.y + bbox.height / 2,\n };\n }\n if (name === 'line' || name === 'arrow') {\n const sx = shape.startPoint?.x ?? 0;\n const sy = shape.startPoint?.y ?? 0;\n const ex = shape.endPoint?.x ?? 0;\n const ey = shape.endPoint?.y ?? 0;\n return {\n left: Math.min(sx, ex),\n top: Math.min(sy, ey),\n right: Math.max(sx, ex),\n bottom: Math.max(sy, ey),\n cx: (sx + ex) / 2,\n cy: (sy + ey) / 2,\n };\n }\n return null;\n}\n\n/**\n * Get the canvas viewport reference points for global alignment.\n */\nfunction getCanvasGuides() {\n const vb = window.currentViewBox;\n if (!vb) return [];\n\n return [\n { // Viewport center\n left: vb.x + vb.width / 2,\n top: vb.y + vb.height / 2,\n right: vb.x + vb.width / 2,\n bottom: vb.y + vb.height / 2,\n cx: vb.x + vb.width / 2,\n cy: vb.y + vb.height / 2,\n },\n { // Viewport edges\n left: vb.x,\n top: vb.y,\n right: vb.x + vb.width,\n bottom: vb.y + vb.height,\n cx: vb.x + vb.width / 2,\n cy: vb.y + vb.height / 2,\n },\n ];\n}\n\n/**\n * Calculate snap offsets and draw guides.\n * Returns { dx, dy } snap offset to apply.\n *\n * Uses a break-out system: once snapped, the shape stays on the guide\n * until the mouse moves BREAK_THRESHOLD away, then it breaks free.\n */\nexport function calculateSnap(movingShape, shiftKey = false, mouseX, mouseY) {\n clearGuides();\n\n const shapes = window.shapes;\n if (!shapes || !movingShape) return { dx: 0, dy: 0 };\n\n const moving = getShapeBounds(movingShape);\n if (!moving) return { dx: 0, dy: 0 };\n\n // Check if we should break out of an active snap\n if (activeSnapX && mouseX !== undefined) {\n if (Math.abs(mouseX - activeSnapX.mouseAtSnap) > BREAK_THRESHOLD) {\n activeSnapX = null;\n }\n }\n if (activeSnapY && mouseY !== undefined) {\n if (Math.abs(mouseY - activeSnapY.mouseAtSnap) > BREAK_THRESHOLD) {\n activeSnapY = null;\n }\n }\n\n let snapX = null;\n let snapY = null;\n let bestDistX = SNAP_THRESHOLD;\n let bestDistY = SNAP_THRESHOLD;\n\n const movingXs = [moving.left, moving.cx, moving.right];\n const movingYs = [moving.top, moving.cy, moving.bottom];\n\n const vb = window.currentViewBox;\n const extendY1 = vb ? vb.y : 0;\n const extendY2 = vb ? vb.y + vb.height : 10000;\n const extendX1 = vb ? vb.x : 0;\n const extendX2 = vb ? vb.x + vb.width : 10000;\n\n let otherShapeCount = 0;\n\n for (const shape of shapes) {\n if (shape === movingShape) continue;\n if (window.multiSelection && window.multiSelection.selectedShapes?.has(shape)) continue;\n\n const other = getShapeBounds(shape);\n if (!other) continue;\n otherShapeCount++;\n\n const otherXs = [other.left, other.cx, other.right];\n const otherYs = [other.top, other.cy, other.bottom];\n\n for (const mx of movingXs) {\n for (const ox of otherXs) {\n const dist = Math.abs(mx - ox);\n if (dist < bestDistX) {\n bestDistX = dist;\n snapX = { offset: ox - mx, x: ox, extendY1, extendY2 };\n }\n }\n }\n\n for (const my of movingYs) {\n for (const oy of otherYs) {\n const dist = Math.abs(my - oy);\n if (dist < bestDistY) {\n bestDistY = dist;\n snapY = { offset: oy - my, y: oy, extendX1, extendX2 };\n }\n }\n }\n }\n\n // Viewport guides when alone, no snap found, or shift held\n if (shiftKey || otherShapeCount === 0 || (!snapX && !snapY)) {\n const canvasGuides = getCanvasGuides();\n for (const guide of canvasGuides) {\n const guideXs = [guide.left, guide.cx, guide.right];\n const guideYs = [guide.top, guide.cy, guide.bottom];\n\n for (const mx of movingXs) {\n for (const gx of guideXs) {\n const dist = Math.abs(mx - gx);\n if (dist < bestDistX) {\n bestDistX = dist;\n snapX = { offset: gx - mx, x: gx, extendY1, extendY2 };\n }\n }\n }\n for (const my of movingYs) {\n for (const gy of guideYs) {\n const dist = Math.abs(my - gy);\n if (dist < bestDistY) {\n bestDistY = dist;\n snapY = { offset: gy - my, y: gy, extendX1, extendX2 };\n }\n }\n }\n }\n }\n\n let dx = 0;\n let dy = 0;\n\n // Apply X snap only if not broken out of a previous X snap\n if (snapX && !activeSnapX) {\n dx = snapX.offset;\n drawGuide(snapX.x, snapX.extendY1, snapX.x, snapX.extendY2);\n if (mouseX !== undefined) {\n activeSnapX = { guideValue: snapX.x, mouseAtSnap: mouseX };\n }\n } else if (activeSnapX) {\n // Still in an active snap \u2014 hold position by drawing guide but no offset\n drawGuide(activeSnapX.guideValue, extendY1, activeSnapX.guideValue, extendY2);\n }\n\n if (snapY && !activeSnapY) {\n dy = snapY.offset;\n drawGuide(snapY.extendX1, snapY.y, snapY.extendX2, snapY.y);\n if (mouseY !== undefined) {\n activeSnapY = { guideValue: snapY.y, mouseAtSnap: mouseY };\n }\n } else if (activeSnapY) {\n drawGuide(extendX1, activeSnapY.guideValue, extendX2, activeSnapY.guideValue);\n }\n\n return { dx, dy };\n}\n\n/**\n * Clear all snap guides and reset snap state. Call on mouseUp.\n */\nexport function clearSnapGuides() {\n clearGuides();\n activeSnapX = null;\n activeSnapY = null;\n}\n", "/* eslint-disable */\n// Arrow tool event handlers - extracted from drawArrow.js\nimport { pushCreateAction, pushDeleteAction, pushOptionsChangeAction, pushTransformAction, pushFrameAttachmentAction } from '../core/UndoRedo.js';\nimport { calculateSnap, clearSnapGuides } from '../core/SnapGuides.js';\n\n\nfunction getThemeStroke() { if (typeof document === \"undefined\") return \"#fff\"; return document.body && document.body.classList.contains(\"theme-dark\") ? \"#fff\" : \"#1a1a2e\"; }\n\nlet arrowStartX, arrowStartY;\nlet currentArrow = null;\nlet isResizing = false;\nlet isDragging = false;\nlet activeAnchor = null;\nlet isDrawingArrow = false;\nlet arrowStrokeColor = null;\nlet arrowStrokeThickness = 2;\nlet arrowOutlineStyle = \"solid\";\nlet arrowCurved = \"straight\";\nlet arrowCurveAmount = 20;\nlet arrowHeadLength = 10;\nlet arrowHeadAngleDeg = 30;\nlet arrowHeadStyle = \"default\";\nlet startX, startY;\nlet dragOldPosArrow = null;\nlet draggedShapeInitialFrameArrow = null;\nlet hoveredFrameArrow = null;\nlet arrowStrokeColorOptions = document.querySelectorAll(\".arrowStrokeSpan\");\nlet arrowStrokeThicknessValue = document.querySelectorAll(\".arrowStrokeThickSpan\");\nlet arrowOutlineStyleValue = document.querySelectorAll(\".arrowOutlineStyle\");\nlet arrowTypeStyleValue = document.querySelectorAll(\".arrowTypeStyle\");\nlet arrowHeadStyleValue = document.querySelectorAll(\".arrowHeadStyleSpan\");\nlet arrowCurveAmountOptions = document.querySelectorAll(\".arrowCurveSpan\");\n\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\nfunction deleteCurrentShape() {\n if (currentShape && currentShape.shapeName === 'arrow') {\n const idx = shapes.indexOf(currentShape);\n if (idx !== -1) shapes.splice(idx, 1);\n if (currentShape.group.parentNode) {\n currentShape.group.parentNode.removeChild(currentShape.group);\n }\n pushDeleteAction(currentShape);\n currentShape = null;\n disableAllSideBars();\n }\n}\n\ndocument.addEventListener('keydown', (e) => {\n if (e.key === 'Delete' && currentShape && currentShape.shapeName === 'arrow') {\n deleteCurrentShape();\n }\n});\n\n\nconst handleMouseDown = (e) => {\n if (!isArrowToolActive && !isSelectionToolActive) return;\n\n const { x, y } = getSVGCoordsFromMouse(e);\n\n if (isArrowToolActive) {\n isDrawingArrow = true;\n currentArrow = new Arrow({ x, y }, { x, y }, {\n stroke: arrowStrokeColor ?? getThemeStroke(),\n strokeWidth: arrowStrokeThickness,\n arrowOutlineStyle: arrowOutlineStyle,\n arrowHeadStyle: arrowHeadStyle,\n arrowCurved: arrowCurved,\n arrowCurveAmount: arrowCurveAmount\n });\n shapes.push(currentArrow);\n currentShape = currentArrow;\n } else if (isSelectionToolActive) {\n let clickedOnShape = false;\n let clickedOnAnchor = false;\n\n if (currentShape && currentShape.shapeName === 'arrow' && currentShape.isSelected) {\n const anchorInfo = currentShape.isNearAnchor(x, y);\n if (anchorInfo && anchorInfo.type === 'anchor') {\n clickedOnAnchor = true;\n clickedOnShape = true;\n } \n if (currentShape.contains(x, y)) {\n isDragging = true;\n dragOldPosArrow = {\n startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },\n endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },\n controlPoint1: currentShape.controlPoint1 ? { x: currentShape.controlPoint1.x, y: currentShape.controlPoint1.y } : null,\n controlPoint2: currentShape.controlPoint2 ? { x: currentShape.controlPoint2.x, y: currentShape.controlPoint2.y } : null,\n parentFrame: currentShape.parentFrame // Add this line\n };\n \n // Store initial frame state\n draggedShapeInitialFrameArrow = currentShape.parentFrame || null;\n \n // Temporarily remove from frame clipping if dragging\n if (currentShape.parentFrame) {\n currentShape.parentFrame.temporarilyRemoveFromFrame(currentShape);\n }\n \n startX = x;\n startY = y;\n clickedOnShape = true;\n }\n }\n\n if (!clickedOnShape) {\n let shapeToSelect = null;\n\n for (let i = shapes.length - 1; i >= 0; i--) {\n const shape = shapes[i];\n if (shape instanceof Arrow && shape.contains(x, y)) {\n shapeToSelect = shape;\n break;\n }\n }\n\n if (currentShape && currentShape !== shapeToSelect) {\n currentShape.removeSelection();\n currentShape = null;\n }\n\n if (shapeToSelect) {\n currentShape = shapeToSelect;\n currentShape.selectArrow();\n\n const anchorInfo = currentShape.isNearAnchor(x, y);\n if (anchorInfo && anchorInfo.type === 'anchor') {\n clickedOnAnchor = true;\n } else {\n isDragging = true;\n dragOldPosArrow = {\n startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },\n endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },\n controlPoint1: currentShape.controlPoint1 ? { x: currentShape.controlPoint1.x, y: currentShape.controlPoint1.y } : null,\n controlPoint2: currentShape.controlPoint2 ? { x: currentShape.controlPoint2.x, y: currentShape.controlPoint2.y } : null\n };\n startX = x;\n startY = y;\n }\n clickedOnShape = true;\n }\n }\n\n if (!clickedOnShape && !clickedOnAnchor && currentShape) {\n currentShape.removeSelection();\n currentShape = null;\n }\n }\n};\n\n// Enhanced mouse move with better cursor feedback\nconst handleMouseMove = (e) => {\n const { x, y } = getSVGCoordsFromMouse(e);\n\n if (isDrawingArrow && currentArrow) {\n let endX = x, endY = y;\n if (e.shiftKey) {\n const dx = x - currentArrow.startPoint.x;\n const dy = y - currentArrow.startPoint.y;\n const angle = Math.atan2(dy, dx);\n const snapAngle = Math.round(angle / (Math.PI / 4)) * (Math.PI / 4);\n const dist = Math.sqrt(dx * dx + dy * dy);\n endX = currentArrow.startPoint.x + dist * Math.cos(snapAngle);\n endY = currentArrow.startPoint.y + dist * Math.sin(snapAngle);\n }\n currentArrow.endPoint = { x: endX, y: endY };\n\n // Check for potential attachment and show preview\n const nearbyShape = Arrow.findNearbyShape({ x: endX, y: endY });\n if (nearbyShape) {\n // Snap to attachment point\n currentArrow.endPoint = nearbyShape.attachment.point;\n svg.style.cursor = 'crosshair';\n\n const existingPreview = svg.querySelector('.attachment-preview');\n if (existingPreview) existingPreview.remove();\n\n const preview = document.createElementNS(\"http://www.w3.org/2000/svg\", \"circle\");\n preview.setAttribute(\"cx\", nearbyShape.attachment.point.x);\n preview.setAttribute(\"cy\", nearbyShape.attachment.point.y);\n preview.setAttribute(\"r\", 6);\n preview.setAttribute(\"fill\", \"none\");\n preview.setAttribute(\"stroke\", \"#5B57D1\");\n preview.setAttribute(\"stroke-width\", 2);\n preview.setAttribute(\"class\", \"attachment-preview\");\n preview.setAttribute(\"opacity\", \"0.7\");\n svg.appendChild(preview);\n } else {\n // Remove preview if no nearby shape\n const existingPreview = svg.querySelector('.attachment-preview');\n if (existingPreview) existingPreview.remove();\n }\n\n // Check for frame containment while drawing (but don't apply clipping yet)\n shapes.forEach(frame => {\n if (frame.shapeName === 'frame') {\n if (frame.isShapeInFrame(currentArrow)) {\n frame.highlightFrame();\n hoveredFrameArrow = frame;\n } else if (hoveredFrameArrow === frame) {\n frame.removeHighlight();\n hoveredFrameArrow = null;\n }\n }\n });\n\n // Update control points for curved arrows during drawing\n if (currentArrow.arrowCurved) {\n currentArrow.initializeCurveControlPoints();\n }\n currentArrow.draw();\n }\n\n else if (isDragging && currentShape && currentShape.isSelected) {\n const dx = x - startX;\n const dy = y - startY;\n currentShape.move(dx, dy);\n startX = x;\n startY = y;\n\n // Issue #24 bug #4: track containing frame during drag of an\n // existing arrow so mouseUp re-parents correctly. Without this\n // hoveredFrameArrow stays null and the arrow is detached the\n // moment the user nudges it inside its own parent frame.\n let newHover = null;\n for (const f of shapes) {\n if (f.shapeName !== 'frame') continue;\n if (f === currentShape) continue;\n if (typeof f.isShapeInFrame === 'function' && f.isShapeInFrame(currentShape)) {\n newHover = f;\n break;\n }\n }\n if (hoveredFrameArrow && hoveredFrameArrow !== newHover && typeof hoveredFrameArrow.removeHighlight === 'function') {\n hoveredFrameArrow.removeHighlight();\n }\n if (newHover && newHover !== hoveredFrameArrow && typeof newHover.highlightFrame === 'function') {\n newHover.highlightFrame();\n }\n hoveredFrameArrow = newHover;\n\n // Snap guides\n if (window.__sketchStoreApi && window.__sketchStoreApi.getState().snapToObjects) {\n const snap = calculateSnap(currentShape, e.shiftKey, e.clientX, e.clientY);\n if (snap.dx || snap.dy) {\n currentShape.move(snap.dx, snap.dy);\n }\n } else {\n clearSnapGuides();\n }\n\n svg.style.cursor = 'grabbing';\n } else if (isSelectionToolActive && currentShape && currentShape.isSelected) {\n // Provide visual feedback when hovering over anchors or the arrow\n const anchorInfo = currentShape.isNearAnchor(x, y);\n if (anchorInfo) {\n svg.style.cursor = 'grab';\n } else if (currentShape.contains(x, y)) {\n svg.style.cursor = 'move';\n } else {\n svg.style.cursor = 'default';\n }\n } else if (isSelectionToolActive) {\n // Check if hovering over any selectable arrow\n let hoveringOverArrow = false;\n for (let i = shapes.length - 1; i >= 0; i--) {\n const shape = shapes[i];\n if (shape instanceof Arrow && shape.contains(x, y)) {\n hoveringOverArrow = true;\n break;\n }\n }\n svg.style.cursor = hoveringOverArrow ? 'pointer' : 'default';\n }\n};\n\nconst handleMouseUp = (e) => {\nif (isDrawingArrow && currentArrow) {\n // Remove any attachment preview that might still be visible\n const existingPreview = svg.querySelector('.attachment-preview');\n if (existingPreview) existingPreview.remove();\n\n // Check if arrow is too small\n const dx = currentArrow.endPoint.x - currentArrow.startPoint.x;\n const dy = currentArrow.endPoint.y - currentArrow.startPoint.y;\n const lengthSq = dx * dx + dy * dy;\n\n if (lengthSq < (5 / currentZoom) ** 2) {\n shapes.pop();\n if (currentArrow.group.parentNode) {\n currentArrow.group.parentNode.removeChild(currentArrow.group);\n }\n currentArrow = null;\n currentShape = null;\n } else {\n const startAttachment = Arrow.findNearbyShape(currentArrow.startPoint);\n const endAttachment = Arrow.findNearbyShape(currentArrow.endPoint);\n\n if (startAttachment) {\n currentArrow.attachToShape(true, startAttachment.shape, startAttachment.attachment);\n }\n\n if (endAttachment) {\n currentArrow.attachToShape(false, endAttachment.shape, endAttachment.attachment);\n }\n\n // Check for frame containment and track attachment\n const finalFrame = hoveredFrameArrow;\n if (finalFrame) {\n finalFrame.addShapeToFrame(currentArrow);\n // Track the attachment for undo\n pushFrameAttachmentAction(finalFrame, currentArrow, 'attach', null);\n }\n\n // Push create action for undo/redo\n pushCreateAction(currentArrow);\n\n // Auto-select the drawn arrow and switch to selection tool\n const drawnArrow = currentArrow;\n if (window.__sketchStoreApi) window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });\n currentShape = drawnArrow;\n drawnArrow.selectArrow();\n }\n\n // Clear frame highlighting\n if (hoveredFrameArrow) {\n hoveredFrameArrow.removeHighlight();\n hoveredFrameArrow = null;\n }\n\n currentArrow = null;\n}\n\nif (isDragging && dragOldPosArrow && currentShape) {\n // Issue #34 bug #2: containment transfer happens later in this block,\n // so currentShape.parentFrame is still the OLD frame here. hoveredFrameArrow\n // tracks the actual destination during mousemove \u2014 use that as the truth.\n const newPos = {\n startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },\n endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },\n parentFrame: hoveredFrameArrow || null,\n };\n const oldPos = {\n ...dragOldPosArrow,\n parentFrame: draggedShapeInitialFrameArrow // Add this line\n };\n \n const stateChanged = dragOldPosArrow.startPoint.x !== newPos.startPoint.x ||\n dragOldPosArrow.startPoint.y !== newPos.startPoint.y ||\n dragOldPosArrow.endPoint.x !== newPos.endPoint.x ||\n dragOldPosArrow.endPoint.y !== newPos.endPoint.y;\n \n const frameChanged = oldPos.parentFrame !== newPos.parentFrame;\n\n if (stateChanged || frameChanged) {\n pushTransformAction(currentShape, oldPos, newPos);\n }\n \n // Handle frame containment changes after drag\n if (isDragging) {\n const finalFrame = hoveredFrameArrow;\n \n // If shape moved to a different frame\n if (draggedShapeInitialFrameArrow !== finalFrame) {\n // Remove from initial frame\n if (draggedShapeInitialFrameArrow) {\n draggedShapeInitialFrameArrow.removeShapeFromFrame(currentShape);\n }\n \n // Add to new frame\n if (finalFrame) {\n finalFrame.addShapeToFrame(currentShape);\n }\n \n // Track the frame change for undo\n if (frameChanged) {\n pushFrameAttachmentAction(finalFrame || draggedShapeInitialFrameArrow, currentShape, \n finalFrame ? 'attach' : 'detach', draggedShapeInitialFrameArrow);\n }\n } else if (draggedShapeInitialFrameArrow) {\n // Shape stayed in same frame, restore clipping\n draggedShapeInitialFrameArrow.restoreToFrame(currentShape);\n }\n }\n \n draggedShapeInitialFrameArrow = null;\n dragOldPosArrow = null;\n}\n\n// Clear frame highlighting\nif (hoveredFrameArrow) {\n hoveredFrameArrow.removeHighlight();\n hoveredFrameArrow = null;\n}\n\nclearSnapGuides();\nisDrawingArrow = false;\nisResizing = false;\nisDragging = false;\nactiveAnchor = null;\nsvg.style.cursor = 'default';\n};\n\n// Remove old event listeners and add new ones\nsvg.removeEventListener('pointerdown', handleMouseDown);\nsvg.removeEventListener('pointermove', handleMouseMove);\nsvg.removeEventListener('pointerup', handleMouseUp);\n\n\n// Updated style handlers with undo/redo support\nconst updateSelectedArrowStyle = (styleChanges) => {\n if (currentShape instanceof Arrow && currentShape.isSelected) {\n const oldOptions = {\n ...currentShape.options,\n arrowOutlineStyle: currentShape.arrowOutlineStyle,\n arrowHeadStyle: currentShape.arrowHeadStyle,\n arrowCurved: currentShape.arrowCurved,\n arrowCurveAmount: currentShape.arrowCurveAmount\n };\n currentShape.updateStyle(styleChanges);\n pushOptionsChangeAction(currentShape, oldOptions);\n } else {\n if (styleChanges.stroke !== undefined) arrowStrokeColor = styleChanges.stroke;\n if (styleChanges.strokeWidth !== undefined) arrowStrokeThickness = styleChanges.strokeWidth;\n if (styleChanges.arrowOutlineStyle !== undefined) arrowOutlineStyle = styleChanges.arrowOutlineStyle;\n if (styleChanges.arrowHeadStyle !== undefined) arrowHeadStyle = styleChanges.arrowHeadStyle;\n if (styleChanges.arrowCurved !== undefined) arrowCurved = styleChanges.arrowCurved;\n if (styleChanges.arrowCurveAmount !== undefined) arrowCurveAmount = styleChanges.arrowCurveAmount;\n }\n};\n\narrowStrokeColorOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n arrowStrokeColorOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n const newColor = span.getAttribute(\"data-id\");\n updateSelectedArrowStyle({ stroke: newColor });\n });\n});\n\narrowStrokeThicknessValue.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n arrowStrokeThicknessValue.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n const newThickness = parseInt(span.getAttribute(\"data-id\"));\n updateSelectedArrowStyle({ strokeWidth: newThickness });\n });\n});\n\narrowOutlineStyleValue.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n arrowOutlineStyleValue.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n const newStyle = span.getAttribute(\"data-id\");\n updateSelectedArrowStyle({ arrowOutlineStyle: newStyle });\n });\n});\n\narrowTypeStyleValue.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n arrowTypeStyleValue.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n updateSelectedArrowStyle({ arrowCurved: span.getAttribute(\"data-id\") });\n });\n});\n\narrowCurveAmountOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n arrowCurveAmountOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n updateSelectedArrowStyle({ arrowCurveAmount: parseInt(span.getAttribute(\"data-id\")) });\n });\n});\n\narrowHeadStyleValue.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n arrowHeadStyleValue.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n const newHeadStyle = span.getAttribute(\"data-id\");\n updateSelectedArrowStyle({ arrowHeadStyle: newHeadStyle });\n });\n});\n\nfunction detachSelectedArrow() {\n if (currentShape instanceof Arrow && currentShape.isSelected) {\n if (currentShape.attachedToStart || currentShape.attachedToEnd) {\n const oldState = {\n attachedToStart: currentShape.attachedToStart,\n attachedToEnd: currentShape.attachedToEnd,\n startPoint: { ...currentShape.startPoint },\n endPoint: { ...currentShape.endPoint }\n };\n\n currentShape.detachFromShape(true);\n currentShape.detachFromShape(false);\n currentShape.draw();\n\n // Add to undo/redo if needed\n }\n }\n}\n\nfunction updateAttachedArrows(shape) {\n if (!shape) return;\n\n // If a DOM element was passed (e.g. from text/code/image move), find the wrapper\n let targetShape = shape;\n if (shape.nodeType) {\n targetShape = shapes.find(s => s.group === shape || s.element === shape) || shape;\n }\n\n shapes.forEach(arrowShape => {\n if (arrowShape instanceof Arrow) {\n let needsUpdate = false;\n if (arrowShape.attachedToStart && arrowShape.attachedToStart.shape === targetShape) {\n needsUpdate = true;\n }\n if (arrowShape.attachedToEnd && arrowShape.attachedToEnd.shape === targetShape) {\n needsUpdate = true;\n }\n\n if (needsUpdate) {\n arrowShape.updateAttachments();\n }\n }\n });\n}\n\nfunction cleanupAttachments(deletedShape) {\n if (!deletedShape) return;\n\n // If a DOM element was passed, find the wrapper\n let targetShape = deletedShape;\n if (deletedShape.nodeType) {\n targetShape = shapes.find(s => s.group === deletedShape || s.element === deletedShape) || deletedShape;\n }\n\n shapes.forEach(shape => {\n if (shape instanceof Arrow) {\n let needsDraw = false;\n if (shape.attachedToStart && shape.attachedToStart.shape === targetShape) {\n shape.detachFromShape(true);\n needsDraw = true;\n }\n if (shape.attachedToEnd && shape.attachedToEnd.shape === targetShape) {\n shape.detachFromShape(false);\n needsDraw = true;\n }\n if (needsDraw) {\n shape.draw();\n }\n }\n });\n}\n\n// Add keyboard shortcut to detach arrows\ndocument.addEventListener('keydown', (e) => {\n if (e.key.toLowerCase() === 'd' && e.ctrlKey) {\n e.preventDefault();\n detachSelectedArrow();\n }\n});\n\n// Expose arrow tool settings on window for React sidebar bridge\nwindow.arrowToolSettings = {\n get strokeColor() { return arrowStrokeColor; },\n set strokeColor(v) { arrowStrokeColor = v; },\n get strokeWidth() { return arrowStrokeThickness; },\n set strokeWidth(v) { arrowStrokeThickness = v; },\n get outlineStyle() { return arrowOutlineStyle; },\n set outlineStyle(v) { arrowOutlineStyle = v; },\n get headStyle() { return arrowHeadStyle; },\n set headStyle(v) { arrowHeadStyle = v; },\n get arrowCurved() { return arrowCurved; },\n set arrowCurved(v) { arrowCurved = v; },\n get curveAmount() { return arrowCurveAmount; },\n set curveAmount(v) { arrowCurveAmount = v; },\n};\nwindow.updateSelectedArrowStyle = updateSelectedArrowStyle;\n\n// Export the cleanup function\n// Expose cleanupAttachments globally for centralized delete\nwindow.cleanupAttachments = cleanupAttachments;\n\nexport {\n handleMouseDown as handleMouseDownArrow,\n handleMouseMove as handleMouseMoveArrow,\n handleMouseUp as handleMouseUpArrow,\n cleanupAttachments,\n updateAttachedArrows\n};\n"],
4
+ "sourcesContent": ["/**\n * SnapGuides - Shows thin red alignment guides when moving shapes\n * to help users align shapes with each other and the viewport.\n */\n\nconst SNAP_THRESHOLD = 6; // pixels \u2014 how close before snapping\nconst BREAK_THRESHOLD = 12; // pixels \u2014 how far mouse must move to break free\nconst GUIDE_COLOR = '#ff4444';\nconst GUIDE_WIDTH = 1;\n\nlet guideLayer = null;\n\n// Track active snaps so we can implement break-out\nlet activeSnapX = null; // { guideValue, mouseAtSnap }\nlet activeSnapY = null;\n\nfunction ensureGuideLayer() {\n if (guideLayer && guideLayer.parentNode) return guideLayer;\n const svg = window.svg;\n if (!svg) return null;\n\n guideLayer = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n guideLayer.setAttribute('id', 'snap-guides');\n guideLayer.setAttribute('pointer-events', 'none');\n svg.appendChild(guideLayer);\n return guideLayer;\n}\n\nfunction clearGuides() {\n if (guideLayer) {\n while (guideLayer.firstChild) guideLayer.removeChild(guideLayer.firstChild);\n }\n}\n\nfunction drawGuide(x1, y1, x2, y2) {\n const layer = ensureGuideLayer();\n if (!layer) return;\n\n const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n line.setAttribute('x1', x1);\n line.setAttribute('y1', y1);\n line.setAttribute('x2', x2);\n line.setAttribute('y2', y2);\n line.setAttribute('stroke', GUIDE_COLOR);\n line.setAttribute('stroke-width', GUIDE_WIDTH);\n line.setAttribute('stroke-dasharray', '4 2');\n layer.appendChild(line);\n}\n\n/**\n * Get the bounding box of a shape in canvas coordinates\n */\nfunction getShapeBounds(shape) {\n if (!shape) return null;\n\n const name = shape.shapeName;\n if (name === 'rectangle' || name === 'frame') {\n return {\n left: shape.x,\n top: shape.y,\n right: shape.x + shape.width,\n bottom: shape.y + shape.height,\n cx: shape.x + shape.width / 2,\n cy: shape.y + shape.height / 2,\n };\n }\n if (name === 'circle') {\n return {\n left: shape.x - shape.rx,\n top: shape.y - shape.ry,\n right: shape.x + shape.rx,\n bottom: shape.y + shape.ry,\n cx: shape.x,\n cy: shape.y,\n };\n }\n if (name === 'text' || name === 'code' || name === 'image' || name === 'icon') {\n const el = shape.group || shape.element;\n if (!el) return null;\n const bbox = el.getBBox();\n return {\n left: bbox.x,\n top: bbox.y,\n right: bbox.x + bbox.width,\n bottom: bbox.y + bbox.height,\n cx: bbox.x + bbox.width / 2,\n cy: bbox.y + bbox.height / 2,\n };\n }\n if (name === 'line' || name === 'arrow') {\n const sx = shape.startPoint?.x ?? 0;\n const sy = shape.startPoint?.y ?? 0;\n const ex = shape.endPoint?.x ?? 0;\n const ey = shape.endPoint?.y ?? 0;\n return {\n left: Math.min(sx, ex),\n top: Math.min(sy, ey),\n right: Math.max(sx, ex),\n bottom: Math.max(sy, ey),\n cx: (sx + ex) / 2,\n cy: (sy + ey) / 2,\n };\n }\n return null;\n}\n\n/**\n * Get the canvas viewport reference points for global alignment.\n */\nfunction getCanvasGuides() {\n const vb = window.currentViewBox;\n if (!vb) return [];\n\n return [\n { // Viewport center\n left: vb.x + vb.width / 2,\n top: vb.y + vb.height / 2,\n right: vb.x + vb.width / 2,\n bottom: vb.y + vb.height / 2,\n cx: vb.x + vb.width / 2,\n cy: vb.y + vb.height / 2,\n },\n { // Viewport edges\n left: vb.x,\n top: vb.y,\n right: vb.x + vb.width,\n bottom: vb.y + vb.height,\n cx: vb.x + vb.width / 2,\n cy: vb.y + vb.height / 2,\n },\n ];\n}\n\n/**\n * Calculate snap offsets and draw guides.\n * Returns { dx, dy } snap offset to apply.\n *\n * Uses a break-out system: once snapped, the shape stays on the guide\n * until the mouse moves BREAK_THRESHOLD away, then it breaks free.\n */\nexport function calculateSnap(movingShape, shiftKey = false, mouseX, mouseY) {\n clearGuides();\n\n const shapes = window.shapes;\n if (!shapes || !movingShape) return { dx: 0, dy: 0 };\n\n const moving = getShapeBounds(movingShape);\n if (!moving) return { dx: 0, dy: 0 };\n\n // Check if we should break out of an active snap\n if (activeSnapX && mouseX !== undefined) {\n if (Math.abs(mouseX - activeSnapX.mouseAtSnap) > BREAK_THRESHOLD) {\n activeSnapX = null;\n }\n }\n if (activeSnapY && mouseY !== undefined) {\n if (Math.abs(mouseY - activeSnapY.mouseAtSnap) > BREAK_THRESHOLD) {\n activeSnapY = null;\n }\n }\n\n let snapX = null;\n let snapY = null;\n let bestDistX = SNAP_THRESHOLD;\n let bestDistY = SNAP_THRESHOLD;\n\n const movingXs = [moving.left, moving.cx, moving.right];\n const movingYs = [moving.top, moving.cy, moving.bottom];\n\n const vb = window.currentViewBox;\n const extendY1 = vb ? vb.y : 0;\n const extendY2 = vb ? vb.y + vb.height : 10000;\n const extendX1 = vb ? vb.x : 0;\n const extendX2 = vb ? vb.x + vb.width : 10000;\n\n let otherShapeCount = 0;\n\n for (const shape of shapes) {\n if (shape === movingShape) continue;\n if (window.multiSelection && window.multiSelection.selectedShapes?.has(shape)) continue;\n\n const other = getShapeBounds(shape);\n if (!other) continue;\n otherShapeCount++;\n\n const otherXs = [other.left, other.cx, other.right];\n const otherYs = [other.top, other.cy, other.bottom];\n\n for (const mx of movingXs) {\n for (const ox of otherXs) {\n const dist = Math.abs(mx - ox);\n if (dist < bestDistX) {\n bestDistX = dist;\n snapX = { offset: ox - mx, x: ox, extendY1, extendY2 };\n }\n }\n }\n\n for (const my of movingYs) {\n for (const oy of otherYs) {\n const dist = Math.abs(my - oy);\n if (dist < bestDistY) {\n bestDistY = dist;\n snapY = { offset: oy - my, y: oy, extendX1, extendX2 };\n }\n }\n }\n }\n\n // Viewport guides when alone, no snap found, or shift held\n if (shiftKey || otherShapeCount === 0 || (!snapX && !snapY)) {\n const canvasGuides = getCanvasGuides();\n for (const guide of canvasGuides) {\n const guideXs = [guide.left, guide.cx, guide.right];\n const guideYs = [guide.top, guide.cy, guide.bottom];\n\n for (const mx of movingXs) {\n for (const gx of guideXs) {\n const dist = Math.abs(mx - gx);\n if (dist < bestDistX) {\n bestDistX = dist;\n snapX = { offset: gx - mx, x: gx, extendY1, extendY2 };\n }\n }\n }\n for (const my of movingYs) {\n for (const gy of guideYs) {\n const dist = Math.abs(my - gy);\n if (dist < bestDistY) {\n bestDistY = dist;\n snapY = { offset: gy - my, y: gy, extendX1, extendX2 };\n }\n }\n }\n }\n }\n\n let dx = 0;\n let dy = 0;\n\n // Apply X snap only if not broken out of a previous X snap\n if (snapX && !activeSnapX) {\n dx = snapX.offset;\n drawGuide(snapX.x, snapX.extendY1, snapX.x, snapX.extendY2);\n if (mouseX !== undefined) {\n activeSnapX = { guideValue: snapX.x, mouseAtSnap: mouseX };\n }\n } else if (activeSnapX) {\n // Still in an active snap \u2014 hold position by drawing guide but no offset\n drawGuide(activeSnapX.guideValue, extendY1, activeSnapX.guideValue, extendY2);\n }\n\n if (snapY && !activeSnapY) {\n dy = snapY.offset;\n drawGuide(snapY.extendX1, snapY.y, snapY.extendX2, snapY.y);\n if (mouseY !== undefined) {\n activeSnapY = { guideValue: snapY.y, mouseAtSnap: mouseY };\n }\n } else if (activeSnapY) {\n drawGuide(extendX1, activeSnapY.guideValue, extendX2, activeSnapY.guideValue);\n }\n\n return { dx, dy };\n}\n\n/**\n * Clear all snap guides and reset snap state. Call on mouseUp.\n */\nexport function clearSnapGuides() {\n clearGuides();\n activeSnapX = null;\n activeSnapY = null;\n}\n", "/* eslint-disable */\n// Arrow tool event handlers - extracted from drawArrow.js\nimport { pushCreateAction, pushDeleteAction, pushOptionsChangeAction, pushTransformAction, pushFrameAttachmentAction } from '../core/UndoRedo.js';\nimport { calculateSnap, clearSnapGuides } from '../core/SnapGuides.js';\n\n\nfunction getThemeStroke() { if (typeof document === \"undefined\") return \"#fff\"; return document.body && document.body.classList.contains(\"theme-dark\") ? \"#fff\" : \"#000000\"; }\n\nlet arrowStartX, arrowStartY;\nlet currentArrow = null;\nlet isResizing = false;\nlet isDragging = false;\nlet activeAnchor = null;\nlet isDrawingArrow = false;\nlet arrowStrokeColor = null;\nlet arrowStrokeThickness = 2;\nlet arrowOutlineStyle = \"solid\";\nlet arrowCurved = \"straight\";\nlet arrowCurveAmount = 20;\nlet arrowHeadLength = 10;\nlet arrowHeadAngleDeg = 30;\nlet arrowHeadStyle = \"default\";\nlet startX, startY;\nlet dragOldPosArrow = null;\nlet draggedShapeInitialFrameArrow = null;\nlet hoveredFrameArrow = null;\nlet arrowStrokeColorOptions = document.querySelectorAll(\".arrowStrokeSpan\");\nlet arrowStrokeThicknessValue = document.querySelectorAll(\".arrowStrokeThickSpan\");\nlet arrowOutlineStyleValue = document.querySelectorAll(\".arrowOutlineStyle\");\nlet arrowTypeStyleValue = document.querySelectorAll(\".arrowTypeStyle\");\nlet arrowHeadStyleValue = document.querySelectorAll(\".arrowHeadStyleSpan\");\nlet arrowCurveAmountOptions = document.querySelectorAll(\".arrowCurveSpan\");\n\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\nfunction deleteCurrentShape() {\n if (currentShape && currentShape.shapeName === 'arrow') {\n const idx = shapes.indexOf(currentShape);\n if (idx !== -1) shapes.splice(idx, 1);\n if (currentShape.group.parentNode) {\n currentShape.group.parentNode.removeChild(currentShape.group);\n }\n pushDeleteAction(currentShape);\n currentShape = null;\n disableAllSideBars();\n }\n}\n\ndocument.addEventListener('keydown', (e) => {\n if (e.key === 'Delete' && currentShape && currentShape.shapeName === 'arrow') {\n deleteCurrentShape();\n }\n});\n\n\nconst handleMouseDown = (e) => {\n if (!isArrowToolActive && !isSelectionToolActive) return;\n\n const { x, y } = getSVGCoordsFromMouse(e);\n\n if (isArrowToolActive) {\n isDrawingArrow = true;\n currentArrow = new Arrow({ x, y }, { x, y }, {\n stroke: arrowStrokeColor ?? getThemeStroke(),\n strokeWidth: arrowStrokeThickness,\n arrowOutlineStyle: arrowOutlineStyle,\n arrowHeadStyle: arrowHeadStyle,\n arrowCurved: arrowCurved,\n arrowCurveAmount: arrowCurveAmount\n });\n shapes.push(currentArrow);\n currentShape = currentArrow;\n } else if (isSelectionToolActive) {\n let clickedOnShape = false;\n let clickedOnAnchor = false;\n\n if (currentShape && currentShape.shapeName === 'arrow' && currentShape.isSelected) {\n const anchorInfo = currentShape.isNearAnchor(x, y);\n if (anchorInfo && anchorInfo.type === 'anchor') {\n clickedOnAnchor = true;\n clickedOnShape = true;\n } \n if (currentShape.contains(x, y)) {\n isDragging = true;\n dragOldPosArrow = {\n startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },\n endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },\n controlPoint1: currentShape.controlPoint1 ? { x: currentShape.controlPoint1.x, y: currentShape.controlPoint1.y } : null,\n controlPoint2: currentShape.controlPoint2 ? { x: currentShape.controlPoint2.x, y: currentShape.controlPoint2.y } : null,\n parentFrame: currentShape.parentFrame // Add this line\n };\n \n // Store initial frame state\n draggedShapeInitialFrameArrow = currentShape.parentFrame || null;\n \n // Temporarily remove from frame clipping if dragging\n if (currentShape.parentFrame) {\n currentShape.parentFrame.temporarilyRemoveFromFrame(currentShape);\n }\n \n startX = x;\n startY = y;\n clickedOnShape = true;\n }\n }\n\n if (!clickedOnShape) {\n let shapeToSelect = null;\n\n for (let i = shapes.length - 1; i >= 0; i--) {\n const shape = shapes[i];\n if (shape instanceof Arrow && shape.contains(x, y)) {\n shapeToSelect = shape;\n break;\n }\n }\n\n if (currentShape && currentShape !== shapeToSelect) {\n currentShape.removeSelection();\n currentShape = null;\n }\n\n if (shapeToSelect) {\n currentShape = shapeToSelect;\n currentShape.selectArrow();\n\n const anchorInfo = currentShape.isNearAnchor(x, y);\n if (anchorInfo && anchorInfo.type === 'anchor') {\n clickedOnAnchor = true;\n } else {\n isDragging = true;\n dragOldPosArrow = {\n startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },\n endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },\n controlPoint1: currentShape.controlPoint1 ? { x: currentShape.controlPoint1.x, y: currentShape.controlPoint1.y } : null,\n controlPoint2: currentShape.controlPoint2 ? { x: currentShape.controlPoint2.x, y: currentShape.controlPoint2.y } : null\n };\n startX = x;\n startY = y;\n }\n clickedOnShape = true;\n }\n }\n\n if (!clickedOnShape && !clickedOnAnchor && currentShape) {\n currentShape.removeSelection();\n currentShape = null;\n }\n }\n};\n\n// Enhanced mouse move with better cursor feedback\nconst handleMouseMove = (e) => {\n const { x, y } = getSVGCoordsFromMouse(e);\n\n if (isDrawingArrow && currentArrow) {\n let endX = x, endY = y;\n if (e.shiftKey) {\n const dx = x - currentArrow.startPoint.x;\n const dy = y - currentArrow.startPoint.y;\n const angle = Math.atan2(dy, dx);\n const snapAngle = Math.round(angle / (Math.PI / 4)) * (Math.PI / 4);\n const dist = Math.sqrt(dx * dx + dy * dy);\n endX = currentArrow.startPoint.x + dist * Math.cos(snapAngle);\n endY = currentArrow.startPoint.y + dist * Math.sin(snapAngle);\n }\n currentArrow.endPoint = { x: endX, y: endY };\n\n // Check for potential attachment and show preview\n const nearbyShape = Arrow.findNearbyShape({ x: endX, y: endY });\n if (nearbyShape) {\n // Snap to attachment point\n currentArrow.endPoint = nearbyShape.attachment.point;\n svg.style.cursor = 'crosshair';\n\n const existingPreview = svg.querySelector('.attachment-preview');\n if (existingPreview) existingPreview.remove();\n\n const preview = document.createElementNS(\"http://www.w3.org/2000/svg\", \"circle\");\n preview.setAttribute(\"cx\", nearbyShape.attachment.point.x);\n preview.setAttribute(\"cy\", nearbyShape.attachment.point.y);\n preview.setAttribute(\"r\", 6);\n preview.setAttribute(\"fill\", \"none\");\n preview.setAttribute(\"stroke\", \"#5B57D1\");\n preview.setAttribute(\"stroke-width\", 2);\n preview.setAttribute(\"class\", \"attachment-preview\");\n preview.setAttribute(\"opacity\", \"0.7\");\n svg.appendChild(preview);\n } else {\n // Remove preview if no nearby shape\n const existingPreview = svg.querySelector('.attachment-preview');\n if (existingPreview) existingPreview.remove();\n }\n\n // Check for frame containment while drawing (but don't apply clipping yet)\n shapes.forEach(frame => {\n if (frame.shapeName === 'frame') {\n if (frame.isShapeInFrame(currentArrow)) {\n frame.highlightFrame();\n hoveredFrameArrow = frame;\n } else if (hoveredFrameArrow === frame) {\n frame.removeHighlight();\n hoveredFrameArrow = null;\n }\n }\n });\n\n // Update control points for curved arrows during drawing\n if (currentArrow.arrowCurved) {\n currentArrow.initializeCurveControlPoints();\n }\n currentArrow.draw();\n }\n\n else if (isDragging && currentShape && currentShape.isSelected) {\n const dx = x - startX;\n const dy = y - startY;\n currentShape.move(dx, dy);\n startX = x;\n startY = y;\n\n // Issue #24 bug #4: track containing frame during drag of an\n // existing arrow so mouseUp re-parents correctly. Without this\n // hoveredFrameArrow stays null and the arrow is detached the\n // moment the user nudges it inside its own parent frame.\n let newHover = null;\n for (const f of shapes) {\n if (f.shapeName !== 'frame') continue;\n if (f === currentShape) continue;\n if (typeof f.isShapeInFrame === 'function' && f.isShapeInFrame(currentShape)) {\n newHover = f;\n break;\n }\n }\n if (hoveredFrameArrow && hoveredFrameArrow !== newHover && typeof hoveredFrameArrow.removeHighlight === 'function') {\n hoveredFrameArrow.removeHighlight();\n }\n if (newHover && newHover !== hoveredFrameArrow && typeof newHover.highlightFrame === 'function') {\n newHover.highlightFrame();\n }\n hoveredFrameArrow = newHover;\n\n // Snap guides\n if (window.__sketchStoreApi && window.__sketchStoreApi.getState().snapToObjects) {\n const snap = calculateSnap(currentShape, e.shiftKey, e.clientX, e.clientY);\n if (snap.dx || snap.dy) {\n currentShape.move(snap.dx, snap.dy);\n }\n } else {\n clearSnapGuides();\n }\n\n svg.style.cursor = 'grabbing';\n } else if (isSelectionToolActive && currentShape && currentShape.isSelected) {\n // Provide visual feedback when hovering over anchors or the arrow\n const anchorInfo = currentShape.isNearAnchor(x, y);\n if (anchorInfo) {\n svg.style.cursor = 'grab';\n } else if (currentShape.contains(x, y)) {\n svg.style.cursor = 'move';\n } else {\n svg.style.cursor = 'default';\n }\n } else if (isSelectionToolActive) {\n // Check if hovering over any selectable arrow\n let hoveringOverArrow = false;\n for (let i = shapes.length - 1; i >= 0; i--) {\n const shape = shapes[i];\n if (shape instanceof Arrow && shape.contains(x, y)) {\n hoveringOverArrow = true;\n break;\n }\n }\n svg.style.cursor = hoveringOverArrow ? 'pointer' : 'default';\n }\n};\n\nconst handleMouseUp = (e) => {\nif (isDrawingArrow && currentArrow) {\n // Remove any attachment preview that might still be visible\n const existingPreview = svg.querySelector('.attachment-preview');\n if (existingPreview) existingPreview.remove();\n\n // Check if arrow is too small\n const dx = currentArrow.endPoint.x - currentArrow.startPoint.x;\n const dy = currentArrow.endPoint.y - currentArrow.startPoint.y;\n const lengthSq = dx * dx + dy * dy;\n\n if (lengthSq < (5 / currentZoom) ** 2) {\n shapes.pop();\n if (currentArrow.group.parentNode) {\n currentArrow.group.parentNode.removeChild(currentArrow.group);\n }\n currentArrow = null;\n currentShape = null;\n } else {\n const startAttachment = Arrow.findNearbyShape(currentArrow.startPoint);\n const endAttachment = Arrow.findNearbyShape(currentArrow.endPoint);\n\n if (startAttachment) {\n currentArrow.attachToShape(true, startAttachment.shape, startAttachment.attachment);\n }\n\n if (endAttachment) {\n currentArrow.attachToShape(false, endAttachment.shape, endAttachment.attachment);\n }\n\n // Check for frame containment and track attachment\n const finalFrame = hoveredFrameArrow;\n if (finalFrame) {\n finalFrame.addShapeToFrame(currentArrow);\n // Track the attachment for undo\n pushFrameAttachmentAction(finalFrame, currentArrow, 'attach', null);\n }\n\n // Push create action for undo/redo\n pushCreateAction(currentArrow);\n\n // Auto-select the drawn arrow and switch to selection tool\n const drawnArrow = currentArrow;\n if (window.__sketchStoreApi) window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });\n currentShape = drawnArrow;\n drawnArrow.selectArrow();\n }\n\n // Clear frame highlighting\n if (hoveredFrameArrow) {\n hoveredFrameArrow.removeHighlight();\n hoveredFrameArrow = null;\n }\n\n currentArrow = null;\n}\n\nif (isDragging && dragOldPosArrow && currentShape) {\n // Issue #34 bug #2: containment transfer happens later in this block,\n // so currentShape.parentFrame is still the OLD frame here. hoveredFrameArrow\n // tracks the actual destination during mousemove \u2014 use that as the truth.\n const newPos = {\n startPoint: { x: currentShape.startPoint.x, y: currentShape.startPoint.y },\n endPoint: { x: currentShape.endPoint.x, y: currentShape.endPoint.y },\n parentFrame: hoveredFrameArrow || null,\n };\n const oldPos = {\n ...dragOldPosArrow,\n parentFrame: draggedShapeInitialFrameArrow // Add this line\n };\n \n const stateChanged = dragOldPosArrow.startPoint.x !== newPos.startPoint.x ||\n dragOldPosArrow.startPoint.y !== newPos.startPoint.y ||\n dragOldPosArrow.endPoint.x !== newPos.endPoint.x ||\n dragOldPosArrow.endPoint.y !== newPos.endPoint.y;\n \n const frameChanged = oldPos.parentFrame !== newPos.parentFrame;\n\n if (stateChanged || frameChanged) {\n pushTransformAction(currentShape, oldPos, newPos);\n }\n \n // Handle frame containment changes after drag\n if (isDragging) {\n const finalFrame = hoveredFrameArrow;\n \n // If shape moved to a different frame\n if (draggedShapeInitialFrameArrow !== finalFrame) {\n // Remove from initial frame\n if (draggedShapeInitialFrameArrow) {\n draggedShapeInitialFrameArrow.removeShapeFromFrame(currentShape);\n }\n \n // Add to new frame\n if (finalFrame) {\n finalFrame.addShapeToFrame(currentShape);\n }\n \n // Track the frame change for undo\n if (frameChanged) {\n pushFrameAttachmentAction(finalFrame || draggedShapeInitialFrameArrow, currentShape, \n finalFrame ? 'attach' : 'detach', draggedShapeInitialFrameArrow);\n }\n } else if (draggedShapeInitialFrameArrow) {\n // Shape stayed in same frame, restore clipping\n draggedShapeInitialFrameArrow.restoreToFrame(currentShape);\n }\n }\n \n draggedShapeInitialFrameArrow = null;\n dragOldPosArrow = null;\n}\n\n// Clear frame highlighting\nif (hoveredFrameArrow) {\n hoveredFrameArrow.removeHighlight();\n hoveredFrameArrow = null;\n}\n\nclearSnapGuides();\nisDrawingArrow = false;\nisResizing = false;\nisDragging = false;\nactiveAnchor = null;\nsvg.style.cursor = 'default';\n};\n\n// Remove old event listeners and add new ones\nsvg.removeEventListener('pointerdown', handleMouseDown);\nsvg.removeEventListener('pointermove', handleMouseMove);\nsvg.removeEventListener('pointerup', handleMouseUp);\n\n\n// Updated style handlers with undo/redo support\nconst updateSelectedArrowStyle = (styleChanges) => {\n if (currentShape instanceof Arrow && currentShape.isSelected) {\n const oldOptions = {\n ...currentShape.options,\n arrowOutlineStyle: currentShape.arrowOutlineStyle,\n arrowHeadStyle: currentShape.arrowHeadStyle,\n arrowCurved: currentShape.arrowCurved,\n arrowCurveAmount: currentShape.arrowCurveAmount\n };\n currentShape.updateStyle(styleChanges);\n pushOptionsChangeAction(currentShape, oldOptions);\n } else {\n if (styleChanges.stroke !== undefined) arrowStrokeColor = styleChanges.stroke;\n if (styleChanges.strokeWidth !== undefined) arrowStrokeThickness = styleChanges.strokeWidth;\n if (styleChanges.arrowOutlineStyle !== undefined) arrowOutlineStyle = styleChanges.arrowOutlineStyle;\n if (styleChanges.arrowHeadStyle !== undefined) arrowHeadStyle = styleChanges.arrowHeadStyle;\n if (styleChanges.arrowCurved !== undefined) arrowCurved = styleChanges.arrowCurved;\n if (styleChanges.arrowCurveAmount !== undefined) arrowCurveAmount = styleChanges.arrowCurveAmount;\n }\n};\n\narrowStrokeColorOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n arrowStrokeColorOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n const newColor = span.getAttribute(\"data-id\");\n updateSelectedArrowStyle({ stroke: newColor });\n });\n});\n\narrowStrokeThicknessValue.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n arrowStrokeThicknessValue.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n const newThickness = parseInt(span.getAttribute(\"data-id\"));\n updateSelectedArrowStyle({ strokeWidth: newThickness });\n });\n});\n\narrowOutlineStyleValue.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n arrowOutlineStyleValue.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n const newStyle = span.getAttribute(\"data-id\");\n updateSelectedArrowStyle({ arrowOutlineStyle: newStyle });\n });\n});\n\narrowTypeStyleValue.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n arrowTypeStyleValue.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n updateSelectedArrowStyle({ arrowCurved: span.getAttribute(\"data-id\") });\n });\n});\n\narrowCurveAmountOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n arrowCurveAmountOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n updateSelectedArrowStyle({ arrowCurveAmount: parseInt(span.getAttribute(\"data-id\")) });\n });\n});\n\narrowHeadStyleValue.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n arrowHeadStyleValue.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n const newHeadStyle = span.getAttribute(\"data-id\");\n updateSelectedArrowStyle({ arrowHeadStyle: newHeadStyle });\n });\n});\n\nfunction detachSelectedArrow() {\n if (currentShape instanceof Arrow && currentShape.isSelected) {\n if (currentShape.attachedToStart || currentShape.attachedToEnd) {\n const oldState = {\n attachedToStart: currentShape.attachedToStart,\n attachedToEnd: currentShape.attachedToEnd,\n startPoint: { ...currentShape.startPoint },\n endPoint: { ...currentShape.endPoint }\n };\n\n currentShape.detachFromShape(true);\n currentShape.detachFromShape(false);\n currentShape.draw();\n\n // Add to undo/redo if needed\n }\n }\n}\n\nfunction updateAttachedArrows(shape) {\n if (!shape) return;\n\n // If a DOM element was passed (e.g. from text/code/image move), find the wrapper\n let targetShape = shape;\n if (shape.nodeType) {\n targetShape = shapes.find(s => s.group === shape || s.element === shape) || shape;\n }\n\n shapes.forEach(arrowShape => {\n if (arrowShape instanceof Arrow) {\n let needsUpdate = false;\n if (arrowShape.attachedToStart && arrowShape.attachedToStart.shape === targetShape) {\n needsUpdate = true;\n }\n if (arrowShape.attachedToEnd && arrowShape.attachedToEnd.shape === targetShape) {\n needsUpdate = true;\n }\n\n if (needsUpdate) {\n arrowShape.updateAttachments();\n }\n }\n });\n}\n\nfunction cleanupAttachments(deletedShape) {\n if (!deletedShape) return;\n\n // If a DOM element was passed, find the wrapper\n let targetShape = deletedShape;\n if (deletedShape.nodeType) {\n targetShape = shapes.find(s => s.group === deletedShape || s.element === deletedShape) || deletedShape;\n }\n\n shapes.forEach(shape => {\n if (shape instanceof Arrow) {\n let needsDraw = false;\n if (shape.attachedToStart && shape.attachedToStart.shape === targetShape) {\n shape.detachFromShape(true);\n needsDraw = true;\n }\n if (shape.attachedToEnd && shape.attachedToEnd.shape === targetShape) {\n shape.detachFromShape(false);\n needsDraw = true;\n }\n if (needsDraw) {\n shape.draw();\n }\n }\n });\n}\n\n// Add keyboard shortcut to detach arrows\ndocument.addEventListener('keydown', (e) => {\n if (e.key.toLowerCase() === 'd' && e.ctrlKey) {\n e.preventDefault();\n detachSelectedArrow();\n }\n});\n\n// Expose arrow tool settings on window for React sidebar bridge\nwindow.arrowToolSettings = {\n get strokeColor() { return arrowStrokeColor; },\n set strokeColor(v) { arrowStrokeColor = v; },\n get strokeWidth() { return arrowStrokeThickness; },\n set strokeWidth(v) { arrowStrokeThickness = v; },\n get outlineStyle() { return arrowOutlineStyle; },\n set outlineStyle(v) { arrowOutlineStyle = v; },\n get headStyle() { return arrowHeadStyle; },\n set headStyle(v) { arrowHeadStyle = v; },\n get arrowCurved() { return arrowCurved; },\n set arrowCurved(v) { arrowCurved = v; },\n get curveAmount() { return arrowCurveAmount; },\n set curveAmount(v) { arrowCurveAmount = v; },\n};\nwindow.updateSelectedArrowStyle = updateSelectedArrowStyle;\n\n// Export the cleanup function\n// Expose cleanupAttachments globally for centralized delete\nwindow.cleanupAttachments = cleanupAttachments;\n\nexport {\n handleMouseDown as handleMouseDownArrow,\n handleMouseMove as handleMouseMoveArrow,\n handleMouseUp as handleMouseUpArrow,\n cleanupAttachments,\n updateAttachedArrows\n};\n"],
5
5
  "mappings": "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",
6
6
  "names": ["svg", "shapes"]
7
7
  }
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  cleanupAttachments,
7
7
  updateAttachedArrows
8
- } from "./chunk-X5ENBMGL.js";
8
+ } from "./chunk-KXLNEFN5.js";
9
9
  import {
10
10
  pushCreateAction,
11
11
  pushDeleteActionWithAttachments,
@@ -19,7 +19,7 @@ import {
19
19
  // src/tools/codeTool.js
20
20
  function getThemeStroke() {
21
21
  if (typeof document === "undefined") return "#fff";
22
- return document.body && document.body.classList.contains("theme-dark") ? "#fff" : "#1a1a2e";
22
+ return document.body && document.body.classList.contains("theme-dark") ? "#fff" : "#000000";
23
23
  }
24
24
  var codeTextSize = "25px";
25
25
  var codeTextFont = "lixCode";
@@ -1601,4 +1601,4 @@ export {
1601
1601
  getCodeLanguage,
1602
1602
  getSelectedCodeBlock
1603
1603
  };
1604
- //# sourceMappingURL=chunk-DODPOWNX.js.map
1604
+ //# sourceMappingURL=chunk-P5476S5I.js.map