@elixpo/lixsketch 5.5.22 → 5.6.1
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/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-MYKRKRJG.js → SketchEngine-UD2XV2KT.js} +50 -23
- package/dist/react/{SketchEngine-MYKRKRJG.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-2THKDSWW.js → chunk-GQUZPON4.js} +94 -64
- package/dist/react/chunk-GQUZPON4.js.map +7 -0
- 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-IQOYPELP.js → textTool-S4XXZHZH.js} +5 -5
- package/package.json +1 -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/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/textTool.js +95 -67
- package/src/tools/webEmbedTool.js +61 -0
- package/dist/react/EventDispatcher-O7HCQQNM.js +0 -464
- package/dist/react/EventDispatcher-O7HCQQNM.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-2THKDSWW.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-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-IQOYPELP.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
|