@plait/mind 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/base/image-base.component.d.ts +16 -0
  2. package/base/index.d.ts +1 -0
  3. package/constants/default.d.ts +1 -0
  4. package/drawer/node-image.drawer.d.ts +16 -0
  5. package/esm2020/base/image-base.component.mjs +28 -0
  6. package/esm2020/base/index.mjs +2 -1
  7. package/esm2020/constants/default.mjs +2 -1
  8. package/esm2020/drawer/node-image.drawer.mjs +61 -0
  9. package/esm2020/interfaces/element-data.mjs +1 -1
  10. package/esm2020/interfaces/element.mjs +9 -1
  11. package/esm2020/interfaces/options.mjs +1 -1
  12. package/esm2020/node.component.mjs +19 -5
  13. package/esm2020/plugins/with-abstract-resize.board.mjs +1 -1
  14. package/esm2020/plugins/with-mind-extend.mjs +3 -4
  15. package/esm2020/plugins/with-mind-hotkey.mjs +42 -32
  16. package/esm2020/plugins/with-mind-image.mjs +49 -0
  17. package/esm2020/plugins/with-mind.board.mjs +1 -1
  18. package/esm2020/plugins/with-mind.mjs +3 -2
  19. package/esm2020/plugins/with-node-dnd.mjs +13 -6
  20. package/esm2020/transforms/abstract-node.mjs +1 -3
  21. package/esm2020/transforms/emoji.mjs +2 -2
  22. package/esm2020/transforms/image.mjs +10 -0
  23. package/esm2020/transforms/index.mjs +4 -2
  24. package/esm2020/transforms/node.mjs +2 -6
  25. package/esm2020/utils/abstract/common.mjs +5 -1
  26. package/esm2020/utils/draw/node-dnd.mjs +8 -1
  27. package/esm2020/utils/mind.mjs +2 -2
  28. package/esm2020/utils/node-style/branch.mjs +6 -1
  29. package/esm2020/utils/node-style/shape.mjs +8 -1
  30. package/esm2020/utils/position/emoji.mjs +8 -8
  31. package/esm2020/utils/position/image.mjs +21 -0
  32. package/esm2020/utils/position/index.mjs +2 -1
  33. package/esm2020/utils/space/emoji.mjs +3 -2
  34. package/esm2020/utils/space/node-space.mjs +25 -6
  35. package/fesm2015/plait-mind.mjs +451 -227
  36. package/fesm2015/plait-mind.mjs.map +1 -1
  37. package/fesm2020/plait-mind.mjs +448 -227
  38. package/fesm2020/plait-mind.mjs.map +1 -1
  39. package/interfaces/element-data.d.ts +9 -0
  40. package/interfaces/element.d.ts +2 -1
  41. package/interfaces/options.d.ts +4 -1
  42. package/node.component.d.ts +3 -0
  43. package/package.json +1 -1
  44. package/plugins/with-abstract-resize.board.d.ts +2 -2
  45. package/plugins/with-mind-hotkey.d.ts +2 -0
  46. package/plugins/with-mind-image.d.ts +2 -0
  47. package/plugins/with-mind.board.d.ts +0 -2
  48. package/transforms/image.d.ts +3 -0
  49. package/transforms/index.d.ts +1 -0
  50. package/utils/abstract/common.d.ts +1 -0
  51. package/utils/position/emoji.d.ts +4 -4
  52. package/utils/position/image.d.ts +6 -0
  53. package/utils/position/index.d.ts +1 -0
  54. package/utils/space/node-space.d.ts +1 -0
@@ -1,9 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, ChangeDetectionStrategy, NgModule, NgZone, Directive, Input, HostListener } from '@angular/core';
2
+ import { Directive, Input, Component, ChangeDetectionStrategy, NgModule, NgZone, HostListener } from '@angular/core';
3
3
  import * as i2 from '@plait/core';
4
- import { DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, RectangleClient, PlaitElement, idCreator, isNullOrUndefined, Transforms, clearSelectedElement, addSelectedElement, PlaitBoard, depthFirstRecursion, Path, drawLinearPath, drawBezierPath, createG, updateForeignObject, PlaitNode, drawRoundRectangle, getRectangleByElements, getSelectedElements, NODE_TO_PARENT, distanceBetweenPointAndRectangle, createForeignObject, drawAbstractRoundRectangle, createText, PlaitPointerType, PlaitPluginElementComponent, NODE_TO_INDEX, PlaitModule, transformPoint, toPoint, getHitElements, distanceBetweenPointAndPoint, CLIP_BOARD_FORMAT_KEY, isMainPointer, BOARD_TO_HOST, PlaitPluginKey, throttleRAF, BoardTransforms, removeSelectedElement, PlaitHistoryBoard, hotkeys } from '@plait/core';
5
- import { MindLayoutType, isIndentedLayout, getNonAbstractChildren, isStandardLayout, AbstractNode, isLeftLayout, isRightLayout, isVerticalLogicLayout, isHorizontalLogicLayout, isTopLayout, isBottomLayout, isHorizontalLayout, getCorrectStartEnd, getAbstractLayout, ConnectingPosition, GlobalLayout } from '@plait/layouts';
6
- import { TEXT_DEFAULT_HEIGHT, buildText, getTextSize, TextManage, TextModule, getTextFromClipboard } from '@plait/text';
4
+ import { DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, RectangleClient, PlaitElement, idCreator, isNullOrUndefined, Transforms, clearSelectedElement, addSelectedElement, PlaitNode, Path, PlaitBoard, depthFirstRecursion, drawLinearPath, drawBezierPath, createG, updateForeignObject, drawRoundRectangle, getRectangleByElements, getSelectedElements, NODE_TO_PARENT, distanceBetweenPointAndRectangle, createForeignObject, drawAbstractRoundRectangle, createText, PlaitPointerType, PlaitPluginElementComponent, NODE_TO_INDEX, PlaitModule, transformPoint, toPoint, getHitElements, distanceBetweenPointAndPoint, CLIP_BOARD_FORMAT_KEY, isMainPointer, BOARD_TO_HOST, PlaitPluginKey, throttleRAF, BoardTransforms, removeSelectedElement, PlaitHistoryBoard, hotkeys } from '@plait/core';
5
+ import { MindLayoutType, isIndentedLayout, AbstractNode, getNonAbstractChildren, isStandardLayout, isLeftLayout, isRightLayout, isVerticalLogicLayout, isHorizontalLogicLayout, isTopLayout, isBottomLayout, isHorizontalLayout, getCorrectStartEnd, getAbstractLayout, ConnectingPosition, GlobalLayout } from '@plait/layouts';
6
+ import { TEXT_DEFAULT_HEIGHT, buildText, getTextSize, TextManage, ExitOrigin, TextModule, getTextFromClipboard } from '@plait/text';
7
7
  import { fromEvent, Subject } from 'rxjs';
8
8
  import { Node, Path as Path$1 } from 'slate';
9
9
  import { isKeyHotkey } from 'is-hotkey';
@@ -149,6 +149,7 @@ const MindThemeColor = {
149
149
  }
150
150
  };
151
151
 
152
+ const WithMindPluginKey = 'plait-mind-plugin-key';
152
153
  const BASE = 4;
153
154
  const PRIMARY_COLOR = '#6698FF';
154
155
  const TRANSPARENT = 'transparent';
@@ -162,7 +163,7 @@ const QUICK_INSERT_CIRCLE_COLOR = '#6698FF';
162
163
  const QUICK_INSERT_INNER_CROSS_COLOR = 'white';
163
164
 
164
165
  function getEmojisWidthHeight(board, element) {
165
- const options = board.getMindOptions();
166
+ const options = board.getPluginOptions(WithMindPluginKey);
166
167
  const count = element.data.emojis.length;
167
168
  const fontSize = getEmojiFontSize(element);
168
169
  return {
@@ -185,7 +186,9 @@ const NodeDefaultSpace = {
185
186
  emojiAndText: BASE * 1.5
186
187
  },
187
188
  vertical: {
188
- nodeAndText: BASE * 1.5
189
+ nodeAndText: BASE * 1.5,
190
+ nodeAndImage: BASE,
191
+ imageAndText: BASE * 1.5
189
192
  }
190
193
  };
191
194
  const RootDefaultSpace = {
@@ -214,18 +217,27 @@ const getSpaceEmojiAndText = (element) => {
214
217
  };
215
218
  const NodeSpace = {
216
219
  getNodeWidth(board, element) {
220
+ var _a;
217
221
  const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
222
+ const imageWidth = MindElement.hasImage(element) ? (_a = element.data.image) === null || _a === void 0 ? void 0 : _a.width : 0;
218
223
  if (MindElement.hasEmojis(element)) {
219
224
  return (NodeSpace.getEmojiLeftSpace(board, element) +
220
225
  getEmojisWidthHeight(board, element).width +
221
226
  getSpaceEmojiAndText(element) +
222
- element.width +
227
+ Math.max(element.width, imageWidth) +
223
228
  nodeAndText);
224
229
  }
225
- return nodeAndText + element.width + nodeAndText;
230
+ return nodeAndText + Math.max(element.width, imageWidth) + nodeAndText;
226
231
  },
227
232
  getNodeHeight(board, element) {
228
233
  const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
234
+ if (MindElement.hasImage(element)) {
235
+ return (NodeDefaultSpace.vertical.nodeAndImage +
236
+ element.data.image.height +
237
+ NodeDefaultSpace.vertical.imageAndText +
238
+ element.height +
239
+ nodeAndText);
240
+ }
229
241
  return nodeAndText + element.height + nodeAndText;
230
242
  },
231
243
  getTextLeftSpace(board, element) {
@@ -239,10 +251,18 @@ const NodeSpace = {
239
251
  },
240
252
  getTextTopSpace(element) {
241
253
  const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
242
- return nodeAndText;
254
+ if (MindElement.hasImage(element)) {
255
+ return element.data.image.height + NodeDefaultSpace.vertical.nodeAndImage + NodeDefaultSpace.vertical.imageAndText;
256
+ }
257
+ else {
258
+ return nodeAndText;
259
+ }
260
+ },
261
+ getImageTopSpace(element) {
262
+ return NodeDefaultSpace.vertical.nodeAndImage;
243
263
  },
244
264
  getEmojiLeftSpace(board, element) {
245
- const options = board.getMindOptions();
265
+ const options = board.getPluginOptions(WithMindPluginKey);
246
266
  const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
247
267
  return nodeAndText - options.emojiPadding;
248
268
  },
@@ -266,12 +286,12 @@ function getEmojiRectangle(board, element) {
266
286
  function getEmojiForeignRectangle(board, element) {
267
287
  let { x, y } = getRectangleByNode(MindElement.getNode(element));
268
288
  x = x + NodeSpace.getEmojiLeftSpace(board, element);
269
- const { width, height } = getEmojisWidthHeight(board, element);
289
+ const { width } = getEmojisWidthHeight(board, element);
270
290
  return {
271
291
  x,
272
292
  y,
273
293
  width,
274
- height: height + NodeSpace.getEmojiTopSpace(element) * 2
294
+ height: NodeSpace.getNodeHeight(board, element)
275
295
  };
276
296
  }
277
297
  const isHitEmojis = (board, element, point) => {
@@ -293,6 +313,23 @@ function getTopicRectangleByElement(board, nodeRectangle, element) {
293
313
  return { height, width, x, y };
294
314
  }
295
315
 
316
+ function getImageForeignRectangle(board, element) {
317
+ let { x, y } = getRectangleByNode(MindElement.getNode(element));
318
+ x = x + NodeSpace.getTextLeftSpace(board, element);
319
+ y = NodeSpace.getImageTopSpace(element) + y;
320
+ const { width, height } = element.data.image;
321
+ return {
322
+ x,
323
+ y,
324
+ width,
325
+ height
326
+ };
327
+ }
328
+ const isHitImage = (board, element, range) => {
329
+ const client = getImageForeignRectangle(board, element);
330
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([range.anchor, range.focus]), client);
331
+ };
332
+
296
333
  const NODE_MIN_WIDTH = 18;
297
334
 
298
335
  function editTopic(element) {
@@ -402,7 +439,7 @@ const copyNewNode = (node) => {
402
439
  const extractNodesText = (node) => {
403
440
  let str = '';
404
441
  if (node) {
405
- str += Node.string(node.data.topic.children[0]) + ' ';
442
+ str += Node.string(node.data.topic) + ' ';
406
443
  for (const childNode of node.children) {
407
444
  str += extractNodesText(childNode);
408
445
  }
@@ -604,10 +641,180 @@ const getAvailableProperty = (board, element, propertyKey) => {
604
641
  return element[propertyKey];
605
642
  };
606
643
 
644
+ const separateChildren = (parentElement) => {
645
+ const rightNodeCount = parentElement.rightNodeCount;
646
+ const children = parentElement.children;
647
+ let rightChildren = [], leftChildren = [];
648
+ for (let i = 0; i < children.length; i++) {
649
+ const child = children[i];
650
+ if (AbstractNode.isAbstract(child) && child.end < rightNodeCount) {
651
+ rightChildren.push(child);
652
+ continue;
653
+ }
654
+ if (AbstractNode.isAbstract(child) && child.start >= rightNodeCount) {
655
+ leftChildren.push(child);
656
+ continue;
657
+ }
658
+ if (i < rightNodeCount) {
659
+ rightChildren.push(child);
660
+ }
661
+ else {
662
+ leftChildren.push(child);
663
+ }
664
+ }
665
+ return { leftChildren, rightChildren };
666
+ };
667
+ const isSetAbstract = (element) => {
668
+ return !!getCorrespondingAbstract(element);
669
+ };
670
+ const canSetAbstract = (element) => {
671
+ return !PlaitElement.isRootElement(element) && !AbstractNode.isAbstract(element) && !isSetAbstract(element);
672
+ };
673
+ const getCorrespondingAbstract = (element) => {
674
+ const parent = MindElement.findParent(element);
675
+ if (!parent)
676
+ return undefined;
677
+ const elementIndex = parent.children.indexOf(element);
678
+ return parent.children.find(child => {
679
+ return AbstractNode.isAbstract(child) && elementIndex >= child.start && elementIndex <= child.end;
680
+ });
681
+ };
682
+ const getBehindAbstracts = (element) => {
683
+ const parent = MindElement.findParent(element);
684
+ if (!parent)
685
+ return [];
686
+ const index = parent.children.indexOf(element);
687
+ return parent.children.filter(child => AbstractNode.isAbstract(child) && child.start > index);
688
+ };
689
+ /**
690
+ * return corresponding abstract that is not child of elements
691
+ */
692
+ const getOverallAbstracts = (board, elements) => {
693
+ const overallAbstracts = [];
694
+ elements
695
+ .filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
696
+ .forEach(value => {
697
+ const abstract = getCorrespondingAbstract(value);
698
+ if (abstract && elements.indexOf(abstract) === -1 && overallAbstracts.indexOf(abstract) === -1) {
699
+ const { start, end } = abstract;
700
+ const parent = MindElement.getParent(value);
701
+ const isOverall = parent.children.slice(start, end + 1).every(includedElement => elements.indexOf(includedElement) > -1);
702
+ if (isOverall) {
703
+ overallAbstracts.push(abstract);
704
+ }
705
+ }
706
+ });
707
+ return overallAbstracts;
708
+ };
709
+ /**
710
+ * abstract node is valid when elements contains at least one element it is referenced with
711
+ */
712
+ const getValidAbstractRefs = (board, elements) => {
713
+ const validAbstractRefs = [];
714
+ elements
715
+ .filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
716
+ .forEach(value => {
717
+ const abstract = getCorrespondingAbstract(value);
718
+ if (abstract && elements.indexOf(abstract) > 0) {
719
+ const index = validAbstractRefs.findIndex(value => value.abstract === abstract);
720
+ if (index === -1) {
721
+ validAbstractRefs.push({
722
+ abstract: abstract,
723
+ references: [value]
724
+ });
725
+ }
726
+ else {
727
+ validAbstractRefs[index].references.push(value);
728
+ }
729
+ }
730
+ });
731
+ return validAbstractRefs;
732
+ };
733
+ function getRelativeStartEndByAbstractRef(abstractRef, elements) {
734
+ const start = elements.indexOf(abstractRef.references[0]);
735
+ const end = elements.indexOf(abstractRef.references[abstractRef.references.length - 1]);
736
+ return { start, end };
737
+ }
738
+ const insertElementHandleAbstract = (board, path, step = 1,
739
+ //由此区分拖拽和新增到概要概括最后一个节点
740
+ isExtendPreviousNode = true, effectedAbstracts = new Map()) => {
741
+ const parent = PlaitNode.parent(board, path);
742
+ const hasPreviousNode = path[path.length - 1] !== 0;
743
+ let behindAbstracts;
744
+ if (!hasPreviousNode) {
745
+ behindAbstracts = parent.children.filter(child => AbstractNode.isAbstract(child));
746
+ }
747
+ else {
748
+ const selectedElement = PlaitNode.get(board, Path.previous(path));
749
+ behindAbstracts = getBehindAbstracts(selectedElement);
750
+ }
751
+ if (behindAbstracts.length) {
752
+ behindAbstracts.forEach(abstract => {
753
+ let newProperties = effectedAbstracts.get(abstract);
754
+ if (!newProperties) {
755
+ newProperties = { start: 0, end: 0 };
756
+ effectedAbstracts.set(abstract, newProperties);
757
+ }
758
+ newProperties.start = newProperties.start + step;
759
+ newProperties.end = newProperties.end + step;
760
+ });
761
+ }
762
+ if (!hasPreviousNode) {
763
+ return effectedAbstracts;
764
+ }
765
+ const selectedElement = PlaitNode.get(board, Path.previous(path));
766
+ const correspondingAbstract = getCorrespondingAbstract(selectedElement);
767
+ const isDragToLast = !isExtendPreviousNode && correspondingAbstract && correspondingAbstract.end === path[path.length - 1] - 1;
768
+ if (correspondingAbstract && !isDragToLast) {
769
+ let newProperties = effectedAbstracts.get(correspondingAbstract);
770
+ if (!newProperties) {
771
+ newProperties = { start: 0, end: 0 };
772
+ effectedAbstracts.set(correspondingAbstract, newProperties);
773
+ }
774
+ newProperties.end = newProperties.end + step;
775
+ }
776
+ return effectedAbstracts;
777
+ };
778
+ const deleteElementHandleAbstract = (board, deletableElements, effectedAbstracts = new Map()) => {
779
+ deletableElements.forEach(node => {
780
+ if (!PlaitMind.isMind(node)) {
781
+ const behindAbstracts = getBehindAbstracts(node).filter(abstract => !deletableElements.includes(abstract));
782
+ if (behindAbstracts.length) {
783
+ behindAbstracts.forEach(abstract => {
784
+ let newProperties = effectedAbstracts.get(abstract);
785
+ if (!newProperties) {
786
+ newProperties = { start: 0, end: 0 };
787
+ effectedAbstracts.set(abstract, newProperties);
788
+ }
789
+ newProperties.start = newProperties.start - 1;
790
+ newProperties.end = newProperties.end - 1;
791
+ });
792
+ }
793
+ const correspondingAbstract = getCorrespondingAbstract(node);
794
+ if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
795
+ let newProperties = effectedAbstracts.get(correspondingAbstract);
796
+ if (!newProperties) {
797
+ newProperties = { start: 0, end: 0 };
798
+ effectedAbstracts.set(correspondingAbstract, newProperties);
799
+ }
800
+ newProperties.end = newProperties.end - 1;
801
+ }
802
+ }
803
+ });
804
+ return effectedAbstracts;
805
+ };
806
+ const isChildOfAbstract = (board, element) => {
807
+ const ancestors = MindElement.getAncestors(board, element);
808
+ return !!ancestors.find((value) => AbstractNode.isAbstract(value));
809
+ };
810
+
607
811
  /**
608
812
  * Processing of branch color, width, style, etc. of the mind node
609
813
  */
610
814
  const getBranchColorByMindElement = (board, element) => {
815
+ if (AbstractNode.isAbstract(element) || isChildOfAbstract(board, element)) {
816
+ return getAbstractBranchColor(board, element);
817
+ }
611
818
  const branchColor = getAvailableProperty(board, element, 'branchColor');
612
819
  return branchColor || getDefaultBranchColor(board, element);
613
820
  };
@@ -661,6 +868,10 @@ const getStrokeByMindElement = (board, element) => {
661
868
  const defaultRootStroke = getMindThemeColor(board).rootFill;
662
869
  return element.strokeColor || defaultRootStroke;
663
870
  }
871
+ if (AbstractNode.isAbstract(element) || isChildOfAbstract(board, element)) {
872
+ return element.strokeColor || DefaultAbstractNodeStyle.strokeColor;
873
+ ;
874
+ }
664
875
  return getAvailableProperty(board, element, 'strokeColor') || getDefaultBranchColor(board, element);
665
876
  };
666
877
  const getShapeByElement = (board, element) => {
@@ -1181,6 +1392,12 @@ const drawFakeDragNode = (board, element, offsetX, offsetY) => {
1181
1392
  updateForeignObject(fakeEmojisG, foreignRectangle.width, foreignRectangle.height, foreignRectangle.x + offsetX, foreignRectangle.y + offsetY);
1182
1393
  dragFakeNodeG === null || dragFakeNodeG === void 0 ? void 0 : dragFakeNodeG.append(fakeEmojisG);
1183
1394
  }
1395
+ if (MindElement.hasImage(element)) {
1396
+ const fakeImageG = activeComponent.imageDrawer.g.cloneNode(true);
1397
+ const foreignRectangle = getImageForeignRectangle(board, element);
1398
+ updateForeignObject(fakeImageG, foreignRectangle.width, foreignRectangle.height, foreignRectangle.x + offsetX, foreignRectangle.y + offsetY);
1399
+ dragFakeNodeG === null || dragFakeNodeG === void 0 ? void 0 : dragFakeNodeG.append(fakeImageG);
1400
+ }
1184
1401
  return dragFakeNodeG;
1185
1402
  };
1186
1403
  const drawFakeDropNode = (board, dropTarget, path) => {
@@ -1292,169 +1509,6 @@ const drawFakeDropNode = (board, dropTarget, path) => {
1292
1509
  return fakeDropNodeG;
1293
1510
  };
1294
1511
 
1295
- const separateChildren = (parentElement) => {
1296
- const rightNodeCount = parentElement.rightNodeCount;
1297
- const children = parentElement.children;
1298
- let rightChildren = [], leftChildren = [];
1299
- for (let i = 0; i < children.length; i++) {
1300
- const child = children[i];
1301
- if (AbstractNode.isAbstract(child) && child.end < rightNodeCount) {
1302
- rightChildren.push(child);
1303
- continue;
1304
- }
1305
- if (AbstractNode.isAbstract(child) && child.start >= rightNodeCount) {
1306
- leftChildren.push(child);
1307
- continue;
1308
- }
1309
- if (i < rightNodeCount) {
1310
- rightChildren.push(child);
1311
- }
1312
- else {
1313
- leftChildren.push(child);
1314
- }
1315
- }
1316
- return { leftChildren, rightChildren };
1317
- };
1318
- const isSetAbstract = (element) => {
1319
- return !!getCorrespondingAbstract(element);
1320
- };
1321
- const canSetAbstract = (element) => {
1322
- return !PlaitElement.isRootElement(element) && !AbstractNode.isAbstract(element) && !isSetAbstract(element);
1323
- };
1324
- const getCorrespondingAbstract = (element) => {
1325
- const parent = MindElement.findParent(element);
1326
- if (!parent)
1327
- return undefined;
1328
- const elementIndex = parent.children.indexOf(element);
1329
- return parent.children.find(child => {
1330
- return AbstractNode.isAbstract(child) && elementIndex >= child.start && elementIndex <= child.end;
1331
- });
1332
- };
1333
- const getBehindAbstracts = (element) => {
1334
- const parent = MindElement.findParent(element);
1335
- if (!parent)
1336
- return [];
1337
- const index = parent.children.indexOf(element);
1338
- return parent.children.filter(child => AbstractNode.isAbstract(child) && child.start > index);
1339
- };
1340
- /**
1341
- * return corresponding abstract that is not child of elements
1342
- */
1343
- const getOverallAbstracts = (board, elements) => {
1344
- const overallAbstracts = [];
1345
- elements
1346
- .filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
1347
- .forEach(value => {
1348
- const abstract = getCorrespondingAbstract(value);
1349
- if (abstract && elements.indexOf(abstract) === -1 && overallAbstracts.indexOf(abstract) === -1) {
1350
- const { start, end } = abstract;
1351
- const parent = MindElement.getParent(value);
1352
- const isOverall = parent.children.slice(start, end + 1).every(includedElement => elements.indexOf(includedElement) > -1);
1353
- if (isOverall) {
1354
- overallAbstracts.push(abstract);
1355
- }
1356
- }
1357
- });
1358
- return overallAbstracts;
1359
- };
1360
- /**
1361
- * abstract node is valid when elements contains at least one element it is referenced with
1362
- */
1363
- const getValidAbstractRefs = (board, elements) => {
1364
- const validAbstractRefs = [];
1365
- elements
1366
- .filter(value => !AbstractNode.isAbstract(value) && !PlaitMind.isMind(value))
1367
- .forEach(value => {
1368
- const abstract = getCorrespondingAbstract(value);
1369
- if (abstract && elements.indexOf(abstract) > 0) {
1370
- const index = validAbstractRefs.findIndex(value => value.abstract === abstract);
1371
- if (index === -1) {
1372
- validAbstractRefs.push({
1373
- abstract: abstract,
1374
- references: [value]
1375
- });
1376
- }
1377
- else {
1378
- validAbstractRefs[index].references.push(value);
1379
- }
1380
- }
1381
- });
1382
- return validAbstractRefs;
1383
- };
1384
- function getRelativeStartEndByAbstractRef(abstractRef, elements) {
1385
- const start = elements.indexOf(abstractRef.references[0]);
1386
- const end = elements.indexOf(abstractRef.references[abstractRef.references.length - 1]);
1387
- return { start, end };
1388
- }
1389
- const insertElementHandleAbstract = (board, path, step = 1,
1390
- //由此区分拖拽和新增到概要概括最后一个节点
1391
- isExtendPreviousNode = true, effectedAbstracts = new Map()) => {
1392
- const parent = PlaitNode.parent(board, path);
1393
- const hasPreviousNode = path[path.length - 1] !== 0;
1394
- let behindAbstracts;
1395
- if (!hasPreviousNode) {
1396
- behindAbstracts = parent.children.filter(child => AbstractNode.isAbstract(child));
1397
- }
1398
- else {
1399
- const selectedElement = PlaitNode.get(board, Path.previous(path));
1400
- behindAbstracts = getBehindAbstracts(selectedElement);
1401
- }
1402
- if (behindAbstracts.length) {
1403
- behindAbstracts.forEach(abstract => {
1404
- let newProperties = effectedAbstracts.get(abstract);
1405
- if (!newProperties) {
1406
- newProperties = { start: 0, end: 0 };
1407
- effectedAbstracts.set(abstract, newProperties);
1408
- }
1409
- newProperties.start = newProperties.start + step;
1410
- newProperties.end = newProperties.end + step;
1411
- });
1412
- }
1413
- if (!hasPreviousNode) {
1414
- return effectedAbstracts;
1415
- }
1416
- const selectedElement = PlaitNode.get(board, Path.previous(path));
1417
- const correspondingAbstract = getCorrespondingAbstract(selectedElement);
1418
- const isDragToLast = !isExtendPreviousNode && correspondingAbstract && correspondingAbstract.end === path[path.length - 1] - 1;
1419
- if (correspondingAbstract && !isDragToLast) {
1420
- let newProperties = effectedAbstracts.get(correspondingAbstract);
1421
- if (!newProperties) {
1422
- newProperties = { start: 0, end: 0 };
1423
- effectedAbstracts.set(correspondingAbstract, newProperties);
1424
- }
1425
- newProperties.end = newProperties.end + step;
1426
- }
1427
- return effectedAbstracts;
1428
- };
1429
- const deleteElementHandleAbstract = (board, deletableElements, effectedAbstracts = new Map()) => {
1430
- deletableElements.forEach(node => {
1431
- if (!PlaitMind.isMind(node)) {
1432
- const behindAbstracts = getBehindAbstracts(node).filter(abstract => !deletableElements.includes(abstract));
1433
- if (behindAbstracts.length) {
1434
- behindAbstracts.forEach(abstract => {
1435
- let newProperties = effectedAbstracts.get(abstract);
1436
- if (!newProperties) {
1437
- newProperties = { start: 0, end: 0 };
1438
- effectedAbstracts.set(abstract, newProperties);
1439
- }
1440
- newProperties.start = newProperties.start - 1;
1441
- newProperties.end = newProperties.end - 1;
1442
- });
1443
- }
1444
- const correspondingAbstract = getCorrespondingAbstract(node);
1445
- if (correspondingAbstract && !deletableElements.includes(correspondingAbstract)) {
1446
- let newProperties = effectedAbstracts.get(correspondingAbstract);
1447
- if (!newProperties) {
1448
- newProperties = { start: 0, end: 0 };
1449
- effectedAbstracts.set(correspondingAbstract, newProperties);
1450
- }
1451
- newProperties.end = newProperties.end - 1;
1452
- }
1453
- }
1454
- });
1455
- return effectedAbstracts;
1456
- };
1457
-
1458
1512
  var AbstractHandlePosition;
1459
1513
  (function (AbstractHandlePosition) {
1460
1514
  AbstractHandlePosition["start"] = "start";
@@ -1855,6 +1909,14 @@ const MindElement = {
1855
1909
  return false;
1856
1910
  }
1857
1911
  },
1912
+ hasImage(element) {
1913
+ if (element.data.image) {
1914
+ return true;
1915
+ }
1916
+ else {
1917
+ return false;
1918
+ }
1919
+ },
1858
1920
  getEmojis(element) {
1859
1921
  return element.data.emojis;
1860
1922
  },
@@ -2099,9 +2161,7 @@ const setAbstractByElements = (board, groupParent, group) => {
2099
2161
  };
2100
2162
  const insertAbstractNode = (board, path, start, end) => {
2101
2163
  const mindElement = createMindElement('概要', 28, 20, {
2102
- strokeColor: DefaultAbstractNodeStyle.strokeColor,
2103
2164
  strokeWidth: DefaultAbstractNodeStyle.branchWidth,
2104
- branchColor: DefaultAbstractNodeStyle.branchColor,
2105
2165
  branchWidth: DefaultAbstractNodeStyle.branchWidth
2106
2166
  });
2107
2167
  mindElement.start = start;
@@ -2142,10 +2202,7 @@ const normalizeWidthAndHeight = (board, width, height) => {
2142
2202
  return { width: newWidth, height: newHeight };
2143
2203
  };
2144
2204
  const setTopic = (board, element, topic, width, height) => {
2145
- const newElement = Object.assign({ data: { topic } }, normalizeWidthAndHeight(board, width, height));
2146
- if (MindElement.hasEmojis(element)) {
2147
- newElement.data.emojis = element.data.emojis;
2148
- }
2205
+ const newElement = Object.assign({ data: Object.assign(Object.assign({}, element.data), { topic }) }, normalizeWidthAndHeight(board, width, height));
2149
2206
  const path = PlaitBoard.findPath(board, element);
2150
2207
  Transforms.setNode(board, newElement, path);
2151
2208
  };
@@ -2219,7 +2276,7 @@ const removeEmoji = (board, element, emojiItem) => {
2219
2276
  };
2220
2277
  const replaceEmoji = (board, element, oldEmoji, newEmoji) => {
2221
2278
  const newElement = {
2222
- data: { topic: element.data.topic }
2279
+ data: Object.assign({}, element.data)
2223
2280
  };
2224
2281
  const newEmojis = element.data.emojis.map(value => {
2225
2282
  if (value === oldEmoji) {
@@ -2232,6 +2289,15 @@ const replaceEmoji = (board, element, oldEmoji, newEmoji) => {
2232
2289
  Transforms.setNode(board, newElement, path);
2233
2290
  };
2234
2291
 
2292
+ const removeImage = (board, element) => {
2293
+ const newElement = {
2294
+ data: Object.assign({}, element.data)
2295
+ };
2296
+ delete newElement.data.image;
2297
+ const path = PlaitBoard.findPath(board, element);
2298
+ Transforms.setNode(board, newElement, path);
2299
+ };
2300
+
2235
2301
  const MindTransforms = {
2236
2302
  setLayout,
2237
2303
  setTopic,
@@ -2245,7 +2311,8 @@ const MindTransforms = {
2245
2311
  removeElements,
2246
2312
  insertNodes,
2247
2313
  insertAbstractNodes,
2248
- setRightNodeCountByRefs
2314
+ setRightNodeCountByRefs,
2315
+ removeImage
2249
2316
  };
2250
2317
 
2251
2318
  class BaseDrawer {
@@ -2564,6 +2631,90 @@ class CollapseDrawer extends BaseDrawer {
2564
2631
  }
2565
2632
  }
2566
2633
 
2634
+ class MindImageBaseComponent {
2635
+ get nativeElement() {
2636
+ return this.elementRef.nativeElement;
2637
+ }
2638
+ constructor(elementRef) {
2639
+ this.elementRef = elementRef;
2640
+ }
2641
+ ngOnInit() { }
2642
+ }
2643
+ MindImageBaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindImageBaseComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
2644
+ MindImageBaseComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.5", type: MindImageBaseComponent, inputs: { imageItem: "imageItem", board: "board", element: "element" }, host: { classAttribute: "mind-node-image" }, ngImport: i0 });
2645
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindImageBaseComponent, decorators: [{
2646
+ type: Directive,
2647
+ args: [{
2648
+ host: {
2649
+ class: 'mind-node-image'
2650
+ }
2651
+ }]
2652
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { imageItem: [{
2653
+ type: Input
2654
+ }], board: [{
2655
+ type: Input
2656
+ }], element: [{
2657
+ type: Input
2658
+ }] } });
2659
+
2660
+ class NodeImageDrawer {
2661
+ constructor(board, viewContainerRef) {
2662
+ this.board = board;
2663
+ this.viewContainerRef = viewContainerRef;
2664
+ this.componentRef = null;
2665
+ }
2666
+ drawImage(element) {
2667
+ this.destroy();
2668
+ if (MindElement.hasImage(element)) {
2669
+ this.g = createG();
2670
+ const foreignRectangle = getImageForeignRectangle(this.board, element);
2671
+ const foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
2672
+ this.g.append(foreignObject);
2673
+ if (this.componentRef) {
2674
+ this.componentRef.destroy();
2675
+ this.componentRef = null;
2676
+ }
2677
+ const componentType = this.board.getPluginOptions(WithMindPluginKey).imageComponentType || MindImageBaseComponent;
2678
+ if (!componentType) {
2679
+ throw new Error('Not implement drawEmoji method error.');
2680
+ }
2681
+ this.componentRef = this.viewContainerRef.createComponent(componentType);
2682
+ this.componentRef.instance.board = this.board;
2683
+ this.componentRef.instance.element = element;
2684
+ this.componentRef.instance.imageItem = element.data.image;
2685
+ foreignObject.append(this.componentRef.instance.nativeElement);
2686
+ return this.g;
2687
+ }
2688
+ return undefined;
2689
+ }
2690
+ drawActive(element) {
2691
+ var _a;
2692
+ this.destroyActive();
2693
+ const imageRectangle = getImageForeignRectangle(this.board, element);
2694
+ const rectangle = RectangleClient.getOutlineRectangle(imageRectangle, -1);
2695
+ const roughSVG = PlaitBoard.getRoughSVG(this.board);
2696
+ this.activeG = roughSVG.rectangle(rectangle.x, rectangle.y, rectangle.width, rectangle.height, {
2697
+ stroke: PRIMARY_COLOR,
2698
+ fill: '',
2699
+ fillStyle: 'solid'
2700
+ });
2701
+ (_a = this.g) === null || _a === void 0 ? void 0 : _a.append(this.activeG);
2702
+ }
2703
+ destroyActive() {
2704
+ var _a;
2705
+ (_a = this.activeG) === null || _a === void 0 ? void 0 : _a.remove();
2706
+ }
2707
+ destroy() {
2708
+ if (this.g) {
2709
+ this.g.remove();
2710
+ }
2711
+ if (this.componentRef) {
2712
+ this.componentRef.destroy();
2713
+ this.componentRef = null;
2714
+ }
2715
+ }
2716
+ }
2717
+
2567
2718
  // 1. When the text at the end has an italic attribute, the text is partially covered
2568
2719
  // 2. There will be some differences in the width measured by different browsers
2569
2720
  const WIDTH_BUFFER = 4;
@@ -2583,7 +2734,8 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2583
2734
  this.nodeInsertDrawer = new NodeInsertDrawer(this.board);
2584
2735
  this.activeDrawer = new NodeActiveDrawer(this.board);
2585
2736
  this.collapseDrawer = new CollapseDrawer(this.board);
2586
- const plugins = this.board.getMindOptions().textPlugins;
2737
+ this.imageDrawer = new NodeImageDrawer(this.board, this.viewContainerRef);
2738
+ const plugins = this.board.getPluginOptions(WithMindPluginKey).textPlugins;
2587
2739
  this.textManage = new TextManage(this.board, this.viewContainerRef, () => {
2588
2740
  const rect = getTopicRectangleByNode(this.board, this.node);
2589
2741
  return rect;
@@ -2613,14 +2765,17 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2613
2765
  this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: this.textManage.isEditing });
2614
2766
  this.drawEmojis();
2615
2767
  this.drawExtend();
2768
+ this.drawImage();
2616
2769
  if (PlaitMind.isMind(this.context.parent)) {
2617
2770
  this.g.classList.add('branch');
2618
2771
  }
2619
2772
  }
2620
2773
  editTopic() {
2621
2774
  this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: true });
2622
- this.textManage.edit(() => {
2623
- this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: false });
2775
+ this.textManage.edit((origin) => {
2776
+ if (origin === ExitOrigin.default) {
2777
+ this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: false });
2778
+ }
2624
2779
  });
2625
2780
  }
2626
2781
  onContextChanged(value, previous) {
@@ -2633,6 +2788,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2633
2788
  this.drawShape();
2634
2789
  this.drawLink();
2635
2790
  this.drawEmojis();
2791
+ this.drawImage();
2636
2792
  this.drawExtend();
2637
2793
  this.textManage.updateText(this.element.data.topic);
2638
2794
  this.textManage.updateRectangle();
@@ -2654,6 +2810,12 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2654
2810
  this.g.append(g);
2655
2811
  }
2656
2812
  }
2813
+ drawImage() {
2814
+ const image = this.imageDrawer.drawImage(this.element);
2815
+ if (image) {
2816
+ this.g.append(image);
2817
+ }
2818
+ }
2657
2819
  drawShape() {
2658
2820
  this.destroyShape();
2659
2821
  const shape = getShapeByElement(this.board, this.node.origin);
@@ -2722,6 +2884,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2722
2884
  super.ngOnDestroy();
2723
2885
  this.textManage.destroy();
2724
2886
  this.nodeEmojisDrawer.destroy();
2887
+ this.imageDrawer.destroy();
2725
2888
  this.destroy$.next();
2726
2889
  this.destroy$.complete();
2727
2890
  if (ELEMENT_TO_NODE.get(this.element) === this.node) {
@@ -2909,12 +3072,11 @@ const withNodeDnd = (board) => {
2909
3072
  !AbstractNode.isAbstract(targetElement)) {
2910
3073
  const targetElements = selectedElements.filter(element => MindElement.isMindElement(board, element) && !element.isRoot && !AbstractNode.isAbstract(element));
2911
3074
  const isMultiple = selectedElements.length > 0 && selectedElements.includes(targetElement);
2912
- const isSingle = !isMultiple && selectedElements.length === 0;
2913
3075
  if (isMultiple) {
2914
3076
  activeElements = targetElements;
2915
3077
  startPoint = point;
2916
3078
  }
2917
- else if (isSingle) {
3079
+ else {
2918
3080
  activeElements = [targetElement];
2919
3081
  startPoint = point;
2920
3082
  }
@@ -2968,6 +3130,7 @@ const withNodeDnd = (board) => {
2968
3130
  }
2969
3131
  if (dropTarget) {
2970
3132
  const targetPathRef = board.pathRef(targetPath);
3133
+ const targetPreviousPathRef = Path.hasPrevious(targetPath) && board.pathRef(Path.previous(targetPath));
2971
3134
  const targetElementPathRef = board.pathRef(PlaitBoard.findPath(board, dropTarget.target));
2972
3135
  let abstractRefs = getValidAbstractRefs(board, firstLevelElements);
2973
3136
  const normalElements = firstLevelElements
@@ -3005,9 +3168,16 @@ const withNodeDnd = (board) => {
3005
3168
  let insertPath = targetPathRef.current;
3006
3169
  const parentPath = Path.parent(targetPathRef.current || targetPath);
3007
3170
  if (!insertPath) {
3008
- const parent = PlaitNode.get(board, parentPath);
3009
- const children = getNonAbstractChildren(parent);
3010
- insertPath = [...parentPath, children.length || 0];
3171
+ //当插入位置和选中节点位置相同时,使用记录的 previousPath
3172
+ const previousPath = targetPreviousPathRef && targetPreviousPathRef.unref();
3173
+ if (previousPath) {
3174
+ insertPath = Path.next(previousPath);
3175
+ }
3176
+ else {
3177
+ const parent = PlaitNode.get(board, parentPath);
3178
+ const children = getNonAbstractChildren(parent);
3179
+ insertPath = [...parentPath, children.length || 0];
3180
+ }
3011
3181
  }
3012
3182
  MindTransforms.insertNodes(board, normalElements, insertPath);
3013
3183
  if (abstractRefs.length) {
@@ -3257,9 +3427,7 @@ const withMindExtend = (board) => {
3257
3427
  newBoard.drawEmoji = (emoji, element) => {
3258
3428
  throw new Error('Not implement drawEmoji method error.');
3259
3429
  };
3260
- newBoard.getMindOptions = () => {
3261
- return { spaceBetweenEmojis: 4, emojiPadding: 0 };
3262
- };
3430
+ board.setPluginOptions(WithMindPluginKey, { spaceBetweenEmojis: 4, emojiPadding: 0 });
3263
3431
  return newBoard;
3264
3432
  };
3265
3433
 
@@ -3408,38 +3576,18 @@ const withMindHotkey = (board) => {
3408
3576
  event.preventDefault();
3409
3577
  const targetMindElements = selectedElements.filter(el => MindElement.isMindElement(board, el));
3410
3578
  const firstLevelElements = getFirstLevelElement(targetMindElements);
3411
- const deletableElements = firstLevelElements.reverse();
3412
- const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
3413
- MindTransforms.setAbstractsByRefs(board, abstractRefs);
3414
- const refs = deleteElementsHandleRightNodeCount(board, targetMindElements);
3415
- MindTransforms.setRightNodeCountByRefs(board, refs);
3416
- MindTransforms.removeElements(board, targetMindElements);
3417
- let activeElement;
3418
- if (AbstractNode.isAbstract(firstLevelElements[0])) {
3419
- const parent = MindElement.getParent(firstLevelElements[0]);
3420
- activeElement = parent.children[firstLevelElements[0].start];
3421
- }
3422
- const firstElement = firstLevelElements[0];
3423
- const firstElementParent = MindElement.findParent(firstElement);
3424
- const hasSameParent = firstLevelElements.every(element => {
3425
- return MindElement.findParent(element) === firstElementParent;
3426
- });
3427
- if (firstElementParent && hasSameParent && !activeElement) {
3428
- const firstElementIndex = firstElementParent.children.indexOf(firstElement);
3429
- const childrenCount = firstElementParent.children.length;
3430
- // active parent element
3431
- if (childrenCount === firstLevelElements.length) {
3432
- activeElement = firstElementParent;
3433
- }
3434
- else {
3435
- if (firstElementIndex > 0) {
3436
- activeElement = firstElementParent.children[firstElementIndex - 1];
3437
- }
3579
+ if (firstLevelElements.length > 0) {
3580
+ const deletableElements = [...firstLevelElements].reverse();
3581
+ const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
3582
+ MindTransforms.setAbstractsByRefs(board, abstractRefs);
3583
+ const refs = deleteElementsHandleRightNodeCount(board, targetMindElements);
3584
+ MindTransforms.setRightNodeCountByRefs(board, refs);
3585
+ MindTransforms.removeElements(board, targetMindElements);
3586
+ const nextSelected = getNextSelectedElement(board, firstLevelElements);
3587
+ if (nextSelected) {
3588
+ addSelectedElement(board, nextSelected);
3438
3589
  }
3439
3590
  }
3440
- if (activeElement) {
3441
- addSelectedElement(board, activeElement);
3442
- }
3443
3591
  return;
3444
3592
  }
3445
3593
  if (!isVirtualKey(event) && !isSpaceHotkey(event) && isSingleSelection) {
@@ -3452,6 +3600,36 @@ const withMindHotkey = (board) => {
3452
3600
  };
3453
3601
  return board;
3454
3602
  };
3603
+ const getNextSelectedElement = (board, firstLevelElements) => {
3604
+ let activeElement;
3605
+ const firstLevelElement = firstLevelElements[0];
3606
+ const firstLevelElementPath = PlaitBoard.findPath(board, firstLevelElement);
3607
+ let nextSelectedPath = firstLevelElementPath;
3608
+ if (Path.hasPrevious(firstLevelElementPath)) {
3609
+ nextSelectedPath = Path.previous(firstLevelElementPath);
3610
+ }
3611
+ if (AbstractNode.isAbstract(firstLevelElement)) {
3612
+ const parent = MindElement.getParent(firstLevelElement);
3613
+ if (!firstLevelElements.includes(parent.children[firstLevelElement.start])) {
3614
+ activeElement = parent.children[firstLevelElement.start];
3615
+ }
3616
+ }
3617
+ try {
3618
+ if (!activeElement) {
3619
+ activeElement = PlaitNode.get(board, nextSelectedPath);
3620
+ }
3621
+ }
3622
+ catch (error) { }
3623
+ const firstElement = firstLevelElements[0];
3624
+ const firstElementParent = MindElement.findParent(firstElement);
3625
+ const hasSameParent = firstLevelElements.every(element => {
3626
+ return MindElement.findParent(element) === firstElementParent;
3627
+ });
3628
+ if (firstElementParent && hasSameParent && !activeElement) {
3629
+ activeElement = firstElementParent;
3630
+ }
3631
+ return activeElement;
3632
+ };
3455
3633
  const isExpandHotkey = (event) => {
3456
3634
  return isKeyHotkey('mod+/', event);
3457
3635
  };
@@ -3527,6 +3705,52 @@ const removeHovered = (element) => {
3527
3705
  }
3528
3706
  };
3529
3707
 
3708
+ const withMindImage = (board) => {
3709
+ let selectedImageElement = null;
3710
+ const { keydown, mousedown } = board;
3711
+ board.mousedown = (event) => {
3712
+ if (PlaitBoard.isReadonly(board) || !isMainPointer(event) || !PlaitBoard.isPointer(board, PlaitPointerType.selection)) {
3713
+ mousedown(event);
3714
+ return;
3715
+ }
3716
+ const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3717
+ const range = { anchor: point, focus: point };
3718
+ const hitElements = getHitElements(board, { ranges: [range] });
3719
+ const hasImage = hitElements.length && MindElement.hasImage(hitElements[0]);
3720
+ const hitImage = hasImage && isHitImage(board, hitElements[0], range);
3721
+ if (hitImage) {
3722
+ const currentOptions = board.getPluginOptions(PlaitPluginKey.withSelection);
3723
+ board.setPluginOptions(PlaitPluginKey.withSelection, {
3724
+ isDisabledSelect: true
3725
+ });
3726
+ setTimeout(() => {
3727
+ board.setPluginOptions(PlaitPluginKey.withSelection, Object.assign({}, currentOptions));
3728
+ }, 0);
3729
+ selectedImageElement = hitElements[0];
3730
+ const component = PlaitElement.getComponent(selectedImageElement);
3731
+ component.imageDrawer.drawActive(selectedImageElement);
3732
+ clearSelectedElement(board);
3733
+ }
3734
+ else {
3735
+ if (selectedImageElement) {
3736
+ const component = PlaitElement.getComponent(selectedImageElement);
3737
+ component && component.imageDrawer.destroyActive();
3738
+ }
3739
+ selectedImageElement = null;
3740
+ }
3741
+ mousedown(event);
3742
+ };
3743
+ board.keydown = (event) => {
3744
+ if (!PlaitBoard.isReadonly(board) && selectedImageElement && (hotkeys.isDeleteBackward(event) || hotkeys.isDeleteForward(event))) {
3745
+ MindTransforms.removeImage(board, selectedImageElement);
3746
+ selectedImageElement = null;
3747
+ return;
3748
+ }
3749
+ keydown(event);
3750
+ };
3751
+ return board;
3752
+ };
3753
+
3530
3754
  const withMind = (board) => {
3531
3755
  const { drawElement, dblclick, keydown, insertFragment, setFragment, deleteFragment, isHitSelection, getRectangle, isMovable, isRecursion } = board;
3532
3756
  board.drawElement = (context) => {
@@ -3644,7 +3868,7 @@ const withMind = (board) => {
3644
3868
  MindTransforms.removeElements(board, selectedElements);
3645
3869
  deleteFragment(data);
3646
3870
  };
3647
- return withNodeHover(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board))))));
3871
+ return withMindImage(withNodeHover(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board)))))));
3648
3872
  };
3649
3873
 
3650
3874
  class MindEmojiBaseComponent {
@@ -3698,5 +3922,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
3698
3922
  * Generated bundle index. Do not edit.
3699
3923
  */
3700
3924
 
3701
- 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, MindModule, MindNode, MindNodeComponent, MindPointerType, MindQueries, MindRetroThemeColor, MindSoftThemeColor, MindStarryThemeColor, MindThemeColor, MindThemeColors, MindTransforms, NODE_MIN_WIDTH, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_TOPIC_FONT_SIZE, ROOT_TOPIC_HEIGHT, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, TRANSPARENT, addActiveOnDragOrigin, adjustAbstractToNode, adjustNodeToRoot, adjustRootToNode, canSetAbstract, copyNewNode, correctLayoutByDirection, createDefaultMind, createEmptyMind, createMindElement, deleteElementHandleAbstract, deleteElementsHandleRightNodeCount, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNode, editTopic, extractNodesText, findLastChild, findLocationLeftIndex, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchShapeByMindElement, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultLayout, getEmojiForeignRectangle, getEmojiRectangle, getFirstLevelElement, getHitAbstractHandle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection, getLocationScope, getMindThemeColor, getNextBranchColor, getOverallAbstracts, getPathByDropTarget, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getShapeByElement, getStrokeByMindElement, getTopicRectangleByElement, getTopicRectangleByNode, getValidAbstractRefs, handleTouchedAbstract, hasAfterDraw, hasPreviousOrNextOfDropPath, insertElementHandleAbstract, insertElementHandleRightNodeCount, insertMindElement, isChildElement, isChildRight, isChildUp, isCorrectLayout, isDragging, isDropStandardRight, isHitEmojis, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, isVirtualKey, removeActiveOnDragOrigin, separateChildren, setIsDragging, withMind, withMindExtend };
3925
+ 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, NODE_MIN_WIDTH, 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, 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, getEmojiForeignRectangle, getEmojiRectangle, getFirstLevelElement, getHitAbstractHandle, getImageForeignRectangle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection, getLocationScope, getMindThemeColor, getNextBranchColor, getOverallAbstracts, getPathByDropTarget, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getShapeByElement, getStrokeByMindElement, 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, separateChildren, setIsDragging, withMind, withMindExtend };
3702
3926
  //# sourceMappingURL=plait-mind.mjs.map