tldraw 4.3.0-canary.fd6b7f2a8adc → 4.3.0-next.085293d79c32

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 (561) hide show
  1. package/README.md +0 -2
  2. package/dist-cjs/index.d.ts +297 -237
  3. package/dist-cjs/index.js +13 -5
  4. package/dist-cjs/index.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/getElbowArrowInfo.js +1 -1
  21. package/dist-cjs/lib/shapes/arrow/elbow/getElbowArrowInfo.js.map +2 -2
  22. package/dist-cjs/lib/shapes/arrow/toolStates/Idle.js +4 -10
  23. package/dist-cjs/lib/shapes/arrow/toolStates/Idle.js.map +2 -2
  24. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +7 -4
  25. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  26. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +1 -1
  27. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  28. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +25 -23
  29. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
  30. package/dist-cjs/lib/shapes/draw/getPath.js +20 -11
  31. package/dist-cjs/lib/shapes/draw/getPath.js.map +2 -2
  32. package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js +82 -86
  33. package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js.map +3 -3
  34. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +6 -0
  35. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
  36. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +6 -5
  37. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  38. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +146 -142
  39. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  40. package/dist-cjs/lib/shapes/geo/toolStates/Idle.js +5 -10
  41. package/dist-cjs/lib/shapes/geo/toolStates/Idle.js.map +2 -2
  42. package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js +3 -3
  43. package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js.map +2 -2
  44. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +23 -21
  45. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
  46. package/dist-cjs/lib/shapes/line/toolStates/Pointing.js +3 -3
  47. package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
  48. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +6 -11
  49. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  50. package/dist-cjs/lib/shapes/note/toolStates/Pointing.js +5 -10
  51. package/dist-cjs/lib/shapes/note/toolStates/Pointing.js.map +2 -2
  52. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +3 -2
  53. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js.map +2 -2
  54. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +14 -2
  55. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +3 -3
  56. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +12 -4
  57. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +3 -3
  58. package/dist-cjs/lib/shapes/shared/ShapeFill.js +2 -2
  59. package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
  60. package/dist-cjs/lib/shapes/shared/interpolate-props.js +3 -3
  61. package/dist-cjs/lib/shapes/shared/interpolate-props.js.map +2 -2
  62. package/dist-cjs/lib/shapes/shared/{useForceSolid.js → useEfficientZoomThreshold.js} +10 -7
  63. package/dist-cjs/lib/shapes/shared/useEfficientZoomThreshold.js.map +7 -0
  64. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +1 -1
  65. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
  66. package/dist-cjs/lib/shapes/text/RichTextArea.js +5 -0
  67. package/dist-cjs/lib/shapes/text/RichTextArea.js.map +2 -2
  68. package/dist-cjs/lib/shapes/text/TextShapeUtil.js +5 -2
  69. package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
  70. package/dist-cjs/lib/shapes/text/toolStates/Idle.js +4 -10
  71. package/dist-cjs/lib/shapes/text/toolStates/Idle.js.map +2 -2
  72. package/dist-cjs/lib/shapes/text/toolStates/Pointing.js +7 -5
  73. package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
  74. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +1 -1
  75. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +2 -2
  76. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +4 -5
  77. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  78. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +2 -4
  79. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  80. package/dist-cjs/lib/tools/HandTool/HandTool.js +3 -5
  81. package/dist-cjs/lib/tools/HandTool/HandTool.js.map +2 -2
  82. package/dist-cjs/lib/tools/HandTool/childStates/Dragging.js +3 -2
  83. package/dist-cjs/lib/tools/HandTool/childStates/Dragging.js.map +2 -2
  84. package/dist-cjs/lib/tools/HandTool/childStates/Pointing.js +1 -1
  85. package/dist-cjs/lib/tools/HandTool/childStates/Pointing.js.map +2 -2
  86. package/dist-cjs/lib/tools/LaserTool/childStates/Lasering.js +1 -1
  87. package/dist-cjs/lib/tools/LaserTool/childStates/Lasering.js.map +2 -2
  88. package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js +9 -7
  89. package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js.map +2 -2
  90. package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js +6 -5
  91. package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js.map +2 -2
  92. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js +4 -6
  93. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js.map +2 -2
  94. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js +1 -1
  95. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
  96. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.js +1 -1
  97. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.js.map +2 -2
  98. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js +1 -1
  99. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js.map +2 -2
  100. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.js +2 -1
  101. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.js.map +2 -2
  102. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.js +1 -1
  103. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.js.map +2 -2
  104. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +7 -5
  105. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  106. package/dist-cjs/lib/tools/SelectTool/childStates/EditingShape.js +38 -11
  107. package/dist-cjs/lib/tools/SelectTool/childStates/EditingShape.js.map +2 -2
  108. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +42 -50
  109. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
  110. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js +6 -6
  111. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
  112. package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js +1 -1
  113. package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js.map +2 -2
  114. package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js +4 -14
  115. package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js.map +2 -2
  116. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js +1 -1
  117. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js.map +2 -2
  118. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js +1 -1
  119. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js.map +2 -2
  120. package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js +2 -2
  121. package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js.map +2 -2
  122. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js +4 -13
  123. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js.map +2 -2
  124. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +5 -6
  125. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  126. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js +2 -3
  127. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js.map +2 -2
  128. package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js +7 -6
  129. package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js.map +2 -2
  130. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +13 -11
  131. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  132. package/dist-cjs/lib/tools/SelectTool/selectHelpers.js +15 -4
  133. package/dist-cjs/lib/tools/SelectTool/selectHelpers.js.map +2 -2
  134. package/dist-cjs/lib/tools/ZoomTool/ZoomTool.js +1 -1
  135. package/dist-cjs/lib/tools/ZoomTool/ZoomTool.js.map +2 -2
  136. package/dist-cjs/lib/tools/ZoomTool/childStates/Pointing.js +3 -3
  137. package/dist-cjs/lib/tools/ZoomTool/childStates/Pointing.js.map +2 -2
  138. package/dist-cjs/lib/tools/ZoomTool/childStates/ZoomBrushing.js +5 -6
  139. package/dist-cjs/lib/tools/ZoomTool/childStates/ZoomBrushing.js.map +2 -2
  140. package/dist-cjs/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.js +1 -3
  141. package/dist-cjs/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.js.map +2 -2
  142. package/dist-cjs/lib/tools/selection-logic/selectOnCanvasPointerUp.js +1 -1
  143. package/dist-cjs/lib/tools/selection-logic/selectOnCanvasPointerUp.js.map +2 -2
  144. package/dist-cjs/lib/tools/selection-logic/updateHoveredShapeId.js +1 -1
  145. package/dist-cjs/lib/tools/selection-logic/updateHoveredShapeId.js.map +2 -2
  146. package/dist-cjs/lib/ui/TldrawUi.js +2 -2
  147. package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
  148. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.js +3 -9
  149. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.js.map +2 -2
  150. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js +1 -3
  151. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js.map +2 -2
  152. package/dist-cjs/lib/ui/components/CursorChatBubble.js +1 -1
  153. package/dist-cjs/lib/ui/components/CursorChatBubble.js.map +2 -2
  154. package/dist-cjs/lib/ui/components/DefaultDebugPanel.js +1 -21
  155. package/dist-cjs/lib/ui/components/DefaultDebugPanel.js.map +2 -2
  156. package/dist-cjs/lib/ui/components/HelperButtons/BackToContent.js +1 -1
  157. package/dist-cjs/lib/ui/components/HelperButtons/BackToContent.js.map +2 -2
  158. package/dist-cjs/lib/ui/components/HelperButtons/StopFollowing.js.map +2 -2
  159. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +1 -1
  160. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
  161. package/dist-cjs/lib/ui/components/OfflineIndicator/OfflineIndicator.js +2 -15
  162. package/dist-cjs/lib/ui/components/OfflineIndicator/OfflineIndicator.js.map +3 -3
  163. package/dist-cjs/lib/ui/components/PageMenu/PageItemInput.js +3 -1
  164. package/dist-cjs/lib/ui/components/PageMenu/PageItemInput.js.map +2 -2
  165. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js +6 -0
  166. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js.map +2 -2
  167. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbar.js +1 -1
  168. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbar.js.map +2 -2
  169. package/dist-cjs/lib/ui/components/Toolbar/DefaultRichTextToolbar.js +1 -1
  170. package/dist-cjs/lib/ui/components/Toolbar/DefaultRichTextToolbar.js.map +2 -2
  171. package/dist-cjs/lib/ui/components/TopPanel/CenteredTopPanelContainer.js.map +1 -1
  172. package/dist-cjs/lib/ui/components/menu-items.js +3 -1
  173. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  174. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +3 -1
  175. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  176. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +1 -1
  177. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  178. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +149 -93
  179. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  180. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuActionCheckboxItem.js.map +2 -2
  181. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuActionItem.js.map +2 -2
  182. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +14 -7
  183. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  184. package/dist-cjs/lib/ui/context/actions.js +6 -6
  185. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  186. package/dist-cjs/lib/ui/context/components.js +1 -2
  187. package/dist-cjs/lib/ui/context/components.js.map +2 -2
  188. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +2 -2
  189. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
  190. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +2 -2
  191. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js.map +2 -2
  192. package/dist-cjs/lib/ui/hooks/useTools.js +4 -5
  193. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  194. package/dist-cjs/lib/ui/version.js +3 -3
  195. package/dist-cjs/lib/ui/version.js.map +1 -1
  196. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js +8 -6
  197. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js.map +2 -2
  198. package/dist-cjs/lib/{tools/selection-logic/getShouldEnterCropModeOnPointerDown.js → utils/test-helpers.js} +21 -8
  199. package/dist-cjs/lib/utils/test-helpers.js.map +7 -0
  200. package/dist-cjs/lib/utils/text/richText.js +15 -19
  201. package/dist-cjs/lib/utils/text/richText.js.map +3 -3
  202. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js +7 -2
  203. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js.map +2 -2
  204. package/dist-esm/index.d.mts +297 -237
  205. package/dist-esm/index.mjs +14 -5
  206. package/dist-esm/index.mjs.map +2 -2
  207. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs +2 -2
  208. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs.map +2 -2
  209. package/dist-esm/lib/defaultEmbedDefinitions.mjs +1 -1
  210. package/dist-esm/lib/defaultEmbedDefinitions.mjs.map +2 -2
  211. package/dist-esm/lib/defaultExternalContentHandlers.mjs +5 -5
  212. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  213. package/dist-esm/lib/defaultSideEffects.mjs +6 -1
  214. package/dist-esm/lib/defaultSideEffects.mjs.map +2 -2
  215. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +15 -15
  216. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  217. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +1 -1
  218. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +2 -2
  219. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs +1 -1
  220. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
  221. package/dist-esm/lib/shapes/arrow/elbow/getElbowArrowInfo.mjs +1 -1
  222. package/dist-esm/lib/shapes/arrow/elbow/getElbowArrowInfo.mjs.map +2 -2
  223. package/dist-esm/lib/shapes/arrow/toolStates/Idle.mjs +4 -10
  224. package/dist-esm/lib/shapes/arrow/toolStates/Idle.mjs.map +2 -2
  225. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +7 -4
  226. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  227. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +1 -1
  228. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  229. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +30 -25
  230. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
  231. package/dist-esm/lib/shapes/draw/getPath.mjs +21 -11
  232. package/dist-esm/lib/shapes/draw/getPath.mjs.map +2 -2
  233. package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs +83 -86
  234. package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs.map +3 -3
  235. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +6 -0
  236. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
  237. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +6 -5
  238. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  239. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +147 -142
  240. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  241. package/dist-esm/lib/shapes/geo/toolStates/Idle.mjs +5 -10
  242. package/dist-esm/lib/shapes/geo/toolStates/Idle.mjs.map +2 -2
  243. package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs +3 -3
  244. package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
  245. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +24 -22
  246. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
  247. package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs +3 -3
  248. package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
  249. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +7 -12
  250. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  251. package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs +5 -10
  252. package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs.map +2 -2
  253. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs +4 -3
  254. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs.map +2 -2
  255. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +14 -2
  256. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  257. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +12 -4
  258. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  259. package/dist-esm/lib/shapes/shared/ShapeFill.mjs +2 -2
  260. package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
  261. package/dist-esm/lib/shapes/shared/interpolate-props.mjs +4 -4
  262. package/dist-esm/lib/shapes/shared/interpolate-props.mjs.map +2 -2
  263. package/dist-esm/lib/shapes/shared/useEfficientZoomThreshold.mjs +12 -0
  264. package/dist-esm/lib/shapes/shared/useEfficientZoomThreshold.mjs.map +7 -0
  265. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +1 -1
  266. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  267. package/dist-esm/lib/shapes/text/RichTextArea.mjs +5 -0
  268. package/dist-esm/lib/shapes/text/RichTextArea.mjs.map +2 -2
  269. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +5 -2
  270. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
  271. package/dist-esm/lib/shapes/text/toolStates/Idle.mjs +4 -10
  272. package/dist-esm/lib/shapes/text/toolStates/Idle.mjs.map +2 -2
  273. package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs +7 -5
  274. package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
  275. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +1 -1
  276. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +2 -2
  277. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +4 -5
  278. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  279. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +2 -4
  280. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  281. package/dist-esm/lib/tools/HandTool/HandTool.mjs +3 -5
  282. package/dist-esm/lib/tools/HandTool/HandTool.mjs.map +2 -2
  283. package/dist-esm/lib/tools/HandTool/childStates/Dragging.mjs +3 -2
  284. package/dist-esm/lib/tools/HandTool/childStates/Dragging.mjs.map +2 -2
  285. package/dist-esm/lib/tools/HandTool/childStates/Pointing.mjs +1 -1
  286. package/dist-esm/lib/tools/HandTool/childStates/Pointing.mjs.map +2 -2
  287. package/dist-esm/lib/tools/LaserTool/childStates/Lasering.mjs +1 -1
  288. package/dist-esm/lib/tools/LaserTool/childStates/Lasering.mjs.map +2 -2
  289. package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs +9 -7
  290. package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs.map +2 -2
  291. package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs +6 -5
  292. package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs.map +2 -2
  293. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs +4 -6
  294. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs.map +2 -2
  295. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs +1 -1
  296. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
  297. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.mjs +1 -1
  298. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.mjs.map +2 -2
  299. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs +1 -1
  300. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs.map +2 -2
  301. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.mjs +2 -1
  302. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.mjs.map +2 -2
  303. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.mjs +1 -1
  304. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.mjs.map +2 -2
  305. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +7 -5
  306. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  307. package/dist-esm/lib/tools/SelectTool/childStates/EditingShape.mjs +38 -11
  308. package/dist-esm/lib/tools/SelectTool/childStates/EditingShape.mjs.map +2 -2
  309. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +43 -51
  310. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
  311. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs +6 -6
  312. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
  313. package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs +1 -1
  314. package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs.map +2 -2
  315. package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs +5 -15
  316. package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs.map +2 -2
  317. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs +1 -1
  318. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs.map +2 -2
  319. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs +1 -1
  320. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs.map +2 -2
  321. package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs +2 -2
  322. package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs.map +2 -2
  323. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs +4 -13
  324. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs.map +2 -2
  325. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +5 -6
  326. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  327. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs +2 -3
  328. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs.map +2 -2
  329. package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs +7 -6
  330. package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs.map +2 -2
  331. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +13 -11
  332. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  333. package/dist-esm/lib/tools/SelectTool/selectHelpers.mjs +17 -4
  334. package/dist-esm/lib/tools/SelectTool/selectHelpers.mjs.map +2 -2
  335. package/dist-esm/lib/tools/ZoomTool/ZoomTool.mjs +1 -1
  336. package/dist-esm/lib/tools/ZoomTool/ZoomTool.mjs.map +2 -2
  337. package/dist-esm/lib/tools/ZoomTool/childStates/Pointing.mjs +3 -3
  338. package/dist-esm/lib/tools/ZoomTool/childStates/Pointing.mjs.map +2 -2
  339. package/dist-esm/lib/tools/ZoomTool/childStates/ZoomBrushing.mjs +5 -6
  340. package/dist-esm/lib/tools/ZoomTool/childStates/ZoomBrushing.mjs.map +2 -2
  341. package/dist-esm/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.mjs +1 -3
  342. package/dist-esm/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.mjs.map +2 -2
  343. package/dist-esm/lib/tools/selection-logic/selectOnCanvasPointerUp.mjs +1 -1
  344. package/dist-esm/lib/tools/selection-logic/selectOnCanvasPointerUp.mjs.map +2 -2
  345. package/dist-esm/lib/tools/selection-logic/updateHoveredShapeId.mjs +1 -1
  346. package/dist-esm/lib/tools/selection-logic/updateHoveredShapeId.mjs.map +2 -2
  347. package/dist-esm/lib/ui/TldrawUi.mjs +2 -2
  348. package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
  349. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.mjs +2 -8
  350. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.mjs.map +2 -2
  351. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs +1 -3
  352. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs.map +2 -2
  353. package/dist-esm/lib/ui/components/CursorChatBubble.mjs +1 -1
  354. package/dist-esm/lib/ui/components/CursorChatBubble.mjs.map +2 -2
  355. package/dist-esm/lib/ui/components/DefaultDebugPanel.mjs +3 -30
  356. package/dist-esm/lib/ui/components/DefaultDebugPanel.mjs.map +2 -2
  357. package/dist-esm/lib/ui/components/HelperButtons/BackToContent.mjs +1 -1
  358. package/dist-esm/lib/ui/components/HelperButtons/BackToContent.mjs.map +2 -2
  359. package/dist-esm/lib/ui/components/HelperButtons/StopFollowing.mjs.map +2 -2
  360. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +1 -1
  361. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
  362. package/dist-esm/lib/ui/components/OfflineIndicator/OfflineIndicator.mjs +3 -6
  363. package/dist-esm/lib/ui/components/OfflineIndicator/OfflineIndicator.mjs.map +2 -2
  364. package/dist-esm/lib/ui/components/PageMenu/PageItemInput.mjs +3 -1
  365. package/dist-esm/lib/ui/components/PageMenu/PageItemInput.mjs.map +2 -2
  366. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs +6 -0
  367. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs.map +2 -2
  368. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbar.mjs +1 -1
  369. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbar.mjs.map +2 -2
  370. package/dist-esm/lib/ui/components/Toolbar/DefaultRichTextToolbar.mjs +1 -1
  371. package/dist-esm/lib/ui/components/Toolbar/DefaultRichTextToolbar.mjs.map +2 -2
  372. package/dist-esm/lib/ui/components/TopPanel/CenteredTopPanelContainer.mjs.map +1 -1
  373. package/dist-esm/lib/ui/components/menu-items.mjs +3 -1
  374. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  375. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +3 -1
  376. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  377. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +2 -2
  378. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  379. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +157 -95
  380. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  381. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuActionCheckboxItem.mjs.map +2 -2
  382. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuActionItem.mjs.map +2 -2
  383. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +15 -8
  384. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  385. package/dist-esm/lib/ui/context/actions.mjs +6 -6
  386. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  387. package/dist-esm/lib/ui/context/components.mjs +1 -2
  388. package/dist-esm/lib/ui/context/components.mjs.map +2 -2
  389. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +2 -2
  390. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
  391. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs +2 -2
  392. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs.map +2 -2
  393. package/dist-esm/lib/ui/hooks/useTools.mjs +4 -5
  394. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  395. package/dist-esm/lib/ui/version.mjs +3 -3
  396. package/dist-esm/lib/ui/version.mjs.map +1 -1
  397. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs +9 -6
  398. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs.map +2 -2
  399. package/dist-esm/lib/utils/test-helpers.mjs +21 -0
  400. package/dist-esm/lib/utils/test-helpers.mjs.map +7 -0
  401. package/dist-esm/lib/utils/text/richText.mjs +12 -5
  402. package/dist-esm/lib/utils/text/richText.mjs.map +2 -2
  403. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs +8 -2
  404. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs.map +2 -2
  405. package/package.json +18 -16
  406. package/src/index.ts +6 -2
  407. package/src/lib/Tldraw.test.tsx +46 -1
  408. package/src/lib/canvas/TldrawSelectionForeground.tsx +2 -2
  409. package/src/lib/defaultEmbedDefinitions.ts +2 -1
  410. package/src/lib/defaultExternalContentHandlers.ts +10 -10
  411. package/src/lib/defaultSideEffects.ts +6 -1
  412. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +40 -133
  413. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +8 -8
  414. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +15 -15
  415. package/src/lib/shapes/arrow/arrow-types.ts +2 -0
  416. package/src/lib/shapes/arrow/arrowLabel.ts +1 -1
  417. package/src/lib/shapes/arrow/arrowTargetState.ts +1 -1
  418. package/src/lib/shapes/arrow/elbow/getElbowArrowInfo.test.ts +80 -0
  419. package/src/lib/shapes/arrow/elbow/getElbowArrowInfo.tsx +1 -1
  420. package/src/lib/shapes/arrow/toolStates/Idle.tsx +4 -14
  421. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +7 -4
  422. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +1 -1
  423. package/src/lib/shapes/draw/DrawShapeUtil.test.ts +146 -0
  424. package/src/lib/shapes/draw/DrawShapeUtil.tsx +33 -27
  425. package/src/lib/shapes/draw/getPath.ts +31 -10
  426. package/src/lib/shapes/draw/toolStates/Drawing.ts +96 -86
  427. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +7 -0
  428. package/src/lib/shapes/frame/FrameShapeUtil.tsx +10 -4
  429. package/src/lib/shapes/geo/GeoShapeUtil.tsx +228 -176
  430. package/src/lib/shapes/geo/toolStates/Idle.ts +5 -15
  431. package/src/lib/shapes/geo/toolStates/Pointing.ts +3 -3
  432. package/src/lib/shapes/highlight/HighlightShapeUtil.test.ts +146 -0
  433. package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +27 -24
  434. package/src/lib/shapes/line/toolStates/Pointing.ts +3 -3
  435. package/src/lib/shapes/note/NoteShapeUtil.tsx +9 -10
  436. package/src/lib/shapes/note/noteCloning.test.ts +3 -1
  437. package/src/lib/shapes/note/toolStates/Pointing.ts +5 -10
  438. package/src/lib/shapes/shared/HyperlinkButton.tsx +4 -3
  439. package/src/lib/shapes/shared/PlainTextLabel.tsx +10 -1
  440. package/src/lib/shapes/shared/RichTextLabel.tsx +12 -3
  441. package/src/lib/shapes/shared/ShapeFill.tsx +2 -2
  442. package/src/lib/shapes/shared/interpolate-props.ts +4 -4
  443. package/src/lib/shapes/shared/useEfficientZoomThreshold.ts +10 -0
  444. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +1 -1
  445. package/src/lib/shapes/text/RichTextArea.tsx +5 -0
  446. package/src/lib/shapes/text/TextShapeUtil.tsx +5 -0
  447. package/src/lib/shapes/text/toolStates/Idle.ts +4 -14
  448. package/src/lib/shapes/text/toolStates/Pointing.ts +7 -7
  449. package/src/lib/shapes/video/VideoShapeUtil.tsx +2 -1
  450. package/src/lib/tools/EraserTool/childStates/Erasing.ts +4 -5
  451. package/src/lib/tools/EraserTool/childStates/Pointing.ts +2 -4
  452. package/src/lib/tools/HandTool/HandTool.ts +3 -5
  453. package/src/lib/tools/HandTool/childStates/Dragging.ts +3 -2
  454. package/src/lib/tools/HandTool/childStates/Pointing.ts +1 -1
  455. package/src/lib/tools/LaserTool/childStates/Lasering.ts +1 -1
  456. package/src/lib/tools/SelectTool/DragAndDropManager.ts +12 -7
  457. package/src/lib/tools/SelectTool/childStates/Brushing.ts +6 -5
  458. package/src/lib/tools/SelectTool/childStates/Crop/children/Cropping.ts +7 -6
  459. package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +1 -1
  460. package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.ts +1 -1
  461. package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.ts +1 -1
  462. package/src/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.ts +2 -1
  463. package/src/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.ts +1 -1
  464. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +7 -5
  465. package/src/lib/tools/SelectTool/childStates/EditingShape.ts +55 -12
  466. package/src/lib/tools/SelectTool/childStates/Idle.ts +58 -71
  467. package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +6 -7
  468. package/src/lib/tools/SelectTool/childStates/PointingCanvas.ts +1 -1
  469. package/src/lib/tools/SelectTool/childStates/PointingHandle.ts +5 -5
  470. package/src/lib/tools/SelectTool/childStates/PointingResizeHandle.ts +1 -1
  471. package/src/lib/tools/SelectTool/childStates/PointingRotateHandle.ts +1 -1
  472. package/src/lib/tools/SelectTool/childStates/PointingSelection.ts +2 -2
  473. package/src/lib/tools/SelectTool/childStates/PointingShape.ts +4 -14
  474. package/src/lib/tools/SelectTool/childStates/Resizing.ts +6 -6
  475. package/src/lib/tools/SelectTool/childStates/Rotating.ts +2 -3
  476. package/src/lib/tools/SelectTool/childStates/ScribbleBrushing.ts +7 -6
  477. package/src/lib/tools/SelectTool/childStates/Translating.ts +15 -12
  478. package/src/lib/tools/SelectTool/selectHelpers.ts +39 -4
  479. package/src/lib/tools/ZoomTool/ZoomTool.ts +1 -1
  480. package/src/lib/tools/ZoomTool/childStates/Pointing.ts +3 -3
  481. package/src/lib/tools/ZoomTool/childStates/ZoomBrushing.ts +5 -6
  482. package/src/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.ts +1 -3
  483. package/src/lib/tools/selection-logic/selectOnCanvasPointerUp.ts +1 -1
  484. package/src/lib/tools/selection-logic/updateHoveredShapeId.ts +1 -1
  485. package/src/lib/ui/TldrawUi.tsx +5 -2
  486. package/src/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.tsx +1 -9
  487. package/src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx +1 -3
  488. package/src/lib/ui/components/CursorChatBubble.tsx +2 -2
  489. package/src/lib/ui/components/DefaultDebugPanel.tsx +3 -42
  490. package/src/lib/ui/components/HelperButtons/BackToContent.tsx +1 -1
  491. package/src/lib/ui/components/HelperButtons/StopFollowing.tsx +2 -2
  492. package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +1 -1
  493. package/src/lib/ui/components/OfflineIndicator/OfflineIndicator.tsx +6 -5
  494. package/src/lib/ui/components/PageMenu/PageItemInput.tsx +3 -1
  495. package/src/lib/ui/components/SharePanel/PeopleMenu.tsx +8 -0
  496. package/src/lib/ui/components/Toolbar/DefaultImageToolbar.tsx +1 -1
  497. package/src/lib/ui/components/Toolbar/DefaultRichTextToolbar.tsx +1 -1
  498. package/src/lib/ui/components/TopPanel/CenteredTopPanelContainer.tsx +1 -1
  499. package/src/lib/ui/components/menu-items.tsx +3 -1
  500. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +5 -3
  501. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +2 -2
  502. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +208 -113
  503. package/src/lib/ui/components/primitives/menus/TldrawUiMenuActionCheckboxItem.tsx +1 -1
  504. package/src/lib/ui/components/primitives/menus/TldrawUiMenuActionItem.tsx +1 -1
  505. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +7 -4
  506. package/src/lib/ui/context/actions.tsx +6 -6
  507. package/src/lib/ui/context/components.tsx +1 -2
  508. package/src/lib/ui/hooks/useClipboardEvents.ts +2 -2
  509. package/src/lib/ui/hooks/useKeyboardShortcuts.ts +2 -2
  510. package/src/lib/ui/hooks/useTools.tsx +4 -5
  511. package/src/lib/ui/version.ts +3 -3
  512. package/src/lib/ui.css +27 -23
  513. package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +12 -48
  514. package/src/lib/utils/excalidraw/putExcalidrawContent.ts +11 -6
  515. package/src/lib/utils/test-helpers.ts +62 -0
  516. package/src/lib/utils/text/richText.ts +13 -8
  517. package/src/lib/utils/tldr/buildFromV1Document.ts +9 -2
  518. package/src/test/Editor.test.tsx +40 -29
  519. package/src/test/EraserTool.test.ts +10 -12
  520. package/src/test/TestEditor.ts +48 -47
  521. package/src/test/TldrawEditor.test.tsx +6 -4
  522. package/src/test/__snapshots__/drawing.test.ts.snap +3 -1257
  523. package/src/test/__snapshots__/resizing.test.ts.snap +3 -12
  524. package/src/test/arrows-megabus.test.tsx +1 -1
  525. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +10 -10
  526. package/src/test/commands/cameraState.test.ts +299 -0
  527. package/src/test/commands/putContent.test.ts +79 -1
  528. package/src/test/commands/setCamera.test.ts +13 -11
  529. package/src/test/commands/stackShapes.test.ts +34 -8
  530. package/src/test/commands/zoomToBounds.test.ts +19 -3
  531. package/src/test/commands/zoomToSelection.test.ts +14 -3
  532. package/src/test/custom-clipping.test.ts +16 -9
  533. package/src/test/drawing.test.ts +17 -10
  534. package/src/test/flipShapes.test.ts +33 -0
  535. package/src/test/frames.test.ts +92 -0
  536. package/src/test/groups.test.tsx +1 -1
  537. package/src/test/modifiers.test.ts +6 -6
  538. package/src/test/resizing.test.ts +7 -9
  539. package/src/test/selection-omnibus.test.ts +2 -2
  540. package/src/test/spacebarPanning.test.ts +28 -10
  541. package/src/test/test-jsx.tsx +3 -0
  542. package/src/test/ui/BackToContent.test.tsx +111 -0
  543. package/tldraw.css +41 -35
  544. package/dist-cjs/lib/shapes/shared/useForceSolid.js.map +0 -7
  545. package/dist-cjs/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.js.map +0 -7
  546. package/dist-cjs/lib/ui/components/TopPanel/DefaultTopPanel.js +0 -32
  547. package/dist-cjs/lib/ui/components/TopPanel/DefaultTopPanel.js.map +0 -7
  548. package/dist-cjs/lib/utils/text/textDirection.js +0 -51
  549. package/dist-cjs/lib/utils/text/textDirection.js.map +0 -7
  550. package/dist-esm/lib/shapes/shared/useForceSolid.mjs +0 -9
  551. package/dist-esm/lib/shapes/shared/useForceSolid.mjs.map +0 -7
  552. package/dist-esm/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.mjs +0 -8
  553. package/dist-esm/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.mjs.map +0 -7
  554. package/dist-esm/lib/ui/components/TopPanel/DefaultTopPanel.mjs +0 -12
  555. package/dist-esm/lib/ui/components/TopPanel/DefaultTopPanel.mjs.map +0 -7
  556. package/dist-esm/lib/utils/text/textDirection.mjs +0 -31
  557. package/dist-esm/lib/utils/text/textDirection.mjs.map +0 -7
  558. package/src/lib/shapes/shared/useForceSolid.ts +0 -6
  559. package/src/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.ts +0 -10
  560. package/src/lib/ui/components/TopPanel/DefaultTopPanel.tsx +0 -10
  561. package/src/lib/utils/text/textDirection.ts +0 -32
@@ -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
  }}
@@ -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 */
@@ -313,7 +313,7 @@ export function getArrowLabelDefaultPosition(editor: Editor, shape: TLArrowShape
313
313
  export function isOverArrowLabel(editor: Editor, shape: TLShape) {
314
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
 
@@ -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)
@@ -1,4 +1,5 @@
1
1
  import { StateNode, TLKeyboardEventInfo, TLPointerEventInfo, TLShapeId } from '@tldraw/editor'
2
+ import { startEditingShapeWithRichText } from '../../../tools/SelectTool/selectHelpers'
2
3
  import { ArrowShapeUtil } from '../ArrowShapeUtil'
3
4
  import { clearArrowTargetState, updateArrowTargetState } from '../arrowTargetState'
4
5
 
@@ -40,20 +41,9 @@ export class Idle extends StateNode {
40
41
  override onKeyUp(info: TLKeyboardEventInfo) {
41
42
  this.update()
42
43
  if (info.key === 'Enter') {
43
- if (this.editor.getIsReadonly()) return null
44
44
  const onlySelectedShape = this.editor.getOnlySelectedShape()
45
- // If the only selected shape is editable, start editing it
46
- if (
47
- onlySelectedShape &&
48
- this.editor.getShapeUtil(onlySelectedShape).canEdit(onlySelectedShape)
49
- ) {
50
- this.editor.setCurrentTool('select')
51
- this.editor.setEditingShape(onlySelectedShape.id)
52
- this.editor.root.getCurrent()?.transition('editing_shape', {
53
- ...info,
54
- target: 'shape',
55
- shape: onlySelectedShape,
56
- })
45
+ if (this.editor.canEditShape(onlySelectedShape)) {
46
+ startEditingShapeWithRichText(this.editor, onlySelectedShape, { selectAll: true })
57
47
  }
58
48
  }
59
49
  }
@@ -63,7 +53,7 @@ export class Idle extends StateNode {
63
53
 
64
54
  const targetState = updateArrowTargetState({
65
55
  editor: this.editor,
66
- pointInPageSpace: this.editor.inputs.currentPagePoint,
56
+ pointInPageSpace: this.editor.inputs.getCurrentPagePoint(),
67
57
  arrow: undefined,
68
58
  isPrecise: this.isPrecise,
69
59
  currentBinding: undefined,
@@ -18,7 +18,7 @@ export class Pointing extends StateNode {
18
18
 
19
19
  const targetState = updateArrowTargetState({
20
20
  editor: this.editor,
21
- pointInPageSpace: this.editor.inputs.currentPagePoint,
21
+ pointInPageSpace: this.editor.inputs.getCurrentPagePoint(),
22
22
  arrow: undefined,
23
23
  isPrecise: this.isPrecise,
24
24
  currentBinding: undefined,
@@ -43,7 +43,7 @@ export class Pointing extends StateNode {
43
43
  }
44
44
 
45
45
  override onPointerMove() {
46
- if (this.editor.inputs.isDragging) {
46
+ if (this.editor.inputs.getIsDragging()) {
47
47
  if (!this.shape) {
48
48
  this.createArrowShape()
49
49
  }
@@ -90,7 +90,7 @@ export class Pointing extends StateNode {
90
90
  }
91
91
 
92
92
  createArrowShape() {
93
- const { originPagePoint } = this.editor.inputs
93
+ const originPagePoint = this.editor.inputs.getOriginPagePoint()
94
94
 
95
95
  const id = createShapeId()
96
96
 
@@ -159,7 +159,10 @@ export class Pointing extends StateNode {
159
159
  {
160
160
  const util = this.editor.getShapeUtil<TLArrowShape>('arrow')
161
161
  const initial = this.shape
162
- const point = this.editor.getPointInShapeSpace(shape, this.editor.inputs.currentPagePoint)
162
+ const point = this.editor.getPointInShapeSpace(
163
+ shape,
164
+ this.editor.inputs.getCurrentPagePoint()
165
+ )
163
166
  const endHandle = handles.find((h) => h.id === 'end')!
164
167
  const change = util.onHandleDrag?.(this.editor.getShape(shape)!, {
165
168
  handle: { ...endHandle, x: point.x, y: point.y },
@@ -139,7 +139,7 @@ export function BookmarkShapeComponent({
139
139
 
140
140
  const markAsHandledOnShiftKey = useCallback<PointerEventHandler>(
141
141
  (e) => {
142
- if (!editor.inputs.shiftKey) editor.markEventAsHandled(e)
142
+ if (!editor.inputs.getShiftKey()) editor.markEventAsHandled(e)
143
143
  },
144
144
  [editor]
145
145
  )
@@ -0,0 +1,146 @@
1
+ import { createShapeId, TLDrawShape } from '@tldraw/editor'
2
+ import { TestEditor } from '../../../test/TestEditor'
3
+ import { createDrawSegments, pointsToBase64 } from '../../utils/test-helpers'
4
+
5
+ let editor: TestEditor
6
+
7
+ beforeEach(() => {
8
+ editor = new TestEditor()
9
+ })
10
+
11
+ afterEach(() => {
12
+ editor?.dispose()
13
+ })
14
+
15
+ describe('DrawShapeUtil dot detection', () => {
16
+ const shapeId = createShapeId('test-draw')
17
+
18
+ function createDrawShape(segments: TLDrawShape['props']['segments']): TLDrawShape {
19
+ editor.createShapes([
20
+ {
21
+ id: shapeId,
22
+ type: 'draw',
23
+ props: { segments },
24
+ },
25
+ ])
26
+ return editor.getShape(shapeId) as TLDrawShape
27
+ }
28
+
29
+ describe('getIsDot behavior via hideResizeHandles', () => {
30
+ it('treats a shape with one segment and zero points as a dot', () => {
31
+ const shape = createDrawShape([{ type: 'free', path: '' }])
32
+ const util = editor.getShapeUtil('draw')
33
+ expect(util.hideResizeHandles(shape)).toBe(true)
34
+ })
35
+
36
+ it('treats a shape with one segment and one point as a dot', () => {
37
+ const shape = createDrawShape(createDrawSegments([[{ x: 0, y: 0, z: 0.5 }]]))
38
+ const util = editor.getShapeUtil('draw')
39
+ expect(util.hideResizeHandles(shape)).toBe(true)
40
+ })
41
+
42
+ it('treats a shape with one segment and two points as NOT a dot', () => {
43
+ const shape = createDrawShape(
44
+ createDrawSegments([
45
+ [
46
+ { x: 0, y: 0, z: 0.5 },
47
+ { x: 10, y: 10, z: 0.5 },
48
+ ],
49
+ ])
50
+ )
51
+ const util = editor.getShapeUtil('draw')
52
+ expect(util.hideResizeHandles(shape)).toBe(false)
53
+ })
54
+
55
+ it('treats a shape with one segment and many points as NOT a dot', () => {
56
+ const shape = createDrawShape(
57
+ createDrawSegments([
58
+ [
59
+ { x: 0, y: 0, z: 0.5 },
60
+ { x: 10, y: 10, z: 0.5 },
61
+ { x: 20, y: 5, z: 0.5 },
62
+ { x: 30, y: 15, z: 0.5 },
63
+ ],
64
+ ])
65
+ )
66
+ const util = editor.getShapeUtil('draw')
67
+ expect(util.hideResizeHandles(shape)).toBe(false)
68
+ })
69
+
70
+ it('treats a shape with multiple segments as NOT a dot', () => {
71
+ const shape = createDrawShape(
72
+ createDrawSegments([[{ x: 0, y: 0, z: 0.5 }], [{ x: 10, y: 10, z: 0.5 }]])
73
+ )
74
+ const util = editor.getShapeUtil('draw')
75
+ expect(util.hideResizeHandles(shape)).toBe(false)
76
+ })
77
+ })
78
+
79
+ describe('hideRotateHandle mirrors hideResizeHandles for dots', () => {
80
+ it('hides rotate handle for dots', () => {
81
+ const shape = createDrawShape(createDrawSegments([[{ x: 0, y: 0, z: 0.5 }]]))
82
+ const util = editor.getShapeUtil('draw')
83
+ expect(util.hideRotateHandle(shape)).toBe(true)
84
+ })
85
+
86
+ it('shows rotate handle for non-dots', () => {
87
+ const shape = createDrawShape(
88
+ createDrawSegments([
89
+ [
90
+ { x: 0, y: 0, z: 0.5 },
91
+ { x: 10, y: 10, z: 0.5 },
92
+ ],
93
+ ])
94
+ )
95
+ const util = editor.getShapeUtil('draw')
96
+ expect(util.hideRotateHandle(shape)).toBe(false)
97
+ })
98
+ })
99
+
100
+ describe('hideSelectionBoundsFg mirrors hideResizeHandles for dots', () => {
101
+ it('hides selection bounds for dots', () => {
102
+ const shape = createDrawShape(createDrawSegments([[{ x: 0, y: 0, z: 0.5 }]]))
103
+ const util = editor.getShapeUtil('draw')
104
+ expect(util.hideSelectionBoundsFg(shape)).toBe(true)
105
+ })
106
+
107
+ it('shows selection bounds for non-dots', () => {
108
+ const shape = createDrawShape(
109
+ createDrawSegments([
110
+ [
111
+ { x: 0, y: 0, z: 0.5 },
112
+ { x: 10, y: 10, z: 0.5 },
113
+ ],
114
+ ])
115
+ )
116
+ const util = editor.getShapeUtil('draw')
117
+ expect(util.hideSelectionBoundsFg(shape)).toBe(false)
118
+ })
119
+ })
120
+
121
+ describe('base64 encoding boundary conditions', () => {
122
+ it('correctly handles the boundary at exactly 24 base64 characters (2 points)', () => {
123
+ // First point is 16 base64 chars (Float32), delta points are 8 chars each (Float16)
124
+ // 2 points = 24 characters, which should NOT be a dot
125
+ const twoPointsBase64 = pointsToBase64([
126
+ { x: 0, y: 0, z: 0.5 },
127
+ { x: 1, y: 1, z: 0.5 },
128
+ ])
129
+ expect(twoPointsBase64.length).toBe(24)
130
+
131
+ const shape = createDrawShape([{ type: 'free', path: twoPointsBase64 }])
132
+ const util = editor.getShapeUtil('draw')
133
+ expect(util.hideResizeHandles(shape)).toBe(false)
134
+ })
135
+
136
+ it('correctly handles the boundary at exactly 16 base64 characters (1 point)', () => {
137
+ // 1 point = 16 characters (Float32 first point), which should be a dot
138
+ const onePointBase64 = pointsToBase64([{ x: 0, y: 0, z: 0.5 }])
139
+ expect(onePointBase64.length).toBe(16)
140
+
141
+ const shape = createDrawShape([{ type: 'free', path: onePointBase64 }])
142
+ const util = editor.getShapeUtil('draw')
143
+ expect(util.hideResizeHandles(shape)).toBe(true)
144
+ })
145
+ })
146
+ })
@@ -8,7 +8,6 @@ import {
8
8
  SvgExportContext,
9
9
  TLDrawShape,
10
10
  TLDrawShapeProps,
11
- TLDrawShapeSegment,
12
11
  TLResizeInfo,
13
12
  TLShapeUtilCanvasSvgDef,
14
13
  VecLike,
@@ -18,7 +17,6 @@ import {
18
17
  last,
19
18
  lerp,
20
19
  rng,
21
- toFixed,
22
20
  useEditor,
23
21
  useValue,
24
22
  } from '@tldraw/editor'
@@ -31,7 +29,11 @@ import { getSvgPathFromStrokePoints } from '../shared/freehand/svg'
31
29
  import { svgInk } from '../shared/freehand/svgInk'
32
30
  import { interpolateSegments } from '../shared/interpolate-props'
33
31
  import { useDefaultColorTheme } from '../shared/useDefaultColorTheme'
34
- import { getDrawShapeStrokeDashArray, getFreehandOptions, getPointsFromSegments } from './getPath'
32
+ import {
33
+ getDrawShapeStrokeDashArray,
34
+ getFreehandOptions,
35
+ getPointsFromDrawSegments,
36
+ } from './getPath'
35
37
 
36
38
  /** @public */
37
39
  export interface DrawShapeOptions {
@@ -73,11 +75,17 @@ export class DrawShapeUtil extends ShapeUtil<TLDrawShape> {
73
75
  isClosed: false,
74
76
  isPen: false,
75
77
  scale: 1,
78
+ scaleX: 1,
79
+ scaleY: 1,
76
80
  }
77
81
  }
78
82
 
79
83
  getGeometry(shape: TLDrawShape) {
80
- const points = getPointsFromSegments(shape.props.segments)
84
+ const points = getPointsFromDrawSegments(
85
+ shape.props.segments,
86
+ shape.props.scaleX,
87
+ shape.props.scaleY
88
+ )
81
89
 
82
90
  const sw = (STROKE_SIZES[shape.props.size] + 1) * shape.props.scale
83
91
 
@@ -131,7 +139,11 @@ export class DrawShapeUtil extends ShapeUtil<TLDrawShape> {
131
139
  }
132
140
 
133
141
  indicator(shape: TLDrawShape) {
134
- const allPointsFromSegments = getPointsFromSegments(shape.props.segments)
142
+ const allPointsFromSegments = getPointsFromDrawSegments(
143
+ shape.props.segments,
144
+ shape.props.scaleX,
145
+ shape.props.scaleY
146
+ )
135
147
 
136
148
  let sw = (STROKE_SIZES[shape.props.size] + 1) * shape.props.scale
137
149
 
@@ -139,7 +151,7 @@ export class DrawShapeUtil extends ShapeUtil<TLDrawShape> {
139
151
  const forceSolid = useValue(
140
152
  'force solid',
141
153
  () => {
142
- const zoomLevel = this.editor.getZoomLevel()
154
+ const zoomLevel = this.editor.getEfficientZoomLevel()
143
155
  return zoomLevel < 0.5 && zoomLevel < 1.5 / sw
144
156
  },
145
157
  [this.editor, sw]
@@ -182,24 +194,10 @@ export class DrawShapeUtil extends ShapeUtil<TLDrawShape> {
182
194
  override onResize(shape: TLDrawShape, info: TLResizeInfo<TLDrawShape>) {
183
195
  const { scaleX, scaleY } = info
184
196
 
185
- const newSegments: TLDrawShapeSegment[] = []
186
-
187
- for (const segment of shape.props.segments) {
188
- newSegments.push({
189
- ...segment,
190
- points: segment.points.map(({ x, y, z }) => {
191
- return {
192
- x: toFixed(scaleX * x),
193
- y: toFixed(scaleY * y),
194
- z,
195
- }
196
- }),
197
- })
198
- }
199
-
200
197
  return {
201
198
  props: {
202
- segments: newSegments,
199
+ scaleX: scaleX * shape.props.scaleX,
200
+ scaleY: scaleY * shape.props.scaleY,
203
201
  },
204
202
  }
205
203
  }
@@ -229,14 +227,22 @@ function getDot(point: VecLike, sw: number) {
229
227
  }
230
228
 
231
229
  function getIsDot(shape: TLDrawShape) {
232
- return shape.props.segments.length === 1 && shape.props.segments[0].points.length < 2
230
+ // First point is 16 base64 chars (3 Float32s = 12 bytes)
231
+ // Each delta point is 8 base64 chars (3 Float16s = 6 bytes)
232
+ // 1 point = 16 chars, 2 points = 24 chars
233
+ // Check if we have less than 2 points without decoding
234
+ return shape.props.segments.length === 1 && shape.props.segments[0].path.length < 24
233
235
  }
234
236
 
235
237
  function DrawShapeSvg({ shape, zoomOverride }: { shape: TLDrawShape; zoomOverride?: number }) {
236
238
  const theme = useDefaultColorTheme()
237
239
  const editor = useEditor()
238
240
 
239
- const allPointsFromSegments = getPointsFromSegments(shape.props.segments)
241
+ const allPointsFromSegments = getPointsFromDrawSegments(
242
+ shape.props.segments,
243
+ shape.props.scaleX,
244
+ shape.props.scaleY
245
+ )
240
246
 
241
247
  const showAsComplete = shape.props.isComplete || last(shape.props.segments)?.type === 'straight'
242
248
 
@@ -244,7 +250,7 @@ function DrawShapeSvg({ shape, zoomOverride }: { shape: TLDrawShape; zoomOverrid
244
250
  const forceSolid = useValue(
245
251
  'force solid',
246
252
  () => {
247
- const zoomLevel = zoomOverride ?? editor.getZoomLevel()
253
+ const zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel()
248
254
  return zoomLevel < 0.5 && zoomLevel < 1.5 / sw
249
255
  },
250
256
  [editor, sw, zoomOverride]
@@ -253,10 +259,10 @@ function DrawShapeSvg({ shape, zoomOverride }: { shape: TLDrawShape; zoomOverrid
253
259
  const dotAdjustment = useValue(
254
260
  'dot adjustment',
255
261
  () => {
256
- const zoomLevel = zoomOverride ?? editor.getZoomLevel()
262
+ const zoomLevel = zoomOverride ?? editor.getEfficientZoomLevel()
257
263
  // If we're zoomed way out (10%), then we need to make the dotted line go to 9 instead 0.1
258
264
  // Chrome doesn't render anything otherwise.
259
- return zoomLevel < 0.2 ? 0 : 0.1
265
+ return zoomLevel < 0.2 ? 9 : 0.1
260
266
  },
261
267
  [editor, zoomOverride]
262
268
  )
@@ -6,6 +6,7 @@ import {
6
6
  TLDrawShape,
7
7
  TLDrawShapeSegment,
8
8
  Vec,
9
+ b64Vecs,
9
10
  modulate,
10
11
  } from '@tldraw/editor'
11
12
  import { StrokeOptions } from '../shared/freehand/types'
@@ -101,19 +102,39 @@ export function getFreehandOptions(
101
102
  return { ...solidSettings(strokeWidth), last }
102
103
  }
103
104
 
104
- export function getPointsFromSegments(segments: TLDrawShapeSegment[]) {
105
+ /** @public */
106
+ export function getPointsFromDrawSegment(
107
+ segment: TLDrawShapeSegment,
108
+ scaleX: number,
109
+ scaleY: number,
110
+ points: Vec[] = []
111
+ ) {
112
+ const _points = b64Vecs.decodePoints(segment.path)
113
+
114
+ // Apply scale factors (used for lazy resize and flipping)
115
+ if (scaleX !== 1 || scaleY !== 1) {
116
+ for (const point of _points) {
117
+ point.x *= scaleX
118
+ point.y *= scaleY
119
+ }
120
+ }
121
+
122
+ if (segment.type === 'free' || _points.length < 2) {
123
+ points.push(..._points.map(Vec.From))
124
+ } else {
125
+ const pointsToInterpolate = Math.max(4, Math.floor(Vec.Dist(_points[0], _points[1]) / 16))
126
+ points.push(...Vec.PointsBetween(_points[0], _points[1], pointsToInterpolate))
127
+ }
128
+
129
+ return points
130
+ }
131
+
132
+ /** @public */
133
+ export function getPointsFromDrawSegments(segments: TLDrawShapeSegment[], scaleX = 1, scaleY = 1) {
105
134
  const points: Vec[] = []
106
135
 
107
136
  for (const segment of segments) {
108
- if (segment.type === 'free' || segment.points.length < 2) {
109
- points.push(...segment.points.map(Vec.Cast))
110
- } else {
111
- const pointsToInterpolate = Math.max(
112
- 4,
113
- Math.floor(Vec.Dist(segment.points[0], segment.points[1]) / 16)
114
- )
115
- points.push(...Vec.PointsBetween(segment.points[0], segment.points[1], pointsToInterpolate))
116
- }
137
+ getPointsFromDrawSegment(segment, scaleX, scaleY, points)
117
138
  }
118
139
 
119
140
  return points