@plait/mind 0.26.0 → 0.27.0-next.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.
@@ -1,10 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
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, 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, CLIP_BOARD_IMAGE_FORMAT_KEY, BOARD_TO_HOST, throttleRAF, BoardTransforms, removeSelectedElement, PlaitHistoryBoard, hotkeys, PRESS_AND_MOVE_BUFFER, MERGING, ResizeCursorClass } from '@plait/core';
4
+ import { DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, RectangleClient, PlaitElement, PlaitPluginKey, getSelectedElements, idCreator, isNullOrUndefined, Transforms, clearSelectedElement, addSelectedElement, PlaitBoard, Path, PlaitNode, PlaitContextService, depthFirstRecursion, getIsRecursionFunc, drawLinearPath, drawBezierPath, createG, updateForeignObject, drawRoundRectangle, getRectangleByElements, NODE_TO_PARENT, distanceBetweenPointAndRectangle, createForeignObject, createText, PlaitPointerType, PlaitPluginElementComponent, NODE_TO_INDEX, PlaitModule, isMainPointer, transformPoint, toPoint, getHitElements, distanceBetweenPointAndPoint, setClipboardData, setClipboardDataByText, BOARD_TO_HOST, throttleRAF, BoardTransforms, removeSelectedElement, PlaitHistoryBoard, hotkeys, setClipboardDataByMedia, getClipboardDataByMedia, ResizeCursorClass, preventTouchMove, PRESS_AND_MOVE_BUFFER, MERGING, getDataFromClipboard } from '@plait/core';
5
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
+ import { RESIZE_HANDLE_DIAMETER, getRectangleResizeTargets, MediaKeys, ResizeDirection, withResize, ActiveGenerator } from '@plait/common';
8
9
  import { Node as Node$1, Path as Path$1 } from 'slate';
9
10
  import { isKeyHotkey } from 'is-hotkey';
10
11
  import { pointsOnBezierCurves } from 'points-on-curve';
@@ -409,11 +410,20 @@ function getImageForeignRectangle(board, element) {
409
410
  width,
410
411
  height
411
412
  };
412
- return RectangleClient.getOutlineRectangle(rectangle, -6);
413
+ return rectangle;
413
414
  }
414
415
  const isHitImage = (board, element, range) => {
415
- const client = getImageForeignRectangle(board, element);
416
- return RectangleClient.isHit(RectangleClient.toRectangleClient([range.anchor, range.focus]), client);
416
+ const imageRectangle = getImageForeignRectangle(board, element);
417
+ const imageOutlineRectangle = RectangleClient.getOutlineRectangle(imageRectangle, -RESIZE_HANDLE_DIAMETER / 2);
418
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([range.anchor, range.focus]), imageOutlineRectangle);
419
+ };
420
+ const getHitImageResizeHandleDirection = (board, element, point) => {
421
+ const imageRectangle = getImageForeignRectangle(board, element);
422
+ const resizeTargets = getRectangleResizeTargets(imageRectangle, RESIZE_HANDLE_DIAMETER);
423
+ const result = resizeTargets.find(resizeTarget => {
424
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), resizeTarget.rectangle);
425
+ });
426
+ return result;
417
427
  };
418
428
 
419
429
  function editTopic(element) {
@@ -429,6 +439,10 @@ const temporaryDisableSelection = (board) => {
429
439
  board.setPluginOptions(PlaitPluginKey.withSelection, { ...currentOptions });
430
440
  }, 0);
431
441
  };
442
+ const getSelectedMindElements = (board) => {
443
+ const selectedElements = getSelectedElements(board).filter(value => MindElement.isMindElement(board, value));
444
+ return selectedElements;
445
+ };
432
446
 
433
447
  const createEmptyMind = (point) => {
434
448
  const element = createMindElement('思维导图', 72, ROOT_TOPIC_HEIGHT, { layout: MindLayoutType.right });
@@ -2373,9 +2387,7 @@ const MindElement = {
2373
2387
  return isIndentedLayout(_layout);
2374
2388
  },
2375
2389
  isMindElement(board, element) {
2376
- const path = PlaitBoard.findPath(board, element);
2377
- const rootElement = PlaitNode.get(board, path.slice(0, 1));
2378
- if (PlaitMind.isMind(rootElement)) {
2390
+ if (element.data && element.data.topic && element.width && element.height) {
2379
2391
  return true;
2380
2392
  }
2381
2393
  else {
@@ -3002,7 +3014,6 @@ class NodeImageDrawer {
3002
3014
  this.g = createG();
3003
3015
  const foreignRectangle = getImageForeignRectangle(this.board, element);
3004
3016
  this.foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
3005
- this.foreignObject.style.padding = `6px`;
3006
3017
  this.g.append(this.foreignObject);
3007
3018
  const componentType = this.board.getPluginOptions(WithMindPluginKey).imageComponentType;
3008
3019
  if (!componentType) {
@@ -3065,19 +3076,23 @@ class MindNodeComponent extends PlaitPluginElementComponent {
3065
3076
  this.collapseDrawer = new CollapseDrawer(this.board);
3066
3077
  this.imageDrawer = new NodeImageDrawer(this.board, this.viewContainerRef);
3067
3078
  const plugins = this.board.getPluginOptions(WithMindPluginKey).textPlugins;
3068
- this.textManage = new TextManage(this.board, this.viewContainerRef, () => {
3069
- const rect = getTopicRectangleByNode(this.board, this.node);
3070
- return rect;
3071
- }, (textManageRef) => {
3072
- const width = textManageRef.width;
3073
- const height = textManageRef.height;
3074
- if (textManageRef.newValue) {
3075
- MindTransforms.setTopic(this.board, this.element, textManageRef.newValue, width, height);
3076
- }
3077
- else {
3078
- MindTransforms.setTopicSize(this.board, this.element, width, height);
3079
- }
3080
- }, plugins);
3079
+ this.textManage = new TextManage(this.board, this.viewContainerRef, {
3080
+ getRectangle: () => {
3081
+ const rect = getTopicRectangleByNode(this.board, this.node);
3082
+ return rect;
3083
+ },
3084
+ onValueChangeHandle: (textManageRef) => {
3085
+ const width = textManageRef.width;
3086
+ const height = textManageRef.height;
3087
+ if (textManageRef.newValue) {
3088
+ MindTransforms.setTopic(this.board, this.element, textManageRef.newValue, width, height);
3089
+ }
3090
+ else {
3091
+ MindTransforms.setTopicSize(this.board, this.element, width, height);
3092
+ }
3093
+ },
3094
+ textPlugins: plugins
3095
+ });
3081
3096
  }
3082
3097
  ngOnInit() {
3083
3098
  super.ngOnInit();
@@ -3320,7 +3335,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
3320
3335
 
3321
3336
  const DRAG_MOVE_BUFFER = 5;
3322
3337
  const withNodeDnd = (board) => {
3323
- const { mousedown, mousemove, globalMouseup } = board;
3338
+ const { pointerDown, pointerMove, globalPointerUp } = board;
3324
3339
  let activeElements = [];
3325
3340
  let correspondingElements = [];
3326
3341
  let startPoint;
@@ -3328,12 +3343,12 @@ const withNodeDnd = (board) => {
3328
3343
  let fakeDropNodeG;
3329
3344
  let dropTarget = null;
3330
3345
  let targetPath;
3331
- board.mousedown = (event) => {
3346
+ board.pointerDown = (event) => {
3332
3347
  if (PlaitBoard.isReadonly(board) ||
3333
3348
  PlaitBoard.hasBeenTextEditing(board) ||
3334
3349
  !PlaitBoard.isPointer(board, PlaitPointerType.selection) ||
3335
3350
  !isMainPointer(event)) {
3336
- mousedown(event);
3351
+ pointerDown(event);
3337
3352
  return;
3338
3353
  }
3339
3354
  const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
@@ -3360,9 +3375,9 @@ const withNodeDnd = (board) => {
3360
3375
  if (activeElements.length) {
3361
3376
  correspondingElements = getOverallAbstracts(board, activeElements);
3362
3377
  }
3363
- mousedown(event);
3378
+ pointerDown(event);
3364
3379
  };
3365
- board.mousemove = (event) => {
3380
+ board.pointerMove = (event) => {
3366
3381
  if (!board.options.readonly && activeElements?.length && startPoint) {
3367
3382
  // prevent text from being selected
3368
3383
  event.preventDefault();
@@ -3393,9 +3408,9 @@ const withNodeDnd = (board) => {
3393
3408
  });
3394
3409
  PlaitBoard.getHost(board).appendChild(dragFakeNodeG);
3395
3410
  }
3396
- mousemove(event);
3411
+ pointerMove(event);
3397
3412
  };
3398
- board.globalMouseup = (event) => {
3413
+ board.globalPointerUp = (event) => {
3399
3414
  const firstLevelElements = getFirstLevelElement(activeElements);
3400
3415
  if (!board.options.readonly && firstLevelElements.length) {
3401
3416
  firstLevelElements.push(...correspondingElements);
@@ -3484,12 +3499,12 @@ const withNodeDnd = (board) => {
3484
3499
  fakeDropNodeG = undefined;
3485
3500
  dropTarget = null;
3486
3501
  }
3487
- globalMouseup(event);
3502
+ globalPointerUp(event);
3488
3503
  };
3489
3504
  return board;
3490
3505
  };
3491
3506
 
3492
- const buildClipboardData = (board, selectedElements) => {
3507
+ const buildClipboardData = (board, selectedElements, startPoint) => {
3493
3508
  let result = [];
3494
3509
  // get overall abstract
3495
3510
  const overallAbstracts = getOverallAbstracts(board, selectedElements);
@@ -3499,11 +3514,10 @@ const buildClipboardData = (board, selectedElements) => {
3499
3514
  const newSelectedElements = selectedElements.filter(value => !validAbstractRefs.find(ref => ref.abstract === value));
3500
3515
  newSelectedElements.push(...validAbstractRefs.map(value => value.abstract));
3501
3516
  const selectedMindNodes = newSelectedElements.map(value => MindElement.getNode(value));
3502
- const nodesRectangle = getRectangleByElements(board, newSelectedElements, true);
3503
3517
  newSelectedElements.forEach((element, index) => {
3504
3518
  // handle relative location
3505
3519
  const nodeRectangle = getRectangleByNode(selectedMindNodes[index]);
3506
- const points = [[nodeRectangle.x - nodesRectangle.x, nodeRectangle.y - nodesRectangle.y]];
3520
+ const points = [[nodeRectangle.x - startPoint[0], nodeRectangle.y - startPoint[1]]];
3507
3521
  // handle invalid abstract
3508
3522
  const abstractRef = validAbstractRefs.find(ref => ref.abstract === element);
3509
3523
  if (AbstractNode.isAbstract(element) && abstractRef) {
@@ -3532,37 +3546,12 @@ const buildClipboardData = (board, selectedElements) => {
3532
3546
  });
3533
3547
  return result;
3534
3548
  };
3535
- const setClipboardData = (data, elements) => {
3536
- const stringObj = JSON.stringify(elements);
3537
- const encoded = window.btoa(encodeURIComponent(stringObj));
3549
+ const setMindClipboardData = (data, elements) => {
3538
3550
  const text = elements.reduce((string, currentNode) => {
3539
3551
  return string + extractNodesText(currentNode);
3540
3552
  }, '');
3541
- data?.setData(`application/${CLIP_BOARD_FORMAT_KEY}`, encoded);
3542
- data?.setData(`text/plain`, text);
3543
- };
3544
- const setClipboardDataByImage = (data, image) => {
3545
- const stringObj = JSON.stringify(image);
3546
- const encoded = window.btoa(encodeURIComponent(stringObj));
3547
- data?.setData(`application/${CLIP_BOARD_IMAGE_FORMAT_KEY}`, encoded);
3548
- };
3549
- const getImageItemFromClipboard = (data) => {
3550
- const encoded = data?.getData(`application/${CLIP_BOARD_IMAGE_FORMAT_KEY}`);
3551
- let imageItem = null;
3552
- if (encoded) {
3553
- const decoded = decodeURIComponent(window.atob(encoded));
3554
- imageItem = JSON.parse(decoded);
3555
- }
3556
- return imageItem;
3557
- };
3558
- const getDataFromClipboard = (data) => {
3559
- const encoded = data?.getData(`application/${CLIP_BOARD_FORMAT_KEY}`);
3560
- let nodesData = [];
3561
- if (encoded) {
3562
- const decoded = decodeURIComponent(window.atob(encoded));
3563
- nodesData = JSON.parse(decoded);
3564
- }
3565
- return nodesData;
3553
+ setClipboardData(data, elements);
3554
+ setClipboardDataByText(data, text);
3566
3555
  };
3567
3556
  const insertClipboardData = (board, elements, targetPoint) => {
3568
3557
  let newElement, path;
@@ -3763,8 +3752,10 @@ const withCreateMind = (board) => {
3763
3752
  const nodeG = drawRoundRectangleByElement(board, nodeRectangle, emptyMind);
3764
3753
  const topicRectangle = getTopicRectangleByElement(newBoard, nodeRectangle, emptyMind);
3765
3754
  if (!fakeCreateNodeRef) {
3766
- const textManage = new TextManage(board, PlaitBoard.getComponent(board).viewContainerRef, () => {
3767
- return topicRectangle;
3755
+ const textManage = new TextManage(board, PlaitBoard.getComponent(board).viewContainerRef, {
3756
+ getRectangle: () => {
3757
+ return topicRectangle;
3758
+ }
3768
3759
  });
3769
3760
  PlaitBoard.getComponent(board)
3770
3761
  .viewContainerRef.injector.get(NgZone)
@@ -3833,7 +3824,7 @@ const withCreateMind = (board) => {
3833
3824
 
3834
3825
  const withMindHotkey = (baseBoard) => {
3835
3826
  const board = baseBoard;
3836
- const { keydown } = board;
3827
+ const { keydown, deleteFragment } = board;
3837
3828
  board.keydown = (event) => {
3838
3829
  const selectedElements = getSelectedElements(board);
3839
3830
  const isSingleSelection = selectedElements.length === 1;
@@ -3873,24 +3864,6 @@ const withMindHotkey = (baseBoard) => {
3873
3864
  insertMindElement(board, targetElement, findNewSiblingNodePath(board, targetElement));
3874
3865
  return;
3875
3866
  }
3876
- if (selectedElements.length > 0 && (hotkeys.isDeleteBackward(event) || hotkeys.isDeleteForward(event))) {
3877
- event.preventDefault();
3878
- const targetMindElements = selectedElements.filter(el => MindElement.isMindElement(board, el));
3879
- const firstLevelElements = getFirstLevelElement(targetMindElements);
3880
- if (firstLevelElements.length > 0) {
3881
- const deletableElements = [...firstLevelElements].reverse();
3882
- const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
3883
- MindTransforms.setAbstractsByRefs(board, abstractRefs);
3884
- const refs = deleteElementsHandleRightNodeCount(board, targetMindElements);
3885
- MindTransforms.setRightNodeCountByRefs(board, refs);
3886
- MindTransforms.removeElements(board, targetMindElements);
3887
- const nextSelected = getNextSelectedElement(board, firstLevelElements);
3888
- if (nextSelected) {
3889
- addSelectedElement(board, nextSelected);
3890
- }
3891
- }
3892
- return;
3893
- }
3894
3867
  if (!isVirtualKey(event) && !isSpaceHotkey(event) && isSingleSelection) {
3895
3868
  event.preventDefault();
3896
3869
  editTopic(targetElement);
@@ -3899,6 +3872,22 @@ const withMindHotkey = (baseBoard) => {
3899
3872
  }
3900
3873
  keydown(event);
3901
3874
  };
3875
+ board.deleteFragment = (data) => {
3876
+ const targetMindElements = getSelectedMindElements(board);
3877
+ if (targetMindElements.length) {
3878
+ const firstLevelElements = getFirstLevelElement(targetMindElements).reverse();
3879
+ const abstractRefs = deleteElementHandleAbstract(board, firstLevelElements);
3880
+ MindTransforms.setAbstractsByRefs(board, abstractRefs);
3881
+ const refs = deleteElementsHandleRightNodeCount(board, targetMindElements);
3882
+ MindTransforms.setRightNodeCountByRefs(board, refs);
3883
+ MindTransforms.removeElements(board, targetMindElements);
3884
+ const nextSelected = getNextSelectedElement(board, firstLevelElements);
3885
+ if (nextSelected) {
3886
+ addSelectedElement(board, nextSelected);
3887
+ }
3888
+ }
3889
+ deleteFragment(data);
3890
+ };
3902
3891
  return board;
3903
3892
  };
3904
3893
  const getNextSelectedElement = (board, firstLevelElements) => {
@@ -4011,24 +4000,24 @@ const withNodeHoverDetect = (board) => {
4011
4000
  };
4012
4001
 
4013
4002
  const withNodeImage = (board) => {
4014
- const { keydown, mousedown, globalMouseup, setFragment, insertFragment, deleteFragment } = board;
4015
- board.mousedown = (event) => {
4003
+ const { keydown, pointerDown, globalPointerUp, setFragment, insertFragment, deleteFragment } = board;
4004
+ board.pointerDown = (event) => {
4016
4005
  const selectedImageElement = getSelectedImageElement(board);
4017
4006
  if (PlaitBoard.isReadonly(board) || !isMainPointer(event) || !PlaitBoard.isPointer(board, PlaitPointerType.selection)) {
4018
4007
  if (selectedImageElement) {
4019
4008
  setImageFocus(board, selectedImageElement, false);
4020
4009
  }
4021
- mousedown(event);
4010
+ pointerDown(event);
4022
4011
  return;
4023
4012
  }
4024
4013
  const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
4025
4014
  const range = { anchor: point, focus: point };
4026
- const hitElements = getHitElements(board, { ranges: [range] });
4027
- const hasImage = hitElements.length && MindElement.hasImage(hitElements[0]);
4028
- const hitImage = hasImage && isHitImage(board, hitElements[0], range);
4029
- if (selectedImageElement && hitImage && hitElements[0] === selectedImageElement) {
4015
+ const hitImageElements = getHitElements(board, { ranges: [range] }, (value) => MindElement.isMindElement(board, value) && MindElement.hasImage(value));
4016
+ const hasImage = hitImageElements.length;
4017
+ const hitImage = hasImage > 0 && isHitImage(board, hitImageElements[0], range);
4018
+ if (selectedImageElement && hitImage && hitImageElements[0] === selectedImageElement) {
4030
4019
  temporaryDisableSelection(board);
4031
- mousedown(event);
4020
+ pointerDown(event);
4032
4021
  return;
4033
4022
  }
4034
4023
  if (selectedImageElement) {
@@ -4036,9 +4025,9 @@ const withNodeImage = (board) => {
4036
4025
  }
4037
4026
  if (hitImage) {
4038
4027
  temporaryDisableSelection(board);
4039
- setImageFocus(board, hitElements[0], true);
4028
+ setImageFocus(board, hitImageElements[0], true);
4040
4029
  }
4041
- mousedown(event);
4030
+ pointerDown(event);
4042
4031
  };
4043
4032
  board.keydown = (event) => {
4044
4033
  const selectedImageElement = getSelectedImageElement(board);
@@ -4049,7 +4038,7 @@ const withNodeImage = (board) => {
4049
4038
  }
4050
4039
  keydown(event);
4051
4040
  };
4052
- board.globalMouseup = (event) => {
4041
+ board.globalPointerUp = (event) => {
4053
4042
  if (PlaitBoard.isFocus(board)) {
4054
4043
  const isInBoard = event.target instanceof Node && PlaitBoard.getBoardContainer(board).contains(event.target);
4055
4044
  const selectedImageElement = getSelectedImageElement(board);
@@ -4058,15 +4047,15 @@ const withNodeImage = (board) => {
4058
4047
  setImageFocus(board, selectedImageElement, false);
4059
4048
  }
4060
4049
  }
4061
- globalMouseup(event);
4050
+ globalPointerUp(event);
4062
4051
  };
4063
- board.setFragment = (data) => {
4052
+ board.setFragment = (data, rectangle) => {
4064
4053
  const selectedImageElement = getSelectedImageElement(board);
4065
4054
  if (selectedImageElement) {
4066
- setClipboardDataByImage(data, selectedImageElement.data.image);
4055
+ setClipboardDataByMedia(data, selectedImageElement.data.image, MediaKeys.image);
4067
4056
  return;
4068
4057
  }
4069
- setFragment(data);
4058
+ setFragment(data, rectangle);
4070
4059
  };
4071
4060
  board.deleteFragment = (data) => {
4072
4061
  const selectedImageElement = getSelectedImageElement(board);
@@ -4088,10 +4077,11 @@ const withNodeImage = (board) => {
4088
4077
  return;
4089
4078
  }
4090
4079
  }
4091
- const imageItem = getImageItemFromClipboard(data);
4080
+ const imageItem = getClipboardDataByMedia(data, MediaKeys.image);
4092
4081
  if (imageItem && (isSingleSelection || isSelectedImage)) {
4093
4082
  const selectedElement = (selectedElements[0] || getSelectedImageElement(board));
4094
4083
  MindTransforms.setImage(board, selectedElement, imageItem);
4084
+ return;
4095
4085
  }
4096
4086
  insertFragment(data, targetPoint);
4097
4087
  };
@@ -4099,25 +4089,30 @@ const withNodeImage = (board) => {
4099
4089
  };
4100
4090
 
4101
4091
  const withNodeResize = (board) => {
4102
- const { mousedown, mousemove, globalMouseup } = board;
4092
+ const { pointerDown, pointerMove, globalPointerUp } = board;
4103
4093
  let targetElement = null;
4104
4094
  let targetElementRef = null;
4105
4095
  let startPoint = null;
4106
- board.mousedown = (event) => {
4107
- if (targetElement) {
4096
+ board.pointerDown = (event) => {
4097
+ const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
4098
+ const newTargetElement = getSelectedTarget(board, point);
4099
+ if (newTargetElement) {
4100
+ PlaitBoard.getBoardContainer(board).classList.add(ResizeCursorClass['ew-resize']);
4101
+ targetElement = newTargetElement;
4108
4102
  startPoint = [event.x, event.y];
4109
4103
  return;
4110
4104
  }
4111
- mousedown(event);
4105
+ pointerDown(event);
4112
4106
  };
4113
- board.mousemove = (event) => {
4107
+ board.pointerMove = (event) => {
4114
4108
  if (PlaitBoard.isReadonly(board) || PlaitBoard.hasBeenTextEditing(board)) {
4115
- mousemove(event);
4109
+ pointerMove(event);
4116
4110
  return;
4117
4111
  }
4118
4112
  if (startPoint && targetElement && !isMindNodeResizing(board)) {
4119
4113
  // prevent text from being selected
4120
4114
  event.preventDefault();
4115
+ preventTouchMove(board, true);
4121
4116
  const endPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
4122
4117
  const distance = distanceBetweenPointAndPoint(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
4123
4118
  if (distance > PRESS_AND_MOVE_BUFFER) {
@@ -4134,6 +4129,7 @@ const withNodeResize = (board) => {
4134
4129
  if (isMindNodeResizing(board) && startPoint && targetElementRef) {
4135
4130
  // prevent text from being selected
4136
4131
  event.preventDefault();
4132
+ preventTouchMove(board, true);
4137
4133
  throttleRAF(() => {
4138
4134
  if (!startPoint) {
4139
4135
  return;
@@ -4158,26 +4154,26 @@ const withNodeResize = (board) => {
4158
4154
  // press and start drag when node is non selected
4159
4155
  if (!isDragging(board)) {
4160
4156
  const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
4161
- const newTargetElement = getTargetElement(board, point);
4157
+ const newTargetElement = getSelectedTarget(board, point);
4162
4158
  if (newTargetElement) {
4163
4159
  PlaitBoard.getBoardContainer(board).classList.add(ResizeCursorClass['ew-resize']);
4164
4160
  }
4165
4161
  else {
4166
4162
  PlaitBoard.getBoardContainer(board).classList.remove(ResizeCursorClass['ew-resize']);
4167
4163
  }
4168
- targetElement = newTargetElement;
4169
4164
  }
4170
4165
  }
4171
- mousemove(event);
4166
+ pointerMove(event);
4172
4167
  };
4173
- board.globalMouseup = (event) => {
4174
- globalMouseup(event);
4168
+ board.globalPointerUp = (event) => {
4169
+ globalPointerUp(event);
4175
4170
  if (isMindNodeResizing(board) || targetElement) {
4176
4171
  targetElement && removeResizing(board, targetElement);
4177
4172
  targetElementRef = null;
4178
4173
  targetElement = null;
4179
4174
  startPoint = null;
4180
4175
  MERGING.set(board, false);
4176
+ preventTouchMove(board, false);
4181
4177
  }
4182
4178
  };
4183
4179
  return board;
@@ -4201,7 +4197,7 @@ const removeResizing = (board, element) => {
4201
4197
  }
4202
4198
  IS_MIND_NODE_RESIZING.set(board, false);
4203
4199
  };
4204
- const getTargetElement = (board, point) => {
4200
+ const getSelectedTarget = (board, point) => {
4205
4201
  const selectedElements = getSelectedElements(board).filter(value => MindElement.isMindElement(board, value));
4206
4202
  if (selectedElements.length > 0) {
4207
4203
  const target = selectedElements.find(value => {
@@ -4218,9 +4214,52 @@ const getResizeActiveRectangle = (board, element) => {
4218
4214
  return { x: rectangle.x + rectangle.width - EXTEND_OFFSET, y: rectangle.y, width: EXTEND_OFFSET * 2, height: rectangle.height };
4219
4215
  };
4220
4216
 
4217
+ const withNodeImageResize = (board) => {
4218
+ const options = {
4219
+ key: 'mind-node-image',
4220
+ canResize: () => {
4221
+ return true;
4222
+ },
4223
+ detect: (point) => {
4224
+ const selectedMindElement = getSelectedImageElement(board);
4225
+ if (selectedMindElement) {
4226
+ const result = getHitImageResizeHandleDirection(board, selectedMindElement, point);
4227
+ if (result) {
4228
+ return {
4229
+ element: selectedMindElement,
4230
+ direction: result.direction,
4231
+ cursorClass: result.cursorClass
4232
+ };
4233
+ }
4234
+ }
4235
+ return null;
4236
+ },
4237
+ onResize: (resizeRef, resizeState) => {
4238
+ let offsetX = resizeState.offsetX;
4239
+ let offsetY = resizeState.offsetY;
4240
+ if (resizeRef.direction === ResizeDirection.nw || resizeRef.direction === ResizeDirection.sw) {
4241
+ offsetX = -offsetX;
4242
+ }
4243
+ const originWidth = resizeRef.element.data.image.width;
4244
+ const originHeight = resizeRef.element.data.image.height;
4245
+ let width = originWidth + offsetX;
4246
+ if (width <= 100) {
4247
+ width = 100;
4248
+ }
4249
+ const ratio = originWidth / width;
4250
+ const height = originHeight / ratio;
4251
+ const imageItem = { ...resizeRef.element.data.image, width, height };
4252
+ MindTransforms.setImage(board, PlaitNode.get(board, resizeRef.path), imageItem);
4253
+ addSelectedImageElement(board, PlaitNode.get(board, resizeRef.path));
4254
+ }
4255
+ };
4256
+ withResize(board, options);
4257
+ return board;
4258
+ };
4259
+
4221
4260
  const withMind = (baseBoard) => {
4222
4261
  const board = baseBoard;
4223
- const { drawElement, dblclick, insertFragment, setFragment, deleteFragment, isHitSelection, getRectangle, isMovable, isRecursion } = board;
4262
+ const { drawElement, dblclick, insertFragment, setFragment, isHitSelection, getRectangle, isMovable, isRecursion } = board;
4224
4263
  board.drawElement = (context) => {
4225
4264
  if (PlaitMind.isMind(context.element)) {
4226
4265
  return PlaitMindComponent;
@@ -4284,48 +4323,34 @@ const withMind = (baseBoard) => {
4284
4323
  }
4285
4324
  dblclick(event);
4286
4325
  };
4287
- board.setFragment = (data) => {
4288
- const selectedElements = getFirstLevelElement(getSelectedElements(board));
4289
- if (selectedElements.length) {
4290
- const elements = buildClipboardData(board, selectedElements);
4291
- setClipboardData(data, elements);
4292
- return;
4293
- }
4294
- setFragment(data);
4326
+ board.setFragment = (data, rectangle) => {
4327
+ const targetMindElements = getSelectedMindElements(board);
4328
+ const firstLevelElements = getFirstLevelElement(targetMindElements);
4329
+ if (firstLevelElements.length) {
4330
+ const elements = buildClipboardData(board, firstLevelElements, rectangle ? [rectangle.x, rectangle.y] : [0, 0]);
4331
+ setMindClipboardData(data, elements);
4332
+ }
4333
+ setFragment(data, rectangle);
4295
4334
  };
4296
4335
  board.insertFragment = (data, targetPoint) => {
4297
- if (board.options.readonly) {
4298
- insertFragment(data, targetPoint);
4299
- return;
4300
- }
4301
4336
  const elements = getDataFromClipboard(data);
4302
- if (elements.length) {
4303
- insertClipboardData(board, elements, targetPoint || [0, 0]);
4337
+ const mindElements = elements.filter(value => MindElement.isMindElement(board, value));
4338
+ if (elements.length > 0 && mindElements.length > 0) {
4339
+ insertClipboardData(board, mindElements, targetPoint);
4304
4340
  }
4305
- else {
4306
- const selectedElements = getSelectedElements(board);
4307
- if (selectedElements.length === 1) {
4341
+ else if (elements.length === 0) {
4342
+ const mindElements = getSelectedMindElements(board);
4343
+ if (mindElements.length === 1) {
4308
4344
  const text = getTextFromClipboard(data);
4309
4345
  if (text) {
4310
- insertClipboardText(board, selectedElements[0], buildText(text));
4346
+ insertClipboardText(board, mindElements[0], buildText(text));
4347
+ return;
4311
4348
  }
4312
4349
  }
4313
4350
  }
4314
4351
  insertFragment(data, targetPoint);
4315
4352
  };
4316
- board.deleteFragment = (data) => {
4317
- const selectedElements = getSelectedElements(board);
4318
- if (selectedElements.length) {
4319
- const deletableElements = getFirstLevelElement(selectedElements).reverse();
4320
- const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
4321
- MindTransforms.setAbstractsByRefs(board, abstractRefs);
4322
- const refs = deleteElementsHandleRightNodeCount(board, selectedElements);
4323
- MindTransforms.setRightNodeCountByRefs(board, refs);
4324
- MindTransforms.removeElements(board, selectedElements);
4325
- }
4326
- deleteFragment(data);
4327
- };
4328
- return withNodeResize(withNodeImage(withNodeHoverDetect(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board))))))));
4353
+ return withNodeResize(withNodeImageResize(withNodeImage(withNodeHoverDetect(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board)))))))));
4329
4354
  };
4330
4355
 
4331
4356
  class MindEmojiBaseComponent {
@@ -4375,17 +4400,43 @@ class MindImageBaseComponent {
4375
4400
  set imageItem(value) {
4376
4401
  this.afterImageItemChange(this._imageItem, value);
4377
4402
  this._imageItem = value;
4403
+ this.drawFocus();
4378
4404
  }
4379
4405
  get imageItem() {
4380
4406
  return this._imageItem;
4381
4407
  }
4408
+ set isFocus(value) {
4409
+ this._isFocus = value;
4410
+ this.drawFocus();
4411
+ }
4412
+ get isFocus() {
4413
+ return this._isFocus;
4414
+ }
4382
4415
  get nativeElement() {
4383
4416
  return this.elementRef.nativeElement;
4384
4417
  }
4385
4418
  constructor(elementRef, cdr) {
4386
4419
  this.elementRef = elementRef;
4387
4420
  this.cdr = cdr;
4388
- this.isFocus = false;
4421
+ this.initialized = false;
4422
+ }
4423
+ ngOnInit() {
4424
+ this.activeGenerator = new ActiveGenerator(this.board, {
4425
+ activeStrokeWidth: 1,
4426
+ getRectangle: (element) => {
4427
+ return getImageForeignRectangle(this.board, this.element);
4428
+ },
4429
+ getStrokeWidthByElement: () => {
4430
+ return 0;
4431
+ }
4432
+ });
4433
+ this.initialized = true;
4434
+ }
4435
+ drawFocus() {
4436
+ if (this.initialized) {
4437
+ const com = PlaitElement.getComponent(this.element);
4438
+ this.activeGenerator.draw(this.element, com.g, { selected: this._isFocus });
4439
+ }
4389
4440
  }
4390
4441
  }
4391
4442
  MindImageBaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindImageBaseComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
@@ -4415,5 +4466,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
4415
4466
  * Generated bundle index. Do not edit.
4416
4467
  */
4417
4468
 
4418
- 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 };
4469
+ export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_FONT_FAMILY, BRANCH_WIDTH, BaseDrawer, BranchShape, DEFAULT_FONT_FAMILY, DefaultAbstractNodeStyle, DefaultNodeStyle, ELEMENT_TO_NODE, EXTEND_DIAMETER, EXTEND_OFFSET, GRAY_COLOR, INHERIT_ATTRIBUTE_KEYS, IS_DRAGGING, LayoutDirection, LayoutDirectionsMap, MindColorfulThemeColor, MindDarkThemeColor, MindDefaultThemeColor, MindElement, MindElementShape, MindEmojiBaseComponent, MindImageBaseComponent, MindModule, MindNode, MindNodeComponent, MindPointerType, MindQueries, MindRetroThemeColor, MindSoftThemeColor, MindStarryThemeColor, MindThemeColor, MindThemeColors, MindTransforms, NodeSpace, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_TOPIC_FONT_SIZE, ROOT_TOPIC_HEIGHT, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, TRANSPARENT, WithMindPluginKey, addActiveOnDragOrigin, addSelectedImageElement, adjustAbstractToNode, adjustNodeToRoot, adjustRootToNode, buildImage, canSetAbstract, copyNewNode, correctLayoutByDirection, createDefaultMind, createEmptyMind, createMindElement, deleteElementHandleAbstract, deleteElementsHandleRightNodeCount, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNode, editTopic, extractNodesText, findLastChild, findLocationLeftIndex, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchShapeByMindElement, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultLayout, getEmojiFontSize, getEmojiForeignRectangle, getEmojiRectangle, getEmojisWidthHeight, getFillByElement, getFirstLevelElement, getFontSizeBySlateElement, getHitAbstractHandle, getHitImageResizeHandleDirection, getImageForeignRectangle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutOptions, getLayoutReverseDirection, getLocationScope, getMindThemeColor, getNewNodeHeight, getNextBranchColor, getNodeDefaultFontSize, getOverallAbstracts, getPathByDropTarget, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getSelectedImageElement, getSelectedMindElements, getShapeByElement, getStrokeByMindElement, getStrokeWidthByElement, getTopicRectangleByElement, getTopicRectangleByNode, getValidAbstractRefs, handleTouchedAbstract, hasAfterDraw, hasPreviousOrNextOfDropPath, insertElementHandleAbstract, insertElementHandleRightNodeCount, insertMindElement, isChildElement, isChildOfAbstract, isChildRight, isChildUp, isCorrectLayout, isDragging, isDropStandardRight, isHitEmojis, isHitImage, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, isVirtualKey, removeActiveOnDragOrigin, removeSelectedImageElement, selectImage, separateChildren, setImageFocus, setIsDragging, temporaryDisableSelection, withMind, withMindExtend };
4419
4470
  //# sourceMappingURL=plait-mind.mjs.map