@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 { __awaiter } from 'tslib';
10
11
  import { isKeyHotkey } from 'is-hotkey';
@@ -381,11 +382,20 @@ function getImageForeignRectangle(board, element) {
381
382
  width,
382
383
  height
383
384
  };
384
- return RectangleClient.getOutlineRectangle(rectangle, -6);
385
+ return rectangle;
385
386
  }
386
387
  const isHitImage = (board, element, range) => {
387
- const client = getImageForeignRectangle(board, element);
388
- return RectangleClient.isHit(RectangleClient.toRectangleClient([range.anchor, range.focus]), client);
388
+ const imageRectangle = getImageForeignRectangle(board, element);
389
+ const imageOutlineRectangle = RectangleClient.getOutlineRectangle(imageRectangle, -RESIZE_HANDLE_DIAMETER / 2);
390
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([range.anchor, range.focus]), imageOutlineRectangle);
391
+ };
392
+ const getHitImageResizeHandleDirection = (board, element, point) => {
393
+ const imageRectangle = getImageForeignRectangle(board, element);
394
+ const resizeTargets = getRectangleResizeTargets(imageRectangle, RESIZE_HANDLE_DIAMETER);
395
+ const result = resizeTargets.find(resizeTarget => {
396
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), resizeTarget.rectangle);
397
+ });
398
+ return result;
389
399
  };
390
400
 
391
401
  function editTopic(element) {
@@ -401,6 +411,10 @@ const temporaryDisableSelection = (board) => {
401
411
  board.setPluginOptions(PlaitPluginKey.withSelection, Object.assign({}, currentOptions));
402
412
  }, 0);
403
413
  };
414
+ const getSelectedMindElements = (board) => {
415
+ const selectedElements = getSelectedElements(board).filter(value => MindElement.isMindElement(board, value));
416
+ return selectedElements;
417
+ };
404
418
 
405
419
  const createEmptyMind = (point) => {
406
420
  const element = createMindElement('思维导图', 72, ROOT_TOPIC_HEIGHT, { layout: MindLayoutType.right });
@@ -2313,9 +2327,7 @@ const MindElement = {
2313
2327
  return isIndentedLayout(_layout);
2314
2328
  },
2315
2329
  isMindElement(board, element) {
2316
- const path = PlaitBoard.findPath(board, element);
2317
- const rootElement = PlaitNode.get(board, path.slice(0, 1));
2318
- if (PlaitMind.isMind(rootElement)) {
2330
+ if (element.data && element.data.topic && element.width && element.height) {
2319
2331
  return true;
2320
2332
  }
2321
2333
  else {
@@ -2942,7 +2954,6 @@ class NodeImageDrawer {
2942
2954
  this.g = createG();
2943
2955
  const foreignRectangle = getImageForeignRectangle(this.board, element);
2944
2956
  this.foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
2945
- this.foreignObject.style.padding = `6px`;
2946
2957
  this.g.append(this.foreignObject);
2947
2958
  const componentType = this.board.getPluginOptions(WithMindPluginKey).imageComponentType;
2948
2959
  if (!componentType) {
@@ -3006,19 +3017,23 @@ class MindNodeComponent extends PlaitPluginElementComponent {
3006
3017
  this.collapseDrawer = new CollapseDrawer(this.board);
3007
3018
  this.imageDrawer = new NodeImageDrawer(this.board, this.viewContainerRef);
3008
3019
  const plugins = this.board.getPluginOptions(WithMindPluginKey).textPlugins;
3009
- this.textManage = new TextManage(this.board, this.viewContainerRef, () => {
3010
- const rect = getTopicRectangleByNode(this.board, this.node);
3011
- return rect;
3012
- }, (textManageRef) => {
3013
- const width = textManageRef.width;
3014
- const height = textManageRef.height;
3015
- if (textManageRef.newValue) {
3016
- MindTransforms.setTopic(this.board, this.element, textManageRef.newValue, width, height);
3017
- }
3018
- else {
3019
- MindTransforms.setTopicSize(this.board, this.element, width, height);
3020
- }
3021
- }, plugins);
3020
+ this.textManage = new TextManage(this.board, this.viewContainerRef, {
3021
+ getRectangle: () => {
3022
+ const rect = getTopicRectangleByNode(this.board, this.node);
3023
+ return rect;
3024
+ },
3025
+ onValueChangeHandle: (textManageRef) => {
3026
+ const width = textManageRef.width;
3027
+ const height = textManageRef.height;
3028
+ if (textManageRef.newValue) {
3029
+ MindTransforms.setTopic(this.board, this.element, textManageRef.newValue, width, height);
3030
+ }
3031
+ else {
3032
+ MindTransforms.setTopicSize(this.board, this.element, width, height);
3033
+ }
3034
+ },
3035
+ textPlugins: plugins
3036
+ });
3022
3037
  }
3023
3038
  ngOnInit() {
3024
3039
  super.ngOnInit();
@@ -3261,7 +3276,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
3261
3276
 
3262
3277
  const DRAG_MOVE_BUFFER = 5;
3263
3278
  const withNodeDnd = (board) => {
3264
- const { mousedown, mousemove, globalMouseup } = board;
3279
+ const { pointerDown, pointerMove, globalPointerUp } = board;
3265
3280
  let activeElements = [];
3266
3281
  let correspondingElements = [];
3267
3282
  let startPoint;
@@ -3269,12 +3284,12 @@ const withNodeDnd = (board) => {
3269
3284
  let fakeDropNodeG;
3270
3285
  let dropTarget = null;
3271
3286
  let targetPath;
3272
- board.mousedown = (event) => {
3287
+ board.pointerDown = (event) => {
3273
3288
  if (PlaitBoard.isReadonly(board) ||
3274
3289
  PlaitBoard.hasBeenTextEditing(board) ||
3275
3290
  !PlaitBoard.isPointer(board, PlaitPointerType.selection) ||
3276
3291
  !isMainPointer(event)) {
3277
- mousedown(event);
3292
+ pointerDown(event);
3278
3293
  return;
3279
3294
  }
3280
3295
  const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
@@ -3301,9 +3316,9 @@ const withNodeDnd = (board) => {
3301
3316
  if (activeElements.length) {
3302
3317
  correspondingElements = getOverallAbstracts(board, activeElements);
3303
3318
  }
3304
- mousedown(event);
3319
+ pointerDown(event);
3305
3320
  };
3306
- board.mousemove = (event) => {
3321
+ board.pointerMove = (event) => {
3307
3322
  if (!board.options.readonly && (activeElements === null || activeElements === void 0 ? void 0 : activeElements.length) && startPoint) {
3308
3323
  // prevent text from being selected
3309
3324
  event.preventDefault();
@@ -3334,9 +3349,9 @@ const withNodeDnd = (board) => {
3334
3349
  });
3335
3350
  PlaitBoard.getHost(board).appendChild(dragFakeNodeG);
3336
3351
  }
3337
- mousemove(event);
3352
+ pointerMove(event);
3338
3353
  };
3339
- board.globalMouseup = (event) => {
3354
+ board.globalPointerUp = (event) => {
3340
3355
  const firstLevelElements = getFirstLevelElement(activeElements);
3341
3356
  if (!board.options.readonly && firstLevelElements.length) {
3342
3357
  firstLevelElements.push(...correspondingElements);
@@ -3425,12 +3440,12 @@ const withNodeDnd = (board) => {
3425
3440
  fakeDropNodeG = undefined;
3426
3441
  dropTarget = null;
3427
3442
  }
3428
- globalMouseup(event);
3443
+ globalPointerUp(event);
3429
3444
  };
3430
3445
  return board;
3431
3446
  };
3432
3447
 
3433
- const buildClipboardData = (board, selectedElements) => {
3448
+ const buildClipboardData = (board, selectedElements, startPoint) => {
3434
3449
  let result = [];
3435
3450
  // get overall abstract
3436
3451
  const overallAbstracts = getOverallAbstracts(board, selectedElements);
@@ -3440,11 +3455,10 @@ const buildClipboardData = (board, selectedElements) => {
3440
3455
  const newSelectedElements = selectedElements.filter(value => !validAbstractRefs.find(ref => ref.abstract === value));
3441
3456
  newSelectedElements.push(...validAbstractRefs.map(value => value.abstract));
3442
3457
  const selectedMindNodes = newSelectedElements.map(value => MindElement.getNode(value));
3443
- const nodesRectangle = getRectangleByElements(board, newSelectedElements, true);
3444
3458
  newSelectedElements.forEach((element, index) => {
3445
3459
  // handle relative location
3446
3460
  const nodeRectangle = getRectangleByNode(selectedMindNodes[index]);
3447
- const points = [[nodeRectangle.x - nodesRectangle.x, nodeRectangle.y - nodesRectangle.y]];
3461
+ const points = [[nodeRectangle.x - startPoint[0], nodeRectangle.y - startPoint[1]]];
3448
3462
  // handle invalid abstract
3449
3463
  const abstractRef = validAbstractRefs.find(ref => ref.abstract === element);
3450
3464
  if (AbstractNode.isAbstract(element) && abstractRef) {
@@ -3467,37 +3481,12 @@ const buildClipboardData = (board, selectedElements) => {
3467
3481
  });
3468
3482
  return result;
3469
3483
  };
3470
- const setClipboardData = (data, elements) => {
3471
- const stringObj = JSON.stringify(elements);
3472
- const encoded = window.btoa(encodeURIComponent(stringObj));
3484
+ const setMindClipboardData = (data, elements) => {
3473
3485
  const text = elements.reduce((string, currentNode) => {
3474
3486
  return string + extractNodesText(currentNode);
3475
3487
  }, '');
3476
- data === null || data === void 0 ? void 0 : data.setData(`application/${CLIP_BOARD_FORMAT_KEY}`, encoded);
3477
- data === null || data === void 0 ? void 0 : data.setData(`text/plain`, text);
3478
- };
3479
- const setClipboardDataByImage = (data, image) => {
3480
- const stringObj = JSON.stringify(image);
3481
- const encoded = window.btoa(encodeURIComponent(stringObj));
3482
- data === null || data === void 0 ? void 0 : data.setData(`application/${CLIP_BOARD_IMAGE_FORMAT_KEY}`, encoded);
3483
- };
3484
- const getImageItemFromClipboard = (data) => {
3485
- const encoded = data === null || data === void 0 ? void 0 : data.getData(`application/${CLIP_BOARD_IMAGE_FORMAT_KEY}`);
3486
- let imageItem = null;
3487
- if (encoded) {
3488
- const decoded = decodeURIComponent(window.atob(encoded));
3489
- imageItem = JSON.parse(decoded);
3490
- }
3491
- return imageItem;
3492
- };
3493
- const getDataFromClipboard = (data) => {
3494
- const encoded = data === null || data === void 0 ? void 0 : data.getData(`application/${CLIP_BOARD_FORMAT_KEY}`);
3495
- let nodesData = [];
3496
- if (encoded) {
3497
- const decoded = decodeURIComponent(window.atob(encoded));
3498
- nodesData = JSON.parse(decoded);
3499
- }
3500
- return nodesData;
3488
+ setClipboardData(data, elements);
3489
+ setClipboardDataByText(data, text);
3501
3490
  };
3502
3491
  const insertClipboardData = (board, elements, targetPoint) => {
3503
3492
  let newElement, path;
@@ -3695,8 +3684,10 @@ const withCreateMind = (board) => {
3695
3684
  const nodeG = drawRoundRectangleByElement(board, nodeRectangle, emptyMind);
3696
3685
  const topicRectangle = getTopicRectangleByElement(newBoard, nodeRectangle, emptyMind);
3697
3686
  if (!fakeCreateNodeRef) {
3698
- const textManage = new TextManage(board, PlaitBoard.getComponent(board).viewContainerRef, () => {
3699
- return topicRectangle;
3687
+ const textManage = new TextManage(board, PlaitBoard.getComponent(board).viewContainerRef, {
3688
+ getRectangle: () => {
3689
+ return topicRectangle;
3690
+ }
3700
3691
  });
3701
3692
  PlaitBoard.getComponent(board)
3702
3693
  .viewContainerRef.injector.get(NgZone)
@@ -3765,7 +3756,7 @@ const withCreateMind = (board) => {
3765
3756
 
3766
3757
  const withMindHotkey = (baseBoard) => {
3767
3758
  const board = baseBoard;
3768
- const { keydown } = board;
3759
+ const { keydown, deleteFragment } = board;
3769
3760
  board.keydown = (event) => {
3770
3761
  const selectedElements = getSelectedElements(board);
3771
3762
  const isSingleSelection = selectedElements.length === 1;
@@ -3805,24 +3796,6 @@ const withMindHotkey = (baseBoard) => {
3805
3796
  insertMindElement(board, targetElement, findNewSiblingNodePath(board, targetElement));
3806
3797
  return;
3807
3798
  }
3808
- if (selectedElements.length > 0 && (hotkeys.isDeleteBackward(event) || hotkeys.isDeleteForward(event))) {
3809
- event.preventDefault();
3810
- const targetMindElements = selectedElements.filter(el => MindElement.isMindElement(board, el));
3811
- const firstLevelElements = getFirstLevelElement(targetMindElements);
3812
- if (firstLevelElements.length > 0) {
3813
- const deletableElements = [...firstLevelElements].reverse();
3814
- const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
3815
- MindTransforms.setAbstractsByRefs(board, abstractRefs);
3816
- const refs = deleteElementsHandleRightNodeCount(board, targetMindElements);
3817
- MindTransforms.setRightNodeCountByRefs(board, refs);
3818
- MindTransforms.removeElements(board, targetMindElements);
3819
- const nextSelected = getNextSelectedElement(board, firstLevelElements);
3820
- if (nextSelected) {
3821
- addSelectedElement(board, nextSelected);
3822
- }
3823
- }
3824
- return;
3825
- }
3826
3799
  if (!isVirtualKey(event) && !isSpaceHotkey(event) && isSingleSelection) {
3827
3800
  event.preventDefault();
3828
3801
  editTopic(targetElement);
@@ -3831,6 +3804,22 @@ const withMindHotkey = (baseBoard) => {
3831
3804
  }
3832
3805
  keydown(event);
3833
3806
  };
3807
+ board.deleteFragment = (data) => {
3808
+ const targetMindElements = getSelectedMindElements(board);
3809
+ if (targetMindElements.length) {
3810
+ const firstLevelElements = getFirstLevelElement(targetMindElements).reverse();
3811
+ const abstractRefs = deleteElementHandleAbstract(board, firstLevelElements);
3812
+ MindTransforms.setAbstractsByRefs(board, abstractRefs);
3813
+ const refs = deleteElementsHandleRightNodeCount(board, targetMindElements);
3814
+ MindTransforms.setRightNodeCountByRefs(board, refs);
3815
+ MindTransforms.removeElements(board, targetMindElements);
3816
+ const nextSelected = getNextSelectedElement(board, firstLevelElements);
3817
+ if (nextSelected) {
3818
+ addSelectedElement(board, nextSelected);
3819
+ }
3820
+ }
3821
+ deleteFragment(data);
3822
+ };
3834
3823
  return board;
3835
3824
  };
3836
3825
  const getNextSelectedElement = (board, firstLevelElements) => {
@@ -3943,24 +3932,24 @@ const withNodeHoverDetect = (board) => {
3943
3932
  };
3944
3933
 
3945
3934
  const withNodeImage = (board) => {
3946
- const { keydown, mousedown, globalMouseup, setFragment, insertFragment, deleteFragment } = board;
3947
- board.mousedown = (event) => {
3935
+ const { keydown, pointerDown, globalPointerUp, setFragment, insertFragment, deleteFragment } = board;
3936
+ board.pointerDown = (event) => {
3948
3937
  const selectedImageElement = getSelectedImageElement(board);
3949
3938
  if (PlaitBoard.isReadonly(board) || !isMainPointer(event) || !PlaitBoard.isPointer(board, PlaitPointerType.selection)) {
3950
3939
  if (selectedImageElement) {
3951
3940
  setImageFocus(board, selectedImageElement, false);
3952
3941
  }
3953
- mousedown(event);
3942
+ pointerDown(event);
3954
3943
  return;
3955
3944
  }
3956
3945
  const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3957
3946
  const range = { anchor: point, focus: point };
3958
- const hitElements = getHitElements(board, { ranges: [range] });
3959
- const hasImage = hitElements.length && MindElement.hasImage(hitElements[0]);
3960
- const hitImage = hasImage && isHitImage(board, hitElements[0], range);
3961
- if (selectedImageElement && hitImage && hitElements[0] === selectedImageElement) {
3947
+ const hitImageElements = getHitElements(board, { ranges: [range] }, (value) => MindElement.isMindElement(board, value) && MindElement.hasImage(value));
3948
+ const hasImage = hitImageElements.length;
3949
+ const hitImage = hasImage > 0 && isHitImage(board, hitImageElements[0], range);
3950
+ if (selectedImageElement && hitImage && hitImageElements[0] === selectedImageElement) {
3962
3951
  temporaryDisableSelection(board);
3963
- mousedown(event);
3952
+ pointerDown(event);
3964
3953
  return;
3965
3954
  }
3966
3955
  if (selectedImageElement) {
@@ -3968,9 +3957,9 @@ const withNodeImage = (board) => {
3968
3957
  }
3969
3958
  if (hitImage) {
3970
3959
  temporaryDisableSelection(board);
3971
- setImageFocus(board, hitElements[0], true);
3960
+ setImageFocus(board, hitImageElements[0], true);
3972
3961
  }
3973
- mousedown(event);
3962
+ pointerDown(event);
3974
3963
  };
3975
3964
  board.keydown = (event) => {
3976
3965
  const selectedImageElement = getSelectedImageElement(board);
@@ -3981,7 +3970,7 @@ const withNodeImage = (board) => {
3981
3970
  }
3982
3971
  keydown(event);
3983
3972
  };
3984
- board.globalMouseup = (event) => {
3973
+ board.globalPointerUp = (event) => {
3985
3974
  if (PlaitBoard.isFocus(board)) {
3986
3975
  const isInBoard = event.target instanceof Node && PlaitBoard.getBoardContainer(board).contains(event.target);
3987
3976
  const selectedImageElement = getSelectedImageElement(board);
@@ -3990,15 +3979,15 @@ const withNodeImage = (board) => {
3990
3979
  setImageFocus(board, selectedImageElement, false);
3991
3980
  }
3992
3981
  }
3993
- globalMouseup(event);
3982
+ globalPointerUp(event);
3994
3983
  };
3995
- board.setFragment = (data) => {
3984
+ board.setFragment = (data, rectangle) => {
3996
3985
  const selectedImageElement = getSelectedImageElement(board);
3997
3986
  if (selectedImageElement) {
3998
- setClipboardDataByImage(data, selectedImageElement.data.image);
3987
+ setClipboardDataByMedia(data, selectedImageElement.data.image, MediaKeys.image);
3999
3988
  return;
4000
3989
  }
4001
- setFragment(data);
3990
+ setFragment(data, rectangle);
4002
3991
  };
4003
3992
  board.deleteFragment = (data) => {
4004
3993
  const selectedImageElement = getSelectedImageElement(board);
@@ -4020,10 +4009,11 @@ const withNodeImage = (board) => {
4020
4009
  return;
4021
4010
  }
4022
4011
  }
4023
- const imageItem = getImageItemFromClipboard(data);
4012
+ const imageItem = getClipboardDataByMedia(data, MediaKeys.image);
4024
4013
  if (imageItem && (isSingleSelection || isSelectedImage)) {
4025
4014
  const selectedElement = (selectedElements[0] || getSelectedImageElement(board));
4026
4015
  MindTransforms.setImage(board, selectedElement, imageItem);
4016
+ return;
4027
4017
  }
4028
4018
  insertFragment(data, targetPoint);
4029
4019
  };
@@ -4031,25 +4021,30 @@ const withNodeImage = (board) => {
4031
4021
  };
4032
4022
 
4033
4023
  const withNodeResize = (board) => {
4034
- const { mousedown, mousemove, globalMouseup } = board;
4024
+ const { pointerDown, pointerMove, globalPointerUp } = board;
4035
4025
  let targetElement = null;
4036
4026
  let targetElementRef = null;
4037
4027
  let startPoint = null;
4038
- board.mousedown = (event) => {
4039
- if (targetElement) {
4028
+ board.pointerDown = (event) => {
4029
+ const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
4030
+ const newTargetElement = getSelectedTarget(board, point);
4031
+ if (newTargetElement) {
4032
+ PlaitBoard.getBoardContainer(board).classList.add(ResizeCursorClass['ew-resize']);
4033
+ targetElement = newTargetElement;
4040
4034
  startPoint = [event.x, event.y];
4041
4035
  return;
4042
4036
  }
4043
- mousedown(event);
4037
+ pointerDown(event);
4044
4038
  };
4045
- board.mousemove = (event) => {
4039
+ board.pointerMove = (event) => {
4046
4040
  if (PlaitBoard.isReadonly(board) || PlaitBoard.hasBeenTextEditing(board)) {
4047
- mousemove(event);
4041
+ pointerMove(event);
4048
4042
  return;
4049
4043
  }
4050
4044
  if (startPoint && targetElement && !isMindNodeResizing(board)) {
4051
4045
  // prevent text from being selected
4052
4046
  event.preventDefault();
4047
+ preventTouchMove(board, true);
4053
4048
  const endPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
4054
4049
  const distance = distanceBetweenPointAndPoint(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
4055
4050
  if (distance > PRESS_AND_MOVE_BUFFER) {
@@ -4066,6 +4061,7 @@ const withNodeResize = (board) => {
4066
4061
  if (isMindNodeResizing(board) && startPoint && targetElementRef) {
4067
4062
  // prevent text from being selected
4068
4063
  event.preventDefault();
4064
+ preventTouchMove(board, true);
4069
4065
  throttleRAF(() => {
4070
4066
  if (!startPoint) {
4071
4067
  return;
@@ -4090,26 +4086,26 @@ const withNodeResize = (board) => {
4090
4086
  // press and start drag when node is non selected
4091
4087
  if (!isDragging(board)) {
4092
4088
  const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
4093
- const newTargetElement = getTargetElement(board, point);
4089
+ const newTargetElement = getSelectedTarget(board, point);
4094
4090
  if (newTargetElement) {
4095
4091
  PlaitBoard.getBoardContainer(board).classList.add(ResizeCursorClass['ew-resize']);
4096
4092
  }
4097
4093
  else {
4098
4094
  PlaitBoard.getBoardContainer(board).classList.remove(ResizeCursorClass['ew-resize']);
4099
4095
  }
4100
- targetElement = newTargetElement;
4101
4096
  }
4102
4097
  }
4103
- mousemove(event);
4098
+ pointerMove(event);
4104
4099
  };
4105
- board.globalMouseup = (event) => {
4106
- globalMouseup(event);
4100
+ board.globalPointerUp = (event) => {
4101
+ globalPointerUp(event);
4107
4102
  if (isMindNodeResizing(board) || targetElement) {
4108
4103
  targetElement && removeResizing(board, targetElement);
4109
4104
  targetElementRef = null;
4110
4105
  targetElement = null;
4111
4106
  startPoint = null;
4112
4107
  MERGING.set(board, false);
4108
+ preventTouchMove(board, false);
4113
4109
  }
4114
4110
  };
4115
4111
  return board;
@@ -4133,7 +4129,7 @@ const removeResizing = (board, element) => {
4133
4129
  }
4134
4130
  IS_MIND_NODE_RESIZING.set(board, false);
4135
4131
  };
4136
- const getTargetElement = (board, point) => {
4132
+ const getSelectedTarget = (board, point) => {
4137
4133
  const selectedElements = getSelectedElements(board).filter(value => MindElement.isMindElement(board, value));
4138
4134
  if (selectedElements.length > 0) {
4139
4135
  const target = selectedElements.find(value => {
@@ -4150,9 +4146,52 @@ const getResizeActiveRectangle = (board, element) => {
4150
4146
  return { x: rectangle.x + rectangle.width - EXTEND_OFFSET, y: rectangle.y, width: EXTEND_OFFSET * 2, height: rectangle.height };
4151
4147
  };
4152
4148
 
4149
+ const withNodeImageResize = (board) => {
4150
+ const options = {
4151
+ key: 'mind-node-image',
4152
+ canResize: () => {
4153
+ return true;
4154
+ },
4155
+ detect: (point) => {
4156
+ const selectedMindElement = getSelectedImageElement(board);
4157
+ if (selectedMindElement) {
4158
+ const result = getHitImageResizeHandleDirection(board, selectedMindElement, point);
4159
+ if (result) {
4160
+ return {
4161
+ element: selectedMindElement,
4162
+ direction: result.direction,
4163
+ cursorClass: result.cursorClass
4164
+ };
4165
+ }
4166
+ }
4167
+ return null;
4168
+ },
4169
+ onResize: (resizeRef, resizeState) => {
4170
+ let offsetX = resizeState.offsetX;
4171
+ let offsetY = resizeState.offsetY;
4172
+ if (resizeRef.direction === ResizeDirection.nw || resizeRef.direction === ResizeDirection.sw) {
4173
+ offsetX = -offsetX;
4174
+ }
4175
+ const originWidth = resizeRef.element.data.image.width;
4176
+ const originHeight = resizeRef.element.data.image.height;
4177
+ let width = originWidth + offsetX;
4178
+ if (width <= 100) {
4179
+ width = 100;
4180
+ }
4181
+ const ratio = originWidth / width;
4182
+ const height = originHeight / ratio;
4183
+ const imageItem = Object.assign(Object.assign({}, resizeRef.element.data.image), { width, height });
4184
+ MindTransforms.setImage(board, PlaitNode.get(board, resizeRef.path), imageItem);
4185
+ addSelectedImageElement(board, PlaitNode.get(board, resizeRef.path));
4186
+ }
4187
+ };
4188
+ withResize(board, options);
4189
+ return board;
4190
+ };
4191
+
4153
4192
  const withMind = (baseBoard) => {
4154
4193
  const board = baseBoard;
4155
- const { drawElement, dblclick, insertFragment, setFragment, deleteFragment, isHitSelection, getRectangle, isMovable, isRecursion } = board;
4194
+ const { drawElement, dblclick, insertFragment, setFragment, isHitSelection, getRectangle, isMovable, isRecursion } = board;
4156
4195
  board.drawElement = (context) => {
4157
4196
  if (PlaitMind.isMind(context.element)) {
4158
4197
  return PlaitMindComponent;
@@ -4216,48 +4255,34 @@ const withMind = (baseBoard) => {
4216
4255
  }
4217
4256
  dblclick(event);
4218
4257
  };
4219
- board.setFragment = (data) => {
4220
- const selectedElements = getFirstLevelElement(getSelectedElements(board));
4221
- if (selectedElements.length) {
4222
- const elements = buildClipboardData(board, selectedElements);
4223
- setClipboardData(data, elements);
4224
- return;
4225
- }
4226
- setFragment(data);
4258
+ board.setFragment = (data, rectangle) => {
4259
+ const targetMindElements = getSelectedMindElements(board);
4260
+ const firstLevelElements = getFirstLevelElement(targetMindElements);
4261
+ if (firstLevelElements.length) {
4262
+ const elements = buildClipboardData(board, firstLevelElements, rectangle ? [rectangle.x, rectangle.y] : [0, 0]);
4263
+ setMindClipboardData(data, elements);
4264
+ }
4265
+ setFragment(data, rectangle);
4227
4266
  };
4228
4267
  board.insertFragment = (data, targetPoint) => {
4229
- if (board.options.readonly) {
4230
- insertFragment(data, targetPoint);
4231
- return;
4232
- }
4233
4268
  const elements = getDataFromClipboard(data);
4234
- if (elements.length) {
4235
- insertClipboardData(board, elements, targetPoint || [0, 0]);
4269
+ const mindElements = elements.filter(value => MindElement.isMindElement(board, value));
4270
+ if (elements.length > 0 && mindElements.length > 0) {
4271
+ insertClipboardData(board, mindElements, targetPoint);
4236
4272
  }
4237
- else {
4238
- const selectedElements = getSelectedElements(board);
4239
- if (selectedElements.length === 1) {
4273
+ else if (elements.length === 0) {
4274
+ const mindElements = getSelectedMindElements(board);
4275
+ if (mindElements.length === 1) {
4240
4276
  const text = getTextFromClipboard(data);
4241
4277
  if (text) {
4242
- insertClipboardText(board, selectedElements[0], buildText(text));
4278
+ insertClipboardText(board, mindElements[0], buildText(text));
4279
+ return;
4243
4280
  }
4244
4281
  }
4245
4282
  }
4246
4283
  insertFragment(data, targetPoint);
4247
4284
  };
4248
- board.deleteFragment = (data) => {
4249
- const selectedElements = getSelectedElements(board);
4250
- if (selectedElements.length) {
4251
- const deletableElements = getFirstLevelElement(selectedElements).reverse();
4252
- const abstractRefs = deleteElementHandleAbstract(board, deletableElements);
4253
- MindTransforms.setAbstractsByRefs(board, abstractRefs);
4254
- const refs = deleteElementsHandleRightNodeCount(board, selectedElements);
4255
- MindTransforms.setRightNodeCountByRefs(board, refs);
4256
- MindTransforms.removeElements(board, selectedElements);
4257
- }
4258
- deleteFragment(data);
4259
- };
4260
- return withNodeResize(withNodeImage(withNodeHoverDetect(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board))))))));
4285
+ return withNodeResize(withNodeImageResize(withNodeImage(withNodeHoverDetect(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board)))))))));
4261
4286
  };
4262
4287
 
4263
4288
  class MindEmojiBaseComponent {
@@ -4307,17 +4332,43 @@ class MindImageBaseComponent {
4307
4332
  set imageItem(value) {
4308
4333
  this.afterImageItemChange(this._imageItem, value);
4309
4334
  this._imageItem = value;
4335
+ this.drawFocus();
4310
4336
  }
4311
4337
  get imageItem() {
4312
4338
  return this._imageItem;
4313
4339
  }
4340
+ set isFocus(value) {
4341
+ this._isFocus = value;
4342
+ this.drawFocus();
4343
+ }
4344
+ get isFocus() {
4345
+ return this._isFocus;
4346
+ }
4314
4347
  get nativeElement() {
4315
4348
  return this.elementRef.nativeElement;
4316
4349
  }
4317
4350
  constructor(elementRef, cdr) {
4318
4351
  this.elementRef = elementRef;
4319
4352
  this.cdr = cdr;
4320
- this.isFocus = false;
4353
+ this.initialized = false;
4354
+ }
4355
+ ngOnInit() {
4356
+ this.activeGenerator = new ActiveGenerator(this.board, {
4357
+ activeStrokeWidth: 1,
4358
+ getRectangle: (element) => {
4359
+ return getImageForeignRectangle(this.board, this.element);
4360
+ },
4361
+ getStrokeWidthByElement: () => {
4362
+ return 0;
4363
+ }
4364
+ });
4365
+ this.initialized = true;
4366
+ }
4367
+ drawFocus() {
4368
+ if (this.initialized) {
4369
+ const com = PlaitElement.getComponent(this.element);
4370
+ this.activeGenerator.draw(this.element, com.g, { selected: this._isFocus });
4371
+ }
4321
4372
  }
4322
4373
  }
4323
4374
  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 });
@@ -4347,5 +4398,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
4347
4398
  * Generated bundle index. Do not edit.
4348
4399
  */
4349
4400
 
4350
- 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 };
4401
+ 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 };
4351
4402
  //# sourceMappingURL=plait-mind.mjs.map