@plait/mind 0.2.2 → 0.3.1

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 (130) hide show
  1. package/{drawer/base/base.d.ts → base/base.drawer.d.ts} +1 -1
  2. package/{plugins/emoji → base}/emoji-base.component.d.ts +2 -2
  3. package/{plugins/emoji → base}/index.d.ts +1 -1
  4. package/draw/abstract.d.ts +2 -1
  5. package/draw/indented-link.d.ts +1 -1
  6. package/draw/link/logic-link.d.ts +1 -1
  7. package/draw/node.d.ts +5 -0
  8. package/draw/topic.d.ts +16 -0
  9. package/{plugins/emoji → drawer}/emoji.drawer.d.ts +3 -3
  10. package/drawer/quick-insert.drawer.d.ts +1 -1
  11. package/esm2020/base/base.drawer.mjs +17 -0
  12. package/esm2020/base/emoji-base.component.mjs +33 -0
  13. package/esm2020/base/index.mjs +3 -0
  14. package/esm2020/draw/abstract.mjs +8 -7
  15. package/esm2020/draw/indented-link.mjs +3 -3
  16. package/esm2020/draw/link/abstract-link.mjs +9 -15
  17. package/esm2020/draw/link/logic-link.mjs +9 -9
  18. package/esm2020/draw/node.mjs +21 -0
  19. package/esm2020/draw/topic.mjs +32 -0
  20. package/esm2020/drawer/emoji.drawer.mjs +73 -0
  21. package/esm2020/drawer/quick-insert.drawer.mjs +3 -3
  22. package/esm2020/interfaces/index.mjs +2 -2
  23. package/esm2020/interfaces/pointer.mjs +5 -0
  24. package/esm2020/mind.component.mjs +2 -2
  25. package/esm2020/mind.module.mjs +5 -5
  26. package/esm2020/node.component.mjs +11 -10
  27. package/esm2020/plugins/with-abstract-resize.board.mjs +12 -0
  28. package/esm2020/plugins/with-abstract-resize.mjs +107 -0
  29. package/esm2020/plugins/with-mind-create.mjs +85 -0
  30. package/esm2020/plugins/with-mind-extend.mjs +11 -0
  31. package/esm2020/plugins/with-mind.board.mjs +2 -0
  32. package/esm2020/plugins/with-mind.mjs +30 -16
  33. package/esm2020/plugins/with-node-dnd.mjs +162 -0
  34. package/esm2020/public-api.mjs +5 -3
  35. package/esm2020/transforms/abstract-node.mjs +3 -2
  36. package/esm2020/transforms/emoji.mjs +37 -0
  37. package/esm2020/transforms/index.mjs +7 -3
  38. package/esm2020/transforms/node.mjs +40 -33
  39. package/esm2020/utils/abstract/common.mjs +64 -31
  40. package/esm2020/utils/abstract/resize.mjs +3 -2
  41. package/esm2020/utils/clipboard.mjs +16 -18
  42. package/esm2020/utils/dnd/common.mjs +35 -0
  43. package/esm2020/utils/dnd/detector.mjs +268 -0
  44. package/esm2020/utils/dnd/draw.mjs +161 -0
  45. package/esm2020/utils/index.mjs +6 -6
  46. package/esm2020/utils/mind.mjs +6 -129
  47. package/esm2020/utils/node/adjust-node.mjs +49 -0
  48. package/esm2020/utils/node/common.mjs +6 -0
  49. package/esm2020/utils/node/create-node.mjs +61 -0
  50. package/esm2020/utils/node/index.mjs +4 -0
  51. package/esm2020/utils/point-placement.mjs +22 -2
  52. package/esm2020/utils/position/emoji.mjs +31 -0
  53. package/esm2020/utils/position/index.mjs +4 -0
  54. package/esm2020/utils/position/node.mjs +34 -0
  55. package/esm2020/utils/position/topic.mjs +14 -0
  56. package/esm2020/utils/space/emoji.mjs +19 -0
  57. package/esm2020/utils/space/layout-options.mjs +72 -0
  58. package/esm2020/utils/space/node-space.mjs +77 -0
  59. package/fesm2015/plait-mind.mjs +1464 -1631
  60. package/fesm2015/plait-mind.mjs.map +1 -1
  61. package/fesm2020/plait-mind.mjs +1486 -1642
  62. package/fesm2020/plait-mind.mjs.map +1 -1
  63. package/interfaces/index.d.ts +1 -1
  64. package/interfaces/pointer.d.ts +3 -0
  65. package/mind.module.d.ts +2 -2
  66. package/node.component.d.ts +3 -3
  67. package/package.json +3 -3
  68. package/{interfaces/abstract.d.ts → plugins/with-abstract-resize.board.d.ts} +2 -2
  69. package/plugins/with-mind-create.d.ts +11 -0
  70. package/plugins/with-mind-extend.d.ts +3 -0
  71. package/plugins/{with-extend-mind.d.ts → with-mind.board.d.ts} +4 -4
  72. package/plugins/with-mind.d.ts +1 -1
  73. package/public-api.d.ts +4 -2
  74. package/styles/styles.scss +5 -2
  75. package/transforms/abstract-node.d.ts +1 -1
  76. package/transforms/emoji.d.ts +6 -0
  77. package/transforms/index.d.ts +3 -0
  78. package/transforms/node.d.ts +5 -5
  79. package/utils/abstract/common.d.ts +19 -4
  80. package/utils/abstract/resize.d.ts +2 -1
  81. package/utils/dnd/common.d.ts +7 -0
  82. package/utils/dnd/detector.d.ts +31 -0
  83. package/utils/dnd/draw.d.ts +9 -0
  84. package/utils/index.d.ts +5 -5
  85. package/utils/mind.d.ts +3 -22
  86. package/utils/node/adjust-node.d.ts +5 -0
  87. package/utils/{node.d.ts → node/common.d.ts} +1 -1
  88. package/utils/node/create-node.d.ts +14 -0
  89. package/utils/node/index.d.ts +3 -0
  90. package/utils/point-placement.d.ts +8 -1
  91. package/utils/position/emoji.d.ts +7 -0
  92. package/utils/position/index.d.ts +3 -0
  93. package/utils/position/node.d.ts +12 -0
  94. package/utils/position/topic.d.ts +16 -0
  95. package/utils/space/emoji.d.ts +7 -0
  96. package/{layout-option.d.ts → utils/space/layout-options.d.ts} +1 -1
  97. package/utils/{node-space.d.ts → space/node-space.d.ts} +4 -4
  98. package/draw/link.d.ts +0 -3
  99. package/draw/richtext.d.ts +0 -15
  100. package/draw/shape.d.ts +0 -3
  101. package/esm2020/draw/link.mjs +0 -160
  102. package/esm2020/draw/richtext.mjs +0 -39
  103. package/esm2020/draw/shape.mjs +0 -18
  104. package/esm2020/drawer/base/base.mjs +0 -17
  105. package/esm2020/interfaces/abstract.mjs +0 -12
  106. package/esm2020/layout-option.mjs +0 -72
  107. package/esm2020/plugins/emoji/emoji-base.component.mjs +0 -33
  108. package/esm2020/plugins/emoji/emoji.drawer.mjs +0 -72
  109. package/esm2020/plugins/emoji/emoji.mjs +0 -47
  110. package/esm2020/plugins/emoji/index.mjs +0 -3
  111. package/esm2020/plugins/with-abstract.mjs +0 -106
  112. package/esm2020/plugins/with-dnd.mjs +0 -179
  113. package/esm2020/plugins/with-extend-mind.mjs +0 -11
  114. package/esm2020/utils/direction-corrector.mjs +0 -54
  115. package/esm2020/utils/direction-detector.mjs +0 -56
  116. package/esm2020/utils/dnd.mjs +0 -122
  117. package/esm2020/utils/draw-placeholder.mjs +0 -313
  118. package/esm2020/utils/drop-target-corrector.mjs +0 -87
  119. package/esm2020/utils/graph.mjs +0 -24
  120. package/esm2020/utils/node-space.mjs +0 -77
  121. package/esm2020/utils/node.mjs +0 -6
  122. package/plugins/emoji/emoji.d.ts +0 -11
  123. package/utils/direction-corrector.d.ts +0 -4
  124. package/utils/direction-detector.d.ts +0 -9
  125. package/utils/dnd.d.ts +0 -16
  126. package/utils/draw-placeholder.d.ts +0 -42
  127. package/utils/drop-target-corrector.d.ts +0 -9
  128. package/utils/graph.d.ts +0 -5
  129. /package/plugins/{with-abstract.d.ts → with-abstract-resize.d.ts} +0 -0
  130. /package/plugins/{with-dnd.d.ts → with-node-dnd.d.ts} +0 -0
@@ -1,16 +1,16 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Component, ChangeDetectionStrategy, NgModule, Directive, Input } from '@angular/core';
3
3
  import * as i2 from '@plait/core';
4
- import { distanceBetweenPointAndRectangle, PlaitBoard, PlaitNode, NODE_TO_PARENT, Path, ELEMENT_TO_COMPONENT, PlaitElement, Transforms, idCreator, isNullOrUndefined, clearSelectedElement, addSelectedElement, drawRoundRectangle, getRectangleByElements, RectangleClient, getSelectedElements, createG, drawAbstractRoundRectangle, PlaitPluginElementComponent, PlaitPointerType, NODE_TO_INDEX, createText, IS_TEXT_EDITABLE, MERGING, transformPoint, toPoint, depthFirstRecursion, PlaitModule, distanceBetweenPointAndPoint, updateForeignObject as updateForeignObject$1, CLIP_BOARD_FORMAT_KEY, BOARD_TO_HOST, Selection, removeSelectedElement, PlaitHistoryBoard, hotkeys } from '@plait/core';
5
- import { MindLayoutType, AbstractNode, getAbstractLayout, isIndentedLayout, isStandardLayout, isHorizontalLogicLayout, isVerticalLogicLayout, isTopLayout, isLeftLayout, isBottomLayout, isRightLayout, isHorizontalLayout, getNonAbstractChildren, getCorrectStartEnd, ConnectingPosition, GlobalLayout } from '@plait/layouts';
6
- import { getSizeByText, ROOT_DEFAULT_HEIGHT, TEXT_DEFAULT_HEIGHT, drawRichtext, updateForeignObject, createForeignObject, updateRichText, setFullSelectionAndFocus, getRichtextContentSize, hasEditableTarget, RichtextModule } from '@plait/richtext';
4
+ import { PlaitBoard, PlaitNode, NODE_TO_PARENT, Path, distanceBetweenPointAndRectangle, RectangleClient, PlaitElement, idCreator, isNullOrUndefined, Transforms, clearSelectedElement, addSelectedElement, 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';
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
10
  import { pointsOnBezierCurves } from 'points-on-curve';
11
11
  import { isKeyHotkey } from 'is-hotkey';
12
12
  import * as i1 from '@angular/common';
13
- import { BrowserModule } from '@angular/platform-browser';
13
+ import { CommonModule } from '@angular/common';
14
14
 
15
15
  const ELEMENT_TO_NODE = new WeakMap();
16
16
 
@@ -56,27 +56,42 @@ const ABSTRACT_INCLUDED_OUTLINE_OFFSET = 3.5;
56
56
  const ABSTRACT_HANDLE_LENGTH = 10;
57
57
  const ABSTRACT_HANDLE_MASK_WIDTH = 8;
58
58
 
59
- function getRectangleByNode(node) {
60
- const x = node.x + node.hGap;
61
- let y = node.y + node.vGap;
62
- const width = node.width - node.hGap * 2;
63
- const height = node.height - node.vGap * 2;
64
- return {
65
- x,
66
- y,
67
- width,
68
- height
69
- };
70
- }
71
- function hitMindElement(board, point, element) {
72
- const node = ELEMENT_TO_NODE.get(element);
73
- if (node && distanceBetweenPointAndRectangle(point[0], point[1], getRectangleByNode(node)) === 0) {
74
- return true;
75
- }
76
- else {
77
- return false;
59
+ const MindNode = {
60
+ get(root, path) {
61
+ let node = root;
62
+ for (let i = 0; i < path.length; i++) {
63
+ const p = path[i];
64
+ if (!node || !node.children || !node.children[p]) {
65
+ throw new Error(`Cannot find a descendant at path [${path}]`);
66
+ }
67
+ node = node.children[p];
68
+ }
69
+ return node;
78
70
  }
79
- }
71
+ };
72
+
73
+ var LayoutDirection;
74
+ (function (LayoutDirection) {
75
+ LayoutDirection["top"] = "top";
76
+ LayoutDirection["right"] = "right";
77
+ LayoutDirection["bottom"] = "bottom";
78
+ LayoutDirection["left"] = "left";
79
+ })(LayoutDirection || (LayoutDirection = {}));
80
+ const LayoutDirectionsMap = {
81
+ [MindLayoutType.right]: [LayoutDirection.right],
82
+ [MindLayoutType.left]: [LayoutDirection.left],
83
+ [MindLayoutType.upward]: [LayoutDirection.top],
84
+ [MindLayoutType.downward]: [LayoutDirection.bottom],
85
+ [MindLayoutType.rightBottomIndented]: [LayoutDirection.right, LayoutDirection.bottom],
86
+ [MindLayoutType.rightTopIndented]: [LayoutDirection.right, LayoutDirection.top],
87
+ [MindLayoutType.leftBottomIndented]: [LayoutDirection.left, LayoutDirection.bottom],
88
+ [MindLayoutType.leftTopIndented]: [LayoutDirection.left, LayoutDirection.top]
89
+ };
90
+
91
+ var MindPointerType;
92
+ (function (MindPointerType) {
93
+ MindPointerType["mind"] = "mind";
94
+ })(MindPointerType || (MindPointerType = {}));
80
95
 
81
96
  /**
82
97
  * get correctly layout:
@@ -368,398 +383,172 @@ var MindElementShape;
368
383
  MindElementShape["underline"] = "underline";
369
384
  })(MindElementShape || (MindElementShape = {}));
370
385
 
371
- const MindNode = {
372
- get(root, path) {
373
- let node = root;
374
- for (let i = 0; i < path.length; i++) {
375
- const p = path[i];
376
- if (!node || !node.children || !node.children[p]) {
377
- throw new Error(`Cannot find a descendant at path [${path}]`);
378
- }
379
- node = node.children[p];
380
- }
381
- return node;
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;
382
401
  }
383
- };
384
-
385
- var LayoutDirection;
386
- (function (LayoutDirection) {
387
- LayoutDirection["top"] = "top";
388
- LayoutDirection["right"] = "right";
389
- LayoutDirection["bottom"] = "bottom";
390
- LayoutDirection["left"] = "left";
391
- })(LayoutDirection || (LayoutDirection = {}));
392
- const LayoutDirectionsMap = {
393
- [MindLayoutType.right]: [LayoutDirection.right],
394
- [MindLayoutType.left]: [LayoutDirection.left],
395
- [MindLayoutType.upward]: [LayoutDirection.top],
396
- [MindLayoutType.downward]: [LayoutDirection.bottom],
397
- [MindLayoutType.rightBottomIndented]: [LayoutDirection.right, LayoutDirection.bottom],
398
- [MindLayoutType.rightTopIndented]: [LayoutDirection.right, LayoutDirection.top],
399
- [MindLayoutType.leftBottomIndented]: [LayoutDirection.left, LayoutDirection.bottom],
400
- [MindLayoutType.leftTopIndented]: [LayoutDirection.left, LayoutDirection.top]
401
- };
402
-
403
- var AbstractHandlePosition;
404
- (function (AbstractHandlePosition) {
405
- AbstractHandlePosition["start"] = "start";
406
- AbstractHandlePosition["end"] = "end";
407
- })(AbstractHandlePosition || (AbstractHandlePosition = {}));
408
- var AbstractResizeState;
409
- (function (AbstractResizeState) {
410
- AbstractResizeState["start"] = "start";
411
- AbstractResizeState["resizing"] = "resizing";
412
- AbstractResizeState["end"] = "end";
413
- })(AbstractResizeState || (AbstractResizeState = {}));
414
-
415
- function enterNodeEditing(element) {
416
- const component = ELEMENT_TO_COMPONENT.get(element);
417
- component.startEditText(false, false);
418
402
  }
419
403
 
420
- const separateChildren = (parentElement) => {
421
- const rightNodeCount = parentElement.rightNodeCount;
422
- const children = parentElement.children;
423
- let rightChildren = [], leftChildren = [];
424
- for (let i = 0; i < children.length; i++) {
425
- const child = children[i];
426
- if (AbstractNode.isAbstract(child) && child.end < rightNodeCount) {
427
- rightChildren.push(child);
428
- continue;
429
- }
430
- if (AbstractNode.isAbstract(child) && child.start >= rightNodeCount) {
431
- leftChildren.push(child);
432
- continue;
433
- }
434
- if (i < rightNodeCount) {
435
- rightChildren.push(child);
436
- }
437
- else {
438
- leftChildren.push(child);
439
- }
404
+ const NodeDefaultSpace = {
405
+ horizontal: {
406
+ nodeAndText: BASE * 3,
407
+ emojiAndText: BASE * 1.5
408
+ },
409
+ vertical: {
410
+ nodeAndText: BASE * 1.5
440
411
  }
441
- return { leftChildren, rightChildren };
442
412
  };
443
- const isSetAbstract = (element) => {
444
- const parent = MindElement.getParent(element);
445
- return !!getCorrespondingAbstract(parent, element);
413
+ const RootDefaultSpace = {
414
+ horizontal: {
415
+ nodeAndText: BASE * 4,
416
+ emojiAndText: BASE * 2
417
+ },
418
+ vertical: {
419
+ nodeAndText: BASE * 2
420
+ }
446
421
  };
447
- const canSetAbstract = (element) => {
448
- return !PlaitElement.isRootElement(element) && !AbstractNode.isAbstract(element) && !isSetAbstract(element);
422
+ const getHorizontalSpaceBetweenNodeAndText = (board, element) => {
423
+ const isMind = PlaitMind.isMind(element);
424
+ const nodeAndText = isMind ? RootDefaultSpace.horizontal.nodeAndText : NodeDefaultSpace.horizontal.nodeAndText;
425
+ return nodeAndText;
449
426
  };
450
- const getCorrespondingAbstract = (parent, element) => {
451
- if (!parent)
452
- return undefined;
453
- const elementIndex = parent.children.indexOf(element);
454
- return parent.children.find(child => {
455
- return AbstractNode.isAbstract(child) && elementIndex >= child.start && elementIndex <= child.end;
456
- });
427
+ const getVerticalSpaceBetweenNodeAndText = (element) => {
428
+ const isMind = PlaitMind.isMind(element);
429
+ const nodeAndText = isMind ? RootDefaultSpace.vertical.nodeAndText : NodeDefaultSpace.vertical.nodeAndText;
430
+ return nodeAndText;
457
431
  };
458
- const getBehindAbstracts = (parent, element) => {
459
- const index = parent.children.indexOf(element);
460
- return parent.children.filter(child => AbstractNode.isAbstract(child) && child.start > index);
432
+ const getSpaceEmojiAndText = (element) => {
433
+ const isMind = PlaitMind.isMind(element);
434
+ const emojiAndText = isMind ? RootDefaultSpace.horizontal.emojiAndText : NodeDefaultSpace.horizontal.emojiAndText;
435
+ return emojiAndText;
461
436
  };
462
- const getOverallAbstracts = (board, elements) => {
463
- const overallAbstracts = [];
464
- elements
465
- .filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
466
- .forEach(value => {
467
- const parent = MindElement.getParent(value);
468
- const abstract = getCorrespondingAbstract(parent, value);
469
- if (abstract && overallAbstracts.indexOf(abstract) === -1) {
470
- const { start, end } = abstract;
471
- const parent = MindElement.getParent(value);
472
- const isOverall = parent.children.slice(start, end + 1).every(includedElement => elements.indexOf(includedElement) > -1);
473
- if (isOverall) {
474
- overallAbstracts.push(abstract);
475
- }
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);
476
446
  }
477
- });
478
- return overallAbstracts;
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
+ }
479
475
  };
480
- const insertElementHandleAbstract = (board, path,
481
- //由此区分拖拽和新增到概要概括最后一个节点
482
- isExtendPreviousNode = true, abstractRefs = new Map()) => {
483
- const parent = PlaitNode.parent(board, path);
484
- const hasPreviousNode = path[path.length - 1] !== 0;
485
- let behindAbstracts;
486
- if (!hasPreviousNode) {
487
- behindAbstracts = parent.children.filter(child => AbstractNode.isAbstract(child));
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;
488
502
  }
489
503
  else {
490
- const selectedElement = PlaitNode.get(board, Path.previous(path));
491
- behindAbstracts = getBehindAbstracts(parent, selectedElement);
492
- }
493
- if (behindAbstracts.length) {
494
- behindAbstracts.forEach(abstract => {
495
- let newProperties = abstractRefs.get(abstract);
496
- if (!newProperties) {
497
- newProperties = { start: 0, end: 0 };
498
- abstractRefs.set(abstract, newProperties);
499
- }
500
- newProperties.start = newProperties.start + 1;
501
- newProperties.end = newProperties.end + 1;
502
- });
503
- }
504
- if (!hasPreviousNode) {
505
- return abstractRefs;
504
+ return false;
506
505
  }
507
- const selectedElement = PlaitNode.get(board, Path.previous(path));
508
- const correspondingAbstract = getCorrespondingAbstract(parent, selectedElement);
509
- const isDragToLast = !isExtendPreviousNode && correspondingAbstract && correspondingAbstract.end === path[path.length - 1] - 1;
510
- if (correspondingAbstract && !isDragToLast) {
511
- let newProperties = abstractRefs.get(correspondingAbstract);
512
- if (!newProperties) {
513
- newProperties = { start: 0, end: 0 };
514
- abstractRefs.set(correspondingAbstract, newProperties);
515
- }
516
- newProperties.end = newProperties.end + 1;
517
- }
518
- return abstractRefs;
519
- };
520
- const deleteElementHandleAbstract = (board, deletableElements, abstractRefs = new Map()) => {
521
- deletableElements.forEach(node => {
522
- if (!PlaitMind.isMind(node)) {
523
- const parent = PlaitNode.parent(board, PlaitBoard.findPath(board, node));
524
- const behindAbstracts = getBehindAbstracts(parent, node).filter(abstract => !deletableElements.includes(abstract));
525
- if (behindAbstracts.length) {
526
- behindAbstracts.forEach(abstract => {
527
- let newProperties = abstractRefs.get(abstract);
528
- if (!newProperties) {
529
- newProperties = { start: 0, end: 0 };
530
- abstractRefs.set(abstract, newProperties);
531
- }
532
- newProperties.start = newProperties.start - 1;
533
- newProperties.end = newProperties.end - 1;
534
- });
535
- }
536
- const correspondingAbstract = getCorrespondingAbstract(parent, node);
537
- if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
538
- let newProperties = abstractRefs.get(correspondingAbstract);
539
- if (!newProperties) {
540
- newProperties = { start: 0, end: 0 };
541
- abstractRefs.set(correspondingAbstract, newProperties);
542
- }
543
- newProperties.end = newProperties.end - 1;
544
- }
545
- }
546
- });
547
- return abstractRefs;
548
- };
549
-
550
- const setAbstractsByRefs = (board, abstractRefs) => {
551
- abstractRefs.forEach((newProperty, element) => {
552
- const start = element.start + newProperty.start;
553
- const end = element.end + newProperty.end;
554
- const path = PlaitBoard.findPath(board, element);
555
- if (start > end) {
556
- Transforms.removeNode(board, path);
557
- }
558
- else {
559
- Transforms.setNode(board, { start, end }, path);
560
- }
561
- });
562
- };
563
- const setAbstractByStandardLayout = (board, element) => {
564
- const rightNodeCount = element.rightNodeCount;
565
- const abstract = element.children.find(child => {
566
- return AbstractNode.isAbstract(child) && child.end >= rightNodeCount && child.start < rightNodeCount;
567
- });
568
- if (abstract) {
569
- const path = PlaitBoard.findPath(board, abstract);
570
- Transforms.setNode(board, { end: rightNodeCount - 1 }, path);
571
- }
572
- };
573
- const insertAbstract = (board, elements) => {
574
- let elementGroup = getFirstLevelElement(elements);
575
- const { parentElements, abstractIncludedGroups } = divideElementByParent(elementGroup);
576
- abstractIncludedGroups.forEach((group, index) => {
577
- const groupParent = parentElements[index];
578
- setAbstractByElements(board, groupParent, group);
579
- });
580
- };
581
- const setAbstractByElements = (board, groupParent, group) => {
582
- const indexArray = group.map(child => groupParent.children.indexOf(child)).sort((a, b) => a - b);
583
- const rightNodeCount = groupParent === null || groupParent === void 0 ? void 0 : groupParent.rightNodeCount;
584
- const start = indexArray[0], end = indexArray[indexArray.length - 1];
585
- if (isStandardLayout(MindQueries.getLayoutByElement(groupParent)) &&
586
- rightNodeCount &&
587
- start < rightNodeCount &&
588
- end >= rightNodeCount) {
589
- const childrenLength = groupParent.children.length;
590
- const path = [...PlaitBoard.findPath(board, groupParent), childrenLength];
591
- const leftChildren = indexArray.filter(index => index >= rightNodeCount);
592
- const rightChildren = indexArray.filter(index => index < rightNodeCount);
593
- insertAbstractNode(board, path, rightChildren[0], rightChildren[rightChildren.length - 1]);
594
- insertAbstractNode(board, Path.next(path), leftChildren[0], leftChildren[leftChildren.length - 1]);
595
- }
596
- else {
597
- const path = [...PlaitBoard.findPath(board, groupParent), groupParent.children.length];
598
- insertAbstractNode(board, path, start, end);
599
- }
600
- };
601
- const insertAbstractNode = (board, path, start, end) => {
602
- const mindElement = createMindElement('概要', 28, 20, {
603
- strokeColor: DefaultAbstractNodeStyle.strokeColor,
604
- strokeWidth: DefaultAbstractNodeStyle.branchWidth,
605
- branchColor: DefaultAbstractNodeStyle.branchColor,
606
- branchWidth: DefaultAbstractNodeStyle.branchWidth
607
- });
608
- mindElement.start = start;
609
- mindElement.end = end;
610
- Transforms.insertNode(board, mindElement, path);
611
- };
612
-
613
- const setLayout = (board, layout, path) => {
614
- correctLogicLayoutNode(board, layout, path);
615
- const element = PlaitNode.get(board, path);
616
- if (PlaitMind.isMind(element) && isStandardLayout(layout)) {
617
- MindTransforms.setAbstractByStandardLayout(board, element);
618
- }
619
- Transforms.setNode(board, { layout }, path);
620
- };
621
- const correctLogicLayoutNode = (board, layout, path) => {
622
- var _a;
623
- const node = PlaitNode.get(board, path);
624
- if (node && layout) {
625
- (_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach((value, index) => {
626
- var _a;
627
- if (value.layout) {
628
- if ((isHorizontalLogicLayout(layout) && isVerticalLogicLayout(value.layout)) ||
629
- (isVerticalLogicLayout(layout) && isHorizontalLogicLayout(value.layout))) {
630
- Transforms.setNode(board, { layout: null }, [...path, index]);
631
- }
632
- if ((_a = value.children) === null || _a === void 0 ? void 0 : _a.length) {
633
- correctLogicLayoutNode(board, layout, [...path, index]);
634
- }
635
- }
636
- });
637
- }
638
- };
506
+ }
639
507
 
640
- const setTopic = (board, element, topic, width, height) => {
641
- const newElement = {
642
- data: { topic },
643
- width: width < NODE_MIN_WIDTH * board.viewport.zoom ? NODE_MIN_WIDTH : width / board.viewport.zoom,
644
- height: height / board.viewport.zoom
645
- };
646
- if (MindElement.hasEmojis(element)) {
647
- newElement.data.emojis = element.data.emojis;
648
- }
649
- const path = PlaitBoard.findPath(board, element);
650
- Transforms.setNode(board, newElement, path);
651
- };
652
- const setTopicSize = (board, element, width, height) => {
653
- const newElement = {
654
- width: width < NODE_MIN_WIDTH * board.viewport.zoom ? NODE_MIN_WIDTH : width / board.viewport.zoom,
655
- height: height / board.viewport.zoom
656
- };
657
- const path = PlaitBoard.findPath(board, element);
658
- Transforms.setNode(board, newElement, path);
659
- };
660
- const addEmoji = (board, element, emojiItem) => {
661
- const emojis = element.data.emojis || [];
662
- const newEmojis = [...emojis];
663
- newEmojis.push(emojiItem);
664
- const newElement = {
665
- data: { topic: element.data.topic, emojis: newEmojis }
666
- };
667
- const path = PlaitBoard.findPath(board, element);
668
- Transforms.setNode(board, newElement, path);
669
- };
670
- const removeEmoji = (board, element, emojiItem) => {
671
- const emojis = element.data.emojis.filter(value => value !== emojiItem);
672
- const newElement = {
673
- data: { topic: element.data.topic }
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
674
517
  };
675
- if (emojis.length > 0) {
676
- newElement.data.emojis = emojis;
677
- }
678
- const path = PlaitBoard.findPath(board, element);
679
- Transforms.setNode(board, newElement, path);
680
- };
681
- const replaceEmoji = (board, element, oldEmoji, newEmoji) => {
682
- const newElement = {
683
- data: { topic: element.data.topic }
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
684
528
  };
685
- const newEmojis = element.data.emojis.map(value => {
686
- if (value === oldEmoji) {
687
- return newEmoji;
688
- }
689
- return value;
690
- });
691
- newElement.data.emojis = newEmojis;
692
- const path = PlaitBoard.findPath(board, element);
693
- Transforms.setNode(board, newElement, path);
529
+ }
530
+ const isHitEmojis = (board, element, point) => {
531
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), getEmojiRectangle(board, element));
694
532
  };
695
533
 
696
- const MindTransforms = {
697
- setLayout,
698
- setTopic,
699
- setTopicSize,
700
- addEmoji,
701
- removeEmoji,
702
- replaceEmoji,
703
- insertAbstract,
704
- setAbstractsByRefs,
705
- setAbstractByStandardLayout
706
- };
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
+ }
707
545
 
708
- function findUpElement(element) {
709
- let branch;
710
- let root = element;
711
- let parent = MindElement.findParent(element);
712
- while (parent) {
713
- branch = root;
714
- root = parent;
715
- parent = MindElement.findParent(parent);
716
- }
717
- return { root, branch };
546
+ function enterNodeEditing(element) {
547
+ const component = PlaitElement.getComponent(element);
548
+ component.startEditText(false, false);
718
549
  }
719
- const getChildrenCount = (element) => {
720
- const count = element.children.reduce((p, c) => {
721
- return p + getChildrenCount(c);
722
- }, 0);
723
- return count + element.children.length;
724
- };
725
- const isChildElement = (origin, child) => {
726
- let parent = MindElement.findParent(child);
727
- while (parent) {
728
- if (parent === origin) {
729
- return true;
730
- }
731
- parent = MindElement.findParent(parent);
732
- }
733
- return false;
734
- };
735
- const getFirstLevelElement = (elements) => {
736
- let result = [];
737
- elements.forEach(element => {
738
- const isChild = elements.some(node => {
739
- return isChildElement(node, element);
740
- });
741
- if (!isChild) {
742
- result.push(element);
743
- }
744
- });
745
- return result;
746
- };
747
- const isChildRight = (node, child) => {
748
- return node.x < child.x;
749
- };
750
- const isChildUp = (node, child) => {
751
- return node.y > child.y;
752
- };
753
- const copyNewNode = (node) => {
754
- const newNode = Object.assign({}, node);
755
- newNode.id = idCreator();
756
- newNode.children = [];
757
- for (const childNode of node.children) {
758
- newNode.children.push(copyNewNode(childNode));
759
- }
760
- return newNode;
761
- };
762
- const transformRootToNode = (board, node) => {
550
+
551
+ const adjustRootToNode = (board, node) => {
763
552
  const newNode = Object.assign({}, node);
764
553
  delete newNode.isRoot;
765
554
  delete newNode.rightNodeCount;
@@ -773,13 +562,13 @@ const transformRootToNode = (board, node) => {
773
562
  }
774
563
  return newNode;
775
564
  };
776
- const transformAbstractToNode = (node) => {
565
+ const adjustAbstractToNode = (node) => {
777
566
  const newNode = Object.assign({}, node);
778
567
  delete newNode.start;
779
568
  delete newNode.end;
780
569
  return newNode;
781
570
  };
782
- const transformNodeToRoot = (board, node) => {
571
+ const adjustNodeToRoot = (board, node) => {
783
572
  var _a;
784
573
  const newElement = Object.assign({}, node);
785
574
  let text = Node.string(newElement.data.topic);
@@ -796,40 +585,14 @@ const transformNodeToRoot = (board, node) => {
796
585
  newElement.height = height;
797
586
  return Object.assign(Object.assign({}, newElement), { layout: (_a = newElement.layout) !== null && _a !== void 0 ? _a : MindLayoutType.right, isCollapsed: false, isRoot: true, type: 'mindmap' });
798
587
  };
799
- const extractNodesText = (node) => {
800
- let str = '';
801
- if (node) {
802
- str += Node.string(node.data.topic.children[0]) + ' ';
803
- for (const childNode of node.children) {
804
- str += extractNodesText(childNode);
805
- }
806
- }
807
- return str;
808
- };
809
- const changeRightNodeCount = (board, parentPath, changeNumber) => {
810
- const _rightNodeCount = board.children[parentPath[0]].rightNodeCount;
811
- Transforms.setNode(board, {
812
- rightNodeCount: changeNumber >= 0
813
- ? _rightNodeCount + changeNumber
814
- : _rightNodeCount + changeNumber < 0
815
- ? 0
816
- : _rightNodeCount + changeNumber
817
- }, parentPath);
818
- };
819
- const shouldChangeRightNodeCount = (selectedElement) => {
820
- const parentElement = MindElement.findParent(selectedElement);
821
- if (parentElement) {
822
- const nodeIndex = parentElement.children.findIndex(item => item.id === selectedElement.id);
823
- if (parentElement.isRoot &&
824
- getRootLayout(parentElement) === MindLayoutType.standard &&
825
- parentElement.rightNodeCount &&
826
- nodeIndex <= parentElement.rightNodeCount - 1) {
827
- return true;
828
- }
829
- }
830
- return false;
588
+
589
+ const createEmptyMind = (board, point) => {
590
+ const element = createMindElement('', 0, 0, { layout: MindLayoutType.right });
591
+ const rootElement = adjustNodeToRoot(board, element);
592
+ rootElement.points = [point];
593
+ return rootElement;
831
594
  };
832
- const createDefaultMindMapElement = (point, rightNodeCount, layout) => {
595
+ const createDefaultMind = (point, rightNodeCount, layout) => {
833
596
  const root = createMindElement('思维导图', 72, ROOT_DEFAULT_HEIGHT, { shape: MindElementShape.roundRectangle, layout });
834
597
  root.rightNodeCount = rightNodeCount;
835
598
  root.isRoot = true;
@@ -878,6 +641,83 @@ const createMindElement = (text, width, height, options) => {
878
641
  }
879
642
  return newElement;
880
643
  };
644
+
645
+ const getChildrenCount = (element) => {
646
+ const count = element.children.reduce((p, c) => {
647
+ return p + getChildrenCount(c);
648
+ }, 0);
649
+ return count + element.children.length;
650
+ };
651
+ const isChildElement = (origin, child) => {
652
+ let parent = MindElement.findParent(child);
653
+ while (parent) {
654
+ if (parent === origin) {
655
+ return true;
656
+ }
657
+ parent = MindElement.findParent(parent);
658
+ }
659
+ return false;
660
+ };
661
+ const getFirstLevelElement = (elements) => {
662
+ let result = [];
663
+ elements.forEach(element => {
664
+ const isChild = elements.some(node => {
665
+ return isChildElement(node, element);
666
+ });
667
+ if (!isChild) {
668
+ result.push(element);
669
+ }
670
+ });
671
+ return result;
672
+ };
673
+ const isChildRight = (node, child) => {
674
+ return node.x < child.x;
675
+ };
676
+ const isChildUp = (node, child) => {
677
+ return node.y > child.y;
678
+ };
679
+ const copyNewNode = (node) => {
680
+ const newNode = Object.assign({}, node);
681
+ newNode.id = idCreator();
682
+ newNode.children = [];
683
+ for (const childNode of node.children) {
684
+ newNode.children.push(copyNewNode(childNode));
685
+ }
686
+ return newNode;
687
+ };
688
+ const extractNodesText = (node) => {
689
+ let str = '';
690
+ if (node) {
691
+ str += Node.string(node.data.topic.children[0]) + ' ';
692
+ for (const childNode of node.children) {
693
+ str += extractNodesText(childNode);
694
+ }
695
+ }
696
+ return str;
697
+ };
698
+ const changeRightNodeCount = (board, parentPath, changeNumber) => {
699
+ const _rightNodeCount = board.children[parentPath[0]].rightNodeCount;
700
+ Transforms.setNode(board, {
701
+ rightNodeCount: changeNumber >= 0
702
+ ? _rightNodeCount + changeNumber
703
+ : _rightNodeCount + changeNumber < 0
704
+ ? 0
705
+ : _rightNodeCount + changeNumber
706
+ }, parentPath);
707
+ };
708
+ const isInRightBranchOfStandardLayout = (selectedElement) => {
709
+ const parentElement = MindElement.findParent(selectedElement);
710
+ if (parentElement) {
711
+ const nodeIndex = parentElement.children.findIndex(item => item.id === selectedElement.id);
712
+ if (parentElement.isRoot &&
713
+ getRootLayout(parentElement) === MindLayoutType.standard &&
714
+ parentElement.rightNodeCount &&
715
+ nodeIndex <= parentElement.rightNodeCount - 1) {
716
+ return true;
717
+ }
718
+ }
719
+ return false;
720
+ };
881
721
  // layoutLevel 用来表示插入兄弟节点还是子节点
882
722
  const insertMindElement = (board, inheritNode, path) => {
883
723
  let fill, strokeColor, strokeWidth, shape = MindElementShape.roundRectangle;
@@ -902,25 +742,6 @@ const findLastChild = (child) => {
902
742
  }
903
743
  return result;
904
744
  };
905
- const deleteSelectedELements = (board, selectedElements) => {
906
- const deletableElements = getFirstLevelElement(selectedElements).reverse();
907
- const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
908
- MindTransforms.setAbstractsByRefs(board, abstractRefs);
909
- //翻转,从下到上修改,防止找不到 path
910
- deletableElements
911
- .map(element => {
912
- const path = PlaitBoard.findPath(board, element);
913
- return () => {
914
- if (shouldChangeRightNodeCount(element)) {
915
- changeRightNodeCount(board, path.slice(0, 1), -1);
916
- }
917
- Transforms.removeNode(board, path);
918
- };
919
- })
920
- .forEach(action => {
921
- action();
922
- });
923
- };
924
745
  const divideElementByParent = (elements) => {
925
746
  const abstractIncludedGroups = [];
926
747
  const parentElements = [];
@@ -1016,467 +837,123 @@ function isVirtualKey(e) {
1016
837
  return isCapsLock || isMod || isAlt || isArrow || isShift || isTab || isEsc || isF;
1017
838
  }
1018
839
 
1019
- function drawLink(board, node, child, defaultStroke = null, isHorizontal = true, needDrawUnderline = true) {
1020
- var _a;
1021
- let beginX, beginY, endX, endY, beginNode = node, endNode = child;
1022
- const layout = MindQueries.getCorrectLayoutByElement(board, node.origin);
1023
- if (isHorizontal) {
1024
- if (!isChildRight(node, child)) {
1025
- beginNode = child;
1026
- endNode = node;
1027
- }
1028
- beginX = beginNode.x + beginNode.width - beginNode.hGap;
1029
- beginY = beginNode.y + beginNode.height / 2;
1030
- endX = endNode.x + endNode.hGap;
1031
- endY = endNode.y + endNode.height / 2;
1032
- if (node.parent &&
1033
- isIndentedLayout(MindQueries.getLayoutByElement((_a = node.parent) === null || _a === void 0 ? void 0 : _a.origin)) &&
1034
- getShapeByElement(board, node.origin) === MindElementShape.underline) {
1035
- if (isChildRight(node, child)) {
1036
- beginY = node.y + node.height - node.vGap;
1037
- }
1038
- else {
1039
- endY = node.y + node.height - node.vGap;
1040
- }
1041
- }
840
+ const IS_DRAGGING = new WeakMap();
841
+ const addActiveOnDragOrigin = (activeElement, isOrigin = true) => {
842
+ const activeComponent = PlaitElement.getComponent(activeElement);
843
+ if (isOrigin) {
844
+ activeComponent.g.classList.add('dragging-origin');
1042
845
  }
1043
846
  else {
1044
- if (node.y > child.y) {
1045
- beginNode = child;
1046
- endNode = node;
1047
- }
1048
- beginX = beginNode.x + beginNode.width / 2;
1049
- beginY = beginNode.y + beginNode.height - beginNode.vGap;
1050
- endX = endNode.x + endNode.width / 2;
1051
- endY = endNode.y + endNode.vGap;
847
+ activeComponent.g.classList.add('dragging-child');
848
+ }
849
+ !activeElement.isCollapsed &&
850
+ activeElement.children.forEach(child => {
851
+ addActiveOnDragOrigin(child, false);
852
+ });
853
+ };
854
+ const removeActiveOnDragOrigin = (activeElement, isOrigin = true) => {
855
+ const activeComponent = PlaitElement.getComponent(activeElement);
856
+ if (isOrigin) {
857
+ activeComponent.g.classList.remove('dragging-origin');
858
+ }
859
+ else {
860
+ activeComponent.g.classList.remove('dragging-child');
1052
861
  }
1053
- const stroke = defaultStroke || getBranchColorByMindElement(board, child.origin);
1054
- const strokeWidth = child.origin.branchWidth ? child.origin.branchWidth : STROKE_WIDTH;
1055
- if (endNode.origin.isRoot) {
1056
- if (layout === MindLayoutType.left || isStandardLayout(layout)) {
1057
- endX -= strokeWidth;
862
+ !activeElement.isCollapsed &&
863
+ activeElement.children.forEach(child => {
864
+ removeActiveOnDragOrigin(child, false);
865
+ });
866
+ };
867
+ const isDragging = (board) => {
868
+ return !!IS_DRAGGING.get(board);
869
+ };
870
+ const setIsDragging = (board, state) => {
871
+ IS_DRAGGING.set(board, state);
872
+ };
873
+
874
+ /**
875
+ *
876
+ * @param targetNode
877
+ * @param centerPoint
878
+ * @returns DetectResult[] | null
879
+ */
880
+ const directionCorrector = (board, node, detectResults) => {
881
+ if (!node.origin.isRoot && !AbstractNode.isAbstract(node.origin)) {
882
+ const parentLayout = MindQueries.getCorrectLayoutByElement(board, node === null || node === void 0 ? void 0 : node.parent.origin);
883
+ if (isStandardLayout(parentLayout)) {
884
+ const idx = node.parent.children.findIndex(x => x === node);
885
+ const isLeft = idx >= (node.parent.origin.rightNodeCount || 0);
886
+ return getAllowedDirection(detectResults, [isLeft ? 'right' : 'left']);
1058
887
  }
1059
- if (layout === MindLayoutType.upward) {
1060
- endY -= strokeWidth;
888
+ if (isLeftLayout(parentLayout)) {
889
+ return getAllowedDirection(detectResults, ['right']);
1061
890
  }
1062
- }
1063
- if (beginNode.origin.isRoot) {
1064
- if (layout === MindLayoutType.right || isStandardLayout(layout)) {
1065
- beginX += strokeWidth;
891
+ if (isRightLayout(parentLayout)) {
892
+ return getAllowedDirection(detectResults, ['left']);
1066
893
  }
1067
- if (layout === MindLayoutType.downward) {
1068
- beginY += strokeWidth;
894
+ if (parentLayout === MindLayoutType.upward) {
895
+ return getAllowedDirection(detectResults, ['bottom']);
1069
896
  }
1070
- }
1071
- if (isHorizontal) {
1072
- let curve = [
1073
- [beginX, beginY],
1074
- [beginX + (beginNode.hGap + endNode.hGap) / 3, beginY],
1075
- [endX - (beginNode.hGap + endNode.hGap) / 2, endY],
1076
- [endX, endY]
1077
- ];
1078
- const shape = getShapeByElement(board, child.origin);
1079
- if (!node.origin.isRoot) {
1080
- if (node.x > child.x) {
1081
- curve = [
1082
- [beginX, beginY],
1083
- [beginX + (beginNode.hGap + endNode.hGap) / 3, beginY],
1084
- [endX - (beginNode.hGap + endNode.hGap) / 2, endY],
1085
- [endX - 12, endY]
1086
- ];
1087
- const line = [
1088
- [endX - 12, endY],
1089
- [endX - 12, endY],
1090
- [endX, endY]
1091
- ];
1092
- curve = [...curve, ...line];
1093
- }
1094
- else {
1095
- curve = [
1096
- [beginX + 12, beginY],
1097
- [beginX + (beginNode.hGap + endNode.hGap) / 2, beginY],
1098
- [endX - (beginNode.hGap + endNode.hGap) / 3, endY],
1099
- [endX, endY]
1100
- ];
1101
- const line = [
1102
- [beginX, beginY],
1103
- [beginX + 12, beginY],
1104
- [beginX + 12, beginY]
1105
- ];
1106
- curve = [...line, ...curve];
1107
- }
1108
- }
1109
- if (needDrawUnderline && shape === MindElementShape.underline) {
1110
- if (child.left) {
1111
- const underline = [
1112
- [beginX - (beginNode.width - beginNode.hGap * 2), beginY],
1113
- [beginX - (beginNode.width - beginNode.hGap * 2), beginY],
1114
- [beginX - (beginNode.width - beginNode.hGap * 2), beginY]
1115
- ];
1116
- curve = [...underline, ...curve];
1117
- }
1118
- else {
1119
- const underline = [
1120
- [endX + (endNode.width - endNode.hGap * 2), endY],
1121
- [endX + (endNode.width - endNode.hGap * 2), endY],
1122
- [endX + (endNode.width - endNode.hGap * 2), endY]
1123
- ];
1124
- curve = [...curve, ...underline];
1125
- }
897
+ if (parentLayout === MindLayoutType.downward) {
898
+ return getAllowedDirection(detectResults, ['top']);
1126
899
  }
1127
- const points = pointsOnBezierCurves(curve);
1128
- return PlaitBoard.getRoughSVG(board).curve(points, { stroke, strokeWidth });
1129
900
  }
1130
901
  else {
1131
- let curve = [
1132
- [beginX, beginY],
1133
- [beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
1134
- [endX, endY - (beginNode.vGap + endNode.vGap) / 2],
1135
- [endX, endY]
1136
- ];
1137
- if (!node.origin.isRoot) {
1138
- if (isTopLayout(layout)) {
1139
- curve = [
1140
- [beginX, beginY],
1141
- [beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
1142
- [endX, endY - (beginNode.vGap + endNode.vGap) / 2],
1143
- [endX, endY - 12]
1144
- ];
1145
- const line = [
1146
- [endX, endY - 12],
1147
- [endX, endY - 12],
1148
- [endX, endY]
1149
- ];
1150
- curve = [...curve, ...line];
1151
- }
1152
- else {
1153
- curve = [
1154
- [beginX, beginY + 12],
1155
- [beginX, beginY + (beginNode.vGap + endNode.vGap) / 2],
1156
- [endX, endY - (beginNode.vGap + endNode.vGap) / 2],
1157
- [endX, endY]
1158
- ];
1159
- const line = [
1160
- [beginX, beginY],
1161
- [beginX, beginY + 12],
1162
- [beginX, beginY + 12]
1163
- ];
1164
- curve = [...line, ...curve];
1165
- }
1166
- }
1167
- const points = pointsOnBezierCurves(curve);
1168
- return PlaitBoard.getRoughSVG(board).curve(points, { stroke, strokeWidth });
1169
- }
1170
- }
1171
-
1172
- const drawPlaceholderDropNodeG = (board, dropTarget, fakeDropNodeG) => {
1173
- const targetComponent = PlaitElement.getComponent(dropTarget.target);
1174
- const targetRect = getRectangleByNode(targetComponent.node);
1175
- if (dropTarget.detectResult && ['right', 'left'].includes(dropTarget.detectResult)) {
1176
- drawStraightDropNodeG(board, targetRect, dropTarget.detectResult, targetComponent, fakeDropNodeG);
1177
- }
1178
- const targetParent = MindElement.findParent(targetComponent.element);
1179
- if (targetParent && dropTarget.detectResult && ['top', 'bottom'].includes(dropTarget.detectResult)) {
1180
- const parentComponent = PlaitElement.getComponent(targetParent);
1181
- const targetIndex = parentComponent.node.origin.children.indexOf(targetComponent.node.origin);
1182
- drawCurvePlaceholderDropNodeG(board, targetRect, dropTarget.detectResult, targetIndex, targetComponent, parentComponent, fakeDropNodeG);
1183
- }
1184
- };
1185
- const drawCurvePlaceholderDropNodeG = (board, targetRect, detectResult, targetIndex, targetComponent, parentComponent, fakeDropNodeG) => {
1186
- const parentNodeLayout = MindQueries.getCorrectLayoutByElement(board, parentComponent.node.origin);
1187
- const layout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.parent.origin);
1188
- const strokeWidth = targetComponent.node.origin.branchWidth ? targetComponent.node.origin.branchWidth : STROKE_WIDTH;
1189
- let fakeX = targetComponent.node.x, fakeY = targetRect.y - 30, fakeRectangleStartX = targetRect.x, fakeRectangleEndX = targetRect.x + 30, fakeRectangleStartY = fakeY, fakeRectangleEndY = fakeRectangleStartY + 12, width = 30;
1190
- if (isLeftLayout(layout)) {
1191
- fakeX = targetComponent.node.x + targetComponent.node.width - 30;
1192
- fakeRectangleStartX = targetRect.x + targetRect.width - 30;
1193
- fakeRectangleEndX = targetRect.x + targetRect.width;
1194
- }
1195
- if (isHorizontalLogicLayout(parentNodeLayout)) {
1196
- fakeY = getHorizontalFakeY(detectResult, targetIndex, parentComponent.node, targetRect, layout, fakeY);
1197
- if (isStandardLayout(parentNodeLayout)) {
1198
- const rightNodeCount = parentComponent.node.origin.rightNodeCount || 0;
1199
- const idx = parentComponent.node.children.findIndex(x => x === targetComponent.node);
1200
- const isLeft = idx >= rightNodeCount;
1201
- // 标准布局的左,需要调整 x
1202
- if (isLeft) {
1203
- fakeX = targetComponent.node.x + targetComponent.node.width - 30;
1204
- fakeRectangleStartX = targetRect.x + targetRect.width - 30;
1205
- fakeRectangleEndX = targetRect.x + targetRect.width;
1206
- }
1207
- const isLeftFirst = idx === rightNodeCount;
1208
- const isRightLast = idx === rightNodeCount - 1;
1209
- // 拖拽至左第一个节点的情况
1210
- if (detectResult === 'top' && isLeftFirst) {
1211
- fakeY = targetRect.y - targetRect.height;
1212
- }
1213
- if (detectResult === 'bottom' && isRightLast) {
1214
- fakeY = targetRect.y + targetRect.height + 30;
1215
- }
1216
- }
1217
- fakeRectangleStartY = fakeY;
1218
- fakeRectangleEndY = fakeRectangleStartY + 12;
1219
- }
1220
- if (isVerticalLogicLayout(layout)) {
1221
- parentComponent = targetComponent;
1222
- targetComponent = PlaitElement.getComponent(MindElement.getParent(targetComponent.element));
1223
- fakeX = parentComponent.node.x;
1224
- width = parentComponent.node.width;
1225
- const vGap = BASE * 6 + strokeWidth;
1226
- if (isTopLayout(layout) && detectResult === 'top') {
1227
- fakeY = targetRect.y - vGap;
1228
- fakeRectangleStartY = fakeY - vGap + strokeWidth;
1229
- }
1230
- if (isBottomLayout(layout) && detectResult === 'bottom') {
1231
- fakeY = targetRect.y + targetRect.height + vGap;
1232
- fakeRectangleStartY = fakeY + vGap - strokeWidth;
1233
- }
1234
- fakeRectangleStartX = fakeX + Math.ceil(parentComponent.node.width / 2) - parentComponent.node.hGap - Math.ceil(strokeWidth / 2);
1235
- fakeRectangleEndX = fakeRectangleStartX + 30;
1236
- fakeRectangleEndY = fakeRectangleStartY + 12;
1237
- }
1238
- if (isIndentedLayout(layout)) {
1239
- // 偏移一个 Gap
902
+ const layout = MindQueries.getCorrectLayoutByElement(board, node === null || node === void 0 ? void 0 : node.origin);
903
+ if (isStandardLayout(layout)) {
904
+ return getAllowedDirection(detectResults, ['top', 'bottom']);
905
+ }
906
+ if (layout === MindLayoutType.upward) {
907
+ return getAllowedDirection(detectResults, ['left', 'right', 'bottom']);
908
+ }
909
+ if (layout === MindLayoutType.downward) {
910
+ return getAllowedDirection(detectResults, ['left', 'right', 'top']);
911
+ }
1240
912
  if (isLeftLayout(layout)) {
1241
- fakeX -= BASE * 4;
913
+ return getAllowedDirection(detectResults, ['right', 'top', 'bottom']);
1242
914
  }
1243
915
  if (isRightLayout(layout)) {
1244
- fakeX += BASE * 4;
1245
- }
1246
- if (isTopLayout(layout)) {
1247
- if (detectResult === 'top') {
1248
- const isLastNode = targetIndex === parentComponent.node.origin.children.length - 1;
1249
- if (isLastNode) {
1250
- fakeY = targetRect.y - targetRect.height - BASE;
1251
- }
1252
- else {
1253
- const nextComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
1254
- const nextRect = getRectangleByNode(nextComponent.node);
1255
- fakeY = targetRect.y - Math.abs((nextRect.y + nextRect.height - targetRect.y) / 2);
1256
- }
1257
- }
1258
- if (detectResult === 'bottom') {
1259
- const isFirstNode = targetIndex === 0;
1260
- if (isFirstNode) {
1261
- const parentRect = getRectangleByNode(parentComponent.node);
1262
- fakeY = parentRect.y - parentRect.height / 2 - BASE;
1263
- }
1264
- else {
1265
- const previousComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
1266
- const previousRect = getRectangleByNode(previousComponent.node);
1267
- fakeY = previousRect.y - Math.abs((targetRect.y + targetRect.height - previousRect.y) / 2);
1268
- }
1269
- }
916
+ return getAllowedDirection(detectResults, ['left', 'top', 'bottom']);
1270
917
  }
1271
- fakeRectangleStartX = fakeX;
1272
- fakeRectangleEndX = fakeRectangleStartX + 30;
1273
- fakeRectangleStartY = fakeY;
1274
- fakeRectangleEndY = fakeRectangleStartY + 12;
1275
918
  }
1276
- // 构造一条曲线
1277
- const fakeNode = Object.assign(Object.assign({}, targetComponent.node), { x: fakeX, y: fakeY, width, height: 12 });
1278
- const linkSVGG = isIndentedLayout(layout)
1279
- ? drawIndentedLink(board, parentComponent.node, fakeNode, PRIMARY_COLOR, false)
1280
- : drawLink(board, parentComponent.node, fakeNode, PRIMARY_COLOR, isHorizontalLayout(layout), false);
1281
- // 构造一个矩形框坐标
1282
- const fakeRectangleG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), fakeRectangleStartX, fakeRectangleStartY, fakeRectangleEndX, fakeRectangleEndY, {
1283
- stroke: PRIMARY_COLOR,
1284
- strokeWidth: 2,
1285
- fill: PRIMARY_COLOR,
1286
- fillStyle: 'solid'
919
+ return null;
920
+ };
921
+ const getAllowedDirection = (detectResults, illegalDirections) => {
922
+ const directions = detectResults;
923
+ illegalDirections.forEach(item => {
924
+ const bottomDirectionIndex = directions.findIndex(direction => direction === item);
925
+ if (bottomDirectionIndex !== -1) {
926
+ directions.splice(bottomDirectionIndex, 1);
927
+ }
1287
928
  });
1288
- fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(linkSVGG);
1289
- fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(fakeRectangleG);
929
+ return directions.length ? directions : null;
1290
930
  };
1291
- const drawStraightDropNodeG = (board, targetRect, detectResult, targetComponent, fakeDropNodeG) => {
1292
- const { x, y, width, height } = targetRect;
1293
- const lineLength = 40;
1294
- let startLinePoint = x + width;
1295
- let endLinePoint = x + width + lineLength;
1296
- let startRectanglePointX = x + width + lineLength;
1297
- let endRectanglePointX = x + lineLength + width + 30;
1298
- let startRectanglePointY = y + height / 2 - 6;
1299
- let endRectanglePointY = y + height / 2 - 6 + 12;
1300
- if (detectResult === 'left') {
1301
- startLinePoint = x - lineLength;
1302
- endLinePoint = x;
1303
- startRectanglePointX = x - lineLength - 30;
1304
- endRectanglePointX = x - lineLength;
1305
- }
1306
- let fakeY = targetComponent.node.y;
1307
- let fakeX = targetRect.x;
1308
- const strokeWidth = targetComponent.node.origin.branchWidth ? targetComponent.node.origin.branchWidth : STROKE_WIDTH;
1309
- const pointOptions = {
1310
- fakeX,
1311
- fakeY,
1312
- x,
1313
- y,
1314
- width,
1315
- height,
1316
- strokeWidth
1317
- };
1318
- const parentLayout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin.isRoot ? targetComponent.node.origin : targetComponent.node.parent.origin);
1319
- const layout = MindQueries.getCorrectLayoutByElement(board, targetComponent.node.origin);
1320
- if (!isMixedLayout(parentLayout, layout)) {
1321
- // 构造一条直线
1322
- let linePoints = [
1323
- [startLinePoint, y + height / 2],
1324
- [endLinePoint, y + height / 2]
1325
- ];
1326
- if (isIndentedLayout(parentLayout)) {
1327
- const fakePoint = getIndentedFakePoint(parentLayout, pointOptions);
1328
- drawIndentNodeG(board, fakeDropNodeG, fakePoint, targetComponent.node);
931
+ const detectDropTarget = (board, detectPoint, dropTarget, activeElements) => {
932
+ let detectResult = null;
933
+ depthFirstRecursion(board, element => {
934
+ if (!MindElement.isMindElement(board, element) || detectResult) {
1329
935
  return;
1330
936
  }
1331
- else if (isVerticalLogicLayout(parentLayout)) {
1332
- if (!targetComponent.node.origin.isRoot) {
1333
- /**
1334
- * 计算逻辑:
1335
- * 1. 移动到左侧:当前节点 startX - 偏移值,偏移值计算如下:
1336
- * a. 第一个节点: 固定值(来源于 getMainAxle,第二级节点:BASE * 8,其他 BASE * 3 + strokeWidth / 2);
1337
- * b. 第二个节点到最后一个节点之间:上一个节点到当前节点间距的一半((当前节点 startX - 上一个节点的 endX) / 2),endX = 当前节点的 startX + width;
1338
- * 2. 移动到右侧:当前节点 x + width + 偏移值,偏移值计算如下:
1339
- * a. 第二个节点到最后一个节点之间的右侧:当前节点到下一个节点间距的一半((下一个节点 startX - 当前节点的 endX) / 2),endX = 当前节点的 startX + width;
1340
- * b. 最后一个节点的右侧:固定值(来源于 getMainAxle,第二级节点:BASE * 8,其他 BASE * 3 + strokeWidth / 2);
1341
- */
1342
- fakeY = targetComponent.node.y;
1343
- const parentComponent = PlaitElement.getComponent(MindElement.getParent(targetComponent.element));
1344
- const targetIndex = parentComponent.node.origin.children.indexOf(targetComponent.node.origin);
1345
- if (detectResult === 'left') {
1346
- let offsetX = 0;
1347
- const isFirstNode = targetIndex === 0;
1348
- if (isFirstNode) {
1349
- offsetX = parentComponent.node.origin.isRoot ? BASE * 8 : BASE * 3 + strokeWidth / 2;
1350
- }
1351
- else {
1352
- const previousComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex - 1]);
1353
- const previousRect = getRectangleByNode(previousComponent.node);
1354
- const space = targetRect.x - (previousRect.x + previousRect.width);
1355
- offsetX = space / 2;
1356
- }
1357
- fakeX = targetRect.x - offsetX - width / 2 - Math.ceil(strokeWidth / 2);
1358
- }
1359
- if (detectResult === 'right') {
1360
- let offsetX = 0;
1361
- const isLastNode = targetIndex === parentComponent.node.origin.children.length - 1;
1362
- if (isLastNode) {
1363
- offsetX = parentComponent.node.origin.isRoot ? BASE * 8 : BASE * 3 + strokeWidth / 2;
1364
- }
1365
- else {
1366
- const nextComponent = PlaitElement.getComponent(parentComponent.node.origin.children[targetIndex + 1]);
1367
- const nextRect = getRectangleByNode(nextComponent.node);
1368
- const space = nextRect.x - (targetRect.x + targetRect.width);
1369
- offsetX = space / 2;
1370
- }
1371
- fakeX = targetRect.x + width + offsetX - width / 2 - Math.ceil(strokeWidth / 2);
1372
- }
1373
- startRectanglePointX = fakeX;
1374
- if (isTopLayout(parentLayout)) {
1375
- // 因为矩形是从左上角为起点向下画的,所以需要向上偏移一个矩形的高度(-12)
1376
- startRectanglePointY = fakeY + height + targetComponent.node.vGap - 12;
1377
- }
1378
- if (isBottomLayout(parentLayout)) {
1379
- startRectanglePointY = fakeY + targetComponent.node.vGap;
1380
- }
1381
- endRectanglePointX = startRectanglePointX + 30;
1382
- endRectanglePointY = startRectanglePointY + 12;
1383
- const fakeNode = Object.assign(Object.assign({}, targetComponent.node), { x: fakeX, y: fakeY, width: 30 });
1384
- const linkSVGG = drawLink(board, parentComponent.node, fakeNode, PRIMARY_COLOR, false, false);
1385
- fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(linkSVGG);
1386
- }
937
+ const node = MindElement.getNode(element);
938
+ const directions = directionDetector(node, detectPoint);
939
+ if (directions) {
940
+ detectResult = directionCorrector(board, node, directions);
1387
941
  }
1388
- else {
1389
- let linkSVGG = PlaitBoard.getRoughSVG(board).linearPath(linePoints, { stroke: PRIMARY_COLOR, strokeWidth });
1390
- fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(linkSVGG);
942
+ dropTarget = null;
943
+ const isValid = activeElements.every(element => isValidTarget(element, node.origin));
944
+ if (detectResult && isValid) {
945
+ dropTarget = { target: node.origin, detectResult: detectResult[0] };
1391
946
  }
1392
- // 构造一个矩形框坐标
1393
- let fakeRectangleG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), startRectanglePointX, startRectanglePointY, endRectanglePointX, endRectanglePointY, {
1394
- stroke: PRIMARY_COLOR,
1395
- strokeWidth: 2,
1396
- fill: PRIMARY_COLOR,
1397
- fillStyle: 'solid'
1398
- });
1399
- fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(fakeRectangleG);
1400
- }
1401
- else {
1402
- // 混合布局画线逻辑
1403
- if (isHorizontalLogicLayout(parentLayout)) {
1404
- if (isIndentedLayout(layout)) {
1405
- const fakePoint = getIndentedFakePoint(layout, pointOptions);
1406
- drawIndentNodeG(board, fakeDropNodeG, fakePoint, targetComponent.node);
1407
- return;
1408
- }
1409
- }
1410
- }
1411
- };
1412
- const getHorizontalFakeY = (detectResult, targetIndex, parentNode, targetRect, layout, fakeY) => {
1413
- const childrenLength = getNonAbstractChildren(parentNode).length;
1414
- if (detectResult === 'top') {
1415
- if (targetIndex === 0 && isTopLayout(layout)) {
1416
- fakeY = targetRect.y + targetRect.height;
1417
- }
1418
- if (targetIndex > 0) {
1419
- const previousComponent = PlaitElement.getComponent(parentNode.origin.children[targetIndex - 1]);
1420
- const previousRect = getRectangleByNode(previousComponent.node);
1421
- const topY = previousRect.y + previousRect.height;
1422
- fakeY = topY + (targetRect.y - topY) / 5;
1423
- }
1424
- }
1425
- if (detectResult === 'bottom') {
1426
- fakeY = targetRect.y + targetRect.height + 30;
1427
- if (targetIndex < childrenLength - 1) {
1428
- const nextComponent = PlaitElement.getComponent(parentNode.origin.children[targetIndex + 1]);
1429
- const nextRect = getRectangleByNode(nextComponent.node);
1430
- const topY = targetRect.y + targetRect.height;
1431
- fakeY = topY + (nextRect.y - topY) / 5;
947
+ }, node => {
948
+ if (PlaitBoard.isBoard(node) || board.isRecursion(node)) {
949
+ return true;
1432
950
  }
1433
- if (targetIndex === childrenLength - 1) {
1434
- fakeY = targetRect.y + targetRect.height + 30;
951
+ else {
952
+ return false;
1435
953
  }
1436
- }
1437
- return fakeY;
1438
- };
1439
- const getIndentedFakePoint = (layout, pointOptions) => {
1440
- let { fakeX, fakeY, x, y, width, height, strokeWidth } = pointOptions;
1441
- const hGap = BASE * 4;
1442
- const vGap = BASE * 6;
1443
- const offsetX = hGap + width / 2 + strokeWidth;
1444
- const offsetY = vGap + height / 2 + strokeWidth;
1445
- if (isLeftLayout(layout)) {
1446
- fakeX = x - offsetX;
1447
- }
1448
- if (isRightLayout(layout)) {
1449
- fakeX = x + offsetX;
1450
- }
1451
- if (isTopLayout(layout)) {
1452
- fakeY = y - offsetY;
1453
- }
1454
- if (isBottomLayout(layout)) {
1455
- fakeY = y + height + offsetY;
1456
- }
1457
- return { fakeX, fakeY };
1458
- };
1459
- const drawIndentNodeG = (board, fakeDropNodeG, fakePoint, node) => {
1460
- const { fakeX, fakeY } = fakePoint;
1461
- const fakeNode = Object.assign(Object.assign({}, node), { x: fakeX, y: fakeY, width: 30, height: 12 });
1462
- const linkSVGG = drawIndentedLink(board, node, fakeNode, PRIMARY_COLOR, false);
1463
- const startRectanglePointX = fakeX, startRectanglePointY = fakeY, endRectanglePointX = fakeX + 30, endRectanglePointY = fakeY + 12;
1464
- const fakeRectangleG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), startRectanglePointX, startRectanglePointY, endRectanglePointX, endRectanglePointY, {
1465
- stroke: PRIMARY_COLOR,
1466
- strokeWidth: 2,
1467
- fill: PRIMARY_COLOR,
1468
- fillStyle: 'solid'
1469
954
  });
1470
- fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(linkSVGG);
1471
- fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(fakeRectangleG);
955
+ return dropTarget;
1472
956
  };
1473
-
1474
- /**
1475
- *
1476
- * @param targetNode
1477
- * @param centerPoint
1478
- * @returns DetectResult[] | null
1479
- */
1480
957
  const directionDetector = (targetNode, centerPoint) => {
1481
958
  const { x, y, width, height } = getRectangleByNode(targetNode);
1482
959
  const yCenter = y + height / 2;
@@ -1525,59 +1002,6 @@ const directionDetector = (targetNode, centerPoint) => {
1525
1002
  }
1526
1003
  return null;
1527
1004
  };
1528
-
1529
- const directionCorrector = (board, node, detectResults) => {
1530
- if (!node.origin.isRoot && !AbstractNode.isAbstract(node.origin)) {
1531
- const parentLayout = MindQueries.getCorrectLayoutByElement(board, node === null || node === void 0 ? void 0 : node.parent.origin);
1532
- if (isStandardLayout(parentLayout)) {
1533
- const idx = node.parent.children.findIndex(x => x === node);
1534
- const isLeft = idx >= (node.parent.origin.rightNodeCount || 0);
1535
- return getAllowedDirection(detectResults, [isLeft ? 'right' : 'left']);
1536
- }
1537
- if (isLeftLayout(parentLayout)) {
1538
- return getAllowedDirection(detectResults, ['right']);
1539
- }
1540
- if (isRightLayout(parentLayout)) {
1541
- return getAllowedDirection(detectResults, ['left']);
1542
- }
1543
- if (parentLayout === MindLayoutType.upward) {
1544
- return getAllowedDirection(detectResults, ['bottom']);
1545
- }
1546
- if (parentLayout === MindLayoutType.downward) {
1547
- return getAllowedDirection(detectResults, ['top']);
1548
- }
1549
- }
1550
- else {
1551
- const layout = MindQueries.getCorrectLayoutByElement(board, node === null || node === void 0 ? void 0 : node.origin);
1552
- if (isStandardLayout(layout)) {
1553
- return getAllowedDirection(detectResults, ['top', 'bottom']);
1554
- }
1555
- if (isTopLayout(layout)) {
1556
- return getAllowedDirection(detectResults, ['left', 'right', 'bottom']);
1557
- }
1558
- if (isBottomLayout(layout)) {
1559
- return getAllowedDirection(detectResults, ['left', 'right', 'top']);
1560
- }
1561
- if (layout === MindLayoutType.left) {
1562
- return getAllowedDirection(detectResults, ['right', 'top', 'bottom']);
1563
- }
1564
- if (layout === MindLayoutType.right) {
1565
- return getAllowedDirection(detectResults, ['left', 'top', 'bottom']);
1566
- }
1567
- }
1568
- return null;
1569
- };
1570
- const getAllowedDirection = (detectResults, illegalDirections) => {
1571
- const directions = detectResults;
1572
- illegalDirections.forEach(item => {
1573
- const bottomDirectionIndex = directions.findIndex(direction => direction === item);
1574
- if (bottomDirectionIndex !== -1) {
1575
- directions.splice(bottomDirectionIndex, 1);
1576
- }
1577
- });
1578
- return directions.length ? directions : null;
1579
- };
1580
-
1581
1005
  /* 根据布局调整 target 以及 direction */
1582
1006
  const readjustmentDropTarget = (board, dropTarget) => {
1583
1007
  const { target, detectResult } = dropTarget;
@@ -1660,262 +1084,126 @@ const readjustmentDropTarget = (board, dropTarget) => {
1660
1084
  }
1661
1085
  return dropTarget;
1662
1086
  };
1663
-
1664
- const getRectangleByResizingLocation = (abstractRectangle, location, activeHandlePosition, isHorizontal) => {
1665
- if (isHorizontal) {
1666
- if (activeHandlePosition === AbstractHandlePosition.start) {
1667
- return Object.assign(Object.assign({}, abstractRectangle), { y: location, height: abstractRectangle.height + abstractRectangle.y - location });
1087
+ const isValidTarget = (origin, target) => {
1088
+ return origin !== target && !isChildElement(origin, target);
1089
+ };
1090
+ const getPathByDropTarget = (board, dropTarget) => {
1091
+ let targetPath = PlaitBoard.findPath(board, dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.target);
1092
+ const layout = PlaitMind.isMind(dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.target)
1093
+ ? getRootLayout(dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.target)
1094
+ : MindQueries.getCorrectLayoutByElement(board, MindElement.getParent(dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.target));
1095
+ const children = getNonAbstractChildren(dropTarget.target);
1096
+ // 上下布局:左右是兄弟节点,上下是子节点
1097
+ if (isVerticalLogicLayout(layout)) {
1098
+ if (dropTarget.detectResult === 'top' || dropTarget.detectResult === 'bottom') {
1099
+ targetPath.push(children.length);
1668
1100
  }
1669
- else {
1670
- return Object.assign(Object.assign({}, abstractRectangle), { height: location - abstractRectangle.y });
1101
+ // 如果是左,位置不变,右则插入到下一个兄弟节点
1102
+ if (dropTarget.detectResult === 'right') {
1103
+ targetPath = Path.next(targetPath);
1671
1104
  }
1672
1105
  }
1673
- else {
1674
- if (activeHandlePosition === AbstractHandlePosition.start) {
1675
- return Object.assign(Object.assign({}, abstractRectangle), { x: location, width: abstractRectangle.width + abstractRectangle.x - location });
1106
+ // 水平布局/标准布局:上下是兄弟节点,左右是子节点
1107
+ if (isHorizontalLogicLayout(layout)) {
1108
+ if (dropTarget.detectResult === 'right' || dropTarget.detectResult === 'left') {
1109
+ targetPath.push(children.length);
1676
1110
  }
1677
- else {
1678
- return Object.assign(Object.assign({}, abstractRectangle), { width: location - abstractRectangle.x });
1111
+ // 如果是上,位置不变,下插入到下一个兄弟节点
1112
+ if (dropTarget.detectResult === 'bottom') {
1113
+ targetPath = Path.next(targetPath);
1679
1114
  }
1680
1115
  }
1681
- };
1682
- const getLocationScope = (board, handlePosition, parentChildren, element, parent, isHorizontal) => {
1683
- const node = MindElement.getNode(element);
1684
- const { start, end } = getCorrectStartEnd(node.origin, parent);
1685
- const startNode = parentChildren[start];
1686
- const endNode = parentChildren[end];
1687
- if (handlePosition === AbstractHandlePosition.start) {
1688
- const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.end < element.start);
1689
- let minNode;
1690
- if (abstractNode.length) {
1691
- const index = abstractNode
1692
- .map(node => {
1693
- const { end } = getCorrectStartEnd(node, parent);
1694
- return end;
1695
- })
1696
- .sort((a, b) => b - a)[0];
1697
- minNode = parentChildren[index + 1];
1116
+ // 缩进布局:上下是兄弟节点,左右是子节点,但上(左上/右上),探测到上是子节点,下则位置不变,反之同理。
1117
+ if (isIndentedLayout(layout)) {
1118
+ if (isTopLayout(layout) && dropTarget.detectResult === 'top') {
1119
+ targetPath = Path.next(targetPath);
1698
1120
  }
1699
- else {
1700
- minNode = parentChildren[0];
1121
+ if (isBottomLayout(layout) && dropTarget.detectResult === 'bottom') {
1122
+ targetPath = Path.next(targetPath);
1701
1123
  }
1702
- const minNodeRectangle = getRectangleByElements(board, [minNode], true);
1703
- const endNodeRectangle = getRectangleByElements(board, [endNode], false);
1704
- if (isHorizontal) {
1705
- return {
1706
- max: endNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1707
- min: minNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET
1708
- };
1124
+ if (isLeftLayout(layout) && dropTarget.detectResult === 'left') {
1125
+ targetPath.push(children.length);
1709
1126
  }
1710
- else {
1711
- return {
1712
- max: endNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1713
- min: minNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET
1714
- };
1127
+ if (isRightLayout(layout) && dropTarget.detectResult === 'right') {
1128
+ targetPath.push(children.length);
1715
1129
  }
1716
1130
  }
1131
+ return targetPath;
1132
+ };
1133
+
1134
+ function drawRoundRectangleByNode(board, node) {
1135
+ const rectangle = getRectangleByNode(node);
1136
+ return drawRoundRectangleByElement(board, rectangle, node.origin);
1137
+ }
1138
+ function drawRoundRectangleByElement(board, nodeRectangle, element) {
1139
+ const fill = element.fill ? element.fill : element.isRoot ? DefaultRootStyle.fill : DefaultNodeStyle.fill;
1140
+ const stroke = getStrokeByMindElement(board, element);
1141
+ const strokeWidth = element.strokeWidth ? element.strokeWidth : DefaultNodeStyle.strokeWidth;
1142
+ const nodeG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), nodeRectangle.x, nodeRectangle.y, nodeRectangle.x + nodeRectangle.width, nodeRectangle.y + nodeRectangle.height, {
1143
+ stroke,
1144
+ strokeWidth,
1145
+ fill,
1146
+ fillStyle: 'solid'
1147
+ });
1148
+ return nodeG;
1149
+ }
1150
+
1151
+ var HorizontalPlacement;
1152
+ (function (HorizontalPlacement) {
1153
+ HorizontalPlacement["left"] = "left";
1154
+ HorizontalPlacement["center"] = "center";
1155
+ HorizontalPlacement["right"] = "right";
1156
+ })(HorizontalPlacement || (HorizontalPlacement = {}));
1157
+ var VerticalPlacement;
1158
+ (function (VerticalPlacement) {
1159
+ VerticalPlacement["top"] = "top";
1160
+ VerticalPlacement["middle"] = "middle";
1161
+ VerticalPlacement["bottom"] = "bottom";
1162
+ })(VerticalPlacement || (VerticalPlacement = {}));
1163
+
1164
+ const getPointByPlacement = (client, placement) => {
1165
+ let x = client.x;
1166
+ let y = client.y;
1167
+ if (placement[0] === HorizontalPlacement.center) {
1168
+ x = client.x + client.width / 2;
1169
+ }
1170
+ if (placement[0] === HorizontalPlacement.right) {
1171
+ x = client.x + client.width;
1172
+ }
1173
+ if (placement[1] === VerticalPlacement.middle) {
1174
+ y = client.y + client.height / 2;
1175
+ }
1176
+ if (placement[1] === VerticalPlacement.bottom) {
1177
+ y = client.y + client.height;
1178
+ }
1179
+ return [x, y];
1180
+ };
1181
+ const getXDistanceBetweenPoint = (point1, point2, isHorizontalLayout) => {
1182
+ if (isHorizontalLayout) {
1183
+ return Math.abs(point1[0] - point2[0]);
1184
+ }
1717
1185
  else {
1718
- const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.start > element.end);
1719
- let maxNode;
1720
- if (abstractNode.length) {
1721
- const index = abstractNode
1722
- .map(node => {
1723
- const { start } = getCorrectStartEnd(node, parent);
1724
- return start;
1725
- })
1726
- .sort((a, b) => a - b)[0];
1727
- maxNode = parentChildren[index - 1];
1186
+ return Math.abs(point1[1] - point2[1]);
1187
+ }
1188
+ };
1189
+ const getYDistanceBetweenPoint = (point1, point2, isHorizontalLayout) => {
1190
+ getXDistanceBetweenPoint(point1, point2, !isHorizontalLayout);
1191
+ };
1192
+ const getLayoutDirection = (node, isHorizontal) => {
1193
+ if (isHorizontal) {
1194
+ if (node.left) {
1195
+ return LayoutDirection.left;
1728
1196
  }
1729
1197
  else {
1730
- const children = parentChildren.filter(child => !AbstractNode.isAbstract(child));
1731
- maxNode = parentChildren[children.length - 1];
1198
+ return LayoutDirection.right;
1732
1199
  }
1733
- const maxNodeRectangle = getRectangleByElements(board, [maxNode], true);
1734
- const startNodeRectangle = getRectangleByElements(board, [startNode], false);
1735
- if (isHorizontal) {
1736
- return {
1737
- max: maxNodeRectangle.y + maxNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1738
- min: startNodeRectangle.y + startNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET
1739
- };
1200
+ }
1201
+ else {
1202
+ if (node.up) {
1203
+ return LayoutDirection.top;
1740
1204
  }
1741
1205
  else {
1742
- return {
1743
- max: maxNodeRectangle.x + maxNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1744
- min: startNodeRectangle.x + startNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET
1745
- };
1746
- }
1747
- }
1748
- };
1749
- const getHitAbstractHandle = (board, element, point) => {
1750
- const nodeLayout = MindQueries.getCorrectLayoutByElement(board, element);
1751
- const isHorizontal = isHorizontalLayout(nodeLayout);
1752
- const parentElement = MindElement.getParent(element);
1753
- const includedElements = parentElement.children.slice(element.start, element.end + 1);
1754
- let abstractRectangle = getRectangleByElements(board, includedElements, true);
1755
- abstractRectangle = RectangleClient.getOutlineRectangle(abstractRectangle, -ABSTRACT_INCLUDED_OUTLINE_OFFSET);
1756
- const startHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.start);
1757
- const endHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.end);
1758
- const pointRec = RectangleClient.toRectangleClient([point, point]);
1759
- if (RectangleClient.isHit(pointRec, startHandleRec))
1760
- return AbstractHandlePosition.start;
1761
- if (RectangleClient.isHit(pointRec, endHandleRec))
1762
- return AbstractHandlePosition.end;
1763
- return undefined;
1764
- };
1765
- const getAbstractHandleRectangle = (rectangle, isHorizontal, position) => {
1766
- let result;
1767
- if (position === AbstractHandlePosition.start) {
1768
- const location = isHorizontal ? rectangle.y : rectangle.x;
1769
- result = getRectangleByResizingLocation(rectangle, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.end, isHorizontal);
1770
- result = getRectangleByResizingLocation(result, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
1771
- }
1772
- else {
1773
- const location = isHorizontal ? rectangle.y + rectangle.height : rectangle.x + rectangle.width;
1774
- result = getRectangleByResizingLocation(rectangle, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.start, isHorizontal);
1775
- result = getRectangleByResizingLocation(result, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
1776
- }
1777
- return result;
1778
- };
1779
- function findLocationLeftIndex(board, parentChildren, location, isHorizontal) {
1780
- const children = parentChildren.filter(child => {
1781
- return !AbstractNode.isAbstract(child);
1782
- });
1783
- const recArray = children.map(child => {
1784
- return getRectangleByElements(board, [child], false);
1785
- });
1786
- const firstRec = getRectangleByElements(board, [children[0]], true);
1787
- const fakeLeftRec = {
1788
- x: firstRec.x - firstRec.width,
1789
- y: firstRec.y - firstRec.height,
1790
- width: firstRec.width,
1791
- height: firstRec.height
1792
- };
1793
- const lastRec = getRectangleByElements(board, [children[children.length - 1]], true);
1794
- const fakeRightRec = {
1795
- x: lastRec.x + lastRec.width,
1796
- y: lastRec.y + lastRec.height,
1797
- width: lastRec.width,
1798
- height: lastRec.height
1799
- };
1800
- recArray.push(fakeRightRec);
1801
- recArray.unshift(fakeLeftRec);
1802
- for (let i = 0; i < recArray.length - 1; i++) {
1803
- const recXOrY = isHorizontal ? recArray[i].y : recArray[i].x;
1804
- const recWidthOrHeight = isHorizontal ? recArray[i].height : recArray[i].width;
1805
- if (location >= recXOrY + recWidthOrHeight / 2 &&
1806
- location <= recArray[i + 1][isHorizontal ? 'y' : 'x'] + recArray[i + 1][isHorizontal ? 'height' : 'width'] / 2) {
1807
- return i - 1;
1808
- }
1809
- }
1810
- return 0;
1811
- }
1812
- function handleTouchedAbstract(board, touchedAbstract, endPoint) {
1813
- let touchedHandle;
1814
- const abstract = getSelectedElements(board)
1815
- .filter(element => AbstractNode.isAbstract(element))
1816
- .find(element => {
1817
- touchedHandle = getHitAbstractHandle(board, element, endPoint);
1818
- return touchedHandle;
1819
- });
1820
- if (touchedAbstract === abstract) {
1821
- return touchedAbstract;
1822
- }
1823
- if (touchedAbstract) {
1824
- const component = PlaitElement.getComponent(touchedAbstract);
1825
- component.updateAbstractIncludedOutline();
1826
- touchedAbstract = undefined;
1827
- }
1828
- if (abstract) {
1829
- touchedAbstract = abstract;
1830
- const component = PlaitElement.getComponent(touchedAbstract);
1831
- component.updateAbstractIncludedOutline(touchedHandle);
1832
- }
1833
- return touchedAbstract;
1834
- }
1835
-
1836
- function drawIndentedLink(board, node, child, defaultStroke = null, needDrawUnderline = true) {
1837
- const branchWidth = getBranchWidthByMindElement(board, child.origin);
1838
- const branchColor = defaultStroke || getBranchColorByMindElement(board, child.origin);
1839
- const isUnderlineShape = getShapeByElement(board, child.origin) === MindElementShape.underline;
1840
- let beginX, beginY, endX, endY, beginNode = node, endNode = child;
1841
- const beginRectangle = getRectangleByNode(beginNode);
1842
- const endRectangle = getRectangleByNode(endNode);
1843
- beginX = beginNode.x + beginNode.width / 2;
1844
- beginY = isChildUp(node, child) ? beginRectangle.y : beginRectangle.y + beginRectangle.height;
1845
- endX = node.left ? endNode.x + endNode.hGap + endRectangle.width : endNode.x + endNode.hGap;
1846
- endY = isUnderlineShape ? endNode.y + endNode.height - endNode.vGap : endNode.y + endNode.height / 2;
1847
- //根据位置,设置正负参数
1848
- let plusMinus = isChildUp(node, child) ? (node.left ? [-1, -1] : [1, -1]) : node.left ? [-1, 1] : [1, 1];
1849
- const layout = MindQueries.getCorrectLayoutByElement(board, node.origin);
1850
- if (beginNode.origin.isRoot) {
1851
- if (layout === MindLayoutType.leftBottomIndented || layout === MindLayoutType.rightBottomIndented) {
1852
- beginY += branchWidth;
1853
- }
1854
- if (layout === MindLayoutType.leftTopIndented || layout === MindLayoutType.rightTopIndented) {
1855
- beginY -= branchWidth;
1856
- }
1857
- }
1858
- let curve = [
1859
- [beginX, beginY],
1860
- [beginX, beginY],
1861
- [beginX, beginY],
1862
- [beginX, endY - (endNode.hGap * 3 * plusMinus[1]) / 5],
1863
- [beginX, endY - (endNode.hGap * plusMinus[1]) / 5],
1864
- [beginX + (endNode.hGap * plusMinus[0]) / 4, endY],
1865
- [beginX + (endNode.hGap * plusMinus[0] * 3) / 5, endY],
1866
- isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
1867
- isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
1868
- isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY]
1869
- ];
1870
- const points = pointsOnBezierCurves(curve);
1871
- return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth: branchWidth });
1872
- }
1873
-
1874
- var HorizontalPlacement;
1875
- (function (HorizontalPlacement) {
1876
- HorizontalPlacement["left"] = "left";
1877
- HorizontalPlacement["center"] = "center";
1878
- HorizontalPlacement["right"] = "right";
1879
- })(HorizontalPlacement || (HorizontalPlacement = {}));
1880
- var VerticalPlacement;
1881
- (function (VerticalPlacement) {
1882
- VerticalPlacement["top"] = "top";
1883
- VerticalPlacement["middle"] = "middle";
1884
- VerticalPlacement["bottom"] = "bottom";
1885
- })(VerticalPlacement || (VerticalPlacement = {}));
1886
-
1887
- const getPointByPlacement = (client, placement) => {
1888
- let x = client.x;
1889
- let y = client.y;
1890
- if (placement[0] === HorizontalPlacement.center) {
1891
- x = client.x + client.width / 2;
1892
- }
1893
- if (placement[0] === HorizontalPlacement.right) {
1894
- x = client.x + client.width;
1895
- }
1896
- if (placement[1] === VerticalPlacement.middle) {
1897
- y = client.y + client.height / 2;
1898
- }
1899
- if (placement[1] === VerticalPlacement.bottom) {
1900
- y = client.y + client.height;
1901
- }
1902
- return [x, y];
1903
- };
1904
- const getLayoutDirection = (node, isHorizontal) => {
1905
- if (isHorizontal) {
1906
- if (node.left) {
1907
- return LayoutDirection.left;
1908
- }
1909
- else {
1910
- return LayoutDirection.right;
1911
- }
1912
- }
1913
- else {
1914
- if (node.up) {
1915
- return LayoutDirection.top;
1916
- }
1917
- else {
1918
- return LayoutDirection.bottom;
1206
+ return LayoutDirection.bottom;
1919
1207
  }
1920
1208
  }
1921
1209
  };
@@ -1929,7 +1217,7 @@ const getLayoutDirection = (node, isHorizontal) => {
1929
1217
  // 下 -> 上:
1930
1218
  // 1. 终点 -> 起点/终点 -> 起点
1931
1219
  // 2. 加 -> 减
1932
- const movePoint = (point, distance, direction = LayoutDirection.right) => {
1220
+ const moveXOfPoint = (point, distance, direction = LayoutDirection.right) => {
1933
1221
  if (direction === LayoutDirection.left) {
1934
1222
  return [point[0] - distance, point[1]];
1935
1223
  }
@@ -1941,6 +1229,15 @@ const movePoint = (point, distance, direction = LayoutDirection.right) => {
1941
1229
  }
1942
1230
  return [point[0] + distance, point[1]];
1943
1231
  };
1232
+ const moveYOfPoint = (point, distance, direction = LayoutDirection.right) => {
1233
+ if (direction === LayoutDirection.bottom) {
1234
+ return [point[0] + distance, point[1]];
1235
+ }
1236
+ if (direction === LayoutDirection.top) {
1237
+ return [point[0] + distance, point[1]];
1238
+ }
1239
+ return [point[0], point[1] + distance];
1240
+ };
1944
1241
  const transformPlacement = (placement, direction) => {
1945
1242
  // to left
1946
1243
  if (direction === LayoutDirection.left) {
@@ -1981,9 +1278,9 @@ const transformPlacement = (placement, direction) => {
1981
1278
  }
1982
1279
  };
1983
1280
 
1984
- function drawLogicLink(board, node, parent, isHorizontal) {
1985
- const branchColor = getBranchColorByMindElement(board, node.origin);
1986
- const branchWidth = getBranchWidthByMindElement(board, node.origin);
1281
+ function drawLogicLink(board, node, parent, isHorizontal, defaultStroke = null, defaultStrokeWidth) {
1282
+ const branchColor = defaultStroke || getBranchColorByMindElement(board, node.origin);
1283
+ const branchWidth = defaultStrokeWidth || getBranchWidthByMindElement(board, node.origin);
1987
1284
  const hasStraightLine = !parent.origin.isRoot;
1988
1285
  const parentShape = getShapeByElement(board, parent.origin);
1989
1286
  const shape = node.origin.shape ? node.origin.shape : parentShape;
@@ -2010,159 +1307,566 @@ function drawLogicLink(board, node, parent, isHorizontal) {
2010
1307
  // ② 确定凸出直线,从起始点开始画一条直线,从直线的结束位置绘制曲线,保证收起图标可以完美覆盖起始连线,根节点不需要这条直线
2011
1308
  // 绘制贝塞尔曲线要求,需要增加三个点,正常两个点就可以确定这条直线
2012
1309
  const straightLineDistance = 8;
2013
- const beginPoint2 = hasStraightLine ? movePoint(beginPoint, straightLineDistance, linkDirection) : beginPoint;
1310
+ const beginPoint2 = hasStraightLine ? moveXOfPoint(beginPoint, straightLineDistance, linkDirection) : beginPoint;
2014
1311
  let straightLine = hasStraightLine ? [beginPoint, beginPoint2, beginPoint2] : [];
2015
1312
  // ③ 确定曲线
2016
1313
  const beginBufferDistance = (parent.hGap + node.hGap) / 3;
2017
1314
  const endBufferDistance = -(parent.hGap + node.hGap) / 2.4;
2018
1315
  let curve = [
2019
1316
  beginPoint2,
2020
- movePoint(beginPoint2, beginBufferDistance, linkDirection),
2021
- movePoint(endPoint, endBufferDistance, linkDirection),
1317
+ moveXOfPoint(beginPoint2, beginBufferDistance, linkDirection),
1318
+ moveXOfPoint(endPoint, endBufferDistance, linkDirection),
2022
1319
  endPoint
2023
1320
  ];
2024
1321
  // ④ 下划线绘制,underline shape and horizontal
2025
- const underlineEnd = movePoint(endPoint, nodeClient.width, linkDirection);
1322
+ const underlineEnd = moveXOfPoint(endPoint, nodeClient.width, linkDirection);
2026
1323
  const underline = hasUnderlineShape && isHorizontal ? [underlineEnd, underlineEnd, underlineEnd] : [];
2027
1324
  const points = pointsOnBezierCurves([...straightLine, ...curve, ...underline]);
2028
1325
  return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth: branchWidth });
2029
1326
  }
2030
1327
 
2031
- function getEmojisWidthHeight(board, element) {
2032
- const options = board.getMindOptions();
2033
- const count = element.data.emojis.length;
2034
- const fontSize = getEmojiFontSize(element);
2035
- return {
2036
- width: fontSize * count + count * 2 * options.emojiPadding + (count - 1) * options.spaceBetweenEmojis,
2037
- height: element.height
2038
- };
2039
- }
2040
- function getEmojiFontSize(element) {
2041
- if (PlaitMind.isMind(element)) {
2042
- return 18 + 2;
1328
+ const drawFakeDragNode = (board, activeComponent, offsetX, offsetY) => {
1329
+ var _a;
1330
+ const dragFakeNodeG = createG();
1331
+ dragFakeNodeG.classList.add('dragging', 'fake-node', 'plait-board-attached');
1332
+ const fakeDraggingNode = Object.assign(Object.assign({}, activeComponent.node), { children: [], x: activeComponent.node.x + offsetX, y: activeComponent.node.y + offsetY });
1333
+ const textRectangle = getTopicRectangleByNode(board, activeComponent.node);
1334
+ const fakeNodeG = drawRoundRectangleByNode(board, fakeDraggingNode);
1335
+ const richtextG = (_a = activeComponent.richtextG) === null || _a === void 0 ? void 0 : _a.cloneNode(true);
1336
+ updateForeignObject(richtextG, textRectangle.width + BASE * 10, textRectangle.height, textRectangle.x + offsetX, textRectangle.y + offsetY);
1337
+ dragFakeNodeG === null || dragFakeNodeG === void 0 ? void 0 : dragFakeNodeG.append(fakeNodeG);
1338
+ dragFakeNodeG === null || dragFakeNodeG === void 0 ? void 0 : dragFakeNodeG.append(richtextG);
1339
+ return dragFakeNodeG;
1340
+ };
1341
+ const drawFakeDropNodeByPath = (board, target, path) => {
1342
+ const fakeDropNodeG = createG();
1343
+ const parent = PlaitNode.get(board, Path.parent(path));
1344
+ const layout = MindQueries.getLayoutByElement(parent);
1345
+ const isHorizontal = isHorizontalLayout(layout);
1346
+ const { hasNextNode, hasPreviousNode } = getPreviousAndNextByPath(parent, target, path);
1347
+ const width = 30;
1348
+ const height = 12;
1349
+ let fakeNode, centerPoint, basicNode, linkDirection;
1350
+ if (!hasPreviousNode && !hasNextNode) {
1351
+ const parentNode = MindElement.getNode(parent);
1352
+ const parentRect = getRectangleByNode(parentNode);
1353
+ linkDirection = getLayoutDirection(parentNode, isHorizontal);
1354
+ basicNode = parentNode;
1355
+ const placement = [HorizontalPlacement.right, VerticalPlacement.middle];
1356
+ transformPlacement(placement, linkDirection);
1357
+ const parentCenterPoint = getPointByPlacement(parentRect, placement);
1358
+ if (isIndentedLayout(layout)) {
1359
+ const placement = [
1360
+ HorizontalPlacement.center,
1361
+ isTopLayout(layout) ? VerticalPlacement.top : VerticalPlacement.bottom
1362
+ ];
1363
+ const parentCenterPoint = getPointByPlacement(parentRect, placement);
1364
+ centerPoint = moveXOfPoint(parentCenterPoint, height, linkDirection);
1365
+ centerPoint[1] = isTopLayout(layout) ? centerPoint[1] - height : centerPoint[1] + height;
1366
+ }
1367
+ else {
1368
+ centerPoint = moveXOfPoint(parentCenterPoint, width, linkDirection);
1369
+ }
1370
+ }
1371
+ else if (!hasPreviousNode && hasNextNode) {
1372
+ const nextElement = PlaitNode.get(board, path);
1373
+ basicNode = MindElement.getNode(nextElement);
1374
+ const nextRect = getRectangleByNode(basicNode);
1375
+ linkDirection = getLayoutDirection(basicNode, isHorizontal);
1376
+ const placement = [HorizontalPlacement.left, VerticalPlacement.top];
1377
+ transformPlacement(placement, linkDirection);
1378
+ let offset = -height;
1379
+ if (MindElement.isIndentedLayout(parent)) {
1380
+ offset = isTopLayout(layout) ? offset / 2 + basicNode.height - basicNode.vGap : 0;
1381
+ }
1382
+ centerPoint = getPointByPlacement(nextRect, placement);
1383
+ centerPoint = moveYOfPoint(centerPoint, offset, linkDirection);
1384
+ }
1385
+ else if (hasPreviousNode && !hasNextNode) {
1386
+ const previousElement = PlaitNode.get(board, Path.previous(path));
1387
+ basicNode = MindElement.getNode(previousElement);
1388
+ const previousRect = getRectangleByNode(basicNode);
1389
+ linkDirection = getLayoutDirection(basicNode, isHorizontal);
1390
+ const placement = [HorizontalPlacement.left, VerticalPlacement.bottom];
1391
+ transformPlacement(placement, linkDirection);
1392
+ let offset = height;
1393
+ if (MindElement.isIndentedLayout(parent)) {
1394
+ offset = isTopLayout(layout) ? -offset - (basicNode.height - basicNode.vGap) : offset;
1395
+ }
1396
+ centerPoint = getPointByPlacement(previousRect, placement);
1397
+ centerPoint = moveYOfPoint(centerPoint, offset, linkDirection);
2043
1398
  }
2044
1399
  else {
2045
- return 14 + 2;
2046
- }
2047
- }
2048
- function getEmojiRectangle(board, element) {
2049
- let { x, y } = getRectangleByNode(MindElement.getNode(element));
2050
- x = x + NodeSpace.getEmojiLeftSpace(board, element);
2051
- const { width, height } = getEmojisWidthHeight(board, element);
2052
- return {
2053
- x,
1400
+ const previousElement = PlaitNode.get(board, Path.previous(path));
1401
+ basicNode = MindElement.getNode(previousElement);
1402
+ const previousRect = getRectangleByNode(basicNode);
1403
+ const nextElement = PlaitNode.get(board, path);
1404
+ const nextNode = MindElement.getNode(nextElement);
1405
+ const nextRect = getRectangleByNode(nextNode);
1406
+ const beginPlacement = [HorizontalPlacement.left, VerticalPlacement.bottom];
1407
+ const endPlacement = [HorizontalPlacement.left, VerticalPlacement.top];
1408
+ linkDirection = getLayoutDirection(basicNode, isHorizontal);
1409
+ transformPlacement(beginPlacement, linkDirection);
1410
+ transformPlacement(endPlacement, linkDirection);
1411
+ const previousPoint = getPointByPlacement(previousRect, beginPlacement);
1412
+ const nextPoint = getPointByPlacement(nextRect, endPlacement);
1413
+ centerPoint = [(previousPoint[0] + nextPoint[0]) / 2, (previousPoint[1] + nextPoint[1]) / 2];
1414
+ }
1415
+ let cornerPoint = centerPoint, oppositePoint = centerPoint;
1416
+ const offsetY = isHorizontal ? height : width;
1417
+ const offsetX = isHorizontal ? width : height;
1418
+ cornerPoint = moveYOfPoint(cornerPoint, -offsetY / 2, linkDirection);
1419
+ oppositePoint = moveYOfPoint(oppositePoint, offsetY / 2, linkDirection);
1420
+ oppositePoint = moveXOfPoint(oppositePoint, offsetX, linkDirection);
1421
+ const x = Math.min(cornerPoint[0], oppositePoint[0]);
1422
+ const y = Math.min(cornerPoint[1], oppositePoint[1]);
1423
+ fakeNode = Object.assign(Object.assign({}, basicNode), { x,
2054
1424
  y,
2055
1425
  width,
2056
- height
2057
- };
2058
- }
2059
- function getEmojiForeignRectangle(board, element) {
2060
- let { x, y } = getRectangleByNode(MindElement.getNode(element));
2061
- x = x + NodeSpace.getEmojiLeftSpace(board, element);
2062
- const { width, height } = getEmojisWidthHeight(board, element);
1426
+ height, hGap: MindElement.isIndentedLayout(parent) ? BASE * 4 + (basicNode.origin.strokeWidth || STROKE_WIDTH) : 0, vGap: MindElement.isIndentedLayout(parent) ? BASE : 0 });
1427
+ const fakeRectangleG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), fakeNode.x, fakeNode.y, fakeNode.x + width, fakeNode.y + height, {
1428
+ stroke: PRIMARY_COLOR,
1429
+ strokeWidth: 2,
1430
+ fill: PRIMARY_COLOR,
1431
+ fillStyle: 'solid'
1432
+ });
1433
+ const link = MindElement.isIndentedLayout(parent)
1434
+ ? drawIndentedLink(board, MindElement.getNode(parent), fakeNode, PRIMARY_COLOR, false, STROKE_WIDTH)
1435
+ : drawLogicLink(board, fakeNode, MindElement.getNode(parent), isHorizontal, PRIMARY_COLOR, STROKE_WIDTH);
1436
+ fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(link);
1437
+ fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.appendChild(fakeRectangleG);
1438
+ return fakeDropNodeG;
1439
+ };
1440
+ const getPreviousAndNextByPath = (parent, target, path) => {
1441
+ const children = getNonAbstractChildren(parent);
1442
+ let hasPreviousNode = path[path.length - 1] !== 0;
1443
+ let hasNextNode = path[path.length - 1] !== ((children === null || children === void 0 ? void 0 : children.length) || 0);
1444
+ if (PlaitMind.isMind(parent) && isStandardLayout(getRootLayout(parent))) {
1445
+ const dropStandardRightBottom = target === parent.children[parent.rightNodeCount - 1] && path[path.length - 1] === parent.rightNodeCount;
1446
+ const dropStandardLeftTop = target === parent.children[parent.rightNodeCount] && path[path.length - 1] === parent.rightNodeCount;
1447
+ if (dropStandardRightBottom) {
1448
+ hasPreviousNode = true;
1449
+ hasNextNode = false;
1450
+ }
1451
+ if (dropStandardLeftTop) {
1452
+ hasPreviousNode = false;
1453
+ hasNextNode = true;
1454
+ }
1455
+ }
1456
+ if (parent.isCollapsed) {
1457
+ hasNextNode = false;
1458
+ hasPreviousNode = false;
1459
+ }
2063
1460
  return {
2064
- x,
2065
- y,
2066
- width,
2067
- height: height + NodeSpace.getEmojiTopSpace(element) * 2
1461
+ hasPreviousNode,
1462
+ hasNextNode
2068
1463
  };
1464
+ };
1465
+
1466
+ const separateChildren = (parentElement) => {
1467
+ const rightNodeCount = parentElement.rightNodeCount;
1468
+ const children = parentElement.children;
1469
+ let rightChildren = [], leftChildren = [];
1470
+ for (let i = 0; i < children.length; i++) {
1471
+ const child = children[i];
1472
+ if (AbstractNode.isAbstract(child) && child.end < rightNodeCount) {
1473
+ rightChildren.push(child);
1474
+ continue;
1475
+ }
1476
+ if (AbstractNode.isAbstract(child) && child.start >= rightNodeCount) {
1477
+ leftChildren.push(child);
1478
+ continue;
1479
+ }
1480
+ if (i < rightNodeCount) {
1481
+ rightChildren.push(child);
1482
+ }
1483
+ else {
1484
+ leftChildren.push(child);
1485
+ }
1486
+ }
1487
+ return { leftChildren, rightChildren };
1488
+ };
1489
+ const isSetAbstract = (element) => {
1490
+ return !!getCorrespondingAbstract(element);
1491
+ };
1492
+ const canSetAbstract = (element) => {
1493
+ return !PlaitElement.isRootElement(element) && !AbstractNode.isAbstract(element) && !isSetAbstract(element);
1494
+ };
1495
+ const getCorrespondingAbstract = (element) => {
1496
+ const parent = MindElement.findParent(element);
1497
+ if (!parent)
1498
+ return undefined;
1499
+ const elementIndex = parent.children.indexOf(element);
1500
+ return parent.children.find(child => {
1501
+ return AbstractNode.isAbstract(child) && elementIndex >= child.start && elementIndex <= child.end;
1502
+ });
1503
+ };
1504
+ const getBehindAbstracts = (element) => {
1505
+ const parent = MindElement.findParent(element);
1506
+ if (!parent)
1507
+ return [];
1508
+ const index = parent.children.indexOf(element);
1509
+ return parent.children.filter(child => AbstractNode.isAbstract(child) && child.start > index);
1510
+ };
1511
+ /**
1512
+ * return corresponding abstract that is not child of elements
1513
+ */
1514
+ const getOverallAbstracts = (board, elements) => {
1515
+ const overallAbstracts = [];
1516
+ elements
1517
+ .filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
1518
+ .forEach(value => {
1519
+ const abstract = getCorrespondingAbstract(value);
1520
+ if (abstract && elements.indexOf(abstract) === -1 && overallAbstracts.indexOf(abstract) === -1) {
1521
+ const { start, end } = abstract;
1522
+ const parent = MindElement.getParent(value);
1523
+ const isOverall = parent.children.slice(start, end + 1).every(includedElement => elements.indexOf(includedElement) > -1);
1524
+ if (isOverall) {
1525
+ overallAbstracts.push(abstract);
1526
+ }
1527
+ }
1528
+ });
1529
+ return overallAbstracts;
1530
+ };
1531
+ /**
1532
+ * abstract node is valid when elements contains at least one element it is referenced with
1533
+ */
1534
+ const getValidAbstractRefs = (board, elements) => {
1535
+ const validAbstractRefs = [];
1536
+ elements
1537
+ .filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
1538
+ .forEach(value => {
1539
+ const abstract = getCorrespondingAbstract(value);
1540
+ if (abstract && elements.indexOf(abstract) > 0) {
1541
+ const index = validAbstractRefs.findIndex(value => value.abstract === abstract);
1542
+ if (index === -1) {
1543
+ validAbstractRefs.push({
1544
+ abstract: abstract,
1545
+ references: [value]
1546
+ });
1547
+ }
1548
+ else {
1549
+ validAbstractRefs[index].references.push(value);
1550
+ }
1551
+ }
1552
+ });
1553
+ return validAbstractRefs;
1554
+ };
1555
+ function getRelativeStartEndByAbstractRef(abstractRef, elements) {
1556
+ const start = elements.indexOf(abstractRef.references[0]);
1557
+ const end = elements.indexOf(abstractRef.references[abstractRef.references.length - 1]);
1558
+ return { start, end };
2069
1559
  }
2070
- const isHitEmojis = (board, element, point) => {
2071
- return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), getEmojiRectangle(board, element));
1560
+ const insertElementHandleAbstract = (board, path, step = 1,
1561
+ //由此区分拖拽和新增到概要概括最后一个节点
1562
+ isExtendPreviousNode = true, effectedAbstracts = new Map()) => {
1563
+ const parent = PlaitNode.parent(board, path);
1564
+ const hasPreviousNode = path[path.length - 1] !== 0;
1565
+ let behindAbstracts;
1566
+ if (!hasPreviousNode) {
1567
+ behindAbstracts = parent.children.filter(child => AbstractNode.isAbstract(child));
1568
+ }
1569
+ else {
1570
+ const selectedElement = PlaitNode.get(board, Path.previous(path));
1571
+ behindAbstracts = getBehindAbstracts(selectedElement);
1572
+ }
1573
+ if (behindAbstracts.length) {
1574
+ behindAbstracts.forEach(abstract => {
1575
+ let newProperties = effectedAbstracts.get(abstract);
1576
+ if (!newProperties) {
1577
+ newProperties = { start: 0, end: 0 };
1578
+ effectedAbstracts.set(abstract, newProperties);
1579
+ }
1580
+ newProperties.start = newProperties.start + step;
1581
+ newProperties.end = newProperties.end + step;
1582
+ });
1583
+ }
1584
+ if (!hasPreviousNode) {
1585
+ return effectedAbstracts;
1586
+ }
1587
+ const selectedElement = PlaitNode.get(board, Path.previous(path));
1588
+ const correspondingAbstract = getCorrespondingAbstract(selectedElement);
1589
+ const isDragToLast = !isExtendPreviousNode && correspondingAbstract && correspondingAbstract.end === path[path.length - 1] - 1;
1590
+ if (correspondingAbstract && !isDragToLast) {
1591
+ let newProperties = effectedAbstracts.get(correspondingAbstract);
1592
+ if (!newProperties) {
1593
+ newProperties = { start: 0, end: 0 };
1594
+ effectedAbstracts.set(correspondingAbstract, newProperties);
1595
+ }
1596
+ newProperties.end = newProperties.end + step;
1597
+ }
1598
+ return effectedAbstracts;
1599
+ };
1600
+ const deleteElementHandleAbstract = (board, deletableElements, effectedAbstracts = new Map()) => {
1601
+ deletableElements.forEach(node => {
1602
+ if (!PlaitMind.isMind(node)) {
1603
+ const behindAbstracts = getBehindAbstracts(node).filter(abstract => !deletableElements.includes(abstract));
1604
+ if (behindAbstracts.length) {
1605
+ behindAbstracts.forEach(abstract => {
1606
+ let newProperties = effectedAbstracts.get(abstract);
1607
+ if (!newProperties) {
1608
+ newProperties = { start: 0, end: 0 };
1609
+ effectedAbstracts.set(abstract, newProperties);
1610
+ }
1611
+ newProperties.start = newProperties.start - 1;
1612
+ newProperties.end = newProperties.end - 1;
1613
+ });
1614
+ }
1615
+ const correspondingAbstract = getCorrespondingAbstract(node);
1616
+ if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
1617
+ let newProperties = effectedAbstracts.get(correspondingAbstract);
1618
+ if (!newProperties) {
1619
+ newProperties = { start: 0, end: 0 };
1620
+ effectedAbstracts.set(correspondingAbstract, newProperties);
1621
+ }
1622
+ newProperties.end = newProperties.end - 1;
1623
+ }
1624
+ }
1625
+ });
1626
+ return effectedAbstracts;
2072
1627
  };
2073
1628
 
2074
- const NodeDefaultSpace = {
2075
- horizontal: {
2076
- nodeAndText: BASE * 3,
2077
- emojiAndText: BASE * 1.5
2078
- },
2079
- vertical: {
2080
- nodeAndText: BASE * 1.5
1629
+ var AbstractHandlePosition;
1630
+ (function (AbstractHandlePosition) {
1631
+ AbstractHandlePosition["start"] = "start";
1632
+ AbstractHandlePosition["end"] = "end";
1633
+ })(AbstractHandlePosition || (AbstractHandlePosition = {}));
1634
+ var AbstractResizeState;
1635
+ (function (AbstractResizeState) {
1636
+ AbstractResizeState["start"] = "start";
1637
+ AbstractResizeState["resizing"] = "resizing";
1638
+ AbstractResizeState["end"] = "end";
1639
+ })(AbstractResizeState || (AbstractResizeState = {}));
1640
+
1641
+ const getRectangleByResizingLocation = (abstractRectangle, location, activeHandlePosition, isHorizontal) => {
1642
+ if (isHorizontal) {
1643
+ if (activeHandlePosition === AbstractHandlePosition.start) {
1644
+ return Object.assign(Object.assign({}, abstractRectangle), { y: location, height: abstractRectangle.height + abstractRectangle.y - location });
1645
+ }
1646
+ else {
1647
+ return Object.assign(Object.assign({}, abstractRectangle), { height: location - abstractRectangle.y });
1648
+ }
1649
+ }
1650
+ else {
1651
+ if (activeHandlePosition === AbstractHandlePosition.start) {
1652
+ return Object.assign(Object.assign({}, abstractRectangle), { x: location, width: abstractRectangle.width + abstractRectangle.x - location });
1653
+ }
1654
+ else {
1655
+ return Object.assign(Object.assign({}, abstractRectangle), { width: location - abstractRectangle.x });
1656
+ }
1657
+ }
1658
+ };
1659
+ const getLocationScope = (board, handlePosition, parentChildren, element, parent, isHorizontal) => {
1660
+ const node = MindElement.getNode(element);
1661
+ const { start, end } = getCorrectStartEnd(node.origin, parent);
1662
+ const startNode = parentChildren[start];
1663
+ const endNode = parentChildren[end];
1664
+ if (handlePosition === AbstractHandlePosition.start) {
1665
+ const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.end < element.start);
1666
+ let minNode;
1667
+ if (abstractNode.length) {
1668
+ const index = abstractNode
1669
+ .map(node => {
1670
+ const { end } = getCorrectStartEnd(node, parent);
1671
+ return end;
1672
+ })
1673
+ .sort((a, b) => b - a)[0];
1674
+ minNode = parentChildren[index + 1];
1675
+ }
1676
+ else {
1677
+ minNode = parentChildren[0];
1678
+ }
1679
+ const minNodeRectangle = getRectangleByElements(board, [minNode], true);
1680
+ const endNodeRectangle = getRectangleByElements(board, [endNode], false);
1681
+ if (isHorizontal) {
1682
+ return {
1683
+ max: endNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1684
+ min: minNodeRectangle.y - ABSTRACT_INCLUDED_OUTLINE_OFFSET
1685
+ };
1686
+ }
1687
+ else {
1688
+ return {
1689
+ max: endNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1690
+ min: minNodeRectangle.x - ABSTRACT_INCLUDED_OUTLINE_OFFSET
1691
+ };
1692
+ }
1693
+ }
1694
+ else {
1695
+ const abstractNode = parentChildren.filter(child => AbstractNode.isAbstract(child) && child.start > element.end);
1696
+ let maxNode;
1697
+ if (abstractNode.length) {
1698
+ const index = abstractNode
1699
+ .map(node => {
1700
+ const { start } = getCorrectStartEnd(node, parent);
1701
+ return start;
1702
+ })
1703
+ .sort((a, b) => a - b)[0];
1704
+ maxNode = parentChildren[index - 1];
1705
+ }
1706
+ else {
1707
+ const children = parentChildren.filter(child => !AbstractNode.isAbstract(child));
1708
+ maxNode = parentChildren[children.length - 1];
1709
+ }
1710
+ const maxNodeRectangle = getRectangleByElements(board, [maxNode], true);
1711
+ const startNodeRectangle = getRectangleByElements(board, [startNode], false);
1712
+ if (isHorizontal) {
1713
+ return {
1714
+ max: maxNodeRectangle.y + maxNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1715
+ min: startNodeRectangle.y + startNodeRectangle.height + ABSTRACT_INCLUDED_OUTLINE_OFFSET
1716
+ };
1717
+ }
1718
+ else {
1719
+ return {
1720
+ max: maxNodeRectangle.x + maxNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET,
1721
+ min: startNodeRectangle.x + startNodeRectangle.width + ABSTRACT_INCLUDED_OUTLINE_OFFSET
1722
+ };
1723
+ }
1724
+ }
1725
+ };
1726
+ const getHitAbstractHandle = (board, element, point) => {
1727
+ const nodeLayout = MindQueries.getCorrectLayoutByElement(board, element);
1728
+ const isHorizontal = isHorizontalLayout(nodeLayout);
1729
+ const parentElement = MindElement.getParent(element);
1730
+ const includedElements = parentElement.children.slice(element.start, element.end + 1);
1731
+ let abstractRectangle = getRectangleByElements(board, includedElements, true);
1732
+ abstractRectangle = RectangleClient.getOutlineRectangle(abstractRectangle, -ABSTRACT_INCLUDED_OUTLINE_OFFSET);
1733
+ const startHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.start);
1734
+ const endHandleRec = getAbstractHandleRectangle(abstractRectangle, isHorizontal, AbstractHandlePosition.end);
1735
+ const pointRec = RectangleClient.toRectangleClient([point, point]);
1736
+ if (RectangleClient.isHit(pointRec, startHandleRec))
1737
+ return AbstractHandlePosition.start;
1738
+ if (RectangleClient.isHit(pointRec, endHandleRec))
1739
+ return AbstractHandlePosition.end;
1740
+ return undefined;
1741
+ };
1742
+ const getAbstractHandleRectangle = (rectangle, isHorizontal, position) => {
1743
+ let result;
1744
+ if (position === AbstractHandlePosition.start) {
1745
+ const location = isHorizontal ? rectangle.y : rectangle.x;
1746
+ result = getRectangleByResizingLocation(rectangle, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.end, isHorizontal);
1747
+ result = getRectangleByResizingLocation(result, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
1748
+ }
1749
+ else {
1750
+ const location = isHorizontal ? rectangle.y + rectangle.height : rectangle.x + rectangle.width;
1751
+ result = getRectangleByResizingLocation(rectangle, location - ABSTRACT_HANDLE_MASK_WIDTH / 2, AbstractHandlePosition.start, isHorizontal);
1752
+ result = getRectangleByResizingLocation(result, location + ABSTRACT_HANDLE_MASK_WIDTH / 2, position, isHorizontal);
1753
+ }
1754
+ return result;
1755
+ };
1756
+ function findLocationLeftIndex(board, parentChildren, location, isHorizontal) {
1757
+ const children = parentChildren.filter(child => {
1758
+ return !AbstractNode.isAbstract(child);
1759
+ });
1760
+ const recArray = children.map(child => {
1761
+ return getRectangleByElements(board, [child], false);
1762
+ });
1763
+ const firstRec = getRectangleByElements(board, [children[0]], true);
1764
+ const fakeLeftRec = {
1765
+ x: firstRec.x - firstRec.width,
1766
+ y: firstRec.y - firstRec.height,
1767
+ width: firstRec.width,
1768
+ height: firstRec.height
1769
+ };
1770
+ const lastRec = getRectangleByElements(board, [children[children.length - 1]], true);
1771
+ const fakeRightRec = {
1772
+ x: lastRec.x + lastRec.width,
1773
+ y: lastRec.y + lastRec.height,
1774
+ width: lastRec.width,
1775
+ height: lastRec.height
1776
+ };
1777
+ recArray.push(fakeRightRec);
1778
+ recArray.unshift(fakeLeftRec);
1779
+ for (let i = 0; i < recArray.length - 1; i++) {
1780
+ const recXOrY = isHorizontal ? recArray[i].y : recArray[i].x;
1781
+ const recWidthOrHeight = isHorizontal ? recArray[i].height : recArray[i].width;
1782
+ if (location >= recXOrY + recWidthOrHeight / 2 &&
1783
+ location <= recArray[i + 1][isHorizontal ? 'y' : 'x'] + recArray[i + 1][isHorizontal ? 'height' : 'width'] / 2) {
1784
+ return i - 1;
1785
+ }
1786
+ }
1787
+ return 0;
1788
+ }
1789
+ function handleTouchedAbstract(board, touchedAbstract, endPoint) {
1790
+ let touchedHandle;
1791
+ const abstract = getSelectedElements(board)
1792
+ .filter(element => AbstractNode.isAbstract(element))
1793
+ .find(element => {
1794
+ touchedHandle = getHitAbstractHandle(board, element, endPoint);
1795
+ return touchedHandle;
1796
+ });
1797
+ if (touchedAbstract === abstract) {
1798
+ return touchedAbstract;
2081
1799
  }
2082
- };
2083
- const RootDefaultSpace = {
2084
- horizontal: {
2085
- nodeAndText: BASE * 4,
2086
- emojiAndText: BASE * 2
2087
- },
2088
- vertical: {
2089
- nodeAndText: BASE * 2
1800
+ if (touchedAbstract) {
1801
+ const component = PlaitElement.getComponent(touchedAbstract);
1802
+ component.updateAbstractIncludedOutline();
1803
+ touchedAbstract = undefined;
2090
1804
  }
2091
- };
2092
- const getHorizontalSpaceBetweenNodeAndText = (board, element) => {
2093
- const isMind = PlaitMind.isMind(element);
2094
- const nodeAndText = isMind ? RootDefaultSpace.horizontal.nodeAndText : NodeDefaultSpace.horizontal.nodeAndText;
2095
- return nodeAndText;
2096
- };
2097
- const getVerticalSpaceBetweenNodeAndText = (element) => {
2098
- const isMind = PlaitMind.isMind(element);
2099
- const nodeAndText = isMind ? RootDefaultSpace.vertical.nodeAndText : NodeDefaultSpace.vertical.nodeAndText;
2100
- return nodeAndText;
2101
- };
2102
- const getSpaceEmojiAndText = (element) => {
2103
- const isMind = PlaitMind.isMind(element);
2104
- const emojiAndText = isMind ? RootDefaultSpace.horizontal.emojiAndText : NodeDefaultSpace.horizontal.emojiAndText;
2105
- return emojiAndText;
2106
- };
2107
- const NodeSpace = {
2108
- getNodeWidth(board, element) {
2109
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
2110
- if (MindElement.hasEmojis(element)) {
2111
- return (NodeSpace.getEmojiLeftSpace(board, element) +
2112
- getEmojisWidthHeight(board, element).width +
2113
- getSpaceEmojiAndText(element) +
2114
- element.width +
2115
- nodeAndText);
2116
- }
2117
- return nodeAndText + element.width + nodeAndText;
2118
- },
2119
- getNodeHeight(element) {
2120
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
2121
- return nodeAndText + element.height + nodeAndText;
2122
- },
2123
- getTextLeftSpace(board, element) {
2124
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
2125
- if (MindElement.hasEmojis(element)) {
2126
- return NodeSpace.getEmojiLeftSpace(board, element) + getEmojisWidthHeight(board, element).width + getSpaceEmojiAndText(element);
1805
+ if (abstract) {
1806
+ touchedAbstract = abstract;
1807
+ const component = PlaitElement.getComponent(touchedAbstract);
1808
+ component.updateAbstractIncludedOutline(touchedHandle);
1809
+ }
1810
+ return touchedAbstract;
1811
+ }
1812
+
1813
+ function drawIndentedLink(board, node, child, defaultStroke = null, needDrawUnderline = true, defaultStrokeWidth) {
1814
+ const branchWidth = defaultStrokeWidth || getBranchWidthByMindElement(board, child.origin);
1815
+ const branchColor = defaultStroke || getBranchColorByMindElement(board, child.origin);
1816
+ const isUnderlineShape = getShapeByElement(board, child.origin) === MindElementShape.underline;
1817
+ let beginX, beginY, endX, endY, beginNode = node, endNode = child;
1818
+ const beginRectangle = getRectangleByNode(beginNode);
1819
+ const endRectangle = getRectangleByNode(endNode);
1820
+ beginX = beginNode.x + beginNode.width / 2;
1821
+ beginY = isChildUp(node, child) ? beginRectangle.y : beginRectangle.y + beginRectangle.height;
1822
+ endX = node.left ? endNode.x + endNode.hGap + endRectangle.width : endNode.x + endNode.hGap;
1823
+ endY = isUnderlineShape ? endNode.y + endNode.height - endNode.vGap : endNode.y + endNode.height / 2;
1824
+ //根据位置,设置正负参数
1825
+ let plusMinus = isChildUp(node, child) ? (node.left ? [-1, -1] : [1, -1]) : node.left ? [-1, 1] : [1, 1];
1826
+ const layout = MindQueries.getCorrectLayoutByElement(board, node.origin);
1827
+ if (beginNode.origin.isRoot) {
1828
+ if (layout === MindLayoutType.leftBottomIndented || layout === MindLayoutType.rightBottomIndented) {
1829
+ beginY += branchWidth;
2127
1830
  }
2128
- else {
2129
- return nodeAndText;
1831
+ if (layout === MindLayoutType.leftTopIndented || layout === MindLayoutType.rightTopIndented) {
1832
+ beginY -= branchWidth;
2130
1833
  }
2131
- },
2132
- getTextTopSpace(element) {
2133
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
2134
- return nodeAndText;
2135
- },
2136
- getEmojiLeftSpace(board, element) {
2137
- const options = board.getMindOptions();
2138
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
2139
- return nodeAndText - options.emojiPadding;
2140
- },
2141
- getEmojiTopSpace(element) {
2142
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
2143
- return nodeAndText;
2144
1834
  }
2145
- };
1835
+ let curve = [
1836
+ [beginX, beginY],
1837
+ [beginX, beginY],
1838
+ [beginX, beginY],
1839
+ [beginX, endY - (endNode.hGap * 3 * plusMinus[1]) / 5],
1840
+ [beginX, endY - (endNode.hGap * plusMinus[1]) / 5],
1841
+ [beginX + (endNode.hGap * plusMinus[0]) / 4, endY],
1842
+ [beginX + (endNode.hGap * plusMinus[0] * 3) / 5, endY],
1843
+ isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
1844
+ isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY],
1845
+ isUnderlineShape && needDrawUnderline ? [endX + (endNode.width - endNode.hGap * 2) * plusMinus[0], endY] : [endX, endY]
1846
+ ];
1847
+ const points = pointsOnBezierCurves(curve);
1848
+ return PlaitBoard.getRoughSVG(board).curve(points, { stroke: branchColor, strokeWidth: branchWidth });
1849
+ }
2146
1850
 
2147
- function drawMindNodeRichtext(board, node, viewContainerRef) {
2148
- var _a, _b;
2149
- const { x, y, width, height } = getRichtextRectangleByNode(board, node);
1851
+ function drawTopicByNode(board, node, viewContainerRef) {
1852
+ const rectangle = getTopicRectangleByNode(board, node);
1853
+ return drawTopicByElement(board, rectangle, node.origin, viewContainerRef);
1854
+ }
1855
+ function drawTopicByElement(board, rectangle, element, viewContainerRef) {
1856
+ const containerRef = viewContainerRef || PlaitBoard.getComponent(board).viewContainerRef;
2150
1857
  const classList = [];
2151
- if (node.origin.isRoot) {
1858
+ if (element.isRoot) {
2152
1859
  classList.push('root-node');
2153
1860
  classList.push('font-size-18');
2154
1861
  }
2155
- else if ((_b = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.origin) === null || _b === void 0 ? void 0 : _b.isRoot) {
2156
- classList.push('root-child-node');
2157
- }
2158
1862
  else {
2159
1863
  classList.push('child-node');
2160
1864
  }
2161
1865
  // COMPAT: last character can not show in safari browser
2162
- return drawRichtext(x, y, width, height, node.origin.data.topic, viewContainerRef, classList);
1866
+ return drawRichtext(rectangle.x, rectangle.y, rectangle.width, rectangle.height, element.data.topic, containerRef, classList);
2163
1867
  }
2164
1868
  function updateMindNodeTopicSize(board, node, g, isEditable) {
2165
- const { x, y, width, height } = getRichtextRectangleByNode(board, node);
1869
+ const { x, y, width, height } = getTopicRectangleByNode(board, node);
2166
1870
  if (isEditable) {
2167
1871
  // add 999, avoid changing lines when paste more text
2168
1872
  updateForeignObject(g, width + 999, height + 999, x, y);
@@ -2172,28 +1876,6 @@ function updateMindNodeTopicSize(board, node, g, isEditable) {
2172
1876
  updateForeignObject(g, width, height, x, y);
2173
1877
  }
2174
1878
  }
2175
- function getRichtextRectangleByNode(board, node) {
2176
- let { x, y } = getRectangleByNode(node);
2177
- x = x + NodeSpace.getTextLeftSpace(board, node.origin);
2178
- y = y + NodeSpace.getTextTopSpace(node.origin);
2179
- const width = Math.ceil(node.origin.width);
2180
- const height = Math.ceil(node.origin.height);
2181
- return { height, width, x, y };
2182
- }
2183
-
2184
- function drawRectangleNode(board, node) {
2185
- const { x, y, width, height } = getRectangleByNode(node);
2186
- const fill = node.origin.fill ? node.origin.fill : node.origin.isRoot ? DefaultRootStyle.fill : DefaultNodeStyle.fill;
2187
- const stroke = getStrokeByMindElement(board, node.origin);
2188
- const strokeWidth = node.origin.strokeWidth ? node.origin.strokeWidth : DefaultNodeStyle.strokeWidth;
2189
- const nodeG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), x, y, x + width, y + height, {
2190
- stroke,
2191
- strokeWidth,
2192
- fill,
2193
- fillStyle: 'solid'
2194
- });
2195
- return nodeG;
2196
- }
2197
1879
 
2198
1880
  function drawAbstractLink(board, node, isHorizontal) {
2199
1881
  const linkPadding = 15;
@@ -2215,18 +1897,12 @@ function drawAbstractLink(board, node, isHorizontal) {
2215
1897
  let bezierBeginPoint = getPointByPlacement(includedElementsRectangle, bezierBeginPlacement);
2216
1898
  let bezierEndPoint = getPointByPlacement(includedElementsRectangle, bezierEndPlacement);
2217
1899
  let abstractConnectorPoint = getPointByPlacement(abstractRectangle, abstractConnectorPlacement);
2218
- let curveDistance = 0;
2219
- if (isHorizontal) {
2220
- curveDistance = Math.abs(abstractConnectorPoint[0] - bezierBeginPoint[0]) - linkPadding * 2;
2221
- }
2222
- else {
2223
- curveDistance = Math.abs(abstractConnectorPoint[1] - bezierBeginPoint[1]) - linkPadding * 2;
2224
- }
2225
- bezierBeginPoint = movePoint(bezierBeginPoint, linkPadding, linkDirection);
2226
- let c1 = movePoint(bezierBeginPoint, curveDistance, linkDirection);
2227
- bezierEndPoint = movePoint(bezierEndPoint, linkPadding, linkDirection);
2228
- let c2 = movePoint(bezierEndPoint, curveDistance, linkDirection);
2229
- let bezierConnectorPoint = movePoint(abstractConnectorPoint, -linkPadding, linkDirection);
1900
+ let curveDistance = getXDistanceBetweenPoint(abstractConnectorPoint, bezierBeginPoint, isHorizontal) - linkPadding * 2;
1901
+ bezierBeginPoint = moveXOfPoint(bezierBeginPoint, linkPadding, linkDirection);
1902
+ let c1 = moveXOfPoint(bezierBeginPoint, curveDistance, linkDirection);
1903
+ bezierEndPoint = moveXOfPoint(bezierEndPoint, linkPadding, linkDirection);
1904
+ let c2 = moveXOfPoint(bezierEndPoint, curveDistance, linkDirection);
1905
+ let bezierConnectorPoint = moveXOfPoint(abstractConnectorPoint, -linkPadding, linkDirection);
2230
1906
  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]}`, {
2231
1907
  stroke: branchColor,
2232
1908
  strokeWidth: branchWidth
@@ -2270,37 +1946,235 @@ class EmojisDrawer {
2270
1946
  this.viewContainerRef = viewContainerRef;
2271
1947
  this.emojiDrawers = [];
2272
1948
  }
2273
- drawEmojis(element) {
2274
- this.destroy();
2275
- if (MindElement.hasEmojis(element)) {
2276
- this.g = createG();
2277
- this.g.classList.add('emojis');
2278
- const foreignRectangle = getEmojiForeignRectangle(this.board, element);
2279
- const foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
2280
- this.g.append(foreignObject);
2281
- const container = document.createElement('div');
2282
- container.classList.add('node-emojis-container');
2283
- foreignObject.append(container);
2284
- this.emojiDrawers = element.data.emojis.map(emojiItem => {
2285
- const drawer = new EmojiDrawer(this.board, this.viewContainerRef);
2286
- drawer.draw(emojiItem, element);
2287
- return drawer;
2288
- });
2289
- this.emojiDrawers.forEach(drawer => {
2290
- container.append(drawer.nativeElement);
2291
- });
2292
- return this.g;
1949
+ drawEmojis(element) {
1950
+ this.destroy();
1951
+ if (MindElement.hasEmojis(element)) {
1952
+ this.g = createG();
1953
+ this.g.classList.add('emojis');
1954
+ const foreignRectangle = getEmojiForeignRectangle(this.board, element);
1955
+ const foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
1956
+ this.g.append(foreignObject);
1957
+ const container = document.createElement('div');
1958
+ container.classList.add('node-emojis-container');
1959
+ foreignObject.append(container);
1960
+ this.emojiDrawers = element.data.emojis.map(emojiItem => {
1961
+ const drawer = new EmojiDrawer(this.board, this.viewContainerRef);
1962
+ drawer.draw(emojiItem, element);
1963
+ return drawer;
1964
+ });
1965
+ this.emojiDrawers.forEach(drawer => {
1966
+ container.append(drawer.nativeElement);
1967
+ });
1968
+ return this.g;
1969
+ }
1970
+ return undefined;
1971
+ }
1972
+ destroy() {
1973
+ if (this.g) {
1974
+ this.g.remove();
1975
+ }
1976
+ this.emojiDrawers.forEach(drawer => drawer.destroy());
1977
+ this.emojiDrawers = [];
1978
+ }
1979
+ }
1980
+
1981
+ const setAbstractsByRefs = (board, abstractRefs) => {
1982
+ abstractRefs.forEach((newProperty, element) => {
1983
+ const start = element.start + newProperty.start;
1984
+ const end = element.end + newProperty.end;
1985
+ const path = PlaitBoard.findPath(board, element);
1986
+ if (start > end) {
1987
+ Transforms.removeNode(board, path);
1988
+ }
1989
+ else {
1990
+ Transforms.setNode(board, { start, end }, path);
1991
+ }
1992
+ });
1993
+ };
1994
+ const setAbstractByStandardLayout = (board, element) => {
1995
+ const rightNodeCount = element.rightNodeCount;
1996
+ const abstract = element.children.find(child => {
1997
+ return AbstractNode.isAbstract(child) && child.end >= rightNodeCount && child.start < rightNodeCount;
1998
+ });
1999
+ if (abstract) {
2000
+ const path = PlaitBoard.findPath(board, abstract);
2001
+ Transforms.setNode(board, { end: rightNodeCount - 1 }, path);
2002
+ }
2003
+ };
2004
+ const insertAbstract = (board, elements) => {
2005
+ let elementGroup = getFirstLevelElement(elements);
2006
+ const { parentElements, abstractIncludedGroups } = divideElementByParent(elementGroup);
2007
+ abstractIncludedGroups.forEach((group, index) => {
2008
+ const groupParent = parentElements[index];
2009
+ setAbstractByElements(board, groupParent, group);
2010
+ });
2011
+ };
2012
+ const setAbstractByElements = (board, groupParent, group) => {
2013
+ const indexArray = group.map(child => groupParent.children.indexOf(child)).sort((a, b) => a - b);
2014
+ const rightNodeCount = groupParent === null || groupParent === void 0 ? void 0 : groupParent.rightNodeCount;
2015
+ const start = indexArray[0], end = indexArray[indexArray.length - 1];
2016
+ if (isStandardLayout(MindQueries.getLayoutByElement(groupParent)) &&
2017
+ rightNodeCount &&
2018
+ start < rightNodeCount &&
2019
+ end >= rightNodeCount) {
2020
+ const childrenLength = groupParent.children.length;
2021
+ const path = [...PlaitBoard.findPath(board, groupParent), childrenLength];
2022
+ const leftChildren = indexArray.filter(index => index >= rightNodeCount);
2023
+ const rightChildren = indexArray.filter(index => index < rightNodeCount);
2024
+ insertAbstractNode(board, path, rightChildren[0], rightChildren[rightChildren.length - 1]);
2025
+ insertAbstractNode(board, Path.next(path), leftChildren[0], leftChildren[leftChildren.length - 1]);
2026
+ }
2027
+ else {
2028
+ const path = [...PlaitBoard.findPath(board, groupParent), groupParent.children.length];
2029
+ insertAbstractNode(board, path, start, end);
2030
+ }
2031
+ };
2032
+ const insertAbstractNode = (board, path, start, end) => {
2033
+ const mindElement = createMindElement('概要', 28, 20, {
2034
+ strokeColor: DefaultAbstractNodeStyle.strokeColor,
2035
+ strokeWidth: DefaultAbstractNodeStyle.branchWidth,
2036
+ branchColor: DefaultAbstractNodeStyle.branchColor,
2037
+ branchWidth: DefaultAbstractNodeStyle.branchWidth
2038
+ });
2039
+ mindElement.start = start;
2040
+ mindElement.end = end;
2041
+ Transforms.insertNode(board, mindElement, path);
2042
+ };
2043
+
2044
+ const setLayout = (board, layout, path) => {
2045
+ correctLogicLayoutNode(board, layout, path);
2046
+ const element = PlaitNode.get(board, path);
2047
+ if (PlaitMind.isMind(element) && isStandardLayout(layout)) {
2048
+ MindTransforms.setAbstractByStandardLayout(board, element);
2049
+ }
2050
+ Transforms.setNode(board, { layout }, path);
2051
+ };
2052
+ const correctLogicLayoutNode = (board, layout, path) => {
2053
+ var _a;
2054
+ const node = PlaitNode.get(board, path);
2055
+ if (node && layout) {
2056
+ (_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach((value, index) => {
2057
+ var _a;
2058
+ if (value.layout) {
2059
+ if ((isHorizontalLogicLayout(layout) && isVerticalLogicLayout(value.layout)) ||
2060
+ (isVerticalLogicLayout(layout) && isHorizontalLogicLayout(value.layout))) {
2061
+ Transforms.setNode(board, { layout: null }, [...path, index]);
2062
+ }
2063
+ if ((_a = value.children) === null || _a === void 0 ? void 0 : _a.length) {
2064
+ correctLogicLayoutNode(board, layout, [...path, index]);
2065
+ }
2066
+ }
2067
+ });
2068
+ }
2069
+ };
2070
+
2071
+ const setTopic = (board, element, topic, width, height) => {
2072
+ const newElement = {
2073
+ data: { topic },
2074
+ width: width < NODE_MIN_WIDTH * board.viewport.zoom ? NODE_MIN_WIDTH : width / board.viewport.zoom,
2075
+ height: height / board.viewport.zoom
2076
+ };
2077
+ if (MindElement.hasEmojis(element)) {
2078
+ newElement.data.emojis = element.data.emojis;
2079
+ }
2080
+ const path = PlaitBoard.findPath(board, element);
2081
+ Transforms.setNode(board, newElement, path);
2082
+ };
2083
+ const setTopicSize = (board, element, width, height) => {
2084
+ const newElement = {
2085
+ width: width < NODE_MIN_WIDTH * board.viewport.zoom ? NODE_MIN_WIDTH : width / board.viewport.zoom,
2086
+ height: height / board.viewport.zoom
2087
+ };
2088
+ const path = PlaitBoard.findPath(board, element);
2089
+ Transforms.setNode(board, newElement, path);
2090
+ };
2091
+ const removeElements = (board, elements) => {
2092
+ const deletableElements = getFirstLevelElement(elements).reverse();
2093
+ //翻转,从下到上修改,防止找不到 path
2094
+ deletableElements
2095
+ .map(element => {
2096
+ const path = PlaitBoard.findPath(board, element);
2097
+ return () => {
2098
+ if (isInRightBranchOfStandardLayout(element)) {
2099
+ changeRightNodeCount(board, path.slice(0, 1), -1);
2100
+ }
2101
+ Transforms.removeNode(board, path);
2102
+ };
2103
+ })
2104
+ .forEach(action => {
2105
+ action();
2106
+ });
2107
+ };
2108
+ const insertNodes = (board, elements, path) => {
2109
+ const pathRef = board.pathRef(path);
2110
+ elements.forEach(element => {
2111
+ if (pathRef.current) {
2112
+ Transforms.insertNode(board, element, pathRef.current);
2293
2113
  }
2294
- return undefined;
2114
+ });
2115
+ pathRef.unref();
2116
+ };
2117
+ const insertAbstractNodes = (board, validAbstractRefs, elements, path) => {
2118
+ var _a;
2119
+ const parent = PlaitNode.get(board, Path$1.parent(path));
2120
+ const abstractPath = [...Path$1.parent(path), (_a = parent.children) === null || _a === void 0 ? void 0 : _a.length];
2121
+ const abstracts = validAbstractRefs.map(refs => {
2122
+ const { start, end } = getRelativeStartEndByAbstractRef(refs, elements);
2123
+ return Object.assign(Object.assign({}, refs.abstract), { start: start + path[path.length - 1], end: end + path[path.length - 1] });
2124
+ });
2125
+ insertNodes(board, abstracts, abstractPath);
2126
+ };
2127
+
2128
+ const addEmoji = (board, element, emojiItem) => {
2129
+ const emojis = element.data.emojis || [];
2130
+ const newEmojis = [...emojis];
2131
+ newEmojis.push(emojiItem);
2132
+ const newElement = {
2133
+ data: { topic: element.data.topic, emojis: newEmojis }
2134
+ };
2135
+ const path = PlaitBoard.findPath(board, element);
2136
+ Transforms.setNode(board, newElement, path);
2137
+ };
2138
+ const removeEmoji = (board, element, emojiItem) => {
2139
+ const emojis = element.data.emojis.filter(value => value !== emojiItem);
2140
+ const newElement = {
2141
+ data: { topic: element.data.topic }
2142
+ };
2143
+ if (emojis.length > 0) {
2144
+ newElement.data.emojis = emojis;
2295
2145
  }
2296
- destroy() {
2297
- if (this.g) {
2298
- this.g.remove();
2146
+ const path = PlaitBoard.findPath(board, element);
2147
+ Transforms.setNode(board, newElement, path);
2148
+ };
2149
+ const replaceEmoji = (board, element, oldEmoji, newEmoji) => {
2150
+ const newElement = {
2151
+ data: { topic: element.data.topic }
2152
+ };
2153
+ const newEmojis = element.data.emojis.map(value => {
2154
+ if (value === oldEmoji) {
2155
+ return newEmoji;
2299
2156
  }
2300
- this.emojiDrawers.forEach(drawer => drawer.destroy());
2301
- this.emojiDrawers = [];
2302
- }
2303
- }
2157
+ return value;
2158
+ });
2159
+ newElement.data.emojis = newEmojis;
2160
+ const path = PlaitBoard.findPath(board, element);
2161
+ Transforms.setNode(board, newElement, path);
2162
+ };
2163
+
2164
+ const MindTransforms = {
2165
+ setLayout,
2166
+ setTopic,
2167
+ setTopicSize,
2168
+ addEmoji,
2169
+ removeEmoji,
2170
+ replaceEmoji,
2171
+ insertAbstract,
2172
+ setAbstractsByRefs,
2173
+ setAbstractByStandardLayout,
2174
+ removeElements,
2175
+ insertNodes,
2176
+ insertAbstractNodes
2177
+ };
2304
2178
 
2305
2179
  function drawAbstractIncludedOutline(board, roughSVG, element, activeHandlePosition, resizingLocation) {
2306
2180
  const abstractIncludedG = createG();
@@ -2325,10 +2199,10 @@ function drawAbstractIncludedOutline(board, roughSVG, element, activeHandlePosit
2325
2199
  transformPlacement(endPlacement, linkDirection);
2326
2200
  let startCenterPoint = getPointByPlacement(abstractRectangle, startPlacement);
2327
2201
  let endCenterPoint = getPointByPlacement(abstractRectangle, endPlacement);
2328
- const startPoint1 = movePoint(startCenterPoint, -ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
2329
- const startPoint2 = movePoint(startCenterPoint, ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
2330
- const endPoint1 = movePoint(endCenterPoint, -ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
2331
- const endPoint2 = movePoint(endCenterPoint, ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
2202
+ const startPoint1 = moveXOfPoint(startCenterPoint, -ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
2203
+ const startPoint2 = moveXOfPoint(startCenterPoint, ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
2204
+ const endPoint1 = moveXOfPoint(endCenterPoint, -ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
2205
+ const endPoint2 = moveXOfPoint(endCenterPoint, ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
2332
2206
  const startHandle = roughSVG.line(startPoint1[0], startPoint1[1], startPoint2[0], startPoint2[1], getHandleOption(activeHandlePosition === AbstractHandlePosition.start));
2333
2207
  const endHandle = roughSVG.line(endPoint1[0], endPoint1[1], endPoint2[0], endPoint2[1], getHandleOption(activeHandlePosition === AbstractHandlePosition.end));
2334
2208
  changeBoardClass(board, activeHandlePosition, isHorizontal);
@@ -2681,7 +2555,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2681
2555
  const shape = getShapeByElement(this.board, this.node.origin);
2682
2556
  switch (shape) {
2683
2557
  case MindElementShape.roundRectangle:
2684
- this.shapeG = drawRectangleNode(this.board, this.node);
2558
+ this.shapeG = drawRoundRectangleByNode(this.board, this.node);
2685
2559
  this.g.prepend(this.shapeG);
2686
2560
  break;
2687
2561
  default:
@@ -2838,7 +2712,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2838
2712
  }
2839
2713
  }
2840
2714
  drawRichtext() {
2841
- const { richtextG, richtextComponentRef, foreignObject } = drawMindNodeRichtext(this.board, this.node, this.viewContainerRef);
2715
+ const { richtextG, richtextComponentRef, foreignObject } = drawTopicByNode(this.board, this.node, this.viewContainerRef);
2842
2716
  this.richtextComponentRef = richtextComponentRef;
2843
2717
  this.richtextG = richtextG;
2844
2718
  this.foreignObject = foreignObject;
@@ -2859,7 +2733,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2859
2733
  }
2860
2734
  // interactive
2861
2735
  fromEvent(collapseG, 'mouseup')
2862
- .pipe(filter(() => !this.handActive || this.board.options.readonly), take(1))
2736
+ .pipe(filter(() => !this.handActive || !PlaitBoard.isReadonly(this.board)), take(1))
2863
2737
  .subscribe(() => {
2864
2738
  const isCollapsed = !this.node.origin.isCollapsed;
2865
2739
  const newElement = { isCollapsed };
@@ -3041,7 +2915,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
3041
2915
  });
3042
2916
  const mousedown$ = fromEvent(document, 'mousedown').subscribe((event) => {
3043
2917
  const point = transformPoint(this.board, toPoint(event.x, event.y, PlaitBoard.getHost(this.board)));
3044
- const clickInNode = hitMindElement(this.board, point, this.element);
2918
+ const clickInNode = isHitMindElement(this.board, point, this.element);
3045
2919
  if (clickInNode && !hasEditableTarget(richtextInstance.editor, event.target)) {
3046
2920
  event.preventDefault();
3047
2921
  }
@@ -3106,6 +2980,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
3106
2980
  super.ngOnDestroy();
3107
2981
  (_a = this.abstractIncludedOutlineG) === null || _a === void 0 ? void 0 : _a.remove();
3108
2982
  this.destroyRichtext();
2983
+ this.emojisDrawer.destroy();
3109
2984
  this.destroy$.next();
3110
2985
  this.destroy$.complete();
3111
2986
  if (ELEMENT_TO_NODE.get(this.element) === this.node) {
@@ -3160,7 +3035,7 @@ const getLayoutOptions = (board) => {
3160
3035
  }
3161
3036
  return {
3162
3037
  getHeight(element) {
3163
- return NodeSpace.getNodeHeight(element);
3038
+ return NodeSpace.getNodeHeight(board, element);
3164
3039
  },
3165
3040
  getWidth(element) {
3166
3041
  return NodeSpace.getNodeWidth(board, element);
@@ -3251,142 +3126,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
3251
3126
  class MindModule {
3252
3127
  }
3253
3128
  MindModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3254
- MindModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.5", ngImport: i0, type: MindModule, declarations: [PlaitMindComponent, MindNodeComponent], imports: [BrowserModule, RichtextModule, PlaitModule], exports: [PlaitMindComponent, MindNodeComponent] });
3255
- MindModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, imports: [BrowserModule, RichtextModule, PlaitModule] });
3129
+ 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] });
3130
+ MindModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, imports: [CommonModule, RichtextModule, PlaitModule] });
3256
3131
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, decorators: [{
3257
3132
  type: NgModule,
3258
3133
  args: [{
3259
3134
  declarations: [PlaitMindComponent, MindNodeComponent],
3260
- imports: [BrowserModule, RichtextModule, PlaitModule],
3135
+ imports: [CommonModule, RichtextModule, PlaitModule],
3261
3136
  exports: [PlaitMindComponent, MindNodeComponent]
3262
3137
  }]
3263
3138
  }] });
3264
3139
 
3265
- const isValidTarget = (origin, target) => {
3266
- return origin !== target && !isChildElement(origin, target);
3267
- };
3268
- const addActiveOnDragOrigin = (activeElement, isOrigin = true) => {
3269
- const activeComponent = PlaitElement.getComponent(activeElement);
3270
- if (isOrigin) {
3271
- activeComponent.g.classList.add('dragging-origin');
3272
- }
3273
- else {
3274
- activeComponent.g.classList.add('dragging-child');
3275
- }
3276
- !activeElement.isCollapsed &&
3277
- activeElement.children.forEach(child => {
3278
- addActiveOnDragOrigin(child, false);
3279
- });
3280
- };
3281
- const removeActiveOnDragOrigin = (activeElement, isOrigin = true) => {
3282
- const activeComponent = PlaitElement.getComponent(activeElement);
3283
- if (isOrigin) {
3284
- activeComponent.g.classList.remove('dragging-origin');
3285
- }
3286
- else {
3287
- activeComponent.g.classList.remove('dragging-child');
3288
- }
3289
- !activeElement.isCollapsed &&
3290
- activeElement.children.forEach(child => {
3291
- removeActiveOnDragOrigin(child, false);
3292
- });
3293
- };
3294
- const updatePathByLayoutAndDropTarget = (targetPath, layout, dropTarget) => {
3295
- // 上下布局:左右是兄弟节点,上下是子节点
3296
- if (isVerticalLogicLayout(layout)) {
3297
- if (isTopLayout(layout) && dropTarget.detectResult === 'top') {
3298
- targetPath.push(dropTarget.target.children.length);
3299
- }
3300
- if (isBottomLayout(layout) && dropTarget.detectResult === 'bottom') {
3301
- targetPath.push(dropTarget.target.children.length);
3302
- }
3303
- // 如果是左,位置不变,右则插入到下一个兄弟节点
3304
- if (dropTarget.detectResult === 'right') {
3305
- targetPath = Path.next(targetPath);
3306
- }
3307
- }
3308
- // 水平布局/标准布局:上下是兄弟节点,左右是子节点
3309
- if (isHorizontalLogicLayout(layout)) {
3310
- if (dropTarget.detectResult === 'right') {
3311
- targetPath.push(dropTarget.target.children.length);
3312
- }
3313
- if (dropTarget.detectResult === 'left') {
3314
- targetPath.push(dropTarget.target.children.length);
3315
- }
3316
- // 如果是上,位置不变,下插入到下一个兄弟节点
3317
- if (dropTarget.detectResult === 'bottom') {
3318
- targetPath = Path.next(targetPath);
3319
- }
3320
- }
3321
- // 缩进布局:上下是兄弟节点,左右是子节点,但上(左上/右上),探测到上是子节点,下则位置不变,反之同理。
3322
- if (isIndentedLayout(layout)) {
3323
- if (isTopLayout(layout) && dropTarget.detectResult === 'top') {
3324
- targetPath = Path.next(targetPath);
3325
- }
3326
- if (isBottomLayout(layout) && dropTarget.detectResult === 'bottom') {
3327
- targetPath = Path.next(targetPath);
3328
- }
3329
- if (isLeftLayout(layout) && dropTarget.detectResult === 'left') {
3330
- targetPath.push(dropTarget.target.children.length);
3331
- }
3332
- if (isRightLayout(layout) && dropTarget.detectResult === 'right') {
3333
- targetPath.push(dropTarget.target.children.length);
3334
- }
3335
- }
3336
- return targetPath;
3337
- };
3338
- const updateRightNodeCount = (board, activeComponent, targetComponent, detectResult) => {
3339
- var _a;
3340
- let rightNodeCount;
3341
- const mindElement = findUpElement(targetComponent.node.origin).root;
3342
- const mindComponent = ELEMENT_TO_COMPONENT.get(mindElement);
3343
- const activeIndex = mindComponent === null || mindComponent === void 0 ? void 0 : mindComponent.root.children.indexOf(activeComponent.node);
3344
- const targetIndex = mindComponent === null || mindComponent === void 0 ? void 0 : mindComponent.root.children.indexOf(targetComponent.node);
3345
- const activeParent = MindElement.getParent(activeComponent.element);
3346
- const targetParent = MindElement.findParent(targetComponent.element);
3347
- const isActiveOnRight = activeIndex !== -1 && activeIndex <= activeParent.rightNodeCount - 1;
3348
- const isTargetOnRight = targetParent && targetIndex !== -1 && targetIndex <= targetParent.rightNodeCount - 1;
3349
- const isBothOnRight = isActiveOnRight && isTargetOnRight;
3350
- const rootChildCount = (_a = mindComponent.root.children) === null || _a === void 0 ? void 0 : _a.length;
3351
- const rootRightNodeCount = mindComponent === null || mindComponent === void 0 ? void 0 : mindComponent.root.origin.rightNodeCount;
3352
- if (!isBothOnRight) {
3353
- if (isActiveOnRight) {
3354
- rightNodeCount = rootChildCount < rootRightNodeCount ? rootChildCount - 1 : rootRightNodeCount - 1;
3355
- Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, activeParent));
3356
- }
3357
- if (isTargetOnRight && detectResult !== 'right') {
3358
- rightNodeCount = rootChildCount < rootRightNodeCount ? rootRightNodeCount : rootRightNodeCount + 1;
3359
- const parent = MindElement.getParent(targetComponent.element);
3360
- Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, parent));
3361
- }
3362
- //二级子节点拖动到根节点左侧
3363
- if (targetComponent.node.origin.isRoot && detectResult === 'left' && activeIndex === -1) {
3364
- rightNodeCount = rootChildCount;
3365
- Transforms.setNode(board, { rightNodeCount }, PlaitBoard.findPath(board, targetComponent.element));
3366
- }
3367
- }
3368
- };
3369
- const IS_DRAGGING = new WeakMap();
3370
- const isDragging = (board) => {
3371
- return !!IS_DRAGGING.get(board);
3372
- };
3373
- const setIsDragging = (board, state) => {
3374
- IS_DRAGGING.set(board, state);
3375
- };
3376
- const updateAbstractInDnd = (board, deletableElements, originPath) => {
3377
- const refs = insertElementHandleAbstract(board, originPath, false);
3378
- deleteElementHandleAbstract(board, deletableElements, refs);
3379
- MindTransforms.setAbstractsByRefs(board, refs);
3380
- };
3381
-
3382
3140
  const DRAG_MOVE_BUFFER = 5;
3383
3141
  const withDnd = (board) => {
3384
- const { mousedown, mousemove, globalMouseup, keydown } = board;
3385
- let activeElement;
3142
+ const { mousedown, mousemove, globalMouseup } = board;
3143
+ let activeElements = [];
3144
+ let correspondingElements = [];
3386
3145
  let startPoint;
3387
- let fakeDragNodeG;
3146
+ let dragFakeNodeG;
3388
3147
  let fakeDropNodeG;
3389
3148
  let dropTarget = null;
3149
+ let targetPath;
3390
3150
  board.mousedown = (event) => {
3391
3151
  if (board.options.readonly || IS_TEXT_EDITABLE.get(board) || event.button === 2) {
3392
3152
  mousedown(event);
@@ -3395,152 +3155,137 @@ const withDnd = (board) => {
3395
3155
  // 确认是否 hit 节点
3396
3156
  const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3397
3157
  const selectedElements = getSelectedElements(board);
3398
- board.children.forEach((value) => {
3399
- if (activeElement) {
3158
+ depthFirstRecursion(board, element => {
3159
+ if (activeElements.length || !MindElement.isMindElement(board, element)) {
3400
3160
  return;
3401
3161
  }
3402
- if (PlaitMind.isMind(value)) {
3403
- const mindComponent = ELEMENT_TO_COMPONENT.get(value);
3404
- const root = mindComponent.root;
3405
- root.eachNode((node) => {
3406
- if (activeElement) {
3407
- return;
3408
- }
3409
- const canDrag = hitMindElement(board, point, node.origin) &&
3410
- !node.origin.isRoot &&
3411
- !AbstractNode.isAbstract(node.origin) &&
3412
- selectedElements.length <= 1;
3413
- if (canDrag) {
3414
- activeElement = node.origin;
3415
- startPoint = point;
3416
- }
3417
- });
3162
+ const isHitElement = isHitMindElement(board, point, element) && !element.isRoot && !AbstractNode.isAbstract(element);
3163
+ const isAllMindElement = selectedElements.every(element => MindElement.isMindElement(board, element));
3164
+ const isMultiple = isHitElement && selectedElements.length > 1 && selectedElements.includes(element) && isAllMindElement;
3165
+ const isSingle = isHitElement && !(selectedElements.length > 1 && selectedElements.includes(element));
3166
+ if (isSingle) {
3167
+ activeElements = [element];
3168
+ startPoint = point;
3169
+ }
3170
+ else if (isMultiple) {
3171
+ activeElements = getFirstLevelElement(selectedElements);
3172
+ startPoint = point;
3173
+ }
3174
+ }, node => {
3175
+ if (PlaitBoard.isBoard(node) || board.isRecursion(node)) {
3176
+ return true;
3177
+ }
3178
+ else {
3179
+ return false;
3418
3180
  }
3419
3181
  });
3420
- if (activeElement) {
3421
- event.preventDefault();
3182
+ if (activeElements.length) {
3183
+ correspondingElements = getOverallAbstracts(board, activeElements);
3422
3184
  }
3423
3185
  mousedown(event);
3424
3186
  };
3425
3187
  board.mousemove = (event) => {
3426
- var _a;
3427
- if (!board.options.readonly && activeElement && startPoint) {
3188
+ if (!board.options.readonly && (activeElements === null || activeElements === void 0 ? void 0 : activeElements.length) && startPoint) {
3428
3189
  const endPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3429
3190
  const distance = distanceBetweenPointAndPoint(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
3430
3191
  if (distance < DRAG_MOVE_BUFFER) {
3431
3192
  return;
3432
3193
  }
3433
- if (!isDragging(board)) {
3434
- setIsDragging(board, true);
3435
- fakeDragNodeG = createG();
3436
- fakeDragNodeG.classList.add('dragging', 'fake-node', 'plait-board-attached');
3437
- fakeDropNodeG = createG();
3438
- addActiveOnDragOrigin(activeElement);
3194
+ setIsDragging(board, true);
3195
+ fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.remove();
3196
+ const detectPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3197
+ dropTarget = detectDropTarget(board, detectPoint, dropTarget, [...activeElements, ...correspondingElements]);
3198
+ if (dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.target) {
3199
+ targetPath = getPathByDropTarget(board, dropTarget);
3200
+ fakeDropNodeG = drawFakeDropNodeByPath(board, dropTarget.target, targetPath);
3439
3201
  PlaitBoard.getHost(board).appendChild(fakeDropNodeG);
3440
- PlaitBoard.getHost(board).appendChild(fakeDragNodeG);
3441
- }
3442
- else {
3443
- if (fakeDragNodeG) {
3444
- fakeDragNodeG.innerHTML = '';
3445
- }
3446
- fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.childNodes.forEach(node => {
3447
- node.remove();
3448
- });
3449
3202
  }
3450
- // fake dragging origin node
3451
3203
  const offsetX = endPoint[0] - startPoint[0];
3452
3204
  const offsetY = endPoint[1] - startPoint[1];
3453
- const activeComponent = PlaitElement.getComponent(activeElement);
3454
- const fakeDraggingNode = Object.assign(Object.assign({}, activeComponent.node), { children: [], x: activeComponent.node.x + offsetX, y: activeComponent.node.y + offsetY });
3455
- const textRectangle = getRichtextRectangleByNode(board, activeComponent.node);
3456
- const fakeNodeG = drawRectangleNode(board, fakeDraggingNode);
3457
- const richtextG = (_a = activeComponent.richtextG) === null || _a === void 0 ? void 0 : _a.cloneNode(true);
3458
- updateForeignObject$1(richtextG, textRectangle.width, textRectangle.height, textRectangle.x + offsetX, textRectangle.y + offsetY);
3459
- fakeDragNodeG === null || fakeDragNodeG === void 0 ? void 0 : fakeDragNodeG.append(fakeNodeG);
3460
- fakeDragNodeG === null || fakeDragNodeG === void 0 ? void 0 : fakeDragNodeG.append(richtextG);
3461
- // draw emojis
3462
- if (MindElement.hasEmojis(activeElement)) {
3463
- const fakeEmojisG = activeComponent.emojisDrawer.g.cloneNode(true);
3464
- const foreignRectangle = getEmojiForeignRectangle(board, activeElement);
3465
- updateForeignObject$1(fakeEmojisG, foreignRectangle.width, foreignRectangle.height, foreignRectangle.x + offsetX, foreignRectangle.y + offsetY);
3466
- fakeDragNodeG === null || fakeDragNodeG === void 0 ? void 0 : fakeDragNodeG.append(fakeEmojisG);
3467
- }
3468
- // drop position detect
3469
- const { x, y } = getRectangleByNode(fakeDraggingNode);
3470
- const detectCenterPoint = [x + textRectangle.width / 2, y + textRectangle.height / 2];
3471
- let detectResult = null;
3472
- board.children.forEach((value) => {
3473
- if (detectResult) {
3474
- return;
3475
- }
3476
- if (PlaitMind.isMind(value)) {
3477
- const mindmapComponent = ELEMENT_TO_COMPONENT.get(value);
3478
- const root = mindmapComponent === null || mindmapComponent === void 0 ? void 0 : mindmapComponent.root;
3479
- root.eachNode((node) => {
3480
- if (detectResult) {
3481
- return;
3482
- }
3483
- const directions = directionDetector(node, detectCenterPoint);
3484
- if (directions) {
3485
- detectResult = directionCorrector(board, node, directions);
3486
- }
3487
- dropTarget = null;
3488
- if (detectResult && isValidTarget(activeComponent.node.origin, node.origin)) {
3489
- dropTarget = { target: node.origin, detectResult: detectResult[0] };
3490
- }
3491
- });
3205
+ dragFakeNodeG === null || dragFakeNodeG === void 0 ? void 0 : dragFakeNodeG.remove();
3206
+ dragFakeNodeG = createG();
3207
+ [...activeElements, ...correspondingElements].forEach(element => {
3208
+ addActiveOnDragOrigin(element);
3209
+ if (activeElements.includes(element)) {
3210
+ const activeComponent = PlaitElement.getComponent(element);
3211
+ const nodeG = drawFakeDragNode(board, activeComponent, offsetX, offsetY);
3212
+ dragFakeNodeG === null || dragFakeNodeG === void 0 ? void 0 : dragFakeNodeG.appendChild(nodeG);
3492
3213
  }
3493
3214
  });
3494
- if (dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.target) {
3495
- dropTarget = readjustmentDropTarget(board, dropTarget);
3496
- drawPlaceholderDropNodeG(board, dropTarget, fakeDropNodeG);
3497
- }
3215
+ PlaitBoard.getHost(board).appendChild(dragFakeNodeG);
3498
3216
  }
3499
3217
  mousemove(event);
3500
3218
  };
3501
3219
  board.globalMouseup = (event) => {
3502
- if (!board.options.readonly && activeElement) {
3503
- if (dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.target) {
3504
- const activeComponent = PlaitElement.getComponent(activeElement);
3505
- const targetComponent = PlaitElement.getComponent(dropTarget.target);
3506
- let targetPath = PlaitBoard.findPath(board, targetComponent.element);
3507
- const mindElement = findUpElement(dropTarget.target).root;
3508
- const mindComponent = ELEMENT_TO_COMPONENT.get(mindElement);
3509
- const layout = MindQueries.getCorrectLayoutByElement(board, mindComponent === null || mindComponent === void 0 ? void 0 : mindComponent.root.origin);
3510
- targetPath = updatePathByLayoutAndDropTarget(targetPath, layout, dropTarget);
3511
- const originPath = PlaitBoard.findPath(board, activeComponent.element);
3512
- let newElement = { isCollapsed: false }, rightTargetPath = PlaitBoard.findPath(board, targetComponent.element);
3513
- updateAbstractInDnd(board, [activeElement], targetPath);
3514
- if (isStandardLayout(layout)) {
3515
- updateRightNodeCount(board, activeComponent, targetComponent, dropTarget.detectResult);
3516
- }
3517
- if (dropTarget.detectResult === 'right') {
3518
- if (targetComponent.node.origin.isRoot) {
3519
- targetPath = PlaitBoard.findPath(board, targetComponent.element);
3520
- targetPath.push(0);
3521
- const rightNodeCount = targetComponent.node.origin.rightNodeCount + 1;
3522
- newElement = { isCollapsed: false, rightNodeCount };
3220
+ if (!board.options.readonly && (activeElements === null || activeElements === void 0 ? void 0 : activeElements.length)) {
3221
+ const elements = [...activeElements, ...correspondingElements];
3222
+ if (isDragging(board)) {
3223
+ elements.forEach(element => removeActiveOnDragOrigin(element));
3224
+ }
3225
+ if (dropTarget) {
3226
+ const targetPathRef = board.pathRef(targetPath);
3227
+ const targetElementPathRef = board.pathRef(PlaitBoard.findPath(board, dropTarget.target));
3228
+ const abstractRefs = getValidAbstractRefs(board, elements);
3229
+ const normalElements = elements
3230
+ .filter(element => !abstractRefs.some(refs => refs.abstract === element))
3231
+ .map(element => {
3232
+ if (AbstractNode.isAbstract(element)) {
3233
+ return adjustAbstractToNode(element);
3234
+ }
3235
+ if (PlaitMind.isMind(element)) {
3236
+ return adjustRootToNode(board, element);
3523
3237
  }
3524
- Transforms.setNode(board, newElement, rightTargetPath);
3238
+ return element;
3239
+ });
3240
+ const effectedAbstracts = deleteElementHandleAbstract(board, elements);
3241
+ insertElementHandleAbstract(board, targetPath, normalElements.length, false, effectedAbstracts);
3242
+ MindTransforms.setAbstractsByRefs(board, effectedAbstracts);
3243
+ MindTransforms.removeElements(board, elements);
3244
+ let insertPath = targetPathRef.current;
3245
+ const parentPath = Path.parent(targetPathRef.current || targetPath);
3246
+ if (!insertPath) {
3247
+ const parent = PlaitNode.get(board, parentPath);
3248
+ const children = getNonAbstractChildren(parent);
3249
+ insertPath = [...parentPath, children.length || 0];
3525
3250
  }
3526
- Transforms.moveNode(board, originPath, targetPath);
3527
- }
3528
- if (isDragging(board)) {
3529
- removeActiveOnDragOrigin(activeElement);
3251
+ MindTransforms.insertNodes(board, normalElements, insertPath);
3252
+ if (abstractRefs.length) {
3253
+ MindTransforms.insertAbstractNodes(board, abstractRefs, normalElements, insertPath);
3254
+ }
3255
+ const shouldChangeRoot = isInRightBranchOfStandardLayout(dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.target) &&
3256
+ targetElementPathRef.current &&
3257
+ (Path.isSibling(targetPath, targetElementPathRef.current) || Path.equals(targetPath, targetElementPathRef.current));
3258
+ if (shouldChangeRoot && targetElementPathRef.current) {
3259
+ changeRightNodeCount(board, targetElementPathRef.current.slice(0, 1), normalElements.length);
3260
+ }
3261
+ if (targetElementPathRef.current &&
3262
+ targetPathRef.current &&
3263
+ Path.isAncestor(targetElementPathRef.current, targetPathRef.current) &&
3264
+ dropTarget.target.isCollapsed) {
3265
+ Transforms.setNode(board, { isCollapsed: false }, targetElementPathRef.current);
3266
+ }
3267
+ targetElementPathRef.unref();
3268
+ targetPathRef.unref();
3269
+ const selectedElements = getSelectedElements(board);
3270
+ let setActiveElements = [];
3271
+ depthFirstRecursion(board, node => {
3272
+ const isSelected = selectedElements.some(element => element.id === node.id);
3273
+ if (isSelected) {
3274
+ setActiveElements.push(node);
3275
+ }
3276
+ });
3277
+ Transforms.setSelectionWithTemporaryElements(board, setActiveElements);
3530
3278
  }
3531
3279
  setIsDragging(board, false);
3532
- activeElement = null;
3533
- fakeDragNodeG === null || fakeDragNodeG === void 0 ? void 0 : fakeDragNodeG.remove();
3534
- fakeDragNodeG = undefined;
3280
+ activeElements = [];
3281
+ dragFakeNodeG === null || dragFakeNodeG === void 0 ? void 0 : dragFakeNodeG.remove();
3282
+ dragFakeNodeG = undefined;
3535
3283
  fakeDropNodeG === null || fakeDropNodeG === void 0 ? void 0 : fakeDropNodeG.remove();
3536
3284
  fakeDropNodeG = undefined;
3537
3285
  dropTarget = null;
3538
3286
  }
3539
3287
  globalMouseup(event);
3540
3288
  };
3541
- board.keydown = (event) => {
3542
- keydown(event);
3543
- };
3544
3289
  return board;
3545
3290
  };
3546
3291
 
@@ -3548,16 +3293,11 @@ const buildClipboardData = (board, selectedElements) => {
3548
3293
  let result = [];
3549
3294
  // get overall abstract
3550
3295
  const overallAbstracts = getOverallAbstracts(board, selectedElements);
3296
+ // get valid abstract refs
3297
+ const validAbstractRefs = getValidAbstractRefs(board, [...selectedElements, ...overallAbstracts]);
3551
3298
  // keep correct order
3552
- const newSelectedElements = selectedElements.filter((value) => !overallAbstracts.includes(value));
3553
- newSelectedElements.push(...overallAbstracts);
3554
- // get correct start and end in selected elements
3555
- function getCorrectStartEnd(abstract) {
3556
- const parent = MindElement.getParent(abstract);
3557
- const startElement = parent.children[abstract.start];
3558
- const index = selectedElements.indexOf(startElement);
3559
- return { start: index, end: index + (abstract.end - abstract.start) };
3560
- }
3299
+ const newSelectedElements = selectedElements.filter(value => !validAbstractRefs.find(ref => ref.abstract === value));
3300
+ newSelectedElements.push(...validAbstractRefs.map(value => value.abstract));
3561
3301
  const selectedMindNodes = newSelectedElements.map(value => MindElement.getNode(value));
3562
3302
  const nodesRectangle = getRectangleByElements(board, newSelectedElements, true);
3563
3303
  newSelectedElements.forEach((element, index) => {
@@ -3565,8 +3305,9 @@ const buildClipboardData = (board, selectedElements) => {
3565
3305
  const nodeRectangle = getRectangleByNode(selectedMindNodes[index]);
3566
3306
  const points = [[nodeRectangle.x - nodesRectangle.x, nodeRectangle.y - nodesRectangle.y]];
3567
3307
  // handle invalid abstract
3568
- if (AbstractNode.isAbstract(element) && overallAbstracts.includes(element)) {
3569
- const { start, end } = getCorrectStartEnd(element);
3308
+ const abstractRef = validAbstractRefs.find(ref => ref.abstract === element);
3309
+ if (AbstractNode.isAbstract(element) && abstractRef) {
3310
+ const { start, end } = getRelativeStartEndByAbstractRef(abstractRef, newSelectedElements);
3570
3311
  result.push(Object.assign(Object.assign({}, element), { points,
3571
3312
  start,
3572
3313
  end }));
@@ -3615,7 +3356,7 @@ const insertClipboardData = (board, elements, targetPoint) => {
3615
3356
  newElement = copyNewNode(item);
3616
3357
  if (hasTargetParent) {
3617
3358
  if (item.isRoot) {
3618
- newElement = transformRootToNode(board, newElement);
3359
+ newElement = adjustRootToNode(board, newElement);
3619
3360
  }
3620
3361
  // handle abstract start and end
3621
3362
  if (AbstractNode.isAbstract(newElement)) {
@@ -3628,10 +3369,10 @@ const insertClipboardData = (board, elements, targetPoint) => {
3628
3369
  const point = [targetPoint[0] + item.points[0][0], targetPoint[1] + item.points[0][1]];
3629
3370
  newElement.points = [point];
3630
3371
  if (AbstractNode.isAbstract(item)) {
3631
- newElement = transformAbstractToNode(newElement);
3372
+ newElement = adjustAbstractToNode(newElement);
3632
3373
  }
3633
3374
  if (!item.isRoot) {
3634
- newElement = transformNodeToRoot(board, newElement);
3375
+ newElement = adjustNodeToRoot(board, newElement);
3635
3376
  }
3636
3377
  path = [board.children.length];
3637
3378
  }
@@ -3662,8 +3403,8 @@ const withAbstract = (board) => {
3662
3403
  const point = transformPoint(board, toPoint(event.x, event.y, host));
3663
3404
  activeAbstractElement = activeAbstractElements.find(element => {
3664
3405
  abstractHandlePosition = getHitAbstractHandle(board, element, point);
3665
- if (newBoard === null || newBoard === void 0 ? void 0 : newBoard.abstractResize) {
3666
- newBoard.abstractResize(AbstractResizeState.start);
3406
+ if (newBoard === null || newBoard === void 0 ? void 0 : newBoard.onAbstractResize) {
3407
+ newBoard.onAbstractResize(AbstractResizeState.start);
3667
3408
  }
3668
3409
  return abstractHandlePosition;
3669
3410
  });
@@ -3697,8 +3438,8 @@ const withAbstract = (board) => {
3697
3438
  children = leftChildren;
3698
3439
  }
3699
3440
  }
3700
- if (newBoard === null || newBoard === void 0 ? void 0 : newBoard.abstractResize) {
3701
- newBoard.abstractResize(AbstractResizeState.resizing);
3441
+ if (newBoard === null || newBoard === void 0 ? void 0 : newBoard.onAbstractResize) {
3442
+ newBoard.onAbstractResize(AbstractResizeState.resizing);
3702
3443
  }
3703
3444
  const resizingLocation = isHorizontal ? endPoint[1] : endPoint[0];
3704
3445
  const parent = MindElement.getNode(parentElement);
@@ -3730,8 +3471,8 @@ const withAbstract = (board) => {
3730
3471
  startPoint = undefined;
3731
3472
  abstractHandlePosition = undefined;
3732
3473
  if (activeAbstractElement) {
3733
- if (newBoard === null || newBoard === void 0 ? void 0 : newBoard.abstractResize) {
3734
- newBoard.abstractResize(AbstractResizeState.end);
3474
+ if (newBoard === null || newBoard === void 0 ? void 0 : newBoard.onAbstractResize) {
3475
+ newBoard.onAbstractResize(AbstractResizeState.end);
3735
3476
  }
3736
3477
  if (newProperty) {
3737
3478
  const path = PlaitBoard.findPath(board, activeAbstractElement);
@@ -3748,7 +3489,7 @@ const withAbstract = (board) => {
3748
3489
  return board;
3749
3490
  };
3750
3491
 
3751
- const withExtendMind = (board) => {
3492
+ const withMindExtend = (board) => {
3752
3493
  const newBoard = board;
3753
3494
  newBoard.drawEmoji = (emoji, element) => {
3754
3495
  throw new Error('Not implement drawEmoji method error.');
@@ -3759,6 +3500,85 @@ const withExtendMind = (board) => {
3759
3500
  return newBoard;
3760
3501
  };
3761
3502
 
3503
+ const DefaultHotkey = 'm';
3504
+ const withCreateMind = (board) => {
3505
+ const newBoard = board;
3506
+ const { keydown, mousemove, mouseup } = board;
3507
+ let fakeCreateNodeRef = null;
3508
+ newBoard.mousemove = (event) => {
3509
+ if (PlaitBoard.isReadonly(board)) {
3510
+ mousemove(event);
3511
+ return;
3512
+ }
3513
+ if (PlaitBoard.isPointer(board, MindPointerType.mind)) {
3514
+ throttleRAF(() => {
3515
+ const movingPoint = PlaitBoard.getMovingPoint(board);
3516
+ if (movingPoint) {
3517
+ const targetPoint = transformPoint(board, toPoint(movingPoint[0], movingPoint[1], PlaitBoard.getHost(board)));
3518
+ const emptyMind = createEmptyMind(board, targetPoint);
3519
+ const nodeRectangle = getRectangleByElement(newBoard, targetPoint, emptyMind);
3520
+ const nodeG = drawRoundRectangleByElement(board, nodeRectangle, emptyMind);
3521
+ const topicRectangle = getTopicRectangleByElement(newBoard, nodeRectangle, emptyMind);
3522
+ if (!fakeCreateNodeRef) {
3523
+ const { richtextComponentRef, richtextG, foreignObject } = drawTopicByElement(newBoard, topicRectangle, emptyMind);
3524
+ fakeCreateNodeRef = {
3525
+ instanceRef: richtextComponentRef,
3526
+ nodeG,
3527
+ foreignObject,
3528
+ topicG: richtextG
3529
+ };
3530
+ richtextComponentRef.changeDetectorRef.detectChanges();
3531
+ PlaitBoard.getHost(board).append(...[fakeCreateNodeRef.nodeG, fakeCreateNodeRef.topicG]);
3532
+ }
3533
+ else {
3534
+ fakeCreateNodeRef.nodeG.remove();
3535
+ fakeCreateNodeRef.nodeG = nodeG;
3536
+ PlaitBoard.getHost(board).append(nodeG);
3537
+ PlaitBoard.getHost(board).append(fakeCreateNodeRef.topicG);
3538
+ updateForeignObject$1(fakeCreateNodeRef.topicG, topicRectangle.width, topicRectangle.height, topicRectangle.x, topicRectangle.y);
3539
+ }
3540
+ }
3541
+ });
3542
+ }
3543
+ else {
3544
+ destroy();
3545
+ }
3546
+ mousemove(event);
3547
+ };
3548
+ newBoard.mouseup = (event) => {
3549
+ const movingPoint = PlaitBoard.getMovingPoint(board);
3550
+ if (movingPoint && fakeCreateNodeRef && PlaitBoard.isPointer(board, MindPointerType.mind)) {
3551
+ const targetPoint = transformPoint(board, toPoint(movingPoint[0], movingPoint[1], PlaitBoard.getHost(board)));
3552
+ const emptyMind = createEmptyMind(board, targetPoint);
3553
+ Transforms.insertNode(board, emptyMind, [board.children.length]);
3554
+ BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
3555
+ }
3556
+ destroy();
3557
+ mouseup(event);
3558
+ };
3559
+ board.keydown = (event) => {
3560
+ if (PlaitBoard.isReadonly(board) || getSelectedElements(board).length > 0) {
3561
+ keydown(event);
3562
+ return;
3563
+ }
3564
+ if (event.key === DefaultHotkey && !PlaitBoard.isPointer(board, MindPointerType.mind)) {
3565
+ BoardTransforms.updatePointerType(board, MindPointerType.mind);
3566
+ event.preventDefault();
3567
+ return;
3568
+ }
3569
+ keydown(event);
3570
+ };
3571
+ function destroy() {
3572
+ if (fakeCreateNodeRef) {
3573
+ fakeCreateNodeRef.instanceRef.destroy();
3574
+ fakeCreateNodeRef.nodeG.remove();
3575
+ fakeCreateNodeRef.topicG.remove();
3576
+ fakeCreateNodeRef = null;
3577
+ }
3578
+ }
3579
+ return newBoard;
3580
+ };
3581
+
3762
3582
  const withMind = (board) => {
3763
3583
  const { drawElement, dblclick, keydown, insertFragment, setFragment, deleteFragment, isHitSelection, getRectangle, isMovable, isRecursion } = board;
3764
3584
  board.drawElement = (context) => {
@@ -3800,7 +3620,7 @@ const withMind = (board) => {
3800
3620
  return isMovable(element);
3801
3621
  };
3802
3622
  board.keydown = (event) => {
3803
- if (board.options.readonly || IS_TEXT_EDITABLE.get(board)) {
3623
+ if (PlaitBoard.isReadonly(board)) {
3804
3624
  keydown(event);
3805
3625
  return;
3806
3626
  }
@@ -3823,7 +3643,7 @@ const withMind = (board) => {
3823
3643
  insertMindElement(board, selectedElement, findNewChildNodePath(board, selectedElement));
3824
3644
  }
3825
3645
  else {
3826
- if (shouldChangeRightNodeCount(selectedElement)) {
3646
+ if (isInRightBranchOfStandardLayout(selectedElement)) {
3827
3647
  changeRightNodeCount(board, selectedElementPath.slice(0, 1), 1);
3828
3648
  }
3829
3649
  const abstractRefs = insertElementHandleAbstract(board, Path.next(selectedElementPath));
@@ -3834,7 +3654,10 @@ const withMind = (board) => {
3834
3654
  }
3835
3655
  if (hotkeys.isDeleteBackward(event) || hotkeys.isDeleteForward(event)) {
3836
3656
  event.preventDefault();
3837
- deleteSelectedELements(board, selectedElements);
3657
+ const deletableElements = getFirstLevelElement(selectedElements).reverse();
3658
+ const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
3659
+ MindTransforms.setAbstractsByRefs(board, abstractRefs);
3660
+ MindTransforms.removeElements(board, selectedElements);
3838
3661
  let activeElement;
3839
3662
  const firstLevelElements = getFirstLevelElement(selectedElements);
3840
3663
  if (AbstractNode.isAbstract(firstLevelElements[0])) {
@@ -3880,7 +3703,7 @@ const withMind = (board) => {
3880
3703
  keydown(event);
3881
3704
  };
3882
3705
  board.dblclick = (event) => {
3883
- if (board.options.readonly || IS_TEXT_EDITABLE.get(board)) {
3706
+ if (PlaitBoard.isReadonly(board)) {
3884
3707
  dblclick(event);
3885
3708
  return;
3886
3709
  }
@@ -3889,9 +3712,16 @@ const withMind = (board) => {
3889
3712
  .filter(value => PlaitMind.isMind(value))
3890
3713
  .forEach(mindMap => {
3891
3714
  depthFirstRecursion(mindMap, node => {
3892
- if (!PlaitBoard.hasBeenTextEditing(board) && hitMindElement(board, point, node)) {
3715
+ if (!PlaitBoard.hasBeenTextEditing(board) && isHitMindElement(board, point, node)) {
3893
3716
  enterNodeEditing(node);
3894
3717
  }
3718
+ }, node => {
3719
+ if (PlaitBoard.isBoard(node) || board.isRecursion(node)) {
3720
+ return true;
3721
+ }
3722
+ else {
3723
+ return false;
3724
+ }
3895
3725
  });
3896
3726
  });
3897
3727
  if (PlaitBoard.hasBeenTextEditing(board)) {
@@ -3929,10 +3759,13 @@ const withMind = (board) => {
3929
3759
  };
3930
3760
  board.deleteFragment = (data) => {
3931
3761
  const selectedElements = getSelectedElements(board);
3932
- deleteSelectedELements(board, selectedElements);
3762
+ const deletableElements = getFirstLevelElement(selectedElements).reverse();
3763
+ const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
3764
+ MindTransforms.setAbstractsByRefs(board, abstractRefs);
3765
+ MindTransforms.removeElements(board, selectedElements);
3933
3766
  deleteFragment(data);
3934
3767
  };
3935
- return withExtendMind(withAbstract(withDnd(board)));
3768
+ return withMindExtend(withCreateMind(withAbstract(withDnd(board))));
3936
3769
  };
3937
3770
 
3938
3771
  class MindEmojiBaseComponent {
@@ -3974,5 +3807,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
3974
3807
  * Generated bundle index. Do not edit.
3975
3808
  */
3976
3809
 
3977
- export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_COLORS, BRANCH_WIDTH, DefaultAbstractNodeStyle, DefaultNodeStyle, DefaultRootStyle, ELEMENT_TO_NODE, EXTEND_OFFSET, EXTEND_RADIUS, GRAY_COLOR, LayoutDirection, LayoutDirectionsMap, MindElement, MindElementShape, MindEmojiBaseComponent, MindModule, MindNode, MindNodeComponent, MindQueries, MindTransforms, NODE_MIN_WIDTH, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_TOPIC_FONT_SIZE, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, TRANSPARENT, canSetAbstract, changeRightNodeCount, copyNewNode, correctLayoutByDirection, createDefaultMindMapElement, createMindElement, deleteElementHandleAbstract, deleteSelectedELements, directionCorrector, directionDetector, divideElementByParent, drawCurvePlaceholderDropNodeG, drawIndentNodeG, drawPlaceholderDropNodeG, drawStraightDropNodeG, extractNodesText, findLastChild, findLocationLeftIndex, findUpElement, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultLayout, getEmojiFontSize, getEmojiForeignRectangle, getEmojiRectangle, getEmojisWidthHeight, getFirstLevelElement, getHitAbstractHandle, getHorizontalFakeY, getInCorrectLayoutDirection, getIndentedFakePoint, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection, getLocationScope, getNextBranchColor, getOverallAbstracts, getRectangleByNode, getRectangleByResizingLocation, getRootLayout, getShapeByElement, getStrokeByMindElement, handleTouchedAbstract, hitMindElement, insertElementHandleAbstract, insertMindElement, isChildElement, isChildRight, isChildUp, isCorrectLayout, isHitEmojis, isMixedLayout, isSetAbstract, isVirtualKey, readjustmentDropTarget, separateChildren, shouldChangeRightNodeCount, transformAbstractToNode, transformNodeToRoot, transformRootToNode, withExtendMind, withMind };
3810
+ 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, adjustAbstractToNode, adjustNodeToRoot, adjustRootToNode, canSetAbstract, changeRightNodeCount, copyNewNode, correctLayoutByDirection, createDefaultMind, createEmptyMind, createMindElement, deleteElementHandleAbstract, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNodeByPath, enterNodeEditing, 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 };
3978
3811
  //# sourceMappingURL=plait-mind.mjs.map