@plait/mind 0.27.0-next.0 → 0.27.0-next.10

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 (162) hide show
  1. package/base/emoji-base.component.d.ts +2 -2
  2. package/base/index.d.ts +0 -1
  3. package/constants/default.d.ts +1 -0
  4. package/constants/node-topic-style.d.ts +4 -0
  5. package/drawer/{node-active.drawer.d.ts → node-active.generator.d.ts} +2 -2
  6. package/drawer/node-shape.generator.d.ts +10 -0
  7. package/esm2022/base/emoji-base.component.mjs +46 -0
  8. package/{esm2020 → esm2022}/base/index.mjs +1 -2
  9. package/{esm2020 → esm2022}/constants/abstract-node.mjs +1 -1
  10. package/{esm2020 → esm2022}/constants/default.mjs +2 -1
  11. package/{esm2020 → esm2022}/constants/index.mjs +1 -1
  12. package/esm2022/constants/node-topic-style.mjs +12 -0
  13. package/esm2022/drawer/node-active.generator.mjs +42 -0
  14. package/esm2022/drawer/node-shape.generator.mjs +19 -0
  15. package/esm2022/interfaces/element-data.mjs +2 -0
  16. package/esm2022/interfaces/element.mjs +118 -0
  17. package/{esm2020 → esm2022}/interfaces/index.mjs +2 -1
  18. package/esm2022/interfaces/options.mjs +2 -0
  19. package/{esm2020 → esm2022}/interfaces/theme-color.mjs +1 -1
  20. package/esm2022/mind-node.component.mjs +235 -0
  21. package/esm2022/mind.component.mjs +52 -0
  22. package/esm2022/plugins/with-abstract-resize.mjs +112 -0
  23. package/esm2022/plugins/with-mind-create.mjs +112 -0
  24. package/esm2022/plugins/with-mind-fragment.mjs +90 -0
  25. package/esm2022/plugins/with-mind-hotkey.mjs +67 -0
  26. package/esm2022/plugins/with-mind.mjs +91 -0
  27. package/esm2022/plugins/with-node-dnd.mjs +180 -0
  28. package/esm2022/plugins/with-node-image-resize.mjs +48 -0
  29. package/esm2022/plugins/with-node-image.mjs +98 -0
  30. package/esm2022/plugins/with-node-resize.mjs +133 -0
  31. package/{esm2020 → esm2022}/public-api.mjs +2 -3
  32. package/{esm2020 → esm2022}/transforms/image.mjs +1 -1
  33. package/esm2022/transforms/index.mjs +23 -0
  34. package/esm2022/transforms/node.mjs +66 -0
  35. package/{esm2020 → esm2022}/utils/abstract/common.mjs +2 -2
  36. package/{esm2020 → esm2022}/utils/abstract/resize.mjs +3 -3
  37. package/{esm2020 → esm2022}/utils/clipboard.mjs +3 -3
  38. package/{esm2020 → esm2022}/utils/dnd/common.mjs +1 -1
  39. package/esm2022/utils/draw/abstract-outline.mjs +117 -0
  40. package/esm2022/utils/draw/node-dnd.mjs +159 -0
  41. package/{esm2020 → esm2022}/utils/draw/node-shape.mjs +4 -3
  42. package/esm2022/utils/index.mjs +15 -0
  43. package/{esm2020 → esm2022}/utils/node/common.mjs +1 -1
  44. package/esm2022/utils/node/create-node.mjs +55 -0
  45. package/esm2022/utils/node/dynamic-width.mjs +19 -0
  46. package/esm2022/utils/node/image.mjs +23 -0
  47. package/esm2022/utils/position/image.mjs +36 -0
  48. package/esm2022/utils/position/node.mjs +36 -0
  49. package/esm2022/utils/position/topic.mjs +16 -0
  50. package/{esm2020 → esm2022}/utils/space/index.mjs +1 -1
  51. package/esm2022/utils/space/layout-options.mjs +69 -0
  52. package/esm2022/utils/space/node-space.mjs +137 -0
  53. package/{fesm2020 → fesm2022}/plait-mind.mjs +1383 -1569
  54. package/fesm2022/plait-mind.mjs.map +1 -0
  55. package/interfaces/element-data.d.ts +5 -9
  56. package/interfaces/element.d.ts +1 -0
  57. package/interfaces/index.d.ts +1 -0
  58. package/interfaces/options.d.ts +2 -4
  59. package/{node.component.d.ts → mind-node.component.d.ts} +11 -10
  60. package/mind.component.d.ts +2 -2
  61. package/package.json +7 -13
  62. package/plugins/with-mind-fragment.d.ts +5 -0
  63. package/plugins/with-mind-hotkey.d.ts +0 -6
  64. package/public-api.d.ts +1 -2
  65. package/styles/styles.scss +7 -3
  66. package/transforms/image.d.ts +3 -2
  67. package/transforms/index.d.ts +1 -2
  68. package/transforms/node.d.ts +0 -1
  69. package/utils/abstract/common.d.ts +2 -2
  70. package/utils/index.d.ts +0 -1
  71. package/utils/node/create-node.d.ts +2 -2
  72. package/utils/node/image.d.ts +0 -2
  73. package/utils/position/image.d.ts +1 -1
  74. package/utils/position/node.d.ts +1 -1
  75. package/utils/space/layout-options.d.ts +2 -2
  76. package/utils/space/node-space.d.ts +1 -5
  77. package/base/image-base.component.d.ts +0 -27
  78. package/constants/image.d.ts +0 -3
  79. package/drawer/node-image.drawer.d.ts +0 -15
  80. package/esm2020/base/emoji-base.component.mjs +0 -46
  81. package/esm2020/base/image-base.component.mjs +0 -67
  82. package/esm2020/constants/image.mjs +0 -4
  83. package/esm2020/constants/node-topic-style.mjs +0 -8
  84. package/esm2020/drawer/node-active.drawer.mjs +0 -44
  85. package/esm2020/drawer/node-image.drawer.mjs +0 -59
  86. package/esm2020/interfaces/element-data.mjs +0 -2
  87. package/esm2020/interfaces/element.mjs +0 -111
  88. package/esm2020/interfaces/options.mjs +0 -2
  89. package/esm2020/mind.component.mjs +0 -51
  90. package/esm2020/mind.module.mjs +0 -21
  91. package/esm2020/node.component.mjs +0 -248
  92. package/esm2020/plugins/with-abstract-resize.mjs +0 -112
  93. package/esm2020/plugins/with-mind-create.mjs +0 -109
  94. package/esm2020/plugins/with-mind-hotkey.mjs +0 -122
  95. package/esm2020/plugins/with-mind.mjs +0 -114
  96. package/esm2020/plugins/with-node-dnd.mjs +0 -180
  97. package/esm2020/plugins/with-node-image-resize.mjs +0 -48
  98. package/esm2020/plugins/with-node-image.mjs +0 -96
  99. package/esm2020/plugins/with-node-resize.mjs +0 -133
  100. package/esm2020/transforms/index.mjs +0 -24
  101. package/esm2020/transforms/node.mjs +0 -82
  102. package/esm2020/utils/draw/abstract-outline.mjs +0 -117
  103. package/esm2020/utils/draw/node-dnd.mjs +0 -159
  104. package/esm2020/utils/index.mjs +0 -16
  105. package/esm2020/utils/is-virtual-key.mjs +0 -13
  106. package/esm2020/utils/node/create-node.mjs +0 -52
  107. package/esm2020/utils/node/dynamic-width.mjs +0 -22
  108. package/esm2020/utils/node/image.mjs +0 -63
  109. package/esm2020/utils/position/image.mjs +0 -36
  110. package/esm2020/utils/position/node.mjs +0 -34
  111. package/esm2020/utils/position/topic.mjs +0 -17
  112. package/esm2020/utils/space/layout-options.mjs +0 -72
  113. package/esm2020/utils/space/node-space.mjs +0 -142
  114. package/fesm2015/plait-mind.mjs +0 -4402
  115. package/fesm2015/plait-mind.mjs.map +0 -1
  116. package/fesm2020/plait-mind.mjs.map +0 -1
  117. package/mind.module.d.ts +0 -11
  118. package/utils/is-virtual-key.d.ts +0 -1
  119. /package/{esm2020 → esm2022}/base/base.drawer.mjs +0 -0
  120. /package/{esm2020 → esm2022}/constants/node-style.mjs +0 -0
  121. /package/{esm2020 → esm2022}/constants/theme.mjs +0 -0
  122. /package/{esm2020 → esm2022}/drawer/node-collapse.drawer.mjs +0 -0
  123. /package/{esm2020 → esm2022}/drawer/node-emojis.drawer.mjs +0 -0
  124. /package/{esm2020 → esm2022}/drawer/node-insert.drawer.mjs +0 -0
  125. /package/{esm2020 → esm2022}/interfaces/layout.mjs +0 -0
  126. /package/{esm2020 → esm2022}/interfaces/node.mjs +0 -0
  127. /package/{esm2020 → esm2022}/interfaces/pointer.mjs +0 -0
  128. /package/{esm2020 → esm2022}/interfaces/types.mjs +0 -0
  129. /package/{esm2020 → esm2022}/plait-mind.mjs +0 -0
  130. /package/{esm2020 → esm2022}/plugins/with-abstract-resize.board.mjs +0 -0
  131. /package/{esm2020 → esm2022}/plugins/with-mind-extend.mjs +0 -0
  132. /package/{esm2020 → esm2022}/plugins/with-mind.board.mjs +0 -0
  133. /package/{esm2020 → esm2022}/plugins/with-node-hover-detect.mjs +0 -0
  134. /package/{esm2020 → esm2022}/queries/get-available-sublayouts-by-element.mjs +0 -0
  135. /package/{esm2020 → esm2022}/queries/get-branch-layouts.mjs +0 -0
  136. /package/{esm2020 → esm2022}/queries/get-correct-layout-by-element.mjs +0 -0
  137. /package/{esm2020 → esm2022}/queries/get-layout-by-element.mjs +0 -0
  138. /package/{esm2020 → esm2022}/queries/index.mjs +0 -0
  139. /package/{esm2020 → esm2022}/transforms/abstract-node.mjs +0 -0
  140. /package/{esm2020 → esm2022}/transforms/emoji.mjs +0 -0
  141. /package/{esm2020 → esm2022}/transforms/layout.mjs +0 -0
  142. /package/{esm2020 → esm2022}/utils/dnd/detector.mjs +0 -0
  143. /package/{esm2020 → esm2022}/utils/draw/node-link/abstract-link.mjs +0 -0
  144. /package/{esm2020 → esm2022}/utils/draw/node-link/draw-link.mjs +0 -0
  145. /package/{esm2020 → esm2022}/utils/draw/node-link/indented-link.mjs +0 -0
  146. /package/{esm2020 → esm2022}/utils/draw/node-link/logic-link.mjs +0 -0
  147. /package/{esm2020 → esm2022}/utils/layout.mjs +0 -0
  148. /package/{esm2020 → esm2022}/utils/mind.mjs +0 -0
  149. /package/{esm2020 → esm2022}/utils/node/adjust-node.mjs +0 -0
  150. /package/{esm2020 → esm2022}/utils/node/index.mjs +0 -0
  151. /package/{esm2020 → esm2022}/utils/node/right-node-count.mjs +0 -0
  152. /package/{esm2020 → esm2022}/utils/node-hover/extend.mjs +0 -0
  153. /package/{esm2020 → esm2022}/utils/node-style/branch.mjs +0 -0
  154. /package/{esm2020 → esm2022}/utils/node-style/common.mjs +0 -0
  155. /package/{esm2020 → esm2022}/utils/node-style/index.mjs +0 -0
  156. /package/{esm2020 → esm2022}/utils/node-style/shape.mjs +0 -0
  157. /package/{esm2020 → esm2022}/utils/path.mjs +0 -0
  158. /package/{esm2020 → esm2022}/utils/point-placement.mjs +0 -0
  159. /package/{esm2020 → esm2022}/utils/position/emoji.mjs +0 -0
  160. /package/{esm2020 → esm2022}/utils/position/index.mjs +0 -0
  161. /package/{esm2020 → esm2022}/utils/space/emoji.mjs +0 -0
  162. /package/{esm2020 → esm2022}/utils/weak-maps.mjs +0 -0
@@ -1,17 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, ChangeDetectionStrategy, NgModule, NgZone, Directive, Input, HostListener } from '@angular/core';
3
- import * as i2 from '@plait/core';
4
- import { DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, RectangleClient, PlaitElement, PlaitPluginKey, getSelectedElements, idCreator, isNullOrUndefined, Transforms, clearSelectedElement, addSelectedElement, PlaitBoard, Path, PlaitNode, PlaitContextService, depthFirstRecursion, getIsRecursionFunc, drawLinearPath, drawBezierPath, createG, updateForeignObject, drawRoundRectangle, getRectangleByElements, NODE_TO_PARENT, distanceBetweenPointAndRectangle, createForeignObject, createText, PlaitPointerType, PlaitPluginElementComponent, NODE_TO_INDEX, PlaitModule, isMainPointer, transformPoint, toPoint, getHitElements, distanceBetweenPointAndPoint, setClipboardData, setClipboardDataByText, BOARD_TO_HOST, throttleRAF, BoardTransforms, removeSelectedElement, PlaitHistoryBoard, hotkeys, setClipboardDataByMedia, getClipboardDataByMedia, ResizeCursorClass, preventTouchMove, PRESS_AND_MOVE_BUFFER, MERGING, getDataFromClipboard } from '@plait/core';
5
- import { MindLayoutType, isIndentedLayout, AbstractNode, isStandardLayout, isHorizontalLogicLayout, isVerticalLogicLayout, getNonAbstractChildren, isLeftLayout, isRightLayout, isTopLayout, isBottomLayout, isHorizontalLayout, getCorrectStartEnd, ConnectingPosition, getAbstractLayout, GlobalLayout } from '@plait/layouts';
6
- import { PlaitMarkEditor, MarkTypes, DEFAULT_FONT_SIZE, TEXT_DEFAULT_HEIGHT, buildText, getTextSize, TextManage, ExitOrigin, TextModule, getTextFromClipboard } from '@plait/text';
2
+ import { Component, ChangeDetectionStrategy, NgZone, Directive, Input, HostListener } from '@angular/core';
3
+ import { DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, PlaitElement, PlaitNode, Path, isNullOrUndefined, PlaitBoard, distanceBetweenPointAndRectangle, RectangleClient, PlaitPluginKey, getSelectedElements, idCreator, Transforms, clearSelectedElement, addSelectedElement, depthFirstRecursion, getIsRecursionFunc, drawRoundRectangle, drawLinearPath, drawBezierPath, createG, updateForeignObject, getRectangleByElements, NODE_TO_PARENT, createForeignObject, setStrokeLinecap, ACTIVE_STROKE_WIDTH, createText, PlaitPointerType, NODE_TO_INDEX, PlaitChildrenElementComponent, isMainPointer, transformPoint, toPoint, getHitElements, distanceBetweenPointAndPoint, CoreTransforms, BOARD_TO_HOST, BoardTransforms, throttleRAF, removeSelectedElement, PlaitHistoryBoard, hotkeys, setClipboardDataByMedia, getClipboardDataByMedia, ResizeCursorClass, preventTouchMove, PRESS_AND_MOVE_BUFFER, MERGING, setClipboardData, setClipboardDataByText, getDataFromClipboard } from '@plait/core';
4
+ import { MindLayoutType, AbstractNode, isIndentedLayout, isHorizontalLayout, isHorizontalLogicLayout, ConnectingPosition, getNonAbstractChildren, isStandardLayout, isLeftLayout, isRightLayout, isVerticalLogicLayout, isTopLayout, isBottomLayout, getCorrectStartEnd, getAbstractLayout, GlobalLayout } from '@plait/layouts';
5
+ import { PlaitMarkEditor, MarkTypes, DEFAULT_FONT_SIZE, TEXT_DEFAULT_HEIGHT, buildText, getTextSize, TextManage, ExitOrigin, getTextFromClipboard } from '@plait/text';
7
6
  import { fromEvent, Subject } from 'rxjs';
8
- import { RESIZE_HANDLE_DIAMETER, getRectangleResizeTargets, MediaKeys, ResizeDirection, withResize, ActiveGenerator } from '@plait/common';
7
+ import { RESIZE_HANDLE_DIAMETER, getRectangleResizeHandleRefs, Generator, CommonPluginElement, ImageGenerator, WithTextPluginKey, isDrawingMode, isDndMode, setCreationMode, BoardCreationMode, isExpandHotkey, isTabHotkey, isEnterHotkey, isVirtualKey, isDelete, isSpaceHotkey, MediaKeys, acceptImageTypes, buildImage, ResizeHandle, withResize } from '@plait/common';
9
8
  import { Node as Node$1, Path as Path$1 } from 'slate';
10
- import { isKeyHotkey } from 'is-hotkey';
11
9
  import { pointsOnBezierCurves } from 'points-on-curve';
12
10
  import { take, filter } from 'rxjs/operators';
13
- import * as i1 from '@angular/common';
14
- import { CommonModule } from '@angular/common';
11
+ import { NgIf } from '@angular/common';
15
12
 
16
13
  const ELEMENT_TO_NODE = new WeakMap();
17
14
 
@@ -192,6 +189,7 @@ const EXTEND_DIAMETER = 16;
192
189
  const QUICK_INSERT_CIRCLE_OFFSET = 9;
193
190
  const QUICK_INSERT_CIRCLE_COLOR = '#6698FF';
194
191
  const QUICK_INSERT_INNER_CROSS_COLOR = 'white';
192
+ const DEFAULT_MIND_IMAGE_WIDTH = 240;
195
193
 
196
194
  function getEmojisWidthHeight(board, element) {
197
195
  const options = board.getPluginOptions(WithMindPluginKey);
@@ -215,980 +213,888 @@ const TOPIC_COLOR = '#333';
215
213
  const TOPIC_FONT_SIZE = 14;
216
214
  const ROOT_TOPIC_FONT_SIZE = 18;
217
215
  const ROOT_TOPIC_HEIGHT = 25;
216
+ const ROOT_TOPIC_WIDTH = 72;
218
217
  const TOPIC_DEFAULT_MAX_WORD_COUNT = 34;
219
218
  const DEFAULT_FONT_FAMILY = 'PingFangSC-Regular, "PingFang SC"';
220
219
  const BRANCH_FONT_FAMILY = 'PingFangSC-Medium, "PingFang SC"';
220
+ const NodeTopicThreshold = {
221
+ defaultTextMaxWidth: 34 * 14
222
+ };
221
223
 
222
- const NodeDefaultSpace = {
223
- horizontal: {
224
- nodeAndText: BASE * 2.5,
225
- emojiAndText: BASE * 1.5
226
- },
227
- vertical: {
228
- nodeAndText: BASE,
229
- nodeAndImage: BASE,
230
- imageAndText: BASE * 1.5
224
+ const getAvailableProperty = (board, element, propertyKey) => {
225
+ return element[propertyKey];
226
+ };
227
+
228
+ const DefaultAbstractNodeStyle = {
229
+ branch: { color: GRAY_COLOR, width: 2 },
230
+ shape: {
231
+ strokeColor: GRAY_COLOR,
232
+ strokeWidth: 2
231
233
  }
232
234
  };
233
- const RootDefaultSpace = {
234
- horizontal: {
235
- nodeAndText: BASE * 4,
236
- emojiAndText: BASE * 2
235
+ const DefaultNodeStyle = {
236
+ branch: {
237
+ width: 3
237
238
  },
238
- vertical: {
239
- nodeAndText: BASE * 2
239
+ shape: {
240
+ rectangleRadius: 4,
241
+ strokeWidth: 3,
242
+ fill: 'none'
240
243
  }
241
244
  };
242
- const getHorizontalSpaceBetweenNodeAndText = (board, element) => {
243
- const isMind = PlaitMind.isMind(element);
244
- const nodeAndText = isMind ? RootDefaultSpace.horizontal.nodeAndText : NodeDefaultSpace.horizontal.nodeAndText;
245
- const strokeWidth = getStrokeWidthByElement(board, element);
246
- return nodeAndText + strokeWidth / 2;
247
- };
248
- const getVerticalSpaceBetweenNodeAndText = (board, element) => {
249
- const isMind = PlaitMind.isMind(element);
250
- const strokeWidth = getStrokeWidthByElement(board, element);
251
- const nodeAndText = isMind ? RootDefaultSpace.vertical.nodeAndText : NodeDefaultSpace.vertical.nodeAndText;
252
- return nodeAndText + strokeWidth / 2;
253
- };
254
- const getSpaceEmojiAndText = (element) => {
255
- const isMind = PlaitMind.isMind(element);
256
- const emojiAndText = isMind ? RootDefaultSpace.horizontal.emojiAndText : NodeDefaultSpace.horizontal.emojiAndText;
257
- return emojiAndText;
258
- };
259
- const NodeSpace = {
260
- getNodeWidth(board, element) {
261
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
262
- if (MindElement.hasEmojis(element)) {
263
- return (NodeSpace.getEmojiLeftSpace(board, element) +
264
- getEmojisWidthHeight(board, element).width +
265
- getSpaceEmojiAndText(element) +
266
- NodeSpace.getNodeDynamicWidth(board, element) +
267
- nodeAndText);
268
- }
269
- return nodeAndText + NodeSpace.getNodeDynamicWidth(board, element) + nodeAndText;
270
- },
271
- getNodeHeight(board, element) {
272
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
273
- if (MindElement.hasImage(element)) {
274
- return NodeSpace.getTextTopSpace(board, element) + element.height + nodeAndText;
275
- }
276
- return nodeAndText + element.height + nodeAndText;
277
- },
278
- getNodeDynamicWidth(board, element) {
279
- const width = element.manualWidth || element.width;
280
- const imageWidth = MindElement.hasImage(element) ? element.data.image?.width : 0;
281
- return Math.max(width, imageWidth);
282
- },
283
- /**
284
- * use this when upload image first or resize image
285
- * @param board
286
- * @param element
287
- * @param imageWidth
288
- * @returns
289
- */
290
- getNodeNewDynamicWidth(board, element, imageWidth) {
291
- const width = element.manualWidth || element.width;
292
- return Math.max(width, imageWidth);
293
- },
294
- getNodeResizableMinWidth(board, element) {
295
- const minTopicWidth = NodeSpace.getNodeTopicMinWidth(board, element);
296
- if (MindElement.hasImage(element) && element.data.image.width > minTopicWidth) {
297
- return element.data.image.width;
298
- }
299
- else {
300
- return minTopicWidth;
301
- }
302
- },
303
- getNodeTopicMinWidth(board, element, isRoot = false) {
304
- const defaultFontSize = getNodeDefaultFontSize(isRoot);
305
- const editor = MindElement.getTextEditor(element);
306
- const marks = PlaitMarkEditor.getMarks(editor);
307
- const fontSize = marks[MarkTypes.fontSize] || defaultFontSize;
308
- return fontSize;
309
- },
310
- getTextLeftSpace(board, element) {
311
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
312
- if (MindElement.hasEmojis(element)) {
313
- return NodeSpace.getEmojiLeftSpace(board, element) + getEmojisWidthHeight(board, element).width + getSpaceEmojiAndText(element);
245
+
246
+ const separateChildren = (parentElement) => {
247
+ const rightNodeCount = parentElement.rightNodeCount;
248
+ const children = parentElement.children;
249
+ let rightChildren = [], leftChildren = [];
250
+ for (let i = 0; i < children.length; i++) {
251
+ const child = children[i];
252
+ if (AbstractNode.isAbstract(child) && child.end < rightNodeCount) {
253
+ rightChildren.push(child);
254
+ continue;
314
255
  }
315
- else {
316
- return nodeAndText;
256
+ if (AbstractNode.isAbstract(child) && child.start >= rightNodeCount) {
257
+ leftChildren.push(child);
258
+ continue;
317
259
  }
318
- },
319
- getTextTopSpace(board, element) {
320
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
321
- if (MindElement.hasImage(element)) {
322
- return NodeSpace.getImageTopSpace(board, element) + element.data.image.height + NodeDefaultSpace.vertical.imageAndText;
260
+ if (i < rightNodeCount) {
261
+ rightChildren.push(child);
323
262
  }
324
263
  else {
325
- return nodeAndText;
264
+ leftChildren.push(child);
326
265
  }
327
- },
328
- getImageTopSpace(board, element) {
329
- const strokeWidth = getStrokeWidthByElement(board, element);
330
- return strokeWidth / 2 + NodeDefaultSpace.vertical.nodeAndImage;
331
- },
332
- getEmojiLeftSpace(board, element) {
333
- const options = board.getPluginOptions(WithMindPluginKey);
334
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
335
- const strokeWidth = getStrokeWidthByElement(board, element);
336
- return strokeWidth / 2 + nodeAndText - options.emojiPadding;
337
- },
338
- getEmojiTopSpace(board, element) {
339
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
340
- return nodeAndText;
341
266
  }
267
+ return { leftChildren, rightChildren };
342
268
  };
343
- const getFontSizeBySlateElement = (text) => {
344
- const defaultFontSize = DEFAULT_FONT_SIZE;
345
- if (typeof text === 'string') {
346
- return defaultFontSize;
347
- }
348
- const marks = PlaitMarkEditor.getMarksByElement(text);
349
- const fontSize = marks[MarkTypes.fontSize] || defaultFontSize;
350
- return fontSize;
269
+ const isSetAbstract = (element) => {
270
+ return !!getCorrespondingAbstract(element);
351
271
  };
352
- const getNodeDefaultFontSize = (isRoot = false) => {
353
- const defaultFontSize = isRoot ? ROOT_TOPIC_FONT_SIZE : DEFAULT_FONT_SIZE;
354
- return defaultFontSize;
272
+ const canSetAbstract = (element) => {
273
+ return !PlaitElement.isRootElement(element) && !AbstractNode.isAbstract(element) && !isSetAbstract(element);
355
274
  };
356
-
357
- function getEmojiRectangle(board, element) {
358
- let { x, y } = getRectangleByNode(MindElement.getNode(element));
359
- x = x + NodeSpace.getEmojiLeftSpace(board, element);
360
- const { width, height } = getEmojisWidthHeight(board, element);
361
- return {
362
- x,
363
- y,
364
- width,
365
- height
366
- };
367
- }
368
- function getEmojiForeignRectangle(board, element) {
369
- let { x, y } = getRectangleByNode(MindElement.getNode(element));
370
- x = x + NodeSpace.getEmojiLeftSpace(board, element);
371
- const { width } = getEmojisWidthHeight(board, element);
372
- return {
373
- x,
374
- y,
375
- width,
376
- height: NodeSpace.getNodeHeight(board, element)
377
- };
378
- }
379
- const isHitEmojis = (board, element, point) => {
380
- return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), getEmojiRectangle(board, element));
275
+ const getCorrespondingAbstract = (element) => {
276
+ const parent = MindElement.findParent(element);
277
+ if (!parent)
278
+ return undefined;
279
+ const elementIndex = parent.children.indexOf(element);
280
+ return parent.children.find(child => {
281
+ return AbstractNode.isAbstract(child) && elementIndex >= child.start && elementIndex <= child.end;
282
+ });
381
283
  };
382
-
383
- function getTopicRectangleByNode(board, node) {
384
- let nodeRectangle = getRectangleByNode(node);
385
- const result = getTopicRectangleByElement(board, nodeRectangle, node.origin);
386
- // add buffer width to avoid unexpected text breaks in different scene
387
- result.width = result.width + 4;
388
- return result;
389
- }
390
- function getTopicRectangleByElement(board, nodeRectangle, element) {
391
- const x = nodeRectangle.x + NodeSpace.getTextLeftSpace(board, element);
392
- const y = nodeRectangle.y + NodeSpace.getTextTopSpace(board, element);
393
- const width = NodeSpace.getNodeDynamicWidth(board, element);
394
- const height = Math.ceil(element.height);
395
- return { height, width, x, y };
396
- }
397
-
398
- function getImageForeignRectangle(board, element) {
399
- let { x, y } = getRectangleByNode(MindElement.getNode(element));
400
- const elementWidth = element.manualWidth || element.width;
401
- x =
402
- elementWidth > element.data.image.width
403
- ? x + NodeSpace.getTextLeftSpace(board, element) + (elementWidth - element.data.image.width) / 2
404
- : x + NodeSpace.getTextLeftSpace(board, element);
405
- y = NodeSpace.getImageTopSpace(board, element) + y;
406
- const { width, height } = element.data.image;
407
- const rectangle = {
408
- x,
409
- y,
410
- width,
411
- height
412
- };
413
- return rectangle;
414
- }
415
- const isHitImage = (board, element, range) => {
416
- const imageRectangle = getImageForeignRectangle(board, element);
417
- const imageOutlineRectangle = RectangleClient.getOutlineRectangle(imageRectangle, -RESIZE_HANDLE_DIAMETER / 2);
418
- return RectangleClient.isHit(RectangleClient.toRectangleClient([range.anchor, range.focus]), imageOutlineRectangle);
284
+ const getBehindAbstracts = (element) => {
285
+ const parent = MindElement.findParent(element);
286
+ if (!parent)
287
+ return [];
288
+ const index = parent.children.indexOf(element);
289
+ return parent.children.filter(child => AbstractNode.isAbstract(child) && child.start > index);
419
290
  };
420
- const getHitImageResizeHandleDirection = (board, element, point) => {
421
- const imageRectangle = getImageForeignRectangle(board, element);
422
- const resizeTargets = getRectangleResizeTargets(imageRectangle, RESIZE_HANDLE_DIAMETER);
423
- const result = resizeTargets.find(resizeTarget => {
424
- return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), resizeTarget.rectangle);
291
+ /**
292
+ * return corresponding abstract that is not child of elements
293
+ */
294
+ const getOverallAbstracts = (board, elements) => {
295
+ const overallAbstracts = [];
296
+ elements
297
+ .filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
298
+ .forEach(value => {
299
+ const abstract = getCorrespondingAbstract(value);
300
+ if (abstract && elements.indexOf(abstract) === -1 && overallAbstracts.indexOf(abstract) === -1) {
301
+ const { start, end } = abstract;
302
+ const parent = MindElement.getParent(value);
303
+ const isOverall = parent.children.slice(start, end + 1).every(includedElement => elements.indexOf(includedElement) > -1);
304
+ if (isOverall) {
305
+ overallAbstracts.push(abstract);
306
+ }
307
+ }
425
308
  });
426
- return result;
309
+ return overallAbstracts;
427
310
  };
428
-
429
- function editTopic(element) {
430
- const component = PlaitElement.getComponent(element);
431
- component?.editTopic();
432
- }
433
- const temporaryDisableSelection = (board) => {
434
- const currentOptions = board.getPluginOptions(PlaitPluginKey.withSelection);
435
- board.setPluginOptions(PlaitPluginKey.withSelection, {
436
- isDisabledSelect: true
437
- });
438
- setTimeout(() => {
439
- board.setPluginOptions(PlaitPluginKey.withSelection, { ...currentOptions });
440
- }, 0);
441
- };
442
- const getSelectedMindElements = (board) => {
443
- const selectedElements = getSelectedElements(board).filter(value => MindElement.isMindElement(board, value));
444
- return selectedElements;
445
- };
446
-
447
- const createEmptyMind = (point) => {
448
- const element = createMindElement('思维导图', 72, ROOT_TOPIC_HEIGHT, { layout: MindLayoutType.right });
449
- element.isRoot = true;
450
- element.points = [point];
451
- element.type = 'mindmap';
452
- return element;
453
- };
454
- const createDefaultMind = (point, rightNodeCount, layout) => {
455
- const root = createMindElement('思维导图', 72, ROOT_TOPIC_HEIGHT, { layout });
456
- root.rightNodeCount = rightNodeCount;
457
- root.isRoot = true;
458
- root.type = 'mindmap';
459
- root.points = [point];
460
- const children = [1, 1, 1].map(() => {
461
- return createMindElement('新建节点', 56, TEXT_DEFAULT_HEIGHT, {});
311
+ /**
312
+ * abstract node is valid when elements contains at least one element it is referenced with
313
+ */
314
+ const getValidAbstractRefs = (board, elements) => {
315
+ const validAbstractRefs = [];
316
+ elements
317
+ .filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
318
+ .forEach(value => {
319
+ const abstract = getCorrespondingAbstract(value);
320
+ if (abstract && elements.indexOf(abstract) > 0) {
321
+ const index = validAbstractRefs.findIndex(value => value.abstract === abstract);
322
+ if (index === -1) {
323
+ validAbstractRefs.push({
324
+ abstract: abstract,
325
+ references: [value]
326
+ });
327
+ }
328
+ else {
329
+ validAbstractRefs[index].references.push(value);
330
+ }
331
+ }
462
332
  });
463
- root.children = children;
464
- return root;
333
+ return validAbstractRefs;
465
334
  };
466
- const createMindElement = (text, width, height, options) => {
467
- const newElement = {
468
- id: idCreator(),
469
- data: {
470
- topic: buildText(text)
471
- },
472
- children: [],
473
- width,
474
- height
475
- };
476
- let key;
477
- for (key in options) {
478
- if (!isNullOrUndefined(options[key])) {
479
- newElement[key] = options[key];
480
- }
335
+ function getRelativeStartEndByAbstractRef(abstractRef, elements) {
336
+ const start = elements.indexOf(abstractRef.references[0]);
337
+ const end = elements.indexOf(abstractRef.references[abstractRef.references.length - 1]);
338
+ return { start, end };
339
+ }
340
+ const insertElementHandleAbstract = (board, path, step = 1,
341
+ //由此区分拖拽和新增到概要概括最后一个节点
342
+ isExtendPreviousNode = true, effectedAbstracts = new Map()) => {
343
+ const parent = PlaitNode.parent(board, path);
344
+ const hasPreviousNode = path[path.length - 1] !== 0;
345
+ let behindAbstracts;
346
+ if (!hasPreviousNode) {
347
+ behindAbstracts = parent.children.filter(child => AbstractNode.isAbstract(child));
481
348
  }
482
- return newElement;
483
- };
484
- const INHERIT_ATTRIBUTE_KEYS = [
485
- 'fill',
486
- 'strokeColor',
487
- 'strokeWidth',
488
- 'shape',
489
- 'layout',
490
- 'branchColor',
491
- 'branchWidth',
492
- 'branchShape'
493
- ];
494
-
495
- const getChildrenCount = (element) => {
496
- const count = element.children.reduce((p, c) => {
497
- return p + getChildrenCount(c);
498
- }, 0);
499
- return count + element.children.length;
500
- };
501
- const isChildElement = (origin, child) => {
502
- let parent = MindElement.findParent(child);
503
- while (parent) {
504
- if (parent === origin) {
505
- return true;
349
+ else {
350
+ const selectedElement = PlaitNode.get(board, Path.previous(path));
351
+ behindAbstracts = getBehindAbstracts(selectedElement);
352
+ }
353
+ if (behindAbstracts.length) {
354
+ behindAbstracts.forEach(abstract => {
355
+ let newProperties = effectedAbstracts.get(abstract);
356
+ if (!newProperties) {
357
+ newProperties = { start: 0, end: 0 };
358
+ effectedAbstracts.set(abstract, newProperties);
359
+ }
360
+ newProperties.start = newProperties.start + step;
361
+ newProperties.end = newProperties.end + step;
362
+ });
363
+ }
364
+ if (!hasPreviousNode) {
365
+ return effectedAbstracts;
366
+ }
367
+ const selectedElement = PlaitNode.get(board, Path.previous(path));
368
+ const correspondingAbstract = getCorrespondingAbstract(selectedElement);
369
+ const isDragToLast = !isExtendPreviousNode && correspondingAbstract && correspondingAbstract.end === path[path.length - 1] - 1;
370
+ if (correspondingAbstract && !isDragToLast) {
371
+ let newProperties = effectedAbstracts.get(correspondingAbstract);
372
+ if (!newProperties) {
373
+ newProperties = { start: 0, end: 0 };
374
+ effectedAbstracts.set(correspondingAbstract, newProperties);
506
375
  }
507
- parent = MindElement.findParent(parent);
376
+ newProperties.end = newProperties.end + step;
508
377
  }
509
- return false;
378
+ return effectedAbstracts;
510
379
  };
511
- const getFirstLevelElement = (elements) => {
512
- let result = [];
513
- elements.forEach(element => {
514
- const isChild = elements.some(node => {
515
- return isChildElement(node, element);
516
- });
517
- if (!isChild) {
518
- result.push(element);
380
+ const deleteElementHandleAbstract = (board, deletableElements, effectedAbstracts = new Map()) => {
381
+ deletableElements.forEach(node => {
382
+ if (!PlaitMind.isMind(node)) {
383
+ const behindAbstracts = getBehindAbstracts(node).filter(abstract => !deletableElements.includes(abstract));
384
+ if (behindAbstracts.length) {
385
+ behindAbstracts.forEach(abstract => {
386
+ let newProperties = effectedAbstracts.get(abstract);
387
+ if (!newProperties) {
388
+ newProperties = { start: 0, end: 0 };
389
+ effectedAbstracts.set(abstract, newProperties);
390
+ }
391
+ newProperties.start = newProperties.start - 1;
392
+ newProperties.end = newProperties.end - 1;
393
+ });
394
+ }
395
+ const correspondingAbstract = getCorrespondingAbstract(node);
396
+ if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
397
+ let newProperties = effectedAbstracts.get(correspondingAbstract);
398
+ if (!newProperties) {
399
+ newProperties = { start: 0, end: 0 };
400
+ effectedAbstracts.set(correspondingAbstract, newProperties);
401
+ }
402
+ newProperties.end = newProperties.end - 1;
403
+ }
519
404
  }
520
405
  });
521
- return result;
522
- };
523
- const isChildRight = (node, child) => {
524
- return node.x < child.x;
406
+ return effectedAbstracts;
525
407
  };
526
- const isChildUp = (node, child) => {
527
- return node.y > child.y;
408
+ const isChildOfAbstract = (board, element) => {
409
+ const ancestors = MindElement.getAncestors(board, element);
410
+ return !!ancestors.find(value => AbstractNode.isAbstract(value));
528
411
  };
529
- const copyNewNode = (node) => {
530
- const newNode = { ...node };
531
- newNode.id = idCreator();
532
- newNode.children = [];
533
- for (const childNode of node.children) {
534
- newNode.children.push(copyNewNode(childNode));
412
+
413
+ /**
414
+ * Processing of branch color, width, style, etc. of the mind node
415
+ */
416
+ const getBranchColorByMindElement = (board, element) => {
417
+ if (AbstractNode.isAbstract(element) || isChildOfAbstract(board, element)) {
418
+ return getAbstractBranchColor(board, element);
535
419
  }
536
- return newNode;
420
+ const branchColor = getAvailableProperty(board, element, 'branchColor');
421
+ return branchColor || getDefaultBranchColor(board, element);
537
422
  };
538
- const extractNodesText = (node) => {
539
- let str = '';
540
- if (node) {
541
- str += Node$1.string(node.data.topic) + ' ';
542
- for (const childNode of node.children) {
543
- str += extractNodesText(childNode);
544
- }
545
- }
546
- return str;
423
+ const getBranchShapeByMindElement = (board, element) => {
424
+ const branchShape = getAvailableProperty(board, element, 'branchShape');
425
+ return branchShape || BranchShape.bight;
547
426
  };
548
- const insertMindElement = (board, inheritNode, path) => {
549
- const newNode = {};
550
- if (!inheritNode.isRoot) {
551
- INHERIT_ATTRIBUTE_KEYS.forEach(attr => {
552
- newNode[attr] = inheritNode[attr];
553
- });
554
- delete newNode.layout;
555
- }
556
- const newElement = createMindElement('', getNodeDefaultFontSize(), TEXT_DEFAULT_HEIGHT, newNode);
557
- Transforms.insertNode(board, newElement, path);
558
- clearSelectedElement(board);
559
- addSelectedElement(board, newElement);
560
- setTimeout(() => {
561
- editTopic(newElement);
562
- });
427
+ const getBranchWidthByMindElement = (board, element) => {
428
+ const branchWidth = getAvailableProperty(board, element, 'branchWidth');
429
+ return branchWidth || BRANCH_WIDTH;
563
430
  };
564
- const findLastChild = (child) => {
565
- let result = child;
566
- while (result.children.length !== 0) {
567
- result = result.children[result.children.length - 1];
431
+ const getAbstractBranchWidth = (board, element) => {
432
+ if (!isNullOrUndefined(element.branchWidth)) {
433
+ return element.branchWidth;
568
434
  }
569
- return result;
435
+ return DefaultAbstractNodeStyle.branch.width;
570
436
  };
571
- const divideElementByParent = (elements) => {
572
- const abstractIncludedGroups = [];
573
- const parentElements = [];
574
- for (let i = 0; i < elements.length; i++) {
575
- const parent = MindElement.getParent(elements[i]);
576
- const parentIndex = parentElements.indexOf(parent);
577
- if (parentIndex === -1) {
578
- parentElements.push(parent);
579
- abstractIncludedGroups.push([elements[i]]);
580
- }
581
- else {
582
- abstractIncludedGroups[parentIndex].push(elements[i]);
583
- }
437
+ const getAbstractBranchColor = (board, element) => {
438
+ if (element.branchColor) {
439
+ return element.branchColor;
584
440
  }
585
- return { parentElements, abstractIncludedGroups };
441
+ return DefaultAbstractNodeStyle.branch.color;
586
442
  };
587
-
588
- const getBranchDirectionsByLayouts = (branchLayouts) => {
589
- const branchDirections = [];
590
- branchLayouts.forEach(l => {
591
- const directions = LayoutDirectionsMap[l];
592
- directions.forEach(d => {
593
- if (!branchDirections.includes(d) && !branchDirections.includes(getLayoutReverseDirection(d))) {
594
- branchDirections.push(d);
595
- }
596
- });
597
- });
598
- return branchDirections;
443
+ const getNextBranchColor = (board, root) => {
444
+ const index = root.children.length;
445
+ return getDefaultBranchColorByIndex(board, index);
599
446
  };
600
- const isCorrectLayout = (root, layout) => {
601
- const rootLayout = root.layout || getDefaultLayout();
602
- return !getInCorrectLayoutDirection(rootLayout, layout);
447
+ const getDefaultBranchColor = (board, element) => {
448
+ const path = PlaitBoard.findPath(board, element);
449
+ return getDefaultBranchColorByIndex(board, path[1]);
603
450
  };
604
- const isMixedLayout = (parentLayout, layout) => {
605
- return (!isIndentedLayout(parentLayout) && isIndentedLayout(layout)) || (isIndentedLayout(parentLayout) && !isIndentedLayout(layout));
451
+ const getDefaultBranchColorByIndex = (board, index) => {
452
+ const themeColor = getMindThemeColor(board);
453
+ const length = themeColor.branchColors.length;
454
+ const remainder = index % length;
455
+ return themeColor.branchColors[remainder];
606
456
  };
607
- const getInCorrectLayoutDirection = (rootLayout, layout) => {
608
- const directions = LayoutDirectionsMap[rootLayout];
609
- const subLayoutDirections = LayoutDirectionsMap[layout];
610
- if (!subLayoutDirections) {
611
- throw new Error(`unexpected layout: ${layout} on correct layout`);
457
+ const getMindThemeColor = (board) => {
458
+ const themeColors = PlaitBoard.getThemeColors(board);
459
+ const themeColor = themeColors.find(val => val.mode === board.theme.themeColorMode);
460
+ if (themeColor && MindThemeColor.isMindThemeColor(themeColor)) {
461
+ return themeColor;
612
462
  }
613
- return subLayoutDirections.find(d => directions.includes(getLayoutReverseDirection(d)));
614
- };
615
- const correctLayoutByDirection = (layout, direction) => {
616
- const isHorizontal = direction === LayoutDirection.left || direction === LayoutDirection.right ? true : false;
617
- let inverseDirectionLayout = MindLayoutType.standard;
618
- switch (layout) {
619
- case MindLayoutType.left:
620
- inverseDirectionLayout = MindLayoutType.right;
621
- break;
622
- case MindLayoutType.right:
623
- inverseDirectionLayout = MindLayoutType.left;
624
- break;
625
- case MindLayoutType.downward:
626
- inverseDirectionLayout = MindLayoutType.upward;
627
- break;
628
- case MindLayoutType.upward:
629
- inverseDirectionLayout = MindLayoutType.downward;
630
- break;
631
- case MindLayoutType.rightBottomIndented:
632
- inverseDirectionLayout = isHorizontal ? MindLayoutType.leftBottomIndented : MindLayoutType.rightTopIndented;
633
- break;
634
- case MindLayoutType.leftBottomIndented:
635
- inverseDirectionLayout = isHorizontal ? MindLayoutType.rightBottomIndented : MindLayoutType.leftTopIndented;
636
- break;
637
- case MindLayoutType.rightTopIndented:
638
- inverseDirectionLayout = isHorizontal ? MindLayoutType.leftTopIndented : MindLayoutType.rightBottomIndented;
639
- break;
640
- case MindLayoutType.leftTopIndented:
641
- inverseDirectionLayout = isHorizontal ? MindLayoutType.rightTopIndented : MindLayoutType.leftBottomIndented;
642
- break;
463
+ else {
464
+ return MindDefaultThemeColor;
643
465
  }
644
- return inverseDirectionLayout;
645
- };
646
- const getLayoutDirection$1 = (root) => {
647
- const layout = root.layout || getDefaultLayout();
648
- return LayoutDirectionsMap[layout];
649
- };
650
- const getDefaultLayout = () => {
651
- return MindLayoutType.standard;
652
466
  };
653
- const getAvailableSubLayoutsByLayoutDirections = (directions) => {
654
- const result = [];
655
- const reverseDirections = directions.map(getLayoutReverseDirection);
656
- for (const key in MindLayoutType) {
657
- const layout = MindLayoutType[key];
658
- const layoutDirections = LayoutDirectionsMap[layout];
659
- if (layoutDirections) {
660
- const hasSameDirection = layoutDirections.some(d => directions.includes(d));
661
- const hasReverseDirection = layoutDirections.some(r => reverseDirections.includes(r));
662
- if (hasSameDirection && !hasReverseDirection) {
663
- result.push(layout);
664
- }
665
- }
467
+
468
+ const getStrokeByMindElement = (board, element) => {
469
+ if (PlaitMind.isMind(element)) {
470
+ const defaultRootStroke = getMindThemeColor(board).rootFill;
471
+ return element.strokeColor || defaultRootStroke;
666
472
  }
667
- return result;
668
- };
669
- const getLayoutReverseDirection = (layoutDirection) => {
670
- let reverseDirection = LayoutDirection.right;
671
- switch (layoutDirection) {
672
- case LayoutDirection.top:
673
- reverseDirection = LayoutDirection.bottom;
674
- break;
675
- case LayoutDirection.bottom:
676
- reverseDirection = LayoutDirection.top;
677
- break;
678
- case LayoutDirection.right:
679
- reverseDirection = LayoutDirection.left;
680
- break;
681
- case LayoutDirection.left:
682
- reverseDirection = LayoutDirection.right;
683
- break;
473
+ if (AbstractNode.isAbstract(element) || isChildOfAbstract(board, element)) {
474
+ return element.strokeColor || DefaultAbstractNodeStyle.shape.strokeColor;
684
475
  }
685
- return reverseDirection;
476
+ return getAvailableProperty(board, element, 'strokeColor') || getDefaultBranchColor(board, element);
686
477
  };
687
- const getRootLayout = (root) => {
688
- return root.layout || getDefaultLayout();
478
+ const getStrokeWidthByElement = (board, element) => {
479
+ const strokeWidth = element.strokeWidth ||
480
+ (AbstractNode.isAbstract(element) ? DefaultAbstractNodeStyle.shape.strokeWidth : DefaultNodeStyle.shape.strokeWidth);
481
+ return strokeWidth;
689
482
  };
690
-
691
- const adjustRootToNode = (board, node) => {
692
- const newNode = { ...node };
693
- delete newNode.isRoot;
694
- delete newNode.rightNodeCount;
695
- delete newNode.type;
696
- if (newNode.layout === MindLayoutType.standard) {
697
- delete newNode.layout;
483
+ const getFillByElement = (board, element) => {
484
+ if (element.fill) {
485
+ return element.fill;
698
486
  }
699
- return newNode;
700
- };
701
- const adjustAbstractToNode = (node) => {
702
- const newNode = { ...node };
703
- delete newNode.start;
704
- delete newNode.end;
705
- return newNode;
487
+ const defaultRootFill = getMindThemeColor(board).rootFill;
488
+ return element.isRoot ? defaultRootFill : DefaultNodeStyle.shape.fill;
706
489
  };
707
- const adjustNodeToRoot = (board, node) => {
708
- const newElement = { ...node };
709
- if (!Node$1.string(newElement.data.topic)) {
710
- newElement.data.topic = { children: [{ text: '思维导图' }] };
711
- }
712
- delete newElement?.strokeColor;
713
- delete newElement?.fill;
714
- delete newElement?.shape;
715
- delete newElement?.strokeWidth;
716
- delete newElement?.isCollapsed;
717
- const { width, height } = getTextSize(board, newElement.data.topic, TOPIC_DEFAULT_MAX_WORD_COUNT, {
718
- fontSize: ROOT_TOPIC_FONT_SIZE,
719
- fontFamily: BRANCH_FONT_FAMILY,
720
- width: node.manualWidth ? node.manualWidth : undefined
721
- });
722
- newElement.width = Math.max(width, getNodeDefaultFontSize(true));
723
- newElement.height = height;
724
- return {
725
- ...newElement,
726
- layout: newElement.layout ?? MindLayoutType.right,
727
- isRoot: true,
728
- type: 'mindmap'
729
- };
490
+ const getShapeByElement = (board, element) => {
491
+ const shape = getAvailableProperty(board, element, 'shape');
492
+ return shape || MindElementShape.roundRectangle;
730
493
  };
731
494
 
732
- const DefaultAbstractNodeStyle = {
733
- branch: { color: GRAY_COLOR, width: 2 },
734
- shape: {
735
- strokeColor: GRAY_COLOR,
736
- strokeWidth: 2
737
- }
738
- };
739
- const DefaultNodeStyle = {
740
- branch: {
741
- width: 3
495
+ const NodeDefaultSpace = {
496
+ horizontal: {
497
+ nodeAndText: BASE * 2.5,
498
+ emojiAndText: BASE * 1.5
742
499
  },
743
- shape: {
744
- rectangleRadius: 4,
745
- strokeWidth: 3,
746
- fill: 'none'
500
+ vertical: {
501
+ nodeAndText: BASE,
502
+ nodeAndImage: BASE,
503
+ imageAndText: BASE * 1.5
747
504
  }
748
505
  };
749
-
750
- const setAbstractsByRefs = (board, abstractRefs) => {
751
- abstractRefs.forEach((newProperty, element) => {
752
- const start = element.start + newProperty.start;
753
- const end = element.end + newProperty.end;
754
- const path = PlaitBoard.findPath(board, element);
755
- if (start > end) {
756
- Transforms.removeNode(board, path);
757
- }
758
- else {
759
- Transforms.setNode(board, { start, end }, path);
760
- }
761
- });
762
- };
763
- const setAbstractByStandardLayout = (board, element) => {
764
- const rightNodeCount = element.rightNodeCount;
765
- const abstract = element.children.find(child => {
766
- return AbstractNode.isAbstract(child) && child.end >= rightNodeCount && child.start < rightNodeCount;
767
- });
768
- if (abstract) {
769
- const path = PlaitBoard.findPath(board, abstract);
770
- Transforms.setNode(board, { end: rightNodeCount - 1 }, path);
506
+ const RootDefaultSpace = {
507
+ horizontal: {
508
+ nodeAndText: BASE * 4,
509
+ emojiAndText: BASE * 2
510
+ },
511
+ vertical: {
512
+ nodeAndText: BASE * 2
771
513
  }
772
514
  };
773
- const insertAbstract = (board, elements) => {
774
- let elementGroup = getFirstLevelElement(elements);
775
- const { parentElements, abstractIncludedGroups } = divideElementByParent(elementGroup);
776
- abstractIncludedGroups.forEach((group, index) => {
777
- const groupParent = parentElements[index];
778
- setAbstractByElements(board, groupParent, group);
779
- });
515
+ const getHorizontalSpaceBetweenNodeAndText = (board, element) => {
516
+ const isMind = PlaitMind.isMind(element);
517
+ const nodeAndText = isMind ? RootDefaultSpace.horizontal.nodeAndText : NodeDefaultSpace.horizontal.nodeAndText;
518
+ const strokeWidth = getStrokeWidthByElement(board, element);
519
+ return nodeAndText + strokeWidth;
780
520
  };
781
- const setAbstractByElements = (board, groupParent, group) => {
782
- const indexArray = group.map(child => groupParent.children.indexOf(child)).sort((a, b) => a - b);
783
- const rightNodeCount = groupParent?.rightNodeCount;
784
- const start = indexArray[0], end = indexArray[indexArray.length - 1];
785
- if (isStandardLayout(MindQueries.getLayoutByElement(groupParent)) &&
786
- rightNodeCount &&
787
- start < rightNodeCount &&
788
- end >= rightNodeCount) {
789
- const childrenLength = groupParent.children.length;
790
- const path = [...PlaitBoard.findPath(board, groupParent), childrenLength];
791
- const leftChildren = indexArray.filter(index => index >= rightNodeCount);
792
- const rightChildren = indexArray.filter(index => index < rightNodeCount);
793
- insertAbstractNode(board, path, rightChildren[0], rightChildren[rightChildren.length - 1]);
794
- insertAbstractNode(board, Path.next(path), leftChildren[0], leftChildren[leftChildren.length - 1]);
795
- }
796
- else {
797
- const path = [...PlaitBoard.findPath(board, groupParent), groupParent.children.length];
798
- insertAbstractNode(board, path, start, end);
799
- }
521
+ const getVerticalSpaceBetweenNodeAndText = (board, element) => {
522
+ const isMind = PlaitMind.isMind(element);
523
+ const strokeWidth = getStrokeWidthByElement(board, element);
524
+ const nodeAndText = isMind ? RootDefaultSpace.vertical.nodeAndText : NodeDefaultSpace.vertical.nodeAndText;
525
+ return nodeAndText + strokeWidth;
800
526
  };
801
- const insertAbstractNode = (board, path, start, end) => {
802
- const mindElement = createMindElement('概要', 28, 20, {
803
- strokeWidth: DefaultAbstractNodeStyle.branch.width,
804
- branchWidth: DefaultAbstractNodeStyle.branch.width
805
- });
806
- mindElement.start = start;
807
- mindElement.end = end;
808
- Transforms.insertNode(board, mindElement, path);
809
- clearSelectedElement(board);
810
- addSelectedElement(board, mindElement);
527
+ const getSpaceEmojiAndText = (element) => {
528
+ const isMind = PlaitMind.isMind(element);
529
+ const emojiAndText = isMind ? RootDefaultSpace.horizontal.emojiAndText : NodeDefaultSpace.horizontal.emojiAndText;
530
+ return emojiAndText;
811
531
  };
812
-
813
- const setLayout = (board, layout, path) => {
814
- correctLogicLayoutNode(board, layout, path);
815
- const element = PlaitNode.get(board, path);
816
- if (PlaitMind.isMind(element) && isStandardLayout(layout)) {
817
- MindTransforms.setAbstractByStandardLayout(board, element);
818
- }
819
- Transforms.setNode(board, { layout }, path);
820
- };
821
- const correctLogicLayoutNode = (board, layout, path) => {
822
- const node = PlaitNode.get(board, path);
823
- if (node && layout) {
824
- node.children?.forEach((value, index) => {
825
- if (value.layout) {
826
- if ((isHorizontalLogicLayout(layout) && isVerticalLogicLayout(value.layout)) ||
827
- (isVerticalLogicLayout(layout) && isHorizontalLogicLayout(value.layout))) {
828
- Transforms.setNode(board, { layout: null }, [...path, index]);
829
- }
830
- if (value.children?.length) {
831
- correctLogicLayoutNode(board, layout, [...path, index]);
832
- }
833
- }
834
- });
835
- }
836
- };
837
-
838
- const separateChildren = (parentElement) => {
839
- const rightNodeCount = parentElement.rightNodeCount;
840
- const children = parentElement.children;
841
- let rightChildren = [], leftChildren = [];
842
- for (let i = 0; i < children.length; i++) {
843
- const child = children[i];
844
- if (AbstractNode.isAbstract(child) && child.end < rightNodeCount) {
845
- rightChildren.push(child);
846
- continue;
532
+ const NodeSpace = {
533
+ getNodeWidth(board, element) {
534
+ const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
535
+ if (MindElement.hasEmojis(element)) {
536
+ return (NodeSpace.getEmojiLeftSpace(board, element) +
537
+ getEmojisWidthHeight(board, element).width +
538
+ getSpaceEmojiAndText(element) +
539
+ NodeSpace.getNodeDynamicWidth(board, element) +
540
+ nodeAndText);
847
541
  }
848
- if (AbstractNode.isAbstract(child) && child.start >= rightNodeCount) {
849
- leftChildren.push(child);
850
- continue;
542
+ return nodeAndText + NodeSpace.getNodeDynamicWidth(board, element) + nodeAndText;
543
+ },
544
+ getNodeHeight(board, element) {
545
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
546
+ if (MindElement.hasImage(element)) {
547
+ return NodeSpace.getTextTopSpace(board, element) + element.height + nodeAndText;
851
548
  }
852
- if (i < rightNodeCount) {
853
- rightChildren.push(child);
549
+ return nodeAndText + element.height + nodeAndText;
550
+ },
551
+ getNodeDynamicWidth(board, element) {
552
+ const width = element.manualWidth || element.width;
553
+ const imageWidth = MindElement.hasImage(element) ? element.data.image?.width : 0;
554
+ return Math.max(width, imageWidth);
555
+ },
556
+ /**
557
+ * use it when upload image first or resize image
558
+ */
559
+ getNodeNewDynamicWidth(board, element, imageWidth) {
560
+ const width = element.manualWidth || element.width;
561
+ return Math.max(width, imageWidth);
562
+ },
563
+ getNodeResizableMinWidth(board, element) {
564
+ const minTopicWidth = NodeSpace.getNodeTopicMinWidth(board, element);
565
+ if (MindElement.hasImage(element) && element.data.image.width > minTopicWidth) {
566
+ return element.data.image.width;
854
567
  }
855
568
  else {
856
- leftChildren.push(child);
569
+ return minTopicWidth;
570
+ }
571
+ },
572
+ getNodeTopicMinWidth(board, element, isRoot = false) {
573
+ const defaultFontSize = getNodeDefaultFontSize(isRoot);
574
+ const editor = MindElement.getTextEditor(element);
575
+ const marks = PlaitMarkEditor.getMarks(editor);
576
+ const fontSize = marks[MarkTypes.fontSize] || defaultFontSize;
577
+ return fontSize;
578
+ },
579
+ getTextLeftSpace(board, element) {
580
+ const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
581
+ if (MindElement.hasEmojis(element)) {
582
+ return NodeSpace.getEmojiLeftSpace(board, element) + getEmojisWidthHeight(board, element).width + getSpaceEmojiAndText(element);
583
+ }
584
+ else {
585
+ return nodeAndText;
857
586
  }
587
+ },
588
+ getTextTopSpace(board, element) {
589
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
590
+ if (MindElement.hasImage(element)) {
591
+ return NodeSpace.getImageTopSpace(board, element) + element.data.image.height + NodeDefaultSpace.vertical.imageAndText;
592
+ }
593
+ else {
594
+ return nodeAndText;
595
+ }
596
+ },
597
+ getImageTopSpace(board, element) {
598
+ const strokeWidth = getStrokeWidthByElement(board, element);
599
+ return strokeWidth + NodeDefaultSpace.vertical.nodeAndImage;
600
+ },
601
+ getEmojiLeftSpace(board, element) {
602
+ const options = board.getPluginOptions(WithMindPluginKey);
603
+ const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
604
+ return nodeAndText - options.emojiPadding;
605
+ },
606
+ getEmojiTopSpace(board, element) {
607
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
608
+ return nodeAndText;
858
609
  }
859
- return { leftChildren, rightChildren };
860
610
  };
861
- const isSetAbstract = (element) => {
862
- return !!getCorrespondingAbstract(element);
611
+ const getFontSizeBySlateElement = (text) => {
612
+ const defaultFontSize = DEFAULT_FONT_SIZE;
613
+ if (typeof text === 'string') {
614
+ return defaultFontSize;
615
+ }
616
+ const marks = PlaitMarkEditor.getMarksByElement(text);
617
+ const fontSize = marks[MarkTypes.fontSize] || defaultFontSize;
618
+ return fontSize;
863
619
  };
864
- const canSetAbstract = (element) => {
865
- return !PlaitElement.isRootElement(element) && !AbstractNode.isAbstract(element) && !isSetAbstract(element);
620
+ const getNodeDefaultFontSize = (isRoot = false) => {
621
+ const defaultFontSize = isRoot ? ROOT_TOPIC_FONT_SIZE : DEFAULT_FONT_SIZE;
622
+ return defaultFontSize;
866
623
  };
867
- const getCorrespondingAbstract = (element) => {
868
- const parent = MindElement.findParent(element);
869
- if (!parent)
870
- return undefined;
871
- const elementIndex = parent.children.indexOf(element);
872
- return parent.children.find(child => {
873
- return AbstractNode.isAbstract(child) && elementIndex >= child.start && elementIndex <= child.end;
874
- });
624
+
625
+ function getRectangleByNode(node) {
626
+ const x = node.x + node.hGap;
627
+ let y = node.y + node.vGap;
628
+ const width = node.width - node.hGap * 2;
629
+ const height = node.height - node.vGap * 2;
630
+ return {
631
+ x,
632
+ y,
633
+ width,
634
+ height
635
+ };
636
+ }
637
+ function getRectangleByElement(board, element) {
638
+ const width = NodeSpace.getNodeWidth(board, element);
639
+ const height = NodeSpace.getNodeHeight(board, element);
640
+ const nodeRectangle = {
641
+ x: element.points[0][0],
642
+ y: element.points[0][1],
643
+ width,
644
+ height
645
+ };
646
+ return nodeRectangle;
647
+ }
648
+ function isHitMindElement(board, point, element) {
649
+ const node = MindElement.getNode(element);
650
+ if (node && distanceBetweenPointAndRectangle(point[0], point[1], getRectangleByNode(node)) === 0) {
651
+ return true;
652
+ }
653
+ else {
654
+ return false;
655
+ }
656
+ }
657
+
658
+ function getEmojiRectangle(board, element) {
659
+ let { x, y } = getRectangleByNode(MindElement.getNode(element));
660
+ x = x + NodeSpace.getEmojiLeftSpace(board, element);
661
+ const { width, height } = getEmojisWidthHeight(board, element);
662
+ return {
663
+ x,
664
+ y,
665
+ width,
666
+ height
667
+ };
668
+ }
669
+ function getEmojiForeignRectangle(board, element) {
670
+ let { x, y } = getRectangleByNode(MindElement.getNode(element));
671
+ x = x + NodeSpace.getEmojiLeftSpace(board, element);
672
+ const { width } = getEmojisWidthHeight(board, element);
673
+ return {
674
+ x,
675
+ y,
676
+ width,
677
+ height: NodeSpace.getNodeHeight(board, element)
678
+ };
679
+ }
680
+ const isHitEmojis = (board, element, point) => {
681
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), getEmojiRectangle(board, element));
875
682
  };
876
- const getBehindAbstracts = (element) => {
877
- const parent = MindElement.findParent(element);
878
- if (!parent)
879
- return [];
880
- const index = parent.children.indexOf(element);
881
- return parent.children.filter(child => AbstractNode.isAbstract(child) && child.start > index);
683
+
684
+ function getTopicRectangleByNode(board, node) {
685
+ let nodeRectangle = getRectangleByNode(node);
686
+ const result = getTopicRectangleByElement(board, nodeRectangle, node.origin);
687
+ result.width = result.width;
688
+ return result;
689
+ }
690
+ function getTopicRectangleByElement(board, nodeRectangle, element) {
691
+ const x = nodeRectangle.x + NodeSpace.getTextLeftSpace(board, element);
692
+ const y = nodeRectangle.y + NodeSpace.getTextTopSpace(board, element);
693
+ const width = NodeSpace.getNodeDynamicWidth(board, element);
694
+ const height = Math.ceil(element.height);
695
+ return { height, width, x, y };
696
+ }
697
+
698
+ function getImageForeignRectangle(board, element) {
699
+ let { x, y } = getRectangleByNode(MindElement.getNode(element));
700
+ const elementWidth = element.manualWidth || element.width;
701
+ x =
702
+ elementWidth > element.data.image.width
703
+ ? x + NodeSpace.getTextLeftSpace(board, element) + (elementWidth - element.data.image.width) / 2
704
+ : x + NodeSpace.getTextLeftSpace(board, element);
705
+ y = NodeSpace.getImageTopSpace(board, element) + y;
706
+ const { width, height } = element.data.image;
707
+ const rectangle = {
708
+ x,
709
+ y,
710
+ width,
711
+ height
712
+ };
713
+ return rectangle;
714
+ }
715
+ const isHitImage = (board, element, range) => {
716
+ const imageRectangle = getImageForeignRectangle(board, element);
717
+ const imageOutlineRectangle = RectangleClient.getOutlineRectangle(imageRectangle, -RESIZE_HANDLE_DIAMETER / 2);
718
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([range.anchor, range.focus]), imageOutlineRectangle);
882
719
  };
883
- /**
884
- * return corresponding abstract that is not child of elements
885
- */
886
- const getOverallAbstracts = (board, elements) => {
887
- const overallAbstracts = [];
888
- elements
889
- .filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
890
- .forEach(value => {
891
- const abstract = getCorrespondingAbstract(value);
892
- if (abstract && elements.indexOf(abstract) === -1 && overallAbstracts.indexOf(abstract) === -1) {
893
- const { start, end } = abstract;
894
- const parent = MindElement.getParent(value);
895
- const isOverall = parent.children.slice(start, end + 1).every(includedElement => elements.indexOf(includedElement) > -1);
896
- if (isOverall) {
897
- overallAbstracts.push(abstract);
898
- }
899
- }
720
+ const getHitImageResizeHandleDirection = (board, element, point) => {
721
+ const imageRectangle = getImageForeignRectangle(board, element);
722
+ const resizeHandleRefs = getRectangleResizeHandleRefs(imageRectangle, RESIZE_HANDLE_DIAMETER);
723
+ const result = resizeHandleRefs.find(resizeHandleRef => {
724
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), resizeHandleRef.rectangle);
900
725
  });
901
- return overallAbstracts;
726
+ return result;
902
727
  };
903
- /**
904
- * abstract node is valid when elements contains at least one element it is referenced with
905
- */
906
- const getValidAbstractRefs = (board, elements) => {
907
- const validAbstractRefs = [];
908
- elements
909
- .filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
910
- .forEach(value => {
911
- const abstract = getCorrespondingAbstract(value);
912
- if (abstract && elements.indexOf(abstract) > 0) {
913
- const index = validAbstractRefs.findIndex(value => value.abstract === abstract);
914
- if (index === -1) {
915
- validAbstractRefs.push({
916
- abstract: abstract,
917
- references: [value]
918
- });
919
- }
920
- else {
921
- validAbstractRefs[index].references.push(value);
728
+
729
+ function editTopic(element) {
730
+ const component = PlaitElement.getComponent(element);
731
+ component?.editTopic();
732
+ }
733
+ const temporaryDisableSelection = (board) => {
734
+ const currentOptions = board.getPluginOptions(PlaitPluginKey.withSelection);
735
+ board.setPluginOptions(PlaitPluginKey.withSelection, {
736
+ isDisabledSelect: true
737
+ });
738
+ setTimeout(() => {
739
+ board.setPluginOptions(PlaitPluginKey.withSelection, { ...currentOptions });
740
+ }, 0);
741
+ };
742
+ const getSelectedMindElements = (board) => {
743
+ const selectedElements = getSelectedElements(board).filter(value => MindElement.isMindElement(board, value));
744
+ return selectedElements;
745
+ };
746
+
747
+ const getBranchDirectionsByLayouts = (branchLayouts) => {
748
+ const branchDirections = [];
749
+ branchLayouts.forEach(l => {
750
+ const directions = LayoutDirectionsMap[l];
751
+ directions.forEach(d => {
752
+ if (!branchDirections.includes(d) && !branchDirections.includes(getLayoutReverseDirection(d))) {
753
+ branchDirections.push(d);
922
754
  }
923
- }
755
+ });
924
756
  });
925
- return validAbstractRefs;
757
+ return branchDirections;
926
758
  };
927
- function getRelativeStartEndByAbstractRef(abstractRef, elements) {
928
- const start = elements.indexOf(abstractRef.references[0]);
929
- const end = elements.indexOf(abstractRef.references[abstractRef.references.length - 1]);
930
- return { start, end };
931
- }
932
- const insertElementHandleAbstract = (board, path, step = 1,
933
- //由此区分拖拽和新增到概要概括最后一个节点
934
- isExtendPreviousNode = true, effectedAbstracts = new Map()) => {
935
- const parent = PlaitNode.parent(board, path);
936
- const hasPreviousNode = path[path.length - 1] !== 0;
937
- let behindAbstracts;
938
- if (!hasPreviousNode) {
939
- behindAbstracts = parent.children.filter(child => AbstractNode.isAbstract(child));
759
+ const isCorrectLayout = (root, layout) => {
760
+ const rootLayout = root.layout || getDefaultLayout();
761
+ return !getInCorrectLayoutDirection(rootLayout, layout);
762
+ };
763
+ const isMixedLayout = (parentLayout, layout) => {
764
+ return (!isIndentedLayout(parentLayout) && isIndentedLayout(layout)) || (isIndentedLayout(parentLayout) && !isIndentedLayout(layout));
765
+ };
766
+ const getInCorrectLayoutDirection = (rootLayout, layout) => {
767
+ const directions = LayoutDirectionsMap[rootLayout];
768
+ const subLayoutDirections = LayoutDirectionsMap[layout];
769
+ if (!subLayoutDirections) {
770
+ throw new Error(`unexpected layout: ${layout} on correct layout`);
940
771
  }
941
- else {
942
- const selectedElement = PlaitNode.get(board, Path.previous(path));
943
- behindAbstracts = getBehindAbstracts(selectedElement);
772
+ return subLayoutDirections.find(d => directions.includes(getLayoutReverseDirection(d)));
773
+ };
774
+ const correctLayoutByDirection = (layout, direction) => {
775
+ const isHorizontal = direction === LayoutDirection.left || direction === LayoutDirection.right ? true : false;
776
+ let inverseDirectionLayout = MindLayoutType.standard;
777
+ switch (layout) {
778
+ case MindLayoutType.left:
779
+ inverseDirectionLayout = MindLayoutType.right;
780
+ break;
781
+ case MindLayoutType.right:
782
+ inverseDirectionLayout = MindLayoutType.left;
783
+ break;
784
+ case MindLayoutType.downward:
785
+ inverseDirectionLayout = MindLayoutType.upward;
786
+ break;
787
+ case MindLayoutType.upward:
788
+ inverseDirectionLayout = MindLayoutType.downward;
789
+ break;
790
+ case MindLayoutType.rightBottomIndented:
791
+ inverseDirectionLayout = isHorizontal ? MindLayoutType.leftBottomIndented : MindLayoutType.rightTopIndented;
792
+ break;
793
+ case MindLayoutType.leftBottomIndented:
794
+ inverseDirectionLayout = isHorizontal ? MindLayoutType.rightBottomIndented : MindLayoutType.leftTopIndented;
795
+ break;
796
+ case MindLayoutType.rightTopIndented:
797
+ inverseDirectionLayout = isHorizontal ? MindLayoutType.leftTopIndented : MindLayoutType.rightBottomIndented;
798
+ break;
799
+ case MindLayoutType.leftTopIndented:
800
+ inverseDirectionLayout = isHorizontal ? MindLayoutType.rightTopIndented : MindLayoutType.leftBottomIndented;
801
+ break;
944
802
  }
945
- if (behindAbstracts.length) {
946
- behindAbstracts.forEach(abstract => {
947
- let newProperties = effectedAbstracts.get(abstract);
948
- if (!newProperties) {
949
- newProperties = { start: 0, end: 0 };
950
- effectedAbstracts.set(abstract, newProperties);
803
+ return inverseDirectionLayout;
804
+ };
805
+ const getLayoutDirection$1 = (root) => {
806
+ const layout = root.layout || getDefaultLayout();
807
+ return LayoutDirectionsMap[layout];
808
+ };
809
+ const getDefaultLayout = () => {
810
+ return MindLayoutType.standard;
811
+ };
812
+ const getAvailableSubLayoutsByLayoutDirections = (directions) => {
813
+ const result = [];
814
+ const reverseDirections = directions.map(getLayoutReverseDirection);
815
+ for (const key in MindLayoutType) {
816
+ const layout = MindLayoutType[key];
817
+ const layoutDirections = LayoutDirectionsMap[layout];
818
+ if (layoutDirections) {
819
+ const hasSameDirection = layoutDirections.some(d => directions.includes(d));
820
+ const hasReverseDirection = layoutDirections.some(r => reverseDirections.includes(r));
821
+ if (hasSameDirection && !hasReverseDirection) {
822
+ result.push(layout);
951
823
  }
952
- newProperties.start = newProperties.start + step;
953
- newProperties.end = newProperties.end + step;
954
- });
824
+ }
955
825
  }
956
- if (!hasPreviousNode) {
957
- return effectedAbstracts;
826
+ return result;
827
+ };
828
+ const getLayoutReverseDirection = (layoutDirection) => {
829
+ let reverseDirection = LayoutDirection.right;
830
+ switch (layoutDirection) {
831
+ case LayoutDirection.top:
832
+ reverseDirection = LayoutDirection.bottom;
833
+ break;
834
+ case LayoutDirection.bottom:
835
+ reverseDirection = LayoutDirection.top;
836
+ break;
837
+ case LayoutDirection.right:
838
+ reverseDirection = LayoutDirection.left;
839
+ break;
840
+ case LayoutDirection.left:
841
+ reverseDirection = LayoutDirection.right;
842
+ break;
958
843
  }
959
- const selectedElement = PlaitNode.get(board, Path.previous(path));
960
- const correspondingAbstract = getCorrespondingAbstract(selectedElement);
961
- const isDragToLast = !isExtendPreviousNode && correspondingAbstract && correspondingAbstract.end === path[path.length - 1] - 1;
962
- if (correspondingAbstract && !isDragToLast) {
963
- let newProperties = effectedAbstracts.get(correspondingAbstract);
964
- if (!newProperties) {
965
- newProperties = { start: 0, end: 0 };
966
- effectedAbstracts.set(correspondingAbstract, newProperties);
844
+ return reverseDirection;
845
+ };
846
+ const getRootLayout = (root) => {
847
+ return root.layout || getDefaultLayout();
848
+ };
849
+
850
+ const getLayoutOptions = (board) => {
851
+ function getMainAxle(element, parent) {
852
+ if (element.isRoot) {
853
+ return BASE * 12;
967
854
  }
968
- newProperties.end = newProperties.end + step;
855
+ if (parent && parent.isRoot()) {
856
+ return BASE * 3;
857
+ }
858
+ return BASE * 3;
969
859
  }
970
- return effectedAbstracts;
971
- };
972
- const deleteElementHandleAbstract = (board, deletableElements, effectedAbstracts = new Map()) => {
973
- deletableElements.forEach(node => {
974
- if (!PlaitMind.isMind(node)) {
975
- const behindAbstracts = getBehindAbstracts(node).filter(abstract => !deletableElements.includes(abstract));
976
- if (behindAbstracts.length) {
977
- behindAbstracts.forEach(abstract => {
978
- let newProperties = effectedAbstracts.get(abstract);
979
- if (!newProperties) {
980
- newProperties = { start: 0, end: 0 };
981
- effectedAbstracts.set(abstract, newProperties);
982
- }
983
- newProperties.start = newProperties.start - 1;
984
- newProperties.end = newProperties.end - 1;
985
- });
860
+ function getSecondAxle(element, parent) {
861
+ if (element.isRoot) {
862
+ return BASE * 10;
863
+ }
864
+ return BASE * 6;
865
+ }
866
+ return {
867
+ getHeight(element) {
868
+ return NodeSpace.getNodeHeight(board, element);
869
+ },
870
+ getWidth(element) {
871
+ return NodeSpace.getNodeWidth(board, element);
872
+ },
873
+ getHorizontalGap(element, parent) {
874
+ const _layout = (parent && parent.layout) || getRootLayout(element);
875
+ const isHorizontal = isHorizontalLayout(_layout);
876
+ if (isIndentedLayout(_layout)) {
877
+ return BASE * 4;
986
878
  }
987
- const correspondingAbstract = getCorrespondingAbstract(node);
988
- if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
989
- let newProperties = effectedAbstracts.get(correspondingAbstract);
990
- if (!newProperties) {
991
- newProperties = { start: 0, end: 0 };
992
- effectedAbstracts.set(correspondingAbstract, newProperties);
993
- }
994
- newProperties.end = newProperties.end - 1;
879
+ if (!isHorizontal) {
880
+ return getMainAxle(element, parent);
881
+ }
882
+ else {
883
+ return getSecondAxle(element, parent);
884
+ }
885
+ },
886
+ getVerticalGap(element, parent) {
887
+ const _layout = (parent && parent.layout) || getRootLayout(element);
888
+ if (isIndentedLayout(_layout)) {
889
+ return BASE;
890
+ }
891
+ const isHorizontal = isHorizontalLayout(_layout);
892
+ if (isHorizontal) {
893
+ return getMainAxle(element, parent);
894
+ }
895
+ else {
896
+ return getSecondAxle(element, parent);
897
+ }
898
+ },
899
+ getVerticalConnectingPosition(element, parent) {
900
+ if (element.shape === MindElementShape.underline && parent && isHorizontalLogicLayout(parent.layout)) {
901
+ return ConnectingPosition.bottom;
995
902
  }
903
+ return undefined;
904
+ },
905
+ getExtendHeight(node) {
906
+ return BASE * 6;
907
+ },
908
+ getIndentedCrossLevelGap() {
909
+ return BASE * 2;
996
910
  }
997
- });
998
- return effectedAbstracts;
999
- };
1000
- const isChildOfAbstract = (board, element) => {
1001
- const ancestors = MindElement.getAncestors(board, element);
1002
- return !!ancestors.find((value) => AbstractNode.isAbstract(value));
911
+ };
1003
912
  };
1004
913
 
1005
- const normalizeWidthAndHeight = (board, element, width, height) => {
1006
- const minWidth = NodeSpace.getNodeTopicMinWidth(board, element, element.isRoot);
1007
- const newWidth = width < minWidth * board.viewport.zoom ? minWidth : width / board.viewport.zoom;
1008
- const newHeight = height / board.viewport.zoom;
1009
- return { width: newWidth, height: newHeight };
1010
- };
1011
- const setTopic = (board, element, topic, width, height) => {
1012
- const newElement = {
1013
- data: { ...element.data, topic },
1014
- ...normalizeWidthAndHeight(board, element, width, height)
1015
- };
1016
- const path = PlaitBoard.findPath(board, element);
1017
- Transforms.setNode(board, newElement, path);
914
+ const createEmptyMind = (board, point) => {
915
+ const element = createMindElement('思维导图', ROOT_TOPIC_WIDTH, ROOT_TOPIC_HEIGHT, { layout: MindLayoutType.right });
916
+ element.isRoot = true;
917
+ element.type = 'mindmap';
918
+ const width = NodeSpace.getNodeWidth(board, element);
919
+ const height = NodeSpace.getNodeHeight(board, element);
920
+ element.points = [[point[0] - width / 2, point[1] - height / 2]];
921
+ return element;
1018
922
  };
1019
- const setNodeManualWidth = (board, element, width, height) => {
1020
- const path = PlaitBoard.findPath(board, element);
1021
- const { width: normalizedWidth, height: normalizedHeight } = normalizeWidthAndHeight(board, element, width, height);
1022
- const newElement = { manualWidth: normalizedWidth, height: normalizedHeight };
1023
- Transforms.setNode(board, newElement, path);
923
+ const createDefaultMind = (point, rightNodeCount, layout) => {
924
+ const root = createMindElement('思维导图', ROOT_TOPIC_WIDTH, ROOT_TOPIC_HEIGHT, { layout });
925
+ root.rightNodeCount = rightNodeCount;
926
+ root.isRoot = true;
927
+ root.type = 'mindmap';
928
+ root.points = [point];
929
+ const children = [1, 1, 1].map(() => {
930
+ return createMindElement('新建节点', 56, TEXT_DEFAULT_HEIGHT, {});
931
+ });
932
+ root.children = children;
933
+ return root;
1024
934
  };
1025
- const setTopicSize = (board, element, width, height) => {
935
+ const createMindElement = (text, width, height, options) => {
1026
936
  const newElement = {
1027
- ...normalizeWidthAndHeight(board, element, width, height)
937
+ id: idCreator(),
938
+ data: {
939
+ topic: buildText(text)
940
+ },
941
+ children: [],
942
+ width,
943
+ height
1028
944
  };
1029
- let isEqualWidth = Math.ceil(element.width) === Math.ceil(newElement.width);
1030
- let isEqualHeight = Math.ceil(element.height) === Math.ceil(newElement.height);
1031
- if (element.manualWidth) {
1032
- isEqualWidth = true;
1033
- }
1034
- if (!isEqualWidth || !isEqualHeight) {
1035
- const path = PlaitBoard.findPath(board, element);
1036
- Transforms.setNode(board, newElement, path);
945
+ let key;
946
+ for (key in options) {
947
+ if (!isNullOrUndefined(options[key])) {
948
+ newElement[key] = options[key];
949
+ }
1037
950
  }
951
+ return newElement;
1038
952
  };
1039
- const removeElements = (board, elements) => {
1040
- const deletableElements = getFirstLevelElement(elements);
1041
- deletableElements
1042
- .map(element => {
1043
- const path = PlaitBoard.findPath(board, element);
1044
- const ref = board.pathRef(path);
1045
- return () => {
1046
- Transforms.removeNode(board, ref.current);
1047
- ref.unref();
1048
- };
1049
- })
1050
- .forEach(action => {
1051
- action();
1052
- });
953
+ const INHERIT_ATTRIBUTE_KEYS = [
954
+ 'fill',
955
+ 'strokeColor',
956
+ 'strokeWidth',
957
+ 'shape',
958
+ 'layout',
959
+ 'branchColor',
960
+ 'branchWidth',
961
+ 'branchShape'
962
+ ];
963
+
964
+ const getChildrenCount = (element) => {
965
+ const count = element.children.reduce((p, c) => {
966
+ return p + getChildrenCount(c);
967
+ }, 0);
968
+ return count + element.children.length;
1053
969
  };
1054
- const insertNodes = (board, elements, path) => {
1055
- const pathRef = board.pathRef(path);
1056
- elements.forEach(element => {
1057
- if (pathRef.current) {
1058
- Transforms.insertNode(board, element, pathRef.current);
970
+ const isChildElement = (origin, child) => {
971
+ let parent = MindElement.findParent(child);
972
+ while (parent) {
973
+ if (parent === origin) {
974
+ return true;
1059
975
  }
1060
- });
1061
- pathRef.unref();
976
+ parent = MindElement.findParent(parent);
977
+ }
978
+ return false;
1062
979
  };
1063
- const insertAbstractNodes = (board, validAbstractRefs, elements, path) => {
1064
- const parent = PlaitNode.get(board, Path$1.parent(path));
1065
- const abstractPath = [...Path$1.parent(path), parent.children?.length];
1066
- const abstracts = validAbstractRefs.map(refs => {
1067
- const { start, end } = getRelativeStartEndByAbstractRef(refs, elements);
1068
- return {
1069
- ...refs.abstract,
1070
- start: start + path[path.length - 1],
1071
- end: end + path[path.length - 1]
1072
- };
980
+ const getFirstLevelElement = (elements) => {
981
+ let result = [];
982
+ elements.forEach(element => {
983
+ const isChild = elements.some(node => {
984
+ return isChildElement(node, element);
985
+ });
986
+ if (!isChild) {
987
+ result.push(element);
988
+ }
1073
989
  });
1074
- insertNodes(board, abstracts, abstractPath);
990
+ return result;
1075
991
  };
1076
- const setRightNodeCountByRefs = (board, refs) => {
1077
- refs.forEach(ref => {
1078
- Transforms.setNode(board, { rightNodeCount: ref.rightNodeCount }, ref.path);
1079
- });
992
+ const isChildRight = (node, child) => {
993
+ return node.x < child.x;
1080
994
  };
1081
-
1082
- const addEmoji = (board, element, emojiItem) => {
1083
- const emojis = element.data.emojis || [];
1084
- const newEmojis = [...emojis];
1085
- newEmojis.push(emojiItem);
1086
- const newElement = {
1087
- data: { ...element.data, emojis: newEmojis }
1088
- };
1089
- const path = PlaitBoard.findPath(board, element);
1090
- Transforms.setNode(board, newElement, path);
995
+ const isChildUp = (node, child) => {
996
+ return node.y > child.y;
1091
997
  };
1092
- const removeEmoji = (board, element, emojiItem) => {
1093
- const emojis = element.data.emojis.filter(value => value !== emojiItem);
1094
- const newElement = {
1095
- data: { topic: element.data.topic }
1096
- };
1097
- if (MindElement.hasImage(element)) {
1098
- newElement.data.image = element.data.image;
1099
- }
1100
- if (emojis.length > 0) {
1101
- newElement.data.emojis = emojis;
998
+ const copyNewNode = (node) => {
999
+ const newNode = { ...node };
1000
+ newNode.id = idCreator();
1001
+ newNode.children = [];
1002
+ for (const childNode of node.children) {
1003
+ newNode.children.push(copyNewNode(childNode));
1102
1004
  }
1103
- const path = PlaitBoard.findPath(board, element);
1104
- Transforms.setNode(board, newElement, path);
1005
+ return newNode;
1105
1006
  };
1106
- const replaceEmoji = (board, element, oldEmoji, newEmoji) => {
1107
- const newElement = {
1108
- data: { ...element.data }
1109
- };
1110
- const newEmojis = element.data.emojis.map(value => {
1111
- if (value === oldEmoji) {
1112
- return newEmoji;
1007
+ const extractNodesText = (node) => {
1008
+ let str = '';
1009
+ if (node) {
1010
+ str += Node$1.string(node.data.topic) + ' ';
1011
+ for (const childNode of node.children) {
1012
+ str += extractNodesText(childNode);
1113
1013
  }
1114
- return value;
1115
- });
1116
- newElement.data.emojis = newEmojis;
1117
- const path = PlaitBoard.findPath(board, element);
1118
- Transforms.setNode(board, newElement, path);
1014
+ }
1015
+ return str;
1119
1016
  };
1120
-
1121
- /**
1122
- * 1. return new node height if height changed
1123
- * 2. new height is effected by zoom
1124
- */
1125
- const getNewNodeHeight = (board, element, newNodeDynamicWidth) => {
1126
- const textManage = PlaitElement.getComponent(element).textManage;
1127
- const { height } = textManage.getSize();
1128
- textManage.updateWidth(newNodeDynamicWidth);
1129
- const { height: newHeight } = textManage.getSize();
1130
- if (!element.manualWidth) {
1131
- textManage.updateWidth(0);
1017
+ const insertMindElement = (board, inheritNode, path) => {
1018
+ const newNode = {};
1019
+ if (!inheritNode.isRoot) {
1020
+ INHERIT_ATTRIBUTE_KEYS.forEach(attr => {
1021
+ newNode[attr] = inheritNode[attr];
1022
+ });
1023
+ delete newNode.layout;
1132
1024
  }
1133
- if (height !== newHeight) {
1134
- return newHeight;
1025
+ const newElement = createMindElement('', getNodeDefaultFontSize(), TEXT_DEFAULT_HEIGHT, newNode);
1026
+ Transforms.insertNode(board, newElement, path);
1027
+ clearSelectedElement(board);
1028
+ addSelectedElement(board, newElement);
1029
+ setTimeout(() => {
1030
+ editTopic(newElement);
1031
+ });
1032
+ };
1033
+ const findLastChild = (child) => {
1034
+ let result = child;
1035
+ while (result.children.length !== 0) {
1036
+ result = result.children[result.children.length - 1];
1135
1037
  }
1136
- if (Math.abs(newHeight / board.viewport.zoom - element.height) > 2) {
1137
- return newHeight;
1038
+ return result;
1039
+ };
1040
+ const divideElementByParent = (elements) => {
1041
+ const abstractIncludedGroups = [];
1042
+ const parentElements = [];
1043
+ for (let i = 0; i < elements.length; i++) {
1044
+ const parent = MindElement.getParent(elements[i]);
1045
+ const parentIndex = parentElements.indexOf(parent);
1046
+ if (parentIndex === -1) {
1047
+ parentElements.push(parent);
1048
+ abstractIncludedGroups.push([elements[i]]);
1049
+ }
1050
+ else {
1051
+ abstractIncludedGroups[parentIndex].push(elements[i]);
1052
+ }
1138
1053
  }
1139
- return undefined;
1054
+ return { parentElements, abstractIncludedGroups };
1140
1055
  };
1141
1056
 
1142
- const removeImage = (board, element) => {
1143
- setImageFocus(board, element, false);
1144
- const newElement = {
1145
- data: { ...element.data }
1146
- };
1147
- delete newElement.data.image;
1148
- const path = PlaitBoard.findPath(board, element);
1149
- const newDynamicWidth = NodeSpace.getNodeNewDynamicWidth(board, element, 0);
1150
- const newHeight = getNewNodeHeight(board, element, newDynamicWidth);
1151
- if (newHeight) {
1152
- newElement.height = newHeight / board.viewport.zoom;
1057
+ const adjustRootToNode = (board, node) => {
1058
+ const newNode = { ...node };
1059
+ delete newNode.isRoot;
1060
+ delete newNode.rightNodeCount;
1061
+ delete newNode.type;
1062
+ if (newNode.layout === MindLayoutType.standard) {
1063
+ delete newNode.layout;
1153
1064
  }
1154
- Transforms.setNode(board, newElement, path);
1065
+ return newNode;
1155
1066
  };
1156
- const setImage = (board, element, imageItem) => {
1157
- const newElement = {
1158
- data: { ...element.data, image: imageItem }
1159
- };
1160
- const newDynamicWidth = NodeSpace.getNodeNewDynamicWidth(board, element, imageItem.width);
1161
- const newHeight = getNewNodeHeight(board, element, newDynamicWidth);
1162
- if (newHeight) {
1163
- newElement.height = newHeight / board.viewport.zoom;
1164
- }
1165
- const path = PlaitBoard.findPath(board, element);
1166
- Transforms.setNode(board, newElement, path);
1067
+ const adjustAbstractToNode = (node) => {
1068
+ const newNode = { ...node };
1069
+ delete newNode.start;
1070
+ delete newNode.end;
1071
+ return newNode;
1167
1072
  };
1168
-
1169
- const MindTransforms = {
1170
- setLayout,
1171
- setTopic,
1172
- setTopicSize,
1173
- setNodeManualWidth,
1174
- addEmoji,
1175
- removeEmoji,
1176
- replaceEmoji,
1177
- insertAbstract,
1178
- setAbstractsByRefs,
1179
- setAbstractByStandardLayout,
1180
- removeElements,
1181
- insertNodes,
1182
- insertAbstractNodes,
1183
- setRightNodeCountByRefs,
1184
- removeImage,
1185
- setImage
1073
+ const adjustNodeToRoot = (board, node) => {
1074
+ const newElement = { ...node };
1075
+ if (!Node$1.string(newElement.data.topic)) {
1076
+ newElement.data.topic = { children: [{ text: '思维导图' }] };
1077
+ }
1078
+ delete newElement?.strokeColor;
1079
+ delete newElement?.fill;
1080
+ delete newElement?.shape;
1081
+ delete newElement?.strokeWidth;
1082
+ delete newElement?.isCollapsed;
1083
+ const { width, height } = getTextSize(board, newElement.data.topic, TOPIC_DEFAULT_MAX_WORD_COUNT, {
1084
+ fontSize: ROOT_TOPIC_FONT_SIZE,
1085
+ fontFamily: BRANCH_FONT_FAMILY,
1086
+ width: node.manualWidth ? node.manualWidth : undefined
1087
+ });
1088
+ newElement.width = Math.max(width, getNodeDefaultFontSize(true));
1089
+ newElement.height = height;
1090
+ return {
1091
+ ...newElement,
1092
+ layout: newElement.layout ?? MindLayoutType.right,
1093
+ isRoot: true,
1094
+ type: 'mindmap'
1095
+ };
1186
1096
  };
1187
1097
 
1188
- const PICTURE_ACCEPTED_UPLOAD_SIZE = 20;
1189
- const acceptImageTypes = ['png', 'jpeg', 'gif', 'bmp'];
1190
- const DEFAULT_IMAGE_WIDTH = 240;
1191
-
1192
1098
  const BOARD_TO_SELECTED_IMAGE_ELEMENT = new WeakMap();
1193
1099
  const getSelectedImageElement = (board) => {
1194
1100
  return BOARD_TO_SELECTED_IMAGE_ELEMENT.get(board);
@@ -1207,146 +1113,28 @@ const setImageFocus = (board, element, isFocus) => {
1207
1113
  removeSelectedImageElement(board);
1208
1114
  }
1209
1115
  const elementComponent = PlaitElement.getComponent(element);
1210
- elementComponent.imageDrawer.componentRef.instance.isFocus = isFocus;
1211
- elementComponent.imageDrawer.componentRef.instance.cdr.markForCheck();
1212
- };
1213
- const selectImage = (board, element, acceptImageTypes = ['png', 'jpeg', 'gif', 'bmp']) => {
1214
- const inputFile = document.createElement('input');
1215
- inputFile.setAttribute('type', 'file');
1216
- const acceptImageTypesString = '.' + acceptImageTypes.join(',.');
1217
- inputFile.setAttribute('accept', acceptImageTypesString);
1218
- inputFile.onchange = (event) => {
1219
- buildImage(board, element, event.target.files[0]);
1220
- };
1221
- inputFile.click();
1222
- };
1223
- const buildImage = async (board, element, imageFile) => {
1224
- let width = 0, height = 0;
1225
- await getImageSize(imageFile).then((value) => {
1226
- width = value.width;
1227
- height = value.height;
1228
- });
1229
- let imageItem = null;
1230
- const url = URL.createObjectURL(imageFile);
1231
- const context = PlaitBoard.getComponent(board).viewContainerRef.injector.get(PlaitContextService);
1232
- context.setUploadingFile({ url, file: imageFile });
1233
- imageItem = {
1234
- url,
1235
- width,
1236
- height
1237
- };
1238
- MindTransforms.setImage(board, element, imageItem);
1239
- };
1240
- function getImageSize(file, defaultImageWidth = DEFAULT_IMAGE_WIDTH) {
1241
- return new Promise((resolve, reject) => {
1242
- const image = new Image();
1243
- image.src = URL.createObjectURL(file);
1244
- image.onload = function () {
1245
- const width = defaultImageWidth;
1246
- const height = (defaultImageWidth * image.naturalHeight) / image.naturalWidth;
1247
- resolve(image.naturalWidth > defaultImageWidth ? { width, height } : { width: image.naturalWidth, height: image.naturalHeight });
1248
- };
1249
- });
1250
- }
1251
-
1252
- const getAvailableProperty = (board, element, propertyKey) => {
1253
- return element[propertyKey];
1116
+ elementComponent.imageGenerator.componentRef.instance.isFocus = isFocus;
1117
+ elementComponent.imageGenerator.componentRef.instance.cdr.markForCheck();
1254
1118
  };
1255
1119
 
1256
1120
  /**
1257
- * Processing of branch color, width, style, etc. of the mind node
1121
+ * 1. return new node height if height changed
1122
+ * 2. new height is effected by zoom
1258
1123
  */
1259
- const getBranchColorByMindElement = (board, element) => {
1260
- if (AbstractNode.isAbstract(element) || isChildOfAbstract(board, element)) {
1261
- return getAbstractBranchColor(board, element);
1262
- }
1263
- const branchColor = getAvailableProperty(board, element, 'branchColor');
1264
- return branchColor || getDefaultBranchColor(board, element);
1265
- };
1266
- const getBranchShapeByMindElement = (board, element) => {
1267
- const branchShape = getAvailableProperty(board, element, 'branchShape');
1268
- return branchShape || BranchShape.bight;
1269
- };
1270
- const getBranchWidthByMindElement = (board, element) => {
1271
- const branchWidth = getAvailableProperty(board, element, 'branchWidth');
1272
- return branchWidth || BRANCH_WIDTH;
1273
- };
1274
- const getAbstractBranchWidth = (board, element) => {
1275
- if (!isNullOrUndefined(element.branchWidth)) {
1276
- return element.branchWidth;
1277
- }
1278
- return DefaultAbstractNodeStyle.branch.width;
1279
- };
1280
- const getAbstractBranchColor = (board, element) => {
1281
- if (element.branchColor) {
1282
- return element.branchColor;
1283
- }
1284
- return DefaultAbstractNodeStyle.branch.color;
1285
- };
1286
- const getNextBranchColor = (board, root) => {
1287
- const index = root.children.length;
1288
- return getDefaultBranchColorByIndex(board, index);
1289
- };
1290
- const getDefaultBranchColor = (board, element) => {
1291
- const path = PlaitBoard.findPath(board, element);
1292
- return getDefaultBranchColorByIndex(board, path[1]);
1293
- };
1294
- const getDefaultBranchColorByIndex = (board, index) => {
1295
- const themeColor = getMindThemeColor(board);
1296
- const length = themeColor.branchColors.length;
1297
- const remainder = index % length;
1298
- return themeColor.branchColors[remainder];
1299
- };
1300
- const getMindThemeColor = (board) => {
1301
- const themeColors = PlaitBoard.getThemeColors(board);
1302
- const themeColor = themeColors.find(val => val.mode === board.theme.themeColorMode);
1303
- if (themeColor && MindThemeColor.isMindThemeColor(themeColor)) {
1304
- return themeColor;
1305
- }
1306
- else {
1307
- return MindDefaultThemeColor;
1308
- }
1309
- };
1310
-
1311
- const getStrokeByMindElement = (board, element) => {
1312
- if (PlaitMind.isMind(element)) {
1313
- const defaultRootStroke = getMindThemeColor(board).rootFill;
1314
- return element.strokeColor || defaultRootStroke;
1315
- }
1316
- if (AbstractNode.isAbstract(element) || isChildOfAbstract(board, element)) {
1317
- return element.strokeColor || DefaultAbstractNodeStyle.shape.strokeColor;
1124
+ const getNewNodeHeight = (board, element, newNodeDynamicWidth) => {
1125
+ const textManage = MindElement.getTextManage(element);
1126
+ const { height } = textManage.getSize();
1127
+ textManage.updateRectangleWidth(newNodeDynamicWidth);
1128
+ const { height: newHeight } = textManage.getSize();
1129
+ if (height !== newHeight) {
1130
+ return newHeight;
1318
1131
  }
1319
- return getAvailableProperty(board, element, 'strokeColor') || getDefaultBranchColor(board, element);
1320
- };
1321
- const getStrokeWidthByElement = (board, element) => {
1322
- const strokeWidth = element.strokeWidth ||
1323
- (AbstractNode.isAbstract(element) ? DefaultAbstractNodeStyle.shape.strokeWidth : DefaultNodeStyle.shape.strokeWidth);
1324
- return strokeWidth;
1325
- };
1326
- const getFillByElement = (board, element) => {
1327
- if (element.fill) {
1328
- return element.fill;
1132
+ if (Math.abs(newHeight / board.viewport.zoom - element.height) > 2) {
1133
+ return newHeight;
1329
1134
  }
1330
- const defaultRootFill = getMindThemeColor(board).rootFill;
1331
- return element.isRoot ? defaultRootFill : DefaultNodeStyle.shape.fill;
1332
- };
1333
- const getShapeByElement = (board, element) => {
1334
- const shape = getAvailableProperty(board, element, 'shape');
1335
- return shape || MindElementShape.roundRectangle;
1135
+ return undefined;
1336
1136
  };
1337
1137
 
1338
- function isVirtualKey(e) {
1339
- const isMod = e.ctrlKey || e.metaKey;
1340
- const isAlt = isKeyHotkey('alt', e);
1341
- const isShift = isKeyHotkey('shift', e);
1342
- const isCapsLock = e.key.includes('CapsLock');
1343
- const isTab = e.key.includes('Tab');
1344
- const isEsc = e.key.includes('Escape');
1345
- const isF = e.key.startsWith('F');
1346
- const isArrow = e.key.includes('Arrow') ? true : false;
1347
- return isCapsLock || isMod || isAlt || isArrow || isShift || isTab || isEsc || isF;
1348
- }
1349
-
1350
1138
  const IS_DRAGGING = new WeakMap();
1351
1139
  const addActiveOnDragOrigin = (activeElement) => {
1352
1140
  const activeComponent = PlaitElement.getComponent(activeElement);
@@ -1581,6 +1369,24 @@ const getPathByDropTarget = (board, dropTarget) => {
1581
1369
  return targetPath;
1582
1370
  };
1583
1371
 
1372
+ function drawRoundRectangleByNode(board, node) {
1373
+ const rectangle = getRectangleByNode(node);
1374
+ return drawRoundRectangleByElement(board, rectangle, node.origin);
1375
+ }
1376
+ function drawRoundRectangleByElement(board, nodeRectangle, element) {
1377
+ const fill = getFillByElement(board, element);
1378
+ const stroke = getStrokeByMindElement(board, element);
1379
+ const strokeWidth = getStrokeWidthByElement(board, element);
1380
+ const newNodeRectangle = RectangleClient.inflate(nodeRectangle, -strokeWidth);
1381
+ const nodeG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), newNodeRectangle.x, newNodeRectangle.y, newNodeRectangle.x + newNodeRectangle.width, newNodeRectangle.y + newNodeRectangle.height, {
1382
+ stroke,
1383
+ strokeWidth,
1384
+ fill,
1385
+ fillStyle: 'solid'
1386
+ }, false, DefaultNodeStyle.shape.rectangleRadius);
1387
+ return nodeG;
1388
+ }
1389
+
1584
1390
  const ABSTRACT_HANDLE_COLOR = '#6698FF80'; //primary color 50% opacity
1585
1391
  const ABSTRACT_INCLUDED_OUTLINE_OFFSET = 3.5;
1586
1392
  const ABSTRACT_HANDLE_LENGTH = 10;
@@ -1833,7 +1639,7 @@ const drawFakeDragNode = (board, element, offsetX, offsetY) => {
1833
1639
  };
1834
1640
  const textRectangle = getTopicRectangleByNode(board, activeComponent.node);
1835
1641
  const fakeNodeG = drawRoundRectangleByNode(board, fakeDraggingNode);
1836
- const richtextG = activeComponent.textManage.g.cloneNode(true);
1642
+ const richtextG = MindElement.getTextManage(element).g.cloneNode(true);
1837
1643
  updateForeignObject(richtextG, textRectangle.width, textRectangle.height, textRectangle.x + offsetX, textRectangle.y + offsetY);
1838
1644
  dragFakeNodeG?.append(fakeNodeG);
1839
1645
  dragFakeNodeG?.append(richtextG);
@@ -1845,7 +1651,7 @@ const drawFakeDragNode = (board, element, offsetX, offsetY) => {
1845
1651
  dragFakeNodeG?.append(fakeEmojisG);
1846
1652
  }
1847
1653
  if (MindElement.hasImage(element)) {
1848
- const fakeImageG = activeComponent.imageDrawer.g.cloneNode(true);
1654
+ const fakeImageG = activeComponent.imageGenerator.g.cloneNode(true);
1849
1655
  const foreignRectangle = getImageForeignRectangle(board, element);
1850
1656
  updateForeignObject(fakeImageG, foreignRectangle.width, foreignRectangle.height, foreignRectangle.x + offsetX, foreignRectangle.y + offsetY);
1851
1657
  dragFakeNodeG?.append(fakeImageG);
@@ -2151,13 +1957,13 @@ function handleTouchedAbstract(board, touchedAbstract, endPoint) {
2151
1957
  }
2152
1958
  if (touchedAbstract) {
2153
1959
  const component = PlaitElement.getComponent(touchedAbstract);
2154
- component.activeDrawer.updateAbstractOutline(touchedAbstract);
1960
+ component.activeGenerator.updateAbstractOutline(touchedAbstract);
2155
1961
  touchedAbstract = undefined;
2156
1962
  }
2157
1963
  if (abstract) {
2158
1964
  touchedAbstract = abstract;
2159
1965
  const component = PlaitElement.getComponent(touchedAbstract);
2160
- component.activeDrawer.updateAbstractOutline(touchedAbstract, touchedHandle);
1966
+ component.activeGenerator.updateAbstractOutline(touchedAbstract, touchedHandle);
2161
1967
  }
2162
1968
  return touchedAbstract;
2163
1969
  }
@@ -2195,79 +2001,12 @@ const deleteElementsHandleRightNodeCount = (board, deletableElements, effectedRi
2195
2001
  if (index === -1) {
2196
2002
  effectedRightNodeCount.push({ path, rightNodeCount: mind.rightNodeCount - 1 });
2197
2003
  }
2198
- else {
2199
- effectedRightNodeCount[index].rightNodeCount -= 1;
2200
- }
2201
- }
2202
- });
2203
- return effectedRightNodeCount;
2204
- };
2205
-
2206
- const getLayoutOptions = (board) => {
2207
- function getMainAxle(element, parent) {
2208
- const strokeWidth = element.strokeWidth || STROKE_WIDTH;
2209
- if (element.isRoot) {
2210
- return BASE * 12;
2211
- }
2212
- if (parent && parent.isRoot()) {
2213
- return BASE * 3 + strokeWidth / 2;
2214
- }
2215
- return BASE * 3 + strokeWidth / 2;
2216
- }
2217
- function getSecondAxle(element, parent) {
2218
- const strokeWidth = element.strokeWidth || STROKE_WIDTH;
2219
- if (element.isRoot) {
2220
- return BASE * 10 + strokeWidth / 2;
2221
- }
2222
- return BASE * 6 + strokeWidth / 2;
2223
- }
2224
- return {
2225
- getHeight(element) {
2226
- return NodeSpace.getNodeHeight(board, element);
2227
- },
2228
- getWidth(element) {
2229
- return NodeSpace.getNodeWidth(board, element);
2230
- },
2231
- getHorizontalGap(element, parent) {
2232
- const _layout = (parent && parent.layout) || getRootLayout(element);
2233
- const isHorizontal = isHorizontalLayout(_layout);
2234
- const strokeWidth = element.strokeWidth || STROKE_WIDTH;
2235
- if (isIndentedLayout(_layout)) {
2236
- return BASE * 4 + strokeWidth;
2237
- }
2238
- if (!isHorizontal) {
2239
- return getMainAxle(element, parent);
2240
- }
2241
- else {
2242
- return getSecondAxle(element, parent);
2243
- }
2244
- },
2245
- getVerticalGap(element, parent) {
2246
- const _layout = (parent && parent.layout) || getRootLayout(element);
2247
- if (isIndentedLayout(_layout)) {
2248
- return BASE;
2249
- }
2250
- const isHorizontal = isHorizontalLayout(_layout);
2251
- if (isHorizontal) {
2252
- return getMainAxle(element, parent);
2253
- }
2254
- else {
2255
- return getSecondAxle(element, parent);
2256
- }
2257
- },
2258
- getVerticalConnectingPosition(element, parent) {
2259
- if (element.shape === MindElementShape.underline && parent && isHorizontalLogicLayout(parent.layout)) {
2260
- return ConnectingPosition.bottom;
2004
+ else {
2005
+ effectedRightNodeCount[index].rightNodeCount -= 1;
2261
2006
  }
2262
- return undefined;
2263
- },
2264
- getExtendHeight(node) {
2265
- return BASE * 6;
2266
- },
2267
- getIndentedCrossLevelGap() {
2268
- return BASE * 2;
2269
2007
  }
2270
- };
2008
+ });
2009
+ return effectedRightNodeCount;
2271
2010
  };
2272
2011
 
2273
2012
  /**
@@ -2463,7 +2202,14 @@ const MindElement = {
2463
2202
  getTextEditor(element) {
2464
2203
  const component = PlaitElement.getComponent(element);
2465
2204
  if (component) {
2466
- return component.textManage.componentRef.instance.editor;
2205
+ return MindElement.getTextManage(element).componentRef.instance.editor;
2206
+ }
2207
+ throw new Error('can not get correctly component in get text editor');
2208
+ },
2209
+ getTextManage(element) {
2210
+ const component = PlaitElement.getComponent(element);
2211
+ if (component) {
2212
+ return component.textManage;
2467
2213
  }
2468
2214
  throw new Error('can not get correctly component in get text editor');
2469
2215
  }
@@ -2479,54 +2225,6 @@ var BranchShape;
2479
2225
  BranchShape["polyline"] = "polyline";
2480
2226
  })(BranchShape || (BranchShape = {}));
2481
2227
 
2482
- function getRectangleByNode(node) {
2483
- const x = node.x + node.hGap;
2484
- let y = node.y + node.vGap;
2485
- const width = node.width - node.hGap * 2;
2486
- const height = node.height - node.vGap * 2;
2487
- return {
2488
- x,
2489
- y,
2490
- width,
2491
- height
2492
- };
2493
- }
2494
- function getRectangleByElement(board, originPoint, element) {
2495
- const nodeRectangle = {
2496
- x: originPoint[0],
2497
- y: originPoint[1],
2498
- width: NodeSpace.getNodeWidth(board, element),
2499
- height: NodeSpace.getNodeHeight(board, element)
2500
- };
2501
- return nodeRectangle;
2502
- }
2503
- function isHitMindElement(board, point, element) {
2504
- const node = MindElement.getNode(element);
2505
- if (node && distanceBetweenPointAndRectangle(point[0], point[1], getRectangleByNode(node)) === 0) {
2506
- return true;
2507
- }
2508
- else {
2509
- return false;
2510
- }
2511
- }
2512
-
2513
- function drawRoundRectangleByNode(board, node) {
2514
- const rectangle = getRectangleByNode(node);
2515
- return drawRoundRectangleByElement(board, rectangle, node.origin);
2516
- }
2517
- function drawRoundRectangleByElement(board, nodeRectangle, element) {
2518
- const fill = getFillByElement(board, element);
2519
- const stroke = getStrokeByMindElement(board, element);
2520
- const strokeWidth = getStrokeWidthByElement(board, element);
2521
- const nodeG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), nodeRectangle.x, nodeRectangle.y, nodeRectangle.x + nodeRectangle.width, nodeRectangle.y + nodeRectangle.height, {
2522
- stroke,
2523
- strokeWidth,
2524
- fill,
2525
- fillStyle: 'solid'
2526
- }, false, DefaultNodeStyle.shape.rectangleRadius);
2527
- return nodeG;
2528
- }
2529
-
2530
2228
  function drawAbstractLink(board, node, isHorizontal) {
2531
2229
  const linkPadding = 15;
2532
2230
  const branchWidth = getAbstractBranchWidth(board, node.origin);
@@ -2632,16 +2330,250 @@ class NodeEmojisDrawer {
2632
2330
  });
2633
2331
  return this.g;
2634
2332
  }
2635
- return undefined;
2333
+ return undefined;
2334
+ }
2335
+ destroy() {
2336
+ if (this.g) {
2337
+ this.g.remove();
2338
+ }
2339
+ this.emojiDrawers.forEach(drawer => drawer.destroy());
2340
+ this.emojiDrawers = [];
2341
+ }
2342
+ }
2343
+
2344
+ const setAbstractsByRefs = (board, abstractRefs) => {
2345
+ abstractRefs.forEach((newProperty, element) => {
2346
+ const start = element.start + newProperty.start;
2347
+ const end = element.end + newProperty.end;
2348
+ const path = PlaitBoard.findPath(board, element);
2349
+ if (start > end) {
2350
+ Transforms.removeNode(board, path);
2351
+ }
2352
+ else {
2353
+ Transforms.setNode(board, { start, end }, path);
2354
+ }
2355
+ });
2356
+ };
2357
+ const setAbstractByStandardLayout = (board, element) => {
2358
+ const rightNodeCount = element.rightNodeCount;
2359
+ const abstract = element.children.find(child => {
2360
+ return AbstractNode.isAbstract(child) && child.end >= rightNodeCount && child.start < rightNodeCount;
2361
+ });
2362
+ if (abstract) {
2363
+ const path = PlaitBoard.findPath(board, abstract);
2364
+ Transforms.setNode(board, { end: rightNodeCount - 1 }, path);
2365
+ }
2366
+ };
2367
+ const insertAbstract = (board, elements) => {
2368
+ let elementGroup = getFirstLevelElement(elements);
2369
+ const { parentElements, abstractIncludedGroups } = divideElementByParent(elementGroup);
2370
+ abstractIncludedGroups.forEach((group, index) => {
2371
+ const groupParent = parentElements[index];
2372
+ setAbstractByElements(board, groupParent, group);
2373
+ });
2374
+ };
2375
+ const setAbstractByElements = (board, groupParent, group) => {
2376
+ const indexArray = group.map(child => groupParent.children.indexOf(child)).sort((a, b) => a - b);
2377
+ const rightNodeCount = groupParent?.rightNodeCount;
2378
+ const start = indexArray[0], end = indexArray[indexArray.length - 1];
2379
+ if (isStandardLayout(MindQueries.getLayoutByElement(groupParent)) &&
2380
+ rightNodeCount &&
2381
+ start < rightNodeCount &&
2382
+ end >= rightNodeCount) {
2383
+ const childrenLength = groupParent.children.length;
2384
+ const path = [...PlaitBoard.findPath(board, groupParent), childrenLength];
2385
+ const leftChildren = indexArray.filter(index => index >= rightNodeCount);
2386
+ const rightChildren = indexArray.filter(index => index < rightNodeCount);
2387
+ insertAbstractNode(board, path, rightChildren[0], rightChildren[rightChildren.length - 1]);
2388
+ insertAbstractNode(board, Path.next(path), leftChildren[0], leftChildren[leftChildren.length - 1]);
2389
+ }
2390
+ else {
2391
+ const path = [...PlaitBoard.findPath(board, groupParent), groupParent.children.length];
2392
+ insertAbstractNode(board, path, start, end);
2393
+ }
2394
+ };
2395
+ const insertAbstractNode = (board, path, start, end) => {
2396
+ const mindElement = createMindElement('概要', 28, 20, {
2397
+ strokeWidth: DefaultAbstractNodeStyle.branch.width,
2398
+ branchWidth: DefaultAbstractNodeStyle.branch.width
2399
+ });
2400
+ mindElement.start = start;
2401
+ mindElement.end = end;
2402
+ Transforms.insertNode(board, mindElement, path);
2403
+ clearSelectedElement(board);
2404
+ addSelectedElement(board, mindElement);
2405
+ };
2406
+
2407
+ const setLayout = (board, layout, path) => {
2408
+ correctLogicLayoutNode(board, layout, path);
2409
+ const element = PlaitNode.get(board, path);
2410
+ if (PlaitMind.isMind(element) && isStandardLayout(layout)) {
2411
+ MindTransforms.setAbstractByStandardLayout(board, element);
2412
+ }
2413
+ Transforms.setNode(board, { layout }, path);
2414
+ };
2415
+ const correctLogicLayoutNode = (board, layout, path) => {
2416
+ const node = PlaitNode.get(board, path);
2417
+ if (node && layout) {
2418
+ node.children?.forEach((value, index) => {
2419
+ if (value.layout) {
2420
+ if ((isHorizontalLogicLayout(layout) && isVerticalLogicLayout(value.layout)) ||
2421
+ (isVerticalLogicLayout(layout) && isHorizontalLogicLayout(value.layout))) {
2422
+ Transforms.setNode(board, { layout: null }, [...path, index]);
2423
+ }
2424
+ if (value.children?.length) {
2425
+ correctLogicLayoutNode(board, layout, [...path, index]);
2426
+ }
2427
+ }
2428
+ });
2429
+ }
2430
+ };
2431
+
2432
+ const normalizeWidthAndHeight = (board, element, width, height) => {
2433
+ const minWidth = NodeSpace.getNodeTopicMinWidth(board, element, element.isRoot);
2434
+ const newWidth = width < minWidth * board.viewport.zoom ? minWidth : width / board.viewport.zoom;
2435
+ const newHeight = height / board.viewport.zoom;
2436
+ return { width: Math.ceil(newWidth), height: newHeight };
2437
+ };
2438
+ const setTopic = (board, element, topic, width, height) => {
2439
+ const newElement = {
2440
+ data: { ...element.data, topic },
2441
+ ...normalizeWidthAndHeight(board, element, width, height)
2442
+ };
2443
+ const path = PlaitBoard.findPath(board, element);
2444
+ Transforms.setNode(board, newElement, path);
2445
+ };
2446
+ const setNodeManualWidth = (board, element, width, height) => {
2447
+ const path = PlaitBoard.findPath(board, element);
2448
+ const { width: normalizedWidth, height: normalizedHeight } = normalizeWidthAndHeight(board, element, width, height);
2449
+ const newElement = { manualWidth: normalizedWidth, height: normalizedHeight };
2450
+ Transforms.setNode(board, newElement, path);
2451
+ };
2452
+ const setTopicSize = (board, element, width, height) => {
2453
+ const newElement = {
2454
+ ...normalizeWidthAndHeight(board, element, width, height)
2455
+ };
2456
+ let isEqualWidth = Math.ceil(element.width) === Math.ceil(newElement.width);
2457
+ let isEqualHeight = Math.ceil(element.height) === Math.ceil(newElement.height);
2458
+ if (element.manualWidth) {
2459
+ isEqualWidth = true;
2460
+ }
2461
+ if (!isEqualWidth || !isEqualHeight) {
2462
+ const path = PlaitBoard.findPath(board, element);
2463
+ Transforms.setNode(board, newElement, path);
2464
+ }
2465
+ };
2466
+ const insertNodes = (board, elements, path) => {
2467
+ const pathRef = board.pathRef(path);
2468
+ elements.forEach(element => {
2469
+ if (pathRef.current) {
2470
+ Transforms.insertNode(board, element, pathRef.current);
2471
+ }
2472
+ });
2473
+ pathRef.unref();
2474
+ };
2475
+ const insertAbstractNodes = (board, validAbstractRefs, elements, path) => {
2476
+ const parent = PlaitNode.get(board, Path$1.parent(path));
2477
+ const abstractPath = [...Path$1.parent(path), parent.children?.length];
2478
+ const abstracts = validAbstractRefs.map(refs => {
2479
+ const { start, end } = getRelativeStartEndByAbstractRef(refs, elements);
2480
+ return {
2481
+ ...refs.abstract,
2482
+ start: start + path[path.length - 1],
2483
+ end: end + path[path.length - 1]
2484
+ };
2485
+ });
2486
+ insertNodes(board, abstracts, abstractPath);
2487
+ };
2488
+ const setRightNodeCountByRefs = (board, refs) => {
2489
+ refs.forEach(ref => {
2490
+ Transforms.setNode(board, { rightNodeCount: ref.rightNodeCount }, ref.path);
2491
+ });
2492
+ };
2493
+
2494
+ const addEmoji = (board, element, emojiItem) => {
2495
+ const emojis = element.data.emojis || [];
2496
+ const newEmojis = [...emojis];
2497
+ newEmojis.push(emojiItem);
2498
+ const newElement = {
2499
+ data: { ...element.data, emojis: newEmojis }
2500
+ };
2501
+ const path = PlaitBoard.findPath(board, element);
2502
+ Transforms.setNode(board, newElement, path);
2503
+ };
2504
+ const removeEmoji = (board, element, emojiItem) => {
2505
+ const emojis = element.data.emojis.filter(value => value !== emojiItem);
2506
+ const newElement = {
2507
+ data: { topic: element.data.topic }
2508
+ };
2509
+ if (MindElement.hasImage(element)) {
2510
+ newElement.data.image = element.data.image;
2511
+ }
2512
+ if (emojis.length > 0) {
2513
+ newElement.data.emojis = emojis;
2514
+ }
2515
+ const path = PlaitBoard.findPath(board, element);
2516
+ Transforms.setNode(board, newElement, path);
2517
+ };
2518
+ const replaceEmoji = (board, element, oldEmoji, newEmoji) => {
2519
+ const newElement = {
2520
+ data: { ...element.data }
2521
+ };
2522
+ const newEmojis = element.data.emojis.map(value => {
2523
+ if (value === oldEmoji) {
2524
+ return newEmoji;
2525
+ }
2526
+ return value;
2527
+ });
2528
+ newElement.data.emojis = newEmojis;
2529
+ const path = PlaitBoard.findPath(board, element);
2530
+ Transforms.setNode(board, newElement, path);
2531
+ };
2532
+
2533
+ const removeImage = (board, element) => {
2534
+ setImageFocus(board, element, false);
2535
+ const newElement = {
2536
+ data: { ...element.data }
2537
+ };
2538
+ delete newElement.data.image;
2539
+ const path = PlaitBoard.findPath(board, element);
2540
+ const newDynamicWidth = NodeSpace.getNodeNewDynamicWidth(board, element, 0);
2541
+ const newHeight = getNewNodeHeight(board, element, newDynamicWidth);
2542
+ if (newHeight) {
2543
+ newElement.height = newHeight / board.viewport.zoom;
2636
2544
  }
2637
- destroy() {
2638
- if (this.g) {
2639
- this.g.remove();
2640
- }
2641
- this.emojiDrawers.forEach(drawer => drawer.destroy());
2642
- this.emojiDrawers = [];
2545
+ Transforms.setNode(board, newElement, path);
2546
+ };
2547
+ const setImage = (board, element, imageItem) => {
2548
+ const newElement = {
2549
+ data: { ...element.data, image: imageItem }
2550
+ };
2551
+ const newDynamicWidth = NodeSpace.getNodeNewDynamicWidth(board, element, imageItem.width);
2552
+ const newHeight = getNewNodeHeight(board, element, newDynamicWidth);
2553
+ if (newHeight) {
2554
+ newElement.height = newHeight / board.viewport.zoom;
2643
2555
  }
2644
- }
2556
+ const path = PlaitBoard.findPath(board, element);
2557
+ Transforms.setNode(board, newElement, path);
2558
+ };
2559
+
2560
+ const MindTransforms = {
2561
+ setLayout,
2562
+ setTopic,
2563
+ setTopicSize,
2564
+ setNodeManualWidth,
2565
+ addEmoji,
2566
+ removeEmoji,
2567
+ replaceEmoji,
2568
+ insertAbstract,
2569
+ setAbstractsByRefs,
2570
+ setAbstractByStandardLayout,
2571
+ insertNodes,
2572
+ insertAbstractNodes,
2573
+ setRightNodeCountByRefs,
2574
+ removeImage,
2575
+ setImage
2576
+ };
2645
2577
 
2646
2578
  class BaseDrawer {
2647
2579
  constructor(board) {
@@ -2794,8 +2726,8 @@ function drawAbstractIncludedOutline(board, roughSVG, element, activeHandlePosit
2794
2726
  const startHandle = roughSVG.line(startPoint1[0], startPoint1[1], startPoint2[0], startPoint2[1], getHandleOption(activeHandlePosition === AbstractHandlePosition.start));
2795
2727
  const endHandle = roughSVG.line(endPoint1[0], endPoint1[1], endPoint2[0], endPoint2[1], getHandleOption(activeHandlePosition === AbstractHandlePosition.end));
2796
2728
  handleBoardClass(board, activeHandlePosition, isHorizontal);
2797
- startHandle.setAttribute('stroke-linecap', 'round');
2798
- endHandle.setAttribute('stroke-linecap', 'round');
2729
+ setStrokeLinecap(startHandle, 'round');
2730
+ setStrokeLinecap(endHandle, 'round');
2799
2731
  abstractIncludedG.append(startHandle);
2800
2732
  abstractIncludedG.append(endHandle);
2801
2733
  abstractIncludedG.append(rectangle);
@@ -2871,7 +2803,7 @@ function drawAbstractRoundRectangle(rs, x1, y1, x2, y2, isHorizontal, options) {
2871
2803
  }
2872
2804
  }
2873
2805
 
2874
- class NodeActiveDrawer extends BaseDrawer {
2806
+ class NodeActiveGenerator extends Generator {
2875
2807
  canDraw(element, data) {
2876
2808
  if (data.selected) {
2877
2809
  return true;
@@ -2882,19 +2814,17 @@ class NodeActiveDrawer extends BaseDrawer {
2882
2814
  }
2883
2815
  baseDraw(element, data) {
2884
2816
  const activeG = createG();
2885
- this.g = activeG;
2886
2817
  if (AbstractNode.isAbstract(element)) {
2887
2818
  this.abstractOutlineG = drawAbstractIncludedOutline(this.board, PlaitBoard.getRoughSVG(this.board), element);
2888
2819
  activeG.append(this.abstractOutlineG);
2889
2820
  }
2890
2821
  const node = MindElement.getNode(element);
2891
2822
  const rectangle = getRectangleByNode(node);
2892
- const activeStrokeWidth = 2;
2893
- // add 0.1 to avoid white gap
2894
- const offset = (getStrokeWidthByElement(this.board, element) + activeStrokeWidth) / 2 - 0.1;
2895
- const activeRectangle = RectangleClient.getOutlineRectangle(rectangle, -offset);
2896
- const strokeG = drawRoundRectangle(PlaitBoard.getRoughSVG(this.board), activeRectangle.x, activeRectangle.y, activeRectangle.x + activeRectangle.width, activeRectangle.y + activeRectangle.height, { stroke: PRIMARY_COLOR, strokeWidth: activeStrokeWidth, fill: '' }, true, DefaultNodeStyle.shape.rectangleRadius + offset);
2897
- this.g.appendChild(strokeG);
2823
+ const strokeWidth = getStrokeWidthByElement(this.board, element);
2824
+ const activeStrokeWidth = ACTIVE_STROKE_WIDTH;
2825
+ const activeRectangle = RectangleClient.inflate(rectangle, activeStrokeWidth);
2826
+ const strokeG = drawRoundRectangle(PlaitBoard.getRoughSVG(this.board), activeRectangle.x, activeRectangle.y, activeRectangle.x + activeRectangle.width, activeRectangle.y + activeRectangle.height, { stroke: PRIMARY_COLOR, strokeWidth: activeStrokeWidth, fill: '' }, true, DefaultNodeStyle.shape.rectangleRadius + (activeStrokeWidth + strokeWidth) / 2);
2827
+ activeG.appendChild(strokeG);
2898
2828
  return activeG;
2899
2829
  }
2900
2830
  updateAbstractOutline(element, activeHandlePosition, resizingLocation) {
@@ -3000,65 +2930,24 @@ class CollapseDrawer extends BaseDrawer {
3000
2930
  }
3001
2931
  }
3002
2932
 
3003
- class NodeImageDrawer {
3004
- constructor(board, viewContainerRef) {
3005
- this.board = board;
3006
- this.viewContainerRef = viewContainerRef;
3007
- this.componentRef = null;
3008
- }
3009
- drawImage(nodeG, element) {
3010
- if (!MindElement.hasImage(element)) {
3011
- this.destroy();
3012
- return;
3013
- }
3014
- this.g = createG();
3015
- const foreignRectangle = getImageForeignRectangle(this.board, element);
3016
- this.foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
3017
- this.g.append(this.foreignObject);
3018
- const componentType = this.board.getPluginOptions(WithMindPluginKey).imageComponentType;
3019
- if (!componentType) {
3020
- throw new Error('Not implement drawEmoji method error.');
3021
- }
3022
- this.componentRef = this.viewContainerRef.createComponent(componentType);
3023
- this.componentRef.instance.board = this.board;
3024
- this.componentRef.instance.element = element;
3025
- this.componentRef.instance.imageItem = element.data.image;
3026
- this.componentRef.instance.cdr.markForCheck();
3027
- this.foreignObject.append(this.componentRef.instance.nativeElement);
3028
- nodeG.appendChild(this.g);
3029
- }
3030
- updateImage(nodeG, previous, current) {
3031
- if (!MindElement.hasImage(previous) || !MindElement.hasImage(current)) {
3032
- this.drawImage(nodeG, current);
3033
- return;
3034
- }
3035
- if (previous !== current && this.componentRef) {
3036
- this.componentRef.instance.element = current;
3037
- this.componentRef.instance.imageItem = current.data.image;
3038
- }
3039
- const currentForeignObject = getImageForeignRectangle(this.board, current);
3040
- updateForeignObject(this.g, currentForeignObject.width, currentForeignObject.height, currentForeignObject.x, currentForeignObject.y);
3041
- // solve image lose on move node
3042
- if (this.foreignObject.children.length === 0) {
3043
- this.foreignObject.append(this.componentRef.instance.nativeElement);
2933
+ class NodeShapeGenerator extends Generator {
2934
+ canDraw(element, data) {
2935
+ const shape = getShapeByElement(this.board, element);
2936
+ if (shape === MindElementShape.roundRectangle) {
2937
+ return true;
3044
2938
  }
3045
- this.componentRef?.instance.cdr.markForCheck();
2939
+ return false;
3046
2940
  }
3047
- destroy() {
3048
- if (this.g) {
3049
- this.g.remove();
3050
- }
3051
- if (this.componentRef) {
3052
- this.componentRef.destroy();
3053
- this.componentRef = null;
3054
- }
2941
+ baseDraw(element, data) {
2942
+ const rectangle = getRectangleByNode(data.node);
2943
+ return drawRoundRectangleByElement(this.board, rectangle, data.node.origin);
3055
2944
  }
3056
2945
  }
3057
2946
 
3058
- // 1. When the text at the end has an italic attribute, the text is partially covered
3059
- // 2. There will be some differences in the width measured by different browsers
3060
- const WIDTH_BUFFER = 4;
3061
- class MindNodeComponent extends PlaitPluginElementComponent {
2947
+ class MindNodeComponent extends CommonPluginElement {
2948
+ get textManage() {
2949
+ return this.getTextManages()[0];
2950
+ }
3062
2951
  constructor(viewContainerRef, cdr) {
3063
2952
  super(cdr);
3064
2953
  this.viewContainerRef = viewContainerRef;
@@ -3070,13 +2959,21 @@ class MindNodeComponent extends PlaitPluginElementComponent {
3070
2959
  };
3071
2960
  }
3072
2961
  initializeDrawer() {
2962
+ this.nodeShapeGenerator = new NodeShapeGenerator(this.board);
3073
2963
  this.nodeEmojisDrawer = new NodeEmojisDrawer(this.board, this.viewContainerRef);
3074
2964
  this.nodeInsertDrawer = new NodeInsertDrawer(this.board);
3075
- this.activeDrawer = new NodeActiveDrawer(this.board);
2965
+ this.activeGenerator = new NodeActiveGenerator(this.board);
3076
2966
  this.collapseDrawer = new CollapseDrawer(this.board);
3077
- this.imageDrawer = new NodeImageDrawer(this.board, this.viewContainerRef);
3078
- const plugins = this.board.getPluginOptions(WithMindPluginKey).textPlugins;
3079
- this.textManage = new TextManage(this.board, this.viewContainerRef, {
2967
+ this.imageGenerator = new ImageGenerator(this.board, {
2968
+ getRectangle: (element) => {
2969
+ return getImageForeignRectangle(this.board, element);
2970
+ },
2971
+ getImageItem: (element) => {
2972
+ return element.data.image;
2973
+ }
2974
+ });
2975
+ const plugins = this.board.getPluginOptions(WithTextPluginKey).textPlugins;
2976
+ const textManage = new TextManage(this.board, this.viewContainerRef, {
3080
2977
  getRectangle: () => {
3081
2978
  const rect = getTopicRectangleByNode(this.board, this.node);
3082
2979
  return rect;
@@ -3091,8 +2988,17 @@ class MindNodeComponent extends PlaitPluginElementComponent {
3091
2988
  MindTransforms.setTopicSize(this.board, this.element, width, height);
3092
2989
  }
3093
2990
  },
3094
- textPlugins: plugins
2991
+ textPlugins: plugins,
2992
+ getMaxWidth: () => {
2993
+ if (this.element.manualWidth) {
2994
+ return NodeSpace.getNodeDynamicWidth(this.board, this.element);
2995
+ }
2996
+ else {
2997
+ return Math.max(NodeSpace.getNodeDynamicWidth(this.board, this.element), NodeTopicThreshold.defaultTextMaxWidth);
2998
+ }
2999
+ }
3095
3000
  });
3001
+ this.initializeTextManages([textManage]);
3096
3002
  }
3097
3003
  ngOnInit() {
3098
3004
  super.ngOnInit();
@@ -3101,13 +3007,13 @@ class MindNodeComponent extends PlaitPluginElementComponent {
3101
3007
  this.index = NODE_TO_INDEX.get(this.element) || 0;
3102
3008
  this.roughSVG = PlaitBoard.getRoughSVG(this.board);
3103
3009
  this.parentG = PlaitElement.getComponent(MindElement.getRoot(this.board, this.element)).rootG;
3104
- this.drawShape();
3010
+ this.nodeShapeGenerator.draw(this.element, this.g, { node: this.node });
3105
3011
  this.drawLink();
3106
3012
  this.drawTopic();
3107
- this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: this.textManage.isEditing });
3013
+ this.activeGenerator.draw(this.element, this.g, { selected: this.selected, isEditing: this.textManage.isEditing });
3108
3014
  this.drawEmojis();
3109
3015
  this.drawExtend();
3110
- this.imageDrawer.drawImage(this.g, this.element);
3016
+ this.imageGenerator.draw(this.element, this.g, this.viewContainerRef);
3111
3017
  if (PlaitMind.isMind(this.context.parent)) {
3112
3018
  this.g.classList.add('branch');
3113
3019
  }
@@ -3118,19 +3024,27 @@ class MindNodeComponent extends PlaitPluginElementComponent {
3118
3024
  this.node = newNode;
3119
3025
  const isChangeTheme = this.board.operations.find(op => op.type === 'set_theme');
3120
3026
  if (!isEqualNode || value.element !== previous.element || isChangeTheme) {
3121
- this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: this.textManage.isEditing });
3122
- this.drawShape();
3027
+ this.activeGenerator.draw(this.element, this.g, { selected: this.selected, isEditing: this.textManage.isEditing });
3028
+ this.nodeShapeGenerator.draw(this.element, this.g, { node: this.node });
3123
3029
  this.drawLink();
3124
3030
  this.drawEmojis();
3125
3031
  this.drawExtend();
3126
- this.imageDrawer.updateImage(this.g, previous.element, value.element);
3032
+ if (!MindElement.hasImage(previous.element) && MindElement.hasImage(this.element)) {
3033
+ this.imageGenerator.draw(this.element, this.g, this.viewContainerRef);
3034
+ }
3035
+ if (MindElement.hasImage(previous.element) && MindElement.hasImage(this.element)) {
3036
+ this.imageGenerator.updateImage(this.g, previous.element, value.element);
3037
+ }
3038
+ if (MindElement.hasImage(previous.element) && !MindElement.hasImage(this.element)) {
3039
+ this.imageGenerator.destroy();
3040
+ }
3127
3041
  this.updateTopic();
3128
3042
  }
3129
3043
  else {
3130
3044
  const hasSameSelected = value.selected === previous.selected;
3131
3045
  const hasSameParent = value.parent === previous.parent;
3132
3046
  if (!hasSameSelected) {
3133
- this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: this.textManage.isEditing });
3047
+ this.activeGenerator.draw(this.element, this.g, { selected: this.selected, isEditing: this.textManage.isEditing });
3134
3048
  }
3135
3049
  if (!hasSameParent) {
3136
3050
  this.drawLink();
@@ -3143,24 +3057,6 @@ class MindNodeComponent extends PlaitPluginElementComponent {
3143
3057
  this.g.append(g);
3144
3058
  }
3145
3059
  }
3146
- drawShape() {
3147
- this.destroyShape();
3148
- const shape = getShapeByElement(this.board, this.node.origin);
3149
- switch (shape) {
3150
- case MindElementShape.roundRectangle:
3151
- this.shapeG = drawRoundRectangleByNode(this.board, this.node);
3152
- this.g.prepend(this.shapeG);
3153
- break;
3154
- default:
3155
- break;
3156
- }
3157
- }
3158
- destroyShape() {
3159
- if (this.shapeG) {
3160
- this.shapeG.remove();
3161
- this.shapeG = null;
3162
- }
3163
- }
3164
3060
  drawLink() {
3165
3061
  if (PlaitMind.isMind(this.element)) {
3166
3062
  return;
@@ -3206,35 +3102,16 @@ class MindNodeComponent extends PlaitPluginElementComponent {
3206
3102
  drawTopic() {
3207
3103
  this.textManage.draw(this.element.data.topic);
3208
3104
  this.g.append(this.textManage.g);
3209
- if (this.element.manualWidth) {
3210
- const width = NodeSpace.getNodeDynamicWidth(this.board, this.element);
3211
- this.textManage.updateWidth(width);
3212
- }
3213
3105
  }
3214
3106
  updateTopic() {
3215
3107
  this.textManage.updateText(this.element.data.topic);
3216
3108
  this.textManage.updateRectangle();
3217
- if (this.element.manualWidth) {
3218
- const width = NodeSpace.getNodeDynamicWidth(this.board, this.element);
3219
- this.textManage.updateWidth(width);
3220
- }
3221
3109
  }
3222
3110
  editTopic() {
3223
- this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: true });
3224
- // update text max-width when image width greater than topic default max width to cover node topic default max width style
3225
- const defaultMaxWidth = TOPIC_DEFAULT_MAX_WORD_COUNT * (PlaitMind.isMind(this.element) ? ROOT_TOPIC_FONT_SIZE : TOPIC_FONT_SIZE);
3226
- let hasMaxWidth = false;
3227
- if (!this.element.manualWidth && MindElement.hasImage(this.element) && this.element.data.image.width > defaultMaxWidth) {
3228
- const width = NodeSpace.getNodeDynamicWidth(this.board, this.element);
3229
- this.textManage.updateWidth(width);
3230
- hasMaxWidth = true;
3231
- }
3111
+ this.activeGenerator.draw(this.element, this.g, { selected: this.selected, isEditing: true });
3232
3112
  this.textManage.edit((origin) => {
3233
3113
  if (origin === ExitOrigin.default) {
3234
- this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: false });
3235
- }
3236
- if (hasMaxWidth) {
3237
- this.textManage.updateWidth(0);
3114
+ this.activeGenerator.draw(this.element, this.g, { selected: this.selected, isEditing: false });
3238
3115
  }
3239
3116
  });
3240
3117
  }
@@ -3242,16 +3119,15 @@ class MindNodeComponent extends PlaitPluginElementComponent {
3242
3119
  super.ngOnDestroy();
3243
3120
  this.textManage.destroy();
3244
3121
  this.nodeEmojisDrawer.destroy();
3245
- this.imageDrawer.destroy();
3122
+ this.imageGenerator.destroy();
3246
3123
  this.destroy$.next();
3247
3124
  this.destroy$.complete();
3248
3125
  if (ELEMENT_TO_NODE.get(this.element) === this.node) {
3249
3126
  ELEMENT_TO_NODE.delete(this.element);
3250
3127
  }
3251
3128
  }
3252
- }
3253
- MindNodeComponentfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindNodeComponent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
3254
- MindNodeComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.5", type: MindNodeComponent, selector: "plait-mind-node", usesInheritance: true, ngImport: i0, template: `
3129
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.3", ngImport: i0, type: MindNodeComponent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
3130
+ static { thiscmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.3", type: MindNodeComponent, isStandalone: true, selector: "plait-mind-node", usesInheritance: true, ngImport: i0, template: `
3255
3131
  <plait-children
3256
3132
  *ngIf="!element.isCollapsed"
3257
3133
  [board]="board"
@@ -3259,8 +3135,9 @@ MindNodeComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", vers
3259
3135
  [effect]="effect"
3260
3136
  [parentG]="parentG"
3261
3137
  ></plait-children>
3262
- `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.PlaitChildrenElement, selector: "plait-children", inputs: ["board", "parent", "effect", "parentG"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3263
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindNodeComponent, decorators: [{
3138
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PlaitChildrenElementComponent, selector: "plait-children", inputs: ["board", "parent", "effect", "parentG"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3139
+ }
3140
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.3", ngImport: i0, type: MindNodeComponent, decorators: [{
3264
3141
  type: Component,
3265
3142
  args: [{
3266
3143
  selector: 'plait-mind-node',
@@ -3273,7 +3150,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
3273
3150
  [parentG]="parentG"
3274
3151
  ></plait-children>
3275
3152
  `,
3276
- changeDetection: ChangeDetectionStrategy.OnPush
3153
+ changeDetection: ChangeDetectionStrategy.OnPush,
3154
+ standalone: true,
3155
+ imports: [NgIf, PlaitChildrenElementComponent]
3277
3156
  }]
3278
3157
  }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; } });
3279
3158
 
@@ -3303,33 +3182,21 @@ class PlaitMindComponent extends MindNodeComponent {
3303
3182
  ELEMENT_TO_NODE.set(node.origin, node);
3304
3183
  });
3305
3184
  }
3306
- }
3307
- PlaitMindComponentfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: PlaitMindComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
3308
- PlaitMindComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.5", type: PlaitMindComponent, selector: "plait-mind", usesInheritance: true, ngImport: i0, template: `
3185
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.3", ngImport: i0, type: PlaitMindComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3186
+ static { thiscmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.3", type: PlaitMindComponent, isStandalone: true, selector: "plait-mind", usesInheritance: true, ngImport: i0, template: `
3309
3187
  <plait-children [board]="board" [parent]="element" [effect]="effect" [parentG]="rootG"></plait-children>
3310
- `, isInline: true, dependencies: [{ kind: "component", type: i2.PlaitChildrenElement, selector: "plait-children", inputs: ["board", "parent", "effect", "parentG"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3311
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: PlaitMindComponent, decorators: [{
3188
+ `, isInline: true, dependencies: [{ kind: "component", type: PlaitChildrenElementComponent, selector: "plait-children", inputs: ["board", "parent", "effect", "parentG"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3189
+ }
3190
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.3", ngImport: i0, type: PlaitMindComponent, decorators: [{
3312
3191
  type: Component,
3313
3192
  args: [{
3314
3193
  selector: 'plait-mind',
3315
3194
  template: `
3316
3195
  <plait-children [board]="board" [parent]="element" [effect]="effect" [parentG]="rootG"></plait-children>
3317
3196
  `,
3318
- changeDetection: ChangeDetectionStrategy.OnPush
3319
- }]
3320
- }] });
3321
-
3322
- class MindModule {
3323
- }
3324
- MindModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3325
- MindModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.5", ngImport: i0, type: MindModule, declarations: [PlaitMindComponent, MindNodeComponent], imports: [CommonModule, TextModule, PlaitModule], exports: [PlaitMindComponent, MindNodeComponent] });
3326
- MindModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, imports: [CommonModule, TextModule, PlaitModule] });
3327
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, decorators: [{
3328
- type: NgModule,
3329
- args: [{
3330
- declarations: [PlaitMindComponent, MindNodeComponent],
3331
- imports: [CommonModule, TextModule, PlaitModule],
3332
- exports: [PlaitMindComponent, MindNodeComponent]
3197
+ changeDetection: ChangeDetectionStrategy.OnPush,
3198
+ standalone: true,
3199
+ imports: [PlaitChildrenElementComponent, MindNodeComponent]
3333
3200
  }]
3334
3201
  }] });
3335
3202
 
@@ -3455,7 +3322,7 @@ const withNodeDnd = (board) => {
3455
3322
  refs = insertElementHandleRightNodeCount(board, targetElementPathRef.current.slice(0, 1), normalElements.length, refs);
3456
3323
  }
3457
3324
  MindTransforms.setRightNodeCountByRefs(board, refs);
3458
- MindTransforms.removeElements(board, firstLevelElements);
3325
+ CoreTransforms.removeElements(board, firstLevelElements);
3459
3326
  let insertPath = targetPathRef.current;
3460
3327
  const parentPath = Path.parent(targetPathRef.current || targetPath);
3461
3328
  if (!insertPath) {
@@ -3489,7 +3356,7 @@ const withNodeDnd = (board) => {
3489
3356
  setActiveElements.push(node);
3490
3357
  }
3491
3358
  });
3492
- Transforms.setSelectionWithTemporaryElements(board, setActiveElements);
3359
+ Transforms.addSelectionWithTemporaryElements(board, setActiveElements);
3493
3360
  }
3494
3361
  setIsDragging(board, false);
3495
3362
  activeElements = [];
@@ -3504,108 +3371,6 @@ const withNodeDnd = (board) => {
3504
3371
  return board;
3505
3372
  };
3506
3373
 
3507
- const buildClipboardData = (board, selectedElements, startPoint) => {
3508
- let result = [];
3509
- // get overall abstract
3510
- const overallAbstracts = getOverallAbstracts(board, selectedElements);
3511
- // get valid abstract refs
3512
- const validAbstractRefs = getValidAbstractRefs(board, [...selectedElements, ...overallAbstracts]);
3513
- // keep correct order
3514
- const newSelectedElements = selectedElements.filter(value => !validAbstractRefs.find(ref => ref.abstract === value));
3515
- newSelectedElements.push(...validAbstractRefs.map(value => value.abstract));
3516
- const selectedMindNodes = newSelectedElements.map(value => MindElement.getNode(value));
3517
- newSelectedElements.forEach((element, index) => {
3518
- // handle relative location
3519
- const nodeRectangle = getRectangleByNode(selectedMindNodes[index]);
3520
- const points = [[nodeRectangle.x - startPoint[0], nodeRectangle.y - startPoint[1]]];
3521
- // handle invalid abstract
3522
- const abstractRef = validAbstractRefs.find(ref => ref.abstract === element);
3523
- if (AbstractNode.isAbstract(element) && abstractRef) {
3524
- const { start, end } = getRelativeStartEndByAbstractRef(abstractRef, newSelectedElements);
3525
- result.push({
3526
- ...element,
3527
- points,
3528
- start,
3529
- end
3530
- });
3531
- }
3532
- else {
3533
- if (AbstractNode.isAbstract(element)) {
3534
- let newElement = { ...element, points };
3535
- delete newElement.start;
3536
- delete newElement.end;
3537
- result.push(newElement);
3538
- }
3539
- else {
3540
- result.push({
3541
- ...element,
3542
- points: points
3543
- });
3544
- }
3545
- }
3546
- });
3547
- return result;
3548
- };
3549
- const setMindClipboardData = (data, elements) => {
3550
- const text = elements.reduce((string, currentNode) => {
3551
- return string + extractNodesText(currentNode);
3552
- }, '');
3553
- setClipboardData(data, elements);
3554
- setClipboardDataByText(data, text);
3555
- };
3556
- const insertClipboardData = (board, elements, targetPoint) => {
3557
- let newElement, path;
3558
- const selectedElements = getSelectedElements(board);
3559
- let newELements = [];
3560
- const hasTargetParent = selectedElements.length === 1;
3561
- const targetParent = selectedElements[0];
3562
- const targetParentPath = targetParent && PlaitBoard.findPath(board, targetParent);
3563
- const nonAbstractChildrenLength = targetParent && getNonAbstractChildren(targetParent).length;
3564
- elements.forEach((item, index) => {
3565
- newElement = copyNewNode(item);
3566
- if (hasTargetParent) {
3567
- if (item.isRoot) {
3568
- newElement = adjustRootToNode(board, newElement);
3569
- const styles = PlaitMind.isMind(targetParent) ? { fontFamily: BRANCH_FONT_FAMILY } : { fontFamily: DEFAULT_FONT_FAMILY };
3570
- const { width, height } = getTextSize(board, newElement.data.topic, TOPIC_DEFAULT_MAX_WORD_COUNT, {
3571
- ...styles,
3572
- width: newElement.manualWidth ? newElement.manualWidth : undefined
3573
- });
3574
- newElement.width = Math.max(width, getNodeDefaultFontSize());
3575
- newElement.height = height;
3576
- }
3577
- // handle abstract start and end
3578
- if (AbstractNode.isAbstract(newElement)) {
3579
- newElement.start = newElement.start + nonAbstractChildrenLength;
3580
- newElement.end = newElement.end + nonAbstractChildrenLength;
3581
- }
3582
- path = [...targetParentPath, nonAbstractChildrenLength + index];
3583
- }
3584
- else {
3585
- const point = [targetPoint[0] + item.points[0][0], targetPoint[1] + item.points[0][1]];
3586
- newElement.points = [point];
3587
- if (AbstractNode.isAbstract(item)) {
3588
- newElement = adjustAbstractToNode(newElement);
3589
- }
3590
- if (!item.isRoot) {
3591
- newElement = adjustNodeToRoot(board, newElement);
3592
- }
3593
- path = [board.children.length];
3594
- }
3595
- newELements.push(newElement);
3596
- Transforms.insertNode(board, newElement, path);
3597
- return;
3598
- });
3599
- Transforms.setSelectionWithTemporaryElements(board, newELements);
3600
- };
3601
- const insertClipboardText = (board, targetParent, text) => {
3602
- const styles = PlaitMind.isMind(targetParent) ? { fontFamily: BRANCH_FONT_FAMILY } : { fontFamily: DEFAULT_FONT_FAMILY };
3603
- const { width, height } = getTextSize(board, text, TOPIC_DEFAULT_MAX_WORD_COUNT, styles);
3604
- const newElement = createMindElement(text, Math.max(width, getFontSizeBySlateElement(text)), height, {});
3605
- Transforms.insertNode(board, newElement, findNewChildNodePath(board, targetParent));
3606
- return;
3607
- };
3608
-
3609
3374
  const withAbstract = (board) => {
3610
3375
  const newBoard = board;
3611
3376
  const { mousedown, mousemove, mouseup } = board;
@@ -3685,7 +3450,7 @@ const withAbstract = (board) => {
3685
3450
  newProperty =
3686
3451
  abstractHandlePosition === AbstractHandlePosition.start ? { start: locationIndex + 1 } : { end: locationIndex };
3687
3452
  }
3688
- abstractComponent.activeDrawer.updateAbstractOutline(activeAbstractElement, abstractHandlePosition, location);
3453
+ abstractComponent.activeGenerator.updateAbstractOutline(activeAbstractElement, abstractHandlePosition, location);
3689
3454
  }
3690
3455
  mousemove(event);
3691
3456
  };
@@ -3702,7 +3467,7 @@ const withAbstract = (board) => {
3702
3467
  }
3703
3468
  else {
3704
3469
  const abstractComponent = PlaitElement.getComponent(activeAbstractElement);
3705
- abstractComponent.activeDrawer.updateAbstractOutline(activeAbstractElement);
3470
+ abstractComponent.activeGenerator.updateAbstractOutline(activeAbstractElement);
3706
3471
  }
3707
3472
  activeAbstractElement = undefined;
3708
3473
  }
@@ -3725,15 +3490,17 @@ const withCreateMind = (board) => {
3725
3490
  const newBoard = board;
3726
3491
  const { keydown, mousedown, mousemove, mouseup } = board;
3727
3492
  let fakeCreateNodeRef = null;
3493
+ let emptyMind = null;
3728
3494
  newBoard.mousedown = (event) => {
3729
- if (fakeCreateNodeRef && PlaitBoard.isPointer(board, MindPointerType.mind)) {
3730
- const currentOptions = board.getPluginOptions(PlaitPluginKey.withSelection);
3731
- board.setPluginOptions(PlaitPluginKey.withSelection, {
3732
- isDisabledSelect: true
3733
- });
3734
- setTimeout(() => {
3735
- board.setPluginOptions(PlaitPluginKey.withSelection, { ...currentOptions });
3736
- }, 0);
3495
+ const isMindPointer = PlaitBoard.isPointer(board, MindPointerType.mind);
3496
+ let movingPoint = PlaitBoard.getMovingPointInBoard(board);
3497
+ if (movingPoint && isDrawingMode(board) && isMindPointer) {
3498
+ movingPoint = transformPoint(board, toPoint(movingPoint[0], movingPoint[1], PlaitBoard.getHost(board)));
3499
+ const emptyMind = createEmptyMind(newBoard, movingPoint);
3500
+ Transforms.insertNode(board, emptyMind, [board.children.length]);
3501
+ clearSelectedElement(board);
3502
+ addSelectedElement(board, emptyMind);
3503
+ BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
3737
3504
  }
3738
3505
  mousedown(event);
3739
3506
  };
@@ -3742,13 +3509,14 @@ const withCreateMind = (board) => {
3742
3509
  mousemove(event);
3743
3510
  return;
3744
3511
  }
3745
- if (PlaitBoard.isPointer(board, MindPointerType.mind)) {
3512
+ const isMindPointer = PlaitBoard.isPointer(board, MindPointerType.mind);
3513
+ if (isDndMode(board) && isMindPointer) {
3746
3514
  throttleRAF(() => {
3747
- const movingPoint = PlaitBoard.getMovingPointInBoard(board);
3515
+ let movingPoint = PlaitBoard.getMovingPointInBoard(board);
3748
3516
  if (movingPoint) {
3749
- const targetPoint = transformPoint(board, toPoint(movingPoint[0], movingPoint[1], PlaitBoard.getHost(board)));
3750
- const emptyMind = createEmptyMind(targetPoint);
3751
- const nodeRectangle = getRectangleByElement(newBoard, targetPoint, emptyMind);
3517
+ movingPoint = transformPoint(newBoard, toPoint(movingPoint[0], movingPoint[1], PlaitBoard.getHost(board)));
3518
+ emptyMind = createEmptyMind(newBoard, movingPoint);
3519
+ const nodeRectangle = getRectangleByElement(newBoard, emptyMind);
3752
3520
  const nodeG = drawRoundRectangleByElement(board, nodeRectangle, emptyMind);
3753
3521
  const topicRectangle = getTopicRectangleByElement(newBoard, nodeRectangle, emptyMind);
3754
3522
  if (!fakeCreateNodeRef) {
@@ -3788,14 +3556,12 @@ const withCreateMind = (board) => {
3788
3556
  mousemove(event);
3789
3557
  };
3790
3558
  newBoard.mouseup = (event) => {
3791
- const movingPoint = PlaitBoard.getMovingPointInBoard(board);
3792
- if (movingPoint && fakeCreateNodeRef && PlaitBoard.isPointer(board, MindPointerType.mind)) {
3793
- const targetPoint = transformPoint(board, toPoint(movingPoint[0], movingPoint[1], PlaitBoard.getHost(board)));
3794
- const emptyMind = createEmptyMind(targetPoint);
3559
+ if (emptyMind) {
3795
3560
  Transforms.insertNode(board, emptyMind, [board.children.length]);
3796
3561
  clearSelectedElement(board);
3797
3562
  addSelectedElement(board, emptyMind);
3798
3563
  BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
3564
+ emptyMind = null;
3799
3565
  }
3800
3566
  destroy();
3801
3567
  mouseup(event);
@@ -3807,6 +3573,7 @@ const withCreateMind = (board) => {
3807
3573
  }
3808
3574
  if (event.key === DefaultHotkey && !PlaitBoard.isPointer(board, MindPointerType.mind)) {
3809
3575
  BoardTransforms.updatePointerType(board, MindPointerType.mind);
3576
+ setCreationMode(board, BoardCreationMode.drawing);
3810
3577
  event.preventDefault();
3811
3578
  return;
3812
3579
  }
@@ -3824,7 +3591,7 @@ const withCreateMind = (board) => {
3824
3591
 
3825
3592
  const withMindHotkey = (baseBoard) => {
3826
3593
  const board = baseBoard;
3827
- const { keydown, deleteFragment } = board;
3594
+ const { keydown } = board;
3828
3595
  board.keydown = (event) => {
3829
3596
  const selectedElements = getSelectedElements(board);
3830
3597
  const isSingleSelection = selectedElements.length === 1;
@@ -3864,73 +3631,19 @@ const withMindHotkey = (baseBoard) => {
3864
3631
  insertMindElement(board, targetElement, findNewSiblingNodePath(board, targetElement));
3865
3632
  return;
3866
3633
  }
3867
- if (!isVirtualKey(event) && !isSpaceHotkey(event) && isSingleSelection) {
3634
+ if (!isVirtualKey(event) &&
3635
+ !isDelete(event) &&
3636
+ !isSpaceHotkey(event) &&
3637
+ isSingleSelection &&
3638
+ MindElement.isMindElement(board, targetElement)) {
3868
3639
  event.preventDefault();
3869
3640
  editTopic(targetElement);
3870
- return;
3871
- }
3872
- }
3873
- keydown(event);
3874
- };
3875
- board.deleteFragment = (data) => {
3876
- const targetMindElements = getSelectedMindElements(board);
3877
- if (targetMindElements.length) {
3878
- const firstLevelElements = getFirstLevelElement(targetMindElements).reverse();
3879
- const abstractRefs = deleteElementHandleAbstract(board, firstLevelElements);
3880
- MindTransforms.setAbstractsByRefs(board, abstractRefs);
3881
- const refs = deleteElementsHandleRightNodeCount(board, targetMindElements);
3882
- MindTransforms.setRightNodeCountByRefs(board, refs);
3883
- MindTransforms.removeElements(board, targetMindElements);
3884
- const nextSelected = getNextSelectedElement(board, firstLevelElements);
3885
- if (nextSelected) {
3886
- addSelectedElement(board, nextSelected);
3887
- }
3888
- }
3889
- deleteFragment(data);
3890
- };
3891
- return board;
3892
- };
3893
- const getNextSelectedElement = (board, firstLevelElements) => {
3894
- let activeElement;
3895
- const firstLevelElement = firstLevelElements[0];
3896
- const firstLevelElementPath = PlaitBoard.findPath(board, firstLevelElement);
3897
- let nextSelectedPath = firstLevelElementPath;
3898
- if (Path.hasPrevious(firstLevelElementPath)) {
3899
- nextSelectedPath = Path.previous(firstLevelElementPath);
3900
- }
3901
- if (AbstractNode.isAbstract(firstLevelElement)) {
3902
- const parent = MindElement.getParent(firstLevelElement);
3903
- if (!firstLevelElements.includes(parent.children[firstLevelElement.start])) {
3904
- activeElement = parent.children[firstLevelElement.start];
3905
- }
3906
- }
3907
- try {
3908
- if (!activeElement) {
3909
- activeElement = PlaitNode.get(board, nextSelectedPath);
3641
+ return;
3642
+ }
3910
3643
  }
3911
- }
3912
- catch (error) { }
3913
- const firstElement = firstLevelElements[0];
3914
- const firstElementParent = MindElement.findParent(firstElement);
3915
- const hasSameParent = firstLevelElements.every(element => {
3916
- return MindElement.findParent(element) === firstElementParent;
3917
- });
3918
- if (firstElementParent && hasSameParent && !activeElement) {
3919
- activeElement = firstElementParent;
3920
- }
3921
- return activeElement;
3922
- };
3923
- const isExpandHotkey = (event) => {
3924
- return isKeyHotkey('mod+/', event);
3925
- };
3926
- const isTabHotkey = (event) => {
3927
- return event.key === 'Tab';
3928
- };
3929
- const isEnterHotkey = (event) => {
3930
- return event.key === 'Enter';
3931
- };
3932
- const isSpaceHotkey = (event) => {
3933
- return event.code === 'Space';
3644
+ keydown(event);
3645
+ };
3646
+ return board;
3934
3647
  };
3935
3648
 
3936
3649
  const mouseMoveHandle = (board, event, nodeHoveredExtendRef) => {
@@ -4049,13 +3762,13 @@ const withNodeImage = (board) => {
4049
3762
  }
4050
3763
  globalPointerUp(event);
4051
3764
  };
4052
- board.setFragment = (data, rectangle) => {
3765
+ board.setFragment = (data, rectangle, type) => {
4053
3766
  const selectedImageElement = getSelectedImageElement(board);
4054
3767
  if (selectedImageElement) {
4055
3768
  setClipboardDataByMedia(data, selectedImageElement.data.image, MediaKeys.image);
4056
3769
  return;
4057
3770
  }
4058
- setFragment(data, rectangle);
3771
+ setFragment(data, rectangle, type);
4059
3772
  };
4060
3773
  board.deleteFragment = (data) => {
4061
3774
  const selectedImageElement = getSelectedImageElement(board);
@@ -4069,11 +3782,13 @@ const withNodeImage = (board) => {
4069
3782
  const isSelectedImage = !!getSelectedImageElement(board);
4070
3783
  const isSingleSelection = selectedElements.length === 1 && MindElement.isMindElement(board, selectedElements[0]);
4071
3784
  if (data?.files.length && (isSingleSelection || isSelectedImage)) {
4072
- const selectedElement = (selectedElements[0] || getSelectedImageElement(board));
4073
3785
  const acceptImageArray = acceptImageTypes.map(type => 'image/' + type);
3786
+ const selectedElement = (selectedElements[0] || getSelectedImageElement(board));
4074
3787
  if (acceptImageArray.includes(data?.files[0].type)) {
4075
3788
  const imageFile = data.files[0];
4076
- buildImage(board, selectedElement, imageFile);
3789
+ buildImage(board, imageFile, DEFAULT_MIND_IMAGE_WIDTH, imageItem => {
3790
+ MindTransforms.setImage(board, selectedElement, imageItem);
3791
+ });
4077
3792
  return;
4078
3793
  }
4079
3794
  }
@@ -4100,6 +3815,7 @@ const withNodeResize = (board) => {
4100
3815
  PlaitBoard.getBoardContainer(board).classList.add(ResizeCursorClass['ew-resize']);
4101
3816
  targetElement = newTargetElement;
4102
3817
  startPoint = [event.x, event.y];
3818
+ preventTouchMove(board, event, true);
4103
3819
  return;
4104
3820
  }
4105
3821
  pointerDown(event);
@@ -4112,7 +3828,6 @@ const withNodeResize = (board) => {
4112
3828
  if (startPoint && targetElement && !isMindNodeResizing(board)) {
4113
3829
  // prevent text from being selected
4114
3830
  event.preventDefault();
4115
- preventTouchMove(board, true);
4116
3831
  const endPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
4117
3832
  const distance = distanceBetweenPointAndPoint(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
4118
3833
  if (distance > PRESS_AND_MOVE_BUFFER) {
@@ -4121,7 +3836,7 @@ const withNodeResize = (board) => {
4121
3836
  minWidth: NodeSpace.getNodeResizableMinWidth(board, targetElement),
4122
3837
  currentWidth: NodeSpace.getNodeDynamicWidth(board, targetElement),
4123
3838
  path: PlaitBoard.findPath(board, targetElement),
4124
- textManage: PlaitElement.getComponent(targetElement).textManage
3839
+ textManage: MindElement.getTextManage(targetElement)
4125
3840
  };
4126
3841
  MERGING.set(board, true);
4127
3842
  }
@@ -4129,7 +3844,7 @@ const withNodeResize = (board) => {
4129
3844
  if (isMindNodeResizing(board) && startPoint && targetElementRef) {
4130
3845
  // prevent text from being selected
4131
3846
  event.preventDefault();
4132
- preventTouchMove(board, true);
3847
+ preventTouchMove(board, event, true);
4133
3848
  throttleRAF(() => {
4134
3849
  if (!startPoint) {
4135
3850
  return;
@@ -4143,7 +3858,7 @@ const withNodeResize = (board) => {
4143
3858
  }
4144
3859
  const newTarget = PlaitNode.get(board, targetElementRef.path);
4145
3860
  if (newTarget && NodeSpace.getNodeTopicMinWidth(board, newTarget) !== resizedWidth) {
4146
- targetElementRef.textManage.updateWidth(resizedWidth);
3861
+ targetElementRef.textManage.updateRectangleWidth(resizedWidth);
4147
3862
  const { height } = targetElementRef.textManage.getSize();
4148
3863
  MindTransforms.setNodeManualWidth(board, newTarget, resizedWidth * zoom, height);
4149
3864
  }
@@ -4173,7 +3888,7 @@ const withNodeResize = (board) => {
4173
3888
  targetElement = null;
4174
3889
  startPoint = null;
4175
3890
  MERGING.set(board, false);
4176
- preventTouchMove(board, false);
3891
+ preventTouchMove(board, event, false);
4177
3892
  }
4178
3893
  };
4179
3894
  return board;
@@ -4227,7 +3942,7 @@ const withNodeImageResize = (board) => {
4227
3942
  if (result) {
4228
3943
  return {
4229
3944
  element: selectedMindElement,
4230
- direction: result.direction,
3945
+ handle: result.handle,
4231
3946
  cursorClass: result.cursorClass
4232
3947
  };
4233
3948
  }
@@ -4237,7 +3952,7 @@ const withNodeImageResize = (board) => {
4237
3952
  onResize: (resizeRef, resizeState) => {
4238
3953
  let offsetX = resizeState.offsetX;
4239
3954
  let offsetY = resizeState.offsetY;
4240
- if (resizeRef.direction === ResizeDirection.nw || resizeRef.direction === ResizeDirection.sw) {
3955
+ if (resizeRef.handle === ResizeHandle.nw || resizeRef.handle === ResizeHandle.sw) {
4241
3956
  offsetX = -offsetX;
4242
3957
  }
4243
3958
  const originWidth = resizeRef.element.data.image.width;
@@ -4257,9 +3972,191 @@ const withNodeImageResize = (board) => {
4257
3972
  return board;
4258
3973
  };
4259
3974
 
3975
+ const buildClipboardData = (board, selectedElements, startPoint) => {
3976
+ let result = [];
3977
+ // get overall abstract
3978
+ const overallAbstracts = getOverallAbstracts(board, selectedElements);
3979
+ // get valid abstract refs
3980
+ const validAbstractRefs = getValidAbstractRefs(board, [...selectedElements, ...overallAbstracts]);
3981
+ // keep correct order
3982
+ const newSelectedElements = selectedElements.filter(value => !validAbstractRefs.find(ref => ref.abstract === value));
3983
+ newSelectedElements.push(...validAbstractRefs.map(value => value.abstract));
3984
+ const selectedMindNodes = newSelectedElements.map(value => MindElement.getNode(value));
3985
+ newSelectedElements.forEach((element, index) => {
3986
+ // handle relative location
3987
+ const nodeRectangle = getRectangleByNode(selectedMindNodes[index]);
3988
+ const points = [[nodeRectangle.x - startPoint[0], nodeRectangle.y - startPoint[1]]];
3989
+ // handle invalid abstract
3990
+ const abstractRef = validAbstractRefs.find(ref => ref.abstract === element);
3991
+ if (AbstractNode.isAbstract(element) && abstractRef) {
3992
+ const { start, end } = getRelativeStartEndByAbstractRef(abstractRef, newSelectedElements);
3993
+ result.push({
3994
+ ...element,
3995
+ points,
3996
+ start,
3997
+ end
3998
+ });
3999
+ }
4000
+ else {
4001
+ if (AbstractNode.isAbstract(element)) {
4002
+ let newElement = { ...element, points };
4003
+ delete newElement.start;
4004
+ delete newElement.end;
4005
+ result.push(newElement);
4006
+ }
4007
+ else {
4008
+ result.push({
4009
+ ...element,
4010
+ points: points
4011
+ });
4012
+ }
4013
+ }
4014
+ });
4015
+ return result;
4016
+ };
4017
+ const setMindClipboardData = (data, elements) => {
4018
+ const text = elements.reduce((string, currentNode) => {
4019
+ return string + extractNodesText(currentNode);
4020
+ }, '');
4021
+ setClipboardData(data, elements);
4022
+ setClipboardDataByText(data, text);
4023
+ };
4024
+ const insertClipboardData = (board, elements, targetPoint) => {
4025
+ let newElement, path;
4026
+ const selectedElements = getSelectedElements(board);
4027
+ let newELements = [];
4028
+ const hasTargetParent = selectedElements.length === 1;
4029
+ const targetParent = selectedElements[0];
4030
+ const targetParentPath = targetParent && PlaitBoard.findPath(board, targetParent);
4031
+ const nonAbstractChildrenLength = targetParent && getNonAbstractChildren(targetParent).length;
4032
+ elements.forEach((item, index) => {
4033
+ newElement = copyNewNode(item);
4034
+ if (hasTargetParent) {
4035
+ if (item.isRoot) {
4036
+ newElement = adjustRootToNode(board, newElement);
4037
+ const styles = PlaitMind.isMind(targetParent) ? { fontFamily: BRANCH_FONT_FAMILY } : { fontFamily: DEFAULT_FONT_FAMILY };
4038
+ const { width, height } = getTextSize(board, newElement.data.topic, TOPIC_DEFAULT_MAX_WORD_COUNT, {
4039
+ ...styles,
4040
+ width: newElement.manualWidth ? newElement.manualWidth : undefined
4041
+ });
4042
+ newElement.width = Math.max(width, getNodeDefaultFontSize());
4043
+ newElement.height = height;
4044
+ }
4045
+ // handle abstract start and end
4046
+ if (AbstractNode.isAbstract(newElement)) {
4047
+ newElement.start = newElement.start + nonAbstractChildrenLength;
4048
+ newElement.end = newElement.end + nonAbstractChildrenLength;
4049
+ }
4050
+ path = [...targetParentPath, nonAbstractChildrenLength + index];
4051
+ }
4052
+ else {
4053
+ const point = [targetPoint[0] + item.points[0][0], targetPoint[1] + item.points[0][1]];
4054
+ newElement.points = [point];
4055
+ if (AbstractNode.isAbstract(item)) {
4056
+ newElement = adjustAbstractToNode(newElement);
4057
+ }
4058
+ if (!item.isRoot) {
4059
+ newElement = adjustNodeToRoot(board, newElement);
4060
+ }
4061
+ path = [board.children.length];
4062
+ }
4063
+ newELements.push(newElement);
4064
+ Transforms.insertNode(board, newElement, path);
4065
+ return;
4066
+ });
4067
+ Transforms.addSelectionWithTemporaryElements(board, newELements);
4068
+ };
4069
+ const insertClipboardText = (board, targetParent, text) => {
4070
+ const styles = PlaitMind.isMind(targetParent) ? { fontFamily: BRANCH_FONT_FAMILY } : { fontFamily: DEFAULT_FONT_FAMILY };
4071
+ const { width, height } = getTextSize(board, text, TOPIC_DEFAULT_MAX_WORD_COUNT, styles);
4072
+ const newElement = createMindElement(text, Math.max(width, getFontSizeBySlateElement(text)), height, {});
4073
+ Transforms.insertNode(board, newElement, findNewChildNodePath(board, targetParent));
4074
+ Transforms.addSelectionWithTemporaryElements(board, [newElement]);
4075
+ };
4076
+
4077
+ const withMindFragment = (baseBoard) => {
4078
+ const board = baseBoard;
4079
+ const { getDeletedFragment, insertFragment, setFragment } = board;
4080
+ board.getDeletedFragment = (data) => {
4081
+ const targetMindElements = getSelectedMindElements(board);
4082
+ if (targetMindElements.length) {
4083
+ const firstLevelElements = getFirstLevelElement(targetMindElements).reverse();
4084
+ const abstractRefs = deleteElementHandleAbstract(board, firstLevelElements);
4085
+ MindTransforms.setAbstractsByRefs(board, abstractRefs);
4086
+ const refs = deleteElementsHandleRightNodeCount(board, targetMindElements);
4087
+ MindTransforms.setRightNodeCountByRefs(board, refs);
4088
+ const deletableElements = getFirstLevelElement(targetMindElements);
4089
+ data.push(...deletableElements);
4090
+ const nextSelected = getNextSelectedElement(board, firstLevelElements);
4091
+ if (nextSelected) {
4092
+ addSelectedElement(board, nextSelected);
4093
+ }
4094
+ }
4095
+ return getDeletedFragment(data);
4096
+ };
4097
+ board.setFragment = (data, rectangle, type) => {
4098
+ const targetMindElements = getSelectedMindElements(board);
4099
+ const firstLevelElements = getFirstLevelElement(targetMindElements);
4100
+ if (firstLevelElements.length) {
4101
+ const elements = buildClipboardData(board, firstLevelElements, rectangle ? [rectangle.x, rectangle.y] : [0, 0]);
4102
+ setMindClipboardData(data, elements);
4103
+ }
4104
+ setFragment(data, rectangle, type);
4105
+ };
4106
+ board.insertFragment = (data, targetPoint) => {
4107
+ const elements = getDataFromClipboard(data);
4108
+ const mindElements = elements.filter(value => MindElement.isMindElement(board, value));
4109
+ if (elements.length > 0 && mindElements.length > 0) {
4110
+ insertClipboardData(board, mindElements, targetPoint);
4111
+ }
4112
+ else if (elements.length === 0) {
4113
+ const mindElements = getSelectedMindElements(board);
4114
+ if (mindElements.length === 1) {
4115
+ const text = getTextFromClipboard(data);
4116
+ if (text) {
4117
+ insertClipboardText(board, mindElements[0], buildText(text));
4118
+ return;
4119
+ }
4120
+ }
4121
+ }
4122
+ insertFragment(data, targetPoint);
4123
+ };
4124
+ return board;
4125
+ };
4126
+ const getNextSelectedElement = (board, firstLevelElements) => {
4127
+ let activeElement;
4128
+ const firstLevelElement = firstLevelElements[0];
4129
+ const firstLevelElementPath = PlaitBoard.findPath(board, firstLevelElement);
4130
+ let nextSelectedPath = firstLevelElementPath;
4131
+ if (Path.hasPrevious(firstLevelElementPath)) {
4132
+ nextSelectedPath = Path.previous(firstLevelElementPath);
4133
+ }
4134
+ if (AbstractNode.isAbstract(firstLevelElement)) {
4135
+ const parent = MindElement.getParent(firstLevelElement);
4136
+ if (!firstLevelElements.includes(parent.children[firstLevelElement.start])) {
4137
+ activeElement = parent.children[firstLevelElement.start];
4138
+ }
4139
+ }
4140
+ try {
4141
+ if (!activeElement) {
4142
+ activeElement = PlaitNode.get(board, nextSelectedPath);
4143
+ }
4144
+ }
4145
+ catch (error) { }
4146
+ const firstElement = firstLevelElements[0];
4147
+ const firstElementParent = MindElement.findParent(firstElement);
4148
+ const hasSameParent = firstLevelElements.every(element => {
4149
+ return MindElement.findParent(element) === firstElementParent;
4150
+ });
4151
+ if (firstElementParent && hasSameParent && !activeElement) {
4152
+ activeElement = firstElementParent;
4153
+ }
4154
+ return activeElement;
4155
+ };
4156
+
4260
4157
  const withMind = (baseBoard) => {
4261
4158
  const board = baseBoard;
4262
- const { drawElement, dblclick, insertFragment, setFragment, isHitSelection, getRectangle, isMovable, isRecursion } = board;
4159
+ const { drawElement, dblclick, isHitSelection, getRectangle, isMovable, isRecursion, isAlign } = board;
4263
4160
  board.drawElement = (context) => {
4264
4161
  if (PlaitMind.isMind(context.element)) {
4265
4162
  return PlaitMindComponent;
@@ -4303,6 +4200,12 @@ const withMind = (baseBoard) => {
4303
4200
  }
4304
4201
  return isMovable(element);
4305
4202
  };
4203
+ board.isAlign = (element) => {
4204
+ if (PlaitMind.isMind(element) && element.isRoot) {
4205
+ return true;
4206
+ }
4207
+ return isAlign(element);
4208
+ };
4306
4209
  board.dblclick = (event) => {
4307
4210
  if (PlaitBoard.isReadonly(board)) {
4308
4211
  dblclick(event);
@@ -4323,41 +4226,14 @@ const withMind = (baseBoard) => {
4323
4226
  }
4324
4227
  dblclick(event);
4325
4228
  };
4326
- board.setFragment = (data, rectangle) => {
4327
- const targetMindElements = getSelectedMindElements(board);
4328
- const firstLevelElements = getFirstLevelElement(targetMindElements);
4329
- if (firstLevelElements.length) {
4330
- const elements = buildClipboardData(board, firstLevelElements, rectangle ? [rectangle.x, rectangle.y] : [0, 0]);
4331
- setMindClipboardData(data, elements);
4332
- }
4333
- setFragment(data, rectangle);
4334
- };
4335
- board.insertFragment = (data, targetPoint) => {
4336
- const elements = getDataFromClipboard(data);
4337
- const mindElements = elements.filter(value => MindElement.isMindElement(board, value));
4338
- if (elements.length > 0 && mindElements.length > 0) {
4339
- insertClipboardData(board, mindElements, targetPoint);
4340
- }
4341
- else if (elements.length === 0) {
4342
- const mindElements = getSelectedMindElements(board);
4343
- if (mindElements.length === 1) {
4344
- const text = getTextFromClipboard(data);
4345
- if (text) {
4346
- insertClipboardText(board, mindElements[0], buildText(text));
4347
- return;
4348
- }
4349
- }
4350
- }
4351
- insertFragment(data, targetPoint);
4352
- };
4353
- return withNodeResize(withNodeImageResize(withNodeImage(withNodeHoverDetect(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board)))))))));
4229
+ return withNodeResize(withNodeImageResize(withNodeImage(withNodeHoverDetect(withMindFragment(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board))))))))));
4354
4230
  };
4355
4231
 
4356
4232
  class MindEmojiBaseComponent {
4357
4233
  get nativeElement() {
4358
4234
  return this.elementRef.nativeElement;
4359
4235
  }
4360
- handleClick() {
4236
+ handlePointerDown() {
4361
4237
  const currentOptions = this.board.getPluginOptions(PlaitPluginKey.withSelection);
4362
4238
  this.board.setPluginOptions(PlaitPluginKey.withSelection, {
4363
4239
  isDisabledSelect: true
@@ -4373,10 +4249,10 @@ class MindEmojiBaseComponent {
4373
4249
  ngOnInit() {
4374
4250
  this.elementRef.nativeElement.style.fontSize = `${this.fontSize}px`;
4375
4251
  }
4252
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.3", ngImport: i0, type: MindEmojiBaseComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
4253
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.3", type: MindEmojiBaseComponent, inputs: { fontSize: "fontSize", emojiItem: "emojiItem", board: "board", element: "element" }, host: { listeners: { "pointerdown": "handlePointerDown()" }, classAttribute: "mind-node-emoji" }, ngImport: i0 }); }
4376
4254
  }
4377
- MindEmojiBaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindEmojiBaseComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
4378
- MindEmojiBaseComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: MindEmojiBaseComponent, inputs: { fontSize: "fontSize", emojiItem: "emojiItem", board: "board", element: "element" }, host: { listeners: { "mousedown": "handleClick()" }, classAttribute: "mind-node-emoji" }, ngImport: i0 });
4379
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindEmojiBaseComponent, decorators: [{
4255
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.3", ngImport: i0, type: MindEmojiBaseComponent, decorators: [{
4380
4256
  type: Directive,
4381
4257
  args: [{
4382
4258
  host: {
@@ -4391,71 +4267,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
4391
4267
  type: Input
4392
4268
  }], element: [{
4393
4269
  type: Input
4394
- }], handleClick: [{
4270
+ }], handlePointerDown: [{
4395
4271
  type: HostListener,
4396
- args: ['mousedown']
4397
- }] } });
4398
-
4399
- class MindImageBaseComponent {
4400
- set imageItem(value) {
4401
- this.afterImageItemChange(this._imageItem, value);
4402
- this._imageItem = value;
4403
- this.drawFocus();
4404
- }
4405
- get imageItem() {
4406
- return this._imageItem;
4407
- }
4408
- set isFocus(value) {
4409
- this._isFocus = value;
4410
- this.drawFocus();
4411
- }
4412
- get isFocus() {
4413
- return this._isFocus;
4414
- }
4415
- get nativeElement() {
4416
- return this.elementRef.nativeElement;
4417
- }
4418
- constructor(elementRef, cdr) {
4419
- this.elementRef = elementRef;
4420
- this.cdr = cdr;
4421
- this.initialized = false;
4422
- }
4423
- ngOnInit() {
4424
- this.activeGenerator = new ActiveGenerator(this.board, {
4425
- activeStrokeWidth: 1,
4426
- getRectangle: (element) => {
4427
- return getImageForeignRectangle(this.board, this.element);
4428
- },
4429
- getStrokeWidthByElement: () => {
4430
- return 0;
4431
- }
4432
- });
4433
- this.initialized = true;
4434
- }
4435
- drawFocus() {
4436
- if (this.initialized) {
4437
- const com = PlaitElement.getComponent(this.element);
4438
- this.activeGenerator.draw(this.element, com.g, { selected: this._isFocus });
4439
- }
4440
- }
4441
- }
4442
- MindImageBaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindImageBaseComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
4443
- MindImageBaseComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: MindImageBaseComponent, inputs: { imageItem: "imageItem", board: "board", element: "element", isFocus: "isFocus" }, host: { classAttribute: "mind-node-image" }, ngImport: i0 });
4444
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindImageBaseComponent, decorators: [{
4445
- type: Directive,
4446
- args: [{
4447
- host: {
4448
- class: 'mind-node-image'
4449
- }
4450
- }]
4451
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { imageItem: [{
4452
- type: Input
4453
- }], board: [{
4454
- type: Input
4455
- }], element: [{
4456
- type: Input
4457
- }], isFocus: [{
4458
- type: Input
4272
+ args: ['pointerdown']
4459
4273
  }] } });
4460
4274
 
4461
4275
  /*
@@ -4466,5 +4280,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
4466
4280
  * Generated bundle index. Do not edit.
4467
4281
  */
4468
4282
 
4469
- export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_FONT_FAMILY, BRANCH_WIDTH, BaseDrawer, BranchShape, DEFAULT_FONT_FAMILY, DefaultAbstractNodeStyle, DefaultNodeStyle, ELEMENT_TO_NODE, EXTEND_DIAMETER, EXTEND_OFFSET, GRAY_COLOR, INHERIT_ATTRIBUTE_KEYS, IS_DRAGGING, LayoutDirection, LayoutDirectionsMap, MindColorfulThemeColor, MindDarkThemeColor, MindDefaultThemeColor, MindElement, MindElementShape, MindEmojiBaseComponent, MindImageBaseComponent, MindModule, MindNode, MindNodeComponent, MindPointerType, MindQueries, MindRetroThemeColor, MindSoftThemeColor, MindStarryThemeColor, MindThemeColor, MindThemeColors, MindTransforms, NodeSpace, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_TOPIC_FONT_SIZE, ROOT_TOPIC_HEIGHT, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, TRANSPARENT, WithMindPluginKey, addActiveOnDragOrigin, addSelectedImageElement, adjustAbstractToNode, adjustNodeToRoot, adjustRootToNode, buildImage, canSetAbstract, copyNewNode, correctLayoutByDirection, createDefaultMind, createEmptyMind, createMindElement, deleteElementHandleAbstract, deleteElementsHandleRightNodeCount, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNode, editTopic, extractNodesText, findLastChild, findLocationLeftIndex, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchShapeByMindElement, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultLayout, getEmojiFontSize, getEmojiForeignRectangle, getEmojiRectangle, getEmojisWidthHeight, getFillByElement, getFirstLevelElement, getFontSizeBySlateElement, getHitAbstractHandle, getHitImageResizeHandleDirection, getImageForeignRectangle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutOptions, getLayoutReverseDirection, getLocationScope, getMindThemeColor, getNewNodeHeight, getNextBranchColor, getNodeDefaultFontSize, getOverallAbstracts, getPathByDropTarget, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getSelectedImageElement, getSelectedMindElements, getShapeByElement, getStrokeByMindElement, getStrokeWidthByElement, getTopicRectangleByElement, getTopicRectangleByNode, getValidAbstractRefs, handleTouchedAbstract, hasAfterDraw, hasPreviousOrNextOfDropPath, insertElementHandleAbstract, insertElementHandleRightNodeCount, insertMindElement, isChildElement, isChildOfAbstract, isChildRight, isChildUp, isCorrectLayout, isDragging, isDropStandardRight, isHitEmojis, isHitImage, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, isVirtualKey, removeActiveOnDragOrigin, removeSelectedImageElement, selectImage, separateChildren, setImageFocus, setIsDragging, temporaryDisableSelection, withMind, withMindExtend };
4283
+ export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_FONT_FAMILY, BRANCH_WIDTH, BaseDrawer, BranchShape, DEFAULT_FONT_FAMILY, DEFAULT_MIND_IMAGE_WIDTH, DefaultAbstractNodeStyle, DefaultNodeStyle, ELEMENT_TO_NODE, EXTEND_DIAMETER, EXTEND_OFFSET, GRAY_COLOR, INHERIT_ATTRIBUTE_KEYS, IS_DRAGGING, LayoutDirection, LayoutDirectionsMap, MindColorfulThemeColor, MindDarkThemeColor, MindDefaultThemeColor, MindElement, MindElementShape, MindEmojiBaseComponent, MindNode, MindNodeComponent, MindPointerType, MindQueries, MindRetroThemeColor, MindSoftThemeColor, MindStarryThemeColor, MindThemeColor, MindThemeColors, MindTransforms, NodeSpace, NodeTopicThreshold, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_TOPIC_FONT_SIZE, ROOT_TOPIC_HEIGHT, ROOT_TOPIC_WIDTH, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, TRANSPARENT, WithMindPluginKey, addActiveOnDragOrigin, addSelectedImageElement, adjustAbstractToNode, adjustNodeToRoot, adjustRootToNode, canSetAbstract, copyNewNode, correctLayoutByDirection, createDefaultMind, createEmptyMind, createMindElement, deleteElementHandleAbstract, deleteElementsHandleRightNodeCount, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNode, editTopic, extractNodesText, findLastChild, findLocationLeftIndex, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchShapeByMindElement, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultLayout, getEmojiFontSize, getEmojiForeignRectangle, getEmojiRectangle, getEmojisWidthHeight, getFillByElement, getFirstLevelElement, getFontSizeBySlateElement, getHitAbstractHandle, getHitImageResizeHandleDirection, getImageForeignRectangle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutOptions, getLayoutReverseDirection, getLocationScope, getMindThemeColor, getNewNodeHeight, getNextBranchColor, getNodeDefaultFontSize, getOverallAbstracts, getPathByDropTarget, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getSelectedImageElement, getSelectedMindElements, getShapeByElement, getStrokeByMindElement, getStrokeWidthByElement, getTopicRectangleByElement, getTopicRectangleByNode, getValidAbstractRefs, handleTouchedAbstract, hasAfterDraw, hasPreviousOrNextOfDropPath, insertElementHandleAbstract, insertElementHandleRightNodeCount, insertMindElement, isChildElement, isChildOfAbstract, isChildRight, isChildUp, isCorrectLayout, isDragging, isDropStandardRight, isHitEmojis, isHitImage, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, removeActiveOnDragOrigin, removeSelectedImageElement, separateChildren, setImageFocus, setIsDragging, temporaryDisableSelection, withMind, withMindExtend };
4470
4284
  //# sourceMappingURL=plait-mind.mjs.map