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