@elixpo/lixsketch 5.4.7 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/dist/react/AIRenderer-M4LMJ66J.js +1105 -0
  2. package/dist/react/AIRenderer-M4LMJ66J.js.map +7 -0
  3. package/dist/react/Arrow-BJDAXPMH.js +8 -0
  4. package/dist/react/Arrow-BJDAXPMH.js.map +7 -0
  5. package/dist/react/Circle-KPG7TKIX.js +8 -0
  6. package/dist/react/Circle-KPG7TKIX.js.map +7 -0
  7. package/dist/react/CodeShape-K4DIZAIV.js +8 -0
  8. package/dist/react/CodeShape-K4DIZAIV.js.map +7 -0
  9. package/dist/react/CopyPaste-4CKJRHJ3.js +569 -0
  10. package/dist/react/CopyPaste-4CKJRHJ3.js.map +7 -0
  11. package/dist/react/EraserTrail-PA6IQLQN.js +20 -0
  12. package/dist/react/EraserTrail-PA6IQLQN.js.map +7 -0
  13. package/dist/react/EventDispatcher-SRFH6LQZ.js +463 -0
  14. package/dist/react/EventDispatcher-SRFH6LQZ.js.map +7 -0
  15. package/dist/react/Frame-6UR5XPAX.js +10 -0
  16. package/dist/react/Frame-6UR5XPAX.js.map +7 -0
  17. package/dist/react/FreehandStroke-CK24NUT3.js +8 -0
  18. package/dist/react/FreehandStroke-CK24NUT3.js.map +7 -0
  19. package/dist/react/GraphEngine-QE5B2PMR.js +340 -0
  20. package/dist/react/GraphEngine-QE5B2PMR.js.map +7 -0
  21. package/dist/react/GraphMathParser-2WMTY4IE.js +10 -0
  22. package/dist/react/GraphMathParser-2WMTY4IE.js.map +7 -0
  23. package/dist/react/IconShape-KMIA6T2H.js +10 -0
  24. package/dist/react/IconShape-KMIA6T2H.js.map +7 -0
  25. package/dist/react/ImageShape-CHHGBXUQ.js +10 -0
  26. package/dist/react/ImageShape-CHHGBXUQ.js.map +7 -0
  27. package/dist/react/LayerOrder-XCHF4MSS.js +66 -0
  28. package/dist/react/LayerOrder-XCHF4MSS.js.map +7 -0
  29. package/dist/react/Line-2KOQEEGA.js +10 -0
  30. package/dist/react/Line-2KOQEEGA.js.map +7 -0
  31. package/dist/react/LixScriptParser-JYWJX375.js +1033 -0
  32. package/dist/react/LixScriptParser-JYWJX375.js.map +7 -0
  33. package/dist/react/MermaidFlowchartRenderer-4QBAZ5MB.js +412 -0
  34. package/dist/react/MermaidFlowchartRenderer-4QBAZ5MB.js.map +7 -0
  35. package/dist/react/MermaidSequenceParser-UKG2NSZY.js +8 -0
  36. package/dist/react/MermaidSequenceParser-UKG2NSZY.js.map +7 -0
  37. package/dist/react/MermaidSequenceRenderer-HPLHY5II.js +387 -0
  38. package/dist/react/MermaidSequenceRenderer-HPLHY5II.js.map +7 -0
  39. package/dist/react/Rectangle-6FE7RN6W.js +8 -0
  40. package/dist/react/Rectangle-6FE7RN6W.js.map +7 -0
  41. package/dist/react/ResizeCode-WAMDTKSW.js +2 -0
  42. package/dist/react/ResizeCode-WAMDTKSW.js.map +7 -0
  43. package/dist/react/ResizeShapes-LKEQTITP.js +250 -0
  44. package/dist/react/ResizeShapes-LKEQTITP.js.map +7 -0
  45. package/dist/react/SceneSerializer-4U4B24JM.js +739 -0
  46. package/dist/react/SceneSerializer-4U4B24JM.js.map +7 -0
  47. package/dist/react/Selection-VVUHY5YJ.js +34 -0
  48. package/dist/react/Selection-VVUHY5YJ.js.map +7 -0
  49. package/dist/react/SketchEngine-YA4RG3KX.js +413 -0
  50. package/dist/react/SketchEngine-YA4RG3KX.js.map +7 -0
  51. package/dist/react/TextShape-54ZJ66E3.js +8 -0
  52. package/dist/react/TextShape-54ZJ66E3.js.map +7 -0
  53. package/dist/react/UndoRedo-M2JZUBKN.js +30 -0
  54. package/dist/react/UndoRedo-M2JZUBKN.js.map +7 -0
  55. package/dist/react/ZoomPan-U3TXC5AJ.js +186 -0
  56. package/dist/react/ZoomPan-U3TXC5AJ.js.map +7 -0
  57. package/dist/react/arrowTool-CWEMIRXK.js +17 -0
  58. package/dist/react/arrowTool-CWEMIRXK.js.map +7 -0
  59. package/dist/react/boxicons-5JNJQPUP.woff +0 -0
  60. package/dist/react/boxicons-6NVWQSCQ.eot +0 -0
  61. package/dist/react/boxicons-AQ5N6WP7.woff2 +0 -0
  62. package/dist/react/boxicons-GDR4JU3X.ttf +0 -0
  63. package/dist/react/boxicons-NNFHLMOR.svg +1660 -0
  64. package/dist/react/chunk-2OQXI7QB.js +564 -0
  65. package/dist/react/chunk-2OQXI7QB.js.map +7 -0
  66. package/dist/react/chunk-5OUBTHHO.js +187 -0
  67. package/dist/react/chunk-5OUBTHHO.js.map +7 -0
  68. package/dist/react/chunk-6PFXZKL2.js +628 -0
  69. package/dist/react/chunk-6PFXZKL2.js.map +7 -0
  70. package/dist/react/chunk-6SFNWGGZ.js +453 -0
  71. package/dist/react/chunk-6SFNWGGZ.js.map +7 -0
  72. package/dist/react/chunk-7TZSIR6V.js +210 -0
  73. package/dist/react/chunk-7TZSIR6V.js.map +7 -0
  74. package/dist/react/chunk-AJAZC37E.js +662 -0
  75. package/dist/react/chunk-AJAZC37E.js.map +7 -0
  76. package/dist/react/chunk-BU4D2WYQ.js +1213 -0
  77. package/dist/react/chunk-BU4D2WYQ.js.map +7 -0
  78. package/dist/react/chunk-BZE4CEBG.js +747 -0
  79. package/dist/react/chunk-BZE4CEBG.js.map +7 -0
  80. package/dist/react/chunk-CB2RANCB.js +212 -0
  81. package/dist/react/chunk-CB2RANCB.js.map +7 -0
  82. package/dist/react/chunk-DNAG7ML6.js +128 -0
  83. package/dist/react/chunk-DNAG7ML6.js.map +7 -0
  84. package/dist/react/chunk-HZWLPXFN.js +198 -0
  85. package/dist/react/chunk-HZWLPXFN.js.map +7 -0
  86. package/dist/react/chunk-I6HCCIXB.js +572 -0
  87. package/dist/react/chunk-I6HCCIXB.js.map +7 -0
  88. package/dist/react/chunk-IZ5OGWGW.js +235 -0
  89. package/dist/react/chunk-IZ5OGWGW.js.map +7 -0
  90. package/dist/react/chunk-JJCJNLNN.js +1490 -0
  91. package/dist/react/chunk-JJCJNLNN.js.map +7 -0
  92. package/dist/react/chunk-JQ3IRFDP.js +222 -0
  93. package/dist/react/chunk-JQ3IRFDP.js.map +7 -0
  94. package/dist/react/chunk-L5OARZJ7.js +1134 -0
  95. package/dist/react/chunk-L5OARZJ7.js.map +7 -0
  96. package/dist/react/chunk-LHRTXNVE.js +1600 -0
  97. package/dist/react/chunk-LHRTXNVE.js.map +7 -0
  98. package/dist/react/chunk-Q2GA4MBZ.js +1653 -0
  99. package/dist/react/chunk-Q2GA4MBZ.js.map +7 -0
  100. package/dist/react/chunk-QNSE5BAY.js +519 -0
  101. package/dist/react/chunk-QNSE5BAY.js.map +7 -0
  102. package/dist/react/chunk-QXFBG7OM.js +191 -0
  103. package/dist/react/chunk-QXFBG7OM.js.map +7 -0
  104. package/dist/react/chunk-T6ZVV5ZO.js +714 -0
  105. package/dist/react/chunk-T6ZVV5ZO.js.map +7 -0
  106. package/dist/react/chunk-URB6MY46.js +974 -0
  107. package/dist/react/chunk-URB6MY46.js.map +7 -0
  108. package/dist/react/chunk-VN62KLOC.js +931 -0
  109. package/dist/react/chunk-VN62KLOC.js.map +7 -0
  110. package/dist/react/chunk-VQVEPJSA.js +158 -0
  111. package/dist/react/chunk-VQVEPJSA.js.map +7 -0
  112. package/dist/react/chunk-XISEAGBV.js +1632 -0
  113. package/dist/react/chunk-XISEAGBV.js.map +7 -0
  114. package/dist/react/chunk-YKJUBFHE.js +575 -0
  115. package/dist/react/chunk-YKJUBFHE.js.map +7 -0
  116. package/dist/react/circleTool-NUATSEI2.js +14 -0
  117. package/dist/react/circleTool-NUATSEI2.js.map +7 -0
  118. package/dist/react/codeTool-MHCB2FNB.js +38 -0
  119. package/dist/react/codeTool-MHCB2FNB.js.map +7 -0
  120. package/dist/react/eraserTool-2GS2LQCS.js +103 -0
  121. package/dist/react/eraserTool-2GS2LQCS.js.map +7 -0
  122. package/dist/react/frameTool-PWVKKXSP.js +14 -0
  123. package/dist/react/frameTool-PWVKKXSP.js.map +7 -0
  124. package/dist/react/freehandTool-SLYGASVP.js +14 -0
  125. package/dist/react/freehandTool-SLYGASVP.js.map +7 -0
  126. package/dist/react/iconTool-GPZ7O7NH.js +18 -0
  127. package/dist/react/iconTool-GPZ7O7NH.js.map +7 -0
  128. package/dist/react/imageTool-D5R4XGEU.js +15 -0
  129. package/dist/react/imageTool-D5R4XGEU.js.map +7 -0
  130. package/dist/react/index.js +5342 -0
  131. package/dist/react/index.js.map +7 -0
  132. package/dist/react/laserTool-XVMV63AV.js +239 -0
  133. package/dist/react/laserTool-XVMV63AV.js.map +7 -0
  134. package/dist/react/lineTool-WNI5EMZ5.js +14 -0
  135. package/dist/react/lineTool-WNI5EMZ5.js.map +7 -0
  136. package/dist/react/lixCode-OJMVUXXI.ttf +0 -0
  137. package/dist/react/lixDefault-JEAPAUJL.ttf +0 -0
  138. package/dist/react/lixFancy-BPXYM5CQ.ttf +0 -0
  139. package/dist/react/lixFont-CPKEUDVM.woff2 +0 -0
  140. package/dist/react/rectangleTool-U7DZ6ZTA.js +14 -0
  141. package/dist/react/rectangleTool-U7DZ6ZTA.js.map +7 -0
  142. package/dist/react/styles.css +6627 -0
  143. package/dist/react/textTool-M7S6F3VC.js +21 -0
  144. package/dist/react/textTool-M7S6F3VC.js.map +7 -0
  145. package/package.json +39 -5
  146. package/src/EngineShortcuts.js +83 -27
  147. package/src/core/AIRenderer.js +30 -18
  148. package/src/core/GraphEngine.js +64 -41
  149. package/src/core/MermaidFlowchartRenderer.js +153 -88
  150. package/src/core/MermaidSequenceRenderer.js +168 -93
  151. package/src/core/SceneSerializer.js +86 -2
  152. package/src/core/Selection.js +119 -19
  153. package/src/core/UndoRedo.js +82 -15
  154. package/src/core/ZoomPan.js +15 -5
  155. package/src/index.js +14 -1
  156. package/src/react/LixSketchCanvas.jsx +347 -0
  157. package/src/react/components/AppMenu.jsx +475 -0
  158. package/src/react/components/Footer.jsx +85 -0
  159. package/src/react/components/Toolbar.jsx +140 -0
  160. package/src/react/components/canvas/CanvasLoadingOverlay.jsx +76 -0
  161. package/src/react/components/canvas/ContextMenu.jsx +466 -0
  162. package/src/react/components/canvas/FindBar.jsx +177 -0
  163. package/src/react/components/canvas/ImageSourcePicker.jsx +133 -0
  164. package/src/react/components/canvas/MultiSelectActions.jsx +120 -0
  165. package/src/react/components/canvas/SVGCanvas.jsx +145 -0
  166. package/src/react/components/canvas/SaveStatusIndicator.jsx +29 -0
  167. package/src/react/components/modals/CanvasPropertiesModal.jsx +358 -0
  168. package/src/react/components/modals/CommandPalette.jsx +307 -0
  169. package/src/react/components/modals/ExportImageModal.jsx +287 -0
  170. package/src/react/components/modals/GraphModal.jsx +174 -0
  171. package/src/react/components/modals/HelpModal.jsx +208 -0
  172. package/src/react/components/modals/LixScriptModal.jsx +130 -0
  173. package/src/react/components/modals/ShortcutsModal.jsx +125 -0
  174. package/src/react/components/sidebars/ArrowSidebar.jsx +173 -0
  175. package/src/react/components/sidebars/CircleSidebar.jsx +134 -0
  176. package/src/react/components/sidebars/FrameSidebar.jsx +263 -0
  177. package/src/react/components/sidebars/IconSidebar.jsx +279 -0
  178. package/src/react/components/sidebars/ImageSidebar.jsx +69 -0
  179. package/src/react/components/sidebars/LineSidebar.jsx +109 -0
  180. package/src/react/components/sidebars/PaintbrushSidebar.jsx +119 -0
  181. package/src/react/components/sidebars/RectangleSidebar.jsx +165 -0
  182. package/src/react/components/sidebars/ShapeSidebar.jsx +130 -0
  183. package/src/react/components/sidebars/TextSidebar.jsx +174 -0
  184. package/src/react/hooks/inertStores.js +58 -0
  185. package/src/react/hooks/useSketchEngine.js +76 -0
  186. package/src/react/hooks/useTranslation.js +92 -0
  187. package/src/react/index.js +41 -0
  188. package/src/react/store/useSketchStore.js +234 -0
  189. package/src/react/store/useUIStore.js +196 -0
  190. package/src/react/styles/arrowSidebar.css +263 -0
  191. package/src/react/styles/canvasStroke.css +47 -0
  192. package/src/react/styles/canvasTools.css +769 -0
  193. package/src/react/styles/circleSidebar.css +206 -0
  194. package/src/react/styles/fonts/fonts.css +29 -0
  195. package/src/react/styles/fonts/lixCode.ttf +0 -0
  196. package/src/react/styles/fonts/lixDefault.ttf +0 -0
  197. package/src/react/styles/fonts/lixDocs.ttf +0 -0
  198. package/src/react/styles/fonts/lixFancy.ttf +0 -0
  199. package/src/react/styles/fonts/lixFont.woff2 +0 -0
  200. package/src/react/styles/lineSidebar.css +207 -0
  201. package/src/react/styles/paintbrushSidebar.css +247 -0
  202. package/src/react/styles/squareSidebar.css +206 -0
  203. package/src/react/styles/writeText.css +149 -0
  204. package/src/react/styles.css +175 -0
  205. package/src/react/toolsEnum.js +20 -0
  206. package/src/react/utils/toast.js +18 -0
  207. package/src/shapes/Frame.js +7 -1
  208. package/src/shapes/Line.js +11 -5
  209. package/src/tools/arrowTool.js +30 -4
  210. package/src/tools/circleTool.js +33 -9
  211. package/src/tools/codeTool.js +5 -3
  212. package/src/tools/frameTool.js +47 -7
  213. package/src/tools/freehandTool.js +12 -4
  214. package/src/tools/iconTool.js +7 -1
  215. package/src/tools/imageTool.js +7 -1
  216. package/src/tools/lineTool.js +27 -3
  217. package/src/tools/rectangleTool.js +45 -8
  218. package/src/tools/textTool.js +23 -6
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/tools/iconTool.js"],
4
+ "sourcesContent": ["/* eslint-disable */\n// Icon tool event handlers - extracted from icons.js\nimport { pushCreateAction, pushDeleteAction, pushTransformAction, pushFrameAttachmentAction } from '../core/UndoRedo.js';\nimport { updateAttachedArrows as updateArrowsForShape, cleanupAttachments } from './arrowTool.js';\n\n\nlet isDraggingIcon = false;\nlet iconToPlace = null;\nlet iconX = 0;\nlet iconY = 0;\nlet scaleFactor = 0.2;\nlet currentIconElement = null;\n\nlet selectedIcon = null;\nlet originalX, originalY, originalWidth, originalHeight;\nlet currentAnchor = null;\nlet isDragging = false;\nlet isRotatingIcon = false;\nlet dragOffsetX, dragOffsetY;\nlet startRotationMouseAngle = null;\nlet startIconRotation = null;\nlet iconRotation = 0;\nlet aspect_ratio_lock = true;\nconst minIconSize = 25;\nconst miniatureSize = 40;\nconst placedIconSize = 40;\nlet draggedShapeInitialFrameIcon = null;\nlet hoveredFrameIcon = null;\nlet _pendingDragChecker = null; // module-level ref so cancelDragPrep can remove it\n\nconst iconSearchInput = document.getElementById('iconSearchInput') || document.createElement('input');\nlet searchTimeout = null;\n\n\nfunction getSVGElement() {\n return document.getElementById('freehand-canvas');\n}\n\n\nfunction removeSelection() {\n const svg = getSVGElement();\n if (!svg) return;\n\n // Remove ALL selection outlines (prevents orphaned ghost elements)\n svg.querySelectorAll(\".selection-outline\").forEach(el => el.remove());\n\n removeResizeAnchors();\n removeRotationAnchor();\n\n if (selectedIcon) {\n selectedIcon.removeEventListener('pointerdown', startDrag);\n selectedIcon.removeEventListener('pointerup', stopDrag);\n selectedIcon.removeEventListener('pointerleave', stopDrag);\n }\n}\n\nfunction wrapIconElement(element) {\n const iconShape = new IconShape(element);\n return iconShape;\n}\n\ndocument.getElementById(\"importIcon\")?.addEventListener('click', () => {\n \n\n const iconContainer = document.getElementById('iconsToolBar');\n if (iconContainer) {\n if(iconContainer.classList.contains('hidden')) {\n iconContainer.classList.remove('hidden');\n iconSearchInput.focus();\n }\n else \n {\n iconContainer.classList.add('hidden');\n }\n \n }\n});\n\nfunction getSVGCoordsFromMouse(e) {\n const svg = getSVGElement();\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\nconst handleMouseMoveIcon = (e) => {\n if (!isDraggingIcon || !iconToPlace || !isIconToolActive) return;\n\n const { x, y } = getSVGCoordsFromMouse(e);\n iconX = x;\n iconY = y;\n\n drawMiniatureIcon();\n\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n shapes.forEach(frame => {\n if (frame.shapeName === 'frame') {\n const tempIconBounds = {\n x: iconX - 50,\n y: iconY - 50,\n width: 100,\n height: 100\n };\n\n if (frame.isShapeInFrame(tempIconBounds)) {\n frame.highlightFrame();\n hoveredFrameIcon = frame;\n if (window.__iconShapeState) window.__iconShapeState.hoveredFrameIcon = frame;\n } else if (hoveredFrameIcon === frame) {\n frame.removeHighlight();\n hoveredFrameIcon = null;\n if (window.__iconShapeState) window.__iconShapeState.hoveredFrameIcon = null;\n }\n }\n });\n }\n};\n\nconst drawMiniatureIcon = () => {\n if (!isDraggingIcon || !iconToPlace || !isIconToolActive) return;\n\n const svg = getSVGElement();\n if (!svg) {\n console.error('SVG element not found for miniature icon');\n return;\n }\n\n if (currentIconElement) {\n svg.removeChild(currentIconElement);\n currentIconElement = null;\n }\n\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = iconToPlace;\n const svgElement = tempDiv.querySelector('svg');\n\n if (svgElement) {\n const iconGroup = document.createElementNS(\"http://www.w3.org/2000/svg\", \"g\");\n\n const viewBox = svgElement.getAttribute('viewBox');\n let vbWidth = 24, vbHeight = 24;\n\n if (viewBox) {\n const [, , widthStr, heightStr] = viewBox.split(/\\s+/);\n vbWidth = parseFloat(widthStr) || 24;\n vbHeight = parseFloat(heightStr) || 24;\n } else {\n const width = svgElement.getAttribute('width');\n const height = svgElement.getAttribute('height');\n if (width && height) {\n vbWidth = parseFloat(width) || 24;\n vbHeight = parseFloat(height) || 24;\n }\n }\n\n const scale = miniatureSize / Math.max(vbWidth, vbHeight);\n iconGroup.setAttribute(\"transform\", `translate(${iconX - miniatureSize / 2}, ${iconY - miniatureSize / 2}) scale(${scale})`);\n\n const allChildren = svgElement.children;\n for (let i = 0; i < allChildren.length; i++) {\n const clonedChild = allChildren[i].cloneNode(true);\n \n const applyGrayStyle = (element) => {\n if (element.nodeType === 1) {\n element.setAttribute('fill', '#666');\n element.setAttribute('stroke', '#666');\n \n for (let j = 0; j < element.children.length; j++) {\n applyGrayStyle(element.children[j]);\n }\n }\n };\n \n applyGrayStyle(clonedChild);\n iconGroup.appendChild(clonedChild);\n }\n\n iconGroup.setAttribute(\"style\", \"pointer-events: none; opacity: 0.7;\");\n iconGroup.setAttribute(\"class\", \"miniature-icon\");\n\n currentIconElement = iconGroup;\n svg.appendChild(currentIconElement);\n }\n};\n\nconst handleMouseDownIcon = async (e) => {\n if (!e.target) return;\n if (isSelectionToolActive) {\n const clickedIcon = e.target.closest('[type=\"icon\"]');\n if (clickedIcon) {\n e.preventDefault();\n e.stopPropagation();\n\n if (selectedIcon === clickedIcon) {\n originalX = parseFloat(selectedIcon.getAttribute('x')) || 0;\n originalY = parseFloat(selectedIcon.getAttribute('y')) || 0;\n originalWidth = parseFloat(selectedIcon.getAttribute('width')) || placedIconSize;\n originalHeight = parseFloat(selectedIcon.getAttribute('height')) || placedIconSize;\n\n const { x, y } = getSVGCoordsFromMouse(e);\n dragOffsetX = x - originalX;\n dragOffsetY = y - originalY;\n\n const initialMouseX = x;\n const initialMouseY = y;\n\n // Threshold in screen pixels converted to SVG units, so zoom doesn't affect sensitivity\n const svgEl = getSVGElement();\n const svgRect2 = svgEl ? svgEl.getBoundingClientRect() : { width: 1536 };\n const svgViewW = svgEl ? svgEl.viewBox.baseVal.width : 1536;\n const dragThreshold = 12 * (svgViewW / svgRect2.width); // ~12 screen pixels\n\n function checkDragStartWithThreshold(moveEvent) {\n const { x: currentX, y: currentY } = getSVGCoordsFromMouse(moveEvent);\n const deltaX = Math.abs(currentX - initialMouseX);\n const deltaY = Math.abs(currentY - initialMouseY);\n\n if (deltaX > dragThreshold || deltaY > dragThreshold) {\n document.removeEventListener('pointermove', checkDragStartWithThreshold);\n document.removeEventListener('pointerup', cancelDragPrep);\n window.removeEventListener('pointerup', cancelDragPrep);\n\n const svg = getSVGElement();\n if (svg) svg.removeEventListener('pointerup', cancelDragPrep);\n\n startDrag(moveEvent);\n }\n }\n\n _pendingDragChecker = checkDragStartWithThreshold;\n document.addEventListener('pointermove', checkDragStartWithThreshold);\n document.addEventListener('pointerup', cancelDragPrep);\n window.addEventListener('pointerup', cancelDragPrep);\n\n const svg = getSVGElement();\n if (svg) svg.addEventListener('pointerup', cancelDragPrep);\n\n return;\n } else {\n selectIcon(e);\n return;\n }\n }\n\n // Clicked on empty canvas while an icon is selected \u2014 deselect it\n if (selectedIcon) {\n removeSelection();\n selectedIcon = null;\n if (currentShape && currentShape.shapeName === 'icon') {\n currentShape = null;\n }\n }\n return;\n }\n\n if (!isDraggingIcon || !iconToPlace || !isIconToolActive) {\n return;\n }\n\n let placedIconShape = null;\n\n try {\n const svg = getSVGElement();\n if (!svg) {\n throw new Error('SVG element not found');\n }\n\n if (currentIconElement) {\n svg.removeChild(currentIconElement);\n currentIconElement = null;\n }\n\n const { x: placedX, y: placedY } = getSVGCoordsFromMouse(e);\n\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = iconToPlace;\n const originalSvgElement = tempDiv.querySelector('svg');\n\n if (!originalSvgElement) {\n throw new Error('Invalid SVG content');\n }\n\n const finalIconGroup = document.createElementNS(\"http://www.w3.org/2000/svg\", \"g\");\n const finalX = placedX - placedIconSize / 2;\n const finalY = placedY - placedIconSize / 2;\n\n const viewBox = originalSvgElement.getAttribute('viewBox');\n let vbWidth = 24, vbHeight = 24;\n\n if (viewBox) {\n const [, , widthStr, heightStr] = viewBox.split(/\\s+/);\n vbWidth = parseFloat(widthStr) || 24;\n vbHeight = parseFloat(heightStr) || 24;\n } else {\n const width = originalSvgElement.getAttribute('width');\n const height = originalSvgElement.getAttribute('height');\n if (width && height) {\n vbWidth = parseFloat(width) || 24;\n vbHeight = parseFloat(height) || 24;\n }\n }\n\n const scale = placedIconSize / Math.max(vbWidth, vbHeight);\n const localCenterX = placedIconSize / 2 / scale;\n const localCenterY = placedIconSize / 2 / scale;\n finalIconGroup.setAttribute('transform', `translate(${finalX}, ${finalY}) scale(${scale}) rotate(0, ${localCenterX}, ${localCenterY})`);\n finalIconGroup.setAttribute('data-viewbox-width', vbWidth);\n finalIconGroup.setAttribute('data-viewbox-height', vbHeight);\n\n const backgroundRect = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n backgroundRect.setAttribute('x', 0);\n backgroundRect.setAttribute('y', 0);\n backgroundRect.setAttribute('width', vbWidth);\n backgroundRect.setAttribute('height', vbHeight);\n backgroundRect.setAttribute('fill', 'transparent');\n backgroundRect.setAttribute('stroke', 'none');\n backgroundRect.setAttribute('style', 'pointer-events: all; cursor: pointer;');\n finalIconGroup.appendChild(backgroundRect);\n\n const allChildren = originalSvgElement.children;\n for (let i = 0; i < allChildren.length; i++) {\n const clonedChild = allChildren[i].cloneNode(true);\n\n // Apply white fill/stroke so icons are visible on dark canvas\n const applyWhiteStyle = (element) => {\n if (element.nodeType === 1) {\n const fill = element.getAttribute('fill');\n const stroke = element.getAttribute('stroke');\n // Replace black/dark fills with white; leave 'none'/'transparent' alone\n if (!fill || fill === '#000' || fill === '#000000' || fill === 'black' || fill === 'currentColor') {\n element.setAttribute('fill', '#ffffff');\n }\n if (stroke === '#000' || stroke === '#000000' || stroke === 'black' || stroke === 'currentColor') {\n element.setAttribute('stroke', '#ffffff');\n }\n for (let j = 0; j < element.children.length; j++) {\n applyWhiteStyle(element.children[j]);\n }\n }\n };\n applyWhiteStyle(clonedChild);\n\n finalIconGroup.appendChild(clonedChild);\n }\n\n finalIconGroup.setAttribute('x', finalX);\n finalIconGroup.setAttribute('y', finalY);\n finalIconGroup.setAttribute('width', placedIconSize);\n finalIconGroup.setAttribute('height', placedIconSize);\n finalIconGroup.setAttribute('type', 'icon');\n finalIconGroup.setAttribute('data-shape-x', finalX);\n finalIconGroup.setAttribute('data-shape-y', finalY);\n finalIconGroup.setAttribute('data-shape-width', placedIconSize);\n finalIconGroup.setAttribute('data-shape-height', placedIconSize);\n finalIconGroup.setAttribute('data-shape-rotation', 0);\n finalIconGroup.shapeID = `icon-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;\n finalIconGroup.setAttribute('id', finalIconGroup.shapeID);\n finalIconGroup.setAttribute('style', 'cursor: pointer; pointer-events: all;');\n\n svg.appendChild(finalIconGroup);\n\n const iconShape = wrapIconElement(finalIconGroup);\n placedIconShape = iconShape;\n\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n // Prevent duplicates \u2014 check if this element is already tracked\n const alreadyExists = shapes.some(s => s.shapeName === 'icon' && s.element === finalIconGroup);\n if (!alreadyExists) {\n shapes.push(iconShape);\n }\n }\n\n const finalFrame = hoveredFrameIcon;\n if (finalFrame) {\n finalFrame.addShapeToFrame(iconShape);\n pushFrameAttachmentAction(finalFrame, iconShape, 'attach', null);\n }\n\n pushCreateAction(iconShape);\n\n // mousedown handles selection; click listener removed to avoid double-selection conflicts\n\n if (hoveredFrameIcon) {\n hoveredFrameIcon.removeHighlight();\n hoveredFrameIcon = null;\n if (window.__iconShapeState) window.__iconShapeState.hoveredFrameIcon = null;\n }\n\n console.log('Icon placed successfully:', finalIconGroup);\n\n } catch (error) {\n console.error(\"Error placing icon:\", error);\n isDraggingIcon = false;\n iconToPlace = null;\n } finally {\n isDraggingIcon = false;\n iconToPlace = null;\n document.body.style.cursor = 'default';\n }\n\n // Select the placed icon but stay in icon tool so the sidebar remains open\n if (placedIconShape) {\n currentShape = placedIconShape;\n currentShape.isSelected = true;\n requestAnimationFrame(() => {\n placedIconShape.selectShape();\n });\n }\n};\n\nconst handleMouseUpIcon = (e) => {\n if (!e.target) return;\n // Deselection on empty-canvas click is handled by handleMouseDownIcon.\n // We intentionally do NOT deselect on mouseup \u2014 after a drag the cursor\n // often ends up on the background, and that shouldn't kill the selection.\n\n if (hoveredFrameIcon) {\n hoveredFrameIcon.removeHighlight();\n hoveredFrameIcon = null;\n }\n};\n\nfunction addSelectionOutline() {\n if (!selectedIcon) return;\n\n const svg = getSVGElement();\n if (!svg) return;\n\n // Use stored SVG-space data attributes \u2014 reliable even immediately after DOM insertion\n const x = parseFloat(selectedIcon.getAttribute('data-shape-x')) || 0;\n const y = parseFloat(selectedIcon.getAttribute('data-shape-y')) || 0;\n const width = parseFloat(selectedIcon.getAttribute('data-shape-width')) || 40;\n const height = parseFloat(selectedIcon.getAttribute('data-shape-height')) || 40;\n const rotation = parseFloat(selectedIcon.getAttribute('data-shape-rotation')) || 0;\n\n const centerX = x + width / 2;\n const centerY = y + height / 2;\n\n const selectionPadding = Math.max(4, width * 0.08);\n const expandedX = x - selectionPadding;\n const expandedY = y - selectionPadding;\n const expandedWidth = width + 2 * selectionPadding;\n const expandedHeight = height + 2 * selectionPadding;\n\n removeSelection();\n\n const outline = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n outline.setAttribute(\"x\", expandedX);\n outline.setAttribute(\"y\", expandedY);\n outline.setAttribute(\"width\", expandedWidth);\n outline.setAttribute(\"height\", expandedHeight);\n outline.setAttribute(\"fill\", \"none\");\n outline.setAttribute(\"stroke\", \"#5B57D1\");\n outline.setAttribute(\"stroke-width\", 1.5);\n outline.setAttribute(\"stroke-dasharray\", \"4 3\");\n outline.setAttribute(\"style\", \"pointer-events: none;\");\n outline.setAttribute(\"class\", \"selection-outline\");\n if (rotation !== 0) {\n outline.setAttribute(\"transform\", `rotate(${rotation}, ${centerX}, ${centerY})`);\n }\n\n svg.appendChild(outline);\n\n addResizeAnchors(expandedX, expandedY, expandedWidth, expandedHeight, centerX, centerY, width, rotation);\n addRotationAnchor(expandedX, expandedY, expandedWidth, expandedHeight, centerX, centerY, width, rotation);\n}\n\nfunction checkDragStart(event) {\n document.removeEventListener('pointermove', checkDragStart);\n document.removeEventListener('pointerup', cancelDragPrep);\n startDrag(event);\n}\nfunction cancelDragPrep(event) {\n if (_pendingDragChecker) {\n document.removeEventListener('pointermove', _pendingDragChecker);\n _pendingDragChecker = null;\n }\n document.removeEventListener('pointerup', cancelDragPrep);\n window.removeEventListener('pointerup', cancelDragPrep);\n\n const svg = getSVGElement();\n if (svg) {\n svg.removeEventListener('pointerup', cancelDragPrep);\n }\n}\n\nfunction startDrag(event) {\n console.log(\"start dragging icon\");\n if (!isSelectionToolActive || !selectedIcon) return;\n \n isDragging = true;\n if (window.__iconShapeState) window.__iconShapeState.isDragging = true;\n\n let iconShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n iconShape = shapes.find(shape => shape.shapeName === 'icon' && shape.element === selectedIcon);\n }\n\n if (iconShape) {\n draggedShapeInitialFrameIcon = iconShape.parentFrame || null;\n\n if (iconShape.parentFrame) {\n iconShape.parentFrame.temporarilyRemoveFromFrame(iconShape);\n }\n }\n\n document.addEventListener('pointermove', dragIcon);\n document.addEventListener('pointerup', stopDrag);\n \n window.addEventListener('pointerup', stopDrag);\n \n const svg = getSVGElement();\n if (svg) {\n svg.addEventListener('pointerup', stopDrag);\n }\n \n document.addEventListener('dragstart', preventDefaultDrag);\n document.addEventListener('selectstart', preventDefaultDrag);\n}\n\nfunction preventDefaultDrag(e) {\n e.preventDefault();\n return false;\n}\n\nfunction selectIcon(event) {\n if (!isSelectionToolActive) return;\n\n event.stopPropagation();\n\n let targetIcon = event.target.closest ? event.target.closest('[type=\"icon\"]') : null;\n if (!targetIcon) {\n let current = event.target;\n while (current && current !== document) {\n if (current.getAttribute && current.getAttribute('type') === 'icon') {\n targetIcon = current;\n break;\n }\n current = current.parentElement;\n }\n }\n\n // Always clean up previous selection before applying new one\n if (selectedIcon) {\n removeSelection();\n }\n\n selectedIcon = targetIcon;\n\n if (!selectedIcon) {\n console.warn('Could not find icon to select');\n return;\n }\n\n const transform = selectedIcon.getAttribute('transform');\n if (transform) {\n const rotateMatch = transform.match(/rotate\\(([^,\\s]+)/);\n if (rotateMatch) {\n iconRotation = parseFloat(rotateMatch[1]);\n }\n } else {\n iconRotation = 0;\n }\n\n addSelectionOutline();\n\n originalX = parseFloat(selectedIcon.getAttribute('x')) || 0;\n originalY = parseFloat(selectedIcon.getAttribute('y')) || 0;\n originalWidth = parseFloat(selectedIcon.getAttribute('width')) || placedIconSize;\n originalHeight = parseFloat(selectedIcon.getAttribute('height')) || placedIconSize;\n\n // Set currentShape so EventDispatcher routes subsequent events to icon handler\n const iconShape = (typeof shapes !== 'undefined' && Array.isArray(shapes))\n ? shapes.find(s => s.shapeName === 'icon' && s.element === selectedIcon)\n : null;\n if (iconShape) {\n currentShape = iconShape;\n currentShape.isSelected = true;\n if (window.__showSidebarForShape) window.__showSidebarForShape('icon');\n }\n}\n\nfunction addResizeAnchors(x, y, width, height, centerX, centerY, iconWidth, rotation) {\n const svg = getSVGElement();\n if (!svg) return;\n\n const zoom = window.currentZoom || 1;\n const anchorSize = Math.max(8, Math.min(16, iconWidth * 0.15)) / zoom;\n const anchorStrokeWidth = Math.max(1.5, anchorSize * 0.15);\n\n const positions = [\n { x: x, y: y, cursor: \"nw-resize\" },\n { x: x + width, y: y, cursor: \"ne-resize\" },\n { x: x, y: y + height, cursor: \"sw-resize\" },\n { x: x + width, y: y + height, cursor: \"se-resize\" }\n ];\n\n positions.forEach((pos) => {\n const anchor = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\n anchor.setAttribute(\"x\", pos.x - anchorSize / 2);\n anchor.setAttribute(\"y\", pos.y - anchorSize / 2);\n anchor.setAttribute(\"width\", anchorSize);\n anchor.setAttribute(\"height\", anchorSize);\n anchor.setAttribute(\"fill\", \"#121212\");\n anchor.setAttribute(\"stroke\", \"#5B57D1\");\n anchor.setAttribute(\"stroke-width\", anchorStrokeWidth);\n anchor.setAttribute(\"class\", \"resize-anchor\");\n anchor.setAttribute(\"transform\", `rotate(${rotation}, ${centerX}, ${centerY})`);\n anchor.style.cursor = pos.cursor;\n\n svg.appendChild(anchor);\n\n anchor.addEventListener('pointerdown', startResize);\n anchor.addEventListener('pointerup', stopResize);\n });\n}\n\nfunction addRotationAnchor(x, y, width, height, centerX, centerY, iconWidth, rotation) {\n const svg = getSVGElement();\n if (!svg) return;\n\n const anchorRadius = Math.max(6, Math.min(12, iconWidth * 0.12));\n const anchorStrokeWidth = Math.max(1.5, anchorRadius * 0.2);\n const rotationDistance = Math.max(25, iconWidth * 0.4);\n\n const rotationAnchorX = x + width / 2;\n const rotationAnchorY = y - rotationDistance;\n\n const rotationAnchor = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n rotationAnchor.setAttribute('cx', rotationAnchorX);\n rotationAnchor.setAttribute('cy', rotationAnchorY);\n rotationAnchor.setAttribute('r', anchorRadius);\n rotationAnchor.setAttribute('class', 'rotation-anchor');\n rotationAnchor.setAttribute('fill', '#121212');\n rotationAnchor.setAttribute('stroke', '#5B57D1');\n rotationAnchor.setAttribute('stroke-width', anchorStrokeWidth);\n rotationAnchor.setAttribute('style', 'pointer-events: all; cursor: grab;');\n rotationAnchor.setAttribute('transform', `rotate(${rotation}, ${centerX}, ${centerY})`);\n\n svg.appendChild(rotationAnchor);\n\n rotationAnchor.addEventListener('pointerdown', startRotation);\n rotationAnchor.addEventListener('pointerup', stopRotation);\n\n rotationAnchor.addEventListener('mouseover', function() {\n if (!isRotatingIcon && !isDragging) {\n rotationAnchor.style.cursor = 'grab';\n }\n });\n\n rotationAnchor.addEventListener('mouseout', function() {\n if (!isRotatingIcon && !isDragging) {\n rotationAnchor.style.cursor = 'default';\n }\n });\n}\n\nfunction removeRotationAnchor() {\n const svg = getSVGElement();\n if (!svg) return;\n\n svg.querySelectorAll(\".rotation-anchor\").forEach(el => el.remove());\n}\n\nfunction removeResizeAnchors() {\n const svg = getSVGElement();\n if (!svg) return;\n\n const anchors = svg.querySelectorAll(\".resize-anchor\");\n anchors.forEach(anchor => svg.removeChild(anchor));\n}\n\nfunction startResize(event) {\n event.preventDefault();\n event.stopPropagation();\n\n currentAnchor = event.target;\n\n originalX = parseFloat(selectedIcon.getAttribute('x')) || 0;\n originalY = parseFloat(selectedIcon.getAttribute('y')) || 0;\n originalWidth = parseFloat(selectedIcon.getAttribute('width')) || 100;\n originalHeight = parseFloat(selectedIcon.getAttribute('height')) || 100;\n\n const { x: mouseX, y: mouseY } = getSVGCoordsFromMouse(event);\n currentAnchor.startMouseX = mouseX;\n currentAnchor.startMouseY = mouseY;\n\n currentAnchor.iconRotation = iconRotation;\n\n const svg = getSVGElement();\n if (svg) {\n svg.addEventListener('pointermove', resizeIcon);\n }\n document.addEventListener('pointerup', stopResize);\n}\n\nfunction stopResize(event) {\n stopInteracting();\n document.removeEventListener('pointerup', stopResize);\n}\n\nfunction resizeIcon(event) {\n if (!selectedIcon || !currentAnchor) return;\n\n const { x: currentMouseX, y: currentMouseY } = getSVGCoordsFromMouse(event);\n\n const rotation = currentAnchor.iconRotation || 0;\n const rotationRad = (rotation * Math.PI) / 180;\n\n const rawDeltaX = currentMouseX - currentAnchor.startMouseX;\n const rawDeltaY = currentMouseY - currentAnchor.startMouseY;\n\n // Rotate delta to local (unrotated) space\n const deltaX = rawDeltaX * Math.cos(-rotationRad) - rawDeltaY * Math.sin(-rotationRad);\n const deltaY = rawDeltaX * Math.sin(-rotationRad) + rawDeltaY * Math.cos(-rotationRad);\n\n let newWidth = originalWidth;\n let newHeight = originalHeight;\n let newX = originalX;\n let newY = originalY;\n\n // Track which corner is fixed (relative to original rect)\n let fixedRelX, fixedRelY;\n\n switch (currentAnchor.style.cursor) {\n case \"nw-resize\":\n newWidth = Math.max(minIconSize, originalWidth - deltaX);\n newHeight = Math.max(minIconSize, originalHeight - deltaY);\n if (aspect_ratio_lock) {\n const scale = Math.min(newWidth / originalWidth, newHeight / originalHeight);\n newWidth = originalWidth * scale;\n newHeight = originalHeight * scale;\n }\n newX = originalX + (originalWidth - newWidth);\n newY = originalY + (originalHeight - newHeight);\n fixedRelX = originalWidth; fixedRelY = originalHeight;\n break;\n case \"ne-resize\":\n newWidth = Math.max(minIconSize, originalWidth + deltaX);\n newHeight = Math.max(minIconSize, originalHeight - deltaY);\n if (aspect_ratio_lock) {\n const scale = Math.max(newWidth / originalWidth, newHeight / originalHeight);\n newWidth = originalWidth * scale;\n newHeight = originalHeight * scale;\n }\n newX = originalX;\n newY = originalY + (originalHeight - newHeight);\n fixedRelX = 0; fixedRelY = originalHeight;\n break;\n case \"sw-resize\":\n newWidth = Math.max(minIconSize, originalWidth - deltaX);\n newHeight = Math.max(minIconSize, originalHeight + deltaY);\n if (aspect_ratio_lock) {\n const scale = Math.max(newWidth / originalWidth, newHeight / originalHeight);\n newWidth = originalWidth * scale;\n newHeight = originalHeight * scale;\n }\n newX = originalX + (originalWidth - newWidth);\n newY = originalY;\n fixedRelX = originalWidth; fixedRelY = 0;\n break;\n case \"se-resize\":\n newWidth = Math.max(minIconSize, originalWidth + deltaX);\n newHeight = Math.max(minIconSize, originalHeight + deltaY);\n if (aspect_ratio_lock) {\n const scale = Math.max(newWidth / originalWidth, newHeight / originalHeight);\n newWidth = originalWidth * scale;\n newHeight = originalHeight * scale;\n }\n newX = originalX;\n newY = originalY;\n fixedRelX = 0; fixedRelY = 0;\n break;\n }\n\n // Compensate for rotation center shift when rotated\n if (rotation !== 0) {\n const cosR = Math.cos(rotationRad);\n const sinR = Math.sin(rotationRad);\n\n // Compute rotated world position of the fixed corner in the original rect\n const oldCX = originalX + originalWidth / 2;\n const oldCY = originalY + originalHeight / 2;\n const odx = (originalX + fixedRelX) - oldCX;\n const ody = (originalY + fixedRelY) - oldCY;\n const fixedWorldX = oldCX + odx * cosR - ody * sinR;\n const fixedWorldY = oldCY + odx * sinR + ody * cosR;\n\n // Determine where the fixed corner sits in the new rect\n const fixedNewRelX = fixedRelX === 0 ? 0 : newWidth;\n const fixedNewRelY = fixedRelY === 0 ? 0 : newHeight;\n\n // Solve for new origin so the fixed corner stays in place\n const ncx = newWidth / 2;\n const ncy = newHeight / 2;\n const ndx = fixedNewRelX - ncx;\n const ndy = fixedNewRelY - ncy;\n const rotX = ncx + ndx * cosR - ndy * sinR;\n const rotY = ncy + ndx * sinR + ndy * cosR;\n\n newX = fixedWorldX - rotX;\n newY = fixedWorldY - rotY;\n }\n\n selectedIcon.setAttribute('width', newWidth);\n selectedIcon.setAttribute('height', newHeight);\n selectedIcon.setAttribute('x', newX);\n selectedIcon.setAttribute('y', newY);\n\n selectedIcon.setAttribute('data-shape-x', newX);\n selectedIcon.setAttribute('data-shape-y', newY);\n selectedIcon.setAttribute('data-shape-width', newWidth);\n selectedIcon.setAttribute('data-shape-height', newHeight);\n\n const vbWidth = parseFloat(selectedIcon.getAttribute('data-viewbox-width')) || 24;\n const vbHeight = parseFloat(selectedIcon.getAttribute('data-viewbox-height')) || 24;\n const iconScale = newWidth / Math.max(vbWidth, vbHeight);\n const localCenterX = newWidth / 2 / iconScale;\n const localCenterY = newHeight / 2 / iconScale;\n selectedIcon.setAttribute('transform', `translate(${newX}, ${newY}) scale(${iconScale}) rotate(${iconRotation}, ${localCenterX}, ${localCenterY})`);\n\n updateArrowsForShape(selectedIcon);\n\n addSelectionOutline();\n}\n\nfunction dragIcon(event) {\n if (!isDragging || !selectedIcon) return;\n\n const { x, y } = getSVGCoordsFromMouse(event);\n let newX = x - dragOffsetX;\n let newY = y - dragOffsetY;\n\n selectedIcon.setAttribute('x', newX);\n selectedIcon.setAttribute('y', newY);\n\n selectedIcon.setAttribute('data-shape-x', newX);\n selectedIcon.setAttribute('data-shape-y', newY);\n\n const width = parseFloat(selectedIcon.getAttribute('width')) || 100;\n const height = parseFloat(selectedIcon.getAttribute('height')) || 100;\n const vbWidth = parseFloat(selectedIcon.getAttribute('data-viewbox-width')) || 24;\n const vbHeight = parseFloat(selectedIcon.getAttribute('data-viewbox-height')) || 24;\n const scale = width / Math.max(vbWidth, vbHeight);\n const localCenterX = width / 2 / scale;\n const localCenterY = height / 2 / scale;\n \n selectedIcon.setAttribute('transform', `translate(${newX}, ${newY}) scale(${scale}) rotate(${iconRotation}, ${localCenterX}, ${localCenterY})`);\n\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n const iconShape = shapes.find(shape => shape.shapeName === 'icon' && shape.element === selectedIcon);\n if (iconShape) {\n iconShape.x = newX;\n iconShape.y = newY;\n iconShape.updateFrameContainment();\n }\n }\n\n updateArrowsForShape(selectedIcon);\n\n removeSelection();\n addSelectionOutline();\n}\n\nfunction stopDrag(event) {\n if (!isDragging) return;\n \n console.log(\"stop dragging icon\");\n isDragging = false;\n if (window.__iconShapeState) window.__iconShapeState.isDragging = false;\n\n document.removeEventListener('pointermove', dragIcon);\n document.removeEventListener('pointerup', stopDrag);\n window.removeEventListener('pointerup', stopDrag);\n \n const svg = getSVGElement();\n if (svg) {\n svg.removeEventListener('pointerup', stopDrag);\n }\n \n document.removeEventListener('dragstart', preventDefaultDrag);\n document.removeEventListener('selectstart', preventDefaultDrag);\n \n stopInteracting();\n}\n\nfunction startRotation(event) {\n event.preventDefault();\n event.stopPropagation();\n\n if (!selectedIcon) return;\n\n isRotatingIcon = true;\n console.log(selectedIcon)\n const iconX = parseFloat(selectedIcon.getAttribute('x'));\n const iconY = parseFloat(selectedIcon.getAttribute('y'));\n const iconWidth = parseFloat(selectedIcon.getAttribute('width'));\n const iconHeight = parseFloat(selectedIcon.getAttribute('height'));\n\n const centerX = iconX + iconWidth / 2;\n const centerY = iconY + iconHeight / 2;\n\n const { x: mouseX, y: mouseY } = getSVGCoordsFromMouse(event);\n\n startRotationMouseAngle = Math.atan2(mouseY - centerY, mouseX - centerX) * 180 / Math.PI;\n console.log('Start rotation mouse angle:', startRotationMouseAngle);\n startIconRotation = iconRotation;\n\n const svg = getSVGElement();\n if (svg) {\n svg.addEventListener('pointermove', rotateIcon);\n svg.style.cursor = 'grabbing';\n }\n document.addEventListener('pointerup', stopRotation);\n}\n\nfunction rotateIcon(event) {\n if (!isRotatingIcon || !selectedIcon) return;\n\n const iconX = parseFloat(selectedIcon.getAttribute('x')) || 0;\n const iconY = parseFloat(selectedIcon.getAttribute('y')) || 0;\n const iconWidth = parseFloat(selectedIcon.getAttribute('width')) || 100;\n const iconHeight = parseFloat(selectedIcon.getAttribute('height')) || 100;\n\n const centerX = iconX + iconWidth / 2;\n const centerY = iconY + iconHeight / 2;\n\n const { x: mouseX, y: mouseY } = getSVGCoordsFromMouse(event);\n\n const currentMouseAngle = Math.atan2(mouseY - centerY, mouseX - centerX) * 180 / Math.PI;\n const angleDiff = currentMouseAngle - startRotationMouseAngle;\n\n iconRotation = startIconRotation + angleDiff;\n iconRotation = iconRotation % 360;\n if (iconRotation < 0) iconRotation += 360;\n\n const vbWidth = parseFloat(selectedIcon.getAttribute('data-viewbox-width')) || 24;\n const vbHeight = parseFloat(selectedIcon.getAttribute('data-viewbox-height')) || 24;\n const scale = iconWidth / Math.max(vbWidth, vbHeight);\n const localCenterX = iconWidth / 2 / scale;\n const localCenterY = iconHeight / 2 / scale;\n\n selectedIcon.setAttribute('transform', `translate(${iconX}, ${iconY}) scale(${scale}) rotate(${iconRotation}, ${localCenterX}, ${localCenterY})`);\n\n selectedIcon.setAttribute('data-shape-rotation', iconRotation);\n\n updateArrowsForShape(selectedIcon);\n\n removeSelection();\n addSelectionOutline();\n}\n\nfunction stopRotation(event) {\n if (!isRotatingIcon) return;\n stopInteracting();\n isRotatingIcon = false;\n startRotationMouseAngle = null;\n startIconRotation = null;\n\n const svg = getSVGElement();\n if (svg) {\n svg.removeEventListener('pointermove', rotateIcon);\n svg.style.cursor = 'default';\n }\n document.removeEventListener('pointerup', stopRotation);\n}\n\nfunction stopInteracting() {\n if (selectedIcon && (isDragging || isRotatingIcon || currentAnchor)) {\n const newPos = {\n x: parseFloat(selectedIcon.getAttribute('x')) || 0,\n y: parseFloat(selectedIcon.getAttribute('y')) || 0,\n width: parseFloat(selectedIcon.getAttribute('width')) || 100,\n height: parseFloat(selectedIcon.getAttribute('height')) || 100,\n rotation: iconRotation\n };\n\n let originalRotation = iconRotation;\n if (isRotatingIcon && startIconRotation !== null) {\n originalRotation = startIconRotation;\n }\n\n const oldPos = {\n x: originalX,\n y: originalY,\n width: originalWidth,\n height: originalHeight,\n rotation: originalRotation\n };\n\n let iconShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n iconShape = shapes.find(shape => shape.shapeName === 'icon' && shape.element === selectedIcon);\n if (iconShape) {\n iconShape.x = newPos.x;\n iconShape.y = newPos.y;\n iconShape.width = newPos.width;\n iconShape.height = newPos.height;\n iconShape.rotation = newPos.rotation;\n }\n }\n\n const oldPosWithFrame = {\n ...oldPos,\n parentFrame: draggedShapeInitialFrameIcon\n };\n // Issue #34 bug #2: for drag, hoveredFrameIcon tracks the actual\n // destination \u2014 currentShape.parentFrame is still the OLD frame.\n // Resize / rotate don't track hover, so fall back to whatever the\n // shape itself reports (parent doesn't change for those gestures).\n const newPosWithFrame = {\n ...newPos,\n parentFrame: isDragging\n ? (hoveredFrameIcon || null)\n : (iconShape ? iconShape.parentFrame : null),\n };\n\n const stateChanged = newPos.x !== oldPos.x || newPos.y !== oldPos.y ||\n newPos.width !== oldPos.width || newPos.height !== oldPos.height ||\n newPos.rotation !== oldPos.rotation;\n const frameChanged = oldPosWithFrame.parentFrame !== newPosWithFrame.parentFrame;\n\n if ((stateChanged || frameChanged) && iconShape) {\n pushTransformAction(iconShape, oldPosWithFrame, newPosWithFrame);\n }\n\n if (isDragging && iconShape) {\n const finalFrame = hoveredFrameIcon;\n\n if (draggedShapeInitialFrameIcon !== finalFrame) {\n if (draggedShapeInitialFrameIcon) {\n draggedShapeInitialFrameIcon.removeShapeFromFrame(iconShape);\n }\n\n if (finalFrame) {\n finalFrame.addShapeToFrame(iconShape);\n }\n\n if (frameChanged) {\n pushFrameAttachmentAction(finalFrame || draggedShapeInitialFrameIcon, iconShape,\n finalFrame ? 'attach' : 'detach', draggedShapeInitialFrameIcon);\n }\n } else if (draggedShapeInitialFrameIcon) {\n draggedShapeInitialFrameIcon.restoreToFrame(iconShape);\n }\n }\n\n draggedShapeInitialFrameIcon = null;\n }\n\n if (hoveredFrameIcon) {\n hoveredFrameIcon.removeHighlight();\n hoveredFrameIcon = null;\n if (window.__iconShapeState) window.__iconShapeState.hoveredFrameIcon = null;\n }\n\n isDragging = false;\n if (window.__iconShapeState) window.__iconShapeState.isDragging = false;\n isRotatingIcon = false;\n\n const svg = getSVGElement();\n if (svg) {\n svg.removeEventListener('pointermove', dragIcon);\n svg.removeEventListener('pointermove', resizeIcon);\n svg.removeEventListener('pointermove', rotateIcon);\n }\n \n document.removeEventListener('pointermove', dragIcon);\n document.removeEventListener('pointermove', resizeIcon);\n document.removeEventListener('pointermove', rotateIcon);\n \n currentAnchor = null;\n startRotationMouseAngle = null;\n startIconRotation = null;\n\n if (selectedIcon) {\n originalX = parseFloat(selectedIcon.getAttribute('x')) || 0;\n originalY = parseFloat(selectedIcon.getAttribute('y')) || 0;\n originalWidth = parseFloat(selectedIcon.getAttribute('width')) || 100;\n originalHeight = parseFloat(selectedIcon.getAttribute('height')) || 100;\n\n selectedIcon.setAttribute('data-shape-x', originalX);\n selectedIcon.setAttribute('data-shape-y', originalY);\n selectedIcon.setAttribute('data-shape-width', originalWidth);\n selectedIcon.setAttribute('data-shape-height', originalHeight);\n selectedIcon.setAttribute('data-shape-rotation', iconRotation);\n\n updateArrowsForShape(selectedIcon);\n }\n}\n\nfunction deleteCurrentIcon() {\n if (selectedIcon) {\n let iconShape = null;\n if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {\n iconShape = shapes.find(shape => shape.shapeName === 'icon' && shape.element === selectedIcon);\n if (iconShape) {\n const idx = shapes.indexOf(iconShape);\n if (idx !== -1) shapes.splice(idx, 1);\n\n if (iconShape.group && iconShape.group.parentNode) {\n iconShape.group.parentNode.removeChild(iconShape.group);\n }\n }\n }\n\n if (!iconShape && selectedIcon.parentNode) {\n selectedIcon.parentNode.removeChild(selectedIcon);\n }\n\n if (typeof cleanupAttachments === 'function') {\n cleanupAttachments(selectedIcon);\n }\n\n if (iconShape) {\n pushDeleteAction(iconShape);\n }\n\n removeSelection();\n selectedIcon = null;\n }\n}\n\ndocument.addEventListener('keydown', (e) => {\n if (e.key === 'Delete' && selectedIcon) {\n deleteCurrentIcon();\n }\n});\n\nasync function fetchIconsFromServer() {\n try {\n const apiUrl = \"/api/icons/feed?offset=0&limit=20\";\n \n const response = await fetch(apiUrl);\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n const data = await response.json();\n return data.results;\n } catch (error) {\n console.error('Failed to fetch icons from server:', error);\n return null;\n }\n}\n\nasync function renderIconsFromServer() {\n const icons = await fetchIconsFromServer();\n if (icons) {\n document.getElementById(\"iconsContainer\").innerHTML = '';\n\n for (const icon of icons) {\n try {\n const response = await fetch(`/api/icons/serve?name=${encodeURIComponent(icon.filename)}`);\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n const svgContent = await response.text();\n\n const normalizedSVG = normalizeSVGSize(svgContent);\n\n // Use normalizedSVG for display, not original svgContent\n let svgIcon = `<div class=\"icons\" data-url=\"${icon.filename}\" data-svg=\"${encodeURIComponent(normalizedSVG)}\">\n ${normalizedSVG}\n </div>`;\n document.getElementById(\"iconsContainer\").innerHTML += svgIcon;\n } catch (error) {\n console.error('Failed to render icon:', icon.filename, error);\n }\n }\n\n addIconClickListeners();\n }\n}\n\nasync function searchAndRenderIcons(query) {\n try {\n const apiUrl = `/api/icons/search?q=${encodeURIComponent(query)}`;\n \n const response = await fetch(apiUrl);\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n const searchResults = await response.json();\n\n document.getElementById(\"iconsContainer\").innerHTML = '';\n\n for (const icon of searchResults) {\n try {\n const svgResponse = await fetch(`/api/icons/serve?name=${encodeURIComponent(icon.filename)}`);\n if (!svgResponse.ok) {\n throw new Error(`HTTP error! status: ${svgResponse.status}`);\n }\n const svgContent = await svgResponse.text();\n\n const normalizedSVG = normalizeSVGSize(svgContent);\n\n // Use normalizedSVG for display, not original svgContent\n let svgIcon = `<div class=\"icons\" data-url=\"${icon.filename}\">\n ${normalizedSVG}\n </div>`;\n document.getElementById(\"iconsContainer\").innerHTML += svgIcon;\n } catch (error) {\n console.error('Failed to render search result:', icon.filename, error);\n }\n }\n\n addIconClickListeners();\n\n } catch (error) {\n console.error('Failed to search icons:', error);\n }\n}\n\nfunction normalizeSVGSize(svgContent, fillColor = '#fff', strokeColor = null) {\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = svgContent;\n const svgElement = tempDiv.querySelector('svg');\n \n if (svgElement) {\n const originalViewBox = svgElement.getAttribute('viewBox');\n \n svgElement.setAttribute('width', '35');\n svgElement.setAttribute('height', '35');\n \n if (!originalViewBox) {\n const width = svgElement.getAttribute('width') || '24';\n const height = svgElement.getAttribute('height') || '24';\n const numWidth = parseFloat(width);\n const numHeight = parseFloat(height);\n \n if (!isNaN(numWidth) && !isNaN(numHeight)) {\n svgElement.setAttribute('viewBox', `0 0 ${numWidth} ${numHeight}`);\n }\n }\n \n // Apply custom styling with more selective logic\n const applyCustomStyling = (element) => {\n if (element.nodeType === 1) {\n const tagName = element.tagName.toLowerCase();\n \n // Only apply to shape elements, not container elements like 'g'\n if (['path', 'circle', 'rect', 'polygon', 'ellipse', 'polyline', 'line'].includes(tagName)) {\n const currentFill = element.getAttribute('fill');\n const currentStroke = element.getAttribute('stroke');\n \n // Check if parent <g> has explicit colors - if so, don't override\n let parentG = element.parentElement;\n let hasParentColor = false;\n \n while (parentG && parentG.tagName.toLowerCase() === 'g') {\n if (parentG.getAttribute('fill') || parentG.getAttribute('stroke')) {\n hasParentColor = true;\n break;\n }\n parentG = parentG.parentElement;\n }\n \n // Only apply white fill if:\n // 1. Element doesn't have explicit 'none' fill\n // 2. Element doesn't already have a specific color (other than black/default)\n // 3. Parent <g> doesn't have explicit colors\n if (!hasParentColor && currentFill !== 'none') {\n // Only override if it's black, default, or unset\n if (!currentFill || currentFill === '#000' || currentFill === '#000000' || currentFill === 'black' || currentFill === 'currentColor') {\n element.setAttribute('fill', fillColor);\n }\n }\n \n // Handle stroke similarly\n if (strokeColor && !hasParentColor) {\n if (currentStroke && currentStroke !== 'none') {\n if (!currentStroke || currentStroke === '#000' || currentStroke === '#000000' || currentStroke === 'black' || currentStroke === 'currentColor') {\n element.setAttribute('stroke', strokeColor);\n }\n }\n }\n }\n \n // Recursively process children\n for (let i = 0; i < element.children.length; i++) {\n applyCustomStyling(element.children[i]);\n }\n }\n };\n \n applyCustomStyling(svgElement);\n \n return svgElement.outerHTML;\n }\n\n return svgContent;\n}\n\nfunction addIconClickListeners() {\n const iconElements = document.querySelectorAll('#iconsContainer .icons');\n iconElements.forEach(iconElement => {\n iconElement.addEventListener('click', (e) => {\n const filename = iconElement.getAttribute('data-url') || 'unknown';\n handleIconClick(e, filename);\n });\n });\n}\n\n// Legacy category/search listeners disabled \u2014 React IconSidebar handles all icon UI\n\nfunction handleIconClick(event, filename) {\n event.stopPropagation();\n\n const iconElement = event.currentTarget;\n const svgElement = iconElement.querySelector('svg');\n\n if (svgElement) {\n iconToPlace = svgElement.outerHTML;\n isDraggingIcon = true;\n isIconToolActive = true;\n\n console.log('Icon selected and ready to place:', filename);\n\n const iconContainer = document.getElementById('iconsToolBar');\n if (iconContainer) {\n iconContainer.classList.add('hidden');\n }\n\n document.body.style.cursor = 'crosshair';\n }\n}\n\n\n\n// Clean up any lingering miniature icon or drag state (called on tool switch)\nfunction cleanupIconTool() {\n if (currentIconElement) {\n const svg = getSVGElement();\n if (svg && currentIconElement.parentNode === svg) {\n svg.removeChild(currentIconElement);\n }\n currentIconElement = null;\n }\n isDraggingIcon = false;\n iconToPlace = null;\n document.body.style.cursor = 'default';\n}\nwindow.__cleanupIconTool = cleanupIconTool;\n\n// Bridge for React sidebar to trigger icon placement\nwindow.prepareIconPlacement = function(svgContent) {\n iconToPlace = svgContent;\n isDraggingIcon = true;\n window.isIconToolActive = true;\n document.body.style.cursor = 'crosshair';\n};\n\n// Bridge for IconShape to call selectIcon and removeSelection\nwindow.__iconToolSelectIcon = selectIcon;\nwindow.__iconToolRemoveSelection = removeSelection;\n\n// Legacy icon rendering disabled \u2014 React IconSidebar handles icon UI\n\nexport { handleMouseDownIcon, handleMouseMoveIcon, handleMouseUpIcon, startDrag, stopDrag}"],
5
+ "mappings": "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",
6
+ "names": ["svg", "iconX", "iconY"]
7
+ }
@@ -0,0 +1,158 @@
1
+ "use client";
2
+
3
+ // src/core/MermaidSequenceParser.js
4
+ var ARROW_TYPES = {
5
+ "->>": { solid: true, arrowHead: "open", cross: false },
6
+ "-->>": { solid: false, arrowHead: "open", cross: false },
7
+ "->>x": { solid: true, arrowHead: "open", cross: true },
8
+ "-->>x": { solid: false, arrowHead: "open", cross: true },
9
+ "->": { solid: true, arrowHead: "filled", cross: false },
10
+ "-->": { solid: false, arrowHead: "filled", cross: false },
11
+ "-x": { solid: true, arrowHead: "cross", cross: true },
12
+ "--x": { solid: false, arrowHead: "cross", cross: true }
13
+ };
14
+ var ARROW_PATTERNS = Object.keys(ARROW_TYPES).sort((a, b) => b.length - a.length);
15
+ function parseSequenceDiagram(src) {
16
+ const lines = src.trim().split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("%%"));
17
+ if (lines.length === 0) return null;
18
+ if (lines[0].toLowerCase() !== "sequencediagram") return null;
19
+ const participants = [];
20
+ const participantSet = /* @__PURE__ */ new Set();
21
+ const messages = [];
22
+ const notes = [];
23
+ const blocks = [];
24
+ const blockStack = [];
25
+ let title = "";
26
+ let autoNumber = false;
27
+ let msgIndex = 0;
28
+ function ensureParticipant(name) {
29
+ if (!name) return;
30
+ const trimmed = name.trim();
31
+ if (!trimmed) return;
32
+ if (!participantSet.has(trimmed)) {
33
+ participantSet.add(trimmed);
34
+ participants.push({ name: trimmed, type: "participant" });
35
+ }
36
+ }
37
+ for (let i = 1; i < lines.length; i++) {
38
+ const line = lines[i];
39
+ if (line.match(/^title\s*:/i)) {
40
+ title = line.replace(/^title\s*:\s*/i, "").trim();
41
+ continue;
42
+ }
43
+ if (line.toLowerCase() === "autonumber") {
44
+ autoNumber = true;
45
+ continue;
46
+ }
47
+ const partMatch = line.match(/^(participant|actor)\s+(.+?)(?:\s+as\s+(.+))?$/i);
48
+ if (partMatch) {
49
+ const type = partMatch[1].toLowerCase();
50
+ const rawName = partMatch[3] || partMatch[2];
51
+ const name = rawName.trim();
52
+ if (!participantSet.has(name)) {
53
+ participantSet.add(name);
54
+ participants.push({ name, type });
55
+ }
56
+ continue;
57
+ }
58
+ const noteMatch = line.match(/^Note\s+(left of|right of|over)\s+([^:]+?):\s*(.+)$/i);
59
+ if (noteMatch) {
60
+ const position = noteMatch[1].toLowerCase();
61
+ const targets = noteMatch[2].split(",").map((s) => s.trim());
62
+ const text = noteMatch[3].trim();
63
+ targets.forEach((t) => ensureParticipant(t));
64
+ notes.push({
65
+ position,
66
+ targets,
67
+ text,
68
+ atMessage: messages.length
69
+ // placed after this many messages
70
+ });
71
+ continue;
72
+ }
73
+ const blockStartMatch = line.match(/^(alt|else|opt|loop|par|critical|break)\s*(.*)?$/i);
74
+ if (blockStartMatch) {
75
+ const blockType = blockStartMatch[1].toLowerCase();
76
+ const label = (blockStartMatch[2] || "").trim();
77
+ if (blockType === "else") {
78
+ if (blockStack.length > 0) {
79
+ const current = blockStack[blockStack.length - 1];
80
+ current.sections.push({ label, startMsg: messages.length });
81
+ }
82
+ } else {
83
+ const block = {
84
+ type: blockType,
85
+ label,
86
+ startMsg: messages.length,
87
+ sections: [{ label, startMsg: messages.length }],
88
+ endMsg: messages.length
89
+ };
90
+ blockStack.push(block);
91
+ }
92
+ continue;
93
+ }
94
+ if (line.toLowerCase() === "end") {
95
+ if (blockStack.length > 0) {
96
+ const block = blockStack.pop();
97
+ block.endMsg = messages.length;
98
+ blocks.push(block);
99
+ }
100
+ continue;
101
+ }
102
+ const actMatch = line.match(/^(activate|deactivate)\s+(.+)$/i);
103
+ if (actMatch) {
104
+ ensureParticipant(actMatch[2].trim());
105
+ continue;
106
+ }
107
+ let foundArrow = null;
108
+ let arrowPos = -1;
109
+ for (const pattern of ARROW_PATTERNS) {
110
+ const idx = line.indexOf(pattern);
111
+ if (idx > 0) {
112
+ foundArrow = pattern;
113
+ arrowPos = idx;
114
+ break;
115
+ }
116
+ }
117
+ if (foundArrow && arrowPos > 0) {
118
+ const from = line.substring(0, arrowPos).trim();
119
+ const rest = line.substring(arrowPos + foundArrow.length);
120
+ const colonIdx = rest.indexOf(":");
121
+ let to, text;
122
+ if (colonIdx >= 0) {
123
+ to = rest.substring(0, colonIdx).trim();
124
+ text = rest.substring(colonIdx + 1).trim();
125
+ } else {
126
+ to = rest.trim();
127
+ text = "";
128
+ }
129
+ ensureParticipant(from);
130
+ ensureParticipant(to);
131
+ const arrowType = ARROW_TYPES[foundArrow];
132
+ msgIndex++;
133
+ messages.push({
134
+ from,
135
+ to,
136
+ text,
137
+ number: autoNumber ? msgIndex : null,
138
+ ...arrowType
139
+ });
140
+ continue;
141
+ }
142
+ }
143
+ if (participants.length === 0) return null;
144
+ return {
145
+ type: "sequenceDiagram",
146
+ title,
147
+ participants,
148
+ messages,
149
+ notes,
150
+ blocks,
151
+ autoNumber
152
+ };
153
+ }
154
+
155
+ export {
156
+ parseSequenceDiagram
157
+ };
158
+ //# sourceMappingURL=chunk-VQVEPJSA.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/core/MermaidSequenceParser.js"],
4
+ "sourcesContent": ["/* eslint-disable */\n/**\n * MermaidSequenceParser - Parses Mermaid sequenceDiagram syntax.\n *\n * Supports:\n * - participant/actor declarations\n * - Message types: ->>, -->>,->>x, -->>x, ->, -->, -x, --x\n * - Notes: Note left of, Note right of, Note over\n * - Activations: activate/deactivate\n * - Alt/else/opt/loop/par/critical/break blocks\n * - Auto-numbering (autonumber)\n * - Title\n */\n\n// Message arrow types\nconst ARROW_TYPES = {\n '->>': { solid: true, arrowHead: 'open', cross: false },\n '-->>': { solid: false, arrowHead: 'open', cross: false },\n '->>x': { solid: true, arrowHead: 'open', cross: true },\n '-->>x':{ solid: false, arrowHead: 'open', cross: true },\n '->': { solid: true, arrowHead: 'filled', cross: false },\n '-->': { solid: false, arrowHead: 'filled', cross: false },\n '-x': { solid: true, arrowHead: 'cross', cross: true },\n '--x': { solid: false, arrowHead: 'cross', cross: true },\n};\n\n// Sorted by length descending so longest match wins\nconst ARROW_PATTERNS = Object.keys(ARROW_TYPES).sort((a, b) => b.length - a.length);\n\nexport function parseSequenceDiagram(src) {\n const lines = src.trim().split('\\n').map(l => l.trim()).filter(l => l && !l.startsWith('%%'));\n if (lines.length === 0) return null;\n\n // Check header\n if (lines[0].toLowerCase() !== 'sequencediagram') return null;\n\n const participants = [];\n const participantSet = new Set();\n const messages = [];\n const notes = [];\n const blocks = []; // alt/loop/opt etc\n const blockStack = []; // nesting stack\n let title = '';\n let autoNumber = false;\n let msgIndex = 0;\n\n function ensureParticipant(name) {\n if (!name) return;\n const trimmed = name.trim();\n if (!trimmed) return;\n if (!participantSet.has(trimmed)) {\n participantSet.add(trimmed);\n participants.push({ name: trimmed, type: 'participant' });\n }\n }\n\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n\n // Title\n if (line.match(/^title\\s*:/i)) {\n title = line.replace(/^title\\s*:\\s*/i, '').trim();\n continue;\n }\n\n // Autonumber\n if (line.toLowerCase() === 'autonumber') {\n autoNumber = true;\n continue;\n }\n\n // Participant / Actor declaration\n const partMatch = line.match(/^(participant|actor)\\s+(.+?)(?:\\s+as\\s+(.+))?$/i);\n if (partMatch) {\n const type = partMatch[1].toLowerCase();\n const rawName = partMatch[3] || partMatch[2];\n const name = rawName.trim();\n if (!participantSet.has(name)) {\n participantSet.add(name);\n participants.push({ name, type });\n }\n continue;\n }\n\n // Note\n const noteMatch = line.match(/^Note\\s+(left of|right of|over)\\s+([^:]+?):\\s*(.+)$/i);\n if (noteMatch) {\n const position = noteMatch[1].toLowerCase();\n const targets = noteMatch[2].split(',').map(s => s.trim());\n const text = noteMatch[3].trim();\n targets.forEach(t => ensureParticipant(t));\n notes.push({\n position,\n targets,\n text,\n atMessage: messages.length, // placed after this many messages\n });\n continue;\n }\n\n // Block start: alt, else, opt, loop, par, critical, break\n const blockStartMatch = line.match(/^(alt|else|opt|loop|par|critical|break)\\s*(.*)?$/i);\n if (blockStartMatch) {\n const blockType = blockStartMatch[1].toLowerCase();\n const label = (blockStartMatch[2] || '').trim();\n\n if (blockType === 'else') {\n // 'else' adds a section to current alt block\n if (blockStack.length > 0) {\n const current = blockStack[blockStack.length - 1];\n current.sections.push({ label, startMsg: messages.length });\n }\n } else {\n const block = {\n type: blockType,\n label,\n startMsg: messages.length,\n sections: [{ label, startMsg: messages.length }],\n endMsg: messages.length,\n };\n blockStack.push(block);\n }\n continue;\n }\n\n // Block end\n if (line.toLowerCase() === 'end') {\n if (blockStack.length > 0) {\n const block = blockStack.pop();\n block.endMsg = messages.length;\n blocks.push(block);\n }\n continue;\n }\n\n // Activate / Deactivate\n const actMatch = line.match(/^(activate|deactivate)\\s+(.+)$/i);\n if (actMatch) {\n ensureParticipant(actMatch[2].trim());\n continue;\n }\n\n // Message: From ARROW To: Text\n let foundArrow = null;\n let arrowPos = -1;\n for (const pattern of ARROW_PATTERNS) {\n const idx = line.indexOf(pattern);\n if (idx > 0) {\n // Make sure it's not part of a longer pattern\n foundArrow = pattern;\n arrowPos = idx;\n break;\n }\n }\n\n if (foundArrow && arrowPos > 0) {\n const from = line.substring(0, arrowPos).trim();\n const rest = line.substring(arrowPos + foundArrow.length);\n const colonIdx = rest.indexOf(':');\n let to, text;\n if (colonIdx >= 0) {\n to = rest.substring(0, colonIdx).trim();\n text = rest.substring(colonIdx + 1).trim();\n } else {\n to = rest.trim();\n text = '';\n }\n\n ensureParticipant(from);\n ensureParticipant(to);\n\n const arrowType = ARROW_TYPES[foundArrow];\n msgIndex++;\n\n messages.push({\n from,\n to,\n text,\n number: autoNumber ? msgIndex : null,\n ...arrowType,\n });\n continue;\n }\n }\n\n if (participants.length === 0) return null;\n\n return {\n type: 'sequenceDiagram',\n title,\n participants,\n messages,\n notes,\n blocks,\n autoNumber,\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }