@elixpo/lixsketch 5.5.19 → 5.5.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/Circle-6POZCUZD.js +9 -0
- package/dist/react/{CopyPaste-JMIXWUUO.js → CopyPaste-FJN7K5LS.js} +43 -14
- package/dist/react/CopyPaste-FJN7K5LS.js.map +7 -0
- package/dist/react/{EventDispatcher-H5EA4KZN.js → EventDispatcher-O7HCQQNM.js} +14 -13
- package/dist/react/{EventDispatcher-H5EA4KZN.js.map → EventDispatcher-O7HCQQNM.js.map} +1 -1
- package/dist/react/Frame-RLSMJJSK.js +11 -0
- package/dist/react/FreehandStroke-U6GYZOM4.js +9 -0
- package/dist/react/{GraphEngine-KQXHNTZQ.js → GraphEngine-MM6ALA2N.js} +105 -148
- package/dist/react/{GraphEngine-KQXHNTZQ.js.map → GraphEngine-MM6ALA2N.js.map} +2 -2
- package/dist/react/IconShape-7OPXAKLK.js +10 -0
- package/dist/react/ImageShape-LRNJQCF3.js +10 -0
- package/dist/react/Line-WWQFBNX5.js +10 -0
- package/dist/react/Rectangle-S7XUKWYD.js +9 -0
- package/dist/react/{SceneSerializer-ARTKPZVR.js → SceneSerializer-GSJR7ZHC.js} +36 -11
- package/dist/react/SceneSerializer-GSJR7ZHC.js.map +7 -0
- package/dist/react/{Selection-YJNZRBON.js → Selection-ZL3G6IAO.js} +5 -4
- package/dist/react/{SketchEngine-ZGYBIZG7.js → SketchEngine-BFLHJPCG.js} +25 -25
- package/dist/react/{UndoRedo-BZ6W4QTV.js → UndoRedo-NL7KLR5B.js} +2 -2
- package/dist/react/{ZoomPan-NYPDJBD5.js → ZoomPan-FAWA5OPS.js} +5 -1
- package/dist/react/ZoomPan-FAWA5OPS.js.map +7 -0
- package/dist/react/{arrowTool-LKFSZKXC.js → arrowTool-CNVGM6RX.js} +3 -3
- package/dist/react/{chunk-RFHMFWVR.js → chunk-2FMFOPGW.js} +5 -6
- package/dist/react/{chunk-RFHMFWVR.js.map → chunk-2FMFOPGW.js.map} +2 -2
- package/dist/react/{chunk-QYNTPZON.js → chunk-2THKDSWW.js} +9 -5
- package/dist/react/chunk-2THKDSWW.js.map +7 -0
- package/dist/react/{chunk-JOPQ27YH.js → chunk-4BLMNGTR.js} +3 -3
- package/dist/react/{chunk-C62SXFBL.js → chunk-4TAS67SL.js} +23 -22
- package/dist/react/chunk-4TAS67SL.js.map +7 -0
- package/dist/react/{chunk-FV3EPR4L.js → chunk-AH4PWNEB.js} +19 -11
- package/dist/react/chunk-AH4PWNEB.js.map +7 -0
- package/dist/react/{chunk-XCJOF6BM.js → chunk-FETTJLCV.js} +5 -1
- package/dist/react/chunk-FETTJLCV.js.map +7 -0
- package/dist/react/{chunk-JJTII2UQ.js → chunk-GC3KTQDA.js} +78 -15
- package/dist/react/chunk-GC3KTQDA.js.map +7 -0
- package/dist/react/{chunk-2V7G2PLX.js → chunk-GPIYXREE.js} +3 -3
- package/dist/react/{chunk-3VSGFP6U.js → chunk-HFQZYCHJ.js} +8 -4
- package/dist/react/chunk-HFQZYCHJ.js.map +7 -0
- package/dist/react/{chunk-C72OHQLE.js → chunk-ILGAFR56.js} +3 -3
- package/dist/react/{chunk-CF7AK4ES.js → chunk-KVAQPCUH.js} +26 -3
- package/dist/react/chunk-KVAQPCUH.js.map +7 -0
- package/dist/react/{chunk-WEWMB35W.js → chunk-OFGJJKPH.js} +3 -3
- package/dist/react/chunk-PAKA6HUX.js +59 -0
- package/dist/react/chunk-PAKA6HUX.js.map +7 -0
- package/dist/react/{chunk-HKYUJUD7.js → chunk-PXFPPO3R.js} +5 -1
- package/dist/react/chunk-PXFPPO3R.js.map +7 -0
- package/dist/react/{chunk-6G3ITAS5.js → chunk-SZD7DKYJ.js} +18 -9
- package/dist/react/chunk-SZD7DKYJ.js.map +7 -0
- package/dist/react/{chunk-N7NZLF6P.js → chunk-TKXKJNTX.js} +5 -1
- package/dist/react/chunk-TKXKJNTX.js.map +7 -0
- package/dist/react/{chunk-MYYBFZD3.js → chunk-U3TB4KRS.js} +45 -6
- package/dist/react/chunk-U3TB4KRS.js.map +7 -0
- package/dist/react/{chunk-UQBT7F4K.js → chunk-V2QTYSBK.js} +2 -2
- package/dist/react/{chunk-73VA5ALZ.js → chunk-XFQECTTF.js} +48 -19
- package/dist/react/chunk-XFQECTTF.js.map +7 -0
- package/dist/react/{chunk-O64N5JPO.js → chunk-YF3TK7SC.js} +2 -2
- package/dist/react/{circleTool-RDOIMKKV.js → circleTool-KICNRQCI.js} +4 -4
- package/dist/react/{codeTool-O2Z7ZXGP.js → codeTool-NCQ73R6M.js} +5 -4
- package/dist/react/{frameTool-Z5ZDCX6H.js → frameTool-Y6KB67DO.js} +4 -4
- package/dist/react/{freehandTool-AAQCTMVM.js → freehandTool-MMULHCQ7.js} +4 -4
- package/dist/react/{iconTool-AUHRLOO2.js → iconTool-LSW2DYGB.js} +5 -4
- package/dist/react/{imageTool-DRKDCPUV.js → imageTool-2DSR32RX.js} +5 -4
- package/dist/react/index.js +141 -66
- package/dist/react/index.js.map +3 -3
- package/dist/react/{lineTool-XLOOZE3E.js → lineTool-N5I7IGT7.js} +4 -4
- package/dist/react/{rectangleTool-AEYDDJCA.js → rectangleTool-YUT7ZK2E.js} +4 -4
- package/dist/react/{textTool-UORBAAJE.js → textTool-IQOYPELP.js} +6 -5
- package/package.json +1 -1
- package/src/core/CopyPaste.js +34 -4
- package/src/core/GraphEngine.js +129 -185
- package/src/core/SceneSerializer.js +26 -0
- package/src/core/ScreenSpaceControls.js +60 -0
- package/src/core/Selection.js +19 -11
- package/src/core/UndoRedo.js +47 -3
- package/src/core/ZoomPan.js +3 -0
- package/src/react/components/canvas/MultiSelectActions.jsx +4 -1
- package/src/react/components/sidebars/IconSidebar.jsx +14 -23
- package/src/react/components/sidebars/ImageSidebar.jsx +47 -24
- package/src/react/store/useUIStore.js +71 -14
- package/src/shapes/Circle.js +2 -0
- package/src/shapes/Frame.js +26 -2
- package/src/shapes/FreehandStroke.js +2 -0
- package/src/shapes/IconShape.js +23 -25
- package/src/shapes/ImageShape.js +6 -2
- package/src/shapes/Rectangle.js +2 -0
- package/src/tools/codeTool.js +3 -2
- package/src/tools/frameTool.js +19 -9
- package/src/tools/iconTool.js +63 -26
- package/src/tools/imageTool.js +80 -14
- package/src/tools/textTool.js +3 -1
- package/dist/react/Circle-QQMKCKFR.js +0 -8
- package/dist/react/CopyPaste-JMIXWUUO.js.map +0 -7
- package/dist/react/Frame-VADA625S.js +0 -10
- package/dist/react/FreehandStroke-BOWDNAVC.js +0 -8
- package/dist/react/IconShape-32EYI2MA.js +0 -10
- package/dist/react/ImageShape-MYP2DVVH.js +0 -10
- package/dist/react/Line-FCCF2BOB.js +0 -10
- package/dist/react/Rectangle-MZ6ZB6KM.js +0 -8
- package/dist/react/SceneSerializer-ARTKPZVR.js.map +0 -7
- package/dist/react/ZoomPan-NYPDJBD5.js.map +0 -7
- package/dist/react/chunk-3VSGFP6U.js.map +0 -7
- package/dist/react/chunk-6G3ITAS5.js.map +0 -7
- package/dist/react/chunk-73VA5ALZ.js.map +0 -7
- package/dist/react/chunk-C62SXFBL.js.map +0 -7
- package/dist/react/chunk-CF7AK4ES.js.map +0 -7
- package/dist/react/chunk-FV3EPR4L.js.map +0 -7
- package/dist/react/chunk-HKYUJUD7.js.map +0 -7
- package/dist/react/chunk-JJTII2UQ.js.map +0 -7
- package/dist/react/chunk-MYYBFZD3.js.map +0 -7
- package/dist/react/chunk-N7NZLF6P.js.map +0 -7
- package/dist/react/chunk-QYNTPZON.js.map +0 -7
- package/dist/react/chunk-XCJOF6BM.js.map +0 -7
- /package/dist/react/{Circle-QQMKCKFR.js.map → Circle-6POZCUZD.js.map} +0 -0
- /package/dist/react/{Frame-VADA625S.js.map → Frame-RLSMJJSK.js.map} +0 -0
- /package/dist/react/{FreehandStroke-BOWDNAVC.js.map → FreehandStroke-U6GYZOM4.js.map} +0 -0
- /package/dist/react/{IconShape-32EYI2MA.js.map → IconShape-7OPXAKLK.js.map} +0 -0
- /package/dist/react/{ImageShape-MYP2DVVH.js.map → ImageShape-LRNJQCF3.js.map} +0 -0
- /package/dist/react/{Line-FCCF2BOB.js.map → Line-WWQFBNX5.js.map} +0 -0
- /package/dist/react/{Rectangle-MZ6ZB6KM.js.map → Rectangle-S7XUKWYD.js.map} +0 -0
- /package/dist/react/{Selection-YJNZRBON.js.map → Selection-ZL3G6IAO.js.map} +0 -0
- /package/dist/react/{SketchEngine-ZGYBIZG7.js.map → SketchEngine-BFLHJPCG.js.map} +0 -0
- /package/dist/react/{UndoRedo-BZ6W4QTV.js.map → UndoRedo-NL7KLR5B.js.map} +0 -0
- /package/dist/react/{arrowTool-LKFSZKXC.js.map → arrowTool-CNVGM6RX.js.map} +0 -0
- /package/dist/react/{chunk-JOPQ27YH.js.map → chunk-4BLMNGTR.js.map} +0 -0
- /package/dist/react/{chunk-2V7G2PLX.js.map → chunk-GPIYXREE.js.map} +0 -0
- /package/dist/react/{chunk-C72OHQLE.js.map → chunk-ILGAFR56.js.map} +0 -0
- /package/dist/react/{chunk-WEWMB35W.js.map → chunk-OFGJJKPH.js.map} +0 -0
- /package/dist/react/{chunk-UQBT7F4K.js.map → chunk-V2QTYSBK.js.map} +0 -0
- /package/dist/react/{chunk-O64N5JPO.js.map → chunk-YF3TK7SC.js.map} +0 -0
- /package/dist/react/{circleTool-RDOIMKKV.js.map → circleTool-KICNRQCI.js.map} +0 -0
- /package/dist/react/{codeTool-O2Z7ZXGP.js.map → codeTool-NCQ73R6M.js.map} +0 -0
- /package/dist/react/{frameTool-Z5ZDCX6H.js.map → frameTool-Y6KB67DO.js.map} +0 -0
- /package/dist/react/{freehandTool-AAQCTMVM.js.map → freehandTool-MMULHCQ7.js.map} +0 -0
- /package/dist/react/{iconTool-AUHRLOO2.js.map → iconTool-LSW2DYGB.js.map} +0 -0
- /package/dist/react/{imageTool-DRKDCPUV.js.map → imageTool-2DSR32RX.js.map} +0 -0
- /package/dist/react/{lineTool-XLOOZE3E.js.map → lineTool-N5I7IGT7.js.map} +0 -0
- /package/dist/react/{rectangleTool-AEYDDJCA.js.map → rectangleTool-YUT7ZK2E.js.map} +0 -0
- /package/dist/react/{textTool-UORBAAJE.js.map → textTool-IQOYPELP.js.map} +0 -0
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/core/SceneSerializer.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable */\n/**\n * SceneSerializer - Save and load .lixsketch scene files\n *\n * Format: JSON with metadata + serialized shapes array\n * File extension: .lixsketch (actually JSON)\n */\n\nimport { Rectangle } from '../shapes/Rectangle.js';\nimport { Circle } from '../shapes/Circle.js';\nimport { Line } from '../shapes/Line.js';\nimport { Arrow } from '../shapes/Arrow.js';\nimport { FreehandStroke } from '../shapes/FreehandStroke.js';\nimport { Frame } from '../shapes/Frame.js';\nimport { TextShape } from '../shapes/TextShape.js';\nimport { CodeShape } from '../shapes/CodeShape.js';\nimport { ImageShape } from '../shapes/ImageShape.js';\nimport { IconShape } from '../shapes/IconShape.js';\n\nconst FORMAT_VERSION = 1;\n\n// Generate a unique session ID for each scene\nlet _sessionID = null;\nexport function getSessionID() {\n if (!_sessionID) {\n _sessionID = `lx-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n }\n return _sessionID;\n}\nexport function resetSessionID() {\n _sessionID = null;\n}\n\nfunction cloneOptions(options) {\n return JSON.parse(JSON.stringify(options));\n}\n\nfunction restoreDocBlockLinks(shape, data) {\n const ids = [...new Set((Array.isArray(data.docBlockIds)\n ? data.docBlockIds\n : (data.docBlockId ? [data.docBlockId] : [])).filter(Boolean))];\n shape.docBlockIds = ids;\n delete shape.docBlockId;\n if (ids.length) {\n (shape.group || shape.element)?.setAttribute('data-doc-block-ids', JSON.stringify(ids));\n }\n}\n\n// ============================================================\n// SERIALIZE a single shape to plain data\n// ============================================================\nfunction serializeShape(shape) {\n const base = {\n shapeID: shape.shapeID,\n // Optional many-to-many connections to BlockNote document blocks.\n // Stored with the encrypted scene so navigation survives restore.\n docBlockIds: [...new Set((Array.isArray(shape.docBlockIds)\n ? shape.docBlockIds\n : (shape.docBlockId ? [shape.docBlockId] : [])).filter(Boolean))],\n parentFrame: shape.parentFrame ? shape.parentFrame.shapeID : null,\n // Group membership \u2014 null when the shape isn't part of a group.\n // All shapes sharing a non-null groupId move/resize/rotate as a\n // unit (see Selection.handleMultiSelectionMouseDown).\n groupId: shape.groupId || null,\n };\n\n switch (shape.shapeName) {\n case 'rectangle':\n return {\n ...base,\n type: 'rectangle',\n x: shape.x, y: shape.y,\n width: shape.width, height: shape.height,\n rotation: shape.rotation,\n options: cloneOptions(shape.options),\n };\n\n case 'circle':\n return {\n ...base,\n type: 'circle',\n x: shape.x, y: shape.y,\n rx: shape.rx, ry: shape.ry,\n rotation: shape.rotation,\n options: cloneOptions(shape.options),\n };\n\n case 'line':\n return {\n ...base,\n type: 'line',\n startPoint: { x: shape.startPoint.x, y: shape.startPoint.y },\n endPoint: { x: shape.endPoint.x, y: shape.endPoint.y },\n controlPoint: shape.controlPoint ? { x: shape.controlPoint.x, y: shape.controlPoint.y } : null,\n isCurved: shape.isCurved || false,\n options: cloneOptions(shape.options),\n };\n\n case 'arrow': {\n const data = {\n ...base,\n type: 'arrow',\n startPoint: { x: shape.startPoint.x, y: shape.startPoint.y },\n endPoint: { x: shape.endPoint.x, y: shape.endPoint.y },\n options: cloneOptions(shape.options),\n arrowOutlineStyle: shape.arrowOutlineStyle,\n arrowHeadStyle: shape.arrowHeadStyle,\n arrowCurved: shape.arrowCurved,\n arrowCurveAmount: shape.arrowCurveAmount,\n };\n if (shape.controlPoint1) data.controlPoint1 = { x: shape.controlPoint1.x, y: shape.controlPoint1.y };\n if (shape.controlPoint2) data.controlPoint2 = { x: shape.controlPoint2.x, y: shape.controlPoint2.y };\n // Serialize attachments by shapeID\n if (shape.startAttachment) data.startAttachmentID = shape.startAttachment.shapeID;\n if (shape.endAttachment) data.endAttachmentID = shape.endAttachment.shapeID;\n return data;\n }\n\n case 'freehandStroke':\n return {\n ...base,\n type: 'freehandStroke',\n points: JSON.parse(JSON.stringify(shape.points)),\n rotation: shape.rotation,\n options: cloneOptions(shape.options),\n };\n\n case 'frame':\n return {\n ...base,\n type: 'frame',\n x: shape.x, y: shape.y,\n width: shape.width, height: shape.height,\n rotation: shape.rotation,\n frameName: shape.frameName,\n fillStyle: shape.fillStyle || 'transparent',\n fillColor: shape.fillColor || '#1e1e28',\n gridSize: shape.gridSize || 20,\n gridColor: shape.gridColor || 'rgba(255,255,255,0.06)',\n options: cloneOptions(shape.options),\n // Issue #24 bug #10: filter out null / undefined / shapeID-less\n // children. A stale reference would serialize as `null` and the\n // load path would skip it (logging a misleading \"missing shape\"\n // warning) \u2014 but also previously skewed the order tracking.\n containedShapeIDs: shape.containedShapes\n ? Array.from(shape.containedShapes)\n .filter(s => s && s.shapeID)\n .map(s => s.shapeID)\n : [],\n };\n\n case 'text': {\n const group = shape.group;\n return {\n ...base,\n type: 'text',\n x: shape.x, y: shape.y,\n rotation: shape.rotation,\n groupHTML: group.cloneNode(true).outerHTML,\n };\n }\n\n case 'code': {\n const group = shape.group;\n return {\n ...base,\n type: 'code',\n x: shape.x, y: shape.y,\n rotation: shape.rotation,\n groupHTML: group.cloneNode(true).outerHTML,\n };\n }\n\n case 'image': {\n const el = shape.element;\n return {\n ...base,\n type: 'image',\n x: shape.x, y: shape.y,\n width: shape.width, height: shape.height,\n rotation: shape.rotation,\n href: el.getAttribute('href') || el.getAttributeNS('http://www.w3.org/1999/xlink', 'href') || '',\n };\n }\n\n case 'icon': {\n const el = shape.element;\n return {\n ...base,\n type: 'icon',\n x: shape.x, y: shape.y,\n width: shape.width, height: shape.height,\n rotation: shape.rotation,\n elementHTML: el.cloneNode(true).outerHTML,\n viewboxWidth: parseFloat(el.getAttribute('data-viewbox-width')) || 24,\n viewboxHeight: parseFloat(el.getAttribute('data-viewbox-height')) || 24,\n };\n }\n\n default:\n console.warn('[SceneSerializer] Unknown shape type:', shape.shapeName);\n return null;\n }\n}\n\n// ============================================================\n// DESERIALIZE: Create a shape from saved data\n// ============================================================\nfunction deserializeShape(data) {\n const svgEl = window.svg;\n if (!svgEl) return null;\n const ns = 'http://www.w3.org/2000/svg';\n\n switch (data.type) {\n case 'rectangle': {\n const shape = new Rectangle(data.x, data.y, data.width, data.height, data.options || {});\n if (data.rotation) shape.rotation = data.rotation;\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'circle': {\n const shape = new Circle(data.x, data.y, data.rx, data.ry, data.options || {});\n if (data.rotation) shape.rotation = data.rotation;\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'line': {\n const shape = new Line(data.startPoint, data.endPoint, data.options || {});\n if (data.controlPoint) shape.controlPoint = data.controlPoint;\n if (data.isCurved) shape.isCurved = data.isCurved;\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'arrow': {\n const shape = new Arrow(data.startPoint, data.endPoint, data.options || {});\n if (data.controlPoint1) shape.controlPoint1 = data.controlPoint1;\n if (data.controlPoint2) shape.controlPoint2 = data.controlPoint2;\n if (data.arrowOutlineStyle) shape.arrowOutlineStyle = data.arrowOutlineStyle;\n if (data.arrowHeadStyle) shape.arrowHeadStyle = data.arrowHeadStyle;\n if (data.arrowCurved) shape.arrowCurved = data.arrowCurved;\n if (data.arrowCurveAmount) shape.arrowCurveAmount = data.arrowCurveAmount;\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'freehandStroke': {\n const shape = new FreehandStroke(data.points, data.options || {});\n if (data.rotation) shape.rotation = data.rotation;\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'frame': {\n const frameOpts = { ...(data.options || {}), frameName: data.frameName || 'Frame' };\n if (data.fillStyle) frameOpts.fillStyle = data.fillStyle;\n if (data.fillColor) frameOpts.fillColor = data.fillColor;\n if (data.gridSize) frameOpts.gridSize = data.gridSize;\n if (data.gridColor) frameOpts.gridColor = data.gridColor;\n const shape = new Frame(data.x, data.y, data.width, data.height, frameOpts);\n if (data.rotation) shape.rotation = data.rotation;\n if (data.shapeID) shape.shapeID = data.shapeID;\n shape.draw();\n return shape;\n }\n\n case 'text': {\n if (!data.groupHTML) return null;\n const parser = new DOMParser();\n const doc = parser.parseFromString(`<svg xmlns=\"${ns}\">${data.groupHTML}</svg>`, 'image/svg+xml');\n const group = doc.querySelector('g');\n if (!group) return null;\n const imported = svgEl.ownerDocument.importNode(group, true);\n svgEl.appendChild(imported);\n const shape = new TextShape(imported);\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'code': {\n if (!data.groupHTML) return null;\n const parser = new DOMParser();\n const doc = parser.parseFromString(`<svg xmlns=\"${ns}\">${data.groupHTML}</svg>`, 'image/svg+xml');\n const group = doc.querySelector('g');\n if (!group) return null;\n const imported = svgEl.ownerDocument.importNode(group, true);\n svgEl.appendChild(imported);\n const shape = new CodeShape(imported);\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'image': {\n const imgEl = document.createElementNS(ns, 'image');\n imgEl.setAttribute('x', data.x);\n imgEl.setAttribute('y', data.y);\n imgEl.setAttribute('width', data.width);\n imgEl.setAttribute('height', data.height);\n imgEl.setAttribute('href', data.href);\n imgEl.setAttribute('preserveAspectRatio', 'none');\n svgEl.appendChild(imgEl);\n const shape = new ImageShape(imgEl);\n if (data.rotation) shape.rotation = data.rotation;\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n case 'icon': {\n if (!data.elementHTML) return null;\n const parser = new DOMParser();\n // Wrap in <svg> so the parser treats the <g> as a valid child, not a document root\n const doc = parser.parseFromString(`<svg xmlns=\"${ns}\">${data.elementHTML}</svg>`, 'image/svg+xml');\n const iconGroup = doc.querySelector('g');\n if (!iconGroup) return null;\n const imported = svgEl.ownerDocument.importNode(iconGroup, true);\n svgEl.appendChild(imported);\n const shape = new IconShape(imported);\n if (data.shapeID) shape.shapeID = data.shapeID;\n return shape;\n }\n\n default:\n console.warn('[SceneSerializer] Unknown type:', data.type);\n return null;\n }\n}\n\n// ============================================================\n// SAVE: Serialize entire scene to .lixsketch JSON\n// ============================================================\nexport function saveScene(workspaceName = 'Untitled') {\n const allShapes = window.shapes || [];\n const serialized = [];\n\n // Issue #24 bug #10: rebuild containment from each shape's own\n // `parentFrame` ref before serialising. The `containedShapes` array\n // on the frame side drifts over time (eraser, partial deletes, drag\n // out + drag back, etc.), and a missing entry there means the child\n // gets serialised as a top-level shape and the frame restores empty.\n // Each shape knows its own parent, so we trust THAT and override the\n // frame's array at save time.\n const childrenByFrame = new Map();\n for (const s of allShapes) {\n if (s && s.parentFrame && s.shapeID && s !== s.parentFrame) {\n const arr = childrenByFrame.get(s.parentFrame.shapeID) || [];\n arr.push(s.shapeID);\n childrenByFrame.set(s.parentFrame.shapeID, arr);\n }\n }\n\n for (const shape of allShapes) {\n const data = serializeShape(shape);\n if (!data) continue;\n if (data.type === 'frame' && shape.shapeID && childrenByFrame.has(shape.shapeID)) {\n const merged = new Set(data.containedShapeIDs || []);\n for (const id of childrenByFrame.get(shape.shapeID)) merged.add(id);\n data.containedShapeIDs = Array.from(merged);\n }\n serialized.push(data);\n }\n\n const scene = {\n format: 'lixsketch',\n version: FORMAT_VERSION,\n sessionID: getSessionID(),\n name: workspaceName,\n createdAt: new Date().toISOString(),\n viewport: window.currentViewBox ? { ...window.currentViewBox } : null,\n zoom: window.currentZoom || 1,\n shapes: serialized,\n };\n\n return scene;\n}\n\n// ============================================================\n// LOAD: Deserialize .lixsketch JSON and recreate scene\n// ============================================================\nexport function loadScene(sceneData) {\n if (!sceneData || sceneData.format !== 'lixsketch') {\n console.error('[SceneSerializer] Invalid scene format');\n return false;\n }\n\n // Clear current scene\n const svgEl = window.svg;\n if (!svgEl) return false;\n\n // Remove all existing shape DOM elements\n const existingShapes = window.shapes || [];\n existingShapes.forEach(shape => {\n // For frames, clean up clipGroup and clipPath too\n if (shape.shapeName === 'frame') {\n if (shape.clipGroup && shape.clipGroup.parentNode) {\n shape.clipGroup.parentNode.removeChild(shape.clipGroup);\n }\n if (shape.clipPath && shape.clipPath.parentNode) {\n shape.clipPath.parentNode.removeChild(shape.clipPath);\n }\n }\n if (shape.group && shape.group.parentNode) {\n shape.group.parentNode.removeChild(shape.group);\n } else if (shape.element && shape.element.parentNode) {\n shape.element.parentNode.removeChild(shape.element);\n }\n });\n\n // Clear arrays IN PLACE \u2014 tool modules hold direct references to these\n // arrays from import-time, so replacing them breaks interactivity.\n if (window.shapes) window.shapes.length = 0; else window.shapes = [];\n window.currentShape = null;\n if (window.historyStack) window.historyStack.length = 0; else window.historyStack = [];\n if (window.redoStack) window.redoStack.length = 0; else window.redoStack = [];\n\n // Build ID -> shape map for frame containment and arrow attachments\n const idMap = new Map();\n\n // First pass: create all shapes (frames first to allow containment)\n const frameData = sceneData.shapes.filter(s => s.type === 'frame');\n const otherData = sceneData.shapes.filter(s => s.type !== 'frame');\n\n // Create frames first\n for (const data of frameData) {\n const shape = deserializeShape(data);\n if (shape) {\n // Restore group membership if present.\n if (data.groupId) shape.groupId = data.groupId;\n restoreDocBlockLinks(shape, data);\n window.shapes.push(shape);\n if (data.shapeID) idMap.set(data.shapeID, shape);\n }\n }\n\n // Create all other shapes\n for (const data of otherData) {\n const shape = deserializeShape(data);\n if (shape) {\n if (data.groupId) shape.groupId = data.groupId;\n restoreDocBlockLinks(shape, data);\n window.shapes.push(shape);\n if (data.shapeID) idMap.set(data.shapeID, shape);\n }\n }\n\n // Second pass: restore frame containment\n for (const data of frameData) {\n const frame = idMap.get(data.shapeID);\n if (frame && data.containedShapeIDs && data.containedShapeIDs.length > 0) {\n for (const childID of data.containedShapeIDs) {\n const child = idMap.get(childID);\n if (!child) {\n console.warn(`[SceneSerializer] Frame \"${data.frameName}\" references missing shape: ${childID}`);\n continue;\n }\n try {\n if (typeof frame.addShapeToFrame === 'function') {\n frame.addShapeToFrame(child);\n } else {\n // Fallback: manually set containment\n frame.containedShapes.push(child);\n child.parentFrame = frame;\n }\n } catch (err) {\n console.warn(`[SceneSerializer] Failed to restore containment for ${childID} in frame ${data.shapeID}:`, err);\n // Fallback: at least set the reference\n if (!frame.containedShapes.includes(child)) {\n frame.containedShapes.push(child);\n }\n child.parentFrame = frame;\n }\n }\n }\n }\n\n // Third pass: restore arrow attachments\n for (const data of sceneData.shapes) {\n if (data.type === 'arrow') {\n const arrow = idMap.get(data.shapeID);\n if (!arrow) continue;\n if (data.startAttachmentID) {\n const target = idMap.get(data.startAttachmentID);\n if (target && arrow.setStartAttachment) arrow.setStartAttachment(target);\n }\n if (data.endAttachmentID) {\n const target = idMap.get(data.endAttachmentID);\n if (target && arrow.setEndAttachment) arrow.setEndAttachment(target);\n }\n }\n }\n\n // \u2500\u2500 Fourth pass: frame containment reconciliation (issue #24 bug #10) \u2500\u2500\n //\n // The pass above attaches each child via `frame.addShapeToFrame(child)`,\n // which is supposed to move the child's <g> into the frame's clipGroup.\n // In practice LixScript-rendered scenes were reloading with empty\n // frames \u2014 children present in the shapes array, frame box drawn, but\n // the children's <g> elements stranded at the svg root (so visually\n // they look orphaned). The cause varies (transient `isBeingMovedByFrame`\n // flag carried over from save time, ordering glitches when nested\n // frames are restored, etc.). Rather than chase the source, repair the\n // DOM state here from the authoritative `containedShapes` array.\n for (const data of frameData) {\n const frame = idMap.get(data.shapeID);\n if (!frame) continue;\n\n // Clear stale flags that suppress DOM mutation inside addShapeToFrame.\n delete frame.isBeingMovedByFrame;\n delete frame.isDraggedOutTemporarily;\n\n // Ensure the frame's own clipGroup is direct child of svg \u2014 sub-frames\n // that didn't get re-parented yet are handled in the next loop.\n if (frame.clipGroup && frame.clipGroup.parentNode !== svgEl) {\n svgEl.appendChild(frame.clipGroup);\n }\n\n for (const child of frame.containedShapes || []) {\n if (!child) continue;\n delete child.isBeingMovedByFrame;\n delete child.isDraggedOutTemporarily;\n\n const el = child.group || child.element;\n if (el && el.parentNode !== frame.clipGroup) {\n if (el.parentNode) el.parentNode.removeChild(el);\n frame.clipGroup.appendChild(el);\n }\n // Sub-frames also carry their own clipGroup \u2014 nest it.\n if (child.shapeName === 'frame' && child.clipGroup\n && child.clipGroup.parentNode !== frame.clipGroup) {\n if (child.clipGroup.parentNode) child.clipGroup.parentNode.removeChild(child.clipGroup);\n frame.clipGroup.appendChild(child.clipGroup);\n }\n // Authoritative parent ref \u2014 `addShapeToFrame` should already\n // have set this but the no-op early return when the child was\n // already in containedShapes skips it.\n child.parentFrame = frame;\n }\n\n // Force the clip rect + visual to match. Some saved frames came\n // through with a stale clipRect from before the resize that lost\n // the children visually.\n if (typeof frame.updateClipPath === 'function') frame.updateClipPath();\n if (typeof frame.draw === 'function') {\n try { frame.draw(); } catch (err) { console.warn('[SceneSerializer] frame redraw failed:', err); }\n }\n }\n\n // Restore viewport\n if (sceneData.viewport && svgEl) {\n const vb = sceneData.viewport;\n window.currentViewBox = { ...vb };\n svgEl.setAttribute('viewBox', `${vb.x} ${vb.y} ${vb.width} ${vb.height}`);\n }\n if (sceneData.zoom) {\n window.currentZoom = sceneData.zoom;\n }\n\n console.log(`[SceneSerializer] Loaded ${window.shapes.length} shapes from \"${sceneData.name}\"`);\n window.dispatchEvent(new CustomEvent('lix-doc-canvas-links-changed'));\n\n // Re-sync tool flags so shapes are interactable after restore\n if (window.__sketchEngine && typeof window.__sketchEngine.setActiveTool === 'function') {\n const store = window.__sketchStoreApi;\n const currentTool = store ? store.getState().activeTool : 'select';\n window.__sketchEngine.setActiveTool(currentTool);\n } else {\n // Fallback: ensure selection tool is active\n window.isSelectionToolActive = true;\n }\n\n return true;\n}\n\n// ============================================================\n// DOWNLOAD: Trigger browser download of .lixsketch file\n// ============================================================\nexport function downloadScene(workspaceName = 'Untitled') {\n const scene = saveScene(workspaceName);\n const json = JSON.stringify(scene, null, 2);\n const blob = new Blob([json], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n\n const a = document.createElement('a');\n a.href = url;\n a.download = `${workspaceName.replace(/[^a-zA-Z0-9_-]/g, '_')}.lixjson`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n}\n\n// ============================================================\n// UPLOAD: Open file picker and load .lixsketch file\n// ============================================================\n// Validate scene JSON structure before loading\nexport function validateScene(data) {\n if (!data || typeof data !== 'object') return { valid: false, error: 'Not a valid JSON object' };\n if (data.format !== 'lixsketch') return { valid: false, error: 'Not a LixSketch scene file (missing format field)' };\n if (!data.version || data.version > FORMAT_VERSION) return { valid: false, error: `Unsupported version: ${data.version}` };\n if (!Array.isArray(data.shapes)) return { valid: false, error: 'Invalid scene: missing shapes array' };\n return {\n valid: true,\n name: data.name || 'Untitled',\n shapeCount: data.shapes.length,\n sessionID: data.sessionID || null,\n createdAt: data.createdAt || null,\n };\n}\n\nexport function uploadScene() {\n return new Promise((resolve, reject) => {\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = '.lixjson,.json';\n input.onchange = (e) => {\n const file = e.target.files[0];\n if (!file) return resolve(false);\n\n const reader = new FileReader();\n reader.onload = (ev) => {\n try {\n const data = JSON.parse(ev.target.result);\n const validation = validateScene(data);\n if (!validation.valid) {\n console.error('[SceneSerializer] Invalid file:', validation.error);\n resolve({ success: false, error: validation.error });\n return;\n }\n resetSessionID(); // New session for loaded scene\n const result = loadScene(data);\n resolve({ success: result, validation });\n } catch (err) {\n console.error('[SceneSerializer] Failed to parse file:', err);\n resolve({ success: false, error: 'Failed to parse JSON file' });\n }\n };\n reader.readAsText(file);\n };\n input.click();\n });\n}\n\n// ============================================================\n// EXPORT as PNG\n// ============================================================\nexport function exportAsPNG() {\n const svgEl = window.svg;\n if (!svgEl) return;\n\n const clone = svgEl.cloneNode(true);\n // Remove selection UI elements\n const selectionEls = clone.querySelectorAll('[data-selection], .selection-handle, .resize-handle, .rotation-handle');\n selectionEls.forEach(el => el.remove());\n\n const svgData = new XMLSerializer().serializeToString(clone);\n const canvas = document.createElement('canvas');\n const vb = svgEl.viewBox.baseVal;\n canvas.width = vb.width * 2; // 2x for retina\n canvas.height = vb.height * 2;\n const ctx = canvas.getContext('2d');\n ctx.scale(2, 2);\n\n const img = new Image();\n const svgBlob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(svgBlob);\n\n img.onload = () => {\n // Draw dark background\n ctx.fillStyle = '#121212';\n ctx.fillRect(0, 0, vb.width, vb.height);\n ctx.drawImage(img, 0, 0, vb.width, vb.height);\n URL.revokeObjectURL(url);\n\n canvas.toBlob(blob => {\n const a = document.createElement('a');\n a.href = URL.createObjectURL(blob);\n a.download = 'lixsketch-export.png';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n }, 'image/png');\n };\n img.src = url;\n}\n\n// ============================================================\n// COPY to clipboard as PNG\n// ============================================================\nexport function copyAsPNG() {\n const svgEl = window.svg;\n if (!svgEl) return;\n\n const clone = svgEl.cloneNode(true);\n const selectionEls = clone.querySelectorAll('[data-selection], .selection-handle, .resize-handle, .rotation-handle');\n selectionEls.forEach(el => el.remove());\n\n const svgData = new XMLSerializer().serializeToString(clone);\n const canvas = document.createElement('canvas');\n const vb = svgEl.viewBox.baseVal;\n canvas.width = vb.width * 2;\n canvas.height = vb.height * 2;\n const ctx = canvas.getContext('2d');\n ctx.scale(2, 2);\n\n const img = new Image();\n const svgBlob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(svgBlob);\n\n img.onload = () => {\n ctx.fillStyle = '#121212';\n ctx.fillRect(0, 0, vb.width, vb.height);\n ctx.drawImage(img, 0, 0, vb.width, vb.height);\n URL.revokeObjectURL(url);\n\n canvas.toBlob(blob => {\n if (!blob) return;\n navigator.clipboard.write([\n new ClipboardItem({ 'image/png': blob })\n ]).catch(err => console.warn('[SceneSerializer] Clipboard write failed:', err));\n }, 'image/png');\n };\n img.src = url;\n}\n\n// ============================================================\n// COPY to clipboard as SVG\n// ============================================================\nexport function copyAsSVG() {\n const svgEl = window.svg;\n if (!svgEl) return;\n\n const clone = svgEl.cloneNode(true);\n const selectionEls = clone.querySelectorAll('[data-selection], .selection-handle, .resize-handle, .rotation-handle');\n selectionEls.forEach(el => el.remove());\n\n const svgData = new XMLSerializer().serializeToString(clone);\n navigator.clipboard.writeText(svgData)\n .catch(err => console.warn('[SceneSerializer] Clipboard write failed:', err));\n}\n\n// ============================================================\n// EXPORT as PDF (uses browser print)\n// ============================================================\nexport function exportAsPDF() {\n const svgEl = window.svg;\n if (!svgEl) return;\n\n const clone = svgEl.cloneNode(true);\n const selectionEls = clone.querySelectorAll('[data-selection], .selection-handle, .resize-handle, .rotation-handle');\n selectionEls.forEach(el => el.remove());\n\n const svgData = new XMLSerializer().serializeToString(clone);\n const printWindow = window.open('', '_blank');\n printWindow.document.write(`\n <!DOCTYPE html>\n <html>\n <head><title>LixSketch Export</title>\n <style>\n body { margin: 0; background: #121212; display: flex; align-items: center; justify-content: center; min-height: 100vh; }\n svg { max-width: 100vw; max-height: 100vh; }\n @media print { body { background: white; } }\n </style>\n </head>\n <body>${svgData}</body>\n </html>\n `);\n printWindow.document.close();\n printWindow.focus();\n setTimeout(() => printWindow.print(), 500);\n}\n\n// ============================================================\n// RESET: Clear the entire canvas\n// ============================================================\nexport function resetCanvas() {\n const svgEl = window.svg;\n if (!svgEl) return;\n\n // Remove all shape DOM elements + frame clipGroups/clipPaths\n const existingShapes = window.shapes || [];\n existingShapes.forEach(shape => {\n if (shape.shapeName === 'frame') {\n if (shape.clipGroup && shape.clipGroup.parentNode) {\n shape.clipGroup.parentNode.removeChild(shape.clipGroup);\n }\n if (shape.clipPath && shape.clipPath.parentNode) {\n shape.clipPath.parentNode.removeChild(shape.clipPath);\n }\n }\n if (shape.group && shape.group.parentNode) {\n shape.group.parentNode.removeChild(shape.group);\n } else if (shape.element && shape.element.parentNode) {\n shape.element.parentNode.removeChild(shape.element);\n }\n });\n\n // Remove selection UI\n svgEl.querySelectorAll(\n '.selection-outline, .resize-anchor, .rotation-anchor, [data-selection]'\n ).forEach(el => el.remove());\n\n // Clear arrays IN PLACE (same reason as loadScene)\n if (window.shapes) window.shapes.length = 0; else window.shapes = [];\n window.currentShape = null;\n if (window.historyStack) window.historyStack.length = 0; else window.historyStack = [];\n if (window.redoStack) window.redoStack.length = 0; else window.redoStack = [];\n\n if (typeof window.clearAllSelections === 'function') {\n window.clearAllSelections();\n }\n if (typeof window.disableAllSideBars === 'function') {\n window.disableAllSideBars();\n }\n\n // Clear auto-save (both legacy and session-scoped keys)\n try {\n localStorage.removeItem('lixsketch-autosave');\n localStorage.removeItem('lixsketch-autosave-meta');\n const sid = window.__sessionID;\n if (sid) {\n localStorage.removeItem(`lixsketch-autosave-${sid}`);\n localStorage.removeItem(`lixsketch-autosave-meta-${sid}`);\n }\n } catch (_) {}\n\n console.log('[SceneSerializer] Canvas reset');\n if (typeof window.__collabSceneChanged === 'function') {\n window.__collabSceneChanged();\n }\n}\n\n// ============================================================\n// FIND: Search for text content on the canvas\n// ============================================================\nexport function findTextOnCanvas(query) {\n const allShapes = window.shapes || [];\n if (!query || query.trim() === '') return [];\n\n const lowerQuery = query.toLowerCase();\n const results = [];\n\n for (const shape of allShapes) {\n let textContent = '';\n\n if (shape.shapeName === 'text' || shape.shapeName === 'code') {\n const group = shape.group;\n if (group) {\n // Get all text content from SVG text/tspan elements\n const textEls = group.querySelectorAll('text, tspan');\n textEls.forEach(el => {\n if (el.textContent) textContent += el.textContent + ' ';\n });\n // Also check foreignObject content\n const foreignEls = group.querySelectorAll('foreignObject *');\n foreignEls.forEach(el => {\n if (el.textContent) textContent += el.textContent + ' ';\n });\n }\n } else if (shape.shapeName === 'frame') {\n textContent = shape.frameName || '';\n }\n\n textContent = textContent.trim();\n if (textContent && textContent.toLowerCase().includes(lowerQuery)) {\n results.push({\n shape,\n text: textContent,\n type: shape.shapeName,\n x: shape.x || 0,\n y: shape.y || 0,\n });\n }\n }\n\n return results;\n}\n\n// ============================================================\n// Initialize bridge for React components\n// ============================================================\nexport function initSceneSerializer() {\n window.__sceneSerializer = {\n save: saveScene,\n load: loadScene,\n download: downloadScene,\n upload: uploadScene,\n exportPNG: exportAsPNG,\n exportPDF: exportAsPDF,\n copyAsPNG,\n copyAsSVG,\n resetCanvas,\n findText: findTextOnCanvas,\n };\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmBA,IAAM,iBAAiB;AAGvB,IAAI,aAAa;AACV,SAAS,eAAe;AAC3B,MAAI,CAAC,YAAY;AACb,iBAAa,MAAM,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,EACxF;AACA,SAAO;AACX;AACO,SAAS,iBAAiB;AAC7B,eAAa;AACjB;AAEA,SAAS,aAAa,SAAS;AAC3B,SAAO,KAAK,MAAM,KAAK,UAAU,OAAO,CAAC;AAC7C;AAEA,SAAS,qBAAqB,OAAO,MAAM;AACvC,QAAM,MAAM,CAAC,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK,WAAW,IACjD,KAAK,cACJ,KAAK,aAAa,CAAC,KAAK,UAAU,IAAI,CAAC,GAAI,OAAO,OAAO,CAAC,CAAC;AAClE,QAAM,cAAc;AACpB,SAAO,MAAM;AACb,MAAI,IAAI,QAAQ;AACZ,KAAC,MAAM,SAAS,MAAM,UAAU,aAAa,sBAAsB,KAAK,UAAU,GAAG,CAAC;AAAA,EAC1F;AACJ;AAKA,SAAS,eAAe,OAAO;AAC3B,QAAM,OAAO;AAAA,IACT,SAAS,MAAM;AAAA;AAAA;AAAA,IAGf,aAAa,CAAC,GAAG,IAAI,KAAK,MAAM,QAAQ,MAAM,WAAW,IACnD,MAAM,cACL,MAAM,aAAa,CAAC,MAAM,UAAU,IAAI,CAAC,GAAI,OAAO,OAAO,CAAC,CAAC;AAAA,IACpE,aAAa,MAAM,cAAc,MAAM,YAAY,UAAU;AAAA;AAAA;AAAA;AAAA,IAI7D,SAAS,MAAM,WAAW;AAAA,EAC9B;AAEA,UAAQ,MAAM,WAAW;AAAA,IACrB,KAAK;AACD,aAAO;AAAA,QACH,GAAG;AAAA,QACH,MAAM;AAAA,QACN,GAAG,MAAM;AAAA,QAAG,GAAG,MAAM;AAAA,QACrB,OAAO,MAAM;AAAA,QAAO,QAAQ,MAAM;AAAA,QAClC,UAAU,MAAM;AAAA,QAChB,SAAS,aAAa,MAAM,OAAO;AAAA,MACvC;AAAA,IAEJ,KAAK;AACD,aAAO;AAAA,QACH,GAAG;AAAA,QACH,MAAM;AAAA,QACN,GAAG,MAAM;AAAA,QAAG,GAAG,MAAM;AAAA,QACrB,IAAI,MAAM;AAAA,QAAI,IAAI,MAAM;AAAA,QACxB,UAAU,MAAM;AAAA,QAChB,SAAS,aAAa,MAAM,OAAO;AAAA,MACvC;AAAA,IAEJ,KAAK;AACD,aAAO;AAAA,QACH,GAAG;AAAA,QACH,MAAM;AAAA,QACN,YAAY,EAAE,GAAG,MAAM,WAAW,GAAG,GAAG,MAAM,WAAW,EAAE;AAAA,QAC3D,UAAU,EAAE,GAAG,MAAM,SAAS,GAAG,GAAG,MAAM,SAAS,EAAE;AAAA,QACrD,cAAc,MAAM,eAAe,EAAE,GAAG,MAAM,aAAa,GAAG,GAAG,MAAM,aAAa,EAAE,IAAI;AAAA,QAC1F,UAAU,MAAM,YAAY;AAAA,QAC5B,SAAS,aAAa,MAAM,OAAO;AAAA,MACvC;AAAA,IAEJ,KAAK,SAAS;AACV,YAAM,OAAO;AAAA,QACT,GAAG;AAAA,QACH,MAAM;AAAA,QACN,YAAY,EAAE,GAAG,MAAM,WAAW,GAAG,GAAG,MAAM,WAAW,EAAE;AAAA,QAC3D,UAAU,EAAE,GAAG,MAAM,SAAS,GAAG,GAAG,MAAM,SAAS,EAAE;AAAA,QACrD,SAAS,aAAa,MAAM,OAAO;AAAA,QACnC,mBAAmB,MAAM;AAAA,QACzB,gBAAgB,MAAM;AAAA,QACtB,aAAa,MAAM;AAAA,QACnB,kBAAkB,MAAM;AAAA,MAC5B;AACA,UAAI,MAAM,cAAe,MAAK,gBAAgB,EAAE,GAAG,MAAM,cAAc,GAAG,GAAG,MAAM,cAAc,EAAE;AACnG,UAAI,MAAM,cAAe,MAAK,gBAAgB,EAAE,GAAG,MAAM,cAAc,GAAG,GAAG,MAAM,cAAc,EAAE;AAEnG,UAAI,MAAM,gBAAiB,MAAK,oBAAoB,MAAM,gBAAgB;AAC1E,UAAI,MAAM,cAAe,MAAK,kBAAkB,MAAM,cAAc;AACpE,aAAO;AAAA,IACX;AAAA,IAEA,KAAK;AACD,aAAO;AAAA,QACH,GAAG;AAAA,QACH,MAAM;AAAA,QACN,QAAQ,KAAK,MAAM,KAAK,UAAU,MAAM,MAAM,CAAC;AAAA,QAC/C,UAAU,MAAM;AAAA,QAChB,SAAS,aAAa,MAAM,OAAO;AAAA,MACvC;AAAA,IAEJ,KAAK;AACD,aAAO;AAAA,QACH,GAAG;AAAA,QACH,MAAM;AAAA,QACN,GAAG,MAAM;AAAA,QAAG,GAAG,MAAM;AAAA,QACrB,OAAO,MAAM;AAAA,QAAO,QAAQ,MAAM;AAAA,QAClC,UAAU,MAAM;AAAA,QAChB,WAAW,MAAM;AAAA,QACjB,WAAW,MAAM,aAAa;AAAA,QAC9B,WAAW,MAAM,aAAa;AAAA,QAC9B,UAAU,MAAM,YAAY;AAAA,QAC5B,WAAW,MAAM,aAAa;AAAA,QAC9B,SAAS,aAAa,MAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,QAKnC,mBAAmB,MAAM,kBACnB,MAAM,KAAK,MAAM,eAAe,EAC7B,OAAO,OAAK,KAAK,EAAE,OAAO,EAC1B,IAAI,OAAK,EAAE,OAAO,IACrB,CAAC;AAAA,MACX;AAAA,IAEJ,KAAK,QAAQ;AACT,YAAM,QAAQ,MAAM;AACpB,aAAO;AAAA,QACH,GAAG;AAAA,QACH,MAAM;AAAA,QACN,GAAG,MAAM;AAAA,QAAG,GAAG,MAAM;AAAA,QACrB,UAAU,MAAM;AAAA,QAChB,WAAW,MAAM,UAAU,IAAI,EAAE;AAAA,MACrC;AAAA,IACJ;AAAA,IAEA,KAAK,QAAQ;AACT,YAAM,QAAQ,MAAM;AACpB,aAAO;AAAA,QACH,GAAG;AAAA,QACH,MAAM;AAAA,QACN,GAAG,MAAM;AAAA,QAAG,GAAG,MAAM;AAAA,QACrB,UAAU,MAAM;AAAA,QAChB,WAAW,MAAM,UAAU,IAAI,EAAE;AAAA,MACrC;AAAA,IACJ;AAAA,IAEA,KAAK,SAAS;AACV,YAAM,KAAK,MAAM;AACjB,aAAO;AAAA,QACH,GAAG;AAAA,QACH,MAAM;AAAA,QACN,GAAG,MAAM;AAAA,QAAG,GAAG,MAAM;AAAA,QACrB,OAAO,MAAM;AAAA,QAAO,QAAQ,MAAM;AAAA,QAClC,UAAU,MAAM;AAAA,QAChB,MAAM,GAAG,aAAa,MAAM,KAAK,GAAG,eAAe,gCAAgC,MAAM,KAAK;AAAA,MAClG;AAAA,IACJ;AAAA,IAEA,KAAK,QAAQ;AACT,YAAM,KAAK,MAAM;AACjB,aAAO;AAAA,QACH,GAAG;AAAA,QACH,MAAM;AAAA,QACN,GAAG,MAAM;AAAA,QAAG,GAAG,MAAM;AAAA,QACrB,OAAO,MAAM;AAAA,QAAO,QAAQ,MAAM;AAAA,QAClC,UAAU,MAAM;AAAA,QAChB,aAAa,GAAG,UAAU,IAAI,EAAE;AAAA,QAChC,cAAc,WAAW,GAAG,aAAa,oBAAoB,CAAC,KAAK;AAAA,QACnE,eAAe,WAAW,GAAG,aAAa,qBAAqB,CAAC,KAAK;AAAA,MACzE;AAAA,IACJ;AAAA,IAEA;AACI,cAAQ,KAAK,yCAAyC,MAAM,SAAS;AACrE,aAAO;AAAA,EACf;AACJ;AAKA,SAAS,iBAAiB,MAAM;AAC5B,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,KAAK;AAEX,UAAQ,KAAK,MAAM;AAAA,IACf,KAAK,aAAa;AACd,YAAM,QAAQ,IAAI,UAAU,KAAK,GAAG,KAAK,GAAG,KAAK,OAAO,KAAK,QAAQ,KAAK,WAAW,CAAC,CAAC;AACvF,UAAI,KAAK,SAAU,OAAM,WAAW,KAAK;AACzC,UAAI,KAAK,QAAS,OAAM,UAAU,KAAK;AACvC,aAAO;AAAA,IACX;AAAA,IAEA,KAAK,UAAU;AACX,YAAM,QAAQ,IAAI,OAAO,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,IAAI,KAAK,WAAW,CAAC,CAAC;AAC7E,UAAI,KAAK,SAAU,OAAM,WAAW,KAAK;AACzC,UAAI,KAAK,QAAS,OAAM,UAAU,KAAK;AACvC,aAAO;AAAA,IACX;AAAA,IAEA,KAAK,QAAQ;AACT,YAAM,QAAQ,IAAI,KAAK,KAAK,YAAY,KAAK,UAAU,KAAK,WAAW,CAAC,CAAC;AACzE,UAAI,KAAK,aAAc,OAAM,eAAe,KAAK;AACjD,UAAI,KAAK,SAAU,OAAM,WAAW,KAAK;AACzC,UAAI,KAAK,QAAS,OAAM,UAAU,KAAK;AACvC,aAAO;AAAA,IACX;AAAA,IAEA,KAAK,SAAS;AACV,YAAM,QAAQ,IAAI,MAAM,KAAK,YAAY,KAAK,UAAU,KAAK,WAAW,CAAC,CAAC;AAC1E,UAAI,KAAK,cAAe,OAAM,gBAAgB,KAAK;AACnD,UAAI,KAAK,cAAe,OAAM,gBAAgB,KAAK;AACnD,UAAI,KAAK,kBAAmB,OAAM,oBAAoB,KAAK;AAC3D,UAAI,KAAK,eAAgB,OAAM,iBAAiB,KAAK;AACrD,UAAI,KAAK,YAAa,OAAM,cAAc,KAAK;AAC/C,UAAI,KAAK,iBAAkB,OAAM,mBAAmB,KAAK;AACzD,UAAI,KAAK,QAAS,OAAM,UAAU,KAAK;AACvC,aAAO;AAAA,IACX;AAAA,IAEA,KAAK,kBAAkB;AACnB,YAAM,QAAQ,IAAI,eAAe,KAAK,QAAQ,KAAK,WAAW,CAAC,CAAC;AAChE,UAAI,KAAK,SAAU,OAAM,WAAW,KAAK;AACzC,UAAI,KAAK,QAAS,OAAM,UAAU,KAAK;AACvC,aAAO;AAAA,IACX;AAAA,IAEA,KAAK,SAAS;AACV,YAAM,YAAY,EAAE,GAAI,KAAK,WAAW,CAAC,GAAI,WAAW,KAAK,aAAa,QAAQ;AAClF,UAAI,KAAK,UAAW,WAAU,YAAY,KAAK;AAC/C,UAAI,KAAK,UAAW,WAAU,YAAY,KAAK;AAC/C,UAAI,KAAK,SAAU,WAAU,WAAW,KAAK;AAC7C,UAAI,KAAK,UAAW,WAAU,YAAY,KAAK;AAC/C,YAAM,QAAQ,IAAI,MAAM,KAAK,GAAG,KAAK,GAAG,KAAK,OAAO,KAAK,QAAQ,SAAS;AAC1E,UAAI,KAAK,SAAU,OAAM,WAAW,KAAK;AACzC,UAAI,KAAK,QAAS,OAAM,UAAU,KAAK;AACvC,YAAM,KAAK;AACX,aAAO;AAAA,IACX;AAAA,IAEA,KAAK,QAAQ;AACT,UAAI,CAAC,KAAK,UAAW,QAAO;AAC5B,YAAM,SAAS,IAAI,UAAU;AAC7B,YAAM,MAAM,OAAO,gBAAgB,eAAe,EAAE,KAAK,KAAK,SAAS,UAAU,eAAe;AAChG,YAAM,QAAQ,IAAI,cAAc,GAAG;AACnC,UAAI,CAAC,MAAO,QAAO;AACnB,YAAM,WAAW,MAAM,cAAc,WAAW,OAAO,IAAI;AAC3D,YAAM,YAAY,QAAQ;AAC1B,YAAM,QAAQ,IAAI,UAAU,QAAQ;AACpC,UAAI,KAAK,QAAS,OAAM,UAAU,KAAK;AACvC,aAAO;AAAA,IACX;AAAA,IAEA,KAAK,QAAQ;AACT,UAAI,CAAC,KAAK,UAAW,QAAO;AAC5B,YAAM,SAAS,IAAI,UAAU;AAC7B,YAAM,MAAM,OAAO,gBAAgB,eAAe,EAAE,KAAK,KAAK,SAAS,UAAU,eAAe;AAChG,YAAM,QAAQ,IAAI,cAAc,GAAG;AACnC,UAAI,CAAC,MAAO,QAAO;AACnB,YAAM,WAAW,MAAM,cAAc,WAAW,OAAO,IAAI;AAC3D,YAAM,YAAY,QAAQ;AAC1B,YAAM,QAAQ,IAAI,UAAU,QAAQ;AACpC,UAAI,KAAK,QAAS,OAAM,UAAU,KAAK;AACvC,aAAO;AAAA,IACX;AAAA,IAEA,KAAK,SAAS;AACV,YAAM,QAAQ,SAAS,gBAAgB,IAAI,OAAO;AAClD,YAAM,aAAa,KAAK,KAAK,CAAC;AAC9B,YAAM,aAAa,KAAK,KAAK,CAAC;AAC9B,YAAM,aAAa,SAAS,KAAK,KAAK;AACtC,YAAM,aAAa,UAAU,KAAK,MAAM;AACxC,YAAM,aAAa,QAAQ,KAAK,IAAI;AACpC,YAAM,aAAa,uBAAuB,MAAM;AAChD,YAAM,YAAY,KAAK;AACvB,YAAM,QAAQ,IAAI,WAAW,KAAK;AAClC,UAAI,KAAK,SAAU,OAAM,WAAW,KAAK;AACzC,UAAI,KAAK,QAAS,OAAM,UAAU,KAAK;AACvC,aAAO;AAAA,IACX;AAAA,IAEA,KAAK,QAAQ;AACT,UAAI,CAAC,KAAK,YAAa,QAAO;AAC9B,YAAM,SAAS,IAAI,UAAU;AAE7B,YAAM,MAAM,OAAO,gBAAgB,eAAe,EAAE,KAAK,KAAK,WAAW,UAAU,eAAe;AAClG,YAAM,YAAY,IAAI,cAAc,GAAG;AACvC,UAAI,CAAC,UAAW,QAAO;AACvB,YAAM,WAAW,MAAM,cAAc,WAAW,WAAW,IAAI;AAC/D,YAAM,YAAY,QAAQ;AAC1B,YAAM,QAAQ,IAAI,UAAU,QAAQ;AACpC,UAAI,KAAK,QAAS,OAAM,UAAU,KAAK;AACvC,aAAO;AAAA,IACX;AAAA,IAEA;AACI,cAAQ,KAAK,mCAAmC,KAAK,IAAI;AACzD,aAAO;AAAA,EACf;AACJ;AAKO,SAAS,UAAU,gBAAgB,YAAY;AAClD,QAAM,YAAY,OAAO,UAAU,CAAC;AACpC,QAAM,aAAa,CAAC;AASpB,QAAM,kBAAkB,oBAAI,IAAI;AAChC,aAAW,KAAK,WAAW;AACvB,QAAI,KAAK,EAAE,eAAe,EAAE,WAAW,MAAM,EAAE,aAAa;AACxD,YAAM,MAAM,gBAAgB,IAAI,EAAE,YAAY,OAAO,KAAK,CAAC;AAC3D,UAAI,KAAK,EAAE,OAAO;AAClB,sBAAgB,IAAI,EAAE,YAAY,SAAS,GAAG;AAAA,IAClD;AAAA,EACJ;AAEA,aAAW,SAAS,WAAW;AAC3B,UAAM,OAAO,eAAe,KAAK;AACjC,QAAI,CAAC,KAAM;AACX,QAAI,KAAK,SAAS,WAAW,MAAM,WAAW,gBAAgB,IAAI,MAAM,OAAO,GAAG;AAC9E,YAAM,SAAS,IAAI,IAAI,KAAK,qBAAqB,CAAC,CAAC;AACnD,iBAAW,MAAM,gBAAgB,IAAI,MAAM,OAAO,EAAG,QAAO,IAAI,EAAE;AAClE,WAAK,oBAAoB,MAAM,KAAK,MAAM;AAAA,IAC9C;AACA,eAAW,KAAK,IAAI;AAAA,EACxB;AAEA,QAAM,QAAQ;AAAA,IACV,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,WAAW,aAAa;AAAA,IACxB,MAAM;AAAA,IACN,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,UAAU,OAAO,iBAAiB,EAAE,GAAG,OAAO,eAAe,IAAI;AAAA,IACjE,MAAM,OAAO,eAAe;AAAA,IAC5B,QAAQ;AAAA,EACZ;AAEA,SAAO;AACX;AAKO,SAAS,UAAU,WAAW;AACjC,MAAI,CAAC,aAAa,UAAU,WAAW,aAAa;AAChD,YAAQ,MAAM,wCAAwC;AACtD,WAAO;AAAA,EACX;AAGA,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAO,QAAO;AAGnB,QAAM,iBAAiB,OAAO,UAAU,CAAC;AACzC,iBAAe,QAAQ,WAAS;AAE5B,QAAI,MAAM,cAAc,SAAS;AAC7B,UAAI,MAAM,aAAa,MAAM,UAAU,YAAY;AAC/C,cAAM,UAAU,WAAW,YAAY,MAAM,SAAS;AAAA,MAC1D;AACA,UAAI,MAAM,YAAY,MAAM,SAAS,YAAY;AAC7C,cAAM,SAAS,WAAW,YAAY,MAAM,QAAQ;AAAA,MACxD;AAAA,IACJ;AACA,QAAI,MAAM,SAAS,MAAM,MAAM,YAAY;AACvC,YAAM,MAAM,WAAW,YAAY,MAAM,KAAK;AAAA,IAClD,WAAW,MAAM,WAAW,MAAM,QAAQ,YAAY;AAClD,YAAM,QAAQ,WAAW,YAAY,MAAM,OAAO;AAAA,IACtD;AAAA,EACJ,CAAC;AAID,MAAI,OAAO,OAAQ,QAAO,OAAO,SAAS;AAAA,MAAQ,QAAO,SAAS,CAAC;AACnE,SAAO,eAAe;AACtB,MAAI,OAAO,aAAc,QAAO,aAAa,SAAS;AAAA,MAAQ,QAAO,eAAe,CAAC;AACrF,MAAI,OAAO,UAAW,QAAO,UAAU,SAAS;AAAA,MAAQ,QAAO,YAAY,CAAC;AAG5E,QAAM,QAAQ,oBAAI,IAAI;AAGtB,QAAM,YAAY,UAAU,OAAO,OAAO,OAAK,EAAE,SAAS,OAAO;AACjE,QAAM,YAAY,UAAU,OAAO,OAAO,OAAK,EAAE,SAAS,OAAO;AAGjE,aAAW,QAAQ,WAAW;AAC1B,UAAM,QAAQ,iBAAiB,IAAI;AACnC,QAAI,OAAO;AAEP,UAAI,KAAK,QAAS,OAAM,UAAU,KAAK;AACvC,2BAAqB,OAAO,IAAI;AAChC,aAAO,OAAO,KAAK,KAAK;AACxB,UAAI,KAAK,QAAS,OAAM,IAAI,KAAK,SAAS,KAAK;AAAA,IACnD;AAAA,EACJ;AAGA,aAAW,QAAQ,WAAW;AAC1B,UAAM,QAAQ,iBAAiB,IAAI;AACnC,QAAI,OAAO;AACP,UAAI,KAAK,QAAS,OAAM,UAAU,KAAK;AACvC,2BAAqB,OAAO,IAAI;AAChC,aAAO,OAAO,KAAK,KAAK;AACxB,UAAI,KAAK,QAAS,OAAM,IAAI,KAAK,SAAS,KAAK;AAAA,IACnD;AAAA,EACJ;AAGA,aAAW,QAAQ,WAAW;AAC1B,UAAM,QAAQ,MAAM,IAAI,KAAK,OAAO;AACpC,QAAI,SAAS,KAAK,qBAAqB,KAAK,kBAAkB,SAAS,GAAG;AACtE,iBAAW,WAAW,KAAK,mBAAmB;AAC1C,cAAM,QAAQ,MAAM,IAAI,OAAO;AAC/B,YAAI,CAAC,OAAO;AACR,kBAAQ,KAAK,4BAA4B,KAAK,SAAS,+BAA+B,OAAO,EAAE;AAC/F;AAAA,QACJ;AACA,YAAI;AACA,cAAI,OAAO,MAAM,oBAAoB,YAAY;AAC7C,kBAAM,gBAAgB,KAAK;AAAA,UAC/B,OAAO;AAEH,kBAAM,gBAAgB,KAAK,KAAK;AAChC,kBAAM,cAAc;AAAA,UACxB;AAAA,QACJ,SAAS,KAAK;AACV,kBAAQ,KAAK,uDAAuD,OAAO,aAAa,KAAK,OAAO,KAAK,GAAG;AAE5G,cAAI,CAAC,MAAM,gBAAgB,SAAS,KAAK,GAAG;AACxC,kBAAM,gBAAgB,KAAK,KAAK;AAAA,UACpC;AACA,gBAAM,cAAc;AAAA,QACxB;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAGA,aAAW,QAAQ,UAAU,QAAQ;AACjC,QAAI,KAAK,SAAS,SAAS;AACvB,YAAM,QAAQ,MAAM,IAAI,KAAK,OAAO;AACpC,UAAI,CAAC,MAAO;AACZ,UAAI,KAAK,mBAAmB;AACxB,cAAM,SAAS,MAAM,IAAI,KAAK,iBAAiB;AAC/C,YAAI,UAAU,MAAM,mBAAoB,OAAM,mBAAmB,MAAM;AAAA,MAC3E;AACA,UAAI,KAAK,iBAAiB;AACtB,cAAM,SAAS,MAAM,IAAI,KAAK,eAAe;AAC7C,YAAI,UAAU,MAAM,iBAAkB,OAAM,iBAAiB,MAAM;AAAA,MACvE;AAAA,IACJ;AAAA,EACJ;AAaA,aAAW,QAAQ,WAAW;AAC1B,UAAM,QAAQ,MAAM,IAAI,KAAK,OAAO;AACpC,QAAI,CAAC,MAAO;AAGZ,WAAO,MAAM;AACb,WAAO,MAAM;AAIb,QAAI,MAAM,aAAa,MAAM,UAAU,eAAe,OAAO;AACzD,YAAM,YAAY,MAAM,SAAS;AAAA,IACrC;AAEA,eAAW,SAAS,MAAM,mBAAmB,CAAC,GAAG;AAC7C,UAAI,CAAC,MAAO;AACZ,aAAO,MAAM;AACb,aAAO,MAAM;AAEb,YAAM,KAAK,MAAM,SAAS,MAAM;AAChC,UAAI,MAAM,GAAG,eAAe,MAAM,WAAW;AACzC,YAAI,GAAG,WAAY,IAAG,WAAW,YAAY,EAAE;AAC/C,cAAM,UAAU,YAAY,EAAE;AAAA,MAClC;AAEA,UAAI,MAAM,cAAc,WAAW,MAAM,aAClC,MAAM,UAAU,eAAe,MAAM,WAAW;AACnD,YAAI,MAAM,UAAU,WAAY,OAAM,UAAU,WAAW,YAAY,MAAM,SAAS;AACtF,cAAM,UAAU,YAAY,MAAM,SAAS;AAAA,MAC/C;AAIA,YAAM,cAAc;AAAA,IACxB;AAKA,QAAI,OAAO,MAAM,mBAAmB,WAAY,OAAM,eAAe;AACrE,QAAI,OAAO,MAAM,SAAS,YAAY;AAClC,UAAI;AAAE,cAAM,KAAK;AAAA,MAAG,SAAS,KAAK;AAAE,gBAAQ,KAAK,0CAA0C,GAAG;AAAA,MAAG;AAAA,IACrG;AAAA,EACJ;AAGA,MAAI,UAAU,YAAY,OAAO;AAC7B,UAAM,KAAK,UAAU;AACrB,WAAO,iBAAiB,EAAE,GAAG,GAAG;AAChC,UAAM,aAAa,WAAW,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,EAAE;AAAA,EAC5E;AACA,MAAI,UAAU,MAAM;AAChB,WAAO,cAAc,UAAU;AAAA,EACnC;AAEA,UAAQ,IAAI,4BAA4B,OAAO,OAAO,MAAM,iBAAiB,UAAU,IAAI,GAAG;AAC9F,SAAO,cAAc,IAAI,YAAY,8BAA8B,CAAC;AAGpE,MAAI,OAAO,kBAAkB,OAAO,OAAO,eAAe,kBAAkB,YAAY;AACpF,UAAM,QAAQ,OAAO;AACrB,UAAM,cAAc,QAAQ,MAAM,SAAS,EAAE,aAAa;AAC1D,WAAO,eAAe,cAAc,WAAW;AAAA,EACnD,OAAO;AAEH,WAAO,wBAAwB;AAAA,EACnC;AAEA,SAAO;AACX;AAKO,SAAS,cAAc,gBAAgB,YAAY;AACtD,QAAM,QAAQ,UAAU,aAAa;AACrC,QAAM,OAAO,KAAK,UAAU,OAAO,MAAM,CAAC;AAC1C,QAAM,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAC1D,QAAM,MAAM,IAAI,gBAAgB,IAAI;AAEpC,QAAM,IAAI,SAAS,cAAc,GAAG;AACpC,IAAE,OAAO;AACT,IAAE,WAAW,GAAG,cAAc,QAAQ,mBAAmB,GAAG,CAAC;AAC7D,WAAS,KAAK,YAAY,CAAC;AAC3B,IAAE,MAAM;AACR,WAAS,KAAK,YAAY,CAAC;AAC3B,MAAI,gBAAgB,GAAG;AAC3B;AAMO,SAAS,cAAc,MAAM;AAChC,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO,EAAE,OAAO,OAAO,OAAO,0BAA0B;AAC/F,MAAI,KAAK,WAAW,YAAa,QAAO,EAAE,OAAO,OAAO,OAAO,oDAAoD;AACnH,MAAI,CAAC,KAAK,WAAW,KAAK,UAAU,eAAgB,QAAO,EAAE,OAAO,OAAO,OAAO,wBAAwB,KAAK,OAAO,GAAG;AACzH,MAAI,CAAC,MAAM,QAAQ,KAAK,MAAM,EAAG,QAAO,EAAE,OAAO,OAAO,OAAO,sCAAsC;AACrG,SAAO;AAAA,IACH,OAAO;AAAA,IACP,MAAM,KAAK,QAAQ;AAAA,IACnB,YAAY,KAAK,OAAO;AAAA,IACxB,WAAW,KAAK,aAAa;AAAA,IAC7B,WAAW,KAAK,aAAa;AAAA,EACjC;AACJ;AAEO,SAAS,cAAc;AAC1B,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,OAAO;AACb,UAAM,SAAS;AACf,UAAM,WAAW,CAAC,MAAM;AACpB,YAAM,OAAO,EAAE,OAAO,MAAM,CAAC;AAC7B,UAAI,CAAC,KAAM,QAAO,QAAQ,KAAK;AAE/B,YAAM,SAAS,IAAI,WAAW;AAC9B,aAAO,SAAS,CAAC,OAAO;AACpB,YAAI;AACA,gBAAM,OAAO,KAAK,MAAM,GAAG,OAAO,MAAM;AACxC,gBAAM,aAAa,cAAc,IAAI;AACrC,cAAI,CAAC,WAAW,OAAO;AACnB,oBAAQ,MAAM,mCAAmC,WAAW,KAAK;AACjE,oBAAQ,EAAE,SAAS,OAAO,OAAO,WAAW,MAAM,CAAC;AACnD;AAAA,UACJ;AACA,yBAAe;AACf,gBAAM,SAAS,UAAU,IAAI;AAC7B,kBAAQ,EAAE,SAAS,QAAQ,WAAW,CAAC;AAAA,QAC3C,SAAS,KAAK;AACV,kBAAQ,MAAM,2CAA2C,GAAG;AAC5D,kBAAQ,EAAE,SAAS,OAAO,OAAO,4BAA4B,CAAC;AAAA,QAClE;AAAA,MACJ;AACA,aAAO,WAAW,IAAI;AAAA,IAC1B;AACA,UAAM,MAAM;AAAA,EAChB,CAAC;AACL;AAKO,SAAS,cAAc;AAC1B,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAO;AAEZ,QAAM,QAAQ,MAAM,UAAU,IAAI;AAElC,QAAM,eAAe,MAAM,iBAAiB,uEAAuE;AACnH,eAAa,QAAQ,QAAM,GAAG,OAAO,CAAC;AAEtC,QAAM,UAAU,IAAI,cAAc,EAAE,kBAAkB,KAAK;AAC3D,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,QAAM,KAAK,MAAM,QAAQ;AACzB,SAAO,QAAQ,GAAG,QAAQ;AAC1B,SAAO,SAAS,GAAG,SAAS;AAC5B,QAAM,MAAM,OAAO,WAAW,IAAI;AAClC,MAAI,MAAM,GAAG,CAAC;AAEd,QAAM,MAAM,IAAI,MAAM;AACtB,QAAM,UAAU,IAAI,KAAK,CAAC,OAAO,GAAG,EAAE,MAAM,8BAA8B,CAAC;AAC3E,QAAM,MAAM,IAAI,gBAAgB,OAAO;AAEvC,MAAI,SAAS,MAAM;AAEf,QAAI,YAAY;AAChB,QAAI,SAAS,GAAG,GAAG,GAAG,OAAO,GAAG,MAAM;AACtC,QAAI,UAAU,KAAK,GAAG,GAAG,GAAG,OAAO,GAAG,MAAM;AAC5C,QAAI,gBAAgB,GAAG;AAEvB,WAAO,OAAO,UAAQ;AAClB,YAAM,IAAI,SAAS,cAAc,GAAG;AACpC,QAAE,OAAO,IAAI,gBAAgB,IAAI;AACjC,QAAE,WAAW;AACb,eAAS,KAAK,YAAY,CAAC;AAC3B,QAAE,MAAM;AACR,eAAS,KAAK,YAAY,CAAC;AAAA,IAC/B,GAAG,WAAW;AAAA,EAClB;AACA,MAAI,MAAM;AACd;AAKO,SAAS,YAAY;AACxB,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAO;AAEZ,QAAM,QAAQ,MAAM,UAAU,IAAI;AAClC,QAAM,eAAe,MAAM,iBAAiB,uEAAuE;AACnH,eAAa,QAAQ,QAAM,GAAG,OAAO,CAAC;AAEtC,QAAM,UAAU,IAAI,cAAc,EAAE,kBAAkB,KAAK;AAC3D,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,QAAM,KAAK,MAAM,QAAQ;AACzB,SAAO,QAAQ,GAAG,QAAQ;AAC1B,SAAO,SAAS,GAAG,SAAS;AAC5B,QAAM,MAAM,OAAO,WAAW,IAAI;AAClC,MAAI,MAAM,GAAG,CAAC;AAEd,QAAM,MAAM,IAAI,MAAM;AACtB,QAAM,UAAU,IAAI,KAAK,CAAC,OAAO,GAAG,EAAE,MAAM,8BAA8B,CAAC;AAC3E,QAAM,MAAM,IAAI,gBAAgB,OAAO;AAEvC,MAAI,SAAS,MAAM;AACf,QAAI,YAAY;AAChB,QAAI,SAAS,GAAG,GAAG,GAAG,OAAO,GAAG,MAAM;AACtC,QAAI,UAAU,KAAK,GAAG,GAAG,GAAG,OAAO,GAAG,MAAM;AAC5C,QAAI,gBAAgB,GAAG;AAEvB,WAAO,OAAO,UAAQ;AAClB,UAAI,CAAC,KAAM;AACX,gBAAU,UAAU,MAAM;AAAA,QACtB,IAAI,cAAc,EAAE,aAAa,KAAK,CAAC;AAAA,MAC3C,CAAC,EAAE,MAAM,SAAO,QAAQ,KAAK,6CAA6C,GAAG,CAAC;AAAA,IAClF,GAAG,WAAW;AAAA,EAClB;AACA,MAAI,MAAM;AACd;AAKO,SAAS,YAAY;AACxB,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAO;AAEZ,QAAM,QAAQ,MAAM,UAAU,IAAI;AAClC,QAAM,eAAe,MAAM,iBAAiB,uEAAuE;AACnH,eAAa,QAAQ,QAAM,GAAG,OAAO,CAAC;AAEtC,QAAM,UAAU,IAAI,cAAc,EAAE,kBAAkB,KAAK;AAC3D,YAAU,UAAU,UAAU,OAAO,EAChC,MAAM,SAAO,QAAQ,KAAK,6CAA6C,GAAG,CAAC;AACpF;AAKO,SAAS,cAAc;AAC1B,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAO;AAEZ,QAAM,QAAQ,MAAM,UAAU,IAAI;AAClC,QAAM,eAAe,MAAM,iBAAiB,uEAAuE;AACnH,eAAa,QAAQ,QAAM,GAAG,OAAO,CAAC;AAEtC,QAAM,UAAU,IAAI,cAAc,EAAE,kBAAkB,KAAK;AAC3D,QAAM,cAAc,OAAO,KAAK,IAAI,QAAQ;AAC5C,cAAY,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAUf,OAAO;AAAA;AAAA,KAElB;AACD,cAAY,SAAS,MAAM;AAC3B,cAAY,MAAM;AAClB,aAAW,MAAM,YAAY,MAAM,GAAG,GAAG;AAC7C;AAKO,SAAS,cAAc;AAC1B,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAO;AAGZ,QAAM,iBAAiB,OAAO,UAAU,CAAC;AACzC,iBAAe,QAAQ,WAAS;AAC5B,QAAI,MAAM,cAAc,SAAS;AAC7B,UAAI,MAAM,aAAa,MAAM,UAAU,YAAY;AAC/C,cAAM,UAAU,WAAW,YAAY,MAAM,SAAS;AAAA,MAC1D;AACA,UAAI,MAAM,YAAY,MAAM,SAAS,YAAY;AAC7C,cAAM,SAAS,WAAW,YAAY,MAAM,QAAQ;AAAA,MACxD;AAAA,IACJ;AACA,QAAI,MAAM,SAAS,MAAM,MAAM,YAAY;AACvC,YAAM,MAAM,WAAW,YAAY,MAAM,KAAK;AAAA,IAClD,WAAW,MAAM,WAAW,MAAM,QAAQ,YAAY;AAClD,YAAM,QAAQ,WAAW,YAAY,MAAM,OAAO;AAAA,IACtD;AAAA,EACJ,CAAC;AAGD,QAAM;AAAA,IACF;AAAA,EACJ,EAAE,QAAQ,QAAM,GAAG,OAAO,CAAC;AAG3B,MAAI,OAAO,OAAQ,QAAO,OAAO,SAAS;AAAA,MAAQ,QAAO,SAAS,CAAC;AACnE,SAAO,eAAe;AACtB,MAAI,OAAO,aAAc,QAAO,aAAa,SAAS;AAAA,MAAQ,QAAO,eAAe,CAAC;AACrF,MAAI,OAAO,UAAW,QAAO,UAAU,SAAS;AAAA,MAAQ,QAAO,YAAY,CAAC;AAE5E,MAAI,OAAO,OAAO,uBAAuB,YAAY;AACjD,WAAO,mBAAmB;AAAA,EAC9B;AACA,MAAI,OAAO,OAAO,uBAAuB,YAAY;AACjD,WAAO,mBAAmB;AAAA,EAC9B;AAGA,MAAI;AACA,iBAAa,WAAW,oBAAoB;AAC5C,iBAAa,WAAW,yBAAyB;AACjD,UAAM,MAAM,OAAO;AACnB,QAAI,KAAK;AACL,mBAAa,WAAW,sBAAsB,GAAG,EAAE;AACnD,mBAAa,WAAW,2BAA2B,GAAG,EAAE;AAAA,IAC5D;AAAA,EACJ,SAAS,GAAG;AAAA,EAAC;AAEb,UAAQ,IAAI,gCAAgC;AAC5C,MAAI,OAAO,OAAO,yBAAyB,YAAY;AACnD,WAAO,qBAAqB;AAAA,EAChC;AACJ;AAKO,SAAS,iBAAiB,OAAO;AACpC,QAAM,YAAY,OAAO,UAAU,CAAC;AACpC,MAAI,CAAC,SAAS,MAAM,KAAK,MAAM,GAAI,QAAO,CAAC;AAE3C,QAAM,aAAa,MAAM,YAAY;AACrC,QAAM,UAAU,CAAC;AAEjB,aAAW,SAAS,WAAW;AAC3B,QAAI,cAAc;AAElB,QAAI,MAAM,cAAc,UAAU,MAAM,cAAc,QAAQ;AAC1D,YAAM,QAAQ,MAAM;AACpB,UAAI,OAAO;AAEP,cAAM,UAAU,MAAM,iBAAiB,aAAa;AACpD,gBAAQ,QAAQ,QAAM;AAClB,cAAI,GAAG,YAAa,gBAAe,GAAG,cAAc;AAAA,QACxD,CAAC;AAED,cAAM,aAAa,MAAM,iBAAiB,iBAAiB;AAC3D,mBAAW,QAAQ,QAAM;AACrB,cAAI,GAAG,YAAa,gBAAe,GAAG,cAAc;AAAA,QACxD,CAAC;AAAA,MACL;AAAA,IACJ,WAAW,MAAM,cAAc,SAAS;AACpC,oBAAc,MAAM,aAAa;AAAA,IACrC;AAEA,kBAAc,YAAY,KAAK;AAC/B,QAAI,eAAe,YAAY,YAAY,EAAE,SAAS,UAAU,GAAG;AAC/D,cAAQ,KAAK;AAAA,QACT;AAAA,QACA,MAAM;AAAA,QACN,MAAM,MAAM;AAAA,QACZ,GAAG,MAAM,KAAK;AAAA,QACd,GAAG,MAAM,KAAK;AAAA,MAClB,CAAC;AAAA,IACL;AAAA,EACJ;AAEA,SAAO;AACX;AAKO,SAAS,sBAAsB;AAClC,SAAO,oBAAoB;AAAA,IACvB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,EACd;AACJ;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/core/ZoomPan.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable */\n// Zoom and Pan controls - combined from zoomFunction.js + panCanvas.js\n// Depends on globals: svg, freehandCanvas, currentZoom, currentViewBox, isPanningToolActive, isPanning\n// Depends on globals: minScale, maxScale, zoomInBtn, zoomOutBtn, zoomPercentSpan, panStart, startCanvasX, startCanvasY\n\n// === Zoom Functions ===\nlet currentY = 0;\nconst scrollRate = 50;\n\nfunction updateZoomDisplay() {\n zoomPercentSpan.innerText = Math.round(currentZoom * 100) + \"%\";\n}\n\nfunction updateViewBox(anchorX = null, anchorY = null) {\n const width = window.innerWidth;\n const height = window.innerHeight;\n const scaledWidth = width / currentZoom;\n const scaledHeight = height / currentZoom;\n\n let centerX, centerY;\n\n if (anchorX === null || anchorY === null) {\n centerX = currentViewBox.x + (currentViewBox.width / 2);\n centerY = currentViewBox.y + (currentViewBox.height / 2);\n } else {\n\n centerX = anchorX;\n centerY = anchorY;\n }\n\n const viewBoxX = centerX - (scaledWidth / 2);\n const viewBoxY = centerY - (scaledHeight / 2);\n\n freehandCanvas.setAttribute(\n \"viewBox\",\n `${viewBoxX} ${viewBoxY} ${scaledWidth} ${scaledHeight}`\n );\n\n currentViewBox.x = viewBoxX;\n currentViewBox.y = viewBoxY;\n currentViewBox.width = scaledWidth;\n currentViewBox.height = scaledHeight;\n}\n\nzoomInBtn.addEventListener(\"click\", function() {\n currentZoom *= 1.1;\n if (currentZoom > maxScale) currentZoom = maxScale;\n updateViewBox();\n updateZoomDisplay();\n});\n\nzoomOutBtn.addEventListener(\"click\", function() {\n currentZoom /= 1.1;\n if (currentZoom < minScale) currentZoom = minScale;\n updateViewBox();\n updateZoomDisplay();\n});\n\n// Exposed for React Footer buttons \u2014 zoom from center of canvas\nwindow.zoomFromCenter = function(direction) {\n if (direction > 0) {\n currentZoom *= 1.1;\n if (currentZoom > maxScale) currentZoom = maxScale;\n } else {\n currentZoom /= 1.1;\n if (currentZoom < minScale) currentZoom = minScale;\n }\n updateViewBox(); // null anchors = zoom from center\n updateZoomDisplay();\n // Sync React zoom state\n if (window.__sketchStoreApi && window.__sketchStoreApi.setZoom) {\n window.__sketchStoreApi.setZoom(currentZoom);\n }\n};\n\nwindow.zoomReset = function() {\n // Issue #24 bug #5: reset zoom in place around the current viewport\n // centre \u2014 do NOT recenter to (0, 0). Recentering used to make whatever\n // the user had on screen vanish until they panned back to it.\n const cx = currentViewBox.x + currentViewBox.width / 2;\n const cy = currentViewBox.y + currentViewBox.height / 2;\n\n currentZoom = 1;\n const rect = freehandCanvas.getBoundingClientRect();\n const vbW = rect.width || window.innerWidth;\n const vbH = rect.height || window.innerHeight;\n\n currentViewBox.x = cx - vbW / 2;\n currentViewBox.y = cy - vbH / 2;\n currentViewBox.width = vbW;\n currentViewBox.height = vbH;\n freehandCanvas.setAttribute(\n \"viewBox\",\n `${currentViewBox.x} ${currentViewBox.y} ${vbW} ${vbH}`\n );\n updateZoomDisplay();\n if (window.__sketchStoreApi && window.__sketchStoreApi.setZoom) {\n window.__sketchStoreApi.setZoom(1);\n }\n};\n\nfunction getShapeBoundsForFit(shape) {\n if (!shape) return null;\n\n const selection = window.multiSelection;\n if (selection && typeof selection.getShapeBounds === \"function\") {\n try {\n const bounds = selection.getShapeBounds(shape);\n if (bounds && [bounds.x, bounds.y, bounds.width, bounds.height].every(Number.isFinite)) {\n return bounds;\n }\n } catch {}\n }\n\n // Fall back to the common shape interface when selection is unavailable.\n // Accessing x/y instead of boundingBox preserves freehand move offsets.\n const bounds = {\n x: Number(shape.x),\n y: Number(shape.y),\n width: Number(shape.width),\n height: Number(shape.height),\n };\n return Object.values(bounds).every(Number.isFinite) ? bounds : null;\n}\n\nwindow.zoomFit = function() {\n if (!window.shapes || window.shapes.length === 0) {\n if (window.zoomReset) window.zoomReset();\n return;\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n window.shapes.forEach(shape => {\n const bounds = getShapeBoundsForFit(shape);\n if (!bounds) return;\n \n // Normalize coordinates just in case width/height is negative\n const x1 = Math.min(bounds.x, bounds.x + bounds.width);\n const x2 = Math.max(bounds.x, bounds.x + bounds.width);\n const y1 = Math.min(bounds.y, bounds.y + bounds.height);\n const y2 = Math.max(bounds.y, bounds.y + bounds.height);\n\n minX = Math.min(minX, x1);\n minY = Math.min(minY, y1);\n maxX = Math.max(maxX, x2);\n maxY = Math.max(maxY, y2);\n });\n\n if (minX === Infinity) {\n if (window.zoomReset) window.zoomReset();\n return;\n }\n\n const rect = freehandCanvas.getBoundingClientRect();\n const screenW = rect.width || window.innerWidth;\n const screenH = rect.height || window.innerHeight;\n\n const contentW = maxX - minX;\n const contentH = maxY - minY;\n \n // Add 10% padding\n const paddingX = Math.max(50, contentW * 0.1);\n const paddingY = Math.max(50, contentH * 0.1);\n\n const paddedW = contentW + paddingX * 2;\n const paddedH = contentH + paddingY * 2;\n\n // Calculate required zoom to fit the padded content in the screen\n const zoomX = screenW / paddedW;\n const zoomY = screenH / paddedH;\n \n let newZoom = Math.min(zoomX, zoomY);\n newZoom = Math.max(minScale, Math.min(newZoom, maxScale));\n\n // Center coordinate of the content\n const cx = minX + contentW / 2;\n const cy = minY + contentH / 2;\n\n // Set the new viewBox and zoom\n currentZoom = newZoom;\n const vbW = screenW / currentZoom;\n const vbH = screenH / currentZoom;\n\n currentViewBox.x = cx - vbW / 2;\n currentViewBox.y = cy - vbH / 2;\n currentViewBox.width = vbW;\n currentViewBox.height = vbH;\n\n freehandCanvas.setAttribute(\n \"viewBox\",\n `${currentViewBox.x} ${currentViewBox.y} ${vbW} ${vbH}`\n );\n \n updateZoomDisplay();\n if (window.__sketchStoreApi && window.__sketchStoreApi.setZoom) {\n window.__sketchStoreApi.setZoom(currentZoom);\n }\n};\n\nfreehandCanvas.addEventListener(\"wheel\", function(e) {\n if (!e.ctrlKey) return;\n e.preventDefault();\n\n // Determine the zoom delta\n const delta = e.deltaY > 0 ? -0.1 : 0.1;\n let newZoom = currentZoom + delta;\n if (newZoom < minScale) newZoom = minScale;\n if (newZoom > maxScale) newZoom = maxScale;\n\n // Get canvas bounding rect \u2014 this MUST be the SVG element's actual\n // size, not the window's. In split mode the canvas pane is narrower\n // than the viewport; using window.innerWidth here would produce a\n // viewBox aspect that doesn't match the element, and (with\n // preserveAspectRatio=\"none\" on the host) the content gets stretched\n // / squeezed on every zoom step.\n const rect = freehandCanvas.getBoundingClientRect();\n\n // Calculate mouse position relative to the canvas in pixels\n const mouseX = e.clientX - rect.left;\n const mouseY = e.clientY - rect.top;\n\n // Determine what fraction of the canvas the mouse is at\n const mouseFracX = mouseX / rect.width;\n const mouseFracY = mouseY / rect.height;\n\n // Compute the current viewBox coordinate under the mouse.\n // currentViewBox.width and .height represent the current viewBox dimensions.\n const anchorViewBoxX = currentViewBox.x + mouseFracX * currentViewBox.width;\n const anchorViewBoxY = currentViewBox.y + mouseFracY * currentViewBox.height;\n\n // New viewBox dimensions sized to the *element*, scaled by the new\n // zoom. This keeps the viewBox aspect ratio matching the element so\n // shapes stay undistorted.\n const newViewBoxWidth = rect.width / newZoom;\n const newViewBoxHeight = rect.height / newZoom;\n \n // Compute the new viewBox's x and y so that the anchor remains at the same screen fraction.\n // That means:\n // newViewBox.x + mouseFracX * newViewBoxWidth === anchorViewBoxX\n // Solve for newViewBox.x:\n const newViewBoxX = anchorViewBoxX - mouseFracX * newViewBoxWidth;\n const newViewBoxY = anchorViewBoxY - mouseFracY * newViewBoxHeight;\n \n // Update the viewBox attribute with the new values.\n freehandCanvas.setAttribute(\n \"viewBox\",\n `${newViewBoxX} ${newViewBoxY} ${newViewBoxWidth} ${newViewBoxHeight}`\n );\n \n // Update our state\n currentZoom = newZoom;\n currentViewBox = {\n x: newViewBoxX,\n y: newViewBoxY,\n width: newViewBoxWidth,\n height: newViewBoxHeight\n };\n\n updateZoomDisplay();\n // Sync React zoom state\n if (window.__sketchStoreApi && window.__sketchStoreApi.setZoom) {\n window.__sketchStoreApi.setZoom(currentZoom);\n }\n});\n\n// Function to resize the canvas to fill the screen (initial setup)\nfunction resizeCanvas() {\n const width = window.innerWidth;\n const height = window.innerHeight;\n\n freehandCanvas.style.width = `${width}px`;\n freehandCanvas.style.height = `${height}px`;\n\n // Set initial viewBox based on initial zoom\n updateViewBox(); // Initial center anchor\n}\n\n\n\nlet isMiddleMousePanning = false;\n\nfreehandCanvas.addEventListener(\"mousedown\", function (e) {\n // Middle mouse button panning\n if (e.button === 1) {\n e.preventDefault();\n isMiddleMousePanning = true;\n isPanning = true;\n startCanvasX = e.clientX;\n startCanvasY = e.clientY;\n panStart = { x: e.clientX, y: e.clientY };\n freehandCanvas.style.cursor = 'grabbing';\n return;\n }\n if (isPanningToolActive) {\n isPanning = true;\n startCanvasX = e.clientX;\n startCanvasY = e.clientY;\n panStart = { x: e.clientX, y: e.clientY };\n freehandCanvas.style.cursor = 'grabbing';\n }\n});\n\nfreehandCanvas.addEventListener(\"mousemove\", (e) => {\n if (!isPanning) return;\n\n const dx = e.clientX - panStart.x;\n const dy = e.clientY - panStart.y;\n const dxViewBox = dx / currentZoom;\n const dyViewBox = dy / currentZoom;\n\n currentViewBox.x -= dxViewBox;\n currentViewBox.y -= dyViewBox;\n\n freehandCanvas.setAttribute(\n \"viewBox\",\n `${currentViewBox.x} ${currentViewBox.y} ${currentViewBox.width} ${currentViewBox.height}`\n );\n\n panStart = { x: e.clientX, y: e.clientY };\n});\n\nfreehandCanvas.addEventListener(\"mouseup\", (e) => {\n if (isMiddleMousePanning) {\n isMiddleMousePanning = false;\n isPanning = false;\n freehandCanvas.style.cursor = '';\n return;\n }\n if(isPanningToolActive)\n {\n isPanning = false;\n freehandCanvas.style.cursor = 'grab';\n }\n});\n\nfreehandCanvas.addEventListener(\"mouseleave\", () => {\n if (isMiddleMousePanning) {\n isMiddleMousePanning = false;\n isPanning = false;\n freehandCanvas.style.cursor = '';\n return;\n }\n if(isPanningToolActive)\n {\n isPanning = false;\n freehandCanvas.style.cursor = 'grab';\n }\n});\n\n// Prevent default middle-click auto-scroll behavior\nfreehandCanvas.addEventListener(\"auxclick\", (e) => {\n if (e.button === 1) e.preventDefault();\n});\n\n\nsvg.addEventListener(\"wheel\", (e) => {\n e.preventDefault();\n if (e.ctrlKey) return; // Ignore zoom gestures\n\n if (e.shiftKey) {\n // Pan sideways when Shift is held\n currentViewBox.x += e.deltaY > 0 ? scrollRate : -scrollRate;\n } else {\n // Pan vertically\n currentViewBox.y += e.deltaY > 0 ? scrollRate : -scrollRate;\n }\n\n svg.setAttribute(\n \"viewBox\",\n `${currentViewBox.x} ${currentViewBox.y} ${currentViewBox.width} ${currentViewBox.height}`\n );\n});\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["bounds"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/tools/codeTool.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable */\n// Code tool event handlers - extracted from writeCode.js\nimport {\n pushCreateAction,\n pushDeleteActionWithAttachments,\n pushTransformAction,\n pushOptionsChangeAction,\n pushFrameAttachmentAction,\n setTextReferences,\n updateSelectedElement\n} from '../core/UndoRedo.js';\nimport { cleanupAttachments, updateAttachedArrows } from './arrowTool.js';\n\nfunction getThemeStroke() { if (typeof document === \"undefined\") return \"#fff\"; return document.body && document.body.classList.contains(\"theme-dark\") ? \"#fff\" : \"#1a1a2e\"; }\n\nlet codeTextSize = \"25px\";\nlet codeTextFont = \"lixCode\";\nlet codeTextColor = null;\nlet codeTextAlign = \"left\";\nlet codeLanguage = \"auto\";\n\nlet codeTextColorOptions = document.querySelectorAll(\".textColorSpan\");\nlet codeTextFontOptions = document.querySelectorAll(\".textFontSpan\");\nlet codeTextSizeOptions = document.querySelectorAll(\".textSizeSpan\");\nlet codeTextAlignOptions = document.querySelectorAll(\".textAlignSpan\"); \n\nlet selectedCodeBlock = null;\nlet codeSelectionBox = null;\nlet codeResizeHandles = {};\nlet codeDragOffsetX, codeDragOffsetY;\nlet isCodeDragging = false;\nlet isCodeResizing = false;\nlet currentCodeResizeHandle = null;\nlet startCodeBBox = null;\nlet startCodeFontSize = null;\nlet startCodePoint = null;\nlet isCodeRotating = false;\nlet codeRotationStartAngle = 0;\nlet codeRotationStartTransform = null;\nlet initialCodeHandlePosRelGroup = null;\nlet initialCodeGroupTx = 0;\nlet initialCodeGroupTy = 0;\n\n\n// Frame attachment variables for code blocks\nlet draggedCodeInitialFrame = null;\nlet hoveredCodeFrame = null;\n\n\nsetTextReferences(selectedCodeBlock, updateCodeSelectionFeedback, svg);\n\n\n// Convert group element to our CodeShape class\nfunction wrapCodeElement(groupElement) {\n const codeShape = new CodeShape(groupElement);\n // Double-click to edit code block (works with any tool)\n groupElement.addEventListener('dblclick', (e) => {\n e.stopPropagation();\n const codeElement = groupElement.querySelector('text');\n if (codeElement) {\n makeCodeEditable(codeElement, groupElement, e);\n }\n });\n return codeShape;\n}\n\nfunction getSVGCoordinates(event, element = svg) {\n if (!svg || !svg.createSVGPoint) {\n console.error(\"SVG element or createSVGPoint method not available.\");\n return { x: 0, y: 0 };\n }\n let pt = svg.createSVGPoint();\n pt.x = event.clientX;\n pt.y = event.clientY;\n\n try {\n let screenCTM = (element && typeof element.getScreenCTM === 'function' && element.getScreenCTM()) || svg.getScreenCTM();\n if (!screenCTM) {\n console.error(\"Could not get Screen CTM.\");\n return { x: event.clientX, y: event.clientY };\n }\n let svgPoint = pt.matrixTransform(screenCTM.inverse());\n return {\n x: svgPoint.x,\n y: svgPoint.y,\n };\n } catch (error) {\n console.error(\"Error getting SVG coordinates:\", error);\n return { x: event.clientX, y: event.clientY };\n }\n}\n\n\nfunction addCodeBlock(event) {\n let { x, y } = getSVGCoordinates(event);\n\n let gElement = document.createElementNS(\"http://www.w3.org/2000/svg\", \"g\");\n gElement.setAttribute(\"data-type\", \"code-group\");\n gElement.setAttribute(\"transform\", `translate(${x}, ${y})`);\n\n // Create background rectangle for code block\n let backgroundRect = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n backgroundRect.setAttribute(\"class\", \"code-background\");\n backgroundRect.setAttribute(\"x\", -10); // Padding\n backgroundRect.setAttribute(\"y\", -10); // Padding\n backgroundRect.setAttribute(\"width\", 300); // Initial width\n backgroundRect.setAttribute(\"height\", 60); // Initial height\n backgroundRect.setAttribute(\"fill\", \"#161b22\"); // GitHub dark background\n backgroundRect.setAttribute(\"stroke\", \"#30363d\");\n backgroundRect.setAttribute(\"stroke-width\", \"1\");\n backgroundRect.setAttribute(\"rx\", \"6\"); // Rounded corners\n backgroundRect.setAttribute(\"ry\", \"6\");\n gElement.appendChild(backgroundRect);\n\n // Create SVG text element\n let codeElement = document.createElementNS(\"http://www.w3.org/2000/svg\", \"text\");\n let textAlignElement = \"start\";\n if (codeTextAlign === \"center\") textAlignElement = \"middle\";\n else if (codeTextAlign === \"right\") textAlignElement = \"end\";\n\n codeElement.setAttribute(\"x\", 0);\n codeElement.setAttribute(\"y\", 0);\n codeElement.setAttribute(\"fill\", codeTextColor ?? getThemeStroke());\n codeElement.setAttribute(\"font-size\", codeTextSize);\n codeElement.setAttribute(\"font-family\", codeTextFont);\n codeElement.setAttribute(\"text-anchor\", textAlignElement);\n codeElement.setAttribute(\"cursor\", \"text\");\n codeElement.setAttribute(\"white-space\", \"pre\");\n codeElement.setAttribute(\"dominant-baseline\", \"hanging\");\n codeElement.textContent = \"\";\n\n gElement.setAttribute(\"data-x\", x);\n gElement.setAttribute(\"data-y\", y);\n codeElement.setAttribute(\"data-initial-size\", codeTextSize);\n codeElement.setAttribute(\"data-initial-font\", codeTextFont);\n codeElement.setAttribute(\"data-initial-color\", codeTextColor ?? getThemeStroke());\n codeElement.setAttribute(\"data-initial-align\", codeTextAlign);\n codeElement.setAttribute(\"data-language\", codeLanguage);\n codeElement.setAttribute(\"data-type\", \"code\");\n gElement.appendChild(codeElement);\n svg.appendChild(gElement);\n \n // Attach ID to both group and code element\n const shapeID = `code-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n gElement.setAttribute('id', shapeID);\n codeElement.setAttribute('id', `${shapeID}-code`);\n \n // Create CodeShape wrapper for frame functionality\n const codeShape = wrapCodeElement(gElement);\n \n // Add to shapes array for arrow attachment and frame functionality\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.push(codeShape);\n }\n \n pushCreateAction({\n type: 'code',\n element: codeShape,\n shapeName: 'code'\n });\n\n makeCodeEditable(codeElement, gElement);\n}\n\n// Function to update highlight.js on content change\nfunction updateSyntaxHighlighting(editor) {\n if (window.hljs) {\n window.hljs.highlightElement(editor);\n }\n}\n\nfunction adjustCodeEditorSize(editor) {\n const foreignObject = editor.closest('foreignObject');\n const codeContainer = editor.closest('.svg-code-container');\n if (!foreignObject || !codeContainer) return;\n\n const svgRect = svg.getBoundingClientRect();\n\n // Allow textarea to expand freely\n editor.style.overflow = 'visible';\n editor.style.height = 'auto';\n editor.style.width = 'auto';\n editor.style.whiteSpace = 'pre'; // No wrapping\n\n // Calculate content size\n let minContentWidth = editor.scrollWidth + (parseFloat(codeContainer.style.paddingLeft) || 0) + (parseFloat(codeContainer.style.paddingRight) || 0);\n let minContentHeight = editor.scrollHeight + (parseFloat(codeContainer.style.paddingTop) || 0) + (parseFloat(codeContainer.style.paddingBottom) || 0);\n\n // Clamp to SVG bounds\n const editorRect = editor.getBoundingClientRect();\n const maxWidth = svgRect.width - (editorRect.left - svgRect.left);\n const maxHeight = svgRect.height - (editorRect.top - svgRect.top);\n\n let newWidth = Math.min(Math.max(minContentWidth, 50), maxWidth);\n let newHeight = Math.min(Math.max(minContentHeight, 30), maxHeight);\n\n foreignObject.setAttribute('width', newWidth);\n foreignObject.setAttribute('height', newHeight);\n\n editor.style.width = `${newWidth - (parseFloat(codeContainer.style.paddingLeft) || 0) - (parseFloat(codeContainer.style.paddingRight) || 0)}px`;\n editor.style.height = `${newHeight - (parseFloat(codeContainer.style.paddingTop) || 0) - (parseFloat(codeContainer.style.paddingBottom) || 0)}px`;\n\n // Overflow only if content exceeds container\n if (editor.scrollHeight > editor.clientHeight || editor.scrollWidth > editor.clientWidth) {\n editor.style.overflow = 'auto';\n } else {\n editor.style.overflow = 'hidden';\n }\n\n if (selectedCodeBlock && selectedCodeBlock.contains(foreignObject)) {\n updateCodeSelectionFeedback();\n }\n}\n\n\nfunction makeCodeEditable(codeElement, groupElement, clickEvent = null) {\n\n if (document.querySelector(\".svg-code-editor\")) {\n return;\n }\n\n if (selectedCodeBlock) {\n deselectCodeBlock();\n }\n\n // Hide the selection feedback for the element being edited\n removeCodeSelectionFeedback();\n\n // Create a container div for the code editor\n let editorContainer = document.createElement(\"div\");\n editorContainer.className = \"svg-code-container\";\n editorContainer.style.position = \"absolute\";\n editorContainer.style.zIndex = \"10000\";\n editorContainer.style.backgroundColor = \"#161b22\";\n editorContainer.style.border = \"1px solid #30363d\";\n editorContainer.style.borderRadius = \"6px\";\n editorContainer.style.padding = \"12px\";\n editorContainer.style.fontFamily = \"monospace\";\n editorContainer.style.overflow = \"hidden\";\n editorContainer.style.minWidth = \"200px\";\n editorContainer.style.minHeight = \"40px\";\n\n // Create the actual code editor\n let input = document.createElement(\"div\");\n input.className = \"svg-code-editor\";\n input.contentEditable = true;\n input.style.outline = \"none\";\n input.style.minHeight = \"30px\";\n input.style.maxHeight = \"400px\";\n input.style.overflowY = \"auto\";\n input.style.whiteSpace = \"pre\";\n input.style.fontFamily = \"lixCode, Consolas, 'Courier New', monospace\";\n input.style.fontSize = codeElement.getAttribute(\"font-size\") || codeTextSize;\n input.style.color = \"#c9d1d9\";\n input.style.lineHeight = \"1.4\";\n input.style.tabSize = \"4\";\n input.style.background = \"transparent\";\n\n // FIXED: Use the improved text extraction\n let codeContent = extractTextFromCodeElement(codeElement);\n\n // Set initial content with plain text (no highlighting initially)\n input.textContent = codeContent;\n\n editorContainer.appendChild(input);\n\n // Position the editor\n const svgRect = svg.getBoundingClientRect();\n let left = svgRect.left, top = svgRect.top;\n if (clickEvent) {\n left += clickEvent.clientX - svgRect.left;\n top += clickEvent.clientY - svgRect.top;\n } else {\n // fallback to code block position if no click event\n let groupTransformMatrix = svg.createSVGMatrix();\n if (groupElement && groupElement.transform && groupElement.transform.baseVal) {\n const transformList = groupElement.transform.baseVal;\n if (transformList.numberOfItems > 0) {\n const consolidatedTransform = transformList.consolidate();\n if (consolidatedTransform) {\n groupTransformMatrix = consolidatedTransform.matrix;\n }\n }\n }\n const codeBBox = codeElement.getBBox();\n let pt = svg.createSVGPoint();\n pt.x = codeBBox.x - 8;\n pt.y = codeBBox.y - 8;\n let screenPt = pt.matrixTransform(groupTransformMatrix.multiply(svg.getScreenCTM()));\n left = screenPt.x + svgRect.left;\n top = screenPt.y + svgRect.top;\n }\n editorContainer.style.left = `${left}px`;\n editorContainer.style.top = `${top}px`;\n\n document.body.appendChild(editorContainer);\n\n // Auto-resize function\n const adjustSize = () => {\n const maxWidth = svgRect.width - (left - svgRect.left);\n const maxHeight = svgRect.height - (top - svgRect.top);\n\n let newWidth = Math.max(300, Math.min(input.scrollWidth + 20, maxWidth));\n let newHeight = Math.max(40, Math.min(input.scrollHeight + 20, maxHeight));\n\n editorContainer.style.width = newWidth + 'px';\n editorContainer.style.height = newHeight + 'px';\n\n if (input.scrollHeight > input.clientHeight) {\n input.style.overflowY = 'auto';\n } else {\n input.style.overflowY = 'hidden';\n }\n };\n\n adjustSize();\n\n setTimeout(() => {\n input.focus();\n // Select all content\n const range = document.createRange();\n range.selectNodeContents(input);\n const selection = window.getSelection();\n selection.removeAllRanges();\n selection.addRange(range);\n\n // Apply initial syntax highlighting after focus\n applySyntaxHighlightingImproved(input);\n }, 50);\n\n // Input handling with duplicate prevention\n let highlightingTimeout = null;\n let isHighlighting = false;\n let lastContent = input.textContent;\n\n input.addEventListener('input', function(e) {\n if (isHighlighting) return;\n\n if (highlightingTimeout) {\n clearTimeout(highlightingTimeout);\n highlightingTimeout = null;\n }\n\n const currentContent = input.textContent || input.innerText || '';\n \n if (currentContent === lastContent) return;\n\n highlightingTimeout = setTimeout(() => {\n const contentAtTimeout = input.textContent || input.innerText || '';\n if (contentAtTimeout !== lastContent && !isHighlighting) {\n applySyntaxHighlightingImproved(input);\n lastContent = contentAtTimeout;\n adjustSize();\n }\n highlightingTimeout = null;\n }, 300);\n });\n\n // Handle special keys\n input.addEventListener(\"keydown\", function (e) {\n if (e.key === \"Tab\") {\n e.preventDefault();\n document.execCommand('insertText', false, '\\t');\n } else if (e.key === \"Enter\" && e.ctrlKey) {\n e.preventDefault();\n renderCodeFromEditor(input, codeElement, true);\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n renderCodeFromEditor(input, codeElement, true);\n }\n });\n\n // Store references\n input.originalCodeElement = codeElement;\n input.codeGroup = groupElement;\n input.isHighlighting = () => isHighlighting;\n input.setHighlighting = (state) => { isHighlighting = state; };\n input.clearHighlightTimeout = () => {\n if (highlightingTimeout) {\n clearTimeout(highlightingTimeout);\n highlightingTimeout = null;\n }\n };\n\n const handleClickOutside = (event) => {\n if (!editorContainer.contains(event.target)) {\n input.clearHighlightTimeout();\n renderCodeFromEditor(input, codeElement, true);\n document.removeEventListener('pointerdown', handleClickOutside, true);\n }\n };\n document.addEventListener('pointerdown', handleClickOutside, true);\n input.handleClickOutside = handleClickOutside;\n\n groupElement.style.display = \"none\";\n}\n\n\nfunction applySyntaxHighlightingImproved(editor) {\n if (!window.hljs) {\n return;\n }\n\n // Prevent multiple highlighting processes\n if (editor.isHighlighting && editor.isHighlighting()) {\n return;\n }\n\n // Set highlighting flag\n if (editor.setHighlighting) {\n editor.setHighlighting(true);\n }\n\n try {\n // Get current cursor position more reliably\n const selection = window.getSelection();\n let cursorOffset = 0;\n let cursorNode = null;\n let cursorNodeOffset = 0;\n \n if (selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n cursorNode = range.startContainer;\n cursorNodeOffset = range.startOffset;\n \n // Calculate absolute cursor position\n cursorOffset = getCursorOffset(editor, cursorNode, cursorNodeOffset);\n }\n\n // Get the plain text content\n const code = editor.textContent || editor.innerText || '';\n \n // Only apply highlighting if content is not empty\n if (!code.trim()) {\n return;\n }\n \n // Auto-detect language and highlight\n const result = window.hljs.highlightAuto(code);\n \n // Only update if the content is actually different\n const newHTML = result.value;\n if (editor.innerHTML !== newHTML) {\n // Apply highlighted HTML\n editor.innerHTML = newHTML;\n\n // Restore cursor position more accurately\n restoreCursorPositionImproved(editor, cursorOffset);\n }\n\n // Add detected language info (optional)\n if (result.language) {\n editor.setAttribute('data-language', result.language);\n }\n } catch (error) {\n } finally {\n // Always clear the highlighting flag\n if (editor.setHighlighting) {\n editor.setHighlighting(false);\n }\n }\n}\n\n\nfunction restoreCursorPositionImproved(editor, targetOffset) {\n if (targetOffset < 0) return;\n \n try {\n const selection = window.getSelection();\n const range = document.createRange();\n \n let currentOffset = 0;\n let targetNode = null;\n let targetNodeOffset = 0;\n \n const walker = document.createTreeWalker(\n editor,\n NodeFilter.SHOW_TEXT,\n null,\n false\n );\n \n let node;\n while (node = walker.nextNode()) {\n const nodeLength = node.textContent.length;\n \n if (currentOffset + nodeLength >= targetOffset) {\n targetNode = node;\n targetNodeOffset = Math.max(0, Math.min(targetOffset - currentOffset, nodeLength));\n break;\n }\n \n currentOffset += nodeLength;\n }\n \n if (targetNode) {\n range.setStart(targetNode, targetNodeOffset);\n range.collapse(true);\n \n selection.removeAllRanges();\n selection.addRange(range);\n } else {\n // Fallback: place cursor at end\n range.selectNodeContents(editor);\n range.collapse(false);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n } catch (error) {\n // Final fallback: just focus the editor\n try {\n editor.focus();\n } catch (focusError) {\n }\n }\n}\n\n// FIXED: More accurate cursor offset calculation\nfunction getCursorOffset(container, node, offset) {\n let cursorOffset = 0;\n \n if (!node || !container.contains(node)) {\n return 0;\n }\n \n const walker = document.createTreeWalker(\n container,\n NodeFilter.SHOW_TEXT,\n null,\n false\n );\n \n let currentNode;\n while (currentNode = walker.nextNode()) {\n if (currentNode === node) {\n return cursorOffset + Math.max(0, Math.min(offset, currentNode.textContent.length));\n }\n cursorOffset += currentNode.textContent.length;\n }\n \n return cursorOffset;\n}\n\n\nfunction extractTextFromCodeElement(codeElement) {\n if (!codeElement) return \"\";\n \n let codeContent = \"\";\n const childNodes = codeElement.childNodes;\n \n // If there are no child nodes, return empty\n if (childNodes.length === 0) {\n return codeElement.textContent || \"\";\n }\n \n for (let i = 0; i < childNodes.length; i++) {\n const node = childNodes[i];\n \n if (node.nodeType === Node.TEXT_NODE) {\n // Direct text content\n codeContent += node.textContent;\n } else if (node.tagName === 'tspan') {\n // Handle tspan elements - get all text content from this tspan\n const tspanText = node.textContent || \"\";\n codeContent += tspanText;\n \n // Add newline after each tspan except the last one\n // This assumes each tspan represents a line\n if (i < childNodes.length - 1) {\n const nextNode = childNodes[i + 1];\n if (nextNode && nextNode.tagName === 'tspan') {\n codeContent += \"\\n\";\n }\n }\n }\n }\n \n // Clean up the content - replace non-breaking spaces and normalize\n return codeContent.replace(/\\u00A0/g, ' ').replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n}\n\n// FIXED: Improved renderCodeFromEditor function\nfunction renderCodeFromEditor(input, codeElement, deleteIfEmpty = false) {\n const editorContainer = input.closest('.svg-code-container');\n if (!editorContainer || !document.body.contains(editorContainer)) {\n return;\n }\n\n // Get plain text content from the contenteditable div\n // FIXED: Use textContent instead of innerHTML to avoid HTML artifacts\n const code = input.textContent || input.innerText || \"\";\n const gElement = input.codeGroup;\n\n // Clean up event listeners\n if (input.handleClickOutside) {\n document.removeEventListener('pointerdown', input.handleClickOutside, true);\n }\n\n // Clear any pending highlighting timeouts\n if (input.clearHighlightTimeout) {\n input.clearHighlightTimeout();\n }\n\n document.body.removeChild(editorContainer);\n\n if (!gElement || !codeElement) {\n return;\n }\n\n if (!gElement.parentNode) {\n if (selectedCodeBlock === gElement) {\n deselectCodeBlock();\n }\n return;\n }\n\n if (deleteIfEmpty && code.trim() === \"\") {\n // Find the CodeShape wrapper\n let codeShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n codeShape = shapes.find(shape => shape.shapeName === 'code' && shape.group === gElement);\n if (codeShape) {\n const idx = shapes.indexOf(codeShape);\n if (idx !== -1) shapes.splice(idx, 1);\n }\n }\n\n pushDeleteActionWithAttachments({\n type: 'code',\n element: codeShape || gElement,\n shapeName: 'code'\n });\n\n if (typeof cleanupAttachments === 'function') {\n cleanupAttachments(gElement);\n }\n\n svg.removeChild(gElement);\n if (selectedCodeBlock === gElement) {\n selectedCodeBlock = null;\n removeCodeSelectionFeedback();\n }\n } else {\n // FIXED: Clear existing content completely before adding new content\n while (codeElement.firstChild) {\n codeElement.removeChild(codeElement.firstChild);\n }\n\n // Reset text content to empty to ensure clean slate\n codeElement.textContent = \"\";\n\n // Apply syntax highlighting and create SVG tspans\n const storedLang = codeElement.getAttribute(\"data-language\") || \"auto\";\n const highlightedCode = applySyntaxHighlightingToSVG(code, storedLang);\n createHighlightedSVGText(highlightedCode, codeElement);\n\n // Update background rectangle to fit content\n updateCodeBackground(gElement, codeElement);\n\n gElement.style.display = 'block';\n\n // Update attached arrows after code content change\n if (typeof updateAttachedArrows === 'function') {\n updateAttachedArrows(gElement);\n }\n\n if (selectedCodeBlock === gElement) {\n setTimeout(updateCodeSelectionFeedback, 0);\n }\n }\n\n // After rendering code, switch to selection tool and auto-select\n if (gElement.parentNode) {\n if (window.__sketchStoreApi) {\n window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });\n } else {\n window.isSelectionToolActive = true;\n }\n selectCodeBlock(gElement);\n }\n}\n\n// FIXED: Improved createHighlightedSVGText function\nfunction createHighlightedSVGText(highlightResult, parentElement) {\n if (!highlightResult || !highlightResult.value) {\n return;\n }\n\n const lines = highlightResult.value.split('\\n');\n const x = parentElement.getAttribute(\"x\") || 0;\n\n lines.forEach((line, index) => {\n const tspan = document.createElementNS(\"http://www.w3.org/2000/svg\", \"tspan\");\n tspan.setAttribute(\"x\", x);\n tspan.setAttribute(\"dy\", index === 0 ? \"0\" : \"1.2em\");\n \n if (line.trim()) {\n // Create highlighted tspans for non-empty lines\n createHighlightedTspans(line, tspan, x);\n \n // If no child tspans were created (plain text), set the text content\n if (tspan.childNodes.length === 0) {\n tspan.textContent = line;\n }\n } else {\n // Empty line - add a space to maintain line height\n tspan.textContent = \" \";\n }\n \n parentElement.appendChild(tspan);\n });\n}\n\n\n\n\n\n\nfunction applySyntaxHighlightingToSVG(code, language) {\n if (!window.hljs) {\n return { value: code, language: null };\n }\n\n const lang = language || codeLanguage;\n if (lang && lang !== \"auto\") {\n try {\n return window.hljs.highlight(code, { language: lang });\n } catch (e) {\n // fallback to auto-detect\n }\n }\n return window.hljs.highlightAuto(code);\n}\n\n\nfunction applySyntaxHighlighting(editor) {\n if (!window.hljs) {\n return;\n }\n\n // Get the plain text content\n const code = editor.textContent || editor.innerText;\n \n // Auto-detect language and highlight\n const result = window.hljs.highlightAuto(code);\n \n // Store cursor position\n const selection = window.getSelection();\n let cursorPos = 0;\n if (selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n cursorPos = range.startOffset;\n }\n\n // Apply highlighted HTML\n editor.innerHTML = result.value;\n\n // Restore cursor position\n restoreCursorPosition(editor, cursorPos);\n\n // Add detected language info (optional)\n if (result.language) {\n editor.setAttribute('data-language', result.language);\n }\n}\n\nfunction restoreCursorPosition(editor, position) {\n try {\n const range = document.createRange();\n const sel = window.getSelection();\n \n let textNode = null;\n let currentPos = 0;\n \n // Find the text node at the desired position\n const walker = document.createTreeWalker(\n editor,\n NodeFilter.SHOW_TEXT,\n null,\n false\n );\n \n while (walker.nextNode()) {\n const node = walker.currentNode;\n const textLength = node.textContent.length;\n \n if (currentPos + textLength >= position) {\n textNode = node;\n break;\n }\n currentPos += textLength;\n }\n \n if (textNode) {\n range.setStart(textNode, Math.min(position - currentPos, textNode.textContent.length));\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\n }\n } catch (error) {\n }\n}\n\n\nfunction renderCode(input, codeElement, deleteIfEmpty = false) {\n if (!input || !document.body.contains(input)) {\n return;\n }\n\n const code = input.value || \"\";\n const gElement = input.codeGroup;\n\n if (input.handleClickOutside) {\n document.removeEventListener('pointerdown', input.handleClickOutside, true);\n }\n\n document.body.removeChild(input);\n\n if (!gElement || !codeElement) {\n return;\n }\n\n if (!gElement.parentNode) {\n if (selectedCodeBlock === gElement) {\n deselectCodeBlock();\n }\n return;\n }\n\n if (deleteIfEmpty && code.trim() === \"\") {\n // Find the CodeShape wrapper\n let codeShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n codeShape = shapes.find(shape => shape.shapeName === 'code' && shape.group === gElement);\n if (codeShape) {\n const idx = shapes.indexOf(codeShape);\n if (idx !== -1) shapes.splice(idx, 1);\n }\n }\n\n pushDeleteActionWithAttachments({\n type: 'code',\n element: codeShape || gElement,\n shapeName: 'code'\n });\n\n if (typeof cleanupAttachments === 'function') {\n cleanupAttachments(gElement);\n }\n\n svg.removeChild(gElement);\n if (selectedCodeBlock === gElement) {\n selectedCodeBlock = null;\n removeCodeSelectionFeedback();\n }\n } else {\n // Clear existing content\n while (codeElement.firstChild) {\n codeElement.removeChild(codeElement.firstChild);\n }\n\n // Split into lines and create tspans with syntax highlighting\n const lines = code.split(\"\\n\");\n const x = codeElement.getAttribute(\"x\") || 0;\n\n lines.forEach((line, index) => {\n if (window.hljs && line.trim()) {\n // Get syntax highlighting for the line\n const result = window.hljs.highlightAuto(line);\n createHighlightedTspans(result.value, codeElement, x, index === 0 ? \"0\" : \"1.2em\");\n } else {\n // Create plain tspan for empty lines or when hljs is not available\n let tspan = document.createElementNS(\"http://www.w3.org/2000/svg\", \"tspan\");\n tspan.setAttribute(\"x\", x);\n tspan.setAttribute(\"dy\", index === 0 ? \"0\" : \"1.2em\");\n tspan.textContent = line.replace(/\\u00A0/g, ' ') || \" \";\n codeElement.appendChild(tspan);\n }\n });\n\n // Update background rectangle to fit content\n updateCodeBackground(gElement, codeElement);\n\n gElement.style.display = 'block';\n\n // Update attached arrows after code content change\n updateAttachedArrows(gElement);\n\n if (selectedCodeBlock === gElement) {\n setTimeout(updateCodeSelectionFeedback, 0);\n }\n }\n\n // After rendering code, switch to selection tool and auto-select\n if (gElement.parentNode) {\n if (window.__sketchStoreApi) {\n window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });\n } else {\n window.isSelectionToolActive = true;\n }\n selectCodeBlock(gElement);\n }\n}\n\n\nfunction createHighlightedTspans(highlightedHtml, parentTspan, x) {\n if (!highlightedHtml || !parentTspan) return;\n \n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = highlightedHtml;\n \n // Process all nodes in the highlighted HTML\n processHighlightedNodes(tempDiv, parentTspan);\n}\n\n\n\nfunction processHighlightedNodes(node, parentTspan) {\n if (!node || !parentTspan) return;\n \n for (let child of node.childNodes) {\n if (child.nodeType === Node.TEXT_NODE) {\n // Direct text content - add to parent tspan\n if (child.textContent) {\n if (parentTspan.textContent) {\n parentTspan.textContent += child.textContent;\n } else {\n parentTspan.textContent = child.textContent;\n }\n }\n } else if (child.nodeType === Node.ELEMENT_NODE) {\n // Create a new nested tspan for styled content\n let styledTspan = document.createElementNS(\"http://www.w3.org/2000/svg\", \"tspan\");\n styledTspan.textContent = child.textContent || \"\";\n \n // Apply comprehensive syntax highlighting colors\n const className = child.className || '';\n applyHighlightColor(styledTspan, className);\n \n parentTspan.appendChild(styledTspan);\n }\n }\n}\n\n\n\nfunction applyHighlightColor(tspan, className) {\n // GitHub Dark Dimmed theme colors\n if (className.includes('hljs-keyword') || className.includes('hljs-built_in')) {\n tspan.setAttribute(\"fill\", \"#ff7b72\"); // Red (keywords)\n } else if (className.includes('hljs-string') || className.includes('hljs-template-string')) {\n tspan.setAttribute(\"fill\", \"#a5d6ff\"); // Light blue (strings)\n } else if (className.includes('hljs-comment')) {\n tspan.setAttribute(\"fill\", \"#8b949e\"); // Gray (comments)\n tspan.setAttribute(\"font-style\", \"italic\");\n } else if (className.includes('hljs-number') || className.includes('hljs-literal')) {\n tspan.setAttribute(\"fill\", \"#79c0ff\"); // Blue (numbers/literals)\n } else if (className.includes('hljs-function') || className.includes('hljs-title')) {\n tspan.setAttribute(\"fill\", \"#d2a8ff\"); // Purple (functions)\n } else if (className.includes('hljs-variable') || className.includes('hljs-name')) {\n tspan.setAttribute(\"fill\", \"#ffa657\"); // Orange (variables)\n } else if (className.includes('hljs-type') || className.includes('hljs-class')) {\n tspan.setAttribute(\"fill\", \"#f0883e\"); // Orange (types)\n } else if (className.includes('hljs-operator') || className.includes('hljs-punctuation')) {\n tspan.setAttribute(\"fill\", \"#c9d1d9\"); // Light gray (operators)\n } else if (className.includes('hljs-property') || className.includes('hljs-attribute')) {\n tspan.setAttribute(\"fill\", \"#79c0ff\"); // Blue (properties)\n } else if (className.includes('hljs-tag')) {\n tspan.setAttribute(\"fill\", \"#7ee787\"); // Green (HTML tags)\n } else if (className.includes('hljs-meta') || className.includes('hljs-doctag')) {\n tspan.setAttribute(\"fill\", \"#8b949e\"); // Gray (meta)\n } else if (className.includes('hljs-regexp')) {\n tspan.setAttribute(\"fill\", \"#a5d6ff\"); // Light blue (regex)\n } else {\n tspan.setAttribute(\"fill\", \"#c9d1d9\"); // GitHub default text color\n }\n}\n\n\nfunction createCodeSelectionFeedback(groupElement) {\n if (!groupElement) return;\n removeCodeSelectionFeedback();\n\n const backgroundRect = groupElement.querySelector('.code-background');\n if (!backgroundRect) {\n return;\n }\n\n // Use background rect dimensions for selection feedback\n const x = parseFloat(backgroundRect.getAttribute('x'));\n const y = parseFloat(backgroundRect.getAttribute('y'));\n const width = parseFloat(backgroundRect.getAttribute('width'));\n const height = parseFloat(backgroundRect.getAttribute('height'));\n\n const zoom = window.currentZoom || 1;\n const padding = 8 / zoom;\n const handleSize = 10 / zoom;\n const handleOffset = handleSize / 2;\n\n const selX = x - padding;\n const selY = y - padding;\n const selWidth = width + 2 * padding;\n const selHeight = height + 2 * padding;\n\n // Draw selection outline (polyline)\n const outlinePoints = [\n [selX, selY],\n [selX + selWidth, selY],\n [selX + selWidth, selY + selHeight],\n [selX, selY + selHeight],\n [selX, selY]\n ];\n const pointsAttr = outlinePoints.map(p => p.join(',')).join(' ');\n codeSelectionBox = document.createElementNS(\"http://www.w3.org/2000/svg\", \"polyline\");\n codeSelectionBox.setAttribute(\"class\", \"selection-box\");\n codeSelectionBox.setAttribute(\"points\", pointsAttr);\n codeSelectionBox.setAttribute(\"fill\", \"none\");\n codeSelectionBox.setAttribute(\"stroke\", \"#5B57D1\");\n codeSelectionBox.setAttribute(\"stroke-width\", \"1.5\");\n codeSelectionBox.setAttribute(\"stroke-dasharray\", \"4 2\");\n codeSelectionBox.setAttribute(\"vector-effect\", \"non-scaling-stroke\");\n codeSelectionBox.setAttribute(\"pointer-events\", \"none\");\n groupElement.appendChild(codeSelectionBox);\n\n // Add resize handles and rotation anchor (rest of the function remains the same)\n const handlesData = [\n { name: 'nw', x: selX, y: selY, cursor: 'nwse-resize' },\n { name: 'ne', x: selX + selWidth, y: selY, cursor: 'nesw-resize' },\n { name: 'sw', x: selX, y: selY + selHeight, cursor: 'nesw-resize' },\n { name: 'se', x: selX + selWidth, y: selY + selHeight, cursor: 'nwse-resize' }\n ];\n codeResizeHandles = {};\n handlesData.forEach(handle => {\n const handleRect = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n handleRect.setAttribute(\"class\", `resize-handle resize-handle-${handle.name}`);\n handleRect.setAttribute(\"x\", handle.x - handleOffset);\n handleRect.setAttribute(\"y\", handle.y - handleOffset);\n handleRect.setAttribute(\"width\", handleSize);\n handleRect.setAttribute(\"height\", handleSize);\n handleRect.setAttribute(\"fill\", \"#121212\");\n handleRect.setAttribute(\"stroke\", \"#5B57D1\");\n handleRect.setAttribute(\"stroke-width\", 2);\n handleRect.setAttribute(\"vector-effect\", \"non-scaling-stroke\");\n handleRect.style.cursor = handle.cursor;\n handleRect.setAttribute(\"data-anchor\", handle.name);\n groupElement.appendChild(handleRect);\n codeResizeHandles[handle.name] = handleRect;\n\n handleRect.addEventListener('pointerdown', (e) => {\n if (window.isSelectionToolActive) {\n e.stopPropagation();\n startCodeResize(e, handle.name);\n }\n });\n });\n\n \n const rotationAnchorPos = { x: selX + selWidth / 2, y: selY - 30 };\n const rotationAnchor = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n rotationAnchor.setAttribute('cx', rotationAnchorPos.x);\n rotationAnchor.setAttribute('cy', rotationAnchorPos.y);\n rotationAnchor.setAttribute('r', 8);\n rotationAnchor.setAttribute('class', 'rotate-anchor');\n rotationAnchor.setAttribute('fill', '#121212');\n rotationAnchor.setAttribute('stroke', '#5B57D1');\n rotationAnchor.setAttribute('stroke-width', 2);\n rotationAnchor.setAttribute('vector-effect', 'non-scaling-stroke');\n rotationAnchor.style.cursor = 'grab';\n rotationAnchor.setAttribute('pointer-events', 'all');\n groupElement.appendChild(rotationAnchor);\n\n codeResizeHandles.rotate = rotationAnchor;\n\n rotationAnchor.addEventListener('pointerdown', (e) => {\n if (window.isSelectionToolActive) {\n e.stopPropagation();\n startCodeRotation(e);\n }\n });\n}\n\n\nfunction updateCodeBackground(groupElement, codeElement) {\n const backgroundRect = groupElement.querySelector('.code-background');\n if (!backgroundRect || !codeElement) return;\n\n const textBBox = codeElement.getBBox();\n const padding = 10;\n\n // Update background dimensions to fit text content\n backgroundRect.setAttribute(\"x\", textBBox.x - padding);\n backgroundRect.setAttribute(\"y\", textBBox.y - padding);\n backgroundRect.setAttribute(\"width\", textBBox.width + (padding * 2));\n backgroundRect.setAttribute(\"height\", textBBox.height + (padding * 2));\n}\n\n\nfunction updateCodeSelectionFeedback() {\n if (!selectedCodeBlock || !codeSelectionBox) return;\n\n const codeElement = selectedCodeBlock.querySelector('text');\n if (!codeElement) return;\n\n // Temporarily set display to 'block' if it was hidden to get correct bbox\n const wasHidden = selectedCodeBlock.style.display === 'none';\n if (wasHidden) selectedCodeBlock.style.display = 'block';\n\n const bbox = codeElement.getBBox(); // Fix: use codeElement, not undefined foreignObject\n\n if (wasHidden) selectedCodeBlock.style.display = 'none';\n\n if (bbox.width === 0 && bbox.height === 0 && codeElement.textContent.trim() !== \"\") {\n }\n\n const zoom = window.currentZoom || 1;\n const padding = 8 / zoom;\n const handleSize = 10 / zoom;\n const handleOffset = handleSize / 2;\n\n const selX = bbox.x - padding;\n const selY = bbox.y - padding;\n const selWidth = Math.max(bbox.width + 2 * padding, handleSize);\n const selHeight = Math.max(bbox.height + 2 * padding, handleSize);\n\n const outlinePoints = [\n [selX, selY],\n [selX + selWidth, selY],\n [selX + selWidth, selY + selHeight],\n [selX, selY + selHeight],\n [selX, selY]\n ];\n\n const pointsAttr = outlinePoints.map(p => p.join(',')).join(' ');\n codeSelectionBox.setAttribute(\"points\", pointsAttr);\n\n const handlesData = [\n { name: 'nw', x: selX, y: selY },\n { name: 'ne', x: selX + selWidth, y: selY },\n { name: 'sw', x: selX, y: selY + selHeight },\n { name: 'se', x: selX + selWidth, y: selY + selHeight }\n ];\n\n handlesData.forEach(handle => {\n const handleRect = codeResizeHandles[handle.name];\n if (handleRect) {\n handleRect.setAttribute(\"x\", handle.x - handleOffset);\n handleRect.setAttribute(\"y\", handle.y - handleOffset);\n }\n });\n\n const rotationAnchor = codeResizeHandles.rotate;\n if (rotationAnchor) {\n const rotationAnchorPos = { x: selX + selWidth / 2, y: selY - 30 };\n rotationAnchor.setAttribute('cx', rotationAnchorPos.x);\n rotationAnchor.setAttribute('cy', rotationAnchorPos.y);\n }\n}\n\n\n\nfunction startCodeRotation(event) {\n if (!selectedCodeBlock || event.button !== 0) return;\n event.preventDefault();\n event.stopPropagation();\n\n isCodeRotating = true;\n isCodeDragging = false;\n isCodeResizing = false;\n\n const codeElement = selectedCodeBlock.querySelector('text'); // Fix: use text element instead of foreignObject\n if (!codeElement) return;\n\n const bbox = codeElement.getBBox();\n const centerX = bbox.x + bbox.width / 2;\n const centerY = bbox.y + bbox.height / 2;\n\n const mousePos = getSVGCoordinates(event);\n\n let centerPoint = svg.createSVGPoint();\n centerPoint.x = centerX;\n centerPoint.y = centerY;\n\n const groupTransform = selectedCodeBlock.transform.baseVal.consolidate();\n if (groupTransform) {\n centerPoint = centerPoint.matrixTransform(groupTransform.matrix);\n }\n\n codeRotationStartAngle = Math.atan2(mousePos.y - centerPoint.y, mousePos.x - centerPoint.x) * 180 / Math.PI;\n\n const currentTransform = selectedCodeBlock.transform.baseVal.consolidate();\n codeRotationStartTransform = currentTransform ? currentTransform.matrix : svg.createSVGMatrix();\n\n svg.style.cursor = 'grabbing';\n\n window.addEventListener('pointermove', handleCodeMouseMove); // Fix: use window instead of svg\n window.addEventListener('pointerup', handleCodeMouseUp);\n}\n\n\nfunction removeCodeSelectionFeedback() {\n if (selectedCodeBlock) {\n selectedCodeBlock.querySelectorAll(\".selection-box, .resize-handle, .rotate-anchor\").forEach(el => el.remove());\n }\n codeSelectionBox = null;\n codeResizeHandles = {};\n}\n\nfunction selectCodeBlock(groupElement) {\n if (!groupElement || !groupElement.parentNode) return;\n if (groupElement === selectedCodeBlock) return;\n\n deselectCodeBlock();\n selectedCodeBlock = groupElement;\n selectedCodeBlock.classList.add(\"selected\");\n createCodeSelectionFeedback(selectedCodeBlock);\n updateSelectedElement(selectedCodeBlock);\n\n // Update code toggle to reflect code mode\n const toggleSpans = document.querySelectorAll(\".textCodeSpan\");\n toggleSpans.forEach(el => el.classList.remove(\"selected\"));\n toggleSpans.forEach(el => {\n if (el.getAttribute(\"data-id\") === \"true\") el.classList.add(\"selected\");\n });\n // Show the text/code property panel via React bridge (pass 'code' to set code mode)\n if (window.__showSidebarForShape) window.__showSidebarForShape('code');\n}\n\nfunction deselectCodeBlock() {\n const activeEditor = document.querySelector(\".svg-code-editor[contenteditable='true']\");\n if (activeEditor) {\n let groupElement = activeEditor.originalGroup;\n if (groupElement) {\n renderCode(activeEditor, true);\n } else if (document.body.contains(activeEditor)){\n activeEditor.remove();\n }\n }\n if (selectedCodeBlock) {\n removeCodeSelectionFeedback();\n selectedCodeBlock.classList.remove(\"selected\");\n selectedCodeBlock = null;\n updateSelectedElement(null);\n }\n if (isCodeRotating) {\n isCodeRotating = false;\n codeRotationStartAngle = 0;\n codeRotationStartTransform = null;\n svg.style.cursor = 'default';\n window.removeEventListener('pointermove', handleCodeMouseMove);\n window.removeEventListener('pointerup', handleCodeMouseUp);\n }\n}\n\n\nfunction startCodeDrag(event) {\n if (!selectedCodeBlock || event.button !== 0) return;\n\n if (event.target.closest('.resize-handle')) {\n return;\n }\n\n isCodeDragging = true;\n isCodeResizing = false;\n event.preventDefault();\n\n const currentTransform = selectedCodeBlock.transform.baseVal.consolidate();\n const initialTranslateX = currentTransform ? currentTransform.matrix.e : 0;\n const initialTranslateY = currentTransform ? currentTransform.matrix.f : 0;\n\n startCodePoint = getSVGCoordinates(event);\n\n codeDragOffsetX = startCodePoint.x - initialTranslateX;\n codeDragOffsetY = startCodePoint.y - initialTranslateY;\n\n // Find the CodeShape wrapper for frame functionality\n let codeShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n codeShape = shapes.find(shape => shape.shapeName === 'code' && shape.group === selectedCodeBlock);\n }\n\n if (codeShape) {\n // Store initial frame state\n draggedCodeInitialFrame = codeShape.parentFrame || null;\n \n // Temporarily remove from frame clipping if dragging\n if (codeShape.parentFrame) {\n codeShape.parentFrame.temporarilyRemoveFromFrame(codeShape);\n }\n }\n\n svg.style.cursor = 'grabbing';\n\n window.addEventListener('pointermove', handleCodeMouseMove); // Fix: use window\n window.addEventListener('pointerup', handleCodeMouseUp); // Fix: use window\n}\n\nfunction startCodeResize(event, anchor) {\n if (!selectedCodeBlock || event.button !== 0) return;\n event.preventDefault();\n event.stopPropagation();\n\n isCodeResizing = true;\n isCodeDragging = false;\n currentCodeResizeHandle = anchor;\n\n \n const codeElement = selectedCodeBlock.querySelector('text');\n if (!codeElement) {\n isCodeResizing = false;\n return;\n }\n\n startCodeBBox = codeElement.getBBox();\n startCodeFontSize = parseFloat(codeElement.getAttribute(\"font-size\") || 25);\n if (isNaN(startCodeFontSize)) startCodeFontSize = 25;\n\n startCodePoint = getSVGCoordinates(event, selectedCodeBlock);\n\n const currentTransform = selectedCodeBlock.transform.baseVal.consolidate();\n initialCodeGroupTx = currentTransform ? currentTransform.matrix.e : 0;\n initialCodeGroupTy = currentTransform ? currentTransform.matrix.f : 0;\n\n const padding = 3;\n const startX = startCodeBBox.x - padding;\n const startY = startCodeBBox.y - padding;\n const startWidth = startCodeBBox.width + 2 * padding;\n const startHeight = startCodeBBox.height + 2 * padding;\n\n let hx = startX;\n let hy = startY;\n if (anchor.includes('e')) { hx = startX + startWidth; }\n if (anchor.includes('s')) { hy = startY + startHeight; }\n initialCodeHandlePosRelGroup = { x: hx, y: hy };\n\n svg.style.cursor = codeResizeHandles[anchor]?.style.cursor || 'default';\n\n window.addEventListener('pointermove', handleCodeMouseMove); \n window.addEventListener('pointerup', handleCodeMouseUp); \n}\n\n\n\n\nconst handleCodeMouseMove = (event) => {\n if (!selectedCodeBlock) return;\n event.preventDefault();\n\n // Keep lastMousePos in screen coordinates for other functions\n const svgRect = svg.getBoundingClientRect();\n lastMousePos = {\n x: event.clientX - svgRect.left, \n y: event.clientY - svgRect.top\n };\n\n if (isCodeDragging) {\n const currentPoint = getSVGCoordinates(event);\n const newTranslateX = currentPoint.x - codeDragOffsetX;\n const newTranslateY = currentPoint.y - codeDragOffsetY;\n\n const currentTransform = selectedCodeBlock.transform.baseVal.consolidate();\n if (currentTransform) {\n const matrix = currentTransform.matrix;\n const angle = Math.atan2(matrix.b, matrix.a) * 180 / Math.PI;\n\n const codeElement = selectedCodeBlock.querySelector('text');\n if (codeElement) {\n const bbox = codeElement.getBBox();\n const centerX = bbox.x + bbox.width / 2;\n const centerY = bbox.y + bbox.height / 2;\n\n selectedCodeBlock.setAttribute('transform',\n `translate(${newTranslateX}, ${newTranslateY}) rotate(${angle}, ${centerX}, ${centerY})`\n );\n } else {\n selectedCodeBlock.setAttribute('transform', `translate(${newTranslateX}, ${newTranslateY})`);\n }\n } else {\n selectedCodeBlock.setAttribute('transform', `translate(${newTranslateX}, ${newTranslateY})`);\n }\n\n // Update frame containment for CodeShape wrapper\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n const codeShape = shapes.find(shape => shape.shapeName === 'code' && shape.group === selectedCodeBlock);\n if (codeShape) {\n codeShape.updateFrameContainment();\n }\n }\n\n // Update attached arrows during dragging\n updateAttachedArrows(selectedCodeBlock);\n\n } else if (isCodeResizing) {\n const codeElement = selectedCodeBlock.querySelector('text');\n if (!codeElement || !startCodeBBox || startCodeFontSize === null || !startCodePoint || !initialCodeHandlePosRelGroup) return;\n\n const currentPoint = getSVGCoordinates(event, selectedCodeBlock);\n\n const startX = startCodeBBox.x;\n const startY = startCodeBBox.y;\n const startWidth = startCodeBBox.width;\n const startHeight = startCodeBBox.height;\n\n let anchorX, anchorY;\n\n switch (currentCodeResizeHandle) {\n case 'nw':\n anchorX = startX + startWidth;\n anchorY = startY + startHeight;\n break;\n case 'ne':\n anchorX = startX;\n anchorY = startY + startHeight;\n break;\n case 'sw':\n anchorX = startX + startWidth;\n anchorY = startY;\n break;\n case 'se':\n anchorX = startX;\n anchorY = startY;\n break;\n }\n\n const newWidth = Math.abs(currentPoint.x - anchorX);\n const newHeight = Math.abs(currentPoint.y - anchorY);\n\n const chosenScale = newHeight / startHeight;\n\n const minScale = 0.1;\n const maxScale = 10.0;\n const clampedScale = Math.max(minScale, Math.min(chosenScale, maxScale));\n\n const newFontSize = startCodeFontSize * clampedScale;\n const minFontSize = 5;\n const finalFontSize = Math.max(newFontSize, minFontSize);\n\n codeElement.setAttribute(\"font-size\", `${finalFontSize}px`);\n\n const currentBBox = codeElement.getBBox();\n\n let newAnchorX, newAnchorY;\n\n switch (currentCodeResizeHandle) {\n case 'nw':\n newAnchorX = currentBBox.x + currentBBox.width;\n newAnchorY = currentBBox.y + currentBBox.height;\n break;\n case 'ne':\n newAnchorX = currentBBox.x;\n newAnchorY = currentBBox.y + currentBBox.height;\n break;\n case 'sw':\n newAnchorX = currentBBox.x + currentBBox.width;\n newAnchorY = currentBBox.y;\n break;\n case 'se':\n newAnchorX = currentBBox.x;\n newAnchorY = currentBBox.y;\n break;\n }\n\n const deltaX = anchorX - newAnchorX;\n const deltaY = anchorY - newAnchorY;\n\n const currentTransform = selectedCodeBlock.transform.baseVal.consolidate();\n if (currentTransform) {\n const matrix = currentTransform.matrix;\n const angle = Math.atan2(matrix.b, matrix.a) * 180 / Math.PI;\n\n const newGroupTx = initialCodeGroupTx + deltaX;\n const newGroupTy = initialCodeGroupTy + deltaY;\n\n const centerX = currentBBox.x + currentBBox.width / 2;\n const centerY = currentBBox.y + currentBBox.height / 2;\n\n selectedCodeBlock.setAttribute('transform',\n `translate(${newGroupTx}, ${newGroupTy}) rotate(${angle}, ${centerX}, ${centerY})`\n );\n } else {\n const newGroupTx = initialCodeGroupTx + deltaX;\n const newGroupTy = initialCodeGroupTy + deltaY;\n selectedCodeBlock.setAttribute('transform', `translate(${newGroupTx}, ${newGroupTy})`);\n }\n\n // Update background to fit new text size\n updateCodeBackground(selectedCodeBlock, codeElement);\n\n // Update attached arrows during resizing\n updateAttachedArrows(selectedCodeBlock);\n\n clearTimeout(selectedCodeBlock.updateFeedbackTimeout);\n selectedCodeBlock.updateFeedbackTimeout = setTimeout(() => {\n updateCodeSelectionFeedback();\n delete selectedCodeBlock.updateFeedbackTimeout;\n }, 0);\n\n } else if (isCodeRotating) {\n const codeElement = selectedCodeBlock.querySelector('text');\n if (!codeElement) return;\n\n const bbox = codeElement.getBBox();\n const centerX = bbox.x + bbox.width / 2;\n const centerY = bbox.y + bbox.height / 2;\n\n const mousePos = getSVGCoordinates(event);\n\n let centerPoint = svg.createSVGPoint();\n centerPoint.x = centerX;\n centerPoint.y = centerY;\n\n const groupTransform = selectedCodeBlock.transform.baseVal.consolidate();\n if (groupTransform) {\n centerPoint = centerPoint.matrixTransform(groupTransform.matrix);\n }\n\n const currentAngle = Math.atan2(mousePos.y - centerPoint.y, mousePos.x - centerPoint.x) * 180 / Math.PI;\n\n const rotationDiff = currentAngle - codeRotationStartAngle;\n\n const newTransform = `translate(${codeRotationStartTransform.e}, ${codeRotationStartTransform.f}) rotate(${rotationDiff}, ${centerX}, ${centerY})`;\n selectedCodeBlock.setAttribute('transform', newTransform);\n\n // Update attached arrows during rotation\n updateAttachedArrows(selectedCodeBlock);\n\n updateCodeSelectionFeedback();\n }\n\n // Handle cursor changes for code tool\n if ((isCodeToolActive || (isTextToolActive && isTextInCodeMode)) && !isCodeDragging && !isCodeResizing && !isCodeRotating) {\n svg.style.cursor = 'text';\n \n // Frame highlighting logic for code tool\n const { x, y } = getSVGCoordinates(event);\n \n const tempCodeBounds = {\n x: x - 275, \n y: y - 30, \n width: 550,\n height: 60\n };\n \n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.forEach(frame => {\n if (frame.shapeName === 'frame') {\n if (frame.isShapeInFrame(tempCodeBounds)) {\n frame.highlightFrame();\n hoveredCodeFrame = frame;\n } else if (hoveredCodeFrame === frame) {\n frame.removeHighlight();\n hoveredCodeFrame = null;\n }\n }\n });\n }\n } else if (isSelectionToolActive && !isCodeDragging && !isCodeResizing && !isCodeRotating) {\n const targetGroup = event.target.closest('g[data-type=\"code-group\"]');\n if (targetGroup) {\n svg.style.cursor = 'move';\n } else {\n svg.style.cursor = 'default';\n }\n }\n};\n\n// Add this complete mouse up handler\nconst handleCodeMouseUp = (event) => {\n if (event.button !== 0) return;\n\n if (isCodeDragging && selectedCodeBlock) {\n const currentTransform = selectedCodeBlock.transform.baseVal.consolidate();\n if (currentTransform) {\n const finalTranslateX = currentTransform.matrix.e;\n const finalTranslateY = currentTransform.matrix.f;\n\n const initialX = parseFloat(selectedCodeBlock.getAttribute(\"data-x\")) || 0;\n const initialY = parseFloat(selectedCodeBlock.getAttribute(\"data-y\")) || 0;\n\n // Find the CodeShape wrapper for frame tracking\n let codeShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n codeShape = shapes.find(shape => shape.shapeName === 'code' && shape.group === selectedCodeBlock);\n }\n\n // Add frame information for undo tracking\n const oldPosWithFrame = {\n x: initialX,\n y: initialY,\n rotation: extractRotationFromTransform(selectedCodeBlock) || 0,\n parentFrame: draggedCodeInitialFrame\n };\n const newPosWithFrame = {\n x: finalTranslateX,\n y: finalTranslateY,\n rotation: extractRotationFromTransform(selectedCodeBlock) || 0,\n parentFrame: codeShape ? codeShape.parentFrame : null\n };\n\n const stateChanged = initialX !== finalTranslateX || initialY !== finalTranslateY;\n const frameChanged = oldPosWithFrame.parentFrame !== newPosWithFrame.parentFrame;\n\n if (stateChanged || frameChanged) {\n pushTransformAction(\n {\n type: 'code',\n element: selectedCodeBlock,\n shapeName: 'code'\n },\n oldPosWithFrame,\n newPosWithFrame\n );\n }\n\n // Handle frame containment changes after drag\n if (codeShape) {\n const finalFrame = hoveredCodeFrame;\n \n // If shape moved to a different frame\n if (draggedCodeInitialFrame !== finalFrame) {\n // Remove from initial frame\n if (draggedCodeInitialFrame) {\n draggedCodeInitialFrame.removeShapeFromFrame(codeShape);\n }\n \n // Add to new frame\n if (finalFrame) {\n finalFrame.addShapeToFrame(codeShape);\n }\n \n // Track the frame change for undo\n if (frameChanged) {\n pushFrameAttachmentAction(finalFrame || draggedCodeInitialFrame, codeShape, \n finalFrame ? 'attach' : 'detach', draggedCodeInitialFrame);\n }\n } else if (draggedCodeInitialFrame) {\n // Shape stayed in same frame, restore clipping\n draggedCodeInitialFrame.restoreToFrame(codeShape);\n }\n }\n\n selectedCodeBlock.setAttribute(\"data-x\", finalTranslateX);\n selectedCodeBlock.setAttribute(\"data-y\", finalTranslateY);\n }\n\n draggedCodeInitialFrame = null;\n\n } else if (isCodeResizing && selectedCodeBlock) {\n const codeElement = selectedCodeBlock.querySelector('text');\n if (codeElement) {\n const finalFontSize = codeElement.getAttribute(\"font-size\");\n const initialFontSize = startCodeFontSize;\n\n const currentTransform = selectedCodeBlock.transform.baseVal.consolidate();\n if (currentTransform && initialFontSize !== parseFloat(finalFontSize)) {\n const finalTranslateX = currentTransform.matrix.e;\n const finalTranslateY = currentTransform.matrix.f;\n\n pushTransformAction(\n {\n type: 'code',\n element: selectedCodeBlock,\n shapeName: 'code'\n },\n {\n x: initialCodeGroupTx,\n y: initialCodeGroupTy,\n fontSize: initialFontSize,\n rotation: extractRotationFromTransform(selectedCodeBlock) || 0\n },\n {\n x: finalTranslateX,\n y: finalTranslateY,\n fontSize: parseFloat(finalFontSize),\n rotation: extractRotationFromTransform(selectedCodeBlock) || 0\n }\n );\n\n selectedCodeBlock.setAttribute(\"data-x\", finalTranslateX);\n selectedCodeBlock.setAttribute(\"data-y\", finalTranslateY);\n }\n\n clearTimeout(selectedCodeBlock.updateFeedbackTimeout);\n updateCodeSelectionFeedback();\n }\n } else if (isCodeRotating && selectedCodeBlock) {\n const currentTransform = selectedCodeBlock.transform.baseVal.consolidate();\n if (currentTransform && codeRotationStartTransform) {\n const initialRotation = Math.atan2(codeRotationStartTransform.b, codeRotationStartTransform.a) * 180 / Math.PI;\n const finalRotation = extractRotationFromTransform(selectedCodeBlock) || 0;\n\n if (Math.abs(initialRotation - finalRotation) > 1) {\n pushTransformAction(\n {\n type: 'code',\n element: selectedCodeBlock,\n shapeName: 'code'\n },\n {\n x: codeRotationStartTransform.e,\n y: codeRotationStartTransform.f,\n rotation: initialRotation\n },\n {\n x: currentTransform.matrix.e,\n y: currentTransform.matrix.f,\n rotation: finalRotation\n }\n );\n }\n\n }\n updateCodeSelectionFeedback();\n }\n\n // Clear frame highlighting\n if (hoveredCodeFrame) {\n hoveredCodeFrame.removeHighlight();\n hoveredCodeFrame = null;\n }\n\n // Handle code deselection when clicking outside\n if (isSelectionToolActive) {\n const targetGroup = event.target.closest('g[data-type=\"code-group\"]');\n const isResizeHandle = event.target.closest('.resize-handle');\n const isRotateAnchor = event.target.closest('.rotate-anchor');\n \n // If we didn't click on code block or its controls, deselect\n if (!targetGroup && !isResizeHandle && !isRotateAnchor && selectedCodeBlock) {\n deselectCodeBlock();\n }\n }\n\n isCodeDragging = false;\n isCodeResizing = false;\n isCodeRotating = false;\n currentCodeResizeHandle = null;\n startCodePoint = null;\n startCodeBBox = null;\n startCodeFontSize = null;\n codeDragOffsetX = undefined;\n codeDragOffsetY = undefined;\n initialCodeHandlePosRelGroup = null;\n initialCodeGroupTx = 0;\n initialCodeGroupTy = 0;\n codeRotationStartAngle = 0;\n codeRotationStartTransform = null;\n\n svg.style.cursor = 'default';\n\n svg.removeEventListener('pointermove', handleCodeMouseMove);\n svg.removeEventListener('pointerup', handleCodeMouseUp);\n};\n\n\nfunction extractRotationFromTransform(element) {\n const currentTransform = element.transform.baseVal.consolidate();\n if (currentTransform) {\n const matrix = currentTransform.matrix;\n return Math.atan2(matrix.b, matrix.a) * 180 / Math.PI;\n }\n return 0;\n}\n\nconst handleCodeMouseDown = function (e) {\n if (!e.target) return;\n // Check for contenteditable code editor (new style)\n const activeContentEditor = document.querySelector(\".svg-code-editor[contenteditable='true']\");\n if (activeContentEditor) {\n const editorContainer = activeContentEditor.closest('.svg-code-container');\n if (editorContainer && editorContainer.contains(e.target)) {\n return;\n }\n let codeElement = activeContentEditor.originalCodeElement;\n if (codeElement) {\n renderCodeFromEditor(activeContentEditor, codeElement, true);\n } else if (editorContainer && document.body.contains(editorContainer)) {\n document.body.removeChild(editorContainer);\n }\n }\n // Check for textarea code editor (legacy style)\n const activeEditor = document.querySelector(\"textarea.svg-code-editor\");\n if (activeEditor && activeEditor.contains(e.target)) {\n return;\n }\n if (activeEditor && !activeEditor.contains(e.target)) {\n let codeElement = activeEditor.originalCodeElement;\n if (codeElement) {\n renderCode(activeEditor, codeElement, true);\n } else if (document.body.contains(activeEditor)){\n document.body.removeChild(activeEditor);\n }\n }\n\n const targetGroup = e.target.closest('g[data-type=\"code-group\"]');\n\n if (isSelectionToolActive && e.button === 0) {\n if (targetGroup) {\n if (e.target.closest('.resize-handle') || e.target.closest('.rotate-anchor')) {\n return; // Let resize/rotate handlers manage\n }\n \n // If clicking on the code block itself, select it and start drag\n if (targetGroup === selectedCodeBlock) {\n startCodeDrag(e);\n } else {\n selectCodeBlock(targetGroup);\n startCodeDrag(e);\n }\n } else {\n deselectCodeBlock();\n }\n\n } else if ((isCodeToolActive || isTextToolActive) && e.button === 0) {\n if (targetGroup) {\n const codeElement = targetGroup.querySelector('text');\n\n if (codeElement && (e.target.tagName === \"text\" || e.target.tagName === \"tspan\")) {\n makeCodeEditable(codeElement, targetGroup, e); // Pass click event for position\n e.stopPropagation();\n } else {\n deselectCodeBlock();\n addCodeBlock(e);\n }\n } else {\n deselectCodeBlock();\n addCodeBlock(e);\n }\n }\n};\n\n\n// updateAttachedArrows is imported from drawArrow.js\n\ncodeTextColorOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n codeTextColorOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n\n const newColor = span.getAttribute(\"data-id\");\n const oldColor = codeTextColor;\n codeTextColor = newColor;\n\n if (selectedCodeBlock) {\n const codeEditor = selectedCodeBlock.querySelector('.svg-code-editor');\n if (codeEditor) {\n const currentColor = codeEditor.style.color;\n\n if (currentColor !== newColor) {\n pushOptionsChangeAction(\n {\n type: 'code',\n element: selectedCodeBlock,\n shapeName: 'code'\n },\n {\n color: currentColor,\n font: codeEditor.style.fontFamily,\n size: codeEditor.style.fontSize,\n align: codeEditor.style.textAlign // Although mostly 'left'\n },\n {\n color: newColor,\n font: codeEditor.style.fontFamily,\n size: codeEditor.style.fontSize,\n align: codeEditor.style.textAlign\n }\n );\n }\n\n codeEditor.style.color = newColor;\n updateSyntaxHighlighting(codeEditor); // Re-highlight with new color\n }\n }\n });\n});\n\ncodeTextFontOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n codeTextFontOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n\n const newFont = span.getAttribute(\"data-id\");\n const oldFont = codeTextFont;\n codeTextFont = newFont;\n\n if (selectedCodeBlock) {\n const codeEditor = selectedCodeBlock.querySelector('.svg-code-editor');\n if (codeEditor) {\n const currentFont = codeEditor.style.fontFamily;\n\n if (currentFont !== newFont) {\n pushOptionsChangeAction(\n {\n type: 'code',\n element: selectedCodeBlock,\n shapeName: 'code'\n },\n {\n color: codeEditor.style.color,\n font: currentFont,\n size: codeEditor.style.fontSize,\n align: codeEditor.style.textAlign\n },\n {\n color: codeEditor.style.color,\n font: newFont,\n size: codeEditor.style.fontSize,\n align: codeEditor.style.textAlign\n }\n );\n }\n\n codeEditor.style.fontFamily = newFont;\n updateSyntaxHighlighting(codeEditor); // Re-highlight with new font\n setTimeout(updateCodeSelectionFeedback, 0);\n }\n }\n });\n});\n\ncodeTextSizeOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n codeTextSizeOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n\n const newSize = span.getAttribute(\"data-id\") + \"px\";\n const oldSize = codeTextSize;\n codeTextSize = newSize;\n\n if (selectedCodeBlock) {\n const codeEditor = selectedCodeBlock.querySelector('.svg-code-editor');\n if (codeEditor) {\n const currentSize = codeEditor.style.fontSize;\n\n if (currentSize !== newSize) {\n pushOptionsChangeAction(\n {\n type: 'code',\n element: selectedCodeBlock,\n shapeName: 'code'\n },\n {\n color: codeEditor.style.color,\n font: codeEditor.style.fontFamily,\n size: currentSize,\n align: codeEditor.style.textAlign\n },\n {\n color: codeEditor.style.color,\n font: codeEditor.style.fontFamily,\n size: newSize,\n align: codeEditor.style.textAlign\n }\n );\n }\n\n codeEditor.style.fontSize = newSize;\n adjustCodeEditorSize(codeEditor); // Adjust container size as font size changes\n updateSyntaxHighlighting(codeEditor); // Re-highlight with new size\n setTimeout(updateCodeSelectionFeedback, 0);\n }\n }\n });\n});\n\ncodeTextAlignOptions.forEach((span) => {\n span.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n codeTextAlignOptions.forEach((el) => el.classList.remove(\"selected\"));\n span.classList.add(\"selected\");\n\n const newAlign = span.getAttribute(\"data-id\");\n const oldAlign = codeTextAlign;\n codeTextAlign = newAlign;\n\n if (selectedCodeBlock) {\n const codeEditor = selectedCodeBlock.querySelector('.svg-code-editor');\n if (codeEditor) {\n const currentAlign = codeEditor.style.textAlign;\n\n if (currentAlign !== newAlign) {\n pushOptionsChangeAction(\n {\n type: 'code',\n element: selectedCodeBlock,\n shapeName: 'code'\n },\n {\n color: codeEditor.style.color,\n font: codeEditor.style.fontFamily,\n size: codeEditor.style.fontSize,\n align: currentAlign\n },\n {\n color: codeEditor.style.color,\n font: codeEditor.style.fontFamily,\n size: codeEditor.style.fontSize,\n align: newAlign\n }\n );\n }\n // Code is typically left-aligned, but if user forces, apply it.\n // Note: Highlight.js might override some text-alignment styles on its own.\n codeEditor.style.textAlign = newAlign; \n setTimeout(updateCodeSelectionFeedback, 0);\n }\n }\n });\n});\n\n\n\nconst editorStyles = `\n.svg-code-container {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n border-radius: 6px;\n}\n\n.svg-code-editor {\n scrollbar-width: thin;\n scrollbar-color: #484f58 #161b22;\n}\n\n.svg-code-editor::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n}\n\n.svg-code-editor::-webkit-scrollbar-track {\n background: #161b22;\n border-radius: 6px;\n}\n\n.svg-code-editor::-webkit-scrollbar-thumb {\n background: #484f58;\n border-radius: 6px;\n}\n\n.svg-code-editor::-webkit-scrollbar-thumb:hover {\n background: #6e7681;\n}\n\n/* Language detection indicator */\n.svg-code-container::after {\n content: attr(data-language);\n position: absolute;\n top: -20px;\n right: 0;\n background: #007acc;\n color: white;\n padding: 2px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-family: monospace;\n opacity: 0.8;\n}\n`;\n\n\nif (!document.getElementById('code-editor-styles')) {\n const styleSheet = document.createElement('style');\n styleSheet.id = 'code-editor-styles';\n styleSheet.textContent = editorStyles;\n document.head.appendChild(styleSheet);\n}\n\nfunction setCodeLanguage(lang) {\n codeLanguage = lang;\n // Update selected code block's language if one is selected\n if (selectedCodeBlock) {\n const codeElement = selectedCodeBlock.querySelector('text');\n if (codeElement) {\n codeElement.setAttribute(\"data-language\", lang);\n }\n }\n}\n\nfunction getCodeLanguage() {\n return codeLanguage;\n}\n\nfunction getSelectedCodeBlock() {\n return selectedCodeBlock;\n}\n\nexport {\n handleCodeMouseDown,\n handleCodeMouseMove,\n handleCodeMouseUp,\n addCodeBlock,\n wrapCodeElement,\n selectCodeBlock,\n deselectCodeBlock,\n makeCodeEditable,\n applySyntaxHighlightingToSVG,\n createHighlightedSVGText,\n updateCodeBackground,\n extractTextFromCodeElement,\n setCodeLanguage,\n getCodeLanguage,\n getSelectedCodeBlock\n};\n\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/tools/frameTool.js"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable */\n// Frame tool event handlers - extracted from frameHolder.js\nimport { pushCreateAction, pushDeleteAction, pushTransformAction, pushFrameAttachmentAction } from '../core/UndoRedo.js';\nimport { updateAttachedArrows, cleanupAttachments } from './arrowTool.js';\n\nlet currentFrame = null;\nlet isResizing = false;\nlet isDragging = false;\nlet activeAnchor = null;\nlet isDrawingFrame = false;\nlet frameStrokeColor = \"#888\";\nlet frameStrokeThickness = 2;\nlet frameFillColor = \"transparent\";\nlet frameOpacity = 1;\nlet startX, startY;\nlet dragOldPosFrame = null;\n\nfunction getSVGCoordsFromMouse(e) {\n const viewBox = svg.viewBox.baseVal;\n const rect = svg.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const mouseY = e.clientY - rect.top;\n const svgX = viewBox.x + (mouseX / rect.width) * viewBox.width;\n const svgY = viewBox.y + (mouseY / rect.height) * viewBox.height;\n return { x: svgX, y: svgY };\n}\n\n\n// Event handlers for frame tool\nconst handleMouseDown = (e) => {\n if (!isFrameToolActive && !isSelectionToolActive) return;\n\n const { x, y } = getSVGCoordsFromMouse(e);\n\n if (isFrameToolActive) {\n isDrawingFrame = true;\n startX = x;\n startY = y;\n currentFrame = new Frame(x, y, 0, 0, {\n stroke: frameStrokeColor,\n strokeWidth: frameStrokeThickness,\n fill: frameFillColor,\n opacity: frameOpacity\n });\n shapes.push(currentFrame);\n currentShape = currentFrame;\n } else if (isSelectionToolActive) {\n // Handle frame selection \u2014 but first check if a contained shape was clicked\n for (let i = shapes.length - 1; i >= 0; i--) {\n if (shapes[i].shapeName === 'frame' && shapes[i].contains(x, y)) {\n const clickedFrame = shapes[i];\n\n // Check if click is on a shape inside this frame \u2014 let shape handlers deal with it\n let clickedContainedShape = false;\n if (clickedFrame.containedShapes && clickedFrame.containedShapes.length > 0) {\n for (let j = clickedFrame.containedShapes.length - 1; j >= 0; j--) {\n const inner = clickedFrame.containedShapes[j];\n if (inner.contains && inner.contains(x, y)) {\n clickedContainedShape = true;\n break;\n }\n }\n }\n // If a contained shape was clicked, don't select the frame \u2014\n // and crucially, clear `currentShape` so the EventDispatcher's\n // `if (handled && prevShape && !currentShape) handled=false` gate\n // triggers and the dispatcher falls through to shape-specific\n // handlers. Without this clear, the dispatcher returns with\n // `handled=true` and the child shape is never selected (Issue\n // #22, bug #2).\n if (clickedContainedShape) {\n if (currentShape && currentShape.shapeName === 'frame'\n && typeof currentShape.removeSelection === 'function') {\n currentShape.removeSelection();\n }\n currentShape = null;\n return;\n }\n\n if (currentShape && currentShape !== clickedFrame) {\n currentShape.removeSelection();\n }\n currentShape = clickedFrame;\n currentShape.selectFrame();\n\n // Check for anchor interaction\n const anchorIndex = typeof currentShape.isNearAnchor === 'function' ? currentShape.isNearAnchor(x, y) : null;\n if (anchorIndex !== null) {\n activeAnchor = anchorIndex;\n isResizing = true;\n } else {\n isDragging = true;\n startX = x;\n startY = y;\n dragOldPosFrame = {\n x: currentShape.x,\n y: currentShape.y,\n width: currentShape.width,\n height: currentShape.height,\n rotation: currentShape.rotation\n };\n }\n return;\n }\n }\n\n // If no frame was clicked, deselect current\n if (currentShape && currentShape.shapeName === 'frame') {\n currentShape.removeSelection();\n currentShape = null;\n }\n }\n};\n\n const handleMouseMove = (e) => {\n const { x, y } = getSVGCoordsFromMouse(e);\n\n if (isDrawingFrame && currentFrame) {\n const width = Math.abs(x - startX);\n const height = Math.abs(y - startY);\n currentFrame.x = Math.min(startX, x);\n currentFrame.y = Math.min(startY, y);\n currentFrame.width = width;\n currentFrame.height = height;\n currentFrame.draw();\n } else if (isDragging && currentShape && currentShape.shapeName === 'frame') {\n const dx = x - startX;\n const dy = y - startY;\n \n // Use the frame's move method which properly handles contained shapes\n currentShape.move(dx, dy);\n \n startX = x;\n startY = y;\n }\n};\n\n const handleMouseUp = (e) => {\n if (isDrawingFrame && currentFrame) {\n // Check if frame is too small\n if (currentFrame.width < 10 || currentFrame.height < 10) {\n currentFrame.destroy();\n currentFrame = null;\n currentShape = null;\n } else {\n pushCreateAction(currentFrame);\n // Check for shapes that should be contained in the new frame\n currentFrame.updateContainedShapes(true); // Apply clipping immediately for new frames\n\n // Auto-select the new frame and switch to selection tool\n const placedFrame = currentFrame;\n if (window.__sketchStoreApi) {\n window.__sketchStoreApi.setActiveTool('select', { afterDraw: true });\n } else {\n window.isSelectionToolActive = true;\n }\n currentShape = placedFrame;\n placedFrame.selectFrame();\n }\n isDrawingFrame = false;\n }\n\n if (isDragging && dragOldPosFrame && currentShape) {\n const newPos = {\n x: currentShape.x,\n y: currentShape.y,\n width: currentShape.width,\n height: currentShape.height,\n rotation: currentShape.rotation\n };\n pushTransformAction(currentShape, dragOldPosFrame, newPos);\n dragOldPosFrame = null;\n \n // Update frame containment after moving frame (but don't re-move contained shapes)\n if (currentShape.shapeName === 'frame') {\n currentShape.updateClipPath();\n }\n }\n\n // Only check frame containment for shapes that aren't already in frames\n if (!isDragging) {\n shapes.forEach(shape => {\n if (shape.shapeName !== 'frame' && !shape.parentFrame) {\n shapes.forEach(frame => {\n if (frame.shapeName === 'frame') {\n if (frame.isShapeInFrame(shape)) {\n frame.addShapeToFrame(shape);\n }\n }\n });\n }\n });\n }\n\n isDrawingFrame = false;\n isDragging = false;\n isResizing = false;\n activeAnchor = null;\n svg.style.cursor = 'default';\n};\n\nFrame.prototype.isNearAnchor = function(x, y) {\n const anchorSize = 10 / currentZoom;\n \n // Define anchor positions\n const anchorPositions = [\n { x: this.x, y: this.y },\n { x: this.x + this.width / 2, y: this.y },\n { x: this.x + this.width, y: this.y },\n { x: this.x + this.width, y: this.y + this.height / 2 },\n { x: this.x + this.width, y: this.y + this.height },\n { x: this.x + this.width / 2, y: this.y + this.height },\n { x: this.x, y: this.y + this.height },\n { x: this.x, y: this.y + this.height / 2 },\n { x: this.x + this.width / 2, y: this.y - 30 / currentZoom } // Rotation handle\n ];\n\n for (let i = 0; i < anchorPositions.length; i++) {\n const pos = anchorPositions[i];\n const distance = Math.sqrt((x - pos.x) ** 2 + (y - pos.y) ** 2);\n if (distance <= anchorSize) {\n return i;\n }\n }\n return null;\n};\n\n// Delete functionality\nfunction deleteCurrentFrame() {\n if (currentShape && currentShape.shapeName === 'frame') {\n const frame = currentShape;\n const isDiagramFrame = !!frame._diagramType;\n\n // Issue #24 bug #7: regular frame \u2192 orphan children + snapshot\n // (mirrors deleteSelectedShapes / EngineShortcuts).\n let childSnapshot = null;\n if (!isDiagramFrame) {\n childSnapshot = [...(frame.containedShapes || [])];\n for (const child of childSnapshot) {\n if (!child || child === frame) continue;\n const el = child.group || child.element;\n if (el) {\n if (frame.clipGroup && el.parentNode === frame.clipGroup) frame.clipGroup.removeChild(el);\n if (window.svg && el.parentNode !== window.svg) window.svg.appendChild(el);\n }\n child.parentFrame = null;\n delete child.isBeingMovedByFrame;\n }\n frame.containedShapes = [];\n }\n\n const idx = shapes.indexOf(frame);\n if (idx !== -1) shapes.splice(idx, 1);\n\n if (!isDiagramFrame) {\n if (frame.group && frame.group.parentNode) frame.group.parentNode.removeChild(frame.group);\n if (frame.clipGroup && frame.clipGroup.parentNode) frame.clipGroup.parentNode.removeChild(frame.clipGroup);\n if (frame.clipPath && frame.clipPath.parentNode) frame.clipPath.parentNode.removeChild(frame.clipPath);\n } else if (frame.group && frame.group.parentNode) {\n frame.group.parentNode.removeChild(frame.group);\n }\n\n if (childSnapshot) pushDeleteAction(frame, { childSnapshot });\n else pushDeleteAction(frame);\n currentShape = null;\n }\n}\n\ndocument.addEventListener('keydown', (e) => {\n if (e.key === 'Delete' && currentShape && currentShape.shapeName === 'frame') {\n deleteCurrentFrame();\n }\n});\n\nwindow.Frame = Frame;\n\nexport {\n handleMouseDown as handleMouseDownFrame,\n handleMouseMove as handleMouseMoveFrame,\n handleMouseUp as handleMouseUpFrame\n};"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|