@elixpo/lixsketch 5.6.5 → 5.6.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mcp/index.js +5 -1
- package/dist/mcp/index.js.map +2 -2
- package/dist/mcp/stdio.js +5 -1
- package/dist/mcp/stdio.js.map +2 -2
- package/dist/react/{AIRenderer-SRF7LU5K.js → AIRenderer-R5M2CIDO.js} +13 -6
- package/dist/react/AIRenderer-R5M2CIDO.js.map +7 -0
- package/dist/react/Circle-HMM5PKJ2.js +10 -0
- package/dist/react/{CopyPaste-YUDZ6DHY.js → CopyPaste-PPDS3AD6.js} +11 -10
- package/dist/react/{CopyPaste-YUDZ6DHY.js.map → CopyPaste-PPDS3AD6.js.map} +1 -1
- package/dist/react/{EventDispatcher-7LAK7GQ7.js → EventDispatcher-UV7LFSAS.js} +216 -63
- package/dist/react/EventDispatcher-UV7LFSAS.js.map +7 -0
- package/dist/react/Frame-DELCMYV6.js +11 -0
- package/dist/react/{FreehandStroke-U6GYZOM4.js → FreehandStroke-WXIJKD5I.js} +2 -2
- package/dist/react/{GraphEngine-MM6ALA2N.js → GraphEngine-XH3RPYO4.js} +9 -2
- package/dist/react/GraphEngine-XH3RPYO4.js.map +7 -0
- package/dist/react/IconShape-PZHMZSLR.js +10 -0
- package/dist/react/ImageShape-ZMBZARRI.js +10 -0
- package/dist/react/Line-VPVPL6ET.js +10 -0
- package/dist/react/{LixScriptParser-JYWJX375.js → LixScriptParser-YS3ZOTGS.js} +6 -2
- package/dist/react/LixScriptParser-YS3ZOTGS.js.map +7 -0
- package/dist/react/{MermaidFlowchartRenderer-PQEC4TMI.js → MermaidFlowchartRenderer-EL3Q2MNW.js} +6 -2
- package/dist/react/MermaidFlowchartRenderer-EL3Q2MNW.js.map +7 -0
- package/dist/react/MermaidSequenceParser-DBYXW23P.js +8 -0
- package/dist/react/{MermaidSequenceRenderer-KCUHO7UI.js → MermaidSequenceRenderer-K4KHHEVC.js} +10 -3
- package/dist/react/MermaidSequenceRenderer-K4KHHEVC.js.map +7 -0
- package/dist/react/{MermaidStructuredRenderer-W7UKN7BM.js → MermaidStructuredRenderer-6LN3WISP.js} +7 -2
- package/dist/react/MermaidStructuredRenderer-6LN3WISP.js.map +7 -0
- package/dist/react/Rectangle-4U4CD2ER.js +10 -0
- package/dist/react/{SceneSerializer-SG6SJN5X.js → SceneSerializer-H6KMQCO2.js} +120 -46
- package/dist/react/SceneSerializer-H6KMQCO2.js.map +7 -0
- package/dist/react/{Selection-2TSH3J6P.js → Selection-CFWRGVKH.js} +4 -4
- package/dist/react/{SketchEngine-UD2XV2KT.js → SketchEngine-UFLZJQXS.js} +26 -26
- package/dist/react/{UndoRedo-IN4SXDG6.js → UndoRedo-RXO7YHA2.js} +12 -2
- package/dist/react/{arrowTool-OYDWJGQK.js → arrowTool-DO327FKU.js} +3 -3
- package/dist/react/{chunk-EOURRJ55.js → chunk-2ALS5JGS.js} +2 -2
- package/dist/react/{chunk-LJR7EVW2.js → chunk-37PF7FG2.js} +3 -3
- package/dist/react/chunk-6AIFXYV6.js +31 -0
- package/dist/react/chunk-6AIFXYV6.js.map +7 -0
- package/dist/react/{chunk-XOWNCYE4.js → chunk-6LWUR7XB.js} +3 -3
- package/dist/react/{chunk-ASBC5G35.js → chunk-7DD2JRBC.js} +2 -2
- package/dist/react/{chunk-OP56XPWF.js → chunk-BOZEDUAF.js} +2 -2
- package/dist/react/{chunk-RGMDWLRJ.js → chunk-CGMUXYPJ.js} +3 -3
- package/dist/react/{chunk-M6TMN76K.js → chunk-DODPOWNX.js} +3 -3
- package/dist/react/{chunk-LSHZYN77.js → chunk-GQLXUZHQ.js} +2 -2
- package/dist/react/{chunk-7CM5XQDN.js → chunk-I7TVGJFF.js} +20 -36
- package/dist/react/chunk-I7TVGJFF.js.map +7 -0
- package/dist/react/{chunk-K5RY4EV7.js → chunk-KC26KJW4.js} +26 -17
- package/dist/react/chunk-KC26KJW4.js.map +7 -0
- package/dist/react/{chunk-XFL4R5ZF.js → chunk-KZBKYHZO.js} +16 -35
- package/dist/react/chunk-KZBKYHZO.js.map +7 -0
- package/dist/react/{chunk-VQVEPJSA.js → chunk-MHV5P6TS.js} +2 -1
- package/dist/react/chunk-MHV5P6TS.js.map +7 -0
- package/dist/react/{chunk-PXFPPO3R.js → chunk-NH3NVSWT.js} +18 -2
- package/dist/react/chunk-NH3NVSWT.js.map +7 -0
- package/dist/react/{chunk-APTOPAOY.js → chunk-O7KXLFZN.js} +3 -3
- package/dist/react/{chunk-GQUZPON4.js → chunk-RK3NVAER.js} +4 -4
- package/dist/react/{chunk-FETTJLCV.js → chunk-VZPH7OAM.js} +14 -22
- package/dist/react/chunk-VZPH7OAM.js.map +7 -0
- package/dist/react/{chunk-6GPEWDRB.js → chunk-VZX55VQL.js} +115 -6
- package/dist/react/chunk-VZX55VQL.js.map +7 -0
- package/dist/react/{chunk-TKXKJNTX.js → chunk-W7XUY4GR.js} +16 -19
- package/dist/react/chunk-W7XUY4GR.js.map +7 -0
- package/dist/react/{chunk-XYUFEIZR.js → chunk-X5ENBMGL.js} +2 -2
- package/dist/react/{chunk-K5BG5MHY.js → chunk-ZNZAICWY.js} +36 -60
- package/dist/react/chunk-ZNZAICWY.js.map +7 -0
- package/dist/react/{circleTool-LDKGZALF.js → circleTool-NK4RVDAR.js} +4 -4
- package/dist/react/{codeTool-4YZO5W7J.js → codeTool-3WF4HEOW.js} +4 -4
- package/dist/react/{frameTool-MXNJEXQQ.js → frameTool-VCNV2NG2.js} +4 -4
- package/dist/react/{freehandTool-26D3FOOX.js → freehandTool-TBAOD46K.js} +4 -4
- package/dist/react/{iconTool-46O5VEUX.js → iconTool-65JCAKYF.js} +4 -4
- package/dist/react/{imageTool-P2RWZRHO.js → imageTool-UQZUBOK2.js} +4 -4
- package/dist/react/index.js +148 -37
- package/dist/react/index.js.map +4 -4
- package/dist/react/{lineTool-ZMR27U5L.js → lineTool-762KBYOM.js} +4 -4
- package/dist/react/{rectangleTool-EJKK6UTX.js → rectangleTool-IQK3HZK6.js} +4 -4
- package/dist/react/{textTool-S4XXZHZH.js → textTool-ITG2SBJK.js} +5 -5
- package/package.json +5 -2
- package/src/core/AIRenderer.js +8 -2
- package/src/core/CanvasSpace.js +28 -0
- package/src/core/GraphRenderer.js +8 -3
- package/src/core/LixScriptParser.js +7 -1
- package/src/core/MermaidFlowchartRenderer.js +5 -1
- package/src/core/MermaidSequenceParser.js +1 -0
- package/src/core/MermaidSequenceRenderer.js +8 -3
- package/src/core/MermaidStructuredRenderer.js +6 -1
- package/src/core/SceneSerializer.js +121 -38
- package/src/core/Selection.js +29 -14
- package/src/core/UndoRedo.js +126 -5
- package/src/react/components/AppMenu.jsx +20 -19
- package/src/react/components/canvas/CanvasRulers.jsx +8 -13
- package/src/react/components/canvas/SVGCanvas.jsx +2 -1
- package/src/react/components/canvas/rulerUnits.js +28 -0
- package/src/react/components/sidebars/PaintBucketSidebar.jsx +1 -1
- package/src/react/store/useSketchStore.js +24 -3
- package/src/react/store/useUIStore.js +24 -1
- package/src/react/utils/canvasBackgrounds.js +29 -0
- package/src/shapes/Circle.js +12 -19
- package/src/shapes/Frame.js +38 -69
- package/src/shapes/FreehandStroke.js +24 -1
- package/src/shapes/Rectangle.js +10 -22
- package/src/tools/circleTool.js +3 -27
- package/src/tools/paintBucketTool.js +72 -15
- package/src/tools/rectangleTool.js +7 -23
- package/src/tools/shapeRecognition.js +270 -0
- package/src/tools/shapeRecognitionTool.js +36 -183
- package/dist/react/AIRenderer-SRF7LU5K.js.map +0 -7
- package/dist/react/Circle-6POZCUZD.js +0 -9
- package/dist/react/EventDispatcher-7LAK7GQ7.js.map +0 -7
- package/dist/react/Frame-7D2MXCFF.js +0 -11
- package/dist/react/GraphEngine-MM6ALA2N.js.map +0 -7
- package/dist/react/IconShape-ZADX7Y33.js +0 -10
- package/dist/react/ImageShape-UJQN2HI7.js +0 -10
- package/dist/react/Line-APEULMHE.js +0 -10
- package/dist/react/LixScriptParser-JYWJX375.js.map +0 -7
- package/dist/react/MermaidFlowchartRenderer-PQEC4TMI.js.map +0 -7
- package/dist/react/MermaidSequenceParser-UKG2NSZY.js +0 -8
- package/dist/react/MermaidSequenceRenderer-KCUHO7UI.js.map +0 -7
- package/dist/react/MermaidStructuredRenderer-W7UKN7BM.js.map +0 -7
- package/dist/react/Rectangle-S7XUKWYD.js +0 -9
- package/dist/react/SceneSerializer-SG6SJN5X.js.map +0 -7
- package/dist/react/chunk-6GPEWDRB.js.map +0 -7
- package/dist/react/chunk-7CM5XQDN.js.map +0 -7
- package/dist/react/chunk-FETTJLCV.js.map +0 -7
- package/dist/react/chunk-K5BG5MHY.js.map +0 -7
- package/dist/react/chunk-K5RY4EV7.js.map +0 -7
- package/dist/react/chunk-PXFPPO3R.js.map +0 -7
- package/dist/react/chunk-TKXKJNTX.js.map +0 -7
- package/dist/react/chunk-VQVEPJSA.js.map +0 -7
- package/dist/react/chunk-XFL4R5ZF.js.map +0 -7
- /package/dist/react/{Circle-6POZCUZD.js.map → Circle-HMM5PKJ2.js.map} +0 -0
- /package/dist/react/{Frame-7D2MXCFF.js.map → Frame-DELCMYV6.js.map} +0 -0
- /package/dist/react/{FreehandStroke-U6GYZOM4.js.map → FreehandStroke-WXIJKD5I.js.map} +0 -0
- /package/dist/react/{IconShape-ZADX7Y33.js.map → IconShape-PZHMZSLR.js.map} +0 -0
- /package/dist/react/{ImageShape-UJQN2HI7.js.map → ImageShape-ZMBZARRI.js.map} +0 -0
- /package/dist/react/{Line-APEULMHE.js.map → Line-VPVPL6ET.js.map} +0 -0
- /package/dist/react/{MermaidSequenceParser-UKG2NSZY.js.map → MermaidSequenceParser-DBYXW23P.js.map} +0 -0
- /package/dist/react/{Rectangle-S7XUKWYD.js.map → Rectangle-4U4CD2ER.js.map} +0 -0
- /package/dist/react/{Selection-2TSH3J6P.js.map → Selection-CFWRGVKH.js.map} +0 -0
- /package/dist/react/{SketchEngine-UD2XV2KT.js.map → SketchEngine-UFLZJQXS.js.map} +0 -0
- /package/dist/react/{UndoRedo-IN4SXDG6.js.map → UndoRedo-RXO7YHA2.js.map} +0 -0
- /package/dist/react/{arrowTool-OYDWJGQK.js.map → arrowTool-DO327FKU.js.map} +0 -0
- /package/dist/react/{chunk-EOURRJ55.js.map → chunk-2ALS5JGS.js.map} +0 -0
- /package/dist/react/{chunk-LJR7EVW2.js.map → chunk-37PF7FG2.js.map} +0 -0
- /package/dist/react/{chunk-XOWNCYE4.js.map → chunk-6LWUR7XB.js.map} +0 -0
- /package/dist/react/{chunk-ASBC5G35.js.map → chunk-7DD2JRBC.js.map} +0 -0
- /package/dist/react/{chunk-OP56XPWF.js.map → chunk-BOZEDUAF.js.map} +0 -0
- /package/dist/react/{chunk-RGMDWLRJ.js.map → chunk-CGMUXYPJ.js.map} +0 -0
- /package/dist/react/{chunk-M6TMN76K.js.map → chunk-DODPOWNX.js.map} +0 -0
- /package/dist/react/{chunk-LSHZYN77.js.map → chunk-GQLXUZHQ.js.map} +0 -0
- /package/dist/react/{chunk-APTOPAOY.js.map → chunk-O7KXLFZN.js.map} +0 -0
- /package/dist/react/{chunk-GQUZPON4.js.map → chunk-RK3NVAER.js.map} +0 -0
- /package/dist/react/{chunk-XYUFEIZR.js.map → chunk-X5ENBMGL.js.map} +0 -0
- /package/dist/react/{circleTool-LDKGZALF.js.map → circleTool-NK4RVDAR.js.map} +0 -0
- /package/dist/react/{codeTool-4YZO5W7J.js.map → codeTool-3WF4HEOW.js.map} +0 -0
- /package/dist/react/{frameTool-MXNJEXQQ.js.map → frameTool-VCNV2NG2.js.map} +0 -0
- /package/dist/react/{freehandTool-26D3FOOX.js.map → freehandTool-TBAOD46K.js.map} +0 -0
- /package/dist/react/{iconTool-46O5VEUX.js.map → iconTool-65JCAKYF.js.map} +0 -0
- /package/dist/react/{imageTool-P2RWZRHO.js.map → imageTool-UQZUBOK2.js.map} +0 -0
- /package/dist/react/{lineTool-ZMR27U5L.js.map → lineTool-762KBYOM.js.map} +0 -0
- /package/dist/react/{rectangleTool-EJKK6UTX.js.map → rectangleTool-IQK3HZK6.js.map} +0 -0
- /package/dist/react/{textTool-S4XXZHZH.js.map → textTool-ITG2SBJK.js.map} +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/shapes/FreehandStroke.js"],
|
|
4
|
+
"sourcesContent": ["/* eslint-disable */\nimport { getStroke } from \"perfect-freehand\";\nimport { registerRotationAnchor } from '../core/ScreenSpaceControls.js';\n// FreehandStroke shape class - extracted from canvasStroke.js\n// Depends on globals: svg, shapes, currentShape, currentZoom, currentViewBox\n\nfunction getSvgCoordinates(event) {\n const rect = svg.getBoundingClientRect();\n const scaleX = currentViewBox.width / rect.width;\n const scaleY = currentViewBox.height / rect.height;\n\n const svgX = currentViewBox.x + (event.clientX - rect.left) * scaleX;\n const svgY = currentViewBox.y + (event.clientY - rect.top) * scaleY;\n\n return { x: svgX, y: svgY };\n}\n\nfunction getSvgPathFromStroke(stroke) {\n if (!stroke.length) return '';\n \n // Use more sophisticated curve fitting\n const pathData = [];\n pathData.push('M', stroke[0][0], stroke[0][1]);\n \n for (let i = 1; i < stroke.length - 1; i++) {\n const curr = stroke[i];\n const next = stroke[i + 1];\n \n // Calculate control points for smoother curves\n const cpX = curr[0] + (next[0] - curr[0]) * 0.5;\n const cpY = curr[1] + (next[1] - curr[1]) * 0.5;\n \n pathData.push('Q', curr[0], curr[1], cpX, cpY);\n }\n \n // Add final point\n if (stroke.length > 1) {\n const lastPoint = stroke[stroke.length - 1];\n pathData.push('L', lastPoint[0], lastPoint[1]);\n }\n \n return pathData.join(' ');\n}\n\nclass FreehandStroke {\n constructor(points = [], options = {}) {\n this.points = points;\n this.rawPoints = []; \n this.options = {\n stroke: \"#fff\",\n strokeWidth: 3,\n fill: \"none\",\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeOpacity: 1,\n thinning: 0.5,\n roughness: 0,\n strokeStyle: \"solid\",\n ...options\n };\n this.element = null;\n this.isSelected = false;\n this.rotation = 0;\n this.group = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n this.anchors = [];\n this.rotationAnchor = null;\n this.rotationLine = null;\n this.selectionPadding = 8;\n this.selectionOutline = null;\n this.boundingBox = { x: 0, y: 0, width: 0, height: 0 };\n this.shapeName = \"freehandStroke\";\n this.shapeID = `freehand-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n this.group.setAttribute('id', this.shapeID);\n this._moveOffsetX = 0;\n this._moveOffsetY = 0;\n\n // Frame attachment properties\n this.parentFrame = null;\n \n svg.appendChild(this.group);\n this.draw();\n }\n\n // Add position and dimension properties for frame compatibility\n // Getters include pending move offset so callers see the visual position\n get x() {\n return this.boundingBox.x + (this._moveOffsetX || 0);\n }\n\n set x(value) {\n const dx = value - this.boundingBox.x - (this._moveOffsetX || 0);\n this.points = this.points.map(point => [point[0] + dx, point[1], point[2] || 0.5]);\n this.boundingBox.x = value - (this._moveOffsetX || 0);\n }\n\n get y() {\n return this.boundingBox.y + (this._moveOffsetY || 0);\n }\n\n set y(value) {\n const dy = value - this.boundingBox.y - (this._moveOffsetY || 0);\n this.points = this.points.map(point => [point[0], point[1] + dy, point[2] || 0.5]);\n this.boundingBox.y = value - (this._moveOffsetY || 0);\n }\n \n get width() {\n return this.boundingBox.width;\n }\n \n set width(value) {\n if (this.boundingBox.width === 0) return;\n const scaleX = value / this.boundingBox.width;\n const centerX = this.boundingBox.x + this.boundingBox.width / 2;\n this.points = this.points.map(point => [\n centerX + (point[0] - centerX) * scaleX,\n point[1],\n point[2] || 0.5\n ]);\n this.boundingBox.width = value;\n }\n \n get height() {\n return this.boundingBox.height;\n }\n \n set height(value) {\n if (this.boundingBox.height === 0) return;\n const scaleY = value / this.boundingBox.height;\n const centerY = this.boundingBox.y + this.boundingBox.height / 2;\n this.points = this.points.map(point => [\n point[0],\n centerY + (point[1] - centerY) * scaleY,\n point[2] || 0.5\n ]);\n this.boundingBox.height = value;\n }\n\n // Enhanced smoothing algorithm\n smoothPoints(points, factor = 0.8) {\n if (points.length < 3) return points;\n \n const smoothed = [points[0]]; // Keep first point\n \n for (let i = 1; i < points.length - 1; i++) {\n const prev = points[i - 1];\n const curr = points[i];\n const next = points[i + 1];\n \n // Apply weighted average smoothing\n const smoothedX = curr[0] * (1 - factor) + (prev[0] + next[0]) * factor * 0.5;\n const smoothedY = curr[1] * (1 - factor) + (prev[1] + next[1]) * factor * 0.5;\n const pressure = curr[2] || 0.5;\n \n smoothed.push([smoothedX, smoothedY, pressure]);\n }\n \n smoothed.push(points[points.length - 1]); // Keep last point\n return smoothed;\n }\n\n // Interpolate points for smoother curves\n interpolatePoints(points, steps = 2) {\n if (points.length < 2) return points;\n \n const interpolated = [points[0]];\n \n for (let i = 0; i < points.length - 1; i++) {\n const curr = points[i];\n const next = points[i + 1];\n \n for (let j = 1; j <= steps; j++) {\n const t = j / (steps + 1);\n const x = curr[0] + (next[0] - curr[0]) * t;\n const y = curr[1] + (next[1] - curr[1]) * t;\n const pressure = curr[2] + (next[2] - curr[2]) * t;\n interpolated.push([x, y, pressure]);\n }\n \n if (i < points.length - 2) {\n interpolated.push(next);\n }\n }\n \n interpolated.push(points[points.length - 1]);\n return interpolated;\n }\n\n // Enhanced path generation with better curve fitting\n getPathData() {\n if (this.points.length < 2) return '';\n\n if (this.options.closedFill) {\n const [first, ...rest] = this.points;\n return [`M ${first[0]} ${first[1]}`, ...rest.map(point => `L ${point[0]} ${point[1]}`), 'Z'].join(' ');\n }\n\n const isRough = this.options.roughness === \"rough\";\n const isMedium = this.options.roughness === \"medium\";\n\n // Roughness: jitter points before smoothing\n let pts = this.points;\n if (isRough || isMedium) {\n const jitter = isRough ? 3.5 : 1.5;\n pts = pts.map((p, i) => {\n if (i === 0 || i === pts.length - 1) return p;\n return [\n p[0] + (Math.random() - 0.5) * jitter,\n p[1] + (Math.random() - 0.5) * jitter,\n p[2] || 0.5\n ];\n });\n }\n\n let smoothedPoints = this.interpolatePoints(pts, 1);\n if (!isRough) {\n smoothedPoints = this.smoothPoints(smoothedPoints, 0.6);\n smoothedPoints = this.smoothPoints(smoothedPoints, 0.4);\n }\n\n const thinning = this.options.thinning !== undefined ? this.options.thinning : 0;\n const smoothing = isRough ? 0.3 : isMedium ? 0.6 : 0.9;\n const streamline = isRough ? 0.1 : isMedium ? 0.25 : 0.4;\n\n const stroke = getStroke(smoothedPoints, {\n size: this.options.strokeWidth,\n thinning: thinning,\n smoothing: smoothing,\n streamline: streamline,\n easing: (t) => Math.sin(t * Math.PI * 0.5),\n start: {\n taper: thinning > 0 ? this.options.strokeWidth * 2 : 0,\n easing: (t) => t * t,\n cap: thinning === 0\n },\n end: {\n taper: thinning > 0 ? this.options.strokeWidth * 2 : 0,\n easing: (t) => --t * t * t + 1,\n cap: thinning === 0\n },\n simulatePressure: thinning > 0\n });\n\n return getSvgPathFromStroke(stroke);\n }\n\n // Simple centerline path used for dashed/dotted overlays\n getCenterlinePathData() {\n if (this.points.length < 2) return '';\n const d = [`M ${this.points[0][0]} ${this.points[0][1]}`];\n for (let i = 1; i < this.points.length - 1; i++) {\n const curr = this.points[i];\n const next = this.points[i + 1];\n const cpX = curr[0] + (next[0] - curr[0]) * 0.5;\n const cpY = curr[1] + (next[1] - curr[1]) * 0.5;\n d.push(`Q ${curr[0]} ${curr[1]} ${cpX} ${cpY}`);\n }\n const last = this.points[this.points.length - 1];\n d.push(`L ${last[0]} ${last[1]}`);\n return d.join(' ');\n }\n\n // Calculate the bounding box of the stroke\n calculateBoundingBox() {\n if (this.points.length === 0) {\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n \n let minX = Infinity, minY = Infinity;\n let maxX = -Infinity, maxY = -Infinity;\n \n this.points.forEach(point => {\n minX = Math.min(minX, point[0]);\n minY = Math.min(minY, point[1]);\n maxX = Math.max(maxX, point[0]);\n maxY = Math.max(maxY, point[1]);\n });\n \n // Ensure we have valid dimensions\n if (minX === Infinity || minY === Infinity) {\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n \n // Add padding for stroke width\n const padding = this.options.strokeWidth / 2;\n return {\n x: minX - padding,\n y: minY - padding,\n width: Math.max(0, (maxX - minX) + padding * 2),\n height: Math.max(0, (maxY - minY) + padding * 2)\n };\n }\n\n draw() {\n while (this.group.firstChild) {\n this.group.removeChild(this.group.firstChild);\n }\n\n if (this.selectionOutline && this.selectionOutline.parentNode === this.group) {\n this.group.removeChild(this.selectionOutline);\n this.selectionOutline = null;\n }\n\n // Normal freehand paths use the filled outline from perfect-freehand.\n // Closed-fill paths (pie sectors, polygons) use their actual polygon\n // geometry with a separate outline, preserving sharp radial edges.\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n const pathData = this.getPathData();\n path.setAttribute('d', pathData);\n const closedFillStyle = this.options.fillStyle || 'solid';\n const closedFill = closedFillStyle === 'none'\n ? 'transparent'\n : (this.options.fill || this.options.stroke);\n const patternedFill = this.options.closedFill\n && !['none', 'solid'].includes(closedFillStyle)\n && typeof rough !== 'undefined';\n path.setAttribute('fill', this.options.closedFill\n ? (patternedFill ? 'transparent' : closedFill)\n : this.options.stroke);\n path.setAttribute('fill-opacity', this.options.strokeOpacity);\n path.setAttribute('stroke', this.options.closedFill ? (this.options.outlineStroke || 'none') : 'none');\n if (this.options.closedFill) {\n path.setAttribute('stroke-width', this.options.outlineWidth || this.options.strokeWidth || 1);\n path.setAttribute('stroke-linejoin', 'round');\n path.setAttribute('vector-effect', 'non-scaling-stroke');\n }\n\n // Overlay a dashed/dotted centerline if needed\n if (this.options.strokeStyle === \"dashed\" || this.options.strokeStyle === \"dotted\") {\n const dashArray = this.options.strokeStyle === \"dashed\"\n ? `${this.options.strokeWidth * 3} ${this.options.strokeWidth * 2}`\n : `${this.options.strokeWidth * 0.5} ${this.options.strokeWidth * 2}`;\n const overlay = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n overlay.setAttribute('d', this.getCenterlinePathData());\n overlay.setAttribute('fill', 'none');\n overlay.setAttribute('stroke', this.options.stroke);\n overlay.setAttribute('stroke-width', this.options.strokeWidth);\n overlay.setAttribute('stroke-linecap', 'round');\n overlay.setAttribute('stroke-linejoin', 'round');\n overlay.setAttribute('stroke-dasharray', dashArray);\n overlay.setAttribute('stroke-opacity', this.options.strokeOpacity);\n this.group.appendChild(overlay);\n }\n\n if (patternedFill) {\n const fillGroup = rough.svg(svg).path(pathData, {\n stroke: 'none',\n fill: closedFill,\n fillStyle: closedFillStyle,\n fillWeight: Math.max(1, (this.options.strokeWidth || 2) / 2),\n roughness: 0.8,\n });\n fillGroup.setAttribute('data-freehand-fill-pattern', closedFillStyle);\n this.group.appendChild(fillGroup);\n }\n\n this.element = path;\n this.group.appendChild(path);\n\n // Calculate and store bounding box\n this.boundingBox = this.calculateBoundingBox();\n\n // Apply rotation\n const centerX = this.boundingBox.x + this.boundingBox.width / 2;\n const centerY = this.boundingBox.y + this.boundingBox.height / 2;\n\n // Ensure centerX and centerY are valid numbers\n if (!isNaN(centerX) && !isNaN(centerY)) {\n this.group.setAttribute('transform', `rotate(${this.rotation} ${centerX} ${centerY})`);\n }\n\n if (this.isSelected) {\n this.addAnchors();\n }\n }\n\n move(dx, dy) {\n // Diagram polygons (currently pie sectors) are redrawn by their parent\n // frame after every movement step. Moving them with a deferred SVG\n // transform therefore loses the visible transform on that redraw while\n // leaving a hidden offset behind, which makes sectors detach from the\n // frame and jump the next time they are selected. Keep their geometry\n // authoritative instead.\n if (this.options.closedFill) {\n this.points = this.points.map(point => [\n point[0] + dx,\n point[1] + dy,\n point[2] || 0.5\n ]);\n this._moveOffsetX = 0;\n this._moveOffsetY = 0;\n this.draw();\n return;\n }\n\n // Accumulate offset for transform-based movement (avoids full path rebuild)\n this._moveOffsetX = (this._moveOffsetX || 0) + dx;\n this._moveOffsetY = (this._moveOffsetY || 0) + dy;\n const centerX = this.boundingBox.x + this.boundingBox.width / 2;\n const centerY = this.boundingBox.y + this.boundingBox.height / 2;\n const rot = this.rotation ? `rotate(${this.rotation} ${centerX} ${centerY})` : '';\n this.group.setAttribute('transform', `translate(${this._moveOffsetX}, ${this._moveOffsetY}) ${rot}`);\n }\n\n // Call after drag ends to bake the offset into actual point coordinates\n finalizeMove() {\n if (this._moveOffsetX || this._moveOffsetY) {\n const ox = this._moveOffsetX || 0;\n const oy = this._moveOffsetY || 0;\n this.points = this.points.map(point => [point[0] + ox, point[1] + oy, point[2] || 0.5]);\n this._moveOffsetX = 0;\n this._moveOffsetY = 0;\n this.draw();\n }\n }\n\n updateAttachedArrows() {\n if (typeof window.__updateArrowsForShape === 'function') {\n window.__updateArrowsForShape(this);\n }\n }\n\n selectStroke() {\n this.isSelected = true;\n this.draw();\n // Show sidebar and update it with current stroke properties\n disableAllSideBars();\n paintBrushSideBar.classList.remove(\"hidden\");\n if (window.__showSidebarForShape) window.__showSidebarForShape('freehandStroke');\n this.updateSidebar();\n }\n\n deselectStroke() {\n this.isSelected = false;\n this.anchors = [];\n this.rotationAnchor = null;\n this.draw();\n }\n\n removeSelection() {\n this.anchors.forEach(anchor => {\n if (anchor.parentNode === this.group) {\n this.group.removeChild(anchor);\n }\n });\n if (this.rotationAnchor && this.rotationAnchor.parentNode === this.group) {\n this.group.removeChild(this.rotationAnchor);\n }\n if (this.rotationLine && this.rotationLine.parentNode === this.group) {\n this.group.removeChild(this.rotationLine);\n }\n if (this.selectionOutline && this.selectionOutline.parentNode === this.group) {\n this.group.removeChild(this.selectionOutline);\n }\n this.anchors = [];\n this.rotationAnchor = null;\n this.rotationLine = null;\n this.selectionOutline = null;\n this.isSelected = false;\n }\n\n // No-op: React sidebar handles UI updates via Zustand store\n updateSidebar() {}\n\n contains(x, y) {\n // Account for pending move offset (during drag, points aren't updated yet)\n const ox = this._moveOffsetX || 0;\n const oy = this._moveOffsetY || 0;\n const bbX = this.boundingBox.x + ox;\n const bbY = this.boundingBox.y + oy;\n const centerX = bbX + this.boundingBox.width / 2;\n const centerY = bbY + this.boundingBox.height / 2;\n\n // Adjust for rotation\n const dx = x - centerX;\n const dy = y - centerY;\n\n const angleRad = -this.rotation * Math.PI / 180;\n const rotatedX = dx * Math.cos(angleRad) - dy * Math.sin(angleRad) + centerX;\n const rotatedY = dx * Math.sin(angleRad) + dy * Math.cos(angleRad) + centerY;\n\n if (this.options.closedFill && this.points.length >= 3) {\n const localX = rotatedX - ox;\n const localY = rotatedY - oy;\n let inside = false;\n for (let i = 0, j = this.points.length - 1; i < this.points.length; j = i++) {\n const xi = this.points[i][0], yi = this.points[i][1];\n const xj = this.points[j][0], yj = this.points[j][1];\n const crosses = ((yi > localY) !== (yj > localY))\n && (localX < (xj - xi) * (localY - yi) / ((yj - yi) || Number.EPSILON) + xi);\n if (crosses) inside = !inside;\n }\n return inside;\n }\n\n return rotatedX >= bbX &&\n rotatedX <= bbX + this.boundingBox.width &&\n rotatedY >= bbY &&\n rotatedY <= bbY + this.boundingBox.height;\n }\n\n isNearAnchor(x, y) {\n if (!this.isSelected) return null;\n const buffer = 10;\n const anchorSize = 10 / currentZoom;\n\n // Account for pending move offset\n const ox = this._moveOffsetX || 0;\n const oy = this._moveOffsetY || 0;\n\n // Transform the input coordinates to account for rotation\n const centerX = this.boundingBox.x + ox + this.boundingBox.width / 2;\n const centerY = this.boundingBox.y + oy + this.boundingBox.height / 2;\n\n // Rotate the mouse coordinates to the shape's local coordinate system\n const angleRad = -this.rotation * Math.PI / 180;\n const dx = x - centerX;\n const dy = y - centerY;\n const localX = dx * Math.cos(angleRad) - dy * Math.sin(angleRad) + centerX;\n const localY = dx * Math.sin(angleRad) + dy * Math.cos(angleRad) + centerY;\n\n // Check resize anchors in local space\n const expandedX = this.boundingBox.x + ox - this.selectionPadding;\n const expandedY = this.boundingBox.y + oy - this.selectionPadding;\n const expandedWidth = this.boundingBox.width + 2 * this.selectionPadding;\n const expandedHeight = this.boundingBox.height + 2 * this.selectionPadding;\n \n const anchorPositions = [\n { x: expandedX, y: expandedY }, // top-left\n { x: expandedX + expandedWidth, y: expandedY }, // top-right\n { x: expandedX, y: expandedY + expandedHeight }, // bottom-left\n { x: expandedX + expandedWidth, y: expandedY + expandedHeight }, // bottom-right\n { x: expandedX + expandedWidth / 2, y: expandedY }, // top-center\n { x: expandedX + expandedWidth / 2, y: expandedY + expandedHeight }, // bottom-center\n { x: expandedX, y: expandedY + expandedHeight / 2 }, // left-center\n { x: expandedX + expandedWidth, y: expandedY + expandedHeight / 2 } // right-center\n ];\n\n for (let i = 0; i < anchorPositions.length; i++) {\n const anchor = anchorPositions[i];\n const distance = Math.sqrt(Math.pow(localX - anchor.x, 2) + Math.pow(localY - anchor.y, 2));\n if (distance <= anchorSize / 2 + buffer) {\n return { type: 'resize', index: i };\n }\n }\n \n // Check rotation anchor (this one stays in world coordinates)\n if (this.rotationAnchor) {\n const rotationX = parseFloat(this.rotationAnchor.getAttribute('cx'));\n const rotationY = parseFloat(this.rotationAnchor.getAttribute('cy'));\n const distance = Math.sqrt(Math.pow(x - rotationX, 2) + Math.pow(y - rotationY, 2));\n if (distance <= anchorSize / 2 + buffer) {\n return { type: 'rotate' };\n }\n }\n \n return null;\n}\n\n rotate(angle) {\n this.rotation = angle;\n // If anchors exist, update their cursors for the new rotation\n if (this.isSelected && this.anchors.length > 0) {\n const cursors = ['nw-resize', 'ne-resize', 'sw-resize', 'se-resize', 'n-resize', 's-resize', 'w-resize', 'e-resize'];\n this.anchors.forEach((anchor, i) => {\n if (anchor) {\n const originalCursor = cursors[i];\n const rotatedCursor = this.getRotatedCursor(originalCursor, this.rotation);\n anchor.style.cursor = rotatedCursor;\n }\n });\n }\n}\n\n addAnchors() {\n const anchorSize = 10 / currentZoom;\n const anchorStrokeWidth = 2 / currentZoom;\n \n const expandedX = this.boundingBox.x - this.selectionPadding;\n const expandedY = this.boundingBox.y - this.selectionPadding;\n const expandedWidth = this.boundingBox.width + 2 * this.selectionPadding;\n const expandedHeight = this.boundingBox.height + 2 * this.selectionPadding;\n \n const positions = [\n { x: expandedX, y: expandedY, cursor: 'nw-resize' }, // top-left\n { x: expandedX + expandedWidth, y: expandedY, cursor: 'ne-resize' }, // top-right\n { x: expandedX, y: expandedY + expandedHeight, cursor: 'sw-resize' }, // bottom-left\n { x: expandedX + expandedWidth, y: expandedY + expandedHeight, cursor: 'se-resize' }, // bottom-right\n { x: expandedX + expandedWidth / 2, y: expandedY, cursor: 'n-resize' }, // top-center\n { x: expandedX + expandedWidth / 2, y: expandedY + expandedHeight, cursor: 's-resize' }, // bottom-center\n { x: expandedX, y: expandedY + expandedHeight / 2, cursor: 'w-resize' }, // left-center\n { x: expandedX + expandedWidth, y: expandedY + expandedHeight / 2, cursor: 'e-resize' } // right-center\n ];\n \n // Create resize anchors\n positions.forEach((pos, i) => {\n const anchor = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n anchor.setAttribute('x', pos.x - anchorSize / 2);\n anchor.setAttribute('y', pos.y - anchorSize / 2);\n anchor.setAttribute('width', anchorSize);\n anchor.setAttribute('height', anchorSize);\n anchor.setAttribute('class', 'anchor');\n anchor.setAttribute('data-index', i);\n anchor.setAttribute('fill', '#121212');\n anchor.setAttribute('stroke', '#5B57D1');\n anchor.setAttribute('stroke-width', anchorStrokeWidth);\n anchor.setAttribute('vector-effect', 'non-scaling-stroke');\n\n // Set proper cursor for each anchor direction, accounting for rotation\n const rotatedCursor = this.getRotatedCursor(pos.cursor, this.rotation);\n anchor.style.cursor = rotatedCursor;\n anchor.style.pointerEvents = 'all';\n \n this.group.appendChild(anchor);\n this.anchors[i] = anchor;\n });\n\n // Create rotation anchor\n const rotationAnchorDistance = 30 / currentZoom;\n const rotationX = expandedX + expandedWidth / 2;\n const rotationY = expandedY - rotationAnchorDistance;\n \n const rotationAnchor = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n rotationAnchor.setAttribute('cx', rotationX);\n rotationAnchor.setAttribute('cy', rotationY);\n rotationAnchor.setAttribute('r', anchorSize / 2);\n rotationAnchor.setAttribute('fill', '#121212');\n rotationAnchor.setAttribute('stroke', '#5B57D1');\n rotationAnchor.setAttribute('stroke-width', anchorStrokeWidth);\n rotationAnchor.setAttribute('vector-effect', 'non-scaling-stroke');\n rotationAnchor.setAttribute('class', 'rotation-anchor');\n rotationAnchor.style.cursor = 'grab';\n rotationAnchor.style.pointerEvents = 'all';\n \n this.group.appendChild(rotationAnchor);\n registerRotationAnchor(rotationAnchor, { radius: 5, edgeY: expandedY });\n this.rotationAnchor = rotationAnchor;\n\n // Create selection outline\n const outlinePoints = [\n [expandedX, expandedY],\n [expandedX + expandedWidth, expandedY],\n [expandedX + expandedWidth, expandedY + expandedHeight],\n [expandedX, expandedY + expandedHeight],\n [expandedX, expandedY]\n ];\n \n const outline = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');\n outline.setAttribute('points', outlinePoints.map(p => p.join(',')).join(' '));\n outline.setAttribute('fill', 'none');\n outline.setAttribute('stroke', '#5B57D1');\n outline.setAttribute('stroke-width', 1.5);\n outline.setAttribute('vector-effect', 'non-scaling-stroke');\n outline.setAttribute('stroke-dasharray', '4 2');\n outline.setAttribute('style', 'pointer-events: none;');\n this.group.appendChild(outline);\n this.selectionOutline = outline;\n\n // Add line from rotation anchor to shape\n const rotationLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n rotationLine.setAttribute('x1', rotationX);\n rotationLine.setAttribute('y1', rotationY);\n rotationLine.setAttribute('x2', expandedX + expandedWidth / 2);\n rotationLine.setAttribute('y2', expandedY);\n rotationLine.setAttribute('stroke', '#5B57D1');\n rotationLine.setAttribute('stroke-width', 1);\n rotationLine.setAttribute('vector-effect', 'non-scaling-stroke');\n rotationLine.setAttribute('stroke-dasharray', '2 2');\n rotationLine.setAttribute('style', 'pointer-events: none;');\n this.group.appendChild(rotationLine);\n this.rotationLine = rotationLine;\n\n // Show sidebar when anchors are added (when shape is selected)\n disableAllSideBars();\n paintBrushSideBar.classList.remove(\"hidden\");\n if (window.__showSidebarForShape) window.__showSidebarForShape('freehandStroke');\n this.updateSidebar();\n}\n\ngetRotatedCursor(direction, angle) {\n // Normalize angle to 0-360\n const normalizedAngle = ((angle % 360) + 360) % 360;\n \n // Map of cursor directions\n const cursors = ['n-resize', 'ne-resize', 'e-resize', 'se-resize', 's-resize', 'sw-resize', 'w-resize', 'nw-resize'];\n const directionMap = {\n 'n-resize': 0,\n 'ne-resize': 1,\n 'e-resize': 2,\n 'se-resize': 3,\n 's-resize': 4,\n 'sw-resize': 5,\n 'w-resize': 6,\n 'nw-resize': 7\n };\n \n if (!(direction in directionMap)) return direction;\n \n // Calculate how many 45-degree increments to rotate\n const rotationSteps = Math.round(normalizedAngle / 45);\n const currentIndex = directionMap[direction];\n const newIndex = (currentIndex + rotationSteps) % 8;\n \n return cursors[newIndex];\n}\n\n updatePosition(anchorIndex, newX, newY) {\n const centerX = this.boundingBox.x + this.boundingBox.width / 2;\n const centerY = this.boundingBox.y + this.boundingBox.height / 2;\n \n // Transform new coordinates to local space (accounting for rotation)\n const angleRad = -this.rotation * Math.PI / 180;\n const dx = newX - centerX;\n const dy = newY - centerY;\n const localX = dx * Math.cos(angleRad) - dy * Math.sin(angleRad) + centerX;\n const localY = dx * Math.sin(angleRad) + dy * Math.cos(angleRad) + centerY;\n \n // Calculate scale factors based on anchor movement in local space\n const expandedX = this.boundingBox.x - this.selectionPadding;\n const expandedY = this.boundingBox.y - this.selectionPadding;\n const expandedWidth = this.boundingBox.width + 2 * this.selectionPadding;\n const expandedHeight = this.boundingBox.height + 2 * this.selectionPadding;\n \n let scaleX = 1, scaleY = 1;\n switch(anchorIndex) {\n case 0: // top-left\n scaleX = (centerX - localX) / (centerX - expandedX);\n scaleY = (centerY - localY) / (centerY - expandedY);\n break;\n case 1: // top-right\n scaleX = (localX - centerX) / (expandedX + expandedWidth - centerX);\n scaleY = (centerY - localY) / (centerY - expandedY);\n break;\n case 2: // bottom-left\n scaleX = (centerX - localX) / (centerX - expandedX);\n scaleY = (localY - centerY) / (expandedY + expandedHeight - centerY);\n break;\n case 3: // bottom-right\n scaleX = (localX - centerX) / (expandedX + expandedWidth - centerX);\n scaleY = (localY - centerY) / (expandedY + expandedHeight - centerY);\n break;\n case 4: // top-center\n scaleY = (centerY - localY) / (centerY - expandedY);\n break;\n case 5: // bottom-center\n scaleY = (localY - centerY) / (expandedY + expandedHeight - centerY);\n break;\n case 6: // left-center\n scaleX = (centerX - localX) / (centerX - expandedX);\n break;\n case 7: // right-center\n scaleX = (localX - centerX) / (expandedX + expandedWidth - centerX);\n break;\n }\n \n // Prevent negative scaling\n scaleX = Math.max(0.1, Math.abs(scaleX));\n scaleY = Math.max(0.1, Math.abs(scaleY));\n \n // Apply scaling to all points relative to center\n this.points = this.points.map(point => {\n const relX = point[0] - centerX;\n const relY = point[1] - centerY;\n return [\n centerX + relX * scaleX,\n centerY + relY * scaleY,\n point[2] || 0.5\n ];\n });\n \n this.draw();\n}\n}\n\nexport { FreehandStroke };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
cleanupAttachments,
|
|
7
7
|
updateAttachedArrows
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-X5ENBMGL.js";
|
|
9
9
|
import {
|
|
10
10
|
pushCreateAction,
|
|
11
11
|
pushDeleteAction,
|
|
12
12
|
pushFrameAttachmentAction,
|
|
13
13
|
pushTransformAction
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-VZX55VQL.js";
|
|
15
15
|
|
|
16
16
|
// src/tools/iconTool.js
|
|
17
17
|
var isDraggingIcon = false;
|
|
@@ -961,4 +961,4 @@ export {
|
|
|
961
961
|
startDrag,
|
|
962
962
|
stopDrag
|
|
963
963
|
};
|
|
964
|
-
//# sourceMappingURL=chunk-
|
|
964
|
+
//# sourceMappingURL=chunk-O7KXLFZN.js.map
|
|
@@ -10,14 +10,14 @@ import {
|
|
|
10
10
|
setCodeLanguage,
|
|
11
11
|
updateCodeBackground,
|
|
12
12
|
wrapCodeElement
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-DODPOWNX.js";
|
|
14
14
|
import {
|
|
15
15
|
registerRotationAnchor
|
|
16
16
|
} from "./chunk-PAKA6HUX.js";
|
|
17
17
|
import {
|
|
18
18
|
cleanupAttachments,
|
|
19
19
|
updateAttachedArrows
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-X5ENBMGL.js";
|
|
21
21
|
import {
|
|
22
22
|
pushCreateAction,
|
|
23
23
|
pushDeleteActionWithAttachments,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
pushTransformAction,
|
|
27
27
|
setTextReferences,
|
|
28
28
|
updateSelectedElement
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-VZX55VQL.js";
|
|
30
30
|
|
|
31
31
|
// src/tools/textTool.js
|
|
32
32
|
function getThemeStroke() {
|
|
@@ -1516,4 +1516,4 @@ export {
|
|
|
1516
1516
|
handleTextMouseUp,
|
|
1517
1517
|
updateCodeToggleForShape
|
|
1518
1518
|
};
|
|
1519
|
-
//# sourceMappingURL=chunk-
|
|
1519
|
+
//# sourceMappingURL=chunk-RK3NVAER.js.map
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import {
|
|
3
|
+
canvasToLocal,
|
|
4
|
+
localToCanvas
|
|
5
|
+
} from "./chunk-6AIFXYV6.js";
|
|
2
6
|
import {
|
|
3
7
|
registerRotationAnchor
|
|
4
8
|
} from "./chunk-PAKA6HUX.js";
|
|
@@ -558,16 +562,15 @@ var Rectangle = class {
|
|
|
558
562
|
// Helper to check if a point is near an anchor
|
|
559
563
|
isNearAnchor(x, y) {
|
|
560
564
|
if (!this.isSelected) return null;
|
|
561
|
-
const
|
|
562
|
-
const
|
|
565
|
+
const zoom = window.currentZoom || 1;
|
|
566
|
+
const buffer = 10 / zoom;
|
|
567
|
+
const anchorSize = 10 / zoom;
|
|
568
|
+
const transform = { x: this.x, y: this.y, rotation: this.rotation, centerX: this.width / 2, centerY: this.height / 2 };
|
|
563
569
|
for (let i = 0; i < this.anchors.length; i++) {
|
|
564
570
|
const anchor = this.anchors[i];
|
|
565
571
|
const anchorLocalX = parseFloat(anchor.getAttribute("x")) + anchorSize / 2;
|
|
566
572
|
const anchorLocalY = parseFloat(anchor.getAttribute("y")) + anchorSize / 2;
|
|
567
|
-
const
|
|
568
|
-
svgPoint.x = anchorLocalX;
|
|
569
|
-
svgPoint.y = anchorLocalY;
|
|
570
|
-
const transformedPoint = svgPoint.matrixTransform(this.group.getCTM());
|
|
573
|
+
const transformedPoint = localToCanvas({ x: anchorLocalX, y: anchorLocalY }, transform);
|
|
571
574
|
const anchorLeft = transformedPoint.x - anchorSize / 2 - buffer;
|
|
572
575
|
const anchorRight = transformedPoint.x + anchorSize / 2 + buffer;
|
|
573
576
|
const anchorTop = transformedPoint.y - anchorSize / 2 - buffer;
|
|
@@ -579,10 +582,7 @@ var Rectangle = class {
|
|
|
579
582
|
if (this.rotationAnchor) {
|
|
580
583
|
const rotateAnchorLocalX = parseFloat(this.rotationAnchor.getAttribute("cx"));
|
|
581
584
|
const rotateAnchorLocalY = parseFloat(this.rotationAnchor.getAttribute("cy"));
|
|
582
|
-
const
|
|
583
|
-
svgPoint.x = rotateAnchorLocalX;
|
|
584
|
-
svgPoint.y = rotateAnchorLocalY;
|
|
585
|
-
const transformedPoint = svgPoint.matrixTransform(this.group.getCTM());
|
|
585
|
+
const transformedPoint = localToCanvas({ x: rotateAnchorLocalX, y: rotateAnchorLocalY }, transform);
|
|
586
586
|
const rotateAnchorRadius = parseFloat(this.rotationAnchor.getAttribute("r"));
|
|
587
587
|
const distSq = (x - transformedPoint.x) ** 2 + (y - transformedPoint.y) ** 2;
|
|
588
588
|
if (distSq <= (rotateAnchorRadius + buffer) ** 2) {
|
|
@@ -622,15 +622,10 @@ var Rectangle = class {
|
|
|
622
622
|
hoveredFrame = targetFrame;
|
|
623
623
|
}
|
|
624
624
|
updatePosition(anchorIndex, newMouseX, newMouseY) {
|
|
625
|
-
const CTM = this.group.getCTM();
|
|
626
|
-
if (!CTM) return;
|
|
627
|
-
const inverseCTM = CTM.inverse();
|
|
628
|
-
const svgPoint = svg.createSVGPoint();
|
|
629
|
-
svgPoint.x = newMouseX;
|
|
630
|
-
svgPoint.y = newMouseY;
|
|
631
|
-
const localMouse = svgPoint.matrixTransform(inverseCTM);
|
|
632
625
|
const oldW = this.width;
|
|
633
626
|
const oldH = this.height;
|
|
627
|
+
const transform = { x: this.x, y: this.y, rotation: this.rotation, centerX: oldW / 2, centerY: oldH / 2 };
|
|
628
|
+
const localMouse = canvasToLocal({ x: newMouseX, y: newMouseY }, transform);
|
|
634
629
|
let fixedOldX, fixedOldY, rawW, rawH;
|
|
635
630
|
switch (anchorIndex) {
|
|
636
631
|
case 0:
|
|
@@ -682,10 +677,7 @@ var Rectangle = class {
|
|
|
682
677
|
rawH = oldH;
|
|
683
678
|
break;
|
|
684
679
|
}
|
|
685
|
-
const
|
|
686
|
-
fp.x = fixedOldX;
|
|
687
|
-
fp.y = fixedOldY;
|
|
688
|
-
const fixedWorld = fp.matrixTransform(CTM);
|
|
680
|
+
const fixedWorld = localToCanvas({ x: fixedOldX, y: fixedOldY }, transform);
|
|
689
681
|
const newW = Math.abs(rawW);
|
|
690
682
|
const newH = Math.abs(rawH);
|
|
691
683
|
const fixedNewX = fixedOldX === 0 ? rawW >= 0 ? 0 : newW : rawW >= 0 ? newW : 0;
|
|
@@ -728,4 +720,4 @@ var Rectangle = class {
|
|
|
728
720
|
export {
|
|
729
721
|
Rectangle
|
|
730
722
|
};
|
|
731
|
-
//# sourceMappingURL=chunk-
|
|
723
|
+
//# sourceMappingURL=chunk-VZPH7OAM.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/shapes/Rectangle.js"],
|
|
4
|
+
"sourcesContent": ["/* eslint-disable */\nimport { registerRotationAnchor } from '../core/ScreenSpaceControls.js';\nimport { canvasToLocal, localToCanvas } from '../core/CanvasSpace.js';\n// Rectangle shape class - extracted from drawSquare.js\n// Depends on globals: svg, shapes, rough, currentShape, currentZoom, rc\n\n// Create local rc from globals; tool-state vars default to false\nconst rc = rough.svg(svg);\nlet isDraggingShapeSquare = false;\nlet isResizingShapeSquare = false;\nlet isRotatingShapeSquare = false;\nlet hoveredFrame = null;\nconst SquarecolorOptions = document.querySelectorAll(\".squareStrokeSpan\");\nconst backgroundColorOptionsSquare = document.querySelectorAll(\".squareBackgroundSpan\");\nconst fillStyleOptions = document.querySelectorAll(\".squareFillStyleSpan\");\nconst squareStrokeThicknessValue = document.querySelectorAll(\".squareStrokeThickSpan\");\nconst squareOutlineStyleValue = document.querySelectorAll(\".squareOutlineStyle\");\n// Depends on globals: squareStrokecolor, squareBackgroundColor, squareFillStyleValue, squareStrokeThicknes, squareOutlineStyle\n// Depends on globals: isDraggingShapeSquare, isResizingShapeSquare, isRotatingShapeSquare\n// Depends on globals: squareSideBar, disableAllSideBars\n// Depends on DOM query: SquarecolorOptions, backgroundColorOptionsSquare, fillStyleOptions, squareStrokeThicknessValue, squareOutlineStyleValue\n\nclass Rectangle {\n constructor(x, y, width, height, options = {}) {\n this.x = x;\n this.y = y;\n this.width = width;\n this.height = height;\n this.options = {\n roughness: 1.5,\n stroke: \"#fff\",\n strokeWidth: 2,\n fill: \"transparent\",\n fillStyle: \"none\",\n strokeDasharray: \"\",\n ...options\n };\n this.element = null;\n this.isSelected = false;\n this.rotation = 0;\n this.group = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n this.anchors = [];\n this.rotationAnchor = null;\n this.selectionPadding = 8;\n this.selectionOutline = null;\n this.shapeName = 'rectangle';\n this.shapeID = `rectangle-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n this.group.setAttribute('id', this.shapeID);\n\n // Embedded label support\n this.label = options.label || '';\n this.labelElement = null;\n this.labelColor = options.labelColor || '#e0e0e0';\n this.labelFontSize = options.labelFontSize || 14;\n this.labelBg = options.labelBg !== false; // set labelBg:false to render plain text with no pill backdrop\n this._isEditingLabel = false;\n this._hitArea = null;\n this._labelBg = null;\n\n // Shading / gradient support for research paper style diagrams\n this.shadeColor = options.shadeColor || null;\n this.shadeOpacity = options.shadeOpacity !== undefined ? options.shadeOpacity : 0.15;\n this.shadeDirection = options.shadeDirection || 'bottom'; // 'top' | 'bottom' | 'left' | 'right'\n this._shadeRect = null;\n this._shadeGradient = null;\n\n if (!this.group.parentNode) {\n svg.appendChild(this.group);\n }\n this._lastDrawn = {\n width: null,\n height: null,\n options: null\n };\n this.isBeingDrawn = false;\n this._setupLabelDblClick();\n this.draw();\n }\n draw() {\n const childrenToRemove = [];\n const preserveSet = this._skipAnchors ? new Set([...this.anchors, this.selectionOutline, this.rotationAnchor].filter(Boolean)) : null;\n for (let i = 0; i < this.group.children.length; i++) {\n const child = this.group.children[i];\n if (child !== this.element && child !== this.labelElement && child !== this._hitArea && child !== this._labelBg && child !== this._shadeRect) {\n if (preserveSet && preserveSet.has(child)) continue;\n childrenToRemove.push(child);\n }\n }\n childrenToRemove.forEach(child => this.group.removeChild(child));\n\n const optionsString = JSON.stringify(this.options);\n const isInitialDraw = this.element === null;\n const optionsChanged = optionsString !== this._lastDrawn.options;\n const sizeChanged = this.width !== this._lastDrawn.width || this.height !== this._lastDrawn.height;\n\n // Only regenerate rough element if it's not being actively drawn OR if options changed OR initial draw\n if (isInitialDraw || optionsChanged || (!this.isBeingDrawn && sizeChanged)) {\n if (this.element && this.element.parentNode === this.group) {\n this.group.removeChild(this.element);\n }\n const roughRect = rc.rectangle(0, 0, this.width, this.height, this.options);\n this.element = roughRect;\n this.group.appendChild(roughRect);\n\n // Cache the values\n this._lastDrawn.width = this.width;\n this._lastDrawn.height = this.height;\n this._lastDrawn.options = optionsString;\n }\n\n // Hit area for dblclick detection (transparent rect that captures pointer events)\n if (!this._hitArea) {\n this._hitArea = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n this._hitArea.setAttribute('fill', 'transparent');\n this._hitArea.setAttribute('stroke', 'none');\n this._hitArea.setAttribute('style', 'pointer-events: all;');\n this.group.insertBefore(this._hitArea, this.group.firstChild);\n }\n this._hitArea.setAttribute('x', 0);\n this._hitArea.setAttribute('y', 0);\n this._hitArea.setAttribute('width', this.width);\n this._hitArea.setAttribute('height', this.height);\n\n // Shading / gradient overlay\n this._updateShade();\n\n // Update embedded label\n this._updateLabelElement();\n\n const rotateCenterX = this.width / 2;\n const rotateCenterY = this.height / 2;\n this.group.setAttribute('transform', `translate(${this.x}, ${this.y}) rotate(${this.rotation}, ${rotateCenterX}, ${rotateCenterY})`);\n\n if (this.isSelected) {\n if (this._skipAnchors) {\n this.updateSelectionControls();\n } else {\n this.addAnchors();\n }\n }\n if (!this.group.parentNode) {\n this.updateAttachedArrows();\n svg.appendChild(this.group);\n }\n }\n\n _updateShade() {\n if (!this.shadeColor) {\n if (this._shadeRect && this._shadeRect.parentNode === this.group) {\n this.group.removeChild(this._shadeRect);\n this._shadeRect = null;\n }\n if (this._shadeGradient && this._shadeGradient.parentNode) {\n this._shadeGradient.parentNode.removeChild(this._shadeGradient);\n this._shadeGradient = null;\n }\n return;\n }\n\n // Create or update gradient in SVG defs\n let defs = svg.querySelector('defs');\n if (!defs) {\n defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\n svg.appendChild(defs);\n }\n\n const gradId = `shade-${this.shapeID}`;\n if (!this._shadeGradient) {\n this._shadeGradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient');\n this._shadeGradient.setAttribute('id', gradId);\n defs.appendChild(this._shadeGradient);\n }\n\n // Direction mapping\n const dirs = {\n top: { x1: '0%', y1: '0%', x2: '0%', y2: '100%' },\n bottom: { x1: '0%', y1: '100%', x2: '0%', y2: '0%' },\n left: { x1: '0%', y1: '0%', x2: '100%', y2: '0%' },\n right: { x1: '100%', y1: '0%', x2: '0%', y2: '0%' },\n };\n const d = dirs[this.shadeDirection] || dirs.bottom;\n this._shadeGradient.setAttribute('x1', d.x1);\n this._shadeGradient.setAttribute('y1', d.y1);\n this._shadeGradient.setAttribute('x2', d.x2);\n this._shadeGradient.setAttribute('y2', d.y2);\n\n // Rebuild stops\n while (this._shadeGradient.firstChild) this._shadeGradient.removeChild(this._shadeGradient.firstChild);\n const stop1 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\n stop1.setAttribute('offset', '0%');\n stop1.setAttribute('stop-color', this.shadeColor);\n stop1.setAttribute('stop-opacity', this.shadeOpacity);\n const stop2 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\n stop2.setAttribute('offset', '100%');\n stop2.setAttribute('stop-color', this.shadeColor);\n stop2.setAttribute('stop-opacity', '0');\n this._shadeGradient.appendChild(stop1);\n this._shadeGradient.appendChild(stop2);\n\n // Create or update shade rect\n if (!this._shadeRect) {\n this._shadeRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n this._shadeRect.setAttribute('pointer-events', 'none');\n }\n this._shadeRect.setAttribute('x', 0);\n this._shadeRect.setAttribute('y', 0);\n this._shadeRect.setAttribute('width', this.width);\n this._shadeRect.setAttribute('height', this.height);\n this._shadeRect.setAttribute('fill', `url(#${gradId})`);\n this._shadeRect.setAttribute('rx', 2);\n\n // Insert after rough element\n if (this._shadeRect.parentNode === this.group) this.group.removeChild(this._shadeRect);\n if (this.element && this.element.nextSibling) {\n this.group.insertBefore(this._shadeRect, this.element.nextSibling);\n } else {\n this.group.appendChild(this._shadeRect);\n }\n }\n\n _updateLabelElement() {\n if (!this.label) {\n // Remove label element if label is empty\n if (this.labelElement && this.labelElement.parentNode === this.group) {\n this.group.removeChild(this.labelElement);\n this.labelElement = null;\n }\n if (this._labelBg && this._labelBg.parentNode === this.group) {\n this.group.removeChild(this._labelBg);\n this._labelBg = null;\n }\n return;\n }\n\n if (!this.labelElement) {\n this.labelElement = document.createElementNS('http://www.w3.org/2000/svg', 'text');\n this.labelElement.setAttribute('class', 'shape-label');\n this.labelElement.setAttribute('pointer-events', 'none');\n }\n\n // Position at center of rectangle\n this.labelElement.setAttribute('x', this.width / 2);\n this.labelElement.setAttribute('y', this.height / 2);\n this.labelElement.setAttribute('text-anchor', 'middle');\n this.labelElement.setAttribute('dominant-baseline', 'central');\n this.labelElement.setAttribute('fill', this.labelColor);\n this.labelElement.setAttribute('font-size', this.labelFontSize);\n this.labelElement.setAttribute('font-family', 'lixFont, sans-serif');\n this.labelElement.textContent = this.label;\n\n // Background padding rect behind text (like arrows have) \u2014 skippable\n // via labelBg:false for dense multi-row content (e.g. mermaid ER\n // attribute rows) where a pill backdrop looks out of place and\n // doesn't match the SVG preview.\n if (!this.labelBg) {\n if (this._labelBg && this._labelBg.parentNode === this.group) {\n this.group.removeChild(this._labelBg);\n this._labelBg = null;\n }\n if (this.labelElement.parentNode === this.group) this.group.removeChild(this.labelElement);\n this.group.appendChild(this.labelElement);\n return;\n }\n const canvasBg = window.getComputedStyle(svg).backgroundColor || '#000';\n if (!this._labelBg) {\n this._labelBg = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n this._labelBg.setAttribute('pointer-events', 'none');\n }\n this._labelBg.setAttribute('fill', canvasBg);\n const hPadding = 6;\n const vPadding = 2;\n const charWidth = this.labelFontSize * 0.6;\n const bgW = this.label.length * charWidth + hPadding * 2;\n const bgH = this.labelFontSize + vPadding * 2;\n this._labelBg.setAttribute('x', this.width / 2 - bgW / 2);\n this._labelBg.setAttribute('y', this.height / 2 - bgH / 2);\n this._labelBg.setAttribute('width', bgW);\n this._labelBg.setAttribute('height', bgH);\n this._labelBg.setAttribute('rx', 3);\n\n // Re-append bg then text on top\n if (this._labelBg.parentNode === this.group) this.group.removeChild(this._labelBg);\n if (this.labelElement.parentNode === this.group) this.group.removeChild(this.labelElement);\n this.group.appendChild(this._labelBg);\n this.group.appendChild(this.labelElement);\n }\n\n _setupLabelDblClick() {\n this.group.addEventListener('dblclick', (e) => {\n e.stopPropagation();\n e.preventDefault();\n this.startLabelEdit();\n });\n }\n\n startLabelEdit() {\n if (this._isEditingLabel) return;\n this._isEditingLabel = true;\n\n // Hide label element during editing\n if (this.labelElement) {\n this.labelElement.setAttribute('visibility', 'hidden');\n }\n\n // Get shape's screen position via CTM\n const ctm = this.group.getScreenCTM();\n if (!ctm) { this._isEditingLabel = false; return; }\n\n // Map the shape corners to screen coords\n const pt1 = svg.createSVGPoint();\n pt1.x = 0; pt1.y = 0;\n const screenTL = pt1.matrixTransform(ctm);\n const pt2 = svg.createSVGPoint();\n pt2.x = this.width; pt2.y = this.height;\n const screenBR = pt2.matrixTransform(ctm);\n\n const screenW = Math.abs(screenBR.x - screenTL.x);\n const screenH = Math.abs(screenBR.y - screenTL.y);\n const screenX = Math.min(screenTL.x, screenBR.x);\n const screenY = Math.min(screenTL.y, screenBR.y);\n\n // Create HTML overlay\n const overlay = document.createElement('div');\n overlay.className = 'shape-label-editor';\n overlay.style.cssText = `\n position: fixed; z-index: 10000;\n left: ${screenX}px; top: ${screenY}px;\n width: ${screenW}px; height: ${screenH}px;\n display: flex; align-items: center; justify-content: center;\n pointer-events: auto;\n `;\n\n const canvasBg = window.getComputedStyle(svg).backgroundColor || '#000';\n const input = document.createElement('div');\n input.setAttribute('contenteditable', 'true');\n input.style.cssText = `\n max-width: ${screenW - 8}px; min-width: 30px; min-height: 20px;\n background: ${canvasBg}; border: none;\n outline: none; padding: 2px 6px;\n color: ${this.labelColor}; font-size: ${Math.max(12, this.labelFontSize * (screenW / Math.max(this.width, 1)))}px;\n font-family: lixFont, sans-serif; text-align: center;\n white-space: pre-wrap; word-break: break-word;\n cursor: text;\n `;\n if (this.label) {\n input.textContent = this.label;\n } else {\n input.innerHTML = ' ';\n }\n\n overlay.appendChild(input);\n document.body.appendChild(overlay);\n\n // Focus and select all text\n setTimeout(() => {\n input.focus();\n const sel = window.getSelection();\n const range = document.createRange();\n range.selectNodeContents(input);\n sel.removeAllRanges();\n sel.addRange(range);\n }, 10);\n\n const finishEdit = () => {\n const newText = input.textContent.trim().replace(/\\u00A0/g, '');\n this.label = newText;\n this._isEditingLabel = false;\n\n if (overlay.parentNode) overlay.parentNode.removeChild(overlay);\n if (this.labelElement) this.labelElement.setAttribute('visibility', 'visible');\n this.draw();\n };\n\n input.addEventListener('blur', finishEdit);\n input.addEventListener('keydown', (e) => {\n e.stopPropagation();\n if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); input.blur(); }\n if (e.key === 'Escape') { input.textContent = this.label; input.blur(); }\n });\n input.addEventListener('pointerdown', (e) => e.stopPropagation());\n input.addEventListener('pointermove', (e) => e.stopPropagation());\n input.addEventListener('pointerup', (e) => e.stopPropagation());\n }\n\n setLabel(text, color, fontSize) {\n this.label = text || '';\n if (color) this.labelColor = color;\n if (fontSize) this.labelFontSize = fontSize;\n this.draw();\n }\n\n setDrawingState(isDrawing) {\n this.isBeingDrawn = isDrawing;\n }\n\n getRotatedCursor(direction, angle) {\n const directions = ['ns', 'nesw', 'ew', 'nwse'];\n angle = angle % 360;\n if (angle < 0) angle += 360;\n\n const baseDirectionMap = {\n '0': 'nwse', '1': 'nesw', \n '2': 'nesw', '3': 'nwse', \n '4': 'ns', '5': 'ns', \n '6': 'ew', '7': 'ew' \n };\n const baseDirection = baseDirectionMap[direction];\n let effectiveAngle = angle; \n if (baseDirection === 'nesw') {\n effectiveAngle += 45;\n } else if (baseDirection === 'ew') {\n effectiveAngle += 90;\n } else if (baseDirection === 'nwse') {\n effectiveAngle += 135;\n }\n effectiveAngle = effectiveAngle % 360;\n if (effectiveAngle < 0) effectiveAngle += 360;\n const index = Math.round(effectiveAngle / 45) % 4; \n let finalIndex;\n if (effectiveAngle >= 337.5 || effectiveAngle < 22.5) finalIndex = 0; \n else if (effectiveAngle >= 22.5 && effectiveAngle < 67.5) finalIndex = 1; \n else if (effectiveAngle >= 67.5 && effectiveAngle < 112.5) finalIndex = 2; \n else if (effectiveAngle >= 112.5 && effectiveAngle < 157.5) finalIndex = 3;\n else if (effectiveAngle >= 157.5 && effectiveAngle < 202.5) finalIndex = 0; \n else if (effectiveAngle >= 202.5 && effectiveAngle < 247.5) finalIndex = 1; \n else if (effectiveAngle >= 247.5 && effectiveAngle < 292.5) finalIndex = 2; \n else if (effectiveAngle >= 292.5 && effectiveAngle < 337.5) finalIndex = 3; \n else finalIndex = 0; \n return directions[finalIndex];\n }\n addAnchors() {\n const zoom = window.currentZoom || 1;\n const anchorSize = 10 / zoom;\n const anchorStrokeWidth = 2;\n const self = this;\n const expandedX = -this.selectionPadding; \n const expandedY = -this.selectionPadding; \n const expandedWidth = this.width + 2 * this.selectionPadding;\n const expandedHeight = this.height + 2 * this.selectionPadding;\n\n const positions = [\n { x: expandedX, y: expandedY }, \n { x: expandedX + expandedWidth, y: expandedY }, \n { x: expandedX, y: expandedY + expandedHeight }, \n { x: expandedX + expandedWidth, y: expandedY + expandedHeight }, \n { x: expandedX + expandedWidth / 2, y: expandedY }, \n { x: expandedX + expandedWidth / 2, y: expandedY + expandedHeight }, \n { x: expandedX, y: expandedHeight / 2 + expandedY }, \n { x: expandedX + expandedWidth, y: expandedHeight / 2 + expandedY } \n ];\n\n const outlinePoints = [\n [positions[0].x, positions[0].y],\n [positions[1].x, positions[1].y],\n [positions[3].x, positions[3].y],\n [positions[2].x, positions[2].y],\n [positions[0].x, positions[0].y]\n ];\n\n this.anchors.forEach(anchor => {\n if (anchor.parentNode === this.group) {\n this.group.removeChild(anchor);\n }\n });\n if (this.rotationAnchor && this.rotationAnchor.parentNode === this.group) {\n this.group.removeChild(this.rotationAnchor);\n }\n if (this.selectionOutline && this.selectionOutline.parentNode === this.group) {\n this.group.removeChild(this.selectionOutline);\n }\n\n this.anchors = [];\n const anchorDirections = {\n 0: 'nwse', \n 1: 'nesw', \n 2: 'nesw', \n 3: 'nwse', \n 4: 'ns', \n 5: 'ns', \n 6: 'ew', \n 7: 'ew' \n };\n\n positions.forEach((pos, i) => {\n const anchor = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n anchor.setAttribute('x', pos.x - anchorSize / 2);\n anchor.setAttribute('y', pos.y - anchorSize / 2);\n anchor.setAttribute('width', anchorSize);\n anchor.setAttribute('height', anchorSize);\n anchor.setAttribute('class', 'anchor');\n anchor.setAttribute('data-index', i);\n anchor.setAttribute('fill', '#121212');\n anchor.setAttribute('stroke', '#5B57D1');\n anchor.setAttribute('stroke-width', anchorStrokeWidth);\n anchor.setAttribute('vector-effect', 'non-scaling-stroke');\n anchor.setAttribute('style', 'pointer-events: all;');\n\n anchor.addEventListener('mouseover', function () {\n const index = this.getAttribute('data-index');\n const baseDirection = anchorDirections[index];\n const rotatedCursor = self.getRotatedCursor(index, self.rotation); \n svg.style.cursor = rotatedCursor + '-resize';\n });\n\n anchor.addEventListener('mouseout', function () {\n if (!isResizingShapeSquare && !isDraggingShapeSquare && !isRotatingShapeSquare) {\n svg.style.cursor = 'default';\n }\n });\n\n this.group.appendChild(anchor);\n this.anchors[i] = anchor;\n });\n const rotationAnchorPos = { x: expandedX + expandedWidth / 2, y: expandedY - 30 / zoom };\n this.rotationAnchor = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n this.rotationAnchor.setAttribute('cx', rotationAnchorPos.x);\n this.rotationAnchor.setAttribute('cy', rotationAnchorPos.y);\n this.rotationAnchor.setAttribute('r', 8 / zoom);\n this.rotationAnchor.setAttribute('class', 'rotate-anchor');\n this.rotationAnchor.setAttribute('fill', '#121212');\n this.rotationAnchor.setAttribute('stroke', '#5B57D1');\n this.rotationAnchor.setAttribute('stroke-width', anchorStrokeWidth);\n this.rotationAnchor.setAttribute('vector-effect', 'non-scaling-stroke');\n this.rotationAnchor.setAttribute('style', 'pointer-events: all;');\n this.group.appendChild(this.rotationAnchor);\n registerRotationAnchor(this.rotationAnchor, { radius: 8, edgeY: expandedY });\n\n this.rotationAnchor.addEventListener('mouseover', function () {\n if (!isResizingShapeSquare && !isDraggingShapeSquare && !isRotatingShapeSquare) {\n svg.style.cursor = 'grab';\n }\n });\n this.rotationAnchor.addEventListener('mouseout', function () {\n if (!isResizingShapeSquare && !isDraggingShapeSquare && !isRotatingShapeSquare) {\n svg.style.cursor = 'default';\n }\n });\n\n const pointsAttr = outlinePoints.map(p => p.join(',')).join(' ');\n const outline = document.createElementNS('http://www.w3.org/2000/svg', 'polyline');\n outline.setAttribute('points', pointsAttr);\n outline.setAttribute('fill', 'none');\n outline.setAttribute('stroke', '#5B57D1');\n outline.setAttribute('stroke-width', 1.5);\n outline.setAttribute('stroke-dasharray', '4 2');\n outline.setAttribute('vector-effect', 'non-scaling-stroke');\n outline.setAttribute('style', 'pointer-events: none;');\n this.group.appendChild(outline);\n this.selectionOutline = outline;\n\n // Show relevant sidebar\n disableAllSideBars();\n squareSideBar.classList.remove(\"hidden\");\n if (window.__showSidebarForShape) window.__showSidebarForShape('rectangle');\n this.updateSidebar();\n }\n\n updateSelectionControls() {\n if (!this.selectionOutline || this.anchors.length === 0) return;\n\n const zoom = window.currentZoom || 1;\n const anchorSize = 10 / zoom;\n const expandedX = -this.selectionPadding;\n const expandedY = -this.selectionPadding;\n const expandedWidth = this.width + 2 * this.selectionPadding;\n const expandedHeight = this.height + 2 * this.selectionPadding;\n\n const positions = [\n { x: expandedX, y: expandedY },\n { x: expandedX + expandedWidth, y: expandedY },\n { x: expandedX, y: expandedY + expandedHeight },\n { x: expandedX + expandedWidth, y: expandedY + expandedHeight },\n { x: expandedX + expandedWidth / 2, y: expandedY },\n { x: expandedX + expandedWidth / 2, y: expandedY + expandedHeight },\n { x: expandedX, y: expandedHeight / 2 + expandedY },\n { x: expandedX + expandedWidth, y: expandedHeight / 2 + expandedY }\n ];\n\n // Update anchor positions\n positions.forEach((pos, i) => {\n if (this.anchors[i]) {\n this.anchors[i].setAttribute('x', pos.x - anchorSize / 2);\n this.anchors[i].setAttribute('y', pos.y - anchorSize / 2);\n }\n });\n\n // Update outline\n const outlinePoints = [\n [positions[0].x, positions[0].y],\n [positions[1].x, positions[1].y],\n [positions[3].x, positions[3].y],\n [positions[2].x, positions[2].y],\n [positions[0].x, positions[0].y]\n ];\n this.selectionOutline.setAttribute('points', outlinePoints.map(p => p.join(',')).join(' '));\n\n // Update rotation anchor\n if (this.rotationAnchor) {\n this.rotationAnchor.setAttribute('cx', expandedX + expandedWidth / 2);\n this.rotationAnchor.setAttribute('cy', expandedY - 30 / zoom);\n }\n }\n\n removeSelection() {\n // Remove selection elements (anchors, outline, rotation anchor) from the group\n this.anchors.forEach(anchor => {\n if (anchor.parentNode === this.group) {\n this.group.removeChild(anchor);\n }\n });\n if (this.rotationAnchor && this.rotationAnchor.parentNode === this.group) {\n this.group.removeChild(this.rotationAnchor);\n }\n if (this.selectionOutline && this.selectionOutline.parentNode === this.group) {\n this.group.removeChild(this.selectionOutline);\n }\n this.anchors = [];\n this.rotationAnchor = null;\n this.selectionOutline = null;\n this.isSelected = false;\n }\n\n contains(x, y) {\n if (!this.element) return false;\n // x/y are already canvas (viewBox) coordinates. getCTM() operates in\n // viewport coordinates and made hit testing drift after pan/zoom.\n const centerX = this.width / 2;\n const centerY = this.height / 2;\n const angle = -(this.rotation || 0) * Math.PI / 180;\n const translatedX = x - this.x;\n const translatedY = y - this.y;\n const dx = translatedX - centerX;\n const dy = translatedY - centerY;\n const localX = dx * Math.cos(angle) - dy * Math.sin(angle) + centerX;\n const localY = dx * Math.sin(angle) + dy * Math.cos(angle) + centerY;\n const tolerance = 5;\n return localX >= -tolerance && localX <= this.width + tolerance &&\n localY >= -tolerance && localY <= this.height + tolerance;\n }\n\n // Helper to check if a point is near an anchor\n isNearAnchor(x, y) {\n if (!this.isSelected) return null;\n const zoom = window.currentZoom || 1;\n const buffer = 10 / zoom;\n const anchorSize = 10 / zoom;\n const transform = { x: this.x, y: this.y, rotation: this.rotation, centerX: this.width / 2, centerY: this.height / 2 };\n\n // Iterate through anchors\n for (let i = 0; i < this.anchors.length; i++) {\n const anchor = this.anchors[i];\n const anchorLocalX = parseFloat(anchor.getAttribute('x')) + anchorSize / 2;\n const anchorLocalY = parseFloat(anchor.getAttribute('y')) + anchorSize / 2;\n const transformedPoint = localToCanvas({ x: anchorLocalX, y: anchorLocalY }, transform);\n const anchorLeft = transformedPoint.x - anchorSize/2 - buffer;\n const anchorRight = transformedPoint.x + anchorSize/2 + buffer;\n const anchorTop = transformedPoint.y - anchorSize/2 - buffer;\n const anchorBottom = transformedPoint.y + anchorSize/2 + buffer;\n if (x >= anchorLeft && x <= anchorRight && y >= anchorTop && y <= anchorBottom) {\n return { type: 'resize', index: i };\n }\n }\n\n // Check rotation anchor\n if (this.rotationAnchor) {\n const rotateAnchorLocalX = parseFloat(this.rotationAnchor.getAttribute('cx'));\n const rotateAnchorLocalY = parseFloat(this.rotationAnchor.getAttribute('cy'));\n const transformedPoint = localToCanvas({ x: rotateAnchorLocalX, y: rotateAnchorLocalY }, transform);\n const rotateAnchorRadius = parseFloat(this.rotationAnchor.getAttribute('r'));\n const distSq = (x - transformedPoint.x)**2 + (y - transformedPoint.y)**2;\n if (distSq <= (rotateAnchorRadius + buffer)**2) {\n return { type: 'rotate' };\n }\n }\n\n return null;\n }\n\n\nmove(dx, dy) {\n this.x += dx;\n this.y += dy;\n\n // Fast path: just update the transform \u2014 no need to rebuild RoughJS element\n const rotateCenterX = this.width / 2;\n const rotateCenterY = this.height / 2;\n this.group.setAttribute('transform', `translate(${this.x}, ${this.y}) rotate(${this.rotation}, ${rotateCenterX}, ${rotateCenterY})`);\n\n this.updateAttachedArrows();\n\n // Only update frame containment if we're actively dragging the shape itself\n // and not being moved by a parent frame\n if (isDraggingShapeSquare && !this.isBeingMovedByFrame) {\n this.updateFrameContainment();\n }\n}\n\nupdateFrameContainment() {\n // Don't update if we're being moved by a frame\n if (this.isBeingMovedByFrame) return;\n \n let targetFrame = null;\n \n // Find which frame this shape is over\n shapes.forEach(shape => {\n if (shape.shapeName === 'frame' && shape.isShapeInFrame(this)) {\n targetFrame = shape;\n }\n });\n \n // If we have a parent frame and we're being dragged, temporarily remove clipping\n if (this.parentFrame && isDraggingShapeSquare) {\n this.parentFrame.temporarilyRemoveFromFrame(this);\n }\n \n // Update frame highlighting\n if (hoveredFrame && hoveredFrame !== targetFrame) {\n hoveredFrame.removeHighlight();\n }\n \n if (targetFrame && targetFrame !== hoveredFrame) {\n targetFrame.highlightFrame();\n }\n \n hoveredFrame = targetFrame;\n}\n\n updatePosition(anchorIndex, newMouseX, newMouseY) {\n const oldW = this.width;\n const oldH = this.height;\n const transform = { x: this.x, y: this.y, rotation: this.rotation, centerX: oldW / 2, centerY: oldH / 2 };\n const localMouse = canvasToLocal({ x: newMouseX, y: newMouseY }, transform);\n\n // Determine fixed point in old local coords and compute raw new dimensions\n let fixedOldX, fixedOldY, rawW, rawH;\n switch (anchorIndex) {\n case 0: fixedOldX = oldW; fixedOldY = oldH; rawW = oldW - localMouse.x; rawH = oldH - localMouse.y; break;\n case 1: fixedOldX = 0; fixedOldY = oldH; rawW = localMouse.x; rawH = oldH - localMouse.y; break;\n case 2: fixedOldX = oldW; fixedOldY = 0; rawW = oldW - localMouse.x; rawH = localMouse.y; break;\n case 3: fixedOldX = 0; fixedOldY = 0; rawW = localMouse.x; rawH = localMouse.y; break;\n case 4: fixedOldX = 0; fixedOldY = oldH; rawW = oldW; rawH = oldH - localMouse.y; break;\n case 5: fixedOldX = 0; fixedOldY = 0; rawW = oldW; rawH = localMouse.y; break;\n case 6: fixedOldX = oldW; fixedOldY = 0; rawW = oldW - localMouse.x; rawH = oldH; break;\n case 7: fixedOldX = 0; fixedOldY = 0; rawW = localMouse.x; rawH = oldH; break;\n }\n\n // Get world position of the fixed point using current CTM\n const fixedWorld = localToCanvas({ x: fixedOldX, y: fixedOldY }, transform);\n\n // Handle negative dimensions (dragged past opposite edge)\n const newW = Math.abs(rawW);\n const newH = Math.abs(rawH);\n\n // Fixed point in new local coords (flips if dimension went negative)\n const fixedNewX = fixedOldX === 0 ? (rawW >= 0 ? 0 : newW) : (rawW >= 0 ? newW : 0);\n const fixedNewY = fixedOldY === 0 ? (rawH >= 0 ? 0 : newH) : (rawH >= 0 ? newH : 0);\n\n // Solve for new x, y so the fixed corner stays in place\n // Transform: translate(x, y) rotate(\u03B8, newW/2, newH/2)\n const rad = this.rotation * Math.PI / 180;\n const cosR = Math.cos(rad);\n const sinR = Math.sin(rad);\n const ncx = newW / 2;\n const ncy = newH / 2;\n const dx = fixedNewX - ncx;\n const dy = fixedNewY - ncy;\n const rotX = ncx + dx * cosR - dy * sinR;\n const rotY = ncy + dx * sinR + dy * cosR;\n\n this.x = fixedWorld.x - rotX;\n this.y = fixedWorld.y - rotY;\n this.width = newW;\n this.height = newH;\n\n this.updateAttachedArrows();\n }\n\n updateAttachedArrows() {\n shapes.forEach(shape => {\n if (shape && shape.shapeName === 'arrow' && typeof shape.updateAttachments === 'function') {\n \n if ((shape.attachedToStart && shape.attachedToStart.shape === this) ||\n (shape.attachedToEnd && shape.attachedToEnd.shape === this)) {\n shape.updateAttachments();\n }\n }\n });\n } \n\n rotate(angle) {\n angle = angle % 360;\n if (angle < 0) angle += 360;\n this.rotation = angle;\n }\n\n // Method to update the sidebar based on the shape's current options\n // No-op: React sidebar handles UI updates via Zustand store\n updateSidebar() {}\n}\n\nexport { Rectangle };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
// src/core/UndoRedo.js
|
|
4
4
|
var undoStack = [];
|
|
5
5
|
var redoStack = [];
|
|
6
|
+
function beginUndoBatch() {
|
|
7
|
+
return { startIndex: undoStack.length };
|
|
8
|
+
}
|
|
9
|
+
function endUndoBatch(batch, label = "batch") {
|
|
10
|
+
if (!batch || !Number.isInteger(batch.startIndex)) return;
|
|
11
|
+
const startIndex = Math.min(Math.max(batch.startIndex, 0), undoStack.length);
|
|
12
|
+
let actions = undoStack.splice(startIndex);
|
|
13
|
+
if (actions.length === 0) return;
|
|
14
|
+
const groupedAction = actions.length === 1 ? actions[0] : { type: "batch", label, actions };
|
|
15
|
+
undoStack.push(groupedAction);
|
|
16
|
+
redoStack.length = 0;
|
|
17
|
+
notifyCollaboration();
|
|
18
|
+
return groupedAction;
|
|
19
|
+
}
|
|
6
20
|
var selectedElement = null;
|
|
7
21
|
var updateSelectionFeedback = null;
|
|
8
22
|
var svg = null;
|
|
@@ -39,10 +53,31 @@ function pushCreateAction(shape, meta = null) {
|
|
|
39
53
|
function pushDeleteAction(shape, meta = null) {
|
|
40
54
|
const action = { type: "delete", shape };
|
|
41
55
|
if (meta && meta.childSnapshot) action.childSnapshot = meta.childSnapshot;
|
|
56
|
+
if (Number.isInteger(meta?.shapeIndex)) action.shapeIndex = meta.shapeIndex;
|
|
57
|
+
if (meta?.parentFrame) action.parentFrame = meta.parentFrame;
|
|
58
|
+
if (Number.isInteger(meta?.frameIndex)) action.frameIndex = meta.frameIndex;
|
|
42
59
|
undoStack.push(action);
|
|
43
60
|
redoStack.length = 0;
|
|
44
61
|
notifyCollaboration();
|
|
45
62
|
}
|
|
63
|
+
function pushCanvasResetAction(snapshot, restore, reset) {
|
|
64
|
+
if (!snapshot || typeof restore !== "function" || typeof reset !== "function") return;
|
|
65
|
+
undoStack.length = 0;
|
|
66
|
+
redoStack.length = 0;
|
|
67
|
+
undoStack.push({ type: "canvasReset", snapshot, restore, reset });
|
|
68
|
+
}
|
|
69
|
+
function invalidateCanvasResetUndo() {
|
|
70
|
+
for (let index = undoStack.length - 1; index >= 0; index -= 1) {
|
|
71
|
+
if (undoStack[index]?.type === "canvasReset") undoStack.splice(index, 1);
|
|
72
|
+
}
|
|
73
|
+
for (let index = redoStack.length - 1; index >= 0; index -= 1) {
|
|
74
|
+
if (redoStack[index]?.type === "canvasReset") redoStack.splice(index, 1);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function clearUndoHistory() {
|
|
78
|
+
undoStack.length = 0;
|
|
79
|
+
redoStack.length = 0;
|
|
80
|
+
}
|
|
46
81
|
function pushDeleteActionWithAttachments(shape) {
|
|
47
82
|
let affectedArrows = [];
|
|
48
83
|
if (shape.type === "text" || shape.shapeName === "text") {
|
|
@@ -371,6 +406,14 @@ function pushOptionsChangeAction(shape, oldOptions, newOptions = null) {
|
|
|
371
406
|
redoStack.length = 0;
|
|
372
407
|
notifyCollaboration();
|
|
373
408
|
}
|
|
409
|
+
function applyOptionsSnapshot(shape, options) {
|
|
410
|
+
shape.options = { ...options };
|
|
411
|
+
if (shape.shapeName === "frame") {
|
|
412
|
+
shape.fillColor = options.fillColor;
|
|
413
|
+
shape.fillStyle = options.fillStyle;
|
|
414
|
+
}
|
|
415
|
+
shape.draw();
|
|
416
|
+
}
|
|
374
417
|
function refreshSelectionAfterAction() {
|
|
375
418
|
const ms = typeof window !== "undefined" ? window.multiSelection : null;
|
|
376
419
|
if (!ms) return;
|
|
@@ -382,10 +425,50 @@ function refreshSelectionAfterAction() {
|
|
|
382
425
|
console.warn("[UndoRedo] selection refresh failed:", err);
|
|
383
426
|
}
|
|
384
427
|
}
|
|
428
|
+
function restoreDeletedShapeFrame(action) {
|
|
429
|
+
const frame = action.parentFrame;
|
|
430
|
+
const shape = action.shape;
|
|
431
|
+
if (!frame || !shape || typeof frame.addShapeToFrame !== "function") return;
|
|
432
|
+
frame.addShapeToFrame(shape);
|
|
433
|
+
if (Number.isInteger(action.frameIndex) && Array.isArray(frame.containedShapes)) {
|
|
434
|
+
const currentIndex = frame.containedShapes.indexOf(shape);
|
|
435
|
+
if (currentIndex >= 0) frame.containedShapes.splice(currentIndex, 1);
|
|
436
|
+
const targetIndex = Math.min(Math.max(action.frameIndex, 0), frame.containedShapes.length);
|
|
437
|
+
frame.containedShapes.splice(targetIndex, 0, shape);
|
|
438
|
+
const element = shape.group || shape.element;
|
|
439
|
+
const nextShape = frame.containedShapes[targetIndex + 1];
|
|
440
|
+
const nextElement = nextShape?.group || nextShape?.element;
|
|
441
|
+
if (element && frame.clipGroup && nextElement?.parentNode === frame.clipGroup) {
|
|
442
|
+
frame.clipGroup.insertBefore(element, nextElement);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
function detachDeletedShapeFrame(action) {
|
|
447
|
+
const frame = action.parentFrame;
|
|
448
|
+
const shape = action.shape;
|
|
449
|
+
if (frame && shape && typeof frame.removeShapeFromFrame === "function" && shape.parentFrame === frame) {
|
|
450
|
+
frame.removeShapeFromFrame(shape);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
385
453
|
function undo() {
|
|
386
454
|
if (undoStack.length === 0) return;
|
|
387
455
|
const action = undoStack.pop();
|
|
388
456
|
try {
|
|
457
|
+
if (action.type === "batch") {
|
|
458
|
+
for (let index = action.actions.length - 1; index >= 0; index -= 1) {
|
|
459
|
+
undoStack.push(action.actions[index]);
|
|
460
|
+
undo();
|
|
461
|
+
redoStack.pop();
|
|
462
|
+
}
|
|
463
|
+
redoStack.push(action);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
if (action.type === "canvasReset") {
|
|
467
|
+
action.restore(action.snapshot);
|
|
468
|
+
redoStack.push(action);
|
|
469
|
+
notifyCollaboration();
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
389
472
|
if (action.type === "frameTransform") {
|
|
390
473
|
action.shape.x = action.oldPos.x;
|
|
391
474
|
action.shape.y = action.oldPos.y;
|
|
@@ -527,7 +610,10 @@ function undo() {
|
|
|
527
610
|
} else if (action.shape.type === "image") {
|
|
528
611
|
action.shape.restore();
|
|
529
612
|
} else {
|
|
530
|
-
shapes.
|
|
613
|
+
if (shapes.indexOf(action.shape) === -1) {
|
|
614
|
+
const index = Number.isInteger(action.shapeIndex) ? Math.min(Math.max(action.shapeIndex, 0), shapes.length) : shapes.length;
|
|
615
|
+
shapes.splice(index, 0, action.shape);
|
|
616
|
+
}
|
|
531
617
|
if (svg) {
|
|
532
618
|
svg.appendChild(action.shape.group);
|
|
533
619
|
}
|
|
@@ -551,6 +637,7 @@ function undo() {
|
|
|
551
637
|
}
|
|
552
638
|
}
|
|
553
639
|
}
|
|
640
|
+
restoreDeletedShapeFrame(action);
|
|
554
641
|
redoStack.push(action);
|
|
555
642
|
return;
|
|
556
643
|
}
|
|
@@ -760,8 +847,7 @@ function undo() {
|
|
|
760
847
|
action.shape.arrowCurveAmount = action.oldOptions.arrowCurveAmount;
|
|
761
848
|
action.shape.draw();
|
|
762
849
|
} else {
|
|
763
|
-
action.shape
|
|
764
|
-
action.shape.draw();
|
|
850
|
+
applyOptionsSnapshot(action.shape, action.oldOptions);
|
|
765
851
|
}
|
|
766
852
|
redoStack.push(action);
|
|
767
853
|
return;
|
|
@@ -775,6 +861,21 @@ function redo() {
|
|
|
775
861
|
if (redoStack.length === 0) return;
|
|
776
862
|
const action = redoStack.pop();
|
|
777
863
|
try {
|
|
864
|
+
if (action.type === "batch") {
|
|
865
|
+
for (const childAction of action.actions) {
|
|
866
|
+
redoStack.push(childAction);
|
|
867
|
+
redo();
|
|
868
|
+
undoStack.pop();
|
|
869
|
+
}
|
|
870
|
+
undoStack.push(action);
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
if (action.type === "canvasReset") {
|
|
874
|
+
action.reset();
|
|
875
|
+
undoStack.push(action);
|
|
876
|
+
notifyCollaboration();
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
778
879
|
if (action.type === "frameTransform") {
|
|
779
880
|
action.shape.x = action.newPos.x;
|
|
780
881
|
action.shape.y = action.newPos.y;
|
|
@@ -901,6 +1002,7 @@ function redo() {
|
|
|
901
1002
|
return;
|
|
902
1003
|
}
|
|
903
1004
|
if (action.type === "delete") {
|
|
1005
|
+
detachDeletedShapeFrame(action);
|
|
904
1006
|
if (action.shape.type === "text") {
|
|
905
1007
|
if ((action.shape.element || action.shape).parentNode) {
|
|
906
1008
|
(action.shape.element || action.shape).parentNode.removeChild(action.shape.element || action.shape);
|
|
@@ -1145,8 +1247,7 @@ function redo() {
|
|
|
1145
1247
|
action.shape.arrowCurveAmount = action.newOptions.arrowCurveAmount;
|
|
1146
1248
|
action.shape.draw();
|
|
1147
1249
|
} else {
|
|
1148
|
-
action.shape
|
|
1149
|
-
action.shape.draw();
|
|
1250
|
+
applyOptionsSnapshot(action.shape, action.newOptions);
|
|
1150
1251
|
}
|
|
1151
1252
|
undoStack.push(action);
|
|
1152
1253
|
return;
|
|
@@ -1170,6 +1271,9 @@ document.getElementById("undo")?.addEventListener("click", undo);
|
|
|
1170
1271
|
document.getElementById("redo")?.addEventListener("click", redo);
|
|
1171
1272
|
window.pushCreateAction = pushCreateAction;
|
|
1172
1273
|
window.pushDeleteAction = pushDeleteAction;
|
|
1274
|
+
window.pushCanvasResetAction = pushCanvasResetAction;
|
|
1275
|
+
window.invalidateCanvasResetUndo = invalidateCanvasResetUndo;
|
|
1276
|
+
window.clearUndoHistory = clearUndoHistory;
|
|
1173
1277
|
window.pushDeleteActionWithAttachments = pushDeleteActionWithAttachments;
|
|
1174
1278
|
window.pushTransformAction = pushTransformAction;
|
|
1175
1279
|
window.pushOptionsChangeAction = pushOptionsChangeAction;
|
|
@@ -1178,11 +1282,16 @@ window.undo = undo;
|
|
|
1178
1282
|
window.redo = redo;
|
|
1179
1283
|
|
|
1180
1284
|
export {
|
|
1285
|
+
beginUndoBatch,
|
|
1286
|
+
endUndoBatch,
|
|
1181
1287
|
setTextReferences,
|
|
1182
1288
|
getCurrentSelectedElement,
|
|
1183
1289
|
updateSelectedElement,
|
|
1184
1290
|
pushCreateAction,
|
|
1185
1291
|
pushDeleteAction,
|
|
1292
|
+
pushCanvasResetAction,
|
|
1293
|
+
invalidateCanvasResetUndo,
|
|
1294
|
+
clearUndoHistory,
|
|
1186
1295
|
pushDeleteActionWithAttachments,
|
|
1187
1296
|
pushFrameAttachmentAction,
|
|
1188
1297
|
pushCreateActionWithAttachments,
|
|
@@ -1191,4 +1300,4 @@ export {
|
|
|
1191
1300
|
undo,
|
|
1192
1301
|
redo
|
|
1193
1302
|
};
|
|
1194
|
-
//# sourceMappingURL=chunk-
|
|
1303
|
+
//# sourceMappingURL=chunk-VZX55VQL.js.map
|