@plait/draw 0.48.0 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- import { ACTIVE_STROKE_WIDTH, ThemeColorMode, PlaitBoard, setStrokeLinecap, isPointInPolygon, getNearestPointBetweenPointAndSegments, RectangleClient, isPointInEllipse, drawRectangle, drawRoundRectangle, isPointInRoundRectangle, idCreator, createG, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, drawCircle, distanceBetweenPointAndSegment, Transforms, clearSelectedElement, addSelectedElement, BoardTransforms, PlaitPointerType, arrowPoints, createPath, distanceBetweenPointAndPoint, drawLinearPath, rotate, depthFirstRecursion, getIsRecursionFunc, getElementById, Direction, catmullRomFitting, distanceBetweenPointAndSegments, createMask, createRect, findElements, Point, getSelectedElements, isPolylineHitRectangle, Path, PlaitNode, BOARD_TO_HOST, transformPoint, toPoint, isSelectionMoving, RgbaToHEX, PlaitElement, preventTouchMove, setClipboardData, getDataFromClipboard, getHitElementByPoint, CursorClass, temporaryDisableSelection, PRESS_AND_MOVE_BUFFER } from '@plait/core';
2
- import { getRectangleByPoints, getMemorizedLatest, memorizeLatest, RESIZE_HANDLE_DIAMETER, getExtendPoint, getFactorByPoints, Generator, getRectangleResizeHandleRefs, getDirectionByVector, getOppositeDirection, getDirectionFactor, getPointByVector, reduceRouteMargin, getNextPoint, generateElbowLineRoute, getPoints, removeDuplicatePoints, getPointOnPolyline, getDirectionByPointOfRectangle, rotateVectorAnti90, TRANSPARENT, normalizeShapePoints, getFirstTextEditor, PRIMARY_COLOR, CommonPluginElement, ActiveGenerator, WithTextPluginKey, isVirtualKey, isDelete, isSpaceHotkey, isDndMode, isDrawingMode, acceptImageTypes, getElementOfFocusedImage, buildImage, ResizeHandle, getFirstTextManage, withResize, isResizingByCondition, getRatioByPoint, ImageGenerator } from '@plait/common';
3
- import { Alignment, buildText, DEFAULT_FONT_SIZE, getTextSize, AlignEditor, TextManage, getTextFromClipboard } from '@plait/text';
1
+ import { ACTIVE_STROKE_WIDTH, ThemeColorMode, PlaitBoard, setStrokeLinecap, isPointInPolygon, getNearestPointBetweenPointAndSegments, RectangleClient, isPointInEllipse, drawRectangle, drawRoundRectangle, isPointInRoundRectangle, idCreator, createG, SELECTION_BORDER_COLOR, SELECTION_FILL_COLOR, drawCircle, distanceBetweenPointAndSegment, Transforms, clearSelectedElement, addSelectedElement, BoardTransforms, PlaitPointerType, arrowPoints, createPath, distanceBetweenPointAndPoint, drawLinearPath, rotate, depthFirstRecursion, getIsRecursionFunc, getElementById, Direction, catmullRomFitting, distanceBetweenPointAndSegments, createMask, createRect, findElements, Point, getSelectedElements, isPolylineHitRectangle, Path, PlaitNode, toViewBoxPoint, toHostPoint, isSelectionMoving, RgbaToHEX, PlaitElement, preventTouchMove, createClipboardContext, WritableClipboardType, addClipboardContext, getHitElementByPoint, CursorClass, temporaryDisableSelection, PRESS_AND_MOVE_BUFFER } from '@plait/core';
2
+ import { getRectangleByPoints, getMemorizedLatest, memorizeLatest, RESIZE_HANDLE_DIAMETER, getExtendPoint, getFactorByPoints, Generator, getRectangleResizeHandleRefs, getDirectionByVector, getOppositeDirection, getDirectionFactor, getPointByVector, reduceRouteMargin, getNextPoint, generateElbowLineRoute, getPoints, removeDuplicatePoints, getPointOnPolyline, getDirectionByPointOfRectangle, rotateVectorAnti90, TRANSPARENT, normalizeShapePoints, getFirstTextEditor, PRIMARY_COLOR, CommonPluginElement, ActiveGenerator, WithTextPluginKey, isVirtualKey, isDelete, isSpaceHotkey, isDndMode, isDrawingMode, getElementsText, acceptImageTypes, getElementOfFocusedImage, buildImage, ResizeHandle, getFirstTextManage, withResize, isResizingByCondition, getRatioByPoint, ImageGenerator } from '@plait/common';
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';
6
6
  import { Component, ChangeDetectionStrategy, NgZone } from '@angular/core';
@@ -2244,12 +2244,29 @@ const removeLineText = (board, element, index) => {
2244
2244
  newTexts.splice(index, 1);
2245
2245
  Transforms.setNode(board, { texts: newTexts }, path);
2246
2246
  };
2247
- const setLineMark = (board, element, handleKey, marker) => {
2248
- const path = PlaitBoard.findPath(board, element);
2249
- let handle = handleKey === LineHandleKey.source ? element.source : element.target;
2250
- handle = { ...handle, marker };
2247
+ const setLineMark = (board, handleKey, marker) => {
2251
2248
  memorizeLatest(MemorizeKey.line, handleKey, marker);
2252
- Transforms.setNode(board, { [handleKey]: handle }, path);
2249
+ const selectedElements = getSelectedLineElements(board);
2250
+ selectedElements.forEach((element) => {
2251
+ const path = PlaitBoard.findPath(board, element);
2252
+ let handle = handleKey === LineHandleKey.source ? element.source : element.target;
2253
+ handle = { ...handle, marker };
2254
+ Transforms.setNode(board, { [handleKey]: handle }, path);
2255
+ });
2256
+ };
2257
+ const setLineShape = (board, newProperties) => {
2258
+ const elements = getSelectedLineElements(board);
2259
+ elements.map(element => {
2260
+ const _properties = { ...newProperties };
2261
+ if (element.shape === newProperties.shape) {
2262
+ return;
2263
+ }
2264
+ if (newProperties.shape === LineShape.elbow) {
2265
+ _properties.points = [element.points[0], element.points[element.points.length - 1]];
2266
+ }
2267
+ const path = PlaitBoard.findPath(board, element);
2268
+ Transforms.setNode(board, _properties, path);
2269
+ });
2253
2270
  };
2254
2271
  const collectLineUpdatedRefsByGeometry = (board, geometry, refs) => {
2255
2272
  const lines = findElements(board, {
@@ -2419,10 +2436,9 @@ const setTextSize = (board, element, textWidth, textHeight) => {
2419
2436
 
2420
2437
  const insertImage = (board, imageItem, startPoint) => {
2421
2438
  const { width, height, url } = imageItem;
2422
- const host = BOARD_TO_HOST.get(board);
2423
2439
  const viewportWidth = PlaitBoard.getComponent(board).nativeElement.clientWidth;
2424
2440
  const viewportHeight = PlaitBoard.getComponent(board).nativeElement.clientHeight;
2425
- const point = transformPoint(board, toPoint(viewportWidth / 2, viewportHeight / 2, host));
2441
+ const point = toViewBoxPoint(board, toHostPoint(board, viewportWidth / 2, viewportHeight / 2));
2426
2442
  const points = startPoint
2427
2443
  ? [startPoint, [startPoint[0] + width, startPoint[1] + height]]
2428
2444
  : [
@@ -2449,6 +2465,7 @@ const DrawTransforms = {
2449
2465
  setLineTexts,
2450
2466
  removeLineText,
2451
2467
  setLineMark,
2468
+ setLineShape,
2452
2469
  insertImage,
2453
2470
  switchGeometryShape,
2454
2471
  connectLineToGeometry,
@@ -2915,7 +2932,7 @@ const withGeometryCreateByDrag = (board) => {
2915
2932
  const geometryPointers = getGeometryPointers();
2916
2933
  const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
2917
2934
  const dragMode = isGeometryPointer && isDndMode(board);
2918
- const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
2935
+ const movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
2919
2936
  const pointer = PlaitBoard.getPointer(board);
2920
2937
  if (dragMode) {
2921
2938
  const memorizedLatest = getMemorizedLatestByPointer(pointer);
@@ -2990,7 +3007,7 @@ const withGeometryCreateByDrawing = (board) => {
2990
3007
  const geometryPointers = getGeometryPointers();
2991
3008
  const isGeometryPointer = PlaitBoard.isInPointer(board, geometryPointers);
2992
3009
  if (!PlaitBoard.isReadonly(board) && isGeometryPointer && isDrawingMode(board)) {
2993
- const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3010
+ const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
2994
3011
  start = point;
2995
3012
  const pointer = PlaitBoard.getPointer(board);
2996
3013
  preventTouchMove(board, event, true);
@@ -3010,7 +3027,7 @@ const withGeometryCreateByDrawing = (board) => {
3010
3027
  geometryShapeG = createG();
3011
3028
  const geometryGenerator = new GeometryShapeGenerator(board);
3012
3029
  const drawMode = !!start;
3013
- const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3030
+ const movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3014
3031
  const pointer = PlaitBoard.getPointer(board);
3015
3032
  if (drawMode && pointer !== BasicShapes.text) {
3016
3033
  const points = normalizeShapePoints([start, movingPoint], isShift);
@@ -3023,7 +3040,7 @@ const withGeometryCreateByDrawing = (board) => {
3023
3040
  board.pointerUp = (event) => {
3024
3041
  const isDrawMode = !!start;
3025
3042
  if (isDrawMode) {
3026
- const targetPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3043
+ const targetPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3027
3044
  const { width, height } = RectangleClient.toRectangleClient([start, targetPoint]);
3028
3045
  if (Math.hypot(width, height) === 0) {
3029
3046
  const pointer = PlaitBoard.getPointer(board);
@@ -3127,7 +3144,7 @@ const withDrawFragment = (baseBoard) => {
3127
3144
  }
3128
3145
  return getDeletedFragment(data);
3129
3146
  };
3130
- board.setFragment = (data, rectangle, type) => {
3147
+ board.setFragment = (data, clipboardContext, rectangle, type) => {
3131
3148
  const targetDrawElements = getSelectedDrawElements(board);
3132
3149
  let boundLineElements = [];
3133
3150
  if (targetDrawElements.length) {
@@ -3136,40 +3153,53 @@ const withDrawFragment = (baseBoard) => {
3136
3153
  const lineElements = targetDrawElements.filter(value => PlaitDrawElement.isLine(value));
3137
3154
  boundLineElements = getBoundedLineElements(board, geometryElements).filter(line => !lineElements.includes(line));
3138
3155
  }
3139
- const elements = buildClipboardData(board, [...targetDrawElements, ...boundLineElements], rectangle ? [rectangle.x, rectangle.y] : [0, 0]);
3140
- setClipboardData(data, elements);
3156
+ const selectedElements = [...targetDrawElements, ...boundLineElements];
3157
+ const elements = buildClipboardData(board, selectedElements, rectangle ? [rectangle.x, rectangle.y] : [0, 0]);
3158
+ const text = getElementsText(selectedElements);
3159
+ if (!clipboardContext) {
3160
+ clipboardContext = createClipboardContext(WritableClipboardType.elements, elements, text);
3161
+ }
3162
+ else {
3163
+ clipboardContext = addClipboardContext(clipboardContext, {
3164
+ text,
3165
+ type: WritableClipboardType.elements,
3166
+ data: elements
3167
+ });
3168
+ }
3141
3169
  }
3142
- setFragment(data, rectangle, type);
3170
+ setFragment(data, clipboardContext, rectangle, type);
3143
3171
  };
3144
- board.insertFragment = (data, targetPoint) => {
3145
- const elements = getDataFromClipboard(data);
3172
+ board.insertFragment = (data, clipboardData, targetPoint) => {
3146
3173
  const selectedElements = getSelectedElements(board);
3147
- const drawElements = elements.filter(value => PlaitDrawElement.isDrawElement(value));
3148
- if (elements.length > 0 && drawElements.length > 0) {
3149
- insertClipboardData(board, drawElements, targetPoint);
3150
- }
3151
- else if (elements.length === 0) {
3152
- const text = getTextFromClipboard(data);
3153
- // (* ̄︶ ̄)
3154
- const insertAsChildren = selectedElements.length === 1 && selectedElements[0].children;
3155
- const insertAsFreeText = !insertAsChildren;
3156
- if (text && insertAsFreeText) {
3157
- DrawTransforms.insertText(board, targetPoint, text);
3158
- return;
3159
- }
3160
- }
3161
- if (data?.files.length) {
3174
+ if (clipboardData?.files?.length) {
3162
3175
  const acceptImageArray = acceptImageTypes.map(type => 'image/' + type);
3163
3176
  const canInsertionImage = !getElementOfFocusedImage(board) && !(selectedElements.length === 1 && board.isImageBindingAllowed(selectedElements[0]));
3164
- if (acceptImageArray.includes(data?.files[0].type) && canInsertionImage) {
3165
- const imageFile = data.files[0];
3177
+ if (acceptImageArray.includes(clipboardData.files[0].type) && canInsertionImage) {
3178
+ const imageFile = clipboardData.files[0];
3166
3179
  buildImage(board, imageFile, DEFAULT_IMAGE_WIDTH, imageItem => {
3167
3180
  DrawTransforms.insertImage(board, imageItem, targetPoint);
3168
3181
  });
3169
3182
  return;
3170
3183
  }
3171
3184
  }
3172
- insertFragment(data, targetPoint);
3185
+ if (clipboardData?.elements?.length) {
3186
+ const drawElements = clipboardData.elements?.filter(value => PlaitDrawElement.isDrawElement(value));
3187
+ if (clipboardData.elements && clipboardData.elements.length > 0 && drawElements.length > 0) {
3188
+ insertClipboardData(board, drawElements, targetPoint);
3189
+ }
3190
+ }
3191
+ if (clipboardData?.text) {
3192
+ if (!clipboardData.elements || clipboardData.elements.length === 0) {
3193
+ // (* ̄︶ ̄)
3194
+ const insertAsChildren = selectedElements.length === 1 && selectedElements[0].children;
3195
+ const insertAsFreeText = !insertAsChildren;
3196
+ if (insertAsFreeText) {
3197
+ DrawTransforms.insertText(board, targetPoint, clipboardData.text);
3198
+ return;
3199
+ }
3200
+ }
3201
+ }
3202
+ insertFragment(data, clipboardData, targetPoint);
3173
3203
  };
3174
3204
  return board;
3175
3205
  };
@@ -3188,7 +3218,7 @@ const withLineCreateByDraw = (board) => {
3188
3218
  const linePointers = getLinePointers();
3189
3219
  const isLinePointer = PlaitBoard.isInPointer(board, linePointers);
3190
3220
  if (!PlaitBoard.isReadonly(board) && isLinePointer && isDrawingMode(board)) {
3191
- const point = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3221
+ const point = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3192
3222
  start = point;
3193
3223
  const hitElement = getHitOutlineGeometry(board, point, REACTION_MARGIN);
3194
3224
  if (hitElement) {
@@ -3201,7 +3231,7 @@ const withLineCreateByDraw = (board) => {
3201
3231
  board.pointerMove = (event) => {
3202
3232
  lineShapeG?.remove();
3203
3233
  lineShapeG = createG();
3204
- let movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3234
+ let movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3205
3235
  if (start) {
3206
3236
  const lineShape = PlaitBoard.getPointer(board);
3207
3237
  temporaryElement = handleLineCreating(board, lineShape, start, movingPoint, sourceElement, lineShapeG);
@@ -3449,7 +3479,7 @@ const withLineBoundReaction = (board) => {
3449
3479
  }
3450
3480
  const linePointers = Object.keys(LineShape);
3451
3481
  const isLinePointer = PlaitBoard.isInPointer(board, linePointers);
3452
- const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3482
+ const movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3453
3483
  const isLineResizing = isResizingByCondition(board, resizeRef => {
3454
3484
  const { element, handle } = resizeRef;
3455
3485
  const isSourceOrTarget = handle === LineResizeHandle.target || handle === LineResizeHandle.source;
@@ -3488,7 +3518,7 @@ const withLineText = (board) => {
3488
3518
  const { dblclick } = board;
3489
3519
  board.dblclick = (event) => {
3490
3520
  if (!PlaitBoard.isReadonly(board)) {
3491
- const clickPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3521
+ const clickPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3492
3522
  const hitTarget = getHitElementByPoint(board, clickPoint, (element) => {
3493
3523
  return PlaitDrawElement.isLine(element);
3494
3524
  });
@@ -3619,7 +3649,7 @@ const withLineAutoCompleteReaction = (board) => {
3619
3649
  PlaitBoard.getBoardContainer(board).classList.remove(CursorClass.crosshair);
3620
3650
  const selectedElements = getSelectedDrawElements(board);
3621
3651
  const targetElement = selectedElements.length === 1 && selectedElements[0];
3622
- const movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3652
+ const movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3623
3653
  if (!PlaitBoard.isReadonly(board) && !isSelectionMoving(board) && targetElement && PlaitDrawElement.isShape(targetElement)) {
3624
3654
  const points = getAutoCompletePoints(targetElement);
3625
3655
  const hitIndex = getHitIndexOfAutoCompletePoint(movingPoint, points);
@@ -3652,7 +3682,7 @@ const withLineAutoComplete = (board) => {
3652
3682
  board.pointerDown = (event) => {
3653
3683
  const selectedElements = getSelectedDrawElements(board);
3654
3684
  const targetElement = selectedElements.length === 1 && selectedElements[0];
3655
- const clickPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3685
+ const clickPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3656
3686
  if (!PlaitBoard.isReadonly(board) && targetElement && PlaitDrawElement.isShape(targetElement)) {
3657
3687
  const points = getAutoCompletePoints(targetElement);
3658
3688
  const index = getHitIndexOfAutoCompletePoint(clickPoint, points);
@@ -3669,7 +3699,7 @@ const withLineAutoComplete = (board) => {
3669
3699
  board.pointerMove = (event) => {
3670
3700
  lineShapeG?.remove();
3671
3701
  lineShapeG = createG();
3672
- let movingPoint = transformPoint(board, toPoint(event.x, event.y, PlaitBoard.getHost(board)));
3702
+ let movingPoint = toViewBoxPoint(board, toHostPoint(board, event.x, event.y));
3673
3703
  if (startPoint && sourceElement) {
3674
3704
  const distance = distanceBetweenPointAndPoint(...movingPoint, ...startPoint);
3675
3705
  if (distance > PRESS_AND_MOVE_BUFFER) {