@myoc/excalidraw 0.19.513 → 0.19.514
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/dev/index.js +1817 -1743
- package/dist/dev/index.js.map +4 -4
- package/dist/prod/index.js +23 -23
- package/dist/types/excalidraw/components/App.d.ts +7 -6
- package/dist/types/excalidraw/components/ContextMenu.d.ts +6 -1
- package/dist/types/excalidraw/index.d.ts +1 -1
- package/dist/types/excalidraw/types.d.ts +7 -5
- package/package.json +4 -4
package/dist/dev/index.js
CHANGED
|
@@ -90,257 +90,257 @@ import {
|
|
|
90
90
|
// components/App.tsx
|
|
91
91
|
import clsx57 from "clsx";
|
|
92
92
|
import throttle2 from "lodash.throttle";
|
|
93
|
-
import { nanoid } from "nanoid";
|
|
94
93
|
import React40, { useContext as useContext3 } from "react";
|
|
95
94
|
import { flushSync as flushSync2 } from "react-dom";
|
|
96
95
|
import rough3 from "roughjs/bin/rough";
|
|
96
|
+
import { nanoid } from "nanoid";
|
|
97
97
|
import {
|
|
98
98
|
clamp as clamp8,
|
|
99
|
-
pointDistance as pointDistance9,
|
|
100
99
|
pointFrom as pointFrom34,
|
|
101
|
-
|
|
100
|
+
pointDistance as pointDistance9,
|
|
102
101
|
vector as vector3,
|
|
103
|
-
|
|
102
|
+
pointRotateRads as pointRotateRads23,
|
|
104
103
|
vectorFromPoint as vectorFromPoint10,
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
vectorSubtract as vectorSubtract2,
|
|
105
|
+
vectorDot,
|
|
106
|
+
vectorNormalize as vectorNormalize5
|
|
107
107
|
} from "@excalidraw/math";
|
|
108
108
|
import {
|
|
109
|
-
addEventListener as addEventListener2,
|
|
110
|
-
APP_NAME,
|
|
111
|
-
AppEventBus,
|
|
112
|
-
applyDarkModeFilter as applyDarkModeFilter4,
|
|
113
|
-
arrayToMap as arrayToMap30,
|
|
114
|
-
ARROW_TYPE as ARROW_TYPE2,
|
|
115
|
-
BIND_MODE_TIMEOUT as BIND_MODE_TIMEOUT2,
|
|
116
|
-
CLASSES as CLASSES10,
|
|
117
|
-
CODES as CODES11,
|
|
118
109
|
COLOR_PALETTE as COLOR_PALETTE6,
|
|
119
|
-
|
|
110
|
+
CODES as CODES11,
|
|
111
|
+
shouldResizeFromCenter,
|
|
112
|
+
shouldMaintainAspectRatio,
|
|
113
|
+
shouldRotateWithDiscreteAngle as shouldRotateWithDiscreteAngle3,
|
|
114
|
+
isArrowKey as isArrowKey2,
|
|
115
|
+
KEYS as KEYS50,
|
|
116
|
+
APP_NAME,
|
|
120
117
|
CURSOR_TYPE as CURSOR_TYPE4,
|
|
121
|
-
debounce as debounce3,
|
|
122
|
-
DEFAULT_COLLISION_THRESHOLD,
|
|
123
|
-
DEFAULT_REDUCED_GLOBAL_ALPHA as DEFAULT_REDUCED_GLOBAL_ALPHA2,
|
|
124
|
-
DEFAULT_TEXT_ALIGN as DEFAULT_TEXT_ALIGN2,
|
|
125
118
|
DEFAULT_TRANSFORM_HANDLE_SPACING as DEFAULT_TRANSFORM_HANDLE_SPACING3,
|
|
126
119
|
DEFAULT_VERTICAL_ALIGN,
|
|
127
|
-
deriveStylesPanelMode as deriveStylesPanelMode2,
|
|
128
|
-
distance as distance2,
|
|
129
|
-
DOUBLE_TAP_POSITION_THRESHOLD,
|
|
130
120
|
DRAGGING_THRESHOLD as DRAGGING_THRESHOLD3,
|
|
131
|
-
easeOut as easeOut4,
|
|
132
|
-
easeToValuesRAF,
|
|
133
121
|
ELEMENT_SHIFT_TRANSLATE_AMOUNT,
|
|
134
122
|
ELEMENT_TRANSLATE_AMOUNT,
|
|
135
|
-
Emitter as Emitter2,
|
|
136
123
|
EVENT as EVENT10,
|
|
137
124
|
FRAME_STYLE as FRAME_STYLE4,
|
|
138
|
-
getDateTime,
|
|
139
|
-
getFeatureFlag as getFeatureFlag4,
|
|
140
|
-
getFontString as getFontString11,
|
|
141
|
-
getFormFactor,
|
|
142
|
-
getGridPoint as getGridPoint2,
|
|
143
|
-
getLineHeight as getLineHeight6,
|
|
144
|
-
getNearestScrollableContainer,
|
|
145
125
|
IMAGE_MIME_TYPES as IMAGE_MIME_TYPES2,
|
|
146
126
|
IMAGE_RENDER_TIMEOUT,
|
|
147
|
-
invariant as invariant16,
|
|
148
|
-
isArrowKey as isArrowKey2,
|
|
149
|
-
isBrave,
|
|
150
|
-
isDevEnv as isDevEnv9,
|
|
151
|
-
isInputLike,
|
|
152
|
-
isIOS,
|
|
153
|
-
isLocalLink as isLocalLink2,
|
|
154
|
-
isSafari as isSafari2,
|
|
155
|
-
isSelectionLikeTool,
|
|
156
|
-
isShallowEqual as isShallowEqual8,
|
|
157
|
-
isTestEnv as isTestEnv5,
|
|
158
|
-
isToolIcon,
|
|
159
|
-
isTransparent as isTransparent6,
|
|
160
|
-
isWritableElement as isWritableElement4,
|
|
161
|
-
KEYS as KEYS50,
|
|
162
127
|
LINE_CONFIRM_THRESHOLD as LINE_CONFIRM_THRESHOLD2,
|
|
163
|
-
loadDesktopUIModePreference,
|
|
164
|
-
matchKey as matchKey3,
|
|
165
128
|
MIME_TYPES as MIME_TYPES7,
|
|
166
|
-
MINIMUM_ARROW_SIZE,
|
|
167
129
|
MQ_RIGHT_SIDEBAR_MIN_WIDTH,
|
|
168
|
-
muteFSAbortError,
|
|
169
|
-
normalizeEOL as normalizeEOL2,
|
|
170
|
-
normalizeLink as normalizeLink3,
|
|
171
|
-
oneOf,
|
|
172
130
|
POINTER_BUTTON as POINTER_BUTTON2,
|
|
173
|
-
POINTER_EVENTS,
|
|
174
|
-
randomInteger as randomInteger4,
|
|
175
131
|
ROUNDNESS as ROUNDNESS7,
|
|
176
|
-
sceneCoordsToViewportCoords as sceneCoordsToViewportCoords7,
|
|
177
132
|
SCROLL_TIMEOUT,
|
|
178
|
-
setDesktopUIMode,
|
|
179
|
-
shouldMaintainAspectRatio,
|
|
180
|
-
shouldResizeFromCenter,
|
|
181
|
-
shouldRotateWithDiscreteAngle as shouldRotateWithDiscreteAngle3,
|
|
182
|
-
supportsResizeObserver as supportsResizeObserver2,
|
|
183
133
|
TAP_TWICE_TIMEOUT,
|
|
184
134
|
TEXT_TO_CENTER_SNAP_THRESHOLD,
|
|
185
135
|
THEME as THEME17,
|
|
186
|
-
TOOL_TYPE as TOOL_TYPE3,
|
|
187
136
|
TOUCH_CTX_MENU_TIMEOUT,
|
|
137
|
+
VERTICAL_ALIGN as VERTICAL_ALIGN5,
|
|
138
|
+
YOUTUBE_STATES,
|
|
139
|
+
ZOOM_STEP as ZOOM_STEP2,
|
|
140
|
+
POINTER_EVENTS,
|
|
141
|
+
TOOL_TYPE as TOOL_TYPE3,
|
|
142
|
+
supportsResizeObserver as supportsResizeObserver2,
|
|
143
|
+
DEFAULT_COLLISION_THRESHOLD,
|
|
144
|
+
DEFAULT_TEXT_ALIGN as DEFAULT_TEXT_ALIGN2,
|
|
145
|
+
ARROW_TYPE as ARROW_TYPE2,
|
|
146
|
+
DEFAULT_REDUCED_GLOBAL_ALPHA as DEFAULT_REDUCED_GLOBAL_ALPHA2,
|
|
147
|
+
isLocalLink as isLocalLink2,
|
|
148
|
+
normalizeLink as normalizeLink3,
|
|
188
149
|
toValidURL,
|
|
150
|
+
getGridPoint as getGridPoint2,
|
|
151
|
+
getLineHeight as getLineHeight6,
|
|
152
|
+
debounce as debounce3,
|
|
153
|
+
distance as distance2,
|
|
154
|
+
getFontString as getFontString11,
|
|
155
|
+
getNearestScrollableContainer,
|
|
156
|
+
isInputLike,
|
|
157
|
+
isToolIcon,
|
|
158
|
+
isWritableElement as isWritableElement4,
|
|
159
|
+
sceneCoordsToViewportCoords as sceneCoordsToViewportCoords7,
|
|
189
160
|
tupleToCoors,
|
|
190
|
-
updateActiveTool as updateActiveTool8,
|
|
191
|
-
updateObject as updateObject2,
|
|
192
|
-
updateStable,
|
|
193
|
-
VERTICAL_ALIGN as VERTICAL_ALIGN5,
|
|
194
161
|
viewportCoordsToSceneCoords as viewportCoordsToSceneCoords3,
|
|
195
162
|
wrapEvent as wrapEvent2,
|
|
196
|
-
|
|
197
|
-
|
|
163
|
+
updateObject as updateObject2,
|
|
164
|
+
updateActiveTool as updateActiveTool8,
|
|
165
|
+
isTransparent as isTransparent6,
|
|
166
|
+
easeToValuesRAF,
|
|
167
|
+
muteFSAbortError,
|
|
168
|
+
isTestEnv as isTestEnv5,
|
|
169
|
+
isDevEnv as isDevEnv9,
|
|
170
|
+
easeOut as easeOut4,
|
|
171
|
+
updateStable,
|
|
172
|
+
addEventListener as addEventListener2,
|
|
173
|
+
normalizeEOL as normalizeEOL2,
|
|
174
|
+
getDateTime,
|
|
175
|
+
isShallowEqual as isShallowEqual8,
|
|
176
|
+
arrayToMap as arrayToMap30,
|
|
177
|
+
applyDarkModeFilter as applyDarkModeFilter4,
|
|
178
|
+
AppEventBus,
|
|
179
|
+
randomInteger as randomInteger4,
|
|
180
|
+
CLASSES as CLASSES10,
|
|
181
|
+
Emitter as Emitter2,
|
|
182
|
+
MINIMUM_ARROW_SIZE,
|
|
183
|
+
DOUBLE_TAP_POSITION_THRESHOLD,
|
|
184
|
+
BIND_MODE_TIMEOUT as BIND_MODE_TIMEOUT2,
|
|
185
|
+
invariant as invariant16,
|
|
186
|
+
getFeatureFlag as getFeatureFlag4,
|
|
187
|
+
createUserAgentDescriptor,
|
|
188
|
+
getFormFactor,
|
|
189
|
+
deriveStylesPanelMode as deriveStylesPanelMode2,
|
|
190
|
+
isIOS,
|
|
191
|
+
isBrave,
|
|
192
|
+
isSafari as isSafari2,
|
|
193
|
+
loadDesktopUIModePreference,
|
|
194
|
+
setDesktopUIMode,
|
|
195
|
+
isSelectionLikeTool,
|
|
196
|
+
oneOf,
|
|
197
|
+
matchKey as matchKey3
|
|
198
198
|
} from "@excalidraw/common";
|
|
199
199
|
import {
|
|
200
|
-
|
|
201
|
-
addElementsToFrame as addElementsToFrame2,
|
|
202
|
-
bindOrUnbindBindingElement as bindOrUnbindBindingElement2,
|
|
203
|
-
bindOrUnbindBindingElements as bindOrUnbindBindingElements2,
|
|
204
|
-
calculateFixedPointForNonElbowArrowBinding as calculateFixedPointForNonElbowArrowBinding2,
|
|
205
|
-
CaptureUpdateAction as CaptureUpdateAction41,
|
|
206
|
-
convertToExcalidrawElements,
|
|
207
|
-
createSrcDoc,
|
|
208
|
-
cropElement,
|
|
209
|
-
deepCopyElement as deepCopyElement4,
|
|
210
|
-
doBoundsIntersect as doBoundsIntersect4,
|
|
211
|
-
dragNewElement,
|
|
212
|
-
dragSelectedElements,
|
|
213
|
-
duplicateElements as duplicateElements2,
|
|
214
|
-
editGroupForSelectedElement,
|
|
215
|
-
elementOverlapsWithFrame as elementOverlapsWithFrame2,
|
|
216
|
-
embeddableURLValidator as embeddableURLValidator2,
|
|
217
|
-
excludeElementsInFramesFromSelection,
|
|
218
|
-
filterElementsEligibleAsFrameChildren,
|
|
219
|
-
fixBindingsAfterDeletion as fixBindingsAfterDeletion2,
|
|
220
|
-
FlowChartCreator,
|
|
221
|
-
FlowChartNavigator,
|
|
222
|
-
getActiveTextElement as getActiveTextElement2,
|
|
223
|
-
getApproxMinLineHeight,
|
|
224
|
-
getApproxMinLineWidth as getApproxMinLineWidth2,
|
|
225
|
-
getBoundTextElement as getBoundTextElement15,
|
|
200
|
+
getObservedAppState,
|
|
226
201
|
getCommonBounds as getCommonBounds11,
|
|
227
|
-
getCommonFrameId as getCommonFrameId2,
|
|
228
|
-
getContainerCenter,
|
|
229
|
-
getContainerElement as getContainerElement5,
|
|
230
|
-
getContainingFrame as getContainingFrame3,
|
|
231
|
-
getCornerRadius as getCornerRadius2,
|
|
232
|
-
getCursorForResizingElement,
|
|
233
|
-
getDragOffsetXY,
|
|
234
202
|
getElementAbsoluteCoords as getElementAbsoluteCoords8,
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
getElementsInNewFrame,
|
|
238
|
-
getElementsInResizingFrame as getElementsInResizingFrame4,
|
|
239
|
-
getElementsOverlappingFrame as getElementsOverlappingFrame2,
|
|
240
|
-
getElementWithTransformHandleType,
|
|
241
|
-
getEmbedLink as getEmbedLink2,
|
|
242
|
-
getFrameChildren as getFrameChildren6,
|
|
243
|
-
getFrameChildrenInsertionIndex as getFrameChildrenInsertionIndex2,
|
|
244
|
-
getFrameLikeTitle,
|
|
203
|
+
bindOrUnbindBindingElements as bindOrUnbindBindingElements2,
|
|
204
|
+
fixBindingsAfterDeletion as fixBindingsAfterDeletion2,
|
|
245
205
|
getHoveredElementForBinding as getHoveredElementForBinding2,
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
handleFocusPointDrag,
|
|
263
|
-
handleFocusPointHover,
|
|
264
|
-
handleFocusPointPointerDown,
|
|
265
|
-
handleFocusPointPointerUp,
|
|
266
|
-
hasBoundingBox as hasBoundingBox2,
|
|
206
|
+
isBindingEnabled as isBindingEnabled2,
|
|
207
|
+
updateBoundElements as updateBoundElements4,
|
|
208
|
+
newElementWith as newElementWith10,
|
|
209
|
+
newFrameElement as newFrameElement2,
|
|
210
|
+
newFreeDrawElement,
|
|
211
|
+
newEmbeddableElement,
|
|
212
|
+
newMagicFrameElement,
|
|
213
|
+
newIframeElement,
|
|
214
|
+
newArrowElement as newArrowElement2,
|
|
215
|
+
newElement as newElement6,
|
|
216
|
+
newImageElement,
|
|
217
|
+
newLinearElement as newLinearElement5,
|
|
218
|
+
newTextElement as newTextElement5,
|
|
219
|
+
refreshTextDimensions,
|
|
220
|
+
deepCopyElement as deepCopyElement4,
|
|
221
|
+
duplicateElements as duplicateElements2,
|
|
267
222
|
hasBoundTextElement as hasBoundTextElement9,
|
|
268
|
-
hitElementBoundingBox as hitElementBoundingBox2,
|
|
269
|
-
hitElementBoundingBoxOnly,
|
|
270
|
-
hitElementBoundText,
|
|
271
|
-
hitElementItself as hitElementItself3,
|
|
272
223
|
isArrowElement as isArrowElement14,
|
|
273
|
-
isBindableElement as isBindableElement3,
|
|
274
224
|
isBindingElement as isBindingElement4,
|
|
275
225
|
isBindingElementType,
|
|
276
|
-
isBindingEnabled as isBindingEnabled2,
|
|
277
226
|
isBoundToContainer as isBoundToContainer9,
|
|
278
|
-
isCursorInFrame,
|
|
279
|
-
isElbowArrow as isElbowArrow10,
|
|
280
|
-
isElementCompletelyInViewport as isElementCompletelyInViewport2,
|
|
281
|
-
isElementInFrame,
|
|
282
|
-
isElementInGroup as isElementInGroup2,
|
|
283
|
-
isElementInViewport as isElementInViewport3,
|
|
284
|
-
isElementLink as isElementLink2,
|
|
285
|
-
isEligibleFrameChildType,
|
|
286
|
-
isEmbeddableElement as isEmbeddableElement4,
|
|
287
|
-
isFlowchartNodeElement as isFlowchartNodeElement2,
|
|
288
227
|
isFrameLikeElement as isFrameLikeElement15,
|
|
289
|
-
isIframeElement as isIframeElement2,
|
|
290
|
-
isIframeLikeElement as isIframeLikeElement2,
|
|
291
228
|
isImageElement as isImageElement9,
|
|
229
|
+
isEmbeddableElement as isEmbeddableElement4,
|
|
292
230
|
isInitializedImageElement as isInitializedImageElement3,
|
|
293
|
-
isInvisiblySmallElement as isInvisiblySmallElement3,
|
|
294
231
|
isLinearElement as isLinearElement12,
|
|
295
232
|
isLinearElementType as isLinearElementType2,
|
|
296
|
-
|
|
233
|
+
isUsingAdaptiveRadius as isUsingAdaptiveRadius4,
|
|
234
|
+
isIframeElement as isIframeElement2,
|
|
235
|
+
isIframeLikeElement as isIframeLikeElement2,
|
|
297
236
|
isMagicFrameElement as isMagicFrameElement2,
|
|
298
|
-
isMeasureTextSupported,
|
|
299
|
-
isNonDeletedElement,
|
|
300
|
-
isPathALoop as isPathALoop3,
|
|
301
|
-
isPointInElement as isPointInElement3,
|
|
302
|
-
isSelectedViaGroup as isSelectedViaGroup2,
|
|
303
|
-
isSimpleArrow,
|
|
304
237
|
isTextBindableContainer as isTextBindableContainer3,
|
|
238
|
+
isElbowArrow as isElbowArrow10,
|
|
239
|
+
isFlowchartNodeElement as isFlowchartNodeElement2,
|
|
240
|
+
isBindableElement as isBindableElement3,
|
|
305
241
|
isTextElement as isTextElement19,
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
242
|
+
getNormalizedDimensions,
|
|
243
|
+
isElementCompletelyInViewport as isElementCompletelyInViewport2,
|
|
244
|
+
isElementInViewport as isElementInViewport3,
|
|
245
|
+
isInvisiblySmallElement as isInvisiblySmallElement3,
|
|
246
|
+
getCornerRadius as getCornerRadius2,
|
|
247
|
+
isPathALoop as isPathALoop3,
|
|
248
|
+
createSrcDoc,
|
|
249
|
+
embeddableURLValidator as embeddableURLValidator2,
|
|
311
250
|
maybeParseEmbedSrc,
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
newArrowElement as newArrowElement2,
|
|
315
|
-
newElement as newElement6,
|
|
316
|
-
newElementWith as newElementWith10,
|
|
317
|
-
newEmbeddableElement,
|
|
318
|
-
newFrameElement as newFrameElement2,
|
|
319
|
-
newFreeDrawElement,
|
|
320
|
-
newIframeElement,
|
|
321
|
-
newImageElement,
|
|
322
|
-
newLinearElement as newLinearElement5,
|
|
323
|
-
newMagicFrameElement,
|
|
324
|
-
newTextElement as newTextElement5,
|
|
251
|
+
getEmbedLink as getEmbedLink2,
|
|
252
|
+
getInitializedImageElements,
|
|
325
253
|
normalizeSVG,
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
254
|
+
updateImageCache as _updateImageCache,
|
|
255
|
+
getBoundTextElement as getBoundTextElement15,
|
|
256
|
+
getContainerCenter,
|
|
257
|
+
getContainerElement as getContainerElement5,
|
|
258
|
+
isValidTextContainer,
|
|
329
259
|
redrawTextBoundingBox as redrawTextBoundingBox8,
|
|
330
|
-
|
|
331
|
-
|
|
260
|
+
hasBoundingBox as hasBoundingBox2,
|
|
261
|
+
getCommonFrameId as getCommonFrameId2,
|
|
262
|
+
getFrameChildren as getFrameChildren6,
|
|
263
|
+
getFrameChildrenInsertionIndex as getFrameChildrenInsertionIndex2,
|
|
264
|
+
isCursorInFrame,
|
|
265
|
+
addElementsToFrame as addElementsToFrame2,
|
|
332
266
|
replaceAllElementsInFrame as replaceAllElementsInFrame4,
|
|
333
|
-
|
|
334
|
-
|
|
267
|
+
removeElementsFromFrame as removeElementsFromFrame2,
|
|
268
|
+
getElementsInResizingFrame as getElementsInResizingFrame4,
|
|
269
|
+
getElementsInNewFrame,
|
|
270
|
+
getContainingFrame as getContainingFrame3,
|
|
271
|
+
elementOverlapsWithFrame as elementOverlapsWithFrame2,
|
|
272
|
+
updateFrameMembershipOfSelectedElements as updateFrameMembershipOfSelectedElements6,
|
|
273
|
+
isElementInFrame,
|
|
274
|
+
getFrameLikeTitle,
|
|
275
|
+
getElementsOverlappingFrame as getElementsOverlappingFrame2,
|
|
276
|
+
filterElementsEligibleAsFrameChildren,
|
|
277
|
+
hitElementBoundText,
|
|
278
|
+
hitElementBoundingBoxOnly,
|
|
279
|
+
hitElementItself as hitElementItself3,
|
|
280
|
+
getVisibleSceneBounds,
|
|
281
|
+
FlowChartCreator,
|
|
282
|
+
FlowChartNavigator,
|
|
283
|
+
getLinkDirectionFromKey,
|
|
284
|
+
cropElement,
|
|
285
|
+
wrapText as wrapText5,
|
|
286
|
+
isElementLink as isElementLink2,
|
|
287
|
+
parseElementLinkFromURL,
|
|
288
|
+
isMeasureTextSupported,
|
|
289
|
+
normalizeText as normalizeText2,
|
|
290
|
+
measureText as measureText8,
|
|
291
|
+
getLineHeightInPx as getLineHeightInPx3,
|
|
292
|
+
getApproxMinLineWidth as getApproxMinLineWidth2,
|
|
293
|
+
getApproxMinLineHeight,
|
|
294
|
+
getMinTextElementWidth,
|
|
335
295
|
ShapeCache as ShapeCache4,
|
|
336
|
-
|
|
337
|
-
|
|
296
|
+
getRenderOpacity,
|
|
297
|
+
editGroupForSelectedElement,
|
|
298
|
+
getElementsInGroup as getElementsInGroup10,
|
|
299
|
+
getSelectedGroupIdForElement,
|
|
300
|
+
getSelectedGroupIds as getSelectedGroupIds4,
|
|
301
|
+
isElementInGroup as isElementInGroup2,
|
|
302
|
+
isSelectedViaGroup as isSelectedViaGroup2,
|
|
303
|
+
selectGroupsForSelectedElements as selectGroupsForSelectedElements7,
|
|
338
304
|
syncInvalidIndices,
|
|
339
305
|
syncMovedIndices as syncMovedIndices5,
|
|
306
|
+
excludeElementsInFramesFromSelection,
|
|
307
|
+
getSelectionStateForElements as getSelectionStateForElements2,
|
|
308
|
+
makeNextSelectedElementIds as makeNextSelectedElementIds3,
|
|
309
|
+
getResizeOffsetXY,
|
|
310
|
+
getResizeArrowDirection,
|
|
340
311
|
transformElements,
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
312
|
+
getCursorForResizingElement,
|
|
313
|
+
getElementWithTransformHandleType,
|
|
314
|
+
getTransformHandleTypeFromCoords,
|
|
315
|
+
dragNewElement,
|
|
316
|
+
dragSelectedElements,
|
|
317
|
+
getDragOffsetXY,
|
|
318
|
+
isNonDeletedElement,
|
|
319
|
+
Scene,
|
|
320
|
+
Store,
|
|
321
|
+
CaptureUpdateAction as CaptureUpdateAction41,
|
|
322
|
+
hitElementBoundingBox as hitElementBoundingBox2,
|
|
323
|
+
isLineElement as isLineElement8,
|
|
324
|
+
isSimpleArrow,
|
|
325
|
+
StoreDelta as StoreDelta2,
|
|
326
|
+
positionElementsOnGrid,
|
|
327
|
+
calculateFixedPointForNonElbowArrowBinding as calculateFixedPointForNonElbowArrowBinding2,
|
|
328
|
+
bindOrUnbindBindingElement as bindOrUnbindBindingElement2,
|
|
329
|
+
mutateElement as mutateElement6,
|
|
330
|
+
getElementBounds as getElementBounds5,
|
|
331
|
+
doBoundsIntersect as doBoundsIntersect4,
|
|
332
|
+
isPointInElement as isPointInElement3,
|
|
333
|
+
maxBindingDistance_simple as maxBindingDistance_simple3,
|
|
334
|
+
convertToExcalidrawElements,
|
|
335
|
+
getSnapOutlineMidPoint as getSnapOutlineMidPoint2,
|
|
336
|
+
handleFocusPointDrag,
|
|
337
|
+
handleFocusPointHover,
|
|
338
|
+
handleFocusPointPointerDown,
|
|
339
|
+
handleFocusPointPointerUp,
|
|
340
|
+
maybeHandleArrowPointlikeDrag,
|
|
341
|
+
getUncroppedWidthAndHeight as getUncroppedWidthAndHeight4,
|
|
342
|
+
getActiveTextElement as getActiveTextElement2,
|
|
343
|
+
isEligibleFrameChildType
|
|
344
344
|
} from "@excalidraw/element";
|
|
345
345
|
import { LinearElementEditor as LinearElementEditor11 } from "@excalidraw/element/linearElementEditor";
|
|
346
346
|
import { findShapeByKey } from "@excalidraw/element/shapes";
|
|
@@ -15025,428 +15025,980 @@ var getCenter = (pointers) => {
|
|
|
15025
15025
|
var getDistance = ([a, b]) => Math.hypot(a.x - b.x, a.y - b.y);
|
|
15026
15026
|
var sum = (array, mapper) => array.reduce((acc, item) => acc + mapper(item), 0);
|
|
15027
15027
|
|
|
15028
|
-
//
|
|
15029
|
-
import {
|
|
15030
|
-
|
|
15031
|
-
|
|
15032
|
-
|
|
15033
|
-
|
|
15034
|
-
|
|
15035
|
-
|
|
15036
|
-
|
|
15037
|
-
|
|
15038
|
-
|
|
15039
|
-
|
|
15040
|
-
|
|
15041
|
-
|
|
15028
|
+
// snapping.ts
|
|
15029
|
+
import {
|
|
15030
|
+
pointFrom as pointFrom18,
|
|
15031
|
+
pointRotateRads as pointRotateRads14,
|
|
15032
|
+
rangeInclusive,
|
|
15033
|
+
rangeIntersection,
|
|
15034
|
+
rangesOverlap
|
|
15035
|
+
} from "@excalidraw/math";
|
|
15036
|
+
import { TOOL_TYPE, KEYS as KEYS34 } from "@excalidraw/common";
|
|
15037
|
+
import {
|
|
15038
|
+
getCommonBounds as getCommonBounds4,
|
|
15039
|
+
getDraggedElementsBounds,
|
|
15040
|
+
getElementAbsoluteCoords as getElementAbsoluteCoords4
|
|
15041
|
+
} from "@excalidraw/element";
|
|
15042
|
+
import { isBoundToContainer as isBoundToContainer6 } from "@excalidraw/element";
|
|
15043
|
+
import { getMaximumGroups } from "@excalidraw/element";
|
|
15044
|
+
import {
|
|
15045
|
+
getSelectedElements as getSelectedElements4,
|
|
15046
|
+
getVisibleAndNonSelectedElements
|
|
15047
|
+
} from "@excalidraw/element";
|
|
15048
|
+
var SNAP_DISTANCE = 8;
|
|
15049
|
+
var VISIBLE_GAPS_LIMIT_PER_AXIS = 99999;
|
|
15050
|
+
var getSnapDistance = (zoomValue) => {
|
|
15051
|
+
return SNAP_DISTANCE / zoomValue;
|
|
15042
15052
|
};
|
|
15043
|
-
var
|
|
15044
|
-
|
|
15045
|
-
|
|
15046
|
-
|
|
15053
|
+
var _SnapCache = class _SnapCache {
|
|
15054
|
+
};
|
|
15055
|
+
__publicField(_SnapCache, "referenceSnapPoints", null);
|
|
15056
|
+
__publicField(_SnapCache, "visibleGaps", null);
|
|
15057
|
+
__publicField(_SnapCache, "setReferenceSnapPoints", (snapPoints) => {
|
|
15058
|
+
_SnapCache.referenceSnapPoints = snapPoints;
|
|
15059
|
+
});
|
|
15060
|
+
__publicField(_SnapCache, "getReferenceSnapPoints", () => {
|
|
15061
|
+
return _SnapCache.referenceSnapPoints;
|
|
15062
|
+
});
|
|
15063
|
+
__publicField(_SnapCache, "setVisibleGaps", (gaps) => {
|
|
15064
|
+
_SnapCache.visibleGaps = gaps;
|
|
15065
|
+
});
|
|
15066
|
+
__publicField(_SnapCache, "getVisibleGaps", () => {
|
|
15067
|
+
return _SnapCache.visibleGaps;
|
|
15068
|
+
});
|
|
15069
|
+
__publicField(_SnapCache, "destroy", () => {
|
|
15070
|
+
_SnapCache.referenceSnapPoints = null;
|
|
15071
|
+
_SnapCache.visibleGaps = null;
|
|
15072
|
+
});
|
|
15073
|
+
var SnapCache = _SnapCache;
|
|
15074
|
+
var isGridModeEnabled = (app) => app.props.gridModeEnabled ?? app.state.gridModeEnabled;
|
|
15075
|
+
var isSnappingEnabled = ({
|
|
15076
|
+
event,
|
|
15077
|
+
app,
|
|
15078
|
+
selectedElements
|
|
15047
15079
|
}) => {
|
|
15048
|
-
|
|
15049
|
-
|
|
15050
|
-
return
|
|
15080
|
+
if (event) {
|
|
15081
|
+
const isLassoDragging = app.state.activeTool.type === "lasso" && app.state.selectedElementsAreBeingDragged;
|
|
15082
|
+
return (app.state.activeTool.type !== "lasso" || isLassoDragging) && (app.state.objectsSnapModeEnabled && !event[KEYS34.CTRL_OR_CMD] || !app.state.objectsSnapModeEnabled && event[KEYS34.CTRL_OR_CMD] && !isGridModeEnabled(app));
|
|
15051
15083
|
}
|
|
15052
|
-
|
|
15053
|
-
|
|
15054
|
-
|
|
15055
|
-
|
|
15056
|
-
|
|
15057
|
-
|
|
15058
|
-
|
|
15059
|
-
|
|
15060
|
-
|
|
15061
|
-
|
|
15062
|
-
|
|
15063
|
-
|
|
15084
|
+
if (selectedElements.length === 1 && selectedElements[0].type === "arrow") {
|
|
15085
|
+
return false;
|
|
15086
|
+
}
|
|
15087
|
+
return app.state.objectsSnapModeEnabled;
|
|
15088
|
+
};
|
|
15089
|
+
var areRoughlyEqual = (a, b, precision = 0.01) => {
|
|
15090
|
+
return Math.abs(a - b) <= precision;
|
|
15091
|
+
};
|
|
15092
|
+
var getElementsCorners = (elements, elementsMap, {
|
|
15093
|
+
omitCenter,
|
|
15094
|
+
boundingBoxCorners,
|
|
15095
|
+
dragOffset
|
|
15096
|
+
} = {
|
|
15097
|
+
omitCenter: false,
|
|
15098
|
+
boundingBoxCorners: false
|
|
15099
|
+
}) => {
|
|
15100
|
+
let result = [];
|
|
15101
|
+
if (elements.length === 1) {
|
|
15102
|
+
const element = elements[0];
|
|
15103
|
+
let [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords4(
|
|
15104
|
+
element,
|
|
15105
|
+
elementsMap
|
|
15106
|
+
);
|
|
15107
|
+
if (dragOffset) {
|
|
15108
|
+
x1 += dragOffset.x;
|
|
15109
|
+
x2 += dragOffset.x;
|
|
15110
|
+
cx += dragOffset.x;
|
|
15111
|
+
y1 += dragOffset.y;
|
|
15112
|
+
y2 += dragOffset.y;
|
|
15113
|
+
cy += dragOffset.y;
|
|
15064
15114
|
}
|
|
15115
|
+
const halfWidth = (x2 - x1) / 2;
|
|
15116
|
+
const halfHeight = (y2 - y1) / 2;
|
|
15117
|
+
if ((element.type === "diamond" || element.type === "ellipse") && !boundingBoxCorners) {
|
|
15118
|
+
const leftMid = pointRotateRads14(
|
|
15119
|
+
pointFrom18(x1, y1 + halfHeight),
|
|
15120
|
+
pointFrom18(cx, cy),
|
|
15121
|
+
element.angle
|
|
15122
|
+
);
|
|
15123
|
+
const topMid = pointRotateRads14(
|
|
15124
|
+
pointFrom18(x1 + halfWidth, y1),
|
|
15125
|
+
pointFrom18(cx, cy),
|
|
15126
|
+
element.angle
|
|
15127
|
+
);
|
|
15128
|
+
const rightMid = pointRotateRads14(
|
|
15129
|
+
pointFrom18(x2, y1 + halfHeight),
|
|
15130
|
+
pointFrom18(cx, cy),
|
|
15131
|
+
element.angle
|
|
15132
|
+
);
|
|
15133
|
+
const bottomMid = pointRotateRads14(
|
|
15134
|
+
pointFrom18(x1 + halfWidth, y2),
|
|
15135
|
+
pointFrom18(cx, cy),
|
|
15136
|
+
element.angle
|
|
15137
|
+
);
|
|
15138
|
+
const center = pointFrom18(cx, cy);
|
|
15139
|
+
result = omitCenter ? [leftMid, topMid, rightMid, bottomMid] : [leftMid, topMid, rightMid, bottomMid, center];
|
|
15140
|
+
} else {
|
|
15141
|
+
const topLeft = pointRotateRads14(
|
|
15142
|
+
pointFrom18(x1, y1),
|
|
15143
|
+
pointFrom18(cx, cy),
|
|
15144
|
+
element.angle
|
|
15145
|
+
);
|
|
15146
|
+
const topRight = pointRotateRads14(
|
|
15147
|
+
pointFrom18(x2, y1),
|
|
15148
|
+
pointFrom18(cx, cy),
|
|
15149
|
+
element.angle
|
|
15150
|
+
);
|
|
15151
|
+
const bottomLeft = pointRotateRads14(
|
|
15152
|
+
pointFrom18(x1, y2),
|
|
15153
|
+
pointFrom18(cx, cy),
|
|
15154
|
+
element.angle
|
|
15155
|
+
);
|
|
15156
|
+
const bottomRight = pointRotateRads14(
|
|
15157
|
+
pointFrom18(x2, y2),
|
|
15158
|
+
pointFrom18(cx, cy),
|
|
15159
|
+
element.angle
|
|
15160
|
+
);
|
|
15161
|
+
const center = pointFrom18(cx, cy);
|
|
15162
|
+
result = omitCenter ? [topLeft, topRight, bottomLeft, bottomRight] : [topLeft, topRight, bottomLeft, bottomRight, center];
|
|
15163
|
+
}
|
|
15164
|
+
} else if (elements.length > 1) {
|
|
15165
|
+
const [minX, minY, maxX, maxY] = getDraggedElementsBounds(
|
|
15166
|
+
elements,
|
|
15167
|
+
dragOffset ?? { x: 0, y: 0 }
|
|
15168
|
+
);
|
|
15169
|
+
const width = maxX - minX;
|
|
15170
|
+
const height = maxY - minY;
|
|
15171
|
+
const topLeft = pointFrom18(minX, minY);
|
|
15172
|
+
const topRight = pointFrom18(maxX, minY);
|
|
15173
|
+
const bottomLeft = pointFrom18(minX, maxY);
|
|
15174
|
+
const bottomRight = pointFrom18(maxX, maxY);
|
|
15175
|
+
const center = pointFrom18(minX + width / 2, minY + height / 2);
|
|
15176
|
+
result = omitCenter ? [topLeft, topRight, bottomLeft, bottomRight] : [topLeft, topRight, bottomLeft, bottomRight, center];
|
|
15177
|
+
}
|
|
15178
|
+
return result.map((p) => pointFrom18(round(p[0]), round(p[1])));
|
|
15179
|
+
};
|
|
15180
|
+
var getReferenceElements = (elements, selectedElements, appState, elementsMap) => getVisibleAndNonSelectedElements(
|
|
15181
|
+
elements,
|
|
15182
|
+
selectedElements,
|
|
15183
|
+
appState,
|
|
15184
|
+
elementsMap
|
|
15185
|
+
);
|
|
15186
|
+
var getVisibleGaps = (elements, selectedElements, appState, elementsMap) => {
|
|
15187
|
+
const referenceElements = getReferenceElements(
|
|
15188
|
+
elements,
|
|
15189
|
+
selectedElements,
|
|
15190
|
+
appState,
|
|
15191
|
+
elementsMap
|
|
15192
|
+
);
|
|
15193
|
+
const referenceBounds = getMaximumGroups(referenceElements, elementsMap).filter(
|
|
15194
|
+
(elementsGroup) => !(elementsGroup.length === 1 && isBoundToContainer6(elementsGroup[0]))
|
|
15195
|
+
).map(
|
|
15196
|
+
(group) => getCommonBounds4(group).map(
|
|
15197
|
+
(bound) => round(bound)
|
|
15198
|
+
)
|
|
15065
15199
|
);
|
|
15200
|
+
const horizontallySorted = referenceBounds.sort((a, b) => a[0] - b[0]);
|
|
15201
|
+
const horizontalGaps = [];
|
|
15202
|
+
let c = 0;
|
|
15203
|
+
horizontal:
|
|
15204
|
+
for (let i = 0; i < horizontallySorted.length; i++) {
|
|
15205
|
+
const startBounds = horizontallySorted[i];
|
|
15206
|
+
for (let j = i + 1; j < horizontallySorted.length; j++) {
|
|
15207
|
+
if (++c > VISIBLE_GAPS_LIMIT_PER_AXIS) {
|
|
15208
|
+
break horizontal;
|
|
15209
|
+
}
|
|
15210
|
+
const endBounds = horizontallySorted[j];
|
|
15211
|
+
const [, startMinY, startMaxX, startMaxY] = startBounds;
|
|
15212
|
+
const [endMinX, endMinY, , endMaxY] = endBounds;
|
|
15213
|
+
if (startMaxX < endMinX && rangesOverlap(
|
|
15214
|
+
rangeInclusive(startMinY, startMaxY),
|
|
15215
|
+
rangeInclusive(endMinY, endMaxY)
|
|
15216
|
+
)) {
|
|
15217
|
+
horizontalGaps.push({
|
|
15218
|
+
startBounds,
|
|
15219
|
+
endBounds,
|
|
15220
|
+
startSide: [
|
|
15221
|
+
pointFrom18(startMaxX, startMinY),
|
|
15222
|
+
pointFrom18(startMaxX, startMaxY)
|
|
15223
|
+
],
|
|
15224
|
+
endSide: [pointFrom18(endMinX, endMinY), pointFrom18(endMinX, endMaxY)],
|
|
15225
|
+
length: endMinX - startMaxX,
|
|
15226
|
+
overlap: rangeIntersection(
|
|
15227
|
+
rangeInclusive(startMinY, startMaxY),
|
|
15228
|
+
rangeInclusive(endMinY, endMaxY)
|
|
15229
|
+
)
|
|
15230
|
+
});
|
|
15231
|
+
}
|
|
15232
|
+
}
|
|
15233
|
+
}
|
|
15234
|
+
const verticallySorted = referenceBounds.sort((a, b) => a[1] - b[1]);
|
|
15235
|
+
const verticalGaps = [];
|
|
15236
|
+
c = 0;
|
|
15237
|
+
vertical:
|
|
15238
|
+
for (let i = 0; i < verticallySorted.length; i++) {
|
|
15239
|
+
const startBounds = verticallySorted[i];
|
|
15240
|
+
for (let j = i + 1; j < verticallySorted.length; j++) {
|
|
15241
|
+
if (++c > VISIBLE_GAPS_LIMIT_PER_AXIS) {
|
|
15242
|
+
break vertical;
|
|
15243
|
+
}
|
|
15244
|
+
const endBounds = verticallySorted[j];
|
|
15245
|
+
const [startMinX, , startMaxX, startMaxY] = startBounds;
|
|
15246
|
+
const [endMinX, endMinY, endMaxX] = endBounds;
|
|
15247
|
+
if (startMaxY < endMinY && rangesOverlap(
|
|
15248
|
+
rangeInclusive(startMinX, startMaxX),
|
|
15249
|
+
rangeInclusive(endMinX, endMaxX)
|
|
15250
|
+
)) {
|
|
15251
|
+
verticalGaps.push({
|
|
15252
|
+
startBounds,
|
|
15253
|
+
endBounds,
|
|
15254
|
+
startSide: [
|
|
15255
|
+
pointFrom18(startMinX, startMaxY),
|
|
15256
|
+
pointFrom18(startMaxX, startMaxY)
|
|
15257
|
+
],
|
|
15258
|
+
endSide: [pointFrom18(endMinX, endMinY), pointFrom18(endMaxX, endMinY)],
|
|
15259
|
+
length: endMinY - startMaxY,
|
|
15260
|
+
overlap: rangeIntersection(
|
|
15261
|
+
rangeInclusive(startMinX, startMaxX),
|
|
15262
|
+
rangeInclusive(endMinX, endMaxX)
|
|
15263
|
+
)
|
|
15264
|
+
});
|
|
15265
|
+
}
|
|
15266
|
+
}
|
|
15267
|
+
}
|
|
15268
|
+
return {
|
|
15269
|
+
horizontalGaps,
|
|
15270
|
+
verticalGaps
|
|
15271
|
+
};
|
|
15066
15272
|
};
|
|
15067
|
-
|
|
15068
|
-
|
|
15069
|
-
|
|
15070
|
-
|
|
15071
|
-
|
|
15072
|
-
|
|
15073
|
-
|
|
15074
|
-
|
|
15075
|
-
|
|
15076
|
-
|
|
15077
|
-
|
|
15078
|
-
|
|
15079
|
-
|
|
15080
|
-
|
|
15081
|
-
|
|
15082
|
-
|
|
15083
|
-
|
|
15084
|
-
|
|
15273
|
+
var getGapSnaps = (selectedElements, dragOffset, app, event, nearestSnapsX, nearestSnapsY, minOffset) => {
|
|
15274
|
+
if (!isSnappingEnabled({ app, event, selectedElements })) {
|
|
15275
|
+
return [];
|
|
15276
|
+
}
|
|
15277
|
+
if (selectedElements.length === 0) {
|
|
15278
|
+
return [];
|
|
15279
|
+
}
|
|
15280
|
+
const visibleGaps = SnapCache.getVisibleGaps();
|
|
15281
|
+
if (visibleGaps) {
|
|
15282
|
+
const { horizontalGaps, verticalGaps } = visibleGaps;
|
|
15283
|
+
const [minX, minY, maxX, maxY] = getDraggedElementsBounds(
|
|
15284
|
+
selectedElements,
|
|
15285
|
+
dragOffset
|
|
15286
|
+
).map((bound) => round(bound));
|
|
15287
|
+
const centerX = (minX + maxX) / 2;
|
|
15288
|
+
const centerY = (minY + maxY) / 2;
|
|
15289
|
+
for (const gap of horizontalGaps) {
|
|
15290
|
+
if (!rangesOverlap(rangeInclusive(minY, maxY), gap.overlap)) {
|
|
15291
|
+
continue;
|
|
15292
|
+
}
|
|
15293
|
+
const gapMidX = gap.startSide[0][0] + gap.length / 2;
|
|
15294
|
+
const centerOffset = round(gapMidX - centerX);
|
|
15295
|
+
const gapIsLargerThanSelection = gap.length > maxX - minX;
|
|
15296
|
+
if (gapIsLargerThanSelection && Math.abs(centerOffset) <= minOffset.x) {
|
|
15297
|
+
if (Math.abs(centerOffset) < minOffset.x) {
|
|
15298
|
+
nearestSnapsX.length = 0;
|
|
15299
|
+
}
|
|
15300
|
+
minOffset.x = Math.abs(centerOffset);
|
|
15301
|
+
const snap = {
|
|
15302
|
+
type: "gap",
|
|
15303
|
+
direction: "center_horizontal",
|
|
15304
|
+
gap,
|
|
15305
|
+
offset: centerOffset
|
|
15306
|
+
};
|
|
15307
|
+
nearestSnapsX.push(snap);
|
|
15308
|
+
continue;
|
|
15309
|
+
}
|
|
15310
|
+
const [, , endMaxX] = gap.endBounds;
|
|
15311
|
+
const distanceToEndElementX = minX - endMaxX;
|
|
15312
|
+
const sideOffsetRight = round(gap.length - distanceToEndElementX);
|
|
15313
|
+
if (Math.abs(sideOffsetRight) <= minOffset.x) {
|
|
15314
|
+
if (Math.abs(sideOffsetRight) < minOffset.x) {
|
|
15315
|
+
nearestSnapsX.length = 0;
|
|
15316
|
+
}
|
|
15317
|
+
minOffset.x = Math.abs(sideOffsetRight);
|
|
15318
|
+
const snap = {
|
|
15319
|
+
type: "gap",
|
|
15320
|
+
direction: "side_right",
|
|
15321
|
+
gap,
|
|
15322
|
+
offset: sideOffsetRight
|
|
15323
|
+
};
|
|
15324
|
+
nearestSnapsX.push(snap);
|
|
15325
|
+
continue;
|
|
15326
|
+
}
|
|
15327
|
+
const [startMinX, , ,] = gap.startBounds;
|
|
15328
|
+
const distanceToStartElementX = startMinX - maxX;
|
|
15329
|
+
const sideOffsetLeft = round(distanceToStartElementX - gap.length);
|
|
15330
|
+
if (Math.abs(sideOffsetLeft) <= minOffset.x) {
|
|
15331
|
+
if (Math.abs(sideOffsetLeft) < minOffset.x) {
|
|
15332
|
+
nearestSnapsX.length = 0;
|
|
15333
|
+
}
|
|
15334
|
+
minOffset.x = Math.abs(sideOffsetLeft);
|
|
15335
|
+
const snap = {
|
|
15336
|
+
type: "gap",
|
|
15337
|
+
direction: "side_left",
|
|
15338
|
+
gap,
|
|
15339
|
+
offset: sideOffsetLeft
|
|
15340
|
+
};
|
|
15341
|
+
nearestSnapsX.push(snap);
|
|
15342
|
+
continue;
|
|
15343
|
+
}
|
|
15344
|
+
}
|
|
15345
|
+
for (const gap of verticalGaps) {
|
|
15346
|
+
if (!rangesOverlap(rangeInclusive(minX, maxX), gap.overlap)) {
|
|
15347
|
+
continue;
|
|
15348
|
+
}
|
|
15349
|
+
const gapMidY = gap.startSide[0][1] + gap.length / 2;
|
|
15350
|
+
const centerOffset = round(gapMidY - centerY);
|
|
15351
|
+
const gapIsLargerThanSelection = gap.length > maxY - minY;
|
|
15352
|
+
if (gapIsLargerThanSelection && Math.abs(centerOffset) <= minOffset.y) {
|
|
15353
|
+
if (Math.abs(centerOffset) < minOffset.y) {
|
|
15354
|
+
nearestSnapsY.length = 0;
|
|
15355
|
+
}
|
|
15356
|
+
minOffset.y = Math.abs(centerOffset);
|
|
15357
|
+
const snap = {
|
|
15358
|
+
type: "gap",
|
|
15359
|
+
direction: "center_vertical",
|
|
15360
|
+
gap,
|
|
15361
|
+
offset: centerOffset
|
|
15362
|
+
};
|
|
15363
|
+
nearestSnapsY.push(snap);
|
|
15364
|
+
continue;
|
|
15365
|
+
}
|
|
15366
|
+
const [, startMinY, ,] = gap.startBounds;
|
|
15367
|
+
const distanceToStartElementY = startMinY - maxY;
|
|
15368
|
+
const sideOffsetTop = round(distanceToStartElementY - gap.length);
|
|
15369
|
+
if (Math.abs(sideOffsetTop) <= minOffset.y) {
|
|
15370
|
+
if (Math.abs(sideOffsetTop) < minOffset.y) {
|
|
15371
|
+
nearestSnapsY.length = 0;
|
|
15372
|
+
}
|
|
15373
|
+
minOffset.y = Math.abs(sideOffsetTop);
|
|
15374
|
+
const snap = {
|
|
15375
|
+
type: "gap",
|
|
15376
|
+
direction: "side_top",
|
|
15377
|
+
gap,
|
|
15378
|
+
offset: sideOffsetTop
|
|
15379
|
+
};
|
|
15380
|
+
nearestSnapsY.push(snap);
|
|
15381
|
+
continue;
|
|
15382
|
+
}
|
|
15383
|
+
const [, , , endMaxY] = gap.endBounds;
|
|
15384
|
+
const distanceToEndElementY = round(minY - endMaxY);
|
|
15385
|
+
const sideOffsetBottom = gap.length - distanceToEndElementY;
|
|
15386
|
+
if (Math.abs(sideOffsetBottom) <= minOffset.y) {
|
|
15387
|
+
if (Math.abs(sideOffsetBottom) < minOffset.y) {
|
|
15388
|
+
nearestSnapsY.length = 0;
|
|
15389
|
+
}
|
|
15390
|
+
minOffset.y = Math.abs(sideOffsetBottom);
|
|
15391
|
+
const snap = {
|
|
15392
|
+
type: "gap",
|
|
15393
|
+
direction: "side_bottom",
|
|
15394
|
+
gap,
|
|
15395
|
+
offset: sideOffsetBottom
|
|
15396
|
+
};
|
|
15397
|
+
nearestSnapsY.push(snap);
|
|
15398
|
+
continue;
|
|
15399
|
+
}
|
|
15400
|
+
}
|
|
15401
|
+
}
|
|
15085
15402
|
};
|
|
15086
|
-
var
|
|
15087
|
-
|
|
15088
|
-
|
|
15403
|
+
var getReferenceSnapPoints = (elements, selectedElements, appState, elementsMap) => {
|
|
15404
|
+
const referenceElements = getReferenceElements(
|
|
15405
|
+
elements,
|
|
15406
|
+
selectedElements,
|
|
15407
|
+
appState,
|
|
15408
|
+
elementsMap
|
|
15409
|
+
);
|
|
15410
|
+
return getMaximumGroups(referenceElements, elementsMap).filter(
|
|
15411
|
+
(elementsGroup) => !(elementsGroup.length === 1 && isBoundToContainer6(elementsGroup[0]))
|
|
15412
|
+
).flatMap((elementGroup) => getElementsCorners(elementGroup, elementsMap));
|
|
15413
|
+
};
|
|
15414
|
+
var getPointSnaps = (selectedElements, selectionSnapPoints, app, event, nearestSnapsX, nearestSnapsY, minOffset) => {
|
|
15415
|
+
if (!isSnappingEnabled({ app, event, selectedElements }) || selectedElements.length === 0 && selectionSnapPoints.length === 0) {
|
|
15416
|
+
return [];
|
|
15417
|
+
}
|
|
15418
|
+
const referenceSnapPoints = SnapCache.getReferenceSnapPoints();
|
|
15419
|
+
if (referenceSnapPoints) {
|
|
15420
|
+
for (const thisSnapPoint of selectionSnapPoints) {
|
|
15421
|
+
for (const otherSnapPoint of referenceSnapPoints) {
|
|
15422
|
+
const offsetX = otherSnapPoint[0] - thisSnapPoint[0];
|
|
15423
|
+
const offsetY = otherSnapPoint[1] - thisSnapPoint[1];
|
|
15424
|
+
if (Math.abs(offsetX) <= minOffset.x) {
|
|
15425
|
+
if (Math.abs(offsetX) < minOffset.x) {
|
|
15426
|
+
nearestSnapsX.length = 0;
|
|
15427
|
+
}
|
|
15428
|
+
nearestSnapsX.push({
|
|
15429
|
+
type: "point",
|
|
15430
|
+
points: [thisSnapPoint, otherSnapPoint],
|
|
15431
|
+
offset: offsetX
|
|
15432
|
+
});
|
|
15433
|
+
minOffset.x = Math.abs(offsetX);
|
|
15434
|
+
}
|
|
15435
|
+
if (Math.abs(offsetY) <= minOffset.y) {
|
|
15436
|
+
if (Math.abs(offsetY) < minOffset.y) {
|
|
15437
|
+
nearestSnapsY.length = 0;
|
|
15438
|
+
}
|
|
15439
|
+
nearestSnapsY.push({
|
|
15440
|
+
type: "point",
|
|
15441
|
+
points: [thisSnapPoint, otherSnapPoint],
|
|
15442
|
+
offset: offsetY
|
|
15443
|
+
});
|
|
15444
|
+
minOffset.y = Math.abs(offsetY);
|
|
15445
|
+
}
|
|
15446
|
+
}
|
|
15447
|
+
}
|
|
15448
|
+
}
|
|
15449
|
+
};
|
|
15450
|
+
var snapDraggedElements = (elements, dragOffset, app, event, elementsMap) => {
|
|
15451
|
+
const appState = app.state;
|
|
15452
|
+
const selectedElements = getSelectedElements4(elements, appState);
|
|
15453
|
+
if (!isSnappingEnabled({ app, event, selectedElements }) || selectedElements.length === 0) {
|
|
15454
|
+
return {
|
|
15455
|
+
snapOffset: {
|
|
15456
|
+
x: 0,
|
|
15457
|
+
y: 0
|
|
15458
|
+
},
|
|
15459
|
+
snapLines: []
|
|
15460
|
+
};
|
|
15461
|
+
}
|
|
15462
|
+
dragOffset.x = round(dragOffset.x);
|
|
15463
|
+
dragOffset.y = round(dragOffset.y);
|
|
15464
|
+
const nearestSnapsX = [];
|
|
15465
|
+
const nearestSnapsY = [];
|
|
15466
|
+
const snapDistance = getSnapDistance(appState.zoom.value);
|
|
15467
|
+
const minOffset = {
|
|
15468
|
+
x: snapDistance,
|
|
15469
|
+
y: snapDistance
|
|
15470
|
+
};
|
|
15471
|
+
const selectionPoints = getElementsCorners(selectedElements, elementsMap, {
|
|
15472
|
+
dragOffset
|
|
15089
15473
|
});
|
|
15474
|
+
getPointSnaps(
|
|
15475
|
+
selectedElements,
|
|
15476
|
+
selectionPoints,
|
|
15477
|
+
app,
|
|
15478
|
+
event,
|
|
15479
|
+
nearestSnapsX,
|
|
15480
|
+
nearestSnapsY,
|
|
15481
|
+
minOffset
|
|
15482
|
+
);
|
|
15483
|
+
getGapSnaps(
|
|
15484
|
+
selectedElements,
|
|
15485
|
+
dragOffset,
|
|
15486
|
+
app,
|
|
15487
|
+
event,
|
|
15488
|
+
nearestSnapsX,
|
|
15489
|
+
nearestSnapsY,
|
|
15490
|
+
minOffset
|
|
15491
|
+
);
|
|
15492
|
+
const snapOffset = {
|
|
15493
|
+
x: nearestSnapsX[0]?.offset ?? 0,
|
|
15494
|
+
y: nearestSnapsY[0]?.offset ?? 0
|
|
15495
|
+
};
|
|
15496
|
+
minOffset.x = 0;
|
|
15497
|
+
minOffset.y = 0;
|
|
15498
|
+
nearestSnapsX.length = 0;
|
|
15499
|
+
nearestSnapsY.length = 0;
|
|
15500
|
+
const newDragOffset = {
|
|
15501
|
+
x: round(dragOffset.x + snapOffset.x),
|
|
15502
|
+
y: round(dragOffset.y + snapOffset.y)
|
|
15503
|
+
};
|
|
15504
|
+
getPointSnaps(
|
|
15505
|
+
selectedElements,
|
|
15506
|
+
getElementsCorners(selectedElements, elementsMap, {
|
|
15507
|
+
dragOffset: newDragOffset
|
|
15508
|
+
}),
|
|
15509
|
+
app,
|
|
15510
|
+
event,
|
|
15511
|
+
nearestSnapsX,
|
|
15512
|
+
nearestSnapsY,
|
|
15513
|
+
minOffset
|
|
15514
|
+
);
|
|
15515
|
+
getGapSnaps(
|
|
15516
|
+
selectedElements,
|
|
15517
|
+
newDragOffset,
|
|
15518
|
+
app,
|
|
15519
|
+
event,
|
|
15520
|
+
nearestSnapsX,
|
|
15521
|
+
nearestSnapsY,
|
|
15522
|
+
minOffset
|
|
15523
|
+
);
|
|
15524
|
+
const pointSnapLines = createPointSnapLines(nearestSnapsX, nearestSnapsY);
|
|
15525
|
+
const gapSnapLines = createGapSnapLines(
|
|
15526
|
+
selectedElements,
|
|
15527
|
+
newDragOffset,
|
|
15528
|
+
[...nearestSnapsX, ...nearestSnapsY].filter(
|
|
15529
|
+
(snap) => snap.type === "gap"
|
|
15530
|
+
)
|
|
15531
|
+
);
|
|
15532
|
+
return {
|
|
15533
|
+
snapOffset,
|
|
15534
|
+
snapLines: [...pointSnapLines, ...gapSnapLines]
|
|
15535
|
+
};
|
|
15090
15536
|
};
|
|
15091
|
-
var
|
|
15092
|
-
|
|
15093
|
-
|
|
15094
|
-
|
|
15095
|
-
|
|
15096
|
-
|
|
15097
|
-
|
|
15537
|
+
var round = (x) => {
|
|
15538
|
+
const decimalPlaces = 6;
|
|
15539
|
+
return Math.round(x * 10 ** decimalPlaces) / 10 ** decimalPlaces;
|
|
15540
|
+
};
|
|
15541
|
+
var dedupePoints = (points) => {
|
|
15542
|
+
const map = /* @__PURE__ */ new Map();
|
|
15543
|
+
for (const point of points) {
|
|
15544
|
+
const key = point.join(",");
|
|
15545
|
+
if (!map.has(key)) {
|
|
15546
|
+
map.set(key, point);
|
|
15547
|
+
}
|
|
15098
15548
|
}
|
|
15099
|
-
|
|
15100
|
-
|
|
15101
|
-
|
|
15102
|
-
|
|
15103
|
-
|
|
15104
|
-
|
|
15105
|
-
|
|
15106
|
-
|
|
15549
|
+
return Array.from(map.values());
|
|
15550
|
+
};
|
|
15551
|
+
var createPointSnapLines = (nearestSnapsX, nearestSnapsY) => {
|
|
15552
|
+
const snapsX = {};
|
|
15553
|
+
const snapsY = {};
|
|
15554
|
+
if (nearestSnapsX.length > 0) {
|
|
15555
|
+
for (const snap of nearestSnapsX) {
|
|
15556
|
+
if (snap.type === "point") {
|
|
15557
|
+
const key = round(snap.points[0][0]);
|
|
15558
|
+
if (!snapsX[key]) {
|
|
15559
|
+
snapsX[key] = [];
|
|
15560
|
+
}
|
|
15561
|
+
snapsX[key].push(
|
|
15562
|
+
...snap.points.map(
|
|
15563
|
+
(p) => pointFrom18(round(p[0]), round(p[1]))
|
|
15564
|
+
)
|
|
15565
|
+
);
|
|
15566
|
+
}
|
|
15567
|
+
}
|
|
15568
|
+
}
|
|
15569
|
+
if (nearestSnapsY.length > 0) {
|
|
15570
|
+
for (const snap of nearestSnapsY) {
|
|
15571
|
+
if (snap.type === "point") {
|
|
15572
|
+
const key = round(snap.points[0][1]);
|
|
15573
|
+
if (!snapsY[key]) {
|
|
15574
|
+
snapsY[key] = [];
|
|
15575
|
+
}
|
|
15576
|
+
snapsY[key].push(
|
|
15577
|
+
...snap.points.map(
|
|
15578
|
+
(p) => pointFrom18(round(p[0]), round(p[1]))
|
|
15579
|
+
)
|
|
15580
|
+
);
|
|
15581
|
+
}
|
|
15582
|
+
}
|
|
15583
|
+
}
|
|
15584
|
+
return Object.entries(snapsX).map(([key, points]) => {
|
|
15585
|
+
return {
|
|
15586
|
+
type: "points",
|
|
15587
|
+
points: dedupePoints(
|
|
15588
|
+
points.map((p) => {
|
|
15589
|
+
return pointFrom18(Number(key), p[1]);
|
|
15590
|
+
}).sort((a, b) => a[1] - b[1])
|
|
15591
|
+
)
|
|
15592
|
+
};
|
|
15593
|
+
}).concat(
|
|
15594
|
+
Object.entries(snapsY).map(([key, points]) => {
|
|
15595
|
+
return {
|
|
15596
|
+
type: "points",
|
|
15597
|
+
points: dedupePoints(
|
|
15598
|
+
points.map((p) => {
|
|
15599
|
+
return pointFrom18(p[0], Number(key));
|
|
15600
|
+
}).sort((a, b) => a[0] - b[0])
|
|
15601
|
+
)
|
|
15602
|
+
};
|
|
15603
|
+
})
|
|
15604
|
+
);
|
|
15605
|
+
};
|
|
15606
|
+
var dedupeGapSnapLines = (gapSnapLines) => {
|
|
15607
|
+
const map = /* @__PURE__ */ new Map();
|
|
15608
|
+
for (const gapSnapLine of gapSnapLines) {
|
|
15609
|
+
const key = gapSnapLine.points.flat().map((point) => [round(point)]).join(",");
|
|
15610
|
+
if (!map.has(key)) {
|
|
15611
|
+
map.set(key, gapSnapLine);
|
|
15612
|
+
}
|
|
15613
|
+
}
|
|
15614
|
+
return Array.from(map.values());
|
|
15615
|
+
};
|
|
15616
|
+
var createGapSnapLines = (selectedElements, dragOffset, gapSnaps) => {
|
|
15617
|
+
const [minX, minY, maxX, maxY] = getDraggedElementsBounds(
|
|
15618
|
+
selectedElements,
|
|
15619
|
+
dragOffset
|
|
15620
|
+
);
|
|
15621
|
+
const gapSnapLines = [];
|
|
15622
|
+
for (const gapSnap of gapSnaps) {
|
|
15623
|
+
const [startMinX, startMinY, startMaxX, startMaxY] = gapSnap.gap.startBounds;
|
|
15624
|
+
const [endMinX, endMinY, endMaxX, endMaxY] = gapSnap.gap.endBounds;
|
|
15625
|
+
const verticalIntersection = rangeIntersection(
|
|
15626
|
+
rangeInclusive(minY, maxY),
|
|
15627
|
+
gapSnap.gap.overlap
|
|
15628
|
+
);
|
|
15629
|
+
const horizontalGapIntersection = rangeIntersection(
|
|
15630
|
+
rangeInclusive(minX, maxX),
|
|
15631
|
+
gapSnap.gap.overlap
|
|
15632
|
+
);
|
|
15633
|
+
switch (gapSnap.direction) {
|
|
15634
|
+
case "center_horizontal": {
|
|
15635
|
+
if (verticalIntersection) {
|
|
15636
|
+
const gapLineY = (verticalIntersection[0] + verticalIntersection[1]) / 2;
|
|
15637
|
+
gapSnapLines.push(
|
|
15638
|
+
{
|
|
15639
|
+
type: "gap",
|
|
15640
|
+
direction: "horizontal",
|
|
15641
|
+
points: [
|
|
15642
|
+
pointFrom18(gapSnap.gap.startSide[0][0], gapLineY),
|
|
15643
|
+
pointFrom18(minX, gapLineY)
|
|
15644
|
+
]
|
|
15645
|
+
},
|
|
15646
|
+
{
|
|
15647
|
+
type: "gap",
|
|
15648
|
+
direction: "horizontal",
|
|
15649
|
+
points: [
|
|
15650
|
+
pointFrom18(maxX, gapLineY),
|
|
15651
|
+
pointFrom18(gapSnap.gap.endSide[0][0], gapLineY)
|
|
15652
|
+
]
|
|
15653
|
+
}
|
|
15654
|
+
);
|
|
15655
|
+
}
|
|
15656
|
+
break;
|
|
15657
|
+
}
|
|
15658
|
+
case "center_vertical": {
|
|
15659
|
+
if (horizontalGapIntersection) {
|
|
15660
|
+
const gapLineX = (horizontalGapIntersection[0] + horizontalGapIntersection[1]) / 2;
|
|
15661
|
+
gapSnapLines.push(
|
|
15662
|
+
{
|
|
15663
|
+
type: "gap",
|
|
15664
|
+
direction: "vertical",
|
|
15665
|
+
points: [
|
|
15666
|
+
pointFrom18(gapLineX, gapSnap.gap.startSide[0][1]),
|
|
15667
|
+
pointFrom18(gapLineX, minY)
|
|
15668
|
+
]
|
|
15669
|
+
},
|
|
15670
|
+
{
|
|
15671
|
+
type: "gap",
|
|
15672
|
+
direction: "vertical",
|
|
15673
|
+
points: [
|
|
15674
|
+
pointFrom18(gapLineX, maxY),
|
|
15675
|
+
pointFrom18(gapLineX, gapSnap.gap.endSide[0][1])
|
|
15676
|
+
]
|
|
15677
|
+
}
|
|
15678
|
+
);
|
|
15679
|
+
}
|
|
15680
|
+
break;
|
|
15681
|
+
}
|
|
15682
|
+
case "side_right": {
|
|
15683
|
+
if (verticalIntersection) {
|
|
15684
|
+
const gapLineY = (verticalIntersection[0] + verticalIntersection[1]) / 2;
|
|
15685
|
+
gapSnapLines.push(
|
|
15686
|
+
{
|
|
15687
|
+
type: "gap",
|
|
15688
|
+
direction: "horizontal",
|
|
15689
|
+
points: [
|
|
15690
|
+
pointFrom18(startMaxX, gapLineY),
|
|
15691
|
+
pointFrom18(endMinX, gapLineY)
|
|
15692
|
+
]
|
|
15693
|
+
},
|
|
15694
|
+
{
|
|
15695
|
+
type: "gap",
|
|
15696
|
+
direction: "horizontal",
|
|
15697
|
+
points: [pointFrom18(endMaxX, gapLineY), pointFrom18(minX, gapLineY)]
|
|
15698
|
+
}
|
|
15699
|
+
);
|
|
15700
|
+
}
|
|
15701
|
+
break;
|
|
15702
|
+
}
|
|
15703
|
+
case "side_left": {
|
|
15704
|
+
if (verticalIntersection) {
|
|
15705
|
+
const gapLineY = (verticalIntersection[0] + verticalIntersection[1]) / 2;
|
|
15706
|
+
gapSnapLines.push(
|
|
15707
|
+
{
|
|
15708
|
+
type: "gap",
|
|
15709
|
+
direction: "horizontal",
|
|
15710
|
+
points: [
|
|
15711
|
+
pointFrom18(maxX, gapLineY),
|
|
15712
|
+
pointFrom18(startMinX, gapLineY)
|
|
15713
|
+
]
|
|
15714
|
+
},
|
|
15715
|
+
{
|
|
15716
|
+
type: "gap",
|
|
15717
|
+
direction: "horizontal",
|
|
15718
|
+
points: [
|
|
15719
|
+
pointFrom18(startMaxX, gapLineY),
|
|
15720
|
+
pointFrom18(endMinX, gapLineY)
|
|
15721
|
+
]
|
|
15722
|
+
}
|
|
15107
15723
|
);
|
|
15108
15724
|
}
|
|
15109
|
-
|
|
15725
|
+
break;
|
|
15110
15726
|
}
|
|
15111
|
-
|
|
15112
|
-
|
|
15113
|
-
|
|
15114
|
-
|
|
15115
|
-
|
|
15116
|
-
|
|
15117
|
-
|
|
15118
|
-
|
|
15119
|
-
|
|
15120
|
-
|
|
15121
|
-
|
|
15122
|
-
|
|
15123
|
-
|
|
15124
|
-
|
|
15125
|
-
|
|
15126
|
-
|
|
15127
|
-
|
|
15128
|
-
|
|
15129
|
-
|
|
15130
|
-
|
|
15131
|
-
|
|
15132
|
-
});
|
|
15133
|
-
_AnimationController.scheduleNextFrame();
|
|
15134
|
-
}
|
|
15135
|
-
}
|
|
15136
|
-
static scheduleNextFrame() {
|
|
15137
|
-
if (_AnimationController.scheduledFrame) {
|
|
15138
|
-
return;
|
|
15139
|
-
}
|
|
15140
|
-
if (isRenderThrottlingEnabled()) {
|
|
15141
|
-
_AnimationController.scheduledFrame = {
|
|
15142
|
-
id: requestAnimationFrame(_AnimationController.tick),
|
|
15143
|
-
type: "raf"
|
|
15144
|
-
};
|
|
15145
|
-
} else {
|
|
15146
|
-
_AnimationController.scheduledFrame = {
|
|
15147
|
-
id: setTimeout(_AnimationController.tick, 0),
|
|
15148
|
-
type: "timeout"
|
|
15149
|
-
};
|
|
15150
|
-
}
|
|
15151
|
-
}
|
|
15152
|
-
static cancelScheduledFrame() {
|
|
15153
|
-
if (!_AnimationController.scheduledFrame) {
|
|
15154
|
-
return;
|
|
15155
|
-
}
|
|
15156
|
-
if (_AnimationController.scheduledFrame.type === "raf") {
|
|
15157
|
-
cancelAnimationFrame(_AnimationController.scheduledFrame.id);
|
|
15158
|
-
} else {
|
|
15159
|
-
clearTimeout(_AnimationController.scheduledFrame.id);
|
|
15160
|
-
}
|
|
15161
|
-
_AnimationController.scheduledFrame = null;
|
|
15162
|
-
}
|
|
15163
|
-
static cancelScheduledFrameIfIdle() {
|
|
15164
|
-
if (_AnimationController.animations.size > 0) {
|
|
15165
|
-
return false;
|
|
15166
|
-
}
|
|
15167
|
-
_AnimationController.cancelScheduledFrame();
|
|
15168
|
-
return true;
|
|
15169
|
-
}
|
|
15170
|
-
static tick() {
|
|
15171
|
-
_AnimationController.scheduledFrame = null;
|
|
15172
|
-
if (_AnimationController.animations.size > 0) {
|
|
15173
|
-
for (const [key, animation] of _AnimationController.animations) {
|
|
15174
|
-
const now = performance.now();
|
|
15175
|
-
const deltaTime = animation.lastTime === 0 ? 0 : now - animation.lastTime;
|
|
15176
|
-
const state = animation.animation({
|
|
15177
|
-
deltaTime,
|
|
15178
|
-
state: animation.state
|
|
15179
|
-
});
|
|
15180
|
-
if (!state) {
|
|
15181
|
-
_AnimationController.animations.delete(key);
|
|
15182
|
-
if (_AnimationController.cancelScheduledFrameIfIdle()) {
|
|
15183
|
-
return;
|
|
15184
|
-
}
|
|
15185
|
-
} else {
|
|
15186
|
-
animation.lastTime = now;
|
|
15187
|
-
animation.state = state;
|
|
15727
|
+
case "side_top": {
|
|
15728
|
+
if (horizontalGapIntersection) {
|
|
15729
|
+
const gapLineX = (horizontalGapIntersection[0] + horizontalGapIntersection[1]) / 2;
|
|
15730
|
+
gapSnapLines.push(
|
|
15731
|
+
{
|
|
15732
|
+
type: "gap",
|
|
15733
|
+
direction: "vertical",
|
|
15734
|
+
points: [
|
|
15735
|
+
pointFrom18(gapLineX, maxY),
|
|
15736
|
+
pointFrom18(gapLineX, startMinY)
|
|
15737
|
+
]
|
|
15738
|
+
},
|
|
15739
|
+
{
|
|
15740
|
+
type: "gap",
|
|
15741
|
+
direction: "vertical",
|
|
15742
|
+
points: [
|
|
15743
|
+
pointFrom18(gapLineX, startMaxY),
|
|
15744
|
+
pointFrom18(gapLineX, endMinY)
|
|
15745
|
+
]
|
|
15746
|
+
}
|
|
15747
|
+
);
|
|
15188
15748
|
}
|
|
15749
|
+
break;
|
|
15189
15750
|
}
|
|
15190
|
-
|
|
15191
|
-
|
|
15751
|
+
case "side_bottom": {
|
|
15752
|
+
if (horizontalGapIntersection) {
|
|
15753
|
+
const gapLineX = (horizontalGapIntersection[0] + horizontalGapIntersection[1]) / 2;
|
|
15754
|
+
gapSnapLines.push(
|
|
15755
|
+
{
|
|
15756
|
+
type: "gap",
|
|
15757
|
+
direction: "vertical",
|
|
15758
|
+
points: [
|
|
15759
|
+
pointFrom18(gapLineX, startMaxY),
|
|
15760
|
+
pointFrom18(gapLineX, endMinY)
|
|
15761
|
+
]
|
|
15762
|
+
},
|
|
15763
|
+
{
|
|
15764
|
+
type: "gap",
|
|
15765
|
+
direction: "vertical",
|
|
15766
|
+
points: [pointFrom18(gapLineX, endMaxY), pointFrom18(gapLineX, minY)]
|
|
15767
|
+
}
|
|
15768
|
+
);
|
|
15769
|
+
}
|
|
15770
|
+
break;
|
|
15192
15771
|
}
|
|
15193
|
-
_AnimationController.scheduleNextFrame();
|
|
15194
15772
|
}
|
|
15195
15773
|
}
|
|
15196
|
-
|
|
15197
|
-
|
|
15198
|
-
|
|
15199
|
-
|
|
15200
|
-
|
|
15201
|
-
|
|
15202
|
-
|
|
15774
|
+
return dedupeGapSnapLines(
|
|
15775
|
+
gapSnapLines.map((gapSnapLine) => {
|
|
15776
|
+
return {
|
|
15777
|
+
...gapSnapLine,
|
|
15778
|
+
points: gapSnapLine.points.map(
|
|
15779
|
+
(p) => pointFrom18(round(p[0]), round(p[1]))
|
|
15780
|
+
)
|
|
15781
|
+
};
|
|
15782
|
+
})
|
|
15783
|
+
);
|
|
15203
15784
|
};
|
|
15204
|
-
|
|
15205
|
-
|
|
15206
|
-
|
|
15207
|
-
|
|
15208
|
-
|
|
15209
|
-
|
|
15210
|
-
constructor(app, options) {
|
|
15211
|
-
this.app = app;
|
|
15212
|
-
this.options = options;
|
|
15213
|
-
__publicField(this, "currentTrail");
|
|
15214
|
-
__publicField(this, "pastTrails", []);
|
|
15215
|
-
__publicField(this, "container");
|
|
15216
|
-
__publicField(this, "trailElement");
|
|
15217
|
-
__publicField(this, "trailAnimation");
|
|
15218
|
-
__publicField(this, "key");
|
|
15219
|
-
this.key = `animated-trail-${_AnimatedTrail.counter++}`;
|
|
15220
|
-
this.trailElement = document.createElementNS(SVG_NS, "path");
|
|
15221
|
-
if (this.options.animateTrail) {
|
|
15222
|
-
this.trailAnimation = document.createElementNS(SVG_NS, "animate");
|
|
15223
|
-
this.trailAnimation.setAttribute("attributeName", "stroke-dashoffset");
|
|
15224
|
-
this.trailElement.setAttribute("stroke-dasharray", "7 7");
|
|
15225
|
-
this.trailElement.setAttribute("stroke-dashoffset", "10");
|
|
15226
|
-
this.trailAnimation.setAttribute("from", "0");
|
|
15227
|
-
this.trailAnimation.setAttribute("to", `-14`);
|
|
15228
|
-
this.trailAnimation.setAttribute("dur", "0.3s");
|
|
15229
|
-
this.trailElement.appendChild(this.trailAnimation);
|
|
15230
|
-
}
|
|
15231
|
-
}
|
|
15232
|
-
get hasCurrentTrail() {
|
|
15233
|
-
return !!this.currentTrail;
|
|
15234
|
-
}
|
|
15235
|
-
hasLastPoint(x, y) {
|
|
15236
|
-
if (this.currentTrail) {
|
|
15237
|
-
const len = this.currentTrail.originalPoints.length;
|
|
15238
|
-
return this.currentTrail.originalPoints[len - 1][0] === x && this.currentTrail.originalPoints[len - 1][1] === y;
|
|
15239
|
-
}
|
|
15240
|
-
return false;
|
|
15241
|
-
}
|
|
15242
|
-
cleanup() {
|
|
15243
|
-
this.pastTrails = [];
|
|
15244
|
-
this.currentTrail = void 0;
|
|
15245
|
-
if (this.trailElement.parentNode === this.container) {
|
|
15246
|
-
this.container?.removeChild(this.trailElement);
|
|
15247
|
-
}
|
|
15248
|
-
}
|
|
15249
|
-
start(container) {
|
|
15250
|
-
if (container) {
|
|
15251
|
-
this.container = container;
|
|
15252
|
-
}
|
|
15253
|
-
if (this.trailElement.parentNode !== this.container && this.container) {
|
|
15254
|
-
this.container.appendChild(this.trailElement);
|
|
15255
|
-
}
|
|
15256
|
-
if (!AnimationController.running(this.key)) {
|
|
15257
|
-
AnimationController.start(this.key, () => {
|
|
15258
|
-
const needsNext = this.onFrame();
|
|
15259
|
-
if (needsNext) {
|
|
15260
|
-
return { keep: true };
|
|
15261
|
-
}
|
|
15262
|
-
this.cleanup();
|
|
15263
|
-
return null;
|
|
15264
|
-
});
|
|
15265
|
-
}
|
|
15266
|
-
}
|
|
15267
|
-
stop() {
|
|
15268
|
-
AnimationController.cancel(this.key);
|
|
15269
|
-
this.cleanup();
|
|
15270
|
-
}
|
|
15271
|
-
startPath(x, y) {
|
|
15272
|
-
this.currentTrail = new LaserPointer(this.options);
|
|
15273
|
-
this.currentTrail.addPoint([x, y, performance.now()]);
|
|
15274
|
-
this.update();
|
|
15275
|
-
}
|
|
15276
|
-
addPointToPath(x, y) {
|
|
15277
|
-
if (this.currentTrail) {
|
|
15278
|
-
this.currentTrail.addPoint([x, y, performance.now()]);
|
|
15279
|
-
this.update();
|
|
15280
|
-
}
|
|
15785
|
+
var snapResizingElements = (selectedElements, selectedOriginalElements, app, event, dragOffset, transformHandle) => {
|
|
15786
|
+
if (!isSnappingEnabled({ event, selectedElements, app }) || selectedElements.length === 0 || selectedElements.length === 1 && !areRoughlyEqual(selectedElements[0].angle, 0)) {
|
|
15787
|
+
return {
|
|
15788
|
+
snapOffset: { x: 0, y: 0 },
|
|
15789
|
+
snapLines: []
|
|
15790
|
+
};
|
|
15281
15791
|
}
|
|
15282
|
-
|
|
15283
|
-
|
|
15284
|
-
|
|
15285
|
-
|
|
15286
|
-
|
|
15287
|
-
|
|
15288
|
-
this.update();
|
|
15792
|
+
let [minX, minY, maxX, maxY] = getCommonBounds4(selectedOriginalElements);
|
|
15793
|
+
if (transformHandle) {
|
|
15794
|
+
if (transformHandle.includes("e")) {
|
|
15795
|
+
maxX += dragOffset.x;
|
|
15796
|
+
} else if (transformHandle.includes("w")) {
|
|
15797
|
+
minX += dragOffset.x;
|
|
15289
15798
|
}
|
|
15290
|
-
|
|
15291
|
-
|
|
15292
|
-
|
|
15293
|
-
|
|
15294
|
-
clearTrails() {
|
|
15295
|
-
this.pastTrails = [];
|
|
15296
|
-
this.currentTrail = void 0;
|
|
15297
|
-
this.update();
|
|
15298
|
-
}
|
|
15299
|
-
update() {
|
|
15300
|
-
this.start();
|
|
15301
|
-
if (this.trailAnimation) {
|
|
15302
|
-
this.trailAnimation.setAttribute("begin", "indefinite");
|
|
15303
|
-
this.trailAnimation.setAttribute("repeatCount", "indefinite");
|
|
15799
|
+
if (transformHandle.includes("n")) {
|
|
15800
|
+
minY += dragOffset.y;
|
|
15801
|
+
} else if (transformHandle.includes("s")) {
|
|
15802
|
+
maxY += dragOffset.y;
|
|
15304
15803
|
}
|
|
15305
15804
|
}
|
|
15306
|
-
|
|
15307
|
-
|
|
15308
|
-
|
|
15309
|
-
|
|
15310
|
-
|
|
15311
|
-
|
|
15312
|
-
|
|
15313
|
-
|
|
15314
|
-
|
|
15315
|
-
|
|
15316
|
-
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
|
|
15321
|
-
|
|
15322
|
-
|
|
15323
|
-
|
|
15324
|
-
|
|
15325
|
-
|
|
15326
|
-
|
|
15327
|
-
|
|
15328
|
-
|
|
15329
|
-
|
|
15330
|
-
|
|
15331
|
-
|
|
15332
|
-
|
|
15333
|
-
|
|
15334
|
-
|
|
15335
|
-
|
|
15336
|
-
|
|
15337
|
-
|
|
15805
|
+
const selectionSnapPoints = [];
|
|
15806
|
+
if (transformHandle) {
|
|
15807
|
+
switch (transformHandle) {
|
|
15808
|
+
case "e": {
|
|
15809
|
+
selectionSnapPoints.push(pointFrom18(maxX, minY), pointFrom18(maxX, maxY));
|
|
15810
|
+
break;
|
|
15811
|
+
}
|
|
15812
|
+
case "w": {
|
|
15813
|
+
selectionSnapPoints.push(pointFrom18(minX, minY), pointFrom18(minX, maxY));
|
|
15814
|
+
break;
|
|
15815
|
+
}
|
|
15816
|
+
case "n": {
|
|
15817
|
+
selectionSnapPoints.push(pointFrom18(minX, minY), pointFrom18(maxX, minY));
|
|
15818
|
+
break;
|
|
15819
|
+
}
|
|
15820
|
+
case "s": {
|
|
15821
|
+
selectionSnapPoints.push(pointFrom18(minX, maxY), pointFrom18(maxX, maxY));
|
|
15822
|
+
break;
|
|
15823
|
+
}
|
|
15824
|
+
case "ne": {
|
|
15825
|
+
selectionSnapPoints.push(pointFrom18(maxX, minY));
|
|
15826
|
+
break;
|
|
15827
|
+
}
|
|
15828
|
+
case "nw": {
|
|
15829
|
+
selectionSnapPoints.push(pointFrom18(minX, minY));
|
|
15830
|
+
break;
|
|
15831
|
+
}
|
|
15832
|
+
case "se": {
|
|
15833
|
+
selectionSnapPoints.push(pointFrom18(maxX, maxY));
|
|
15834
|
+
break;
|
|
15835
|
+
}
|
|
15836
|
+
case "sw": {
|
|
15837
|
+
selectionSnapPoints.push(pointFrom18(minX, maxY));
|
|
15838
|
+
break;
|
|
15839
|
+
}
|
|
15338
15840
|
}
|
|
15339
|
-
return true;
|
|
15340
|
-
}
|
|
15341
|
-
drawTrail(trail, state) {
|
|
15342
|
-
const _stroke = trail.getStrokeOutline(trail.options.size / state.zoom.value).map(([x, y]) => {
|
|
15343
|
-
const result = sceneCoordsToViewportCoords3(
|
|
15344
|
-
{ sceneX: x, sceneY: y },
|
|
15345
|
-
state
|
|
15346
|
-
);
|
|
15347
|
-
return [result.x, result.y];
|
|
15348
|
-
});
|
|
15349
|
-
const stroke = this.trailAnimation ? _stroke.slice(0, _stroke.length / 2) : _stroke;
|
|
15350
|
-
return getSvgPathFromStroke2(stroke, true);
|
|
15351
15841
|
}
|
|
15842
|
+
const snapDistance = getSnapDistance(app.state.zoom.value);
|
|
15843
|
+
const minOffset = {
|
|
15844
|
+
x: snapDistance,
|
|
15845
|
+
y: snapDistance
|
|
15846
|
+
};
|
|
15847
|
+
const nearestSnapsX = [];
|
|
15848
|
+
const nearestSnapsY = [];
|
|
15849
|
+
getPointSnaps(
|
|
15850
|
+
selectedOriginalElements,
|
|
15851
|
+
selectionSnapPoints,
|
|
15852
|
+
app,
|
|
15853
|
+
event,
|
|
15854
|
+
nearestSnapsX,
|
|
15855
|
+
nearestSnapsY,
|
|
15856
|
+
minOffset
|
|
15857
|
+
);
|
|
15858
|
+
const snapOffset = {
|
|
15859
|
+
x: nearestSnapsX[0]?.offset ?? 0,
|
|
15860
|
+
y: nearestSnapsY[0]?.offset ?? 0
|
|
15861
|
+
};
|
|
15862
|
+
minOffset.x = 0;
|
|
15863
|
+
minOffset.y = 0;
|
|
15864
|
+
nearestSnapsX.length = 0;
|
|
15865
|
+
nearestSnapsY.length = 0;
|
|
15866
|
+
const [x1, y1, x2, y2] = getCommonBounds4(selectedElements).map(
|
|
15867
|
+
(bound) => round(bound)
|
|
15868
|
+
);
|
|
15869
|
+
const corners = [
|
|
15870
|
+
pointFrom18(x1, y1),
|
|
15871
|
+
pointFrom18(x1, y2),
|
|
15872
|
+
pointFrom18(x2, y1),
|
|
15873
|
+
pointFrom18(x2, y2)
|
|
15874
|
+
];
|
|
15875
|
+
getPointSnaps(
|
|
15876
|
+
selectedElements,
|
|
15877
|
+
corners,
|
|
15878
|
+
app,
|
|
15879
|
+
event,
|
|
15880
|
+
nearestSnapsX,
|
|
15881
|
+
nearestSnapsY,
|
|
15882
|
+
minOffset
|
|
15883
|
+
);
|
|
15884
|
+
const pointSnapLines = createPointSnapLines(nearestSnapsX, nearestSnapsY);
|
|
15885
|
+
return {
|
|
15886
|
+
snapOffset,
|
|
15887
|
+
snapLines: pointSnapLines
|
|
15888
|
+
};
|
|
15352
15889
|
};
|
|
15353
|
-
|
|
15354
|
-
|
|
15355
|
-
|
|
15356
|
-
// laserTrails.ts
|
|
15357
|
-
var LaserTrails = class {
|
|
15358
|
-
constructor(app) {
|
|
15359
|
-
this.app = app;
|
|
15360
|
-
__publicField(this, "localTrail");
|
|
15361
|
-
__publicField(this, "collabTrails", /* @__PURE__ */ new Map());
|
|
15362
|
-
__publicField(this, "container");
|
|
15363
|
-
this.localTrail = new AnimatedTrail(app, {
|
|
15364
|
-
...this.getTrailOptions(),
|
|
15365
|
-
fill: () => DEFAULT_LASER_COLOR
|
|
15366
|
-
});
|
|
15367
|
-
}
|
|
15368
|
-
getTrailOptions() {
|
|
15890
|
+
var snapNewElement = (newElement7, app, event, origin, dragOffset, elementsMap) => {
|
|
15891
|
+
if (!isSnappingEnabled({ event, selectedElements: [newElement7], app })) {
|
|
15369
15892
|
return {
|
|
15370
|
-
|
|
15371
|
-
|
|
15372
|
-
sizeMapping: (c) => {
|
|
15373
|
-
const DECAY_TIME = 1e3;
|
|
15374
|
-
const DECAY_LENGTH = 50;
|
|
15375
|
-
const t2 = Math.max(
|
|
15376
|
-
0,
|
|
15377
|
-
1 - (performance.now() - c.pressure) / DECAY_TIME
|
|
15378
|
-
);
|
|
15379
|
-
const l = (DECAY_LENGTH - Math.min(DECAY_LENGTH, c.totalLength - c.currentIndex)) / DECAY_LENGTH;
|
|
15380
|
-
return Math.min(easeOut(l), easeOut(t2));
|
|
15381
|
-
}
|
|
15893
|
+
snapOffset: { x: 0, y: 0 },
|
|
15894
|
+
snapLines: []
|
|
15382
15895
|
};
|
|
15383
15896
|
}
|
|
15384
|
-
|
|
15385
|
-
|
|
15386
|
-
|
|
15387
|
-
|
|
15388
|
-
|
|
15389
|
-
|
|
15390
|
-
|
|
15391
|
-
|
|
15392
|
-
|
|
15393
|
-
|
|
15394
|
-
|
|
15395
|
-
|
|
15396
|
-
|
|
15397
|
-
|
|
15398
|
-
|
|
15399
|
-
|
|
15400
|
-
|
|
15401
|
-
|
|
15402
|
-
|
|
15403
|
-
|
|
15404
|
-
|
|
15405
|
-
|
|
15406
|
-
|
|
15407
|
-
|
|
15408
|
-
|
|
15409
|
-
|
|
15897
|
+
const selectionSnapPoints = [
|
|
15898
|
+
pointFrom18(origin.x + dragOffset.x, origin.y + dragOffset.y)
|
|
15899
|
+
];
|
|
15900
|
+
const snapDistance = getSnapDistance(app.state.zoom.value);
|
|
15901
|
+
const minOffset = {
|
|
15902
|
+
x: snapDistance,
|
|
15903
|
+
y: snapDistance
|
|
15904
|
+
};
|
|
15905
|
+
const nearestSnapsX = [];
|
|
15906
|
+
const nearestSnapsY = [];
|
|
15907
|
+
getPointSnaps(
|
|
15908
|
+
[newElement7],
|
|
15909
|
+
selectionSnapPoints,
|
|
15910
|
+
app,
|
|
15911
|
+
event,
|
|
15912
|
+
nearestSnapsX,
|
|
15913
|
+
nearestSnapsY,
|
|
15914
|
+
minOffset
|
|
15915
|
+
);
|
|
15916
|
+
const snapOffset = {
|
|
15917
|
+
x: nearestSnapsX[0]?.offset ?? 0,
|
|
15918
|
+
y: nearestSnapsY[0]?.offset ?? 0
|
|
15919
|
+
};
|
|
15920
|
+
minOffset.x = 0;
|
|
15921
|
+
minOffset.y = 0;
|
|
15922
|
+
nearestSnapsX.length = 0;
|
|
15923
|
+
nearestSnapsY.length = 0;
|
|
15924
|
+
const corners = getElementsCorners([newElement7], elementsMap, {
|
|
15925
|
+
boundingBoxCorners: true,
|
|
15926
|
+
omitCenter: true
|
|
15927
|
+
});
|
|
15928
|
+
getPointSnaps(
|
|
15929
|
+
[newElement7],
|
|
15930
|
+
corners,
|
|
15931
|
+
app,
|
|
15932
|
+
event,
|
|
15933
|
+
nearestSnapsX,
|
|
15934
|
+
nearestSnapsY,
|
|
15935
|
+
minOffset
|
|
15936
|
+
);
|
|
15937
|
+
const pointSnapLines = createPointSnapLines(nearestSnapsX, nearestSnapsY);
|
|
15938
|
+
return {
|
|
15939
|
+
snapOffset,
|
|
15940
|
+
snapLines: pointSnapLines
|
|
15941
|
+
};
|
|
15942
|
+
};
|
|
15943
|
+
var getSnapLinesAtPointer = (elements, app, pointer, event, elementsMap) => {
|
|
15944
|
+
if (!isSnappingEnabled({ event, selectedElements: [], app })) {
|
|
15945
|
+
return {
|
|
15946
|
+
originOffset: { x: 0, y: 0 },
|
|
15947
|
+
snapLines: []
|
|
15948
|
+
};
|
|
15410
15949
|
}
|
|
15411
|
-
|
|
15412
|
-
|
|
15413
|
-
|
|
15414
|
-
|
|
15415
|
-
|
|
15416
|
-
|
|
15417
|
-
|
|
15418
|
-
|
|
15419
|
-
|
|
15420
|
-
|
|
15421
|
-
|
|
15422
|
-
|
|
15423
|
-
|
|
15424
|
-
|
|
15950
|
+
const referenceElements = getVisibleAndNonSelectedElements(
|
|
15951
|
+
elements,
|
|
15952
|
+
[],
|
|
15953
|
+
app.state,
|
|
15954
|
+
elementsMap
|
|
15955
|
+
);
|
|
15956
|
+
const snapDistance = getSnapDistance(app.state.zoom.value);
|
|
15957
|
+
const minOffset = {
|
|
15958
|
+
x: snapDistance,
|
|
15959
|
+
y: snapDistance
|
|
15960
|
+
};
|
|
15961
|
+
const horizontalSnapLines = [];
|
|
15962
|
+
const verticalSnapLines = [];
|
|
15963
|
+
for (const referenceElement of referenceElements) {
|
|
15964
|
+
const corners = getElementsCorners([referenceElement], elementsMap);
|
|
15965
|
+
for (const corner of corners) {
|
|
15966
|
+
const offsetX = corner[0] - pointer.x;
|
|
15967
|
+
if (Math.abs(offsetX) <= Math.abs(minOffset.x)) {
|
|
15968
|
+
if (Math.abs(offsetX) < Math.abs(minOffset.x)) {
|
|
15969
|
+
verticalSnapLines.length = 0;
|
|
15970
|
+
}
|
|
15971
|
+
verticalSnapLines.push({
|
|
15972
|
+
type: "pointer",
|
|
15973
|
+
points: [corner, pointFrom18(corner[0], pointer.y)],
|
|
15974
|
+
direction: "vertical"
|
|
15425
15975
|
});
|
|
15426
|
-
|
|
15427
|
-
this.collabTrails.set(key, trail);
|
|
15976
|
+
minOffset.x = offsetX;
|
|
15428
15977
|
}
|
|
15429
|
-
|
|
15430
|
-
|
|
15431
|
-
|
|
15432
|
-
|
|
15433
|
-
if (buttonDown && !hasTrail) {
|
|
15434
|
-
trail.startPath(collaborator.pointer.x, collaborator.pointer.y);
|
|
15435
|
-
}
|
|
15436
|
-
const lastPointOriginal = !trail.hasLastPoint(
|
|
15437
|
-
collaborator.pointer.x,
|
|
15438
|
-
collaborator.pointer.y
|
|
15439
|
-
);
|
|
15440
|
-
if (buttonDown && lastPointOriginal) {
|
|
15441
|
-
trail.addPointToPath(collaborator.pointer.x, collaborator.pointer.y);
|
|
15442
|
-
}
|
|
15443
|
-
if (buttonUp && hasTrail) {
|
|
15444
|
-
trail.addPointToPath(collaborator.pointer.x, collaborator.pointer.y);
|
|
15445
|
-
trail.endPath();
|
|
15978
|
+
const offsetY = corner[1] - pointer.y;
|
|
15979
|
+
if (Math.abs(offsetY) <= Math.abs(minOffset.y)) {
|
|
15980
|
+
if (Math.abs(offsetY) < Math.abs(minOffset.y)) {
|
|
15981
|
+
horizontalSnapLines.length = 0;
|
|
15446
15982
|
}
|
|
15983
|
+
horizontalSnapLines.push({
|
|
15984
|
+
type: "pointer",
|
|
15985
|
+
points: [corner, pointFrom18(pointer.x, corner[1])],
|
|
15986
|
+
direction: "horizontal"
|
|
15987
|
+
});
|
|
15988
|
+
minOffset.y = offsetY;
|
|
15447
15989
|
}
|
|
15448
15990
|
}
|
|
15449
15991
|
}
|
|
15992
|
+
return {
|
|
15993
|
+
originOffset: {
|
|
15994
|
+
x: verticalSnapLines.length > 0 ? verticalSnapLines[0].points[0][0] - pointer.x : 0,
|
|
15995
|
+
y: horizontalSnapLines.length > 0 ? horizontalSnapLines[0].points[0][1] - pointer.y : 0
|
|
15996
|
+
},
|
|
15997
|
+
snapLines: [...verticalSnapLines, ...horizontalSnapLines]
|
|
15998
|
+
};
|
|
15999
|
+
};
|
|
16000
|
+
var isActiveToolNonLinearSnappable = (activeToolType) => {
|
|
16001
|
+
return activeToolType === TOOL_TYPE.rectangle || activeToolType === TOOL_TYPE.ellipse || activeToolType === TOOL_TYPE.diamond || activeToolType === TOOL_TYPE.frame || activeToolType === TOOL_TYPE.magicframe || activeToolType === TOOL_TYPE.image || activeToolType === TOOL_TYPE.text;
|
|
15450
16002
|
};
|
|
15451
16003
|
|
|
15452
16004
|
// scene/Renderer.ts
|
|
@@ -15587,1070 +16139,449 @@ var Renderer = class {
|
|
|
15587
16139
|
const deselectedElements = visibleElements.filter(
|
|
15588
16140
|
(element) => !selectedElementsMap.has(element.id)
|
|
15589
16141
|
);
|
|
15590
|
-
const insertionIndex = getFrameChildrenInsertionIndex(
|
|
15591
|
-
deselectedElements,
|
|
15592
|
-
frameToHighlight.id
|
|
15593
|
-
);
|
|
15594
|
-
if (insertionIndex === null) {
|
|
15595
|
-
return visibleElements;
|
|
15596
|
-
}
|
|
15597
|
-
return [
|
|
15598
|
-
...deselectedElements.slice(0, insertionIndex),
|
|
15599
|
-
...selectedElements,
|
|
15600
|
-
...deselectedElements.slice(insertionIndex)
|
|
15601
|
-
];
|
|
15602
|
-
}
|
|
15603
|
-
// NOTE Doesn't destroy everything (scene, rc, etc.) because it may not be
|
|
15604
|
-
// safe to break TS contract here (for upstream cases)
|
|
15605
|
-
destroy() {
|
|
15606
|
-
renderStaticSceneThrottled.cancel();
|
|
15607
|
-
this._getRenderableElements.clear();
|
|
15608
|
-
}
|
|
15609
|
-
};
|
|
15610
|
-
|
|
15611
|
-
// scene/scrollbars.ts
|
|
15612
|
-
import { getGlobalCSSVariable } from "@excalidraw/common";
|
|
15613
|
-
import { getCommonBounds as getCommonBounds4 } from "@excalidraw/element";
|
|
15614
|
-
var SCROLLBAR_MARGIN = 4;
|
|
15615
|
-
var SCROLLBAR_WIDTH = 6;
|
|
15616
|
-
var SCROLLBAR_COLOR = "rgba(0,0,0,0.3)";
|
|
15617
|
-
var getScrollBars = (elements, viewportWidth, viewportHeight, appState) => {
|
|
15618
|
-
if (!elements.size) {
|
|
15619
|
-
return {
|
|
15620
|
-
horizontal: null,
|
|
15621
|
-
vertical: null
|
|
15622
|
-
};
|
|
15623
|
-
}
|
|
15624
|
-
const [elementsMinX, elementsMinY, elementsMaxX, elementsMaxY] = getCommonBounds4(elements);
|
|
15625
|
-
const viewportWidthWithZoom = viewportWidth / appState.zoom.value;
|
|
15626
|
-
const viewportHeightWithZoom = viewportHeight / appState.zoom.value;
|
|
15627
|
-
const safeArea = {
|
|
15628
|
-
top: parseInt(getGlobalCSSVariable("sat")) || 0,
|
|
15629
|
-
bottom: parseInt(getGlobalCSSVariable("sab")) || 0,
|
|
15630
|
-
left: parseInt(getGlobalCSSVariable("sal")) || 0,
|
|
15631
|
-
right: parseInt(getGlobalCSSVariable("sar")) || 0
|
|
15632
|
-
};
|
|
15633
|
-
const isRTL3 = getLanguage().rtl;
|
|
15634
|
-
const viewportMinX = -appState.scrollX + safeArea.left;
|
|
15635
|
-
const viewportMinY = -appState.scrollY + safeArea.top;
|
|
15636
|
-
const viewportMaxX = viewportMinX + viewportWidthWithZoom - safeArea.right;
|
|
15637
|
-
const viewportMaxY = viewportMinY + viewportHeightWithZoom - safeArea.bottom;
|
|
15638
|
-
const sceneMinX = Math.min(elementsMinX, viewportMinX);
|
|
15639
|
-
const sceneMinY = Math.min(elementsMinY, viewportMinY);
|
|
15640
|
-
const sceneMaxX = Math.max(elementsMaxX, viewportMaxX);
|
|
15641
|
-
const sceneMaxY = Math.max(elementsMaxY, viewportMaxY);
|
|
15642
|
-
const sceneWidth = elementsMaxX - elementsMinX;
|
|
15643
|
-
const sceneHeight = elementsMaxY - elementsMinY;
|
|
15644
|
-
const extendedSceneWidth = sceneMaxX - sceneMinX;
|
|
15645
|
-
const extendedSceneHeight = sceneMaxY - sceneMinY;
|
|
15646
|
-
const scrollWidthOffset = Math.max(SCROLLBAR_MARGIN * 2, safeArea.left + safeArea.right) + SCROLLBAR_WIDTH * 2;
|
|
15647
|
-
const scrollbarWidth = viewportWidth * (viewportWidthWithZoom / extendedSceneWidth) - scrollWidthOffset;
|
|
15648
|
-
const scrollbarHeightOffset = Math.max(SCROLLBAR_MARGIN * 2, safeArea.top + safeArea.bottom) + SCROLLBAR_WIDTH * 2;
|
|
15649
|
-
const scrollbarHeight = viewportHeight * (viewportHeightWithZoom / extendedSceneHeight) - scrollbarHeightOffset;
|
|
15650
|
-
const horizontalDeltaMultiplier = extendedSceneWidth > sceneWidth ? extendedSceneWidth * appState.zoom.value / (scrollbarWidth + scrollWidthOffset) : viewportWidth / (scrollbarWidth + scrollWidthOffset);
|
|
15651
|
-
const verticalDeltaMultiplier = extendedSceneHeight > sceneHeight ? extendedSceneHeight * appState.zoom.value / (scrollbarHeight + scrollbarHeightOffset) : viewportHeight / (scrollbarHeight + scrollbarHeightOffset);
|
|
15652
|
-
return {
|
|
15653
|
-
horizontal: viewportMinX === sceneMinX && viewportMaxX === sceneMaxX ? null : {
|
|
15654
|
-
x: Math.max(safeArea.left, SCROLLBAR_MARGIN) + SCROLLBAR_WIDTH + (viewportMinX - sceneMinX) / extendedSceneWidth * viewportWidth,
|
|
15655
|
-
y: viewportHeight - SCROLLBAR_WIDTH - Math.max(SCROLLBAR_MARGIN, safeArea.bottom),
|
|
15656
|
-
width: scrollbarWidth,
|
|
15657
|
-
height: SCROLLBAR_WIDTH,
|
|
15658
|
-
deltaMultiplier: horizontalDeltaMultiplier
|
|
15659
|
-
},
|
|
15660
|
-
vertical: viewportMinY === sceneMinY && viewportMaxY === sceneMaxY ? null : {
|
|
15661
|
-
x: isRTL3 ? Math.max(safeArea.left, SCROLLBAR_MARGIN) : viewportWidth - SCROLLBAR_WIDTH - Math.max(safeArea.right, SCROLLBAR_MARGIN),
|
|
15662
|
-
y: Math.max(safeArea.top, SCROLLBAR_MARGIN) + SCROLLBAR_WIDTH + (viewportMinY - sceneMinY) / extendedSceneHeight * viewportHeight,
|
|
15663
|
-
width: SCROLLBAR_WIDTH,
|
|
15664
|
-
height: scrollbarHeight,
|
|
15665
|
-
deltaMultiplier: verticalDeltaMultiplier
|
|
15666
|
-
}
|
|
15667
|
-
};
|
|
15668
|
-
};
|
|
15669
|
-
var isOverScrollBars = (scrollBars, x, y) => {
|
|
15670
|
-
const [isOverHorizontal, isOverVertical] = [
|
|
15671
|
-
scrollBars.horizontal,
|
|
15672
|
-
scrollBars.vertical
|
|
15673
|
-
].map((scrollBar) => {
|
|
15674
|
-
return scrollBar != null && scrollBar.x <= x && x <= scrollBar.x + scrollBar.width && scrollBar.y <= y && y <= scrollBar.y + scrollBar.height;
|
|
15675
|
-
});
|
|
15676
|
-
const isOverEither = isOverHorizontal || isOverVertical;
|
|
15677
|
-
return { isOverEither, isOverHorizontal, isOverVertical };
|
|
15678
|
-
};
|
|
15679
|
-
|
|
15680
|
-
// snapping.ts
|
|
15681
|
-
import {
|
|
15682
|
-
pointFrom as pointFrom18,
|
|
15683
|
-
pointRotateRads as pointRotateRads14,
|
|
15684
|
-
rangeInclusive,
|
|
15685
|
-
rangeIntersection,
|
|
15686
|
-
rangesOverlap
|
|
15687
|
-
} from "@excalidraw/math";
|
|
15688
|
-
import { TOOL_TYPE, KEYS as KEYS34 } from "@excalidraw/common";
|
|
15689
|
-
import {
|
|
15690
|
-
getCommonBounds as getCommonBounds5,
|
|
15691
|
-
getDraggedElementsBounds,
|
|
15692
|
-
getElementAbsoluteCoords as getElementAbsoluteCoords5
|
|
15693
|
-
} from "@excalidraw/element";
|
|
15694
|
-
import { isBoundToContainer as isBoundToContainer6 } from "@excalidraw/element";
|
|
15695
|
-
import { getMaximumGroups } from "@excalidraw/element";
|
|
15696
|
-
import {
|
|
15697
|
-
getSelectedElements as getSelectedElements4,
|
|
15698
|
-
getVisibleAndNonSelectedElements
|
|
15699
|
-
} from "@excalidraw/element";
|
|
15700
|
-
var SNAP_DISTANCE = 8;
|
|
15701
|
-
var VISIBLE_GAPS_LIMIT_PER_AXIS = 99999;
|
|
15702
|
-
var getSnapDistance = (zoomValue) => {
|
|
15703
|
-
return SNAP_DISTANCE / zoomValue;
|
|
15704
|
-
};
|
|
15705
|
-
var _SnapCache = class _SnapCache {
|
|
15706
|
-
};
|
|
15707
|
-
__publicField(_SnapCache, "referenceSnapPoints", null);
|
|
15708
|
-
__publicField(_SnapCache, "visibleGaps", null);
|
|
15709
|
-
__publicField(_SnapCache, "setReferenceSnapPoints", (snapPoints) => {
|
|
15710
|
-
_SnapCache.referenceSnapPoints = snapPoints;
|
|
15711
|
-
});
|
|
15712
|
-
__publicField(_SnapCache, "getReferenceSnapPoints", () => {
|
|
15713
|
-
return _SnapCache.referenceSnapPoints;
|
|
15714
|
-
});
|
|
15715
|
-
__publicField(_SnapCache, "setVisibleGaps", (gaps) => {
|
|
15716
|
-
_SnapCache.visibleGaps = gaps;
|
|
15717
|
-
});
|
|
15718
|
-
__publicField(_SnapCache, "getVisibleGaps", () => {
|
|
15719
|
-
return _SnapCache.visibleGaps;
|
|
15720
|
-
});
|
|
15721
|
-
__publicField(_SnapCache, "destroy", () => {
|
|
15722
|
-
_SnapCache.referenceSnapPoints = null;
|
|
15723
|
-
_SnapCache.visibleGaps = null;
|
|
15724
|
-
});
|
|
15725
|
-
var SnapCache = _SnapCache;
|
|
15726
|
-
var isGridModeEnabled = (app) => app.props.gridModeEnabled ?? app.state.gridModeEnabled;
|
|
15727
|
-
var isSnappingEnabled = ({
|
|
15728
|
-
event,
|
|
15729
|
-
app,
|
|
15730
|
-
selectedElements
|
|
15731
|
-
}) => {
|
|
15732
|
-
if (event) {
|
|
15733
|
-
const isLassoDragging = app.state.activeTool.type === "lasso" && app.state.selectedElementsAreBeingDragged;
|
|
15734
|
-
return (app.state.activeTool.type !== "lasso" || isLassoDragging) && (app.state.objectsSnapModeEnabled && !event[KEYS34.CTRL_OR_CMD] || !app.state.objectsSnapModeEnabled && event[KEYS34.CTRL_OR_CMD] && !isGridModeEnabled(app));
|
|
15735
|
-
}
|
|
15736
|
-
if (selectedElements.length === 1 && selectedElements[0].type === "arrow") {
|
|
15737
|
-
return false;
|
|
15738
|
-
}
|
|
15739
|
-
return app.state.objectsSnapModeEnabled;
|
|
15740
|
-
};
|
|
15741
|
-
var areRoughlyEqual = (a, b, precision = 0.01) => {
|
|
15742
|
-
return Math.abs(a - b) <= precision;
|
|
15743
|
-
};
|
|
15744
|
-
var getElementsCorners = (elements, elementsMap, {
|
|
15745
|
-
omitCenter,
|
|
15746
|
-
boundingBoxCorners,
|
|
15747
|
-
dragOffset
|
|
15748
|
-
} = {
|
|
15749
|
-
omitCenter: false,
|
|
15750
|
-
boundingBoxCorners: false
|
|
15751
|
-
}) => {
|
|
15752
|
-
let result = [];
|
|
15753
|
-
if (elements.length === 1) {
|
|
15754
|
-
const element = elements[0];
|
|
15755
|
-
let [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords5(
|
|
15756
|
-
element,
|
|
15757
|
-
elementsMap
|
|
15758
|
-
);
|
|
15759
|
-
if (dragOffset) {
|
|
15760
|
-
x1 += dragOffset.x;
|
|
15761
|
-
x2 += dragOffset.x;
|
|
15762
|
-
cx += dragOffset.x;
|
|
15763
|
-
y1 += dragOffset.y;
|
|
15764
|
-
y2 += dragOffset.y;
|
|
15765
|
-
cy += dragOffset.y;
|
|
15766
|
-
}
|
|
15767
|
-
const halfWidth = (x2 - x1) / 2;
|
|
15768
|
-
const halfHeight = (y2 - y1) / 2;
|
|
15769
|
-
if ((element.type === "diamond" || element.type === "ellipse") && !boundingBoxCorners) {
|
|
15770
|
-
const leftMid = pointRotateRads14(
|
|
15771
|
-
pointFrom18(x1, y1 + halfHeight),
|
|
15772
|
-
pointFrom18(cx, cy),
|
|
15773
|
-
element.angle
|
|
15774
|
-
);
|
|
15775
|
-
const topMid = pointRotateRads14(
|
|
15776
|
-
pointFrom18(x1 + halfWidth, y1),
|
|
15777
|
-
pointFrom18(cx, cy),
|
|
15778
|
-
element.angle
|
|
15779
|
-
);
|
|
15780
|
-
const rightMid = pointRotateRads14(
|
|
15781
|
-
pointFrom18(x2, y1 + halfHeight),
|
|
15782
|
-
pointFrom18(cx, cy),
|
|
15783
|
-
element.angle
|
|
15784
|
-
);
|
|
15785
|
-
const bottomMid = pointRotateRads14(
|
|
15786
|
-
pointFrom18(x1 + halfWidth, y2),
|
|
15787
|
-
pointFrom18(cx, cy),
|
|
15788
|
-
element.angle
|
|
15789
|
-
);
|
|
15790
|
-
const center = pointFrom18(cx, cy);
|
|
15791
|
-
result = omitCenter ? [leftMid, topMid, rightMid, bottomMid] : [leftMid, topMid, rightMid, bottomMid, center];
|
|
15792
|
-
} else {
|
|
15793
|
-
const topLeft = pointRotateRads14(
|
|
15794
|
-
pointFrom18(x1, y1),
|
|
15795
|
-
pointFrom18(cx, cy),
|
|
15796
|
-
element.angle
|
|
15797
|
-
);
|
|
15798
|
-
const topRight = pointRotateRads14(
|
|
15799
|
-
pointFrom18(x2, y1),
|
|
15800
|
-
pointFrom18(cx, cy),
|
|
15801
|
-
element.angle
|
|
15802
|
-
);
|
|
15803
|
-
const bottomLeft = pointRotateRads14(
|
|
15804
|
-
pointFrom18(x1, y2),
|
|
15805
|
-
pointFrom18(cx, cy),
|
|
15806
|
-
element.angle
|
|
15807
|
-
);
|
|
15808
|
-
const bottomRight = pointRotateRads14(
|
|
15809
|
-
pointFrom18(x2, y2),
|
|
15810
|
-
pointFrom18(cx, cy),
|
|
15811
|
-
element.angle
|
|
15812
|
-
);
|
|
15813
|
-
const center = pointFrom18(cx, cy);
|
|
15814
|
-
result = omitCenter ? [topLeft, topRight, bottomLeft, bottomRight] : [topLeft, topRight, bottomLeft, bottomRight, center];
|
|
15815
|
-
}
|
|
15816
|
-
} else if (elements.length > 1) {
|
|
15817
|
-
const [minX, minY, maxX, maxY] = getDraggedElementsBounds(
|
|
15818
|
-
elements,
|
|
15819
|
-
dragOffset ?? { x: 0, y: 0 }
|
|
15820
|
-
);
|
|
15821
|
-
const width = maxX - minX;
|
|
15822
|
-
const height = maxY - minY;
|
|
15823
|
-
const topLeft = pointFrom18(minX, minY);
|
|
15824
|
-
const topRight = pointFrom18(maxX, minY);
|
|
15825
|
-
const bottomLeft = pointFrom18(minX, maxY);
|
|
15826
|
-
const bottomRight = pointFrom18(maxX, maxY);
|
|
15827
|
-
const center = pointFrom18(minX + width / 2, minY + height / 2);
|
|
15828
|
-
result = omitCenter ? [topLeft, topRight, bottomLeft, bottomRight] : [topLeft, topRight, bottomLeft, bottomRight, center];
|
|
15829
|
-
}
|
|
15830
|
-
return result.map((p) => pointFrom18(round(p[0]), round(p[1])));
|
|
15831
|
-
};
|
|
15832
|
-
var getReferenceElements = (elements, selectedElements, appState, elementsMap) => getVisibleAndNonSelectedElements(
|
|
15833
|
-
elements,
|
|
15834
|
-
selectedElements,
|
|
15835
|
-
appState,
|
|
15836
|
-
elementsMap
|
|
15837
|
-
);
|
|
15838
|
-
var getVisibleGaps = (elements, selectedElements, appState, elementsMap) => {
|
|
15839
|
-
const referenceElements = getReferenceElements(
|
|
15840
|
-
elements,
|
|
15841
|
-
selectedElements,
|
|
15842
|
-
appState,
|
|
15843
|
-
elementsMap
|
|
15844
|
-
);
|
|
15845
|
-
const referenceBounds = getMaximumGroups(referenceElements, elementsMap).filter(
|
|
15846
|
-
(elementsGroup) => !(elementsGroup.length === 1 && isBoundToContainer6(elementsGroup[0]))
|
|
15847
|
-
).map(
|
|
15848
|
-
(group) => getCommonBounds5(group).map(
|
|
15849
|
-
(bound) => round(bound)
|
|
15850
|
-
)
|
|
15851
|
-
);
|
|
15852
|
-
const horizontallySorted = referenceBounds.sort((a, b) => a[0] - b[0]);
|
|
15853
|
-
const horizontalGaps = [];
|
|
15854
|
-
let c = 0;
|
|
15855
|
-
horizontal:
|
|
15856
|
-
for (let i = 0; i < horizontallySorted.length; i++) {
|
|
15857
|
-
const startBounds = horizontallySorted[i];
|
|
15858
|
-
for (let j = i + 1; j < horizontallySorted.length; j++) {
|
|
15859
|
-
if (++c > VISIBLE_GAPS_LIMIT_PER_AXIS) {
|
|
15860
|
-
break horizontal;
|
|
15861
|
-
}
|
|
15862
|
-
const endBounds = horizontallySorted[j];
|
|
15863
|
-
const [, startMinY, startMaxX, startMaxY] = startBounds;
|
|
15864
|
-
const [endMinX, endMinY, , endMaxY] = endBounds;
|
|
15865
|
-
if (startMaxX < endMinX && rangesOverlap(
|
|
15866
|
-
rangeInclusive(startMinY, startMaxY),
|
|
15867
|
-
rangeInclusive(endMinY, endMaxY)
|
|
15868
|
-
)) {
|
|
15869
|
-
horizontalGaps.push({
|
|
15870
|
-
startBounds,
|
|
15871
|
-
endBounds,
|
|
15872
|
-
startSide: [
|
|
15873
|
-
pointFrom18(startMaxX, startMinY),
|
|
15874
|
-
pointFrom18(startMaxX, startMaxY)
|
|
15875
|
-
],
|
|
15876
|
-
endSide: [pointFrom18(endMinX, endMinY), pointFrom18(endMinX, endMaxY)],
|
|
15877
|
-
length: endMinX - startMaxX,
|
|
15878
|
-
overlap: rangeIntersection(
|
|
15879
|
-
rangeInclusive(startMinY, startMaxY),
|
|
15880
|
-
rangeInclusive(endMinY, endMaxY)
|
|
15881
|
-
)
|
|
15882
|
-
});
|
|
15883
|
-
}
|
|
15884
|
-
}
|
|
15885
|
-
}
|
|
15886
|
-
const verticallySorted = referenceBounds.sort((a, b) => a[1] - b[1]);
|
|
15887
|
-
const verticalGaps = [];
|
|
15888
|
-
c = 0;
|
|
15889
|
-
vertical:
|
|
15890
|
-
for (let i = 0; i < verticallySorted.length; i++) {
|
|
15891
|
-
const startBounds = verticallySorted[i];
|
|
15892
|
-
for (let j = i + 1; j < verticallySorted.length; j++) {
|
|
15893
|
-
if (++c > VISIBLE_GAPS_LIMIT_PER_AXIS) {
|
|
15894
|
-
break vertical;
|
|
15895
|
-
}
|
|
15896
|
-
const endBounds = verticallySorted[j];
|
|
15897
|
-
const [startMinX, , startMaxX, startMaxY] = startBounds;
|
|
15898
|
-
const [endMinX, endMinY, endMaxX] = endBounds;
|
|
15899
|
-
if (startMaxY < endMinY && rangesOverlap(
|
|
15900
|
-
rangeInclusive(startMinX, startMaxX),
|
|
15901
|
-
rangeInclusive(endMinX, endMaxX)
|
|
15902
|
-
)) {
|
|
15903
|
-
verticalGaps.push({
|
|
15904
|
-
startBounds,
|
|
15905
|
-
endBounds,
|
|
15906
|
-
startSide: [
|
|
15907
|
-
pointFrom18(startMinX, startMaxY),
|
|
15908
|
-
pointFrom18(startMaxX, startMaxY)
|
|
15909
|
-
],
|
|
15910
|
-
endSide: [pointFrom18(endMinX, endMinY), pointFrom18(endMaxX, endMinY)],
|
|
15911
|
-
length: endMinY - startMaxY,
|
|
15912
|
-
overlap: rangeIntersection(
|
|
15913
|
-
rangeInclusive(startMinX, startMaxX),
|
|
15914
|
-
rangeInclusive(endMinX, endMaxX)
|
|
15915
|
-
)
|
|
15916
|
-
});
|
|
15917
|
-
}
|
|
15918
|
-
}
|
|
15919
|
-
}
|
|
15920
|
-
return {
|
|
15921
|
-
horizontalGaps,
|
|
15922
|
-
verticalGaps
|
|
15923
|
-
};
|
|
15924
|
-
};
|
|
15925
|
-
var getGapSnaps = (selectedElements, dragOffset, app, event, nearestSnapsX, nearestSnapsY, minOffset) => {
|
|
15926
|
-
if (!isSnappingEnabled({ app, event, selectedElements })) {
|
|
15927
|
-
return [];
|
|
15928
|
-
}
|
|
15929
|
-
if (selectedElements.length === 0) {
|
|
15930
|
-
return [];
|
|
15931
|
-
}
|
|
15932
|
-
const visibleGaps = SnapCache.getVisibleGaps();
|
|
15933
|
-
if (visibleGaps) {
|
|
15934
|
-
const { horizontalGaps, verticalGaps } = visibleGaps;
|
|
15935
|
-
const [minX, minY, maxX, maxY] = getDraggedElementsBounds(
|
|
15936
|
-
selectedElements,
|
|
15937
|
-
dragOffset
|
|
15938
|
-
).map((bound) => round(bound));
|
|
15939
|
-
const centerX = (minX + maxX) / 2;
|
|
15940
|
-
const centerY = (minY + maxY) / 2;
|
|
15941
|
-
for (const gap of horizontalGaps) {
|
|
15942
|
-
if (!rangesOverlap(rangeInclusive(minY, maxY), gap.overlap)) {
|
|
15943
|
-
continue;
|
|
15944
|
-
}
|
|
15945
|
-
const gapMidX = gap.startSide[0][0] + gap.length / 2;
|
|
15946
|
-
const centerOffset = round(gapMidX - centerX);
|
|
15947
|
-
const gapIsLargerThanSelection = gap.length > maxX - minX;
|
|
15948
|
-
if (gapIsLargerThanSelection && Math.abs(centerOffset) <= minOffset.x) {
|
|
15949
|
-
if (Math.abs(centerOffset) < minOffset.x) {
|
|
15950
|
-
nearestSnapsX.length = 0;
|
|
15951
|
-
}
|
|
15952
|
-
minOffset.x = Math.abs(centerOffset);
|
|
15953
|
-
const snap = {
|
|
15954
|
-
type: "gap",
|
|
15955
|
-
direction: "center_horizontal",
|
|
15956
|
-
gap,
|
|
15957
|
-
offset: centerOffset
|
|
15958
|
-
};
|
|
15959
|
-
nearestSnapsX.push(snap);
|
|
15960
|
-
continue;
|
|
15961
|
-
}
|
|
15962
|
-
const [, , endMaxX] = gap.endBounds;
|
|
15963
|
-
const distanceToEndElementX = minX - endMaxX;
|
|
15964
|
-
const sideOffsetRight = round(gap.length - distanceToEndElementX);
|
|
15965
|
-
if (Math.abs(sideOffsetRight) <= minOffset.x) {
|
|
15966
|
-
if (Math.abs(sideOffsetRight) < minOffset.x) {
|
|
15967
|
-
nearestSnapsX.length = 0;
|
|
15968
|
-
}
|
|
15969
|
-
minOffset.x = Math.abs(sideOffsetRight);
|
|
15970
|
-
const snap = {
|
|
15971
|
-
type: "gap",
|
|
15972
|
-
direction: "side_right",
|
|
15973
|
-
gap,
|
|
15974
|
-
offset: sideOffsetRight
|
|
15975
|
-
};
|
|
15976
|
-
nearestSnapsX.push(snap);
|
|
15977
|
-
continue;
|
|
15978
|
-
}
|
|
15979
|
-
const [startMinX, , ,] = gap.startBounds;
|
|
15980
|
-
const distanceToStartElementX = startMinX - maxX;
|
|
15981
|
-
const sideOffsetLeft = round(distanceToStartElementX - gap.length);
|
|
15982
|
-
if (Math.abs(sideOffsetLeft) <= minOffset.x) {
|
|
15983
|
-
if (Math.abs(sideOffsetLeft) < minOffset.x) {
|
|
15984
|
-
nearestSnapsX.length = 0;
|
|
15985
|
-
}
|
|
15986
|
-
minOffset.x = Math.abs(sideOffsetLeft);
|
|
15987
|
-
const snap = {
|
|
15988
|
-
type: "gap",
|
|
15989
|
-
direction: "side_left",
|
|
15990
|
-
gap,
|
|
15991
|
-
offset: sideOffsetLeft
|
|
15992
|
-
};
|
|
15993
|
-
nearestSnapsX.push(snap);
|
|
15994
|
-
continue;
|
|
15995
|
-
}
|
|
15996
|
-
}
|
|
15997
|
-
for (const gap of verticalGaps) {
|
|
15998
|
-
if (!rangesOverlap(rangeInclusive(minX, maxX), gap.overlap)) {
|
|
15999
|
-
continue;
|
|
16000
|
-
}
|
|
16001
|
-
const gapMidY = gap.startSide[0][1] + gap.length / 2;
|
|
16002
|
-
const centerOffset = round(gapMidY - centerY);
|
|
16003
|
-
const gapIsLargerThanSelection = gap.length > maxY - minY;
|
|
16004
|
-
if (gapIsLargerThanSelection && Math.abs(centerOffset) <= minOffset.y) {
|
|
16005
|
-
if (Math.abs(centerOffset) < minOffset.y) {
|
|
16006
|
-
nearestSnapsY.length = 0;
|
|
16007
|
-
}
|
|
16008
|
-
minOffset.y = Math.abs(centerOffset);
|
|
16009
|
-
const snap = {
|
|
16010
|
-
type: "gap",
|
|
16011
|
-
direction: "center_vertical",
|
|
16012
|
-
gap,
|
|
16013
|
-
offset: centerOffset
|
|
16014
|
-
};
|
|
16015
|
-
nearestSnapsY.push(snap);
|
|
16016
|
-
continue;
|
|
16017
|
-
}
|
|
16018
|
-
const [, startMinY, ,] = gap.startBounds;
|
|
16019
|
-
const distanceToStartElementY = startMinY - maxY;
|
|
16020
|
-
const sideOffsetTop = round(distanceToStartElementY - gap.length);
|
|
16021
|
-
if (Math.abs(sideOffsetTop) <= minOffset.y) {
|
|
16022
|
-
if (Math.abs(sideOffsetTop) < minOffset.y) {
|
|
16023
|
-
nearestSnapsY.length = 0;
|
|
16024
|
-
}
|
|
16025
|
-
minOffset.y = Math.abs(sideOffsetTop);
|
|
16026
|
-
const snap = {
|
|
16027
|
-
type: "gap",
|
|
16028
|
-
direction: "side_top",
|
|
16029
|
-
gap,
|
|
16030
|
-
offset: sideOffsetTop
|
|
16031
|
-
};
|
|
16032
|
-
nearestSnapsY.push(snap);
|
|
16033
|
-
continue;
|
|
16034
|
-
}
|
|
16035
|
-
const [, , , endMaxY] = gap.endBounds;
|
|
16036
|
-
const distanceToEndElementY = round(minY - endMaxY);
|
|
16037
|
-
const sideOffsetBottom = gap.length - distanceToEndElementY;
|
|
16038
|
-
if (Math.abs(sideOffsetBottom) <= minOffset.y) {
|
|
16039
|
-
if (Math.abs(sideOffsetBottom) < minOffset.y) {
|
|
16040
|
-
nearestSnapsY.length = 0;
|
|
16041
|
-
}
|
|
16042
|
-
minOffset.y = Math.abs(sideOffsetBottom);
|
|
16043
|
-
const snap = {
|
|
16044
|
-
type: "gap",
|
|
16045
|
-
direction: "side_bottom",
|
|
16046
|
-
gap,
|
|
16047
|
-
offset: sideOffsetBottom
|
|
16048
|
-
};
|
|
16049
|
-
nearestSnapsY.push(snap);
|
|
16050
|
-
continue;
|
|
16051
|
-
}
|
|
16142
|
+
const insertionIndex = getFrameChildrenInsertionIndex(
|
|
16143
|
+
deselectedElements,
|
|
16144
|
+
frameToHighlight.id
|
|
16145
|
+
);
|
|
16146
|
+
if (insertionIndex === null) {
|
|
16147
|
+
return visibleElements;
|
|
16052
16148
|
}
|
|
16149
|
+
return [
|
|
16150
|
+
...deselectedElements.slice(0, insertionIndex),
|
|
16151
|
+
...selectedElements,
|
|
16152
|
+
...deselectedElements.slice(insertionIndex)
|
|
16153
|
+
];
|
|
16154
|
+
}
|
|
16155
|
+
// NOTE Doesn't destroy everything (scene, rc, etc.) because it may not be
|
|
16156
|
+
// safe to break TS contract here (for upstream cases)
|
|
16157
|
+
destroy() {
|
|
16158
|
+
renderStaticSceneThrottled.cancel();
|
|
16159
|
+
this._getRenderableElements.clear();
|
|
16053
16160
|
}
|
|
16054
16161
|
};
|
|
16055
|
-
|
|
16056
|
-
|
|
16057
|
-
|
|
16058
|
-
|
|
16059
|
-
|
|
16060
|
-
|
|
16162
|
+
|
|
16163
|
+
// components/ElementCanvasButtons.tsx
|
|
16164
|
+
import { sceneCoordsToViewportCoords as sceneCoordsToViewportCoords2 } from "@excalidraw/common";
|
|
16165
|
+
import { getElementAbsoluteCoords as getElementAbsoluteCoords5 } from "@excalidraw/element";
|
|
16166
|
+
import { jsx as jsx57 } from "react/jsx-runtime";
|
|
16167
|
+
var CONTAINER_PADDING = 5;
|
|
16168
|
+
var getContainerCoords2 = (element, appState, elementsMap) => {
|
|
16169
|
+
const [x1, y1] = getElementAbsoluteCoords5(element, elementsMap);
|
|
16170
|
+
const { x: viewportX, y: viewportY } = sceneCoordsToViewportCoords2(
|
|
16171
|
+
{ sceneX: x1 + element.width, sceneY: y1 },
|
|
16172
|
+
appState
|
|
16061
16173
|
);
|
|
16062
|
-
|
|
16063
|
-
|
|
16064
|
-
|
|
16174
|
+
const x = viewportX - appState.offsetLeft + 10;
|
|
16175
|
+
const y = viewportY - appState.offsetTop;
|
|
16176
|
+
return { x, y };
|
|
16065
16177
|
};
|
|
16066
|
-
var
|
|
16067
|
-
|
|
16068
|
-
|
|
16069
|
-
|
|
16070
|
-
|
|
16071
|
-
|
|
16072
|
-
|
|
16073
|
-
|
|
16074
|
-
const offsetX = otherSnapPoint[0] - thisSnapPoint[0];
|
|
16075
|
-
const offsetY = otherSnapPoint[1] - thisSnapPoint[1];
|
|
16076
|
-
if (Math.abs(offsetX) <= minOffset.x) {
|
|
16077
|
-
if (Math.abs(offsetX) < minOffset.x) {
|
|
16078
|
-
nearestSnapsX.length = 0;
|
|
16079
|
-
}
|
|
16080
|
-
nearestSnapsX.push({
|
|
16081
|
-
type: "point",
|
|
16082
|
-
points: [thisSnapPoint, otherSnapPoint],
|
|
16083
|
-
offset: offsetX
|
|
16084
|
-
});
|
|
16085
|
-
minOffset.x = Math.abs(offsetX);
|
|
16086
|
-
}
|
|
16087
|
-
if (Math.abs(offsetY) <= minOffset.y) {
|
|
16088
|
-
if (Math.abs(offsetY) < minOffset.y) {
|
|
16089
|
-
nearestSnapsY.length = 0;
|
|
16090
|
-
}
|
|
16091
|
-
nearestSnapsY.push({
|
|
16092
|
-
type: "point",
|
|
16093
|
-
points: [thisSnapPoint, otherSnapPoint],
|
|
16094
|
-
offset: offsetY
|
|
16095
|
-
});
|
|
16096
|
-
minOffset.y = Math.abs(offsetY);
|
|
16097
|
-
}
|
|
16098
|
-
}
|
|
16099
|
-
}
|
|
16178
|
+
var ElementCanvasButtons = ({
|
|
16179
|
+
children,
|
|
16180
|
+
element,
|
|
16181
|
+
elementsMap
|
|
16182
|
+
}) => {
|
|
16183
|
+
const appState = useExcalidrawAppState();
|
|
16184
|
+
if (appState.contextMenu || appState.newElement || appState.resizingElement || appState.isRotating || appState.openMenu || appState.viewModeEnabled) {
|
|
16185
|
+
return null;
|
|
16100
16186
|
}
|
|
16101
|
-
};
|
|
16102
|
-
|
|
16103
|
-
|
|
16104
|
-
|
|
16105
|
-
|
|
16106
|
-
|
|
16107
|
-
|
|
16108
|
-
|
|
16109
|
-
|
|
16187
|
+
const { x, y } = getContainerCoords2(element, appState, elementsMap);
|
|
16188
|
+
return /* @__PURE__ */ jsx57(
|
|
16189
|
+
"div",
|
|
16190
|
+
{
|
|
16191
|
+
className: "excalidraw-canvas-buttons",
|
|
16192
|
+
style: {
|
|
16193
|
+
top: `${y}px`,
|
|
16194
|
+
left: `${x}px`,
|
|
16195
|
+
// width: CONTAINER_WIDTH,
|
|
16196
|
+
padding: CONTAINER_PADDING
|
|
16110
16197
|
},
|
|
16111
|
-
|
|
16112
|
-
}
|
|
16113
|
-
}
|
|
16114
|
-
dragOffset.x = round(dragOffset.x);
|
|
16115
|
-
dragOffset.y = round(dragOffset.y);
|
|
16116
|
-
const nearestSnapsX = [];
|
|
16117
|
-
const nearestSnapsY = [];
|
|
16118
|
-
const snapDistance = getSnapDistance(appState.zoom.value);
|
|
16119
|
-
const minOffset = {
|
|
16120
|
-
x: snapDistance,
|
|
16121
|
-
y: snapDistance
|
|
16122
|
-
};
|
|
16123
|
-
const selectionPoints = getElementsCorners(selectedElements, elementsMap, {
|
|
16124
|
-
dragOffset
|
|
16125
|
-
});
|
|
16126
|
-
getPointSnaps(
|
|
16127
|
-
selectedElements,
|
|
16128
|
-
selectionPoints,
|
|
16129
|
-
app,
|
|
16130
|
-
event,
|
|
16131
|
-
nearestSnapsX,
|
|
16132
|
-
nearestSnapsY,
|
|
16133
|
-
minOffset
|
|
16134
|
-
);
|
|
16135
|
-
getGapSnaps(
|
|
16136
|
-
selectedElements,
|
|
16137
|
-
dragOffset,
|
|
16138
|
-
app,
|
|
16139
|
-
event,
|
|
16140
|
-
nearestSnapsX,
|
|
16141
|
-
nearestSnapsY,
|
|
16142
|
-
minOffset
|
|
16143
|
-
);
|
|
16144
|
-
const snapOffset = {
|
|
16145
|
-
x: nearestSnapsX[0]?.offset ?? 0,
|
|
16146
|
-
y: nearestSnapsY[0]?.offset ?? 0
|
|
16147
|
-
};
|
|
16148
|
-
minOffset.x = 0;
|
|
16149
|
-
minOffset.y = 0;
|
|
16150
|
-
nearestSnapsX.length = 0;
|
|
16151
|
-
nearestSnapsY.length = 0;
|
|
16152
|
-
const newDragOffset = {
|
|
16153
|
-
x: round(dragOffset.x + snapOffset.x),
|
|
16154
|
-
y: round(dragOffset.y + snapOffset.y)
|
|
16155
|
-
};
|
|
16156
|
-
getPointSnaps(
|
|
16157
|
-
selectedElements,
|
|
16158
|
-
getElementsCorners(selectedElements, elementsMap, {
|
|
16159
|
-
dragOffset: newDragOffset
|
|
16160
|
-
}),
|
|
16161
|
-
app,
|
|
16162
|
-
event,
|
|
16163
|
-
nearestSnapsX,
|
|
16164
|
-
nearestSnapsY,
|
|
16165
|
-
minOffset
|
|
16166
|
-
);
|
|
16167
|
-
getGapSnaps(
|
|
16168
|
-
selectedElements,
|
|
16169
|
-
newDragOffset,
|
|
16170
|
-
app,
|
|
16171
|
-
event,
|
|
16172
|
-
nearestSnapsX,
|
|
16173
|
-
nearestSnapsY,
|
|
16174
|
-
minOffset
|
|
16175
|
-
);
|
|
16176
|
-
const pointSnapLines = createPointSnapLines(nearestSnapsX, nearestSnapsY);
|
|
16177
|
-
const gapSnapLines = createGapSnapLines(
|
|
16178
|
-
selectedElements,
|
|
16179
|
-
newDragOffset,
|
|
16180
|
-
[...nearestSnapsX, ...nearestSnapsY].filter(
|
|
16181
|
-
(snap) => snap.type === "gap"
|
|
16182
|
-
)
|
|
16198
|
+
children
|
|
16199
|
+
}
|
|
16183
16200
|
);
|
|
16184
|
-
return {
|
|
16185
|
-
snapOffset,
|
|
16186
|
-
snapLines: [...pointSnapLines, ...gapSnapLines]
|
|
16187
|
-
};
|
|
16188
16201
|
};
|
|
16189
|
-
|
|
16190
|
-
|
|
16191
|
-
|
|
16202
|
+
|
|
16203
|
+
// laserTrails.ts
|
|
16204
|
+
import { DEFAULT_LASER_COLOR, easeOut } from "@excalidraw/common";
|
|
16205
|
+
|
|
16206
|
+
// animatedTrail.ts
|
|
16207
|
+
import { LaserPointer } from "@excalidraw/laser-pointer";
|
|
16208
|
+
import {
|
|
16209
|
+
SVG_NS,
|
|
16210
|
+
getSvgPathFromStroke as getSvgPathFromStroke2,
|
|
16211
|
+
sceneCoordsToViewportCoords as sceneCoordsToViewportCoords3
|
|
16212
|
+
} from "@excalidraw/common";
|
|
16213
|
+
|
|
16214
|
+
// reactUtils.ts
|
|
16215
|
+
import { version as ReactVersion } from "react";
|
|
16216
|
+
import { unstable_batchedUpdates } from "react-dom";
|
|
16217
|
+
import { throttleRAF } from "@excalidraw/common";
|
|
16218
|
+
var withBatchedUpdates = (func) => (event) => {
|
|
16219
|
+
unstable_batchedUpdates(func, event);
|
|
16192
16220
|
};
|
|
16193
|
-
var
|
|
16194
|
-
|
|
16195
|
-
|
|
16196
|
-
|
|
16197
|
-
if (!map.has(key)) {
|
|
16198
|
-
map.set(key, point);
|
|
16199
|
-
}
|
|
16200
|
-
}
|
|
16201
|
-
return Array.from(map.values());
|
|
16221
|
+
var withBatchedUpdatesThrottled = (func) => {
|
|
16222
|
+
return throttleRAF((event) => {
|
|
16223
|
+
unstable_batchedUpdates(func, event);
|
|
16224
|
+
});
|
|
16202
16225
|
};
|
|
16203
|
-
var
|
|
16204
|
-
|
|
16205
|
-
|
|
16206
|
-
|
|
16207
|
-
|
|
16208
|
-
|
|
16209
|
-
|
|
16210
|
-
if (!snapsX[key]) {
|
|
16211
|
-
snapsX[key] = [];
|
|
16212
|
-
}
|
|
16213
|
-
snapsX[key].push(
|
|
16214
|
-
...snap.points.map(
|
|
16215
|
-
(p) => pointFrom18(round(p[0]), round(p[1]))
|
|
16216
|
-
)
|
|
16217
|
-
);
|
|
16218
|
-
}
|
|
16219
|
-
}
|
|
16226
|
+
var isRenderThrottlingEnabled = (() => {
|
|
16227
|
+
let IS_REACT_18_AND_UP;
|
|
16228
|
+
try {
|
|
16229
|
+
const version = ReactVersion.split(".");
|
|
16230
|
+
IS_REACT_18_AND_UP = Number(version[0]) > 17;
|
|
16231
|
+
} catch {
|
|
16232
|
+
IS_REACT_18_AND_UP = false;
|
|
16220
16233
|
}
|
|
16221
|
-
|
|
16222
|
-
|
|
16223
|
-
|
|
16224
|
-
|
|
16225
|
-
if (!
|
|
16226
|
-
|
|
16234
|
+
let hasWarned = false;
|
|
16235
|
+
return () => {
|
|
16236
|
+
if (window.EXCALIDRAW_THROTTLE_RENDER === true) {
|
|
16237
|
+
if (!IS_REACT_18_AND_UP) {
|
|
16238
|
+
if (!hasWarned) {
|
|
16239
|
+
hasWarned = true;
|
|
16240
|
+
console.warn(
|
|
16241
|
+
"Excalidraw: render throttling is disabled on React versions < 18."
|
|
16242
|
+
);
|
|
16227
16243
|
}
|
|
16228
|
-
|
|
16229
|
-
...snap.points.map(
|
|
16230
|
-
(p) => pointFrom18(round(p[0]), round(p[1]))
|
|
16231
|
-
)
|
|
16232
|
-
);
|
|
16244
|
+
return false;
|
|
16233
16245
|
}
|
|
16246
|
+
return true;
|
|
16247
|
+
}
|
|
16248
|
+
return false;
|
|
16249
|
+
};
|
|
16250
|
+
})();
|
|
16251
|
+
|
|
16252
|
+
// renderer/animation.ts
|
|
16253
|
+
var _AnimationController = class _AnimationController {
|
|
16254
|
+
static start(key, animation) {
|
|
16255
|
+
if (_AnimationController.animations.has(key)) {
|
|
16256
|
+
return;
|
|
16257
|
+
}
|
|
16258
|
+
const initialState = animation({
|
|
16259
|
+
deltaTime: 0,
|
|
16260
|
+
state: void 0
|
|
16261
|
+
});
|
|
16262
|
+
if (initialState) {
|
|
16263
|
+
_AnimationController.animations.set(key, {
|
|
16264
|
+
animation,
|
|
16265
|
+
lastTime: 0,
|
|
16266
|
+
state: initialState
|
|
16267
|
+
});
|
|
16268
|
+
_AnimationController.scheduleNextFrame();
|
|
16234
16269
|
}
|
|
16235
16270
|
}
|
|
16236
|
-
|
|
16237
|
-
|
|
16238
|
-
|
|
16239
|
-
|
|
16240
|
-
|
|
16241
|
-
|
|
16242
|
-
|
|
16243
|
-
|
|
16244
|
-
|
|
16245
|
-
|
|
16246
|
-
|
|
16247
|
-
|
|
16248
|
-
type: "
|
|
16249
|
-
points: dedupePoints(
|
|
16250
|
-
points.map((p) => {
|
|
16251
|
-
return pointFrom18(p[0], Number(key));
|
|
16252
|
-
}).sort((a, b) => a[0] - b[0])
|
|
16253
|
-
)
|
|
16271
|
+
static scheduleNextFrame() {
|
|
16272
|
+
if (_AnimationController.scheduledFrame) {
|
|
16273
|
+
return;
|
|
16274
|
+
}
|
|
16275
|
+
if (isRenderThrottlingEnabled()) {
|
|
16276
|
+
_AnimationController.scheduledFrame = {
|
|
16277
|
+
id: requestAnimationFrame(_AnimationController.tick),
|
|
16278
|
+
type: "raf"
|
|
16279
|
+
};
|
|
16280
|
+
} else {
|
|
16281
|
+
_AnimationController.scheduledFrame = {
|
|
16282
|
+
id: setTimeout(_AnimationController.tick, 0),
|
|
16283
|
+
type: "timeout"
|
|
16254
16284
|
};
|
|
16255
|
-
})
|
|
16256
|
-
);
|
|
16257
|
-
};
|
|
16258
|
-
var dedupeGapSnapLines = (gapSnapLines) => {
|
|
16259
|
-
const map = /* @__PURE__ */ new Map();
|
|
16260
|
-
for (const gapSnapLine of gapSnapLines) {
|
|
16261
|
-
const key = gapSnapLine.points.flat().map((point) => [round(point)]).join(",");
|
|
16262
|
-
if (!map.has(key)) {
|
|
16263
|
-
map.set(key, gapSnapLine);
|
|
16264
16285
|
}
|
|
16265
16286
|
}
|
|
16266
|
-
|
|
16267
|
-
|
|
16268
|
-
|
|
16269
|
-
|
|
16270
|
-
|
|
16271
|
-
|
|
16272
|
-
|
|
16273
|
-
|
|
16274
|
-
|
|
16275
|
-
|
|
16276
|
-
|
|
16277
|
-
|
|
16278
|
-
|
|
16279
|
-
|
|
16280
|
-
|
|
16281
|
-
|
|
16282
|
-
|
|
16283
|
-
|
|
16284
|
-
|
|
16285
|
-
|
|
16286
|
-
|
|
16287
|
-
|
|
16288
|
-
|
|
16289
|
-
|
|
16290
|
-
|
|
16291
|
-
|
|
16292
|
-
|
|
16293
|
-
|
|
16294
|
-
|
|
16295
|
-
|
|
16296
|
-
|
|
16297
|
-
|
|
16298
|
-
|
|
16299
|
-
|
|
16300
|
-
|
|
16301
|
-
|
|
16302
|
-
pointFrom18(maxX, gapLineY),
|
|
16303
|
-
pointFrom18(gapSnap.gap.endSide[0][0], gapLineY)
|
|
16304
|
-
]
|
|
16305
|
-
}
|
|
16306
|
-
);
|
|
16307
|
-
}
|
|
16308
|
-
break;
|
|
16309
|
-
}
|
|
16310
|
-
case "center_vertical": {
|
|
16311
|
-
if (horizontalGapIntersection) {
|
|
16312
|
-
const gapLineX = (horizontalGapIntersection[0] + horizontalGapIntersection[1]) / 2;
|
|
16313
|
-
gapSnapLines.push(
|
|
16314
|
-
{
|
|
16315
|
-
type: "gap",
|
|
16316
|
-
direction: "vertical",
|
|
16317
|
-
points: [
|
|
16318
|
-
pointFrom18(gapLineX, gapSnap.gap.startSide[0][1]),
|
|
16319
|
-
pointFrom18(gapLineX, minY)
|
|
16320
|
-
]
|
|
16321
|
-
},
|
|
16322
|
-
{
|
|
16323
|
-
type: "gap",
|
|
16324
|
-
direction: "vertical",
|
|
16325
|
-
points: [
|
|
16326
|
-
pointFrom18(gapLineX, maxY),
|
|
16327
|
-
pointFrom18(gapLineX, gapSnap.gap.endSide[0][1])
|
|
16328
|
-
]
|
|
16329
|
-
}
|
|
16330
|
-
);
|
|
16331
|
-
}
|
|
16332
|
-
break;
|
|
16333
|
-
}
|
|
16334
|
-
case "side_right": {
|
|
16335
|
-
if (verticalIntersection) {
|
|
16336
|
-
const gapLineY = (verticalIntersection[0] + verticalIntersection[1]) / 2;
|
|
16337
|
-
gapSnapLines.push(
|
|
16338
|
-
{
|
|
16339
|
-
type: "gap",
|
|
16340
|
-
direction: "horizontal",
|
|
16341
|
-
points: [
|
|
16342
|
-
pointFrom18(startMaxX, gapLineY),
|
|
16343
|
-
pointFrom18(endMinX, gapLineY)
|
|
16344
|
-
]
|
|
16345
|
-
},
|
|
16346
|
-
{
|
|
16347
|
-
type: "gap",
|
|
16348
|
-
direction: "horizontal",
|
|
16349
|
-
points: [pointFrom18(endMaxX, gapLineY), pointFrom18(minX, gapLineY)]
|
|
16350
|
-
}
|
|
16351
|
-
);
|
|
16352
|
-
}
|
|
16353
|
-
break;
|
|
16354
|
-
}
|
|
16355
|
-
case "side_left": {
|
|
16356
|
-
if (verticalIntersection) {
|
|
16357
|
-
const gapLineY = (verticalIntersection[0] + verticalIntersection[1]) / 2;
|
|
16358
|
-
gapSnapLines.push(
|
|
16359
|
-
{
|
|
16360
|
-
type: "gap",
|
|
16361
|
-
direction: "horizontal",
|
|
16362
|
-
points: [
|
|
16363
|
-
pointFrom18(maxX, gapLineY),
|
|
16364
|
-
pointFrom18(startMinX, gapLineY)
|
|
16365
|
-
]
|
|
16366
|
-
},
|
|
16367
|
-
{
|
|
16368
|
-
type: "gap",
|
|
16369
|
-
direction: "horizontal",
|
|
16370
|
-
points: [
|
|
16371
|
-
pointFrom18(startMaxX, gapLineY),
|
|
16372
|
-
pointFrom18(endMinX, gapLineY)
|
|
16373
|
-
]
|
|
16374
|
-
}
|
|
16375
|
-
);
|
|
16376
|
-
}
|
|
16377
|
-
break;
|
|
16378
|
-
}
|
|
16379
|
-
case "side_top": {
|
|
16380
|
-
if (horizontalGapIntersection) {
|
|
16381
|
-
const gapLineX = (horizontalGapIntersection[0] + horizontalGapIntersection[1]) / 2;
|
|
16382
|
-
gapSnapLines.push(
|
|
16383
|
-
{
|
|
16384
|
-
type: "gap",
|
|
16385
|
-
direction: "vertical",
|
|
16386
|
-
points: [
|
|
16387
|
-
pointFrom18(gapLineX, maxY),
|
|
16388
|
-
pointFrom18(gapLineX, startMinY)
|
|
16389
|
-
]
|
|
16390
|
-
},
|
|
16391
|
-
{
|
|
16392
|
-
type: "gap",
|
|
16393
|
-
direction: "vertical",
|
|
16394
|
-
points: [
|
|
16395
|
-
pointFrom18(gapLineX, startMaxY),
|
|
16396
|
-
pointFrom18(gapLineX, endMinY)
|
|
16397
|
-
]
|
|
16398
|
-
}
|
|
16399
|
-
);
|
|
16287
|
+
static cancelScheduledFrame() {
|
|
16288
|
+
if (!_AnimationController.scheduledFrame) {
|
|
16289
|
+
return;
|
|
16290
|
+
}
|
|
16291
|
+
if (_AnimationController.scheduledFrame.type === "raf") {
|
|
16292
|
+
cancelAnimationFrame(_AnimationController.scheduledFrame.id);
|
|
16293
|
+
} else {
|
|
16294
|
+
clearTimeout(_AnimationController.scheduledFrame.id);
|
|
16295
|
+
}
|
|
16296
|
+
_AnimationController.scheduledFrame = null;
|
|
16297
|
+
}
|
|
16298
|
+
static cancelScheduledFrameIfIdle() {
|
|
16299
|
+
if (_AnimationController.animations.size > 0) {
|
|
16300
|
+
return false;
|
|
16301
|
+
}
|
|
16302
|
+
_AnimationController.cancelScheduledFrame();
|
|
16303
|
+
return true;
|
|
16304
|
+
}
|
|
16305
|
+
static tick() {
|
|
16306
|
+
_AnimationController.scheduledFrame = null;
|
|
16307
|
+
if (_AnimationController.animations.size > 0) {
|
|
16308
|
+
for (const [key, animation] of _AnimationController.animations) {
|
|
16309
|
+
const now = performance.now();
|
|
16310
|
+
const deltaTime = animation.lastTime === 0 ? 0 : now - animation.lastTime;
|
|
16311
|
+
const state = animation.animation({
|
|
16312
|
+
deltaTime,
|
|
16313
|
+
state: animation.state
|
|
16314
|
+
});
|
|
16315
|
+
if (!state) {
|
|
16316
|
+
_AnimationController.animations.delete(key);
|
|
16317
|
+
if (_AnimationController.cancelScheduledFrameIfIdle()) {
|
|
16318
|
+
return;
|
|
16319
|
+
}
|
|
16320
|
+
} else {
|
|
16321
|
+
animation.lastTime = now;
|
|
16322
|
+
animation.state = state;
|
|
16400
16323
|
}
|
|
16401
|
-
break;
|
|
16402
16324
|
}
|
|
16403
|
-
|
|
16404
|
-
|
|
16405
|
-
const gapLineX = (horizontalGapIntersection[0] + horizontalGapIntersection[1]) / 2;
|
|
16406
|
-
gapSnapLines.push(
|
|
16407
|
-
{
|
|
16408
|
-
type: "gap",
|
|
16409
|
-
direction: "vertical",
|
|
16410
|
-
points: [
|
|
16411
|
-
pointFrom18(gapLineX, startMaxY),
|
|
16412
|
-
pointFrom18(gapLineX, endMinY)
|
|
16413
|
-
]
|
|
16414
|
-
},
|
|
16415
|
-
{
|
|
16416
|
-
type: "gap",
|
|
16417
|
-
direction: "vertical",
|
|
16418
|
-
points: [pointFrom18(gapLineX, endMaxY), pointFrom18(gapLineX, minY)]
|
|
16419
|
-
}
|
|
16420
|
-
);
|
|
16421
|
-
}
|
|
16422
|
-
break;
|
|
16325
|
+
if (_AnimationController.cancelScheduledFrameIfIdle()) {
|
|
16326
|
+
return;
|
|
16423
16327
|
}
|
|
16328
|
+
_AnimationController.scheduleNextFrame();
|
|
16424
16329
|
}
|
|
16425
16330
|
}
|
|
16426
|
-
|
|
16427
|
-
|
|
16428
|
-
|
|
16429
|
-
|
|
16430
|
-
|
|
16431
|
-
|
|
16432
|
-
|
|
16433
|
-
};
|
|
16434
|
-
})
|
|
16435
|
-
);
|
|
16331
|
+
static running(key) {
|
|
16332
|
+
return _AnimationController.animations.has(key);
|
|
16333
|
+
}
|
|
16334
|
+
static cancel(key) {
|
|
16335
|
+
_AnimationController.animations.delete(key);
|
|
16336
|
+
_AnimationController.cancelScheduledFrameIfIdle();
|
|
16337
|
+
}
|
|
16436
16338
|
};
|
|
16437
|
-
|
|
16438
|
-
|
|
16439
|
-
|
|
16440
|
-
|
|
16441
|
-
|
|
16442
|
-
|
|
16339
|
+
__publicField(_AnimationController, "scheduledFrame", null);
|
|
16340
|
+
__publicField(_AnimationController, "animations", /* @__PURE__ */ new Map());
|
|
16341
|
+
var AnimationController = _AnimationController;
|
|
16342
|
+
|
|
16343
|
+
// animatedTrail.ts
|
|
16344
|
+
var _AnimatedTrail = class _AnimatedTrail {
|
|
16345
|
+
constructor(app, options) {
|
|
16346
|
+
this.app = app;
|
|
16347
|
+
this.options = options;
|
|
16348
|
+
__publicField(this, "currentTrail");
|
|
16349
|
+
__publicField(this, "pastTrails", []);
|
|
16350
|
+
__publicField(this, "container");
|
|
16351
|
+
__publicField(this, "trailElement");
|
|
16352
|
+
__publicField(this, "trailAnimation");
|
|
16353
|
+
__publicField(this, "key");
|
|
16354
|
+
this.key = `animated-trail-${_AnimatedTrail.counter++}`;
|
|
16355
|
+
this.trailElement = document.createElementNS(SVG_NS, "path");
|
|
16356
|
+
if (this.options.animateTrail) {
|
|
16357
|
+
this.trailAnimation = document.createElementNS(SVG_NS, "animate");
|
|
16358
|
+
this.trailAnimation.setAttribute("attributeName", "stroke-dashoffset");
|
|
16359
|
+
this.trailElement.setAttribute("stroke-dasharray", "7 7");
|
|
16360
|
+
this.trailElement.setAttribute("stroke-dashoffset", "10");
|
|
16361
|
+
this.trailAnimation.setAttribute("from", "0");
|
|
16362
|
+
this.trailAnimation.setAttribute("to", `-14`);
|
|
16363
|
+
this.trailAnimation.setAttribute("dur", "0.3s");
|
|
16364
|
+
this.trailElement.appendChild(this.trailAnimation);
|
|
16365
|
+
}
|
|
16443
16366
|
}
|
|
16444
|
-
|
|
16445
|
-
|
|
16446
|
-
|
|
16447
|
-
|
|
16448
|
-
|
|
16449
|
-
|
|
16367
|
+
get hasCurrentTrail() {
|
|
16368
|
+
return !!this.currentTrail;
|
|
16369
|
+
}
|
|
16370
|
+
hasLastPoint(x, y) {
|
|
16371
|
+
if (this.currentTrail) {
|
|
16372
|
+
const len = this.currentTrail.originalPoints.length;
|
|
16373
|
+
return this.currentTrail.originalPoints[len - 1][0] === x && this.currentTrail.originalPoints[len - 1][1] === y;
|
|
16450
16374
|
}
|
|
16451
|
-
|
|
16452
|
-
|
|
16453
|
-
|
|
16454
|
-
|
|
16375
|
+
return false;
|
|
16376
|
+
}
|
|
16377
|
+
cleanup() {
|
|
16378
|
+
this.pastTrails = [];
|
|
16379
|
+
this.currentTrail = void 0;
|
|
16380
|
+
if (this.trailElement.parentNode === this.container) {
|
|
16381
|
+
this.container?.removeChild(this.trailElement);
|
|
16455
16382
|
}
|
|
16456
16383
|
}
|
|
16457
|
-
|
|
16458
|
-
|
|
16459
|
-
|
|
16460
|
-
|
|
16461
|
-
|
|
16462
|
-
|
|
16463
|
-
|
|
16464
|
-
|
|
16465
|
-
|
|
16466
|
-
|
|
16467
|
-
|
|
16468
|
-
|
|
16469
|
-
|
|
16470
|
-
|
|
16471
|
-
|
|
16472
|
-
|
|
16473
|
-
selectionSnapPoints.push(pointFrom18(minX, maxY), pointFrom18(maxX, maxY));
|
|
16474
|
-
break;
|
|
16475
|
-
}
|
|
16476
|
-
case "ne": {
|
|
16477
|
-
selectionSnapPoints.push(pointFrom18(maxX, minY));
|
|
16478
|
-
break;
|
|
16479
|
-
}
|
|
16480
|
-
case "nw": {
|
|
16481
|
-
selectionSnapPoints.push(pointFrom18(minX, minY));
|
|
16482
|
-
break;
|
|
16483
|
-
}
|
|
16484
|
-
case "se": {
|
|
16485
|
-
selectionSnapPoints.push(pointFrom18(maxX, maxY));
|
|
16486
|
-
break;
|
|
16487
|
-
}
|
|
16488
|
-
case "sw": {
|
|
16489
|
-
selectionSnapPoints.push(pointFrom18(minX, maxY));
|
|
16490
|
-
break;
|
|
16491
|
-
}
|
|
16384
|
+
start(container) {
|
|
16385
|
+
if (container) {
|
|
16386
|
+
this.container = container;
|
|
16387
|
+
}
|
|
16388
|
+
if (this.trailElement.parentNode !== this.container && this.container) {
|
|
16389
|
+
this.container.appendChild(this.trailElement);
|
|
16390
|
+
}
|
|
16391
|
+
if (!AnimationController.running(this.key)) {
|
|
16392
|
+
AnimationController.start(this.key, () => {
|
|
16393
|
+
const needsNext = this.onFrame();
|
|
16394
|
+
if (needsNext) {
|
|
16395
|
+
return { keep: true };
|
|
16396
|
+
}
|
|
16397
|
+
this.cleanup();
|
|
16398
|
+
return null;
|
|
16399
|
+
});
|
|
16492
16400
|
}
|
|
16493
16401
|
}
|
|
16494
|
-
|
|
16495
|
-
|
|
16496
|
-
|
|
16497
|
-
|
|
16498
|
-
|
|
16499
|
-
|
|
16500
|
-
|
|
16501
|
-
|
|
16502
|
-
|
|
16503
|
-
|
|
16504
|
-
|
|
16505
|
-
|
|
16506
|
-
|
|
16507
|
-
|
|
16508
|
-
|
|
16509
|
-
)
|
|
16510
|
-
|
|
16511
|
-
|
|
16512
|
-
|
|
16513
|
-
|
|
16514
|
-
|
|
16515
|
-
|
|
16516
|
-
|
|
16517
|
-
|
|
16518
|
-
|
|
16519
|
-
|
|
16520
|
-
|
|
16521
|
-
|
|
16522
|
-
|
|
16523
|
-
|
|
16524
|
-
|
|
16525
|
-
|
|
16526
|
-
|
|
16527
|
-
|
|
16528
|
-
|
|
16529
|
-
|
|
16530
|
-
|
|
16531
|
-
|
|
16532
|
-
|
|
16533
|
-
|
|
16534
|
-
|
|
16535
|
-
|
|
16536
|
-
|
|
16537
|
-
|
|
16538
|
-
|
|
16539
|
-
|
|
16540
|
-
|
|
16541
|
-
}
|
|
16542
|
-
|
|
16543
|
-
|
|
16544
|
-
|
|
16545
|
-
|
|
16546
|
-
|
|
16547
|
-
|
|
16402
|
+
stop() {
|
|
16403
|
+
AnimationController.cancel(this.key);
|
|
16404
|
+
this.cleanup();
|
|
16405
|
+
}
|
|
16406
|
+
startPath(x, y) {
|
|
16407
|
+
this.currentTrail = new LaserPointer(this.options);
|
|
16408
|
+
this.currentTrail.addPoint([x, y, performance.now()]);
|
|
16409
|
+
this.update();
|
|
16410
|
+
}
|
|
16411
|
+
addPointToPath(x, y) {
|
|
16412
|
+
if (this.currentTrail) {
|
|
16413
|
+
this.currentTrail.addPoint([x, y, performance.now()]);
|
|
16414
|
+
this.update();
|
|
16415
|
+
}
|
|
16416
|
+
}
|
|
16417
|
+
endPath() {
|
|
16418
|
+
if (this.currentTrail) {
|
|
16419
|
+
this.currentTrail.close();
|
|
16420
|
+
this.currentTrail.options.keepHead = false;
|
|
16421
|
+
this.pastTrails.push(this.currentTrail);
|
|
16422
|
+
this.currentTrail = void 0;
|
|
16423
|
+
this.update();
|
|
16424
|
+
}
|
|
16425
|
+
}
|
|
16426
|
+
getCurrentTrail() {
|
|
16427
|
+
return this.currentTrail;
|
|
16428
|
+
}
|
|
16429
|
+
clearTrails() {
|
|
16430
|
+
this.pastTrails = [];
|
|
16431
|
+
this.currentTrail = void 0;
|
|
16432
|
+
this.update();
|
|
16433
|
+
}
|
|
16434
|
+
update() {
|
|
16435
|
+
this.start();
|
|
16436
|
+
if (this.trailAnimation) {
|
|
16437
|
+
this.trailAnimation.setAttribute("begin", "indefinite");
|
|
16438
|
+
this.trailAnimation.setAttribute("repeatCount", "indefinite");
|
|
16439
|
+
}
|
|
16440
|
+
}
|
|
16441
|
+
onFrame() {
|
|
16442
|
+
const paths = [];
|
|
16443
|
+
for (const trail of this.pastTrails) {
|
|
16444
|
+
paths.push(this.drawTrail(trail, this.app.state));
|
|
16445
|
+
}
|
|
16446
|
+
if (this.currentTrail) {
|
|
16447
|
+
const currentPath = this.drawTrail(this.currentTrail, this.app.state);
|
|
16448
|
+
paths.push(currentPath);
|
|
16449
|
+
}
|
|
16450
|
+
this.pastTrails = this.pastTrails.filter(
|
|
16451
|
+
(t2) => t2.getStrokeOutline(t2.options.size / this.app.state.zoom.value).length !== 0
|
|
16452
|
+
);
|
|
16453
|
+
if (paths.length === 0) {
|
|
16454
|
+
this.trailElement.setAttribute("d", "");
|
|
16455
|
+
return false;
|
|
16456
|
+
}
|
|
16457
|
+
const svgPaths = paths.join(" ").trim();
|
|
16458
|
+
this.trailElement.setAttribute("d", svgPaths);
|
|
16459
|
+
if (this.trailAnimation) {
|
|
16460
|
+
this.trailElement.setAttribute(
|
|
16461
|
+
"fill",
|
|
16462
|
+
(this.options.fill ?? (() => "black"))(this)
|
|
16463
|
+
);
|
|
16464
|
+
this.trailElement.setAttribute(
|
|
16465
|
+
"stroke",
|
|
16466
|
+
(this.options.stroke ?? (() => "black"))(this)
|
|
16467
|
+
);
|
|
16468
|
+
} else {
|
|
16469
|
+
this.trailElement.setAttribute(
|
|
16470
|
+
"fill",
|
|
16471
|
+
(this.options.fill ?? (() => "black"))(this)
|
|
16472
|
+
);
|
|
16473
|
+
}
|
|
16474
|
+
return true;
|
|
16475
|
+
}
|
|
16476
|
+
drawTrail(trail, state) {
|
|
16477
|
+
const _stroke = trail.getStrokeOutline(trail.options.size / state.zoom.value).map(([x, y]) => {
|
|
16478
|
+
const result = sceneCoordsToViewportCoords3(
|
|
16479
|
+
{ sceneX: x, sceneY: y },
|
|
16480
|
+
state
|
|
16481
|
+
);
|
|
16482
|
+
return [result.x, result.y];
|
|
16483
|
+
});
|
|
16484
|
+
const stroke = this.trailAnimation ? _stroke.slice(0, _stroke.length / 2) : _stroke;
|
|
16485
|
+
return getSvgPathFromStroke2(stroke, true);
|
|
16548
16486
|
}
|
|
16549
|
-
const selectionSnapPoints = [
|
|
16550
|
-
pointFrom18(origin.x + dragOffset.x, origin.y + dragOffset.y)
|
|
16551
|
-
];
|
|
16552
|
-
const snapDistance = getSnapDistance(app.state.zoom.value);
|
|
16553
|
-
const minOffset = {
|
|
16554
|
-
x: snapDistance,
|
|
16555
|
-
y: snapDistance
|
|
16556
|
-
};
|
|
16557
|
-
const nearestSnapsX = [];
|
|
16558
|
-
const nearestSnapsY = [];
|
|
16559
|
-
getPointSnaps(
|
|
16560
|
-
[newElement7],
|
|
16561
|
-
selectionSnapPoints,
|
|
16562
|
-
app,
|
|
16563
|
-
event,
|
|
16564
|
-
nearestSnapsX,
|
|
16565
|
-
nearestSnapsY,
|
|
16566
|
-
minOffset
|
|
16567
|
-
);
|
|
16568
|
-
const snapOffset = {
|
|
16569
|
-
x: nearestSnapsX[0]?.offset ?? 0,
|
|
16570
|
-
y: nearestSnapsY[0]?.offset ?? 0
|
|
16571
|
-
};
|
|
16572
|
-
minOffset.x = 0;
|
|
16573
|
-
minOffset.y = 0;
|
|
16574
|
-
nearestSnapsX.length = 0;
|
|
16575
|
-
nearestSnapsY.length = 0;
|
|
16576
|
-
const corners = getElementsCorners([newElement7], elementsMap, {
|
|
16577
|
-
boundingBoxCorners: true,
|
|
16578
|
-
omitCenter: true
|
|
16579
|
-
});
|
|
16580
|
-
getPointSnaps(
|
|
16581
|
-
[newElement7],
|
|
16582
|
-
corners,
|
|
16583
|
-
app,
|
|
16584
|
-
event,
|
|
16585
|
-
nearestSnapsX,
|
|
16586
|
-
nearestSnapsY,
|
|
16587
|
-
minOffset
|
|
16588
|
-
);
|
|
16589
|
-
const pointSnapLines = createPointSnapLines(nearestSnapsX, nearestSnapsY);
|
|
16590
|
-
return {
|
|
16591
|
-
snapOffset,
|
|
16592
|
-
snapLines: pointSnapLines
|
|
16593
|
-
};
|
|
16594
16487
|
};
|
|
16595
|
-
|
|
16596
|
-
|
|
16488
|
+
__publicField(_AnimatedTrail, "counter", 0);
|
|
16489
|
+
var AnimatedTrail = _AnimatedTrail;
|
|
16490
|
+
|
|
16491
|
+
// laserTrails.ts
|
|
16492
|
+
var LaserTrails = class {
|
|
16493
|
+
constructor(app) {
|
|
16494
|
+
this.app = app;
|
|
16495
|
+
__publicField(this, "localTrail");
|
|
16496
|
+
__publicField(this, "collabTrails", /* @__PURE__ */ new Map());
|
|
16497
|
+
__publicField(this, "container");
|
|
16498
|
+
this.localTrail = new AnimatedTrail(app, {
|
|
16499
|
+
...this.getTrailOptions(),
|
|
16500
|
+
fill: () => DEFAULT_LASER_COLOR
|
|
16501
|
+
});
|
|
16502
|
+
}
|
|
16503
|
+
getTrailOptions() {
|
|
16597
16504
|
return {
|
|
16598
|
-
|
|
16599
|
-
|
|
16505
|
+
simplify: 0,
|
|
16506
|
+
streamline: 0.4,
|
|
16507
|
+
sizeMapping: (c) => {
|
|
16508
|
+
const DECAY_TIME = 1e3;
|
|
16509
|
+
const DECAY_LENGTH = 50;
|
|
16510
|
+
const t2 = Math.max(
|
|
16511
|
+
0,
|
|
16512
|
+
1 - (performance.now() - c.pressure) / DECAY_TIME
|
|
16513
|
+
);
|
|
16514
|
+
const l = (DECAY_LENGTH - Math.min(DECAY_LENGTH, c.totalLength - c.currentIndex)) / DECAY_LENGTH;
|
|
16515
|
+
return Math.min(easeOut(l), easeOut(t2));
|
|
16516
|
+
}
|
|
16600
16517
|
};
|
|
16601
16518
|
}
|
|
16602
|
-
|
|
16603
|
-
|
|
16604
|
-
|
|
16605
|
-
|
|
16606
|
-
|
|
16607
|
-
|
|
16608
|
-
|
|
16609
|
-
|
|
16610
|
-
|
|
16611
|
-
|
|
16612
|
-
|
|
16613
|
-
|
|
16614
|
-
|
|
16615
|
-
|
|
16616
|
-
|
|
16617
|
-
|
|
16618
|
-
|
|
16619
|
-
|
|
16620
|
-
|
|
16621
|
-
|
|
16622
|
-
|
|
16623
|
-
|
|
16624
|
-
|
|
16625
|
-
|
|
16626
|
-
|
|
16519
|
+
startPath(x, y) {
|
|
16520
|
+
this.localTrail.startPath(x, y);
|
|
16521
|
+
}
|
|
16522
|
+
addPointToPath(x, y) {
|
|
16523
|
+
this.localTrail.addPointToPath(x, y);
|
|
16524
|
+
}
|
|
16525
|
+
endPath() {
|
|
16526
|
+
this.localTrail.endPath();
|
|
16527
|
+
}
|
|
16528
|
+
start(container) {
|
|
16529
|
+
this.container = container;
|
|
16530
|
+
this.localTrail.start(container);
|
|
16531
|
+
}
|
|
16532
|
+
stop() {
|
|
16533
|
+
this.localTrail.stop();
|
|
16534
|
+
this.stopCollabTrails();
|
|
16535
|
+
this.container = void 0;
|
|
16536
|
+
}
|
|
16537
|
+
stopCollabTrails(collaborators) {
|
|
16538
|
+
for (const [key, trail] of this.collabTrails) {
|
|
16539
|
+
const collaborator = collaborators?.get(key);
|
|
16540
|
+
if (!collaborator) {
|
|
16541
|
+
trail.stop();
|
|
16542
|
+
this.collabTrails.delete(key);
|
|
16543
|
+
}
|
|
16544
|
+
}
|
|
16545
|
+
}
|
|
16546
|
+
updateCollabTrails(collaborators) {
|
|
16547
|
+
this.stopCollabTrails(collaborators);
|
|
16548
|
+
if (!this.container || collaborators.size === 0) {
|
|
16549
|
+
return;
|
|
16550
|
+
}
|
|
16551
|
+
for (const [key, collaborator] of collaborators.entries()) {
|
|
16552
|
+
if (collaborator.isCurrentUser) {
|
|
16553
|
+
continue;
|
|
16554
|
+
}
|
|
16555
|
+
let trail = this.collabTrails.get(key);
|
|
16556
|
+
if (!trail) {
|
|
16557
|
+
trail = new AnimatedTrail(this.app, {
|
|
16558
|
+
...this.getTrailOptions(),
|
|
16559
|
+
fill: () => collaborator.pointer?.laserColor || getClientColor(key, collaborator)
|
|
16627
16560
|
});
|
|
16628
|
-
|
|
16561
|
+
trail.start(this.container);
|
|
16562
|
+
this.collabTrails.set(key, trail);
|
|
16629
16563
|
}
|
|
16630
|
-
|
|
16631
|
-
|
|
16632
|
-
|
|
16633
|
-
|
|
16564
|
+
if (collaborator.pointer && collaborator.pointer.tool === "laser") {
|
|
16565
|
+
const buttonDown = collaborator.button === "down";
|
|
16566
|
+
const buttonUp = collaborator.button === "up";
|
|
16567
|
+
const hasTrail = trail.hasCurrentTrail;
|
|
16568
|
+
if (buttonDown && !hasTrail) {
|
|
16569
|
+
trail.startPath(collaborator.pointer.x, collaborator.pointer.y);
|
|
16570
|
+
}
|
|
16571
|
+
const lastPointOriginal = !trail.hasLastPoint(
|
|
16572
|
+
collaborator.pointer.x,
|
|
16573
|
+
collaborator.pointer.y
|
|
16574
|
+
);
|
|
16575
|
+
if (buttonDown && lastPointOriginal) {
|
|
16576
|
+
trail.addPointToPath(collaborator.pointer.x, collaborator.pointer.y);
|
|
16577
|
+
}
|
|
16578
|
+
if (buttonUp && hasTrail) {
|
|
16579
|
+
trail.addPointToPath(collaborator.pointer.x, collaborator.pointer.y);
|
|
16580
|
+
trail.endPath();
|
|
16634
16581
|
}
|
|
16635
|
-
horizontalSnapLines.push({
|
|
16636
|
-
type: "pointer",
|
|
16637
|
-
points: [corner, pointFrom18(pointer.x, corner[1])],
|
|
16638
|
-
direction: "horizontal"
|
|
16639
|
-
});
|
|
16640
|
-
minOffset.y = offsetY;
|
|
16641
16582
|
}
|
|
16642
16583
|
}
|
|
16643
16584
|
}
|
|
16644
|
-
return {
|
|
16645
|
-
originOffset: {
|
|
16646
|
-
x: verticalSnapLines.length > 0 ? verticalSnapLines[0].points[0][0] - pointer.x : 0,
|
|
16647
|
-
y: horizontalSnapLines.length > 0 ? horizontalSnapLines[0].points[0][1] - pointer.y : 0
|
|
16648
|
-
},
|
|
16649
|
-
snapLines: [...verticalSnapLines, ...horizontalSnapLines]
|
|
16650
|
-
};
|
|
16651
|
-
};
|
|
16652
|
-
var isActiveToolNonLinearSnappable = (activeToolType) => {
|
|
16653
|
-
return activeToolType === TOOL_TYPE.rectangle || activeToolType === TOOL_TYPE.ellipse || activeToolType === TOOL_TYPE.diamond || activeToolType === TOOL_TYPE.frame || activeToolType === TOOL_TYPE.magicframe || activeToolType === TOOL_TYPE.image || activeToolType === TOOL_TYPE.text;
|
|
16654
16585
|
};
|
|
16655
16586
|
|
|
16656
16587
|
// textAutoResizeHandle.ts
|
|
@@ -17428,6 +17359,75 @@ var textWysiwyg = ({
|
|
|
17428
17359
|
return handleSubmit;
|
|
17429
17360
|
};
|
|
17430
17361
|
|
|
17362
|
+
// scene/scrollbars.ts
|
|
17363
|
+
import { getGlobalCSSVariable } from "@excalidraw/common";
|
|
17364
|
+
import { getCommonBounds as getCommonBounds5 } from "@excalidraw/element";
|
|
17365
|
+
var SCROLLBAR_MARGIN = 4;
|
|
17366
|
+
var SCROLLBAR_WIDTH = 6;
|
|
17367
|
+
var SCROLLBAR_COLOR = "rgba(0,0,0,0.3)";
|
|
17368
|
+
var getScrollBars = (elements, viewportWidth, viewportHeight, appState) => {
|
|
17369
|
+
if (!elements.size) {
|
|
17370
|
+
return {
|
|
17371
|
+
horizontal: null,
|
|
17372
|
+
vertical: null
|
|
17373
|
+
};
|
|
17374
|
+
}
|
|
17375
|
+
const [elementsMinX, elementsMinY, elementsMaxX, elementsMaxY] = getCommonBounds5(elements);
|
|
17376
|
+
const viewportWidthWithZoom = viewportWidth / appState.zoom.value;
|
|
17377
|
+
const viewportHeightWithZoom = viewportHeight / appState.zoom.value;
|
|
17378
|
+
const safeArea = {
|
|
17379
|
+
top: parseInt(getGlobalCSSVariable("sat")) || 0,
|
|
17380
|
+
bottom: parseInt(getGlobalCSSVariable("sab")) || 0,
|
|
17381
|
+
left: parseInt(getGlobalCSSVariable("sal")) || 0,
|
|
17382
|
+
right: parseInt(getGlobalCSSVariable("sar")) || 0
|
|
17383
|
+
};
|
|
17384
|
+
const isRTL3 = getLanguage().rtl;
|
|
17385
|
+
const viewportMinX = -appState.scrollX + safeArea.left;
|
|
17386
|
+
const viewportMinY = -appState.scrollY + safeArea.top;
|
|
17387
|
+
const viewportMaxX = viewportMinX + viewportWidthWithZoom - safeArea.right;
|
|
17388
|
+
const viewportMaxY = viewportMinY + viewportHeightWithZoom - safeArea.bottom;
|
|
17389
|
+
const sceneMinX = Math.min(elementsMinX, viewportMinX);
|
|
17390
|
+
const sceneMinY = Math.min(elementsMinY, viewportMinY);
|
|
17391
|
+
const sceneMaxX = Math.max(elementsMaxX, viewportMaxX);
|
|
17392
|
+
const sceneMaxY = Math.max(elementsMaxY, viewportMaxY);
|
|
17393
|
+
const sceneWidth = elementsMaxX - elementsMinX;
|
|
17394
|
+
const sceneHeight = elementsMaxY - elementsMinY;
|
|
17395
|
+
const extendedSceneWidth = sceneMaxX - sceneMinX;
|
|
17396
|
+
const extendedSceneHeight = sceneMaxY - sceneMinY;
|
|
17397
|
+
const scrollWidthOffset = Math.max(SCROLLBAR_MARGIN * 2, safeArea.left + safeArea.right) + SCROLLBAR_WIDTH * 2;
|
|
17398
|
+
const scrollbarWidth = viewportWidth * (viewportWidthWithZoom / extendedSceneWidth) - scrollWidthOffset;
|
|
17399
|
+
const scrollbarHeightOffset = Math.max(SCROLLBAR_MARGIN * 2, safeArea.top + safeArea.bottom) + SCROLLBAR_WIDTH * 2;
|
|
17400
|
+
const scrollbarHeight = viewportHeight * (viewportHeightWithZoom / extendedSceneHeight) - scrollbarHeightOffset;
|
|
17401
|
+
const horizontalDeltaMultiplier = extendedSceneWidth > sceneWidth ? extendedSceneWidth * appState.zoom.value / (scrollbarWidth + scrollWidthOffset) : viewportWidth / (scrollbarWidth + scrollWidthOffset);
|
|
17402
|
+
const verticalDeltaMultiplier = extendedSceneHeight > sceneHeight ? extendedSceneHeight * appState.zoom.value / (scrollbarHeight + scrollbarHeightOffset) : viewportHeight / (scrollbarHeight + scrollbarHeightOffset);
|
|
17403
|
+
return {
|
|
17404
|
+
horizontal: viewportMinX === sceneMinX && viewportMaxX === sceneMaxX ? null : {
|
|
17405
|
+
x: Math.max(safeArea.left, SCROLLBAR_MARGIN) + SCROLLBAR_WIDTH + (viewportMinX - sceneMinX) / extendedSceneWidth * viewportWidth,
|
|
17406
|
+
y: viewportHeight - SCROLLBAR_WIDTH - Math.max(SCROLLBAR_MARGIN, safeArea.bottom),
|
|
17407
|
+
width: scrollbarWidth,
|
|
17408
|
+
height: SCROLLBAR_WIDTH,
|
|
17409
|
+
deltaMultiplier: horizontalDeltaMultiplier
|
|
17410
|
+
},
|
|
17411
|
+
vertical: viewportMinY === sceneMinY && viewportMaxY === sceneMaxY ? null : {
|
|
17412
|
+
x: isRTL3 ? Math.max(safeArea.left, SCROLLBAR_MARGIN) : viewportWidth - SCROLLBAR_WIDTH - Math.max(safeArea.right, SCROLLBAR_MARGIN),
|
|
17413
|
+
y: Math.max(safeArea.top, SCROLLBAR_MARGIN) + SCROLLBAR_WIDTH + (viewportMinY - sceneMinY) / extendedSceneHeight * viewportHeight,
|
|
17414
|
+
width: SCROLLBAR_WIDTH,
|
|
17415
|
+
height: scrollbarHeight,
|
|
17416
|
+
deltaMultiplier: verticalDeltaMultiplier
|
|
17417
|
+
}
|
|
17418
|
+
};
|
|
17419
|
+
};
|
|
17420
|
+
var isOverScrollBars = (scrollBars, x, y) => {
|
|
17421
|
+
const [isOverHorizontal, isOverVertical] = [
|
|
17422
|
+
scrollBars.horizontal,
|
|
17423
|
+
scrollBars.vertical
|
|
17424
|
+
].map((scrollBar) => {
|
|
17425
|
+
return scrollBar != null && scrollBar.x <= x && x <= scrollBar.x + scrollBar.width && scrollBar.y <= y && y <= scrollBar.y + scrollBar.height;
|
|
17426
|
+
});
|
|
17427
|
+
const isOverEither = isOverHorizontal || isOverVertical;
|
|
17428
|
+
return { isOverEither, isOverHorizontal, isOverVertical };
|
|
17429
|
+
};
|
|
17430
|
+
|
|
17431
17431
|
// lasso/index.ts
|
|
17432
17432
|
import {
|
|
17433
17433
|
pointFrom as pointFrom21
|
|
@@ -19586,122 +19586,6 @@ var getConvertibleType = (element) => {
|
|
|
19586
19586
|
};
|
|
19587
19587
|
var ConvertElementTypePopup_default = ConvertElementTypePopup;
|
|
19588
19588
|
|
|
19589
|
-
// components/AppStateObserver.ts
|
|
19590
|
-
var AppStateObserver = class {
|
|
19591
|
-
constructor(getState) {
|
|
19592
|
-
this.getState = getState;
|
|
19593
|
-
__publicField(this, "listeners", []);
|
|
19594
|
-
__publicField(this, "onStateChange", (propOrOpts, callback, opts) => {
|
|
19595
|
-
const {
|
|
19596
|
-
predicate,
|
|
19597
|
-
getValue,
|
|
19598
|
-
callback: stateChangeCallback,
|
|
19599
|
-
once,
|
|
19600
|
-
matchesImmediately
|
|
19601
|
-
} = this.normalize(propOrOpts, callback, opts);
|
|
19602
|
-
if (stateChangeCallback) {
|
|
19603
|
-
if (matchesImmediately) {
|
|
19604
|
-
queueMicrotask(() => {
|
|
19605
|
-
const state = this.getState();
|
|
19606
|
-
stateChangeCallback(getValue(state), state);
|
|
19607
|
-
});
|
|
19608
|
-
if (once) {
|
|
19609
|
-
return () => {
|
|
19610
|
-
};
|
|
19611
|
-
}
|
|
19612
|
-
}
|
|
19613
|
-
return this.subscribe({
|
|
19614
|
-
predicate,
|
|
19615
|
-
getValue,
|
|
19616
|
-
callback: stateChangeCallback,
|
|
19617
|
-
once
|
|
19618
|
-
});
|
|
19619
|
-
}
|
|
19620
|
-
if (matchesImmediately) {
|
|
19621
|
-
return Promise.resolve(getValue(this.getState()));
|
|
19622
|
-
}
|
|
19623
|
-
return new Promise((resolve) => {
|
|
19624
|
-
this.subscribe({
|
|
19625
|
-
predicate,
|
|
19626
|
-
getValue,
|
|
19627
|
-
callback: (value) => resolve(value),
|
|
19628
|
-
once: true
|
|
19629
|
-
});
|
|
19630
|
-
});
|
|
19631
|
-
});
|
|
19632
|
-
}
|
|
19633
|
-
isStateChangePredicateOptions(propOrOpts) {
|
|
19634
|
-
return typeof propOrOpts === "object" && !Array.isArray(propOrOpts) && "predicate" in propOrOpts;
|
|
19635
|
-
}
|
|
19636
|
-
subscribe(listener) {
|
|
19637
|
-
this.listeners.push(listener);
|
|
19638
|
-
return () => {
|
|
19639
|
-
this.listeners = this.listeners.filter(
|
|
19640
|
-
(existingListener) => existingListener !== listener
|
|
19641
|
-
);
|
|
19642
|
-
};
|
|
19643
|
-
}
|
|
19644
|
-
normalize(propOrOpts, callback, opts) {
|
|
19645
|
-
let predicate;
|
|
19646
|
-
let getValue;
|
|
19647
|
-
let normalizedCallback = callback;
|
|
19648
|
-
let once = opts?.once ?? false;
|
|
19649
|
-
let matchesImmediately = false;
|
|
19650
|
-
if (this.isStateChangePredicateOptions(propOrOpts)) {
|
|
19651
|
-
const {
|
|
19652
|
-
predicate: predicateFn,
|
|
19653
|
-
callback: callbackFromOpts,
|
|
19654
|
-
once: onceFromOpts
|
|
19655
|
-
} = propOrOpts;
|
|
19656
|
-
predicate = predicateFn;
|
|
19657
|
-
getValue = (appState) => appState;
|
|
19658
|
-
normalizedCallback = callbackFromOpts ? (_value, appState) => callbackFromOpts(appState) : void 0;
|
|
19659
|
-
once = onceFromOpts ?? false;
|
|
19660
|
-
matchesImmediately = predicateFn(this.getState());
|
|
19661
|
-
} else if (typeof propOrOpts === "function") {
|
|
19662
|
-
const selector = propOrOpts;
|
|
19663
|
-
predicate = (appState, prevState) => selector(appState) !== selector(prevState);
|
|
19664
|
-
getValue = (appState) => selector(appState);
|
|
19665
|
-
} else if (Array.isArray(propOrOpts)) {
|
|
19666
|
-
const keys = propOrOpts;
|
|
19667
|
-
predicate = (appState, prevState) => keys.some((key) => appState[key] !== prevState[key]);
|
|
19668
|
-
getValue = (appState) => appState;
|
|
19669
|
-
} else {
|
|
19670
|
-
const key = propOrOpts;
|
|
19671
|
-
predicate = (appState, prevState) => appState[key] !== prevState[key];
|
|
19672
|
-
getValue = (appState) => appState[key];
|
|
19673
|
-
}
|
|
19674
|
-
return {
|
|
19675
|
-
predicate,
|
|
19676
|
-
getValue,
|
|
19677
|
-
callback: normalizedCallback,
|
|
19678
|
-
once,
|
|
19679
|
-
matchesImmediately
|
|
19680
|
-
};
|
|
19681
|
-
}
|
|
19682
|
-
flush(prevState) {
|
|
19683
|
-
if (!this.listeners.length) {
|
|
19684
|
-
return;
|
|
19685
|
-
}
|
|
19686
|
-
const state = this.getState();
|
|
19687
|
-
const listenersToKeep = [];
|
|
19688
|
-
for (const listener of this.listeners) {
|
|
19689
|
-
if (listener.predicate(state, prevState)) {
|
|
19690
|
-
listener.callback(listener.getValue(state), state);
|
|
19691
|
-
if (!listener.once) {
|
|
19692
|
-
listenersToKeep.push(listener);
|
|
19693
|
-
}
|
|
19694
|
-
} else {
|
|
19695
|
-
listenersToKeep.push(listener);
|
|
19696
|
-
}
|
|
19697
|
-
}
|
|
19698
|
-
this.listeners = listenersToKeep;
|
|
19699
|
-
}
|
|
19700
|
-
clear() {
|
|
19701
|
-
this.listeners = [];
|
|
19702
|
-
}
|
|
19703
|
-
};
|
|
19704
|
-
|
|
19705
19589
|
// components/Trans.tsx
|
|
19706
19590
|
import React17 from "react";
|
|
19707
19591
|
var SPLIT_REGEX = /({{[\w-]+}})|(<[\w-]+>)|(<\/[\w-]+>)/g;
|
|
@@ -19997,17 +19881,29 @@ var Popover6 = ({
|
|
|
19997
19881
|
// components/ContextMenu.tsx
|
|
19998
19882
|
import { jsx as jsx62, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
19999
19883
|
var CONTEXT_MENU_SEPARATOR = "separator";
|
|
19884
|
+
var isCustomContextMenuItem = (item) => "onSelect" in item;
|
|
20000
19885
|
var ContextMenu = React19.memo(
|
|
20001
19886
|
({ actionManager, items, top, left, onClose }) => {
|
|
20002
19887
|
const appState = useExcalidrawAppState();
|
|
20003
19888
|
const elements = useExcalidrawElements();
|
|
20004
19889
|
const filteredItems = items.reduce((acc, item) => {
|
|
20005
|
-
if (
|
|
19890
|
+
if (!item) {
|
|
19891
|
+
return acc;
|
|
19892
|
+
}
|
|
19893
|
+
if (item === CONTEXT_MENU_SEPARATOR) {
|
|
19894
|
+
acc.push(item);
|
|
19895
|
+
return acc;
|
|
19896
|
+
}
|
|
19897
|
+
if (isCustomContextMenuItem(item)) {
|
|
19898
|
+
acc.push(item);
|
|
19899
|
+
return acc;
|
|
19900
|
+
}
|
|
19901
|
+
if (!item.predicate || item.predicate(
|
|
20006
19902
|
elements,
|
|
20007
19903
|
appState,
|
|
20008
19904
|
actionManager.app.props,
|
|
20009
19905
|
actionManager.app
|
|
20010
|
-
))
|
|
19906
|
+
)) {
|
|
20011
19907
|
acc.push(item);
|
|
20012
19908
|
}
|
|
20013
19909
|
return acc;
|
|
@@ -20038,6 +19934,24 @@ var ContextMenu = React19.memo(
|
|
|
20038
19934
|
}
|
|
20039
19935
|
return /* @__PURE__ */ jsx62("hr", { className: "context-menu-item-separator" }, idx);
|
|
20040
19936
|
}
|
|
19937
|
+
if (isCustomContextMenuItem(item)) {
|
|
19938
|
+
return /* @__PURE__ */ jsx62(
|
|
19939
|
+
"li",
|
|
19940
|
+
{
|
|
19941
|
+
"data-testid": item.key,
|
|
19942
|
+
onClick: () => {
|
|
19943
|
+
onClose(() => {
|
|
19944
|
+
item.onSelect();
|
|
19945
|
+
});
|
|
19946
|
+
},
|
|
19947
|
+
children: /* @__PURE__ */ jsxs29("button", { type: "button", className: "context-menu-item", children: [
|
|
19948
|
+
/* @__PURE__ */ jsx62("div", { className: "context-menu-item__label", children: item.label }),
|
|
19949
|
+
/* @__PURE__ */ jsx62("kbd", { className: "context-menu-item__shortcut" })
|
|
19950
|
+
] })
|
|
19951
|
+
},
|
|
19952
|
+
item.key
|
|
19953
|
+
);
|
|
19954
|
+
}
|
|
20041
19955
|
const actionName = item.name;
|
|
20042
19956
|
let label = "";
|
|
20043
19957
|
if (item.label) {
|
|
@@ -31500,6 +31414,122 @@ var NewElementCanvas = (props) => {
|
|
|
31500
31414
|
};
|
|
31501
31415
|
var NewElementCanvas_default = NewElementCanvas;
|
|
31502
31416
|
|
|
31417
|
+
// components/AppStateObserver.ts
|
|
31418
|
+
var AppStateObserver = class {
|
|
31419
|
+
constructor(getState) {
|
|
31420
|
+
this.getState = getState;
|
|
31421
|
+
__publicField(this, "listeners", []);
|
|
31422
|
+
__publicField(this, "onStateChange", (propOrOpts, callback, opts) => {
|
|
31423
|
+
const {
|
|
31424
|
+
predicate,
|
|
31425
|
+
getValue,
|
|
31426
|
+
callback: stateChangeCallback,
|
|
31427
|
+
once,
|
|
31428
|
+
matchesImmediately
|
|
31429
|
+
} = this.normalize(propOrOpts, callback, opts);
|
|
31430
|
+
if (stateChangeCallback) {
|
|
31431
|
+
if (matchesImmediately) {
|
|
31432
|
+
queueMicrotask(() => {
|
|
31433
|
+
const state = this.getState();
|
|
31434
|
+
stateChangeCallback(getValue(state), state);
|
|
31435
|
+
});
|
|
31436
|
+
if (once) {
|
|
31437
|
+
return () => {
|
|
31438
|
+
};
|
|
31439
|
+
}
|
|
31440
|
+
}
|
|
31441
|
+
return this.subscribe({
|
|
31442
|
+
predicate,
|
|
31443
|
+
getValue,
|
|
31444
|
+
callback: stateChangeCallback,
|
|
31445
|
+
once
|
|
31446
|
+
});
|
|
31447
|
+
}
|
|
31448
|
+
if (matchesImmediately) {
|
|
31449
|
+
return Promise.resolve(getValue(this.getState()));
|
|
31450
|
+
}
|
|
31451
|
+
return new Promise((resolve) => {
|
|
31452
|
+
this.subscribe({
|
|
31453
|
+
predicate,
|
|
31454
|
+
getValue,
|
|
31455
|
+
callback: (value) => resolve(value),
|
|
31456
|
+
once: true
|
|
31457
|
+
});
|
|
31458
|
+
});
|
|
31459
|
+
});
|
|
31460
|
+
}
|
|
31461
|
+
isStateChangePredicateOptions(propOrOpts) {
|
|
31462
|
+
return typeof propOrOpts === "object" && !Array.isArray(propOrOpts) && "predicate" in propOrOpts;
|
|
31463
|
+
}
|
|
31464
|
+
subscribe(listener) {
|
|
31465
|
+
this.listeners.push(listener);
|
|
31466
|
+
return () => {
|
|
31467
|
+
this.listeners = this.listeners.filter(
|
|
31468
|
+
(existingListener) => existingListener !== listener
|
|
31469
|
+
);
|
|
31470
|
+
};
|
|
31471
|
+
}
|
|
31472
|
+
normalize(propOrOpts, callback, opts) {
|
|
31473
|
+
let predicate;
|
|
31474
|
+
let getValue;
|
|
31475
|
+
let normalizedCallback = callback;
|
|
31476
|
+
let once = opts?.once ?? false;
|
|
31477
|
+
let matchesImmediately = false;
|
|
31478
|
+
if (this.isStateChangePredicateOptions(propOrOpts)) {
|
|
31479
|
+
const {
|
|
31480
|
+
predicate: predicateFn,
|
|
31481
|
+
callback: callbackFromOpts,
|
|
31482
|
+
once: onceFromOpts
|
|
31483
|
+
} = propOrOpts;
|
|
31484
|
+
predicate = predicateFn;
|
|
31485
|
+
getValue = (appState) => appState;
|
|
31486
|
+
normalizedCallback = callbackFromOpts ? (_value, appState) => callbackFromOpts(appState) : void 0;
|
|
31487
|
+
once = onceFromOpts ?? false;
|
|
31488
|
+
matchesImmediately = predicateFn(this.getState());
|
|
31489
|
+
} else if (typeof propOrOpts === "function") {
|
|
31490
|
+
const selector = propOrOpts;
|
|
31491
|
+
predicate = (appState, prevState) => selector(appState) !== selector(prevState);
|
|
31492
|
+
getValue = (appState) => selector(appState);
|
|
31493
|
+
} else if (Array.isArray(propOrOpts)) {
|
|
31494
|
+
const keys = propOrOpts;
|
|
31495
|
+
predicate = (appState, prevState) => keys.some((key) => appState[key] !== prevState[key]);
|
|
31496
|
+
getValue = (appState) => appState;
|
|
31497
|
+
} else {
|
|
31498
|
+
const key = propOrOpts;
|
|
31499
|
+
predicate = (appState, prevState) => appState[key] !== prevState[key];
|
|
31500
|
+
getValue = (appState) => appState[key];
|
|
31501
|
+
}
|
|
31502
|
+
return {
|
|
31503
|
+
predicate,
|
|
31504
|
+
getValue,
|
|
31505
|
+
callback: normalizedCallback,
|
|
31506
|
+
once,
|
|
31507
|
+
matchesImmediately
|
|
31508
|
+
};
|
|
31509
|
+
}
|
|
31510
|
+
flush(prevState) {
|
|
31511
|
+
if (!this.listeners.length) {
|
|
31512
|
+
return;
|
|
31513
|
+
}
|
|
31514
|
+
const state = this.getState();
|
|
31515
|
+
const listenersToKeep = [];
|
|
31516
|
+
for (const listener of this.listeners) {
|
|
31517
|
+
if (listener.predicate(state, prevState)) {
|
|
31518
|
+
listener.callback(listener.getValue(state), state);
|
|
31519
|
+
if (!listener.once) {
|
|
31520
|
+
listenersToKeep.push(listener);
|
|
31521
|
+
}
|
|
31522
|
+
} else {
|
|
31523
|
+
listenersToKeep.push(listener);
|
|
31524
|
+
}
|
|
31525
|
+
}
|
|
31526
|
+
this.listeners = listenersToKeep;
|
|
31527
|
+
}
|
|
31528
|
+
clear() {
|
|
31529
|
+
this.listeners = [];
|
|
31530
|
+
}
|
|
31531
|
+
};
|
|
31532
|
+
|
|
31503
31533
|
// components/UnlockPopup.tsx
|
|
31504
31534
|
import {
|
|
31505
31535
|
getCommonBounds as getCommonBounds10,
|
|
@@ -31709,8 +31739,8 @@ var App = class _App extends React40.Component {
|
|
|
31709
31739
|
__publicField(this, "missingPointerEventCleanupEmitter", new Emitter2());
|
|
31710
31740
|
__publicField(this, "onRemoveEventListenersEmitter", new Emitter2());
|
|
31711
31741
|
__publicField(this, "api");
|
|
31712
|
-
__publicField(this, "addImageElementsToScene", async (imageFiles, sceneX, sceneY
|
|
31713
|
-
await this.insertImages(imageFiles, sceneX, sceneY
|
|
31742
|
+
__publicField(this, "addImageElementsToScene", async (imageFiles, sceneX, sceneY) => {
|
|
31743
|
+
await this.insertImages(imageFiles, sceneX, sceneY);
|
|
31714
31744
|
});
|
|
31715
31745
|
__publicField(this, "updateEditorAtom", (atom2, ...args) => {
|
|
31716
31746
|
const result = editorJotaiStore.set(atom2, ...args);
|
|
@@ -35625,7 +35655,8 @@ var App = class _App extends React40.Component {
|
|
|
35625
35655
|
__publicField(this, "newImagePlaceholder", ({
|
|
35626
35656
|
sceneX,
|
|
35627
35657
|
sceneY,
|
|
35628
|
-
addToFrameUnderCursor = true
|
|
35658
|
+
addToFrameUnderCursor = true,
|
|
35659
|
+
customData
|
|
35629
35660
|
}) => {
|
|
35630
35661
|
const [gridX, gridY] = getGridPoint2(
|
|
35631
35662
|
sceneX,
|
|
@@ -35652,7 +35683,8 @@ var App = class _App extends React40.Component {
|
|
|
35652
35683
|
x: gridX - placeholderSize / 2,
|
|
35653
35684
|
y: gridY - placeholderSize / 2,
|
|
35654
35685
|
width: placeholderSize,
|
|
35655
|
-
height: placeholderSize
|
|
35686
|
+
height: placeholderSize,
|
|
35687
|
+
customData
|
|
35656
35688
|
});
|
|
35657
35689
|
});
|
|
35658
35690
|
__publicField(this, "handleLinearElementOnPointerDown", (event, elementType, pointerDownState) => {
|
|
@@ -36046,7 +36078,6 @@ var App = class _App extends React40.Component {
|
|
|
36046
36078
|
const fileId = await (this.props.generateIdForFile?.(
|
|
36047
36079
|
imageFile
|
|
36048
36080
|
) || generateIdFromFile(imageFile));
|
|
36049
|
-
console.info("Excalidraw File ID:", fileId);
|
|
36050
36081
|
if (!fileId) {
|
|
36051
36082
|
console.warn(
|
|
36052
36083
|
"Couldn't generate file id or the supplied `generateIdForFile` didn't resolve to one."
|
|
@@ -36128,7 +36159,13 @@ var App = class _App extends React40.Component {
|
|
|
36128
36159
|
),
|
|
36129
36160
|
multiple: true
|
|
36130
36161
|
});
|
|
36131
|
-
this.insertImages(
|
|
36162
|
+
this.insertImages(
|
|
36163
|
+
imageFiles.map((f) => ({
|
|
36164
|
+
file: f
|
|
36165
|
+
})),
|
|
36166
|
+
x,
|
|
36167
|
+
y
|
|
36168
|
+
);
|
|
36132
36169
|
} catch (error) {
|
|
36133
36170
|
if (error.name !== "AbortError") {
|
|
36134
36171
|
console.error(error);
|
|
@@ -36238,11 +36275,12 @@ var App = class _App extends React40.Component {
|
|
|
36238
36275
|
);
|
|
36239
36276
|
}
|
|
36240
36277
|
});
|
|
36241
|
-
__publicField(this, "insertImages", async (imageFiles, sceneX, sceneY
|
|
36242
|
-
const waitFor = options?.waitFor ?? "inserted";
|
|
36278
|
+
__publicField(this, "insertImages", async (imageFiles, sceneX, sceneY) => {
|
|
36243
36279
|
const gridPadding = 50 / this.state.zoom.value;
|
|
36244
36280
|
const placeholders = positionElementsOnGrid(
|
|
36245
|
-
imageFiles.map(
|
|
36281
|
+
imageFiles.map(
|
|
36282
|
+
({ customData }) => this.newImagePlaceholder({ sceneX, sceneY, customData })
|
|
36283
|
+
),
|
|
36246
36284
|
sceneX,
|
|
36247
36285
|
sceneY,
|
|
36248
36286
|
gridPadding
|
|
@@ -36253,7 +36291,7 @@ var App = class _App extends React40.Component {
|
|
|
36253
36291
|
try {
|
|
36254
36292
|
return await this.initializeImage(
|
|
36255
36293
|
placeholder,
|
|
36256
|
-
await normalizeFile(imageFiles[i])
|
|
36294
|
+
await normalizeFile(imageFiles[i].file)
|
|
36257
36295
|
);
|
|
36258
36296
|
} catch (error) {
|
|
36259
36297
|
this.setState({
|
|
@@ -36282,17 +36320,8 @@ var App = class _App extends React40.Component {
|
|
|
36282
36320
|
elements: nextElements,
|
|
36283
36321
|
captureUpdate: CaptureUpdateAction41.IMMEDIATELY
|
|
36284
36322
|
});
|
|
36285
|
-
|
|
36286
|
-
this.
|
|
36287
|
-
this.actionManager.executeAction(actionFinalize);
|
|
36288
|
-
if (waitFor === "painted") {
|
|
36289
|
-
requestAnimationFrame(() => {
|
|
36290
|
-
requestAnimationFrame(() => resolve());
|
|
36291
|
-
});
|
|
36292
|
-
return;
|
|
36293
|
-
}
|
|
36294
|
-
resolve();
|
|
36295
|
-
});
|
|
36323
|
+
this.setState({}, () => {
|
|
36324
|
+
this.actionManager.executeAction(actionFinalize);
|
|
36296
36325
|
});
|
|
36297
36326
|
});
|
|
36298
36327
|
__publicField(this, "handleAppOnDrop", async (event) => {
|
|
@@ -36331,7 +36360,13 @@ var App = class _App extends React40.Component {
|
|
|
36331
36360
|
}
|
|
36332
36361
|
const imageFiles = fileItems.map((data) => data.file).filter((file2) => isSupportedImageFile(file2));
|
|
36333
36362
|
if (imageFiles.length > 0 && this.isToolSupported("image")) {
|
|
36334
|
-
return this.insertImages(
|
|
36363
|
+
return this.insertImages(
|
|
36364
|
+
imageFiles.map((file2) => ({
|
|
36365
|
+
file: file2
|
|
36366
|
+
})),
|
|
36367
|
+
sceneX,
|
|
36368
|
+
sceneY
|
|
36369
|
+
);
|
|
36335
36370
|
}
|
|
36336
36371
|
if (fileItems.length > 0) {
|
|
36337
36372
|
const { file: file2, fileHandle } = fileItems[0];
|
|
@@ -36691,6 +36726,8 @@ var App = class _App extends React40.Component {
|
|
|
36691
36726
|
});
|
|
36692
36727
|
__publicField(this, "getContextMenuItems", (type) => {
|
|
36693
36728
|
const options = [];
|
|
36729
|
+
const imageContextMenuItems = this.getImageContextMenuItems();
|
|
36730
|
+
const imageContextMenuSection = imageContextMenuItems.length > 0 ? [CONTEXT_MENU_SEPARATOR, ...imageContextMenuItems] : [];
|
|
36694
36731
|
if (type === "canvas") {
|
|
36695
36732
|
if (this.state.viewModeEnabled) {
|
|
36696
36733
|
return [actionToggleGridMode, actionToggleViewMode, actionToggleStats];
|
|
@@ -36713,7 +36750,9 @@ var App = class _App extends React40.Component {
|
|
|
36713
36750
|
}
|
|
36714
36751
|
options.push(copyText);
|
|
36715
36752
|
if (this.state.viewModeEnabled) {
|
|
36716
|
-
|
|
36753
|
+
const viewModeItems = [actionCopy];
|
|
36754
|
+
viewModeItems.push(...imageContextMenuSection, ...options);
|
|
36755
|
+
return viewModeItems;
|
|
36717
36756
|
}
|
|
36718
36757
|
const zIndexActions = this.editorInterface.formFactor === "desktop" ? [
|
|
36719
36758
|
CONTEXT_MENU_SEPARATOR,
|
|
@@ -36722,11 +36761,17 @@ var App = class _App extends React40.Component {
|
|
|
36722
36761
|
actionSendToBack,
|
|
36723
36762
|
actionBringToFront
|
|
36724
36763
|
] : [];
|
|
36725
|
-
|
|
36764
|
+
const elementItems = [
|
|
36726
36765
|
CONTEXT_MENU_SEPARATOR,
|
|
36727
36766
|
actionCut,
|
|
36728
36767
|
actionCopy,
|
|
36729
|
-
actionPaste
|
|
36768
|
+
actionPaste
|
|
36769
|
+
];
|
|
36770
|
+
elementItems.push(...imageContextMenuSection);
|
|
36771
|
+
if (imageContextMenuItems.length > 0) {
|
|
36772
|
+
elementItems.push(CONTEXT_MENU_SEPARATOR);
|
|
36773
|
+
}
|
|
36774
|
+
elementItems.push(
|
|
36730
36775
|
CONTEXT_MENU_SEPARATOR,
|
|
36731
36776
|
actionSelectAllElementsInFrame,
|
|
36732
36777
|
actionRemoveAllElementsFromFrame,
|
|
@@ -36759,6 +36804,21 @@ var App = class _App extends React40.Component {
|
|
|
36759
36804
|
actionToggleElementLock,
|
|
36760
36805
|
CONTEXT_MENU_SEPARATOR,
|
|
36761
36806
|
actionDeleteSelected
|
|
36807
|
+
);
|
|
36808
|
+
return elementItems;
|
|
36809
|
+
});
|
|
36810
|
+
__publicField(this, "getImageContextMenuItems", () => {
|
|
36811
|
+
if (!this.props.imageContextMenuItems) {
|
|
36812
|
+
return [];
|
|
36813
|
+
}
|
|
36814
|
+
const selectedElements = this.scene.getSelectedElements(this.state);
|
|
36815
|
+
if (selectedElements.length === 0 || !selectedElements.every((element) => isImageElement9(element))) {
|
|
36816
|
+
return [];
|
|
36817
|
+
}
|
|
36818
|
+
return [
|
|
36819
|
+
...this.props.imageContextMenuItems(
|
|
36820
|
+
selectedElements.map((element) => element.id)
|
|
36821
|
+
)
|
|
36762
36822
|
];
|
|
36763
36823
|
});
|
|
36764
36824
|
__publicField(this, "handleWheel", withBatchedUpdates(
|
|
@@ -38382,7 +38442,13 @@ var App = class _App extends React40.Component {
|
|
|
38382
38442
|
}
|
|
38383
38443
|
if (imageFiles.length > 0) {
|
|
38384
38444
|
if (this.isToolSupported("image")) {
|
|
38385
|
-
await this.insertImages(
|
|
38445
|
+
await this.insertImages(
|
|
38446
|
+
imageFiles.map((file2) => ({
|
|
38447
|
+
file: file2
|
|
38448
|
+
})),
|
|
38449
|
+
sceneX,
|
|
38450
|
+
sceneY
|
|
38451
|
+
);
|
|
38386
38452
|
} else {
|
|
38387
38453
|
this.setState({ errorMessage: t("errors.imageToolNotSupported") });
|
|
38388
38454
|
}
|
|
@@ -38458,7 +38524,13 @@ var App = class _App extends React40.Component {
|
|
|
38458
38524
|
})
|
|
38459
38525
|
);
|
|
38460
38526
|
const imageFiles = responses.filter((response) => !!response.file).map((response) => response.file);
|
|
38461
|
-
await this.insertImages(
|
|
38527
|
+
await this.insertImages(
|
|
38528
|
+
imageFiles.map((file2) => ({
|
|
38529
|
+
file: file2
|
|
38530
|
+
})),
|
|
38531
|
+
sceneX,
|
|
38532
|
+
sceneY
|
|
38533
|
+
);
|
|
38462
38534
|
const error = responses.find((response) => !!response.errorMessage);
|
|
38463
38535
|
if (error && error.errorMessage) {
|
|
38464
38536
|
this.setState({ errorMessage: error.errorMessage });
|
|
@@ -41206,6 +41278,7 @@ var ExcalidrawBase = (props) => {
|
|
|
41206
41278
|
onPointerUp,
|
|
41207
41279
|
onScrollChange,
|
|
41208
41280
|
onDuplicate,
|
|
41281
|
+
imageContextMenuItems,
|
|
41209
41282
|
children,
|
|
41210
41283
|
validateEmbeddable,
|
|
41211
41284
|
renderEmbeddable,
|
|
@@ -41301,6 +41374,7 @@ var ExcalidrawBase = (props) => {
|
|
|
41301
41374
|
onPointerUp,
|
|
41302
41375
|
onScrollChange,
|
|
41303
41376
|
onDuplicate,
|
|
41377
|
+
imageContextMenuItems,
|
|
41304
41378
|
validateEmbeddable,
|
|
41305
41379
|
renderEmbeddable,
|
|
41306
41380
|
showDeprecatedFonts,
|