@plait/mind 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/drawer/{emoji.drawer.d.ts → emojis.drawer.d.ts} +2 -1
  2. package/esm2020/base/emoji-base.component.mjs +3 -3
  3. package/esm2020/drawer/emojis.drawer.mjs +73 -0
  4. package/esm2020/interfaces/element.mjs +6 -1
  5. package/esm2020/mind.component.mjs +3 -3
  6. package/esm2020/mind.module.mjs +4 -4
  7. package/esm2020/node.component.mjs +11 -15
  8. package/esm2020/plugins/with-abstract-resize.mjs +6 -2
  9. package/esm2020/plugins/with-mind-create.mjs +5 -4
  10. package/esm2020/plugins/with-mind.mjs +9 -4
  11. package/esm2020/plugins/with-node-dnd.mjs +13 -12
  12. package/esm2020/transforms/index.mjs +4 -3
  13. package/esm2020/transforms/node.mjs +11 -8
  14. package/esm2020/utils/dnd/common.mjs +29 -1
  15. package/esm2020/utils/dnd/detector.mjs +1 -7
  16. package/esm2020/utils/draw/abstract-outline.mjs +75 -0
  17. package/esm2020/utils/draw/node-dnd.mjs +133 -0
  18. package/esm2020/utils/draw/node-link/abstract-link.mjs +54 -0
  19. package/esm2020/utils/draw/node-link/draw-link.mjs +9 -0
  20. package/esm2020/utils/draw/node-link/indented-link.mjs +54 -0
  21. package/esm2020/utils/draw/node-link/logic-link.mjs +67 -0
  22. package/esm2020/utils/draw/node-shape.mjs +21 -0
  23. package/esm2020/utils/draw/node-topic.mjs +32 -0
  24. package/esm2020/utils/index.mjs +4 -2
  25. package/esm2020/utils/mind.mjs +2 -27
  26. package/esm2020/utils/node/common.mjs +6 -0
  27. package/esm2020/utils/node/index.mjs +4 -0
  28. package/esm2020/utils/node/right-node-count.mjs +45 -0
  29. package/esm2020/utils/node-style/branch.mjs +6 -1
  30. package/fesm2015/plait-mind.mjs +985 -911
  31. package/fesm2015/plait-mind.mjs.map +1 -1
  32. package/fesm2020/plait-mind.mjs +1005 -931
  33. package/fesm2020/plait-mind.mjs.map +1 -1
  34. package/interfaces/element.d.ts +5 -0
  35. package/node.component.d.ts +1 -1
  36. package/package.json +1 -1
  37. package/transforms/index.d.ts +1 -0
  38. package/transforms/node.d.ts +2 -0
  39. package/utils/dnd/common.d.ts +5 -1
  40. package/utils/dnd/detector.d.ts +0 -6
  41. package/{draw/abstract.d.ts → utils/draw/abstract-outline.d.ts} +2 -2
  42. package/utils/{dnd/draw.d.ts → draw/node-dnd.d.ts} +1 -5
  43. package/{draw/link → utils/draw/node-link}/abstract-link.d.ts +1 -1
  44. package/utils/draw/node-link/draw-link.d.ts +3 -0
  45. package/{draw → utils/draw/node-link}/indented-link.d.ts +1 -1
  46. package/utils/draw/node-link/logic-link.d.ts +3 -0
  47. package/{draw/node.d.ts → utils/draw/node-shape.d.ts} +2 -2
  48. package/{draw/topic.d.ts → utils/draw/node-topic.d.ts} +3 -3
  49. package/utils/index.d.ts +3 -1
  50. package/utils/mind.d.ts +0 -2
  51. package/utils/{node.d.ts → node/common.d.ts} +1 -1
  52. package/utils/node/index.d.ts +3 -0
  53. package/utils/node/right-node-count.d.ts +9 -0
  54. package/utils/node-style/branch.d.ts +1 -0
  55. package/draw/link/logic-link.d.ts +0 -3
  56. package/esm2020/draw/abstract.mjs +0 -75
  57. package/esm2020/draw/indented-link.mjs +0 -45
  58. package/esm2020/draw/link/abstract-link.mjs +0 -38
  59. package/esm2020/draw/link/logic-link.mjs +0 -54
  60. package/esm2020/draw/node.mjs +0 -21
  61. package/esm2020/draw/topic.mjs +0 -32
  62. package/esm2020/drawer/emoji.drawer.mjs +0 -73
  63. package/esm2020/utils/dnd/draw.mjs +0 -161
  64. package/esm2020/utils/node.mjs +0 -6
@@ -1,14 +1,14 @@
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 { PlaitBoard, PlaitNode, NODE_TO_PARENT, Path, distanceBetweenPointAndRectangle, RectangleClient, ELEMENT_TO_COMPONENT, idCreator, isNullOrUndefined, Transforms, clearSelectedElement, addSelectedElement, PlaitElement, depthFirstRecursion, drawRoundRectangle, createG, getRectangleByElements, getSelectedElements, drawAbstractRoundRectangle, PlaitPluginElementComponent, PlaitPointerType, NODE_TO_INDEX, createText, IS_TEXT_EDITABLE, MERGING, transformPoint, toPoint, PlaitModule, distanceBetweenPointAndPoint, CLIP_BOARD_FORMAT_KEY, BOARD_TO_HOST, throttleRAF, updateForeignObject as updateForeignObject$1, BoardTransforms, Selection, removeSelectedElement, PlaitHistoryBoard, hotkeys } from '@plait/core';
5
- import { MindLayoutType, AbstractNode, getAbstractLayout, isIndentedLayout, isStandardLayout, isLeftLayout, isRightLayout, getNonAbstractChildren, isTopLayout, isVerticalLogicLayout, isHorizontalLogicLayout, isBottomLayout, isHorizontalLayout, getCorrectStartEnd, ConnectingPosition, GlobalLayout } from '@plait/layouts';
4
+ import { distanceBetweenPointAndRectangle, RectangleClient, PlaitElement, PlaitBoard, idCreator, isNullOrUndefined, Transforms, clearSelectedElement, addSelectedElement, depthFirstRecursion, Path, drawRoundRectangle, drawLinearPath, createG, PlaitNode, getRectangleByElements, getSelectedElements, NODE_TO_PARENT, drawAbstractRoundRectangle, PlaitPluginElementComponent, PlaitPointerType, NODE_TO_INDEX, createText, IS_TEXT_EDITABLE, MERGING, transformPoint, toPoint, PlaitModule, distanceBetweenPointAndPoint, CLIP_BOARD_FORMAT_KEY, isMainPointer, BOARD_TO_HOST, throttleRAF, updateForeignObject as updateForeignObject$1, BoardTransforms, Selection, removeSelectedElement, PlaitHistoryBoard, hotkeys } from '@plait/core';
5
+ import { MindLayoutType, isIndentedLayout, getNonAbstractChildren, isStandardLayout, AbstractNode, isLeftLayout, isRightLayout, isTopLayout, isVerticalLogicLayout, isHorizontalLogicLayout, isBottomLayout, isHorizontalLayout, getCorrectStartEnd, getAbstractLayout, ConnectingPosition, GlobalLayout } from '@plait/layouts';
6
6
  import { getSizeByText, ROOT_DEFAULT_HEIGHT, TEXT_DEFAULT_HEIGHT, updateForeignObject, drawRichtext, 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';
9
9
  import { Node, Path as Path$1, Editor, Operation } from 'slate';
10
- import { pointsOnBezierCurves } from 'points-on-curve';
11
10
  import { isKeyHotkey } from 'is-hotkey';
11
+ import { pointsOnBezierCurves } from 'points-on-curve';
12
12
  import * as i1 from '@angular/common';
13
13
  import { CommonModule } from '@angular/common';
14
14
 
@@ -93,117 +93,310 @@ var MindPointerType;
93
93
  MindPointerType["mind"] = "mind";
94
94
  })(MindPointerType || (MindPointerType = {}));
95
95
 
96
- /**
97
- * get correctly layout:
98
- * 1. root is standard -> left or right
99
- * 2. correct layout by incorrect layout direction
100
- * @param element
101
- */
102
- const getCorrectLayoutByElement = (board, element) => {
103
- const ancestors = MindElement.getAncestors(board, element);
104
- ancestors.unshift(element);
105
- const root = ancestors[ancestors.length - 1];
106
- let rootLayout = getRootLayout(root);
107
- if (PlaitMind.isMind(element)) {
108
- return rootLayout;
109
- }
96
+ function getRectangleByNode(node) {
97
+ const x = node.x + node.hGap;
98
+ let y = node.y + node.vGap;
99
+ const width = node.width - node.hGap * 2;
100
+ const height = node.height - node.vGap * 2;
101
+ return {
102
+ x,
103
+ y,
104
+ width,
105
+ height
106
+ };
107
+ }
108
+ function getRectangleByElement(board, originPoint, element) {
109
+ const nodeRectangle = {
110
+ x: originPoint[0],
111
+ y: originPoint[1],
112
+ width: NodeSpace.getNodeWidth(board, element),
113
+ height: NodeSpace.getNodeHeight(board, element)
114
+ };
115
+ return nodeRectangle;
116
+ }
117
+ function isHitMindElement(board, point, element) {
110
118
  const node = MindElement.getNode(element);
111
- let correctRootLayout = rootLayout;
112
- if (rootLayout === MindLayoutType.standard) {
113
- correctRootLayout = node.left ? MindLayoutType.left : MindLayoutType.right;
119
+ if (node && distanceBetweenPointAndRectangle(point[0], point[1], getRectangleByNode(node)) === 0) {
120
+ return true;
114
121
  }
115
- let layout = null;
116
- const elementWithLayout = ancestors.find(value => value.layout || AbstractNode.isAbstract(value));
117
- if (elementWithLayout) {
118
- if (AbstractNode.isAbstract(elementWithLayout)) {
119
- const parent = MindElement.getParent(elementWithLayout);
120
- const parentLayout = getCorrectLayoutByElement(board, parent);
121
- layout = getAbstractLayout(parentLayout);
122
- }
123
- else {
124
- layout = elementWithLayout?.layout;
125
- }
122
+ else {
123
+ return false;
126
124
  }
127
- if (layout === MindLayoutType.standard || !layout) {
128
- return correctRootLayout;
125
+ }
126
+
127
+ function getEmojisWidthHeight(board, element) {
128
+ const options = board.getMindOptions();
129
+ const count = element.data.emojis.length;
130
+ const fontSize = getEmojiFontSize(element);
131
+ return {
132
+ width: fontSize * count + count * 2 * options.emojiPadding + (count - 1) * options.spaceBetweenEmojis,
133
+ height: element.height
134
+ };
135
+ }
136
+ function getEmojiFontSize(element) {
137
+ if (PlaitMind.isMind(element)) {
138
+ return 18 + 2;
129
139
  }
130
140
  else {
131
- const incorrectDirection = getInCorrectLayoutDirection(correctRootLayout, layout);
132
- if (incorrectDirection) {
133
- return correctLayoutByDirection(layout, incorrectDirection);
134
- }
135
- else {
136
- return layout;
137
- }
141
+ return 14 + 2;
138
142
  }
143
+ }
144
+
145
+ function getEmojiRectangle(board, element) {
146
+ let { x, y } = getRectangleByNode(MindElement.getNode(element));
147
+ x = x + NodeSpace.getEmojiLeftSpace(board, element);
148
+ const { width, height } = getEmojisWidthHeight(board, element);
149
+ return {
150
+ x,
151
+ y,
152
+ width,
153
+ height
154
+ };
155
+ }
156
+ function getEmojiForeignRectangle(board, element) {
157
+ let { x, y } = getRectangleByNode(MindElement.getNode(element));
158
+ x = x + NodeSpace.getEmojiLeftSpace(board, element);
159
+ const { width, height } = getEmojisWidthHeight(board, element);
160
+ return {
161
+ x,
162
+ y,
163
+ width,
164
+ height: height + NodeSpace.getEmojiTopSpace(element) * 2
165
+ };
166
+ }
167
+ const isHitEmojis = (board, element, point) => {
168
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), getEmojiRectangle(board, element));
139
169
  };
140
170
 
141
- const getBranchLayouts = (board, element) => {
142
- const layouts = [];
143
- if (element.layout) {
144
- // TODO: getCorrectLayoutByElement 含有递归操作,getBranchLayouts 本身也有递归操作,有待优化
145
- layouts.unshift(getCorrectLayoutByElement(board, element));
146
- }
147
- let parent = MindElement.findParent(element);
148
- while (parent) {
149
- if (parent.layout) {
150
- layouts.unshift(parent.layout);
151
- }
152
- parent = MindElement.findParent(parent);
171
+ function enterNodeEditing(element) {
172
+ const component = PlaitElement.getComponent(element);
173
+ component.startEditText(false, false);
174
+ }
175
+
176
+ const adjustRootToNode = (board, node) => {
177
+ const newNode = { ...node };
178
+ delete newNode.isRoot;
179
+ delete newNode.rightNodeCount;
180
+ delete newNode.type;
181
+ const text = Node.string(node.data.topic.children[0]) || ' ';
182
+ const { width, height } = getSizeByText(text, PlaitBoard.getViewportContainer(board), TOPIC_DEFAULT_MAX_WORD_COUNT);
183
+ newNode.width = Math.max(width, NODE_MIN_WIDTH);
184
+ newNode.height = height;
185
+ if (newNode.layout === MindLayoutType.standard) {
186
+ delete newNode.layout;
153
187
  }
154
- return layouts;
188
+ return newNode;
155
189
  };
156
-
157
- const getAvailableSubLayoutsByElement = (board, element) => {
158
- const parentElement = MindElement.findParent(element);
159
- if (parentElement) {
160
- const branchLayouts = getBranchLayouts(board, parentElement);
161
- if (branchLayouts[0] === MindLayoutType.standard) {
162
- const node = MindElement.getNode(element);
163
- branchLayouts[0] = node.left ? MindLayoutType.left : MindLayoutType.right;
164
- }
165
- const currentLayoutDirections = getBranchDirectionsByLayouts(branchLayouts);
166
- let availableSubLayouts = getAvailableSubLayoutsByLayoutDirections(currentLayoutDirections);
167
- const parentLayout = [branchLayouts[branchLayouts.length - 1]];
168
- const parentDirections = getBranchDirectionsByLayouts(parentLayout);
169
- const parentAvailableSubLayouts = getAvailableSubLayoutsByLayoutDirections(parentDirections);
170
- availableSubLayouts = availableSubLayouts.filter(layout => parentAvailableSubLayouts.some(parentAvailableSubLayout => parentAvailableSubLayout === layout));
171
- return availableSubLayouts;
190
+ const adjustAbstractToNode = (node) => {
191
+ const newNode = { ...node };
192
+ delete newNode.start;
193
+ delete newNode.end;
194
+ return newNode;
195
+ };
196
+ const adjustNodeToRoot = (board, node) => {
197
+ const newElement = { ...node };
198
+ let text = Node.string(newElement.data.topic);
199
+ if (!text) {
200
+ text = '思维导图';
201
+ newElement.data.topic = { children: [{ text }] };
172
202
  }
173
- return undefined;
203
+ delete newElement?.strokeColor;
204
+ delete newElement?.fill;
205
+ delete newElement?.shape;
206
+ delete newElement?.strokeWidth;
207
+ const { width, height } = getSizeByText(text, PlaitBoard.getViewportContainer(board), TOPIC_DEFAULT_MAX_WORD_COUNT, ROOT_TOPIC_FONT_SIZE);
208
+ newElement.width = Math.max(width, NODE_MIN_WIDTH);
209
+ newElement.height = height;
210
+ return {
211
+ ...newElement,
212
+ layout: newElement.layout ?? MindLayoutType.right,
213
+ isCollapsed: false,
214
+ isRoot: true,
215
+ type: 'mindmap'
216
+ };
174
217
  };
175
218
 
176
- const getBranchDirectionsByLayouts = (branchLayouts) => {
177
- const branchDirections = [];
178
- branchLayouts.forEach(l => {
179
- const directions = LayoutDirectionsMap[l];
180
- directions.forEach(d => {
181
- if (!branchDirections.includes(d) && !branchDirections.includes(getLayoutReverseDirection(d))) {
182
- branchDirections.push(d);
183
- }
184
- });
185
- });
186
- return branchDirections;
187
- };
188
- const isCorrectLayout = (root, layout) => {
189
- const rootLayout = root.layout || getDefaultLayout();
190
- return !getInCorrectLayoutDirection(rootLayout, layout);
219
+ const createEmptyMind = (board, point) => {
220
+ const element = createMindElement('', 0, 0, { layout: MindLayoutType.right });
221
+ const rootElement = adjustNodeToRoot(board, element);
222
+ rootElement.points = [point];
223
+ return rootElement;
191
224
  };
192
- const isMixedLayout = (parentLayout, layout) => {
193
- return (!isIndentedLayout(parentLayout) && isIndentedLayout(layout)) || (isIndentedLayout(parentLayout) && !isIndentedLayout(layout));
225
+ const createDefaultMind = (point, rightNodeCount, layout) => {
226
+ const root = createMindElement('思维导图', 72, ROOT_DEFAULT_HEIGHT, { shape: MindElementShape.roundRectangle, layout });
227
+ root.rightNodeCount = rightNodeCount;
228
+ root.isRoot = true;
229
+ root.type = 'mindmap';
230
+ root.points = [point];
231
+ const children = [1, 1, 1].map(() => {
232
+ return createMindElement('新建节点', 56, TEXT_DEFAULT_HEIGHT, { shape: MindElementShape.roundRectangle });
233
+ });
234
+ root.children = children;
235
+ return root;
194
236
  };
195
- const getInCorrectLayoutDirection = (rootLayout, layout) => {
196
- const directions = LayoutDirectionsMap[rootLayout];
197
- const subLayoutDirections = LayoutDirectionsMap[layout];
198
- if (!subLayoutDirections) {
199
- throw new Error(`unexpected layout: ${layout} on correct layout`);
237
+ const createMindElement = (text, width, height, options) => {
238
+ const newElement = {
239
+ id: idCreator(),
240
+ data: {
241
+ topic: { children: [{ text }] }
242
+ },
243
+ children: [],
244
+ width,
245
+ height,
246
+ fill: options.fill,
247
+ strokeColor: options.strokeColor,
248
+ strokeWidth: options.strokeWidth,
249
+ shape: options.shape
250
+ };
251
+ if (options.fill) {
252
+ newElement.fill = options.fill;
200
253
  }
201
- return subLayoutDirections.find(d => directions.includes(getLayoutReverseDirection(d)));
254
+ if (options.strokeColor) {
255
+ newElement.strokeColor = options.strokeColor;
256
+ }
257
+ if (!isNullOrUndefined(options.strokeWidth)) {
258
+ newElement.strokeWidth = options.strokeWidth;
259
+ }
260
+ if (options.shape) {
261
+ newElement.shape = options.shape;
262
+ }
263
+ if (options.layout) {
264
+ newElement.layout = options.layout;
265
+ }
266
+ if (options.branchColor) {
267
+ newElement.branchColor = options.branchColor;
268
+ }
269
+ if (!isNullOrUndefined(options.branchWidth)) {
270
+ newElement.branchWidth = options.branchWidth;
271
+ }
272
+ return newElement;
202
273
  };
203
- const correctLayoutByDirection = (layout, direction) => {
204
- const isHorizontal = direction === LayoutDirection.left || direction === LayoutDirection.right ? true : false;
205
- let inverseDirectionLayout = MindLayoutType.standard;
206
- switch (layout) {
274
+
275
+ const getChildrenCount = (element) => {
276
+ const count = element.children.reduce((p, c) => {
277
+ return p + getChildrenCount(c);
278
+ }, 0);
279
+ return count + element.children.length;
280
+ };
281
+ const isChildElement = (origin, child) => {
282
+ let parent = MindElement.findParent(child);
283
+ while (parent) {
284
+ if (parent === origin) {
285
+ return true;
286
+ }
287
+ parent = MindElement.findParent(parent);
288
+ }
289
+ return false;
290
+ };
291
+ const getFirstLevelElement = (elements) => {
292
+ let result = [];
293
+ elements.forEach(element => {
294
+ const isChild = elements.some(node => {
295
+ return isChildElement(node, element);
296
+ });
297
+ if (!isChild) {
298
+ result.push(element);
299
+ }
300
+ });
301
+ return result;
302
+ };
303
+ const isChildRight = (node, child) => {
304
+ return node.x < child.x;
305
+ };
306
+ const isChildUp = (node, child) => {
307
+ return node.y > child.y;
308
+ };
309
+ const copyNewNode = (node) => {
310
+ const newNode = { ...node };
311
+ newNode.id = idCreator();
312
+ newNode.children = [];
313
+ for (const childNode of node.children) {
314
+ newNode.children.push(copyNewNode(childNode));
315
+ }
316
+ return newNode;
317
+ };
318
+ const extractNodesText = (node) => {
319
+ let str = '';
320
+ if (node) {
321
+ str += Node.string(node.data.topic.children[0]) + ' ';
322
+ for (const childNode of node.children) {
323
+ str += extractNodesText(childNode);
324
+ }
325
+ }
326
+ return str;
327
+ };
328
+ // layoutLevel 用来表示插入兄弟节点还是子节点
329
+ const insertMindElement = (board, inheritNode, path) => {
330
+ let fill, strokeColor, strokeWidth, shape = MindElementShape.roundRectangle;
331
+ if (!inheritNode.isRoot) {
332
+ fill = inheritNode.fill;
333
+ strokeColor = inheritNode.strokeColor;
334
+ strokeWidth = inheritNode.strokeWidth;
335
+ }
336
+ shape = inheritNode.shape;
337
+ const newElement = createMindElement('', NODE_MIN_WIDTH, TEXT_DEFAULT_HEIGHT, { fill, strokeColor, strokeWidth, shape });
338
+ Transforms.insertNode(board, newElement, path);
339
+ clearSelectedElement(board);
340
+ addSelectedElement(board, newElement);
341
+ setTimeout(() => {
342
+ enterNodeEditing(newElement);
343
+ });
344
+ };
345
+ const findLastChild = (child) => {
346
+ let result = child;
347
+ while (result.children.length !== 0) {
348
+ result = result.children[result.children.length - 1];
349
+ }
350
+ return result;
351
+ };
352
+ const divideElementByParent = (elements) => {
353
+ const abstractIncludedGroups = [];
354
+ const parentElements = [];
355
+ for (let i = 0; i < elements.length; i++) {
356
+ const parent = MindElement.getParent(elements[i]);
357
+ const parentIndex = parentElements.indexOf(parent);
358
+ if (parentIndex === -1) {
359
+ parentElements.push(parent);
360
+ abstractIncludedGroups.push([elements[i]]);
361
+ }
362
+ else {
363
+ abstractIncludedGroups[parentIndex].push(elements[i]);
364
+ }
365
+ }
366
+ return { parentElements, abstractIncludedGroups };
367
+ };
368
+
369
+ const getBranchDirectionsByLayouts = (branchLayouts) => {
370
+ const branchDirections = [];
371
+ branchLayouts.forEach(l => {
372
+ const directions = LayoutDirectionsMap[l];
373
+ directions.forEach(d => {
374
+ if (!branchDirections.includes(d) && !branchDirections.includes(getLayoutReverseDirection(d))) {
375
+ branchDirections.push(d);
376
+ }
377
+ });
378
+ });
379
+ return branchDirections;
380
+ };
381
+ const isCorrectLayout = (root, layout) => {
382
+ const rootLayout = root.layout || getDefaultLayout();
383
+ return !getInCorrectLayoutDirection(rootLayout, layout);
384
+ };
385
+ const isMixedLayout = (parentLayout, layout) => {
386
+ return (!isIndentedLayout(parentLayout) && isIndentedLayout(layout)) || (isIndentedLayout(parentLayout) && !isIndentedLayout(layout));
387
+ };
388
+ const getInCorrectLayoutDirection = (rootLayout, layout) => {
389
+ const directions = LayoutDirectionsMap[rootLayout];
390
+ const subLayoutDirections = LayoutDirectionsMap[layout];
391
+ if (!subLayoutDirections) {
392
+ throw new Error(`unexpected layout: ${layout} on correct layout`);
393
+ }
394
+ return subLayoutDirections.find(d => directions.includes(getLayoutReverseDirection(d)));
395
+ };
396
+ const correctLayoutByDirection = (layout, direction) => {
397
+ const isHorizontal = direction === LayoutDirection.left || direction === LayoutDirection.right ? true : false;
398
+ let inverseDirectionLayout = MindLayoutType.standard;
399
+ switch (layout) {
207
400
  case MindLayoutType.left:
208
401
  inverseDirectionLayout = MindLayoutType.right;
209
402
  break;
@@ -276,528 +469,44 @@ const getRootLayout = (root) => {
276
469
  return root.layout || getDefaultLayout();
277
470
  };
278
471
 
279
- const getLayoutByElement = (element) => {
280
- const layout = element.layout;
281
- if (layout) {
282
- return layout;
283
- }
284
- const parent = !PlaitMind.isMind(element) && MindElement.getParent(element);
285
- if (AbstractNode.isAbstract(element) && parent) {
286
- return getAbstractLayout(getLayoutByElement(parent));
472
+ const getAvailableProperty = (board, element, propertyKey) => {
473
+ const ancestors = MindElement.getAncestors(board, element);
474
+ ancestors.unshift(element);
475
+ const ancestor = ancestors.find(value => value[propertyKey]);
476
+ if (ancestor) {
477
+ return ancestor[propertyKey];
287
478
  }
288
- if (parent) {
289
- return getLayoutByElement(parent);
479
+ else {
480
+ return undefined;
290
481
  }
291
- return getDefaultLayout();
292
482
  };
293
483
 
294
- const MindQueries = {
295
- getAvailableSubLayoutsByElement,
296
- getBranchLayouts,
297
- getLayoutByElement,
298
- getCorrectLayoutByElement
484
+ /**
485
+ * Processing of branch color, width, style, etc. of the mind node
486
+ */
487
+ const getBranchColorByMindElement = (board, element) => {
488
+ const branchColor = getAvailableProperty(board, element, 'branchColor');
489
+ return branchColor || getDefaultBranchColor(board, element);
299
490
  };
300
-
301
- const PlaitMind = {
302
- isMind: (value) => {
303
- return value.type === 'mindmap';
491
+ const getBranchShapeByMindElement = (board, element) => {
492
+ const branchShape = getAvailableProperty(board, element, 'branchShape');
493
+ return branchShape || BranchShape.bight;
494
+ };
495
+ const getBranchWidthByMindElement = (board, element) => {
496
+ const branchWidth = getAvailableProperty(board, element, 'branchWidth');
497
+ return branchWidth || BRANCH_WIDTH;
498
+ };
499
+ const getAbstractBranchWidth = (board, element) => {
500
+ if (!isNullOrUndefined(element.branchWidth)) {
501
+ return element.branchWidth;
304
502
  }
503
+ return DefaultAbstractNodeStyle.branchWidth;
305
504
  };
306
- const MindElement = {
307
- hasLayout(value, layout) {
308
- const _layout = MindQueries.getLayoutByElement(value);
309
- return _layout === layout;
310
- },
311
- isIndentedLayout(value) {
312
- const _layout = MindQueries.getLayoutByElement(value);
313
- return isIndentedLayout(_layout);
314
- },
315
- isMindElement(board, element) {
316
- const path = PlaitBoard.findPath(board, element);
317
- const rootElement = PlaitNode.get(board, path.slice(0, 1));
318
- if (PlaitMind.isMind(rootElement)) {
319
- return true;
320
- }
321
- else {
322
- return false;
323
- }
324
- },
325
- getParent(node) {
326
- if (PlaitMind.isMind(node)) {
327
- throw new Error('mind root node can not get parent');
328
- }
329
- const parent = NODE_TO_PARENT.get(node);
330
- return parent;
331
- },
332
- findParent(node) {
333
- if (PlaitMind.isMind(node)) {
334
- return undefined;
335
- }
336
- const parent = NODE_TO_PARENT.get(node);
337
- return parent;
338
- },
339
- getRoot(board, element) {
340
- const path = PlaitBoard.findPath(board, element);
341
- return PlaitNode.get(board, path.slice(0, 1));
342
- },
343
- getAncestors(board, element) {
344
- const path = PlaitBoard.findPath(board, element);
345
- const parents = [];
346
- for (const p of Path.ancestors(path, { reverse: true })) {
347
- const n = PlaitNode.get(board, p);
348
- if (n && !PlaitBoard.isBoard(n)) {
349
- parents.push(n);
350
- }
351
- }
352
- return parents;
353
- },
354
- getNode(element) {
355
- const node = ELEMENT_TO_NODE.get(element);
356
- if (!node) {
357
- throw new Error(`can not get node from ${JSON.stringify(element)}`);
358
- }
359
- return node;
360
- },
361
- findParentNode(element) {
362
- if (PlaitMind.isMind(element)) {
363
- return undefined;
364
- }
365
- const parent = MindElement.getParent(element);
366
- return MindElement.getNode(parent);
367
- },
368
- hasEmojis(element) {
369
- if (element.data.emojis) {
370
- return true;
371
- }
372
- else {
373
- return false;
374
- }
375
- },
376
- getEmojis(element) {
377
- return element.data.emojis;
505
+ const getAbstractBranchColor = (board, element) => {
506
+ if (element.branchColor) {
507
+ return element.branchColor;
378
508
  }
379
- };
380
- var MindElementShape;
381
- (function (MindElementShape) {
382
- MindElementShape["roundRectangle"] = "round-rectangle";
383
- MindElementShape["underline"] = "underline";
384
- })(MindElementShape || (MindElementShape = {}));
385
-
386
- function getEmojisWidthHeight(board, element) {
387
- const options = board.getMindOptions();
388
- const count = element.data.emojis.length;
389
- const fontSize = getEmojiFontSize(element);
390
- return {
391
- width: fontSize * count + count * 2 * options.emojiPadding + (count - 1) * options.spaceBetweenEmojis,
392
- height: element.height
393
- };
394
- }
395
- function getEmojiFontSize(element) {
396
- if (PlaitMind.isMind(element)) {
397
- return 18 + 2;
398
- }
399
- else {
400
- return 14 + 2;
401
- }
402
- }
403
-
404
- const NodeDefaultSpace = {
405
- horizontal: {
406
- nodeAndText: BASE * 3,
407
- emojiAndText: BASE * 1.5
408
- },
409
- vertical: {
410
- nodeAndText: BASE * 1.5
411
- }
412
- };
413
- const RootDefaultSpace = {
414
- horizontal: {
415
- nodeAndText: BASE * 4,
416
- emojiAndText: BASE * 2
417
- },
418
- vertical: {
419
- nodeAndText: BASE * 2
420
- }
421
- };
422
- const getHorizontalSpaceBetweenNodeAndText = (board, element) => {
423
- const isMind = PlaitMind.isMind(element);
424
- const nodeAndText = isMind ? RootDefaultSpace.horizontal.nodeAndText : NodeDefaultSpace.horizontal.nodeAndText;
425
- return nodeAndText;
426
- };
427
- const getVerticalSpaceBetweenNodeAndText = (element) => {
428
- const isMind = PlaitMind.isMind(element);
429
- const nodeAndText = isMind ? RootDefaultSpace.vertical.nodeAndText : NodeDefaultSpace.vertical.nodeAndText;
430
- return nodeAndText;
431
- };
432
- const getSpaceEmojiAndText = (element) => {
433
- const isMind = PlaitMind.isMind(element);
434
- const emojiAndText = isMind ? RootDefaultSpace.horizontal.emojiAndText : NodeDefaultSpace.horizontal.emojiAndText;
435
- return emojiAndText;
436
- };
437
- const NodeSpace = {
438
- getNodeWidth(board, element) {
439
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
440
- if (MindElement.hasEmojis(element)) {
441
- return (NodeSpace.getEmojiLeftSpace(board, element) +
442
- getEmojisWidthHeight(board, element).width +
443
- getSpaceEmojiAndText(element) +
444
- element.width +
445
- nodeAndText);
446
- }
447
- return nodeAndText + element.width + nodeAndText;
448
- },
449
- getNodeHeight(board, element) {
450
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
451
- return nodeAndText + element.height + nodeAndText;
452
- },
453
- getTextLeftSpace(board, element) {
454
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
455
- if (MindElement.hasEmojis(element)) {
456
- return NodeSpace.getEmojiLeftSpace(board, element) + getEmojisWidthHeight(board, element).width + getSpaceEmojiAndText(element);
457
- }
458
- else {
459
- return nodeAndText;
460
- }
461
- },
462
- getTextTopSpace(element) {
463
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
464
- return nodeAndText;
465
- },
466
- getEmojiLeftSpace(board, element) {
467
- const options = board.getMindOptions();
468
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
469
- return nodeAndText - options.emojiPadding;
470
- },
471
- getEmojiTopSpace(element) {
472
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
473
- return nodeAndText;
474
- }
475
- };
476
-
477
- function getRectangleByNode(node) {
478
- const x = node.x + node.hGap;
479
- let y = node.y + node.vGap;
480
- const width = node.width - node.hGap * 2;
481
- const height = node.height - node.vGap * 2;
482
- return {
483
- x,
484
- y,
485
- width,
486
- height
487
- };
488
- }
489
- function getRectangleByElement(board, originPoint, element) {
490
- const nodeRectangle = {
491
- x: originPoint[0],
492
- y: originPoint[1],
493
- width: NodeSpace.getNodeWidth(board, element),
494
- height: NodeSpace.getNodeHeight(board, element)
495
- };
496
- return nodeRectangle;
497
- }
498
- function isHitMindElement(board, point, element) {
499
- const node = MindElement.getNode(element);
500
- if (node && distanceBetweenPointAndRectangle(point[0], point[1], getRectangleByNode(node)) === 0) {
501
- return true;
502
- }
503
- else {
504
- return false;
505
- }
506
- }
507
-
508
- function getEmojiRectangle(board, element) {
509
- let { x, y } = getRectangleByNode(MindElement.getNode(element));
510
- x = x + NodeSpace.getEmojiLeftSpace(board, element);
511
- const { width, height } = getEmojisWidthHeight(board, element);
512
- return {
513
- x,
514
- y,
515
- width,
516
- height
517
- };
518
- }
519
- function getEmojiForeignRectangle(board, element) {
520
- let { x, y } = getRectangleByNode(MindElement.getNode(element));
521
- x = x + NodeSpace.getEmojiLeftSpace(board, element);
522
- const { width, height } = getEmojisWidthHeight(board, element);
523
- return {
524
- x,
525
- y,
526
- width,
527
- height: height + NodeSpace.getEmojiTopSpace(element) * 2
528
- };
529
- }
530
- const isHitEmojis = (board, element, point) => {
531
- return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), getEmojiRectangle(board, element));
532
- };
533
-
534
- function getTopicRectangleByNode(board, node) {
535
- let nodeRectangle = getRectangleByNode(node);
536
- return getTopicRectangleByElement(board, nodeRectangle, node.origin);
537
- }
538
- function getTopicRectangleByElement(board, nodeRectangle, element) {
539
- const x = nodeRectangle.x + NodeSpace.getTextLeftSpace(board, element);
540
- const y = nodeRectangle.y + NodeSpace.getTextTopSpace(element);
541
- const width = Math.ceil(element.width);
542
- const height = Math.ceil(element.height);
543
- return { height, width, x, y };
544
- }
545
-
546
- function enterNodeEditing(element) {
547
- const component = ELEMENT_TO_COMPONENT.get(element);
548
- component.startEditText(false, false);
549
- }
550
-
551
- const adjustRootToNode = (board, node) => {
552
- const newNode = { ...node };
553
- delete newNode.isRoot;
554
- delete newNode.rightNodeCount;
555
- delete newNode.type;
556
- const text = Node.string(node.data.topic.children[0]) || ' ';
557
- const { width, height } = getSizeByText(text, PlaitBoard.getViewportContainer(board), TOPIC_DEFAULT_MAX_WORD_COUNT);
558
- newNode.width = Math.max(width, NODE_MIN_WIDTH);
559
- newNode.height = height;
560
- if (newNode.layout === MindLayoutType.standard) {
561
- delete newNode.layout;
562
- }
563
- return newNode;
564
- };
565
- const adjustAbstractToNode = (node) => {
566
- const newNode = { ...node };
567
- delete newNode.start;
568
- delete newNode.end;
569
- return newNode;
570
- };
571
- const adjustNodeToRoot = (board, node) => {
572
- const newElement = { ...node };
573
- let text = Node.string(newElement.data.topic);
574
- if (!text) {
575
- text = '思维导图';
576
- newElement.data.topic = { children: [{ text }] };
577
- }
578
- delete newElement?.strokeColor;
579
- delete newElement?.fill;
580
- delete newElement?.shape;
581
- delete newElement?.strokeWidth;
582
- const { width, height } = getSizeByText(text, PlaitBoard.getViewportContainer(board), TOPIC_DEFAULT_MAX_WORD_COUNT, ROOT_TOPIC_FONT_SIZE);
583
- newElement.width = Math.max(width, NODE_MIN_WIDTH);
584
- newElement.height = height;
585
- return {
586
- ...newElement,
587
- layout: newElement.layout ?? MindLayoutType.right,
588
- isCollapsed: false,
589
- isRoot: true,
590
- type: 'mindmap'
591
- };
592
- };
593
-
594
- const createEmptyMind = (board, point) => {
595
- const element = createMindElement('', 0, 0, { layout: MindLayoutType.right });
596
- const rootElement = adjustNodeToRoot(board, element);
597
- rootElement.points = [point];
598
- return rootElement;
599
- };
600
- const createDefaultMind = (point, rightNodeCount, layout) => {
601
- const root = createMindElement('思维导图', 72, ROOT_DEFAULT_HEIGHT, { shape: MindElementShape.roundRectangle, layout });
602
- root.rightNodeCount = rightNodeCount;
603
- root.isRoot = true;
604
- root.type = 'mindmap';
605
- root.points = [point];
606
- const children = [1, 1, 1].map(() => {
607
- return createMindElement('新建节点', 56, TEXT_DEFAULT_HEIGHT, { shape: MindElementShape.roundRectangle });
608
- });
609
- root.children = children;
610
- return root;
611
- };
612
- const createMindElement = (text, width, height, options) => {
613
- const newElement = {
614
- id: idCreator(),
615
- data: {
616
- topic: { children: [{ text }] }
617
- },
618
- children: [],
619
- width,
620
- height,
621
- fill: options.fill,
622
- strokeColor: options.strokeColor,
623
- strokeWidth: options.strokeWidth,
624
- shape: options.shape
625
- };
626
- if (options.fill) {
627
- newElement.fill = options.fill;
628
- }
629
- if (options.strokeColor) {
630
- newElement.strokeColor = options.strokeColor;
631
- }
632
- if (!isNullOrUndefined(options.strokeWidth)) {
633
- newElement.strokeWidth = options.strokeWidth;
634
- }
635
- if (options.shape) {
636
- newElement.shape = options.shape;
637
- }
638
- if (options.layout) {
639
- newElement.layout = options.layout;
640
- }
641
- if (options.branchColor) {
642
- newElement.branchColor = options.branchColor;
643
- }
644
- if (!isNullOrUndefined(options.branchWidth)) {
645
- newElement.branchWidth = options.branchWidth;
646
- }
647
- return newElement;
648
- };
649
-
650
- const getChildrenCount = (element) => {
651
- const count = element.children.reduce((p, c) => {
652
- return p + getChildrenCount(c);
653
- }, 0);
654
- return count + element.children.length;
655
- };
656
- const isChildElement = (origin, child) => {
657
- let parent = MindElement.findParent(child);
658
- while (parent) {
659
- if (parent === origin) {
660
- return true;
661
- }
662
- parent = MindElement.findParent(parent);
663
- }
664
- return false;
665
- };
666
- const getFirstLevelElement = (elements) => {
667
- let result = [];
668
- elements.forEach(element => {
669
- const isChild = elements.some(node => {
670
- return isChildElement(node, element);
671
- });
672
- if (!isChild) {
673
- result.push(element);
674
- }
675
- });
676
- return result;
677
- };
678
- const isChildRight = (node, child) => {
679
- return node.x < child.x;
680
- };
681
- const isChildUp = (node, child) => {
682
- return node.y > child.y;
683
- };
684
- const copyNewNode = (node) => {
685
- const newNode = { ...node };
686
- newNode.id = idCreator();
687
- newNode.children = [];
688
- for (const childNode of node.children) {
689
- newNode.children.push(copyNewNode(childNode));
690
- }
691
- return newNode;
692
- };
693
- const extractNodesText = (node) => {
694
- let str = '';
695
- if (node) {
696
- str += Node.string(node.data.topic.children[0]) + ' ';
697
- for (const childNode of node.children) {
698
- str += extractNodesText(childNode);
699
- }
700
- }
701
- return str;
702
- };
703
- const changeRightNodeCount = (board, parentPath, changeNumber) => {
704
- const _rightNodeCount = board.children[parentPath[0]].rightNodeCount;
705
- Transforms.setNode(board, {
706
- rightNodeCount: changeNumber >= 0
707
- ? _rightNodeCount + changeNumber
708
- : _rightNodeCount + changeNumber < 0
709
- ? 0
710
- : _rightNodeCount + changeNumber
711
- }, parentPath);
712
- };
713
- const isInRightBranchOfStandardLayout = (selectedElement) => {
714
- const parentElement = MindElement.findParent(selectedElement);
715
- if (parentElement) {
716
- const nodeIndex = parentElement.children.findIndex(item => item.id === selectedElement.id);
717
- if (parentElement.isRoot &&
718
- getRootLayout(parentElement) === MindLayoutType.standard &&
719
- parentElement.rightNodeCount &&
720
- nodeIndex <= parentElement.rightNodeCount - 1) {
721
- return true;
722
- }
723
- }
724
- return false;
725
- };
726
- // layoutLevel 用来表示插入兄弟节点还是子节点
727
- const insertMindElement = (board, inheritNode, path) => {
728
- let fill, strokeColor, strokeWidth, shape = MindElementShape.roundRectangle;
729
- if (!inheritNode.isRoot) {
730
- fill = inheritNode.fill;
731
- strokeColor = inheritNode.strokeColor;
732
- strokeWidth = inheritNode.strokeWidth;
733
- }
734
- shape = inheritNode.shape;
735
- const newElement = createMindElement('', NODE_MIN_WIDTH, TEXT_DEFAULT_HEIGHT, { fill, strokeColor, strokeWidth, shape });
736
- Transforms.insertNode(board, newElement, path);
737
- clearSelectedElement(board);
738
- addSelectedElement(board, newElement);
739
- setTimeout(() => {
740
- enterNodeEditing(newElement);
741
- });
742
- };
743
- const findLastChild = (child) => {
744
- let result = child;
745
- while (result.children.length !== 0) {
746
- result = result.children[result.children.length - 1];
747
- }
748
- return result;
749
- };
750
- const divideElementByParent = (elements) => {
751
- const abstractIncludedGroups = [];
752
- const parentElements = [];
753
- for (let i = 0; i < elements.length; i++) {
754
- const parent = MindElement.getParent(elements[i]);
755
- const parentIndex = parentElements.indexOf(parent);
756
- if (parentIndex === -1) {
757
- parentElements.push(parent);
758
- abstractIncludedGroups.push([elements[i]]);
759
- }
760
- else {
761
- abstractIncludedGroups[parentIndex].push(elements[i]);
762
- }
763
- }
764
- return { parentElements, abstractIncludedGroups };
765
- };
766
-
767
- const getAvailableProperty = (board, element, propertyKey) => {
768
- const ancestors = MindElement.getAncestors(board, element);
769
- ancestors.unshift(element);
770
- const ancestor = ancestors.find(value => value[propertyKey]);
771
- if (ancestor) {
772
- return ancestor[propertyKey];
773
- }
774
- else {
775
- return undefined;
776
- }
777
- };
778
-
779
- /**
780
- * Processing of branch color, width, style, etc. of the mind node
781
- */
782
- const getBranchColorByMindElement = (board, element) => {
783
- const branchColor = getAvailableProperty(board, element, 'branchColor');
784
- return branchColor || getDefaultBranchColor(board, element);
785
- };
786
- const getBranchWidthByMindElement = (board, element) => {
787
- const branchWidth = getAvailableProperty(board, element, 'branchWidth');
788
- return branchWidth || BRANCH_WIDTH;
789
- };
790
- const getAbstractBranchWidth = (board, element) => {
791
- if (!isNullOrUndefined(element.branchWidth)) {
792
- return element.branchWidth;
793
- }
794
- return DefaultAbstractNodeStyle.branchWidth;
795
- };
796
- const getAbstractBranchColor = (board, element) => {
797
- if (element.branchColor) {
798
- return element.branchColor;
799
- }
800
- return DefaultAbstractNodeStyle.branchColor;
509
+ return DefaultAbstractNodeStyle.branchColor;
801
510
  };
802
511
  const getNextBranchColor = (root) => {
803
512
  const index = root.children.length;
@@ -875,13 +584,32 @@ const isDragging = (board) => {
875
584
  const setIsDragging = (board, state) => {
876
585
  IS_DRAGGING.set(board, state);
877
586
  };
587
+ const hasPreviousOrNextOfDropPath = (parent, target, dropPath) => {
588
+ const children = getNonAbstractChildren(parent);
589
+ let hasPreviousNode = dropPath[dropPath.length - 1] !== 0;
590
+ let hasNextNode = dropPath[dropPath.length - 1] !== (children?.length || 0);
591
+ if (PlaitMind.isMind(parent) && isStandardLayout(getRootLayout(parent))) {
592
+ const dropStandardRightBottom = target === parent.children[parent.rightNodeCount - 1] && dropPath[dropPath.length - 1] === parent.rightNodeCount;
593
+ const dropStandardLeftTop = target === parent.children[parent.rightNodeCount] && dropPath[dropPath.length - 1] === parent.rightNodeCount;
594
+ if (dropStandardRightBottom) {
595
+ hasPreviousNode = true;
596
+ hasNextNode = false;
597
+ }
598
+ if (dropStandardLeftTop) {
599
+ hasPreviousNode = false;
600
+ hasNextNode = true;
601
+ }
602
+ }
603
+ if (parent.isCollapsed) {
604
+ hasNextNode = false;
605
+ hasPreviousNode = false;
606
+ }
607
+ return {
608
+ hasPreviousNode,
609
+ hasNextNode
610
+ };
611
+ };
878
612
 
879
- /**
880
- *
881
- * @param targetNode
882
- * @param centerPoint
883
- * @returns DetectResult[] | null
884
- */
885
613
  const directionCorrector = (board, node, detectResults) => {
886
614
  if (!node.origin.isRoot && !AbstractNode.isAbstract(node.origin)) {
887
615
  const parentLayout = MindQueries.getCorrectLayoutByElement(board, node?.parent.origin);
@@ -1283,7 +1011,55 @@ const transformPlacement = (placement, direction) => {
1283
1011
  }
1284
1012
  };
1285
1013
 
1286
- function drawLogicLink(board, node, parent, isHorizontal, defaultStroke = null, defaultStrokeWidth) {
1014
+ function drawIndentedLink(board, node, child, defaultStroke = null, needDrawUnderline = true, defaultStrokeWidth) {
1015
+ const branchShape = getBranchShapeByMindElement(board, node.origin);
1016
+ const branchWidth = defaultStrokeWidth || getBranchWidthByMindElement(board, child.origin);
1017
+ const branchColor = defaultStroke || getBranchColorByMindElement(board, child.origin);
1018
+ const isUnderlineShape = getShapeByElement(board, child.origin) === MindElementShape.underline;
1019
+ let beginX, beginY, endX, endY, beginNode = node, endNode = child;
1020
+ const beginRectangle = getRectangleByNode(beginNode);
1021
+ const endRectangle = getRectangleByNode(endNode);
1022
+ beginX = beginNode.x + beginNode.width / 2;
1023
+ beginY = isChildUp(node, child) ? beginRectangle.y : beginRectangle.y + beginRectangle.height;
1024
+ endX = node.left ? endNode.x + endNode.hGap + endRectangle.width : endNode.x + endNode.hGap;
1025
+ endY = isUnderlineShape ? endNode.y + endNode.height - endNode.vGap : endNode.y + endNode.height / 2;
1026
+ //根据位置,设置正负参数
1027
+ let plusMinus = isChildUp(node, child) ? (node.left ? [-1, -1] : [1, -1]) : node.left ? [-1, 1] : [1, 1];
1028
+ const layout = MindQueries.getCorrectLayoutByElement(board, node.origin);
1029
+ if (beginNode.origin.isRoot) {
1030
+ if (layout === MindLayoutType.leftBottomIndented || layout === MindLayoutType.rightBottomIndented) {
1031
+ beginY += branchWidth;
1032
+ }
1033
+ if (layout === MindLayoutType.leftTopIndented || layout === MindLayoutType.rightTopIndented) {
1034
+ beginY -= branchWidth;
1035
+ }
1036
+ }
1037
+ let curve = [
1038
+ [beginX, beginY],
1039
+ [beginX, beginY],
1040
+ [beginX, beginY],
1041
+ [beginX, endY - (endNode.hGap * 3 * plusMinus[1]) / 5],
1042
+ [beginX, endY - (endNode.hGap * plusMinus[1]) / 5],
1043
+ [beginX + (endNode.hGap * plusMinus[0]) / 4, endY],
1044
+ [beginX + (endNode.hGap * plusMinus[0] * 3) / 5, endY],
1045
+ isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
1046
+ isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
1047
+ isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY]
1048
+ ];
1049
+ if (branchShape === BranchShape.polyline) {
1050
+ const polylinePoints = [
1051
+ [beginX, beginY],
1052
+ [beginX, endY],
1053
+ [endX, endY]
1054
+ ];
1055
+ return drawLinearPath(polylinePoints, { stroke: branchColor, strokeWidth: branchWidth });
1056
+ }
1057
+ const points = pointsOnBezierCurves(curve);
1058
+ return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth: branchWidth });
1059
+ }
1060
+
1061
+ function drawLogicLink(board, parent, node, isHorizontal, defaultStroke = null, defaultStrokeWidth) {
1062
+ const branchShape = getBranchShapeByMindElement(board, parent.origin);
1287
1063
  const branchColor = defaultStroke || getBranchColorByMindElement(board, node.origin);
1288
1064
  const branchWidth = defaultStrokeWidth || getBranchWidthByMindElement(board, node.origin);
1289
1065
  const hasStraightLine = !parent.origin.isRoot;
@@ -1327,9 +1103,27 @@ function drawLogicLink(board, node, parent, isHorizontal, defaultStroke = null,
1327
1103
  const underlineEnd = moveXOfPoint(endPoint, nodeClient.width, linkDirection);
1328
1104
  const underline = hasUnderlineShape && isHorizontal ? [underlineEnd, underlineEnd, underlineEnd] : [];
1329
1105
  const points = pointsOnBezierCurves([...straightLine, ...curve, ...underline]);
1106
+ if (branchShape === BranchShape.polyline) {
1107
+ const buffer = 8;
1108
+ const movePoint = moveXOfPoint(beginPoint2, buffer, linkDirection);
1109
+ const polylinePoints = [
1110
+ ...straightLine,
1111
+ movePoint,
1112
+ isHorizontal ? [movePoint[0], endPoint[1]] : [endPoint[0], movePoint[1]],
1113
+ endPoint,
1114
+ ...underline
1115
+ ];
1116
+ return drawLinearPath(polylinePoints, { stroke: branchColor, strokeWidth: branchWidth });
1117
+ }
1330
1118
  return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth: branchWidth });
1331
1119
  }
1332
1120
 
1121
+ function drawLink(board, parentNode, node, isHorizontal, needDrawUnderline, defaultStroke, defaultStrokeWidth) {
1122
+ return MindElement.isIndentedLayout(parentNode.origin)
1123
+ ? drawIndentedLink(board, parentNode, node, defaultStroke, needDrawUnderline, defaultStrokeWidth)
1124
+ : drawLogicLink(board, parentNode, node, isHorizontal, defaultStroke, defaultStrokeWidth);
1125
+ }
1126
+
1333
1127
  const drawFakeDragNode = (board, activeComponent, offsetX, offsetY) => {
1334
1128
  const dragFakeNodeG = createG();
1335
1129
  dragFakeNodeG.classList.add('dragging', 'fake-node', 'plait-board-attached');
@@ -1342,17 +1136,17 @@ const drawFakeDragNode = (board, activeComponent, offsetX, offsetY) => {
1342
1136
  const textRectangle = getTopicRectangleByNode(board, activeComponent.node);
1343
1137
  const fakeNodeG = drawRoundRectangleByNode(board, fakeDraggingNode);
1344
1138
  const richtextG = activeComponent.richtextG?.cloneNode(true);
1345
- updateForeignObject(richtextG, textRectangle.width + BASE * 10, textRectangle.height, textRectangle.x + offsetX, textRectangle.y + offsetY);
1139
+ updateForeignObject(richtextG, textRectangle.width, textRectangle.height, textRectangle.x + offsetX, textRectangle.y + offsetY);
1346
1140
  dragFakeNodeG?.append(fakeNodeG);
1347
1141
  dragFakeNodeG?.append(richtextG);
1348
1142
  return dragFakeNodeG;
1349
1143
  };
1350
- const drawFakeDropNodeByPath = (board, target, path) => {
1144
+ const drawFakeDropNode = (board, target, path) => {
1351
1145
  const fakeDropNodeG = createG();
1352
1146
  const parent = PlaitNode.get(board, Path.parent(path));
1353
1147
  const layout = MindQueries.getLayoutByElement(parent);
1354
1148
  const isHorizontal = isHorizontalLayout(layout);
1355
- const { hasNextNode, hasPreviousNode } = getPreviousAndNextByPath(parent, target, path);
1149
+ const { hasNextNode, hasPreviousNode } = hasPreviousOrNextOfDropPath(parent, target, path);
1356
1150
  const width = 30;
1357
1151
  const height = 12;
1358
1152
  let fakeNode, centerPoint, basicNode, linkDirection;
@@ -1441,40 +1235,13 @@ const drawFakeDropNodeByPath = (board, target, path) => {
1441
1235
  const fakeRectangleG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), fakeNode.x, fakeNode.y, fakeNode.x + width, fakeNode.y + height, {
1442
1236
  stroke: PRIMARY_COLOR,
1443
1237
  strokeWidth: 2,
1444
- fill: PRIMARY_COLOR,
1445
- fillStyle: 'solid'
1446
- });
1447
- const link = MindElement.isIndentedLayout(parent)
1448
- ? drawIndentedLink(board, MindElement.getNode(parent), fakeNode, PRIMARY_COLOR, false, STROKE_WIDTH)
1449
- : drawLogicLink(board, fakeNode, MindElement.getNode(parent), isHorizontal, PRIMARY_COLOR, STROKE_WIDTH);
1450
- fakeDropNodeG?.appendChild(link);
1451
- fakeDropNodeG?.appendChild(fakeRectangleG);
1452
- return fakeDropNodeG;
1453
- };
1454
- const getPreviousAndNextByPath = (parent, target, path) => {
1455
- const children = getNonAbstractChildren(parent);
1456
- let hasPreviousNode = path[path.length - 1] !== 0;
1457
- let hasNextNode = path[path.length - 1] !== (children?.length || 0);
1458
- if (PlaitMind.isMind(parent) && isStandardLayout(getRootLayout(parent))) {
1459
- const dropStandardRightBottom = target === parent.children[parent.rightNodeCount - 1] && path[path.length - 1] === parent.rightNodeCount;
1460
- const dropStandardLeftTop = target === parent.children[parent.rightNodeCount] && path[path.length - 1] === parent.rightNodeCount;
1461
- if (dropStandardRightBottom) {
1462
- hasPreviousNode = true;
1463
- hasNextNode = false;
1464
- }
1465
- if (dropStandardLeftTop) {
1466
- hasPreviousNode = false;
1467
- hasNextNode = true;
1468
- }
1469
- }
1470
- if (parent.isCollapsed) {
1471
- hasNextNode = false;
1472
- hasPreviousNode = false;
1473
- }
1474
- return {
1475
- hasPreviousNode,
1476
- hasNextNode
1477
- };
1238
+ fill: PRIMARY_COLOR,
1239
+ fillStyle: 'solid'
1240
+ });
1241
+ const link = drawLink(board, MindElement.getNode(parent), fakeNode, isHorizontal, false, PRIMARY_COLOR, STROKE_WIDTH);
1242
+ fakeDropNodeG?.appendChild(link);
1243
+ fakeDropNodeG?.appendChild(fakeRectangleG);
1244
+ return fakeDropNodeG;
1478
1245
  };
1479
1246
 
1480
1247
  const separateChildren = (parentElement) => {
@@ -1595,285 +1362,565 @@ isExtendPreviousNode = true, effectedAbstracts = new Map()) => {
1595
1362
  newProperties.end = newProperties.end + step;
1596
1363
  });
1597
1364
  }
1598
- if (!hasPreviousNode) {
1599
- return effectedAbstracts;
1365
+ if (!hasPreviousNode) {
1366
+ return effectedAbstracts;
1367
+ }
1368
+ const selectedElement = PlaitNode.get(board, Path.previous(path));
1369
+ const correspondingAbstract = getCorrespondingAbstract(selectedElement);
1370
+ const isDragToLast = !isExtendPreviousNode && correspondingAbstract && correspondingAbstract.end === path[path.length - 1] - 1;
1371
+ if (correspondingAbstract && !isDragToLast) {
1372
+ let newProperties = effectedAbstracts.get(correspondingAbstract);
1373
+ if (!newProperties) {
1374
+ newProperties = { start: 0, end: 0 };
1375
+ effectedAbstracts.set(correspondingAbstract, newProperties);
1376
+ }
1377
+ newProperties.end = newProperties.end + step;
1378
+ }
1379
+ return effectedAbstracts;
1380
+ };
1381
+ const deleteElementHandleAbstract = (board, deletableElements, effectedAbstracts = new Map()) => {
1382
+ deletableElements.forEach(node => {
1383
+ if (!PlaitMind.isMind(node)) {
1384
+ const behindAbstracts = getBehindAbstracts(node).filter(abstract => !deletableElements.includes(abstract));
1385
+ if (behindAbstracts.length) {
1386
+ behindAbstracts.forEach(abstract => {
1387
+ let newProperties = effectedAbstracts.get(abstract);
1388
+ if (!newProperties) {
1389
+ newProperties = { start: 0, end: 0 };
1390
+ effectedAbstracts.set(abstract, newProperties);
1391
+ }
1392
+ newProperties.start = newProperties.start - 1;
1393
+ newProperties.end = newProperties.end - 1;
1394
+ });
1395
+ }
1396
+ const correspondingAbstract = getCorrespondingAbstract(node);
1397
+ if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
1398
+ let newProperties = effectedAbstracts.get(correspondingAbstract);
1399
+ if (!newProperties) {
1400
+ newProperties = { start: 0, end: 0 };
1401
+ effectedAbstracts.set(correspondingAbstract, newProperties);
1402
+ }
1403
+ newProperties.end = newProperties.end - 1;
1404
+ }
1405
+ }
1406
+ });
1407
+ return effectedAbstracts;
1408
+ };
1409
+
1410
+ var AbstractHandlePosition;
1411
+ (function (AbstractHandlePosition) {
1412
+ AbstractHandlePosition["start"] = "start";
1413
+ AbstractHandlePosition["end"] = "end";
1414
+ })(AbstractHandlePosition || (AbstractHandlePosition = {}));
1415
+ var AbstractResizeState;
1416
+ (function (AbstractResizeState) {
1417
+ AbstractResizeState["start"] = "start";
1418
+ AbstractResizeState["resizing"] = "resizing";
1419
+ AbstractResizeState["end"] = "end";
1420
+ })(AbstractResizeState || (AbstractResizeState = {}));
1421
+
1422
+ const getRectangleByResizingLocation = (abstractRectangle, location, activeHandlePosition, isHorizontal) => {
1423
+ if (isHorizontal) {
1424
+ if (activeHandlePosition === AbstractHandlePosition.start) {
1425
+ return {
1426
+ ...abstractRectangle,
1427
+ y: location,
1428
+ height: abstractRectangle.height + abstractRectangle.y - location
1429
+ };
1430
+ }
1431
+ else {
1432
+ return {
1433
+ ...abstractRectangle,
1434
+ height: location - abstractRectangle.y
1435
+ };
1436
+ }
1437
+ }
1438
+ else {
1439
+ if (activeHandlePosition === AbstractHandlePosition.start) {
1440
+ return {
1441
+ ...abstractRectangle,
1442
+ x: location,
1443
+ width: abstractRectangle.width + abstractRectangle.x - location
1444
+ };
1445
+ }
1446
+ else {
1447
+ return {
1448
+ ...abstractRectangle,
1449
+ width: location - abstractRectangle.x
1450
+ };
1451
+ }
1452
+ }
1453
+ };
1454
+ const getLocationScope = (board, handlePosition, parentChildren, element, parent, isHorizontal) => {
1455
+ const node = MindElement.getNode(element);
1456
+ const { start, end } = getCorrectStartEnd(node.origin, parent);
1457
+ const startNode = parentChildren[start];
1458
+ const endNode = parentChildren[end];
1459
+ if (handlePosition === AbstractHandlePosition.start) {
1460
+ const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.end < element.start);
1461
+ let minNode;
1462
+ if (abstractNode.length) {
1463
+ const index = abstractNode
1464
+ .map(node => {
1465
+ const { end } = getCorrectStartEnd(node, parent);
1466
+ return end;
1467
+ })
1468
+ .sort((a, b) => b - a)[0];
1469
+ minNode = parentChildren[index + 1];
1470
+ }
1471
+ else {
1472
+ minNode = parentChildren[0];
1473
+ }
1474
+ const minNodeRectangle = getRectangleByElements(board, [minNode], true);
1475
+ const endNodeRectangle = getRectangleByElements(board, [endNode], false);
1476
+ if (isHorizontal) {
1477
+ return {
1478
+ max: endNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1479
+ min: minNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET
1480
+ };
1481
+ }
1482
+ else {
1483
+ return {
1484
+ max: endNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1485
+ min: minNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET
1486
+ };
1487
+ }
1488
+ }
1489
+ else {
1490
+ const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.start > element.end);
1491
+ let maxNode;
1492
+ if (abstractNode.length) {
1493
+ const index = abstractNode
1494
+ .map(node => {
1495
+ const { start } = getCorrectStartEnd(node, parent);
1496
+ return start;
1497
+ })
1498
+ .sort((a, b) => a - b)[0];
1499
+ maxNode = parentChildren[index - 1];
1500
+ }
1501
+ else {
1502
+ const children = parentChildren.filter(child => !AbstractNode.isAbstract(child));
1503
+ maxNode = parentChildren[children.length - 1];
1504
+ }
1505
+ const maxNodeRectangle = getRectangleByElements(board, [maxNode], true);
1506
+ const startNodeRectangle = getRectangleByElements(board, [startNode], false);
1507
+ if (isHorizontal) {
1508
+ return {
1509
+ max: maxNodeRectangle.y + maxNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1510
+ min: startNodeRectangle.y + startNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET
1511
+ };
1512
+ }
1513
+ else {
1514
+ return {
1515
+ max: maxNodeRectangle.x + maxNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1516
+ min: startNodeRectangle.x + startNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET
1517
+ };
1518
+ }
1519
+ }
1520
+ };
1521
+ const getHitAbstractHandle = (board, element, point) => {
1522
+ const nodeLayout = MindQueries.getCorrectLayoutByElement(board, element);
1523
+ const isHorizontal = isHorizontalLayout(nodeLayout);
1524
+ const parentElement = MindElement.getParent(element);
1525
+ const includedElements = parentElement.children.slice(element.start, element.end + 1);
1526
+ let abstractRectangle = getRectangleByElements(board, includedElements, true);
1527
+ abstractRectangle = RectangleClient.getOutlineRectangle(abstractRectangle, -ABSTRACT_INCLUDED_OUTLINE_OFFSET);
1528
+ const startHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.start);
1529
+ const endHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.end);
1530
+ const pointRec = RectangleClient.toRectangleClient([point, point]);
1531
+ if (RectangleClient.isHit(pointRec, startHandleRec))
1532
+ return AbstractHandlePosition.start;
1533
+ if (RectangleClient.isHit(pointRec, endHandleRec))
1534
+ return AbstractHandlePosition.end;
1535
+ return undefined;
1536
+ };
1537
+ const getAbstractHandleRectangle = (rectangle, isHorizontal, position) => {
1538
+ let result;
1539
+ if (position === AbstractHandlePosition.start) {
1540
+ const location = isHorizontal ? rectangle.y : rectangle.x;
1541
+ result = getRectangleByResizingLocation(rectangle, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.end, isHorizontal);
1542
+ result = getRectangleByResizingLocation(result, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
1543
+ }
1544
+ else {
1545
+ const location = isHorizontal ? rectangle.y + rectangle.height : rectangle.x + rectangle.width;
1546
+ result = getRectangleByResizingLocation(rectangle, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.start, isHorizontal);
1547
+ result = getRectangleByResizingLocation(result, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
1548
+ }
1549
+ return result;
1550
+ };
1551
+ function findLocationLeftIndex(board, parentChildren, location, isHorizontal) {
1552
+ const children = parentChildren.filter(child => {
1553
+ return !AbstractNode.isAbstract(child);
1554
+ });
1555
+ const recArray = children.map(child => {
1556
+ return getRectangleByElements(board, [child], false);
1557
+ });
1558
+ const firstRec = getRectangleByElements(board, [children[0]], true);
1559
+ const fakeLeftRec = {
1560
+ x: firstRec.x - firstRec.width,
1561
+ y: firstRec.y - firstRec.height,
1562
+ width: firstRec.width,
1563
+ height: firstRec.height
1564
+ };
1565
+ const lastRec = getRectangleByElements(board, [children[children.length - 1]], true);
1566
+ const fakeRightRec = {
1567
+ x: lastRec.x + lastRec.width,
1568
+ y: lastRec.y + lastRec.height,
1569
+ width: lastRec.width,
1570
+ height: lastRec.height
1571
+ };
1572
+ recArray.push(fakeRightRec);
1573
+ recArray.unshift(fakeLeftRec);
1574
+ for (let i = 0; i < recArray.length - 1; i++) {
1575
+ const recXOrY = isHorizontal ? recArray[i].y : recArray[i].x;
1576
+ const recWidthOrHeight = isHorizontal ? recArray[i].height : recArray[i].width;
1577
+ if (location >= recXOrY + recWidthOrHeight / 2 &&
1578
+ location <= recArray[i + 1][isHorizontal ? 'y' : 'x'] + recArray[i + 1][isHorizontal ? 'height' : 'width'] / 2) {
1579
+ return i - 1;
1580
+ }
1581
+ }
1582
+ return 0;
1583
+ }
1584
+ function handleTouchedAbstract(board, touchedAbstract, endPoint) {
1585
+ let touchedHandle;
1586
+ const abstract = getSelectedElements(board)
1587
+ .filter(element => AbstractNode.isAbstract(element))
1588
+ .find(element => {
1589
+ touchedHandle = getHitAbstractHandle(board, element, endPoint);
1590
+ return touchedHandle;
1591
+ });
1592
+ if (touchedAbstract === abstract) {
1593
+ return touchedAbstract;
1594
+ }
1595
+ if (touchedAbstract) {
1596
+ const component = PlaitElement.getComponent(touchedAbstract);
1597
+ component.updateAbstractIncludedOutline();
1598
+ touchedAbstract = undefined;
1599
+ }
1600
+ if (abstract) {
1601
+ touchedAbstract = abstract;
1602
+ const component = PlaitElement.getComponent(touchedAbstract);
1603
+ component.updateAbstractIncludedOutline(touchedHandle);
1604
+ }
1605
+ return touchedAbstract;
1606
+ }
1607
+
1608
+ const isInRightBranchOfStandardLayout = (selectedElement) => {
1609
+ const parentElement = MindElement.findParent(selectedElement);
1610
+ if (parentElement) {
1611
+ const nodeIndex = parentElement.children.findIndex(item => item.id === selectedElement.id);
1612
+ if (parentElement.isRoot &&
1613
+ getRootLayout(parentElement) === MindLayoutType.standard &&
1614
+ parentElement.rightNodeCount &&
1615
+ nodeIndex <= parentElement.rightNodeCount - 1) {
1616
+ return true;
1617
+ }
1618
+ }
1619
+ return false;
1620
+ };
1621
+ const insertElementHandleRightNodeCount = (board, path, insertCount, effectedRightNodeCount = []) => {
1622
+ let index = effectedRightNodeCount.findIndex(ref => Path.equals(ref.path, path));
1623
+ const mind = PlaitNode.get(board, path);
1624
+ if (index === -1) {
1625
+ effectedRightNodeCount.push({ path, rightNodeCount: mind.rightNodeCount + insertCount });
1600
1626
  }
1601
- const selectedElement = PlaitNode.get(board, Path.previous(path));
1602
- const correspondingAbstract = getCorrespondingAbstract(selectedElement);
1603
- const isDragToLast = !isExtendPreviousNode && correspondingAbstract && correspondingAbstract.end === path[path.length - 1] - 1;
1604
- if (correspondingAbstract && !isDragToLast) {
1605
- let newProperties = effectedAbstracts.get(correspondingAbstract);
1606
- if (!newProperties) {
1607
- newProperties = { start: 0, end: 0 };
1608
- effectedAbstracts.set(correspondingAbstract, newProperties);
1609
- }
1610
- newProperties.end = newProperties.end + step;
1627
+ else {
1628
+ effectedRightNodeCount[index].rightNodeCount += insertCount;
1611
1629
  }
1612
- return effectedAbstracts;
1630
+ return effectedRightNodeCount;
1613
1631
  };
1614
- const deleteElementHandleAbstract = (board, deletableElements, effectedAbstracts = new Map()) => {
1615
- deletableElements.forEach(node => {
1616
- if (!PlaitMind.isMind(node)) {
1617
- const behindAbstracts = getBehindAbstracts(node).filter(abstract => !deletableElements.includes(abstract));
1618
- if (behindAbstracts.length) {
1619
- behindAbstracts.forEach(abstract => {
1620
- let newProperties = effectedAbstracts.get(abstract);
1621
- if (!newProperties) {
1622
- newProperties = { start: 0, end: 0 };
1623
- effectedAbstracts.set(abstract, newProperties);
1624
- }
1625
- newProperties.start = newProperties.start - 1;
1626
- newProperties.end = newProperties.end - 1;
1627
- });
1632
+ const deleteElementsHandleRightNodeCount = (board, deletableElements, effectedRightNodeCount = []) => {
1633
+ deletableElements.forEach(element => {
1634
+ if (isInRightBranchOfStandardLayout(element)) {
1635
+ const mind = MindElement.getParent(element);
1636
+ const path = PlaitBoard.findPath(board, mind);
1637
+ let index = effectedRightNodeCount.findIndex(ref => Path.equals(ref.path, path));
1638
+ if (index === -1) {
1639
+ effectedRightNodeCount.push({ path, rightNodeCount: mind.rightNodeCount - 1 });
1628
1640
  }
1629
- const correspondingAbstract = getCorrespondingAbstract(node);
1630
- if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
1631
- let newProperties = effectedAbstracts.get(correspondingAbstract);
1632
- if (!newProperties) {
1633
- newProperties = { start: 0, end: 0 };
1634
- effectedAbstracts.set(correspondingAbstract, newProperties);
1635
- }
1636
- newProperties.end = newProperties.end - 1;
1641
+ else {
1642
+ effectedRightNodeCount[index].rightNodeCount -= 1;
1637
1643
  }
1638
1644
  }
1639
1645
  });
1640
- return effectedAbstracts;
1646
+ return effectedRightNodeCount;
1641
1647
  };
1642
1648
 
1643
- var AbstractHandlePosition;
1644
- (function (AbstractHandlePosition) {
1645
- AbstractHandlePosition["start"] = "start";
1646
- AbstractHandlePosition["end"] = "end";
1647
- })(AbstractHandlePosition || (AbstractHandlePosition = {}));
1648
- var AbstractResizeState;
1649
- (function (AbstractResizeState) {
1650
- AbstractResizeState["start"] = "start";
1651
- AbstractResizeState["resizing"] = "resizing";
1652
- AbstractResizeState["end"] = "end";
1653
- })(AbstractResizeState || (AbstractResizeState = {}));
1654
-
1655
- const getRectangleByResizingLocation = (abstractRectangle, location, activeHandlePosition, isHorizontal) => {
1656
- if (isHorizontal) {
1657
- if (activeHandlePosition === AbstractHandlePosition.start) {
1658
- return {
1659
- ...abstractRectangle,
1660
- y: location,
1661
- height: abstractRectangle.height + abstractRectangle.y - location
1662
- };
1649
+ /**
1650
+ * get correctly layout:
1651
+ * 1. root is standard -> left or right
1652
+ * 2. correct layout by incorrect layout direction
1653
+ * @param element
1654
+ */
1655
+ const getCorrectLayoutByElement = (board, element) => {
1656
+ const ancestors = MindElement.getAncestors(board, element);
1657
+ ancestors.unshift(element);
1658
+ const root = ancestors[ancestors.length - 1];
1659
+ let rootLayout = getRootLayout(root);
1660
+ if (PlaitMind.isMind(element)) {
1661
+ return rootLayout;
1662
+ }
1663
+ const node = MindElement.getNode(element);
1664
+ let correctRootLayout = rootLayout;
1665
+ if (rootLayout === MindLayoutType.standard) {
1666
+ correctRootLayout = node.left ? MindLayoutType.left : MindLayoutType.right;
1667
+ }
1668
+ let layout = null;
1669
+ const elementWithLayout = ancestors.find(value => value.layout || AbstractNode.isAbstract(value));
1670
+ if (elementWithLayout) {
1671
+ if (AbstractNode.isAbstract(elementWithLayout)) {
1672
+ const parent = MindElement.getParent(elementWithLayout);
1673
+ const parentLayout = getCorrectLayoutByElement(board, parent);
1674
+ layout = getAbstractLayout(parentLayout);
1663
1675
  }
1664
1676
  else {
1665
- return {
1666
- ...abstractRectangle,
1667
- height: location - abstractRectangle.y
1668
- };
1677
+ layout = elementWithLayout?.layout;
1669
1678
  }
1670
1679
  }
1680
+ if (layout === MindLayoutType.standard || !layout) {
1681
+ return correctRootLayout;
1682
+ }
1671
1683
  else {
1672
- if (activeHandlePosition === AbstractHandlePosition.start) {
1673
- return {
1674
- ...abstractRectangle,
1675
- x: location,
1676
- width: abstractRectangle.width + abstractRectangle.x - location
1677
- };
1684
+ const incorrectDirection = getInCorrectLayoutDirection(correctRootLayout, layout);
1685
+ if (incorrectDirection) {
1686
+ return correctLayoutByDirection(layout, incorrectDirection);
1678
1687
  }
1679
1688
  else {
1680
- return {
1681
- ...abstractRectangle,
1682
- width: location - abstractRectangle.x
1683
- };
1689
+ return layout;
1684
1690
  }
1685
1691
  }
1686
1692
  };
1687
- const getLocationScope = (board, handlePosition, parentChildren, element, parent, isHorizontal) => {
1688
- const node = MindElement.getNode(element);
1689
- const { start, end } = getCorrectStartEnd(node.origin, parent);
1690
- const startNode = parentChildren[start];
1691
- const endNode = parentChildren[end];
1692
- if (handlePosition === AbstractHandlePosition.start) {
1693
- const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.end < element.start);
1694
- let minNode;
1695
- if (abstractNode.length) {
1696
- const index = abstractNode
1697
- .map(node => {
1698
- const { end } = getCorrectStartEnd(node, parent);
1699
- return end;
1700
- })
1701
- .sort((a, b) => b - a)[0];
1702
- minNode = parentChildren[index + 1];
1693
+
1694
+ const getBranchLayouts = (board, element) => {
1695
+ const layouts = [];
1696
+ if (element.layout) {
1697
+ // TODO: getCorrectLayoutByElement 含有递归操作,getBranchLayouts 本身也有递归操作,有待优化
1698
+ layouts.unshift(getCorrectLayoutByElement(board, element));
1699
+ }
1700
+ let parent = MindElement.findParent(element);
1701
+ while (parent) {
1702
+ if (parent.layout) {
1703
+ layouts.unshift(parent.layout);
1703
1704
  }
1704
- else {
1705
- minNode = parentChildren[0];
1705
+ parent = MindElement.findParent(parent);
1706
+ }
1707
+ return layouts;
1708
+ };
1709
+
1710
+ const getAvailableSubLayoutsByElement = (board, element) => {
1711
+ const parentElement = MindElement.findParent(element);
1712
+ if (parentElement) {
1713
+ const branchLayouts = getBranchLayouts(board, parentElement);
1714
+ if (branchLayouts[0] === MindLayoutType.standard) {
1715
+ const node = MindElement.getNode(element);
1716
+ branchLayouts[0] = node.left ? MindLayoutType.left : MindLayoutType.right;
1706
1717
  }
1707
- const minNodeRectangle = getRectangleByElements(board, [minNode], true);
1708
- const endNodeRectangle = getRectangleByElements(board, [endNode], false);
1709
- if (isHorizontal) {
1710
- return {
1711
- max: endNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1712
- min: minNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET
1713
- };
1718
+ const currentLayoutDirections = getBranchDirectionsByLayouts(branchLayouts);
1719
+ let availableSubLayouts = getAvailableSubLayoutsByLayoutDirections(currentLayoutDirections);
1720
+ const parentLayout = [branchLayouts[branchLayouts.length - 1]];
1721
+ const parentDirections = getBranchDirectionsByLayouts(parentLayout);
1722
+ const parentAvailableSubLayouts = getAvailableSubLayoutsByLayoutDirections(parentDirections);
1723
+ availableSubLayouts = availableSubLayouts.filter(layout => parentAvailableSubLayouts.some(parentAvailableSubLayout => parentAvailableSubLayout === layout));
1724
+ return availableSubLayouts;
1725
+ }
1726
+ return undefined;
1727
+ };
1728
+
1729
+ const getLayoutByElement = (element) => {
1730
+ const layout = element.layout;
1731
+ if (layout) {
1732
+ return layout;
1733
+ }
1734
+ const parent = !PlaitMind.isMind(element) && MindElement.getParent(element);
1735
+ if (AbstractNode.isAbstract(element) && parent) {
1736
+ return getAbstractLayout(getLayoutByElement(parent));
1737
+ }
1738
+ if (parent) {
1739
+ return getLayoutByElement(parent);
1740
+ }
1741
+ return getDefaultLayout();
1742
+ };
1743
+
1744
+ const MindQueries = {
1745
+ getAvailableSubLayoutsByElement,
1746
+ getBranchLayouts,
1747
+ getLayoutByElement,
1748
+ getCorrectLayoutByElement
1749
+ };
1750
+
1751
+ const PlaitMind = {
1752
+ isMind: (value) => {
1753
+ return value.type === 'mindmap';
1754
+ }
1755
+ };
1756
+ const MindElement = {
1757
+ hasLayout(value, layout) {
1758
+ const _layout = MindQueries.getLayoutByElement(value);
1759
+ return _layout === layout;
1760
+ },
1761
+ isIndentedLayout(value) {
1762
+ const _layout = MindQueries.getLayoutByElement(value);
1763
+ return isIndentedLayout(_layout);
1764
+ },
1765
+ isMindElement(board, element) {
1766
+ const path = PlaitBoard.findPath(board, element);
1767
+ const rootElement = PlaitNode.get(board, path.slice(0, 1));
1768
+ if (PlaitMind.isMind(rootElement)) {
1769
+ return true;
1714
1770
  }
1715
1771
  else {
1716
- return {
1717
- max: endNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1718
- min: minNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET
1719
- };
1772
+ return false;
1720
1773
  }
1721
- }
1722
- else {
1723
- const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.start > element.end);
1724
- let maxNode;
1725
- if (abstractNode.length) {
1726
- const index = abstractNode
1727
- .map(node => {
1728
- const { start } = getCorrectStartEnd(node, parent);
1729
- return start;
1730
- })
1731
- .sort((a, b) => a - b)[0];
1732
- maxNode = parentChildren[index - 1];
1774
+ },
1775
+ getParent(node) {
1776
+ if (PlaitMind.isMind(node)) {
1777
+ throw new Error('mind root node can not get parent');
1778
+ }
1779
+ const parent = NODE_TO_PARENT.get(node);
1780
+ return parent;
1781
+ },
1782
+ findParent(node) {
1783
+ if (PlaitMind.isMind(node)) {
1784
+ return undefined;
1785
+ }
1786
+ const parent = NODE_TO_PARENT.get(node);
1787
+ return parent;
1788
+ },
1789
+ getRoot(board, element) {
1790
+ const path = PlaitBoard.findPath(board, element);
1791
+ return PlaitNode.get(board, path.slice(0, 1));
1792
+ },
1793
+ getAncestors(board, element) {
1794
+ const path = PlaitBoard.findPath(board, element);
1795
+ const parents = [];
1796
+ for (const p of Path.ancestors(path, { reverse: true })) {
1797
+ const n = PlaitNode.get(board, p);
1798
+ if (n && !PlaitBoard.isBoard(n)) {
1799
+ parents.push(n);
1800
+ }
1733
1801
  }
1734
- else {
1735
- const children = parentChildren.filter(child => !AbstractNode.isAbstract(child));
1736
- maxNode = parentChildren[children.length - 1];
1802
+ return parents;
1803
+ },
1804
+ getNode(element) {
1805
+ const node = ELEMENT_TO_NODE.get(element);
1806
+ if (!node) {
1807
+ throw new Error(`can not get node from ${JSON.stringify(element)}`);
1737
1808
  }
1738
- const maxNodeRectangle = getRectangleByElements(board, [maxNode], true);
1739
- const startNodeRectangle = getRectangleByElements(board, [startNode], false);
1740
- if (isHorizontal) {
1741
- return {
1742
- max: maxNodeRectangle.y + maxNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1743
- min: startNodeRectangle.y + startNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET
1744
- };
1809
+ return node;
1810
+ },
1811
+ findParentNode(element) {
1812
+ if (PlaitMind.isMind(element)) {
1813
+ return undefined;
1814
+ }
1815
+ const parent = MindElement.getParent(element);
1816
+ return MindElement.getNode(parent);
1817
+ },
1818
+ hasEmojis(element) {
1819
+ if (element.data.emojis) {
1820
+ return true;
1745
1821
  }
1746
1822
  else {
1747
- return {
1748
- max: maxNodeRectangle.x + maxNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1749
- min: startNodeRectangle.x + startNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET
1750
- };
1823
+ return false;
1751
1824
  }
1825
+ },
1826
+ getEmojis(element) {
1827
+ return element.data.emojis;
1752
1828
  }
1753
1829
  };
1754
- const getHitAbstractHandle = (board, element, point) => {
1755
- const nodeLayout = MindQueries.getCorrectLayoutByElement(board, element);
1756
- const isHorizontal = isHorizontalLayout(nodeLayout);
1757
- const parentElement = MindElement.getParent(element);
1758
- const includedElements = parentElement.children.slice(element.start, element.end + 1);
1759
- let abstractRectangle = getRectangleByElements(board, includedElements, true);
1760
- abstractRectangle = RectangleClient.getOutlineRectangle(abstractRectangle, -ABSTRACT_INCLUDED_OUTLINE_OFFSET);
1761
- const startHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.start);
1762
- const endHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.end);
1763
- const pointRec = RectangleClient.toRectangleClient([point, point]);
1764
- if (RectangleClient.isHit(pointRec, startHandleRec))
1765
- return AbstractHandlePosition.start;
1766
- if (RectangleClient.isHit(pointRec, endHandleRec))
1767
- return AbstractHandlePosition.end;
1768
- return undefined;
1769
- };
1770
- const getAbstractHandleRectangle = (rectangle, isHorizontal, position) => {
1771
- let result;
1772
- if (position === AbstractHandlePosition.start) {
1773
- const location = isHorizontal ? rectangle.y : rectangle.x;
1774
- result = getRectangleByResizingLocation(rectangle, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.end, isHorizontal);
1775
- result = getRectangleByResizingLocation(result, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
1830
+ var MindElementShape;
1831
+ (function (MindElementShape) {
1832
+ MindElementShape["roundRectangle"] = "round-rectangle";
1833
+ MindElementShape["underline"] = "underline";
1834
+ })(MindElementShape || (MindElementShape = {}));
1835
+ var BranchShape;
1836
+ (function (BranchShape) {
1837
+ BranchShape["bight"] = "bight";
1838
+ BranchShape["polyline"] = "polyline";
1839
+ })(BranchShape || (BranchShape = {}));
1840
+
1841
+ const NodeDefaultSpace = {
1842
+ horizontal: {
1843
+ nodeAndText: BASE * 3,
1844
+ emojiAndText: BASE * 1.5
1845
+ },
1846
+ vertical: {
1847
+ nodeAndText: BASE * 1.5
1776
1848
  }
1777
- else {
1778
- const location = isHorizontal ? rectangle.y + rectangle.height : rectangle.x + rectangle.width;
1779
- result = getRectangleByResizingLocation(rectangle, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.start, isHorizontal);
1780
- result = getRectangleByResizingLocation(result, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
1849
+ };
1850
+ const RootDefaultSpace = {
1851
+ horizontal: {
1852
+ nodeAndText: BASE * 4,
1853
+ emojiAndText: BASE * 2
1854
+ },
1855
+ vertical: {
1856
+ nodeAndText: BASE * 2
1781
1857
  }
1782
- return result;
1783
1858
  };
1784
- function findLocationLeftIndex(board, parentChildren, location, isHorizontal) {
1785
- const children = parentChildren.filter(child => {
1786
- return !AbstractNode.isAbstract(child);
1787
- });
1788
- const recArray = children.map(child => {
1789
- return getRectangleByElements(board, [child], false);
1790
- });
1791
- const firstRec = getRectangleByElements(board, [children[0]], true);
1792
- const fakeLeftRec = {
1793
- x: firstRec.x - firstRec.width,
1794
- y: firstRec.y - firstRec.height,
1795
- width: firstRec.width,
1796
- height: firstRec.height
1797
- };
1798
- const lastRec = getRectangleByElements(board, [children[children.length - 1]], true);
1799
- const fakeRightRec = {
1800
- x: lastRec.x + lastRec.width,
1801
- y: lastRec.y + lastRec.height,
1802
- width: lastRec.width,
1803
- height: lastRec.height
1804
- };
1805
- recArray.push(fakeRightRec);
1806
- recArray.unshift(fakeLeftRec);
1807
- for (let i = 0; i < recArray.length - 1; i++) {
1808
- const recXOrY = isHorizontal ? recArray[i].y : recArray[i].x;
1809
- const recWidthOrHeight = isHorizontal ? recArray[i].height : recArray[i].width;
1810
- if (location >= recXOrY + recWidthOrHeight / 2 &&
1811
- location <= recArray[i + 1][isHorizontal ? 'y' : 'x'] + recArray[i + 1][isHorizontal ? 'height' : 'width'] / 2) {
1812
- return i - 1;
1859
+ const getHorizontalSpaceBetweenNodeAndText = (board, element) => {
1860
+ const isMind = PlaitMind.isMind(element);
1861
+ const nodeAndText = isMind ? RootDefaultSpace.horizontal.nodeAndText : NodeDefaultSpace.horizontal.nodeAndText;
1862
+ return nodeAndText;
1863
+ };
1864
+ const getVerticalSpaceBetweenNodeAndText = (element) => {
1865
+ const isMind = PlaitMind.isMind(element);
1866
+ const nodeAndText = isMind ? RootDefaultSpace.vertical.nodeAndText : NodeDefaultSpace.vertical.nodeAndText;
1867
+ return nodeAndText;
1868
+ };
1869
+ const getSpaceEmojiAndText = (element) => {
1870
+ const isMind = PlaitMind.isMind(element);
1871
+ const emojiAndText = isMind ? RootDefaultSpace.horizontal.emojiAndText : NodeDefaultSpace.horizontal.emojiAndText;
1872
+ return emojiAndText;
1873
+ };
1874
+ const NodeSpace = {
1875
+ getNodeWidth(board, element) {
1876
+ const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
1877
+ if (MindElement.hasEmojis(element)) {
1878
+ return (NodeSpace.getEmojiLeftSpace(board, element) +
1879
+ getEmojisWidthHeight(board, element).width +
1880
+ getSpaceEmojiAndText(element) +
1881
+ element.width +
1882
+ nodeAndText);
1813
1883
  }
1814
- }
1815
- return 0;
1816
- }
1817
- function handleTouchedAbstract(board, touchedAbstract, endPoint) {
1818
- let touchedHandle;
1819
- const abstract = getSelectedElements(board)
1820
- .filter(element => AbstractNode.isAbstract(element))
1821
- .find(element => {
1822
- touchedHandle = getHitAbstractHandle(board, element, endPoint);
1823
- return touchedHandle;
1824
- });
1825
- if (touchedAbstract === abstract) {
1826
- return touchedAbstract;
1827
- }
1828
- if (touchedAbstract) {
1829
- const component = PlaitElement.getComponent(touchedAbstract);
1830
- component.updateAbstractIncludedOutline();
1831
- touchedAbstract = undefined;
1832
- }
1833
- if (abstract) {
1834
- touchedAbstract = abstract;
1835
- const component = PlaitElement.getComponent(touchedAbstract);
1836
- component.updateAbstractIncludedOutline(touchedHandle);
1837
- }
1838
- return touchedAbstract;
1839
- }
1840
-
1841
- function drawIndentedLink(board, node, child, defaultStroke = null, needDrawUnderline = true, defaultStrokeWidth) {
1842
- const branchWidth = defaultStrokeWidth || getBranchWidthByMindElement(board, child.origin);
1843
- const branchColor = defaultStroke || getBranchColorByMindElement(board, child.origin);
1844
- const isUnderlineShape = getShapeByElement(board, child.origin) === MindElementShape.underline;
1845
- let beginX, beginY, endX, endY, beginNode = node, endNode = child;
1846
- const beginRectangle = getRectangleByNode(beginNode);
1847
- const endRectangle = getRectangleByNode(endNode);
1848
- beginX = beginNode.x + beginNode.width / 2;
1849
- beginY = isChildUp(node, child) ? beginRectangle.y : beginRectangle.y + beginRectangle.height;
1850
- endX = node.left ? endNode.x + endNode.hGap + endRectangle.width : endNode.x + endNode.hGap;
1851
- endY = isUnderlineShape ? endNode.y + endNode.height - endNode.vGap : endNode.y + endNode.height / 2;
1852
- //根据位置,设置正负参数
1853
- let plusMinus = isChildUp(node, child) ? (node.left ? [-1, -1] : [1, -1]) : node.left ? [-1, 1] : [1, 1];
1854
- const layout = MindQueries.getCorrectLayoutByElement(board, node.origin);
1855
- if (beginNode.origin.isRoot) {
1856
- if (layout === MindLayoutType.leftBottomIndented || layout === MindLayoutType.rightBottomIndented) {
1857
- beginY += branchWidth;
1884
+ return nodeAndText + element.width + nodeAndText;
1885
+ },
1886
+ getNodeHeight(board, element) {
1887
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
1888
+ return nodeAndText + element.height + nodeAndText;
1889
+ },
1890
+ getTextLeftSpace(board, element) {
1891
+ const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
1892
+ if (MindElement.hasEmojis(element)) {
1893
+ return NodeSpace.getEmojiLeftSpace(board, element) + getEmojisWidthHeight(board, element).width + getSpaceEmojiAndText(element);
1858
1894
  }
1859
- if (layout === MindLayoutType.leftTopIndented || layout === MindLayoutType.rightTopIndented) {
1860
- beginY -= branchWidth;
1895
+ else {
1896
+ return nodeAndText;
1861
1897
  }
1898
+ },
1899
+ getTextTopSpace(element) {
1900
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
1901
+ return nodeAndText;
1902
+ },
1903
+ getEmojiLeftSpace(board, element) {
1904
+ const options = board.getMindOptions();
1905
+ const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
1906
+ return nodeAndText - options.emojiPadding;
1907
+ },
1908
+ getEmojiTopSpace(element) {
1909
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
1910
+ return nodeAndText;
1862
1911
  }
1863
- let curve = [
1864
- [beginX, beginY],
1865
- [beginX, beginY],
1866
- [beginX, beginY],
1867
- [beginX, endY - (endNode.hGap * 3 * plusMinus[1]) / 5],
1868
- [beginX, endY - (endNode.hGap * plusMinus[1]) / 5],
1869
- [beginX + (endNode.hGap * plusMinus[0]) / 4, endY],
1870
- [beginX + (endNode.hGap * plusMinus[0] * 3) / 5, endY],
1871
- isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
1872
- isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
1873
- isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY]
1874
- ];
1875
- const points = pointsOnBezierCurves(curve);
1876
- return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth: branchWidth });
1912
+ };
1913
+
1914
+ function getTopicRectangleByNode(board, node) {
1915
+ let nodeRectangle = getRectangleByNode(node);
1916
+ return getTopicRectangleByElement(board, nodeRectangle, node.origin);
1917
+ }
1918
+ function getTopicRectangleByElement(board, nodeRectangle, element) {
1919
+ const x = nodeRectangle.x + NodeSpace.getTextLeftSpace(board, element);
1920
+ const y = nodeRectangle.y + NodeSpace.getTextTopSpace(element);
1921
+ const width = Math.ceil(element.width);
1922
+ const height = Math.ceil(element.height);
1923
+ return { height, width, x, y };
1877
1924
  }
1878
1925
 
1879
1926
  function drawTopicByNode(board, node, viewContainerRef) {
@@ -1910,6 +1957,7 @@ function drawAbstractLink(board, node, isHorizontal) {
1910
1957
  const branchWidth = getAbstractBranchWidth(board, node.origin);
1911
1958
  const branchColor = getAbstractBranchColor(board, node.origin);
1912
1959
  const parent = node.parent;
1960
+ const branchShape = getBranchShapeByMindElement(board, parent.origin);
1913
1961
  const abstractRectangle = getRectangleByNode(node);
1914
1962
  let includedElements = parent.children.slice(node.origin.start, node.origin.end + 1).map(node => {
1915
1963
  return node.origin;
@@ -1931,6 +1979,20 @@ function drawAbstractLink(board, node, isHorizontal) {
1931
1979
  bezierEndPoint = moveXOfPoint(bezierEndPoint, linkPadding, linkDirection);
1932
1980
  let c2 = moveXOfPoint(bezierEndPoint, curveDistance, linkDirection);
1933
1981
  let bezierConnectorPoint = moveXOfPoint(abstractConnectorPoint, -linkPadding, linkDirection);
1982
+ if (branchShape === BranchShape.polyline) {
1983
+ const g = createG();
1984
+ const polyline = drawLinearPath([bezierBeginPoint, c1, bezierConnectorPoint, c2, bezierEndPoint], {
1985
+ stroke: branchColor,
1986
+ strokeWidth: branchWidth
1987
+ });
1988
+ const straightLine = drawLinearPath([abstractConnectorPoint, bezierConnectorPoint], {
1989
+ stroke: branchColor,
1990
+ strokeWidth: branchWidth
1991
+ });
1992
+ g.appendChild(polyline);
1993
+ g.appendChild(straightLine);
1994
+ return g;
1995
+ }
1934
1996
  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]}`, {
1935
1997
  stroke: branchColor,
1936
1998
  strokeWidth: branchWidth
@@ -2115,16 +2177,14 @@ const setTopicSize = (board, element, width, height) => {
2115
2177
  Transforms.setNode(board, newElement, path);
2116
2178
  };
2117
2179
  const removeElements = (board, elements) => {
2118
- const deletableElements = getFirstLevelElement(elements).reverse();
2119
- //翻转,从下到上修改,防止找不到 path
2180
+ const deletableElements = getFirstLevelElement(elements);
2120
2181
  deletableElements
2121
2182
  .map(element => {
2122
2183
  const path = PlaitBoard.findPath(board, element);
2184
+ const ref = board.pathRef(path);
2123
2185
  return () => {
2124
- if (isInRightBranchOfStandardLayout(element)) {
2125
- changeRightNodeCount(board, path.slice(0, 1), -1);
2126
- }
2127
- Transforms.removeNode(board, path);
2186
+ Transforms.removeNode(board, ref.current);
2187
+ ref.unref();
2128
2188
  };
2129
2189
  })
2130
2190
  .forEach(action => {
@@ -2153,6 +2213,11 @@ const insertAbstractNodes = (board, validAbstractRefs, elements, path) => {
2153
2213
  });
2154
2214
  insertNodes(board, abstracts, abstractPath);
2155
2215
  };
2216
+ const setRightNodeCountByRefs = (board, refs) => {
2217
+ refs.forEach(ref => {
2218
+ Transforms.setNode(board, { rightNodeCount: ref.rightNodeCount }, ref.path);
2219
+ });
2220
+ };
2156
2221
 
2157
2222
  const addEmoji = (board, element, emojiItem) => {
2158
2223
  const emojis = element.data.emojis || [];
@@ -2202,7 +2267,8 @@ const MindTransforms = {
2202
2267
  setAbstractByStandardLayout,
2203
2268
  removeElements,
2204
2269
  insertNodes,
2205
- insertAbstractNodes
2270
+ insertAbstractNodes,
2271
+ setRightNodeCountByRefs
2206
2272
  };
2207
2273
 
2208
2274
  function drawAbstractIncludedOutline(board, roughSVG, element, activeHandlePosition, resizingLocation) {
@@ -2608,11 +2674,8 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2608
2674
  if (AbstractNode.isAbstract(this.node.origin)) {
2609
2675
  this.linkG = drawAbstractLink(this.board, this.node, isHorizontalLayout(layout));
2610
2676
  }
2611
- else if (MindElement.isIndentedLayout(parent)) {
2612
- this.linkG = drawIndentedLink(this.board, parentNode, this.node);
2613
- }
2614
2677
  else {
2615
- this.linkG = drawLogicLink(this.board, this.node, parentNode, isHorizontalLayout(layout));
2678
+ this.linkG = drawLink(this.board, parentNode, this.node, isHorizontalLayout(layout));
2616
2679
  }
2617
2680
  this.g.append(this.linkG);
2618
2681
  }
@@ -3011,8 +3074,8 @@ class MindNodeComponent extends PlaitPluginElementComponent {
3011
3074
  }
3012
3075
  }
3013
3076
  }
3014
- MindNodeComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: MindNodeComponent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
3015
- MindNodeComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: MindNodeComponent, selector: "plait-mind-node", usesInheritance: true, ngImport: i0, template: `
3077
+ MindNodeComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindNodeComponent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
3078
+ MindNodeComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.5", type: MindNodeComponent, selector: "plait-mind-node", usesInheritance: true, ngImport: i0, template: `
3016
3079
  <plait-children
3017
3080
  *ngIf="!element.isCollapsed"
3018
3081
  [board]="board"
@@ -3021,7 +3084,7 @@ MindNodeComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", vers
3021
3084
  [parentG]="parentG"
3022
3085
  ></plait-children>
3023
3086
  `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.PlaitChildrenElement, selector: "plait-children", inputs: ["board", "parent", "effect", "parentG"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3024
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: MindNodeComponent, decorators: [{
3087
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindNodeComponent, decorators: [{
3025
3088
  type: Component,
3026
3089
  args: [{
3027
3090
  selector: 'plait-mind-node',
@@ -3131,11 +3194,11 @@ class PlaitMindComponent extends MindNodeComponent {
3131
3194
  });
3132
3195
  }
3133
3196
  }
3134
- PlaitMindComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: PlaitMindComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3135
- PlaitMindComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: PlaitMindComponent, selector: "plait-mind", usesInheritance: true, ngImport: i0, template: `
3197
+ PlaitMindComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: PlaitMindComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3198
+ PlaitMindComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.5", type: PlaitMindComponent, selector: "plait-mind", usesInheritance: true, ngImport: i0, template: `
3136
3199
  <plait-children [board]="board" [parent]="element" [effect]="effect" [parentG]="rootG"></plait-children>
3137
3200
  `, isInline: true, dependencies: [{ kind: "component", type: i2.PlaitChildrenElement, selector: "plait-children", inputs: ["board", "parent", "effect", "parentG"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3138
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: PlaitMindComponent, decorators: [{
3201
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: PlaitMindComponent, decorators: [{
3139
3202
  type: Component,
3140
3203
  args: [{
3141
3204
  selector: 'plait-mind',
@@ -3148,10 +3211,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImpor
3148
3211
 
3149
3212
  class MindModule {
3150
3213
  }
3151
- MindModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: MindModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3152
- MindModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.2", ngImport: i0, type: MindModule, declarations: [PlaitMindComponent, MindNodeComponent], imports: [CommonModule, RichtextModule, PlaitModule], exports: [PlaitMindComponent, MindNodeComponent] });
3153
- MindModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: MindModule, imports: [CommonModule, RichtextModule, PlaitModule] });
3154
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: MindModule, decorators: [{
3214
+ MindModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3215
+ MindModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.5", ngImport: i0, type: MindModule, declarations: [PlaitMindComponent, MindNodeComponent], imports: [CommonModule, RichtextModule, PlaitModule], exports: [PlaitMindComponent, MindNodeComponent] });
3216
+ MindModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, imports: [CommonModule, RichtextModule, PlaitModule] });
3217
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, decorators: [{
3155
3218
  type: NgModule,
3156
3219
  args: [{
3157
3220
  declarations: [PlaitMindComponent, MindNodeComponent],
@@ -3220,7 +3283,7 @@ const withDnd = (board) => {
3220
3283
  dropTarget = detectDropTarget(board, detectPoint, dropTarget, [...activeElements, ...correspondingElements]);
3221
3284
  if (dropTarget?.target) {
3222
3285
  targetPath = getPathByDropTarget(board, dropTarget);
3223
- fakeDropNodeG = drawFakeDropNodeByPath(board, dropTarget.target, targetPath);
3286
+ fakeDropNodeG = drawFakeDropNode(board, dropTarget.target, targetPath);
3224
3287
  PlaitBoard.getHost(board).appendChild(fakeDropNodeG);
3225
3288
  }
3226
3289
  const offsetX = endPoint[0] - startPoint[0];
@@ -3263,6 +3326,14 @@ const withDnd = (board) => {
3263
3326
  const effectedAbstracts = deleteElementHandleAbstract(board, elements);
3264
3327
  insertElementHandleAbstract(board, targetPath, normalElements.length, false, effectedAbstracts);
3265
3328
  MindTransforms.setAbstractsByRefs(board, effectedAbstracts);
3329
+ let refs = deleteElementsHandleRightNodeCount(board, elements);
3330
+ const shouldChangeRoot = isInRightBranchOfStandardLayout(dropTarget?.target) &&
3331
+ targetElementPathRef.current &&
3332
+ (Path.isSibling(targetPath, targetElementPathRef.current) || Path.equals(targetPath, targetElementPathRef.current));
3333
+ if (shouldChangeRoot && targetElementPathRef.current) {
3334
+ refs = insertElementHandleRightNodeCount(board, targetElementPathRef.current.slice(0, 1), normalElements.length, refs);
3335
+ }
3336
+ MindTransforms.setRightNodeCountByRefs(board, refs);
3266
3337
  MindTransforms.removeElements(board, elements);
3267
3338
  let insertPath = targetPathRef.current;
3268
3339
  const parentPath = Path.parent(targetPathRef.current || targetPath);
@@ -3275,12 +3346,6 @@ const withDnd = (board) => {
3275
3346
  if (abstractRefs.length) {
3276
3347
  MindTransforms.insertAbstractNodes(board, abstractRefs, normalElements, insertPath);
3277
3348
  }
3278
- const shouldChangeRoot = isInRightBranchOfStandardLayout(dropTarget?.target) &&
3279
- targetElementPathRef.current &&
3280
- (Path.isSibling(targetPath, targetElementPathRef.current) || Path.equals(targetPath, targetElementPathRef.current));
3281
- if (shouldChangeRoot && targetElementPathRef.current) {
3282
- changeRightNodeCount(board, targetElementPathRef.current.slice(0, 1), normalElements.length);
3283
- }
3284
3349
  if (targetElementPathRef.current &&
3285
3350
  targetPathRef.current &&
3286
3351
  Path.isAncestor(targetElementPathRef.current, targetPathRef.current) &&
@@ -3289,10 +3354,9 @@ const withDnd = (board) => {
3289
3354
  }
3290
3355
  targetElementPathRef.unref();
3291
3356
  targetPathRef.unref();
3292
- const selectedElements = getSelectedElements(board);
3293
3357
  let setActiveElements = [];
3294
3358
  depthFirstRecursion(board, node => {
3295
- const isSelected = selectedElements.some(element => element.id === node.id);
3359
+ const isSelected = activeElements.some(element => element.id === node.id);
3296
3360
  if (isSelected) {
3297
3361
  setActiveElements.push(node);
3298
3362
  }
@@ -3427,6 +3491,10 @@ const withAbstract = (board) => {
3427
3491
  let startPoint;
3428
3492
  let newProperty;
3429
3493
  board.mousedown = (event) => {
3494
+ if (!isMainPointer(event)) {
3495
+ mousedown(event);
3496
+ return;
3497
+ }
3430
3498
  const activeAbstractElements = getSelectedElements(board).filter(element => AbstractNode.isAbstract(element));
3431
3499
  const host = BOARD_TO_HOST.get(board);
3432
3500
  const point = transformPoint(board, toPoint(event.x, event.y, host));
@@ -3580,6 +3648,7 @@ const withCreateMind = (board) => {
3580
3648
  const targetPoint = transformPoint(board, toPoint(movingPoint[0], movingPoint[1], PlaitBoard.getHost(board)));
3581
3649
  const emptyMind = createEmptyMind(board, targetPoint);
3582
3650
  Transforms.insertNode(board, emptyMind, [board.children.length]);
3651
+ addSelectedElement(board, emptyMind);
3583
3652
  BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
3584
3653
  }
3585
3654
  destroy();
@@ -3673,7 +3742,8 @@ const withMind = (board) => {
3673
3742
  }
3674
3743
  else {
3675
3744
  if (isInRightBranchOfStandardLayout(selectedElement)) {
3676
- changeRightNodeCount(board, selectedElementPath.slice(0, 1), 1);
3745
+ const refs = insertElementHandleRightNodeCount(board, selectedElementPath.slice(0, 1), 1);
3746
+ MindTransforms.setRightNodeCountByRefs(board, refs);
3677
3747
  }
3678
3748
  const abstractRefs = insertElementHandleAbstract(board, Path.next(selectedElementPath));
3679
3749
  MindTransforms.setAbstractsByRefs(board, abstractRefs);
@@ -3686,6 +3756,8 @@ const withMind = (board) => {
3686
3756
  const deletableElements = getFirstLevelElement(selectedElements).reverse();
3687
3757
  const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
3688
3758
  MindTransforms.setAbstractsByRefs(board, abstractRefs);
3759
+ const refs = deleteElementsHandleRightNodeCount(board, selectedElements);
3760
+ MindTransforms.setRightNodeCountByRefs(board, refs);
3689
3761
  MindTransforms.removeElements(board, selectedElements);
3690
3762
  let activeElement;
3691
3763
  const firstLevelElements = getFirstLevelElement(selectedElements);
@@ -3791,6 +3863,8 @@ const withMind = (board) => {
3791
3863
  const deletableElements = getFirstLevelElement(selectedElements).reverse();
3792
3864
  const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
3793
3865
  MindTransforms.setAbstractsByRefs(board, abstractRefs);
3866
+ const refs = deleteElementsHandleRightNodeCount(board, selectedElements);
3867
+ MindTransforms.setRightNodeCountByRefs(board, refs);
3794
3868
  MindTransforms.removeElements(board, selectedElements);
3795
3869
  deleteFragment(data);
3796
3870
  };
@@ -3809,9 +3883,9 @@ class MindEmojiBaseComponent {
3809
3883
  this.elementRef.nativeElement.style.fontSize = `${this.fontSize}px`;
3810
3884
  }
3811
3885
  }
3812
- MindEmojiBaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: MindEmojiBaseComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
3813
- MindEmojiBaseComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.2", type: MindEmojiBaseComponent, inputs: { fontSize: "fontSize", emojiItem: "emojiItem", board: "board", element: "element" }, host: { classAttribute: "mind-node-emoji" }, ngImport: i0 });
3814
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: MindEmojiBaseComponent, decorators: [{
3886
+ MindEmojiBaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindEmojiBaseComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
3887
+ MindEmojiBaseComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: MindEmojiBaseComponent, inputs: { fontSize: "fontSize", emojiItem: "emojiItem", board: "board", element: "element" }, host: { classAttribute: "mind-node-emoji" }, ngImport: i0 });
3888
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindEmojiBaseComponent, decorators: [{
3815
3889
  type: Directive,
3816
3890
  args: [{
3817
3891
  host: {
@@ -3836,5 +3910,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImpor
3836
3910
  * Generated bundle index. Do not edit.
3837
3911
  */
3838
3912
 
3839
- export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_COLORS, BRANCH_WIDTH, BaseDrawer, DefaultAbstractNodeStyle, DefaultNodeStyle, DefaultRootStyle, ELEMENT_TO_NODE, EXTEND_OFFSET, EXTEND_RADIUS, GRAY_COLOR, IS_DRAGGING, LayoutDirection, LayoutDirectionsMap, MindElement, MindElementShape, MindEmojiBaseComponent, MindModule, MindNode, MindNodeComponent, MindPointerType, 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, addActiveOnDragOrigin, canSetAbstract, changeRightNodeCount, copyNewNode, correctLayoutByDirection, deleteElementHandleAbstract, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNodeByPath, extractNodesText, findLastChild, findLocationLeftIndex, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultLayout, getEmojiForeignRectangle, getEmojiRectangle, getFirstLevelElement, getHitAbstractHandle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection, getLocationScope, getNextBranchColor, getOverallAbstracts, getPathByDropTarget, getPreviousAndNextByPath, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getShapeByElement, getStrokeByMindElement, getTopicRectangleByElement, getTopicRectangleByNode, getValidAbstractRefs, handleTouchedAbstract, hasAfterDraw, insertElementHandleAbstract, insertMindElement, isChildElement, isChildRight, isChildUp, isCorrectLayout, isDragging, isHitEmojis, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, isVirtualKey, readjustmentDropTarget, removeActiveOnDragOrigin, separateChildren, setIsDragging, withMind, withMindExtend };
3913
+ export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_COLORS, BRANCH_WIDTH, BaseDrawer, BranchShape, DefaultAbstractNodeStyle, DefaultNodeStyle, DefaultRootStyle, ELEMENT_TO_NODE, EXTEND_OFFSET, EXTEND_RADIUS, GRAY_COLOR, IS_DRAGGING, LayoutDirection, LayoutDirectionsMap, MindElement, MindElementShape, MindEmojiBaseComponent, MindModule, MindNode, MindNodeComponent, MindPointerType, 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, addActiveOnDragOrigin, adjustAbstractToNode, adjustNodeToRoot, adjustRootToNode, canSetAbstract, copyNewNode, correctLayoutByDirection, createDefaultMind, createEmptyMind, createMindElement, deleteElementHandleAbstract, deleteElementsHandleRightNodeCount, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNode, enterNodeEditing, extractNodesText, findLastChild, findLocationLeftIndex, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchShapeByMindElement, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultLayout, getEmojiForeignRectangle, getEmojiRectangle, getFirstLevelElement, getHitAbstractHandle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection, getLocationScope, getNextBranchColor, getOverallAbstracts, getPathByDropTarget, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getShapeByElement, getStrokeByMindElement, getTopicRectangleByElement, getTopicRectangleByNode, getValidAbstractRefs, handleTouchedAbstract, hasAfterDraw, hasPreviousOrNextOfDropPath, insertElementHandleAbstract, insertElementHandleRightNodeCount, insertMindElement, isChildElement, isChildRight, isChildUp, isCorrectLayout, isDragging, isHitEmojis, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, isVirtualKey, readjustmentDropTarget, removeActiveOnDragOrigin, separateChildren, setIsDragging, withMind, withMindExtend };
3840
3914
  //# sourceMappingURL=plait-mind.mjs.map