tldraw 3.15.0-next.f1dfcef63951 → 3.16.0-next.c30b1b5e551a

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 (247) hide show
  1. package/dist-cjs/index.d.ts +161 -95
  2. package/dist-cjs/index.js +42 -31
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawImage.js +5 -2
  5. package/dist-cjs/lib/TldrawImage.js.map +3 -3
  6. package/dist-cjs/lib/canvas/TldrawCropHandles.js +1 -1
  7. package/dist-cjs/lib/canvas/TldrawCropHandles.js.map +2 -2
  8. package/dist-cjs/lib/canvas/TldrawHandles.js +1 -1
  9. package/dist-cjs/lib/canvas/TldrawHandles.js.map +2 -2
  10. package/dist-cjs/lib/canvas/TldrawOverlays.js +1 -1
  11. package/dist-cjs/lib/canvas/TldrawOverlays.js.map +2 -2
  12. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js +279 -271
  13. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js.map +2 -2
  14. package/dist-cjs/lib/defaultExternalContentHandlers.js +1 -0
  15. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  16. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +22 -36
  17. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  18. package/dist-cjs/lib/shapes/arrow/arrowLabel.js +16 -4
  19. package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +2 -2
  20. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +3 -0
  21. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  22. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +5 -5
  23. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  24. package/dist-cjs/lib/shapes/line/LineShapeUtil.js +15 -1
  25. package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
  26. package/dist-cjs/lib/shapes/shared/PathBuilder.js +21 -3
  27. package/dist-cjs/lib/shapes/shared/PathBuilder.js.map +2 -2
  28. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -0
  29. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  30. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +1 -0
  31. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
  32. package/dist-cjs/lib/shapes/text/TextShapeUtil.js +5 -11
  33. package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
  34. package/dist-cjs/lib/styles.js.map +2 -2
  35. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +43 -22
  36. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  37. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +2 -15
  38. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
  39. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js +5 -0
  40. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js.map +2 -2
  41. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +8 -0
  42. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  43. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js +8 -0
  44. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js.map +2 -2
  45. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +8 -0
  46. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  47. package/dist-cjs/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.js.map +2 -2
  48. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +51 -1
  49. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +2 -2
  50. package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js +1 -0
  51. package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js.map +2 -2
  52. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js +3 -4
  53. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js.map +2 -2
  54. package/dist-cjs/lib/ui/components/Spinner.js +2 -25
  55. package/dist-cjs/lib/ui/components/Spinner.js.map +2 -2
  56. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +2 -1
  57. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  58. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
  59. package/dist-cjs/lib/ui/components/menu-items.js +16 -0
  60. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  61. package/dist-cjs/lib/ui/components/primitives/Button/TldrawUiButtonIcon.js.map +2 -2
  62. package/dist-cjs/lib/ui/components/primitives/TldrawUiDialog.js +1 -1
  63. package/dist-cjs/lib/ui/components/primitives/TldrawUiDialog.js.map +2 -2
  64. package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js +35 -1
  65. package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js.map +2 -2
  66. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +6 -2
  67. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  68. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +1 -0
  69. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  70. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js.map +2 -2
  71. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +0 -2
  72. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  73. package/dist-cjs/lib/ui/context/actions.js +42 -8
  74. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  75. package/dist-cjs/lib/ui/context/events.js.map +2 -2
  76. package/dist-cjs/lib/ui/hooks/menu-hooks.js.map +2 -2
  77. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +24 -7
  78. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
  79. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +2 -2
  80. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js.map +2 -2
  81. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  82. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  83. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +8 -0
  84. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  85. package/dist-cjs/lib/ui/kbd-utils.js +2 -1
  86. package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
  87. package/dist-cjs/lib/ui/version.js +3 -3
  88. package/dist-cjs/lib/ui/version.js.map +1 -1
  89. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js +1 -1
  90. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js.map +2 -2
  91. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js +3 -2
  92. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js.map +2 -2
  93. package/dist-esm/index.d.mts +161 -95
  94. package/dist-esm/index.mjs +154 -135
  95. package/dist-esm/index.mjs.map +2 -2
  96. package/dist-esm/lib/TldrawImage.mjs +5 -2
  97. package/dist-esm/lib/TldrawImage.mjs.map +2 -2
  98. package/dist-esm/lib/canvas/TldrawCropHandles.mjs +1 -1
  99. package/dist-esm/lib/canvas/TldrawCropHandles.mjs.map +2 -2
  100. package/dist-esm/lib/canvas/TldrawHandles.mjs +1 -1
  101. package/dist-esm/lib/canvas/TldrawHandles.mjs.map +2 -2
  102. package/dist-esm/lib/canvas/TldrawOverlays.mjs +1 -1
  103. package/dist-esm/lib/canvas/TldrawOverlays.mjs.map +2 -2
  104. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs +279 -271
  105. package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs.map +2 -2
  106. package/dist-esm/lib/defaultExternalContentHandlers.mjs +1 -0
  107. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  108. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +24 -36
  109. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  110. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +19 -5
  111. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +2 -2
  112. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +3 -0
  113. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  114. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +5 -5
  115. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  116. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +15 -1
  117. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
  118. package/dist-esm/lib/shapes/shared/PathBuilder.mjs +22 -3
  119. package/dist-esm/lib/shapes/shared/PathBuilder.mjs.map +2 -2
  120. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -0
  121. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  122. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +1 -0
  123. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  124. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +5 -11
  125. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
  126. package/dist-esm/lib/styles.mjs.map +2 -2
  127. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +43 -22
  128. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  129. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +2 -15
  130. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
  131. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs +5 -0
  132. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs.map +2 -2
  133. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +8 -0
  134. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  135. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs +8 -0
  136. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs.map +2 -2
  137. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +8 -0
  138. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  139. package/dist-esm/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.mjs.map +2 -2
  140. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +51 -1
  141. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +2 -2
  142. package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs +2 -0
  143. package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs.map +2 -2
  144. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs +3 -4
  145. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs.map +2 -2
  146. package/dist-esm/lib/ui/components/Spinner.mjs +3 -26
  147. package/dist-esm/lib/ui/components/Spinner.mjs.map +2 -2
  148. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +2 -1
  149. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  150. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
  151. package/dist-esm/lib/ui/components/menu-items.mjs +16 -0
  152. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  153. package/dist-esm/lib/ui/components/primitives/Button/TldrawUiButtonIcon.mjs.map +2 -2
  154. package/dist-esm/lib/ui/components/primitives/TldrawUiDialog.mjs +1 -1
  155. package/dist-esm/lib/ui/components/primitives/TldrawUiDialog.mjs.map +2 -2
  156. package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs +36 -2
  157. package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs.map +2 -2
  158. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +6 -2
  159. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  160. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +1 -0
  161. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  162. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs.map +2 -2
  163. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +0 -2
  164. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  165. package/dist-esm/lib/ui/context/actions.mjs +42 -8
  166. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  167. package/dist-esm/lib/ui/context/events.mjs.map +2 -2
  168. package/dist-esm/lib/ui/hooks/menu-hooks.mjs.map +2 -2
  169. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +24 -7
  170. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
  171. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs +2 -2
  172. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs.map +2 -2
  173. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  174. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +8 -0
  175. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  176. package/dist-esm/lib/ui/kbd-utils.mjs +2 -1
  177. package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
  178. package/dist-esm/lib/ui/version.mjs +3 -3
  179. package/dist-esm/lib/ui/version.mjs.map +1 -1
  180. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs +1 -1
  181. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs.map +2 -2
  182. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs +3 -2
  183. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs.map +2 -2
  184. package/package.json +4 -3
  185. package/src/index.ts +174 -160
  186. package/src/lib/TldrawImage.tsx +6 -2
  187. package/src/lib/canvas/TldrawCropHandles.tsx +3 -1
  188. package/src/lib/canvas/TldrawHandles.tsx +5 -1
  189. package/src/lib/canvas/TldrawOverlays.tsx +1 -1
  190. package/src/lib/canvas/TldrawSelectionForeground.tsx +5 -1
  191. package/src/lib/defaultExternalContentHandlers.ts +2 -1
  192. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +5 -5
  193. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +25 -39
  194. package/src/lib/shapes/arrow/arrowLabel.ts +23 -3
  195. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +3 -0
  196. package/src/lib/shapes/frame/FrameShapeUtil.tsx +5 -7
  197. package/src/lib/shapes/line/LineShapeUtil.tsx +19 -2
  198. package/src/lib/shapes/shared/PathBuilder.test.tsx +1 -1
  199. package/src/lib/shapes/shared/PathBuilder.tsx +35 -1
  200. package/src/lib/shapes/shared/PlainTextLabel.tsx +1 -0
  201. package/src/lib/shapes/shared/RichTextLabel.tsx +1 -0
  202. package/src/lib/shapes/text/TextShapeUtil.tsx +5 -12
  203. package/src/lib/styles.tsx +3 -1
  204. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +54 -30
  205. package/src/lib/tools/SelectTool/childStates/Idle.ts +2 -24
  206. package/src/lib/tools/SelectTool/childStates/PointingShape.ts +7 -0
  207. package/src/lib/tools/SelectTool/childStates/Resizing.ts +12 -1
  208. package/src/lib/tools/SelectTool/childStates/Rotating.ts +11 -0
  209. package/src/lib/tools/SelectTool/childStates/Translating.ts +11 -0
  210. package/src/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.ts +1 -0
  211. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +40 -0
  212. package/src/lib/ui/components/MainMenu/DefaultMainMenuContent.tsx +2 -0
  213. package/src/lib/ui/components/NavigationPanel/DefaultNavigationPanel.tsx +3 -4
  214. package/src/lib/ui/components/Spinner.tsx +2 -24
  215. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +1 -0
  216. package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +3 -1
  217. package/src/lib/ui/components/menu-items.tsx +17 -0
  218. package/src/lib/ui/components/primitives/Button/TldrawUiButtonIcon.tsx +2 -2
  219. package/src/lib/ui/components/primitives/TldrawUiDialog.tsx +1 -1
  220. package/src/lib/ui/components/primitives/TldrawUiIcon.tsx +41 -3
  221. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +6 -1
  222. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +4 -0
  223. package/src/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.tsx +2 -2
  224. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +3 -4
  225. package/src/lib/ui/context/actions.tsx +44 -9
  226. package/src/lib/ui/context/events.tsx +4 -2
  227. package/src/lib/ui/hooks/menu-hooks.ts +1 -0
  228. package/src/lib/ui/hooks/useClipboardEvents.ts +31 -10
  229. package/src/lib/ui/hooks/useKeyboardShortcuts.ts +3 -2
  230. package/src/lib/ui/hooks/useTools.tsx +2 -1
  231. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +8 -0
  232. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +8 -0
  233. package/src/lib/ui/kbd-utils.ts +2 -1
  234. package/src/lib/ui/version.ts +3 -3
  235. package/src/lib/ui.css +8 -22
  236. package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +16 -2
  237. package/src/lib/utils/excalidraw/putExcalidrawContent.ts +1 -1
  238. package/src/lib/utils/tldr/__snapshots__/buildFromV1Document.test.ts.snap +24 -3
  239. package/src/lib/utils/tldr/buildFromV1Document.ts +2 -1
  240. package/src/test/Editor.test.tsx +68 -1
  241. package/src/test/SelectTool.test.ts +37 -11
  242. package/src/test/commands/clipboard.test.ts +1 -1
  243. package/src/test/commands/deletePage.test.ts +84 -1
  244. package/src/test/navigation.test.ts +254 -0
  245. package/src/test/shapeutils.test.ts +394 -45
  246. package/tldraw.css +29 -49
  247. package/src/test/editor.test.ts +0 -77
@@ -1,4 +1,4 @@
1
- import { createShapeId, TLFrameShape, TLGeoShape } from '@tldraw/editor'
1
+ import { createShapeId, TLFrameShape, TLGeoShape, TLLineShape } from '@tldraw/editor'
2
2
  import { TestEditor } from './TestEditor'
3
3
 
4
4
  let editor: TestEditor
@@ -11,6 +11,8 @@ const ids = {
11
11
  frame1: createShapeId('frame1'),
12
12
  box1: createShapeId('box1'),
13
13
  box2: createShapeId('box2'),
14
+ line1: createShapeId('line1'),
15
+ page1: createShapeId('page1'),
14
16
  }
15
17
 
16
18
  beforeEach(() => {
@@ -56,34 +58,93 @@ describe('When interacting with a shape...', () => {
56
58
  // Set start / change / end events on only the geo shape
57
59
  const util = editor.getShapeUtil<TLFrameShape>('frame')
58
60
 
59
- const fnStart = jest.fn()
60
- util.onRotateStart = fnStart
61
+ const calls: string[] = []
62
+
63
+ util.onRotateStart = () => {
64
+ calls.push('start')
65
+ }
61
66
 
62
- const fnChange = jest.fn()
63
- util.onRotate = fnChange
67
+ util.onRotate = () => {
68
+ calls.push('change')
69
+ }
64
70
 
65
- const fnEnd = jest.fn()
66
- util.onRotateEnd = fnEnd
71
+ util.onRotateEnd = () => {
72
+ calls.push('end')
73
+ }
67
74
 
68
75
  editor.selectAll()
69
76
  expect(editor.getSelectedShapeIds()).toMatchObject([ids.frame1, ids.box1])
70
77
 
71
- editor
72
- .pointerDown(300, 300, {
73
- target: 'selection',
74
- handle: 'bottom_right_rotate',
75
- })
76
- .pointerMove(200, 200)
77
- .pointerUp(200, 200)
78
+ editor.pointerDown(300, 300, {
79
+ target: 'selection',
80
+ handle: 'bottom_right_rotate',
81
+ })
78
82
 
79
- // Once on start (for frame only)
80
- expect(fnStart).toHaveBeenCalledTimes(1)
83
+ // Should not have called any callbacks yet
84
+ expect(calls).toEqual([])
85
+
86
+ editor.pointerMove(200, 200)
81
87
 
82
- // Once on start, once during the move
83
- expect(fnChange).toHaveBeenCalledTimes(2)
88
+ // Should have called start once and change at least once now
89
+ expect(calls).toEqual(['start', 'change'])
84
90
 
85
- // Once on end
86
- expect(fnEnd).toHaveBeenCalledTimes(1)
91
+ editor.pointerMove(200, 210)
92
+
93
+ // Should have called start once and change multiple times
94
+ expect(calls).toEqual(['start', 'change', 'change'])
95
+
96
+ editor.pointerUp(200, 210)
97
+
98
+ // Should have called end once now
99
+ expect(calls).toEqual(['start', 'change', 'change', 'change', 'end'])
100
+ })
101
+
102
+ it('fires rotate cancel events', () => {
103
+ const util = editor.getShapeUtil<TLFrameShape>('frame')
104
+
105
+ const calls: string[] = []
106
+
107
+ util.onRotateStart = () => {
108
+ calls.push('start')
109
+ }
110
+
111
+ util.onRotate = () => {
112
+ calls.push('change')
113
+ }
114
+
115
+ util.onRotateEnd = () => {
116
+ calls.push('end')
117
+ }
118
+
119
+ util.onRotateCancel = () => {
120
+ calls.push('cancel')
121
+ }
122
+
123
+ editor.selectAll()
124
+ expect(editor.getSelectedShapeIds()).toMatchObject([ids.frame1, ids.box1])
125
+
126
+ editor.pointerDown(300, 300, {
127
+ target: 'selection',
128
+ handle: 'bottom_right_rotate',
129
+ })
130
+
131
+ // Should not have called any callbacks yet
132
+ expect(calls).toEqual([])
133
+
134
+ editor.pointerMove(200, 200)
135
+
136
+ // Should have called start once and change at least once now
137
+ expect(calls).toEqual(['start', 'change'])
138
+
139
+ editor.pointerMove(200, 210)
140
+
141
+ // Should have called start once and change multiple times
142
+ expect(calls).toEqual(['start', 'change', 'change'])
143
+
144
+ editor.cancel()
145
+
146
+ // Should have called cancel instead of end
147
+ expect(calls).toEqual(['start', 'change', 'change', 'cancel'])
87
148
  })
88
149
 
89
150
  it('cleans up events', () => {
@@ -105,14 +166,19 @@ describe('When interacting with a shape...', () => {
105
166
  it('Fires resisizing events', () => {
106
167
  const util = editor.getShapeUtil<TLFrameShape>('frame')
107
168
 
108
- const fnStart = jest.fn()
109
- util.onResizeStart = fnStart
169
+ const calls: string[] = []
170
+
171
+ util.onResizeStart = () => {
172
+ calls.push('start')
173
+ }
110
174
 
111
- const fnChange = jest.fn()
112
- util.onResize = fnChange
175
+ util.onResize = () => {
176
+ calls.push('change')
177
+ }
113
178
 
114
- const fnEnd = jest.fn()
115
- util.onResizeEnd = fnEnd
179
+ util.onResizeEnd = () => {
180
+ calls.push('end')
181
+ }
116
182
 
117
183
  editor.selectAll()
118
184
  expect(editor.getSelectedShapeIds()).toMatchObject([ids.frame1, ids.box1])
@@ -123,48 +189,165 @@ describe('When interacting with a shape...', () => {
123
189
  })
124
190
 
125
191
  editor.expectToBeIn('select.pointing_resize_handle')
192
+
193
+ // Should not have called any callbacks yet
194
+ expect(calls).toEqual([])
195
+
126
196
  editor.pointerMove(200, 200)
127
197
  editor.expectToBeIn('select.resizing')
198
+
199
+ // Should have called start once and change at least once now
200
+ expect(calls).toEqual(['start', 'change'])
201
+
128
202
  editor.pointerMove(200, 210)
203
+
204
+ // Should have called start once and change multiple times
205
+ expect(calls).toEqual(['start', 'change', 'change'])
206
+
129
207
  editor.pointerUp(200, 210)
130
208
  editor.expectToBeIn('select.idle')
131
209
 
132
- // Once on start (for frame only)
133
- expect(fnStart).toHaveBeenCalledTimes(1)
210
+ // Should have called end once now
211
+ expect(calls).toEqual(['start', 'change', 'change', 'end'])
212
+ })
213
+
214
+ it('Fires resizing cancel events', () => {
215
+ const util = editor.getShapeUtil<TLFrameShape>('frame')
216
+
217
+ const calls: string[] = []
218
+
219
+ util.onResizeStart = () => {
220
+ calls.push('start')
221
+ }
134
222
 
135
- // Once on start, once during the resize
136
- expect(fnChange).toHaveBeenCalledTimes(2)
223
+ util.onResize = () => {
224
+ calls.push('change')
225
+ }
226
+
227
+ util.onResizeEnd = () => {
228
+ calls.push('end')
229
+ }
230
+
231
+ util.onResizeCancel = () => {
232
+ calls.push('cancel')
233
+ }
234
+
235
+ editor.selectAll()
236
+ expect(editor.getSelectedShapeIds()).toMatchObject([ids.frame1, ids.box1])
237
+
238
+ editor.pointerDown(300, 300, {
239
+ target: 'selection',
240
+ handle: 'bottom_right',
241
+ })
242
+
243
+ editor.expectToBeIn('select.pointing_resize_handle')
244
+
245
+ // Should not have called any callbacks yet
246
+ expect(calls).toEqual([])
247
+
248
+ editor.pointerMove(200, 200)
249
+ editor.expectToBeIn('select.resizing')
137
250
 
138
- // Once on end
139
- expect(fnEnd).toHaveBeenCalledTimes(1)
251
+ // Should have called start once and change at least once now
252
+ expect(calls).toEqual(['start', 'change'])
253
+
254
+ editor.pointerMove(200, 210)
255
+
256
+ // Should have called start once and change multiple times
257
+ expect(calls).toEqual(['start', 'change', 'change'])
258
+
259
+ editor.cancel()
260
+
261
+ // Should have called cancel instead of end
262
+ expect(calls).toEqual(['start', 'change', 'change', 'cancel'])
140
263
  })
141
264
 
142
265
  it('Fires translating events', () => {
143
266
  const util = editor.getShapeUtil<TLFrameShape>('frame')
144
267
 
145
- const fnStart = jest.fn()
146
- util.onTranslateStart = fnStart
268
+ const calls: string[] = []
269
+
270
+ util.onTranslateStart = () => {
271
+ calls.push('start')
272
+ }
147
273
 
148
- const fnChange = jest.fn()
149
- util.onTranslate = fnChange
274
+ util.onTranslate = () => {
275
+ calls.push('change')
276
+ }
150
277
 
151
- const fnEnd = jest.fn()
152
- util.onTranslateEnd = fnEnd
278
+ util.onTranslateEnd = () => {
279
+ calls.push('end')
280
+ }
153
281
 
154
282
  editor.selectAll()
155
283
  expect(editor.getSelectedShapeIds()).toMatchObject([ids.frame1, ids.box1])
156
284
 
157
285
  // Translate the shapes...
158
- editor.pointerDown(50, 50, ids.box1).pointerMove(50, 40).pointerUp(50, 40)
286
+ editor.pointerDown(50, 50, ids.box1)
159
287
 
160
- // Once on start for frame
161
- expect(fnStart).toHaveBeenCalledTimes(1)
288
+ // Should not have called any callbacks yet
289
+ expect(calls).toEqual([])
290
+
291
+ editor.pointerMove(50, 40)
162
292
 
163
- // Once on start, once during the move
164
- expect(fnChange).toHaveBeenCalledTimes(2)
293
+ // Should have called start once and change at least once now
294
+ expect(calls).toEqual(['start', 'change'])
165
295
 
166
- // Once on end
167
- expect(fnEnd).toHaveBeenCalledTimes(1)
296
+ editor.pointerMove(50, 35)
297
+
298
+ // Should have called start once and change multiple times
299
+ expect(calls).toEqual(['start', 'change', 'change'])
300
+
301
+ editor.pointerUp(50, 35)
302
+
303
+ // Should have called end once now
304
+ expect(calls).toEqual(['start', 'change', 'change', 'change', 'end'])
305
+ })
306
+
307
+ it('Fires translating cancel events', () => {
308
+ const util = editor.getShapeUtil<TLFrameShape>('frame')
309
+
310
+ const calls: string[] = []
311
+
312
+ util.onTranslateStart = () => {
313
+ calls.push('start')
314
+ }
315
+
316
+ util.onTranslate = () => {
317
+ calls.push('change')
318
+ }
319
+
320
+ util.onTranslateEnd = () => {
321
+ calls.push('end')
322
+ }
323
+
324
+ util.onTranslateCancel = () => {
325
+ calls.push('cancel')
326
+ }
327
+
328
+ editor.selectAll()
329
+ expect(editor.getSelectedShapeIds()).toMatchObject([ids.frame1, ids.box1])
330
+
331
+ // Translate the shapes...
332
+ editor.pointerDown(50, 50, ids.box1)
333
+
334
+ // Should not have called any callbacks yet
335
+ expect(calls).toEqual([])
336
+
337
+ editor.pointerMove(50, 40)
338
+
339
+ // Should have called start once and change at least once now
340
+ expect(calls).toEqual(['start', 'change'])
341
+
342
+ editor.pointerMove(50, 35)
343
+
344
+ // Should have called start once and change multiple times
345
+ expect(calls).toEqual(['start', 'change', 'change'])
346
+
347
+ editor.cancel()
348
+
349
+ // Should have called cancel instead of end
350
+ expect(calls).toEqual(['start', 'change', 'change', 'cancel'])
168
351
  })
169
352
 
170
353
  it('Uses the shape utils onClick handler', () => {
@@ -201,4 +384,170 @@ describe('When interacting with a shape...', () => {
201
384
  // it should not be selected.
202
385
  expect(editor.getSelectedShapeIds().length).toBe(0)
203
386
  })
387
+
388
+ it('Fires handle dragging events', () => {
389
+ const util = editor.getShapeUtil<TLLineShape>('line')
390
+
391
+ const calls: string[] = []
392
+
393
+ util.onHandleDragStart = () => {
394
+ calls.push('start')
395
+ }
396
+
397
+ util.onHandleDrag = () => {
398
+ calls.push('change')
399
+ }
400
+
401
+ util.onHandleDragEnd = () => {
402
+ calls.push('end')
403
+ }
404
+
405
+ util.onHandleDragCancel = () => {
406
+ calls.push('cancel')
407
+ }
408
+
409
+ // Create a line shape with handles
410
+ const lineShape: TLLineShape = {
411
+ id: ids.line1,
412
+ type: 'line',
413
+ typeName: 'shape',
414
+ parentId: ids.page1,
415
+ index: 'a1' as any,
416
+ x: 100,
417
+ y: 100,
418
+ rotation: 0,
419
+ isLocked: false,
420
+ opacity: 1,
421
+ meta: {},
422
+ props: {
423
+ dash: 'draw',
424
+ size: 'm',
425
+ color: 'black',
426
+ spline: 'line',
427
+ scale: 1,
428
+ points: {
429
+ a1: { id: 'a1', index: 'a1' as any, x: 0, y: 0 },
430
+ a2: { id: 'a2', index: 'a2' as any, x: 100, y: 100 },
431
+ },
432
+ },
433
+ }
434
+
435
+ editor.createShapes([lineShape])
436
+
437
+ // Get the handle point
438
+ const handlePagePoint = editor
439
+ .getShapePageTransform(lineShape.id)!
440
+ .applyToPoint(lineShape.props.points['a2'])
441
+
442
+ editor.pointerDown(handlePagePoint.x, handlePagePoint.y, {
443
+ target: 'handle',
444
+ shape: editor.getShape(lineShape.id)!,
445
+ handle: { id: 'a2', type: 'vertex', index: 'a2' as any, x: 100, y: 100 },
446
+ })
447
+
448
+ editor.expectToBeIn('select.pointing_handle')
449
+
450
+ // Should not have called any callbacks yet
451
+ expect(calls).toEqual([])
452
+
453
+ editor.pointerMove(handlePagePoint.x + 20, handlePagePoint.y + 20) // Larger move to trigger drag
454
+ editor.expectToBeIn('select.dragging_handle')
455
+
456
+ // Should have called start once and change at least once now
457
+ expect(calls).toEqual(['start', 'change'])
458
+
459
+ editor.pointerMove(150, 150)
460
+
461
+ // Should have called start once and change multiple times
462
+ expect(calls).toEqual(['start', 'change', 'change'])
463
+
464
+ editor.pointerUp(150, 150)
465
+ editor.expectToBeIn('select.idle')
466
+
467
+ // Should have called end once now
468
+ expect(calls).toEqual(['start', 'change', 'change', 'end'])
469
+ })
470
+
471
+ it('Fires handle dragging cancel events', () => {
472
+ const util = editor.getShapeUtil<TLLineShape>('line')
473
+
474
+ const calls: string[] = []
475
+
476
+ util.onHandleDragStart = () => {
477
+ calls.push('start')
478
+ }
479
+
480
+ util.onHandleDrag = () => {
481
+ calls.push('change')
482
+ }
483
+
484
+ util.onHandleDragEnd = () => {
485
+ calls.push('end')
486
+ }
487
+
488
+ util.onHandleDragCancel = () => {
489
+ calls.push('cancel')
490
+ }
491
+
492
+ // Create a line shape with handles
493
+ const lineShape: TLLineShape = {
494
+ id: ids.line1,
495
+ type: 'line',
496
+ typeName: 'shape',
497
+ parentId: ids.page1,
498
+ index: 'a1' as any,
499
+ x: 100,
500
+ y: 100,
501
+ rotation: 0,
502
+ isLocked: false,
503
+ opacity: 1,
504
+ meta: {},
505
+ props: {
506
+ dash: 'draw',
507
+ size: 'm',
508
+ color: 'black',
509
+ spline: 'line',
510
+ scale: 1,
511
+ points: {
512
+ a1: { id: 'a1', index: 'a1' as any, x: 0, y: 0 },
513
+ a2: { id: 'a2', index: 'a2' as any, x: 100, y: 100 },
514
+ },
515
+ },
516
+ }
517
+
518
+ editor.createShapes([lineShape])
519
+
520
+ // Get the handle point
521
+ const handlePagePoint = editor
522
+ .getShapePageTransform(lineShape.id)!
523
+ .applyToPoint(lineShape.props.points['a2'])
524
+
525
+ editor.pointerDown(handlePagePoint.x, handlePagePoint.y, {
526
+ target: 'handle',
527
+ shape: editor.getShape(lineShape.id)!,
528
+ handle: { id: 'a2', type: 'vertex', index: 'a2' as any, x: 100, y: 100 },
529
+ })
530
+
531
+ editor.expectToBeIn('select.pointing_handle')
532
+
533
+ // Should not have called any callbacks yet
534
+ expect(calls).toEqual([])
535
+
536
+ editor.pointerMove(handlePagePoint.x + 20, handlePagePoint.y + 20) // Larger move to trigger drag
537
+ editor.expectToBeIn('select.dragging_handle')
538
+
539
+ // Should have called start once and change at least once now
540
+ expect(calls).toEqual(['start', 'change'])
541
+
542
+ editor.pointerMove(150, 150)
543
+
544
+ // Should have called start once and change multiple times
545
+ expect(calls).toEqual(['start', 'change', 'change'])
546
+
547
+ editor.cancel()
548
+ editor.expectToBeIn('select.idle')
549
+
550
+ // Should have called cancel instead of end
551
+ expect(calls).toEqual(['start', 'change', 'change', 'cancel'])
552
+ })
204
553
  })
package/tldraw.css CHANGED
@@ -171,7 +171,7 @@
171
171
  --color-text: hsl(0, 0%, 0%);
172
172
  --color-text-0: hsl(0, 0%, 11%);
173
173
  --color-text-1: hsl(0, 0%, 18%);
174
- --color-text-3: hsl(220, 2%, 65%);
174
+ --color-text-3: hsl(204, 4%, 45%);
175
175
  --color-text-shadow: hsl(0, 0%, 100%);
176
176
  --color-text-highlight: hsl(52, 100%, 50%);
177
177
  --color-text-highlight-p3: color(display-p3 0.972 0.8205 0.05);
@@ -226,7 +226,7 @@
226
226
  --color-text: hsl(210, 17%, 98%);
227
227
  --color-text-0: hsl(0, 9%, 94%);
228
228
  --color-text-1: hsl(0, 0%, 85%);
229
- --color-text-3: hsl(210, 6%, 45%);
229
+ --color-text-3: hsl(204, 4%, 75%);
230
230
  --color-text-shadow: hsl(210, 13%, 18%);
231
231
  --color-text-highlight: hsl(52, 100%, 41%);
232
232
  --color-text-highlight-p3: color(display-p3 0.8078 0.6225 0.0312);
@@ -778,8 +778,7 @@ input,
778
778
  position: static;
779
779
  }
780
780
 
781
- .tl-text-wrapper[data-isediting='false'] .tl-text-input,
782
- .tl-arrow-label[data-isediting='false'] .tl-text-input {
781
+ .tl-text-wrapper[data-isediting='false'] .tl-text-input {
783
782
  opacity: 0;
784
783
  cursor: var(--tl-cursor-default);
785
784
  }
@@ -972,14 +971,14 @@ input,
972
971
  font-size: 14px;
973
972
  font-weight: 500;
974
973
  opacity: 0;
975
- animation: fade-in 0.2s ease-in-out forwards;
974
+ animation: tl-fade-in 0.2s ease-in-out forwards;
976
975
  animation-delay: 0.2s;
977
976
  position: absolute;
978
977
  inset: 0px;
979
978
  z-index: var(--layer-canvas-blocker);
980
979
  }
981
980
 
982
- @keyframes fade-in {
981
+ @keyframes tl-fade-in {
983
982
  0% {
984
983
  opacity: 0;
985
984
  }
@@ -988,6 +987,19 @@ input,
988
987
  }
989
988
  }
990
989
 
990
+ .tl-spinner {
991
+ animation: tl-spin 1s linear infinite;
992
+ }
993
+
994
+ @keyframes tl-spin {
995
+ 0% {
996
+ transform: rotate(0deg);
997
+ }
998
+ 100% {
999
+ transform: rotate(360deg);
1000
+ }
1001
+ }
1002
+
991
1003
  /* ---------------------- Brush --------------------- */
992
1004
 
993
1005
  .tl-brush {
@@ -1179,7 +1191,7 @@ input,
1179
1191
 
1180
1192
  /* --------------------- Arrow shape -------------------- */
1181
1193
 
1182
- .tl-arrow-label {
1194
+ .tl-shape[data-shape-type='arrow'] .tl-text-label {
1183
1195
  position: absolute;
1184
1196
  top: -1px;
1185
1197
  left: -1px;
@@ -1194,33 +1206,15 @@ input,
1194
1206
  text-shadow: var(--tl-text-outline);
1195
1207
  }
1196
1208
 
1197
- .tl-arrow-label[data-isediting='true'] p {
1198
- opacity: 0;
1199
- }
1200
-
1201
- .tl-arrow-label__inner {
1209
+ .tl-shape[data-shape-type='arrow'] .tl-text-label__inner {
1202
1210
  border-radius: var(--radius-1);
1203
1211
  box-sizing: content-box;
1204
- position: relative;
1205
1212
  height: max-content;
1206
1213
  width: max-content;
1207
- pointer-events: none;
1208
- display: flex;
1209
- justify-content: center;
1210
- align-items: center;
1211
1214
  }
1212
1215
 
1213
- .tl-arrow-label .tl-arrow {
1214
- position: relative;
1216
+ .tl-shape[data-shape-type='arrow'] .tl-text {
1215
1217
  height: max-content;
1216
- padding: inherit;
1217
- overflow: visible;
1218
- }
1219
-
1220
- .tl-arrow-label textarea {
1221
- padding: inherit;
1222
- /* Don't allow textarea to be zero width */
1223
- min-width: 4px;
1224
1218
  }
1225
1219
 
1226
1220
  .tl-arrow-hint {
@@ -2748,7 +2742,7 @@ it from receiving any pointer events or affecting the cursor. */
2748
2742
  justify-content: center;
2749
2743
  border-radius: 99px;
2750
2744
  opacity: 0;
2751
- animation: fade-in;
2745
+ animation: tl-fade-in;
2752
2746
  animation-duration: 0.12s;
2753
2747
  animation-delay: 2s;
2754
2748
  animation-fill-mode: forwards;
@@ -2892,20 +2886,6 @@ it from receiving any pointer events or affecting the cursor. */
2892
2886
  display: none;
2893
2887
  }
2894
2888
 
2895
- .tlui-navigation-panel__toggle .tlui-icon {
2896
- opacity: 0.24;
2897
- }
2898
-
2899
- .tlui-navigation-panel__toggle:active .tlui-icon {
2900
- opacity: 1;
2901
- }
2902
-
2903
- @media (hover: hover) {
2904
- .tlui-navigation-panel__toggle:hover .tlui-icon {
2905
- opacity: 1;
2906
- }
2907
- }
2908
-
2909
2889
  /* Minimap */
2910
2890
 
2911
2891
  .tlui-minimap {
@@ -3163,11 +3143,11 @@ it from receiving any pointer events or affecting the cursor. */
3163
3143
 
3164
3144
  @media (prefers-reduced-motion: no-preference) {
3165
3145
  .tlui-toast__container[data-state='open'] {
3166
- animation: slide-in 200ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
3146
+ animation: tlui-slide-in 200ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
3167
3147
  }
3168
3148
 
3169
3149
  .tlui-toast__container[data-state='closed'] {
3170
- animation: hide 100ms ease-in;
3150
+ animation: tlui-fade-out 100ms ease-in;
3171
3151
  }
3172
3152
 
3173
3153
  .tlui-toast__container[data-swipe='move'] {
@@ -3180,7 +3160,7 @@ it from receiving any pointer events or affecting the cursor. */
3180
3160
  }
3181
3161
 
3182
3162
  .tlui-toast__container[data-swipe='end'] {
3183
- animation: swipe-out 100ms ease-out;
3163
+ animation: tlui-slide-out 100ms ease-out;
3184
3164
  }
3185
3165
  }
3186
3166
 
@@ -3195,7 +3175,7 @@ it from receiving any pointer events or affecting the cursor. */
3195
3175
  z-index: var(--layer-canvas-overlays);
3196
3176
  background-color: var(--color-overlay);
3197
3177
  pointer-events: all;
3198
- animation: fadeIn 0.12s ease-out;
3178
+ animation: tl-fade-in 0.12s ease-out;
3199
3179
  display: grid;
3200
3180
  place-items: center;
3201
3181
  overflow-y: auto;
@@ -3762,7 +3742,7 @@ it from receiving any pointer events or affecting the cursor. */
3762
3742
  }
3763
3743
 
3764
3744
  /* ------------------- Animations ------------------- */
3765
- @keyframes hide {
3745
+ @keyframes tlui-fade-out {
3766
3746
  0% {
3767
3747
  opacity: 1;
3768
3748
  }
@@ -3771,7 +3751,7 @@ it from receiving any pointer events or affecting the cursor. */
3771
3751
  }
3772
3752
  }
3773
3753
 
3774
- @keyframes slide-in {
3754
+ @keyframes tlui-slide-in {
3775
3755
  from {
3776
3756
  transform: translateX(calc(100% + var(--space-3)));
3777
3757
  }
@@ -3780,7 +3760,7 @@ it from receiving any pointer events or affecting the cursor. */
3780
3760
  }
3781
3761
  }
3782
3762
 
3783
- @keyframes swipe-out {
3763
+ @keyframes tlui-slide-out {
3784
3764
  from {
3785
3765
  transform: translateX(var(--radix-toast-swipe-end-x));
3786
3766
  }