@elixpo/lixsketch 4.5.8

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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +169 -0
  3. package/fonts/fonts.css +29 -0
  4. package/fonts/lixCode.ttf +0 -0
  5. package/fonts/lixDefault.ttf +0 -0
  6. package/fonts/lixDocs.ttf +0 -0
  7. package/fonts/lixFancy.ttf +0 -0
  8. package/fonts/lixFont.woff2 +0 -0
  9. package/package.json +49 -0
  10. package/src/SketchEngine.js +473 -0
  11. package/src/core/AIRenderer.js +1390 -0
  12. package/src/core/CopyPaste.js +655 -0
  13. package/src/core/EraserTrail.js +234 -0
  14. package/src/core/EventDispatcher.js +371 -0
  15. package/src/core/GraphEngine.js +150 -0
  16. package/src/core/GraphMathParser.js +231 -0
  17. package/src/core/GraphRenderer.js +255 -0
  18. package/src/core/LayerOrder.js +91 -0
  19. package/src/core/LixScriptParser.js +1299 -0
  20. package/src/core/MermaidFlowchartRenderer.js +475 -0
  21. package/src/core/MermaidSequenceParser.js +197 -0
  22. package/src/core/MermaidSequenceRenderer.js +479 -0
  23. package/src/core/ResizeCode.js +175 -0
  24. package/src/core/ResizeShapes.js +318 -0
  25. package/src/core/SceneSerializer.js +778 -0
  26. package/src/core/Selection.js +1861 -0
  27. package/src/core/SnapGuides.js +273 -0
  28. package/src/core/UndoRedo.js +1358 -0
  29. package/src/core/ZoomPan.js +258 -0
  30. package/src/core/ai-system-prompt.js +663 -0
  31. package/src/index.js +69 -0
  32. package/src/shapes/Arrow.js +1979 -0
  33. package/src/shapes/Circle.js +751 -0
  34. package/src/shapes/CodeShape.js +244 -0
  35. package/src/shapes/Frame.js +1460 -0
  36. package/src/shapes/FreehandStroke.js +724 -0
  37. package/src/shapes/IconShape.js +265 -0
  38. package/src/shapes/ImageShape.js +270 -0
  39. package/src/shapes/Line.js +738 -0
  40. package/src/shapes/Rectangle.js +794 -0
  41. package/src/shapes/TextShape.js +225 -0
  42. package/src/tools/arrowTool.js +581 -0
  43. package/src/tools/circleTool.js +619 -0
  44. package/src/tools/codeTool.js +2103 -0
  45. package/src/tools/eraserTool.js +131 -0
  46. package/src/tools/frameTool.js +241 -0
  47. package/src/tools/freehandTool.js +620 -0
  48. package/src/tools/iconTool.js +1344 -0
  49. package/src/tools/imageTool.js +1323 -0
  50. package/src/tools/laserTool.js +317 -0
  51. package/src/tools/lineTool.js +502 -0
  52. package/src/tools/rectangleTool.js +544 -0
  53. package/src/tools/textTool.js +1823 -0
  54. package/src/utils/imageCompressor.js +107 -0
@@ -0,0 +1,244 @@
1
+ /* eslint-disable */
2
+ // CodeShape class - extracted from writeCode.js
3
+ // Depends on globals: svg, shapes, currentShape
4
+
5
+ function extractRotationFromTransform(el) {
6
+ const t = el.getAttribute("transform") || "";
7
+ const m = t.match(/rotate\(([^,)]+)/);
8
+ return m ? parseFloat(m[1]) : 0;
9
+ }
10
+ function updateAttachedArrows(wrapper) {
11
+ if (!wrapper || typeof shapes === "undefined") return;
12
+ shapes.forEach(s => {
13
+ if (s && s.shapeName === "arrow" && typeof s.updateAttachments === "function") {
14
+ if ((s.attachedToStart && s.attachedToStart.shape === wrapper) ||
15
+ (s.attachedToEnd && s.attachedToEnd.shape === wrapper)) {
16
+ s.updateAttachments();
17
+ }
18
+ }
19
+ });
20
+ }
21
+ function adjustCodeEditorSize(editor) {
22
+ if (!editor) return;
23
+ editor.style.height = "auto";
24
+ editor.style.height = editor.scrollHeight + "px";
25
+ }
26
+ let isCodeDragging = false;
27
+ let hoveredCodeFrame = null;
28
+ let selectedCodeBlock = null;
29
+ function updateCodeSelectionFeedback() {}
30
+ function deselectCodeBlock() { selectedCodeBlock = null; }
31
+ function selectCodeBlock(el) { selectedCodeBlock = el; }
32
+
33
+ class CodeShape {
34
+ constructor(groupElement) {
35
+ this.group = groupElement;
36
+ this.shapeName = 'code';
37
+ this.shapeID = groupElement.getAttribute('id') || `code-${String(Date.now()).slice(0, 8)}-${Math.floor(Math.random() * 10000)}`;
38
+
39
+ // Frame attachment properties
40
+ this.parentFrame = null;
41
+
42
+ // Update group attributes — ensure data-type is set for codeTool interaction
43
+ this.group.setAttribute('type', 'code');
44
+ this.group.setAttribute('data-type', 'code-group');
45
+ this.group.shapeName = 'code';
46
+ this.group.shapeID = this.shapeID;
47
+ }
48
+
49
+ // Position and dimension properties for frame compatibility
50
+ get x() {
51
+ const transform = this.group.transform.baseVal.consolidate();
52
+ return transform ? transform.matrix.e : parseFloat(this.group.getAttribute('data-x')) || 0;
53
+ }
54
+
55
+ set x(value) {
56
+ const transform = this.group.transform.baseVal.consolidate();
57
+ const currentY = transform ? transform.matrix.f : parseFloat(this.group.getAttribute('data-y')) || 0;
58
+ const rotation = extractRotationFromTransform(this.group) || 0;
59
+ const codeBlockContainer = this.group.querySelector('foreignObject');
60
+ if (codeBlockContainer) {
61
+ const bbox = codeBlockContainer.getBBox();
62
+ const centerX = bbox.x + bbox.width / 2;
63
+ const centerY = bbox.y + bbox.height / 2;
64
+ this.group.setAttribute('transform', `translate(${value}, ${currentY}) rotate(${rotation}, ${centerX}, ${centerY})`);
65
+ } else {
66
+ this.group.setAttribute('transform', `translate(${value}, ${currentY})`);
67
+ }
68
+ this.group.setAttribute('data-x', value);
69
+ }
70
+
71
+ get y() {
72
+ const transform = this.group.transform.baseVal.consolidate();
73
+ return transform ? transform.matrix.f : parseFloat(this.group.getAttribute('data-y')) || 0;
74
+ }
75
+
76
+ set y(value) {
77
+ const transform = this.group.transform.baseVal.consolidate();
78
+ const currentX = transform ? transform.matrix.e : parseFloat(this.group.getAttribute('data-x')) || 0;
79
+ const rotation = extractRotationFromTransform(this.group) || 0;
80
+ const codeBlockContainer = this.group.querySelector('foreignObject');
81
+ if (codeBlockContainer) {
82
+ const bbox = codeBlockContainer.getBBox();
83
+ const centerX = bbox.x + bbox.width / 2;
84
+ const centerY = bbox.y + bbox.height / 2;
85
+ this.group.setAttribute('transform', `translate(${currentX}, ${value}) rotate(${rotation}, ${centerX}, ${centerY})`);
86
+ } else {
87
+ this.group.setAttribute('transform', `translate(${currentX}, ${value})`);
88
+ }
89
+ this.group.setAttribute('data-y', value);
90
+ }
91
+
92
+ get width() {
93
+ const codeElement = this.group.querySelector('text');
94
+ if (codeElement) {
95
+ return codeElement.getBBox().width;
96
+ }
97
+ return 0;
98
+ }
99
+
100
+ set width(value) {
101
+ const codeBlockContainer = this.group.querySelector('foreignObject');
102
+ if (codeBlockContainer) {
103
+ codeBlockContainer.setAttribute('width', value);
104
+ // This might trigger a reflow in the foreignObject content
105
+ const codeEditor = codeBlockContainer.querySelector('.svg-code-editor');
106
+ if (codeEditor) {
107
+ codeEditor.style.width = `${value}px`;
108
+ adjustCodeEditorSize(codeEditor);
109
+ }
110
+ }
111
+ }
112
+
113
+ get height() {
114
+ const codeElement = this.group.querySelector('text');
115
+ if (codeElement) {
116
+ return codeElement.getBBox().height;
117
+ }
118
+ return 0;
119
+ }
120
+
121
+ set height(value) {
122
+ const codeBlockContainer = this.group.querySelector('foreignObject');
123
+ if (codeBlockContainer) {
124
+ codeBlockContainer.setAttribute('height', value);
125
+ const codeEditor = codeBlockContainer.querySelector('.svg-code-editor');
126
+ if (codeEditor) {
127
+ codeEditor.style.height = `${value}px`;
128
+ adjustCodeEditorSize(codeEditor);
129
+ }
130
+ }
131
+ }
132
+
133
+ get rotation() {
134
+ return extractRotationFromTransform(this.group) || 0;
135
+ }
136
+
137
+ set rotation(value) {
138
+ const currentTransform = this.group.transform.baseVal.consolidate();
139
+ const currentX = currentTransform ? currentTransform.matrix.e : 0;
140
+ const currentY = currentTransform ? currentTransform.matrix.f : 0;
141
+ const codeBlockContainer = this.group.querySelector('foreignObject');
142
+ if (codeBlockContainer) {
143
+ const bbox = codeBlockContainer.getBBox();
144
+ const centerX = bbox.x + bbox.width / 2;
145
+ const centerY = bbox.y + bbox.height / 2;
146
+ this.group.setAttribute('transform', `translate(${currentX}, ${currentY}) rotate(${value}, ${centerX}, ${centerY})`);
147
+ }
148
+ }
149
+
150
+ move(dx, dy) {
151
+ const currentTransform = this.group.transform.baseVal.consolidate();
152
+ const currentX = currentTransform ? currentTransform.matrix.e : 0;
153
+ const currentY = currentTransform ? currentTransform.matrix.f : 0;
154
+
155
+ this.x = currentX + dx;
156
+ this.y = currentY + dy;
157
+
158
+ // Only update frame containment if we're actively dragging the shape itself
159
+ // and not being moved by a parent frame
160
+ if (isCodeDragging && !this.isBeingMovedByFrame) {
161
+ this.updateFrameContainment();
162
+ }
163
+
164
+ this.updateAttachedArrows();
165
+ }
166
+
167
+ updateAttachedArrows() {
168
+ updateAttachedArrows(this);
169
+ }
170
+
171
+ updateFrameContainment() {
172
+ // Don't update if we're being moved by a frame
173
+ if (this.isBeingMovedByFrame) return;
174
+
175
+ let targetFrame = null;
176
+
177
+ // Find which frame this shape is over
178
+ if (typeof shapes !== 'undefined' && Array.isArray(shapes)) {
179
+ shapes.forEach(shape => {
180
+ if (shape.shapeName === 'frame' && shape.isShapeInFrame(this)) {
181
+ targetFrame = shape;
182
+ }
183
+ });
184
+ }
185
+
186
+ // If we have a parent frame and we're being dragged, temporarily remove clipping
187
+ if (this.parentFrame && isCodeDragging) {
188
+ this.parentFrame.temporarilyRemoveFromFrame(this);
189
+ }
190
+
191
+ // Update frame highlighting
192
+ if (hoveredCodeFrame && hoveredCodeFrame !== targetFrame) {
193
+ hoveredCodeFrame.removeHighlight();
194
+ }
195
+
196
+ if (targetFrame && targetFrame !== hoveredCodeFrame) {
197
+ targetFrame.highlightFrame();
198
+ }
199
+
200
+ hoveredCodeFrame = targetFrame;
201
+ }
202
+
203
+ contains(x, y) {
204
+ const codeElement = this.group.querySelector('text');
205
+ if (!codeElement) return false;
206
+
207
+ const bbox = codeElement.getBBox();
208
+ const padding = 8; // Selection padding
209
+
210
+ const CTM = this.group.getCTM();
211
+ if (!CTM) return false;
212
+
213
+ const inverseCTM = CTM.inverse();
214
+ const svgPoint = svg.createSVGPoint();
215
+ svgPoint.x = x;
216
+ svgPoint.y = y;
217
+ const transformedPoint = svgPoint.matrixTransform(inverseCTM);
218
+
219
+ return transformedPoint.x >= bbox.x - padding &&
220
+ transformedPoint.x <= bbox.x + bbox.width + padding &&
221
+ transformedPoint.y >= bbox.y - padding &&
222
+ transformedPoint.y <= bbox.y + bbox.height + padding;
223
+ }
224
+
225
+ // Add draw method for consistency with other shapes
226
+ draw() {
227
+ if (selectedCodeBlock === this.group) {
228
+ updateCodeSelectionFeedback();
229
+ }
230
+ }
231
+
232
+ // Add methods for frame compatibility
233
+ removeSelection() {
234
+ if (selectedCodeBlock === this.group) {
235
+ deselectCodeBlock();
236
+ }
237
+ }
238
+
239
+ selectShape() {
240
+ selectCodeBlock(this.group);
241
+ }
242
+ }
243
+
244
+ export { CodeShape };