@plait/mind 0.89.1 → 0.90.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,4 +1,4 @@
1
- import { DEFAULT_COLOR, DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, rgbaToHEX, PlaitElement, PlaitNode, Path, isNullOrUndefined, PlaitBoard, getSelectedElements, getI18nValue, idCreator, Transforms, clearSelectedElement, addSelectedElement, distanceBetweenPointAndRectangle, RectangleClient, setDragging, depthFirstRecursion, getIsRecursionFunc, drawRoundRectangle, drawLinearPath, drawBezierPath, setStrokeLinecap, createG, createForeignObject, updateForeignObject, getRectangleByElements, toActiveRectangleFromViewBoxRectangle, ACTIVE_STROKE_WIDTH, SELECTION_RECTANGLE_CLASS_NAME, NODE_TO_PARENT, removeSelectedElement, PlaitHistoryBoard, isSelectedElement, createText, isSelectionMoving, isDragging, isMovingElements, NODE_TO_INDEX, PlaitPointerType, isMainPointer, toViewBoxPoint, toHostPoint, getHitElementByPoint, distanceBetweenPointAndPoint, CoreTransforms, toActivePointFromViewBoxPoint, BoardTransforms, throttleRAF, isContextmenu, temporaryDisableSelection, hotkeys, createClipboardContext, WritableClipboardType, Point, ResizeCursorClass, WritableClipboardOperationType, addOrCreateClipboardContext } from '@plait/core';
1
+ import { DEFAULT_COLOR, DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, rgbaToHEX, PlaitElement, PlaitNode, Path, isNullOrUndefined, PlaitBoard, getSelectedElements, getI18nValue, idCreator, Transforms, clearSelectedElement, addSelectedElement, distanceBetweenPointAndRectangle, RectangleClient, setDragging, depthFirstRecursion, getIsRecursionFunc, drawRoundRectangle, drawLinearPath, drawBezierPath, setStrokeLinecap, createG, createForeignObject, updateForeignObject, getRectangleByElements, toActiveRectangleFromViewBoxRectangle, ACTIVE_STROKE_WIDTH, SELECTION_RECTANGLE_CLASS_NAME, NODE_TO_PARENT, removeSelectedElement, PlaitHistoryBoard, createText, isSelectionMoving, isDragging, isMovingElements, NODE_TO_INDEX, PlaitPointerType, isMainPointer, toViewBoxPoint, toHostPoint, getHitElementByPoint, distanceBetweenPointAndPoint, CoreTransforms, toActivePointFromViewBoxPoint, BoardTransforms, throttleRAF, getElementById, isTouchDevice, isSelectedElement, isContextmenu, temporaryDisableSelection, hotkeys, createClipboardContext, WritableClipboardType, Point, ResizeCursorClass, WritableClipboardOperationType, addOrCreateClipboardContext } from '@plait/core';
2
2
  import { MindLayoutType, AbstractNode, isIndentedLayout, isHorizontalLogicLayout, ConnectingPosition, isHorizontalLayout, getNonAbstractChildren, isStandardLayout, isLeftLayout, isRightLayout, isVerticalLogicLayout, isTopLayout, isBottomLayout, getCorrectStartEnd, getAbstractLayout, GlobalLayout } from '@plait/layouts';
3
3
  import { StrokeStyle, getFirstTextManage, buildText, getElementSize, DEFAULT_FONT_FAMILY, RESIZE_HANDLE_DIAMETER, getRectangleResizeHandleRefs, addElementOfFocusedImage, ImageGenerator, removeElementOfFocusedImage, getStrokeLineDash, getXDistanceBetweenPoint, moveXOfPoint, moveYOfPoint, Generator, PropertyTransforms, TRANSPARENT, measureElement, isResizing, CommonElementFlavour, WithTextPluginKey, TextManage, isDrawingMode, isDndMode, setCreationMode, BoardCreationMode, isExpandHotkey, isTabHotkey, isEnterHotkey, isVirtualKey, isDelete, isSpaceHotkey, getElementOfFocusedImage, acceptImageTypes, buildImage, withResize, getElementsText } from '@plait/common';
4
4
  import { DEFAULT_FONT_SIZE, PlaitMarkEditor, MarkTypes, FontSizes } from '@plait/text-plugins';
@@ -2152,6 +2152,9 @@ function findNewChildNodePath(board, element) {
2152
2152
  const children = getNonAbstractChildren(element);
2153
2153
  return PlaitBoard.findPath(board, element).concat(children.length);
2154
2154
  }
2155
+ function findNewRightChildNodePath(board, element, rightNodeCount) {
2156
+ return PlaitBoard.findPath(board, element).concat(rightNodeCount ? rightNodeCount - 1 : 0);
2157
+ }
2155
2158
  function findNewSiblingNodePath(board, element) {
2156
2159
  const path = PlaitBoard.findPath(board, element);
2157
2160
  return Path$1.next(path);
@@ -2690,8 +2693,10 @@ class NodeShapeGenerator extends Generator {
2690
2693
  class NodeMoreGenerator extends Generator {
2691
2694
  static { this.key = 'mind-node-more'; }
2692
2695
  canDraw(element, extraData) {
2693
- if (((extraData?.isHovered || extraData?.isHoveredCollapseArea || extraData?.isHoveredAddArea) && canHandleNodeMore(this.board)) ||
2694
- (extraData?.isSelected && isLastSelectedMindElement(this.board, element) && canHandleNodeMore(this.board)) ||
2696
+ const selectedElements = getSelectedElements(this.board);
2697
+ if (((extraData?.isHit || extraData?.isHitAwarenessRectangle || extraData?.isHitStandardLeftAwarenessRectangle) &&
2698
+ canHandleNodeMore(this.board)) ||
2699
+ (extraData?.isSelected && selectedElements.length === 1 && canHandleNodeMore(this.board)) ||
2695
2700
  element.isCollapsed) {
2696
2701
  return true;
2697
2702
  }
@@ -2700,25 +2705,14 @@ class NodeMoreGenerator extends Generator {
2700
2705
  draw(element, extraData) {
2701
2706
  const moreGContainer = createG();
2702
2707
  const stroke = getBranchColorByMindElement(this.board, element);
2703
- const layoutDirection = getNodeMoreLayoutDirection(this.board, element);
2704
- const moreStartAndEnd = getMoreStartAndEnd(this.board, element, layoutDirection);
2705
- const collapseOrExpandCenter = moveXOfPoint(moreStartAndEnd[1], NODE_MORE_ICON_DIAMETER / 2, layoutDirection);
2706
- const hasChildren = element.children.length > 0;
2707
- const isShowCollapseOrAdd = !element.isCollapsed &&
2708
- (isSelectedElement(this.board, element) ||
2709
- !!extraData?.isHovered ||
2710
- !!extraData?.isHoveredCollapseArea ||
2711
- !!extraData?.isHoveredAddArea);
2712
- const isShowCollapse = isShowCollapseOrAdd && hasChildren && !PlaitMind.isMind(element);
2713
- const isShowAdd = isShowCollapseOrAdd && !PlaitBoard.isReadonly(this.board);
2714
- const addCenter = (isShowCollapseOrAdd && getAddCenterByCollapseOrExpandCenter(element, collapseOrExpandCenter, layoutDirection)) || null;
2715
- this.toggleCollapseOrAdd(collapseOrExpandCenter, addCenter, stroke, moreGContainer, isShowCollapse, isShowAdd, !!extraData?.isHoveredAddArea, !!extraData?.isShowCollapseAnimation, !!extraData?.isShowAddAnimation);
2716
- this.toggleExpandBadge(element, moreStartAndEnd, collapseOrExpandCenter, stroke, moreGContainer, !!element.isCollapsed, !!extraData?.isHoveredExpandArea);
2708
+ const { startPoint, endPoint, hasCollapsedIcon, hasExpandedIcon, hasAddIcon, collapsedIconCenter, expandedIconCenter, addCenter, hasLeftAddIcon, standardRef } = getNodeMoreKeyPosition(this.board, element);
2709
+ this.toggleCollapseAndAdd(collapsedIconCenter, addCenter, standardRef?.addCenter, stroke, moreGContainer, hasCollapsedIcon, hasAddIcon, hasLeftAddIcon, !!extraData?.isHitAddArea, !!extraData?.isHitStandardLeftAddArea, !!extraData?.isShowCollapseAnimation, !!extraData?.isShowAddAnimation);
2710
+ this.toggleExpandBadge(element, [startPoint, endPoint], expandedIconCenter, stroke, moreGContainer, !!hasExpandedIcon, !!extraData?.isHitExpandArea);
2717
2711
  return moreGContainer;
2718
2712
  }
2719
- toggleCollapseOrAdd(center, addCenter, stroke, parentG, isShowCollapse, isShowAdd, isHoveredAddArea, isShowCollapseAnimation, isShowAddAnimation) {
2713
+ toggleCollapseAndAdd(center, addCenter, standardLeftAddCenter, stroke, parentG, isShowCollapse, isShowAdd, isShowStandardLeftAdd, isHitAddArea, isHitStandardLeftAdd, isShowCollapseAnimation, isShowAddAnimation) {
2720
2714
  this.collapseOrAddG?.remove();
2721
- if (!isShowCollapse && !isShowAdd) {
2715
+ if (!isShowCollapse && !isShowAdd && !isShowStandardLeftAdd) {
2722
2716
  return;
2723
2717
  }
2724
2718
  this.collapseOrAddG = createG();
@@ -2747,15 +2741,15 @@ class NodeMoreGenerator extends Generator {
2747
2741
  collapseG.appendChild(collapseLine);
2748
2742
  setStrokeLinecap(collapseLine, 'round');
2749
2743
  }
2750
- if (isShowAdd && addCenter) {
2744
+ const createAddIcon = (collapseOrAddG, addCenter, isHit) => {
2751
2745
  const addG = createG();
2752
- this.collapseOrAddG.appendChild(addG);
2746
+ collapseOrAddG.appendChild(addG);
2753
2747
  addG.classList.add('add-button');
2754
2748
  if (isShowAddAnimation) {
2755
2749
  addG.classList.add('animated');
2756
2750
  }
2757
2751
  const circle = PlaitBoard.getRoughSVG(this.board).circle(addCenter[0], addCenter[1], NODE_MORE_ICON_DIAMETER + NODE_MORE_STROKE_WIDTH, {
2758
- fill: isHoveredAddArea ? NODE_ADD_HOVER_COLOR : NODE_ADD_CIRCLE_COLOR,
2752
+ fill: isHit ? NODE_ADD_HOVER_COLOR : NODE_ADD_CIRCLE_COLOR,
2759
2753
  stroke: TRANSPARENT,
2760
2754
  fillStyle: 'solid'
2761
2755
  });
@@ -2776,6 +2770,12 @@ class NodeMoreGenerator extends Generator {
2776
2770
  addG.appendChild(circle);
2777
2771
  addG.appendChild(innerCrossHLine);
2778
2772
  addG.appendChild(innerCrossVLine);
2773
+ };
2774
+ if (isShowAdd && addCenter) {
2775
+ createAddIcon(this.collapseOrAddG, addCenter, isHitAddArea);
2776
+ }
2777
+ if (isShowStandardLeftAdd && standardLeftAddCenter) {
2778
+ createAddIcon(this.collapseOrAddG, standardLeftAddCenter, isHitStandardLeftAdd);
2779
2779
  }
2780
2780
  parentG.appendChild(this.collapseOrAddG);
2781
2781
  }
@@ -2818,19 +2818,65 @@ class NodeMoreGenerator extends Generator {
2818
2818
  parentG.appendChild(this.expandG);
2819
2819
  }
2820
2820
  }
2821
- const getCollapseAndAddCenterPoint = (board, element) => {
2821
+ const getNodeMoreKeyPosition = (board, element) => {
2822
+ const isMind = PlaitMind.isMind(element);
2823
+ const hasLeftAddIcon = isMind && element.layout === MindLayoutType.standard;
2822
2824
  const layoutDirection = getNodeMoreLayoutDirection(board, element);
2823
- const [startPoint, endPoint] = getMoreStartAndEnd(board, element, layoutDirection);
2824
- const collapseCenter = moveXOfPoint(endPoint, NODE_MORE_ICON_DIAMETER / 2, layoutDirection);
2825
- const addCenter = getAddCenterByCollapseOrExpandCenter(element, collapseCenter, layoutDirection);
2826
- return { collapseCenter, addCenter };
2827
- };
2828
- const getAddCenterByCollapseOrExpandCenter = (target, collapseOrExpandCenter, layoutDirection) => {
2829
- let addCenter = collapseOrExpandCenter;
2830
- if (target.children?.length > 0 && !PlaitMind.isMind(target)) {
2831
- addCenter = moveXOfPoint(addCenter, NODE_MORE_LINE_DISTANCE + NODE_MORE_ICON_DIAMETER, layoutDirection);
2825
+ const startPoint = getNodeMoreStartPoint(board, element, layoutDirection);
2826
+ const endPoint = moveXOfPoint(startPoint, NODE_MORE_LINE_DISTANCE, layoutDirection);
2827
+ const hasCollapsedIcon = element.children?.length > 0 && !isMind && !element.isCollapsed;
2828
+ const hasExpandedIcon = element.children?.length > 0 && !isMind && element.isCollapsed;
2829
+ const hasAddIcon = !hasExpandedIcon;
2830
+ const firstIconCenter = moveXOfPoint(endPoint, NODE_MORE_ICON_DIAMETER / 2, layoutDirection);
2831
+ const collapsedIconCenter = hasCollapsedIcon ? firstIconCenter : null;
2832
+ const expandedIconCenter = hasExpandedIcon ? firstIconCenter : null;
2833
+ let addCenter = null;
2834
+ if (hasAddIcon) {
2835
+ addCenter = hasCollapsedIcon
2836
+ ? moveXOfPoint(firstIconCenter, NODE_MORE_LINE_DISTANCE + NODE_MORE_ICON_DIAMETER, layoutDirection)
2837
+ : firstIconCenter;
2838
+ }
2839
+ let awarenessRectangle = null;
2840
+ if (hasAddIcon) {
2841
+ const addIconEndPoint = moveXOfPoint(addCenter, NODE_MORE_ICON_DIAMETER / 2, layoutDirection);
2842
+ awarenessRectangle = RectangleClient.getRectangleByPoints([
2843
+ moveYOfPoint(startPoint, -NODE_MORE_ICON_DIAMETER / 2, layoutDirection),
2844
+ moveYOfPoint(addIconEndPoint, NODE_MORE_ICON_DIAMETER / 2, layoutDirection)
2845
+ ]);
2846
+ }
2847
+ else if (hasExpandedIcon) {
2848
+ const expandedIconEndPoint = moveXOfPoint(expandedIconCenter, NODE_MORE_ICON_DIAMETER / 2, layoutDirection);
2849
+ awarenessRectangle = RectangleClient.getRectangleByPoints([
2850
+ moveYOfPoint(startPoint, -NODE_MORE_ICON_DIAMETER / 2, layoutDirection),
2851
+ moveYOfPoint(expandedIconEndPoint, NODE_MORE_ICON_DIAMETER / 2, layoutDirection)
2852
+ ]);
2853
+ }
2854
+ let standardRef = null;
2855
+ if (hasLeftAddIcon) {
2856
+ const leftStartPoint = getNodeMoreStartPoint(board, element, layoutDirection, true);
2857
+ const leftAddCenter = [leftStartPoint[0] - NODE_MORE_LINE_DISTANCE - NODE_MORE_ICON_DIAMETER / 2, leftStartPoint[1]];
2858
+ const leftAwarenessRectangle = RectangleClient.getRectangleByPoints([
2859
+ [leftStartPoint[0] - NODE_MORE_ICON_DIAMETER - NODE_MORE_LINE_DISTANCE, leftStartPoint[1] - NODE_MORE_ICON_DIAMETER / 2],
2860
+ [leftStartPoint[0], leftStartPoint[1] + NODE_MORE_ICON_DIAMETER / 2]
2861
+ ]);
2862
+ standardRef = {
2863
+ addCenter: leftAddCenter,
2864
+ awarenessRectangle: leftAwarenessRectangle
2865
+ };
2832
2866
  }
2833
- return addCenter;
2867
+ return {
2868
+ startPoint,
2869
+ endPoint,
2870
+ hasCollapsedIcon,
2871
+ hasExpandedIcon,
2872
+ hasAddIcon,
2873
+ collapsedIconCenter,
2874
+ expandedIconCenter,
2875
+ addCenter,
2876
+ awarenessRectangle,
2877
+ hasLeftAddIcon,
2878
+ standardRef
2879
+ };
2834
2880
  };
2835
2881
  const getNodeMoreLayoutDirection = (board, element) => {
2836
2882
  const node = MindElement.getNode(element);
@@ -2842,11 +2888,14 @@ const getNodeMoreLayoutDirection = (board, element) => {
2842
2888
  }
2843
2889
  return layoutDirection;
2844
2890
  };
2845
- const getMoreStartAndEnd = (board, element, linkLineDirection) => {
2891
+ const getNodeMoreStartPoint = (board, element, linkLineDirection, isLeft = false) => {
2846
2892
  const node = MindElement.getNode(element);
2847
2893
  const isUnderlineShape = getShapeByElement(board, element) === MindElementShape.underline;
2848
2894
  const nodeClient = getRectangleByNode(node);
2849
2895
  let placement = [HorizontalPlacement.right, VerticalPlacement.middle];
2896
+ if (isLeft) {
2897
+ placement[0] = HorizontalPlacement.left;
2898
+ }
2850
2899
  transformPlacement(placement, linkLineDirection);
2851
2900
  // underline shape and horizontal
2852
2901
  const layout = MindQueries.getLayoutByElement(element);
@@ -2855,13 +2904,7 @@ const getMoreStartAndEnd = (board, element, linkLineDirection) => {
2855
2904
  placement[1] = VerticalPlacement.bottom;
2856
2905
  }
2857
2906
  let startPoint = getPointByPlacement(nodeClient, placement);
2858
- const endPoint = moveXOfPoint(startPoint, NODE_MORE_LINE_DISTANCE, linkLineDirection);
2859
- return [startPoint, endPoint];
2860
- };
2861
- const isLastSelectedMindElement = (board, element) => {
2862
- const selectedElements = getSelectedElements(board);
2863
- const selectedMindElements = selectedElements.filter((element) => MindElement.isMindElement(board, element)).reverse();
2864
- return selectedMindElements[selectedMindElements.length - 1] === element;
2907
+ return startPoint;
2865
2908
  };
2866
2909
  const canHandleNodeMore = (board) => {
2867
2910
  return !isResizing(board) && !isSelectionMoving(board) && !isDragging(board) && !isMovingElements(board);
@@ -3475,6 +3518,20 @@ const withMindHotkey = (baseBoard) => {
3475
3518
  return board;
3476
3519
  };
3477
3520
 
3521
+ const isSameNodeMoreRef = (ref1, ref2) => {
3522
+ if (!ref1 || !ref2) {
3523
+ return false;
3524
+ }
3525
+ const result = ref1.target === ref2.target &&
3526
+ ref1.isHit === ref2.isHit &&
3527
+ ref1.isHitAwarenessRectangle === ref2.isHitAwarenessRectangle &&
3528
+ ref1.isHitCollapseArea === ref2.isHitCollapseArea &&
3529
+ ref1.isHitExpandArea === ref2.isHitExpandArea &&
3530
+ ref1.isHitAddArea === ref2.isHitAddArea &&
3531
+ ref1.isHitStandardLeftAddArea === ref2.isHitStandardLeftAddArea &&
3532
+ ref1.isHitStandardLeftAwarenessRectangle === ref2.isHitStandardLeftAwarenessRectangle;
3533
+ return result;
3534
+ };
3478
3535
  const withNodeMore = (board) => {
3479
3536
  const { pointerMove, pointerLeave, pointerUp } = board;
3480
3537
  let nodeMoreRef = null;
@@ -3486,28 +3543,30 @@ const withNodeMore = (board) => {
3486
3543
  nodeMoreRef = null;
3487
3544
  }
3488
3545
  const newNodeMoreRef = getNodeMoreRef(board, event.x, event.y);
3489
- if (nodeMoreRef && newNodeMoreRef && nodeMoreRef.target === newNodeMoreRef.target) {
3546
+ if (nodeMoreRef && newNodeMoreRef && isSameNodeMoreRef(nodeMoreRef, newNodeMoreRef)) {
3490
3547
  return;
3491
3548
  }
3492
- if (nodeMoreRef) {
3493
- toggleHoveredNodeCallback({
3494
- target: nodeMoreRef.target,
3495
- isHovered: false,
3496
- isHoveredCollapseArea: false,
3497
- isHoveredExpandArea: false,
3498
- isHoveredAddArea: false
3499
- });
3549
+ if (nodeMoreRef && (!newNodeMoreRef || newNodeMoreRef.target !== nodeMoreRef.target)) {
3550
+ const element = getElementById(board, nodeMoreRef.target.id);
3551
+ // maybe element has been changed
3552
+ if (element && element === nodeMoreRef.target) {
3553
+ toggleHoveredNodeCallback({
3554
+ target: nodeMoreRef.target,
3555
+ isHit: false,
3556
+ isHitAwarenessRectangle: false,
3557
+ isHitCollapseArea: false,
3558
+ isHitExpandArea: false,
3559
+ isHitAddArea: false,
3560
+ isHitStandardLeftAddArea: false,
3561
+ isHitStandardLeftAwarenessRectangle: false
3562
+ });
3563
+ }
3500
3564
  }
3501
3565
  if (newNodeMoreRef) {
3502
- toggleHoveredNodeCallback(newNodeMoreRef);
3503
- if (nodeMoreRef) {
3504
- nodeMoreRef.target = newNodeMoreRef.target;
3505
- }
3506
- else {
3507
- nodeMoreRef = newNodeMoreRef;
3508
- }
3566
+ toggleHoveredNodeCallback(newNodeMoreRef, nodeMoreRef);
3567
+ nodeMoreRef = newNodeMoreRef;
3509
3568
  }
3510
- else {
3569
+ else if (nodeMoreRef) {
3511
3570
  nodeMoreRef = null;
3512
3571
  }
3513
3572
  });
@@ -3515,7 +3574,7 @@ const withNodeMore = (board) => {
3515
3574
  pointerMove(event);
3516
3575
  };
3517
3576
  board.pointerUp = (event) => {
3518
- if (nodeMoreRef && (nodeMoreRef.isHoveredCollapseArea || nodeMoreRef.isHoveredExpandArea)) {
3577
+ if (nodeMoreRef && (nodeMoreRef.isHitCollapseArea || nodeMoreRef.isHitExpandArea)) {
3519
3578
  const isCollapsed = !nodeMoreRef.target.isCollapsed;
3520
3579
  const newElement = { isCollapsed };
3521
3580
  const path = PlaitBoard.findPath(board, nodeMoreRef.target);
@@ -3532,28 +3591,58 @@ const withNodeMore = (board) => {
3532
3591
  }, 0);
3533
3592
  return;
3534
3593
  }
3535
- if (nodeMoreRef && nodeMoreRef.isHoveredAddArea && !PlaitBoard.isReadonly(board)) {
3536
- if (nodeMoreRef) {
3594
+ const insertMindElementByAdd = (nodeMoreRef) => {
3595
+ if (nodeMoreRef.isHitAddArea && PlaitMind.isMind(nodeMoreRef.target) && nodeMoreRef.target.layout === MindLayoutType.standard) {
3596
+ const path = PlaitBoard.findPath(board, nodeMoreRef.target);
3597
+ const refs = insertElementHandleRightNodeCount(board, path, 1);
3598
+ setRightNodeCountByRefs(board, refs);
3599
+ const newPath = findNewRightChildNodePath(board, nodeMoreRef.target, refs[0].rightNodeCount);
3600
+ insertMindElement(board, nodeMoreRef.target, newPath);
3601
+ }
3602
+ else {
3537
3603
  const path = findNewChildNodePath(board, nodeMoreRef.target);
3538
3604
  insertMindElement(board, nodeMoreRef.target, path);
3539
3605
  }
3606
+ };
3607
+ if (nodeMoreRef && (nodeMoreRef.isHitAddArea || nodeMoreRef.isHitStandardLeftAddArea) && !PlaitBoard.isReadonly(board)) {
3608
+ if (nodeMoreRef) {
3609
+ insertMindElementByAdd(nodeMoreRef);
3610
+ }
3540
3611
  return;
3541
3612
  }
3613
+ if (isTouchDevice()) {
3614
+ const nodeMoreRef = getNodeMoreRef(board, event.x, event.y);
3615
+ if (nodeMoreRef && (nodeMoreRef.isHitAddArea || nodeMoreRef.isHitStandardLeftAddArea)) {
3616
+ insertMindElementByAdd(nodeMoreRef);
3617
+ return;
3618
+ }
3619
+ if (nodeMoreRef && (nodeMoreRef.isHitExpandArea || nodeMoreRef.isHitCollapseArea)) {
3620
+ const isCollapsed = !nodeMoreRef.target.isCollapsed;
3621
+ const newElement = { isCollapsed };
3622
+ const path = PlaitBoard.findPath(board, nodeMoreRef.target);
3623
+ Transforms.setNode(board, newElement, path);
3624
+ return;
3625
+ }
3626
+ }
3542
3627
  pointerUp(event);
3543
3628
  };
3544
- const toggleHoveredNodeCallback = (ref) => {
3629
+ const toggleHoveredNodeCallback = (ref, oldRef) => {
3545
3630
  const elementRef = PlaitElement.getElementRef(ref.target);
3546
3631
  const nodeMoreGenerator = elementRef?.getGenerator(NodeMoreGenerator.key);
3547
3632
  if (nodeMoreGenerator) {
3633
+ const isSameTarget = oldRef?.target === ref.target;
3548
3634
  const g = PlaitElement.getElementG(ref.target);
3549
3635
  nodeMoreGenerator.processDrawing(ref.target, g, {
3550
- isHovered: ref.isHovered,
3551
- isHoveredCollapseArea: ref.isHoveredCollapseArea,
3552
- isHoveredExpandArea: ref.isHoveredExpandArea,
3636
+ isHit: ref.isHit,
3637
+ isHitStandardLeftAddArea: ref.isHitStandardLeftAddArea,
3638
+ isHitStandardLeftAwarenessRectangle: ref.isHitStandardLeftAwarenessRectangle,
3639
+ isHitAwarenessRectangle: ref.isHitAwarenessRectangle,
3640
+ isHitCollapseArea: ref.isHitCollapseArea,
3641
+ isHitExpandArea: ref.isHitExpandArea,
3642
+ isHitAddArea: ref.isHitAddArea,
3553
3643
  isSelected: isSelectedElement(board, ref.target),
3554
- isHoveredAddArea: ref.isHoveredAddArea,
3555
- isShowCollapseAnimation: (ref.isHovered || ref.isHoveredCollapseArea) && !isSelectedElement(board, ref.target),
3556
- isShowAddAnimation: (ref.isHovered || ref.isHoveredAddArea) && !isSelectedElement(board, ref.target)
3644
+ isShowCollapseAnimation: (ref.isHit || ref.isHitCollapseArea) && !isSelectedElement(board, ref.target) && !isSameTarget,
3645
+ isShowAddAnimation: (ref.isHit || ref.isHitAddArea) && !isSelectedElement(board, ref.target) && !isSameTarget
3557
3646
  });
3558
3647
  }
3559
3648
  };
@@ -3561,10 +3650,13 @@ const withNodeMore = (board) => {
3561
3650
  if (nodeMoreRef) {
3562
3651
  toggleHoveredNodeCallback({
3563
3652
  target: nodeMoreRef.target,
3564
- isHovered: false,
3565
- isHoveredCollapseArea: false,
3566
- isHoveredExpandArea: false,
3567
- isHoveredAddArea: false
3653
+ isHit: false,
3654
+ isHitAwarenessRectangle: false,
3655
+ isHitCollapseArea: false,
3656
+ isHitExpandArea: false,
3657
+ isHitAddArea: false,
3658
+ isHitStandardLeftAddArea: false,
3659
+ isHitStandardLeftAwarenessRectangle: false
3568
3660
  });
3569
3661
  }
3570
3662
  nodeMoreRef = null;
@@ -3574,10 +3666,13 @@ const withNodeMore = (board) => {
3574
3666
  };
3575
3667
  const getNodeMoreRef = (board, x, y) => {
3576
3668
  let target = null;
3577
- let isHovered = false;
3578
- let isHoveredCollapseArea = false;
3579
- let isHoveredExpandArea = false;
3580
- let isHoveredAddArea = false;
3669
+ let isHit = false;
3670
+ let isHitAwarenessRectangle = false;
3671
+ let isHitCollapseArea = false;
3672
+ let isHitExpandArea = false;
3673
+ let isHitAddArea = false;
3674
+ let isHitStandardLeftAddArea = false;
3675
+ let isHitStandardLeftAwarenessRectangle = false;
3581
3676
  const point = toViewBoxPoint(board, toHostPoint(board, x, y));
3582
3677
  depthFirstRecursion(board, (element) => {
3583
3678
  if (target) {
@@ -3586,29 +3681,30 @@ const getNodeMoreRef = (board, x, y) => {
3586
3681
  if (!MindElement.isMindElement(board, element)) {
3587
3682
  return;
3588
3683
  }
3589
- const isMind = PlaitMind.isMind(element);
3590
3684
  const isHitElement = isHitMindElement(board, point, element);
3591
- let isHitCollapseOrExpand = false;
3592
- let isHitAdd = false;
3593
- const { collapseCenter, addCenter } = getCollapseAndAddCenterPoint(board, element);
3594
- const collapseOrExpandIconRectangle = !isMind && RectangleClient.getRectangleByCenterPoint(collapseCenter, NODE_MORE_ICON_DIAMETER, NODE_MORE_ICON_DIAMETER);
3595
- isHitCollapseOrExpand =
3596
- collapseOrExpandIconRectangle &&
3597
- RectangleClient.isHit(RectangleClient.getRectangleByPoints([point, point]), collapseOrExpandIconRectangle);
3598
- const addIconRectangle = RectangleClient.getRectangleByCenterPoint(addCenter, NODE_MORE_ICON_DIAMETER, NODE_MORE_ICON_DIAMETER);
3599
- isHitAdd = RectangleClient.isHit(RectangleClient.getRectangleByPoints([point, point]), addIconRectangle);
3600
- if (isHitElement || isHitCollapseOrExpand || isHitAdd) {
3601
- isHovered = isHitElement;
3602
- if (element.children.length > 0) {
3603
- if (element.isCollapsed) {
3604
- isHoveredExpandArea = isHitCollapseOrExpand;
3605
- }
3606
- else {
3607
- isHoveredCollapseArea = isHitCollapseOrExpand;
3608
- }
3609
- }
3610
- isHoveredAddArea = isHitAdd;
3685
+ const { hasCollapsedIcon, hasExpandedIcon, hasAddIcon, collapsedIconCenter, expandedIconCenter, addCenter, awarenessRectangle, hasLeftAddIcon, standardRef } = getNodeMoreKeyPosition(board, element);
3686
+ const isHitAwarenessRectangleInternal = awarenessRectangle && RectangleClient.isHit(RectangleClient.getRectangleByPoints([point, point]), awarenessRectangle);
3687
+ const isHitCollapsedIcon = hasCollapsedIcon &&
3688
+ RectangleClient.isHit(RectangleClient.getRectangleByPoints([point, point]), RectangleClient.getRectangleByCenterPoint(collapsedIconCenter, NODE_MORE_ICON_DIAMETER, NODE_MORE_ICON_DIAMETER));
3689
+ const isHitExpandedIcon = hasExpandedIcon &&
3690
+ RectangleClient.isHit(RectangleClient.getRectangleByPoints([point, point]), RectangleClient.getRectangleByCenterPoint(expandedIconCenter, NODE_MORE_ICON_DIAMETER, NODE_MORE_ICON_DIAMETER));
3691
+ const isHitAddIcon = hasAddIcon &&
3692
+ RectangleClient.isHit(RectangleClient.getRectangleByPoints([point, point]), RectangleClient.getRectangleByCenterPoint(addCenter, NODE_MORE_ICON_DIAMETER, NODE_MORE_ICON_DIAMETER));
3693
+ const isHitStandardLeftAwarenessRectangleInternal = hasLeftAddIcon &&
3694
+ standardRef &&
3695
+ RectangleClient.isHit(RectangleClient.getRectangleByPoints([point, point]), standardRef.awarenessRectangle);
3696
+ const isHitStandardLeftAddIcon = hasLeftAddIcon &&
3697
+ standardRef &&
3698
+ RectangleClient.isHit(RectangleClient.getRectangleByPoints([point, point]), RectangleClient.getRectangleByCenterPoint(standardRef.addCenter, NODE_MORE_ICON_DIAMETER, NODE_MORE_ICON_DIAMETER));
3699
+ if (isHitElement || isHitAwarenessRectangleInternal || isHitStandardLeftAwarenessRectangleInternal) {
3700
+ isHit = isHitElement;
3611
3701
  target = element;
3702
+ isHitCollapseArea = isHitCollapsedIcon;
3703
+ isHitExpandArea = !!isHitExpandedIcon;
3704
+ isHitAddArea = isHitAddIcon;
3705
+ isHitAwarenessRectangle = !!isHitAwarenessRectangleInternal;
3706
+ isHitStandardLeftAwarenessRectangle = !!isHitStandardLeftAwarenessRectangleInternal;
3707
+ isHitStandardLeftAddArea = !!isHitStandardLeftAddIcon;
3612
3708
  }
3613
3709
  }, getIsRecursionFunc(board), true);
3614
3710
  if (!target) {
@@ -3616,10 +3712,13 @@ const getNodeMoreRef = (board, x, y) => {
3616
3712
  }
3617
3713
  return {
3618
3714
  target,
3619
- isHovered,
3620
- isHoveredCollapseArea,
3621
- isHoveredExpandArea,
3622
- isHoveredAddArea
3715
+ isHit,
3716
+ isHitAwarenessRectangle,
3717
+ isHitCollapseArea,
3718
+ isHitExpandArea,
3719
+ isHitAddArea,
3720
+ isHitStandardLeftAddArea,
3721
+ isHitStandardLeftAwarenessRectangle
3623
3722
  };
3624
3723
  };
3625
3724
 
@@ -4193,5 +4292,5 @@ class MindEmojiBaseComponent {
4193
4292
  * Generated bundle index. Do not edit.
4194
4293
  */
4195
4294
 
4196
- export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, ABSTRACT_NODE_TEXT, AbstractHandlePosition, AbstractResizeState, BASE, BranchShape, DEFAULT_MIND_IMAGE_WIDTH, DefaultAbstractNodeStyle, DefaultNodeStyle, GRAY_COLOR, INHERIT_ATTRIBUTE_KEYS, LayoutDirection, LayoutDirectionsMap, MIND_CENTRAL_TEXT, MIND_ELEMENT_TO_NODE, MindColorfulThemeColor, MindDarkThemeColor, MindDefaultThemeColor, MindElement, MindElementShape, MindEmojiBaseComponent, MindI18nKey, MindNode, MindNodeComponent, MindPointerType, MindQueries, MindRetroThemeColor, MindSoftThemeColor, MindStarryThemeColor, MindThemeColor, MindThemeColors, MindTransforms, NODE_ADD_CIRCLE_COLOR, NODE_ADD_HOVER_COLOR, NODE_ADD_INNER_CROSS_COLOR, NODE_MORE_BRIDGE_DISTANCE, NODE_MORE_ICON_DIAMETER, NODE_MORE_LINE_DISTANCE, NODE_MORE_STROKE_WIDTH, NodeSpace, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, RESIZE_HANDLE_BUFFER_DISTANCE, ROOT_TOPIC_FONT_SIZE, STROKE_WIDTH, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, WithMindPluginKey, addActiveOnDragOrigin, addImageFocus, adjustAbstractToNode, adjustNodeToRoot, adjustRootToNode, canSetAbstract, copyNewNode, correctLayoutByDirection, createEmptyMind, createMindElement, deleteElementHandleAbstract, deleteElementsHandleRightNodeCount, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNode, editTopic, findLastChild, findLocationLeftIndex, findNewChildNodePath, findNewSiblingNodePath, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAbstractNodeText, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchShapeByMindElement, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultFontSizeForMindElement, getDefaultLayout, getDefaultMindNameText, getEmojiFontSize, getEmojiForeignRectangle, getEmojiRectangle, getEmojisWidthHeight, getFillByElement, getFirstLevelElement, getFontSizeByMindElement, getHitAbstractHandle, getHitImageResizeHandleDirection, getImageForeignRectangle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutOptions, getLayoutReverseDirection, getLocationScope, getMindThemeColor, getNewNodeHeight, getNextBranchColor, getOverallAbstracts, getPathByDropTarget, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getSelectedMindElements, getShapeByElement, getStrokeColorByElement, getStrokeStyleByElement, getStrokeWidthByElement, getTopicRectangleByElement, getTopicRectangleByNode, getValidAbstractRefs, handleTouchedAbstract, hasPreviousOrNextOfDropPath, insertElementHandleAbstract, insertElementHandleRightNodeCount, insertMindElement, isChildElement, isChildOfAbstract, isChildRight, isChildUp, isCorrectLayout, isDropStandardRight, isHitEmojis, isHitImage, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, normalizeWidthAndHeight, removeActiveOnDragOrigin, removeImageFocus, separateChildren, setMindDragging, withEmoji, withMind, withMindExtend };
4295
+ export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, ABSTRACT_NODE_TEXT, AbstractHandlePosition, AbstractResizeState, BASE, BranchShape, DEFAULT_MIND_IMAGE_WIDTH, DefaultAbstractNodeStyle, DefaultNodeStyle, GRAY_COLOR, INHERIT_ATTRIBUTE_KEYS, LayoutDirection, LayoutDirectionsMap, MIND_CENTRAL_TEXT, MIND_ELEMENT_TO_NODE, MindColorfulThemeColor, MindDarkThemeColor, MindDefaultThemeColor, MindElement, MindElementShape, MindEmojiBaseComponent, MindI18nKey, MindNode, MindNodeComponent, MindPointerType, MindQueries, MindRetroThemeColor, MindSoftThemeColor, MindStarryThemeColor, MindThemeColor, MindThemeColors, MindTransforms, NODE_ADD_CIRCLE_COLOR, NODE_ADD_HOVER_COLOR, NODE_ADD_INNER_CROSS_COLOR, NODE_MORE_BRIDGE_DISTANCE, NODE_MORE_ICON_DIAMETER, NODE_MORE_LINE_DISTANCE, NODE_MORE_STROKE_WIDTH, NodeSpace, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, RESIZE_HANDLE_BUFFER_DISTANCE, ROOT_TOPIC_FONT_SIZE, STROKE_WIDTH, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, WithMindPluginKey, addActiveOnDragOrigin, addImageFocus, adjustAbstractToNode, adjustNodeToRoot, adjustRootToNode, canSetAbstract, copyNewNode, correctLayoutByDirection, createEmptyMind, createMindElement, deleteElementHandleAbstract, deleteElementsHandleRightNodeCount, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNode, editTopic, findLastChild, findLocationLeftIndex, findNewChildNodePath, findNewRightChildNodePath, findNewSiblingNodePath, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAbstractNodeText, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchShapeByMindElement, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultFontSizeForMindElement, getDefaultLayout, getDefaultMindNameText, getEmojiFontSize, getEmojiForeignRectangle, getEmojiRectangle, getEmojisWidthHeight, getFillByElement, getFirstLevelElement, getFontSizeByMindElement, getHitAbstractHandle, getHitImageResizeHandleDirection, getImageForeignRectangle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutOptions, getLayoutReverseDirection, getLocationScope, getMindThemeColor, getNewNodeHeight, getNextBranchColor, getOverallAbstracts, getPathByDropTarget, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getSelectedMindElements, getShapeByElement, getStrokeColorByElement, getStrokeStyleByElement, getStrokeWidthByElement, getTopicRectangleByElement, getTopicRectangleByNode, getValidAbstractRefs, handleTouchedAbstract, hasPreviousOrNextOfDropPath, insertElementHandleAbstract, insertElementHandleRightNodeCount, insertMindElement, isChildElement, isChildOfAbstract, isChildRight, isChildUp, isCorrectLayout, isDropStandardRight, isHitEmojis, isHitImage, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, normalizeWidthAndHeight, removeActiveOnDragOrigin, removeImageFocus, separateChildren, setMindDragging, withEmoji, withMind, withMindExtend };
4197
4296
  //# sourceMappingURL=plait-mind.mjs.map