tldraw 4.1.0-canary.9c36de6e611c → 4.1.0-canary.a152954244d2

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 (225) hide show
  1. package/dist-cjs/index.d.ts +46 -12
  2. package/dist-cjs/index.js +6 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/canvas/TldrawCropHandles.js +1 -1
  5. package/dist-cjs/lib/canvas/TldrawScribble.js +1 -1
  6. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js +1 -1
  7. package/dist-cjs/lib/defaultEmbedDefinitions.js +25 -30
  8. package/dist-cjs/lib/defaultEmbedDefinitions.js.map +2 -2
  9. package/dist-cjs/lib/defaultExternalContentHandlers.js +10 -33
  10. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  11. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +3 -0
  12. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  13. package/dist-cjs/lib/shapes/arrow/curved-arrow.js +8 -2
  14. package/dist-cjs/lib/shapes/arrow/curved-arrow.js.map +2 -2
  15. package/dist-cjs/lib/shapes/arrow/straight-arrow.js +4 -1
  16. package/dist-cjs/lib/shapes/arrow/straight-arrow.js.map +2 -2
  17. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +44 -102
  18. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  19. package/dist-cjs/lib/shapes/bookmark/bookmarks.js +138 -0
  20. package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +7 -0
  21. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +25 -3
  22. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
  23. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +1 -1
  24. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +1 -1
  25. package/dist-cjs/lib/shapes/line/LineShapeUtil.js +3 -0
  26. package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
  27. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +1 -1
  28. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -1
  29. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +2 -2
  30. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
  31. package/dist-cjs/lib/shapes/shared/ShapeFill.js +1 -1
  32. package/dist-cjs/lib/shapes/text/PlainTextArea.js +1 -1
  33. package/dist-cjs/lib/shapes/text/RichTextArea.js +1 -1
  34. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +1 -1
  35. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js +20 -4
  36. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js.map +2 -2
  37. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js +1 -1
  38. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
  39. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js +23 -11
  40. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js.map +2 -2
  41. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +27 -6
  42. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  43. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +1 -1
  44. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
  45. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js +21 -9
  46. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
  47. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js +24 -8
  48. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js.map +2 -2
  49. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js +21 -9
  50. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js.map +2 -2
  51. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +23 -8
  52. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  53. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js +21 -9
  54. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js.map +2 -2
  55. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +26 -11
  56. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  57. package/dist-cjs/lib/ui/TldrawUi.js +2 -2
  58. package/dist-cjs/lib/ui/components/DebugMenu/DefaultDebugMenuContent.js +3 -3
  59. package/dist-cjs/lib/ui/components/DebugMenu/DefaultDebugMenuContent.js.map +1 -1
  60. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialog.js +1 -1
  61. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +1 -1
  62. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
  63. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +1 -1
  64. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +5 -0
  65. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
  66. package/dist-cjs/lib/ui/components/OfflineIndicator/OfflineIndicator.js +1 -1
  67. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js +6 -2
  68. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js.map +2 -2
  69. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js +1 -1
  70. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +1 -1
  71. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +64 -56
  72. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  73. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js +54 -47
  74. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +3 -3
  75. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js +63 -56
  76. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +2 -2
  77. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js +13 -6
  78. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +2 -2
  79. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +1 -1
  80. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +1 -1
  81. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +1 -1
  82. package/dist-cjs/lib/ui/components/menu-items.js +2 -2
  83. package/dist-cjs/lib/ui/components/menu-items.js.map +1 -1
  84. package/dist-cjs/lib/ui/components/primitives/Button/TldrawUiButton.js +2 -2
  85. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -1
  86. package/dist-cjs/lib/ui/components/primitives/TldrawUiDialog.js +1 -1
  87. package/dist-cjs/lib/ui/components/primitives/TldrawUiDropdownMenu.js +1 -1
  88. package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js +1 -1
  89. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +2 -2
  90. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +2 -2
  91. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +1 -1
  92. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +2 -2
  93. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +1 -1
  94. package/dist-cjs/lib/ui/components/primitives/layout.js +1 -1
  95. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +1 -1
  96. package/dist-cjs/lib/ui/context/actions.js +44 -30
  97. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  98. package/dist-cjs/lib/ui/context/breakpoints.js +1 -1
  99. package/dist-cjs/lib/ui/context/events.js +1 -1
  100. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +1 -1
  101. package/dist-cjs/lib/ui/hooks/useEditorEvents.js +1 -1
  102. package/dist-cjs/lib/ui/hooks/useEditorEvents.js.map +1 -1
  103. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +1 -1
  104. package/dist-cjs/lib/ui/hooks/useLocalStorageState.js +1 -1
  105. package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
  106. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +4 -4
  107. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +1 -1
  108. package/dist-cjs/lib/ui/hooks/useTranslation/useTranslation.js +1 -1
  109. package/dist-cjs/lib/ui/version.js +3 -3
  110. package/dist-cjs/lib/ui/version.js.map +1 -1
  111. package/dist-cjs/lib/utils/text/richText.js +4 -4
  112. package/dist-esm/index.d.mts +46 -12
  113. package/dist-esm/index.mjs +12 -4
  114. package/dist-esm/index.mjs.map +2 -2
  115. package/dist-esm/lib/defaultEmbedDefinitions.mjs +25 -30
  116. package/dist-esm/lib/defaultEmbedDefinitions.mjs.map +2 -2
  117. package/dist-esm/lib/defaultExternalContentHandlers.mjs +10 -33
  118. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  119. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +3 -0
  120. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  121. package/dist-esm/lib/shapes/arrow/curved-arrow.mjs +8 -2
  122. package/dist-esm/lib/shapes/arrow/curved-arrow.mjs.map +2 -2
  123. package/dist-esm/lib/shapes/arrow/straight-arrow.mjs +4 -1
  124. package/dist-esm/lib/shapes/arrow/straight-arrow.mjs.map +2 -2
  125. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +46 -101
  126. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  127. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs +124 -0
  128. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +7 -0
  129. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +26 -3
  130. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
  131. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +3 -0
  132. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
  133. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +1 -1
  134. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  135. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs +20 -4
  136. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs.map +2 -2
  137. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs +1 -1
  138. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
  139. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs +23 -11
  140. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs.map +2 -2
  141. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +29 -7
  142. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  143. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +1 -1
  144. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
  145. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs +21 -9
  146. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
  147. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs +24 -8
  148. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs.map +2 -2
  149. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs +21 -9
  150. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs.map +2 -2
  151. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +23 -8
  152. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  153. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs +21 -9
  154. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs.map +2 -2
  155. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +26 -11
  156. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  157. package/dist-esm/lib/ui/components/DebugMenu/DefaultDebugMenuContent.mjs +2 -2
  158. package/dist-esm/lib/ui/components/DebugMenu/DefaultDebugMenuContent.mjs.map +1 -1
  159. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +1 -1
  160. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
  161. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +5 -0
  162. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
  163. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs +6 -2
  164. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs.map +2 -2
  165. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +68 -57
  166. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  167. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +54 -47
  168. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +3 -3
  169. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs +63 -56
  170. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +2 -2
  171. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs +12 -5
  172. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +2 -2
  173. package/dist-esm/lib/ui/components/menu-items.mjs +2 -2
  174. package/dist-esm/lib/ui/components/menu-items.mjs.map +1 -1
  175. package/dist-esm/lib/ui/context/actions.mjs +43 -29
  176. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  177. package/dist-esm/lib/ui/hooks/useEditorEvents.mjs +1 -1
  178. package/dist-esm/lib/ui/hooks/useEditorEvents.mjs.map +1 -1
  179. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +4 -4
  180. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +1 -1
  181. package/dist-esm/lib/ui/version.mjs +3 -3
  182. package/dist-esm/lib/ui/version.mjs.map +1 -1
  183. package/package.json +11 -11
  184. package/src/index.ts +4 -0
  185. package/src/lib/defaultEmbedDefinitions.ts +20 -24
  186. package/src/lib/defaultExternalContentHandlers.ts +12 -37
  187. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +211 -1
  188. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +3 -0
  189. package/src/lib/shapes/arrow/curved-arrow.ts +8 -2
  190. package/src/lib/shapes/arrow/straight-arrow.ts +5 -1
  191. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +51 -135
  192. package/src/lib/shapes/bookmark/bookmarks.ts +170 -0
  193. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +28 -2
  194. package/src/lib/shapes/line/LineShapeUtil.tsx +3 -0
  195. package/src/lib/shapes/shared/RichTextLabel.tsx +1 -1
  196. package/src/lib/shapes/text/TextShapeTool.test.ts +74 -0
  197. package/src/lib/tools/SelectTool/childStates/Crop/children/Cropping.ts +23 -6
  198. package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +1 -1
  199. package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.ts +24 -12
  200. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +34 -11
  201. package/src/lib/tools/SelectTool/childStates/Idle.ts +1 -1
  202. package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +23 -11
  203. package/src/lib/tools/SelectTool/childStates/PointingResizeHandle.ts +26 -9
  204. package/src/lib/tools/SelectTool/childStates/PointingRotateHandle.ts +23 -10
  205. package/src/lib/tools/SelectTool/childStates/Resizing.ts +24 -9
  206. package/src/lib/tools/SelectTool/childStates/Rotating.ts +27 -11
  207. package/src/lib/tools/SelectTool/childStates/Translating.ts +28 -12
  208. package/src/lib/ui/components/DebugMenu/DefaultDebugMenuContent.tsx +2 -2
  209. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +1 -1
  210. package/src/lib/ui/components/Minimap/MinimapManager.ts +6 -0
  211. package/src/lib/ui/components/SharePanel/PeopleMenu.tsx +6 -2
  212. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +60 -49
  213. package/src/lib/ui/components/StylePanel/StylePanelButtonPicker.tsx +70 -53
  214. package/src/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.tsx +105 -90
  215. package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +72 -51
  216. package/src/lib/ui/components/menu-items.tsx +2 -2
  217. package/src/lib/ui/context/actions.tsx +49 -31
  218. package/src/lib/ui/hooks/useEditorEvents.ts +1 -1
  219. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +4 -4
  220. package/src/lib/ui/version.ts +3 -3
  221. package/src/lib/utils/embeds/embeds.test.ts +16 -34
  222. package/src/test/SelectTool.test.ts +251 -0
  223. package/src/test/bookmark-shapes.test.ts +129 -7
  224. package/src/test/customSnapping.test.tsx +55 -11
  225. package/tldraw.css +7 -2
@@ -3,6 +3,7 @@
3
3
  import {
4
4
  BaseBoxShapeUtil,
5
5
  HTMLContainer,
6
+ Rectangle2d,
6
7
  TLEmbedShape,
7
8
  TLEmbedShapeProps,
8
9
  TLResizeInfo,
@@ -24,6 +25,8 @@ import {
24
25
  embedShapePermissionDefaults,
25
26
  } from '../../defaultEmbedDefinitions'
26
27
  import { TLEmbedResult, getEmbedInfo } from '../../utils/embeds/embeds'
28
+ import { BookmarkIndicatorComponent, BookmarkShapeComponent } from '../bookmark/BookmarkShapeUtil'
29
+ import { BOOKMARK_JUST_URL_HEIGHT, BOOKMARK_WIDTH } from '../bookmark/bookmarks'
27
30
  import { getRotatedBoxShadow } from '../shared/rotated-box-shadow'
28
31
 
29
32
  const getSandboxPermissions = (permissions: TLEmbedShapePermissions) => {
@@ -82,6 +85,18 @@ export class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {
82
85
  }
83
86
  }
84
87
 
88
+ override getGeometry(shape: TLEmbedShape) {
89
+ const embedInfo = this.getEmbedDefinition(shape.props.url)
90
+ if (!embedInfo?.definition) {
91
+ return new Rectangle2d({
92
+ width: BOOKMARK_WIDTH,
93
+ height: BOOKMARK_JUST_URL_HEIGHT,
94
+ isFilled: true,
95
+ })
96
+ }
97
+ return super.getGeometry(shape)
98
+ }
99
+
85
100
  override isAspectRatioLocked(shape: TLEmbedShape) {
86
101
  const embedInfo = this.getEmbedDefinition(shape.props.url)
87
102
  return embedInfo?.definition.isAspectRatioLocked ?? false
@@ -206,20 +221,31 @@ export class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {
206
221
  background: embedInfo?.definition.backgroundColor,
207
222
  }}
208
223
  />
209
- ) : null}
224
+ ) : (
225
+ <BookmarkShapeComponent
226
+ url={url}
227
+ h={h}
228
+ rotation={pageRotation}
229
+ assetId={null}
230
+ showImageContainer={false}
231
+ />
232
+ )}
210
233
  </HTMLContainer>
211
234
  )
212
235
  }
213
236
 
214
237
  override indicator(shape: TLEmbedShape) {
215
238
  const embedInfo = this.getEmbedDefinition(shape.props.url)
216
- return (
239
+
240
+ return embedInfo?.definition ? (
217
241
  <rect
218
242
  width={toDomPrecision(shape.props.w)}
219
243
  height={toDomPrecision(shape.props.h)}
220
244
  rx={embedInfo?.definition.overrideOutlineRadius ?? 8}
221
245
  ry={embedInfo?.definition.overrideOutlineRadius ?? 8}
222
246
  />
247
+ ) : (
248
+ <BookmarkIndicatorComponent w={BOOKMARK_WIDTH} h={BOOKMARK_JUST_URL_HEIGHT} />
223
249
  )
224
250
  }
225
251
  override getInterpolatedProps(
@@ -48,6 +48,9 @@ export class LineShapeUtil extends ShapeUtil<TLLineShape> {
48
48
  override hideSelectionBoundsBg() {
49
49
  return true
50
50
  }
51
+ override hideInMinimap() {
52
+ return true
53
+ }
51
54
 
52
55
  override getDefaultProps(): TLLineShape['props'] {
53
56
  const [start, end] = getIndices(2)
@@ -109,7 +109,7 @@ export const RichTextLabel = React.memo(function RichTextLabel({
109
109
  // We don't get the mouseup event later because we preventDefault
110
110
  // so we have to do it manually.
111
111
  const handlePointerUp = (e: TLEventInfo) => {
112
- if (e.name !== 'pointer_up') return
112
+ if (e.name !== 'pointer_up' || !link) return
113
113
 
114
114
  if (!isDragging.current) {
115
115
  window.open(link, '_blank', 'noopener, noreferrer')
@@ -86,6 +86,80 @@ describe('When in idle state', () => {
86
86
  editor.cancel()
87
87
  editor.expectToBeIn('select.idle')
88
88
  })
89
+
90
+ it('starts editing selected text shape on Enter key', () => {
91
+ // Create a text shape using the same method as other tests
92
+ expect(editor.getCurrentPageShapes().length).toBe(0)
93
+ editor.setCurrentTool('text')
94
+ editor.pointerDown(0, 0)
95
+ editor.pointerUp()
96
+ editor.expectToBeIn('select.editing_shape')
97
+
98
+ // Update the text shape with some content
99
+ editor.updateShapes<TLTextShape>([
100
+ {
101
+ ...editor.getCurrentPageShapes()[0]!,
102
+ type: 'text',
103
+ props: { richText: toRichText('Hello') },
104
+ },
105
+ ])
106
+
107
+ // Exit editing mode
108
+ editor.cancel()
109
+ editor.expectToBeIn('select.idle')
110
+
111
+ // Verify the text shape exists and is selected
112
+ expect(editor.getCurrentPageShapes().length).toBe(1)
113
+ const textShape = editor.getCurrentPageShapes()[0]
114
+ expect(textShape.type).toBe('text')
115
+ editor.setSelectedShapes([textShape])
116
+
117
+ // Switch to text tool and press Enter
118
+ editor.setCurrentTool('text')
119
+ editor.expectToBeIn('text.idle')
120
+ editor.keyDown('Enter')
121
+
122
+ // Should transition to editing the selected text shape
123
+ editor.expectToBeIn('select.editing_shape')
124
+ expect(editor.getEditingShapeId()).toBe(textShape.id)
125
+ })
126
+
127
+ it('starts editing selected text shape on numpad Enter key', () => {
128
+ // Create a text shape using the same method as other tests
129
+ expect(editor.getCurrentPageShapes().length).toBe(0)
130
+ editor.setCurrentTool('text')
131
+ editor.pointerDown(0, 0)
132
+ editor.pointerUp()
133
+ editor.expectToBeIn('select.editing_shape')
134
+
135
+ // Update the text shape with some content
136
+ editor.updateShapes<TLTextShape>([
137
+ {
138
+ ...editor.getCurrentPageShapes()[0]!,
139
+ type: 'text',
140
+ props: { richText: toRichText('Hello') },
141
+ },
142
+ ])
143
+
144
+ // Exit editing mode
145
+ editor.cancel()
146
+ editor.expectToBeIn('select.idle')
147
+
148
+ // Verify the text shape exists and is selected
149
+ expect(editor.getCurrentPageShapes().length).toBe(1)
150
+ const textShape = editor.getCurrentPageShapes()[0]
151
+ expect(textShape.type).toBe('text')
152
+ editor.setSelectedShapes([textShape])
153
+
154
+ // Switch to text tool and press numpad Enter
155
+ editor.setCurrentTool('text')
156
+ editor.expectToBeIn('text.idle')
157
+ editor.keyDown('Enter', { code: 'NumpadEnter' })
158
+
159
+ // Should transition to editing the selected text shape
160
+ editor.expectToBeIn('select.editing_shape')
161
+ expect(editor.getEditingShapeId()).toBe(textShape.id)
162
+ })
89
163
  })
90
164
 
91
165
  describe('When in the pointing state', () => {
@@ -17,7 +17,7 @@ export class Cropping extends StateNode {
17
17
  info = {} as TLPointerEventInfo & {
18
18
  target: 'selection'
19
19
  handle: SelectionHandle
20
- onInteractionEnd?: string
20
+ onInteractionEnd?: string | (() => void)
21
21
  }
22
22
 
23
23
  markId = ''
@@ -28,10 +28,13 @@ export class Cropping extends StateNode {
28
28
  info: TLPointerEventInfo & {
29
29
  target: 'selection'
30
30
  handle: SelectionHandle
31
- onInteractionEnd?: string
31
+ onInteractionEnd?: string | (() => void)
32
32
  }
33
33
  ) {
34
34
  this.info = info
35
+ if (typeof info.onInteractionEnd === 'string') {
36
+ this.parent.setCurrentToolIdMask(info.onInteractionEnd)
37
+ }
35
38
  this.markId = this.editor.markHistoryStoppingPoint('cropping')
36
39
  this.snapshot = this.createSnapshot()
37
40
  this.updateShapes()
@@ -61,6 +64,10 @@ export class Cropping extends StateNode {
61
64
  this.cancel()
62
65
  }
63
66
 
67
+ override onExit() {
68
+ this.parent.setCurrentToolIdMask(undefined)
69
+ }
70
+
64
71
  private updateCursor() {
65
72
  const selectedShape = this.editor.getSelectedShapes()[0]
66
73
  if (!selectedShape) return
@@ -108,8 +115,13 @@ export class Cropping extends StateNode {
108
115
  private complete() {
109
116
  this.updateShapes()
110
117
  kickoutOccludedShapes(this.editor, [this.snapshot.shape.id])
111
- if (this.info.onInteractionEnd) {
112
- this.editor.setCurrentTool(this.info.onInteractionEnd, this.info)
118
+ const { onInteractionEnd } = this.info
119
+ if (onInteractionEnd) {
120
+ if (typeof onInteractionEnd === 'string') {
121
+ this.editor.setCurrentTool(onInteractionEnd, this.info)
122
+ } else {
123
+ onInteractionEnd()
124
+ }
113
125
  } else {
114
126
  this.editor.setCroppingShape(null)
115
127
  this.editor.setCurrentTool('select.idle')
@@ -118,8 +130,13 @@ export class Cropping extends StateNode {
118
130
 
119
131
  private cancel() {
120
132
  this.editor.bailToMark(this.markId)
121
- if (this.info.onInteractionEnd) {
122
- this.editor.setCurrentTool(this.info.onInteractionEnd, this.info)
133
+ const { onInteractionEnd } = this.info
134
+ if (onInteractionEnd) {
135
+ if (typeof onInteractionEnd === 'string') {
136
+ this.editor.setCurrentTool(onInteractionEnd, this.info)
137
+ } else {
138
+ onInteractionEnd()
139
+ }
123
140
  } else {
124
141
  this.editor.setCroppingShape(null)
125
142
  this.editor.setCurrentTool('select.idle')
@@ -143,7 +143,7 @@ export class Idle extends StateNode {
143
143
  }
144
144
 
145
145
  override onKeyUp(info: TLKeyboardEventInfo) {
146
- switch (info.code) {
146
+ switch (info.key) {
147
147
  case 'Enter': {
148
148
  this.editor.setCroppingShape(null)
149
149
  this.editor.setCurrentTool('select.idle', {})
@@ -4,7 +4,7 @@ import { CursorTypeMap } from '../../PointingResizeHandle'
4
4
  type TLPointingCropHandleInfo = TLPointerEventInfo & {
5
5
  target: 'selection'
6
6
  } & {
7
- onInteractionEnd?: string
7
+ onInteractionEnd?: string | (() => void)
8
8
  }
9
9
 
10
10
  export class PointingCropHandle extends StateNode {
@@ -14,7 +14,9 @@ export class PointingCropHandle extends StateNode {
14
14
 
15
15
  override onEnter(info: TLPointingCropHandleInfo) {
16
16
  this.info = info
17
- this.parent.setCurrentToolIdMask(info.onInteractionEnd)
17
+ if (typeof info.onInteractionEnd === 'string') {
18
+ this.parent.setCurrentToolIdMask(info.onInteractionEnd)
19
+ }
18
20
  const selectedShape = this.editor.getSelectedShapes()[0]
19
21
  if (!selectedShape) return
20
22
 
@@ -47,12 +49,17 @@ export class PointingCropHandle extends StateNode {
47
49
  }
48
50
 
49
51
  override onPointerUp() {
50
- if (this.info.onInteractionEnd) {
51
- this.editor.setCurrentTool(this.info.onInteractionEnd, this.info)
52
- } else {
53
- this.editor.setCroppingShape(null)
54
- this.editor.setCurrentTool('select.idle')
52
+ const { onInteractionEnd } = this.info
53
+ if (onInteractionEnd) {
54
+ if (typeof onInteractionEnd === 'string') {
55
+ this.editor.setCurrentTool(onInteractionEnd, this.info)
56
+ } else {
57
+ onInteractionEnd()
58
+ }
59
+ return
55
60
  }
61
+ this.editor.setCroppingShape(null)
62
+ this.editor.setCurrentTool('select.idle')
56
63
  }
57
64
 
58
65
  override onCancel() {
@@ -68,11 +75,16 @@ export class PointingCropHandle extends StateNode {
68
75
  }
69
76
 
70
77
  private cancel() {
71
- if (this.info.onInteractionEnd) {
72
- this.editor.setCurrentTool(this.info.onInteractionEnd, this.info)
73
- } else {
74
- this.editor.setCroppingShape(null)
75
- this.editor.setCurrentTool('select.idle')
78
+ const { onInteractionEnd } = this.info
79
+ if (onInteractionEnd) {
80
+ if (typeof onInteractionEnd === 'string') {
81
+ this.editor.setCurrentTool(onInteractionEnd, this.info)
82
+ } else {
83
+ onInteractionEnd()
84
+ }
85
+ return
76
86
  }
87
+ this.editor.setCroppingShape(null)
88
+ this.editor.setCurrentTool('select.idle')
77
89
  }
78
90
  }
@@ -12,6 +12,7 @@ import {
12
12
  snapAngle,
13
13
  sortByIndex,
14
14
  structuredClone,
15
+ warnOnce,
15
16
  } from '@tldraw/editor'
16
17
  import { ArrowShapeUtil } from '../../../shapes/arrow/ArrowShapeUtil'
17
18
  import { clearArrowTargetState } from '../../../shapes/arrow/arrowTargetState'
@@ -20,7 +21,7 @@ import { getArrowBindings } from '../../../shapes/arrow/shared'
20
21
  export type DraggingHandleInfo = TLPointerEventInfo & {
21
22
  shape: TLArrowShape | TLLineShape
22
23
  target: 'handle'
23
- onInteractionEnd?: string
24
+ onInteractionEnd?: string | (() => void)
24
25
  isCreating?: boolean
25
26
  creatingMarkId?: string
26
27
  }
@@ -46,7 +47,9 @@ export class DraggingHandle extends StateNode {
46
47
  override onEnter(info: DraggingHandleInfo) {
47
48
  const { shape, isCreating, creatingMarkId, handle } = info
48
49
  this.info = info
49
- this.parent.setCurrentToolIdMask(info.onInteractionEnd)
50
+ if (typeof info.onInteractionEnd === 'string') {
51
+ this.parent.setCurrentToolIdMask(info.onInteractionEnd)
52
+ }
50
53
  this.shapeId = shape.id
51
54
  this.markId = ''
52
55
 
@@ -219,11 +222,17 @@ export class DraggingHandle extends StateNode {
219
222
  }
220
223
 
221
224
  const { onInteractionEnd } = this.info
222
- if (this.editor.getInstanceState().isToolLocked && onInteractionEnd) {
223
- // Return to the tool that was active before this one,
224
- // but only if tool lock is turned on!
225
- this.editor.setCurrentTool(onInteractionEnd, { shapeId: this.shapeId })
226
- return
225
+ if (onInteractionEnd) {
226
+ if (typeof onInteractionEnd === 'string') {
227
+ if (this.editor.getInstanceState().isToolLocked && onInteractionEnd) {
228
+ // Return to the tool that was active before this one but only if tool lock is turned on!
229
+ this.editor.setCurrentTool(onInteractionEnd, { shapeId: this.shapeId })
230
+ return
231
+ }
232
+ } else {
233
+ onInteractionEnd?.()
234
+ return
235
+ }
227
236
  }
228
237
 
229
238
  this.parent.transition('idle')
@@ -248,9 +257,12 @@ export class DraggingHandle extends StateNode {
248
257
 
249
258
  const { onInteractionEnd } = this.info
250
259
  if (onInteractionEnd) {
251
- // Return to the tool that was active before this one,
252
- // whether tool lock is turned on or not!
253
- this.editor.setCurrentTool(onInteractionEnd, { shapeId: this.shapeId })
260
+ if (typeof onInteractionEnd === 'string') {
261
+ // Return to the tool that was active before this one, whether tool lock is turned on or not!
262
+ this.editor.setCurrentTool(onInteractionEnd, { shapeId: this.shapeId })
263
+ } else {
264
+ onInteractionEnd?.()
265
+ }
254
266
  return
255
267
  }
256
268
 
@@ -294,7 +306,18 @@ export class DraggingHandle extends StateNode {
294
306
 
295
307
  let nextHandle = { ...initialHandle, x: point.x, y: point.y }
296
308
 
297
- if (initialHandle.canSnap && (isSnapMode ? !ctrlKey : ctrlKey)) {
309
+ let canSnap = false
310
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
311
+ if (initialHandle.canSnap && initialHandle.snapType) {
312
+ warnOnce(
313
+ 'canSnap is deprecated. Cannot use both canSnap and snapType together - snapping disabled. Please use only snapType.'
314
+ )
315
+ } else {
316
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
317
+ canSnap = initialHandle.canSnap || initialHandle.snapType !== undefined
318
+ }
319
+
320
+ if (canSnap && (isSnapMode ? !ctrlKey : ctrlKey)) {
298
321
  // We're snapping
299
322
  const pageTransform = editor.getShapePageTransform(shape.id)
300
323
  if (!pageTransform) throw Error('Expected a page transform')
@@ -516,7 +516,7 @@ export class Idle extends StateNode {
516
516
  }
517
517
 
518
518
  override onKeyUp(info: TLKeyboardEventInfo) {
519
- switch (info.code) {
519
+ switch (info.key) {
520
520
  case 'Enter': {
521
521
  // Because Enter onKeyDown can happen outside the canvas (but then focus the canvas potentially),
522
522
  // we need to check if the canvas was initially selecting something before continuing.
@@ -23,7 +23,7 @@ export class PointingArrowLabel extends StateNode {
23
23
 
24
24
  private info = {} as TLPointerEventInfo & {
25
25
  shape: TLArrowShape
26
- onInteractionEnd?: string
26
+ onInteractionEnd?: string | (() => void)
27
27
  isCreating: boolean
28
28
  }
29
29
 
@@ -34,12 +34,14 @@ export class PointingArrowLabel extends StateNode {
34
34
  override onEnter(
35
35
  info: TLPointerEventInfo & {
36
36
  shape: TLArrowShape
37
- onInteractionEnd?: string
37
+ onInteractionEnd?: string | (() => void)
38
38
  isCreating: boolean
39
39
  }
40
40
  ) {
41
41
  const { shape } = info
42
- this.parent.setCurrentToolIdMask(info.onInteractionEnd)
42
+ if (typeof info.onInteractionEnd === 'string') {
43
+ this.parent.setCurrentToolIdMask(info.onInteractionEnd)
44
+ }
43
45
  this.info = info
44
46
  this.shapeId = shape.id
45
47
  this.didDrag = false
@@ -155,20 +157,30 @@ export class PointingArrowLabel extends StateNode {
155
157
  }
156
158
 
157
159
  private complete() {
158
- if (this.info.onInteractionEnd) {
159
- this.editor.setCurrentTool(this.info.onInteractionEnd, {})
160
- } else {
161
- this.parent.transition('idle')
160
+ const { onInteractionEnd } = this.info
161
+ if (onInteractionEnd) {
162
+ if (typeof onInteractionEnd === 'string') {
163
+ this.editor.setCurrentTool(onInteractionEnd, {})
164
+ } else {
165
+ onInteractionEnd()
166
+ }
167
+ return
162
168
  }
169
+ this.parent.transition('idle')
163
170
  }
164
171
 
165
172
  private cancel() {
166
173
  this.editor.bailToMark(this.markId)
167
174
 
168
- if (this.info.onInteractionEnd) {
169
- this.editor.setCurrentTool(this.info.onInteractionEnd, {})
170
- } else {
171
- this.parent.transition('idle')
175
+ const { onInteractionEnd } = this.info
176
+ if (onInteractionEnd) {
177
+ if (typeof onInteractionEnd === 'string') {
178
+ this.editor.setCurrentTool(onInteractionEnd, {})
179
+ } else {
180
+ onInteractionEnd()
181
+ }
182
+ return
172
183
  }
184
+ this.parent.transition('idle')
173
185
  }
174
186
  }
@@ -17,7 +17,7 @@ export const CursorTypeMap: Record<TLSelectionHandle, TLCursorType> = {
17
17
  }
18
18
 
19
19
  type PointingResizeHandleInfo = Extract<TLPointerEventInfo, { target: 'selection' }> & {
20
- onInteractionEnd?: string
20
+ onInteractionEnd?: string | (() => void)
21
21
  }
22
22
 
23
23
  export class PointingResizeHandle extends StateNode {
@@ -36,9 +36,16 @@ export class PointingResizeHandle extends StateNode {
36
36
 
37
37
  override onEnter(info: PointingResizeHandleInfo) {
38
38
  this.info = info
39
+ if (typeof info.onInteractionEnd === 'string') {
40
+ this.parent.setCurrentToolIdMask(info.onInteractionEnd)
41
+ }
39
42
  this.updateCursor()
40
43
  }
41
44
 
45
+ override onExit() {
46
+ this.parent.setCurrentToolIdMask(undefined)
47
+ }
48
+
42
49
  override onPointerMove() {
43
50
  if (this.editor.inputs.isDragging) {
44
51
  this.startResizing()
@@ -71,18 +78,28 @@ export class PointingResizeHandle extends StateNode {
71
78
  }
72
79
 
73
80
  private complete() {
74
- if (this.info.onInteractionEnd) {
75
- this.editor.setCurrentTool(this.info.onInteractionEnd, {})
76
- } else {
77
- this.parent.transition('idle')
81
+ const { onInteractionEnd } = this.info
82
+ if (onInteractionEnd) {
83
+ if (typeof onInteractionEnd === 'string') {
84
+ this.editor.setCurrentTool(onInteractionEnd, {})
85
+ } else {
86
+ onInteractionEnd()
87
+ }
88
+ return
78
89
  }
90
+ this.parent.transition('idle')
79
91
  }
80
92
 
81
93
  private cancel() {
82
- if (this.info.onInteractionEnd) {
83
- this.editor.setCurrentTool(this.info.onInteractionEnd, {})
84
- } else {
85
- this.parent.transition('idle')
94
+ const { onInteractionEnd } = this.info
95
+ if (onInteractionEnd) {
96
+ if (typeof onInteractionEnd === 'string') {
97
+ this.editor.setCurrentTool(onInteractionEnd, {})
98
+ } else {
99
+ onInteractionEnd()
100
+ }
101
+ return
86
102
  }
103
+ this.parent.transition('idle')
87
104
  }
88
105
  }
@@ -2,7 +2,7 @@ import { RotateCorner, StateNode, TLPointerEventInfo } from '@tldraw/editor'
2
2
  import { CursorTypeMap } from './PointingResizeHandle'
3
3
 
4
4
  type PointingRotateHandleInfo = Extract<TLPointerEventInfo, { target: 'selection' }> & {
5
- onInteractionEnd?: string
5
+ onInteractionEnd?: string | (() => void)
6
6
  }
7
7
 
8
8
  export class PointingRotateHandle extends StateNode {
@@ -18,8 +18,10 @@ export class PointingRotateHandle extends StateNode {
18
18
  }
19
19
 
20
20
  override onEnter(info: PointingRotateHandleInfo) {
21
- this.parent.setCurrentToolIdMask(info.onInteractionEnd)
22
21
  this.info = info
22
+ if (typeof info.onInteractionEnd === 'string') {
23
+ this.parent.setCurrentToolIdMask(info.onInteractionEnd)
24
+ }
23
25
  this.updateCursor()
24
26
  }
25
27
 
@@ -60,18 +62,29 @@ export class PointingRotateHandle extends StateNode {
60
62
  }
61
63
 
62
64
  private complete() {
63
- if (this.info.onInteractionEnd) {
64
- this.editor.setCurrentTool(this.info.onInteractionEnd, {})
65
- } else {
66
- this.parent.transition('idle')
65
+ const { onInteractionEnd } = this.info
66
+ if (onInteractionEnd) {
67
+ if (typeof onInteractionEnd === 'string') {
68
+ // Return to the tool that was active before this one, whether tool lock is turned on or not!
69
+ this.editor.setCurrentTool(onInteractionEnd, {})
70
+ } else {
71
+ onInteractionEnd?.()
72
+ }
73
+ return
67
74
  }
75
+ this.parent.transition('idle')
68
76
  }
69
77
 
70
78
  private cancel() {
71
- if (this.info.onInteractionEnd) {
72
- this.editor.setCurrentTool(this.info.onInteractionEnd, {})
73
- } else {
74
- this.parent.transition('idle')
79
+ const { onInteractionEnd } = this.info
80
+ if (onInteractionEnd) {
81
+ if (typeof onInteractionEnd === 'string') {
82
+ this.editor.setCurrentTool(onInteractionEnd, {})
83
+ } else {
84
+ onInteractionEnd()
85
+ }
86
+ return
75
87
  }
88
+ this.parent.transition('idle')
76
89
  }
77
90
  }
@@ -29,7 +29,7 @@ export type ResizingInfo = TLPointerEventInfo & {
29
29
  creatingMarkId?: string
30
30
  onCreate?(shape: TLShape | null): void
31
31
  creationCursorOffset?: VecLike
32
- onInteractionEnd?: string
32
+ onInteractionEnd?: string | (() => void)
33
33
  }
34
34
 
35
35
  export class Resizing extends StateNode {
@@ -55,7 +55,9 @@ export class Resizing extends StateNode {
55
55
  this.info = info
56
56
  this.didHoldCommand = false
57
57
 
58
- this.parent.setCurrentToolIdMask(info.onInteractionEnd)
58
+ if (typeof info.onInteractionEnd === 'string') {
59
+ this.parent.setCurrentToolIdMask(info.onInteractionEnd)
60
+ }
59
61
  this.creationCursorOffset = creationCursorOffset
60
62
 
61
63
  try {
@@ -135,11 +137,16 @@ export class Resizing extends StateNode {
135
137
 
136
138
  this.editor.bailToMark(this.markId)
137
139
 
138
- if (this.info.onInteractionEnd) {
139
- this.editor.setCurrentTool(this.info.onInteractionEnd, {})
140
- } else {
141
- this.parent.transition('idle')
140
+ const { onInteractionEnd } = this.info
141
+ if (onInteractionEnd) {
142
+ if (typeof onInteractionEnd === 'string') {
143
+ this.editor.setCurrentTool(onInteractionEnd, {})
144
+ } else {
145
+ onInteractionEnd()
146
+ }
147
+ return
142
148
  }
149
+ this.parent.transition('idle')
143
150
  }
144
151
 
145
152
  private complete() {
@@ -152,9 +159,17 @@ export class Resizing extends StateNode {
152
159
  return
153
160
  }
154
161
 
155
- if (this.editor.getInstanceState().isToolLocked && this.info.onInteractionEnd) {
156
- this.editor.setCurrentTool(this.info.onInteractionEnd, {})
157
- return
162
+ const { onInteractionEnd } = this.info
163
+ if (onInteractionEnd) {
164
+ if (typeof onInteractionEnd === 'string') {
165
+ if (this.editor.getInstanceState().isToolLocked) {
166
+ this.editor.setCurrentTool(onInteractionEnd, {})
167
+ return
168
+ }
169
+ } else {
170
+ onInteractionEnd()
171
+ return
172
+ }
158
173
  }
159
174
 
160
175
  this.parent.transition('idle')