@myoc/element 0.19.505 → 0.19.508
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev/index.js +875 -983
- package/dist/dev/index.js.map +4 -4
- package/dist/prod/index.js +12 -12
- 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 +3 -3
- package/dist/types/excalidraw/actions/actionBoundText.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionCanvas.d.ts +11 -11
- package/dist/types/excalidraw/actions/actionClipboard.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionCropEditor.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionDeselect.d.ts +168 -0
- package/dist/types/excalidraw/actions/actionElementLink.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionElementLock.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionEmbeddable.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionExport.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionFrame.d.ts +4 -4
- package/dist/types/excalidraw/actions/actionGroup.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionLink.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionMenu.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionProperties.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionSelectAll.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionStyles.d.ts +3 -5
- package/dist/types/excalidraw/actions/actionToggleArrowBinding.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleMidpointSnapping.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleStats.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +2 -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/components/App.d.ts +9 -0
- package/dist/types/excalidraw/components/PublishLibrary.d.ts +3 -2
- 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/data/blob.d.ts +4 -8
- package/dist/types/excalidraw/data/json.d.ts +1 -1
- package/dist/types/excalidraw/scene/Renderer.d.ts +425 -19
- package/dist/types/excalidraw/scene/types.d.ts +2 -0
- package/dist/types/excalidraw/types.d.ts +15 -2
- 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 +6 -4
package/dist/dev/index.js
CHANGED
|
@@ -3862,14 +3862,14 @@ var rough_default = {
|
|
|
3862
3862
|
|
|
3863
3863
|
// src/bounds.ts
|
|
3864
3864
|
import {
|
|
3865
|
-
arrayToMap as
|
|
3865
|
+
arrayToMap as arrayToMap7,
|
|
3866
3866
|
invariant as invariant10,
|
|
3867
3867
|
rescalePoints,
|
|
3868
3868
|
sizeOf
|
|
3869
3869
|
} from "@excalidraw/common";
|
|
3870
3870
|
import {
|
|
3871
3871
|
degreesToRadians,
|
|
3872
|
-
lineSegment as
|
|
3872
|
+
lineSegment as lineSegment7,
|
|
3873
3873
|
pointDistance as pointDistance7,
|
|
3874
3874
|
pointFrom as pointFrom14,
|
|
3875
3875
|
pointFromArray as pointFromArray3,
|
|
@@ -4233,7 +4233,7 @@ import {
|
|
|
4233
4233
|
init_define_import_meta_env();
|
|
4234
4234
|
import {
|
|
4235
4235
|
isRightAngleRads,
|
|
4236
|
-
lineSegment as
|
|
4236
|
+
lineSegment as lineSegment6,
|
|
4237
4237
|
pointFrom as pointFrom12,
|
|
4238
4238
|
pointRotateRads as pointRotateRads11
|
|
4239
4239
|
} from "@excalidraw/math";
|
|
@@ -4969,6 +4969,25 @@ var canBecomePolygon = (points) => {
|
|
|
4969
4969
|
return points.length > 3 || // 3-point polygons can't have all points in a single line
|
|
4970
4970
|
points.length === 3 && !pointsEqual(points[0], points[points.length - 1]);
|
|
4971
4971
|
};
|
|
4972
|
+
var isEligibleFrameChildType = (type) => {
|
|
4973
|
+
switch (type) {
|
|
4974
|
+
case "rectangle":
|
|
4975
|
+
case "diamond":
|
|
4976
|
+
case "ellipse":
|
|
4977
|
+
case "arrow":
|
|
4978
|
+
case "line":
|
|
4979
|
+
case "freedraw":
|
|
4980
|
+
case "text":
|
|
4981
|
+
case "image":
|
|
4982
|
+
case "frame":
|
|
4983
|
+
case "embeddable": {
|
|
4984
|
+
return true;
|
|
4985
|
+
}
|
|
4986
|
+
default: {
|
|
4987
|
+
return false;
|
|
4988
|
+
}
|
|
4989
|
+
}
|
|
4990
|
+
};
|
|
4972
4991
|
|
|
4973
4992
|
// src/utils.ts
|
|
4974
4993
|
var ElementShapesCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -5003,12 +5022,12 @@ var setElementShapesCacheEntry = (element, shape, offset) => {
|
|
|
5003
5022
|
}
|
|
5004
5023
|
shapes.set(offset, shape);
|
|
5005
5024
|
};
|
|
5006
|
-
function deconstructLinearOrFreeDrawElement(element) {
|
|
5025
|
+
function deconstructLinearOrFreeDrawElement(element, elementsMap) {
|
|
5007
5026
|
const cachedShape = getElementShapesCacheEntry(element, 0);
|
|
5008
5027
|
if (cachedShape) {
|
|
5009
5028
|
return cachedShape;
|
|
5010
5029
|
}
|
|
5011
|
-
const ops = generateLinearCollisionShape(element);
|
|
5030
|
+
const ops = generateLinearCollisionShape(element, elementsMap);
|
|
5012
5031
|
const lines = [];
|
|
5013
5032
|
const curves = [];
|
|
5014
5033
|
for (let idx = 0; idx < ops.length; idx += 1) {
|
|
@@ -5415,7 +5434,7 @@ var getSnapOutlineMidPoint = (point, element, elementsMap, zoom) => {
|
|
|
5415
5434
|
)
|
|
5416
5435
|
];
|
|
5417
5436
|
const candidate = sideMidpoints.find(
|
|
5418
|
-
(
|
|
5437
|
+
(midpoint) => pointDistance2(point, midpoint) <= maxBindingDistance_simple(zoom) + element.strokeWidth / 2 && !hitElementItself({
|
|
5419
5438
|
point,
|
|
5420
5439
|
element,
|
|
5421
5440
|
threshold: 0,
|
|
@@ -6340,7 +6359,8 @@ var getContainerCenter = (container, appState, elementsMap) => {
|
|
|
6340
6359
|
if (!midSegmentMidpoint) {
|
|
6341
6360
|
midSegmentMidpoint = LinearElementEditor.getSegmentMidPoint(
|
|
6342
6361
|
container,
|
|
6343
|
-
index + 1
|
|
6362
|
+
index + 1,
|
|
6363
|
+
elementsMap
|
|
6344
6364
|
);
|
|
6345
6365
|
}
|
|
6346
6366
|
return { x: midSegmentMidpoint[0], y: midSegmentMidpoint[1] };
|
|
@@ -6491,7 +6511,7 @@ var distanceToElement = (element, elementsMap, p) => {
|
|
|
6491
6511
|
case "line":
|
|
6492
6512
|
case "arrow":
|
|
6493
6513
|
case "freedraw":
|
|
6494
|
-
return distanceToLinearOrFreeDraElement(element, p);
|
|
6514
|
+
return distanceToLinearOrFreeDraElement(element, elementsMap, p);
|
|
6495
6515
|
}
|
|
6496
6516
|
};
|
|
6497
6517
|
var distanceToRectanguloidElement = (element, elementsMap, p) => {
|
|
@@ -6520,20 +6540,33 @@ var distanceToEllipseElement = (element, elementsMap, p) => {
|
|
|
6520
6540
|
ellipse2(center, element.width / 2, element.height / 2)
|
|
6521
6541
|
);
|
|
6522
6542
|
};
|
|
6523
|
-
var distanceToLinearOrFreeDraElement = (element, p) => {
|
|
6524
|
-
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
6543
|
+
var distanceToLinearOrFreeDraElement = (element, elementsMap, p) => {
|
|
6544
|
+
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
6545
|
+
element,
|
|
6546
|
+
elementsMap
|
|
6547
|
+
);
|
|
6525
6548
|
return Math.min(
|
|
6526
6549
|
...lines.map((s) => distanceToLineSegment(p, s)),
|
|
6527
6550
|
...curves.map((a2) => curvePointDistance(a2, p))
|
|
6528
6551
|
);
|
|
6529
6552
|
};
|
|
6530
6553
|
|
|
6554
|
+
// src/comparisons.ts
|
|
6555
|
+
init_define_import_meta_env();
|
|
6556
|
+
var hasBackground = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "line" || type === "freedraw";
|
|
6557
|
+
var hasStrokeColor = (type) => type === "rectangle" || type === "ellipse" || type === "diamond" || type === "freedraw" || type === "arrow" || type === "line" || type === "text" || type === "embeddable";
|
|
6558
|
+
var hasStrokeWidth = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "freedraw" || type === "arrow" || type === "line";
|
|
6559
|
+
var hasStrokeStyle = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "arrow" || type === "line";
|
|
6560
|
+
var canChangeRoundness = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "line" || type === "diamond" || type === "image";
|
|
6561
|
+
var toolIsArrow = (type) => type === "arrow";
|
|
6562
|
+
var canHaveArrowheads = (type) => type === "arrow";
|
|
6563
|
+
|
|
6531
6564
|
// src/collision.ts
|
|
6532
6565
|
var shouldTestInside = (element) => {
|
|
6533
6566
|
if (element.type === "arrow") {
|
|
6534
6567
|
return false;
|
|
6535
6568
|
}
|
|
6536
|
-
const isDraggableFromInside = !isTransparent(element.backgroundColor) || hasBoundTextElement(element) || isIframeLikeElement(element) || isTextElement(element);
|
|
6569
|
+
const isDraggableFromInside = hasBackground(element.type) && !isTransparent(element.backgroundColor) || hasBoundTextElement(element) || isIframeLikeElement(element) || isTextElement(element);
|
|
6537
6570
|
if (element.type === "line") {
|
|
6538
6571
|
return isDraggableFromInside && isPathALoop(element.points);
|
|
6539
6572
|
}
|
|
@@ -6570,14 +6603,11 @@ var hitElementItself = ({
|
|
|
6570
6603
|
)
|
|
6571
6604
|
) : false;
|
|
6572
6605
|
const bounds = getElementBounds(element, elementsMap, true);
|
|
6573
|
-
const hitBounds =
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
-element.angle
|
|
6579
|
-
),
|
|
6580
|
-
pointFrom5(bounds[2] + threshold, bounds[3] + threshold)
|
|
6606
|
+
const hitBounds = isPointInRotatedBounds(
|
|
6607
|
+
point,
|
|
6608
|
+
bounds,
|
|
6609
|
+
element.angle,
|
|
6610
|
+
threshold
|
|
6581
6611
|
);
|
|
6582
6612
|
if (!hitBounds && !hitFrameName) {
|
|
6583
6613
|
return false;
|
|
@@ -6595,13 +6625,17 @@ var hitElementItself = ({
|
|
|
6595
6625
|
cachedHit = result;
|
|
6596
6626
|
return result;
|
|
6597
6627
|
};
|
|
6628
|
+
var isPointInRotatedBounds = (point, bounds, angle, tolerance = 0) => {
|
|
6629
|
+
const adjustedPoint = angle === 0 ? point : pointRotateRads6(point, getCenterForBounds(bounds), -angle);
|
|
6630
|
+
return isPointWithinBounds(
|
|
6631
|
+
pointFrom5(bounds[0] - tolerance, bounds[1] - tolerance),
|
|
6632
|
+
adjustedPoint,
|
|
6633
|
+
pointFrom5(bounds[2] + tolerance, bounds[3] + tolerance)
|
|
6634
|
+
);
|
|
6635
|
+
};
|
|
6598
6636
|
var hitElementBoundingBox = (point, element, elementsMap, tolerance = 0) => {
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
y1 -= tolerance;
|
|
6602
|
-
x2 += tolerance;
|
|
6603
|
-
y2 += tolerance;
|
|
6604
|
-
return isPointWithinBounds(pointFrom5(x1, y1), point, pointFrom5(x2, y2));
|
|
6637
|
+
const bounds = getElementBounds(element, elementsMap, true);
|
|
6638
|
+
return isPointInRotatedBounds(point, bounds, element.angle, tolerance);
|
|
6605
6639
|
};
|
|
6606
6640
|
var hitElementBoundingBoxOnly = (hitArgs, elementsMap) => !hitElementItself(hitArgs) && // bound text is considered part of the element (even if it's outside the bounding box)
|
|
6607
6641
|
!hitElementBoundText(hitArgs.point, hitArgs.element, elementsMap) && hitElementBoundingBox(hitArgs.point, hitArgs.element, elementsMap);
|
|
@@ -6665,7 +6699,7 @@ var getAllHoveredElementAtPoint = (point, elements, elementsMap, tolerance) => {
|
|
|
6665
6699
|
);
|
|
6666
6700
|
if (isBindableElement(element, false) && bindingBorderTest(element, point, elementsMap, tolerance)) {
|
|
6667
6701
|
candidateElements.push(element);
|
|
6668
|
-
if (!isTransparent(element.backgroundColor)) {
|
|
6702
|
+
if (hasBackground(element.type) && !isTransparent(element.backgroundColor)) {
|
|
6669
6703
|
break;
|
|
6670
6704
|
}
|
|
6671
6705
|
}
|
|
@@ -6760,7 +6794,12 @@ var intersectElementWithLineSegment = (element, elementsMap, line2, offset = 0,
|
|
|
6760
6794
|
case "line":
|
|
6761
6795
|
case "freedraw":
|
|
6762
6796
|
case "arrow":
|
|
6763
|
-
return intersectLinearOrFreeDrawWithLineSegment(
|
|
6797
|
+
return intersectLinearOrFreeDrawWithLineSegment(
|
|
6798
|
+
element,
|
|
6799
|
+
line2,
|
|
6800
|
+
elementsMap,
|
|
6801
|
+
onlyFirst
|
|
6802
|
+
);
|
|
6764
6803
|
}
|
|
6765
6804
|
};
|
|
6766
6805
|
var curveIntersections = (curves, segment, intersections, center, angle, onlyFirst = false) => {
|
|
@@ -6799,8 +6838,11 @@ var lineIntersections = (lines, segment, intersections, center, angle, onlyFirst
|
|
|
6799
6838
|
}
|
|
6800
6839
|
return intersections;
|
|
6801
6840
|
};
|
|
6802
|
-
var intersectLinearOrFreeDrawWithLineSegment = (element, segment, onlyFirst = false) => {
|
|
6803
|
-
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
6841
|
+
var intersectLinearOrFreeDrawWithLineSegment = (element, segment, elementsMap, onlyFirst = false) => {
|
|
6842
|
+
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
6843
|
+
element,
|
|
6844
|
+
elementsMap
|
|
6845
|
+
);
|
|
6804
6846
|
const intersections = [];
|
|
6805
6847
|
for (const l2 of lines) {
|
|
6806
6848
|
const intersection = lineSegmentIntersectionPoints2(l2, segment);
|
|
@@ -6822,7 +6864,9 @@ var intersectLinearOrFreeDrawWithLineSegment = (element, segment, onlyFirst = fa
|
|
|
6822
6864
|
if (!doBoundsIntersect(b1, b2)) {
|
|
6823
6865
|
continue;
|
|
6824
6866
|
}
|
|
6825
|
-
const hits = curveIntersectLineSegment(c, segment
|
|
6867
|
+
const hits = curveIntersectLineSegment(c, segment, {
|
|
6868
|
+
iterLimit: 10
|
|
6869
|
+
});
|
|
6826
6870
|
if (hits.length > 0) {
|
|
6827
6871
|
intersections.push(...hits);
|
|
6828
6872
|
if (onlyFirst) {
|
|
@@ -8533,7 +8577,7 @@ var normalizeArrowElementUpdate = (global2, nextFixedSegments, startIsSpecial, e
|
|
|
8533
8577
|
vectorScale6(vectorFromPoint6(global2[0]), -1)
|
|
8534
8578
|
)
|
|
8535
8579
|
);
|
|
8536
|
-
if (offsetX < -MAX_POS || offsetX > MAX_POS || offsetY < -MAX_POS || offsetY > MAX_POS || offsetX + points[points.length - 1][0] < -MAX_POS ||
|
|
8580
|
+
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) {
|
|
8537
8581
|
console.error(
|
|
8538
8582
|
"Elbow arrow normalization is outside reasonable bounds (> 1e6)",
|
|
8539
8583
|
{
|
|
@@ -9137,11 +9181,7 @@ var getBindingStrategyForDraggingBindingElementEndpoints_simple = (arrow, draggi
|
|
|
9137
9181
|
threshold: 0,
|
|
9138
9182
|
overrideShouldTestInside: true
|
|
9139
9183
|
});
|
|
9140
|
-
if (otherBinding && otherBinding.elementId === hit?.id) {
|
|
9141
|
-
invariant7(
|
|
9142
|
-
!opts?.newArrow || appState.selectedLinearElement?.initialState.origin,
|
|
9143
|
-
"appState.selectedLinearElement.initialState.origin must be defined for new arrows"
|
|
9144
|
-
);
|
|
9184
|
+
if (otherBinding && otherBinding.elementId === hit?.id && (!opts?.newArrow || appState.selectedLinearElement?.initialState.origin)) {
|
|
9145
9185
|
return {
|
|
9146
9186
|
start: {
|
|
9147
9187
|
mode: "inside",
|
|
@@ -9951,8 +9991,8 @@ var calculateFixedPointForElbowArrowBinding = (linearElement, hoveredElement, st
|
|
|
9951
9991
|
);
|
|
9952
9992
|
return {
|
|
9953
9993
|
fixedPoint: normalizeFixedPoint([
|
|
9954
|
-
(nonRotatedSnappedGlobalPoint[0] - hoveredElement.x) / hoveredElement.width,
|
|
9955
|
-
(nonRotatedSnappedGlobalPoint[1] - hoveredElement.y) / hoveredElement.height
|
|
9994
|
+
(nonRotatedSnappedGlobalPoint[0] - hoveredElement.x) / Math.max(hoveredElement.width, PRECISION2),
|
|
9995
|
+
(nonRotatedSnappedGlobalPoint[1] - hoveredElement.y) / Math.max(hoveredElement.height, PRECISION2)
|
|
9956
9996
|
])
|
|
9957
9997
|
};
|
|
9958
9998
|
};
|
|
@@ -9968,8 +10008,8 @@ var calculateFixedPointForNonElbowArrowBinding = (linearElement, hoveredElement,
|
|
|
9968
10008
|
elementCenter,
|
|
9969
10009
|
-hoveredElement.angle
|
|
9970
10010
|
);
|
|
9971
|
-
const fixedPointX = (nonRotatedPoint[0] - hoveredElement.x) / hoveredElement.width;
|
|
9972
|
-
const fixedPointY = (nonRotatedPoint[1] - hoveredElement.y) / hoveredElement.height;
|
|
10011
|
+
const fixedPointX = (nonRotatedPoint[0] - hoveredElement.x) / Math.max(hoveredElement.width, PRECISION2);
|
|
10012
|
+
const fixedPointY = (nonRotatedPoint[1] - hoveredElement.y) / Math.max(hoveredElement.height, PRECISION2);
|
|
9973
10013
|
return {
|
|
9974
10014
|
fixedPoint: normalizeFixedPoint([fixedPointX, fixedPointY])
|
|
9975
10015
|
};
|
|
@@ -10659,7 +10699,7 @@ var getMidPoint = (p1, p2) => {
|
|
|
10659
10699
|
|
|
10660
10700
|
// src/zindex.ts
|
|
10661
10701
|
init_define_import_meta_env();
|
|
10662
|
-
import { arrayToMap as
|
|
10702
|
+
import { arrayToMap as arrayToMap6, findIndex, findLastIndex } from "@excalidraw/common";
|
|
10663
10703
|
|
|
10664
10704
|
// src/groups.ts
|
|
10665
10705
|
init_define_import_meta_env();
|
|
@@ -10667,11 +10707,16 @@ init_define_import_meta_env();
|
|
|
10667
10707
|
// src/selection.ts
|
|
10668
10708
|
init_define_import_meta_env();
|
|
10669
10709
|
import { arrayToMap as arrayToMap5, isShallowEqual } from "@excalidraw/common";
|
|
10710
|
+
import {
|
|
10711
|
+
lineSegment as lineSegment5,
|
|
10712
|
+
pointFrom as pointFrom10,
|
|
10713
|
+
pointRotateRads as pointRotateRads9
|
|
10714
|
+
} from "@excalidraw/math";
|
|
10670
10715
|
|
|
10671
10716
|
// src/frame.ts
|
|
10672
10717
|
init_define_import_meta_env();
|
|
10673
10718
|
import { arrayToMap as arrayToMap4 } from "@excalidraw/common";
|
|
10674
|
-
import { isPointWithinBounds as isPointWithinBounds2, pointFrom as
|
|
10719
|
+
import { isPointWithinBounds as isPointWithinBounds2, pointFrom as pointFrom9 } from "@excalidraw/math";
|
|
10675
10720
|
|
|
10676
10721
|
// ../utils/src/bbox.ts
|
|
10677
10722
|
init_define_import_meta_env();
|
|
@@ -10709,163 +10754,272 @@ function doLineSegmentsIntersect(a2, b2) {
|
|
|
10709
10754
|
return doBBoxesIntersect(getBBox(a2), getBBox(b2)) && isLineSegmentTouchingOrCrossingLine(a2, b2) && isLineSegmentTouchingOrCrossingLine(b2, a2);
|
|
10710
10755
|
}
|
|
10711
10756
|
|
|
10712
|
-
//
|
|
10757
|
+
// src/fractionalIndex.ts
|
|
10713
10758
|
init_define_import_meta_env();
|
|
10714
10759
|
import { arrayToMap as arrayToMap3 } from "@excalidraw/common";
|
|
10715
|
-
import { getElementBounds as getElementBounds2 } from "@excalidraw/element";
|
|
10716
|
-
import {
|
|
10717
|
-
isArrowElement as isArrowElement2,
|
|
10718
|
-
isExcalidrawElement as isExcalidrawElement2,
|
|
10719
|
-
isFreeDrawElement as isFreeDrawElement2,
|
|
10720
|
-
isLinearElement as isLinearElement2,
|
|
10721
|
-
isTextElement as isTextElement2
|
|
10722
|
-
} from "@excalidraw/element";
|
|
10723
10760
|
import {
|
|
10724
|
-
|
|
10725
|
-
|
|
10726
|
-
|
|
10727
|
-
|
|
10728
|
-
|
|
10729
|
-
var getNonLinearElementRelativePoints = (element) => {
|
|
10730
|
-
if (element.type === "diamond") {
|
|
10731
|
-
return [
|
|
10732
|
-
pointFrom9(element.width / 2, 0),
|
|
10733
|
-
pointFrom9(element.width, element.height / 2),
|
|
10734
|
-
pointFrom9(element.width / 2, element.height),
|
|
10735
|
-
pointFrom9(0, element.height / 2)
|
|
10736
|
-
];
|
|
10737
|
-
}
|
|
10738
|
-
return [
|
|
10739
|
-
pointFrom9(0, 0),
|
|
10740
|
-
pointFrom9(0 + element.width, 0),
|
|
10741
|
-
pointFrom9(0 + element.width, element.height),
|
|
10742
|
-
pointFrom9(0, element.height)
|
|
10743
|
-
];
|
|
10761
|
+
validateOrderKey,
|
|
10762
|
+
generateNKeysBetween
|
|
10763
|
+
} from "@excalidraw/fractional-indexing";
|
|
10764
|
+
var InvalidFractionalIndexError = class extends Error {
|
|
10765
|
+
code = "ELEMENT_HAS_INVALID_INDEX";
|
|
10744
10766
|
};
|
|
10745
|
-
var
|
|
10746
|
-
|
|
10747
|
-
|
|
10767
|
+
var validateFractionalIndices = (elements, {
|
|
10768
|
+
shouldThrow = false,
|
|
10769
|
+
includeBoundTextValidation = false,
|
|
10770
|
+
ignoreLogs,
|
|
10771
|
+
reconciliationContext
|
|
10772
|
+
}) => {
|
|
10773
|
+
const errorMessages = [];
|
|
10774
|
+
const stringifyElement = (element) => `${element?.index}:${element?.id}:${element?.type}:${element?.isDeleted}:${element?.version}:${element?.versionNonce}`;
|
|
10775
|
+
const indices = elements.map((x) => x.index);
|
|
10776
|
+
for (const [i, index] of indices.entries()) {
|
|
10777
|
+
const predecessorIndex = indices[i - 1];
|
|
10778
|
+
const successorIndex = indices[i + 1];
|
|
10779
|
+
if (!isValidFractionalIndex(index, predecessorIndex, successorIndex)) {
|
|
10780
|
+
errorMessages.push(
|
|
10781
|
+
`Fractional indices invariant has been compromised: "${stringifyElement(
|
|
10782
|
+
elements[i - 1]
|
|
10783
|
+
)}", "${stringifyElement(elements[i])}", "${stringifyElement(
|
|
10784
|
+
elements[i + 1]
|
|
10785
|
+
)}"`
|
|
10786
|
+
);
|
|
10787
|
+
}
|
|
10788
|
+
if (includeBoundTextValidation && hasBoundTextElement(elements[i])) {
|
|
10789
|
+
const container = elements[i];
|
|
10790
|
+
const text = getBoundTextElement(container, arrayToMap3(elements));
|
|
10791
|
+
if (text && text.index <= container.index) {
|
|
10792
|
+
errorMessages.push(
|
|
10793
|
+
`Fractional indices invariant for bound elements has been compromised: "${stringifyElement(
|
|
10794
|
+
text
|
|
10795
|
+
)}", "${stringifyElement(container)}"`
|
|
10796
|
+
);
|
|
10797
|
+
}
|
|
10798
|
+
}
|
|
10799
|
+
}
|
|
10800
|
+
if (errorMessages.length) {
|
|
10801
|
+
const error = new InvalidFractionalIndexError();
|
|
10802
|
+
const additionalContext = [];
|
|
10803
|
+
if (reconciliationContext) {
|
|
10804
|
+
additionalContext.push("Additional reconciliation context:");
|
|
10805
|
+
additionalContext.push(
|
|
10806
|
+
reconciliationContext.localElements.map((x) => stringifyElement(x))
|
|
10807
|
+
);
|
|
10808
|
+
additionalContext.push(
|
|
10809
|
+
reconciliationContext.remoteElements.map((x) => stringifyElement(x))
|
|
10810
|
+
);
|
|
10811
|
+
}
|
|
10812
|
+
if (!ignoreLogs) {
|
|
10813
|
+
console.error(
|
|
10814
|
+
errorMessages.join("\n\n"),
|
|
10815
|
+
error.stack,
|
|
10816
|
+
elements.map((x) => stringifyElement(x)),
|
|
10817
|
+
...additionalContext
|
|
10818
|
+
);
|
|
10819
|
+
}
|
|
10820
|
+
if (shouldThrow) {
|
|
10821
|
+
throw error;
|
|
10822
|
+
}
|
|
10748
10823
|
}
|
|
10749
|
-
return getNonLinearElementRelativePoints(element);
|
|
10750
10824
|
};
|
|
10751
|
-
var
|
|
10752
|
-
|
|
10753
|
-
(
|
|
10754
|
-
|
|
10755
|
-
|
|
10756
|
-
|
|
10757
|
-
|
|
10758
|
-
|
|
10759
|
-
|
|
10760
|
-
{
|
|
10761
|
-
minX: Infinity,
|
|
10762
|
-
minY: Infinity,
|
|
10763
|
-
maxX: -Infinity,
|
|
10764
|
-
maxY: -Infinity,
|
|
10765
|
-
cx: 0,
|
|
10766
|
-
cy: 0
|
|
10825
|
+
var orderByFractionalIndex = (elements) => {
|
|
10826
|
+
return elements.sort((a2, b2) => {
|
|
10827
|
+
if (isOrderedElement(a2) && isOrderedElement(b2)) {
|
|
10828
|
+
if (a2.index < b2.index) {
|
|
10829
|
+
return -1;
|
|
10830
|
+
} else if (a2.index > b2.index) {
|
|
10831
|
+
return 1;
|
|
10832
|
+
}
|
|
10833
|
+
return a2.id < b2.id ? -1 : 1;
|
|
10767
10834
|
}
|
|
10768
|
-
|
|
10769
|
-
|
|
10770
|
-
ret.cy = (ret.maxY + ret.minY) / 2;
|
|
10771
|
-
return ret;
|
|
10835
|
+
return 1;
|
|
10836
|
+
});
|
|
10772
10837
|
};
|
|
10773
|
-
var
|
|
10774
|
-
|
|
10775
|
-
|
|
10776
|
-
|
|
10777
|
-
|
|
10778
|
-
(
|
|
10779
|
-
|
|
10780
|
-
|
|
10781
|
-
|
|
10782
|
-
|
|
10783
|
-
|
|
10784
|
-
|
|
10785
|
-
|
|
10786
|
-
|
|
10838
|
+
var syncMovedIndices = (elements, movedElements) => {
|
|
10839
|
+
try {
|
|
10840
|
+
const elementsMap = arrayToMap3(elements);
|
|
10841
|
+
const indicesGroups = getMovedIndicesGroups(elements, movedElements);
|
|
10842
|
+
const elementsUpdates = generateIndices(elements, indicesGroups);
|
|
10843
|
+
const elementsCandidates = elements.map((x) => {
|
|
10844
|
+
const elementUpdates = elementsUpdates.get(x);
|
|
10845
|
+
if (elementUpdates) {
|
|
10846
|
+
return { ...x, index: elementUpdates.index };
|
|
10847
|
+
}
|
|
10848
|
+
return x;
|
|
10849
|
+
});
|
|
10850
|
+
validateFractionalIndices(
|
|
10851
|
+
elementsCandidates,
|
|
10852
|
+
// we don't autofix invalid bound text indices, hence don't include it in the validation
|
|
10853
|
+
{
|
|
10854
|
+
includeBoundTextValidation: false,
|
|
10855
|
+
shouldThrow: true,
|
|
10856
|
+
ignoreLogs: true
|
|
10857
|
+
}
|
|
10858
|
+
);
|
|
10859
|
+
for (const [element, { index }] of elementsUpdates) {
|
|
10860
|
+
mutateElement(element, elementsMap, { index });
|
|
10861
|
+
}
|
|
10862
|
+
} catch (e) {
|
|
10863
|
+
syncInvalidIndices(elements);
|
|
10864
|
+
}
|
|
10865
|
+
return elements;
|
|
10787
10866
|
};
|
|
10788
|
-
var
|
|
10789
|
-
const
|
|
10790
|
-
const
|
|
10791
|
-
|
|
10792
|
-
|
|
10867
|
+
var syncInvalidIndices = (elements) => {
|
|
10868
|
+
const elementsMap = arrayToMap3(elements);
|
|
10869
|
+
const indicesGroups = getInvalidIndicesGroups(elements);
|
|
10870
|
+
const elementsUpdates = generateIndices(elements, indicesGroups);
|
|
10871
|
+
for (const [element, { index }] of elementsUpdates) {
|
|
10872
|
+
mutateElement(element, elementsMap, { index });
|
|
10793
10873
|
}
|
|
10794
|
-
|
|
10795
|
-
|
|
10874
|
+
return elements;
|
|
10875
|
+
};
|
|
10876
|
+
var syncInvalidIndicesImmutable = (elements) => {
|
|
10877
|
+
const syncedElements = arrayToMap3(elements);
|
|
10878
|
+
const indicesGroups = getInvalidIndicesGroups(elements);
|
|
10879
|
+
const elementsUpdates = generateIndices(elements, indicesGroups);
|
|
10880
|
+
for (const [element, { index }] of elementsUpdates) {
|
|
10881
|
+
syncedElements.set(element.id, newElementWith(element, { index }));
|
|
10796
10882
|
}
|
|
10797
|
-
return
|
|
10798
|
-
};
|
|
10799
|
-
var
|
|
10800
|
-
const
|
|
10801
|
-
|
|
10802
|
-
|
|
10803
|
-
|
|
10804
|
-
|
|
10805
|
-
|
|
10806
|
-
|
|
10807
|
-
|
|
10808
|
-
};
|
|
10809
|
-
var elementsOverlappingBBox = ({
|
|
10810
|
-
elements,
|
|
10811
|
-
bounds,
|
|
10812
|
-
type,
|
|
10813
|
-
errorMargin = 0
|
|
10814
|
-
}) => {
|
|
10815
|
-
if (isExcalidrawElement2(bounds)) {
|
|
10816
|
-
bounds = getElementBounds2(bounds, arrayToMap3(elements));
|
|
10817
|
-
}
|
|
10818
|
-
const adjustedBBox = [
|
|
10819
|
-
bounds[0] - errorMargin,
|
|
10820
|
-
bounds[1] - errorMargin,
|
|
10821
|
-
bounds[2] + errorMargin,
|
|
10822
|
-
bounds[3] + errorMargin
|
|
10823
|
-
];
|
|
10824
|
-
const includedElementSet = /* @__PURE__ */ new Set();
|
|
10825
|
-
for (const element of elements) {
|
|
10826
|
-
if (includedElementSet.has(element.id)) {
|
|
10827
|
-
continue;
|
|
10828
|
-
}
|
|
10829
|
-
const isOverlaping = type === "overlap" ? elementPartiallyOverlapsWithOrContainsBBox(element, adjustedBBox) : type === "inside" ? isElementInsideBBox(element, adjustedBBox) : isElementInsideBBox(element, adjustedBBox, true);
|
|
10830
|
-
if (isOverlaping) {
|
|
10831
|
-
includedElementSet.add(element.id);
|
|
10832
|
-
if (element.boundElements) {
|
|
10833
|
-
for (const boundElement of element.boundElements) {
|
|
10834
|
-
includedElementSet.add(boundElement.id);
|
|
10835
|
-
}
|
|
10836
|
-
}
|
|
10837
|
-
if (isTextElement2(element) && element.containerId) {
|
|
10838
|
-
includedElementSet.add(element.containerId);
|
|
10839
|
-
}
|
|
10840
|
-
if (isArrowElement2(element)) {
|
|
10841
|
-
if (element.startBinding) {
|
|
10842
|
-
includedElementSet.add(element.startBinding.elementId);
|
|
10843
|
-
}
|
|
10844
|
-
if (element.endBinding) {
|
|
10845
|
-
includedElementSet.add(element.endBinding?.elementId);
|
|
10883
|
+
return syncedElements;
|
|
10884
|
+
};
|
|
10885
|
+
var getMovedIndicesGroups = (elements, movedElements) => {
|
|
10886
|
+
const indicesGroups = [];
|
|
10887
|
+
let i = 0;
|
|
10888
|
+
while (i < elements.length) {
|
|
10889
|
+
if (movedElements.has(elements[i].id)) {
|
|
10890
|
+
const indicesGroup = [i - 1, i];
|
|
10891
|
+
while (++i < elements.length) {
|
|
10892
|
+
if (!movedElements.has(elements[i].id)) {
|
|
10893
|
+
break;
|
|
10846
10894
|
}
|
|
10895
|
+
indicesGroup.push(i);
|
|
10847
10896
|
}
|
|
10897
|
+
indicesGroup.push(i);
|
|
10898
|
+
indicesGroups.push(indicesGroup);
|
|
10899
|
+
} else {
|
|
10900
|
+
i++;
|
|
10848
10901
|
}
|
|
10849
10902
|
}
|
|
10850
|
-
return
|
|
10903
|
+
return indicesGroups;
|
|
10851
10904
|
};
|
|
10852
|
-
|
|
10853
|
-
|
|
10854
|
-
|
|
10855
|
-
|
|
10856
|
-
|
|
10857
|
-
|
|
10858
|
-
|
|
10859
|
-
|
|
10860
|
-
|
|
10861
|
-
|
|
10862
|
-
|
|
10863
|
-
|
|
10864
|
-
|
|
10905
|
+
var getInvalidIndicesGroups = (elements) => {
|
|
10906
|
+
const indicesGroups = [];
|
|
10907
|
+
let lowerBound = void 0;
|
|
10908
|
+
let upperBound = void 0;
|
|
10909
|
+
let lowerBoundIndex = -1;
|
|
10910
|
+
let upperBoundIndex = 0;
|
|
10911
|
+
const getLowerBound = (index) => {
|
|
10912
|
+
const lowerBound2 = elements[lowerBoundIndex] ? elements[lowerBoundIndex].index : void 0;
|
|
10913
|
+
const candidate = elements[index - 1]?.index;
|
|
10914
|
+
if (!lowerBound2 && candidate || // first lowerBound
|
|
10915
|
+
lowerBound2 && candidate && candidate > lowerBound2) {
|
|
10916
|
+
return [candidate, index - 1];
|
|
10917
|
+
}
|
|
10918
|
+
return [lowerBound2, lowerBoundIndex];
|
|
10919
|
+
};
|
|
10920
|
+
const getUpperBound = (index) => {
|
|
10921
|
+
const upperBound2 = elements[upperBoundIndex] ? elements[upperBoundIndex].index : void 0;
|
|
10922
|
+
if (upperBound2 && index < upperBoundIndex) {
|
|
10923
|
+
return [upperBound2, upperBoundIndex];
|
|
10924
|
+
}
|
|
10925
|
+
let i2 = upperBoundIndex;
|
|
10926
|
+
while (++i2 < elements.length) {
|
|
10927
|
+
const candidate = elements[i2]?.index;
|
|
10928
|
+
if (!upperBound2 && candidate || // first upperBound
|
|
10929
|
+
upperBound2 && candidate && candidate > upperBound2) {
|
|
10930
|
+
return [candidate, i2];
|
|
10865
10931
|
}
|
|
10866
10932
|
}
|
|
10867
|
-
|
|
10868
|
-
};
|
|
10933
|
+
return [void 0, i2];
|
|
10934
|
+
};
|
|
10935
|
+
let i = 0;
|
|
10936
|
+
while (i < elements.length) {
|
|
10937
|
+
const current = elements[i].index;
|
|
10938
|
+
[lowerBound, lowerBoundIndex] = getLowerBound(i);
|
|
10939
|
+
[upperBound, upperBoundIndex] = getUpperBound(i);
|
|
10940
|
+
if (!isValidFractionalIndex(current, lowerBound, upperBound)) {
|
|
10941
|
+
const indicesGroup = [lowerBoundIndex, i];
|
|
10942
|
+
while (++i < elements.length) {
|
|
10943
|
+
const current2 = elements[i].index;
|
|
10944
|
+
const [nextLowerBound, nextLowerBoundIndex] = getLowerBound(i);
|
|
10945
|
+
const [nextUpperBound, nextUpperBoundIndex] = getUpperBound(i);
|
|
10946
|
+
if (isValidFractionalIndex(current2, nextLowerBound, nextUpperBound)) {
|
|
10947
|
+
break;
|
|
10948
|
+
}
|
|
10949
|
+
[lowerBound, lowerBoundIndex] = [nextLowerBound, nextLowerBoundIndex];
|
|
10950
|
+
[upperBound, upperBoundIndex] = [nextUpperBound, nextUpperBoundIndex];
|
|
10951
|
+
indicesGroup.push(i);
|
|
10952
|
+
}
|
|
10953
|
+
indicesGroup.push(upperBoundIndex);
|
|
10954
|
+
indicesGroups.push(indicesGroup);
|
|
10955
|
+
} else {
|
|
10956
|
+
i++;
|
|
10957
|
+
}
|
|
10958
|
+
}
|
|
10959
|
+
return indicesGroups;
|
|
10960
|
+
};
|
|
10961
|
+
var isValidFractionalIndex = (index, predecessor, successor) => {
|
|
10962
|
+
if (!index) {
|
|
10963
|
+
return false;
|
|
10964
|
+
}
|
|
10965
|
+
try {
|
|
10966
|
+
validateOrderKey(index);
|
|
10967
|
+
} catch {
|
|
10968
|
+
return false;
|
|
10969
|
+
}
|
|
10970
|
+
if (predecessor && successor) {
|
|
10971
|
+
return predecessor < index && index < successor;
|
|
10972
|
+
}
|
|
10973
|
+
if (!predecessor && successor) {
|
|
10974
|
+
return index < successor;
|
|
10975
|
+
}
|
|
10976
|
+
if (predecessor && !successor) {
|
|
10977
|
+
return predecessor < index;
|
|
10978
|
+
}
|
|
10979
|
+
return !!index;
|
|
10980
|
+
};
|
|
10981
|
+
var generateIndices = (elements, indicesGroups) => {
|
|
10982
|
+
const elementsUpdates = /* @__PURE__ */ new Map();
|
|
10983
|
+
for (const indices of indicesGroups) {
|
|
10984
|
+
const lowerBoundIndex = indices.shift();
|
|
10985
|
+
const upperBoundIndex = indices.pop();
|
|
10986
|
+
const fractionalIndices = generateNKeysBetween(
|
|
10987
|
+
elements[lowerBoundIndex]?.index,
|
|
10988
|
+
elements[upperBoundIndex]?.index,
|
|
10989
|
+
indices.length
|
|
10990
|
+
);
|
|
10991
|
+
for (let i = 0; i < indices.length; i++) {
|
|
10992
|
+
const element = elements[indices[i]];
|
|
10993
|
+
elementsUpdates.set(element, {
|
|
10994
|
+
index: fractionalIndices[i]
|
|
10995
|
+
});
|
|
10996
|
+
}
|
|
10997
|
+
}
|
|
10998
|
+
return elementsUpdates;
|
|
10999
|
+
};
|
|
11000
|
+
var isOrderedElement = (element) => {
|
|
11001
|
+
if (element.index) {
|
|
11002
|
+
return true;
|
|
11003
|
+
}
|
|
11004
|
+
return false;
|
|
11005
|
+
};
|
|
11006
|
+
|
|
11007
|
+
// src/frame.ts
|
|
11008
|
+
var bindElementsToFramesAfterDuplication = (nextElements, origElements, origIdToDuplicateId) => {
|
|
11009
|
+
const nextElementMap = arrayToMap4(nextElements);
|
|
11010
|
+
for (const element of origElements) {
|
|
11011
|
+
if (element.frameId) {
|
|
11012
|
+
const nextElementId = origIdToDuplicateId.get(element.id);
|
|
11013
|
+
const nextFrameId = origIdToDuplicateId.get(element.frameId);
|
|
11014
|
+
const nextElement = nextElementId && nextElementMap.get(nextElementId);
|
|
11015
|
+
if (nextElement) {
|
|
11016
|
+
mutateElement(nextElement, nextElementMap, {
|
|
11017
|
+
frameId: nextFrameId ?? null
|
|
11018
|
+
});
|
|
11019
|
+
}
|
|
11020
|
+
}
|
|
11021
|
+
}
|
|
11022
|
+
};
|
|
10869
11023
|
function isElementIntersectingFrame(element, frame, elementsMap) {
|
|
10870
11024
|
const frameLineSegments = getElementLineSegments(frame, elementsMap);
|
|
10871
11025
|
const elementLineSegments = getElementLineSegments(element, elementsMap);
|
|
@@ -10882,8 +11036,9 @@ var getElementsCompletelyInFrame = (elements, frame, elementsMap) => omitGroupsC
|
|
|
10882
11036
|
(element) => !isFrameLikeElement(element) && !element.frameId || element.frameId === frame.id
|
|
10883
11037
|
);
|
|
10884
11038
|
var isElementContainingFrame = (element, frame, elementsMap) => {
|
|
10885
|
-
return
|
|
10886
|
-
(
|
|
11039
|
+
return boundsContainBounds(
|
|
11040
|
+
getElementBounds(element, elementsMap),
|
|
11041
|
+
getElementBounds(frame, elementsMap)
|
|
10887
11042
|
);
|
|
10888
11043
|
};
|
|
10889
11044
|
var getElementsIntersectingFrame = (elements, frame) => {
|
|
@@ -10906,9 +11061,9 @@ var elementOverlapsWithFrame = (element, frame, elementsMap) => {
|
|
|
10906
11061
|
var isCursorInFrame = (cursorCoords, frame, elementsMap) => {
|
|
10907
11062
|
const [fx1, fy1, fx2, fy2] = getElementAbsoluteCoords2(frame, elementsMap);
|
|
10908
11063
|
return isPointWithinBounds2(
|
|
10909
|
-
|
|
10910
|
-
|
|
10911
|
-
|
|
11064
|
+
pointFrom9(fx1, fy1),
|
|
11065
|
+
pointFrom9(cursorCoords.x, cursorCoords.y),
|
|
11066
|
+
pointFrom9(fx2, fy2)
|
|
10912
11067
|
);
|
|
10913
11068
|
};
|
|
10914
11069
|
var groupsAreAtLeastIntersectingTheFrame = (elements, groupIds, frame) => {
|
|
@@ -11116,16 +11271,35 @@ var filterElementsEligibleAsFrameChildren = (elements, frame) => {
|
|
|
11116
11271
|
}
|
|
11117
11272
|
return eligibleElements;
|
|
11118
11273
|
};
|
|
11119
|
-
var
|
|
11120
|
-
|
|
11121
|
-
const
|
|
11122
|
-
|
|
11123
|
-
|
|
11124
|
-
|
|
11274
|
+
var getCommonFrameId = (elements) => {
|
|
11275
|
+
let commonFrameId;
|
|
11276
|
+
for (const element of elements) {
|
|
11277
|
+
if (isFrameLikeElement(element) || !element.frameId) {
|
|
11278
|
+
return null;
|
|
11279
|
+
}
|
|
11280
|
+
if (commonFrameId === void 0) {
|
|
11281
|
+
commonFrameId = element.frameId;
|
|
11282
|
+
} else if (commonFrameId !== element.frameId) {
|
|
11283
|
+
return null;
|
|
11284
|
+
}
|
|
11285
|
+
}
|
|
11286
|
+
return commonFrameId ?? null;
|
|
11287
|
+
};
|
|
11288
|
+
var getFrameChildrenInsertionIndex = (elements, frameId) => {
|
|
11289
|
+
for (let index = elements.length - 1; index >= 0; index--) {
|
|
11290
|
+
const element = elements[index];
|
|
11291
|
+
if (element.id === frameId) {
|
|
11292
|
+
return index;
|
|
11293
|
+
} else if (element.frameId === frameId) {
|
|
11294
|
+
return index + 1;
|
|
11125
11295
|
}
|
|
11126
11296
|
}
|
|
11127
|
-
|
|
11128
|
-
|
|
11297
|
+
return null;
|
|
11298
|
+
};
|
|
11299
|
+
var addElementsToFrame = (allElements, elementsToAdd, frame) => {
|
|
11300
|
+
const elementsMap = arrayToMap4(allElements);
|
|
11301
|
+
const commonFrameId = getCommonFrameId(elementsToAdd);
|
|
11302
|
+
const finalElementsToAdd = /* @__PURE__ */ new Set();
|
|
11129
11303
|
const otherFrames = /* @__PURE__ */ new Set();
|
|
11130
11304
|
for (const element of elementsToAdd) {
|
|
11131
11305
|
if (isFrameLikeElement(element) && element.id !== frame.id) {
|
|
@@ -11139,23 +11313,44 @@ var addElementsToFrame = (allElements, elementsToAdd, frame, appState) => {
|
|
|
11139
11313
|
if (isFrameLikeElement(element) || element.frameId && otherFrames.has(element.frameId)) {
|
|
11140
11314
|
continue;
|
|
11141
11315
|
}
|
|
11142
|
-
if (element.frameId &&
|
|
11316
|
+
if (element.frameId && element.frameId !== frame.id) {
|
|
11143
11317
|
continue;
|
|
11144
11318
|
}
|
|
11145
|
-
|
|
11146
|
-
finalElementsToAdd.push(element);
|
|
11147
|
-
}
|
|
11319
|
+
finalElementsToAdd.add(element);
|
|
11148
11320
|
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
11149
|
-
if (boundTextElement && !
|
|
11150
|
-
finalElementsToAdd.
|
|
11321
|
+
if (boundTextElement && !finalElementsToAdd.has(boundTextElement)) {
|
|
11322
|
+
finalElementsToAdd.add(boundTextElement);
|
|
11151
11323
|
}
|
|
11152
11324
|
}
|
|
11153
11325
|
for (const element of finalElementsToAdd) {
|
|
11154
|
-
|
|
11155
|
-
|
|
11156
|
-
|
|
11326
|
+
if (element.frameId !== frame.id) {
|
|
11327
|
+
mutateElement(element, elementsMap, {
|
|
11328
|
+
frameId: frame.id
|
|
11329
|
+
});
|
|
11330
|
+
}
|
|
11157
11331
|
}
|
|
11158
|
-
|
|
11332
|
+
if (!finalElementsToAdd.size || // if all elements to add already belong to the frame, then we don't want to
|
|
11333
|
+
// reorder (case: we're dragging element children within the frame)
|
|
11334
|
+
commonFrameId === frame.id) {
|
|
11335
|
+
return allElements;
|
|
11336
|
+
}
|
|
11337
|
+
const otherElements = Array.from(allElements.values()).filter(
|
|
11338
|
+
(element) => !finalElementsToAdd.has(element)
|
|
11339
|
+
);
|
|
11340
|
+
const insertionIndex = getFrameChildrenInsertionIndex(
|
|
11341
|
+
otherElements,
|
|
11342
|
+
frame.id
|
|
11343
|
+
);
|
|
11344
|
+
if (insertionIndex === null) {
|
|
11345
|
+
return allElements;
|
|
11346
|
+
}
|
|
11347
|
+
const reorderedElements = [
|
|
11348
|
+
...otherElements.slice(0, insertionIndex),
|
|
11349
|
+
...finalElementsToAdd,
|
|
11350
|
+
...otherElements.slice(insertionIndex)
|
|
11351
|
+
];
|
|
11352
|
+
syncMovedIndices(reorderedElements, arrayToMap4([...finalElementsToAdd]));
|
|
11353
|
+
return Array.isArray(allElements) ? reorderedElements : new Map(reorderedElements.map((element) => [element.id, element]));
|
|
11159
11354
|
};
|
|
11160
11355
|
var removeElementsFromFrame = (elementsToRemove, elementsMap) => {
|
|
11161
11356
|
const _elementsToRemove = /* @__PURE__ */ new Map();
|
|
@@ -11184,12 +11379,11 @@ var removeAllElementsFromFrame = (allElements, frame) => {
|
|
|
11184
11379
|
removeElementsFromFrame(elementsInFrame, arrayToMap4(allElements));
|
|
11185
11380
|
return allElements;
|
|
11186
11381
|
};
|
|
11187
|
-
var replaceAllElementsInFrame = (allElements, nextElementsInFrame, frame
|
|
11382
|
+
var replaceAllElementsInFrame = (allElements, nextElementsInFrame, frame) => {
|
|
11188
11383
|
return addElementsToFrame(
|
|
11189
11384
|
removeAllElementsFromFrame(allElements, frame),
|
|
11190
11385
|
nextElementsInFrame,
|
|
11191
|
-
frame
|
|
11192
|
-
app.state
|
|
11386
|
+
frame
|
|
11193
11387
|
).slice();
|
|
11194
11388
|
};
|
|
11195
11389
|
var updateFrameMembershipOfSelectedElements = (allElements, appState, app) => {
|
|
@@ -11354,12 +11548,17 @@ var getDefaultFrameName = (element) => {
|
|
|
11354
11548
|
var getFrameLikeTitle = (element) => {
|
|
11355
11549
|
return element.name === null ? getDefaultFrameName(element) : element.name;
|
|
11356
11550
|
};
|
|
11357
|
-
var getElementsOverlappingFrame = (elements, frame) => {
|
|
11358
|
-
return
|
|
11359
|
-
|
|
11360
|
-
|
|
11361
|
-
|
|
11362
|
-
|
|
11551
|
+
var getElementsOverlappingFrame = (elements, frame, elementsMap) => {
|
|
11552
|
+
return elements.filter(
|
|
11553
|
+
(el) => (
|
|
11554
|
+
// exclude elements which are overlapping, but are in a different frame,
|
|
11555
|
+
// and thus invisible in target frame
|
|
11556
|
+
(!el.frameId || el.frameId === frame.id) && doBoundsIntersect(
|
|
11557
|
+
getElementBounds(el, elementsMap),
|
|
11558
|
+
getElementBounds(frame, elementsMap)
|
|
11559
|
+
)
|
|
11560
|
+
)
|
|
11561
|
+
);
|
|
11363
11562
|
};
|
|
11364
11563
|
var frameAndChildrenSelectedTogether = (selectedElements) => {
|
|
11365
11564
|
const selectedElementsMap = arrayToMap4(selectedElements);
|
|
@@ -11369,6 +11568,15 @@ var frameAndChildrenSelectedTogether = (selectedElements) => {
|
|
|
11369
11568
|
};
|
|
11370
11569
|
|
|
11371
11570
|
// src/selection.ts
|
|
11571
|
+
var shouldIgnoreElementFromSelection = (element) => element.locked || isBoundToContainer(element);
|
|
11572
|
+
var excludeElementsFromFrames = (selectedElements, framesInSelection) => {
|
|
11573
|
+
return selectedElements.filter((element) => {
|
|
11574
|
+
if (element.frameId && framesInSelection.has(element.frameId)) {
|
|
11575
|
+
return false;
|
|
11576
|
+
}
|
|
11577
|
+
return true;
|
|
11578
|
+
});
|
|
11579
|
+
};
|
|
11372
11580
|
var excludeElementsInFramesFromSelection = (selectedElements) => {
|
|
11373
11581
|
const framesInSelection = /* @__PURE__ */ new Set();
|
|
11374
11582
|
selectedElements.forEach((element) => {
|
|
@@ -11376,42 +11584,211 @@ var excludeElementsInFramesFromSelection = (selectedElements) => {
|
|
|
11376
11584
|
framesInSelection.add(element.id);
|
|
11377
11585
|
}
|
|
11378
11586
|
});
|
|
11379
|
-
return selectedElements
|
|
11380
|
-
|
|
11381
|
-
|
|
11587
|
+
return excludeElementsFromFrames(selectedElements, framesInSelection);
|
|
11588
|
+
};
|
|
11589
|
+
var getElementsWithinSelection = (elements, selection, elementsMap, excludeElementsInFrames = true, boxSelectionMode = "contain") => {
|
|
11590
|
+
const [selectionStartX, selectionStartY, selectionEndX, selectionEndY] = getElementAbsoluteCoords2(selection, elementsMap);
|
|
11591
|
+
const selectionX1 = Math.min(selectionStartX, selectionEndX);
|
|
11592
|
+
const selectionY1 = Math.min(selectionStartY, selectionEndY);
|
|
11593
|
+
const selectionX2 = Math.max(selectionStartX, selectionEndX);
|
|
11594
|
+
const selectionY2 = Math.max(selectionStartY, selectionEndY);
|
|
11595
|
+
const selectionBounds = [
|
|
11596
|
+
selectionX1,
|
|
11597
|
+
selectionY1,
|
|
11598
|
+
selectionX2,
|
|
11599
|
+
selectionY2
|
|
11600
|
+
];
|
|
11601
|
+
const selectionEdges = [
|
|
11602
|
+
lineSegment5(
|
|
11603
|
+
pointFrom10(selectionX1, selectionY1),
|
|
11604
|
+
pointFrom10(selectionX2, selectionY1)
|
|
11605
|
+
),
|
|
11606
|
+
lineSegment5(
|
|
11607
|
+
pointFrom10(selectionX2, selectionY1),
|
|
11608
|
+
pointFrom10(selectionX2, selectionY2)
|
|
11609
|
+
),
|
|
11610
|
+
lineSegment5(
|
|
11611
|
+
pointFrom10(selectionX2, selectionY2),
|
|
11612
|
+
pointFrom10(selectionX1, selectionY2)
|
|
11613
|
+
),
|
|
11614
|
+
lineSegment5(
|
|
11615
|
+
pointFrom10(selectionX1, selectionY2),
|
|
11616
|
+
pointFrom10(selectionX1, selectionY1)
|
|
11617
|
+
)
|
|
11618
|
+
];
|
|
11619
|
+
const framesInSelection = excludeElementsInFrames ? /* @__PURE__ */ new Set() : null;
|
|
11620
|
+
const groups = {};
|
|
11621
|
+
const elementsInSelection = /* @__PURE__ */ new Set();
|
|
11622
|
+
for (const element of elements) {
|
|
11623
|
+
if (shouldIgnoreElementFromSelection(element)) {
|
|
11624
|
+
continue;
|
|
11382
11625
|
}
|
|
11383
|
-
|
|
11384
|
-
|
|
11385
|
-
|
|
11386
|
-
|
|
11387
|
-
|
|
11388
|
-
|
|
11389
|
-
|
|
11390
|
-
|
|
11391
|
-
|
|
11392
|
-
);
|
|
11393
|
-
|
|
11394
|
-
|
|
11395
|
-
|
|
11396
|
-
|
|
11626
|
+
const groupId = element.groupIds.at(-1);
|
|
11627
|
+
if (groupId) {
|
|
11628
|
+
if (!groups[groupId]) {
|
|
11629
|
+
groups[groupId] = [];
|
|
11630
|
+
}
|
|
11631
|
+
groups[groupId].push(element);
|
|
11632
|
+
}
|
|
11633
|
+
const strokeWidth = element.strokeWidth;
|
|
11634
|
+
let labelAABB = null;
|
|
11635
|
+
let elementAABB = getElementBounds(element, elementsMap);
|
|
11636
|
+
elementAABB = [
|
|
11637
|
+
elementAABB[0] - strokeWidth / 2,
|
|
11638
|
+
elementAABB[1] - strokeWidth / 2,
|
|
11639
|
+
elementAABB[2] + strokeWidth / 2,
|
|
11640
|
+
elementAABB[3] + strokeWidth / 2
|
|
11641
|
+
];
|
|
11642
|
+
const boundTextElement = isArrowElement(element) && getBoundTextElement(element, elementsMap);
|
|
11643
|
+
if (boundTextElement) {
|
|
11644
|
+
const { x, y } = LinearElementEditor.getBoundTextElementPosition(
|
|
11645
|
+
element,
|
|
11646
|
+
boundTextElement,
|
|
11397
11647
|
elementsMap
|
|
11398
11648
|
);
|
|
11399
|
-
|
|
11400
|
-
|
|
11401
|
-
|
|
11402
|
-
|
|
11649
|
+
labelAABB = [
|
|
11650
|
+
x,
|
|
11651
|
+
y,
|
|
11652
|
+
x + boundTextElement.width,
|
|
11653
|
+
y + boundTextElement.height
|
|
11654
|
+
];
|
|
11403
11655
|
}
|
|
11404
|
-
|
|
11405
|
-
|
|
11406
|
-
|
|
11407
|
-
|
|
11408
|
-
|
|
11409
|
-
|
|
11410
|
-
|
|
11656
|
+
const associatedFrame = getContainingFrame(element, elementsMap);
|
|
11657
|
+
if (associatedFrame && elementOverlapsWithFrame(element, associatedFrame, elementsMap)) {
|
|
11658
|
+
const frameAABB = getElementBounds(associatedFrame, elementsMap);
|
|
11659
|
+
elementAABB = [
|
|
11660
|
+
Math.max(elementAABB[0], frameAABB[0]),
|
|
11661
|
+
Math.max(elementAABB[1], frameAABB[1]),
|
|
11662
|
+
Math.min(elementAABB[2], frameAABB[2]),
|
|
11663
|
+
Math.min(elementAABB[3], frameAABB[3])
|
|
11664
|
+
];
|
|
11665
|
+
labelAABB = labelAABB ? [
|
|
11666
|
+
Math.max(labelAABB[0], frameAABB[0]),
|
|
11667
|
+
Math.max(labelAABB[1], frameAABB[1]),
|
|
11668
|
+
Math.min(labelAABB[2], frameAABB[2]),
|
|
11669
|
+
Math.min(labelAABB[3], frameAABB[3])
|
|
11670
|
+
] : null;
|
|
11671
|
+
}
|
|
11672
|
+
const commonAABB2 = labelAABB ? [
|
|
11673
|
+
Math.min(labelAABB[0], elementAABB[0]),
|
|
11674
|
+
Math.min(labelAABB[1], elementAABB[1]),
|
|
11675
|
+
Math.max(labelAABB[2], elementAABB[2]),
|
|
11676
|
+
Math.max(labelAABB[3], elementAABB[3])
|
|
11677
|
+
] : elementAABB;
|
|
11678
|
+
if (boundsContainBounds(selectionBounds, commonAABB2)) {
|
|
11679
|
+
if (framesInSelection && isFrameLikeElement(element)) {
|
|
11680
|
+
framesInSelection.add(element.id);
|
|
11681
|
+
}
|
|
11682
|
+
elementsInSelection.add(element);
|
|
11683
|
+
continue;
|
|
11411
11684
|
}
|
|
11412
|
-
|
|
11413
|
-
|
|
11414
|
-
|
|
11685
|
+
if (boxSelectionMode === "overlap" && labelAABB && doBoundsIntersect(selectionBounds, labelAABB)) {
|
|
11686
|
+
elementsInSelection.add(element);
|
|
11687
|
+
continue;
|
|
11688
|
+
}
|
|
11689
|
+
if (boxSelectionMode === "overlap" && doBoundsIntersect(selectionBounds, elementAABB)) {
|
|
11690
|
+
let hasIntersection = false;
|
|
11691
|
+
if (isLinearElement(element) || isFreeDrawElement(element)) {
|
|
11692
|
+
const center = elementCenterPoint(element, elementsMap);
|
|
11693
|
+
hasIntersection = element.points.some((point) => {
|
|
11694
|
+
const rotatedPoint = pointRotateRads9(
|
|
11695
|
+
pointFrom10(element.x + point[0], element.y + point[1]),
|
|
11696
|
+
center,
|
|
11697
|
+
element.angle
|
|
11698
|
+
);
|
|
11699
|
+
return pointInsideBounds(rotatedPoint, selectionBounds);
|
|
11700
|
+
});
|
|
11701
|
+
} else {
|
|
11702
|
+
const nonRotatedElementBounds = getElementBounds(
|
|
11703
|
+
element,
|
|
11704
|
+
elementsMap,
|
|
11705
|
+
true
|
|
11706
|
+
);
|
|
11707
|
+
const center = elementCenterPoint(element, elementsMap);
|
|
11708
|
+
hasIntersection = [
|
|
11709
|
+
pointRotateRads9(
|
|
11710
|
+
pointFrom10(
|
|
11711
|
+
(nonRotatedElementBounds[0] + nonRotatedElementBounds[2]) / 2,
|
|
11712
|
+
nonRotatedElementBounds[1]
|
|
11713
|
+
),
|
|
11714
|
+
center,
|
|
11715
|
+
element.angle
|
|
11716
|
+
),
|
|
11717
|
+
pointRotateRads9(
|
|
11718
|
+
pointFrom10(
|
|
11719
|
+
nonRotatedElementBounds[2],
|
|
11720
|
+
(nonRotatedElementBounds[1] + nonRotatedElementBounds[3]) / 2
|
|
11721
|
+
),
|
|
11722
|
+
center,
|
|
11723
|
+
element.angle
|
|
11724
|
+
),
|
|
11725
|
+
pointRotateRads9(
|
|
11726
|
+
pointFrom10(
|
|
11727
|
+
(nonRotatedElementBounds[0] + nonRotatedElementBounds[2]) / 2,
|
|
11728
|
+
nonRotatedElementBounds[3]
|
|
11729
|
+
),
|
|
11730
|
+
center,
|
|
11731
|
+
element.angle
|
|
11732
|
+
),
|
|
11733
|
+
pointRotateRads9(
|
|
11734
|
+
pointFrom10(
|
|
11735
|
+
nonRotatedElementBounds[0],
|
|
11736
|
+
(nonRotatedElementBounds[1] + nonRotatedElementBounds[3]) / 2
|
|
11737
|
+
),
|
|
11738
|
+
center,
|
|
11739
|
+
element.angle
|
|
11740
|
+
)
|
|
11741
|
+
].some((point) => {
|
|
11742
|
+
return pointInsideBounds(
|
|
11743
|
+
pointRotateRads9(point, center, element.angle),
|
|
11744
|
+
selectionBounds
|
|
11745
|
+
);
|
|
11746
|
+
});
|
|
11747
|
+
}
|
|
11748
|
+
if (!hasIntersection) {
|
|
11749
|
+
hasIntersection = selectionEdges.some(
|
|
11750
|
+
(selectionEdge) => intersectElementWithLineSegment(
|
|
11751
|
+
element,
|
|
11752
|
+
elementsMap,
|
|
11753
|
+
selectionEdge,
|
|
11754
|
+
strokeWidth / 2,
|
|
11755
|
+
true
|
|
11756
|
+
// Stop at first hit for better performance
|
|
11757
|
+
).length > 0
|
|
11758
|
+
);
|
|
11759
|
+
}
|
|
11760
|
+
if (hasIntersection) {
|
|
11761
|
+
if (framesInSelection && isFrameLikeElement(element)) {
|
|
11762
|
+
framesInSelection.add(element.id);
|
|
11763
|
+
}
|
|
11764
|
+
elementsInSelection.add(element);
|
|
11765
|
+
continue;
|
|
11766
|
+
}
|
|
11767
|
+
}
|
|
11768
|
+
}
|
|
11769
|
+
if (framesInSelection) {
|
|
11770
|
+
elementsInSelection.forEach((element) => {
|
|
11771
|
+
if (element.frameId && framesInSelection.has(element.frameId)) {
|
|
11772
|
+
elementsInSelection.delete(element);
|
|
11773
|
+
}
|
|
11774
|
+
});
|
|
11775
|
+
}
|
|
11776
|
+
if (boxSelectionMode === "overlap") {
|
|
11777
|
+
Array.from(elementsInSelection).forEach((element) => {
|
|
11778
|
+
const groupId = element.groupIds.at(-1);
|
|
11779
|
+
const group = groupId ? groups[groupId] : null;
|
|
11780
|
+
group?.forEach((groupElement) => elementsInSelection.add(groupElement));
|
|
11781
|
+
});
|
|
11782
|
+
} else if (boxSelectionMode === "contain") {
|
|
11783
|
+
elementsInSelection.forEach((element) => {
|
|
11784
|
+
const groupId = element.groupIds.at(-1);
|
|
11785
|
+
const group = groupId ? groups[groupId] : null;
|
|
11786
|
+
if (group && !group.every((groupElement) => elementsInSelection.has(groupElement))) {
|
|
11787
|
+
elementsInSelection.delete(element);
|
|
11788
|
+
}
|
|
11789
|
+
});
|
|
11790
|
+
}
|
|
11791
|
+
return elements.filter((element) => elementsInSelection.has(element));
|
|
11415
11792
|
};
|
|
11416
11793
|
var getVisibleAndNonSelectedElements = (elements, selectedElements, appState, elementsMap) => {
|
|
11417
11794
|
const selectedElementsSet = new Set(
|
|
@@ -11654,604 +12031,150 @@ var selectGroupsFromGivenElements = (elements, appState) => {
|
|
|
11654
12031
|
...appState,
|
|
11655
12032
|
selectedGroupIds: {}
|
|
11656
12033
|
};
|
|
11657
|
-
for (const element of elements) {
|
|
11658
|
-
let groupIds = element.groupIds;
|
|
11659
|
-
if (appState.editingGroupId) {
|
|
11660
|
-
const indexOfEditingGroup = groupIds.indexOf(appState.editingGroupId);
|
|
11661
|
-
if (indexOfEditingGroup > -1) {
|
|
11662
|
-
groupIds = groupIds.slice(0, indexOfEditingGroup);
|
|
11663
|
-
}
|
|
11664
|
-
}
|
|
11665
|
-
if (groupIds.length > 0) {
|
|
11666
|
-
const groupId = groupIds[groupIds.length - 1];
|
|
11667
|
-
nextAppState = {
|
|
11668
|
-
...nextAppState,
|
|
11669
|
-
...selectGroup(groupId, nextAppState, elements)
|
|
11670
|
-
};
|
|
11671
|
-
}
|
|
11672
|
-
}
|
|
11673
|
-
return nextAppState.selectedGroupIds;
|
|
11674
|
-
};
|
|
11675
|
-
var editGroupForSelectedElement = (appState, element) => {
|
|
11676
|
-
return {
|
|
11677
|
-
...appState,
|
|
11678
|
-
editingGroupId: element.groupIds.length ? element.groupIds[0] : null,
|
|
11679
|
-
selectedGroupIds: {},
|
|
11680
|
-
selectedElementIds: {
|
|
11681
|
-
[element.id]: true
|
|
11682
|
-
}
|
|
11683
|
-
};
|
|
11684
|
-
};
|
|
11685
|
-
var isElementInGroup = (element, groupId) => element.groupIds.includes(groupId);
|
|
11686
|
-
var getElementsInGroup = (elements, groupId) => {
|
|
11687
|
-
const elementsInGroup = [];
|
|
11688
|
-
for (const element of elements.values()) {
|
|
11689
|
-
if (isElementInGroup(element, groupId)) {
|
|
11690
|
-
elementsInGroup.push(element);
|
|
11691
|
-
}
|
|
11692
|
-
}
|
|
11693
|
-
return elementsInGroup;
|
|
11694
|
-
};
|
|
11695
|
-
var getSelectedGroupIdForElement = (element, selectedGroupIds) => element.groupIds.find((groupId) => selectedGroupIds[groupId]);
|
|
11696
|
-
var addToGroup = (prevGroupIds, newGroupId, editingGroupId) => {
|
|
11697
|
-
const groupIds = [...prevGroupIds];
|
|
11698
|
-
const positionOfEditingGroupId = editingGroupId ? groupIds.indexOf(editingGroupId) : -1;
|
|
11699
|
-
const positionToInsert = positionOfEditingGroupId > -1 ? positionOfEditingGroupId : groupIds.length;
|
|
11700
|
-
groupIds.splice(positionToInsert, 0, newGroupId);
|
|
11701
|
-
return groupIds;
|
|
11702
|
-
};
|
|
11703
|
-
var removeFromSelectedGroups = (groupIds, selectedGroupIds) => groupIds.filter((groupId) => !selectedGroupIds[groupId]);
|
|
11704
|
-
var getMaximumGroups = (elements, elementsMap) => {
|
|
11705
|
-
const groups = /* @__PURE__ */ new Map();
|
|
11706
|
-
elements.forEach((element) => {
|
|
11707
|
-
const groupId = element.groupIds.length === 0 ? element.id : element.groupIds[element.groupIds.length - 1];
|
|
11708
|
-
const currentGroupMembers = groups.get(groupId) || [];
|
|
11709
|
-
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
11710
|
-
if (boundTextElement) {
|
|
11711
|
-
currentGroupMembers.push(boundTextElement);
|
|
11712
|
-
}
|
|
11713
|
-
groups.set(groupId, [...currentGroupMembers, element]);
|
|
11714
|
-
});
|
|
11715
|
-
return Array.from(groups.values());
|
|
11716
|
-
};
|
|
11717
|
-
var getNonDeletedGroupIds = (elements) => {
|
|
11718
|
-
const nonDeletedGroupIds = /* @__PURE__ */ new Set();
|
|
11719
|
-
for (const [, element] of elements) {
|
|
11720
|
-
if (element.isDeleted) {
|
|
11721
|
-
continue;
|
|
11722
|
-
}
|
|
11723
|
-
for (const groupId of element.groupIds ?? []) {
|
|
11724
|
-
nonDeletedGroupIds.add(groupId);
|
|
11725
|
-
}
|
|
11726
|
-
}
|
|
11727
|
-
return nonDeletedGroupIds;
|
|
11728
|
-
};
|
|
11729
|
-
var elementsAreInSameGroup = (elements) => {
|
|
11730
|
-
const allGroups = elements.flatMap((element) => element.groupIds);
|
|
11731
|
-
const groupCount = /* @__PURE__ */ new Map();
|
|
11732
|
-
let maxGroup = 0;
|
|
11733
|
-
for (const group of allGroups) {
|
|
11734
|
-
groupCount.set(group, (groupCount.get(group) ?? 0) + 1);
|
|
11735
|
-
if (groupCount.get(group) > maxGroup) {
|
|
11736
|
-
maxGroup = groupCount.get(group);
|
|
11737
|
-
}
|
|
11738
|
-
}
|
|
11739
|
-
return maxGroup === elements.length;
|
|
11740
|
-
};
|
|
11741
|
-
var isInGroup = (element) => {
|
|
11742
|
-
return element.groupIds.length > 0;
|
|
11743
|
-
};
|
|
11744
|
-
var getNewGroupIdsForDuplication = (groupIds, editingGroupId, mapper) => {
|
|
11745
|
-
const copy = [...groupIds];
|
|
11746
|
-
const positionOfEditingGroupId = editingGroupId ? groupIds.indexOf(editingGroupId) : -1;
|
|
11747
|
-
const endIndex = positionOfEditingGroupId > -1 ? positionOfEditingGroupId : groupIds.length;
|
|
11748
|
-
for (let index = 0; index < endIndex; index++) {
|
|
11749
|
-
copy[index] = mapper(copy[index]);
|
|
11750
|
-
}
|
|
11751
|
-
return copy;
|
|
11752
|
-
};
|
|
11753
|
-
var getSelectedElementsByGroup = (selectedElements, elementsMap, appState) => {
|
|
11754
|
-
const selectedGroupIds = getSelectedGroupIds(appState);
|
|
11755
|
-
const unboundElements = selectedElements.filter(
|
|
11756
|
-
(element) => !isBoundToContainer(element)
|
|
11757
|
-
);
|
|
11758
|
-
const groups = /* @__PURE__ */ new Map();
|
|
11759
|
-
const elements = /* @__PURE__ */ new Map();
|
|
11760
|
-
const addToElementsMap = (element) => {
|
|
11761
|
-
const currentElementMembers = elements.get(element.id) || [];
|
|
11762
|
-
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
11763
|
-
if (boundTextElement) {
|
|
11764
|
-
currentElementMembers.push(boundTextElement);
|
|
11765
|
-
}
|
|
11766
|
-
elements.set(element.id, [...currentElementMembers, element]);
|
|
11767
|
-
};
|
|
11768
|
-
const addToGroupsMap = (element, groupId) => {
|
|
11769
|
-
const currentGroupMembers = groups.get(groupId) || [];
|
|
11770
|
-
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
11771
|
-
if (boundTextElement) {
|
|
11772
|
-
currentGroupMembers.push(boundTextElement);
|
|
11773
|
-
}
|
|
11774
|
-
groups.set(groupId, [...currentGroupMembers, element]);
|
|
11775
|
-
};
|
|
11776
|
-
const handleSingleSelectedGroupCase = (element, selectedGroupId) => {
|
|
11777
|
-
const indexOfSelectedGroupId = element.groupIds.indexOf(selectedGroupId, 0);
|
|
11778
|
-
const nestedGroupCount = element.groupIds.slice(
|
|
11779
|
-
0,
|
|
11780
|
-
indexOfSelectedGroupId
|
|
11781
|
-
).length;
|
|
11782
|
-
return nestedGroupCount > 0 ? addToGroupsMap(element, element.groupIds[indexOfSelectedGroupId - 1]) : addToElementsMap(element);
|
|
11783
|
-
};
|
|
11784
|
-
const isAllInSameGroup = selectedElements.every(
|
|
11785
|
-
(element) => isSelectedViaGroup(appState, element)
|
|
11786
|
-
);
|
|
11787
|
-
unboundElements.forEach((element) => {
|
|
11788
|
-
const selectedGroupId = getSelectedGroupIdForElement(
|
|
11789
|
-
element,
|
|
11790
|
-
appState.selectedGroupIds
|
|
11791
|
-
);
|
|
11792
|
-
if (!selectedGroupId) {
|
|
11793
|
-
addToElementsMap(element);
|
|
11794
|
-
} else if (selectedGroupIds.length === 1 && isAllInSameGroup) {
|
|
11795
|
-
handleSingleSelectedGroupCase(element, selectedGroupId);
|
|
11796
|
-
} else {
|
|
11797
|
-
addToGroupsMap(element, selectedGroupId);
|
|
11798
|
-
}
|
|
11799
|
-
});
|
|
11800
|
-
return Array.from(groups.values()).concat(Array.from(elements.values()));
|
|
11801
|
-
};
|
|
11802
|
-
|
|
11803
|
-
// src/fractionalIndex.ts
|
|
11804
|
-
init_define_import_meta_env();
|
|
11805
|
-
|
|
11806
|
-
// ../../node_modules/fractional-indexing/src/index.js
|
|
11807
|
-
init_define_import_meta_env();
|
|
11808
|
-
var BASE_62_DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
11809
|
-
function midpoint(a2, b2, digits) {
|
|
11810
|
-
const zero = digits[0];
|
|
11811
|
-
if (b2 != null && a2 >= b2) {
|
|
11812
|
-
throw new Error(a2 + " >= " + b2);
|
|
11813
|
-
}
|
|
11814
|
-
if (a2.slice(-1) === zero || b2 && b2.slice(-1) === zero) {
|
|
11815
|
-
throw new Error("trailing zero");
|
|
11816
|
-
}
|
|
11817
|
-
if (b2) {
|
|
11818
|
-
let n = 0;
|
|
11819
|
-
while ((a2[n] || zero) === b2[n]) {
|
|
11820
|
-
n++;
|
|
11821
|
-
}
|
|
11822
|
-
if (n > 0) {
|
|
11823
|
-
return b2.slice(0, n) + midpoint(a2.slice(n), b2.slice(n), digits);
|
|
11824
|
-
}
|
|
11825
|
-
}
|
|
11826
|
-
const digitA = a2 ? digits.indexOf(a2[0]) : 0;
|
|
11827
|
-
const digitB = b2 != null ? digits.indexOf(b2[0]) : digits.length;
|
|
11828
|
-
if (digitB - digitA > 1) {
|
|
11829
|
-
const midDigit = Math.round(0.5 * (digitA + digitB));
|
|
11830
|
-
return digits[midDigit];
|
|
11831
|
-
} else {
|
|
11832
|
-
if (b2 && b2.length > 1) {
|
|
11833
|
-
return b2.slice(0, 1);
|
|
11834
|
-
} else {
|
|
11835
|
-
return digits[digitA] + midpoint(a2.slice(1), null, digits);
|
|
11836
|
-
}
|
|
11837
|
-
}
|
|
11838
|
-
}
|
|
11839
|
-
function validateInteger(int) {
|
|
11840
|
-
if (int.length !== getIntegerLength(int[0])) {
|
|
11841
|
-
throw new Error("invalid integer part of order key: " + int);
|
|
11842
|
-
}
|
|
11843
|
-
}
|
|
11844
|
-
function getIntegerLength(head) {
|
|
11845
|
-
if (head >= "a" && head <= "z") {
|
|
11846
|
-
return head.charCodeAt(0) - "a".charCodeAt(0) + 2;
|
|
11847
|
-
} else if (head >= "A" && head <= "Z") {
|
|
11848
|
-
return "Z".charCodeAt(0) - head.charCodeAt(0) + 2;
|
|
11849
|
-
} else {
|
|
11850
|
-
throw new Error("invalid order key head: " + head);
|
|
11851
|
-
}
|
|
11852
|
-
}
|
|
11853
|
-
function getIntegerPart(key) {
|
|
11854
|
-
const integerPartLength = getIntegerLength(key[0]);
|
|
11855
|
-
if (integerPartLength > key.length) {
|
|
11856
|
-
throw new Error("invalid order key: " + key);
|
|
11857
|
-
}
|
|
11858
|
-
return key.slice(0, integerPartLength);
|
|
11859
|
-
}
|
|
11860
|
-
function validateOrderKey(key, digits) {
|
|
11861
|
-
if (key === "A" + digits[0].repeat(26)) {
|
|
11862
|
-
throw new Error("invalid order key: " + key);
|
|
11863
|
-
}
|
|
11864
|
-
const i = getIntegerPart(key);
|
|
11865
|
-
const f = key.slice(i.length);
|
|
11866
|
-
if (f.slice(-1) === digits[0]) {
|
|
11867
|
-
throw new Error("invalid order key: " + key);
|
|
11868
|
-
}
|
|
11869
|
-
}
|
|
11870
|
-
function incrementInteger(x, digits) {
|
|
11871
|
-
validateInteger(x);
|
|
11872
|
-
const [head, ...digs] = x.split("");
|
|
11873
|
-
let carry = true;
|
|
11874
|
-
for (let i = digs.length - 1; carry && i >= 0; i--) {
|
|
11875
|
-
const d = digits.indexOf(digs[i]) + 1;
|
|
11876
|
-
if (d === digits.length) {
|
|
11877
|
-
digs[i] = digits[0];
|
|
11878
|
-
} else {
|
|
11879
|
-
digs[i] = digits[d];
|
|
11880
|
-
carry = false;
|
|
11881
|
-
}
|
|
11882
|
-
}
|
|
11883
|
-
if (carry) {
|
|
11884
|
-
if (head === "Z") {
|
|
11885
|
-
return "a" + digits[0];
|
|
11886
|
-
}
|
|
11887
|
-
if (head === "z") {
|
|
11888
|
-
return null;
|
|
11889
|
-
}
|
|
11890
|
-
const h = String.fromCharCode(head.charCodeAt(0) + 1);
|
|
11891
|
-
if (h > "a") {
|
|
11892
|
-
digs.push(digits[0]);
|
|
11893
|
-
} else {
|
|
11894
|
-
digs.pop();
|
|
11895
|
-
}
|
|
11896
|
-
return h + digs.join("");
|
|
11897
|
-
} else {
|
|
11898
|
-
return head + digs.join("");
|
|
11899
|
-
}
|
|
11900
|
-
}
|
|
11901
|
-
function decrementInteger(x, digits) {
|
|
11902
|
-
validateInteger(x);
|
|
11903
|
-
const [head, ...digs] = x.split("");
|
|
11904
|
-
let borrow = true;
|
|
11905
|
-
for (let i = digs.length - 1; borrow && i >= 0; i--) {
|
|
11906
|
-
const d = digits.indexOf(digs[i]) - 1;
|
|
11907
|
-
if (d === -1) {
|
|
11908
|
-
digs[i] = digits.slice(-1);
|
|
11909
|
-
} else {
|
|
11910
|
-
digs[i] = digits[d];
|
|
11911
|
-
borrow = false;
|
|
11912
|
-
}
|
|
11913
|
-
}
|
|
11914
|
-
if (borrow) {
|
|
11915
|
-
if (head === "a") {
|
|
11916
|
-
return "Z" + digits.slice(-1);
|
|
11917
|
-
}
|
|
11918
|
-
if (head === "A") {
|
|
11919
|
-
return null;
|
|
11920
|
-
}
|
|
11921
|
-
const h = String.fromCharCode(head.charCodeAt(0) - 1);
|
|
11922
|
-
if (h < "Z") {
|
|
11923
|
-
digs.push(digits.slice(-1));
|
|
11924
|
-
} else {
|
|
11925
|
-
digs.pop();
|
|
11926
|
-
}
|
|
11927
|
-
return h + digs.join("");
|
|
11928
|
-
} else {
|
|
11929
|
-
return head + digs.join("");
|
|
11930
|
-
}
|
|
11931
|
-
}
|
|
11932
|
-
function generateKeyBetween(a2, b2, digits = BASE_62_DIGITS) {
|
|
11933
|
-
if (a2 != null) {
|
|
11934
|
-
validateOrderKey(a2, digits);
|
|
11935
|
-
}
|
|
11936
|
-
if (b2 != null) {
|
|
11937
|
-
validateOrderKey(b2, digits);
|
|
11938
|
-
}
|
|
11939
|
-
if (a2 != null && b2 != null && a2 >= b2) {
|
|
11940
|
-
throw new Error(a2 + " >= " + b2);
|
|
11941
|
-
}
|
|
11942
|
-
if (a2 == null) {
|
|
11943
|
-
if (b2 == null) {
|
|
11944
|
-
return "a" + digits[0];
|
|
11945
|
-
}
|
|
11946
|
-
const ib2 = getIntegerPart(b2);
|
|
11947
|
-
const fb2 = b2.slice(ib2.length);
|
|
11948
|
-
if (ib2 === "A" + digits[0].repeat(26)) {
|
|
11949
|
-
return ib2 + midpoint("", fb2, digits);
|
|
11950
|
-
}
|
|
11951
|
-
if (ib2 < b2) {
|
|
11952
|
-
return ib2;
|
|
11953
|
-
}
|
|
11954
|
-
const res = decrementInteger(ib2, digits);
|
|
11955
|
-
if (res == null) {
|
|
11956
|
-
throw new Error("cannot decrement any more");
|
|
11957
|
-
}
|
|
11958
|
-
return res;
|
|
11959
|
-
}
|
|
11960
|
-
if (b2 == null) {
|
|
11961
|
-
const ia2 = getIntegerPart(a2);
|
|
11962
|
-
const fa2 = a2.slice(ia2.length);
|
|
11963
|
-
const i2 = incrementInteger(ia2, digits);
|
|
11964
|
-
return i2 == null ? ia2 + midpoint(fa2, null, digits) : i2;
|
|
11965
|
-
}
|
|
11966
|
-
const ia = getIntegerPart(a2);
|
|
11967
|
-
const fa = a2.slice(ia.length);
|
|
11968
|
-
const ib = getIntegerPart(b2);
|
|
11969
|
-
const fb = b2.slice(ib.length);
|
|
11970
|
-
if (ia === ib) {
|
|
11971
|
-
return ia + midpoint(fa, fb, digits);
|
|
11972
|
-
}
|
|
11973
|
-
const i = incrementInteger(ia, digits);
|
|
11974
|
-
if (i == null) {
|
|
11975
|
-
throw new Error("cannot increment any more");
|
|
11976
|
-
}
|
|
11977
|
-
if (i < b2) {
|
|
11978
|
-
return i;
|
|
11979
|
-
}
|
|
11980
|
-
return ia + midpoint(fa, null, digits);
|
|
11981
|
-
}
|
|
11982
|
-
function generateNKeysBetween(a2, b2, n, digits = BASE_62_DIGITS) {
|
|
11983
|
-
if (n === 0) {
|
|
11984
|
-
return [];
|
|
11985
|
-
}
|
|
11986
|
-
if (n === 1) {
|
|
11987
|
-
return [generateKeyBetween(a2, b2, digits)];
|
|
11988
|
-
}
|
|
11989
|
-
if (b2 == null) {
|
|
11990
|
-
let c2 = generateKeyBetween(a2, b2, digits);
|
|
11991
|
-
const result = [c2];
|
|
11992
|
-
for (let i = 0; i < n - 1; i++) {
|
|
11993
|
-
c2 = generateKeyBetween(c2, b2, digits);
|
|
11994
|
-
result.push(c2);
|
|
11995
|
-
}
|
|
11996
|
-
return result;
|
|
11997
|
-
}
|
|
11998
|
-
if (a2 == null) {
|
|
11999
|
-
let c2 = generateKeyBetween(a2, b2, digits);
|
|
12000
|
-
const result = [c2];
|
|
12001
|
-
for (let i = 0; i < n - 1; i++) {
|
|
12002
|
-
c2 = generateKeyBetween(a2, c2, digits);
|
|
12003
|
-
result.push(c2);
|
|
12004
|
-
}
|
|
12005
|
-
result.reverse();
|
|
12006
|
-
return result;
|
|
12007
|
-
}
|
|
12008
|
-
const mid = Math.floor(n / 2);
|
|
12009
|
-
const c = generateKeyBetween(a2, b2, digits);
|
|
12010
|
-
return [
|
|
12011
|
-
...generateNKeysBetween(a2, c, mid, digits),
|
|
12012
|
-
c,
|
|
12013
|
-
...generateNKeysBetween(c, b2, n - mid - 1, digits)
|
|
12014
|
-
];
|
|
12015
|
-
}
|
|
12016
|
-
|
|
12017
|
-
// src/fractionalIndex.ts
|
|
12018
|
-
import { arrayToMap as arrayToMap6 } from "@excalidraw/common";
|
|
12019
|
-
var InvalidFractionalIndexError = class extends Error {
|
|
12020
|
-
code = "ELEMENT_HAS_INVALID_INDEX";
|
|
12021
|
-
};
|
|
12022
|
-
var validateFractionalIndices = (elements, {
|
|
12023
|
-
shouldThrow = false,
|
|
12024
|
-
includeBoundTextValidation = false,
|
|
12025
|
-
ignoreLogs,
|
|
12026
|
-
reconciliationContext
|
|
12027
|
-
}) => {
|
|
12028
|
-
const errorMessages = [];
|
|
12029
|
-
const stringifyElement = (element) => `${element?.index}:${element?.id}:${element?.type}:${element?.isDeleted}:${element?.version}:${element?.versionNonce}`;
|
|
12030
|
-
const indices = elements.map((x) => x.index);
|
|
12031
|
-
for (const [i, index] of indices.entries()) {
|
|
12032
|
-
const predecessorIndex = indices[i - 1];
|
|
12033
|
-
const successorIndex = indices[i + 1];
|
|
12034
|
-
if (!isValidFractionalIndex(index, predecessorIndex, successorIndex)) {
|
|
12035
|
-
errorMessages.push(
|
|
12036
|
-
`Fractional indices invariant has been compromised: "${stringifyElement(
|
|
12037
|
-
elements[i - 1]
|
|
12038
|
-
)}", "${stringifyElement(elements[i])}", "${stringifyElement(
|
|
12039
|
-
elements[i + 1]
|
|
12040
|
-
)}"`
|
|
12041
|
-
);
|
|
12042
|
-
}
|
|
12043
|
-
if (includeBoundTextValidation && hasBoundTextElement(elements[i])) {
|
|
12044
|
-
const container = elements[i];
|
|
12045
|
-
const text = getBoundTextElement(container, arrayToMap6(elements));
|
|
12046
|
-
if (text && text.index <= container.index) {
|
|
12047
|
-
errorMessages.push(
|
|
12048
|
-
`Fractional indices invariant for bound elements has been compromised: "${stringifyElement(
|
|
12049
|
-
text
|
|
12050
|
-
)}", "${stringifyElement(container)}"`
|
|
12051
|
-
);
|
|
12052
|
-
}
|
|
12053
|
-
}
|
|
12054
|
-
}
|
|
12055
|
-
if (errorMessages.length) {
|
|
12056
|
-
const error = new InvalidFractionalIndexError();
|
|
12057
|
-
const additionalContext = [];
|
|
12058
|
-
if (reconciliationContext) {
|
|
12059
|
-
additionalContext.push("Additional reconciliation context:");
|
|
12060
|
-
additionalContext.push(
|
|
12061
|
-
reconciliationContext.localElements.map((x) => stringifyElement(x))
|
|
12062
|
-
);
|
|
12063
|
-
additionalContext.push(
|
|
12064
|
-
reconciliationContext.remoteElements.map((x) => stringifyElement(x))
|
|
12065
|
-
);
|
|
12066
|
-
}
|
|
12067
|
-
if (!ignoreLogs) {
|
|
12068
|
-
console.error(
|
|
12069
|
-
errorMessages.join("\n\n"),
|
|
12070
|
-
error.stack,
|
|
12071
|
-
elements.map((x) => stringifyElement(x)),
|
|
12072
|
-
...additionalContext
|
|
12073
|
-
);
|
|
12074
|
-
}
|
|
12075
|
-
if (shouldThrow) {
|
|
12076
|
-
throw error;
|
|
12077
|
-
}
|
|
12078
|
-
}
|
|
12079
|
-
};
|
|
12080
|
-
var orderByFractionalIndex = (elements) => {
|
|
12081
|
-
return elements.sort((a2, b2) => {
|
|
12082
|
-
if (isOrderedElement(a2) && isOrderedElement(b2)) {
|
|
12083
|
-
if (a2.index < b2.index) {
|
|
12084
|
-
return -1;
|
|
12085
|
-
} else if (a2.index > b2.index) {
|
|
12086
|
-
return 1;
|
|
12087
|
-
}
|
|
12088
|
-
return a2.id < b2.id ? -1 : 1;
|
|
12089
|
-
}
|
|
12090
|
-
return 1;
|
|
12091
|
-
});
|
|
12092
|
-
};
|
|
12093
|
-
var syncMovedIndices = (elements, movedElements) => {
|
|
12094
|
-
try {
|
|
12095
|
-
const elementsMap = arrayToMap6(elements);
|
|
12096
|
-
const indicesGroups = getMovedIndicesGroups(elements, movedElements);
|
|
12097
|
-
const elementsUpdates = generateIndices(elements, indicesGroups);
|
|
12098
|
-
const elementsCandidates = elements.map((x) => {
|
|
12099
|
-
const elementUpdates = elementsUpdates.get(x);
|
|
12100
|
-
if (elementUpdates) {
|
|
12101
|
-
return { ...x, index: elementUpdates.index };
|
|
12102
|
-
}
|
|
12103
|
-
return x;
|
|
12104
|
-
});
|
|
12105
|
-
validateFractionalIndices(
|
|
12106
|
-
elementsCandidates,
|
|
12107
|
-
// we don't autofix invalid bound text indices, hence don't include it in the validation
|
|
12108
|
-
{
|
|
12109
|
-
includeBoundTextValidation: false,
|
|
12110
|
-
shouldThrow: true,
|
|
12111
|
-
ignoreLogs: true
|
|
12112
|
-
}
|
|
12113
|
-
);
|
|
12114
|
-
for (const [element, { index }] of elementsUpdates) {
|
|
12115
|
-
mutateElement(element, elementsMap, { index });
|
|
12116
|
-
}
|
|
12117
|
-
} catch (e) {
|
|
12118
|
-
syncInvalidIndices(elements);
|
|
12119
|
-
}
|
|
12120
|
-
return elements;
|
|
12121
|
-
};
|
|
12122
|
-
var syncInvalidIndices = (elements) => {
|
|
12123
|
-
const elementsMap = arrayToMap6(elements);
|
|
12124
|
-
const indicesGroups = getInvalidIndicesGroups(elements);
|
|
12125
|
-
const elementsUpdates = generateIndices(elements, indicesGroups);
|
|
12126
|
-
for (const [element, { index }] of elementsUpdates) {
|
|
12127
|
-
mutateElement(element, elementsMap, { index });
|
|
12128
|
-
}
|
|
12129
|
-
return elements;
|
|
12130
|
-
};
|
|
12131
|
-
var syncInvalidIndicesImmutable = (elements) => {
|
|
12132
|
-
const syncedElements = arrayToMap6(elements);
|
|
12133
|
-
const indicesGroups = getInvalidIndicesGroups(elements);
|
|
12134
|
-
const elementsUpdates = generateIndices(elements, indicesGroups);
|
|
12135
|
-
for (const [element, { index }] of elementsUpdates) {
|
|
12136
|
-
syncedElements.set(element.id, newElementWith(element, { index }));
|
|
12137
|
-
}
|
|
12138
|
-
return syncedElements;
|
|
12139
|
-
};
|
|
12140
|
-
var getMovedIndicesGroups = (elements, movedElements) => {
|
|
12141
|
-
const indicesGroups = [];
|
|
12142
|
-
let i = 0;
|
|
12143
|
-
while (i < elements.length) {
|
|
12144
|
-
if (movedElements.has(elements[i].id)) {
|
|
12145
|
-
const indicesGroup = [i - 1, i];
|
|
12146
|
-
while (++i < elements.length) {
|
|
12147
|
-
if (!movedElements.has(elements[i].id)) {
|
|
12148
|
-
break;
|
|
12149
|
-
}
|
|
12150
|
-
indicesGroup.push(i);
|
|
12151
|
-
}
|
|
12152
|
-
indicesGroup.push(i);
|
|
12153
|
-
indicesGroups.push(indicesGroup);
|
|
12154
|
-
} else {
|
|
12155
|
-
i++;
|
|
12156
|
-
}
|
|
12157
|
-
}
|
|
12158
|
-
return indicesGroups;
|
|
12159
|
-
};
|
|
12160
|
-
var getInvalidIndicesGroups = (elements) => {
|
|
12161
|
-
const indicesGroups = [];
|
|
12162
|
-
let lowerBound = void 0;
|
|
12163
|
-
let upperBound = void 0;
|
|
12164
|
-
let lowerBoundIndex = -1;
|
|
12165
|
-
let upperBoundIndex = 0;
|
|
12166
|
-
const getLowerBound = (index) => {
|
|
12167
|
-
const lowerBound2 = elements[lowerBoundIndex] ? elements[lowerBoundIndex].index : void 0;
|
|
12168
|
-
const candidate = elements[index - 1]?.index;
|
|
12169
|
-
if (!lowerBound2 && candidate || // first lowerBound
|
|
12170
|
-
lowerBound2 && candidate && candidate > lowerBound2) {
|
|
12171
|
-
return [candidate, index - 1];
|
|
12172
|
-
}
|
|
12173
|
-
return [lowerBound2, lowerBoundIndex];
|
|
12174
|
-
};
|
|
12175
|
-
const getUpperBound = (index) => {
|
|
12176
|
-
const upperBound2 = elements[upperBoundIndex] ? elements[upperBoundIndex].index : void 0;
|
|
12177
|
-
if (upperBound2 && index < upperBoundIndex) {
|
|
12178
|
-
return [upperBound2, upperBoundIndex];
|
|
12179
|
-
}
|
|
12180
|
-
let i2 = upperBoundIndex;
|
|
12181
|
-
while (++i2 < elements.length) {
|
|
12182
|
-
const candidate = elements[i2]?.index;
|
|
12183
|
-
if (!upperBound2 && candidate || // first upperBound
|
|
12184
|
-
upperBound2 && candidate && candidate > upperBound2) {
|
|
12185
|
-
return [candidate, i2];
|
|
12186
|
-
}
|
|
12187
|
-
}
|
|
12188
|
-
return [void 0, i2];
|
|
12189
|
-
};
|
|
12190
|
-
let i = 0;
|
|
12191
|
-
while (i < elements.length) {
|
|
12192
|
-
const current = elements[i].index;
|
|
12193
|
-
[lowerBound, lowerBoundIndex] = getLowerBound(i);
|
|
12194
|
-
[upperBound, upperBoundIndex] = getUpperBound(i);
|
|
12195
|
-
if (!isValidFractionalIndex(current, lowerBound, upperBound)) {
|
|
12196
|
-
const indicesGroup = [lowerBoundIndex, i];
|
|
12197
|
-
while (++i < elements.length) {
|
|
12198
|
-
const current2 = elements[i].index;
|
|
12199
|
-
const [nextLowerBound, nextLowerBoundIndex] = getLowerBound(i);
|
|
12200
|
-
const [nextUpperBound, nextUpperBoundIndex] = getUpperBound(i);
|
|
12201
|
-
if (isValidFractionalIndex(current2, nextLowerBound, nextUpperBound)) {
|
|
12202
|
-
break;
|
|
12203
|
-
}
|
|
12204
|
-
[lowerBound, lowerBoundIndex] = [nextLowerBound, nextLowerBoundIndex];
|
|
12205
|
-
[upperBound, upperBoundIndex] = [nextUpperBound, nextUpperBoundIndex];
|
|
12206
|
-
indicesGroup.push(i);
|
|
12034
|
+
for (const element of elements) {
|
|
12035
|
+
let groupIds = element.groupIds;
|
|
12036
|
+
if (appState.editingGroupId) {
|
|
12037
|
+
const indexOfEditingGroup = groupIds.indexOf(appState.editingGroupId);
|
|
12038
|
+
if (indexOfEditingGroup > -1) {
|
|
12039
|
+
groupIds = groupIds.slice(0, indexOfEditingGroup);
|
|
12207
12040
|
}
|
|
12208
|
-
|
|
12209
|
-
|
|
12210
|
-
|
|
12211
|
-
|
|
12041
|
+
}
|
|
12042
|
+
if (groupIds.length > 0) {
|
|
12043
|
+
const groupId = groupIds[groupIds.length - 1];
|
|
12044
|
+
nextAppState = {
|
|
12045
|
+
...nextAppState,
|
|
12046
|
+
...selectGroup(groupId, nextAppState, elements)
|
|
12047
|
+
};
|
|
12212
12048
|
}
|
|
12213
12049
|
}
|
|
12214
|
-
return
|
|
12050
|
+
return nextAppState.selectedGroupIds;
|
|
12215
12051
|
};
|
|
12216
|
-
var
|
|
12217
|
-
|
|
12218
|
-
|
|
12219
|
-
|
|
12220
|
-
|
|
12221
|
-
|
|
12222
|
-
|
|
12223
|
-
|
|
12224
|
-
|
|
12052
|
+
var editGroupForSelectedElement = (appState, element) => {
|
|
12053
|
+
return {
|
|
12054
|
+
...appState,
|
|
12055
|
+
editingGroupId: element.groupIds.length ? element.groupIds[0] : null,
|
|
12056
|
+
selectedGroupIds: {},
|
|
12057
|
+
selectedElementIds: {
|
|
12058
|
+
[element.id]: true
|
|
12059
|
+
}
|
|
12060
|
+
};
|
|
12061
|
+
};
|
|
12062
|
+
var isElementInGroup = (element, groupId) => element.groupIds.includes(groupId);
|
|
12063
|
+
var getElementsInGroup = (elements, groupId) => {
|
|
12064
|
+
const elementsInGroup = [];
|
|
12065
|
+
for (const element of elements.values()) {
|
|
12066
|
+
if (isElementInGroup(element, groupId)) {
|
|
12067
|
+
elementsInGroup.push(element);
|
|
12068
|
+
}
|
|
12225
12069
|
}
|
|
12226
|
-
|
|
12227
|
-
|
|
12070
|
+
return elementsInGroup;
|
|
12071
|
+
};
|
|
12072
|
+
var getSelectedGroupIdForElement = (element, selectedGroupIds) => element.groupIds.find((groupId) => selectedGroupIds[groupId]);
|
|
12073
|
+
var addToGroup = (prevGroupIds, newGroupId, editingGroupId) => {
|
|
12074
|
+
const groupIds = [...prevGroupIds];
|
|
12075
|
+
const positionOfEditingGroupId = editingGroupId ? groupIds.indexOf(editingGroupId) : -1;
|
|
12076
|
+
const positionToInsert = positionOfEditingGroupId > -1 ? positionOfEditingGroupId : groupIds.length;
|
|
12077
|
+
groupIds.splice(positionToInsert, 0, newGroupId);
|
|
12078
|
+
return groupIds;
|
|
12079
|
+
};
|
|
12080
|
+
var removeFromSelectedGroups = (groupIds, selectedGroupIds) => groupIds.filter((groupId) => !selectedGroupIds[groupId]);
|
|
12081
|
+
var getMaximumGroups = (elements, elementsMap) => {
|
|
12082
|
+
const groups = /* @__PURE__ */ new Map();
|
|
12083
|
+
elements.forEach((element) => {
|
|
12084
|
+
const groupId = element.groupIds.length === 0 ? element.id : element.groupIds[element.groupIds.length - 1];
|
|
12085
|
+
const currentGroupMembers = groups.get(groupId) || [];
|
|
12086
|
+
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
12087
|
+
if (boundTextElement) {
|
|
12088
|
+
currentGroupMembers.push(boundTextElement);
|
|
12089
|
+
}
|
|
12090
|
+
groups.set(groupId, [...currentGroupMembers, element]);
|
|
12091
|
+
});
|
|
12092
|
+
return Array.from(groups.values());
|
|
12093
|
+
};
|
|
12094
|
+
var getNonDeletedGroupIds = (elements) => {
|
|
12095
|
+
const nonDeletedGroupIds = /* @__PURE__ */ new Set();
|
|
12096
|
+
for (const [, element] of elements) {
|
|
12097
|
+
if (element.isDeleted) {
|
|
12098
|
+
continue;
|
|
12099
|
+
}
|
|
12100
|
+
for (const groupId of element.groupIds ?? []) {
|
|
12101
|
+
nonDeletedGroupIds.add(groupId);
|
|
12102
|
+
}
|
|
12228
12103
|
}
|
|
12229
|
-
return
|
|
12104
|
+
return nonDeletedGroupIds;
|
|
12230
12105
|
};
|
|
12231
|
-
var
|
|
12232
|
-
const
|
|
12233
|
-
|
|
12234
|
-
|
|
12235
|
-
|
|
12236
|
-
|
|
12237
|
-
|
|
12238
|
-
|
|
12239
|
-
indices.length
|
|
12240
|
-
);
|
|
12241
|
-
for (let i = 0; i < indices.length; i++) {
|
|
12242
|
-
const element = elements[indices[i]];
|
|
12243
|
-
elementsUpdates.set(element, {
|
|
12244
|
-
index: fractionalIndices[i]
|
|
12245
|
-
});
|
|
12106
|
+
var elementsAreInSameGroup = (elements) => {
|
|
12107
|
+
const allGroups = elements.flatMap((element) => element.groupIds);
|
|
12108
|
+
const groupCount = /* @__PURE__ */ new Map();
|
|
12109
|
+
let maxGroup = 0;
|
|
12110
|
+
for (const group of allGroups) {
|
|
12111
|
+
groupCount.set(group, (groupCount.get(group) ?? 0) + 1);
|
|
12112
|
+
if (groupCount.get(group) > maxGroup) {
|
|
12113
|
+
maxGroup = groupCount.get(group);
|
|
12246
12114
|
}
|
|
12247
12115
|
}
|
|
12248
|
-
return
|
|
12116
|
+
return maxGroup === elements.length;
|
|
12249
12117
|
};
|
|
12250
|
-
var
|
|
12251
|
-
|
|
12252
|
-
|
|
12118
|
+
var isInGroup = (element) => {
|
|
12119
|
+
return element.groupIds.length > 0;
|
|
12120
|
+
};
|
|
12121
|
+
var getNewGroupIdsForDuplication = (groupIds, editingGroupId, mapper) => {
|
|
12122
|
+
const copy = [...groupIds];
|
|
12123
|
+
const positionOfEditingGroupId = editingGroupId ? groupIds.indexOf(editingGroupId) : -1;
|
|
12124
|
+
const endIndex = positionOfEditingGroupId > -1 ? positionOfEditingGroupId : groupIds.length;
|
|
12125
|
+
for (let index = 0; index < endIndex; index++) {
|
|
12126
|
+
copy[index] = mapper(copy[index]);
|
|
12253
12127
|
}
|
|
12254
|
-
return
|
|
12128
|
+
return copy;
|
|
12129
|
+
};
|
|
12130
|
+
var getSelectedElementsByGroup = (selectedElements, elementsMap, appState) => {
|
|
12131
|
+
const selectedGroupIds = getSelectedGroupIds(appState);
|
|
12132
|
+
const unboundElements = selectedElements.filter(
|
|
12133
|
+
(element) => !isBoundToContainer(element)
|
|
12134
|
+
);
|
|
12135
|
+
const groups = /* @__PURE__ */ new Map();
|
|
12136
|
+
const elements = /* @__PURE__ */ new Map();
|
|
12137
|
+
const addToElementsMap = (element) => {
|
|
12138
|
+
const currentElementMembers = elements.get(element.id) || [];
|
|
12139
|
+
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
12140
|
+
if (boundTextElement) {
|
|
12141
|
+
currentElementMembers.push(boundTextElement);
|
|
12142
|
+
}
|
|
12143
|
+
elements.set(element.id, [...currentElementMembers, element]);
|
|
12144
|
+
};
|
|
12145
|
+
const addToGroupsMap = (element, groupId) => {
|
|
12146
|
+
const currentGroupMembers = groups.get(groupId) || [];
|
|
12147
|
+
const boundTextElement = getBoundTextElement(element, elementsMap);
|
|
12148
|
+
if (boundTextElement) {
|
|
12149
|
+
currentGroupMembers.push(boundTextElement);
|
|
12150
|
+
}
|
|
12151
|
+
groups.set(groupId, [...currentGroupMembers, element]);
|
|
12152
|
+
};
|
|
12153
|
+
const handleSingleSelectedGroupCase = (element, selectedGroupId) => {
|
|
12154
|
+
const indexOfSelectedGroupId = element.groupIds.indexOf(selectedGroupId, 0);
|
|
12155
|
+
const nestedGroupCount = element.groupIds.slice(
|
|
12156
|
+
0,
|
|
12157
|
+
indexOfSelectedGroupId
|
|
12158
|
+
).length;
|
|
12159
|
+
return nestedGroupCount > 0 ? addToGroupsMap(element, element.groupIds[indexOfSelectedGroupId - 1]) : addToElementsMap(element);
|
|
12160
|
+
};
|
|
12161
|
+
const isAllInSameGroup = selectedElements.every(
|
|
12162
|
+
(element) => isSelectedViaGroup(appState, element)
|
|
12163
|
+
);
|
|
12164
|
+
unboundElements.forEach((element) => {
|
|
12165
|
+
const selectedGroupId = getSelectedGroupIdForElement(
|
|
12166
|
+
element,
|
|
12167
|
+
appState.selectedGroupIds
|
|
12168
|
+
);
|
|
12169
|
+
if (!selectedGroupId) {
|
|
12170
|
+
addToElementsMap(element);
|
|
12171
|
+
} else if (selectedGroupIds.length === 1 && isAllInSameGroup) {
|
|
12172
|
+
handleSingleSelectedGroupCase(element, selectedGroupId);
|
|
12173
|
+
} else {
|
|
12174
|
+
addToGroupsMap(element, selectedGroupId);
|
|
12175
|
+
}
|
|
12176
|
+
});
|
|
12177
|
+
return Array.from(groups.values()).concat(Array.from(elements.values()));
|
|
12255
12178
|
};
|
|
12256
12179
|
|
|
12257
12180
|
// src/zindex.ts
|
|
@@ -12263,7 +12186,7 @@ var getIndicesToMove = (elements, appState, elementsToBeMoved) => {
|
|
|
12263
12186
|
let deletedIndices = [];
|
|
12264
12187
|
let includeDeletedIndex = null;
|
|
12265
12188
|
let index = -1;
|
|
12266
|
-
const selectedElementIds =
|
|
12189
|
+
const selectedElementIds = arrayToMap6(
|
|
12267
12190
|
elementsToBeMoved ? elementsToBeMoved : getSelectedElements(elements, appState, {
|
|
12268
12191
|
includeBoundTextElement: true,
|
|
12269
12192
|
includeElementsInFrames: true
|
|
@@ -12553,7 +12476,7 @@ var shiftElementsToEnd = (elements, appState, direction, containingFrame, elemen
|
|
|
12553
12476
|
return nextElements;
|
|
12554
12477
|
};
|
|
12555
12478
|
function shiftElementsAccountingForFrames(allElements, appState, direction, shiftFunction) {
|
|
12556
|
-
const elementsToMove =
|
|
12479
|
+
const elementsToMove = arrayToMap6(
|
|
12557
12480
|
getSelectedElements(allElements, appState, {
|
|
12558
12481
|
includeBoundTextElement: true,
|
|
12559
12482
|
includeElementsInFrames: true
|
|
@@ -12888,7 +12811,7 @@ var LinearElementEditor = class _LinearElementEditor {
|
|
|
12888
12811
|
console.error(
|
|
12889
12812
|
`There must be a valid lastClickedPoint in order to drag it. selectedPointsIndices(${JSON.stringify(
|
|
12890
12813
|
selectedPointsIndices
|
|
12891
|
-
)}) points(0..${element.points.length - 1}) lastClickedPoint(${lastClickedPoint})`
|
|
12814
|
+
)}) points(0..${element.points.length - 1}) lastClickedPoint(${lastClickedPoint}) isElbowArrow: ${elbowed}`
|
|
12892
12815
|
);
|
|
12893
12816
|
lastClickedPoint = element.points.length - 1;
|
|
12894
12817
|
}
|
|
@@ -13105,7 +13028,8 @@ var LinearElementEditor = class _LinearElementEditor {
|
|
|
13105
13028
|
element.points[index],
|
|
13106
13029
|
element.points[index + 1],
|
|
13107
13030
|
index,
|
|
13108
|
-
appState.zoom
|
|
13031
|
+
appState.zoom,
|
|
13032
|
+
elementsMap
|
|
13109
13033
|
)) {
|
|
13110
13034
|
midpoints.push(null);
|
|
13111
13035
|
index++;
|
|
@@ -13113,7 +13037,8 @@ var LinearElementEditor = class _LinearElementEditor {
|
|
|
13113
13037
|
}
|
|
13114
13038
|
const segmentMidPoint = _LinearElementEditor.getSegmentMidPoint(
|
|
13115
13039
|
element,
|
|
13116
|
-
index + 1
|
|
13040
|
+
index + 1,
|
|
13041
|
+
elementsMap
|
|
13117
13042
|
);
|
|
13118
13043
|
midpoints.push(segmentMidPoint);
|
|
13119
13044
|
index++;
|
|
@@ -13177,7 +13102,7 @@ var LinearElementEditor = class _LinearElementEditor {
|
|
|
13177
13102
|
}
|
|
13178
13103
|
return null;
|
|
13179
13104
|
};
|
|
13180
|
-
static isSegmentTooShort(element, startPoint, endPoint, index, zoom) {
|
|
13105
|
+
static isSegmentTooShort(element, startPoint, endPoint, index, zoom, elementsMap) {
|
|
13181
13106
|
if (isElbowArrow(element)) {
|
|
13182
13107
|
if (index >= 0 && index < element.points.length) {
|
|
13183
13108
|
return pointDistance5(startPoint, endPoint) * zoom.value < _LinearElementEditor.POINT_HANDLE_SIZE / 2;
|
|
@@ -13186,7 +13111,10 @@ var LinearElementEditor = class _LinearElementEditor {
|
|
|
13186
13111
|
}
|
|
13187
13112
|
let distance3 = pointDistance5(startPoint, endPoint);
|
|
13188
13113
|
if (element.points.length > 2 && element.roundness) {
|
|
13189
|
-
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
13114
|
+
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
13115
|
+
element,
|
|
13116
|
+
elementsMap
|
|
13117
|
+
);
|
|
13190
13118
|
invariant8(
|
|
13191
13119
|
lines.length === 0 && curves.length > 0,
|
|
13192
13120
|
"Only linears built out of curves are supported"
|
|
@@ -13199,7 +13127,7 @@ var LinearElementEditor = class _LinearElementEditor {
|
|
|
13199
13127
|
}
|
|
13200
13128
|
return distance3 * zoom.value < _LinearElementEditor.POINT_HANDLE_SIZE * 4;
|
|
13201
13129
|
}
|
|
13202
|
-
static getSegmentMidPoint(element, index) {
|
|
13130
|
+
static getSegmentMidPoint(element, index, elementsMap) {
|
|
13203
13131
|
if (isElbowArrow(element)) {
|
|
13204
13132
|
invariant8(
|
|
13205
13133
|
element.points.length >= index,
|
|
@@ -13208,7 +13136,10 @@ var LinearElementEditor = class _LinearElementEditor {
|
|
|
13208
13136
|
const p = pointCenter2(element.points[index - 1], element.points[index]);
|
|
13209
13137
|
return pointFrom11(element.x + p[0], element.y + p[1]);
|
|
13210
13138
|
}
|
|
13211
|
-
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
13139
|
+
const [lines, curves] = deconstructLinearOrFreeDrawElement(
|
|
13140
|
+
element,
|
|
13141
|
+
elementsMap
|
|
13142
|
+
);
|
|
13212
13143
|
invariant8(
|
|
13213
13144
|
lines.length === 0 && curves.length > 0 || lines.length > 0 && curves.length === 0,
|
|
13214
13145
|
"Only linears built out of either segments or curves are supported"
|
|
@@ -13728,7 +13659,7 @@ var LinearElementEditor = class _LinearElementEditor {
|
|
|
13728
13659
|
pointerDownState: linearElementEditor.initialState,
|
|
13729
13660
|
selectedPointsIndices: linearElementEditor.selectedPointsIndices
|
|
13730
13661
|
};
|
|
13731
|
-
const
|
|
13662
|
+
const midpoint = _LinearElementEditor.createPointAt(
|
|
13732
13663
|
element,
|
|
13733
13664
|
elementsMap,
|
|
13734
13665
|
pointerCoords.x,
|
|
@@ -13737,7 +13668,7 @@ var LinearElementEditor = class _LinearElementEditor {
|
|
|
13737
13668
|
);
|
|
13738
13669
|
const points = [
|
|
13739
13670
|
...element.points.slice(0, segmentMidpoint.index),
|
|
13740
|
-
|
|
13671
|
+
midpoint,
|
|
13741
13672
|
...element.points.slice(segmentMidpoint.index)
|
|
13742
13673
|
];
|
|
13743
13674
|
scene.mutateElement(element, { points });
|
|
@@ -13843,7 +13774,8 @@ var LinearElementEditor = class _LinearElementEditor {
|
|
|
13843
13774
|
const index = element.points.length / 2 - 1;
|
|
13844
13775
|
const midSegmentMidpoint = _LinearElementEditor.getSegmentMidPoint(
|
|
13845
13776
|
element,
|
|
13846
|
-
index + 1
|
|
13777
|
+
index + 1,
|
|
13778
|
+
elementsMap
|
|
13847
13779
|
);
|
|
13848
13780
|
x = midSegmentMidpoint[0] - boundTextElement.width / 2;
|
|
13849
13781
|
y = midSegmentMidpoint[1] - boundTextElement.height / 2;
|
|
@@ -14031,13 +13963,11 @@ var normalizeSelectedPoints = (points) => {
|
|
|
14031
13963
|
var pointDraggingUpdates = (selectedPointsIndices, deltaX, deltaY, scenePointerX, scenePointerY, elementsMap, element, elements, app, angleLocked, altKey, linearElementEditor) => {
|
|
14032
13964
|
const naiveDraggingPoints = new Map(
|
|
14033
13965
|
selectedPointsIndices.map((pointIndex) => {
|
|
13966
|
+
const point = element.points[pointIndex] ?? element.points.at(-1);
|
|
14034
13967
|
return [
|
|
14035
13968
|
pointIndex,
|
|
14036
13969
|
{
|
|
14037
|
-
point: pointFrom11(
|
|
14038
|
-
element.points[pointIndex][0] + deltaX,
|
|
14039
|
-
element.points[pointIndex][1] + deltaY
|
|
14040
|
-
),
|
|
13970
|
+
point: pointFrom11(point[0] + deltaX, point[1] + deltaY),
|
|
14041
13971
|
isDragging: true
|
|
14042
13972
|
}
|
|
14043
13973
|
];
|
|
@@ -14224,7 +14154,7 @@ var pointDraggingUpdates = (selectedPointsIndices, deltaX, deltaY, scenePointerX
|
|
|
14224
14154
|
nextArrow.endBinding.elementId
|
|
14225
14155
|
) : null;
|
|
14226
14156
|
const endLocalPoint = startIsDraggingOverEndElement ? nextArrow.points[nextArrow.points.length - 1] : endIsDraggingOverStartElement && app.state.bindMode !== "inside" && getFeatureFlag2("COMPLEX_BINDINGS") ? nextArrow.points[0] : endBindable ? updateBoundPoint(
|
|
14227
|
-
|
|
14157
|
+
nextArrow,
|
|
14228
14158
|
"endBinding",
|
|
14229
14159
|
nextArrow.endBinding,
|
|
14230
14160
|
endBindable,
|
|
@@ -14236,7 +14166,7 @@ var pointDraggingUpdates = (selectedPointsIndices, deltaX, deltaY, scenePointerX
|
|
|
14236
14166
|
nextArrow.startBinding.elementId
|
|
14237
14167
|
) : null;
|
|
14238
14168
|
const startLocalPoint = endIsDraggingOverStartElement && getFeatureFlag2("COMPLEX_BINDINGS") ? nextArrow.points[0] : startIsDraggingOverEndElement && app.state.bindMode !== "inside" && getFeatureFlag2("COMPLEX_BINDINGS") ? endLocalPoint : startBindable ? updateBoundPoint(
|
|
14239
|
-
|
|
14169
|
+
nextArrow,
|
|
14240
14170
|
"startBinding",
|
|
14241
14171
|
nextArrow.startBinding,
|
|
14242
14172
|
startBindable,
|
|
@@ -14920,7 +14850,7 @@ function getFreedrawOutlineAsSegments(element, points, elementsMap) {
|
|
|
14920
14850
|
return points.slice(2).reduce(
|
|
14921
14851
|
(acc, curr) => {
|
|
14922
14852
|
acc.push(
|
|
14923
|
-
|
|
14853
|
+
lineSegment6(
|
|
14924
14854
|
acc[acc.length - 1][1],
|
|
14925
14855
|
pointRotateRads11(
|
|
14926
14856
|
pointFrom12(curr[0] + element.x, curr[1] + element.y),
|
|
@@ -14932,7 +14862,7 @@ function getFreedrawOutlineAsSegments(element, points, elementsMap) {
|
|
|
14932
14862
|
return acc;
|
|
14933
14863
|
},
|
|
14934
14864
|
[
|
|
14935
|
-
|
|
14865
|
+
lineSegment6(
|
|
14936
14866
|
pointRotateRads11(
|
|
14937
14867
|
pointFrom12(
|
|
14938
14868
|
points[0][0] + element.x,
|
|
@@ -14954,16 +14884,6 @@ function getFreedrawOutlineAsSegments(element, points, elementsMap) {
|
|
|
14954
14884
|
);
|
|
14955
14885
|
}
|
|
14956
14886
|
|
|
14957
|
-
// src/comparisons.ts
|
|
14958
|
-
init_define_import_meta_env();
|
|
14959
|
-
var hasBackground = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "line" || type === "freedraw";
|
|
14960
|
-
var hasStrokeColor = (type) => type === "rectangle" || type === "ellipse" || type === "diamond" || type === "freedraw" || type === "arrow" || type === "line" || type === "text" || type === "embeddable";
|
|
14961
|
-
var hasStrokeWidth = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "freedraw" || type === "arrow" || type === "line";
|
|
14962
|
-
var hasStrokeStyle = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "ellipse" || type === "diamond" || type === "arrow" || type === "line";
|
|
14963
|
-
var canChangeRoundness = (type) => type === "rectangle" || type === "iframe" || type === "embeddable" || type === "line" || type === "diamond" || type === "image";
|
|
14964
|
-
var toolIsArrow = (type) => type === "arrow";
|
|
14965
|
-
var canHaveArrowheads = (type) => type === "arrow";
|
|
14966
|
-
|
|
14967
14887
|
// src/shape.ts
|
|
14968
14888
|
var ShapeCache = class _ShapeCache {
|
|
14969
14889
|
static rg = new RoughGenerator();
|
|
@@ -15315,7 +15235,7 @@ var getArrowheadShapes = (element, shape, position, arrowhead, generator, option
|
|
|
15315
15235
|
}
|
|
15316
15236
|
}
|
|
15317
15237
|
};
|
|
15318
|
-
var generateLinearCollisionShape = (element) => {
|
|
15238
|
+
var generateLinearCollisionShape = (element, elementsMap) => {
|
|
15319
15239
|
const generator = new RoughGenerator();
|
|
15320
15240
|
const options = {
|
|
15321
15241
|
seed: element.seed,
|
|
@@ -15324,20 +15244,7 @@ var generateLinearCollisionShape = (element) => {
|
|
|
15324
15244
|
roughness: 0,
|
|
15325
15245
|
preserveVertices: true
|
|
15326
15246
|
};
|
|
15327
|
-
const center =
|
|
15328
|
-
// Need a non-rotated center point
|
|
15329
|
-
element.points.reduce(
|
|
15330
|
-
(acc, point) => {
|
|
15331
|
-
return [
|
|
15332
|
-
Math.min(element.x + point[0], acc[0]),
|
|
15333
|
-
Math.min(element.y + point[1], acc[1]),
|
|
15334
|
-
Math.max(element.x + point[0], acc[2]),
|
|
15335
|
-
Math.max(element.y + point[1], acc[3])
|
|
15336
|
-
];
|
|
15337
|
-
},
|
|
15338
|
-
[Infinity, Infinity, -Infinity, -Infinity]
|
|
15339
|
-
)
|
|
15340
|
-
);
|
|
15247
|
+
const center = elementCenterPoint(element, elementsMap);
|
|
15341
15248
|
switch (element.type) {
|
|
15342
15249
|
case "line":
|
|
15343
15250
|
case "arrow": {
|
|
@@ -15984,7 +15891,7 @@ var getElementLineSegments = (element, elementsMap) => {
|
|
|
15984
15891
|
let i = 0;
|
|
15985
15892
|
while (i < points.length - 1) {
|
|
15986
15893
|
segments.push(
|
|
15987
|
-
|
|
15894
|
+
lineSegment7(
|
|
15988
15895
|
pointFrom14(points[i][0], points[i][1]),
|
|
15989
15896
|
pointFrom14(points[i + 1][0], points[i + 1][1])
|
|
15990
15897
|
)
|
|
@@ -15997,7 +15904,7 @@ var getElementLineSegments = (element, elementsMap) => {
|
|
|
15997
15904
|
let i = 0;
|
|
15998
15905
|
while (i < points.length - 1) {
|
|
15999
15906
|
segments.push(
|
|
16000
|
-
|
|
15907
|
+
lineSegment7(
|
|
16001
15908
|
pointFrom14(points[i][0], points[i][1]),
|
|
16002
15909
|
pointFrom14(points[i + 1][0], points[i + 1][1])
|
|
16003
15910
|
)
|
|
@@ -16023,10 +15930,10 @@ var getElementLineSegments = (element, elementsMap) => {
|
|
|
16023
15930
|
const container = getContainerElement(element, elementsMap);
|
|
16024
15931
|
if (container && isLinearElement(container)) {
|
|
16025
15932
|
const segments2 = [
|
|
16026
|
-
|
|
16027
|
-
|
|
16028
|
-
|
|
16029
|
-
|
|
15933
|
+
lineSegment7(pointFrom14(x1, y1), pointFrom14(x2, y1)),
|
|
15934
|
+
lineSegment7(pointFrom14(x2, y1), pointFrom14(x2, y2)),
|
|
15935
|
+
lineSegment7(pointFrom14(x2, y2), pointFrom14(x1, y2)),
|
|
15936
|
+
lineSegment7(pointFrom14(x1, y2), pointFrom14(x1, y1))
|
|
16030
15937
|
];
|
|
16031
15938
|
return segments2;
|
|
16032
15939
|
}
|
|
@@ -16034,7 +15941,7 @@ var getElementLineSegments = (element, elementsMap) => {
|
|
|
16034
15941
|
const points = shape.data;
|
|
16035
15942
|
const segments = [];
|
|
16036
15943
|
for (let i = 0; i < points.length - 1; i++) {
|
|
16037
|
-
segments.push(
|
|
15944
|
+
segments.push(lineSegment7(points[i], points[i + 1]));
|
|
16038
15945
|
}
|
|
16039
15946
|
return segments;
|
|
16040
15947
|
} else if (shape.type === "ellipse") {
|
|
@@ -16051,14 +15958,14 @@ var getElementLineSegments = (element, elementsMap) => {
|
|
|
16051
15958
|
[x2, cy]
|
|
16052
15959
|
].map((point) => pointRotateRads13(point, center, element.angle));
|
|
16053
15960
|
return [
|
|
16054
|
-
|
|
16055
|
-
|
|
16056
|
-
|
|
16057
|
-
|
|
16058
|
-
|
|
16059
|
-
|
|
16060
|
-
|
|
16061
|
-
|
|
15961
|
+
lineSegment7(nw, ne),
|
|
15962
|
+
lineSegment7(sw, se2),
|
|
15963
|
+
lineSegment7(nw, sw),
|
|
15964
|
+
lineSegment7(ne, se2),
|
|
15965
|
+
lineSegment7(nw, e),
|
|
15966
|
+
lineSegment7(sw, e),
|
|
15967
|
+
lineSegment7(ne, w),
|
|
15968
|
+
lineSegment7(se2, w)
|
|
16062
15969
|
];
|
|
16063
15970
|
};
|
|
16064
15971
|
var _isRectanguloidElement = (element) => {
|
|
@@ -16066,7 +15973,7 @@ var _isRectanguloidElement = (element) => {
|
|
|
16066
15973
|
};
|
|
16067
15974
|
var getRotatedSides = (sides, center, angle) => {
|
|
16068
15975
|
return sides.map((side) => {
|
|
16069
|
-
return
|
|
15976
|
+
return lineSegment7(
|
|
16070
15977
|
pointRotateRads13(side[0], center, angle),
|
|
16071
15978
|
pointRotateRads13(side[1], center, angle)
|
|
16072
15979
|
);
|
|
@@ -16078,7 +15985,7 @@ var getSegmentsOnCurve = (curve4, center, angle) => {
|
|
|
16078
15985
|
const segments = [];
|
|
16079
15986
|
while (i < points.length - 1) {
|
|
16080
15987
|
segments.push(
|
|
16081
|
-
|
|
15988
|
+
lineSegment7(
|
|
16082
15989
|
pointRotateRads13(
|
|
16083
15990
|
pointFrom14(points[i][0], points[i][1]),
|
|
16084
15991
|
center,
|
|
@@ -16113,9 +16020,9 @@ var getSegmentsOnEllipse = (ellipse4) => {
|
|
|
16113
16020
|
points.push(pointRotateRads13(pointFrom14(x, y), center, ellipse4.angle));
|
|
16114
16021
|
}
|
|
16115
16022
|
for (let i = 0; i < points.length - 1; i++) {
|
|
16116
|
-
segments.push(
|
|
16023
|
+
segments.push(lineSegment7(points[i], points[i + 1]));
|
|
16117
16024
|
}
|
|
16118
|
-
segments.push(
|
|
16025
|
+
segments.push(lineSegment7(points[points.length - 1], points[0]));
|
|
16119
16026
|
return segments;
|
|
16120
16027
|
};
|
|
16121
16028
|
var getRectangleBoxAbsoluteCoords = (boxSceneCoords) => {
|
|
@@ -16228,7 +16135,7 @@ var getMinMaxXYFromCurvePathOps = (ops, transformXY) => {
|
|
|
16228
16135
|
);
|
|
16229
16136
|
return [minX, minY, maxX, maxY];
|
|
16230
16137
|
};
|
|
16231
|
-
var getBoundsFromPoints = (points) => {
|
|
16138
|
+
var getBoundsFromPoints = (points, padding = 0) => {
|
|
16232
16139
|
let minX = Infinity;
|
|
16233
16140
|
let minY = Infinity;
|
|
16234
16141
|
let maxX = -Infinity;
|
|
@@ -16239,7 +16146,7 @@ var getBoundsFromPoints = (points) => {
|
|
|
16239
16146
|
maxX = Math.max(maxX, x);
|
|
16240
16147
|
maxY = Math.max(maxY, y);
|
|
16241
16148
|
}
|
|
16242
|
-
return [minX, minY, maxX, maxY];
|
|
16149
|
+
return [minX - padding, minY - padding, maxX + padding, maxY + padding];
|
|
16243
16150
|
};
|
|
16244
16151
|
var getFreeDrawElementAbsoluteCoords = (element) => {
|
|
16245
16152
|
const [minX, minY, maxX, maxY] = getBoundsFromPoints(element.points);
|
|
@@ -16455,7 +16362,7 @@ var getCommonBounds = (elements, elementsMap) => {
|
|
|
16455
16362
|
let maxX = -Infinity;
|
|
16456
16363
|
let minY = Infinity;
|
|
16457
16364
|
let maxY = -Infinity;
|
|
16458
|
-
const _elementsMap = elementsMap ||
|
|
16365
|
+
const _elementsMap = elementsMap || arrayToMap7(elements);
|
|
16459
16366
|
elements.forEach((element) => {
|
|
16460
16367
|
const [x1, y1, x2, y2] = getElementBounds(element, _elementsMap);
|
|
16461
16368
|
minX = Math.min(minX, x1);
|
|
@@ -16530,7 +16437,7 @@ var getClosestElementBounds = (elements, from) => {
|
|
|
16530
16437
|
}
|
|
16531
16438
|
let minDistance = Infinity;
|
|
16532
16439
|
let closestElement = elements[0];
|
|
16533
|
-
const elementsMap =
|
|
16440
|
+
const elementsMap = arrayToMap7(elements);
|
|
16534
16441
|
elements.forEach((element) => {
|
|
16535
16442
|
const [x1, y1, x2, y2] = getElementBounds(element, elementsMap);
|
|
16536
16443
|
const distance3 = pointDistance7(
|
|
@@ -16623,6 +16530,7 @@ var aabbForElement = (element, elementsMap, offset) => {
|
|
|
16623
16530
|
return bounds;
|
|
16624
16531
|
};
|
|
16625
16532
|
var pointInsideBounds = (p, bounds) => p[0] > bounds[0] && p[0] < bounds[2] && p[1] > bounds[1] && p[1] < bounds[3];
|
|
16533
|
+
var pointInsideBoundsInclusive = (p, bounds) => p[0] >= bounds[0] && p[0] <= bounds[2] && p[1] >= bounds[1] && p[1] <= bounds[3];
|
|
16626
16534
|
var doBoundsIntersect = (bounds1, bounds2) => {
|
|
16627
16535
|
if (bounds1 == null || bounds2 == null) {
|
|
16628
16536
|
return false;
|
|
@@ -16631,8 +16539,14 @@ var doBoundsIntersect = (bounds1, bounds2) => {
|
|
|
16631
16539
|
const [minX2, minY2, maxX2, maxY2] = bounds2;
|
|
16632
16540
|
return minX1 < maxX2 && maxX1 > minX2 && minY1 < maxY2 && maxY1 > minY2;
|
|
16633
16541
|
};
|
|
16542
|
+
var boundsContainBounds = (outerBounds, innerBounds) => [
|
|
16543
|
+
pointFrom14(innerBounds[0], innerBounds[1]),
|
|
16544
|
+
pointFrom14(innerBounds[0], innerBounds[3]),
|
|
16545
|
+
pointFrom14(innerBounds[2], innerBounds[1]),
|
|
16546
|
+
pointFrom14(innerBounds[2], innerBounds[3])
|
|
16547
|
+
].every((point) => pointInsideBoundsInclusive(point, outerBounds));
|
|
16634
16548
|
var elementCenterPoint = (element, elementsMap, xOffset = 0, yOffset = 0) => {
|
|
16635
|
-
if (isLinearElement(element)) {
|
|
16549
|
+
if (isLinearElement(element) || isFreeDrawElement(element)) {
|
|
16636
16550
|
const [x1, y1, x2, y2] = getElementAbsoluteCoords2(element, elementsMap);
|
|
16637
16551
|
const [x3, y3] = pointFrom14((x1 + x2) / 2, (y1 + y2) / 2);
|
|
16638
16552
|
return pointFrom14(x3 + xOffset, y3 + yOffset);
|
|
@@ -17398,79 +17312,61 @@ import {
|
|
|
17398
17312
|
|
|
17399
17313
|
// src/sortElements.ts
|
|
17400
17314
|
init_define_import_meta_env();
|
|
17401
|
-
import {
|
|
17402
|
-
var
|
|
17403
|
-
const
|
|
17404
|
-
|
|
17405
|
-
const orderInnerGroups = (elements2) => {
|
|
17406
|
-
const firstGroupSig = elements2[0]?.groupIds?.join("");
|
|
17407
|
-
const aGroup = [elements2[0]];
|
|
17408
|
-
const bGroup = [];
|
|
17409
|
-
for (const element of elements2.slice(1)) {
|
|
17410
|
-
if (element.groupIds?.join("") === firstGroupSig) {
|
|
17411
|
-
aGroup.push(element);
|
|
17412
|
-
} else {
|
|
17413
|
-
bGroup.push(element);
|
|
17414
|
-
}
|
|
17415
|
-
}
|
|
17416
|
-
return bGroup.length ? [...aGroup, ...orderInnerGroups(bGroup)] : aGroup;
|
|
17315
|
+
import { arrayToMap as arrayToMap8 } from "@excalidraw/common";
|
|
17316
|
+
var defragmentGroups = (elements) => {
|
|
17317
|
+
const groupIdAtLevel = (element, level) => {
|
|
17318
|
+
return element.groupIds[element.groupIds.length - level - 1];
|
|
17417
17319
|
};
|
|
17418
|
-
const
|
|
17419
|
-
|
|
17420
|
-
|
|
17421
|
-
|
|
17422
|
-
|
|
17423
|
-
|
|
17424
|
-
|
|
17425
|
-
|
|
17426
|
-
const ret = element2?.groupIds?.some((id) => id === topGroup);
|
|
17427
|
-
if (ret) {
|
|
17428
|
-
groupHandledElements.set(element2.id, true);
|
|
17429
|
-
}
|
|
17430
|
-
return ret;
|
|
17431
|
-
});
|
|
17432
|
-
for (const elem of orderInnerGroups(groupElements)) {
|
|
17433
|
-
sortedElements.add(elem);
|
|
17320
|
+
const orderLevel = (levelElements, level) => {
|
|
17321
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
17322
|
+
const slots = [];
|
|
17323
|
+
for (const element of levelElements) {
|
|
17324
|
+
const groupId = groupIdAtLevel(element, level);
|
|
17325
|
+
if (groupId === void 0) {
|
|
17326
|
+
slots.push(element);
|
|
17327
|
+
continue;
|
|
17434
17328
|
}
|
|
17435
|
-
|
|
17436
|
-
|
|
17329
|
+
let bucket = buckets.get(groupId);
|
|
17330
|
+
if (!bucket) {
|
|
17331
|
+
bucket = [];
|
|
17332
|
+
buckets.set(groupId, bucket);
|
|
17333
|
+
slots.push(groupId);
|
|
17334
|
+
}
|
|
17335
|
+
bucket.push(element);
|
|
17437
17336
|
}
|
|
17438
|
-
|
|
17439
|
-
|
|
17440
|
-
|
|
17337
|
+
return slots.flatMap(
|
|
17338
|
+
(slot) => typeof slot === "string" ? orderLevel(buckets.get(slot), level + 1) : [slot]
|
|
17339
|
+
);
|
|
17340
|
+
};
|
|
17341
|
+
const sortedElements = orderLevel(elements, 0);
|
|
17342
|
+
if (sortedElements.length !== elements.length) {
|
|
17343
|
+
console.error("defragmentGroups: lost some elements... bailing!");
|
|
17441
17344
|
return elements;
|
|
17442
17345
|
}
|
|
17443
|
-
return
|
|
17346
|
+
return sortedElements;
|
|
17444
17347
|
};
|
|
17445
17348
|
var normalizeBoundElementsOrder = (elements) => {
|
|
17446
|
-
const elementsMap =
|
|
17447
|
-
const origElements = elements.slice();
|
|
17349
|
+
const elementsMap = arrayToMap8(elements);
|
|
17448
17350
|
const sortedElements = /* @__PURE__ */ new Set();
|
|
17449
|
-
|
|
17450
|
-
if (
|
|
17451
|
-
|
|
17351
|
+
for (const element of elements) {
|
|
17352
|
+
if (sortedElements.has(element)) {
|
|
17353
|
+
continue;
|
|
17452
17354
|
}
|
|
17453
17355
|
if (element.boundElements?.length) {
|
|
17454
17356
|
sortedElements.add(element);
|
|
17455
|
-
|
|
17456
|
-
element.boundElements.forEach((boundElement) => {
|
|
17357
|
+
for (const boundElement of element.boundElements) {
|
|
17457
17358
|
const child = elementsMap.get(boundElement.id);
|
|
17458
17359
|
if (child && boundElement.type === "text") {
|
|
17459
|
-
sortedElements.add(child
|
|
17460
|
-
origElements[child[1]] = null;
|
|
17360
|
+
sortedElements.add(child);
|
|
17461
17361
|
}
|
|
17462
|
-
});
|
|
17463
|
-
} else if (element.type === "text" && element.containerId) {
|
|
17464
|
-
const parent = elementsMap.get(element.containerId);
|
|
17465
|
-
if (!parent?.[0].boundElements?.find((x) => x.id === element.id)) {
|
|
17466
|
-
sortedElements.add(element);
|
|
17467
|
-
origElements[idx] = null;
|
|
17468
17362
|
}
|
|
17469
|
-
|
|
17470
|
-
sortedElements.add(element);
|
|
17471
|
-
origElements[idx] = null;
|
|
17363
|
+
continue;
|
|
17472
17364
|
}
|
|
17473
|
-
|
|
17365
|
+
if (element.type === "text" && element.containerId && elementsMap.get(element.containerId)?.boundElements?.some((el) => el.id === element.id)) {
|
|
17366
|
+
continue;
|
|
17367
|
+
}
|
|
17368
|
+
sortedElements.add(element);
|
|
17369
|
+
}
|
|
17474
17370
|
if (sortedElements.size !== elements.length) {
|
|
17475
17371
|
console.error(
|
|
17476
17372
|
"normalizeBoundElementsOrder: lost some elements... bailing!"
|
|
@@ -17480,7 +17376,7 @@ var normalizeBoundElementsOrder = (elements) => {
|
|
|
17480
17376
|
return [...sortedElements];
|
|
17481
17377
|
};
|
|
17482
17378
|
var normalizeElementOrder = (elements) => {
|
|
17483
|
-
return normalizeBoundElementsOrder(
|
|
17379
|
+
return normalizeBoundElementsOrder(defragmentGroups(elements));
|
|
17484
17380
|
};
|
|
17485
17381
|
|
|
17486
17382
|
// src/duplicate.ts
|
|
@@ -17522,6 +17418,7 @@ var duplicateElements = (opts) => {
|
|
|
17522
17418
|
const duplicateElementsMap = /* @__PURE__ */ new Map();
|
|
17523
17419
|
const elementsMap = arrayToMap9(elements);
|
|
17524
17420
|
const _idsOfElementsToDuplicate = opts.type === "in-place" ? opts.idsOfElementsToDuplicate : new Map(elements.map((el) => [el.id, el]));
|
|
17421
|
+
const preserveFrameChildrenOrder = opts.type === "everything" && opts.preserveFrameChildrenOrder;
|
|
17525
17422
|
if (opts.type === "in-place") {
|
|
17526
17423
|
for (const groupId of Object.keys(opts.appState.selectedGroupIds)) {
|
|
17527
17424
|
elements.filter((el) => el.groupIds?.includes(groupId)).forEach((el) => _idsOfElementsToDuplicate.set(el.id, el));
|
|
@@ -17581,7 +17478,7 @@ var duplicateElements = (opts) => {
|
|
|
17581
17478
|
const groupId = getSelectedGroupForElement(appState, element);
|
|
17582
17479
|
if (groupId) {
|
|
17583
17480
|
const groupElements = getElementsInGroup(elements, groupId).flatMap(
|
|
17584
|
-
(element2) => isFrameLikeElement(element2) ? [...getFrameChildren(elements, element2.id), element2] : [element2]
|
|
17481
|
+
(element2) => isFrameLikeElement(element2) && !preserveFrameChildrenOrder ? [...getFrameChildren(elements, element2.id), element2] : [element2]
|
|
17585
17482
|
);
|
|
17586
17483
|
const targetIndex = findLastIndex2(elementsWithDuplicates, (el) => {
|
|
17587
17484
|
return el.groupIds?.includes(groupId);
|
|
@@ -17589,11 +17486,18 @@ var duplicateElements = (opts) => {
|
|
|
17589
17486
|
insertBeforeOrAfterIndex(targetIndex, copyElements(groupElements));
|
|
17590
17487
|
continue;
|
|
17591
17488
|
}
|
|
17592
|
-
if (element.frameId && frameIdsToDuplicate.has(element.frameId)) {
|
|
17489
|
+
if (!preserveFrameChildrenOrder && element.frameId && frameIdsToDuplicate.has(element.frameId)) {
|
|
17593
17490
|
continue;
|
|
17594
17491
|
}
|
|
17595
17492
|
if (isFrameLikeElement(element)) {
|
|
17596
17493
|
const frameId = element.id;
|
|
17494
|
+
if (preserveFrameChildrenOrder) {
|
|
17495
|
+
insertBeforeOrAfterIndex(
|
|
17496
|
+
findLastIndex2(elementsWithDuplicates, (el) => el.id === frameId),
|
|
17497
|
+
copyElements(element)
|
|
17498
|
+
);
|
|
17499
|
+
continue;
|
|
17500
|
+
}
|
|
17597
17501
|
const frameChildren = getFrameChildren(elements, frameId);
|
|
17598
17502
|
const targetIndex = findLastIndex2(elementsWithDuplicates, (el) => {
|
|
17599
17503
|
return el.frameId === frameId || el.id === frameId;
|
|
@@ -18591,24 +18495,14 @@ var Scene = class {
|
|
|
18591
18495
|
this.selectedElementsCache.cache.clear();
|
|
18592
18496
|
this.callbacks.clear();
|
|
18593
18497
|
}
|
|
18594
|
-
|
|
18595
|
-
if (!Number.isFinite(index) || index < 0) {
|
|
18596
|
-
throw new Error(
|
|
18597
|
-
"insertElementAtIndex can only be called with index >= 0"
|
|
18598
|
-
);
|
|
18599
|
-
}
|
|
18600
|
-
const nextElements = [
|
|
18601
|
-
...this.elements.slice(0, index),
|
|
18602
|
-
element,
|
|
18603
|
-
...this.elements.slice(index)
|
|
18604
|
-
];
|
|
18605
|
-
syncMovedIndices2(nextElements, arrayToMap10([element]));
|
|
18606
|
-
this.replaceAllElements(nextElements);
|
|
18607
|
-
}
|
|
18498
|
+
/** low-level - generally use app.insertNewElements() */
|
|
18608
18499
|
insertElementsAtIndex(elements, index) {
|
|
18609
18500
|
if (!elements.length) {
|
|
18610
18501
|
return;
|
|
18611
18502
|
}
|
|
18503
|
+
if (index === null) {
|
|
18504
|
+
index = this.elements.length;
|
|
18505
|
+
}
|
|
18612
18506
|
if (!Number.isFinite(index) || index < 0) {
|
|
18613
18507
|
throw new Error(
|
|
18614
18508
|
"insertElementAtIndex can only be called with index >= 0"
|
|
@@ -18622,16 +18516,9 @@ var Scene = class {
|
|
|
18622
18516
|
syncMovedIndices2(nextElements, arrayToMap10(elements));
|
|
18623
18517
|
this.replaceAllElements(nextElements);
|
|
18624
18518
|
}
|
|
18519
|
+
/** low-level - generally use app.insertNewElement() */
|
|
18625
18520
|
insertElement = (element) => {
|
|
18626
|
-
|
|
18627
|
-
this.insertElementAtIndex(element, index);
|
|
18628
|
-
};
|
|
18629
|
-
insertElements = (elements) => {
|
|
18630
|
-
if (!elements.length) {
|
|
18631
|
-
return;
|
|
18632
|
-
}
|
|
18633
|
-
const index = elements[0]?.frameId ? this.getElementIndex(elements[0].frameId) : this.elements.length;
|
|
18634
|
-
this.insertElementsAtIndex(elements, index);
|
|
18521
|
+
this.insertElementsAtIndex([element], null);
|
|
18635
18522
|
};
|
|
18636
18523
|
getElementIndex(elementId) {
|
|
18637
18524
|
return this.elements.findIndex((element) => element.id === elementId);
|
|
@@ -26758,6 +26645,7 @@ export {
|
|
|
26758
26645
|
bindOrUnbindBindingElements,
|
|
26759
26646
|
bindPointToSnapToElementOutline,
|
|
26760
26647
|
bindingProperties,
|
|
26648
|
+
boundsContainBounds,
|
|
26761
26649
|
bumpVersion,
|
|
26762
26650
|
calculateFixedPointForElbowArrowBinding,
|
|
26763
26651
|
calculateFixedPointForNonElbowArrowBinding,
|
|
@@ -26828,6 +26716,7 @@ export {
|
|
|
26828
26716
|
getClosestElementBounds,
|
|
26829
26717
|
getCommonBoundingBox,
|
|
26830
26718
|
getCommonBounds,
|
|
26719
|
+
getCommonFrameId,
|
|
26831
26720
|
getContainerCenter,
|
|
26832
26721
|
getContainerCoords,
|
|
26833
26722
|
getContainerElement,
|
|
@@ -26857,6 +26746,7 @@ export {
|
|
|
26857
26746
|
getEmbedLink,
|
|
26858
26747
|
getFlipAdjustedCropPosition,
|
|
26859
26748
|
getFrameChildren,
|
|
26749
|
+
getFrameChildrenInsertionIndex,
|
|
26860
26750
|
getFrameLikeElements,
|
|
26861
26751
|
getFrameLikeTitle,
|
|
26862
26752
|
getFreedrawOutlineAsSegments,
|
|
@@ -26961,6 +26851,7 @@ export {
|
|
|
26961
26851
|
isElementInViewport,
|
|
26962
26852
|
isElementIntersectingFrame,
|
|
26963
26853
|
isElementLink,
|
|
26854
|
+
isEligibleFrameChildType,
|
|
26964
26855
|
isEmbeddableElement,
|
|
26965
26856
|
isExcalidrawElement,
|
|
26966
26857
|
isFixedPoint,
|
|
@@ -27035,6 +26926,7 @@ export {
|
|
|
27035
26926
|
parseElementLinkFromURL,
|
|
27036
26927
|
parseTokens,
|
|
27037
26928
|
pointInsideBounds,
|
|
26929
|
+
pointInsideBoundsInclusive,
|
|
27038
26930
|
positionElementsOnGrid,
|
|
27039
26931
|
projectFixedPointOntoDiagonal,
|
|
27040
26932
|
redrawTextBoundingBox,
|