@plait/core 0.52.0 → 0.54.0
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/constants/cursor.d.ts +1 -0
- package/constants/selection.d.ts +1 -0
- package/esm2022/board/board.component.mjs +8 -6
- package/esm2022/constants/cursor.mjs +2 -1
- package/esm2022/constants/selection.mjs +2 -1
- package/esm2022/interfaces/board.mjs +5 -1
- package/esm2022/interfaces/path.mjs +2 -2
- package/esm2022/interfaces/rectangle-client.mjs +4 -1
- package/esm2022/interfaces/selection.mjs +2 -2
- package/esm2022/plugins/create-board.mjs +9 -6
- package/esm2022/plugins/with-hotkey.mjs +3 -3
- package/esm2022/plugins/with-moving.mjs +41 -21
- package/esm2022/plugins/with-related-fragment.mjs +20 -0
- package/esm2022/plugins/with-selection.mjs +37 -101
- package/esm2022/public-api.mjs +2 -1
- package/esm2022/transforms/element.mjs +2 -2
- package/esm2022/transforms/group.mjs +47 -0
- package/esm2022/transforms/index.mjs +2 -1
- package/esm2022/utils/angle.mjs +114 -0
- package/esm2022/utils/common.mjs +3 -2
- package/esm2022/utils/debug.mjs +91 -0
- package/esm2022/utils/element.mjs +17 -5
- package/esm2022/utils/fragment.mjs +5 -0
- package/esm2022/utils/group.mjs +88 -87
- package/esm2022/utils/helper.mjs +10 -1
- package/esm2022/utils/index.mjs +3 -1
- package/esm2022/utils/math.mjs +11 -1
- package/esm2022/utils/moving-snap.mjs +372 -0
- package/esm2022/utils/selection.mjs +90 -5
- package/esm2022/utils/touch.mjs +15 -4
- package/esm2022/utils/weak-maps.mjs +2 -1
- package/fesm2022/plait-core.mjs +587 -251
- package/fesm2022/plait-core.mjs.map +1 -1
- package/interfaces/board.d.ts +5 -2
- package/interfaces/rectangle-client.d.ts +1 -0
- package/interfaces/selection.d.ts +1 -1
- package/package.json +1 -1
- package/plugins/with-moving.d.ts +1 -1
- package/plugins/with-related-fragment.d.ts +2 -0
- package/public-api.d.ts +1 -0
- package/transforms/group.d.ts +7 -0
- package/transforms/index.d.ts +1 -0
- package/utils/angle.d.ts +18 -0
- package/utils/debug.d.ts +14 -0
- package/utils/fragment.d.ts +2 -0
- package/utils/group.d.ts +16 -16
- package/utils/helper.d.ts +2 -0
- package/utils/index.d.ts +2 -0
- package/utils/math.d.ts +8 -0
- package/utils/{reaction-manager.d.ts → moving-snap.d.ts} +3 -3
- package/utils/selection.d.ts +7 -4
- package/utils/touch.d.ts +1 -1
- package/utils/weak-maps.d.ts +1 -0
- package/esm2022/plugins/with-group.mjs +0 -27
- package/esm2022/utils/reaction-manager.mjs +0 -371
- package/plugins/with-group.d.ts +0 -2
package/fesm2022/plait-core.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import rough from 'roughjs/bin/rough';
|
|
|
4
4
|
import { timer, Subject, fromEvent } from 'rxjs';
|
|
5
5
|
import { takeUntil, filter, tap } from 'rxjs/operators';
|
|
6
6
|
import { isKeyHotkey, isHotkey } from 'is-hotkey';
|
|
7
|
-
import produce,
|
|
7
|
+
import { produce, createDraft, finishDraft, isDraft } from 'immer';
|
|
8
8
|
import { NgFor } from '@angular/common';
|
|
9
9
|
|
|
10
10
|
// record richtext type status
|
|
@@ -18,6 +18,7 @@ const BOARD_TO_AFTER_CHANGE = new WeakMap();
|
|
|
18
18
|
const BOARD_TO_COMPONENT = new WeakMap();
|
|
19
19
|
const BOARD_TO_ROUGH_SVG = new WeakMap();
|
|
20
20
|
const BOARD_TO_HOST = new WeakMap();
|
|
21
|
+
const IS_BOARD_ALIVE = new WeakMap();
|
|
21
22
|
const BOARD_TO_ELEMENT_HOST = new WeakMap();
|
|
22
23
|
const BOARD_TO_SELECTED_ELEMENT = new WeakMap();
|
|
23
24
|
const BOARD_TO_MOVING_POINT_IN_BOARD = new WeakMap();
|
|
@@ -64,7 +65,7 @@ const getIsRecursionFunc = (board) => {
|
|
|
64
65
|
};
|
|
65
66
|
|
|
66
67
|
const SELECTION_BORDER_COLOR = '#6698FF';
|
|
67
|
-
const SELECTION_FILL_COLOR = '#
|
|
68
|
+
const SELECTION_FILL_COLOR = '#6698FF25'; // opacity 0.25
|
|
68
69
|
const Selection = {
|
|
69
70
|
isCollapsed(selection) {
|
|
70
71
|
if (selection.anchor[0] == selection.focus[0] && selection.anchor[1] === selection.focus[1]) {
|
|
@@ -185,6 +186,9 @@ const RectangleClient = {
|
|
|
185
186
|
getCenterPoint: (rectangle) => {
|
|
186
187
|
return [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height / 2];
|
|
187
188
|
},
|
|
189
|
+
getCenterPointByPoints: (points) => {
|
|
190
|
+
return RectangleClient.getCenterPoint(RectangleClient.getRectangleByPoints(points));
|
|
191
|
+
},
|
|
188
192
|
getEdgeCenterPoints: (rectangle) => {
|
|
189
193
|
return [
|
|
190
194
|
[rectangle.x + rectangle.width / 2, rectangle.y],
|
|
@@ -493,9 +497,11 @@ var CursorClass;
|
|
|
493
497
|
(function (CursorClass) {
|
|
494
498
|
CursorClass["crosshair"] = "crosshair";
|
|
495
499
|
})(CursorClass || (CursorClass = {}));
|
|
500
|
+
const RESIZE_CURSORS = [ResizeCursorClass.ns, ResizeCursorClass.nesw, ResizeCursorClass.ew, ResizeCursorClass.nwse];
|
|
496
501
|
|
|
497
502
|
const ATTACHED_ELEMENT_CLASS_NAME = 'plait-board-attached';
|
|
498
503
|
const ACTIVE_STROKE_WIDTH = 1;
|
|
504
|
+
const SNAPPING_STROKE_WIDTH = 2;
|
|
499
505
|
const SELECTION_RECTANGLE_CLASS_NAME = 'selection-rectangle';
|
|
500
506
|
|
|
501
507
|
const HOST_CLASS_NAME = 'plait-board-container';
|
|
@@ -952,6 +958,16 @@ function toDomPrecision(v) {
|
|
|
952
958
|
function toFixed(v) {
|
|
953
959
|
return +v.toFixed(2);
|
|
954
960
|
}
|
|
961
|
+
/**
|
|
962
|
+
* Whether two numbers numbers a and b are approximately equal.
|
|
963
|
+
*
|
|
964
|
+
* @param a - The first point.
|
|
965
|
+
* @param b - The second point.
|
|
966
|
+
* @public
|
|
967
|
+
*/
|
|
968
|
+
function approximately(a, b, precision = 0.000001) {
|
|
969
|
+
return Math.abs(a - b) <= precision;
|
|
970
|
+
}
|
|
955
971
|
|
|
956
972
|
function isInPlaitBoard(board, x, y) {
|
|
957
973
|
const plaitBoardElement = PlaitBoard.getBoardContainer(board);
|
|
@@ -1030,6 +1046,15 @@ const RgbaToHEX = (Rgb, opacity) => {
|
|
|
1030
1046
|
function isContextmenu(event) {
|
|
1031
1047
|
return event.button === 2;
|
|
1032
1048
|
}
|
|
1049
|
+
function uniqueById(elements) {
|
|
1050
|
+
const uniqueMap = new Map();
|
|
1051
|
+
elements.forEach(item => {
|
|
1052
|
+
if (!uniqueMap.has(item.id)) {
|
|
1053
|
+
uniqueMap.set(item.id, item);
|
|
1054
|
+
}
|
|
1055
|
+
});
|
|
1056
|
+
return Array.from(uniqueMap.values());
|
|
1057
|
+
}
|
|
1033
1058
|
|
|
1034
1059
|
/**
|
|
1035
1060
|
* Check whether to merge an operation into the previous operation.
|
|
@@ -1683,7 +1708,7 @@ const throttleRAF = (board, key, fn) => {
|
|
|
1683
1708
|
const value = BOARD_TO_RAF.get(board) || {};
|
|
1684
1709
|
value[key] = null;
|
|
1685
1710
|
BOARD_TO_RAF.set(board, value);
|
|
1686
|
-
fn();
|
|
1711
|
+
PlaitBoard.isAlive(board) && fn();
|
|
1687
1712
|
});
|
|
1688
1713
|
const state = getRAFState(board);
|
|
1689
1714
|
state[key] = timerId;
|
|
@@ -2151,8 +2176,16 @@ const isPreventTouchMove = (board) => {
|
|
|
2151
2176
|
return !!BOARD_TO_TOUCH_REF.get(board);
|
|
2152
2177
|
};
|
|
2153
2178
|
const preventTouchMove = (board, event, state) => {
|
|
2154
|
-
|
|
2155
|
-
|
|
2179
|
+
const hostElement = PlaitBoard.getElementHost(board);
|
|
2180
|
+
const activeHostElement = PlaitBoard.getElementActiveHost(board);
|
|
2181
|
+
if (state) {
|
|
2182
|
+
if ((event.target instanceof HTMLElement || event.target instanceof SVGElement) &&
|
|
2183
|
+
(hostElement.contains(event.target) || activeHostElement.contains(event.target))) {
|
|
2184
|
+
BOARD_TO_TOUCH_REF.set(board, { state, target: event.target instanceof SVGElement ? event.target : undefined });
|
|
2185
|
+
}
|
|
2186
|
+
else {
|
|
2187
|
+
BOARD_TO_TOUCH_REF.set(board, { state, target: undefined });
|
|
2188
|
+
}
|
|
2156
2189
|
}
|
|
2157
2190
|
else {
|
|
2158
2191
|
const ref = BOARD_TO_TOUCH_REF.get(board);
|
|
@@ -2170,7 +2203,10 @@ const preventTouchMove = (board, event, state) => {
|
|
|
2170
2203
|
*/
|
|
2171
2204
|
const handleTouchTarget = (board) => {
|
|
2172
2205
|
const touchRef = BOARD_TO_TOUCH_REF.get(board);
|
|
2173
|
-
if (touchRef &&
|
|
2206
|
+
if (touchRef &&
|
|
2207
|
+
touchRef.target &&
|
|
2208
|
+
!PlaitBoard.getElementHost(board).contains(touchRef.target) &&
|
|
2209
|
+
!PlaitBoard.getElementActiveHost(board).contains(touchRef.target)) {
|
|
2174
2210
|
touchRef.target.style.opacity = '0';
|
|
2175
2211
|
const host = createG();
|
|
2176
2212
|
host.appendChild(touchRef.target);
|
|
@@ -2180,12 +2216,6 @@ const handleTouchTarget = (board) => {
|
|
|
2180
2216
|
}
|
|
2181
2217
|
};
|
|
2182
2218
|
|
|
2183
|
-
const PlaitGroupElement = {
|
|
2184
|
-
isGroup: (value) => {
|
|
2185
|
-
return value.type === 'group';
|
|
2186
|
-
}
|
|
2187
|
-
};
|
|
2188
|
-
|
|
2189
2219
|
const Viewport = {
|
|
2190
2220
|
isViewport: (value) => {
|
|
2191
2221
|
return !isNullOrUndefined(value.zoom) && !isNullOrUndefined(value.viewBackgroundColor);
|
|
@@ -2622,7 +2652,7 @@ const removeElements = (board, elements) => {
|
|
|
2622
2652
|
const path = PlaitBoard.findPath(board, element);
|
|
2623
2653
|
const ref = board.pathRef(path);
|
|
2624
2654
|
return () => {
|
|
2625
|
-
removeNode(board, ref.current);
|
|
2655
|
+
ref.current && removeNode(board, ref.current);
|
|
2626
2656
|
ref.unref();
|
|
2627
2657
|
removeSelectedElement(board, element, true);
|
|
2628
2658
|
};
|
|
@@ -2635,6 +2665,50 @@ const CoreTransforms = {
|
|
|
2635
2665
|
removeElements
|
|
2636
2666
|
};
|
|
2637
2667
|
|
|
2668
|
+
const addGroup = (board, elements) => {
|
|
2669
|
+
const selectedGroups = getHighestSelectedGroups(board, elements);
|
|
2670
|
+
const selectedIsolatedElements = getSelectedIsolatedElementsCanAddToGroup(board);
|
|
2671
|
+
const highestSelectedElements = [...selectedGroups, ...selectedIsolatedElements];
|
|
2672
|
+
const group = createGroup();
|
|
2673
|
+
if (canAddGroup(board)) {
|
|
2674
|
+
highestSelectedElements.forEach(item => {
|
|
2675
|
+
const path = PlaitBoard.findPath(board, item);
|
|
2676
|
+
NodeTransforms.setNode(board, { groupId: group.id }, path);
|
|
2677
|
+
});
|
|
2678
|
+
if (hasSelectedElementsInSameGroup(highestSelectedElements)) {
|
|
2679
|
+
const newGroupId = selectedIsolatedElements[0].groupId;
|
|
2680
|
+
NodeTransforms.insertNode(board, {
|
|
2681
|
+
...group,
|
|
2682
|
+
groupId: newGroupId
|
|
2683
|
+
}, [board.children.length]);
|
|
2684
|
+
}
|
|
2685
|
+
else {
|
|
2686
|
+
NodeTransforms.insertNode(board, group, [board.children.length]);
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
};
|
|
2690
|
+
const removeGroup = (board, elements) => {
|
|
2691
|
+
const selectedGroups = getHighestSelectedGroups(board, elements);
|
|
2692
|
+
if (canRemoveGroup(board)) {
|
|
2693
|
+
selectedGroups.map(group => {
|
|
2694
|
+
const elementsInGroup = findElements(board, {
|
|
2695
|
+
match: item => item.groupId === group.id,
|
|
2696
|
+
recursion: () => false
|
|
2697
|
+
});
|
|
2698
|
+
elementsInGroup.forEach(item => {
|
|
2699
|
+
const path = PlaitBoard.findPath(board, item);
|
|
2700
|
+
NodeTransforms.setNode(board, { groupId: group.groupId || undefined }, path);
|
|
2701
|
+
});
|
|
2702
|
+
const groupPath = PlaitBoard.findPath(board, group);
|
|
2703
|
+
NodeTransforms.removeNode(board, groupPath);
|
|
2704
|
+
});
|
|
2705
|
+
}
|
|
2706
|
+
};
|
|
2707
|
+
const GroupTransforms = {
|
|
2708
|
+
addGroup,
|
|
2709
|
+
removeGroup
|
|
2710
|
+
};
|
|
2711
|
+
|
|
2638
2712
|
const Transforms = {
|
|
2639
2713
|
...GeneralTransforms,
|
|
2640
2714
|
...ViewportTransforms$1,
|
|
@@ -2642,6 +2716,116 @@ const Transforms = {
|
|
|
2642
2716
|
...NodeTransforms
|
|
2643
2717
|
};
|
|
2644
2718
|
|
|
2719
|
+
const rotatePoints = (points, centerPoint, angle) => {
|
|
2720
|
+
if (!angle) {
|
|
2721
|
+
angle = 0;
|
|
2722
|
+
}
|
|
2723
|
+
if (Array.isArray(points) && typeof points[0] === 'number') {
|
|
2724
|
+
return rotate(points[0], points[1], centerPoint[0], centerPoint[1], angle);
|
|
2725
|
+
}
|
|
2726
|
+
else {
|
|
2727
|
+
return points.map(point => {
|
|
2728
|
+
return rotate(point[0], point[1], centerPoint[0], centerPoint[1], angle);
|
|
2729
|
+
});
|
|
2730
|
+
}
|
|
2731
|
+
};
|
|
2732
|
+
const getSelectionAngle = (elements) => {
|
|
2733
|
+
let angle = elements[0]?.angle || 0;
|
|
2734
|
+
elements.forEach(item => {
|
|
2735
|
+
if (item.angle !== angle && !approximately((item.angle % (Math.PI / 2)) - (angle % (Math.PI / 2)), 0)) {
|
|
2736
|
+
angle = 0;
|
|
2737
|
+
}
|
|
2738
|
+
});
|
|
2739
|
+
return angle;
|
|
2740
|
+
};
|
|
2741
|
+
const hasSameAngle = (elements) => {
|
|
2742
|
+
if (!elements.length) {
|
|
2743
|
+
return false;
|
|
2744
|
+
}
|
|
2745
|
+
const angle = elements[0].angle;
|
|
2746
|
+
if (angle === undefined) {
|
|
2747
|
+
return false;
|
|
2748
|
+
}
|
|
2749
|
+
return !elements.some(item => item.angle !== angle);
|
|
2750
|
+
};
|
|
2751
|
+
const getRotatedBoundingRectangle = (rectanglesCornerPoints, angle) => {
|
|
2752
|
+
let rectanglesFromOrigin = [];
|
|
2753
|
+
for (let i = 0; i < rectanglesCornerPoints.length; i++) {
|
|
2754
|
+
const cornerPoints = rectanglesCornerPoints[i];
|
|
2755
|
+
const invertCornerPointsFromOrigin = rotatePoints(cornerPoints, [0, 0], -angle);
|
|
2756
|
+
rectanglesFromOrigin.push(RectangleClient.getRectangleByPoints(invertCornerPointsFromOrigin));
|
|
2757
|
+
}
|
|
2758
|
+
const selectionRectangleFromOrigin = RectangleClient.getBoundingRectangle(rectanglesFromOrigin);
|
|
2759
|
+
const selectionCornerPoints = RectangleClient.getCornerPoints(selectionRectangleFromOrigin);
|
|
2760
|
+
const cornerPointsFromOrigin = rotatePoints(selectionCornerPoints, [0, 0], angle);
|
|
2761
|
+
const centerPoint = RectangleClient.getCenterPoint(RectangleClient.getRectangleByPoints(cornerPointsFromOrigin));
|
|
2762
|
+
return RectangleClient.getRectangleByPoints(rotatePoints(cornerPointsFromOrigin, centerPoint, -angle));
|
|
2763
|
+
};
|
|
2764
|
+
const getOffsetAfterRotate = (rectangle, rotateCenterPoint, angle) => {
|
|
2765
|
+
const targetCenterPoint = RectangleClient.getCenterPoint(rectangle);
|
|
2766
|
+
const [rotatedCenterPoint] = rotatePoints([targetCenterPoint], rotateCenterPoint, angle);
|
|
2767
|
+
const offsetX = rotatedCenterPoint[0] - targetCenterPoint[0];
|
|
2768
|
+
const offsetY = rotatedCenterPoint[1] - targetCenterPoint[1];
|
|
2769
|
+
return { offsetX, offsetY };
|
|
2770
|
+
};
|
|
2771
|
+
const rotatedDataPoints = (points, rotateCenterPoint, angle) => {
|
|
2772
|
+
const { offsetX, offsetY } = getOffsetAfterRotate(RectangleClient.getRectangleByPoints(points), rotateCenterPoint, angle);
|
|
2773
|
+
return points.map(p => [p[0] + offsetX, p[1] + offsetY]);
|
|
2774
|
+
};
|
|
2775
|
+
const hasValidAngle = (node) => {
|
|
2776
|
+
return node.angle && node.angle !== 0;
|
|
2777
|
+
};
|
|
2778
|
+
const rotatePointsByElement = (points, element) => {
|
|
2779
|
+
if (hasValidAngle(element)) {
|
|
2780
|
+
let rectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
2781
|
+
const centerPoint = RectangleClient.getCenterPoint(rectangle);
|
|
2782
|
+
return rotatePoints(points, centerPoint, element.angle);
|
|
2783
|
+
}
|
|
2784
|
+
else {
|
|
2785
|
+
return null;
|
|
2786
|
+
}
|
|
2787
|
+
};
|
|
2788
|
+
const rotateAntiPointsByElement = (points, element) => {
|
|
2789
|
+
if (hasValidAngle(element)) {
|
|
2790
|
+
let rectangle = RectangleClient.getRectangleByPoints(element.points);
|
|
2791
|
+
const centerPoint = RectangleClient.getCenterPoint(rectangle);
|
|
2792
|
+
return rotatePoints(points, centerPoint, -element.angle);
|
|
2793
|
+
}
|
|
2794
|
+
else {
|
|
2795
|
+
return null;
|
|
2796
|
+
}
|
|
2797
|
+
};
|
|
2798
|
+
const getRectangleByAngle = (rectangle, angle) => {
|
|
2799
|
+
if (angle) {
|
|
2800
|
+
const cornerPoints = RectangleClient.getCornerPoints(rectangle);
|
|
2801
|
+
const centerPoint = RectangleClient.getCenterPoint(rectangle);
|
|
2802
|
+
return RectangleClient.getRectangleByPoints(rotatePoints(cornerPoints, centerPoint, angle));
|
|
2803
|
+
}
|
|
2804
|
+
else {
|
|
2805
|
+
return null;
|
|
2806
|
+
}
|
|
2807
|
+
};
|
|
2808
|
+
const isAxisChangedByAngle = (angle) => {
|
|
2809
|
+
const unitAngle = Math.abs(angle) % Math.PI;
|
|
2810
|
+
return unitAngle >= (1 / 4) * Math.PI && unitAngle <= (3 / 4) * Math.PI;
|
|
2811
|
+
};
|
|
2812
|
+
function degreesToRadians(d) {
|
|
2813
|
+
return (d / 180) * Math.PI;
|
|
2814
|
+
}
|
|
2815
|
+
function radiansToDegrees(r) {
|
|
2816
|
+
return (r / Math.PI) * 180;
|
|
2817
|
+
}
|
|
2818
|
+
function rotateElements(board, elements, angle) {
|
|
2819
|
+
const selectionRectangle = getRectangleByElements(board, elements, false);
|
|
2820
|
+
const selectionCenterPoint = RectangleClient.getCenterPoint(selectionRectangle);
|
|
2821
|
+
elements.forEach(item => {
|
|
2822
|
+
const originAngle = item.angle;
|
|
2823
|
+
const points = rotatedDataPoints(item.points, selectionCenterPoint, angle);
|
|
2824
|
+
const path = PlaitBoard.findPath(board, item);
|
|
2825
|
+
Transforms.setNode(board, { points, angle: originAngle + angle }, path);
|
|
2826
|
+
});
|
|
2827
|
+
}
|
|
2828
|
+
|
|
2645
2829
|
function isSelectionMoving(board) {
|
|
2646
2830
|
return !!BOARD_TO_IS_SELECTION_MOVING.get(board);
|
|
2647
2831
|
}
|
|
@@ -2677,7 +2861,7 @@ function getTemporaryRef(board) {
|
|
|
2677
2861
|
function deleteTemporaryElements(board) {
|
|
2678
2862
|
BOARD_TO_TEMPORARY_ELEMENTS.delete(board);
|
|
2679
2863
|
}
|
|
2680
|
-
function
|
|
2864
|
+
function drawEntireActiveRectangleG(board) {
|
|
2681
2865
|
const elements = getSelectedElements(board);
|
|
2682
2866
|
const rectangle = getRectangleByElements(board, elements, false);
|
|
2683
2867
|
if (rectangle.width > 0 && rectangle.height > 0 && elements.length > 1) {
|
|
@@ -2687,11 +2871,91 @@ function createSelectionRectangleG(board) {
|
|
|
2687
2871
|
fillStyle: 'solid'
|
|
2688
2872
|
});
|
|
2689
2873
|
selectionRectangleG.classList.add(SELECTION_RECTANGLE_CLASS_NAME);
|
|
2690
|
-
|
|
2874
|
+
const angle = getSelectionAngle(elements);
|
|
2875
|
+
if (angle) {
|
|
2876
|
+
setAngleForG(selectionRectangleG, RectangleClient.getCenterPoint(rectangle), angle);
|
|
2877
|
+
}
|
|
2691
2878
|
return selectionRectangleG;
|
|
2692
2879
|
}
|
|
2693
2880
|
return null;
|
|
2694
2881
|
}
|
|
2882
|
+
function setSelectedElementsWithGroup(board, elements, isShift) {
|
|
2883
|
+
if (!board.selection) {
|
|
2884
|
+
return;
|
|
2885
|
+
}
|
|
2886
|
+
const selectedElements = getSelectedElements(board);
|
|
2887
|
+
if (!Selection.isCollapsed(board.selection)) {
|
|
2888
|
+
let newElements = [...selectedElements];
|
|
2889
|
+
elements.forEach(item => {
|
|
2890
|
+
if (!item.groupId) {
|
|
2891
|
+
newElements.push(item);
|
|
2892
|
+
}
|
|
2893
|
+
else {
|
|
2894
|
+
newElements.push(...getElementsInGroupByElement(board, item));
|
|
2895
|
+
}
|
|
2896
|
+
});
|
|
2897
|
+
cacheSelectedElements(board, uniqueById(newElements));
|
|
2898
|
+
return;
|
|
2899
|
+
}
|
|
2900
|
+
if (Selection.isCollapsed(board.selection)) {
|
|
2901
|
+
const hitElement = elements[0];
|
|
2902
|
+
const hitElementGroups = getGroupByElement(board, hitElement, true);
|
|
2903
|
+
if (hitElementGroups.length) {
|
|
2904
|
+
const elementsInHighestGroup = getElementsInGroup(board, hitElementGroups[hitElementGroups.length - 1], true) || [];
|
|
2905
|
+
const isSelectGroupElement = selectedElements.some(element => elementsInHighestGroup.map(item => item.id).includes(element.id));
|
|
2906
|
+
if (isShift) {
|
|
2907
|
+
cacheSelectedElementsWithGroupOnShift(board, elements, isSelectGroupElement, elementsInHighestGroup);
|
|
2908
|
+
}
|
|
2909
|
+
else {
|
|
2910
|
+
cacheSelectedElementsWithGroup(board, elements, isSelectGroupElement, hitElementGroups);
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
}
|
|
2915
|
+
function cacheSelectedElementsWithGroupOnShift(board, elements, isSelectGroupElement, elementsInHighestGroup) {
|
|
2916
|
+
const selectedElements = getSelectedElements(board);
|
|
2917
|
+
let newElements = [...selectedElements];
|
|
2918
|
+
const hitElement = elements[0];
|
|
2919
|
+
let pendingElements = [];
|
|
2920
|
+
if (!isSelectGroupElement) {
|
|
2921
|
+
pendingElements = elementsInHighestGroup;
|
|
2922
|
+
}
|
|
2923
|
+
else {
|
|
2924
|
+
const isHitSelectedElement = selectedElements.some(item => item.id === hitElement.id);
|
|
2925
|
+
const selectedElementsInGroup = elementsInHighestGroup.filter(item => selectedElements.includes(item));
|
|
2926
|
+
if (isHitSelectedElement) {
|
|
2927
|
+
pendingElements = selectedElementsInGroup.filter(item => item.id !== hitElement.id);
|
|
2928
|
+
}
|
|
2929
|
+
else {
|
|
2930
|
+
pendingElements.push(...selectedElementsInGroup, ...elements);
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
elementsInHighestGroup.forEach(element => {
|
|
2934
|
+
if (newElements.includes(element)) {
|
|
2935
|
+
newElements.splice(newElements.indexOf(element), 1);
|
|
2936
|
+
}
|
|
2937
|
+
});
|
|
2938
|
+
if (pendingElements.length) {
|
|
2939
|
+
newElements.push(...pendingElements);
|
|
2940
|
+
}
|
|
2941
|
+
cacheSelectedElements(board, uniqueById(newElements));
|
|
2942
|
+
}
|
|
2943
|
+
function cacheSelectedElementsWithGroup(board, elements, isSelectGroupElement, hitElementGroups) {
|
|
2944
|
+
let newElements = [...elements];
|
|
2945
|
+
const selectedGroups = filterSelectedGroups(board, hitElementGroups);
|
|
2946
|
+
if (selectedGroups.length > 0) {
|
|
2947
|
+
if (selectedGroups.length > 1) {
|
|
2948
|
+
newElements = getAllElementsInGroup(board, selectedGroups[selectedGroups.length - 2], true);
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
else {
|
|
2952
|
+
const elementsInGroup = getAllElementsInGroup(board, hitElementGroups[hitElementGroups.length - 1], true);
|
|
2953
|
+
if (!isSelectGroupElement) {
|
|
2954
|
+
newElements = elementsInGroup;
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2957
|
+
cacheSelectedElements(board, uniqueById(newElements));
|
|
2958
|
+
}
|
|
2695
2959
|
|
|
2696
2960
|
const getElementsInGroup = (board, group, recursion, includeGroup) => {
|
|
2697
2961
|
let result = [];
|
|
@@ -2702,7 +2966,7 @@ const getElementsInGroup = (board, group, recursion, includeGroup) => {
|
|
|
2702
2966
|
if (includeGroup) {
|
|
2703
2967
|
result.push(item);
|
|
2704
2968
|
}
|
|
2705
|
-
result.push(...getElementsInGroup(board, item, recursion));
|
|
2969
|
+
result.push(...getElementsInGroup(board, item, recursion, includeGroup));
|
|
2706
2970
|
}
|
|
2707
2971
|
else {
|
|
2708
2972
|
result.push(item);
|
|
@@ -2714,18 +2978,28 @@ const getElementsInGroup = (board, group, recursion, includeGroup) => {
|
|
|
2714
2978
|
}
|
|
2715
2979
|
return result;
|
|
2716
2980
|
};
|
|
2981
|
+
const getAllElementsInGroup = (board, group, recursion, includeGroup) => {
|
|
2982
|
+
const elementsInGroup = getElementsInGroup(board, group, recursion, includeGroup);
|
|
2983
|
+
const result = [];
|
|
2984
|
+
elementsInGroup.forEach(element => {
|
|
2985
|
+
depthFirstRecursion(element, node => {
|
|
2986
|
+
result.push(node);
|
|
2987
|
+
}, () => true);
|
|
2988
|
+
});
|
|
2989
|
+
return result;
|
|
2990
|
+
};
|
|
2717
2991
|
const getRectangleByGroup = (board, group, recursion) => {
|
|
2718
|
-
const elementsInGroup =
|
|
2992
|
+
const elementsInGroup = getAllElementsInGroup(board, group, recursion);
|
|
2719
2993
|
return getRectangleByElements(board, elementsInGroup, false);
|
|
2720
2994
|
};
|
|
2721
|
-
const getGroupByElement = (board, element, recursion) => {
|
|
2722
|
-
const group = board.children.find(item => item.id === element?.groupId);
|
|
2995
|
+
const getGroupByElement = (board, element, recursion, source) => {
|
|
2996
|
+
const group = (source || board.children).find(item => item.id === element?.groupId);
|
|
2723
2997
|
if (!group) {
|
|
2724
2998
|
return recursion ? [] : null;
|
|
2725
2999
|
}
|
|
2726
3000
|
if (recursion) {
|
|
2727
3001
|
const groups = [group];
|
|
2728
|
-
const grandGroups = getGroupByElement(board, group, recursion);
|
|
3002
|
+
const grandGroups = getGroupByElement(board, group, recursion, source);
|
|
2729
3003
|
if (grandGroups.length) {
|
|
2730
3004
|
groups.push(...grandGroups);
|
|
2731
3005
|
}
|
|
@@ -2736,56 +3010,66 @@ const getGroupByElement = (board, element, recursion) => {
|
|
|
2736
3010
|
}
|
|
2737
3011
|
};
|
|
2738
3012
|
const getHighestGroup = (board, element) => {
|
|
2739
|
-
const
|
|
2740
|
-
if (
|
|
2741
|
-
return
|
|
3013
|
+
const hitElementGroups = getGroupByElement(board, element, true);
|
|
3014
|
+
if (hitElementGroups.length) {
|
|
3015
|
+
return hitElementGroups[hitElementGroups.length - 1];
|
|
2742
3016
|
}
|
|
2743
3017
|
return null;
|
|
2744
3018
|
};
|
|
2745
3019
|
const getElementsInGroupByElement = (board, element) => {
|
|
2746
3020
|
const highestGroup = getHighestGroup(board, element);
|
|
2747
3021
|
if (highestGroup) {
|
|
2748
|
-
return
|
|
3022
|
+
return getAllElementsInGroup(board, highestGroup, true);
|
|
2749
3023
|
}
|
|
2750
3024
|
else {
|
|
2751
3025
|
return [element];
|
|
2752
3026
|
}
|
|
2753
3027
|
};
|
|
2754
|
-
const isSelectedElementOrGroup = (board, element) => {
|
|
2755
|
-
const selectedElements = getSelectedElements(board);
|
|
3028
|
+
const isSelectedElementOrGroup = (board, element, elements) => {
|
|
3029
|
+
const selectedElements = elements || getSelectedElements(board);
|
|
2756
3030
|
if (PlaitGroupElement.isGroup(element)) {
|
|
2757
|
-
return isSelectedAllElementsInGroup(board, element);
|
|
3031
|
+
return isSelectedAllElementsInGroup(board, element, elements);
|
|
2758
3032
|
}
|
|
2759
|
-
return selectedElements.includes(element);
|
|
3033
|
+
return selectedElements.map(item => item.id).includes(element.id);
|
|
2760
3034
|
};
|
|
2761
|
-
const isSelectedAllElementsInGroup = (board, group) => {
|
|
2762
|
-
const selectedElements = getSelectedElements(board);
|
|
3035
|
+
const isSelectedAllElementsInGroup = (board, group, elements) => {
|
|
3036
|
+
const selectedElements = elements || getSelectedElements(board);
|
|
2763
3037
|
const elementsInGroup = getElementsInGroup(board, group, true);
|
|
2764
|
-
return elementsInGroup.every(item => selectedElements.includes(item));
|
|
3038
|
+
return elementsInGroup.every(item => selectedElements.map(element => element.id).includes(item.id));
|
|
2765
3039
|
};
|
|
2766
|
-
const
|
|
3040
|
+
const filterSelectedGroups = (board, groups, elements) => {
|
|
2767
3041
|
const selectedGroups = [];
|
|
2768
3042
|
groups.forEach(item => {
|
|
2769
|
-
if (isSelectedElementOrGroup(board, item)) {
|
|
3043
|
+
if (isSelectedElementOrGroup(board, item, elements)) {
|
|
2770
3044
|
selectedGroups.push(item);
|
|
2771
3045
|
}
|
|
2772
3046
|
});
|
|
2773
3047
|
return selectedGroups;
|
|
2774
3048
|
};
|
|
2775
|
-
const
|
|
2776
|
-
const
|
|
2777
|
-
const
|
|
3049
|
+
const getSelectedGroups = (board, elements) => {
|
|
3050
|
+
const highestSelectedGroups = getHighestSelectedGroups(board, elements);
|
|
3051
|
+
const groups = [];
|
|
3052
|
+
highestSelectedGroups.forEach(item => {
|
|
3053
|
+
groups.push(item);
|
|
3054
|
+
const elementsInGroup = getElementsInGroup(board, item, true, true);
|
|
3055
|
+
groups.push(...elementsInGroup.filter(item => PlaitGroupElement.isGroup(item)));
|
|
3056
|
+
});
|
|
3057
|
+
return groups;
|
|
3058
|
+
};
|
|
3059
|
+
const getHighestSelectedGroup = (board, element, elements) => {
|
|
3060
|
+
const hitElementGroups = getGroupByElement(board, element, true, elements);
|
|
3061
|
+
const selectedGroups = filterSelectedGroups(board, hitElementGroups, elements);
|
|
2778
3062
|
if (selectedGroups.length) {
|
|
2779
3063
|
return selectedGroups[selectedGroups.length - 1];
|
|
2780
3064
|
}
|
|
2781
3065
|
return null;
|
|
2782
3066
|
};
|
|
2783
|
-
const getHighestSelectedGroups = (board) => {
|
|
3067
|
+
const getHighestSelectedGroups = (board, elements) => {
|
|
2784
3068
|
let result = [];
|
|
2785
|
-
const selectedElements = getSelectedElements(board);
|
|
3069
|
+
const selectedElements = elements || getSelectedElements(board);
|
|
2786
3070
|
selectedElements.forEach(item => {
|
|
2787
3071
|
if (item.groupId) {
|
|
2788
|
-
const group = getHighestSelectedGroup(board, item);
|
|
3072
|
+
const group = getHighestSelectedGroup(board, item, elements);
|
|
2789
3073
|
if (group && !result.includes(group)) {
|
|
2790
3074
|
result.push(group);
|
|
2791
3075
|
}
|
|
@@ -2793,15 +3077,17 @@ const getHighestSelectedGroups = (board) => {
|
|
|
2793
3077
|
});
|
|
2794
3078
|
return result;
|
|
2795
3079
|
};
|
|
2796
|
-
const getSelectedIsolatedElements = (board) => {
|
|
3080
|
+
const getSelectedIsolatedElements = (board, elements) => {
|
|
2797
3081
|
let result = [];
|
|
2798
|
-
const selectedElements = getSelectedElements(board);
|
|
2799
|
-
selectedElements
|
|
3082
|
+
const selectedElements = elements || getSelectedElements(board);
|
|
3083
|
+
selectedElements
|
|
3084
|
+
.filter(item => !PlaitGroupElement.isGroup(item))
|
|
3085
|
+
.forEach(item => {
|
|
2800
3086
|
if (!item.groupId) {
|
|
2801
3087
|
result.push(item);
|
|
2802
3088
|
}
|
|
2803
3089
|
else {
|
|
2804
|
-
const group = getHighestSelectedGroup(board, item);
|
|
3090
|
+
const group = getHighestSelectedGroup(board, item, elements);
|
|
2805
3091
|
if (!group) {
|
|
2806
3092
|
result.push(item);
|
|
2807
3093
|
}
|
|
@@ -2809,8 +3095,12 @@ const getSelectedIsolatedElements = (board) => {
|
|
|
2809
3095
|
});
|
|
2810
3096
|
return result;
|
|
2811
3097
|
};
|
|
2812
|
-
const
|
|
2813
|
-
|
|
3098
|
+
const getSelectedIsolatedElementsCanAddToGroup = (board, elements) => {
|
|
3099
|
+
const selectedIsolatedElements = getSelectedIsolatedElements(board, elements);
|
|
3100
|
+
return selectedIsolatedElements.filter(item => board.canAddToGroup(item));
|
|
3101
|
+
};
|
|
3102
|
+
const getHighestSelectedElements = (board, elements) => {
|
|
3103
|
+
return [...getHighestSelectedGroups(board, elements), ...getSelectedIsolatedElements(board, elements)];
|
|
2814
3104
|
};
|
|
2815
3105
|
const createGroupRectangleG = (board, elements) => {
|
|
2816
3106
|
const selectedElements = getSelectedElements(board);
|
|
@@ -2821,20 +3111,31 @@ const createGroupRectangleG = (board, elements) => {
|
|
|
2821
3111
|
if (item.groupId && isRender) {
|
|
2822
3112
|
const elements = getElementsInGroupByElement(board, item);
|
|
2823
3113
|
const rectangle = getRectangleByElements(board, elements, false);
|
|
2824
|
-
|
|
3114
|
+
const rectangleG = drawRectangle(board, rectangle, {
|
|
2825
3115
|
stroke: SELECTION_BORDER_COLOR,
|
|
2826
3116
|
strokeWidth: ACTIVE_STROKE_WIDTH,
|
|
2827
3117
|
strokeLineDash: [5]
|
|
2828
|
-
})
|
|
3118
|
+
});
|
|
3119
|
+
const angle = getSelectionAngle(elements);
|
|
3120
|
+
if (angle) {
|
|
3121
|
+
setAngleForG(rectangleG, RectangleClient.getCenterPoint(rectangle), angle);
|
|
3122
|
+
}
|
|
3123
|
+
groupRectangleG.append(rectangleG);
|
|
2829
3124
|
}
|
|
2830
3125
|
});
|
|
2831
3126
|
return groupRectangleG;
|
|
2832
3127
|
};
|
|
2833
|
-
const createGroup = () => {
|
|
2834
|
-
return
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
3128
|
+
const createGroup = (groupId) => {
|
|
3129
|
+
return groupId
|
|
3130
|
+
? {
|
|
3131
|
+
id: idCreator(),
|
|
3132
|
+
type: 'group',
|
|
3133
|
+
groupId
|
|
3134
|
+
}
|
|
3135
|
+
: {
|
|
3136
|
+
id: idCreator(),
|
|
3137
|
+
type: 'group'
|
|
3138
|
+
};
|
|
2838
3139
|
};
|
|
2839
3140
|
const nonGroupInHighestSelectedElements = (elements) => {
|
|
2840
3141
|
return elements.every(item => !item.groupId);
|
|
@@ -2842,54 +3143,23 @@ const nonGroupInHighestSelectedElements = (elements) => {
|
|
|
2842
3143
|
const hasSelectedElementsInSameGroup = (elements) => {
|
|
2843
3144
|
return elements.every(item => item.groupId && item.groupId === elements[0].groupId);
|
|
2844
3145
|
};
|
|
2845
|
-
const canAddGroup = (
|
|
2846
|
-
|
|
2847
|
-
|
|
3146
|
+
const canAddGroup = (board, elements) => {
|
|
3147
|
+
const highestSelectedElements = getHighestSelectedElements(board, elements);
|
|
3148
|
+
const rootElements = highestSelectedElements.filter(item => board.canAddToGroup(item));
|
|
3149
|
+
if (rootElements.length > 1) {
|
|
3150
|
+
return nonGroupInHighestSelectedElements(rootElements) || hasSelectedElementsInSameGroup(rootElements);
|
|
2848
3151
|
}
|
|
2849
3152
|
return false;
|
|
2850
3153
|
};
|
|
2851
|
-
const
|
|
2852
|
-
const selectedGroups = getHighestSelectedGroups(board);
|
|
2853
|
-
const
|
|
2854
|
-
const highestSelectedElements = [...selectedGroups, ...selectedIsolatedElements];
|
|
2855
|
-
const group = createGroup();
|
|
2856
|
-
if (canAddGroup(highestSelectedElements)) {
|
|
2857
|
-
highestSelectedElements.forEach(item => {
|
|
2858
|
-
const path = PlaitBoard.findPath(board, item);
|
|
2859
|
-
Transforms.setNode(board, { groupId: group.id }, path);
|
|
2860
|
-
});
|
|
2861
|
-
if (hasSelectedElementsInSameGroup(highestSelectedElements)) {
|
|
2862
|
-
const newGroupId = selectedIsolatedElements[0].groupId;
|
|
2863
|
-
Transforms.insertNode(board, {
|
|
2864
|
-
...group,
|
|
2865
|
-
groupId: newGroupId
|
|
2866
|
-
}, [board.children.length]);
|
|
2867
|
-
}
|
|
2868
|
-
else {
|
|
2869
|
-
Transforms.insertNode(board, group, [board.children.length]);
|
|
2870
|
-
}
|
|
2871
|
-
}
|
|
2872
|
-
};
|
|
2873
|
-
const canRemoveGroup = (board, selectedGroups) => {
|
|
2874
|
-
const selectedElements = getSelectedElements(board);
|
|
3154
|
+
const canRemoveGroup = (board, elements) => {
|
|
3155
|
+
const selectedGroups = getHighestSelectedGroups(board, elements);
|
|
3156
|
+
const selectedElements = elements || getSelectedElements(board);
|
|
2875
3157
|
return selectedElements.length > 0 && selectedGroups.length > 0;
|
|
2876
3158
|
};
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
const elementsInGroup = findElements(board, {
|
|
2882
|
-
match: item => item.groupId === group.id,
|
|
2883
|
-
recursion: () => false
|
|
2884
|
-
});
|
|
2885
|
-
elementsInGroup.forEach(item => {
|
|
2886
|
-
const path = PlaitBoard.findPath(board, item);
|
|
2887
|
-
Transforms.setNode(board, { groupId: group.groupId || undefined }, path);
|
|
2888
|
-
});
|
|
2889
|
-
const groupPath = PlaitBoard.findPath(board, group);
|
|
2890
|
-
Transforms.removeNode(board, groupPath);
|
|
2891
|
-
});
|
|
2892
|
-
}
|
|
3159
|
+
|
|
3160
|
+
const deleteFragment = (board) => {
|
|
3161
|
+
const elements = board.getDeletedFragment([]);
|
|
3162
|
+
board.deleteFragment(elements);
|
|
2893
3163
|
};
|
|
2894
3164
|
|
|
2895
3165
|
const PlaitElement = {
|
|
@@ -3080,12 +3350,20 @@ var Direction;
|
|
|
3080
3350
|
Direction["bottom"] = "bottom";
|
|
3081
3351
|
})(Direction || (Direction = {}));
|
|
3082
3352
|
|
|
3353
|
+
const PlaitGroupElement = {
|
|
3354
|
+
isGroup: (value) => {
|
|
3355
|
+
return value.type === 'group';
|
|
3356
|
+
}
|
|
3357
|
+
};
|
|
3358
|
+
|
|
3083
3359
|
function getRectangleByElements(board, elements, recursion) {
|
|
3084
|
-
const
|
|
3360
|
+
const rectanglesCornerPoints = [];
|
|
3085
3361
|
const callback = (node) => {
|
|
3086
3362
|
const nodeRectangle = board.getRectangle(node);
|
|
3087
3363
|
if (nodeRectangle) {
|
|
3088
|
-
|
|
3364
|
+
const cornerPoints = RectangleClient.getCornerPoints(nodeRectangle);
|
|
3365
|
+
const rotatedCornerPoints = rotatePointsByElement(cornerPoints, node) || cornerPoints;
|
|
3366
|
+
rectanglesCornerPoints.push(rotatedCornerPoints);
|
|
3089
3367
|
}
|
|
3090
3368
|
else {
|
|
3091
3369
|
console.error(`can not get rectangle of element:`, node);
|
|
@@ -3099,8 +3377,17 @@ function getRectangleByElements(board, elements, recursion) {
|
|
|
3099
3377
|
callback(element);
|
|
3100
3378
|
}
|
|
3101
3379
|
});
|
|
3102
|
-
if (
|
|
3103
|
-
|
|
3380
|
+
if (rectanglesCornerPoints.length > 0) {
|
|
3381
|
+
if (hasSameAngle(elements)) {
|
|
3382
|
+
const angle = getSelectionAngle(elements);
|
|
3383
|
+
return getRotatedBoundingRectangle(rectanglesCornerPoints, angle);
|
|
3384
|
+
}
|
|
3385
|
+
else {
|
|
3386
|
+
const flatCornerPoints = rectanglesCornerPoints.reduce((acc, val) => {
|
|
3387
|
+
return acc.concat(val);
|
|
3388
|
+
}, []);
|
|
3389
|
+
return RectangleClient.getRectangleByPoints(flatCornerPoints);
|
|
3390
|
+
}
|
|
3104
3391
|
}
|
|
3105
3392
|
else {
|
|
3106
3393
|
return {
|
|
@@ -3149,6 +3436,10 @@ const PlaitBoard = {
|
|
|
3149
3436
|
IS_BOARD_CACHE.set(value, isBoard);
|
|
3150
3437
|
return isBoard;
|
|
3151
3438
|
},
|
|
3439
|
+
isAlive(board) {
|
|
3440
|
+
const isAlive = IS_BOARD_CACHE.get(board);
|
|
3441
|
+
return !!isAlive;
|
|
3442
|
+
},
|
|
3152
3443
|
findPath(board, node) {
|
|
3153
3444
|
const path = [];
|
|
3154
3445
|
let child = node;
|
|
@@ -3311,6 +3602,9 @@ function createBoard(children, options) {
|
|
|
3311
3602
|
},
|
|
3312
3603
|
onChange: () => { },
|
|
3313
3604
|
afterChange: () => { },
|
|
3605
|
+
drawActiveRectangle: () => {
|
|
3606
|
+
return drawEntireActiveRectangleG(board);
|
|
3607
|
+
},
|
|
3314
3608
|
mousedown: (event) => { },
|
|
3315
3609
|
mousemove: (event) => { },
|
|
3316
3610
|
mouseleave: (event) => { },
|
|
@@ -3325,12 +3619,11 @@ function createBoard(children, options) {
|
|
|
3325
3619
|
setClipboardData(data, clipboardContext);
|
|
3326
3620
|
},
|
|
3327
3621
|
insertFragment: (data) => { },
|
|
3328
|
-
deleteFragment: (
|
|
3329
|
-
const elements = board.getDeletedFragment([]);
|
|
3622
|
+
deleteFragment: (elements) => {
|
|
3330
3623
|
CoreTransforms.removeElements(board, elements);
|
|
3331
3624
|
},
|
|
3332
3625
|
getDeletedFragment: (data) => data,
|
|
3333
|
-
getRelatedFragment: (data) => data,
|
|
3626
|
+
getRelatedFragment: (data, originData) => data,
|
|
3334
3627
|
drawElement: (context) => [],
|
|
3335
3628
|
redrawElement: (context, previousContext) => { },
|
|
3336
3629
|
destroyElement: (context) => { },
|
|
@@ -3351,7 +3644,8 @@ function createBoard(children, options) {
|
|
|
3351
3644
|
pointerLeave: pointer => { },
|
|
3352
3645
|
globalPointerMove: pointer => { },
|
|
3353
3646
|
globalPointerUp: pointer => { },
|
|
3354
|
-
isImageBindingAllowed: (element) => false
|
|
3647
|
+
isImageBindingAllowed: (element) => false,
|
|
3648
|
+
canAddToGroup: (element) => true
|
|
3355
3649
|
};
|
|
3356
3650
|
return board;
|
|
3357
3651
|
}
|
|
@@ -3514,7 +3808,7 @@ function withHandPointer(board) {
|
|
|
3514
3808
|
}
|
|
3515
3809
|
|
|
3516
3810
|
function withSelection(board) {
|
|
3517
|
-
const { pointerDown, pointerUp, pointerMove, globalPointerUp, onChange, afterChange } = board;
|
|
3811
|
+
const { pointerDown, pointerUp, pointerMove, globalPointerUp, onChange, afterChange, drawActiveRectangle } = board;
|
|
3518
3812
|
let start = null;
|
|
3519
3813
|
let end = null;
|
|
3520
3814
|
let selectionMovingG;
|
|
@@ -3628,112 +3922,46 @@ function withSelection(board) {
|
|
|
3628
3922
|
selectionRectangleG?.remove();
|
|
3629
3923
|
}
|
|
3630
3924
|
const temporaryElements = getTemporaryElements(board);
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
elements = [elements[0]];
|
|
3925
|
+
if (temporaryElements) {
|
|
3926
|
+
cacheSelectedElements(board, [...temporaryElements]);
|
|
3634
3927
|
}
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
const selectedElementsInGroup = elementsInHighestGroup.filter(item => newSelectedElements.includes(item));
|
|
3653
|
-
// When partially selected elements belong to a group,
|
|
3654
|
-
// only select those elements along with the hit elements.
|
|
3655
|
-
if (selectedElementsInGroup.length) {
|
|
3656
|
-
pendingElements.push(...selectedElementsInGroup);
|
|
3928
|
+
else {
|
|
3929
|
+
let elements = getHitElementsBySelection(board);
|
|
3930
|
+
if (!options.isMultiple && elements.length > 1) {
|
|
3931
|
+
elements = [elements[0]];
|
|
3932
|
+
}
|
|
3933
|
+
const isHitElementWithGroup = elements.some(item => item.groupId);
|
|
3934
|
+
const selectedElements = getSelectedElements(board);
|
|
3935
|
+
if (isHitElementWithGroup) {
|
|
3936
|
+
setSelectedElementsWithGroup(board, elements, isShift);
|
|
3937
|
+
}
|
|
3938
|
+
else {
|
|
3939
|
+
if (isShift) {
|
|
3940
|
+
const newElements = [...selectedElements];
|
|
3941
|
+
if (board.selection && Selection.isCollapsed(board.selection)) {
|
|
3942
|
+
elements.forEach(element => {
|
|
3943
|
+
if (newElements.includes(element)) {
|
|
3944
|
+
newElements.splice(newElements.indexOf(element), 1);
|
|
3657
3945
|
}
|
|
3658
3946
|
else {
|
|
3659
|
-
|
|
3947
|
+
newElements.push(element);
|
|
3660
3948
|
}
|
|
3661
|
-
}
|
|
3662
|
-
|
|
3663
|
-
pendingElements = [];
|
|
3664
|
-
}
|
|
3949
|
+
});
|
|
3950
|
+
cacheSelectedElements(board, newElements);
|
|
3665
3951
|
}
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
}
|
|
3674
|
-
}
|
|
3675
|
-
else {
|
|
3676
|
-
elements.forEach(element => {
|
|
3677
|
-
if (newSelectedElements.includes(element)) {
|
|
3678
|
-
newSelectedElements.splice(newSelectedElements.indexOf(element), 1);
|
|
3679
|
-
}
|
|
3680
|
-
else {
|
|
3681
|
-
newSelectedElements.push(element);
|
|
3682
|
-
}
|
|
3683
|
-
});
|
|
3684
|
-
}
|
|
3685
|
-
cacheSelectedElements(board, newSelectedElements);
|
|
3686
|
-
}
|
|
3687
|
-
else {
|
|
3688
|
-
let newElements = [...elements];
|
|
3689
|
-
if (isHitElementWithGroup) {
|
|
3690
|
-
elements.forEach(item => {
|
|
3691
|
-
if (!item.groupId) {
|
|
3692
|
-
newElements.push(item);
|
|
3693
|
-
}
|
|
3694
|
-
else {
|
|
3695
|
-
newElements.push(...getElementsInGroupByElement(board, item));
|
|
3696
|
-
}
|
|
3697
|
-
});
|
|
3698
|
-
}
|
|
3699
|
-
newElements.forEach(element => {
|
|
3700
|
-
if (!newSelectedElements.includes(element)) {
|
|
3701
|
-
newSelectedElements.push(element);
|
|
3952
|
+
else {
|
|
3953
|
+
elements.forEach(element => {
|
|
3954
|
+
if (!newElements.includes(element)) {
|
|
3955
|
+
newElements.push(element);
|
|
3956
|
+
}
|
|
3957
|
+
});
|
|
3958
|
+
cacheSelectedElements(board, [...newElements]);
|
|
3702
3959
|
}
|
|
3703
|
-
});
|
|
3704
|
-
cacheSelectedElements(board, newSelectedElements);
|
|
3705
|
-
}
|
|
3706
|
-
}
|
|
3707
|
-
else {
|
|
3708
|
-
let newSelectedElements = [...elements];
|
|
3709
|
-
if (isHitElementWithGroup) {
|
|
3710
|
-
const isCollapsed = Selection.isCollapsed(board.selection);
|
|
3711
|
-
if (!isCollapsed) {
|
|
3712
|
-
newSelectedElements = [];
|
|
3713
|
-
elements.forEach(item => {
|
|
3714
|
-
if (!item.groupId) {
|
|
3715
|
-
newSelectedElements.push(item);
|
|
3716
|
-
}
|
|
3717
|
-
else {
|
|
3718
|
-
newSelectedElements.push(...getElementsInGroupByElement(board, item));
|
|
3719
|
-
}
|
|
3720
|
-
});
|
|
3721
3960
|
}
|
|
3722
3961
|
else {
|
|
3723
|
-
|
|
3724
|
-
const groups = getGroupByElement(board, hitElement, true);
|
|
3725
|
-
const selectedGroups = getSelectedGroups(board, groups);
|
|
3726
|
-
if (selectedGroups.length > 0) {
|
|
3727
|
-
if (selectedGroups.length > 1) {
|
|
3728
|
-
newSelectedElements = getElementsInGroup(board, selectedGroups[selectedGroups.length - 2], true);
|
|
3729
|
-
}
|
|
3730
|
-
}
|
|
3731
|
-
else {
|
|
3732
|
-
newSelectedElements = getElementsInGroup(board, groups[groups.length - 1], true);
|
|
3733
|
-
}
|
|
3962
|
+
cacheSelectedElements(board, [...elements]);
|
|
3734
3963
|
}
|
|
3735
3964
|
}
|
|
3736
|
-
cacheSelectedElements(board, newSelectedElements);
|
|
3737
3965
|
}
|
|
3738
3966
|
const newElements = getSelectedElements(board);
|
|
3739
3967
|
previousSelectedElements = newElements;
|
|
@@ -3741,7 +3969,8 @@ function withSelection(board) {
|
|
|
3741
3969
|
if (!isSelectionMoving(board)) {
|
|
3742
3970
|
selectionRectangleG?.remove();
|
|
3743
3971
|
if (newElements.length > 1) {
|
|
3744
|
-
selectionRectangleG =
|
|
3972
|
+
selectionRectangleG = board.drawActiveRectangle();
|
|
3973
|
+
PlaitBoard.getElementActiveHost(board).append(selectionRectangleG);
|
|
3745
3974
|
}
|
|
3746
3975
|
}
|
|
3747
3976
|
}
|
|
@@ -3760,7 +3989,8 @@ function withSelection(board) {
|
|
|
3760
3989
|
(currentSelectedElements.length !== previousSelectedElements.length ||
|
|
3761
3990
|
currentSelectedElements.some((c, index) => c !== previousSelectedElements[index]))) {
|
|
3762
3991
|
selectionRectangleG?.remove();
|
|
3763
|
-
selectionRectangleG =
|
|
3992
|
+
selectionRectangleG = board.drawActiveRectangle();
|
|
3993
|
+
PlaitBoard.getElementActiveHost(board).append(selectionRectangleG);
|
|
3764
3994
|
previousSelectedElements = currentSelectedElements;
|
|
3765
3995
|
}
|
|
3766
3996
|
}
|
|
@@ -3809,8 +4039,8 @@ function withViewport(board) {
|
|
|
3809
4039
|
return board;
|
|
3810
4040
|
}
|
|
3811
4041
|
|
|
3812
|
-
const
|
|
3813
|
-
class
|
|
4042
|
+
const SNAP_TOLERANCE = 2;
|
|
4043
|
+
class MovingSnapReaction {
|
|
3814
4044
|
constructor(board, activeElements, activeRectangle) {
|
|
3815
4045
|
this.board = board;
|
|
3816
4046
|
this.activeElements = activeElements;
|
|
@@ -3824,7 +4054,7 @@ class AlignReaction {
|
|
|
3824
4054
|
return;
|
|
3825
4055
|
}
|
|
3826
4056
|
const rectangle = this.board.getRectangle(node);
|
|
3827
|
-
rectangle && result.push(rectangle);
|
|
4057
|
+
rectangle && result.push(getRectangleByAngle(rectangle, node.angle) || rectangle);
|
|
3828
4058
|
}, node => {
|
|
3829
4059
|
if (node && (PlaitBoard.isBoard(node) || this.board.isRecursion(node))) {
|
|
3830
4060
|
return true;
|
|
@@ -3835,7 +4065,7 @@ class AlignReaction {
|
|
|
3835
4065
|
}, true);
|
|
3836
4066
|
return result;
|
|
3837
4067
|
}
|
|
3838
|
-
|
|
4068
|
+
handleSnapping() {
|
|
3839
4069
|
const alignRectangles = this.getAlignRectangle();
|
|
3840
4070
|
const g = createG();
|
|
3841
4071
|
let alignLines = [];
|
|
@@ -3847,7 +4077,7 @@ class AlignReaction {
|
|
|
3847
4077
|
for (let alignRectangle of alignRectangles) {
|
|
3848
4078
|
const closestDistances = this.calculateClosestDistances(this.activeRectangle, alignRectangle);
|
|
3849
4079
|
let canDrawHorizontal = false;
|
|
3850
|
-
if (!isCorrectX && closestDistances.absXDistance <
|
|
4080
|
+
if (!isCorrectX && closestDistances.absXDistance < SNAP_TOLERANCE) {
|
|
3851
4081
|
deltaX = closestDistances.xDistance;
|
|
3852
4082
|
this.activeRectangle.x -= deltaX;
|
|
3853
4083
|
isCorrectX = true;
|
|
@@ -3897,7 +4127,7 @@ class AlignReaction {
|
|
|
3897
4127
|
isCorrectX = true;
|
|
3898
4128
|
}
|
|
3899
4129
|
let canDrawVertical = false;
|
|
3900
|
-
if (!isCorrectY && closestDistances.absYDistance <
|
|
4130
|
+
if (!isCorrectY && closestDistances.absYDistance < SNAP_TOLERANCE) {
|
|
3901
4131
|
deltaY = closestDistances.yDistance;
|
|
3902
4132
|
this.activeRectangle.y -= deltaY;
|
|
3903
4133
|
isCorrectY = true;
|
|
@@ -4044,7 +4274,7 @@ class AlignReaction {
|
|
|
4044
4274
|
//middle
|
|
4045
4275
|
let _center = (before[axis] + before[side] + after[axis]) / 2;
|
|
4046
4276
|
dif = Math.abs(activeRectangleCenter - _center);
|
|
4047
|
-
if (dif <
|
|
4277
|
+
if (dif < SNAP_TOLERANCE) {
|
|
4048
4278
|
distributeDistance = (after[axis] - (before[axis] + before[side]) - this.activeRectangle[side]) / 2;
|
|
4049
4279
|
delta = activeRectangleCenter - _center;
|
|
4050
4280
|
beforeIndex = i;
|
|
@@ -4054,7 +4284,7 @@ class AlignReaction {
|
|
|
4054
4284
|
const distanceRight = after[axis] - (before[axis] + before[side]);
|
|
4055
4285
|
_center = after[axis] + after[side] + distanceRight + this.activeRectangle[side] / 2;
|
|
4056
4286
|
dif = Math.abs(activeRectangleCenter - _center);
|
|
4057
|
-
if (!distributeDistance && dif <
|
|
4287
|
+
if (!distributeDistance && dif < SNAP_TOLERANCE) {
|
|
4058
4288
|
distributeDistance = distanceRight;
|
|
4059
4289
|
beforeIndex = j;
|
|
4060
4290
|
delta = activeRectangleCenter - _center;
|
|
@@ -4063,7 +4293,7 @@ class AlignReaction {
|
|
|
4063
4293
|
const distanceBefore = after[axis] - (before[axis] + before[side]);
|
|
4064
4294
|
_center = before[axis] - distanceBefore - this.activeRectangle[side] / 2;
|
|
4065
4295
|
dif = Math.abs(activeRectangleCenter - _center);
|
|
4066
|
-
if (!distributeDistance && dif <
|
|
4296
|
+
if (!distributeDistance && dif < SNAP_TOLERANCE) {
|
|
4067
4297
|
distributeDistance = distanceBefore;
|
|
4068
4298
|
afterIndex = i;
|
|
4069
4299
|
delta = activeRectangleCenter - _center;
|
|
@@ -4185,6 +4415,9 @@ function withMoving(board) {
|
|
|
4185
4415
|
let activeElements = [];
|
|
4186
4416
|
let alignG = null;
|
|
4187
4417
|
let activeElementsRectangle = null;
|
|
4418
|
+
let selectedTargetElements = null;
|
|
4419
|
+
let hitTargetElement = undefined;
|
|
4420
|
+
let isHitSelectedTarget = undefined;
|
|
4188
4421
|
board.pointerDown = (event) => {
|
|
4189
4422
|
if (PlaitBoard.isReadonly(board) ||
|
|
4190
4423
|
!PlaitBoard.isPointer(board, PlaitPointerType.selection) ||
|
|
@@ -4194,24 +4427,32 @@ function withMoving(board) {
|
|
|
4194
4427
|
return;
|
|
4195
4428
|
}
|
|
4196
4429
|
const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
if (
|
|
4430
|
+
hitTargetElement = getHitElementByPoint(board, point, el => board.isMovable(el));
|
|
4431
|
+
selectedTargetElements = getSelectedTargetElements(board);
|
|
4432
|
+
isHitSelectedTarget = hitTargetElement && selectedTargetElements.includes(hitTargetElement);
|
|
4433
|
+
if (hitTargetElement && isHitSelectedTarget) {
|
|
4201
4434
|
startPoint = point;
|
|
4202
|
-
activeElements =
|
|
4435
|
+
activeElements = selectedTargetElements;
|
|
4436
|
+
activeElementsRectangle = getRectangleByElements(board, activeElements, true);
|
|
4203
4437
|
preventTouchMove(board, event, true);
|
|
4438
|
+
}
|
|
4439
|
+
else if (hitTargetElement) {
|
|
4440
|
+
startPoint = point;
|
|
4441
|
+
const relatedElements = board.getRelatedFragment([], [hitTargetElement]);
|
|
4442
|
+
activeElements = [...getElementsInGroupByElement(board, hitTargetElement), ...relatedElements];
|
|
4204
4443
|
activeElementsRectangle = getRectangleByElements(board, activeElements, true);
|
|
4444
|
+
preventTouchMove(board, event, true);
|
|
4205
4445
|
}
|
|
4206
4446
|
else {
|
|
4207
|
-
|
|
4208
|
-
|
|
4447
|
+
// 只有判定用户未击中元素之后才可以验证用户是否击中了已选元素所在的空白区域
|
|
4448
|
+
// Only after it is determined that the user has not hit the element can it be verified whether the user hit the blank area where the selected element is located.
|
|
4449
|
+
const targetRectangle = selectedTargetElements.length > 0 && getRectangleByElements(board, selectedTargetElements, false);
|
|
4450
|
+
const isHitInTargetRectangle = targetRectangle && RectangleClient.isPointInRectangle(targetRectangle, point);
|
|
4451
|
+
if (isHitInTargetRectangle) {
|
|
4209
4452
|
startPoint = point;
|
|
4210
|
-
activeElements =
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
}
|
|
4214
|
-
activeElementsRectangle = getRectangleByElements(board, activeElements, true);
|
|
4453
|
+
activeElements = selectedTargetElements;
|
|
4454
|
+
activeElementsRectangle = targetRectangle;
|
|
4455
|
+
preventTouchMove(board, event, true);
|
|
4215
4456
|
}
|
|
4216
4457
|
}
|
|
4217
4458
|
pointerDown(event);
|
|
@@ -4227,6 +4468,12 @@ function withMoving(board) {
|
|
|
4227
4468
|
offsetY = endPoint[1] - startPoint[1];
|
|
4228
4469
|
const distance = distanceBetweenPointAndPoint(...endPoint, ...startPoint);
|
|
4229
4470
|
if (distance > PRESS_AND_MOVE_BUFFER || getMovingElements(board).length > 0) {
|
|
4471
|
+
if (hitTargetElement && !isHitSelectedTarget && selectedTargetElements && selectedTargetElements.length > 0) {
|
|
4472
|
+
addSelectionWithTemporaryElements(board, []);
|
|
4473
|
+
hitTargetElement = undefined;
|
|
4474
|
+
selectedTargetElements = null;
|
|
4475
|
+
isHitSelectedTarget = undefined;
|
|
4476
|
+
}
|
|
4230
4477
|
throttleRAF(board, 'with-moving', () => {
|
|
4231
4478
|
if (!activeElementsRectangle) {
|
|
4232
4479
|
return;
|
|
@@ -4236,8 +4483,8 @@ function withMoving(board) {
|
|
|
4236
4483
|
x: activeElementsRectangle.x + offsetX,
|
|
4237
4484
|
y: activeElementsRectangle.y + offsetY
|
|
4238
4485
|
};
|
|
4239
|
-
const
|
|
4240
|
-
const ref =
|
|
4486
|
+
const movingSnapReaction = new MovingSnapReaction(board, activeElements, getRectangleByAngle(newRectangle, getSelectionAngle(activeElements)) || newRectangle);
|
|
4487
|
+
const ref = movingSnapReaction.handleSnapping();
|
|
4241
4488
|
offsetX -= ref.deltaX;
|
|
4242
4489
|
offsetY -= ref.deltaY;
|
|
4243
4490
|
alignG = ref.g;
|
|
@@ -4267,6 +4514,9 @@ function withMoving(board) {
|
|
|
4267
4514
|
};
|
|
4268
4515
|
board.globalPointerUp = event => {
|
|
4269
4516
|
isPreventDefault = false;
|
|
4517
|
+
hitTargetElement = undefined;
|
|
4518
|
+
selectedTargetElements = null;
|
|
4519
|
+
isHitSelectedTarget = undefined;
|
|
4270
4520
|
if (startPoint) {
|
|
4271
4521
|
cancelMove(board);
|
|
4272
4522
|
}
|
|
@@ -4315,7 +4565,7 @@ function withArrowMoving(board) {
|
|
|
4315
4565
|
break;
|
|
4316
4566
|
}
|
|
4317
4567
|
}
|
|
4318
|
-
const targetElements =
|
|
4568
|
+
const targetElements = getSelectedTargetElements(board);
|
|
4319
4569
|
throttleRAF(board, 'with-arrow-moving', () => {
|
|
4320
4570
|
updatePoints(board, targetElements, offset[0], offset[1]);
|
|
4321
4571
|
});
|
|
@@ -4328,7 +4578,7 @@ function withArrowMoving(board) {
|
|
|
4328
4578
|
};
|
|
4329
4579
|
return board;
|
|
4330
4580
|
}
|
|
4331
|
-
function
|
|
4581
|
+
function getSelectedTargetElements(board) {
|
|
4332
4582
|
const selectedElements = getSelectedElements(board);
|
|
4333
4583
|
const movableElements = board.children.filter(item => board.isMovable(item));
|
|
4334
4584
|
const targetElements = selectedElements.filter(element => {
|
|
@@ -4339,7 +4589,7 @@ function getTargetElements(board) {
|
|
|
4339
4589
|
return targetElements;
|
|
4340
4590
|
}
|
|
4341
4591
|
function updatePoints(board, targetElements, offsetX, offsetY) {
|
|
4342
|
-
const validElements = targetElements.filter(element => board.children.findIndex(item => item.id === element.id) > -1);
|
|
4592
|
+
const validElements = targetElements.filter(element => !PlaitGroupElement.isGroup(element) && board.children.findIndex(item => item.id === element.id) > -1);
|
|
4343
4593
|
const currentElements = validElements.map(element => {
|
|
4344
4594
|
const points = element.points || [];
|
|
4345
4595
|
const newPoints = points.map(p => [p[0] + offsetX, p[1] + offsetY]);
|
|
@@ -4463,7 +4713,7 @@ const withHotkey = (board) => {
|
|
|
4463
4713
|
selectedElements.length > 0 &&
|
|
4464
4714
|
(hotkeys.isDeleteBackward(event) || hotkeys.isDeleteForward(event))) {
|
|
4465
4715
|
event.preventDefault();
|
|
4466
|
-
|
|
4716
|
+
deleteFragment(board);
|
|
4467
4717
|
}
|
|
4468
4718
|
keyDown(event);
|
|
4469
4719
|
};
|
|
@@ -4671,27 +4921,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
|
|
|
4671
4921
|
type: Input
|
|
4672
4922
|
}] } });
|
|
4673
4923
|
|
|
4674
|
-
function
|
|
4675
|
-
const {
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
let selection = { anchor: point, focus: point };
|
|
4681
|
-
if (board.selection && !Selection.isCollapsed(board.selection)) {
|
|
4682
|
-
selection = board.selection;
|
|
4924
|
+
function withRelatedFragment(board) {
|
|
4925
|
+
const { setFragment } = board;
|
|
4926
|
+
board.setFragment = (data, clipboardContext, rectangle, type) => {
|
|
4927
|
+
const relatedFragment = board.getRelatedFragment([]);
|
|
4928
|
+
if (!clipboardContext) {
|
|
4929
|
+
clipboardContext = createClipboardContext(WritableClipboardType.elements, relatedFragment, '');
|
|
4683
4930
|
}
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4931
|
+
else {
|
|
4932
|
+
clipboardContext = addClipboardContext(clipboardContext, {
|
|
4933
|
+
text: '',
|
|
4934
|
+
type: WritableClipboardType.elements,
|
|
4935
|
+
data: relatedFragment
|
|
4936
|
+
});
|
|
4688
4937
|
}
|
|
4689
|
-
|
|
4690
|
-
};
|
|
4691
|
-
board.globalPointerUp = (event) => {
|
|
4692
|
-
groupRectangleG?.remove();
|
|
4693
|
-
groupRectangleG = null;
|
|
4694
|
-
globalPointerUp(event);
|
|
4938
|
+
setFragment(data, clipboardContext, rectangle, type);
|
|
4695
4939
|
};
|
|
4696
4940
|
return board;
|
|
4697
4941
|
}
|
|
@@ -4769,6 +5013,7 @@ class PlaitBoardComponent {
|
|
|
4769
5013
|
BOARD_TO_COMPONENT.set(this.board, this);
|
|
4770
5014
|
BOARD_TO_ROUGH_SVG.set(this.board, roughSVG);
|
|
4771
5015
|
BOARD_TO_HOST.set(this.board, this.host);
|
|
5016
|
+
IS_BOARD_ALIVE.set(this.board, true);
|
|
4772
5017
|
BOARD_TO_ELEMENT_HOST.set(this.board, {
|
|
4773
5018
|
host: elementHost,
|
|
4774
5019
|
upperHost: elementUpperHost,
|
|
@@ -4821,7 +5066,7 @@ class PlaitBoardComponent {
|
|
|
4821
5066
|
initializeViewportOffset(this.board);
|
|
4822
5067
|
}
|
|
4823
5068
|
initializePlugins() {
|
|
4824
|
-
let board = withHotkey(withHandPointer(withHistory(withSelection(
|
|
5069
|
+
let board = withRelatedFragment(withHotkey(withHandPointer(withHistory(withSelection(withMoving(withBoard(withViewport(withOptions(createBoard(this.plaitValue, this.plaitOptions))))))))));
|
|
4825
5070
|
this.plaitPlugins.forEach(plugin => {
|
|
4826
5071
|
board = plugin(board);
|
|
4827
5072
|
});
|
|
@@ -4942,7 +5187,7 @@ class PlaitBoardComponent {
|
|
|
4942
5187
|
event.preventDefault();
|
|
4943
5188
|
const rectangle = getRectangleByElements(this.board, selectedElements, false);
|
|
4944
5189
|
this.board.setFragment(event.clipboardData, null, rectangle, 'cut');
|
|
4945
|
-
this.board
|
|
5190
|
+
deleteFragment(this.board);
|
|
4946
5191
|
});
|
|
4947
5192
|
}
|
|
4948
5193
|
viewportScrollListener() {
|
|
@@ -5024,6 +5269,7 @@ class PlaitBoardComponent {
|
|
|
5024
5269
|
BOARD_TO_ROUGH_SVG.delete(this.board);
|
|
5025
5270
|
BOARD_TO_HOST.delete(this.board);
|
|
5026
5271
|
BOARD_TO_ELEMENT_HOST.delete(this.board);
|
|
5272
|
+
IS_BOARD_ALIVE.set(this.board, false);
|
|
5027
5273
|
BOARD_TO_ON_CHANGE.delete(this.board);
|
|
5028
5274
|
BOARD_TO_AFTER_CHANGE.set(this.board, () => { });
|
|
5029
5275
|
}
|
|
@@ -5263,6 +5509,96 @@ function createModModifierKeys() {
|
|
|
5263
5509
|
return modifiers;
|
|
5264
5510
|
}
|
|
5265
5511
|
|
|
5512
|
+
const TEMPORARY_G = new Map();
|
|
5513
|
+
const getTemporaryGArray = (debugKey) => {
|
|
5514
|
+
return TEMPORARY_G.get(debugKey) || [];
|
|
5515
|
+
};
|
|
5516
|
+
const setTemporaryGArray = (debugKey, gArray) => {
|
|
5517
|
+
TEMPORARY_G.set(debugKey, gArray);
|
|
5518
|
+
};
|
|
5519
|
+
class DebugGenerator {
|
|
5520
|
+
constructor(debugKey) {
|
|
5521
|
+
this.debugKey = debugKey;
|
|
5522
|
+
}
|
|
5523
|
+
isDebug() {
|
|
5524
|
+
return isDebug(this.debugKey);
|
|
5525
|
+
}
|
|
5526
|
+
clear() {
|
|
5527
|
+
if (!this.isDebug()) {
|
|
5528
|
+
return;
|
|
5529
|
+
}
|
|
5530
|
+
const gArray = getTemporaryGArray(this.debugKey);
|
|
5531
|
+
setTemporaryGArray(this.debugKey, []);
|
|
5532
|
+
gArray.forEach(g => g.remove());
|
|
5533
|
+
}
|
|
5534
|
+
drawPolygon(board, points, options) {
|
|
5535
|
+
if (!isDebug(this.debugKey)) {
|
|
5536
|
+
return;
|
|
5537
|
+
}
|
|
5538
|
+
const polygonG = PlaitBoard.getRoughSVG(board).polygon(points, options || { stroke: 'red' });
|
|
5539
|
+
polygonG.classList.add(this.debugKey);
|
|
5540
|
+
PlaitBoard.getElementActiveHost(board).append(polygonG);
|
|
5541
|
+
const gArray = getTemporaryGArray(this.debugKey);
|
|
5542
|
+
gArray.push(polygonG);
|
|
5543
|
+
setTemporaryGArray(this.debugKey, gArray);
|
|
5544
|
+
return polygonG;
|
|
5545
|
+
}
|
|
5546
|
+
drawLine(board, points, options) {
|
|
5547
|
+
if (!isDebug(this.debugKey)) {
|
|
5548
|
+
return;
|
|
5549
|
+
}
|
|
5550
|
+
const lineG = PlaitBoard.getRoughSVG(board).linearPath(points, options || { stroke: 'red' });
|
|
5551
|
+
lineG.classList.add(this.debugKey);
|
|
5552
|
+
PlaitBoard.getElementActiveHost(board).append(lineG);
|
|
5553
|
+
const gArray = getTemporaryGArray(this.debugKey);
|
|
5554
|
+
gArray.push(lineG);
|
|
5555
|
+
setTemporaryGArray(this.debugKey, gArray);
|
|
5556
|
+
return lineG;
|
|
5557
|
+
}
|
|
5558
|
+
drawRectangle(board, data, options) {
|
|
5559
|
+
if (!isDebug(this.debugKey)) {
|
|
5560
|
+
return;
|
|
5561
|
+
}
|
|
5562
|
+
let rectangle;
|
|
5563
|
+
if (data instanceof Array) {
|
|
5564
|
+
rectangle = RectangleClient.getRectangleByPoints(data);
|
|
5565
|
+
}
|
|
5566
|
+
else {
|
|
5567
|
+
rectangle = data;
|
|
5568
|
+
}
|
|
5569
|
+
const rectangleG = PlaitBoard.getRoughSVG(board).rectangle(rectangle.x, rectangle.y, rectangle.width, rectangle.height, options || { stroke: 'red' });
|
|
5570
|
+
rectangleG.classList.add(this.debugKey);
|
|
5571
|
+
PlaitBoard.getElementActiveHost(board).append(rectangleG);
|
|
5572
|
+
const gArray = getTemporaryGArray(this.debugKey);
|
|
5573
|
+
gArray.push(rectangleG);
|
|
5574
|
+
setTemporaryGArray(this.debugKey, gArray);
|
|
5575
|
+
return rectangleG;
|
|
5576
|
+
}
|
|
5577
|
+
drawCircles(board, points, diameter = 0, isCumulativeDiameter = false, options) {
|
|
5578
|
+
if (!isDebug(this.debugKey)) {
|
|
5579
|
+
return;
|
|
5580
|
+
}
|
|
5581
|
+
const result = [];
|
|
5582
|
+
points.forEach((p, i) => {
|
|
5583
|
+
const circle = PlaitBoard.getRoughSVG(board).circle(p[0], p[1], isCumulativeDiameter ? diameter * (i + 1) : diameter, Object.assign({}, { stroke: 'red', fill: 'red', fillStyle: 'solid' }, options || {}));
|
|
5584
|
+
circle.classList.add(this.debugKey);
|
|
5585
|
+
PlaitBoard.getElementActiveHost(board).append(circle);
|
|
5586
|
+
const gArray = getTemporaryGArray(this.debugKey);
|
|
5587
|
+
gArray.push(circle);
|
|
5588
|
+
result.push(circle);
|
|
5589
|
+
setTemporaryGArray(this.debugKey, gArray);
|
|
5590
|
+
});
|
|
5591
|
+
return result;
|
|
5592
|
+
}
|
|
5593
|
+
}
|
|
5594
|
+
const createDebugGenerator = (debugKey) => {
|
|
5595
|
+
return new DebugGenerator(debugKey);
|
|
5596
|
+
};
|
|
5597
|
+
const isDebug = (key) => {
|
|
5598
|
+
const defaultKey = 'debug:plait';
|
|
5599
|
+
return localStorage.getItem(key || defaultKey) === 'true';
|
|
5600
|
+
};
|
|
5601
|
+
|
|
5266
5602
|
/*
|
|
5267
5603
|
* Public API Surface of plait
|
|
5268
5604
|
*/
|
|
@@ -5271,5 +5607,5 @@ function createModModifierKeys() {
|
|
|
5271
5607
|
* Generated bundle index. Do not edit.
|
|
5272
5608
|
*/
|
|
5273
5609
|
|
|
5274
|
-
export { A, ACTIVE_MOVING_CLASS_NAME, ACTIVE_STROKE_WIDTH, ALT, APOSTROPHE, ATTACHED_ELEMENT_CLASS_NAME, AT_SIGN, B, BACKSLASH, BACKSPACE, BOARD_TO_AFTER_CHANGE, BOARD_TO_COMPONENT, BOARD_TO_ELEMENT_HOST, BOARD_TO_HOST, BOARD_TO_IS_SELECTION_MOVING, BOARD_TO_MOVING_ELEMENT, BOARD_TO_MOVING_POINT, BOARD_TO_MOVING_POINT_IN_BOARD, BOARD_TO_ON_CHANGE, BOARD_TO_ROUGH_SVG, BOARD_TO_SELECTED_ELEMENT, BOARD_TO_TEMPORARY_ELEMENTS, BOARD_TO_TOUCH_REF, BOARD_TO_VIEWPORT_ORIGINATION, BoardTransforms, C, CAPS_LOCK, CLOSE_SQUARE_BRACKET, COMMA, CONTEXT_MENU, CONTROL, ColorfulThemeColor, CoreTransforms, CursorClass, D, DASH, DELETE, DOWN_ARROW, DarkThemeColor, DefaultThemeColor, Direction, E, EIGHT, ELEMENT_TO_COMPONENT, END, ENTER, EQUALS, ESCAPE, F, F1, F10, F11, F12, F2, F3, F4, F5, F6, F7, F8, F9, FF_EQUALS, FF_MINUS, FF_MUTE, FF_SEMICOLON, FF_VOLUME_DOWN, FF_VOLUME_UP, FIRST_MEDIA, FIVE, FLUSHING, FOUR, G, H, HIT_DISTANCE_BUFFER, HOME, HOST_CLASS_NAME, I, INSERT, IS_APPLE, IS_BOARD_CACHE, IS_CHROME, IS_CHROME_LEGACY, IS_DRAGGING, IS_EDGE_LEGACY, IS_FIREFOX, IS_IOS, IS_MAC, IS_SAFARI, IS_TEXT_EDITABLE, J, K, L, LAST_MEDIA, LEFT_ARROW, M, MAC_ENTER, MAC_META, MAC_WK_CMD_LEFT, MAC_WK_CMD_RIGHT, MAX_RADIUS, MERGING, META, MUTE, N, NINE, NODE_TO_INDEX, NODE_TO_PARENT, NS, NUMPAD_DIVIDE, NUMPAD_EIGHT, NUMPAD_FIVE, NUMPAD_FOUR, NUMPAD_MINUS, NUMPAD_MULTIPLY, NUMPAD_NINE, NUMPAD_ONE, NUMPAD_PERIOD, NUMPAD_PLUS, NUMPAD_SEVEN, NUMPAD_SIX, NUMPAD_THREE, NUMPAD_TWO, NUMPAD_ZERO, NUM_CENTER, NUM_LOCK, O, ONE, OPEN_SQUARE_BRACKET, P, PAGE_DOWN, PAGE_UP, PATH_REFS, PAUSE, PERIOD, PLUS_SIGN, POINTER_BUTTON, PRESS_AND_MOVE_BUFFER, PRINT_SCREEN, Path, PlaitBoard, PlaitBoardComponent, PlaitChildrenElementComponent, PlaitContextService, PlaitElement, PlaitElementComponent, PlaitGroupElement, PlaitHistoryBoard, PlaitIslandBaseComponent, PlaitIslandPopoverBaseComponent, PlaitNode, PlaitOperation, PlaitPluginElementComponent, PlaitPluginKey, PlaitPointerType, Point, Q, QUESTION_MARK, R, RIGHT_ARROW, RectangleClient, ResizeCursorClass, RetroThemeColor, RgbaToHEX, S, SAVING, SCROLL_BAR_WIDTH, SCROLL_LOCK, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, SELECTION_RECTANGLE_CLASS_NAME, SEMICOLON, SEVEN, SHIFT, SINGLE_QUOTE, SIX, SLASH, SPACE, Selection, SoftThemeColor, StarryThemeColor, T, TAB, THREE, TILDE, TWO, ThemeColorMode, ThemeColors, Transforms, U, UP_ARROW, V, VOLUME_DOWN, VOLUME_UP, Viewport, W, WritableClipboardType, X, Y, Z, ZERO, addClipboardContext,
|
|
5610
|
+
export { A, ACTIVE_MOVING_CLASS_NAME, ACTIVE_STROKE_WIDTH, ALT, APOSTROPHE, ATTACHED_ELEMENT_CLASS_NAME, AT_SIGN, B, BACKSLASH, BACKSPACE, BOARD_TO_AFTER_CHANGE, BOARD_TO_COMPONENT, BOARD_TO_ELEMENT_HOST, BOARD_TO_HOST, BOARD_TO_IS_SELECTION_MOVING, BOARD_TO_MOVING_ELEMENT, BOARD_TO_MOVING_POINT, BOARD_TO_MOVING_POINT_IN_BOARD, BOARD_TO_ON_CHANGE, BOARD_TO_ROUGH_SVG, BOARD_TO_SELECTED_ELEMENT, BOARD_TO_TEMPORARY_ELEMENTS, BOARD_TO_TOUCH_REF, BOARD_TO_VIEWPORT_ORIGINATION, BoardTransforms, C, CAPS_LOCK, CLOSE_SQUARE_BRACKET, COMMA, CONTEXT_MENU, CONTROL, ColorfulThemeColor, CoreTransforms, CursorClass, D, DASH, DELETE, DOWN_ARROW, DarkThemeColor, DebugGenerator, DefaultThemeColor, Direction, E, EIGHT, ELEMENT_TO_COMPONENT, END, ENTER, EQUALS, ESCAPE, F, F1, F10, F11, F12, F2, F3, F4, F5, F6, F7, F8, F9, FF_EQUALS, FF_MINUS, FF_MUTE, FF_SEMICOLON, FF_VOLUME_DOWN, FF_VOLUME_UP, FIRST_MEDIA, FIVE, FLUSHING, FOUR, G, GroupTransforms, H, HIT_DISTANCE_BUFFER, HOME, HOST_CLASS_NAME, I, INSERT, IS_APPLE, IS_BOARD_ALIVE, IS_BOARD_CACHE, IS_CHROME, IS_CHROME_LEGACY, IS_DRAGGING, IS_EDGE_LEGACY, IS_FIREFOX, IS_IOS, IS_MAC, IS_SAFARI, IS_TEXT_EDITABLE, J, K, L, LAST_MEDIA, LEFT_ARROW, M, MAC_ENTER, MAC_META, MAC_WK_CMD_LEFT, MAC_WK_CMD_RIGHT, MAX_RADIUS, MERGING, META, MUTE, N, NINE, NODE_TO_INDEX, NODE_TO_PARENT, NS, NUMPAD_DIVIDE, NUMPAD_EIGHT, NUMPAD_FIVE, NUMPAD_FOUR, NUMPAD_MINUS, NUMPAD_MULTIPLY, NUMPAD_NINE, NUMPAD_ONE, NUMPAD_PERIOD, NUMPAD_PLUS, NUMPAD_SEVEN, NUMPAD_SIX, NUMPAD_THREE, NUMPAD_TWO, NUMPAD_ZERO, NUM_CENTER, NUM_LOCK, O, ONE, OPEN_SQUARE_BRACKET, P, PAGE_DOWN, PAGE_UP, PATH_REFS, PAUSE, PERIOD, PLUS_SIGN, POINTER_BUTTON, PRESS_AND_MOVE_BUFFER, PRINT_SCREEN, Path, PlaitBoard, PlaitBoardComponent, PlaitChildrenElementComponent, PlaitContextService, PlaitElement, PlaitElementComponent, PlaitGroupElement, PlaitHistoryBoard, PlaitIslandBaseComponent, PlaitIslandPopoverBaseComponent, PlaitNode, PlaitOperation, PlaitPluginElementComponent, PlaitPluginKey, PlaitPointerType, Point, Q, QUESTION_MARK, R, RESIZE_CURSORS, RIGHT_ARROW, RectangleClient, ResizeCursorClass, RetroThemeColor, RgbaToHEX, S, SAVING, SCROLL_BAR_WIDTH, SCROLL_LOCK, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, SELECTION_RECTANGLE_CLASS_NAME, SEMICOLON, SEVEN, SHIFT, SINGLE_QUOTE, SIX, SLASH, SNAPPING_STROKE_WIDTH, SPACE, Selection, SoftThemeColor, StarryThemeColor, T, TAB, THREE, TILDE, TWO, ThemeColorMode, ThemeColors, Transforms, U, UP_ARROW, V, VOLUME_DOWN, VOLUME_UP, Viewport, W, WritableClipboardType, X, Y, Z, ZERO, addClipboardContext, addSelectedElement, approximately, arrowPoints, buildPlaitHtml, cacheMovingElements, cacheSelectedElements, cacheSelectedElementsWithGroup, cacheSelectedElementsWithGroupOnShift, calcNewViewBox, canAddGroup, canRemoveGroup, catmullRomFitting, clampZoomLevel, clearNodeWeakMap, clearSelectedElement, clearSelectionMoving, clearViewportOrigination, createClipboardContext, createDebugGenerator, createFakeEvent, createForeignObject, createG, createGroup, createGroupRectangleG, createKeyboardEvent, createMask, createModModifierKeys, createMouseEvent, createPath, createPointerEvent, createRect, createSVG, createTestingBoard, createText, createTouchEvent, debounce, degreesToRadians, deleteFragment, deleteTemporaryElements, depthFirstRecursion, distanceBetweenPointAndPoint, distanceBetweenPointAndRectangle, distanceBetweenPointAndSegment, distanceBetweenPointAndSegments, downloadImage, drawArrow, drawBezierPath, drawCircle, drawEntireActiveRectangleG, drawLine, drawLinearPath, drawRectangle, drawRoundRectangle, fakeNodeWeakMap, filterSelectedGroups, findElements, getAllElementsInGroup, getBoardRectangle, getClipboardData, getClipboardFromHtml, getDataTransferClipboard, getDataTransferClipboardText, getElementById, getElementHostBBox, getElementsInGroup, getElementsInGroupByElement, getEllipseTangentSlope, getGroupByElement, getHighestGroup, getHighestSelectedElements, getHighestSelectedGroup, getHighestSelectedGroups, getHitElementByPoint, getHitElementsBySelection, getHitSelectedElements, getIsRecursionFunc, getMovingElements, getNearestPointBetweenPointAndSegment, getNearestPointBetweenPointAndSegments, getOffsetAfterRotate, getProbablySupportsClipboardRead, getProbablySupportsClipboardWrite, getProbablySupportsClipboardWriteText, getRealScrollBarWidth, getRectangleByAngle, getRectangleByElements, getRectangleByGroup, getRotatedBoundingRectangle, getSelectedElements, getSelectedGroups, getSelectedIsolatedElements, getSelectedIsolatedElementsCanAddToGroup, getSelectedTargetElements, getSelectionAngle, getTemporaryElements, getTemporaryRef, getVectorFromPointAndSlope, getViewBox, getViewBoxCenterPoint, getViewportContainerRect, getViewportOrigination, handleTouchTarget, hasBeforeContextChange, hasInputOrTextareaTarget, hasOnBoardChange, hasOnContextChanged, hasSameAngle, hasSelectedElementsInSameGroup, hasValidAngle, hotkeys, idCreator, initializeViewBox, initializeViewportContainer, initializeViewportOffset, inverse, isAxisChangedByAngle, isContextmenu, isDOMElement, isDOMNode, isDebug, isDragging, isFromScrolling, isFromViewportChange, isHandleSelection, isInPlaitBoard, isLineHitLine, isMainPointer, isMovingElements, isNullOrUndefined, isPointInEllipse, isPointInPolygon, isPointInRoundRectangle, isPolylineHitRectangle, isPreventTouchMove, isSecondaryPointer, isSelectedAllElementsInGroup, isSelectedElement, isSelectedElementOrGroup, isSelectionMoving, isSetSelectionOperation, isSetViewportOperation, nonGroupInHighestSelectedElements, normalizePoint, preventTouchMove, radiansToDegrees, removeMovingElements, removeSelectedElement, rotate, rotateAntiPointsByElement, rotateElements, rotatePoints, rotatePointsByElement, rotatedDataPoints, scrollToRectangle, setAngleForG, setClipboardData, setDataTransferClipboard, setDataTransferClipboardText, setDragging, setIsFromScrolling, setIsFromViewportChange, setPathStrokeLinecap, setSVGViewBox, setSelectedElementsWithGroup, setSelectionMoving, setStrokeLinecap, shouldClear, shouldMerge, shouldSave, stripHtml, temporaryDisableSelection, throttleRAF, toDomPrecision, toFixed, toHostPoint, toHostPointFromViewBoxPoint, toImage, toScreenPointFromHostPoint, toViewBoxPoint, toViewBoxPoints, uniqueById, updateForeignObject, updateForeignObjectWidth, updatePoints, updateViewportByScrolling, updateViewportContainerScroll, updateViewportOffset, updateViewportOrigination, withArrowMoving, withMoving, withOptions, withSelection };
|
|
5275
5611
|
//# sourceMappingURL=plait-core.mjs.map
|