@plait/draw 0.55.1 → 0.56.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.
Files changed (56) hide show
  1. package/constants/geometry.d.ts +52 -0
  2. package/engines/basic-shapes/ellipse.d.ts +8 -3
  3. package/engines/flowchart/database.d.ts +2 -0
  4. package/engines/flowchart/document.d.ts +2 -0
  5. package/engines/flowchart/hard-disk.d.ts +2 -0
  6. package/engines/flowchart/internal-storage.d.ts +2 -0
  7. package/engines/flowchart/multi-document.d.ts +4 -0
  8. package/engines/flowchart/note-curly-left.d.ts +2 -0
  9. package/engines/flowchart/note-curly-right.d.ts +2 -0
  10. package/engines/flowchart/note-square.d.ts +2 -0
  11. package/esm2022/constants/geometry.mjs +30 -2
  12. package/esm2022/engines/basic-shapes/ellipse.mjs +49 -36
  13. package/esm2022/engines/basic-shapes/round-rectangle.mjs +2 -3
  14. package/esm2022/engines/flowchart/database.mjs +84 -0
  15. package/esm2022/engines/flowchart/delay.mjs +2 -3
  16. package/esm2022/engines/flowchart/document.mjs +81 -0
  17. package/esm2022/engines/flowchart/hard-disk.mjs +84 -0
  18. package/esm2022/engines/flowchart/internal-storage.mjs +47 -0
  19. package/esm2022/engines/flowchart/multi-document.mjs +143 -0
  20. package/esm2022/engines/flowchart/note-curly-left.mjs +50 -0
  21. package/esm2022/engines/flowchart/note-curly-right.mjs +50 -0
  22. package/esm2022/engines/flowchart/note-square.mjs +46 -0
  23. package/esm2022/engines/flowchart/or.mjs +2 -2
  24. package/esm2022/engines/flowchart/stored-data.mjs +2 -3
  25. package/esm2022/engines/flowchart/summing-junction.mjs +2 -2
  26. package/esm2022/engines/flowchart/terminal.mjs +2 -3
  27. package/esm2022/engines/index.mjs +18 -2
  28. package/esm2022/generators/line-active.generator.mjs +15 -13
  29. package/esm2022/generators/line-auto-complete.generator.mjs +2 -1
  30. package/esm2022/geometry.component.mjs +12 -20
  31. package/esm2022/image.component.mjs +8 -8
  32. package/esm2022/interfaces/geometry.mjs +9 -1
  33. package/esm2022/line.component.mjs +6 -6
  34. package/esm2022/plugins/with-draw-fragment.mjs +4 -4
  35. package/esm2022/plugins/with-draw-hotkey.mjs +5 -5
  36. package/esm2022/plugins/with-draw-rotate.mjs +6 -7
  37. package/esm2022/plugins/with-draw.mjs +3 -3
  38. package/esm2022/plugins/with-geometry-create.mjs +35 -22
  39. package/esm2022/plugins/with-geometry-resize.mjs +4 -5
  40. package/esm2022/plugins/with-line-auto-complete-reaction.mjs +6 -4
  41. package/esm2022/plugins/with-line-text-move.mjs +5 -5
  42. package/esm2022/plugins/with-line-text.mjs +11 -7
  43. package/esm2022/utils/geometry.mjs +7 -3
  44. package/esm2022/utils/selected.mjs +4 -4
  45. package/fesm2022/plait-draw.mjs +699 -131
  46. package/fesm2022/plait-draw.mjs.map +1 -1
  47. package/generators/line-auto-complete.generator.d.ts +1 -0
  48. package/geometry.component.d.ts +1 -4
  49. package/image.component.d.ts +1 -3
  50. package/interfaces/geometry.d.ts +9 -1
  51. package/line.component.d.ts +1 -3
  52. package/package.json +1 -1
  53. package/utils/geometry.d.ts +16 -0
  54. package/utils/selected.d.ts +2 -2
  55. package/engines/basic-shapes/circle.d.ts +0 -8
  56. package/esm2022/engines/basic-shapes/circle.mjs +0 -51
@@ -1,5 +1,5 @@
1
- import { ACTIVE_STROKE_WIDTH, ThemeColorMode, createDebugGenerator, Point, RectangleClient, getElementById, rotatePointsByElement, createG, arrowPoints, createPath, distanceBetweenPointAndPoint, drawLinearPath, rotate, distanceBetweenPointAndSegments, HIT_DISTANCE_BUFFER, isPolylineHitRectangle, rotateAntiPointsByElement, rotatePoints, depthFirstRecursion, PlaitBoard, getIsRecursionFunc, idCreator, catmullRomFitting, setStrokeLinecap, findElements, createMask, createRect, getSelectedElements, isPointInPolygon, getNearestPointBetweenPointAndSegments, isPointInEllipse, getEllipseTangentSlope, getVectorFromPointAndSlope, drawRectangle, drawRoundRectangle, isPointInRoundRectangle, setPathStrokeLinecap, getCrossingPointsBetweenEllipseAndSegment, SNAPPING_STROKE_WIDTH, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, drawCircle, Transforms, clearSelectedElement, addSelectedElement, BoardTransforms, PlaitPointerType, Direction, hasValidAngle, Path, PlaitNode, toViewBoxPoint, toHostPoint, isSelectionMoving, RgbaToHEX, PlaitElement, getHitElementByPoint, getRectangleByElements, getSelectionAngle, rotatedDataPoints, isAxisChangedByAngle, getRectangleByAngle, getSnapRectangles, getTripleAxis, getMinPointDelta, SNAP_TOLERANCE, drawPointSnapLines, drawSolidLines, preventTouchMove, createClipboardContext, WritableClipboardType, addClipboardContext, setAngleForG, CursorClass, temporaryDisableSelection, PRESS_AND_MOVE_BUFFER, isMainPointer, throttleRAF, getAngleBetweenPoints, degreesToRadians, normalizeAngle, rotateElements, MERGING, ROTATE_HANDLE_CLASS_NAME, SELECTION_RECTANGLE_CLASS_NAME } from '@plait/core';
2
- import { removeDuplicatePoints, generateElbowLineRoute, simplifyOrthogonalPoints, isSourceAndTargetIntersect, getPoints, DEFAULT_ROUTE_MARGIN, getPointByVectorComponent, getExtendPoint, getUnitVectorByPointAndPoint, Generator, RESIZE_HANDLE_DIAMETER, getPointOnPolyline, TRANSPARENT, getRectangleResizeHandleRefs, getRotatedResizeCursorClassByAngle, ROTATE_HANDLE_DISTANCE_TO_ELEMENT, ROTATE_HANDLE_SIZE, getMemorizedLatest, memorizeLatest, getCrossingPointsBetweenPointAndSegment, isPointOnSegment, getDirectionByVector, getOppositeDirection, getDirectionFactor, rotateVector, getDirectionByPointOfRectangle, rotateVectorAnti90, getSourceAndTargetOuterRectangle, getNextPoint, normalizeShapePoints, getFirstTextEditor, PRIMARY_COLOR, CommonPluginElement, ActiveGenerator, WithTextPluginKey, drawPrimaryHandle, drawFillPrimaryHandle, isVirtualKey, isDelete, isSpaceHotkey, isCornerHandle, getIndexByResizeHandle, resetPointsAfterResize, getFirstTextManage, withResize, drawHandle, getSymmetricHandleIndex, getResizeHandlePointByIndex, getDirectionFactorByDirectionComponent, isDndMode, isDrawingMode, getElementsText, acceptImageTypes, getElementOfFocusedImage, buildImage, isResizingByCondition, getRatioByPoint, ImageGenerator, ResizeHandle, addRotating, removeRotating, drawRotateHandle } from '@plait/common';
1
+ import { ACTIVE_STROKE_WIDTH, ThemeColorMode, createDebugGenerator, Point, RectangleClient, getElementById, rotatePointsByElement, createG, arrowPoints, createPath, distanceBetweenPointAndPoint, drawLinearPath, rotate, distanceBetweenPointAndSegments, HIT_DISTANCE_BUFFER, isPolylineHitRectangle, rotateAntiPointsByElement, rotatePoints, depthFirstRecursion, PlaitBoard, getIsRecursionFunc, idCreator, catmullRomFitting, setStrokeLinecap, findElements, createMask, createRect, getSelectedElements, isPointInPolygon, getNearestPointBetweenPointAndSegments, isPointInEllipse, getNearestPointBetweenPointAndEllipse, getEllipseTangentSlope, getVectorFromPointAndSlope, drawRectangle, drawRoundRectangle, isPointInRoundRectangle, setPathStrokeLinecap, getCrossingPointsBetweenEllipseAndSegment, Direction, SNAPPING_STROKE_WIDTH, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, drawCircle, Transforms, clearSelectedElement, addSelectedElement, BoardTransforms, PlaitPointerType, hasValidAngle, Path, PlaitNode, toViewBoxPoint, toHostPoint, isSelectionMoving, RgbaToHEX, getHitElementByPoint, getRectangleByElements, getSelectionAngle, rotatedDataPoints, isAxisChangedByAngle, getRectangleByAngle, getSnapRectangles, getTripleAxis, getMinPointDelta, SNAP_TOLERANCE, drawPointSnapLines, drawSolidLines, preventTouchMove, createClipboardContext, WritableClipboardType, addClipboardContext, setAngleForG, CursorClass, PlaitElement, temporaryDisableSelection, PRESS_AND_MOVE_BUFFER, isMainPointer, throttleRAF, getAngleBetweenPoints, normalizeAngle, degreesToRadians, rotateElements, MERGING, ROTATE_HANDLE_CLASS_NAME, SELECTION_RECTANGLE_CLASS_NAME } from '@plait/core';
2
+ import { removeDuplicatePoints, generateElbowLineRoute, simplifyOrthogonalPoints, isSourceAndTargetIntersect, getPoints, DEFAULT_ROUTE_MARGIN, getPointByVectorComponent, getExtendPoint, getUnitVectorByPointAndPoint, Generator, RESIZE_HANDLE_DIAMETER, getPointOnPolyline, TRANSPARENT, getRectangleResizeHandleRefs, getRotatedResizeCursorClassByAngle, ROTATE_HANDLE_DISTANCE_TO_ELEMENT, ROTATE_HANDLE_SIZE, getMemorizedLatest, memorizeLatest, getCrossingPointsBetweenPointAndSegment, isPointOnSegment, getDirectionByPointOfRectangle, getDirectionFactor, getFirstTextManage, getDirectionByVector, getOppositeDirection, rotateVector, rotateVectorAnti90, getSourceAndTargetOuterRectangle, getNextPoint, normalizeShapePoints, getFirstTextEditor, PRIMARY_COLOR, CommonPluginElement, ActiveGenerator, canResize, WithTextPluginKey, drawPrimaryHandle, drawFillPrimaryHandle, isVirtualKey, isDelete, isSpaceHotkey, isCornerHandle, getIndexByResizeHandle, resetPointsAfterResize, withResize, drawHandle, getSymmetricHandleIndex, getResizeHandlePointByIndex, getDirectionFactorByDirectionComponent, isDndMode, isDrawingMode, getElementsText, acceptImageTypes, getElementOfFocusedImage, buildImage, isResizingByCondition, getRatioByPoint, getTextManages, ImageGenerator, ResizeHandle, addRotating, removeRotating, drawRotateHandle } from '@plait/common';
3
3
  import { Alignment, buildText, DEFAULT_FONT_SIZE, getTextSize, AlignEditor, TextManage } from '@plait/text';
4
4
  import { pointsOnBezierCurves } from 'points-on-curve';
5
5
  import * as i0 from '@angular/core';
@@ -49,6 +49,14 @@ var FlowchartSymbols;
49
49
  FlowchartSymbols["summingJunction"] = "summingJunction";
50
50
  FlowchartSymbols["predefinedProcess"] = "predefinedProcess";
51
51
  FlowchartSymbols["offPage"] = "offPage";
52
+ FlowchartSymbols["document"] = "document";
53
+ FlowchartSymbols["multiDocument"] = "multiDocument";
54
+ FlowchartSymbols["database"] = "database";
55
+ FlowchartSymbols["hardDisk"] = "hardDisk";
56
+ FlowchartSymbols["internalStorage"] = "internalStorage";
57
+ FlowchartSymbols["noteCurlyRight"] = "noteCurlyRight";
58
+ FlowchartSymbols["noteCurlyLeft"] = "noteCurlyLeft";
59
+ FlowchartSymbols["noteSquare"] = "noteSquare";
52
60
  })(FlowchartSymbols || (FlowchartSymbols = {}));
53
61
  const PlaitGeometry = {};
54
62
 
@@ -93,6 +101,14 @@ const DefaultFlowchartProperty = {
93
101
  width: 120,
94
102
  height: 60
95
103
  };
104
+ const DefaultDataBaseProperty = {
105
+ width: 70,
106
+ height: 80
107
+ };
108
+ const DefaultInternalStorageProperty = {
109
+ width: 80,
110
+ height: 80
111
+ };
96
112
  const DefaultDecisionProperty = {
97
113
  width: 140,
98
114
  height: 70
@@ -101,6 +117,18 @@ const DefaultDataProperty = {
101
117
  width: 124,
102
118
  height: 60
103
119
  };
120
+ const DefaultDocumentProperty = {
121
+ width: 120,
122
+ height: 70
123
+ };
124
+ const DefaultNoteProperty = {
125
+ width: 160,
126
+ height: 100
127
+ };
128
+ const DefaultMultiDocumentProperty = {
129
+ width: 120,
130
+ height: 80
131
+ };
104
132
  const DefaultManualInputProperty = {
105
133
  width: 117,
106
134
  height: 59
@@ -124,7 +152,15 @@ const DefaultFlowchartPropertyMap = {
124
152
  [FlowchartSymbols.or]: DefaultConnectorProperty,
125
153
  [FlowchartSymbols.summingJunction]: DefaultConnectorProperty,
126
154
  [FlowchartSymbols.predefinedProcess]: DefaultFlowchartProperty,
127
- [FlowchartSymbols.offPage]: DefaultFlowchartProperty
155
+ [FlowchartSymbols.offPage]: DefaultFlowchartProperty,
156
+ [FlowchartSymbols.document]: DefaultDocumentProperty,
157
+ [FlowchartSymbols.multiDocument]: DefaultMultiDocumentProperty,
158
+ [FlowchartSymbols.database]: DefaultDataBaseProperty,
159
+ [FlowchartSymbols.hardDisk]: DefaultFlowchartProperty,
160
+ [FlowchartSymbols.internalStorage]: DefaultInternalStorageProperty,
161
+ [FlowchartSymbols.noteCurlyLeft]: DefaultNoteProperty,
162
+ [FlowchartSymbols.noteCurlyRight]: DefaultNoteProperty,
163
+ [FlowchartSymbols.noteSquare]: DefaultNoteProperty
128
164
  };
129
165
  const LINE_HIT_GEOMETRY_BUFFER = 10;
130
166
  const LINE_SNAPPING_BUFFER = 6;
@@ -1288,9 +1324,9 @@ function drawMask(board, element, id) {
1288
1324
  return { mask, maskTargetFillRect };
1289
1325
  }
1290
1326
 
1291
- const getSelectedDrawElements = (board) => {
1292
- const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isDrawElement(value));
1293
- return selectedElements;
1327
+ const getSelectedDrawElements = (board, elements) => {
1328
+ const selectedElements = elements?.length ? elements : getSelectedElements(board);
1329
+ return selectedElements.filter(value => PlaitDrawElement.isDrawElement(value));
1294
1330
  };
1295
1331
  const getSelectedGeometryElements = (board) => {
1296
1332
  const selectedElements = getSelectedElements(board).filter(value => PlaitDrawElement.isGeometry(value));
@@ -1530,43 +1566,7 @@ function createEllipseEngine(createOptions) {
1530
1566
  }
1531
1567
  return engine;
1532
1568
  }
1533
-
1534
1569
  const EllipseEngine = createEllipseEngine();
1535
- function getNearestPointBetweenPointAndEllipse(point, center, rx, ry, rotation = 0) {
1536
- const rectangleClient = {
1537
- x: center[0] - rx,
1538
- y: center[1] - ry,
1539
- height: ry * 2,
1540
- width: rx * 2
1541
- };
1542
- // https://stackoverflow.com/a/46007540/232122
1543
- const px = Math.abs(point[0] - rectangleClient.x - rectangleClient.width / 2);
1544
- const py = Math.abs(point[1] - rectangleClient.y - rectangleClient.height / 2);
1545
- let tx = 0.707;
1546
- let ty = 0.707;
1547
- const a = Math.abs(rectangleClient.width) / 2;
1548
- const b = Math.abs(rectangleClient.height) / 2;
1549
- [0, 1, 2, 3].forEach(x => {
1550
- const xx = a * tx;
1551
- const yy = b * ty;
1552
- const ex = ((a * a - b * b) * tx ** 3) / a;
1553
- const ey = ((b * b - a * a) * ty ** 3) / b;
1554
- const rx = xx - ex;
1555
- const ry = yy - ey;
1556
- const qx = px - ex;
1557
- const qy = py - ey;
1558
- const r = Math.hypot(ry, rx);
1559
- const q = Math.hypot(qy, qx);
1560
- tx = Math.min(1, Math.max(0, ((qx * r) / q + ex) / a));
1561
- ty = Math.min(1, Math.max(0, ((qy * r) / q + ey) / b));
1562
- const t = Math.hypot(ty, tx);
1563
- tx /= t;
1564
- ty /= t;
1565
- });
1566
- const signX = point[0] > center[0] ? 1 : -1;
1567
- const signY = point[1] > center[1] ? 1 : -1;
1568
- return [center[0] + a * tx * signX, center[1] + b * ty * signY];
1569
- }
1570
1570
 
1571
1571
  const getHexagonPoints = (rectangle) => {
1572
1572
  return [
@@ -2489,6 +2489,551 @@ const SummingJunctionEngine = createEllipseEngine({
2489
2489
  }
2490
2490
  });
2491
2491
 
2492
+ const DocumentEngine = {
2493
+ draw(board, rectangle, options) {
2494
+ const rs = PlaitBoard.getRoughSVG(board);
2495
+ const shape = rs.path(`M${rectangle.x} ${rectangle.y + rectangle.height - rectangle.height / 9} V${rectangle.y} H${rectangle.x +
2496
+ rectangle.width} V${rectangle.y + rectangle.height - rectangle.height / 9}
2497
+ Q${rectangle.x + rectangle.width - rectangle.width / 4} ${rectangle.y +
2498
+ rectangle.height -
2499
+ (rectangle.height / 9) * 3}, ${rectangle.x + rectangle.width / 2} ${rectangle.y +
2500
+ rectangle.height -
2501
+ rectangle.height / 9} T${rectangle.x} ${rectangle.y + rectangle.height - rectangle.height / 9}
2502
+ `, { ...options, fillStyle: 'solid' });
2503
+ setStrokeLinecap(shape, 'round');
2504
+ return shape;
2505
+ },
2506
+ isInsidePoint(rectangle, point) {
2507
+ const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
2508
+ return RectangleClient.isHit(rectangle, rangeRectangle);
2509
+ },
2510
+ getCornerPoints(rectangle) {
2511
+ return RectangleClient.getCornerPoints(rectangle);
2512
+ },
2513
+ getNearestPoint(rectangle, point) {
2514
+ let nearestPoint = getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
2515
+ let curvePoints = catmullRomFitting([
2516
+ [rectangle.x, rectangle.y + rectangle.height - rectangle.height / 9],
2517
+ [rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height],
2518
+ [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height - rectangle.height / 9],
2519
+ [rectangle.x + (rectangle.width / 4) * 3, rectangle.y + rectangle.height - (rectangle.height / 9) * 2],
2520
+ [rectangle.x + rectangle.width, rectangle.y + rectangle.height - rectangle.height / 9]
2521
+ ]);
2522
+ curvePoints = pointsOnBezierCurves(curvePoints);
2523
+ if (nearestPoint[1] > rectangle.y + rectangle.height - rectangle.height / 9) {
2524
+ if (nearestPoint[0] === rectangle.x + rectangle.width / 2) {
2525
+ nearestPoint[1] = rectangle.y + rectangle.height - rectangle.height / 9;
2526
+ return nearestPoint;
2527
+ }
2528
+ nearestPoint = getNearestPointBetweenPointAndSegments(point, curvePoints, false);
2529
+ }
2530
+ return nearestPoint;
2531
+ },
2532
+ getConnectorPoints(rectangle) {
2533
+ return [
2534
+ [rectangle.x + rectangle.width / 2, rectangle.y],
2535
+ [rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
2536
+ [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height - rectangle.height / 9],
2537
+ [rectangle.x, rectangle.y + rectangle.height / 2]
2538
+ ];
2539
+ },
2540
+ getTangentVectorByConnectionPoint(rectangle, pointOfRectangle) {
2541
+ const connectionPoint = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
2542
+ if (connectionPoint[0] > rectangle.x && connectionPoint[0] < rectangle.x + rectangle.width / 4) {
2543
+ return getUnitVectorByPointAndPoint([rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height], connectionPoint);
2544
+ }
2545
+ if (connectionPoint[0] > rectangle.x + rectangle.width / 4 && connectionPoint[0] < rectangle.x + (rectangle.width / 4) * 3) {
2546
+ return getUnitVectorByPointAndPoint([rectangle.x + (rectangle.width / 4) * 3, rectangle.y + rectangle.height - rectangle.height / 9], [rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height]);
2547
+ }
2548
+ if (connectionPoint[0] > rectangle.x + (rectangle.width / 4) * 3) {
2549
+ return getUnitVectorByPointAndPoint([rectangle.x + rectangle.width, rectangle.y + rectangle.height - rectangle.height / 9], connectionPoint);
2550
+ }
2551
+ return getUnitVectorByPointAndPoint(connectionPoint, [rectangle.x + rectangle.width / 4, rectangle.y + rectangle.height]);
2552
+ },
2553
+ getTextRectangle: (element) => {
2554
+ const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
2555
+ const strokeWidth = getStrokeWidthByElement(element);
2556
+ const height = element.textHeight;
2557
+ const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2 - elementRectangle.width * 0.06 * 2;
2558
+ return {
2559
+ height,
2560
+ width: width > 0 ? width : 0,
2561
+ x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth + elementRectangle.width * 0.06,
2562
+ y: elementRectangle.y + (elementRectangle.height - height) / 2
2563
+ };
2564
+ }
2565
+ };
2566
+
2567
+ const getMultiDocumentPoints = (rectangle) => {
2568
+ const linePoints = [
2569
+ [rectangle.x, rectangle.y + 10],
2570
+ [rectangle.x + 5, rectangle.y + 10],
2571
+ [rectangle.x + 5, rectangle.y + 5],
2572
+ [rectangle.x + 10, rectangle.y + 5],
2573
+ [rectangle.x + 10, rectangle.y],
2574
+ [rectangle.x + rectangle.width, rectangle.y],
2575
+ [rectangle.x + rectangle.width, rectangle.y + rectangle.height - rectangle.height / 9 - 10 - 3],
2576
+ [rectangle.x + rectangle.width - 5, rectangle.y + rectangle.height - rectangle.height / 9 - 10 - 3 - 4],
2577
+ [rectangle.x + rectangle.width - 5, rectangle.y + rectangle.height - rectangle.height / 9 - 5 - 3],
2578
+ [rectangle.x + rectangle.width - 10, rectangle.y + rectangle.height - rectangle.height / 9 - 5 - 3 - 4],
2579
+ [rectangle.x + rectangle.width - 10, rectangle.y + rectangle.height - rectangle.height / 9]
2580
+ ];
2581
+ let curvePoints = catmullRomFitting([
2582
+ [rectangle.x + rectangle.width - 10, rectangle.y + rectangle.height - rectangle.height / 9],
2583
+ [rectangle.x + rectangle.width - 10 - (rectangle.width - 10) / 4, rectangle.y + rectangle.height - (rectangle.height / 9) * 2],
2584
+ [rectangle.x + (rectangle.width - 10) / 2, rectangle.y + rectangle.height - rectangle.height / 9],
2585
+ [rectangle.x + (rectangle.width - 10) / 4, rectangle.y + rectangle.height],
2586
+ [rectangle.x, rectangle.y + rectangle.height - rectangle.height / 9]
2587
+ ]);
2588
+ curvePoints = pointsOnBezierCurves(curvePoints);
2589
+ return [...linePoints, ...curvePoints];
2590
+ };
2591
+ const MultiDocumentEngine = {
2592
+ draw(board, rectangle, options) {
2593
+ const rs = PlaitBoard.getRoughSVG(board);
2594
+ const shape = rs.path(`M${rectangle.x} ${rectangle.y + rectangle.height - rectangle.height / 9} V${rectangle.y + 10} H${rectangle.x +
2595
+ 5} V${rectangle.y + 5} H${rectangle.x + 10} V${rectangle.y} H${rectangle.x + rectangle.width} V${rectangle.y +
2596
+ rectangle.height -
2597
+ rectangle.height / 9 -
2598
+ 10 -
2599
+ 3} L${rectangle.x + rectangle.width - 5} ${rectangle.y +
2600
+ rectangle.height -
2601
+ rectangle.height / 9 -
2602
+ 10 -
2603
+ 3 -
2604
+ 4} V${rectangle.y + rectangle.height - rectangle.height / 9 - 5 - 3}
2605
+ L${rectangle.x + rectangle.width - 10} ${rectangle.y +
2606
+ rectangle.height -
2607
+ rectangle.height / 9 -
2608
+ 5 -
2609
+ 3 -
2610
+ 4} V${rectangle.y + rectangle.height - rectangle.height / 9}
2611
+
2612
+ Q${rectangle.x + rectangle.width - 10 - (rectangle.width - 10) / 4} ${rectangle.y +
2613
+ rectangle.height -
2614
+ (rectangle.height / 9) * 3}, ${rectangle.x + (rectangle.width - 10) / 2} ${rectangle.y +
2615
+ rectangle.height -
2616
+ rectangle.height / 9} T${rectangle.x} ${rectangle.y + rectangle.height - rectangle.height / 9}
2617
+
2618
+ M${rectangle.x + 5} ${rectangle.y + 10} H${rectangle.x + rectangle.width - 10} V${rectangle.y +
2619
+ rectangle.height -
2620
+ rectangle.height / 9}
2621
+
2622
+ M${rectangle.x + 10} ${rectangle.y + 5} H${rectangle.x + rectangle.width - 5} V${rectangle.y +
2623
+ rectangle.height -
2624
+ rectangle.height / 9 -
2625
+ 10 -
2626
+ 3}
2627
+ `, { ...options, fillStyle: 'solid' });
2628
+ setStrokeLinecap(shape, 'round');
2629
+ return shape;
2630
+ },
2631
+ isInsidePoint(rectangle, point) {
2632
+ const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
2633
+ return RectangleClient.isHit(rectangle, rangeRectangle);
2634
+ },
2635
+ getCornerPoints(rectangle) {
2636
+ return RectangleClient.getCornerPoints(rectangle);
2637
+ },
2638
+ getNearestPoint(rectangle, point) {
2639
+ return getNearestPointBetweenPointAndSegments(point, getMultiDocumentPoints(rectangle), false);
2640
+ },
2641
+ getConnectorPoints(rectangle) {
2642
+ let curvePoints = catmullRomFitting([
2643
+ [rectangle.x, rectangle.y + rectangle.height - rectangle.height / 9],
2644
+ [rectangle.x + (rectangle.width - 10) / 4, rectangle.y + rectangle.height],
2645
+ [rectangle.x + (rectangle.width - 10) / 2, rectangle.y + rectangle.height - rectangle.height / 9],
2646
+ [rectangle.x + ((rectangle.width - 10) / 4) * 3, rectangle.y + rectangle.height - (rectangle.height / 9) * 2],
2647
+ [rectangle.x + rectangle.width - 10, rectangle.y + rectangle.height - rectangle.height / 9]
2648
+ ]);
2649
+ curvePoints = pointsOnBezierCurves(curvePoints);
2650
+ const crossingPoint = getNearestPointBetweenPointAndSegments([rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height], curvePoints);
2651
+ return [
2652
+ [rectangle.x + rectangle.width / 2, rectangle.y],
2653
+ [rectangle.x + rectangle.width, rectangle.y + rectangle.height / 2],
2654
+ [crossingPoint[0], crossingPoint[1]],
2655
+ [rectangle.x, rectangle.y + rectangle.height / 2]
2656
+ ];
2657
+ },
2658
+ getNearestCrossingPoint(rectangle, point) {
2659
+ const crossingPoints = getCrossingPointBetweenPointAndPolygon(getMultiDocumentPoints(rectangle), point);
2660
+ let nearestPoint = crossingPoints[0];
2661
+ let nearestDistance = distanceBetweenPointAndPoint(point[0], point[1], nearestPoint[0], nearestPoint[1]);
2662
+ crossingPoints
2663
+ .filter((v, index) => index > 0)
2664
+ .forEach(crossingPoint => {
2665
+ let distance = distanceBetweenPointAndPoint(point[0], point[1], crossingPoint[0], crossingPoint[1]);
2666
+ if (distance < nearestDistance) {
2667
+ nearestDistance = distance;
2668
+ nearestPoint = crossingPoint;
2669
+ }
2670
+ });
2671
+ return nearestPoint;
2672
+ },
2673
+ getTangentVectorByConnectionPoint(rectangle, pointOfRectangle) {
2674
+ const connectionPoint = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
2675
+ if (connectionPoint[0] > rectangle.x && connectionPoint[0] < rectangle.x + (rectangle.width - 10) / 4) {
2676
+ return getUnitVectorByPointAndPoint([rectangle.x + (rectangle.width - 10) / 4, rectangle.y + rectangle.height], connectionPoint);
2677
+ }
2678
+ if (connectionPoint[0] > rectangle.x + (rectangle.width - 10) / 4 &&
2679
+ connectionPoint[0] < rectangle.x + ((rectangle.width - 10) / 4) * 3) {
2680
+ return getUnitVectorByPointAndPoint([rectangle.x + ((rectangle.width - 10) / 4) * 3, rectangle.y + rectangle.height - rectangle.height / 9], [rectangle.x + (rectangle.width - 10) / 4, rectangle.y + rectangle.height]);
2681
+ }
2682
+ if (connectionPoint[0] > rectangle.x + ((rectangle.width - 10) / 4) * 3 &&
2683
+ connectionPoint[0] < rectangle.x + rectangle.width - 10) {
2684
+ return getUnitVectorByPointAndPoint([rectangle.x + (rectangle.width - 10), rectangle.y + rectangle.height - rectangle.height / 9], connectionPoint);
2685
+ }
2686
+ const direction = getDirectionByPointOfRectangle(pointOfRectangle) || Direction.bottom;
2687
+ const factor = getDirectionFactor(direction);
2688
+ return [factor.x, factor.y];
2689
+ },
2690
+ getTextRectangle: (element) => {
2691
+ const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
2692
+ const strokeWidth = getStrokeWidthByElement(element);
2693
+ const height = element.textHeight;
2694
+ const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2 - elementRectangle.width * 0.06 * 2;
2695
+ return {
2696
+ height,
2697
+ width: width > 0 ? width - 10 : 0,
2698
+ x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth + elementRectangle.width * 0.06,
2699
+ y: elementRectangle.y + (elementRectangle.height - height) / 2
2700
+ };
2701
+ }
2702
+ };
2703
+
2704
+ const DatabaseEngine = {
2705
+ draw(board, rectangle, options) {
2706
+ const rs = PlaitBoard.getRoughSVG(board);
2707
+ const shape = rs.path(`M${rectangle.x} ${rectangle.y + rectangle.height * 0.15}
2708
+ A${rectangle.width / 2} ${rectangle.height * 0.15}, 0, 0, 0,${rectangle.x + rectangle.width} ${rectangle.y +
2709
+ rectangle.height * 0.15}
2710
+ A${rectangle.width / 2} ${rectangle.height * 0.15}, 0, 0, 0,${rectangle.x} ${rectangle.y + rectangle.height * 0.15}
2711
+ V${rectangle.y + rectangle.height - rectangle.height * 0.15}
2712
+ A${rectangle.width / 2} ${rectangle.height * 0.15}, 0, 0, 0, ${rectangle.x + rectangle.width} ${rectangle.y +
2713
+ rectangle.height -
2714
+ rectangle.height * 0.15}
2715
+ V${rectangle.y + rectangle.height * 0.15}`, { ...options, fillStyle: 'solid' });
2716
+ setStrokeLinecap(shape, 'round');
2717
+ return shape;
2718
+ },
2719
+ isInsidePoint(rectangle, point) {
2720
+ const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
2721
+ const isInRectangle = RectangleClient.isHit({
2722
+ ...rectangle,
2723
+ y: rectangle.y + rectangle.height * 0.15,
2724
+ height: rectangle.height - rectangle.height * 0.3
2725
+ }, rangeRectangle);
2726
+ const isInTopEllipse = isPointInEllipse(point, [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height * 0.15], rectangle.width / 2, rectangle.height * 0.15);
2727
+ const isInBottomEllipse = isPointInEllipse(point, [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height - rectangle.height * 0.15], rectangle.width / 2, rectangle.height * 0.15);
2728
+ return isInRectangle || isInTopEllipse || isInBottomEllipse;
2729
+ },
2730
+ getCornerPoints(rectangle) {
2731
+ return RectangleClient.getCornerPoints(rectangle);
2732
+ },
2733
+ getNearestPoint(rectangle, point) {
2734
+ const nearestPoint = getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
2735
+ if (nearestPoint[1] < rectangle.y + rectangle.height * 0.15) {
2736
+ const centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height * 0.15];
2737
+ const nearestPoint = getNearestPointBetweenPointAndEllipse(point, centerPoint, rectangle.width / 2, rectangle.height * 0.15);
2738
+ if (nearestPoint[1] > centerPoint[1]) {
2739
+ nearestPoint[1] = centerPoint[1] * 2 - nearestPoint[1];
2740
+ }
2741
+ return nearestPoint;
2742
+ }
2743
+ if (nearestPoint[1] > rectangle.y + rectangle.height - rectangle.height * 0.15) {
2744
+ const centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height - rectangle.height * 0.15];
2745
+ const nearestPoint = getNearestPointBetweenPointAndEllipse(point, centerPoint, rectangle.width / 2, rectangle.height * 0.15);
2746
+ if (nearestPoint[1] < centerPoint[1]) {
2747
+ nearestPoint[1] = centerPoint[0] * 2 - nearestPoint[1];
2748
+ }
2749
+ return nearestPoint;
2750
+ }
2751
+ return nearestPoint;
2752
+ },
2753
+ getConnectorPoints(rectangle) {
2754
+ return RectangleClient.getEdgeCenterPoints(rectangle);
2755
+ },
2756
+ getTangentVectorByConnectionPoint(rectangle, pointOfRectangle) {
2757
+ const connectionPoint = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
2758
+ let centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height - rectangle.height * 0.15];
2759
+ let a = rectangle.width / 2;
2760
+ let b = rectangle.height * 0.15;
2761
+ const isInTopEllipse = connectionPoint[1] < rectangle.y + rectangle.height * 0.15 && connectionPoint[0] > rectangle.x;
2762
+ if (isInTopEllipse) {
2763
+ centerPoint = [rectangle.x + rectangle.width / 2, rectangle.y + rectangle.height * 0.15];
2764
+ }
2765
+ const point = [connectionPoint[0] - centerPoint[0], -(connectionPoint[1] - centerPoint[1])];
2766
+ const slope = getEllipseTangentSlope(point[0], point[1], a, b);
2767
+ const vector = getVectorFromPointAndSlope(point[0], point[1], slope);
2768
+ return vector;
2769
+ },
2770
+ getTextRectangle: (element) => {
2771
+ const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
2772
+ const strokeWidth = getStrokeWidthByElement(element);
2773
+ const height = element.textHeight;
2774
+ const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
2775
+ return {
2776
+ height,
2777
+ width: width > 0 ? width : 0,
2778
+ x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth,
2779
+ y: elementRectangle.y + elementRectangle.height * 0.3 + (elementRectangle.height - elementRectangle.height * 0.45 - height) / 2
2780
+ };
2781
+ }
2782
+ };
2783
+
2784
+ const HardDiskEngine = {
2785
+ draw(board, rectangle, options) {
2786
+ const rs = PlaitBoard.getRoughSVG(board);
2787
+ const shape = rs.path(`M${rectangle.x + rectangle.width - rectangle.width * 0.15} ${rectangle.y}
2788
+ A${rectangle.width * 0.15} ${rectangle.height / 2}, 0, 0, 0,${rectangle.x +
2789
+ rectangle.width -
2790
+ rectangle.width * 0.15} ${rectangle.y + rectangle.height}
2791
+ A${rectangle.width * 0.15} ${rectangle.height / 2}, 0, 0, 0,${rectangle.x + rectangle.width - rectangle.width * 0.15} ${rectangle.y}
2792
+ H${rectangle.x + rectangle.width * 0.15}
2793
+ A${rectangle.width * 0.15} ${rectangle.height / 2}, 0, 0, 0, ${rectangle.x + rectangle.width * 0.15} ${rectangle.y +
2794
+ rectangle.height}
2795
+ H${rectangle.x + rectangle.width - rectangle.width * 0.15}`, { ...options, fillStyle: 'solid' });
2796
+ setStrokeLinecap(shape, 'round');
2797
+ return shape;
2798
+ },
2799
+ isInsidePoint(rectangle, point) {
2800
+ const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
2801
+ const isInRectangle = RectangleClient.isHit({
2802
+ ...rectangle,
2803
+ x: rectangle.x + rectangle.width * 0.15,
2804
+ width: rectangle.width - rectangle.width * 0.3
2805
+ }, rangeRectangle);
2806
+ const isInLeftEllipse = isPointInEllipse(point, [rectangle.x + rectangle.width * 0.15, rectangle.y + rectangle.height / 2], rectangle.width * 0.15, rectangle.height / 2);
2807
+ const isInRightEllipse = isPointInEllipse(point, [rectangle.x + rectangle.width - rectangle.width * 0.15, rectangle.y + rectangle.height / 2], rectangle.width * 0.15, rectangle.height / 2);
2808
+ return isInRectangle || isInLeftEllipse || isInRightEllipse;
2809
+ },
2810
+ getCornerPoints(rectangle) {
2811
+ return RectangleClient.getCornerPoints(rectangle);
2812
+ },
2813
+ getNearestPoint(rectangle, point) {
2814
+ const nearestPoint = getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
2815
+ if (nearestPoint[0] < rectangle.x + rectangle.width * 0.15) {
2816
+ const centerPoint = [rectangle.x + rectangle.width * 0.15, rectangle.y + rectangle.height / 2];
2817
+ const nearestPoint = getNearestPointBetweenPointAndEllipse(point, centerPoint, rectangle.width * 0.15, rectangle.height / 2);
2818
+ if (nearestPoint[0] > centerPoint[0]) {
2819
+ nearestPoint[0] = centerPoint[0] * 2 - nearestPoint[0];
2820
+ }
2821
+ return nearestPoint;
2822
+ }
2823
+ if (nearestPoint[0] > rectangle.x + rectangle.width - rectangle.width * 0.15) {
2824
+ const centerPoint = [rectangle.x + rectangle.width - rectangle.width * 0.15, rectangle.y + rectangle.height / 2];
2825
+ const nearestPoint = getNearestPointBetweenPointAndEllipse(point, centerPoint, rectangle.width * 0.15, rectangle.height / 2);
2826
+ if (nearestPoint[0] < centerPoint[0]) {
2827
+ nearestPoint[0] = centerPoint[0] * 2 - nearestPoint[0];
2828
+ }
2829
+ return nearestPoint;
2830
+ }
2831
+ return nearestPoint;
2832
+ },
2833
+ getConnectorPoints(rectangle) {
2834
+ return RectangleClient.getEdgeCenterPoints(rectangle);
2835
+ },
2836
+ getTangentVectorByConnectionPoint(rectangle, pointOfRectangle) {
2837
+ const connectionPoint = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
2838
+ let centerPoint = [rectangle.x + rectangle.width * 0.15, rectangle.y + rectangle.height / 2];
2839
+ let a = rectangle.width * 0.15;
2840
+ let b = rectangle.height / 2;
2841
+ const isInRightEllipse = connectionPoint[0] > rectangle.x + rectangle.width - rectangle.width * 0.15 && connectionPoint[1] > rectangle.y;
2842
+ if (isInRightEllipse) {
2843
+ centerPoint = [rectangle.x + rectangle.width - rectangle.width * 0.15, rectangle.y + rectangle.height / 2];
2844
+ }
2845
+ const point = [connectionPoint[0] - centerPoint[0], -(connectionPoint[1] - centerPoint[1])];
2846
+ const slope = getEllipseTangentSlope(point[0], point[1], a, b);
2847
+ const vector = getVectorFromPointAndSlope(point[0], point[1], slope);
2848
+ return vector;
2849
+ },
2850
+ getTextRectangle: (element) => {
2851
+ const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
2852
+ const strokeWidth = getStrokeWidthByElement(element);
2853
+ const height = element.textHeight;
2854
+ const width = elementRectangle.width - elementRectangle.width * 0.45 - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
2855
+ return {
2856
+ height,
2857
+ width: width > 0 ? width : 0,
2858
+ x: elementRectangle.x + elementRectangle.width * 0.15 + ShapeDefaultSpace.rectangleAndText + strokeWidth,
2859
+ y: elementRectangle.y + (elementRectangle.height - height) / 2
2860
+ };
2861
+ }
2862
+ };
2863
+
2864
+ const InternalStorageEngine = {
2865
+ draw(board, rectangle, options) {
2866
+ const rs = PlaitBoard.getRoughSVG(board);
2867
+ const shape = rs.path(`M${rectangle.x} ${rectangle.y} h${rectangle.width} v${rectangle.height} h${-rectangle.width} v${-rectangle.height}
2868
+ M${rectangle.x} ${rectangle.y + rectangle.height / 10} h${rectangle.width}
2869
+ M${rectangle.x + rectangle.width / 10} ${rectangle.y} v${rectangle.height}
2870
+ `, { ...options, fillStyle: 'solid' });
2871
+ setStrokeLinecap(shape, 'round');
2872
+ return shape;
2873
+ },
2874
+ isInsidePoint(rectangle, point) {
2875
+ const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
2876
+ return RectangleClient.isHit(rectangle, rangeRectangle);
2877
+ },
2878
+ getCornerPoints(rectangle) {
2879
+ return RectangleClient.getCornerPoints(rectangle);
2880
+ },
2881
+ getNearestPoint(rectangle, point) {
2882
+ return getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
2883
+ },
2884
+ getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
2885
+ const corners = RectangleEngine.getCornerPoints(rectangle);
2886
+ const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
2887
+ return getPolygonEdgeByConnectionPoint(corners, point);
2888
+ },
2889
+ getConnectorPoints(rectangle) {
2890
+ return RectangleClient.getEdgeCenterPoints(rectangle);
2891
+ },
2892
+ getTextRectangle: (element) => {
2893
+ const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
2894
+ const strokeWidth = getStrokeWidthByElement(element);
2895
+ const height = element.textHeight;
2896
+ const width = elementRectangle.width - elementRectangle.width * 0.1 - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
2897
+ return {
2898
+ height,
2899
+ width: width > 0 ? width : 0,
2900
+ x: elementRectangle.x + elementRectangle.width * 0.1 + ShapeDefaultSpace.rectangleAndText + strokeWidth,
2901
+ y: elementRectangle.y + elementRectangle.height * 0.1 + (elementRectangle.height - elementRectangle.height * 0.1 - height) / 2
2902
+ };
2903
+ }
2904
+ };
2905
+
2906
+ const NoteCurlyLeftEngine = {
2907
+ draw(board, rectangle, options) {
2908
+ const rs = PlaitBoard.getRoughSVG(board);
2909
+ const shape = rs.path(`M${rectangle.x + rectangle.width} ${rectangle.y}
2910
+ C${rectangle.x + rectangle.width - rectangle.width * 0.09} ${rectangle.y},
2911
+ ${rectangle.x + rectangle.width} ${rectangle.y + rectangle.height / 2},
2912
+ ${rectangle.x + rectangle.width - rectangle.width * 0.09} ${rectangle.y + rectangle.height / 2}
2913
+ C${rectangle.x + rectangle.width} ${rectangle.y + rectangle.height / 2},
2914
+ ${rectangle.x + rectangle.width - rectangle.width * 0.09} ${rectangle.y + rectangle.height},
2915
+ ${rectangle.x + rectangle.width} ${rectangle.y + rectangle.height}`, { ...options, fillStyle: 'solid' });
2916
+ setStrokeLinecap(shape, 'round');
2917
+ return shape;
2918
+ },
2919
+ isInsidePoint(rectangle, point) {
2920
+ const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
2921
+ return RectangleClient.isHit(rectangle, rangeRectangle);
2922
+ },
2923
+ getCornerPoints(rectangle) {
2924
+ return RectangleClient.getCornerPoints(rectangle);
2925
+ },
2926
+ getNearestPoint(rectangle, point) {
2927
+ return getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
2928
+ },
2929
+ getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
2930
+ const corners = RectangleEngine.getCornerPoints(rectangle);
2931
+ const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
2932
+ return getPolygonEdgeByConnectionPoint(corners, point);
2933
+ },
2934
+ getConnectorPoints(rectangle) {
2935
+ return RectangleClient.getEdgeCenterPoints(rectangle);
2936
+ },
2937
+ getTextRectangle: (element) => {
2938
+ const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
2939
+ const strokeWidth = getStrokeWidthByElement(element);
2940
+ const height = element.textHeight;
2941
+ const width = elementRectangle.width - elementRectangle.width * 0.09 - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
2942
+ return {
2943
+ height,
2944
+ width: width > 0 ? width : 0,
2945
+ x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth,
2946
+ y: elementRectangle.y + (elementRectangle.height - height) / 2
2947
+ };
2948
+ }
2949
+ };
2950
+
2951
+ const NoteCurlyRightEngine = {
2952
+ draw(board, rectangle, options) {
2953
+ const rs = PlaitBoard.getRoughSVG(board);
2954
+ const shape = rs.path(`M${rectangle.x} ${rectangle.y}
2955
+ C${rectangle.x + rectangle.width * 0.09} ${rectangle.y},
2956
+ ${rectangle.x} ${rectangle.y + rectangle.height / 2},
2957
+ ${rectangle.x + rectangle.width * 0.09} ${rectangle.y + rectangle.height / 2}
2958
+ C${rectangle.x} ${rectangle.y + rectangle.height / 2},
2959
+ ${rectangle.x + rectangle.width * 0.09} ${rectangle.y + rectangle.height},
2960
+ ${rectangle.x} ${rectangle.y + rectangle.height}`, { ...options, fillStyle: 'solid' });
2961
+ setStrokeLinecap(shape, 'round');
2962
+ return shape;
2963
+ },
2964
+ isInsidePoint(rectangle, point) {
2965
+ const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
2966
+ return RectangleClient.isHit(rectangle, rangeRectangle);
2967
+ },
2968
+ getCornerPoints(rectangle) {
2969
+ return RectangleClient.getCornerPoints(rectangle);
2970
+ },
2971
+ getNearestPoint(rectangle, point) {
2972
+ return getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
2973
+ },
2974
+ getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
2975
+ const corners = RectangleEngine.getCornerPoints(rectangle);
2976
+ const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
2977
+ return getPolygonEdgeByConnectionPoint(corners, point);
2978
+ },
2979
+ getConnectorPoints(rectangle) {
2980
+ return RectangleClient.getEdgeCenterPoints(rectangle);
2981
+ },
2982
+ getTextRectangle: (element) => {
2983
+ const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
2984
+ const strokeWidth = getStrokeWidthByElement(element);
2985
+ const height = element.textHeight;
2986
+ const width = elementRectangle.width - elementRectangle.width * 0.09 - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
2987
+ return {
2988
+ height,
2989
+ width: width > 0 ? width : 0,
2990
+ x: elementRectangle.x + elementRectangle.width * 0.09 + ShapeDefaultSpace.rectangleAndText + strokeWidth,
2991
+ y: elementRectangle.y + (elementRectangle.height - height) / 2
2992
+ };
2993
+ }
2994
+ };
2995
+
2996
+ const NoteSquareEngine = {
2997
+ draw(board, rectangle, options) {
2998
+ const rs = PlaitBoard.getRoughSVG(board);
2999
+ const shape = rs.path(`M${rectangle.x + rectangle.width * 0.075} ${rectangle.y + rectangle.height} H${rectangle.x} V${rectangle.y} H${rectangle.x +
3000
+ rectangle.width * 0.075}
3001
+ `, { ...options, fillStyle: 'solid' });
3002
+ setStrokeLinecap(shape, 'round');
3003
+ return shape;
3004
+ },
3005
+ isInsidePoint(rectangle, point) {
3006
+ const rangeRectangle = RectangleClient.getRectangleByPoints([point, point]);
3007
+ return RectangleClient.isHit(rectangle, rangeRectangle);
3008
+ },
3009
+ getCornerPoints(rectangle) {
3010
+ return RectangleClient.getCornerPoints(rectangle);
3011
+ },
3012
+ getNearestPoint(rectangle, point) {
3013
+ return getNearestPointBetweenPointAndSegments(point, RectangleEngine.getCornerPoints(rectangle));
3014
+ },
3015
+ getEdgeByConnectionPoint(rectangle, pointOfRectangle) {
3016
+ const corners = RectangleEngine.getCornerPoints(rectangle);
3017
+ const point = RectangleClient.getConnectionPoint(rectangle, pointOfRectangle);
3018
+ return getPolygonEdgeByConnectionPoint(corners, point);
3019
+ },
3020
+ getConnectorPoints(rectangle) {
3021
+ return RectangleClient.getEdgeCenterPoints(rectangle);
3022
+ },
3023
+ getTextRectangle: (element) => {
3024
+ const elementRectangle = RectangleClient.getRectangleByPoints(element.points);
3025
+ const strokeWidth = getStrokeWidthByElement(element);
3026
+ const height = element.textHeight;
3027
+ const width = elementRectangle.width - ShapeDefaultSpace.rectangleAndText * 2 - strokeWidth * 2;
3028
+ return {
3029
+ height,
3030
+ width: width > 0 ? width : 0,
3031
+ x: elementRectangle.x + ShapeDefaultSpace.rectangleAndText + strokeWidth,
3032
+ y: elementRectangle.y + (elementRectangle.height - height) / 2
3033
+ };
3034
+ }
3035
+ };
3036
+
2492
3037
  const ShapeEngineMap = {
2493
3038
  [BasicShapes.rectangle]: RectangleEngine,
2494
3039
  [BasicShapes.diamond]: DiamondEngine,
@@ -2516,6 +3061,9 @@ const ShapeEngineMap = {
2516
3061
  [FlowchartSymbols.connector]: EllipseEngine,
2517
3062
  [FlowchartSymbols.data]: ParallelogramEngine,
2518
3063
  [FlowchartSymbols.terminal]: TerminalEngine,
3064
+ [FlowchartSymbols.database]: DatabaseEngine,
3065
+ [FlowchartSymbols.hardDisk]: HardDiskEngine,
3066
+ [FlowchartSymbols.internalStorage]: InternalStorageEngine,
2519
3067
  [FlowchartSymbols.manualInput]: ManualInputEngine,
2520
3068
  [FlowchartSymbols.preparation]: PreparationEngine,
2521
3069
  [FlowchartSymbols.manualLoop]: ManualLoopEngine,
@@ -2525,7 +3073,12 @@ const ShapeEngineMap = {
2525
3073
  [FlowchartSymbols.or]: OrEngine,
2526
3074
  [FlowchartSymbols.summingJunction]: SummingJunctionEngine,
2527
3075
  [FlowchartSymbols.predefinedProcess]: PredefinedProcessEngine,
2528
- [FlowchartSymbols.offPage]: OffPageEngine
3076
+ [FlowchartSymbols.offPage]: OffPageEngine,
3077
+ [FlowchartSymbols.document]: DocumentEngine,
3078
+ [FlowchartSymbols.multiDocument]: MultiDocumentEngine,
3079
+ [FlowchartSymbols.noteCurlyLeft]: NoteCurlyLeftEngine,
3080
+ [FlowchartSymbols.noteCurlyRight]: NoteCurlyRightEngine,
3081
+ [FlowchartSymbols.noteSquare]: NoteSquareEngine
2529
3082
  };
2530
3083
  const getEngine = (shape) => {
2531
3084
  return ShapeEngineMap[shape];
@@ -2635,7 +3188,7 @@ const createDefaultFlowchart = (point) => {
2635
3188
  const processPoint1 = [point[0], point[1] + terminalProperty.height / 2 + 55 + processProperty.height / 2];
2636
3189
  const processElement1 = createGeometryElement(FlowchartSymbols.process, getDefaultGeometryPoints(FlowchartSymbols.process, processPoint1), '过程', options);
2637
3190
  const decisionPoint = [processPoint1[0], processPoint1[1] + processProperty.height / 2 + 55 + decisionProperty.height / 2];
2638
- const decisionElement = createGeometryElement(FlowchartSymbols.decision, getDefaultGeometryPoints(FlowchartSymbols.decision, decisionPoint), '过程', options);
3191
+ const decisionElement = createGeometryElement(FlowchartSymbols.decision, getDefaultGeometryPoints(FlowchartSymbols.decision, decisionPoint), '判断', options);
2639
3192
  const processPoint2 = [decisionPoint[0] + decisionProperty.width / 2 + 75 + processProperty.width / 2, decisionPoint[1]];
2640
3193
  const processElement2 = createGeometryElement(FlowchartSymbols.process, getDefaultGeometryPoints(FlowchartSymbols.process, processPoint2), '过程', options);
2641
3194
  const endPoint = [decisionPoint[0], decisionPoint[1] + decisionProperty.height / 2 + 95 + terminalProperty.height / 2];
@@ -2747,6 +3300,10 @@ const createDefaultGeometry = (board, points, shape) => {
2747
3300
  ...memorizedLatest.geometryProperties
2748
3301
  }, { ...memorizedLatest.textProperties, textHeight });
2749
3302
  };
3303
+ const editText = (element) => {
3304
+ const textManage = getFirstTextManage(element);
3305
+ textManage.edit();
3306
+ };
2750
3307
 
2751
3308
  const getStrokeWidthByElement = (element) => {
2752
3309
  if (PlaitDrawElement.isText(element)) {
@@ -3274,6 +3831,7 @@ const DrawTransforms = {
3274
3831
  };
3275
3832
 
3276
3833
  class LineAutoCompleteGenerator extends Generator {
3834
+ static { this.key = 'line-auto-complete-generator'; }
3277
3835
  constructor(board) {
3278
3836
  super(board);
3279
3837
  this.board = board;
@@ -3315,14 +3873,13 @@ class LineAutoCompleteGenerator extends Generator {
3315
3873
  }
3316
3874
 
3317
3875
  class GeometryComponent extends CommonPluginElement {
3876
+ constructor() {
3877
+ super(...arguments);
3878
+ this.destroy$ = new Subject();
3879
+ }
3318
3880
  get textManage() {
3319
3881
  return this.getTextManages()[0];
3320
3882
  }
3321
- constructor(cdr) {
3322
- super(cdr);
3323
- this.cdr = cdr;
3324
- this.destroy$ = new Subject();
3325
- }
3326
3883
  initializeGenerator() {
3327
3884
  this.activeGenerator = new ActiveGenerator(this.board, {
3328
3885
  getStrokeWidth: () => {
@@ -3347,16 +3904,13 @@ class GeometryComponent extends CommonPluginElement {
3347
3904
  return RectangleClient.getRectangleByPoints(element.points);
3348
3905
  },
3349
3906
  hasResizeHandle: () => {
3350
- const selectedElements = getSelectedElements(this.board);
3351
- if (PlaitBoard.hasBeenTextEditing(this.board) && PlaitDrawElement.isText(this.element)) {
3352
- return false;
3353
- }
3354
- return selectedElements.length === 1 && !isSelectionMoving(this.board);
3907
+ return canResize(this.board, this.element);
3355
3908
  }
3356
3909
  });
3357
3910
  this.lineAutoCompleteGenerator = new LineAutoCompleteGenerator(this.board);
3358
3911
  this.shapeGenerator = new GeometryShapeGenerator(this.board);
3359
3912
  this.initializeTextManage();
3913
+ this.getRef().addGenerator(LineAutoCompleteGenerator.key, this.lineAutoCompleteGenerator);
3360
3914
  }
3361
3915
  ngOnInit() {
3362
3916
  super.ngOnInit();
@@ -3369,6 +3923,7 @@ class GeometryComponent extends CommonPluginElement {
3369
3923
  this.drawText();
3370
3924
  }
3371
3925
  onContextChanged(value, previous) {
3926
+ this.initializeWeakMap();
3372
3927
  const isChangeTheme = this.board.operations.find(op => op.type === 'set_theme');
3373
3928
  if (value.element !== previous.element || isChangeTheme) {
3374
3929
  this.shapeGenerator.processDrawing(this.element, this.getElementG());
@@ -3389,10 +3944,6 @@ class GeometryComponent extends CommonPluginElement {
3389
3944
  }
3390
3945
  }
3391
3946
  }
3392
- editText() {
3393
- this.textManage.edit();
3394
- this.activeGenerator.processDrawing(this.element, PlaitBoard.getElementActiveHost(this.board), { selected: this.selected });
3395
- }
3396
3947
  drawText() {
3397
3948
  this.textManage.draw(this.element.text);
3398
3949
  this.getElementG().append(this.textManage.g);
@@ -3440,13 +3991,13 @@ class GeometryComponent extends CommonPluginElement {
3440
3991
  }
3441
3992
  ngOnDestroy() {
3442
3993
  super.ngOnDestroy();
3443
- this.textManage.destroy();
3444
3994
  this.destroy$.next();
3445
3995
  this.destroy$.complete();
3446
3996
  this.activeGenerator.destroy();
3447
3997
  this.lineAutoCompleteGenerator.destroy();
3998
+ this.destroyTextManages();
3448
3999
  }
3449
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: GeometryComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
4000
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: GeometryComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3450
4001
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: GeometryComponent, isStandalone: true, selector: "plait-draw-geometry", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3451
4002
  }
3452
4003
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: GeometryComponent, decorators: [{
@@ -3457,7 +4008,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
3457
4008
  changeDetection: ChangeDetectionStrategy.OnPush,
3458
4009
  standalone: true
3459
4010
  }]
3460
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }] });
4011
+ }] });
3461
4012
 
3462
4013
  class LineActiveGenerator extends Generator {
3463
4014
  constructor() {
@@ -3491,19 +4042,21 @@ class LineActiveGenerator extends Generator {
3491
4042
  activeG.appendChild(updateHandle);
3492
4043
  });
3493
4044
  const middlePoints = getMiddlePoints(this.board, element);
3494
- for (let i = 0; i < middlePoints.length; i++) {
3495
- const point = middlePoints[i];
3496
- if (element.shape === LineShape.elbow && elbowNextRenderPoints.length) {
3497
- const handleIndex = getHitPointIndex(middlePoints, point);
3498
- const isUpdateHandleIndex = isUpdatedHandleIndex(this.board, element, [...points], elbowNextRenderPoints, handleIndex);
3499
- if (isUpdateHandleIndex) {
3500
- const updateHandle = drawPrimaryHandle(this.board, point);
3501
- activeG.appendChild(updateHandle);
3502
- continue;
4045
+ if (!PlaitBoard.hasBeenTextEditing(this.board)) {
4046
+ for (let i = 0; i < middlePoints.length; i++) {
4047
+ const point = middlePoints[i];
4048
+ if (element.shape === LineShape.elbow && elbowNextRenderPoints.length) {
4049
+ const handleIndex = getHitPointIndex(middlePoints, point);
4050
+ const isUpdateHandleIndex = isUpdatedHandleIndex(this.board, element, [...points], elbowNextRenderPoints, handleIndex);
4051
+ if (isUpdateHandleIndex) {
4052
+ const updateHandle = drawPrimaryHandle(this.board, point);
4053
+ activeG.appendChild(updateHandle);
4054
+ continue;
4055
+ }
3503
4056
  }
4057
+ const circle = drawFillPrimaryHandle(this.board, point);
4058
+ activeG.appendChild(circle);
3504
4059
  }
3505
- const circle = drawFillPrimaryHandle(this.board, point);
3506
- activeG.appendChild(circle);
3507
4060
  }
3508
4061
  }
3509
4062
  else {
@@ -3533,9 +4086,8 @@ class LineActiveGenerator extends Generator {
3533
4086
  const debugKey$2 = 'debug:plait:line-turning';
3534
4087
  const debugGenerator$2 = createDebugGenerator(debugKey$2);
3535
4088
  class LineComponent extends CommonPluginElement {
3536
- constructor(cdr) {
3537
- super(cdr);
3538
- this.cdr = cdr;
4089
+ constructor() {
4090
+ super(...arguments);
3539
4091
  this.destroy$ = new Subject();
3540
4092
  this.boundedElements = {};
3541
4093
  }
@@ -3574,6 +4126,7 @@ class LineComponent extends CommonPluginElement {
3574
4126
  return boundedElements;
3575
4127
  }
3576
4128
  onContextChanged(value, previous) {
4129
+ this.initializeWeakMap();
3577
4130
  const boundedElements = this.getBoundedElements();
3578
4131
  const isBoundedElementsChanged = boundedElements.source !== this.boundedElements.source || boundedElements.target !== this.boundedElements.target;
3579
4132
  this.boundedElements = boundedElements;
@@ -3678,7 +4231,7 @@ class LineComponent extends CommonPluginElement {
3678
4231
  this.destroy$.complete();
3679
4232
  this.destroyTextManages();
3680
4233
  }
3681
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: LineComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
4234
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: LineComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3682
4235
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: LineComponent, isStandalone: true, selector: "plait-draw-line", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3683
4236
  }
3684
4237
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: LineComponent, decorators: [{
@@ -3689,7 +4242,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
3689
4242
  changeDetection: ChangeDetectionStrategy.OnPush,
3690
4243
  standalone: true
3691
4244
  }]
3692
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }] });
4245
+ }] });
3693
4246
 
3694
4247
  const withDrawHotkey = (board) => {
3695
4248
  const { keyDown, dblClick } = board;
@@ -3704,7 +4257,7 @@ const withDrawHotkey = (board) => {
3704
4257
  isSingleSelection &&
3705
4258
  PlaitDrawElement.isGeometry(targetElement)) {
3706
4259
  event.preventDefault();
3707
- PlaitElement.getComponent(targetElement).editText();
4260
+ editText(targetElement);
3708
4261
  return;
3709
4262
  }
3710
4263
  keyDown(event);
@@ -3715,8 +4268,7 @@ const withDrawHotkey = (board) => {
3715
4268
  const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3716
4269
  const hitElement = getHitElementByPoint(board, point);
3717
4270
  if (hitElement && PlaitDrawElement.isGeometry(hitElement)) {
3718
- const component = PlaitElement.getComponent(hitElement);
3719
- component.editText();
4271
+ editText(hitElement);
3720
4272
  }
3721
4273
  }
3722
4274
  dblClick(event);
@@ -4150,8 +4702,20 @@ function drawIsometricSnapLines(board, activePoints, snapRectangles, resizeSnapO
4150
4702
  return drawSolidLines(board, isometricLines);
4151
4703
  }
4152
4704
 
4705
+ const isGeometryDndMode = (board) => {
4706
+ const geometryPointers = getGeometryPointers();
4707
+ const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
4708
+ const dndMode = isGeometryPointer && isDndMode(board);
4709
+ return dndMode;
4710
+ };
4711
+ const isGeometryDrawingMode = (board) => {
4712
+ const geometryPointers = getGeometryPointers();
4713
+ const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
4714
+ const drawingMode = isGeometryPointer && isDrawingMode(board);
4715
+ return drawingMode;
4716
+ };
4153
4717
  const withGeometryCreateByDrag = (board) => {
4154
- const { pointerMove, globalPointerUp } = board;
4718
+ const { pointerMove, globalPointerUp, pointerUp } = board;
4155
4719
  let geometryShapeG = null;
4156
4720
  let temporaryElement = null;
4157
4721
  let fakeCreateTextRef = null;
@@ -4202,11 +4766,14 @@ const withGeometryCreateByDrag = (board) => {
4202
4766
  }
4203
4767
  pointerMove(event);
4204
4768
  };
4769
+ board.pointerUp = (event) => {
4770
+ if (isGeometryDndMode(board) && temporaryElement) {
4771
+ return;
4772
+ }
4773
+ pointerUp(event);
4774
+ };
4205
4775
  board.globalPointerUp = (event) => {
4206
- const geometryPointers = getGeometryPointers();
4207
- const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
4208
- const dragMode = isGeometryPointer && isDndMode(board);
4209
- if (dragMode && temporaryElement) {
4776
+ if (isGeometryDndMode(board) && temporaryElement) {
4210
4777
  insertElement(board, temporaryElement);
4211
4778
  fakeCreateTextRef?.textManage.destroy();
4212
4779
  fakeCreateTextRef?.g.remove();
@@ -4235,9 +4802,7 @@ const withGeometryCreateByDrawing = (board) => {
4235
4802
  keyUp(event);
4236
4803
  };
4237
4804
  board.pointerDown = (event) => {
4238
- const geometryPointers = getGeometryPointers();
4239
- const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
4240
- if (!PlaitBoard.isReadonly(board) && isGeometryPointer && isDrawingMode(board)) {
4805
+ if (!PlaitBoard.isReadonly(board) && isGeometryDrawingMode(board)) {
4241
4806
  const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
4242
4807
  start = point;
4243
4808
  const pointer = PlaitBoard.getPointer(board);
@@ -4260,7 +4825,7 @@ const withGeometryCreateByDrawing = (board) => {
4260
4825
  const movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
4261
4826
  const pointer = PlaitBoard.getPointer(board);
4262
4827
  snapG?.remove();
4263
- if (start && pointer !== BasicShapes.text) {
4828
+ if (start && isGeometryDrawingMode(board)) {
4264
4829
  let points = normalizeShapePoints([start, movingPoint], isShift);
4265
4830
  const activeRectangle = RectangleClient.getRectangleByPoints(points);
4266
4831
  const [x, y] = getUnitVectorByPointAndPoint(start, movingPoint);
@@ -4282,27 +4847,27 @@ const withGeometryCreateByDrawing = (board) => {
4282
4847
  pointerMove(event);
4283
4848
  };
4284
4849
  board.pointerUp = (event) => {
4285
- const isDrawMode = !!start;
4286
- if (isDrawMode) {
4850
+ if (isGeometryDrawingMode(board) && start) {
4287
4851
  const targetPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
4288
4852
  const { width, height } = RectangleClient.getRectangleByPoints([start, targetPoint]);
4289
- if (Math.hypot(width, height) === 0) {
4853
+ if (Math.hypot(width, height) < 8) {
4290
4854
  const pointer = PlaitBoard.getPointer(board);
4291
4855
  if (pointer !== BasicShapes.text) {
4292
4856
  const points = getDefaultGeometryPoints(pointer, targetPoint);
4293
4857
  temporaryElement = createDefaultGeometry(board, points, pointer);
4294
4858
  }
4295
4859
  }
4860
+ if (temporaryElement) {
4861
+ insertElement(board, temporaryElement);
4862
+ }
4863
+ snapG?.remove();
4864
+ geometryShapeG?.remove();
4865
+ geometryShapeG = null;
4866
+ start = null;
4867
+ temporaryElement = null;
4868
+ preventTouchMove(board, event, false);
4869
+ return;
4296
4870
  }
4297
- if (temporaryElement) {
4298
- insertElement(board, temporaryElement);
4299
- }
4300
- snapG?.remove();
4301
- geometryShapeG?.remove();
4302
- geometryShapeG = null;
4303
- start = null;
4304
- temporaryElement = null;
4305
- preventTouchMove(board, event, false);
4306
4871
  pointerUp(event);
4307
4872
  };
4308
4873
  return board;
@@ -4389,8 +4954,8 @@ const withDrawFragment = (baseBoard) => {
4389
4954
  }
4390
4955
  return getDeletedFragment(data);
4391
4956
  };
4392
- board.buildFragment = (clipboardContext, rectangle, type) => {
4393
- const targetDrawElements = getSelectedDrawElements(board);
4957
+ board.buildFragment = (clipboardContext, rectangle, type, originData) => {
4958
+ const targetDrawElements = getSelectedDrawElements(board, originData);
4394
4959
  let boundLineElements = [];
4395
4960
  if (targetDrawElements.length) {
4396
4961
  if (type === 'cut') {
@@ -4412,7 +4977,7 @@ const withDrawFragment = (baseBoard) => {
4412
4977
  });
4413
4978
  }
4414
4979
  }
4415
- return buildFragment(clipboardContext, rectangle, type);
4980
+ return buildFragment(clipboardContext, rectangle, type, originData);
4416
4981
  };
4417
4982
  board.insertFragment = (clipboardData, targetPoint) => {
4418
4983
  const selectedElements = getSelectedElements(board);
@@ -4514,8 +5079,7 @@ const withGeometryResize = (board) => {
4514
5079
  return null;
4515
5080
  }
4516
5081
  const target = selectedElements[0];
4517
- const targetComponent = PlaitElement.getComponent(selectedElements[0]);
4518
- if (targetComponent.activeGenerator.hasResizeHandle) {
5082
+ if (canResize(board, target)) {
4519
5083
  const rectangle = board.getRectangle(target);
4520
5084
  const handleRef = getHitRectangleResizeHandleRef(board, rectangle, point, target.angle);
4521
5085
  if (handleRef) {
@@ -4766,6 +5330,7 @@ const withLineText = (board) => {
4766
5330
  const hitTarget = getHitElementByPoint(board, clickPoint, (element) => {
4767
5331
  return PlaitDrawElement.isLine(element);
4768
5332
  });
5333
+ const hitTargetPath = hitTarget && PlaitBoard.findPath(board, hitTarget);
4769
5334
  if (hitTarget) {
4770
5335
  const points = getLinePoints(board, hitTarget);
4771
5336
  const point = getNearestPointBetweenPointAndSegments(clickPoint, points);
@@ -4785,8 +5350,11 @@ const withLineText = (board) => {
4785
5350
  });
4786
5351
  DrawTransforms.setLineTexts(board, hitTarget, texts);
4787
5352
  setTimeout(() => {
4788
- const hitComponent = PlaitElement.getComponent(hitTarget);
4789
- editHandle(board, hitTarget, hitComponent.getTextManages().length - 1, true);
5353
+ if (hitTargetPath) {
5354
+ const newHitTarget = PlaitNode.get(board, hitTargetPath);
5355
+ const textManages = getTextManages(newHitTarget);
5356
+ editHandle(board, newHitTarget, textManages.length - 1, true);
5357
+ }
4790
5358
  });
4791
5359
  }
4792
5360
  }
@@ -4796,8 +5364,8 @@ const withLineText = (board) => {
4796
5364
  return board;
4797
5365
  };
4798
5366
  function editHandle(board, element, manageIndex, isFirstEdit = false) {
4799
- const hitComponent = PlaitElement.getComponent(element);
4800
- const textManage = hitComponent.getTextManages()[manageIndex];
5367
+ const textManages = getTextManages(element);
5368
+ const textManage = textManages[manageIndex];
4801
5369
  const originText = textManage.componentRef.instance.children;
4802
5370
  textManage.edit((origin, descendant) => {
4803
5371
  const text = Node.string(descendant[0]);
@@ -4809,14 +5377,13 @@ function editHandle(board, element, manageIndex, isFirstEdit = false) {
4809
5377
  }
4810
5378
 
4811
5379
  class ImageComponent extends CommonPluginElement {
5380
+ constructor() {
5381
+ super(...arguments);
5382
+ this.destroy$ = new Subject();
5383
+ }
4812
5384
  get activeGenerator() {
4813
5385
  return this.imageGenerator.componentRef.instance.activeGenerator;
4814
5386
  }
4815
- constructor(cdr) {
4816
- super(cdr);
4817
- this.cdr = cdr;
4818
- this.destroy$ = new Subject();
4819
- }
4820
5387
  initializeGenerator() {
4821
5388
  this.imageGenerator = new ImageGenerator(this.board, {
4822
5389
  getRectangle: (element) => {
@@ -4836,6 +5403,7 @@ class ImageComponent extends CommonPluginElement {
4836
5403
  }
4837
5404
  });
4838
5405
  this.lineAutoCompleteGenerator = new LineAutoCompleteGenerator(this.board);
5406
+ this.getRef().addGenerator(LineAutoCompleteGenerator.key, this.lineAutoCompleteGenerator);
4839
5407
  }
4840
5408
  ngOnInit() {
4841
5409
  super.ngOnInit();
@@ -4871,7 +5439,7 @@ class ImageComponent extends CommonPluginElement {
4871
5439
  this.imageGenerator.destroy();
4872
5440
  this.lineAutoCompleteGenerator.destroy();
4873
5441
  }
4874
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ImageComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
5442
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ImageComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
4875
5443
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: ImageComponent, isStandalone: true, selector: "plait-draw-geometry", usesInheritance: true, ngImport: i0, template: ``, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4876
5444
  }
4877
5445
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: ImageComponent, decorators: [{
@@ -4882,7 +5450,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImpor
4882
5450
  changeDetection: ChangeDetectionStrategy.OnPush,
4883
5451
  standalone: true
4884
5452
  }]
4885
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }] });
5453
+ }] });
4886
5454
 
4887
5455
  const withLineAutoCompleteReaction = (board) => {
4888
5456
  const { pointerMove } = board;
@@ -4897,10 +5465,11 @@ const withLineAutoCompleteReaction = (board) => {
4897
5465
  const points = getAutoCompletePoints(targetElement);
4898
5466
  const hitIndex = getHitIndexOfAutoCompletePoint(rotateAntiPointsByElement(movingPoint, targetElement) || movingPoint, points);
4899
5467
  const hitPoint = points[hitIndex];
4900
- const component = PlaitElement.getComponent(targetElement);
4901
- component.lineAutoCompleteGenerator.recoverAutoCompleteG();
5468
+ const ref = PlaitElement.getElementRef(targetElement);
5469
+ const lineAutoCompleteGenerator = ref.getGenerator(LineAutoCompleteGenerator.key);
5470
+ lineAutoCompleteGenerator.recoverAutoCompleteG();
4902
5471
  if (hitPoint) {
4903
- component.lineAutoCompleteGenerator.removeAutoCompleteG(hitIndex);
5472
+ lineAutoCompleteGenerator.removeAutoCompleteG(hitIndex);
4904
5473
  reactionG = drawCircle(PlaitBoard.getRoughSVG(board), hitPoint, LINE_AUTO_COMPLETE_HOVERED_DIAMETER, {
4905
5474
  stroke: 'none',
4906
5475
  fill: RgbaToHEX(PRIMARY_COLOR, LINE_AUTO_COMPLETE_HOVERED_OPACITY),
@@ -5001,8 +5570,8 @@ const withLineTextMove = (board) => {
5001
5570
  });
5002
5571
  if (line) {
5003
5572
  const index = getHitLineTextIndex(board, line, point);
5004
- const hitComponent = PlaitElement.getComponent(line);
5005
- const textManage = hitComponent.getTextManages()[index];
5573
+ const textManages = getTextManages(line);
5574
+ const textManage = textManages[index];
5006
5575
  if (index !== -1 && !textManage.isEditing) {
5007
5576
  textIndex = index;
5008
5577
  return { element: line, handle: ResizeHandle.e };
@@ -5075,12 +5644,13 @@ const withDrawRotate = (board) => {
5075
5644
  throttleRAF(board, 'with-common-rotate', () => {
5076
5645
  if (rotateRef && rotateRef.startPoint) {
5077
5646
  let angle = getAngleBetweenPoints(rotateRef.startPoint, endPoint, selectionCenterPoint);
5647
+ const selectionAngle = getSelectionAngle(rotateRef.elements);
5648
+ angle = normalizeAngle(selectionAngle + angle);
5078
5649
  if (isShift) {
5079
5650
  angle += Math.PI / 12 / 2;
5080
5651
  angle -= angle % (Math.PI / 12);
5081
5652
  }
5082
- const selectionAngle = getSelectionAngle(rotateRef.elements);
5083
- let remainder = (selectionAngle + angle) % (Math.PI / 2);
5653
+ let remainder = angle % (Math.PI / 2);
5084
5654
  if (Math.PI / 2 - remainder <= degreesToRadians(5)) {
5085
5655
  const snapAngle = Math.PI / 2 - remainder;
5086
5656
  angle += snapAngle;
@@ -5089,10 +5659,8 @@ const withDrawRotate = (board) => {
5089
5659
  const snapAngle = -remainder;
5090
5660
  angle += snapAngle;
5091
5661
  }
5092
- rotateRef.angle = normalizeAngle(angle);
5093
- if (rotateRef.angle) {
5094
- rotateElements(board, rotateRef.elements, rotateRef.angle);
5095
- }
5662
+ rotateRef.angle = normalizeAngle(angle - selectionAngle) || 0;
5663
+ rotateElements(board, rotateRef.elements, rotateRef.angle);
5096
5664
  PlaitBoard.getBoardContainer(board).classList.add('element-rotating');
5097
5665
  }
5098
5666
  });
@@ -5241,7 +5809,7 @@ const withDraw = (board) => {
5241
5809
  return isAlign(element);
5242
5810
  };
5243
5811
  board.getRelatedFragment = (elements, originData) => {
5244
- const selectedElements = originData || getSelectedElements(board);
5812
+ const selectedElements = originData?.length ? originData : getSelectedElements(board);
5245
5813
  const lineElements = board.children.filter(element => PlaitDrawElement.isLine(element));
5246
5814
  const activeLines = lineElements.filter(line => {
5247
5815
  const source = selectedElements.find(element => element.id === line.source.boundId);
@@ -5251,12 +5819,12 @@ const withDraw = (board) => {
5251
5819
  });
5252
5820
  return getRelatedFragment([...elements, ...activeLines], originData);
5253
5821
  };
5254
- return withDrawResize(withLineTextMove(withLineAutoCompleteReaction(withLineText(withLineBoundReaction(withLineResize(withGeometryResize(withDrawRotate(withLineCreateByDraw(withLineAutoComplete(withGeometryCreateByDrag(withGeometryCreateByDrawing(withDrawFragment(withDrawHotkey(board))))))))))))));
5822
+ return withDrawResize(withLineResize(withLineTextMove(withLineAutoCompleteReaction(withLineText(withLineBoundReaction(withGeometryResize(withDrawRotate(withLineCreateByDraw(withLineAutoComplete(withGeometryCreateByDrag(withGeometryCreateByDrawing(withDrawFragment(withDrawHotkey(board))))))))))))));
5255
5823
  };
5256
5824
 
5257
5825
  /**
5258
5826
  * Generated bundle index. Do not edit.
5259
5827
  */
5260
5828
 
5261
- export { BasicShapes, DEFAULT_IMAGE_WIDTH, DefaultBasicShapeProperty, DefaultCloudShapeProperty, DefaultConnectorProperty, DefaultDataProperty, DefaultDecisionProperty, DefaultFlowchartProperty, DefaultFlowchartPropertyMap, DefaultGeometryActiveStyle, DefaultGeometryStyle, DefaultManualInputProperty, DefaultMergeProperty, DefaultTextProperty, DrawThemeColors, DrawTransforms, FlowchartSymbols, GeometryComponent, GeometryThreshold, LINE_HIT_GEOMETRY_BUFFER, LINE_SNAPPING_BUFFER, LINE_SNAPPING_CONNECTOR_BUFFER, LineComponent, LineHandleKey, LineMarkerType, LineShape, MemorizeKey, PlaitDrawElement, PlaitGeometry, PlaitLine, Q2C, ShapeDefaultSpace, StrokeStyle, WithLineAutoCompletePluginKey, alignElbowSegment, alignPoints, createDefaultFlowchart, createDefaultGeometry, createGeometryElement, createLineElement, createTextElement, drawBoundReaction, drawGeometry, drawLine, drawLineArrow, getAutoCompletePoints, getBasicPointers, getCenterPointsOnPolygon, getConnectionPoint, getCurvePoints, getDefaultFlowchartProperty, getDefaultGeometryPoints, getDefaultGeometryProperty, getDefaultTextPoints, getDrawDefaultStrokeColor, getElbowLineRouteOptions, getElbowPoints, getFillByElement, getFlowchartDefaultFill, getFlowchartPointers, getGeometryPointers, getHitConnection, getHitConnectorPoint, getHitIndexOfAutoCompletePoint, getIndexAndDeleteCountByKeyPoint, getLineDashByElement, getLineHandleRefPair, getLineMemorizedLatest, getLinePointers, getLinePoints, getLineTextRectangle, getLines, getMemorizeKey, getMemorizedLatestByPointer, getMemorizedLatestShape, getMidKeyPoints, getMiddlePoints, getMirrorDataPoints, getNearestPoint, getNextRenderPoints, getNextSourceAndTargetPoints, getResizedPreviousAndNextPoint, getSelectedDrawElements, getSelectedGeometryElements, getSelectedImageElements, getSelectedLineElements, getSourceAndTargetRectangle, getStrokeColorByElement, getStrokeStyleByElement, getStrokeWidthByElement, getTextRectangle, getTextShapeProperty, getVectorByConnection, handleLineCreating, hasIllegalElbowPoint, insertElement, isHitDrawElement, isHitEdgeOfShape, isHitElementInside, isHitLine, isHitLineText, isHitPolyLine, isInsideOfShape, isRectangleHitDrawElement, isSelfLoop, isTextExceedingBounds, isUpdatedHandleIndex, isUseDefaultOrthogonalRoute, memorizeLatestShape, memorizeLatestText, withDraw, withLineAutoComplete };
5829
+ export { BasicShapes, DEFAULT_IMAGE_WIDTH, DefaultBasicShapeProperty, DefaultCloudShapeProperty, DefaultConnectorProperty, DefaultDataBaseProperty, DefaultDataProperty, DefaultDecisionProperty, DefaultDocumentProperty, DefaultFlowchartProperty, DefaultFlowchartPropertyMap, DefaultGeometryActiveStyle, DefaultGeometryStyle, DefaultInternalStorageProperty, DefaultManualInputProperty, DefaultMergeProperty, DefaultMultiDocumentProperty, DefaultNoteProperty, DefaultTextProperty, DrawThemeColors, DrawTransforms, FlowchartSymbols, GeometryComponent, GeometryThreshold, LINE_HIT_GEOMETRY_BUFFER, LINE_SNAPPING_BUFFER, LINE_SNAPPING_CONNECTOR_BUFFER, LineComponent, LineHandleKey, LineMarkerType, LineShape, MemorizeKey, PlaitDrawElement, PlaitGeometry, PlaitLine, Q2C, ShapeDefaultSpace, StrokeStyle, WithLineAutoCompletePluginKey, alignElbowSegment, alignPoints, createDefaultFlowchart, createDefaultGeometry, createGeometryElement, createLineElement, createTextElement, drawBoundReaction, drawGeometry, drawLine, drawLineArrow, editText, getAutoCompletePoints, getBasicPointers, getCenterPointsOnPolygon, getConnectionPoint, getCurvePoints, getDefaultFlowchartProperty, getDefaultGeometryPoints, getDefaultGeometryProperty, getDefaultTextPoints, getDrawDefaultStrokeColor, getElbowLineRouteOptions, getElbowPoints, getFillByElement, getFlowchartDefaultFill, getFlowchartPointers, getGeometryPointers, getHitConnection, getHitConnectorPoint, getHitIndexOfAutoCompletePoint, getIndexAndDeleteCountByKeyPoint, getLineDashByElement, getLineHandleRefPair, getLineMemorizedLatest, getLinePointers, getLinePoints, getLineTextRectangle, getLines, getMemorizeKey, getMemorizedLatestByPointer, getMemorizedLatestShape, getMidKeyPoints, getMiddlePoints, getMirrorDataPoints, getNearestPoint, getNextRenderPoints, getNextSourceAndTargetPoints, getResizedPreviousAndNextPoint, getSelectedDrawElements, getSelectedGeometryElements, getSelectedImageElements, getSelectedLineElements, getSourceAndTargetRectangle, getStrokeColorByElement, getStrokeStyleByElement, getStrokeWidthByElement, getTextRectangle, getTextShapeProperty, getVectorByConnection, handleLineCreating, hasIllegalElbowPoint, insertElement, isHitDrawElement, isHitEdgeOfShape, isHitElementInside, isHitLine, isHitLineText, isHitPolyLine, isInsideOfShape, isRectangleHitDrawElement, isSelfLoop, isTextExceedingBounds, isUpdatedHandleIndex, isUseDefaultOrthogonalRoute, memorizeLatestShape, memorizeLatestText, withDraw, withLineAutoComplete };
5262
5830
  //# sourceMappingURL=plait-draw.mjs.map