@plait/core 0.1.1 → 0.1.2

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.
Files changed (45) hide show
  1. package/board/board.component.d.ts +4 -17
  2. package/board/board.component.interface.d.ts +0 -2
  3. package/constants/selection.d.ts +1 -0
  4. package/esm2020/board/board.component.interface.mjs +1 -1
  5. package/esm2020/board/board.component.mjs +49 -248
  6. package/esm2020/constants/selection.mjs +2 -0
  7. package/esm2020/core/element/element.component.mjs +2 -2
  8. package/esm2020/interfaces/board.mjs +11 -2
  9. package/esm2020/interfaces/viewport.mjs +1 -1
  10. package/esm2020/plugins/create-board.mjs +2 -1
  11. package/esm2020/plugins/with-hand.mjs +9 -6
  12. package/esm2020/plugins/with-moving.mjs +91 -0
  13. package/esm2020/plugins/with-selection.mjs +43 -12
  14. package/esm2020/plugins/with-viewport.mjs +11 -0
  15. package/esm2020/public-api.mjs +2 -1
  16. package/esm2020/utils/board.mjs +7 -3
  17. package/esm2020/utils/common.mjs +15 -0
  18. package/esm2020/utils/element.mjs +3 -3
  19. package/esm2020/utils/helper.mjs +14 -1
  20. package/esm2020/utils/index.mjs +4 -2
  21. package/esm2020/utils/moving-element.mjs +15 -0
  22. package/esm2020/utils/selected-element.mjs +14 -1
  23. package/esm2020/utils/viewport.mjs +170 -0
  24. package/esm2020/utils/weak-maps.mjs +3 -1
  25. package/fesm2015/plait-core.mjs +548 -561
  26. package/fesm2015/plait-core.mjs.map +1 -1
  27. package/fesm2020/plait-core.mjs +548 -558
  28. package/fesm2020/plait-core.mjs.map +1 -1
  29. package/interfaces/board.d.ts +4 -10
  30. package/interfaces/viewport.d.ts +2 -2
  31. package/package.json +1 -1
  32. package/plugins/with-moving.d.ts +2 -0
  33. package/plugins/with-selection.d.ts +4 -1
  34. package/plugins/with-viewport.d.ts +2 -0
  35. package/public-api.d.ts +1 -0
  36. package/utils/board.d.ts +1 -1
  37. package/utils/common.d.ts +1 -0
  38. package/utils/helper.d.ts +9 -0
  39. package/utils/index.d.ts +3 -1
  40. package/utils/moving-element.d.ts +5 -0
  41. package/utils/selected-element.d.ts +2 -0
  42. package/utils/viewport.d.ts +29 -0
  43. package/utils/weak-maps.d.ts +2 -0
  44. package/esm2020/utils/matrix.mjs +0 -170
  45. package/utils/matrix.d.ts +0 -82
@@ -4,13 +4,100 @@ import rough from 'roughjs/bin/rough';
4
4
  import { Subject, fromEvent } from 'rxjs';
5
5
  import { takeUntil, filter } from 'rxjs/operators';
6
6
  import produce, { createDraft, finishDraft, isDraft } from 'immer';
7
- import { isKeyHotkey, isHotkey } from 'is-hotkey';
7
+ import isHotkey$1, { isKeyHotkey, isHotkey } from 'is-hotkey';
8
8
  import * as i1 from '@angular/common';
9
9
  import { BrowserModule } from '@angular/platform-browser';
10
10
 
11
- const CLIP_BOARD_FORMAT_KEY = 'x-plait-fragment';
12
- const SCROLL_BAR_WIDTH = 20;
13
- const MAX_RADIUS = 16;
11
+ // record richtext type status
12
+ const FLUSHING = new WeakMap();
13
+ const IS_TEXT_EDITABLE = new WeakMap();
14
+ const BOARD_TO_ON_CHANGE = new WeakMap();
15
+ const BOARD_TO_COMPONENT = new WeakMap();
16
+ const BOARD_TO_ROUGH_SVG = new WeakMap();
17
+ const BOARD_TO_HOST = new WeakMap();
18
+ const BOARD_TO_ELEMENT_HOST = new WeakMap();
19
+ const BOARD_TO_SELECTED_ELEMENT = new WeakMap();
20
+ const BOARD_TO_MOVING_POINT = new WeakMap();
21
+ const BOARD_TO_IS_SELECTION_MOVING = new WeakMap();
22
+ // save no standard selected elements
23
+ const BOARD_TO_TEMPORARY_ELEMENTS = new WeakMap();
24
+ const BOARD_TO_MOVING_ELEMENT = new WeakMap();
25
+
26
+ function depthFirstRecursion(node, callback) {
27
+ var _a;
28
+ (_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach(child => {
29
+ depthFirstRecursion(child, callback);
30
+ });
31
+ callback(node);
32
+ }
33
+
34
+ function getRectangleByElements(board, elements, recursion) {
35
+ const boundaryBox = {
36
+ left: Number.MAX_VALUE,
37
+ top: Number.MAX_VALUE,
38
+ right: Number.NEGATIVE_INFINITY,
39
+ bottom: Number.NEGATIVE_INFINITY
40
+ };
41
+ const calcRectangleClient = (node) => {
42
+ const nodeRectangle = board.getRectangle(node);
43
+ if (nodeRectangle) {
44
+ boundaryBox.left = Math.min(boundaryBox.left, nodeRectangle.x);
45
+ boundaryBox.top = Math.min(boundaryBox.top, nodeRectangle.y);
46
+ boundaryBox.right = Math.max(boundaryBox.right, nodeRectangle.x + nodeRectangle.width);
47
+ boundaryBox.bottom = Math.max(boundaryBox.bottom, nodeRectangle.y + nodeRectangle.height);
48
+ }
49
+ };
50
+ elements.forEach(element => {
51
+ if (recursion) {
52
+ depthFirstRecursion(element, node => calcRectangleClient(node));
53
+ }
54
+ else {
55
+ calcRectangleClient(element);
56
+ }
57
+ });
58
+ return {
59
+ x: boundaryBox.left,
60
+ y: boundaryBox.top,
61
+ width: boundaryBox.right - boundaryBox.left,
62
+ height: boundaryBox.bottom - boundaryBox.top
63
+ };
64
+ }
65
+ function getBoardRectangle(board) {
66
+ return getRectangleByElements(board, board.children, true);
67
+ }
68
+
69
+ const PlaitBoard = {
70
+ getHost(board) {
71
+ return BOARD_TO_HOST.get(board);
72
+ },
73
+ getElementHost(board) {
74
+ return BOARD_TO_ELEMENT_HOST.get(board);
75
+ },
76
+ getRoughSVG(board) {
77
+ return BOARD_TO_ROUGH_SVG.get(board);
78
+ },
79
+ getComponent(board) {
80
+ return BOARD_TO_COMPONENT.get(board);
81
+ },
82
+ getBoardNativeElement(board) {
83
+ return PlaitBoard.getComponent(board).nativeElement;
84
+ },
85
+ getRectangle(board) {
86
+ return getRectangleByElements(board, board.children, true);
87
+ },
88
+ getViewportContainer(board) {
89
+ return PlaitBoard.getHost(board).parentElement;
90
+ },
91
+ isFocus(board) {
92
+ return !!board.selection;
93
+ },
94
+ isReadonly(board) {
95
+ return board.options.readonly;
96
+ },
97
+ hasBeenTextEditing(board) {
98
+ return !!IS_TEXT_EDITABLE.get(board);
99
+ }
100
+ };
14
101
 
15
102
  var PlaitPointerType;
16
103
  (function (PlaitPointerType) {
@@ -21,6 +108,19 @@ var PlaitPointerType;
21
108
  function isNullOrUndefined(value) {
22
109
  return value === null || value === undefined;
23
110
  }
111
+ /**
112
+ * 规范 point
113
+ * @param point
114
+ * @returns point
115
+ */
116
+ function normalizePoint(point) {
117
+ return Array.isArray(point)
118
+ ? {
119
+ x: point[0],
120
+ y: point[1]
121
+ }
122
+ : point;
123
+ }
24
124
 
25
125
  const Viewport = {
26
126
  isViewport: (value) => {
@@ -356,19 +456,6 @@ const NodeTransforms = {
356
456
  moveNode
357
457
  };
358
458
 
359
- // record richtext type status
360
- const FLUSHING = new WeakMap();
361
- const IS_TEXT_EDITABLE = new WeakMap();
362
- const BOARD_TO_ON_CHANGE = new WeakMap();
363
- const BOARD_TO_COMPONENT = new WeakMap();
364
- const BOARD_TO_ROUGH_SVG = new WeakMap();
365
- const BOARD_TO_HOST = new WeakMap();
366
- const BOARD_TO_ELEMENT_HOST = new WeakMap();
367
- const BOARD_TO_SELECTED_ELEMENT = new WeakMap();
368
- const BOARD_TO_MOVING_POINT = new WeakMap();
369
- // save no standard selected elements
370
- const BOARD_TO_TEMPORARY_ELEMENTS = new WeakMap();
371
-
372
459
  function setSelection(board, selection) {
373
460
  const operation = { type: 'set_selection', properties: board.selection, newProperties: selection };
374
461
  board.apply(operation);
@@ -384,80 +471,61 @@ function setSelectionWithTemporaryElements(board, elements) {
384
471
  });
385
472
  }
386
473
 
387
- function setViewport(board, viewport) {
474
+ function setViewport$1(board, viewport) {
388
475
  const operation = { type: 'set_viewport', properties: board.viewport, newProperties: viewport };
389
476
  board.apply(operation);
390
477
  }
391
478
  const ViewportTransforms = {
392
- setViewport
479
+ setViewport: setViewport$1
393
480
  };
394
481
 
395
- function depthFirstRecursion(node, callback) {
396
- var _a;
397
- (_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach(child => {
398
- depthFirstRecursion(child, callback);
399
- });
400
- callback(node);
482
+ // https://stackoverflow.com/a/6853926/232122
483
+ function distanceBetweenPointAndSegment(x, y, x1, y1, x2, y2) {
484
+ const A = x - x1;
485
+ const B = y - y1;
486
+ const C = x2 - x1;
487
+ const D = y2 - y1;
488
+ const dot = A * C + B * D;
489
+ const lenSquare = C * C + D * D;
490
+ let param = -1;
491
+ if (lenSquare !== 0) {
492
+ // in case of 0 length line
493
+ param = dot / lenSquare;
494
+ }
495
+ let xx, yy;
496
+ if (param < 0) {
497
+ xx = x1;
498
+ yy = y1;
499
+ }
500
+ else if (param > 1) {
501
+ xx = x2;
502
+ yy = y2;
503
+ }
504
+ else {
505
+ xx = x1 + param * C;
506
+ yy = y1 + param * D;
507
+ }
508
+ const dx = x - xx;
509
+ const dy = y - yy;
510
+ return Math.hypot(dx, dy);
401
511
  }
402
-
403
- function getRectangleByElements(board, elements, recursion) {
404
- const boundaryBox = {
405
- left: Number.MAX_VALUE,
406
- top: Number.MAX_VALUE,
407
- right: Number.MIN_VALUE,
408
- bottom: Number.MIN_VALUE
409
- };
410
- const calcRectangleClient = (node) => {
411
- const nodeRectangle = board.getRectangle(node);
412
- if (nodeRectangle) {
413
- boundaryBox.left = Math.min(boundaryBox.left, nodeRectangle.x);
414
- boundaryBox.top = Math.min(boundaryBox.top, nodeRectangle.y);
415
- boundaryBox.right = Math.max(boundaryBox.right, nodeRectangle.x + nodeRectangle.width);
416
- boundaryBox.bottom = Math.max(boundaryBox.bottom, nodeRectangle.y + nodeRectangle.height);
417
- }
418
- };
419
- elements.forEach(element => {
420
- if (recursion) {
421
- depthFirstRecursion(element, node => calcRectangleClient(node));
422
- }
423
- else {
424
- calcRectangleClient(element);
425
- }
426
- });
427
- return {
428
- x: boundaryBox.left,
429
- y: boundaryBox.top,
430
- width: boundaryBox.right - boundaryBox.left,
431
- height: boundaryBox.bottom - boundaryBox.top
432
- };
512
+ function rotate(x1, y1, x2, y2, angle) {
513
+ // 𝑎′𝑥=(𝑎𝑥−𝑐𝑥)cos𝜃−(𝑎𝑦−𝑐𝑦)sin𝜃+𝑐𝑥
514
+ // 𝑎′𝑦=(𝑎𝑥−𝑐𝑥)sin𝜃+(𝑎𝑦−𝑐𝑦)cos𝜃+𝑐𝑦.
515
+ // https://math.stackexchange.com/questions/2204520/how-do-i-rotate-a-line-segment-in-a-specific-point-on-the-line
516
+ return [(x1 - x2) * Math.cos(angle) - (y1 - y2) * Math.sin(angle) + x2, (x1 - x2) * Math.sin(angle) + (y1 - y2) * Math.cos(angle) + y2];
433
517
  }
434
- function getBoardRectangle(board) {
435
- return getRectangleByElements(board, board.children, true);
518
+ function distanceBetweenPointAndPoint(x1, y1, x2, y2) {
519
+ const dx = x1 - x2;
520
+ const dy = y1 - y2;
521
+ return Math.hypot(dx, dy);
522
+ }
523
+ // https://stackoverflow.com/questions/5254838/calculating-distance-between-a-point-and-a-rectangular-box-nearest-point
524
+ function distanceBetweenPointAndRectangle(x, y, rect) {
525
+ var dx = Math.max(rect.x - x, 0, x - (rect.x + rect.width));
526
+ var dy = Math.max(rect.y - y, 0, y - (rect.y + rect.height));
527
+ return Math.sqrt(dx * dx + dy * dy);
436
528
  }
437
-
438
- const PlaitBoard = {
439
- getHost(board) {
440
- return BOARD_TO_HOST.get(board);
441
- },
442
- getElementHost(board) {
443
- return BOARD_TO_ELEMENT_HOST.get(board);
444
- },
445
- getRoughSVG(board) {
446
- return BOARD_TO_ROUGH_SVG.get(board);
447
- },
448
- getComponent(board) {
449
- return BOARD_TO_COMPONENT.get(board);
450
- },
451
- getBoardNativeElement(board) {
452
- return PlaitBoard.getComponent(board).nativeElement;
453
- },
454
- getRectangle(board) {
455
- return getRectangleByElements(board, board.children, true);
456
- },
457
- getViewportContainer(board) {
458
- return PlaitBoard.getHost(board).parentElement;
459
- }
460
- };
461
529
 
462
530
  function transformPoints(board, points) {
463
531
  const newPoints = points.map(point => {
@@ -473,9 +541,11 @@ function transformPoint(board, point) {
473
541
  const newPoint = [x, y];
474
542
  return newPoint;
475
543
  }
476
- function isNoSelectionElement(e) {
477
- var _a;
478
- return (_a = e.target) === null || _a === void 0 ? void 0 : _a.closest('.plait-board-attached');
544
+ function isInPlaitBoard(board, x, y) {
545
+ const plaitBoardElement = PlaitBoard.getBoardNativeElement(board);
546
+ const plaitBoardRect = plaitBoardElement.getBoundingClientRect();
547
+ const distances = distanceBetweenPointAndRectangle(x, y, plaitBoardRect);
548
+ return distances === 0;
479
549
  }
480
550
 
481
551
  const NS = 'http://www.w3.org/2000/svg';
@@ -796,222 +866,6 @@ function idCreator(length = 5) {
796
866
  return key;
797
867
  }
798
868
 
799
- // https://stackoverflow.com/a/6853926/232122
800
- function distanceBetweenPointAndSegment(x, y, x1, y1, x2, y2) {
801
- const A = x - x1;
802
- const B = y - y1;
803
- const C = x2 - x1;
804
- const D = y2 - y1;
805
- const dot = A * C + B * D;
806
- const lenSquare = C * C + D * D;
807
- let param = -1;
808
- if (lenSquare !== 0) {
809
- // in case of 0 length line
810
- param = dot / lenSquare;
811
- }
812
- let xx, yy;
813
- if (param < 0) {
814
- xx = x1;
815
- yy = y1;
816
- }
817
- else if (param > 1) {
818
- xx = x2;
819
- yy = y2;
820
- }
821
- else {
822
- xx = x1 + param * C;
823
- yy = y1 + param * D;
824
- }
825
- const dx = x - xx;
826
- const dy = y - yy;
827
- return Math.hypot(dx, dy);
828
- }
829
- function rotate(x1, y1, x2, y2, angle) {
830
- // 𝑎′𝑥=(𝑎𝑥−𝑐𝑥)cos𝜃−(𝑎𝑦−𝑐𝑦)sin𝜃+𝑐𝑥
831
- // 𝑎′𝑦=(𝑎𝑥−𝑐𝑥)sin𝜃+(𝑎𝑦−𝑐𝑦)cos𝜃+𝑐𝑦.
832
- // https://math.stackexchange.com/questions/2204520/how-do-i-rotate-a-line-segment-in-a-specific-point-on-the-line
833
- return [(x1 - x2) * Math.cos(angle) - (y1 - y2) * Math.sin(angle) + x2, (x1 - x2) * Math.sin(angle) + (y1 - y2) * Math.cos(angle) + y2];
834
- }
835
- function distanceBetweenPointAndPoint(x1, y1, x2, y2) {
836
- const dx = x1 - x2;
837
- const dy = y1 - y2;
838
- return Math.hypot(dx, dy);
839
- }
840
- // https://stackoverflow.com/questions/5254838/calculating-distance-between-a-point-and-a-rectangular-box-nearest-point
841
- function distanceBetweenPointAndRectangle(x, y, rect) {
842
- var dx = Math.max(rect.x - x, 0, x - (rect.x + rect.width));
843
- var dy = Math.max(rect.y - y, 0, y - (rect.y + rect.height));
844
- return Math.sqrt(dx * dx + dy * dy);
845
- }
846
-
847
- /**
848
- * 逆矩阵
849
- * [a c e]
850
- * [b d f]
851
- * [0 0 1]
852
- * @param newMatrix 输出返回矩阵
853
- * @param matrix 新矩阵
854
- * @returns 逆矩阵
855
- */
856
- function invertMatrix(newMatrix, matrix) {
857
- const [n, r, a, i, o, c, l, s, u] = matrix;
858
- const determinant = u * o - c * s;
859
- const h = -u * i + c * l;
860
- const f = s * i - o * l;
861
- const product = n * determinant + r * h + a * f;
862
- if (!product) {
863
- return null;
864
- }
865
- const reciprocal = 1 / product;
866
- newMatrix[0] = determinant * reciprocal;
867
- newMatrix[1] = (-u * r + a * s) * reciprocal;
868
- newMatrix[2] = (c * r - a * o) * reciprocal;
869
- newMatrix[3] = h * reciprocal;
870
- newMatrix[4] = (u * n - a * l) * reciprocal;
871
- newMatrix[5] = (-c * n + a * i) * reciprocal;
872
- newMatrix[6] = f * reciprocal;
873
- newMatrix[7] = (-s * n + r * l) * reciprocal;
874
- newMatrix[8] = (o * n - r * i) * reciprocal;
875
- return newMatrix;
876
- }
877
- /**
878
- * 将视图坐标与反转矩阵相乘,以得到原始坐标
879
- * 使用给定的矩阵进行转换
880
- * 矩阵与向量乘法,3 维向量与3x3矩阵的乘积
881
- * [m11 m12 m13][v1]
882
- * [m21 m22 m23][v2]
883
- * [m31 m32 m33][v3]
884
- * @param out 输出结果向量
885
- * @param t 要转换的向量
886
- * @param n 矩阵转换
887
- * @returns [v1 * m11 + v2 * m12 + v3 * m13, v1 * m21 + v2 * m22 + v3 * m23, v1 * m31 + v2 * m32 + v3 * m33];
888
- */
889
- function transformMat3(out, vector, matrix) {
890
- out = [
891
- vector[0] * matrix[0] + vector[1] * matrix[3] + vector[2] * matrix[6],
892
- vector[0] * matrix[1] + vector[1] * matrix[4] + vector[2] * matrix[7],
893
- vector[0] * matrix[2] + vector[1] * matrix[5] + vector[2] * matrix[8]
894
- ];
895
- return out;
896
- }
897
- /**
898
- * 规范 point
899
- * @param point
900
- * @returns point
901
- */
902
- function normalizePoint(point) {
903
- return Array.isArray(point)
904
- ? {
905
- x: point[0],
906
- y: point[1]
907
- }
908
- : point;
909
- }
910
- /**
911
- * 将一个点坐标反转回它的原始坐标
912
- * @param point 表示要反转的点的视图坐标,它是一个长度为 2 的数组,存储点的 x 和 y 坐标
913
- * @param matrix 表示视图矩阵,是在视图中对图形进行缩放和平移时使用的矩阵
914
- * @returns 最终结果是一个长度为 3 的数组,存储点的 x,y 和 w 坐标(w 坐标是点的齐次坐标)
915
- */
916
- function invertViewportCoordinates(point, matrix) {
917
- const { x, y } = normalizePoint(point);
918
- const invertedMatrix = invertMatrix([], matrix);
919
- return transformMat3([], [x, y, 1], invertedMatrix);
920
- }
921
- function convertToViewportCoordinates(point, matrix) {
922
- const { x, y } = normalizePoint(point);
923
- return transformMat3([], [x, y, 1], matrix);
924
- }
925
- /**
926
- * 获取 contentContainer 的 clientBox
927
- * @param board
928
- * @returns
929
- */
930
- function getViewportContainerBox(board) {
931
- const { hideScrollbar } = board.options;
932
- const scrollBarWidth = hideScrollbar ? SCROLL_BAR_WIDTH : 0;
933
- const container = PlaitBoard.getViewportContainer(board);
934
- const containerRect = container.getBoundingClientRect();
935
- const x = containerRect.x || containerRect.left;
936
- const y = containerRect.y || containerRect.top;
937
- const width = containerRect.width - scrollBarWidth;
938
- const height = containerRect.height - scrollBarWidth;
939
- return {
940
- minX: x,
941
- minY: y,
942
- maxX: x + width,
943
- maxY: y + height,
944
- x,
945
- y,
946
- width,
947
- height
948
- };
949
- }
950
- /**
951
- * 获取 board.plait-board 的 clientBox
952
- * @param board
953
- * @returns
954
- */
955
- function getBoardClientBox(board) {
956
- const { hideScrollbar } = board.options;
957
- const scrollBarWidth = hideScrollbar ? SCROLL_BAR_WIDTH : 0;
958
- const viewportRect = PlaitBoard.getViewportContainer(board).getBoundingClientRect();
959
- return {
960
- width: viewportRect.width + scrollBarWidth,
961
- height: viewportRect.height + scrollBarWidth
962
- };
963
- }
964
- /**
965
- * 获取 rootGroup 相对于当前 svg 空间的最小矩阵坐标
966
- */
967
- function getRootGroupBBox(board, zoom) {
968
- const elementHost = PlaitBoard.getElementHost(board);
969
- const rootGroupBox = elementHost.getBBox();
970
- const viewportContainerBox = getViewportContainerBox(board);
971
- const containerWidth = viewportContainerBox.width / zoom;
972
- const containerHeight = viewportContainerBox.height / zoom;
973
- let left;
974
- let right;
975
- let top;
976
- let bottom;
977
- if (rootGroupBox.width < containerWidth) {
978
- const offsetX = rootGroupBox.x + rootGroupBox.width / 2;
979
- const containerX = containerWidth / 2;
980
- left = offsetX - containerX;
981
- right = offsetX + containerX;
982
- }
983
- else {
984
- left = rootGroupBox.x;
985
- right = rootGroupBox.x + rootGroupBox.width;
986
- }
987
- if (rootGroupBox.height < containerHeight) {
988
- const offsetY = rootGroupBox.y + rootGroupBox.height / 2;
989
- const containerY = containerHeight / 2;
990
- top = offsetY - containerY;
991
- bottom = offsetY + containerY;
992
- }
993
- else {
994
- top = rootGroupBox.y;
995
- bottom = rootGroupBox.y + rootGroupBox.height;
996
- }
997
- return {
998
- left,
999
- right,
1000
- top,
1001
- bottom
1002
- };
1003
- }
1004
- /**
1005
- * 验证缩放比是否符合限制,如果超出限制,则返回合适的缩放比
1006
- * @param zoom 缩放比
1007
- * @param minZoom 最小缩放比
1008
- * @param maxZoom 最大缩放比
1009
- * @returns 正确的缩放比
1010
- */
1011
- function clampZoomLevel(zoom, minZoom = 0.2, maxZoom = 4) {
1012
- return zoom < minZoom ? minZoom : zoom > maxZoom ? maxZoom : zoom;
1013
- }
1014
-
1015
869
  const calcElementIntersectionSelection = (board) => {
1016
870
  const selectedElements = [];
1017
871
  depthFirstRecursion(board, node => {
@@ -1025,6 +879,19 @@ const calcElementIntersectionSelection = (board) => {
1025
879
  });
1026
880
  return selectedElements;
1027
881
  };
882
+ const isIntersectionElements = (board, elements, ranges) => {
883
+ let isIntersectionElements = false;
884
+ if (elements.length) {
885
+ elements.map(item => {
886
+ if (!isIntersectionElements) {
887
+ isIntersectionElements = ranges.some(range => {
888
+ return board.isIntersectionSelection(item, range);
889
+ });
890
+ }
891
+ });
892
+ }
893
+ return isIntersectionElements;
894
+ };
1028
895
  const cacheSelectedElements = (board, selectedElements) => {
1029
896
  BOARD_TO_SELECTED_ELEMENT.set(board, selectedElements);
1030
897
  };
@@ -1045,6 +912,10 @@ const isSelectedElement = (board, element) => {
1045
912
  return !!selectedElements.find(value => value === element);
1046
913
  };
1047
914
 
915
+ const CLIP_BOARD_FORMAT_KEY = 'x-plait-fragment';
916
+ const SCROLL_BAR_WIDTH = 20;
917
+ const MAX_RADIUS = 16;
918
+
1048
919
  /**
1049
920
  * drawRoundRectangle
1050
921
  * @param rs RoughSVG
@@ -1097,6 +968,196 @@ function drawArrow(rs, start, end, options, maxHypotenuseLength = 10, degree = 4
1097
968
  return [arrowLineLeft, arrowLineRight];
1098
969
  }
1099
970
 
971
+ function getViewportContainerRect(board) {
972
+ const { hideScrollbar } = board.options;
973
+ const scrollBarWidth = hideScrollbar ? SCROLL_BAR_WIDTH : 0;
974
+ const viewportRect = PlaitBoard.getBoardNativeElement(board).getBoundingClientRect();
975
+ return {
976
+ width: viewportRect.width + scrollBarWidth,
977
+ height: viewportRect.height + scrollBarWidth
978
+ };
979
+ }
980
+ function getElementHostBBox(board, zoom) {
981
+ const childrenRect = getRectangleByElements(board, board.children, true);
982
+ const viewportContainerRect = getViewportContainerRect(board);
983
+ const containerWidth = viewportContainerRect.width / zoom;
984
+ const containerHeight = viewportContainerRect.height / zoom;
985
+ let left;
986
+ let right;
987
+ let top;
988
+ let bottom;
989
+ if (childrenRect.width < containerWidth) {
990
+ const centerX = Math.ceil(childrenRect.x + childrenRect.width / 2);
991
+ const halfContainerWidth = Math.ceil(containerWidth / 2);
992
+ left = centerX - halfContainerWidth;
993
+ right = centerX + halfContainerWidth;
994
+ }
995
+ else {
996
+ left = childrenRect.x;
997
+ right = childrenRect.x + childrenRect.width;
998
+ }
999
+ if (childrenRect.height < containerHeight) {
1000
+ const centerY = Math.ceil(childrenRect.y + childrenRect.height / 2);
1001
+ const halfContainerHeight = Math.ceil(containerHeight / 2);
1002
+ top = centerY - halfContainerHeight;
1003
+ bottom = centerY + halfContainerHeight;
1004
+ }
1005
+ else {
1006
+ top = childrenRect.y;
1007
+ bottom = childrenRect.y + childrenRect.height;
1008
+ }
1009
+ return {
1010
+ left,
1011
+ right,
1012
+ top,
1013
+ bottom
1014
+ };
1015
+ }
1016
+ /**
1017
+ * 验证缩放比是否符合限制,如果超出限制,则返回合适的缩放比
1018
+ * @param zoom 缩放比
1019
+ * @param minZoom 最小缩放比
1020
+ * @param maxZoom 最大缩放比
1021
+ * @returns 正确的缩放比
1022
+ */
1023
+ function clampZoomLevel(zoom, minZoom = 0.2, maxZoom = 4) {
1024
+ return zoom < minZoom ? minZoom : zoom > maxZoom ? maxZoom : zoom;
1025
+ }
1026
+ function getViewBox(board, zoom) {
1027
+ const { hideScrollbar } = board.options;
1028
+ const scrollBarWidth = hideScrollbar ? SCROLL_BAR_WIDTH : 0;
1029
+ const viewportContainerRect = getViewportContainerRect(board);
1030
+ const elementHostBBox = getElementHostBBox(board, zoom);
1031
+ const horizontalPadding = viewportContainerRect.width / 2;
1032
+ const verticalPadding = viewportContainerRect.height / 2;
1033
+ const viewportWidth = (elementHostBBox.right - elementHostBBox.left) * zoom + 2 * horizontalPadding + scrollBarWidth;
1034
+ const viewportHeight = (elementHostBBox.bottom - elementHostBBox.top) * zoom + 2 * verticalPadding + scrollBarWidth;
1035
+ const viewBox = [
1036
+ elementHostBBox.left - horizontalPadding / zoom,
1037
+ elementHostBBox.top - verticalPadding / zoom,
1038
+ viewportWidth / zoom,
1039
+ viewportHeight / zoom
1040
+ ];
1041
+ return viewBox;
1042
+ }
1043
+ function setSVGViewBox(board, viewBox) {
1044
+ const zoom = board.viewport.zoom;
1045
+ const hostElement = PlaitBoard.getHost(board);
1046
+ hostElement.style.display = 'block';
1047
+ hostElement.style.width = `${viewBox[2] * zoom}px`;
1048
+ hostElement.style.height = `${viewBox[3] * zoom}px`;
1049
+ if (viewBox && viewBox[2] > 0 && viewBox[3] > 0) {
1050
+ hostElement.setAttribute('viewBox', viewBox.join(' '));
1051
+ }
1052
+ }
1053
+ function updateViewportContainerOffset(board, origination) {
1054
+ origination = origination !== null && origination !== void 0 ? origination : board.viewport.origination;
1055
+ if (!origination)
1056
+ return;
1057
+ const { zoom } = board.viewport;
1058
+ const viewBox = getViewBox(board, zoom);
1059
+ const scrollLeft = (origination[0] - viewBox[0]) * zoom;
1060
+ const scrollTop = (origination[1] - viewBox[1]) * zoom;
1061
+ setViewportContainerScroll(board, scrollLeft, scrollTop);
1062
+ }
1063
+ function setViewportContainerScroll(board, left, top) {
1064
+ const viewportContainer = PlaitBoard.getViewportContainer(board);
1065
+ viewportContainer.scrollLeft = Math.floor(left);
1066
+ viewportContainer.scrollTop = Math.floor(top);
1067
+ }
1068
+ function initializeViewport(board) {
1069
+ const zoom = board.viewport.zoom;
1070
+ const viewBox = getViewBox(board, zoom);
1071
+ setSVGViewBox(board, viewBox);
1072
+ }
1073
+ function initializeViewportContainerOffset(board) {
1074
+ var _a;
1075
+ if (!((_a = board.viewport) === null || _a === void 0 ? void 0 : _a.origination)) {
1076
+ const zoom = board.viewport.zoom;
1077
+ const viewportContainerBox = PlaitBoard.getBoardNativeElement(board).getBoundingClientRect();
1078
+ const viewBox = getViewBox(board, zoom);
1079
+ const centerX = viewBox[0] + viewBox[2] / 2;
1080
+ const centerY = viewBox[1] + viewBox[3] / 2;
1081
+ const origination = [centerX - viewportContainerBox.width / 2 / zoom, centerY - viewportContainerBox.height / 2 / zoom];
1082
+ updateViewportContainerOffset(board, origination);
1083
+ return;
1084
+ }
1085
+ updateViewportContainerOffset(board);
1086
+ }
1087
+ function setViewport(board, origination, zoom) {
1088
+ zoom = zoom !== null && zoom !== void 0 ? zoom : board.viewport.zoom;
1089
+ Transforms.setViewport(board, Object.assign(Object.assign({}, board.viewport), { zoom,
1090
+ origination }));
1091
+ }
1092
+ function changeZoom(board, newZoom, isCenter = true) {
1093
+ newZoom = clampZoomLevel(newZoom);
1094
+ const mousePoint = BOARD_TO_MOVING_POINT.get(board);
1095
+ const nativeElement = PlaitBoard.getBoardNativeElement(board);
1096
+ const rect = nativeElement.getBoundingClientRect();
1097
+ const viewportContainerRect = getViewportContainerRect(board);
1098
+ let focusPoint = [viewportContainerRect.width / 2, viewportContainerRect.height / 2];
1099
+ if (!isCenter && mousePoint && distanceBetweenPointAndRectangle(mousePoint[0], mousePoint[1], rect) === 0) {
1100
+ focusPoint = toPoint(mousePoint[0], mousePoint[1], nativeElement);
1101
+ }
1102
+ const { origination, zoom } = board.viewport;
1103
+ const centerX = origination[0] + focusPoint[0] / zoom;
1104
+ const centerY = origination[1] + focusPoint[1] / zoom;
1105
+ const viewBox = getViewBox(board, newZoom);
1106
+ const newOrigination = [centerX - focusPoint[0] / newZoom, centerY - focusPoint[1] / newZoom];
1107
+ setSVGViewBox(board, viewBox);
1108
+ setViewport(board, newOrigination, newZoom);
1109
+ }
1110
+ function fitViewport(board) {
1111
+ const viewportContainerRect = getViewportContainerRect(board);
1112
+ const rootGroupBox = getRectangleByElements(board, board.children, true);
1113
+ const zoom = board.viewport.zoom;
1114
+ const autoFitPadding = 8;
1115
+ const viewportWidth = viewportContainerRect.width - 2 * autoFitPadding;
1116
+ const viewportHeight = viewportContainerRect.height - 2 * autoFitPadding;
1117
+ let newZoom = zoom;
1118
+ if (viewportWidth < rootGroupBox.width || viewportHeight < rootGroupBox.height) {
1119
+ newZoom = Math.min(viewportWidth / rootGroupBox.width, viewportHeight / rootGroupBox.height);
1120
+ }
1121
+ else {
1122
+ newZoom = 1;
1123
+ }
1124
+ const viewBox = getViewBox(board, newZoom);
1125
+ const centerX = viewBox[0] + viewBox[2] / 2;
1126
+ const centerY = viewBox[1] + viewBox[3] / 2;
1127
+ const newOrigination = [centerX - viewportContainerRect.width / 2 / newZoom, centerY - viewportContainerRect.height / 2 / newZoom];
1128
+ setViewport(board, newOrigination, newZoom);
1129
+ }
1130
+ function scrollToRectangle(board, client) { }
1131
+
1132
+ let timerId = null;
1133
+ const throttleRAF = (fn) => {
1134
+ const scheduleFunc = () => {
1135
+ timerId = requestAnimationFrame(() => {
1136
+ timerId = null;
1137
+ fn();
1138
+ });
1139
+ };
1140
+ if (timerId !== null) {
1141
+ cancelAnimationFrame(timerId);
1142
+ timerId = null;
1143
+ }
1144
+ scheduleFunc();
1145
+ };
1146
+
1147
+ const getMovingElements = (board) => {
1148
+ return BOARD_TO_MOVING_ELEMENT.get(board) || [];
1149
+ };
1150
+ const addMovingElements = (board, elements) => {
1151
+ const movingElements = getMovingElements(board);
1152
+ cacheMovingElements(board, [...movingElements, ...elements]);
1153
+ };
1154
+ const removeMovingElements = (board) => {
1155
+ BOARD_TO_MOVING_ELEMENT.delete(board);
1156
+ };
1157
+ const cacheMovingElements = (board, elements) => {
1158
+ BOARD_TO_MOVING_ELEMENT.set(board, elements);
1159
+ };
1160
+
1100
1161
  const updatePointerType = (board, pointer) => {
1101
1162
  board.pointer = pointer;
1102
1163
  const boardComponent = BOARD_TO_COMPONENT.get(board);
@@ -1157,6 +1218,7 @@ function createBoard(children, options) {
1157
1218
  destroyElement: (context) => { },
1158
1219
  isWithinSelection: element => false,
1159
1220
  isIntersectionSelection: element => false,
1221
+ isMovable: element => false,
1160
1222
  getRectangle: element => null
1161
1223
  };
1162
1224
  return board;
@@ -1282,11 +1344,13 @@ function withHandPointer(board) {
1282
1344
  };
1283
1345
  board.mousemove = (event) => {
1284
1346
  if (board.pointer === PlaitPointerType.hand && board.selection && isMoving) {
1285
- const boardComponent = PlaitBoard.getComponent(board);
1286
- const left = event.x - plaitBoardMove.x;
1287
- const top = event.y - plaitBoardMove.y;
1288
- const { scrollLeft, scrollTop } = boardComponent.viewportState;
1289
- boardComponent.setScroll(scrollLeft - left, scrollTop - top);
1347
+ const viewportContainer = PlaitBoard.getViewportContainer(board);
1348
+ const left = viewportContainer.scrollLeft + (event.x - plaitBoardMove.x);
1349
+ const top = viewportContainer.scrollTop + (event.y - plaitBoardMove.y);
1350
+ const zoom = board.viewport.zoom;
1351
+ const viewBox = getViewBox(board, zoom);
1352
+ const origination = [left / zoom + viewBox[0], top / zoom + viewBox[1]];
1353
+ setViewport(board, origination);
1290
1354
  plaitBoardMove.x = event.x;
1291
1355
  plaitBoardMove.y = event.y;
1292
1356
  }
@@ -1319,6 +1383,8 @@ function withHandPointer(board) {
1319
1383
  return board;
1320
1384
  }
1321
1385
 
1386
+ const ATTACHED_ELEMENT_CLASS_NAME = 'plait-board-attached';
1387
+
1322
1388
  function withSelection(board) {
1323
1389
  const { mousedown, globalMousemove, globalMouseup, onChange } = board;
1324
1390
  let start = null;
@@ -1326,12 +1392,22 @@ function withSelection(board) {
1326
1392
  let selectionMovingG;
1327
1393
  let selectionOuterG;
1328
1394
  board.mousedown = (event) => {
1329
- selectionOuterG === null || selectionOuterG === void 0 ? void 0 : selectionOuterG.remove();
1330
1395
  if (event.button === 0) {
1331
1396
  start = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
1332
1397
  }
1333
1398
  if (start) {
1334
- Transforms.setSelection(board, { ranges: [{ anchor: start, focus: start }] });
1399
+ const ranges = [{ anchor: start, focus: start }];
1400
+ const selectedElements = getSelectedElements(board);
1401
+ const intersectionSelectedElement = isIntersectionElements(board, selectedElements, ranges);
1402
+ if (intersectionSelectedElement) {
1403
+ start = null;
1404
+ }
1405
+ else {
1406
+ Transforms.setSelection(board, { ranges: ranges });
1407
+ if (calcElementIntersectionSelection(board).length) {
1408
+ start = null;
1409
+ }
1410
+ }
1335
1411
  }
1336
1412
  mousedown(event);
1337
1413
  };
@@ -1339,13 +1415,11 @@ function withSelection(board) {
1339
1415
  if (start) {
1340
1416
  const movedTarget = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
1341
1417
  const { x, y, width, height } = RectangleClient.toRectangleClient([start, movedTarget]);
1418
+ selectionMovingG === null || selectionMovingG === void 0 ? void 0 : selectionMovingG.remove();
1342
1419
  if (Math.hypot(width, height) > 5) {
1343
1420
  end = movedTarget;
1344
- if (end) {
1345
- Transforms.setSelection(board, { ranges: [{ anchor: start, focus: end }] });
1346
- }
1347
- PlaitBoard.getBoardNativeElement(board).classList.add('selection-moving');
1348
- selectionMovingG === null || selectionMovingG === void 0 ? void 0 : selectionMovingG.remove();
1421
+ Transforms.setSelection(board, { ranges: [{ anchor: start, focus: end }] });
1422
+ setSelectionMoving(board);
1349
1423
  const rough = PlaitBoard.getRoughSVG(board);
1350
1424
  selectionMovingG = rough.rectangle(x, y, width, height, {
1351
1425
  stroke: SELECTION_BORDER_COLOR,
@@ -1360,8 +1434,18 @@ function withSelection(board) {
1360
1434
  };
1361
1435
  board.globalMouseup = (event) => {
1362
1436
  if (start && end) {
1363
- PlaitBoard.getBoardNativeElement(board).classList.remove('selection-moving');
1364
1437
  selectionMovingG === null || selectionMovingG === void 0 ? void 0 : selectionMovingG.remove();
1438
+ clearSelectionMoving(board);
1439
+ Transforms.setSelection(board, { ranges: [{ anchor: start, focus: end }] });
1440
+ }
1441
+ if (PlaitBoard.isFocus(board)) {
1442
+ const isInBoard = event.target instanceof Node && PlaitBoard.getBoardNativeElement(board).contains(event.target);
1443
+ const isAttachedElement = event.target instanceof HTMLElement && event.target.closest(`.${ATTACHED_ELEMENT_CLASS_NAME}`);
1444
+ // Clear selection when mouse board outside area
1445
+ // The framework needs to determine whether the board is focused through selection
1446
+ if (!isInBoard && !start && !isAttachedElement) {
1447
+ Transforms.setSelection(board, null);
1448
+ }
1365
1449
  }
1366
1450
  start = null;
1367
1451
  end = null;
@@ -1370,6 +1454,7 @@ function withSelection(board) {
1370
1454
  board.onChange = () => {
1371
1455
  // calc selected elements entry
1372
1456
  try {
1457
+ selectionOuterG === null || selectionOuterG === void 0 ? void 0 : selectionOuterG.remove();
1373
1458
  if (board.operations.find(value => value.type === 'set_selection')) {
1374
1459
  const temporaryElements = getTemporaryElements(board);
1375
1460
  const elements = temporaryElements ? temporaryElements : calcElementIntersectionSelection(board);
@@ -1377,12 +1462,12 @@ function withSelection(board) {
1377
1462
  const { x, y, width, height } = getRectangleByElements(board, elements, false);
1378
1463
  if (width > 0 && height > 0) {
1379
1464
  const rough = PlaitBoard.getRoughSVG(board);
1380
- selectionOuterG === null || selectionOuterG === void 0 ? void 0 : selectionOuterG.remove();
1381
1465
  selectionOuterG = rough.rectangle(x - 2, y - 2, width + 4, height + 4, {
1382
1466
  stroke: SELECTION_BORDER_COLOR,
1383
1467
  strokeWidth: 1,
1384
1468
  fillStyle: 'solid'
1385
1469
  });
1470
+ selectionOuterG.classList.add('selection-outer');
1386
1471
  PlaitBoard.getHost(board).append(selectionOuterG);
1387
1472
  }
1388
1473
  }
@@ -1401,6 +1486,27 @@ function getTemporaryElements(board) {
1401
1486
  function deleteTemporaryElements(board) {
1402
1487
  BOARD_TO_TEMPORARY_ELEMENTS.delete(board);
1403
1488
  }
1489
+ function isSelectionMoving(board) {
1490
+ return !!BOARD_TO_IS_SELECTION_MOVING.get(board);
1491
+ }
1492
+ function setSelectionMoving(board) {
1493
+ PlaitBoard.getBoardNativeElement(board).classList.add('selection-moving');
1494
+ BOARD_TO_IS_SELECTION_MOVING.set(board, true);
1495
+ }
1496
+ function clearSelectionMoving(board) {
1497
+ PlaitBoard.getBoardNativeElement(board).classList.remove('selection-moving');
1498
+ BOARD_TO_IS_SELECTION_MOVING.delete(board);
1499
+ }
1500
+
1501
+ function withViewport(board) {
1502
+ const { onChange } = board;
1503
+ board.onChange = () => {
1504
+ initializeViewport(board);
1505
+ updateViewportContainerOffset(board);
1506
+ onChange();
1507
+ };
1508
+ return board;
1509
+ }
1404
1510
 
1405
1511
  class PlaitElementComponent {
1406
1512
  constructor(renderer2, viewContainerRef) {
@@ -1454,7 +1560,7 @@ class PlaitElementComponent {
1454
1560
  const current = {
1455
1561
  element: this.element,
1456
1562
  selection: this.selection,
1457
- board: this.board,
1563
+ board: this.board
1458
1564
  };
1459
1565
  if (this.context) {
1460
1566
  const previous = Object.assign({}, this.context);
@@ -1555,10 +1661,6 @@ class PlaitBoardComponent {
1555
1661
  this.elementRef = elementRef;
1556
1662
  this.hasInitialized = false;
1557
1663
  this.destroy$ = new Subject();
1558
- this.viewportState = {
1559
- zoom: 1,
1560
- autoFitPadding: 8
1561
- };
1562
1664
  this.plaitValue = [];
1563
1665
  this.plaitPlugins = [];
1564
1666
  this.plaitChange = new EventEmitter();
@@ -1567,10 +1669,6 @@ class PlaitBoardComponent {
1567
1669
  return index;
1568
1670
  };
1569
1671
  }
1570
- get isFocused() {
1571
- var _a;
1572
- return (_a = this.board) === null || _a === void 0 ? void 0 : _a.selection;
1573
- }
1574
1672
  get host() {
1575
1673
  return this.svg.nativeElement;
1576
1674
  }
@@ -1580,8 +1678,8 @@ class PlaitBoardComponent {
1580
1678
  get readonly() {
1581
1679
  return this.board.options.readonly;
1582
1680
  }
1583
- get focused() {
1584
- return this.isFocused;
1681
+ get isFocused() {
1682
+ return PlaitBoard.isFocus(this.board);
1585
1683
  }
1586
1684
  get nativeElement() {
1587
1685
  return this.elementRef.nativeElement;
@@ -1591,10 +1689,12 @@ class PlaitBoardComponent {
1591
1689
  const roughSVG = rough.svg(this.host, {
1592
1690
  options: { roughness: 0, strokeWidth: 1 }
1593
1691
  });
1692
+ this.roughSVG = roughSVG;
1594
1693
  this.initializePlugins();
1595
1694
  this.initializeEvents();
1596
1695
  this.viewportScrollListener();
1597
1696
  this.elementResizeListener();
1697
+ this.mouseLeaveListener();
1598
1698
  BOARD_TO_COMPONENT.set(this.board, this);
1599
1699
  BOARD_TO_ROUGH_SVG.set(this.board, roughSVG);
1600
1700
  BOARD_TO_HOST.set(this.board, this.host);
@@ -1611,13 +1711,19 @@ class PlaitBoardComponent {
1611
1711
  });
1612
1712
  this.hasInitialized = true;
1613
1713
  }
1714
+ mouseLeaveListener() {
1715
+ fromEvent(this.host, 'mouseleave')
1716
+ .pipe(takeUntil(this.destroy$))
1717
+ .subscribe((event) => {
1718
+ BOARD_TO_MOVING_POINT.delete(this.board);
1719
+ });
1720
+ }
1614
1721
  ngOnChanges(changes) {
1615
1722
  if (this.hasInitialized) {
1616
1723
  const valueChange = changes['plaitValue'];
1617
1724
  const options = changes['plaitOptions'];
1618
- if (valueChange) {
1725
+ if (valueChange)
1619
1726
  this.board.children = valueChange.currentValue;
1620
- }
1621
1727
  if (options)
1622
1728
  this.board.options = options.currentValue;
1623
1729
  this.cdr.markForCheck();
@@ -1626,21 +1732,17 @@ class PlaitBoardComponent {
1626
1732
  ngAfterViewInit() {
1627
1733
  this.plaitBoardInitialized.emit(this.board);
1628
1734
  this.initViewportContainer();
1629
- this.calcViewBox(this.viewportState.zoom);
1630
- this.initViewport();
1735
+ initializeViewport(this.board);
1736
+ initializeViewportContainerOffset(this.board);
1631
1737
  }
1632
1738
  initializePlugins() {
1633
- var _a, _b;
1634
- let board = withHandPointer(withHistory(withSelection(withBoard(createBoard(this.plaitValue, this.plaitOptions)))));
1739
+ let board = withHandPointer(withHistory(withSelection(withBoard(withViewport(createBoard(this.plaitValue, this.plaitOptions))))));
1635
1740
  this.plaitPlugins.forEach(plugin => {
1636
1741
  board = plugin(board);
1637
1742
  });
1638
1743
  this.board = board;
1639
1744
  if (this.plaitViewport) {
1640
1745
  this.board.viewport = this.plaitViewport;
1641
- this.updateViewportState({
1642
- zoom: (_b = (_a = this.plaitViewport) === null || _a === void 0 ? void 0 : _a.zoom) !== null && _b !== void 0 ? _b : 1
1643
- });
1644
1746
  }
1645
1747
  }
1646
1748
  initializeEvents() {
@@ -1676,34 +1778,34 @@ class PlaitBoardComponent {
1676
1778
  this.board.dblclick(event);
1677
1779
  });
1678
1780
  fromEvent(document, 'keydown')
1679
- .pipe(takeUntil(this.destroy$), filter(() => {
1680
- return !IS_TEXT_EDITABLE.get(this.board) && !!this.board.selection;
1681
- }))
1781
+ .pipe(takeUntil(this.destroy$), filter(() => this.isFocused && !PlaitBoard.hasBeenTextEditing(this.board)))
1682
1782
  .subscribe((event) => {
1683
1783
  var _a;
1784
+ if (isHotkey$1(['mod+=', 'mod++'], { byKey: true })(event)) {
1785
+ event.preventDefault();
1786
+ this.zoomInHandle(false);
1787
+ }
1788
+ if (isHotkey$1('mod+-', { byKey: true })(event)) {
1789
+ this.zoomOutHandle();
1790
+ event.preventDefault();
1791
+ }
1684
1792
  (_a = this.board) === null || _a === void 0 ? void 0 : _a.keydown(event);
1685
1793
  });
1686
1794
  fromEvent(document, 'keyup')
1687
- .pipe(takeUntil(this.destroy$), filter(() => {
1688
- return !IS_TEXT_EDITABLE.get(this.board) && !!this.board.selection;
1689
- }))
1795
+ .pipe(takeUntil(this.destroy$), filter(() => this.isFocused && !PlaitBoard.hasBeenTextEditing(this.board)))
1690
1796
  .subscribe((event) => {
1691
1797
  var _a;
1692
1798
  (_a = this.board) === null || _a === void 0 ? void 0 : _a.keyup(event);
1693
1799
  });
1694
1800
  fromEvent(document, 'copy')
1695
- .pipe(takeUntil(this.destroy$), filter(() => {
1696
- return !IS_TEXT_EDITABLE.get(this.board) && !!this.board.selection;
1697
- }))
1801
+ .pipe(takeUntil(this.destroy$), filter(() => this.isFocused && !PlaitBoard.hasBeenTextEditing(this.board)))
1698
1802
  .subscribe((event) => {
1699
1803
  var _a;
1700
1804
  event.preventDefault();
1701
1805
  (_a = this.board) === null || _a === void 0 ? void 0 : _a.setFragment(event.clipboardData);
1702
1806
  });
1703
1807
  fromEvent(document, 'paste')
1704
- .pipe(takeUntil(this.destroy$), filter(() => {
1705
- return !IS_TEXT_EDITABLE.get(this.board) && !!this.board.selection && !this.readonly;
1706
- }))
1808
+ .pipe(takeUntil(this.destroy$), filter(() => this.isFocused && !PlaitBoard.isReadonly(this.board) && !PlaitBoard.hasBeenTextEditing(this.board)))
1707
1809
  .subscribe((clipboardEvent) => {
1708
1810
  const mousePoint = BOARD_TO_MOVING_POINT.get(this.board);
1709
1811
  const rect = this.nativeElement.getBoundingClientRect();
@@ -1713,9 +1815,7 @@ class PlaitBoardComponent {
1713
1815
  }
1714
1816
  });
1715
1817
  fromEvent(document, 'cut')
1716
- .pipe(takeUntil(this.destroy$), filter(() => {
1717
- return !IS_TEXT_EDITABLE.get(this.board) && !!this.board.selection;
1718
- }))
1818
+ .pipe(takeUntil(this.destroy$), filter(() => this.isFocused && !PlaitBoard.isReadonly(this.board) && !PlaitBoard.hasBeenTextEditing(this.board)))
1719
1819
  .subscribe((event) => {
1720
1820
  var _a, _b;
1721
1821
  event.preventDefault();
@@ -1725,206 +1825,43 @@ class PlaitBoardComponent {
1725
1825
  }
1726
1826
  viewportScrollListener() {
1727
1827
  fromEvent(this.viewportContainer.nativeElement, 'scroll')
1728
- .pipe(takeUntil(this.destroy$), filter(() => {
1729
- return !!this.isFocused;
1730
- }))
1828
+ .pipe(takeUntil(this.destroy$), filter(() => this.isFocused))
1731
1829
  .subscribe((event) => {
1732
1830
  const { scrollLeft, scrollTop } = event.target;
1733
- const left = this.viewportState.scrollLeft;
1734
- const top = this.viewportState.scrollTop;
1735
- if (Math.abs(left - scrollLeft) >= 1 || Math.abs(top - scrollTop) >= 1) {
1736
- this.setScrollLeft(scrollLeft);
1737
- this.setScrollTop(scrollTop);
1738
- this.setViewport();
1739
- }
1831
+ const zoom = this.board.viewport.zoom;
1832
+ const viewBox = getViewBox(this.board, zoom);
1833
+ const origination = [scrollLeft / zoom + viewBox[0], scrollTop / zoom + viewBox[1]];
1834
+ setViewport(this.board, origination);
1740
1835
  });
1741
1836
  }
1742
1837
  elementResizeListener() {
1743
1838
  this.resizeObserver = new ResizeObserver(() => {
1744
1839
  this.initViewportContainer();
1745
- this.calcViewBox(this.board.viewport.zoom);
1746
- this.updateViewBoxStyles();
1747
- this.updateViewportScrolling();
1748
- this.setViewport();
1749
1840
  });
1750
1841
  this.resizeObserver.observe(this.nativeElement);
1751
1842
  }
1752
- updateViewportState(state) {
1753
- this.viewportState = Object.assign(Object.assign({}, this.viewportState), state);
1754
- }
1755
1843
  initViewportContainer() {
1756
- const { width, height } = getBoardClientBox(this.board);
1844
+ const { width, height } = getViewportContainerRect(this.board);
1757
1845
  this.renderer2.setStyle(this.viewportContainer.nativeElement, 'width', `${width}px`);
1758
1846
  this.renderer2.setStyle(this.viewportContainer.nativeElement, 'height', `${height}px`);
1759
1847
  }
1760
- initViewport(viewport = this.board.viewport) {
1761
- var _a;
1762
- const originationCoord = viewport === null || viewport === void 0 ? void 0 : viewport.originationCoord;
1763
- const zoom = (_a = viewport === null || viewport === void 0 ? void 0 : viewport.zoom) !== null && _a !== void 0 ? _a : this.viewportState.zoom;
1764
- if (originationCoord) {
1765
- const matrix = this.getMatrix();
1766
- const [pointX, pointY] = invertViewportCoordinates([0, 0], matrix);
1767
- const scrollLeft = this.viewportState.scrollLeft;
1768
- const scrollTop = this.viewportState.scrollTop;
1769
- const left = scrollLeft + (originationCoord[0] - pointX) * zoom;
1770
- const top = scrollTop + (originationCoord[1] - pointY) * zoom;
1771
- this.setScroll(left, top);
1772
- }
1773
- else {
1774
- this.adaptHandle();
1775
- }
1776
- }
1777
- calcViewBox(zoom = this.viewportState.zoom) {
1778
- var _a;
1779
- zoom = clampZoomLevel(zoom);
1780
- const scrollBarWidth = ((_a = this.plaitOptions) === null || _a === void 0 ? void 0 : _a.hideScrollbar) ? SCROLL_BAR_WIDTH : 0;
1781
- const viewportContainerBox = getViewportContainerBox(this.board);
1782
- const groupBBox = getRootGroupBBox(this.board, zoom);
1783
- const horizontalPadding = viewportContainerBox.width / 2;
1784
- const verticalPadding = viewportContainerBox.height / 2;
1785
- const viewportWidth = (groupBBox.right - groupBBox.left) * zoom + 2 * horizontalPadding + scrollBarWidth;
1786
- const viewportHeight = (groupBBox.bottom - groupBBox.top) * zoom + 2 * verticalPadding + scrollBarWidth;
1787
- const viewBox = [
1788
- groupBBox.left - horizontalPadding / zoom,
1789
- groupBBox.top - verticalPadding / zoom,
1790
- viewportWidth / zoom,
1791
- viewportHeight / zoom
1792
- ];
1793
- const matrix = this.getMatrix();
1794
- let scrollLeft;
1795
- let scrollTop;
1796
- if (matrix.length > 0) {
1797
- // focusPoint
1798
- const focusX = viewportContainerBox.x + viewportContainerBox.width / 2;
1799
- const focusY = viewportContainerBox.y + viewportContainerBox.height / 2;
1800
- const viewportContainerPoint = [focusX - viewportContainerBox.x, focusY - viewportContainerBox.y, 1];
1801
- const point = invertViewportCoordinates([viewportContainerPoint[0], viewportContainerPoint[1]], matrix);
1802
- const newMatrix = [zoom, 0, 0, 0, zoom, 0, -zoom * viewBox[0], -zoom * viewBox[1], 1];
1803
- const newPoint = transformMat3([], point, newMatrix);
1804
- scrollLeft = newPoint[0] - viewportContainerPoint[0];
1805
- scrollTop = newPoint[1] - viewportContainerPoint[1];
1806
- }
1807
- else {
1808
- scrollLeft = horizontalPadding;
1809
- scrollTop = verticalPadding;
1810
- }
1811
- this.updateViewportState({
1812
- viewportWidth,
1813
- viewportHeight,
1814
- zoom,
1815
- viewBox
1816
- });
1817
- this.setScrollLeft(scrollLeft);
1818
- this.setScrollTop(scrollTop);
1819
- }
1820
- getMatrix() {
1821
- const { viewBox, zoom, scrollLeft, scrollTop } = this.viewportState;
1822
- if (scrollLeft >= 0 && scrollTop >= 0) {
1823
- return [zoom, 0, 0, 0, zoom, 0, -scrollLeft - zoom * viewBox[0], -scrollTop - zoom * viewBox[1], 1];
1824
- }
1825
- return [];
1826
- }
1827
- setScrollLeft(left) {
1828
- var _a;
1829
- const viewportContainerBox = getViewportContainerBox(this.board);
1830
- const scrollBarWidth = ((_a = this.plaitOptions) === null || _a === void 0 ? void 0 : _a.hideScrollbar) ? SCROLL_BAR_WIDTH : 0;
1831
- const { viewportWidth } = this.viewportState;
1832
- const width = viewportWidth - viewportContainerBox.width + scrollBarWidth;
1833
- this.viewportState.scrollLeft = left < 0 ? 0 : left > width ? width : left;
1834
- }
1835
- setScrollTop(top) {
1836
- var _a;
1837
- const viewportContainerBox = getViewportContainerBox(this.board);
1838
- const scrollBarWidth = ((_a = this.plaitOptions) === null || _a === void 0 ? void 0 : _a.hideScrollbar) ? SCROLL_BAR_WIDTH : 0;
1839
- const { viewportHeight } = this.viewportState;
1840
- const height = viewportHeight - viewportContainerBox.height + scrollBarWidth;
1841
- this.viewportState.scrollTop = top < 0 ? 0 : top > height ? height : top;
1842
- }
1843
- setScroll(left, top) {
1844
- this.setScrollLeft(left);
1845
- this.setScrollTop(top);
1846
- this.updateViewBoxStyles();
1847
- this.updateViewportScrolling();
1848
- this.setViewport();
1849
- }
1850
- updateViewBoxStyles() {
1851
- const { host, viewportState } = this;
1852
- const { viewportWidth, viewportHeight, viewBox } = viewportState;
1853
- this.renderer2.setStyle(host, 'display', 'block');
1854
- this.renderer2.setStyle(host, 'width', `${viewportWidth}px`);
1855
- this.renderer2.setStyle(host, 'height', `${viewportHeight}px`);
1856
- if (viewBox && viewBox[2] > 0 && viewBox[3] > 0) {
1857
- this.renderer2.setAttribute(host, 'viewBox', viewBox.join(' '));
1858
- }
1859
- }
1860
- updateViewportScrolling() {
1861
- const { viewportContainer, viewportState } = this;
1862
- const { scrollLeft, scrollTop } = viewportState;
1863
- viewportContainer.nativeElement.scrollLeft = scrollLeft;
1864
- viewportContainer.nativeElement.scrollTop = scrollTop;
1865
- }
1866
- setViewport() {
1867
- var _a, _b;
1868
- const viewport = (_a = this.board) === null || _a === void 0 ? void 0 : _a.viewport;
1869
- const oldOriginationCoord = (_b = viewport === null || viewport === void 0 ? void 0 : viewport.originationCoord) !== null && _b !== void 0 ? _b : [];
1870
- const matrix = this.getMatrix();
1871
- const originationCoord = invertViewportCoordinates([0, 0], matrix);
1872
- if (!originationCoord.every((item, index) => item === oldOriginationCoord[index])) {
1873
- Transforms.setViewport(this.board, Object.assign(Object.assign({}, viewport), { zoom: this.viewportState.zoom, originationCoord }));
1874
- }
1875
- }
1876
1848
  adaptHandle() {
1877
- const containerBox = getViewportContainerBox(this.board);
1878
- const rootGroup = this.host.firstChild;
1879
- const matrix = this.getMatrix();
1880
- const rootGroupBox = rootGroup.getBBox();
1881
- const centerPoint = [containerBox.width / 2, containerBox.height / 2];
1882
- const rootGroupCenterX = rootGroupBox.x + rootGroupBox.width / 2;
1883
- const rootGroupCenterY = rootGroupBox.y + rootGroupBox.height / 2;
1884
- const transformedPoint = transformMat3([], [rootGroupCenterX, rootGroupCenterY, 1], matrix);
1885
- const offsetLeft = centerPoint[0] - transformedPoint[0];
1886
- const offsetTop = centerPoint[1] - transformedPoint[1];
1887
- const { autoFitPadding, zoom, scrollLeft, scrollTop } = this.viewportState;
1888
- const viewportWidth = containerBox.width - 2 * autoFitPadding;
1889
- const viewportHeight = containerBox.height - 2 * autoFitPadding;
1890
- let newZoom = zoom;
1891
- if (viewportWidth < rootGroupBox.width || viewportHeight < rootGroupBox.height) {
1892
- newZoom = Math.min(viewportWidth / rootGroupBox.width, viewportHeight / rootGroupBox.height);
1893
- }
1894
- else {
1895
- newZoom = 1;
1896
- }
1897
- this.setScrollLeft(scrollLeft - offsetLeft);
1898
- this.setScrollTop(scrollTop - offsetTop);
1899
- this.calcViewBox(newZoom);
1900
- this.updateViewBoxStyles();
1901
- this.updateViewportScrolling();
1902
- this.setViewport();
1849
+ fitViewport(this.board);
1903
1850
  }
1904
- zoomInHandle() {
1905
- this.calcViewBox(this.viewportState.zoom + 0.1);
1906
- this.updateViewBoxStyles();
1907
- this.updateViewportScrolling();
1908
- this.setViewport();
1851
+ zoomInHandle(isCenter = true) {
1852
+ changeZoom(this.board, this.board.viewport.zoom + 0.1, isCenter);
1909
1853
  }
1910
1854
  zoomOutHandle() {
1911
- this.calcViewBox(this.viewportState.zoom - 0.1);
1912
- this.updateViewBoxStyles();
1913
- this.updateViewportScrolling();
1914
- this.setViewport();
1855
+ changeZoom(this.board, this.board.viewport.zoom - 0.1);
1915
1856
  }
1916
1857
  resetZoomHandel() {
1917
- this.calcViewBox(1);
1918
- this.updateViewBoxStyles();
1919
- this.updateViewportScrolling();
1920
- this.setViewport();
1858
+ changeZoom(this.board, 1);
1921
1859
  }
1922
1860
  ngOnDestroy() {
1861
+ var _a;
1923
1862
  this.destroy$.next();
1924
1863
  this.destroy$.complete();
1925
- if (this.resizeObserver) {
1926
- this.resizeObserver.disconnect();
1927
- }
1864
+ this.resizeObserver && ((_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect());
1928
1865
  BOARD_TO_ROUGH_SVG.delete(this.board);
1929
1866
  BOARD_TO_COMPONENT.delete(this.board);
1930
1867
  BOARD_TO_ROUGH_SVG.delete(this.board);
@@ -1935,41 +1872,9 @@ class PlaitBoardComponent {
1935
1872
  markForCheck() {
1936
1873
  this.cdr.markForCheck();
1937
1874
  }
1938
- scrollToRectangle(client) {
1939
- var _a;
1940
- this.calcViewBox();
1941
- this.updateViewBoxStyles();
1942
- this.updateViewportScrolling();
1943
- this.setViewport();
1944
- const svgRect = this.host.getBoundingClientRect();
1945
- const viewportContainerBox = getViewportContainerBox(this.board);
1946
- if (svgRect.width > viewportContainerBox.width || svgRect.height > viewportContainerBox.height) {
1947
- const scrollBarWidth = ((_a = this.plaitOptions) === null || _a === void 0 ? void 0 : _a.hideScrollbar) ? SCROLL_BAR_WIDTH : 0;
1948
- const matrix = this.getMatrix();
1949
- const [nodePointX, nodePointY] = convertToViewportCoordinates([client.x, client.y], matrix);
1950
- const [fullNodePointX, fullNodePointY] = convertToViewportCoordinates([client.x + client.width, client.y + client.height], matrix);
1951
- let newLeft = this.viewportState.scrollLeft;
1952
- let newTop = this.viewportState.scrollTop;
1953
- if (nodePointX < 0) {
1954
- newLeft -= Math.abs(nodePointX);
1955
- }
1956
- if (nodePointX > 0 && fullNodePointX > viewportContainerBox.width) {
1957
- newLeft += fullNodePointX - viewportContainerBox.width + scrollBarWidth;
1958
- }
1959
- if (nodePointY < 0) {
1960
- newTop -= Math.abs(nodePointY);
1961
- }
1962
- if (nodePointY > 0 && fullNodePointY > viewportContainerBox.height) {
1963
- newTop += fullNodePointY - viewportContainerBox.height + scrollBarWidth;
1964
- }
1965
- if (newLeft !== this.viewportState.scrollLeft || newTop !== this.viewportState.scrollTop) {
1966
- this.setScroll(newLeft, newTop);
1967
- }
1968
- }
1969
- }
1970
1875
  }
1971
1876
  PlaitBoardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: PlaitBoardComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
1972
- PlaitBoardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: PlaitBoardComponent, selector: "plait-board", inputs: { plaitValue: "plaitValue", plaitViewport: "plaitViewport", plaitPlugins: "plaitPlugins", plaitOptions: "plaitOptions" }, outputs: { plaitChange: "plaitChange", plaitBoardInitialized: "plaitBoardInitialized" }, host: { properties: { "class": "this.hostClass", "class.readonly": "this.readonly", "class.focused": "this.focused" } }, queries: [{ propertyName: "toolbarTemplateRef", first: true, predicate: ["plaitToolbar"], descendants: true }], viewQueries: [{ propertyName: "svg", first: true, predicate: ["svg"], descendants: true, static: true }, { propertyName: "viewportContainer", first: true, predicate: ["viewportContainer"], descendants: true, read: ElementRef, static: true }], usesOnChanges: true, ngImport: i0, template: `
1877
+ PlaitBoardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: PlaitBoardComponent, selector: "plait-board", inputs: { plaitValue: "plaitValue", plaitViewport: "plaitViewport", plaitPlugins: "plaitPlugins", plaitOptions: "plaitOptions" }, outputs: { plaitChange: "plaitChange", plaitBoardInitialized: "plaitBoardInitialized" }, host: { properties: { "class": "this.hostClass", "class.readonly": "this.readonly", "class.focused": "this.isFocused" } }, queries: [{ propertyName: "toolbarTemplateRef", first: true, predicate: ["plaitToolbar"], descendants: true }], viewQueries: [{ propertyName: "svg", first: true, predicate: ["svg"], descendants: true, static: true }, { propertyName: "viewportContainer", first: true, predicate: ["viewportContainer"], descendants: true, read: ElementRef, static: true }], usesOnChanges: true, ngImport: i0, template: `
1973
1878
  <div class="viewport-container" #viewportContainer>
1974
1879
  <svg #svg width="100%" height="100%" style="position: relative;"><g class="element-host"></g></svg>
1975
1880
  <plait-element
@@ -2035,7 +1940,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
2035
1940
  }], readonly: [{
2036
1941
  type: HostBinding,
2037
1942
  args: ['class.readonly']
2038
- }], focused: [{
1943
+ }], isFocused: [{
2039
1944
  type: HostBinding,
2040
1945
  args: ['class.focused']
2041
1946
  }], svg: [{
@@ -2133,6 +2038,88 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
2133
2038
  }]
2134
2039
  }] });
2135
2040
 
2041
+ function withMoving(board) {
2042
+ const { mousedown, mousemove, globalMouseup, globalMousemove } = board;
2043
+ let offsetX = 0;
2044
+ let offsetY = 0;
2045
+ let isPreventDefault = false;
2046
+ let startPoint;
2047
+ let activeElements = [];
2048
+ board.mousedown = event => {
2049
+ const host = BOARD_TO_HOST.get(board);
2050
+ const point = transformPoint(board, toPoint(event.x, event.y, host));
2051
+ const ranges = [{ anchor: point, focus: point }];
2052
+ let movableElements = board.children.filter(item => PlaitElement.isElement(item) && board.isMovable(item));
2053
+ if (movableElements.length) {
2054
+ startPoint = point;
2055
+ const selectedRootElements = getSelectedElements(board).filter(item => movableElements.includes(item));
2056
+ const intersectionSelectedElement = isIntersectionElements(board, selectedRootElements, ranges);
2057
+ if (intersectionSelectedElement) {
2058
+ activeElements = selectedRootElements;
2059
+ }
2060
+ else {
2061
+ activeElements = movableElements.filter(item => ranges.some(range => {
2062
+ return board.isIntersectionSelection(item, range);
2063
+ }));
2064
+ }
2065
+ }
2066
+ mousedown(event);
2067
+ };
2068
+ board.mousemove = event => {
2069
+ if (startPoint && (activeElements === null || activeElements === void 0 ? void 0 : activeElements.length)) {
2070
+ if (!isPreventDefault) {
2071
+ isPreventDefault = true;
2072
+ }
2073
+ const host = BOARD_TO_HOST.get(board);
2074
+ const endPoint = transformPoint(board, toPoint(event.x, event.y, host));
2075
+ offsetX = endPoint[0] - startPoint[0];
2076
+ offsetY = endPoint[1] - startPoint[1];
2077
+ throttleRAF(() => {
2078
+ const currentElements = activeElements.map(activeElement => {
2079
+ const [x, y] = activeElement === null || activeElement === void 0 ? void 0 : activeElement.points[0];
2080
+ const index = board.children.findIndex(item => item.id === activeElement.id);
2081
+ Transforms.setNode(board, {
2082
+ points: [[x + offsetX, y + offsetY]]
2083
+ }, [index]);
2084
+ MERGING.set(board, true);
2085
+ return PlaitNode.get(board, [index]);
2086
+ });
2087
+ addMovingElements(board, currentElements);
2088
+ });
2089
+ }
2090
+ if (isPreventDefault) {
2091
+ // 阻止 move 过程中触发画布滚动行为
2092
+ event.preventDefault();
2093
+ }
2094
+ mousemove(event);
2095
+ };
2096
+ board.globalMousemove = event => {
2097
+ if (startPoint) {
2098
+ const inPliatBordElement = isInPlaitBoard(board, event.x, event.y);
2099
+ if (!inPliatBordElement) {
2100
+ cancelMove(board);
2101
+ }
2102
+ }
2103
+ globalMousemove(event);
2104
+ };
2105
+ board.globalMouseup = event => {
2106
+ isPreventDefault = false;
2107
+ if (startPoint) {
2108
+ cancelMove(board);
2109
+ }
2110
+ globalMouseup(event);
2111
+ };
2112
+ function cancelMove(board) {
2113
+ startPoint = null;
2114
+ offsetX = 0;
2115
+ offsetY = 0;
2116
+ activeElements = [];
2117
+ removeMovingElements(board);
2118
+ MERGING.set(board, false);
2119
+ }
2120
+ return board;
2121
+ }
2122
+
2136
2123
  /*
2137
2124
  * Public API Surface of plait
2138
2125
  */
@@ -2141,5 +2128,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
2141
2128
  * Generated bundle index. Do not edit.
2142
2129
  */
2143
2130
 
2144
- export { BOARD_TO_COMPONENT, BOARD_TO_ELEMENT_HOST, BOARD_TO_HOST, BOARD_TO_MOVING_POINT, BOARD_TO_ON_CHANGE, BOARD_TO_ROUGH_SVG, BOARD_TO_SELECTED_ELEMENT, BOARD_TO_TEMPORARY_ELEMENTS, BoardTransforms, CLIP_BOARD_FORMAT_KEY, ELEMENT_TO_PLUGIN_COMPONENT, FLUSHING, IS_APPLE, IS_CHROME, IS_CHROME_LEGACY, IS_EDGE_LEGACY, IS_FIREFOX, IS_IOS, IS_SAFARI, IS_TEXT_EDITABLE, MAX_RADIUS, MERGING, NS, Path, PlaitBoard, PlaitBoardComponent, PlaitElement, PlaitElementComponent, PlaitHistoryBoard, PlaitModule, PlaitNode, PlaitOperation, PlaitPluginElementComponent, PlaitPointerType, PlaitToolbarComponent, RectangleClient, SAVING, SCROLL_BAR_WIDTH, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, Selection, Transforms, Viewport, addSelectedElement, arrowPoints, cacheSelectedElements, calcElementIntersectionSelection, clampZoomLevel, convertToViewportCoordinates, createG, createSVG, createText, deleteTemporaryElements, depthFirstRecursion, distanceBetweenPointAndPoint, distanceBetweenPointAndRectangle, distanceBetweenPointAndSegment, drawArrow, drawRoundRectangle, getBoardClientBox, getBoardRectangle, getRectangleByElements, getRootGroupBBox, getSelectedElements, getTemporaryElements, getViewportContainerBox, hasBeforeContextChange, hotkeys, idCreator, inverse, invertMatrix, invertViewportCoordinates, isNoSelectionElement, isNullOrUndefined, isSelectedElement, isSetViewportOperation, normalizePoint, removeSelectedElement, rotate, shouldClear, shouldMerge, shouldSave, toPoint, transformMat3, transformPoint, transformPoints, withSelection };
2131
+ export { 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_ON_CHANGE, BOARD_TO_ROUGH_SVG, BOARD_TO_SELECTED_ELEMENT, BOARD_TO_TEMPORARY_ELEMENTS, BoardTransforms, CLIP_BOARD_FORMAT_KEY, ELEMENT_TO_PLUGIN_COMPONENT, FLUSHING, IS_APPLE, IS_CHROME, IS_CHROME_LEGACY, IS_EDGE_LEGACY, IS_FIREFOX, IS_IOS, IS_SAFARI, IS_TEXT_EDITABLE, MAX_RADIUS, MERGING, NS, Path, PlaitBoard, PlaitBoardComponent, PlaitElement, PlaitElementComponent, PlaitHistoryBoard, PlaitModule, PlaitNode, PlaitOperation, PlaitPluginElementComponent, PlaitPointerType, PlaitToolbarComponent, RectangleClient, SAVING, SCROLL_BAR_WIDTH, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, Selection, Transforms, Viewport, addMovingElements, addSelectedElement, arrowPoints, cacheMovingElements, cacheSelectedElements, calcElementIntersectionSelection, changeZoom, clampZoomLevel, clearSelectionMoving, createG, createSVG, createText, deleteTemporaryElements, depthFirstRecursion, distanceBetweenPointAndPoint, distanceBetweenPointAndRectangle, distanceBetweenPointAndSegment, drawArrow, drawRoundRectangle, fitViewport, getBoardRectangle, getElementHostBBox, getMovingElements, getRectangleByElements, getSelectedElements, getTemporaryElements, getViewBox, getViewportContainerRect, hasBeforeContextChange, hotkeys, idCreator, initializeViewport, initializeViewportContainerOffset, inverse, isInPlaitBoard, isIntersectionElements, isNullOrUndefined, isSelectedElement, isSelectionMoving, isSetViewportOperation, normalizePoint, removeMovingElements, removeSelectedElement, rotate, scrollToRectangle, setSVGViewBox, setSelectionMoving, setViewport, setViewportContainerScroll, shouldClear, shouldMerge, shouldSave, throttleRAF, toPoint, transformPoint, transformPoints, updateViewportContainerOffset, withMoving, withSelection };
2145
2132
  //# sourceMappingURL=plait-core.mjs.map