@plait/mind 0.20.0 → 0.21.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 (37) hide show
  1. package/base/image-base.component.d.ts +5 -3
  2. package/drawer/node-image.drawer.d.ts +3 -5
  3. package/esm2020/base/image-base.component.mjs +9 -5
  4. package/esm2020/drawer/node-image.drawer.mjs +34 -39
  5. package/esm2020/interfaces/element.mjs +1 -1
  6. package/esm2020/node.component.mjs +8 -9
  7. package/esm2020/plugins/with-abstract-resize.mjs +1 -2
  8. package/esm2020/plugins/with-mind-hotkey.mjs +3 -2
  9. package/esm2020/plugins/with-mind.mjs +4 -3
  10. package/esm2020/plugins/with-node-dnd.mjs +3 -3
  11. package/esm2020/plugins/with-node-image.mjs +46 -0
  12. package/esm2020/plugins/with-node-resize.mjs +119 -0
  13. package/esm2020/transforms/index.mjs +3 -2
  14. package/esm2020/transforms/node.mjs +13 -2
  15. package/esm2020/utils/node/common.mjs +11 -2
  16. package/esm2020/utils/node/image.mjs +23 -0
  17. package/esm2020/utils/position/image.mjs +9 -4
  18. package/esm2020/utils/position/topic.mjs +3 -3
  19. package/esm2020/utils/space/node-space.mjs +23 -22
  20. package/fesm2015/plait-mind.mjs +252 -99
  21. package/fesm2015/plait-mind.mjs.map +1 -1
  22. package/fesm2020/plait-mind.mjs +253 -99
  23. package/fesm2020/plait-mind.mjs.map +1 -1
  24. package/interfaces/element.d.ts +1 -0
  25. package/node.component.d.ts +0 -1
  26. package/package.json +1 -1
  27. package/plugins/with-mind-hotkey.d.ts +1 -1
  28. package/plugins/with-node-image.d.ts +2 -0
  29. package/plugins/with-node-resize.d.ts +10 -0
  30. package/styles/styles.scss +9 -2
  31. package/transforms/index.d.ts +1 -0
  32. package/transforms/node.d.ts +1 -0
  33. package/utils/node/common.d.ts +2 -0
  34. package/utils/node/image.d.ts +6 -0
  35. package/utils/space/node-space.d.ts +3 -3
  36. package/esm2020/plugins/with-mind-image.mjs +0 -49
  37. package/plugins/with-mind-image.d.ts +0 -2
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
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, 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, PlaitPluginKey, throttleRAF, BoardTransforms, removeSelectedElement, PlaitHistoryBoard, hotkeys } 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
5
  import { MindLayoutType, isIndentedLayout, AbstractNode, getNonAbstractChildren, isStandardLayout, isLeftLayout, isRightLayout, isVerticalLogicLayout, isHorizontalLogicLayout, isTopLayout, isBottomLayout, isHorizontalLayout, getCorrectStartEnd, getAbstractLayout, ConnectingPosition, 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';
@@ -190,11 +190,11 @@ const BRANCH_FONT_FAMILY = 'PingFangSC-Medium, "PingFang SC"';
190
190
 
191
191
  const NodeDefaultSpace = {
192
192
  horizontal: {
193
- nodeAndText: BASE * 3,
193
+ nodeAndText: BASE * 2.5,
194
194
  emojiAndText: BASE * 1.5
195
195
  },
196
196
  vertical: {
197
- nodeAndText: BASE * 1.5,
197
+ nodeAndText: BASE,
198
198
  nodeAndImage: BASE,
199
199
  imageAndText: BASE * 1.5
200
200
  }
@@ -211,12 +211,14 @@ const RootDefaultSpace = {
211
211
  const getHorizontalSpaceBetweenNodeAndText = (board, element) => {
212
212
  const isMind = PlaitMind.isMind(element);
213
213
  const nodeAndText = isMind ? RootDefaultSpace.horizontal.nodeAndText : NodeDefaultSpace.horizontal.nodeAndText;
214
- return nodeAndText;
214
+ const strokeWidth = getStrokeWidthByElement(board, element);
215
+ return nodeAndText + strokeWidth / 2;
215
216
  };
216
- const getVerticalSpaceBetweenNodeAndText = (element) => {
217
+ const getVerticalSpaceBetweenNodeAndText = (board, element) => {
217
218
  const isMind = PlaitMind.isMind(element);
219
+ const strokeWidth = getStrokeWidthByElement(board, element);
218
220
  const nodeAndText = isMind ? RootDefaultSpace.vertical.nodeAndText : NodeDefaultSpace.vertical.nodeAndText;
219
- return nodeAndText;
221
+ return nodeAndText + strokeWidth / 2;
220
222
  };
221
223
  const getSpaceEmojiAndText = (element) => {
222
224
  const isMind = PlaitMind.isMind(element);
@@ -236,20 +238,17 @@ const NodeSpace = {
236
238
  return nodeAndText + NodeSpace.getNodeResizableWidth(board, element) + nodeAndText;
237
239
  },
238
240
  getNodeHeight(board, element) {
239
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
241
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
240
242
  if (MindElement.hasImage(element)) {
241
- return (NodeDefaultSpace.vertical.nodeAndImage +
242
- element.data.image.height +
243
- NodeDefaultSpace.vertical.imageAndText +
244
- element.height +
245
- nodeAndText);
243
+ return NodeSpace.getTextTopSpace(board, element) + element.height + nodeAndText;
246
244
  }
247
245
  return nodeAndText + element.height + nodeAndText;
248
246
  },
249
247
  getNodeResizableWidth(board, element) {
250
248
  var _a;
249
+ const width = element.manualWidth || element.width;
251
250
  const imageWidth = MindElement.hasImage(element) ? (_a = element.data.image) === null || _a === void 0 ? void 0 : _a.width : 0;
252
- return Math.max(element.width, imageWidth);
251
+ return Math.max(width, imageWidth);
253
252
  },
254
253
  getNodeResizableMinWidth(board, element) {
255
254
  const minTopicWidth = NodeSpace.getNodeTopicMinWidth(board, element);
@@ -276,25 +275,27 @@ const NodeSpace = {
276
275
  return nodeAndText;
277
276
  }
278
277
  },
279
- getTextTopSpace(element) {
280
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
278
+ getTextTopSpace(board, element) {
279
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
281
280
  if (MindElement.hasImage(element)) {
282
- return element.data.image.height + NodeDefaultSpace.vertical.nodeAndImage + NodeDefaultSpace.vertical.imageAndText;
281
+ return NodeSpace.getImageTopSpace(board, element) + element.data.image.height + NodeDefaultSpace.vertical.imageAndText;
283
282
  }
284
283
  else {
285
284
  return nodeAndText;
286
285
  }
287
286
  },
288
- getImageTopSpace(element) {
289
- return NodeDefaultSpace.vertical.nodeAndImage;
287
+ getImageTopSpace(board, element) {
288
+ const strokeWidth = getStrokeWidthByElement(board, element);
289
+ return strokeWidth / 2 + NodeDefaultSpace.vertical.nodeAndImage;
290
290
  },
291
291
  getEmojiLeftSpace(board, element) {
292
292
  const options = board.getPluginOptions(WithMindPluginKey);
293
293
  const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
294
- return nodeAndText - options.emojiPadding;
294
+ const strokeWidth = getStrokeWidthByElement(board, element);
295
+ return strokeWidth / 2 + nodeAndText - options.emojiPadding;
295
296
  },
296
- getEmojiTopSpace(element) {
297
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
297
+ getEmojiTopSpace(board, element) {
298
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
298
299
  return nodeAndText;
299
300
  }
300
301
  };
@@ -347,23 +348,28 @@ function getTopicRectangleByNode(board, node) {
347
348
  }
348
349
  function getTopicRectangleByElement(board, nodeRectangle, element) {
349
350
  const x = nodeRectangle.x + NodeSpace.getTextLeftSpace(board, element);
350
- const y = nodeRectangle.y + NodeSpace.getTextTopSpace(element);
351
- const width = Math.ceil(element.width);
351
+ const y = nodeRectangle.y + NodeSpace.getTextTopSpace(board, element);
352
+ const width = NodeSpace.getNodeResizableWidth(board, element);
352
353
  const height = Math.ceil(element.height);
353
354
  return { height, width, x, y };
354
355
  }
355
356
 
356
357
  function getImageForeignRectangle(board, element) {
357
358
  let { x, y } = getRectangleByNode(MindElement.getNode(element));
358
- x = x + NodeSpace.getTextLeftSpace(board, element);
359
- y = NodeSpace.getImageTopSpace(element) + y;
359
+ const elementWidth = element.manualWidth || element.width;
360
+ x =
361
+ elementWidth > element.data.image.width
362
+ ? x + NodeSpace.getTextLeftSpace(board, element) + (elementWidth - element.data.image.width) / 2
363
+ : x + NodeSpace.getTextLeftSpace(board, element);
364
+ y = NodeSpace.getImageTopSpace(board, element) + y;
360
365
  const { width, height } = element.data.image;
361
- return {
366
+ const rectangle = {
362
367
  x,
363
368
  y,
364
369
  width,
365
370
  height
366
371
  };
372
+ return RectangleClient.getOutlineRectangle(rectangle, -6);
367
373
  }
368
374
  const isHitImage = (board, element, range) => {
369
375
  const client = getImageForeignRectangle(board, element);
@@ -374,6 +380,15 @@ function editTopic(element) {
374
380
  const component = PlaitElement.getComponent(element);
375
381
  component === null || component === void 0 ? void 0 : component.editTopic();
376
382
  }
383
+ const temporaryDisableSelection = (board) => {
384
+ const currentOptions = board.getPluginOptions(PlaitPluginKey.withSelection);
385
+ board.setPluginOptions(PlaitPluginKey.withSelection, {
386
+ isDisabledSelect: true
387
+ });
388
+ setTimeout(() => {
389
+ board.setPluginOptions(PlaitPluginKey.withSelection, Object.assign({}, currentOptions));
390
+ }, 0);
391
+ };
377
392
 
378
393
  const createEmptyMind = (point) => {
379
394
  const element = createMindElement('思维导图', 72, ROOT_TOPIC_HEIGHT, { layout: MindLayoutType.right });
@@ -2246,9 +2261,20 @@ const setTopic = (board, element, topic, width, height) => {
2246
2261
  const path = PlaitBoard.findPath(board, element);
2247
2262
  Transforms.setNode(board, newElement, path);
2248
2263
  };
2264
+ const setNodeManualWidth = (board, element, width, height) => {
2265
+ const path = PlaitBoard.findPath(board, element);
2266
+ const { width: normalizedWidth, height: normalizedHeight } = normalizeWidthAndHeight(board, element, width, height);
2267
+ const newElement = { manualWidth: normalizedWidth, height: normalizedHeight };
2268
+ Transforms.setNode(board, newElement, path);
2269
+ };
2249
2270
  const setTopicSize = (board, element, width, height) => {
2250
2271
  const newElement = Object.assign({}, normalizeWidthAndHeight(board, element, width, height));
2251
- if (Math.floor(element.width) !== Math.floor(newElement.width) || Math.floor(element.height) !== Math.floor(newElement.height)) {
2272
+ let isEqualWidth = Math.ceil(element.width) === Math.ceil(newElement.width);
2273
+ let isEqualHeight = Math.ceil(element.height) === Math.ceil(newElement.height);
2274
+ if (element.manualWidth) {
2275
+ isEqualWidth = true;
2276
+ }
2277
+ if (!isEqualWidth || !isEqualHeight) {
2252
2278
  const path = PlaitBoard.findPath(board, element);
2253
2279
  Transforms.setNode(board, newElement, path);
2254
2280
  }
@@ -2342,6 +2368,7 @@ const MindTransforms = {
2342
2368
  setLayout,
2343
2369
  setTopic,
2344
2370
  setTopicSize,
2371
+ setNodeManualWidth,
2345
2372
  addEmoji,
2346
2373
  removeEmoji,
2347
2374
  replaceEmoji,
@@ -2716,13 +2743,15 @@ class MindImageBaseComponent {
2716
2743
  get nativeElement() {
2717
2744
  return this.elementRef.nativeElement;
2718
2745
  }
2719
- constructor(elementRef) {
2746
+ constructor(elementRef, cdr) {
2720
2747
  this.elementRef = elementRef;
2748
+ this.cdr = cdr;
2749
+ this.isFocus = false;
2721
2750
  }
2722
2751
  ngOnInit() { }
2723
2752
  }
2724
- MindImageBaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindImageBaseComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
2725
- 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 });
2753
+ 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 });
2754
+ 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 });
2726
2755
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindImageBaseComponent, decorators: [{
2727
2756
  type: Directive,
2728
2757
  args: [{
@@ -2730,12 +2759,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
2730
2759
  class: 'mind-node-image'
2731
2760
  }
2732
2761
  }]
2733
- }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { imageItem: [{
2762
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { imageItem: [{
2734
2763
  type: Input
2735
2764
  }], board: [{
2736
2765
  type: Input
2737
2766
  }], element: [{
2738
2767
  type: Input
2768
+ }], isFocus: [{
2769
+ type: Input
2739
2770
  }] } });
2740
2771
 
2741
2772
  class NodeImageDrawer {
@@ -2744,46 +2775,40 @@ class NodeImageDrawer {
2744
2775
  this.viewContainerRef = viewContainerRef;
2745
2776
  this.componentRef = null;
2746
2777
  }
2747
- drawImage(element) {
2748
- this.destroy();
2749
- if (MindElement.hasImage(element)) {
2750
- this.g = createG();
2751
- const foreignRectangle = getImageForeignRectangle(this.board, element);
2752
- const foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
2753
- this.g.append(foreignObject);
2754
- if (this.componentRef) {
2755
- this.componentRef.destroy();
2756
- this.componentRef = null;
2757
- }
2758
- const componentType = this.board.getPluginOptions(WithMindPluginKey).imageComponentType || MindImageBaseComponent;
2759
- if (!componentType) {
2760
- throw new Error('Not implement drawEmoji method error.');
2761
- }
2762
- this.componentRef = this.viewContainerRef.createComponent(componentType);
2763
- this.componentRef.instance.board = this.board;
2764
- this.componentRef.instance.element = element;
2765
- this.componentRef.instance.imageItem = element.data.image;
2766
- foreignObject.append(this.componentRef.instance.nativeElement);
2767
- return this.g;
2778
+ drawImage(nodeG, element) {
2779
+ if (!MindElement.hasImage(element)) {
2780
+ this.destroy();
2781
+ return;
2768
2782
  }
2769
- return undefined;
2770
- }
2771
- drawActive(element) {
2772
- var _a;
2773
- this.destroyActive();
2774
- const imageRectangle = getImageForeignRectangle(this.board, element);
2775
- const rectangle = RectangleClient.getOutlineRectangle(imageRectangle, -1);
2776
- const roughSVG = PlaitBoard.getRoughSVG(this.board);
2777
- this.activeG = roughSVG.rectangle(rectangle.x, rectangle.y, rectangle.width, rectangle.height, {
2778
- stroke: PRIMARY_COLOR,
2779
- fill: '',
2780
- fillStyle: 'solid'
2781
- });
2782
- (_a = this.g) === null || _a === void 0 ? void 0 : _a.append(this.activeG);
2783
+ this.g = createG();
2784
+ const foreignRectangle = getImageForeignRectangle(this.board, element);
2785
+ const foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
2786
+ this.g.append(foreignObject);
2787
+ const componentType = this.board.getPluginOptions(WithMindPluginKey).imageComponentType || MindImageBaseComponent;
2788
+ if (!componentType) {
2789
+ throw new Error('Not implement drawEmoji method error.');
2790
+ }
2791
+ this.componentRef = this.viewContainerRef.createComponent(componentType);
2792
+ this.componentRef.instance.board = this.board;
2793
+ this.componentRef.instance.element = element;
2794
+ this.componentRef.instance.imageItem = element.data.image;
2795
+ this.componentRef.instance.cdr.markForCheck();
2796
+ foreignObject.append(this.componentRef.instance.nativeElement);
2797
+ nodeG.appendChild(this.g);
2783
2798
  }
2784
- destroyActive() {
2799
+ updateImage(nodeG, previous, current) {
2785
2800
  var _a;
2786
- (_a = this.activeG) === null || _a === void 0 ? void 0 : _a.remove();
2801
+ if (!MindElement.hasImage(previous) || !MindElement.hasImage(current)) {
2802
+ this.drawImage(nodeG, current);
2803
+ return;
2804
+ }
2805
+ if (previous !== current && this.componentRef) {
2806
+ this.componentRef.instance.element = current;
2807
+ this.componentRef.instance.imageItem = current.data.image;
2808
+ }
2809
+ const currentForeignObject = getImageForeignRectangle(this.board, current);
2810
+ updateForeignObject(this.g, currentForeignObject.width, currentForeignObject.height, currentForeignObject.x, currentForeignObject.y);
2811
+ (_a = this.componentRef) === null || _a === void 0 ? void 0 : _a.instance.cdr.markForCheck();
2787
2812
  }
2788
2813
  destroy() {
2789
2814
  if (this.g) {
@@ -2846,13 +2871,17 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2846
2871
  this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: this.textManage.isEditing });
2847
2872
  this.drawEmojis();
2848
2873
  this.drawExtend();
2849
- this.drawImage();
2874
+ this.imageDrawer.drawImage(this.g, this.element);
2850
2875
  if (PlaitMind.isMind(this.context.parent)) {
2851
2876
  this.g.classList.add('branch');
2852
2877
  }
2853
2878
  }
2854
2879
  editTopic() {
2855
2880
  this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: true });
2881
+ if (this.element.manualWidth) {
2882
+ const width = NodeSpace.getNodeResizableWidth(this.board, this.element);
2883
+ this.textManage.updateWidth(width);
2884
+ }
2856
2885
  this.textManage.edit((origin) => {
2857
2886
  if (origin === ExitOrigin.default) {
2858
2887
  this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: false });
@@ -2869,8 +2898,8 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2869
2898
  this.drawShape();
2870
2899
  this.drawLink();
2871
2900
  this.drawEmojis();
2872
- this.drawImage();
2873
2901
  this.drawExtend();
2902
+ this.imageDrawer.updateImage(this.g, previous.element, value.element);
2874
2903
  this.textManage.updateText(this.element.data.topic);
2875
2904
  this.textManage.updateRectangle();
2876
2905
  }
@@ -2891,12 +2920,6 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2891
2920
  this.g.append(g);
2892
2921
  }
2893
2922
  }
2894
- drawImage() {
2895
- const image = this.imageDrawer.drawImage(this.element);
2896
- if (image) {
2897
- this.g.append(image);
2898
- }
2899
- }
2900
2923
  drawShape() {
2901
2924
  this.destroyShape();
2902
2925
  const shape = getShapeByElement(this.board, this.node.origin);
@@ -3161,11 +3184,11 @@ const withNodeDnd = (board) => {
3161
3184
  activeElements = [targetElement];
3162
3185
  startPoint = point;
3163
3186
  }
3164
- event.preventDefault();
3165
3187
  }
3166
3188
  if (activeElements.length) {
3167
- correspondingElements = getOverallAbstracts(board, activeElements);
3189
+ // prevent text from being selected
3168
3190
  event.preventDefault();
3191
+ correspondingElements = getOverallAbstracts(board, activeElements);
3169
3192
  }
3170
3193
  mousedown(event);
3171
3194
  };
@@ -3434,7 +3457,6 @@ const withAbstract = (board) => {
3434
3457
  const endPoint = transformPoint(board, toPoint(event.x, event.y, host));
3435
3458
  touchedAbstract = handleTouchedAbstract(board, touchedAbstract, endPoint);
3436
3459
  if (abstractHandlePosition && activeAbstractElement) {
3437
- event.preventDefault();
3438
3460
  const abstractComponent = PlaitElement.getComponent(activeAbstractElement);
3439
3461
  const element = abstractComponent.element;
3440
3462
  const nodeLayout = MindQueries.getCorrectLayoutByElement(board, activeAbstractElement);
@@ -3612,7 +3634,8 @@ const withCreateMind = (board) => {
3612
3634
  return newBoard;
3613
3635
  };
3614
3636
 
3615
- const withMindHotkey = (board) => {
3637
+ const withMindHotkey = (baseBoard) => {
3638
+ const board = baseBoard;
3616
3639
  const { keydown } = board;
3617
3640
  board.keydown = (event) => {
3618
3641
  const selectedElements = getSelectedElements(board);
@@ -3779,7 +3802,29 @@ const removeHovered = (element) => {
3779
3802
  }
3780
3803
  };
3781
3804
 
3782
- const withMindImage = (board) => {
3805
+ const BOARD_TO_SELECTED_IMAGE_ELEMENT = new WeakMap();
3806
+ const getSelectedImageElement = (board) => {
3807
+ return BOARD_TO_SELECTED_IMAGE_ELEMENT.get(board);
3808
+ };
3809
+ const addSelectedImageElement = (board, element) => {
3810
+ BOARD_TO_SELECTED_IMAGE_ELEMENT.set(board, element);
3811
+ };
3812
+ const removeSelectedImageElement = (board) => {
3813
+ BOARD_TO_SELECTED_IMAGE_ELEMENT.delete(board);
3814
+ };
3815
+ const setImageFocus = (board, element, isFocus) => {
3816
+ if (isFocus) {
3817
+ addSelectedImageElement(board, element);
3818
+ }
3819
+ else {
3820
+ removeSelectedImageElement(board);
3821
+ }
3822
+ const elementComponent = PlaitElement.getComponent(element);
3823
+ elementComponent.imageDrawer.componentRef.instance.isFocus = isFocus;
3824
+ elementComponent.imageDrawer.componentRef.instance.cdr.markForCheck();
3825
+ };
3826
+
3827
+ const withNodeImage = (board) => {
3783
3828
  let selectedImageElement = null;
3784
3829
  const { keydown, mousedown } = board;
3785
3830
  board.mousedown = (event) => {
@@ -3792,26 +3837,21 @@ const withMindImage = (board) => {
3792
3837
  const hitElements = getHitElements(board, { ranges: [range] });
3793
3838
  const hasImage = hitElements.length && MindElement.hasImage(hitElements[0]);
3794
3839
  const hitImage = hasImage && isHitImage(board, hitElements[0], range);
3840
+ if (selectedImageElement && hitImage && hitElements[0] === selectedImageElement) {
3841
+ temporaryDisableSelection(board);
3842
+ mousedown(event);
3843
+ return;
3844
+ }
3845
+ if (selectedImageElement) {
3846
+ setImageFocus(board, selectedImageElement, false);
3847
+ selectedImageElement = null;
3848
+ }
3795
3849
  if (hitImage) {
3796
- const currentOptions = board.getPluginOptions(PlaitPluginKey.withSelection);
3797
- board.setPluginOptions(PlaitPluginKey.withSelection, {
3798
- isDisabledSelect: true
3799
- });
3800
- setTimeout(() => {
3801
- board.setPluginOptions(PlaitPluginKey.withSelection, Object.assign({}, currentOptions));
3802
- }, 0);
3850
+ temporaryDisableSelection(board);
3803
3851
  selectedImageElement = hitElements[0];
3804
- const component = PlaitElement.getComponent(selectedImageElement);
3805
- component.imageDrawer.drawActive(selectedImageElement);
3852
+ setImageFocus(board, selectedImageElement, true);
3806
3853
  clearSelectedElement(board);
3807
3854
  }
3808
- else {
3809
- if (selectedImageElement) {
3810
- const component = PlaitElement.getComponent(selectedImageElement);
3811
- component && component.imageDrawer.destroyActive();
3812
- }
3813
- selectedImageElement = null;
3814
- }
3815
3855
  mousedown(event);
3816
3856
  };
3817
3857
  board.keydown = (event) => {
@@ -3825,6 +3865,119 @@ const withMindImage = (board) => {
3825
3865
  return board;
3826
3866
  };
3827
3867
 
3868
+ const withNodeResize = (board) => {
3869
+ const { mousedown, mousemove, globalMouseup } = board;
3870
+ let targetElement = null;
3871
+ let targetElementRef = null;
3872
+ let startPoint = null;
3873
+ board.mousedown = (event) => {
3874
+ if (targetElement) {
3875
+ startPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3876
+ // prevent text from being selected
3877
+ event.preventDefault();
3878
+ return;
3879
+ }
3880
+ mousedown(event);
3881
+ };
3882
+ board.mousemove = (event) => {
3883
+ if (PlaitBoard.isReadonly(board) || PlaitBoard.hasBeenTextEditing(board)) {
3884
+ mousemove(event);
3885
+ return;
3886
+ }
3887
+ if (startPoint && targetElement && !isMindNodeResizing(board)) {
3888
+ const endPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3889
+ const distance = distanceBetweenPointAndPoint(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
3890
+ if (distance > PRESS_AND_MOVE_BUFFER) {
3891
+ startPoint = endPoint;
3892
+ addResizing(board, targetElement);
3893
+ targetElementRef = {
3894
+ minWidth: NodeSpace.getNodeResizableMinWidth(board, targetElement),
3895
+ currentWidth: NodeSpace.getNodeResizableWidth(board, targetElement),
3896
+ path: PlaitBoard.findPath(board, targetElement),
3897
+ textManage: PlaitElement.getComponent(targetElement).textManage
3898
+ };
3899
+ MERGING.set(board, true);
3900
+ }
3901
+ }
3902
+ if (isMindNodeResizing(board) && startPoint && targetElementRef) {
3903
+ const endPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3904
+ const offsetX = endPoint[0] - startPoint[0];
3905
+ let resizedWidth = targetElementRef.currentWidth + offsetX;
3906
+ if (resizedWidth < targetElementRef.minWidth) {
3907
+ resizedWidth = targetElementRef.minWidth;
3908
+ }
3909
+ const newTarget = PlaitNode.get(board, targetElementRef.path);
3910
+ if (newTarget && NodeSpace.getNodeTopicMinWidth(board, newTarget) !== resizedWidth) {
3911
+ targetElementRef.textManage.updateWidth(resizedWidth);
3912
+ const { width, height } = targetElementRef.textManage.getSize();
3913
+ MindTransforms.setNodeManualWidth(board, newTarget, resizedWidth, height);
3914
+ }
3915
+ }
3916
+ else {
3917
+ // press and start drag when node is non selected
3918
+ if (!isDragging(board)) {
3919
+ const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3920
+ const newTargetElement = getTargetElement(board, point);
3921
+ if (newTargetElement) {
3922
+ PlaitBoard.getBoardContainer(board).classList.add(ResizeCursorClass['ew-resize']);
3923
+ }
3924
+ else {
3925
+ PlaitBoard.getBoardContainer(board).classList.remove(ResizeCursorClass['ew-resize']);
3926
+ }
3927
+ targetElement = newTargetElement;
3928
+ }
3929
+ }
3930
+ mousemove(event);
3931
+ };
3932
+ board.globalMouseup = (event) => {
3933
+ globalMouseup(event);
3934
+ if (isMindNodeResizing(board) && targetElement) {
3935
+ removeResizing(board, targetElement);
3936
+ targetElementRef = null;
3937
+ targetElement = null;
3938
+ startPoint = null;
3939
+ MERGING.set(board, false);
3940
+ }
3941
+ };
3942
+ return board;
3943
+ };
3944
+ const IS_MIND_NODE_RESIZING = new WeakMap();
3945
+ const isMindNodeResizing = (board) => {
3946
+ return !!IS_MIND_NODE_RESIZING.get(board);
3947
+ };
3948
+ const addResizing = (board, element) => {
3949
+ PlaitBoard.getBoardContainer(board).classList.add('mind-node-resizing');
3950
+ const component = PlaitElement.getComponent(element);
3951
+ component.g.classList.add('resizing');
3952
+ IS_MIND_NODE_RESIZING.set(board, true);
3953
+ };
3954
+ const removeResizing = (board, element) => {
3955
+ PlaitBoard.getBoardContainer(board).classList.remove('mind-node-resizing');
3956
+ PlaitBoard.getBoardContainer(board).classList.remove(ResizeCursorClass['ew-resize']);
3957
+ const component = PlaitElement.getComponent(element);
3958
+ if (component && component.g) {
3959
+ component.g.classList.remove('resizing');
3960
+ }
3961
+ IS_MIND_NODE_RESIZING.set(board, false);
3962
+ };
3963
+ const getTargetElement = (board, point) => {
3964
+ const selectedElements = getSelectedElements(board).filter(value => MindElement.isMindElement(board, value));
3965
+ if (selectedElements.length > 0) {
3966
+ const target = selectedElements.find(value => {
3967
+ const rectangle = getResizeActiveRectangle(board, value);
3968
+ return distanceBetweenPointAndRectangle(point[0], point[1], rectangle) <= 0;
3969
+ });
3970
+ return target ? target : null;
3971
+ }
3972
+ return null;
3973
+ };
3974
+ const getResizeActiveRectangle = (board, element) => {
3975
+ const activeWidth = 20;
3976
+ const node = MindElement.getNode(element);
3977
+ const rectangle = getRectangleByNode(node);
3978
+ return { x: rectangle.x + rectangle.width - activeWidth / 2, y: rectangle.y, width: activeWidth, height: rectangle.height };
3979
+ };
3980
+
3828
3981
  const withMind = (baseBoard) => {
3829
3982
  const board = baseBoard;
3830
3983
  const { drawElement, dblclick, insertFragment, setFragment, deleteFragment, isHitSelection, getRectangle, isMovable, isRecursion } = board;
@@ -3930,7 +4083,7 @@ const withMind = (baseBoard) => {
3930
4083
  MindTransforms.removeElements(board, selectedElements);
3931
4084
  deleteFragment(data);
3932
4085
  };
3933
- return withMindImage(withNodeHover(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board)))))));
4086
+ return withNodeResize(withNodeImage(withNodeHover(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board))))))));
3934
4087
  };
3935
4088
 
3936
4089
  class MindEmojiBaseComponent {
@@ -3984,5 +4137,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
3984
4137
  * Generated bundle index. Do not edit.
3985
4138
  */
3986
4139
 
3987
- 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, 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, 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, separateChildren, setIsDragging, withMind, withMindExtend };
4140
+ 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, 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, 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, separateChildren, setIsDragging, temporaryDisableSelection, withMind, withMindExtend };
3988
4141
  //# sourceMappingURL=plait-mind.mjs.map