@plait/mind 0.2.0-next.8 → 0.2.0-next.9

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 (74) 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/esm2020/constants/abstract-node.mjs +5 -0
  8. package/esm2020/constants/default.mjs +2 -3
  9. package/esm2020/constants/index.mjs +5 -2
  10. package/esm2020/constants/node-rule.mjs +2 -0
  11. package/esm2020/constants/node-style.mjs +19 -0
  12. package/esm2020/constants/node-topic-style.mjs +5 -0
  13. package/esm2020/draw/abstract.mjs +4 -3
  14. package/esm2020/draw/indented-link.mjs +14 -14
  15. package/esm2020/draw/link/abstract-link.mjs +6 -4
  16. package/esm2020/draw/link/logic-link.mjs +7 -7
  17. package/esm2020/draw/link.mjs +6 -5
  18. package/esm2020/draw/shape.mjs +4 -4
  19. package/esm2020/drawer/quick-insert.drawer.mjs +11 -12
  20. package/esm2020/interfaces/abstract.mjs +1 -1
  21. package/esm2020/interfaces/element.mjs +6 -1
  22. package/esm2020/interfaces/node.mjs +1 -1
  23. package/esm2020/layout-option.mjs +3 -3
  24. package/esm2020/node.component.mjs +11 -9
  25. package/esm2020/plugins/with-abstract.mjs +2 -2
  26. package/esm2020/plugins/with-dnd.mjs +11 -116
  27. package/esm2020/plugins/with-mind.mjs +7 -5
  28. package/esm2020/queries/get-available-sublayouts-by-element.mjs +4 -9
  29. package/esm2020/queries/get-branch-layouts.mjs +4 -4
  30. package/esm2020/queries/get-correct-layout-by-element.mjs +28 -31
  31. package/esm2020/queries/get-layout-by-element.mjs +10 -8
  32. package/esm2020/queries/index.mjs +1 -3
  33. package/esm2020/transforms/abstract-node.mjs +68 -0
  34. package/esm2020/transforms/index.mjs +6 -2
  35. package/esm2020/transforms/layout.mjs +3 -3
  36. package/esm2020/transforms/node.mjs +2 -2
  37. package/esm2020/utils/abstract/common.mjs +90 -70
  38. package/esm2020/utils/abstract/resize.mjs +3 -3
  39. package/esm2020/utils/clipboard.mjs +54 -14
  40. package/esm2020/utils/direction-corrector.mjs +11 -11
  41. package/esm2020/utils/dnd.mjs +118 -0
  42. package/esm2020/utils/draw-placeholder.mjs +5 -5
  43. package/esm2020/utils/drop-target-corrector.mjs +11 -10
  44. package/esm2020/utils/layout.mjs +1 -1
  45. package/esm2020/utils/mind.mjs +23 -58
  46. package/esm2020/utils/node-style/branch.mjs +33 -6
  47. package/esm2020/utils/node-style/node.mjs +6 -5
  48. package/esm2020/utils/path.mjs +4 -3
  49. package/esm2020/utils/shape.mjs +3 -3
  50. package/fesm2015/plait-mind.mjs +691 -575
  51. package/fesm2015/plait-mind.mjs.map +1 -1
  52. package/fesm2020/plait-mind.mjs +693 -573
  53. package/fesm2020/plait-mind.mjs.map +1 -1
  54. package/interfaces/abstract.d.ts +3 -0
  55. package/interfaces/element.d.ts +5 -2
  56. package/package.json +1 -1
  57. package/plugins/with-dnd.d.ts +0 -9
  58. package/queries/get-available-sublayouts-by-element.d.ts +2 -6
  59. package/queries/get-branch-layouts.d.ts +2 -1
  60. package/queries/get-correct-layout-by-element.d.ts +2 -1
  61. package/queries/index.d.ts +3 -4
  62. package/transforms/abstract-node.d.ts +6 -0
  63. package/transforms/index.d.ts +3 -0
  64. package/utils/abstract/common.d.ts +6 -8
  65. package/utils/direction-corrector.d.ts +2 -1
  66. package/utils/dnd.d.ts +16 -0
  67. package/utils/drop-target-corrector.d.ts +2 -1
  68. package/utils/mind.d.ts +3 -3
  69. package/utils/node-style/branch.d.ts +3 -0
  70. package/utils/shape.d.ts +2 -3
  71. package/constants/node.d.ts +0 -17
  72. package/esm2020/constants/node.mjs +0 -19
  73. package/esm2020/queries/get-layout-parent-by-element.mjs +0 -17
  74. package/queries/get-layout-parent-by-element.d.ts +0 -8
@@ -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, CLIP_BOARD_FORMAT_KEY, BOARD_TO_HOST, 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;
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;
84
94
  }
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);
97
- }
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;
99
+ }
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
+ }
101
111
  }
102
- if (parentComponent && parentComponent.node.origin.isRoot) {
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,16 +121,13 @@ 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
132
  let parent = findParentElement(element);
126
133
  while (parent) {
@@ -132,15 +139,10 @@ const getBranchLayouts = (element) => {
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) => {
142
+ const getAvailableSubLayoutsByElement = (board, element) => {
141
143
  const parentElement = findParentElement(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 = MindElement.getParent(element);
270
+ if (AbstractNode.isAbstract(element)) {
271
+ return getAbstractLayout(getLayoutByElement(parent));
272
+ }
273
+ if (parent) {
274
+ return getLayoutByElement(parent);
184
275
  }
185
- return getLayoutParentByElement(element);
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
@@ -258,6 +348,11 @@ const MindElement = {
258
348
  return element.data.emojis;
259
349
  }
260
350
  };
351
+ var MindElementShape;
352
+ (function (MindElementShape) {
353
+ MindElementShape["roundRectangle"] = "round-rectangle";
354
+ MindElementShape["underline"] = "underline";
355
+ })(MindElementShape || (MindElementShape = {}));
261
356
 
262
357
  const MindNode = {
263
358
  get(root, path) {
@@ -312,109 +407,6 @@ var AbstractResizeState;
312
407
  AbstractResizeState["end"] = "end";
313
408
  })(AbstractResizeState || (AbstractResizeState = {}));
314
409
 
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
410
  function enterNodeEditing(element) {
419
411
  const component = ELEMENT_TO_COMPONENT.get(element);
420
412
  component.startEditText(false, false);
@@ -434,22 +426,146 @@ const separateChildren = (parentElement) => {
434
426
  leftChildren.push(child);
435
427
  continue;
436
428
  }
437
- if (i < rightNodeCount) {
438
- rightChildren.push(child);
429
+ if (i < rightNodeCount) {
430
+ rightChildren.push(child);
431
+ }
432
+ else {
433
+ leftChildren.push(child);
434
+ }
435
+ }
436
+ return { leftChildren, rightChildren };
437
+ };
438
+ const isSetAbstract = (element) => {
439
+ const parent = MindElement.getParent(element);
440
+ return !!getCorrespondingAbstract(parent, element);
441
+ };
442
+ const canSetAbstract = (element) => {
443
+ return !PlaitElement.isRootElement(element) && !AbstractNode.isAbstract(element) && !isSetAbstract(element);
444
+ };
445
+ const getCorrespondingAbstract = (parent, element) => {
446
+ if (!parent)
447
+ return undefined;
448
+ const elementIndex = parent.children.indexOf(element);
449
+ return parent.children.find(child => {
450
+ return AbstractNode.isAbstract(child) && elementIndex >= child.start && elementIndex <= child.end;
451
+ });
452
+ };
453
+ const getBehindAbstracts = (parent, element) => {
454
+ const index = parent.children.indexOf(element);
455
+ return parent.children.filter(child => AbstractNode.isAbstract(child) && child.start > index);
456
+ };
457
+ const getOverallAbstracts = (board, elements) => {
458
+ const overallAbstracts = [];
459
+ elements
460
+ .filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
461
+ .forEach(value => {
462
+ const parent = MindElement.getParent(value);
463
+ const abstract = getCorrespondingAbstract(parent, value);
464
+ if (abstract && overallAbstracts.indexOf(abstract) === -1) {
465
+ const { start, end } = abstract;
466
+ const parent = MindElement.getParent(value);
467
+ const isOverall = parent.children.slice(start, end + 1).every(includedElement => elements.indexOf(includedElement) > -1);
468
+ if (isOverall) {
469
+ overallAbstracts.push(abstract);
470
+ }
471
+ }
472
+ });
473
+ return overallAbstracts;
474
+ };
475
+ const insertElementHandleAbstract = (board, path,
476
+ //由此区分拖拽和新增到概要概括最后一个节点
477
+ isExtendPreviousNode = true, abstractRefs = new Map()) => {
478
+ const parent = PlaitNode.parent(board, path);
479
+ const hasPreviousNode = path[path.length - 1] !== 0;
480
+ let behindAbstracts;
481
+ if (!hasPreviousNode) {
482
+ behindAbstracts = parent.children.filter(child => AbstractNode.isAbstract(child));
483
+ }
484
+ else {
485
+ const selectedElement = PlaitNode.get(board, Path.previous(path));
486
+ behindAbstracts = getBehindAbstracts(parent, selectedElement);
487
+ }
488
+ if (behindAbstracts.length) {
489
+ behindAbstracts.forEach(abstract => {
490
+ let newProperties = abstractRefs.get(abstract);
491
+ if (!newProperties) {
492
+ newProperties = { start: 0, end: 0 };
493
+ abstractRefs.set(abstract, newProperties);
494
+ }
495
+ newProperties.start = newProperties.start + 1;
496
+ newProperties.end = newProperties.end + 1;
497
+ });
498
+ }
499
+ if (!hasPreviousNode) {
500
+ return abstractRefs;
501
+ }
502
+ const selectedElement = PlaitNode.get(board, Path.previous(path));
503
+ const correspondingAbstract = getCorrespondingAbstract(parent, selectedElement);
504
+ const isDragToLast = !isExtendPreviousNode && correspondingAbstract && correspondingAbstract.end === path[path.length - 1] - 1;
505
+ if (correspondingAbstract && !isDragToLast) {
506
+ let newProperties = abstractRefs.get(correspondingAbstract);
507
+ if (!newProperties) {
508
+ newProperties = { start: 0, end: 0 };
509
+ abstractRefs.set(correspondingAbstract, newProperties);
510
+ }
511
+ newProperties.end = newProperties.end + 1;
512
+ }
513
+ return abstractRefs;
514
+ };
515
+ const deleteElementHandleAbstract = (board, deletableElements, abstractRefs = new Map()) => {
516
+ deletableElements.forEach(node => {
517
+ if (!PlaitMind.isMind(node)) {
518
+ const parent = PlaitNode.parent(board, PlaitBoard.findPath(board, node));
519
+ const behindAbstracts = getBehindAbstracts(parent, node).filter(abstract => !deletableElements.includes(abstract));
520
+ if (behindAbstracts.length) {
521
+ behindAbstracts.forEach(abstract => {
522
+ let newProperties = abstractRefs.get(abstract);
523
+ if (!newProperties) {
524
+ newProperties = { start: 0, end: 0 };
525
+ abstractRefs.set(abstract, newProperties);
526
+ }
527
+ newProperties.start = newProperties.start - 1;
528
+ newProperties.end = newProperties.end - 1;
529
+ });
530
+ }
531
+ const correspondingAbstract = getCorrespondingAbstract(parent, node);
532
+ if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
533
+ let newProperties = abstractRefs.get(correspondingAbstract);
534
+ if (!newProperties) {
535
+ newProperties = { start: 0, end: 0 };
536
+ abstractRefs.set(correspondingAbstract, newProperties);
537
+ }
538
+ newProperties.end = newProperties.end - 1;
539
+ }
540
+ }
541
+ });
542
+ return abstractRefs;
543
+ };
544
+
545
+ const setAbstractsByRefs = (board, abstractRefs) => {
546
+ abstractRefs.forEach((newProperty, element) => {
547
+ const start = element.start + newProperty.start;
548
+ const end = element.end + newProperty.end;
549
+ const path = PlaitBoard.findPath(board, element);
550
+ if (start > end) {
551
+ Transforms.removeNode(board, path);
439
552
  }
440
553
  else {
441
- leftChildren.push(child);
554
+ Transforms.setNode(board, { start, end }, path);
442
555
  }
443
- }
444
- return { leftChildren, rightChildren };
445
- };
446
- const isSetAbstract = (element) => {
447
- return !!getCorrespondingAbstract(element);
556
+ });
448
557
  };
449
- const canSetAbstract = (element) => {
450
- return !PlaitElement.isRootElement(element) && !AbstractNode.isAbstract(element) && !isSetAbstract(element);
558
+ const setAbstractByStandardLayout = (board, element) => {
559
+ const rightNodeCount = element.rightNodeCount;
560
+ const abstract = element.children.find(child => {
561
+ return AbstractNode.isAbstract(child) && child.end >= rightNodeCount && child.start < rightNodeCount;
562
+ });
563
+ if (abstract) {
564
+ const path = PlaitBoard.findPath(board, abstract);
565
+ Transforms.setNode(board, { end: rightNodeCount - 1 }, path);
566
+ }
451
567
  };
452
- const setAbstract = (board, elements) => {
568
+ const insertAbstract = (board, elements) => {
453
569
  let elementGroup = filterChildElement(elements);
454
570
  const { parentElements, abstractIncludedGroups } = divideElementByParent(elementGroup);
455
571
  abstractIncludedGroups.forEach((group, index) => {
@@ -479,52 +595,109 @@ const setAbstractByElements = (board, groupParent, group) => {
479
595
  };
480
596
  const insertAbstractNode = (board, path, start, end) => {
481
597
  const mindElement = createMindElement('概要', 28, 20, {
482
- strokeColor: GRAY_COLOR,
483
- branchColor: GRAY_COLOR
598
+ strokeColor: DefaultAbstractNodeStyle.strokeColor,
599
+ strokeWidth: DefaultAbstractNodeStyle.branchWidth,
600
+ branchColor: DefaultAbstractNodeStyle.branchColor,
601
+ branchWidth: DefaultAbstractNodeStyle.branchWidth
484
602
  });
485
603
  mindElement.start = start;
486
604
  mindElement.end = end;
487
605
  Transforms.insertNode(board, mindElement, path);
488
606
  };
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);
607
+
608
+ const setLayout = (board, layout, path) => {
609
+ correctLogicLayoutNode(board, layout, path);
610
+ const element = PlaitNode.get(board, path);
611
+ if (PlaitMind.isMind(element) && isStandardLayout(layout)) {
612
+ MindTransforms.setAbstractByStandardLayout(board, element);
497
613
  }
614
+ Transforms.setNode(board, { layout }, path);
498
615
  };
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
- });
507
- };
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);
616
+ const correctLogicLayoutNode = (board, layout, path) => {
617
+ var _a;
618
+ const node = PlaitNode.get(board, path);
619
+ if (node && layout) {
620
+ (_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach((value, index) => {
621
+ var _a;
622
+ if (value.layout) {
623
+ if ((isHorizontalLogicLayout(layout) && isVerticalLogicLayout(value.layout)) ||
624
+ (isVerticalLogicLayout(layout) && isHorizontalLogicLayout(value.layout))) {
625
+ Transforms.setNode(board, { layout: null }, [...path, index]);
626
+ }
627
+ if ((_a = value.children) === null || _a === void 0 ? void 0 : _a.length) {
628
+ correctLogicLayoutNode(board, layout, [...path, index]);
629
+ }
630
+ }
631
+ });
632
+ }
512
633
  };
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));
634
+
635
+ const setTopic = (board, element, topic, width, height) => {
636
+ const newElement = {
637
+ data: { topic },
638
+ width: width < NODE_MIN_WIDTH * board.viewport.zoom ? NODE_MIN_WIDTH : width / board.viewport.zoom,
639
+ height: height / board.viewport.zoom
640
+ };
641
+ if (MindElement.hasEmojis(element)) {
642
+ newElement.data.emojis = element.data.emojis;
518
643
  }
519
- const abstracts = getBehindAbstracts(selectedElement);
520
- if (abstracts.length) {
521
- moveAbstractPosition(board, abstracts, 1);
644
+ const path = PlaitBoard.findPath(board, element);
645
+ Transforms.setNode(board, newElement, path);
646
+ };
647
+ const setTopicSize = (board, element, width, height) => {
648
+ const newElement = {
649
+ width: width < NODE_MIN_WIDTH * board.viewport.zoom ? NODE_MIN_WIDTH : width / board.viewport.zoom,
650
+ height: height / board.viewport.zoom
651
+ };
652
+ const path = PlaitBoard.findPath(board, element);
653
+ Transforms.setNode(board, newElement, path);
654
+ };
655
+ const addEmoji = (board, element, emojiItem) => {
656
+ const emojis = element.data.emojis || [];
657
+ const newEmojis = [...emojis];
658
+ newEmojis.push(emojiItem);
659
+ const newElement = {
660
+ data: { topic: element.data.topic, emojis: newEmojis }
661
+ };
662
+ const path = PlaitBoard.findPath(board, element);
663
+ Transforms.setNode(board, newElement, path);
664
+ };
665
+ const removeEmoji = (board, element, emojiItem) => {
666
+ const emojis = element.data.emojis.filter(value => value !== emojiItem);
667
+ const newElement = {
668
+ data: { topic: element.data.topic }
669
+ };
670
+ if (emojis.length > 0) {
671
+ newElement.data.emojis = emojis;
522
672
  }
673
+ const path = PlaitBoard.findPath(board, element);
674
+ Transforms.setNode(board, newElement, path);
523
675
  };
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));
676
+ const replaceEmoji = (board, element, oldEmoji, newEmoji) => {
677
+ const newElement = {
678
+ data: { topic: element.data.topic }
679
+ };
680
+ const newEmojis = element.data.emojis.map(value => {
681
+ if (value === oldEmoji) {
682
+ return newEmoji;
683
+ }
684
+ return value;
527
685
  });
686
+ newElement.data.emojis = newEmojis;
687
+ const path = PlaitBoard.findPath(board, element);
688
+ Transforms.setNode(board, newElement, path);
689
+ };
690
+
691
+ const MindTransforms = {
692
+ setLayout,
693
+ setTopic,
694
+ setTopicSize,
695
+ addEmoji,
696
+ removeEmoji,
697
+ replaceEmoji,
698
+ insertAbstract,
699
+ setAbstractsByRefs,
700
+ setAbstractByStandardLayout
528
701
  };
529
702
 
530
703
  function findParentElement(element) {
@@ -659,13 +832,13 @@ const shouldChangeRightNodeCount = (selectedElement) => {
659
832
  return false;
660
833
  };
661
834
  const createDefaultMindMapElement = (point, rightNodeCount, layout) => {
662
- const root = createMindElement('思维导图', 72, ROOT_DEFAULT_HEIGHT, { shape: MindNodeShape.roundRectangle, layout });
835
+ const root = createMindElement('思维导图', 72, ROOT_DEFAULT_HEIGHT, { shape: MindElementShape.roundRectangle, layout });
663
836
  root.rightNodeCount = rightNodeCount;
664
837
  root.isRoot = true;
665
838
  root.type = 'mindmap';
666
839
  root.points = [point];
667
840
  const children = [1, 1, 1].map(() => {
668
- return createMindElement('新建节点', 56, TEXT_DEFAULT_HEIGHT, { shape: MindNodeShape.roundRectangle });
841
+ return createMindElement('新建节点', 56, TEXT_DEFAULT_HEIGHT, { shape: MindElementShape.roundRectangle });
669
842
  });
670
843
  root.children = children;
671
844
  return root;
@@ -702,11 +875,14 @@ const createMindElement = (text, width, height, options) => {
702
875
  if (options.branchColor) {
703
876
  newElement.branchColor = options.branchColor;
704
877
  }
878
+ if (!isNullOrUndefined(options.branchWidth)) {
879
+ newElement.branchWidth = options.branchWidth;
880
+ }
705
881
  return newElement;
706
882
  };
707
883
  // layoutLevel 用来表示插入兄弟节点还是子节点
708
884
  const insertMindElement = (board, inheritNode, path) => {
709
- let fill, strokeColor, strokeWidth, shape = MindNodeShape.roundRectangle;
885
+ let fill, strokeColor, strokeWidth, shape = MindElementShape.roundRectangle;
710
886
  if (!inheritNode.isRoot) {
711
887
  fill = inheritNode.fill;
712
888
  strokeColor = inheritNode.strokeColor;
@@ -729,63 +905,23 @@ const findLastChild = (child) => {
729
905
  return result;
730
906
  };
731
907
  const deleteSelectedELements = (board, selectedElements) => {
732
- //翻转,从下到上修改,防止找不到 path
733
908
  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);
909
+ const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
910
+ MindTransforms.setAbstractsByRefs(board, abstractRefs);
911
+ //翻转,从下到上修改,防止找不到 path
912
+ deletableElements
913
+ .map(element => {
914
+ const path = PlaitBoard.findPath(board, element);
780
915
  return () => {
781
- if (shouldChangeRightNodeCount(node)) {
782
- changeRightNodeCount(board, path.slice(0, path.length - 1), -1);
916
+ if (shouldChangeRightNodeCount(element)) {
917
+ changeRightNodeCount(board, path.slice(0, 1), -1);
783
918
  }
784
919
  Transforms.removeNode(board, path);
785
920
  };
921
+ })
922
+ .forEach(action => {
923
+ action();
786
924
  });
787
- abstractHandles.forEach(action => action());
788
- deletableHandles.forEach(action => action());
789
925
  };
790
926
  const divideElementByParent = (elements) => {
791
927
  const abstractIncludedGroups = [];
@@ -816,9 +952,12 @@ const getNodeShapeByElement = (element) => {
816
952
  }
817
953
  parent = findParentElement(parent);
818
954
  }
819
- return MindNodeShape.roundRectangle;
955
+ return MindElementShape.roundRectangle;
820
956
  };
821
957
 
958
+ /**
959
+ * Processing of branch color, width, style, etc. of the mind node
960
+ */
822
961
  const getBranchColorByMindElement = (board, element) => {
823
962
  const ancestors = MindElement.getAncestors(board, element);
824
963
  ancestors.unshift(element);
@@ -830,19 +969,40 @@ const getBranchColorByMindElement = (board, element) => {
830
969
  const branch = ancestors[ancestors.length - 2];
831
970
  if (branch) {
832
971
  const index = root.children.indexOf(branch);
833
- const length = COLORS.length;
972
+ const length = BRANCH_COLORS.length;
834
973
  const remainder = index % length;
835
- return COLORS[remainder];
974
+ return BRANCH_COLORS[remainder];
836
975
  }
837
976
  else {
838
977
  throw new Error('root element should not have branch color');
839
978
  }
840
979
  };
980
+ const getBranchWidthByMindElement = (board, element) => {
981
+ const ancestors = MindElement.getAncestors(board, element);
982
+ ancestors.unshift(element);
983
+ const ancestor = ancestors.find(value => value.branchColor);
984
+ if (ancestor && ancestor.branchWidth) {
985
+ return ancestor.branchWidth;
986
+ }
987
+ return BRANCH_WIDTH;
988
+ };
989
+ const getAbstractBranchWidth = (board, element) => {
990
+ if (!isNullOrUndefined(element.branchWidth)) {
991
+ return element.branchWidth;
992
+ }
993
+ return DefaultAbstractNodeStyle.branchWidth;
994
+ };
995
+ const getAbstractBranchColor = (board, element) => {
996
+ if (element.branchColor) {
997
+ return element.branchColor;
998
+ }
999
+ return DefaultAbstractNodeStyle.branchColor;
1000
+ };
841
1001
  const getNextBranchColor = (root) => {
842
1002
  const index = root.children.length;
843
- const length = COLORS.length;
1003
+ const length = BRANCH_COLORS.length;
844
1004
  const remainder = index % length;
845
- return COLORS[remainder];
1005
+ return BRANCH_COLORS[remainder];
846
1006
  };
847
1007
 
848
1008
  const getStrokeByMindElement = (board, element) => {
@@ -856,12 +1016,12 @@ const getStrokeByMindElement = (board, element) => {
856
1016
  const branch = ancestors[ancestors.length - 2];
857
1017
  if (branch) {
858
1018
  const index = root.children.indexOf(branch);
859
- const length = COLORS.length;
1019
+ const length = BRANCH_COLORS.length;
860
1020
  const remainder = index % length;
861
- return COLORS[remainder];
1021
+ return BRANCH_COLORS[remainder];
862
1022
  }
863
1023
  else {
864
- return ROOT_NODE_STROKE;
1024
+ return DefaultRootStyle.strokeColor;
865
1025
  }
866
1026
  };
867
1027
 
@@ -880,7 +1040,7 @@ function isVirtualKey(e) {
880
1040
  function drawLink(board, node, child, defaultStroke = null, isHorizontal = true, needDrawUnderline = true) {
881
1041
  var _a;
882
1042
  let beginX, beginY, endX, endY, beginNode = node, endNode = child;
883
- const layout = MindQueries.getCorrectLayoutByElement(node.origin);
1043
+ const layout = MindQueries.getCorrectLayoutByElement(board, node.origin);
884
1044
  if (isHorizontal) {
885
1045
  if (!isChildRight(node, child)) {
886
1046
  beginNode = child;
@@ -892,7 +1052,7 @@ function drawLink(board, node, child, defaultStroke = null, isHorizontal = true,
892
1052
  endY = endNode.y + endNode.height / 2;
893
1053
  if (node.parent &&
894
1054
  isIndentedLayout(MindQueries.getLayoutByElement((_a = node.parent) === null || _a === void 0 ? void 0 : _a.origin)) &&
895
- getNodeShapeByElement(node.origin) === MindNodeShape.underline) {
1055
+ getNodeShapeByElement(node.origin) === MindElementShape.underline) {
896
1056
  if (isChildRight(node, child)) {
897
1057
  beginY = node.y + node.height - node.vGap;
898
1058
  }
@@ -967,7 +1127,7 @@ function drawLink(board, node, child, defaultStroke = null, isHorizontal = true,
967
1127
  curve = [...line, ...curve];
968
1128
  }
969
1129
  }
970
- if (needDrawUnderline && shape === MindNodeShape.underline) {
1130
+ if (needDrawUnderline && shape === MindElementShape.underline) {
971
1131
  if (child.left) {
972
1132
  const underline = [
973
1133
  [beginX - (beginNode.width - beginNode.hGap * 2), beginY],
@@ -1043,8 +1203,8 @@ const drawPlaceholderDropNodeG = (board, dropTarget, fakeDropNodeG) => {
1043
1203
  }
1044
1204
  };
1045
1205
  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);
1206
+ const parentNodeLayout = MindQueries.getCorrectLayoutByElement(board, parentComponent.node.origin);
1207
+ const layout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.parent.origin);
1048
1208
  const strokeWidth = targetComponent.node.origin.branchWidth ? targetComponent.node.origin.branchWidth : STROKE_WIDTH;
1049
1209
  let fakeX = targetComponent.node.x, fakeY = targetRect.y - 30, fakeRectangleStartX = targetRect.x, fakeRectangleEndX = targetRect.x + 30, fakeRectangleStartY = fakeY, fakeRectangleEndY = fakeRectangleStartY + 12, width = 30;
1050
1210
  if (isLeftLayout(layout)) {
@@ -1175,8 +1335,8 @@ const drawStraightDropNodeG = (board, targetRect, detectResult, targetComponent,
1175
1335
  height,
1176
1336
  strokeWidth
1177
1337
  };
1178
- const parentLayout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
1179
- const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
1338
+ const parentLayout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
1339
+ const layout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin);
1180
1340
  if (!isMixedLayout(parentLayout, layout)) {
1181
1341
  // 构造一条直线
1182
1342
  let linePoints = [
@@ -1386,29 +1546,29 @@ const directionDetector = (targetNode, centerPoint) => {
1386
1546
  return null;
1387
1547
  };
1388
1548
 
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)) {
1549
+ const directionCorrector = (board, node, detectResults) => {
1550
+ if (!node.origin.isRoot && !AbstractNode.isAbstract(node.origin)) {
1551
+ const parentLayout = MindQueries.getCorrectLayoutByElement(board, node === null || node === void 0 ? void 0 : node.parent.origin);
1552
+ if (isStandardLayout(parentLayout)) {
1393
1553
  const idx = node.parent.children.findIndex(x => x === node);
1394
1554
  const isLeft = idx >= (node.parent.origin.rightNodeCount || 0);
1395
1555
  return getAllowedDirection(detectResults, [isLeft ? 'right' : 'left']);
1396
1556
  }
1397
- if (isLeftLayout(parentlayout)) {
1557
+ if (isLeftLayout(parentLayout)) {
1398
1558
  return getAllowedDirection(detectResults, ['right']);
1399
1559
  }
1400
- if (isRightLayout(parentlayout)) {
1560
+ if (isRightLayout(parentLayout)) {
1401
1561
  return getAllowedDirection(detectResults, ['left']);
1402
1562
  }
1403
- if (parentlayout === MindLayoutType.upward) {
1563
+ if (parentLayout === MindLayoutType.upward) {
1404
1564
  return getAllowedDirection(detectResults, ['bottom']);
1405
1565
  }
1406
- if (parentlayout === MindLayoutType.downward) {
1566
+ if (parentLayout === MindLayoutType.downward) {
1407
1567
  return getAllowedDirection(detectResults, ['top']);
1408
1568
  }
1409
1569
  }
1410
1570
  else {
1411
- const layout = MindQueries.getCorrectLayoutByElement(node === null || node === void 0 ? void 0 : node.origin);
1571
+ const layout = MindQueries.getCorrectLayoutByElement(board, node === null || node === void 0 ? void 0 : node.origin);
1412
1572
  if (isStandardLayout(layout)) {
1413
1573
  return getAllowedDirection(detectResults, ['top', 'bottom']);
1414
1574
  }
@@ -1439,17 +1599,18 @@ const getAllowedDirection = (detectResults, illegalDirections) => {
1439
1599
  };
1440
1600
 
1441
1601
  /* 根据布局调整 target 以及 direction */
1442
- const readjustmentDropTarget = (dropTarget) => {
1602
+ const readjustmentDropTarget = (board, dropTarget) => {
1443
1603
  const { target, detectResult } = dropTarget;
1444
1604
  const newDropTarget = { target, detectResult };
1445
1605
  const targetComponent = PlaitElement.getComponent(target);
1446
1606
  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);
1607
+ const layout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin);
1608
+ const parentLayout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
1609
+ const children = getNonAbstractChildren(targetComponent.node);
1449
1610
  if (['right', 'left'].includes(dropTarget.detectResult)) {
1450
1611
  if (!isMixedLayout(parentLayout, layout)) {
1451
1612
  if (targetComponent.node.origin.isRoot) {
1452
- const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
1613
+ const layout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin);
1453
1614
  // 标准布局,根节点
1454
1615
  if (isStandardLayout(layout)) {
1455
1616
  const rightNodeCount = targetComponent.node.origin.rightNodeCount;
@@ -1483,14 +1644,14 @@ const readjustmentDropTarget = (dropTarget) => {
1483
1644
  return newDropTarget;
1484
1645
  }
1485
1646
  // 剩下是水平布局的默认情况:插入最后一个子节点的下方
1486
- const lastChildNodeIndex = targetComponent.node.children.length - 1;
1647
+ const lastChildNodeIndex = children.length - 1;
1487
1648
  newDropTarget.target = targetComponent.node.children[lastChildNodeIndex].origin;
1488
1649
  newDropTarget.detectResult = 'bottom';
1489
1650
  }
1490
1651
  else {
1491
1652
  // 处理左右布局下的混合布局
1492
1653
  if ([MindLayoutType.left, MindLayoutType.right].includes(parentLayout)) {
1493
- const layout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin);
1654
+ const layout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin);
1494
1655
  if (isIndentedLayout(layout)) {
1495
1656
  newDropTarget.target = targetComponent.node.children[0].origin;
1496
1657
  newDropTarget.detectResult = isTopLayout(layout) ? 'bottom' : 'top';
@@ -1507,9 +1668,9 @@ const readjustmentDropTarget = (dropTarget) => {
1507
1668
  return newDropTarget;
1508
1669
  }
1509
1670
  // 上下布局,插到右边
1510
- const parentLayout = MindQueries.getCorrectLayoutByElement(targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
1671
+ const parentLayout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
1511
1672
  if (isVerticalLogicLayout(parentLayout)) {
1512
- const lastChildNodeIndex = targetComponent.node.children.length - 1;
1673
+ const lastChildNodeIndex = children.length - 1;
1513
1674
  newDropTarget.target = targetComponent.node.children[lastChildNodeIndex].origin;
1514
1675
  newDropTarget.detectResult = 'right';
1515
1676
  return newDropTarget;
@@ -1606,7 +1767,7 @@ const getLocationScope = (board, handlePosition, parentChildren, element, parent
1606
1767
  }
1607
1768
  };
1608
1769
  const getHitAbstractHandle = (board, element, point) => {
1609
- const nodeLayout = MindQueries.getCorrectLayoutByElement(element);
1770
+ const nodeLayout = MindQueries.getCorrectLayoutByElement(board, element);
1610
1771
  const isHorizontal = isHorizontalLayout(nodeLayout);
1611
1772
  const parentElement = MindElement.getParent(element);
1612
1773
  const includedElements = parentElement.children.slice(element.start, element.end + 1);
@@ -1693,24 +1854,25 @@ function handleTouchedAbstract(board, touchedAbstract, endPoint) {
1693
1854
  }
1694
1855
 
1695
1856
  function drawIndentedLink(board, node, child, defaultStroke = null, needDrawUnderline = true) {
1696
- const isUnderlineShap = getNodeShapeByElement(child.origin) === MindNodeShape.underline;
1857
+ const branchWidth = getBranchWidthByMindElement(board, child.origin);
1858
+ const branchColor = defaultStroke || getBranchColorByMindElement(board, child.origin);
1859
+ const isUnderlineShape = getNodeShapeByElement(child.origin) === MindElementShape.underline;
1697
1860
  let beginX, beginY, endX, endY, beginNode = node, endNode = child;
1698
1861
  const beginRectangle = getRectangleByNode(beginNode);
1699
1862
  const endRectangle = getRectangleByNode(endNode);
1700
1863
  beginX = beginNode.x + beginNode.width / 2;
1701
1864
  beginY = isChildUp(node, child) ? beginRectangle.y : beginRectangle.y + beginRectangle.height;
1702
1865
  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;
1866
+ endY = isUnderlineShape ? endNode.y + endNode.height - endNode.vGap : endNode.y + endNode.height / 2;
1704
1867
  //根据位置,设置正负参数
1705
1868
  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;
1869
+ const layout = MindQueries.getCorrectLayoutByElement(board, node.origin);
1708
1870
  if (beginNode.origin.isRoot) {
1709
1871
  if (layout === MindLayoutType.leftBottomIndented || layout === MindLayoutType.rightBottomIndented) {
1710
- beginY += strokeWidth;
1872
+ beginY += branchWidth;
1711
1873
  }
1712
1874
  if (layout === MindLayoutType.leftTopIndented || layout === MindLayoutType.rightTopIndented) {
1713
- beginY -= strokeWidth;
1875
+ beginY -= branchWidth;
1714
1876
  }
1715
1877
  }
1716
1878
  let curve = [
@@ -1721,13 +1883,12 @@ function drawIndentedLink(board, node, child, defaultStroke = null, needDrawUnde
1721
1883
  [beginX, endY - (endNode.hGap * plusMinus[1]) / 5],
1722
1884
  [beginX + (endNode.hGap * plusMinus[0]) / 4, endY],
1723
1885
  [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]
1886
+ isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
1887
+ isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
1888
+ isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY]
1727
1889
  ];
1728
- const stroke = defaultStroke || getBranchColorByMindElement(board, child.origin);
1729
1890
  const points = pointsOnBezierCurves(curve);
1730
- return PlaitBoard.getRoughSVG(board).curve(points, { stroke, strokeWidth });
1891
+ return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth: branchWidth });
1731
1892
  }
1732
1893
 
1733
1894
  var HorizontalPlacement;
@@ -1842,10 +2003,10 @@ const transformPlacement = (placement, direction) => {
1842
2003
 
1843
2004
  function drawLogicLink(board, node, parent, isHorizontal) {
1844
2005
  const branchColor = getBranchColorByMindElement(board, node.origin);
1845
- const strokeWidth = node.origin.branchWidth ? node.origin.branchWidth : STROKE_WIDTH;
2006
+ const branchWidth = getBranchWidthByMindElement(board, node.origin);
1846
2007
  const hasStraightLine = !parent.origin.isRoot;
1847
- const hasUnderlineShape = node.origin.shape === MindNodeShape.underline;
1848
- const hasUnderlineShapeOfParent = parent.origin.shape === MindNodeShape.underline;
2008
+ const hasUnderlineShape = node.origin.shape === MindElementShape.underline;
2009
+ const hasUnderlineShapeOfParent = parent.origin.shape === MindElementShape.underline;
1849
2010
  const nodeClient = getRectangleByNode(node);
1850
2011
  const parentClient = getRectangleByNode(parent);
1851
2012
  const linkDirection = getLayoutDirection(node, isHorizontal);
@@ -1882,7 +2043,7 @@ function drawLogicLink(board, node, parent, isHorizontal) {
1882
2043
  const underlineEnd = movePoint(endPoint, nodeClient.width, linkDirection);
1883
2044
  const underline = hasUnderlineShape && isHorizontal ? [underlineEnd, underlineEnd, underlineEnd] : [];
1884
2045
  const points = pointsOnBezierCurves([...straightLine, ...curve, ...underline]);
1885
- return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth });
2046
+ return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth: branchWidth });
1886
2047
  }
1887
2048
 
1888
2049
  function getEmojisRectangle(board, element) {
@@ -2008,9 +2169,9 @@ function getRichtextRectangleByNode(board, node) {
2008
2169
 
2009
2170
  function drawRectangleNode(board, node) {
2010
2171
  const { x, y, width, height } = getRectangleByNode(node);
2011
- const fill = node.origin.fill ? node.origin.fill : node.origin.isRoot ? ROOT_NODE_FILL : NODE_FILL;
2172
+ const fill = node.origin.fill ? node.origin.fill : node.origin.isRoot ? DefaultRootStyle.fill : DefaultNodeStyle.fill;
2012
2173
  const stroke = getStrokeByMindElement(board, node.origin);
2013
- const strokeWidth = node.origin.strokeWidth ? node.origin.strokeWidth : STROKE_WIDTH;
2174
+ const strokeWidth = node.origin.strokeWidth ? node.origin.strokeWidth : DefaultNodeStyle.strokeWidth;
2014
2175
  const nodeG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), x, y, x + width, y + height, {
2015
2176
  stroke,
2016
2177
  strokeWidth,
@@ -2022,6 +2183,8 @@ function drawRectangleNode(board, node) {
2022
2183
 
2023
2184
  function drawAbstractLink(board, node, isHorizontal) {
2024
2185
  const linkPadding = 15;
2186
+ const branchWidth = getAbstractBranchWidth(board, node.origin);
2187
+ const branchColor = getAbstractBranchColor(board, node.origin);
2025
2188
  const parent = node.parent;
2026
2189
  const abstractRectangle = getRectangleByNode(node);
2027
2190
  let includedElements = parent.children.slice(node.origin.start, node.origin.end + 1).map(node => {
@@ -2051,8 +2214,8 @@ function drawAbstractLink(board, node, isHorizontal) {
2051
2214
  let c2 = movePoint(bezierEndPoint, curveDistance, linkDirection);
2052
2215
  let bezierConnectorPoint = movePoint(abstractConnectorPoint, -linkPadding, linkDirection);
2053
2216
  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
2217
+ stroke: branchColor,
2218
+ strokeWidth: branchWidth
2056
2219
  });
2057
2220
  return link;
2058
2221
  }
@@ -2106,123 +2269,31 @@ class EmojisDrawer {
2106
2269
  const container = document.createElement('div');
2107
2270
  container.classList.add('node-emojis-container');
2108
2271
  foreignObject.append(container);
2109
- this.emojiDrawers = element.data.emojis.map(emojiItem => {
2110
- const drawer = new EmojiDrawer(this.board, this.viewContainerRef);
2111
- drawer.draw(emojiItem, element);
2112
- 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;
2272
+ this.emojiDrawers = element.data.emojis.map(emojiItem => {
2273
+ const drawer = new EmojiDrawer(this.board, this.viewContainerRef);
2274
+ drawer.draw(emojiItem, element);
2275
+ return drawer;
2276
+ });
2277
+ this.emojiDrawers.forEach(drawer => {
2278
+ container.append(drawer.nativeElement);
2279
+ });
2280
+ return this.g;
2281
+ }
2282
+ return undefined;
2194
2283
  }
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;
2284
+ destroy() {
2285
+ if (this.g) {
2286
+ this.g.remove();
2205
2287
  }
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
- };
2288
+ this.emojiDrawers.forEach(drawer => drawer.destroy());
2289
+ this.emojiDrawers = [];
2290
+ }
2291
+ }
2221
2292
 
2222
2293
  function drawAbstractIncludedOutline(board, roughSVG, element, activeHandlePosition, resizingLocation) {
2223
2294
  const abstractIncludedG = createG();
2224
2295
  const parentElement = MindElement.getParent(element);
2225
- const nodeLayout = MindQueries.getCorrectLayoutByElement(element);
2296
+ const nodeLayout = MindQueries.getCorrectLayoutByElement(board, element);
2226
2297
  const isHorizontal = isHorizontalLayout(nodeLayout);
2227
2298
  const includedElements = parentElement.children.slice(element.start, element.end + 1);
2228
2299
  let abstractRectangle = getRectangleByElements(board, includedElements, true);
@@ -2302,7 +2373,8 @@ function hasAfterDraw(value) {
2302
2373
  }
2303
2374
 
2304
2375
  function findNewChildNodePath(board, element) {
2305
- return PlaitBoard.findPath(board, element).concat((element.children || []).filter(child => !AbstractNode.isAbstract(child)).length);
2376
+ const children = getNonAbstractChildren(element);
2377
+ return PlaitBoard.findPath(board, element).concat(children.length);
2306
2378
  }
2307
2379
  function findNewSiblingNodePath(board, element) {
2308
2380
  const path = PlaitBoard.findPath(board, element);
@@ -2332,14 +2404,14 @@ class QuickInsertDrawer extends BaseDrawer {
2332
2404
  */
2333
2405
  const shape = getNodeShapeByElement(element);
2334
2406
  // 形状是矩形要偏移边框的线宽
2335
- const strokeWidth = element.branchWidth ? element.branchWidth : STROKE_WIDTH;
2407
+ const branchWidth = getBranchWidthByMindElement(this.board, element);
2336
2408
  let offsetBorderLineWidth = 0;
2337
- if (shape === MindNodeShape.roundRectangle && offset === 0) {
2338
- offsetBorderLineWidth = strokeWidth;
2409
+ if (shape === MindElementShape.roundRectangle && offset === 0) {
2410
+ offsetBorderLineWidth = branchWidth;
2339
2411
  }
2340
2412
  let offsetRootBorderLineWidth = 0;
2341
2413
  if (element.isRoot) {
2342
- offsetRootBorderLineWidth = strokeWidth;
2414
+ offsetRootBorderLineWidth = branchWidth;
2343
2415
  }
2344
2416
  // 当没有子节点时,需要缩小的偏移量
2345
2417
  const extraOffset = 3;
@@ -2434,21 +2506,21 @@ class QuickInsertDrawer extends BaseDrawer {
2434
2506
  offsetRootBorderLineWidth
2435
2507
  }
2436
2508
  };
2437
- if (shape === MindNodeShape.roundRectangle || element.isRoot) {
2509
+ if (shape === MindElementShape.roundRectangle || element.isRoot) {
2438
2510
  underlineCoordinates[MindLayoutType.left].startY -= height * 0.5;
2439
2511
  underlineCoordinates[MindLayoutType.left].endY -= height * 0.5;
2440
2512
  underlineCoordinates[MindLayoutType.right].startY -= height * 0.5;
2441
2513
  underlineCoordinates[MindLayoutType.right].endY -= height * 0.5;
2442
2514
  }
2443
2515
  const branchColor = PlaitMind.isMind(element) ? getNextBranchColor(element) : getBranchColorByMindElement(this.board, element);
2444
- let nodeLayout = MindQueries.getCorrectLayoutByElement(element);
2516
+ let nodeLayout = MindQueries.getCorrectLayoutByElement(this.board, element);
2445
2517
  if (element.isRoot && isStandardLayout(nodeLayout)) {
2446
2518
  const root = element;
2447
2519
  nodeLayout = root.children.length >= root.rightNodeCount ? MindLayoutType.left : MindLayoutType.right;
2448
2520
  }
2449
2521
  const underlineCoordinate = underlineCoordinates[nodeLayout];
2450
2522
  if (underlineCoordinate) {
2451
- const underline = PlaitBoard.getRoughSVG(this.board).line(underlineCoordinate.startX, underlineCoordinate.startY, underlineCoordinate.endX, underlineCoordinate.endY, { stroke: branchColor, strokeWidth });
2523
+ const underline = PlaitBoard.getRoughSVG(this.board).line(underlineCoordinate.startX, underlineCoordinate.startY, underlineCoordinate.endX, underlineCoordinate.endY, { stroke: branchColor, strokeWidth: branchWidth });
2452
2524
  const circleCoordinates = {
2453
2525
  startX: underlineCoordinate.endX,
2454
2526
  startY: underlineCoordinate.endY
@@ -2590,7 +2662,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2590
2662
  this.destroyShape();
2591
2663
  const shape = getNodeShapeByElement(this.node.origin);
2592
2664
  switch (shape) {
2593
- case MindNodeShape.roundRectangle:
2665
+ case MindElementShape.roundRectangle:
2594
2666
  this.shapeG = drawRectangleNode(this.board, this.node);
2595
2667
  this.g.prepend(this.shapeG);
2596
2668
  break;
@@ -2778,9 +2850,9 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2778
2850
  });
2779
2851
  const { x, y, width, height } = getRectangleByNode(this.node);
2780
2852
  const stroke = getBranchColorByMindElement(this.board, this.element);
2781
- const strokeWidth = this.node.origin.branchWidth ? this.node.origin.branchWidth : STROKE_WIDTH;
2853
+ const branchWidth = getBranchWidthByMindElement(this.board, this.element);
2782
2854
  const extendY = y + height / 2;
2783
- const nodeLayout = MindQueries.getCorrectLayoutByElement(this.element);
2855
+ const nodeLayout = MindQueries.getCorrectLayoutByElement(this.board, this.element);
2784
2856
  let extendLineXY = [
2785
2857
  [x + width, extendY],
2786
2858
  [x + width + EXTEND_OFFSET, extendY]
@@ -2792,7 +2864,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2792
2864
  let circleOffset = [EXTEND_RADIUS / 2, 0];
2793
2865
  if (isHorizontalLayout(nodeLayout) && !isIndentedLayout(nodeLayout)) {
2794
2866
  extendLineYOffset =
2795
- getNodeShapeByElement(this.node.origin) === MindNodeShape.roundRectangle
2867
+ getNodeShapeByElement(this.node.origin) === MindElementShape.roundRectangle
2796
2868
  ? [0, 0]
2797
2869
  : [height / 2, height / 2];
2798
2870
  if (isLeftLayout(nodeLayout)) {
@@ -2824,7 +2896,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2824
2896
  [extendLineXY[1][0] + extendLineXOffset[1], extendLineXY[1][1] + extendLineYOffset[1]]
2825
2897
  ];
2826
2898
  const extendLine = this.roughSVG.line(extendLineXY[0][0], extendLineXY[0][1], extendLineXY[1][0], extendLineXY[1][1], {
2827
- strokeWidth,
2899
+ strokeWidth: branchWidth,
2828
2900
  stroke
2829
2901
  });
2830
2902
  //绘制箭头
@@ -2861,7 +2933,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2861
2933
  const hideCircleG = this.roughSVG.circle(extendLineXY[1][0] + circleOffset[0], extendLineXY[1][1] + circleOffset[1], EXTEND_RADIUS - 1, {
2862
2934
  fill: '#fff',
2863
2935
  stroke,
2864
- strokeWidth,
2936
+ strokeWidth: branchWidth,
2865
2937
  fillStyle: 'solid'
2866
2938
  });
2867
2939
  collapseG.appendChild(hideCircleG);
@@ -3101,7 +3173,7 @@ const getLayoutOptions = (board) => {
3101
3173
  }
3102
3174
  },
3103
3175
  getVerticalConnectingPosition(element, parent) {
3104
- if (element.shape === MindNodeShape.underline && parent && isHorizontalLogicLayout(parent.layout)) {
3176
+ if (element.shape === MindElementShape.underline && parent && isHorizontalLogicLayout(parent.layout)) {
3105
3177
  return ConnectingPosition.bottom;
3106
3178
  }
3107
3179
  return undefined;
@@ -3170,6 +3242,120 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
3170
3242
  }]
3171
3243
  }] });
3172
3244
 
3245
+ const isValidTarget = (origin, target) => {
3246
+ return origin !== target && !isChildElement(origin, target);
3247
+ };
3248
+ const addActiveOnDragOrigin = (activeElement, isOrigin = true) => {
3249
+ const activeComponent = PlaitElement.getComponent(activeElement);
3250
+ if (isOrigin) {
3251
+ activeComponent.g.classList.add('dragging-origin');
3252
+ }
3253
+ else {
3254
+ activeComponent.g.classList.add('dragging-child');
3255
+ }
3256
+ !activeElement.isCollapsed &&
3257
+ activeElement.children.forEach(child => {
3258
+ addActiveOnDragOrigin(child, false);
3259
+ });
3260
+ };
3261
+ const removeActiveOnDragOrigin = (activeElement, isOrigin = true) => {
3262
+ const activeComponent = PlaitElement.getComponent(activeElement);
3263
+ if (isOrigin) {
3264
+ activeComponent.g.classList.remove('dragging-origin');
3265
+ }
3266
+ else {
3267
+ activeComponent.g.classList.remove('dragging-child');
3268
+ }
3269
+ !activeElement.isCollapsed &&
3270
+ activeElement.children.forEach(child => {
3271
+ removeActiveOnDragOrigin(child, false);
3272
+ });
3273
+ };
3274
+ const updatePathByLayoutAndDropTarget = (targetPath, layout, dropTarget) => {
3275
+ // 上下布局:左右是兄弟节点,上下是子节点
3276
+ if (isVerticalLogicLayout(layout)) {
3277
+ if (isTopLayout(layout) && dropTarget.detectResult === 'top') {
3278
+ targetPath.push(dropTarget.target.children.length);
3279
+ }
3280
+ if (isBottomLayout(layout) && dropTarget.detectResult === 'bottom') {
3281
+ targetPath.push(dropTarget.target.children.length);
3282
+ }
3283
+ // 如果是左,位置不变,右则插入到下一个兄弟节点
3284
+ if (dropTarget.detectResult === 'right') {
3285
+ targetPath = Path.next(targetPath);
3286
+ }
3287
+ }
3288
+ // 水平布局/标准布局:上下是兄弟节点,左右是子节点
3289
+ if (isHorizontalLogicLayout(layout)) {
3290
+ if (dropTarget.detectResult === 'right') {
3291
+ targetPath.push(dropTarget.target.children.length);
3292
+ }
3293
+ if (dropTarget.detectResult === 'left') {
3294
+ targetPath.push(dropTarget.target.children.length);
3295
+ }
3296
+ // 如果是上,位置不变,下插入到下一个兄弟节点
3297
+ if (dropTarget.detectResult === 'bottom') {
3298
+ targetPath = Path.next(targetPath);
3299
+ }
3300
+ }
3301
+ // 缩进布局:上下是兄弟节点,左右是子节点,但上(左上/右上),探测到上是子节点,下则位置不变,反之同理。
3302
+ if (isIndentedLayout(layout)) {
3303
+ if (isTopLayout(layout) && dropTarget.detectResult === 'top') {
3304
+ targetPath = Path.next(targetPath);
3305
+ }
3306
+ if (isBottomLayout(layout) && dropTarget.detectResult === 'bottom') {
3307
+ targetPath = Path.next(targetPath);
3308
+ }
3309
+ if (isLeftLayout(layout) && dropTarget.detectResult === 'left') {
3310
+ targetPath.push(dropTarget.target.children.length);
3311
+ }
3312
+ if (isRightLayout(layout) && dropTarget.detectResult === 'right') {
3313
+ targetPath.push(dropTarget.target.children.length);
3314
+ }
3315
+ }
3316
+ return targetPath;
3317
+ };
3318
+ const updateRightNodeCount = (board, activeComponent, targetComponent, detectResult) => {
3319
+ var _a;
3320
+ let rightNodeCount;
3321
+ const mindElement = findUpElement(targetComponent.node.origin).root;
3322
+ const mindComponent = ELEMENT_TO_COMPONENT.get(mindElement);
3323
+ const activeIndex = mindComponent === null || mindComponent === void 0 ? void 0 : mindComponent.root.children.indexOf(activeComponent.node);
3324
+ const targetIndex = mindComponent === null || mindComponent === void 0 ? void 0 : mindComponent.root.children.indexOf(targetComponent.node);
3325
+ const isActiveOnRight = activeIndex !== -1 && activeIndex <= activeComponent.parent.origin.rightNodeCount - 1;
3326
+ const isTargetOnRight = targetComponent.parent && targetIndex !== -1 && targetIndex <= targetComponent.parent.origin.rightNodeCount - 1;
3327
+ const isBothOnRight = isActiveOnRight && isTargetOnRight;
3328
+ const rootChildCount = (_a = mindComponent.root.children) === null || _a === void 0 ? void 0 : _a.length;
3329
+ const rootRightNodeCount = mindComponent === null || mindComponent === void 0 ? void 0 : mindComponent.root.origin.rightNodeCount;
3330
+ if (!isBothOnRight) {
3331
+ if (isActiveOnRight) {
3332
+ rightNodeCount = rootChildCount < rootRightNodeCount ? rootChildCount - 1 : rootRightNodeCount - 1;
3333
+ Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, activeComponent.parent.origin));
3334
+ }
3335
+ if (isTargetOnRight && detectResult !== 'right') {
3336
+ rightNodeCount = rootChildCount < rootRightNodeCount ? rootRightNodeCount : rootRightNodeCount + 1;
3337
+ Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, targetComponent.parent.origin));
3338
+ }
3339
+ //二级子节点拖动到根节点左侧
3340
+ if (targetComponent.node.origin.isRoot && detectResult === 'left' && activeIndex === -1) {
3341
+ rightNodeCount = rootChildCount;
3342
+ Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, targetComponent.element));
3343
+ }
3344
+ }
3345
+ };
3346
+ const IS_DRAGGING = new WeakMap();
3347
+ const isDragging = (board) => {
3348
+ return !!IS_DRAGGING.get(board);
3349
+ };
3350
+ const setIsDragging = (board, state) => {
3351
+ IS_DRAGGING.set(board, state);
3352
+ };
3353
+ const updateAbstractInDnd = (board, deletableElements, originPath) => {
3354
+ const refs = insertElementHandleAbstract(board, originPath, false);
3355
+ deleteElementHandleAbstract(board, deletableElements, refs);
3356
+ MindTransforms.setAbstractsByRefs(board, refs);
3357
+ };
3358
+
3173
3359
  const DRAG_MOVE_BUFFER = 5;
3174
3360
  const withDnd = (board) => {
3175
3361
  const { mousedown, mousemove, globalMouseup, keydown } = board;
@@ -3267,7 +3453,7 @@ const withDnd = (board) => {
3267
3453
  }
3268
3454
  const directions = directionDetector(node, detectCenterPoint);
3269
3455
  if (directions) {
3270
- detectResult = directionCorrector(node, directions);
3456
+ detectResult = directionCorrector(board, node, directions);
3271
3457
  }
3272
3458
  dropTarget = null;
3273
3459
  if (detectResult && isValidTarget(activeComponent.node.origin, node.origin)) {
@@ -3277,7 +3463,7 @@ const withDnd = (board) => {
3277
3463
  }
3278
3464
  });
3279
3465
  if (dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.target) {
3280
- dropTarget = readjustmentDropTarget(dropTarget);
3466
+ dropTarget = readjustmentDropTarget(board, dropTarget);
3281
3467
  drawPlaceholderDropNodeG(board, dropTarget, fakeDropNodeG);
3282
3468
  }
3283
3469
  }
@@ -3289,12 +3475,13 @@ const withDnd = (board) => {
3289
3475
  const activeComponent = PlaitElement.getComponent(activeElement);
3290
3476
  const targetComponent = PlaitElement.getComponent(dropTarget.target);
3291
3477
  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);
3478
+ const mindElement = findUpElement(dropTarget.target).root;
3479
+ const mindComponent = ELEMENT_TO_COMPONENT.get(mindElement);
3480
+ const layout = MindQueries.getCorrectLayoutByElement(board, mindComponent === null || mindComponent === void 0 ? void 0 : mindComponent.root.origin);
3295
3481
  targetPath = updatePathByLayoutAndDropTarget(targetPath, layout, dropTarget);
3296
3482
  const originPath = PlaitBoard.findPath(board, activeComponent.element);
3297
3483
  let newElement = { isCollapsed: false }, rightTargetPath = PlaitBoard.findPath(board, targetComponent.element);
3484
+ updateAbstractInDnd(board, [activeElement], targetPath);
3298
3485
  if (isStandardLayout(layout)) {
3299
3486
  updateRightNodeCount(board, activeComponent, targetComponent, dropTarget.detectResult);
3300
3487
  }
@@ -3327,122 +3514,45 @@ const withDnd = (board) => {
3327
3514
  };
3328
3515
  return board;
3329
3516
  };
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
3517
 
3439
3518
  const buildClipboardData = (board, selectedElements) => {
3440
3519
  let result = [];
3441
- const selectedMindNodes = selectedElements.map(value => MindElement.getNode(value));
3442
- const nodesRectangle = getRectangleByElements(board, selectedElements, true);
3443
- selectedElements.forEach((node, index) => {
3520
+ // get overall abstract
3521
+ const overallAbstracts = getOverallAbstracts(board, selectedElements);
3522
+ // keep correct order
3523
+ const newSelectedElements = selectedElements.filter((value) => !overallAbstracts.includes(value));
3524
+ newSelectedElements.push(...overallAbstracts);
3525
+ // get correct start and end in selected elements
3526
+ function getCorrectStartEnd(abstract) {
3527
+ const parent = MindElement.getParent(abstract);
3528
+ const startElement = parent.children[abstract.start];
3529
+ const index = selectedElements.indexOf(startElement);
3530
+ return { start: index, end: index + (abstract.end - abstract.start) };
3531
+ }
3532
+ const selectedMindNodes = newSelectedElements.map(value => MindElement.getNode(value));
3533
+ const nodesRectangle = getRectangleByElements(board, newSelectedElements, true);
3534
+ newSelectedElements.forEach((element, index) => {
3535
+ // handle relative location
3444
3536
  const nodeRectangle = getRectangleByNode(selectedMindNodes[index]);
3445
- result.push(Object.assign(Object.assign({}, node), { points: [[nodeRectangle.x - nodesRectangle.x, nodeRectangle.y - nodesRectangle.y]] }));
3537
+ const points = [[nodeRectangle.x - nodesRectangle.x, nodeRectangle.y - nodesRectangle.y]];
3538
+ // handle invalid abstract
3539
+ if (AbstractNode.isAbstract(element) && overallAbstracts.includes(element)) {
3540
+ const { start, end } = getCorrectStartEnd(element);
3541
+ result.push(Object.assign(Object.assign({}, element), { points,
3542
+ start,
3543
+ end }));
3544
+ }
3545
+ else {
3546
+ if (AbstractNode.isAbstract(element)) {
3547
+ let newElement = Object.assign(Object.assign({}, element), { points });
3548
+ delete newElement.start;
3549
+ delete newElement.end;
3550
+ result.push(newElement);
3551
+ }
3552
+ else {
3553
+ result.push(Object.assign(Object.assign({}, element), { points: points }));
3554
+ }
3555
+ }
3446
3556
  });
3447
3557
  return result;
3448
3558
  };
@@ -3468,17 +3578,22 @@ const insertClipboardData = (board, elements, targetPoint) => {
3468
3578
  let newElement, path;
3469
3579
  const selectedElements = getSelectedElements(board);
3470
3580
  let newELements = [];
3581
+ const hasTargetParent = selectedElements.length === 1;
3582
+ const targetParent = selectedElements[0];
3583
+ const targetParentPath = targetParent && PlaitBoard.findPath(board, targetParent);
3584
+ const nonAbstractChildrenLength = targetParent && getNonAbstractChildren(targetParent).length;
3471
3585
  elements.forEach((item, index) => {
3472
3586
  newElement = copyNewNode(item);
3473
- if (selectedElements.length === 1) {
3587
+ if (hasTargetParent) {
3474
3588
  if (item.isRoot) {
3475
3589
  newElement = transformRootToNode(board, newElement);
3476
3590
  }
3477
- if (AbstractNode.isAbstract(item)) {
3478
- newElement = transformAbstractToNode(newElement);
3591
+ // handle abstract start and end
3592
+ if (AbstractNode.isAbstract(newElement)) {
3593
+ newElement.start = newElement.start + nonAbstractChildrenLength;
3594
+ newElement.end = newElement.end + nonAbstractChildrenLength;
3479
3595
  }
3480
- const selectedElementPath = PlaitBoard.findPath(board, selectedElements[0]);
3481
- path = selectedElementPath.concat((selectedElements[0].children || []).length + index);
3596
+ path = [...targetParentPath, nonAbstractChildrenLength + index];
3482
3597
  }
3483
3598
  else {
3484
3599
  const point = [targetPoint[0] + item.points[0][0], targetPoint[1] + item.points[0][1]];
@@ -3538,7 +3653,7 @@ const withAbstract = (board) => {
3538
3653
  event.preventDefault();
3539
3654
  const abstractComponent = PlaitElement.getComponent(activeAbstractElement);
3540
3655
  const element = abstractComponent.element;
3541
- const nodeLayout = MindQueries.getCorrectLayoutByElement(activeAbstractElement);
3656
+ const nodeLayout = MindQueries.getCorrectLayoutByElement(board, activeAbstractElement);
3542
3657
  const isHorizontal = isHorizontalLayout(nodeLayout);
3543
3658
  const parentElement = MindElement.getParent(element);
3544
3659
  let children = parentElement.children;
@@ -3679,7 +3794,8 @@ const withMind = (board) => {
3679
3794
  if (shouldChangeRightNodeCount(selectedElement)) {
3680
3795
  changeRightNodeCount(board, selectedElementPath.slice(0, 1), 1);
3681
3796
  }
3682
- insertSiblingElementHandleAbstract(board, selectedElement);
3797
+ const abstractRefs = insertElementHandleAbstract(board, Path.next(selectedElementPath));
3798
+ MindTransforms.setAbstractsByRefs(board, abstractRefs);
3683
3799
  insertMindElement(board, selectedElement, findNewSiblingNodePath(board, selectedElement));
3684
3800
  }
3685
3801
  return;
@@ -3825,5 +3941,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
3825
3941
  * Generated bundle index. Do not edit.
3826
3942
  */
3827
3943
 
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 };
3944
+ 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, filterChildElement, findLastChild, findLocationLeftIndex, findParentElement, findUpElement, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultLayout, getEmojiFontSize, getEmojisRectangle, getHitAbstractHandle, getHorizontalFakeY, getInCorrectLayoutDirection, getIndentedFakePoint, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection, getLocationScope, getNextBranchColor, getNodeShapeByElement, getOverallAbstracts, getRectangleByNode, getRectangleByResizingLocation, getRootLayout, getStrokeByMindElement, handleTouchedAbstract, hitMindElement, insertElementHandleAbstract, insertMindElement, isChildElement, isChildRight, isChildUp, isCorrectLayout, isMixedLayout, isSetAbstract, isVirtualKey, readjustmentDropTarget, separateChildren, shouldChangeRightNodeCount, transformAbstractToNode, transformNodeToRoot, transformRootToNode, withExtendMind, withMind };
3829
3945
  //# sourceMappingURL=plait-mind.mjs.map