tldraw 4.2.2 → 4.2.3

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 (621) hide show
  1. package/dist-cjs/index.d.ts +242 -311
  2. package/dist-cjs/index.js +5 -13
  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 +4 -7
  6. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js.map +2 -2
  7. package/dist-cjs/lib/defaultEmbedDefinitions.js.map +2 -2
  8. package/dist-cjs/lib/defaultExternalContentHandlers.js +5 -5
  9. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  10. package/dist-cjs/lib/defaultSideEffects.js +1 -6
  11. package/dist-cjs/lib/defaultSideEffects.js.map +2 -2
  12. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +13 -14
  13. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  14. package/dist-cjs/lib/shapes/arrow/arrow-types.js.map +1 -1
  15. package/dist-cjs/lib/shapes/arrow/arrowLabel.js +1 -1
  16. package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +2 -2
  17. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js +1 -1
  18. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
  19. package/dist-cjs/lib/shapes/arrow/elbow/elbowArrowSnapLines.js.map +2 -2
  20. package/dist-cjs/lib/shapes/arrow/shared.js.map +2 -2
  21. package/dist-cjs/lib/shapes/arrow/toolStates/Idle.js +10 -4
  22. package/dist-cjs/lib/shapes/arrow/toolStates/Idle.js.map +2 -2
  23. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +4 -7
  24. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  25. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +1 -1
  26. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  27. package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +2 -2
  28. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +22 -24
  29. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
  30. package/dist-cjs/lib/shapes/draw/getPath.js +11 -20
  31. package/dist-cjs/lib/shapes/draw/getPath.js.map +2 -2
  32. package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js +86 -82
  33. package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js.map +3 -3
  34. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +0 -6
  35. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
  36. package/dist-cjs/lib/shapes/frame/FrameShapeTool.js.map +1 -1
  37. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +5 -6
  38. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  39. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +142 -146
  40. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  41. package/dist-cjs/lib/shapes/geo/toolStates/Idle.js +10 -5
  42. package/dist-cjs/lib/shapes/geo/toolStates/Idle.js.map +2 -2
  43. package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js +3 -3
  44. package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js.map +2 -2
  45. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +21 -23
  46. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
  47. package/dist-cjs/lib/shapes/line/toolStates/Pointing.js +3 -3
  48. package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
  49. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +11 -6
  50. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  51. package/dist-cjs/lib/shapes/note/noteHelpers.js.map +2 -2
  52. package/dist-cjs/lib/shapes/note/toolStates/Pointing.js +10 -5
  53. package/dist-cjs/lib/shapes/note/toolStates/Pointing.js.map +2 -2
  54. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +2 -3
  55. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js.map +2 -2
  56. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +2 -14
  57. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +3 -3
  58. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +4 -12
  59. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +3 -3
  60. package/dist-cjs/lib/shapes/shared/ShapeFill.js +2 -2
  61. package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
  62. package/dist-cjs/lib/shapes/shared/crop.js +0 -1
  63. package/dist-cjs/lib/shapes/shared/crop.js.map +2 -2
  64. package/dist-cjs/lib/shapes/shared/interpolate-props.js +3 -3
  65. package/dist-cjs/lib/shapes/shared/interpolate-props.js.map +2 -2
  66. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  67. package/dist-cjs/lib/shapes/shared/useEditableRichText.js.map +2 -2
  68. package/dist-cjs/lib/shapes/shared/{useEfficientZoomThreshold.js → useForceSolid.js} +7 -10
  69. package/dist-cjs/lib/shapes/shared/useForceSolid.js.map +7 -0
  70. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +1 -1
  71. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
  72. package/dist-cjs/lib/shapes/text/RichTextArea.js +0 -5
  73. package/dist-cjs/lib/shapes/text/RichTextArea.js.map +2 -2
  74. package/dist-cjs/lib/shapes/text/TextShapeUtil.js +2 -5
  75. package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
  76. package/dist-cjs/lib/shapes/text/toolStates/Idle.js +10 -4
  77. package/dist-cjs/lib/shapes/text/toolStates/Idle.js.map +2 -2
  78. package/dist-cjs/lib/shapes/text/toolStates/Pointing.js +5 -7
  79. package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
  80. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +1 -1
  81. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +2 -2
  82. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +5 -4
  83. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  84. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +4 -2
  85. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  86. package/dist-cjs/lib/tools/HandTool/HandTool.js +5 -3
  87. package/dist-cjs/lib/tools/HandTool/HandTool.js.map +2 -2
  88. package/dist-cjs/lib/tools/HandTool/childStates/Dragging.js +2 -3
  89. package/dist-cjs/lib/tools/HandTool/childStates/Dragging.js.map +2 -2
  90. package/dist-cjs/lib/tools/HandTool/childStates/Pointing.js +1 -1
  91. package/dist-cjs/lib/tools/HandTool/childStates/Pointing.js.map +2 -2
  92. package/dist-cjs/lib/tools/LaserTool/childStates/Lasering.js +1 -1
  93. package/dist-cjs/lib/tools/LaserTool/childStates/Lasering.js.map +2 -2
  94. package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js +11 -10
  95. package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js.map +2 -2
  96. package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js +5 -6
  97. package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js.map +2 -2
  98. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js +6 -4
  99. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js.map +2 -2
  100. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js +1 -1
  101. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
  102. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.js +1 -1
  103. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.js.map +2 -2
  104. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js +1 -1
  105. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js.map +2 -2
  106. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.js +1 -2
  107. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.js.map +2 -2
  108. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.js +1 -1
  109. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.js.map +2 -2
  110. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +6 -8
  111. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  112. package/dist-cjs/lib/tools/SelectTool/childStates/EditingShape.js +11 -38
  113. package/dist-cjs/lib/tools/SelectTool/childStates/EditingShape.js.map +2 -2
  114. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +50 -42
  115. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
  116. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js +6 -6
  117. package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
  118. package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js +1 -1
  119. package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js.map +2 -2
  120. package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js +14 -4
  121. package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js.map +2 -2
  122. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js +1 -1
  123. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js.map +2 -2
  124. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js +1 -1
  125. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js.map +2 -2
  126. package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js +2 -2
  127. package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js.map +2 -2
  128. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js +13 -4
  129. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js.map +2 -2
  130. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +6 -5
  131. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  132. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js +3 -2
  133. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js.map +2 -2
  134. package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js +6 -7
  135. package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js.map +2 -2
  136. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +11 -13
  137. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  138. package/dist-cjs/lib/tools/SelectTool/selectHelpers.js +4 -15
  139. package/dist-cjs/lib/tools/SelectTool/selectHelpers.js.map +2 -2
  140. package/dist-cjs/lib/tools/ZoomTool/ZoomTool.js +1 -1
  141. package/dist-cjs/lib/tools/ZoomTool/ZoomTool.js.map +2 -2
  142. package/dist-cjs/lib/tools/ZoomTool/childStates/Pointing.js +3 -3
  143. package/dist-cjs/lib/tools/ZoomTool/childStates/Pointing.js.map +2 -2
  144. package/dist-cjs/lib/tools/ZoomTool/childStates/ZoomBrushing.js +6 -5
  145. package/dist-cjs/lib/tools/ZoomTool/childStates/ZoomBrushing.js.map +2 -2
  146. package/dist-cjs/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.js +3 -1
  147. package/dist-cjs/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.js.map +2 -2
  148. package/dist-cjs/lib/{utils/test-helpers.js → tools/selection-logic/getShouldEnterCropModeOnPointerDown.js} +8 -21
  149. package/dist-cjs/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.js.map +7 -0
  150. package/dist-cjs/lib/tools/selection-logic/selectOnCanvasPointerUp.js +1 -1
  151. package/dist-cjs/lib/tools/selection-logic/selectOnCanvasPointerUp.js.map +2 -2
  152. package/dist-cjs/lib/tools/selection-logic/updateHoveredShapeId.js +1 -1
  153. package/dist-cjs/lib/tools/selection-logic/updateHoveredShapeId.js.map +2 -2
  154. package/dist-cjs/lib/ui/TldrawUi.js +2 -2
  155. package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
  156. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.js +9 -3
  157. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.js.map +2 -2
  158. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js +3 -1
  159. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js.map +2 -2
  160. package/dist-cjs/lib/ui/components/CursorChatBubble.js +1 -1
  161. package/dist-cjs/lib/ui/components/CursorChatBubble.js.map +2 -2
  162. package/dist-cjs/lib/ui/components/DefaultDebugPanel.js +21 -1
  163. package/dist-cjs/lib/ui/components/DefaultDebugPanel.js.map +2 -2
  164. package/dist-cjs/lib/ui/components/EditLinkDialog.js +1 -11
  165. package/dist-cjs/lib/ui/components/EditLinkDialog.js.map +2 -2
  166. package/dist-cjs/lib/ui/components/HelperButtons/StopFollowing.js.map +2 -2
  167. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +1 -1
  168. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
  169. package/dist-cjs/lib/ui/components/OfflineIndicator/OfflineIndicator.js +15 -2
  170. package/dist-cjs/lib/ui/components/OfflineIndicator/OfflineIndicator.js.map +3 -3
  171. package/dist-cjs/lib/ui/components/PageMenu/PageItemInput.js +1 -3
  172. package/dist-cjs/lib/ui/components/PageMenu/PageItemInput.js.map +2 -2
  173. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js +0 -6
  174. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js.map +2 -2
  175. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  176. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbar.js +1 -1
  177. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbar.js.map +2 -2
  178. package/dist-cjs/lib/ui/components/Toolbar/DefaultRichTextToolbar.js +1 -1
  179. package/dist-cjs/lib/ui/components/Toolbar/DefaultRichTextToolbar.js.map +2 -2
  180. package/dist-cjs/lib/ui/components/TopPanel/CenteredTopPanelContainer.js.map +1 -1
  181. package/dist-cjs/lib/ui/components/TopPanel/DefaultTopPanel.js +32 -0
  182. package/dist-cjs/lib/ui/components/TopPanel/DefaultTopPanel.js.map +7 -0
  183. package/dist-cjs/lib/ui/components/menu-items.js +1 -3
  184. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  185. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -3
  186. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  187. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +1 -1
  188. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  189. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +93 -149
  190. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  191. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuActionCheckboxItem.js.map +2 -2
  192. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuActionItem.js.map +2 -2
  193. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +1 -1
  194. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  195. package/dist-cjs/lib/ui/context/actions.js +8 -7
  196. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  197. package/dist-cjs/lib/ui/context/components.js +2 -1
  198. package/dist-cjs/lib/ui/context/components.js.map +2 -2
  199. package/dist-cjs/lib/ui/hooks/menu-hooks.js.map +2 -2
  200. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +2 -2
  201. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
  202. package/dist-cjs/lib/ui/hooks/useFlatten.js.map +2 -2
  203. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +2 -2
  204. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js.map +2 -2
  205. package/dist-cjs/lib/ui/hooks/useTools.js +5 -4
  206. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  207. package/dist-cjs/lib/ui/version.js +3 -3
  208. package/dist-cjs/lib/ui/version.js.map +1 -1
  209. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js +6 -16
  210. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js.map +2 -2
  211. package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
  212. package/dist-cjs/lib/utils/frames/frames.js.map +2 -2
  213. package/dist-cjs/lib/utils/text/richText.js +2 -4
  214. package/dist-cjs/lib/utils/text/richText.js.map +2 -2
  215. package/dist-cjs/lib/utils/text/textDirection.js +51 -0
  216. package/dist-cjs/lib/utils/text/textDirection.js.map +7 -0
  217. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js +2 -7
  218. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js.map +2 -2
  219. package/dist-esm/index.d.mts +242 -311
  220. package/dist-esm/index.mjs +5 -14
  221. package/dist-esm/index.mjs.map +2 -2
  222. package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs.map +2 -2
  223. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs +4 -8
  224. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs.map +2 -2
  225. package/dist-esm/lib/defaultEmbedDefinitions.mjs.map +2 -2
  226. package/dist-esm/lib/defaultExternalContentHandlers.mjs +5 -5
  227. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  228. package/dist-esm/lib/defaultSideEffects.mjs +1 -6
  229. package/dist-esm/lib/defaultSideEffects.mjs.map +2 -2
  230. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +15 -15
  231. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  232. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +1 -1
  233. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +2 -2
  234. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs +1 -1
  235. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
  236. package/dist-esm/lib/shapes/arrow/elbow/elbowArrowSnapLines.mjs.map +2 -2
  237. package/dist-esm/lib/shapes/arrow/shared.mjs.map +2 -2
  238. package/dist-esm/lib/shapes/arrow/toolStates/Idle.mjs +10 -4
  239. package/dist-esm/lib/shapes/arrow/toolStates/Idle.mjs.map +2 -2
  240. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +4 -7
  241. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  242. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +1 -1
  243. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  244. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +2 -2
  245. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +24 -29
  246. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
  247. package/dist-esm/lib/shapes/draw/getPath.mjs +11 -21
  248. package/dist-esm/lib/shapes/draw/getPath.mjs.map +2 -2
  249. package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs +86 -83
  250. package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs.map +3 -3
  251. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +0 -6
  252. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
  253. package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs.map +1 -1
  254. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +5 -6
  255. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  256. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +142 -147
  257. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  258. package/dist-esm/lib/shapes/geo/toolStates/Idle.mjs +10 -5
  259. package/dist-esm/lib/shapes/geo/toolStates/Idle.mjs.map +2 -2
  260. package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs +3 -3
  261. package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
  262. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +22 -24
  263. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
  264. package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs +3 -3
  265. package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
  266. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +12 -7
  267. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  268. package/dist-esm/lib/shapes/note/noteHelpers.mjs.map +2 -2
  269. package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs +10 -5
  270. package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs.map +2 -2
  271. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs +3 -4
  272. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs.map +2 -2
  273. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +2 -14
  274. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  275. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +4 -12
  276. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  277. package/dist-esm/lib/shapes/shared/ShapeFill.mjs +2 -2
  278. package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
  279. package/dist-esm/lib/shapes/shared/crop.mjs +0 -1
  280. package/dist-esm/lib/shapes/shared/crop.mjs.map +2 -2
  281. package/dist-esm/lib/shapes/shared/interpolate-props.mjs +4 -4
  282. package/dist-esm/lib/shapes/shared/interpolate-props.mjs.map +2 -2
  283. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  284. package/dist-esm/lib/shapes/shared/useEditableRichText.mjs.map +2 -2
  285. package/dist-esm/lib/shapes/shared/useForceSolid.mjs +9 -0
  286. package/dist-esm/lib/shapes/shared/useForceSolid.mjs.map +7 -0
  287. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +1 -1
  288. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  289. package/dist-esm/lib/shapes/text/RichTextArea.mjs +0 -5
  290. package/dist-esm/lib/shapes/text/RichTextArea.mjs.map +2 -2
  291. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +2 -5
  292. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
  293. package/dist-esm/lib/shapes/text/toolStates/Idle.mjs +10 -4
  294. package/dist-esm/lib/shapes/text/toolStates/Idle.mjs.map +2 -2
  295. package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs +5 -7
  296. package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
  297. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +1 -1
  298. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +2 -2
  299. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +5 -4
  300. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  301. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +8 -3
  302. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  303. package/dist-esm/lib/tools/HandTool/HandTool.mjs +5 -3
  304. package/dist-esm/lib/tools/HandTool/HandTool.mjs.map +2 -2
  305. package/dist-esm/lib/tools/HandTool/childStates/Dragging.mjs +2 -3
  306. package/dist-esm/lib/tools/HandTool/childStates/Dragging.mjs.map +2 -2
  307. package/dist-esm/lib/tools/HandTool/childStates/Pointing.mjs +1 -1
  308. package/dist-esm/lib/tools/HandTool/childStates/Pointing.mjs.map +2 -2
  309. package/dist-esm/lib/tools/LaserTool/childStates/Lasering.mjs +1 -1
  310. package/dist-esm/lib/tools/LaserTool/childStates/Lasering.mjs.map +2 -2
  311. package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs +11 -10
  312. package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs.map +2 -2
  313. package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs +5 -6
  314. package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs.map +2 -2
  315. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs +6 -4
  316. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs.map +2 -2
  317. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs +1 -1
  318. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
  319. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.mjs +1 -1
  320. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.mjs.map +2 -2
  321. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs +1 -1
  322. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs.map +2 -2
  323. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.mjs +1 -2
  324. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.mjs.map +2 -2
  325. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.mjs +1 -1
  326. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.mjs.map +2 -2
  327. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +6 -8
  328. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  329. package/dist-esm/lib/tools/SelectTool/childStates/EditingShape.mjs +11 -38
  330. package/dist-esm/lib/tools/SelectTool/childStates/EditingShape.mjs.map +2 -2
  331. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +51 -43
  332. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
  333. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs +6 -6
  334. package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
  335. package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs +1 -1
  336. package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs.map +2 -2
  337. package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs +19 -6
  338. package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs.map +2 -2
  339. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs +1 -1
  340. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs.map +2 -2
  341. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs +1 -1
  342. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs.map +2 -2
  343. package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs +2 -2
  344. package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs.map +2 -2
  345. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs +13 -4
  346. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs.map +2 -2
  347. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +6 -5
  348. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  349. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs +3 -2
  350. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs.map +2 -2
  351. package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs +6 -7
  352. package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs.map +2 -2
  353. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +11 -13
  354. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  355. package/dist-esm/lib/tools/SelectTool/selectHelpers.mjs +4 -17
  356. package/dist-esm/lib/tools/SelectTool/selectHelpers.mjs.map +2 -2
  357. package/dist-esm/lib/tools/ZoomTool/ZoomTool.mjs +1 -1
  358. package/dist-esm/lib/tools/ZoomTool/ZoomTool.mjs.map +2 -2
  359. package/dist-esm/lib/tools/ZoomTool/childStates/Pointing.mjs +3 -3
  360. package/dist-esm/lib/tools/ZoomTool/childStates/Pointing.mjs.map +2 -2
  361. package/dist-esm/lib/tools/ZoomTool/childStates/ZoomBrushing.mjs +6 -5
  362. package/dist-esm/lib/tools/ZoomTool/childStates/ZoomBrushing.mjs.map +2 -2
  363. package/dist-esm/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.mjs +3 -1
  364. package/dist-esm/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.mjs.map +2 -2
  365. package/dist-esm/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.mjs +8 -0
  366. package/dist-esm/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.mjs.map +7 -0
  367. package/dist-esm/lib/tools/selection-logic/selectOnCanvasPointerUp.mjs +1 -1
  368. package/dist-esm/lib/tools/selection-logic/selectOnCanvasPointerUp.mjs.map +2 -2
  369. package/dist-esm/lib/tools/selection-logic/updateHoveredShapeId.mjs +1 -1
  370. package/dist-esm/lib/tools/selection-logic/updateHoveredShapeId.mjs.map +2 -2
  371. package/dist-esm/lib/ui/TldrawUi.mjs +2 -2
  372. package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
  373. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.mjs +8 -2
  374. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.mjs.map +2 -2
  375. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs +3 -1
  376. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs.map +2 -2
  377. package/dist-esm/lib/ui/components/CursorChatBubble.mjs +1 -1
  378. package/dist-esm/lib/ui/components/CursorChatBubble.mjs.map +2 -2
  379. package/dist-esm/lib/ui/components/DefaultDebugPanel.mjs +30 -3
  380. package/dist-esm/lib/ui/components/DefaultDebugPanel.mjs.map +2 -2
  381. package/dist-esm/lib/ui/components/EditLinkDialog.mjs +1 -11
  382. package/dist-esm/lib/ui/components/EditLinkDialog.mjs.map +2 -2
  383. package/dist-esm/lib/ui/components/HelperButtons/StopFollowing.mjs.map +2 -2
  384. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +1 -1
  385. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
  386. package/dist-esm/lib/ui/components/OfflineIndicator/OfflineIndicator.mjs +6 -3
  387. package/dist-esm/lib/ui/components/OfflineIndicator/OfflineIndicator.mjs.map +2 -2
  388. package/dist-esm/lib/ui/components/PageMenu/PageItemInput.mjs +1 -3
  389. package/dist-esm/lib/ui/components/PageMenu/PageItemInput.mjs.map +2 -2
  390. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs +0 -6
  391. package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs.map +2 -2
  392. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  393. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbar.mjs +1 -1
  394. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbar.mjs.map +2 -2
  395. package/dist-esm/lib/ui/components/Toolbar/DefaultRichTextToolbar.mjs +1 -1
  396. package/dist-esm/lib/ui/components/Toolbar/DefaultRichTextToolbar.mjs.map +2 -2
  397. package/dist-esm/lib/ui/components/TopPanel/CenteredTopPanelContainer.mjs.map +1 -1
  398. package/dist-esm/lib/ui/components/TopPanel/DefaultTopPanel.mjs +12 -0
  399. package/dist-esm/lib/ui/components/TopPanel/DefaultTopPanel.mjs.map +7 -0
  400. package/dist-esm/lib/ui/components/menu-items.mjs +5 -4
  401. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  402. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +1 -3
  403. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  404. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +2 -2
  405. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  406. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +95 -157
  407. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  408. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuActionCheckboxItem.mjs.map +2 -2
  409. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuActionItem.mjs.map +2 -2
  410. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +2 -2
  411. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  412. package/dist-esm/lib/ui/context/actions.mjs +8 -7
  413. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  414. package/dist-esm/lib/ui/context/components.mjs +2 -1
  415. package/dist-esm/lib/ui/context/components.mjs.map +2 -2
  416. package/dist-esm/lib/ui/hooks/menu-hooks.mjs +4 -1
  417. package/dist-esm/lib/ui/hooks/menu-hooks.mjs.map +2 -2
  418. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +2 -2
  419. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
  420. package/dist-esm/lib/ui/hooks/useFlatten.mjs.map +2 -2
  421. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs +2 -2
  422. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs.map +2 -2
  423. package/dist-esm/lib/ui/hooks/useTools.mjs +5 -4
  424. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  425. package/dist-esm/lib/ui/version.mjs +3 -3
  426. package/dist-esm/lib/ui/version.mjs.map +1 -1
  427. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs +6 -17
  428. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs.map +2 -2
  429. package/dist-esm/lib/utils/export/exportAs.mjs +3 -1
  430. package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
  431. package/dist-esm/lib/utils/frames/frames.mjs.map +2 -2
  432. package/dist-esm/lib/utils/text/richText.mjs +2 -5
  433. package/dist-esm/lib/utils/text/richText.mjs.map +2 -2
  434. package/dist-esm/lib/utils/text/textDirection.mjs +31 -0
  435. package/dist-esm/lib/utils/text/textDirection.mjs.map +7 -0
  436. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs +2 -8
  437. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs.map +2 -2
  438. package/package.json +16 -18
  439. package/src/index.ts +2 -6
  440. package/src/lib/Tldraw.test.tsx +1 -46
  441. package/src/lib/bindings/arrow/ArrowBindingUtil.ts +1 -1
  442. package/src/lib/canvas/TldrawSelectionForeground.tsx +9 -20
  443. package/src/lib/defaultEmbedDefinitions.ts +0 -1
  444. package/src/lib/defaultExternalContentHandlers.ts +14 -13
  445. package/src/lib/defaultSideEffects.ts +1 -6
  446. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +133 -40
  447. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +8 -8
  448. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +2 -2
  449. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +16 -16
  450. package/src/lib/shapes/arrow/arrow-types.ts +0 -2
  451. package/src/lib/shapes/arrow/arrowLabel.ts +2 -2
  452. package/src/lib/shapes/arrow/arrowTargetState.ts +2 -2
  453. package/src/lib/shapes/arrow/elbow/elbowArrowSnapLines.tsx +3 -3
  454. package/src/lib/shapes/arrow/shared.ts +4 -4
  455. package/src/lib/shapes/arrow/toolStates/Idle.tsx +14 -4
  456. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +5 -8
  457. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +1 -1
  458. package/src/lib/shapes/bookmark/bookmarks.ts +3 -3
  459. package/src/lib/shapes/draw/DrawShapeUtil.tsx +26 -30
  460. package/src/lib/shapes/draw/getPath.ts +10 -31
  461. package/src/lib/shapes/draw/toolStates/Drawing.ts +90 -100
  462. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -8
  463. package/src/lib/shapes/frame/FrameShapeTool.ts +1 -1
  464. package/src/lib/shapes/frame/FrameShapeUtil.tsx +4 -10
  465. package/src/lib/shapes/geo/GeoShapeUtil.test.tsx +2 -10
  466. package/src/lib/shapes/geo/GeoShapeUtil.tsx +176 -228
  467. package/src/lib/shapes/geo/toolStates/Idle.ts +15 -5
  468. package/src/lib/shapes/geo/toolStates/Pointing.ts +6 -6
  469. package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +24 -25
  470. package/src/lib/shapes/line/LineShapeTool.test.ts +6 -6
  471. package/src/lib/shapes/line/LineShapeUtil.test.tsx +5 -5
  472. package/src/lib/shapes/line/toolStates/Pointing.ts +4 -4
  473. package/src/lib/shapes/note/NoteShapeTool.test.ts +1 -2
  474. package/src/lib/shapes/note/NoteShapeUtil.tsx +10 -9
  475. package/src/lib/shapes/note/noteCloning.test.ts +1 -3
  476. package/src/lib/shapes/note/noteHelpers.ts +2 -2
  477. package/src/lib/shapes/note/toolStates/Pointing.ts +10 -5
  478. package/src/lib/shapes/shared/HyperlinkButton.tsx +3 -4
  479. package/src/lib/shapes/shared/PlainTextLabel.tsx +2 -12
  480. package/src/lib/shapes/shared/RichTextLabel.tsx +4 -14
  481. package/src/lib/shapes/shared/ShapeFill.tsx +2 -2
  482. package/src/lib/shapes/shared/crop.ts +0 -1
  483. package/src/lib/shapes/shared/interpolate-props.ts +4 -4
  484. package/src/lib/shapes/shared/useEditablePlainText.ts +3 -7
  485. package/src/lib/shapes/shared/useEditableRichText.ts +3 -7
  486. package/src/lib/shapes/shared/useForceSolid.ts +6 -0
  487. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +1 -1
  488. package/src/lib/shapes/text/RichTextArea.tsx +0 -5
  489. package/src/lib/shapes/text/TextShapeTool.test.ts +4 -4
  490. package/src/lib/shapes/text/TextShapeUtil.tsx +0 -5
  491. package/src/lib/shapes/text/toolStates/Idle.ts +14 -4
  492. package/src/lib/shapes/text/toolStates/Pointing.ts +8 -8
  493. package/src/lib/shapes/video/VideoShapeUtil.tsx +1 -2
  494. package/src/lib/tools/EraserTool/childStates/Erasing.ts +10 -7
  495. package/src/lib/tools/EraserTool/childStates/Pointing.ts +20 -5
  496. package/src/lib/tools/HandTool/HandTool.ts +5 -3
  497. package/src/lib/tools/HandTool/childStates/Dragging.ts +2 -3
  498. package/src/lib/tools/HandTool/childStates/Pointing.ts +1 -1
  499. package/src/lib/tools/LaserTool/childStates/Lasering.ts +1 -1
  500. package/src/lib/tools/SelectTool/DragAndDropManager.ts +11 -14
  501. package/src/lib/tools/SelectTool/childStates/Brushing.ts +11 -8
  502. package/src/lib/tools/SelectTool/childStates/Crop/children/Cropping.ts +6 -7
  503. package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +4 -3
  504. package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.ts +1 -1
  505. package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.ts +1 -1
  506. package/src/lib/tools/SelectTool/childStates/Crop/children/TranslatingCrop.ts +1 -2
  507. package/src/lib/tools/SelectTool/childStates/Crop/children/crop_helpers.ts +1 -1
  508. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +12 -11
  509. package/src/lib/tools/SelectTool/childStates/EditingShape.ts +16 -57
  510. package/src/lib/tools/SelectTool/childStates/Idle.ts +81 -64
  511. package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +8 -7
  512. package/src/lib/tools/SelectTool/childStates/PointingCanvas.ts +1 -1
  513. package/src/lib/tools/SelectTool/childStates/PointingHandle.ts +17 -9
  514. package/src/lib/tools/SelectTool/childStates/PointingResizeHandle.ts +1 -1
  515. package/src/lib/tools/SelectTool/childStates/PointingRotateHandle.ts +1 -1
  516. package/src/lib/tools/SelectTool/childStates/PointingSelection.ts +4 -4
  517. package/src/lib/tools/SelectTool/childStates/PointingShape.ts +14 -4
  518. package/src/lib/tools/SelectTool/childStates/Resizing.ts +10 -8
  519. package/src/lib/tools/SelectTool/childStates/Rotating.ts +3 -2
  520. package/src/lib/tools/SelectTool/childStates/ScribbleBrushing.ts +10 -9
  521. package/src/lib/tools/SelectTool/childStates/Translating.ts +15 -16
  522. package/src/lib/tools/SelectTool/selectHelpers.ts +4 -39
  523. package/src/lib/tools/ZoomTool/ZoomTool.ts +1 -1
  524. package/src/lib/tools/ZoomTool/childStates/Pointing.ts +3 -3
  525. package/src/lib/tools/ZoomTool/childStates/ZoomBrushing.ts +6 -5
  526. package/src/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.ts +3 -1
  527. package/src/lib/tools/selection-logic/getShouldEnterCropModeOnPointerDown.ts +10 -0
  528. package/src/lib/tools/selection-logic/selectOnCanvasPointerUp.ts +1 -1
  529. package/src/lib/tools/selection-logic/updateHoveredShapeId.ts +1 -1
  530. package/src/lib/ui/TldrawUi.tsx +2 -5
  531. package/src/lib/ui/components/ActionsMenu/DefaultActionsMenuContent.tsx +9 -1
  532. package/src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx +3 -1
  533. package/src/lib/ui/components/CursorChatBubble.tsx +2 -2
  534. package/src/lib/ui/components/DefaultDebugPanel.tsx +42 -3
  535. package/src/lib/ui/components/EditLinkDialog.tsx +6 -16
  536. package/src/lib/ui/components/HelperButtons/StopFollowing.tsx +2 -2
  537. package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +1 -1
  538. package/src/lib/ui/components/OfflineIndicator/OfflineIndicator.tsx +5 -6
  539. package/src/lib/ui/components/PageMenu/PageItemInput.tsx +1 -3
  540. package/src/lib/ui/components/SharePanel/PeopleMenu.tsx +0 -8
  541. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +2 -2
  542. package/src/lib/ui/components/Toolbar/DefaultImageToolbar.tsx +1 -1
  543. package/src/lib/ui/components/Toolbar/DefaultRichTextToolbar.tsx +1 -1
  544. package/src/lib/ui/components/TopPanel/CenteredTopPanelContainer.tsx +1 -1
  545. package/src/lib/ui/components/TopPanel/DefaultTopPanel.tsx +10 -0
  546. package/src/lib/ui/components/menu-items.tsx +15 -9
  547. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +3 -5
  548. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +2 -2
  549. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +113 -208
  550. package/src/lib/ui/components/primitives/menus/TldrawUiMenuActionCheckboxItem.tsx +1 -1
  551. package/src/lib/ui/components/primitives/menus/TldrawUiMenuActionItem.tsx +1 -1
  552. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +2 -2
  553. package/src/lib/ui/context/actions.tsx +19 -15
  554. package/src/lib/ui/context/components.tsx +2 -1
  555. package/src/lib/ui/hooks/menu-hooks.ts +19 -9
  556. package/src/lib/ui/hooks/useClipboardEvents.ts +2 -2
  557. package/src/lib/ui/hooks/useFlatten.ts +2 -1
  558. package/src/lib/ui/hooks/useKeyboardShortcuts.ts +2 -2
  559. package/src/lib/ui/hooks/useTools.tsx +7 -5
  560. package/src/lib/ui/version.ts +3 -3
  561. package/src/lib/ui.css +29 -31
  562. package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +48 -12
  563. package/src/lib/utils/excalidraw/putExcalidrawContent.ts +6 -19
  564. package/src/lib/utils/export/exportAs.ts +9 -2
  565. package/src/lib/utils/frames/frames.ts +1 -1
  566. package/src/lib/utils/text/richText.ts +5 -6
  567. package/src/lib/utils/text/textDirection.ts +32 -0
  568. package/src/lib/utils/tldr/buildFromV1Document.ts +19 -21
  569. package/src/test/Editor.test.tsx +41 -78
  570. package/src/test/EraserTool.test.ts +12 -10
  571. package/src/test/SelectTool.test.ts +19 -11
  572. package/src/test/TestEditor.ts +51 -49
  573. package/src/test/TldrawEditor.test.tsx +20 -24
  574. package/src/test/__snapshots__/drawing.test.ts.snap +1257 -3
  575. package/src/test/__snapshots__/resizing.test.ts.snap +12 -3
  576. package/src/test/arrows-megabus.test.tsx +1 -1
  577. package/src/test/bindings.test.tsx +25 -29
  578. package/src/test/bindingsIndex.test.tsx +4 -4
  579. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +10 -10
  580. package/src/test/commands/createShapes.test.ts +1 -15
  581. package/src/test/commands/getSvgString.test.ts +2 -2
  582. package/src/test/commands/putContent.test.ts +1 -80
  583. package/src/test/commands/setCamera.test.ts +11 -13
  584. package/src/test/commands/stackShapes.test.ts +8 -34
  585. package/src/test/commands/updateShapes.test.ts +5 -21
  586. package/src/test/commands/zoomToBounds.test.ts +3 -19
  587. package/src/test/commands/zoomToSelection.test.ts +3 -14
  588. package/src/test/custom-clipping.test.ts +44 -52
  589. package/src/test/customSnapping.test.tsx +62 -77
  590. package/src/test/drawing.test.ts +10 -17
  591. package/src/test/duplicate.test.ts +1 -1
  592. package/src/test/flipShapes.test.ts +0 -33
  593. package/src/test/frames.test.ts +2 -94
  594. package/src/test/getCulledShapes.test.tsx +3 -11
  595. package/src/test/getShapeAtPoint.test.ts +2 -2
  596. package/src/test/groups.test.tsx +4 -7
  597. package/src/test/modifiers.test.ts +6 -6
  598. package/src/test/resizing.test.ts +22 -16
  599. package/src/test/selection-omnibus.test.ts +13 -13
  600. package/src/test/shapeutils.test.ts +1 -1
  601. package/src/test/spacebarPanning.test.ts +10 -28
  602. package/src/test/styles2.test.tsx +1 -1
  603. package/src/test/styles3.test.ts +5 -5
  604. package/src/test/test-jsx.tsx +57 -72
  605. package/src/test/text.test.ts +17 -15
  606. package/src/test/translating.test.ts +8 -6
  607. package/tldraw.css +41 -45
  608. package/dist-cjs/lib/shapes/shared/useEfficientZoomThreshold.js.map +0 -7
  609. package/dist-cjs/lib/utils/test-helpers.js.map +0 -7
  610. package/dist-esm/lib/shapes/shared/useEfficientZoomThreshold.mjs +0 -12
  611. package/dist-esm/lib/shapes/shared/useEfficientZoomThreshold.mjs.map +0 -7
  612. package/dist-esm/lib/utils/test-helpers.mjs +0 -21
  613. package/dist-esm/lib/utils/test-helpers.mjs.map +0 -7
  614. package/src/lib/shapes/draw/DrawShapeUtil.test.ts +0 -146
  615. package/src/lib/shapes/highlight/HighlightShapeUtil.test.ts +0 -146
  616. package/src/lib/shapes/shared/useEfficientZoomThreshold.ts +0 -10
  617. package/src/lib/utils/test-helpers.ts +0 -60
  618. package/src/test/commands/cameraState.test.ts +0 -299
  619. package/src/test/commands/createShape.test.ts +0 -64
  620. package/src/test/commands/isShapeOfType.test.ts +0 -44
  621. package/src/test/commands/updateShape.test.ts +0 -67
@@ -15,7 +15,6 @@ import {
15
15
  TLResizeInfo,
16
16
  TLShapeUtilCanvasSvgDef,
17
17
  Vec,
18
- WeakCache,
19
18
  exhaustiveSwitchError,
20
19
  geoShapeMigrations,
21
20
  geoShapeProps,
@@ -44,7 +43,6 @@ import {
44
43
  import { getFillDefForCanvas, getFillDefForExport } from '../shared/defaultStyleDefs'
45
44
  import { useDefaultColorTheme } from '../shared/useDefaultColorTheme'
46
45
  import { useIsReadyForEditing } from '../shared/useEditablePlainText'
47
- import { useEfficientZoomThreshold } from '../shared/useEfficientZoomThreshold'
48
46
  import { GeoShapeBody } from './components/GeoShapeBody'
49
47
  import { getGeoShapePath } from './getGeoShapePath'
50
48
 
@@ -56,10 +54,6 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
56
54
  static override props = geoShapeProps
57
55
  static override migrations = geoShapeMigrations
58
56
 
59
- override options = {
60
- showTextOutline: true,
61
- }
62
-
63
57
  override canEdit() {
64
58
  return true
65
59
  }
@@ -87,40 +81,53 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
87
81
  }
88
82
 
89
83
  override getGeometry(shape: TLGeoShape) {
90
- const { props } = shape
91
- const { scale } = props
92
- const path = getGeoShapePath(shape)
93
- const pathGeometry = path.toGeometry()
84
+ const w = Math.max(1, shape.props.w)
85
+ const h = Math.max(1, shape.props.h + shape.props.growY)
94
86
 
95
- const scaledW = Math.max(1, props.w)
96
- const scaledH = Math.max(1, props.h + props.growY)
97
- const unscaledW = scaledW / scale
98
- const unscaledH = scaledH / scale
99
-
100
- const isEmptyLabel = isEmptyRichText(props.richText)
101
- const unscaledLabelSize = isEmptyLabel
102
- ? EMPTY_LABEL_SIZE
103
- : getUnscaledLabelSize(this.editor, shape)
87
+ const path = getGeoShapePath(shape)
88
+ const unscaledlabelSize = getUnscaledLabelSize(this.editor, shape)
89
+ // unscaled w and h
90
+ const unscaledW = w / shape.props.scale
91
+ const unscaledH = h / shape.props.scale
92
+ const unscaledminWidth = Math.min(100, unscaledW / 2)
93
+ const unscaledMinHeight = Math.min(
94
+ LABEL_FONT_SIZES[shape.props.size] * TEXT_PROPS.lineHeight + LABEL_PADDING * 2,
95
+ unscaledH / 2
96
+ )
104
97
 
105
- const labelBounds = getLabelBounds(
98
+ const unscaledLabelWidth = Math.min(
106
99
  unscaledW,
100
+ Math.max(unscaledlabelSize.w, Math.min(unscaledminWidth, Math.max(1, unscaledW - 8)))
101
+ )
102
+ const unscaledLabelHeight = Math.min(
107
103
  unscaledH,
108
- unscaledLabelSize,
109
- props.size,
110
- props.align,
111
- props.verticalAlign,
112
- scale
104
+ Math.max(unscaledlabelSize.h, Math.min(unscaledMinHeight, Math.max(1, unscaledH - 8)))
113
105
  )
114
106
 
107
+ // todo: use centroid for label position
108
+
115
109
  return new Group2d({
116
110
  children: [
117
- pathGeometry,
111
+ path.toGeometry(),
118
112
  new Rectangle2d({
119
- ...labelBounds,
113
+ x:
114
+ shape.props.align === 'start'
115
+ ? 0
116
+ : shape.props.align === 'end'
117
+ ? (unscaledW - unscaledLabelWidth) * shape.props.scale
118
+ : ((unscaledW - unscaledLabelWidth) / 2) * shape.props.scale,
119
+ y:
120
+ shape.props.verticalAlign === 'start'
121
+ ? 0
122
+ : shape.props.verticalAlign === 'end'
123
+ ? (unscaledH - unscaledLabelHeight) * shape.props.scale
124
+ : ((unscaledH - unscaledLabelHeight) / 2) * shape.props.scale,
125
+ width: unscaledLabelWidth * shape.props.scale,
126
+ height: unscaledLabelHeight * shape.props.scale,
120
127
  isFilled: true,
121
128
  isLabel: true,
122
129
  excludeFromShapeBounds: true,
123
- isEmptyLabel: isEmptyLabel,
130
+ isEmptyLabel: isEmptyRichText(shape.props.richText),
124
131
  }),
125
132
  ],
126
133
  })
@@ -188,7 +195,7 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
188
195
  const isReadyForEditing = useIsReadyForEditing(editor, shape.id)
189
196
  const isEmpty = isEmptyRichText(shape.props.richText)
190
197
  const showHtmlContainer = isReadyForEditing || !isEmpty
191
- const isForceSolid = useEfficientZoomThreshold(shape.props.scale * 0.25)
198
+ const isForceSolid = useValue('force solid', () => editor.getZoomLevel() < 0.2, [editor])
192
199
 
193
200
  return (
194
201
  <>
@@ -217,7 +224,6 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
217
224
  isSelected={isOnlySelected}
218
225
  labelColor={getColorValue(theme, props.labelColor, 'solid')}
219
226
  wrap
220
- showTextOutline={this.options.showTextOutline}
221
227
  />
222
228
  </HTMLContainer>
223
229
  )}
@@ -227,7 +233,9 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
227
233
  }
228
234
 
229
235
  indicator(shape: TLGeoShape) {
230
- const isZoomedOut = useEfficientZoomThreshold(shape.props.scale * 0.25)
236
+ const isZoomedOut = useValue('isZoomedOut', () => this.editor.getZoomLevel() < 0.25, [
237
+ this.editor,
238
+ ])
231
239
 
232
240
  const { size, dash, scale } = shape.props
233
241
  const strokeWidth = STROKE_SIZES[size]
@@ -275,7 +283,6 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
275
283
  labelColor={getColorValue(theme, props.labelColor, 'solid')}
276
284
  bounds={bounds}
277
285
  padding={LABEL_PADDING}
278
- showTextOutline={this.options.showTextOutline}
279
286
  />
280
287
  )
281
288
  }
@@ -296,32 +303,41 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
296
303
  shape: TLGeoShape,
297
304
  { handle, newPoint, scaleX, scaleY, initialShape }: TLResizeInfo<TLGeoShape>
298
305
  ) {
299
- const unscaledInitial = getUnscaledGeoProps(initialShape.props)
306
+ const unscaledInitialW = initialShape.props.w / initialShape.props.scale
307
+ const unscaledInitialH = initialShape.props.h / initialShape.props.scale
308
+ const unscaledGrowY = initialShape.props.growY / initialShape.props.scale
300
309
  // use the w/h from props here instead of the initialBounds here,
301
310
  // since cloud shapes calculated bounds can differ from the props w/h.
302
- let unscaledW = unscaledInitial.w * scaleX
303
- let unscaledH = (unscaledInitial.h + unscaledInitial.growY) * scaleY
311
+ let unscaledW = unscaledInitialW * scaleX
312
+ let unscaledH = (unscaledInitialH + unscaledGrowY) * scaleY
304
313
  let overShrinkX = 0
305
314
  let overShrinkY = 0
306
315
 
316
+ const min = MIN_SIZE_WITH_LABEL
317
+
307
318
  if (!isEmptyRichText(shape.props.richText)) {
308
- // Use initialShape for label measurement to hit the cache.
309
- // Creating a temp shape with new dimensions would break WeakCache and cause
310
- // expensive measurements on every resize frame.
311
- const unscaledLabelSize = getUnscaledLabelSize(this.editor, initialShape)
319
+ let newW = Math.max(Math.abs(unscaledW), min)
320
+ let newH = Math.max(Math.abs(unscaledH), min)
312
321
 
313
- const absUnscaledW = Math.abs(unscaledW)
314
- const absUnscaledH = Math.abs(unscaledH)
322
+ if (newW < min && newH === min) newW = min
323
+ if (newW === min && newH < min) newH = min
315
324
 
316
- // Constrain to label size (primary constraint) and min size with label (secondary)
317
- const constrainedW = Math.max(absUnscaledW, unscaledLabelSize.w, MIN_SIZE_WITH_LABEL)
318
- const constrainedH = Math.max(absUnscaledH, unscaledLabelSize.h, MIN_SIZE_WITH_LABEL)
325
+ const unscaledLabelSize = getUnscaledLabelSize(this.editor, {
326
+ ...shape,
327
+ props: {
328
+ ...shape.props,
329
+ w: newW * shape.props.scale,
330
+ h: newH * shape.props.scale,
331
+ },
332
+ })
319
333
 
320
- overShrinkX = constrainedW - absUnscaledW
321
- overShrinkY = constrainedH - absUnscaledH
334
+ const nextW = Math.max(Math.abs(unscaledW), unscaledLabelSize.w) * Math.sign(unscaledW)
335
+ const nextH = Math.max(Math.abs(unscaledH), unscaledLabelSize.h) * Math.sign(unscaledH)
336
+ overShrinkX = Math.abs(nextW) - Math.abs(unscaledW)
337
+ overShrinkY = Math.abs(nextH) - Math.abs(unscaledH)
322
338
 
323
- unscaledW = constrainedW * Math.sign(unscaledW || 1)
324
- unscaledH = constrainedH * Math.sign(unscaledH || 1)
339
+ unscaledW = nextW
340
+ unscaledH = nextH
325
341
  }
326
342
 
327
343
  const scaledW = unscaledW * shape.props.scale
@@ -363,93 +379,147 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
363
379
  }
364
380
 
365
381
  override onBeforeCreate(shape: TLGeoShape) {
366
- const { props } = shape
367
-
368
- // No text - ensure growY is 0
369
- if (isEmptyRichText(props.richText)) {
370
- return props.growY !== 0 ? { ...shape, props: { ...props, growY: 0 } } : undefined
382
+ if (isEmptyRichText(shape.props.richText)) {
383
+ if (shape.props.growY) {
384
+ // No text / some growY, set growY to 0
385
+ return {
386
+ ...shape,
387
+ props: {
388
+ ...shape.props,
389
+ growY: 0,
390
+ },
391
+ }
392
+ } else {
393
+ // No text / no growY, nothing to change
394
+ return
395
+ }
371
396
  }
372
397
 
373
- // Has text - calculate growY needed to fit label
374
- const unscaledShapeH = props.h / props.scale
375
- const unscaledLabelH = getUnscaledLabelSize(this.editor, shape).h
376
- const unscaledGrowY = calculateGrowY(unscaledShapeH, unscaledLabelH, props.growY / props.scale)
398
+ const unscaledPrevHeight = shape.props.h / shape.props.scale
399
+ const unscaledNextHeight = getUnscaledLabelSize(this.editor, shape).h
400
+
401
+ let growY: number | null = null
402
+
403
+ if (unscaledNextHeight > unscaledPrevHeight) {
404
+ growY = unscaledNextHeight - unscaledPrevHeight
405
+ } else {
406
+ if (shape.props.growY) {
407
+ growY = 0
408
+ }
409
+ }
377
410
 
378
- if (unscaledGrowY !== null) {
411
+ if (growY !== null) {
379
412
  return {
380
413
  ...shape,
381
- props: { ...props, growY: unscaledGrowY * props.scale },
414
+ props: {
415
+ ...shape.props,
416
+ // scale the growY
417
+ growY: growY * shape.props.scale,
418
+ },
382
419
  }
383
420
  }
384
421
  }
385
422
 
386
423
  override onBeforeUpdate(prev: TLGeoShape, next: TLGeoShape) {
387
- const { props: prevProps } = prev
388
- const { props: nextProps } = next
389
-
390
- // No change to text, font, or size - no update needed
424
+ // No change to text, font, or size, no need to update update
391
425
  if (
392
- isEqual(prevProps.richText, nextProps.richText) &&
393
- prevProps.font === nextProps.font &&
394
- prevProps.size === nextProps.size
426
+ isEqual(prev.props.richText, next.props.richText) &&
427
+ prev.props.font === next.props.font &&
428
+ prev.props.size === next.props.size
395
429
  ) {
396
430
  return
397
431
  }
398
432
 
399
- const wasEmpty = isEmptyRichText(prevProps.richText)
400
- const isEmpty = isEmptyRichText(nextProps.richText)
401
-
402
- // If label is empty and used to be empty, skip label measurement and dimension adjustment
403
- if (wasEmpty && isEmpty) {
404
- return
433
+ // If we got rid of the text, cancel out any growY from the prev text
434
+ const wasEmpty = isEmptyRichText(prev.props.richText)
435
+ const isEmpty = isEmptyRichText(next.props.richText)
436
+ if (!wasEmpty && isEmpty) {
437
+ return {
438
+ ...next,
439
+ props: {
440
+ ...next.props,
441
+ growY: 0,
442
+ },
443
+ }
405
444
  }
406
445
 
407
- // Text was removed - reset growY
408
- if (isEmpty) {
409
- return nextProps.growY !== 0 ? { ...next, props: { ...nextProps, growY: 0 } } : undefined
410
- }
446
+ // Get the prev width and height in unscaled values
447
+ const unscaledPrevWidth = prev.props.w / prev.props.scale
448
+ const unscaledPrevHeight = prev.props.h / prev.props.scale
449
+ const unscaledPrevGrowY = prev.props.growY / prev.props.scale
411
450
 
412
- const unscaledPrev = getUnscaledGeoProps(prevProps)
413
- const unscaledLabelSize = getUnscaledLabelSize(this.editor, next)
414
- const { scale } = nextProps
451
+ // Get the next width and height in unscaled values
452
+ const unscaledNextLabelSize = getUnscaledLabelSize(this.editor, next)
453
+
454
+ // When entering the first character in a label (not pasting in multiple characters...)
455
+ if (wasEmpty && !isEmpty && renderPlaintextFromRichText(this.editor, next.props.richText)) {
456
+ let unscaledW = Math.max(unscaledPrevWidth, unscaledNextLabelSize.w)
457
+ let unscaledH = Math.max(unscaledPrevHeight, unscaledNextLabelSize.h)
458
+
459
+ const min = MIN_SIZE_WITH_LABEL
460
+
461
+ // If both the width and height were less than the minimum size, make the shape square
462
+ if (unscaledPrevWidth < min && unscaledPrevHeight < min) {
463
+ unscaledW = Math.max(unscaledW, min)
464
+ unscaledH = Math.max(unscaledH, min)
465
+ unscaledW = Math.max(unscaledW, unscaledH)
466
+ unscaledH = Math.max(unscaledW, unscaledH)
467
+ }
415
468
 
416
- // Text was added for the first time - expand shape to fit (if wasEmpty and now there's text...
417
- // It might be just whitespace but it is faster to assume that it is NOT just whitespace and expand
418
- // the shape in either case (a label with just spaces text will be less performant but that's acceptable)
419
- if (wasEmpty && !isEmpty) {
420
- const expanded = expandShapeForFirstLabel(unscaledPrev.w, unscaledPrev.h, unscaledLabelSize)
469
+ // Don't set a growY—at least, not until we've implemented a growX property
421
470
  return {
422
471
  ...next,
423
472
  props: {
424
- ...nextProps,
425
- w: expanded.w * scale,
426
- h: expanded.h * scale,
473
+ ...next.props,
474
+ // Scale the results
475
+ w: unscaledW * next.props.scale,
476
+ h: unscaledH * next.props.scale,
427
477
  growY: 0,
428
478
  },
429
479
  }
430
480
  }
431
481
 
432
- // Text was modified - adjust dimensions to fit new label
433
- const unscaledNextW = next.props.w / scale
434
- const needsWidthExpand = unscaledLabelSize.w > unscaledNextW
435
- const unscaledGrowY = calculateGrowY(unscaledPrev.h, unscaledLabelSize.h, unscaledPrev.growY)
482
+ let growY: number | null = null
436
483
 
437
- if (unscaledGrowY !== null || needsWidthExpand) {
484
+ if (unscaledNextLabelSize.h > unscaledPrevHeight) {
485
+ growY = unscaledNextLabelSize.h - unscaledPrevHeight
486
+ } else {
487
+ if (unscaledPrevGrowY) {
488
+ growY = 0
489
+ }
490
+ }
491
+
492
+ if (growY !== null) {
493
+ const unscaledNextWidth = next.props.w / next.props.scale
494
+ return {
495
+ ...next,
496
+ props: {
497
+ ...next.props,
498
+ // Scale the results
499
+ growY: growY * next.props.scale,
500
+ w: Math.max(unscaledNextWidth, unscaledNextLabelSize.w) * next.props.scale,
501
+ },
502
+ }
503
+ }
504
+
505
+ if (unscaledNextLabelSize.w > unscaledPrevWidth) {
438
506
  return {
439
507
  ...next,
440
508
  props: {
441
- ...nextProps,
442
- growY: (unscaledGrowY ?? unscaledPrev.growY) * scale,
443
- w: Math.max(unscaledNextW, unscaledLabelSize.w) * scale,
509
+ ...next.props,
510
+ // Scale the results
511
+ w: unscaledNextLabelSize.w * next.props.scale,
444
512
  },
445
513
  }
446
514
  }
515
+
516
+ // otherwise, no update needed
447
517
  }
448
518
 
449
519
  override onDoubleClick(shape: TLGeoShape) {
450
520
  // Little easter egg: double-clicking a rectangle / checkbox while
451
521
  // holding alt will toggle between check-box and rectangle
452
- if (this.editor.inputs.getAltKey()) {
522
+ if (this.editor.inputs.altKey) {
453
523
  switch (shape.props.geo) {
454
524
  case 'rectangle': {
455
525
  return {
@@ -487,151 +557,29 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
487
557
  }
488
558
 
489
559
  // imperfect but good enough, should be the width of the W in the font / size combo
490
- const MIN_WIDTHS = Object.freeze({
560
+ const minWidths = {
491
561
  s: 12,
492
562
  m: 14,
493
563
  l: 16,
494
564
  xl: 20,
495
- })
565
+ }
496
566
 
497
- const EXTRA_PADDINGS = Object.freeze({
567
+ const extraPaddings = {
498
568
  s: 2,
499
569
  m: 3.5,
500
570
  l: 5,
501
571
  xl: 10,
502
- })
503
-
504
- const EMPTY_LABEL_SIZE = Object.freeze({ w: 0, h: 0 })
505
-
506
- // Margin between label edge and shape edge (in unscaled units)
507
- const LABEL_EDGE_MARGIN = 8
508
-
509
- /** Calculate label bounds for hit testing */
510
- function getLabelBounds(
511
- unscaledShapeW: number,
512
- unscaledShapeH: number,
513
- unscaledLabelSize: { w: number; h: number },
514
- size: TLGeoShapeProps['size'],
515
- align: TLGeoShapeProps['align'],
516
- verticalAlign: TLGeoShapeProps['verticalAlign'],
517
- scale: number
518
- ): { x: number; y: number; width: number; height: number } {
519
- // Calculate minimum label dimensions based on font size and shape size
520
- const unscaledMinWidth = Math.min(100, unscaledShapeW / 2)
521
- const unscaledMinHeight = Math.min(
522
- LABEL_FONT_SIZES[size] * TEXT_PROPS.lineHeight + LABEL_PADDING * 2,
523
- unscaledShapeH / 2
524
- )
525
-
526
- // Label dimensions: at least the measured size, but constrained to shape bounds
527
- const unscaledLabelW = Math.min(
528
- unscaledShapeW,
529
- Math.max(
530
- unscaledLabelSize.w,
531
- Math.min(unscaledMinWidth, Math.max(1, unscaledShapeW - LABEL_EDGE_MARGIN))
532
- )
533
- )
534
- const unscaledLabelH = Math.min(
535
- unscaledShapeH,
536
- Math.max(
537
- unscaledLabelSize.h,
538
- Math.min(unscaledMinHeight, Math.max(1, unscaledShapeH - LABEL_EDGE_MARGIN))
539
- )
540
- )
541
-
542
- // Calculate position based on alignment
543
- const unscaledX =
544
- align === 'start'
545
- ? 0
546
- : align === 'end'
547
- ? unscaledShapeW - unscaledLabelW
548
- : (unscaledShapeW - unscaledLabelW) / 2
549
-
550
- const unscaledY =
551
- verticalAlign === 'start'
552
- ? 0
553
- : verticalAlign === 'end'
554
- ? unscaledShapeH - unscaledLabelH
555
- : (unscaledShapeH - unscaledLabelH) / 2
556
-
557
- return {
558
- x: unscaledX * scale,
559
- y: unscaledY * scale,
560
- width: unscaledLabelW * scale,
561
- height: unscaledLabelH * scale,
562
- }
563
572
  }
564
573
 
565
- /** Get the unscaled dimensions from a geo shape's props */
566
- function getUnscaledGeoProps(props: TLGeoShapeProps) {
567
- const { w, h, growY, scale } = props
568
- return {
569
- w: w / scale,
570
- h: h / scale,
571
- growY: growY / scale,
572
- }
573
- }
574
-
575
- /**
576
- * Calculate the growY needed to fit a label within a shape.
577
- * Returns null if no change is needed, otherwise returns the new unscaled growY value.
578
- */
579
- function calculateGrowY(
580
- unscaledShapeH: number,
581
- unscaledLabelH: number,
582
- unscaledCurrentGrowY: number
583
- ): number | null {
584
- if (unscaledLabelH > unscaledShapeH) {
585
- // Label is taller than shape - need to grow
586
- return unscaledLabelH - unscaledShapeH
587
- }
588
- if (unscaledCurrentGrowY > 0) {
589
- // Label fits and we have existing growY - reset it
590
- return 0
591
- }
592
- // No change needed
593
- return null
594
- }
595
-
596
- /**
597
- * Calculate expanded dimensions when adding a label to a shape for the first time.
598
- * Ensures the shape meets minimum size requirements and is square if originally small.
599
- */
600
- function expandShapeForFirstLabel(
601
- unscaledW: number,
602
- unscaledH: number,
603
- unscaledLabelSize: { w: number; h: number }
604
- ): { w: number; h: number } {
605
- let w = Math.max(unscaledW, unscaledLabelSize.w)
606
- let h = Math.max(unscaledH, unscaledLabelSize.h)
607
-
608
- // If shape was smaller than min size in both dimensions, make it square
609
- if (unscaledW < MIN_SIZE_WITH_LABEL && unscaledH < MIN_SIZE_WITH_LABEL) {
610
- w = Math.max(w, MIN_SIZE_WITH_LABEL)
611
- h = Math.max(h, MIN_SIZE_WITH_LABEL)
612
- // Make square by using the larger dimension
613
- const maxDim = Math.max(w, h)
614
- w = maxDim
615
- h = maxDim
616
- }
617
-
618
- return { w, h }
619
- }
620
-
621
- const labelSizesForGeo = new WeakCache<TLGeoShape, { w: number; h: number }>()
622
-
623
- // Returns cached label size for the shape. Don't call with empty rich text.
624
574
  function getUnscaledLabelSize(editor: Editor, shape: TLGeoShape) {
625
- return labelSizesForGeo.get(shape, () => {
626
- return measureUnscaledLabelSize(editor, shape)
627
- })
628
- }
629
-
630
- // This is the expensive part of the code so we want to avoid calling it if we can
631
- function measureUnscaledLabelSize(editor: Editor, shape: TLGeoShape) {
632
575
  const { richText, font, size, w } = shape.props
633
576
 
634
- const minWidth = MIN_WIDTHS[size]
577
+ if (!richText || isEmptyRichText(richText)) {
578
+ return { w: 0, h: 0 }
579
+ }
580
+
581
+ // way too expensive to be recomputing on every update
582
+ const minWidth = minWidths[size]
635
583
 
636
584
  const html = renderHtmlFromRichTextForMeasurement(editor, richText)
637
585
  const textSize = editor.textMeasure.measureHtml(html, {
@@ -643,7 +591,7 @@ function measureUnscaledLabelSize(editor: Editor, shape: TLGeoShape) {
643
591
  // Guard because a DOM nodes can't be less 0
644
592
  0,
645
593
  // A 'w' width that we're setting as the min-width
646
- Math.ceil(minWidth + EXTRA_PADDINGS[size]),
594
+ Math.ceil(minWidth + extraPaddings[size]),
647
595
  // The actual text size
648
596
  Math.ceil(w / shape.props.scale - LABEL_PADDING * 2)
649
597
  ),
@@ -1,5 +1,4 @@
1
1
  import { StateNode, TLKeyboardEventInfo, TLPointerEventInfo } from '@tldraw/editor'
2
- import { startEditingShapeWithRichText } from '../../../tools/SelectTool/selectHelpers'
3
2
 
4
3
  export class Idle extends StateNode {
5
4
  static override id = 'idle'
@@ -13,11 +12,22 @@ export class Idle extends StateNode {
13
12
  }
14
13
 
15
14
  override onKeyUp(info: TLKeyboardEventInfo) {
16
- const { editor } = this
17
15
  if (info.key === 'Enter') {
18
- const onlySelectedShape = editor.getOnlySelectedShape()
19
- if (editor.canEditShape(onlySelectedShape)) {
20
- startEditingShapeWithRichText(editor, onlySelectedShape, { selectAll: true })
16
+ if (this.editor.getIsReadonly()) return null
17
+
18
+ const onlySelectedShape = this.editor.getOnlySelectedShape()
19
+ // If the only selected shape is editable, start editing it
20
+ if (
21
+ onlySelectedShape &&
22
+ this.editor.getShapeUtil(onlySelectedShape).canEdit(onlySelectedShape)
23
+ ) {
24
+ this.editor.setCurrentTool('select')
25
+ this.editor.setEditingShape(onlySelectedShape.id)
26
+ this.editor.root.getCurrent()?.transition('editing_shape', {
27
+ ...info,
28
+ target: 'shape',
29
+ shape: onlySelectedShape,
30
+ })
21
31
  }
22
32
  }
23
33
  }
@@ -16,15 +16,15 @@ export class Pointing extends StateNode {
16
16
  }
17
17
 
18
18
  override onPointerMove(info: TLPointerEventInfo) {
19
- if (this.editor.inputs.getIsDragging()) {
20
- const originPagePoint = this.editor.inputs.getOriginPagePoint()
19
+ if (this.editor.inputs.isDragging) {
20
+ const { originPagePoint } = this.editor.inputs
21
21
 
22
22
  const id = createShapeId()
23
23
 
24
24
  const creatingMarkId = this.editor.markHistoryStoppingPoint(`creating_geo:${id}`)
25
25
  const newPoint = maybeSnapToGrid(originPagePoint, this.editor)
26
26
  this.editor
27
- .createShapes([
27
+ .createShapes<TLGeoShape>([
28
28
  {
29
29
  id,
30
30
  type: 'geo',
@@ -71,7 +71,7 @@ export class Pointing extends StateNode {
71
71
  }
72
72
 
73
73
  private complete() {
74
- const originPagePoint = this.editor.inputs.getOriginPagePoint()
74
+ const { originPagePoint } = this.editor.inputs
75
75
 
76
76
  const id = createShapeId()
77
77
 
@@ -88,7 +88,7 @@ export class Pointing extends StateNode {
88
88
  ? { w: 300, h: 180 }
89
89
  : { w: 200, h: 200 }
90
90
 
91
- this.editor.createShapes([
91
+ this.editor.createShapes<TLGeoShape>([
92
92
  {
93
93
  id,
94
94
  type: 'geo',
@@ -115,7 +115,7 @@ export class Pointing extends StateNode {
115
115
  if (parentTransform) delta.rot(-parentTransform.rotation())
116
116
  const newPoint = maybeSnapToGrid(new Vec(shape.x - delta.x, shape.y - delta.y), this.editor)
117
117
  this.editor.select(id)
118
- this.editor.updateShape({
118
+ this.editor.updateShape<TLGeoShape>({
119
119
  id: shape.id,
120
120
  type: 'geo',
121
121
  x: newPoint.x,