@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,662 @@
1
+ "use client";
2
+
3
+ // src/shapes/Circle.js
4
+ var rc = rough.svg(svg);
5
+ var isDraggingShapeCircle = false;
6
+ var isResizingShapeCircle = false;
7
+ var isRotatingShapeCircle = false;
8
+ var hoveredFrameCircle = null;
9
+ var colorOptionsCircle = document.querySelectorAll(".circleStrokeSpan");
10
+ var backgroundColorOptionsCircle = document.querySelectorAll(".circleBackgroundSpan");
11
+ var fillStyleOptionsCircle = document.querySelectorAll(".circleFillStyleSpan");
12
+ var strokeThicknessValueCircle = document.querySelectorAll(".circleStrokeThickSpan");
13
+ var outlineStyleValueCircle = document.querySelectorAll(".circleOutlineStyle");
14
+ var Circle = class {
15
+ constructor(x, y, rx, ry, options = {}) {
16
+ this.x = x;
17
+ this.y = y;
18
+ this.rx = rx;
19
+ this.ry = ry;
20
+ this.options = {
21
+ roughness: 1.5,
22
+ stroke: "#fff",
23
+ strokeWidth: 2,
24
+ fill: "transparent",
25
+ fillStyle: "none",
26
+ strokeDasharray: "",
27
+ ...options
28
+ };
29
+ this.element = null;
30
+ this.isSelected = false;
31
+ this.rotation = 0;
32
+ this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
33
+ this.anchors = [];
34
+ this.rotationAnchor = null;
35
+ this.selectionPadding = 8;
36
+ this.selectionOutline = null;
37
+ this.shapeName = "circle";
38
+ this.shapeID = `circle-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 1e4)}`;
39
+ this.group.setAttribute("id", this.shapeID);
40
+ this.parentFrame = null;
41
+ this.label = options.label || "";
42
+ this.labelElement = null;
43
+ this.labelColor = options.labelColor || "#e0e0e0";
44
+ this.labelFontSize = options.labelFontSize || 14;
45
+ this._isEditingLabel = false;
46
+ this._hitArea = null;
47
+ this._labelBg = null;
48
+ this.shadeColor = options.shadeColor || null;
49
+ this.shadeOpacity = options.shadeOpacity !== void 0 ? options.shadeOpacity : 0.15;
50
+ this.shadeDirection = options.shadeDirection || "bottom";
51
+ this._shadeEllipse = null;
52
+ this._shadeGradient = null;
53
+ if (!this.group.parentNode) {
54
+ svg.appendChild(this.group);
55
+ }
56
+ this._lastDrawn = {
57
+ width: null,
58
+ height: null,
59
+ options: null
60
+ };
61
+ this._setupLabelDblClick();
62
+ this.draw();
63
+ }
64
+ // Add width and height properties for frame compatibility
65
+ get width() {
66
+ return this.rx * 2;
67
+ }
68
+ set width(value) {
69
+ this.rx = value / 2;
70
+ }
71
+ get height() {
72
+ return this.ry * 2;
73
+ }
74
+ set height(value) {
75
+ this.ry = value / 2;
76
+ }
77
+ draw() {
78
+ const childrenToRemove = [];
79
+ const preserveSet = this._skipAnchors ? new Set([...this.anchors, this.selectionOutline, this.rotationAnchor].filter(Boolean)) : null;
80
+ for (let i = 0; i < this.group.children.length; i++) {
81
+ const child = this.group.children[i];
82
+ if (child !== this.element && child !== this.labelElement && child !== this._hitArea && child !== this._labelBg && child !== this._shadeEllipse) {
83
+ if (preserveSet && preserveSet.has(child)) continue;
84
+ childrenToRemove.push(child);
85
+ }
86
+ }
87
+ childrenToRemove.forEach((child) => this.group.removeChild(child));
88
+ const optionsString = JSON.stringify(this.options);
89
+ const isInitialDraw = this.element === null;
90
+ const sizeChanged = this.rx !== this._lastDrawn.rx || this.ry !== this._lastDrawn.ry;
91
+ const optionsChanged = optionsString !== this._lastDrawn.options;
92
+ if (isInitialDraw || optionsChanged || sizeChanged) {
93
+ if (this.element && this.element.parentNode === this.group) {
94
+ this.group.removeChild(this.element);
95
+ }
96
+ const roughEllipse = rc.ellipse(0, 0, this.rx * 2, this.ry * 2, this.options);
97
+ this.element = roughEllipse;
98
+ this.group.appendChild(roughEllipse);
99
+ this._lastDrawn.rx = this.rx;
100
+ this._lastDrawn.ry = this.ry;
101
+ this._lastDrawn.options = optionsString;
102
+ }
103
+ if (!this._hitArea) {
104
+ this._hitArea = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
105
+ this._hitArea.setAttribute("fill", "transparent");
106
+ this._hitArea.setAttribute("stroke", "none");
107
+ this._hitArea.setAttribute("style", "pointer-events: all;");
108
+ this.group.insertBefore(this._hitArea, this.group.firstChild);
109
+ }
110
+ this._hitArea.setAttribute("cx", 0);
111
+ this._hitArea.setAttribute("cy", 0);
112
+ this._hitArea.setAttribute("rx", this.rx);
113
+ this._hitArea.setAttribute("ry", this.ry);
114
+ this._updateShade();
115
+ this._updateLabelElement();
116
+ this.group.setAttribute("transform", `translate(${this.x}, ${this.y}) rotate(${this.rotation}, 0, 0)`);
117
+ if (this.isSelected) {
118
+ if (this._skipAnchors) {
119
+ this.updateSelectionControls();
120
+ } else {
121
+ this.addAnchors();
122
+ }
123
+ }
124
+ if (!this.group.parentNode) {
125
+ svg.appendChild(this.group);
126
+ }
127
+ }
128
+ move(dx, dy) {
129
+ this.x += dx;
130
+ this.y += dy;
131
+ this.group.setAttribute("transform", `translate(${this.x}, ${this.y}) rotate(${this.rotation}, 0, 0)`);
132
+ this.updateAttachedArrows();
133
+ if (isDraggingShapeCircle && !this.isBeingMovedByFrame) {
134
+ this.updateFrameContainment();
135
+ }
136
+ }
137
+ updateFrameContainment() {
138
+ if (this.isBeingMovedByFrame) return;
139
+ let targetFrame = null;
140
+ shapes.forEach((shape) => {
141
+ if (shape.shapeName === "frame" && shape.isShapeInFrame(this)) {
142
+ targetFrame = shape;
143
+ }
144
+ });
145
+ if (this.parentFrame && isDraggingShapeCircle) {
146
+ this.parentFrame.temporarilyRemoveFromFrame(this);
147
+ }
148
+ if (hoveredFrameCircle && hoveredFrameCircle !== targetFrame) {
149
+ hoveredFrameCircle.removeHighlight();
150
+ }
151
+ if (targetFrame && targetFrame !== hoveredFrameCircle) {
152
+ targetFrame.highlightFrame();
153
+ }
154
+ hoveredFrameCircle = targetFrame;
155
+ }
156
+ getRotatedCursor(direction, angle) {
157
+ const directions = ["ns", "nesw", "ew", "nwse"];
158
+ angle = angle % 360;
159
+ if (angle < 0) angle += 360;
160
+ const baseDirectionMap = {
161
+ "0": "nwse",
162
+ "1": "nesw",
163
+ "2": "nesw",
164
+ "3": "nwse",
165
+ "4": "ns",
166
+ "5": "ns",
167
+ "6": "ew",
168
+ "7": "ew"
169
+ };
170
+ const baseDirection = baseDirectionMap[direction];
171
+ let effectiveAngle = angle;
172
+ if (baseDirection === "nesw") {
173
+ effectiveAngle += 45;
174
+ } else if (baseDirection === "ew") {
175
+ effectiveAngle += 90;
176
+ } else if (baseDirection === "nwse") {
177
+ effectiveAngle += 135;
178
+ }
179
+ effectiveAngle = effectiveAngle % 360;
180
+ if (effectiveAngle < 0) effectiveAngle += 360;
181
+ const index = Math.round(effectiveAngle / 45) % 4;
182
+ let finalIndex;
183
+ if (effectiveAngle >= 337.5 || effectiveAngle < 22.5) finalIndex = 0;
184
+ else if (effectiveAngle >= 22.5 && effectiveAngle < 67.5) finalIndex = 1;
185
+ else if (effectiveAngle >= 67.5 && effectiveAngle < 112.5) finalIndex = 2;
186
+ else if (effectiveAngle >= 112.5 && effectiveAngle < 157.5) finalIndex = 3;
187
+ else if (effectiveAngle >= 157.5 && effectiveAngle < 202.5) finalIndex = 0;
188
+ else if (effectiveAngle >= 202.5 && effectiveAngle < 247.5) finalIndex = 1;
189
+ else if (effectiveAngle >= 247.5 && effectiveAngle < 292.5) finalIndex = 2;
190
+ else if (effectiveAngle >= 292.5 && effectiveAngle < 337.5) finalIndex = 3;
191
+ else finalIndex = 0;
192
+ return directions[finalIndex];
193
+ }
194
+ addAnchors() {
195
+ const zoom = window.currentZoom || 1;
196
+ const anchorSize = 10 / zoom;
197
+ const anchorStrokeWidth = 2;
198
+ const self = this;
199
+ const expandedX = -this.rx - this.selectionPadding;
200
+ const expandedY = -this.ry - this.selectionPadding;
201
+ const expandedWidth = this.rx * 2 + 2 * this.selectionPadding;
202
+ const expandedHeight = this.ry * 2 + 2 * this.selectionPadding;
203
+ const positions = [
204
+ { x: expandedX, y: expandedY },
205
+ { x: expandedX + expandedWidth, y: expandedY },
206
+ { x: expandedX, y: expandedY + expandedHeight },
207
+ { x: expandedX + expandedWidth, y: expandedY + expandedHeight },
208
+ { x: expandedX + expandedWidth / 2, y: expandedY },
209
+ { x: expandedX + expandedWidth / 2, y: expandedY + expandedHeight },
210
+ { x: expandedX, y: expandedHeight / 2 + expandedY },
211
+ { x: expandedX + expandedWidth, y: expandedHeight / 2 + expandedY }
212
+ ];
213
+ const outlinePoints = [
214
+ [positions[0].x, positions[0].y],
215
+ [positions[1].x, positions[1].y],
216
+ [positions[3].x, positions[3].y],
217
+ [positions[2].x, positions[2].y],
218
+ [positions[0].x, positions[0].y]
219
+ ];
220
+ this.anchors.forEach((anchor) => {
221
+ if (anchor.parentNode === this.group) {
222
+ this.group.removeChild(anchor);
223
+ }
224
+ });
225
+ if (this.rotationAnchor && this.rotationAnchor.parentNode === this.group) {
226
+ this.group.removeChild(this.rotationAnchor);
227
+ }
228
+ if (this.selectionOutline && this.selectionOutline.parentNode === this.group) {
229
+ this.group.removeChild(this.selectionOutline);
230
+ }
231
+ this.anchors = [];
232
+ const anchorDirections = {
233
+ 0: "nwse",
234
+ 1: "nesw",
235
+ 2: "nesw",
236
+ 3: "nwse",
237
+ 4: "ns",
238
+ 5: "ns",
239
+ 6: "ew",
240
+ 7: "ew"
241
+ };
242
+ positions.forEach((pos, i) => {
243
+ const anchor = document.createElementNS("http://www.w3.org/2000/svg", "rect");
244
+ anchor.setAttribute("x", pos.x - anchorSize / 2);
245
+ anchor.setAttribute("y", pos.y - anchorSize / 2);
246
+ anchor.setAttribute("width", anchorSize);
247
+ anchor.setAttribute("height", anchorSize);
248
+ anchor.setAttribute("class", "anchor");
249
+ anchor.setAttribute("data-index", i);
250
+ anchor.setAttribute("fill", "#121212");
251
+ anchor.setAttribute("stroke", "#5B57D1");
252
+ anchor.setAttribute("stroke-width", anchorStrokeWidth);
253
+ anchor.setAttribute("vector-effect", "non-scaling-stroke");
254
+ anchor.setAttribute("style", "pointer-events: all;");
255
+ anchor.addEventListener("mouseover", function() {
256
+ const index = this.getAttribute("data-index");
257
+ const baseDirection = anchorDirections[index];
258
+ const rotatedCursor = self.getRotatedCursor(index, self.rotation);
259
+ svg.style.cursor = rotatedCursor + "-resize";
260
+ });
261
+ anchor.addEventListener("mouseout", function() {
262
+ if (!isResizingShapeCircle && !isDraggingShapeCircle && !isRotatingShapeCircle) {
263
+ svg.style.cursor = "default";
264
+ }
265
+ });
266
+ this.group.appendChild(anchor);
267
+ this.anchors[i] = anchor;
268
+ });
269
+ const rotationAnchorPos = { x: expandedX + expandedWidth / 2, y: expandedY - 30 / zoom };
270
+ this.rotationAnchor = document.createElementNS("http://www.w3.org/2000/svg", "circle");
271
+ this.rotationAnchor.setAttribute("cx", rotationAnchorPos.x);
272
+ this.rotationAnchor.setAttribute("cy", rotationAnchorPos.y);
273
+ this.rotationAnchor.setAttribute("r", 8 / zoom);
274
+ this.rotationAnchor.setAttribute("class", "rotate-anchor");
275
+ this.rotationAnchor.setAttribute("fill", "#121212");
276
+ this.rotationAnchor.setAttribute("stroke", "#5B57D1");
277
+ this.rotationAnchor.setAttribute("stroke-width", anchorStrokeWidth);
278
+ this.rotationAnchor.setAttribute("vector-effect", "non-scaling-stroke");
279
+ this.rotationAnchor.setAttribute("style", "pointer-events: all;");
280
+ this.group.appendChild(this.rotationAnchor);
281
+ this.rotationAnchor.addEventListener("mouseover", function() {
282
+ if (!isResizingShapeCircle && !isDraggingShapeCircle && !isRotatingShapeCircle) {
283
+ svg.style.cursor = "grab";
284
+ }
285
+ });
286
+ this.rotationAnchor.addEventListener("mouseout", function() {
287
+ if (!isResizingShapeCircle && !isDraggingShapeCircle && !isRotatingShapeCircle) {
288
+ svg.style.cursor = "default";
289
+ }
290
+ });
291
+ const pointsAttr = outlinePoints.map((p) => p.join(",")).join(" ");
292
+ const outline = document.createElementNS("http://www.w3.org/2000/svg", "polyline");
293
+ outline.setAttribute("points", pointsAttr);
294
+ outline.setAttribute("fill", "none");
295
+ outline.setAttribute("stroke", "#5B57D1");
296
+ outline.setAttribute("stroke-width", 1.5);
297
+ outline.setAttribute("vector-effect", "non-scaling-stroke");
298
+ outline.setAttribute("stroke-dasharray", "4 2");
299
+ outline.setAttribute("style", "pointer-events: none;");
300
+ this.group.appendChild(outline);
301
+ this.selectionOutline = outline;
302
+ disableAllSideBars();
303
+ circleSideBar.classList.remove("hidden");
304
+ if (window.__showSidebarForShape) window.__showSidebarForShape("circle");
305
+ this.updateSidebar();
306
+ }
307
+ updateSelectionControls() {
308
+ if (!this.selectionOutline || this.anchors.length === 0) return;
309
+ const anchorSize = 10;
310
+ const expandedX = -this.rx - this.selectionPadding;
311
+ const expandedY = -this.ry - this.selectionPadding;
312
+ const expandedWidth = this.rx * 2 + 2 * this.selectionPadding;
313
+ const expandedHeight = this.ry * 2 + 2 * this.selectionPadding;
314
+ const positions = [
315
+ { x: expandedX, y: expandedY },
316
+ { x: expandedX + expandedWidth, y: expandedY },
317
+ { x: expandedX, y: expandedY + expandedHeight },
318
+ { x: expandedX + expandedWidth, y: expandedY + expandedHeight },
319
+ { x: expandedX + expandedWidth / 2, y: expandedY },
320
+ { x: expandedX + expandedWidth / 2, y: expandedY + expandedHeight },
321
+ { x: expandedX, y: expandedHeight / 2 + expandedY },
322
+ { x: expandedX + expandedWidth, y: expandedHeight / 2 + expandedY }
323
+ ];
324
+ positions.forEach((pos, i) => {
325
+ if (this.anchors[i]) {
326
+ this.anchors[i].setAttribute("x", pos.x - anchorSize / 2);
327
+ this.anchors[i].setAttribute("y", pos.y - anchorSize / 2);
328
+ }
329
+ });
330
+ const outlinePoints = [
331
+ [positions[0].x, positions[0].y],
332
+ [positions[1].x, positions[1].y],
333
+ [positions[3].x, positions[3].y],
334
+ [positions[2].x, positions[2].y],
335
+ [positions[0].x, positions[0].y]
336
+ ];
337
+ this.selectionOutline.setAttribute("points", outlinePoints.map((p) => p.join(",")).join(" "));
338
+ if (this.rotationAnchor) {
339
+ this.rotationAnchor.setAttribute("cx", expandedX + expandedWidth / 2);
340
+ this.rotationAnchor.setAttribute("cy", expandedY - 30);
341
+ }
342
+ }
343
+ removeSelection() {
344
+ this.anchors.forEach((anchor) => {
345
+ if (anchor.parentNode === this.group) {
346
+ this.group.removeChild(anchor);
347
+ }
348
+ });
349
+ if (this.rotationAnchor && this.rotationAnchor.parentNode === this.group) {
350
+ this.group.removeChild(this.rotationAnchor);
351
+ }
352
+ if (this.selectionOutline && this.selectionOutline.parentNode === this.group) {
353
+ this.group.removeChild(this.selectionOutline);
354
+ }
355
+ this.anchors = [];
356
+ this.rotationAnchor = null;
357
+ this.selectionOutline = null;
358
+ this.isSelected = false;
359
+ }
360
+ contains(x, y) {
361
+ if (!this.element) return false;
362
+ const CTM = this.group.getCTM();
363
+ if (!CTM) return false;
364
+ const inverseCTM = CTM.inverse();
365
+ const svgPoint = svg.createSVGPoint();
366
+ svgPoint.x = x;
367
+ svgPoint.y = y;
368
+ const transformedPoint = svgPoint.matrixTransform(inverseCTM);
369
+ const dx = transformedPoint.x - 0;
370
+ const dy = transformedPoint.y - 0;
371
+ const rx = this.rx;
372
+ const ry = this.ry;
373
+ return dx * dx / (rx * rx) + dy * dy / (ry * ry) <= 1.05;
374
+ }
375
+ isNearAnchor(x, y) {
376
+ if (!this.isSelected) return null;
377
+ const buffer = 10 / currentZoom;
378
+ const anchorSize = 10 / currentZoom;
379
+ for (let i = 0; i < this.anchors.length; i++) {
380
+ const anchor = this.anchors[i];
381
+ const anchorLocalX = parseFloat(anchor.getAttribute("x")) + anchorSize / 2;
382
+ const anchorLocalY = parseFloat(anchor.getAttribute("y")) + anchorSize / 2;
383
+ const svgPoint = svg.createSVGPoint();
384
+ svgPoint.x = anchorLocalX;
385
+ svgPoint.y = anchorLocalY;
386
+ const transformedPoint = svgPoint.matrixTransform(this.group.getCTM());
387
+ const anchorLeft = transformedPoint.x - anchorSize / 2 - buffer;
388
+ const anchorRight = transformedPoint.x + anchorSize / 2 + buffer;
389
+ const anchorTop = transformedPoint.y - anchorSize / 2 - buffer;
390
+ const anchorBottom = transformedPoint.y + anchorSize / 2 + buffer;
391
+ if (x >= anchorLeft && x <= anchorRight && y >= anchorTop && y <= anchorBottom) {
392
+ return { type: "resize", index: i };
393
+ }
394
+ }
395
+ if (this.rotationAnchor) {
396
+ const rotateAnchorLocalX = parseFloat(this.rotationAnchor.getAttribute("cx"));
397
+ const rotateAnchorLocalY = parseFloat(this.rotationAnchor.getAttribute("cy"));
398
+ const svgPoint = svg.createSVGPoint();
399
+ svgPoint.x = rotateAnchorLocalX;
400
+ svgPoint.y = rotateAnchorLocalY;
401
+ const transformedPoint = svgPoint.matrixTransform(this.group.getCTM());
402
+ const rotateAnchorRadius = parseFloat(this.rotationAnchor.getAttribute("r")) / currentZoom;
403
+ const distSq = (x - transformedPoint.x) ** 2 + (y - transformedPoint.y) ** 2;
404
+ if (distSq <= (rotateAnchorRadius + buffer) ** 2) {
405
+ return { type: "rotate" };
406
+ }
407
+ }
408
+ return null;
409
+ }
410
+ updatePosition(anchorIndex, newMouseX, newMouseY) {
411
+ const CTM = this.group.getCTM();
412
+ if (!CTM) return;
413
+ const inverseCTM = CTM.inverse();
414
+ const svgPoint = svg.createSVGPoint();
415
+ svgPoint.x = newMouseX;
416
+ svgPoint.y = newMouseY;
417
+ const transformedPoint = svgPoint.matrixTransform(inverseCTM);
418
+ const dx = transformedPoint.x;
419
+ const dy = transformedPoint.y;
420
+ const MIN_RADIUS = 10;
421
+ switch (anchorIndex) {
422
+ case 0:
423
+ // top-left
424
+ case 1:
425
+ // top-right
426
+ case 2:
427
+ // bottom-left
428
+ case 3:
429
+ this.rx = Math.max(Math.abs(dx), MIN_RADIUS);
430
+ this.ry = Math.max(Math.abs(dy), MIN_RADIUS);
431
+ break;
432
+ case 4:
433
+ // top-center
434
+ case 5:
435
+ this.ry = Math.max(Math.abs(dy), MIN_RADIUS);
436
+ break;
437
+ case 6:
438
+ // left-center
439
+ case 7:
440
+ this.rx = Math.max(Math.abs(dx), MIN_RADIUS);
441
+ break;
442
+ }
443
+ this.updateAttachedArrows();
444
+ }
445
+ updateAttachedArrows() {
446
+ shapes.forEach((shape) => {
447
+ if (shape && shape.shapeName === "arrow" && typeof shape.updateAttachments === "function") {
448
+ if (shape.attachedToStart && shape.attachedToStart.shape === this || shape.attachedToEnd && shape.attachedToEnd.shape === this) {
449
+ shape.updateAttachments();
450
+ }
451
+ }
452
+ });
453
+ }
454
+ _updateShade() {
455
+ if (!this.shadeColor) {
456
+ if (this._shadeEllipse && this._shadeEllipse.parentNode === this.group) {
457
+ this.group.removeChild(this._shadeEllipse);
458
+ this._shadeEllipse = null;
459
+ }
460
+ if (this._shadeGradient && this._shadeGradient.parentNode) {
461
+ this._shadeGradient.parentNode.removeChild(this._shadeGradient);
462
+ this._shadeGradient = null;
463
+ }
464
+ return;
465
+ }
466
+ let defs = svg.querySelector("defs");
467
+ if (!defs) {
468
+ defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
469
+ svg.appendChild(defs);
470
+ }
471
+ const gradId = `shade-${this.shapeID}`;
472
+ if (!this._shadeGradient) {
473
+ this._shadeGradient = document.createElementNS("http://www.w3.org/2000/svg", "radialGradient");
474
+ this._shadeGradient.setAttribute("id", gradId);
475
+ defs.appendChild(this._shadeGradient);
476
+ }
477
+ this._shadeGradient.setAttribute("cx", "50%");
478
+ this._shadeGradient.setAttribute("cy", "50%");
479
+ this._shadeGradient.setAttribute("r", "50%");
480
+ while (this._shadeGradient.firstChild) this._shadeGradient.removeChild(this._shadeGradient.firstChild);
481
+ const stop1 = document.createElementNS("http://www.w3.org/2000/svg", "stop");
482
+ stop1.setAttribute("offset", "0%");
483
+ stop1.setAttribute("stop-color", this.shadeColor);
484
+ stop1.setAttribute("stop-opacity", this.shadeOpacity);
485
+ const stop2 = document.createElementNS("http://www.w3.org/2000/svg", "stop");
486
+ stop2.setAttribute("offset", "100%");
487
+ stop2.setAttribute("stop-color", this.shadeColor);
488
+ stop2.setAttribute("stop-opacity", "0");
489
+ this._shadeGradient.appendChild(stop1);
490
+ this._shadeGradient.appendChild(stop2);
491
+ if (!this._shadeEllipse) {
492
+ this._shadeEllipse = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
493
+ this._shadeEllipse.setAttribute("pointer-events", "none");
494
+ }
495
+ this._shadeEllipse.setAttribute("cx", 0);
496
+ this._shadeEllipse.setAttribute("cy", 0);
497
+ this._shadeEllipse.setAttribute("rx", this.rx);
498
+ this._shadeEllipse.setAttribute("ry", this.ry);
499
+ this._shadeEllipse.setAttribute("fill", `url(#${gradId})`);
500
+ if (this._shadeEllipse.parentNode === this.group) this.group.removeChild(this._shadeEllipse);
501
+ if (this.element && this.element.nextSibling) {
502
+ this.group.insertBefore(this._shadeEllipse, this.element.nextSibling);
503
+ } else {
504
+ this.group.appendChild(this._shadeEllipse);
505
+ }
506
+ }
507
+ _updateLabelElement() {
508
+ if (!this.label) {
509
+ if (this.labelElement && this.labelElement.parentNode === this.group) {
510
+ this.group.removeChild(this.labelElement);
511
+ this.labelElement = null;
512
+ }
513
+ if (this._labelBg && this._labelBg.parentNode === this.group) {
514
+ this.group.removeChild(this._labelBg);
515
+ this._labelBg = null;
516
+ }
517
+ return;
518
+ }
519
+ if (!this.labelElement) {
520
+ this.labelElement = document.createElementNS("http://www.w3.org/2000/svg", "text");
521
+ this.labelElement.setAttribute("class", "shape-label");
522
+ this.labelElement.setAttribute("pointer-events", "none");
523
+ }
524
+ this.labelElement.setAttribute("x", 0);
525
+ this.labelElement.setAttribute("y", 0);
526
+ this.labelElement.setAttribute("text-anchor", "middle");
527
+ this.labelElement.setAttribute("dominant-baseline", "central");
528
+ this.labelElement.setAttribute("fill", this.labelColor);
529
+ this.labelElement.setAttribute("font-size", this.labelFontSize);
530
+ this.labelElement.setAttribute("font-family", "lixFont, sans-serif");
531
+ this.labelElement.textContent = this.label;
532
+ const canvasBg = window.getComputedStyle(svg).backgroundColor || "#000";
533
+ if (!this._labelBg) {
534
+ this._labelBg = document.createElementNS("http://www.w3.org/2000/svg", "rect");
535
+ this._labelBg.setAttribute("pointer-events", "none");
536
+ }
537
+ this._labelBg.setAttribute("fill", canvasBg);
538
+ const hPadding = 6;
539
+ const vPadding = 2;
540
+ const charWidth = this.labelFontSize * 0.6;
541
+ const bgW = this.label.length * charWidth + hPadding * 2;
542
+ const bgH = this.labelFontSize + vPadding * 2;
543
+ this._labelBg.setAttribute("x", -bgW / 2);
544
+ this._labelBg.setAttribute("y", -bgH / 2);
545
+ this._labelBg.setAttribute("width", bgW);
546
+ this._labelBg.setAttribute("height", bgH);
547
+ this._labelBg.setAttribute("rx", 3);
548
+ if (this._labelBg.parentNode === this.group) this.group.removeChild(this._labelBg);
549
+ if (this.labelElement.parentNode === this.group) this.group.removeChild(this.labelElement);
550
+ this.group.appendChild(this._labelBg);
551
+ this.group.appendChild(this.labelElement);
552
+ }
553
+ _setupLabelDblClick() {
554
+ this.group.addEventListener("dblclick", (e) => {
555
+ e.stopPropagation();
556
+ e.preventDefault();
557
+ this.startLabelEdit();
558
+ });
559
+ }
560
+ startLabelEdit() {
561
+ if (this._isEditingLabel) return;
562
+ this._isEditingLabel = true;
563
+ if (this.labelElement) {
564
+ this.labelElement.setAttribute("visibility", "hidden");
565
+ }
566
+ const ctm = this.group.getScreenCTM();
567
+ if (!ctm) {
568
+ this._isEditingLabel = false;
569
+ return;
570
+ }
571
+ const pt1 = svg.createSVGPoint();
572
+ pt1.x = -this.rx;
573
+ pt1.y = -this.ry;
574
+ const screenTL = pt1.matrixTransform(ctm);
575
+ const pt2 = svg.createSVGPoint();
576
+ pt2.x = this.rx;
577
+ pt2.y = this.ry;
578
+ const screenBR = pt2.matrixTransform(ctm);
579
+ const screenW = Math.abs(screenBR.x - screenTL.x);
580
+ const screenH = Math.abs(screenBR.y - screenTL.y);
581
+ const screenX = Math.min(screenTL.x, screenBR.x);
582
+ const screenY = Math.min(screenTL.y, screenBR.y);
583
+ const overlay = document.createElement("div");
584
+ overlay.className = "shape-label-editor";
585
+ overlay.style.cssText = `
586
+ position: fixed; z-index: 10000;
587
+ left: ${screenX}px; top: ${screenY}px;
588
+ width: ${screenW}px; height: ${screenH}px;
589
+ display: flex; align-items: center; justify-content: center;
590
+ pointer-events: auto;
591
+ `;
592
+ const canvasBg = window.getComputedStyle(svg).backgroundColor || "#000";
593
+ const input = document.createElement("div");
594
+ input.setAttribute("contenteditable", "true");
595
+ input.style.cssText = `
596
+ max-width: ${screenW - 8}px; min-width: 30px; min-height: 20px;
597
+ background: ${canvasBg}; border: none;
598
+ outline: none; padding: 2px 6px;
599
+ color: ${this.labelColor}; font-size: ${Math.max(12, this.labelFontSize * (screenW / Math.max(this.rx * 2, 1)))}px;
600
+ font-family: lixFont, sans-serif; text-align: center;
601
+ white-space: pre-wrap; word-break: break-word;
602
+ cursor: text;
603
+ `;
604
+ if (this.label) {
605
+ input.textContent = this.label;
606
+ } else {
607
+ input.innerHTML = "&nbsp;";
608
+ }
609
+ overlay.appendChild(input);
610
+ document.body.appendChild(overlay);
611
+ setTimeout(() => {
612
+ input.focus();
613
+ const sel = window.getSelection();
614
+ const range = document.createRange();
615
+ range.selectNodeContents(input);
616
+ sel.removeAllRanges();
617
+ sel.addRange(range);
618
+ }, 10);
619
+ const finishEdit = () => {
620
+ const newText = input.textContent.trim().replace(/\u00A0/g, "");
621
+ this.label = newText;
622
+ this._isEditingLabel = false;
623
+ if (overlay.parentNode) overlay.parentNode.removeChild(overlay);
624
+ if (this.labelElement) this.labelElement.setAttribute("visibility", "visible");
625
+ this.draw();
626
+ };
627
+ input.addEventListener("blur", finishEdit);
628
+ input.addEventListener("keydown", (e) => {
629
+ e.stopPropagation();
630
+ if (e.key === "Enter" && !e.shiftKey) {
631
+ e.preventDefault();
632
+ input.blur();
633
+ }
634
+ if (e.key === "Escape") {
635
+ input.textContent = this.label;
636
+ input.blur();
637
+ }
638
+ });
639
+ input.addEventListener("pointerdown", (e) => e.stopPropagation());
640
+ input.addEventListener("pointermove", (e) => e.stopPropagation());
641
+ input.addEventListener("pointerup", (e) => e.stopPropagation());
642
+ }
643
+ setLabel(text, color, fontSize) {
644
+ this.label = text || "";
645
+ if (color) this.labelColor = color;
646
+ if (fontSize) this.labelFontSize = fontSize;
647
+ this.draw();
648
+ }
649
+ rotate(angle) {
650
+ angle = angle % 360;
651
+ if (angle < 0) angle += 360;
652
+ this.rotation = angle;
653
+ }
654
+ // No-op: React sidebar handles UI updates via Zustand store
655
+ updateSidebar() {
656
+ }
657
+ };
658
+
659
+ export {
660
+ Circle
661
+ };
662
+ //# sourceMappingURL=chunk-AJAZC37E.js.map