tldraw 4.3.0-next.f13438eb7775 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (636) hide show
  1. package/README.md +0 -2
  2. package/dist-cjs/index.d.ts +311 -242
  3. package/dist-cjs/index.js +13 -5
  4. package/dist-cjs/index.js.map +2 -2
  5. package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js.map +2 -2
  6. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js +2 -2
  7. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js.map +2 -2
  8. package/dist-cjs/lib/defaultEmbedDefinitions.js +1 -1
  9. package/dist-cjs/lib/defaultEmbedDefinitions.js.map +2 -2
  10. package/dist-cjs/lib/defaultExternalContentHandlers.js +5 -5
  11. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  12. package/dist-cjs/lib/defaultSideEffects.js +6 -1
  13. package/dist-cjs/lib/defaultSideEffects.js.map +2 -2
  14. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +14 -13
  15. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  16. package/dist-cjs/lib/shapes/arrow/arrow-types.js.map +1 -1
  17. package/dist-cjs/lib/shapes/arrow/arrowLabel.js +1 -1
  18. package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +2 -2
  19. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js +1 -1
  20. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
  21. package/dist-cjs/lib/shapes/arrow/elbow/elbowArrowSnapLines.js.map +2 -2
  22. package/dist-cjs/lib/shapes/arrow/elbow/getElbowArrowInfo.js +1 -1
  23. package/dist-cjs/lib/shapes/arrow/elbow/getElbowArrowInfo.js.map +2 -2
  24. package/dist-cjs/lib/shapes/arrow/shared.js.map +2 -2
  25. package/dist-cjs/lib/shapes/arrow/toolStates/Idle.js +4 -10
  26. package/dist-cjs/lib/shapes/arrow/toolStates/Idle.js.map +2 -2
  27. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +7 -4
  28. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  29. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +1 -1
  30. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  31. package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +2 -2
  32. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +25 -23
  33. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
  34. package/dist-cjs/lib/shapes/draw/getPath.js +20 -11
  35. package/dist-cjs/lib/shapes/draw/getPath.js.map +2 -2
  36. package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js +82 -86
  37. package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js.map +3 -3
  38. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +6 -0
  39. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
  40. package/dist-cjs/lib/shapes/frame/FrameShapeTool.js.map +1 -1
  41. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +6 -5
  42. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  43. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +146 -142
  44. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  45. package/dist-cjs/lib/shapes/geo/toolStates/Idle.js +5 -10
  46. package/dist-cjs/lib/shapes/geo/toolStates/Idle.js.map +2 -2
  47. package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js +3 -3
  48. package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js.map +2 -2
  49. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +23 -21
  50. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
  51. package/dist-cjs/lib/shapes/line/toolStates/Pointing.js +3 -3
  52. package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
  53. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +6 -11
  54. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  55. package/dist-cjs/lib/shapes/note/noteHelpers.js.map +2 -2
  56. package/dist-cjs/lib/shapes/note/toolStates/Pointing.js +5 -10
  57. package/dist-cjs/lib/shapes/note/toolStates/Pointing.js.map +2 -2
  58. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +3 -2
  59. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js.map +2 -2
  60. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +14 -2
  61. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +3 -3
  62. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +12 -4
  63. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +3 -3
  64. package/dist-cjs/lib/shapes/shared/ShapeFill.js +2 -2
  65. package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
  66. package/dist-cjs/lib/shapes/shared/crop.js +1 -0
  67. package/dist-cjs/lib/shapes/shared/crop.js.map +2 -2
  68. package/dist-cjs/lib/shapes/shared/interpolate-props.js +3 -3
  69. package/dist-cjs/lib/shapes/shared/interpolate-props.js.map +2 -2
  70. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  71. package/dist-cjs/lib/shapes/shared/useEditableRichText.js.map +2 -2
  72. package/dist-cjs/lib/shapes/shared/{useForceSolid.js → useEfficientZoomThreshold.js} +10 -7
  73. package/dist-cjs/lib/shapes/shared/useEfficientZoomThreshold.js.map +7 -0
  74. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +1 -1
  75. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
  76. package/dist-cjs/lib/shapes/text/RichTextArea.js +5 -0
  77. package/dist-cjs/lib/shapes/text/RichTextArea.js.map +2 -2
  78. package/dist-cjs/lib/shapes/text/TextShapeUtil.js +5 -2
  79. package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
  80. package/dist-cjs/lib/shapes/text/toolStates/Idle.js +4 -10
  81. package/dist-cjs/lib/shapes/text/toolStates/Idle.js.map +2 -2
  82. package/dist-cjs/lib/shapes/text/toolStates/Pointing.js +7 -5
  83. package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
  84. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +1 -1
  85. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +2 -2
  86. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +4 -5
  87. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  88. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +2 -4
  89. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  90. package/dist-cjs/lib/tools/HandTool/HandTool.js +3 -5
  91. package/dist-cjs/lib/tools/HandTool/HandTool.js.map +2 -2
  92. package/dist-cjs/lib/tools/HandTool/childStates/Dragging.js +3 -2
  93. package/dist-cjs/lib/tools/HandTool/childStates/Dragging.js.map +2 -2
  94. package/dist-cjs/lib/tools/HandTool/childStates/Pointing.js +1 -1
  95. package/dist-cjs/lib/tools/HandTool/childStates/Pointing.js.map +2 -2
  96. package/dist-cjs/lib/tools/LaserTool/childStates/Lasering.js +1 -1
  97. package/dist-cjs/lib/tools/LaserTool/childStates/Lasering.js.map +2 -2
  98. package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js +10 -11
  99. package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js.map +2 -2
  100. package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js +6 -5
  101. package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js.map +2 -2
  102. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js +4 -6
  103. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js.map +2 -2
  104. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js +1 -1
  105. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
  106. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.js +1 -1
  107. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.js.map +2 -2
  108. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js +1 -1
  109. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js.map +2 -2
  110. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.js +2 -1
  111. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.js.map +2 -2
  112. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.js +1 -1
  113. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.js.map +2 -2
  114. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +8 -6
  115. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  116. package/dist-cjs/lib/tools/SelectTool/childStates/EditingShape.js +38 -11
  117. package/dist-cjs/lib/tools/SelectTool/childStates/EditingShape.js.map +2 -2
  118. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +42 -50
  119. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
  120. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js +6 -6
  121. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
  122. package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js +1 -1
  123. package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js.map +2 -2
  124. package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js +4 -14
  125. package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js.map +2 -2
  126. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js +1 -1
  127. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js.map +2 -2
  128. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js +1 -1
  129. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js.map +2 -2
  130. package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js +2 -2
  131. package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js.map +2 -2
  132. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js +4 -13
  133. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js.map +2 -2
  134. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +5 -6
  135. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  136. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js +2 -3
  137. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js.map +2 -2
  138. package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js +7 -6
  139. package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js.map +2 -2
  140. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +13 -11
  141. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  142. package/dist-cjs/lib/tools/SelectTool/selectHelpers.js +15 -4
  143. package/dist-cjs/lib/tools/SelectTool/selectHelpers.js.map +2 -2
  144. package/dist-cjs/lib/tools/ZoomTool/ZoomTool.js +1 -1
  145. package/dist-cjs/lib/tools/ZoomTool/ZoomTool.js.map +2 -2
  146. package/dist-cjs/lib/tools/ZoomTool/childStates/Pointing.js +3 -3
  147. package/dist-cjs/lib/tools/ZoomTool/childStates/Pointing.js.map +2 -2
  148. package/dist-cjs/lib/tools/ZoomTool/childStates/ZoomBrushing.js +5 -6
  149. package/dist-cjs/lib/tools/ZoomTool/childStates/ZoomBrushing.js.map +2 -2
  150. package/dist-cjs/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.js +1 -3
  151. package/dist-cjs/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.js.map +2 -2
  152. package/dist-cjs/lib/tools/selection-logic/selectOnCanvasPointerUp.js +1 -1
  153. package/dist-cjs/lib/tools/selection-logic/selectOnCanvasPointerUp.js.map +2 -2
  154. package/dist-cjs/lib/tools/selection-logic/updateHoveredShapeId.js +1 -1
  155. package/dist-cjs/lib/tools/selection-logic/updateHoveredShapeId.js.map +2 -2
  156. package/dist-cjs/lib/ui/TldrawUi.js +2 -2
  157. package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
  158. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.js +3 -9
  159. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.js.map +2 -2
  160. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js +1 -3
  161. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js.map +2 -2
  162. package/dist-cjs/lib/ui/components/CursorChatBubble.js +1 -1
  163. package/dist-cjs/lib/ui/components/CursorChatBubble.js.map +2 -2
  164. package/dist-cjs/lib/ui/components/DefaultDebugPanel.js +1 -21
  165. package/dist-cjs/lib/ui/components/DefaultDebugPanel.js.map +2 -2
  166. package/dist-cjs/lib/ui/components/EditLinkDialog.js +11 -1
  167. package/dist-cjs/lib/ui/components/EditLinkDialog.js.map +2 -2
  168. package/dist-cjs/lib/ui/components/HelperButtons/BackToContent.js +1 -1
  169. package/dist-cjs/lib/ui/components/HelperButtons/BackToContent.js.map +2 -2
  170. package/dist-cjs/lib/ui/components/HelperButtons/StopFollowing.js.map +2 -2
  171. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +1 -1
  172. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
  173. package/dist-cjs/lib/ui/components/OfflineIndicator/OfflineIndicator.js +2 -15
  174. package/dist-cjs/lib/ui/components/OfflineIndicator/OfflineIndicator.js.map +3 -3
  175. package/dist-cjs/lib/ui/components/PageMenu/PageItemInput.js +3 -1
  176. package/dist-cjs/lib/ui/components/PageMenu/PageItemInput.js.map +2 -2
  177. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js +6 -0
  178. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js.map +2 -2
  179. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  180. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbar.js +1 -1
  181. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbar.js.map +2 -2
  182. package/dist-cjs/lib/ui/components/Toolbar/DefaultRichTextToolbar.js +1 -1
  183. package/dist-cjs/lib/ui/components/Toolbar/DefaultRichTextToolbar.js.map +2 -2
  184. package/dist-cjs/lib/ui/components/TopPanel/CenteredTopPanelContainer.js.map +1 -1
  185. package/dist-cjs/lib/ui/components/menu-items.js +3 -1
  186. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  187. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +3 -1
  188. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  189. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +1 -1
  190. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  191. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +149 -93
  192. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  193. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuActionCheckboxItem.js.map +2 -2
  194. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuActionItem.js.map +2 -2
  195. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +14 -7
  196. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  197. package/dist-cjs/lib/ui/context/actions.js +7 -8
  198. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  199. package/dist-cjs/lib/ui/context/components.js +1 -2
  200. package/dist-cjs/lib/ui/context/components.js.map +2 -2
  201. package/dist-cjs/lib/ui/hooks/menu-hooks.js.map +2 -2
  202. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +2 -2
  203. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
  204. package/dist-cjs/lib/ui/hooks/useFlatten.js.map +2 -2
  205. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +2 -2
  206. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js.map +2 -2
  207. package/dist-cjs/lib/ui/hooks/useTools.js +4 -5
  208. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  209. package/dist-cjs/lib/ui/version.js +3 -3
  210. package/dist-cjs/lib/ui/version.js.map +1 -1
  211. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js +16 -6
  212. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js.map +2 -2
  213. package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
  214. package/dist-cjs/lib/utils/frames/frames.js.map +2 -2
  215. package/dist-cjs/lib/{tools/selection-logic/getShouldEnterCropModeOnPointerDown.js → utils/test-helpers.js} +21 -8
  216. package/dist-cjs/lib/utils/test-helpers.js.map +7 -0
  217. package/dist-cjs/lib/utils/text/richText.js +15 -19
  218. package/dist-cjs/lib/utils/text/richText.js.map +3 -3
  219. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js +7 -2
  220. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js.map +2 -2
  221. package/dist-esm/index.d.mts +311 -242
  222. package/dist-esm/index.mjs +14 -5
  223. package/dist-esm/index.mjs.map +2 -2
  224. package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs.map +2 -2
  225. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs +2 -2
  226. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs.map +2 -2
  227. package/dist-esm/lib/defaultEmbedDefinitions.mjs +1 -1
  228. package/dist-esm/lib/defaultEmbedDefinitions.mjs.map +2 -2
  229. package/dist-esm/lib/defaultExternalContentHandlers.mjs +5 -5
  230. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  231. package/dist-esm/lib/defaultSideEffects.mjs +6 -1
  232. package/dist-esm/lib/defaultSideEffects.mjs.map +2 -2
  233. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +15 -15
  234. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  235. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +1 -1
  236. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +2 -2
  237. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs +1 -1
  238. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
  239. package/dist-esm/lib/shapes/arrow/elbow/elbowArrowSnapLines.mjs.map +2 -2
  240. package/dist-esm/lib/shapes/arrow/elbow/getElbowArrowInfo.mjs +1 -1
  241. package/dist-esm/lib/shapes/arrow/elbow/getElbowArrowInfo.mjs.map +2 -2
  242. package/dist-esm/lib/shapes/arrow/shared.mjs.map +2 -2
  243. package/dist-esm/lib/shapes/arrow/toolStates/Idle.mjs +4 -10
  244. package/dist-esm/lib/shapes/arrow/toolStates/Idle.mjs.map +2 -2
  245. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +7 -4
  246. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  247. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +1 -1
  248. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  249. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +2 -2
  250. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +30 -25
  251. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
  252. package/dist-esm/lib/shapes/draw/getPath.mjs +21 -11
  253. package/dist-esm/lib/shapes/draw/getPath.mjs.map +2 -2
  254. package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs +83 -86
  255. package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs.map +3 -3
  256. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +6 -0
  257. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
  258. package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs.map +1 -1
  259. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +6 -5
  260. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  261. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +147 -142
  262. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  263. package/dist-esm/lib/shapes/geo/toolStates/Idle.mjs +5 -10
  264. package/dist-esm/lib/shapes/geo/toolStates/Idle.mjs.map +2 -2
  265. package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs +3 -3
  266. package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
  267. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +24 -22
  268. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
  269. package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs +3 -3
  270. package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
  271. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +7 -12
  272. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  273. package/dist-esm/lib/shapes/note/noteHelpers.mjs.map +2 -2
  274. package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs +5 -10
  275. package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs.map +2 -2
  276. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs +4 -3
  277. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs.map +2 -2
  278. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +14 -2
  279. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  280. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +12 -4
  281. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  282. package/dist-esm/lib/shapes/shared/ShapeFill.mjs +2 -2
  283. package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
  284. package/dist-esm/lib/shapes/shared/crop.mjs +1 -0
  285. package/dist-esm/lib/shapes/shared/crop.mjs.map +2 -2
  286. package/dist-esm/lib/shapes/shared/interpolate-props.mjs +4 -4
  287. package/dist-esm/lib/shapes/shared/interpolate-props.mjs.map +2 -2
  288. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  289. package/dist-esm/lib/shapes/shared/useEditableRichText.mjs.map +2 -2
  290. package/dist-esm/lib/shapes/shared/useEfficientZoomThreshold.mjs +12 -0
  291. package/dist-esm/lib/shapes/shared/useEfficientZoomThreshold.mjs.map +7 -0
  292. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +1 -1
  293. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  294. package/dist-esm/lib/shapes/text/RichTextArea.mjs +5 -0
  295. package/dist-esm/lib/shapes/text/RichTextArea.mjs.map +2 -2
  296. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +5 -2
  297. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
  298. package/dist-esm/lib/shapes/text/toolStates/Idle.mjs +4 -10
  299. package/dist-esm/lib/shapes/text/toolStates/Idle.mjs.map +2 -2
  300. package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs +7 -5
  301. package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
  302. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +1 -1
  303. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +2 -2
  304. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +4 -5
  305. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  306. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +3 -8
  307. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  308. package/dist-esm/lib/tools/HandTool/HandTool.mjs +3 -5
  309. package/dist-esm/lib/tools/HandTool/HandTool.mjs.map +2 -2
  310. package/dist-esm/lib/tools/HandTool/childStates/Dragging.mjs +3 -2
  311. package/dist-esm/lib/tools/HandTool/childStates/Dragging.mjs.map +2 -2
  312. package/dist-esm/lib/tools/HandTool/childStates/Pointing.mjs +1 -1
  313. package/dist-esm/lib/tools/HandTool/childStates/Pointing.mjs.map +2 -2
  314. package/dist-esm/lib/tools/LaserTool/childStates/Lasering.mjs +1 -1
  315. package/dist-esm/lib/tools/LaserTool/childStates/Lasering.mjs.map +2 -2
  316. package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs +10 -11
  317. package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs.map +2 -2
  318. package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs +6 -5
  319. package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs.map +2 -2
  320. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs +4 -6
  321. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs.map +2 -2
  322. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs +1 -1
  323. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
  324. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.mjs +1 -1
  325. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.mjs.map +2 -2
  326. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs +1 -1
  327. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs.map +2 -2
  328. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.mjs +2 -1
  329. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.mjs.map +2 -2
  330. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.mjs +1 -1
  331. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.mjs.map +2 -2
  332. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +8 -6
  333. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  334. package/dist-esm/lib/tools/SelectTool/childStates/EditingShape.mjs +38 -11
  335. package/dist-esm/lib/tools/SelectTool/childStates/EditingShape.mjs.map +2 -2
  336. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +43 -51
  337. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
  338. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs +6 -6
  339. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
  340. package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs +1 -1
  341. package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs.map +2 -2
  342. package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs +6 -19
  343. package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs.map +2 -2
  344. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs +1 -1
  345. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs.map +2 -2
  346. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs +1 -1
  347. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs.map +2 -2
  348. package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs +2 -2
  349. package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs.map +2 -2
  350. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs +4 -13
  351. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs.map +2 -2
  352. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +5 -6
  353. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  354. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs +2 -3
  355. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs.map +2 -2
  356. package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs +7 -6
  357. package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs.map +2 -2
  358. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +13 -11
  359. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  360. package/dist-esm/lib/tools/SelectTool/selectHelpers.mjs +17 -4
  361. package/dist-esm/lib/tools/SelectTool/selectHelpers.mjs.map +2 -2
  362. package/dist-esm/lib/tools/ZoomTool/ZoomTool.mjs +1 -1
  363. package/dist-esm/lib/tools/ZoomTool/ZoomTool.mjs.map +2 -2
  364. package/dist-esm/lib/tools/ZoomTool/childStates/Pointing.mjs +3 -3
  365. package/dist-esm/lib/tools/ZoomTool/childStates/Pointing.mjs.map +2 -2
  366. package/dist-esm/lib/tools/ZoomTool/childStates/ZoomBrushing.mjs +5 -6
  367. package/dist-esm/lib/tools/ZoomTool/childStates/ZoomBrushing.mjs.map +2 -2
  368. package/dist-esm/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.mjs +1 -3
  369. package/dist-esm/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.mjs.map +2 -2
  370. package/dist-esm/lib/tools/selection-logic/selectOnCanvasPointerUp.mjs +1 -1
  371. package/dist-esm/lib/tools/selection-logic/selectOnCanvasPointerUp.mjs.map +2 -2
  372. package/dist-esm/lib/tools/selection-logic/updateHoveredShapeId.mjs +1 -1
  373. package/dist-esm/lib/tools/selection-logic/updateHoveredShapeId.mjs.map +2 -2
  374. package/dist-esm/lib/ui/TldrawUi.mjs +2 -2
  375. package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
  376. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.mjs +2 -8
  377. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.mjs.map +2 -2
  378. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs +1 -3
  379. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs.map +2 -2
  380. package/dist-esm/lib/ui/components/CursorChatBubble.mjs +1 -1
  381. package/dist-esm/lib/ui/components/CursorChatBubble.mjs.map +2 -2
  382. package/dist-esm/lib/ui/components/DefaultDebugPanel.mjs +3 -30
  383. package/dist-esm/lib/ui/components/DefaultDebugPanel.mjs.map +2 -2
  384. package/dist-esm/lib/ui/components/EditLinkDialog.mjs +11 -1
  385. package/dist-esm/lib/ui/components/EditLinkDialog.mjs.map +2 -2
  386. package/dist-esm/lib/ui/components/HelperButtons/BackToContent.mjs +1 -1
  387. package/dist-esm/lib/ui/components/HelperButtons/BackToContent.mjs.map +2 -2
  388. package/dist-esm/lib/ui/components/HelperButtons/StopFollowing.mjs.map +2 -2
  389. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +1 -1
  390. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
  391. package/dist-esm/lib/ui/components/OfflineIndicator/OfflineIndicator.mjs +3 -6
  392. package/dist-esm/lib/ui/components/OfflineIndicator/OfflineIndicator.mjs.map +2 -2
  393. package/dist-esm/lib/ui/components/PageMenu/PageItemInput.mjs +3 -1
  394. package/dist-esm/lib/ui/components/PageMenu/PageItemInput.mjs.map +2 -2
  395. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs +6 -0
  396. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs.map +2 -2
  397. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  398. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbar.mjs +1 -1
  399. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbar.mjs.map +2 -2
  400. package/dist-esm/lib/ui/components/Toolbar/DefaultRichTextToolbar.mjs +1 -1
  401. package/dist-esm/lib/ui/components/Toolbar/DefaultRichTextToolbar.mjs.map +2 -2
  402. package/dist-esm/lib/ui/components/TopPanel/CenteredTopPanelContainer.mjs.map +1 -1
  403. package/dist-esm/lib/ui/components/menu-items.mjs +4 -5
  404. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  405. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +3 -1
  406. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  407. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +2 -2
  408. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  409. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +157 -95
  410. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  411. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuActionCheckboxItem.mjs.map +2 -2
  412. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuActionItem.mjs.map +2 -2
  413. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +15 -8
  414. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  415. package/dist-esm/lib/ui/context/actions.mjs +7 -8
  416. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  417. package/dist-esm/lib/ui/context/components.mjs +1 -2
  418. package/dist-esm/lib/ui/context/components.mjs.map +2 -2
  419. package/dist-esm/lib/ui/hooks/menu-hooks.mjs +1 -4
  420. package/dist-esm/lib/ui/hooks/menu-hooks.mjs.map +2 -2
  421. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +2 -2
  422. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
  423. package/dist-esm/lib/ui/hooks/useFlatten.mjs.map +2 -2
  424. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs +2 -2
  425. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs.map +2 -2
  426. package/dist-esm/lib/ui/hooks/useTools.mjs +4 -5
  427. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  428. package/dist-esm/lib/ui/version.mjs +3 -3
  429. package/dist-esm/lib/ui/version.mjs.map +1 -1
  430. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs +17 -6
  431. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs.map +2 -2
  432. package/dist-esm/lib/utils/export/exportAs.mjs +1 -3
  433. package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
  434. package/dist-esm/lib/utils/frames/frames.mjs.map +2 -2
  435. package/dist-esm/lib/utils/test-helpers.mjs +21 -0
  436. package/dist-esm/lib/utils/test-helpers.mjs.map +7 -0
  437. package/dist-esm/lib/utils/text/richText.mjs +12 -5
  438. package/dist-esm/lib/utils/text/richText.mjs.map +2 -2
  439. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs +8 -2
  440. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs.map +2 -2
  441. package/package.json +18 -16
  442. package/src/index.ts +6 -2
  443. package/src/lib/Tldraw.test.tsx +46 -1
  444. package/src/lib/bindings/arrow/ArrowBindingUtil.ts +1 -1
  445. package/src/lib/canvas/TldrawSelectionForeground.tsx +6 -11
  446. package/src/lib/defaultEmbedDefinitions.ts +2 -1
  447. package/src/lib/defaultExternalContentHandlers.ts +13 -14
  448. package/src/lib/defaultSideEffects.ts +6 -1
  449. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +40 -133
  450. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +8 -8
  451. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +2 -2
  452. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +16 -16
  453. package/src/lib/shapes/arrow/arrow-types.ts +2 -0
  454. package/src/lib/shapes/arrow/arrowLabel.ts +2 -2
  455. package/src/lib/shapes/arrow/arrowTargetState.ts +2 -2
  456. package/src/lib/shapes/arrow/elbow/elbowArrowSnapLines.tsx +3 -3
  457. package/src/lib/shapes/arrow/elbow/getElbowArrowInfo.test.ts +80 -0
  458. package/src/lib/shapes/arrow/elbow/getElbowArrowInfo.tsx +1 -1
  459. package/src/lib/shapes/arrow/shared.ts +4 -4
  460. package/src/lib/shapes/arrow/toolStates/Idle.tsx +4 -14
  461. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +8 -5
  462. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +1 -1
  463. package/src/lib/shapes/bookmark/bookmarks.ts +3 -3
  464. package/src/lib/shapes/draw/DrawShapeUtil.test.ts +146 -0
  465. package/src/lib/shapes/draw/DrawShapeUtil.tsx +33 -27
  466. package/src/lib/shapes/draw/getPath.ts +31 -10
  467. package/src/lib/shapes/draw/toolStates/Drawing.ts +100 -90
  468. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +8 -1
  469. package/src/lib/shapes/frame/FrameShapeTool.ts +1 -1
  470. package/src/lib/shapes/frame/FrameShapeUtil.tsx +10 -4
  471. package/src/lib/shapes/geo/GeoShapeUtil.test.tsx +10 -2
  472. package/src/lib/shapes/geo/GeoShapeUtil.tsx +228 -176
  473. package/src/lib/shapes/geo/toolStates/Idle.ts +5 -15
  474. package/src/lib/shapes/geo/toolStates/Pointing.ts +6 -6
  475. package/src/lib/shapes/highlight/HighlightShapeUtil.test.ts +146 -0
  476. package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +27 -24
  477. package/src/lib/shapes/line/LineShapeTool.test.ts +6 -6
  478. package/src/lib/shapes/line/LineShapeUtil.test.tsx +5 -5
  479. package/src/lib/shapes/line/toolStates/Pointing.ts +4 -4
  480. package/src/lib/shapes/note/NoteShapeTool.test.ts +2 -1
  481. package/src/lib/shapes/note/NoteShapeUtil.tsx +9 -10
  482. package/src/lib/shapes/note/noteCloning.test.ts +3 -1
  483. package/src/lib/shapes/note/noteHelpers.ts +2 -2
  484. package/src/lib/shapes/note/toolStates/Pointing.ts +5 -10
  485. package/src/lib/shapes/shared/HyperlinkButton.tsx +4 -3
  486. package/src/lib/shapes/shared/PlainTextLabel.tsx +12 -2
  487. package/src/lib/shapes/shared/RichTextLabel.tsx +14 -4
  488. package/src/lib/shapes/shared/ShapeFill.tsx +2 -2
  489. package/src/lib/shapes/shared/crop.ts +1 -0
  490. package/src/lib/shapes/shared/interpolate-props.ts +4 -4
  491. package/src/lib/shapes/shared/useEditablePlainText.ts +7 -3
  492. package/src/lib/shapes/shared/useEditableRichText.ts +7 -3
  493. package/src/lib/shapes/shared/useEfficientZoomThreshold.ts +10 -0
  494. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +1 -1
  495. package/src/lib/shapes/text/RichTextArea.tsx +5 -0
  496. package/src/lib/shapes/text/TextShapeTool.test.ts +4 -4
  497. package/src/lib/shapes/text/TextShapeUtil.tsx +5 -0
  498. package/src/lib/shapes/text/toolStates/Idle.ts +4 -14
  499. package/src/lib/shapes/text/toolStates/Pointing.ts +8 -8
  500. package/src/lib/shapes/video/VideoShapeUtil.tsx +2 -1
  501. package/src/lib/tools/EraserTool/childStates/Erasing.ts +7 -10
  502. package/src/lib/tools/EraserTool/childStates/Pointing.ts +5 -20
  503. package/src/lib/tools/HandTool/HandTool.ts +3 -5
  504. package/src/lib/tools/HandTool/childStates/Dragging.ts +3 -2
  505. package/src/lib/tools/HandTool/childStates/Pointing.ts +1 -1
  506. package/src/lib/tools/LaserTool/childStates/Lasering.ts +1 -1
  507. package/src/lib/tools/SelectTool/DragAndDropManager.ts +14 -11
  508. package/src/lib/tools/SelectTool/childStates/Brushing.ts +8 -11
  509. package/src/lib/tools/SelectTool/childStates/Crop/children/Cropping.ts +7 -6
  510. package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +3 -4
  511. package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.ts +1 -1
  512. package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.ts +1 -1
  513. package/src/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.ts +2 -1
  514. package/src/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.ts +1 -1
  515. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +11 -12
  516. package/src/lib/tools/SelectTool/childStates/EditingShape.ts +57 -16
  517. package/src/lib/tools/SelectTool/childStates/Idle.ts +64 -81
  518. package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +7 -8
  519. package/src/lib/tools/SelectTool/childStates/PointingCanvas.ts +1 -1
  520. package/src/lib/tools/SelectTool/childStates/PointingHandle.ts +9 -17
  521. package/src/lib/tools/SelectTool/childStates/PointingResizeHandle.ts +1 -1
  522. package/src/lib/tools/SelectTool/childStates/PointingRotateHandle.ts +1 -1
  523. package/src/lib/tools/SelectTool/childStates/PointingSelection.ts +4 -4
  524. package/src/lib/tools/SelectTool/childStates/PointingShape.ts +4 -14
  525. package/src/lib/tools/SelectTool/childStates/Resizing.ts +8 -10
  526. package/src/lib/tools/SelectTool/childStates/Rotating.ts +2 -3
  527. package/src/lib/tools/SelectTool/childStates/ScribbleBrushing.ts +9 -10
  528. package/src/lib/tools/SelectTool/childStates/Translating.ts +16 -15
  529. package/src/lib/tools/SelectTool/selectHelpers.ts +39 -4
  530. package/src/lib/tools/ZoomTool/ZoomTool.ts +1 -1
  531. package/src/lib/tools/ZoomTool/childStates/Pointing.ts +3 -3
  532. package/src/lib/tools/ZoomTool/childStates/ZoomBrushing.ts +5 -6
  533. package/src/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.ts +1 -3
  534. package/src/lib/tools/selection-logic/selectOnCanvasPointerUp.ts +1 -1
  535. package/src/lib/tools/selection-logic/updateHoveredShapeId.ts +1 -1
  536. package/src/lib/ui/TldrawUi.tsx +5 -2
  537. package/src/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.tsx +1 -9
  538. package/src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx +1 -3
  539. package/src/lib/ui/components/CursorChatBubble.tsx +2 -2
  540. package/src/lib/ui/components/DefaultDebugPanel.tsx +3 -42
  541. package/src/lib/ui/components/EditLinkDialog.tsx +16 -6
  542. package/src/lib/ui/components/HelperButtons/BackToContent.tsx +1 -1
  543. package/src/lib/ui/components/HelperButtons/StopFollowing.tsx +2 -2
  544. package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +1 -1
  545. package/src/lib/ui/components/OfflineIndicator/OfflineIndicator.tsx +6 -5
  546. package/src/lib/ui/components/PageMenu/PageItemInput.tsx +3 -1
  547. package/src/lib/ui/components/SharePanel/PeopleMenu.tsx +8 -0
  548. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +2 -2
  549. package/src/lib/ui/components/Toolbar/DefaultImageToolbar.tsx +1 -1
  550. package/src/lib/ui/components/Toolbar/DefaultRichTextToolbar.tsx +1 -1
  551. package/src/lib/ui/components/TopPanel/CenteredTopPanelContainer.tsx +1 -1
  552. package/src/lib/ui/components/menu-items.tsx +9 -15
  553. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +5 -3
  554. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +2 -2
  555. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +208 -113
  556. package/src/lib/ui/components/primitives/menus/TldrawUiMenuActionCheckboxItem.tsx +1 -1
  557. package/src/lib/ui/components/primitives/menus/TldrawUiMenuActionItem.tsx +1 -1
  558. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +7 -4
  559. package/src/lib/ui/context/actions.tsx +15 -19
  560. package/src/lib/ui/context/components.tsx +1 -2
  561. package/src/lib/ui/hooks/menu-hooks.ts +9 -19
  562. package/src/lib/ui/hooks/useClipboardEvents.ts +2 -2
  563. package/src/lib/ui/hooks/useFlatten.ts +1 -2
  564. package/src/lib/ui/hooks/useKeyboardShortcuts.ts +2 -2
  565. package/src/lib/ui/hooks/useTools.tsx +5 -7
  566. package/src/lib/ui/version.ts +3 -3
  567. package/src/lib/ui.css +27 -23
  568. package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +12 -48
  569. package/src/lib/utils/excalidraw/putExcalidrawContent.ts +19 -6
  570. package/src/lib/utils/export/exportAs.ts +2 -9
  571. package/src/lib/utils/frames/frames.ts +1 -1
  572. package/src/lib/utils/test-helpers.ts +62 -0
  573. package/src/lib/utils/text/richText.ts +13 -8
  574. package/src/lib/utils/tldr/buildFromV1Document.ts +21 -19
  575. package/src/test/Editor.test.tsx +78 -41
  576. package/src/test/EraserTool.test.ts +10 -12
  577. package/src/test/SelectTool.test.ts +11 -19
  578. package/src/test/TestEditor.ts +49 -51
  579. package/src/test/TldrawEditor.test.tsx +24 -20
  580. package/src/test/__snapshots__/drawing.test.ts.snap +3 -1257
  581. package/src/test/__snapshots__/resizing.test.ts.snap +3 -12
  582. package/src/test/arrows-megabus.test.tsx +1 -1
  583. package/src/test/bindings.test.tsx +29 -25
  584. package/src/test/bindingsIndex.test.tsx +4 -4
  585. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +10 -10
  586. package/src/test/commands/cameraState.test.ts +299 -0
  587. package/src/test/commands/createShape.test.ts +64 -0
  588. package/src/test/commands/createShapes.test.ts +15 -1
  589. package/src/test/commands/getSvgString.test.ts +2 -2
  590. package/src/test/commands/isShapeOfType.test.ts +44 -0
  591. package/src/test/commands/putContent.test.ts +80 -1
  592. package/src/test/commands/setCamera.test.ts +13 -11
  593. package/src/test/commands/stackShapes.test.ts +34 -8
  594. package/src/test/commands/updateShape.test.ts +67 -0
  595. package/src/test/commands/updateShapes.test.ts +21 -5
  596. package/src/test/commands/zoomToBounds.test.ts +19 -3
  597. package/src/test/commands/zoomToSelection.test.ts +14 -3
  598. package/src/test/custom-clipping.test.ts +52 -44
  599. package/src/test/customSnapping.test.tsx +77 -62
  600. package/src/test/drawing.test.ts +17 -10
  601. package/src/test/duplicate.test.ts +1 -1
  602. package/src/test/flipShapes.test.ts +33 -0
  603. package/src/test/frames.test.ts +94 -2
  604. package/src/test/getCulledShapes.test.tsx +11 -3
  605. package/src/test/getShapeAtPoint.test.ts +2 -2
  606. package/src/test/groups.test.tsx +7 -4
  607. package/src/test/modifiers.test.ts +6 -6
  608. package/src/test/resizing.test.ts +16 -22
  609. package/src/test/selection-omnibus.test.ts +13 -13
  610. package/src/test/shapeutils.test.ts +1 -1
  611. package/src/test/spacebarPanning.test.ts +28 -10
  612. package/src/test/styles2.test.tsx +1 -1
  613. package/src/test/styles3.test.ts +5 -5
  614. package/src/test/test-jsx.tsx +72 -57
  615. package/src/test/text.test.ts +15 -17
  616. package/src/test/translating.test.ts +6 -8
  617. package/src/test/ui/BackToContent.test.tsx +111 -0
  618. package/tldraw.css +41 -35
  619. package/dist-cjs/lib/shapes/shared/useForceSolid.js.map +0 -7
  620. package/dist-cjs/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.js.map +0 -7
  621. package/dist-cjs/lib/ui/components/TopPanel/DefaultTopPanel.js +0 -32
  622. package/dist-cjs/lib/ui/components/TopPanel/DefaultTopPanel.js.map +0 -7
  623. package/dist-cjs/lib/utils/text/textDirection.js +0 -51
  624. package/dist-cjs/lib/utils/text/textDirection.js.map +0 -7
  625. package/dist-esm/lib/shapes/shared/useForceSolid.mjs +0 -9
  626. package/dist-esm/lib/shapes/shared/useForceSolid.mjs.map +0 -7
  627. package/dist-esm/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.mjs +0 -8
  628. package/dist-esm/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.mjs.map +0 -7
  629. package/dist-esm/lib/ui/components/TopPanel/DefaultTopPanel.mjs +0 -12
  630. package/dist-esm/lib/ui/components/TopPanel/DefaultTopPanel.mjs.map +0 -7
  631. package/dist-esm/lib/utils/text/textDirection.mjs +0 -31
  632. package/dist-esm/lib/utils/text/textDirection.mjs.map +0 -7
  633. package/src/lib/shapes/shared/useForceSolid.ts +0 -6
  634. package/src/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.ts +0 -10
  635. package/src/lib/ui/components/TopPanel/DefaultTopPanel.tsx +0 -10
  636. package/src/lib/utils/text/textDirection.ts +0 -32
@@ -34,10 +34,15 @@ export function registerDefaultSideEffects(editor: Editor) {
34
34
  editor.getInstanceState().isToolLocked
35
35
  ) {
36
36
  editor.setCurrentTool('select.editing_shape', {
37
+ target: 'shape',
38
+ shape: shape,
37
39
  isCreatingTextWhileToolLocked: true,
38
40
  })
39
41
  } else {
40
- editor.setCurrentTool('select.editing_shape')
42
+ editor.setCurrentTool('select.editing_shape', {
43
+ target: 'shape',
44
+ shape: shape,
45
+ })
41
46
  }
42
47
  }
43
48
  } else if (prev.editingShapeId && !next.editingShapeId) {
@@ -48,19 +48,19 @@ describe('ArrowShapeOptions', () => {
48
48
  const util = editor.getShapeUtil<ArrowShapeUtil>('arrow')
49
49
 
50
50
  // Test without alt key, not precise
51
- editor.inputs.altKey = false
51
+ editor.inputs.setAltKey(false)
52
52
  expect(util.options.shouldBeExact(editor, false)).toBe(false)
53
53
 
54
54
  // Test without alt key, precise
55
- editor.inputs.altKey = false
55
+ editor.inputs.setAltKey(false)
56
56
  expect(util.options.shouldBeExact(editor, true)).toBe(false)
57
57
 
58
58
  // Test with alt key, not precise
59
- editor.inputs.altKey = true
59
+ editor.inputs.setAltKey(true)
60
60
  expect(util.options.shouldBeExact(editor, false)).toBe(true)
61
61
 
62
62
  // Test with alt key, precise
63
- editor.inputs.altKey = true
63
+ editor.inputs.setAltKey(true)
64
64
  expect(util.options.shouldBeExact(editor, true)).toBe(true)
65
65
  })
66
66
 
@@ -68,59 +68,19 @@ describe('ArrowShapeOptions', () => {
68
68
  const util = editor.getShapeUtil<ArrowShapeUtil>('arrow')
69
69
 
70
70
  // Test without ctrl key
71
- editor.inputs.ctrlKey = false
71
+ editor.inputs.setCtrlKey(false)
72
72
  expect(util.options.shouldIgnoreTargets(editor)).toBe(false)
73
73
 
74
74
  // Test with ctrl key
75
- editor.inputs.ctrlKey = true
75
+ editor.inputs.setCtrlKey(true)
76
76
  expect(util.options.shouldIgnoreTargets(editor)).toBe(true)
77
77
  })
78
78
  })
79
79
 
80
80
  describe('shouldIgnoreTargets option', () => {
81
- it('should not bind to shapes when shouldIgnoreTargets returns true', () => {
82
- editor.setCurrentTool('arrow')
83
-
84
- // Simulate ctrl key held (default shouldIgnoreTargets behavior)
85
- editor.inputs.ctrlKey = true
86
-
87
- editor.pointerDown(50, 50) // Start outside any shape
88
- editor.pointerMove(150, 150) // Move to center of box1
89
- editor.pointerUp()
90
-
91
- const createdArrow = editor
92
- .getCurrentPageShapes()
93
- .find((s) => s.type === 'arrow') as TLArrowShape
94
- expect(createdArrow).toBeDefined()
95
-
96
- const arrowBindings = getArrowBindings(editor, createdArrow)
97
- expect(arrowBindings.start).toBeUndefined()
98
- expect(arrowBindings.end).toBeUndefined()
99
- })
100
-
101
- it('should bind to shapes when shouldIgnoreTargets returns false', () => {
102
- editor.setCurrentTool('arrow')
103
-
104
- // Simulate no ctrl key (default shouldIgnoreTargets behavior)
105
- editor.inputs.ctrlKey = false
106
-
107
- editor.pointerDown(50, 50) // Start outside any shape
108
- editor.pointerMove(150, 150) // Move to center of box1
109
- editor.pointerUp()
110
-
111
- const createdArrow = editor
112
- .getCurrentPageShapes()
113
- .find((s) => s.type === 'arrow') as TLArrowShape
114
- expect(createdArrow).toBeDefined()
115
-
116
- const arrowBindings = getArrowBindings(editor, createdArrow)
117
- expect(arrowBindings.end).toBeDefined()
118
- expect(arrowBindings.end?.toId).toBe(ids.box1)
119
- })
120
-
121
81
  it('should work with updateArrowTargetState function', () => {
122
82
  // Test that updateArrowTargetState returns null when shouldIgnoreTargets is true
123
- editor.inputs.ctrlKey = true
83
+ editor.inputs.setCtrlKey(true)
124
84
 
125
85
  const targetState = updateArrowTargetState({
126
86
  editor,
@@ -135,7 +95,7 @@ describe('ArrowShapeOptions', () => {
135
95
  })
136
96
 
137
97
  it('should return valid target state when shouldIgnoreTargets is false', () => {
138
- editor.inputs.ctrlKey = false
98
+ editor.inputs.setCtrlKey(false)
139
99
 
140
100
  const targetState = updateArrowTargetState({
141
101
  editor,
@@ -153,8 +113,8 @@ describe('ArrowShapeOptions', () => {
153
113
 
154
114
  describe('shouldBeExact option', () => {
155
115
  it('should affect arrow targeting behavior when true', () => {
156
- editor.inputs.altKey = true // shouldBeExact = true
157
- editor.inputs.ctrlKey = false // shouldIgnoreTargets = false
116
+ editor.inputs.setAltKey(true) // shouldBeExact = true
117
+ editor.inputs.setCtrlKey(false) // shouldIgnoreTargets = false
158
118
 
159
119
  const targetState = updateArrowTargetState({
160
120
  editor,
@@ -170,8 +130,8 @@ describe('ArrowShapeOptions', () => {
170
130
  })
171
131
 
172
132
  it('should affect arrow targeting behavior when false', () => {
173
- editor.inputs.altKey = false // shouldBeExact = false
174
- editor.inputs.ctrlKey = false // shouldIgnoreTargets = false
133
+ editor.inputs.setAltKey(false) // shouldBeExact = false
134
+ editor.inputs.setCtrlKey(false) // shouldIgnoreTargets = false
175
135
 
176
136
  const targetState = updateArrowTargetState({
177
137
  editor,
@@ -194,21 +154,21 @@ describe('ArrowShapeOptions', () => {
194
154
  class CustomArrowShapeUtil extends ArrowShapeUtil {
195
155
  override options = {
196
156
  ...baseUtil.options,
197
- shouldBeExact: (editor: any, _isPrecise: boolean) => editor.inputs.shiftKey, // Use shift instead of alt
157
+ shouldBeExact: (editor: any, _isPrecise: boolean) => editor.inputs.getShiftKey(), // Use shift instead of alt
198
158
  }
199
159
  }
200
160
 
201
161
  const customUtil = new CustomArrowShapeUtil(editor)
202
162
 
203
163
  // Test with shift key
204
- editor.inputs.shiftKey = true
205
- editor.inputs.altKey = false
164
+ editor.inputs.setShiftKey(true)
165
+ editor.inputs.setAltKey(false)
206
166
  expect(customUtil.options.shouldBeExact(editor, false)).toBe(true)
207
167
  expect(customUtil.options.shouldBeExact(editor, true)).toBe(true)
208
168
 
209
169
  // Test without shift key
210
- editor.inputs.shiftKey = false
211
- editor.inputs.altKey = true // Alt key should not matter for custom implementation
170
+ editor.inputs.setShiftKey(false)
171
+ editor.inputs.setAltKey(true) // Alt key should not matter for custom implementation
212
172
  expect(customUtil.options.shouldBeExact(editor, false)).toBe(false)
213
173
  expect(customUtil.options.shouldBeExact(editor, true)).toBe(false)
214
174
  })
@@ -219,20 +179,20 @@ describe('ArrowShapeOptions', () => {
219
179
  class CustomArrowShapeUtil extends ArrowShapeUtil {
220
180
  override options = {
221
181
  ...baseUtil.options,
222
- shouldIgnoreTargets: (editor: any) => editor.inputs.shiftKey, // Use shift instead of ctrl
182
+ shouldIgnoreTargets: (editor: any) => editor.inputs.getShiftKey(), // Use shift instead of ctrl
223
183
  }
224
184
  }
225
185
 
226
186
  const customUtil = new CustomArrowShapeUtil(editor)
227
187
 
228
188
  // Test with shift key
229
- editor.inputs.shiftKey = true
230
- editor.inputs.ctrlKey = false
189
+ editor.inputs.setShiftKey(true)
190
+ editor.inputs.setCtrlKey(false)
231
191
  expect(customUtil.options.shouldIgnoreTargets(editor)).toBe(true)
232
192
 
233
193
  // Test without shift key
234
- editor.inputs.shiftKey = false
235
- editor.inputs.ctrlKey = true // Ctrl key should not matter for custom implementation
194
+ editor.inputs.setShiftKey(false)
195
+ editor.inputs.setCtrlKey(true) // Ctrl key should not matter for custom implementation
236
196
  expect(customUtil.options.shouldIgnoreTargets(editor)).toBe(false)
237
197
  })
238
198
 
@@ -244,11 +204,13 @@ describe('ArrowShapeOptions', () => {
244
204
  ...baseUtil.options,
245
205
  shouldBeExact: (editor: any, isPrecise: boolean) => {
246
206
  // Custom logic: exact when both alt and shift are pressed, and only if precise
247
- return editor.inputs.altKey && editor.inputs.shiftKey && isPrecise
207
+ return editor.inputs.getAltKey() && editor.inputs.getShiftKey() && isPrecise
248
208
  },
249
209
  shouldIgnoreTargets: (editor: any) => {
250
210
  // Custom logic: ignore targets when any modifier key is pressed
251
- return editor.inputs.altKey || editor.inputs.ctrlKey || editor.inputs.shiftKey
211
+ return (
212
+ editor.inputs.getAltKey() || editor.inputs.getCtrlKey() || editor.inputs.getShiftKey()
213
+ )
252
214
  },
253
215
  }
254
216
  }
@@ -256,48 +218,35 @@ describe('ArrowShapeOptions', () => {
256
218
  const customUtil = new CustomArrowShapeUtil(editor)
257
219
 
258
220
  // Test shouldBeExact with both keys and precise
259
- editor.inputs.altKey = true
260
- editor.inputs.shiftKey = true
221
+ editor.inputs.setAltKey(true)
222
+ editor.inputs.setShiftKey(true)
261
223
  expect(customUtil.options.shouldBeExact(editor, true)).toBe(true)
262
224
 
263
225
  // Test shouldBeExact with both keys but not precise
264
- editor.inputs.altKey = true
265
- editor.inputs.shiftKey = true
226
+ editor.inputs.setAltKey(true)
227
+ editor.inputs.setShiftKey(true)
266
228
  expect(customUtil.options.shouldBeExact(editor, false)).toBe(false)
267
229
 
268
230
  // Test shouldBeExact with only one key
269
- editor.inputs.altKey = true
270
- editor.inputs.shiftKey = false
231
+ editor.inputs.setAltKey(true)
232
+ editor.inputs.setShiftKey(false)
271
233
  expect(customUtil.options.shouldBeExact(editor, true)).toBe(false)
272
234
 
273
235
  // Test shouldIgnoreTargets with any key
274
- editor.inputs.altKey = false
275
- editor.inputs.ctrlKey = false
276
- editor.inputs.shiftKey = true
236
+ editor.inputs.setAltKey(false)
237
+ editor.inputs.setCtrlKey(false)
238
+ editor.inputs.setShiftKey(true)
277
239
  expect(customUtil.options.shouldIgnoreTargets(editor)).toBe(true)
278
240
 
279
241
  // Test shouldIgnoreTargets with no keys
280
- editor.inputs.altKey = false
281
- editor.inputs.ctrlKey = false
282
- editor.inputs.shiftKey = false
242
+ editor.inputs.setAltKey(false)
243
+ editor.inputs.setCtrlKey(false)
244
+ editor.inputs.setShiftKey(false)
283
245
  expect(customUtil.options.shouldIgnoreTargets(editor)).toBe(false)
284
246
  })
285
247
  })
286
248
 
287
249
  describe('Integration with arrow tool states', () => {
288
- it('should respect shouldIgnoreTargets in idle state', () => {
289
- editor.setCurrentTool('arrow')
290
- editor.expectToBeIn('arrow.idle')
291
-
292
- // Move to a position over box1
293
- editor.inputs.ctrlKey = true // shouldIgnoreTargets = true
294
- editor.pointerMove(150, 150)
295
-
296
- // The arrow tool should not show any target highlighting
297
- // (This is more of an integration test - exact assertions would depend on internal state)
298
- expect(editor.getCurrentToolId()).toBe('arrow')
299
- })
300
-
301
250
  it('should allow custom shouldBeExact logic based on isPrecise - example from arrow precise-exact', () => {
302
251
  // This replicates the logic from the arrows-precise-exact example
303
252
  const baseUtil = editor.getShapeUtil<ArrowShapeUtil>('arrow')
@@ -315,10 +264,10 @@ describe('ArrowShapeOptions', () => {
315
264
 
316
265
  try {
317
266
  editor.setCurrentTool('arrow')
318
- editor.inputs.ctrlKey = false // Allow binding
267
+ editor.inputs.setCtrlKey(false) // Allow binding
319
268
 
320
269
  // Set up fast pointer velocity to ensure precise remains false
321
- editor.inputs.pointerVelocity = { x: 2, y: 2, len: () => 2.8 } as any
270
+ editor.inputs.setPointerVelocity({ x: 2, y: 2, len: () => 2.8 } as any)
322
271
 
323
272
  const targetState = updateArrowTargetState({
324
273
  editor,
@@ -352,47 +301,5 @@ describe('ArrowShapeOptions', () => {
352
301
  baseUtil.options.shouldBeExact = originalShouldBeExact
353
302
  }
354
303
  })
355
-
356
- it('should respect shouldIgnoreTargets when starting arrow creation', () => {
357
- editor.setCurrentTool('arrow')
358
-
359
- // Start creating arrow with ctrl held (shouldIgnoreTargets = true)
360
- editor.inputs.ctrlKey = true
361
- editor.pointerDown(150, 150) // Start in center of box1
362
-
363
- // Even though we're starting in a shape, no binding should be created
364
- editor.pointerMove(200, 200)
365
- editor.pointerUp()
366
-
367
- const createdArrow = editor
368
- .getCurrentPageShapes()
369
- .find((s) => s.type === 'arrow') as TLArrowShape
370
- expect(createdArrow).toBeDefined()
371
-
372
- const arrowBindings = getArrowBindings(editor, createdArrow)
373
- expect(arrowBindings.start).toBeUndefined()
374
- expect(arrowBindings.end).toBeUndefined()
375
- })
376
-
377
- it('should respect shouldBeExact during arrow creation', () => {
378
- editor.setCurrentTool('arrow')
379
-
380
- // Create arrow with alt held (shouldBeExact = true)
381
- editor.inputs.altKey = true
382
- editor.inputs.ctrlKey = false // Allow binding
383
-
384
- editor.pointerDown(50, 50) // Start outside shapes
385
- editor.pointerMove(150, 150) // Move to center of box1
386
- editor.pointerUp()
387
-
388
- const createdArrow = editor
389
- .getCurrentPageShapes()
390
- .find((s) => s.type === 'arrow') as TLArrowShape
391
- expect(createdArrow).toBeDefined()
392
-
393
- const arrowBindings = getArrowBindings(editor, createdArrow)
394
- expect(arrowBindings.end).toBeDefined()
395
- expect(arrowBindings.end?.props.isExact).toBe(true)
396
- })
397
304
  })
398
305
  })
@@ -144,7 +144,7 @@ describe('When pointing a start shape', () => {
144
144
  expect(getArrowTargetState(editor)).not.toBeNull()
145
145
 
146
146
  // Fake some velocity
147
- editor.inputs.pointerVelocity = new Vec(1, 1)
147
+ editor.inputs.setPointerVelocity(new Vec(1, 1))
148
148
 
149
149
  editor.pointerMove(375, 500)
150
150
 
@@ -189,7 +189,7 @@ describe('When pointing an end shape', () => {
189
189
  expect(editor.getHintingShapeIds().length).toBe(0)
190
190
 
191
191
  // Fake some velocity
192
- editor.inputs.pointerVelocity = new Vec(1, 1)
192
+ editor.inputs.setPointerVelocity(new Vec(1, 1))
193
193
 
194
194
  // Move onto shape
195
195
  editor.pointerMove(375, 375)
@@ -227,7 +227,7 @@ describe('When pointing an end shape', () => {
227
227
  it('unbinds and rebinds', () => {
228
228
  editor.setCurrentTool('arrow').pointerDown(0, 0)
229
229
 
230
- editor.inputs.pointerVelocity = new Vec(1, 1)
230
+ editor.inputs.setPointerVelocity(new Vec(1, 1))
231
231
 
232
232
  editor.pointerMove(375, 375)
233
233
 
@@ -283,7 +283,7 @@ describe('When pointing an end shape', () => {
283
283
  })
284
284
 
285
285
  // Build up some velocity
286
- editor.inputs.pointerVelocity = new Vec(1, 1)
286
+ editor.inputs.setPointerVelocity(new Vec(1, 1))
287
287
  editor.pointerMove(325, 325)
288
288
  expect(getArrowTargetState(editor)).not.toBeNull()
289
289
 
@@ -403,7 +403,7 @@ describe('When pointing an end shape', () => {
403
403
 
404
404
  it('begins imprecise when moving quickly', () => {
405
405
  editor.setCurrentTool('arrow').pointerDown(0, 0)
406
- editor.inputs.pointerVelocity = new Vec(1, 1)
406
+ editor.inputs.setPointerVelocity(new Vec(1, 1))
407
407
  editor.pointerMove(370, 370)
408
408
 
409
409
  const arrow = editor.getCurrentPageShapes()[editor.getCurrentPageShapes().length - 1]
@@ -435,7 +435,7 @@ describe('When pointing an end shape', () => {
435
435
 
436
436
  expect(getArrowTargetState(editor)).toBeNull()
437
437
 
438
- editor.inputs.pointerVelocity = new Vec(0.001, 0.001)
438
+ editor.inputs.setPointerVelocity(new Vec(0.001, 0.001))
439
439
  editor.pointerMove(375, 375)
440
440
 
441
441
  arrow = editor.getCurrentPageShapes()[editor.getCurrentPageShapes().length - 1]
@@ -588,7 +588,7 @@ describe('precision timeout configuration', () => {
588
588
 
589
589
  editor.setCurrentTool('arrow').pointerDown(0, 0)
590
590
  // Use high velocity to avoid precise mode immediately
591
- editor.inputs.pointerVelocity = new Vec(1, 1)
591
+ editor.inputs.setPointerVelocity(new Vec(1, 1))
592
592
  editor.pointerMove(100, 100)
593
593
 
594
594
  const arrow = editor.getCurrentPageShapes()[
@@ -630,7 +630,7 @@ describe('precision timeout configuration', () => {
630
630
 
631
631
  editor.setCurrentTool('arrow').pointerDown(0, 0)
632
632
  // Use high velocity to avoid precise mode immediately
633
- editor.inputs.pointerVelocity = new Vec(1, 1)
633
+ editor.inputs.setPointerVelocity(new Vec(1, 1))
634
634
  editor.pointerMove(100, 100)
635
635
 
636
636
  const arrow = editor.getCurrentPageShapes()[
@@ -333,7 +333,7 @@ describe('Arrow labels', () => {
333
333
  // Create an arrow with a label
334
334
  editor.setCurrentTool('arrow').pointerDown(10, 10).pointerMove(100, 100).pointerUp()
335
335
  const arrowId = editor.getOnlySelectedShape()!.id
336
- editor.updateShapes<TLArrowShape>([
336
+ editor.updateShapes([
337
337
  { id: arrowId, type: 'arrow', props: { richText: toRichText('Test Label') } },
338
338
  ])
339
339
  })
@@ -349,7 +349,7 @@ describe('Arrow labels', () => {
349
349
 
350
350
  it('should update the label of an arrow', () => {
351
351
  const arrowId = editor.getOnlySelectedShape()!.id
352
- editor.updateShapes<TLArrowShape>([
352
+ editor.updateShapes([
353
353
  { id: arrowId, type: 'arrow', props: { richText: toRichText('New Label') } },
354
354
  ])
355
355
  expect(arrow(arrowId)).toMatchObject({
@@ -45,7 +45,6 @@ import {
45
45
  useEditor,
46
46
  useIsEditing,
47
47
  useSharedSafeId,
48
- useValue,
49
48
  } from '@tldraw/editor'
50
49
  import React, { useMemo } from 'react'
51
50
  import { updateArrowTerminal } from '../../bindings/arrow/ArrowBindingUtil'
@@ -56,6 +55,7 @@ import { ShapeFill } from '../shared/ShapeFill'
56
55
  import { ARROW_LABEL_PADDING, STROKE_SIZES, TEXT_PROPS } from '../shared/default-shape-constants'
57
56
  import { getFillDefForCanvas, getFillDefForExport } from '../shared/defaultStyleDefs'
58
57
  import { useDefaultColorTheme } from '../shared/useDefaultColorTheme'
58
+ import { useEfficientZoomThreshold } from '../shared/useEfficientZoomThreshold'
59
59
  import { getArrowBodyPath, getArrowHandlePath } from './ArrowPath'
60
60
  import { ArrowShapeOptions } from './arrow-types'
61
61
  import {
@@ -117,9 +117,13 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
117
117
 
118
118
  hoverPreciseTimeout: 600,
119
119
  pointingPreciseTimeout: 320,
120
-
121
- shouldBeExact: (editor: Editor) => editor.inputs.altKey,
122
- shouldIgnoreTargets: (editor: Editor) => editor.inputs.ctrlKey,
120
+ shouldBeExact(editor: Editor) {
121
+ return editor.inputs.getAltKey()
122
+ },
123
+ shouldIgnoreTargets(editor: Editor) {
124
+ return editor.inputs.getCtrlKey()
125
+ },
126
+ showTextOutline: true,
123
127
  }
124
128
 
125
129
  override canEdit() {
@@ -269,7 +273,7 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
269
273
 
270
274
  const segmentStart = shapePageTransform.applyToPoint(info.route.midpointHandle.segmentStart)
271
275
  const segmentEnd = shapePageTransform.applyToPoint(info.route.midpointHandle.segmentEnd)
272
- const segmentLength = Vec.Dist(segmentStart, segmentEnd) * this.editor.getZoomLevel()
276
+ const segmentLength = Vec.Dist(segmentStart, segmentEnd) * this.editor.getEfficientZoomLevel()
273
277
 
274
278
  if (segmentLength > this.options.elbowMinSegmentLengthToShowMidpointHandle) {
275
279
  handles.push({
@@ -369,7 +373,8 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
369
373
 
370
374
  // we want to snap to certain points. the maximum distance at which a snap will occur is
371
375
  // relative to the zoom level:
372
- const maxSnapDistance = this.options.elbowMidpointSnapDistance / this.editor.getZoomLevel()
376
+ const maxSnapDistance =
377
+ this.options.elbowMidpointSnapDistance / this.editor.getEfficientZoomLevel()
373
378
 
374
379
  // we snap to the midpoint of the range by default
375
380
  const midPoint = perpDistanceToLineAngle(
@@ -794,6 +799,7 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
794
799
  textWidth={labelPosition.box.w - ARROW_LABEL_PADDING * 2 * shape.props.scale}
795
800
  isSelected={isSelected}
796
801
  padding={0}
802
+ showTextOutline={this.options.showTextOutline}
797
803
  style={{
798
804
  transform: `translate(${labelPosition.box.center.x}px, ${labelPosition.box.center.y}px)`,
799
805
  }}
@@ -917,7 +923,7 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
917
923
  if (isEmptyRichText(shape.props.richText)) {
918
924
  // editing text for the first time, so set the position to the default:
919
925
  const labelPosition = getArrowLabelDefaultPosition(this.editor, shape)
920
- this.editor.updateShape<TLArrowShape>({
926
+ this.editor.updateShape({
921
927
  id: shape.id,
922
928
  type: shape.type,
923
929
  props: { labelPosition },
@@ -944,7 +950,7 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
944
950
  .box.clone()
945
951
  .expandBy(-ARROW_LABEL_PADDING * shape.props.scale)}
946
952
  padding={0}
947
- showTextOutline={true}
953
+ showTextOutline={this.options.showTextOutline}
948
954
  />
949
955
  </g>
950
956
  )
@@ -1005,13 +1011,7 @@ const ArrowSvg = track(function ArrowSvg({
1005
1011
  const editor = useEditor()
1006
1012
  const theme = useDefaultColorTheme()
1007
1013
  const info = getArrowInfo(editor, shape)
1008
- const isForceSolid = useValue(
1009
- 'force solid',
1010
- () => {
1011
- return editor.getZoomLevel() < 0.2
1012
- },
1013
- [editor]
1014
- )
1014
+ const isForceSolid = useEfficientZoomThreshold(shape.props.scale * 0.25)
1015
1015
  const clipPathId = useSharedSafeId(shape.id + '_clip')
1016
1016
  const arrowheadDotId = useSharedSafeId('arrowhead-dot')
1017
1017
  const arrowheadCrossId = useSharedSafeId('arrowhead-cross')
@@ -1037,7 +1037,7 @@ const ArrowSvg = track(function ArrowSvg({
1037
1037
  start: 'skip',
1038
1038
  end: 'skip',
1039
1039
  lengthRatio: 2.5,
1040
- strokeWidth: 2 / editor.getZoomLevel(),
1040
+ strokeWidth: 2 / editor.getEfficientZoomLevel(),
1041
1041
  props: {
1042
1042
  className: 'tl-arrow-hint',
1043
1043
  markerStart: bindings.start
@@ -95,6 +95,8 @@ export interface ArrowShapeOptions {
95
95
  * When creating an arrow, should it bind to the target shape.
96
96
  */
97
97
  shouldIgnoreTargets(editor: Editor): boolean
98
+ /** Whether to show the outline of the arrow shape's label (using the same color as the canvas). This helps with overlapping shapes. It does not show up on Safari, where text outline is a performance issues. */
99
+ readonly showTextOutline: boolean
98
100
  }
99
101
 
100
102
  /** @public */
@@ -311,9 +311,9 @@ export function getArrowLabelDefaultPosition(editor: Editor, shape: TLArrowShape
311
311
 
312
312
  /** @internal */
313
313
  export function isOverArrowLabel(editor: Editor, shape: TLShape) {
314
- if (!editor.isShapeOfType<TLArrowShape>(shape, 'arrow')) return false
314
+ if (!editor.isShapeOfType(shape, 'arrow')) return false
315
315
 
316
- const pointInShapeSpace = editor.getPointInShapeSpace(shape, editor.inputs.currentPagePoint)
316
+ const pointInShapeSpace = editor.getPointInShapeSpace(shape, editor.inputs.getCurrentPagePoint())
317
317
  // How should we handle multiple labels? Do shapes ever have multiple labels?
318
318
  const labelGeometry = editor.getShapeGeometry<Group2d>(shape).children[1]
319
319
  // Knowing what we know about arrows... if the shape has no text in its label,
@@ -198,7 +198,7 @@ export function updateArrowTargetState({
198
198
  if (!precise) {
199
199
  // If we're switching to a new bound shape, then precise only if moving slowly
200
200
  if (!currentBinding || (currentBinding && target.id !== currentBinding.toId)) {
201
- precise = editor.inputs.pointerVelocity.len() < 0.5
201
+ precise = editor.inputs.getPointerVelocity().len() < 0.5
202
202
  }
203
203
  }
204
204
 
@@ -377,7 +377,7 @@ export function updateArrowTargetState({
377
377
  return result
378
378
  }
379
379
 
380
- const targetFilterFallback = { type: 'arrow' }
380
+ const targetFilterFallback = { type: 'arrow' as const }
381
381
 
382
382
  /**
383
383
  * Funky math but we want the snap distance to be 4 at the minimum and either 16 or 15% of the
@@ -39,17 +39,17 @@ export function getElbowArrowSnapLines(editor: Editor) {
39
39
  .get(editor, (editor) => {
40
40
  const currentSelectedArrowShape = computed('current selected arrow shape', () => {
41
41
  const shape = editor.getOnlySelectedShape()
42
- if (!shape || !editor.isShapeOfType<TLArrowShape>(shape, 'arrow')) return null
42
+ if (!shape || !editor.isShapeOfType(shape, 'arrow')) return null
43
43
  return shape.id
44
44
  })
45
45
 
46
46
  const unselectedArrowShapeIds = editor.store.query.ids('shape', () => {
47
47
  const activeArrowShapeId = currentSelectedArrowShape.get()
48
- if (!activeArrowShapeId) return { type: { eq: 'arrow' } }
48
+ if (!activeArrowShapeId) return { type: { eq: 'arrow' } } as const
49
49
  return {
50
50
  type: { eq: 'arrow' },
51
51
  id: { neq: activeArrowShapeId },
52
- }
52
+ } as const
53
53
  })
54
54
 
55
55
  return computed('elbow arrow snap lines', () => {
@@ -0,0 +1,80 @@
1
+ import { createShapeId, TLArrowShape } from '@tldraw/editor'
2
+ import { TestEditor } from '../../../../test/TestEditor'
3
+ import { createOrUpdateArrowBinding, getArrowBindings } from '../shared'
4
+ import { getElbowArrowInfo } from './getElbowArrowInfo'
5
+
6
+ let editor: TestEditor
7
+
8
+ const ids = {
9
+ box1: createShapeId('box1'),
10
+ box2: createShapeId('box2'),
11
+ arrow1: createShapeId('arrow1'),
12
+ }
13
+
14
+ beforeEach(() => {
15
+ editor = new TestEditor()
16
+ })
17
+
18
+ describe('Elbow arrow with scale', () => {
19
+ it.each([1, 5, 10, 20])('creates valid orthogonal routes with scale=%i', (scale) => {
20
+ editor.createShapes([
21
+ { id: ids.box1, type: 'geo', x: 0, y: 0, props: { w: 100, h: 100 } },
22
+ { id: ids.box2, type: 'geo', x: 250, y: 100, props: { w: 100, h: 100 } },
23
+ {
24
+ id: ids.arrow1,
25
+ type: 'arrow',
26
+ x: 0,
27
+ y: 0,
28
+ props: {
29
+ start: { x: 0, y: 0 },
30
+ end: { x: 0, y: 0 },
31
+ kind: 'elbow',
32
+ scale,
33
+ size: 's',
34
+ },
35
+ },
36
+ ])
37
+
38
+ createOrUpdateArrowBinding(editor, ids.arrow1, ids.box1, {
39
+ terminal: 'start',
40
+ isExact: false,
41
+ isPrecise: false,
42
+ normalizedAnchor: { x: 0.5, y: 0.5 },
43
+ snap: 'none',
44
+ })
45
+
46
+ createOrUpdateArrowBinding(editor, ids.arrow1, ids.box2, {
47
+ terminal: 'end',
48
+ isExact: false,
49
+ isPrecise: false,
50
+ normalizedAnchor: { x: 0.5, y: 0.5 },
51
+ snap: 'none',
52
+ })
53
+
54
+ const arrow = editor.getShape(ids.arrow1)! as TLArrowShape
55
+ const bindings = getArrowBindings(editor, arrow)
56
+ const info = getElbowArrowInfo(editor, arrow, bindings)
57
+
58
+ expect(info).toBeDefined()
59
+ expect(arrow.props.kind).toBe('elbow')
60
+ expect(info.route).toBeDefined()
61
+ expect(info.route!.points.length).toBeGreaterThanOrEqual(3)
62
+
63
+ // No duplicate consecutive points
64
+ for (let i = 0; i < info.route!.points.length - 1; i++) {
65
+ const p1 = info.route!.points[i]
66
+ const p2 = info.route!.points[i + 1]
67
+ const isDuplicate = Math.abs(p1.x - p2.x) < 0.01 && Math.abs(p1.y - p2.y) < 0.01
68
+ expect(isDuplicate).toBe(false)
69
+ }
70
+
71
+ // All segments orthogonal
72
+ for (let i = 0; i < info.route!.points.length - 1; i++) {
73
+ const p1 = info.route!.points[i]
74
+ const p2 = info.route!.points[i + 1]
75
+ const isHorizontal = Math.abs(p1.y - p2.y) < 0.01
76
+ const isVertical = Math.abs(p1.x - p2.x) < 0.01
77
+ expect(isHorizontal || isVertical).toBe(true)
78
+ }
79
+ })
80
+ })
@@ -348,7 +348,7 @@ function getElbowArrowTerminalInfo(
348
348
  point: VecModel
349
349
  ): ElbowArrowTerminal {
350
350
  const arrowStrokeSize = (STROKE_SIZES[arrow.props.size] * arrow.props.scale) / 2
351
- const minEndSegmentLength = arrowStrokeSize * arrow.props.scale * 3
351
+ const minEndSegmentLength = arrowStrokeSize * 3
352
352
 
353
353
  if (binding) {
354
354
  const target = editor.getShape(binding.toId)