@elixpo/lixsketch 5.5.23 → 5.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -6
- package/dist/mcp/index.js +585 -0
- package/dist/mcp/index.js.map +7 -0
- package/dist/mcp/node.js +184 -0
- package/dist/mcp/node.js.map +7 -0
- package/dist/mcp/stdio.js +723 -0
- package/dist/mcp/stdio.js.map +7 -0
- package/dist/react/{CopyPaste-5OWPTCQ5.js → CopyPaste-YUDZ6DHY.js} +7 -7
- package/dist/react/EventDispatcher-7LAK7GQ7.js +1097 -0
- package/dist/react/EventDispatcher-7LAK7GQ7.js.map +7 -0
- package/dist/react/Frame-7D2MXCFF.js +11 -0
- package/dist/react/IconShape-ZADX7Y33.js +10 -0
- package/dist/react/ImageShape-UJQN2HI7.js +10 -0
- package/dist/react/Line-APEULMHE.js +10 -0
- package/dist/react/{SceneSerializer-RDISX4X7.js → SceneSerializer-SG6SJN5X.js} +17 -7
- package/dist/react/SceneSerializer-SG6SJN5X.js.map +7 -0
- package/dist/react/{Selection-ZL3G6IAO.js → Selection-2TSH3J6P.js} +6 -4
- package/dist/react/{SketchEngine-OB6ZW3B6.js → SketchEngine-UD2XV2KT.js} +50 -23
- package/dist/react/{SketchEngine-OB6ZW3B6.js.map → SketchEngine-UD2XV2KT.js.map} +2 -2
- package/dist/react/{UndoRedo-NL7KLR5B.js → UndoRedo-IN4SXDG6.js} +2 -2
- package/dist/react/{ZoomPan-FAWA5OPS.js → ZoomPan-RR7KUYZT.js} +34 -1
- package/dist/react/{ZoomPan-FAWA5OPS.js.map → ZoomPan-RR7KUYZT.js.map} +2 -2
- package/dist/react/{arrowTool-CNVGM6RX.js → arrowTool-OYDWJGQK.js} +3 -3
- package/dist/react/{chunk-U3TB4KRS.js → chunk-6GPEWDRB.js} +19 -12
- package/dist/react/chunk-6GPEWDRB.js.map +7 -0
- package/dist/react/{chunk-4BLMNGTR.js → chunk-7CM5XQDN.js} +3 -3
- package/dist/react/{chunk-XFQECTTF.js → chunk-APTOPAOY.js} +3 -3
- package/dist/react/{chunk-EDSKEM6E.js → chunk-ASBC5G35.js} +47 -8
- package/dist/react/chunk-ASBC5G35.js.map +7 -0
- package/dist/react/{chunk-4TAS67SL.js → chunk-EOURRJ55.js} +2 -2
- package/dist/react/{chunk-ETAAQUUV.js → chunk-GQUZPON4.js} +4 -4
- package/dist/react/{chunk-KVAQPCUH.js → chunk-K5BG5MHY.js} +49 -5
- package/dist/react/chunk-K5BG5MHY.js.map +7 -0
- package/dist/react/{chunk-AH4PWNEB.js → chunk-K5RY4EV7.js} +23 -3
- package/dist/react/chunk-K5RY4EV7.js.map +7 -0
- package/dist/react/{chunk-GC3KTQDA.js → chunk-LJR7EVW2.js} +3 -3
- package/dist/react/{chunk-SZD7DKYJ.js → chunk-LSHZYN77.js} +2 -2
- package/dist/react/{chunk-HFQZYCHJ.js → chunk-M6TMN76K.js} +3 -3
- package/dist/react/{chunk-V2QTYSBK.js → chunk-OP56XPWF.js} +2 -2
- package/dist/react/chunk-QZI4UIE5.js +48 -0
- package/dist/react/chunk-QZI4UIE5.js.map +7 -0
- package/dist/react/{chunk-ILGAFR56.js → chunk-RGMDWLRJ.js} +3 -3
- package/dist/react/{chunk-OFGJJKPH.js → chunk-XFL4R5ZF.js} +3 -3
- package/dist/react/{chunk-GPIYXREE.js → chunk-XOWNCYE4.js} +3 -3
- package/dist/react/{chunk-YF3TK7SC.js → chunk-XYUFEIZR.js} +2 -2
- package/dist/react/{circleTool-KICNRQCI.js → circleTool-LDKGZALF.js} +4 -4
- package/dist/react/{codeTool-NCQ73R6M.js → codeTool-4YZO5W7J.js} +4 -4
- package/dist/react/{frameTool-Y6KB67DO.js → frameTool-MXNJEXQQ.js} +4 -4
- package/dist/react/{freehandTool-MMULHCQ7.js → freehandTool-26D3FOOX.js} +4 -4
- package/dist/react/{iconTool-LSW2DYGB.js → iconTool-46O5VEUX.js} +4 -4
- package/dist/react/{imageTool-2DSR32RX.js → imageTool-P2RWZRHO.js} +4 -4
- package/dist/react/index.js +848 -614
- package/dist/react/index.js.map +4 -4
- package/dist/react/{lineTool-N5I7IGT7.js → lineTool-ZMR27U5L.js} +4 -4
- package/dist/react/{rectangleTool-YUT7ZK2E.js → rectangleTool-EJKK6UTX.js} +4 -4
- package/dist/react/{textTool-JMTX7OVT.js → textTool-S4XXZHZH.js} +5 -5
- package/package.json +7 -1
- package/src/EngineShortcuts.js +22 -0
- package/src/SketchEngine.js +27 -0
- package/src/core/EventDispatcher.js +35 -4
- package/src/core/SceneSerializer.js +5 -0
- package/src/core/Selection.js +26 -0
- package/src/core/UndoRedo.js +20 -16
- package/src/core/WebEmbedPolicy.js +41 -0
- package/src/core/ZoomPan.js +36 -0
- package/src/index.js +4 -0
- package/src/mcp/fileStore.js +70 -0
- package/src/mcp/index.js +5 -0
- package/src/mcp/node.js +2 -0
- package/src/mcp/preview.js +39 -0
- package/src/mcp/scene.js +275 -0
- package/src/mcp/server.js +195 -0
- package/src/mcp/stdio.js +41 -0
- package/src/mcp/stdioTransport.js +46 -0
- package/src/mcp/store.js +23 -0
- package/src/mcp/templates.js +51 -0
- package/src/react/LixSketchCanvas.jsx +4 -0
- package/src/react/components/Toolbar.jsx +84 -7
- package/src/react/components/modals/CommandPalette.jsx +8 -0
- package/src/react/components/modals/WebEmbedModal.jsx +40 -0
- package/src/react/components/sidebars/PaintBucketSidebar.jsx +49 -0
- package/src/react/components/sidebars/PaintbrushSidebar.jsx +1 -1
- package/src/react/store/useSketchStore.js +13 -0
- package/src/react/toolsEnum.js +4 -0
- package/src/shapes/Frame.js +47 -4
- package/src/shapes/ImageShape.js +49 -6
- package/src/tools/lassoTool.js +84 -0
- package/src/tools/paintBucketTool.js +50 -0
- package/src/tools/shapeRecognitionTool.js +431 -0
- package/src/tools/webEmbedTool.js +61 -0
- package/dist/react/EventDispatcher-GKNO2KSL.js +0 -464
- package/dist/react/EventDispatcher-GKNO2KSL.js.map +0 -7
- package/dist/react/Frame-RLSMJJSK.js +0 -11
- package/dist/react/IconShape-7OPXAKLK.js +0 -10
- package/dist/react/ImageShape-T7UEHP4A.js +0 -10
- package/dist/react/Line-WWQFBNX5.js +0 -10
- package/dist/react/SceneSerializer-RDISX4X7.js.map +0 -7
- package/dist/react/chunk-AH4PWNEB.js.map +0 -7
- package/dist/react/chunk-EDSKEM6E.js.map +0 -7
- package/dist/react/chunk-KVAQPCUH.js.map +0 -7
- package/dist/react/chunk-U3TB4KRS.js.map +0 -7
- /package/dist/react/{CopyPaste-5OWPTCQ5.js.map → CopyPaste-YUDZ6DHY.js.map} +0 -0
- /package/dist/react/{Frame-RLSMJJSK.js.map → Frame-7D2MXCFF.js.map} +0 -0
- /package/dist/react/{IconShape-7OPXAKLK.js.map → IconShape-ZADX7Y33.js.map} +0 -0
- /package/dist/react/{ImageShape-T7UEHP4A.js.map → ImageShape-UJQN2HI7.js.map} +0 -0
- /package/dist/react/{Line-WWQFBNX5.js.map → Line-APEULMHE.js.map} +0 -0
- /package/dist/react/{Selection-ZL3G6IAO.js.map → Selection-2TSH3J6P.js.map} +0 -0
- /package/dist/react/{UndoRedo-NL7KLR5B.js.map → UndoRedo-IN4SXDG6.js.map} +0 -0
- /package/dist/react/{arrowTool-CNVGM6RX.js.map → arrowTool-OYDWJGQK.js.map} +0 -0
- /package/dist/react/{chunk-4BLMNGTR.js.map → chunk-7CM5XQDN.js.map} +0 -0
- /package/dist/react/{chunk-XFQECTTF.js.map → chunk-APTOPAOY.js.map} +0 -0
- /package/dist/react/{chunk-4TAS67SL.js.map → chunk-EOURRJ55.js.map} +0 -0
- /package/dist/react/{chunk-ETAAQUUV.js.map → chunk-GQUZPON4.js.map} +0 -0
- /package/dist/react/{chunk-GC3KTQDA.js.map → chunk-LJR7EVW2.js.map} +0 -0
- /package/dist/react/{chunk-SZD7DKYJ.js.map → chunk-LSHZYN77.js.map} +0 -0
- /package/dist/react/{chunk-HFQZYCHJ.js.map → chunk-M6TMN76K.js.map} +0 -0
- /package/dist/react/{chunk-V2QTYSBK.js.map → chunk-OP56XPWF.js.map} +0 -0
- /package/dist/react/{chunk-ILGAFR56.js.map → chunk-RGMDWLRJ.js.map} +0 -0
- /package/dist/react/{chunk-OFGJJKPH.js.map → chunk-XFL4R5ZF.js.map} +0 -0
- /package/dist/react/{chunk-GPIYXREE.js.map → chunk-XOWNCYE4.js.map} +0 -0
- /package/dist/react/{chunk-YF3TK7SC.js.map → chunk-XYUFEIZR.js.map} +0 -0
- /package/dist/react/{circleTool-KICNRQCI.js.map → circleTool-LDKGZALF.js.map} +0 -0
- /package/dist/react/{codeTool-NCQ73R6M.js.map → codeTool-4YZO5W7J.js.map} +0 -0
- /package/dist/react/{frameTool-Y6KB67DO.js.map → frameTool-MXNJEXQQ.js.map} +0 -0
- /package/dist/react/{freehandTool-MMULHCQ7.js.map → freehandTool-26D3FOOX.js.map} +0 -0
- /package/dist/react/{iconTool-LSW2DYGB.js.map → iconTool-46O5VEUX.js.map} +0 -0
- /package/dist/react/{imageTool-2DSR32RX.js.map → imageTool-P2RWZRHO.js.map} +0 -0
- /package/dist/react/{lineTool-N5I7IGT7.js.map → lineTool-ZMR27U5L.js.map} +0 -0
- /package/dist/react/{rectangleTool-YUT7ZK2E.js.map → rectangleTool-EJKK6UTX.js.map} +0 -0
- /package/dist/react/{textTool-JMTX7OVT.js.map → textTool-S4XXZHZH.js.map} +0 -0
|
@@ -0,0 +1,1097 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
enterEditMode,
|
|
4
|
+
handleTextMouseDown,
|
|
5
|
+
handleTextMouseMove,
|
|
6
|
+
handleTextMouseUp
|
|
7
|
+
} from "./chunk-GQUZPON4.js";
|
|
8
|
+
import {
|
|
9
|
+
handleCodeMouseDown,
|
|
10
|
+
handleCodeMouseMove,
|
|
11
|
+
handleCodeMouseUp
|
|
12
|
+
} from "./chunk-M6TMN76K.js";
|
|
13
|
+
import {
|
|
14
|
+
handleMouseDownImage,
|
|
15
|
+
handleMouseMoveImage,
|
|
16
|
+
handleMouseUpImage
|
|
17
|
+
} from "./chunk-LJR7EVW2.js";
|
|
18
|
+
import {
|
|
19
|
+
handleMouseDownIcon,
|
|
20
|
+
handleMouseMoveIcon,
|
|
21
|
+
handleMouseUpIcon
|
|
22
|
+
} from "./chunk-APTOPAOY.js";
|
|
23
|
+
import {
|
|
24
|
+
handleMouseDown as handleMouseDown4,
|
|
25
|
+
handleMouseMove as handleMouseMove4,
|
|
26
|
+
handleMouseUp as handleMouseUp4
|
|
27
|
+
} from "./chunk-LSHZYN77.js";
|
|
28
|
+
import {
|
|
29
|
+
handleMouseDown as handleMouseDown5,
|
|
30
|
+
handleMouseMove as handleMouseMove5,
|
|
31
|
+
handleMouseUp as handleMouseUp5
|
|
32
|
+
} from "./chunk-XOWNCYE4.js";
|
|
33
|
+
import {
|
|
34
|
+
handleMultiSelectionMouseDown,
|
|
35
|
+
handleMultiSelectionMouseMove,
|
|
36
|
+
handleMultiSelectionMouseUp,
|
|
37
|
+
isMultiSelecting,
|
|
38
|
+
multiSelection,
|
|
39
|
+
removeMultiSelectionRect
|
|
40
|
+
} from "./chunk-K5RY4EV7.js";
|
|
41
|
+
import {
|
|
42
|
+
Frame
|
|
43
|
+
} from "./chunk-K5BG5MHY.js";
|
|
44
|
+
import {
|
|
45
|
+
handleMouseDownRect,
|
|
46
|
+
handleMouseMoveRect,
|
|
47
|
+
handleMouseUpRect
|
|
48
|
+
} from "./chunk-7CM5XQDN.js";
|
|
49
|
+
import {
|
|
50
|
+
handleMouseDown as handleMouseDown2,
|
|
51
|
+
handleMouseMove as handleMouseMove2,
|
|
52
|
+
handleMouseUp as handleMouseUp2
|
|
53
|
+
} from "./chunk-XFL4R5ZF.js";
|
|
54
|
+
import {
|
|
55
|
+
handleMouseDown as handleMouseDown3,
|
|
56
|
+
handleMouseMove as handleMouseMove3,
|
|
57
|
+
handleMouseUp as handleMouseUp3
|
|
58
|
+
} from "./chunk-RGMDWLRJ.js";
|
|
59
|
+
import {
|
|
60
|
+
normalizeWebEmbedUrl
|
|
61
|
+
} from "./chunk-QZI4UIE5.js";
|
|
62
|
+
import "./chunk-DNAG7ML6.js";
|
|
63
|
+
import "./chunk-PAKA6HUX.js";
|
|
64
|
+
import {
|
|
65
|
+
handleMouseDown,
|
|
66
|
+
handleMouseMove,
|
|
67
|
+
handleMouseUp
|
|
68
|
+
} from "./chunk-XYUFEIZR.js";
|
|
69
|
+
import {
|
|
70
|
+
pushCreateAction,
|
|
71
|
+
pushFrameAttachmentAction,
|
|
72
|
+
pushOptionsChangeAction
|
|
73
|
+
} from "./chunk-6GPEWDRB.js";
|
|
74
|
+
|
|
75
|
+
// src/tools/shapeRecognitionTool.js
|
|
76
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
77
|
+
var MAX_POINTS = 96;
|
|
78
|
+
var MIN_SCREEN_SAMPLE_PX = 4;
|
|
79
|
+
var MIN_SHAPE_SIZE = 8;
|
|
80
|
+
var drawing = false;
|
|
81
|
+
var points = [];
|
|
82
|
+
var previewPath = null;
|
|
83
|
+
var previewFrame = 0;
|
|
84
|
+
var latestPrediction = null;
|
|
85
|
+
function getThemeStroke() {
|
|
86
|
+
return document.body?.classList.contains("theme-dark") ? "#f7f4ff" : "#211a33";
|
|
87
|
+
}
|
|
88
|
+
function getSVGPoint(event) {
|
|
89
|
+
const viewBox = svg.viewBox.baseVal;
|
|
90
|
+
const rect = svg.getBoundingClientRect();
|
|
91
|
+
return {
|
|
92
|
+
x: viewBox.x + (event.clientX - rect.left) / rect.width * viewBox.width,
|
|
93
|
+
y: viewBox.y + (event.clientY - rect.top) / rect.height * viewBox.height,
|
|
94
|
+
pressure: event.pressure || 0.5
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function distance(a, b) {
|
|
98
|
+
return Math.hypot(b.x - a.x, b.y - a.y);
|
|
99
|
+
}
|
|
100
|
+
function orientedBounds(sample, angle) {
|
|
101
|
+
const cos = Math.cos(angle);
|
|
102
|
+
const sin = Math.sin(angle);
|
|
103
|
+
let minU = Infinity;
|
|
104
|
+
let maxU = -Infinity;
|
|
105
|
+
let minV = Infinity;
|
|
106
|
+
let maxV = -Infinity;
|
|
107
|
+
for (const point of sample) {
|
|
108
|
+
const u = point.x * cos + point.y * sin;
|
|
109
|
+
const v = -point.x * sin + point.y * cos;
|
|
110
|
+
minU = Math.min(minU, u);
|
|
111
|
+
maxU = Math.max(maxU, u);
|
|
112
|
+
minV = Math.min(minV, v);
|
|
113
|
+
maxV = Math.max(maxV, v);
|
|
114
|
+
}
|
|
115
|
+
const centerU = (minU + maxU) / 2;
|
|
116
|
+
const centerV = (minV + maxV) / 2;
|
|
117
|
+
return {
|
|
118
|
+
center: {
|
|
119
|
+
x: centerU * cos - centerV * sin,
|
|
120
|
+
y: centerU * sin + centerV * cos
|
|
121
|
+
},
|
|
122
|
+
width: Math.max(MIN_SHAPE_SIZE, maxU - minU),
|
|
123
|
+
height: Math.max(MIN_SHAPE_SIZE, maxV - minV),
|
|
124
|
+
angle,
|
|
125
|
+
minU,
|
|
126
|
+
maxU,
|
|
127
|
+
minV,
|
|
128
|
+
maxV
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function principalAngle(sample) {
|
|
132
|
+
let meanX = 0;
|
|
133
|
+
let meanY = 0;
|
|
134
|
+
for (const point of sample) {
|
|
135
|
+
meanX += point.x;
|
|
136
|
+
meanY += point.y;
|
|
137
|
+
}
|
|
138
|
+
meanX /= sample.length;
|
|
139
|
+
meanY /= sample.length;
|
|
140
|
+
let xx = 0;
|
|
141
|
+
let yy = 0;
|
|
142
|
+
let xy = 0;
|
|
143
|
+
for (const point of sample) {
|
|
144
|
+
const dx = point.x - meanX;
|
|
145
|
+
const dy = point.y - meanY;
|
|
146
|
+
xx += dx * dx;
|
|
147
|
+
yy += dy * dy;
|
|
148
|
+
xy += dx * dy;
|
|
149
|
+
}
|
|
150
|
+
if (Math.abs(xx - yy) + Math.abs(xy) < 1e-3) return 0;
|
|
151
|
+
return Math.atan2(2 * xy, xx - yy) / 2;
|
|
152
|
+
}
|
|
153
|
+
function rectangleAngle(sample) {
|
|
154
|
+
let x = 0;
|
|
155
|
+
let y = 0;
|
|
156
|
+
for (let index = 1; index < sample.length; index += 1) {
|
|
157
|
+
const dx = sample[index].x - sample[index - 1].x;
|
|
158
|
+
const dy = sample[index].y - sample[index - 1].y;
|
|
159
|
+
const length = Math.hypot(dx, dy);
|
|
160
|
+
if (length === 0) continue;
|
|
161
|
+
const angle = Math.atan2(dy, dx) * 4;
|
|
162
|
+
x += Math.cos(angle) * length;
|
|
163
|
+
y += Math.sin(angle) * length;
|
|
164
|
+
}
|
|
165
|
+
return Math.atan2(y, x) / 4;
|
|
166
|
+
}
|
|
167
|
+
function closedShapePrediction(sample, pathLength) {
|
|
168
|
+
const rectBounds = orientedBounds(sample, rectangleAngle(sample));
|
|
169
|
+
const ellipseBounds = orientedBounds(sample, principalAngle(sample));
|
|
170
|
+
let rectangleError = 0;
|
|
171
|
+
let ellipseError = 0;
|
|
172
|
+
const rectCos = Math.cos(rectBounds.angle);
|
|
173
|
+
const rectSin = Math.sin(rectBounds.angle);
|
|
174
|
+
const ellipseCos = Math.cos(ellipseBounds.angle);
|
|
175
|
+
const ellipseSin = Math.sin(ellipseBounds.angle);
|
|
176
|
+
const rectHalfW = rectBounds.width / 2;
|
|
177
|
+
const rectHalfH = rectBounds.height / 2;
|
|
178
|
+
const ellipseHalfW = ellipseBounds.width / 2;
|
|
179
|
+
const ellipseHalfH = ellipseBounds.height / 2;
|
|
180
|
+
for (const point of sample) {
|
|
181
|
+
const rectDx = point.x - rectBounds.center.x;
|
|
182
|
+
const rectDy = point.y - rectBounds.center.y;
|
|
183
|
+
const rectU = Math.abs(rectDx * rectCos + rectDy * rectSin) / rectHalfW;
|
|
184
|
+
const rectV = Math.abs(-rectDx * rectSin + rectDy * rectCos) / rectHalfH;
|
|
185
|
+
rectangleError += Math.min(Math.abs(1 - rectU), Math.abs(1 - rectV));
|
|
186
|
+
const ellipseDx = point.x - ellipseBounds.center.x;
|
|
187
|
+
const ellipseDy = point.y - ellipseBounds.center.y;
|
|
188
|
+
const ellipseU = (ellipseDx * ellipseCos + ellipseDy * ellipseSin) / ellipseHalfW;
|
|
189
|
+
const ellipseV = (-ellipseDx * ellipseSin + ellipseDy * ellipseCos) / ellipseHalfH;
|
|
190
|
+
ellipseError += Math.abs(1 - Math.hypot(ellipseU, ellipseV));
|
|
191
|
+
}
|
|
192
|
+
rectangleError /= sample.length;
|
|
193
|
+
ellipseError /= sample.length;
|
|
194
|
+
const rectangle = rectangleError <= ellipseError * 1.08;
|
|
195
|
+
const bestError = rectangle ? rectangleError : ellipseError;
|
|
196
|
+
if (bestError > 0.24) {
|
|
197
|
+
return { type: "freehand", points: sample.map((point) => ({ ...point })), pathLength };
|
|
198
|
+
}
|
|
199
|
+
const bounds = rectangle ? rectBounds : ellipseBounds;
|
|
200
|
+
return {
|
|
201
|
+
type: rectangle ? "rectangle" : "circle",
|
|
202
|
+
...bounds,
|
|
203
|
+
pathLength
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function predictDrawnShape(sample) {
|
|
207
|
+
if (!Array.isArray(sample) || sample.length < 2) return null;
|
|
208
|
+
const start2 = sample[0];
|
|
209
|
+
let pathLength = 0;
|
|
210
|
+
let farthestIndex = 1;
|
|
211
|
+
let farthestDistance = 0;
|
|
212
|
+
let minX = start2.x;
|
|
213
|
+
let maxX = start2.x;
|
|
214
|
+
let minY = start2.y;
|
|
215
|
+
let maxY = start2.y;
|
|
216
|
+
for (let index = 1; index < sample.length; index += 1) {
|
|
217
|
+
pathLength += distance(sample[index - 1], sample[index]);
|
|
218
|
+
const fromStart = distance(start2, sample[index]);
|
|
219
|
+
if (fromStart > farthestDistance) {
|
|
220
|
+
farthestDistance = fromStart;
|
|
221
|
+
farthestIndex = index;
|
|
222
|
+
}
|
|
223
|
+
minX = Math.min(minX, sample[index].x);
|
|
224
|
+
maxX = Math.max(maxX, sample[index].x);
|
|
225
|
+
minY = Math.min(minY, sample[index].y);
|
|
226
|
+
maxY = Math.max(maxY, sample[index].y);
|
|
227
|
+
}
|
|
228
|
+
const diagonal = Math.max(MIN_SHAPE_SIZE, Math.hypot(maxX - minX, maxY - minY));
|
|
229
|
+
const end = sample[sample.length - 1];
|
|
230
|
+
const closed = sample.length >= 8 && distance(start2, end) <= diagonal * 0.28 && pathLength >= diagonal * 2.05;
|
|
231
|
+
if (closed) return closedShapePrediction(sample, pathLength);
|
|
232
|
+
const tip = sample[farthestIndex];
|
|
233
|
+
let afterTipLength = 0;
|
|
234
|
+
for (let index = farthestIndex + 1; index < sample.length; index += 1) {
|
|
235
|
+
afterTipLength += distance(sample[index - 1], sample[index]);
|
|
236
|
+
}
|
|
237
|
+
let shaftLength = 0;
|
|
238
|
+
for (let index = 1; index <= farthestIndex; index += 1) {
|
|
239
|
+
shaftLength += distance(sample[index - 1], sample[index]);
|
|
240
|
+
}
|
|
241
|
+
const arrow = farthestIndex >= Math.floor(sample.length * 0.45) && farthestIndex < sample.length - 2 && afterTipLength >= diagonal * 0.18 && distance(end, tip) <= diagonal * 0.48 && farthestDistance / Math.max(shaftLength, 1) >= 0.86;
|
|
242
|
+
const directDistance = distance(start2, end);
|
|
243
|
+
const line = !arrow && directDistance / Math.max(pathLength, 1) >= 0.92;
|
|
244
|
+
if (!arrow && !line) {
|
|
245
|
+
return { type: "freehand", points: sample.map((point) => ({ ...point })), pathLength };
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
type: arrow ? "arrow" : "line",
|
|
249
|
+
start: { ...start2 },
|
|
250
|
+
end: arrow ? { ...tip } : { ...end },
|
|
251
|
+
width: Math.max(MIN_SHAPE_SIZE, maxX - minX),
|
|
252
|
+
height: Math.max(MIN_SHAPE_SIZE, maxY - minY),
|
|
253
|
+
pathLength
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function rotatedPoint(center, x, y, angle) {
|
|
257
|
+
const cos = Math.cos(angle);
|
|
258
|
+
const sin = Math.sin(angle);
|
|
259
|
+
return { x: center.x + x * cos - y * sin, y: center.y + x * sin + y * cos };
|
|
260
|
+
}
|
|
261
|
+
function pathForPrediction(prediction) {
|
|
262
|
+
if (!prediction) return "";
|
|
263
|
+
if (prediction.type === "rectangle") {
|
|
264
|
+
const halfW = prediction.width / 2;
|
|
265
|
+
const halfH = prediction.height / 2;
|
|
266
|
+
const corners = [
|
|
267
|
+
rotatedPoint(prediction.center, -halfW, -halfH, prediction.angle),
|
|
268
|
+
rotatedPoint(prediction.center, halfW, -halfH, prediction.angle),
|
|
269
|
+
rotatedPoint(prediction.center, halfW, halfH, prediction.angle),
|
|
270
|
+
rotatedPoint(prediction.center, -halfW, halfH, prediction.angle)
|
|
271
|
+
];
|
|
272
|
+
return `M ${corners[0].x} ${corners[0].y} L ${corners[1].x} ${corners[1].y} L ${corners[2].x} ${corners[2].y} L ${corners[3].x} ${corners[3].y} Z`;
|
|
273
|
+
}
|
|
274
|
+
if (prediction.type === "circle") {
|
|
275
|
+
const rx = prediction.width / 2;
|
|
276
|
+
const ry = prediction.height / 2;
|
|
277
|
+
const start3 = rotatedPoint(prediction.center, rx, 0, prediction.angle);
|
|
278
|
+
const opposite = rotatedPoint(prediction.center, -rx, 0, prediction.angle);
|
|
279
|
+
const rotation = prediction.angle * 180 / Math.PI;
|
|
280
|
+
return `M ${start3.x} ${start3.y} A ${rx} ${ry} ${rotation} 1 0 ${opposite.x} ${opposite.y} A ${rx} ${ry} ${rotation} 1 0 ${start3.x} ${start3.y}`;
|
|
281
|
+
}
|
|
282
|
+
if (prediction.type === "freehand") {
|
|
283
|
+
if (!prediction.points.length) return "";
|
|
284
|
+
return prediction.points.reduce((path2, point, index) => `${path2}${index === 0 ? "M" : " L"} ${point.x} ${point.y}`, "");
|
|
285
|
+
}
|
|
286
|
+
const { start: start2, end } = prediction;
|
|
287
|
+
let path = `M ${start2.x} ${start2.y} L ${end.x} ${end.y}`;
|
|
288
|
+
if (prediction.type === "arrow") {
|
|
289
|
+
const angle = Math.atan2(end.y - start2.y, end.x - start2.x);
|
|
290
|
+
const head = Math.min(24 / (window.currentZoom || 1), distance(start2, end) * 0.25);
|
|
291
|
+
const left = rotatedPoint(end, -head, head * 0.55, angle);
|
|
292
|
+
const right = rotatedPoint(end, -head, -head * 0.55, angle);
|
|
293
|
+
path += ` M ${left.x} ${left.y} L ${end.x} ${end.y} L ${right.x} ${right.y}`;
|
|
294
|
+
}
|
|
295
|
+
return path;
|
|
296
|
+
}
|
|
297
|
+
function ensurePreview() {
|
|
298
|
+
if (previewPath?.isConnected) return;
|
|
299
|
+
previewPath = document.createElementNS(SVG_NS, "path");
|
|
300
|
+
previewPath.dataset.recognitionPreview = "true";
|
|
301
|
+
previewPath.setAttribute("fill", "rgba(148, 148, 158, 0.06)");
|
|
302
|
+
previewPath.setAttribute("stroke", "#9696a0");
|
|
303
|
+
previewPath.setAttribute("stroke-width", "2");
|
|
304
|
+
previewPath.setAttribute("stroke-dasharray", "5 7");
|
|
305
|
+
previewPath.setAttribute("stroke-linecap", "round");
|
|
306
|
+
previewPath.setAttribute("stroke-linejoin", "round");
|
|
307
|
+
previewPath.setAttribute("vector-effect", "non-scaling-stroke");
|
|
308
|
+
previewPath.setAttribute("pointer-events", "none");
|
|
309
|
+
svg.appendChild(previewPath);
|
|
310
|
+
}
|
|
311
|
+
function renderPreview() {
|
|
312
|
+
previewFrame = 0;
|
|
313
|
+
if (!drawing) return;
|
|
314
|
+
latestPrediction = predictDrawnShape(points);
|
|
315
|
+
ensurePreview();
|
|
316
|
+
previewPath.setAttribute("d", pathForPrediction(latestPrediction));
|
|
317
|
+
previewPath.setAttribute("fill", latestPrediction?.type === "rectangle" || latestPrediction?.type === "circle" ? "rgba(148, 148, 158, 0.06)" : "none");
|
|
318
|
+
}
|
|
319
|
+
function schedulePreview() {
|
|
320
|
+
if (!previewFrame) previewFrame = requestAnimationFrame(renderPreview);
|
|
321
|
+
}
|
|
322
|
+
function cleanupPreview() {
|
|
323
|
+
if (previewFrame) cancelAnimationFrame(previewFrame);
|
|
324
|
+
previewFrame = 0;
|
|
325
|
+
previewPath?.remove();
|
|
326
|
+
previewPath = null;
|
|
327
|
+
}
|
|
328
|
+
function currentStyle() {
|
|
329
|
+
const settings = window.freehandToolSettings || {};
|
|
330
|
+
const outline = settings.strokeStyle || "solid";
|
|
331
|
+
return {
|
|
332
|
+
stroke: settings.strokeColor || getThemeStroke(),
|
|
333
|
+
fill: "transparent",
|
|
334
|
+
fillStyle: "none",
|
|
335
|
+
strokeWidth: settings.strokeWidth || 2,
|
|
336
|
+
strokeDasharray: outline === "dashed" ? "10,10" : outline === "dotted" ? "2,8" : "",
|
|
337
|
+
outline
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
function attachToContainingFrame(shape) {
|
|
341
|
+
for (let index = shapes.length - 1; index >= 0; index -= 1) {
|
|
342
|
+
const frame2 = shapes[index];
|
|
343
|
+
if (frame2.shapeName !== "frame" || typeof frame2.isShapeInFrame !== "function") continue;
|
|
344
|
+
if (!frame2.isShapeInFrame(shape)) continue;
|
|
345
|
+
frame2.addShapeToFrame(shape);
|
|
346
|
+
pushFrameAttachmentAction(frame2, shape, "attach", null);
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
function createPredictedShape(prediction) {
|
|
351
|
+
if (!prediction) return null;
|
|
352
|
+
const style = currentStyle();
|
|
353
|
+
let shape = null;
|
|
354
|
+
if (prediction.type === "rectangle") {
|
|
355
|
+
shape = new window.Rectangle(
|
|
356
|
+
prediction.center.x - prediction.width / 2,
|
|
357
|
+
prediction.center.y - prediction.height / 2,
|
|
358
|
+
prediction.width,
|
|
359
|
+
prediction.height,
|
|
360
|
+
style
|
|
361
|
+
);
|
|
362
|
+
shape.rotation = prediction.angle * 180 / Math.PI;
|
|
363
|
+
shape.draw();
|
|
364
|
+
} else if (prediction.type === "circle") {
|
|
365
|
+
shape = new window.Circle(
|
|
366
|
+
prediction.center.x,
|
|
367
|
+
prediction.center.y,
|
|
368
|
+
prediction.width / 2,
|
|
369
|
+
prediction.height / 2,
|
|
370
|
+
style
|
|
371
|
+
);
|
|
372
|
+
shape.rotation = prediction.angle * 180 / Math.PI;
|
|
373
|
+
shape.draw();
|
|
374
|
+
} else if (prediction.type === "freehand") {
|
|
375
|
+
const brush = window.freehandToolSettings || {};
|
|
376
|
+
shape = new window.FreehandStroke(
|
|
377
|
+
prediction.points.map((point) => [point.x, point.y, point.pressure || 0.5]),
|
|
378
|
+
{
|
|
379
|
+
stroke: style.stroke,
|
|
380
|
+
strokeWidth: style.strokeWidth,
|
|
381
|
+
strokeStyle: style.outline,
|
|
382
|
+
thinning: brush.thinning ?? 0.5,
|
|
383
|
+
roughness: brush.roughness || "smooth",
|
|
384
|
+
strokeOpacity: brush.opacity ?? 1
|
|
385
|
+
}
|
|
386
|
+
);
|
|
387
|
+
} else if (prediction.type === "arrow") {
|
|
388
|
+
shape = new window.Arrow(prediction.start, prediction.end, {
|
|
389
|
+
stroke: style.stroke,
|
|
390
|
+
strokeWidth: style.strokeWidth,
|
|
391
|
+
arrowOutlineStyle: style.outline,
|
|
392
|
+
arrowCurved: "straight"
|
|
393
|
+
});
|
|
394
|
+
} else {
|
|
395
|
+
shape = new window.Line(prediction.start, prediction.end, {
|
|
396
|
+
stroke: style.stroke,
|
|
397
|
+
strokeWidth: style.strokeWidth,
|
|
398
|
+
strokeDasharray: style.strokeDasharray,
|
|
399
|
+
roughness: 1.5,
|
|
400
|
+
bowing: 1
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
shapes.push(shape);
|
|
404
|
+
pushCreateAction(shape);
|
|
405
|
+
attachToContainingFrame(shape);
|
|
406
|
+
return shape;
|
|
407
|
+
}
|
|
408
|
+
function handleShapeRecognitionDown(event) {
|
|
409
|
+
if (!window.isShapeRecognitionToolActive || event.button !== 0) return;
|
|
410
|
+
drawing = true;
|
|
411
|
+
points = [getSVGPoint(event)];
|
|
412
|
+
latestPrediction = null;
|
|
413
|
+
ensurePreview();
|
|
414
|
+
schedulePreview();
|
|
415
|
+
}
|
|
416
|
+
function handleShapeRecognitionMove(event) {
|
|
417
|
+
if (!drawing || !window.isShapeRecognitionToolActive) return;
|
|
418
|
+
const point = getSVGPoint(event);
|
|
419
|
+
const last = points[points.length - 1];
|
|
420
|
+
const threshold = MIN_SCREEN_SAMPLE_PX / (window.currentZoom || 1);
|
|
421
|
+
if (distance(last, point) < threshold) return;
|
|
422
|
+
if (points.length < MAX_POINTS) {
|
|
423
|
+
points.push(point);
|
|
424
|
+
} else {
|
|
425
|
+
points = [points[0], ...points.slice(2).filter((_, index) => index % 2 === 0), point];
|
|
426
|
+
}
|
|
427
|
+
schedulePreview();
|
|
428
|
+
}
|
|
429
|
+
function handleShapeRecognitionUp(event) {
|
|
430
|
+
if (!drawing) return;
|
|
431
|
+
drawing = false;
|
|
432
|
+
const rect = svg.getBoundingClientRect();
|
|
433
|
+
if (event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom) {
|
|
434
|
+
const point = getSVGPoint(event);
|
|
435
|
+
if (distance(points[points.length - 1], point) > 0) points.push(point);
|
|
436
|
+
}
|
|
437
|
+
latestPrediction = predictDrawnShape(points);
|
|
438
|
+
cleanupPreview();
|
|
439
|
+
const prediction = latestPrediction;
|
|
440
|
+
points = [];
|
|
441
|
+
latestPrediction = null;
|
|
442
|
+
if (!prediction || prediction.pathLength < MIN_SHAPE_SIZE) return;
|
|
443
|
+
const shape = createPredictedShape(prediction);
|
|
444
|
+
if (!shape) return;
|
|
445
|
+
if (window.__sketchStoreApi) window.__sketchStoreApi.setActiveTool("select", { afterDraw: true });
|
|
446
|
+
currentShape = shape;
|
|
447
|
+
if (shape.shapeName === "freehandStroke" && typeof shape.selectStroke === "function") {
|
|
448
|
+
shape.selectStroke();
|
|
449
|
+
} else {
|
|
450
|
+
shape.isSelected = true;
|
|
451
|
+
if (typeof shape.addAnchors === "function") shape.addAnchors();
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
function cancelShapeRecognition() {
|
|
455
|
+
drawing = false;
|
|
456
|
+
points = [];
|
|
457
|
+
latestPrediction = null;
|
|
458
|
+
cleanupPreview();
|
|
459
|
+
}
|
|
460
|
+
window.__cancelShapeRecognition = cancelShapeRecognition;
|
|
461
|
+
|
|
462
|
+
// src/tools/paintBucketTool.js
|
|
463
|
+
var CLOSED_SHAPES = /* @__PURE__ */ new Set(["rectangle", "circle"]);
|
|
464
|
+
window.paintBucketSettings = window.paintBucketSettings || {
|
|
465
|
+
fillColor: "#A98DEB",
|
|
466
|
+
fillStyle: "solid"
|
|
467
|
+
};
|
|
468
|
+
function getSVGPoint2(event) {
|
|
469
|
+
const viewBox = svg.viewBox.baseVal;
|
|
470
|
+
const rect = svg.getBoundingClientRect();
|
|
471
|
+
return {
|
|
472
|
+
x: viewBox.x + (event.clientX - rect.left) / rect.width * viewBox.width,
|
|
473
|
+
y: viewBox.y + (event.clientY - rect.top) / rect.height * viewBox.height
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
function findClosedShapeAt(x, y) {
|
|
477
|
+
for (let index = shapes.length - 1; index >= 0; index -= 1) {
|
|
478
|
+
const shape = shapes[index];
|
|
479
|
+
if (!CLOSED_SHAPES.has(shape?.shapeName) || typeof shape.contains !== "function") continue;
|
|
480
|
+
if (shape.contains(x, y)) return shape;
|
|
481
|
+
}
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
function handlePaintBucketDown(event) {
|
|
485
|
+
if (!window.isPaintBucketToolActive || event.button !== 0) return;
|
|
486
|
+
const { x, y } = getSVGPoint2(event);
|
|
487
|
+
const shape = findClosedShapeAt(x, y);
|
|
488
|
+
if (!shape) {
|
|
489
|
+
window.dispatchEvent(new CustomEvent("lixsketch:bucket-miss"));
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
const settings = window.paintBucketSettings;
|
|
493
|
+
const transparent = settings.fillStyle === "none" || settings.fillStyle === "transparent";
|
|
494
|
+
const nextFill = transparent ? "transparent" : settings.fillColor;
|
|
495
|
+
const nextStyle = transparent ? "none" : settings.fillStyle;
|
|
496
|
+
if (shape.options.fill === nextFill && shape.options.fillStyle === nextStyle) return;
|
|
497
|
+
const oldOptions = { ...shape.options };
|
|
498
|
+
const newOptions = { ...shape.options, fill: nextFill, fillStyle: nextStyle };
|
|
499
|
+
pushOptionsChangeAction(shape, oldOptions, newOptions);
|
|
500
|
+
shape.options = newOptions;
|
|
501
|
+
shape.draw();
|
|
502
|
+
window.dispatchEvent(new CustomEvent("lixsketch:bucket-filled", { detail: { shapeID: shape.shapeID } }));
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// src/tools/lassoTool.js
|
|
506
|
+
var MAX_POINTS2 = 192;
|
|
507
|
+
var MIN_SAMPLE_PX = 4;
|
|
508
|
+
var points2 = [];
|
|
509
|
+
var preview = null;
|
|
510
|
+
var drawing2 = false;
|
|
511
|
+
function coords(e) {
|
|
512
|
+
const vb = svg.viewBox.baseVal;
|
|
513
|
+
const rect = svg.getBoundingClientRect();
|
|
514
|
+
return { x: vb.x + (e.clientX - rect.left) / rect.width * vb.width, y: vb.y + (e.clientY - rect.top) / rect.height * vb.height };
|
|
515
|
+
}
|
|
516
|
+
function pointInPolygon(point, polygon) {
|
|
517
|
+
let inside = false;
|
|
518
|
+
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
|
519
|
+
const a = polygon[i], b = polygon[j];
|
|
520
|
+
if (a.y > point.y !== b.y > point.y && point.x < (b.x - a.x) * (point.y - a.y) / (b.y - a.y || Number.EPSILON) + a.x) inside = !inside;
|
|
521
|
+
}
|
|
522
|
+
return inside;
|
|
523
|
+
}
|
|
524
|
+
function boundsPoints(shape) {
|
|
525
|
+
if ((shape.shapeName === "line" || shape.shapeName === "arrow") && shape.startPoint && shape.endPoint) return [shape.startPoint, shape.endPoint];
|
|
526
|
+
if (shape.shapeName === "freehandStroke" && Array.isArray(shape.points)) {
|
|
527
|
+
const step = Math.max(1, Math.ceil(shape.points.length / 16));
|
|
528
|
+
return shape.points.filter((_, i) => i % step === 0).map((p) => ({ x: p[0], y: p[1] }));
|
|
529
|
+
}
|
|
530
|
+
let x = shape.x || 0, y = shape.y || 0, width = shape.width || 0, height = shape.height || 0;
|
|
531
|
+
if (shape.shapeName === "circle") {
|
|
532
|
+
x = shape.x - shape.rx;
|
|
533
|
+
y = shape.y - shape.ry;
|
|
534
|
+
width = shape.rx * 2;
|
|
535
|
+
height = shape.ry * 2;
|
|
536
|
+
}
|
|
537
|
+
if ((!width || !height) && shape.group?.getBBox) {
|
|
538
|
+
try {
|
|
539
|
+
const box = shape.group.getBBox();
|
|
540
|
+
x = box.x;
|
|
541
|
+
y = box.y;
|
|
542
|
+
width = box.width;
|
|
543
|
+
height = box.height;
|
|
544
|
+
} catch {
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
const raw = [{ x, y }, { x: x + width, y }, { x: x + width, y: y + height }, { x, y: y + height }, { x: x + width / 2, y: y + height / 2 }];
|
|
548
|
+
const rotation = Number(shape.rotation) || 0;
|
|
549
|
+
if (!rotation) return raw;
|
|
550
|
+
const cx = x + width / 2, cy = y + height / 2, angle = rotation * Math.PI / 180;
|
|
551
|
+
return raw.map((p) => ({ x: cx + (p.x - cx) * Math.cos(angle) - (p.y - cy) * Math.sin(angle), y: cy + (p.x - cx) * Math.sin(angle) + (p.y - cy) * Math.cos(angle) }));
|
|
552
|
+
}
|
|
553
|
+
function cleanup() {
|
|
554
|
+
preview?.remove();
|
|
555
|
+
preview = null;
|
|
556
|
+
points2 = [];
|
|
557
|
+
drawing2 = false;
|
|
558
|
+
}
|
|
559
|
+
function handleLassoDown(e) {
|
|
560
|
+
if (!window.isLassoToolActive) return;
|
|
561
|
+
cleanup();
|
|
562
|
+
multiSelection.clearSelection();
|
|
563
|
+
drawing2 = true;
|
|
564
|
+
points2 = [coords(e)];
|
|
565
|
+
preview = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
566
|
+
preview.setAttribute("fill", "rgba(139, 118, 214, .10)");
|
|
567
|
+
preview.setAttribute("stroke", "#a78bfa");
|
|
568
|
+
preview.setAttribute("stroke-dasharray", "5 4");
|
|
569
|
+
preview.setAttribute("vector-effect", "non-scaling-stroke");
|
|
570
|
+
preview.style.pointerEvents = "none";
|
|
571
|
+
svg.appendChild(preview);
|
|
572
|
+
}
|
|
573
|
+
function handleLassoMove(e) {
|
|
574
|
+
if (!drawing2) return;
|
|
575
|
+
const p = coords(e), last = points2[points2.length - 1];
|
|
576
|
+
const min = MIN_SAMPLE_PX / (window.currentZoom || 1);
|
|
577
|
+
if (Math.hypot(p.x - last.x, p.y - last.y) < min) return;
|
|
578
|
+
if (points2.length < MAX_POINTS2) points2.push(p);
|
|
579
|
+
else points2[points2.length - 1] = p;
|
|
580
|
+
preview?.setAttribute("d", `M ${points2.map((v) => `${v.x} ${v.y}`).join(" L ")} Z`);
|
|
581
|
+
}
|
|
582
|
+
function handleLassoUp() {
|
|
583
|
+
if (!drawing2) return;
|
|
584
|
+
const polygon = points2.slice();
|
|
585
|
+
cleanup();
|
|
586
|
+
window.__sketchStoreApi?.setActiveTool("select", { afterDraw: true });
|
|
587
|
+
if (polygon.length >= 3 && Array.isArray(window.shapes)) {
|
|
588
|
+
const selected = window.shapes.filter((shape) => boundsPoints(shape).every((p) => pointInPolygon(p, polygon)));
|
|
589
|
+
const filtered = selected.filter((shape) => !shape.parentFrame || !selected.includes(shape.parentFrame));
|
|
590
|
+
filtered.forEach((shape) => {
|
|
591
|
+
multiSelection.selectedShapes.add(shape);
|
|
592
|
+
shape.isSelected = true;
|
|
593
|
+
});
|
|
594
|
+
if (filtered.length) multiSelection.updateControls();
|
|
595
|
+
window.currentShape = filtered.length === 1 ? filtered[0] : null;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
function cancelLasso() {
|
|
599
|
+
cleanup();
|
|
600
|
+
}
|
|
601
|
+
window.__cancelLasso = cancelLasso;
|
|
602
|
+
|
|
603
|
+
// src/tools/webEmbedTool.js
|
|
604
|
+
var frame = null;
|
|
605
|
+
var start = null;
|
|
606
|
+
function coords2(e) {
|
|
607
|
+
const vb = svg.viewBox.baseVal, rect = svg.getBoundingClientRect();
|
|
608
|
+
return { x: vb.x + (e.clientX - rect.left) / rect.width * vb.width, y: vb.y + (e.clientY - rect.top) / rect.height * vb.height };
|
|
609
|
+
}
|
|
610
|
+
function placeWebEmbed(urlValue) {
|
|
611
|
+
const url = normalizeWebEmbedUrl(urlValue);
|
|
612
|
+
if (!url || typeof svg === "undefined") return null;
|
|
613
|
+
window.__sketchStoreApi?.setActiveTool("select");
|
|
614
|
+
const viewBox = svg.viewBox.baseVal;
|
|
615
|
+
const width = Math.min(640, Math.max(320, viewBox.width * 0.56));
|
|
616
|
+
const height = width * 9 / 16;
|
|
617
|
+
const x = viewBox.x + (viewBox.width - width) / 2;
|
|
618
|
+
const y = viewBox.y + (viewBox.height - height) / 2;
|
|
619
|
+
const placedFrame = new Frame(x, y, width, height, {
|
|
620
|
+
frameName: "Web embed",
|
|
621
|
+
frameType: "web-embed",
|
|
622
|
+
webEmbedURL: url,
|
|
623
|
+
stroke: "#8b76d6",
|
|
624
|
+
strokeWidth: 2
|
|
625
|
+
});
|
|
626
|
+
shapes.push(placedFrame);
|
|
627
|
+
pushCreateAction(placedFrame);
|
|
628
|
+
currentShape = placedFrame;
|
|
629
|
+
placedFrame.selectFrame();
|
|
630
|
+
window.__pendingWebEmbedURL = null;
|
|
631
|
+
return placedFrame;
|
|
632
|
+
}
|
|
633
|
+
function handleWebEmbedDown(e) {
|
|
634
|
+
const url = normalizeWebEmbedUrl(window.__pendingWebEmbedURL);
|
|
635
|
+
if (!window.isWebEmbedToolActive || !url) {
|
|
636
|
+
window.__showWebEmbedModal?.();
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
start = coords2(e);
|
|
640
|
+
frame = new Frame(start.x, start.y, 0, 0, { frameName: "Web embed", frameType: "web-embed", webEmbedURL: url, stroke: "#8b76d6", strokeWidth: 2 });
|
|
641
|
+
shapes.push(frame);
|
|
642
|
+
currentShape = frame;
|
|
643
|
+
}
|
|
644
|
+
function handleWebEmbedMove(e) {
|
|
645
|
+
if (!frame || !start) return;
|
|
646
|
+
const p = coords2(e);
|
|
647
|
+
frame.x = Math.min(start.x, p.x);
|
|
648
|
+
frame.y = Math.min(start.y, p.y);
|
|
649
|
+
frame.width = Math.abs(p.x - start.x);
|
|
650
|
+
frame.height = Math.abs(p.y - start.y);
|
|
651
|
+
frame.draw();
|
|
652
|
+
}
|
|
653
|
+
function handleWebEmbedUp() {
|
|
654
|
+
if (!frame) return;
|
|
655
|
+
if (frame.width < 40 || frame.height < 30) {
|
|
656
|
+
frame.width = 560;
|
|
657
|
+
frame.height = 315;
|
|
658
|
+
}
|
|
659
|
+
frame.draw();
|
|
660
|
+
pushCreateAction(frame);
|
|
661
|
+
const placedFrame = frame;
|
|
662
|
+
window.__pendingWebEmbedURL = null;
|
|
663
|
+
frame = null;
|
|
664
|
+
start = null;
|
|
665
|
+
window.__sketchStoreApi?.setActiveTool("select", { afterDraw: true });
|
|
666
|
+
currentShape = placedFrame;
|
|
667
|
+
placedFrame.selectFrame();
|
|
668
|
+
}
|
|
669
|
+
window.__placeWebEmbed = placeWebEmbed;
|
|
670
|
+
|
|
671
|
+
// src/core/EventDispatcher.js
|
|
672
|
+
var EDGE_THRESHOLD = 40;
|
|
673
|
+
var SCROLL_SPEED = 8;
|
|
674
|
+
var _autoScrollRAF = null;
|
|
675
|
+
function _autoScroll(e) {
|
|
676
|
+
if (!(e.buttons & 1)) {
|
|
677
|
+
_stopAutoScroll();
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
if (typeof currentViewBox === "undefined" || typeof currentZoom === "undefined") return;
|
|
681
|
+
if (typeof isPanning !== "undefined" && isPanning) return;
|
|
682
|
+
if (typeof isPanningToolActive !== "undefined" && isPanningToolActive) return;
|
|
683
|
+
const rect = svg.getBoundingClientRect();
|
|
684
|
+
const mx = e.clientX - rect.left;
|
|
685
|
+
const my = e.clientY - rect.top;
|
|
686
|
+
let dx = 0, dy = 0;
|
|
687
|
+
if (mx < EDGE_THRESHOLD) dx = -SCROLL_SPEED * (1 - mx / EDGE_THRESHOLD);
|
|
688
|
+
else if (mx > rect.width - EDGE_THRESHOLD) dx = SCROLL_SPEED * (1 - (rect.width - mx) / EDGE_THRESHOLD);
|
|
689
|
+
if (my < EDGE_THRESHOLD) dy = -SCROLL_SPEED * (1 - my / EDGE_THRESHOLD);
|
|
690
|
+
else if (my > rect.height - EDGE_THRESHOLD) dy = SCROLL_SPEED * (1 - (rect.height - my) / EDGE_THRESHOLD);
|
|
691
|
+
if (e.clientX < rect.left) dx = -SCROLL_SPEED;
|
|
692
|
+
else if (e.clientX > rect.right) dx = SCROLL_SPEED;
|
|
693
|
+
if (e.clientY < rect.top) dy = -SCROLL_SPEED;
|
|
694
|
+
else if (e.clientY > rect.bottom) dy = SCROLL_SPEED;
|
|
695
|
+
if (dx === 0 && dy === 0) {
|
|
696
|
+
_stopAutoScroll();
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
const scale = 1 / currentZoom;
|
|
700
|
+
currentViewBox.x += dx * scale;
|
|
701
|
+
currentViewBox.y += dy * scale;
|
|
702
|
+
svg.setAttribute("viewBox", `${currentViewBox.x} ${currentViewBox.y} ${currentViewBox.width} ${currentViewBox.height}`);
|
|
703
|
+
if (typeof freehandCanvas !== "undefined" && freehandCanvas !== svg) {
|
|
704
|
+
freehandCanvas.setAttribute("viewBox", `${currentViewBox.x} ${currentViewBox.y} ${currentViewBox.width} ${currentViewBox.height}`);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
function _startAutoScroll() {
|
|
708
|
+
if (_autoScrollRAF) return;
|
|
709
|
+
const tick = () => {
|
|
710
|
+
if (_lastDragEvent) _autoScroll(_lastDragEvent);
|
|
711
|
+
_autoScrollRAF = requestAnimationFrame(tick);
|
|
712
|
+
};
|
|
713
|
+
_autoScrollRAF = requestAnimationFrame(tick);
|
|
714
|
+
}
|
|
715
|
+
function _stopAutoScroll() {
|
|
716
|
+
if (_autoScrollRAF) {
|
|
717
|
+
cancelAnimationFrame(_autoScrollRAF);
|
|
718
|
+
_autoScrollRAF = null;
|
|
719
|
+
}
|
|
720
|
+
_lastDragEvent = null;
|
|
721
|
+
}
|
|
722
|
+
var _lastDragEvent = null;
|
|
723
|
+
var _documentDragActive = false;
|
|
724
|
+
function _onDocumentDragMove(e) {
|
|
725
|
+
_lastDragEvent = e;
|
|
726
|
+
const rect = svg.getBoundingClientRect();
|
|
727
|
+
const clampedX = Math.max(rect.left, Math.min(rect.right, e.clientX));
|
|
728
|
+
const clampedY = Math.max(rect.top, Math.min(rect.bottom, e.clientY));
|
|
729
|
+
const clampedEvent = new PointerEvent(e.type, {
|
|
730
|
+
clientX: clampedX,
|
|
731
|
+
clientY: clampedY,
|
|
732
|
+
buttons: e.buttons,
|
|
733
|
+
button: e.button,
|
|
734
|
+
ctrlKey: e.ctrlKey,
|
|
735
|
+
shiftKey: e.shiftKey,
|
|
736
|
+
altKey: e.altKey,
|
|
737
|
+
metaKey: e.metaKey
|
|
738
|
+
});
|
|
739
|
+
handleMainMouseMove(clampedEvent);
|
|
740
|
+
}
|
|
741
|
+
function _onDocumentDragUp(e) {
|
|
742
|
+
_stopAutoScroll();
|
|
743
|
+
document.removeEventListener("pointermove", _onDocumentDragMove);
|
|
744
|
+
document.removeEventListener("pointerup", _onDocumentDragUp);
|
|
745
|
+
_documentDragActive = false;
|
|
746
|
+
handleMainMouseUp(e);
|
|
747
|
+
}
|
|
748
|
+
var handleMainMouseDown = (e) => {
|
|
749
|
+
if (!e.target) return;
|
|
750
|
+
if (e.button === 1 || e.button === 2 || window.__spacePanActive) return;
|
|
751
|
+
removeMultiSelectionRect();
|
|
752
|
+
if (!isSelectionToolActive) {
|
|
753
|
+
if (multiSelection.selectedShapes.size > 0) {
|
|
754
|
+
multiSelection.clearSelection();
|
|
755
|
+
}
|
|
756
|
+
if (currentShape && typeof currentShape.removeSelection === "function") {
|
|
757
|
+
currentShape.removeSelection();
|
|
758
|
+
currentShape = null;
|
|
759
|
+
}
|
|
760
|
+
if (typeof disableAllSideBars === "function") {
|
|
761
|
+
disableAllSideBars();
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
if (window.isLassoToolActive) {
|
|
765
|
+
handleLassoDown(e);
|
|
766
|
+
} else if (window.isWebEmbedToolActive) {
|
|
767
|
+
handleWebEmbedDown(e);
|
|
768
|
+
} else if (window.isShapeRecognitionToolActive) {
|
|
769
|
+
handleShapeRecognitionDown(e);
|
|
770
|
+
} else if (window.isPaintBucketToolActive) {
|
|
771
|
+
handlePaintBucketDown(e);
|
|
772
|
+
} else if (isSquareToolActive) {
|
|
773
|
+
handleMouseDownRect(e);
|
|
774
|
+
} else if (isArrowToolActive) {
|
|
775
|
+
handleMouseDown(e);
|
|
776
|
+
} else if (isCircleToolActive) {
|
|
777
|
+
handleMouseDown2(e);
|
|
778
|
+
} else if (isImageToolActive) {
|
|
779
|
+
handleMouseDownImage(e);
|
|
780
|
+
} else if (isLineToolActive) {
|
|
781
|
+
handleMouseDown3(e);
|
|
782
|
+
} else if (isPaintToolActive) {
|
|
783
|
+
handleMouseDown5(e);
|
|
784
|
+
} else if (isTextToolActive) {
|
|
785
|
+
const targetCodeGroup = e.target.closest('g[data-type="code-group"]');
|
|
786
|
+
const targetTextGroup = e.target.closest('g[data-type="text-group"]');
|
|
787
|
+
if (targetCodeGroup && !targetTextGroup) {
|
|
788
|
+
handleCodeMouseDown(e);
|
|
789
|
+
} else if (isTextInCodeMode && !targetTextGroup && !targetCodeGroup) {
|
|
790
|
+
handleCodeMouseDown(e);
|
|
791
|
+
} else {
|
|
792
|
+
handleTextMouseDown(e);
|
|
793
|
+
}
|
|
794
|
+
} else if (isFrameToolActive) {
|
|
795
|
+
handleMouseDown4(e);
|
|
796
|
+
} else if (isIconToolActive) {
|
|
797
|
+
handleMouseDownIcon(e);
|
|
798
|
+
} else if (isSelectionToolActive) {
|
|
799
|
+
if (handleMultiSelectionMouseDown(e)) {
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
const prevShape = currentShape;
|
|
803
|
+
let handled = false;
|
|
804
|
+
if (currentShape?.shapeName === "rectangle") {
|
|
805
|
+
handleMouseDownRect(e);
|
|
806
|
+
handled = true;
|
|
807
|
+
} else if (currentShape?.shapeName === "arrow") {
|
|
808
|
+
handleMouseDown(e);
|
|
809
|
+
handled = true;
|
|
810
|
+
} else if (currentShape?.shapeName === "circle") {
|
|
811
|
+
handleMouseDown2(e);
|
|
812
|
+
handled = true;
|
|
813
|
+
} else if (currentShape?.shapeName === "image") {
|
|
814
|
+
handleMouseDownImage(e);
|
|
815
|
+
handled = true;
|
|
816
|
+
} else if (currentShape?.shapeName === "line") {
|
|
817
|
+
handleMouseDown3(e);
|
|
818
|
+
handled = true;
|
|
819
|
+
} else if (currentShape?.shapeName === "freehandStroke") {
|
|
820
|
+
handleMouseDown5(e);
|
|
821
|
+
handled = true;
|
|
822
|
+
} else if (currentShape?.shapeName === "text") {
|
|
823
|
+
handleTextMouseDown(e);
|
|
824
|
+
handled = true;
|
|
825
|
+
} else if (currentShape?.shapeName === "frame") {
|
|
826
|
+
handleMouseDown4(e);
|
|
827
|
+
handled = true;
|
|
828
|
+
} else if (currentShape?.shapeName === "icon") {
|
|
829
|
+
handleMouseDownIcon(e);
|
|
830
|
+
handled = true;
|
|
831
|
+
} else if (currentShape?.shapeName === "code") {
|
|
832
|
+
handleCodeMouseDown(e);
|
|
833
|
+
handled = true;
|
|
834
|
+
}
|
|
835
|
+
if (handled && prevShape && !currentShape) {
|
|
836
|
+
handled = false;
|
|
837
|
+
}
|
|
838
|
+
if (!handled) {
|
|
839
|
+
const originalCurrentShape = currentShape;
|
|
840
|
+
handleMouseDownRect(e);
|
|
841
|
+
if (currentShape && currentShape !== originalCurrentShape) return;
|
|
842
|
+
handleMouseDown2(e);
|
|
843
|
+
if (currentShape && currentShape !== originalCurrentShape) return;
|
|
844
|
+
handleMouseDown(e);
|
|
845
|
+
if (currentShape && currentShape !== originalCurrentShape) return;
|
|
846
|
+
handleMouseDownImage(e);
|
|
847
|
+
if (currentShape && currentShape !== originalCurrentShape) return;
|
|
848
|
+
handleMouseDown3(e);
|
|
849
|
+
if (currentShape && currentShape !== originalCurrentShape) return;
|
|
850
|
+
handleMouseDown5(e);
|
|
851
|
+
if (currentShape && currentShape !== originalCurrentShape) return;
|
|
852
|
+
handleTextMouseDown(e);
|
|
853
|
+
if (currentShape && currentShape !== originalCurrentShape) return;
|
|
854
|
+
handleMouseDown4(e);
|
|
855
|
+
if (currentShape && currentShape !== originalCurrentShape) return;
|
|
856
|
+
handleMouseDownIcon(e);
|
|
857
|
+
if (currentShape && currentShape !== originalCurrentShape) return;
|
|
858
|
+
handleCodeMouseDown(e);
|
|
859
|
+
if (currentShape && currentShape !== originalCurrentShape) return;
|
|
860
|
+
if (currentShape === originalCurrentShape) {
|
|
861
|
+
if (currentShape) {
|
|
862
|
+
currentShape.removeSelection();
|
|
863
|
+
currentShape = null;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
};
|
|
869
|
+
var handleMainMouseMove = (e) => {
|
|
870
|
+
if (window.__spacePanPointerActive) return;
|
|
871
|
+
if (e.buttons & 1) {
|
|
872
|
+
_lastDragEvent = e;
|
|
873
|
+
_startAutoScroll();
|
|
874
|
+
} else {
|
|
875
|
+
_stopAutoScroll();
|
|
876
|
+
}
|
|
877
|
+
if (window.isLassoToolActive) {
|
|
878
|
+
handleLassoMove(e);
|
|
879
|
+
} else if (window.isWebEmbedToolActive) {
|
|
880
|
+
handleWebEmbedMove(e);
|
|
881
|
+
} else if (window.isShapeRecognitionToolActive) {
|
|
882
|
+
handleShapeRecognitionMove(e);
|
|
883
|
+
} else if (window.isPaintBucketToolActive) {
|
|
884
|
+
return;
|
|
885
|
+
} else if (isSquareToolActive) {
|
|
886
|
+
handleMouseMoveRect(e);
|
|
887
|
+
} else if (isArrowToolActive) {
|
|
888
|
+
handleMouseMove(e);
|
|
889
|
+
} else if (isCircleToolActive) {
|
|
890
|
+
handleMouseMove2(e);
|
|
891
|
+
} else if (isImageToolActive) {
|
|
892
|
+
handleMouseMoveImage(e);
|
|
893
|
+
} else if (isLineToolActive) {
|
|
894
|
+
handleMouseMove3(e);
|
|
895
|
+
} else if (isPaintToolActive) {
|
|
896
|
+
handleMouseMove5(e);
|
|
897
|
+
} else if (isTextToolActive) {
|
|
898
|
+
handleTextMouseMove(e);
|
|
899
|
+
handleCodeMouseMove(e);
|
|
900
|
+
} else if (isFrameToolActive) {
|
|
901
|
+
handleMouseMove4(e);
|
|
902
|
+
} else if (isIconToolActive) {
|
|
903
|
+
handleMouseMoveIcon(e);
|
|
904
|
+
} else if (isSelectionToolActive) {
|
|
905
|
+
if (isMultiSelecting || multiSelection.isDragging || multiSelection.isResizing || multiSelection.isRotating) {
|
|
906
|
+
if (handleMultiSelectionMouseMove(e)) {
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
if (currentShape?.shapeName === "rectangle") {
|
|
911
|
+
handleMouseMoveRect(e);
|
|
912
|
+
} else if (currentShape?.shapeName === "arrow") {
|
|
913
|
+
handleMouseMove(e);
|
|
914
|
+
} else if (currentShape?.shapeName === "circle") {
|
|
915
|
+
handleMouseMove2(e);
|
|
916
|
+
} else if (currentShape?.shapeName === "image") {
|
|
917
|
+
handleMouseMoveImage(e);
|
|
918
|
+
} else if (currentShape?.shapeName === "line") {
|
|
919
|
+
handleMouseMove3(e);
|
|
920
|
+
} else if (currentShape?.shapeName === "freehandStroke") {
|
|
921
|
+
handleMouseMove5(e);
|
|
922
|
+
} else if (currentShape?.shapeName === "text") {
|
|
923
|
+
handleTextMouseMove(e);
|
|
924
|
+
} else if (currentShape?.shapeName === "frame") {
|
|
925
|
+
handleMouseMove4(e);
|
|
926
|
+
} else if (currentShape?.shapeName === "icon") {
|
|
927
|
+
handleMouseMoveIcon(e);
|
|
928
|
+
} else if (currentShape?.shapeName === "code") {
|
|
929
|
+
handleCodeMouseMove(e);
|
|
930
|
+
} else {
|
|
931
|
+
if (handleMultiSelectionMouseMove(e)) {
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
handleMouseMoveRect(e);
|
|
935
|
+
handleMouseMove(e);
|
|
936
|
+
handleMouseMove2(e);
|
|
937
|
+
handleMouseMoveImage(e);
|
|
938
|
+
handleMouseMove3(e);
|
|
939
|
+
handleMouseMove5(e);
|
|
940
|
+
handleTextMouseMove(e);
|
|
941
|
+
handleMouseMove4(e);
|
|
942
|
+
handleMouseMoveIcon(e);
|
|
943
|
+
handleCodeMouseMove(e);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
};
|
|
947
|
+
var handleMainMouseUp = (e) => {
|
|
948
|
+
if (window.__spacePanPointerActive) return;
|
|
949
|
+
_stopAutoScroll();
|
|
950
|
+
if (window.isLassoToolActive) {
|
|
951
|
+
handleLassoUp(e);
|
|
952
|
+
} else if (window.isWebEmbedToolActive) {
|
|
953
|
+
handleWebEmbedUp(e);
|
|
954
|
+
} else if (window.isShapeRecognitionToolActive) {
|
|
955
|
+
handleShapeRecognitionUp(e);
|
|
956
|
+
} else if (window.isPaintBucketToolActive) {
|
|
957
|
+
return;
|
|
958
|
+
} else if (isSquareToolActive) {
|
|
959
|
+
handleMouseUpRect(e);
|
|
960
|
+
} else if (isArrowToolActive) {
|
|
961
|
+
handleMouseUp(e);
|
|
962
|
+
} else if (isCircleToolActive) {
|
|
963
|
+
handleMouseUp2(e);
|
|
964
|
+
} else if (isImageToolActive) {
|
|
965
|
+
handleMouseUpImage(e);
|
|
966
|
+
} else if (isLineToolActive) {
|
|
967
|
+
handleMouseUp3(e);
|
|
968
|
+
} else if (isPaintToolActive) {
|
|
969
|
+
handleMouseUp5(e);
|
|
970
|
+
} else if (isTextToolActive) {
|
|
971
|
+
handleTextMouseUp(e);
|
|
972
|
+
handleCodeMouseUp(e);
|
|
973
|
+
} else if (isFrameToolActive) {
|
|
974
|
+
handleMouseUp4(e);
|
|
975
|
+
} else if (isIconToolActive) {
|
|
976
|
+
handleMouseUpIcon(e);
|
|
977
|
+
} else if (isSelectionToolActive) {
|
|
978
|
+
if (isMultiSelecting || multiSelection.isDragging || multiSelection.isResizing || multiSelection.isRotating) {
|
|
979
|
+
handleMultiSelectionMouseUp(e);
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
if (currentShape?.shapeName === "rectangle") {
|
|
983
|
+
handleMouseUpRect(e);
|
|
984
|
+
} else if (currentShape?.shapeName === "arrow") {
|
|
985
|
+
handleMouseUp(e);
|
|
986
|
+
} else if (currentShape?.shapeName === "circle") {
|
|
987
|
+
handleMouseUp2(e);
|
|
988
|
+
} else if (currentShape?.shapeName === "image") {
|
|
989
|
+
handleMouseUpImage(e);
|
|
990
|
+
} else if (currentShape?.shapeName === "line") {
|
|
991
|
+
handleMouseUp3(e);
|
|
992
|
+
} else if (currentShape?.shapeName === "freehandStroke") {
|
|
993
|
+
handleMouseUp5(e);
|
|
994
|
+
} else if (currentShape?.shapeName === "text") {
|
|
995
|
+
handleTextMouseUp(e);
|
|
996
|
+
} else if (currentShape?.shapeName === "frame") {
|
|
997
|
+
handleMouseUp4(e);
|
|
998
|
+
} else if (currentShape?.shapeName === "icon") {
|
|
999
|
+
handleMouseUpIcon(e);
|
|
1000
|
+
} else if (currentShape?.shapeName === "code") {
|
|
1001
|
+
handleCodeMouseUp(e);
|
|
1002
|
+
} else {
|
|
1003
|
+
handleMultiSelectionMouseUp(e);
|
|
1004
|
+
handleMouseUpRect(e);
|
|
1005
|
+
handleMouseUp(e);
|
|
1006
|
+
handleMouseUp2(e);
|
|
1007
|
+
handleMouseUpImage(e);
|
|
1008
|
+
handleMouseUp3(e);
|
|
1009
|
+
handleMouseUp5(e);
|
|
1010
|
+
handleTextMouseUp(e);
|
|
1011
|
+
handleMouseUp4(e);
|
|
1012
|
+
handleMouseUpIcon(e);
|
|
1013
|
+
handleCodeMouseUp(e);
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
};
|
|
1017
|
+
var handleMainMouseLeave = (e) => {
|
|
1018
|
+
if (window.__spacePanPointerActive) return;
|
|
1019
|
+
if (e.buttons & 1) {
|
|
1020
|
+
_lastDragEvent = e;
|
|
1021
|
+
_startAutoScroll();
|
|
1022
|
+
if (!_documentDragActive) {
|
|
1023
|
+
_documentDragActive = true;
|
|
1024
|
+
document.addEventListener("pointermove", _onDocumentDragMove);
|
|
1025
|
+
document.addEventListener("pointerup", _onDocumentDragUp);
|
|
1026
|
+
}
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
1029
|
+
handleMainMouseUp(e);
|
|
1030
|
+
removeMultiSelectionRect();
|
|
1031
|
+
if (typeof window.forceCleanupEraserTrail === "function") {
|
|
1032
|
+
window.forceCleanupEraserTrail();
|
|
1033
|
+
}
|
|
1034
|
+
if (typeof isDrawing !== "undefined" && isDrawing) {
|
|
1035
|
+
isDrawing = false;
|
|
1036
|
+
if (typeof lasers !== "undefined" && lasers.length > 0 && typeof fadeLaserTrail === "function") {
|
|
1037
|
+
const lastLaser = lasers[lasers.length - 1];
|
|
1038
|
+
fadeLaserTrail(lastLaser);
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
};
|
|
1042
|
+
var _boundSvg = null;
|
|
1043
|
+
function _onMouseEnter(e) {
|
|
1044
|
+
if (_documentDragActive) {
|
|
1045
|
+
document.removeEventListener("pointermove", _onDocumentDragMove);
|
|
1046
|
+
document.removeEventListener("pointerup", _onDocumentDragUp);
|
|
1047
|
+
_documentDragActive = false;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
var handleMainDblClick = (e) => {
|
|
1051
|
+
if (!e.target) return;
|
|
1052
|
+
const targetTextGroup = e.target.closest('g[data-type="text-group"]');
|
|
1053
|
+
if (targetTextGroup) {
|
|
1054
|
+
e.stopPropagation();
|
|
1055
|
+
enterEditMode(targetTextGroup);
|
|
1056
|
+
}
|
|
1057
|
+
};
|
|
1058
|
+
function initEventDispatcher(svgEl) {
|
|
1059
|
+
if (_boundSvg) cleanupEventDispatcher();
|
|
1060
|
+
const target = svgEl || svg;
|
|
1061
|
+
target.addEventListener("pointerdown", handleMainMouseDown);
|
|
1062
|
+
target.addEventListener("pointermove", handleMainMouseMove);
|
|
1063
|
+
target.addEventListener("pointerup", handleMainMouseUp);
|
|
1064
|
+
target.addEventListener("pointerleave", handleMainMouseLeave);
|
|
1065
|
+
target.addEventListener("pointerenter", _onMouseEnter);
|
|
1066
|
+
target.addEventListener("dblclick", handleMainDblClick);
|
|
1067
|
+
_boundSvg = target;
|
|
1068
|
+
}
|
|
1069
|
+
function cleanupEventDispatcher() {
|
|
1070
|
+
_stopAutoScroll();
|
|
1071
|
+
if (_documentDragActive) {
|
|
1072
|
+
document.removeEventListener("pointermove", _onDocumentDragMove);
|
|
1073
|
+
document.removeEventListener("pointerup", _onDocumentDragUp);
|
|
1074
|
+
_documentDragActive = false;
|
|
1075
|
+
}
|
|
1076
|
+
if (_boundSvg) {
|
|
1077
|
+
_boundSvg.removeEventListener("pointerdown", handleMainMouseDown);
|
|
1078
|
+
_boundSvg.removeEventListener("pointermove", handleMainMouseMove);
|
|
1079
|
+
_boundSvg.removeEventListener("pointerup", handleMainMouseUp);
|
|
1080
|
+
_boundSvg.removeEventListener("pointerleave", handleMainMouseLeave);
|
|
1081
|
+
_boundSvg.removeEventListener("pointerenter", _onMouseEnter);
|
|
1082
|
+
_boundSvg.removeEventListener("dblclick", handleMainDblClick);
|
|
1083
|
+
_boundSvg = null;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
if (typeof svg !== "undefined" && svg) {
|
|
1087
|
+
initEventDispatcher(svg);
|
|
1088
|
+
}
|
|
1089
|
+
export {
|
|
1090
|
+
cleanupEventDispatcher,
|
|
1091
|
+
handleMainMouseDown,
|
|
1092
|
+
handleMainMouseLeave,
|
|
1093
|
+
handleMainMouseMove,
|
|
1094
|
+
handleMainMouseUp,
|
|
1095
|
+
initEventDispatcher
|
|
1096
|
+
};
|
|
1097
|
+
//# sourceMappingURL=EventDispatcher-7LAK7GQ7.js.map
|