@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';
@@ -220,11 +220,11 @@ const BRANCH_FONT_FAMILY = 'PingFangSC-Medium, "PingFang SC"';
220
220
 
221
221
  const NodeDefaultSpace = {
222
222
  horizontal: {
223
- nodeAndText: BASE * 3,
223
+ nodeAndText: BASE * 2.5,
224
224
  emojiAndText: BASE * 1.5
225
225
  },
226
226
  vertical: {
227
- nodeAndText: BASE * 1.5,
227
+ nodeAndText: BASE,
228
228
  nodeAndImage: BASE,
229
229
  imageAndText: BASE * 1.5
230
230
  }
@@ -241,12 +241,14 @@ const RootDefaultSpace = {
241
241
  const getHorizontalSpaceBetweenNodeAndText = (board, element) => {
242
242
  const isMind = PlaitMind.isMind(element);
243
243
  const nodeAndText = isMind ? RootDefaultSpace.horizontal.nodeAndText : NodeDefaultSpace.horizontal.nodeAndText;
244
- return nodeAndText;
244
+ const strokeWidth = getStrokeWidthByElement(board, element);
245
+ return nodeAndText + strokeWidth / 2;
245
246
  };
246
- const getVerticalSpaceBetweenNodeAndText = (element) => {
247
+ const getVerticalSpaceBetweenNodeAndText = (board, element) => {
247
248
  const isMind = PlaitMind.isMind(element);
249
+ const strokeWidth = getStrokeWidthByElement(board, element);
248
250
  const nodeAndText = isMind ? RootDefaultSpace.vertical.nodeAndText : NodeDefaultSpace.vertical.nodeAndText;
249
- return nodeAndText;
251
+ return nodeAndText + strokeWidth / 2;
250
252
  };
251
253
  const getSpaceEmojiAndText = (element) => {
252
254
  const isMind = PlaitMind.isMind(element);
@@ -266,19 +268,16 @@ const NodeSpace = {
266
268
  return nodeAndText + NodeSpace.getNodeResizableWidth(board, element) + nodeAndText;
267
269
  },
268
270
  getNodeHeight(board, element) {
269
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
271
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
270
272
  if (MindElement.hasImage(element)) {
271
- return (NodeDefaultSpace.vertical.nodeAndImage +
272
- element.data.image.height +
273
- NodeDefaultSpace.vertical.imageAndText +
274
- element.height +
275
- nodeAndText);
273
+ return NodeSpace.getTextTopSpace(board, element) + element.height + nodeAndText;
276
274
  }
277
275
  return nodeAndText + element.height + nodeAndText;
278
276
  },
279
277
  getNodeResizableWidth(board, element) {
278
+ const width = element.manualWidth || element.width;
280
279
  const imageWidth = MindElement.hasImage(element) ? element.data.image?.width : 0;
281
- return Math.max(element.width, imageWidth);
280
+ return Math.max(width, imageWidth);
282
281
  },
283
282
  getNodeResizableMinWidth(board, element) {
284
283
  const minTopicWidth = NodeSpace.getNodeTopicMinWidth(board, element);
@@ -305,25 +304,27 @@ const NodeSpace = {
305
304
  return nodeAndText;
306
305
  }
307
306
  },
308
- getTextTopSpace(element) {
309
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
307
+ getTextTopSpace(board, element) {
308
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
310
309
  if (MindElement.hasImage(element)) {
311
- return element.data.image.height + NodeDefaultSpace.vertical.nodeAndImage + NodeDefaultSpace.vertical.imageAndText;
310
+ return NodeSpace.getImageTopSpace(board, element) + element.data.image.height + NodeDefaultSpace.vertical.imageAndText;
312
311
  }
313
312
  else {
314
313
  return nodeAndText;
315
314
  }
316
315
  },
317
- getImageTopSpace(element) {
318
- return NodeDefaultSpace.vertical.nodeAndImage;
316
+ getImageTopSpace(board, element) {
317
+ const strokeWidth = getStrokeWidthByElement(board, element);
318
+ return strokeWidth / 2 + NodeDefaultSpace.vertical.nodeAndImage;
319
319
  },
320
320
  getEmojiLeftSpace(board, element) {
321
321
  const options = board.getPluginOptions(WithMindPluginKey);
322
322
  const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
323
- return nodeAndText - options.emojiPadding;
323
+ const strokeWidth = getStrokeWidthByElement(board, element);
324
+ return strokeWidth / 2 + nodeAndText - options.emojiPadding;
324
325
  },
325
- getEmojiTopSpace(element) {
326
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
326
+ getEmojiTopSpace(board, element) {
327
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
327
328
  return nodeAndText;
328
329
  }
329
330
  };
@@ -376,23 +377,28 @@ function getTopicRectangleByNode(board, node) {
376
377
  }
377
378
  function getTopicRectangleByElement(board, nodeRectangle, element) {
378
379
  const x = nodeRectangle.x + NodeSpace.getTextLeftSpace(board, element);
379
- const y = nodeRectangle.y + NodeSpace.getTextTopSpace(element);
380
- const width = Math.ceil(element.width);
380
+ const y = nodeRectangle.y + NodeSpace.getTextTopSpace(board, element);
381
+ const width = NodeSpace.getNodeResizableWidth(board, element);
381
382
  const height = Math.ceil(element.height);
382
383
  return { height, width, x, y };
383
384
  }
384
385
 
385
386
  function getImageForeignRectangle(board, element) {
386
387
  let { x, y } = getRectangleByNode(MindElement.getNode(element));
387
- x = x + NodeSpace.getTextLeftSpace(board, element);
388
- y = NodeSpace.getImageTopSpace(element) + y;
388
+ const elementWidth = element.manualWidth || element.width;
389
+ x =
390
+ elementWidth > element.data.image.width
391
+ ? x + NodeSpace.getTextLeftSpace(board, element) + (elementWidth - element.data.image.width) / 2
392
+ : x + NodeSpace.getTextLeftSpace(board, element);
393
+ y = NodeSpace.getImageTopSpace(board, element) + y;
389
394
  const { width, height } = element.data.image;
390
- return {
395
+ const rectangle = {
391
396
  x,
392
397
  y,
393
398
  width,
394
399
  height
395
400
  };
401
+ return RectangleClient.getOutlineRectangle(rectangle, -6);
396
402
  }
397
403
  const isHitImage = (board, element, range) => {
398
404
  const client = getImageForeignRectangle(board, element);
@@ -403,6 +409,15 @@ function editTopic(element) {
403
409
  const component = PlaitElement.getComponent(element);
404
410
  component?.editTopic();
405
411
  }
412
+ const temporaryDisableSelection = (board) => {
413
+ const currentOptions = board.getPluginOptions(PlaitPluginKey.withSelection);
414
+ board.setPluginOptions(PlaitPluginKey.withSelection, {
415
+ isDisabledSelect: true
416
+ });
417
+ setTimeout(() => {
418
+ board.setPluginOptions(PlaitPluginKey.withSelection, { ...currentOptions });
419
+ }, 0);
420
+ };
406
421
 
407
422
  const createEmptyMind = (point) => {
408
423
  const element = createMindElement('思维导图', 72, ROOT_TOPIC_HEIGHT, { layout: MindLayoutType.right });
@@ -2302,11 +2317,22 @@ const setTopic = (board, element, topic, width, height) => {
2302
2317
  const path = PlaitBoard.findPath(board, element);
2303
2318
  Transforms.setNode(board, newElement, path);
2304
2319
  };
2320
+ const setNodeManualWidth = (board, element, width, height) => {
2321
+ const path = PlaitBoard.findPath(board, element);
2322
+ const { width: normalizedWidth, height: normalizedHeight } = normalizeWidthAndHeight(board, element, width, height);
2323
+ const newElement = { manualWidth: normalizedWidth, height: normalizedHeight };
2324
+ Transforms.setNode(board, newElement, path);
2325
+ };
2305
2326
  const setTopicSize = (board, element, width, height) => {
2306
2327
  const newElement = {
2307
2328
  ...normalizeWidthAndHeight(board, element, width, height)
2308
2329
  };
2309
- if (Math.floor(element.width) !== Math.floor(newElement.width) || Math.floor(element.height) !== Math.floor(newElement.height)) {
2330
+ let isEqualWidth = Math.ceil(element.width) === Math.ceil(newElement.width);
2331
+ let isEqualHeight = Math.ceil(element.height) === Math.ceil(newElement.height);
2332
+ if (element.manualWidth) {
2333
+ isEqualWidth = true;
2334
+ }
2335
+ if (!isEqualWidth || !isEqualHeight) {
2310
2336
  const path = PlaitBoard.findPath(board, element);
2311
2337
  Transforms.setNode(board, newElement, path);
2312
2338
  }
@@ -2403,6 +2429,7 @@ const MindTransforms = {
2403
2429
  setLayout,
2404
2430
  setTopic,
2405
2431
  setTopicSize,
2432
+ setNodeManualWidth,
2406
2433
  addEmoji,
2407
2434
  removeEmoji,
2408
2435
  replaceEmoji,
@@ -2777,13 +2804,15 @@ class MindImageBaseComponent {
2777
2804
  get nativeElement() {
2778
2805
  return this.elementRef.nativeElement;
2779
2806
  }
2780
- constructor(elementRef) {
2807
+ constructor(elementRef, cdr) {
2781
2808
  this.elementRef = elementRef;
2809
+ this.cdr = cdr;
2810
+ this.isFocus = false;
2782
2811
  }
2783
2812
  ngOnInit() { }
2784
2813
  }
2785
- MindImageBaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindImageBaseComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
2786
- 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 });
2814
+ 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 });
2815
+ 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 });
2787
2816
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindImageBaseComponent, decorators: [{
2788
2817
  type: Directive,
2789
2818
  args: [{
@@ -2791,12 +2820,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
2791
2820
  class: 'mind-node-image'
2792
2821
  }
2793
2822
  }]
2794
- }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { imageItem: [{
2823
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { imageItem: [{
2795
2824
  type: Input
2796
2825
  }], board: [{
2797
2826
  type: Input
2798
2827
  }], element: [{
2799
2828
  type: Input
2829
+ }], isFocus: [{
2830
+ type: Input
2800
2831
  }] } });
2801
2832
 
2802
2833
  class NodeImageDrawer {
@@ -2805,44 +2836,39 @@ class NodeImageDrawer {
2805
2836
  this.viewContainerRef = viewContainerRef;
2806
2837
  this.componentRef = null;
2807
2838
  }
2808
- drawImage(element) {
2809
- this.destroy();
2810
- if (MindElement.hasImage(element)) {
2811
- this.g = createG();
2812
- const foreignRectangle = getImageForeignRectangle(this.board, element);
2813
- const foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
2814
- this.g.append(foreignObject);
2815
- if (this.componentRef) {
2816
- this.componentRef.destroy();
2817
- this.componentRef = null;
2818
- }
2819
- const componentType = this.board.getPluginOptions(WithMindPluginKey).imageComponentType || MindImageBaseComponent;
2820
- if (!componentType) {
2821
- throw new Error('Not implement drawEmoji method error.');
2822
- }
2823
- this.componentRef = this.viewContainerRef.createComponent(componentType);
2824
- this.componentRef.instance.board = this.board;
2825
- this.componentRef.instance.element = element;
2826
- this.componentRef.instance.imageItem = element.data.image;
2827
- foreignObject.append(this.componentRef.instance.nativeElement);
2828
- return this.g;
2839
+ drawImage(nodeG, element) {
2840
+ if (!MindElement.hasImage(element)) {
2841
+ this.destroy();
2842
+ return;
2829
2843
  }
2830
- return undefined;
2831
- }
2832
- drawActive(element) {
2833
- this.destroyActive();
2834
- const imageRectangle = getImageForeignRectangle(this.board, element);
2835
- const rectangle = RectangleClient.getOutlineRectangle(imageRectangle, -1);
2836
- const roughSVG = PlaitBoard.getRoughSVG(this.board);
2837
- this.activeG = roughSVG.rectangle(rectangle.x, rectangle.y, rectangle.width, rectangle.height, {
2838
- stroke: PRIMARY_COLOR,
2839
- fill: '',
2840
- fillStyle: 'solid'
2841
- });
2842
- this.g?.append(this.activeG);
2843
- }
2844
- destroyActive() {
2845
- this.activeG?.remove();
2844
+ this.g = createG();
2845
+ const foreignRectangle = getImageForeignRectangle(this.board, element);
2846
+ const foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
2847
+ this.g.append(foreignObject);
2848
+ const componentType = this.board.getPluginOptions(WithMindPluginKey).imageComponentType || MindImageBaseComponent;
2849
+ if (!componentType) {
2850
+ throw new Error('Not implement drawEmoji method error.');
2851
+ }
2852
+ this.componentRef = this.viewContainerRef.createComponent(componentType);
2853
+ this.componentRef.instance.board = this.board;
2854
+ this.componentRef.instance.element = element;
2855
+ this.componentRef.instance.imageItem = element.data.image;
2856
+ this.componentRef.instance.cdr.markForCheck();
2857
+ foreignObject.append(this.componentRef.instance.nativeElement);
2858
+ nodeG.appendChild(this.g);
2859
+ }
2860
+ updateImage(nodeG, previous, current) {
2861
+ if (!MindElement.hasImage(previous) || !MindElement.hasImage(current)) {
2862
+ this.drawImage(nodeG, current);
2863
+ return;
2864
+ }
2865
+ if (previous !== current && this.componentRef) {
2866
+ this.componentRef.instance.element = current;
2867
+ this.componentRef.instance.imageItem = current.data.image;
2868
+ }
2869
+ const currentForeignObject = getImageForeignRectangle(this.board, current);
2870
+ updateForeignObject(this.g, currentForeignObject.width, currentForeignObject.height, currentForeignObject.x, currentForeignObject.y);
2871
+ this.componentRef?.instance.cdr.markForCheck();
2846
2872
  }
2847
2873
  destroy() {
2848
2874
  if (this.g) {
@@ -2905,13 +2931,17 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2905
2931
  this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: this.textManage.isEditing });
2906
2932
  this.drawEmojis();
2907
2933
  this.drawExtend();
2908
- this.drawImage();
2934
+ this.imageDrawer.drawImage(this.g, this.element);
2909
2935
  if (PlaitMind.isMind(this.context.parent)) {
2910
2936
  this.g.classList.add('branch');
2911
2937
  }
2912
2938
  }
2913
2939
  editTopic() {
2914
2940
  this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: true });
2941
+ if (this.element.manualWidth) {
2942
+ const width = NodeSpace.getNodeResizableWidth(this.board, this.element);
2943
+ this.textManage.updateWidth(width);
2944
+ }
2915
2945
  this.textManage.edit((origin) => {
2916
2946
  if (origin === ExitOrigin.default) {
2917
2947
  this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: false });
@@ -2928,8 +2958,8 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2928
2958
  this.drawShape();
2929
2959
  this.drawLink();
2930
2960
  this.drawEmojis();
2931
- this.drawImage();
2932
2961
  this.drawExtend();
2962
+ this.imageDrawer.updateImage(this.g, previous.element, value.element);
2933
2963
  this.textManage.updateText(this.element.data.topic);
2934
2964
  this.textManage.updateRectangle();
2935
2965
  }
@@ -2950,12 +2980,6 @@ class MindNodeComponent extends PlaitPluginElementComponent {
2950
2980
  this.g.append(g);
2951
2981
  }
2952
2982
  }
2953
- drawImage() {
2954
- const image = this.imageDrawer.drawImage(this.element);
2955
- if (image) {
2956
- this.g.append(image);
2957
- }
2958
- }
2959
2983
  drawShape() {
2960
2984
  this.destroyShape();
2961
2985
  const shape = getShapeByElement(this.board, this.node.origin);
@@ -3220,11 +3244,11 @@ const withNodeDnd = (board) => {
3220
3244
  activeElements = [targetElement];
3221
3245
  startPoint = point;
3222
3246
  }
3223
- event.preventDefault();
3224
3247
  }
3225
3248
  if (activeElements.length) {
3226
- correspondingElements = getOverallAbstracts(board, activeElements);
3249
+ // prevent text from being selected
3227
3250
  event.preventDefault();
3251
+ correspondingElements = getOverallAbstracts(board, activeElements);
3228
3252
  }
3229
3253
  mousedown(event);
3230
3254
  };
@@ -3499,7 +3523,6 @@ const withAbstract = (board) => {
3499
3523
  const endPoint = transformPoint(board, toPoint(event.x, event.y, host));
3500
3524
  touchedAbstract = handleTouchedAbstract(board, touchedAbstract, endPoint);
3501
3525
  if (abstractHandlePosition && activeAbstractElement) {
3502
- event.preventDefault();
3503
3526
  const abstractComponent = PlaitElement.getComponent(activeAbstractElement);
3504
3527
  const element = abstractComponent.element;
3505
3528
  const nodeLayout = MindQueries.getCorrectLayoutByElement(board, activeAbstractElement);
@@ -3677,7 +3700,8 @@ const withCreateMind = (board) => {
3677
3700
  return newBoard;
3678
3701
  };
3679
3702
 
3680
- const withMindHotkey = (board) => {
3703
+ const withMindHotkey = (baseBoard) => {
3704
+ const board = baseBoard;
3681
3705
  const { keydown } = board;
3682
3706
  board.keydown = (event) => {
3683
3707
  const selectedElements = getSelectedElements(board);
@@ -3844,7 +3868,29 @@ const removeHovered = (element) => {
3844
3868
  }
3845
3869
  };
3846
3870
 
3847
- const withMindImage = (board) => {
3871
+ const BOARD_TO_SELECTED_IMAGE_ELEMENT = new WeakMap();
3872
+ const getSelectedImageElement = (board) => {
3873
+ return BOARD_TO_SELECTED_IMAGE_ELEMENT.get(board);
3874
+ };
3875
+ const addSelectedImageElement = (board, element) => {
3876
+ BOARD_TO_SELECTED_IMAGE_ELEMENT.set(board, element);
3877
+ };
3878
+ const removeSelectedImageElement = (board) => {
3879
+ BOARD_TO_SELECTED_IMAGE_ELEMENT.delete(board);
3880
+ };
3881
+ const setImageFocus = (board, element, isFocus) => {
3882
+ if (isFocus) {
3883
+ addSelectedImageElement(board, element);
3884
+ }
3885
+ else {
3886
+ removeSelectedImageElement(board);
3887
+ }
3888
+ const elementComponent = PlaitElement.getComponent(element);
3889
+ elementComponent.imageDrawer.componentRef.instance.isFocus = isFocus;
3890
+ elementComponent.imageDrawer.componentRef.instance.cdr.markForCheck();
3891
+ };
3892
+
3893
+ const withNodeImage = (board) => {
3848
3894
  let selectedImageElement = null;
3849
3895
  const { keydown, mousedown } = board;
3850
3896
  board.mousedown = (event) => {
@@ -3857,26 +3903,21 @@ const withMindImage = (board) => {
3857
3903
  const hitElements = getHitElements(board, { ranges: [range] });
3858
3904
  const hasImage = hitElements.length && MindElement.hasImage(hitElements[0]);
3859
3905
  const hitImage = hasImage && isHitImage(board, hitElements[0], range);
3906
+ if (selectedImageElement && hitImage && hitElements[0] === selectedImageElement) {
3907
+ temporaryDisableSelection(board);
3908
+ mousedown(event);
3909
+ return;
3910
+ }
3911
+ if (selectedImageElement) {
3912
+ setImageFocus(board, selectedImageElement, false);
3913
+ selectedImageElement = null;
3914
+ }
3860
3915
  if (hitImage) {
3861
- const currentOptions = board.getPluginOptions(PlaitPluginKey.withSelection);
3862
- board.setPluginOptions(PlaitPluginKey.withSelection, {
3863
- isDisabledSelect: true
3864
- });
3865
- setTimeout(() => {
3866
- board.setPluginOptions(PlaitPluginKey.withSelection, { ...currentOptions });
3867
- }, 0);
3916
+ temporaryDisableSelection(board);
3868
3917
  selectedImageElement = hitElements[0];
3869
- const component = PlaitElement.getComponent(selectedImageElement);
3870
- component.imageDrawer.drawActive(selectedImageElement);
3918
+ setImageFocus(board, selectedImageElement, true);
3871
3919
  clearSelectedElement(board);
3872
3920
  }
3873
- else {
3874
- if (selectedImageElement) {
3875
- const component = PlaitElement.getComponent(selectedImageElement);
3876
- component && component.imageDrawer.destroyActive();
3877
- }
3878
- selectedImageElement = null;
3879
- }
3880
3921
  mousedown(event);
3881
3922
  };
3882
3923
  board.keydown = (event) => {
@@ -3890,6 +3931,119 @@ const withMindImage = (board) => {
3890
3931
  return board;
3891
3932
  };
3892
3933
 
3934
+ const withNodeResize = (board) => {
3935
+ const { mousedown, mousemove, globalMouseup } = board;
3936
+ let targetElement = null;
3937
+ let targetElementRef = null;
3938
+ let startPoint = null;
3939
+ board.mousedown = (event) => {
3940
+ if (targetElement) {
3941
+ startPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3942
+ // prevent text from being selected
3943
+ event.preventDefault();
3944
+ return;
3945
+ }
3946
+ mousedown(event);
3947
+ };
3948
+ board.mousemove = (event) => {
3949
+ if (PlaitBoard.isReadonly(board) || PlaitBoard.hasBeenTextEditing(board)) {
3950
+ mousemove(event);
3951
+ return;
3952
+ }
3953
+ if (startPoint && targetElement && !isMindNodeResizing(board)) {
3954
+ const endPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3955
+ const distance = distanceBetweenPointAndPoint(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
3956
+ if (distance > PRESS_AND_MOVE_BUFFER) {
3957
+ startPoint = endPoint;
3958
+ addResizing(board, targetElement);
3959
+ targetElementRef = {
3960
+ minWidth: NodeSpace.getNodeResizableMinWidth(board, targetElement),
3961
+ currentWidth: NodeSpace.getNodeResizableWidth(board, targetElement),
3962
+ path: PlaitBoard.findPath(board, targetElement),
3963
+ textManage: PlaitElement.getComponent(targetElement).textManage
3964
+ };
3965
+ MERGING.set(board, true);
3966
+ }
3967
+ }
3968
+ if (isMindNodeResizing(board) && startPoint && targetElementRef) {
3969
+ const endPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3970
+ const offsetX = endPoint[0] - startPoint[0];
3971
+ let resizedWidth = targetElementRef.currentWidth + offsetX;
3972
+ if (resizedWidth < targetElementRef.minWidth) {
3973
+ resizedWidth = targetElementRef.minWidth;
3974
+ }
3975
+ const newTarget = PlaitNode.get(board, targetElementRef.path);
3976
+ if (newTarget && NodeSpace.getNodeTopicMinWidth(board, newTarget) !== resizedWidth) {
3977
+ targetElementRef.textManage.updateWidth(resizedWidth);
3978
+ const { width, height } = targetElementRef.textManage.getSize();
3979
+ MindTransforms.setNodeManualWidth(board, newTarget, resizedWidth, height);
3980
+ }
3981
+ }
3982
+ else {
3983
+ // press and start drag when node is non selected
3984
+ if (!isDragging(board)) {
3985
+ const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3986
+ const newTargetElement = getTargetElement(board, point);
3987
+ if (newTargetElement) {
3988
+ PlaitBoard.getBoardContainer(board).classList.add(ResizeCursorClass['ew-resize']);
3989
+ }
3990
+ else {
3991
+ PlaitBoard.getBoardContainer(board).classList.remove(ResizeCursorClass['ew-resize']);
3992
+ }
3993
+ targetElement = newTargetElement;
3994
+ }
3995
+ }
3996
+ mousemove(event);
3997
+ };
3998
+ board.globalMouseup = (event) => {
3999
+ globalMouseup(event);
4000
+ if (isMindNodeResizing(board) && targetElement) {
4001
+ removeResizing(board, targetElement);
4002
+ targetElementRef = null;
4003
+ targetElement = null;
4004
+ startPoint = null;
4005
+ MERGING.set(board, false);
4006
+ }
4007
+ };
4008
+ return board;
4009
+ };
4010
+ const IS_MIND_NODE_RESIZING = new WeakMap();
4011
+ const isMindNodeResizing = (board) => {
4012
+ return !!IS_MIND_NODE_RESIZING.get(board);
4013
+ };
4014
+ const addResizing = (board, element) => {
4015
+ PlaitBoard.getBoardContainer(board).classList.add('mind-node-resizing');
4016
+ const component = PlaitElement.getComponent(element);
4017
+ component.g.classList.add('resizing');
4018
+ IS_MIND_NODE_RESIZING.set(board, true);
4019
+ };
4020
+ const removeResizing = (board, element) => {
4021
+ PlaitBoard.getBoardContainer(board).classList.remove('mind-node-resizing');
4022
+ PlaitBoard.getBoardContainer(board).classList.remove(ResizeCursorClass['ew-resize']);
4023
+ const component = PlaitElement.getComponent(element);
4024
+ if (component && component.g) {
4025
+ component.g.classList.remove('resizing');
4026
+ }
4027
+ IS_MIND_NODE_RESIZING.set(board, false);
4028
+ };
4029
+ const getTargetElement = (board, point) => {
4030
+ const selectedElements = getSelectedElements(board).filter(value => MindElement.isMindElement(board, value));
4031
+ if (selectedElements.length > 0) {
4032
+ const target = selectedElements.find(value => {
4033
+ const rectangle = getResizeActiveRectangle(board, value);
4034
+ return distanceBetweenPointAndRectangle(point[0], point[1], rectangle) <= 0;
4035
+ });
4036
+ return target ? target : null;
4037
+ }
4038
+ return null;
4039
+ };
4040
+ const getResizeActiveRectangle = (board, element) => {
4041
+ const activeWidth = 20;
4042
+ const node = MindElement.getNode(element);
4043
+ const rectangle = getRectangleByNode(node);
4044
+ return { x: rectangle.x + rectangle.width - activeWidth / 2, y: rectangle.y, width: activeWidth, height: rectangle.height };
4045
+ };
4046
+
3893
4047
  const withMind = (baseBoard) => {
3894
4048
  const board = baseBoard;
3895
4049
  const { drawElement, dblclick, insertFragment, setFragment, deleteFragment, isHitSelection, getRectangle, isMovable, isRecursion } = board;
@@ -3995,7 +4149,7 @@ const withMind = (baseBoard) => {
3995
4149
  MindTransforms.removeElements(board, selectedElements);
3996
4150
  deleteFragment(data);
3997
4151
  };
3998
- return withMindImage(withNodeHover(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board)))))));
4152
+ return withNodeResize(withNodeImage(withNodeHover(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board))))))));
3999
4153
  };
4000
4154
 
4001
4155
  class MindEmojiBaseComponent {
@@ -4049,5 +4203,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
4049
4203
  * Generated bundle index. Do not edit.
4050
4204
  */
4051
4205
 
4052
- 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 };
4206
+ 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 };
4053
4207
  //# sourceMappingURL=plait-mind.mjs.map