@plait/mind 0.23.0 → 0.24.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 (36) hide show
  1. package/base/image-base.component.d.ts +6 -4
  2. package/constants/image.d.ts +3 -0
  3. package/drawer/node-image.drawer.d.ts +1 -0
  4. package/esm2020/base/image-base.component.mjs +8 -2
  5. package/esm2020/constants/image.mjs +4 -0
  6. package/esm2020/drawer/node-image.drawer.mjs +9 -6
  7. package/esm2020/interfaces/element-data.mjs +1 -1
  8. package/esm2020/node.component.mjs +24 -17
  9. package/esm2020/plugins/with-node-image.mjs +20 -6
  10. package/esm2020/plugins/with-node-resize.mjs +3 -3
  11. package/esm2020/transforms/emoji.mjs +6 -2
  12. package/esm2020/transforms/image.mjs +22 -1
  13. package/esm2020/transforms/index.mjs +4 -3
  14. package/esm2020/utils/clipboard.mjs +5 -2
  15. package/esm2020/utils/index.mjs +3 -1
  16. package/esm2020/utils/node/adjust-node.mjs +3 -2
  17. package/esm2020/utils/node/dynamic-width.mjs +19 -0
  18. package/esm2020/utils/node/image.mjs +42 -2
  19. package/esm2020/utils/node/index.mjs +2 -1
  20. package/esm2020/utils/position/topic.mjs +2 -2
  21. package/esm2020/utils/space/index.mjs +4 -0
  22. package/esm2020/utils/space/node-space.mjs +15 -4
  23. package/fesm2015/plait-mind.mjs +522 -397
  24. package/fesm2015/plait-mind.mjs.map +1 -1
  25. package/fesm2020/plait-mind.mjs +526 -399
  26. package/fesm2020/plait-mind.mjs.map +1 -1
  27. package/node.component.d.ts +3 -2
  28. package/package.json +1 -1
  29. package/transforms/image.d.ts +2 -1
  30. package/transforms/index.d.ts +1 -0
  31. package/utils/index.d.ts +2 -0
  32. package/utils/node/dynamic-width.d.ts +7 -0
  33. package/utils/node/image.d.ts +2 -0
  34. package/utils/node/index.d.ts +1 -0
  35. package/utils/space/index.d.ts +3 -0
  36. package/utils/space/node-space.d.ts +9 -1
@@ -1,11 +1,12 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Directive, Input, Component, ChangeDetectionStrategy, NgModule, NgZone, HostListener } from '@angular/core';
2
+ import { Component, ChangeDetectionStrategy, NgModule, NgZone, Directive, Input, HostListener } from '@angular/core';
3
3
  import * as i2 from '@plait/core';
4
- import { DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, RectangleClient, PlaitElement, PlaitPluginKey, idCreator, isNullOrUndefined, Transforms, clearSelectedElement, addSelectedElement, PlaitNode, Path, PlaitBoard, depthFirstRecursion, getIsRecursionFunc, drawLinearPath, drawBezierPath, createG, updateForeignObject, drawRoundRectangle, getRectangleByElements, getSelectedElements, NODE_TO_PARENT, distanceBetweenPointAndRectangle, createForeignObject, createText, PlaitPointerType, PlaitPluginElementComponent, NODE_TO_INDEX, PlaitModule, isMainPointer, transformPoint, toPoint, getHitElements, distanceBetweenPointAndPoint, CLIP_BOARD_FORMAT_KEY, BOARD_TO_HOST, throttleRAF, BoardTransforms, removeSelectedElement, PlaitHistoryBoard, hotkeys, PRESS_AND_MOVE_BUFFER, MERGING, ResizeCursorClass } from '@plait/core';
5
- import { MindLayoutType, isIndentedLayout, AbstractNode, getNonAbstractChildren, isStandardLayout, isLeftLayout, isRightLayout, isVerticalLogicLayout, isHorizontalLogicLayout, isTopLayout, isBottomLayout, isHorizontalLayout, getCorrectStartEnd, getAbstractLayout, ConnectingPosition, GlobalLayout } from '@plait/layouts';
4
+ import { DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, RectangleClient, PlaitElement, PlaitPluginKey, idCreator, isNullOrUndefined, Transforms, clearSelectedElement, addSelectedElement, PlaitBoard, Path, PlaitNode, PlaitContextService, depthFirstRecursion, getIsRecursionFunc, drawLinearPath, drawBezierPath, createG, updateForeignObject, drawRoundRectangle, getRectangleByElements, getSelectedElements, NODE_TO_PARENT, distanceBetweenPointAndRectangle, createForeignObject, createText, PlaitPointerType, PlaitPluginElementComponent, NODE_TO_INDEX, PlaitModule, isMainPointer, transformPoint, toPoint, getHitElements, distanceBetweenPointAndPoint, CLIP_BOARD_FORMAT_KEY, BOARD_TO_HOST, throttleRAF, BoardTransforms, removeSelectedElement, PlaitHistoryBoard, hotkeys, PRESS_AND_MOVE_BUFFER, MERGING, ResizeCursorClass } 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
6
  import { PlaitMarkEditor, MarkTypes, DEFAULT_FONT_SIZE, TEXT_DEFAULT_HEIGHT, buildText, getTextSize, TextManage, ExitOrigin, TextModule, getTextFromClipboard } from '@plait/text';
7
7
  import { fromEvent, Subject } from 'rxjs';
8
8
  import { Node as Node$1, Path as Path$1 } from 'slate';
9
+ import { __awaiter } from 'tslib';
9
10
  import { isKeyHotkey } from 'is-hotkey';
10
11
  import { pointsOnBezierCurves } from 'points-on-curve';
11
12
  import { take, filter } from 'rxjs/operators';
@@ -232,10 +233,10 @@ const NodeSpace = {
232
233
  return (NodeSpace.getEmojiLeftSpace(board, element) +
233
234
  getEmojisWidthHeight(board, element).width +
234
235
  getSpaceEmojiAndText(element) +
235
- NodeSpace.getNodeResizableWidth(board, element) +
236
+ NodeSpace.getNodeDynamicWidth(board, element) +
236
237
  nodeAndText);
237
238
  }
238
- return nodeAndText + NodeSpace.getNodeResizableWidth(board, element) + nodeAndText;
239
+ return nodeAndText + NodeSpace.getNodeDynamicWidth(board, element) + nodeAndText;
239
240
  },
240
241
  getNodeHeight(board, element) {
241
242
  const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
@@ -244,12 +245,23 @@ const NodeSpace = {
244
245
  }
245
246
  return nodeAndText + element.height + nodeAndText;
246
247
  },
247
- getNodeResizableWidth(board, element) {
248
+ getNodeDynamicWidth(board, element) {
248
249
  var _a;
249
250
  const width = element.manualWidth || element.width;
250
251
  const imageWidth = MindElement.hasImage(element) ? (_a = element.data.image) === null || _a === void 0 ? void 0 : _a.width : 0;
251
252
  return Math.max(width, imageWidth);
252
253
  },
254
+ /**
255
+ * use this when upload image first or resize image
256
+ * @param board
257
+ * @param element
258
+ * @param imageWidth
259
+ * @returns
260
+ */
261
+ getNodeNewDynamicWidth(board, element, imageWidth) {
262
+ const width = element.manualWidth || element.width;
263
+ return Math.max(width, imageWidth);
264
+ },
253
265
  getNodeResizableMinWidth(board, element) {
254
266
  const minTopicWidth = NodeSpace.getNodeTopicMinWidth(board, element);
255
267
  if (MindElement.hasImage(element) && element.data.image.width > minTopicWidth) {
@@ -349,7 +361,7 @@ function getTopicRectangleByNode(board, node) {
349
361
  function getTopicRectangleByElement(board, nodeRectangle, element) {
350
362
  const x = nodeRectangle.x + NodeSpace.getTextLeftSpace(board, element);
351
363
  const y = nodeRectangle.y + NodeSpace.getTextTopSpace(board, element);
352
- const width = NodeSpace.getNodeResizableWidth(board, element);
364
+ const width = NodeSpace.getNodeDynamicWidth(board, element);
353
365
  const height = Math.ceil(element.height);
354
366
  return { height, width, x, y };
355
367
  }
@@ -663,35 +675,14 @@ const adjustNodeToRoot = (board, node) => {
663
675
  newElement === null || newElement === void 0 ? true : delete newElement.isCollapsed;
664
676
  const { width, height } = getTextSize(board, newElement.data.topic, TOPIC_DEFAULT_MAX_WORD_COUNT, {
665
677
  fontSize: ROOT_TOPIC_FONT_SIZE,
666
- fontFamily: BRANCH_FONT_FAMILY
678
+ fontFamily: BRANCH_FONT_FAMILY,
679
+ width: node.manualWidth ? node.manualWidth : undefined
667
680
  });
668
681
  newElement.width = Math.max(width, getNodeDefaultFontSize(true));
669
682
  newElement.height = height;
670
683
  return Object.assign(Object.assign({}, newElement), { layout: (_a = newElement.layout) !== null && _a !== void 0 ? _a : MindLayoutType.right, isRoot: true, type: 'mindmap' });
671
684
  };
672
685
 
673
- const BOARD_TO_SELECTED_IMAGE_ELEMENT = new WeakMap();
674
- const getSelectedImageElement = (board) => {
675
- return BOARD_TO_SELECTED_IMAGE_ELEMENT.get(board);
676
- };
677
- const addSelectedImageElement = (board, element) => {
678
- BOARD_TO_SELECTED_IMAGE_ELEMENT.set(board, element);
679
- };
680
- const removeSelectedImageElement = (board) => {
681
- BOARD_TO_SELECTED_IMAGE_ELEMENT.delete(board);
682
- };
683
- const setImageFocus = (board, element, isFocus) => {
684
- if (isFocus) {
685
- addSelectedImageElement(board, element);
686
- }
687
- else {
688
- removeSelectedImageElement(board);
689
- }
690
- const elementComponent = PlaitElement.getComponent(element);
691
- elementComponent.imageDrawer.componentRef.instance.isFocus = isFocus;
692
- elementComponent.imageDrawer.componentRef.instance.cdr.markForCheck();
693
- };
694
-
695
686
  const DefaultAbstractNodeStyle = {
696
687
  branch: { color: GRAY_COLOR, width: 2 },
697
688
  shape: {
@@ -710,8 +701,94 @@ const DefaultNodeStyle = {
710
701
  }
711
702
  };
712
703
 
713
- const getAvailableProperty = (board, element, propertyKey) => {
714
- return element[propertyKey];
704
+ const setAbstractsByRefs = (board, abstractRefs) => {
705
+ abstractRefs.forEach((newProperty, element) => {
706
+ const start = element.start + newProperty.start;
707
+ const end = element.end + newProperty.end;
708
+ const path = PlaitBoard.findPath(board, element);
709
+ if (start > end) {
710
+ Transforms.removeNode(board, path);
711
+ }
712
+ else {
713
+ Transforms.setNode(board, { start, end }, path);
714
+ }
715
+ });
716
+ };
717
+ const setAbstractByStandardLayout = (board, element) => {
718
+ const rightNodeCount = element.rightNodeCount;
719
+ const abstract = element.children.find(child => {
720
+ return AbstractNode.isAbstract(child) && child.end >= rightNodeCount && child.start < rightNodeCount;
721
+ });
722
+ if (abstract) {
723
+ const path = PlaitBoard.findPath(board, abstract);
724
+ Transforms.setNode(board, { end: rightNodeCount - 1 }, path);
725
+ }
726
+ };
727
+ const insertAbstract = (board, elements) => {
728
+ let elementGroup = getFirstLevelElement(elements);
729
+ const { parentElements, abstractIncludedGroups } = divideElementByParent(elementGroup);
730
+ abstractIncludedGroups.forEach((group, index) => {
731
+ const groupParent = parentElements[index];
732
+ setAbstractByElements(board, groupParent, group);
733
+ });
734
+ };
735
+ const setAbstractByElements = (board, groupParent, group) => {
736
+ const indexArray = group.map(child => groupParent.children.indexOf(child)).sort((a, b) => a - b);
737
+ const rightNodeCount = groupParent === null || groupParent === void 0 ? void 0 : groupParent.rightNodeCount;
738
+ const start = indexArray[0], end = indexArray[indexArray.length - 1];
739
+ if (isStandardLayout(MindQueries.getLayoutByElement(groupParent)) &&
740
+ rightNodeCount &&
741
+ start < rightNodeCount &&
742
+ end >= rightNodeCount) {
743
+ const childrenLength = groupParent.children.length;
744
+ const path = [...PlaitBoard.findPath(board, groupParent), childrenLength];
745
+ const leftChildren = indexArray.filter(index => index >= rightNodeCount);
746
+ const rightChildren = indexArray.filter(index => index < rightNodeCount);
747
+ insertAbstractNode(board, path, rightChildren[0], rightChildren[rightChildren.length - 1]);
748
+ insertAbstractNode(board, Path.next(path), leftChildren[0], leftChildren[leftChildren.length - 1]);
749
+ }
750
+ else {
751
+ const path = [...PlaitBoard.findPath(board, groupParent), groupParent.children.length];
752
+ insertAbstractNode(board, path, start, end);
753
+ }
754
+ };
755
+ const insertAbstractNode = (board, path, start, end) => {
756
+ const mindElement = createMindElement('概要', 28, 20, {
757
+ strokeWidth: DefaultAbstractNodeStyle.branch.width,
758
+ branchWidth: DefaultAbstractNodeStyle.branch.width
759
+ });
760
+ mindElement.start = start;
761
+ mindElement.end = end;
762
+ Transforms.insertNode(board, mindElement, path);
763
+ clearSelectedElement(board);
764
+ addSelectedElement(board, mindElement);
765
+ };
766
+
767
+ const setLayout = (board, layout, path) => {
768
+ correctLogicLayoutNode(board, layout, path);
769
+ const element = PlaitNode.get(board, path);
770
+ if (PlaitMind.isMind(element) && isStandardLayout(layout)) {
771
+ MindTransforms.setAbstractByStandardLayout(board, element);
772
+ }
773
+ Transforms.setNode(board, { layout }, path);
774
+ };
775
+ const correctLogicLayoutNode = (board, layout, path) => {
776
+ var _a;
777
+ const node = PlaitNode.get(board, path);
778
+ if (node && layout) {
779
+ (_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach((value, index) => {
780
+ var _a;
781
+ if (value.layout) {
782
+ if ((isHorizontalLogicLayout(layout) && isVerticalLogicLayout(value.layout)) ||
783
+ (isVerticalLogicLayout(layout) && isHorizontalLogicLayout(value.layout))) {
784
+ Transforms.setNode(board, { layout: null }, [...path, index]);
785
+ }
786
+ if ((_a = value.children) === null || _a === void 0 ? void 0 : _a.length) {
787
+ correctLogicLayoutNode(board, layout, [...path, index]);
788
+ }
789
+ }
790
+ });
791
+ }
715
792
  };
716
793
 
717
794
  const separateChildren = (parentElement) => {
@@ -876,9 +953,249 @@ const deleteElementHandleAbstract = (board, deletableElements, effectedAbstracts
876
953
  });
877
954
  return effectedAbstracts;
878
955
  };
879
- const isChildOfAbstract = (board, element) => {
880
- const ancestors = MindElement.getAncestors(board, element);
881
- return !!ancestors.find((value) => AbstractNode.isAbstract(value));
956
+ const isChildOfAbstract = (board, element) => {
957
+ const ancestors = MindElement.getAncestors(board, element);
958
+ return !!ancestors.find((value) => AbstractNode.isAbstract(value));
959
+ };
960
+
961
+ const normalizeWidthAndHeight = (board, element, width, height) => {
962
+ const minWidth = NodeSpace.getNodeTopicMinWidth(board, element, element.isRoot);
963
+ const newWidth = width < minWidth * board.viewport.zoom ? minWidth : width / board.viewport.zoom;
964
+ const newHeight = height / board.viewport.zoom;
965
+ return { width: newWidth, height: newHeight };
966
+ };
967
+ const setTopic = (board, element, topic, width, height) => {
968
+ const newElement = Object.assign({ data: Object.assign(Object.assign({}, element.data), { topic }) }, normalizeWidthAndHeight(board, element, width, height));
969
+ const path = PlaitBoard.findPath(board, element);
970
+ Transforms.setNode(board, newElement, path);
971
+ };
972
+ const setNodeManualWidth = (board, element, width, height) => {
973
+ const path = PlaitBoard.findPath(board, element);
974
+ const { width: normalizedWidth, height: normalizedHeight } = normalizeWidthAndHeight(board, element, width, height);
975
+ const newElement = { manualWidth: normalizedWidth, height: normalizedHeight };
976
+ Transforms.setNode(board, newElement, path);
977
+ };
978
+ const setTopicSize = (board, element, width, height) => {
979
+ const newElement = Object.assign({}, normalizeWidthAndHeight(board, element, width, height));
980
+ let isEqualWidth = Math.ceil(element.width) === Math.ceil(newElement.width);
981
+ let isEqualHeight = Math.ceil(element.height) === Math.ceil(newElement.height);
982
+ if (element.manualWidth) {
983
+ isEqualWidth = true;
984
+ }
985
+ if (!isEqualWidth || !isEqualHeight) {
986
+ const path = PlaitBoard.findPath(board, element);
987
+ Transforms.setNode(board, newElement, path);
988
+ }
989
+ };
990
+ const removeElements = (board, elements) => {
991
+ const deletableElements = getFirstLevelElement(elements);
992
+ deletableElements
993
+ .map(element => {
994
+ const path = PlaitBoard.findPath(board, element);
995
+ const ref = board.pathRef(path);
996
+ return () => {
997
+ Transforms.removeNode(board, ref.current);
998
+ ref.unref();
999
+ };
1000
+ })
1001
+ .forEach(action => {
1002
+ action();
1003
+ });
1004
+ };
1005
+ const insertNodes = (board, elements, path) => {
1006
+ const pathRef = board.pathRef(path);
1007
+ elements.forEach(element => {
1008
+ if (pathRef.current) {
1009
+ Transforms.insertNode(board, element, pathRef.current);
1010
+ }
1011
+ });
1012
+ pathRef.unref();
1013
+ };
1014
+ const insertAbstractNodes = (board, validAbstractRefs, elements, path) => {
1015
+ var _a;
1016
+ const parent = PlaitNode.get(board, Path$1.parent(path));
1017
+ const abstractPath = [...Path$1.parent(path), (_a = parent.children) === null || _a === void 0 ? void 0 : _a.length];
1018
+ const abstracts = validAbstractRefs.map(refs => {
1019
+ const { start, end } = getRelativeStartEndByAbstractRef(refs, elements);
1020
+ return Object.assign(Object.assign({}, refs.abstract), { start: start + path[path.length - 1], end: end + path[path.length - 1] });
1021
+ });
1022
+ insertNodes(board, abstracts, abstractPath);
1023
+ };
1024
+ const setRightNodeCountByRefs = (board, refs) => {
1025
+ refs.forEach(ref => {
1026
+ Transforms.setNode(board, { rightNodeCount: ref.rightNodeCount }, ref.path);
1027
+ });
1028
+ };
1029
+
1030
+ const addEmoji = (board, element, emojiItem) => {
1031
+ const emojis = element.data.emojis || [];
1032
+ const newEmojis = [...emojis];
1033
+ newEmojis.push(emojiItem);
1034
+ const newElement = {
1035
+ data: Object.assign(Object.assign({}, element.data), { emojis: newEmojis })
1036
+ };
1037
+ const path = PlaitBoard.findPath(board, element);
1038
+ Transforms.setNode(board, newElement, path);
1039
+ };
1040
+ const removeEmoji = (board, element, emojiItem) => {
1041
+ const emojis = element.data.emojis.filter(value => value !== emojiItem);
1042
+ const newElement = {
1043
+ data: { topic: element.data.topic }
1044
+ };
1045
+ if (MindElement.hasImage(element)) {
1046
+ newElement.data.image = element.data.image;
1047
+ }
1048
+ if (emojis.length > 0) {
1049
+ newElement.data.emojis = emojis;
1050
+ }
1051
+ const path = PlaitBoard.findPath(board, element);
1052
+ Transforms.setNode(board, newElement, path);
1053
+ };
1054
+ const replaceEmoji = (board, element, oldEmoji, newEmoji) => {
1055
+ const newElement = {
1056
+ data: Object.assign({}, element.data)
1057
+ };
1058
+ const newEmojis = element.data.emojis.map(value => {
1059
+ if (value === oldEmoji) {
1060
+ return newEmoji;
1061
+ }
1062
+ return value;
1063
+ });
1064
+ newElement.data.emojis = newEmojis;
1065
+ const path = PlaitBoard.findPath(board, element);
1066
+ Transforms.setNode(board, newElement, path);
1067
+ };
1068
+
1069
+ /**
1070
+ * 1. return new node height if height changed
1071
+ * 2. new height is effected by zoom
1072
+ */
1073
+ const getNewNodeHeight = (board, element, newNodeDynamicWidth) => {
1074
+ const textManage = PlaitElement.getComponent(element).textManage;
1075
+ const { height } = textManage.getSize();
1076
+ textManage.updateWidth(newNodeDynamicWidth);
1077
+ const { height: newHeight } = textManage.getSize();
1078
+ if (!element.manualWidth) {
1079
+ textManage.updateWidth(0);
1080
+ }
1081
+ if (height !== newHeight) {
1082
+ return newHeight;
1083
+ }
1084
+ return undefined;
1085
+ };
1086
+
1087
+ const removeImage = (board, element) => {
1088
+ setImageFocus(board, element, false);
1089
+ const newElement = {
1090
+ data: Object.assign({}, element.data)
1091
+ };
1092
+ delete newElement.data.image;
1093
+ const path = PlaitBoard.findPath(board, element);
1094
+ const newDynamicWidth = NodeSpace.getNodeNewDynamicWidth(board, element, 0);
1095
+ const newHeight = getNewNodeHeight(board, element, newDynamicWidth);
1096
+ if (newHeight) {
1097
+ newElement.height = newHeight / board.viewport.zoom;
1098
+ }
1099
+ Transforms.setNode(board, newElement, path);
1100
+ };
1101
+ const setImage = (board, element, imageItem) => {
1102
+ const newElement = {
1103
+ data: Object.assign(Object.assign({}, element.data), { image: imageItem })
1104
+ };
1105
+ const newDynamicWidth = NodeSpace.getNodeNewDynamicWidth(board, element, imageItem.width);
1106
+ const newHeight = getNewNodeHeight(board, element, newDynamicWidth);
1107
+ if (newHeight) {
1108
+ newElement.height = newHeight / board.viewport.zoom;
1109
+ }
1110
+ const path = PlaitBoard.findPath(board, element);
1111
+ Transforms.setNode(board, newElement, path);
1112
+ };
1113
+
1114
+ const MindTransforms = {
1115
+ setLayout,
1116
+ setTopic,
1117
+ setTopicSize,
1118
+ setNodeManualWidth,
1119
+ addEmoji,
1120
+ removeEmoji,
1121
+ replaceEmoji,
1122
+ insertAbstract,
1123
+ setAbstractsByRefs,
1124
+ setAbstractByStandardLayout,
1125
+ removeElements,
1126
+ insertNodes,
1127
+ insertAbstractNodes,
1128
+ setRightNodeCountByRefs,
1129
+ removeImage,
1130
+ setImage
1131
+ };
1132
+
1133
+ const PICTURE_ACCEPTED_UPLOAD_SIZE = 20;
1134
+ const acceptImageTypes = ['png', 'jpeg', 'gif', 'bmp'];
1135
+ const DEFAULT_IMAGE_WIDTH = 240;
1136
+
1137
+ const BOARD_TO_SELECTED_IMAGE_ELEMENT = new WeakMap();
1138
+ const getSelectedImageElement = (board) => {
1139
+ return BOARD_TO_SELECTED_IMAGE_ELEMENT.get(board);
1140
+ };
1141
+ const addSelectedImageElement = (board, element) => {
1142
+ BOARD_TO_SELECTED_IMAGE_ELEMENT.set(board, element);
1143
+ };
1144
+ const removeSelectedImageElement = (board) => {
1145
+ BOARD_TO_SELECTED_IMAGE_ELEMENT.delete(board);
1146
+ };
1147
+ const setImageFocus = (board, element, isFocus) => {
1148
+ if (isFocus) {
1149
+ addSelectedImageElement(board, element);
1150
+ }
1151
+ else {
1152
+ removeSelectedImageElement(board);
1153
+ }
1154
+ const elementComponent = PlaitElement.getComponent(element);
1155
+ elementComponent.imageDrawer.componentRef.instance.isFocus = isFocus;
1156
+ elementComponent.imageDrawer.componentRef.instance.cdr.markForCheck();
1157
+ };
1158
+ const selectImage = (board, element, acceptImageTypes = ['png', 'jpeg', 'gif', 'bmp']) => {
1159
+ const inputFile = document.createElement('input');
1160
+ inputFile.setAttribute('type', 'file');
1161
+ const acceptImageTypesString = '.' + acceptImageTypes.join(',.');
1162
+ inputFile.setAttribute('accept', acceptImageTypesString);
1163
+ inputFile.onchange = (event) => {
1164
+ buildImage(board, element, event.target.files[0]);
1165
+ };
1166
+ inputFile.click();
1167
+ };
1168
+ const buildImage = (board, element, imageFile) => __awaiter(void 0, void 0, void 0, function* () {
1169
+ let width = 0, height = 0;
1170
+ yield getImageSize(imageFile).then((value) => {
1171
+ width = value.width;
1172
+ height = value.height;
1173
+ });
1174
+ let imageItem = null;
1175
+ const url = URL.createObjectURL(imageFile);
1176
+ const context = PlaitBoard.getComponent(board).viewContainerRef.injector.get(PlaitContextService);
1177
+ context.setUploadingFile({ url, file: imageFile });
1178
+ imageItem = {
1179
+ url,
1180
+ width,
1181
+ height
1182
+ };
1183
+ MindTransforms.setImage(board, element, imageItem);
1184
+ });
1185
+ function getImageSize(file, defaultImageWidth = DEFAULT_IMAGE_WIDTH) {
1186
+ return new Promise((resolve, reject) => {
1187
+ const image = new Image();
1188
+ image.src = URL.createObjectURL(file);
1189
+ image.onload = function () {
1190
+ const width = defaultImageWidth;
1191
+ const height = (defaultImageWidth * image.naturalHeight) / image.naturalWidth;
1192
+ resolve(image.naturalWidth > defaultImageWidth ? { width, height } : { width: image.naturalWidth, height: image.naturalHeight });
1193
+ };
1194
+ });
1195
+ }
1196
+
1197
+ const getAvailableProperty = (board, element, propertyKey) => {
1198
+ return element[propertyKey];
882
1199
  };
883
1200
 
884
1201
  /**
@@ -1809,6 +2126,73 @@ const deleteElementsHandleRightNodeCount = (board, deletableElements, effectedRi
1809
2126
  return effectedRightNodeCount;
1810
2127
  };
1811
2128
 
2129
+ const getLayoutOptions = (board) => {
2130
+ function getMainAxle(element, parent) {
2131
+ const strokeWidth = element.strokeWidth || STROKE_WIDTH;
2132
+ if (element.isRoot) {
2133
+ return BASE * 12;
2134
+ }
2135
+ if (parent && parent.isRoot()) {
2136
+ return BASE * 3 + strokeWidth / 2;
2137
+ }
2138
+ return BASE * 3 + strokeWidth / 2;
2139
+ }
2140
+ function getSecondAxle(element, parent) {
2141
+ const strokeWidth = element.strokeWidth || STROKE_WIDTH;
2142
+ if (element.isRoot) {
2143
+ return BASE * 10 + strokeWidth / 2;
2144
+ }
2145
+ return BASE * 6 + strokeWidth / 2;
2146
+ }
2147
+ return {
2148
+ getHeight(element) {
2149
+ return NodeSpace.getNodeHeight(board, element);
2150
+ },
2151
+ getWidth(element) {
2152
+ return NodeSpace.getNodeWidth(board, element);
2153
+ },
2154
+ getHorizontalGap(element, parent) {
2155
+ const _layout = (parent && parent.layout) || getRootLayout(element);
2156
+ const isHorizontal = isHorizontalLayout(_layout);
2157
+ const strokeWidth = element.strokeWidth || STROKE_WIDTH;
2158
+ if (isIndentedLayout(_layout)) {
2159
+ return BASE * 4 + strokeWidth;
2160
+ }
2161
+ if (!isHorizontal) {
2162
+ return getMainAxle(element, parent);
2163
+ }
2164
+ else {
2165
+ return getSecondAxle(element, parent);
2166
+ }
2167
+ },
2168
+ getVerticalGap(element, parent) {
2169
+ const _layout = (parent && parent.layout) || getRootLayout(element);
2170
+ if (isIndentedLayout(_layout)) {
2171
+ return BASE;
2172
+ }
2173
+ const isHorizontal = isHorizontalLayout(_layout);
2174
+ if (isHorizontal) {
2175
+ return getMainAxle(element, parent);
2176
+ }
2177
+ else {
2178
+ return getSecondAxle(element, parent);
2179
+ }
2180
+ },
2181
+ getVerticalConnectingPosition(element, parent) {
2182
+ if (element.shape === MindElementShape.underline && parent && isHorizontalLogicLayout(parent.layout)) {
2183
+ return ConnectingPosition.bottom;
2184
+ }
2185
+ return undefined;
2186
+ },
2187
+ getExtendHeight(node) {
2188
+ return BASE * 6;
2189
+ },
2190
+ getIndentedCrossLevelGap() {
2191
+ return BASE * 2;
2192
+ }
2193
+ };
2194
+ };
2195
+
1812
2196
  /**
1813
2197
  * get correctly layout:
1814
2198
  * 1. root is standard -> left or right
@@ -2164,247 +2548,25 @@ class NodeEmojisDrawer {
2164
2548
  container.classList.add('node-emojis-container');
2165
2549
  foreignObject.append(container);
2166
2550
  this.emojiDrawers = element.data.emojis.map(emojiItem => {
2167
- const drawer = new EmojiDrawer(this.board, this.viewContainerRef);
2168
- drawer.draw(emojiItem, element);
2169
- return drawer;
2170
- });
2171
- this.emojiDrawers.forEach(drawer => {
2172
- container.append(drawer.nativeElement);
2173
- });
2174
- return this.g;
2175
- }
2176
- return undefined;
2177
- }
2178
- destroy() {
2179
- if (this.g) {
2180
- this.g.remove();
2181
- }
2182
- this.emojiDrawers.forEach(drawer => drawer.destroy());
2183
- this.emojiDrawers = [];
2184
- }
2185
- }
2186
-
2187
- const setAbstractsByRefs = (board, abstractRefs) => {
2188
- abstractRefs.forEach((newProperty, element) => {
2189
- const start = element.start + newProperty.start;
2190
- const end = element.end + newProperty.end;
2191
- const path = PlaitBoard.findPath(board, element);
2192
- if (start > end) {
2193
- Transforms.removeNode(board, path);
2194
- }
2195
- else {
2196
- Transforms.setNode(board, { start, end }, path);
2197
- }
2198
- });
2199
- };
2200
- const setAbstractByStandardLayout = (board, element) => {
2201
- const rightNodeCount = element.rightNodeCount;
2202
- const abstract = element.children.find(child => {
2203
- return AbstractNode.isAbstract(child) && child.end >= rightNodeCount && child.start < rightNodeCount;
2204
- });
2205
- if (abstract) {
2206
- const path = PlaitBoard.findPath(board, abstract);
2207
- Transforms.setNode(board, { end: rightNodeCount - 1 }, path);
2208
- }
2209
- };
2210
- const insertAbstract = (board, elements) => {
2211
- let elementGroup = getFirstLevelElement(elements);
2212
- const { parentElements, abstractIncludedGroups } = divideElementByParent(elementGroup);
2213
- abstractIncludedGroups.forEach((group, index) => {
2214
- const groupParent = parentElements[index];
2215
- setAbstractByElements(board, groupParent, group);
2216
- });
2217
- };
2218
- const setAbstractByElements = (board, groupParent, group) => {
2219
- const indexArray = group.map(child => groupParent.children.indexOf(child)).sort((a, b) => a - b);
2220
- const rightNodeCount = groupParent === null || groupParent === void 0 ? void 0 : groupParent.rightNodeCount;
2221
- const start = indexArray[0], end = indexArray[indexArray.length - 1];
2222
- if (isStandardLayout(MindQueries.getLayoutByElement(groupParent)) &&
2223
- rightNodeCount &&
2224
- start < rightNodeCount &&
2225
- end >= rightNodeCount) {
2226
- const childrenLength = groupParent.children.length;
2227
- const path = [...PlaitBoard.findPath(board, groupParent), childrenLength];
2228
- const leftChildren = indexArray.filter(index => index >= rightNodeCount);
2229
- const rightChildren = indexArray.filter(index => index < rightNodeCount);
2230
- insertAbstractNode(board, path, rightChildren[0], rightChildren[rightChildren.length - 1]);
2231
- insertAbstractNode(board, Path.next(path), leftChildren[0], leftChildren[leftChildren.length - 1]);
2232
- }
2233
- else {
2234
- const path = [...PlaitBoard.findPath(board, groupParent), groupParent.children.length];
2235
- insertAbstractNode(board, path, start, end);
2236
- }
2237
- };
2238
- const insertAbstractNode = (board, path, start, end) => {
2239
- const mindElement = createMindElement('概要', 28, 20, {
2240
- strokeWidth: DefaultAbstractNodeStyle.branch.width,
2241
- branchWidth: DefaultAbstractNodeStyle.branch.width
2242
- });
2243
- mindElement.start = start;
2244
- mindElement.end = end;
2245
- Transforms.insertNode(board, mindElement, path);
2246
- clearSelectedElement(board);
2247
- addSelectedElement(board, mindElement);
2248
- };
2249
-
2250
- const setLayout = (board, layout, path) => {
2251
- correctLogicLayoutNode(board, layout, path);
2252
- const element = PlaitNode.get(board, path);
2253
- if (PlaitMind.isMind(element) && isStandardLayout(layout)) {
2254
- MindTransforms.setAbstractByStandardLayout(board, element);
2255
- }
2256
- Transforms.setNode(board, { layout }, path);
2257
- };
2258
- const correctLogicLayoutNode = (board, layout, path) => {
2259
- var _a;
2260
- const node = PlaitNode.get(board, path);
2261
- if (node && layout) {
2262
- (_a = node.children) === null || _a === void 0 ? void 0 : _a.forEach((value, index) => {
2263
- var _a;
2264
- if (value.layout) {
2265
- if ((isHorizontalLogicLayout(layout) && isVerticalLogicLayout(value.layout)) ||
2266
- (isVerticalLogicLayout(layout) && isHorizontalLogicLayout(value.layout))) {
2267
- Transforms.setNode(board, { layout: null }, [...path, index]);
2268
- }
2269
- if ((_a = value.children) === null || _a === void 0 ? void 0 : _a.length) {
2270
- correctLogicLayoutNode(board, layout, [...path, index]);
2271
- }
2272
- }
2273
- });
2274
- }
2275
- };
2276
-
2277
- const normalizeWidthAndHeight = (board, element, width, height) => {
2278
- const minWidth = NodeSpace.getNodeTopicMinWidth(board, element, element.isRoot);
2279
- const newWidth = width < minWidth * board.viewport.zoom ? minWidth : width / board.viewport.zoom;
2280
- const newHeight = height / board.viewport.zoom;
2281
- return { width: newWidth, height: newHeight };
2282
- };
2283
- const setTopic = (board, element, topic, width, height) => {
2284
- const newElement = Object.assign({ data: Object.assign(Object.assign({}, element.data), { topic }) }, normalizeWidthAndHeight(board, element, width, height));
2285
- const path = PlaitBoard.findPath(board, element);
2286
- Transforms.setNode(board, newElement, path);
2287
- };
2288
- const setNodeManualWidth = (board, element, width, height) => {
2289
- const path = PlaitBoard.findPath(board, element);
2290
- const { width: normalizedWidth, height: normalizedHeight } = normalizeWidthAndHeight(board, element, width, height);
2291
- const newElement = { manualWidth: normalizedWidth, height: normalizedHeight };
2292
- Transforms.setNode(board, newElement, path);
2293
- };
2294
- const setTopicSize = (board, element, width, height) => {
2295
- const newElement = Object.assign({}, normalizeWidthAndHeight(board, element, width, height));
2296
- let isEqualWidth = Math.ceil(element.width) === Math.ceil(newElement.width);
2297
- let isEqualHeight = Math.ceil(element.height) === Math.ceil(newElement.height);
2298
- if (element.manualWidth) {
2299
- isEqualWidth = true;
2300
- }
2301
- if (!isEqualWidth || !isEqualHeight) {
2302
- const path = PlaitBoard.findPath(board, element);
2303
- Transforms.setNode(board, newElement, path);
2304
- }
2305
- };
2306
- const removeElements = (board, elements) => {
2307
- const deletableElements = getFirstLevelElement(elements);
2308
- deletableElements
2309
- .map(element => {
2310
- const path = PlaitBoard.findPath(board, element);
2311
- const ref = board.pathRef(path);
2312
- return () => {
2313
- Transforms.removeNode(board, ref.current);
2314
- ref.unref();
2315
- };
2316
- })
2317
- .forEach(action => {
2318
- action();
2319
- });
2320
- };
2321
- const insertNodes = (board, elements, path) => {
2322
- const pathRef = board.pathRef(path);
2323
- elements.forEach(element => {
2324
- if (pathRef.current) {
2325
- Transforms.insertNode(board, element, pathRef.current);
2551
+ const drawer = new EmojiDrawer(this.board, this.viewContainerRef);
2552
+ drawer.draw(emojiItem, element);
2553
+ return drawer;
2554
+ });
2555
+ this.emojiDrawers.forEach(drawer => {
2556
+ container.append(drawer.nativeElement);
2557
+ });
2558
+ return this.g;
2326
2559
  }
2327
- });
2328
- pathRef.unref();
2329
- };
2330
- const insertAbstractNodes = (board, validAbstractRefs, elements, path) => {
2331
- var _a;
2332
- const parent = PlaitNode.get(board, Path$1.parent(path));
2333
- const abstractPath = [...Path$1.parent(path), (_a = parent.children) === null || _a === void 0 ? void 0 : _a.length];
2334
- const abstracts = validAbstractRefs.map(refs => {
2335
- const { start, end } = getRelativeStartEndByAbstractRef(refs, elements);
2336
- return Object.assign(Object.assign({}, refs.abstract), { start: start + path[path.length - 1], end: end + path[path.length - 1] });
2337
- });
2338
- insertNodes(board, abstracts, abstractPath);
2339
- };
2340
- const setRightNodeCountByRefs = (board, refs) => {
2341
- refs.forEach(ref => {
2342
- Transforms.setNode(board, { rightNodeCount: ref.rightNodeCount }, ref.path);
2343
- });
2344
- };
2345
-
2346
- const addEmoji = (board, element, emojiItem) => {
2347
- const emojis = element.data.emojis || [];
2348
- const newEmojis = [...emojis];
2349
- newEmojis.push(emojiItem);
2350
- const newElement = {
2351
- data: { topic: element.data.topic, emojis: newEmojis }
2352
- };
2353
- const path = PlaitBoard.findPath(board, element);
2354
- Transforms.setNode(board, newElement, path);
2355
- };
2356
- const removeEmoji = (board, element, emojiItem) => {
2357
- const emojis = element.data.emojis.filter(value => value !== emojiItem);
2358
- const newElement = {
2359
- data: { topic: element.data.topic }
2360
- };
2361
- if (emojis.length > 0) {
2362
- newElement.data.emojis = emojis;
2560
+ return undefined;
2363
2561
  }
2364
- const path = PlaitBoard.findPath(board, element);
2365
- Transforms.setNode(board, newElement, path);
2366
- };
2367
- const replaceEmoji = (board, element, oldEmoji, newEmoji) => {
2368
- const newElement = {
2369
- data: Object.assign({}, element.data)
2370
- };
2371
- const newEmojis = element.data.emojis.map(value => {
2372
- if (value === oldEmoji) {
2373
- return newEmoji;
2562
+ destroy() {
2563
+ if (this.g) {
2564
+ this.g.remove();
2374
2565
  }
2375
- return value;
2376
- });
2377
- newElement.data.emojis = newEmojis;
2378
- const path = PlaitBoard.findPath(board, element);
2379
- Transforms.setNode(board, newElement, path);
2380
- };
2381
-
2382
- const removeImage = (board, element) => {
2383
- const newElement = {
2384
- data: Object.assign({}, element.data)
2385
- };
2386
- delete newElement.data.image;
2387
- const path = PlaitBoard.findPath(board, element);
2388
- Transforms.setNode(board, newElement, path);
2389
- };
2390
-
2391
- const MindTransforms = {
2392
- setLayout,
2393
- setTopic,
2394
- setTopicSize,
2395
- setNodeManualWidth,
2396
- addEmoji,
2397
- removeEmoji,
2398
- replaceEmoji,
2399
- insertAbstract,
2400
- setAbstractsByRefs,
2401
- setAbstractByStandardLayout,
2402
- removeElements,
2403
- insertNodes,
2404
- insertAbstractNodes,
2405
- setRightNodeCountByRefs,
2406
- removeImage
2407
- };
2566
+ this.emojiDrawers.forEach(drawer => drawer.destroy());
2567
+ this.emojiDrawers = [];
2568
+ }
2569
+ }
2408
2570
 
2409
2571
  class BaseDrawer {
2410
2572
  constructor(board) {
@@ -2763,36 +2925,6 @@ class CollapseDrawer extends BaseDrawer {
2763
2925
  }
2764
2926
  }
2765
2927
 
2766
- class MindImageBaseComponent {
2767
- get nativeElement() {
2768
- return this.elementRef.nativeElement;
2769
- }
2770
- constructor(elementRef, cdr) {
2771
- this.elementRef = elementRef;
2772
- this.cdr = cdr;
2773
- this.isFocus = false;
2774
- }
2775
- ngOnInit() { }
2776
- }
2777
- 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 });
2778
- 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 });
2779
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindImageBaseComponent, decorators: [{
2780
- type: Directive,
2781
- args: [{
2782
- host: {
2783
- class: 'mind-node-image'
2784
- }
2785
- }]
2786
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { imageItem: [{
2787
- type: Input
2788
- }], board: [{
2789
- type: Input
2790
- }], element: [{
2791
- type: Input
2792
- }], isFocus: [{
2793
- type: Input
2794
- }] } });
2795
-
2796
2928
  class NodeImageDrawer {
2797
2929
  constructor(board, viewContainerRef) {
2798
2930
  this.board = board;
@@ -2806,9 +2938,9 @@ class NodeImageDrawer {
2806
2938
  }
2807
2939
  this.g = createG();
2808
2940
  const foreignRectangle = getImageForeignRectangle(this.board, element);
2809
- const foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
2810
- this.g.append(foreignObject);
2811
- const componentType = this.board.getPluginOptions(WithMindPluginKey).imageComponentType || MindImageBaseComponent;
2941
+ this.foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
2942
+ this.g.append(this.foreignObject);
2943
+ const componentType = this.board.getPluginOptions(WithMindPluginKey).imageComponentType;
2812
2944
  if (!componentType) {
2813
2945
  throw new Error('Not implement drawEmoji method error.');
2814
2946
  }
@@ -2817,7 +2949,7 @@ class NodeImageDrawer {
2817
2949
  this.componentRef.instance.element = element;
2818
2950
  this.componentRef.instance.imageItem = element.data.image;
2819
2951
  this.componentRef.instance.cdr.markForCheck();
2820
- foreignObject.append(this.componentRef.instance.nativeElement);
2952
+ this.foreignObject.append(this.componentRef.instance.nativeElement);
2821
2953
  nodeG.appendChild(this.g);
2822
2954
  }
2823
2955
  updateImage(nodeG, previous, current) {
@@ -2832,6 +2964,10 @@ class NodeImageDrawer {
2832
2964
  }
2833
2965
  const currentForeignObject = getImageForeignRectangle(this.board, current);
2834
2966
  updateForeignObject(this.g, currentForeignObject.width, currentForeignObject.height, currentForeignObject.x, currentForeignObject.y);
2967
+ // solve image lose on move node
2968
+ if (this.foreignObject.children.length === 0) {
2969
+ this.foreignObject.append(this.componentRef.instance.nativeElement);
2970
+ }
2835
2971
  (_a = this.componentRef) === null || _a === void 0 ? void 0 : _a.instance.cdr.markForCheck();
2836
2972
  }
2837
2973
  destroy() {
@@ -2891,7 +3027,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2891
3027
  this.parentG = PlaitElement.getComponent(MindElement.getRoot(this.board, this.element)).rootG;
2892
3028
  this.drawShape();
2893
3029
  this.drawLink();
2894
- this.drawText();
3030
+ this.drawTopic();
2895
3031
  this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: this.textManage.isEditing });
2896
3032
  this.drawEmojis();
2897
3033
  this.drawExtend();
@@ -2900,18 +3036,6 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2900
3036
  this.g.classList.add('branch');
2901
3037
  }
2902
3038
  }
2903
- editTopic() {
2904
- this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: true });
2905
- if (this.element.manualWidth) {
2906
- const width = NodeSpace.getNodeResizableWidth(this.board, this.element);
2907
- this.textManage.updateWidth(width);
2908
- }
2909
- this.textManage.edit((origin) => {
2910
- if (origin === ExitOrigin.default) {
2911
- this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: false });
2912
- }
2913
- });
2914
- }
2915
3039
  onContextChanged(value, previous) {
2916
3040
  const newNode = MindElement.getNode(value.element);
2917
3041
  const isEqualNode = RectangleClient.isEqual(this.node, newNode);
@@ -2924,8 +3048,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2924
3048
  this.drawEmojis();
2925
3049
  this.drawExtend();
2926
3050
  this.imageDrawer.updateImage(this.g, previous.element, value.element);
2927
- this.textManage.updateText(this.element.data.topic);
2928
- this.textManage.updateRectangle();
3051
+ this.updateTopic();
2929
3052
  }
2930
3053
  else {
2931
3054
  const hasSameSelected = value.selected === previous.selected;
@@ -3004,9 +3127,29 @@ class MindNodeComponent extends PlaitPluginElementComponent {
3004
3127
  this.extendG.remove();
3005
3128
  }
3006
3129
  }
3007
- drawText() {
3130
+ drawTopic() {
3008
3131
  this.textManage.draw(this.element.data.topic);
3009
3132
  this.g.append(this.textManage.g);
3133
+ if (this.element.manualWidth) {
3134
+ const width = NodeSpace.getNodeDynamicWidth(this.board, this.element);
3135
+ this.textManage.updateWidth(width);
3136
+ }
3137
+ }
3138
+ updateTopic() {
3139
+ this.textManage.updateText(this.element.data.topic);
3140
+ this.textManage.updateRectangle();
3141
+ if (this.element.manualWidth) {
3142
+ const width = NodeSpace.getNodeDynamicWidth(this.board, this.element);
3143
+ this.textManage.updateWidth(width);
3144
+ }
3145
+ }
3146
+ editTopic() {
3147
+ this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: true });
3148
+ this.textManage.edit((origin) => {
3149
+ if (origin === ExitOrigin.default) {
3150
+ this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: false });
3151
+ }
3152
+ });
3010
3153
  }
3011
3154
  ngOnDestroy() {
3012
3155
  super.ngOnDestroy();
@@ -3047,73 +3190,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
3047
3190
  }]
3048
3191
  }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; } });
3049
3192
 
3050
- const getLayoutOptions = (board) => {
3051
- function getMainAxle(element, parent) {
3052
- const strokeWidth = element.strokeWidth || STROKE_WIDTH;
3053
- if (element.isRoot) {
3054
- return BASE * 12;
3055
- }
3056
- if (parent && parent.isRoot()) {
3057
- return BASE * 3 + strokeWidth / 2;
3058
- }
3059
- return BASE * 3 + strokeWidth / 2;
3060
- }
3061
- function getSecondAxle(element, parent) {
3062
- const strokeWidth = element.strokeWidth || STROKE_WIDTH;
3063
- if (element.isRoot) {
3064
- return BASE * 10 + strokeWidth / 2;
3065
- }
3066
- return BASE * 6 + strokeWidth / 2;
3067
- }
3068
- return {
3069
- getHeight(element) {
3070
- return NodeSpace.getNodeHeight(board, element);
3071
- },
3072
- getWidth(element) {
3073
- return NodeSpace.getNodeWidth(board, element);
3074
- },
3075
- getHorizontalGap(element, parent) {
3076
- const _layout = (parent && parent.layout) || getRootLayout(element);
3077
- const isHorizontal = isHorizontalLayout(_layout);
3078
- const strokeWidth = element.strokeWidth || STROKE_WIDTH;
3079
- if (isIndentedLayout(_layout)) {
3080
- return BASE * 4 + strokeWidth;
3081
- }
3082
- if (!isHorizontal) {
3083
- return getMainAxle(element, parent);
3084
- }
3085
- else {
3086
- return getSecondAxle(element, parent);
3087
- }
3088
- },
3089
- getVerticalGap(element, parent) {
3090
- const _layout = (parent && parent.layout) || getRootLayout(element);
3091
- if (isIndentedLayout(_layout)) {
3092
- return BASE;
3093
- }
3094
- const isHorizontal = isHorizontalLayout(_layout);
3095
- if (isHorizontal) {
3096
- return getMainAxle(element, parent);
3097
- }
3098
- else {
3099
- return getSecondAxle(element, parent);
3100
- }
3101
- },
3102
- getVerticalConnectingPosition(element, parent) {
3103
- if (element.shape === MindElementShape.underline && parent && isHorizontalLogicLayout(parent.layout)) {
3104
- return ConnectingPosition.bottom;
3105
- }
3106
- return undefined;
3107
- },
3108
- getExtendHeight(node) {
3109
- return BASE * 6;
3110
- },
3111
- getIndentedCrossLevelGap() {
3112
- return BASE * 2;
3113
- }
3114
- };
3115
- };
3116
-
3117
3193
  class PlaitMindComponent extends MindNodeComponent {
3118
3194
  ngOnInit() {
3119
3195
  this.updateMindLayout();
@@ -3410,7 +3486,7 @@ const insertClipboardData = (board, elements, targetPoint) => {
3410
3486
  if (item.isRoot) {
3411
3487
  newElement = adjustRootToNode(board, newElement);
3412
3488
  const styles = PlaitMind.isMind(targetParent) ? { fontFamily: BRANCH_FONT_FAMILY } : { fontFamily: DEFAULT_FONT_FAMILY };
3413
- const { width, height } = getTextSize(board, newElement.data.topic, TOPIC_DEFAULT_MAX_WORD_COUNT, styles);
3489
+ const { width, height } = getTextSize(board, newElement.data.topic, TOPIC_DEFAULT_MAX_WORD_COUNT, Object.assign(Object.assign({}, styles), { width: newElement.manualWidth ? newElement.manualWidth : undefined }));
3414
3490
  newElement.width = Math.max(width, getNodeDefaultFontSize());
3415
3491
  newElement.height = height;
3416
3492
  }
@@ -3840,7 +3916,7 @@ const withNodeHoverDetect = (board) => {
3840
3916
  };
3841
3917
 
3842
3918
  const withNodeImage = (board) => {
3843
- const { keydown, mousedown, globalMouseup } = board;
3919
+ const { keydown, mousedown, globalMouseup, insertFragment } = board;
3844
3920
  board.mousedown = (event) => {
3845
3921
  const selectedImageElement = getSelectedImageElement(board);
3846
3922
  if (PlaitBoard.isReadonly(board) || !isMainPointer(event) || !PlaitBoard.isPointer(board, PlaitPointerType.selection)) {
@@ -3866,7 +3942,6 @@ const withNodeImage = (board) => {
3866
3942
  if (hitImage) {
3867
3943
  temporaryDisableSelection(board);
3868
3944
  setImageFocus(board, hitElements[0], true);
3869
- clearSelectedElement(board);
3870
3945
  }
3871
3946
  mousedown(event);
3872
3947
  };
@@ -3874,7 +3949,6 @@ const withNodeImage = (board) => {
3874
3949
  const selectedImageElement = getSelectedImageElement(board);
3875
3950
  if (!PlaitBoard.isReadonly(board) && selectedImageElement && (hotkeys.isDeleteBackward(event) || hotkeys.isDeleteForward(event))) {
3876
3951
  addSelectedElement(board, selectedImageElement);
3877
- setImageFocus(board, selectedImageElement, false);
3878
3952
  MindTransforms.removeImage(board, selectedImageElement);
3879
3953
  return;
3880
3954
  }
@@ -3891,6 +3965,21 @@ const withNodeImage = (board) => {
3891
3965
  }
3892
3966
  globalMouseup(event);
3893
3967
  };
3968
+ board.insertFragment = (data, targetPoint) => {
3969
+ const selectedElements = getSelectedElements(board);
3970
+ const isSelectedImage = !!getSelectedImageElement(board);
3971
+ const isSingleSelection = selectedElements.length === 1 && MindElement.isMindElement(board, selectedElements[0]);
3972
+ if ((data === null || data === void 0 ? void 0 : data.files.length) && (isSingleSelection || isSelectedImage)) {
3973
+ const selectedElement = (selectedElements[0] || getSelectedImageElement(board));
3974
+ const acceptImageArray = acceptImageTypes.map(type => 'image/' + type);
3975
+ if (acceptImageArray.includes(data === null || data === void 0 ? void 0 : data.files[0].type)) {
3976
+ const imageFile = data.files[0];
3977
+ buildImage(board, selectedElement, imageFile);
3978
+ return;
3979
+ }
3980
+ }
3981
+ insertFragment(data, targetPoint);
3982
+ };
3894
3983
  return board;
3895
3984
  };
3896
3985
 
@@ -3920,7 +4009,7 @@ const withNodeResize = (board) => {
3920
4009
  addResizing(board, targetElement);
3921
4010
  targetElementRef = {
3922
4011
  minWidth: NodeSpace.getNodeResizableMinWidth(board, targetElement),
3923
- currentWidth: NodeSpace.getNodeResizableWidth(board, targetElement),
4012
+ currentWidth: NodeSpace.getNodeDynamicWidth(board, targetElement),
3924
4013
  path: PlaitBoard.findPath(board, targetElement),
3925
4014
  textManage: PlaitElement.getComponent(targetElement).textManage
3926
4015
  };
@@ -3936,7 +4025,7 @@ const withNodeResize = (board) => {
3936
4025
  const offsetX = endPoint[0] - startPoint[0];
3937
4026
  const zoom = board.viewport.zoom;
3938
4027
  let resizedWidth = targetElementRef.currentWidth + offsetX / zoom;
3939
- if (resizedWidth < targetElementRef.minWidth) {
4028
+ if (resizedWidth <= targetElementRef.minWidth) {
3940
4029
  resizedWidth = targetElementRef.minWidth;
3941
4030
  }
3942
4031
  const newTarget = PlaitNode.get(board, targetElementRef.path);
@@ -4163,6 +4252,42 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
4163
4252
  args: ['mousedown']
4164
4253
  }] } });
4165
4254
 
4255
+ class MindImageBaseComponent {
4256
+ set imageItem(value) {
4257
+ this.afterImageItemChange(this._imageItem, value);
4258
+ this._imageItem = value;
4259
+ }
4260
+ get imageItem() {
4261
+ return this._imageItem;
4262
+ }
4263
+ get nativeElement() {
4264
+ return this.elementRef.nativeElement;
4265
+ }
4266
+ constructor(elementRef, cdr) {
4267
+ this.elementRef = elementRef;
4268
+ this.cdr = cdr;
4269
+ this.isFocus = false;
4270
+ }
4271
+ }
4272
+ 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 });
4273
+ 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 });
4274
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindImageBaseComponent, decorators: [{
4275
+ type: Directive,
4276
+ args: [{
4277
+ host: {
4278
+ class: 'mind-node-image'
4279
+ }
4280
+ }]
4281
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { imageItem: [{
4282
+ type: Input
4283
+ }], board: [{
4284
+ type: Input
4285
+ }], element: [{
4286
+ type: Input
4287
+ }], isFocus: [{
4288
+ type: Input
4289
+ }] } });
4290
+
4166
4291
  /*
4167
4292
  * Public API Surface of mind
4168
4293
  */
@@ -4171,5 +4296,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
4171
4296
  * Generated bundle index. Do not edit.
4172
4297
  */
4173
4298
 
4174
- 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, 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, 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, getFillByElement, getFirstLevelElement, getHitAbstractHandle, getImageForeignRectangle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection, getLocationScope, getMindThemeColor, getNextBranchColor, getOverallAbstracts, getPathByDropTarget, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getSelectedImageElement, 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, separateChildren, setImageFocus, setIsDragging, temporaryDisableSelection, withMind, withMindExtend };
4299
+ 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, getImageForeignRectangle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutOptions, getLayoutReverseDirection, getLocationScope, getMindThemeColor, getNewNodeHeight, getNextBranchColor, getNodeDefaultFontSize, getOverallAbstracts, getPathByDropTarget, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getSelectedImageElement, 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 };
4175
4300
  //# sourceMappingURL=plait-mind.mjs.map