@plait/mind 0.2.0-next.8 → 0.2.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.
Files changed (93) hide show
  1. package/constants/abstract-node.d.ts +4 -0
  2. package/constants/default.d.ts +1 -2
  3. package/constants/index.d.ts +4 -1
  4. package/constants/node-rule.d.ts +1 -0
  5. package/constants/node-style.d.ts +17 -0
  6. package/constants/node-topic-style.d.ts +4 -0
  7. package/draw/richtext.d.ts +1 -1
  8. package/esm2020/constants/abstract-node.mjs +5 -0
  9. package/esm2020/constants/default.mjs +2 -3
  10. package/esm2020/constants/index.mjs +5 -2
  11. package/esm2020/constants/node-rule.mjs +2 -0
  12. package/esm2020/constants/node-style.mjs +19 -0
  13. package/esm2020/constants/node-topic-style.mjs +5 -0
  14. package/esm2020/draw/abstract.mjs +4 -3
  15. package/esm2020/draw/indented-link.mjs +15 -15
  16. package/esm2020/draw/link/abstract-link.mjs +6 -4
  17. package/esm2020/draw/link/logic-link.mjs +10 -8
  18. package/esm2020/draw/link.mjs +8 -7
  19. package/esm2020/draw/richtext.mjs +10 -8
  20. package/esm2020/draw/shape.mjs +5 -5
  21. package/esm2020/drawer/quick-insert.drawer.mjs +13 -14
  22. package/esm2020/interfaces/abstract.mjs +1 -1
  23. package/esm2020/interfaces/element.mjs +20 -1
  24. package/esm2020/interfaces/node.mjs +1 -10
  25. package/esm2020/layout-option.mjs +3 -3
  26. package/esm2020/node.component.mjs +43 -34
  27. package/esm2020/plugins/emoji/emoji.drawer.mjs +4 -8
  28. package/esm2020/plugins/emoji/emoji.mjs +31 -3
  29. package/esm2020/plugins/with-abstract.mjs +2 -2
  30. package/esm2020/plugins/with-dnd.mjs +23 -123
  31. package/esm2020/plugins/with-mind.mjs +37 -29
  32. package/esm2020/queries/get-available-sublayouts-by-element.mjs +5 -10
  33. package/esm2020/queries/get-branch-layouts.mjs +7 -7
  34. package/esm2020/queries/get-correct-layout-by-element.mjs +28 -31
  35. package/esm2020/queries/get-layout-by-element.mjs +11 -9
  36. package/esm2020/queries/index.mjs +1 -3
  37. package/esm2020/transforms/abstract-node.mjs +68 -0
  38. package/esm2020/transforms/index.mjs +6 -2
  39. package/esm2020/transforms/layout.mjs +3 -3
  40. package/esm2020/transforms/node.mjs +2 -2
  41. package/esm2020/utils/abstract/common.mjs +90 -70
  42. package/esm2020/utils/abstract/resize.mjs +3 -3
  43. package/esm2020/utils/clipboard.mjs +54 -14
  44. package/esm2020/utils/direction-corrector.mjs +11 -11
  45. package/esm2020/utils/dnd.mjs +122 -0
  46. package/esm2020/utils/draw-placeholder.mjs +11 -9
  47. package/esm2020/utils/drop-target-corrector.mjs +11 -10
  48. package/esm2020/utils/index.mjs +1 -2
  49. package/esm2020/utils/layout.mjs +1 -1
  50. package/esm2020/utils/mind.mjs +30 -72
  51. package/esm2020/utils/node-space.mjs +23 -18
  52. package/esm2020/utils/node-style/branch.mjs +34 -20
  53. package/esm2020/utils/node-style/common.mjs +13 -0
  54. package/esm2020/utils/node-style/index.mjs +3 -2
  55. package/esm2020/utils/node-style/shape.mjs +21 -0
  56. package/esm2020/utils/path.mjs +4 -3
  57. package/fesm2015/plait-mind.mjs +862 -713
  58. package/fesm2015/plait-mind.mjs.map +1 -1
  59. package/fesm2020/plait-mind.mjs +865 -711
  60. package/fesm2020/plait-mind.mjs.map +1 -1
  61. package/interfaces/abstract.d.ts +3 -0
  62. package/interfaces/element.d.ts +7 -2
  63. package/interfaces/node.d.ts +0 -1
  64. package/node.component.d.ts +0 -1
  65. package/package.json +1 -1
  66. package/plugins/emoji/emoji.d.ts +5 -1
  67. package/plugins/with-dnd.d.ts +0 -9
  68. package/queries/get-available-sublayouts-by-element.d.ts +2 -6
  69. package/queries/get-branch-layouts.d.ts +2 -1
  70. package/queries/get-correct-layout-by-element.d.ts +2 -1
  71. package/queries/index.d.ts +3 -4
  72. package/styles/styles.scss +19 -19
  73. package/transforms/abstract-node.d.ts +6 -0
  74. package/transforms/index.d.ts +3 -0
  75. package/utils/abstract/common.d.ts +6 -8
  76. package/utils/direction-corrector.d.ts +2 -1
  77. package/utils/dnd.d.ts +16 -0
  78. package/utils/drop-target-corrector.d.ts +2 -1
  79. package/utils/index.d.ts +0 -1
  80. package/utils/mind.d.ts +4 -5
  81. package/utils/node-space.d.ts +5 -4
  82. package/utils/node-style/branch.d.ts +6 -1
  83. package/utils/node-style/common.d.ts +3 -0
  84. package/utils/node-style/index.d.ts +2 -1
  85. package/utils/node-style/shape.d.ts +4 -0
  86. package/constants/node.d.ts +0 -17
  87. package/esm2020/constants/node.mjs +0 -19
  88. package/esm2020/queries/get-layout-parent-by-element.mjs +0 -17
  89. package/esm2020/utils/node-style/node.mjs +0 -22
  90. package/esm2020/utils/shape.mjs +0 -17
  91. package/queries/get-layout-parent-by-element.d.ts +0 -8
  92. package/utils/node-style/node.d.ts +0 -3
  93. package/utils/shape.d.ts +0 -3
@@ -1,8 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Component, ChangeDetectionStrategy, NgModule, Directive, Input } from '@angular/core';
3
3
  import * as i2 from '@plait/core';
4
- import { distanceBetweenPointAndRectangle, PlaitElement, PlaitBoard, PlaitNode, NODE_TO_PARENT, Path, ELEMENT_TO_COMPONENT, Transforms, idCreator, isNullOrUndefined, clearSelectedElement, addSelectedElement, drawRoundRectangle, getRectangleByElements, RectangleClient, getSelectedElements, createG, drawAbstractRoundRectangle, PlaitPluginElementComponent, PlaitPointerType, NODE_TO_INDEX, createText, IS_TEXT_EDITABLE, MERGING, transformPoint, toPoint, depthFirstRecursion, PlaitModule, distanceBetweenPointAndPoint, CLIP_BOARD_FORMAT_KEY, BOARD_TO_HOST, removeSelectedElement, PlaitHistoryBoard, hotkeys } from '@plait/core';
5
- import { AbstractNode, isChildOfAbstract, isIndentedLayout, getAbstractLayout, MindLayoutType, isStandardLayout, isTopLayout, isLeftLayout, isHorizontalLogicLayout, isVerticalLogicLayout, isBottomLayout, isRightLayout, isHorizontalLayout, getNonAbstractChildren, getCorrectStartEnd, ConnectingPosition, GlobalLayout } from '@plait/layouts';
4
+ import { distanceBetweenPointAndRectangle, PlaitBoard, PlaitNode, NODE_TO_PARENT, Path, ELEMENT_TO_COMPONENT, PlaitElement, Transforms, idCreator, isNullOrUndefined, clearSelectedElement, addSelectedElement, drawRoundRectangle, getRectangleByElements, RectangleClient, getSelectedElements, createG, drawAbstractRoundRectangle, PlaitPluginElementComponent, PlaitPointerType, NODE_TO_INDEX, createText, IS_TEXT_EDITABLE, MERGING, transformPoint, toPoint, depthFirstRecursion, PlaitModule, distanceBetweenPointAndPoint, updateForeignObject as updateForeignObject$1, CLIP_BOARD_FORMAT_KEY, BOARD_TO_HOST, Selection, removeSelectedElement, PlaitHistoryBoard, hotkeys } from '@plait/core';
5
+ import { MindLayoutType, AbstractNode, getAbstractLayout, isIndentedLayout, isStandardLayout, isHorizontalLogicLayout, isVerticalLogicLayout, isTopLayout, isLeftLayout, isBottomLayout, isRightLayout, isHorizontalLayout, getNonAbstractChildren, getCorrectStartEnd, ConnectingPosition, GlobalLayout } from '@plait/layouts';
6
6
  import { getSizeByText, ROOT_DEFAULT_HEIGHT, TEXT_DEFAULT_HEIGHT, drawRichtext, updateForeignObject, createForeignObject, updateRichText, setFullSelectionAndFocus, getRichtextContentSize, hasEditableTarget, RichtextModule } from '@plait/richtext';
7
7
  import { fromEvent, Subject, timer } from 'rxjs';
8
8
  import { take, takeUntil, filter, debounceTime } from 'rxjs/operators';
@@ -16,34 +16,44 @@ const ELEMENT_TO_NODE = new WeakMap();
16
16
 
17
17
  const BASE = 4;
18
18
  const PRIMARY_COLOR = '#6698FF';
19
- const MINDMAP_KEY = 'plait-mindmap';
20
- const MAX_RADIUS = BASE * 4;
21
19
  const TRANSPARENT = 'transparent';
22
20
  const GRAY_COLOR = '#AAAAAA';
23
21
  const STROKE_WIDTH = 3;
22
+ const BRANCH_WIDTH = 3;
24
23
  const EXTEND_OFFSET = 8;
25
24
  const EXTEND_RADIUS = 16;
26
25
  const QUICK_INSERT_CIRCLE_OFFSET = 9;
27
26
  const QUICK_INSERT_CIRCLE_COLOR = '#6698FF';
28
27
  const QUICK_INSERT_INNER_CROSS_COLOR = 'white';
29
28
 
29
+ const DefaultAbstractNodeStyle = {
30
+ strokeColor: GRAY_COLOR,
31
+ strokeWidth: 2,
32
+ branchColor: GRAY_COLOR,
33
+ branchWidth: 2,
34
+ fill: '#FFFFFF'
35
+ };
36
+ const DefaultNodeStyle = {
37
+ strokeWidth: 3,
38
+ branchWidth: 3,
39
+ fill: '#FFFFFF'
40
+ };
41
+ const DefaultRootStyle = {
42
+ fill: '#F5F5F5',
43
+ strokeColor: '#F5F5F5',
44
+ };
45
+ const BRANCH_COLORS = ['#A287E1', '#6F81DB', '#6EC4C4', '#DFB85D', '#B1C774', '#77C386', '#C28976', '#E48484', '#E482D4', '#69B1E4'];
46
+
30
47
  const TOPIC_COLOR = '#333';
31
48
  const TOPIC_FONT_SIZE = 14;
32
- const NODE_FILL = '#FFFFFF';
33
- const ROOT_NODE_FILL = '#F5F5F5';
34
- const ROOT_NODE_STROKE = '#F5F5F5';
35
49
  const ROOT_TOPIC_FONT_SIZE = 18;
50
+ const TOPIC_DEFAULT_MAX_WORD_COUNT = 34;
51
+
36
52
  const NODE_MIN_WIDTH = 18;
37
- const COLORS = ['#A287E1', '#6F81DB', '#6EC4C4', '#DFB85D', '#B1C774', '#77C386', '#C28976', '#E48484', '#E482D4', '#69B1E4'];
38
- var MindNodeShape;
39
- (function (MindNodeShape) {
40
- MindNodeShape["roundRectangle"] = "round-rectangle";
41
- MindNodeShape["underline"] = "underline";
42
- })(MindNodeShape || (MindNodeShape = {}));
43
- const ABSTRACT_HANDLE_COLOR = '#6698FF80'; //PRIMARY_COLOR 50% 透明度
53
+
54
+ const ABSTRACT_HANDLE_COLOR = '#6698FF80'; //primary color 50% opacity
44
55
  const ABSTRACT_INCLUDED_OUTLINE_OFFSET = 3.5;
45
56
  const ABSTRACT_HANDLE_LENGTH = 10;
46
- const TOPIC_DEFAULT_MAX_WORD_COUNT = 34;
47
57
  const ABSTRACT_HANDLE_MASK_WIDTH = 8;
48
58
 
49
59
  function getRectangleByNode(node) {
@@ -74,35 +84,35 @@ function hitMindElement(board, point, element) {
74
84
  * 2. correct layout by incorrect layout direction
75
85
  * @param element
76
86
  */
77
- const getCorrectLayoutByElement = (element) => {
78
- var _a;
79
- const { root } = findUpElement(element);
80
- const rootLayout = root.layout || getDefaultLayout();
81
- let correctRootLayout = rootLayout;
82
- if (element.isRoot) {
83
- return correctRootLayout;
84
- }
85
- const component = PlaitElement.getComponent(element);
86
- let layout = element.layout;
87
- let parentComponent = null;
88
- let parent = component.parent.origin;
89
- while (!layout && parent) {
90
- parentComponent = PlaitElement.getComponent(parent);
91
- layout = parentComponent.node.origin.layout;
92
- parent = (_a = parentComponent.parent) === null || _a === void 0 ? void 0 : _a.origin;
93
- }
94
- if ((AbstractNode.isAbstract(element) || isChildOfAbstract(MindElement.getNode(element))) &&
95
- isIndentedLayout(layout)) {
96
- return getAbstractLayout(layout);
87
+ const getCorrectLayoutByElement = (board, element) => {
88
+ const ancestors = MindElement.getAncestors(board, element);
89
+ ancestors.unshift(element);
90
+ const root = ancestors[ancestors.length - 1];
91
+ let rootLayout = getRootLayout(root);
92
+ if (PlaitMind.isMind(element)) {
93
+ return rootLayout;
97
94
  }
98
- // handle root standard
95
+ const node = MindElement.getNode(element);
96
+ let correctRootLayout = rootLayout;
99
97
  if (rootLayout === MindLayoutType.standard) {
100
- correctRootLayout = (component === null || component === void 0 ? void 0 : component.node.left) ? MindLayoutType.left : MindLayoutType.right;
98
+ correctRootLayout = node.left ? MindLayoutType.left : MindLayoutType.right;
101
99
  }
102
- if (parentComponent && parentComponent.node.origin.isRoot) {
100
+ let layout = null;
101
+ const elementWithLayout = ancestors.find(value => value.layout || AbstractNode.isAbstract(value));
102
+ if (elementWithLayout) {
103
+ if (AbstractNode.isAbstract(elementWithLayout)) {
104
+ const parent = MindElement.getParent(elementWithLayout);
105
+ const parentLayout = getCorrectLayoutByElement(board, parent);
106
+ layout = getAbstractLayout(parentLayout);
107
+ }
108
+ else {
109
+ layout = elementWithLayout === null || elementWithLayout === void 0 ? void 0 : elementWithLayout.layout;
110
+ }
111
+ }
112
+ if (layout === MindLayoutType.standard || !layout) {
103
113
  return correctRootLayout;
104
114
  }
105
- if (layout) {
115
+ else {
106
116
  const incorrectDirection = getInCorrectLayoutDirection(correctRootLayout, layout);
107
117
  if (incorrectDirection) {
108
118
  return correctLayoutByDirection(layout, incorrectDirection);
@@ -111,36 +121,28 @@ const getCorrectLayoutByElement = (element) => {
111
121
  return layout;
112
122
  }
113
123
  }
114
- else {
115
- return correctRootLayout;
116
- }
117
124
  };
118
125
 
119
- const getBranchLayouts = (element) => {
126
+ const getBranchLayouts = (board, element) => {
120
127
  const layouts = [];
121
128
  if (element.layout) {
122
- //getCorrectLayoutByElement含有递归操作,getBranchMindmapLayouts本身也有递归操作,有待优化
123
- layouts.unshift(getCorrectLayoutByElement(element));
129
+ // TODO: getCorrectLayoutByElement 含有递归操作,getBranchLayouts 本身也有递归操作,有待优化
130
+ layouts.unshift(getCorrectLayoutByElement(board, element));
124
131
  }
125
- let parent = findParentElement(element);
132
+ let parent = MindElement.findParent(element);
126
133
  while (parent) {
127
134
  if (parent.layout) {
128
135
  layouts.unshift(parent.layout);
129
136
  }
130
- parent = findParentElement(parent);
137
+ parent = MindElement.findParent(parent);
131
138
  }
132
139
  return layouts;
133
140
  };
134
141
 
135
- /**
136
- * get available sub layouts by element
137
- * @param element
138
- * @returns MindLayoutType[]
139
- */
140
- const getAvailableSubLayoutsByElement = (element) => {
141
- const parentElement = findParentElement(element);
142
+ const getAvailableSubLayoutsByElement = (board, element) => {
143
+ const parentElement = MindElement.findParent(element);
142
144
  if (parentElement) {
143
- const branchLayouts = getBranchLayouts(parentElement);
145
+ const branchLayouts = getBranchLayouts(board, parentElement);
144
146
  if (branchLayouts[0] === MindLayoutType.standard) {
145
147
  const node = MindElement.getNode(element);
146
148
  branchLayouts[0] = node.left ? MindLayoutType.left : MindLayoutType.right;
@@ -156,20 +158,107 @@ const getAvailableSubLayoutsByElement = (element) => {
156
158
  return undefined;
157
159
  };
158
160
 
159
- /**
160
- * 获取父节点布局类型
161
- * @param element
162
- * @returns MindLayoutType
163
- */
164
- const getLayoutParentByElement = (element) => {
165
- let parent = findParentElement(element);
166
- while (parent) {
167
- if (parent.layout) {
168
- return parent.layout;
161
+ const getBranchDirectionsByLayouts = (branchLayouts) => {
162
+ const branchDirections = [];
163
+ branchLayouts.forEach(l => {
164
+ const directions = LayoutDirectionsMap[l];
165
+ directions.forEach(d => {
166
+ if (!branchDirections.includes(d) && !branchDirections.includes(getLayoutReverseDirection(d))) {
167
+ branchDirections.push(d);
168
+ }
169
+ });
170
+ });
171
+ return branchDirections;
172
+ };
173
+ const isCorrectLayout = (root, layout) => {
174
+ const rootLayout = root.layout || getDefaultLayout();
175
+ return !getInCorrectLayoutDirection(rootLayout, layout);
176
+ };
177
+ const isMixedLayout = (parentLayout, layout) => {
178
+ return (!isIndentedLayout(parentLayout) && isIndentedLayout(layout)) || (isIndentedLayout(parentLayout) && !isIndentedLayout(layout));
179
+ };
180
+ const getInCorrectLayoutDirection = (rootLayout, layout) => {
181
+ const directions = LayoutDirectionsMap[rootLayout];
182
+ const subLayoutDirections = LayoutDirectionsMap[layout];
183
+ if (!subLayoutDirections) {
184
+ throw new Error(`unexpected layout: ${layout} on correct layout`);
185
+ }
186
+ return subLayoutDirections.find(d => directions.includes(getLayoutReverseDirection(d)));
187
+ };
188
+ const correctLayoutByDirection = (layout, direction) => {
189
+ const isHorizontal = direction === LayoutDirection.left || direction === LayoutDirection.right ? true : false;
190
+ let inverseDirectionLayout = MindLayoutType.standard;
191
+ switch (layout) {
192
+ case MindLayoutType.left:
193
+ inverseDirectionLayout = MindLayoutType.right;
194
+ break;
195
+ case MindLayoutType.right:
196
+ inverseDirectionLayout = MindLayoutType.left;
197
+ break;
198
+ case MindLayoutType.downward:
199
+ inverseDirectionLayout = MindLayoutType.upward;
200
+ break;
201
+ case MindLayoutType.upward:
202
+ inverseDirectionLayout = MindLayoutType.downward;
203
+ break;
204
+ case MindLayoutType.rightBottomIndented:
205
+ inverseDirectionLayout = isHorizontal ? MindLayoutType.leftBottomIndented : MindLayoutType.rightTopIndented;
206
+ break;
207
+ case MindLayoutType.leftBottomIndented:
208
+ inverseDirectionLayout = isHorizontal ? MindLayoutType.rightBottomIndented : MindLayoutType.leftTopIndented;
209
+ break;
210
+ case MindLayoutType.rightTopIndented:
211
+ inverseDirectionLayout = isHorizontal ? MindLayoutType.leftTopIndented : MindLayoutType.rightBottomIndented;
212
+ break;
213
+ case MindLayoutType.leftTopIndented:
214
+ inverseDirectionLayout = isHorizontal ? MindLayoutType.rightTopIndented : MindLayoutType.leftBottomIndented;
215
+ break;
216
+ }
217
+ return inverseDirectionLayout;
218
+ };
219
+ const getLayoutDirection$1 = (root) => {
220
+ const layout = root.layout || getDefaultLayout();
221
+ return LayoutDirectionsMap[layout];
222
+ };
223
+ const getDefaultLayout = () => {
224
+ return MindLayoutType.standard;
225
+ };
226
+ const getAvailableSubLayoutsByLayoutDirections = (directions) => {
227
+ const result = [];
228
+ const reverseDirections = directions.map(getLayoutReverseDirection);
229
+ for (const key in MindLayoutType) {
230
+ const layout = MindLayoutType[key];
231
+ const layoutDirections = LayoutDirectionsMap[layout];
232
+ if (layoutDirections) {
233
+ const hasSameDirection = layoutDirections.some(d => directions.includes(d));
234
+ const hasReverseDirection = layoutDirections.some(r => reverseDirections.includes(r));
235
+ if (hasSameDirection && !hasReverseDirection) {
236
+ result.push(layout);
237
+ }
169
238
  }
170
- parent = findParentElement(parent);
171
239
  }
172
- return getDefaultLayout();
240
+ return result;
241
+ };
242
+ const getLayoutReverseDirection = (layoutDirection) => {
243
+ let reverseDirection = LayoutDirection.right;
244
+ switch (layoutDirection) {
245
+ case LayoutDirection.top:
246
+ reverseDirection = LayoutDirection.bottom;
247
+ break;
248
+ case LayoutDirection.bottom:
249
+ reverseDirection = LayoutDirection.top;
250
+ break;
251
+ case LayoutDirection.right:
252
+ reverseDirection = LayoutDirection.left;
253
+ break;
254
+ case LayoutDirection.left:
255
+ reverseDirection = LayoutDirection.right;
256
+ break;
257
+ }
258
+ return reverseDirection;
259
+ };
260
+ const getRootLayout = (root) => {
261
+ return root.layout || getDefaultLayout();
173
262
  };
174
263
 
175
264
  const getLayoutByElement = (element) => {
@@ -177,17 +266,18 @@ const getLayoutByElement = (element) => {
177
266
  if (layout) {
178
267
  return layout;
179
268
  }
180
- if (AbstractNode.isAbstract(element) ||
181
- (isChildOfAbstract(MindElement.getNode(element)) && isIndentedLayout(layout))) {
182
- const parentLayout = getLayoutParentByElement(element);
183
- return getAbstractLayout(parentLayout);
269
+ const parent = !PlaitMind.isMind(element) && MindElement.getParent(element);
270
+ if (AbstractNode.isAbstract(element) && parent) {
271
+ return getAbstractLayout(getLayoutByElement(parent));
184
272
  }
185
- return getLayoutParentByElement(element);
273
+ if (parent) {
274
+ return getLayoutByElement(parent);
275
+ }
276
+ return getDefaultLayout();
186
277
  };
187
278
 
188
279
  const MindQueries = {
189
280
  getAvailableSubLayoutsByElement,
190
- getLayoutParentByElement,
191
281
  getBranchLayouts,
192
282
  getLayoutByElement,
193
283
  getCorrectLayoutByElement
@@ -224,6 +314,13 @@ const MindElement = {
224
314
  const parent = NODE_TO_PARENT.get(node);
225
315
  return parent;
226
316
  },
317
+ findParent(node) {
318
+ if (PlaitMind.isMind(node)) {
319
+ return undefined;
320
+ }
321
+ const parent = NODE_TO_PARENT.get(node);
322
+ return parent;
323
+ },
227
324
  getRoot(board, element) {
228
325
  const path = PlaitBoard.findPath(board, element);
229
326
  return PlaitNode.get(board, path.slice(0, 1));
@@ -246,6 +343,13 @@ const MindElement = {
246
343
  }
247
344
  return node;
248
345
  },
346
+ findParentNode(element) {
347
+ if (PlaitMind.isMind(element)) {
348
+ return undefined;
349
+ }
350
+ const parent = MindElement.getParent(element);
351
+ return MindElement.getNode(parent);
352
+ },
249
353
  hasEmojis(element) {
250
354
  if (element.data.emojis) {
251
355
  return true;
@@ -258,6 +362,11 @@ const MindElement = {
258
362
  return element.data.emojis;
259
363
  }
260
364
  };
365
+ var MindElementShape;
366
+ (function (MindElementShape) {
367
+ MindElementShape["roundRectangle"] = "round-rectangle";
368
+ MindElementShape["underline"] = "underline";
369
+ })(MindElementShape || (MindElementShape = {}));
261
370
 
262
371
  const MindNode = {
263
372
  get(root, path) {
@@ -270,15 +379,6 @@ const MindNode = {
270
379
  node = node.children[p];
271
380
  }
272
381
  return node;
273
- },
274
- isEquals(node, otherNode) {
275
- const hasSameSize = node.x === otherNode.x && node.y === otherNode.y && node.width === otherNode.width && node.height === otherNode.height;
276
- const hasSameOrigin = node.origin === otherNode.origin;
277
- let hasSameParentOriginChildren = false;
278
- if (node.parent && otherNode.parent) {
279
- hasSameParentOriginChildren = node.parent.origin.children == otherNode.parent.origin.children;
280
- }
281
- return hasSameSize && hasSameOrigin && hasSameParentOriginChildren;
282
382
  }
283
383
  };
284
384
 
@@ -312,109 +412,6 @@ var AbstractResizeState;
312
412
  AbstractResizeState["end"] = "end";
313
413
  })(AbstractResizeState || (AbstractResizeState = {}));
314
414
 
315
- const getBranchDirectionsByLayouts = (branchLayouts) => {
316
- const branchDirections = [];
317
- branchLayouts.forEach(l => {
318
- const directions = LayoutDirectionsMap[l];
319
- directions.forEach(d => {
320
- if (!branchDirections.includes(d) && !branchDirections.includes(getLayoutReverseDirection(d))) {
321
- branchDirections.push(d);
322
- }
323
- });
324
- });
325
- return branchDirections;
326
- };
327
- const isCorrectLayout = (root, layout) => {
328
- const rootLayout = root.layout || getDefaultLayout();
329
- return !getInCorrectLayoutDirection(rootLayout, layout);
330
- };
331
- const isMixedLayout = (parentLayout, layout) => {
332
- return (!isIndentedLayout(parentLayout) && isIndentedLayout(layout)) || (isIndentedLayout(parentLayout) && !isIndentedLayout(layout));
333
- };
334
- const getInCorrectLayoutDirection = (rootLayout, layout) => {
335
- const directions = LayoutDirectionsMap[rootLayout];
336
- const subLayoutDirections = LayoutDirectionsMap[layout];
337
- if (!subLayoutDirections) {
338
- throw new Error(`unexpected layout: ${layout} on correct layout`);
339
- }
340
- return subLayoutDirections.find(d => directions.includes(getLayoutReverseDirection(d)));
341
- };
342
- const correctLayoutByDirection = (layout, direction) => {
343
- const isHorizontal = direction === LayoutDirection.left || direction === LayoutDirection.right ? true : false;
344
- let inverseDirectionLayout = MindLayoutType.standard;
345
- switch (layout) {
346
- case MindLayoutType.left:
347
- inverseDirectionLayout = MindLayoutType.right;
348
- break;
349
- case MindLayoutType.right:
350
- inverseDirectionLayout = MindLayoutType.left;
351
- break;
352
- case MindLayoutType.downward:
353
- inverseDirectionLayout = MindLayoutType.upward;
354
- break;
355
- case MindLayoutType.upward:
356
- inverseDirectionLayout = MindLayoutType.downward;
357
- break;
358
- case MindLayoutType.rightBottomIndented:
359
- inverseDirectionLayout = isHorizontal ? MindLayoutType.leftBottomIndented : MindLayoutType.rightTopIndented;
360
- break;
361
- case MindLayoutType.leftBottomIndented:
362
- inverseDirectionLayout = isHorizontal ? MindLayoutType.rightBottomIndented : MindLayoutType.leftTopIndented;
363
- break;
364
- case MindLayoutType.rightTopIndented:
365
- inverseDirectionLayout = isHorizontal ? MindLayoutType.leftTopIndented : MindLayoutType.rightBottomIndented;
366
- break;
367
- case MindLayoutType.leftTopIndented:
368
- inverseDirectionLayout = isHorizontal ? MindLayoutType.rightTopIndented : MindLayoutType.leftBottomIndented;
369
- break;
370
- }
371
- return inverseDirectionLayout;
372
- };
373
- const getLayoutDirection$1 = (root) => {
374
- const layout = root.layout || getDefaultLayout();
375
- return LayoutDirectionsMap[layout];
376
- };
377
- const getDefaultLayout = () => {
378
- return MindLayoutType.standard;
379
- };
380
- const getAvailableSubLayoutsByLayoutDirections = (directions) => {
381
- const result = [];
382
- const reverseDirections = directions.map(getLayoutReverseDirection);
383
- for (const key in MindLayoutType) {
384
- const layout = MindLayoutType[key];
385
- const layoutDirections = LayoutDirectionsMap[layout];
386
- if (layoutDirections) {
387
- const hasSameDirection = layoutDirections.some(d => directions.includes(d));
388
- const hasReverseDirection = layoutDirections.some(r => reverseDirections.includes(r));
389
- if (hasSameDirection && !hasReverseDirection) {
390
- result.push(layout);
391
- }
392
- }
393
- }
394
- return result;
395
- };
396
- const getLayoutReverseDirection = (layoutDirection) => {
397
- let reverseDirection = LayoutDirection.right;
398
- switch (layoutDirection) {
399
- case LayoutDirection.top:
400
- reverseDirection = LayoutDirection.bottom;
401
- break;
402
- case LayoutDirection.bottom:
403
- reverseDirection = LayoutDirection.top;
404
- break;
405
- case LayoutDirection.right:
406
- reverseDirection = LayoutDirection.left;
407
- break;
408
- case LayoutDirection.left:
409
- reverseDirection = LayoutDirection.right;
410
- break;
411
- }
412
- return reverseDirection;
413
- };
414
- const getRootLayout = (root) => {
415
- return root.layout || getDefaultLayout();
416
- };
417
-
418
415
  function enterNodeEditing(element) {
419
416
  const component = ELEMENT_TO_COMPONENT.get(element);
420
417
  component.startEditText(false, false);
@@ -444,13 +441,137 @@ const separateChildren = (parentElement) => {
444
441
  return { leftChildren, rightChildren };
445
442
  };
446
443
  const isSetAbstract = (element) => {
447
- return !!getCorrespondingAbstract(element);
444
+ const parent = MindElement.getParent(element);
445
+ return !!getCorrespondingAbstract(parent, element);
448
446
  };
449
447
  const canSetAbstract = (element) => {
450
448
  return !PlaitElement.isRootElement(element) && !AbstractNode.isAbstract(element) && !isSetAbstract(element);
451
449
  };
452
- const setAbstract = (board, elements) => {
453
- let elementGroup = filterChildElement(elements);
450
+ const getCorrespondingAbstract = (parent, element) => {
451
+ if (!parent)
452
+ return undefined;
453
+ const elementIndex = parent.children.indexOf(element);
454
+ return parent.children.find(child => {
455
+ return AbstractNode.isAbstract(child) && elementIndex >= child.start && elementIndex <= child.end;
456
+ });
457
+ };
458
+ const getBehindAbstracts = (parent, element) => {
459
+ const index = parent.children.indexOf(element);
460
+ return parent.children.filter(child => AbstractNode.isAbstract(child) && child.start > index);
461
+ };
462
+ const getOverallAbstracts = (board, elements) => {
463
+ const overallAbstracts = [];
464
+ elements
465
+ .filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
466
+ .forEach(value => {
467
+ const parent = MindElement.getParent(value);
468
+ const abstract = getCorrespondingAbstract(parent, value);
469
+ if (abstract && overallAbstracts.indexOf(abstract) === -1) {
470
+ const { start, end } = abstract;
471
+ const parent = MindElement.getParent(value);
472
+ const isOverall = parent.children.slice(start, end + 1).every(includedElement => elements.indexOf(includedElement) > -1);
473
+ if (isOverall) {
474
+ overallAbstracts.push(abstract);
475
+ }
476
+ }
477
+ });
478
+ return overallAbstracts;
479
+ };
480
+ const insertElementHandleAbstract = (board, path,
481
+ //由此区分拖拽和新增到概要概括最后一个节点
482
+ isExtendPreviousNode = true, abstractRefs = new Map()) => {
483
+ const parent = PlaitNode.parent(board, path);
484
+ const hasPreviousNode = path[path.length - 1] !== 0;
485
+ let behindAbstracts;
486
+ if (!hasPreviousNode) {
487
+ behindAbstracts = parent.children.filter(child => AbstractNode.isAbstract(child));
488
+ }
489
+ else {
490
+ const selectedElement = PlaitNode.get(board, Path.previous(path));
491
+ behindAbstracts = getBehindAbstracts(parent, selectedElement);
492
+ }
493
+ if (behindAbstracts.length) {
494
+ behindAbstracts.forEach(abstract => {
495
+ let newProperties = abstractRefs.get(abstract);
496
+ if (!newProperties) {
497
+ newProperties = { start: 0, end: 0 };
498
+ abstractRefs.set(abstract, newProperties);
499
+ }
500
+ newProperties.start = newProperties.start + 1;
501
+ newProperties.end = newProperties.end + 1;
502
+ });
503
+ }
504
+ if (!hasPreviousNode) {
505
+ return abstractRefs;
506
+ }
507
+ const selectedElement = PlaitNode.get(board, Path.previous(path));
508
+ const correspondingAbstract = getCorrespondingAbstract(parent, selectedElement);
509
+ const isDragToLast = !isExtendPreviousNode && correspondingAbstract && correspondingAbstract.end === path[path.length - 1] - 1;
510
+ if (correspondingAbstract && !isDragToLast) {
511
+ let newProperties = abstractRefs.get(correspondingAbstract);
512
+ if (!newProperties) {
513
+ newProperties = { start: 0, end: 0 };
514
+ abstractRefs.set(correspondingAbstract, newProperties);
515
+ }
516
+ newProperties.end = newProperties.end + 1;
517
+ }
518
+ return abstractRefs;
519
+ };
520
+ const deleteElementHandleAbstract = (board, deletableElements, abstractRefs = new Map()) => {
521
+ deletableElements.forEach(node => {
522
+ if (!PlaitMind.isMind(node)) {
523
+ const parent = PlaitNode.parent(board, PlaitBoard.findPath(board, node));
524
+ const behindAbstracts = getBehindAbstracts(parent, node).filter(abstract => !deletableElements.includes(abstract));
525
+ if (behindAbstracts.length) {
526
+ behindAbstracts.forEach(abstract => {
527
+ let newProperties = abstractRefs.get(abstract);
528
+ if (!newProperties) {
529
+ newProperties = { start: 0, end: 0 };
530
+ abstractRefs.set(abstract, newProperties);
531
+ }
532
+ newProperties.start = newProperties.start - 1;
533
+ newProperties.end = newProperties.end - 1;
534
+ });
535
+ }
536
+ const correspondingAbstract = getCorrespondingAbstract(parent, node);
537
+ if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
538
+ let newProperties = abstractRefs.get(correspondingAbstract);
539
+ if (!newProperties) {
540
+ newProperties = { start: 0, end: 0 };
541
+ abstractRefs.set(correspondingAbstract, newProperties);
542
+ }
543
+ newProperties.end = newProperties.end - 1;
544
+ }
545
+ }
546
+ });
547
+ return abstractRefs;
548
+ };
549
+
550
+ const setAbstractsByRefs = (board, abstractRefs) => {
551
+ abstractRefs.forEach((newProperty, element) => {
552
+ const start = element.start + newProperty.start;
553
+ const end = element.end + newProperty.end;
554
+ const path = PlaitBoard.findPath(board, element);
555
+ if (start > end) {
556
+ Transforms.removeNode(board, path);
557
+ }
558
+ else {
559
+ Transforms.setNode(board, { start, end }, path);
560
+ }
561
+ });
562
+ };
563
+ const setAbstractByStandardLayout = (board, element) => {
564
+ const rightNodeCount = element.rightNodeCount;
565
+ const abstract = element.children.find(child => {
566
+ return AbstractNode.isAbstract(child) && child.end >= rightNodeCount && child.start < rightNodeCount;
567
+ });
568
+ if (abstract) {
569
+ const path = PlaitBoard.findPath(board, abstract);
570
+ Transforms.setNode(board, { end: rightNodeCount - 1 }, path);
571
+ }
572
+ };
573
+ const insertAbstract = (board, elements) => {
574
+ let elementGroup = getFirstLevelElement(elements);
454
575
  const { parentElements, abstractIncludedGroups } = divideElementByParent(elementGroup);
455
576
  abstractIncludedGroups.forEach((group, index) => {
456
577
  const groupParent = parentElements[index];
@@ -477,71 +598,121 @@ const setAbstractByElements = (board, groupParent, group) => {
477
598
  insertAbstractNode(board, path, start, end);
478
599
  }
479
600
  };
480
- const insertAbstractNode = (board, path, start, end) => {
481
- const mindElement = createMindElement('概要', 28, 20, {
482
- strokeColor: GRAY_COLOR,
483
- branchColor: GRAY_COLOR
484
- });
485
- mindElement.start = start;
486
- mindElement.end = end;
487
- Transforms.insertNode(board, mindElement, path);
488
- };
489
- const handleAbstractIncluded = (board, element) => {
490
- const rightNodeCount = element.rightNodeCount;
491
- const abstract = element.children.find(child => {
492
- return AbstractNode.isAbstract(child) && child.end >= rightNodeCount && child.start < rightNodeCount;
493
- });
494
- if (abstract) {
495
- const path = PlaitBoard.findPath(board, abstract);
496
- Transforms.setNode(board, { end: rightNodeCount - 1 }, path);
601
+ const insertAbstractNode = (board, path, start, end) => {
602
+ const mindElement = createMindElement('概要', 28, 20, {
603
+ strokeColor: DefaultAbstractNodeStyle.strokeColor,
604
+ strokeWidth: DefaultAbstractNodeStyle.branchWidth,
605
+ branchColor: DefaultAbstractNodeStyle.branchColor,
606
+ branchWidth: DefaultAbstractNodeStyle.branchWidth
607
+ });
608
+ mindElement.start = start;
609
+ mindElement.end = end;
610
+ Transforms.insertNode(board, mindElement, path);
611
+ };
612
+
613
+ const setLayout = (board, layout, path) => {
614
+ correctLogicLayoutNode(board, layout, path);
615
+ const element = PlaitNode.get(board, path);
616
+ if (PlaitMind.isMind(element) && isStandardLayout(layout)) {
617
+ MindTransforms.setAbstractByStandardLayout(board, element);
618
+ }
619
+ Transforms.setNode(board, { layout }, path);
620
+ };
621
+ const correctLogicLayoutNode = (board, layout, path) => {
622
+ var _a;
623
+ const node = PlaitNode.get(board, path);
624
+ if (node && layout) {
625
+ (_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach((value, index) => {
626
+ var _a;
627
+ if (value.layout) {
628
+ if ((isHorizontalLogicLayout(layout) && isVerticalLogicLayout(value.layout)) ||
629
+ (isVerticalLogicLayout(layout) && isHorizontalLogicLayout(value.layout))) {
630
+ Transforms.setNode(board, { layout: null }, [...path, index]);
631
+ }
632
+ if ((_a = value.children) === null || _a === void 0 ? void 0 : _a.length) {
633
+ correctLogicLayoutNode(board, layout, [...path, index]);
634
+ }
635
+ }
636
+ });
637
+ }
638
+ };
639
+
640
+ const setTopic = (board, element, topic, width, height) => {
641
+ const newElement = {
642
+ data: { topic },
643
+ width: width < NODE_MIN_WIDTH * board.viewport.zoom ? NODE_MIN_WIDTH : width / board.viewport.zoom,
644
+ height: height / board.viewport.zoom
645
+ };
646
+ if (MindElement.hasEmojis(element)) {
647
+ newElement.data.emojis = element.data.emojis;
497
648
  }
649
+ const path = PlaitBoard.findPath(board, element);
650
+ Transforms.setNode(board, newElement, path);
498
651
  };
499
- const getCorrespondingAbstract = (element) => {
500
- const parent = MindElement.getParent(element);
501
- if (!parent)
502
- return undefined;
503
- const elementIndex = parent.children.indexOf(element);
504
- return parent.children.find(child => {
505
- return AbstractNode.isAbstract(child) && elementIndex >= child.start && elementIndex <= child.end;
506
- });
652
+ const setTopicSize = (board, element, width, height) => {
653
+ const newElement = {
654
+ width: width < NODE_MIN_WIDTH * board.viewport.zoom ? NODE_MIN_WIDTH : width / board.viewport.zoom,
655
+ height: height / board.viewport.zoom
656
+ };
657
+ const path = PlaitBoard.findPath(board, element);
658
+ Transforms.setNode(board, newElement, path);
507
659
  };
508
- const getBehindAbstracts = (element) => {
509
- const parent = MindElement.getParent(element);
510
- const index = parent.children.indexOf(element);
511
- return parent.children.filter(child => AbstractNode.isAbstract(child) && child.start > index);
660
+ const addEmoji = (board, element, emojiItem) => {
661
+ const emojis = element.data.emojis || [];
662
+ const newEmojis = [...emojis];
663
+ newEmojis.push(emojiItem);
664
+ const newElement = {
665
+ data: { topic: element.data.topic, emojis: newEmojis }
666
+ };
667
+ const path = PlaitBoard.findPath(board, element);
668
+ Transforms.setNode(board, newElement, path);
512
669
  };
513
- const insertSiblingElementHandleAbstract = (board, selectedElement) => {
514
- const abstract = getCorrespondingAbstract(selectedElement);
515
- if (abstract) {
516
- PlaitBoard.findPath(board, abstract);
517
- Transforms.setNode(board, { end: abstract.end + 1 }, PlaitBoard.findPath(board, abstract));
518
- }
519
- const abstracts = getBehindAbstracts(selectedElement);
520
- if (abstracts.length) {
521
- moveAbstractPosition(board, abstracts, 1);
670
+ const removeEmoji = (board, element, emojiItem) => {
671
+ const emojis = element.data.emojis.filter(value => value !== emojiItem);
672
+ const newElement = {
673
+ data: { topic: element.data.topic }
674
+ };
675
+ if (emojis.length > 0) {
676
+ newElement.data.emojis = emojis;
522
677
  }
678
+ const path = PlaitBoard.findPath(board, element);
679
+ Transforms.setNode(board, newElement, path);
523
680
  };
524
- const moveAbstractPosition = (board, abstracts, step) => {
525
- abstracts.forEach(abstract => {
526
- Transforms.setNode(board, { start: abstract.start + step, end: abstract.end + step }, PlaitBoard.findPath(board, abstract));
681
+ const replaceEmoji = (board, element, oldEmoji, newEmoji) => {
682
+ const newElement = {
683
+ data: { topic: element.data.topic }
684
+ };
685
+ const newEmojis = element.data.emojis.map(value => {
686
+ if (value === oldEmoji) {
687
+ return newEmoji;
688
+ }
689
+ return value;
527
690
  });
691
+ newElement.data.emojis = newEmojis;
692
+ const path = PlaitBoard.findPath(board, element);
693
+ Transforms.setNode(board, newElement, path);
694
+ };
695
+
696
+ const MindTransforms = {
697
+ setLayout,
698
+ setTopic,
699
+ setTopicSize,
700
+ addEmoji,
701
+ removeEmoji,
702
+ replaceEmoji,
703
+ insertAbstract,
704
+ setAbstractsByRefs,
705
+ setAbstractByStandardLayout
528
706
  };
529
707
 
530
- function findParentElement(element) {
531
- const component = PlaitElement.getComponent(element);
532
- if (component && component.parent) {
533
- return component.parent.origin;
534
- }
535
- return undefined;
536
- }
537
708
  function findUpElement(element) {
538
709
  let branch;
539
710
  let root = element;
540
- let parent = findParentElement(element);
711
+ let parent = MindElement.findParent(element);
541
712
  while (parent) {
542
713
  branch = root;
543
714
  root = parent;
544
- parent = findParentElement(parent);
715
+ parent = MindElement.findParent(parent);
545
716
  }
546
717
  return { root, branch };
547
718
  }
@@ -552,16 +723,16 @@ const getChildrenCount = (element) => {
552
723
  return count + element.children.length;
553
724
  };
554
725
  const isChildElement = (origin, child) => {
555
- let parent = findParentElement(child);
726
+ let parent = MindElement.findParent(child);
556
727
  while (parent) {
557
728
  if (parent === origin) {
558
729
  return true;
559
730
  }
560
- parent = findParentElement(parent);
731
+ parent = MindElement.findParent(parent);
561
732
  }
562
733
  return false;
563
734
  };
564
- const filterChildElement = (elements) => {
735
+ const getFirstLevelElement = (elements) => {
565
736
  let result = [];
566
737
  elements.forEach(element => {
567
738
  const isChild = elements.some(node => {
@@ -646,7 +817,7 @@ const changeRightNodeCount = (board, parentPath, changeNumber) => {
646
817
  }, parentPath);
647
818
  };
648
819
  const shouldChangeRightNodeCount = (selectedElement) => {
649
- const parentElement = findParentElement(selectedElement);
820
+ const parentElement = MindElement.findParent(selectedElement);
650
821
  if (parentElement) {
651
822
  const nodeIndex = parentElement.children.findIndex(item => item.id === selectedElement.id);
652
823
  if (parentElement.isRoot &&
@@ -659,13 +830,13 @@ const shouldChangeRightNodeCount = (selectedElement) => {
659
830
  return false;
660
831
  };
661
832
  const createDefaultMindMapElement = (point, rightNodeCount, layout) => {
662
- const root = createMindElement('思维导图', 72, ROOT_DEFAULT_HEIGHT, { shape: MindNodeShape.roundRectangle, layout });
833
+ const root = createMindElement('思维导图', 72, ROOT_DEFAULT_HEIGHT, { shape: MindElementShape.roundRectangle, layout });
663
834
  root.rightNodeCount = rightNodeCount;
664
835
  root.isRoot = true;
665
836
  root.type = 'mindmap';
666
837
  root.points = [point];
667
838
  const children = [1, 1, 1].map(() => {
668
- return createMindElement('新建节点', 56, TEXT_DEFAULT_HEIGHT, { shape: MindNodeShape.roundRectangle });
839
+ return createMindElement('新建节点', 56, TEXT_DEFAULT_HEIGHT, { shape: MindElementShape.roundRectangle });
669
840
  });
670
841
  root.children = children;
671
842
  return root;
@@ -702,11 +873,14 @@ const createMindElement = (text, width, height, options) => {
702
873
  if (options.branchColor) {
703
874
  newElement.branchColor = options.branchColor;
704
875
  }
876
+ if (!isNullOrUndefined(options.branchWidth)) {
877
+ newElement.branchWidth = options.branchWidth;
878
+ }
705
879
  return newElement;
706
880
  };
707
881
  // layoutLevel 用来表示插入兄弟节点还是子节点
708
882
  const insertMindElement = (board, inheritNode, path) => {
709
- let fill, strokeColor, strokeWidth, shape = MindNodeShape.roundRectangle;
883
+ let fill, strokeColor, strokeWidth, shape = MindElementShape.roundRectangle;
710
884
  if (!inheritNode.isRoot) {
711
885
  fill = inheritNode.fill;
712
886
  strokeColor = inheritNode.strokeColor;
@@ -729,63 +903,23 @@ const findLastChild = (child) => {
729
903
  return result;
730
904
  };
731
905
  const deleteSelectedELements = (board, selectedElements) => {
906
+ const deletableElements = getFirstLevelElement(selectedElements).reverse();
907
+ const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
908
+ MindTransforms.setAbstractsByRefs(board, abstractRefs);
732
909
  //翻转,从下到上修改,防止找不到 path
733
- const deletableElements = filterChildElement(selectedElements).reverse();
734
- const relativeAbstracts = [];
735
- const accumulativeProperties = new WeakMap();
736
- deletableElements.forEach(node => {
737
- if (!PlaitMind.isMind(node)) {
738
- const behindAbstracts = getBehindAbstracts(node).filter(abstract => !deletableElements.includes(abstract));
739
- if (behindAbstracts.length) {
740
- behindAbstracts.forEach(abstract => {
741
- let newProperties = accumulativeProperties.get(abstract);
742
- if (!newProperties) {
743
- newProperties = { start: abstract.start, end: abstract.end };
744
- accumulativeProperties.set(abstract, newProperties);
745
- relativeAbstracts.push(abstract);
746
- }
747
- newProperties.start = newProperties.start - 1;
748
- newProperties.end = newProperties.end - 1;
749
- });
750
- }
751
- const correspondingAbstract = getCorrespondingAbstract(node);
752
- if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
753
- let newProperties = accumulativeProperties.get(correspondingAbstract);
754
- if (!newProperties) {
755
- newProperties = { start: correspondingAbstract.start, end: correspondingAbstract.end };
756
- accumulativeProperties.set(correspondingAbstract, newProperties);
757
- relativeAbstracts.push(correspondingAbstract);
758
- }
759
- newProperties.end = newProperties.end - 1;
760
- }
761
- }
762
- });
763
- const abstractHandles = relativeAbstracts.map(value => {
764
- const newProperties = accumulativeProperties.get(value);
765
- if (newProperties) {
766
- const path = PlaitBoard.findPath(board, value);
767
- return () => {
768
- if (newProperties.start > newProperties.end) {
769
- Transforms.removeNode(board, path);
770
- }
771
- else {
772
- Transforms.setNode(board, newProperties, path);
773
- }
774
- };
775
- }
776
- return () => { };
777
- });
778
- const deletableHandles = deletableElements.map(node => {
779
- const path = PlaitBoard.findPath(board, node);
910
+ deletableElements
911
+ .map(element => {
912
+ const path = PlaitBoard.findPath(board, element);
780
913
  return () => {
781
- if (shouldChangeRightNodeCount(node)) {
782
- changeRightNodeCount(board, path.slice(0, path.length - 1), -1);
914
+ if (shouldChangeRightNodeCount(element)) {
915
+ changeRightNodeCount(board, path.slice(0, 1), -1);
783
916
  }
784
917
  Transforms.removeNode(board, path);
785
918
  };
919
+ })
920
+ .forEach(action => {
921
+ action();
786
922
  });
787
- abstractHandles.forEach(action => action());
788
- deletableHandles.forEach(action => action());
789
923
  };
790
924
  const divideElementByParent = (elements) => {
791
925
  const abstractIncludedGroups = [];
@@ -804,65 +938,70 @@ const divideElementByParent = (elements) => {
804
938
  return { parentElements, abstractIncludedGroups };
805
939
  };
806
940
 
807
- const getNodeShapeByElement = (element) => {
808
- let nodeShape = element.shape;
809
- if (nodeShape) {
810
- return nodeShape;
941
+ const getAvailableProperty = (board, element, propertyKey) => {
942
+ const ancestors = MindElement.getAncestors(board, element);
943
+ ancestors.unshift(element);
944
+ const ancestor = ancestors.find(value => value[propertyKey]);
945
+ if (ancestor) {
946
+ return ancestor[propertyKey];
811
947
  }
812
- let parent = findParentElement(element);
813
- while (parent) {
814
- if (parent.shape) {
815
- return parent.shape;
816
- }
817
- parent = findParentElement(parent);
948
+ else {
949
+ return undefined;
818
950
  }
819
- return MindNodeShape.roundRectangle;
820
951
  };
821
952
 
953
+ /**
954
+ * Processing of branch color, width, style, etc. of the mind node
955
+ */
822
956
  const getBranchColorByMindElement = (board, element) => {
823
- const ancestors = MindElement.getAncestors(board, element);
824
- ancestors.unshift(element);
825
- const ancestor = ancestors.find(value => value.branchColor);
826
- if (ancestor && ancestor.branchColor) {
827
- return ancestor.branchColor;
828
- }
829
- const root = ancestors[ancestors.length - 1];
830
- const branch = ancestors[ancestors.length - 2];
831
- if (branch) {
832
- const index = root.children.indexOf(branch);
833
- const length = COLORS.length;
834
- const remainder = index % length;
835
- return COLORS[remainder];
957
+ const branchColor = getAvailableProperty(board, element, 'branchColor');
958
+ return branchColor || getDefaultBranchColor(board, element);
959
+ };
960
+ const getBranchWidthByMindElement = (board, element) => {
961
+ const branchWidth = getAvailableProperty(board, element, 'branchWidth');
962
+ return branchWidth || BRANCH_WIDTH;
963
+ };
964
+ const getAbstractBranchWidth = (board, element) => {
965
+ if (!isNullOrUndefined(element.branchWidth)) {
966
+ return element.branchWidth;
836
967
  }
837
- else {
838
- throw new Error('root element should not have branch color');
968
+ return DefaultAbstractNodeStyle.branchWidth;
969
+ };
970
+ const getAbstractBranchColor = (board, element) => {
971
+ if (element.branchColor) {
972
+ return element.branchColor;
839
973
  }
974
+ return DefaultAbstractNodeStyle.branchColor;
840
975
  };
841
976
  const getNextBranchColor = (root) => {
842
977
  const index = root.children.length;
843
- const length = COLORS.length;
978
+ return getDefaultBranchColorByIndex(index);
979
+ };
980
+ const getDefaultBranchColor = (board, element) => {
981
+ const path = PlaitBoard.findPath(board, element);
982
+ return getDefaultBranchColorByIndex(path[1]);
983
+ };
984
+ const getDefaultBranchColorByIndex = (index) => {
985
+ const length = BRANCH_COLORS.length;
844
986
  const remainder = index % length;
845
- return COLORS[remainder];
987
+ return BRANCH_COLORS[remainder];
846
988
  };
847
989
 
848
990
  const getStrokeByMindElement = (board, element) => {
991
+ if (PlaitMind.isMind(element)) {
992
+ return element.strokeColor || DefaultRootStyle.strokeColor;
993
+ }
849
994
  const ancestors = MindElement.getAncestors(board, element);
850
995
  ancestors.unshift(element);
851
996
  const ancestor = ancestors.find(value => value.strokeColor);
852
- if (ancestor && ancestor.strokeColor) {
997
+ if (ancestor && ancestor.strokeColor && !PlaitMind.isMind(ancestor)) {
853
998
  return ancestor.strokeColor;
854
999
  }
855
- const root = ancestors[ancestors.length - 1];
856
- const branch = ancestors[ancestors.length - 2];
857
- if (branch) {
858
- const index = root.children.indexOf(branch);
859
- const length = COLORS.length;
860
- const remainder = index % length;
861
- return COLORS[remainder];
862
- }
863
- else {
864
- return ROOT_NODE_STROKE;
865
- }
1000
+ return getDefaultBranchColor(board, element);
1001
+ };
1002
+ const getShapeByElement = (board, element) => {
1003
+ const shape = getAvailableProperty(board, element, 'shape');
1004
+ return shape || MindElementShape.roundRectangle;
866
1005
  };
867
1006
 
868
1007
  function isVirtualKey(e) {
@@ -880,7 +1019,7 @@ function isVirtualKey(e) {
880
1019
  function drawLink(board, node, child, defaultStroke = null, isHorizontal = true, needDrawUnderline = true) {
881
1020
  var _a;
882
1021
  let beginX, beginY, endX, endY, beginNode = node, endNode = child;
883
- const layout = MindQueries.getCorrectLayoutByElement(node.origin);
1022
+ const layout = MindQueries.getCorrectLayoutByElement(board, node.origin);
884
1023
  if (isHorizontal) {
885
1024
  if (!isChildRight(node, child)) {
886
1025
  beginNode = child;
@@ -892,7 +1031,7 @@ function drawLink(board, node, child, defaultStroke = null, isHorizontal = true,
892
1031
  endY = endNode.y + endNode.height / 2;
893
1032
  if (node.parent &&
894
1033
  isIndentedLayout(MindQueries.getLayoutByElement((_a = node.parent) === null || _a === void 0 ? void 0 : _a.origin)) &&
895
- getNodeShapeByElement(node.origin) === MindNodeShape.underline) {
1034
+ getShapeByElement(board, node.origin) === MindElementShape.underline) {
896
1035
  if (isChildRight(node, child)) {
897
1036
  beginY = node.y + node.height - node.vGap;
898
1037
  }
@@ -936,7 +1075,7 @@ function drawLink(board, node, child, defaultStroke = null, isHorizontal = true,
936
1075
  [endX - (beginNode.hGap + endNode.hGap) / 2, endY],
937
1076
  [endX, endY]
938
1077
  ];
939
- const shape = getNodeShapeByElement(child.origin);
1078
+ const shape = getShapeByElement(board, child.origin);
940
1079
  if (!node.origin.isRoot) {
941
1080
  if (node.x > child.x) {
942
1081
  curve = [
@@ -967,7 +1106,7 @@ function drawLink(board, node, child, defaultStroke = null, isHorizontal = true,
967
1106
  curve = [...line, ...curve];
968
1107
  }
969
1108
  }
970
- if (needDrawUnderline && shape === MindNodeShape.underline) {
1109
+ if (needDrawUnderline && shape === MindElementShape.underline) {
971
1110
  if (child.left) {
972
1111
  const underline = [
973
1112
  [beginX - (beginNode.width - beginNode.hGap * 2), beginY],
@@ -1036,15 +1175,16 @@ const drawPlaceholderDropNodeG = (board, dropTarget, fakeDropNodeG) => {
1036
1175
  if (dropTarget.detectResult && ['right', 'left'].includes(dropTarget.detectResult)) {
1037
1176
  drawStraightDropNodeG(board, targetRect, dropTarget.detectResult, targetComponent, fakeDropNodeG);
1038
1177
  }
1039
- if (targetComponent.parent && dropTarget.detectResult && ['top', 'bottom'].includes(dropTarget.detectResult)) {
1040
- const parentComponent = PlaitElement.getComponent(targetComponent.parent.origin);
1178
+ const targetParent = MindElement.findParent(targetComponent.element);
1179
+ if (targetParent && dropTarget.detectResult && ['top', 'bottom'].includes(dropTarget.detectResult)) {
1180
+ const parentComponent = PlaitElement.getComponent(targetParent);
1041
1181
  const targetIndex = parentComponent.node.origin.children.indexOf(targetComponent.node.origin);
1042
1182
  drawCurvePlaceholderDropNodeG(board, targetRect, dropTarget.detectResult, targetIndex, targetComponent, parentComponent, fakeDropNodeG);
1043
1183
  }
1044
1184
  };
1045
1185
  const drawCurvePlaceholderDropNodeG = (board, targetRect, detectResult, targetIndex, targetComponent, parentComponent, fakeDropNodeG) => {
1046
- const parentNodeLayout = MindQueries.getCorrectLayoutByElement(parentComponent.node.origin);
1047
- const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.parent.origin);
1186
+ const parentNodeLayout = MindQueries.getCorrectLayoutByElement(board, parentComponent.node.origin);
1187
+ const layout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.parent.origin);
1048
1188
  const strokeWidth = targetComponent.node.origin.branchWidth ? targetComponent.node.origin.branchWidth : STROKE_WIDTH;
1049
1189
  let fakeX = targetComponent.node.x, fakeY = targetRect.y - 30, fakeRectangleStartX = targetRect.x, fakeRectangleEndX = targetRect.x + 30, fakeRectangleStartY = fakeY, fakeRectangleEndY = fakeRectangleStartY + 12, width = 30;
1050
1190
  if (isLeftLayout(layout)) {
@@ -1079,7 +1219,7 @@ const drawCurvePlaceholderDropNodeG = (board, targetRect, detectResult, targetIn
1079
1219
  }
1080
1220
  if (isVerticalLogicLayout(layout)) {
1081
1221
  parentComponent = targetComponent;
1082
- targetComponent = PlaitElement.getComponent(targetComponent.parent.origin);
1222
+ targetComponent = PlaitElement.getComponent(MindElement.getParent(targetComponent.element));
1083
1223
  fakeX = parentComponent.node.x;
1084
1224
  width = parentComponent.node.width;
1085
1225
  const vGap = BASE * 6 + strokeWidth;
@@ -1175,8 +1315,8 @@ const drawStraightDropNodeG = (board, targetRect, detectResult, targetComponent,
1175
1315
  height,
1176
1316
  strokeWidth
1177
1317
  };
1178
- const parentLayout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
1179
- const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
1318
+ const parentLayout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
1319
+ const layout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin);
1180
1320
  if (!isMixedLayout(parentLayout, layout)) {
1181
1321
  // 构造一条直线
1182
1322
  let linePoints = [
@@ -1200,7 +1340,7 @@ const drawStraightDropNodeG = (board, targetRect, detectResult, targetComponent,
1200
1340
  * b. 最后一个节点的右侧:固定值(来源于 getMainAxle,第二级节点:BASE * 8,其他 BASE * 3 + strokeWidth / 2);
1201
1341
  */
1202
1342
  fakeY = targetComponent.node.y;
1203
- const parentComponent = PlaitElement.getComponent(targetComponent.parent.origin);
1343
+ const parentComponent = PlaitElement.getComponent(MindElement.getParent(targetComponent.element));
1204
1344
  const targetIndex = parentComponent.node.origin.children.indexOf(targetComponent.node.origin);
1205
1345
  if (detectResult === 'left') {
1206
1346
  let offsetX = 0;
@@ -1386,29 +1526,29 @@ const directionDetector = (targetNode, centerPoint) => {
1386
1526
  return null;
1387
1527
  };
1388
1528
 
1389
- const directionCorrector = (node, detectResults) => {
1390
- if (!node.origin.isRoot) {
1391
- const parentlayout = MindQueries.getCorrectLayoutByElement(node === null || node === void 0 ? void 0 : node.parent.origin);
1392
- if (isStandardLayout(parentlayout)) {
1529
+ const directionCorrector = (board, node, detectResults) => {
1530
+ if (!node.origin.isRoot && !AbstractNode.isAbstract(node.origin)) {
1531
+ const parentLayout = MindQueries.getCorrectLayoutByElement(board, node === null || node === void 0 ? void 0 : node.parent.origin);
1532
+ if (isStandardLayout(parentLayout)) {
1393
1533
  const idx = node.parent.children.findIndex(x => x === node);
1394
1534
  const isLeft = idx >= (node.parent.origin.rightNodeCount || 0);
1395
1535
  return getAllowedDirection(detectResults, [isLeft ? 'right' : 'left']);
1396
1536
  }
1397
- if (isLeftLayout(parentlayout)) {
1537
+ if (isLeftLayout(parentLayout)) {
1398
1538
  return getAllowedDirection(detectResults, ['right']);
1399
1539
  }
1400
- if (isRightLayout(parentlayout)) {
1540
+ if (isRightLayout(parentLayout)) {
1401
1541
  return getAllowedDirection(detectResults, ['left']);
1402
1542
  }
1403
- if (parentlayout === MindLayoutType.upward) {
1543
+ if (parentLayout === MindLayoutType.upward) {
1404
1544
  return getAllowedDirection(detectResults, ['bottom']);
1405
1545
  }
1406
- if (parentlayout === MindLayoutType.downward) {
1546
+ if (parentLayout === MindLayoutType.downward) {
1407
1547
  return getAllowedDirection(detectResults, ['top']);
1408
1548
  }
1409
1549
  }
1410
1550
  else {
1411
- const layout = MindQueries.getCorrectLayoutByElement(node === null || node === void 0 ? void 0 : node.origin);
1551
+ const layout = MindQueries.getCorrectLayoutByElement(board, node === null || node === void 0 ? void 0 : node.origin);
1412
1552
  if (isStandardLayout(layout)) {
1413
1553
  return getAllowedDirection(detectResults, ['top', 'bottom']);
1414
1554
  }
@@ -1439,17 +1579,18 @@ const getAllowedDirection = (detectResults, illegalDirections) => {
1439
1579
  };
1440
1580
 
1441
1581
  /* 根据布局调整 target 以及 direction */
1442
- const readjustmentDropTarget = (dropTarget) => {
1582
+ const readjustmentDropTarget = (board, dropTarget) => {
1443
1583
  const { target, detectResult } = dropTarget;
1444
1584
  const newDropTarget = { target, detectResult };
1445
1585
  const targetComponent = PlaitElement.getComponent(target);
1446
1586
  if (targetComponent.node.children.length > 0 && dropTarget.detectResult) {
1447
- const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
1448
- const parentLayout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
1587
+ const layout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin);
1588
+ const parentLayout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
1589
+ const children = getNonAbstractChildren(targetComponent.node);
1449
1590
  if (['right', 'left'].includes(dropTarget.detectResult)) {
1450
1591
  if (!isMixedLayout(parentLayout, layout)) {
1451
1592
  if (targetComponent.node.origin.isRoot) {
1452
- const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
1593
+ const layout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin);
1453
1594
  // 标准布局,根节点
1454
1595
  if (isStandardLayout(layout)) {
1455
1596
  const rightNodeCount = targetComponent.node.origin.rightNodeCount;
@@ -1483,14 +1624,14 @@ const readjustmentDropTarget = (dropTarget) => {
1483
1624
  return newDropTarget;
1484
1625
  }
1485
1626
  // 剩下是水平布局的默认情况:插入最后一个子节点的下方
1486
- const lastChildNodeIndex = targetComponent.node.children.length - 1;
1627
+ const lastChildNodeIndex = children.length - 1;
1487
1628
  newDropTarget.target = targetComponent.node.children[lastChildNodeIndex].origin;
1488
1629
  newDropTarget.detectResult = 'bottom';
1489
1630
  }
1490
1631
  else {
1491
1632
  // 处理左右布局下的混合布局
1492
1633
  if ([MindLayoutType.left, MindLayoutType.right].includes(parentLayout)) {
1493
- const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
1634
+ const layout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin);
1494
1635
  if (isIndentedLayout(layout)) {
1495
1636
  newDropTarget.target = targetComponent.node.children[0].origin;
1496
1637
  newDropTarget.detectResult = isTopLayout(layout) ? 'bottom' : 'top';
@@ -1507,9 +1648,9 @@ const readjustmentDropTarget = (dropTarget) => {
1507
1648
  return newDropTarget;
1508
1649
  }
1509
1650
  // 上下布局,插到右边
1510
- const parentLayout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
1651
+ const parentLayout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
1511
1652
  if (isVerticalLogicLayout(parentLayout)) {
1512
- const lastChildNodeIndex = targetComponent.node.children.length - 1;
1653
+ const lastChildNodeIndex = children.length - 1;
1513
1654
  newDropTarget.target = targetComponent.node.children[lastChildNodeIndex].origin;
1514
1655
  newDropTarget.detectResult = 'right';
1515
1656
  return newDropTarget;
@@ -1606,7 +1747,7 @@ const getLocationScope = (board, handlePosition, parentChildren, element, parent
1606
1747
  }
1607
1748
  };
1608
1749
  const getHitAbstractHandle = (board, element, point) => {
1609
- const nodeLayout = MindQueries.getCorrectLayoutByElement(element);
1750
+ const nodeLayout = MindQueries.getCorrectLayoutByElement(board, element);
1610
1751
  const isHorizontal = isHorizontalLayout(nodeLayout);
1611
1752
  const parentElement = MindElement.getParent(element);
1612
1753
  const includedElements = parentElement.children.slice(element.start, element.end + 1);
@@ -1693,24 +1834,25 @@ function handleTouchedAbstract(board, touchedAbstract, endPoint) {
1693
1834
  }
1694
1835
 
1695
1836
  function drawIndentedLink(board, node, child, defaultStroke = null, needDrawUnderline = true) {
1696
- const isUnderlineShap = getNodeShapeByElement(child.origin) === MindNodeShape.underline;
1837
+ const branchWidth = getBranchWidthByMindElement(board, child.origin);
1838
+ const branchColor = defaultStroke || getBranchColorByMindElement(board, child.origin);
1839
+ const isUnderlineShape = getShapeByElement(board, child.origin) === MindElementShape.underline;
1697
1840
  let beginX, beginY, endX, endY, beginNode = node, endNode = child;
1698
1841
  const beginRectangle = getRectangleByNode(beginNode);
1699
1842
  const endRectangle = getRectangleByNode(endNode);
1700
1843
  beginX = beginNode.x + beginNode.width / 2;
1701
1844
  beginY = isChildUp(node, child) ? beginRectangle.y : beginRectangle.y + beginRectangle.height;
1702
1845
  endX = node.left ? endNode.x + endNode.hGap + endRectangle.width : endNode.x + endNode.hGap;
1703
- endY = isUnderlineShap ? endNode.y + endNode.height - endNode.vGap : endNode.y + endNode.height / 2;
1846
+ endY = isUnderlineShape ? endNode.y + endNode.height - endNode.vGap : endNode.y + endNode.height / 2;
1704
1847
  //根据位置,设置正负参数
1705
1848
  let plusMinus = isChildUp(node, child) ? (node.left ? [-1, -1] : [1, -1]) : node.left ? [-1, 1] : [1, 1];
1706
- const layout = MindQueries.getCorrectLayoutByElement(node.origin);
1707
- const strokeWidth = child.origin.branchWidth ? child.origin.branchWidth : STROKE_WIDTH;
1849
+ const layout = MindQueries.getCorrectLayoutByElement(board, node.origin);
1708
1850
  if (beginNode.origin.isRoot) {
1709
1851
  if (layout === MindLayoutType.leftBottomIndented || layout === MindLayoutType.rightBottomIndented) {
1710
- beginY += strokeWidth;
1852
+ beginY += branchWidth;
1711
1853
  }
1712
1854
  if (layout === MindLayoutType.leftTopIndented || layout === MindLayoutType.rightTopIndented) {
1713
- beginY -= strokeWidth;
1855
+ beginY -= branchWidth;
1714
1856
  }
1715
1857
  }
1716
1858
  let curve = [
@@ -1721,13 +1863,12 @@ function drawIndentedLink(board, node, child, defaultStroke = null, needDrawUnde
1721
1863
  [beginX, endY - (endNode.hGap * plusMinus[1]) / 5],
1722
1864
  [beginX + (endNode.hGap * plusMinus[0]) / 4, endY],
1723
1865
  [beginX + (endNode.hGap * plusMinus[0] * 3) / 5, endY],
1724
- isUnderlineShap && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
1725
- isUnderlineShap && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
1726
- isUnderlineShap && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY]
1866
+ isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
1867
+ isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
1868
+ isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY]
1727
1869
  ];
1728
- const stroke = defaultStroke || getBranchColorByMindElement(board, child.origin);
1729
1870
  const points = pointsOnBezierCurves(curve);
1730
- return PlaitBoard.getRoughSVG(board).curve(points, { stroke, strokeWidth });
1871
+ return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth: branchWidth });
1731
1872
  }
1732
1873
 
1733
1874
  var HorizontalPlacement;
@@ -1842,10 +1983,12 @@ const transformPlacement = (placement, direction) => {
1842
1983
 
1843
1984
  function drawLogicLink(board, node, parent, isHorizontal) {
1844
1985
  const branchColor = getBranchColorByMindElement(board, node.origin);
1845
- const strokeWidth = node.origin.branchWidth ? node.origin.branchWidth : STROKE_WIDTH;
1986
+ const branchWidth = getBranchWidthByMindElement(board, node.origin);
1846
1987
  const hasStraightLine = !parent.origin.isRoot;
1847
- const hasUnderlineShape = node.origin.shape === MindNodeShape.underline;
1848
- const hasUnderlineShapeOfParent = parent.origin.shape === MindNodeShape.underline;
1988
+ const parentShape = getShapeByElement(board, parent.origin);
1989
+ const shape = node.origin.shape ? node.origin.shape : parentShape;
1990
+ const hasUnderlineShape = shape === MindElementShape.underline;
1991
+ const hasUnderlineShapeOfParent = parentShape === MindElementShape.underline;
1849
1992
  const nodeClient = getRectangleByNode(node);
1850
1993
  const parentClient = getRectangleByNode(parent);
1851
1994
  const linkDirection = getLayoutDirection(node, isHorizontal);
@@ -1882,10 +2025,10 @@ function drawLogicLink(board, node, parent, isHorizontal) {
1882
2025
  const underlineEnd = movePoint(endPoint, nodeClient.width, linkDirection);
1883
2026
  const underline = hasUnderlineShape && isHorizontal ? [underlineEnd, underlineEnd, underlineEnd] : [];
1884
2027
  const points = pointsOnBezierCurves([...straightLine, ...curve, ...underline]);
1885
- return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth });
2028
+ return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth: branchWidth });
1886
2029
  }
1887
2030
 
1888
- function getEmojisRectangle(board, element) {
2031
+ function getEmojisWidthHeight(board, element) {
1889
2032
  const options = board.getMindOptions();
1890
2033
  const count = element.data.emojis.length;
1891
2034
  const fontSize = getEmojiFontSize(element);
@@ -1902,6 +2045,31 @@ function getEmojiFontSize(element) {
1902
2045
  return 14 + 2;
1903
2046
  }
1904
2047
  }
2048
+ function getEmojiRectangle(board, element) {
2049
+ let { x, y } = getRectangleByNode(MindElement.getNode(element));
2050
+ x = x + NodeSpace.getEmojiLeftSpace(board, element);
2051
+ const { width, height } = getEmojisWidthHeight(board, element);
2052
+ return {
2053
+ x,
2054
+ y,
2055
+ width,
2056
+ height
2057
+ };
2058
+ }
2059
+ function getEmojiForeignRectangle(board, element) {
2060
+ let { x, y } = getRectangleByNode(MindElement.getNode(element));
2061
+ x = x + NodeSpace.getEmojiLeftSpace(board, element);
2062
+ const { width, height } = getEmojisWidthHeight(board, element);
2063
+ return {
2064
+ x,
2065
+ y,
2066
+ width,
2067
+ height: height + NodeSpace.getEmojiTopSpace(element) * 2
2068
+ };
2069
+ }
2070
+ const isHitEmojis = (board, element, point) => {
2071
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), getEmojiRectangle(board, element));
2072
+ };
1905
2073
 
1906
2074
  const NodeDefaultSpace = {
1907
2075
  horizontal: {
@@ -1921,26 +2089,30 @@ const RootDefaultSpace = {
1921
2089
  nodeAndText: BASE * 2
1922
2090
  }
1923
2091
  };
1924
- const getHorizontalSpaceBetweenNodeAndText = (element) => {
2092
+ const getHorizontalSpaceBetweenNodeAndText = (board, element) => {
1925
2093
  const isMind = PlaitMind.isMind(element);
1926
2094
  const nodeAndText = isMind ? RootDefaultSpace.horizontal.nodeAndText : NodeDefaultSpace.horizontal.nodeAndText;
1927
2095
  return nodeAndText;
1928
2096
  };
1929
- const getHorizontalSpaceEmojiAndText = (element) => {
1930
- const isMind = PlaitMind.isMind(element);
1931
- const emojiAndText = isMind ? RootDefaultSpace.horizontal.emojiAndText : NodeDefaultSpace.horizontal.emojiAndText;
1932
- return emojiAndText;
1933
- };
1934
2097
  const getVerticalSpaceBetweenNodeAndText = (element) => {
1935
2098
  const isMind = PlaitMind.isMind(element);
1936
2099
  const nodeAndText = isMind ? RootDefaultSpace.vertical.nodeAndText : NodeDefaultSpace.vertical.nodeAndText;
1937
2100
  return nodeAndText;
1938
2101
  };
2102
+ const getSpaceEmojiAndText = (element) => {
2103
+ const isMind = PlaitMind.isMind(element);
2104
+ const emojiAndText = isMind ? RootDefaultSpace.horizontal.emojiAndText : NodeDefaultSpace.horizontal.emojiAndText;
2105
+ return emojiAndText;
2106
+ };
1939
2107
  const NodeSpace = {
1940
2108
  getNodeWidth(board, element) {
1941
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(element);
2109
+ const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
1942
2110
  if (MindElement.hasEmojis(element)) {
1943
- return nodeAndText + getEmojisRectangle(board, element).width + getHorizontalSpaceEmojiAndText(element) + element.width + nodeAndText;
2111
+ return (NodeSpace.getEmojiLeftSpace(board, element) +
2112
+ getEmojisWidthHeight(board, element).width +
2113
+ getSpaceEmojiAndText(element) +
2114
+ element.width +
2115
+ nodeAndText);
1944
2116
  }
1945
2117
  return nodeAndText + element.width + nodeAndText;
1946
2118
  },
@@ -1948,24 +2120,25 @@ const NodeSpace = {
1948
2120
  const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
1949
2121
  return nodeAndText + element.height + nodeAndText;
1950
2122
  },
1951
- getTextHorizontalSpace(board, element) {
1952
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(element);
2123
+ getTextLeftSpace(board, element) {
2124
+ const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
1953
2125
  if (MindElement.hasEmojis(element)) {
1954
- return nodeAndText + getEmojisRectangle(board, element).width + getHorizontalSpaceEmojiAndText(element);
2126
+ return NodeSpace.getEmojiLeftSpace(board, element) + getEmojisWidthHeight(board, element).width + getSpaceEmojiAndText(element);
1955
2127
  }
1956
2128
  else {
1957
2129
  return nodeAndText;
1958
2130
  }
1959
2131
  },
1960
- getTextVerticalSpace(element) {
2132
+ getTextTopSpace(element) {
1961
2133
  const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
1962
2134
  return nodeAndText;
1963
2135
  },
1964
- getEmojiHorizontalSpace(element) {
1965
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(element);
1966
- return nodeAndText;
2136
+ getEmojiLeftSpace(board, element) {
2137
+ const options = board.getMindOptions();
2138
+ const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
2139
+ return nodeAndText - options.emojiPadding;
1967
2140
  },
1968
- getEmojiVerticalSpace(element) {
2141
+ getEmojiTopSpace(element) {
1969
2142
  const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
1970
2143
  return nodeAndText;
1971
2144
  }
@@ -1973,7 +2146,7 @@ const NodeSpace = {
1973
2146
 
1974
2147
  function drawMindNodeRichtext(board, node, viewContainerRef) {
1975
2148
  var _a, _b;
1976
- const { x, y } = getRichtextRectangleByNode(board, node);
2149
+ const { x, y, width, height } = getRichtextRectangleByNode(board, node);
1977
2150
  const classList = [];
1978
2151
  if (node.origin.isRoot) {
1979
2152
  classList.push('root-node');
@@ -1986,7 +2159,7 @@ function drawMindNodeRichtext(board, node, viewContainerRef) {
1986
2159
  classList.push('child-node');
1987
2160
  }
1988
2161
  // COMPAT: last character can not show in safari browser
1989
- return drawRichtext(x, y, Math.ceil(node.origin.width), Math.ceil(node.origin.height), node.origin.data.topic, viewContainerRef, classList);
2162
+ return drawRichtext(x, y, width, height, node.origin.data.topic, viewContainerRef, classList);
1990
2163
  }
1991
2164
  function updateMindNodeTopicSize(board, node, g, isEditable) {
1992
2165
  const { x, y, width, height } = getRichtextRectangleByNode(board, node);
@@ -1996,21 +2169,23 @@ function updateMindNodeTopicSize(board, node, g, isEditable) {
1996
2169
  }
1997
2170
  else {
1998
2171
  // COMPAT: last character can not show in safari browser
1999
- updateForeignObject(g, Math.ceil(node.origin.width), Math.ceil(node.origin.height), x, y);
2172
+ updateForeignObject(g, width, height, x, y);
2000
2173
  }
2001
2174
  }
2002
2175
  function getRichtextRectangleByNode(board, node) {
2003
- let { x, y, width, height } = getRectangleByNode(node);
2004
- x = x + NodeSpace.getTextHorizontalSpace(board, node.origin);
2005
- y = y + NodeSpace.getTextVerticalSpace(node.origin);
2006
- return { width, height, x, y };
2176
+ let { x, y } = getRectangleByNode(node);
2177
+ x = x + NodeSpace.getTextLeftSpace(board, node.origin);
2178
+ y = y + NodeSpace.getTextTopSpace(node.origin);
2179
+ const width = Math.ceil(node.origin.width);
2180
+ const height = Math.ceil(node.origin.height);
2181
+ return { height, width, x, y };
2007
2182
  }
2008
2183
 
2009
2184
  function drawRectangleNode(board, node) {
2010
2185
  const { x, y, width, height } = getRectangleByNode(node);
2011
- const fill = node.origin.fill ? node.origin.fill : node.origin.isRoot ? ROOT_NODE_FILL : NODE_FILL;
2186
+ const fill = node.origin.fill ? node.origin.fill : node.origin.isRoot ? DefaultRootStyle.fill : DefaultNodeStyle.fill;
2012
2187
  const stroke = getStrokeByMindElement(board, node.origin);
2013
- const strokeWidth = node.origin.strokeWidth ? node.origin.strokeWidth : STROKE_WIDTH;
2188
+ const strokeWidth = node.origin.strokeWidth ? node.origin.strokeWidth : DefaultNodeStyle.strokeWidth;
2014
2189
  const nodeG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), x, y, x + width, y + height, {
2015
2190
  stroke,
2016
2191
  strokeWidth,
@@ -2022,6 +2197,8 @@ function drawRectangleNode(board, node) {
2022
2197
 
2023
2198
  function drawAbstractLink(board, node, isHorizontal) {
2024
2199
  const linkPadding = 15;
2200
+ const branchWidth = getAbstractBranchWidth(board, node.origin);
2201
+ const branchColor = getAbstractBranchColor(board, node.origin);
2025
2202
  const parent = node.parent;
2026
2203
  const abstractRectangle = getRectangleByNode(node);
2027
2204
  let includedElements = parent.children.slice(node.origin.start, node.origin.end + 1).map(node => {
@@ -2051,8 +2228,8 @@ function drawAbstractLink(board, node, isHorizontal) {
2051
2228
  let c2 = movePoint(bezierEndPoint, curveDistance, linkDirection);
2052
2229
  let bezierConnectorPoint = movePoint(abstractConnectorPoint, -linkPadding, linkDirection);
2053
2230
  const link = PlaitBoard.getRoughSVG(board).path(`M${bezierBeginPoint[0]},${bezierBeginPoint[1]} Q${c1[0]},${c1[1]} ${bezierConnectorPoint[0]},${bezierConnectorPoint[1]} Q${c2[0]},${c2[1]} ${bezierEndPoint[0]},${bezierEndPoint[1]} M${abstractConnectorPoint[0]},${abstractConnectorPoint[1]} L${bezierConnectorPoint[0]},${bezierConnectorPoint[1]}`, {
2054
- stroke: GRAY_COLOR,
2055
- strokeWidth: 2
2231
+ stroke: branchColor,
2232
+ strokeWidth: branchWidth
2056
2233
  });
2057
2234
  return link;
2058
2235
  }
@@ -2098,10 +2275,8 @@ class EmojisDrawer {
2098
2275
  if (MindElement.hasEmojis(element)) {
2099
2276
  this.g = createG();
2100
2277
  this.g.classList.add('emojis');
2101
- let { x, y } = getRectangleByNode(MindElement.getNode(element));
2102
- x = x + NodeSpace.getEmojiHorizontalSpace(element);
2103
- const { width, height } = getEmojisRectangle(this.board, element);
2104
- const foreignObject = createForeignObject(x, y, width, height + NodeSpace.getEmojiVerticalSpace(element) * 2);
2278
+ const foreignRectangle = getEmojiForeignRectangle(this.board, element);
2279
+ const foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
2105
2280
  this.g.append(foreignObject);
2106
2281
  const container = document.createElement('div');
2107
2282
  container.classList.add('node-emojis-container');
@@ -2110,119 +2285,27 @@ class EmojisDrawer {
2110
2285
  const drawer = new EmojiDrawer(this.board, this.viewContainerRef);
2111
2286
  drawer.draw(emojiItem, element);
2112
2287
  return drawer;
2113
- });
2114
- this.emojiDrawers.forEach(drawer => {
2115
- container.append(drawer.nativeElement);
2116
- });
2117
- return this.g;
2118
- }
2119
- return undefined;
2120
- }
2121
- destroy() {
2122
- if (this.g) {
2123
- this.g.remove();
2124
- }
2125
- this.emojiDrawers.forEach(drawer => drawer.destroy());
2126
- this.emojiDrawers = [];
2127
- }
2128
- }
2129
-
2130
- const setLayout = (board, layout, path) => {
2131
- correctLogicLayoutNode(board, layout, path);
2132
- const element = PlaitNode.get(board, path);
2133
- if (PlaitMind.isMind(element) && isStandardLayout(layout)) {
2134
- handleAbstractIncluded(board, element);
2135
- }
2136
- Transforms.setNode(board, { layout }, path);
2137
- };
2138
- const correctLogicLayoutNode = (board, layout, path) => {
2139
- var _a;
2140
- const node = PlaitNode.get(board, path);
2141
- if (node && layout) {
2142
- (_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach((value, index) => {
2143
- var _a;
2144
- if (value.layout) {
2145
- if ((isHorizontalLogicLayout(layout) && isVerticalLogicLayout(value.layout)) ||
2146
- (isVerticalLogicLayout(layout) && isHorizontalLogicLayout(value.layout))) {
2147
- Transforms.setNode(board, { layout: null }, [...path, index]);
2148
- }
2149
- if ((_a = value.children) === null || _a === void 0 ? void 0 : _a.length) {
2150
- correctLogicLayoutNode(board, layout, [...path, index]);
2151
- }
2152
- }
2153
- });
2154
- }
2155
- };
2156
-
2157
- const setTopic = (board, element, topic, width, height) => {
2158
- const newElement = {
2159
- data: { topic },
2160
- width: width < NODE_MIN_WIDTH * board.viewport.zoom ? NODE_MIN_WIDTH : width / board.viewport.zoom,
2161
- height: height / board.viewport.zoom
2162
- };
2163
- if (MindElement.hasEmojis(element)) {
2164
- newElement.data.emojis = element.data.emojis;
2165
- }
2166
- const path = PlaitBoard.findPath(board, element);
2167
- Transforms.setNode(board, newElement, path);
2168
- };
2169
- const setTopicSize = (board, element, width, height) => {
2170
- const newElement = {
2171
- width: width < NODE_MIN_WIDTH * board.viewport.zoom ? NODE_MIN_WIDTH : width / board.viewport.zoom,
2172
- height: height / board.viewport.zoom
2173
- };
2174
- const path = PlaitBoard.findPath(board, element);
2175
- Transforms.setNode(board, newElement, path);
2176
- };
2177
- const addEmoji = (board, element, emojiItem) => {
2178
- const emojis = element.data.emojis || [];
2179
- const newEmojis = [...emojis];
2180
- newEmojis.push(emojiItem);
2181
- const newElement = {
2182
- data: { topic: element.data.topic, emojis: newEmojis }
2183
- };
2184
- const path = PlaitBoard.findPath(board, element);
2185
- Transforms.setNode(board, newElement, path);
2186
- };
2187
- const removeEmoji = (board, element, emojiItem) => {
2188
- const emojis = element.data.emojis.filter(value => value !== emojiItem);
2189
- const newElement = {
2190
- data: { topic: element.data.topic }
2191
- };
2192
- if (emojis.length > 0) {
2193
- newElement.data.emojis = emojis;
2194
- }
2195
- const path = PlaitBoard.findPath(board, element);
2196
- Transforms.setNode(board, newElement, path);
2197
- };
2198
- const replaceEmoji = (board, element, oldEmoji, newEmoji) => {
2199
- const newElement = {
2200
- data: { topic: element.data.topic }
2201
- };
2202
- const newEmojis = element.data.emojis.map(value => {
2203
- if (value === oldEmoji) {
2204
- return newEmoji;
2288
+ });
2289
+ this.emojiDrawers.forEach(drawer => {
2290
+ container.append(drawer.nativeElement);
2291
+ });
2292
+ return this.g;
2205
2293
  }
2206
- return value;
2207
- });
2208
- newElement.data.emojis = newEmojis;
2209
- const path = PlaitBoard.findPath(board, element);
2210
- Transforms.setNode(board, newElement, path);
2211
- };
2212
-
2213
- const MindTransforms = {
2214
- setLayout,
2215
- setTopic,
2216
- setTopicSize,
2217
- addEmoji,
2218
- removeEmoji,
2219
- replaceEmoji
2220
- };
2294
+ return undefined;
2295
+ }
2296
+ destroy() {
2297
+ if (this.g) {
2298
+ this.g.remove();
2299
+ }
2300
+ this.emojiDrawers.forEach(drawer => drawer.destroy());
2301
+ this.emojiDrawers = [];
2302
+ }
2303
+ }
2221
2304
 
2222
2305
  function drawAbstractIncludedOutline(board, roughSVG, element, activeHandlePosition, resizingLocation) {
2223
2306
  const abstractIncludedG = createG();
2224
2307
  const parentElement = MindElement.getParent(element);
2225
- const nodeLayout = MindQueries.getCorrectLayoutByElement(element);
2308
+ const nodeLayout = MindQueries.getCorrectLayoutByElement(board, element);
2226
2309
  const isHorizontal = isHorizontalLayout(nodeLayout);
2227
2310
  const includedElements = parentElement.children.slice(element.start, element.end + 1);
2228
2311
  let abstractRectangle = getRectangleByElements(board, includedElements, true);
@@ -2302,7 +2385,8 @@ function hasAfterDraw(value) {
2302
2385
  }
2303
2386
 
2304
2387
  function findNewChildNodePath(board, element) {
2305
- return PlaitBoard.findPath(board, element).concat((element.children || []).filter(child => !AbstractNode.isAbstract(child)).length);
2388
+ const children = getNonAbstractChildren(element);
2389
+ return PlaitBoard.findPath(board, element).concat(children.length);
2306
2390
  }
2307
2391
  function findNewSiblingNodePath(board, element) {
2308
2392
  const path = PlaitBoard.findPath(board, element);
@@ -2330,16 +2414,16 @@ class QuickInsertDrawer extends BaseDrawer {
2330
2414
  * 3. 上、上左、上右
2331
2415
  * 4. 下、下左、下右
2332
2416
  */
2333
- const shape = getNodeShapeByElement(element);
2417
+ const shape = getShapeByElement(this.board, element);
2334
2418
  // 形状是矩形要偏移边框的线宽
2335
- const strokeWidth = element.branchWidth ? element.branchWidth : STROKE_WIDTH;
2419
+ const branchWidth = getBranchWidthByMindElement(this.board, element);
2336
2420
  let offsetBorderLineWidth = 0;
2337
- if (shape === MindNodeShape.roundRectangle && offset === 0) {
2338
- offsetBorderLineWidth = strokeWidth;
2421
+ if (shape === MindElementShape.roundRectangle && offset === 0) {
2422
+ offsetBorderLineWidth = branchWidth;
2339
2423
  }
2340
2424
  let offsetRootBorderLineWidth = 0;
2341
2425
  if (element.isRoot) {
2342
- offsetRootBorderLineWidth = strokeWidth;
2426
+ offsetRootBorderLineWidth = branchWidth;
2343
2427
  }
2344
2428
  // 当没有子节点时,需要缩小的偏移量
2345
2429
  const extraOffset = 3;
@@ -2434,21 +2518,21 @@ class QuickInsertDrawer extends BaseDrawer {
2434
2518
  offsetRootBorderLineWidth
2435
2519
  }
2436
2520
  };
2437
- if (shape === MindNodeShape.roundRectangle || element.isRoot) {
2521
+ if (shape === MindElementShape.roundRectangle || element.isRoot) {
2438
2522
  underlineCoordinates[MindLayoutType.left].startY -= height * 0.5;
2439
2523
  underlineCoordinates[MindLayoutType.left].endY -= height * 0.5;
2440
2524
  underlineCoordinates[MindLayoutType.right].startY -= height * 0.5;
2441
2525
  underlineCoordinates[MindLayoutType.right].endY -= height * 0.5;
2442
2526
  }
2443
2527
  const branchColor = PlaitMind.isMind(element) ? getNextBranchColor(element) : getBranchColorByMindElement(this.board, element);
2444
- let nodeLayout = MindQueries.getCorrectLayoutByElement(element);
2528
+ let nodeLayout = MindQueries.getCorrectLayoutByElement(this.board, element);
2445
2529
  if (element.isRoot && isStandardLayout(nodeLayout)) {
2446
2530
  const root = element;
2447
2531
  nodeLayout = root.children.length >= root.rightNodeCount ? MindLayoutType.left : MindLayoutType.right;
2448
2532
  }
2449
2533
  const underlineCoordinate = underlineCoordinates[nodeLayout];
2450
2534
  if (underlineCoordinate) {
2451
- const underline = PlaitBoard.getRoughSVG(this.board).line(underlineCoordinate.startX, underlineCoordinate.startY, underlineCoordinate.endX, underlineCoordinate.endY, { stroke: branchColor, strokeWidth });
2535
+ const underline = PlaitBoard.getRoughSVG(this.board).line(underlineCoordinate.startX, underlineCoordinate.startY, underlineCoordinate.endX, underlineCoordinate.endY, { stroke: branchColor, strokeWidth: branchWidth });
2452
2536
  const circleCoordinates = {
2453
2537
  startX: underlineCoordinate.endX,
2454
2538
  startY: underlineCoordinate.endY
@@ -2526,10 +2610,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2526
2610
  this.emojisDrawer = new EmojisDrawer(this.board, this.viewContainerRef);
2527
2611
  this.quickInsertDrawer = new QuickInsertDrawer(this.board);
2528
2612
  super.ngOnInit();
2529
- this.node = ELEMENT_TO_NODE.get(this.element);
2530
- if (!PlaitMind.isMind(this.element)) {
2531
- this.parent = MindElement.getNode(MindElement.getParent(this.element));
2532
- }
2613
+ this.node = MindElement.getNode(this.element);
2533
2614
  this.index = NODE_TO_INDEX.get(this.element) || 0;
2534
2615
  this.roughSVG = PlaitBoard.getRoughSVG(this.board);
2535
2616
  this.parentG = PlaitElement.getComponent(MindElement.getRoot(this.board, this.element)).rootG;
@@ -2545,21 +2626,18 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2545
2626
  }
2546
2627
  onContextChanged(value, previous) {
2547
2628
  var _a, _b;
2548
- const newNode = ELEMENT_TO_NODE.get(this.element);
2549
- if (!PlaitMind.isMind(this.element)) {
2550
- this.parent = MindElement.getNode(MindElement.getParent(this.element));
2551
- }
2629
+ const newNode = MindElement.getNode(value.element);
2552
2630
  // resolve move node richtext lose issue
2553
2631
  if (this.node !== newNode) {
2554
2632
  if (this.foreignObject && this.foreignObject.children.length <= 0) {
2555
2633
  (_a = this.foreignObject) === null || _a === void 0 ? void 0 : _a.appendChild((_b = this.richtextComponentRef) === null || _b === void 0 ? void 0 : _b.instance.editable);
2556
2634
  }
2557
2635
  }
2558
- const isEquals = MindNode.isEquals(this.node, newNode);
2636
+ const isEqualNode = RectangleClient.isEqual(this.node, newNode);
2559
2637
  this.node = newNode;
2560
- this.drawActiveG();
2561
- this.updateActiveClass();
2562
- if (!isEquals) {
2638
+ if (!isEqualNode || value.element !== previous.element) {
2639
+ this.drawActiveG();
2640
+ this.updateActiveClass();
2563
2641
  this.drawShape();
2564
2642
  this.drawLink();
2565
2643
  this.updateRichtext();
@@ -2568,6 +2646,20 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2568
2646
  this.drawQuickInsert();
2569
2647
  this.drawEmojis();
2570
2648
  }
2649
+ else {
2650
+ if (value.selected !== previous.selected) {
2651
+ this.drawActiveG();
2652
+ this.updateActiveClass();
2653
+ }
2654
+ if (!PlaitMind.isMind(value.element)) {
2655
+ const parent = MindElement.getParent(previous.element);
2656
+ const newParent = MindElement.getParent(value.element);
2657
+ const hasSameChildren = parent.children.length === newParent.children.length;
2658
+ if (!hasSameChildren) {
2659
+ this.drawLink();
2660
+ }
2661
+ }
2662
+ }
2571
2663
  }
2572
2664
  drawEmojis() {
2573
2665
  const g = this.emojisDrawer.drawEmojis(this.element);
@@ -2588,9 +2680,9 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2588
2680
  }
2589
2681
  drawShape() {
2590
2682
  this.destroyShape();
2591
- const shape = getNodeShapeByElement(this.node.origin);
2683
+ const shape = getShapeByElement(this.board, this.node.origin);
2592
2684
  switch (shape) {
2593
- case MindNodeShape.roundRectangle:
2685
+ case MindElementShape.roundRectangle:
2594
2686
  this.shapeG = drawRectangleNode(this.board, this.node);
2595
2687
  this.g.prepend(this.shapeG);
2596
2688
  break;
@@ -2605,29 +2697,29 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2605
2697
  }
2606
2698
  }
2607
2699
  drawLink() {
2608
- if (!this.parent) {
2700
+ if (PlaitMind.isMind(this.element)) {
2609
2701
  return;
2610
2702
  }
2703
+ const parent = MindElement.getParent(this.element);
2704
+ const parentNode = MindElement.getNode(parent);
2611
2705
  if (this.linkG) {
2612
2706
  this.linkG.remove();
2613
2707
  }
2614
- const layout = MindQueries.getLayoutByElement(this.parent.origin);
2708
+ const layout = MindQueries.getLayoutByElement(parent);
2615
2709
  if (AbstractNode.isAbstract(this.node.origin)) {
2616
2710
  this.linkG = drawAbstractLink(this.board, this.node, isHorizontalLayout(layout));
2617
2711
  }
2618
- else if (MindElement.isIndentedLayout(this.parent.origin)) {
2619
- this.linkG = drawIndentedLink(this.board, this.parent, this.node);
2712
+ else if (MindElement.isIndentedLayout(parent)) {
2713
+ this.linkG = drawIndentedLink(this.board, parentNode, this.node);
2620
2714
  }
2621
2715
  else {
2622
- this.linkG = drawLogicLink(this.board, this.node, this.parent, isHorizontalLayout(layout));
2716
+ this.linkG = drawLogicLink(this.board, this.node, parentNode, isHorizontalLayout(layout));
2623
2717
  }
2624
2718
  this.g.append(this.linkG);
2625
2719
  }
2626
2720
  destroyLine() {
2627
- if (this.parent) {
2628
- if (this.linkG) {
2629
- this.linkG.remove();
2630
- }
2721
+ if (this.linkG) {
2722
+ this.linkG.remove();
2631
2723
  }
2632
2724
  }
2633
2725
  drawMaskG() {
@@ -2778,9 +2870,9 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2778
2870
  });
2779
2871
  const { x, y, width, height } = getRectangleByNode(this.node);
2780
2872
  const stroke = getBranchColorByMindElement(this.board, this.element);
2781
- const strokeWidth = this.node.origin.branchWidth ? this.node.origin.branchWidth : STROKE_WIDTH;
2873
+ const branchWidth = getBranchWidthByMindElement(this.board, this.element);
2782
2874
  const extendY = y + height / 2;
2783
- const nodeLayout = MindQueries.getCorrectLayoutByElement(this.element);
2875
+ const nodeLayout = MindQueries.getCorrectLayoutByElement(this.board, this.element);
2784
2876
  let extendLineXY = [
2785
2877
  [x + width, extendY],
2786
2878
  [x + width + EXTEND_OFFSET, extendY]
@@ -2792,7 +2884,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2792
2884
  let circleOffset = [EXTEND_RADIUS / 2, 0];
2793
2885
  if (isHorizontalLayout(nodeLayout) && !isIndentedLayout(nodeLayout)) {
2794
2886
  extendLineYOffset =
2795
- getNodeShapeByElement(this.node.origin) === MindNodeShape.roundRectangle
2887
+ getShapeByElement(this.board, this.node.origin) === MindElementShape.roundRectangle
2796
2888
  ? [0, 0]
2797
2889
  : [height / 2, height / 2];
2798
2890
  if (isLeftLayout(nodeLayout)) {
@@ -2824,7 +2916,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2824
2916
  [extendLineXY[1][0] + extendLineXOffset[1], extendLineXY[1][1] + extendLineYOffset[1]]
2825
2917
  ];
2826
2918
  const extendLine = this.roughSVG.line(extendLineXY[0][0], extendLineXY[0][1], extendLineXY[1][0], extendLineXY[1][1], {
2827
- strokeWidth,
2919
+ strokeWidth: branchWidth,
2828
2920
  stroke
2829
2921
  });
2830
2922
  //绘制箭头
@@ -2861,7 +2953,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2861
2953
  const hideCircleG = this.roughSVG.circle(extendLineXY[1][0] + circleOffset[0], extendLineXY[1][1] + circleOffset[1], EXTEND_RADIUS - 1, {
2862
2954
  fill: '#fff',
2863
2955
  stroke,
2864
- strokeWidth,
2956
+ strokeWidth: branchWidth,
2865
2957
  fillStyle: 'solid'
2866
2958
  });
2867
2959
  collapseG.appendChild(hideCircleG);
@@ -3101,7 +3193,7 @@ const getLayoutOptions = (board) => {
3101
3193
  }
3102
3194
  },
3103
3195
  getVerticalConnectingPosition(element, parent) {
3104
- if (element.shape === MindNodeShape.underline && parent && isHorizontalLogicLayout(parent.layout)) {
3196
+ if (element.shape === MindElementShape.underline && parent && isHorizontalLogicLayout(parent.layout)) {
3105
3197
  return ConnectingPosition.bottom;
3106
3198
  }
3107
3199
  return undefined;
@@ -3170,6 +3262,123 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
3170
3262
  }]
3171
3263
  }] });
3172
3264
 
3265
+ const isValidTarget = (origin, target) => {
3266
+ return origin !== target && !isChildElement(origin, target);
3267
+ };
3268
+ const addActiveOnDragOrigin = (activeElement, isOrigin = true) => {
3269
+ const activeComponent = PlaitElement.getComponent(activeElement);
3270
+ if (isOrigin) {
3271
+ activeComponent.g.classList.add('dragging-origin');
3272
+ }
3273
+ else {
3274
+ activeComponent.g.classList.add('dragging-child');
3275
+ }
3276
+ !activeElement.isCollapsed &&
3277
+ activeElement.children.forEach(child => {
3278
+ addActiveOnDragOrigin(child, false);
3279
+ });
3280
+ };
3281
+ const removeActiveOnDragOrigin = (activeElement, isOrigin = true) => {
3282
+ const activeComponent = PlaitElement.getComponent(activeElement);
3283
+ if (isOrigin) {
3284
+ activeComponent.g.classList.remove('dragging-origin');
3285
+ }
3286
+ else {
3287
+ activeComponent.g.classList.remove('dragging-child');
3288
+ }
3289
+ !activeElement.isCollapsed &&
3290
+ activeElement.children.forEach(child => {
3291
+ removeActiveOnDragOrigin(child, false);
3292
+ });
3293
+ };
3294
+ const updatePathByLayoutAndDropTarget = (targetPath, layout, dropTarget) => {
3295
+ // 上下布局:左右是兄弟节点,上下是子节点
3296
+ if (isVerticalLogicLayout(layout)) {
3297
+ if (isTopLayout(layout) && dropTarget.detectResult === 'top') {
3298
+ targetPath.push(dropTarget.target.children.length);
3299
+ }
3300
+ if (isBottomLayout(layout) && dropTarget.detectResult === 'bottom') {
3301
+ targetPath.push(dropTarget.target.children.length);
3302
+ }
3303
+ // 如果是左,位置不变,右则插入到下一个兄弟节点
3304
+ if (dropTarget.detectResult === 'right') {
3305
+ targetPath = Path.next(targetPath);
3306
+ }
3307
+ }
3308
+ // 水平布局/标准布局:上下是兄弟节点,左右是子节点
3309
+ if (isHorizontalLogicLayout(layout)) {
3310
+ if (dropTarget.detectResult === 'right') {
3311
+ targetPath.push(dropTarget.target.children.length);
3312
+ }
3313
+ if (dropTarget.detectResult === 'left') {
3314
+ targetPath.push(dropTarget.target.children.length);
3315
+ }
3316
+ // 如果是上,位置不变,下插入到下一个兄弟节点
3317
+ if (dropTarget.detectResult === 'bottom') {
3318
+ targetPath = Path.next(targetPath);
3319
+ }
3320
+ }
3321
+ // 缩进布局:上下是兄弟节点,左右是子节点,但上(左上/右上),探测到上是子节点,下则位置不变,反之同理。
3322
+ if (isIndentedLayout(layout)) {
3323
+ if (isTopLayout(layout) && dropTarget.detectResult === 'top') {
3324
+ targetPath = Path.next(targetPath);
3325
+ }
3326
+ if (isBottomLayout(layout) && dropTarget.detectResult === 'bottom') {
3327
+ targetPath = Path.next(targetPath);
3328
+ }
3329
+ if (isLeftLayout(layout) && dropTarget.detectResult === 'left') {
3330
+ targetPath.push(dropTarget.target.children.length);
3331
+ }
3332
+ if (isRightLayout(layout) && dropTarget.detectResult === 'right') {
3333
+ targetPath.push(dropTarget.target.children.length);
3334
+ }
3335
+ }
3336
+ return targetPath;
3337
+ };
3338
+ const updateRightNodeCount = (board, activeComponent, targetComponent, detectResult) => {
3339
+ var _a;
3340
+ let rightNodeCount;
3341
+ const mindElement = findUpElement(targetComponent.node.origin).root;
3342
+ const mindComponent = ELEMENT_TO_COMPONENT.get(mindElement);
3343
+ const activeIndex = mindComponent === null || mindComponent === void 0 ? void 0 : mindComponent.root.children.indexOf(activeComponent.node);
3344
+ const targetIndex = mindComponent === null || mindComponent === void 0 ? void 0 : mindComponent.root.children.indexOf(targetComponent.node);
3345
+ const activeParent = MindElement.getParent(activeComponent.element);
3346
+ const targetParent = MindElement.findParent(targetComponent.element);
3347
+ const isActiveOnRight = activeIndex !== -1 && activeIndex <= activeParent.rightNodeCount - 1;
3348
+ const isTargetOnRight = targetParent && targetIndex !== -1 && targetIndex <= targetParent.rightNodeCount - 1;
3349
+ const isBothOnRight = isActiveOnRight && isTargetOnRight;
3350
+ const rootChildCount = (_a = mindComponent.root.children) === null || _a === void 0 ? void 0 : _a.length;
3351
+ const rootRightNodeCount = mindComponent === null || mindComponent === void 0 ? void 0 : mindComponent.root.origin.rightNodeCount;
3352
+ if (!isBothOnRight) {
3353
+ if (isActiveOnRight) {
3354
+ rightNodeCount = rootChildCount < rootRightNodeCount ? rootChildCount - 1 : rootRightNodeCount - 1;
3355
+ Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, activeParent));
3356
+ }
3357
+ if (isTargetOnRight && detectResult !== 'right') {
3358
+ rightNodeCount = rootChildCount < rootRightNodeCount ? rootRightNodeCount : rootRightNodeCount + 1;
3359
+ const parent = MindElement.getParent(targetComponent.element);
3360
+ Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, parent));
3361
+ }
3362
+ //二级子节点拖动到根节点左侧
3363
+ if (targetComponent.node.origin.isRoot && detectResult === 'left' && activeIndex === -1) {
3364
+ rightNodeCount = rootChildCount;
3365
+ Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, targetComponent.element));
3366
+ }
3367
+ }
3368
+ };
3369
+ const IS_DRAGGING = new WeakMap();
3370
+ const isDragging = (board) => {
3371
+ return !!IS_DRAGGING.get(board);
3372
+ };
3373
+ const setIsDragging = (board, state) => {
3374
+ IS_DRAGGING.set(board, state);
3375
+ };
3376
+ const updateAbstractInDnd = (board, deletableElements, originPath) => {
3377
+ const refs = insertElementHandleAbstract(board, originPath, false);
3378
+ deleteElementHandleAbstract(board, deletableElements, refs);
3379
+ MindTransforms.setAbstractsByRefs(board, refs);
3380
+ };
3381
+
3173
3382
  const DRAG_MOVE_BUFFER = 5;
3174
3383
  const withDnd = (board) => {
3175
3384
  const { mousedown, mousemove, globalMouseup, keydown } = board;
@@ -3191,8 +3400,8 @@ const withDnd = (board) => {
3191
3400
  return;
3192
3401
  }
3193
3402
  if (PlaitMind.isMind(value)) {
3194
- const mindmapComponent = ELEMENT_TO_COMPONENT.get(value);
3195
- const root = mindmapComponent === null || mindmapComponent === void 0 ? void 0 : mindmapComponent.root;
3403
+ const mindComponent = ELEMENT_TO_COMPONENT.get(value);
3404
+ const root = mindComponent.root;
3196
3405
  root.eachNode((node) => {
3197
3406
  if (activeElement) {
3198
3407
  return;
@@ -3242,14 +3451,20 @@ const withDnd = (board) => {
3242
3451
  const offsetX = endPoint[0] - startPoint[0];
3243
3452
  const offsetY = endPoint[1] - startPoint[1];
3244
3453
  const activeComponent = PlaitElement.getComponent(activeElement);
3245
- const roughSVG = PlaitBoard.getRoughSVG(board);
3246
3454
  const fakeDraggingNode = Object.assign(Object.assign({}, activeComponent.node), { children: [], x: activeComponent.node.x + offsetX, y: activeComponent.node.y + offsetY });
3247
3455
  const textRectangle = getRichtextRectangleByNode(board, activeComponent.node);
3248
3456
  const fakeNodeG = drawRectangleNode(board, fakeDraggingNode);
3249
3457
  const richtextG = (_a = activeComponent.richtextG) === null || _a === void 0 ? void 0 : _a.cloneNode(true);
3250
- updateForeignObject(richtextG, textRectangle.width + BASE * 10, textRectangle.height, textRectangle.x + offsetX, textRectangle.y + offsetY);
3458
+ updateForeignObject$1(richtextG, textRectangle.width, textRectangle.height, textRectangle.x + offsetX, textRectangle.y + offsetY);
3251
3459
  fakeDragNodeG === null || fakeDragNodeG === void 0 ? void 0 : fakeDragNodeG.append(fakeNodeG);
3252
3460
  fakeDragNodeG === null || fakeDragNodeG === void 0 ? void 0 : fakeDragNodeG.append(richtextG);
3461
+ // draw emojis
3462
+ if (MindElement.hasEmojis(activeElement)) {
3463
+ const fakeEmojisG = activeComponent.emojisDrawer.g.cloneNode(true);
3464
+ const foreignRectangle = getEmojiForeignRectangle(board, activeElement);
3465
+ updateForeignObject$1(fakeEmojisG, foreignRectangle.width, foreignRectangle.height, foreignRectangle.x + offsetX, foreignRectangle.y + offsetY);
3466
+ fakeDragNodeG === null || fakeDragNodeG === void 0 ? void 0 : fakeDragNodeG.append(fakeEmojisG);
3467
+ }
3253
3468
  // drop position detect
3254
3469
  const { x, y } = getRectangleByNode(fakeDraggingNode);
3255
3470
  const detectCenterPoint = [x + textRectangle.width / 2, y + textRectangle.height / 2];
@@ -3267,7 +3482,7 @@ const withDnd = (board) => {
3267
3482
  }
3268
3483
  const directions = directionDetector(node, detectCenterPoint);
3269
3484
  if (directions) {
3270
- detectResult = directionCorrector(node, directions);
3485
+ detectResult = directionCorrector(board, node, directions);
3271
3486
  }
3272
3487
  dropTarget = null;
3273
3488
  if (detectResult && isValidTarget(activeComponent.node.origin, node.origin)) {
@@ -3277,7 +3492,7 @@ const withDnd = (board) => {
3277
3492
  }
3278
3493
  });
3279
3494
  if (dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.target) {
3280
- dropTarget = readjustmentDropTarget(dropTarget);
3495
+ dropTarget = readjustmentDropTarget(board, dropTarget);
3281
3496
  drawPlaceholderDropNodeG(board, dropTarget, fakeDropNodeG);
3282
3497
  }
3283
3498
  }
@@ -3289,12 +3504,13 @@ const withDnd = (board) => {
3289
3504
  const activeComponent = PlaitElement.getComponent(activeElement);
3290
3505
  const targetComponent = PlaitElement.getComponent(dropTarget.target);
3291
3506
  let targetPath = PlaitBoard.findPath(board, targetComponent.element);
3292
- const mindmapElement = findUpElement(dropTarget.target).root;
3293
- const mindmapComponent = ELEMENT_TO_COMPONENT.get(mindmapElement);
3294
- const layout = MindQueries.getCorrectLayoutByElement(mindmapComponent === null || mindmapComponent === void 0 ? void 0 : mindmapComponent.root.origin);
3507
+ const mindElement = findUpElement(dropTarget.target).root;
3508
+ const mindComponent = ELEMENT_TO_COMPONENT.get(mindElement);
3509
+ const layout = MindQueries.getCorrectLayoutByElement(board, mindComponent === null || mindComponent === void 0 ? void 0 : mindComponent.root.origin);
3295
3510
  targetPath = updatePathByLayoutAndDropTarget(targetPath, layout, dropTarget);
3296
3511
  const originPath = PlaitBoard.findPath(board, activeComponent.element);
3297
3512
  let newElement = { isCollapsed: false }, rightTargetPath = PlaitBoard.findPath(board, targetComponent.element);
3513
+ updateAbstractInDnd(board, [activeElement], targetPath);
3298
3514
  if (isStandardLayout(layout)) {
3299
3515
  updateRightNodeCount(board, activeComponent, targetComponent, dropTarget.detectResult);
3300
3516
  }
@@ -3327,122 +3543,45 @@ const withDnd = (board) => {
3327
3543
  };
3328
3544
  return board;
3329
3545
  };
3330
- const isValidTarget = (origin, target) => {
3331
- return origin !== target && !isChildElement(origin, target);
3332
- };
3333
- const addActiveOnDragOrigin = (activeElement, isOrigin = true) => {
3334
- const activeComponent = PlaitElement.getComponent(activeElement);
3335
- if (isOrigin) {
3336
- activeComponent.g.classList.add('dragging-origin');
3337
- }
3338
- else {
3339
- activeComponent.g.classList.add('dragging-child');
3340
- }
3341
- !activeElement.isCollapsed &&
3342
- activeElement.children.forEach(child => {
3343
- addActiveOnDragOrigin(child, false);
3344
- });
3345
- };
3346
- const removeActiveOnDragOrigin = (activeElement, isOrigin = true) => {
3347
- const activeComponent = PlaitElement.getComponent(activeElement);
3348
- if (isOrigin) {
3349
- activeComponent.g.classList.remove('dragging-origin');
3350
- }
3351
- else {
3352
- activeComponent.g.classList.remove('dragging-child');
3353
- }
3354
- !activeElement.isCollapsed &&
3355
- activeElement.children.forEach(child => {
3356
- removeActiveOnDragOrigin(child, false);
3357
- });
3358
- };
3359
- const updatePathByLayoutAndDropTarget = (targetPath, layout, dropTarget) => {
3360
- // 上下布局:左右是兄弟节点,上下是子节点
3361
- if (isVerticalLogicLayout(layout)) {
3362
- if (isTopLayout(layout) && dropTarget.detectResult === 'top') {
3363
- targetPath.push(dropTarget.target.children.length);
3364
- }
3365
- if (isBottomLayout(layout) && dropTarget.detectResult === 'bottom') {
3366
- targetPath.push(dropTarget.target.children.length);
3367
- }
3368
- // 如果是左,位置不变,右则插入到下一个兄弟节点
3369
- if (dropTarget.detectResult === 'right') {
3370
- targetPath = Path.next(targetPath);
3371
- }
3372
- }
3373
- // 水平布局/标准布局:上下是兄弟节点,左右是子节点
3374
- if (isHorizontalLogicLayout(layout)) {
3375
- if (dropTarget.detectResult === 'right') {
3376
- targetPath.push(dropTarget.target.children.length);
3377
- }
3378
- if (dropTarget.detectResult === 'left') {
3379
- targetPath.push(dropTarget.target.children.length);
3380
- }
3381
- // 如果是上,位置不变,下插入到下一个兄弟节点
3382
- if (dropTarget.detectResult === 'bottom') {
3383
- targetPath = Path.next(targetPath);
3384
- }
3385
- }
3386
- // 缩进布局:上下是兄弟节点,左右是子节点,但上(左上/右上),探测到上是子节点,下则位置不变,反之同理。
3387
- if (isIndentedLayout(layout)) {
3388
- if (isTopLayout(layout) && dropTarget.detectResult === 'top') {
3389
- targetPath = Path.next(targetPath);
3390
- }
3391
- if (isBottomLayout(layout) && dropTarget.detectResult === 'bottom') {
3392
- targetPath = Path.next(targetPath);
3393
- }
3394
- if (isLeftLayout(layout) && dropTarget.detectResult === 'left') {
3395
- targetPath.push(dropTarget.target.children.length);
3396
- }
3397
- if (isRightLayout(layout) && dropTarget.detectResult === 'right') {
3398
- targetPath.push(dropTarget.target.children.length);
3399
- }
3400
- }
3401
- return targetPath;
3402
- };
3403
- const updateRightNodeCount = (board, activeComponent, targetComponent, detectResult) => {
3404
- var _a;
3405
- let rightNodeCount;
3406
- const mindmapElement = findUpElement(targetComponent.node.origin).root;
3407
- const mindmapComponent = ELEMENT_TO_COMPONENT.get(mindmapElement);
3408
- const activeIndex = mindmapComponent === null || mindmapComponent === void 0 ? void 0 : mindmapComponent.root.children.indexOf(activeComponent.node);
3409
- const targetIndex = mindmapComponent === null || mindmapComponent === void 0 ? void 0 : mindmapComponent.root.children.indexOf(targetComponent.node);
3410
- const isActiveOnRight = activeIndex !== -1 && activeIndex <= activeComponent.parent.origin.rightNodeCount - 1;
3411
- const isTargetOnRight = targetComponent.parent && targetIndex !== -1 && targetIndex <= targetComponent.parent.origin.rightNodeCount - 1;
3412
- const isBothOnRight = isActiveOnRight && isTargetOnRight;
3413
- const rootChildCount = (_a = mindmapComponent.root.children) === null || _a === void 0 ? void 0 : _a.length;
3414
- const rootRightNodeCount = mindmapComponent === null || mindmapComponent === void 0 ? void 0 : mindmapComponent.root.origin.rightNodeCount;
3415
- if (!isBothOnRight) {
3416
- if (isActiveOnRight) {
3417
- rightNodeCount = rootChildCount < rootRightNodeCount ? rootChildCount - 1 : rootRightNodeCount - 1;
3418
- Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, activeComponent.parent.origin));
3419
- }
3420
- if (isTargetOnRight && detectResult !== 'right') {
3421
- rightNodeCount = rootChildCount < rootRightNodeCount ? rootRightNodeCount : rootRightNodeCount + 1;
3422
- Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, targetComponent.parent.origin));
3423
- }
3424
- //二级子节点拖动到根节点左侧
3425
- if (targetComponent.node.origin.isRoot && detectResult === 'left' && activeIndex === -1) {
3426
- rightNodeCount = rootChildCount;
3427
- Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, targetComponent.element));
3428
- }
3429
- }
3430
- };
3431
- const IS_DRAGGING = new WeakMap();
3432
- const isDragging = (board) => {
3433
- return !!IS_DRAGGING.get(board);
3434
- };
3435
- const setIsDragging = (board, state) => {
3436
- IS_DRAGGING.set(board, state);
3437
- };
3438
3546
 
3439
3547
  const buildClipboardData = (board, selectedElements) => {
3440
3548
  let result = [];
3441
- const selectedMindNodes = selectedElements.map(value => MindElement.getNode(value));
3442
- const nodesRectangle = getRectangleByElements(board, selectedElements, true);
3443
- selectedElements.forEach((node, index) => {
3549
+ // get overall abstract
3550
+ const overallAbstracts = getOverallAbstracts(board, selectedElements);
3551
+ // keep correct order
3552
+ const newSelectedElements = selectedElements.filter((value) => !overallAbstracts.includes(value));
3553
+ newSelectedElements.push(...overallAbstracts);
3554
+ // get correct start and end in selected elements
3555
+ function getCorrectStartEnd(abstract) {
3556
+ const parent = MindElement.getParent(abstract);
3557
+ const startElement = parent.children[abstract.start];
3558
+ const index = selectedElements.indexOf(startElement);
3559
+ return { start: index, end: index + (abstract.end - abstract.start) };
3560
+ }
3561
+ const selectedMindNodes = newSelectedElements.map(value => MindElement.getNode(value));
3562
+ const nodesRectangle = getRectangleByElements(board, newSelectedElements, true);
3563
+ newSelectedElements.forEach((element, index) => {
3564
+ // handle relative location
3444
3565
  const nodeRectangle = getRectangleByNode(selectedMindNodes[index]);
3445
- result.push(Object.assign(Object.assign({}, node), { points: [[nodeRectangle.x - nodesRectangle.x, nodeRectangle.y - nodesRectangle.y]] }));
3566
+ const points = [[nodeRectangle.x - nodesRectangle.x, nodeRectangle.y - nodesRectangle.y]];
3567
+ // handle invalid abstract
3568
+ if (AbstractNode.isAbstract(element) && overallAbstracts.includes(element)) {
3569
+ const { start, end } = getCorrectStartEnd(element);
3570
+ result.push(Object.assign(Object.assign({}, element), { points,
3571
+ start,
3572
+ end }));
3573
+ }
3574
+ else {
3575
+ if (AbstractNode.isAbstract(element)) {
3576
+ let newElement = Object.assign(Object.assign({}, element), { points });
3577
+ delete newElement.start;
3578
+ delete newElement.end;
3579
+ result.push(newElement);
3580
+ }
3581
+ else {
3582
+ result.push(Object.assign(Object.assign({}, element), { points: points }));
3583
+ }
3584
+ }
3446
3585
  });
3447
3586
  return result;
3448
3587
  };
@@ -3468,17 +3607,22 @@ const insertClipboardData = (board, elements, targetPoint) => {
3468
3607
  let newElement, path;
3469
3608
  const selectedElements = getSelectedElements(board);
3470
3609
  let newELements = [];
3610
+ const hasTargetParent = selectedElements.length === 1;
3611
+ const targetParent = selectedElements[0];
3612
+ const targetParentPath = targetParent && PlaitBoard.findPath(board, targetParent);
3613
+ const nonAbstractChildrenLength = targetParent && getNonAbstractChildren(targetParent).length;
3471
3614
  elements.forEach((item, index) => {
3472
3615
  newElement = copyNewNode(item);
3473
- if (selectedElements.length === 1) {
3616
+ if (hasTargetParent) {
3474
3617
  if (item.isRoot) {
3475
3618
  newElement = transformRootToNode(board, newElement);
3476
3619
  }
3477
- if (AbstractNode.isAbstract(item)) {
3478
- newElement = transformAbstractToNode(newElement);
3620
+ // handle abstract start and end
3621
+ if (AbstractNode.isAbstract(newElement)) {
3622
+ newElement.start = newElement.start + nonAbstractChildrenLength;
3623
+ newElement.end = newElement.end + nonAbstractChildrenLength;
3479
3624
  }
3480
- const selectedElementPath = PlaitBoard.findPath(board, selectedElements[0]);
3481
- path = selectedElementPath.concat((selectedElements[0].children || []).length + index);
3625
+ path = [...targetParentPath, nonAbstractChildrenLength + index];
3482
3626
  }
3483
3627
  else {
3484
3628
  const point = [targetPoint[0] + item.points[0][0], targetPoint[1] + item.points[0][1]];
@@ -3538,7 +3682,7 @@ const withAbstract = (board) => {
3538
3682
  event.preventDefault();
3539
3683
  const abstractComponent = PlaitElement.getComponent(activeAbstractElement);
3540
3684
  const element = abstractComponent.element;
3541
- const nodeLayout = MindQueries.getCorrectLayoutByElement(activeAbstractElement);
3685
+ const nodeLayout = MindQueries.getCorrectLayoutByElement(board, activeAbstractElement);
3542
3686
  const isHorizontal = isHorizontalLayout(nodeLayout);
3543
3687
  const parentElement = MindElement.getParent(element);
3544
3688
  let children = parentElement.children;
@@ -3641,7 +3785,11 @@ const withMind = (board) => {
3641
3785
  board.isHitSelection = (element, range) => {
3642
3786
  if (MindElement.isMindElement(board, element) && board.selection) {
3643
3787
  const client = getRectangleByNode(MindElement.getNode(element));
3644
- return RectangleClient.isHit(RectangleClient.toRectangleClient([range.anchor, range.focus]), client);
3788
+ const isHit = RectangleClient.isHit(RectangleClient.toRectangleClient([range.anchor, range.focus]), client);
3789
+ if (isHit && MindElement.hasEmojis(element) && Selection.isCollapsed(range) && isHitEmojis(board, element, range.anchor)) {
3790
+ return false;
3791
+ }
3792
+ return isHit;
3645
3793
  }
3646
3794
  return isHitSelection(element, range);
3647
3795
  };
@@ -3652,7 +3800,6 @@ const withMind = (board) => {
3652
3800
  return isMovable(element);
3653
3801
  };
3654
3802
  board.keydown = (event) => {
3655
- var _a, _b;
3656
3803
  if (board.options.readonly || IS_TEXT_EDITABLE.get(board)) {
3657
3804
  keydown(event);
3658
3805
  return;
@@ -3679,7 +3826,8 @@ const withMind = (board) => {
3679
3826
  if (shouldChangeRightNodeCount(selectedElement)) {
3680
3827
  changeRightNodeCount(board, selectedElementPath.slice(0, 1), 1);
3681
3828
  }
3682
- insertSiblingElementHandleAbstract(board, selectedElement);
3829
+ const abstractRefs = insertElementHandleAbstract(board, Path.next(selectedElementPath));
3830
+ MindTransforms.setAbstractsByRefs(board, abstractRefs);
3683
3831
  insertMindElement(board, selectedElement, findNewSiblingNodePath(board, selectedElement));
3684
3832
  }
3685
3833
  return;
@@ -3687,31 +3835,32 @@ const withMind = (board) => {
3687
3835
  if (hotkeys.isDeleteBackward(event) || hotkeys.isDeleteForward(event)) {
3688
3836
  event.preventDefault();
3689
3837
  deleteSelectedELements(board, selectedElements);
3690
- let lastNode = null;
3691
- const firstLevelElements = filterChildElement(selectedElements);
3838
+ let activeElement;
3839
+ const firstLevelElements = getFirstLevelElement(selectedElements);
3840
+ if (AbstractNode.isAbstract(firstLevelElements[0])) {
3841
+ const parent = MindElement.getParent(firstLevelElements[0]);
3842
+ activeElement = parent.children[firstLevelElements[0].start];
3843
+ }
3692
3844
  const firstElement = firstLevelElements[0];
3693
- const firstComponent = PlaitElement.getComponent(firstElement);
3694
- const nodeIndex = (_a = firstComponent === null || firstComponent === void 0 ? void 0 : firstComponent.parent) === null || _a === void 0 ? void 0 : _a.children.findIndex(item => item.origin.id === firstElement.id);
3695
- const isSameParent = firstLevelElements.every(element => {
3696
- return findParentElement(element) && findParentElement(firstLevelElements[0]) === findParentElement(element);
3845
+ const firstElementParent = MindElement.findParent(firstElement);
3846
+ const hasSameParent = firstLevelElements.every(element => {
3847
+ return MindElement.findParent(element) === firstElementParent;
3697
3848
  });
3698
- if (isSameParent) {
3699
- const childCount = ((_b = firstComponent.parent) === null || _b === void 0 ? void 0 : _b.children.length) - firstLevelElements.length;
3700
- if (childCount === 0) {
3701
- lastNode = firstComponent === null || firstComponent === void 0 ? void 0 : firstComponent.parent;
3849
+ if (firstElementParent && hasSameParent && !activeElement) {
3850
+ const firstElementIndex = firstElementParent.children.indexOf(firstElement);
3851
+ const childrenCount = firstElementParent.children.length;
3852
+ // active parent element
3853
+ if (childrenCount === firstLevelElements.length) {
3854
+ activeElement = firstElementParent;
3702
3855
  }
3703
- else if (nodeIndex === 0) {
3704
- lastNode = firstComponent === null || firstComponent === void 0 ? void 0 : firstComponent.parent.children[firstLevelElements.length];
3705
- }
3706
- else if (nodeIndex > 0) {
3707
- lastNode = firstComponent === null || firstComponent === void 0 ? void 0 : firstComponent.parent.children[nodeIndex - 1];
3856
+ else {
3857
+ if (firstElementIndex > 0) {
3858
+ activeElement = firstElementParent.children[firstElementIndex - 1];
3859
+ }
3708
3860
  }
3709
3861
  }
3710
- if (firstLevelElements.length === 1 && AbstractNode.isAbstract(firstElement)) {
3711
- lastNode = firstComponent.parent.children[firstElement.start];
3712
- }
3713
- if (lastNode) {
3714
- addSelectedElement(board, lastNode.origin);
3862
+ if (activeElement) {
3863
+ addSelectedElement(board, activeElement);
3715
3864
  }
3716
3865
  return;
3717
3866
  }
@@ -3738,8 +3887,8 @@ const withMind = (board) => {
3738
3887
  const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3739
3888
  board.children
3740
3889
  .filter(value => PlaitMind.isMind(value))
3741
- .forEach(mindmap => {
3742
- depthFirstRecursion(mindmap, node => {
3890
+ .forEach(mindMap => {
3891
+ depthFirstRecursion(mindMap, node => {
3743
3892
  if (!PlaitBoard.hasBeenTextEditing(board) && hitMindElement(board, point, node)) {
3744
3893
  enterNodeEditing(node);
3745
3894
  }
@@ -3751,7 +3900,7 @@ const withMind = (board) => {
3751
3900
  dblclick(event);
3752
3901
  };
3753
3902
  board.setFragment = (data) => {
3754
- const selectedElements = filterChildElement(getSelectedElements(board));
3903
+ const selectedElements = getFirstLevelElement(getSelectedElements(board));
3755
3904
  if (selectedElements.length) {
3756
3905
  const elements = buildClipboardData(board, selectedElements);
3757
3906
  setClipboardData(data, elements);
@@ -3825,5 +3974,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
3825
3974
  * Generated bundle index. Do not edit.
3826
3975
  */
3827
3976
 
3828
- export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, COLORS, ELEMENT_TO_NODE, EXTEND_OFFSET, EXTEND_RADIUS, GRAY_COLOR, LayoutDirection, LayoutDirectionsMap, MAX_RADIUS, MINDMAP_KEY, MindElement, MindEmojiBaseComponent, MindModule, MindNode, MindNodeComponent, MindNodeShape, MindQueries, MindTransforms, NODE_FILL, NODE_MIN_WIDTH, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_NODE_FILL, ROOT_NODE_STROKE, ROOT_TOPIC_FONT_SIZE, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, TRANSPARENT, canSetAbstract, changeRightNodeCount, copyNewNode, correctLayoutByDirection, createDefaultMindMapElement, createMindElement, deleteSelectedELements, directionCorrector, directionDetector, divideElementByParent, drawCurvePlaceholderDropNodeG, drawIndentNodeG, drawPlaceholderDropNodeG, drawStraightDropNodeG, extractNodesText, filterChildElement, findLastChild, findLocationLeftIndex, findParentElement, findUpElement, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getChildrenCount, getCorrespondingAbstract, getDefaultLayout, getEmojiFontSize, getEmojisRectangle, getHitAbstractHandle, getHorizontalFakeY, getInCorrectLayoutDirection, getIndentedFakePoint, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection, getLocationScope, getNextBranchColor, getNodeShapeByElement, getRectangleByNode, getRectangleByResizingLocation, getRootLayout, getStrokeByMindElement, handleAbstractIncluded, handleTouchedAbstract, hitMindElement, insertAbstractNode, insertMindElement, insertSiblingElementHandleAbstract, isChildElement, isChildRight, isChildUp, isCorrectLayout, isMixedLayout, isSetAbstract, isVirtualKey, moveAbstractPosition, readjustmentDropTarget, separateChildren, setAbstract, setAbstractByElements, shouldChangeRightNodeCount, transformAbstractToNode, transformNodeToRoot, transformRootToNode, withExtendMind, withMind };
3977
+ export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_COLORS, BRANCH_WIDTH, DefaultAbstractNodeStyle, DefaultNodeStyle, DefaultRootStyle, ELEMENT_TO_NODE, EXTEND_OFFSET, EXTEND_RADIUS, GRAY_COLOR, LayoutDirection, LayoutDirectionsMap, MindElement, MindElementShape, MindEmojiBaseComponent, MindModule, MindNode, MindNodeComponent, MindQueries, MindTransforms, NODE_MIN_WIDTH, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_TOPIC_FONT_SIZE, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, TRANSPARENT, canSetAbstract, changeRightNodeCount, copyNewNode, correctLayoutByDirection, createDefaultMindMapElement, createMindElement, deleteElementHandleAbstract, deleteSelectedELements, directionCorrector, directionDetector, divideElementByParent, drawCurvePlaceholderDropNodeG, drawIndentNodeG, drawPlaceholderDropNodeG, drawStraightDropNodeG, extractNodesText, findLastChild, findLocationLeftIndex, findUpElement, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultLayout, getEmojiFontSize, getEmojiForeignRectangle, getEmojiRectangle, getEmojisWidthHeight, getFirstLevelElement, getHitAbstractHandle, getHorizontalFakeY, getInCorrectLayoutDirection, getIndentedFakePoint, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection, getLocationScope, getNextBranchColor, getOverallAbstracts, getRectangleByNode, getRectangleByResizingLocation, getRootLayout, getShapeByElement, getStrokeByMindElement, handleTouchedAbstract, hitMindElement, insertElementHandleAbstract, insertMindElement, isChildElement, isChildRight, isChildUp, isCorrectLayout, isHitEmojis, isMixedLayout, isSetAbstract, isVirtualKey, readjustmentDropTarget, separateChildren, shouldChangeRightNodeCount, transformAbstractToNode, transformNodeToRoot, transformRootToNode, withExtendMind, withMind };
3829
3978
  //# sourceMappingURL=plait-mind.mjs.map