@plait/core 0.56.2 → 0.57.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/board/board.component.d.ts +1 -1
- package/core/element/plugin-element.d.ts +0 -1
- package/esm2022/board/board.component.mjs +6 -1
- package/esm2022/core/element/plugin-element.mjs +1 -8
- package/esm2022/interfaces/board.mjs +4 -1
- package/esm2022/interfaces/element.mjs +1 -5
- package/esm2022/utils/element.mjs +7 -2
- package/esm2022/utils/weak-maps.mjs +1 -1
- package/fesm2022/plait-core.mjs +896 -893
- package/fesm2022/plait-core.mjs.map +1 -1
- package/interfaces/board.d.ts +1 -0
- package/interfaces/element.d.ts +0 -3
- package/package.json +1 -1
- package/utils/element.d.ts +1 -0
- package/utils/weak-maps.d.ts +1 -0
package/fesm2022/plait-core.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { Directive, Input, Injectable, IterableDiffers, EventEmitter, inject, ElementRef, Component, ChangeDetectionStrategy, Output, HostBinding, ViewChild, ContentChildren, ViewContainerRef, ChangeDetectorRef } from '@angular/core';
|
|
3
3
|
import rough from 'roughjs/bin/rough';
|
|
4
4
|
import { timer, Subject, fromEvent } from 'rxjs';
|
|
5
5
|
import { takeUntil, filter, tap } from 'rxjs/operators';
|
|
@@ -42,51 +42,6 @@ var PlaitPointerType;
|
|
|
42
42
|
* Extendable Custom Types Interface
|
|
43
43
|
*/
|
|
44
44
|
|
|
45
|
-
function depthFirstRecursion(node, callback, recursion, isReverse) {
|
|
46
|
-
if (!recursion || recursion(node)) {
|
|
47
|
-
let children = [];
|
|
48
|
-
if (node.children) {
|
|
49
|
-
children = [...node.children];
|
|
50
|
-
}
|
|
51
|
-
children = isReverse ? children.reverse() : children;
|
|
52
|
-
children.forEach(child => {
|
|
53
|
-
depthFirstRecursion(child, callback, recursion);
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
callback(node);
|
|
57
|
-
}
|
|
58
|
-
const getIsRecursionFunc = (board) => {
|
|
59
|
-
return (element) => {
|
|
60
|
-
if (PlaitBoard.isBoard(element) || board.isRecursion(element)) {
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const SELECTION_BORDER_COLOR = '#6698FF';
|
|
70
|
-
const SELECTION_FILL_COLOR = '#6698FF25'; // opacity 0.25
|
|
71
|
-
const Selection = {
|
|
72
|
-
isCollapsed(selection) {
|
|
73
|
-
if (selection.anchor[0] == selection.focus[0] && selection.anchor[1] === selection.focus[1]) {
|
|
74
|
-
return true;
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const sortElements = (board, elements, ascendingOrder = true) => {
|
|
83
|
-
return [...elements].sort((a, b) => {
|
|
84
|
-
const pathA = PlaitBoard.findPath(board, a);
|
|
85
|
-
const pathB = PlaitBoard.findPath(board, b);
|
|
86
|
-
return ascendingOrder ? pathA[0] - pathB[0] : pathB[0] - pathA[0];
|
|
87
|
-
});
|
|
88
|
-
};
|
|
89
|
-
|
|
90
45
|
const RectangleClient = {
|
|
91
46
|
isHit: (origin, target) => {
|
|
92
47
|
return RectangleClient.isHitX(origin, target) && RectangleClient.isHitY(origin, target);
|
|
@@ -242,717 +197,7 @@ const RectangleClient = {
|
|
|
242
197
|
height: maxY - minY
|
|
243
198
|
};
|
|
244
199
|
}
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
var PlaitPluginKey;
|
|
248
|
-
(function (PlaitPluginKey) {
|
|
249
|
-
PlaitPluginKey["withSelection"] = "withSelection";
|
|
250
|
-
})(PlaitPluginKey || (PlaitPluginKey = {}));
|
|
251
|
-
|
|
252
|
-
const getHitElementsBySelection = (board, selection, match = () => true) => {
|
|
253
|
-
const newSelection = selection || board.selection;
|
|
254
|
-
const rectangleHitElements = [];
|
|
255
|
-
if (!newSelection) {
|
|
256
|
-
return [];
|
|
257
|
-
}
|
|
258
|
-
const isCollapsed = Selection.isCollapsed(newSelection);
|
|
259
|
-
if (isCollapsed) {
|
|
260
|
-
const hitElement = getHitElementByPoint(board, newSelection.anchor, match);
|
|
261
|
-
if (hitElement) {
|
|
262
|
-
return [hitElement];
|
|
263
|
-
}
|
|
264
|
-
else {
|
|
265
|
-
return [];
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
depthFirstRecursion(board, node => {
|
|
269
|
-
if (!PlaitBoard.isBoard(node) && match(node) && board.isRectangleHit(node, newSelection)) {
|
|
270
|
-
rectangleHitElements.push(node);
|
|
271
|
-
}
|
|
272
|
-
}, getIsRecursionFunc(board), true);
|
|
273
|
-
return rectangleHitElements;
|
|
274
|
-
};
|
|
275
|
-
const getHitElementByPoint = (board, point, match = () => true) => {
|
|
276
|
-
let hitElement = undefined;
|
|
277
|
-
let hitInsideElement = undefined;
|
|
278
|
-
depthFirstRecursion(board, node => {
|
|
279
|
-
if (hitElement) {
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
if (PlaitBoard.isBoard(node) || !match(node) || !PlaitElement.hasMounted(node)) {
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
if (board.isHit(node, point)) {
|
|
286
|
-
hitElement = node;
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* 需要增加场景测试
|
|
291
|
-
* hitInsideElement 存的是第一个符合 isInsidePoint 的元素
|
|
292
|
-
* 当有元素符合 isHit 时结束遍历,并返回 hitElement
|
|
293
|
-
* 当所有元素都不符合 isHit ,则返回第一个符合 isInsidePoint 的元素
|
|
294
|
-
* 这样保证最上面的元素优先被探测到;
|
|
295
|
-
*/
|
|
296
|
-
if (!hitInsideElement && board.isInsidePoint(node, point)) {
|
|
297
|
-
hitInsideElement = node;
|
|
298
|
-
}
|
|
299
|
-
}, getIsRecursionFunc(board), true);
|
|
300
|
-
return hitElement || hitInsideElement;
|
|
301
|
-
};
|
|
302
|
-
const getHitSelectedElements = (board, point) => {
|
|
303
|
-
const selectedElements = getSelectedElements(board);
|
|
304
|
-
const targetRectangle = selectedElements.length > 0 && getRectangleByElements(board, selectedElements, false);
|
|
305
|
-
const isInTargetRectangle = targetRectangle && RectangleClient.isPointInRectangle(targetRectangle, point);
|
|
306
|
-
if (isInTargetRectangle) {
|
|
307
|
-
return selectedElements;
|
|
308
|
-
}
|
|
309
|
-
else {
|
|
310
|
-
return [];
|
|
311
|
-
}
|
|
312
|
-
};
|
|
313
|
-
const cacheSelectedElements = (board, selectedElements) => {
|
|
314
|
-
const sortedElements = sortElements(board, selectedElements);
|
|
315
|
-
BOARD_TO_SELECTED_ELEMENT.set(board, sortedElements);
|
|
316
|
-
};
|
|
317
|
-
const getSelectedElements = (board) => {
|
|
318
|
-
return BOARD_TO_SELECTED_ELEMENT.get(board) || [];
|
|
319
|
-
};
|
|
320
|
-
const addSelectedElement = (board, element) => {
|
|
321
|
-
let elements = [];
|
|
322
|
-
if (Array.isArray(element)) {
|
|
323
|
-
elements.push(...element);
|
|
324
|
-
}
|
|
325
|
-
else {
|
|
326
|
-
elements.push(element);
|
|
327
|
-
}
|
|
328
|
-
const selectedElements = getSelectedElements(board);
|
|
329
|
-
cacheSelectedElements(board, [...selectedElements, ...elements]);
|
|
330
|
-
};
|
|
331
|
-
const removeSelectedElement = (board, element, isRemoveChildren = false) => {
|
|
332
|
-
const selectedElements = getSelectedElements(board);
|
|
333
|
-
if (selectedElements.includes(element)) {
|
|
334
|
-
const targetElements = [];
|
|
335
|
-
if (board.isRecursion(element) && isRemoveChildren) {
|
|
336
|
-
depthFirstRecursion(element, node => {
|
|
337
|
-
targetElements.push(node);
|
|
338
|
-
}, node => board.isRecursion(node));
|
|
339
|
-
}
|
|
340
|
-
else {
|
|
341
|
-
targetElements.push(element);
|
|
342
|
-
}
|
|
343
|
-
const newSelectedElements = selectedElements.filter(value => !targetElements.includes(value));
|
|
344
|
-
cacheSelectedElements(board, newSelectedElements);
|
|
345
|
-
}
|
|
346
|
-
};
|
|
347
|
-
const clearSelectedElement = (board) => {
|
|
348
|
-
cacheSelectedElements(board, []);
|
|
349
|
-
};
|
|
350
|
-
const isSelectedElement = (board, element) => {
|
|
351
|
-
const selectedElements = getSelectedElements(board);
|
|
352
|
-
return !!selectedElements.find(value => value === element);
|
|
353
|
-
};
|
|
354
|
-
const temporaryDisableSelection = (board) => {
|
|
355
|
-
const currentOptions = board.getPluginOptions(PlaitPluginKey.withSelection);
|
|
356
|
-
board.setPluginOptions(PlaitPluginKey.withSelection, {
|
|
357
|
-
isDisabledSelect: true
|
|
358
|
-
});
|
|
359
|
-
setTimeout(() => {
|
|
360
|
-
board.setPluginOptions(PlaitPluginKey.withSelection, { ...currentOptions });
|
|
361
|
-
}, 0);
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* @license
|
|
366
|
-
* Copyright Google LLC All Rights Reserved.
|
|
367
|
-
*
|
|
368
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
369
|
-
* found in the LICENSE file at https://angular.io/license
|
|
370
|
-
*/
|
|
371
|
-
const MAC_ENTER = 3;
|
|
372
|
-
const BACKSPACE = 8;
|
|
373
|
-
const TAB = 9;
|
|
374
|
-
const NUM_CENTER = 12;
|
|
375
|
-
const ENTER = 13;
|
|
376
|
-
const SHIFT = 16;
|
|
377
|
-
const CONTROL = 17;
|
|
378
|
-
const ALT = 18;
|
|
379
|
-
const PAUSE = 19;
|
|
380
|
-
const CAPS_LOCK = 20;
|
|
381
|
-
const ESCAPE = 27;
|
|
382
|
-
const SPACE = 32;
|
|
383
|
-
const PAGE_UP = 33;
|
|
384
|
-
const PAGE_DOWN = 34;
|
|
385
|
-
const END = 35;
|
|
386
|
-
const HOME = 36;
|
|
387
|
-
const LEFT_ARROW = 37;
|
|
388
|
-
const UP_ARROW = 38;
|
|
389
|
-
const RIGHT_ARROW = 39;
|
|
390
|
-
const DOWN_ARROW = 40;
|
|
391
|
-
const PLUS_SIGN = 43;
|
|
392
|
-
const PRINT_SCREEN = 44;
|
|
393
|
-
const INSERT = 45;
|
|
394
|
-
const DELETE = 46;
|
|
395
|
-
const ZERO = 48;
|
|
396
|
-
const ONE = 49;
|
|
397
|
-
const TWO = 50;
|
|
398
|
-
const THREE = 51;
|
|
399
|
-
const FOUR = 52;
|
|
400
|
-
const FIVE = 53;
|
|
401
|
-
const SIX = 54;
|
|
402
|
-
const SEVEN = 55;
|
|
403
|
-
const EIGHT = 56;
|
|
404
|
-
const NINE = 57;
|
|
405
|
-
const FF_SEMICOLON = 59; // Firefox (Gecko) fires this for semicolon instead of 186
|
|
406
|
-
const FF_EQUALS = 61; // Firefox (Gecko) fires this for equals instead of 187
|
|
407
|
-
const QUESTION_MARK = 63;
|
|
408
|
-
const AT_SIGN = 64;
|
|
409
|
-
const A = 65;
|
|
410
|
-
const B = 66;
|
|
411
|
-
const C = 67;
|
|
412
|
-
const D = 68;
|
|
413
|
-
const E = 69;
|
|
414
|
-
const F = 70;
|
|
415
|
-
const G = 71;
|
|
416
|
-
const H = 72;
|
|
417
|
-
const I = 73;
|
|
418
|
-
const J = 74;
|
|
419
|
-
const K = 75;
|
|
420
|
-
const L = 76;
|
|
421
|
-
const M = 77;
|
|
422
|
-
const N = 78;
|
|
423
|
-
const O = 79;
|
|
424
|
-
const P = 80;
|
|
425
|
-
const Q = 81;
|
|
426
|
-
const R = 82;
|
|
427
|
-
const S = 83;
|
|
428
|
-
const T = 84;
|
|
429
|
-
const U = 85;
|
|
430
|
-
const V = 86;
|
|
431
|
-
const W = 87;
|
|
432
|
-
const X = 88;
|
|
433
|
-
const Y = 89;
|
|
434
|
-
const Z = 90;
|
|
435
|
-
const META = 91; // WIN_KEY_LEFT
|
|
436
|
-
const MAC_WK_CMD_LEFT = 91;
|
|
437
|
-
const MAC_WK_CMD_RIGHT = 93;
|
|
438
|
-
const CONTEXT_MENU = 93;
|
|
439
|
-
const NUMPAD_ZERO = 96;
|
|
440
|
-
const NUMPAD_ONE = 97;
|
|
441
|
-
const NUMPAD_TWO = 98;
|
|
442
|
-
const NUMPAD_THREE = 99;
|
|
443
|
-
const NUMPAD_FOUR = 100;
|
|
444
|
-
const NUMPAD_FIVE = 101;
|
|
445
|
-
const NUMPAD_SIX = 102;
|
|
446
|
-
const NUMPAD_SEVEN = 103;
|
|
447
|
-
const NUMPAD_EIGHT = 104;
|
|
448
|
-
const NUMPAD_NINE = 105;
|
|
449
|
-
const NUMPAD_MULTIPLY = 106;
|
|
450
|
-
const NUMPAD_PLUS = 107;
|
|
451
|
-
const NUMPAD_MINUS = 109;
|
|
452
|
-
const NUMPAD_PERIOD = 110;
|
|
453
|
-
const NUMPAD_DIVIDE = 111;
|
|
454
|
-
const F1 = 112;
|
|
455
|
-
const F2 = 113;
|
|
456
|
-
const F3 = 114;
|
|
457
|
-
const F4 = 115;
|
|
458
|
-
const F5 = 116;
|
|
459
|
-
const F6 = 117;
|
|
460
|
-
const F7 = 118;
|
|
461
|
-
const F8 = 119;
|
|
462
|
-
const F9 = 120;
|
|
463
|
-
const F10 = 121;
|
|
464
|
-
const F11 = 122;
|
|
465
|
-
const F12 = 123;
|
|
466
|
-
const NUM_LOCK = 144;
|
|
467
|
-
const SCROLL_LOCK = 145;
|
|
468
|
-
const FIRST_MEDIA = 166;
|
|
469
|
-
const FF_MINUS = 173;
|
|
470
|
-
const MUTE = 173; // Firefox (Gecko) fires 181 for MUTE
|
|
471
|
-
const VOLUME_DOWN = 174; // Firefox (Gecko) fires 182 for VOLUME_DOWN
|
|
472
|
-
const VOLUME_UP = 175; // Firefox (Gecko) fires 183 for VOLUME_UP
|
|
473
|
-
const FF_MUTE = 181;
|
|
474
|
-
const FF_VOLUME_DOWN = 182;
|
|
475
|
-
const LAST_MEDIA = 183;
|
|
476
|
-
const FF_VOLUME_UP = 183;
|
|
477
|
-
const SEMICOLON = 186; // Firefox (Gecko) fires 59 for SEMICOLON
|
|
478
|
-
const EQUALS = 187; // Firefox (Gecko) fires 61 for EQUALS
|
|
479
|
-
const COMMA = 188;
|
|
480
|
-
const DASH = 189; // Firefox (Gecko) fires 173 for DASH/MINUS
|
|
481
|
-
const PERIOD = 190;
|
|
482
|
-
const SLASH = 191;
|
|
483
|
-
const APOSTROPHE = 192;
|
|
484
|
-
const TILDE = 192;
|
|
485
|
-
const OPEN_SQUARE_BRACKET = 219;
|
|
486
|
-
const BACKSLASH = 220;
|
|
487
|
-
const CLOSE_SQUARE_BRACKET = 221;
|
|
488
|
-
const SINGLE_QUOTE = 222;
|
|
489
|
-
const MAC_META = 224;
|
|
490
|
-
|
|
491
|
-
var ResizeCursorClass;
|
|
492
|
-
(function (ResizeCursorClass) {
|
|
493
|
-
ResizeCursorClass["ew"] = "ew-resize";
|
|
494
|
-
ResizeCursorClass["ns"] = "ns-resize";
|
|
495
|
-
ResizeCursorClass["nesw"] = "nesw-resize";
|
|
496
|
-
ResizeCursorClass["nwse"] = "nwse-resize";
|
|
497
|
-
})(ResizeCursorClass || (ResizeCursorClass = {}));
|
|
498
|
-
var CursorClass;
|
|
499
|
-
(function (CursorClass) {
|
|
500
|
-
CursorClass["crosshair"] = "crosshair";
|
|
501
|
-
})(CursorClass || (CursorClass = {}));
|
|
502
|
-
const RESIZE_CURSORS = [ResizeCursorClass.ns, ResizeCursorClass.nesw, ResizeCursorClass.ew, ResizeCursorClass.nwse];
|
|
503
|
-
|
|
504
|
-
const ATTACHED_ELEMENT_CLASS_NAME = 'plait-board-attached';
|
|
505
|
-
const ACTIVE_STROKE_WIDTH = 1;
|
|
506
|
-
const SNAPPING_STROKE_WIDTH = 2;
|
|
507
|
-
const SELECTION_RECTANGLE_CLASS_NAME = 'selection-rectangle';
|
|
508
|
-
|
|
509
|
-
const HOST_CLASS_NAME = 'plait-board-container';
|
|
510
|
-
const ACTIVE_MOVING_CLASS_NAME = 'active-with-moving';
|
|
511
|
-
const ROTATE_HANDLE_CLASS_NAME = 'rotate-handle';
|
|
512
|
-
const RESIZE_HANDLE_CLASS_NAME = 'resize-handle';
|
|
513
|
-
const SCROLL_BAR_WIDTH = 20;
|
|
514
|
-
const MAX_RADIUS = 16;
|
|
515
|
-
const POINTER_BUTTON = {
|
|
516
|
-
MAIN: 0,
|
|
517
|
-
WHEEL: 1,
|
|
518
|
-
SECONDARY: 2,
|
|
519
|
-
TOUCH: -1
|
|
520
|
-
};
|
|
521
|
-
const PRESS_AND_MOVE_BUFFER = 3;
|
|
522
|
-
const HIT_DISTANCE_BUFFER = 5;
|
|
523
|
-
|
|
524
|
-
const NS = 'http://www.w3.org/2000/svg';
|
|
525
|
-
function createG() {
|
|
526
|
-
const newG = document.createElementNS(NS, 'g');
|
|
527
|
-
return newG;
|
|
528
|
-
}
|
|
529
|
-
function createPath() {
|
|
530
|
-
const newG = document.createElementNS(NS, 'path');
|
|
531
|
-
return newG;
|
|
532
|
-
}
|
|
533
|
-
function createRect(rectangle, options) {
|
|
534
|
-
const rect = document.createElementNS(NS, 'rect');
|
|
535
|
-
rect.setAttribute('x', `${rectangle.x}`);
|
|
536
|
-
rect.setAttribute('y', `${rectangle.y}`);
|
|
537
|
-
rect.setAttribute('width', `${rectangle.width}`);
|
|
538
|
-
rect.setAttribute('height', `${rectangle.height}`);
|
|
539
|
-
for (let key in options) {
|
|
540
|
-
const optionKey = key;
|
|
541
|
-
rect.setAttribute(key, `${options[optionKey]}`);
|
|
542
|
-
}
|
|
543
|
-
return rect;
|
|
544
|
-
}
|
|
545
|
-
const setStrokeLinecap = (g, value) => {
|
|
546
|
-
g.setAttribute('stroke-linecap', value);
|
|
547
|
-
};
|
|
548
|
-
const setPathStrokeLinecap = (g, value) => {
|
|
549
|
-
g.querySelectorAll('path').forEach(path => {
|
|
550
|
-
path.setAttribute('stroke-linecap', value);
|
|
551
|
-
});
|
|
552
|
-
};
|
|
553
|
-
function createMask() {
|
|
554
|
-
return document.createElementNS(NS, 'mask');
|
|
555
|
-
}
|
|
556
|
-
function createSVG() {
|
|
557
|
-
const svg = document.createElementNS(NS, 'svg');
|
|
558
|
-
return svg;
|
|
559
|
-
}
|
|
560
|
-
function createText(x, y, fill, textContent) {
|
|
561
|
-
var text = document.createElementNS(NS, 'text');
|
|
562
|
-
text.setAttribute('x', `${x}`);
|
|
563
|
-
text.setAttribute('y', `${y}`);
|
|
564
|
-
text.setAttribute('fill', fill);
|
|
565
|
-
text.textContent = textContent;
|
|
566
|
-
return text;
|
|
567
|
-
}
|
|
568
|
-
/**
|
|
569
|
-
* Check if a DOM node is an element node.
|
|
570
|
-
*/
|
|
571
|
-
const isDOMElement = (value) => {
|
|
572
|
-
return isDOMNode(value) && value.nodeType === 1;
|
|
573
|
-
};
|
|
574
|
-
/**
|
|
575
|
-
* Check if a value is a DOM node.
|
|
576
|
-
*/
|
|
577
|
-
const isDOMNode = (value) => {
|
|
578
|
-
return value instanceof window.Node;
|
|
579
|
-
};
|
|
580
|
-
const hasInputOrTextareaTarget = (target) => {
|
|
581
|
-
if (isDOMElement(target)) {
|
|
582
|
-
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {
|
|
583
|
-
return true;
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
return false;
|
|
587
|
-
};
|
|
588
|
-
const isSecondaryPointer = (event) => {
|
|
589
|
-
return event.button === POINTER_BUTTON.SECONDARY;
|
|
590
|
-
};
|
|
591
|
-
const isMainPointer = (event) => {
|
|
592
|
-
return event.button === POINTER_BUTTON.MAIN;
|
|
593
|
-
};
|
|
594
|
-
|
|
595
|
-
function hasBeforeContextChange(value) {
|
|
596
|
-
if (value.beforeContextChange) {
|
|
597
|
-
return true;
|
|
598
|
-
}
|
|
599
|
-
return false;
|
|
600
|
-
}
|
|
601
|
-
function hasOnContextChanged(value) {
|
|
602
|
-
if (value.onContextChanged) {
|
|
603
|
-
return true;
|
|
604
|
-
}
|
|
605
|
-
return false;
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
class ListRender {
|
|
609
|
-
constructor(board, viewContainerRef) {
|
|
610
|
-
this.board = board;
|
|
611
|
-
this.viewContainerRef = viewContainerRef;
|
|
612
|
-
this.children = [];
|
|
613
|
-
this.componentRefs = [];
|
|
614
|
-
this.contexts = [];
|
|
615
|
-
this.differ = null;
|
|
616
|
-
this.initialized = false;
|
|
617
|
-
}
|
|
618
|
-
initialize(children, childrenContext) {
|
|
619
|
-
this.initialized = true;
|
|
620
|
-
this.children = children;
|
|
621
|
-
children.forEach((descendant, index) => {
|
|
622
|
-
NODE_TO_INDEX.set(descendant, index);
|
|
623
|
-
NODE_TO_PARENT.set(descendant, childrenContext.parent);
|
|
624
|
-
const context = getContext(this.board, descendant, index, childrenContext.parent);
|
|
625
|
-
const componentType = getComponentType(this.board, context);
|
|
626
|
-
const componentRef = createPluginComponent(componentType, context, this.viewContainerRef, childrenContext);
|
|
627
|
-
this.componentRefs.push(componentRef);
|
|
628
|
-
this.contexts.push(context);
|
|
629
|
-
});
|
|
630
|
-
const newDiffers = this.viewContainerRef.injector.get(IterableDiffers);
|
|
631
|
-
this.differ = newDiffers.find(children).create(trackBy);
|
|
632
|
-
this.differ.diff(children);
|
|
633
|
-
}
|
|
634
|
-
update(children, childrenContext) {
|
|
635
|
-
if (!this.initialized) {
|
|
636
|
-
this.initialize(children, childrenContext);
|
|
637
|
-
return;
|
|
638
|
-
}
|
|
639
|
-
if (!this.differ) {
|
|
640
|
-
throw new Error('Exception: Can not find differ ');
|
|
641
|
-
}
|
|
642
|
-
const { board, parent } = childrenContext;
|
|
643
|
-
const diffResult = this.differ.diff(children);
|
|
644
|
-
if (diffResult) {
|
|
645
|
-
const newContexts = [];
|
|
646
|
-
const newComponentRefs = [];
|
|
647
|
-
let currentIndexForFirstElement = null;
|
|
648
|
-
diffResult.forEachItem((record) => {
|
|
649
|
-
NODE_TO_INDEX.set(record.item, record.currentIndex);
|
|
650
|
-
NODE_TO_PARENT.set(record.item, childrenContext.parent);
|
|
651
|
-
const previousContext = record.previousIndex === null ? undefined : this.contexts[record.previousIndex];
|
|
652
|
-
const context = getContext(board, record.item, record.currentIndex, parent, previousContext);
|
|
653
|
-
if (record.previousIndex === null) {
|
|
654
|
-
const componentType = getComponentType(board, context);
|
|
655
|
-
const componentRef = createPluginComponent(componentType, context, this.viewContainerRef, childrenContext);
|
|
656
|
-
newContexts.push(context);
|
|
657
|
-
newComponentRefs.push(componentRef);
|
|
658
|
-
}
|
|
659
|
-
else {
|
|
660
|
-
const componentRef = this.componentRefs[record.previousIndex];
|
|
661
|
-
componentRef.instance.context = context;
|
|
662
|
-
newComponentRefs.push(componentRef);
|
|
663
|
-
newContexts.push(context);
|
|
664
|
-
}
|
|
665
|
-
// item might has been changed, so need to compare the id
|
|
666
|
-
if (record.item === this.children[0] || record.item.id === this.children[0]?.id) {
|
|
667
|
-
currentIndexForFirstElement = record.currentIndex;
|
|
668
|
-
}
|
|
669
|
-
});
|
|
670
|
-
diffResult.forEachOperation(record => {
|
|
671
|
-
// removed
|
|
672
|
-
if (record.currentIndex === null) {
|
|
673
|
-
const componentRef = this.componentRefs[record.previousIndex];
|
|
674
|
-
componentRef?.destroy();
|
|
675
|
-
}
|
|
676
|
-
// moved
|
|
677
|
-
if (record.previousIndex !== null && record.currentIndex !== null) {
|
|
678
|
-
mountOnItemMove(record.item, record.currentIndex, childrenContext, currentIndexForFirstElement);
|
|
679
|
-
}
|
|
680
|
-
});
|
|
681
|
-
this.componentRefs = newComponentRefs;
|
|
682
|
-
this.contexts = newContexts;
|
|
683
|
-
this.children = children;
|
|
684
|
-
}
|
|
685
|
-
else {
|
|
686
|
-
const newContexts = [];
|
|
687
|
-
this.children.forEach((element, index) => {
|
|
688
|
-
NODE_TO_INDEX.set(element, index);
|
|
689
|
-
NODE_TO_PARENT.set(element, childrenContext.parent);
|
|
690
|
-
const previousContext = this.contexts[index];
|
|
691
|
-
const previousComponentRef = this.componentRefs[index];
|
|
692
|
-
const context = getContext(board, element, index, parent, previousContext);
|
|
693
|
-
previousComponentRef.instance.context = context;
|
|
694
|
-
newContexts.push(context);
|
|
695
|
-
});
|
|
696
|
-
this.contexts = newContexts;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
destroy() {
|
|
700
|
-
this.children.forEach((element, index) => {
|
|
701
|
-
if (this.componentRefs[index]) {
|
|
702
|
-
this.componentRefs[index].destroy();
|
|
703
|
-
}
|
|
704
|
-
});
|
|
705
|
-
this.componentRefs = [];
|
|
706
|
-
this.children = [];
|
|
707
|
-
this.contexts = [];
|
|
708
|
-
this.initialized = false;
|
|
709
|
-
this.differ = null;
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
const trackBy = (index, element) => {
|
|
713
|
-
return element.id;
|
|
714
|
-
};
|
|
715
|
-
const createPluginComponent = (componentType, context, viewContainerRef, childrenContext) => {
|
|
716
|
-
const componentRef = viewContainerRef.createComponent(componentType, { injector: viewContainerRef.injector });
|
|
717
|
-
const instance = componentRef.instance;
|
|
718
|
-
instance.context = context;
|
|
719
|
-
componentRef.changeDetectorRef.detectChanges();
|
|
720
|
-
const g = componentRef.instance.getContainerG();
|
|
721
|
-
mountElementG(context.index, g, childrenContext);
|
|
722
|
-
componentRef.instance.initializeListRender();
|
|
723
|
-
return componentRef;
|
|
724
|
-
};
|
|
725
|
-
const getComponentType = (board, context) => {
|
|
726
|
-
const result = board.drawElement(context);
|
|
727
|
-
return result;
|
|
728
|
-
};
|
|
729
|
-
const getContext = (board, element, index, parent, previousContext) => {
|
|
730
|
-
let isSelected = isSelectedElement(board, element);
|
|
731
|
-
const previousElement = previousContext && previousContext.element;
|
|
732
|
-
if (previousElement && previousElement !== element && isSelectedElement(board, previousElement)) {
|
|
733
|
-
isSelected = true;
|
|
734
|
-
removeSelectedElement(board, previousElement);
|
|
735
|
-
addSelectedElement(board, element);
|
|
736
|
-
}
|
|
737
|
-
const context = {
|
|
738
|
-
element: element,
|
|
739
|
-
parent: parent,
|
|
740
|
-
board: board,
|
|
741
|
-
selected: isSelected,
|
|
742
|
-
index
|
|
743
|
-
};
|
|
744
|
-
return context;
|
|
745
|
-
};
|
|
746
|
-
// the g depth of root element:[1]-[2]-[3]-[4]
|
|
747
|
-
// the g depth of root element and children element(the [2] element has children):
|
|
748
|
-
// [1]-
|
|
749
|
-
// [2]([2-1-1][2-1-2][2-1][2-2][2-3-1][2-3-2][2-3][2])-
|
|
750
|
-
// [3]-
|
|
751
|
-
// [4]
|
|
752
|
-
const mountElementG = (index, g, childrenContext,
|
|
753
|
-
// for moving scene: the current index for first element before moving
|
|
754
|
-
currentIndexForFirstElement = null) => {
|
|
755
|
-
const { parent, parentG } = childrenContext;
|
|
756
|
-
if (PlaitBoard.isBoard(parent)) {
|
|
757
|
-
if (index > 0) {
|
|
758
|
-
const previousElement = parent.children[index - 1];
|
|
759
|
-
const previousContainerG = PlaitElement.getContainerG(previousElement, { suppressThrow: false });
|
|
760
|
-
previousContainerG.insertAdjacentElement('afterend', g);
|
|
761
|
-
}
|
|
762
|
-
else {
|
|
763
|
-
if (currentIndexForFirstElement !== null) {
|
|
764
|
-
const firstElement = parent.children[currentIndexForFirstElement];
|
|
765
|
-
const firstContainerG = firstElement && PlaitElement.getContainerG(firstElement, { suppressThrow: true });
|
|
766
|
-
if (firstElement && firstContainerG) {
|
|
767
|
-
parentG.insertBefore(g, firstContainerG);
|
|
768
|
-
}
|
|
769
|
-
else {
|
|
770
|
-
throw new Error('fail to mount container on moving');
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
else {
|
|
774
|
-
parentG.append(g);
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
else {
|
|
779
|
-
if (index > 0) {
|
|
780
|
-
const previousElement = parent.children[index - 1];
|
|
781
|
-
const previousElementG = PlaitElement.getElementG(previousElement);
|
|
782
|
-
previousElementG.insertAdjacentElement('afterend', g);
|
|
783
|
-
}
|
|
784
|
-
else {
|
|
785
|
-
if (currentIndexForFirstElement) {
|
|
786
|
-
const nextElement = parent.children[currentIndexForFirstElement];
|
|
787
|
-
const nextPath = nextElement && PlaitBoard.findPath(childrenContext.board, nextElement);
|
|
788
|
-
const first = nextPath && PlaitNode.first(childrenContext.board, nextPath);
|
|
789
|
-
const firstContainerG = first && PlaitElement.getContainerG(first, { suppressThrow: false });
|
|
790
|
-
if (firstContainerG) {
|
|
791
|
-
parentG.insertBefore(g, firstContainerG);
|
|
792
|
-
}
|
|
793
|
-
else {
|
|
794
|
-
throw new Error('fail to mount container on moving');
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
else {
|
|
798
|
-
let parentElementG = PlaitElement.getElementG(parent);
|
|
799
|
-
parentG.insertBefore(g, parentElementG);
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
};
|
|
804
|
-
const mountOnItemMove = (element, index, childrenContext, currentIndexForFirstElement) => {
|
|
805
|
-
const containerG = PlaitElement.getContainerG(element, { suppressThrow: false });
|
|
806
|
-
mountElementG(index, containerG, childrenContext, currentIndexForFirstElement);
|
|
807
|
-
if (element.children && !PlaitElement.isRootElement(element)) {
|
|
808
|
-
element.children.forEach((child, index) => {
|
|
809
|
-
mountOnItemMove(child, index, { ...childrenContext, parent: element }, null);
|
|
810
|
-
});
|
|
811
|
-
}
|
|
812
|
-
};
|
|
813
|
-
|
|
814
|
-
class PlaitPluginElementComponent {
|
|
815
|
-
get hasChildren() {
|
|
816
|
-
return !!this.element.children;
|
|
817
|
-
}
|
|
818
|
-
set context(value) {
|
|
819
|
-
if (hasBeforeContextChange(this)) {
|
|
820
|
-
this.beforeContextChange(value);
|
|
821
|
-
}
|
|
822
|
-
const previousContext = this._context;
|
|
823
|
-
this._context = value;
|
|
824
|
-
if (this.element) {
|
|
825
|
-
ELEMENT_TO_COMPONENT.set(this.element, this);
|
|
826
|
-
}
|
|
827
|
-
if (this.initialized) {
|
|
828
|
-
const elementG = this.getElementG();
|
|
829
|
-
const containerG = this.getContainerG();
|
|
830
|
-
NODE_TO_G.set(this.element, elementG);
|
|
831
|
-
NODE_TO_CONTAINER_G.set(this.element, containerG);
|
|
832
|
-
ELEMENT_TO_REF.set(this.element, this.ref);
|
|
833
|
-
this.updateListRender();
|
|
834
|
-
this.cdr.markForCheck();
|
|
835
|
-
if (hasOnContextChanged(this)) {
|
|
836
|
-
this.onContextChanged(value, previousContext);
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
else {
|
|
840
|
-
if (PlaitElement.isRootElement(this.element) && this.hasChildren) {
|
|
841
|
-
this._g = createG();
|
|
842
|
-
this._containerG = createG();
|
|
843
|
-
this._containerG.append(this._g);
|
|
844
|
-
}
|
|
845
|
-
else {
|
|
846
|
-
this._g = createG();
|
|
847
|
-
this._containerG = this._g;
|
|
848
|
-
}
|
|
849
|
-
NODE_TO_G.set(this.element, this._g);
|
|
850
|
-
NODE_TO_CONTAINER_G.set(this.element, this._containerG);
|
|
851
|
-
ELEMENT_TO_REF.set(this.element, this.ref);
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
get context() {
|
|
855
|
-
return this._context;
|
|
856
|
-
}
|
|
857
|
-
get element() {
|
|
858
|
-
return this.context && this.context.element;
|
|
859
|
-
}
|
|
860
|
-
get board() {
|
|
861
|
-
return this.context && this.context.board;
|
|
862
|
-
}
|
|
863
|
-
get selected() {
|
|
864
|
-
return this.context && this.context.selected;
|
|
865
|
-
}
|
|
866
|
-
getContainerG() {
|
|
867
|
-
return this._containerG;
|
|
868
|
-
}
|
|
869
|
-
getElementG() {
|
|
870
|
-
return this._g;
|
|
871
|
-
}
|
|
872
|
-
constructor(ref) {
|
|
873
|
-
this.ref = ref;
|
|
874
|
-
this.viewContainerRef = inject(ViewContainerRef);
|
|
875
|
-
this.cdr = inject(ChangeDetectorRef);
|
|
876
|
-
this.initialized = false;
|
|
877
|
-
}
|
|
878
|
-
ngOnInit() {
|
|
879
|
-
if (this.element.type) {
|
|
880
|
-
this.getContainerG().setAttribute(`plait-${this.element.type}`, 'true');
|
|
881
|
-
}
|
|
882
|
-
if (this.hasChildren) {
|
|
883
|
-
if (PlaitElement.isRootElement(this.element)) {
|
|
884
|
-
this._rootContainerG = this._containerG;
|
|
885
|
-
}
|
|
886
|
-
else {
|
|
887
|
-
const path = PlaitBoard.findPath(this.board, this.element);
|
|
888
|
-
const rootNode = PlaitNode.get(this.board, path.slice(0, 1));
|
|
889
|
-
this._rootContainerG = PlaitElement.getContainerG(rootNode, { suppressThrow: false });
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
this.getContainerG().setAttribute('plait-data-id', this.element.id);
|
|
893
|
-
this.initialized = true;
|
|
894
|
-
}
|
|
895
|
-
initializeListRender() {
|
|
896
|
-
if (this.hasChildren) {
|
|
897
|
-
this.listRender = new ListRender(this.board, this.viewContainerRef);
|
|
898
|
-
if (this.board.isExpanded(this.element)) {
|
|
899
|
-
this.listRender.initialize(this.element.children, this.initializeChildrenContext());
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
getRef() {
|
|
904
|
-
return this.ref;
|
|
905
|
-
}
|
|
906
|
-
updateListRender() {
|
|
907
|
-
if (this.hasChildren) {
|
|
908
|
-
if (!this.listRender) {
|
|
909
|
-
throw new Error('incorrectly initialize list render');
|
|
910
|
-
}
|
|
911
|
-
if (this.board.isExpanded(this.element)) {
|
|
912
|
-
this.listRender.update(this.element.children, this.initializeChildrenContext());
|
|
913
|
-
}
|
|
914
|
-
else {
|
|
915
|
-
if (this.listRender.initialized) {
|
|
916
|
-
this.listRender.destroy();
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
initializeChildrenContext() {
|
|
922
|
-
if (!this._rootContainerG) {
|
|
923
|
-
throw new Error('can not resolve root container g');
|
|
924
|
-
}
|
|
925
|
-
return {
|
|
926
|
-
board: this.board,
|
|
927
|
-
parent: this.element,
|
|
928
|
-
parentG: this._rootContainerG
|
|
929
|
-
};
|
|
930
|
-
}
|
|
931
|
-
ngOnDestroy() {
|
|
932
|
-
if (ELEMENT_TO_COMPONENT.get(this.element) === this) {
|
|
933
|
-
ELEMENT_TO_COMPONENT.delete(this.element);
|
|
934
|
-
}
|
|
935
|
-
if (NODE_TO_G.get(this.element) === this._g) {
|
|
936
|
-
NODE_TO_G.delete(this.element);
|
|
937
|
-
}
|
|
938
|
-
if (NODE_TO_CONTAINER_G.get(this.element) === this._containerG) {
|
|
939
|
-
NODE_TO_CONTAINER_G.delete(this.element);
|
|
940
|
-
}
|
|
941
|
-
if (ELEMENT_TO_REF.get(this.element) === this.ref) {
|
|
942
|
-
ELEMENT_TO_REF.set(this.element, this.ref);
|
|
943
|
-
}
|
|
944
|
-
removeSelectedElement(this.board, this.element);
|
|
945
|
-
this.getContainerG().remove();
|
|
946
|
-
}
|
|
947
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: PlaitPluginElementComponent, deps: "invalid", target: i0.ɵɵFactoryTarget.Directive }); }
|
|
948
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: PlaitPluginElementComponent, inputs: { context: "context" }, ngImport: i0 }); }
|
|
949
|
-
}
|
|
950
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: PlaitPluginElementComponent, decorators: [{
|
|
951
|
-
type: Directive
|
|
952
|
-
}], ctorParameters: () => [{ type: undefined }], propDecorators: { context: [{
|
|
953
|
-
type: Input
|
|
954
|
-
}] } });
|
|
955
|
-
const ELEMENT_TO_COMPONENT = new WeakMap();
|
|
200
|
+
};
|
|
956
201
|
|
|
957
202
|
// https://stackoverflow.com/a/6853926/232122
|
|
958
203
|
function distanceBetweenPointAndSegment(x, y, x1, y1, x2, y2) {
|
|
@@ -1246,79 +491,310 @@ function getVectorFromPointAndSlope(x, y, slope) {
|
|
|
1246
491
|
if (y < 0) {
|
|
1247
492
|
vector = [-vector[0], -vector[1]];
|
|
1248
493
|
}
|
|
1249
|
-
return vector;
|
|
494
|
+
return vector;
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* The DOM likes values to be fixed to 3 decimal places
|
|
498
|
+
*/
|
|
499
|
+
function toDomPrecision(v) {
|
|
500
|
+
return +v.toFixed(4);
|
|
501
|
+
}
|
|
502
|
+
function toFixed(v) {
|
|
503
|
+
return +v.toFixed(2);
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Whether two numbers numbers a and b are approximately equal.
|
|
507
|
+
*
|
|
508
|
+
* @param a - The first point.
|
|
509
|
+
* @param b - The second point.
|
|
510
|
+
* @public
|
|
511
|
+
*/
|
|
512
|
+
function approximately(a, b, precision = 0.000001) {
|
|
513
|
+
return Math.abs(a - b) <= precision;
|
|
514
|
+
}
|
|
515
|
+
// https://medium.com/@steveruiz/find-the-points-where-a-line-segment-intercepts-an-angled-ellipse-in-javascript-typescript-e451524beece
|
|
516
|
+
function getCrossingPointsBetweenEllipseAndSegment(startPoint, endPoint, cx, cy, rx, ry, segment_only = true) {
|
|
517
|
+
// If the ellipse or line segment are empty, return no tValues.
|
|
518
|
+
if (rx === 0 || ry === 0 || (startPoint[0] === endPoint[0] && startPoint[1] === endPoint[1])) {
|
|
519
|
+
return [];
|
|
520
|
+
}
|
|
521
|
+
rx = rx < 0 ? rx : -rx;
|
|
522
|
+
ry = ry < 0 ? ry : -ry;
|
|
523
|
+
startPoint[0] -= cx;
|
|
524
|
+
startPoint[1] -= cy;
|
|
525
|
+
endPoint[0] -= cx;
|
|
526
|
+
endPoint[1] -= cy;
|
|
527
|
+
// Calculate the quadratic parameters.
|
|
528
|
+
var A = ((endPoint[0] - startPoint[0]) * (endPoint[0] - startPoint[0])) / rx / rx +
|
|
529
|
+
((endPoint[1] - startPoint[1]) * (endPoint[1] - startPoint[1])) / ry / ry;
|
|
530
|
+
var B = (2 * startPoint[0] * (endPoint[0] - startPoint[0])) / rx / rx + (2 * startPoint[1] * (endPoint[1] - startPoint[1])) / ry / ry;
|
|
531
|
+
var C = (startPoint[0] * startPoint[0]) / rx / rx + (startPoint[1] * startPoint[1]) / ry / ry - 1;
|
|
532
|
+
// Make a list of t values (normalized points on the line where intersections occur).
|
|
533
|
+
var tValues = [];
|
|
534
|
+
// Calculate the discriminant.
|
|
535
|
+
var discriminant = B * B - 4 * A * C;
|
|
536
|
+
if (discriminant === 0) {
|
|
537
|
+
// One real solution.
|
|
538
|
+
tValues.push(-B / 2 / A);
|
|
539
|
+
}
|
|
540
|
+
else if (discriminant > 0) {
|
|
541
|
+
// Two real solutions.
|
|
542
|
+
tValues.push((-B + Math.sqrt(discriminant)) / 2 / A);
|
|
543
|
+
tValues.push((-B - Math.sqrt(discriminant)) / 2 / A);
|
|
544
|
+
}
|
|
545
|
+
return (tValues
|
|
546
|
+
// Filter to only points that are on the segment.
|
|
547
|
+
.filter(t => !segment_only || (t >= 0 && t <= 1))
|
|
548
|
+
// Solve for points.
|
|
549
|
+
.map(t => [startPoint[0] + (endPoint[0] - startPoint[0]) * t + cx, startPoint[1] + (endPoint[1] - startPoint[1]) * t + cy]));
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
function isInPlaitBoard(board, x, y) {
|
|
553
|
+
const plaitBoardElement = PlaitBoard.getBoardContainer(board);
|
|
554
|
+
const plaitBoardRect = plaitBoardElement.getBoundingClientRect();
|
|
555
|
+
const distances = distanceBetweenPointAndRectangle(x, y, plaitBoardRect);
|
|
556
|
+
return distances === 0;
|
|
557
|
+
}
|
|
558
|
+
function getRealScrollBarWidth(board) {
|
|
559
|
+
const { hideScrollbar } = board.options;
|
|
560
|
+
let scrollBarWidth = 0;
|
|
561
|
+
if (!hideScrollbar) {
|
|
562
|
+
const viewportContainer = PlaitBoard.getViewportContainer(board);
|
|
563
|
+
scrollBarWidth = viewportContainer.offsetWidth - viewportContainer.clientWidth;
|
|
564
|
+
}
|
|
565
|
+
return scrollBarWidth;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* @license
|
|
570
|
+
* Copyright Google LLC All Rights Reserved.
|
|
571
|
+
*
|
|
572
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
573
|
+
* found in the LICENSE file at https://angular.io/license
|
|
574
|
+
*/
|
|
575
|
+
const MAC_ENTER = 3;
|
|
576
|
+
const BACKSPACE = 8;
|
|
577
|
+
const TAB = 9;
|
|
578
|
+
const NUM_CENTER = 12;
|
|
579
|
+
const ENTER = 13;
|
|
580
|
+
const SHIFT = 16;
|
|
581
|
+
const CONTROL = 17;
|
|
582
|
+
const ALT = 18;
|
|
583
|
+
const PAUSE = 19;
|
|
584
|
+
const CAPS_LOCK = 20;
|
|
585
|
+
const ESCAPE = 27;
|
|
586
|
+
const SPACE = 32;
|
|
587
|
+
const PAGE_UP = 33;
|
|
588
|
+
const PAGE_DOWN = 34;
|
|
589
|
+
const END = 35;
|
|
590
|
+
const HOME = 36;
|
|
591
|
+
const LEFT_ARROW = 37;
|
|
592
|
+
const UP_ARROW = 38;
|
|
593
|
+
const RIGHT_ARROW = 39;
|
|
594
|
+
const DOWN_ARROW = 40;
|
|
595
|
+
const PLUS_SIGN = 43;
|
|
596
|
+
const PRINT_SCREEN = 44;
|
|
597
|
+
const INSERT = 45;
|
|
598
|
+
const DELETE = 46;
|
|
599
|
+
const ZERO = 48;
|
|
600
|
+
const ONE = 49;
|
|
601
|
+
const TWO = 50;
|
|
602
|
+
const THREE = 51;
|
|
603
|
+
const FOUR = 52;
|
|
604
|
+
const FIVE = 53;
|
|
605
|
+
const SIX = 54;
|
|
606
|
+
const SEVEN = 55;
|
|
607
|
+
const EIGHT = 56;
|
|
608
|
+
const NINE = 57;
|
|
609
|
+
const FF_SEMICOLON = 59; // Firefox (Gecko) fires this for semicolon instead of 186
|
|
610
|
+
const FF_EQUALS = 61; // Firefox (Gecko) fires this for equals instead of 187
|
|
611
|
+
const QUESTION_MARK = 63;
|
|
612
|
+
const AT_SIGN = 64;
|
|
613
|
+
const A = 65;
|
|
614
|
+
const B = 66;
|
|
615
|
+
const C = 67;
|
|
616
|
+
const D = 68;
|
|
617
|
+
const E = 69;
|
|
618
|
+
const F = 70;
|
|
619
|
+
const G = 71;
|
|
620
|
+
const H = 72;
|
|
621
|
+
const I = 73;
|
|
622
|
+
const J = 74;
|
|
623
|
+
const K = 75;
|
|
624
|
+
const L = 76;
|
|
625
|
+
const M = 77;
|
|
626
|
+
const N = 78;
|
|
627
|
+
const O = 79;
|
|
628
|
+
const P = 80;
|
|
629
|
+
const Q = 81;
|
|
630
|
+
const R = 82;
|
|
631
|
+
const S = 83;
|
|
632
|
+
const T = 84;
|
|
633
|
+
const U = 85;
|
|
634
|
+
const V = 86;
|
|
635
|
+
const W = 87;
|
|
636
|
+
const X = 88;
|
|
637
|
+
const Y = 89;
|
|
638
|
+
const Z = 90;
|
|
639
|
+
const META = 91; // WIN_KEY_LEFT
|
|
640
|
+
const MAC_WK_CMD_LEFT = 91;
|
|
641
|
+
const MAC_WK_CMD_RIGHT = 93;
|
|
642
|
+
const CONTEXT_MENU = 93;
|
|
643
|
+
const NUMPAD_ZERO = 96;
|
|
644
|
+
const NUMPAD_ONE = 97;
|
|
645
|
+
const NUMPAD_TWO = 98;
|
|
646
|
+
const NUMPAD_THREE = 99;
|
|
647
|
+
const NUMPAD_FOUR = 100;
|
|
648
|
+
const NUMPAD_FIVE = 101;
|
|
649
|
+
const NUMPAD_SIX = 102;
|
|
650
|
+
const NUMPAD_SEVEN = 103;
|
|
651
|
+
const NUMPAD_EIGHT = 104;
|
|
652
|
+
const NUMPAD_NINE = 105;
|
|
653
|
+
const NUMPAD_MULTIPLY = 106;
|
|
654
|
+
const NUMPAD_PLUS = 107;
|
|
655
|
+
const NUMPAD_MINUS = 109;
|
|
656
|
+
const NUMPAD_PERIOD = 110;
|
|
657
|
+
const NUMPAD_DIVIDE = 111;
|
|
658
|
+
const F1 = 112;
|
|
659
|
+
const F2 = 113;
|
|
660
|
+
const F3 = 114;
|
|
661
|
+
const F4 = 115;
|
|
662
|
+
const F5 = 116;
|
|
663
|
+
const F6 = 117;
|
|
664
|
+
const F7 = 118;
|
|
665
|
+
const F8 = 119;
|
|
666
|
+
const F9 = 120;
|
|
667
|
+
const F10 = 121;
|
|
668
|
+
const F11 = 122;
|
|
669
|
+
const F12 = 123;
|
|
670
|
+
const NUM_LOCK = 144;
|
|
671
|
+
const SCROLL_LOCK = 145;
|
|
672
|
+
const FIRST_MEDIA = 166;
|
|
673
|
+
const FF_MINUS = 173;
|
|
674
|
+
const MUTE = 173; // Firefox (Gecko) fires 181 for MUTE
|
|
675
|
+
const VOLUME_DOWN = 174; // Firefox (Gecko) fires 182 for VOLUME_DOWN
|
|
676
|
+
const VOLUME_UP = 175; // Firefox (Gecko) fires 183 for VOLUME_UP
|
|
677
|
+
const FF_MUTE = 181;
|
|
678
|
+
const FF_VOLUME_DOWN = 182;
|
|
679
|
+
const LAST_MEDIA = 183;
|
|
680
|
+
const FF_VOLUME_UP = 183;
|
|
681
|
+
const SEMICOLON = 186; // Firefox (Gecko) fires 59 for SEMICOLON
|
|
682
|
+
const EQUALS = 187; // Firefox (Gecko) fires 61 for EQUALS
|
|
683
|
+
const COMMA = 188;
|
|
684
|
+
const DASH = 189; // Firefox (Gecko) fires 173 for DASH/MINUS
|
|
685
|
+
const PERIOD = 190;
|
|
686
|
+
const SLASH = 191;
|
|
687
|
+
const APOSTROPHE = 192;
|
|
688
|
+
const TILDE = 192;
|
|
689
|
+
const OPEN_SQUARE_BRACKET = 219;
|
|
690
|
+
const BACKSLASH = 220;
|
|
691
|
+
const CLOSE_SQUARE_BRACKET = 221;
|
|
692
|
+
const SINGLE_QUOTE = 222;
|
|
693
|
+
const MAC_META = 224;
|
|
694
|
+
|
|
695
|
+
var ResizeCursorClass;
|
|
696
|
+
(function (ResizeCursorClass) {
|
|
697
|
+
ResizeCursorClass["ew"] = "ew-resize";
|
|
698
|
+
ResizeCursorClass["ns"] = "ns-resize";
|
|
699
|
+
ResizeCursorClass["nesw"] = "nesw-resize";
|
|
700
|
+
ResizeCursorClass["nwse"] = "nwse-resize";
|
|
701
|
+
})(ResizeCursorClass || (ResizeCursorClass = {}));
|
|
702
|
+
var CursorClass;
|
|
703
|
+
(function (CursorClass) {
|
|
704
|
+
CursorClass["crosshair"] = "crosshair";
|
|
705
|
+
})(CursorClass || (CursorClass = {}));
|
|
706
|
+
const RESIZE_CURSORS = [ResizeCursorClass.ns, ResizeCursorClass.nesw, ResizeCursorClass.ew, ResizeCursorClass.nwse];
|
|
707
|
+
|
|
708
|
+
const ATTACHED_ELEMENT_CLASS_NAME = 'plait-board-attached';
|
|
709
|
+
const ACTIVE_STROKE_WIDTH = 1;
|
|
710
|
+
const SNAPPING_STROKE_WIDTH = 2;
|
|
711
|
+
const SELECTION_RECTANGLE_CLASS_NAME = 'selection-rectangle';
|
|
712
|
+
|
|
713
|
+
const HOST_CLASS_NAME = 'plait-board-container';
|
|
714
|
+
const ACTIVE_MOVING_CLASS_NAME = 'active-with-moving';
|
|
715
|
+
const ROTATE_HANDLE_CLASS_NAME = 'rotate-handle';
|
|
716
|
+
const RESIZE_HANDLE_CLASS_NAME = 'resize-handle';
|
|
717
|
+
const SCROLL_BAR_WIDTH = 20;
|
|
718
|
+
const MAX_RADIUS = 16;
|
|
719
|
+
const POINTER_BUTTON = {
|
|
720
|
+
MAIN: 0,
|
|
721
|
+
WHEEL: 1,
|
|
722
|
+
SECONDARY: 2,
|
|
723
|
+
TOUCH: -1
|
|
724
|
+
};
|
|
725
|
+
const PRESS_AND_MOVE_BUFFER = 3;
|
|
726
|
+
const HIT_DISTANCE_BUFFER = 5;
|
|
727
|
+
|
|
728
|
+
const NS = 'http://www.w3.org/2000/svg';
|
|
729
|
+
function createG() {
|
|
730
|
+
const newG = document.createElementNS(NS, 'g');
|
|
731
|
+
return newG;
|
|
732
|
+
}
|
|
733
|
+
function createPath() {
|
|
734
|
+
const newG = document.createElementNS(NS, 'path');
|
|
735
|
+
return newG;
|
|
736
|
+
}
|
|
737
|
+
function createRect(rectangle, options) {
|
|
738
|
+
const rect = document.createElementNS(NS, 'rect');
|
|
739
|
+
rect.setAttribute('x', `${rectangle.x}`);
|
|
740
|
+
rect.setAttribute('y', `${rectangle.y}`);
|
|
741
|
+
rect.setAttribute('width', `${rectangle.width}`);
|
|
742
|
+
rect.setAttribute('height', `${rectangle.height}`);
|
|
743
|
+
for (let key in options) {
|
|
744
|
+
const optionKey = key;
|
|
745
|
+
rect.setAttribute(key, `${options[optionKey]}`);
|
|
746
|
+
}
|
|
747
|
+
return rect;
|
|
1250
748
|
}
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
749
|
+
const setStrokeLinecap = (g, value) => {
|
|
750
|
+
g.setAttribute('stroke-linecap', value);
|
|
751
|
+
};
|
|
752
|
+
const setPathStrokeLinecap = (g, value) => {
|
|
753
|
+
g.querySelectorAll('path').forEach(path => {
|
|
754
|
+
path.setAttribute('stroke-linecap', value);
|
|
755
|
+
});
|
|
756
|
+
};
|
|
757
|
+
function createMask() {
|
|
758
|
+
return document.createElementNS(NS, 'mask');
|
|
1256
759
|
}
|
|
1257
|
-
function
|
|
1258
|
-
|
|
760
|
+
function createSVG() {
|
|
761
|
+
const svg = document.createElementNS(NS, 'svg');
|
|
762
|
+
return svg;
|
|
763
|
+
}
|
|
764
|
+
function createText(x, y, fill, textContent) {
|
|
765
|
+
var text = document.createElementNS(NS, 'text');
|
|
766
|
+
text.setAttribute('x', `${x}`);
|
|
767
|
+
text.setAttribute('y', `${y}`);
|
|
768
|
+
text.setAttribute('fill', fill);
|
|
769
|
+
text.textContent = textContent;
|
|
770
|
+
return text;
|
|
1259
771
|
}
|
|
1260
772
|
/**
|
|
1261
|
-
*
|
|
1262
|
-
*
|
|
1263
|
-
* @param a - The first point.
|
|
1264
|
-
* @param b - The second point.
|
|
1265
|
-
* @public
|
|
773
|
+
* Check if a DOM node is an element node.
|
|
1266
774
|
*/
|
|
1267
|
-
|
|
1268
|
-
return
|
|
1269
|
-
}
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
endPoint[1] -= cy;
|
|
1282
|
-
// Calculate the quadratic parameters.
|
|
1283
|
-
var A = ((endPoint[0] - startPoint[0]) * (endPoint[0] - startPoint[0])) / rx / rx +
|
|
1284
|
-
((endPoint[1] - startPoint[1]) * (endPoint[1] - startPoint[1])) / ry / ry;
|
|
1285
|
-
var B = (2 * startPoint[0] * (endPoint[0] - startPoint[0])) / rx / rx + (2 * startPoint[1] * (endPoint[1] - startPoint[1])) / ry / ry;
|
|
1286
|
-
var C = (startPoint[0] * startPoint[0]) / rx / rx + (startPoint[1] * startPoint[1]) / ry / ry - 1;
|
|
1287
|
-
// Make a list of t values (normalized points on the line where intersections occur).
|
|
1288
|
-
var tValues = [];
|
|
1289
|
-
// Calculate the discriminant.
|
|
1290
|
-
var discriminant = B * B - 4 * A * C;
|
|
1291
|
-
if (discriminant === 0) {
|
|
1292
|
-
// One real solution.
|
|
1293
|
-
tValues.push(-B / 2 / A);
|
|
1294
|
-
}
|
|
1295
|
-
else if (discriminant > 0) {
|
|
1296
|
-
// Two real solutions.
|
|
1297
|
-
tValues.push((-B + Math.sqrt(discriminant)) / 2 / A);
|
|
1298
|
-
tValues.push((-B - Math.sqrt(discriminant)) / 2 / A);
|
|
1299
|
-
}
|
|
1300
|
-
return (tValues
|
|
1301
|
-
// Filter to only points that are on the segment.
|
|
1302
|
-
.filter(t => !segment_only || (t >= 0 && t <= 1))
|
|
1303
|
-
// Solve for points.
|
|
1304
|
-
.map(t => [startPoint[0] + (endPoint[0] - startPoint[0]) * t + cx, startPoint[1] + (endPoint[1] - startPoint[1]) * t + cy]));
|
|
1305
|
-
}
|
|
1306
|
-
|
|
1307
|
-
function isInPlaitBoard(board, x, y) {
|
|
1308
|
-
const plaitBoardElement = PlaitBoard.getBoardContainer(board);
|
|
1309
|
-
const plaitBoardRect = plaitBoardElement.getBoundingClientRect();
|
|
1310
|
-
const distances = distanceBetweenPointAndRectangle(x, y, plaitBoardRect);
|
|
1311
|
-
return distances === 0;
|
|
1312
|
-
}
|
|
1313
|
-
function getRealScrollBarWidth(board) {
|
|
1314
|
-
const { hideScrollbar } = board.options;
|
|
1315
|
-
let scrollBarWidth = 0;
|
|
1316
|
-
if (!hideScrollbar) {
|
|
1317
|
-
const viewportContainer = PlaitBoard.getViewportContainer(board);
|
|
1318
|
-
scrollBarWidth = viewportContainer.offsetWidth - viewportContainer.clientWidth;
|
|
775
|
+
const isDOMElement = (value) => {
|
|
776
|
+
return isDOMNode(value) && value.nodeType === 1;
|
|
777
|
+
};
|
|
778
|
+
/**
|
|
779
|
+
* Check if a value is a DOM node.
|
|
780
|
+
*/
|
|
781
|
+
const isDOMNode = (value) => {
|
|
782
|
+
return value instanceof window.Node;
|
|
783
|
+
};
|
|
784
|
+
const hasInputOrTextareaTarget = (target) => {
|
|
785
|
+
if (isDOMElement(target)) {
|
|
786
|
+
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {
|
|
787
|
+
return true;
|
|
788
|
+
}
|
|
1319
789
|
}
|
|
1320
|
-
return
|
|
1321
|
-
}
|
|
790
|
+
return false;
|
|
791
|
+
};
|
|
792
|
+
const isSecondaryPointer = (event) => {
|
|
793
|
+
return event.button === POINTER_BUTTON.SECONDARY;
|
|
794
|
+
};
|
|
795
|
+
const isMainPointer = (event) => {
|
|
796
|
+
return event.button === POINTER_BUTTON.MAIN;
|
|
797
|
+
};
|
|
1322
798
|
|
|
1323
799
|
function createForeignObject(x, y, width, height) {
|
|
1324
800
|
var newForeignObject = document.createElementNS(NS, 'foreignObject');
|
|
@@ -1593,17 +1069,179 @@ const hotkeys = {
|
|
|
1593
1069
|
isUndo: create('undo'),
|
|
1594
1070
|
isShift: create('shift')
|
|
1595
1071
|
};
|
|
1596
|
-
|
|
1597
|
-
function idCreator(length = 5) {
|
|
1598
|
-
// remove numeral
|
|
1599
|
-
const $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz'; /**** Easily confusing characters are removed by default oOLl,9gq,Vv,Uu,I1****/
|
|
1600
|
-
const maxPosition = $chars.length;
|
|
1601
|
-
let key = '';
|
|
1602
|
-
for (let i = 0; i < length; i++) {
|
|
1603
|
-
key += $chars.charAt(Math.floor(Math.random() * maxPosition));
|
|
1072
|
+
|
|
1073
|
+
function idCreator(length = 5) {
|
|
1074
|
+
// remove numeral
|
|
1075
|
+
const $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz'; /**** Easily confusing characters are removed by default oOLl,9gq,Vv,Uu,I1****/
|
|
1076
|
+
const maxPosition = $chars.length;
|
|
1077
|
+
let key = '';
|
|
1078
|
+
for (let i = 0; i < length; i++) {
|
|
1079
|
+
key += $chars.charAt(Math.floor(Math.random() * maxPosition));
|
|
1080
|
+
}
|
|
1081
|
+
return key;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
function depthFirstRecursion(node, callback, recursion, isReverse) {
|
|
1085
|
+
if (!recursion || recursion(node)) {
|
|
1086
|
+
let children = [];
|
|
1087
|
+
if (node.children) {
|
|
1088
|
+
children = [...node.children];
|
|
1089
|
+
}
|
|
1090
|
+
children = isReverse ? children.reverse() : children;
|
|
1091
|
+
children.forEach(child => {
|
|
1092
|
+
depthFirstRecursion(child, callback, recursion);
|
|
1093
|
+
});
|
|
1094
|
+
}
|
|
1095
|
+
callback(node);
|
|
1096
|
+
}
|
|
1097
|
+
const getIsRecursionFunc = (board) => {
|
|
1098
|
+
return (element) => {
|
|
1099
|
+
if (PlaitBoard.isBoard(element) || board.isRecursion(element)) {
|
|
1100
|
+
return true;
|
|
1101
|
+
}
|
|
1102
|
+
else {
|
|
1103
|
+
return false;
|
|
1104
|
+
}
|
|
1105
|
+
};
|
|
1106
|
+
};
|
|
1107
|
+
|
|
1108
|
+
const SELECTION_BORDER_COLOR = '#6698FF';
|
|
1109
|
+
const SELECTION_FILL_COLOR = '#6698FF25'; // opacity 0.25
|
|
1110
|
+
const Selection = {
|
|
1111
|
+
isCollapsed(selection) {
|
|
1112
|
+
if (selection.anchor[0] == selection.focus[0] && selection.anchor[1] === selection.focus[1]) {
|
|
1113
|
+
return true;
|
|
1114
|
+
}
|
|
1115
|
+
else {
|
|
1116
|
+
return false;
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
1120
|
+
|
|
1121
|
+
const sortElements = (board, elements, ascendingOrder = true) => {
|
|
1122
|
+
return [...elements].sort((a, b) => {
|
|
1123
|
+
const pathA = PlaitBoard.findPath(board, a);
|
|
1124
|
+
const pathB = PlaitBoard.findPath(board, b);
|
|
1125
|
+
return ascendingOrder ? pathA[0] - pathB[0] : pathB[0] - pathA[0];
|
|
1126
|
+
});
|
|
1127
|
+
};
|
|
1128
|
+
|
|
1129
|
+
var PlaitPluginKey;
|
|
1130
|
+
(function (PlaitPluginKey) {
|
|
1131
|
+
PlaitPluginKey["withSelection"] = "withSelection";
|
|
1132
|
+
})(PlaitPluginKey || (PlaitPluginKey = {}));
|
|
1133
|
+
|
|
1134
|
+
const getHitElementsBySelection = (board, selection, match = () => true) => {
|
|
1135
|
+
const newSelection = selection || board.selection;
|
|
1136
|
+
const rectangleHitElements = [];
|
|
1137
|
+
if (!newSelection) {
|
|
1138
|
+
return [];
|
|
1139
|
+
}
|
|
1140
|
+
const isCollapsed = Selection.isCollapsed(newSelection);
|
|
1141
|
+
if (isCollapsed) {
|
|
1142
|
+
const hitElement = getHitElementByPoint(board, newSelection.anchor, match);
|
|
1143
|
+
if (hitElement) {
|
|
1144
|
+
return [hitElement];
|
|
1145
|
+
}
|
|
1146
|
+
else {
|
|
1147
|
+
return [];
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
depthFirstRecursion(board, node => {
|
|
1151
|
+
if (!PlaitBoard.isBoard(node) && match(node) && board.isRectangleHit(node, newSelection)) {
|
|
1152
|
+
rectangleHitElements.push(node);
|
|
1153
|
+
}
|
|
1154
|
+
}, getIsRecursionFunc(board), true);
|
|
1155
|
+
return rectangleHitElements;
|
|
1156
|
+
};
|
|
1157
|
+
const getHitElementByPoint = (board, point, match = () => true) => {
|
|
1158
|
+
let hitElement = undefined;
|
|
1159
|
+
let hitInsideElement = undefined;
|
|
1160
|
+
depthFirstRecursion(board, node => {
|
|
1161
|
+
if (hitElement) {
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
if (PlaitBoard.isBoard(node) || !match(node) || !PlaitElement.hasMounted(node)) {
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
if (board.isHit(node, point)) {
|
|
1168
|
+
hitElement = node;
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
/**
|
|
1172
|
+
* 需要增加场景测试
|
|
1173
|
+
* hitInsideElement 存的是第一个符合 isInsidePoint 的元素
|
|
1174
|
+
* 当有元素符合 isHit 时结束遍历,并返回 hitElement
|
|
1175
|
+
* 当所有元素都不符合 isHit ,则返回第一个符合 isInsidePoint 的元素
|
|
1176
|
+
* 这样保证最上面的元素优先被探测到;
|
|
1177
|
+
*/
|
|
1178
|
+
if (!hitInsideElement && board.isInsidePoint(node, point)) {
|
|
1179
|
+
hitInsideElement = node;
|
|
1180
|
+
}
|
|
1181
|
+
}, getIsRecursionFunc(board), true);
|
|
1182
|
+
return hitElement || hitInsideElement;
|
|
1183
|
+
};
|
|
1184
|
+
const getHitSelectedElements = (board, point) => {
|
|
1185
|
+
const selectedElements = getSelectedElements(board);
|
|
1186
|
+
const targetRectangle = selectedElements.length > 0 && getRectangleByElements(board, selectedElements, false);
|
|
1187
|
+
const isInTargetRectangle = targetRectangle && RectangleClient.isPointInRectangle(targetRectangle, point);
|
|
1188
|
+
if (isInTargetRectangle) {
|
|
1189
|
+
return selectedElements;
|
|
1190
|
+
}
|
|
1191
|
+
else {
|
|
1192
|
+
return [];
|
|
1193
|
+
}
|
|
1194
|
+
};
|
|
1195
|
+
const cacheSelectedElements = (board, selectedElements) => {
|
|
1196
|
+
const sortedElements = sortElements(board, selectedElements);
|
|
1197
|
+
BOARD_TO_SELECTED_ELEMENT.set(board, sortedElements);
|
|
1198
|
+
};
|
|
1199
|
+
const getSelectedElements = (board) => {
|
|
1200
|
+
return BOARD_TO_SELECTED_ELEMENT.get(board) || [];
|
|
1201
|
+
};
|
|
1202
|
+
const addSelectedElement = (board, element) => {
|
|
1203
|
+
let elements = [];
|
|
1204
|
+
if (Array.isArray(element)) {
|
|
1205
|
+
elements.push(...element);
|
|
1206
|
+
}
|
|
1207
|
+
else {
|
|
1208
|
+
elements.push(element);
|
|
1209
|
+
}
|
|
1210
|
+
const selectedElements = getSelectedElements(board);
|
|
1211
|
+
cacheSelectedElements(board, [...selectedElements, ...elements]);
|
|
1212
|
+
};
|
|
1213
|
+
const removeSelectedElement = (board, element, isRemoveChildren = false) => {
|
|
1214
|
+
const selectedElements = getSelectedElements(board);
|
|
1215
|
+
if (selectedElements.includes(element)) {
|
|
1216
|
+
const targetElements = [];
|
|
1217
|
+
if (board.isRecursion(element) && isRemoveChildren) {
|
|
1218
|
+
depthFirstRecursion(element, node => {
|
|
1219
|
+
targetElements.push(node);
|
|
1220
|
+
}, node => board.isRecursion(node));
|
|
1221
|
+
}
|
|
1222
|
+
else {
|
|
1223
|
+
targetElements.push(element);
|
|
1224
|
+
}
|
|
1225
|
+
const newSelectedElements = selectedElements.filter(value => !targetElements.includes(value));
|
|
1226
|
+
cacheSelectedElements(board, newSelectedElements);
|
|
1604
1227
|
}
|
|
1605
|
-
|
|
1606
|
-
|
|
1228
|
+
};
|
|
1229
|
+
const clearSelectedElement = (board) => {
|
|
1230
|
+
cacheSelectedElements(board, []);
|
|
1231
|
+
};
|
|
1232
|
+
const isSelectedElement = (board, element) => {
|
|
1233
|
+
const selectedElements = getSelectedElements(board);
|
|
1234
|
+
return !!selectedElements.find(value => value === element);
|
|
1235
|
+
};
|
|
1236
|
+
const temporaryDisableSelection = (board) => {
|
|
1237
|
+
const currentOptions = board.getPluginOptions(PlaitPluginKey.withSelection);
|
|
1238
|
+
board.setPluginOptions(PlaitPluginKey.withSelection, {
|
|
1239
|
+
isDisabledSelect: true
|
|
1240
|
+
});
|
|
1241
|
+
setTimeout(() => {
|
|
1242
|
+
board.setPluginOptions(PlaitPluginKey.withSelection, { ...currentOptions });
|
|
1243
|
+
}, 0);
|
|
1244
|
+
};
|
|
1607
1245
|
|
|
1608
1246
|
/**
|
|
1609
1247
|
* drawRoundRectangle
|
|
@@ -4077,9 +3715,6 @@ const PlaitElement = {
|
|
|
4077
3715
|
return false;
|
|
4078
3716
|
}
|
|
4079
3717
|
},
|
|
4080
|
-
getComponent(value) {
|
|
4081
|
-
return ELEMENT_TO_COMPONENT.get(value);
|
|
4082
|
-
},
|
|
4083
3718
|
getElementRef(value) {
|
|
4084
3719
|
return ELEMENT_TO_REF.get(value);
|
|
4085
3720
|
},
|
|
@@ -4332,6 +3967,11 @@ function getRectangleByElements(board, elements, recursion) {
|
|
|
4332
3967
|
};
|
|
4333
3968
|
}
|
|
4334
3969
|
}
|
|
3970
|
+
function getBoundingRectangleByElements(board, elements, recursion) {
|
|
3971
|
+
const rectangle = getRectangleByElements(board, elements, recursion);
|
|
3972
|
+
const angle = getSelectionAngle(elements);
|
|
3973
|
+
return getRectangleByAngle(rectangle, angle) || rectangle;
|
|
3974
|
+
}
|
|
4335
3975
|
function getBoardRectangle(board) {
|
|
4336
3976
|
return getRectangleByElements(board, board.children, true);
|
|
4337
3977
|
}
|
|
@@ -4399,6 +4039,9 @@ const PlaitBoard = {
|
|
|
4399
4039
|
getHost(board) {
|
|
4400
4040
|
return BOARD_TO_HOST.get(board);
|
|
4401
4041
|
},
|
|
4042
|
+
getElementLowerHost(board) {
|
|
4043
|
+
return BOARD_TO_ELEMENT_HOST.get(board)?.lowerHost;
|
|
4044
|
+
},
|
|
4402
4045
|
getElementHost(board) {
|
|
4403
4046
|
return BOARD_TO_ELEMENT_HOST.get(board)?.host;
|
|
4404
4047
|
},
|
|
@@ -5606,70 +5249,277 @@ const withHotkey = (board) => {
|
|
|
5606
5249
|
BoardTransforms.updateZoom(board, board.viewport.zoom - 0.1);
|
|
5607
5250
|
return;
|
|
5608
5251
|
}
|
|
5609
|
-
if (isHotkey(['mod+0', 'mod+shift+0'], { byKey: true })(event)) {
|
|
5610
|
-
event.preventDefault();
|
|
5611
|
-
BoardTransforms.updateZoom(board, 1);
|
|
5612
|
-
return;
|
|
5252
|
+
if (isHotkey(['mod+0', 'mod+shift+0'], { byKey: true })(event)) {
|
|
5253
|
+
event.preventDefault();
|
|
5254
|
+
BoardTransforms.updateZoom(board, 1);
|
|
5255
|
+
return;
|
|
5256
|
+
}
|
|
5257
|
+
}
|
|
5258
|
+
globalKeyDown(event);
|
|
5259
|
+
};
|
|
5260
|
+
return board;
|
|
5261
|
+
};
|
|
5262
|
+
|
|
5263
|
+
class PlaitContextService {
|
|
5264
|
+
constructor() {
|
|
5265
|
+
this._stable = new Subject();
|
|
5266
|
+
this.uploadingFiles = [];
|
|
5267
|
+
}
|
|
5268
|
+
getUploadingFile(url) {
|
|
5269
|
+
return this.uploadingFiles.find(file => file.url === url);
|
|
5270
|
+
}
|
|
5271
|
+
setUploadingFile(file) {
|
|
5272
|
+
return this.uploadingFiles.push(file);
|
|
5273
|
+
}
|
|
5274
|
+
removeUploadingFile(fileEntry) {
|
|
5275
|
+
this.uploadingFiles = this.uploadingFiles.filter(file => file.url !== fileEntry.url);
|
|
5276
|
+
}
|
|
5277
|
+
onStable() {
|
|
5278
|
+
return this._stable.asObservable();
|
|
5279
|
+
}
|
|
5280
|
+
nextStable() {
|
|
5281
|
+
this._stable.next('');
|
|
5282
|
+
}
|
|
5283
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: PlaitContextService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5284
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: PlaitContextService }); }
|
|
5285
|
+
}
|
|
5286
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: PlaitContextService, decorators: [{
|
|
5287
|
+
type: Injectable
|
|
5288
|
+
}] });
|
|
5289
|
+
|
|
5290
|
+
function withRelatedFragment(board) {
|
|
5291
|
+
const { buildFragment } = board;
|
|
5292
|
+
board.buildFragment = (clipboardContext, rectangle, operationType, originData) => {
|
|
5293
|
+
let relatedFragment = board.getRelatedFragment(originData || []);
|
|
5294
|
+
if (relatedFragment) {
|
|
5295
|
+
if (originData?.length) {
|
|
5296
|
+
relatedFragment = relatedFragment.filter(item => !originData.map(element => element.id).includes(item.id));
|
|
5297
|
+
}
|
|
5298
|
+
if (relatedFragment.length) {
|
|
5299
|
+
if (!clipboardContext) {
|
|
5300
|
+
clipboardContext = createClipboardContext(WritableClipboardType.elements, relatedFragment, '');
|
|
5301
|
+
}
|
|
5302
|
+
else {
|
|
5303
|
+
clipboardContext = addClipboardContext(clipboardContext, {
|
|
5304
|
+
text: '',
|
|
5305
|
+
type: WritableClipboardType.elements,
|
|
5306
|
+
elements: relatedFragment
|
|
5307
|
+
});
|
|
5308
|
+
}
|
|
5309
|
+
}
|
|
5310
|
+
}
|
|
5311
|
+
return buildFragment(clipboardContext, rectangle, operationType, originData);
|
|
5312
|
+
};
|
|
5313
|
+
return board;
|
|
5314
|
+
}
|
|
5315
|
+
|
|
5316
|
+
class ListRender {
|
|
5317
|
+
constructor(board, viewContainerRef) {
|
|
5318
|
+
this.board = board;
|
|
5319
|
+
this.viewContainerRef = viewContainerRef;
|
|
5320
|
+
this.children = [];
|
|
5321
|
+
this.componentRefs = [];
|
|
5322
|
+
this.contexts = [];
|
|
5323
|
+
this.differ = null;
|
|
5324
|
+
this.initialized = false;
|
|
5325
|
+
}
|
|
5326
|
+
initialize(children, childrenContext) {
|
|
5327
|
+
this.initialized = true;
|
|
5328
|
+
this.children = children;
|
|
5329
|
+
children.forEach((descendant, index) => {
|
|
5330
|
+
NODE_TO_INDEX.set(descendant, index);
|
|
5331
|
+
NODE_TO_PARENT.set(descendant, childrenContext.parent);
|
|
5332
|
+
const context = getContext(this.board, descendant, index, childrenContext.parent);
|
|
5333
|
+
const componentType = getComponentType(this.board, context);
|
|
5334
|
+
const componentRef = createPluginComponent(componentType, context, this.viewContainerRef, childrenContext);
|
|
5335
|
+
this.componentRefs.push(componentRef);
|
|
5336
|
+
this.contexts.push(context);
|
|
5337
|
+
});
|
|
5338
|
+
const newDiffers = this.viewContainerRef.injector.get(IterableDiffers);
|
|
5339
|
+
this.differ = newDiffers.find(children).create(trackBy);
|
|
5340
|
+
this.differ.diff(children);
|
|
5341
|
+
}
|
|
5342
|
+
update(children, childrenContext) {
|
|
5343
|
+
if (!this.initialized) {
|
|
5344
|
+
this.initialize(children, childrenContext);
|
|
5345
|
+
return;
|
|
5346
|
+
}
|
|
5347
|
+
if (!this.differ) {
|
|
5348
|
+
throw new Error('Exception: Can not find differ ');
|
|
5349
|
+
}
|
|
5350
|
+
const { board, parent } = childrenContext;
|
|
5351
|
+
const diffResult = this.differ.diff(children);
|
|
5352
|
+
if (diffResult) {
|
|
5353
|
+
const newContexts = [];
|
|
5354
|
+
const newComponentRefs = [];
|
|
5355
|
+
let currentIndexForFirstElement = null;
|
|
5356
|
+
diffResult.forEachItem((record) => {
|
|
5357
|
+
NODE_TO_INDEX.set(record.item, record.currentIndex);
|
|
5358
|
+
NODE_TO_PARENT.set(record.item, childrenContext.parent);
|
|
5359
|
+
const previousContext = record.previousIndex === null ? undefined : this.contexts[record.previousIndex];
|
|
5360
|
+
const context = getContext(board, record.item, record.currentIndex, parent, previousContext);
|
|
5361
|
+
if (record.previousIndex === null) {
|
|
5362
|
+
const componentType = getComponentType(board, context);
|
|
5363
|
+
const componentRef = createPluginComponent(componentType, context, this.viewContainerRef, childrenContext);
|
|
5364
|
+
newContexts.push(context);
|
|
5365
|
+
newComponentRefs.push(componentRef);
|
|
5366
|
+
}
|
|
5367
|
+
else {
|
|
5368
|
+
const componentRef = this.componentRefs[record.previousIndex];
|
|
5369
|
+
componentRef.instance.context = context;
|
|
5370
|
+
newComponentRefs.push(componentRef);
|
|
5371
|
+
newContexts.push(context);
|
|
5372
|
+
}
|
|
5373
|
+
// item might has been changed, so need to compare the id
|
|
5374
|
+
if (record.item === this.children[0] || record.item.id === this.children[0]?.id) {
|
|
5375
|
+
currentIndexForFirstElement = record.currentIndex;
|
|
5376
|
+
}
|
|
5377
|
+
});
|
|
5378
|
+
diffResult.forEachOperation(record => {
|
|
5379
|
+
// removed
|
|
5380
|
+
if (record.currentIndex === null) {
|
|
5381
|
+
const componentRef = this.componentRefs[record.previousIndex];
|
|
5382
|
+
componentRef?.destroy();
|
|
5383
|
+
}
|
|
5384
|
+
// moved
|
|
5385
|
+
if (record.previousIndex !== null && record.currentIndex !== null) {
|
|
5386
|
+
mountOnItemMove(record.item, record.currentIndex, childrenContext, currentIndexForFirstElement);
|
|
5387
|
+
}
|
|
5388
|
+
});
|
|
5389
|
+
this.componentRefs = newComponentRefs;
|
|
5390
|
+
this.contexts = newContexts;
|
|
5391
|
+
this.children = children;
|
|
5392
|
+
}
|
|
5393
|
+
else {
|
|
5394
|
+
const newContexts = [];
|
|
5395
|
+
this.children.forEach((element, index) => {
|
|
5396
|
+
NODE_TO_INDEX.set(element, index);
|
|
5397
|
+
NODE_TO_PARENT.set(element, childrenContext.parent);
|
|
5398
|
+
const previousContext = this.contexts[index];
|
|
5399
|
+
const previousComponentRef = this.componentRefs[index];
|
|
5400
|
+
const context = getContext(board, element, index, parent, previousContext);
|
|
5401
|
+
previousComponentRef.instance.context = context;
|
|
5402
|
+
newContexts.push(context);
|
|
5403
|
+
});
|
|
5404
|
+
this.contexts = newContexts;
|
|
5405
|
+
}
|
|
5406
|
+
}
|
|
5407
|
+
destroy() {
|
|
5408
|
+
this.children.forEach((element, index) => {
|
|
5409
|
+
if (this.componentRefs[index]) {
|
|
5410
|
+
this.componentRefs[index].destroy();
|
|
5411
|
+
}
|
|
5412
|
+
});
|
|
5413
|
+
this.componentRefs = [];
|
|
5414
|
+
this.children = [];
|
|
5415
|
+
this.contexts = [];
|
|
5416
|
+
this.initialized = false;
|
|
5417
|
+
this.differ = null;
|
|
5418
|
+
}
|
|
5419
|
+
}
|
|
5420
|
+
const trackBy = (index, element) => {
|
|
5421
|
+
return element.id;
|
|
5422
|
+
};
|
|
5423
|
+
const createPluginComponent = (componentType, context, viewContainerRef, childrenContext) => {
|
|
5424
|
+
const componentRef = viewContainerRef.createComponent(componentType, { injector: viewContainerRef.injector });
|
|
5425
|
+
const instance = componentRef.instance;
|
|
5426
|
+
instance.context = context;
|
|
5427
|
+
componentRef.changeDetectorRef.detectChanges();
|
|
5428
|
+
const g = componentRef.instance.getContainerG();
|
|
5429
|
+
mountElementG(context.index, g, childrenContext);
|
|
5430
|
+
componentRef.instance.initializeListRender();
|
|
5431
|
+
return componentRef;
|
|
5432
|
+
};
|
|
5433
|
+
const getComponentType = (board, context) => {
|
|
5434
|
+
const result = board.drawElement(context);
|
|
5435
|
+
return result;
|
|
5436
|
+
};
|
|
5437
|
+
const getContext = (board, element, index, parent, previousContext) => {
|
|
5438
|
+
let isSelected = isSelectedElement(board, element);
|
|
5439
|
+
const previousElement = previousContext && previousContext.element;
|
|
5440
|
+
if (previousElement && previousElement !== element && isSelectedElement(board, previousElement)) {
|
|
5441
|
+
isSelected = true;
|
|
5442
|
+
removeSelectedElement(board, previousElement);
|
|
5443
|
+
addSelectedElement(board, element);
|
|
5444
|
+
}
|
|
5445
|
+
const context = {
|
|
5446
|
+
element: element,
|
|
5447
|
+
parent: parent,
|
|
5448
|
+
board: board,
|
|
5449
|
+
selected: isSelected,
|
|
5450
|
+
index
|
|
5451
|
+
};
|
|
5452
|
+
return context;
|
|
5453
|
+
};
|
|
5454
|
+
// the g depth of root element:[1]-[2]-[3]-[4]
|
|
5455
|
+
// the g depth of root element and children element(the [2] element has children):
|
|
5456
|
+
// [1]-
|
|
5457
|
+
// [2]([2-1-1][2-1-2][2-1][2-2][2-3-1][2-3-2][2-3][2])-
|
|
5458
|
+
// [3]-
|
|
5459
|
+
// [4]
|
|
5460
|
+
const mountElementG = (index, g, childrenContext,
|
|
5461
|
+
// for moving scene: the current index for first element before moving
|
|
5462
|
+
currentIndexForFirstElement = null) => {
|
|
5463
|
+
const { parent, parentG } = childrenContext;
|
|
5464
|
+
if (PlaitBoard.isBoard(parent)) {
|
|
5465
|
+
if (index > 0) {
|
|
5466
|
+
const previousElement = parent.children[index - 1];
|
|
5467
|
+
const previousContainerG = PlaitElement.getContainerG(previousElement, { suppressThrow: false });
|
|
5468
|
+
previousContainerG.insertAdjacentElement('afterend', g);
|
|
5469
|
+
}
|
|
5470
|
+
else {
|
|
5471
|
+
if (currentIndexForFirstElement !== null) {
|
|
5472
|
+
const firstElement = parent.children[currentIndexForFirstElement];
|
|
5473
|
+
const firstContainerG = firstElement && PlaitElement.getContainerG(firstElement, { suppressThrow: true });
|
|
5474
|
+
if (firstElement && firstContainerG) {
|
|
5475
|
+
parentG.insertBefore(g, firstContainerG);
|
|
5476
|
+
}
|
|
5477
|
+
else {
|
|
5478
|
+
throw new Error('fail to mount container on moving');
|
|
5479
|
+
}
|
|
5480
|
+
}
|
|
5481
|
+
else {
|
|
5482
|
+
parentG.append(g);
|
|
5613
5483
|
}
|
|
5614
5484
|
}
|
|
5615
|
-
globalKeyDown(event);
|
|
5616
|
-
};
|
|
5617
|
-
return board;
|
|
5618
|
-
};
|
|
5619
|
-
|
|
5620
|
-
class PlaitContextService {
|
|
5621
|
-
constructor() {
|
|
5622
|
-
this._stable = new Subject();
|
|
5623
|
-
this.uploadingFiles = [];
|
|
5624
|
-
}
|
|
5625
|
-
getUploadingFile(url) {
|
|
5626
|
-
return this.uploadingFiles.find(file => file.url === url);
|
|
5627
|
-
}
|
|
5628
|
-
setUploadingFile(file) {
|
|
5629
|
-
return this.uploadingFiles.push(file);
|
|
5630
|
-
}
|
|
5631
|
-
removeUploadingFile(fileEntry) {
|
|
5632
|
-
this.uploadingFiles = this.uploadingFiles.filter(file => file.url !== fileEntry.url);
|
|
5633
|
-
}
|
|
5634
|
-
onStable() {
|
|
5635
|
-
return this._stable.asObservable();
|
|
5636
|
-
}
|
|
5637
|
-
nextStable() {
|
|
5638
|
-
this._stable.next('');
|
|
5639
5485
|
}
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
}
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
}
|
|
5655
|
-
if (relatedFragment.length) {
|
|
5656
|
-
if (!clipboardContext) {
|
|
5657
|
-
clipboardContext = createClipboardContext(WritableClipboardType.elements, relatedFragment, '');
|
|
5486
|
+
else {
|
|
5487
|
+
if (index > 0) {
|
|
5488
|
+
const previousElement = parent.children[index - 1];
|
|
5489
|
+
const previousElementG = PlaitElement.getElementG(previousElement);
|
|
5490
|
+
previousElementG.insertAdjacentElement('afterend', g);
|
|
5491
|
+
}
|
|
5492
|
+
else {
|
|
5493
|
+
if (currentIndexForFirstElement) {
|
|
5494
|
+
const nextElement = parent.children[currentIndexForFirstElement];
|
|
5495
|
+
const nextPath = nextElement && PlaitBoard.findPath(childrenContext.board, nextElement);
|
|
5496
|
+
const first = nextPath && PlaitNode.first(childrenContext.board, nextPath);
|
|
5497
|
+
const firstContainerG = first && PlaitElement.getContainerG(first, { suppressThrow: false });
|
|
5498
|
+
if (firstContainerG) {
|
|
5499
|
+
parentG.insertBefore(g, firstContainerG);
|
|
5658
5500
|
}
|
|
5659
5501
|
else {
|
|
5660
|
-
|
|
5661
|
-
text: '',
|
|
5662
|
-
type: WritableClipboardType.elements,
|
|
5663
|
-
elements: relatedFragment
|
|
5664
|
-
});
|
|
5502
|
+
throw new Error('fail to mount container on moving');
|
|
5665
5503
|
}
|
|
5666
5504
|
}
|
|
5505
|
+
else {
|
|
5506
|
+
let parentElementG = PlaitElement.getElementG(parent);
|
|
5507
|
+
parentG.insertBefore(g, parentElementG);
|
|
5508
|
+
}
|
|
5667
5509
|
}
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
}
|
|
5510
|
+
}
|
|
5511
|
+
};
|
|
5512
|
+
const mountOnItemMove = (element, index, childrenContext, currentIndexForFirstElement) => {
|
|
5513
|
+
const containerG = PlaitElement.getContainerG(element, { suppressThrow: false });
|
|
5514
|
+
mountElementG(index, containerG, childrenContext, currentIndexForFirstElement);
|
|
5515
|
+
if (element.children && !PlaitElement.isRootElement(element)) {
|
|
5516
|
+
element.children.forEach((child, index) => {
|
|
5517
|
+
mountOnItemMove(child, index, { ...childrenContext, parent: element }, null);
|
|
5518
|
+
});
|
|
5519
|
+
}
|
|
5520
|
+
};
|
|
5672
5521
|
|
|
5522
|
+
const ElementLowerHostClass = 'element-lower-host';
|
|
5673
5523
|
const ElementHostClass = 'element-host';
|
|
5674
5524
|
const ElementUpperHostClass = 'element-upper-host';
|
|
5675
5525
|
const ElementActiveHostClass = 'element-active-host';
|
|
@@ -5721,6 +5571,7 @@ class PlaitBoardComponent {
|
|
|
5721
5571
|
};
|
|
5722
5572
|
}
|
|
5723
5573
|
ngOnInit() {
|
|
5574
|
+
const elementLowerHost = this.host.querySelector(`.${ElementLowerHostClass}`);
|
|
5724
5575
|
const elementHost = this.host.querySelector(`.${ElementHostClass}`);
|
|
5725
5576
|
const elementUpperHost = this.host.querySelector(`.${ElementUpperHostClass}`);
|
|
5726
5577
|
const elementActiveHost = this.host.querySelector(`.${ElementActiveHostClass}`);
|
|
@@ -5745,6 +5596,7 @@ class PlaitBoardComponent {
|
|
|
5745
5596
|
BOARD_TO_HOST.set(this.board, this.host);
|
|
5746
5597
|
IS_BOARD_ALIVE.set(this.board, true);
|
|
5747
5598
|
BOARD_TO_ELEMENT_HOST.set(this.board, {
|
|
5599
|
+
lowerHost: elementLowerHost,
|
|
5748
5600
|
host: elementHost,
|
|
5749
5601
|
upperHost: elementUpperHost,
|
|
5750
5602
|
activeHost: elementActiveHost,
|
|
@@ -6024,6 +5876,7 @@ class PlaitBoardComponent {
|
|
|
6024
5876
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: PlaitBoardComponent, isStandalone: true, selector: "plait-board", inputs: { plaitValue: "plaitValue", plaitViewport: "plaitViewport", plaitPlugins: "plaitPlugins", plaitOptions: "plaitOptions", plaitTheme: "plaitTheme" }, outputs: { plaitChange: "plaitChange", plaitBoardInitialized: "plaitBoardInitialized" }, host: { properties: { "class": "this.hostClass", "class.readonly": "this.readonly", "class.focused": "this.isFocused", "class.disabled-scroll": "this.disabledScrollOnNonFocus" } }, providers: [PlaitContextService], queries: [{ propertyName: "islands", predicate: PlaitIslandBaseComponent, descendants: true }], viewQueries: [{ propertyName: "svg", first: true, predicate: ["svg"], descendants: true, static: true }, { propertyName: "viewportContainer", first: true, predicate: ["viewportContainer"], descendants: true, read: ElementRef, static: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
6025
5877
|
<div class="viewport-container" #viewportContainer>
|
|
6026
5878
|
<svg #svg width="100%" height="100%" style="position: relative;" class="board-host-svg">
|
|
5879
|
+
<g class="element-lower-host"></g>
|
|
6027
5880
|
<g class="element-host"></g>
|
|
6028
5881
|
<g class="element-upper-host"></g>
|
|
6029
5882
|
<g class="element-active-host"></g>
|
|
@@ -6039,6 +5892,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
|
|
|
6039
5892
|
template: `
|
|
6040
5893
|
<div class="viewport-container" #viewportContainer>
|
|
6041
5894
|
<svg #svg width="100%" height="100%" style="position: relative;" class="board-host-svg">
|
|
5895
|
+
<g class="element-lower-host"></g>
|
|
6042
5896
|
<g class="element-host"></g>
|
|
6043
5897
|
<g class="element-upper-host"></g>
|
|
6044
5898
|
<g class="element-active-host"></g>
|
|
@@ -6087,6 +5941,155 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
|
|
|
6087
5941
|
args: [PlaitIslandBaseComponent, { descendants: true }]
|
|
6088
5942
|
}] } });
|
|
6089
5943
|
|
|
5944
|
+
function hasBeforeContextChange(value) {
|
|
5945
|
+
if (value.beforeContextChange) {
|
|
5946
|
+
return true;
|
|
5947
|
+
}
|
|
5948
|
+
return false;
|
|
5949
|
+
}
|
|
5950
|
+
function hasOnContextChanged(value) {
|
|
5951
|
+
if (value.onContextChanged) {
|
|
5952
|
+
return true;
|
|
5953
|
+
}
|
|
5954
|
+
return false;
|
|
5955
|
+
}
|
|
5956
|
+
|
|
5957
|
+
class PlaitPluginElementComponent {
|
|
5958
|
+
get hasChildren() {
|
|
5959
|
+
return !!this.element.children;
|
|
5960
|
+
}
|
|
5961
|
+
set context(value) {
|
|
5962
|
+
if (hasBeforeContextChange(this)) {
|
|
5963
|
+
this.beforeContextChange(value);
|
|
5964
|
+
}
|
|
5965
|
+
const previousContext = this._context;
|
|
5966
|
+
this._context = value;
|
|
5967
|
+
if (this.initialized) {
|
|
5968
|
+
const elementG = this.getElementG();
|
|
5969
|
+
const containerG = this.getContainerG();
|
|
5970
|
+
NODE_TO_G.set(this.element, elementG);
|
|
5971
|
+
NODE_TO_CONTAINER_G.set(this.element, containerG);
|
|
5972
|
+
ELEMENT_TO_REF.set(this.element, this.ref);
|
|
5973
|
+
this.updateListRender();
|
|
5974
|
+
this.cdr.markForCheck();
|
|
5975
|
+
if (hasOnContextChanged(this)) {
|
|
5976
|
+
this.onContextChanged(value, previousContext);
|
|
5977
|
+
}
|
|
5978
|
+
}
|
|
5979
|
+
else {
|
|
5980
|
+
if (PlaitElement.isRootElement(this.element) && this.hasChildren) {
|
|
5981
|
+
this._g = createG();
|
|
5982
|
+
this._containerG = createG();
|
|
5983
|
+
this._containerG.append(this._g);
|
|
5984
|
+
}
|
|
5985
|
+
else {
|
|
5986
|
+
this._g = createG();
|
|
5987
|
+
this._containerG = this._g;
|
|
5988
|
+
}
|
|
5989
|
+
NODE_TO_G.set(this.element, this._g);
|
|
5990
|
+
NODE_TO_CONTAINER_G.set(this.element, this._containerG);
|
|
5991
|
+
ELEMENT_TO_REF.set(this.element, this.ref);
|
|
5992
|
+
}
|
|
5993
|
+
}
|
|
5994
|
+
get context() {
|
|
5995
|
+
return this._context;
|
|
5996
|
+
}
|
|
5997
|
+
get element() {
|
|
5998
|
+
return this.context && this.context.element;
|
|
5999
|
+
}
|
|
6000
|
+
get board() {
|
|
6001
|
+
return this.context && this.context.board;
|
|
6002
|
+
}
|
|
6003
|
+
get selected() {
|
|
6004
|
+
return this.context && this.context.selected;
|
|
6005
|
+
}
|
|
6006
|
+
getContainerG() {
|
|
6007
|
+
return this._containerG;
|
|
6008
|
+
}
|
|
6009
|
+
getElementG() {
|
|
6010
|
+
return this._g;
|
|
6011
|
+
}
|
|
6012
|
+
constructor(ref) {
|
|
6013
|
+
this.ref = ref;
|
|
6014
|
+
this.viewContainerRef = inject(ViewContainerRef);
|
|
6015
|
+
this.cdr = inject(ChangeDetectorRef);
|
|
6016
|
+
this.initialized = false;
|
|
6017
|
+
}
|
|
6018
|
+
ngOnInit() {
|
|
6019
|
+
if (this.element.type) {
|
|
6020
|
+
this.getContainerG().setAttribute(`plait-${this.element.type}`, 'true');
|
|
6021
|
+
}
|
|
6022
|
+
if (this.hasChildren) {
|
|
6023
|
+
if (PlaitElement.isRootElement(this.element)) {
|
|
6024
|
+
this._rootContainerG = this._containerG;
|
|
6025
|
+
}
|
|
6026
|
+
else {
|
|
6027
|
+
const path = PlaitBoard.findPath(this.board, this.element);
|
|
6028
|
+
const rootNode = PlaitNode.get(this.board, path.slice(0, 1));
|
|
6029
|
+
this._rootContainerG = PlaitElement.getContainerG(rootNode, { suppressThrow: false });
|
|
6030
|
+
}
|
|
6031
|
+
}
|
|
6032
|
+
this.getContainerG().setAttribute('plait-data-id', this.element.id);
|
|
6033
|
+
this.initialized = true;
|
|
6034
|
+
}
|
|
6035
|
+
initializeListRender() {
|
|
6036
|
+
if (this.hasChildren) {
|
|
6037
|
+
this.listRender = new ListRender(this.board, this.viewContainerRef);
|
|
6038
|
+
if (this.board.isExpanded(this.element)) {
|
|
6039
|
+
this.listRender.initialize(this.element.children, this.initializeChildrenContext());
|
|
6040
|
+
}
|
|
6041
|
+
}
|
|
6042
|
+
}
|
|
6043
|
+
getRef() {
|
|
6044
|
+
return this.ref;
|
|
6045
|
+
}
|
|
6046
|
+
updateListRender() {
|
|
6047
|
+
if (this.hasChildren) {
|
|
6048
|
+
if (!this.listRender) {
|
|
6049
|
+
throw new Error('incorrectly initialize list render');
|
|
6050
|
+
}
|
|
6051
|
+
if (this.board.isExpanded(this.element)) {
|
|
6052
|
+
this.listRender.update(this.element.children, this.initializeChildrenContext());
|
|
6053
|
+
}
|
|
6054
|
+
else {
|
|
6055
|
+
if (this.listRender.initialized) {
|
|
6056
|
+
this.listRender.destroy();
|
|
6057
|
+
}
|
|
6058
|
+
}
|
|
6059
|
+
}
|
|
6060
|
+
}
|
|
6061
|
+
initializeChildrenContext() {
|
|
6062
|
+
if (!this._rootContainerG) {
|
|
6063
|
+
throw new Error('can not resolve root container g');
|
|
6064
|
+
}
|
|
6065
|
+
return {
|
|
6066
|
+
board: this.board,
|
|
6067
|
+
parent: this.element,
|
|
6068
|
+
parentG: this._rootContainerG
|
|
6069
|
+
};
|
|
6070
|
+
}
|
|
6071
|
+
ngOnDestroy() {
|
|
6072
|
+
if (NODE_TO_G.get(this.element) === this._g) {
|
|
6073
|
+
NODE_TO_G.delete(this.element);
|
|
6074
|
+
}
|
|
6075
|
+
if (NODE_TO_CONTAINER_G.get(this.element) === this._containerG) {
|
|
6076
|
+
NODE_TO_CONTAINER_G.delete(this.element);
|
|
6077
|
+
}
|
|
6078
|
+
if (ELEMENT_TO_REF.get(this.element) === this.ref) {
|
|
6079
|
+
ELEMENT_TO_REF.set(this.element, this.ref);
|
|
6080
|
+
}
|
|
6081
|
+
removeSelectedElement(this.board, this.element);
|
|
6082
|
+
this.getContainerG().remove();
|
|
6083
|
+
}
|
|
6084
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: PlaitPluginElementComponent, deps: "invalid", target: i0.ɵɵFactoryTarget.Directive }); }
|
|
6085
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.4", type: PlaitPluginElementComponent, inputs: { context: "context" }, ngImport: i0 }); }
|
|
6086
|
+
}
|
|
6087
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: PlaitPluginElementComponent, decorators: [{
|
|
6088
|
+
type: Directive
|
|
6089
|
+
}], ctorParameters: () => [{ type: undefined }], propDecorators: { context: [{
|
|
6090
|
+
type: Input
|
|
6091
|
+
}] } });
|
|
6092
|
+
|
|
6090
6093
|
/**
|
|
6091
6094
|
* 1.create board instance
|
|
6092
6095
|
* 2.build fake node weak map
|
|
@@ -6345,5 +6348,5 @@ const isDebug = (key) => {
|
|
|
6345
6348
|
* Generated bundle index. Do not edit.
|
|
6346
6349
|
*/
|
|
6347
6350
|
|
|
6348
|
-
export { A, ACTIVE_MOVING_CLASS_NAME, ACTIVE_STROKE_WIDTH, ALT, APOSTROPHE, ATTACHED_ELEMENT_CLASS_NAME, AT_SIGN, B, BACKSLASH, BACKSPACE, BOARD_TO_AFTER_CHANGE, BOARD_TO_COMPONENT, BOARD_TO_ELEMENT_HOST, BOARD_TO_HOST, BOARD_TO_IS_SELECTION_MOVING, BOARD_TO_MOVING_ELEMENT, BOARD_TO_MOVING_POINT, BOARD_TO_MOVING_POINT_IN_BOARD, BOARD_TO_ON_CHANGE, BOARD_TO_ROUGH_SVG, BOARD_TO_SELECTED_ELEMENT, BOARD_TO_TEMPORARY_ELEMENTS, BOARD_TO_TOUCH_REF, BOARD_TO_VIEWPORT_ORIGINATION, BoardTransforms, C, CAPS_LOCK, CLOSE_SQUARE_BRACKET, COMMA, CONTEXT_MENU, CONTROL, ColorfulThemeColor, CoreTransforms, CursorClass, D, DASH, DELETE, DOWN_ARROW, DarkThemeColor, DebugGenerator, DefaultThemeColor, Direction, E, EIGHT,
|
|
6351
|
+
export { A, ACTIVE_MOVING_CLASS_NAME, ACTIVE_STROKE_WIDTH, ALT, APOSTROPHE, ATTACHED_ELEMENT_CLASS_NAME, AT_SIGN, B, BACKSLASH, BACKSPACE, BOARD_TO_AFTER_CHANGE, BOARD_TO_COMPONENT, BOARD_TO_ELEMENT_HOST, BOARD_TO_HOST, BOARD_TO_IS_SELECTION_MOVING, BOARD_TO_MOVING_ELEMENT, BOARD_TO_MOVING_POINT, BOARD_TO_MOVING_POINT_IN_BOARD, BOARD_TO_ON_CHANGE, BOARD_TO_ROUGH_SVG, BOARD_TO_SELECTED_ELEMENT, BOARD_TO_TEMPORARY_ELEMENTS, BOARD_TO_TOUCH_REF, BOARD_TO_VIEWPORT_ORIGINATION, BoardTransforms, C, CAPS_LOCK, CLOSE_SQUARE_BRACKET, COMMA, CONTEXT_MENU, CONTROL, ColorfulThemeColor, CoreTransforms, CursorClass, D, DASH, DELETE, DOWN_ARROW, DarkThemeColor, DebugGenerator, DefaultThemeColor, Direction, E, EIGHT, ELEMENT_TO_REF, END, ENTER, EQUALS, ESCAPE, F, F1, F10, F11, F12, F2, F3, F4, F5, F6, F7, F8, F9, FF_EQUALS, FF_MINUS, FF_MUTE, FF_SEMICOLON, FF_VOLUME_DOWN, FF_VOLUME_UP, FIRST_MEDIA, FIVE, FLUSHING, FOUR, G, H, HIT_DISTANCE_BUFFER, HOME, HOST_CLASS_NAME, I, INSERT, IS_APPLE, IS_BOARD_ALIVE, IS_BOARD_CACHE, IS_CHROME, IS_CHROME_LEGACY, IS_DRAGGING, IS_EDGE_LEGACY, IS_FIREFOX, IS_IOS, IS_MAC, IS_SAFARI, IS_TEXT_EDITABLE, J, K, L, LAST_MEDIA, LEFT_ARROW, M, MAC_ENTER, MAC_META, MAC_WK_CMD_LEFT, MAC_WK_CMD_RIGHT, MAX_RADIUS, MERGING, META, MUTE, N, NINE, NODE_TO_CONTAINER_G, NODE_TO_G, NODE_TO_INDEX, NODE_TO_PARENT, NS, NUMPAD_DIVIDE, NUMPAD_EIGHT, NUMPAD_FIVE, NUMPAD_FOUR, NUMPAD_MINUS, NUMPAD_MULTIPLY, NUMPAD_NINE, NUMPAD_ONE, NUMPAD_PERIOD, NUMPAD_PLUS, NUMPAD_SEVEN, NUMPAD_SIX, NUMPAD_THREE, NUMPAD_TWO, NUMPAD_ZERO, NUM_CENTER, NUM_LOCK, O, ONE, OPEN_SQUARE_BRACKET, P, PAGE_DOWN, PAGE_UP, PATH_REFS, PAUSE, PERIOD, PLUS_SIGN, POINTER_BUTTON, PRESS_AND_MOVE_BUFFER, PRINT_SCREEN, Path, PlaitBoard, PlaitBoardComponent, PlaitContextService, PlaitElement, PlaitGroupElement, PlaitHistoryBoard, PlaitIslandBaseComponent, PlaitIslandPopoverBaseComponent, PlaitNode, PlaitOperation, PlaitPluginElementComponent, PlaitPluginKey, PlaitPointerType, Point, Q, QUESTION_MARK, R, RESIZE_CURSORS, RESIZE_HANDLE_CLASS_NAME, RIGHT_ARROW, ROTATE_HANDLE_CLASS_NAME, RectangleClient, ResizeCursorClass, RetroThemeColor, RgbaToHEX, S, SAVING, SCROLL_BAR_WIDTH, SCROLL_LOCK, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, SELECTION_RECTANGLE_CLASS_NAME, SEMICOLON, SEVEN, SHIFT, SINGLE_QUOTE, SIX, SLASH, SNAPPING_STROKE_WIDTH, SNAP_TOLERANCE, SPACE, Selection, SoftThemeColor, StarryThemeColor, T, TAB, THREE, TILDE, TWO, ThemeColorMode, ThemeColors, Transforms, U, UP_ARROW, V, VOLUME_DOWN, VOLUME_UP, Viewport, W, WritableClipboardOperationType, WritableClipboardType, X, Y, Z, ZERO, addClipboardContext, addSelectedElement, approximately, arrowPoints, buildPlaitHtml, cacheMovingElements, cacheSelectedElements, cacheSelectedElementsWithGroup, cacheSelectedElementsWithGroupOnShift, calcNewViewBox, canAddGroup, canRemoveGroup, canSetZIndex, catmullRomFitting, clampZoomLevel, clearNodeWeakMap, clearSelectedElement, clearSelectionMoving, clearViewportOrigination, createClipboardContext, createDebugGenerator, createFakeEvent, createForeignObject, createG, createGroup, createGroupRectangleG, createKeyboardEvent, createMask, createModModifierKeys, createMouseEvent, createPath, createPointerEvent, createRect, createSVG, createTestingBoard, createText, createTouchEvent, debounce, degreesToRadians, deleteFragment, deleteTemporaryElements, depthFirstRecursion, distanceBetweenPointAndPoint, distanceBetweenPointAndRectangle, distanceBetweenPointAndSegment, distanceBetweenPointAndSegments, downloadImage, drawArrow, drawBezierPath, drawCircle, drawDashedLines, drawEntireActiveRectangleG, drawLine, drawLinearPath, drawPendingNodesG, drawPointSnapLines, drawRectangle, drawRoundRectangle, drawSolidLines, duplicateElements, fakeNodeWeakMap, filterSelectedGroups, findElements, findIndex, findLastIndex, getAllElementsInGroup, getAllMoveOptions, getAngleBetweenPoints, getAngleByElement, getBarPoint, getBoardRectangle, getBoundingRectangleByElements, getClipboardData, getClipboardFromHtml, getCrossingPointsBetweenEllipseAndSegment, getDataTransferClipboard, getDataTransferClipboardText, getEditingGroup, getElementById, getElementHostBBox, getElementsInGroup, getElementsInGroupByElement, getElementsIndices, getEllipseTangentSlope, getGroupByElement, getHighestGroup, getHighestIndexOfElement, getHighestSelectedElements, getHighestSelectedGroup, getHighestSelectedGroups, getHitElementByPoint, getHitElementsBySelection, getHitSelectedElements, getIsRecursionFunc, getMinPointDelta, getMovingElements, getNearestDelta, getNearestPointBetweenPointAndEllipse, getNearestPointBetweenPointAndSegment, getNearestPointBetweenPointAndSegments, getNearestPointRectangle, getOffsetAfterRotate, getOneMoveOptions, getProbablySupportsClipboardRead, getProbablySupportsClipboardWrite, getProbablySupportsClipboardWriteText, getRealScrollBarWidth, getRectangleByAngle, getRectangleByElements, getRectangleByGroup, getRotatedBoundingRectangle, getSelectedElements, getSelectedGroups, getSelectedIsolatedElements, getSelectedIsolatedElementsCanAddToGroup, getSelectedTargetElements, getSelectionAngle, getSnapRectangles, getTemporaryElements, getTemporaryRef, getTripleAxis, getValidElements, getVectorFromPointAndSlope, getViewBox, getViewBoxCenterPoint, getViewportContainerRect, getViewportOrigination, handleTouchTarget, hasBeforeContextChange, hasInputOrTextareaTarget, hasOnBoardChange, hasOnContextChanged, hasSameAngle, hasSelectedElementsInSameGroup, hasValidAngle, hotkeys, idCreator, initializeViewBox, initializeViewportContainer, initializeViewportOffset, inverse, isAxisChangedByAngle, isContextmenu, isDOMElement, isDOMNode, isDebug, isDragging, isFromScrolling, isFromViewportChange, isHandleSelection, isInPlaitBoard, isIndicesContinuous, isLineHitLine, isMainPointer, isMovingElements, isNullOrUndefined, isPointInEllipse, isPointInPolygon, isPointInRoundRectangle, isPolylineHitRectangle, isPreventTouchMove, isSecondaryPointer, isSelectedAllElementsInGroup, isSelectedElement, isSelectedElementOrGroup, isSelectionMoving, isSetSelectionOperation, isSetViewportOperation, isSnapPoint, moveElementsToNewPath, moveElementsToNewPathAfterAddGroup, nonGroupInHighestSelectedElements, normalizeAngle, normalizePoint, preventTouchMove, radiansToDegrees, removeMovingElements, removeSelectedElement, rotate, rotateAntiPointsByElement, rotateElements, rotatePoints, rotatePointsByElement, rotatedDataPoints, scrollToRectangle, setAngleForG, setClipboardData, setDataTransferClipboard, setDataTransferClipboardText, setDragging, setFragment, setIsFromScrolling, setIsFromViewportChange, setPathStrokeLinecap, setSVGViewBox, setSelectedElementsWithGroup, setSelectionMoving, setStrokeLinecap, shouldClear, shouldMerge, shouldSave, sortElements, stripHtml, temporaryDisableSelection, throttleRAF, toDomPrecision, toFixed, toHostPoint, toHostPointFromViewBoxPoint, toImage, toScreenPointFromHostPoint, toViewBoxPoint, toViewBoxPoints, uniqueById, updateForeignObject, updateForeignObjectWidth, updatePoints, updateViewportByScrolling, updateViewportContainerScroll, updateViewportOffset, updateViewportOrigination, withArrowMoving, withMoving, withOptions, withSelection };
|
|
6349
6352
|
//# sourceMappingURL=plait-core.mjs.map
|