tldraw 3.16.0-next.4337ae1ab96d → 3.16.0-next.8eb6d5c2d8f4

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 (224) hide show
  1. package/dist-cjs/index.d.ts +100 -14
  2. package/dist-cjs/index.js +6 -2
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/defaultExternalContentHandlers.js +10 -0
  5. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  6. package/dist-cjs/lib/shapes/arrow/arrow-types.js.map +1 -1
  7. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js +3 -2
  8. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
  9. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +1 -1
  10. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  11. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +4 -4
  12. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  13. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +2 -1
  14. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  15. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js +8 -2
  16. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js.map +2 -2
  17. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +1 -0
  18. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  19. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +2 -1
  20. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  21. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +4 -4
  22. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js.map +2 -2
  23. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +3 -3
  24. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  25. package/dist-cjs/lib/shapes/text/PlainTextArea.js +3 -2
  26. package/dist-cjs/lib/shapes/text/PlainTextArea.js.map +2 -2
  27. package/dist-cjs/lib/shapes/text/RichTextArea.js +3 -3
  28. package/dist-cjs/lib/shapes/text/RichTextArea.js.map +2 -2
  29. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +3 -1
  30. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  31. package/dist-cjs/lib/ui/components/A11y.js +1 -1
  32. package/dist-cjs/lib/ui/components/A11y.js.map +2 -2
  33. package/dist-cjs/lib/ui/components/AccessibilityMenu.js +1 -1
  34. package/dist-cjs/lib/ui/components/AccessibilityMenu.js.map +2 -2
  35. package/dist-cjs/lib/ui/components/InputModeMenu.js +77 -0
  36. package/dist-cjs/lib/ui/components/InputModeMenu.js.map +7 -0
  37. package/dist-cjs/lib/ui/components/LanguageMenu.js +1 -0
  38. package/dist-cjs/lib/ui/components/LanguageMenu.js.map +2 -2
  39. package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js +2 -0
  40. package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js.map +2 -2
  41. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +2 -1
  42. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
  43. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +1 -1
  44. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
  45. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +4 -2
  46. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
  47. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +2 -2
  48. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  49. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js +12 -3
  50. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +2 -2
  51. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js +4 -2
  52. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js.map +2 -2
  53. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +3 -2
  54. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  55. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +5 -4
  56. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
  57. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +1 -1
  58. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +2 -2
  59. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +6 -2
  60. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
  61. package/dist-cjs/lib/ui/components/menu-items.js +6 -4
  62. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  63. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -1
  64. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  65. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +5 -3
  66. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js.map +2 -2
  67. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +1 -1
  68. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  69. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +1 -0
  70. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  71. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +68 -20
  72. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  73. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js +3 -0
  74. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js.map +2 -2
  75. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +8 -8
  76. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  77. package/dist-cjs/lib/ui/context/actions.js +11 -25
  78. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  79. package/dist-cjs/lib/ui/context/events.js.map +2 -2
  80. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +1 -1
  81. package/dist-cjs/lib/ui/hooks/useClipboardEvents.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 +11 -3
  84. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  85. package/dist-cjs/lib/ui/version.js +3 -3
  86. package/dist-cjs/lib/ui/version.js.map +1 -1
  87. package/dist-esm/index.d.mts +100 -14
  88. package/dist-esm/index.mjs +11 -3
  89. package/dist-esm/index.mjs.map +2 -2
  90. package/dist-esm/lib/defaultExternalContentHandlers.mjs +10 -0
  91. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  92. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs +3 -2
  93. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
  94. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +1 -1
  95. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  96. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +4 -5
  97. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  98. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +2 -1
  99. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  100. package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs +9 -3
  101. package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs.map +2 -2
  102. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +1 -0
  103. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  104. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +2 -1
  105. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  106. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs +5 -5
  107. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs.map +2 -2
  108. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +3 -4
  109. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  110. package/dist-esm/lib/shapes/text/PlainTextArea.mjs +4 -3
  111. package/dist-esm/lib/shapes/text/PlainTextArea.mjs.map +2 -2
  112. package/dist-esm/lib/shapes/text/RichTextArea.mjs +3 -4
  113. package/dist-esm/lib/shapes/text/RichTextArea.mjs.map +2 -2
  114. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +3 -1
  115. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  116. package/dist-esm/lib/ui/components/A11y.mjs +1 -2
  117. package/dist-esm/lib/ui/components/A11y.mjs.map +2 -2
  118. package/dist-esm/lib/ui/components/AccessibilityMenu.mjs +3 -3
  119. package/dist-esm/lib/ui/components/AccessibilityMenu.mjs.map +2 -2
  120. package/dist-esm/lib/ui/components/InputModeMenu.mjs +57 -0
  121. package/dist-esm/lib/ui/components/InputModeMenu.mjs.map +7 -0
  122. package/dist-esm/lib/ui/components/LanguageMenu.mjs +1 -0
  123. package/dist-esm/lib/ui/components/LanguageMenu.mjs.map +2 -2
  124. package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs +2 -0
  125. package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs.map +2 -2
  126. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +2 -1
  127. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
  128. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +1 -2
  129. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
  130. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +4 -2
  131. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
  132. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +2 -2
  133. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  134. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +12 -3
  135. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +2 -2
  136. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +4 -2
  137. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +2 -2
  138. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +3 -2
  139. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  140. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +5 -4
  141. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
  142. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +1 -1
  143. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +2 -2
  144. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +6 -2
  145. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
  146. package/dist-esm/lib/ui/components/menu-items.mjs +6 -4
  147. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  148. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +1 -2
  149. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  150. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs +6 -4
  151. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs.map +2 -2
  152. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +1 -1
  153. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  154. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +1 -0
  155. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  156. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +69 -20
  157. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  158. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs +3 -0
  159. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs.map +2 -2
  160. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +8 -8
  161. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  162. package/dist-esm/lib/ui/context/actions.mjs +11 -25
  163. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  164. package/dist-esm/lib/ui/context/events.mjs.map +2 -2
  165. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +1 -2
  166. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
  167. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +11 -3
  168. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  169. package/dist-esm/lib/ui/version.mjs +3 -3
  170. package/dist-esm/lib/ui/version.mjs.map +1 -1
  171. package/package.json +3 -3
  172. package/src/index.ts +8 -1
  173. package/src/lib/defaultExternalContentHandlers.ts +14 -0
  174. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +83 -13
  175. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +99 -5
  176. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +41 -0
  177. package/src/lib/shapes/arrow/arrow-types.ts +3 -5
  178. package/src/lib/shapes/arrow/arrowTargetState.ts +34 -3
  179. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +1 -1
  180. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +4 -5
  181. package/src/lib/shapes/frame/FrameShapeUtil.tsx +1 -0
  182. package/src/lib/shapes/frame/components/FrameLabelInput.tsx +10 -3
  183. package/src/lib/shapes/geo/GeoShapeUtil.tsx +1 -0
  184. package/src/lib/shapes/note/NoteShapeUtil.tsx +1 -0
  185. package/src/lib/shapes/shared/HyperlinkButton.tsx +5 -5
  186. package/src/lib/shapes/shared/useEditablePlainText.ts +3 -4
  187. package/src/lib/shapes/text/PlainTextArea.tsx +4 -3
  188. package/src/lib/shapes/text/RichTextArea.tsx +3 -4
  189. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +6 -2
  190. package/src/lib/ui/components/A11y.tsx +1 -2
  191. package/src/lib/ui/components/AccessibilityMenu.tsx +2 -2
  192. package/src/lib/ui/components/InputModeMenu.tsx +65 -0
  193. package/src/lib/ui/components/LanguageMenu.tsx +1 -0
  194. package/src/lib/ui/components/MainMenu/DefaultMainMenuContent.tsx +4 -0
  195. package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +2 -1
  196. package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +1 -2
  197. package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +4 -2
  198. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +4 -2
  199. package/src/lib/ui/components/StylePanel/StylePanelButtonPicker.tsx +10 -3
  200. package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +5 -3
  201. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +4 -3
  202. package/src/lib/ui/components/Toolbar/LinkEditor.tsx +6 -5
  203. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +1 -1
  204. package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +9 -2
  205. package/src/lib/ui/components/menu-items.tsx +5 -3
  206. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +1 -2
  207. package/src/lib/ui/components/primitives/TldrawUiInput.tsx +6 -3
  208. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +2 -2
  209. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +2 -1
  210. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +65 -14
  211. package/src/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.tsx +4 -0
  212. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +9 -9
  213. package/src/lib/ui/context/actions.tsx +18 -27
  214. package/src/lib/ui/context/events.tsx +2 -1
  215. package/src/lib/ui/hooks/useClipboardEvents.ts +1 -2
  216. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +10 -2
  217. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +11 -3
  218. package/src/lib/ui/version.ts +3 -3
  219. package/src/lib/ui.css +25 -2
  220. package/src/test/TestEditor.ts +8 -2
  221. package/src/test/commands/setCamera.test.ts +13 -0
  222. package/src/test/frames.test.ts +15 -0
  223. package/src/test/getCulledShapes.test.tsx +71 -2
  224. package/tldraw.css +33 -5
@@ -13,6 +13,7 @@ import {
13
13
  sortByIndex,
14
14
  structuredClone,
15
15
  } from '@tldraw/editor'
16
+ import { ArrowShapeUtil } from '../../../shapes/arrow/ArrowShapeUtil'
16
17
  import { clearArrowTargetState } from '../../../shapes/arrow/arrowTargetState'
17
18
  import { getArrowBindings } from '../../../shapes/arrow/shared'
18
19
 
@@ -135,10 +136,13 @@ export class DraggingHandle extends StateNode {
135
136
  }
136
137
 
137
138
  // Only relevant to arrows
138
- private exactTimeout = -1 as any
139
+ private exactTimeout = -1
139
140
 
140
141
  // Only relevant to arrows
141
142
  private resetExactTimeout() {
143
+ const arrowUtil = this.editor.getShapeUtil<ArrowShapeUtil>('arrow')
144
+ const timeoutValue = arrowUtil.options.pointingPreciseTimeout
145
+
142
146
  if (this.exactTimeout !== -1) {
143
147
  this.clearExactTimeout()
144
148
  }
@@ -150,7 +154,7 @@ export class DraggingHandle extends StateNode {
150
154
  this.update()
151
155
  }
152
156
  this.exactTimeout = -1
153
- }, 750)
157
+ }, timeoutValue)
154
158
  }
155
159
 
156
160
  // Only relevant to arrows
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  debugFlags,
3
3
  Editor,
4
- stopEventPropagation,
5
4
  TLGeoShape,
6
5
  TLShapeId,
7
6
  unsafe__withoutCapture,
@@ -23,7 +22,7 @@ export function SkipToMainContent() {
23
22
 
24
23
  const handleNavigateToFirstShape = useCallback(
25
24
  (e: MouseEvent | KeyboardEvent) => {
26
- stopEventPropagation(e)
25
+ editor.markEventAsHandled(e)
27
26
  button.current?.blur()
28
27
  const shapes = editor.getCurrentPageShapesInReadingOrder()
29
28
  if (!shapes.length) return
@@ -1,7 +1,7 @@
1
1
  import {
2
+ ToggleEnhancedA11yModeItem,
2
3
  ToggleKeyboardShortcutsItem,
3
4
  ToggleReduceMotionItem,
4
- ToggleUiLabelsItem,
5
5
  } from './menu-items'
6
6
  import { TldrawUiMenuGroup } from './primitives/menus/TldrawUiMenuGroup'
7
7
  import { TldrawUiMenuSubmenu } from './primitives/menus/TldrawUiMenuSubmenu'
@@ -13,7 +13,7 @@ export function AccessibilityMenu() {
13
13
  <TldrawUiMenuGroup id="accessibility">
14
14
  <ToggleReduceMotionItem />
15
15
  <ToggleKeyboardShortcutsItem />
16
- <ToggleUiLabelsItem />
16
+ <ToggleEnhancedA11yModeItem />
17
17
  </TldrawUiMenuGroup>
18
18
  </TldrawUiMenuSubmenu>
19
19
  )
@@ -0,0 +1,65 @@
1
+ import { useEditor, useValue } from '@tldraw/editor'
2
+ import { useUiEvents } from '../context/events'
3
+ import { TldrawUiMenuCheckboxItem } from './primitives/menus/TldrawUiMenuCheckboxItem'
4
+ import { TldrawUiMenuGroup } from './primitives/menus/TldrawUiMenuGroup'
5
+ import { TldrawUiMenuSubmenu } from './primitives/menus/TldrawUiMenuSubmenu'
6
+
7
+ const MODES = ['auto', 'trackpad', 'mouse'] as const
8
+
9
+ /** @public @react */
10
+ export function InputModeMenu() {
11
+ const editor = useEditor()
12
+ const trackEvent = useUiEvents()
13
+
14
+ const inputMode = useValue('inputMode', () => editor.user.getUserPreferences().inputMode, [
15
+ editor,
16
+ ])
17
+ const wheelBehavior = useValue('wheelBehavior', () => editor.getCameraOptions().wheelBehavior, [
18
+ editor,
19
+ ])
20
+
21
+ const isModeChecked = (mode: string) => {
22
+ if (mode === 'auto') {
23
+ return inputMode === null
24
+ }
25
+ return inputMode === mode
26
+ }
27
+
28
+ const getLabel = (mode: string, wheelBehavior: 'zoom' | 'pan' | 'none') => {
29
+ if (mode === 'auto') {
30
+ return `action.toggle-auto-${wheelBehavior}`
31
+ }
32
+
33
+ return mode === 'trackpad' ? 'action.toggle-trackpad' : 'action.toggle-mouse'
34
+ }
35
+
36
+ return (
37
+ <TldrawUiMenuSubmenu id="help menu input-mode" label="menu.input-mode">
38
+ <TldrawUiMenuGroup id="peripheral-mode">
39
+ {MODES.map((mode) => (
40
+ <TldrawUiMenuCheckboxItem
41
+ id={`peripheral-mode-${mode}`}
42
+ key={mode}
43
+ label={getLabel(mode, wheelBehavior)}
44
+ checked={isModeChecked(mode)}
45
+ readonlyOk
46
+ onSelect={() => {
47
+ trackEvent('input-mode', { source: 'menu', value: mode })
48
+ switch (mode) {
49
+ case 'auto':
50
+ editor.user.updateUserPreferences({ inputMode: null })
51
+ break
52
+ case 'trackpad':
53
+ editor.user.updateUserPreferences({ inputMode: 'trackpad' })
54
+ break
55
+ case 'mouse':
56
+ editor.user.updateUserPreferences({ inputMode: 'mouse' })
57
+ break
58
+ }
59
+ }}
60
+ />
61
+ ))}
62
+ </TldrawUiMenuGroup>
63
+ </TldrawUiMenuSubmenu>
64
+ )
65
+ }
@@ -18,6 +18,7 @@ export function LanguageMenu() {
18
18
  {LANGUAGES.map(({ locale, label }) => (
19
19
  <TldrawUiMenuCheckboxItem
20
20
  id={`language-${locale}`}
21
+ lang={locale}
21
22
  key={locale}
22
23
  title={locale}
23
24
  label={label}
@@ -2,6 +2,7 @@ import { useCanRedo, useCanUndo } from '../../hooks/menu-hooks'
2
2
  import { AccessibilityMenu } from '../AccessibilityMenu'
3
3
  import { ColorSchemeMenu } from '../ColorSchemeMenu'
4
4
  import { KeyboardShortcutsMenuItem } from '../HelpMenu/DefaultHelpMenuContent'
5
+ import { InputModeMenu } from '../InputModeMenu'
5
6
  import { LanguageMenu } from '../LanguageMenu'
6
7
  import {
7
8
  ClipboardMenuGroup,
@@ -164,6 +165,9 @@ export function PreferencesGroup() {
164
165
  <TogglePasteAtCursorItem />
165
166
  <ToggleDebugModeItem />
166
167
  </TldrawUiMenuGroup>
168
+ <TldrawUiMenuGroup id="input-mode">
169
+ <InputModeMenu />
170
+ </TldrawUiMenuGroup>
167
171
  <TldrawUiMenuGroup id="color-scheme">
168
172
  <ColorSchemeMenu />
169
173
  </TldrawUiMenuGroup>
@@ -159,7 +159,7 @@ export function DefaultMinimap() {
159
159
  type: 'pointer',
160
160
  target: 'canvas',
161
161
  name: 'pointer_move',
162
- ...getPointerInfo(e),
162
+ ...getPointerInfo(editor, e),
163
163
  point: screenPoint,
164
164
  isPen: editor.getInstanceState().isPenMode,
165
165
  }
@@ -204,6 +204,7 @@ export function DefaultMinimap() {
204
204
  <canvas
205
205
  role="img"
206
206
  aria-label={msg('navigation-zone.minimap')}
207
+ data-testid="minimap.canvas"
207
208
  ref={rCanvas}
208
209
  className="tlui-minimap__canvas"
209
210
  onDoubleClick={onDoubleClick}
@@ -3,7 +3,6 @@ import {
3
3
  TLPageId,
4
4
  releasePointerCapture,
5
5
  setPointerCapture,
6
- stopEventPropagation,
7
6
  tlenv,
8
7
  useEditor,
9
8
  useValue,
@@ -451,7 +450,7 @@ export const DefaultPageMenu = memo(function DefaultPageMenu() {
451
450
  if (e.key === 'Enter') {
452
451
  if (page.id === currentPage.id) {
453
452
  toggleEditing()
454
- stopEventPropagation(e)
453
+ editor.markEventAsHandled(e)
455
454
  }
456
455
  }
457
456
  }}
@@ -24,7 +24,9 @@ export const DefaultStylePanel = memo(function DefaultStylePanel({
24
24
  children,
25
25
  }: TLUiStylePanelProps) {
26
26
  const editor = useEditor()
27
- const showUiLabels = useValue('showUiLabels', () => editor.user.getShowUiLabels(), [editor])
27
+ const enhancedA11yMode = useValue('enhancedA11yMode', () => editor.user.getEnhancedA11yMode(), [
28
+ editor,
29
+ ])
28
30
 
29
31
  const ref = useRef<HTMLDivElement>(null)
30
32
  usePassThroughWheelEvents(ref)
@@ -62,7 +64,7 @@ export const DefaultStylePanel = memo(function DefaultStylePanel({
62
64
  data-testid="style.panel"
63
65
  className={classNames('tlui-style-panel', { 'tlui-style-panel__wrapper': !isMobile })}
64
66
  data-ismobile={isMobile}
65
- data-show-ui-labels={showUiLabels}
67
+ data-enhanced-a11y-mode={enhancedA11yMode}
66
68
  onPointerLeave={handlePointerOut}
67
69
  >
68
70
  <StylePanelContextProvider styles={styles}>
@@ -91,7 +91,7 @@ const tldrawSupportedOpacities = [0.1, 0.25, 0.5, 0.75, 1] as const
91
91
  /** @public @react */
92
92
  export function StylePanelOpacityPicker() {
93
93
  const editor = useEditor()
94
- const { onHistoryMark, showUiLabels } = useStylePanelContext()
94
+ const { onHistoryMark, enhancedA11yMode } = useStylePanelContext()
95
95
 
96
96
  const opacity = useValue('opacity', () => editor.getSharedOpacity(), [editor])
97
97
  const trackEvent = useUiEvents()
@@ -126,7 +126,9 @@ export function StylePanelOpacityPicker() {
126
126
 
127
127
  return (
128
128
  <>
129
- {showUiLabels && <StylePanelSubheading>{msg('style-panel.opacity')}</StylePanelSubheading>}
129
+ {enhancedA11yMode && (
130
+ <StylePanelSubheading>{msg('style-panel.opacity')}</StylePanelSubheading>
131
+ )}
130
132
  <TldrawUiSlider
131
133
  data-testid="style.opacity"
132
134
  value={opacityIndex >= 0 ? opacityIndex : tldrawSupportedOpacities.length - 1}
@@ -127,7 +127,7 @@ export const StylePanelButtonPicker = memo(function StylePanelButtonPicker<T ext
127
127
 
128
128
  return (
129
129
  <>
130
- {ctx.showUiLabels && <StylePanelSubheading>{title}</StylePanelSubheading>}
130
+ {ctx.enhancedA11yMode && <StylePanelSubheading>{title}</StylePanelSubheading>}
131
131
  <TldrawUiToolbar label={title}>
132
132
  <TldrawUiToolbarToggleGroup
133
133
  data-testid={`style.${uiType}`}
@@ -137,6 +137,7 @@ export const StylePanelButtonPicker = memo(function StylePanelButtonPicker<T ext
137
137
  >
138
138
  <Layout>
139
139
  {items.map((item) => {
140
+ const isActive = value.type === 'shared' && value.value === item.value
140
141
  const label =
141
142
  title + ' — ' + msg(`${uiType}-style.${item.value}` as TLUiTranslationKey)
142
143
  return (
@@ -145,10 +146,16 @@ export const StylePanelButtonPicker = memo(function StylePanelButtonPicker<T ext
145
146
  key={item.value}
146
147
  data-id={item.value}
147
148
  data-testid={`style.${uiType}.${item.value}`}
148
- aria-label={label}
149
+ aria-label={label + (isActive ? ` (${msg('style-panel.selected')})` : '')}
150
+ tooltip={
151
+ <>
152
+ <div>{label}</div>
153
+ {isActive ? <div>({msg('style-panel.selected')})</div> : null}
154
+ </>
155
+ }
149
156
  value={item.value}
150
157
  data-state={value.type === 'shared' && value.value === item.value ? 'on' : 'off'}
151
- data-isactive={value.type === 'shared' && value.value === item.value}
158
+ data-isactive={isActive}
152
159
  title={label}
153
160
  style={
154
161
  style === (DefaultColorStyle as StyleProp<unknown>)
@@ -5,7 +5,7 @@ import { useUiEvents } from '../../context/events'
5
5
  /** @public */
6
6
  export interface StylePanelContext {
7
7
  styles: ReadonlySharedStyleMap
8
- showUiLabels: boolean
8
+ enhancedA11yMode: boolean
9
9
  onHistoryMark(id: string): void
10
10
  onValueChange<T>(style: StyleProp<T>, value: T): void
11
11
  }
@@ -23,7 +23,9 @@ export function StylePanelContextProvider({ children, styles }: StylePanelContex
23
23
  const trackEvent = useUiEvents()
24
24
 
25
25
  const onHistoryMark = useCallback((id: string) => editor.markHistoryStoppingPoint(id), [editor])
26
- const showUiLabels = useValue('showUiLabels', () => editor.user.getShowUiLabels(), [editor])
26
+ const enhancedA11yMode = useValue('enhancedA11yMode', () => editor.user.getEnhancedA11yMode(), [
27
+ editor,
28
+ ])
27
29
  const onValueChange = useCallback(
28
30
  function <T>(style: StyleProp<T>, value: T) {
29
31
  editor.run(() => {
@@ -43,7 +45,7 @@ export function StylePanelContextProvider({ children, styles }: StylePanelContex
43
45
  <StylePanelContext.Provider
44
46
  value={{
45
47
  styles: styles,
46
- showUiLabels,
48
+ enhancedA11yMode,
47
49
  onHistoryMark,
48
50
  onValueChange,
49
51
  }}
@@ -2,9 +2,9 @@ import { preventDefault, TLShape, TLShapeId, useEditor } from '@tldraw/editor'
2
2
  import { useCallback, useEffect, useRef, useState } from 'react'
3
3
  import { useUiEvents } from '../../context/events'
4
4
  import { useTranslation } from '../../hooks/useTranslation/useTranslation'
5
+ import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
5
6
  import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
6
7
  import { TldrawUiInput } from '../primitives/TldrawUiInput'
7
- import { TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
8
8
 
9
9
  /** @public */
10
10
  export interface AltTextEditorProps {
@@ -70,13 +70,14 @@ export function AltTextEditor({ shapeId, onClose, source }: AltTextEditorProps)
70
70
  data-testid="media-toolbar.alt-text-input"
71
71
  value={altText}
72
72
  placeholder={msg('tool.media-alt-text-desc')}
73
+ aria-label={msg('tool.media-alt-text-desc')}
73
74
  onValueChange={handleValueChange}
74
75
  onComplete={handleComplete}
75
76
  onCancel={handleAltTextCancel}
76
77
  disabled={isReadonly}
77
78
  />
78
79
  {!isReadonly && (
79
- <TldrawUiToolbarButton
80
+ <TldrawUiButton
80
81
  title={msg('tool.media-alt-text-confirm')}
81
82
  data-testid="tool.media-alt-text-confirm"
82
83
  type="icon"
@@ -84,7 +85,7 @@ export function AltTextEditor({ shapeId, onClose, source }: AltTextEditorProps)
84
85
  onClick={handleConfirm}
85
86
  >
86
87
  <TldrawUiButtonIcon small icon="check" />
87
- </TldrawUiToolbarButton>
88
+ </TldrawUiButton>
88
89
  )}
89
90
  </>
90
91
  )
@@ -2,9 +2,9 @@ import { preventDefault, TiptapEditor, useEditor } from '@tldraw/editor'
2
2
  import { useEffect, useRef, useState } from 'react'
3
3
  import { useUiEvents } from '../../context/events'
4
4
  import { useTranslation } from '../../hooks/useTranslation/useTranslation'
5
+ import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
5
6
  import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
6
7
  import { TldrawUiInput } from '../primitives/TldrawUiInput'
7
- import { TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
8
8
 
9
9
  /** @public */
10
10
  export interface LinkEditorProps {
@@ -75,8 +75,9 @@ export function LinkEditor({ textEditor, value: initialValue, onClose }: LinkEdi
75
75
  onComplete={handleLinkComplete}
76
76
  onCancel={handleLinkCancel}
77
77
  placeholder="example.com"
78
+ aria-label="example.com"
78
79
  />
79
- <TldrawUiToolbarButton
80
+ <TldrawUiButton
80
81
  className="tlui-rich-text__toolbar-link-visit"
81
82
  title={msg('tool.rich-text-link-visit')}
82
83
  type="icon"
@@ -85,8 +86,8 @@ export function LinkEditor({ textEditor, value: initialValue, onClose }: LinkEdi
85
86
  disabled={!value}
86
87
  >
87
88
  <TldrawUiButtonIcon small icon="external-link" />
88
- </TldrawUiToolbarButton>
89
- <TldrawUiToolbarButton
89
+ </TldrawUiButton>
90
+ <TldrawUiButton
90
91
  className="tlui-rich-text__toolbar-link-remove"
91
92
  title={msg('tool.rich-text-link-remove')}
92
93
  data-testid="rich-text.link-remove"
@@ -95,7 +96,7 @@ export function LinkEditor({ textEditor, value: initialValue, onClose }: LinkEdi
95
96
  onClick={handleRemoveLink}
96
97
  >
97
98
  <TldrawUiButtonIcon small icon="trash" />
98
- </TldrawUiToolbarButton>
99
+ </TldrawUiButton>
99
100
  </>
100
101
  )
101
102
  }
@@ -101,7 +101,7 @@ export function OverflowingToolbar({
101
101
  items: collectItems(child.children),
102
102
  element: child as HTMLElement,
103
103
  })
104
- } else {
104
+ } else if (!child.hasAttribute('data-radix-popper-content-wrapper')) {
105
105
  items.push({ type: 'item', element: child as HTMLElement })
106
106
  }
107
107
  }
@@ -1,8 +1,10 @@
1
1
  import { useEditor, useValue } from '@tldraw/editor'
2
2
  import classNames from 'classnames'
3
3
  import { PORTRAIT_BREAKPOINT } from '../../constants'
4
+ import { useActions } from '../../context/actions'
4
5
  import { useBreakpoint } from '../../context/breakpoints'
5
6
  import { useTranslation } from '../../hooks/useTranslation/useTranslation'
7
+ import { kbdStr } from '../../kbd-utils'
6
8
  import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
7
9
  import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
8
10
  import { TldrawUiTooltip } from '../primitives/TldrawUiTooltip'
@@ -17,6 +19,7 @@ export function ToggleToolLockedButton({ activeToolId }: ToggleToolLockedButtonP
17
19
  const editor = useEditor()
18
20
  const breakpoint = useBreakpoint()
19
21
  const msg = useTranslation()
22
+ const actions = useActions()
20
23
 
21
24
  const isToolLocked = useValue('is tool locked', () => editor.getInstanceState().isToolLocked, [
22
25
  editor,
@@ -25,11 +28,15 @@ export function ToggleToolLockedButton({ activeToolId }: ToggleToolLockedButtonP
25
28
 
26
29
  if (!activeToolId || !tool.isLockable) return null
27
30
 
31
+ const toggleLockAction = actions['toggle-tool-lock']
32
+ const tooltipContent = toggleLockAction?.kbd
33
+ ? `${msg('action.toggle-tool-lock')} ${kbdStr(toggleLockAction.kbd)}`
34
+ : msg('action.toggle-tool-lock')
35
+
28
36
  return (
29
- <TldrawUiTooltip content={msg('action.toggle-tool-lock')}>
37
+ <TldrawUiTooltip content={tooltipContent}>
30
38
  <TldrawUiButton
31
39
  type="normal"
32
- title={msg('action.toggle-tool-lock')}
33
40
  data-testid="tool-lock"
34
41
  className={classNames('tlui-main-toolbar__lock-button', {
35
42
  'tlui-main-toolbar__lock-button__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,
@@ -652,11 +652,13 @@ export function ToggleKeyboardShortcutsItem() {
652
652
  }
653
653
 
654
654
  /** @public @react */
655
- export function ToggleUiLabelsItem() {
655
+ export function ToggleEnhancedA11yModeItem() {
656
656
  const editor = useEditor()
657
- const showUiLabels = useValue('showUiLabels', () => editor.user.getShowUiLabels(), [editor])
657
+ const enhancedA11yMode = useValue('enhancedA11yMode', () => editor.user.getEnhancedA11yMode(), [
658
+ editor,
659
+ ])
658
660
 
659
- return <TldrawUiMenuActionCheckboxItem actionId="toggle-ui-labels" checked={showUiLabels} />
661
+ return <TldrawUiMenuActionCheckboxItem actionId="enhanced-a11y-mode" checked={enhancedA11yMode} />
660
662
  }
661
663
 
662
664
  /** @public @react */
@@ -4,7 +4,6 @@ import {
4
4
  clamp,
5
5
  Editor,
6
6
  react,
7
- stopEventPropagation,
8
7
  useAtom,
9
8
  useEditor,
10
9
  usePassThroughMouseOverEvents,
@@ -170,7 +169,7 @@ export const TldrawUiContextualToolbar = ({
170
169
  data-visible={false}
171
170
  data-testid="contextual-toolbar"
172
171
  className={classNames('tlui-contextual-toolbar', className)}
173
- onPointerDown={stopEventPropagation}
172
+ onPointerDown={editor.markEventAsHandled}
174
173
  >
175
174
  <TldrawUiToolbar
176
175
  orientation="horizontal"
@@ -1,4 +1,4 @@
1
- import { stopEventPropagation, tlenv, tltime, useMaybeEditor } from '@tldraw/editor'
1
+ import { tlenv, tltime, useMaybeEditor } from '@tldraw/editor'
2
2
  import classNames from 'classnames'
3
3
  import * as React from 'react'
4
4
  import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
@@ -35,6 +35,7 @@ export interface TLUiInputProps {
35
35
  shouldManuallyMaintainScrollPositionWhenFocused?: boolean
36
36
  value?: string
37
37
  'data-testid'?: string
38
+ 'aria-label'?: string
38
39
  }
39
40
 
40
41
  /** @public @react */
@@ -60,6 +61,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
60
61
  value,
61
62
  'data-testid': dataTestId,
62
63
  disabled,
64
+ 'aria-label': ariaLabel,
63
65
  },
64
66
  ref
65
67
  ) {
@@ -118,7 +120,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
118
120
  // `onChange` with a duplicated text value.
119
121
  if (isComposing.current) return
120
122
  e.currentTarget.blur()
121
- stopEventPropagation(e)
123
+ e.stopPropagation()
122
124
  onComplete?.(e.currentTarget.value)
123
125
  break
124
126
  }
@@ -126,7 +128,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
126
128
  e.currentTarget.value = rInitialValue.current
127
129
  onCancel?.(e.currentTarget.value)
128
130
  e.currentTarget.blur()
129
- stopEventPropagation(e)
131
+ e.stopPropagation()
130
132
  break
131
133
  }
132
134
  }
@@ -198,6 +200,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
198
200
  onCompositionStart={handleCompositionStart}
199
201
  onCompositionEnd={handleCompositionEnd}
200
202
  autoFocus={autoFocus}
203
+ aria-label={ariaLabel}
201
204
  placeholder={placeholder}
202
205
  value={value}
203
206
  data-testid={dataTestId}
@@ -13,7 +13,7 @@ export interface TLUiSliderProps {
13
13
  label: string
14
14
  title: string
15
15
  onValueChange(value: number): void
16
- onHistoryMark(id: string): void
16
+ onHistoryMark?(id: string): void
17
17
  'data-testid'?: string
18
18
  ariaValueModifier?: number
19
19
  }
@@ -53,7 +53,7 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
53
53
 
54
54
  const handlePointerDown = useCallback(() => {
55
55
  tooltipManager.hideAllTooltips()
56
- onHistoryMark('click slider')
56
+ onHistoryMark?.('click slider')
57
57
  }, [onHistoryMark])
58
58
 
59
59
  // N.B. This is a bit silly. The Radix slider auto-focuses which
@@ -71,6 +71,7 @@ export const TldrawUiToolbarButton = React.forwardRef<HTMLButtonElement, TLUiToo
71
71
  draggable={false}
72
72
  data-isactive={isActive}
73
73
  {...props}
74
+ aria-label={props.title}
74
75
  // The tooltip takes care of this.
75
76
  title={undefined}
76
77
  className={classnames('tlui-button', `tlui-button__${type}`, props.className)}
@@ -127,7 +128,7 @@ export interface TLUiToolbarToggleItemProps extends React.HTMLAttributes<HTMLBut
127
128
  className?: string
128
129
  type: 'icon' | 'tool'
129
130
  value: string
130
- tooltip?: string
131
+ tooltip?: React.ReactNode
131
132
  }
132
133
 
133
134
  /** @public @react */