tldraw 4.1.0-canary.c62140a07605 → 4.1.0-canary.c9992319dc92

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 (118) hide show
  1. package/dist-cjs/index.d.ts +35 -10
  2. package/dist-cjs/index.js +3 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/defaultEmbedDefinitions.js +25 -30
  5. package/dist-cjs/lib/defaultEmbedDefinitions.js.map +2 -2
  6. package/dist-cjs/lib/defaultExternalContentHandlers.js +9 -32
  7. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  8. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +3 -0
  9. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  10. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +43 -101
  11. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/shapes/bookmark/bookmarks.js +138 -0
  13. package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +7 -0
  14. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +25 -3
  15. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
  16. package/dist-cjs/lib/shapes/line/LineShapeUtil.js +3 -0
  17. package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
  18. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js +20 -4
  19. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js.map +2 -2
  20. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js +23 -11
  21. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js.map +2 -2
  22. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +27 -6
  23. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  24. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js +21 -9
  25. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
  26. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js +24 -8
  27. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js.map +2 -2
  28. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js +21 -9
  29. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js.map +2 -2
  30. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +23 -8
  31. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  32. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js +21 -9
  33. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js.map +2 -2
  34. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +26 -11
  35. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  36. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +5 -0
  37. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
  38. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js +6 -2
  39. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js.map +2 -2
  40. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js +1 -1
  41. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +1 -1
  42. package/dist-cjs/lib/ui/context/actions.js +23 -29
  43. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  44. package/dist-cjs/lib/ui/version.js +3 -3
  45. package/dist-cjs/lib/ui/version.js.map +1 -1
  46. package/dist-esm/index.d.mts +35 -10
  47. package/dist-esm/index.mjs +3 -1
  48. package/dist-esm/index.mjs.map +2 -2
  49. package/dist-esm/lib/defaultEmbedDefinitions.mjs +25 -30
  50. package/dist-esm/lib/defaultEmbedDefinitions.mjs.map +2 -2
  51. package/dist-esm/lib/defaultExternalContentHandlers.mjs +9 -32
  52. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  53. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +3 -0
  54. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  55. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +46 -101
  56. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  57. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs +124 -0
  58. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +7 -0
  59. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +26 -3
  60. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
  61. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +3 -0
  62. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
  63. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs +20 -4
  64. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs.map +2 -2
  65. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs +23 -11
  66. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs.map +2 -2
  67. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +29 -7
  68. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  69. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs +21 -9
  70. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
  71. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs +24 -8
  72. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs.map +2 -2
  73. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs +21 -9
  74. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs.map +2 -2
  75. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +23 -8
  76. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  77. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs +21 -9
  78. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs.map +2 -2
  79. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +26 -11
  80. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  81. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +5 -0
  82. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
  83. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs +6 -2
  84. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs.map +2 -2
  85. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +1 -1
  86. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +1 -1
  87. package/dist-esm/lib/ui/context/actions.mjs +23 -29
  88. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  89. package/dist-esm/lib/ui/version.mjs +3 -3
  90. package/dist-esm/lib/ui/version.mjs.map +1 -1
  91. package/package.json +3 -3
  92. package/src/index.ts +1 -0
  93. package/src/lib/defaultEmbedDefinitions.ts +20 -24
  94. package/src/lib/defaultExternalContentHandlers.ts +11 -36
  95. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +3 -0
  96. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +51 -135
  97. package/src/lib/shapes/bookmark/bookmarks.ts +170 -0
  98. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +28 -2
  99. package/src/lib/shapes/line/LineShapeUtil.tsx +3 -0
  100. package/src/lib/tools/SelectTool/childStates/Crop/children/Cropping.ts +23 -6
  101. package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.ts +24 -12
  102. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +34 -11
  103. package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +23 -11
  104. package/src/lib/tools/SelectTool/childStates/PointingResizeHandle.ts +26 -9
  105. package/src/lib/tools/SelectTool/childStates/PointingRotateHandle.ts +23 -10
  106. package/src/lib/tools/SelectTool/childStates/Resizing.ts +24 -9
  107. package/src/lib/tools/SelectTool/childStates/Rotating.ts +27 -11
  108. package/src/lib/tools/SelectTool/childStates/Translating.ts +28 -12
  109. package/src/lib/ui/components/Minimap/MinimapManager.ts +6 -0
  110. package/src/lib/ui/components/SharePanel/PeopleMenu.tsx +6 -2
  111. package/src/lib/ui/components/StylePanel/StylePanelButtonPicker.tsx +1 -1
  112. package/src/lib/ui/context/actions.tsx +27 -31
  113. package/src/lib/ui/version.ts +3 -3
  114. package/src/lib/utils/embeds/embeds.test.ts +16 -34
  115. package/src/test/SelectTool.test.ts +251 -0
  116. package/src/test/bookmark-shapes.test.ts +129 -7
  117. package/src/test/customSnapping.test.tsx +55 -11
  118. package/tldraw.css +7 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/tools/SelectTool/childStates/DraggingHandle.tsx"],
4
- "sourcesContent": ["import {\n\tMat,\n\tStateNode,\n\tTLArrowShape,\n\tTLHandle,\n\tTLLineShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\tTLShapePartial,\n\tVec,\n\tkickoutOccludedShapes,\n\tsnapAngle,\n\tsortByIndex,\n\tstructuredClone,\n} from '@tldraw/editor'\nimport { ArrowShapeUtil } from '../../../shapes/arrow/ArrowShapeUtil'\nimport { clearArrowTargetState } from '../../../shapes/arrow/arrowTargetState'\nimport { getArrowBindings } from '../../../shapes/arrow/shared'\n\nexport type DraggingHandleInfo = TLPointerEventInfo & {\n\tshape: TLArrowShape | TLLineShape\n\ttarget: 'handle'\n\tonInteractionEnd?: string\n\tisCreating?: boolean\n\tcreatingMarkId?: string\n}\n\nexport class DraggingHandle extends StateNode {\n\tstatic override id = 'dragging_handle'\n\n\tshapeId!: TLShapeId\n\tinitialHandle!: TLHandle\n\tinitialAdjacentHandle!: TLHandle | null\n\tinitialPagePoint!: Vec\n\n\tmarkId!: string\n\tinitialPageTransform!: Mat\n\tinitialPageRotation!: number\n\n\tinfo!: DraggingHandleInfo\n\n\tisPrecise = false\n\tisPreciseId: TLShapeId | null = null\n\tpointingId: TLShapeId | null = null\n\n\toverride onEnter(info: DraggingHandleInfo) {\n\t\tconst { shape, isCreating, creatingMarkId, handle } = info\n\t\tthis.info = info\n\t\tthis.parent.setCurrentToolIdMask(info.onInteractionEnd)\n\t\tthis.shapeId = shape.id\n\t\tthis.markId = ''\n\n\t\tif (isCreating) {\n\t\t\tif (creatingMarkId) {\n\t\t\t\tthis.markId = creatingMarkId\n\t\t\t} else {\n\t\t\t\t// handle legacy implicit `creating:{shapeId}` marks\n\t\t\t\tconst markId = this.editor.getMarkIdMatching(\n\t\t\t\t\t`creating:${this.editor.getOnlySelectedShapeId()}`\n\t\t\t\t)\n\t\t\t\tif (markId) {\n\t\t\t\t\tthis.markId = markId\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.markId = this.editor.markHistoryStoppingPoint('dragging handle')\n\t\t}\n\n\t\tthis.initialHandle = structuredClone(handle)\n\n\t\tthis.initialPageTransform = this.editor.getShapePageTransform(shape)!\n\t\tthis.initialPageRotation = this.initialPageTransform.rotation()\n\t\tthis.initialPagePoint = this.editor.inputs.originPagePoint.clone()\n\n\t\tthis.editor.setCursor({ type: isCreating ? 'cross' : 'grabbing', rotation: 0 })\n\n\t\tconst handles = this.editor.getShapeHandles(shape)!.sort(sortByIndex)\n\t\tconst index = handles.findIndex((h) => h.id === info.handle.id)\n\n\t\t// Find the adjacent handle\n\t\tthis.initialAdjacentHandle = null\n\n\t\t// Start from the handle and work forward\n\t\tfor (let i = index + 1; i < handles.length; i++) {\n\t\t\tconst handle = handles[i]\n\t\t\tif (handle.type === 'vertex' && handle.id !== 'middle' && handle.id !== info.handle.id) {\n\t\t\t\tthis.initialAdjacentHandle = handle\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// If still no handle, start from the end and work backward\n\t\tif (!this.initialAdjacentHandle) {\n\t\t\tfor (let i = handles.length - 1; i >= 0; i--) {\n\t\t\t\tconst handle = handles[i]\n\t\t\t\tif (handle.type === 'vertex' && handle.id !== 'middle' && handle.id !== info.handle.id) {\n\t\t\t\t\tthis.initialAdjacentHandle = handle\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// <!-- Only relevant to arrows\n\t\tif (this.editor.isShapeOfType<TLArrowShape>(shape, 'arrow')) {\n\t\t\tconst initialBinding = getArrowBindings(this.editor, shape)[info.handle.id as 'start' | 'end']\n\n\t\t\tthis.isPrecise = false\n\n\t\t\tif (initialBinding) {\n\t\t\t\tthis.isPrecise = initialBinding.props.isPrecise\n\t\t\t\tif (this.isPrecise) {\n\t\t\t\t\tthis.isPreciseId = initialBinding.toId\n\t\t\t\t} else {\n\t\t\t\t\tthis.resetExactTimeout()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// -->\n\n\t\t// Call onHandleDragStart callback\n\t\tconst handleDragInfo = {\n\t\t\thandle: this.initialHandle,\n\t\t\tisPrecise: this.isPrecise,\n\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\tinitial: shape,\n\t\t}\n\t\tconst util = this.editor.getShapeUtil(shape)\n\t\tconst startChanges = util.onHandleDragStart?.(shape, handleDragInfo)\n\t\tif (startChanges) {\n\t\t\tthis.editor.updateShapes([{ ...startChanges, id: shape.id, type: shape.type }])\n\t\t}\n\n\t\tthis.update()\n\n\t\tthis.editor.select(this.shapeId)\n\t}\n\n\t// Only relevant to arrows\n\tprivate exactTimeout = -1\n\n\t// Only relevant to arrows\n\tprivate resetExactTimeout() {\n\t\tconst arrowUtil = this.editor.getShapeUtil<ArrowShapeUtil>('arrow')\n\t\tconst timeoutValue = arrowUtil.options.pointingPreciseTimeout\n\n\t\tif (this.exactTimeout !== -1) {\n\t\t\tthis.clearExactTimeout()\n\t\t}\n\n\t\tthis.exactTimeout = this.editor.timers.setTimeout(() => {\n\t\t\tif (this.getIsActive() && !this.isPrecise) {\n\t\t\t\tthis.isPrecise = true\n\t\t\t\tthis.isPreciseId = this.pointingId\n\t\t\t\tthis.update()\n\t\t\t}\n\t\t\tthis.exactTimeout = -1\n\t\t}, timeoutValue)\n\t}\n\n\t// Only relevant to arrows\n\tprivate clearExactTimeout() {\n\t\tif (this.exactTimeout !== -1) {\n\t\t\tclearTimeout(this.exactTimeout)\n\t\t\tthis.exactTimeout = -1\n\t\t}\n\t}\n\n\toverride onPointerMove() {\n\t\tthis.update()\n\t}\n\n\toverride onKeyDown() {\n\t\tthis.update()\n\t}\n\n\toverride onKeyUp() {\n\t\tthis.update()\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onComplete() {\n\t\tthis.update()\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onExit() {\n\t\tthis.parent.setCurrentToolIdMask(undefined)\n\t\tclearArrowTargetState(this.editor)\n\t\tthis.editor.snaps.clearIndicators()\n\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t}\n\n\tprivate complete() {\n\t\tthis.editor.snaps.clearIndicators()\n\t\tkickoutOccludedShapes(this.editor, [this.shapeId])\n\n\t\t// Call onHandleDragEnd callback before state transitions\n\t\tconst shape = this.editor.getShape(this.shapeId)\n\t\tif (shape) {\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst handleDragInfo = {\n\t\t\t\thandle: this.initialHandle,\n\t\t\t\tisPrecise: this.isPrecise,\n\t\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\t\tinitial: this.info.shape,\n\t\t\t}\n\t\t\tconst endChanges = util.onHandleDragEnd?.(shape, handleDragInfo)\n\t\t\tif (endChanges) {\n\t\t\t\tthis.editor.updateShapes([{ ...endChanges, id: shape.id, type: shape.type }])\n\t\t\t}\n\t\t}\n\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (this.editor.getInstanceState().isToolLocked && onInteractionEnd) {\n\t\t\t// Return to the tool that was active before this one,\n\t\t\t// but only if tool lock is turned on!\n\t\t\tthis.editor.setCurrentTool(onInteractionEnd, { shapeId: this.shapeId })\n\t\t\treturn\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tprivate cancel() {\n\t\t// Call onHandleDragCancel callback before bailing to mark\n\t\tconst shape = this.editor.getShape(this.shapeId)\n\t\tif (shape) {\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst handleDragInfo = {\n\t\t\t\thandle: this.initialHandle,\n\t\t\t\tisPrecise: this.isPrecise,\n\t\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\t\tinitial: this.info.shape,\n\t\t\t}\n\t\t\tutil.onHandleDragCancel?.(shape, handleDragInfo)\n\t\t}\n\n\t\tthis.editor.bailToMark(this.markId)\n\t\tthis.editor.snaps.clearIndicators()\n\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\t// Return to the tool that was active before this one,\n\t\t\t// whether tool lock is turned on or not!\n\t\t\tthis.editor.setCurrentTool(onInteractionEnd, { shapeId: this.shapeId })\n\t\t\treturn\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tprivate update() {\n\t\tconst { editor, shapeId, initialPagePoint } = this\n\t\tconst { initialHandle, initialPageRotation, initialAdjacentHandle } = this\n\t\tconst isSnapMode = this.editor.user.getIsSnapMode()\n\t\tconst {\n\t\t\tsnaps,\n\t\t\tinputs: { currentPagePoint, shiftKey, ctrlKey, altKey, pointerVelocity },\n\t\t} = editor\n\n\t\tconst initial = this.info.shape\n\n\t\tconst shape = editor.getShape(shapeId)\n\t\tif (!shape) return\n\t\tconst util = editor.getShapeUtil(shape)\n\n\t\tconst initialBinding = editor.isShapeOfType<TLArrowShape>(shape, 'arrow')\n\t\t\t? getArrowBindings(editor, shape)[initialHandle.id as 'start' | 'end']\n\t\t\t: undefined\n\n\t\tlet point = currentPagePoint\n\t\t\t.clone()\n\t\t\t.sub(initialPagePoint)\n\t\t\t.rot(-initialPageRotation)\n\t\t\t.add(initialHandle)\n\n\t\tif (shiftKey && initialAdjacentHandle && initialHandle.id !== 'middle') {\n\t\t\tconst angle = Vec.Angle(initialAdjacentHandle, point)\n\t\t\tconst snappedAngle = snapAngle(angle, 24)\n\t\t\tconst angleDifference = snappedAngle - angle\n\t\t\tpoint = Vec.RotWith(point, initialAdjacentHandle, angleDifference)\n\t\t}\n\n\t\t// Clear any existing snaps\n\t\teditor.snaps.clearIndicators()\n\n\t\tlet nextHandle = { ...initialHandle, x: point.x, y: point.y }\n\n\t\tif (initialHandle.canSnap && (isSnapMode ? !ctrlKey : ctrlKey)) {\n\t\t\t// We're snapping\n\t\t\tconst pageTransform = editor.getShapePageTransform(shape.id)\n\t\t\tif (!pageTransform) throw Error('Expected a page transform')\n\n\t\t\tconst snap = snaps.handles.snapHandle({ currentShapeId: shapeId, handle: nextHandle })\n\n\t\t\tif (snap) {\n\t\t\t\tsnap.nudge.rot(-editor.getShapeParentTransform(shape)!.rotation())\n\t\t\t\tpoint.add(snap.nudge)\n\t\t\t\tnextHandle = { ...initialHandle, x: point.x, y: point.y }\n\t\t\t}\n\t\t}\n\n\t\tconst changes = util.onHandleDrag?.(shape, {\n\t\t\thandle: nextHandle,\n\t\t\tisPrecise: this.isPrecise || altKey,\n\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\tinitial: initial,\n\t\t})\n\n\t\tconst next: TLShapePartial<any> = { id: shape.id, type: shape.type, ...changes }\n\n\t\t// Arrows\n\t\tif (\n\t\t\tinitialHandle.type === 'vertex' &&\n\t\t\tthis.editor.isShapeOfType<TLArrowShape>(shape, 'arrow')\n\t\t) {\n\t\t\tconst bindingAfter = getArrowBindings(editor, shape)[initialHandle.id as 'start' | 'end']\n\n\t\t\tif (bindingAfter) {\n\t\t\t\tif (initialBinding?.toId !== bindingAfter.toId) {\n\t\t\t\t\tthis.pointingId = bindingAfter.toId\n\t\t\t\t\tthis.isPrecise = pointerVelocity.len() < 0.5 || altKey\n\t\t\t\t\tthis.isPreciseId = this.isPrecise ? bindingAfter.toId : null\n\t\t\t\t\tthis.resetExactTimeout()\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (initialBinding) {\n\t\t\t\t\tthis.pointingId = null\n\t\t\t\t\tthis.isPrecise = false\n\t\t\t\t\tthis.isPreciseId = null\n\t\t\t\t\tthis.resetExactTimeout()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (changes) {\n\t\t\teditor.updateShapes([next])\n\t\t}\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tMat,\n\tStateNode,\n\tTLArrowShape,\n\tTLHandle,\n\tTLLineShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\tTLShapePartial,\n\tVec,\n\tkickoutOccludedShapes,\n\tsnapAngle,\n\tsortByIndex,\n\tstructuredClone,\n\twarnOnce,\n} from '@tldraw/editor'\nimport { ArrowShapeUtil } from '../../../shapes/arrow/ArrowShapeUtil'\nimport { clearArrowTargetState } from '../../../shapes/arrow/arrowTargetState'\nimport { getArrowBindings } from '../../../shapes/arrow/shared'\n\nexport type DraggingHandleInfo = TLPointerEventInfo & {\n\tshape: TLArrowShape | TLLineShape\n\ttarget: 'handle'\n\tonInteractionEnd?: string | (() => void)\n\tisCreating?: boolean\n\tcreatingMarkId?: string\n}\n\nexport class DraggingHandle extends StateNode {\n\tstatic override id = 'dragging_handle'\n\n\tshapeId!: TLShapeId\n\tinitialHandle!: TLHandle\n\tinitialAdjacentHandle!: TLHandle | null\n\tinitialPagePoint!: Vec\n\n\tmarkId!: string\n\tinitialPageTransform!: Mat\n\tinitialPageRotation!: number\n\n\tinfo!: DraggingHandleInfo\n\n\tisPrecise = false\n\tisPreciseId: TLShapeId | null = null\n\tpointingId: TLShapeId | null = null\n\n\toverride onEnter(info: DraggingHandleInfo) {\n\t\tconst { shape, isCreating, creatingMarkId, handle } = info\n\t\tthis.info = info\n\t\tif (typeof info.onInteractionEnd === 'string') {\n\t\t\tthis.parent.setCurrentToolIdMask(info.onInteractionEnd)\n\t\t}\n\t\tthis.shapeId = shape.id\n\t\tthis.markId = ''\n\n\t\tif (isCreating) {\n\t\t\tif (creatingMarkId) {\n\t\t\t\tthis.markId = creatingMarkId\n\t\t\t} else {\n\t\t\t\t// handle legacy implicit `creating:{shapeId}` marks\n\t\t\t\tconst markId = this.editor.getMarkIdMatching(\n\t\t\t\t\t`creating:${this.editor.getOnlySelectedShapeId()}`\n\t\t\t\t)\n\t\t\t\tif (markId) {\n\t\t\t\t\tthis.markId = markId\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.markId = this.editor.markHistoryStoppingPoint('dragging handle')\n\t\t}\n\n\t\tthis.initialHandle = structuredClone(handle)\n\n\t\tthis.initialPageTransform = this.editor.getShapePageTransform(shape)!\n\t\tthis.initialPageRotation = this.initialPageTransform.rotation()\n\t\tthis.initialPagePoint = this.editor.inputs.originPagePoint.clone()\n\n\t\tthis.editor.setCursor({ type: isCreating ? 'cross' : 'grabbing', rotation: 0 })\n\n\t\tconst handles = this.editor.getShapeHandles(shape)!.sort(sortByIndex)\n\t\tconst index = handles.findIndex((h) => h.id === info.handle.id)\n\n\t\t// Find the adjacent handle\n\t\tthis.initialAdjacentHandle = null\n\n\t\t// Start from the handle and work forward\n\t\tfor (let i = index + 1; i < handles.length; i++) {\n\t\t\tconst handle = handles[i]\n\t\t\tif (handle.type === 'vertex' && handle.id !== 'middle' && handle.id !== info.handle.id) {\n\t\t\t\tthis.initialAdjacentHandle = handle\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// If still no handle, start from the end and work backward\n\t\tif (!this.initialAdjacentHandle) {\n\t\t\tfor (let i = handles.length - 1; i >= 0; i--) {\n\t\t\t\tconst handle = handles[i]\n\t\t\t\tif (handle.type === 'vertex' && handle.id !== 'middle' && handle.id !== info.handle.id) {\n\t\t\t\t\tthis.initialAdjacentHandle = handle\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// <!-- Only relevant to arrows\n\t\tif (this.editor.isShapeOfType<TLArrowShape>(shape, 'arrow')) {\n\t\t\tconst initialBinding = getArrowBindings(this.editor, shape)[info.handle.id as 'start' | 'end']\n\n\t\t\tthis.isPrecise = false\n\n\t\t\tif (initialBinding) {\n\t\t\t\tthis.isPrecise = initialBinding.props.isPrecise\n\t\t\t\tif (this.isPrecise) {\n\t\t\t\t\tthis.isPreciseId = initialBinding.toId\n\t\t\t\t} else {\n\t\t\t\t\tthis.resetExactTimeout()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// -->\n\n\t\t// Call onHandleDragStart callback\n\t\tconst handleDragInfo = {\n\t\t\thandle: this.initialHandle,\n\t\t\tisPrecise: this.isPrecise,\n\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\tinitial: shape,\n\t\t}\n\t\tconst util = this.editor.getShapeUtil(shape)\n\t\tconst startChanges = util.onHandleDragStart?.(shape, handleDragInfo)\n\t\tif (startChanges) {\n\t\t\tthis.editor.updateShapes([{ ...startChanges, id: shape.id, type: shape.type }])\n\t\t}\n\n\t\tthis.update()\n\n\t\tthis.editor.select(this.shapeId)\n\t}\n\n\t// Only relevant to arrows\n\tprivate exactTimeout = -1\n\n\t// Only relevant to arrows\n\tprivate resetExactTimeout() {\n\t\tconst arrowUtil = this.editor.getShapeUtil<ArrowShapeUtil>('arrow')\n\t\tconst timeoutValue = arrowUtil.options.pointingPreciseTimeout\n\n\t\tif (this.exactTimeout !== -1) {\n\t\t\tthis.clearExactTimeout()\n\t\t}\n\n\t\tthis.exactTimeout = this.editor.timers.setTimeout(() => {\n\t\t\tif (this.getIsActive() && !this.isPrecise) {\n\t\t\t\tthis.isPrecise = true\n\t\t\t\tthis.isPreciseId = this.pointingId\n\t\t\t\tthis.update()\n\t\t\t}\n\t\t\tthis.exactTimeout = -1\n\t\t}, timeoutValue)\n\t}\n\n\t// Only relevant to arrows\n\tprivate clearExactTimeout() {\n\t\tif (this.exactTimeout !== -1) {\n\t\t\tclearTimeout(this.exactTimeout)\n\t\t\tthis.exactTimeout = -1\n\t\t}\n\t}\n\n\toverride onPointerMove() {\n\t\tthis.update()\n\t}\n\n\toverride onKeyDown() {\n\t\tthis.update()\n\t}\n\n\toverride onKeyUp() {\n\t\tthis.update()\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onComplete() {\n\t\tthis.update()\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onExit() {\n\t\tthis.parent.setCurrentToolIdMask(undefined)\n\t\tclearArrowTargetState(this.editor)\n\t\tthis.editor.snaps.clearIndicators()\n\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t}\n\n\tprivate complete() {\n\t\tthis.editor.snaps.clearIndicators()\n\t\tkickoutOccludedShapes(this.editor, [this.shapeId])\n\n\t\t// Call onHandleDragEnd callback before state transitions\n\t\tconst shape = this.editor.getShape(this.shapeId)\n\t\tif (shape) {\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst handleDragInfo = {\n\t\t\t\thandle: this.initialHandle,\n\t\t\t\tisPrecise: this.isPrecise,\n\t\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\t\tinitial: this.info.shape,\n\t\t\t}\n\t\t\tconst endChanges = util.onHandleDragEnd?.(shape, handleDragInfo)\n\t\t\tif (endChanges) {\n\t\t\t\tthis.editor.updateShapes([{ ...endChanges, id: shape.id, type: shape.type }])\n\t\t\t}\n\t\t}\n\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\tif (this.editor.getInstanceState().isToolLocked && onInteractionEnd) {\n\t\t\t\t\t// Return to the tool that was active before this one but only if tool lock is turned on!\n\t\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd, { shapeId: this.shapeId })\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tonInteractionEnd?.()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tprivate cancel() {\n\t\t// Call onHandleDragCancel callback before bailing to mark\n\t\tconst shape = this.editor.getShape(this.shapeId)\n\t\tif (shape) {\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst handleDragInfo = {\n\t\t\t\thandle: this.initialHandle,\n\t\t\t\tisPrecise: this.isPrecise,\n\t\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\t\tinitial: this.info.shape,\n\t\t\t}\n\t\t\tutil.onHandleDragCancel?.(shape, handleDragInfo)\n\t\t}\n\n\t\tthis.editor.bailToMark(this.markId)\n\t\tthis.editor.snaps.clearIndicators()\n\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\t// Return to the tool that was active before this one, whether tool lock is turned on or not!\n\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd, { shapeId: this.shapeId })\n\t\t\t} else {\n\t\t\t\tonInteractionEnd?.()\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tprivate update() {\n\t\tconst { editor, shapeId, initialPagePoint } = this\n\t\tconst { initialHandle, initialPageRotation, initialAdjacentHandle } = this\n\t\tconst isSnapMode = this.editor.user.getIsSnapMode()\n\t\tconst {\n\t\t\tsnaps,\n\t\t\tinputs: { currentPagePoint, shiftKey, ctrlKey, altKey, pointerVelocity },\n\t\t} = editor\n\n\t\tconst initial = this.info.shape\n\n\t\tconst shape = editor.getShape(shapeId)\n\t\tif (!shape) return\n\t\tconst util = editor.getShapeUtil(shape)\n\n\t\tconst initialBinding = editor.isShapeOfType<TLArrowShape>(shape, 'arrow')\n\t\t\t? getArrowBindings(editor, shape)[initialHandle.id as 'start' | 'end']\n\t\t\t: undefined\n\n\t\tlet point = currentPagePoint\n\t\t\t.clone()\n\t\t\t.sub(initialPagePoint)\n\t\t\t.rot(-initialPageRotation)\n\t\t\t.add(initialHandle)\n\n\t\tif (shiftKey && initialAdjacentHandle && initialHandle.id !== 'middle') {\n\t\t\tconst angle = Vec.Angle(initialAdjacentHandle, point)\n\t\t\tconst snappedAngle = snapAngle(angle, 24)\n\t\t\tconst angleDifference = snappedAngle - angle\n\t\t\tpoint = Vec.RotWith(point, initialAdjacentHandle, angleDifference)\n\t\t}\n\n\t\t// Clear any existing snaps\n\t\teditor.snaps.clearIndicators()\n\n\t\tlet nextHandle = { ...initialHandle, x: point.x, y: point.y }\n\n\t\tlet canSnap = false\n\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\tif (initialHandle.canSnap && initialHandle.snapType) {\n\t\t\twarnOnce(\n\t\t\t\t'canSnap is deprecated. Cannot use both canSnap and snapType together - snapping disabled. Please use only snapType.'\n\t\t\t)\n\t\t} else {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\tcanSnap = initialHandle.canSnap || initialHandle.snapType !== undefined\n\t\t}\n\n\t\tif (canSnap && (isSnapMode ? !ctrlKey : ctrlKey)) {\n\t\t\t// We're snapping\n\t\t\tconst pageTransform = editor.getShapePageTransform(shape.id)\n\t\t\tif (!pageTransform) throw Error('Expected a page transform')\n\n\t\t\tconst snap = snaps.handles.snapHandle({ currentShapeId: shapeId, handle: nextHandle })\n\n\t\t\tif (snap) {\n\t\t\t\tsnap.nudge.rot(-editor.getShapeParentTransform(shape)!.rotation())\n\t\t\t\tpoint.add(snap.nudge)\n\t\t\t\tnextHandle = { ...initialHandle, x: point.x, y: point.y }\n\t\t\t}\n\t\t}\n\n\t\tconst changes = util.onHandleDrag?.(shape, {\n\t\t\thandle: nextHandle,\n\t\t\tisPrecise: this.isPrecise || altKey,\n\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\tinitial: initial,\n\t\t})\n\n\t\tconst next: TLShapePartial<any> = { id: shape.id, type: shape.type, ...changes }\n\n\t\t// Arrows\n\t\tif (\n\t\t\tinitialHandle.type === 'vertex' &&\n\t\t\tthis.editor.isShapeOfType<TLArrowShape>(shape, 'arrow')\n\t\t) {\n\t\t\tconst bindingAfter = getArrowBindings(editor, shape)[initialHandle.id as 'start' | 'end']\n\n\t\t\tif (bindingAfter) {\n\t\t\t\tif (initialBinding?.toId !== bindingAfter.toId) {\n\t\t\t\t\tthis.pointingId = bindingAfter.toId\n\t\t\t\t\tthis.isPrecise = pointerVelocity.len() < 0.5 || altKey\n\t\t\t\t\tthis.isPreciseId = this.isPrecise ? bindingAfter.toId : null\n\t\t\t\t\tthis.resetExactTimeout()\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (initialBinding) {\n\t\t\t\t\tthis.pointingId = null\n\t\t\t\t\tthis.isPrecise = false\n\t\t\t\t\tthis.isPreciseId = null\n\t\t\t\t\tthis.resetExactTimeout()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (changes) {\n\t\t\teditor.updateShapes([next])\n\t\t}\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["handle"]
7
7
  }
@@ -19,7 +19,9 @@ class PointingArrowLabel extends StateNode {
19
19
  }
20
20
  onEnter(info) {
21
21
  const { shape } = info;
22
- this.parent.setCurrentToolIdMask(info.onInteractionEnd);
22
+ if (typeof info.onInteractionEnd === "string") {
23
+ this.parent.setCurrentToolIdMask(info.onInteractionEnd);
24
+ }
23
25
  this.info = info;
24
26
  this.shapeId = shape.id;
25
27
  this.didDrag = false;
@@ -104,19 +106,29 @@ class PointingArrowLabel extends StateNode {
104
106
  this.cancel();
105
107
  }
106
108
  complete() {
107
- if (this.info.onInteractionEnd) {
108
- this.editor.setCurrentTool(this.info.onInteractionEnd, {});
109
- } else {
110
- this.parent.transition("idle");
109
+ const { onInteractionEnd } = this.info;
110
+ if (onInteractionEnd) {
111
+ if (typeof onInteractionEnd === "string") {
112
+ this.editor.setCurrentTool(onInteractionEnd, {});
113
+ } else {
114
+ onInteractionEnd();
115
+ }
116
+ return;
111
117
  }
118
+ this.parent.transition("idle");
112
119
  }
113
120
  cancel() {
114
121
  this.editor.bailToMark(this.markId);
115
- if (this.info.onInteractionEnd) {
116
- this.editor.setCurrentTool(this.info.onInteractionEnd, {});
117
- } else {
118
- this.parent.transition("idle");
122
+ const { onInteractionEnd } = this.info;
123
+ if (onInteractionEnd) {
124
+ if (typeof onInteractionEnd === "string") {
125
+ this.editor.setCurrentTool(onInteractionEnd, {});
126
+ } else {
127
+ onInteractionEnd();
128
+ }
129
+ return;
119
130
  }
131
+ this.parent.transition("idle");
120
132
  }
121
133
  }
122
134
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts"],
4
- "sourcesContent": ["import {\n\tGroup2d,\n\tStateNode,\n\tTLArrowShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\tVec,\n} from '@tldraw/editor'\nimport { ArrowShapeUtil } from '../../../shapes/arrow/ArrowShapeUtil'\nimport {\n\tgetArrowBodyGeometry,\n\tgetArrowLabelDefaultPosition,\n} from '../../../shapes/arrow/arrowLabel'\n\nexport class PointingArrowLabel extends StateNode {\n\tstatic override id = 'pointing_arrow_label'\n\n\tshapeId = '' as TLShapeId\n\tmarkId = ''\n\twasAlreadySelected = false\n\tdidDrag = false\n\tdidCtrlOnEnter = false\n\n\tprivate info = {} as TLPointerEventInfo & {\n\t\tshape: TLArrowShape\n\t\tonInteractionEnd?: string\n\t\tisCreating: boolean\n\t}\n\n\tprivate updateCursor() {\n\t\tthis.editor.setCursor({ type: 'grabbing', rotation: 0 })\n\t}\n\n\toverride onEnter(\n\t\tinfo: TLPointerEventInfo & {\n\t\t\tshape: TLArrowShape\n\t\t\tonInteractionEnd?: string\n\t\t\tisCreating: boolean\n\t\t}\n\t) {\n\t\tconst { shape } = info\n\t\tthis.parent.setCurrentToolIdMask(info.onInteractionEnd)\n\t\tthis.info = info\n\t\tthis.shapeId = shape.id\n\t\tthis.didDrag = false\n\t\tthis.didCtrlOnEnter = info.accelKey\n\t\tthis.wasAlreadySelected = this.editor.getOnlySelectedShapeId() === shape.id\n\t\tthis.updateCursor()\n\n\t\tconst geometry = this.editor.getShapeGeometry<Group2d>(shape)\n\t\tconst labelGeometry = geometry.children[1]\n\t\tif (!labelGeometry) {\n\t\t\tthrow Error(`Expected to find an arrow label geometry for shape: ${shape.id}`)\n\t\t}\n\t\tconst { currentPagePoint } = this.editor.inputs\n\t\tconst pointInShapeSpace = this.editor.getPointInShapeSpace(shape, currentPagePoint)\n\n\t\tthis._labelDragOffset = Vec.Sub(labelGeometry.center, pointInShapeSpace)\n\n\t\tthis.markId = this.editor.markHistoryStoppingPoint('label-drag start')\n\n\t\tconst additiveSelectionKey = info.shiftKey || info.accelKey\n\t\tif (additiveSelectionKey) {\n\t\t\tconst selectedShapeIds = this.editor.getSelectedShapeIds()\n\t\t\tthis.editor.setSelectedShapes([...selectedShapeIds, this.shapeId])\n\n\t\t\treturn\n\t\t}\n\n\t\tthis.editor.setSelectedShapes([this.shapeId])\n\t}\n\n\toverride onExit() {\n\t\tthis.parent.setCurrentToolIdMask(undefined)\n\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t}\n\n\tprivate _labelDragOffset = new Vec(0, 0)\n\n\toverride onPointerMove() {\n\t\tconst { isDragging } = this.editor.inputs\n\t\tif (!isDragging) return\n\n\t\tif (this.didCtrlOnEnter) {\n\t\t\tthis.parent.transition('brushing', this.info)\n\t\t\treturn\n\t\t}\n\n\t\tconst shape = this.editor.getShape<TLArrowShape>(this.shapeId)\n\t\tif (!shape) return\n\n\t\tconst options = this.editor.getShapeUtil<ArrowShapeUtil>('arrow').options\n\t\tconst geometry = getArrowBodyGeometry(this.editor, shape)\n\t\tconst transform = this.editor.getShapePageTransform(shape.id)\n\n\t\tconst pointInShapeSpace = this.editor\n\t\t\t.getPointInShapeSpace(shape, this.editor.inputs.currentPagePoint)\n\t\t\t.add(this._labelDragOffset)\n\n\t\tconst defaultLabelPosition = getArrowLabelDefaultPosition(this.editor, shape)\n\n\t\tlet nextLabelPosition = geometry.uninterpolateAlongEdge(pointInShapeSpace)\n\n\t\tif (isNaN(nextLabelPosition)) {\n\t\t\tnextLabelPosition = defaultLabelPosition\n\t\t}\n\n\t\tconst nextLabelPoint = transform.applyToPoint(geometry.interpolateAlongEdge(nextLabelPosition))\n\t\tconst labelDefaultPoint = transform.applyToPoint(\n\t\t\tgeometry.interpolateAlongEdge(defaultLabelPosition)\n\t\t)\n\n\t\tif (\n\t\t\tVec.DistMin(\n\t\t\t\tnextLabelPoint,\n\t\t\t\tlabelDefaultPoint,\n\t\t\t\toptions.labelCenterSnapDistance / this.editor.getZoomLevel()\n\t\t\t)\n\t\t) {\n\t\t\tnextLabelPosition = defaultLabelPosition\n\t\t}\n\n\t\tthis.didDrag = true\n\t\tthis.editor.updateShape<TLArrowShape>({\n\t\t\tid: shape.id,\n\t\t\ttype: shape.type,\n\t\t\tprops: { labelPosition: nextLabelPosition },\n\t\t})\n\t}\n\n\toverride onPointerUp() {\n\t\tconst shape = this.editor.getShape<TLArrowShape>(this.shapeId)\n\t\tif (!shape) return\n\n\t\tif (this.didDrag || !this.wasAlreadySelected) {\n\t\t\tthis.complete()\n\t\t} else if (!this.editor.getIsReadonly()) {\n\t\t\t// Go into edit mode.\n\t\t\tthis.editor.setEditingShape(shape.id)\n\t\t\tthis.editor.setCurrentTool('select.editing_shape')\n\t\t}\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.cancel()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate complete() {\n\t\tif (this.info.onInteractionEnd) {\n\t\t\tthis.editor.setCurrentTool(this.info.onInteractionEnd, {})\n\t\t} else {\n\t\t\tthis.parent.transition('idle')\n\t\t}\n\t}\n\n\tprivate cancel() {\n\t\tthis.editor.bailToMark(this.markId)\n\n\t\tif (this.info.onInteractionEnd) {\n\t\t\tthis.editor.setCurrentTool(this.info.onInteractionEnd, {})\n\t\t} else {\n\t\t\tthis.parent.transition('idle')\n\t\t}\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tGroup2d,\n\tStateNode,\n\tTLArrowShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\tVec,\n} from '@tldraw/editor'\nimport { ArrowShapeUtil } from '../../../shapes/arrow/ArrowShapeUtil'\nimport {\n\tgetArrowBodyGeometry,\n\tgetArrowLabelDefaultPosition,\n} from '../../../shapes/arrow/arrowLabel'\n\nexport class PointingArrowLabel extends StateNode {\n\tstatic override id = 'pointing_arrow_label'\n\n\tshapeId = '' as TLShapeId\n\tmarkId = ''\n\twasAlreadySelected = false\n\tdidDrag = false\n\tdidCtrlOnEnter = false\n\n\tprivate info = {} as TLPointerEventInfo & {\n\t\tshape: TLArrowShape\n\t\tonInteractionEnd?: string | (() => void)\n\t\tisCreating: boolean\n\t}\n\n\tprivate updateCursor() {\n\t\tthis.editor.setCursor({ type: 'grabbing', rotation: 0 })\n\t}\n\n\toverride onEnter(\n\t\tinfo: TLPointerEventInfo & {\n\t\t\tshape: TLArrowShape\n\t\t\tonInteractionEnd?: string | (() => void)\n\t\t\tisCreating: boolean\n\t\t}\n\t) {\n\t\tconst { shape } = info\n\t\tif (typeof info.onInteractionEnd === 'string') {\n\t\t\tthis.parent.setCurrentToolIdMask(info.onInteractionEnd)\n\t\t}\n\t\tthis.info = info\n\t\tthis.shapeId = shape.id\n\t\tthis.didDrag = false\n\t\tthis.didCtrlOnEnter = info.accelKey\n\t\tthis.wasAlreadySelected = this.editor.getOnlySelectedShapeId() === shape.id\n\t\tthis.updateCursor()\n\n\t\tconst geometry = this.editor.getShapeGeometry<Group2d>(shape)\n\t\tconst labelGeometry = geometry.children[1]\n\t\tif (!labelGeometry) {\n\t\t\tthrow Error(`Expected to find an arrow label geometry for shape: ${shape.id}`)\n\t\t}\n\t\tconst { currentPagePoint } = this.editor.inputs\n\t\tconst pointInShapeSpace = this.editor.getPointInShapeSpace(shape, currentPagePoint)\n\n\t\tthis._labelDragOffset = Vec.Sub(labelGeometry.center, pointInShapeSpace)\n\n\t\tthis.markId = this.editor.markHistoryStoppingPoint('label-drag start')\n\n\t\tconst additiveSelectionKey = info.shiftKey || info.accelKey\n\t\tif (additiveSelectionKey) {\n\t\t\tconst selectedShapeIds = this.editor.getSelectedShapeIds()\n\t\t\tthis.editor.setSelectedShapes([...selectedShapeIds, this.shapeId])\n\n\t\t\treturn\n\t\t}\n\n\t\tthis.editor.setSelectedShapes([this.shapeId])\n\t}\n\n\toverride onExit() {\n\t\tthis.parent.setCurrentToolIdMask(undefined)\n\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t}\n\n\tprivate _labelDragOffset = new Vec(0, 0)\n\n\toverride onPointerMove() {\n\t\tconst { isDragging } = this.editor.inputs\n\t\tif (!isDragging) return\n\n\t\tif (this.didCtrlOnEnter) {\n\t\t\tthis.parent.transition('brushing', this.info)\n\t\t\treturn\n\t\t}\n\n\t\tconst shape = this.editor.getShape<TLArrowShape>(this.shapeId)\n\t\tif (!shape) return\n\n\t\tconst options = this.editor.getShapeUtil<ArrowShapeUtil>('arrow').options\n\t\tconst geometry = getArrowBodyGeometry(this.editor, shape)\n\t\tconst transform = this.editor.getShapePageTransform(shape.id)\n\n\t\tconst pointInShapeSpace = this.editor\n\t\t\t.getPointInShapeSpace(shape, this.editor.inputs.currentPagePoint)\n\t\t\t.add(this._labelDragOffset)\n\n\t\tconst defaultLabelPosition = getArrowLabelDefaultPosition(this.editor, shape)\n\n\t\tlet nextLabelPosition = geometry.uninterpolateAlongEdge(pointInShapeSpace)\n\n\t\tif (isNaN(nextLabelPosition)) {\n\t\t\tnextLabelPosition = defaultLabelPosition\n\t\t}\n\n\t\tconst nextLabelPoint = transform.applyToPoint(geometry.interpolateAlongEdge(nextLabelPosition))\n\t\tconst labelDefaultPoint = transform.applyToPoint(\n\t\t\tgeometry.interpolateAlongEdge(defaultLabelPosition)\n\t\t)\n\n\t\tif (\n\t\t\tVec.DistMin(\n\t\t\t\tnextLabelPoint,\n\t\t\t\tlabelDefaultPoint,\n\t\t\t\toptions.labelCenterSnapDistance / this.editor.getZoomLevel()\n\t\t\t)\n\t\t) {\n\t\t\tnextLabelPosition = defaultLabelPosition\n\t\t}\n\n\t\tthis.didDrag = true\n\t\tthis.editor.updateShape<TLArrowShape>({\n\t\t\tid: shape.id,\n\t\t\ttype: shape.type,\n\t\t\tprops: { labelPosition: nextLabelPosition },\n\t\t})\n\t}\n\n\toverride onPointerUp() {\n\t\tconst shape = this.editor.getShape<TLArrowShape>(this.shapeId)\n\t\tif (!shape) return\n\n\t\tif (this.didDrag || !this.wasAlreadySelected) {\n\t\t\tthis.complete()\n\t\t} else if (!this.editor.getIsReadonly()) {\n\t\t\t// Go into edit mode.\n\t\t\tthis.editor.setEditingShape(shape.id)\n\t\t\tthis.editor.setCurrentTool('select.editing_shape')\n\t\t}\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.cancel()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate complete() {\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd, {})\n\t\t\t} else {\n\t\t\t\tonInteractionEnd()\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tthis.parent.transition('idle')\n\t}\n\n\tprivate cancel() {\n\t\tthis.editor.bailToMark(this.markId)\n\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd, {})\n\t\t\t} else {\n\t\t\t\tonInteractionEnd()\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tthis.parent.transition('idle')\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -27,8 +27,14 @@ class PointingResizeHandle extends StateNode {
27
27
  }
28
28
  onEnter(info) {
29
29
  this.info = info;
30
+ if (typeof info.onInteractionEnd === "string") {
31
+ this.parent.setCurrentToolIdMask(info.onInteractionEnd);
32
+ }
30
33
  this.updateCursor();
31
34
  }
35
+ onExit() {
36
+ this.parent.setCurrentToolIdMask(void 0);
37
+ }
32
38
  onPointerMove() {
33
39
  if (this.editor.inputs.isDragging) {
34
40
  this.startResizing();
@@ -54,18 +60,28 @@ class PointingResizeHandle extends StateNode {
54
60
  this.cancel();
55
61
  }
56
62
  complete() {
57
- if (this.info.onInteractionEnd) {
58
- this.editor.setCurrentTool(this.info.onInteractionEnd, {});
59
- } else {
60
- this.parent.transition("idle");
63
+ const { onInteractionEnd } = this.info;
64
+ if (onInteractionEnd) {
65
+ if (typeof onInteractionEnd === "string") {
66
+ this.editor.setCurrentTool(onInteractionEnd, {});
67
+ } else {
68
+ onInteractionEnd();
69
+ }
70
+ return;
61
71
  }
72
+ this.parent.transition("idle");
62
73
  }
63
74
  cancel() {
64
- if (this.info.onInteractionEnd) {
65
- this.editor.setCurrentTool(this.info.onInteractionEnd, {});
66
- } else {
67
- this.parent.transition("idle");
75
+ const { onInteractionEnd } = this.info;
76
+ if (onInteractionEnd) {
77
+ if (typeof onInteractionEnd === "string") {
78
+ this.editor.setCurrentTool(onInteractionEnd, {});
79
+ } else {
80
+ onInteractionEnd();
81
+ }
82
+ return;
68
83
  }
84
+ this.parent.transition("idle");
69
85
  }
70
86
  }
71
87
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/tools/SelectTool/childStates/PointingResizeHandle.ts"],
4
- "sourcesContent": ["import { StateNode, TLCursorType, TLPointerEventInfo, TLSelectionHandle } from '@tldraw/editor'\n\nexport const CursorTypeMap: Record<TLSelectionHandle, TLCursorType> = {\n\tbottom: 'ns-resize',\n\ttop: 'ns-resize',\n\tleft: 'ew-resize',\n\tright: 'ew-resize',\n\tbottom_left: 'nesw-resize',\n\tbottom_right: 'nwse-resize',\n\ttop_left: 'nwse-resize',\n\ttop_right: 'nesw-resize',\n\tbottom_left_rotate: 'swne-rotate',\n\tbottom_right_rotate: 'senw-rotate',\n\ttop_left_rotate: 'nwse-rotate',\n\ttop_right_rotate: 'nesw-rotate',\n\tmobile_rotate: 'grabbing',\n}\n\ntype PointingResizeHandleInfo = Extract<TLPointerEventInfo, { target: 'selection' }> & {\n\tonInteractionEnd?: string\n}\n\nexport class PointingResizeHandle extends StateNode {\n\tstatic override id = 'pointing_resize_handle'\n\n\tprivate info = {} as PointingResizeHandleInfo\n\n\tprivate updateCursor() {\n\t\tconst selected = this.editor.getSelectedShapes()\n\t\tconst cursorType = CursorTypeMap[this.info.handle!]\n\t\tthis.editor.setCursor({\n\t\t\ttype: cursorType,\n\t\t\trotation: selected.length === 1 ? this.editor.getSelectionRotation() : 0,\n\t\t})\n\t}\n\n\toverride onEnter(info: PointingResizeHandleInfo) {\n\t\tthis.info = info\n\t\tthis.updateCursor()\n\t}\n\n\toverride onPointerMove() {\n\t\tif (this.editor.inputs.isDragging) {\n\t\t\tthis.startResizing()\n\t\t}\n\t}\n\n\toverride onLongPress() {\n\t\tthis.startResizing()\n\t}\n\n\tprivate startResizing() {\n\t\tif (this.editor.getIsReadonly()) return\n\t\tthis.parent.transition('resizing', this.info)\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.cancel()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate complete() {\n\t\tif (this.info.onInteractionEnd) {\n\t\t\tthis.editor.setCurrentTool(this.info.onInteractionEnd, {})\n\t\t} else {\n\t\t\tthis.parent.transition('idle')\n\t\t}\n\t}\n\n\tprivate cancel() {\n\t\tif (this.info.onInteractionEnd) {\n\t\t\tthis.editor.setCurrentTool(this.info.onInteractionEnd, {})\n\t\t} else {\n\t\t\tthis.parent.transition('idle')\n\t\t}\n\t}\n}\n"],
5
- "mappings": "AAAA,SAAS,iBAAsE;AAExE,MAAM,gBAAyD;AAAA,EACrE,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,cAAc;AAAA,EACd,UAAU;AAAA,EACV,WAAW;AAAA,EACX,oBAAoB;AAAA,EACpB,qBAAqB;AAAA,EACrB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,eAAe;AAChB;AAMO,MAAM,6BAA6B,UAAU;AAAA,EACnD,OAAgB,KAAK;AAAA,EAEb,OAAO,CAAC;AAAA,EAER,eAAe;AACtB,UAAM,WAAW,KAAK,OAAO,kBAAkB;AAC/C,UAAM,aAAa,cAAc,KAAK,KAAK,MAAO;AAClD,SAAK,OAAO,UAAU;AAAA,MACrB,MAAM;AAAA,MACN,UAAU,SAAS,WAAW,IAAI,KAAK,OAAO,qBAAqB,IAAI;AAAA,IACxE,CAAC;AAAA,EACF;AAAA,EAES,QAAQ,MAAgC;AAChD,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACnB;AAAA,EAES,gBAAgB;AACxB,QAAI,KAAK,OAAO,OAAO,YAAY;AAClC,WAAK,cAAc;AAAA,IACpB;AAAA,EACD;AAAA,EAES,cAAc;AACtB,SAAK,cAAc;AAAA,EACpB;AAAA,EAEQ,gBAAgB;AACvB,QAAI,KAAK,OAAO,cAAc,EAAG;AACjC,SAAK,OAAO,WAAW,YAAY,KAAK,IAAI;AAAA,EAC7C;AAAA,EAES,cAAc;AACtB,SAAK,SAAS;AAAA,EACf;AAAA,EAES,WAAW;AACnB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,aAAa;AACrB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,cAAc;AACtB,SAAK,OAAO;AAAA,EACb;AAAA,EAEQ,WAAW;AAClB,QAAI,KAAK,KAAK,kBAAkB;AAC/B,WAAK,OAAO,eAAe,KAAK,KAAK,kBAAkB,CAAC,CAAC;AAAA,IAC1D,OAAO;AACN,WAAK,OAAO,WAAW,MAAM;AAAA,IAC9B;AAAA,EACD;AAAA,EAEQ,SAAS;AAChB,QAAI,KAAK,KAAK,kBAAkB;AAC/B,WAAK,OAAO,eAAe,KAAK,KAAK,kBAAkB,CAAC,CAAC;AAAA,IAC1D,OAAO;AACN,WAAK,OAAO,WAAW,MAAM;AAAA,IAC9B;AAAA,EACD;AACD;",
4
+ "sourcesContent": ["import { StateNode, TLCursorType, TLPointerEventInfo, TLSelectionHandle } from '@tldraw/editor'\n\nexport const CursorTypeMap: Record<TLSelectionHandle, TLCursorType> = {\n\tbottom: 'ns-resize',\n\ttop: 'ns-resize',\n\tleft: 'ew-resize',\n\tright: 'ew-resize',\n\tbottom_left: 'nesw-resize',\n\tbottom_right: 'nwse-resize',\n\ttop_left: 'nwse-resize',\n\ttop_right: 'nesw-resize',\n\tbottom_left_rotate: 'swne-rotate',\n\tbottom_right_rotate: 'senw-rotate',\n\ttop_left_rotate: 'nwse-rotate',\n\ttop_right_rotate: 'nesw-rotate',\n\tmobile_rotate: 'grabbing',\n}\n\ntype PointingResizeHandleInfo = Extract<TLPointerEventInfo, { target: 'selection' }> & {\n\tonInteractionEnd?: string | (() => void)\n}\n\nexport class PointingResizeHandle extends StateNode {\n\tstatic override id = 'pointing_resize_handle'\n\n\tprivate info = {} as PointingResizeHandleInfo\n\n\tprivate updateCursor() {\n\t\tconst selected = this.editor.getSelectedShapes()\n\t\tconst cursorType = CursorTypeMap[this.info.handle!]\n\t\tthis.editor.setCursor({\n\t\t\ttype: cursorType,\n\t\t\trotation: selected.length === 1 ? this.editor.getSelectionRotation() : 0,\n\t\t})\n\t}\n\n\toverride onEnter(info: PointingResizeHandleInfo) {\n\t\tthis.info = info\n\t\tif (typeof info.onInteractionEnd === 'string') {\n\t\t\tthis.parent.setCurrentToolIdMask(info.onInteractionEnd)\n\t\t}\n\t\tthis.updateCursor()\n\t}\n\n\toverride onExit() {\n\t\tthis.parent.setCurrentToolIdMask(undefined)\n\t}\n\n\toverride onPointerMove() {\n\t\tif (this.editor.inputs.isDragging) {\n\t\t\tthis.startResizing()\n\t\t}\n\t}\n\n\toverride onLongPress() {\n\t\tthis.startResizing()\n\t}\n\n\tprivate startResizing() {\n\t\tif (this.editor.getIsReadonly()) return\n\t\tthis.parent.transition('resizing', this.info)\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.cancel()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate complete() {\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd, {})\n\t\t\t} else {\n\t\t\t\tonInteractionEnd()\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tthis.parent.transition('idle')\n\t}\n\n\tprivate cancel() {\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd, {})\n\t\t\t} else {\n\t\t\t\tonInteractionEnd()\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tthis.parent.transition('idle')\n\t}\n}\n"],
5
+ "mappings": "AAAA,SAAS,iBAAsE;AAExE,MAAM,gBAAyD;AAAA,EACrE,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,cAAc;AAAA,EACd,UAAU;AAAA,EACV,WAAW;AAAA,EACX,oBAAoB;AAAA,EACpB,qBAAqB;AAAA,EACrB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,eAAe;AAChB;AAMO,MAAM,6BAA6B,UAAU;AAAA,EACnD,OAAgB,KAAK;AAAA,EAEb,OAAO,CAAC;AAAA,EAER,eAAe;AACtB,UAAM,WAAW,KAAK,OAAO,kBAAkB;AAC/C,UAAM,aAAa,cAAc,KAAK,KAAK,MAAO;AAClD,SAAK,OAAO,UAAU;AAAA,MACrB,MAAM;AAAA,MACN,UAAU,SAAS,WAAW,IAAI,KAAK,OAAO,qBAAqB,IAAI;AAAA,IACxE,CAAC;AAAA,EACF;AAAA,EAES,QAAQ,MAAgC;AAChD,SAAK,OAAO;AACZ,QAAI,OAAO,KAAK,qBAAqB,UAAU;AAC9C,WAAK,OAAO,qBAAqB,KAAK,gBAAgB;AAAA,IACvD;AACA,SAAK,aAAa;AAAA,EACnB;AAAA,EAES,SAAS;AACjB,SAAK,OAAO,qBAAqB,MAAS;AAAA,EAC3C;AAAA,EAES,gBAAgB;AACxB,QAAI,KAAK,OAAO,OAAO,YAAY;AAClC,WAAK,cAAc;AAAA,IACpB;AAAA,EACD;AAAA,EAES,cAAc;AACtB,SAAK,cAAc;AAAA,EACpB;AAAA,EAEQ,gBAAgB;AACvB,QAAI,KAAK,OAAO,cAAc,EAAG;AACjC,SAAK,OAAO,WAAW,YAAY,KAAK,IAAI;AAAA,EAC7C;AAAA,EAES,cAAc;AACtB,SAAK,SAAS;AAAA,EACf;AAAA,EAES,WAAW;AACnB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,aAAa;AACrB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,cAAc;AACtB,SAAK,OAAO;AAAA,EACb;AAAA,EAEQ,WAAW;AAClB,UAAM,EAAE,iBAAiB,IAAI,KAAK;AAClC,QAAI,kBAAkB;AACrB,UAAI,OAAO,qBAAqB,UAAU;AACzC,aAAK,OAAO,eAAe,kBAAkB,CAAC,CAAC;AAAA,MAChD,OAAO;AACN,yBAAiB;AAAA,MAClB;AACA;AAAA,IACD;AACA,SAAK,OAAO,WAAW,MAAM;AAAA,EAC9B;AAAA,EAEQ,SAAS;AAChB,UAAM,EAAE,iBAAiB,IAAI,KAAK;AAClC,QAAI,kBAAkB;AACrB,UAAI,OAAO,qBAAqB,UAAU;AACzC,aAAK,OAAO,eAAe,kBAAkB,CAAC,CAAC;AAAA,MAChD,OAAO;AACN,yBAAiB;AAAA,MAClB;AACA;AAAA,IACD;AACA,SAAK,OAAO,WAAW,MAAM;AAAA,EAC9B;AACD;",
6
6
  "names": []
7
7
  }
@@ -10,8 +10,10 @@ class PointingRotateHandle extends StateNode {
10
10
  });
11
11
  }
12
12
  onEnter(info) {
13
- this.parent.setCurrentToolIdMask(info.onInteractionEnd);
14
13
  this.info = info;
14
+ if (typeof info.onInteractionEnd === "string") {
15
+ this.parent.setCurrentToolIdMask(info.onInteractionEnd);
16
+ }
15
17
  this.updateCursor();
16
18
  }
17
19
  onExit() {
@@ -43,18 +45,28 @@ class PointingRotateHandle extends StateNode {
43
45
  this.cancel();
44
46
  }
45
47
  complete() {
46
- if (this.info.onInteractionEnd) {
47
- this.editor.setCurrentTool(this.info.onInteractionEnd, {});
48
- } else {
49
- this.parent.transition("idle");
48
+ const { onInteractionEnd } = this.info;
49
+ if (onInteractionEnd) {
50
+ if (typeof onInteractionEnd === "string") {
51
+ this.editor.setCurrentTool(onInteractionEnd, {});
52
+ } else {
53
+ onInteractionEnd?.();
54
+ }
55
+ return;
50
56
  }
57
+ this.parent.transition("idle");
51
58
  }
52
59
  cancel() {
53
- if (this.info.onInteractionEnd) {
54
- this.editor.setCurrentTool(this.info.onInteractionEnd, {});
55
- } else {
56
- this.parent.transition("idle");
60
+ const { onInteractionEnd } = this.info;
61
+ if (onInteractionEnd) {
62
+ if (typeof onInteractionEnd === "string") {
63
+ this.editor.setCurrentTool(onInteractionEnd, {});
64
+ } else {
65
+ onInteractionEnd();
66
+ }
67
+ return;
57
68
  }
69
+ this.parent.transition("idle");
58
70
  }
59
71
  }
60
72
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/tools/SelectTool/childStates/PointingRotateHandle.ts"],
4
- "sourcesContent": ["import { RotateCorner, StateNode, TLPointerEventInfo } from '@tldraw/editor'\nimport { CursorTypeMap } from './PointingResizeHandle'\n\ntype PointingRotateHandleInfo = Extract<TLPointerEventInfo, { target: 'selection' }> & {\n\tonInteractionEnd?: string\n}\n\nexport class PointingRotateHandle extends StateNode {\n\tstatic override id = 'pointing_rotate_handle'\n\n\tprivate info = {} as PointingRotateHandleInfo\n\n\tprivate updateCursor() {\n\t\tthis.editor.setCursor({\n\t\t\ttype: CursorTypeMap[this.info.handle as RotateCorner],\n\t\t\trotation: this.editor.getSelectionRotation(),\n\t\t})\n\t}\n\n\toverride onEnter(info: PointingRotateHandleInfo) {\n\t\tthis.parent.setCurrentToolIdMask(info.onInteractionEnd)\n\t\tthis.info = info\n\t\tthis.updateCursor()\n\t}\n\n\toverride onExit() {\n\t\tthis.parent.setCurrentToolIdMask(undefined)\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t}\n\n\toverride onPointerMove() {\n\t\tif (this.editor.inputs.isDragging) {\n\t\t\tthis.startRotating()\n\t\t}\n\t}\n\n\toverride onLongPress() {\n\t\tthis.startRotating()\n\t}\n\n\tprivate startRotating() {\n\t\tif (this.editor.getIsReadonly()) return\n\t\tthis.parent.transition('rotating', this.info)\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.cancel()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate complete() {\n\t\tif (this.info.onInteractionEnd) {\n\t\t\tthis.editor.setCurrentTool(this.info.onInteractionEnd, {})\n\t\t} else {\n\t\t\tthis.parent.transition('idle')\n\t\t}\n\t}\n\n\tprivate cancel() {\n\t\tif (this.info.onInteractionEnd) {\n\t\t\tthis.editor.setCurrentTool(this.info.onInteractionEnd, {})\n\t\t} else {\n\t\t\tthis.parent.transition('idle')\n\t\t}\n\t}\n}\n"],
5
- "mappings": "AAAA,SAAuB,iBAAqC;AAC5D,SAAS,qBAAqB;AAMvB,MAAM,6BAA6B,UAAU;AAAA,EACnD,OAAgB,KAAK;AAAA,EAEb,OAAO,CAAC;AAAA,EAER,eAAe;AACtB,SAAK,OAAO,UAAU;AAAA,MACrB,MAAM,cAAc,KAAK,KAAK,MAAsB;AAAA,MACpD,UAAU,KAAK,OAAO,qBAAqB;AAAA,IAC5C,CAAC;AAAA,EACF;AAAA,EAES,QAAQ,MAAgC;AAChD,SAAK,OAAO,qBAAqB,KAAK,gBAAgB;AACtD,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACnB;AAAA,EAES,SAAS;AACjB,SAAK,OAAO,qBAAqB,MAAS;AAC1C,SAAK,OAAO,UAAU,EAAE,MAAM,WAAW,UAAU,EAAE,CAAC;AAAA,EACvD;AAAA,EAES,gBAAgB;AACxB,QAAI,KAAK,OAAO,OAAO,YAAY;AAClC,WAAK,cAAc;AAAA,IACpB;AAAA,EACD;AAAA,EAES,cAAc;AACtB,SAAK,cAAc;AAAA,EACpB;AAAA,EAEQ,gBAAgB;AACvB,QAAI,KAAK,OAAO,cAAc,EAAG;AACjC,SAAK,OAAO,WAAW,YAAY,KAAK,IAAI;AAAA,EAC7C;AAAA,EAES,cAAc;AACtB,SAAK,SAAS;AAAA,EACf;AAAA,EAES,WAAW;AACnB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,aAAa;AACrB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,cAAc;AACtB,SAAK,OAAO;AAAA,EACb;AAAA,EAEQ,WAAW;AAClB,QAAI,KAAK,KAAK,kBAAkB;AAC/B,WAAK,OAAO,eAAe,KAAK,KAAK,kBAAkB,CAAC,CAAC;AAAA,IAC1D,OAAO;AACN,WAAK,OAAO,WAAW,MAAM;AAAA,IAC9B;AAAA,EACD;AAAA,EAEQ,SAAS;AAChB,QAAI,KAAK,KAAK,kBAAkB;AAC/B,WAAK,OAAO,eAAe,KAAK,KAAK,kBAAkB,CAAC,CAAC;AAAA,IAC1D,OAAO;AACN,WAAK,OAAO,WAAW,MAAM;AAAA,IAC9B;AAAA,EACD;AACD;",
4
+ "sourcesContent": ["import { RotateCorner, StateNode, TLPointerEventInfo } from '@tldraw/editor'\nimport { CursorTypeMap } from './PointingResizeHandle'\n\ntype PointingRotateHandleInfo = Extract<TLPointerEventInfo, { target: 'selection' }> & {\n\tonInteractionEnd?: string | (() => void)\n}\n\nexport class PointingRotateHandle extends StateNode {\n\tstatic override id = 'pointing_rotate_handle'\n\n\tprivate info = {} as PointingRotateHandleInfo\n\n\tprivate updateCursor() {\n\t\tthis.editor.setCursor({\n\t\t\ttype: CursorTypeMap[this.info.handle as RotateCorner],\n\t\t\trotation: this.editor.getSelectionRotation(),\n\t\t})\n\t}\n\n\toverride onEnter(info: PointingRotateHandleInfo) {\n\t\tthis.info = info\n\t\tif (typeof info.onInteractionEnd === 'string') {\n\t\t\tthis.parent.setCurrentToolIdMask(info.onInteractionEnd)\n\t\t}\n\t\tthis.updateCursor()\n\t}\n\n\toverride onExit() {\n\t\tthis.parent.setCurrentToolIdMask(undefined)\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t}\n\n\toverride onPointerMove() {\n\t\tif (this.editor.inputs.isDragging) {\n\t\t\tthis.startRotating()\n\t\t}\n\t}\n\n\toverride onLongPress() {\n\t\tthis.startRotating()\n\t}\n\n\tprivate startRotating() {\n\t\tif (this.editor.getIsReadonly()) return\n\t\tthis.parent.transition('rotating', this.info)\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.cancel()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate complete() {\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\t// Return to the tool that was active before this one, whether tool lock is turned on or not!\n\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd, {})\n\t\t\t} else {\n\t\t\t\tonInteractionEnd?.()\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tthis.parent.transition('idle')\n\t}\n\n\tprivate cancel() {\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd, {})\n\t\t\t} else {\n\t\t\t\tonInteractionEnd()\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tthis.parent.transition('idle')\n\t}\n}\n"],
5
+ "mappings": "AAAA,SAAuB,iBAAqC;AAC5D,SAAS,qBAAqB;AAMvB,MAAM,6BAA6B,UAAU;AAAA,EACnD,OAAgB,KAAK;AAAA,EAEb,OAAO,CAAC;AAAA,EAER,eAAe;AACtB,SAAK,OAAO,UAAU;AAAA,MACrB,MAAM,cAAc,KAAK,KAAK,MAAsB;AAAA,MACpD,UAAU,KAAK,OAAO,qBAAqB;AAAA,IAC5C,CAAC;AAAA,EACF;AAAA,EAES,QAAQ,MAAgC;AAChD,SAAK,OAAO;AACZ,QAAI,OAAO,KAAK,qBAAqB,UAAU;AAC9C,WAAK,OAAO,qBAAqB,KAAK,gBAAgB;AAAA,IACvD;AACA,SAAK,aAAa;AAAA,EACnB;AAAA,EAES,SAAS;AACjB,SAAK,OAAO,qBAAqB,MAAS;AAC1C,SAAK,OAAO,UAAU,EAAE,MAAM,WAAW,UAAU,EAAE,CAAC;AAAA,EACvD;AAAA,EAES,gBAAgB;AACxB,QAAI,KAAK,OAAO,OAAO,YAAY;AAClC,WAAK,cAAc;AAAA,IACpB;AAAA,EACD;AAAA,EAES,cAAc;AACtB,SAAK,cAAc;AAAA,EACpB;AAAA,EAEQ,gBAAgB;AACvB,QAAI,KAAK,OAAO,cAAc,EAAG;AACjC,SAAK,OAAO,WAAW,YAAY,KAAK,IAAI;AAAA,EAC7C;AAAA,EAES,cAAc;AACtB,SAAK,SAAS;AAAA,EACf;AAAA,EAES,WAAW;AACnB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,aAAa;AACrB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,cAAc;AACtB,SAAK,OAAO;AAAA,EACb;AAAA,EAEQ,WAAW;AAClB,UAAM,EAAE,iBAAiB,IAAI,KAAK;AAClC,QAAI,kBAAkB;AACrB,UAAI,OAAO,qBAAqB,UAAU;AAEzC,aAAK,OAAO,eAAe,kBAAkB,CAAC,CAAC;AAAA,MAChD,OAAO;AACN,2BAAmB;AAAA,MACpB;AACA;AAAA,IACD;AACA,SAAK,OAAO,WAAW,MAAM;AAAA,EAC9B;AAAA,EAEQ,SAAS;AAChB,UAAM,EAAE,iBAAiB,IAAI,KAAK;AAClC,QAAI,kBAAkB;AACrB,UAAI,OAAO,qBAAqB,UAAU;AACzC,aAAK,OAAO,eAAe,kBAAkB,CAAC,CAAC;AAAA,MAChD,OAAO;AACN,yBAAiB;AAAA,MAClB;AACA;AAAA,IACD;AACA,SAAK,OAAO,WAAW,MAAM;AAAA,EAC9B;AACD;",
6
6
  "names": []
7
7
  }
@@ -25,7 +25,9 @@ class Resizing extends StateNode {
25
25
  const { isCreating = false, creatingMarkId, creationCursorOffset = { x: 0, y: 0 } } = info;
26
26
  this.info = info;
27
27
  this.didHoldCommand = false;
28
- this.parent.setCurrentToolIdMask(info.onInteractionEnd);
28
+ if (typeof info.onInteractionEnd === "string") {
29
+ this.parent.setCurrentToolIdMask(info.onInteractionEnd);
30
+ }
29
31
  this.creationCursorOffset = creationCursorOffset;
30
32
  try {
31
33
  this.snapshot = this._createSnapshot();
@@ -87,11 +89,16 @@ class Resizing extends StateNode {
87
89
  }
88
90
  });
89
91
  this.editor.bailToMark(this.markId);
90
- if (this.info.onInteractionEnd) {
91
- this.editor.setCurrentTool(this.info.onInteractionEnd, {});
92
- } else {
93
- this.parent.transition("idle");
92
+ const { onInteractionEnd } = this.info;
93
+ if (onInteractionEnd) {
94
+ if (typeof onInteractionEnd === "string") {
95
+ this.editor.setCurrentTool(onInteractionEnd, {});
96
+ } else {
97
+ onInteractionEnd();
98
+ }
99
+ return;
94
100
  }
101
+ this.parent.transition("idle");
95
102
  }
96
103
  complete() {
97
104
  kickoutOccludedShapes(this.editor, this.snapshot.selectedShapeIds);
@@ -100,9 +107,17 @@ class Resizing extends StateNode {
100
107
  this.info.onCreate?.(this.editor.getOnlySelectedShape());
101
108
  return;
102
109
  }
103
- if (this.editor.getInstanceState().isToolLocked && this.info.onInteractionEnd) {
104
- this.editor.setCurrentTool(this.info.onInteractionEnd, {});
105
- return;
110
+ const { onInteractionEnd } = this.info;
111
+ if (onInteractionEnd) {
112
+ if (typeof onInteractionEnd === "string") {
113
+ if (this.editor.getInstanceState().isToolLocked) {
114
+ this.editor.setCurrentTool(onInteractionEnd, {});
115
+ return;
116
+ }
117
+ } else {
118
+ onInteractionEnd();
119
+ return;
120
+ }
106
121
  }
107
122
  this.parent.transition("idle");
108
123
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/tools/SelectTool/childStates/Resizing.ts"],
4
- "sourcesContent": ["import {\n\tBox,\n\tHALF_PI,\n\tMat,\n\tPI,\n\tPI2,\n\tSelectionCorner,\n\tSelectionEdge,\n\tStateNode,\n\tTLFrameShape,\n\tTLPointerEventInfo,\n\tTLShape,\n\tTLShapeId,\n\tTLShapePartial,\n\tTLTextShape,\n\tTLTickEventInfo,\n\tVec,\n\tVecLike,\n\tareAnglesCompatible,\n\tcompact,\n\tisAccelKey,\n\tkickoutOccludedShapes,\n} from '@tldraw/editor'\n\nexport type ResizingInfo = TLPointerEventInfo & {\n\ttarget: 'selection'\n\thandle: SelectionEdge | SelectionCorner\n\tisCreating?: boolean\n\tcreatingMarkId?: string\n\tonCreate?(shape: TLShape | null): void\n\tcreationCursorOffset?: VecLike\n\tonInteractionEnd?: string\n}\n\nexport class Resizing extends StateNode {\n\tstatic override id = 'resizing'\n\n\tinfo = {} as ResizingInfo\n\n\tmarkId = ''\n\n\t// A switch to detect when the user is holding ctrl\n\tprivate didHoldCommand = false\n\n\t// we transition into the resizing state from the geo pointing state, which starts with a shape of size w: 1, h: 1,\n\t// so if the user drags x: +50, y: +50 after mouseDown, the shape will be w: 51, h: 51, which is too many pixels, alas\n\t// so we allow passing a further offset into this state to negate such issues\n\tcreationCursorOffset = { x: 0, y: 0 } as VecLike\n\n\tprivate snapshot = {} as any as Snapshot\n\n\toverride onEnter(info: ResizingInfo) {\n\t\tconst { isCreating = false, creatingMarkId, creationCursorOffset = { x: 0, y: 0 } } = info\n\n\t\tthis.info = info\n\t\tthis.didHoldCommand = false\n\n\t\tthis.parent.setCurrentToolIdMask(info.onInteractionEnd)\n\t\tthis.creationCursorOffset = creationCursorOffset\n\n\t\ttry {\n\t\t\t// On rare and mysterious occasions, the user can enter the resizing state with no shapes selected\n\t\t\tthis.snapshot = this._createSnapshot()\n\t\t} catch (e) {\n\t\t\tconsole.error(e)\n\t\t\tthis.cancel()\n\t\t\treturn\n\t\t}\n\n\t\tthis.markId = ''\n\n\t\tif (isCreating) {\n\t\t\tif (creatingMarkId) {\n\t\t\t\tthis.markId = creatingMarkId\n\t\t\t} else {\n\t\t\t\t// handle legacy implicit `creating:{shapeId}` marks\n\t\t\t\tconst markId = this.editor.getMarkIdMatching(\n\t\t\t\t\t`creating:${this.editor.getOnlySelectedShapeId()}`\n\t\t\t\t)\n\t\t\t\tif (markId) {\n\t\t\t\t\tthis.markId = markId\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.markId = this.editor.markHistoryStoppingPoint('starting resizing')\n\t\t}\n\n\t\tif (isCreating) {\n\t\t\tthis.editor.setCursor({ type: 'cross', rotation: 0 })\n\t\t}\n\n\t\tthis.handleResizeStart()\n\t\tthis.updateShapes()\n\t}\n\n\toverride onTick({ elapsed }: TLTickEventInfo) {\n\t\tconst { editor } = this\n\t\teditor.edgeScrollManager.updateEdgeScrolling(elapsed)\n\t}\n\n\toverride onPointerMove() {\n\t\tthis.updateShapes()\n\t}\n\n\toverride onKeyDown() {\n\t\tthis.updateShapes()\n\t}\n\toverride onKeyUp() {\n\t\tthis.updateShapes()\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\tprivate cancel() {\n\t\t// Call onResizeCancel callback before resetting\n\t\tconst { shapeSnapshots } = this.snapshot\n\n\t\tshapeSnapshots.forEach(({ shape }) => {\n\t\t\tconst current = this.editor.getShape(shape.id)\n\t\t\tif (current) {\n\t\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\t\tutil.onResizeCancel?.(shape, current)\n\t\t\t}\n\t\t})\n\n\t\tthis.editor.bailToMark(this.markId)\n\n\t\tif (this.info.onInteractionEnd) {\n\t\t\tthis.editor.setCurrentTool(this.info.onInteractionEnd, {})\n\t\t} else {\n\t\t\tthis.parent.transition('idle')\n\t\t}\n\t}\n\n\tprivate complete() {\n\t\tkickoutOccludedShapes(this.editor, this.snapshot.selectedShapeIds)\n\n\t\tthis.handleResizeEnd()\n\n\t\tif (this.info.isCreating && this.info.onCreate) {\n\t\t\tthis.info.onCreate?.(this.editor.getOnlySelectedShape())\n\t\t\treturn\n\t\t}\n\n\t\tif (this.editor.getInstanceState().isToolLocked && this.info.onInteractionEnd) {\n\t\t\tthis.editor.setCurrentTool(this.info.onInteractionEnd, {})\n\t\t\treturn\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tprivate handleResizeStart() {\n\t\tconst { shapeSnapshots } = this.snapshot\n\n\t\tconst changes: TLShapePartial[] = []\n\n\t\tshapeSnapshots.forEach(({ shape }) => {\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst change = util.onResizeStart?.(shape)\n\t\t\tif (change) {\n\t\t\t\tchanges.push(change)\n\t\t\t}\n\t\t})\n\n\t\tif (changes.length > 0) {\n\t\t\tthis.editor.updateShapes(changes)\n\t\t}\n\t}\n\n\tprivate handleResizeEnd() {\n\t\tconst { shapeSnapshots } = this.snapshot\n\n\t\tconst changes: TLShapePartial[] = []\n\n\t\tshapeSnapshots.forEach(({ shape }) => {\n\t\t\tconst current = this.editor.getShape(shape.id)!\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst change = util.onResizeEnd?.(shape, current)\n\t\t\tif (change) {\n\t\t\t\tchanges.push(change)\n\t\t\t}\n\t\t})\n\n\t\tif (changes.length > 0) {\n\t\t\tthis.editor.updateShapes(changes)\n\t\t}\n\t}\n\n\tprivate updateShapes() {\n\t\tconst { altKey, shiftKey } = this.editor.inputs\n\t\tconst {\n\t\t\tframes,\n\t\t\tshapeSnapshots,\n\t\t\tselectionBounds,\n\t\t\tcursorHandleOffset,\n\t\t\tselectedShapeIds,\n\t\t\tselectionRotation,\n\t\t\tcanShapesDeform,\n\t\t} = this.snapshot\n\n\t\tlet isAspectRatioLocked = shiftKey || !canShapesDeform\n\n\t\tif (shapeSnapshots.size === 1) {\n\t\t\tconst onlySnapshot = [...shapeSnapshots.values()][0]!\n\t\t\tif (this.editor.isShapeOfType<TLTextShape>(onlySnapshot.shape, 'text')) {\n\t\t\t\tisAspectRatioLocked = !(this.info.handle === 'left' || this.info.handle === 'right')\n\t\t\t}\n\t\t}\n\n\t\t// first negate the 'cursor handle offset'\n\t\t// we need to do this because we do grid snapping based on the page point of the handle\n\t\t// rather than the page point of the cursor, so it's easier to pretend that the cursor\n\t\t// is really where the handle actually is\n\t\t//\n\t\t// *** Massively zoomed-in diagram of the initial mouseDown ***\n\t\t//\n\t\t//\n\t\t// \u2502\n\t\t// \u2502\n\t\t// \u2502\n\t\t// \u2502\n\t\t// \u2502\n\t\t// \u2502\n\t\t// \u2502\n\t\t// \u2502corner handle\n\t\t// \u250C\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2510\n\t\t// selection \u2502 \u2502\n\t\t// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524 x\u25C4\u2500\u2500\u253C\u2500\u2500\u2500\u2500 drag handle point \u25B2\n\t\t// \u2502 \u2502 \u2502\n\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u251C\u2500 cursorHandleOffset.y\n\t\t// \u2502\n\t\t// originPagePoint\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25BAx\u2500\u2510 \u25BC\n\t\t// \u2502 \u2514\u2500\u2510\n\t\t// \u2502 \u2514\u2500\u2510\n\t\t// \u2502 \u2502 mouse (sorry)\n\t\t// \u2514\u2500\u2500\u2510 \u250C\u2518\n\t\t// \u2502 \u2502\n\t\t// \u2514\u2500\u2518\n\t\t// \u25C4\u2500\u2500\u252C\u2500\u2500\u25BA\n\t\t// \u2502\n\t\t// cursorHandleOffset.x\n\n\t\tconst isHoldingAccel = isAccelKey(this.editor.inputs)\n\n\t\tconst currentPagePoint = this.editor.inputs.currentPagePoint\n\t\t\t.clone()\n\t\t\t.sub(cursorHandleOffset)\n\t\t\t.sub(this.creationCursorOffset)\n\n\t\tconst originPagePoint = this.editor.inputs.originPagePoint.clone().sub(cursorHandleOffset)\n\n\t\tif (this.editor.getInstanceState().isGridMode && !isHoldingAccel) {\n\t\t\tconst { gridSize } = this.editor.getDocumentSettings()\n\t\t\tcurrentPagePoint.snapToGrid(gridSize)\n\t\t}\n\n\t\tconst dragHandle = this.info.handle as SelectionCorner | SelectionEdge\n\t\tconst scaleOriginHandle = rotateSelectionHandle(dragHandle, Math.PI)\n\n\t\tthis.editor.snaps.clearIndicators()\n\n\t\tconst shouldSnap = this.editor.user.getIsSnapMode() ? !isHoldingAccel : isHoldingAccel\n\n\t\tif (shouldSnap && selectionRotation % HALF_PI === 0) {\n\t\t\tconst { nudge } = this.editor.snaps.shapeBounds.snapResizeShapes({\n\t\t\t\tdragDelta: Vec.Sub(currentPagePoint, originPagePoint),\n\t\t\t\tinitialSelectionPageBounds: this.snapshot.initialSelectionPageBounds,\n\t\t\t\thandle: rotateSelectionHandle(dragHandle, selectionRotation),\n\t\t\t\tisAspectRatioLocked,\n\t\t\t\tisResizingFromCenter: altKey,\n\t\t\t})\n\n\t\t\tcurrentPagePoint.add(nudge)\n\t\t}\n\n\t\t// get the page point of the selection handle opposite to the drag handle\n\t\t// or the center of the selection box if altKey is pressed\n\t\tconst scaleOriginPage = Vec.RotWith(\n\t\t\taltKey ? selectionBounds.center : selectionBounds.getHandlePoint(scaleOriginHandle),\n\t\t\tselectionBounds.point,\n\t\t\tselectionRotation\n\t\t)\n\n\t\t// calculate the scale by measuring the current distance between the drag handle and the scale origin\n\t\t// and dividing by the original distance between the drag handle and the scale origin\n\n\t\t// bug: for edges, the page point doesn't matter, the\n\n\t\tconst distanceFromScaleOriginNow = Vec.Sub(currentPagePoint, scaleOriginPage).rot(\n\t\t\t-selectionRotation\n\t\t)\n\n\t\tconst distanceFromScaleOriginAtStart = Vec.Sub(originPagePoint, scaleOriginPage).rot(\n\t\t\t-selectionRotation\n\t\t)\n\n\t\tconst scale = Vec.DivV(distanceFromScaleOriginNow, distanceFromScaleOriginAtStart)\n\n\t\tif (!Number.isFinite(scale.x)) scale.x = 1\n\t\tif (!Number.isFinite(scale.y)) scale.y = 1\n\n\t\tconst isXLocked = dragHandle === 'top' || dragHandle === 'bottom'\n\t\tconst isYLocked = dragHandle === 'left' || dragHandle === 'right'\n\n\t\t// lock an axis if required\n\t\tif (isAspectRatioLocked) {\n\t\t\tif (isYLocked) {\n\t\t\t\t// holding shift and dragging either the left or the right edge\n\t\t\t\tscale.y = Math.abs(scale.x)\n\t\t\t} else if (isXLocked) {\n\t\t\t\t// holding shift and dragging either the top or the bottom edge\n\t\t\t\tscale.x = Math.abs(scale.y)\n\t\t\t} else if (Math.abs(scale.x) > Math.abs(scale.y)) {\n\t\t\t\t// holding shift and the drag has moved further in the x dimension\n\t\t\t\tscale.y = Math.abs(scale.x) * (scale.y < 0 ? -1 : 1)\n\t\t\t} else {\n\t\t\t\t// holding shift and the drag has moved further in the y dimension\n\t\t\t\tscale.x = Math.abs(scale.y) * (scale.x < 0 ? -1 : 1)\n\t\t\t}\n\t\t} else {\n\t\t\t// not holding shift, but still need to lock axes if dragging an edge\n\t\t\tif (isXLocked) {\n\t\t\t\tscale.x = 1\n\t\t\t}\n\t\t\tif (isYLocked) {\n\t\t\t\tscale.y = 1\n\t\t\t}\n\t\t}\n\n\t\tif (!this.info.isCreating) {\n\t\t\tthis.updateCursor({\n\t\t\t\tdragHandle,\n\t\t\t\tisFlippedX: scale.x < 0,\n\t\t\t\tisFlippedY: scale.y < 0,\n\t\t\t\trotation: selectionRotation,\n\t\t\t})\n\t\t}\n\n\t\tfor (const id of shapeSnapshots.keys()) {\n\t\t\tconst snapshot = shapeSnapshots.get(id)!\n\n\t\t\tthis.editor.resizeShape(id, scale, {\n\t\t\t\tinitialShape: snapshot.shape,\n\t\t\t\tinitialBounds: snapshot.bounds,\n\t\t\t\tinitialPageTransform: snapshot.pageTransform,\n\t\t\t\tdragHandle,\n\t\t\t\tmode:\n\t\t\t\t\tselectedShapeIds.length === 1 && id === selectedShapeIds[0]\n\t\t\t\t\t\t? 'resize_bounds'\n\t\t\t\t\t\t: 'scale_shape',\n\t\t\t\tscaleOrigin: scaleOriginPage,\n\t\t\t\tisAspectRatioLocked,\n\t\t\t\tscaleAxisRotation: selectionRotation,\n\t\t\t\tskipStartAndEndCallbacks: true,\n\t\t\t})\n\t\t}\n\n\t\t// If there's only one shape snapshot and it's a frame and the user is holding ctrl,\n\t\t// then we preserve the position of the frame's children, almost like the user is cropping\n\t\t// the frame rather than resizing it.\n\t\tif (isHoldingAccel) {\n\t\t\tthis.didHoldCommand = true\n\n\t\t\tfor (const { id, children } of frames) {\n\t\t\t\tif (!children.length) continue\n\t\t\t\tconst initial = shapeSnapshots.get(id)!.shape\n\t\t\t\tconst current = this.editor.getShape(id)!\n\t\t\t\tif (!(initial && current)) continue\n\n\t\t\t\tconst dx = current.x - initial.x\n\t\t\t\tconst dy = current.y - initial.y\n\n\t\t\t\tconst delta = new Vec(dx, dy).rot(-initial.rotation)\n\n\t\t\t\tif (delta.x !== 0 || delta.y !== 0) {\n\t\t\t\t\tfor (const child of children) {\n\t\t\t\t\t\tthis.editor.updateShape({\n\t\t\t\t\t\t\tid: child.id,\n\t\t\t\t\t\t\ttype: child.type,\n\t\t\t\t\t\t\tx: child.x - delta.x,\n\t\t\t\t\t\t\ty: child.y - delta.y,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.didHoldCommand) {\n\t\t\t// If we're no longer holding the command key...\n\t\t\tthis.didHoldCommand = false\n\n\t\t\tfor (const { children } of frames) {\n\t\t\t\tif (!children.length) continue\n\t\t\t\tfor (const child of children) {\n\t\t\t\t\tthis.editor.updateShape({\n\t\t\t\t\t\tid: child.id,\n\t\t\t\t\t\ttype: child.type,\n\t\t\t\t\t\tx: child.x,\n\t\t\t\t\t\ty: child.y,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// ---\n\n\tprivate updateCursor({\n\t\tdragHandle,\n\t\tisFlippedX,\n\t\tisFlippedY,\n\t\trotation,\n\t}: {\n\t\tdragHandle: SelectionCorner | SelectionEdge\n\t\tisFlippedX: boolean\n\t\tisFlippedY: boolean\n\t\trotation: number\n\t}) {\n\t\tconst nextCursor = { ...this.editor.getInstanceState().cursor }\n\n\t\tswitch (dragHandle) {\n\t\t\tcase 'top_left':\n\t\t\tcase 'bottom_right': {\n\t\t\t\tnextCursor.type = 'nwse-resize'\n\t\t\t\tif (isFlippedX !== isFlippedY) {\n\t\t\t\t\tnextCursor.type = 'nesw-resize'\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'top_right':\n\t\t\tcase 'bottom_left': {\n\t\t\t\tnextCursor.type = 'nesw-resize'\n\t\t\t\tif (isFlippedX !== isFlippedY) {\n\t\t\t\t\tnextCursor.type = 'nwse-resize'\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tnextCursor.rotation = rotation\n\n\t\tthis.editor.setCursor(nextCursor)\n\t}\n\n\toverride onExit() {\n\t\tthis.parent.setCurrentToolIdMask(undefined)\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t\tthis.editor.snaps.clearIndicators()\n\t}\n\n\tprivate _createSnapshot() {\n\t\tconst { editor } = this\n\t\tconst selectedShapeIds = editor.getSelectedShapeIds()\n\t\tconst selectionRotation = editor.getSelectionRotation()\n\t\tconst {\n\t\t\tinputs: { originPagePoint },\n\t\t} = editor\n\n\t\tconst selectionBounds = editor.getSelectionRotatedPageBounds()\n\t\tif (!selectionBounds) throw Error('Resizing but nothing is selected')\n\n\t\tconst dragHandlePoint = Vec.RotWith(\n\t\t\tselectionBounds.getHandlePoint(this.info.handle!),\n\t\t\tselectionBounds.point,\n\t\t\tselectionRotation\n\t\t)\n\n\t\tconst cursorHandleOffset = Vec.Sub(originPagePoint, dragHandlePoint)\n\n\t\tconst shapeSnapshots = new Map<\n\t\t\tTLShapeId,\n\t\t\t{\n\t\t\t\tshape: TLShape\n\t\t\t\tbounds: Box\n\t\t\t\tpageTransform: Mat\n\t\t\t\tpageRotation: number\n\t\t\t\tisAspectRatioLocked: boolean\n\t\t\t}\n\t\t>()\n\n\t\tconst frames: { id: TLShapeId; children: TLShape[] }[] = []\n\n\t\tconst populateResizingShapes = (shapeId: TLShapeId): false | undefined => {\n\t\t\tconst shape = editor.getShape(shapeId)\n\t\t\tif (!shape) return false\n\n\t\t\tconst util = editor.getShapeUtil(shape)\n\n\t\t\t// If the shape can resize, add it to the resizing shapes snapshots\n\t\t\tif (util.canResize(shape)) {\n\t\t\t\tconst pageTransform = editor.getShapePageTransform(shape)!\n\t\t\t\tshapeSnapshots.set(shape.id, {\n\t\t\t\t\tshape,\n\t\t\t\t\tbounds: editor.getShapeGeometry(shape).bounds,\n\t\t\t\t\tpageTransform,\n\t\t\t\t\tpageRotation: Mat.Decompose(pageTransform).rotation,\n\t\t\t\t\tisAspectRatioLocked: util.isAspectRatioLocked(shape),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// Special case:\n\t\t\t// For frames, we don't want to resize children but we DO want to get a snapshot of their children so that we can restore their\n\t\t\t// positions with the accel key behavior. We could break this further into APIs, for example by collecting snapshots of all\n\t\t\t// descendants (easy) but also flagging with behavior like \"resize\" or \"keep absolute position\" or \"reposition only with accel key\",\n\t\t\t// though I'm not sure where that would be defined; perhaps better handled with onResizeStart / onResize callbacks on the util, and\n\t\t\t// pass `accelKeyIsPressed` as well as `accelKeyWasPressed`?\n\t\t\tif (editor.isShapeOfType<TLFrameShape>(shape, 'frame')) {\n\t\t\t\tframes.push({\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\tchildren: compact(\n\t\t\t\t\t\teditor.getSortedChildIdsForParent(shape).map((id) => editor.getShape(id))\n\t\t\t\t\t),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// This will stop the traversal of descendants\n\t\t\tif (!util.canResizeChildren(shape)) return false\n\t\t}\n\n\t\tselectedShapeIds.forEach((shapeId) => {\n\t\t\tconst keepDescending = populateResizingShapes(shapeId)\n\t\t\tif (keepDescending === false) return\n\t\t\teditor.visitDescendants(shapeId, populateResizingShapes)\n\t\t})\n\n\t\tconst canShapesDeform = ![...shapeSnapshots.values()].some(\n\t\t\t(shape) =>\n\t\t\t\t!areAnglesCompatible(shape.pageRotation, selectionRotation) || shape.isAspectRatioLocked\n\t\t)\n\n\t\treturn {\n\t\t\tshapeSnapshots,\n\t\t\tselectionBounds,\n\t\t\tcursorHandleOffset,\n\t\t\tselectionRotation,\n\t\t\tselectedShapeIds,\n\t\t\tcanShapesDeform,\n\t\t\tinitialSelectionPageBounds: this.editor.getSelectionPageBounds()!,\n\t\t\tframes,\n\t\t}\n\t}\n}\n\ntype Snapshot = ReturnType<Resizing['_createSnapshot']>\n\nconst ORDERED_SELECTION_HANDLES: (SelectionEdge | SelectionCorner)[] = [\n\t'top',\n\t'top_right',\n\t'right',\n\t'bottom_right',\n\t'bottom',\n\t'bottom_left',\n\t'left',\n\t'top_left',\n]\n\nexport function rotateSelectionHandle(handle: SelectionEdge | SelectionCorner, rotation: number) {\n\t// first find out how many tau we need to rotate by\n\trotation = rotation % PI2\n\tconst numSteps = Math.round(rotation / (PI / 4))\n\n\tconst currentIndex = ORDERED_SELECTION_HANDLES.indexOf(handle)\n\treturn ORDERED_SELECTION_HANDLES[(currentIndex + numSteps) % ORDERED_SELECTION_HANDLES.length]\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tBox,\n\tHALF_PI,\n\tMat,\n\tPI,\n\tPI2,\n\tSelectionCorner,\n\tSelectionEdge,\n\tStateNode,\n\tTLFrameShape,\n\tTLPointerEventInfo,\n\tTLShape,\n\tTLShapeId,\n\tTLShapePartial,\n\tTLTextShape,\n\tTLTickEventInfo,\n\tVec,\n\tVecLike,\n\tareAnglesCompatible,\n\tcompact,\n\tisAccelKey,\n\tkickoutOccludedShapes,\n} from '@tldraw/editor'\n\nexport type ResizingInfo = TLPointerEventInfo & {\n\ttarget: 'selection'\n\thandle: SelectionEdge | SelectionCorner\n\tisCreating?: boolean\n\tcreatingMarkId?: string\n\tonCreate?(shape: TLShape | null): void\n\tcreationCursorOffset?: VecLike\n\tonInteractionEnd?: string | (() => void)\n}\n\nexport class Resizing extends StateNode {\n\tstatic override id = 'resizing'\n\n\tinfo = {} as ResizingInfo\n\n\tmarkId = ''\n\n\t// A switch to detect when the user is holding ctrl\n\tprivate didHoldCommand = false\n\n\t// we transition into the resizing state from the geo pointing state, which starts with a shape of size w: 1, h: 1,\n\t// so if the user drags x: +50, y: +50 after mouseDown, the shape will be w: 51, h: 51, which is too many pixels, alas\n\t// so we allow passing a further offset into this state to negate such issues\n\tcreationCursorOffset = { x: 0, y: 0 } as VecLike\n\n\tprivate snapshot = {} as any as Snapshot\n\n\toverride onEnter(info: ResizingInfo) {\n\t\tconst { isCreating = false, creatingMarkId, creationCursorOffset = { x: 0, y: 0 } } = info\n\n\t\tthis.info = info\n\t\tthis.didHoldCommand = false\n\n\t\tif (typeof info.onInteractionEnd === 'string') {\n\t\t\tthis.parent.setCurrentToolIdMask(info.onInteractionEnd)\n\t\t}\n\t\tthis.creationCursorOffset = creationCursorOffset\n\n\t\ttry {\n\t\t\t// On rare and mysterious occasions, the user can enter the resizing state with no shapes selected\n\t\t\tthis.snapshot = this._createSnapshot()\n\t\t} catch (e) {\n\t\t\tconsole.error(e)\n\t\t\tthis.cancel()\n\t\t\treturn\n\t\t}\n\n\t\tthis.markId = ''\n\n\t\tif (isCreating) {\n\t\t\tif (creatingMarkId) {\n\t\t\t\tthis.markId = creatingMarkId\n\t\t\t} else {\n\t\t\t\t// handle legacy implicit `creating:{shapeId}` marks\n\t\t\t\tconst markId = this.editor.getMarkIdMatching(\n\t\t\t\t\t`creating:${this.editor.getOnlySelectedShapeId()}`\n\t\t\t\t)\n\t\t\t\tif (markId) {\n\t\t\t\t\tthis.markId = markId\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.markId = this.editor.markHistoryStoppingPoint('starting resizing')\n\t\t}\n\n\t\tif (isCreating) {\n\t\t\tthis.editor.setCursor({ type: 'cross', rotation: 0 })\n\t\t}\n\n\t\tthis.handleResizeStart()\n\t\tthis.updateShapes()\n\t}\n\n\toverride onTick({ elapsed }: TLTickEventInfo) {\n\t\tconst { editor } = this\n\t\teditor.edgeScrollManager.updateEdgeScrolling(elapsed)\n\t}\n\n\toverride onPointerMove() {\n\t\tthis.updateShapes()\n\t}\n\n\toverride onKeyDown() {\n\t\tthis.updateShapes()\n\t}\n\toverride onKeyUp() {\n\t\tthis.updateShapes()\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\tprivate cancel() {\n\t\t// Call onResizeCancel callback before resetting\n\t\tconst { shapeSnapshots } = this.snapshot\n\n\t\tshapeSnapshots.forEach(({ shape }) => {\n\t\t\tconst current = this.editor.getShape(shape.id)\n\t\t\tif (current) {\n\t\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\t\tutil.onResizeCancel?.(shape, current)\n\t\t\t}\n\t\t})\n\n\t\tthis.editor.bailToMark(this.markId)\n\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd, {})\n\t\t\t} else {\n\t\t\t\tonInteractionEnd()\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tthis.parent.transition('idle')\n\t}\n\n\tprivate complete() {\n\t\tkickoutOccludedShapes(this.editor, this.snapshot.selectedShapeIds)\n\n\t\tthis.handleResizeEnd()\n\n\t\tif (this.info.isCreating && this.info.onCreate) {\n\t\t\tthis.info.onCreate?.(this.editor.getOnlySelectedShape())\n\t\t\treturn\n\t\t}\n\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\tif (typeof onInteractionEnd === 'string') {\n\t\t\t\tif (this.editor.getInstanceState().isToolLocked) {\n\t\t\t\t\tthis.editor.setCurrentTool(onInteractionEnd, {})\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tonInteractionEnd()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tprivate handleResizeStart() {\n\t\tconst { shapeSnapshots } = this.snapshot\n\n\t\tconst changes: TLShapePartial[] = []\n\n\t\tshapeSnapshots.forEach(({ shape }) => {\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst change = util.onResizeStart?.(shape)\n\t\t\tif (change) {\n\t\t\t\tchanges.push(change)\n\t\t\t}\n\t\t})\n\n\t\tif (changes.length > 0) {\n\t\t\tthis.editor.updateShapes(changes)\n\t\t}\n\t}\n\n\tprivate handleResizeEnd() {\n\t\tconst { shapeSnapshots } = this.snapshot\n\n\t\tconst changes: TLShapePartial[] = []\n\n\t\tshapeSnapshots.forEach(({ shape }) => {\n\t\t\tconst current = this.editor.getShape(shape.id)!\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst change = util.onResizeEnd?.(shape, current)\n\t\t\tif (change) {\n\t\t\t\tchanges.push(change)\n\t\t\t}\n\t\t})\n\n\t\tif (changes.length > 0) {\n\t\t\tthis.editor.updateShapes(changes)\n\t\t}\n\t}\n\n\tprivate updateShapes() {\n\t\tconst { altKey, shiftKey } = this.editor.inputs\n\t\tconst {\n\t\t\tframes,\n\t\t\tshapeSnapshots,\n\t\t\tselectionBounds,\n\t\t\tcursorHandleOffset,\n\t\t\tselectedShapeIds,\n\t\t\tselectionRotation,\n\t\t\tcanShapesDeform,\n\t\t} = this.snapshot\n\n\t\tlet isAspectRatioLocked = shiftKey || !canShapesDeform\n\n\t\tif (shapeSnapshots.size === 1) {\n\t\t\tconst onlySnapshot = [...shapeSnapshots.values()][0]!\n\t\t\tif (this.editor.isShapeOfType<TLTextShape>(onlySnapshot.shape, 'text')) {\n\t\t\t\tisAspectRatioLocked = !(this.info.handle === 'left' || this.info.handle === 'right')\n\t\t\t}\n\t\t}\n\n\t\t// first negate the 'cursor handle offset'\n\t\t// we need to do this because we do grid snapping based on the page point of the handle\n\t\t// rather than the page point of the cursor, so it's easier to pretend that the cursor\n\t\t// is really where the handle actually is\n\t\t//\n\t\t// *** Massively zoomed-in diagram of the initial mouseDown ***\n\t\t//\n\t\t//\n\t\t// \u2502\n\t\t// \u2502\n\t\t// \u2502\n\t\t// \u2502\n\t\t// \u2502\n\t\t// \u2502\n\t\t// \u2502\n\t\t// \u2502corner handle\n\t\t// \u250C\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2510\n\t\t// selection \u2502 \u2502\n\t\t// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524 x\u25C4\u2500\u2500\u253C\u2500\u2500\u2500\u2500 drag handle point \u25B2\n\t\t// \u2502 \u2502 \u2502\n\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u251C\u2500 cursorHandleOffset.y\n\t\t// \u2502\n\t\t// originPagePoint\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25BAx\u2500\u2510 \u25BC\n\t\t// \u2502 \u2514\u2500\u2510\n\t\t// \u2502 \u2514\u2500\u2510\n\t\t// \u2502 \u2502 mouse (sorry)\n\t\t// \u2514\u2500\u2500\u2510 \u250C\u2518\n\t\t// \u2502 \u2502\n\t\t// \u2514\u2500\u2518\n\t\t// \u25C4\u2500\u2500\u252C\u2500\u2500\u25BA\n\t\t// \u2502\n\t\t// cursorHandleOffset.x\n\n\t\tconst isHoldingAccel = isAccelKey(this.editor.inputs)\n\n\t\tconst currentPagePoint = this.editor.inputs.currentPagePoint\n\t\t\t.clone()\n\t\t\t.sub(cursorHandleOffset)\n\t\t\t.sub(this.creationCursorOffset)\n\n\t\tconst originPagePoint = this.editor.inputs.originPagePoint.clone().sub(cursorHandleOffset)\n\n\t\tif (this.editor.getInstanceState().isGridMode && !isHoldingAccel) {\n\t\t\tconst { gridSize } = this.editor.getDocumentSettings()\n\t\t\tcurrentPagePoint.snapToGrid(gridSize)\n\t\t}\n\n\t\tconst dragHandle = this.info.handle as SelectionCorner | SelectionEdge\n\t\tconst scaleOriginHandle = rotateSelectionHandle(dragHandle, Math.PI)\n\n\t\tthis.editor.snaps.clearIndicators()\n\n\t\tconst shouldSnap = this.editor.user.getIsSnapMode() ? !isHoldingAccel : isHoldingAccel\n\n\t\tif (shouldSnap && selectionRotation % HALF_PI === 0) {\n\t\t\tconst { nudge } = this.editor.snaps.shapeBounds.snapResizeShapes({\n\t\t\t\tdragDelta: Vec.Sub(currentPagePoint, originPagePoint),\n\t\t\t\tinitialSelectionPageBounds: this.snapshot.initialSelectionPageBounds,\n\t\t\t\thandle: rotateSelectionHandle(dragHandle, selectionRotation),\n\t\t\t\tisAspectRatioLocked,\n\t\t\t\tisResizingFromCenter: altKey,\n\t\t\t})\n\n\t\t\tcurrentPagePoint.add(nudge)\n\t\t}\n\n\t\t// get the page point of the selection handle opposite to the drag handle\n\t\t// or the center of the selection box if altKey is pressed\n\t\tconst scaleOriginPage = Vec.RotWith(\n\t\t\taltKey ? selectionBounds.center : selectionBounds.getHandlePoint(scaleOriginHandle),\n\t\t\tselectionBounds.point,\n\t\t\tselectionRotation\n\t\t)\n\n\t\t// calculate the scale by measuring the current distance between the drag handle and the scale origin\n\t\t// and dividing by the original distance between the drag handle and the scale origin\n\n\t\t// bug: for edges, the page point doesn't matter, the\n\n\t\tconst distanceFromScaleOriginNow = Vec.Sub(currentPagePoint, scaleOriginPage).rot(\n\t\t\t-selectionRotation\n\t\t)\n\n\t\tconst distanceFromScaleOriginAtStart = Vec.Sub(originPagePoint, scaleOriginPage).rot(\n\t\t\t-selectionRotation\n\t\t)\n\n\t\tconst scale = Vec.DivV(distanceFromScaleOriginNow, distanceFromScaleOriginAtStart)\n\n\t\tif (!Number.isFinite(scale.x)) scale.x = 1\n\t\tif (!Number.isFinite(scale.y)) scale.y = 1\n\n\t\tconst isXLocked = dragHandle === 'top' || dragHandle === 'bottom'\n\t\tconst isYLocked = dragHandle === 'left' || dragHandle === 'right'\n\n\t\t// lock an axis if required\n\t\tif (isAspectRatioLocked) {\n\t\t\tif (isYLocked) {\n\t\t\t\t// holding shift and dragging either the left or the right edge\n\t\t\t\tscale.y = Math.abs(scale.x)\n\t\t\t} else if (isXLocked) {\n\t\t\t\t// holding shift and dragging either the top or the bottom edge\n\t\t\t\tscale.x = Math.abs(scale.y)\n\t\t\t} else if (Math.abs(scale.x) > Math.abs(scale.y)) {\n\t\t\t\t// holding shift and the drag has moved further in the x dimension\n\t\t\t\tscale.y = Math.abs(scale.x) * (scale.y < 0 ? -1 : 1)\n\t\t\t} else {\n\t\t\t\t// holding shift and the drag has moved further in the y dimension\n\t\t\t\tscale.x = Math.abs(scale.y) * (scale.x < 0 ? -1 : 1)\n\t\t\t}\n\t\t} else {\n\t\t\t// not holding shift, but still need to lock axes if dragging an edge\n\t\t\tif (isXLocked) {\n\t\t\t\tscale.x = 1\n\t\t\t}\n\t\t\tif (isYLocked) {\n\t\t\t\tscale.y = 1\n\t\t\t}\n\t\t}\n\n\t\tif (!this.info.isCreating) {\n\t\t\tthis.updateCursor({\n\t\t\t\tdragHandle,\n\t\t\t\tisFlippedX: scale.x < 0,\n\t\t\t\tisFlippedY: scale.y < 0,\n\t\t\t\trotation: selectionRotation,\n\t\t\t})\n\t\t}\n\n\t\tfor (const id of shapeSnapshots.keys()) {\n\t\t\tconst snapshot = shapeSnapshots.get(id)!\n\n\t\t\tthis.editor.resizeShape(id, scale, {\n\t\t\t\tinitialShape: snapshot.shape,\n\t\t\t\tinitialBounds: snapshot.bounds,\n\t\t\t\tinitialPageTransform: snapshot.pageTransform,\n\t\t\t\tdragHandle,\n\t\t\t\tmode:\n\t\t\t\t\tselectedShapeIds.length === 1 && id === selectedShapeIds[0]\n\t\t\t\t\t\t? 'resize_bounds'\n\t\t\t\t\t\t: 'scale_shape',\n\t\t\t\tscaleOrigin: scaleOriginPage,\n\t\t\t\tisAspectRatioLocked,\n\t\t\t\tscaleAxisRotation: selectionRotation,\n\t\t\t\tskipStartAndEndCallbacks: true,\n\t\t\t})\n\t\t}\n\n\t\t// If there's only one shape snapshot and it's a frame and the user is holding ctrl,\n\t\t// then we preserve the position of the frame's children, almost like the user is cropping\n\t\t// the frame rather than resizing it.\n\t\tif (isHoldingAccel) {\n\t\t\tthis.didHoldCommand = true\n\n\t\t\tfor (const { id, children } of frames) {\n\t\t\t\tif (!children.length) continue\n\t\t\t\tconst initial = shapeSnapshots.get(id)!.shape\n\t\t\t\tconst current = this.editor.getShape(id)!\n\t\t\t\tif (!(initial && current)) continue\n\n\t\t\t\tconst dx = current.x - initial.x\n\t\t\t\tconst dy = current.y - initial.y\n\n\t\t\t\tconst delta = new Vec(dx, dy).rot(-initial.rotation)\n\n\t\t\t\tif (delta.x !== 0 || delta.y !== 0) {\n\t\t\t\t\tfor (const child of children) {\n\t\t\t\t\t\tthis.editor.updateShape({\n\t\t\t\t\t\t\tid: child.id,\n\t\t\t\t\t\t\ttype: child.type,\n\t\t\t\t\t\t\tx: child.x - delta.x,\n\t\t\t\t\t\t\ty: child.y - delta.y,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.didHoldCommand) {\n\t\t\t// If we're no longer holding the command key...\n\t\t\tthis.didHoldCommand = false\n\n\t\t\tfor (const { children } of frames) {\n\t\t\t\tif (!children.length) continue\n\t\t\t\tfor (const child of children) {\n\t\t\t\t\tthis.editor.updateShape({\n\t\t\t\t\t\tid: child.id,\n\t\t\t\t\t\ttype: child.type,\n\t\t\t\t\t\tx: child.x,\n\t\t\t\t\t\ty: child.y,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// ---\n\n\tprivate updateCursor({\n\t\tdragHandle,\n\t\tisFlippedX,\n\t\tisFlippedY,\n\t\trotation,\n\t}: {\n\t\tdragHandle: SelectionCorner | SelectionEdge\n\t\tisFlippedX: boolean\n\t\tisFlippedY: boolean\n\t\trotation: number\n\t}) {\n\t\tconst nextCursor = { ...this.editor.getInstanceState().cursor }\n\n\t\tswitch (dragHandle) {\n\t\t\tcase 'top_left':\n\t\t\tcase 'bottom_right': {\n\t\t\t\tnextCursor.type = 'nwse-resize'\n\t\t\t\tif (isFlippedX !== isFlippedY) {\n\t\t\t\t\tnextCursor.type = 'nesw-resize'\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'top_right':\n\t\t\tcase 'bottom_left': {\n\t\t\t\tnextCursor.type = 'nesw-resize'\n\t\t\t\tif (isFlippedX !== isFlippedY) {\n\t\t\t\t\tnextCursor.type = 'nwse-resize'\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tnextCursor.rotation = rotation\n\n\t\tthis.editor.setCursor(nextCursor)\n\t}\n\n\toverride onExit() {\n\t\tthis.parent.setCurrentToolIdMask(undefined)\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t\tthis.editor.snaps.clearIndicators()\n\t}\n\n\tprivate _createSnapshot() {\n\t\tconst { editor } = this\n\t\tconst selectedShapeIds = editor.getSelectedShapeIds()\n\t\tconst selectionRotation = editor.getSelectionRotation()\n\t\tconst {\n\t\t\tinputs: { originPagePoint },\n\t\t} = editor\n\n\t\tconst selectionBounds = editor.getSelectionRotatedPageBounds()\n\t\tif (!selectionBounds) throw Error('Resizing but nothing is selected')\n\n\t\tconst dragHandlePoint = Vec.RotWith(\n\t\t\tselectionBounds.getHandlePoint(this.info.handle!),\n\t\t\tselectionBounds.point,\n\t\t\tselectionRotation\n\t\t)\n\n\t\tconst cursorHandleOffset = Vec.Sub(originPagePoint, dragHandlePoint)\n\n\t\tconst shapeSnapshots = new Map<\n\t\t\tTLShapeId,\n\t\t\t{\n\t\t\t\tshape: TLShape\n\t\t\t\tbounds: Box\n\t\t\t\tpageTransform: Mat\n\t\t\t\tpageRotation: number\n\t\t\t\tisAspectRatioLocked: boolean\n\t\t\t}\n\t\t>()\n\n\t\tconst frames: { id: TLShapeId; children: TLShape[] }[] = []\n\n\t\tconst populateResizingShapes = (shapeId: TLShapeId): false | undefined => {\n\t\t\tconst shape = editor.getShape(shapeId)\n\t\t\tif (!shape) return false\n\n\t\t\tconst util = editor.getShapeUtil(shape)\n\n\t\t\t// If the shape can resize, add it to the resizing shapes snapshots\n\t\t\tif (util.canResize(shape)) {\n\t\t\t\tconst pageTransform = editor.getShapePageTransform(shape)!\n\t\t\t\tshapeSnapshots.set(shape.id, {\n\t\t\t\t\tshape,\n\t\t\t\t\tbounds: editor.getShapeGeometry(shape).bounds,\n\t\t\t\t\tpageTransform,\n\t\t\t\t\tpageRotation: Mat.Decompose(pageTransform).rotation,\n\t\t\t\t\tisAspectRatioLocked: util.isAspectRatioLocked(shape),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// Special case:\n\t\t\t// For frames, we don't want to resize children but we DO want to get a snapshot of their children so that we can restore their\n\t\t\t// positions with the accel key behavior. We could break this further into APIs, for example by collecting snapshots of all\n\t\t\t// descendants (easy) but also flagging with behavior like \"resize\" or \"keep absolute position\" or \"reposition only with accel key\",\n\t\t\t// though I'm not sure where that would be defined; perhaps better handled with onResizeStart / onResize callbacks on the util, and\n\t\t\t// pass `accelKeyIsPressed` as well as `accelKeyWasPressed`?\n\t\t\tif (editor.isShapeOfType<TLFrameShape>(shape, 'frame')) {\n\t\t\t\tframes.push({\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\tchildren: compact(\n\t\t\t\t\t\teditor.getSortedChildIdsForParent(shape).map((id) => editor.getShape(id))\n\t\t\t\t\t),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// This will stop the traversal of descendants\n\t\t\tif (!util.canResizeChildren(shape)) return false\n\t\t}\n\n\t\tselectedShapeIds.forEach((shapeId) => {\n\t\t\tconst keepDescending = populateResizingShapes(shapeId)\n\t\t\tif (keepDescending === false) return\n\t\t\teditor.visitDescendants(shapeId, populateResizingShapes)\n\t\t})\n\n\t\tconst canShapesDeform = ![...shapeSnapshots.values()].some(\n\t\t\t(shape) =>\n\t\t\t\t!areAnglesCompatible(shape.pageRotation, selectionRotation) || shape.isAspectRatioLocked\n\t\t)\n\n\t\treturn {\n\t\t\tshapeSnapshots,\n\t\t\tselectionBounds,\n\t\t\tcursorHandleOffset,\n\t\t\tselectionRotation,\n\t\t\tselectedShapeIds,\n\t\t\tcanShapesDeform,\n\t\t\tinitialSelectionPageBounds: this.editor.getSelectionPageBounds()!,\n\t\t\tframes,\n\t\t}\n\t}\n}\n\ntype Snapshot = ReturnType<Resizing['_createSnapshot']>\n\nconst ORDERED_SELECTION_HANDLES: (SelectionEdge | SelectionCorner)[] = [\n\t'top',\n\t'top_right',\n\t'right',\n\t'bottom_right',\n\t'bottom',\n\t'bottom_left',\n\t'left',\n\t'top_left',\n]\n\nexport function rotateSelectionHandle(handle: SelectionEdge | SelectionCorner, rotation: number) {\n\t// first find out how many tau we need to rotate by\n\trotation = rotation % PI2\n\tconst numSteps = Math.round(rotation / (PI / 4))\n\n\tconst currentIndex = ORDERED_SELECTION_HANDLES.indexOf(handle)\n\treturn ORDERED_SELECTION_HANDLES[(currentIndex + numSteps) % ORDERED_SELECTION_HANDLES.length]\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -16,7 +16,9 @@ class Rotating extends StateNode {
16
16
  markId = "";
17
17
  onEnter(info) {
18
18
  this.info = info;
19
- this.parent.setCurrentToolIdMask(info.onInteractionEnd);
19
+ if (typeof info.onInteractionEnd === "string") {
20
+ this.parent.setCurrentToolIdMask(info.onInteractionEnd);
21
+ }
20
22
  this.markId = this.editor.markHistoryStoppingPoint("rotate start");
21
23
  const snapshot = getRotationSnapshot({
22
24
  editor: this.editor,
@@ -87,11 +89,16 @@ class Rotating extends StateNode {
87
89
  }
88
90
  });
89
91
  this.editor.bailToMark(this.markId);
90
- if (this.info.onInteractionEnd) {
91
- this.editor.setCurrentTool(this.info.onInteractionEnd, this.info);
92
- } else {
93
- this.parent.transition("idle", this.info);
92
+ const { onInteractionEnd } = this.info;
93
+ if (onInteractionEnd) {
94
+ if (typeof onInteractionEnd === "string") {
95
+ this.editor.setCurrentTool(onInteractionEnd, this.info);
96
+ } else {
97
+ onInteractionEnd();
98
+ }
99
+ return;
94
100
  }
101
+ this.parent.transition("idle", this.info);
95
102
  }
96
103
  complete() {
97
104
  applyRotationToSnapshotShapes({
@@ -104,11 +111,16 @@ class Rotating extends StateNode {
104
111
  this.editor,
105
112
  this.snapshot.shapeSnapshots.map((s) => s.shape.id)
106
113
  );
107
- if (this.info.onInteractionEnd) {
108
- this.editor.setCurrentTool(this.info.onInteractionEnd, this.info);
109
- } else {
110
- this.parent.transition("idle", this.info);
114
+ const { onInteractionEnd } = this.info;
115
+ if (onInteractionEnd) {
116
+ if (typeof onInteractionEnd === "string") {
117
+ this.editor.setCurrentTool(onInteractionEnd, this.info);
118
+ } else {
119
+ onInteractionEnd();
120
+ }
121
+ return;
111
122
  }
123
+ this.parent.transition("idle", this.info);
112
124
  }
113
125
  _getRotationFromPointerPosition({ snapToNearestDegree }) {
114
126
  const {