@dwelle/excalidraw 0.5.0-ef89e88 → 0.5.0-efddbb7
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/CHANGELOG.md +81 -0
- package/README.md +111 -14
- package/dist/dev/{chunk-UPL5GSGP.js → chunk-AVAC6BVM.js} +11 -2
- package/dist/dev/chunk-AVAC6BVM.js.map +7 -0
- package/dist/dev/{chunk-VLJRILK3.js → chunk-OKDHCI5V.js} +1844 -1440
- package/dist/dev/chunk-OKDHCI5V.js.map +7 -0
- package/dist/dev/{chunk-H5SL5I5R.js → chunk-UEBEBUE2.js} +2 -2
- package/dist/dev/components/TTDDialog/{CodeMirrorEditor-65RQRK4A.js → CodeMirrorEditor-2YIEAZU7.js} +2 -2
- package/dist/dev/data/{image-JR54FB4B.js → image-O7OJXMIJ.js} +3 -3
- package/dist/dev/index.css +85 -43
- package/dist/dev/index.css.map +3 -3
- package/dist/dev/index.js +2939 -2010
- package/dist/dev/index.js.map +4 -4
- package/dist/dev/locales/{en-IZ5JJCQN.js → en-XVKSJYG2.js} +4 -2
- package/dist/dev/subset-shared.chunk.js +1 -1
- package/dist/dev/subset-worker.chunk.js +1 -1
- package/dist/prod/chunk-5EYFVTC7.js +34 -0
- package/dist/prod/{chunk-MYTKOPOQ.js → chunk-T6UH5ZKV.js} +5 -5
- package/dist/prod/{chunk-B47HEJUH.js → chunk-Y6NXDCR7.js} +1 -1
- package/dist/prod/components/TTDDialog/{CodeMirrorEditor-B64TEOC3.js → CodeMirrorEditor-JV2LT6ZS.js} +1 -1
- package/dist/prod/data/image-XRO5552B.js +1 -0
- package/dist/prod/index.css +1 -1
- package/dist/prod/index.js +28 -28
- package/dist/prod/locales/en-BNQNBQ43.js +1 -0
- package/dist/prod/subset-shared.chunk.js +1 -1
- package/dist/prod/subset-worker.chunk.js +1 -1
- package/dist/types/common/src/appEventBus.d.ts +27 -0
- package/dist/types/common/src/index.d.ts +2 -0
- package/dist/types/common/src/utils.d.ts +1 -3
- package/dist/types/common/src/versionedSnapshotStore.d.ts +17 -0
- package/dist/types/element/src/Scene.d.ts +5 -3
- package/dist/types/element/src/bounds.d.ts +4 -2
- package/dist/types/element/src/duplicate.d.ts +1 -0
- package/dist/types/element/src/frame.d.ts +7 -6
- package/dist/types/element/src/linearElementEditor.d.ts +2 -2
- package/dist/types/element/src/selection.d.ts +2 -2
- package/dist/types/element/src/shape.d.ts +1 -1
- package/dist/types/element/src/typeChecks.d.ts +1 -0
- package/dist/types/element/src/utils.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionAddToLibrary.d.ts +8 -8
- package/dist/types/excalidraw/actions/actionBoundText.d.ts +6 -6
- package/dist/types/excalidraw/actions/actionCanvas.d.ts +30 -30
- package/dist/types/excalidraw/actions/actionClipboard.d.ts +6 -6
- package/dist/types/excalidraw/actions/actionCropEditor.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +9 -9
- package/dist/types/excalidraw/actions/actionDeselect.d.ts +160 -0
- package/dist/types/excalidraw/actions/actionElementLink.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionElementLock.d.ts +6 -6
- package/dist/types/excalidraw/actions/actionEmbeddable.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionExport.d.ts +48 -323
- package/dist/types/excalidraw/actions/actionFrame.d.ts +12 -12
- package/dist/types/excalidraw/actions/actionGroup.d.ts +6 -6
- package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionLink.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionMenu.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionProperties.d.ts +6 -6
- package/dist/types/excalidraw/actions/actionSelectAll.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionStyles.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionToggleArrowBinding.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionToggleMidpointSnapping.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionToggleStats.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +3 -3
- package/dist/types/excalidraw/actions/index.d.ts +1 -0
- package/dist/types/excalidraw/actions/types.d.ts +1 -1
- package/dist/types/excalidraw/appState.d.ts +1 -0
- package/dist/types/excalidraw/clipboard.d.ts +2 -3
- package/dist/types/excalidraw/components/App.d.ts +41 -10
- package/dist/types/excalidraw/components/AppStateObserver.d.ts +37 -0
- package/dist/types/excalidraw/components/TTDDialog/utils/TTDStreamFetch.d.ts +1 -1
- package/dist/types/excalidraw/components/Toast.d.ts +8 -4
- package/dist/types/excalidraw/components/canvases/InteractiveCanvas.d.ts +1 -1
- package/dist/types/excalidraw/components/canvases/NewElementCanvas.d.ts +1 -0
- package/dist/types/excalidraw/components/canvases/StaticCanvas.d.ts +1 -1
- package/dist/types/excalidraw/components/dropdownMenu/DropdownMenuItemContentRadio.d.ts +2 -1
- package/dist/types/excalidraw/components/main-menu/DefaultItems.d.ts +1 -0
- package/dist/types/excalidraw/components/shapes.d.ts +7 -0
- package/dist/types/excalidraw/data/blob.d.ts +13 -14
- package/dist/types/excalidraw/data/filesystem.d.ts +3 -5
- package/dist/types/excalidraw/data/index.d.ts +2 -3
- package/dist/types/excalidraw/data/json.d.ts +21 -13
- package/dist/types/excalidraw/data/resave.d.ts +7 -2
- package/dist/types/excalidraw/hooks/useAppStateValue.d.ts +29 -0
- package/dist/types/excalidraw/index.d.ts +23 -3
- package/dist/types/excalidraw/scene/Renderer.d.ts +425 -19
- package/dist/types/excalidraw/types.d.ts +76 -5
- package/dist/types/fractional-indexing/src/index.d.ts +29 -0
- package/dist/types/math/src/constants.d.ts +0 -1
- package/dist/types/math/src/curve.d.ts +4 -1
- package/package.json +4 -5
- package/dist/dev/chunk-UPL5GSGP.js.map +0 -7
- package/dist/dev/chunk-VLJRILK3.js.map +0 -7
- package/dist/prod/chunk-ZTGTHG3M.js +0 -34
- package/dist/prod/data/image-I4FBW6ZT.js +0 -1
- package/dist/prod/locales/en-4R6EP6SP.js +0 -1
- package/dist/types/utils/src/index.d.ts +0 -4
- /package/dist/dev/{chunk-H5SL5I5R.js.map → chunk-UEBEBUE2.js.map} +0 -0
- /package/dist/dev/components/TTDDialog/{CodeMirrorEditor-65RQRK4A.js.map → CodeMirrorEditor-2YIEAZU7.js.map} +0 -0
- /package/dist/dev/data/{image-JR54FB4B.js.map → image-O7OJXMIJ.js.map} +0 -0
- /package/dist/dev/locales/{en-IZ5JJCQN.js.map → en-XVKSJYG2.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
define_import_meta_env_default
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UEBEBUE2.js";
|
|
4
4
|
import {
|
|
5
5
|
__publicField
|
|
6
6
|
} from "./chunk-XDFCUUT6.js";
|
|
@@ -348,8 +348,15 @@ var initial_guesses = [
|
|
|
348
348
|
[0.2, 0],
|
|
349
349
|
[0.8, 0]
|
|
350
350
|
];
|
|
351
|
-
var calculate = ([t0, s0], l, c) => {
|
|
352
|
-
const solution = solveWithAnalyticalJacobian(
|
|
351
|
+
var calculate = ([t0, s0], l, c, tolerance = 0.01, iterLimit = 4) => {
|
|
352
|
+
const solution = solveWithAnalyticalJacobian(
|
|
353
|
+
c,
|
|
354
|
+
l,
|
|
355
|
+
t0,
|
|
356
|
+
s0,
|
|
357
|
+
tolerance,
|
|
358
|
+
iterLimit
|
|
359
|
+
);
|
|
353
360
|
if (!solution) {
|
|
354
361
|
return null;
|
|
355
362
|
}
|
|
@@ -359,16 +366,34 @@ var calculate = ([t0, s0], l, c) => {
|
|
|
359
366
|
}
|
|
360
367
|
return bezierEquation(c, t);
|
|
361
368
|
};
|
|
362
|
-
function curveIntersectLineSegment(c, l) {
|
|
363
|
-
let solution = calculate(
|
|
369
|
+
function curveIntersectLineSegment(c, l, opts) {
|
|
370
|
+
let solution = calculate(
|
|
371
|
+
initial_guesses[0],
|
|
372
|
+
l,
|
|
373
|
+
c,
|
|
374
|
+
opts?.tolerance,
|
|
375
|
+
opts?.iterLimit
|
|
376
|
+
);
|
|
364
377
|
if (solution) {
|
|
365
378
|
return [solution];
|
|
366
379
|
}
|
|
367
|
-
solution = calculate(
|
|
380
|
+
solution = calculate(
|
|
381
|
+
initial_guesses[1],
|
|
382
|
+
l,
|
|
383
|
+
c,
|
|
384
|
+
opts?.tolerance,
|
|
385
|
+
opts?.iterLimit
|
|
386
|
+
);
|
|
368
387
|
if (solution) {
|
|
369
388
|
return [solution];
|
|
370
389
|
}
|
|
371
|
-
solution = calculate(
|
|
390
|
+
solution = calculate(
|
|
391
|
+
initial_guesses[2],
|
|
392
|
+
l,
|
|
393
|
+
c,
|
|
394
|
+
opts?.tolerance,
|
|
395
|
+
opts?.iterLimit
|
|
396
|
+
);
|
|
372
397
|
if (solution) {
|
|
373
398
|
return [solution];
|
|
374
399
|
}
|
|
@@ -1846,32 +1871,23 @@ var debounce = (fn, timeout) => {
|
|
|
1846
1871
|
};
|
|
1847
1872
|
return ret;
|
|
1848
1873
|
};
|
|
1849
|
-
var throttleRAF = (fn
|
|
1874
|
+
var throttleRAF = (fn) => {
|
|
1850
1875
|
let timerId = null;
|
|
1851
1876
|
let lastArgs = null;
|
|
1852
|
-
|
|
1853
|
-
const scheduleFunc = (args) => {
|
|
1877
|
+
const scheduleFunc = () => {
|
|
1854
1878
|
timerId = window.requestAnimationFrame(() => {
|
|
1855
1879
|
timerId = null;
|
|
1856
|
-
|
|
1880
|
+
const args = lastArgs;
|
|
1857
1881
|
lastArgs = null;
|
|
1858
|
-
if (
|
|
1859
|
-
|
|
1860
|
-
lastArgsTrailing = null;
|
|
1861
|
-
scheduleFunc(lastArgs);
|
|
1882
|
+
if (args) {
|
|
1883
|
+
fn(...args);
|
|
1862
1884
|
}
|
|
1863
1885
|
});
|
|
1864
1886
|
};
|
|
1865
1887
|
const ret = (...args) => {
|
|
1866
|
-
if (isTestEnv()) {
|
|
1867
|
-
fn(...args);
|
|
1868
|
-
return;
|
|
1869
|
-
}
|
|
1870
1888
|
lastArgs = args;
|
|
1871
1889
|
if (timerId === null) {
|
|
1872
|
-
scheduleFunc(
|
|
1873
|
-
} else if (opts?.trailing) {
|
|
1874
|
-
lastArgsTrailing = args;
|
|
1890
|
+
scheduleFunc();
|
|
1875
1891
|
}
|
|
1876
1892
|
};
|
|
1877
1893
|
ret.flush = () => {
|
|
@@ -1880,12 +1896,12 @@ var throttleRAF = (fn, opts) => {
|
|
|
1880
1896
|
timerId = null;
|
|
1881
1897
|
}
|
|
1882
1898
|
if (lastArgs) {
|
|
1883
|
-
fn(...
|
|
1884
|
-
lastArgs =
|
|
1899
|
+
fn(...lastArgs);
|
|
1900
|
+
lastArgs = null;
|
|
1885
1901
|
}
|
|
1886
1902
|
};
|
|
1887
1903
|
ret.cancel = () => {
|
|
1888
|
-
lastArgs =
|
|
1904
|
+
lastArgs = null;
|
|
1889
1905
|
if (timerId !== null) {
|
|
1890
1906
|
cancelAnimationFrame(timerId);
|
|
1891
1907
|
timerId = null;
|
|
@@ -2117,10 +2133,6 @@ var arrayToMap = (items) => {
|
|
|
2117
2133
|
return acc;
|
|
2118
2134
|
}, /* @__PURE__ */ new Map());
|
|
2119
2135
|
};
|
|
2120
|
-
var arrayToMapWithIndex = (elements) => elements.reduce((acc, element, idx) => {
|
|
2121
|
-
acc.set(element.id, [element, idx]);
|
|
2122
|
-
return acc;
|
|
2123
|
-
}, /* @__PURE__ */ new Map());
|
|
2124
2136
|
var arrayToObject = (array, groupBy) => array.reduce((acc, value, idx) => {
|
|
2125
2137
|
acc[groupBy ? groupBy(value) : idx] = value;
|
|
2126
2138
|
return acc;
|
|
@@ -2473,6 +2485,81 @@ var Emitter = class {
|
|
|
2473
2485
|
}
|
|
2474
2486
|
};
|
|
2475
2487
|
|
|
2488
|
+
// ../common/src/appEventBus.ts
|
|
2489
|
+
var AppEventBus = class {
|
|
2490
|
+
constructor(behavior) {
|
|
2491
|
+
this.behavior = behavior;
|
|
2492
|
+
__publicField(this, "emitters", /* @__PURE__ */ new Map());
|
|
2493
|
+
__publicField(this, "lastPayload", /* @__PURE__ */ new Map());
|
|
2494
|
+
__publicField(this, "emittedOnce", /* @__PURE__ */ new Set());
|
|
2495
|
+
}
|
|
2496
|
+
getEmitter(name) {
|
|
2497
|
+
let emitter = this.emitters.get(name);
|
|
2498
|
+
if (!emitter) {
|
|
2499
|
+
emitter = new Emitter();
|
|
2500
|
+
this.emitters.set(name, emitter);
|
|
2501
|
+
}
|
|
2502
|
+
return emitter;
|
|
2503
|
+
}
|
|
2504
|
+
toPromiseValue(args) {
|
|
2505
|
+
return args.length === 1 ? args[0] : args;
|
|
2506
|
+
}
|
|
2507
|
+
on(name, callback) {
|
|
2508
|
+
const eventBehavior = this.behavior[name];
|
|
2509
|
+
const cachedPayload = this.lastPayload.get(name);
|
|
2510
|
+
if (callback) {
|
|
2511
|
+
if (eventBehavior.replay === "last" && cachedPayload) {
|
|
2512
|
+
queueMicrotask(() => callback(...cachedPayload));
|
|
2513
|
+
if (eventBehavior.cardinality === "once") {
|
|
2514
|
+
return () => {
|
|
2515
|
+
};
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
return this.getEmitter(name).on(callback);
|
|
2519
|
+
}
|
|
2520
|
+
if (eventBehavior.cardinality !== "once" || eventBehavior.replay !== "last") {
|
|
2521
|
+
throw new Error(`Event "${String(name)}" requires a callback`);
|
|
2522
|
+
}
|
|
2523
|
+
if (cachedPayload) {
|
|
2524
|
+
return Promise.resolve(this.toPromiseValue(cachedPayload));
|
|
2525
|
+
}
|
|
2526
|
+
return new Promise((resolve) => {
|
|
2527
|
+
this.getEmitter(name).once((...args) => {
|
|
2528
|
+
resolve(this.toPromiseValue(args));
|
|
2529
|
+
});
|
|
2530
|
+
});
|
|
2531
|
+
}
|
|
2532
|
+
emit(name, ...args) {
|
|
2533
|
+
const eventBehavior = this.behavior[name];
|
|
2534
|
+
if (!isProdEnv()) {
|
|
2535
|
+
if (eventBehavior.cardinality === "once") {
|
|
2536
|
+
if (this.emittedOnce.has(name)) {
|
|
2537
|
+
throw new Error(`Event "${String(name)}" can only be emitted once`);
|
|
2538
|
+
}
|
|
2539
|
+
this.emittedOnce.add(name);
|
|
2540
|
+
}
|
|
2541
|
+
}
|
|
2542
|
+
if (eventBehavior.replay === "last") {
|
|
2543
|
+
this.lastPayload.set(name, args);
|
|
2544
|
+
}
|
|
2545
|
+
try {
|
|
2546
|
+
this.getEmitter(name).trigger(...args);
|
|
2547
|
+
} finally {
|
|
2548
|
+
if (eventBehavior.cardinality === "once") {
|
|
2549
|
+
this.getEmitter(name).clear();
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
clear() {
|
|
2554
|
+
this.lastPayload.clear();
|
|
2555
|
+
this.emittedOnce.clear();
|
|
2556
|
+
for (const emitter of this.emitters.values()) {
|
|
2557
|
+
emitter.clear();
|
|
2558
|
+
}
|
|
2559
|
+
this.emitters.clear();
|
|
2560
|
+
}
|
|
2561
|
+
};
|
|
2562
|
+
|
|
2476
2563
|
// ../common/debug.ts
|
|
2477
2564
|
var lessPrecise = (num, precision = 5) => parseFloat(num.toPrecision(precision));
|
|
2478
2565
|
var getAvgFrameTime = (times) => lessPrecise(times.reduce((a, b) => a + b) / times.length);
|
|
@@ -2722,7 +2809,6 @@ var getDefaultAppState = () => {
|
|
|
2722
2809
|
open: false,
|
|
2723
2810
|
panels: STATS_PANELS.generalStats | STATS_PANELS.elementProperties
|
|
2724
2811
|
},
|
|
2725
|
-
startBoundElement: null,
|
|
2726
2812
|
suggestedBinding: null,
|
|
2727
2813
|
frameRendering: { enabled: true, clip: true, name: true, outline: true },
|
|
2728
2814
|
frameToHighlight: null,
|
|
@@ -2750,7 +2836,8 @@ var getDefaultAppState = () => {
|
|
|
2750
2836
|
searchMatches: null,
|
|
2751
2837
|
lockedMultiSelections: {},
|
|
2752
2838
|
activeLockedId: null,
|
|
2753
|
-
bindMode: "orbit"
|
|
2839
|
+
bindMode: "orbit",
|
|
2840
|
+
boxSelectionMode: "contain"
|
|
2754
2841
|
};
|
|
2755
2842
|
};
|
|
2756
2843
|
var APP_STATE_STORAGE_CONF = /* @__PURE__ */ ((config) => config)({
|
|
@@ -2800,6 +2887,7 @@ var APP_STATE_STORAGE_CONF = /* @__PURE__ */ ((config) => config)({
|
|
|
2800
2887
|
gridModeEnabled: { browser: true, export: true, server: true },
|
|
2801
2888
|
height: { browser: false, export: false, server: false },
|
|
2802
2889
|
isBindingEnabled: { browser: true, export: false, server: false },
|
|
2890
|
+
boxSelectionMode: { browser: true, export: false, server: false },
|
|
2803
2891
|
bindingPreference: { browser: true, export: false, server: false },
|
|
2804
2892
|
isMidpointSnappingEnabled: { browser: true, export: false, server: false },
|
|
2805
2893
|
defaultSidebarDockedPreference: {
|
|
@@ -2836,7 +2924,6 @@ var APP_STATE_STORAGE_CONF = /* @__PURE__ */ ((config) => config)({
|
|
|
2836
2924
|
selectionElement: { browser: false, export: false, server: false },
|
|
2837
2925
|
shouldCacheIgnoreZoom: { browser: true, export: false, server: false },
|
|
2838
2926
|
stats: { browser: true, export: false, server: false },
|
|
2839
|
-
startBoundElement: { browser: false, export: false, server: false },
|
|
2840
2927
|
suggestedBinding: { browser: false, export: false, server: false },
|
|
2841
2928
|
frameRendering: { browser: false, export: false, server: false },
|
|
2842
2929
|
frameToHighlight: { browser: false, export: false, server: false },
|
|
@@ -3724,6 +3811,25 @@ var canBecomePolygon = (points) => {
|
|
|
3724
3811
|
return points.length > 3 || // 3-point polygons can't have all points in a single line
|
|
3725
3812
|
points.length === 3 && !pointsEqual(points[0], points[points.length - 1]);
|
|
3726
3813
|
};
|
|
3814
|
+
var isEligibleFrameChildType = (type) => {
|
|
3815
|
+
switch (type) {
|
|
3816
|
+
case "rectangle":
|
|
3817
|
+
case "diamond":
|
|
3818
|
+
case "ellipse":
|
|
3819
|
+
case "arrow":
|
|
3820
|
+
case "line":
|
|
3821
|
+
case "freedraw":
|
|
3822
|
+
case "text":
|
|
3823
|
+
case "image":
|
|
3824
|
+
case "frame":
|
|
3825
|
+
case "embeddable": {
|
|
3826
|
+
return true;
|
|
3827
|
+
}
|
|
3828
|
+
default: {
|
|
3829
|
+
return false;
|
|
3830
|
+
}
|
|
3831
|
+
}
|
|
3832
|
+
};
|
|
3727
3833
|
|
|
3728
3834
|
// ../element/src/utils.ts
|
|
3729
3835
|
var ElementShapesCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -3758,12 +3864,12 @@ var setElementShapesCacheEntry = (element, shape, offset) => {
|
|
|
3758
3864
|
}
|
|
3759
3865
|
shapes.set(offset, shape);
|
|
3760
3866
|
};
|
|
3761
|
-
function deconstructLinearOrFreeDrawElement(element) {
|
|
3867
|
+
function deconstructLinearOrFreeDrawElement(element, elementsMap) {
|
|
3762
3868
|
const cachedShape = getElementShapesCacheEntry(element, 0);
|
|
3763
3869
|
if (cachedShape) {
|
|
3764
3870
|
return cachedShape;
|
|
3765
3871
|
}
|
|
3766
|
-
const ops = generateLinearCollisionShape(element);
|
|
3872
|
+
const ops = generateLinearCollisionShape(element, elementsMap);
|
|
3767
3873
|
const lines = [];
|
|
3768
3874
|
const curves = [];
|
|
3769
3875
|
for (let idx = 0; idx < ops.length; idx += 1) {
|
|
@@ -4170,7 +4276,7 @@ var getSnapOutlineMidPoint = (point, element, elementsMap, zoom) => {
|
|
|
4170
4276
|
)
|
|
4171
4277
|
];
|
|
4172
4278
|
const candidate = sideMidpoints.find(
|
|
4173
|
-
(
|
|
4279
|
+
(midpoint2) => pointDistance(point, midpoint2) <= maxBindingDistance_simple(zoom) + element.strokeWidth / 2 && !hitElementItself({
|
|
4174
4280
|
point,
|
|
4175
4281
|
element,
|
|
4176
4282
|
threshold: 0,
|
|
@@ -5060,7 +5166,8 @@ var getContainerCenter = (container, appState, elementsMap) => {
|
|
|
5060
5166
|
if (!midSegmentMidpoint) {
|
|
5061
5167
|
midSegmentMidpoint = LinearElementEditor.getSegmentMidPoint(
|
|
5062
5168
|
container,
|
|
5063
|
-
index + 1
|
|
5169
|
+
index + 1,
|
|
5170
|
+
elementsMap
|
|
5064
5171
|
);
|
|
5065
5172
|
}
|
|
5066
5173
|
return { x: midSegmentMidpoint[0], y: midSegmentMidpoint[1] };
|
|
@@ -5195,7 +5302,7 @@ var distanceToElement = (element, elementsMap, p) => {
|
|
|
5195
5302
|
case "line":
|
|
5196
5303
|
case "arrow":
|
|
5197
5304
|
case "freedraw":
|
|
5198
|
-
return distanceToLinearOrFreeDraElement(element, p);
|
|
5305
|
+
return distanceToLinearOrFreeDraElement(element, elementsMap, p);
|
|
5199
5306
|
}
|
|
5200
5307
|
};
|
|
5201
5308
|
var distanceToRectanguloidElement = (element, elementsMap, p) => {
|
|
@@ -5224,20 +5331,32 @@ var distanceToEllipseElement = (element, elementsMap, p) => {
|
|
|
5224
5331
|
ellipse(center, element.width / 2, element.height / 2)
|
|
5225
5332
|
);
|
|
5226
5333
|
};
|
|
5227
|
-
var distanceToLinearOrFreeDraElement = (element, p) => {
|
|
5228
|
-
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
5334
|
+
var distanceToLinearOrFreeDraElement = (element, elementsMap, p) => {
|
|
5335
|
+
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
5336
|
+
element,
|
|
5337
|
+
elementsMap
|
|
5338
|
+
);
|
|
5229
5339
|
return Math.min(
|
|
5230
5340
|
...lines.map((s) => distanceToLineSegment(p, s)),
|
|
5231
5341
|
...curves.map((a) => curvePointDistance(a, p))
|
|
5232
5342
|
);
|
|
5233
5343
|
};
|
|
5234
5344
|
|
|
5345
|
+
// ../element/src/comparisons.ts
|
|
5346
|
+
var hasBackground = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "line" || type === "freedraw";
|
|
5347
|
+
var hasStrokeColor = (type) => type === "rectangle" || type === "ellipse" || type === "diamond" || type === "freedraw" || type === "arrow" || type === "line" || type === "text" || type === "embeddable";
|
|
5348
|
+
var hasStrokeWidth = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "freedraw" || type === "arrow" || type === "line";
|
|
5349
|
+
var hasStrokeStyle = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "arrow" || type === "line";
|
|
5350
|
+
var canChangeRoundness = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "line" || type === "diamond" || type === "image";
|
|
5351
|
+
var toolIsArrow = (type) => type === "arrow";
|
|
5352
|
+
var canHaveArrowheads = (type) => type === "arrow";
|
|
5353
|
+
|
|
5235
5354
|
// ../element/src/collision.ts
|
|
5236
5355
|
var shouldTestInside = (element) => {
|
|
5237
5356
|
if (element.type === "arrow") {
|
|
5238
5357
|
return false;
|
|
5239
5358
|
}
|
|
5240
|
-
const isDraggableFromInside = !isTransparent(element.backgroundColor) || hasBoundTextElement(element) || isIframeLikeElement(element) || isTextElement(element);
|
|
5359
|
+
const isDraggableFromInside = hasBackground(element.type) && !isTransparent(element.backgroundColor) || hasBoundTextElement(element) || isIframeLikeElement(element) || isTextElement(element);
|
|
5241
5360
|
if (element.type === "line") {
|
|
5242
5361
|
return isDraggableFromInside && isPathALoop(element.points);
|
|
5243
5362
|
}
|
|
@@ -5274,14 +5393,11 @@ var hitElementItself = ({
|
|
|
5274
5393
|
)
|
|
5275
5394
|
) : false;
|
|
5276
5395
|
const bounds = getElementBounds(element, elementsMap, true);
|
|
5277
|
-
const hitBounds =
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
-element.angle
|
|
5283
|
-
),
|
|
5284
|
-
pointFrom(bounds[2] + threshold, bounds[3] + threshold)
|
|
5396
|
+
const hitBounds = isPointInRotatedBounds(
|
|
5397
|
+
point,
|
|
5398
|
+
bounds,
|
|
5399
|
+
element.angle,
|
|
5400
|
+
threshold
|
|
5285
5401
|
);
|
|
5286
5402
|
if (!hitBounds && !hitFrameName) {
|
|
5287
5403
|
return false;
|
|
@@ -5299,13 +5415,17 @@ var hitElementItself = ({
|
|
|
5299
5415
|
cachedHit = result;
|
|
5300
5416
|
return result;
|
|
5301
5417
|
};
|
|
5418
|
+
var isPointInRotatedBounds = (point, bounds, angle, tolerance = 0) => {
|
|
5419
|
+
const adjustedPoint = angle === 0 ? point : pointRotateRads(point, getCenterForBounds(bounds), -angle);
|
|
5420
|
+
return isPointWithinBounds(
|
|
5421
|
+
pointFrom(bounds[0] - tolerance, bounds[1] - tolerance),
|
|
5422
|
+
adjustedPoint,
|
|
5423
|
+
pointFrom(bounds[2] + tolerance, bounds[3] + tolerance)
|
|
5424
|
+
);
|
|
5425
|
+
};
|
|
5302
5426
|
var hitElementBoundingBox = (point, element, elementsMap, tolerance = 0) => {
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
y1 -= tolerance;
|
|
5306
|
-
x2 += tolerance;
|
|
5307
|
-
y2 += tolerance;
|
|
5308
|
-
return isPointWithinBounds(pointFrom(x1, y1), point, pointFrom(x2, y2));
|
|
5427
|
+
const bounds = getElementBounds(element, elementsMap, true);
|
|
5428
|
+
return isPointInRotatedBounds(point, bounds, element.angle, tolerance);
|
|
5309
5429
|
};
|
|
5310
5430
|
var hitElementBoundingBoxOnly = (hitArgs, elementsMap) => !hitElementItself(hitArgs) && // bound text is considered part of the element (even if it's outside the bounding box)
|
|
5311
5431
|
!hitElementBoundText(hitArgs.point, hitArgs.element, elementsMap) && hitElementBoundingBox(hitArgs.point, hitArgs.element, elementsMap);
|
|
@@ -5369,7 +5489,7 @@ var getAllHoveredElementAtPoint = (point, elements, elementsMap, tolerance) => {
|
|
|
5369
5489
|
);
|
|
5370
5490
|
if (isBindableElement(element, false) && bindingBorderTest(element, point, elementsMap, tolerance)) {
|
|
5371
5491
|
candidateElements.push(element);
|
|
5372
|
-
if (!isTransparent(element.backgroundColor)) {
|
|
5492
|
+
if (hasBackground(element.type) && !isTransparent(element.backgroundColor)) {
|
|
5373
5493
|
break;
|
|
5374
5494
|
}
|
|
5375
5495
|
}
|
|
@@ -5464,7 +5584,12 @@ var intersectElementWithLineSegment = (element, elementsMap, line2, offset = 0,
|
|
|
5464
5584
|
case "line":
|
|
5465
5585
|
case "freedraw":
|
|
5466
5586
|
case "arrow":
|
|
5467
|
-
return intersectLinearOrFreeDrawWithLineSegment(
|
|
5587
|
+
return intersectLinearOrFreeDrawWithLineSegment(
|
|
5588
|
+
element,
|
|
5589
|
+
line2,
|
|
5590
|
+
elementsMap,
|
|
5591
|
+
onlyFirst
|
|
5592
|
+
);
|
|
5468
5593
|
}
|
|
5469
5594
|
};
|
|
5470
5595
|
var curveIntersections = (curves, segment, intersections, center, angle, onlyFirst = false) => {
|
|
@@ -5503,8 +5628,11 @@ var lineIntersections = (lines, segment, intersections, center, angle, onlyFirst
|
|
|
5503
5628
|
}
|
|
5504
5629
|
return intersections;
|
|
5505
5630
|
};
|
|
5506
|
-
var intersectLinearOrFreeDrawWithLineSegment = (element, segment, onlyFirst = false) => {
|
|
5507
|
-
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
5631
|
+
var intersectLinearOrFreeDrawWithLineSegment = (element, segment, elementsMap, onlyFirst = false) => {
|
|
5632
|
+
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
5633
|
+
element,
|
|
5634
|
+
elementsMap
|
|
5635
|
+
);
|
|
5508
5636
|
const intersections = [];
|
|
5509
5637
|
for (const l of lines) {
|
|
5510
5638
|
const intersection = lineSegmentIntersectionPoints(l, segment);
|
|
@@ -5526,7 +5654,9 @@ var intersectLinearOrFreeDrawWithLineSegment = (element, segment, onlyFirst = fa
|
|
|
5526
5654
|
if (!doBoundsIntersect(b1, b2)) {
|
|
5527
5655
|
continue;
|
|
5528
5656
|
}
|
|
5529
|
-
const hits = curveIntersectLineSegment(c, segment
|
|
5657
|
+
const hits = curveIntersectLineSegment(c, segment, {
|
|
5658
|
+
iterLimit: 10
|
|
5659
|
+
});
|
|
5530
5660
|
if (hits.length > 0) {
|
|
5531
5661
|
intersections.push(...hits);
|
|
5532
5662
|
if (onlyFirst) {
|
|
@@ -7190,7 +7320,7 @@ var normalizeArrowElementUpdate = (global, nextFixedSegments, startIsSpecial, en
|
|
|
7190
7320
|
vectorScale(vectorFromPoint(global[0]), -1)
|
|
7191
7321
|
)
|
|
7192
7322
|
);
|
|
7193
|
-
if (offsetX < -MAX_POS || offsetX > MAX_POS || offsetY < -MAX_POS || offsetY > MAX_POS || offsetX + points[points.length - 1][0] < -MAX_POS ||
|
|
7323
|
+
if (offsetX < -MAX_POS || offsetX > MAX_POS || offsetY < -MAX_POS || offsetY > MAX_POS || offsetX + points[points.length - 1][0] < -MAX_POS || offsetX + points[points.length - 1][0] > MAX_POS || offsetY + points[points.length - 1][1] < -MAX_POS || offsetY + points[points.length - 1][1] > MAX_POS) {
|
|
7194
7324
|
console.error(
|
|
7195
7325
|
"Elbow arrow normalization is outside reasonable bounds (> 1e6)",
|
|
7196
7326
|
{
|
|
@@ -7794,11 +7924,7 @@ var getBindingStrategyForDraggingBindingElementEndpoints_simple = (arrow, draggi
|
|
|
7794
7924
|
threshold: 0,
|
|
7795
7925
|
overrideShouldTestInside: true
|
|
7796
7926
|
});
|
|
7797
|
-
if (otherBinding && otherBinding.elementId === hit?.id) {
|
|
7798
|
-
invariant(
|
|
7799
|
-
!opts?.newArrow || appState.selectedLinearElement?.initialState.origin,
|
|
7800
|
-
"appState.selectedLinearElement.initialState.origin must be defined for new arrows"
|
|
7801
|
-
);
|
|
7927
|
+
if (otherBinding && otherBinding.elementId === hit?.id && (!opts?.newArrow || appState.selectedLinearElement?.initialState.origin)) {
|
|
7802
7928
|
return {
|
|
7803
7929
|
start: {
|
|
7804
7930
|
mode: "inside",
|
|
@@ -8608,8 +8734,8 @@ var calculateFixedPointForElbowArrowBinding = (linearElement, hoveredElement, st
|
|
|
8608
8734
|
);
|
|
8609
8735
|
return {
|
|
8610
8736
|
fixedPoint: normalizeFixedPoint([
|
|
8611
|
-
(nonRotatedSnappedGlobalPoint[0] - hoveredElement.x) / hoveredElement.width,
|
|
8612
|
-
(nonRotatedSnappedGlobalPoint[1] - hoveredElement.y) / hoveredElement.height
|
|
8737
|
+
(nonRotatedSnappedGlobalPoint[0] - hoveredElement.x) / Math.max(hoveredElement.width, PRECISION),
|
|
8738
|
+
(nonRotatedSnappedGlobalPoint[1] - hoveredElement.y) / Math.max(hoveredElement.height, PRECISION)
|
|
8613
8739
|
])
|
|
8614
8740
|
};
|
|
8615
8741
|
};
|
|
@@ -8625,8 +8751,8 @@ var calculateFixedPointForNonElbowArrowBinding = (linearElement, hoveredElement,
|
|
|
8625
8751
|
elementCenter,
|
|
8626
8752
|
-hoveredElement.angle
|
|
8627
8753
|
);
|
|
8628
|
-
const fixedPointX = (nonRotatedPoint[0] - hoveredElement.x) / hoveredElement.width;
|
|
8629
|
-
const fixedPointY = (nonRotatedPoint[1] - hoveredElement.y) / hoveredElement.height;
|
|
8754
|
+
const fixedPointX = (nonRotatedPoint[0] - hoveredElement.x) / Math.max(hoveredElement.width, PRECISION);
|
|
8755
|
+
const fixedPointY = (nonRotatedPoint[1] - hoveredElement.y) / Math.max(hoveredElement.height, PRECISION);
|
|
8630
8756
|
return {
|
|
8631
8757
|
fixedPoint: normalizeFixedPoint([fixedPointX, fixedPointY])
|
|
8632
8758
|
};
|
|
@@ -9216,12 +9342,14 @@ var _LinearElementEditor = class _LinearElementEditor {
|
|
|
9216
9342
|
return false;
|
|
9217
9343
|
});
|
|
9218
9344
|
}
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
|
|
9345
|
+
if (lastClickedPoint < 0 || !selectedPointsIndices.includes(lastClickedPoint) || !element.points[lastClickedPoint]) {
|
|
9346
|
+
console.error(
|
|
9347
|
+
`There must be a valid lastClickedPoint in order to drag it. selectedPointsIndices(${JSON.stringify(
|
|
9348
|
+
selectedPointsIndices
|
|
9349
|
+
)}) points(0..${element.points.length - 1}) lastClickedPoint(${lastClickedPoint}) isElbowArrow: ${elbowed}`
|
|
9350
|
+
);
|
|
9351
|
+
lastClickedPoint = element.points.length - 1;
|
|
9352
|
+
}
|
|
9225
9353
|
const draggingPoint = element.points[lastClickedPoint];
|
|
9226
9354
|
const pivotPoint = element.points[lastClickedPoint === 0 ? 1 : lastClickedPoint - 1];
|
|
9227
9355
|
const singlePointDragged = selectedPointsIndices.length === 1;
|
|
@@ -9418,7 +9546,7 @@ var _LinearElementEditor = class _LinearElementEditor {
|
|
|
9418
9546
|
}
|
|
9419
9547
|
};
|
|
9420
9548
|
}
|
|
9421
|
-
static isSegmentTooShort(element, startPoint, endPoint, index, zoom) {
|
|
9549
|
+
static isSegmentTooShort(element, startPoint, endPoint, index, zoom, elementsMap) {
|
|
9422
9550
|
if (isElbowArrow(element)) {
|
|
9423
9551
|
if (index >= 0 && index < element.points.length) {
|
|
9424
9552
|
return pointDistance(startPoint, endPoint) * zoom.value < _LinearElementEditor.POINT_HANDLE_SIZE / 2;
|
|
@@ -9427,7 +9555,10 @@ var _LinearElementEditor = class _LinearElementEditor {
|
|
|
9427
9555
|
}
|
|
9428
9556
|
let distance2 = pointDistance(startPoint, endPoint);
|
|
9429
9557
|
if (element.points.length > 2 && element.roundness) {
|
|
9430
|
-
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
9558
|
+
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
9559
|
+
element,
|
|
9560
|
+
elementsMap
|
|
9561
|
+
);
|
|
9431
9562
|
invariant(
|
|
9432
9563
|
lines.length === 0 && curves.length > 0,
|
|
9433
9564
|
"Only linears built out of curves are supported"
|
|
@@ -9440,7 +9571,7 @@ var _LinearElementEditor = class _LinearElementEditor {
|
|
|
9440
9571
|
}
|
|
9441
9572
|
return distance2 * zoom.value < _LinearElementEditor.POINT_HANDLE_SIZE * 4;
|
|
9442
9573
|
}
|
|
9443
|
-
static getSegmentMidPoint(element, index) {
|
|
9574
|
+
static getSegmentMidPoint(element, index, elementsMap) {
|
|
9444
9575
|
if (isElbowArrow(element)) {
|
|
9445
9576
|
invariant(
|
|
9446
9577
|
element.points.length >= index,
|
|
@@ -9449,7 +9580,10 @@ var _LinearElementEditor = class _LinearElementEditor {
|
|
|
9449
9580
|
const p = pointCenter(element.points[index - 1], element.points[index]);
|
|
9450
9581
|
return pointFrom(element.x + p[0], element.y + p[1]);
|
|
9451
9582
|
}
|
|
9452
|
-
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
9583
|
+
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
9584
|
+
element,
|
|
9585
|
+
elementsMap
|
|
9586
|
+
);
|
|
9453
9587
|
invariant(
|
|
9454
9588
|
lines.length === 0 && curves.length > 0 || lines.length > 0 && curves.length === 0,
|
|
9455
9589
|
"Only linears built out of either segments or curves are supported"
|
|
@@ -9969,7 +10103,7 @@ var _LinearElementEditor = class _LinearElementEditor {
|
|
|
9969
10103
|
pointerDownState: linearElementEditor.initialState,
|
|
9970
10104
|
selectedPointsIndices: linearElementEditor.selectedPointsIndices
|
|
9971
10105
|
};
|
|
9972
|
-
const
|
|
10106
|
+
const midpoint2 = _LinearElementEditor.createPointAt(
|
|
9973
10107
|
element,
|
|
9974
10108
|
elementsMap,
|
|
9975
10109
|
pointerCoords.x,
|
|
@@ -9978,7 +10112,7 @@ var _LinearElementEditor = class _LinearElementEditor {
|
|
|
9978
10112
|
);
|
|
9979
10113
|
const points = [
|
|
9980
10114
|
...element.points.slice(0, segmentMidpoint.index),
|
|
9981
|
-
|
|
10115
|
+
midpoint2,
|
|
9982
10116
|
...element.points.slice(segmentMidpoint.index)
|
|
9983
10117
|
];
|
|
9984
10118
|
scene.mutateElement(element, { points });
|
|
@@ -10149,7 +10283,8 @@ __publicField(_LinearElementEditor, "getEditorMidPoints", (element, elementsMap,
|
|
|
10149
10283
|
element.points[index],
|
|
10150
10284
|
element.points[index + 1],
|
|
10151
10285
|
index,
|
|
10152
|
-
appState.zoom
|
|
10286
|
+
appState.zoom,
|
|
10287
|
+
elementsMap
|
|
10153
10288
|
)) {
|
|
10154
10289
|
midpoints.push(null);
|
|
10155
10290
|
index++;
|
|
@@ -10157,7 +10292,8 @@ __publicField(_LinearElementEditor, "getEditorMidPoints", (element, elementsMap,
|
|
|
10157
10292
|
}
|
|
10158
10293
|
const segmentMidPoint = _LinearElementEditor.getSegmentMidPoint(
|
|
10159
10294
|
element,
|
|
10160
|
-
index + 1
|
|
10295
|
+
index + 1,
|
|
10296
|
+
elementsMap
|
|
10161
10297
|
);
|
|
10162
10298
|
midpoints.push(segmentMidPoint);
|
|
10163
10299
|
index++;
|
|
@@ -10244,7 +10380,8 @@ __publicField(_LinearElementEditor, "getBoundTextElementPosition", (element, bou
|
|
|
10244
10380
|
const index = element.points.length / 2 - 1;
|
|
10245
10381
|
const midSegmentMidpoint = _LinearElementEditor.getSegmentMidPoint(
|
|
10246
10382
|
element,
|
|
10247
|
-
index + 1
|
|
10383
|
+
index + 1,
|
|
10384
|
+
elementsMap
|
|
10248
10385
|
);
|
|
10249
10386
|
x = midSegmentMidpoint[0] - boundTextElement.width / 2;
|
|
10250
10387
|
y = midSegmentMidpoint[1] - boundTextElement.height / 2;
|
|
@@ -10366,13 +10503,11 @@ var normalizeSelectedPoints = (points) => {
|
|
|
10366
10503
|
var pointDraggingUpdates = (selectedPointsIndices, deltaX, deltaY, scenePointerX, scenePointerY, elementsMap, element, elements, app, angleLocked, altKey, linearElementEditor) => {
|
|
10367
10504
|
const naiveDraggingPoints = new Map(
|
|
10368
10505
|
selectedPointsIndices.map((pointIndex) => {
|
|
10506
|
+
const point = element.points[pointIndex] ?? element.points.at(-1);
|
|
10369
10507
|
return [
|
|
10370
10508
|
pointIndex,
|
|
10371
10509
|
{
|
|
10372
|
-
point: pointFrom(
|
|
10373
|
-
element.points[pointIndex][0] + deltaX,
|
|
10374
|
-
element.points[pointIndex][1] + deltaY
|
|
10375
|
-
),
|
|
10510
|
+
point: pointFrom(point[0] + deltaX, point[1] + deltaY),
|
|
10376
10511
|
isDragging: true
|
|
10377
10512
|
}
|
|
10378
10513
|
];
|
|
@@ -10559,7 +10694,7 @@ var pointDraggingUpdates = (selectedPointsIndices, deltaX, deltaY, scenePointerX
|
|
|
10559
10694
|
nextArrow.endBinding.elementId
|
|
10560
10695
|
) : null;
|
|
10561
10696
|
const endLocalPoint = startIsDraggingOverEndElement ? nextArrow.points[nextArrow.points.length - 1] : endIsDraggingOverStartElement && app.state.bindMode !== "inside" && getFeatureFlag("COMPLEX_BINDINGS") ? nextArrow.points[0] : endBindable ? updateBoundPoint(
|
|
10562
|
-
|
|
10697
|
+
nextArrow,
|
|
10563
10698
|
"endBinding",
|
|
10564
10699
|
nextArrow.endBinding,
|
|
10565
10700
|
endBindable,
|
|
@@ -10571,7 +10706,7 @@ var pointDraggingUpdates = (selectedPointsIndices, deltaX, deltaY, scenePointerX
|
|
|
10571
10706
|
nextArrow.startBinding.elementId
|
|
10572
10707
|
) : null;
|
|
10573
10708
|
const startLocalPoint = endIsDraggingOverStartElement && getFeatureFlag("COMPLEX_BINDINGS") ? nextArrow.points[0] : startIsDraggingOverEndElement && app.state.bindMode !== "inside" && getFeatureFlag("COMPLEX_BINDINGS") ? endLocalPoint : startBindable ? updateBoundPoint(
|
|
10574
|
-
|
|
10709
|
+
nextArrow,
|
|
10575
10710
|
"startBinding",
|
|
10576
10711
|
nextArrow.startBinding,
|
|
10577
10712
|
startBindable,
|
|
@@ -10639,131 +10774,6 @@ function doLineSegmentsIntersect(a, b) {
|
|
|
10639
10774
|
return doBBoxesIntersect(getBBox(a), getBBox(b)) && isLineSegmentTouchingOrCrossingLine(a, b) && isLineSegmentTouchingOrCrossingLine(b, a);
|
|
10640
10775
|
}
|
|
10641
10776
|
|
|
10642
|
-
// ../utils/src/withinBounds.ts
|
|
10643
|
-
var getNonLinearElementRelativePoints = (element) => {
|
|
10644
|
-
if (element.type === "diamond") {
|
|
10645
|
-
return [
|
|
10646
|
-
pointFrom(element.width / 2, 0),
|
|
10647
|
-
pointFrom(element.width, element.height / 2),
|
|
10648
|
-
pointFrom(element.width / 2, element.height),
|
|
10649
|
-
pointFrom(0, element.height / 2)
|
|
10650
|
-
];
|
|
10651
|
-
}
|
|
10652
|
-
return [
|
|
10653
|
-
pointFrom(0, 0),
|
|
10654
|
-
pointFrom(0 + element.width, 0),
|
|
10655
|
-
pointFrom(0 + element.width, element.height),
|
|
10656
|
-
pointFrom(0, element.height)
|
|
10657
|
-
];
|
|
10658
|
-
};
|
|
10659
|
-
var getElementRelativePoints = (element) => {
|
|
10660
|
-
if (isLinearElement(element) || isFreeDrawElement(element)) {
|
|
10661
|
-
return element.points;
|
|
10662
|
-
}
|
|
10663
|
-
return getNonLinearElementRelativePoints(element);
|
|
10664
|
-
};
|
|
10665
|
-
var getMinMaxPoints = (points) => {
|
|
10666
|
-
const ret = points.reduce(
|
|
10667
|
-
(limits, [x, y]) => {
|
|
10668
|
-
limits.minY = Math.min(limits.minY, y);
|
|
10669
|
-
limits.minX = Math.min(limits.minX, x);
|
|
10670
|
-
limits.maxX = Math.max(limits.maxX, x);
|
|
10671
|
-
limits.maxY = Math.max(limits.maxY, y);
|
|
10672
|
-
return limits;
|
|
10673
|
-
},
|
|
10674
|
-
{
|
|
10675
|
-
minX: Infinity,
|
|
10676
|
-
minY: Infinity,
|
|
10677
|
-
maxX: -Infinity,
|
|
10678
|
-
maxY: -Infinity,
|
|
10679
|
-
cx: 0,
|
|
10680
|
-
cy: 0
|
|
10681
|
-
}
|
|
10682
|
-
);
|
|
10683
|
-
ret.cx = (ret.maxX + ret.minX) / 2;
|
|
10684
|
-
ret.cy = (ret.maxY + ret.minY) / 2;
|
|
10685
|
-
return ret;
|
|
10686
|
-
};
|
|
10687
|
-
var getRotatedBBox = (element) => {
|
|
10688
|
-
const points = getElementRelativePoints(element);
|
|
10689
|
-
const { cx, cy } = getMinMaxPoints(points);
|
|
10690
|
-
const centerPoint = pointFrom(cx, cy);
|
|
10691
|
-
const rotatedPoints = points.map(
|
|
10692
|
-
(p) => pointRotateRads(p, centerPoint, element.angle)
|
|
10693
|
-
);
|
|
10694
|
-
const { minX, minY, maxX, maxY } = getMinMaxPoints(rotatedPoints);
|
|
10695
|
-
return [
|
|
10696
|
-
minX + element.x,
|
|
10697
|
-
minY + element.y,
|
|
10698
|
-
maxX + element.x,
|
|
10699
|
-
maxY + element.y
|
|
10700
|
-
];
|
|
10701
|
-
};
|
|
10702
|
-
var isElementInsideBBox = (element, bbox, eitherDirection = false) => {
|
|
10703
|
-
const elementBBox = getRotatedBBox(element);
|
|
10704
|
-
const elementInsideBbox = bbox[0] <= elementBBox[0] && bbox[2] >= elementBBox[2] && bbox[1] <= elementBBox[1] && bbox[3] >= elementBBox[3];
|
|
10705
|
-
if (!eitherDirection) {
|
|
10706
|
-
return elementInsideBbox;
|
|
10707
|
-
}
|
|
10708
|
-
if (elementInsideBbox) {
|
|
10709
|
-
return true;
|
|
10710
|
-
}
|
|
10711
|
-
return elementBBox[0] <= bbox[0] && elementBBox[2] >= bbox[2] && elementBBox[1] <= bbox[1] && elementBBox[3] >= bbox[3];
|
|
10712
|
-
};
|
|
10713
|
-
var elementPartiallyOverlapsWithOrContainsBBox = (element, bbox) => {
|
|
10714
|
-
const elementBBox = getRotatedBBox(element);
|
|
10715
|
-
return (rangeIncludesValue(elementBBox[0], rangeInclusive(bbox[0], bbox[2])) || rangeIncludesValue(
|
|
10716
|
-
bbox[0],
|
|
10717
|
-
rangeInclusive(elementBBox[0], elementBBox[2])
|
|
10718
|
-
)) && (rangeIncludesValue(elementBBox[1], rangeInclusive(bbox[1], bbox[3])) || rangeIncludesValue(
|
|
10719
|
-
bbox[1],
|
|
10720
|
-
rangeInclusive(elementBBox[1], elementBBox[3])
|
|
10721
|
-
));
|
|
10722
|
-
};
|
|
10723
|
-
var elementsOverlappingBBox = ({
|
|
10724
|
-
elements,
|
|
10725
|
-
bounds,
|
|
10726
|
-
type,
|
|
10727
|
-
errorMargin = 0
|
|
10728
|
-
}) => {
|
|
10729
|
-
if (isExcalidrawElement(bounds)) {
|
|
10730
|
-
bounds = getElementBounds(bounds, arrayToMap(elements));
|
|
10731
|
-
}
|
|
10732
|
-
const adjustedBBox = [
|
|
10733
|
-
bounds[0] - errorMargin,
|
|
10734
|
-
bounds[1] - errorMargin,
|
|
10735
|
-
bounds[2] + errorMargin,
|
|
10736
|
-
bounds[3] + errorMargin
|
|
10737
|
-
];
|
|
10738
|
-
const includedElementSet = /* @__PURE__ */ new Set();
|
|
10739
|
-
for (const element of elements) {
|
|
10740
|
-
if (includedElementSet.has(element.id)) {
|
|
10741
|
-
continue;
|
|
10742
|
-
}
|
|
10743
|
-
const isOverlaping = type === "overlap" ? elementPartiallyOverlapsWithOrContainsBBox(element, adjustedBBox) : type === "inside" ? isElementInsideBBox(element, adjustedBBox) : isElementInsideBBox(element, adjustedBBox, true);
|
|
10744
|
-
if (isOverlaping) {
|
|
10745
|
-
includedElementSet.add(element.id);
|
|
10746
|
-
if (element.boundElements) {
|
|
10747
|
-
for (const boundElement of element.boundElements) {
|
|
10748
|
-
includedElementSet.add(boundElement.id);
|
|
10749
|
-
}
|
|
10750
|
-
}
|
|
10751
|
-
if (isTextElement(element) && element.containerId) {
|
|
10752
|
-
includedElementSet.add(element.containerId);
|
|
10753
|
-
}
|
|
10754
|
-
if (isArrowElement(element)) {
|
|
10755
|
-
if (element.startBinding) {
|
|
10756
|
-
includedElementSet.add(element.startBinding.elementId);
|
|
10757
|
-
}
|
|
10758
|
-
if (element.endBinding) {
|
|
10759
|
-
includedElementSet.add(element.endBinding?.elementId);
|
|
10760
|
-
}
|
|
10761
|
-
}
|
|
10762
|
-
}
|
|
10763
|
-
}
|
|
10764
|
-
return elements.filter((element) => includedElementSet.has(element.id));
|
|
10765
|
-
};
|
|
10766
|
-
|
|
10767
10777
|
// ../element/src/groups.ts
|
|
10768
10778
|
var selectGroup = (groupId, appState, elements) => {
|
|
10769
10779
|
const elementsInGroup = elements.reduce(
|
|
@@ -11037,13 +11047,8 @@ var getSelectedElementsByGroup = (selectedElements, elementsMap, appState) => {
|
|
|
11037
11047
|
};
|
|
11038
11048
|
|
|
11039
11049
|
// ../element/src/selection.ts
|
|
11040
|
-
var
|
|
11041
|
-
|
|
11042
|
-
selectedElements.forEach((element) => {
|
|
11043
|
-
if (isFrameLikeElement(element)) {
|
|
11044
|
-
framesInSelection.add(element.id);
|
|
11045
|
-
}
|
|
11046
|
-
});
|
|
11050
|
+
var shouldIgnoreElementFromSelection = (element) => element.locked || isBoundToContainer(element);
|
|
11051
|
+
var excludeElementsFromFrames = (selectedElements, framesInSelection) => {
|
|
11047
11052
|
return selectedElements.filter((element) => {
|
|
11048
11053
|
if (element.frameId && framesInSelection.has(element.frameId)) {
|
|
11049
11054
|
return false;
|
|
@@ -11051,90 +11056,273 @@ var excludeElementsInFramesFromSelection = (selectedElements) => {
|
|
|
11051
11056
|
return true;
|
|
11052
11057
|
});
|
|
11053
11058
|
};
|
|
11054
|
-
var
|
|
11055
|
-
const
|
|
11056
|
-
|
|
11057
|
-
|
|
11058
|
-
element
|
|
11059
|
-
elementsMap
|
|
11060
|
-
);
|
|
11061
|
-
const containingFrame = getContainingFrame(element, elementsMap);
|
|
11062
|
-
if (containingFrame) {
|
|
11063
|
-
const [fx1, fy1, fx2, fy2] = getElementBounds(
|
|
11064
|
-
containingFrame,
|
|
11065
|
-
elementsMap
|
|
11066
|
-
);
|
|
11067
|
-
elementX1 = Math.max(fx1, elementX1);
|
|
11068
|
-
elementY1 = Math.max(fy1, elementY1);
|
|
11069
|
-
elementX2 = Math.min(fx2, elementX2);
|
|
11070
|
-
elementY2 = Math.min(fy2, elementY2);
|
|
11059
|
+
var excludeElementsInFramesFromSelection = (selectedElements) => {
|
|
11060
|
+
const framesInSelection = /* @__PURE__ */ new Set();
|
|
11061
|
+
selectedElements.forEach((element) => {
|
|
11062
|
+
if (isFrameLikeElement(element)) {
|
|
11063
|
+
framesInSelection.add(element.id);
|
|
11071
11064
|
}
|
|
11072
|
-
return element.locked === false && element.type !== "selection" && !isBoundToContainer(element) && selectionX1 <= elementX1 && selectionY1 <= elementY1 && selectionX2 >= elementX2 && selectionY2 >= elementY2;
|
|
11073
11065
|
});
|
|
11074
|
-
|
|
11075
|
-
|
|
11076
|
-
|
|
11077
|
-
|
|
11078
|
-
|
|
11066
|
+
return excludeElementsFromFrames(selectedElements, framesInSelection);
|
|
11067
|
+
};
|
|
11068
|
+
var getElementsWithinSelection = (elements, selection, elementsMap, excludeElementsInFrames = true, boxSelectionMode = "contain") => {
|
|
11069
|
+
const [selectionStartX, selectionStartY, selectionEndX, selectionEndY] = getElementAbsoluteCoords(selection, elementsMap);
|
|
11070
|
+
const selectionX1 = Math.min(selectionStartX, selectionEndX);
|
|
11071
|
+
const selectionY1 = Math.min(selectionStartY, selectionEndY);
|
|
11072
|
+
const selectionX2 = Math.max(selectionStartX, selectionEndX);
|
|
11073
|
+
const selectionY2 = Math.max(selectionStartY, selectionEndY);
|
|
11074
|
+
const selectionBounds = [
|
|
11075
|
+
selectionX1,
|
|
11076
|
+
selectionY1,
|
|
11077
|
+
selectionX2,
|
|
11078
|
+
selectionY2
|
|
11079
|
+
];
|
|
11080
|
+
const selectionEdges = [
|
|
11081
|
+
lineSegment(
|
|
11082
|
+
pointFrom(selectionX1, selectionY1),
|
|
11083
|
+
pointFrom(selectionX2, selectionY1)
|
|
11084
|
+
),
|
|
11085
|
+
lineSegment(
|
|
11086
|
+
pointFrom(selectionX2, selectionY1),
|
|
11087
|
+
pointFrom(selectionX2, selectionY2)
|
|
11088
|
+
),
|
|
11089
|
+
lineSegment(
|
|
11090
|
+
pointFrom(selectionX2, selectionY2),
|
|
11091
|
+
pointFrom(selectionX1, selectionY2)
|
|
11092
|
+
),
|
|
11093
|
+
lineSegment(
|
|
11094
|
+
pointFrom(selectionX1, selectionY2),
|
|
11095
|
+
pointFrom(selectionX1, selectionY1)
|
|
11096
|
+
)
|
|
11097
|
+
];
|
|
11098
|
+
const framesInSelection = excludeElementsInFrames ? /* @__PURE__ */ new Set() : null;
|
|
11099
|
+
const groups = {};
|
|
11100
|
+
const elementsInSelection = /* @__PURE__ */ new Set();
|
|
11101
|
+
for (const element of elements) {
|
|
11102
|
+
if (shouldIgnoreElementFromSelection(element)) {
|
|
11103
|
+
continue;
|
|
11079
11104
|
}
|
|
11080
|
-
|
|
11081
|
-
|
|
11082
|
-
|
|
11083
|
-
|
|
11084
|
-
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
|
|
11088
|
-
|
|
11089
|
-
|
|
11090
|
-
|
|
11091
|
-
|
|
11092
|
-
|
|
11093
|
-
|
|
11094
|
-
|
|
11095
|
-
|
|
11096
|
-
|
|
11097
|
-
|
|
11098
|
-
}
|
|
11099
|
-
|
|
11100
|
-
|
|
11101
|
-
|
|
11102
|
-
|
|
11103
|
-
|
|
11104
|
-
|
|
11105
|
-
|
|
11105
|
+
const groupId = element.groupIds.at(-1);
|
|
11106
|
+
if (groupId) {
|
|
11107
|
+
if (!groups[groupId]) {
|
|
11108
|
+
groups[groupId] = [];
|
|
11109
|
+
}
|
|
11110
|
+
groups[groupId].push(element);
|
|
11111
|
+
}
|
|
11112
|
+
const strokeWidth = element.strokeWidth;
|
|
11113
|
+
let labelAABB = null;
|
|
11114
|
+
let elementAABB = getElementBounds(element, elementsMap);
|
|
11115
|
+
elementAABB = [
|
|
11116
|
+
elementAABB[0] - strokeWidth / 2,
|
|
11117
|
+
elementAABB[1] - strokeWidth / 2,
|
|
11118
|
+
elementAABB[2] + strokeWidth / 2,
|
|
11119
|
+
elementAABB[3] + strokeWidth / 2
|
|
11120
|
+
];
|
|
11121
|
+
const boundTextElement = isArrowElement(element) && getBoundTextElement(element, elementsMap);
|
|
11122
|
+
if (boundTextElement) {
|
|
11123
|
+
const { x, y } = LinearElementEditor.getBoundTextElementPosition(
|
|
11124
|
+
element,
|
|
11125
|
+
boundTextElement,
|
|
11126
|
+
elementsMap
|
|
11127
|
+
);
|
|
11128
|
+
labelAABB = [
|
|
11129
|
+
x,
|
|
11130
|
+
y,
|
|
11131
|
+
x + boundTextElement.width,
|
|
11132
|
+
y + boundTextElement.height
|
|
11133
|
+
];
|
|
11106
11134
|
}
|
|
11107
|
-
|
|
11108
|
-
|
|
11109
|
-
|
|
11110
|
-
|
|
11111
|
-
|
|
11112
|
-
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
|
|
11116
|
-
|
|
11117
|
-
|
|
11118
|
-
|
|
11119
|
-
|
|
11120
|
-
|
|
11121
|
-
|
|
11122
|
-
|
|
11123
|
-
|
|
11124
|
-
|
|
11125
|
-
|
|
11126
|
-
|
|
11127
|
-
|
|
11135
|
+
const associatedFrame = getContainingFrame(element, elementsMap);
|
|
11136
|
+
if (associatedFrame && elementOverlapsWithFrame(element, associatedFrame, elementsMap)) {
|
|
11137
|
+
const frameAABB = getElementBounds(associatedFrame, elementsMap);
|
|
11138
|
+
elementAABB = [
|
|
11139
|
+
Math.max(elementAABB[0], frameAABB[0]),
|
|
11140
|
+
Math.max(elementAABB[1], frameAABB[1]),
|
|
11141
|
+
Math.min(elementAABB[2], frameAABB[2]),
|
|
11142
|
+
Math.min(elementAABB[3], frameAABB[3])
|
|
11143
|
+
];
|
|
11144
|
+
labelAABB = labelAABB ? [
|
|
11145
|
+
Math.max(labelAABB[0], frameAABB[0]),
|
|
11146
|
+
Math.max(labelAABB[1], frameAABB[1]),
|
|
11147
|
+
Math.min(labelAABB[2], frameAABB[2]),
|
|
11148
|
+
Math.min(labelAABB[3], frameAABB[3])
|
|
11149
|
+
] : null;
|
|
11150
|
+
}
|
|
11151
|
+
const commonAABB2 = labelAABB ? [
|
|
11152
|
+
Math.min(labelAABB[0], elementAABB[0]),
|
|
11153
|
+
Math.min(labelAABB[1], elementAABB[1]),
|
|
11154
|
+
Math.max(labelAABB[2], elementAABB[2]),
|
|
11155
|
+
Math.max(labelAABB[3], elementAABB[3])
|
|
11156
|
+
] : elementAABB;
|
|
11157
|
+
if (boundsContainBounds(selectionBounds, commonAABB2)) {
|
|
11158
|
+
if (framesInSelection && isFrameLikeElement(element)) {
|
|
11159
|
+
framesInSelection.add(element.id);
|
|
11160
|
+
}
|
|
11161
|
+
elementsInSelection.add(element);
|
|
11128
11162
|
continue;
|
|
11129
11163
|
}
|
|
11130
|
-
if (
|
|
11131
|
-
|
|
11132
|
-
addedElements.add(element.id);
|
|
11164
|
+
if (boxSelectionMode === "overlap" && labelAABB && doBoundsIntersect(selectionBounds, labelAABB)) {
|
|
11165
|
+
elementsInSelection.add(element);
|
|
11133
11166
|
continue;
|
|
11134
11167
|
}
|
|
11135
|
-
|
|
11136
|
-
|
|
11137
|
-
|
|
11168
|
+
if (boxSelectionMode === "overlap" && doBoundsIntersect(selectionBounds, elementAABB)) {
|
|
11169
|
+
let hasIntersection = false;
|
|
11170
|
+
if (isLinearElement(element) || isFreeDrawElement(element)) {
|
|
11171
|
+
const center = elementCenterPoint(element, elementsMap);
|
|
11172
|
+
hasIntersection = element.points.some((point) => {
|
|
11173
|
+
const rotatedPoint = pointRotateRads(
|
|
11174
|
+
pointFrom(element.x + point[0], element.y + point[1]),
|
|
11175
|
+
center,
|
|
11176
|
+
element.angle
|
|
11177
|
+
);
|
|
11178
|
+
return pointInsideBounds(rotatedPoint, selectionBounds);
|
|
11179
|
+
});
|
|
11180
|
+
} else {
|
|
11181
|
+
const nonRotatedElementBounds = getElementBounds(
|
|
11182
|
+
element,
|
|
11183
|
+
elementsMap,
|
|
11184
|
+
true
|
|
11185
|
+
);
|
|
11186
|
+
const center = elementCenterPoint(element, elementsMap);
|
|
11187
|
+
hasIntersection = [
|
|
11188
|
+
pointRotateRads(
|
|
11189
|
+
pointFrom(
|
|
11190
|
+
(nonRotatedElementBounds[0] + nonRotatedElementBounds[2]) / 2,
|
|
11191
|
+
nonRotatedElementBounds[1]
|
|
11192
|
+
),
|
|
11193
|
+
center,
|
|
11194
|
+
element.angle
|
|
11195
|
+
),
|
|
11196
|
+
pointRotateRads(
|
|
11197
|
+
pointFrom(
|
|
11198
|
+
nonRotatedElementBounds[2],
|
|
11199
|
+
(nonRotatedElementBounds[1] + nonRotatedElementBounds[3]) / 2
|
|
11200
|
+
),
|
|
11201
|
+
center,
|
|
11202
|
+
element.angle
|
|
11203
|
+
),
|
|
11204
|
+
pointRotateRads(
|
|
11205
|
+
pointFrom(
|
|
11206
|
+
(nonRotatedElementBounds[0] + nonRotatedElementBounds[2]) / 2,
|
|
11207
|
+
nonRotatedElementBounds[3]
|
|
11208
|
+
),
|
|
11209
|
+
center,
|
|
11210
|
+
element.angle
|
|
11211
|
+
),
|
|
11212
|
+
pointRotateRads(
|
|
11213
|
+
pointFrom(
|
|
11214
|
+
nonRotatedElementBounds[0],
|
|
11215
|
+
(nonRotatedElementBounds[1] + nonRotatedElementBounds[3]) / 2
|
|
11216
|
+
),
|
|
11217
|
+
center,
|
|
11218
|
+
element.angle
|
|
11219
|
+
)
|
|
11220
|
+
].some((point) => {
|
|
11221
|
+
return pointInsideBounds(
|
|
11222
|
+
pointRotateRads(point, center, element.angle),
|
|
11223
|
+
selectionBounds
|
|
11224
|
+
);
|
|
11225
|
+
});
|
|
11226
|
+
}
|
|
11227
|
+
if (!hasIntersection) {
|
|
11228
|
+
hasIntersection = selectionEdges.some(
|
|
11229
|
+
(selectionEdge) => intersectElementWithLineSegment(
|
|
11230
|
+
element,
|
|
11231
|
+
elementsMap,
|
|
11232
|
+
selectionEdge,
|
|
11233
|
+
strokeWidth / 2,
|
|
11234
|
+
true
|
|
11235
|
+
// Stop at first hit for better performance
|
|
11236
|
+
).length > 0
|
|
11237
|
+
);
|
|
11238
|
+
}
|
|
11239
|
+
if (hasIntersection) {
|
|
11240
|
+
if (framesInSelection && isFrameLikeElement(element)) {
|
|
11241
|
+
framesInSelection.add(element.id);
|
|
11242
|
+
}
|
|
11243
|
+
elementsInSelection.add(element);
|
|
11244
|
+
continue;
|
|
11245
|
+
}
|
|
11246
|
+
}
|
|
11247
|
+
}
|
|
11248
|
+
if (framesInSelection) {
|
|
11249
|
+
elementsInSelection.forEach((element) => {
|
|
11250
|
+
if (element.frameId && framesInSelection.has(element.frameId)) {
|
|
11251
|
+
elementsInSelection.delete(element);
|
|
11252
|
+
}
|
|
11253
|
+
});
|
|
11254
|
+
}
|
|
11255
|
+
if (boxSelectionMode === "overlap") {
|
|
11256
|
+
Array.from(elementsInSelection).forEach((element) => {
|
|
11257
|
+
const groupId = element.groupIds.at(-1);
|
|
11258
|
+
const group = groupId ? groups[groupId] : null;
|
|
11259
|
+
group?.forEach((groupElement) => elementsInSelection.add(groupElement));
|
|
11260
|
+
});
|
|
11261
|
+
} else if (boxSelectionMode === "contain") {
|
|
11262
|
+
elementsInSelection.forEach((element) => {
|
|
11263
|
+
const groupId = element.groupIds.at(-1);
|
|
11264
|
+
const group = groupId ? groups[groupId] : null;
|
|
11265
|
+
if (group && !group.every((groupElement) => elementsInSelection.has(groupElement))) {
|
|
11266
|
+
elementsInSelection.delete(element);
|
|
11267
|
+
}
|
|
11268
|
+
});
|
|
11269
|
+
}
|
|
11270
|
+
return elements.filter((element) => elementsInSelection.has(element));
|
|
11271
|
+
};
|
|
11272
|
+
var getVisibleAndNonSelectedElements = (elements, selectedElements, appState, elementsMap) => {
|
|
11273
|
+
const selectedElementsSet = new Set(
|
|
11274
|
+
selectedElements.map((element) => element.id)
|
|
11275
|
+
);
|
|
11276
|
+
return elements.filter((element) => {
|
|
11277
|
+
const isVisible = isElementInViewport(
|
|
11278
|
+
element,
|
|
11279
|
+
appState.width,
|
|
11280
|
+
appState.height,
|
|
11281
|
+
appState,
|
|
11282
|
+
elementsMap
|
|
11283
|
+
);
|
|
11284
|
+
return !selectedElementsSet.has(element.id) && isVisible;
|
|
11285
|
+
});
|
|
11286
|
+
};
|
|
11287
|
+
var isSomeElementSelected = function() {
|
|
11288
|
+
let lastElements = null;
|
|
11289
|
+
let lastSelectedElementIds = null;
|
|
11290
|
+
let isSelected = null;
|
|
11291
|
+
const ret = (elements, appState) => {
|
|
11292
|
+
if (isSelected != null && elements === lastElements && appState.selectedElementIds === lastSelectedElementIds) {
|
|
11293
|
+
return isSelected;
|
|
11294
|
+
}
|
|
11295
|
+
isSelected = elements.some(
|
|
11296
|
+
(element) => appState.selectedElementIds[element.id]
|
|
11297
|
+
);
|
|
11298
|
+
lastElements = elements;
|
|
11299
|
+
lastSelectedElementIds = appState.selectedElementIds;
|
|
11300
|
+
return isSelected;
|
|
11301
|
+
};
|
|
11302
|
+
ret.clearCache = () => {
|
|
11303
|
+
lastElements = null;
|
|
11304
|
+
lastSelectedElementIds = null;
|
|
11305
|
+
isSelected = null;
|
|
11306
|
+
};
|
|
11307
|
+
return ret;
|
|
11308
|
+
}();
|
|
11309
|
+
var getSelectedElements = (elements, appState, opts) => {
|
|
11310
|
+
const addedElements = /* @__PURE__ */ new Set();
|
|
11311
|
+
const selectedElements = [];
|
|
11312
|
+
for (const element of elements.values()) {
|
|
11313
|
+
if (appState.selectedElementIds[element.id]) {
|
|
11314
|
+
selectedElements.push(element);
|
|
11315
|
+
addedElements.add(element.id);
|
|
11316
|
+
continue;
|
|
11317
|
+
}
|
|
11318
|
+
if (opts?.includeBoundTextElement && isBoundToContainer(element) && appState.selectedElementIds[element?.containerId]) {
|
|
11319
|
+
selectedElements.push(element);
|
|
11320
|
+
addedElements.add(element.id);
|
|
11321
|
+
continue;
|
|
11322
|
+
}
|
|
11323
|
+
}
|
|
11324
|
+
if (opts?.includeElementsInFrames) {
|
|
11325
|
+
const elementsToInclude = [];
|
|
11138
11326
|
selectedElements.forEach((element) => {
|
|
11139
11327
|
if (isFrameLikeElement(element)) {
|
|
11140
11328
|
getFrameChildren(elements, element.id).forEach(
|
|
@@ -11196,486 +11384,984 @@ var getActiveTextElement = (selectedElements, appState) => {
|
|
|
11196
11384
|
return activeTextElement || null;
|
|
11197
11385
|
};
|
|
11198
11386
|
|
|
11199
|
-
// ../
|
|
11200
|
-
var
|
|
11201
|
-
|
|
11202
|
-
|
|
11203
|
-
|
|
11204
|
-
|
|
11205
|
-
|
|
11206
|
-
|
|
11207
|
-
|
|
11208
|
-
|
|
11209
|
-
|
|
11210
|
-
|
|
11211
|
-
|
|
11387
|
+
// ../fractional-indexing/src/index.ts
|
|
11388
|
+
var BASE_62_DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
11389
|
+
function midpoint(a, b, digits) {
|
|
11390
|
+
const zero = digits[0];
|
|
11391
|
+
if (b != null && a >= b) {
|
|
11392
|
+
throw new Error(`${a} >= ${b}`);
|
|
11393
|
+
}
|
|
11394
|
+
if (a.slice(-1) === zero || b && b.slice(-1) === zero) {
|
|
11395
|
+
throw new Error("trailing zero");
|
|
11396
|
+
}
|
|
11397
|
+
if (b) {
|
|
11398
|
+
let n = 0;
|
|
11399
|
+
while ((a[n] || zero) === b[n]) {
|
|
11400
|
+
n++;
|
|
11401
|
+
}
|
|
11402
|
+
if (n > 0) {
|
|
11403
|
+
return b.slice(0, n) + midpoint(a.slice(n), b.slice(n), digits);
|
|
11212
11404
|
}
|
|
11213
11405
|
}
|
|
11214
|
-
|
|
11215
|
-
|
|
11216
|
-
|
|
11217
|
-
|
|
11218
|
-
|
|
11219
|
-
|
|
11220
|
-
|
|
11221
|
-
)
|
|
11222
|
-
|
|
11223
|
-
return
|
|
11406
|
+
const digitA = a ? digits.indexOf(a[0]) : 0;
|
|
11407
|
+
const digitB = b != null ? digits.indexOf(b[0]) : digits.length;
|
|
11408
|
+
if (digitB - digitA > 1) {
|
|
11409
|
+
const midDigit = Math.round(0.5 * (digitA + digitB));
|
|
11410
|
+
return digits[midDigit];
|
|
11411
|
+
}
|
|
11412
|
+
if (b && b.length > 1) {
|
|
11413
|
+
return b.slice(0, 1);
|
|
11414
|
+
}
|
|
11415
|
+
return digits[digitA] + midpoint(a.slice(1), null, digits);
|
|
11224
11416
|
}
|
|
11225
|
-
|
|
11226
|
-
|
|
11227
|
-
)
|
|
11228
|
-
|
|
11229
|
-
|
|
11230
|
-
|
|
11231
|
-
|
|
11232
|
-
(
|
|
11233
|
-
)
|
|
11234
|
-
|
|
11235
|
-
|
|
11236
|
-
|
|
11237
|
-
|
|
11238
|
-
|
|
11239
|
-
);
|
|
11240
|
-
|
|
11241
|
-
|
|
11242
|
-
}
|
|
11243
|
-
|
|
11244
|
-
|
|
11245
|
-
|
|
11246
|
-
|
|
11247
|
-
|
|
11248
|
-
|
|
11249
|
-
|
|
11250
|
-
|
|
11251
|
-
|
|
11252
|
-
)
|
|
11253
|
-
};
|
|
11254
|
-
|
|
11255
|
-
|
|
11256
|
-
|
|
11257
|
-
|
|
11258
|
-
|
|
11259
|
-
|
|
11417
|
+
function validateInteger(int) {
|
|
11418
|
+
if (int.length !== getIntegerLength(int[0])) {
|
|
11419
|
+
throw new Error(`invalid integer part of order key: ${int}`);
|
|
11420
|
+
}
|
|
11421
|
+
}
|
|
11422
|
+
function getIntegerLength(head) {
|
|
11423
|
+
if (head >= "a" && head <= "z") {
|
|
11424
|
+
return head.charCodeAt(0) - "a".charCodeAt(0) + 2;
|
|
11425
|
+
} else if (head >= "A" && head <= "Z") {
|
|
11426
|
+
return "Z".charCodeAt(0) - head.charCodeAt(0) + 2;
|
|
11427
|
+
}
|
|
11428
|
+
throw new Error(`invalid order key head: ${head}`);
|
|
11429
|
+
}
|
|
11430
|
+
function getIntegerPart(key) {
|
|
11431
|
+
const integerPartLength = getIntegerLength(key[0]);
|
|
11432
|
+
if (integerPartLength > key.length) {
|
|
11433
|
+
throw new Error(`invalid order key: ${key}`);
|
|
11434
|
+
}
|
|
11435
|
+
return key.slice(0, integerPartLength);
|
|
11436
|
+
}
|
|
11437
|
+
function validateOrderKey(key, digits = BASE_62_DIGITS) {
|
|
11438
|
+
const validChars = key.split("").every((char) => digits.includes(char));
|
|
11439
|
+
if (key === `A${digits[0].repeat(26)}` || !validChars) {
|
|
11440
|
+
throw new Error(`invalid order key: ${key}`);
|
|
11441
|
+
}
|
|
11442
|
+
const i = getIntegerPart(key);
|
|
11443
|
+
const f = key.slice(i.length);
|
|
11444
|
+
if (f.slice(-1) === digits[0]) {
|
|
11445
|
+
throw new Error(`invalid order key: ${key}`);
|
|
11446
|
+
}
|
|
11447
|
+
}
|
|
11448
|
+
function incrementInteger(x, digits) {
|
|
11449
|
+
validateInteger(x);
|
|
11450
|
+
const [head, ...digs] = x.split("");
|
|
11451
|
+
let carry = true;
|
|
11452
|
+
for (let i = digs.length - 1; carry && i >= 0; i--) {
|
|
11453
|
+
const d = digits.indexOf(digs[i]) + 1;
|
|
11454
|
+
if (d === digits.length) {
|
|
11455
|
+
digs[i] = digits[0];
|
|
11456
|
+
} else {
|
|
11457
|
+
digs[i] = digits[d];
|
|
11458
|
+
carry = false;
|
|
11260
11459
|
}
|
|
11261
11460
|
}
|
|
11262
|
-
|
|
11263
|
-
|
|
11264
|
-
|
|
11265
|
-
|
|
11266
|
-
|
|
11267
|
-
|
|
11268
|
-
frameChildren.push(element);
|
|
11461
|
+
if (carry) {
|
|
11462
|
+
if (head === "Z") {
|
|
11463
|
+
return `a${digits[0]}`;
|
|
11464
|
+
}
|
|
11465
|
+
if (head === "z") {
|
|
11466
|
+
return null;
|
|
11269
11467
|
}
|
|
11468
|
+
const h = String.fromCharCode(head.charCodeAt(0) + 1);
|
|
11469
|
+
if (h > "a") {
|
|
11470
|
+
digs.push(digits[0]);
|
|
11471
|
+
} else {
|
|
11472
|
+
digs.pop();
|
|
11473
|
+
}
|
|
11474
|
+
return h + digs.join("");
|
|
11270
11475
|
}
|
|
11271
|
-
return
|
|
11272
|
-
}
|
|
11273
|
-
|
|
11274
|
-
|
|
11275
|
-
|
|
11276
|
-
|
|
11277
|
-
|
|
11278
|
-
|
|
11279
|
-
|
|
11280
|
-
|
|
11281
|
-
|
|
11282
|
-
|
|
11283
|
-
|
|
11284
|
-
var getElementsInResizingFrame = (allElements, frame, appState, elementsMap) => {
|
|
11285
|
-
const prevElementsInFrame = getFrameChildren(allElements, frame.id);
|
|
11286
|
-
const nextElementsInFrame = new Set(prevElementsInFrame);
|
|
11287
|
-
const elementsCompletelyInFrame = /* @__PURE__ */ new Set([
|
|
11288
|
-
...getElementsCompletelyInFrame(allElements, frame, elementsMap),
|
|
11289
|
-
...prevElementsInFrame.filter(
|
|
11290
|
-
(element) => isElementContainingFrame(element, frame, elementsMap)
|
|
11291
|
-
)
|
|
11292
|
-
]);
|
|
11293
|
-
const elementsNotCompletelyInFrame = prevElementsInFrame.filter(
|
|
11294
|
-
(element) => !elementsCompletelyInFrame.has(element)
|
|
11295
|
-
);
|
|
11296
|
-
const groupsToKeep = new Set(
|
|
11297
|
-
Array.from(elementsCompletelyInFrame).flatMap(
|
|
11298
|
-
(element) => element.groupIds
|
|
11299
|
-
)
|
|
11300
|
-
);
|
|
11301
|
-
for (const element of elementsNotCompletelyInFrame) {
|
|
11302
|
-
if (!isElementIntersectingFrame(element, frame, elementsMap)) {
|
|
11303
|
-
if (element.groupIds.length === 0) {
|
|
11304
|
-
nextElementsInFrame.delete(element);
|
|
11305
|
-
}
|
|
11306
|
-
} else if (element.groupIds.length > 0) {
|
|
11307
|
-
for (const id of element.groupIds) {
|
|
11308
|
-
groupsToKeep.add(id);
|
|
11309
|
-
}
|
|
11476
|
+
return head + digs.join("");
|
|
11477
|
+
}
|
|
11478
|
+
function decrementInteger(x, digits) {
|
|
11479
|
+
validateInteger(x);
|
|
11480
|
+
const [head, ...digs] = x.split("");
|
|
11481
|
+
let borrow = true;
|
|
11482
|
+
for (let i = digs.length - 1; borrow && i >= 0; i--) {
|
|
11483
|
+
const d = digits.indexOf(digs[i]) - 1;
|
|
11484
|
+
if (d === -1) {
|
|
11485
|
+
digs[i] = digits.slice(-1);
|
|
11486
|
+
} else {
|
|
11487
|
+
digs[i] = digits[d];
|
|
11488
|
+
borrow = false;
|
|
11310
11489
|
}
|
|
11311
11490
|
}
|
|
11312
|
-
|
|
11313
|
-
if (
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
}
|
|
11319
|
-
}
|
|
11320
|
-
if (shouldRemoveElement) {
|
|
11321
|
-
nextElementsInFrame.delete(element);
|
|
11322
|
-
}
|
|
11491
|
+
if (borrow) {
|
|
11492
|
+
if (head === "a") {
|
|
11493
|
+
return `Z${digits.slice(-1)}`;
|
|
11494
|
+
}
|
|
11495
|
+
if (head === "A") {
|
|
11496
|
+
return null;
|
|
11323
11497
|
}
|
|
11498
|
+
const h = String.fromCharCode(head.charCodeAt(0) - 1);
|
|
11499
|
+
if (h < "Z") {
|
|
11500
|
+
digs.push(digits.slice(-1));
|
|
11501
|
+
} else {
|
|
11502
|
+
digs.pop();
|
|
11503
|
+
}
|
|
11504
|
+
return h + digs.join("");
|
|
11324
11505
|
}
|
|
11325
|
-
|
|
11326
|
-
|
|
11327
|
-
|
|
11328
|
-
|
|
11329
|
-
|
|
11506
|
+
return head + digs.join("");
|
|
11507
|
+
}
|
|
11508
|
+
function generateKeyBetween(a, b, digits = BASE_62_DIGITS) {
|
|
11509
|
+
if (a != null) {
|
|
11510
|
+
validateOrderKey(a, digits);
|
|
11330
11511
|
}
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
).filter((element) => element.groupIds.length > 0);
|
|
11334
|
-
const groupIds = selectGroupsFromGivenElements(
|
|
11335
|
-
newGroupElementsCompletelyInFrame,
|
|
11336
|
-
appState
|
|
11337
|
-
);
|
|
11338
|
-
for (const [id, isSelected] of Object.entries(groupIds)) {
|
|
11339
|
-
if (isSelected) {
|
|
11340
|
-
const elementsInGroup = getElementsInGroup(allElements, id);
|
|
11341
|
-
if (elementsAreInFrameBounds(elementsInGroup, frame, elementsMap)) {
|
|
11342
|
-
for (const element of elementsInGroup) {
|
|
11343
|
-
nextElementsInFrame.add(element);
|
|
11344
|
-
}
|
|
11345
|
-
}
|
|
11346
|
-
}
|
|
11512
|
+
if (b != null) {
|
|
11513
|
+
validateOrderKey(b, digits);
|
|
11347
11514
|
}
|
|
11348
|
-
|
|
11349
|
-
|
|
11350
|
-
}
|
|
11351
|
-
|
|
11352
|
-
|
|
11353
|
-
|
|
11354
|
-
omitGroupsContainingFrameLikes(
|
|
11355
|
-
elements,
|
|
11356
|
-
getElementsCompletelyInFrame(elements, frame, elementsMap)
|
|
11357
|
-
),
|
|
11358
|
-
frame,
|
|
11359
|
-
elementsMap
|
|
11360
|
-
);
|
|
11361
|
-
};
|
|
11362
|
-
var omitPartialGroups = (elements, frame, allElementsMap) => {
|
|
11363
|
-
const elementsToReturn = [];
|
|
11364
|
-
const checkedGroups = /* @__PURE__ */ new Map();
|
|
11365
|
-
for (const element of elements) {
|
|
11366
|
-
let shouldOmit = false;
|
|
11367
|
-
if (element.groupIds.length > 0) {
|
|
11368
|
-
if (element.groupIds.some((gid) => checkedGroups.get(gid))) {
|
|
11369
|
-
shouldOmit = true;
|
|
11370
|
-
} else {
|
|
11371
|
-
const allElementsInGroup = new Set(
|
|
11372
|
-
element.groupIds.flatMap(
|
|
11373
|
-
(gid) => getElementsInGroup(allElementsMap, gid)
|
|
11374
|
-
)
|
|
11375
|
-
);
|
|
11376
|
-
shouldOmit = !elementsAreInFrameBounds(
|
|
11377
|
-
Array.from(allElementsInGroup),
|
|
11378
|
-
frame,
|
|
11379
|
-
allElementsMap
|
|
11380
|
-
);
|
|
11381
|
-
}
|
|
11382
|
-
element.groupIds.forEach((gid) => {
|
|
11383
|
-
checkedGroups.set(gid, shouldOmit);
|
|
11384
|
-
});
|
|
11515
|
+
if (a != null && b != null && a >= b) {
|
|
11516
|
+
throw new Error(`${a} >= ${b}`);
|
|
11517
|
+
}
|
|
11518
|
+
if (a == null) {
|
|
11519
|
+
if (b == null) {
|
|
11520
|
+
return `a${digits[0]}`;
|
|
11385
11521
|
}
|
|
11386
|
-
|
|
11387
|
-
|
|
11522
|
+
const ib2 = getIntegerPart(b);
|
|
11523
|
+
const fb2 = b.slice(ib2.length);
|
|
11524
|
+
if (ib2 === `A${digits[0].repeat(26)}`) {
|
|
11525
|
+
return ib2 + midpoint("", fb2, digits);
|
|
11388
11526
|
}
|
|
11527
|
+
if (ib2 < b) {
|
|
11528
|
+
return ib2;
|
|
11529
|
+
}
|
|
11530
|
+
const res = decrementInteger(ib2, digits);
|
|
11531
|
+
if (res == null) {
|
|
11532
|
+
throw new Error("cannot decrement any more");
|
|
11533
|
+
}
|
|
11534
|
+
return res;
|
|
11389
11535
|
}
|
|
11390
|
-
|
|
11391
|
-
|
|
11392
|
-
|
|
11393
|
-
|
|
11394
|
-
return null;
|
|
11536
|
+
if (b == null) {
|
|
11537
|
+
const ia2 = getIntegerPart(a);
|
|
11538
|
+
const fa2 = a.slice(ia2.length);
|
|
11539
|
+
const i2 = incrementInteger(ia2, digits);
|
|
11540
|
+
return i2 == null ? ia2 + midpoint(fa2, null, digits) : i2;
|
|
11395
11541
|
}
|
|
11396
|
-
|
|
11397
|
-
|
|
11398
|
-
|
|
11399
|
-
const
|
|
11400
|
-
|
|
11401
|
-
|
|
11402
|
-
for (const element of elements) {
|
|
11403
|
-
if (isFrameLikeElement(element) && element.id !== frame.id) {
|
|
11404
|
-
otherFrames.add(element.id);
|
|
11405
|
-
}
|
|
11542
|
+
const ia = getIntegerPart(a);
|
|
11543
|
+
const fa = a.slice(ia.length);
|
|
11544
|
+
const ib = getIntegerPart(b);
|
|
11545
|
+
const fb = b.slice(ib.length);
|
|
11546
|
+
if (ia === ib) {
|
|
11547
|
+
return ia + midpoint(fa, fb, digits);
|
|
11406
11548
|
}
|
|
11407
|
-
const
|
|
11408
|
-
|
|
11409
|
-
|
|
11410
|
-
|
|
11411
|
-
|
|
11549
|
+
const i = incrementInteger(ia, digits);
|
|
11550
|
+
if (i == null) {
|
|
11551
|
+
throw new Error("cannot increment any more");
|
|
11552
|
+
}
|
|
11553
|
+
if (i < b) {
|
|
11554
|
+
return i;
|
|
11555
|
+
}
|
|
11556
|
+
return ia + midpoint(fa, null, digits);
|
|
11557
|
+
}
|
|
11558
|
+
function generateNKeysBetween(a, b, n, digits = BASE_62_DIGITS) {
|
|
11559
|
+
if (n === 0) {
|
|
11560
|
+
return [];
|
|
11561
|
+
}
|
|
11562
|
+
if (n === 1) {
|
|
11563
|
+
return [generateKeyBetween(a, b, digits)];
|
|
11564
|
+
}
|
|
11565
|
+
if (b == null) {
|
|
11566
|
+
let c2 = generateKeyBetween(a, b, digits);
|
|
11567
|
+
const result = [c2];
|
|
11568
|
+
for (let i = 0; i < n - 1; i++) {
|
|
11569
|
+
c2 = generateKeyBetween(c2, b, digits);
|
|
11570
|
+
result.push(c2);
|
|
11412
11571
|
}
|
|
11413
|
-
|
|
11414
|
-
|
|
11415
|
-
|
|
11416
|
-
|
|
11417
|
-
|
|
11418
|
-
|
|
11419
|
-
|
|
11420
|
-
|
|
11421
|
-
for (const child of groupElements) {
|
|
11422
|
-
eligibleElements.push(child);
|
|
11423
|
-
}
|
|
11424
|
-
}
|
|
11425
|
-
}
|
|
11426
|
-
} else {
|
|
11427
|
-
const overlaps = elementOverlapsWithFrame(element, frame, elementsMap);
|
|
11428
|
-
if (overlaps) {
|
|
11429
|
-
eligibleElements.push(element);
|
|
11430
|
-
}
|
|
11572
|
+
return result;
|
|
11573
|
+
}
|
|
11574
|
+
if (a == null) {
|
|
11575
|
+
let c2 = generateKeyBetween(a, b, digits);
|
|
11576
|
+
const result = [c2];
|
|
11577
|
+
for (let i = 0; i < n - 1; i++) {
|
|
11578
|
+
c2 = generateKeyBetween(a, c2, digits);
|
|
11579
|
+
result.push(c2);
|
|
11431
11580
|
}
|
|
11581
|
+
result.reverse();
|
|
11582
|
+
return result;
|
|
11583
|
+
}
|
|
11584
|
+
const mid = Math.floor(n / 2);
|
|
11585
|
+
const c = generateKeyBetween(a, b, digits);
|
|
11586
|
+
return [
|
|
11587
|
+
...generateNKeysBetween(a, c, mid, digits),
|
|
11588
|
+
c,
|
|
11589
|
+
...generateNKeysBetween(c, b, n - mid - 1, digits)
|
|
11590
|
+
];
|
|
11591
|
+
}
|
|
11592
|
+
|
|
11593
|
+
// ../element/src/fractionalIndex.ts
|
|
11594
|
+
var InvalidFractionalIndexError = class extends Error {
|
|
11595
|
+
constructor() {
|
|
11596
|
+
super(...arguments);
|
|
11597
|
+
__publicField(this, "code", "ELEMENT_HAS_INVALID_INDEX");
|
|
11432
11598
|
}
|
|
11433
|
-
return eligibleElements;
|
|
11434
11599
|
};
|
|
11435
|
-
var
|
|
11436
|
-
|
|
11437
|
-
|
|
11438
|
-
|
|
11439
|
-
|
|
11440
|
-
|
|
11600
|
+
var validateFractionalIndices = (elements, {
|
|
11601
|
+
shouldThrow = false,
|
|
11602
|
+
includeBoundTextValidation = false,
|
|
11603
|
+
ignoreLogs,
|
|
11604
|
+
reconciliationContext
|
|
11605
|
+
}) => {
|
|
11606
|
+
const errorMessages = [];
|
|
11607
|
+
const stringifyElement = (element) => `${element?.index}:${element?.id}:${element?.type}:${element?.isDeleted}:${element?.version}:${element?.versionNonce}`;
|
|
11608
|
+
const indices = elements.map((x) => x.index);
|
|
11609
|
+
for (const [i, index] of indices.entries()) {
|
|
11610
|
+
const predecessorIndex = indices[i - 1];
|
|
11611
|
+
const successorIndex = indices[i + 1];
|
|
11612
|
+
if (!isValidFractionalIndex(index, predecessorIndex, successorIndex)) {
|
|
11613
|
+
errorMessages.push(
|
|
11614
|
+
`Fractional indices invariant has been compromised: "${stringifyElement(
|
|
11615
|
+
elements[i - 1]
|
|
11616
|
+
)}", "${stringifyElement(elements[i])}", "${stringifyElement(
|
|
11617
|
+
elements[i + 1]
|
|
11618
|
+
)}"`
|
|
11619
|
+
);
|
|
11441
11620
|
}
|
|
11442
|
-
|
|
11443
|
-
|
|
11444
|
-
|
|
11445
|
-
|
|
11446
|
-
|
|
11447
|
-
|
|
11448
|
-
|
|
11621
|
+
if (includeBoundTextValidation && hasBoundTextElement(elements[i])) {
|
|
11622
|
+
const container = elements[i];
|
|
11623
|
+
const text = getBoundTextElement(container, arrayToMap(elements));
|
|
11624
|
+
if (text && text.index <= container.index) {
|
|
11625
|
+
errorMessages.push(
|
|
11626
|
+
`Fractional indices invariant for bound elements has been compromised: "${stringifyElement(
|
|
11627
|
+
text
|
|
11628
|
+
)}", "${stringifyElement(container)}"`
|
|
11629
|
+
);
|
|
11630
|
+
}
|
|
11449
11631
|
}
|
|
11450
11632
|
}
|
|
11451
|
-
|
|
11452
|
-
|
|
11453
|
-
|
|
11454
|
-
|
|
11455
|
-
|
|
11456
|
-
|
|
11457
|
-
|
|
11458
|
-
|
|
11459
|
-
|
|
11633
|
+
if (errorMessages.length) {
|
|
11634
|
+
const error = new InvalidFractionalIndexError();
|
|
11635
|
+
const additionalContext = [];
|
|
11636
|
+
if (reconciliationContext) {
|
|
11637
|
+
additionalContext.push("Additional reconciliation context:");
|
|
11638
|
+
additionalContext.push(
|
|
11639
|
+
reconciliationContext.localElements.map((x) => stringifyElement(x))
|
|
11640
|
+
);
|
|
11641
|
+
additionalContext.push(
|
|
11642
|
+
reconciliationContext.remoteElements.map((x) => stringifyElement(x))
|
|
11643
|
+
);
|
|
11460
11644
|
}
|
|
11461
|
-
if (!
|
|
11462
|
-
|
|
11645
|
+
if (!ignoreLogs) {
|
|
11646
|
+
console.error(
|
|
11647
|
+
errorMessages.join("\n\n"),
|
|
11648
|
+
error.stack,
|
|
11649
|
+
elements.map((x) => stringifyElement(x)),
|
|
11650
|
+
...additionalContext
|
|
11651
|
+
);
|
|
11463
11652
|
}
|
|
11464
|
-
|
|
11465
|
-
|
|
11466
|
-
finalElementsToAdd.push(boundTextElement);
|
|
11653
|
+
if (shouldThrow) {
|
|
11654
|
+
throw error;
|
|
11467
11655
|
}
|
|
11468
11656
|
}
|
|
11469
|
-
for (const element of finalElementsToAdd) {
|
|
11470
|
-
mutateElement(element, elementsMap, {
|
|
11471
|
-
frameId: frame.id
|
|
11472
|
-
});
|
|
11473
|
-
}
|
|
11474
|
-
return allElements;
|
|
11475
11657
|
};
|
|
11476
|
-
var
|
|
11477
|
-
|
|
11478
|
-
|
|
11479
|
-
|
|
11480
|
-
|
|
11481
|
-
|
|
11482
|
-
|
|
11483
|
-
arr.push(element);
|
|
11484
|
-
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
11485
|
-
if (boundTextElement) {
|
|
11486
|
-
_elementsToRemove.set(boundTextElement.id, boundTextElement);
|
|
11487
|
-
arr.push(boundTextElement);
|
|
11658
|
+
var orderByFractionalIndex = (elements) => {
|
|
11659
|
+
return elements.sort((a, b) => {
|
|
11660
|
+
if (isOrderedElement(a) && isOrderedElement(b)) {
|
|
11661
|
+
if (a.index < b.index) {
|
|
11662
|
+
return -1;
|
|
11663
|
+
} else if (a.index > b.index) {
|
|
11664
|
+
return 1;
|
|
11488
11665
|
}
|
|
11489
|
-
|
|
11666
|
+
return a.id < b.id ? -1 : 1;
|
|
11490
11667
|
}
|
|
11491
|
-
|
|
11492
|
-
|
|
11493
|
-
|
|
11494
|
-
|
|
11668
|
+
return 1;
|
|
11669
|
+
});
|
|
11670
|
+
};
|
|
11671
|
+
var syncMovedIndices = (elements, movedElements) => {
|
|
11672
|
+
try {
|
|
11673
|
+
const elementsMap = arrayToMap(elements);
|
|
11674
|
+
const indicesGroups = getMovedIndicesGroups(elements, movedElements);
|
|
11675
|
+
const elementsUpdates = generateIndices(elements, indicesGroups);
|
|
11676
|
+
const elementsCandidates = elements.map((x) => {
|
|
11677
|
+
const elementUpdates = elementsUpdates.get(x);
|
|
11678
|
+
if (elementUpdates) {
|
|
11679
|
+
return { ...x, index: elementUpdates.index };
|
|
11680
|
+
}
|
|
11681
|
+
return x;
|
|
11495
11682
|
});
|
|
11683
|
+
validateFractionalIndices(
|
|
11684
|
+
elementsCandidates,
|
|
11685
|
+
// we don't autofix invalid bound text indices, hence don't include it in the validation
|
|
11686
|
+
{
|
|
11687
|
+
includeBoundTextValidation: false,
|
|
11688
|
+
shouldThrow: true,
|
|
11689
|
+
ignoreLogs: true
|
|
11690
|
+
}
|
|
11691
|
+
);
|
|
11692
|
+
for (const [element, { index }] of elementsUpdates) {
|
|
11693
|
+
mutateElement(element, elementsMap, { index });
|
|
11694
|
+
}
|
|
11695
|
+
} catch (e) {
|
|
11696
|
+
syncInvalidIndices(elements);
|
|
11496
11697
|
}
|
|
11698
|
+
return elements;
|
|
11497
11699
|
};
|
|
11498
|
-
var
|
|
11499
|
-
const
|
|
11500
|
-
|
|
11501
|
-
|
|
11502
|
-
}
|
|
11503
|
-
|
|
11504
|
-
|
|
11505
|
-
|
|
11506
|
-
nextElementsInFrame,
|
|
11507
|
-
frame,
|
|
11508
|
-
app.state
|
|
11509
|
-
).slice();
|
|
11700
|
+
var syncInvalidIndices = (elements) => {
|
|
11701
|
+
const elementsMap = arrayToMap(elements);
|
|
11702
|
+
const indicesGroups = getInvalidIndicesGroups(elements);
|
|
11703
|
+
const elementsUpdates = generateIndices(elements, indicesGroups);
|
|
11704
|
+
for (const [element, { index }] of elementsUpdates) {
|
|
11705
|
+
mutateElement(element, elementsMap, { index });
|
|
11706
|
+
}
|
|
11707
|
+
return elements;
|
|
11510
11708
|
};
|
|
11511
|
-
var
|
|
11512
|
-
const
|
|
11513
|
-
|
|
11514
|
-
|
|
11515
|
-
|
|
11516
|
-
|
|
11517
|
-
const elementsToFilter = new Set(selectedElements);
|
|
11518
|
-
if (appState.editingGroupId) {
|
|
11519
|
-
for (const element of selectedElements) {
|
|
11520
|
-
if (element.groupIds.length === 0) {
|
|
11521
|
-
elementsToFilter.add(element);
|
|
11522
|
-
} else {
|
|
11523
|
-
element.groupIds.flatMap((gid) => getElementsInGroup(allElements, gid)).forEach((element2) => elementsToFilter.add(element2));
|
|
11524
|
-
}
|
|
11525
|
-
}
|
|
11709
|
+
var syncInvalidIndicesImmutable = (elements) => {
|
|
11710
|
+
const syncedElements = arrayToMap(elements);
|
|
11711
|
+
const indicesGroups = getInvalidIndicesGroups(elements);
|
|
11712
|
+
const elementsUpdates = generateIndices(elements, indicesGroups);
|
|
11713
|
+
for (const [element, { index }] of elementsUpdates) {
|
|
11714
|
+
syncedElements.set(element.id, newElementWith(element, { index }));
|
|
11526
11715
|
}
|
|
11527
|
-
|
|
11528
|
-
|
|
11529
|
-
|
|
11530
|
-
|
|
11531
|
-
|
|
11716
|
+
return syncedElements;
|
|
11717
|
+
};
|
|
11718
|
+
var getMovedIndicesGroups = (elements, movedElements) => {
|
|
11719
|
+
const indicesGroups = [];
|
|
11720
|
+
let i = 0;
|
|
11721
|
+
while (i < elements.length) {
|
|
11722
|
+
if (movedElements.has(elements[i].id)) {
|
|
11723
|
+
const indicesGroup = [i - 1, i];
|
|
11724
|
+
while (++i < elements.length) {
|
|
11725
|
+
if (!movedElements.has(elements[i].id)) {
|
|
11726
|
+
break;
|
|
11727
|
+
}
|
|
11728
|
+
indicesGroup.push(i);
|
|
11729
|
+
}
|
|
11730
|
+
indicesGroup.push(i);
|
|
11731
|
+
indicesGroups.push(indicesGroup);
|
|
11732
|
+
} else {
|
|
11733
|
+
i++;
|
|
11532
11734
|
}
|
|
11533
|
-
});
|
|
11534
|
-
if (elementsToRemove.size > 0) {
|
|
11535
|
-
removeElementsFromFrame(elementsToRemove, elementsMap);
|
|
11536
11735
|
}
|
|
11537
|
-
return
|
|
11736
|
+
return indicesGroups;
|
|
11538
11737
|
};
|
|
11539
|
-
var
|
|
11540
|
-
const
|
|
11541
|
-
|
|
11542
|
-
|
|
11543
|
-
|
|
11544
|
-
|
|
11545
|
-
|
|
11738
|
+
var getInvalidIndicesGroups = (elements) => {
|
|
11739
|
+
const indicesGroups = [];
|
|
11740
|
+
let lowerBound = void 0;
|
|
11741
|
+
let upperBound = void 0;
|
|
11742
|
+
let lowerBoundIndex = -1;
|
|
11743
|
+
let upperBoundIndex = 0;
|
|
11744
|
+
const getLowerBound = (index) => {
|
|
11745
|
+
const lowerBound2 = elements[lowerBoundIndex] ? elements[lowerBoundIndex].index : void 0;
|
|
11746
|
+
const candidate = elements[index - 1]?.index;
|
|
11747
|
+
if (!lowerBound2 && candidate || // first lowerBound
|
|
11748
|
+
lowerBound2 && candidate && candidate > lowerBound2) {
|
|
11749
|
+
return [candidate, index - 1];
|
|
11546
11750
|
}
|
|
11547
|
-
|
|
11548
|
-
|
|
11549
|
-
|
|
11550
|
-
|
|
11551
|
-
|
|
11552
|
-
|
|
11553
|
-
rejectedGroupIds.add(groupId);
|
|
11751
|
+
return [lowerBound2, lowerBoundIndex];
|
|
11752
|
+
};
|
|
11753
|
+
const getUpperBound = (index) => {
|
|
11754
|
+
const upperBound2 = elements[upperBoundIndex] ? elements[upperBoundIndex].index : void 0;
|
|
11755
|
+
if (upperBound2 && index < upperBoundIndex) {
|
|
11756
|
+
return [upperBound2, upperBoundIndex];
|
|
11554
11757
|
}
|
|
11555
|
-
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
|
|
11559
|
-
|
|
11758
|
+
let i2 = upperBoundIndex;
|
|
11759
|
+
while (++i2 < elements.length) {
|
|
11760
|
+
const candidate = elements[i2]?.index;
|
|
11761
|
+
if (!upperBound2 && candidate || // first upperBound
|
|
11762
|
+
upperBound2 && candidate && candidate > upperBound2) {
|
|
11763
|
+
return [candidate, i2];
|
|
11764
|
+
}
|
|
11765
|
+
}
|
|
11766
|
+
return [void 0, i2];
|
|
11767
|
+
};
|
|
11768
|
+
let i = 0;
|
|
11769
|
+
while (i < elements.length) {
|
|
11770
|
+
const current = elements[i].index;
|
|
11771
|
+
[lowerBound, lowerBoundIndex] = getLowerBound(i);
|
|
11772
|
+
[upperBound, upperBoundIndex] = getUpperBound(i);
|
|
11773
|
+
if (!isValidFractionalIndex(current, lowerBound, upperBound)) {
|
|
11774
|
+
const indicesGroup = [lowerBoundIndex, i];
|
|
11775
|
+
while (++i < elements.length) {
|
|
11776
|
+
const current2 = elements[i].index;
|
|
11777
|
+
const [nextLowerBound, nextLowerBoundIndex] = getLowerBound(i);
|
|
11778
|
+
const [nextUpperBound, nextUpperBoundIndex] = getUpperBound(i);
|
|
11779
|
+
if (isValidFractionalIndex(current2, nextLowerBound, nextUpperBound)) {
|
|
11780
|
+
break;
|
|
11781
|
+
}
|
|
11782
|
+
[lowerBound, lowerBoundIndex] = [nextLowerBound, nextLowerBoundIndex];
|
|
11783
|
+
[upperBound, upperBoundIndex] = [nextUpperBound, nextUpperBoundIndex];
|
|
11784
|
+
indicesGroup.push(i);
|
|
11785
|
+
}
|
|
11786
|
+
indicesGroup.push(upperBoundIndex);
|
|
11787
|
+
indicesGroups.push(indicesGroup);
|
|
11788
|
+
} else {
|
|
11789
|
+
i++;
|
|
11560
11790
|
}
|
|
11561
11791
|
}
|
|
11562
|
-
return
|
|
11792
|
+
return indicesGroups;
|
|
11563
11793
|
};
|
|
11564
|
-
var
|
|
11565
|
-
|
|
11566
|
-
|
|
11567
|
-
return getContainingFrame(_element, elementsMap);
|
|
11794
|
+
var isValidFractionalIndex = (index, predecessor, successor) => {
|
|
11795
|
+
if (!index) {
|
|
11796
|
+
return false;
|
|
11568
11797
|
}
|
|
11569
|
-
|
|
11570
|
-
|
|
11571
|
-
|
|
11572
|
-
const frame = opts?.targetFrame ?? getTargetFrame(element, allElementsMap, appState);
|
|
11573
|
-
if (!frame) {
|
|
11798
|
+
try {
|
|
11799
|
+
validateOrderKey(index);
|
|
11800
|
+
} catch {
|
|
11574
11801
|
return false;
|
|
11575
11802
|
}
|
|
11576
|
-
|
|
11577
|
-
|
|
11578
|
-
if (opts?.checkedGroups) {
|
|
11579
|
-
_element.groupIds.forEach((groupId) => {
|
|
11580
|
-
opts.checkedGroups?.set(groupId, isInFrame);
|
|
11581
|
-
});
|
|
11582
|
-
}
|
|
11583
|
-
};
|
|
11584
|
-
if (
|
|
11585
|
-
// if the element is not selected, or it is selected but not being dragged,
|
|
11586
|
-
// frame membership won't update, so return true
|
|
11587
|
-
!appState.selectedElementIds[_element.id] || !appState.selectedElementsAreBeingDragged || // if both frame and element are selected, won't update membership, so return true
|
|
11588
|
-
appState.selectedElementIds[_element.id] && appState.selectedElementIds[frame.id]
|
|
11589
|
-
) {
|
|
11590
|
-
return true;
|
|
11803
|
+
if (predecessor && successor) {
|
|
11804
|
+
return predecessor < index && index < successor;
|
|
11591
11805
|
}
|
|
11592
|
-
if (
|
|
11593
|
-
return
|
|
11806
|
+
if (!predecessor && successor) {
|
|
11807
|
+
return index < successor;
|
|
11594
11808
|
}
|
|
11595
|
-
|
|
11596
|
-
|
|
11597
|
-
return opts.checkedGroups.get(gid);
|
|
11598
|
-
}
|
|
11809
|
+
if (predecessor && !successor) {
|
|
11810
|
+
return predecessor < index;
|
|
11599
11811
|
}
|
|
11600
|
-
|
|
11601
|
-
|
|
11602
|
-
|
|
11603
|
-
|
|
11604
|
-
|
|
11605
|
-
|
|
11606
|
-
|
|
11607
|
-
|
|
11608
|
-
|
|
11609
|
-
|
|
11610
|
-
|
|
11812
|
+
return !!index;
|
|
11813
|
+
};
|
|
11814
|
+
var generateIndices = (elements, indicesGroups) => {
|
|
11815
|
+
const elementsUpdates = /* @__PURE__ */ new Map();
|
|
11816
|
+
for (const indices of indicesGroups) {
|
|
11817
|
+
const lowerBoundIndex = indices.shift();
|
|
11818
|
+
const upperBoundIndex = indices.pop();
|
|
11819
|
+
const fractionalIndices = generateNKeysBetween(
|
|
11820
|
+
elements[lowerBoundIndex]?.index,
|
|
11821
|
+
elements[upperBoundIndex]?.index,
|
|
11822
|
+
indices.length
|
|
11611
11823
|
);
|
|
11612
|
-
|
|
11613
|
-
|
|
11614
|
-
|
|
11615
|
-
|
|
11616
|
-
|
|
11617
|
-
allElementsInGroup.delete(selectedElement);
|
|
11618
|
-
});
|
|
11619
|
-
}
|
|
11620
|
-
for (const elementInGroup of allElementsInGroup) {
|
|
11621
|
-
if (isFrameLikeElement(elementInGroup)) {
|
|
11622
|
-
setGroupsInFrame(false);
|
|
11623
|
-
return false;
|
|
11624
|
-
}
|
|
11625
|
-
}
|
|
11626
|
-
for (const elementInGroup of allElementsInGroup) {
|
|
11627
|
-
if (elementOverlapsWithFrame(elementInGroup, frame, allElementsMap)) {
|
|
11628
|
-
setGroupsInFrame(true);
|
|
11629
|
-
return true;
|
|
11824
|
+
for (let i = 0; i < indices.length; i++) {
|
|
11825
|
+
const element = elements[indices[i]];
|
|
11826
|
+
elementsUpdates.set(element, {
|
|
11827
|
+
index: fractionalIndices[i]
|
|
11828
|
+
});
|
|
11630
11829
|
}
|
|
11631
11830
|
}
|
|
11632
|
-
return
|
|
11831
|
+
return elementsUpdates;
|
|
11633
11832
|
};
|
|
11634
|
-
var
|
|
11635
|
-
if (
|
|
11636
|
-
return false;
|
|
11637
|
-
}
|
|
11638
|
-
const shouldClipElementItself = isElementIntersectingFrame(element, frame, elementsMap) || isElementContainingFrame(element, frame, elementsMap);
|
|
11639
|
-
if (shouldClipElementItself) {
|
|
11640
|
-
for (const groupId of element.groupIds) {
|
|
11641
|
-
checkedGroups?.set(groupId, true);
|
|
11642
|
-
}
|
|
11833
|
+
var isOrderedElement = (element) => {
|
|
11834
|
+
if (element.index) {
|
|
11643
11835
|
return true;
|
|
11644
11836
|
}
|
|
11645
|
-
|
|
11646
|
-
|
|
11647
|
-
|
|
11648
|
-
|
|
11649
|
-
|
|
11650
|
-
|
|
11837
|
+
return false;
|
|
11838
|
+
};
|
|
11839
|
+
|
|
11840
|
+
// ../element/src/frame.ts
|
|
11841
|
+
var bindElementsToFramesAfterDuplication = (nextElements, origElements, origIdToDuplicateId) => {
|
|
11842
|
+
const nextElementMap = arrayToMap(nextElements);
|
|
11843
|
+
for (const element of origElements) {
|
|
11844
|
+
if (element.frameId) {
|
|
11845
|
+
const nextElementId = origIdToDuplicateId.get(element.id);
|
|
11846
|
+
const nextFrameId = origIdToDuplicateId.get(element.frameId);
|
|
11847
|
+
const nextElement = nextElementId && nextElementMap.get(nextElementId);
|
|
11848
|
+
if (nextElement) {
|
|
11849
|
+
mutateElement(nextElement, nextElementMap, {
|
|
11850
|
+
frameId: nextFrameId ?? null
|
|
11851
|
+
});
|
|
11651
11852
|
}
|
|
11652
|
-
} else {
|
|
11653
|
-
shouldClip = isElementInFrame(element, elementsMap, appState, {
|
|
11654
|
-
targetFrame: frame,
|
|
11655
|
-
checkedGroups
|
|
11656
|
-
});
|
|
11657
11853
|
}
|
|
11658
|
-
for (const groupId of element.groupIds) {
|
|
11659
|
-
checkedGroups?.set(groupId, shouldClip);
|
|
11660
|
-
}
|
|
11661
|
-
return shouldClip;
|
|
11662
11854
|
}
|
|
11663
|
-
return false;
|
|
11664
|
-
};
|
|
11665
|
-
var DEFAULT_FRAME_NAME = "Frame";
|
|
11666
|
-
var DEFAULT_AI_FRAME_NAME = "AI Frame";
|
|
11667
|
-
var getDefaultFrameName = (element) => {
|
|
11668
|
-
return isFrameElement(element) ? DEFAULT_FRAME_NAME : DEFAULT_AI_FRAME_NAME;
|
|
11669
11855
|
};
|
|
11670
|
-
|
|
11671
|
-
|
|
11856
|
+
function isElementIntersectingFrame(element, frame, elementsMap) {
|
|
11857
|
+
const frameLineSegments = getElementLineSegments(frame, elementsMap);
|
|
11858
|
+
const elementLineSegments = getElementLineSegments(element, elementsMap);
|
|
11859
|
+
const intersecting = frameLineSegments.some(
|
|
11860
|
+
(frameLineSegment) => elementLineSegments.some(
|
|
11861
|
+
(elementLineSegment) => doLineSegmentsIntersect(frameLineSegment, elementLineSegment)
|
|
11862
|
+
)
|
|
11863
|
+
);
|
|
11864
|
+
return intersecting;
|
|
11865
|
+
}
|
|
11866
|
+
var getElementsCompletelyInFrame = (elements, frame, elementsMap) => omitGroupsContainingFrameLikes(
|
|
11867
|
+
getElementsWithinSelection(elements, frame, elementsMap, false)
|
|
11868
|
+
).filter(
|
|
11869
|
+
(element) => !isFrameLikeElement(element) && !element.frameId || element.frameId === frame.id
|
|
11870
|
+
);
|
|
11871
|
+
var isElementContainingFrame = (element, frame, elementsMap) => {
|
|
11872
|
+
return boundsContainBounds(
|
|
11873
|
+
getElementBounds(element, elementsMap),
|
|
11874
|
+
getElementBounds(frame, elementsMap)
|
|
11875
|
+
);
|
|
11876
|
+
};
|
|
11877
|
+
var elementsAreInFrameBounds = (elements, frame, elementsMap) => {
|
|
11878
|
+
const [frameX1, frameY1, frameX2, frameY2] = getElementAbsoluteCoords(
|
|
11879
|
+
frame,
|
|
11880
|
+
elementsMap
|
|
11881
|
+
);
|
|
11882
|
+
const [elementX1, elementY1, elementX2, elementY2] = getCommonBounds(elements);
|
|
11883
|
+
return frameX1 <= elementX1 && frameY1 <= elementY1 && frameX2 >= elementX2 && frameY2 >= elementY2;
|
|
11884
|
+
};
|
|
11885
|
+
var elementOverlapsWithFrame = (element, frame, elementsMap) => {
|
|
11886
|
+
return elementsAreInFrameBounds([element], frame, elementsMap) || isElementIntersectingFrame(element, frame, elementsMap) || isElementContainingFrame(element, frame, elementsMap);
|
|
11887
|
+
};
|
|
11888
|
+
var isCursorInFrame = (cursorCoords, frame, elementsMap) => {
|
|
11889
|
+
const [fx1, fy1, fx2, fy2] = getElementAbsoluteCoords(frame, elementsMap);
|
|
11890
|
+
return isPointWithinBounds(
|
|
11891
|
+
pointFrom(fx1, fy1),
|
|
11892
|
+
pointFrom(cursorCoords.x, cursorCoords.y),
|
|
11893
|
+
pointFrom(fx2, fy2)
|
|
11894
|
+
);
|
|
11895
|
+
};
|
|
11896
|
+
var groupByFrameLikes = (elements) => {
|
|
11897
|
+
const frameElementsMap = /* @__PURE__ */ new Map();
|
|
11898
|
+
for (const element of elements) {
|
|
11899
|
+
const frameId = isFrameLikeElement(element) ? element.id : element.frameId;
|
|
11900
|
+
if (frameId && !frameElementsMap.has(frameId)) {
|
|
11901
|
+
frameElementsMap.set(frameId, getFrameChildren(elements, frameId));
|
|
11902
|
+
}
|
|
11903
|
+
}
|
|
11904
|
+
return frameElementsMap;
|
|
11905
|
+
};
|
|
11906
|
+
var getFrameChildren = (allElements, frameId) => {
|
|
11907
|
+
const frameChildren = [];
|
|
11908
|
+
for (const element of allElements.values()) {
|
|
11909
|
+
if (element.frameId === frameId) {
|
|
11910
|
+
frameChildren.push(element);
|
|
11911
|
+
}
|
|
11912
|
+
}
|
|
11913
|
+
return frameChildren;
|
|
11914
|
+
};
|
|
11915
|
+
var getFrameLikeElements = (allElements) => {
|
|
11916
|
+
return allElements.filter(
|
|
11917
|
+
(element) => isFrameLikeElement(element)
|
|
11918
|
+
);
|
|
11919
|
+
};
|
|
11920
|
+
var getRootElements = (allElements) => {
|
|
11921
|
+
const frameElements = arrayToMap(getFrameLikeElements(allElements));
|
|
11922
|
+
return allElements.filter(
|
|
11923
|
+
(element) => frameElements.has(element.id) || !element.frameId || !frameElements.has(element.frameId)
|
|
11924
|
+
);
|
|
11925
|
+
};
|
|
11926
|
+
var getElementsInResizingFrame = (allElements, frame, appState, elementsMap) => {
|
|
11927
|
+
const prevElementsInFrame = getFrameChildren(allElements, frame.id);
|
|
11928
|
+
const nextElementsInFrame = new Set(prevElementsInFrame);
|
|
11929
|
+
const elementsCompletelyInFrame = /* @__PURE__ */ new Set([
|
|
11930
|
+
...getElementsCompletelyInFrame(allElements, frame, elementsMap),
|
|
11931
|
+
...prevElementsInFrame.filter(
|
|
11932
|
+
(element) => isElementContainingFrame(element, frame, elementsMap)
|
|
11933
|
+
)
|
|
11934
|
+
]);
|
|
11935
|
+
const elementsNotCompletelyInFrame = prevElementsInFrame.filter(
|
|
11936
|
+
(element) => !elementsCompletelyInFrame.has(element)
|
|
11937
|
+
);
|
|
11938
|
+
const groupsToKeep = new Set(
|
|
11939
|
+
Array.from(elementsCompletelyInFrame).flatMap(
|
|
11940
|
+
(element) => element.groupIds
|
|
11941
|
+
)
|
|
11942
|
+
);
|
|
11943
|
+
for (const element of elementsNotCompletelyInFrame) {
|
|
11944
|
+
if (!isElementIntersectingFrame(element, frame, elementsMap)) {
|
|
11945
|
+
if (element.groupIds.length === 0) {
|
|
11946
|
+
nextElementsInFrame.delete(element);
|
|
11947
|
+
}
|
|
11948
|
+
} else if (element.groupIds.length > 0) {
|
|
11949
|
+
for (const id of element.groupIds) {
|
|
11950
|
+
groupsToKeep.add(id);
|
|
11951
|
+
}
|
|
11952
|
+
}
|
|
11953
|
+
}
|
|
11954
|
+
for (const element of elementsNotCompletelyInFrame) {
|
|
11955
|
+
if (element.groupIds.length > 0) {
|
|
11956
|
+
let shouldRemoveElement = true;
|
|
11957
|
+
for (const id of element.groupIds) {
|
|
11958
|
+
if (groupsToKeep.has(id)) {
|
|
11959
|
+
shouldRemoveElement = false;
|
|
11960
|
+
}
|
|
11961
|
+
}
|
|
11962
|
+
if (shouldRemoveElement) {
|
|
11963
|
+
nextElementsInFrame.delete(element);
|
|
11964
|
+
}
|
|
11965
|
+
}
|
|
11966
|
+
}
|
|
11967
|
+
const individualElementsCompletelyInFrame = Array.from(
|
|
11968
|
+
elementsCompletelyInFrame
|
|
11969
|
+
).filter((element) => element.groupIds.length === 0);
|
|
11970
|
+
for (const element of individualElementsCompletelyInFrame) {
|
|
11971
|
+
nextElementsInFrame.add(element);
|
|
11972
|
+
}
|
|
11973
|
+
const newGroupElementsCompletelyInFrame = Array.from(
|
|
11974
|
+
elementsCompletelyInFrame
|
|
11975
|
+
).filter((element) => element.groupIds.length > 0);
|
|
11976
|
+
const groupIds = selectGroupsFromGivenElements(
|
|
11977
|
+
newGroupElementsCompletelyInFrame,
|
|
11978
|
+
appState
|
|
11979
|
+
);
|
|
11980
|
+
for (const [id, isSelected] of Object.entries(groupIds)) {
|
|
11981
|
+
if (isSelected) {
|
|
11982
|
+
const elementsInGroup = getElementsInGroup(allElements, id);
|
|
11983
|
+
if (elementsAreInFrameBounds(elementsInGroup, frame, elementsMap)) {
|
|
11984
|
+
for (const element of elementsInGroup) {
|
|
11985
|
+
nextElementsInFrame.add(element);
|
|
11986
|
+
}
|
|
11987
|
+
}
|
|
11988
|
+
}
|
|
11989
|
+
}
|
|
11990
|
+
return [...nextElementsInFrame].filter((element) => {
|
|
11991
|
+
return !(isTextElement(element) && element.containerId);
|
|
11992
|
+
});
|
|
11993
|
+
};
|
|
11994
|
+
var getElementsInNewFrame = (elements, frame, elementsMap) => {
|
|
11995
|
+
return omitPartialGroups(
|
|
11996
|
+
omitGroupsContainingFrameLikes(
|
|
11997
|
+
elements,
|
|
11998
|
+
getElementsCompletelyInFrame(elements, frame, elementsMap)
|
|
11999
|
+
),
|
|
12000
|
+
frame,
|
|
12001
|
+
elementsMap
|
|
12002
|
+
);
|
|
12003
|
+
};
|
|
12004
|
+
var omitPartialGroups = (elements, frame, allElementsMap) => {
|
|
12005
|
+
const elementsToReturn = [];
|
|
12006
|
+
const checkedGroups = /* @__PURE__ */ new Map();
|
|
12007
|
+
for (const element of elements) {
|
|
12008
|
+
let shouldOmit = false;
|
|
12009
|
+
if (element.groupIds.length > 0) {
|
|
12010
|
+
if (element.groupIds.some((gid) => checkedGroups.get(gid))) {
|
|
12011
|
+
shouldOmit = true;
|
|
12012
|
+
} else {
|
|
12013
|
+
const allElementsInGroup = new Set(
|
|
12014
|
+
element.groupIds.flatMap(
|
|
12015
|
+
(gid) => getElementsInGroup(allElementsMap, gid)
|
|
12016
|
+
)
|
|
12017
|
+
);
|
|
12018
|
+
shouldOmit = !elementsAreInFrameBounds(
|
|
12019
|
+
Array.from(allElementsInGroup),
|
|
12020
|
+
frame,
|
|
12021
|
+
allElementsMap
|
|
12022
|
+
);
|
|
12023
|
+
}
|
|
12024
|
+
element.groupIds.forEach((gid) => {
|
|
12025
|
+
checkedGroups.set(gid, shouldOmit);
|
|
12026
|
+
});
|
|
12027
|
+
}
|
|
12028
|
+
if (!shouldOmit) {
|
|
12029
|
+
elementsToReturn.push(element);
|
|
12030
|
+
}
|
|
12031
|
+
}
|
|
12032
|
+
return elementsToReturn;
|
|
12033
|
+
};
|
|
12034
|
+
var getContainingFrame = (element, elementsMap) => {
|
|
12035
|
+
if (!element.frameId) {
|
|
12036
|
+
return null;
|
|
12037
|
+
}
|
|
12038
|
+
return elementsMap.get(element.frameId) || null;
|
|
12039
|
+
};
|
|
12040
|
+
var filterElementsEligibleAsFrameChildren = (elements, frame) => {
|
|
12041
|
+
const otherFrames = /* @__PURE__ */ new Set();
|
|
12042
|
+
const elementsMap = arrayToMap(elements);
|
|
12043
|
+
elements = omitGroupsContainingFrameLikes(elements);
|
|
12044
|
+
for (const element of elements) {
|
|
12045
|
+
if (isFrameLikeElement(element) && element.id !== frame.id) {
|
|
12046
|
+
otherFrames.add(element.id);
|
|
12047
|
+
}
|
|
12048
|
+
}
|
|
12049
|
+
const processedGroups = /* @__PURE__ */ new Set();
|
|
12050
|
+
const eligibleElements = [];
|
|
12051
|
+
for (const element of elements) {
|
|
12052
|
+
if (isFrameLikeElement(element) || element.frameId && otherFrames.has(element.frameId)) {
|
|
12053
|
+
continue;
|
|
12054
|
+
}
|
|
12055
|
+
if (element.groupIds.length) {
|
|
12056
|
+
const shallowestGroupId = element.groupIds.at(-1);
|
|
12057
|
+
if (!processedGroups.has(shallowestGroupId)) {
|
|
12058
|
+
processedGroups.add(shallowestGroupId);
|
|
12059
|
+
const groupElements = getElementsInGroup(elements, shallowestGroupId);
|
|
12060
|
+
if (groupElements.some(
|
|
12061
|
+
(el) => elementOverlapsWithFrame(el, frame, elementsMap)
|
|
12062
|
+
)) {
|
|
12063
|
+
for (const child of groupElements) {
|
|
12064
|
+
eligibleElements.push(child);
|
|
12065
|
+
}
|
|
12066
|
+
}
|
|
12067
|
+
}
|
|
12068
|
+
} else {
|
|
12069
|
+
const overlaps = elementOverlapsWithFrame(element, frame, elementsMap);
|
|
12070
|
+
if (overlaps) {
|
|
12071
|
+
eligibleElements.push(element);
|
|
12072
|
+
}
|
|
12073
|
+
}
|
|
12074
|
+
}
|
|
12075
|
+
return eligibleElements;
|
|
12076
|
+
};
|
|
12077
|
+
var getCommonFrameId = (elements) => {
|
|
12078
|
+
let commonFrameId;
|
|
12079
|
+
for (const element of elements) {
|
|
12080
|
+
if (isFrameLikeElement(element) || !element.frameId) {
|
|
12081
|
+
return null;
|
|
12082
|
+
}
|
|
12083
|
+
if (commonFrameId === void 0) {
|
|
12084
|
+
commonFrameId = element.frameId;
|
|
12085
|
+
} else if (commonFrameId !== element.frameId) {
|
|
12086
|
+
return null;
|
|
12087
|
+
}
|
|
12088
|
+
}
|
|
12089
|
+
return commonFrameId ?? null;
|
|
12090
|
+
};
|
|
12091
|
+
var getFrameChildrenInsertionIndex = (elements, frameId) => {
|
|
12092
|
+
for (let index = elements.length - 1; index >= 0; index--) {
|
|
12093
|
+
const element = elements[index];
|
|
12094
|
+
if (element.id === frameId) {
|
|
12095
|
+
return index;
|
|
12096
|
+
} else if (element.frameId === frameId) {
|
|
12097
|
+
return index + 1;
|
|
12098
|
+
}
|
|
12099
|
+
}
|
|
12100
|
+
return null;
|
|
12101
|
+
};
|
|
12102
|
+
var addElementsToFrame = (allElements, elementsToAdd, frame) => {
|
|
12103
|
+
const elementsMap = arrayToMap(allElements);
|
|
12104
|
+
const commonFrameId = getCommonFrameId(elementsToAdd);
|
|
12105
|
+
const finalElementsToAdd = /* @__PURE__ */ new Set();
|
|
12106
|
+
const otherFrames = /* @__PURE__ */ new Set();
|
|
12107
|
+
for (const element of elementsToAdd) {
|
|
12108
|
+
if (isFrameLikeElement(element) && element.id !== frame.id) {
|
|
12109
|
+
otherFrames.add(element.id);
|
|
12110
|
+
}
|
|
12111
|
+
}
|
|
12112
|
+
for (const element of omitGroupsContainingFrameLikes(
|
|
12113
|
+
allElements,
|
|
12114
|
+
elementsToAdd
|
|
12115
|
+
)) {
|
|
12116
|
+
if (isFrameLikeElement(element) || element.frameId && otherFrames.has(element.frameId)) {
|
|
12117
|
+
continue;
|
|
12118
|
+
}
|
|
12119
|
+
if (element.frameId && element.frameId !== frame.id) {
|
|
12120
|
+
continue;
|
|
12121
|
+
}
|
|
12122
|
+
finalElementsToAdd.add(element);
|
|
12123
|
+
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
12124
|
+
if (boundTextElement && !finalElementsToAdd.has(boundTextElement)) {
|
|
12125
|
+
finalElementsToAdd.add(boundTextElement);
|
|
12126
|
+
}
|
|
12127
|
+
}
|
|
12128
|
+
for (const element of finalElementsToAdd) {
|
|
12129
|
+
if (element.frameId !== frame.id) {
|
|
12130
|
+
mutateElement(element, elementsMap, {
|
|
12131
|
+
frameId: frame.id
|
|
12132
|
+
});
|
|
12133
|
+
}
|
|
12134
|
+
}
|
|
12135
|
+
if (!finalElementsToAdd.size || // if all elements to add already belong to the frame, then we don't want to
|
|
12136
|
+
// reorder (case: we're dragging element children within the frame)
|
|
12137
|
+
commonFrameId === frame.id) {
|
|
12138
|
+
return allElements;
|
|
12139
|
+
}
|
|
12140
|
+
const otherElements = Array.from(allElements.values()).filter(
|
|
12141
|
+
(element) => !finalElementsToAdd.has(element)
|
|
12142
|
+
);
|
|
12143
|
+
const insertionIndex = getFrameChildrenInsertionIndex(
|
|
12144
|
+
otherElements,
|
|
12145
|
+
frame.id
|
|
12146
|
+
);
|
|
12147
|
+
if (insertionIndex === null) {
|
|
12148
|
+
return allElements;
|
|
12149
|
+
}
|
|
12150
|
+
const reorderedElements = [
|
|
12151
|
+
...otherElements.slice(0, insertionIndex),
|
|
12152
|
+
...finalElementsToAdd,
|
|
12153
|
+
...otherElements.slice(insertionIndex)
|
|
12154
|
+
];
|
|
12155
|
+
syncMovedIndices(reorderedElements, arrayToMap([...finalElementsToAdd]));
|
|
12156
|
+
return Array.isArray(allElements) ? reorderedElements : new Map(reorderedElements.map((element) => [element.id, element]));
|
|
12157
|
+
};
|
|
12158
|
+
var removeElementsFromFrame = (elementsToRemove, elementsMap) => {
|
|
12159
|
+
const _elementsToRemove = /* @__PURE__ */ new Map();
|
|
12160
|
+
const toRemoveElementsByFrame = /* @__PURE__ */ new Map();
|
|
12161
|
+
for (const element of elementsToRemove) {
|
|
12162
|
+
if (element.frameId) {
|
|
12163
|
+
_elementsToRemove.set(element.id, element);
|
|
12164
|
+
const arr = toRemoveElementsByFrame.get(element.frameId) || [];
|
|
12165
|
+
arr.push(element);
|
|
12166
|
+
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
12167
|
+
if (boundTextElement) {
|
|
12168
|
+
_elementsToRemove.set(boundTextElement.id, boundTextElement);
|
|
12169
|
+
arr.push(boundTextElement);
|
|
12170
|
+
}
|
|
12171
|
+
toRemoveElementsByFrame.set(element.frameId, arr);
|
|
12172
|
+
}
|
|
12173
|
+
}
|
|
12174
|
+
for (const [, element] of _elementsToRemove) {
|
|
12175
|
+
mutateElement(element, elementsMap, {
|
|
12176
|
+
frameId: null
|
|
12177
|
+
});
|
|
12178
|
+
}
|
|
12179
|
+
};
|
|
12180
|
+
var removeAllElementsFromFrame = (allElements, frame) => {
|
|
12181
|
+
const elementsInFrame = getFrameChildren(allElements, frame.id);
|
|
12182
|
+
removeElementsFromFrame(elementsInFrame, arrayToMap(allElements));
|
|
12183
|
+
return allElements;
|
|
12184
|
+
};
|
|
12185
|
+
var replaceAllElementsInFrame = (allElements, nextElementsInFrame, frame) => {
|
|
12186
|
+
return addElementsToFrame(
|
|
12187
|
+
removeAllElementsFromFrame(allElements, frame),
|
|
12188
|
+
nextElementsInFrame,
|
|
12189
|
+
frame
|
|
12190
|
+
).slice();
|
|
12191
|
+
};
|
|
12192
|
+
var updateFrameMembershipOfSelectedElements = (allElements, appState, app) => {
|
|
12193
|
+
const selectedElements = app.scene.getSelectedElements({
|
|
12194
|
+
selectedElementIds: appState.selectedElementIds,
|
|
12195
|
+
// supplying elements explicitly in case we're passed non-state elements
|
|
12196
|
+
elements: allElements
|
|
12197
|
+
});
|
|
12198
|
+
const elementsToFilter = new Set(selectedElements);
|
|
12199
|
+
if (appState.editingGroupId) {
|
|
12200
|
+
for (const element of selectedElements) {
|
|
12201
|
+
if (element.groupIds.length === 0) {
|
|
12202
|
+
elementsToFilter.add(element);
|
|
12203
|
+
} else {
|
|
12204
|
+
element.groupIds.flatMap((gid) => getElementsInGroup(allElements, gid)).forEach((element2) => elementsToFilter.add(element2));
|
|
12205
|
+
}
|
|
12206
|
+
}
|
|
12207
|
+
}
|
|
12208
|
+
const elementsToRemove = /* @__PURE__ */ new Set();
|
|
12209
|
+
const elementsMap = arrayToMap(allElements);
|
|
12210
|
+
elementsToFilter.forEach((element) => {
|
|
12211
|
+
if (element.frameId && !isFrameLikeElement(element) && !isElementInFrame(element, elementsMap, appState)) {
|
|
12212
|
+
elementsToRemove.add(element);
|
|
12213
|
+
}
|
|
12214
|
+
});
|
|
12215
|
+
if (elementsToRemove.size > 0) {
|
|
12216
|
+
removeElementsFromFrame(elementsToRemove, elementsMap);
|
|
12217
|
+
}
|
|
12218
|
+
return allElements;
|
|
12219
|
+
};
|
|
12220
|
+
var omitGroupsContainingFrameLikes = (allElements, selectedElements) => {
|
|
12221
|
+
const uniqueGroupIds = /* @__PURE__ */ new Set();
|
|
12222
|
+
const elements = selectedElements || allElements;
|
|
12223
|
+
for (const el of elements.values()) {
|
|
12224
|
+
const topMostGroupId = el.groupIds[el.groupIds.length - 1];
|
|
12225
|
+
if (topMostGroupId) {
|
|
12226
|
+
uniqueGroupIds.add(topMostGroupId);
|
|
12227
|
+
}
|
|
12228
|
+
}
|
|
12229
|
+
const rejectedGroupIds = /* @__PURE__ */ new Set();
|
|
12230
|
+
for (const groupId of uniqueGroupIds) {
|
|
12231
|
+
if (getElementsInGroup(allElements, groupId).some(
|
|
12232
|
+
(el) => isFrameLikeElement(el)
|
|
12233
|
+
)) {
|
|
12234
|
+
rejectedGroupIds.add(groupId);
|
|
12235
|
+
}
|
|
12236
|
+
}
|
|
12237
|
+
const ret = [];
|
|
12238
|
+
for (const element of elements.values()) {
|
|
12239
|
+
if (!rejectedGroupIds.has(element.groupIds[element.groupIds.length - 1])) {
|
|
12240
|
+
ret.push(element);
|
|
12241
|
+
}
|
|
12242
|
+
}
|
|
12243
|
+
return ret;
|
|
12244
|
+
};
|
|
12245
|
+
var getTargetFrame = (element, elementsMap, appState) => {
|
|
12246
|
+
const _element = isTextElement(element) ? getContainerElement(element, elementsMap) || element : element;
|
|
12247
|
+
if (_element.frameId && appState.selectedElementIds[_element.id] && appState.selectedElementIds[_element.frameId]) {
|
|
12248
|
+
return getContainingFrame(_element, elementsMap);
|
|
12249
|
+
}
|
|
12250
|
+
return appState.selectedElementIds[_element.id] && appState.selectedElementsAreBeingDragged ? appState.frameToHighlight : getContainingFrame(_element, elementsMap);
|
|
12251
|
+
};
|
|
12252
|
+
var isElementInFrame = (element, allElementsMap, appState, opts) => {
|
|
12253
|
+
const frame = opts?.targetFrame ?? getTargetFrame(element, allElementsMap, appState);
|
|
12254
|
+
if (!frame) {
|
|
12255
|
+
return false;
|
|
12256
|
+
}
|
|
12257
|
+
const _element = isTextElement(element) ? getContainerElement(element, allElementsMap) || element : element;
|
|
12258
|
+
const setGroupsInFrame = (isInFrame) => {
|
|
12259
|
+
if (opts?.checkedGroups) {
|
|
12260
|
+
_element.groupIds.forEach((groupId) => {
|
|
12261
|
+
opts.checkedGroups?.set(groupId, isInFrame);
|
|
12262
|
+
});
|
|
12263
|
+
}
|
|
12264
|
+
};
|
|
12265
|
+
if (
|
|
12266
|
+
// if the element is not selected, or it is selected but not being dragged,
|
|
12267
|
+
// frame membership won't update, so return true
|
|
12268
|
+
!appState.selectedElementIds[_element.id] || !appState.selectedElementsAreBeingDragged || // if both frame and element are selected, won't update membership, so return true
|
|
12269
|
+
appState.selectedElementIds[_element.id] && appState.selectedElementIds[frame.id]
|
|
12270
|
+
) {
|
|
12271
|
+
return true;
|
|
12272
|
+
}
|
|
12273
|
+
if (_element.groupIds.length === 0) {
|
|
12274
|
+
return elementOverlapsWithFrame(_element, frame, allElementsMap);
|
|
12275
|
+
}
|
|
12276
|
+
for (const gid of _element.groupIds) {
|
|
12277
|
+
if (opts?.checkedGroups?.has(gid)) {
|
|
12278
|
+
return opts.checkedGroups.get(gid);
|
|
12279
|
+
}
|
|
12280
|
+
}
|
|
12281
|
+
const allElementsInGroup = new Set(
|
|
12282
|
+
_element.groupIds.filter((gid) => {
|
|
12283
|
+
if (opts?.checkedGroups) {
|
|
12284
|
+
return !opts.checkedGroups.has(gid);
|
|
12285
|
+
}
|
|
12286
|
+
return true;
|
|
12287
|
+
}).flatMap((gid) => getElementsInGroup(allElementsMap, gid))
|
|
12288
|
+
);
|
|
12289
|
+
if (appState.editingGroupId && appState.selectedElementsAreBeingDragged) {
|
|
12290
|
+
const selectedElements = new Set(
|
|
12291
|
+
getSelectedElements(allElementsMap, appState)
|
|
12292
|
+
);
|
|
12293
|
+
const editingGroupOverlapsFrame = appState.frameToHighlight !== null;
|
|
12294
|
+
if (editingGroupOverlapsFrame) {
|
|
12295
|
+
return true;
|
|
12296
|
+
}
|
|
12297
|
+
selectedElements.forEach((selectedElement) => {
|
|
12298
|
+
allElementsInGroup.delete(selectedElement);
|
|
12299
|
+
});
|
|
12300
|
+
}
|
|
12301
|
+
for (const elementInGroup of allElementsInGroup) {
|
|
12302
|
+
if (isFrameLikeElement(elementInGroup)) {
|
|
12303
|
+
setGroupsInFrame(false);
|
|
12304
|
+
return false;
|
|
12305
|
+
}
|
|
12306
|
+
}
|
|
12307
|
+
for (const elementInGroup of allElementsInGroup) {
|
|
12308
|
+
if (elementOverlapsWithFrame(elementInGroup, frame, allElementsMap)) {
|
|
12309
|
+
setGroupsInFrame(true);
|
|
12310
|
+
return true;
|
|
12311
|
+
}
|
|
12312
|
+
}
|
|
12313
|
+
return false;
|
|
11672
12314
|
};
|
|
11673
|
-
var
|
|
11674
|
-
|
|
11675
|
-
|
|
11676
|
-
|
|
11677
|
-
|
|
11678
|
-
|
|
12315
|
+
var shouldApplyFrameClip = (element, frame, appState, elementsMap, checkedGroups) => {
|
|
12316
|
+
if (!appState.frameRendering || !appState.frameRendering.clip) {
|
|
12317
|
+
return false;
|
|
12318
|
+
}
|
|
12319
|
+
const shouldClipElementItself = isElementIntersectingFrame(element, frame, elementsMap) || isElementContainingFrame(element, frame, elementsMap);
|
|
12320
|
+
if (shouldClipElementItself) {
|
|
12321
|
+
for (const groupId of element.groupIds) {
|
|
12322
|
+
checkedGroups?.set(groupId, true);
|
|
12323
|
+
}
|
|
12324
|
+
return true;
|
|
12325
|
+
}
|
|
12326
|
+
if (!shouldClipElementItself && element.groupIds.length > 0 && !elementsAreInFrameBounds([element], frame, elementsMap)) {
|
|
12327
|
+
let shouldClip = false;
|
|
12328
|
+
if (!appState.selectedElementsAreBeingDragged) {
|
|
12329
|
+
shouldClip = element.frameId === frame.id;
|
|
12330
|
+
for (const groupId of element.groupIds) {
|
|
12331
|
+
checkedGroups?.set(groupId, shouldClip);
|
|
12332
|
+
}
|
|
12333
|
+
} else {
|
|
12334
|
+
shouldClip = isElementInFrame(element, elementsMap, appState, {
|
|
12335
|
+
targetFrame: frame,
|
|
12336
|
+
checkedGroups
|
|
12337
|
+
});
|
|
12338
|
+
}
|
|
12339
|
+
for (const groupId of element.groupIds) {
|
|
12340
|
+
checkedGroups?.set(groupId, shouldClip);
|
|
12341
|
+
}
|
|
12342
|
+
return shouldClip;
|
|
12343
|
+
}
|
|
12344
|
+
return false;
|
|
12345
|
+
};
|
|
12346
|
+
var DEFAULT_FRAME_NAME = "Frame";
|
|
12347
|
+
var DEFAULT_AI_FRAME_NAME = "AI Frame";
|
|
12348
|
+
var getDefaultFrameName = (element) => {
|
|
12349
|
+
return isFrameElement(element) ? DEFAULT_FRAME_NAME : DEFAULT_AI_FRAME_NAME;
|
|
12350
|
+
};
|
|
12351
|
+
var getFrameLikeTitle = (element) => {
|
|
12352
|
+
return element.name === null ? getDefaultFrameName(element) : element.name;
|
|
12353
|
+
};
|
|
12354
|
+
var getElementsOverlappingFrame = (elements, frame, elementsMap) => {
|
|
12355
|
+
return elements.filter(
|
|
12356
|
+
(el) => (
|
|
12357
|
+
// exclude elements which are overlapping, but are in a different frame,
|
|
12358
|
+
// and thus invisible in target frame
|
|
12359
|
+
(!el.frameId || el.frameId === frame.id) && doBoundsIntersect(
|
|
12360
|
+
getElementBounds(el, elementsMap),
|
|
12361
|
+
getElementBounds(frame, elementsMap)
|
|
12362
|
+
)
|
|
12363
|
+
)
|
|
12364
|
+
);
|
|
11679
12365
|
};
|
|
11680
12366
|
var frameAndChildrenSelectedTogether = (selectedElements) => {
|
|
11681
12367
|
const selectedElementsMap = arrayToMap(selectedElements);
|
|
@@ -12367,15 +13053,6 @@ function getFreedrawOutlineAsSegments(element, points, elementsMap) {
|
|
|
12367
13053
|
);
|
|
12368
13054
|
}
|
|
12369
13055
|
|
|
12370
|
-
// ../element/src/comparisons.ts
|
|
12371
|
-
var hasBackground = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "line" || type === "freedraw";
|
|
12372
|
-
var hasStrokeColor = (type) => type === "rectangle" || type === "ellipse" || type === "diamond" || type === "freedraw" || type === "arrow" || type === "line" || type === "text" || type === "embeddable";
|
|
12373
|
-
var hasStrokeWidth = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "freedraw" || type === "arrow" || type === "line";
|
|
12374
|
-
var hasStrokeStyle = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "arrow" || type === "line";
|
|
12375
|
-
var canChangeRoundness = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "line" || type === "diamond" || type === "image";
|
|
12376
|
-
var toolIsArrow = (type) => type === "arrow";
|
|
12377
|
-
var canHaveArrowheads = (type) => type === "arrow";
|
|
12378
|
-
|
|
12379
13056
|
// ../element/src/shape.ts
|
|
12380
13057
|
var _ShapeCache = class _ShapeCache {
|
|
12381
13058
|
};
|
|
@@ -12552,7 +13229,6 @@ var generateArrowheadOutlineCircle = (generator, options, strokeColor, arrowhead
|
|
|
12552
13229
|
return [generator.circle(x, y, diameter * diameterScale, circleOptions)];
|
|
12553
13230
|
};
|
|
12554
13231
|
var getArrowheadShapes = (element, shape, position, arrowhead, generator, options, canvasBackgroundColor, isDarkMode) => {
|
|
12555
|
-
canvasBackgroundColor = canvasBackgroundColor || "transparent";
|
|
12556
13232
|
if (arrowhead === null) {
|
|
12557
13233
|
return [];
|
|
12558
13234
|
}
|
|
@@ -12729,7 +13405,7 @@ var getArrowheadShapes = (element, shape, position, arrowhead, generator, option
|
|
|
12729
13405
|
}
|
|
12730
13406
|
}
|
|
12731
13407
|
};
|
|
12732
|
-
var generateLinearCollisionShape = (element) => {
|
|
13408
|
+
var generateLinearCollisionShape = (element, elementsMap) => {
|
|
12733
13409
|
const generator = new RoughGenerator();
|
|
12734
13410
|
const options = {
|
|
12735
13411
|
seed: element.seed,
|
|
@@ -12738,20 +13414,7 @@ var generateLinearCollisionShape = (element) => {
|
|
|
12738
13414
|
roughness: 0,
|
|
12739
13415
|
preserveVertices: true
|
|
12740
13416
|
};
|
|
12741
|
-
const center =
|
|
12742
|
-
// Need a non-rotated center point
|
|
12743
|
-
element.points.reduce(
|
|
12744
|
-
(acc, point) => {
|
|
12745
|
-
return [
|
|
12746
|
-
Math.min(element.x + point[0], acc[0]),
|
|
12747
|
-
Math.min(element.y + point[1], acc[1]),
|
|
12748
|
-
Math.max(element.x + point[0], acc[2]),
|
|
12749
|
-
Math.max(element.y + point[1], acc[3])
|
|
12750
|
-
];
|
|
12751
|
-
},
|
|
12752
|
-
[Infinity, Infinity, -Infinity, -Infinity]
|
|
12753
|
-
)
|
|
12754
|
-
);
|
|
13417
|
+
const center = elementCenterPoint(element, elementsMap);
|
|
12755
13418
|
switch (element.type) {
|
|
12756
13419
|
case "line":
|
|
12757
13420
|
case "arrow": {
|
|
@@ -13633,7 +14296,7 @@ var getMinMaxXYFromCurvePathOps = (ops, transformXY) => {
|
|
|
13633
14296
|
);
|
|
13634
14297
|
return [minX, minY, maxX, maxY];
|
|
13635
14298
|
};
|
|
13636
|
-
var getBoundsFromPoints = (points) => {
|
|
14299
|
+
var getBoundsFromPoints = (points, padding = 0) => {
|
|
13637
14300
|
let minX = Infinity;
|
|
13638
14301
|
let minY = Infinity;
|
|
13639
14302
|
let maxX = -Infinity;
|
|
@@ -13644,7 +14307,7 @@ var getBoundsFromPoints = (points) => {
|
|
|
13644
14307
|
maxX = Math.max(maxX, x);
|
|
13645
14308
|
maxY = Math.max(maxY, y);
|
|
13646
14309
|
}
|
|
13647
|
-
return [minX, minY, maxX, maxY];
|
|
14310
|
+
return [minX - padding, minY - padding, maxX + padding, maxY + padding];
|
|
13648
14311
|
};
|
|
13649
14312
|
var getFreeDrawElementAbsoluteCoords = (element) => {
|
|
13650
14313
|
const [minX, minY, maxX, maxY] = getBoundsFromPoints(element.points);
|
|
@@ -14028,6 +14691,7 @@ var aabbForElement = (element, elementsMap, offset) => {
|
|
|
14028
14691
|
return bounds;
|
|
14029
14692
|
};
|
|
14030
14693
|
var pointInsideBounds = (p, bounds) => p[0] > bounds[0] && p[0] < bounds[2] && p[1] > bounds[1] && p[1] < bounds[3];
|
|
14694
|
+
var pointInsideBoundsInclusive = (p, bounds) => p[0] >= bounds[0] && p[0] <= bounds[2] && p[1] >= bounds[1] && p[1] <= bounds[3];
|
|
14031
14695
|
var doBoundsIntersect = (bounds1, bounds2) => {
|
|
14032
14696
|
if (bounds1 == null || bounds2 == null) {
|
|
14033
14697
|
return false;
|
|
@@ -14036,8 +14700,14 @@ var doBoundsIntersect = (bounds1, bounds2) => {
|
|
|
14036
14700
|
const [minX2, minY2, maxX2, maxY2] = bounds2;
|
|
14037
14701
|
return minX1 < maxX2 && maxX1 > minX2 && minY1 < maxY2 && maxY1 > minY2;
|
|
14038
14702
|
};
|
|
14703
|
+
var boundsContainBounds = (outerBounds, innerBounds) => [
|
|
14704
|
+
pointFrom(innerBounds[0], innerBounds[1]),
|
|
14705
|
+
pointFrom(innerBounds[0], innerBounds[3]),
|
|
14706
|
+
pointFrom(innerBounds[2], innerBounds[1]),
|
|
14707
|
+
pointFrom(innerBounds[2], innerBounds[3])
|
|
14708
|
+
].every((point) => pointInsideBoundsInclusive(point, outerBounds));
|
|
14039
14709
|
var elementCenterPoint = (element, elementsMap, xOffset = 0, yOffset = 0) => {
|
|
14040
|
-
if (isLinearElement(element)) {
|
|
14710
|
+
if (isLinearElement(element) || isFreeDrawElement(element)) {
|
|
14041
14711
|
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);
|
|
14042
14712
|
const [x3, y3] = pointFrom((x1 + x2) / 2, (y1 + y2) / 2);
|
|
14043
14713
|
return pointFrom(x3 + xOffset, y3 + yOffset);
|
|
@@ -14218,78 +14888,60 @@ var calculateTranslation = (group, selectionBoundingBox, { axis, position }) =>
|
|
|
14218
14888
|
};
|
|
14219
14889
|
|
|
14220
14890
|
// ../element/src/sortElements.ts
|
|
14221
|
-
var
|
|
14222
|
-
const
|
|
14223
|
-
|
|
14224
|
-
const orderInnerGroups = (elements2) => {
|
|
14225
|
-
const firstGroupSig = elements2[0]?.groupIds?.join("");
|
|
14226
|
-
const aGroup = [elements2[0]];
|
|
14227
|
-
const bGroup = [];
|
|
14228
|
-
for (const element of elements2.slice(1)) {
|
|
14229
|
-
if (element.groupIds?.join("") === firstGroupSig) {
|
|
14230
|
-
aGroup.push(element);
|
|
14231
|
-
} else {
|
|
14232
|
-
bGroup.push(element);
|
|
14233
|
-
}
|
|
14234
|
-
}
|
|
14235
|
-
return bGroup.length ? [...aGroup, ...orderInnerGroups(bGroup)] : aGroup;
|
|
14891
|
+
var defragmentGroups = (elements) => {
|
|
14892
|
+
const groupIdAtLevel = (element, level) => {
|
|
14893
|
+
return element.groupIds[element.groupIds.length - level - 1];
|
|
14236
14894
|
};
|
|
14237
|
-
const
|
|
14238
|
-
|
|
14239
|
-
|
|
14240
|
-
|
|
14241
|
-
|
|
14242
|
-
|
|
14243
|
-
|
|
14244
|
-
|
|
14245
|
-
const ret = element2?.groupIds?.some((id) => id === topGroup);
|
|
14246
|
-
if (ret) {
|
|
14247
|
-
groupHandledElements.set(element2.id, true);
|
|
14248
|
-
}
|
|
14249
|
-
return ret;
|
|
14250
|
-
});
|
|
14251
|
-
for (const elem of orderInnerGroups(groupElements)) {
|
|
14252
|
-
sortedElements.add(elem);
|
|
14895
|
+
const orderLevel = (levelElements, level) => {
|
|
14896
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
14897
|
+
const slots = [];
|
|
14898
|
+
for (const element of levelElements) {
|
|
14899
|
+
const groupId = groupIdAtLevel(element, level);
|
|
14900
|
+
if (groupId === void 0) {
|
|
14901
|
+
slots.push(element);
|
|
14902
|
+
continue;
|
|
14253
14903
|
}
|
|
14254
|
-
|
|
14255
|
-
|
|
14904
|
+
let bucket = buckets.get(groupId);
|
|
14905
|
+
if (!bucket) {
|
|
14906
|
+
bucket = [];
|
|
14907
|
+
buckets.set(groupId, bucket);
|
|
14908
|
+
slots.push(groupId);
|
|
14909
|
+
}
|
|
14910
|
+
bucket.push(element);
|
|
14256
14911
|
}
|
|
14257
|
-
|
|
14258
|
-
|
|
14259
|
-
|
|
14912
|
+
return slots.flatMap(
|
|
14913
|
+
(slot) => typeof slot === "string" ? orderLevel(buckets.get(slot), level + 1) : [slot]
|
|
14914
|
+
);
|
|
14915
|
+
};
|
|
14916
|
+
const sortedElements = orderLevel(elements, 0);
|
|
14917
|
+
if (sortedElements.length !== elements.length) {
|
|
14918
|
+
console.error("defragmentGroups: lost some elements... bailing!");
|
|
14260
14919
|
return elements;
|
|
14261
14920
|
}
|
|
14262
|
-
return
|
|
14921
|
+
return sortedElements;
|
|
14263
14922
|
};
|
|
14264
14923
|
var normalizeBoundElementsOrder = (elements) => {
|
|
14265
|
-
const elementsMap =
|
|
14266
|
-
const origElements = elements.slice();
|
|
14924
|
+
const elementsMap = arrayToMap(elements);
|
|
14267
14925
|
const sortedElements = /* @__PURE__ */ new Set();
|
|
14268
|
-
|
|
14269
|
-
if (
|
|
14270
|
-
|
|
14926
|
+
for (const element of elements) {
|
|
14927
|
+
if (sortedElements.has(element)) {
|
|
14928
|
+
continue;
|
|
14271
14929
|
}
|
|
14272
14930
|
if (element.boundElements?.length) {
|
|
14273
14931
|
sortedElements.add(element);
|
|
14274
|
-
|
|
14275
|
-
element.boundElements.forEach((boundElement) => {
|
|
14932
|
+
for (const boundElement of element.boundElements) {
|
|
14276
14933
|
const child = elementsMap.get(boundElement.id);
|
|
14277
14934
|
if (child && boundElement.type === "text") {
|
|
14278
|
-
sortedElements.add(child
|
|
14279
|
-
origElements[child[1]] = null;
|
|
14935
|
+
sortedElements.add(child);
|
|
14280
14936
|
}
|
|
14281
|
-
});
|
|
14282
|
-
} else if (element.type === "text" && element.containerId) {
|
|
14283
|
-
const parent = elementsMap.get(element.containerId);
|
|
14284
|
-
if (!parent?.[0].boundElements?.find((x) => x.id === element.id)) {
|
|
14285
|
-
sortedElements.add(element);
|
|
14286
|
-
origElements[idx] = null;
|
|
14287
14937
|
}
|
|
14288
|
-
|
|
14289
|
-
sortedElements.add(element);
|
|
14290
|
-
origElements[idx] = null;
|
|
14938
|
+
continue;
|
|
14291
14939
|
}
|
|
14292
|
-
|
|
14940
|
+
if (element.type === "text" && element.containerId && elementsMap.get(element.containerId)?.boundElements?.some((el) => el.id === element.id)) {
|
|
14941
|
+
continue;
|
|
14942
|
+
}
|
|
14943
|
+
sortedElements.add(element);
|
|
14944
|
+
}
|
|
14293
14945
|
if (sortedElements.size !== elements.length) {
|
|
14294
14946
|
console.error(
|
|
14295
14947
|
"normalizeBoundElementsOrder: lost some elements... bailing!"
|
|
@@ -14299,7 +14951,7 @@ var normalizeBoundElementsOrder = (elements) => {
|
|
|
14299
14951
|
return [...sortedElements];
|
|
14300
14952
|
};
|
|
14301
14953
|
var normalizeElementOrder = (elements) => {
|
|
14302
|
-
return normalizeBoundElementsOrder(
|
|
14954
|
+
return normalizeBoundElementsOrder(defragmentGroups(elements));
|
|
14303
14955
|
};
|
|
14304
14956
|
|
|
14305
14957
|
// ../element/src/duplicate.ts
|
|
@@ -14341,6 +14993,7 @@ var duplicateElements = (opts) => {
|
|
|
14341
14993
|
const duplicateElementsMap = /* @__PURE__ */ new Map();
|
|
14342
14994
|
const elementsMap = arrayToMap(elements);
|
|
14343
14995
|
const _idsOfElementsToDuplicate = opts.type === "in-place" ? opts.idsOfElementsToDuplicate : new Map(elements.map((el) => [el.id, el]));
|
|
14996
|
+
const preserveFrameChildrenOrder = opts.type === "everything" && opts.preserveFrameChildrenOrder;
|
|
14344
14997
|
if (opts.type === "in-place") {
|
|
14345
14998
|
for (const groupId of Object.keys(opts.appState.selectedGroupIds)) {
|
|
14346
14999
|
elements.filter((el) => el.groupIds?.includes(groupId)).forEach((el) => _idsOfElementsToDuplicate.set(el.id, el));
|
|
@@ -14400,7 +15053,7 @@ var duplicateElements = (opts) => {
|
|
|
14400
15053
|
const groupId = getSelectedGroupForElement(appState, element);
|
|
14401
15054
|
if (groupId) {
|
|
14402
15055
|
const groupElements = getElementsInGroup(elements, groupId).flatMap(
|
|
14403
|
-
(element2) => isFrameLikeElement(element2) ? [...getFrameChildren(elements, element2.id), element2] : [element2]
|
|
15056
|
+
(element2) => isFrameLikeElement(element2) && !preserveFrameChildrenOrder ? [...getFrameChildren(elements, element2.id), element2] : [element2]
|
|
14404
15057
|
);
|
|
14405
15058
|
const targetIndex = findLastIndex(elementsWithDuplicates, (el) => {
|
|
14406
15059
|
return el.groupIds?.includes(groupId);
|
|
@@ -14408,11 +15061,18 @@ var duplicateElements = (opts) => {
|
|
|
14408
15061
|
insertBeforeOrAfterIndex(targetIndex, copyElements(groupElements));
|
|
14409
15062
|
continue;
|
|
14410
15063
|
}
|
|
14411
|
-
if (element.frameId && frameIdsToDuplicate.has(element.frameId)) {
|
|
15064
|
+
if (!preserveFrameChildrenOrder && element.frameId && frameIdsToDuplicate.has(element.frameId)) {
|
|
14412
15065
|
continue;
|
|
14413
15066
|
}
|
|
14414
15067
|
if (isFrameLikeElement(element)) {
|
|
14415
15068
|
const frameId = element.id;
|
|
15069
|
+
if (preserveFrameChildrenOrder) {
|
|
15070
|
+
insertBeforeOrAfterIndex(
|
|
15071
|
+
findLastIndex(elementsWithDuplicates, (el) => el.id === frameId),
|
|
15072
|
+
copyElements(element)
|
|
15073
|
+
);
|
|
15074
|
+
continue;
|
|
15075
|
+
}
|
|
14416
15076
|
const frameChildren = getFrameChildren(elements, frameId);
|
|
14417
15077
|
const targetIndex = findLastIndex(elementsWithDuplicates, (el) => {
|
|
14418
15078
|
return el.frameId === frameId || el.id === frameId;
|
|
@@ -14839,602 +15499,359 @@ var StoreDelta = class _StoreDelta {
|
|
|
14839
15499
|
/**
|
|
14840
15500
|
* Create a new instance of `StoreDelta`.
|
|
14841
15501
|
*/
|
|
14842
|
-
static create(elements, appState, opts = {
|
|
14843
|
-
id: randomId()
|
|
14844
|
-
}) {
|
|
14845
|
-
return new this(opts.id, elements, appState);
|
|
14846
|
-
}
|
|
14847
|
-
/**
|
|
14848
|
-
* Calculate the delta between the previous and next snapshot.
|
|
14849
|
-
*/
|
|
14850
|
-
static calculate(prevSnapshot, nextSnapshot) {
|
|
14851
|
-
const elementsDelta = nextSnapshot.metadata.didElementsChange ? ElementsDelta.calculate(prevSnapshot.elements, nextSnapshot.elements) : ElementsDelta.empty();
|
|
14852
|
-
const appStateDelta = nextSnapshot.metadata.didAppStateChange ? AppStateDelta.calculate(prevSnapshot.appState, nextSnapshot.appState) : AppStateDelta.empty();
|
|
14853
|
-
return this.create(elementsDelta, appStateDelta);
|
|
14854
|
-
}
|
|
14855
|
-
/**
|
|
14856
|
-
* Restore a store delta instance from a DTO.
|
|
14857
|
-
*/
|
|
14858
|
-
static restore(storeDeltaDTO) {
|
|
14859
|
-
const { id, elements, appState } = storeDeltaDTO;
|
|
14860
|
-
return new this(
|
|
14861
|
-
id,
|
|
14862
|
-
ElementsDelta.restore(elements),
|
|
14863
|
-
AppStateDelta.restore(appState)
|
|
14864
|
-
);
|
|
14865
|
-
}
|
|
14866
|
-
/**
|
|
14867
|
-
* Parse and load the delta from the remote payload.
|
|
14868
|
-
*/
|
|
14869
|
-
static load({
|
|
14870
|
-
id,
|
|
14871
|
-
elements: { added, removed, updated },
|
|
14872
|
-
appState: { delta: appStateDelta }
|
|
14873
|
-
}) {
|
|
14874
|
-
const elements = ElementsDelta.create(added, removed, updated);
|
|
14875
|
-
const appState = AppStateDelta.create(appStateDelta);
|
|
14876
|
-
return new this(id, elements, appState);
|
|
14877
|
-
}
|
|
14878
|
-
/**
|
|
14879
|
-
* Squash the passed deltas into the aggregated delta instance.
|
|
14880
|
-
*/
|
|
14881
|
-
static squash(...deltas) {
|
|
14882
|
-
const aggregatedDelta = _StoreDelta.empty();
|
|
14883
|
-
for (const delta of deltas) {
|
|
14884
|
-
aggregatedDelta.elements.squash(delta.elements);
|
|
14885
|
-
aggregatedDelta.appState.squash(delta.appState);
|
|
14886
|
-
}
|
|
14887
|
-
return aggregatedDelta;
|
|
14888
|
-
}
|
|
14889
|
-
/**
|
|
14890
|
-
* Inverse store delta, creates new instance of `StoreDelta`.
|
|
14891
|
-
*/
|
|
14892
|
-
static inverse(delta) {
|
|
14893
|
-
return this.create(delta.elements.inverse(), delta.appState.inverse());
|
|
14894
|
-
}
|
|
14895
|
-
/**
|
|
14896
|
-
* Apply the delta to the passed elements and appState, does not modify the snapshot.
|
|
14897
|
-
*/
|
|
14898
|
-
static applyTo(delta, elements, appState, options) {
|
|
14899
|
-
const [nextElements, elementsContainVisibleChange] = delta.elements.applyTo(
|
|
14900
|
-
elements,
|
|
14901
|
-
StoreSnapshot.empty().elements,
|
|
14902
|
-
options
|
|
14903
|
-
);
|
|
14904
|
-
const [nextAppState, appStateContainsVisibleChange] = delta.appState.applyTo(appState, nextElements);
|
|
14905
|
-
const appliedVisibleChanges = elementsContainVisibleChange || appStateContainsVisibleChange;
|
|
14906
|
-
return [nextElements, nextAppState, appliedVisibleChanges];
|
|
14907
|
-
}
|
|
14908
|
-
/**
|
|
14909
|
-
* Apply latest (remote) changes to the delta, creates new instance of `StoreDelta`.
|
|
14910
|
-
*/
|
|
14911
|
-
static applyLatestChanges(delta, prevElements, nextElements, modifierOptions) {
|
|
14912
|
-
return this.create(
|
|
14913
|
-
delta.elements.applyLatestChanges(
|
|
14914
|
-
prevElements,
|
|
14915
|
-
nextElements,
|
|
14916
|
-
modifierOptions
|
|
14917
|
-
),
|
|
14918
|
-
delta.appState,
|
|
14919
|
-
{
|
|
14920
|
-
id: delta.id
|
|
14921
|
-
}
|
|
14922
|
-
);
|
|
14923
|
-
}
|
|
14924
|
-
static empty() {
|
|
14925
|
-
return _StoreDelta.create(ElementsDelta.empty(), AppStateDelta.empty());
|
|
14926
|
-
}
|
|
14927
|
-
isEmpty() {
|
|
14928
|
-
return this.elements.isEmpty() && this.appState.isEmpty();
|
|
14929
|
-
}
|
|
14930
|
-
};
|
|
14931
|
-
var StoreSnapshot = class _StoreSnapshot {
|
|
14932
|
-
constructor(elements, appState, metadata = {
|
|
14933
|
-
didElementsChange: false,
|
|
14934
|
-
didAppStateChange: false,
|
|
14935
|
-
isEmpty: false
|
|
14936
|
-
}) {
|
|
14937
|
-
this.elements = elements;
|
|
14938
|
-
this.appState = appState;
|
|
14939
|
-
this.metadata = metadata;
|
|
14940
|
-
__publicField(this, "_lastChangedElementsHash", 0);
|
|
14941
|
-
__publicField(this, "_lastChangedAppStateHash", 0);
|
|
14942
|
-
}
|
|
14943
|
-
static create(elements, appState, metadata = {
|
|
14944
|
-
didElementsChange: false,
|
|
14945
|
-
didAppStateChange: false
|
|
14946
|
-
}) {
|
|
14947
|
-
return new _StoreSnapshot(
|
|
14948
|
-
elements,
|
|
14949
|
-
isObservedAppState(appState) ? appState : getObservedAppState(appState),
|
|
14950
|
-
metadata
|
|
14951
|
-
);
|
|
14952
|
-
}
|
|
14953
|
-
static empty() {
|
|
14954
|
-
return new _StoreSnapshot(
|
|
14955
|
-
/* @__PURE__ */ new Map(),
|
|
14956
|
-
getDefaultObservedAppState(),
|
|
14957
|
-
{
|
|
14958
|
-
didElementsChange: false,
|
|
14959
|
-
didAppStateChange: false,
|
|
14960
|
-
isEmpty: true
|
|
14961
|
-
}
|
|
14962
|
-
);
|
|
14963
|
-
}
|
|
14964
|
-
getChangedElements(prevSnapshot) {
|
|
14965
|
-
const changedElements = {};
|
|
14966
|
-
for (const prevElement of toIterable(prevSnapshot.elements)) {
|
|
14967
|
-
const nextElement = this.elements.get(prevElement.id);
|
|
14968
|
-
if (!nextElement) {
|
|
14969
|
-
changedElements[prevElement.id] = newElementWith(prevElement, {
|
|
14970
|
-
isDeleted: true
|
|
14971
|
-
});
|
|
14972
|
-
}
|
|
14973
|
-
}
|
|
14974
|
-
for (const nextElement of toIterable(this.elements)) {
|
|
14975
|
-
if (prevSnapshot.elements.get(nextElement.id) !== nextElement) {
|
|
14976
|
-
changedElements[nextElement.id] = nextElement;
|
|
14977
|
-
}
|
|
14978
|
-
}
|
|
14979
|
-
return changedElements;
|
|
14980
|
-
}
|
|
14981
|
-
getChangedAppState(prevSnapshot) {
|
|
14982
|
-
return Delta.getRightDifferences(
|
|
14983
|
-
prevSnapshot.appState,
|
|
14984
|
-
this.appState
|
|
14985
|
-
).reduce(
|
|
14986
|
-
(acc, key) => Object.assign(acc, {
|
|
14987
|
-
[key]: this.appState[key]
|
|
14988
|
-
}),
|
|
14989
|
-
{}
|
|
14990
|
-
);
|
|
14991
|
-
}
|
|
14992
|
-
isEmpty() {
|
|
14993
|
-
return this.metadata.isEmpty;
|
|
15502
|
+
static create(elements, appState, opts = {
|
|
15503
|
+
id: randomId()
|
|
15504
|
+
}) {
|
|
15505
|
+
return new this(opts.id, elements, appState);
|
|
14994
15506
|
}
|
|
14995
15507
|
/**
|
|
14996
|
-
*
|
|
15508
|
+
* Calculate the delta between the previous and next snapshot.
|
|
14997
15509
|
*/
|
|
14998
|
-
|
|
14999
|
-
const
|
|
15000
|
-
|
|
15001
|
-
|
|
15002
|
-
}
|
|
15003
|
-
const nextAppState = getObservedAppState({
|
|
15004
|
-
...this.appState,
|
|
15005
|
-
...change.appState
|
|
15006
|
-
});
|
|
15007
|
-
return _StoreSnapshot.create(nextElements, nextAppState, {
|
|
15008
|
-
// by default we assume that change is different from what we have in the snapshot
|
|
15009
|
-
// so that we trigger the delta calculation and if it isn't different, delta will be empty
|
|
15010
|
-
didElementsChange: Object.keys(change.elements).length > 0,
|
|
15011
|
-
didAppStateChange: Object.keys(change.appState).length > 0
|
|
15012
|
-
});
|
|
15510
|
+
static calculate(prevSnapshot, nextSnapshot) {
|
|
15511
|
+
const elementsDelta = nextSnapshot.metadata.didElementsChange ? ElementsDelta.calculate(prevSnapshot.elements, nextSnapshot.elements) : ElementsDelta.empty();
|
|
15512
|
+
const appStateDelta = nextSnapshot.metadata.didAppStateChange ? AppStateDelta.calculate(prevSnapshot.appState, nextSnapshot.appState) : AppStateDelta.empty();
|
|
15513
|
+
return this.create(elementsDelta, appStateDelta);
|
|
15013
15514
|
}
|
|
15014
15515
|
/**
|
|
15015
|
-
*
|
|
15016
|
-
*
|
|
15017
|
-
* @returns same instance if there are no changes detected, new instance otherwise.
|
|
15516
|
+
* Restore a store delta instance from a DTO.
|
|
15018
15517
|
*/
|
|
15019
|
-
|
|
15020
|
-
const
|
|
15021
|
-
|
|
15022
|
-
|
|
15023
|
-
|
|
15024
|
-
|
|
15025
|
-
}
|
|
15026
|
-
const nextElementsSnapshot = this.maybeCreateElementsSnapshot(
|
|
15027
|
-
elements,
|
|
15028
|
-
options
|
|
15029
|
-
);
|
|
15030
|
-
const nextAppStateSnapshot = this.maybeCreateAppStateSnapshot(
|
|
15031
|
-
appState,
|
|
15032
|
-
options
|
|
15033
|
-
);
|
|
15034
|
-
let didElementsChange = false;
|
|
15035
|
-
let didAppStateChange = false;
|
|
15036
|
-
if (this.elements !== nextElementsSnapshot) {
|
|
15037
|
-
didElementsChange = true;
|
|
15038
|
-
}
|
|
15039
|
-
if (this.appState !== nextAppStateSnapshot) {
|
|
15040
|
-
didAppStateChange = true;
|
|
15041
|
-
}
|
|
15042
|
-
if (!didElementsChange && !didAppStateChange) {
|
|
15043
|
-
return this;
|
|
15044
|
-
}
|
|
15045
|
-
const snapshot = new _StoreSnapshot(
|
|
15046
|
-
nextElementsSnapshot,
|
|
15047
|
-
nextAppStateSnapshot,
|
|
15048
|
-
{
|
|
15049
|
-
didElementsChange,
|
|
15050
|
-
didAppStateChange
|
|
15051
|
-
}
|
|
15518
|
+
static restore(storeDeltaDTO) {
|
|
15519
|
+
const { id, elements, appState } = storeDeltaDTO;
|
|
15520
|
+
return new this(
|
|
15521
|
+
id,
|
|
15522
|
+
ElementsDelta.restore(elements),
|
|
15523
|
+
AppStateDelta.restore(appState)
|
|
15052
15524
|
);
|
|
15053
|
-
return snapshot;
|
|
15054
15525
|
}
|
|
15055
|
-
|
|
15056
|
-
|
|
15526
|
+
/**
|
|
15527
|
+
* Parse and load the delta from the remote payload.
|
|
15528
|
+
*/
|
|
15529
|
+
static load({
|
|
15530
|
+
id,
|
|
15531
|
+
elements: { added, removed, updated },
|
|
15532
|
+
appState: { delta: appStateDelta }
|
|
15057
15533
|
}) {
|
|
15058
|
-
|
|
15059
|
-
|
|
15060
|
-
|
|
15061
|
-
const nextAppStateSnapshot = !isObservedAppState(appState) ? getObservedAppState(appState) : appState;
|
|
15062
|
-
const didAppStateChange = this.detectChangedAppState(
|
|
15063
|
-
nextAppStateSnapshot,
|
|
15064
|
-
options
|
|
15065
|
-
);
|
|
15066
|
-
if (!didAppStateChange) {
|
|
15067
|
-
return this.appState;
|
|
15068
|
-
}
|
|
15069
|
-
return nextAppStateSnapshot;
|
|
15534
|
+
const elements = ElementsDelta.create(added, removed, updated);
|
|
15535
|
+
const appState = AppStateDelta.create(appStateDelta);
|
|
15536
|
+
return new this(id, elements, appState);
|
|
15070
15537
|
}
|
|
15071
|
-
|
|
15072
|
-
|
|
15073
|
-
|
|
15074
|
-
|
|
15075
|
-
|
|
15076
|
-
|
|
15077
|
-
|
|
15078
|
-
|
|
15079
|
-
return this.elements;
|
|
15538
|
+
/**
|
|
15539
|
+
* Squash the passed deltas into the aggregated delta instance.
|
|
15540
|
+
*/
|
|
15541
|
+
static squash(...deltas) {
|
|
15542
|
+
const aggregatedDelta = _StoreDelta.empty();
|
|
15543
|
+
for (const delta of deltas) {
|
|
15544
|
+
aggregatedDelta.elements.squash(delta.elements);
|
|
15545
|
+
aggregatedDelta.appState.squash(delta.appState);
|
|
15080
15546
|
}
|
|
15081
|
-
|
|
15082
|
-
return elementsSnapshot;
|
|
15547
|
+
return aggregatedDelta;
|
|
15083
15548
|
}
|
|
15084
|
-
|
|
15085
|
-
|
|
15086
|
-
|
|
15087
|
-
|
|
15088
|
-
|
|
15089
|
-
}
|
|
15090
|
-
const didAppStateChange = Delta.isRightDifferent(
|
|
15091
|
-
this.appState,
|
|
15092
|
-
nextObservedAppState
|
|
15093
|
-
);
|
|
15094
|
-
if (!didAppStateChange) {
|
|
15095
|
-
return;
|
|
15096
|
-
}
|
|
15097
|
-
const changedAppStateHash = hashString(
|
|
15098
|
-
JSON.stringify(nextObservedAppState)
|
|
15099
|
-
);
|
|
15100
|
-
if (options.shouldCompareHashes && this._lastChangedAppStateHash === changedAppStateHash) {
|
|
15101
|
-
return;
|
|
15102
|
-
}
|
|
15103
|
-
this._lastChangedAppStateHash = changedAppStateHash;
|
|
15104
|
-
return didAppStateChange;
|
|
15549
|
+
/**
|
|
15550
|
+
* Inverse store delta, creates new instance of `StoreDelta`.
|
|
15551
|
+
*/
|
|
15552
|
+
static inverse(delta) {
|
|
15553
|
+
return this.create(delta.elements.inverse(), delta.appState.inverse());
|
|
15105
15554
|
}
|
|
15106
15555
|
/**
|
|
15107
|
-
*
|
|
15556
|
+
* Apply the delta to the passed elements and appState, does not modify the snapshot.
|
|
15108
15557
|
*/
|
|
15109
|
-
|
|
15110
|
-
|
|
15111
|
-
|
|
15112
|
-
|
|
15113
|
-
|
|
15114
|
-
|
|
15115
|
-
const
|
|
15116
|
-
|
|
15117
|
-
|
|
15118
|
-
if (!nextElement) {
|
|
15119
|
-
changedElements.set(
|
|
15120
|
-
prevElement.id,
|
|
15121
|
-
newElementWith(prevElement, { isDeleted: true })
|
|
15122
|
-
);
|
|
15123
|
-
}
|
|
15124
|
-
}
|
|
15125
|
-
for (const nextElement of toIterable(nextElements)) {
|
|
15126
|
-
const prevElement = this.elements.get(nextElement.id);
|
|
15127
|
-
if (!prevElement || // element was added
|
|
15128
|
-
prevElement.version < nextElement.version) {
|
|
15129
|
-
if (isImageElement(nextElement) && !isInitializedImageElement(nextElement)) {
|
|
15130
|
-
continue;
|
|
15131
|
-
}
|
|
15132
|
-
changedElements.set(nextElement.id, nextElement);
|
|
15133
|
-
}
|
|
15134
|
-
}
|
|
15135
|
-
if (!changedElements.size) {
|
|
15136
|
-
return;
|
|
15137
|
-
}
|
|
15138
|
-
const changedElementsHash = hashElementsVersion(changedElements);
|
|
15139
|
-
if (options.shouldCompareHashes && this._lastChangedElementsHash === changedElementsHash) {
|
|
15140
|
-
return;
|
|
15141
|
-
}
|
|
15142
|
-
this._lastChangedElementsHash = changedElementsHash;
|
|
15143
|
-
return changedElements;
|
|
15558
|
+
static applyTo(delta, elements, appState, options) {
|
|
15559
|
+
const [nextElements, elementsContainVisibleChange] = delta.elements.applyTo(
|
|
15560
|
+
elements,
|
|
15561
|
+
StoreSnapshot.empty().elements,
|
|
15562
|
+
options
|
|
15563
|
+
);
|
|
15564
|
+
const [nextAppState, appStateContainsVisibleChange] = delta.appState.applyTo(appState, nextElements);
|
|
15565
|
+
const appliedVisibleChanges = elementsContainVisibleChange || appStateContainsVisibleChange;
|
|
15566
|
+
return [nextElements, nextAppState, appliedVisibleChanges];
|
|
15144
15567
|
}
|
|
15145
15568
|
/**
|
|
15146
|
-
*
|
|
15569
|
+
* Apply latest (remote) changes to the delta, creates new instance of `StoreDelta`.
|
|
15147
15570
|
*/
|
|
15148
|
-
|
|
15149
|
-
|
|
15150
|
-
|
|
15151
|
-
|
|
15152
|
-
|
|
15153
|
-
|
|
15154
|
-
|
|
15155
|
-
|
|
15156
|
-
|
|
15571
|
+
static applyLatestChanges(delta, prevElements, nextElements, modifierOptions) {
|
|
15572
|
+
return this.create(
|
|
15573
|
+
delta.elements.applyLatestChanges(
|
|
15574
|
+
prevElements,
|
|
15575
|
+
nextElements,
|
|
15576
|
+
modifierOptions
|
|
15577
|
+
),
|
|
15578
|
+
delta.appState,
|
|
15579
|
+
{
|
|
15580
|
+
id: delta.id
|
|
15581
|
+
}
|
|
15582
|
+
);
|
|
15157
15583
|
}
|
|
15158
|
-
|
|
15159
|
-
|
|
15160
|
-
|
|
15161
|
-
|
|
15162
|
-
|
|
15163
|
-
editingGroupId: null,
|
|
15164
|
-
viewBackgroundColor: COLOR_PALETTE.white,
|
|
15165
|
-
selectedElementIds: {},
|
|
15166
|
-
selectedGroupIds: {},
|
|
15167
|
-
selectedLinearElement: null,
|
|
15168
|
-
croppingElementId: null,
|
|
15169
|
-
activeLockedId: null,
|
|
15170
|
-
lockedMultiSelections: {}
|
|
15171
|
-
};
|
|
15172
|
-
};
|
|
15173
|
-
var getObservedAppState = (appState) => {
|
|
15174
|
-
const observedAppState = {
|
|
15175
|
-
name: appState.name,
|
|
15176
|
-
editingGroupId: appState.editingGroupId,
|
|
15177
|
-
viewBackgroundColor: appState.viewBackgroundColor,
|
|
15178
|
-
selectedElementIds: appState.selectedElementIds,
|
|
15179
|
-
selectedGroupIds: appState.selectedGroupIds,
|
|
15180
|
-
croppingElementId: appState.croppingElementId,
|
|
15181
|
-
activeLockedId: appState.activeLockedId,
|
|
15182
|
-
lockedMultiSelections: appState.lockedMultiSelections,
|
|
15183
|
-
selectedLinearElement: appState.selectedLinearElement ? {
|
|
15184
|
-
elementId: appState.selectedLinearElement.elementId,
|
|
15185
|
-
isEditing: !!appState.selectedLinearElement.isEditing
|
|
15186
|
-
} : null
|
|
15187
|
-
};
|
|
15188
|
-
Reflect.defineProperty(observedAppState, hiddenObservedAppStateProp, {
|
|
15189
|
-
value: true,
|
|
15190
|
-
enumerable: false
|
|
15191
|
-
});
|
|
15192
|
-
return observedAppState;
|
|
15193
|
-
};
|
|
15194
|
-
var isObservedAppState = (appState) => !!Reflect.get(appState, hiddenObservedAppStateProp);
|
|
15195
|
-
|
|
15196
|
-
// ../element/src/fractionalIndex.ts
|
|
15197
|
-
import { generateNKeysBetween } from "fractional-indexing";
|
|
15198
|
-
var InvalidFractionalIndexError = class extends Error {
|
|
15199
|
-
constructor() {
|
|
15200
|
-
super(...arguments);
|
|
15201
|
-
__publicField(this, "code", "ELEMENT_HAS_INVALID_INDEX");
|
|
15584
|
+
static empty() {
|
|
15585
|
+
return _StoreDelta.create(ElementsDelta.empty(), AppStateDelta.empty());
|
|
15586
|
+
}
|
|
15587
|
+
isEmpty() {
|
|
15588
|
+
return this.elements.isEmpty() && this.appState.isEmpty();
|
|
15202
15589
|
}
|
|
15203
15590
|
};
|
|
15204
|
-
var
|
|
15205
|
-
|
|
15206
|
-
|
|
15207
|
-
|
|
15208
|
-
|
|
15209
|
-
})
|
|
15210
|
-
|
|
15211
|
-
|
|
15212
|
-
|
|
15213
|
-
|
|
15214
|
-
|
|
15215
|
-
|
|
15216
|
-
|
|
15217
|
-
|
|
15218
|
-
|
|
15219
|
-
|
|
15220
|
-
|
|
15221
|
-
|
|
15222
|
-
|
|
15223
|
-
|
|
15591
|
+
var StoreSnapshot = class _StoreSnapshot {
|
|
15592
|
+
constructor(elements, appState, metadata = {
|
|
15593
|
+
didElementsChange: false,
|
|
15594
|
+
didAppStateChange: false,
|
|
15595
|
+
isEmpty: false
|
|
15596
|
+
}) {
|
|
15597
|
+
this.elements = elements;
|
|
15598
|
+
this.appState = appState;
|
|
15599
|
+
this.metadata = metadata;
|
|
15600
|
+
__publicField(this, "_lastChangedElementsHash", 0);
|
|
15601
|
+
__publicField(this, "_lastChangedAppStateHash", 0);
|
|
15602
|
+
}
|
|
15603
|
+
static create(elements, appState, metadata = {
|
|
15604
|
+
didElementsChange: false,
|
|
15605
|
+
didAppStateChange: false
|
|
15606
|
+
}) {
|
|
15607
|
+
return new _StoreSnapshot(
|
|
15608
|
+
elements,
|
|
15609
|
+
isObservedAppState(appState) ? appState : getObservedAppState(appState),
|
|
15610
|
+
metadata
|
|
15611
|
+
);
|
|
15612
|
+
}
|
|
15613
|
+
static empty() {
|
|
15614
|
+
return new _StoreSnapshot(
|
|
15615
|
+
/* @__PURE__ */ new Map(),
|
|
15616
|
+
getDefaultObservedAppState(),
|
|
15617
|
+
{
|
|
15618
|
+
didElementsChange: false,
|
|
15619
|
+
didAppStateChange: false,
|
|
15620
|
+
isEmpty: true
|
|
15621
|
+
}
|
|
15622
|
+
);
|
|
15623
|
+
}
|
|
15624
|
+
getChangedElements(prevSnapshot) {
|
|
15625
|
+
const changedElements = {};
|
|
15626
|
+
for (const prevElement of toIterable(prevSnapshot.elements)) {
|
|
15627
|
+
const nextElement = this.elements.get(prevElement.id);
|
|
15628
|
+
if (!nextElement) {
|
|
15629
|
+
changedElements[prevElement.id] = newElementWith(prevElement, {
|
|
15630
|
+
isDeleted: true
|
|
15631
|
+
});
|
|
15632
|
+
}
|
|
15224
15633
|
}
|
|
15225
|
-
|
|
15226
|
-
|
|
15227
|
-
|
|
15228
|
-
if (text && text.index <= container.index) {
|
|
15229
|
-
errorMessages.push(
|
|
15230
|
-
`Fractional indices invariant for bound elements has been compromised: "${stringifyElement(
|
|
15231
|
-
text
|
|
15232
|
-
)}", "${stringifyElement(container)}"`
|
|
15233
|
-
);
|
|
15634
|
+
for (const nextElement of toIterable(this.elements)) {
|
|
15635
|
+
if (prevSnapshot.elements.get(nextElement.id) !== nextElement) {
|
|
15636
|
+
changedElements[nextElement.id] = nextElement;
|
|
15234
15637
|
}
|
|
15235
15638
|
}
|
|
15639
|
+
return changedElements;
|
|
15236
15640
|
}
|
|
15237
|
-
|
|
15238
|
-
|
|
15239
|
-
|
|
15240
|
-
|
|
15241
|
-
|
|
15242
|
-
|
|
15243
|
-
|
|
15244
|
-
)
|
|
15245
|
-
|
|
15246
|
-
|
|
15247
|
-
|
|
15641
|
+
getChangedAppState(prevSnapshot) {
|
|
15642
|
+
return Delta.getRightDifferences(
|
|
15643
|
+
prevSnapshot.appState,
|
|
15644
|
+
this.appState
|
|
15645
|
+
).reduce(
|
|
15646
|
+
(acc, key) => Object.assign(acc, {
|
|
15647
|
+
[key]: this.appState[key]
|
|
15648
|
+
}),
|
|
15649
|
+
{}
|
|
15650
|
+
);
|
|
15651
|
+
}
|
|
15652
|
+
isEmpty() {
|
|
15653
|
+
return this.metadata.isEmpty;
|
|
15654
|
+
}
|
|
15655
|
+
/**
|
|
15656
|
+
* Apply the change and return a new snapshot instance.
|
|
15657
|
+
*/
|
|
15658
|
+
applyChange(change) {
|
|
15659
|
+
const nextElements = new Map(this.elements);
|
|
15660
|
+
for (const [id, changedElement] of Object.entries(change.elements)) {
|
|
15661
|
+
nextElements.set(id, changedElement);
|
|
15248
15662
|
}
|
|
15249
|
-
|
|
15250
|
-
|
|
15251
|
-
|
|
15252
|
-
|
|
15253
|
-
|
|
15254
|
-
|
|
15255
|
-
|
|
15663
|
+
const nextAppState = getObservedAppState({
|
|
15664
|
+
...this.appState,
|
|
15665
|
+
...change.appState
|
|
15666
|
+
});
|
|
15667
|
+
return _StoreSnapshot.create(nextElements, nextAppState, {
|
|
15668
|
+
// by default we assume that change is different from what we have in the snapshot
|
|
15669
|
+
// so that we trigger the delta calculation and if it isn't different, delta will be empty
|
|
15670
|
+
didElementsChange: Object.keys(change.elements).length > 0,
|
|
15671
|
+
didAppStateChange: Object.keys(change.appState).length > 0
|
|
15672
|
+
});
|
|
15673
|
+
}
|
|
15674
|
+
/**
|
|
15675
|
+
* Efficiently clone the existing snapshot, only if we detected changes.
|
|
15676
|
+
*
|
|
15677
|
+
* @returns same instance if there are no changes detected, new instance otherwise.
|
|
15678
|
+
*/
|
|
15679
|
+
maybeClone(action, elements, appState) {
|
|
15680
|
+
const options = {
|
|
15681
|
+
shouldCompareHashes: false
|
|
15682
|
+
};
|
|
15683
|
+
if (action === CaptureUpdateAction.EVENTUALLY) {
|
|
15684
|
+
options.shouldCompareHashes = true;
|
|
15256
15685
|
}
|
|
15257
|
-
|
|
15258
|
-
|
|
15686
|
+
const nextElementsSnapshot = this.maybeCreateElementsSnapshot(
|
|
15687
|
+
elements,
|
|
15688
|
+
options
|
|
15689
|
+
);
|
|
15690
|
+
const nextAppStateSnapshot = this.maybeCreateAppStateSnapshot(
|
|
15691
|
+
appState,
|
|
15692
|
+
options
|
|
15693
|
+
);
|
|
15694
|
+
let didElementsChange = false;
|
|
15695
|
+
let didAppStateChange = false;
|
|
15696
|
+
if (this.elements !== nextElementsSnapshot) {
|
|
15697
|
+
didElementsChange = true;
|
|
15259
15698
|
}
|
|
15260
|
-
|
|
15261
|
-
|
|
15262
|
-
var orderByFractionalIndex = (elements) => {
|
|
15263
|
-
return elements.sort((a, b) => {
|
|
15264
|
-
if (isOrderedElement(a) && isOrderedElement(b)) {
|
|
15265
|
-
if (a.index < b.index) {
|
|
15266
|
-
return -1;
|
|
15267
|
-
} else if (a.index > b.index) {
|
|
15268
|
-
return 1;
|
|
15269
|
-
}
|
|
15270
|
-
return a.id < b.id ? -1 : 1;
|
|
15699
|
+
if (this.appState !== nextAppStateSnapshot) {
|
|
15700
|
+
didAppStateChange = true;
|
|
15271
15701
|
}
|
|
15272
|
-
|
|
15273
|
-
|
|
15274
|
-
}
|
|
15275
|
-
|
|
15276
|
-
|
|
15277
|
-
|
|
15278
|
-
const indicesGroups = getMovedIndicesGroups(elements, movedElements);
|
|
15279
|
-
const elementsUpdates = generateIndices(elements, indicesGroups);
|
|
15280
|
-
const elementsCandidates = elements.map((x) => {
|
|
15281
|
-
const elementUpdates = elementsUpdates.get(x);
|
|
15282
|
-
if (elementUpdates) {
|
|
15283
|
-
return { ...x, index: elementUpdates.index };
|
|
15284
|
-
}
|
|
15285
|
-
return x;
|
|
15286
|
-
});
|
|
15287
|
-
validateFractionalIndices(
|
|
15288
|
-
elementsCandidates,
|
|
15289
|
-
// we don't autofix invalid bound text indices, hence don't include it in the validation
|
|
15702
|
+
if (!didElementsChange && !didAppStateChange) {
|
|
15703
|
+
return this;
|
|
15704
|
+
}
|
|
15705
|
+
const snapshot = new _StoreSnapshot(
|
|
15706
|
+
nextElementsSnapshot,
|
|
15707
|
+
nextAppStateSnapshot,
|
|
15290
15708
|
{
|
|
15291
|
-
|
|
15292
|
-
|
|
15293
|
-
ignoreLogs: true
|
|
15709
|
+
didElementsChange,
|
|
15710
|
+
didAppStateChange
|
|
15294
15711
|
}
|
|
15295
15712
|
);
|
|
15296
|
-
|
|
15297
|
-
mutateElement(element, elementsMap, { index });
|
|
15298
|
-
}
|
|
15299
|
-
} catch (e) {
|
|
15300
|
-
syncInvalidIndices(elements);
|
|
15301
|
-
}
|
|
15302
|
-
return elements;
|
|
15303
|
-
};
|
|
15304
|
-
var syncInvalidIndices = (elements) => {
|
|
15305
|
-
const elementsMap = arrayToMap(elements);
|
|
15306
|
-
const indicesGroups = getInvalidIndicesGroups(elements);
|
|
15307
|
-
const elementsUpdates = generateIndices(elements, indicesGroups);
|
|
15308
|
-
for (const [element, { index }] of elementsUpdates) {
|
|
15309
|
-
mutateElement(element, elementsMap, { index });
|
|
15713
|
+
return snapshot;
|
|
15310
15714
|
}
|
|
15311
|
-
|
|
15312
|
-
|
|
15313
|
-
|
|
15314
|
-
|
|
15315
|
-
|
|
15316
|
-
|
|
15317
|
-
|
|
15318
|
-
|
|
15715
|
+
maybeCreateAppStateSnapshot(appState, options = {
|
|
15716
|
+
shouldCompareHashes: false
|
|
15717
|
+
}) {
|
|
15718
|
+
if (!appState) {
|
|
15719
|
+
return this.appState;
|
|
15720
|
+
}
|
|
15721
|
+
const nextAppStateSnapshot = !isObservedAppState(appState) ? getObservedAppState(appState) : appState;
|
|
15722
|
+
const didAppStateChange = this.detectChangedAppState(
|
|
15723
|
+
nextAppStateSnapshot,
|
|
15724
|
+
options
|
|
15725
|
+
);
|
|
15726
|
+
if (!didAppStateChange) {
|
|
15727
|
+
return this.appState;
|
|
15728
|
+
}
|
|
15729
|
+
return nextAppStateSnapshot;
|
|
15319
15730
|
}
|
|
15320
|
-
|
|
15321
|
-
|
|
15322
|
-
|
|
15323
|
-
|
|
15324
|
-
|
|
15325
|
-
|
|
15326
|
-
|
|
15327
|
-
|
|
15328
|
-
|
|
15329
|
-
if (!movedElements.has(elements[i].id)) {
|
|
15330
|
-
break;
|
|
15331
|
-
}
|
|
15332
|
-
indicesGroup.push(i);
|
|
15333
|
-
}
|
|
15334
|
-
indicesGroup.push(i);
|
|
15335
|
-
indicesGroups.push(indicesGroup);
|
|
15336
|
-
} else {
|
|
15337
|
-
i++;
|
|
15731
|
+
maybeCreateElementsSnapshot(elements, options = {
|
|
15732
|
+
shouldCompareHashes: false
|
|
15733
|
+
}) {
|
|
15734
|
+
if (!elements) {
|
|
15735
|
+
return this.elements;
|
|
15736
|
+
}
|
|
15737
|
+
const changedElements = this.detectChangedElements(elements, options);
|
|
15738
|
+
if (!changedElements?.size) {
|
|
15739
|
+
return this.elements;
|
|
15338
15740
|
}
|
|
15741
|
+
const elementsSnapshot = this.createElementsSnapshot(changedElements);
|
|
15742
|
+
return elementsSnapshot;
|
|
15339
15743
|
}
|
|
15340
|
-
|
|
15341
|
-
|
|
15342
|
-
|
|
15343
|
-
|
|
15344
|
-
|
|
15345
|
-
let upperBound = void 0;
|
|
15346
|
-
let lowerBoundIndex = -1;
|
|
15347
|
-
let upperBoundIndex = 0;
|
|
15348
|
-
const getLowerBound = (index) => {
|
|
15349
|
-
const lowerBound2 = elements[lowerBoundIndex] ? elements[lowerBoundIndex].index : void 0;
|
|
15350
|
-
const candidate = elements[index - 1]?.index;
|
|
15351
|
-
if (!lowerBound2 && candidate || // first lowerBound
|
|
15352
|
-
lowerBound2 && candidate && candidate > lowerBound2) {
|
|
15353
|
-
return [candidate, index - 1];
|
|
15744
|
+
detectChangedAppState(nextObservedAppState, options = {
|
|
15745
|
+
shouldCompareHashes: false
|
|
15746
|
+
}) {
|
|
15747
|
+
if (this.appState === nextObservedAppState) {
|
|
15748
|
+
return;
|
|
15354
15749
|
}
|
|
15355
|
-
|
|
15356
|
-
|
|
15357
|
-
|
|
15358
|
-
|
|
15359
|
-
if (
|
|
15360
|
-
return
|
|
15750
|
+
const didAppStateChange = Delta.isRightDifferent(
|
|
15751
|
+
this.appState,
|
|
15752
|
+
nextObservedAppState
|
|
15753
|
+
);
|
|
15754
|
+
if (!didAppStateChange) {
|
|
15755
|
+
return;
|
|
15361
15756
|
}
|
|
15362
|
-
|
|
15363
|
-
|
|
15364
|
-
|
|
15365
|
-
|
|
15366
|
-
|
|
15367
|
-
|
|
15757
|
+
const changedAppStateHash = hashString(
|
|
15758
|
+
JSON.stringify(nextObservedAppState)
|
|
15759
|
+
);
|
|
15760
|
+
if (options.shouldCompareHashes && this._lastChangedAppStateHash === changedAppStateHash) {
|
|
15761
|
+
return;
|
|
15762
|
+
}
|
|
15763
|
+
this._lastChangedAppStateHash = changedAppStateHash;
|
|
15764
|
+
return didAppStateChange;
|
|
15765
|
+
}
|
|
15766
|
+
/**
|
|
15767
|
+
* Detect if there are any changed elements.
|
|
15768
|
+
*/
|
|
15769
|
+
detectChangedElements(nextElements, options = {
|
|
15770
|
+
shouldCompareHashes: false
|
|
15771
|
+
}) {
|
|
15772
|
+
if (this.elements === nextElements) {
|
|
15773
|
+
return;
|
|
15774
|
+
}
|
|
15775
|
+
const changedElements = /* @__PURE__ */ new Map();
|
|
15776
|
+
for (const prevElement of toIterable(this.elements)) {
|
|
15777
|
+
const nextElement = nextElements.get(prevElement.id);
|
|
15778
|
+
if (!nextElement) {
|
|
15779
|
+
changedElements.set(
|
|
15780
|
+
prevElement.id,
|
|
15781
|
+
newElementWith(prevElement, { isDeleted: true })
|
|
15782
|
+
);
|
|
15368
15783
|
}
|
|
15369
15784
|
}
|
|
15370
|
-
|
|
15371
|
-
|
|
15372
|
-
|
|
15373
|
-
|
|
15374
|
-
|
|
15375
|
-
|
|
15376
|
-
[upperBound, upperBoundIndex] = getUpperBound(i);
|
|
15377
|
-
if (!isValidFractionalIndex(current, lowerBound, upperBound)) {
|
|
15378
|
-
const indicesGroup = [lowerBoundIndex, i];
|
|
15379
|
-
while (++i < elements.length) {
|
|
15380
|
-
const current2 = elements[i].index;
|
|
15381
|
-
const [nextLowerBound, nextLowerBoundIndex] = getLowerBound(i);
|
|
15382
|
-
const [nextUpperBound, nextUpperBoundIndex] = getUpperBound(i);
|
|
15383
|
-
if (isValidFractionalIndex(current2, nextLowerBound, nextUpperBound)) {
|
|
15384
|
-
break;
|
|
15785
|
+
for (const nextElement of toIterable(nextElements)) {
|
|
15786
|
+
const prevElement = this.elements.get(nextElement.id);
|
|
15787
|
+
if (!prevElement || // element was added
|
|
15788
|
+
prevElement.version < nextElement.version) {
|
|
15789
|
+
if (isImageElement(nextElement) && !isInitializedImageElement(nextElement)) {
|
|
15790
|
+
continue;
|
|
15385
15791
|
}
|
|
15386
|
-
|
|
15387
|
-
[upperBound, upperBoundIndex] = [nextUpperBound, nextUpperBoundIndex];
|
|
15388
|
-
indicesGroup.push(i);
|
|
15792
|
+
changedElements.set(nextElement.id, nextElement);
|
|
15389
15793
|
}
|
|
15390
|
-
indicesGroup.push(upperBoundIndex);
|
|
15391
|
-
indicesGroups.push(indicesGroup);
|
|
15392
|
-
} else {
|
|
15393
|
-
i++;
|
|
15394
15794
|
}
|
|
15795
|
+
if (!changedElements.size) {
|
|
15796
|
+
return;
|
|
15797
|
+
}
|
|
15798
|
+
const changedElementsHash = hashElementsVersion(changedElements);
|
|
15799
|
+
if (options.shouldCompareHashes && this._lastChangedElementsHash === changedElementsHash) {
|
|
15800
|
+
return;
|
|
15801
|
+
}
|
|
15802
|
+
this._lastChangedElementsHash = changedElementsHash;
|
|
15803
|
+
return changedElements;
|
|
15395
15804
|
}
|
|
15396
|
-
|
|
15397
|
-
|
|
15398
|
-
|
|
15399
|
-
|
|
15400
|
-
|
|
15401
|
-
|
|
15402
|
-
|
|
15403
|
-
|
|
15404
|
-
|
|
15405
|
-
|
|
15406
|
-
return index < successor;
|
|
15407
|
-
}
|
|
15408
|
-
if (predecessor && !successor) {
|
|
15409
|
-
return predecessor < index;
|
|
15410
|
-
}
|
|
15411
|
-
return !!index;
|
|
15412
|
-
};
|
|
15413
|
-
var generateIndices = (elements, indicesGroups) => {
|
|
15414
|
-
const elementsUpdates = /* @__PURE__ */ new Map();
|
|
15415
|
-
for (const indices of indicesGroups) {
|
|
15416
|
-
const lowerBoundIndex = indices.shift();
|
|
15417
|
-
const upperBoundIndex = indices.pop();
|
|
15418
|
-
const fractionalIndices = generateNKeysBetween(
|
|
15419
|
-
elements[lowerBoundIndex]?.index,
|
|
15420
|
-
elements[upperBoundIndex]?.index,
|
|
15421
|
-
indices.length
|
|
15422
|
-
);
|
|
15423
|
-
for (let i = 0; i < indices.length; i++) {
|
|
15424
|
-
const element = elements[indices[i]];
|
|
15425
|
-
elementsUpdates.set(element, {
|
|
15426
|
-
index: fractionalIndices[i]
|
|
15427
|
-
});
|
|
15805
|
+
/**
|
|
15806
|
+
* Perform structural clone, deep cloning only elements that changed.
|
|
15807
|
+
*/
|
|
15808
|
+
createElementsSnapshot(changedElements) {
|
|
15809
|
+
const clonedElements = /* @__PURE__ */ new Map();
|
|
15810
|
+
for (const prevElement of toIterable(this.elements)) {
|
|
15811
|
+
clonedElements.set(prevElement.id, prevElement);
|
|
15812
|
+
}
|
|
15813
|
+
for (const changedElement of toIterable(changedElements)) {
|
|
15814
|
+
clonedElements.set(changedElement.id, deepCopyElement(changedElement));
|
|
15428
15815
|
}
|
|
15816
|
+
return clonedElements;
|
|
15429
15817
|
}
|
|
15430
|
-
return elementsUpdates;
|
|
15431
15818
|
};
|
|
15432
|
-
var
|
|
15433
|
-
|
|
15434
|
-
|
|
15435
|
-
|
|
15436
|
-
|
|
15819
|
+
var hiddenObservedAppStateProp = "__observedAppState";
|
|
15820
|
+
var getDefaultObservedAppState = () => {
|
|
15821
|
+
return {
|
|
15822
|
+
name: null,
|
|
15823
|
+
editingGroupId: null,
|
|
15824
|
+
viewBackgroundColor: COLOR_PALETTE.white,
|
|
15825
|
+
selectedElementIds: {},
|
|
15826
|
+
selectedGroupIds: {},
|
|
15827
|
+
selectedLinearElement: null,
|
|
15828
|
+
croppingElementId: null,
|
|
15829
|
+
activeLockedId: null,
|
|
15830
|
+
lockedMultiSelections: {}
|
|
15831
|
+
};
|
|
15832
|
+
};
|
|
15833
|
+
var getObservedAppState = (appState) => {
|
|
15834
|
+
const observedAppState = {
|
|
15835
|
+
name: appState.name,
|
|
15836
|
+
editingGroupId: appState.editingGroupId,
|
|
15837
|
+
viewBackgroundColor: appState.viewBackgroundColor,
|
|
15838
|
+
selectedElementIds: appState.selectedElementIds,
|
|
15839
|
+
selectedGroupIds: appState.selectedGroupIds,
|
|
15840
|
+
croppingElementId: appState.croppingElementId,
|
|
15841
|
+
activeLockedId: appState.activeLockedId,
|
|
15842
|
+
lockedMultiSelections: appState.lockedMultiSelections,
|
|
15843
|
+
selectedLinearElement: appState.selectedLinearElement ? {
|
|
15844
|
+
elementId: appState.selectedLinearElement.elementId,
|
|
15845
|
+
isEditing: !!appState.selectedLinearElement.isEditing
|
|
15846
|
+
} : null
|
|
15847
|
+
};
|
|
15848
|
+
Reflect.defineProperty(observedAppState, hiddenObservedAppStateProp, {
|
|
15849
|
+
value: true,
|
|
15850
|
+
enumerable: false
|
|
15851
|
+
});
|
|
15852
|
+
return observedAppState;
|
|
15437
15853
|
};
|
|
15854
|
+
var isObservedAppState = (appState) => !!Reflect.get(appState, hiddenObservedAppStateProp);
|
|
15438
15855
|
|
|
15439
15856
|
// ../element/src/Scene.ts
|
|
15440
15857
|
import throttle from "lodash.throttle";
|
|
@@ -15500,16 +15917,9 @@ var Scene = class {
|
|
|
15500
15917
|
* cache-invalidation nonce at the moment.
|
|
15501
15918
|
*/
|
|
15502
15919
|
__publicField(this, "sceneNonce");
|
|
15920
|
+
/** low-level - generally use app.insertNewElement() */
|
|
15503
15921
|
__publicField(this, "insertElement", (element) => {
|
|
15504
|
-
|
|
15505
|
-
this.insertElementAtIndex(element, index);
|
|
15506
|
-
});
|
|
15507
|
-
__publicField(this, "insertElements", (elements) => {
|
|
15508
|
-
if (!elements.length) {
|
|
15509
|
-
return;
|
|
15510
|
-
}
|
|
15511
|
-
const index = elements[0]?.frameId ? this.getElementIndex(elements[0].frameId) : this.elements.length;
|
|
15512
|
-
this.insertElementsAtIndex(elements, index);
|
|
15922
|
+
this.insertElementsAtIndex([element], null);
|
|
15513
15923
|
});
|
|
15514
15924
|
__publicField(this, "getContainerElement", (element) => {
|
|
15515
15925
|
if (!element) {
|
|
@@ -15662,24 +16072,14 @@ var Scene = class {
|
|
|
15662
16072
|
this.selectedElementsCache.cache.clear();
|
|
15663
16073
|
this.callbacks.clear();
|
|
15664
16074
|
}
|
|
15665
|
-
|
|
15666
|
-
if (!Number.isFinite(index) || index < 0) {
|
|
15667
|
-
throw new Error(
|
|
15668
|
-
"insertElementAtIndex can only be called with index >= 0"
|
|
15669
|
-
);
|
|
15670
|
-
}
|
|
15671
|
-
const nextElements = [
|
|
15672
|
-
...this.elements.slice(0, index),
|
|
15673
|
-
element,
|
|
15674
|
-
...this.elements.slice(index)
|
|
15675
|
-
];
|
|
15676
|
-
syncMovedIndices(nextElements, arrayToMap([element]));
|
|
15677
|
-
this.replaceAllElements(nextElements);
|
|
15678
|
-
}
|
|
16075
|
+
/** low-level - generally use app.insertNewElements() */
|
|
15679
16076
|
insertElementsAtIndex(elements, index) {
|
|
15680
16077
|
if (!elements.length) {
|
|
15681
16078
|
return;
|
|
15682
16079
|
}
|
|
16080
|
+
if (index === null) {
|
|
16081
|
+
index = this.elements.length;
|
|
16082
|
+
}
|
|
15683
16083
|
if (!Number.isFinite(index) || index < 0) {
|
|
15684
16084
|
throw new Error(
|
|
15685
16085
|
"insertElementAtIndex can only be called with index >= 0"
|
|
@@ -21484,7 +21884,6 @@ import {
|
|
|
21484
21884
|
fileSave as _fileSave,
|
|
21485
21885
|
supported as nativeFileSystemSupported
|
|
21486
21886
|
} from "browser-fs-access";
|
|
21487
|
-
var INPUT_CHANGE_INTERVAL_MS = 5e3;
|
|
21488
21887
|
var fileOpen = async (opts) => {
|
|
21489
21888
|
const mimeTypes = opts.extensions?.reduce((mimeTypes2, type) => {
|
|
21490
21889
|
mimeTypes2.push(MIME_TYPES[type]);
|
|
@@ -21500,39 +21899,7 @@ var fileOpen = async (opts) => {
|
|
|
21500
21899
|
description: opts.description,
|
|
21501
21900
|
extensions,
|
|
21502
21901
|
mimeTypes,
|
|
21503
|
-
multiple: opts.multiple ?? false
|
|
21504
|
-
legacySetup: (resolve, reject, input) => {
|
|
21505
|
-
const scheduleRejection = debounce(reject, INPUT_CHANGE_INTERVAL_MS);
|
|
21506
|
-
const focusHandler = () => {
|
|
21507
|
-
checkForFile();
|
|
21508
|
-
document.addEventListener("keyup" /* KEYUP */, scheduleRejection);
|
|
21509
|
-
document.addEventListener("pointerup" /* POINTER_UP */, scheduleRejection);
|
|
21510
|
-
scheduleRejection();
|
|
21511
|
-
};
|
|
21512
|
-
const checkForFile = () => {
|
|
21513
|
-
if (input.files?.length) {
|
|
21514
|
-
const ret = opts.multiple ? [...input.files] : input.files[0];
|
|
21515
|
-
resolve(ret);
|
|
21516
|
-
}
|
|
21517
|
-
};
|
|
21518
|
-
requestAnimationFrame(() => {
|
|
21519
|
-
window.addEventListener("focus" /* FOCUS */, focusHandler);
|
|
21520
|
-
});
|
|
21521
|
-
const interval = window.setInterval(() => {
|
|
21522
|
-
checkForFile();
|
|
21523
|
-
}, INPUT_CHANGE_INTERVAL_MS);
|
|
21524
|
-
return (rejectPromise) => {
|
|
21525
|
-
clearInterval(interval);
|
|
21526
|
-
scheduleRejection.cancel();
|
|
21527
|
-
window.removeEventListener("focus" /* FOCUS */, focusHandler);
|
|
21528
|
-
document.removeEventListener("keyup" /* KEYUP */, scheduleRejection);
|
|
21529
|
-
document.removeEventListener("pointerup" /* POINTER_UP */, scheduleRejection);
|
|
21530
|
-
if (rejectPromise) {
|
|
21531
|
-
console.warn("Opening the file was canceled (legacy-fs).");
|
|
21532
|
-
rejectPromise(new AbortError());
|
|
21533
|
-
}
|
|
21534
|
-
};
|
|
21535
|
-
}
|
|
21902
|
+
multiple: opts.multiple ?? false
|
|
21536
21903
|
});
|
|
21537
21904
|
if (Array.isArray(files)) {
|
|
21538
21905
|
return await Promise.all(
|
|
@@ -21550,7 +21917,8 @@ var fileSave = (blob, opts) => {
|
|
|
21550
21917
|
extensions: [`.${opts.extension}`],
|
|
21551
21918
|
mimeTypes: opts.mimeTypes
|
|
21552
21919
|
},
|
|
21553
|
-
opts.fileHandle
|
|
21920
|
+
opts.fileHandle,
|
|
21921
|
+
false
|
|
21554
21922
|
);
|
|
21555
21923
|
};
|
|
21556
21924
|
|
|
@@ -21578,18 +21946,24 @@ var serializeAsJSON = (elements, appState, files, type) => {
|
|
|
21578
21946
|
};
|
|
21579
21947
|
return JSON.stringify(data, null, 2);
|
|
21580
21948
|
};
|
|
21581
|
-
var saveAsJSON = async (
|
|
21582
|
-
|
|
21583
|
-
|
|
21584
|
-
|
|
21949
|
+
var saveAsJSON = async ({
|
|
21950
|
+
data,
|
|
21951
|
+
filename,
|
|
21952
|
+
fileHandle
|
|
21953
|
+
}) => {
|
|
21954
|
+
const blob = Promise.resolve(data).then(({ elements, appState, files }) => {
|
|
21955
|
+
const serialized = serializeAsJSON(elements, appState, files, "local");
|
|
21956
|
+
return new Blob([serialized], {
|
|
21957
|
+
type: MIME_TYPES.excalidraw
|
|
21958
|
+
});
|
|
21585
21959
|
});
|
|
21586
|
-
const
|
|
21587
|
-
name,
|
|
21960
|
+
const savedFileHandle = await fileSave(blob, {
|
|
21961
|
+
name: filename,
|
|
21588
21962
|
extension: "excalidraw",
|
|
21589
21963
|
description: "Excalidraw file",
|
|
21590
|
-
fileHandle: isImageFileHandle(
|
|
21964
|
+
fileHandle: isImageFileHandle(fileHandle) ? null : fileHandle
|
|
21591
21965
|
});
|
|
21592
|
-
return { fileHandle };
|
|
21966
|
+
return { fileHandle: savedFileHandle };
|
|
21593
21967
|
};
|
|
21594
21968
|
var loadFromJSON = async (localAppState, localElements) => {
|
|
21595
21969
|
const file = await fileOpen({
|
|
@@ -24422,8 +24796,7 @@ var _renderStaticScene = ({
|
|
|
24422
24796
|
var renderStaticSceneThrottled = throttleRAF(
|
|
24423
24797
|
(config) => {
|
|
24424
24798
|
_renderStaticScene(config);
|
|
24425
|
-
}
|
|
24426
|
-
{ trailing: true }
|
|
24799
|
+
}
|
|
24427
24800
|
);
|
|
24428
24801
|
var renderStaticScene = (renderConfig, throttle2) => {
|
|
24429
24802
|
if (throttle2) {
|
|
@@ -24992,6 +25365,7 @@ var renderSceneToSvg = (elements, elementsMap, rsvg, svgRoot, files, renderConfi
|
|
|
24992
25365
|
};
|
|
24993
25366
|
|
|
24994
25367
|
// data/restore.ts
|
|
25368
|
+
var MAX_ARROW_PX = 75e3;
|
|
24995
25369
|
var AllowedExcalidrawActiveTools = {
|
|
24996
25370
|
selection: true,
|
|
24997
25371
|
lasso: true,
|
|
@@ -25084,7 +25458,9 @@ var repairBinding = (element, binding, targetElementsMap, existingElementsMap, s
|
|
|
25084
25458
|
fixedPoint
|
|
25085
25459
|
};
|
|
25086
25460
|
}
|
|
25087
|
-
console.error(
|
|
25461
|
+
console.error(
|
|
25462
|
+
`Could not repair binding for element "${boundElement?.id}" out of (${elementsMap?.size}) elements`
|
|
25463
|
+
);
|
|
25088
25464
|
} catch (error) {
|
|
25089
25465
|
console.error("Error repairing binding:", error);
|
|
25090
25466
|
}
|
|
@@ -25247,8 +25623,8 @@ var restoreElement = (element, targetElementsMap, existingElementsMap, opts) =>
|
|
|
25247
25623
|
startArrowhead: startArrowhead2,
|
|
25248
25624
|
endArrowhead: endArrowhead2,
|
|
25249
25625
|
points: points2,
|
|
25250
|
-
x: x2,
|
|
25251
|
-
y: y2,
|
|
25626
|
+
x: x2 ?? 0,
|
|
25627
|
+
y: y2 ?? 0,
|
|
25252
25628
|
elbowed: element.elbowed,
|
|
25253
25629
|
...getSizeFromPoints(points2)
|
|
25254
25630
|
};
|
|
@@ -25259,12 +25635,30 @@ var restoreElement = (element, targetElementsMap, existingElementsMap, opts) =>
|
|
|
25259
25635
|
startIsSpecial: element.startIsSpecial,
|
|
25260
25636
|
endIsSpecial: element.endIsSpecial
|
|
25261
25637
|
}) : restoreElementWithProperties(element, base);
|
|
25262
|
-
|
|
25638
|
+
const normalizedRestoredElement = {
|
|
25263
25639
|
...restoredElement,
|
|
25264
25640
|
...LinearElementEditor.getNormalizeElementPointsAndCoords(
|
|
25265
25641
|
restoredElement
|
|
25266
25642
|
)
|
|
25267
25643
|
};
|
|
25644
|
+
if (normalizedRestoredElement.width > MAX_ARROW_PX || normalizedRestoredElement.height > MAX_ARROW_PX) {
|
|
25645
|
+
console.error(
|
|
25646
|
+
`Removing extremely large arrow ${normalizedRestoredElement.id} (type: ${isElbowArrow(normalizedRestoredElement) ? "elbow" : "simple"}, width: ${normalizedRestoredElement.width}, height: ${normalizedRestoredElement.height}, x: ${normalizedRestoredElement.x}, y: ${normalizedRestoredElement.y})`
|
|
25647
|
+
);
|
|
25648
|
+
return {
|
|
25649
|
+
...normalizedRestoredElement,
|
|
25650
|
+
x: 0,
|
|
25651
|
+
y: 0,
|
|
25652
|
+
width: 100,
|
|
25653
|
+
height: 100,
|
|
25654
|
+
points: [
|
|
25655
|
+
pointFrom(0, 0),
|
|
25656
|
+
pointFrom(100, 100)
|
|
25657
|
+
],
|
|
25658
|
+
isDeleted: true
|
|
25659
|
+
};
|
|
25660
|
+
}
|
|
25661
|
+
return normalizedRestoredElement;
|
|
25268
25662
|
}
|
|
25269
25663
|
case "ellipse":
|
|
25270
25664
|
case "rectangle":
|
|
@@ -25489,6 +25883,10 @@ var restoreAppState = (appState, localAppState) => {
|
|
|
25489
25883
|
const localValue = localAppState ? localAppState[key] : void 0;
|
|
25490
25884
|
nextAppState[key] = suppliedValue !== void 0 ? suppliedValue : localValue !== void 0 ? localValue : defaultValue;
|
|
25491
25885
|
}
|
|
25886
|
+
const boxSelectionMode = appState.boxSelectionMode ?? localAppState?.boxSelectionMode;
|
|
25887
|
+
if (boxSelectionMode !== void 0) {
|
|
25888
|
+
nextAppState.boxSelectionMode = boxSelectionMode;
|
|
25889
|
+
}
|
|
25492
25890
|
return {
|
|
25493
25891
|
...nextAppState,
|
|
25494
25892
|
cursorButton: localAppState?.cursorButton || "up",
|
|
@@ -25619,7 +26017,11 @@ var prepareElementsForRender = ({
|
|
|
25619
26017
|
}) => {
|
|
25620
26018
|
let nextElements;
|
|
25621
26019
|
if (exportingFrame) {
|
|
25622
|
-
nextElements = getElementsOverlappingFrame(
|
|
26020
|
+
nextElements = getElementsOverlappingFrame(
|
|
26021
|
+
elements,
|
|
26022
|
+
exportingFrame,
|
|
26023
|
+
arrayToMap(elements)
|
|
26024
|
+
);
|
|
25623
26025
|
} else if (frameRendering.enabled && frameRendering.name) {
|
|
25624
26026
|
nextElements = addFrameLabelsAsTextElements(elements, {
|
|
25625
26027
|
exportWithDarkMode
|
|
@@ -26018,7 +26420,7 @@ var parseFileContents = async (blob) => {
|
|
|
26018
26420
|
let contents;
|
|
26019
26421
|
if (blob.type === MIME_TYPES.png) {
|
|
26020
26422
|
try {
|
|
26021
|
-
return await (await import("./data/image-
|
|
26423
|
+
return await (await import("./data/image-O7OJXMIJ.js")).decodePngMetadata(blob);
|
|
26022
26424
|
} catch (error) {
|
|
26023
26425
|
if (error.message === "INVALID") {
|
|
26024
26426
|
throw new ImageSceneDataError(
|
|
@@ -26407,6 +26809,7 @@ export {
|
|
|
26407
26809
|
rangeInclusive,
|
|
26408
26810
|
rangesOverlap,
|
|
26409
26811
|
rangeIntersection,
|
|
26812
|
+
rangeIncludesValue,
|
|
26410
26813
|
supportsResizeObserver,
|
|
26411
26814
|
APP_NAME,
|
|
26412
26815
|
DRAGGING_THRESHOLD,
|
|
@@ -26582,6 +26985,7 @@ export {
|
|
|
26582
26985
|
isLocalLink,
|
|
26583
26986
|
toValidURL,
|
|
26584
26987
|
Emitter,
|
|
26988
|
+
AppEventBus,
|
|
26585
26989
|
MINIMAL_CROP_SIZE,
|
|
26586
26990
|
cropElement,
|
|
26587
26991
|
getUncroppedWidthAndHeight,
|
|
@@ -26616,6 +27020,7 @@ export {
|
|
|
26616
27020
|
getLinearElementSubType,
|
|
26617
27021
|
isValidPolygon,
|
|
26618
27022
|
canBecomePolygon,
|
|
27023
|
+
isEligibleFrameChildType,
|
|
26619
27024
|
deconstructRectanguloidElement,
|
|
26620
27025
|
getDiamondBaseCorners,
|
|
26621
27026
|
deconstructDiamondElement,
|
|
@@ -26653,6 +27058,13 @@ export {
|
|
|
26653
27058
|
getBoundTextMaxWidth,
|
|
26654
27059
|
getBoundTextMaxHeight,
|
|
26655
27060
|
getTextFromElements,
|
|
27061
|
+
hasBackground,
|
|
27062
|
+
hasStrokeColor,
|
|
27063
|
+
hasStrokeWidth,
|
|
27064
|
+
hasStrokeStyle,
|
|
27065
|
+
canChangeRoundness,
|
|
27066
|
+
toolIsArrow,
|
|
27067
|
+
canHaveArrowheads,
|
|
26656
27068
|
shouldTestInside,
|
|
26657
27069
|
hitElementItself,
|
|
26658
27070
|
hitElementBoundingBox,
|
|
@@ -26679,9 +27091,6 @@ export {
|
|
|
26679
27091
|
fixBindingsAfterDeletion,
|
|
26680
27092
|
getGlobalFixedPointForBindableElement,
|
|
26681
27093
|
LinearElementEditor,
|
|
26682
|
-
isElementInsideBBox,
|
|
26683
|
-
elementPartiallyOverlapsWithOrContainsBBox,
|
|
26684
|
-
elementsOverlappingBBox,
|
|
26685
27094
|
selectGroup,
|
|
26686
27095
|
selectGroupsForSelectedElements,
|
|
26687
27096
|
isSelectedViaGroup,
|
|
@@ -26706,6 +27115,10 @@ export {
|
|
|
26706
27115
|
makeNextSelectedElementIds,
|
|
26707
27116
|
getSelectionStateForElements,
|
|
26708
27117
|
getActiveTextElement,
|
|
27118
|
+
validateFractionalIndices,
|
|
27119
|
+
orderByFractionalIndex,
|
|
27120
|
+
syncMovedIndices,
|
|
27121
|
+
syncInvalidIndices,
|
|
26709
27122
|
elementOverlapsWithFrame,
|
|
26710
27123
|
isCursorInFrame,
|
|
26711
27124
|
groupByFrameLikes,
|
|
@@ -26716,6 +27129,8 @@ export {
|
|
|
26716
27129
|
getElementsInNewFrame,
|
|
26717
27130
|
getContainingFrame,
|
|
26718
27131
|
filterElementsEligibleAsFrameChildren,
|
|
27132
|
+
getCommonFrameId,
|
|
27133
|
+
getFrameChildrenInsertionIndex,
|
|
26719
27134
|
addElementsToFrame,
|
|
26720
27135
|
removeElementsFromFrame,
|
|
26721
27136
|
removeAllElementsFromFrame,
|
|
@@ -26733,13 +27148,6 @@ export {
|
|
|
26733
27148
|
renderSelectionElement,
|
|
26734
27149
|
renderElement,
|
|
26735
27150
|
getFreedrawOutlineAsSegments,
|
|
26736
|
-
hasBackground,
|
|
26737
|
-
hasStrokeColor,
|
|
26738
|
-
hasStrokeWidth,
|
|
26739
|
-
hasStrokeStyle,
|
|
26740
|
-
canChangeRoundness,
|
|
26741
|
-
toolIsArrow,
|
|
26742
|
-
canHaveArrowheads,
|
|
26743
27151
|
ShapeCache,
|
|
26744
27152
|
toggleLinePolygonState,
|
|
26745
27153
|
getFreedrawOutlinePoints,
|
|
@@ -26765,10 +27173,6 @@ export {
|
|
|
26765
27173
|
StoreChange,
|
|
26766
27174
|
StoreDelta,
|
|
26767
27175
|
getObservedAppState,
|
|
26768
|
-
validateFractionalIndices,
|
|
26769
|
-
orderByFractionalIndex,
|
|
26770
|
-
syncMovedIndices,
|
|
26771
|
-
syncInvalidIndices,
|
|
26772
27176
|
Scene,
|
|
26773
27177
|
distributeElements,
|
|
26774
27178
|
dragSelectedElements,
|
|
@@ -26896,4 +27300,4 @@ export {
|
|
|
26896
27300
|
createFile,
|
|
26897
27301
|
normalizeFile
|
|
26898
27302
|
};
|
|
26899
|
-
//# sourceMappingURL=chunk-
|
|
27303
|
+
//# sourceMappingURL=chunk-OKDHCI5V.js.map
|