@plait/mind 0.26.0 → 0.27.0-next.1

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,13 +1,13 @@
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, getRectangleResizeHandleRefs, isExpandHotkey, isTabHotkey, isEnterHotkey, isVirtualKey, isSpaceHotkey, MediaKeys, ResizeHandle, 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
- import { isKeyHotkey } from 'is-hotkey';
11
11
  import { pointsOnBezierCurves } from 'points-on-curve';
12
12
  import { take, filter } from 'rxjs/operators';
13
13
  import * as i1 from '@angular/common';
@@ -381,11 +381,20 @@ function getImageForeignRectangle(board, element) {
381
381
  width,
382
382
  height
383
383
  };
384
- return RectangleClient.getOutlineRectangle(rectangle, -6);
384
+ return rectangle;
385
385
  }
386
386
  const isHitImage = (board, element, range) => {
387
- const client = getImageForeignRectangle(board, element);
388
- return RectangleClient.isHit(RectangleClient.toRectangleClient([range.anchor, range.focus]), client);
387
+ const imageRectangle = getImageForeignRectangle(board, element);
388
+ const imageOutlineRectangle = RectangleClient.getOutlineRectangle(imageRectangle, -RESIZE_HANDLE_DIAMETER / 2);
389
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([range.anchor, range.focus]), imageOutlineRectangle);
390
+ };
391
+ const getHitImageResizeHandleDirection = (board, element, point) => {
392
+ const imageRectangle = getImageForeignRectangle(board, element);
393
+ const resizeHandleRefs = getRectangleResizeHandleRefs(imageRectangle, RESIZE_HANDLE_DIAMETER);
394
+ const result = resizeHandleRefs.find(resizeHandleRef => {
395
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), resizeHandleRef.rectangle);
396
+ });
397
+ return result;
389
398
  };
390
399
 
391
400
  function editTopic(element) {
@@ -401,6 +410,10 @@ const temporaryDisableSelection = (board) => {
401
410
  board.setPluginOptions(PlaitPluginKey.withSelection, Object.assign({}, currentOptions));
402
411
  }, 0);
403
412
  };
413
+ const getSelectedMindElements = (board) => {
414
+ const selectedElements = getSelectedElements(board).filter(value => MindElement.isMindElement(board, value));
415
+ return selectedElements;
416
+ };
404
417
 
405
418
  const createEmptyMind = (point) => {
406
419
  const element = createMindElement('思维导图', 72, ROOT_TOPIC_HEIGHT, { layout: MindLayoutType.right });
@@ -1283,18 +1296,6 @@ const getShapeByElement = (board, element) => {
1283
1296
  return shape || MindElementShape.roundRectangle;
1284
1297
  };
1285
1298
 
1286
- function isVirtualKey(e) {
1287
- const isMod = e.ctrlKey || e.metaKey;
1288
- const isAlt = isKeyHotkey('alt', e);
1289
- const isShift = isKeyHotkey('shift', e);
1290
- const isCapsLock = e.key.includes('CapsLock');
1291
- const isTab = e.key.includes('Tab');
1292
- const isEsc = e.key.includes('Escape');
1293
- const isF = e.key.startsWith('F');
1294
- const isArrow = e.key.includes('Arrow') ? true : false;
1295
- return isCapsLock || isMod || isAlt || isArrow || isShift || isTab || isEsc || isF;
1296
- }
1297
-
1298
1299
  const IS_DRAGGING = new WeakMap();
1299
1300
  const addActiveOnDragOrigin = (activeElement) => {
1300
1301
  const activeComponent = PlaitElement.getComponent(activeElement);
@@ -2313,9 +2314,7 @@ const MindElement = {
2313
2314
  return isIndentedLayout(_layout);
2314
2315
  },
2315
2316
  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)) {
2317
+ if (element.data && element.data.topic && element.width && element.height) {
2319
2318
  return true;
2320
2319
  }
2321
2320
  else {
@@ -2942,7 +2941,6 @@ class NodeImageDrawer {
2942
2941
  this.g = createG();
2943
2942
  const foreignRectangle = getImageForeignRectangle(this.board, element);
2944
2943
  this.foreignObject = createForeignObject(foreignRectangle.x, foreignRectangle.y, foreignRectangle.width, foreignRectangle.height);
2945
- this.foreignObject.style.padding = `6px`;
2946
2944
  this.g.append(this.foreignObject);
2947
2945
  const componentType = this.board.getPluginOptions(WithMindPluginKey).imageComponentType;
2948
2946
  if (!componentType) {
@@ -3006,19 +3004,23 @@ class MindNodeComponent extends PlaitPluginElementComponent {
3006
3004
  this.collapseDrawer = new CollapseDrawer(this.board);
3007
3005
  this.imageDrawer = new NodeImageDrawer(this.board, this.viewContainerRef);
3008
3006
  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);
3007
+ this.textManage = new TextManage(this.board, this.viewContainerRef, {
3008
+ getRectangle: () => {
3009
+ const rect = getTopicRectangleByNode(this.board, this.node);
3010
+ return rect;
3011
+ },
3012
+ onValueChangeHandle: (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
+ },
3022
+ textPlugins: plugins
3023
+ });
3022
3024
  }
3023
3025
  ngOnInit() {
3024
3026
  super.ngOnInit();
@@ -3261,7 +3263,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
3261
3263
 
3262
3264
  const DRAG_MOVE_BUFFER = 5;
3263
3265
  const withNodeDnd = (board) => {
3264
- const { mousedown, mousemove, globalMouseup } = board;
3266
+ const { pointerDown, pointerMove, globalPointerUp } = board;
3265
3267
  let activeElements = [];
3266
3268
  let correspondingElements = [];
3267
3269
  let startPoint;
@@ -3269,12 +3271,12 @@ const withNodeDnd = (board) => {
3269
3271
  let fakeDropNodeG;
3270
3272
  let dropTarget = null;
3271
3273
  let targetPath;
3272
- board.mousedown = (event) => {
3274
+ board.pointerDown = (event) => {
3273
3275
  if (PlaitBoard.isReadonly(board) ||
3274
3276
  PlaitBoard.hasBeenTextEditing(board) ||
3275
3277
  !PlaitBoard.isPointer(board, PlaitPointerType.selection) ||
3276
3278
  !isMainPointer(event)) {
3277
- mousedown(event);
3279
+ pointerDown(event);
3278
3280
  return;
3279
3281
  }
3280
3282
  const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
@@ -3301,9 +3303,9 @@ const withNodeDnd = (board) => {
3301
3303
  if (activeElements.length) {
3302
3304
  correspondingElements = getOverallAbstracts(board, activeElements);
3303
3305
  }
3304
- mousedown(event);
3306
+ pointerDown(event);
3305
3307
  };
3306
- board.mousemove = (event) => {
3308
+ board.pointerMove = (event) => {
3307
3309
  if (!board.options.readonly && (activeElements === null || activeElements === void 0 ? void 0 : activeElements.length) && startPoint) {
3308
3310
  // prevent text from being selected
3309
3311
  event.preventDefault();
@@ -3334,9 +3336,9 @@ const withNodeDnd = (board) => {
3334
3336
  });
3335
3337
  PlaitBoard.getHost(board).appendChild(dragFakeNodeG);
3336
3338
  }
3337
- mousemove(event);
3339
+ pointerMove(event);
3338
3340
  };
3339
- board.globalMouseup = (event) => {
3341
+ board.globalPointerUp = (event) => {
3340
3342
  const firstLevelElements = getFirstLevelElement(activeElements);
3341
3343
  if (!board.options.readonly && firstLevelElements.length) {
3342
3344
  firstLevelElements.push(...correspondingElements);
@@ -3425,12 +3427,12 @@ const withNodeDnd = (board) => {
3425
3427
  fakeDropNodeG = undefined;
3426
3428
  dropTarget = null;
3427
3429
  }
3428
- globalMouseup(event);
3430
+ globalPointerUp(event);
3429
3431
  };
3430
3432
  return board;
3431
3433
  };
3432
3434
 
3433
- const buildClipboardData = (board, selectedElements) => {
3435
+ const buildClipboardData = (board, selectedElements, startPoint) => {
3434
3436
  let result = [];
3435
3437
  // get overall abstract
3436
3438
  const overallAbstracts = getOverallAbstracts(board, selectedElements);
@@ -3440,11 +3442,10 @@ const buildClipboardData = (board, selectedElements) => {
3440
3442
  const newSelectedElements = selectedElements.filter(value => !validAbstractRefs.find(ref => ref.abstract === value));
3441
3443
  newSelectedElements.push(...validAbstractRefs.map(value => value.abstract));
3442
3444
  const selectedMindNodes = newSelectedElements.map(value => MindElement.getNode(value));
3443
- const nodesRectangle = getRectangleByElements(board, newSelectedElements, true);
3444
3445
  newSelectedElements.forEach((element, index) => {
3445
3446
  // handle relative location
3446
3447
  const nodeRectangle = getRectangleByNode(selectedMindNodes[index]);
3447
- const points = [[nodeRectangle.x - nodesRectangle.x, nodeRectangle.y - nodesRectangle.y]];
3448
+ const points = [[nodeRectangle.x - startPoint[0], nodeRectangle.y - startPoint[1]]];
3448
3449
  // handle invalid abstract
3449
3450
  const abstractRef = validAbstractRefs.find(ref => ref.abstract === element);
3450
3451
  if (AbstractNode.isAbstract(element) && abstractRef) {
@@ -3467,37 +3468,12 @@ const buildClipboardData = (board, selectedElements) => {
3467
3468
  });
3468
3469
  return result;
3469
3470
  };
3470
- const setClipboardData = (data, elements) => {
3471
- const stringObj = JSON.stringify(elements);
3472
- const encoded = window.btoa(encodeURIComponent(stringObj));
3471
+ const setMindClipboardData = (data, elements) => {
3473
3472
  const text = elements.reduce((string, currentNode) => {
3474
3473
  return string + extractNodesText(currentNode);
3475
3474
  }, '');
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;
3475
+ setClipboardData(data, elements);
3476
+ setClipboardDataByText(data, text);
3501
3477
  };
3502
3478
  const insertClipboardData = (board, elements, targetPoint) => {
3503
3479
  let newElement, path;
@@ -3695,8 +3671,10 @@ const withCreateMind = (board) => {
3695
3671
  const nodeG = drawRoundRectangleByElement(board, nodeRectangle, emptyMind);
3696
3672
  const topicRectangle = getTopicRectangleByElement(newBoard, nodeRectangle, emptyMind);
3697
3673
  if (!fakeCreateNodeRef) {
3698
- const textManage = new TextManage(board, PlaitBoard.getComponent(board).viewContainerRef, () => {
3699
- return topicRectangle;
3674
+ const textManage = new TextManage(board, PlaitBoard.getComponent(board).viewContainerRef, {
3675
+ getRectangle: () => {
3676
+ return topicRectangle;
3677
+ }
3700
3678
  });
3701
3679
  PlaitBoard.getComponent(board)
3702
3680
  .viewContainerRef.injector.get(NgZone)
@@ -3765,7 +3743,7 @@ const withCreateMind = (board) => {
3765
3743
 
3766
3744
  const withMindHotkey = (baseBoard) => {
3767
3745
  const board = baseBoard;
3768
- const { keydown } = board;
3746
+ const { keydown, deleteFragment } = board;
3769
3747
  board.keydown = (event) => {
3770
3748
  const selectedElements = getSelectedElements(board);
3771
3749
  const isSingleSelection = selectedElements.length === 1;
@@ -3805,25 +3783,7 @@ const withMindHotkey = (baseBoard) => {
3805
3783
  insertMindElement(board, targetElement, findNewSiblingNodePath(board, targetElement));
3806
3784
  return;
3807
3785
  }
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
- if (!isVirtualKey(event) && !isSpaceHotkey(event) && isSingleSelection) {
3786
+ if (!isVirtualKey(event) && !isSpaceHotkey(event) && isSingleSelection && MindElement.isMindElement(board, targetElement)) {
3827
3787
  event.preventDefault();
3828
3788
  editTopic(targetElement);
3829
3789
  return;
@@ -3831,6 +3791,22 @@ const withMindHotkey = (baseBoard) => {
3831
3791
  }
3832
3792
  keydown(event);
3833
3793
  };
3794
+ board.deleteFragment = (data) => {
3795
+ const targetMindElements = getSelectedMindElements(board);
3796
+ if (targetMindElements.length) {
3797
+ const firstLevelElements = getFirstLevelElement(targetMindElements).reverse();
3798
+ const abstractRefs = deleteElementHandleAbstract(board, firstLevelElements);
3799
+ MindTransforms.setAbstractsByRefs(board, abstractRefs);
3800
+ const refs = deleteElementsHandleRightNodeCount(board, targetMindElements);
3801
+ MindTransforms.setRightNodeCountByRefs(board, refs);
3802
+ MindTransforms.removeElements(board, targetMindElements);
3803
+ const nextSelected = getNextSelectedElement(board, firstLevelElements);
3804
+ if (nextSelected) {
3805
+ addSelectedElement(board, nextSelected);
3806
+ }
3807
+ }
3808
+ deleteFragment(data);
3809
+ };
3834
3810
  return board;
3835
3811
  };
3836
3812
  const getNextSelectedElement = (board, firstLevelElements) => {
@@ -3863,18 +3839,6 @@ const getNextSelectedElement = (board, firstLevelElements) => {
3863
3839
  }
3864
3840
  return activeElement;
3865
3841
  };
3866
- const isExpandHotkey = (event) => {
3867
- return isKeyHotkey('mod+/', event);
3868
- };
3869
- const isTabHotkey = (event) => {
3870
- return event.key === 'Tab';
3871
- };
3872
- const isEnterHotkey = (event) => {
3873
- return event.key === 'Enter';
3874
- };
3875
- const isSpaceHotkey = (event) => {
3876
- return event.code === 'Space';
3877
- };
3878
3842
 
3879
3843
  const mouseMoveHandle = (board, event, nodeHoveredExtendRef) => {
3880
3844
  let target = null;
@@ -3943,24 +3907,24 @@ const withNodeHoverDetect = (board) => {
3943
3907
  };
3944
3908
 
3945
3909
  const withNodeImage = (board) => {
3946
- const { keydown, mousedown, globalMouseup, setFragment, insertFragment, deleteFragment } = board;
3947
- board.mousedown = (event) => {
3910
+ const { keydown, pointerDown, globalPointerUp, setFragment, insertFragment, deleteFragment } = board;
3911
+ board.pointerDown = (event) => {
3948
3912
  const selectedImageElement = getSelectedImageElement(board);
3949
3913
  if (PlaitBoard.isReadonly(board) || !isMainPointer(event) || !PlaitBoard.isPointer(board, PlaitPointerType.selection)) {
3950
3914
  if (selectedImageElement) {
3951
3915
  setImageFocus(board, selectedImageElement, false);
3952
3916
  }
3953
- mousedown(event);
3917
+ pointerDown(event);
3954
3918
  return;
3955
3919
  }
3956
3920
  const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3957
3921
  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) {
3922
+ const hitImageElements = getHitElements(board, { ranges: [range] }, (value) => MindElement.isMindElement(board, value) && MindElement.hasImage(value));
3923
+ const hasImage = hitImageElements.length;
3924
+ const hitImage = hasImage > 0 && isHitImage(board, hitImageElements[0], range);
3925
+ if (selectedImageElement && hitImage && hitImageElements[0] === selectedImageElement) {
3962
3926
  temporaryDisableSelection(board);
3963
- mousedown(event);
3927
+ pointerDown(event);
3964
3928
  return;
3965
3929
  }
3966
3930
  if (selectedImageElement) {
@@ -3968,9 +3932,9 @@ const withNodeImage = (board) => {
3968
3932
  }
3969
3933
  if (hitImage) {
3970
3934
  temporaryDisableSelection(board);
3971
- setImageFocus(board, hitElements[0], true);
3935
+ setImageFocus(board, hitImageElements[0], true);
3972
3936
  }
3973
- mousedown(event);
3937
+ pointerDown(event);
3974
3938
  };
3975
3939
  board.keydown = (event) => {
3976
3940
  const selectedImageElement = getSelectedImageElement(board);
@@ -3981,7 +3945,7 @@ const withNodeImage = (board) => {
3981
3945
  }
3982
3946
  keydown(event);
3983
3947
  };
3984
- board.globalMouseup = (event) => {
3948
+ board.globalPointerUp = (event) => {
3985
3949
  if (PlaitBoard.isFocus(board)) {
3986
3950
  const isInBoard = event.target instanceof Node && PlaitBoard.getBoardContainer(board).contains(event.target);
3987
3951
  const selectedImageElement = getSelectedImageElement(board);
@@ -3990,15 +3954,15 @@ const withNodeImage = (board) => {
3990
3954
  setImageFocus(board, selectedImageElement, false);
3991
3955
  }
3992
3956
  }
3993
- globalMouseup(event);
3957
+ globalPointerUp(event);
3994
3958
  };
3995
- board.setFragment = (data) => {
3959
+ board.setFragment = (data, rectangle) => {
3996
3960
  const selectedImageElement = getSelectedImageElement(board);
3997
3961
  if (selectedImageElement) {
3998
- setClipboardDataByImage(data, selectedImageElement.data.image);
3962
+ setClipboardDataByMedia(data, selectedImageElement.data.image, MediaKeys.image);
3999
3963
  return;
4000
3964
  }
4001
- setFragment(data);
3965
+ setFragment(data, rectangle);
4002
3966
  };
4003
3967
  board.deleteFragment = (data) => {
4004
3968
  const selectedImageElement = getSelectedImageElement(board);
@@ -4020,10 +3984,11 @@ const withNodeImage = (board) => {
4020
3984
  return;
4021
3985
  }
4022
3986
  }
4023
- const imageItem = getImageItemFromClipboard(data);
3987
+ const imageItem = getClipboardDataByMedia(data, MediaKeys.image);
4024
3988
  if (imageItem && (isSingleSelection || isSelectedImage)) {
4025
3989
  const selectedElement = (selectedElements[0] || getSelectedImageElement(board));
4026
3990
  MindTransforms.setImage(board, selectedElement, imageItem);
3991
+ return;
4027
3992
  }
4028
3993
  insertFragment(data, targetPoint);
4029
3994
  };
@@ -4031,25 +3996,30 @@ const withNodeImage = (board) => {
4031
3996
  };
4032
3997
 
4033
3998
  const withNodeResize = (board) => {
4034
- const { mousedown, mousemove, globalMouseup } = board;
3999
+ const { pointerDown, pointerMove, globalPointerUp } = board;
4035
4000
  let targetElement = null;
4036
4001
  let targetElementRef = null;
4037
4002
  let startPoint = null;
4038
- board.mousedown = (event) => {
4039
- if (targetElement) {
4003
+ board.pointerDown = (event) => {
4004
+ const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
4005
+ const newTargetElement = getSelectedTarget(board, point);
4006
+ if (newTargetElement) {
4007
+ PlaitBoard.getBoardContainer(board).classList.add(ResizeCursorClass['ew-resize']);
4008
+ targetElement = newTargetElement;
4040
4009
  startPoint = [event.x, event.y];
4041
4010
  return;
4042
4011
  }
4043
- mousedown(event);
4012
+ pointerDown(event);
4044
4013
  };
4045
- board.mousemove = (event) => {
4014
+ board.pointerMove = (event) => {
4046
4015
  if (PlaitBoard.isReadonly(board) || PlaitBoard.hasBeenTextEditing(board)) {
4047
- mousemove(event);
4016
+ pointerMove(event);
4048
4017
  return;
4049
4018
  }
4050
4019
  if (startPoint && targetElement && !isMindNodeResizing(board)) {
4051
4020
  // prevent text from being selected
4052
4021
  event.preventDefault();
4022
+ preventTouchMove(board, true);
4053
4023
  const endPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
4054
4024
  const distance = distanceBetweenPointAndPoint(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
4055
4025
  if (distance > PRESS_AND_MOVE_BUFFER) {
@@ -4066,6 +4036,7 @@ const withNodeResize = (board) => {
4066
4036
  if (isMindNodeResizing(board) && startPoint && targetElementRef) {
4067
4037
  // prevent text from being selected
4068
4038
  event.preventDefault();
4039
+ preventTouchMove(board, true);
4069
4040
  throttleRAF(() => {
4070
4041
  if (!startPoint) {
4071
4042
  return;
@@ -4090,26 +4061,26 @@ const withNodeResize = (board) => {
4090
4061
  // press and start drag when node is non selected
4091
4062
  if (!isDragging(board)) {
4092
4063
  const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
4093
- const newTargetElement = getTargetElement(board, point);
4064
+ const newTargetElement = getSelectedTarget(board, point);
4094
4065
  if (newTargetElement) {
4095
4066
  PlaitBoard.getBoardContainer(board).classList.add(ResizeCursorClass['ew-resize']);
4096
4067
  }
4097
4068
  else {
4098
4069
  PlaitBoard.getBoardContainer(board).classList.remove(ResizeCursorClass['ew-resize']);
4099
4070
  }
4100
- targetElement = newTargetElement;
4101
4071
  }
4102
4072
  }
4103
- mousemove(event);
4073
+ pointerMove(event);
4104
4074
  };
4105
- board.globalMouseup = (event) => {
4106
- globalMouseup(event);
4075
+ board.globalPointerUp = (event) => {
4076
+ globalPointerUp(event);
4107
4077
  if (isMindNodeResizing(board) || targetElement) {
4108
4078
  targetElement && removeResizing(board, targetElement);
4109
4079
  targetElementRef = null;
4110
4080
  targetElement = null;
4111
4081
  startPoint = null;
4112
4082
  MERGING.set(board, false);
4083
+ preventTouchMove(board, false);
4113
4084
  }
4114
4085
  };
4115
4086
  return board;
@@ -4133,7 +4104,7 @@ const removeResizing = (board, element) => {
4133
4104
  }
4134
4105
  IS_MIND_NODE_RESIZING.set(board, false);
4135
4106
  };
4136
- const getTargetElement = (board, point) => {
4107
+ const getSelectedTarget = (board, point) => {
4137
4108
  const selectedElements = getSelectedElements(board).filter(value => MindElement.isMindElement(board, value));
4138
4109
  if (selectedElements.length > 0) {
4139
4110
  const target = selectedElements.find(value => {
@@ -4150,9 +4121,52 @@ const getResizeActiveRectangle = (board, element) => {
4150
4121
  return { x: rectangle.x + rectangle.width - EXTEND_OFFSET, y: rectangle.y, width: EXTEND_OFFSET * 2, height: rectangle.height };
4151
4122
  };
4152
4123
 
4124
+ const withNodeImageResize = (board) => {
4125
+ const options = {
4126
+ key: 'mind-node-image',
4127
+ canResize: () => {
4128
+ return true;
4129
+ },
4130
+ detect: (point) => {
4131
+ const selectedMindElement = getSelectedImageElement(board);
4132
+ if (selectedMindElement) {
4133
+ const result = getHitImageResizeHandleDirection(board, selectedMindElement, point);
4134
+ if (result) {
4135
+ return {
4136
+ element: selectedMindElement,
4137
+ handle: result.handle,
4138
+ cursorClass: result.cursorClass
4139
+ };
4140
+ }
4141
+ }
4142
+ return null;
4143
+ },
4144
+ onResize: (resizeRef, resizeState) => {
4145
+ let offsetX = resizeState.offsetX;
4146
+ let offsetY = resizeState.offsetY;
4147
+ if (resizeRef.handle === ResizeHandle.nw || resizeRef.handle === ResizeHandle.sw) {
4148
+ offsetX = -offsetX;
4149
+ }
4150
+ const originWidth = resizeRef.element.data.image.width;
4151
+ const originHeight = resizeRef.element.data.image.height;
4152
+ let width = originWidth + offsetX;
4153
+ if (width <= 100) {
4154
+ width = 100;
4155
+ }
4156
+ const ratio = originWidth / width;
4157
+ const height = originHeight / ratio;
4158
+ const imageItem = Object.assign(Object.assign({}, resizeRef.element.data.image), { width, height });
4159
+ MindTransforms.setImage(board, PlaitNode.get(board, resizeRef.path), imageItem);
4160
+ addSelectedImageElement(board, PlaitNode.get(board, resizeRef.path));
4161
+ }
4162
+ };
4163
+ withResize(board, options);
4164
+ return board;
4165
+ };
4166
+
4153
4167
  const withMind = (baseBoard) => {
4154
4168
  const board = baseBoard;
4155
- const { drawElement, dblclick, insertFragment, setFragment, deleteFragment, isHitSelection, getRectangle, isMovable, isRecursion } = board;
4169
+ const { drawElement, dblclick, insertFragment, setFragment, isHitSelection, getRectangle, isMovable, isRecursion } = board;
4156
4170
  board.drawElement = (context) => {
4157
4171
  if (PlaitMind.isMind(context.element)) {
4158
4172
  return PlaitMindComponent;
@@ -4216,48 +4230,34 @@ const withMind = (baseBoard) => {
4216
4230
  }
4217
4231
  dblclick(event);
4218
4232
  };
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);
4233
+ board.setFragment = (data, rectangle) => {
4234
+ const targetMindElements = getSelectedMindElements(board);
4235
+ const firstLevelElements = getFirstLevelElement(targetMindElements);
4236
+ if (firstLevelElements.length) {
4237
+ const elements = buildClipboardData(board, firstLevelElements, rectangle ? [rectangle.x, rectangle.y] : [0, 0]);
4238
+ setMindClipboardData(data, elements);
4239
+ }
4240
+ setFragment(data, rectangle);
4227
4241
  };
4228
4242
  board.insertFragment = (data, targetPoint) => {
4229
- if (board.options.readonly) {
4230
- insertFragment(data, targetPoint);
4231
- return;
4232
- }
4233
4243
  const elements = getDataFromClipboard(data);
4234
- if (elements.length) {
4235
- insertClipboardData(board, elements, targetPoint || [0, 0]);
4244
+ const mindElements = elements.filter(value => MindElement.isMindElement(board, value));
4245
+ if (elements.length > 0 && mindElements.length > 0) {
4246
+ insertClipboardData(board, mindElements, targetPoint);
4236
4247
  }
4237
- else {
4238
- const selectedElements = getSelectedElements(board);
4239
- if (selectedElements.length === 1) {
4248
+ else if (elements.length === 0) {
4249
+ const mindElements = getSelectedMindElements(board);
4250
+ if (mindElements.length === 1) {
4240
4251
  const text = getTextFromClipboard(data);
4241
4252
  if (text) {
4242
- insertClipboardText(board, selectedElements[0], buildText(text));
4253
+ insertClipboardText(board, mindElements[0], buildText(text));
4254
+ return;
4243
4255
  }
4244
4256
  }
4245
4257
  }
4246
4258
  insertFragment(data, targetPoint);
4247
4259
  };
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))))))));
4260
+ return withNodeResize(withNodeImageResize(withNodeImage(withNodeHoverDetect(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board)))))))));
4261
4261
  };
4262
4262
 
4263
4263
  class MindEmojiBaseComponent {
@@ -4307,17 +4307,48 @@ class MindImageBaseComponent {
4307
4307
  set imageItem(value) {
4308
4308
  this.afterImageItemChange(this._imageItem, value);
4309
4309
  this._imageItem = value;
4310
+ this.drawFocus();
4310
4311
  }
4311
4312
  get imageItem() {
4312
4313
  return this._imageItem;
4313
4314
  }
4315
+ set isFocus(value) {
4316
+ this._isFocus = value;
4317
+ this.drawFocus();
4318
+ }
4319
+ get isFocus() {
4320
+ return this._isFocus;
4321
+ }
4314
4322
  get nativeElement() {
4315
4323
  return this.elementRef.nativeElement;
4316
4324
  }
4317
4325
  constructor(elementRef, cdr) {
4318
4326
  this.elementRef = elementRef;
4319
4327
  this.cdr = cdr;
4320
- this.isFocus = false;
4328
+ this.initialized = false;
4329
+ }
4330
+ ngOnInit() {
4331
+ this.activeGenerator = new ActiveGenerator(this.board, {
4332
+ activeStrokeWidth: 1,
4333
+ getRectangle: (element) => {
4334
+ return getImageForeignRectangle(this.board, this.element);
4335
+ },
4336
+ getStrokeWidthByElement: () => {
4337
+ return 0;
4338
+ }
4339
+ });
4340
+ this.initialized = true;
4341
+ }
4342
+ drawFocus() {
4343
+ if (this.initialized) {
4344
+ const com = PlaitElement.getComponent(this.element);
4345
+ this.activeGenerator.draw(this.element, com.g, { selected: this._isFocus });
4346
+ }
4347
+ }
4348
+ ngOnDestroy() {
4349
+ if (this.activeGenerator) {
4350
+ this.activeGenerator.destroy();
4351
+ }
4321
4352
  }
4322
4353
  }
4323
4354
  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 +4378,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
4347
4378
  * Generated bundle index. Do not edit.
4348
4379
  */
4349
4380
 
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 };
4381
+ 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, removeActiveOnDragOrigin, removeSelectedImageElement, selectImage, separateChildren, setImageFocus, setIsDragging, temporaryDisableSelection, withMind, withMindExtend };
4351
4382
  //# sourceMappingURL=plait-mind.mjs.map