@plait/mind 0.9.0 → 0.11.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/README.md +132 -13
- package/base/base.drawer.d.ts +4 -3
- package/constants/default.d.ts +1 -1
- package/constants/node-topic-style.d.ts +1 -0
- package/drawer/node-active.drawer.d.ts +13 -0
- package/drawer/node-collapse.drawer.d.ts +8 -0
- package/drawer/{emojis.drawer.d.ts → node-emojis.drawer.d.ts} +1 -1
- package/drawer/{quick-insert.drawer.d.ts → node-insert.drawer.d.ts} +2 -2
- package/esm2020/base/base.drawer.mjs +13 -1
- package/esm2020/constants/default.mjs +2 -2
- package/esm2020/constants/node-rule.mjs +1 -1
- package/esm2020/constants/node-topic-style.mjs +2 -1
- package/esm2020/drawer/node-active.drawer.mjs +43 -0
- package/esm2020/drawer/node-collapse.drawer.mjs +108 -0
- package/esm2020/drawer/node-emojis.drawer.mjs +72 -0
- package/esm2020/drawer/node-insert.drawer.mjs +98 -0
- package/esm2020/interfaces/element.mjs +5 -2
- package/esm2020/mind.component.mjs +2 -1
- package/esm2020/mind.module.mjs +5 -5
- package/esm2020/node.component.mjs +57 -424
- package/esm2020/plugins/with-abstract-resize.mjs +3 -3
- package/esm2020/plugins/with-mind-create.mjs +22 -15
- package/esm2020/plugins/with-mind.mjs +9 -8
- package/esm2020/plugins/with-node-dnd.mjs +2 -2
- package/esm2020/plugins/with-node-hover.mjs +65 -0
- package/esm2020/transforms/node.mjs +10 -7
- package/esm2020/utils/abstract/resize.mjs +4 -6
- package/esm2020/utils/dnd/common.mjs +8 -2
- package/esm2020/utils/draw/abstract-outline.mjs +7 -7
- package/esm2020/utils/draw/node-dnd.mjs +3 -3
- package/esm2020/utils/mind.mjs +4 -4
- package/esm2020/utils/node/adjust-node.mjs +4 -5
- package/esm2020/utils/node/common.mjs +3 -3
- package/esm2020/utils/node/create-node.mjs +4 -3
- package/fesm2015/plait-mind.mjs +547 -726
- package/fesm2015/plait-mind.mjs.map +1 -1
- package/fesm2020/plait-mind.mjs +547 -714
- package/fesm2020/plait-mind.mjs.map +1 -1
- package/interfaces/element.d.ts +1 -0
- package/mind.module.d.ts +2 -2
- package/node.component.d.ts +15 -31
- package/package.json +1 -1
- package/plugins/with-mind-create.d.ts +3 -5
- package/plugins/with-node-dnd.d.ts +1 -1
- package/plugins/with-node-hover.d.ts +5 -0
- package/styles/mixins.scss +13 -15
- package/styles/styles.scss +11 -10
- package/utils/abstract/resize.d.ts +2 -2
- package/utils/draw/abstract-outline.d.ts +0 -1
- package/utils/node/common.d.ts +1 -1
- package/esm2020/drawer/emojis.drawer.mjs +0 -72
- package/esm2020/drawer/quick-insert.drawer.mjs +0 -98
- package/esm2020/utils/draw/node-topic.mjs +0 -32
- package/utils/draw/node-topic.d.ts +0 -16
package/fesm2020/plait-mind.mjs
CHANGED
|
@@ -1,55 +1,19 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Component, ChangeDetectionStrategy, NgModule, Directive, Input, HostListener } from '@angular/core';
|
|
2
|
+
import { Component, ChangeDetectionStrategy, NgModule, NgZone, Directive, Input, HostListener } from '@angular/core';
|
|
3
3
|
import * as i2 from '@plait/core';
|
|
4
|
-
import { DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor,
|
|
4
|
+
import { DefaultThemeColor, ColorfulThemeColor, SoftThemeColor, RetroThemeColor, DarkThemeColor, StarryThemeColor, RectangleClient, PlaitElement, idCreator, isNullOrUndefined, Transforms, clearSelectedElement, addSelectedElement, PlaitBoard, depthFirstRecursion, Path, drawLinearPath, createG, updateForeignObject, PlaitNode, drawRoundRectangle, getRectangleByElements, getSelectedElements, NODE_TO_PARENT, distanceBetweenPointAndRectangle, createForeignObject, drawAbstractRoundRectangle, createText, PlaitPointerType, PlaitPluginElementComponent, NODE_TO_INDEX, PlaitModule, transformPoint, toPoint, distanceBetweenPointAndPoint, CLIP_BOARD_FORMAT_KEY, isMainPointer, BOARD_TO_HOST, PlaitPluginKey, throttleRAF, BoardTransforms, removeSelectedElement, PlaitHistoryBoard, hotkeys } from '@plait/core';
|
|
5
5
|
import { MindLayoutType, isIndentedLayout, getNonAbstractChildren, isStandardLayout, AbstractNode, isLeftLayout, isRightLayout, isVerticalLogicLayout, isHorizontalLogicLayout, isTopLayout, isBottomLayout, isHorizontalLayout, getCorrectStartEnd, getAbstractLayout, ConnectingPosition, GlobalLayout } from '@plait/layouts';
|
|
6
|
-
import {
|
|
7
|
-
import { fromEvent, Subject
|
|
8
|
-
import {
|
|
9
|
-
import { Node, Path as Path$1, Editor, Operation } from 'slate';
|
|
6
|
+
import { getTextSize, TEXT_DEFAULT_HEIGHT, TextManage, TextModule } from '@plait/text';
|
|
7
|
+
import { fromEvent, Subject } from 'rxjs';
|
|
8
|
+
import { Node, Path as Path$1 } from 'slate';
|
|
10
9
|
import { isKeyHotkey } from 'is-hotkey';
|
|
11
10
|
import { pointsOnBezierCurves } from 'points-on-curve';
|
|
11
|
+
import { take, filter } from 'rxjs/operators';
|
|
12
12
|
import * as i1 from '@angular/common';
|
|
13
13
|
import { CommonModule } from '@angular/common';
|
|
14
14
|
|
|
15
15
|
const ELEMENT_TO_NODE = new WeakMap();
|
|
16
16
|
|
|
17
|
-
const BASE = 4;
|
|
18
|
-
const PRIMARY_COLOR = '#6698FF';
|
|
19
|
-
const TRANSPARENT = 'transparent';
|
|
20
|
-
const GRAY_COLOR = '#AAAAAA';
|
|
21
|
-
const STROKE_WIDTH = 3;
|
|
22
|
-
const BRANCH_WIDTH = 3;
|
|
23
|
-
const EXTEND_OFFSET = 8;
|
|
24
|
-
const EXTEND_RADIUS = 16;
|
|
25
|
-
const QUICK_INSERT_CIRCLE_OFFSET = 9;
|
|
26
|
-
const QUICK_INSERT_CIRCLE_COLOR = '#6698FF';
|
|
27
|
-
const QUICK_INSERT_INNER_CROSS_COLOR = 'white';
|
|
28
|
-
|
|
29
|
-
const DefaultAbstractNodeStyle = {
|
|
30
|
-
strokeColor: GRAY_COLOR,
|
|
31
|
-
strokeWidth: 2,
|
|
32
|
-
branchColor: GRAY_COLOR,
|
|
33
|
-
branchWidth: 2
|
|
34
|
-
};
|
|
35
|
-
const DefaultNodeStyle = {
|
|
36
|
-
strokeWidth: 3,
|
|
37
|
-
branchWidth: 3,
|
|
38
|
-
fill: 'none'
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const TOPIC_COLOR = '#333';
|
|
42
|
-
const TOPIC_FONT_SIZE = 14;
|
|
43
|
-
const ROOT_TOPIC_FONT_SIZE = 18;
|
|
44
|
-
const TOPIC_DEFAULT_MAX_WORD_COUNT = 34;
|
|
45
|
-
|
|
46
|
-
const NODE_MIN_WIDTH = 18;
|
|
47
|
-
|
|
48
|
-
const ABSTRACT_HANDLE_COLOR = '#6698FF80'; //primary color 50% opacity
|
|
49
|
-
const ABSTRACT_INCLUDED_OUTLINE_OFFSET = 3.5;
|
|
50
|
-
const ABSTRACT_HANDLE_LENGTH = 10;
|
|
51
|
-
const ABSTRACT_HANDLE_MASK_WIDTH = 8;
|
|
52
|
-
|
|
53
17
|
const MindNode = {
|
|
54
18
|
get(root, path) {
|
|
55
19
|
let node = root;
|
|
@@ -215,36 +179,17 @@ const MindThemeColor = {
|
|
|
215
179
|
}
|
|
216
180
|
};
|
|
217
181
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
function getRectangleByElement(board, originPoint, element) {
|
|
231
|
-
const nodeRectangle = {
|
|
232
|
-
x: originPoint[0],
|
|
233
|
-
y: originPoint[1],
|
|
234
|
-
width: NodeSpace.getNodeWidth(board, element),
|
|
235
|
-
height: NodeSpace.getNodeHeight(board, element)
|
|
236
|
-
};
|
|
237
|
-
return nodeRectangle;
|
|
238
|
-
}
|
|
239
|
-
function isHitMindElement(board, point, element) {
|
|
240
|
-
const node = MindElement.getNode(element);
|
|
241
|
-
if (node && distanceBetweenPointAndRectangle(point[0], point[1], getRectangleByNode(node)) === 0) {
|
|
242
|
-
return true;
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
return false;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
182
|
+
const BASE = 4;
|
|
183
|
+
const PRIMARY_COLOR = '#6698FF';
|
|
184
|
+
const TRANSPARENT = 'transparent';
|
|
185
|
+
const GRAY_COLOR = '#AAAAAA';
|
|
186
|
+
const STROKE_WIDTH = 3;
|
|
187
|
+
const BRANCH_WIDTH = 3;
|
|
188
|
+
const EXTEND_OFFSET = 8;
|
|
189
|
+
const EXTEND_DIAMETER = 16;
|
|
190
|
+
const QUICK_INSERT_CIRCLE_OFFSET = 9;
|
|
191
|
+
const QUICK_INSERT_CIRCLE_COLOR = '#6698FF';
|
|
192
|
+
const QUICK_INSERT_INNER_CROSS_COLOR = 'white';
|
|
248
193
|
|
|
249
194
|
function getEmojisWidthHeight(board, element) {
|
|
250
195
|
const options = board.getMindOptions();
|
|
@@ -264,6 +209,79 @@ function getEmojiFontSize(element) {
|
|
|
264
209
|
}
|
|
265
210
|
}
|
|
266
211
|
|
|
212
|
+
const NodeDefaultSpace = {
|
|
213
|
+
horizontal: {
|
|
214
|
+
nodeAndText: BASE * 3,
|
|
215
|
+
emojiAndText: BASE * 1.5
|
|
216
|
+
},
|
|
217
|
+
vertical: {
|
|
218
|
+
nodeAndText: BASE * 1.5
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
const RootDefaultSpace = {
|
|
222
|
+
horizontal: {
|
|
223
|
+
nodeAndText: BASE * 4,
|
|
224
|
+
emojiAndText: BASE * 2
|
|
225
|
+
},
|
|
226
|
+
vertical: {
|
|
227
|
+
nodeAndText: BASE * 2
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
const getHorizontalSpaceBetweenNodeAndText = (board, element) => {
|
|
231
|
+
const isMind = PlaitMind.isMind(element);
|
|
232
|
+
const nodeAndText = isMind ? RootDefaultSpace.horizontal.nodeAndText : NodeDefaultSpace.horizontal.nodeAndText;
|
|
233
|
+
return nodeAndText;
|
|
234
|
+
};
|
|
235
|
+
const getVerticalSpaceBetweenNodeAndText = (element) => {
|
|
236
|
+
const isMind = PlaitMind.isMind(element);
|
|
237
|
+
const nodeAndText = isMind ? RootDefaultSpace.vertical.nodeAndText : NodeDefaultSpace.vertical.nodeAndText;
|
|
238
|
+
return nodeAndText;
|
|
239
|
+
};
|
|
240
|
+
const getSpaceEmojiAndText = (element) => {
|
|
241
|
+
const isMind = PlaitMind.isMind(element);
|
|
242
|
+
const emojiAndText = isMind ? RootDefaultSpace.horizontal.emojiAndText : NodeDefaultSpace.horizontal.emojiAndText;
|
|
243
|
+
return emojiAndText;
|
|
244
|
+
};
|
|
245
|
+
const NodeSpace = {
|
|
246
|
+
getNodeWidth(board, element) {
|
|
247
|
+
const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
|
|
248
|
+
if (MindElement.hasEmojis(element)) {
|
|
249
|
+
return (NodeSpace.getEmojiLeftSpace(board, element) +
|
|
250
|
+
getEmojisWidthHeight(board, element).width +
|
|
251
|
+
getSpaceEmojiAndText(element) +
|
|
252
|
+
element.width +
|
|
253
|
+
nodeAndText);
|
|
254
|
+
}
|
|
255
|
+
return nodeAndText + element.width + nodeAndText;
|
|
256
|
+
},
|
|
257
|
+
getNodeHeight(board, element) {
|
|
258
|
+
const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
|
|
259
|
+
return nodeAndText + element.height + nodeAndText;
|
|
260
|
+
},
|
|
261
|
+
getTextLeftSpace(board, element) {
|
|
262
|
+
const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
|
|
263
|
+
if (MindElement.hasEmojis(element)) {
|
|
264
|
+
return NodeSpace.getEmojiLeftSpace(board, element) + getEmojisWidthHeight(board, element).width + getSpaceEmojiAndText(element);
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
return nodeAndText;
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
getTextTopSpace(element) {
|
|
271
|
+
const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
|
|
272
|
+
return nodeAndText;
|
|
273
|
+
},
|
|
274
|
+
getEmojiLeftSpace(board, element) {
|
|
275
|
+
const options = board.getMindOptions();
|
|
276
|
+
const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
|
|
277
|
+
return nodeAndText - options.emojiPadding;
|
|
278
|
+
},
|
|
279
|
+
getEmojiTopSpace(element) {
|
|
280
|
+
const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
|
|
281
|
+
return nodeAndText;
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
|
|
267
285
|
function getEmojiRectangle(board, element) {
|
|
268
286
|
let { x, y } = getRectangleByNode(MindElement.getNode(element));
|
|
269
287
|
x = x + NodeSpace.getEmojiLeftSpace(board, element);
|
|
@@ -290,18 +308,38 @@ const isHitEmojis = (board, element, point) => {
|
|
|
290
308
|
return RectangleClient.isHit(RectangleClient.toRectangleClient([point, point]), getEmojiRectangle(board, element));
|
|
291
309
|
};
|
|
292
310
|
|
|
293
|
-
function
|
|
311
|
+
function getTopicRectangleByNode(board, node) {
|
|
312
|
+
let nodeRectangle = getRectangleByNode(node);
|
|
313
|
+
return getTopicRectangleByElement(board, nodeRectangle, node.origin);
|
|
314
|
+
}
|
|
315
|
+
function getTopicRectangleByElement(board, nodeRectangle, element) {
|
|
316
|
+
const x = nodeRectangle.x + NodeSpace.getTextLeftSpace(board, element);
|
|
317
|
+
const y = nodeRectangle.y + NodeSpace.getTextTopSpace(element);
|
|
318
|
+
const width = Math.ceil(element.width);
|
|
319
|
+
const height = Math.ceil(element.height);
|
|
320
|
+
return { height, width, x, y };
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const NODE_MIN_WIDTH = 18;
|
|
324
|
+
|
|
325
|
+
function editTopic(element) {
|
|
294
326
|
const component = PlaitElement.getComponent(element);
|
|
295
|
-
component.
|
|
327
|
+
component.editTopic();
|
|
296
328
|
}
|
|
297
329
|
|
|
330
|
+
const TOPIC_COLOR = '#333';
|
|
331
|
+
const TOPIC_FONT_SIZE = 14;
|
|
332
|
+
const ROOT_TOPIC_FONT_SIZE = 18;
|
|
333
|
+
const ROOT_TOPIC_HEIGHT = 25;
|
|
334
|
+
const TOPIC_DEFAULT_MAX_WORD_COUNT = 34;
|
|
335
|
+
|
|
298
336
|
const adjustRootToNode = (board, node) => {
|
|
299
337
|
const newNode = { ...node };
|
|
300
338
|
delete newNode.isRoot;
|
|
301
339
|
delete newNode.rightNodeCount;
|
|
302
340
|
delete newNode.type;
|
|
303
341
|
const text = Node.string(node.data.topic.children[0]) || ' ';
|
|
304
|
-
const { width, height } =
|
|
342
|
+
const { width, height } = getTextSize(board, text, TOPIC_DEFAULT_MAX_WORD_COUNT);
|
|
305
343
|
newNode.width = Math.max(width, NODE_MIN_WIDTH);
|
|
306
344
|
newNode.height = height;
|
|
307
345
|
if (newNode.layout === MindLayoutType.standard) {
|
|
@@ -326,7 +364,7 @@ const adjustNodeToRoot = (board, node) => {
|
|
|
326
364
|
delete newElement?.fill;
|
|
327
365
|
delete newElement?.shape;
|
|
328
366
|
delete newElement?.strokeWidth;
|
|
329
|
-
const { width, height } =
|
|
367
|
+
const { width, height } = getTextSize(board, text, TOPIC_DEFAULT_MAX_WORD_COUNT, ROOT_TOPIC_FONT_SIZE);
|
|
330
368
|
newElement.width = Math.max(width, NODE_MIN_WIDTH);
|
|
331
369
|
newElement.height = height;
|
|
332
370
|
return {
|
|
@@ -345,7 +383,7 @@ const createEmptyMind = (board, point) => {
|
|
|
345
383
|
return rootElement;
|
|
346
384
|
};
|
|
347
385
|
const createDefaultMind = (point, rightNodeCount, layout) => {
|
|
348
|
-
const root = createMindElement('思维导图', 72,
|
|
386
|
+
const root = createMindElement('思维导图', 72, ROOT_TOPIC_HEIGHT, { layout });
|
|
349
387
|
root.rightNodeCount = rightNodeCount;
|
|
350
388
|
root.isRoot = true;
|
|
351
389
|
root.type = 'mindmap';
|
|
@@ -452,7 +490,7 @@ const insertMindElement = (board, inheritNode, path) => {
|
|
|
452
490
|
clearSelectedElement(board);
|
|
453
491
|
addSelectedElement(board, newElement);
|
|
454
492
|
setTimeout(() => {
|
|
455
|
-
|
|
493
|
+
editTopic(newElement);
|
|
456
494
|
});
|
|
457
495
|
};
|
|
458
496
|
const findLastChild = (child) => {
|
|
@@ -582,6 +620,18 @@ const getRootLayout = (root) => {
|
|
|
582
620
|
return root.layout || getDefaultLayout();
|
|
583
621
|
};
|
|
584
622
|
|
|
623
|
+
const DefaultAbstractNodeStyle = {
|
|
624
|
+
strokeColor: GRAY_COLOR,
|
|
625
|
+
strokeWidth: 2,
|
|
626
|
+
branchColor: GRAY_COLOR,
|
|
627
|
+
branchWidth: 2
|
|
628
|
+
};
|
|
629
|
+
const DefaultNodeStyle = {
|
|
630
|
+
strokeWidth: 3,
|
|
631
|
+
branchWidth: 3,
|
|
632
|
+
fill: 'none'
|
|
633
|
+
};
|
|
634
|
+
|
|
585
635
|
const getAvailableProperty = (board, element, propertyKey) => {
|
|
586
636
|
return element[propertyKey];
|
|
587
637
|
};
|
|
@@ -684,6 +734,12 @@ const isDragging = (board) => {
|
|
|
684
734
|
};
|
|
685
735
|
const setIsDragging = (board, state) => {
|
|
686
736
|
IS_DRAGGING.set(board, state);
|
|
737
|
+
if (state) {
|
|
738
|
+
PlaitBoard.getBoardContainer(board).classList.add('mind-node-dragging');
|
|
739
|
+
}
|
|
740
|
+
else {
|
|
741
|
+
PlaitBoard.getBoardContainer(board).classList.remove('mind-node-dragging');
|
|
742
|
+
}
|
|
687
743
|
};
|
|
688
744
|
const hasPreviousOrNextOfDropPath = (parent, dropTarget, dropPath) => {
|
|
689
745
|
let children = getNonAbstractChildren(parent);
|
|
@@ -897,23 +953,10 @@ const getPathByDropTarget = (board, dropTarget) => {
|
|
|
897
953
|
return targetPath;
|
|
898
954
|
};
|
|
899
955
|
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
function drawRoundRectangleByElement(board, nodeRectangle, element) {
|
|
905
|
-
const defaultRootFill = getMindThemeColor(board).rootFill;
|
|
906
|
-
const fill = element.fill ? element.fill : element.isRoot ? defaultRootFill : DefaultNodeStyle.fill;
|
|
907
|
-
const stroke = getStrokeByMindElement(board, element);
|
|
908
|
-
const strokeWidth = element.strokeWidth ? element.strokeWidth : DefaultNodeStyle.strokeWidth;
|
|
909
|
-
const nodeG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), nodeRectangle.x, nodeRectangle.y, nodeRectangle.x + nodeRectangle.width, nodeRectangle.y + nodeRectangle.height, {
|
|
910
|
-
stroke,
|
|
911
|
-
strokeWidth,
|
|
912
|
-
fill,
|
|
913
|
-
fillStyle: 'solid'
|
|
914
|
-
});
|
|
915
|
-
return nodeG;
|
|
916
|
-
}
|
|
956
|
+
const ABSTRACT_HANDLE_COLOR = '#6698FF80'; //primary color 50% opacity
|
|
957
|
+
const ABSTRACT_INCLUDED_OUTLINE_OFFSET = 3.5;
|
|
958
|
+
const ABSTRACT_HANDLE_LENGTH = 10;
|
|
959
|
+
const ABSTRACT_HANDLE_MASK_WIDTH = 8;
|
|
917
960
|
|
|
918
961
|
var HorizontalPlacement;
|
|
919
962
|
(function (HorizontalPlacement) {
|
|
@@ -1171,13 +1214,13 @@ const drawFakeDragNode = (board, element, offsetX, offsetY) => {
|
|
|
1171
1214
|
};
|
|
1172
1215
|
const textRectangle = getTopicRectangleByNode(board, activeComponent.node);
|
|
1173
1216
|
const fakeNodeG = drawRoundRectangleByNode(board, fakeDraggingNode);
|
|
1174
|
-
const richtextG = activeComponent.
|
|
1217
|
+
const richtextG = activeComponent.textManage.g.cloneNode(true);
|
|
1175
1218
|
updateForeignObject(richtextG, textRectangle.width, textRectangle.height, textRectangle.x + offsetX, textRectangle.y + offsetY);
|
|
1176
1219
|
dragFakeNodeG?.append(fakeNodeG);
|
|
1177
1220
|
dragFakeNodeG?.append(richtextG);
|
|
1178
1221
|
// draw emojis
|
|
1179
1222
|
if (MindElement.hasEmojis(element)) {
|
|
1180
|
-
const fakeEmojisG = activeComponent.
|
|
1223
|
+
const fakeEmojisG = activeComponent.nodeEmojisDrawer.g.cloneNode(true);
|
|
1181
1224
|
const foreignRectangle = getEmojiForeignRectangle(board, element);
|
|
1182
1225
|
updateForeignObject(fakeEmojisG, foreignRectangle.width, foreignRectangle.height, foreignRectangle.x + offsetX, foreignRectangle.y + offsetY);
|
|
1183
1226
|
dragFakeNodeG?.append(fakeEmojisG);
|
|
@@ -1637,9 +1680,7 @@ function findLocationLeftIndex(board, parentChildren, location, isHorizontal) {
|
|
|
1637
1680
|
}
|
|
1638
1681
|
function handleTouchedAbstract(board, touchedAbstract, endPoint) {
|
|
1639
1682
|
let touchedHandle;
|
|
1640
|
-
const abstract = getSelectedElements(board)
|
|
1641
|
-
.filter(element => AbstractNode.isAbstract(element))
|
|
1642
|
-
.find(element => {
|
|
1683
|
+
const abstract = getSelectedElements(board).filter(element => AbstractNode.isAbstract(element)).find(element => {
|
|
1643
1684
|
touchedHandle = getHitAbstractHandle(board, element, endPoint);
|
|
1644
1685
|
return touchedHandle;
|
|
1645
1686
|
});
|
|
@@ -1648,13 +1689,13 @@ function handleTouchedAbstract(board, touchedAbstract, endPoint) {
|
|
|
1648
1689
|
}
|
|
1649
1690
|
if (touchedAbstract) {
|
|
1650
1691
|
const component = PlaitElement.getComponent(touchedAbstract);
|
|
1651
|
-
component.
|
|
1692
|
+
component.activeDrawer.updateAbstractOutline(touchedAbstract);
|
|
1652
1693
|
touchedAbstract = undefined;
|
|
1653
1694
|
}
|
|
1654
1695
|
if (abstract) {
|
|
1655
1696
|
touchedAbstract = abstract;
|
|
1656
1697
|
const component = PlaitElement.getComponent(touchedAbstract);
|
|
1657
|
-
component.
|
|
1698
|
+
component.activeDrawer.updateAbstractOutline(touchedAbstract, touchedHandle);
|
|
1658
1699
|
}
|
|
1659
1700
|
return touchedAbstract;
|
|
1660
1701
|
}
|
|
@@ -1879,6 +1920,9 @@ const MindElement = {
|
|
|
1879
1920
|
},
|
|
1880
1921
|
getEmojis(element) {
|
|
1881
1922
|
return element.data.emojis;
|
|
1923
|
+
},
|
|
1924
|
+
getEditor(element) {
|
|
1925
|
+
return PlaitElement.getComponent(element).textManage.componentRef.instance.editor;
|
|
1882
1926
|
}
|
|
1883
1927
|
};
|
|
1884
1928
|
var MindElementShape;
|
|
@@ -1892,118 +1936,53 @@ var BranchShape;
|
|
|
1892
1936
|
BranchShape["polyline"] = "polyline";
|
|
1893
1937
|
})(BranchShape || (BranchShape = {}));
|
|
1894
1938
|
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1939
|
+
function getRectangleByNode(node) {
|
|
1940
|
+
const x = node.x + node.hGap;
|
|
1941
|
+
let y = node.y + node.vGap;
|
|
1942
|
+
const width = node.width - node.hGap * 2;
|
|
1943
|
+
const height = node.height - node.vGap * 2;
|
|
1944
|
+
return {
|
|
1945
|
+
x,
|
|
1946
|
+
y,
|
|
1947
|
+
width,
|
|
1948
|
+
height
|
|
1949
|
+
};
|
|
1950
|
+
}
|
|
1951
|
+
function getRectangleByElement(board, originPoint, element) {
|
|
1952
|
+
const nodeRectangle = {
|
|
1953
|
+
x: originPoint[0],
|
|
1954
|
+
y: originPoint[1],
|
|
1955
|
+
width: NodeSpace.getNodeWidth(board, element),
|
|
1956
|
+
height: NodeSpace.getNodeHeight(board, element)
|
|
1957
|
+
};
|
|
1958
|
+
return nodeRectangle;
|
|
1959
|
+
}
|
|
1960
|
+
function isHitMindElement(board, point, element) {
|
|
1961
|
+
const node = MindElement.getNode(element);
|
|
1962
|
+
if (node && distanceBetweenPointAndRectangle(point[0], point[1], getRectangleByNode(node)) === 0) {
|
|
1963
|
+
return true;
|
|
1902
1964
|
}
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
horizontal: {
|
|
1906
|
-
nodeAndText: BASE * 4,
|
|
1907
|
-
emojiAndText: BASE * 2
|
|
1908
|
-
},
|
|
1909
|
-
vertical: {
|
|
1910
|
-
nodeAndText: BASE * 2
|
|
1965
|
+
else {
|
|
1966
|
+
return false;
|
|
1911
1967
|
}
|
|
1912
|
-
};
|
|
1913
|
-
const getHorizontalSpaceBetweenNodeAndText = (board, element) => {
|
|
1914
|
-
const isMind = PlaitMind.isMind(element);
|
|
1915
|
-
const nodeAndText = isMind ? RootDefaultSpace.horizontal.nodeAndText : NodeDefaultSpace.horizontal.nodeAndText;
|
|
1916
|
-
return nodeAndText;
|
|
1917
|
-
};
|
|
1918
|
-
const getVerticalSpaceBetweenNodeAndText = (element) => {
|
|
1919
|
-
const isMind = PlaitMind.isMind(element);
|
|
1920
|
-
const nodeAndText = isMind ? RootDefaultSpace.vertical.nodeAndText : NodeDefaultSpace.vertical.nodeAndText;
|
|
1921
|
-
return nodeAndText;
|
|
1922
|
-
};
|
|
1923
|
-
const getSpaceEmojiAndText = (element) => {
|
|
1924
|
-
const isMind = PlaitMind.isMind(element);
|
|
1925
|
-
const emojiAndText = isMind ? RootDefaultSpace.horizontal.emojiAndText : NodeDefaultSpace.horizontal.emojiAndText;
|
|
1926
|
-
return emojiAndText;
|
|
1927
|
-
};
|
|
1928
|
-
const NodeSpace = {
|
|
1929
|
-
getNodeWidth(board, element) {
|
|
1930
|
-
const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
|
|
1931
|
-
if (MindElement.hasEmojis(element)) {
|
|
1932
|
-
return (NodeSpace.getEmojiLeftSpace(board, element) +
|
|
1933
|
-
getEmojisWidthHeight(board, element).width +
|
|
1934
|
-
getSpaceEmojiAndText(element) +
|
|
1935
|
-
element.width +
|
|
1936
|
-
nodeAndText);
|
|
1937
|
-
}
|
|
1938
|
-
return nodeAndText + element.width + nodeAndText;
|
|
1939
|
-
},
|
|
1940
|
-
getNodeHeight(board, element) {
|
|
1941
|
-
const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
|
|
1942
|
-
return nodeAndText + element.height + nodeAndText;
|
|
1943
|
-
},
|
|
1944
|
-
getTextLeftSpace(board, element) {
|
|
1945
|
-
const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
|
|
1946
|
-
if (MindElement.hasEmojis(element)) {
|
|
1947
|
-
return NodeSpace.getEmojiLeftSpace(board, element) + getEmojisWidthHeight(board, element).width + getSpaceEmojiAndText(element);
|
|
1948
|
-
}
|
|
1949
|
-
else {
|
|
1950
|
-
return nodeAndText;
|
|
1951
|
-
}
|
|
1952
|
-
},
|
|
1953
|
-
getTextTopSpace(element) {
|
|
1954
|
-
const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
|
|
1955
|
-
return nodeAndText;
|
|
1956
|
-
},
|
|
1957
|
-
getEmojiLeftSpace(board, element) {
|
|
1958
|
-
const options = board.getMindOptions();
|
|
1959
|
-
const nodeAndText = getHorizontalSpaceBetweenNodeAndText(board, element);
|
|
1960
|
-
return nodeAndText - options.emojiPadding;
|
|
1961
|
-
},
|
|
1962
|
-
getEmojiTopSpace(element) {
|
|
1963
|
-
const nodeAndText = getVerticalSpaceBetweenNodeAndText(element);
|
|
1964
|
-
return nodeAndText;
|
|
1965
|
-
}
|
|
1966
|
-
};
|
|
1967
|
-
|
|
1968
|
-
function getTopicRectangleByNode(board, node) {
|
|
1969
|
-
let nodeRectangle = getRectangleByNode(node);
|
|
1970
|
-
return getTopicRectangleByElement(board, nodeRectangle, node.origin);
|
|
1971
|
-
}
|
|
1972
|
-
function getTopicRectangleByElement(board, nodeRectangle, element) {
|
|
1973
|
-
const x = nodeRectangle.x + NodeSpace.getTextLeftSpace(board, element);
|
|
1974
|
-
const y = nodeRectangle.y + NodeSpace.getTextTopSpace(element);
|
|
1975
|
-
const width = Math.ceil(element.width);
|
|
1976
|
-
const height = Math.ceil(element.height);
|
|
1977
|
-
return { height, width, x, y };
|
|
1978
1968
|
}
|
|
1979
1969
|
|
|
1980
|
-
function
|
|
1981
|
-
const rectangle =
|
|
1982
|
-
return
|
|
1983
|
-
}
|
|
1984
|
-
function drawTopicByElement(board, rectangle, element, viewContainerRef) {
|
|
1985
|
-
const containerRef = viewContainerRef || PlaitBoard.getComponent(board).viewContainerRef;
|
|
1986
|
-
const classList = [];
|
|
1987
|
-
if (element.isRoot) {
|
|
1988
|
-
classList.push('root-node');
|
|
1989
|
-
classList.push('font-size-18');
|
|
1990
|
-
}
|
|
1991
|
-
else {
|
|
1992
|
-
classList.push('child-node');
|
|
1993
|
-
}
|
|
1994
|
-
// COMPAT: last character can not show in safari browser
|
|
1995
|
-
return drawRichtext(rectangle.x, rectangle.y, rectangle.width, rectangle.height, element.data.topic, containerRef, classList);
|
|
1970
|
+
function drawRoundRectangleByNode(board, node) {
|
|
1971
|
+
const rectangle = getRectangleByNode(node);
|
|
1972
|
+
return drawRoundRectangleByElement(board, rectangle, node.origin);
|
|
1996
1973
|
}
|
|
1997
|
-
function
|
|
1998
|
-
const
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
1974
|
+
function drawRoundRectangleByElement(board, nodeRectangle, element) {
|
|
1975
|
+
const defaultRootFill = getMindThemeColor(board).rootFill;
|
|
1976
|
+
const fill = element.fill ? element.fill : element.isRoot ? defaultRootFill : DefaultNodeStyle.fill;
|
|
1977
|
+
const stroke = getStrokeByMindElement(board, element);
|
|
1978
|
+
const strokeWidth = element.strokeWidth ? element.strokeWidth : DefaultNodeStyle.strokeWidth;
|
|
1979
|
+
const nodeG = drawRoundRectangle(PlaitBoard.getRoughSVG(board), nodeRectangle.x, nodeRectangle.y, nodeRectangle.x + nodeRectangle.width, nodeRectangle.y + nodeRectangle.height, {
|
|
1980
|
+
stroke,
|
|
1981
|
+
strokeWidth,
|
|
1982
|
+
fill,
|
|
1983
|
+
fillStyle: 'solid'
|
|
1984
|
+
});
|
|
1985
|
+
return nodeG;
|
|
2007
1986
|
}
|
|
2008
1987
|
|
|
2009
1988
|
function drawAbstractLink(board, node, isHorizontal) {
|
|
@@ -2084,7 +2063,7 @@ class EmojiDrawer {
|
|
|
2084
2063
|
}
|
|
2085
2064
|
}
|
|
2086
2065
|
}
|
|
2087
|
-
class
|
|
2066
|
+
class NodeEmojisDrawer {
|
|
2088
2067
|
constructor(board, viewContainerRef) {
|
|
2089
2068
|
this.board = board;
|
|
2090
2069
|
this.viewContainerRef = viewContainerRef;
|
|
@@ -2210,11 +2189,15 @@ const correctLogicLayoutNode = (board, layout, path) => {
|
|
|
2210
2189
|
}
|
|
2211
2190
|
};
|
|
2212
2191
|
|
|
2192
|
+
const normalizeWidthAndHeight = (board, width, height) => {
|
|
2193
|
+
const newWidth = width < NODE_MIN_WIDTH * board.viewport.zoom ? NODE_MIN_WIDTH : width / board.viewport.zoom;
|
|
2194
|
+
const newHeight = height / board.viewport.zoom;
|
|
2195
|
+
return { width: newWidth, height: newHeight };
|
|
2196
|
+
};
|
|
2213
2197
|
const setTopic = (board, element, topic, width, height) => {
|
|
2214
2198
|
const newElement = {
|
|
2215
2199
|
data: { topic },
|
|
2216
|
-
|
|
2217
|
-
height: height / board.viewport.zoom
|
|
2200
|
+
...normalizeWidthAndHeight(board, width, height)
|
|
2218
2201
|
};
|
|
2219
2202
|
if (MindElement.hasEmojis(element)) {
|
|
2220
2203
|
newElement.data.emojis = element.data.emojis;
|
|
@@ -2224,11 +2207,10 @@ const setTopic = (board, element, topic, width, height) => {
|
|
|
2224
2207
|
};
|
|
2225
2208
|
const setTopicSize = (board, element, width, height) => {
|
|
2226
2209
|
const newElement = {
|
|
2227
|
-
|
|
2228
|
-
height: height / board.viewport.zoom
|
|
2210
|
+
...normalizeWidthAndHeight(board, width, height)
|
|
2229
2211
|
};
|
|
2230
|
-
|
|
2231
|
-
|
|
2212
|
+
if (element.width !== newElement.width || element.height !== newElement.height) {
|
|
2213
|
+
const path = PlaitBoard.findPath(board, element);
|
|
2232
2214
|
Transforms.setNode(board, newElement, path);
|
|
2233
2215
|
}
|
|
2234
2216
|
};
|
|
@@ -2327,75 +2309,22 @@ const MindTransforms = {
|
|
|
2327
2309
|
setRightNodeCountByRefs
|
|
2328
2310
|
};
|
|
2329
2311
|
|
|
2330
|
-
function drawAbstractIncludedOutline(board, roughSVG, element, activeHandlePosition, resizingLocation) {
|
|
2331
|
-
const abstractIncludedG = createG();
|
|
2332
|
-
const parentElement = MindElement.getParent(element);
|
|
2333
|
-
const nodeLayout = MindQueries.getCorrectLayoutByElement(board, element);
|
|
2334
|
-
const isHorizontal = isHorizontalLayout(nodeLayout);
|
|
2335
|
-
const includedElements = parentElement.children.slice(element.start, element.end + 1);
|
|
2336
|
-
let abstractRectangle = getRectangleByElements(board, includedElements, true);
|
|
2337
|
-
abstractRectangle = RectangleClient.getOutlineRectangle(abstractRectangle, -ABSTRACT_INCLUDED_OUTLINE_OFFSET);
|
|
2338
|
-
if (resizingLocation) {
|
|
2339
|
-
abstractRectangle = getRectangleByResizingLocation(abstractRectangle, resizingLocation, activeHandlePosition, isHorizontal);
|
|
2340
|
-
}
|
|
2341
|
-
const rectangle = drawAbstractRoundRectangle(roughSVG, abstractRectangle.x, abstractRectangle.y, abstractRectangle.x + abstractRectangle.width, abstractRectangle.y + abstractRectangle.height, isHorizontal, {
|
|
2342
|
-
stroke: PRIMARY_COLOR,
|
|
2343
|
-
strokeWidth: 1,
|
|
2344
|
-
fillStyle: 'solid'
|
|
2345
|
-
});
|
|
2346
|
-
const startPlacement = [HorizontalPlacement.center, VerticalPlacement.top];
|
|
2347
|
-
const endPlacement = [HorizontalPlacement.center, VerticalPlacement.bottom];
|
|
2348
|
-
const linkDirection = getLayoutDirection(MindElement.getNode(element), isHorizontal);
|
|
2349
|
-
transformPlacement(startPlacement, linkDirection);
|
|
2350
|
-
transformPlacement(endPlacement, linkDirection);
|
|
2351
|
-
let startCenterPoint = getPointByPlacement(abstractRectangle, startPlacement);
|
|
2352
|
-
let endCenterPoint = getPointByPlacement(abstractRectangle, endPlacement);
|
|
2353
|
-
const startPoint1 = moveXOfPoint(startCenterPoint, -ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
|
|
2354
|
-
const startPoint2 = moveXOfPoint(startCenterPoint, ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
|
|
2355
|
-
const endPoint1 = moveXOfPoint(endCenterPoint, -ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
|
|
2356
|
-
const endPoint2 = moveXOfPoint(endCenterPoint, ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
|
|
2357
|
-
const startHandle = roughSVG.line(startPoint1[0], startPoint1[1], startPoint2[0], startPoint2[1], getHandleOption(activeHandlePosition === AbstractHandlePosition.start));
|
|
2358
|
-
const endHandle = roughSVG.line(endPoint1[0], endPoint1[1], endPoint2[0], endPoint2[1], getHandleOption(activeHandlePosition === AbstractHandlePosition.end));
|
|
2359
|
-
changeBoardClass(board, activeHandlePosition, isHorizontal);
|
|
2360
|
-
startHandle.setAttribute('stroke-linecap', 'round');
|
|
2361
|
-
endHandle.setAttribute('stroke-linecap', 'round');
|
|
2362
|
-
abstractIncludedG.append(startHandle);
|
|
2363
|
-
abstractIncludedG.append(endHandle);
|
|
2364
|
-
abstractIncludedG.append(rectangle);
|
|
2365
|
-
return abstractIncludedG;
|
|
2366
|
-
}
|
|
2367
|
-
function getHandleOption(isHover) {
|
|
2368
|
-
return isHover
|
|
2369
|
-
? {
|
|
2370
|
-
stroke: PRIMARY_COLOR,
|
|
2371
|
-
strokeWidth: 4,
|
|
2372
|
-
fillStyle: 'solid'
|
|
2373
|
-
}
|
|
2374
|
-
: {
|
|
2375
|
-
stroke: ABSTRACT_HANDLE_COLOR,
|
|
2376
|
-
strokeWidth: 3,
|
|
2377
|
-
fillStyle: 'solid'
|
|
2378
|
-
};
|
|
2379
|
-
}
|
|
2380
|
-
function changeBoardClass(board, activeHandlePosition, isHorizontal) {
|
|
2381
|
-
if (activeHandlePosition) {
|
|
2382
|
-
if (isHorizontal) {
|
|
2383
|
-
PlaitBoard.getBoardNativeElement(board).classList.add('abstract-resizing-horizontal');
|
|
2384
|
-
}
|
|
2385
|
-
else {
|
|
2386
|
-
PlaitBoard.getBoardNativeElement(board).classList.add('abstract-resizing-vertical');
|
|
2387
|
-
}
|
|
2388
|
-
}
|
|
2389
|
-
else {
|
|
2390
|
-
PlaitBoard.getBoardNativeElement(board).classList.remove('abstract-resizing-horizontal');
|
|
2391
|
-
PlaitBoard.getBoardNativeElement(board).classList.remove('abstract-resizing-vertical');
|
|
2392
|
-
}
|
|
2393
|
-
}
|
|
2394
|
-
|
|
2395
2312
|
class BaseDrawer {
|
|
2396
2313
|
constructor(board) {
|
|
2397
2314
|
this.board = board;
|
|
2398
2315
|
}
|
|
2316
|
+
draw(element, parentG, data) {
|
|
2317
|
+
this.destroy();
|
|
2318
|
+
if (this.canDraw && this.canDraw(element, data)) {
|
|
2319
|
+
const g = this.baseDraw(element, data);
|
|
2320
|
+
if (g) {
|
|
2321
|
+
parentG.append(g);
|
|
2322
|
+
}
|
|
2323
|
+
if (hasAfterDraw(this)) {
|
|
2324
|
+
this.afterDraw(element);
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2399
2328
|
destroy() {
|
|
2400
2329
|
if (this.g) {
|
|
2401
2330
|
this.g.remove();
|
|
@@ -2418,14 +2347,14 @@ function findNewSiblingNodePath(board, element) {
|
|
|
2418
2347
|
return Path$1.next(path);
|
|
2419
2348
|
}
|
|
2420
2349
|
|
|
2421
|
-
class
|
|
2350
|
+
class NodeInsertDrawer extends BaseDrawer {
|
|
2422
2351
|
canDraw(element) {
|
|
2423
2352
|
if (PlaitBoard.isReadonly(this.board) || element?.isCollapsed) {
|
|
2424
2353
|
return false;
|
|
2425
2354
|
}
|
|
2426
2355
|
return true;
|
|
2427
2356
|
}
|
|
2428
|
-
|
|
2357
|
+
baseDraw(element) {
|
|
2429
2358
|
const quickInsertG = createG();
|
|
2430
2359
|
this.g = quickInsertG;
|
|
2431
2360
|
quickInsertG.classList.add('quick-insert');
|
|
@@ -2451,7 +2380,7 @@ class QuickInsertDrawer extends BaseDrawer {
|
|
|
2451
2380
|
}
|
|
2452
2381
|
let beginPoint = getPointByPlacement(nodeClient, placement);
|
|
2453
2382
|
if (element.children.length > 0 && !element.isRoot) {
|
|
2454
|
-
beginPoint = moveXOfPoint(beginPoint,
|
|
2383
|
+
beginPoint = moveXOfPoint(beginPoint, EXTEND_DIAMETER + 8, linkDirection);
|
|
2455
2384
|
distance = 5;
|
|
2456
2385
|
}
|
|
2457
2386
|
const endPoint = moveXOfPoint(beginPoint, distance, linkDirection);
|
|
@@ -2460,7 +2389,7 @@ class QuickInsertDrawer extends BaseDrawer {
|
|
|
2460
2389
|
stroke: branchColor,
|
|
2461
2390
|
strokeWidth: branchWidth
|
|
2462
2391
|
});
|
|
2463
|
-
const circle = PlaitBoard.getRoughSVG(this.board).circle(circleCenter[0], circleCenter[1],
|
|
2392
|
+
const circle = PlaitBoard.getRoughSVG(this.board).circle(circleCenter[0], circleCenter[1], EXTEND_DIAMETER, {
|
|
2464
2393
|
fill: QUICK_INSERT_CIRCLE_COLOR,
|
|
2465
2394
|
stroke: QUICK_INSERT_CIRCLE_COLOR,
|
|
2466
2395
|
fillStyle: 'solid'
|
|
@@ -2501,70 +2430,271 @@ class QuickInsertDrawer extends BaseDrawer {
|
|
|
2501
2430
|
}
|
|
2502
2431
|
}
|
|
2503
2432
|
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2433
|
+
function drawAbstractIncludedOutline(board, roughSVG, element, activeHandlePosition, resizingLocation) {
|
|
2434
|
+
const abstractIncludedG = createG();
|
|
2435
|
+
const parentElement = MindElement.getParent(element);
|
|
2436
|
+
const nodeLayout = MindQueries.getCorrectLayoutByElement(board, element);
|
|
2437
|
+
const isHorizontal = isHorizontalLayout(nodeLayout);
|
|
2438
|
+
const includedElements = parentElement.children.slice(element.start, element.end + 1);
|
|
2439
|
+
let abstractRectangle = getRectangleByElements(board, includedElements, true);
|
|
2440
|
+
abstractRectangle = RectangleClient.getOutlineRectangle(abstractRectangle, -ABSTRACT_INCLUDED_OUTLINE_OFFSET);
|
|
2441
|
+
if (resizingLocation) {
|
|
2442
|
+
abstractRectangle = getRectangleByResizingLocation(abstractRectangle, resizingLocation, activeHandlePosition, isHorizontal);
|
|
2443
|
+
}
|
|
2444
|
+
const rectangle = drawAbstractRoundRectangle(roughSVG, abstractRectangle.x, abstractRectangle.y, abstractRectangle.x + abstractRectangle.width, abstractRectangle.y + abstractRectangle.height, isHorizontal, {
|
|
2445
|
+
stroke: PRIMARY_COLOR,
|
|
2446
|
+
strokeWidth: 1,
|
|
2447
|
+
fillStyle: 'solid'
|
|
2448
|
+
});
|
|
2449
|
+
const startPlacement = [HorizontalPlacement.center, VerticalPlacement.top];
|
|
2450
|
+
const endPlacement = [HorizontalPlacement.center, VerticalPlacement.bottom];
|
|
2451
|
+
const linkDirection = getLayoutDirection(MindElement.getNode(element), isHorizontal);
|
|
2452
|
+
transformPlacement(startPlacement, linkDirection);
|
|
2453
|
+
transformPlacement(endPlacement, linkDirection);
|
|
2454
|
+
let startCenterPoint = getPointByPlacement(abstractRectangle, startPlacement);
|
|
2455
|
+
let endCenterPoint = getPointByPlacement(abstractRectangle, endPlacement);
|
|
2456
|
+
const startPoint1 = moveXOfPoint(startCenterPoint, -ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
|
|
2457
|
+
const startPoint2 = moveXOfPoint(startCenterPoint, ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
|
|
2458
|
+
const endPoint1 = moveXOfPoint(endCenterPoint, -ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
|
|
2459
|
+
const endPoint2 = moveXOfPoint(endCenterPoint, ABSTRACT_HANDLE_LENGTH / 2, linkDirection);
|
|
2460
|
+
const startHandle = roughSVG.line(startPoint1[0], startPoint1[1], startPoint2[0], startPoint2[1], getHandleOption(activeHandlePosition === AbstractHandlePosition.start));
|
|
2461
|
+
const endHandle = roughSVG.line(endPoint1[0], endPoint1[1], endPoint2[0], endPoint2[1], getHandleOption(activeHandlePosition === AbstractHandlePosition.end));
|
|
2462
|
+
handleBoardClass(board, activeHandlePosition, isHorizontal);
|
|
2463
|
+
startHandle.setAttribute('stroke-linecap', 'round');
|
|
2464
|
+
endHandle.setAttribute('stroke-linecap', 'round');
|
|
2465
|
+
abstractIncludedG.append(startHandle);
|
|
2466
|
+
abstractIncludedG.append(endHandle);
|
|
2467
|
+
abstractIncludedG.append(rectangle);
|
|
2468
|
+
return abstractIncludedG;
|
|
2469
|
+
}
|
|
2470
|
+
function getHandleOption(isHover) {
|
|
2471
|
+
return isHover
|
|
2472
|
+
? {
|
|
2473
|
+
stroke: PRIMARY_COLOR,
|
|
2474
|
+
strokeWidth: 4,
|
|
2475
|
+
fillStyle: 'solid'
|
|
2476
|
+
}
|
|
2477
|
+
: {
|
|
2478
|
+
stroke: ABSTRACT_HANDLE_COLOR,
|
|
2479
|
+
strokeWidth: 3,
|
|
2480
|
+
fillStyle: 'solid'
|
|
2481
|
+
};
|
|
2482
|
+
}
|
|
2483
|
+
function handleBoardClass(board, activeHandlePosition, isHorizontal) {
|
|
2484
|
+
if (activeHandlePosition) {
|
|
2485
|
+
if (isHorizontal) {
|
|
2486
|
+
PlaitBoard.getBoardContainer(board).classList.add('abstract-resizing-horizontal');
|
|
2487
|
+
}
|
|
2488
|
+
else {
|
|
2489
|
+
PlaitBoard.getBoardContainer(board).classList.add('abstract-resizing-vertical');
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
else {
|
|
2493
|
+
PlaitBoard.getBoardContainer(board).classList.remove('abstract-resizing-horizontal');
|
|
2494
|
+
PlaitBoard.getBoardContainer(board).classList.remove('abstract-resizing-vertical');
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
class NodeActiveDrawer extends BaseDrawer {
|
|
2499
|
+
canDraw(element, data) {
|
|
2500
|
+
if (data.selected) {
|
|
2501
|
+
return true;
|
|
2502
|
+
}
|
|
2503
|
+
else {
|
|
2504
|
+
return false;
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
baseDraw(element, data) {
|
|
2508
|
+
const activeG = createG();
|
|
2509
|
+
this.g = activeG;
|
|
2510
|
+
if (AbstractNode.isAbstract(element)) {
|
|
2511
|
+
this.abstractOutlineG = drawAbstractIncludedOutline(this.board, PlaitBoard.getRoughSVG(this.board), element);
|
|
2512
|
+
activeG.append(this.abstractOutlineG);
|
|
2513
|
+
}
|
|
2514
|
+
const node = MindElement.getNode(element);
|
|
2515
|
+
let { x, y, width, height } = getRectangleByNode(node);
|
|
2516
|
+
const strokeG = drawRoundRectangle(PlaitBoard.getRoughSVG(this.board), x - 2, y - 2, x + width + 2, y + height + 2, { stroke: PRIMARY_COLOR, strokeWidth: 2, fill: '' }, true);
|
|
2517
|
+
this.g.appendChild(strokeG);
|
|
2518
|
+
if (!data.isEditing) {
|
|
2519
|
+
const fillG = drawRoundRectangle(PlaitBoard.getRoughSVG(this.board), x - 2, y - 2, x + width + 2, y + height + 2, { stroke: PRIMARY_COLOR, fill: PRIMARY_COLOR, fillStyle: 'solid' }, true);
|
|
2520
|
+
fillG.style.opacity = '0.15';
|
|
2521
|
+
this.g.appendChild(fillG);
|
|
2522
|
+
}
|
|
2523
|
+
return activeG;
|
|
2524
|
+
}
|
|
2525
|
+
updateAbstractOutline(element, activeHandlePosition, resizingLocation) {
|
|
2526
|
+
if (this.abstractOutlineG) {
|
|
2527
|
+
this.abstractOutlineG.remove();
|
|
2528
|
+
}
|
|
2529
|
+
this.abstractOutlineG = drawAbstractIncludedOutline(this.board, PlaitBoard.getRoughSVG(this.board), element, activeHandlePosition, resizingLocation);
|
|
2530
|
+
this.g.append(this.abstractOutlineG);
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
class CollapseDrawer extends BaseDrawer {
|
|
2535
|
+
canDraw(element) {
|
|
2536
|
+
if (element.children.length && !PlaitMind.isMind(element)) {
|
|
2537
|
+
return true;
|
|
2538
|
+
}
|
|
2539
|
+
return false;
|
|
2507
2540
|
}
|
|
2508
|
-
|
|
2541
|
+
baseDraw(element) {
|
|
2542
|
+
const collapseG = createG();
|
|
2543
|
+
this.g = collapseG;
|
|
2544
|
+
collapseG.classList.add('collapse-container');
|
|
2545
|
+
const node = MindElement.getNode(element);
|
|
2546
|
+
const stroke = getBranchColorByMindElement(this.board, element);
|
|
2547
|
+
const branchWidth = getBranchWidthByMindElement(this.board, element);
|
|
2548
|
+
const layout = MindQueries.getLayoutByElement(element);
|
|
2549
|
+
const isUnderlineShape = getShapeByElement(this.board, element) === MindElementShape.underline;
|
|
2550
|
+
const isHorizontal = isHorizontalLayout(layout);
|
|
2551
|
+
const nodeClient = getRectangleByNode(node);
|
|
2552
|
+
let linkDirection = getLayoutDirection(node, isHorizontal);
|
|
2553
|
+
if (isIndentedLayout(layout)) {
|
|
2554
|
+
linkDirection = isTopLayout(layout) ? LayoutDirection.top : LayoutDirection.bottom;
|
|
2555
|
+
}
|
|
2556
|
+
let placement = [HorizontalPlacement.right, VerticalPlacement.middle];
|
|
2557
|
+
transformPlacement(placement, linkDirection);
|
|
2558
|
+
// underline shape and horizontal
|
|
2559
|
+
if (isHorizontal && isUnderlineShape && !element.isRoot) {
|
|
2560
|
+
placement[1] = VerticalPlacement.bottom;
|
|
2561
|
+
}
|
|
2562
|
+
let startPoint = getPointByPlacement(nodeClient, placement);
|
|
2563
|
+
const endPoint = moveXOfPoint(startPoint, EXTEND_OFFSET, linkDirection);
|
|
2564
|
+
const circleCenter = moveXOfPoint(endPoint, EXTEND_DIAMETER / 2, linkDirection);
|
|
2565
|
+
const arrowPoints = this.getArrowPoints(circleCenter, linkDirection);
|
|
2566
|
+
const arrowLine = drawLinearPath(arrowPoints, {
|
|
2567
|
+
stroke,
|
|
2568
|
+
strokeWidth: 2
|
|
2569
|
+
});
|
|
2570
|
+
const extendLine = PlaitBoard.getRoughSVG(this.board).line(startPoint[0], startPoint[1], endPoint[0], endPoint[1], {
|
|
2571
|
+
strokeWidth: branchWidth,
|
|
2572
|
+
stroke
|
|
2573
|
+
});
|
|
2574
|
+
const badge = PlaitBoard.getRoughSVG(this.board).circle(circleCenter[0], circleCenter[1], EXTEND_DIAMETER, {
|
|
2575
|
+
fill: stroke,
|
|
2576
|
+
stroke,
|
|
2577
|
+
fillStyle: 'solid'
|
|
2578
|
+
});
|
|
2579
|
+
const hideCircleG = PlaitBoard.getRoughSVG(this.board).circle(circleCenter[0], circleCenter[1], EXTEND_DIAMETER, {
|
|
2580
|
+
fill: '#fff',
|
|
2581
|
+
stroke,
|
|
2582
|
+
strokeWidth: branchWidth > 3 ? 3 : branchWidth,
|
|
2583
|
+
fillStyle: 'solid'
|
|
2584
|
+
});
|
|
2585
|
+
if (element.isCollapsed) {
|
|
2586
|
+
let numberOffset = 0;
|
|
2587
|
+
if (getChildrenCount(element) >= 10)
|
|
2588
|
+
numberOffset = -2;
|
|
2589
|
+
if (getChildrenCount(element) === 1)
|
|
2590
|
+
numberOffset = 1;
|
|
2591
|
+
const badgeText = createText(circleCenter[0] - 4 + numberOffset, circleCenter[1] + 4, stroke, `${getChildrenCount(element)}`);
|
|
2592
|
+
badge.setAttribute('style', 'opacity: 0.15');
|
|
2593
|
+
badgeText.setAttribute('style', 'font-size: 12px');
|
|
2594
|
+
collapseG.appendChild(badge);
|
|
2595
|
+
collapseG.appendChild(badgeText);
|
|
2596
|
+
collapseG.appendChild(extendLine);
|
|
2597
|
+
}
|
|
2598
|
+
else {
|
|
2599
|
+
collapseG.appendChild(hideCircleG);
|
|
2600
|
+
collapseG.appendChild(arrowLine);
|
|
2601
|
+
}
|
|
2602
|
+
collapseG.appendChild(extendLine);
|
|
2603
|
+
return collapseG;
|
|
2604
|
+
}
|
|
2605
|
+
afterDraw(element) {
|
|
2606
|
+
if (!this.g) {
|
|
2607
|
+
throw new Error(`can not find quick insert g`);
|
|
2608
|
+
}
|
|
2609
|
+
fromEvent(this.g, 'mouseup')
|
|
2610
|
+
.pipe(filter(() => !PlaitBoard.isPointer(this.board, PlaitPointerType.hand) || !!PlaitBoard.isReadonly(this.board)), take(1))
|
|
2611
|
+
.subscribe(() => {
|
|
2612
|
+
const isCollapsed = !element.isCollapsed;
|
|
2613
|
+
const newElement = { isCollapsed };
|
|
2614
|
+
const path = PlaitBoard.findPath(this.board, element);
|
|
2615
|
+
Transforms.setNode(this.board, newElement, path);
|
|
2616
|
+
});
|
|
2617
|
+
}
|
|
2618
|
+
getArrowPoints(circleCenter, linkDirection) {
|
|
2619
|
+
let arrowTopPoint = moveXOfPoint(circleCenter, 2, linkDirection);
|
|
2620
|
+
arrowTopPoint = moveYOfPoint(arrowTopPoint, 4, linkDirection);
|
|
2621
|
+
const arrowMiddlePoint = moveXOfPoint(circleCenter, -2, linkDirection);
|
|
2622
|
+
let arrowBottomPoint = moveXOfPoint(circleCenter, 2, linkDirection);
|
|
2623
|
+
arrowBottomPoint = moveYOfPoint(arrowBottomPoint, -4, linkDirection);
|
|
2624
|
+
return [arrowTopPoint, arrowMiddlePoint, arrowBottomPoint];
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2628
|
+
class MindNodeComponent extends PlaitPluginElementComponent {
|
|
2629
|
+
constructor(viewContainerRef, cdr) {
|
|
2509
2630
|
super(cdr);
|
|
2510
2631
|
this.viewContainerRef = viewContainerRef;
|
|
2511
2632
|
this.cdr = cdr;
|
|
2512
|
-
this.render2 = render2;
|
|
2513
|
-
this.ngZone = ngZone;
|
|
2514
|
-
this.isEditable = false;
|
|
2515
|
-
this.activeG = [];
|
|
2516
2633
|
this.shapeG = null;
|
|
2517
2634
|
this.destroy$ = new Subject();
|
|
2518
2635
|
this.trackBy = (index, node) => {
|
|
2519
2636
|
return node.origin.id;
|
|
2520
2637
|
};
|
|
2521
2638
|
}
|
|
2639
|
+
initializeDrawer() {
|
|
2640
|
+
this.nodeEmojisDrawer = new NodeEmojisDrawer(this.board, this.viewContainerRef);
|
|
2641
|
+
this.nodeInsertDrawer = new NodeInsertDrawer(this.board);
|
|
2642
|
+
this.activeDrawer = new NodeActiveDrawer(this.board);
|
|
2643
|
+
this.collapseDrawer = new CollapseDrawer(this.board);
|
|
2644
|
+
this.textManage = new TextManage(this.board, this.viewContainerRef, () => {
|
|
2645
|
+
return getTopicRectangleByNode(this.board, this.node);
|
|
2646
|
+
}, (point) => {
|
|
2647
|
+
return isHitMindElement(this.board, point, this.element);
|
|
2648
|
+
}, (textManageRef) => {
|
|
2649
|
+
const width = textManageRef.width;
|
|
2650
|
+
const height = textManageRef.height;
|
|
2651
|
+
if (textManageRef.newValue) {
|
|
2652
|
+
MindTransforms.setTopic(this.board, this.element, textManageRef.newValue, width, height);
|
|
2653
|
+
}
|
|
2654
|
+
else {
|
|
2655
|
+
MindTransforms.setTopicSize(this.board, this.element, width, height);
|
|
2656
|
+
}
|
|
2657
|
+
});
|
|
2658
|
+
}
|
|
2522
2659
|
ngOnInit() {
|
|
2523
|
-
this.emojisDrawer = new EmojisDrawer(this.board, this.viewContainerRef);
|
|
2524
|
-
this.quickInsertDrawer = new QuickInsertDrawer(this.board);
|
|
2525
2660
|
super.ngOnInit();
|
|
2661
|
+
this.initializeDrawer();
|
|
2526
2662
|
this.node = MindElement.getNode(this.element);
|
|
2527
2663
|
this.index = NODE_TO_INDEX.get(this.element) || 0;
|
|
2528
2664
|
this.roughSVG = PlaitBoard.getRoughSVG(this.board);
|
|
2529
2665
|
this.parentG = PlaitElement.getComponent(MindElement.getRoot(this.board, this.element)).rootG;
|
|
2530
2666
|
this.drawShape();
|
|
2531
2667
|
this.drawLink();
|
|
2532
|
-
this.
|
|
2533
|
-
this.
|
|
2534
|
-
this.updateActiveClass();
|
|
2535
|
-
this.drawMaskG();
|
|
2668
|
+
this.drawText();
|
|
2669
|
+
this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: this.textManage.isEditing });
|
|
2536
2670
|
this.drawEmojis();
|
|
2537
2671
|
this.drawExtend();
|
|
2538
|
-
|
|
2672
|
+
}
|
|
2673
|
+
editTopic() {
|
|
2674
|
+
this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: true });
|
|
2675
|
+
this.textManage.edit(() => {
|
|
2676
|
+
this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: false });
|
|
2677
|
+
});
|
|
2539
2678
|
}
|
|
2540
2679
|
onContextChanged(value, previous) {
|
|
2541
2680
|
const newNode = MindElement.getNode(value.element);
|
|
2542
|
-
// resolve move node richtext lose issue
|
|
2543
|
-
if (this.node !== newNode) {
|
|
2544
|
-
if (this.foreignObject && this.foreignObject.children.length <= 0) {
|
|
2545
|
-
this.foreignObject?.appendChild(this.richtextComponentRef?.instance.editable);
|
|
2546
|
-
}
|
|
2547
|
-
}
|
|
2548
2681
|
const isEqualNode = RectangleClient.isEqual(this.node, newNode);
|
|
2549
2682
|
this.node = newNode;
|
|
2550
2683
|
const isChangeTheme = this.board.operations.find(op => op.type === 'set_theme');
|
|
2551
2684
|
if (!isEqualNode || value.element !== previous.element || isChangeTheme) {
|
|
2552
|
-
this.
|
|
2553
|
-
this.updateActiveClass();
|
|
2685
|
+
this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: this.textManage.isEditing });
|
|
2554
2686
|
this.drawShape();
|
|
2555
2687
|
this.drawLink();
|
|
2556
|
-
this.updateRichtext();
|
|
2557
|
-
this.drawMaskG();
|
|
2558
|
-
this.drawExtend();
|
|
2559
|
-
this.drawQuickInsert();
|
|
2560
2688
|
this.drawEmojis();
|
|
2689
|
+
this.drawExtend();
|
|
2690
|
+
this.textManage.updateText(this.element.data.topic);
|
|
2691
|
+
this.textManage.updateRectangle();
|
|
2561
2692
|
}
|
|
2562
2693
|
else {
|
|
2563
2694
|
const hasSameSelected = value.selected === previous.selected;
|
|
2564
2695
|
const hasSameParent = value.parent === previous.parent;
|
|
2565
2696
|
if (!hasSameSelected) {
|
|
2566
|
-
this.
|
|
2567
|
-
this.updateActiveClass();
|
|
2697
|
+
this.activeDrawer.draw(this.element, this.g, { selected: this.selected, isEditing: this.textManage.isEditing });
|
|
2568
2698
|
}
|
|
2569
2699
|
if (!hasSameParent) {
|
|
2570
2700
|
this.drawLink();
|
|
@@ -2572,21 +2702,11 @@ class MindNodeComponent extends PlaitPluginElementComponent {
|
|
|
2572
2702
|
}
|
|
2573
2703
|
}
|
|
2574
2704
|
drawEmojis() {
|
|
2575
|
-
const g = this.
|
|
2705
|
+
const g = this.nodeEmojisDrawer.drawEmojis(this.element);
|
|
2576
2706
|
if (g) {
|
|
2577
2707
|
this.g.append(g);
|
|
2578
2708
|
}
|
|
2579
2709
|
}
|
|
2580
|
-
drawQuickInsert() {
|
|
2581
|
-
this.quickInsertDrawer.destroy();
|
|
2582
|
-
if (this.quickInsertDrawer.canDraw(this.element)) {
|
|
2583
|
-
const g = this.quickInsertDrawer.draw(this.element);
|
|
2584
|
-
if (hasAfterDraw(this.quickInsertDrawer)) {
|
|
2585
|
-
this.quickInsertDrawer.afterDraw(this.element);
|
|
2586
|
-
}
|
|
2587
|
-
this.extendG?.appendChild(g);
|
|
2588
|
-
}
|
|
2589
|
-
}
|
|
2590
2710
|
drawShape() {
|
|
2591
2711
|
this.destroyShape();
|
|
2592
2712
|
const shape = getShapeByElement(this.board, this.node.origin);
|
|
@@ -2628,389 +2748,33 @@ class MindNodeComponent extends PlaitPluginElementComponent {
|
|
|
2628
2748
|
this.linkG.remove();
|
|
2629
2749
|
}
|
|
2630
2750
|
}
|
|
2631
|
-
drawMaskG() {
|
|
2632
|
-
this.destroyMaskG();
|
|
2633
|
-
const lineWidthOffset = 2;
|
|
2634
|
-
const extendOffset = 15;
|
|
2635
|
-
const nodeLayout = MindQueries.getLayoutByElement(this.node.origin);
|
|
2636
|
-
const isTop = isTopLayout(nodeLayout);
|
|
2637
|
-
const isRight = isRightLayout(nodeLayout);
|
|
2638
|
-
const isBottom = isBottomLayout(nodeLayout);
|
|
2639
|
-
const isLeft = isLeftLayout(nodeLayout);
|
|
2640
|
-
const { x, y, width, height } = getRectangleByNode(this.node);
|
|
2641
|
-
let drawX = x;
|
|
2642
|
-
let drawY = y;
|
|
2643
|
-
let drawWidth = x + width;
|
|
2644
|
-
let drawHeight = y + height;
|
|
2645
|
-
switch (true) {
|
|
2646
|
-
case isTop:
|
|
2647
|
-
drawX = x - lineWidthOffset;
|
|
2648
|
-
drawY = y - extendOffset;
|
|
2649
|
-
drawWidth = x + width + lineWidthOffset;
|
|
2650
|
-
drawHeight = y + height + lineWidthOffset;
|
|
2651
|
-
break;
|
|
2652
|
-
case isBottom:
|
|
2653
|
-
drawX = x - lineWidthOffset;
|
|
2654
|
-
drawY = y - lineWidthOffset;
|
|
2655
|
-
drawWidth = x + width + lineWidthOffset;
|
|
2656
|
-
drawHeight = y + height + extendOffset;
|
|
2657
|
-
break;
|
|
2658
|
-
case isLeft:
|
|
2659
|
-
drawX = x - extendOffset;
|
|
2660
|
-
drawY = y - lineWidthOffset;
|
|
2661
|
-
drawWidth = x + width + lineWidthOffset;
|
|
2662
|
-
drawHeight = y + height + lineWidthOffset;
|
|
2663
|
-
break;
|
|
2664
|
-
case isRight:
|
|
2665
|
-
drawX = x - lineWidthOffset;
|
|
2666
|
-
drawY = y - lineWidthOffset;
|
|
2667
|
-
drawWidth = x + width + extendOffset;
|
|
2668
|
-
drawHeight = y + height + lineWidthOffset;
|
|
2669
|
-
break;
|
|
2670
|
-
}
|
|
2671
|
-
this.maskG = drawRoundRectangle(this.roughSVG, drawX, drawY, drawWidth, drawHeight, { stroke: 'none', fill: 'rgba(255,255,255,0)', fillStyle: 'solid' }, true);
|
|
2672
|
-
this.maskG.classList.add('mask');
|
|
2673
|
-
this.maskG.setAttribute('visibility', 'visible');
|
|
2674
|
-
this.g.append(this.maskG);
|
|
2675
|
-
if (this.isEditable) {
|
|
2676
|
-
this.disabledMaskG();
|
|
2677
|
-
}
|
|
2678
|
-
fromEvent(this.maskG, 'mouseenter')
|
|
2679
|
-
.pipe(takeUntil(this.destroy$), filter(() => {
|
|
2680
|
-
return PlaitBoard.isFocus(this.board) && !this.element.isCollapsed && !this.handActive;
|
|
2681
|
-
}))
|
|
2682
|
-
.subscribe(() => {
|
|
2683
|
-
this.g.classList.add('hovered');
|
|
2684
|
-
});
|
|
2685
|
-
fromEvent(this.maskG, 'mouseleave')
|
|
2686
|
-
.pipe(takeUntil(this.destroy$), filter(() => {
|
|
2687
|
-
return PlaitBoard.isFocus(this.board) && !this.element.isCollapsed;
|
|
2688
|
-
}))
|
|
2689
|
-
.subscribe(() => {
|
|
2690
|
-
this.g.classList.remove('hovered');
|
|
2691
|
-
});
|
|
2692
|
-
}
|
|
2693
|
-
destroyMaskG() {
|
|
2694
|
-
if (this.maskG) {
|
|
2695
|
-
this.maskG.remove();
|
|
2696
|
-
this.g.classList.remove('hovered');
|
|
2697
|
-
}
|
|
2698
|
-
}
|
|
2699
|
-
enableMaskG() {
|
|
2700
|
-
if (this.maskG) {
|
|
2701
|
-
this.maskG.setAttribute('visibility', 'visible');
|
|
2702
|
-
}
|
|
2703
|
-
}
|
|
2704
|
-
disabledMaskG() {
|
|
2705
|
-
if (this.maskG) {
|
|
2706
|
-
this.maskG.setAttribute('visibility', 'hidden');
|
|
2707
|
-
}
|
|
2708
|
-
}
|
|
2709
|
-
drawActiveG() {
|
|
2710
|
-
this.destroyActiveG();
|
|
2711
|
-
this.abstractIncludedOutlineG?.remove();
|
|
2712
|
-
if (this.selected) {
|
|
2713
|
-
if (AbstractNode.isAbstract(this.element)) {
|
|
2714
|
-
this.updateAbstractIncludedOutline();
|
|
2715
|
-
}
|
|
2716
|
-
let { x, y, width, height } = getRectangleByNode(this.node);
|
|
2717
|
-
const selectedStrokeG = drawRoundRectangle(this.roughSVG, x - 2, y - 2, x + width + 2, y + height + 2, { stroke: PRIMARY_COLOR, strokeWidth: 2, fill: '' }, true);
|
|
2718
|
-
// 影响 mask 移入移出事件
|
|
2719
|
-
selectedStrokeG.style.pointerEvents = 'none';
|
|
2720
|
-
this.g.appendChild(selectedStrokeG);
|
|
2721
|
-
this.activeG.push(selectedStrokeG);
|
|
2722
|
-
if (this.richtextComponentRef?.instance.plaitReadonly === true) {
|
|
2723
|
-
const selectedBackgroundG = drawRoundRectangle(this.roughSVG, x - 2, y - 2, x + width + 2, y + height + 2, { stroke: PRIMARY_COLOR, fill: PRIMARY_COLOR, fillStyle: 'solid' }, true);
|
|
2724
|
-
selectedBackgroundG.style.opacity = '0.15';
|
|
2725
|
-
// 影响双击事件
|
|
2726
|
-
selectedBackgroundG.style.pointerEvents = 'none';
|
|
2727
|
-
this.g.appendChild(selectedBackgroundG);
|
|
2728
|
-
this.activeG.push(selectedBackgroundG, selectedStrokeG);
|
|
2729
|
-
}
|
|
2730
|
-
}
|
|
2731
|
-
}
|
|
2732
|
-
destroyActiveG() {
|
|
2733
|
-
this.activeG.forEach(g => g.remove());
|
|
2734
|
-
this.activeG = [];
|
|
2735
|
-
}
|
|
2736
|
-
updateActiveClass() {
|
|
2737
|
-
if (!this.g) {
|
|
2738
|
-
return;
|
|
2739
|
-
}
|
|
2740
|
-
if (this.selected) {
|
|
2741
|
-
this.render2.addClass(this.g, 'active');
|
|
2742
|
-
}
|
|
2743
|
-
else {
|
|
2744
|
-
this.render2.removeClass(this.g, 'active');
|
|
2745
|
-
}
|
|
2746
|
-
}
|
|
2747
|
-
drawRichtext() {
|
|
2748
|
-
const { richtextG, richtextComponentRef, foreignObject } = drawTopicByNode(this.board, this.node, this.viewContainerRef);
|
|
2749
|
-
this.richtextComponentRef = richtextComponentRef;
|
|
2750
|
-
this.richtextG = richtextG;
|
|
2751
|
-
this.foreignObject = foreignObject;
|
|
2752
|
-
this.render2.addClass(richtextG, 'richtext');
|
|
2753
|
-
this.g.append(richtextG);
|
|
2754
|
-
}
|
|
2755
2751
|
drawExtend() {
|
|
2756
2752
|
this.destroyExtend();
|
|
2757
|
-
// create extend
|
|
2758
2753
|
this.extendG = createG();
|
|
2759
|
-
const collapseG = createG();
|
|
2760
2754
|
this.extendG.classList.add('extend');
|
|
2761
|
-
collapseG.classList.add('collapse-container');
|
|
2762
2755
|
this.g.append(this.extendG);
|
|
2763
|
-
this.
|
|
2764
|
-
if (this.node.origin.isRoot) {
|
|
2765
|
-
return;
|
|
2766
|
-
}
|
|
2767
|
-
// interactive
|
|
2768
|
-
fromEvent(collapseG, 'mouseup')
|
|
2769
|
-
.pipe(filter(() => !this.handActive || !!PlaitBoard.isReadonly(this.board)), take(1))
|
|
2770
|
-
.subscribe(() => {
|
|
2771
|
-
const isCollapsed = !this.node.origin.isCollapsed;
|
|
2772
|
-
const newElement = { isCollapsed };
|
|
2773
|
-
const path = PlaitBoard.findPath(this.board, this.element);
|
|
2774
|
-
Transforms.setNode(this.board, newElement, path);
|
|
2775
|
-
});
|
|
2776
|
-
const { x, y, width, height } = getRectangleByNode(this.node);
|
|
2777
|
-
const stroke = getBranchColorByMindElement(this.board, this.element);
|
|
2778
|
-
const branchWidth = getBranchWidthByMindElement(this.board, this.element);
|
|
2779
|
-
const extendY = y + height / 2;
|
|
2780
|
-
const nodeLayout = MindQueries.getCorrectLayoutByElement(this.board, this.element);
|
|
2781
|
-
let extendLineXY = [
|
|
2782
|
-
[x + width, extendY],
|
|
2783
|
-
[x + width + EXTEND_OFFSET, extendY]
|
|
2784
|
-
];
|
|
2785
|
-
let arrowYOffset = [-4, 1, -0.6, 4];
|
|
2786
|
-
let arrowXOffset = [10, 5.5, 5.5, 10];
|
|
2787
|
-
let extendLineXOffset = [0, 0];
|
|
2788
|
-
let extendLineYOffset = [0, 0];
|
|
2789
|
-
let circleOffset = [EXTEND_RADIUS / 2, 0];
|
|
2790
|
-
if (isHorizontalLayout(nodeLayout) && !isIndentedLayout(nodeLayout)) {
|
|
2791
|
-
extendLineYOffset =
|
|
2792
|
-
getShapeByElement(this.board, this.node.origin) === MindElementShape.roundRectangle
|
|
2793
|
-
? [0, 0]
|
|
2794
|
-
: [height / 2, height / 2];
|
|
2795
|
-
if (isLeftLayout(nodeLayout)) {
|
|
2796
|
-
//左
|
|
2797
|
-
extendLineXOffset = [-width, -width - EXTEND_OFFSET * 2];
|
|
2798
|
-
circleOffset = [-EXTEND_RADIUS / 2, 0];
|
|
2799
|
-
arrowXOffset = [-10, -5.5, -5.5, -10];
|
|
2800
|
-
}
|
|
2801
|
-
}
|
|
2802
|
-
else {
|
|
2803
|
-
arrowXOffset = [-4, 0.6, -1, 4];
|
|
2804
|
-
if (isTopLayout(nodeLayout)) {
|
|
2805
|
-
//上
|
|
2806
|
-
extendLineXOffset = [-width / 2, -width / 2 - EXTEND_OFFSET];
|
|
2807
|
-
extendLineYOffset = [-height / 2, -height / 2 - EXTEND_OFFSET];
|
|
2808
|
-
arrowYOffset = [-10, -5.5, -5.5, -10];
|
|
2809
|
-
circleOffset = [0, -EXTEND_RADIUS / 2];
|
|
2810
|
-
}
|
|
2811
|
-
else {
|
|
2812
|
-
//下
|
|
2813
|
-
extendLineXOffset = [-width / 2, -width / 2 - EXTEND_OFFSET];
|
|
2814
|
-
extendLineYOffset = [height / 2, height / 2 + EXTEND_OFFSET];
|
|
2815
|
-
arrowYOffset = [10, 5.5, 5.5, 10];
|
|
2816
|
-
circleOffset = [0, EXTEND_RADIUS / 2];
|
|
2817
|
-
}
|
|
2818
|
-
}
|
|
2819
|
-
extendLineXY = [
|
|
2820
|
-
[extendLineXY[0][0] + extendLineXOffset[0], extendLineXY[0][1] + extendLineYOffset[0]],
|
|
2821
|
-
[extendLineXY[1][0] + extendLineXOffset[1], extendLineXY[1][1] + extendLineYOffset[1]]
|
|
2822
|
-
];
|
|
2823
|
-
const extendLine = this.roughSVG.line(extendLineXY[0][0], extendLineXY[0][1], extendLineXY[1][0], extendLineXY[1][1], {
|
|
2824
|
-
strokeWidth: branchWidth,
|
|
2825
|
-
stroke
|
|
2826
|
-
});
|
|
2827
|
-
//绘制箭头
|
|
2828
|
-
const hideArrowTopLine = this.roughSVG.line(extendLineXY[1][0] + arrowXOffset[0], extendLineXY[1][1] + arrowYOffset[0], extendLineXY[1][0] + arrowXOffset[1], extendLineXY[1][1] + arrowYOffset[1], {
|
|
2829
|
-
stroke,
|
|
2830
|
-
strokeWidth: 2
|
|
2831
|
-
});
|
|
2832
|
-
const hideArrowBottomLine = this.roughSVG.line(extendLineXY[1][0] + arrowXOffset[2], extendLineXY[1][1] + arrowYOffset[2], extendLineXY[1][0] + arrowXOffset[3], extendLineXY[1][1] + arrowYOffset[3], {
|
|
2833
|
-
stroke,
|
|
2834
|
-
strokeWidth: 2
|
|
2835
|
-
});
|
|
2836
|
-
if (this.node.origin.isCollapsed) {
|
|
2837
|
-
const badge = this.roughSVG.circle(extendLineXY[1][0] + circleOffset[0], extendLineXY[1][1] + circleOffset[1], EXTEND_RADIUS, {
|
|
2838
|
-
fill: stroke,
|
|
2839
|
-
stroke,
|
|
2840
|
-
fillStyle: 'solid'
|
|
2841
|
-
});
|
|
2842
|
-
let numberOffset = 0;
|
|
2843
|
-
if (getChildrenCount(this.node.origin) >= 10)
|
|
2844
|
-
numberOffset = -2;
|
|
2845
|
-
if (getChildrenCount(this.node.origin) === 1)
|
|
2846
|
-
numberOffset = 1;
|
|
2847
|
-
const badgeText = createText(extendLineXY[1][0] + circleOffset[0] - 4 + numberOffset, extendLineXY[1][1] + circleOffset[1] + 4, stroke, `${getChildrenCount(this.node.origin)}`);
|
|
2756
|
+
if (this.element.isCollapsed) {
|
|
2848
2757
|
this.g.classList.add('collapsed');
|
|
2849
|
-
badge.setAttribute('style', 'opacity: 0.15');
|
|
2850
|
-
badgeText.setAttribute('style', 'font-size: 12px');
|
|
2851
|
-
collapseG.appendChild(badge);
|
|
2852
|
-
collapseG.appendChild(badgeText);
|
|
2853
|
-
collapseG.appendChild(extendLine);
|
|
2854
2758
|
}
|
|
2855
2759
|
else {
|
|
2856
2760
|
this.g.classList.remove('collapsed');
|
|
2857
|
-
if (this.node.origin.children.length > 0) {
|
|
2858
|
-
const hideCircleG = this.roughSVG.circle(extendLineXY[1][0] + circleOffset[0], extendLineXY[1][1] + circleOffset[1], EXTEND_RADIUS - 1, {
|
|
2859
|
-
fill: '#fff',
|
|
2860
|
-
stroke,
|
|
2861
|
-
strokeWidth: branchWidth > 3 ? 3 : branchWidth,
|
|
2862
|
-
fillStyle: 'solid'
|
|
2863
|
-
});
|
|
2864
|
-
collapseG.appendChild(hideCircleG);
|
|
2865
|
-
collapseG.appendChild(hideArrowTopLine);
|
|
2866
|
-
collapseG.appendChild(hideArrowBottomLine);
|
|
2867
|
-
}
|
|
2868
2761
|
}
|
|
2762
|
+
this.nodeInsertDrawer.draw(this.element, this.extendG);
|
|
2763
|
+
this.collapseDrawer.draw(this.element, this.extendG);
|
|
2869
2764
|
}
|
|
2870
2765
|
destroyExtend() {
|
|
2871
2766
|
if (this.extendG) {
|
|
2872
2767
|
this.extendG.remove();
|
|
2873
2768
|
}
|
|
2874
2769
|
}
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
}
|
|
2879
|
-
if (this.richtextComponentRef) {
|
|
2880
|
-
this.richtextComponentRef.destroy();
|
|
2881
|
-
}
|
|
2882
|
-
}
|
|
2883
|
-
updateAbstractIncludedOutline(activeHandlePosition, resizingLocation) {
|
|
2884
|
-
this.abstractIncludedOutlineG?.remove();
|
|
2885
|
-
this.abstractIncludedOutlineG = drawAbstractIncludedOutline(this.board, this.roughSVG, this.element, activeHandlePosition, resizingLocation);
|
|
2886
|
-
PlaitBoard.getHost(this.board).append(this.abstractIncludedOutlineG);
|
|
2887
|
-
}
|
|
2888
|
-
updateRichtext() {
|
|
2889
|
-
updateRichText(this.node.origin.data.topic, this.richtextComponentRef);
|
|
2890
|
-
updateMindNodeTopicSize(this.board, this.node, this.richtextG, this.isEditable);
|
|
2891
|
-
}
|
|
2892
|
-
startEditText(isEnd, isClear) {
|
|
2893
|
-
if (!this.richtextComponentRef) {
|
|
2894
|
-
throw new Error('undefined richtextComponentRef');
|
|
2895
|
-
}
|
|
2896
|
-
const richtextInstance = this.richtextComponentRef.instance;
|
|
2897
|
-
this.isEditable = true;
|
|
2898
|
-
IS_TEXT_EDITABLE.set(this.board, true);
|
|
2899
|
-
this.disabledMaskG();
|
|
2900
|
-
updateMindNodeTopicSize(this.board, this.node, this.richtextG, this.isEditable);
|
|
2901
|
-
if (richtextInstance.plaitReadonly) {
|
|
2902
|
-
richtextInstance.plaitReadonly = false;
|
|
2903
|
-
this.richtextComponentRef.changeDetectorRef.detectChanges();
|
|
2904
|
-
this.drawActiveG();
|
|
2905
|
-
const location = isEnd ? Editor.end(richtextInstance.editor, [0]) : [0];
|
|
2906
|
-
setFullSelectionAndFocus(richtextInstance.editor, location);
|
|
2907
|
-
if (isClear) {
|
|
2908
|
-
Editor.deleteBackward(richtextInstance.editor);
|
|
2909
|
-
}
|
|
2910
|
-
// handle invalid width and height (old data)
|
|
2911
|
-
let { width, height } = getRichtextContentSize(richtextInstance.editable);
|
|
2912
|
-
if (width !== this.element.width || height !== this.element.height) {
|
|
2913
|
-
MindTransforms.setTopicSize(this.board, this.element, width, height);
|
|
2914
|
-
}
|
|
2915
|
-
}
|
|
2916
|
-
let richtext = richtextInstance.plaitValue;
|
|
2917
|
-
// use debounceTime to wait DOM render complete
|
|
2918
|
-
const valueChange$ = richtextInstance.plaitChange
|
|
2919
|
-
.pipe(debounceTime(0), filter(event => {
|
|
2920
|
-
// 过滤掉 operations 中全是 set_selection 的操作
|
|
2921
|
-
return !event.operations.every(op => Operation.isSelectionOperation(op));
|
|
2922
|
-
}))
|
|
2923
|
-
.subscribe(event => {
|
|
2924
|
-
if (richtext === event.value) {
|
|
2925
|
-
return;
|
|
2926
|
-
}
|
|
2927
|
-
this.updateRichtext();
|
|
2928
|
-
// 更新富文本、更新宽高
|
|
2929
|
-
let { width, height } = getRichtextContentSize(richtextInstance.editable);
|
|
2930
|
-
MindTransforms.setTopic(this.board, this.element, event.value, width, height);
|
|
2931
|
-
MERGING.set(this.board, true);
|
|
2932
|
-
});
|
|
2933
|
-
const composition$ = richtextInstance.plaitComposition.pipe(debounceTime(0)).subscribe(event => {
|
|
2934
|
-
let { width, height } = getRichtextContentSize(richtextInstance.editable);
|
|
2935
|
-
if (width < NODE_MIN_WIDTH) {
|
|
2936
|
-
width = NODE_MIN_WIDTH;
|
|
2937
|
-
}
|
|
2938
|
-
if (event.isComposing && (width !== this.node.origin.width || height !== this.node.origin.height)) {
|
|
2939
|
-
const newElement = {
|
|
2940
|
-
width: width / this.board.viewport.zoom,
|
|
2941
|
-
height: height / this.board.viewport.zoom
|
|
2942
|
-
};
|
|
2943
|
-
const path = PlaitBoard.findPath(this.board, this.element);
|
|
2944
|
-
Transforms.setNode(this.board, newElement, path);
|
|
2945
|
-
MERGING.set(this.board, true);
|
|
2946
|
-
}
|
|
2947
|
-
});
|
|
2948
|
-
const mousedown$ = fromEvent(document, 'mousedown').subscribe((event) => {
|
|
2949
|
-
const point = transformPoint(this.board, toPoint(event.x, event.y, PlaitBoard.getHost(this.board)));
|
|
2950
|
-
const clickInNode = isHitMindElement(this.board, point, this.element);
|
|
2951
|
-
if (clickInNode && !hasEditableTarget(richtextInstance.editor, event.target)) {
|
|
2952
|
-
event.preventDefault();
|
|
2953
|
-
}
|
|
2954
|
-
else if (!clickInNode) {
|
|
2955
|
-
// handle composition input state, like: Chinese IME Composition Input
|
|
2956
|
-
timer(0).subscribe(() => {
|
|
2957
|
-
exitHandle();
|
|
2958
|
-
this.enableMaskG();
|
|
2959
|
-
});
|
|
2960
|
-
}
|
|
2961
|
-
});
|
|
2962
|
-
const editor = richtextInstance.editor;
|
|
2963
|
-
const { keydown } = editor;
|
|
2964
|
-
editor.keydown = (event) => {
|
|
2965
|
-
if (event.isComposing) {
|
|
2966
|
-
return;
|
|
2967
|
-
}
|
|
2968
|
-
if (event.key === 'Escape') {
|
|
2969
|
-
event.preventDefault();
|
|
2970
|
-
event.stopPropagation();
|
|
2971
|
-
exitHandle();
|
|
2972
|
-
this.drawActiveG();
|
|
2973
|
-
this.enableMaskG();
|
|
2974
|
-
return;
|
|
2975
|
-
}
|
|
2976
|
-
if (event.key === 'Enter' && !event.shiftKey) {
|
|
2977
|
-
event.preventDefault();
|
|
2978
|
-
event.stopPropagation();
|
|
2979
|
-
exitHandle();
|
|
2980
|
-
this.drawActiveG();
|
|
2981
|
-
this.enableMaskG();
|
|
2982
|
-
return;
|
|
2983
|
-
}
|
|
2984
|
-
if (event.key === 'Tab') {
|
|
2985
|
-
event.preventDefault();
|
|
2986
|
-
event.stopPropagation();
|
|
2987
|
-
exitHandle();
|
|
2988
|
-
this.drawActiveG();
|
|
2989
|
-
this.drawMaskG();
|
|
2990
|
-
}
|
|
2991
|
-
};
|
|
2992
|
-
const exitHandle = () => {
|
|
2993
|
-
this.ngZone.run(() => {
|
|
2994
|
-
// unsubscribe
|
|
2995
|
-
valueChange$.unsubscribe();
|
|
2996
|
-
composition$.unsubscribe();
|
|
2997
|
-
mousedown$.unsubscribe();
|
|
2998
|
-
editor.keydown = keydown; // reset keydown
|
|
2999
|
-
// editable status
|
|
3000
|
-
MERGING.set(this.board, false);
|
|
3001
|
-
richtextInstance.plaitReadonly = true;
|
|
3002
|
-
this.richtextComponentRef?.changeDetectorRef.markForCheck();
|
|
3003
|
-
this.isEditable = false;
|
|
3004
|
-
updateMindNodeTopicSize(this.board, this.node, this.richtextG, this.isEditable);
|
|
3005
|
-
IS_TEXT_EDITABLE.set(this.board, false);
|
|
3006
|
-
});
|
|
3007
|
-
};
|
|
2770
|
+
drawText() {
|
|
2771
|
+
this.textManage.draw(this.element.data.topic);
|
|
2772
|
+
this.g.append(this.textManage.g);
|
|
3008
2773
|
}
|
|
3009
2774
|
ngOnDestroy() {
|
|
3010
2775
|
super.ngOnDestroy();
|
|
3011
|
-
this.
|
|
3012
|
-
this.
|
|
3013
|
-
this.emojisDrawer.destroy();
|
|
2776
|
+
this.textManage.destroy();
|
|
2777
|
+
this.nodeEmojisDrawer.destroy();
|
|
3014
2778
|
this.destroy$.next();
|
|
3015
2779
|
this.destroy$.complete();
|
|
3016
2780
|
if (ELEMENT_TO_NODE.get(this.element) === this.node) {
|
|
@@ -3018,7 +2782,7 @@ class MindNodeComponent extends PlaitPluginElementComponent {
|
|
|
3018
2782
|
}
|
|
3019
2783
|
}
|
|
3020
2784
|
}
|
|
3021
|
-
MindNodeComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindNodeComponent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }
|
|
2785
|
+
MindNodeComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindNodeComponent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
3022
2786
|
MindNodeComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.5", type: MindNodeComponent, selector: "plait-mind-node", usesInheritance: true, ngImport: i0, template: `
|
|
3023
2787
|
<plait-children
|
|
3024
2788
|
*ngIf="!element.isCollapsed"
|
|
@@ -3043,7 +2807,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
|
|
|
3043
2807
|
`,
|
|
3044
2808
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
3045
2809
|
}]
|
|
3046
|
-
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }
|
|
2810
|
+
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }]; } });
|
|
3047
2811
|
|
|
3048
2812
|
const getLayoutOptions = (board) => {
|
|
3049
2813
|
function getMainAxle(element, parent) {
|
|
@@ -3116,6 +2880,7 @@ class PlaitMindComponent extends MindNodeComponent {
|
|
|
3116
2880
|
ngOnInit() {
|
|
3117
2881
|
this.updateMindLayout();
|
|
3118
2882
|
super.ngOnInit();
|
|
2883
|
+
this.g.classList.add('root');
|
|
3119
2884
|
}
|
|
3120
2885
|
beforeContextChange(value) {
|
|
3121
2886
|
if (value.element !== this.element && this.initialized) {
|
|
@@ -3156,19 +2921,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
|
|
|
3156
2921
|
class MindModule {
|
|
3157
2922
|
}
|
|
3158
2923
|
MindModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3159
|
-
MindModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.5", ngImport: i0, type: MindModule, declarations: [PlaitMindComponent, MindNodeComponent], imports: [CommonModule,
|
|
3160
|
-
MindModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, imports: [CommonModule,
|
|
2924
|
+
MindModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.5", ngImport: i0, type: MindModule, declarations: [PlaitMindComponent, MindNodeComponent], imports: [CommonModule, TextModule, PlaitModule], exports: [PlaitMindComponent, MindNodeComponent] });
|
|
2925
|
+
MindModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, imports: [CommonModule, TextModule, PlaitModule] });
|
|
3161
2926
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImport: i0, type: MindModule, decorators: [{
|
|
3162
2927
|
type: NgModule,
|
|
3163
2928
|
args: [{
|
|
3164
2929
|
declarations: [PlaitMindComponent, MindNodeComponent],
|
|
3165
|
-
imports: [CommonModule,
|
|
2930
|
+
imports: [CommonModule, TextModule, PlaitModule],
|
|
3166
2931
|
exports: [PlaitMindComponent, MindNodeComponent]
|
|
3167
2932
|
}]
|
|
3168
2933
|
}] });
|
|
3169
2934
|
|
|
3170
2935
|
const DRAG_MOVE_BUFFER = 5;
|
|
3171
|
-
const
|
|
2936
|
+
const withNodeDnd = (board) => {
|
|
3172
2937
|
const { mousedown, mousemove, globalMouseup } = board;
|
|
3173
2938
|
let activeElements = [];
|
|
3174
2939
|
let correspondingElements = [];
|
|
@@ -3522,7 +3287,7 @@ const withAbstract = (board) => {
|
|
|
3522
3287
|
newProperty =
|
|
3523
3288
|
abstractHandlePosition === AbstractHandlePosition.start ? { start: locationIndex + 1 } : { end: locationIndex };
|
|
3524
3289
|
}
|
|
3525
|
-
abstractComponent.
|
|
3290
|
+
abstractComponent.activeDrawer.updateAbstractOutline(activeAbstractElement, abstractHandlePosition, location);
|
|
3526
3291
|
}
|
|
3527
3292
|
mousemove(event);
|
|
3528
3293
|
};
|
|
@@ -3539,7 +3304,7 @@ const withAbstract = (board) => {
|
|
|
3539
3304
|
}
|
|
3540
3305
|
else {
|
|
3541
3306
|
const abstractComponent = PlaitElement.getComponent(activeAbstractElement);
|
|
3542
|
-
abstractComponent.
|
|
3307
|
+
abstractComponent.activeDrawer.updateAbstractOutline(activeAbstractElement);
|
|
3543
3308
|
}
|
|
3544
3309
|
activeAbstractElement = undefined;
|
|
3545
3310
|
}
|
|
@@ -3591,22 +3356,29 @@ const withCreateMind = (board) => {
|
|
|
3591
3356
|
const nodeG = drawRoundRectangleByElement(board, nodeRectangle, emptyMind);
|
|
3592
3357
|
const topicRectangle = getTopicRectangleByElement(newBoard, nodeRectangle, emptyMind);
|
|
3593
3358
|
if (!fakeCreateNodeRef) {
|
|
3594
|
-
const
|
|
3359
|
+
const textManage = new TextManage(board, PlaitBoard.getComponent(board).viewContainerRef, () => {
|
|
3360
|
+
return topicRectangle;
|
|
3361
|
+
});
|
|
3362
|
+
PlaitBoard.getComponent(board)
|
|
3363
|
+
.viewContainerRef.injector.get(NgZone)
|
|
3364
|
+
.run(() => {
|
|
3365
|
+
textManage.draw(emptyMind.data.topic);
|
|
3366
|
+
});
|
|
3595
3367
|
fakeCreateNodeRef = {
|
|
3596
|
-
|
|
3368
|
+
g: createG(),
|
|
3597
3369
|
nodeG,
|
|
3598
|
-
|
|
3599
|
-
topicG: richtextG
|
|
3370
|
+
textManage
|
|
3600
3371
|
};
|
|
3601
|
-
|
|
3602
|
-
PlaitBoard.getHost(board).append(
|
|
3372
|
+
fakeCreateNodeRef.g.classList.add('root');
|
|
3373
|
+
PlaitBoard.getHost(board).append(fakeCreateNodeRef.g);
|
|
3374
|
+
fakeCreateNodeRef.g.append(...[fakeCreateNodeRef.nodeG, textManage.g]);
|
|
3603
3375
|
}
|
|
3604
3376
|
else {
|
|
3377
|
+
fakeCreateNodeRef.textManage.updateRectangle(topicRectangle);
|
|
3605
3378
|
fakeCreateNodeRef.nodeG.remove();
|
|
3606
3379
|
fakeCreateNodeRef.nodeG = nodeG;
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
updateForeignObject(fakeCreateNodeRef.topicG, topicRectangle.width, topicRectangle.height, topicRectangle.x, topicRectangle.y);
|
|
3380
|
+
fakeCreateNodeRef.g.append(nodeG);
|
|
3381
|
+
fakeCreateNodeRef.g.append(fakeCreateNodeRef.textManage.g);
|
|
3610
3382
|
}
|
|
3611
3383
|
}
|
|
3612
3384
|
});
|
|
@@ -3643,9 +3415,8 @@ const withCreateMind = (board) => {
|
|
|
3643
3415
|
};
|
|
3644
3416
|
function destroy() {
|
|
3645
3417
|
if (fakeCreateNodeRef) {
|
|
3646
|
-
fakeCreateNodeRef.
|
|
3647
|
-
fakeCreateNodeRef.
|
|
3648
|
-
fakeCreateNodeRef.topicG.remove();
|
|
3418
|
+
fakeCreateNodeRef.textManage.destroy();
|
|
3419
|
+
fakeCreateNodeRef.g.remove();
|
|
3649
3420
|
fakeCreateNodeRef = null;
|
|
3650
3421
|
}
|
|
3651
3422
|
}
|
|
@@ -3677,6 +3448,68 @@ const isExpandHotkey = (keyboardEvent) => {
|
|
|
3677
3448
|
return isKeyHotkey('mod+/', keyboardEvent);
|
|
3678
3449
|
};
|
|
3679
3450
|
|
|
3451
|
+
const withNodeHover = (board) => {
|
|
3452
|
+
const { mousemove, mouseleave } = board;
|
|
3453
|
+
let hoveredMindElement = null;
|
|
3454
|
+
board.mousemove = (event) => {
|
|
3455
|
+
throttleRAF(() => {
|
|
3456
|
+
let target = null;
|
|
3457
|
+
const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
|
|
3458
|
+
depthFirstRecursion(board, element => {
|
|
3459
|
+
if (target) {
|
|
3460
|
+
return;
|
|
3461
|
+
}
|
|
3462
|
+
if (!MindElement.isMindElement(board, element)) {
|
|
3463
|
+
return;
|
|
3464
|
+
}
|
|
3465
|
+
const isHitElement = isHitMindElement(board, point, element);
|
|
3466
|
+
if (isHitElement) {
|
|
3467
|
+
target = element;
|
|
3468
|
+
}
|
|
3469
|
+
}, node => {
|
|
3470
|
+
if (PlaitBoard.isBoard(node) || board.isRecursion(node)) {
|
|
3471
|
+
return true;
|
|
3472
|
+
}
|
|
3473
|
+
else {
|
|
3474
|
+
return false;
|
|
3475
|
+
}
|
|
3476
|
+
}, true);
|
|
3477
|
+
if (hoveredMindElement && target && hoveredMindElement === target) {
|
|
3478
|
+
return;
|
|
3479
|
+
}
|
|
3480
|
+
if (hoveredMindElement) {
|
|
3481
|
+
removeHovered(hoveredMindElement);
|
|
3482
|
+
}
|
|
3483
|
+
if (target) {
|
|
3484
|
+
addHovered(target);
|
|
3485
|
+
hoveredMindElement = target;
|
|
3486
|
+
}
|
|
3487
|
+
else {
|
|
3488
|
+
hoveredMindElement = null;
|
|
3489
|
+
}
|
|
3490
|
+
});
|
|
3491
|
+
mousemove(event);
|
|
3492
|
+
};
|
|
3493
|
+
board.mouseleave = (event) => {
|
|
3494
|
+
if (hoveredMindElement) {
|
|
3495
|
+
removeHovered(hoveredMindElement);
|
|
3496
|
+
hoveredMindElement = null;
|
|
3497
|
+
}
|
|
3498
|
+
mouseleave(event);
|
|
3499
|
+
};
|
|
3500
|
+
return board;
|
|
3501
|
+
};
|
|
3502
|
+
const addHovered = (element) => {
|
|
3503
|
+
const component = PlaitElement.getComponent(element);
|
|
3504
|
+
component.g.classList.add('hovered');
|
|
3505
|
+
};
|
|
3506
|
+
const removeHovered = (element) => {
|
|
3507
|
+
const component = PlaitElement.getComponent(element);
|
|
3508
|
+
if (component && component.g) {
|
|
3509
|
+
component.g.classList.remove('hovered');
|
|
3510
|
+
}
|
|
3511
|
+
};
|
|
3512
|
+
|
|
3680
3513
|
const withMind = (board) => {
|
|
3681
3514
|
const { drawElement, dblclick, keydown, insertFragment, setFragment, deleteFragment, isHitSelection, getRectangle, isMovable, isRecursion } = board;
|
|
3682
3515
|
board.drawElement = (context) => {
|
|
@@ -3803,7 +3636,7 @@ const withMind = (board) => {
|
|
|
3803
3636
|
if (!isVirtualKey(event)) {
|
|
3804
3637
|
event.preventDefault();
|
|
3805
3638
|
const selectedElement = selectedElements[0];
|
|
3806
|
-
|
|
3639
|
+
editTopic(selectedElement);
|
|
3807
3640
|
return;
|
|
3808
3641
|
}
|
|
3809
3642
|
}
|
|
@@ -3825,7 +3658,7 @@ const withMind = (board) => {
|
|
|
3825
3658
|
.forEach(mindMap => {
|
|
3826
3659
|
depthFirstRecursion(mindMap, node => {
|
|
3827
3660
|
if (!PlaitBoard.hasBeenTextEditing(board) && isHitMindElement(board, point, node)) {
|
|
3828
|
-
|
|
3661
|
+
editTopic(node);
|
|
3829
3662
|
}
|
|
3830
3663
|
}, node => {
|
|
3831
3664
|
if (PlaitBoard.isBoard(node) || board.isRecursion(node)) {
|
|
@@ -3861,7 +3694,7 @@ const withMind = (board) => {
|
|
|
3861
3694
|
}
|
|
3862
3695
|
else {
|
|
3863
3696
|
const text = data?.getData(`text/plain`);
|
|
3864
|
-
const { width, height } =
|
|
3697
|
+
const { width, height } = getTextSize(board, text, TOPIC_DEFAULT_MAX_WORD_COUNT);
|
|
3865
3698
|
const selectedElements = getSelectedElements(board);
|
|
3866
3699
|
if (text && selectedElements.length === 1) {
|
|
3867
3700
|
insertClipboardText(board, selectedElements[0], text, width, height);
|
|
@@ -3879,7 +3712,7 @@ const withMind = (board) => {
|
|
|
3879
3712
|
MindTransforms.removeElements(board, selectedElements);
|
|
3880
3713
|
deleteFragment(data);
|
|
3881
3714
|
};
|
|
3882
|
-
return withMindHotkey(withMindExtend(withCreateMind(withAbstract(
|
|
3715
|
+
return withNodeHover(withMindHotkey(withMindExtend(withCreateMind(withAbstract(withNodeDnd(board))))));
|
|
3883
3716
|
};
|
|
3884
3717
|
|
|
3885
3718
|
class MindEmojiBaseComponent {
|
|
@@ -3933,5 +3766,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.5", ngImpor
|
|
|
3933
3766
|
* Generated bundle index. Do not edit.
|
|
3934
3767
|
*/
|
|
3935
3768
|
|
|
3936
|
-
export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_WIDTH, BaseDrawer, BranchShape, DefaultAbstractNodeStyle, DefaultNodeStyle, ELEMENT_TO_NODE,
|
|
3769
|
+
export { ABSTRACT_HANDLE_COLOR, ABSTRACT_HANDLE_LENGTH, ABSTRACT_HANDLE_MASK_WIDTH, ABSTRACT_INCLUDED_OUTLINE_OFFSET, AbstractHandlePosition, AbstractResizeState, BASE, BRANCH_WIDTH, BaseDrawer, BranchShape, DefaultAbstractNodeStyle, DefaultNodeStyle, ELEMENT_TO_NODE, EXTEND_DIAMETER, EXTEND_OFFSET, GRAY_COLOR, INHERIT_ATTRIBUTE_KEYS, IS_DRAGGING, LayoutDirection, LayoutDirectionsMap, MindColorfulThemeColor, MindDarkThemeColor, MindDefaultThemeColor, MindElement, MindElementShape, MindEmojiBaseComponent, MindModule, MindNode, MindNodeComponent, MindPointerType, MindQueries, MindRetroThemeColor, MindSoftThemeColor, MindStarryThemeColor, MindThemeColor, MindThemeColors, MindTransforms, NODE_MIN_WIDTH, PRIMARY_COLOR, PlaitMind, PlaitMindComponent, QUICK_INSERT_CIRCLE_COLOR, QUICK_INSERT_CIRCLE_OFFSET, QUICK_INSERT_INNER_CROSS_COLOR, ROOT_TOPIC_FONT_SIZE, ROOT_TOPIC_HEIGHT, STROKE_WIDTH, TOPIC_COLOR, TOPIC_DEFAULT_MAX_WORD_COUNT, TOPIC_FONT_SIZE, TRANSPARENT, addActiveOnDragOrigin, adjustAbstractToNode, adjustNodeToRoot, adjustRootToNode, canSetAbstract, copyNewNode, correctLayoutByDirection, createDefaultMind, createEmptyMind, createMindElement, deleteElementHandleAbstract, deleteElementsHandleRightNodeCount, detectDropTarget, directionCorrector, directionDetector, divideElementByParent, drawFakeDragNode, drawFakeDropNode, editTopic, extractNodesText, findLastChild, findLocationLeftIndex, getAbstractBranchColor, getAbstractBranchWidth, getAbstractHandleRectangle, getAllowedDirection, getAvailableSubLayoutsByLayoutDirections, getBehindAbstracts, getBranchColorByMindElement, getBranchDirectionsByLayouts, getBranchShapeByMindElement, getBranchWidthByMindElement, getChildrenCount, getCorrespondingAbstract, getDefaultBranchColor, getDefaultBranchColorByIndex, getDefaultLayout, getEmojiForeignRectangle, getEmojiRectangle, getFirstLevelElement, getHitAbstractHandle, getInCorrectLayoutDirection, getLayoutDirection$1 as getLayoutDirection, getLayoutReverseDirection, getLocationScope, getMindThemeColor, getNextBranchColor, getOverallAbstracts, getPathByDropTarget, getRectangleByElement, getRectangleByNode, getRectangleByResizingLocation, getRelativeStartEndByAbstractRef, getRootLayout, getShapeByElement, getStrokeByMindElement, getTopicRectangleByElement, getTopicRectangleByNode, getValidAbstractRefs, handleTouchedAbstract, hasAfterDraw, hasPreviousOrNextOfDropPath, insertElementHandleAbstract, insertElementHandleRightNodeCount, insertMindElement, isChildElement, isChildRight, isChildUp, isCorrectLayout, isDragging, isDropStandardRight, isHitEmojis, isHitMindElement, isInRightBranchOfStandardLayout, isMixedLayout, isSetAbstract, isValidTarget, isVirtualKey, removeActiveOnDragOrigin, separateChildren, setIsDragging, withMind, withMindExtend };
|
|
3937
3770
|
//# sourceMappingURL=plait-mind.mjs.map
|