@plait/mind 0.47.0 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Component, ChangeDetectionStrategy, NgZone, Directive, Input, HostListener } from '@angular/core';
3
- import { DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, PlaitElement, PlaitNode, Path, isNullOrUndefined, PlaitBoard, distanceBetweenPointAndRectangle, RectangleClient, getSelectedElements, idCreator, Transforms, clearSelectedElement, addSelectedElement, depthFirstRecursion, getIsRecursionFunc, drawRoundRectangle, drawLinearPath, drawBezierPath, createG, updateForeignObject, getRectangleByElements, NODE_TO_PARENT, createForeignObject, removeSelectedElement, PlaitHistoryBoard, setStrokeLinecap, ACTIVE_STROKE_WIDTH, createText, PlaitPointerType, NODE_TO_INDEX, PlaitChildrenElementComponent, isMainPointer, transformPoint, toPoint, getHitElementByPoint, distanceBetweenPointAndPoint, CoreTransforms, BOARD_TO_HOST, BoardTransforms, throttleRAF, temporaryDisableSelection, hotkeys, setClipboardDataByMedia, getClipboardDataByMedia, ResizeCursorClass, setClipboardData, setClipboardDataByText, getDataFromClipboard, PlaitPluginKey } from '@plait/core';
3
+ import { DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, PlaitElement, PlaitNode, Path, isNullOrUndefined, PlaitBoard, getSelectedElements, idCreator, Transforms, clearSelectedElement, addSelectedElement, distanceBetweenPointAndRectangle, RectangleClient, depthFirstRecursion, getIsRecursionFunc, drawRoundRectangle, drawLinearPath, drawBezierPath, createG, updateForeignObject, getRectangleByElements, NODE_TO_PARENT, createForeignObject, removeSelectedElement, PlaitHistoryBoard, setStrokeLinecap, ACTIVE_STROKE_WIDTH, createText, PlaitPointerType, NODE_TO_INDEX, PlaitChildrenElementComponent, isMainPointer, toViewBoxPoint, toHostPoint, getHitElementByPoint, distanceBetweenPointAndPoint, CoreTransforms, BOARD_TO_HOST, BoardTransforms, throttleRAF, temporaryDisableSelection, hotkeys, setClipboardDataByMedia, getClipboardDataByMedia, ResizeCursorClass, setClipboardData, setClipboardDataByText, getDataFromClipboard, PlaitPluginKey } from '@plait/core';
4
4
  import { MindLayoutType, AbstractNode, isIndentedLayout, isHorizontalLayout, isHorizontalLogicLayout, ConnectingPosition, getNonAbstractChildren, isStandardLayout, isLeftLayout, isRightLayout, isVerticalLogicLayout, isTopLayout, isBottomLayout, getCorrectStartEnd, getAbstractLayout, GlobalLayout } from '@plait/layouts';
5
- import { PlaitMarkEditor, MarkTypes, DEFAULT_FONT_SIZE, TEXT_DEFAULT_HEIGHT, buildText, getTextSize, TextManage, ExitOrigin, getTextFromClipboard } from '@plait/text';
5
+ import { TEXT_DEFAULT_HEIGHT, buildText, PlaitMarkEditor, MarkTypes, DEFAULT_FONT_SIZE, getTextSize, TextManage, ExitOrigin, getTextFromClipboard } from '@plait/text';
6
6
  import { fromEvent, Subject } from 'rxjs';
7
- import { getFirstTextEditor, RESIZE_HANDLE_DIAMETER, getRectangleResizeHandleRefs, addElementOfFocusedImage, removeElementOfFocusedImage, getFirstTextManage, Generator, CommonPluginElement, ImageGenerator, WithTextPluginKey, isDrawingMode, isDndMode, setCreationMode, BoardCreationMode, isExpandHotkey, isTabHotkey, isEnterHotkey, isVirtualKey, isDelete, isSpaceHotkey, getElementOfFocusedImage, MediaKeys, acceptImageTypes, buildImage, withResize, ResizeHandle } from '@plait/common';
7
+ import { getFirstTextEditor, RESIZE_HANDLE_DIAMETER, getRectangleResizeHandleRefs, addElementOfFocusedImage, removeElementOfFocusedImage, getFirstTextManage, PropertyTransforms, Generator, CommonPluginElement, ImageGenerator, WithTextPluginKey, isDrawingMode, isDndMode, setCreationMode, BoardCreationMode, isExpandHotkey, isTabHotkey, isEnterHotkey, isVirtualKey, isDelete, isSpaceHotkey, getElementOfFocusedImage, MediaKeys, acceptImageTypes, buildImage, withResize, ResizeHandle } from '@plait/common';
8
8
  import { Node as Node$1, Path as Path$1 } from 'slate';
9
9
  import { pointsOnBezierCurves } from 'points-on-curve';
10
10
  import { take, filter } from 'rxjs/operators';
@@ -208,18 +208,6 @@ function getEmojiFontSize(element) {
208
208
  }
209
209
  }
210
210
 
211
- const TOPIC_COLOR = '#333';
212
- const TOPIC_FONT_SIZE = 14;
213
- const ROOT_TOPIC_FONT_SIZE = 18;
214
- const ROOT_TOPIC_HEIGHT = 25;
215
- const ROOT_TOPIC_WIDTH = 72;
216
- const TOPIC_DEFAULT_MAX_WORD_COUNT = 34;
217
- const DEFAULT_FONT_FAMILY = 'PingFangSC-Regular, "PingFang SC"';
218
- const BRANCH_FONT_FAMILY = 'PingFangSC-Medium, "PingFang SC"';
219
- const NodeTopicThreshold = {
220
- defaultTextMaxWidth: 34 * 14
221
- };
222
-
223
211
  const getAvailableProperty = (board, element, propertyKey) => {
224
212
  return element[propertyKey];
225
213
  };
@@ -337,7 +325,7 @@ function getRelativeStartEndByAbstractRef(abstractRef, elements) {
337
325
  return { start, end };
338
326
  }
339
327
  const insertElementHandleAbstract = (board, path, step = 1,
340
- //由此区分拖拽和新增到概要概括最后一个节点
328
+ // This distinguishes between dragging and adding to the last node summarized in the abstract node
341
329
  isExtendPreviousNode = true, effectedAbstracts = new Map()) => {
342
330
  const parent = PlaitNode.parent(board, path);
343
331
  const hasPreviousNode = path[path.length - 1] !== 0;
@@ -491,240 +479,6 @@ const getShapeByElement = (board, element) => {
491
479
  return shape || MindElementShape.roundRectangle;
492
480
  };
493
481
 
494
- const NodeDefaultSpace = {
495
- horizontal: {
496
- nodeAndText: BASE * 2.5,
497
- emojiAndText: BASE * 1.5
498
- },
499
- vertical: {
500
- nodeAndText: BASE,
501
- nodeAndImage: BASE,
502
- imageAndText: BASE * 1.5
503
- }
504
- };
505
- const RootDefaultSpace = {
506
- horizontal: {
507
- nodeAndText: BASE * 4,
508
- emojiAndText: BASE * 2
509
- },
510
- vertical: {
511
- nodeAndText: BASE * 2
512
- }
513
- };
514
- const getHorizontalSpaceBetweenNodeAndText = (board, element) => {
515
- const isMind = PlaitMind.isMind(element);
516
- const nodeAndText = isMind ? RootDefaultSpace.horizontal.nodeAndText : NodeDefaultSpace.horizontal.nodeAndText;
517
- const strokeWidth = getStrokeWidthByElement(board, element);
518
- return nodeAndText + strokeWidth;
519
- };
520
- const getVerticalSpaceBetweenNodeAndText = (board, element) => {
521
- const isMind = PlaitMind.isMind(element);
522
- const strokeWidth = getStrokeWidthByElement(board, element);
523
- const nodeAndText = isMind ? RootDefaultSpace.vertical.nodeAndText : NodeDefaultSpace.vertical.nodeAndText;
524
- return nodeAndText + strokeWidth;
525
- };
526
- const getSpaceEmojiAndText = (element) => {
527
- const isMind = PlaitMind.isMind(element);
528
- const emojiAndText = isMind ? RootDefaultSpace.horizontal.emojiAndText : NodeDefaultSpace.horizontal.emojiAndText;
529
- return emojiAndText;
530
- };
531
- const NodeSpace = {
532
- getNodeWidth(board, element) {
533
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
534
- if (MindElement.hasEmojis(element)) {
535
- return (NodeSpace.getEmojiLeftSpace(board, element) +
536
- getEmojisWidthHeight(board, element).width +
537
- getSpaceEmojiAndText(element) +
538
- NodeSpace.getNodeDynamicWidth(board, element) +
539
- nodeAndText);
540
- }
541
- return nodeAndText + NodeSpace.getNodeDynamicWidth(board, element) + nodeAndText;
542
- },
543
- getNodeHeight(board, element) {
544
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
545
- if (MindElement.hasImage(element)) {
546
- return NodeSpace.getTextTopSpace(board, element) + element.height + nodeAndText;
547
- }
548
- return nodeAndText + element.height + nodeAndText;
549
- },
550
- getNodeDynamicWidth(board, element) {
551
- const width = element.manualWidth || element.width;
552
- const imageWidth = MindElement.hasImage(element) ? element.data.image?.width : 0;
553
- return Math.max(width, imageWidth);
554
- },
555
- /**
556
- * use it when upload image first or resize image
557
- */
558
- getNodeNewDynamicWidth(board, element, imageWidth) {
559
- const width = element.manualWidth || element.width;
560
- return Math.max(width, imageWidth);
561
- },
562
- getNodeResizableMinWidth(board, element) {
563
- const minTopicWidth = NodeSpace.getNodeTopicMinWidth(board, element);
564
- if (MindElement.hasImage(element) && element.data.image.width > minTopicWidth) {
565
- return element.data.image.width;
566
- }
567
- else {
568
- return minTopicWidth;
569
- }
570
- },
571
- getNodeTopicMinWidth(board, element, isRoot = false) {
572
- const defaultFontSize = getNodeDefaultFontSize(isRoot);
573
- const editor = getFirstTextEditor(element);
574
- const marks = PlaitMarkEditor.getMarks(editor);
575
- const fontSize = marks[MarkTypes.fontSize] || defaultFontSize;
576
- return fontSize;
577
- },
578
- getTextLeftSpace(board, element) {
579
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
580
- if (MindElement.hasEmojis(element)) {
581
- return NodeSpace.getEmojiLeftSpace(board, element) + getEmojisWidthHeight(board, element).width + getSpaceEmojiAndText(element);
582
- }
583
- else {
584
- return nodeAndText;
585
- }
586
- },
587
- getTextTopSpace(board, element) {
588
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
589
- if (MindElement.hasImage(element)) {
590
- return NodeSpace.getImageTopSpace(board, element) + element.data.image.height + NodeDefaultSpace.vertical.imageAndText;
591
- }
592
- else {
593
- return nodeAndText;
594
- }
595
- },
596
- getImageTopSpace(board, element) {
597
- const strokeWidth = getStrokeWidthByElement(board, element);
598
- return strokeWidth + NodeDefaultSpace.vertical.nodeAndImage;
599
- },
600
- getEmojiLeftSpace(board, element) {
601
- const options = board.getPluginOptions(WithMindPluginKey);
602
- const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
603
- return nodeAndText - options.emojiPadding;
604
- },
605
- getEmojiTopSpace(board, element) {
606
- const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
607
- return nodeAndText;
608
- }
609
- };
610
- const getFontSizeBySlateElement = (text) => {
611
- const defaultFontSize = DEFAULT_FONT_SIZE;
612
- if (typeof text === 'string') {
613
- return defaultFontSize;
614
- }
615
- const marks = PlaitMarkEditor.getMarksByElement(text);
616
- const fontSize = marks[MarkTypes.fontSize] || defaultFontSize;
617
- return fontSize;
618
- };
619
- const getNodeDefaultFontSize = (isRoot = false) => {
620
- const defaultFontSize = isRoot ? ROOT_TOPIC_FONT_SIZE : DEFAULT_FONT_SIZE;
621
- return defaultFontSize;
622
- };
623
-
624
- function getRectangleByNode(node) {
625
- const x = node.x + node.hGap;
626
- let y = node.y + node.vGap;
627
- const width = node.width - node.hGap * 2;
628
- const height = node.height - node.vGap * 2;
629
- return {
630
- x,
631
- y,
632
- width,
633
- height
634
- };
635
- }
636
- function getRectangleByElement(board, element) {
637
- const width = NodeSpace.getNodeWidth(board, element);
638
- const height = NodeSpace.getNodeHeight(board, element);
639
- const nodeRectangle = {
640
- x: element.points[0][0],
641
- y: element.points[0][1],
642
- width,
643
- height
644
- };
645
- return nodeRectangle;
646
- }
647
- function isHitMindElement(board, point, element) {
648
- const node = MindElement.getNode(element);
649
- if (node && distanceBetweenPointAndRectangle(point[0], point[1], getRectangleByNode(node)) === 0) {
650
- return true;
651
- }
652
- else {
653
- return false;
654
- }
655
- }
656
-
657
- function getEmojiRectangle(board, element) {
658
- let { x, y } = getRectangleByNode(MindElement.getNode(element));
659
- x = x + NodeSpace.getEmojiLeftSpace(board, element);
660
- const { width, height } = getEmojisWidthHeight(board, element);
661
- return {
662
- x,
663
- y,
664
- width,
665
- height
666
- };
667
- }
668
- function getEmojiForeignRectangle(board, element) {
669
- let { x, y } = getRectangleByNode(MindElement.getNode(element));
670
- x = x + NodeSpace.getEmojiLeftSpace(board, element);
671
- const { width } = getEmojisWidthHeight(board, element);
672
- return {
673
- x,
674
- y,
675
- width,
676
- height: NodeSpace.getNodeHeight(board, element)
677
- };
678
- }
679
- const isHitEmojis = (board, element, point) => {
680
- return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), getEmojiRectangle(board, element));
681
- };
682
-
683
- function getTopicRectangleByNode(board, node) {
684
- let nodeRectangle = getRectangleByNode(node);
685
- const result = getTopicRectangleByElement(board, nodeRectangle, node.origin);
686
- result.width = result.width;
687
- return result;
688
- }
689
- function getTopicRectangleByElement(board, nodeRectangle, element) {
690
- const x = nodeRectangle.x + NodeSpace.getTextLeftSpace(board, element);
691
- const y = nodeRectangle.y + NodeSpace.getTextTopSpace(board, element);
692
- const width = NodeSpace.getNodeDynamicWidth(board, element);
693
- const height = Math.ceil(element.height);
694
- return { height, width, x, y };
695
- }
696
-
697
- function getImageForeignRectangle(board, element) {
698
- let { x, y } = getRectangleByNode(MindElement.getNode(element));
699
- const elementWidth = element.manualWidth || element.width;
700
- x =
701
- elementWidth > element.data.image.width
702
- ? x + NodeSpace.getTextLeftSpace(board, element) + (elementWidth - element.data.image.width) / 2
703
- : x + NodeSpace.getTextLeftSpace(board, element);
704
- y = NodeSpace.getImageTopSpace(board, element) + y;
705
- const { width, height } = element.data.image;
706
- const rectangle = {
707
- x,
708
- y,
709
- width,
710
- height
711
- };
712
- return rectangle;
713
- }
714
- const isHitImage = (board, element, point) => {
715
- const imageRectangle = getImageForeignRectangle(board, element);
716
- const imageOutlineRectangle = RectangleClient.getOutlineRectangle(imageRectangle, -RESIZE_HANDLE_DIAMETER / 2);
717
- return RectangleClient.isPointInRectangle(imageOutlineRectangle, point);
718
- };
719
- const getHitImageResizeHandleDirection = (board, element, point) => {
720
- const imageRectangle = getImageForeignRectangle(board, element);
721
- const resizeHandleRefs = getRectangleResizeHandleRefs(imageRectangle, RESIZE_HANDLE_DIAMETER);
722
- const result = resizeHandleRefs.find(resizeHandleRef => {
723
- return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), resizeHandleRef.rectangle);
724
- });
725
- return result;
726
- };
727
-
728
482
  function editTopic(element) {
729
483
  const component = PlaitElement.getComponent(element);
730
484
  component?.editTopic();
@@ -734,6 +488,18 @@ const getSelectedMindElements = (board) => {
734
488
  return selectedElements;
735
489
  };
736
490
 
491
+ const TOPIC_COLOR = '#333';
492
+ const TOPIC_FONT_SIZE = 14;
493
+ const ROOT_TOPIC_FONT_SIZE = 18;
494
+ const ROOT_TOPIC_HEIGHT = 25;
495
+ const ROOT_TOPIC_WIDTH = 72;
496
+ const TOPIC_DEFAULT_MAX_WORD_COUNT = 34;
497
+ const DEFAULT_FONT_FAMILY = 'PingFangSC-Regular, "PingFang SC"';
498
+ const BRANCH_FONT_FAMILY = 'PingFangSC-Medium, "PingFang SC"';
499
+ const NodeTopicThreshold = {
500
+ defaultTextMaxWidth: 34 * 14
501
+ };
502
+
737
503
  const getBranchDirectionsByLayouts = (branchLayouts) => {
738
504
  const branchDirections = [];
739
505
  branchLayouts.forEach(l => {
@@ -907,142 +673,381 @@ const createEmptyMind = (board, point) => {
907
673
  element.type = 'mindmap';
908
674
  const width = NodeSpace.getNodeWidth(board, element);
909
675
  const height = NodeSpace.getNodeHeight(board, element);
910
- element.points = [[point[0] - width / 2, point[1] - height / 2]];
911
- return element;
912
- };
913
- const createDefaultMind = (point, rightNodeCount, layout) => {
914
- const root = createMindElement('思维导图', ROOT_TOPIC_WIDTH, ROOT_TOPIC_HEIGHT, { layout });
915
- root.rightNodeCount = rightNodeCount;
916
- root.isRoot = true;
917
- root.type = 'mindmap';
918
- root.points = [point];
919
- const children = [1, 1, 1].map(() => {
920
- return createMindElement('新建节点', 56, TEXT_DEFAULT_HEIGHT, {});
921
- });
922
- root.children = children;
923
- return root;
924
- };
925
- const createMindElement = (text, width, height, options) => {
926
- const newElement = {
927
- id: idCreator(),
928
- data: {
929
- topic: buildText(text)
930
- },
931
- children: [],
676
+ element.points = [[point[0] - width / 2, point[1] - height / 2]];
677
+ return element;
678
+ };
679
+ const createDefaultMind = (point, rightNodeCount, layout) => {
680
+ const root = createMindElement('思维导图', ROOT_TOPIC_WIDTH, ROOT_TOPIC_HEIGHT, { layout });
681
+ root.rightNodeCount = rightNodeCount;
682
+ root.isRoot = true;
683
+ root.type = 'mindmap';
684
+ root.points = [point];
685
+ const children = [1, 1, 1].map(() => {
686
+ return createMindElement('新建节点', 56, TEXT_DEFAULT_HEIGHT, {});
687
+ });
688
+ root.children = children;
689
+ return root;
690
+ };
691
+ const createMindElement = (text, width, height, options) => {
692
+ const newElement = {
693
+ id: idCreator(),
694
+ data: {
695
+ topic: buildText(text)
696
+ },
697
+ children: [],
698
+ width,
699
+ height
700
+ };
701
+ let key;
702
+ for (key in options) {
703
+ if (!isNullOrUndefined(options[key])) {
704
+ newElement[key] = options[key];
705
+ }
706
+ }
707
+ return newElement;
708
+ };
709
+ const INHERIT_ATTRIBUTE_KEYS = [
710
+ 'fill',
711
+ 'strokeColor',
712
+ 'strokeWidth',
713
+ 'shape',
714
+ 'layout',
715
+ 'branchColor',
716
+ 'branchWidth',
717
+ 'branchShape'
718
+ ];
719
+
720
+ const getChildrenCount = (element) => {
721
+ const count = element.children.reduce((p, c) => {
722
+ return p + getChildrenCount(c);
723
+ }, 0);
724
+ return count + element.children.length;
725
+ };
726
+ const isChildElement = (origin, child) => {
727
+ let parent = MindElement.findParent(child);
728
+ while (parent) {
729
+ if (parent === origin) {
730
+ return true;
731
+ }
732
+ parent = MindElement.findParent(parent);
733
+ }
734
+ return false;
735
+ };
736
+ const getFirstLevelElement = (elements) => {
737
+ let result = [];
738
+ elements.forEach(element => {
739
+ const isChild = elements.some(node => {
740
+ return isChildElement(node, element);
741
+ });
742
+ if (!isChild) {
743
+ result.push(element);
744
+ }
745
+ });
746
+ return result;
747
+ };
748
+ const isChildRight = (node, child) => {
749
+ return node.x < child.x;
750
+ };
751
+ const isChildUp = (node, child) => {
752
+ return node.y > child.y;
753
+ };
754
+ const copyNewNode = (node) => {
755
+ const newNode = { ...node };
756
+ newNode.id = idCreator();
757
+ newNode.children = [];
758
+ for (const childNode of node.children) {
759
+ newNode.children.push(copyNewNode(childNode));
760
+ }
761
+ return newNode;
762
+ };
763
+ const extractNodesText = (node) => {
764
+ let str = '';
765
+ if (node) {
766
+ str += Node$1.string(node.data.topic) + ' ';
767
+ for (const childNode of node.children) {
768
+ str += extractNodesText(childNode);
769
+ }
770
+ }
771
+ return str;
772
+ };
773
+ const insertMindElement = (board, inheritNode, path) => {
774
+ const newNode = {};
775
+ if (!inheritNode.isRoot) {
776
+ INHERIT_ATTRIBUTE_KEYS.forEach(attr => {
777
+ newNode[attr] = inheritNode[attr];
778
+ });
779
+ delete newNode.layout;
780
+ }
781
+ const newElement = createMindElement('', TOPIC_FONT_SIZE, TEXT_DEFAULT_HEIGHT, newNode);
782
+ Transforms.insertNode(board, newElement, path);
783
+ clearSelectedElement(board);
784
+ addSelectedElement(board, newElement);
785
+ setTimeout(() => {
786
+ editTopic(newElement);
787
+ });
788
+ };
789
+ const findLastChild = (child) => {
790
+ let result = child;
791
+ while (result.children.length !== 0) {
792
+ result = result.children[result.children.length - 1];
793
+ }
794
+ return result;
795
+ };
796
+ const divideElementByParent = (elements) => {
797
+ const abstractIncludedGroups = [];
798
+ const parentElements = [];
799
+ for (let i = 0; i < elements.length; i++) {
800
+ const parent = MindElement.getParent(elements[i]);
801
+ const parentIndex = parentElements.indexOf(parent);
802
+ if (parentIndex === -1) {
803
+ parentElements.push(parent);
804
+ abstractIncludedGroups.push([elements[i]]);
805
+ }
806
+ else {
807
+ abstractIncludedGroups[parentIndex].push(elements[i]);
808
+ }
809
+ }
810
+ return { parentElements, abstractIncludedGroups };
811
+ };
812
+ const getDefaultMindElementFontSize = (board, element) => {
813
+ if (PlaitMind.isMind(element)) {
814
+ return ROOT_TOPIC_FONT_SIZE;
815
+ }
816
+ if (MindElement.isMindElement(board, element)) {
817
+ return TOPIC_FONT_SIZE;
818
+ }
819
+ throw new Error('can not find default font-size');
820
+ };
821
+
822
+ const NodeDefaultSpace = {
823
+ horizontal: {
824
+ nodeAndText: BASE * 2.5,
825
+ emojiAndText: BASE * 1.5
826
+ },
827
+ vertical: {
828
+ nodeAndText: BASE,
829
+ nodeAndImage: BASE,
830
+ imageAndText: BASE * 1.5
831
+ }
832
+ };
833
+ const RootDefaultSpace = {
834
+ horizontal: {
835
+ nodeAndText: BASE * 4,
836
+ emojiAndText: BASE * 2
837
+ },
838
+ vertical: {
839
+ nodeAndText: BASE * 2
840
+ }
841
+ };
842
+ const getHorizontalSpaceBetweenNodeAndText = (board, element) => {
843
+ const isMind = PlaitMind.isMind(element);
844
+ const nodeAndText = isMind ? RootDefaultSpace.horizontal.nodeAndText : NodeDefaultSpace.horizontal.nodeAndText;
845
+ const strokeWidth = getStrokeWidthByElement(board, element);
846
+ return nodeAndText + strokeWidth;
847
+ };
848
+ const getVerticalSpaceBetweenNodeAndText = (board, element) => {
849
+ const isMind = PlaitMind.isMind(element);
850
+ const strokeWidth = getStrokeWidthByElement(board, element);
851
+ const nodeAndText = isMind ? RootDefaultSpace.vertical.nodeAndText : NodeDefaultSpace.vertical.nodeAndText;
852
+ return nodeAndText + strokeWidth;
853
+ };
854
+ const getSpaceEmojiAndText = (element) => {
855
+ const isMind = PlaitMind.isMind(element);
856
+ const emojiAndText = isMind ? RootDefaultSpace.horizontal.emojiAndText : NodeDefaultSpace.horizontal.emojiAndText;
857
+ return emojiAndText;
858
+ };
859
+ const NodeSpace = {
860
+ getNodeWidth(board, element) {
861
+ const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
862
+ if (MindElement.hasEmojis(element)) {
863
+ return (NodeSpace.getEmojiLeftSpace(board, element) +
864
+ getEmojisWidthHeight(board, element).width +
865
+ getSpaceEmojiAndText(element) +
866
+ NodeSpace.getNodeDynamicWidth(board, element) +
867
+ nodeAndText);
868
+ }
869
+ return nodeAndText + NodeSpace.getNodeDynamicWidth(board, element) + nodeAndText;
870
+ },
871
+ getNodeHeight(board, element) {
872
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
873
+ if (MindElement.hasImage(element)) {
874
+ return NodeSpace.getTextTopSpace(board, element) + element.height + nodeAndText;
875
+ }
876
+ return nodeAndText + element.height + nodeAndText;
877
+ },
878
+ getNodeDynamicWidth(board, element) {
879
+ const width = element.manualWidth || element.width;
880
+ const imageWidth = MindElement.hasImage(element) ? element.data.image?.width : 0;
881
+ return Math.max(width, imageWidth);
882
+ },
883
+ /**
884
+ * use it when upload image first or resize image
885
+ */
886
+ getNodeNewDynamicWidth(board, element, imageWidth) {
887
+ const width = element.manualWidth || element.width;
888
+ return Math.max(width, imageWidth);
889
+ },
890
+ getNodeResizableMinWidth(board, element) {
891
+ const minTopicWidth = NodeSpace.getNodeTopicMinWidth(board, element);
892
+ if (MindElement.hasImage(element) && element.data.image.width > minTopicWidth) {
893
+ return element.data.image.width;
894
+ }
895
+ else {
896
+ return minTopicWidth;
897
+ }
898
+ },
899
+ getNodeTopicMinWidth(board, element) {
900
+ const defaultFontSize = getDefaultMindElementFontSize(board, element);
901
+ const editor = getFirstTextEditor(element);
902
+ const marks = PlaitMarkEditor.getMarks(editor);
903
+ const fontSize = marks[MarkTypes.fontSize] || defaultFontSize;
904
+ return fontSize;
905
+ },
906
+ getTextLeftSpace(board, element) {
907
+ const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
908
+ if (MindElement.hasEmojis(element)) {
909
+ return NodeSpace.getEmojiLeftSpace(board, element) + getEmojisWidthHeight(board, element).width + getSpaceEmojiAndText(element);
910
+ }
911
+ else {
912
+ return nodeAndText;
913
+ }
914
+ },
915
+ getTextTopSpace(board, element) {
916
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
917
+ if (MindElement.hasImage(element)) {
918
+ return NodeSpace.getImageTopSpace(board, element) + element.data.image.height + NodeDefaultSpace.vertical.imageAndText;
919
+ }
920
+ else {
921
+ return nodeAndText;
922
+ }
923
+ },
924
+ getImageTopSpace(board, element) {
925
+ const strokeWidth = getStrokeWidthByElement(board, element);
926
+ return strokeWidth + NodeDefaultSpace.vertical.nodeAndImage;
927
+ },
928
+ getEmojiLeftSpace(board, element) {
929
+ const options = board.getPluginOptions(WithMindPluginKey);
930
+ const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
931
+ return nodeAndText - options.emojiPadding;
932
+ },
933
+ getEmojiTopSpace(board, element) {
934
+ const nodeAndText = getVerticalSpaceBetweenNodeAndText(board, element);
935
+ return nodeAndText;
936
+ }
937
+ };
938
+ const getFontSizeBySlateElement = (text) => {
939
+ const defaultFontSize = DEFAULT_FONT_SIZE;
940
+ if (typeof text === 'string') {
941
+ return defaultFontSize;
942
+ }
943
+ const marks = PlaitMarkEditor.getMarksByElement(text);
944
+ const fontSize = marks[MarkTypes.fontSize] || defaultFontSize;
945
+ return fontSize;
946
+ };
947
+
948
+ function getRectangleByNode(node) {
949
+ const x = node.x + node.hGap;
950
+ let y = node.y + node.vGap;
951
+ const width = node.width - node.hGap * 2;
952
+ const height = node.height - node.vGap * 2;
953
+ return {
954
+ x,
955
+ y,
956
+ width,
957
+ height
958
+ };
959
+ }
960
+ function getRectangleByElement(board, element) {
961
+ const width = NodeSpace.getNodeWidth(board, element);
962
+ const height = NodeSpace.getNodeHeight(board, element);
963
+ const nodeRectangle = {
964
+ x: element.points[0][0],
965
+ y: element.points[0][1],
932
966
  width,
933
967
  height
934
968
  };
935
- let key;
936
- for (key in options) {
937
- if (!isNullOrUndefined(options[key])) {
938
- newElement[key] = options[key];
939
- }
969
+ return nodeRectangle;
970
+ }
971
+ function isHitMindElement(board, point, element) {
972
+ const node = MindElement.getNode(element);
973
+ if (node && distanceBetweenPointAndRectangle(point[0], point[1], getRectangleByNode(node)) === 0) {
974
+ return true;
940
975
  }
941
- return newElement;
942
- };
943
- const INHERIT_ATTRIBUTE_KEYS = [
944
- 'fill',
945
- 'strokeColor',
946
- 'strokeWidth',
947
- 'shape',
948
- 'layout',
949
- 'branchColor',
950
- 'branchWidth',
951
- 'branchShape'
952
- ];
953
-
954
- const getChildrenCount = (element) => {
955
- const count = element.children.reduce((p, c) => {
956
- return p + getChildrenCount(c);
957
- }, 0);
958
- return count + element.children.length;
959
- };
960
- const isChildElement = (origin, child) => {
961
- let parent = MindElement.findParent(child);
962
- while (parent) {
963
- if (parent === origin) {
964
- return true;
965
- }
966
- parent = MindElement.findParent(parent);
976
+ else {
977
+ return false;
967
978
  }
968
- return false;
979
+ }
980
+
981
+ function getEmojiRectangle(board, element) {
982
+ let { x, y } = getRectangleByNode(MindElement.getNode(element));
983
+ x = x + NodeSpace.getEmojiLeftSpace(board, element);
984
+ const { width, height } = getEmojisWidthHeight(board, element);
985
+ return {
986
+ x,
987
+ y,
988
+ width,
989
+ height
990
+ };
991
+ }
992
+ function getEmojiForeignRectangle(board, element) {
993
+ let { x, y } = getRectangleByNode(MindElement.getNode(element));
994
+ x = x + NodeSpace.getEmojiLeftSpace(board, element);
995
+ const { width } = getEmojisWidthHeight(board, element);
996
+ return {
997
+ x,
998
+ y,
999
+ width,
1000
+ height: NodeSpace.getNodeHeight(board, element)
1001
+ };
1002
+ }
1003
+ const isHitEmojis = (board, element, point) => {
1004
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), getEmojiRectangle(board, element));
969
1005
  };
970
- const getFirstLevelElement = (elements) => {
971
- let result = [];
972
- elements.forEach(element => {
973
- const isChild = elements.some(node => {
974
- return isChildElement(node, element);
975
- });
976
- if (!isChild) {
977
- result.push(element);
978
- }
979
- });
1006
+
1007
+ function getTopicRectangleByNode(board, node) {
1008
+ let nodeRectangle = getRectangleByNode(node);
1009
+ const result = getTopicRectangleByElement(board, nodeRectangle, node.origin);
1010
+ result.width = result.width;
980
1011
  return result;
1012
+ }
1013
+ function getTopicRectangleByElement(board, nodeRectangle, element) {
1014
+ const x = nodeRectangle.x + NodeSpace.getTextLeftSpace(board, element);
1015
+ const y = nodeRectangle.y + NodeSpace.getTextTopSpace(board, element);
1016
+ const width = NodeSpace.getNodeDynamicWidth(board, element);
1017
+ const height = Math.ceil(element.height);
1018
+ return { height, width, x, y };
1019
+ }
1020
+
1021
+ function getImageForeignRectangle(board, element) {
1022
+ let { x, y } = getRectangleByNode(MindElement.getNode(element));
1023
+ const elementWidth = element.manualWidth || element.width;
1024
+ x =
1025
+ elementWidth > element.data.image.width
1026
+ ? x + NodeSpace.getTextLeftSpace(board, element) + (elementWidth - element.data.image.width) / 2
1027
+ : x + NodeSpace.getTextLeftSpace(board, element);
1028
+ y = NodeSpace.getImageTopSpace(board, element) + y;
1029
+ const { width, height } = element.data.image;
1030
+ const rectangle = {
1031
+ x,
1032
+ y,
1033
+ width,
1034
+ height
1035
+ };
1036
+ return rectangle;
1037
+ }
1038
+ const isHitImage = (board, element, point) => {
1039
+ const imageRectangle = getImageForeignRectangle(board, element);
1040
+ const imageOutlineRectangle = RectangleClient.getOutlineRectangle(imageRectangle, -RESIZE_HANDLE_DIAMETER / 2);
1041
+ return RectangleClient.isPointInRectangle(imageOutlineRectangle, point);
981
1042
  };
982
- const isChildRight = (node, child) => {
983
- return node.x < child.x;
984
- };
985
- const isChildUp = (node, child) => {
986
- return node.y > child.y;
987
- };
988
- const copyNewNode = (node) => {
989
- const newNode = { ...node };
990
- newNode.id = idCreator();
991
- newNode.children = [];
992
- for (const childNode of node.children) {
993
- newNode.children.push(copyNewNode(childNode));
994
- }
995
- return newNode;
996
- };
997
- const extractNodesText = (node) => {
998
- let str = '';
999
- if (node) {
1000
- str += Node$1.string(node.data.topic) + ' ';
1001
- for (const childNode of node.children) {
1002
- str += extractNodesText(childNode);
1003
- }
1004
- }
1005
- return str;
1006
- };
1007
- const insertMindElement = (board, inheritNode, path) => {
1008
- const newNode = {};
1009
- if (!inheritNode.isRoot) {
1010
- INHERIT_ATTRIBUTE_KEYS.forEach(attr => {
1011
- newNode[attr] = inheritNode[attr];
1012
- });
1013
- delete newNode.layout;
1014
- }
1015
- const newElement = createMindElement('', getNodeDefaultFontSize(), TEXT_DEFAULT_HEIGHT, newNode);
1016
- Transforms.insertNode(board, newElement, path);
1017
- clearSelectedElement(board);
1018
- addSelectedElement(board, newElement);
1019
- setTimeout(() => {
1020
- editTopic(newElement);
1043
+ const getHitImageResizeHandleDirection = (board, element, point) => {
1044
+ const imageRectangle = getImageForeignRectangle(board, element);
1045
+ const resizeHandleRefs = getRectangleResizeHandleRefs(imageRectangle, RESIZE_HANDLE_DIAMETER);
1046
+ const result = resizeHandleRefs.find(resizeHandleRef => {
1047
+ return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), resizeHandleRef.rectangle);
1021
1048
  });
1022
- };
1023
- const findLastChild = (child) => {
1024
- let result = child;
1025
- while (result.children.length !== 0) {
1026
- result = result.children[result.children.length - 1];
1027
- }
1028
1049
  return result;
1029
1050
  };
1030
- const divideElementByParent = (elements) => {
1031
- const abstractIncludedGroups = [];
1032
- const parentElements = [];
1033
- for (let i = 0; i < elements.length; i++) {
1034
- const parent = MindElement.getParent(elements[i]);
1035
- const parentIndex = parentElements.indexOf(parent);
1036
- if (parentIndex === -1) {
1037
- parentElements.push(parent);
1038
- abstractIncludedGroups.push([elements[i]]);
1039
- }
1040
- else {
1041
- abstractIncludedGroups[parentIndex].push(elements[i]);
1042
- }
1043
- }
1044
- return { parentElements, abstractIncludedGroups };
1045
- };
1046
1051
 
1047
1052
  const adjustRootToNode = (board, node) => {
1048
1053
  const newNode = { ...node };
@@ -1075,7 +1080,7 @@ const adjustNodeToRoot = (board, node) => {
1075
1080
  fontFamily: BRANCH_FONT_FAMILY,
1076
1081
  width: node.manualWidth ? node.manualWidth : undefined
1077
1082
  });
1078
- newElement.width = Math.max(width, getNodeDefaultFontSize(true));
1083
+ newElement.width = Math.max(width, ROOT_TOPIC_FONT_SIZE);
1079
1084
  newElement.height = height;
1080
1085
  return {
1081
1086
  ...newElement,
@@ -1256,7 +1261,7 @@ const directionDetector = (targetNode, centerPoint) => {
1256
1261
  const left = targetNode.x;
1257
1262
  const right = targetNode.x + targetNode.width;
1258
1263
  const direction = [];
1259
- // x
1264
+ // x-axis
1260
1265
  if (centerPoint[1] > y && centerPoint[1] < y + height) {
1261
1266
  if (centerPoint[0] > left && centerPoint[0] < xCenter) {
1262
1267
  direction.push('left');
@@ -1264,7 +1269,7 @@ const directionDetector = (targetNode, centerPoint) => {
1264
1269
  if (centerPoint[0] > xCenter && centerPoint[0] < right) {
1265
1270
  direction.push('right');
1266
1271
  }
1267
- // 重合区域,返回两个方向
1272
+ // Overlapping area, return in both directions
1268
1273
  if ((centerPoint[0] > x && centerPoint[0] < xCenter) || (centerPoint[0] > xCenter && centerPoint[0] < x + width)) {
1269
1274
  if (centerPoint[1] < yCenter) {
1270
1275
  direction.push('top');
@@ -1275,7 +1280,7 @@ const directionDetector = (targetNode, centerPoint) => {
1275
1280
  }
1276
1281
  return direction.length ? direction : null;
1277
1282
  }
1278
- // y
1283
+ // y-axis
1279
1284
  if (centerPoint[0] > x && centerPoint[0] < x + width) {
1280
1285
  if (centerPoint[1] > top && centerPoint[1] < yCenter) {
1281
1286
  direction.push('top');
@@ -1304,17 +1309,14 @@ const getPathByDropTarget = (board, dropTarget) => {
1304
1309
  ? getRootLayout(dropTarget?.target)
1305
1310
  : MindQueries.getCorrectLayoutByElement(board, MindElement.getParent(dropTarget?.target));
1306
1311
  const children = getNonAbstractChildren(dropTarget.target);
1307
- // 上下布局:左右是兄弟节点,上下是子节点
1308
1312
  if (isVerticalLogicLayout(layout)) {
1309
1313
  if (dropTarget.detectResult === 'top' || dropTarget.detectResult === 'bottom') {
1310
1314
  targetPath.push(children.length);
1311
1315
  }
1312
- // 如果是左,位置不变,右则插入到下一个兄弟节点
1313
1316
  if (dropTarget.detectResult === 'right') {
1314
1317
  targetPath = Path.next(targetPath);
1315
1318
  }
1316
1319
  }
1317
- // 水平布局/标准布局:上下是兄弟节点,左右是子节点
1318
1320
  if (isHorizontalLogicLayout(layout)) {
1319
1321
  if (dropTarget.detectResult === 'right') {
1320
1322
  if (PlaitMind.isMind(dropTarget?.target) && isStandardLayout(layout)) {
@@ -1327,12 +1329,10 @@ const getPathByDropTarget = (board, dropTarget) => {
1327
1329
  if (dropTarget.detectResult === 'left') {
1328
1330
  targetPath.push(children.length);
1329
1331
  }
1330
- // 如果是上,位置不变,下插入到下一个兄弟节点
1331
1332
  if (dropTarget.detectResult === 'bottom') {
1332
1333
  targetPath = Path.next(targetPath);
1333
1334
  }
1334
1335
  }
1335
- // 缩进布局:上下是兄弟节点,左右是子节点,但上(左上/右上),探测到上是子节点,下则位置不变,反之同理。
1336
1336
  if (isIndentedLayout(layout)) {
1337
1337
  if (isTopLayout(layout) && dropTarget.detectResult === 'top') {
1338
1338
  targetPath = Path.next(targetPath);
@@ -1432,16 +1432,16 @@ const getLayoutDirection = (node, isHorizontal) => {
1432
1432
  }
1433
1433
  }
1434
1434
  };
1435
- // 以右为基准
1436
- // -> 左:
1437
- // 1. 终点 -> 起点/起点 -> 终点
1438
- // 2. ->
1439
- // 水平 -> 垂直:
1440
- // 1. 起点/终点 -> 纵轴
1441
- // 2. 加减 -> 纵轴
1442
- // -> 上:
1443
- // 1. 终点 -> 起点/终点 -> 起点
1444
- // 2. ->
1435
+ // Based on right
1436
+ // Right -> Left:
1437
+ // 1. End point -> starting point/start point -> end point
1438
+ // 2. Add -> Subtract
1439
+ // Horizontal -> Vertical:
1440
+ // 1. Starting point/end point -> vertical axis
1441
+ // 2. Addition and subtraction -> vertical axis
1442
+ // Bottom -> Top:
1443
+ // 1. End point -> starting point/end point -> starting point
1444
+ // 2. Add -> Subtract
1445
1445
  const moveXOfPoint = (point, distance, direction = LayoutDirection.right) => {
1446
1446
  if (direction === LayoutDirection.left) {
1447
1447
  return [point[0] - distance, point[1]];
@@ -1515,7 +1515,6 @@ function drawIndentedLink(board, node, child, defaultStroke = null, needDrawUnde
1515
1515
  beginY = isChildUp(node, child) ? beginRectangle.y : beginRectangle.y + beginRectangle.height;
1516
1516
  endX = node.left ? endNode.x + endNode.hGap + endRectangle.width : endNode.x + endNode.hGap;
1517
1517
  endY = isUnderlineShape ? endNode.y + endNode.height - endNode.vGap : endNode.y + endNode.height / 2;
1518
- //根据位置,设置正负参数
1519
1518
  let plusMinus = isChildUp(node, child) ? (node.left ? [-1, -1] : [1, -1]) : node.left ? [-1, 1] : [1, 1];
1520
1519
  let curve = [
1521
1520
  [beginX, beginY],
@@ -1569,12 +1568,11 @@ function drawLogicLink(board, parent, node, isHorizontal, defaultStroke = null,
1569
1568
  }
1570
1569
  let beginPoint = getPointByPlacement(parentClient, beginPlacement);
1571
1570
  let endPoint = getPointByPlacement(nodeClient, endPlacement);
1572
- // ② 确定凸出直线,从起始点开始画一条直线,从直线的结束位置绘制曲线,保证收起图标可以完美覆盖起始连线,根节点不需要这条直线
1573
- // 绘制贝塞尔曲线要求,需要增加三个点,正常两个点就可以确定这条直线
1571
+ // ② Determine the convex straight line
1574
1572
  const straightLineDistance = 8;
1575
1573
  const beginPoint2 = hasStraightLine ? moveXOfPoint(beginPoint, straightLineDistance, linkDirection) : beginPoint;
1576
1574
  let straightLine = hasStraightLine ? [beginPoint, beginPoint2, beginPoint2] : [];
1577
- // ③ 确定曲线
1575
+ // ③ Determine the curve
1578
1576
  const beginBufferDistance = (parent.hGap + node.hGap) / 3;
1579
1577
  const endBufferDistance = -(parent.hGap + node.hGap) / 2.4;
1580
1578
  let curve = [
@@ -1583,7 +1581,7 @@ function drawLogicLink(board, parent, node, isHorizontal, defaultStroke = null,
1583
1581
  moveXOfPoint(endPoint, endBufferDistance, linkDirection),
1584
1582
  endPoint
1585
1583
  ];
1586
- // ④ 下划线绘制,underline shape and horizontal
1584
+ // ④ underline shape and horizontal
1587
1585
  const underlineEnd = moveXOfPoint(endPoint, nodeClient.width, linkDirection);
1588
1586
  const underline = hasUnderlineShape && isHorizontal ? [underlineEnd, underlineEnd, underlineEnd] : [];
1589
1587
  const points = pointsOnBezierCurves([...straightLine, ...curve, ...underline]);
@@ -2047,7 +2045,7 @@ const getCorrectLayoutByElement = (board, element) => {
2047
2045
  const getBranchLayouts = (board, element) => {
2048
2046
  const layouts = [];
2049
2047
  if (element.layout) {
2050
- // TODO: getCorrectLayoutByElement 含有递归操作,getBranchLayouts 本身也有递归操作,有待优化
2048
+ // TODO: getCorrectLayoutByElement Contains recursive operations. getBranchLayouts itself also has recursive operations and needs to be optimized.
2051
2049
  layouts.unshift(getCorrectLayoutByElement(board, element));
2052
2050
  }
2053
2051
  let parent = MindElement.findParent(element);
@@ -2383,33 +2381,8 @@ const insertAbstractNode = (board, path, start, end) => {
2383
2381
  addSelectedElement(board, mindElement);
2384
2382
  };
2385
2383
 
2386
- const setLayout = (board, layout, path) => {
2387
- correctLogicLayoutNode(board, layout, path);
2388
- const element = PlaitNode.get(board, path);
2389
- if (PlaitMind.isMind(element) && isStandardLayout(layout)) {
2390
- MindTransforms.setAbstractByStandardLayout(board, element);
2391
- }
2392
- Transforms.setNode(board, { layout }, path);
2393
- };
2394
- const correctLogicLayoutNode = (board, layout, path) => {
2395
- const node = PlaitNode.get(board, path);
2396
- if (node && layout) {
2397
- node.children?.forEach((value, index) => {
2398
- if (value.layout) {
2399
- if ((isHorizontalLogicLayout(layout) && isVerticalLogicLayout(value.layout)) ||
2400
- (isVerticalLogicLayout(layout) && isHorizontalLogicLayout(value.layout))) {
2401
- Transforms.setNode(board, { layout: null }, [...path, index]);
2402
- }
2403
- if (value.children?.length) {
2404
- correctLogicLayoutNode(board, layout, [...path, index]);
2405
- }
2406
- }
2407
- });
2408
- }
2409
- };
2410
-
2411
2384
  const normalizeWidthAndHeight = (board, element, width, height) => {
2412
- const minWidth = NodeSpace.getNodeTopicMinWidth(board, element, element.isRoot);
2385
+ const minWidth = NodeSpace.getNodeTopicMinWidth(board, element);
2413
2386
  const newWidth = width < minWidth * board.viewport.zoom ? minWidth : width / board.viewport.zoom;
2414
2387
  const newHeight = height / board.viewport.zoom;
2415
2388
  return { width: Math.ceil(newWidth), height: newHeight };
@@ -2561,8 +2534,57 @@ const setImage = (board, element, imageItem) => {
2561
2534
  Transforms.setNode(board, newElement, path);
2562
2535
  };
2563
2536
 
2537
+ const correctLogicLayoutNode = (board, layout, path) => {
2538
+ const node = PlaitNode.get(board, path);
2539
+ if (node && layout) {
2540
+ node.children?.forEach((value, index) => {
2541
+ if (value.layout) {
2542
+ if ((isHorizontalLogicLayout(layout) && isVerticalLogicLayout(value.layout)) ||
2543
+ (isVerticalLogicLayout(layout) && isHorizontalLogicLayout(value.layout))) {
2544
+ Transforms.setNode(board, { layout: null }, [...path, index]);
2545
+ }
2546
+ if (value.children?.length) {
2547
+ correctLogicLayoutNode(board, layout, [...path, index]);
2548
+ }
2549
+ }
2550
+ });
2551
+ }
2552
+ };
2553
+
2554
+ const setLayout = (board, type) => {
2555
+ const callback = (element, path) => {
2556
+ if (MindElement.isMindElement(board, element)) {
2557
+ correctLogicLayoutNode(board, type, path);
2558
+ const element = PlaitNode.get(board, path);
2559
+ if (PlaitMind.isMind(element) && isStandardLayout(type)) {
2560
+ let properties = { rightNodeCount: element.children.length / 2 };
2561
+ Transforms.setNode(board, properties, path);
2562
+ setAbstractByStandardLayout(board, element);
2563
+ }
2564
+ Transforms.setNode(board, { layout: type }, path);
2565
+ }
2566
+ };
2567
+ PropertyTransforms.setProperty(board, {}, { callback });
2568
+ };
2569
+ const setShape = (board, shape) => {
2570
+ PropertyTransforms.setProperty(board, { shape });
2571
+ };
2572
+ const setBranchShape = (board, branchShape) => {
2573
+ PropertyTransforms.setProperty(board, { branchShape });
2574
+ };
2575
+ const setBranchWidth = (board, branchWidth) => {
2576
+ PropertyTransforms.setProperty(board, { branchWidth });
2577
+ };
2578
+ const setBranchColor = (board, branchColor) => {
2579
+ PropertyTransforms.setProperty(board, { branchColor });
2580
+ };
2581
+
2564
2582
  const MindTransforms = {
2565
2583
  setLayout,
2584
+ setShape,
2585
+ setBranchShape,
2586
+ setBranchWidth,
2587
+ setBranchColor,
2566
2588
  setTopic,
2567
2589
  setTopicSize,
2568
2590
  setNodeManualWidth,
@@ -3196,7 +3218,7 @@ const withNodeDnd = (board) => {
3196
3218
  pointerDown(event);
3197
3219
  return;
3198
3220
  }
3199
- const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3221
+ const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3200
3222
  const selectedElements = getSelectedElements(board);
3201
3223
  const hitElement = getHitElementByPoint(board, point);
3202
3224
  if (hitElement &&
@@ -3224,14 +3246,14 @@ const withNodeDnd = (board) => {
3224
3246
  if (!board.options.readonly && activeElements.length && startPoint) {
3225
3247
  // prevent text from being selected
3226
3248
  event.preventDefault();
3227
- const endPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3249
+ const endPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3228
3250
  const distance = distanceBetweenPointAndPoint(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
3229
3251
  if (distance < DRAG_MOVE_BUFFER) {
3230
3252
  return;
3231
3253
  }
3232
3254
  setIsDragging(board, true);
3233
3255
  fakeDropNodeG?.remove();
3234
- const detectPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3256
+ const detectPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3235
3257
  dropTarget = detectDropTarget(board, detectPoint, dropTarget, [...activeElements, ...correspondingElements]);
3236
3258
  if (dropTarget?.target) {
3237
3259
  targetPath = getPathByDropTarget(board, dropTarget);
@@ -3302,7 +3324,7 @@ const withNodeDnd = (board) => {
3302
3324
  let insertPath = targetPathRef.current;
3303
3325
  const parentPath = Path.parent(targetPathRef.current || targetPath);
3304
3326
  if (!insertPath) {
3305
- //当插入位置和选中节点位置相同时,使用记录的 previousPath
3327
+ // When the insertion position and the selected node position are the same, the recorded previousPath is used
3306
3328
  const previousPath = targetPreviousPathRef && targetPreviousPathRef.unref();
3307
3329
  if (previousPath) {
3308
3330
  insertPath = Path.next(previousPath);
@@ -3361,8 +3383,7 @@ const withAbstract = (board) => {
3361
3383
  return;
3362
3384
  }
3363
3385
  const activeAbstractElements = getSelectedElements(board).filter(element => AbstractNode.isAbstract(element));
3364
- const host = BOARD_TO_HOST.get(board);
3365
- const point = transformPoint(board, toPoint(event.x, event.y, host));
3386
+ const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3366
3387
  activeAbstractElement = activeAbstractElements.find(element => {
3367
3388
  abstractHandlePosition = getHitAbstractHandle(board, element, point);
3368
3389
  return abstractHandlePosition;
@@ -3379,7 +3400,7 @@ const withAbstract = (board) => {
3379
3400
  board.pointerMove = (event) => {
3380
3401
  getSelectedElements(board);
3381
3402
  const host = BOARD_TO_HOST.get(board);
3382
- const endPoint = transformPoint(board, toPoint(event.x, event.y, host));
3403
+ const endPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3383
3404
  touchedAbstract = handleTouchedAbstract(board, touchedAbstract, endPoint);
3384
3405
  if (abstractHandlePosition && activeAbstractElement) {
3385
3406
  // prevent text from being selected
@@ -3461,25 +3482,25 @@ const withMindExtend = (board) => {
3461
3482
  const DefaultHotkey = 'm';
3462
3483
  const withCreateMind = (board) => {
3463
3484
  const newBoard = board;
3464
- const { keydown, mousedown, mousemove, mouseup } = board;
3485
+ const { keydown, pointerDown, pointerMove, pointerUp } = board;
3465
3486
  let fakeCreateNodeRef = null;
3466
3487
  let emptyMind = null;
3467
- newBoard.mousedown = (event) => {
3488
+ newBoard.pointerDown = (event) => {
3468
3489
  const isMindPointer = PlaitBoard.isPointer(board, MindPointerType.mind);
3469
3490
  let movingPoint = PlaitBoard.getMovingPointInBoard(board);
3470
3491
  if (!PlaitBoard.isReadonly(board) && movingPoint && isDrawingMode(board) && isMindPointer) {
3471
- movingPoint = transformPoint(board, toPoint(movingPoint[0], movingPoint[1], PlaitBoard.getHost(board)));
3492
+ movingPoint = toViewBoxPoint(board, toHostPoint(board, movingPoint[0], movingPoint[1]));
3472
3493
  const emptyMind = createEmptyMind(newBoard, movingPoint);
3473
3494
  Transforms.insertNode(board, emptyMind, [board.children.length]);
3474
3495
  clearSelectedElement(board);
3475
3496
  addSelectedElement(board, emptyMind);
3476
3497
  BoardTransforms.updatePointerType(board, PlaitPointerType.selection);
3477
3498
  }
3478
- mousedown(event);
3499
+ pointerDown(event);
3479
3500
  };
3480
- newBoard.mousemove = (event) => {
3501
+ newBoard.pointerMove = (event) => {
3481
3502
  if (PlaitBoard.isReadonly(board)) {
3482
- mousemove(event);
3503
+ pointerMove(event);
3483
3504
  return;
3484
3505
  }
3485
3506
  const isMindPointer = PlaitBoard.isPointer(board, MindPointerType.mind);
@@ -3487,7 +3508,7 @@ const withCreateMind = (board) => {
3487
3508
  throttleRAF(() => {
3488
3509
  let movingPoint = PlaitBoard.getMovingPointInBoard(board);
3489
3510
  if (movingPoint) {
3490
- movingPoint = transformPoint(newBoard, toPoint(movingPoint[0], movingPoint[1], PlaitBoard.getHost(board)));
3511
+ movingPoint = toViewBoxPoint(newBoard, toHostPoint(board, movingPoint[0], movingPoint[1]));
3491
3512
  emptyMind = createEmptyMind(newBoard, movingPoint);
3492
3513
  const nodeRectangle = getRectangleByElement(newBoard, emptyMind);
3493
3514
  const nodeG = drawRoundRectangleByElement(board, nodeRectangle, emptyMind);
@@ -3526,9 +3547,9 @@ const withCreateMind = (board) => {
3526
3547
  else {
3527
3548
  destroy();
3528
3549
  }
3529
- mousemove(event);
3550
+ pointerMove(event);
3530
3551
  };
3531
- newBoard.mouseup = (event) => {
3552
+ newBoard.pointerUp = (event) => {
3532
3553
  if (emptyMind) {
3533
3554
  Transforms.insertNode(board, emptyMind, [board.children.length]);
3534
3555
  clearSelectedElement(board);
@@ -3537,7 +3558,7 @@ const withCreateMind = (board) => {
3537
3558
  emptyMind = null;
3538
3559
  }
3539
3560
  destroy();
3540
- mouseup(event);
3561
+ pointerUp(event);
3541
3562
  };
3542
3563
  board.keydown = (event) => {
3543
3564
  if (PlaitBoard.isReadonly(board) || getSelectedElements(board).length > 0) {
@@ -3606,7 +3627,7 @@ const withMindHotkey = (baseBoard) => {
3606
3627
 
3607
3628
  const mouseMoveHandle = (board, event, nodeHoveredExtendRef) => {
3608
3629
  let target = null;
3609
- const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3630
+ const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3610
3631
  depthFirstRecursion(board, element => {
3611
3632
  if (target) {
3612
3633
  return;
@@ -3681,7 +3702,7 @@ const withNodeImage = (board) => {
3681
3702
  pointerDown(event);
3682
3703
  return;
3683
3704
  }
3684
- const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3705
+ const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3685
3706
  const hitElement = getHitElementByPoint(board, point);
3686
3707
  const isHitImageResult = hitElement &&
3687
3708
  MindElement.isMindElement(board, hitElement) &&
@@ -3936,7 +3957,7 @@ const insertClipboardData = (board, elements, targetPoint) => {
3936
3957
  ...styles,
3937
3958
  width: newElement.manualWidth ? newElement.manualWidth : undefined
3938
3959
  });
3939
- newElement.width = Math.max(width, getNodeDefaultFontSize());
3960
+ newElement.width = Math.max(width, ROOT_TOPIC_FONT_SIZE);
3940
3961
  newElement.height = height;
3941
3962
  }
3942
3963
  // handle abstract start and end
@@ -4122,7 +4143,7 @@ const withMind = (baseBoard) => {
4122
4143
  dblclick(event);
4123
4144
  return;
4124
4145
  }
4125
- const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
4146
+ const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
4126
4147
  board.children
4127
4148
  .filter(value => PlaitMind.isMind(value))
4128
4149
  .forEach(mindMap => {
@@ -4191,5 +4212,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
4191
4212
  * Generated bundle index. Do not edit.
4192
4213
  */
4193
4214
 
4194
- export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_FONT_FAMILY, BRANCH_WIDTH, BranchShape, DEFAULT_FONT_FAMILY, DEFAULT_MIND_IMAGE_WIDTH, DefaultAbstractNodeStyle, DefaultNodeStyle, ELEMENT_TO_NODE, EXTEND_DIAMETER, EXTEND_OFFSET, GRAY_COLOR, INHERIT_ATTRIBUTE_KEYS, IS_DRAGGING, LayoutDirection, LayoutDirectionsMap, MindColorfulThemeColor, MindDarkThemeColor, MindDefaultThemeColor, MindElement, MindElementShape, MindEmojiBaseComponent, MindNode, MindNodeComponent, MindPointerType, MindQueries, MindRetroThemeColor, MindSoftThemeColor, MindStarryThemeColor, MindThemeColor, MindThemeColors, MindTransforms, NodeSpace, NodeTopicThreshold, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_TOPIC_FONT_SIZE, ROOT_TOPIC_HEIGHT, ROOT_TOPIC_WIDTH, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, WithMindPluginKey, addActiveOnDragOrigin, addImageFocus, adjustAbstractToNode, adjustNodeToRoot, adjustRootToNode, canSetAbstract, copyNewNode, correctLayoutByDirection, createDefaultMind, createEmptyMind, createMindElement, deleteElementHandleAbstract, deleteElementsHandleRightNodeCount, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNode, editTopic, extractNodesText, findLastChild, findLocationLeftIndex, findNewChildNodePath, findNewSiblingNodePath, 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, getSelectedMindElements, getShapeByElement, getStrokeByMindElement, getStrokeWidthByElement, getTopicRectangleByElement, getTopicRectangleByNode, getValidAbstractRefs, handleTouchedAbstract, hasPreviousOrNextOfDropPath, insertElementHandleAbstract, insertElementHandleRightNodeCount, insertMindElement, isChildElement, isChildOfAbstract, isChildRight, isChildUp, isCorrectLayout, isDragging, isDropStandardRight, isHitEmojis, isHitImage, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, removeActiveOnDragOrigin, removeImageFocus, separateChildren, setIsDragging, withMind, withMindExtend };
4215
+ export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_FONT_FAMILY, BRANCH_WIDTH, BranchShape, DEFAULT_FONT_FAMILY, DEFAULT_MIND_IMAGE_WIDTH, DefaultAbstractNodeStyle, DefaultNodeStyle, ELEMENT_TO_NODE, EXTEND_DIAMETER, EXTEND_OFFSET, GRAY_COLOR, INHERIT_ATTRIBUTE_KEYS, IS_DRAGGING, LayoutDirection, LayoutDirectionsMap, MindColorfulThemeColor, MindDarkThemeColor, MindDefaultThemeColor, MindElement, MindElementShape, MindEmojiBaseComponent, MindNode, MindNodeComponent, MindPointerType, MindQueries, MindRetroThemeColor, MindSoftThemeColor, MindStarryThemeColor, MindThemeColor, MindThemeColors, MindTransforms, NodeSpace, NodeTopicThreshold, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_TOPIC_FONT_SIZE, ROOT_TOPIC_HEIGHT, ROOT_TOPIC_WIDTH, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, WithMindPluginKey, addActiveOnDragOrigin, addImageFocus, adjustAbstractToNode, adjustNodeToRoot, adjustRootToNode, canSetAbstract, copyNewNode, correctLayoutByDirection, createDefaultMind, createEmptyMind, createMindElement, deleteElementHandleAbstract, deleteElementsHandleRightNodeCount, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNode, editTopic, extractNodesText, findLastChild, findLocationLeftIndex, findNewChildNodePath, findNewSiblingNodePath, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchShapeByMindElement, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultLayout, getDefaultMindElementFontSize, 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, getStrokeByMindElement, getStrokeWidthByElement, getTopicRectangleByElement, getTopicRectangleByNode, getValidAbstractRefs, handleTouchedAbstract, hasPreviousOrNextOfDropPath, insertElementHandleAbstract, insertElementHandleRightNodeCount, insertMindElement, isChildElement, isChildOfAbstract, isChildRight, isChildUp, isCorrectLayout, isDragging, isDropStandardRight, isHitEmojis, isHitImage, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, removeActiveOnDragOrigin, removeImageFocus, separateChildren, setIsDragging, withMind, withMindExtend };
4195
4216
  //# sourceMappingURL=plait-mind.mjs.map