@plait/mind 0.82.0-next.0 → 0.83.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.
- package/constants/default.d.ts +8 -5
- package/fesm2022/plait-mind.mjs +357 -319
- package/fesm2022/plait-mind.mjs.map +1 -1
- package/generators/node-more.generator.d.ts +30 -0
- package/mind-node.component.d.ts +3 -7
- package/package.json +1 -1
- package/plugins/with-node-more.d.ts +10 -0
- package/styles/styles.scss +16 -56
- package/utils/clipboard.d.ts +1 -1
- package/utils/common.d.ts +1 -1
- package/utils/point-placement.d.ts +0 -3
- package/generators/node-collapse.generator.d.ts +0 -8
- package/generators/node-plus.generator.d.ts +0 -7
- package/plugins/with-node-hover-hit-test.d.ts +0 -2
- package/utils/node-hover/extend.d.ts +0 -9
package/fesm2022/plait-mind.mjs
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { DEFAULT_COLOR, DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, 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,
|
|
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';
|
|
2
2
|
import { MindLayoutType, AbstractNode, isIndentedLayout, isHorizontalLogicLayout, ConnectingPosition, isHorizontalLayout, getNonAbstractChildren, isStandardLayout, isLeftLayout, isRightLayout, isVerticalLogicLayout, isTopLayout, isBottomLayout, getCorrectStartEnd, getAbstractLayout, GlobalLayout } from '@plait/layouts';
|
|
3
|
-
import { StrokeStyle, getFirstTextManage, DEFAULT_FONT_FAMILY, measureElement, buildText, getFirstTextEditor, RESIZE_HANDLE_DIAMETER, getRectangleResizeHandleRefs, addElementOfFocusedImage, ImageGenerator, removeElementOfFocusedImage, getStrokeLineDash, Generator, PropertyTransforms, CommonElementFlavour, WithTextPluginKey, TextManage, isDrawingMode, isDndMode, setCreationMode, BoardCreationMode, isExpandHotkey, isTabHotkey, isEnterHotkey, isVirtualKey, isDelete, isSpaceHotkey, getElementOfFocusedImage, acceptImageTypes, buildImage, withResize, getElementsText } from '@plait/common';
|
|
4
|
-
import { TEXT_DEFAULT_HEIGHT, PlaitMarkEditor, MarkTypes, DEFAULT_FONT_SIZE } from '@plait/text-plugins';
|
|
3
|
+
import { StrokeStyle, getFirstTextManage, DEFAULT_FONT_FAMILY, measureElement, buildText, getFirstTextEditor, RESIZE_HANDLE_DIAMETER, getRectangleResizeHandleRefs, addElementOfFocusedImage, ImageGenerator, removeElementOfFocusedImage, getStrokeLineDash, getXDistanceBetweenPoint, moveXOfPoint, moveYOfPoint, Generator, PropertyTransforms, TRANSPARENT, isResizing, CommonElementFlavour, WithTextPluginKey, TextManage, isDrawingMode, isDndMode, setCreationMode, BoardCreationMode, isExpandHotkey, isTabHotkey, isEnterHotkey, isVirtualKey, isDelete, isSpaceHotkey, getElementOfFocusedImage, acceptImageTypes, buildImage, withResize, getElementsText } from '@plait/common';
|
|
4
|
+
import { TEXT_DEFAULT_HEIGHT, PlaitMarkEditor, MarkTypes, DEFAULT_FONT_SIZE, FontSizes } from '@plait/text-plugins';
|
|
5
5
|
import { Node as Node$1, Path as Path$1 } from 'slate';
|
|
6
6
|
import { pointsOnBezierCurves } from 'points-on-curve';
|
|
7
|
-
import { fromEvent } from 'rxjs';
|
|
8
|
-
import { take, filter } from 'rxjs/operators';
|
|
9
7
|
import { isHotkey } from 'is-hotkey';
|
|
10
8
|
|
|
11
9
|
const ELEMENT_TO_NODE = new WeakMap();
|
|
@@ -180,11 +178,14 @@ const BASE = 4;
|
|
|
180
178
|
const PRIMARY_COLOR = '#6698FF';
|
|
181
179
|
const GRAY_COLOR = '#AAAAAA';
|
|
182
180
|
const STROKE_WIDTH = 3;
|
|
183
|
-
const
|
|
184
|
-
const
|
|
185
|
-
const
|
|
186
|
-
const
|
|
187
|
-
const
|
|
181
|
+
const RESIZE_HANDLE_BUFFER_DISTANCE = 8;
|
|
182
|
+
const NODE_MORE_LINE_DISTANCE = 10;
|
|
183
|
+
const NODE_MORE_STROKE_WIDTH = 2;
|
|
184
|
+
const NODE_MORE_ICON_DIAMETER = 20;
|
|
185
|
+
const NODE_MORE_BRIDGE_DISTANCE = 10;
|
|
186
|
+
const NODE_ADD_CIRCLE_COLOR = rgbaToHEX('#000000', 0.2);
|
|
187
|
+
const NODE_ADD_HOVER_COLOR = '#6698FF';
|
|
188
|
+
const NODE_ADD_INNER_CROSS_COLOR = 'white';
|
|
188
189
|
const DEFAULT_MIND_IMAGE_WIDTH = 240;
|
|
189
190
|
var MindI18nKey;
|
|
190
191
|
(function (MindI18nKey) {
|
|
@@ -611,9 +612,9 @@ const getLayoutOptions = (board) => {
|
|
|
611
612
|
}
|
|
612
613
|
function getSecondAxle(element, parent) {
|
|
613
614
|
if (element.isRoot) {
|
|
614
|
-
return BASE *
|
|
615
|
+
return BASE * 12;
|
|
615
616
|
}
|
|
616
|
-
return BASE *
|
|
617
|
+
return BASE * 8.5;
|
|
617
618
|
}
|
|
618
619
|
return {
|
|
619
620
|
getHeight(element) {
|
|
@@ -626,7 +627,7 @@ const getLayoutOptions = (board) => {
|
|
|
626
627
|
const _layout = (parent && parent.layout) || getRootLayout(element);
|
|
627
628
|
const isHorizontal = isHorizontalLayout(_layout);
|
|
628
629
|
if (isIndentedLayout(_layout)) {
|
|
629
|
-
return BASE *
|
|
630
|
+
return BASE * 6;
|
|
630
631
|
}
|
|
631
632
|
if (!isHorizontal) {
|
|
632
633
|
return getMainAxle(element, parent);
|
|
@@ -638,7 +639,7 @@ const getLayoutOptions = (board) => {
|
|
|
638
639
|
getVerticalGap(element, parent) {
|
|
639
640
|
const _layout = (parent && parent.layout) || getRootLayout(element);
|
|
640
641
|
if (isIndentedLayout(_layout)) {
|
|
641
|
-
return BASE;
|
|
642
|
+
return BASE * 3.5;
|
|
642
643
|
}
|
|
643
644
|
const isHorizontal = isHorizontalLayout(_layout);
|
|
644
645
|
if (isHorizontal) {
|
|
@@ -655,10 +656,10 @@ const getLayoutOptions = (board) => {
|
|
|
655
656
|
return undefined;
|
|
656
657
|
},
|
|
657
658
|
getExtendHeight(node) {
|
|
658
|
-
return
|
|
659
|
+
return 0;
|
|
659
660
|
},
|
|
660
661
|
getIndentedCrossLevelGap() {
|
|
661
|
-
return BASE *
|
|
662
|
+
return BASE * 1;
|
|
662
663
|
}
|
|
663
664
|
};
|
|
664
665
|
};
|
|
@@ -683,7 +684,7 @@ const getDefaultMindNameText = (board) => {
|
|
|
683
684
|
const getAbstractNodeText = (board) => {
|
|
684
685
|
return getI18nValue(board, MindI18nKey.abstractNodeText, ABSTRACT_NODE_TEXT);
|
|
685
686
|
};
|
|
686
|
-
const getTopicSize = (isRoot, isBranch, topic, manualWidth) => {
|
|
687
|
+
const getTopicSize = (board, isRoot, isBranch, topic, manualWidth) => {
|
|
687
688
|
let fontFamily = DEFAULT_FONT_FAMILY;
|
|
688
689
|
let fontSize = TOPIC_FONT_SIZE;
|
|
689
690
|
if (isRoot) {
|
|
@@ -694,12 +695,12 @@ const getTopicSize = (isRoot, isBranch, topic, manualWidth) => {
|
|
|
694
695
|
fontFamily = DEFAULT_FONT_FAMILY;
|
|
695
696
|
}
|
|
696
697
|
const maxWidth = fontSize * TOPIC_DEFAULT_MAX_WORD_COUNT;
|
|
697
|
-
return measureElement(topic, { fontSize, fontFamily }, manualWidth ? manualWidth : maxWidth);
|
|
698
|
+
return measureElement(board, topic, { fontSize, fontFamily }, manualWidth ? manualWidth : maxWidth);
|
|
698
699
|
};
|
|
699
700
|
|
|
700
701
|
const createEmptyMind = (board, point) => {
|
|
701
702
|
const text = getDefaultMindNameText(board);
|
|
702
|
-
const topicSize = getTopicSize(true, false, buildText(text));
|
|
703
|
+
const topicSize = getTopicSize(board, true, false, buildText(text));
|
|
703
704
|
const element = createMindElement(text, topicSize.width, topicSize.height, { layout: MindLayoutType.right });
|
|
704
705
|
element.isRoot = true;
|
|
705
706
|
element.type = 'mindmap';
|
|
@@ -1394,14 +1395,6 @@ const getPointByPlacement = (client, placement) => {
|
|
|
1394
1395
|
}
|
|
1395
1396
|
return [x, y];
|
|
1396
1397
|
};
|
|
1397
|
-
const getXDistanceBetweenPoint = (point1, point2, isHorizontalLayout) => {
|
|
1398
|
-
if (isHorizontalLayout) {
|
|
1399
|
-
return Math.abs(point1[0] - point2[0]);
|
|
1400
|
-
}
|
|
1401
|
-
else {
|
|
1402
|
-
return Math.abs(point1[1] - point2[1]);
|
|
1403
|
-
}
|
|
1404
|
-
};
|
|
1405
1398
|
const getYDistanceBetweenPoint = (point1, point2, isHorizontalLayout) => {
|
|
1406
1399
|
getXDistanceBetweenPoint(point1, point2, !isHorizontalLayout);
|
|
1407
1400
|
};
|
|
@@ -1423,37 +1416,6 @@ const getLayoutDirection = (node, isHorizontal) => {
|
|
|
1423
1416
|
}
|
|
1424
1417
|
}
|
|
1425
1418
|
};
|
|
1426
|
-
// Based on right
|
|
1427
|
-
// Right -> Left:
|
|
1428
|
-
// 1. End point -> starting point/start point -> end point
|
|
1429
|
-
// 2. Add -> Subtract
|
|
1430
|
-
// Horizontal -> Vertical:
|
|
1431
|
-
// 1. Starting point/end point -> vertical axis
|
|
1432
|
-
// 2. Addition and subtraction -> vertical axis
|
|
1433
|
-
// Bottom -> Top:
|
|
1434
|
-
// 1. End point -> starting point/end point -> starting point
|
|
1435
|
-
// 2. Add -> Subtract
|
|
1436
|
-
const moveXOfPoint = (point, distance, direction = LayoutDirection.right) => {
|
|
1437
|
-
if (direction === LayoutDirection.left) {
|
|
1438
|
-
return [point[0] - distance, point[1]];
|
|
1439
|
-
}
|
|
1440
|
-
if (direction === LayoutDirection.bottom) {
|
|
1441
|
-
return [point[0], point[1] + distance];
|
|
1442
|
-
}
|
|
1443
|
-
if (direction === LayoutDirection.top) {
|
|
1444
|
-
return [point[0], point[1] - distance];
|
|
1445
|
-
}
|
|
1446
|
-
return [point[0] + distance, point[1]];
|
|
1447
|
-
};
|
|
1448
|
-
const moveYOfPoint = (point, distance, direction = LayoutDirection.right) => {
|
|
1449
|
-
if (direction === LayoutDirection.bottom) {
|
|
1450
|
-
return [point[0] + distance, point[1]];
|
|
1451
|
-
}
|
|
1452
|
-
if (direction === LayoutDirection.top) {
|
|
1453
|
-
return [point[0] + distance, point[1]];
|
|
1454
|
-
}
|
|
1455
|
-
return [point[0], point[1] + distance];
|
|
1456
|
-
};
|
|
1457
1419
|
const transformPlacement = (placement, direction) => {
|
|
1458
1420
|
// to left
|
|
1459
1421
|
if (direction === LayoutDirection.left) {
|
|
@@ -1564,7 +1526,9 @@ function drawLogicLink(board, parent, node, isHorizontal, defaultStrokeColor = n
|
|
|
1564
1526
|
let endPoint = getPointByPlacement(nodeClient, endPlacement);
|
|
1565
1527
|
// ② Determine the convex straight line
|
|
1566
1528
|
const straightLineDistance = 8;
|
|
1567
|
-
const beginPoint2 = hasStraightLine
|
|
1529
|
+
const beginPoint2 = hasStraightLine
|
|
1530
|
+
? moveXOfPoint(beginPoint, straightLineDistance, linkDirection)
|
|
1531
|
+
: beginPoint;
|
|
1568
1532
|
let straightLine = hasStraightLine ? [beginPoint, beginPoint2, beginPoint2] : [];
|
|
1569
1533
|
// ③ Determine the curve
|
|
1570
1534
|
const beginBufferDistance = (parent.hGap + node.hGap) / 3;
|
|
@@ -2514,7 +2478,7 @@ const setAbstractByElements = (board, groupParent, group) => {
|
|
|
2514
2478
|
};
|
|
2515
2479
|
const insertAbstractNode = (board, path, start, end) => {
|
|
2516
2480
|
const abstractNodeText = getAbstractNodeText(board);
|
|
2517
|
-
const { width, height } = getTopicSize(false, false, buildText(abstractNodeText));
|
|
2481
|
+
const { width, height } = getTopicSize(board, false, false, buildText(abstractNodeText));
|
|
2518
2482
|
const mindElement = createMindElement(abstractNodeText, width, height, {
|
|
2519
2483
|
strokeWidth: DefaultAbstractNodeStyle.branch.width,
|
|
2520
2484
|
branchWidth: DefaultAbstractNodeStyle.branch.width
|
|
@@ -2752,201 +2716,202 @@ const MindTransforms = {
|
|
|
2752
2716
|
insertMind
|
|
2753
2717
|
};
|
|
2754
2718
|
|
|
2755
|
-
class
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
return false;
|
|
2759
|
-
}
|
|
2760
|
-
return true;
|
|
2719
|
+
class NodeShapeGenerator extends Generator {
|
|
2720
|
+
constructor(board) {
|
|
2721
|
+
super(board, { prepend: true });
|
|
2761
2722
|
}
|
|
2762
|
-
|
|
2763
|
-
const
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
const layout = MindQueries.getLayoutByElement(element);
|
|
2767
|
-
const isHorizontal = isHorizontalLayout(layout);
|
|
2768
|
-
let linkDirection = getLayoutDirection(node, isHorizontal);
|
|
2769
|
-
if (isIndentedLayout(layout)) {
|
|
2770
|
-
linkDirection = isTopLayout(layout) ? LayoutDirection.top : LayoutDirection.bottom;
|
|
2771
|
-
}
|
|
2772
|
-
const isUnderlineShape = getShapeByElement(this.board, element) === MindElementShape.underline;
|
|
2773
|
-
const nodeClient = getRectangleByNode(node);
|
|
2774
|
-
const branchWidth = getBranchWidthByMindElement(this.board, element);
|
|
2775
|
-
const branchColor = PlaitMind.isMind(element)
|
|
2776
|
-
? getNextBranchColor(this.board, element)
|
|
2777
|
-
: getBranchColorByMindElement(this.board, element);
|
|
2778
|
-
let distance = 8;
|
|
2779
|
-
let placement = [HorizontalPlacement.right, VerticalPlacement.middle];
|
|
2780
|
-
transformPlacement(placement, linkDirection);
|
|
2781
|
-
// underline shape and horizontal
|
|
2782
|
-
if (isHorizontal && isUnderlineShape && !element.isRoot) {
|
|
2783
|
-
placement[1] = VerticalPlacement.bottom;
|
|
2784
|
-
}
|
|
2785
|
-
let beginPoint = getPointByPlacement(nodeClient, placement);
|
|
2786
|
-
if (element.children.length > 0 && !element.isRoot) {
|
|
2787
|
-
beginPoint = moveXOfPoint(beginPoint, EXTEND_DIAMETER + 8, linkDirection);
|
|
2788
|
-
distance = 5;
|
|
2723
|
+
canDraw(element, data) {
|
|
2724
|
+
const shape = getShapeByElement(this.board, element);
|
|
2725
|
+
if (shape === MindElementShape.roundRectangle) {
|
|
2726
|
+
return true;
|
|
2789
2727
|
}
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
});
|
|
2796
|
-
const circle = PlaitBoard.getRoughSVG(this.board).circle(circleCenter[0], circleCenter[1], EXTEND_DIAMETER, {
|
|
2797
|
-
fill: QUICK_INSERT_CIRCLE_COLOR,
|
|
2798
|
-
stroke: QUICK_INSERT_CIRCLE_COLOR,
|
|
2799
|
-
fillStyle: 'solid'
|
|
2800
|
-
});
|
|
2801
|
-
const HLineBeginPoint = [circleCenter[0] - 5, circleCenter[1]];
|
|
2802
|
-
const HLineEndPoint = [circleCenter[0] + 5, circleCenter[1]];
|
|
2803
|
-
const VLineBeginPoint = [circleCenter[0], circleCenter[1] - 5];
|
|
2804
|
-
const VLineEndPoint = [circleCenter[0], circleCenter[1] + 5];
|
|
2805
|
-
const innerCrossHLine = PlaitBoard.getRoughSVG(this.board).line(HLineBeginPoint[0], HLineBeginPoint[1], HLineEndPoint[0], HLineEndPoint[1], {
|
|
2806
|
-
stroke: QUICK_INSERT_INNER_CROSS_COLOR,
|
|
2807
|
-
strokeWidth: 2
|
|
2808
|
-
});
|
|
2809
|
-
const innerCrossVLine = PlaitBoard.getRoughSVG(this.board).line(VLineBeginPoint[0], VLineBeginPoint[1], VLineEndPoint[0], VLineEndPoint[1], {
|
|
2810
|
-
stroke: QUICK_INSERT_INNER_CROSS_COLOR,
|
|
2811
|
-
strokeWidth: 2
|
|
2812
|
-
});
|
|
2813
|
-
plusG.appendChild(line);
|
|
2814
|
-
plusG.appendChild(circle);
|
|
2815
|
-
plusG.appendChild(innerCrossHLine);
|
|
2816
|
-
plusG.appendChild(innerCrossVLine);
|
|
2817
|
-
return plusG;
|
|
2818
|
-
}
|
|
2819
|
-
afterDraw(element) {
|
|
2820
|
-
if (!this.g) {
|
|
2821
|
-
throw new Error(`can not find quick insert g`);
|
|
2822
|
-
}
|
|
2823
|
-
fromEvent(this.g, 'pointerdown')
|
|
2824
|
-
.pipe(take(1))
|
|
2825
|
-
.subscribe(e => {
|
|
2826
|
-
e.preventDefault();
|
|
2827
|
-
});
|
|
2828
|
-
fromEvent(this.g, 'pointerup')
|
|
2829
|
-
.pipe(take(1))
|
|
2830
|
-
.subscribe((event) => {
|
|
2831
|
-
// wait the event period end of pointerup to otherwise the pointerup will cause new element lose selected state
|
|
2832
|
-
setTimeout(() => {
|
|
2833
|
-
const path = findNewChildNodePath(this.board, element);
|
|
2834
|
-
insertMindElement(this.board, element, path);
|
|
2835
|
-
}, 0);
|
|
2836
|
-
});
|
|
2728
|
+
return false;
|
|
2729
|
+
}
|
|
2730
|
+
draw(element, data) {
|
|
2731
|
+
const rectangle = getRectangleByNode(data.node);
|
|
2732
|
+
return drawRoundRectangleByElement(this.board, rectangle, data.node.origin);
|
|
2837
2733
|
}
|
|
2838
2734
|
}
|
|
2839
2735
|
|
|
2840
|
-
class
|
|
2841
|
-
|
|
2842
|
-
|
|
2736
|
+
class NodeMoreGenerator extends Generator {
|
|
2737
|
+
static { this.key = 'mind-node-more'; }
|
|
2738
|
+
canDraw(element, extraData) {
|
|
2739
|
+
if (((extraData?.isHovered || extraData?.isHoveredCollapseArea || extraData?.isHoveredAddArea) && canHandleNodeMore(this.board)) ||
|
|
2740
|
+
(extraData?.isSelected && isLastSelectedMindElement(this.board, element) && canHandleNodeMore(this.board)) ||
|
|
2741
|
+
element.isCollapsed) {
|
|
2843
2742
|
return true;
|
|
2844
2743
|
}
|
|
2845
2744
|
return false;
|
|
2846
2745
|
}
|
|
2847
|
-
draw(element) {
|
|
2848
|
-
const
|
|
2849
|
-
collapseG.classList.add('collapse');
|
|
2850
|
-
const node = MindElement.getNode(element);
|
|
2746
|
+
draw(element, extraData) {
|
|
2747
|
+
const moreGContainer = createG();
|
|
2851
2748
|
const stroke = getBranchColorByMindElement(this.board, element);
|
|
2852
|
-
const
|
|
2853
|
-
const
|
|
2854
|
-
const
|
|
2855
|
-
const
|
|
2856
|
-
const
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2749
|
+
const layoutDirection = getNodeMoreLayoutDirection(this.board, element);
|
|
2750
|
+
const moreStartAndEnd = getMoreStartAndEnd(this.board, element, layoutDirection);
|
|
2751
|
+
const collapseOrExpandCenter = moveXOfPoint(moreStartAndEnd[1], NODE_MORE_ICON_DIAMETER / 2, layoutDirection);
|
|
2752
|
+
const hasChildren = element.children.length > 0;
|
|
2753
|
+
const isShowCollapseOrAdd = !element.isCollapsed &&
|
|
2754
|
+
(isSelectedElement(this.board, element) ||
|
|
2755
|
+
!!extraData?.isHovered ||
|
|
2756
|
+
!!extraData?.isHoveredCollapseArea ||
|
|
2757
|
+
!!extraData?.isHoveredAddArea);
|
|
2758
|
+
const isShowCollapse = isShowCollapseOrAdd && hasChildren && !PlaitMind.isMind(element);
|
|
2759
|
+
const isShowAdd = isShowCollapseOrAdd && !PlaitBoard.isReadonly(this.board);
|
|
2760
|
+
const addCenter = (isShowCollapseOrAdd && getAddCenterByCollapseOrExpandCenter(element, collapseOrExpandCenter, layoutDirection)) || null;
|
|
2761
|
+
this.toggleCollapseOrAdd(collapseOrExpandCenter, addCenter, stroke, moreGContainer, isShowCollapse, isShowAdd, !!extraData?.isHoveredAddArea, !!extraData?.isShowCollapseAnimation, !!extraData?.isShowAddAnimation);
|
|
2762
|
+
this.toggleExpandBadge(element, moreStartAndEnd, collapseOrExpandCenter, stroke, moreGContainer, !!element.isCollapsed, !!extraData?.isHoveredExpandArea);
|
|
2763
|
+
return moreGContainer;
|
|
2764
|
+
}
|
|
2765
|
+
toggleCollapseOrAdd(center, addCenter, stroke, parentG, isShowCollapse, isShowAdd, isHoveredAddArea, isShowCollapseAnimation, isShowAddAnimation) {
|
|
2766
|
+
this.collapseOrAddG?.remove();
|
|
2767
|
+
if (!isShowCollapse && !isShowAdd) {
|
|
2768
|
+
return;
|
|
2860
2769
|
}
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2770
|
+
this.collapseOrAddG = createG();
|
|
2771
|
+
if (isShowCollapse) {
|
|
2772
|
+
const collapseG = createG();
|
|
2773
|
+
this.collapseOrAddG.appendChild(collapseG);
|
|
2774
|
+
collapseG.classList.add('collapse-button');
|
|
2775
|
+
if (isShowCollapseAnimation) {
|
|
2776
|
+
collapseG.classList.add('animated');
|
|
2777
|
+
}
|
|
2778
|
+
const collapseCircle = PlaitBoard.getRoughSVG(this.board).circle(center[0], center[1], NODE_MORE_ICON_DIAMETER, {
|
|
2779
|
+
fill: '#fff',
|
|
2780
|
+
stroke,
|
|
2781
|
+
strokeWidth: NODE_MORE_STROKE_WIDTH,
|
|
2782
|
+
fillStyle: 'solid'
|
|
2783
|
+
});
|
|
2784
|
+
const start = moveXOfPoint(center, -NODE_MORE_BRIDGE_DISTANCE / 2);
|
|
2785
|
+
const end = moveXOfPoint(center, NODE_MORE_BRIDGE_DISTANCE / 2);
|
|
2786
|
+
const collapseLine = PlaitBoard.getRoughSVG(this.board).line(start[0], start[1], end[0], end[1], {
|
|
2787
|
+
fill: '#fff',
|
|
2788
|
+
stroke,
|
|
2789
|
+
strokeWidth: NODE_MORE_STROKE_WIDTH,
|
|
2790
|
+
fillStyle: 'solid'
|
|
2791
|
+
});
|
|
2792
|
+
collapseG.appendChild(collapseCircle);
|
|
2793
|
+
collapseG.appendChild(collapseLine);
|
|
2794
|
+
setStrokeLinecap(collapseLine, 'round');
|
|
2795
|
+
}
|
|
2796
|
+
if (isShowAdd && addCenter) {
|
|
2797
|
+
const addG = createG();
|
|
2798
|
+
this.collapseOrAddG.appendChild(addG);
|
|
2799
|
+
addG.classList.add('add-button');
|
|
2800
|
+
if (isShowAddAnimation) {
|
|
2801
|
+
addG.classList.add('animated');
|
|
2802
|
+
}
|
|
2803
|
+
const circle = PlaitBoard.getRoughSVG(this.board).circle(addCenter[0], addCenter[1], NODE_MORE_ICON_DIAMETER + NODE_MORE_STROKE_WIDTH, {
|
|
2804
|
+
fill: isHoveredAddArea ? NODE_ADD_HOVER_COLOR : NODE_ADD_CIRCLE_COLOR,
|
|
2805
|
+
stroke: TRANSPARENT,
|
|
2806
|
+
fillStyle: 'solid'
|
|
2807
|
+
});
|
|
2808
|
+
const hLineBeginPoint = [addCenter[0] - NODE_MORE_BRIDGE_DISTANCE / 2, addCenter[1]];
|
|
2809
|
+
const hLineEndPoint = [addCenter[0] + NODE_MORE_BRIDGE_DISTANCE / 2, addCenter[1]];
|
|
2810
|
+
const vLineBeginPoint = [addCenter[0], addCenter[1] - NODE_MORE_BRIDGE_DISTANCE / 2];
|
|
2811
|
+
const vLineEndPoint = [addCenter[0], addCenter[1] + NODE_MORE_BRIDGE_DISTANCE / 2];
|
|
2812
|
+
const innerCrossHLine = PlaitBoard.getRoughSVG(this.board).line(hLineBeginPoint[0], hLineBeginPoint[1], hLineEndPoint[0], hLineEndPoint[1], {
|
|
2813
|
+
stroke: NODE_ADD_INNER_CROSS_COLOR,
|
|
2814
|
+
strokeWidth: NODE_MORE_STROKE_WIDTH
|
|
2815
|
+
});
|
|
2816
|
+
setStrokeLinecap(innerCrossHLine, 'round');
|
|
2817
|
+
const innerCrossVLine = PlaitBoard.getRoughSVG(this.board).line(vLineBeginPoint[0], vLineBeginPoint[1], vLineEndPoint[0], vLineEndPoint[1], {
|
|
2818
|
+
stroke: NODE_ADD_INNER_CROSS_COLOR,
|
|
2819
|
+
strokeWidth: NODE_MORE_STROKE_WIDTH
|
|
2820
|
+
});
|
|
2821
|
+
setStrokeLinecap(innerCrossVLine, 'round');
|
|
2822
|
+
addG.appendChild(circle);
|
|
2823
|
+
addG.appendChild(innerCrossHLine);
|
|
2824
|
+
addG.appendChild(innerCrossVLine);
|
|
2866
2825
|
}
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
});
|
|
2879
|
-
const badge = PlaitBoard.getRoughSVG(this.board).circle(circleCenter[0], circleCenter[1], EXTEND_DIAMETER, {
|
|
2826
|
+
parentG.appendChild(this.collapseOrAddG);
|
|
2827
|
+
}
|
|
2828
|
+
toggleExpandBadge(element, moreStartAndEnd, center, stroke, parentG, isCollapsed, isHoveredExpandIcon) {
|
|
2829
|
+
this.expandG?.remove();
|
|
2830
|
+
if (!isCollapsed) {
|
|
2831
|
+
return;
|
|
2832
|
+
}
|
|
2833
|
+
this.expandG = createG();
|
|
2834
|
+
this.expandG.classList.add('expanded-button');
|
|
2835
|
+
const endWithWidth = moreStartAndEnd[1];
|
|
2836
|
+
const moreLine = PlaitBoard.getRoughSVG(this.board).line(moreStartAndEnd[0][0], moreStartAndEnd[0][1], endWithWidth[0], endWithWidth[1], {
|
|
2880
2837
|
fill: stroke,
|
|
2881
2838
|
stroke,
|
|
2882
|
-
fillStyle: 'solid'
|
|
2839
|
+
fillStyle: 'solid',
|
|
2840
|
+
strokeWidth: NODE_MORE_STROKE_WIDTH
|
|
2883
2841
|
});
|
|
2884
|
-
const
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2842
|
+
const backgroundColor = isHoveredExpandIcon ? rgbaToHEX(stroke, 0.4) : rgbaToHEX(stroke, 0.2);
|
|
2843
|
+
const badgeBackground = PlaitBoard.getRoughSVG(this.board).circle(center[0], center[1], NODE_MORE_ICON_DIAMETER + NODE_MORE_STROKE_WIDTH, {
|
|
2844
|
+
fill: backgroundColor,
|
|
2845
|
+
stroke: TRANSPARENT,
|
|
2888
2846
|
fillStyle: 'solid'
|
|
2889
2847
|
});
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
collapseG.appendChild(badgeText);
|
|
2901
|
-
collapseG.appendChild(extendLine);
|
|
2902
|
-
}
|
|
2903
|
-
else {
|
|
2904
|
-
collapseG.appendChild(hideCircleG);
|
|
2905
|
-
collapseG.appendChild(arrowLine);
|
|
2906
|
-
}
|
|
2907
|
-
collapseG.appendChild(extendLine);
|
|
2908
|
-
return collapseG;
|
|
2909
|
-
}
|
|
2910
|
-
afterDraw(element) {
|
|
2911
|
-
if (!this.g) {
|
|
2912
|
-
throw new Error(`can not find quick insert g`);
|
|
2913
|
-
}
|
|
2914
|
-
fromEvent(this.g, 'pointerdown')
|
|
2915
|
-
.pipe(filter(() => !PlaitBoard.isPointer(this.board, PlaitPointerType.hand) || !!PlaitBoard.isReadonly(this.board)), take(1))
|
|
2916
|
-
.subscribe((event) => {
|
|
2917
|
-
event.preventDefault();
|
|
2918
|
-
const isCollapsed = !element.isCollapsed;
|
|
2919
|
-
const newElement = { isCollapsed };
|
|
2920
|
-
const path = PlaitBoard.findPath(this.board, element);
|
|
2921
|
-
Transforms.setNode(this.board, newElement, path);
|
|
2848
|
+
const childrenCount = getChildrenCount(element);
|
|
2849
|
+
let text = `${childrenCount}`;
|
|
2850
|
+
let y = center[1] + 4.5;
|
|
2851
|
+
if (childrenCount >= 99) {
|
|
2852
|
+
text = '...';
|
|
2853
|
+
y = center[1] + 1;
|
|
2854
|
+
}
|
|
2855
|
+
const { width, height } = measureElement(this.board, buildText(text), {
|
|
2856
|
+
fontSize: Number(FontSizes.fontSize12),
|
|
2857
|
+
fontFamily: DEFAULT_FONT_FAMILY
|
|
2922
2858
|
});
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
arrowBottomPoint = moveYOfPoint(arrowBottomPoint, -4, linkDirection);
|
|
2930
|
-
return [arrowTopPoint, arrowMiddlePoint, arrowBottomPoint];
|
|
2859
|
+
const badgeText = createText(center[0] - width / 2 + 0.5, y, stroke, `${text}`);
|
|
2860
|
+
badgeText.setAttribute('style', `font-size: ${Number(FontSizes.fontSize12)}px;`);
|
|
2861
|
+
this.expandG.appendChild(moreLine);
|
|
2862
|
+
this.expandG.appendChild(badgeBackground);
|
|
2863
|
+
this.expandG.appendChild(badgeText);
|
|
2864
|
+
parentG.appendChild(this.expandG);
|
|
2931
2865
|
}
|
|
2932
2866
|
}
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2867
|
+
const getCollapseAndAddCenterPoint = (board, element) => {
|
|
2868
|
+
const layoutDirection = getNodeMoreLayoutDirection(board, element);
|
|
2869
|
+
const [startPoint, endPoint] = getMoreStartAndEnd(board, element, layoutDirection);
|
|
2870
|
+
const collapseCenter = moveXOfPoint(endPoint, NODE_MORE_ICON_DIAMETER / 2, layoutDirection);
|
|
2871
|
+
const addCenter = getAddCenterByCollapseOrExpandCenter(element, collapseCenter, layoutDirection);
|
|
2872
|
+
return { collapseCenter, addCenter };
|
|
2873
|
+
};
|
|
2874
|
+
const getAddCenterByCollapseOrExpandCenter = (target, collapseOrExpandCenter, layoutDirection) => {
|
|
2875
|
+
let addCenter = collapseOrExpandCenter;
|
|
2876
|
+
if (target.children?.length > 0 && !PlaitMind.isMind(target)) {
|
|
2877
|
+
addCenter = moveXOfPoint(addCenter, NODE_MORE_LINE_DISTANCE + NODE_MORE_ICON_DIAMETER, layoutDirection);
|
|
2937
2878
|
}
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2879
|
+
return addCenter;
|
|
2880
|
+
};
|
|
2881
|
+
const getNodeMoreLayoutDirection = (board, element) => {
|
|
2882
|
+
const node = MindElement.getNode(element);
|
|
2883
|
+
const layout = MindQueries.getLayoutByElement(element);
|
|
2884
|
+
const isHorizontal = isHorizontalLayout(layout);
|
|
2885
|
+
let layoutDirection = getLayoutDirection(node, isHorizontal);
|
|
2886
|
+
if (isIndentedLayout(layout)) {
|
|
2887
|
+
layoutDirection = isTopLayout(layout) ? LayoutDirection.top : LayoutDirection.bottom;
|
|
2944
2888
|
}
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2889
|
+
return layoutDirection;
|
|
2890
|
+
};
|
|
2891
|
+
const getMoreStartAndEnd = (board, element, linkLineDirection) => {
|
|
2892
|
+
const node = MindElement.getNode(element);
|
|
2893
|
+
const isUnderlineShape = getShapeByElement(board, element) === MindElementShape.underline;
|
|
2894
|
+
const nodeClient = getRectangleByNode(node);
|
|
2895
|
+
let placement = [HorizontalPlacement.right, VerticalPlacement.middle];
|
|
2896
|
+
transformPlacement(placement, linkLineDirection);
|
|
2897
|
+
// underline shape and horizontal
|
|
2898
|
+
const layout = MindQueries.getLayoutByElement(element);
|
|
2899
|
+
const isHorizontal = isHorizontalLayout(layout);
|
|
2900
|
+
if (isHorizontal && isUnderlineShape && !element.isRoot) {
|
|
2901
|
+
placement[1] = VerticalPlacement.bottom;
|
|
2948
2902
|
}
|
|
2949
|
-
|
|
2903
|
+
let startPoint = getPointByPlacement(nodeClient, placement);
|
|
2904
|
+
const endPoint = moveXOfPoint(startPoint, NODE_MORE_LINE_DISTANCE, linkLineDirection);
|
|
2905
|
+
return [startPoint, endPoint];
|
|
2906
|
+
};
|
|
2907
|
+
const isLastSelectedMindElement = (board, element) => {
|
|
2908
|
+
const selectedElements = getSelectedElements(board);
|
|
2909
|
+
const selectedMindElements = selectedElements.filter((element) => MindElement.isMindElement(board, element)).reverse();
|
|
2910
|
+
return selectedMindElements[selectedMindElements.length - 1] === element;
|
|
2911
|
+
};
|
|
2912
|
+
const canHandleNodeMore = (board) => {
|
|
2913
|
+
return !isResizing(board) && !isSelectionMoving(board) && !isDragging(board) && !isMovingElements(board);
|
|
2914
|
+
};
|
|
2950
2915
|
|
|
2951
2916
|
class MindNodeComponent extends CommonElementFlavour {
|
|
2952
2917
|
get textManage() {
|
|
@@ -2963,8 +2928,7 @@ class MindNodeComponent extends CommonElementFlavour {
|
|
|
2963
2928
|
this.nodeShapeGenerator = new NodeShapeGenerator(this.board);
|
|
2964
2929
|
this.nodeEmojisGenerator = new NodeEmojisGenerator(this.board);
|
|
2965
2930
|
this.activeGenerator = new NodeActiveGenerator(this.board);
|
|
2966
|
-
this.
|
|
2967
|
-
this.collapseGenerator = new CollapseGenerator(this.board);
|
|
2931
|
+
this.nodeMoreGenerator = new NodeMoreGenerator(this.board);
|
|
2968
2932
|
this.imageGenerator = new ImageGenerator(this.board, {
|
|
2969
2933
|
getRectangle: (element) => {
|
|
2970
2934
|
return getImageForeignRectangle(this.board, element);
|
|
@@ -3002,6 +2966,7 @@ class MindNodeComponent extends CommonElementFlavour {
|
|
|
3002
2966
|
this.getRef().addGenerator(NodeActiveGenerator.key, this.activeGenerator);
|
|
3003
2967
|
this.getRef().addGenerator(NodeEmojisGenerator.key, this.nodeEmojisGenerator);
|
|
3004
2968
|
this.getRef().addGenerator(ImageGenerator.key, this.imageGenerator);
|
|
2969
|
+
this.getRef().addGenerator(NodeMoreGenerator.key, this.nodeMoreGenerator);
|
|
3005
2970
|
this.getRef().initializeTextManage(textManage);
|
|
3006
2971
|
this.getRef().updateActiveSection = () => {
|
|
3007
2972
|
this.activeGenerator.processDrawing(this.element, PlaitBoard.getActiveHost(this.board), {
|
|
@@ -3021,8 +2986,8 @@ class MindNodeComponent extends CommonElementFlavour {
|
|
|
3021
2986
|
this.activeGenerator.processDrawing(this.element, PlaitBoard.getActiveHost(this.board), {
|
|
3022
2987
|
selected: this.selected
|
|
3023
2988
|
});
|
|
2989
|
+
this.nodeMoreGenerator.processDrawing(this.element, this.getElementG());
|
|
3024
2990
|
this.drawEmojis();
|
|
3025
|
-
this.drawExtend();
|
|
3026
2991
|
this.imageGenerator.processDrawing(this.element, this.getElementG());
|
|
3027
2992
|
if (PlaitMind.isMind(this.context.parent)) {
|
|
3028
2993
|
this.getElementG().classList.add('branch');
|
|
@@ -3036,10 +3001,10 @@ class MindNodeComponent extends CommonElementFlavour {
|
|
|
3036
3001
|
this.activeGenerator.processDrawing(this.element, PlaitBoard.getActiveHost(this.board), {
|
|
3037
3002
|
selected: this.selected
|
|
3038
3003
|
});
|
|
3004
|
+
this.nodeMoreGenerator.processDrawing(this.element, this.getElementG(), { isSelected: this.selected });
|
|
3039
3005
|
this.nodeShapeGenerator.processDrawing(this.element, this.getElementG(), { node: this.node });
|
|
3040
3006
|
this.drawLink();
|
|
3041
3007
|
this.drawEmojis();
|
|
3042
|
-
this.drawExtend();
|
|
3043
3008
|
if (!MindElement.hasImage(previous.element) && MindElement.hasImage(this.element)) {
|
|
3044
3009
|
this.imageGenerator.processDrawing(this.element, this.getElementG());
|
|
3045
3010
|
}
|
|
@@ -3058,6 +3023,9 @@ class MindNodeComponent extends CommonElementFlavour {
|
|
|
3058
3023
|
this.activeGenerator.processDrawing(this.element, PlaitBoard.getActiveHost(this.board), {
|
|
3059
3024
|
selected: this.selected
|
|
3060
3025
|
});
|
|
3026
|
+
this.nodeMoreGenerator.processDrawing(this.element, this.getElementG(), {
|
|
3027
|
+
isSelected: this.selected
|
|
3028
|
+
});
|
|
3061
3029
|
}
|
|
3062
3030
|
if (!hasSameParent) {
|
|
3063
3031
|
this.drawLink();
|
|
@@ -3076,32 +3044,17 @@ class MindNodeComponent extends CommonElementFlavour {
|
|
|
3076
3044
|
}
|
|
3077
3045
|
const parent = MindElement.getParent(this.element);
|
|
3078
3046
|
const parentNode = MindElement.getNode(parent);
|
|
3079
|
-
if (this.
|
|
3080
|
-
this.
|
|
3047
|
+
if (this.linkLineG) {
|
|
3048
|
+
this.linkLineG.remove();
|
|
3081
3049
|
}
|
|
3082
3050
|
const layout = MindQueries.getLayoutByElement(parent);
|
|
3083
3051
|
if (AbstractNode.isAbstract(this.node.origin)) {
|
|
3084
|
-
this.
|
|
3052
|
+
this.linkLineG = drawAbstractLink(this.board, this.node, isHorizontalLayout(layout));
|
|
3085
3053
|
}
|
|
3086
3054
|
else {
|
|
3087
|
-
this.
|
|
3055
|
+
this.linkLineG = drawLink(this.board, parentNode, this.node, isHorizontalLayout(layout));
|
|
3088
3056
|
}
|
|
3089
|
-
this.getElementG().append(this.
|
|
3090
|
-
}
|
|
3091
|
-
drawExtend() {
|
|
3092
|
-
if (!this.extendG) {
|
|
3093
|
-
this.extendG = createG();
|
|
3094
|
-
this.extendG.classList.add('extend');
|
|
3095
|
-
this.getElementG().append(this.extendG);
|
|
3096
|
-
}
|
|
3097
|
-
if (this.element.isCollapsed) {
|
|
3098
|
-
this.getElementG().classList.add('collapsed');
|
|
3099
|
-
}
|
|
3100
|
-
else {
|
|
3101
|
-
this.getElementG().classList.remove('collapsed');
|
|
3102
|
-
}
|
|
3103
|
-
this.nodePlusGenerator.processDrawing(this.element, this.extendG);
|
|
3104
|
-
this.collapseGenerator.processDrawing(this.element, this.extendG);
|
|
3057
|
+
this.getElementG().append(this.linkLineG);
|
|
3105
3058
|
}
|
|
3106
3059
|
drawTopic() {
|
|
3107
3060
|
this.textManage.draw(this.element.data.topic);
|
|
@@ -3580,72 +3533,152 @@ const withMindHotkey = (baseBoard) => {
|
|
|
3580
3533
|
return board;
|
|
3581
3534
|
};
|
|
3582
3535
|
|
|
3583
|
-
const
|
|
3536
|
+
const withNodeMore = (board) => {
|
|
3537
|
+
const { pointerMove, pointerLeave, pointerUp } = board;
|
|
3538
|
+
let nodeMoreRef = null;
|
|
3539
|
+
board.pointerMove = (event) => {
|
|
3540
|
+
if (canHandleNodeMore(board)) {
|
|
3541
|
+
throttleRAF(board, 'with-mind-node-hover-hit-test', () => {
|
|
3542
|
+
// target has been deleted
|
|
3543
|
+
if (nodeMoreRef && !PlaitElement.hasMounted(nodeMoreRef.target)) {
|
|
3544
|
+
nodeMoreRef = null;
|
|
3545
|
+
}
|
|
3546
|
+
const newNodeMoreRef = getNodeMoreRef(board, event.x, event.y);
|
|
3547
|
+
if (nodeMoreRef && newNodeMoreRef && nodeMoreRef.target === newNodeMoreRef.target) {
|
|
3548
|
+
return;
|
|
3549
|
+
}
|
|
3550
|
+
if (nodeMoreRef) {
|
|
3551
|
+
toggleHoveredNodeCallback({
|
|
3552
|
+
target: nodeMoreRef.target,
|
|
3553
|
+
isHovered: false,
|
|
3554
|
+
isHoveredCollapseArea: false,
|
|
3555
|
+
isHoveredExpandArea: false,
|
|
3556
|
+
isHoveredAddArea: false
|
|
3557
|
+
});
|
|
3558
|
+
}
|
|
3559
|
+
if (newNodeMoreRef) {
|
|
3560
|
+
toggleHoveredNodeCallback(newNodeMoreRef);
|
|
3561
|
+
if (nodeMoreRef) {
|
|
3562
|
+
nodeMoreRef.target = newNodeMoreRef.target;
|
|
3563
|
+
}
|
|
3564
|
+
else {
|
|
3565
|
+
nodeMoreRef = newNodeMoreRef;
|
|
3566
|
+
}
|
|
3567
|
+
}
|
|
3568
|
+
else {
|
|
3569
|
+
nodeMoreRef = null;
|
|
3570
|
+
}
|
|
3571
|
+
});
|
|
3572
|
+
}
|
|
3573
|
+
pointerMove(event);
|
|
3574
|
+
};
|
|
3575
|
+
board.pointerUp = (event) => {
|
|
3576
|
+
if (nodeMoreRef && (nodeMoreRef.isHoveredCollapseArea || nodeMoreRef.isHoveredExpandArea)) {
|
|
3577
|
+
const isCollapsed = !nodeMoreRef.target.isCollapsed;
|
|
3578
|
+
const newElement = { isCollapsed };
|
|
3579
|
+
const path = PlaitBoard.findPath(board, nodeMoreRef.target);
|
|
3580
|
+
Transforms.setNode(board, newElement, path);
|
|
3581
|
+
setTimeout(() => {
|
|
3582
|
+
const newNodeMoreRef = getNodeMoreRef(board, event.x, event.y);
|
|
3583
|
+
if (newNodeMoreRef) {
|
|
3584
|
+
toggleHoveredNodeCallback(newNodeMoreRef);
|
|
3585
|
+
nodeMoreRef = newNodeMoreRef;
|
|
3586
|
+
}
|
|
3587
|
+
else {
|
|
3588
|
+
nodeMoreRef = null;
|
|
3589
|
+
}
|
|
3590
|
+
}, 0);
|
|
3591
|
+
return;
|
|
3592
|
+
}
|
|
3593
|
+
if (nodeMoreRef && nodeMoreRef.isHoveredAddArea && !PlaitBoard.isReadonly(board)) {
|
|
3594
|
+
if (nodeMoreRef) {
|
|
3595
|
+
const path = findNewChildNodePath(board, nodeMoreRef.target);
|
|
3596
|
+
insertMindElement(board, nodeMoreRef.target, path);
|
|
3597
|
+
}
|
|
3598
|
+
return;
|
|
3599
|
+
}
|
|
3600
|
+
pointerUp(event);
|
|
3601
|
+
};
|
|
3602
|
+
const toggleHoveredNodeCallback = (ref) => {
|
|
3603
|
+
const elementRef = PlaitElement.getElementRef(ref.target);
|
|
3604
|
+
const nodeMoreGenerator = elementRef?.getGenerator(NodeMoreGenerator.key);
|
|
3605
|
+
if (nodeMoreGenerator) {
|
|
3606
|
+
const g = PlaitElement.getElementG(ref.target);
|
|
3607
|
+
nodeMoreGenerator.processDrawing(ref.target, g, {
|
|
3608
|
+
isHovered: ref.isHovered,
|
|
3609
|
+
isHoveredCollapseArea: ref.isHoveredCollapseArea,
|
|
3610
|
+
isHoveredExpandArea: ref.isHoveredExpandArea,
|
|
3611
|
+
isSelected: isSelectedElement(board, ref.target),
|
|
3612
|
+
isHoveredAddArea: ref.isHoveredAddArea,
|
|
3613
|
+
isShowCollapseAnimation: (ref.isHovered || ref.isHoveredCollapseArea) && !isSelectedElement(board, ref.target),
|
|
3614
|
+
isShowAddAnimation: (ref.isHovered || ref.isHoveredAddArea) && !isSelectedElement(board, ref.target)
|
|
3615
|
+
});
|
|
3616
|
+
}
|
|
3617
|
+
};
|
|
3618
|
+
board.pointerLeave = (event) => {
|
|
3619
|
+
if (nodeMoreRef) {
|
|
3620
|
+
toggleHoveredNodeCallback({
|
|
3621
|
+
target: nodeMoreRef.target,
|
|
3622
|
+
isHovered: false,
|
|
3623
|
+
isHoveredCollapseArea: false,
|
|
3624
|
+
isHoveredExpandArea: false,
|
|
3625
|
+
isHoveredAddArea: false
|
|
3626
|
+
});
|
|
3627
|
+
}
|
|
3628
|
+
nodeMoreRef = null;
|
|
3629
|
+
pointerLeave(event);
|
|
3630
|
+
};
|
|
3631
|
+
return board;
|
|
3632
|
+
};
|
|
3633
|
+
const getNodeMoreRef = (board, x, y) => {
|
|
3584
3634
|
let target = null;
|
|
3585
|
-
|
|
3586
|
-
|
|
3635
|
+
let isHovered = false;
|
|
3636
|
+
let isHoveredCollapseArea = false;
|
|
3637
|
+
let isHoveredExpandArea = false;
|
|
3638
|
+
let isHoveredAddArea = false;
|
|
3639
|
+
const point = toViewBoxPoint(board, toHostPoint(board, x, y));
|
|
3640
|
+
depthFirstRecursion(board, (element) => {
|
|
3587
3641
|
if (target) {
|
|
3588
3642
|
return;
|
|
3589
3643
|
}
|
|
3590
3644
|
if (!MindElement.isMindElement(board, element)) {
|
|
3591
3645
|
return;
|
|
3592
3646
|
}
|
|
3647
|
+
const isMind = PlaitMind.isMind(element);
|
|
3593
3648
|
const isHitElement = isHitMindElement(board, point, element);
|
|
3594
|
-
|
|
3649
|
+
let isHitCollapseOrExpand = false;
|
|
3650
|
+
let isHitAdd = false;
|
|
3651
|
+
const { collapseCenter, addCenter } = getCollapseAndAddCenterPoint(board, element);
|
|
3652
|
+
const collapseOrExpandIconRectangle = !isMind && RectangleClient.getRectangleByCenterPoint(collapseCenter, NODE_MORE_ICON_DIAMETER, NODE_MORE_ICON_DIAMETER);
|
|
3653
|
+
isHitCollapseOrExpand =
|
|
3654
|
+
collapseOrExpandIconRectangle &&
|
|
3655
|
+
RectangleClient.isHit(RectangleClient.getRectangleByPoints([point, point]), collapseOrExpandIconRectangle);
|
|
3656
|
+
const addIconRectangle = RectangleClient.getRectangleByCenterPoint(addCenter, NODE_MORE_ICON_DIAMETER, NODE_MORE_ICON_DIAMETER);
|
|
3657
|
+
isHitAdd = RectangleClient.isHit(RectangleClient.getRectangleByPoints([point, point]), addIconRectangle);
|
|
3658
|
+
if (isHitElement || isHitCollapseOrExpand || isHitAdd) {
|
|
3659
|
+
isHovered = isHitElement;
|
|
3660
|
+
if (element.children.length > 0) {
|
|
3661
|
+
if (element.isCollapsed) {
|
|
3662
|
+
isHoveredExpandArea = isHitCollapseOrExpand;
|
|
3663
|
+
}
|
|
3664
|
+
else {
|
|
3665
|
+
isHoveredCollapseArea = isHitCollapseOrExpand;
|
|
3666
|
+
}
|
|
3667
|
+
}
|
|
3668
|
+
isHoveredAddArea = isHitAdd;
|
|
3595
3669
|
target = element;
|
|
3596
3670
|
}
|
|
3597
3671
|
}, getIsRecursionFunc(board), true);
|
|
3598
|
-
if (
|
|
3599
|
-
return
|
|
3600
|
-
}
|
|
3601
|
-
if (nodeExtendHoveredRef) {
|
|
3602
|
-
removeHovered(nodeExtendHoveredRef.element);
|
|
3603
|
-
}
|
|
3604
|
-
if (target) {
|
|
3605
|
-
addHovered(target);
|
|
3606
|
-
if (nodeExtendHoveredRef) {
|
|
3607
|
-
nodeExtendHoveredRef.element = target;
|
|
3608
|
-
}
|
|
3609
|
-
else {
|
|
3610
|
-
nodeExtendHoveredRef = { element: target };
|
|
3611
|
-
}
|
|
3672
|
+
if (!target) {
|
|
3673
|
+
return null;
|
|
3612
3674
|
}
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
if (nodeExtendHoveredRef) {
|
|
3620
|
-
removeHovered(nodeExtendHoveredRef.element);
|
|
3621
|
-
}
|
|
3622
|
-
};
|
|
3623
|
-
const addHovered = (element) => {
|
|
3624
|
-
PlaitElement.getElementG(element).classList.add('hovered');
|
|
3625
|
-
};
|
|
3626
|
-
const removeHovered = (element) => {
|
|
3627
|
-
PlaitElement.getElementG(element)?.classList?.remove('hovered');
|
|
3628
|
-
};
|
|
3629
|
-
|
|
3630
|
-
const withNodeHoverHitTest = (board) => {
|
|
3631
|
-
const { pointerMove, pointerLeave } = board;
|
|
3632
|
-
let nodeExtendHoveredRef = null;
|
|
3633
|
-
board.pointerMove = (event) => {
|
|
3634
|
-
throttleRAF(board, 'with-mind-node-hover-hit-test', () => {
|
|
3635
|
-
// element has been deleted
|
|
3636
|
-
if (nodeExtendHoveredRef && !PlaitElement.hasMounted(nodeExtendHoveredRef.element)) {
|
|
3637
|
-
nodeExtendHoveredRef = null;
|
|
3638
|
-
}
|
|
3639
|
-
nodeExtendHoveredRef = pointerMoveHandle(board, event, nodeExtendHoveredRef);
|
|
3640
|
-
});
|
|
3641
|
-
pointerMove(event);
|
|
3642
|
-
};
|
|
3643
|
-
board.pointerLeave = (event) => {
|
|
3644
|
-
pointerLeaveHandle(board, event, nodeExtendHoveredRef);
|
|
3645
|
-
nodeExtendHoveredRef = null;
|
|
3646
|
-
pointerLeave(event);
|
|
3675
|
+
return {
|
|
3676
|
+
target,
|
|
3677
|
+
isHovered,
|
|
3678
|
+
isHoveredCollapseArea,
|
|
3679
|
+
isHoveredExpandArea,
|
|
3680
|
+
isHoveredAddArea
|
|
3647
3681
|
};
|
|
3648
|
-
return board;
|
|
3649
3682
|
};
|
|
3650
3683
|
|
|
3651
3684
|
const withNodeImage = (board) => {
|
|
@@ -3800,9 +3833,9 @@ const withNodeResize = (board) => {
|
|
|
3800
3833
|
return board;
|
|
3801
3834
|
};
|
|
3802
3835
|
const getSelectedTarget = (board, point) => {
|
|
3803
|
-
const selectedElements = getSelectedElements(board).filter(value => MindElement.isMindElement(board, value));
|
|
3836
|
+
const selectedElements = getSelectedElements(board).filter((value) => MindElement.isMindElement(board, value));
|
|
3804
3837
|
if (selectedElements.length > 0) {
|
|
3805
|
-
const target = selectedElements.find(value => {
|
|
3838
|
+
const target = selectedElements.find((value) => {
|
|
3806
3839
|
const rectangle = getResizeActiveRectangle(board, value);
|
|
3807
3840
|
return distanceBetweenPointAndRectangle(point[0], point[1], rectangle) <= 0;
|
|
3808
3841
|
});
|
|
@@ -3813,7 +3846,12 @@ const getSelectedTarget = (board, point) => {
|
|
|
3813
3846
|
const getResizeActiveRectangle = (board, element) => {
|
|
3814
3847
|
const node = MindElement.getNode(element);
|
|
3815
3848
|
const rectangle = getRectangleByNode(node);
|
|
3816
|
-
return {
|
|
3849
|
+
return {
|
|
3850
|
+
x: rectangle.x + rectangle.width - RESIZE_HANDLE_BUFFER_DISTANCE,
|
|
3851
|
+
y: rectangle.y,
|
|
3852
|
+
width: RESIZE_HANDLE_BUFFER_DISTANCE * 2,
|
|
3853
|
+
height: rectangle.height
|
|
3854
|
+
};
|
|
3817
3855
|
};
|
|
3818
3856
|
|
|
3819
3857
|
const withNodeImageResize = (board) => {
|
|
@@ -3912,7 +3950,7 @@ const insertClipboardData = (board, elements, targetPoint, operationType) => {
|
|
|
3912
3950
|
if (hasTargetParent && operationType !== WritableClipboardOperationType.duplicate) {
|
|
3913
3951
|
if (item.isRoot) {
|
|
3914
3952
|
newElement = adjustRootToNode(board, newElement);
|
|
3915
|
-
const { width, height } = getTopicSizeByElement(newElement, targetParent);
|
|
3953
|
+
const { width, height } = getTopicSizeByElement(board, newElement, targetParent);
|
|
3916
3954
|
newElement.width = width;
|
|
3917
3955
|
newElement.height = height;
|
|
3918
3956
|
}
|
|
@@ -3931,7 +3969,7 @@ const insertClipboardData = (board, elements, targetPoint, operationType) => {
|
|
|
3931
3969
|
}
|
|
3932
3970
|
if (!item.isRoot) {
|
|
3933
3971
|
newElement = adjustNodeToRoot(board, newElement);
|
|
3934
|
-
const { width, height } = getTopicSizeByElement(newElement);
|
|
3972
|
+
const { width, height } = getTopicSizeByElement(board, newElement);
|
|
3935
3973
|
newElement.width = width;
|
|
3936
3974
|
newElement.height = height;
|
|
3937
3975
|
}
|
|
@@ -3944,13 +3982,13 @@ const insertClipboardData = (board, elements, targetPoint, operationType) => {
|
|
|
3944
3982
|
Transforms.addSelectionWithTemporaryElements(board, newELements);
|
|
3945
3983
|
};
|
|
3946
3984
|
const insertClipboardText = (board, targetParent, text) => {
|
|
3947
|
-
const { width, height } = getTopicSize(false, PlaitMind.isMind(targetParent), buildText(text));
|
|
3985
|
+
const { width, height } = getTopicSize(board, false, PlaitMind.isMind(targetParent), buildText(text));
|
|
3948
3986
|
const newElement = createMindElement(text, Math.max(width, getFontSizeBySlateElement(text)), height, {});
|
|
3949
3987
|
Transforms.insertNode(board, newElement, findNewChildNodePath(board, targetParent));
|
|
3950
3988
|
Transforms.addSelectionWithTemporaryElements(board, [newElement]);
|
|
3951
3989
|
};
|
|
3952
|
-
const getTopicSizeByElement = (element, parentElement) => {
|
|
3953
|
-
return getTopicSize(PlaitMind.isMind(element), (parentElement && PlaitMind.isMind(parentElement)) || false, element.data.topic, element.manualWidth);
|
|
3990
|
+
const getTopicSizeByElement = (board, element, parentElement) => {
|
|
3991
|
+
return getTopicSize(board, PlaitMind.isMind(element), (parentElement && PlaitMind.isMind(parentElement)) || false, element.data.topic, element.manualWidth);
|
|
3954
3992
|
};
|
|
3955
3993
|
|
|
3956
3994
|
const withMindFragment = (baseBoard) => {
|
|
@@ -4218,7 +4256,7 @@ const withMind = (baseBoard) => {
|
|
|
4218
4256
|
}
|
|
4219
4257
|
dblClick(event);
|
|
4220
4258
|
};
|
|
4221
|
-
return withEmoji(withNodeResize(withNodeImageResize(withNodeImage(
|
|
4259
|
+
return withEmoji(withNodeResize(withNodeImageResize(withNodeImage(withNodeMore(withMindFragment(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board)))))))))));
|
|
4222
4260
|
};
|
|
4223
4261
|
|
|
4224
4262
|
class MindEmojiBaseComponent {
|
|
@@ -4235,5 +4273,5 @@ class MindEmojiBaseComponent {
|
|
|
4235
4273
|
* Generated bundle index. Do not edit.
|
|
4236
4274
|
*/
|
|
4237
4275
|
|
|
4238
|
-
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, ELEMENT_TO_NODE,
|
|
4276
|
+
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, ELEMENT_TO_NODE, GRAY_COLOR, INHERIT_ATTRIBUTE_KEYS, LayoutDirection, LayoutDirectionsMap, MIND_CENTRAL_TEXT, 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, NodeTopicThreshold, 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, getDefaultLayout, getDefaultMindElementFontSize, getDefaultMindNameText, getEmojiFontSize, getEmojiForeignRectangle, getEmojiRectangle, getEmojisWidthHeight, getFillByElement, getFirstLevelElement, getFontSizeBySlateElement, 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, getTopicSize, getValidAbstractRefs, handleTouchedAbstract, hasPreviousOrNextOfDropPath, insertElementHandleAbstract, insertElementHandleRightNodeCount, insertMindElement, isChildElement, isChildOfAbstract, isChildRight, isChildUp, isCorrectLayout, isDropStandardRight, isHitEmojis, isHitImage, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, removeActiveOnDragOrigin, removeImageFocus, separateChildren, setMindDragging, withEmoji, withMind, withMindExtend };
|
|
4239
4277
|
//# sourceMappingURL=plait-mind.mjs.map
|