tldraw 4.3.0-next.82cfddd7ee89 → 4.3.0-next.842fb21476f2

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 (635) hide show
  1. package/dist-cjs/index.d.ts +311 -242
  2. package/dist-cjs/index.js +13 -5
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js.map +2 -2
  5. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js +2 -2
  6. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js.map +2 -2
  7. package/dist-cjs/lib/defaultEmbedDefinitions.js +1 -1
  8. package/dist-cjs/lib/defaultEmbedDefinitions.js.map +2 -2
  9. package/dist-cjs/lib/defaultExternalContentHandlers.js +5 -5
  10. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  11. package/dist-cjs/lib/defaultSideEffects.js +6 -1
  12. package/dist-cjs/lib/defaultSideEffects.js.map +2 -2
  13. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +14 -13
  14. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  15. package/dist-cjs/lib/shapes/arrow/arrow-types.js.map +1 -1
  16. package/dist-cjs/lib/shapes/arrow/arrowLabel.js +1 -1
  17. package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +2 -2
  18. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js +1 -1
  19. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
  20. package/dist-cjs/lib/shapes/arrow/elbow/elbowArrowSnapLines.js.map +2 -2
  21. package/dist-cjs/lib/shapes/arrow/elbow/getElbowArrowInfo.js +1 -1
  22. package/dist-cjs/lib/shapes/arrow/elbow/getElbowArrowInfo.js.map +2 -2
  23. package/dist-cjs/lib/shapes/arrow/shared.js.map +2 -2
  24. package/dist-cjs/lib/shapes/arrow/toolStates/Idle.js +4 -10
  25. package/dist-cjs/lib/shapes/arrow/toolStates/Idle.js.map +2 -2
  26. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +7 -4
  27. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  28. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +1 -1
  29. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  30. package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +2 -2
  31. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +25 -23
  32. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
  33. package/dist-cjs/lib/shapes/draw/getPath.js +20 -11
  34. package/dist-cjs/lib/shapes/draw/getPath.js.map +2 -2
  35. package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js +82 -86
  36. package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js.map +3 -3
  37. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +6 -0
  38. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
  39. package/dist-cjs/lib/shapes/frame/FrameShapeTool.js.map +1 -1
  40. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +6 -5
  41. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  42. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +146 -142
  43. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  44. package/dist-cjs/lib/shapes/geo/toolStates/Idle.js +5 -10
  45. package/dist-cjs/lib/shapes/geo/toolStates/Idle.js.map +2 -2
  46. package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js +3 -3
  47. package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js.map +2 -2
  48. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +23 -21
  49. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
  50. package/dist-cjs/lib/shapes/line/toolStates/Pointing.js +3 -3
  51. package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
  52. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +6 -11
  53. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  54. package/dist-cjs/lib/shapes/note/noteHelpers.js.map +2 -2
  55. package/dist-cjs/lib/shapes/note/toolStates/Pointing.js +5 -10
  56. package/dist-cjs/lib/shapes/note/toolStates/Pointing.js.map +2 -2
  57. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +3 -2
  58. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js.map +2 -2
  59. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +14 -2
  60. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +3 -3
  61. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +12 -4
  62. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +3 -3
  63. package/dist-cjs/lib/shapes/shared/ShapeFill.js +2 -2
  64. package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
  65. package/dist-cjs/lib/shapes/shared/crop.js +1 -0
  66. package/dist-cjs/lib/shapes/shared/crop.js.map +2 -2
  67. package/dist-cjs/lib/shapes/shared/interpolate-props.js +3 -3
  68. package/dist-cjs/lib/shapes/shared/interpolate-props.js.map +2 -2
  69. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  70. package/dist-cjs/lib/shapes/shared/useEditableRichText.js.map +2 -2
  71. package/dist-cjs/lib/shapes/shared/{useForceSolid.js → useEfficientZoomThreshold.js} +10 -7
  72. package/dist-cjs/lib/shapes/shared/useEfficientZoomThreshold.js.map +7 -0
  73. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +1 -1
  74. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
  75. package/dist-cjs/lib/shapes/text/RichTextArea.js +5 -0
  76. package/dist-cjs/lib/shapes/text/RichTextArea.js.map +2 -2
  77. package/dist-cjs/lib/shapes/text/TextShapeUtil.js +5 -2
  78. package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
  79. package/dist-cjs/lib/shapes/text/toolStates/Idle.js +4 -10
  80. package/dist-cjs/lib/shapes/text/toolStates/Idle.js.map +2 -2
  81. package/dist-cjs/lib/shapes/text/toolStates/Pointing.js +7 -5
  82. package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
  83. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +1 -1
  84. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +2 -2
  85. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +4 -5
  86. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  87. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +2 -4
  88. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  89. package/dist-cjs/lib/tools/HandTool/HandTool.js +3 -5
  90. package/dist-cjs/lib/tools/HandTool/HandTool.js.map +2 -2
  91. package/dist-cjs/lib/tools/HandTool/childStates/Dragging.js +3 -2
  92. package/dist-cjs/lib/tools/HandTool/childStates/Dragging.js.map +2 -2
  93. package/dist-cjs/lib/tools/HandTool/childStates/Pointing.js +1 -1
  94. package/dist-cjs/lib/tools/HandTool/childStates/Pointing.js.map +2 -2
  95. package/dist-cjs/lib/tools/LaserTool/childStates/Lasering.js +1 -1
  96. package/dist-cjs/lib/tools/LaserTool/childStates/Lasering.js.map +2 -2
  97. package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js +10 -11
  98. package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js.map +2 -2
  99. package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js +6 -5
  100. package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js.map +2 -2
  101. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js +4 -6
  102. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js.map +2 -2
  103. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js +1 -1
  104. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
  105. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.js +1 -1
  106. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.js.map +2 -2
  107. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js +1 -1
  108. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js.map +2 -2
  109. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.js +2 -1
  110. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.js.map +2 -2
  111. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.js +1 -1
  112. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.js.map +2 -2
  113. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +8 -6
  114. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  115. package/dist-cjs/lib/tools/SelectTool/childStates/EditingShape.js +38 -11
  116. package/dist-cjs/lib/tools/SelectTool/childStates/EditingShape.js.map +2 -2
  117. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +42 -50
  118. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
  119. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js +6 -6
  120. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
  121. package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js +1 -1
  122. package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js.map +2 -2
  123. package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js +4 -14
  124. package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js.map +2 -2
  125. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js +1 -1
  126. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js.map +2 -2
  127. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js +1 -1
  128. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js.map +2 -2
  129. package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js +2 -2
  130. package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js.map +2 -2
  131. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js +4 -13
  132. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js.map +2 -2
  133. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +5 -6
  134. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  135. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js +2 -3
  136. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js.map +2 -2
  137. package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js +7 -6
  138. package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js.map +2 -2
  139. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +13 -11
  140. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  141. package/dist-cjs/lib/tools/SelectTool/selectHelpers.js +15 -4
  142. package/dist-cjs/lib/tools/SelectTool/selectHelpers.js.map +2 -2
  143. package/dist-cjs/lib/tools/ZoomTool/ZoomTool.js +1 -1
  144. package/dist-cjs/lib/tools/ZoomTool/ZoomTool.js.map +2 -2
  145. package/dist-cjs/lib/tools/ZoomTool/childStates/Pointing.js +3 -3
  146. package/dist-cjs/lib/tools/ZoomTool/childStates/Pointing.js.map +2 -2
  147. package/dist-cjs/lib/tools/ZoomTool/childStates/ZoomBrushing.js +5 -6
  148. package/dist-cjs/lib/tools/ZoomTool/childStates/ZoomBrushing.js.map +2 -2
  149. package/dist-cjs/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.js +1 -3
  150. package/dist-cjs/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.js.map +2 -2
  151. package/dist-cjs/lib/tools/selection-logic/selectOnCanvasPointerUp.js +1 -1
  152. package/dist-cjs/lib/tools/selection-logic/selectOnCanvasPointerUp.js.map +2 -2
  153. package/dist-cjs/lib/tools/selection-logic/updateHoveredShapeId.js +1 -1
  154. package/dist-cjs/lib/tools/selection-logic/updateHoveredShapeId.js.map +2 -2
  155. package/dist-cjs/lib/ui/TldrawUi.js +2 -2
  156. package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
  157. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.js +3 -9
  158. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.js.map +2 -2
  159. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js +1 -3
  160. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js.map +2 -2
  161. package/dist-cjs/lib/ui/components/CursorChatBubble.js +1 -1
  162. package/dist-cjs/lib/ui/components/CursorChatBubble.js.map +2 -2
  163. package/dist-cjs/lib/ui/components/DefaultDebugPanel.js +1 -21
  164. package/dist-cjs/lib/ui/components/DefaultDebugPanel.js.map +2 -2
  165. package/dist-cjs/lib/ui/components/EditLinkDialog.js +11 -1
  166. package/dist-cjs/lib/ui/components/EditLinkDialog.js.map +2 -2
  167. package/dist-cjs/lib/ui/components/HelperButtons/BackToContent.js +1 -1
  168. package/dist-cjs/lib/ui/components/HelperButtons/BackToContent.js.map +2 -2
  169. package/dist-cjs/lib/ui/components/HelperButtons/StopFollowing.js.map +2 -2
  170. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +1 -1
  171. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
  172. package/dist-cjs/lib/ui/components/OfflineIndicator/OfflineIndicator.js +2 -15
  173. package/dist-cjs/lib/ui/components/OfflineIndicator/OfflineIndicator.js.map +3 -3
  174. package/dist-cjs/lib/ui/components/PageMenu/PageItemInput.js +3 -1
  175. package/dist-cjs/lib/ui/components/PageMenu/PageItemInput.js.map +2 -2
  176. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js +6 -0
  177. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js.map +2 -2
  178. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  179. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbar.js +1 -1
  180. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbar.js.map +2 -2
  181. package/dist-cjs/lib/ui/components/Toolbar/DefaultRichTextToolbar.js +1 -1
  182. package/dist-cjs/lib/ui/components/Toolbar/DefaultRichTextToolbar.js.map +2 -2
  183. package/dist-cjs/lib/ui/components/TopPanel/CenteredTopPanelContainer.js.map +1 -1
  184. package/dist-cjs/lib/ui/components/menu-items.js +3 -1
  185. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  186. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +3 -1
  187. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  188. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +1 -1
  189. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  190. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +149 -93
  191. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  192. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuActionCheckboxItem.js.map +2 -2
  193. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuActionItem.js.map +2 -2
  194. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +14 -7
  195. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  196. package/dist-cjs/lib/ui/context/actions.js +7 -8
  197. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  198. package/dist-cjs/lib/ui/context/components.js +1 -2
  199. package/dist-cjs/lib/ui/context/components.js.map +2 -2
  200. package/dist-cjs/lib/ui/hooks/menu-hooks.js.map +2 -2
  201. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +2 -2
  202. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
  203. package/dist-cjs/lib/ui/hooks/useFlatten.js.map +2 -2
  204. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +2 -2
  205. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js.map +2 -2
  206. package/dist-cjs/lib/ui/hooks/useTools.js +4 -5
  207. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  208. package/dist-cjs/lib/ui/version.js +3 -3
  209. package/dist-cjs/lib/ui/version.js.map +1 -1
  210. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js +16 -6
  211. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js.map +2 -2
  212. package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
  213. package/dist-cjs/lib/utils/frames/frames.js.map +2 -2
  214. package/dist-cjs/lib/{tools/selection-logic/getShouldEnterCropModeOnPointerDown.js → utils/test-helpers.js} +21 -8
  215. package/dist-cjs/lib/utils/test-helpers.js.map +7 -0
  216. package/dist-cjs/lib/utils/text/richText.js +11 -19
  217. package/dist-cjs/lib/utils/text/richText.js.map +3 -3
  218. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js +7 -2
  219. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js.map +2 -2
  220. package/dist-esm/index.d.mts +311 -242
  221. package/dist-esm/index.mjs +14 -5
  222. package/dist-esm/index.mjs.map +2 -2
  223. package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs.map +2 -2
  224. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs +2 -2
  225. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs.map +2 -2
  226. package/dist-esm/lib/defaultEmbedDefinitions.mjs +1 -1
  227. package/dist-esm/lib/defaultEmbedDefinitions.mjs.map +2 -2
  228. package/dist-esm/lib/defaultExternalContentHandlers.mjs +5 -5
  229. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  230. package/dist-esm/lib/defaultSideEffects.mjs +6 -1
  231. package/dist-esm/lib/defaultSideEffects.mjs.map +2 -2
  232. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +15 -15
  233. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  234. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +1 -1
  235. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +2 -2
  236. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs +1 -1
  237. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
  238. package/dist-esm/lib/shapes/arrow/elbow/elbowArrowSnapLines.mjs.map +2 -2
  239. package/dist-esm/lib/shapes/arrow/elbow/getElbowArrowInfo.mjs +1 -1
  240. package/dist-esm/lib/shapes/arrow/elbow/getElbowArrowInfo.mjs.map +2 -2
  241. package/dist-esm/lib/shapes/arrow/shared.mjs.map +2 -2
  242. package/dist-esm/lib/shapes/arrow/toolStates/Idle.mjs +4 -10
  243. package/dist-esm/lib/shapes/arrow/toolStates/Idle.mjs.map +2 -2
  244. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +7 -4
  245. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  246. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +1 -1
  247. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  248. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +2 -2
  249. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +30 -25
  250. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
  251. package/dist-esm/lib/shapes/draw/getPath.mjs +21 -11
  252. package/dist-esm/lib/shapes/draw/getPath.mjs.map +2 -2
  253. package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs +83 -86
  254. package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs.map +3 -3
  255. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +6 -0
  256. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
  257. package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs.map +1 -1
  258. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +6 -5
  259. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  260. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +147 -142
  261. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  262. package/dist-esm/lib/shapes/geo/toolStates/Idle.mjs +5 -10
  263. package/dist-esm/lib/shapes/geo/toolStates/Idle.mjs.map +2 -2
  264. package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs +3 -3
  265. package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
  266. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +24 -22
  267. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
  268. package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs +3 -3
  269. package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
  270. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +7 -12
  271. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  272. package/dist-esm/lib/shapes/note/noteHelpers.mjs.map +2 -2
  273. package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs +5 -10
  274. package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs.map +2 -2
  275. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs +4 -3
  276. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs.map +2 -2
  277. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +14 -2
  278. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  279. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +12 -4
  280. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  281. package/dist-esm/lib/shapes/shared/ShapeFill.mjs +2 -2
  282. package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
  283. package/dist-esm/lib/shapes/shared/crop.mjs +1 -0
  284. package/dist-esm/lib/shapes/shared/crop.mjs.map +2 -2
  285. package/dist-esm/lib/shapes/shared/interpolate-props.mjs +4 -4
  286. package/dist-esm/lib/shapes/shared/interpolate-props.mjs.map +2 -2
  287. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  288. package/dist-esm/lib/shapes/shared/useEditableRichText.mjs.map +2 -2
  289. package/dist-esm/lib/shapes/shared/useEfficientZoomThreshold.mjs +12 -0
  290. package/dist-esm/lib/shapes/shared/useEfficientZoomThreshold.mjs.map +7 -0
  291. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +1 -1
  292. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  293. package/dist-esm/lib/shapes/text/RichTextArea.mjs +5 -0
  294. package/dist-esm/lib/shapes/text/RichTextArea.mjs.map +2 -2
  295. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +5 -2
  296. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
  297. package/dist-esm/lib/shapes/text/toolStates/Idle.mjs +4 -10
  298. package/dist-esm/lib/shapes/text/toolStates/Idle.mjs.map +2 -2
  299. package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs +7 -5
  300. package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
  301. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +1 -1
  302. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +2 -2
  303. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +4 -5
  304. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  305. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +3 -8
  306. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  307. package/dist-esm/lib/tools/HandTool/HandTool.mjs +3 -5
  308. package/dist-esm/lib/tools/HandTool/HandTool.mjs.map +2 -2
  309. package/dist-esm/lib/tools/HandTool/childStates/Dragging.mjs +3 -2
  310. package/dist-esm/lib/tools/HandTool/childStates/Dragging.mjs.map +2 -2
  311. package/dist-esm/lib/tools/HandTool/childStates/Pointing.mjs +1 -1
  312. package/dist-esm/lib/tools/HandTool/childStates/Pointing.mjs.map +2 -2
  313. package/dist-esm/lib/tools/LaserTool/childStates/Lasering.mjs +1 -1
  314. package/dist-esm/lib/tools/LaserTool/childStates/Lasering.mjs.map +2 -2
  315. package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs +10 -11
  316. package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs.map +2 -2
  317. package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs +6 -5
  318. package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs.map +2 -2
  319. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs +4 -6
  320. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs.map +2 -2
  321. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs +1 -1
  322. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
  323. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.mjs +1 -1
  324. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.mjs.map +2 -2
  325. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs +1 -1
  326. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs.map +2 -2
  327. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.mjs +2 -1
  328. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.mjs.map +2 -2
  329. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.mjs +1 -1
  330. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.mjs.map +2 -2
  331. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +8 -6
  332. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  333. package/dist-esm/lib/tools/SelectTool/childStates/EditingShape.mjs +38 -11
  334. package/dist-esm/lib/tools/SelectTool/childStates/EditingShape.mjs.map +2 -2
  335. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +43 -51
  336. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
  337. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs +6 -6
  338. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
  339. package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs +1 -1
  340. package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs.map +2 -2
  341. package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs +6 -19
  342. package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs.map +2 -2
  343. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs +1 -1
  344. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs.map +2 -2
  345. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs +1 -1
  346. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs.map +2 -2
  347. package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs +2 -2
  348. package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs.map +2 -2
  349. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs +4 -13
  350. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs.map +2 -2
  351. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +5 -6
  352. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  353. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs +2 -3
  354. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs.map +2 -2
  355. package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs +7 -6
  356. package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs.map +2 -2
  357. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +13 -11
  358. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  359. package/dist-esm/lib/tools/SelectTool/selectHelpers.mjs +17 -4
  360. package/dist-esm/lib/tools/SelectTool/selectHelpers.mjs.map +2 -2
  361. package/dist-esm/lib/tools/ZoomTool/ZoomTool.mjs +1 -1
  362. package/dist-esm/lib/tools/ZoomTool/ZoomTool.mjs.map +2 -2
  363. package/dist-esm/lib/tools/ZoomTool/childStates/Pointing.mjs +3 -3
  364. package/dist-esm/lib/tools/ZoomTool/childStates/Pointing.mjs.map +2 -2
  365. package/dist-esm/lib/tools/ZoomTool/childStates/ZoomBrushing.mjs +5 -6
  366. package/dist-esm/lib/tools/ZoomTool/childStates/ZoomBrushing.mjs.map +2 -2
  367. package/dist-esm/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.mjs +1 -3
  368. package/dist-esm/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.mjs.map +2 -2
  369. package/dist-esm/lib/tools/selection-logic/selectOnCanvasPointerUp.mjs +1 -1
  370. package/dist-esm/lib/tools/selection-logic/selectOnCanvasPointerUp.mjs.map +2 -2
  371. package/dist-esm/lib/tools/selection-logic/updateHoveredShapeId.mjs +1 -1
  372. package/dist-esm/lib/tools/selection-logic/updateHoveredShapeId.mjs.map +2 -2
  373. package/dist-esm/lib/ui/TldrawUi.mjs +2 -2
  374. package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
  375. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.mjs +2 -8
  376. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.mjs.map +2 -2
  377. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs +1 -3
  378. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs.map +2 -2
  379. package/dist-esm/lib/ui/components/CursorChatBubble.mjs +1 -1
  380. package/dist-esm/lib/ui/components/CursorChatBubble.mjs.map +2 -2
  381. package/dist-esm/lib/ui/components/DefaultDebugPanel.mjs +3 -30
  382. package/dist-esm/lib/ui/components/DefaultDebugPanel.mjs.map +2 -2
  383. package/dist-esm/lib/ui/components/EditLinkDialog.mjs +11 -1
  384. package/dist-esm/lib/ui/components/EditLinkDialog.mjs.map +2 -2
  385. package/dist-esm/lib/ui/components/HelperButtons/BackToContent.mjs +1 -1
  386. package/dist-esm/lib/ui/components/HelperButtons/BackToContent.mjs.map +2 -2
  387. package/dist-esm/lib/ui/components/HelperButtons/StopFollowing.mjs.map +2 -2
  388. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +1 -1
  389. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
  390. package/dist-esm/lib/ui/components/OfflineIndicator/OfflineIndicator.mjs +3 -6
  391. package/dist-esm/lib/ui/components/OfflineIndicator/OfflineIndicator.mjs.map +2 -2
  392. package/dist-esm/lib/ui/components/PageMenu/PageItemInput.mjs +3 -1
  393. package/dist-esm/lib/ui/components/PageMenu/PageItemInput.mjs.map +2 -2
  394. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs +6 -0
  395. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs.map +2 -2
  396. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  397. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbar.mjs +1 -1
  398. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbar.mjs.map +2 -2
  399. package/dist-esm/lib/ui/components/Toolbar/DefaultRichTextToolbar.mjs +1 -1
  400. package/dist-esm/lib/ui/components/Toolbar/DefaultRichTextToolbar.mjs.map +2 -2
  401. package/dist-esm/lib/ui/components/TopPanel/CenteredTopPanelContainer.mjs.map +1 -1
  402. package/dist-esm/lib/ui/components/menu-items.mjs +4 -5
  403. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  404. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +3 -1
  405. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  406. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +2 -2
  407. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  408. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +157 -95
  409. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  410. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuActionCheckboxItem.mjs.map +2 -2
  411. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuActionItem.mjs.map +2 -2
  412. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +15 -8
  413. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  414. package/dist-esm/lib/ui/context/actions.mjs +7 -8
  415. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  416. package/dist-esm/lib/ui/context/components.mjs +1 -2
  417. package/dist-esm/lib/ui/context/components.mjs.map +2 -2
  418. package/dist-esm/lib/ui/hooks/menu-hooks.mjs +1 -4
  419. package/dist-esm/lib/ui/hooks/menu-hooks.mjs.map +2 -2
  420. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +2 -2
  421. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
  422. package/dist-esm/lib/ui/hooks/useFlatten.mjs.map +2 -2
  423. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs +2 -2
  424. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs.map +2 -2
  425. package/dist-esm/lib/ui/hooks/useTools.mjs +4 -5
  426. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  427. package/dist-esm/lib/ui/version.mjs +3 -3
  428. package/dist-esm/lib/ui/version.mjs.map +1 -1
  429. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs +17 -6
  430. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs.map +2 -2
  431. package/dist-esm/lib/utils/export/exportAs.mjs +1 -3
  432. package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
  433. package/dist-esm/lib/utils/frames/frames.mjs.map +2 -2
  434. package/dist-esm/lib/utils/test-helpers.mjs +21 -0
  435. package/dist-esm/lib/utils/test-helpers.mjs.map +7 -0
  436. package/dist-esm/lib/utils/text/richText.mjs +8 -5
  437. package/dist-esm/lib/utils/text/richText.mjs.map +2 -2
  438. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs +8 -2
  439. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs.map +2 -2
  440. package/package.json +18 -16
  441. package/src/index.ts +6 -2
  442. package/src/lib/Tldraw.test.tsx +46 -1
  443. package/src/lib/bindings/arrow/ArrowBindingUtil.ts +1 -1
  444. package/src/lib/canvas/TldrawSelectionForeground.tsx +6 -11
  445. package/src/lib/defaultEmbedDefinitions.ts +2 -1
  446. package/src/lib/defaultExternalContentHandlers.ts +13 -14
  447. package/src/lib/defaultSideEffects.ts +6 -1
  448. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +40 -133
  449. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +8 -8
  450. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +2 -2
  451. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +16 -16
  452. package/src/lib/shapes/arrow/arrow-types.ts +2 -0
  453. package/src/lib/shapes/arrow/arrowLabel.ts +2 -2
  454. package/src/lib/shapes/arrow/arrowTargetState.ts +2 -2
  455. package/src/lib/shapes/arrow/elbow/elbowArrowSnapLines.tsx +3 -3
  456. package/src/lib/shapes/arrow/elbow/getElbowArrowInfo.test.ts +80 -0
  457. package/src/lib/shapes/arrow/elbow/getElbowArrowInfo.tsx +1 -1
  458. package/src/lib/shapes/arrow/shared.ts +4 -4
  459. package/src/lib/shapes/arrow/toolStates/Idle.tsx +4 -14
  460. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +8 -5
  461. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +1 -1
  462. package/src/lib/shapes/bookmark/bookmarks.ts +3 -3
  463. package/src/lib/shapes/draw/DrawShapeUtil.test.ts +146 -0
  464. package/src/lib/shapes/draw/DrawShapeUtil.tsx +31 -27
  465. package/src/lib/shapes/draw/getPath.ts +31 -10
  466. package/src/lib/shapes/draw/toolStates/Drawing.ts +100 -90
  467. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +8 -1
  468. package/src/lib/shapes/frame/FrameShapeTool.ts +1 -1
  469. package/src/lib/shapes/frame/FrameShapeUtil.tsx +10 -4
  470. package/src/lib/shapes/geo/GeoShapeUtil.test.tsx +10 -2
  471. package/src/lib/shapes/geo/GeoShapeUtil.tsx +228 -176
  472. package/src/lib/shapes/geo/toolStates/Idle.ts +5 -15
  473. package/src/lib/shapes/geo/toolStates/Pointing.ts +6 -6
  474. package/src/lib/shapes/highlight/HighlightShapeUtil.test.ts +146 -0
  475. package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +25 -24
  476. package/src/lib/shapes/line/LineShapeTool.test.ts +6 -6
  477. package/src/lib/shapes/line/LineShapeUtil.test.tsx +5 -5
  478. package/src/lib/shapes/line/toolStates/Pointing.ts +4 -4
  479. package/src/lib/shapes/note/NoteShapeTool.test.ts +2 -1
  480. package/src/lib/shapes/note/NoteShapeUtil.tsx +9 -10
  481. package/src/lib/shapes/note/noteCloning.test.ts +3 -1
  482. package/src/lib/shapes/note/noteHelpers.ts +2 -2
  483. package/src/lib/shapes/note/toolStates/Pointing.ts +5 -10
  484. package/src/lib/shapes/shared/HyperlinkButton.tsx +4 -3
  485. package/src/lib/shapes/shared/PlainTextLabel.tsx +12 -2
  486. package/src/lib/shapes/shared/RichTextLabel.tsx +14 -4
  487. package/src/lib/shapes/shared/ShapeFill.tsx +2 -2
  488. package/src/lib/shapes/shared/crop.ts +1 -0
  489. package/src/lib/shapes/shared/interpolate-props.ts +4 -4
  490. package/src/lib/shapes/shared/useEditablePlainText.ts +7 -3
  491. package/src/lib/shapes/shared/useEditableRichText.ts +7 -3
  492. package/src/lib/shapes/shared/useEfficientZoomThreshold.ts +10 -0
  493. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +1 -1
  494. package/src/lib/shapes/text/RichTextArea.tsx +5 -0
  495. package/src/lib/shapes/text/TextShapeTool.test.ts +4 -4
  496. package/src/lib/shapes/text/TextShapeUtil.tsx +5 -0
  497. package/src/lib/shapes/text/toolStates/Idle.ts +4 -14
  498. package/src/lib/shapes/text/toolStates/Pointing.ts +8 -8
  499. package/src/lib/shapes/video/VideoShapeUtil.tsx +2 -1
  500. package/src/lib/tools/EraserTool/childStates/Erasing.ts +7 -10
  501. package/src/lib/tools/EraserTool/childStates/Pointing.ts +5 -20
  502. package/src/lib/tools/HandTool/HandTool.ts +3 -5
  503. package/src/lib/tools/HandTool/childStates/Dragging.ts +3 -2
  504. package/src/lib/tools/HandTool/childStates/Pointing.ts +1 -1
  505. package/src/lib/tools/LaserTool/childStates/Lasering.ts +1 -1
  506. package/src/lib/tools/SelectTool/DragAndDropManager.ts +14 -11
  507. package/src/lib/tools/SelectTool/childStates/Brushing.ts +8 -11
  508. package/src/lib/tools/SelectTool/childStates/Crop/children/Cropping.ts +7 -6
  509. package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +3 -4
  510. package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.ts +1 -1
  511. package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.ts +1 -1
  512. package/src/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.ts +2 -1
  513. package/src/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.ts +1 -1
  514. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +11 -12
  515. package/src/lib/tools/SelectTool/childStates/EditingShape.ts +57 -16
  516. package/src/lib/tools/SelectTool/childStates/Idle.ts +64 -81
  517. package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +7 -8
  518. package/src/lib/tools/SelectTool/childStates/PointingCanvas.ts +1 -1
  519. package/src/lib/tools/SelectTool/childStates/PointingHandle.ts +9 -17
  520. package/src/lib/tools/SelectTool/childStates/PointingResizeHandle.ts +1 -1
  521. package/src/lib/tools/SelectTool/childStates/PointingRotateHandle.ts +1 -1
  522. package/src/lib/tools/SelectTool/childStates/PointingSelection.ts +4 -4
  523. package/src/lib/tools/SelectTool/childStates/PointingShape.ts +4 -14
  524. package/src/lib/tools/SelectTool/childStates/Resizing.ts +8 -10
  525. package/src/lib/tools/SelectTool/childStates/Rotating.ts +2 -3
  526. package/src/lib/tools/SelectTool/childStates/ScribbleBrushing.ts +9 -10
  527. package/src/lib/tools/SelectTool/childStates/Translating.ts +16 -15
  528. package/src/lib/tools/SelectTool/selectHelpers.ts +39 -4
  529. package/src/lib/tools/ZoomTool/ZoomTool.ts +1 -1
  530. package/src/lib/tools/ZoomTool/childStates/Pointing.ts +3 -3
  531. package/src/lib/tools/ZoomTool/childStates/ZoomBrushing.ts +5 -6
  532. package/src/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.ts +1 -3
  533. package/src/lib/tools/selection-logic/selectOnCanvasPointerUp.ts +1 -1
  534. package/src/lib/tools/selection-logic/updateHoveredShapeId.ts +1 -1
  535. package/src/lib/ui/TldrawUi.tsx +5 -2
  536. package/src/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.tsx +1 -9
  537. package/src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx +1 -3
  538. package/src/lib/ui/components/CursorChatBubble.tsx +2 -2
  539. package/src/lib/ui/components/DefaultDebugPanel.tsx +3 -42
  540. package/src/lib/ui/components/EditLinkDialog.tsx +16 -6
  541. package/src/lib/ui/components/HelperButtons/BackToContent.tsx +1 -1
  542. package/src/lib/ui/components/HelperButtons/StopFollowing.tsx +2 -2
  543. package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +1 -1
  544. package/src/lib/ui/components/OfflineIndicator/OfflineIndicator.tsx +6 -5
  545. package/src/lib/ui/components/PageMenu/PageItemInput.tsx +3 -1
  546. package/src/lib/ui/components/SharePanel/PeopleMenu.tsx +8 -0
  547. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +2 -2
  548. package/src/lib/ui/components/Toolbar/DefaultImageToolbar.tsx +1 -1
  549. package/src/lib/ui/components/Toolbar/DefaultRichTextToolbar.tsx +1 -1
  550. package/src/lib/ui/components/TopPanel/CenteredTopPanelContainer.tsx +1 -1
  551. package/src/lib/ui/components/menu-items.tsx +9 -15
  552. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +5 -3
  553. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +2 -2
  554. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +208 -113
  555. package/src/lib/ui/components/primitives/menus/TldrawUiMenuActionCheckboxItem.tsx +1 -1
  556. package/src/lib/ui/components/primitives/menus/TldrawUiMenuActionItem.tsx +1 -1
  557. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +7 -4
  558. package/src/lib/ui/context/actions.tsx +15 -19
  559. package/src/lib/ui/context/components.tsx +1 -2
  560. package/src/lib/ui/hooks/menu-hooks.ts +9 -19
  561. package/src/lib/ui/hooks/useClipboardEvents.ts +2 -2
  562. package/src/lib/ui/hooks/useFlatten.ts +1 -2
  563. package/src/lib/ui/hooks/useKeyboardShortcuts.ts +2 -2
  564. package/src/lib/ui/hooks/useTools.tsx +5 -7
  565. package/src/lib/ui/version.ts +3 -3
  566. package/src/lib/ui.css +27 -23
  567. package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +12 -48
  568. package/src/lib/utils/excalidraw/putExcalidrawContent.ts +19 -6
  569. package/src/lib/utils/export/exportAs.ts +2 -9
  570. package/src/lib/utils/frames/frames.ts +1 -1
  571. package/src/lib/utils/test-helpers.ts +60 -0
  572. package/src/lib/utils/text/richText.ts +9 -8
  573. package/src/lib/utils/tldr/buildFromV1Document.ts +21 -19
  574. package/src/test/Editor.test.tsx +78 -41
  575. package/src/test/EraserTool.test.ts +10 -12
  576. package/src/test/SelectTool.test.ts +11 -19
  577. package/src/test/TestEditor.ts +49 -51
  578. package/src/test/TldrawEditor.test.tsx +24 -20
  579. package/src/test/__snapshots__/drawing.test.ts.snap +3 -1257
  580. package/src/test/__snapshots__/resizing.test.ts.snap +3 -12
  581. package/src/test/arrows-megabus.test.tsx +1 -1
  582. package/src/test/bindings.test.tsx +29 -25
  583. package/src/test/bindingsIndex.test.tsx +4 -4
  584. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +10 -10
  585. package/src/test/commands/cameraState.test.ts +299 -0
  586. package/src/test/commands/createShape.test.ts +64 -0
  587. package/src/test/commands/createShapes.test.ts +15 -1
  588. package/src/test/commands/getSvgString.test.ts +2 -2
  589. package/src/test/commands/isShapeOfType.test.ts +44 -0
  590. package/src/test/commands/putContent.test.ts +80 -1
  591. package/src/test/commands/setCamera.test.ts +13 -11
  592. package/src/test/commands/stackShapes.test.ts +34 -8
  593. package/src/test/commands/updateShape.test.ts +67 -0
  594. package/src/test/commands/updateShapes.test.ts +21 -5
  595. package/src/test/commands/zoomToBounds.test.ts +19 -3
  596. package/src/test/commands/zoomToSelection.test.ts +14 -3
  597. package/src/test/custom-clipping.test.ts +52 -44
  598. package/src/test/customSnapping.test.tsx +77 -62
  599. package/src/test/drawing.test.ts +17 -10
  600. package/src/test/duplicate.test.ts +1 -1
  601. package/src/test/flipShapes.test.ts +33 -0
  602. package/src/test/frames.test.ts +94 -2
  603. package/src/test/getCulledShapes.test.tsx +11 -3
  604. package/src/test/getShapeAtPoint.test.ts +2 -2
  605. package/src/test/groups.test.tsx +7 -4
  606. package/src/test/modifiers.test.ts +6 -6
  607. package/src/test/resizing.test.ts +16 -22
  608. package/src/test/selection-omnibus.test.ts +13 -13
  609. package/src/test/shapeutils.test.ts +1 -1
  610. package/src/test/spacebarPanning.test.ts +28 -10
  611. package/src/test/styles2.test.tsx +1 -1
  612. package/src/test/styles3.test.ts +5 -5
  613. package/src/test/test-jsx.tsx +72 -57
  614. package/src/test/text.test.ts +15 -17
  615. package/src/test/translating.test.ts +6 -8
  616. package/src/test/ui/BackToContent.test.tsx +111 -0
  617. package/tldraw.css +41 -35
  618. package/dist-cjs/lib/shapes/shared/useForceSolid.js.map +0 -7
  619. package/dist-cjs/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.js.map +0 -7
  620. package/dist-cjs/lib/ui/components/TopPanel/DefaultTopPanel.js +0 -32
  621. package/dist-cjs/lib/ui/components/TopPanel/DefaultTopPanel.js.map +0 -7
  622. package/dist-cjs/lib/utils/text/textDirection.js +0 -51
  623. package/dist-cjs/lib/utils/text/textDirection.js.map +0 -7
  624. package/dist-esm/lib/shapes/shared/useForceSolid.mjs +0 -9
  625. package/dist-esm/lib/shapes/shared/useForceSolid.mjs.map +0 -7
  626. package/dist-esm/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.mjs +0 -8
  627. package/dist-esm/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.mjs.map +0 -7
  628. package/dist-esm/lib/ui/components/TopPanel/DefaultTopPanel.mjs +0 -12
  629. package/dist-esm/lib/ui/components/TopPanel/DefaultTopPanel.mjs.map +0 -7
  630. package/dist-esm/lib/utils/text/textDirection.mjs +0 -31
  631. package/dist-esm/lib/utils/text/textDirection.mjs.map +0 -7
  632. package/src/lib/shapes/shared/useForceSolid.ts +0 -6
  633. package/src/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.ts +0 -10
  634. package/src/lib/ui/components/TopPanel/DefaultTopPanel.tsx +0 -10
  635. package/src/lib/utils/text/textDirection.ts +0 -32
@@ -1,12 +1,4 @@
1
- import {
2
- TLBookmarkShape,
3
- TLEmbedShape,
4
- TLFrameShape,
5
- TLImageShape,
6
- TLPageId,
7
- useEditor,
8
- useValue,
9
- } from '@tldraw/editor'
1
+ import { TLPageId, useEditor, useValue } from '@tldraw/editor'
10
2
  import { supportsDownloadingOriginal } from '../context/actions'
11
3
  import { useUiEvents } from '../context/events'
12
4
  import { useToasts } from '../context/toasts'
@@ -64,7 +56,7 @@ export function FlattenMenuItem() {
64
56
  const selectedShapeIds = editor.getSelectedShapeIds()
65
57
  if (selectedShapeIds.length === 0) return false
66
58
  const onlySelectedShape = editor.getOnlySelectedShape()
67
- if (onlySelectedShape && editor.isShapeOfType<TLImageShape>(onlySelectedShape, 'image')) {
59
+ if (onlySelectedShape && editor.isShapeOfType(onlySelectedShape, 'image')) {
68
60
  return false
69
61
  }
70
62
  return true
@@ -117,7 +109,7 @@ export function RemoveFrameMenuItem() {
117
109
  () => {
118
110
  const selectedShapes = editor.getSelectedShapes()
119
111
  if (selectedShapes.length === 0) return false
120
- return selectedShapes.every((shape) => editor.isShapeOfType<TLFrameShape>(shape, 'frame'))
112
+ return selectedShapes.every((shape) => editor.isShapeOfType(shape, 'frame'))
121
113
  },
122
114
  [editor]
123
115
  )
@@ -135,7 +127,7 @@ export function FitFrameToContentMenuItem() {
135
127
  const onlySelectedShape = editor.getOnlySelectedShape()
136
128
  if (!onlySelectedShape) return false
137
129
  return (
138
- editor.isShapeOfType<TLFrameShape>(onlySelectedShape, 'frame') &&
130
+ editor.isShapeOfType(onlySelectedShape, 'frame') &&
139
131
  editor.getSortedChildIdsForParent(onlySelectedShape).length > 0
140
132
  )
141
133
  },
@@ -190,7 +182,9 @@ export function UnlockAllMenuItem() {
190
182
  /** @public @react */
191
183
  export function ZoomTo100MenuItem() {
192
184
  const editor = useEditor()
193
- const isZoomedTo100 = useValue('zoomed to 100', () => editor.getZoomLevel() === 1, [editor])
185
+ const isZoomedTo100 = useValue('zoomed to 100', () => editor.getEfficientZoomLevel() === 1, [
186
+ editor,
187
+ ])
194
188
 
195
189
  return <TldrawUiMenuActionItem actionId="zoom-to-100" noClose disabled={isZoomedTo100} />
196
190
  }
@@ -518,7 +512,7 @@ export function ConvertToBookmarkMenuItem() {
518
512
  const onlySelectedShape = editor.getOnlySelectedShape()
519
513
  if (!onlySelectedShape) return false
520
514
  return !!(
521
- editor.isShapeOfType<TLEmbedShape>(onlySelectedShape, 'embed') &&
515
+ editor.isShapeOfType(onlySelectedShape, 'embed') &&
522
516
  onlySelectedShape.props.url &&
523
517
  !editor.isShapeOrAncestorLocked(onlySelectedShape)
524
518
  )
@@ -542,7 +536,7 @@ export function ConvertToEmbedMenuItem() {
542
536
  const onlySelectedShape = editor.getOnlySelectedShape()
543
537
  if (!onlySelectedShape) return false
544
538
  return !!(
545
- editor.isShapeOfType<TLBookmarkShape>(onlySelectedShape, 'bookmark') &&
539
+ editor.isShapeOfType(onlySelectedShape, 'bookmark') &&
546
540
  onlySelectedShape.props.url &&
547
541
  getEmbedDefinition(onlySelectedShape.props.url) &&
548
542
  !editor.isShapeOrAncestorLocked(onlySelectedShape)
@@ -52,8 +52,8 @@ export const TldrawUiContextualToolbar = ({
52
52
  const editor = useEditor()
53
53
  const toolbarRef = useRef<HTMLDivElement>(null)
54
54
 
55
- usePassThroughWheelEvents(toolbarRef as RefObject<HTMLDivElement>)
56
- usePassThroughMouseOverEvents(toolbarRef as RefObject<HTMLDivElement>)
55
+ usePassThroughWheelEvents(toolbarRef as RefObject<HTMLDivElement | null>)
56
+ usePassThroughMouseOverEvents(toolbarRef as RefObject<HTMLDivElement | null>)
57
57
 
58
58
  const { isVisible, isInteractive, hide, show, position, move } =
59
59
  useToolbarVisibilityStateMachine(changeOnlyWhenYChanges)
@@ -105,7 +105,9 @@ export const TldrawUiContextualToolbar = ({
105
105
  // to have the last updated position in page space, so that we could convert
106
106
  // it to screen space and update it here
107
107
  const elm = toolbarRef.current
108
- elm.style.setProperty('transform', `translate(${position.x}px, ${position.y}px)`)
108
+ if (elm) {
109
+ elm.style.setProperty('transform', `translate(${position.x}px, ${position.y}px)`)
110
+ }
109
111
  } else {
110
112
  const moveImmediately = lastContentSizeUpdateCounter !== nextContentSizeUpdateCounter
111
113
  // Schedule a move to its next location
@@ -3,7 +3,7 @@ import { Slider as _Slider } from 'radix-ui'
3
3
  import React, { useCallback, useEffect, useState } from 'react'
4
4
  import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
5
5
  import { useTranslation } from '../../hooks/useTranslation/useTranslation'
6
- import { TldrawUiTooltip, tooltipManager } from './TldrawUiTooltip'
6
+ import { hideAllTooltips, TldrawUiTooltip } from './TldrawUiTooltip'
7
7
 
8
8
  /** @public */
9
9
  export interface TLUiSliderProps {
@@ -52,7 +52,7 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
52
52
  )
53
53
 
54
54
  const handlePointerDown = useCallback(() => {
55
- tooltipManager.hideAllTooltips()
55
+ hideAllTooltips()
56
56
  onHistoryMark?.('click slider')
57
57
  }, [onHistoryMark])
58
58
 
@@ -1,4 +1,12 @@
1
- import { assert, Atom, atom, Editor, uniqueId, useMaybeEditor, useValue } from '@tldraw/editor'
1
+ import {
2
+ assert,
3
+ atom,
4
+ Editor,
5
+ tlenvReactive,
6
+ uniqueId,
7
+ useMaybeEditor,
8
+ useValue,
9
+ } from '@tldraw/editor'
2
10
  import { Tooltip as _Tooltip } from 'radix-ui'
3
11
  import React, {
4
12
  createContext,
@@ -6,7 +14,6 @@ import React, {
6
14
  ReactNode,
7
15
  useContext,
8
16
  useEffect,
9
- useLayoutEffect,
10
17
  useRef,
11
18
  useState,
12
19
  } from 'react'
@@ -25,7 +32,7 @@ export interface TldrawUiTooltipProps {
25
32
  delayDuration?: number
26
33
  }
27
34
 
28
- interface CurrentTooltip {
35
+ interface TooltipData {
29
36
  id: string
30
37
  content: ReactNode
31
38
  side: 'top' | 'right' | 'bottom' | 'left'
@@ -35,11 +42,25 @@ interface CurrentTooltip {
35
42
  delayDuration: number
36
43
  }
37
44
 
38
- // Singleton tooltip manager
45
+ // State machine states
46
+ type TooltipState =
47
+ | { name: 'idle' }
48
+ | { name: 'pointer_down' }
49
+ | { name: 'showing'; tooltip: TooltipData }
50
+ | { name: 'waiting_to_hide'; tooltip: TooltipData; timeoutId: number }
51
+
52
+ // State machine events
53
+ type TooltipEvent =
54
+ | { type: 'pointer_down' }
55
+ | { type: 'pointer_up' }
56
+ | { type: 'show'; tooltip: TooltipData }
57
+ | { type: 'hide'; tooltipId: string; editor: Editor | null; instant: boolean }
58
+ | { type: 'hide_all' }
59
+
60
+ // Singleton tooltip manager using explicit state machine
39
61
  class TooltipManager {
40
62
  private static instance: TooltipManager | null = null
41
- private currentTooltip = atom<CurrentTooltip | null>('current tooltip', null)
42
- private destroyTimeoutId: number | null = null
63
+ private state = atom<TooltipState>('tooltip state', { name: 'idle' })
43
64
 
44
65
  static getInstance(): TooltipManager {
45
66
  if (!TooltipManager.instance) {
@@ -48,86 +69,117 @@ class TooltipManager {
48
69
  return TooltipManager.instance
49
70
  }
50
71
 
51
- showTooltip(
52
- tooltipId: string,
53
- content: string | React.ReactNode,
54
- targetElement: HTMLElement,
55
- side: 'top' | 'right' | 'bottom' | 'left',
56
- sideOffset: number,
57
- showOnMobile: boolean,
58
- delayDuration: number
59
- ) {
60
- // Clear any existing destroy timeout
61
- if (this.destroyTimeoutId) {
62
- clearTimeout(this.destroyTimeoutId)
63
- this.destroyTimeoutId = null
64
- }
65
-
66
- // Update current tooltip
67
- this.currentTooltip.set({
68
- id: tooltipId,
69
- content,
70
- side,
71
- sideOffset,
72
- showOnMobile,
73
- targetElement,
74
- delayDuration,
75
- })
72
+ hideAllTooltips() {
73
+ this.handleEvent({ type: 'hide_all' })
76
74
  }
77
75
 
78
- updateCurrentTooltip(tooltipId: string, update: (tooltip: CurrentTooltip) => CurrentTooltip) {
79
- this.currentTooltip.update((tooltip) => {
80
- if (tooltip?.id === tooltipId) {
81
- return update(tooltip)
76
+ handleEvent(event: TooltipEvent) {
77
+ const currentState = this.state.get()
78
+
79
+ switch (event.type) {
80
+ case 'pointer_down': {
81
+ // Transition to pointer_down from any state
82
+ if (currentState.name === 'waiting_to_hide') {
83
+ clearTimeout(currentState.timeoutId)
84
+ }
85
+ this.state.set({ name: 'pointer_down' })
86
+ break
82
87
  }
83
- return tooltip
84
- })
85
- }
86
88
 
87
- hideTooltip(editor: Editor | null, tooltipId: string, instant: boolean = false) {
88
- const hide = () => {
89
- // Only hide if this is the current tooltip
90
- if (this.currentTooltip.get()?.id === tooltipId) {
91
- this.currentTooltip.set(null)
92
- this.destroyTimeoutId = null
89
+ case 'pointer_up': {
90
+ // Only transition from pointer_down to idle
91
+ if (currentState.name === 'pointer_down') {
92
+ this.state.set({ name: 'idle' })
93
+ }
94
+ break
93
95
  }
94
- }
95
96
 
96
- if (editor && !instant) {
97
- // Start destroy timeout (1 second)
98
- this.destroyTimeoutId = editor.timers.setTimeout(hide, 300)
99
- } else {
100
- hide()
101
- }
102
- }
97
+ case 'show': {
98
+ // Don't show tooltips while pointer is down
99
+ if (currentState.name === 'pointer_down') {
100
+ return
101
+ }
103
102
 
104
- hideAllTooltips() {
105
- this.currentTooltip.set(null)
106
- this.destroyTimeoutId = null
107
- }
103
+ // Clear any existing timeout if transitioning from waiting_to_hide
104
+ if (currentState.name === 'waiting_to_hide') {
105
+ clearTimeout(currentState.timeoutId)
106
+ }
107
+
108
+ // Transition to showing state
109
+ this.state.set({ name: 'showing', tooltip: event.tooltip })
110
+ break
111
+ }
112
+
113
+ case 'hide': {
114
+ const { tooltipId, editor, instant } = event
115
+
116
+ // Only hide if the tooltip matches
117
+ if (currentState.name === 'showing' && currentState.tooltip.id === tooltipId) {
118
+ if (editor && !instant) {
119
+ // Transition to waiting_to_hide state
120
+ const timeoutId = editor.timers.setTimeout(() => {
121
+ const state = this.state.get()
122
+ if (state.name === 'waiting_to_hide' && state.tooltip.id === tooltipId) {
123
+ this.state.set({ name: 'idle' })
124
+ }
125
+ }, 300)
126
+ this.state.set({
127
+ name: 'waiting_to_hide',
128
+ tooltip: currentState.tooltip,
129
+ timeoutId,
130
+ })
131
+ } else {
132
+ this.state.set({ name: 'idle' })
133
+ }
134
+ } else if (
135
+ currentState.name === 'waiting_to_hide' &&
136
+ currentState.tooltip.id === tooltipId
137
+ ) {
138
+ // Already waiting to hide, make it instant if requested
139
+ if (instant) {
140
+ clearTimeout(currentState.timeoutId)
141
+ this.state.set({ name: 'idle' })
142
+ }
143
+ }
144
+ break
145
+ }
108
146
 
109
- getCurrentTooltipData() {
110
- const currentTooltip = this.currentTooltip.get()
111
- if (!currentTooltip) return null
112
- if (!this.supportsHover() && !currentTooltip.showOnMobile) return null
113
- return currentTooltip
147
+ case 'hide_all': {
148
+ if (currentState.name === 'waiting_to_hide') {
149
+ clearTimeout(currentState.timeoutId)
150
+ }
151
+ // Preserve pointer_down state if that's the current state
152
+ if (currentState.name === 'pointer_down') {
153
+ return
154
+ }
155
+ this.state.set({ name: 'idle' })
156
+ break
157
+ }
158
+ }
114
159
  }
115
160
 
116
- private supportsHoverAtom: Atom<boolean> | null = null
117
- supportsHover() {
118
- if (!this.supportsHoverAtom) {
119
- const mediaQuery = window.matchMedia('(hover: hover)')
120
- const supportsHover = atom('has hover', mediaQuery.matches)
121
- this.supportsHoverAtom = supportsHover
122
- mediaQuery.addEventListener('change', (e) => {
123
- supportsHover.set(e.matches)
124
- })
161
+ getCurrentTooltipData(): TooltipData | null {
162
+ const currentState = this.state.get()
163
+ let tooltip: TooltipData | null = null
164
+
165
+ if (currentState.name === 'showing') {
166
+ tooltip = currentState.tooltip
167
+ } else if (currentState.name === 'waiting_to_hide') {
168
+ tooltip = currentState.tooltip
125
169
  }
126
- return this.supportsHoverAtom.get()
170
+
171
+ if (!tooltip) return null
172
+ if (tlenvReactive.get().isCoarsePointer && !tooltip.showOnMobile) return null
173
+ return tooltip
127
174
  }
128
175
  }
129
176
 
130
- export const tooltipManager = TooltipManager.getInstance()
177
+ const tooltipManager = TooltipManager.getInstance()
178
+
179
+ /** @public */
180
+ export function hideAllTooltips() {
181
+ tooltipManager.hideAllTooltips()
182
+ }
131
183
 
132
184
  // Context for the tooltip singleton
133
185
  const TooltipSingletonContext = createContext<boolean>(false)
@@ -167,14 +219,19 @@ function TooltipSingleton() {
167
219
  // Hide tooltip when camera is moving (panning/zooming)
168
220
  useEffect(() => {
169
221
  if (cameraState === 'moving' && isOpen && currentTooltip) {
170
- tooltipManager.hideTooltip(editor, currentTooltip.id, true)
222
+ tooltipManager.handleEvent({
223
+ type: 'hide',
224
+ tooltipId: currentTooltip.id,
225
+ editor,
226
+ instant: true,
227
+ })
171
228
  }
172
229
  }, [cameraState, isOpen, currentTooltip, editor])
173
230
 
174
231
  useEffect(() => {
175
232
  function handleKeyDown(event: KeyboardEvent) {
176
233
  if (event.key === 'Escape' && currentTooltip && isOpen) {
177
- tooltipManager.hideTooltip(editor, currentTooltip.id)
234
+ hideAllTooltips()
178
235
  event.stopPropagation()
179
236
  }
180
237
  }
@@ -183,7 +240,29 @@ function TooltipSingleton() {
183
240
  return () => {
184
241
  document.removeEventListener('keydown', handleKeyDown, { capture: true })
185
242
  }
186
- }, [editor, currentTooltip, isOpen])
243
+ }, [currentTooltip, isOpen])
244
+
245
+ // Hide tooltip and prevent new ones from opening while pointer is down
246
+ useEffect(() => {
247
+ function handlePointerDown() {
248
+ tooltipManager.handleEvent({ type: 'pointer_down' })
249
+ }
250
+
251
+ function handlePointerUp() {
252
+ tooltipManager.handleEvent({ type: 'pointer_up' })
253
+ }
254
+
255
+ document.addEventListener('pointerdown', handlePointerDown, { capture: true })
256
+ document.addEventListener('pointerup', handlePointerUp, { capture: true })
257
+ document.addEventListener('pointercancel', handlePointerUp, { capture: true })
258
+ return () => {
259
+ document.removeEventListener('pointerdown', handlePointerDown, { capture: true })
260
+ document.removeEventListener('pointerup', handlePointerUp, { capture: true })
261
+ document.removeEventListener('pointercancel', handlePointerUp, { capture: true })
262
+ // Reset pointer state on unmount to prevent stuck state
263
+ tooltipManager.handleEvent({ type: 'pointer_up' })
264
+ }
265
+ }, [])
187
266
 
188
267
  // Update open state and trigger position
189
268
  useEffect(() => {
@@ -280,23 +359,16 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
280
359
  const currentTooltipId = tooltipId.current
281
360
  return () => {
282
361
  if (hasProvider) {
283
- tooltipManager.hideTooltip(editor, currentTooltipId, true)
362
+ tooltipManager.handleEvent({
363
+ type: 'hide',
364
+ tooltipId: currentTooltipId,
365
+ editor,
366
+ instant: true,
367
+ })
284
368
  }
285
369
  }
286
370
  }, [editor, hasProvider])
287
371
 
288
- useLayoutEffect(() => {
289
- if (hasProvider && tooltipManager.getCurrentTooltipData()?.id === tooltipId.current) {
290
- tooltipManager.updateCurrentTooltip(tooltipId.current, (tooltip) => ({
291
- ...tooltip,
292
- content,
293
- side: sideToUse,
294
- sideOffset,
295
- showOnMobile,
296
- }))
297
- }
298
- }, [content, sideToUse, sideOffset, showOnMobile, hasProvider])
299
-
300
372
  // Don't show tooltip if disabled, no content, or enhanced accessibility mode is disabled
301
373
  if (disabled || !content) {
302
374
  return <>{children}</>
@@ -338,43 +410,66 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
338
410
  const child = React.Children.only(children)
339
411
  assert(React.isValidElement(child), 'TldrawUiTooltip children must be a single element')
340
412
 
413
+ const childElement = child as React.ReactElement<{
414
+ onMouseEnter?(event: React.MouseEvent<HTMLElement>): void
415
+ onMouseLeave?(event: React.MouseEvent<HTMLElement>): void
416
+ onFocus?(event: React.FocusEvent<HTMLElement>): void
417
+ onBlur?(event: React.FocusEvent<HTMLElement>): void
418
+ }>
419
+
341
420
  const handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {
342
- child.props.onMouseEnter?.(event)
343
- tooltipManager.showTooltip(
344
- tooltipId.current,
345
- content,
346
- event.currentTarget as HTMLElement,
347
- sideToUse,
348
- sideOffset,
349
- showOnMobile,
350
- delayDurationToUse
351
- )
421
+ childElement.props.onMouseEnter?.(event)
422
+ tooltipManager.handleEvent({
423
+ type: 'show',
424
+ tooltip: {
425
+ id: tooltipId.current,
426
+ content,
427
+ targetElement: event.currentTarget as HTMLElement,
428
+ side: sideToUse,
429
+ sideOffset,
430
+ showOnMobile,
431
+ delayDuration: delayDurationToUse,
432
+ },
433
+ })
352
434
  }
353
435
 
354
436
  const handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {
355
- child.props.onMouseLeave?.(event)
356
- tooltipManager.hideTooltip(editor, tooltipId.current)
437
+ childElement.props.onMouseLeave?.(event)
438
+ tooltipManager.handleEvent({
439
+ type: 'hide',
440
+ tooltipId: tooltipId.current,
441
+ editor,
442
+ instant: false,
443
+ })
357
444
  }
358
445
 
359
446
  const handleFocus = (event: React.FocusEvent<HTMLElement>) => {
360
- child.props.onFocus?.(event)
361
- tooltipManager.showTooltip(
362
- tooltipId.current,
363
- content,
364
- event.currentTarget as HTMLElement,
365
- sideToUse,
366
- sideOffset,
367
- showOnMobile,
368
- delayDurationToUse
369
- )
447
+ childElement.props.onFocus?.(event)
448
+ tooltipManager.handleEvent({
449
+ type: 'show',
450
+ tooltip: {
451
+ id: tooltipId.current,
452
+ content,
453
+ targetElement: event.currentTarget as HTMLElement,
454
+ side: sideToUse,
455
+ sideOffset,
456
+ showOnMobile,
457
+ delayDuration: delayDurationToUse,
458
+ },
459
+ })
370
460
  }
371
461
 
372
462
  const handleBlur = (event: React.FocusEvent<HTMLElement>) => {
373
- child.props.onBlur?.(event)
374
- tooltipManager.hideTooltip(editor, tooltipId.current)
463
+ childElement.props.onBlur?.(event)
464
+ tooltipManager.handleEvent({
465
+ type: 'hide',
466
+ tooltipId: tooltipId.current,
467
+ editor,
468
+ instant: false,
469
+ })
375
470
  }
376
471
 
377
- const childrenWithHandlers = React.cloneElement(children as React.ReactElement, {
472
+ const childrenWithHandlers = React.cloneElement(childElement, {
378
473
  onMouseEnter: handleMouseEnter,
379
474
  onMouseLeave: handleMouseLeave,
380
475
  onFocus: handleFocus,
@@ -17,5 +17,5 @@ export function TldrawUiMenuActionCheckboxItem({
17
17
  const actions = useActions()
18
18
  const action = actions[actionId]
19
19
  if (!action) return null
20
- return <TldrawUiMenuCheckboxItem {...action} {...rest} />
20
+ return <TldrawUiMenuCheckboxItem {...(action as TLUiMenuCheckboxItemProps)} {...rest} />
21
21
  }
@@ -11,5 +11,5 @@ export function TldrawUiMenuActionItem({ actionId = '', ...rest }: TLUiMenuActio
11
11
  const actions = useActions()
12
12
  const action = actions[actionId]
13
13
  if (!action) return null
14
- return <TldrawUiMenuItem {...action} {...rest} />
14
+ return <TldrawUiMenuItem {...(action as TLUiMenuItemProps)} {...rest} />
15
15
  }
@@ -24,7 +24,7 @@ import { TldrawUiDropdownMenuItem } from '../TldrawUiDropdownMenu'
24
24
  import { TLUiIconJsx } from '../TldrawUiIcon'
25
25
  import { TldrawUiKbd } from '../TldrawUiKbd'
26
26
  import { TldrawUiToolbarButton } from '../TldrawUiToolbar'
27
- import { tooltipManager } from '../TldrawUiTooltip'
27
+ import { hideAllTooltips } from '../TldrawUiTooltip'
28
28
  import { useTldrawUiMenuContext } from './TldrawUiMenuContext'
29
29
 
30
30
  /** @public */
@@ -134,7 +134,6 @@ export function TldrawUiMenuItem<
134
134
  {iconLeft && <TldrawUiButtonIcon icon={iconLeft} small />}
135
135
  <TldrawUiButtonLabel>{labelStr}</TldrawUiButtonLabel>
136
136
  {kbd && <TldrawUiKbd>{kbd}</TldrawUiKbd>}
137
- {icon && <TldrawUiButtonIcon icon={icon} small />}
138
137
  </TldrawUiButton>
139
138
  </TldrawUiDropdownMenuItem>
140
139
  )
@@ -200,7 +199,11 @@ export function TldrawUiMenuItem<
200
199
  }
201
200
  case 'helper-buttons': {
202
201
  return (
203
- <TldrawUiButton type="low" onClick={() => onSelect(sourceId)}>
202
+ <TldrawUiButton
203
+ type="low"
204
+ data-testid={`${sourceId}.${id}`}
205
+ onClick={() => onSelect(sourceId)}
206
+ >
204
207
  <TldrawUiButtonIcon icon={icon!} />
205
208
  <TldrawUiButtonLabel>{labelStr}</TldrawUiButtonLabel>
206
209
  </TldrawUiButton>
@@ -350,7 +353,7 @@ function useDraggableEvents(
350
353
  point: screenSpaceStart,
351
354
  })
352
355
 
353
- tooltipManager.hideAllTooltips()
356
+ hideAllTooltips()
354
357
  editor.getContainer().focus()
355
358
  })
356
359
  }