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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/shared/useEditablePlainText.ts"],
4
- "sourcesContent": ["import {\n\tEditor,\n\tTLShapeId,\n\tTLUnknownShape,\n\tgetPointerInfo,\n\tnoop,\n\tpreventDefault,\n\tstopEventPropagation,\n\ttlenv,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\nimport React, { useCallback, useEffect, useRef } from 'react'\nimport { TextHelpers } from './TextHelpers'\n\n/** @public */\nexport function useEditablePlainText(shapeId: TLShapeId, type: string, text?: string) {\n\tconst commonUseEditableTextHandlers = useEditableTextCommon(shapeId)\n\tconst isEditing = commonUseEditableTextHandlers.isEditing\n\tconst editor = useEditor()\n\tconst rInput = useRef<HTMLTextAreaElement>(null)\n\tconst isEmpty = (text || '').trim().length === 0\n\n\tuseEffect(() => {\n\t\tfunction selectAllIfEditing(event: { shapeId: TLShapeId }) {\n\t\t\tif (event.shapeId === shapeId) {\n\t\t\t\trInput.current?.select?.()\n\t\t\t}\n\t\t}\n\n\t\teditor.on('select-all-text', selectAllIfEditing)\n\t\treturn () => {\n\t\t\teditor.off('select-all-text', selectAllIfEditing)\n\t\t}\n\t}, [editor, shapeId, isEditing])\n\n\tuseEffect(() => {\n\t\tif (!isEditing) return\n\n\t\tif (document.activeElement !== rInput.current) {\n\t\t\trInput.current?.focus()\n\t\t}\n\n\t\tif (editor.getInstanceState().isCoarsePointer) {\n\t\t\trInput.current?.select()\n\t\t}\n\n\t\t// XXX(mime): This fixes iOS not showing the caret sometimes.\n\t\t// This \"shakes\" the caret awake.\n\t\tif (tlenv.isSafari) {\n\t\t\trInput.current?.blur()\n\t\t\trInput.current?.focus()\n\t\t}\n\t}, [editor, isEditing])\n\n\t// When the user presses ctrl / meta enter, complete the editing state.\n\tconst handleKeyDown = useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\n\t\t\tswitch (e.key) {\n\t\t\t\tcase 'Enter': {\n\t\t\t\t\tif (e.ctrlKey || e.metaKey) {\n\t\t\t\t\t\teditor.complete()\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\t// When the text changes, update the text value.\n\tconst handleChange = useCallback(\n\t\t({ plaintext }: { plaintext: string }) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\n\t\t\tconst normalizedPlaintext = TextHelpers.normalizeText(plaintext || '')\n\t\t\teditor.updateShape<TLUnknownShape & { props: { text: string } }>({\n\t\t\t\tid: shapeId,\n\t\t\t\ttype,\n\t\t\t\tprops: { text: normalizedPlaintext },\n\t\t\t})\n\t\t},\n\t\t[editor, shapeId, type]\n\t)\n\n\treturn {\n\t\trInput,\n\t\thandleKeyDown,\n\t\thandleChange,\n\t\tisEmpty,\n\t\t...commonUseEditableTextHandlers,\n\t}\n}\n\n/** @internal */\nexport function useIsReadyForEditing(editor: Editor, shapeId: TLShapeId) {\n\treturn useValue(\n\t\t'isReadyForEditing',\n\t\t() => {\n\t\t\tconst editingShapeId = editor.getEditingShapeId()\n\t\t\treturn (\n\t\t\t\t// something's being editing... and either it's this shape OR this shape is hovered\n\t\t\t\teditingShapeId !== null &&\n\t\t\t\t(editingShapeId === shapeId || editor.getHoveredShapeId() === shapeId)\n\t\t\t)\n\t\t},\n\t\t[editor, shapeId]\n\t)\n}\n\n/** @internal */\nexport function useEditableTextCommon(shapeId: TLShapeId) {\n\tconst editor = useEditor()\n\tconst isEditing = useValue('isEditing', () => editor.getEditingShapeId() === shapeId, [editor])\n\tconst isReadyForEditing = useIsReadyForEditing(editor, shapeId)\n\n\tconst handleInputPointerDown = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\t// N.B. We used to only do this only when isEditing to help\n\t\t\t// prevent an issue where you could drag a selected shape\n\t\t\t// behind another shape. That is addressed now by the CSS logic\n\t\t\t// looking at data-isselectinganything.\n\t\t\t//\n\t\t\t// We still need to follow this logic even if not isEditing\n\t\t\t// because otherwise there is some flakiness in selection.\n\t\t\t// When selecting text, it would sometimes select some text\n\t\t\t// partially if we didn't dispatch/stop below.\n\n\t\t\teditor.dispatch({\n\t\t\t\t...getPointerInfo(e),\n\t\t\t\ttype: 'pointer',\n\t\t\t\tname: 'pointer_down',\n\t\t\t\ttarget: 'shape',\n\t\t\t\tshape: editor.getShape(shapeId)!,\n\t\t\t})\n\n\t\t\tstopEventPropagation(e) // we need to prevent blurring the input\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\tconst handlePaste = useCallback(\n\t\t(e: ClipboardEvent | React.ClipboardEvent<HTMLTextAreaElement>) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\t\t\tif (e.clipboardData) {\n\t\t\t\t// find html in the clipboard and look for the tldraw data\n\t\t\t\tconst html = e.clipboardData.getData('text/html')\n\t\t\t\tif (html) {\n\t\t\t\t\tif (html.includes('<div data-tldraw')) {\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\treturn {\n\t\thandleFocus: noop,\n\t\thandleBlur: noop,\n\t\thandleInputPointerDown,\n\t\thandleDoubleClick: stopEventPropagation,\n\t\thandlePaste,\n\t\tisEditing,\n\t\tisReadyForEditing,\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tEditor,\n\tTLShapeId,\n\tTLUnknownShape,\n\tgetPointerInfo,\n\tnoop,\n\tpreventDefault,\n\ttlenv,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\nimport React, { useCallback, useEffect, useRef } from 'react'\nimport { TextHelpers } from './TextHelpers'\n\n/** @public */\nexport function useEditablePlainText(shapeId: TLShapeId, type: string, text?: string) {\n\tconst commonUseEditableTextHandlers = useEditableTextCommon(shapeId)\n\tconst isEditing = commonUseEditableTextHandlers.isEditing\n\tconst editor = useEditor()\n\tconst rInput = useRef<HTMLTextAreaElement>(null)\n\tconst isEmpty = (text || '').trim().length === 0\n\n\tuseEffect(() => {\n\t\tfunction selectAllIfEditing(event: { shapeId: TLShapeId }) {\n\t\t\tif (event.shapeId === shapeId) {\n\t\t\t\trInput.current?.select?.()\n\t\t\t}\n\t\t}\n\n\t\teditor.on('select-all-text', selectAllIfEditing)\n\t\treturn () => {\n\t\t\teditor.off('select-all-text', selectAllIfEditing)\n\t\t}\n\t}, [editor, shapeId, isEditing])\n\n\tuseEffect(() => {\n\t\tif (!isEditing) return\n\n\t\tif (document.activeElement !== rInput.current) {\n\t\t\trInput.current?.focus()\n\t\t}\n\n\t\tif (editor.getInstanceState().isCoarsePointer) {\n\t\t\trInput.current?.select()\n\t\t}\n\n\t\t// XXX(mime): This fixes iOS not showing the caret sometimes.\n\t\t// This \"shakes\" the caret awake.\n\t\tif (tlenv.isSafari) {\n\t\t\trInput.current?.blur()\n\t\t\trInput.current?.focus()\n\t\t}\n\t}, [editor, isEditing])\n\n\t// When the user presses ctrl / meta enter, complete the editing state.\n\tconst handleKeyDown = useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\n\t\t\tswitch (e.key) {\n\t\t\t\tcase 'Enter': {\n\t\t\t\t\tif (e.ctrlKey || e.metaKey) {\n\t\t\t\t\t\teditor.complete()\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\t// When the text changes, update the text value.\n\tconst handleChange = useCallback(\n\t\t({ plaintext }: { plaintext: string }) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\n\t\t\tconst normalizedPlaintext = TextHelpers.normalizeText(plaintext || '')\n\t\t\teditor.updateShape<TLUnknownShape & { props: { text: string } }>({\n\t\t\t\tid: shapeId,\n\t\t\t\ttype,\n\t\t\t\tprops: { text: normalizedPlaintext },\n\t\t\t})\n\t\t},\n\t\t[editor, shapeId, type]\n\t)\n\n\treturn {\n\t\trInput,\n\t\thandleKeyDown,\n\t\thandleChange,\n\t\tisEmpty,\n\t\t...commonUseEditableTextHandlers,\n\t}\n}\n\n/** @internal */\nexport function useIsReadyForEditing(editor: Editor, shapeId: TLShapeId) {\n\treturn useValue(\n\t\t'isReadyForEditing',\n\t\t() => {\n\t\t\tconst editingShapeId = editor.getEditingShapeId()\n\t\t\treturn (\n\t\t\t\t// something's being editing... and either it's this shape OR this shape is hovered\n\t\t\t\teditingShapeId !== null &&\n\t\t\t\t(editingShapeId === shapeId || editor.getHoveredShapeId() === shapeId)\n\t\t\t)\n\t\t},\n\t\t[editor, shapeId]\n\t)\n}\n\n/** @internal */\nexport function useEditableTextCommon(shapeId: TLShapeId) {\n\tconst editor = useEditor()\n\tconst isEditing = useValue('isEditing', () => editor.getEditingShapeId() === shapeId, [editor])\n\tconst isReadyForEditing = useIsReadyForEditing(editor, shapeId)\n\n\tconst handleInputPointerDown = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\t// N.B. We used to only do this only when isEditing to help\n\t\t\t// prevent an issue where you could drag a selected shape\n\t\t\t// behind another shape. That is addressed now by the CSS logic\n\t\t\t// looking at data-isselectinganything.\n\t\t\t//\n\t\t\t// We still need to follow this logic even if not isEditing\n\t\t\t// because otherwise there is some flakiness in selection.\n\t\t\t// When selecting text, it would sometimes select some text\n\t\t\t// partially if we didn't dispatch/stop below.\n\n\t\t\teditor.dispatch({\n\t\t\t\t...getPointerInfo(editor, e),\n\t\t\t\ttype: 'pointer',\n\t\t\t\tname: 'pointer_down',\n\t\t\t\ttarget: 'shape',\n\t\t\t\tshape: editor.getShape(shapeId)!,\n\t\t\t})\n\n\t\t\te.stopPropagation() // we need to prevent blurring the input\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\tconst handlePaste = useCallback(\n\t\t(e: ClipboardEvent | React.ClipboardEvent<HTMLTextAreaElement>) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\t\t\tif (e.clipboardData) {\n\t\t\t\t// find html in the clipboard and look for the tldraw data\n\t\t\t\tconst html = e.clipboardData.getData('text/html')\n\t\t\t\tif (html) {\n\t\t\t\t\tif (html.includes('<div data-tldraw')) {\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\treturn {\n\t\thandleFocus: noop,\n\t\thandleBlur: noop,\n\t\thandleInputPointerDown,\n\t\thandleDoubleClick: editor.markEventAsHandled,\n\t\thandlePaste,\n\t\tisEditing,\n\t\tisReadyForEditing,\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,5 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { preventDefault, stopEventPropagation } from "@tldraw/editor";
2
+ import { preventDefault, useEditor } from "@tldraw/editor";
3
3
  import React from "react";
4
4
  const PlainTextArea = React.forwardRef(function TextArea({
5
5
  isEditing,
@@ -12,6 +12,7 @@ const PlainTextArea = React.forwardRef(function TextArea({
12
12
  handleInputPointerDown,
13
13
  handleDoubleClick
14
14
  }, ref) {
15
+ const editor = useEditor();
15
16
  const onChange = (e) => {
16
17
  handleChange({ plaintext: e.target.value });
17
18
  };
@@ -37,8 +38,8 @@ const PlainTextArea = React.forwardRef(function TextArea({
37
38
  onChange,
38
39
  onKeyDown: (e) => handleKeyDown(e.nativeEvent),
39
40
  onBlur: handleBlur,
40
- onTouchEnd: stopEventPropagation,
41
- onContextMenu: isEditing ? stopEventPropagation : void 0,
41
+ onTouchEnd: editor.markEventAsHandled,
42
+ onContextMenu: isEditing ? (e) => e.stopPropagation() : void 0,
42
43
  onPointerDown: handleInputPointerDown,
43
44
  onPaste: handlePaste,
44
45
  onDoubleClick: handleDoubleClick,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/text/PlainTextArea.tsx"],
4
- "sourcesContent": ["import { preventDefault, stopEventPropagation } from '@tldraw/editor'\nimport React from 'react'\nimport { TextAreaProps } from './RichTextArea'\n\n/**\n * A plain text area that can be used for basic editing text.\n *\n * @public @react\n */\nexport const PlainTextArea = React.forwardRef<HTMLTextAreaElement, TextAreaProps>(function TextArea(\n\t{\n\t\tisEditing,\n\t\ttext,\n\t\thandleFocus,\n\t\thandleChange,\n\t\thandleKeyDown,\n\t\thandlePaste,\n\t\thandleBlur,\n\t\thandleInputPointerDown,\n\t\thandleDoubleClick,\n\t},\n\tref\n) {\n\tconst onChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n\t\thandleChange({ plaintext: e.target.value })\n\t}\n\n\treturn (\n\t\t<textarea\n\t\t\tref={ref}\n\t\t\tclassName=\"tl-text tl-text-input\"\n\t\t\tname=\"text\"\n\t\t\ttabIndex={-1}\n\t\t\tdisabled={!isEditing}\n\t\t\treadOnly={!isEditing}\n\t\t\tautoComplete=\"off\"\n\t\t\tautoCapitalize=\"off\"\n\t\t\tautoCorrect=\"off\"\n\t\t\tautoSave=\"off\"\n\t\t\tplaceholder=\"\"\n\t\t\tspellCheck=\"true\"\n\t\t\twrap=\"off\"\n\t\t\tdir=\"auto\"\n\t\t\tdefaultValue={text}\n\t\t\tonFocus={handleFocus}\n\t\t\tonChange={onChange}\n\t\t\tonKeyDown={(e) => handleKeyDown(e.nativeEvent)}\n\t\t\tonBlur={handleBlur}\n\t\t\tonTouchEnd={stopEventPropagation}\n\t\t\tonContextMenu={isEditing ? stopEventPropagation : undefined}\n\t\t\tonPointerDown={handleInputPointerDown}\n\t\t\tonPaste={handlePaste}\n\t\t\tonDoubleClick={handleDoubleClick}\n\t\t\t// On FF, there's a behavior where dragging a selection will grab that selection into\n\t\t\t// the drag event. However, once the drag is over, and you select away from the textarea,\n\t\t\t// starting a drag over the textarea will restart a selection drag instead of a shape drag.\n\t\t\t// This prevents that default behavior in FF.\n\t\t\tonDragStart={preventDefault}\n\t\t/>\n\t)\n})\n"],
5
- "mappings": "AA4BE;AA5BF,SAAS,gBAAgB,4BAA4B;AACrD,OAAO,WAAW;AAQX,MAAM,gBAAgB,MAAM,WAA+C,SAAS,SAC1F;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GACA,KACC;AACD,QAAM,WAAW,CAAC,MAA8C;AAC/D,iBAAa,EAAE,WAAW,EAAE,OAAO,MAAM,CAAC;AAAA,EAC3C;AAEA,SACC;AAAA,IAAC;AAAA;AAAA,MACA;AAAA,MACA,WAAU;AAAA,MACV,MAAK;AAAA,MACL,UAAU;AAAA,MACV,UAAU,CAAC;AAAA,MACX,UAAU,CAAC;AAAA,MACX,cAAa;AAAA,MACb,gBAAe;AAAA,MACf,aAAY;AAAA,MACZ,UAAS;AAAA,MACT,aAAY;AAAA,MACZ,YAAW;AAAA,MACX,MAAK;AAAA,MACL,KAAI;AAAA,MACJ,cAAc;AAAA,MACd,SAAS;AAAA,MACT;AAAA,MACA,WAAW,CAAC,MAAM,cAAc,EAAE,WAAW;AAAA,MAC7C,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,eAAe,YAAY,uBAAuB;AAAA,MAClD,eAAe;AAAA,MACf,SAAS;AAAA,MACT,eAAe;AAAA,MAKf,aAAa;AAAA;AAAA,EACd;AAEF,CAAC;",
4
+ "sourcesContent": ["import { preventDefault, useEditor } from '@tldraw/editor'\nimport React from 'react'\nimport { TextAreaProps } from './RichTextArea'\n\n/**\n * A plain text area that can be used for basic editing text.\n *\n * @public @react\n */\nexport const PlainTextArea = React.forwardRef<HTMLTextAreaElement, TextAreaProps>(function TextArea(\n\t{\n\t\tisEditing,\n\t\ttext,\n\t\thandleFocus,\n\t\thandleChange,\n\t\thandleKeyDown,\n\t\thandlePaste,\n\t\thandleBlur,\n\t\thandleInputPointerDown,\n\t\thandleDoubleClick,\n\t},\n\tref\n) {\n\tconst editor = useEditor()\n\tconst onChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n\t\thandleChange({ plaintext: e.target.value })\n\t}\n\n\treturn (\n\t\t<textarea\n\t\t\tref={ref}\n\t\t\tclassName=\"tl-text tl-text-input\"\n\t\t\tname=\"text\"\n\t\t\ttabIndex={-1}\n\t\t\tdisabled={!isEditing}\n\t\t\treadOnly={!isEditing}\n\t\t\tautoComplete=\"off\"\n\t\t\tautoCapitalize=\"off\"\n\t\t\tautoCorrect=\"off\"\n\t\t\tautoSave=\"off\"\n\t\t\tplaceholder=\"\"\n\t\t\tspellCheck=\"true\"\n\t\t\twrap=\"off\"\n\t\t\tdir=\"auto\"\n\t\t\tdefaultValue={text}\n\t\t\tonFocus={handleFocus}\n\t\t\tonChange={onChange}\n\t\t\tonKeyDown={(e) => handleKeyDown(e.nativeEvent)}\n\t\t\tonBlur={handleBlur}\n\t\t\tonTouchEnd={editor.markEventAsHandled}\n\t\t\tonContextMenu={isEditing ? (e) => e.stopPropagation() : undefined}\n\t\t\tonPointerDown={handleInputPointerDown}\n\t\t\tonPaste={handlePaste}\n\t\t\tonDoubleClick={handleDoubleClick}\n\t\t\t// On FF, there's a behavior where dragging a selection will grab that selection into\n\t\t\t// the drag event. However, once the drag is over, and you select away from the textarea,\n\t\t\t// starting a drag over the textarea will restart a selection drag instead of a shape drag.\n\t\t\t// This prevents that default behavior in FF.\n\t\t\tonDragStart={preventDefault}\n\t\t/>\n\t)\n})\n"],
5
+ "mappings": "AA6BE;AA7BF,SAAS,gBAAgB,iBAAiB;AAC1C,OAAO,WAAW;AAQX,MAAM,gBAAgB,MAAM,WAA+C,SAAS,SAC1F;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GACA,KACC;AACD,QAAM,SAAS,UAAU;AACzB,QAAM,WAAW,CAAC,MAA8C;AAC/D,iBAAa,EAAE,WAAW,EAAE,OAAO,MAAM,CAAC;AAAA,EAC3C;AAEA,SACC;AAAA,IAAC;AAAA;AAAA,MACA;AAAA,MACA,WAAU;AAAA,MACV,MAAK;AAAA,MACL,UAAU;AAAA,MACV,UAAU,CAAC;AAAA,MACX,UAAU,CAAC;AAAA,MACX,cAAa;AAAA,MACb,gBAAe;AAAA,MACf,aAAY;AAAA,MACZ,UAAS;AAAA,MACT,aAAY;AAAA,MACZ,YAAW;AAAA,MACX,MAAK;AAAA,MACL,KAAI;AAAA,MACJ,cAAc;AAAA,MACd,SAAS;AAAA,MACT;AAAA,MACA,WAAW,CAAC,MAAM,cAAc,EAAE,WAAW;AAAA,MAC7C,QAAQ;AAAA,MACR,YAAY,OAAO;AAAA,MACnB,eAAe,YAAY,CAAC,MAAM,EAAE,gBAAgB,IAAI;AAAA,MACxD,eAAe;AAAA,MACf,SAAS;AAAA,MACT,eAAe;AAAA,MAKf,aAAa;AAAA;AAAA,EACd;AAEF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -4,7 +4,6 @@ import {
4
4
  } from "@tiptap/react";
5
5
  import {
6
6
  preventDefault,
7
- stopEventPropagation,
8
7
  useEditor,
9
8
  useEvent,
10
9
  useUniqueSafeId
@@ -158,9 +157,9 @@ const RichTextArea = React.forwardRef(function RichTextArea2({
158
157
  tabIndex: -1,
159
158
  "data-testid": "rich-text-area",
160
159
  className: "tl-rich-text tl-text tl-text-input",
161
- onContextMenu: isEditing ? stopEventPropagation : void 0,
162
- onPointerDownCapture: stopEventPropagation,
163
- onTouchEnd: stopEventPropagation,
160
+ onContextMenu: isEditing ? (e) => e.stopPropagation() : void 0,
161
+ onPointerDownCapture: (e) => e.stopPropagation(),
162
+ onTouchEnd: (e) => e.stopPropagation(),
164
163
  onDragStart: preventDefault,
165
164
  children: /* @__PURE__ */ jsx("div", { className: "tl-rich-text", ref: rTextEditorEl })
166
165
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/text/RichTextArea.tsx"],
4
- "sourcesContent": ["import { EditorView } from '@tiptap/pm/view'\nimport {\n\tEditorEvents,\n\tJSONContent,\n\tEditor as TextEditor,\n\ttype Editor as TTEditor,\n} from '@tiptap/react'\nimport {\n\tEditor,\n\tTLRichText,\n\tTLShapeId,\n\tpreventDefault,\n\tstopEventPropagation,\n\tuseEditor,\n\tuseEvent,\n\tuseUniqueSafeId,\n} from '@tldraw/editor'\nimport React, { useLayoutEffect, useRef } from 'react'\n\n/** @public */\nexport interface TextAreaProps {\n\tisEditing: boolean\n\ttext?: string\n\tshapeId: TLShapeId\n\trichText?: TLRichText\n\thandleFocus(): void\n\thandleBlur(): void\n\thandleKeyDown(e: KeyboardEvent): void\n\thandleChange(changeInfo: { plaintext?: string; richText?: TLRichText }): void\n\thandleInputPointerDown(e: React.PointerEvent<HTMLElement>): void\n\thandleDoubleClick(e: any): any\n\thandlePaste(e: ClipboardEvent | React.ClipboardEvent<HTMLTextAreaElement>): void\n\thasCustomTabBehavior?: boolean\n}\n\n/**\n * N.B. In Development mode you need to ensure you're testing this without StrictMode on.\n * Otherwise it's not gonna work as expected on iOS.\n * Specifically, it means that the virtual keyboard won't pop open sometimes\n * (iOS starts flipping out when you render multiple times when trying to focus something) .\n */\n\n/**\n * A rich text area that can be used for editing text with rich text formatting.\n * This component uses the TipTap editor under the hood.\n *\n * @public @react\n */\nexport const RichTextArea = React.forwardRef<HTMLDivElement, TextAreaProps>(function RichTextArea(\n\t{\n\t\tshapeId,\n\t\tisEditing,\n\t\trichText,\n\t\thandleFocus,\n\t\thandleChange,\n\t\thandleBlur,\n\t\thandleKeyDown,\n\t\thandleDoubleClick,\n\t\thasCustomTabBehavior,\n\t\thandlePaste,\n\t},\n\tref\n) {\n\tconst editor = useEditor()\n\tconst tipTapId = useUniqueSafeId('tip-tap-editor')\n\tconst tipTapConfig = editor.getTextOptions().tipTapConfig\n\n\tconst rInitialRichText = useRef(richText)\n\tconst rTextEditor = useRef<TTEditor | null>(null)\n\tconst rTextEditorEl = useRef<HTMLDivElement>(null)\n\n\tuseLayoutEffect(() => {\n\t\tif (!rTextEditor.current) {\n\t\t\trInitialRichText.current = richText\n\t\t} else if (rInitialRichText.current !== richText) {\n\t\t\trTextEditor.current.commands.setContent(richText as JSONContent)\n\t\t}\n\t}, [richText])\n\n\t// The order of events is:\n\t// - editor begins editing any shape\n\t// - we set listeners for select all / place caret events\n\t// - if the user is editing this shape, this component is rendered\n\t// - editor emits the select all event / place caret event\n\t// - the text editor is onCreate callback is called\n\tconst rCreateInfo = useRef({\n\t\tselectAll: false,\n\t\tcaretPosition: null as { x: number; y: number } | null,\n\t})\n\n\tuseLayoutEffect(() => {\n\t\tfunction selectAllIfEditing(event: { shapeId: TLShapeId }) {\n\t\t\tif (event.shapeId === editor.getEditingShapeId()) {\n\t\t\t\trCreateInfo.current.selectAll = true\n\t\t\t}\n\t\t}\n\n\t\tfunction placeCaret(event: { shapeId: TLShapeId; point: { x: number; y: number } }) {\n\t\t\tif (event.shapeId === editor.getEditingShapeId()) {\n\t\t\t\trCreateInfo.current.caretPosition = event.point\n\t\t\t}\n\t\t}\n\n\t\teditor.on('select-all-text', selectAllIfEditing)\n\t\teditor.on('place-caret', placeCaret)\n\t\treturn () => {\n\t\t\teditor.off('select-all-text', selectAllIfEditing)\n\t\t\teditor.off('place-caret', placeCaret)\n\t\t}\n\t}, [editor, isEditing])\n\n\tconst onChange = useEvent(handleChange)\n\tconst onKeyDown = useEvent(handleKeyDown)\n\tconst onFocus = useEvent(handleFocus)\n\tconst onBlur = useEvent(handleBlur)\n\tconst onDoubleClick = useEvent(handleDoubleClick)\n\tconst onPaste = useEvent(handlePaste)\n\tuseLayoutEffect(() => {\n\t\tif (!isEditing || !tipTapConfig || !rTextEditorEl.current) return\n\n\t\tconst { editorProps, ...restOfTipTapConfig } = tipTapConfig\n\n\t\t// Because React can double-render in Strict Mode, we need to make sure we're not setting\n\t\t// the text editor twice. This became more much more prevalent in React 19, but also it\n\t\t// started manifesting in some cases in Next 14.2 (which maybe patches React 18.3 in weird\n\t\t// ways). So we used to use EditorProvider but we into weird rendering issues.\n\t\tconst textEditorInstance = new TextEditor({\n\t\t\telement: rTextEditorEl.current,\n\t\t\tautofocus: true,\n\t\t\teditable: isEditing,\n\t\t\tonUpdate: (props: EditorEvents['update']) => {\n\t\t\t\tconst content: TLRichText = props.editor.state.doc.toJSON()\n\t\t\t\trInitialRichText.current = content\n\t\t\t\tonChange({ richText: content })\n\t\t\t},\n\t\t\tonFocus,\n\t\t\tonBlur,\n\t\t\t// onCreate is called after a `setTimeout(0)`\n\t\t\tonCreate: (props) => {\n\t\t\t\t// If we're not still editing the original shape, then don't do anything.\n\t\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\n\t\t\t\tconst textEditor = props.editor\n\t\t\t\teditor.setRichTextEditor(textEditor)\n\n\t\t\t\tconst { selectAll, caretPosition } = rCreateInfo.current\n\n\t\t\t\tif (selectAll) {\n\t\t\t\t\t// Select all of the text\n\t\t\t\t\ttextEditor.chain().focus().selectAll().run()\n\t\t\t\t} else if (caretPosition) {\n\t\t\t\t\t// Set the initial caret screen position\n\t\t\t\t\tconst pos = textEditor.view.posAtCoords({\n\t\t\t\t\t\tleft: caretPosition.x,\n\t\t\t\t\t\ttop: caretPosition.y,\n\t\t\t\t\t})?.pos\n\n\t\t\t\t\tif (pos) {\n\t\t\t\t\t\t// Focus to that position.\n\t\t\t\t\t\ttextEditor.chain().focus().setTextSelection(pos).run()\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If no position, default to select all.\n\t\t\t\t\t\ttextEditor.chain().focus().selectAll().run()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\teditorProps: {\n\t\t\t\thandleKeyDown: (view: EditorView, event: KeyboardEvent) => {\n\t\t\t\t\tif (!hasCustomTabBehavior && event.key === 'Tab') {\n\t\t\t\t\t\thandleTab(editor, view, event)\n\t\t\t\t\t}\n\n\t\t\t\t\tonKeyDown(event)\n\t\t\t\t},\n\t\t\t\thandlePaste: (view: EditorView, event: ClipboardEvent) => {\n\t\t\t\t\tonPaste(event)\n\t\t\t\t\tif (event.defaultPrevented) return true\n\t\t\t\t},\n\t\t\t\thandleDoubleClick: (_view, _pos, event) => onDoubleClick(event),\n\t\t\t\t...editorProps,\n\t\t\t},\n\t\t\tcoreExtensionOptions: {\n\t\t\t\tclipboardTextSerializer: {\n\t\t\t\t\tblockSeparator: '\\n',\n\t\t\t\t},\n\t\t\t},\n\t\t\t...restOfTipTapConfig,\n\t\t\tcontent: rInitialRichText.current as JSONContent,\n\t\t})\n\n\t\t// XXX: When creating a brand new shape and double-clicking into it quickly to edit it,\n\t\t// there's some kind of race condition happening where the editor doesn't focus properly.\n\t\tconst timeout = editor.timers.setTimeout(() => {\n\t\t\tif (rCreateInfo.current.caretPosition || rCreateInfo.current.selectAll) {\n\t\t\t\ttextEditorInstance.commands.focus()\n\t\t\t} else {\n\t\t\t\ttextEditorInstance.commands.focus('end')\n\t\t\t}\n\n\t\t\trCreateInfo.current.selectAll = false\n\t\t\trCreateInfo.current.caretPosition = null\n\t\t}, 100)\n\n\t\trTextEditor.current = textEditorInstance\n\n\t\treturn () => {\n\t\t\trTextEditor.current = null\n\t\t\tclearTimeout(timeout)\n\t\t\ttextEditorInstance.destroy()\n\t\t}\n\t}, [\n\t\tisEditing,\n\t\ttipTapConfig,\n\t\tonFocus,\n\t\tonBlur,\n\t\tonDoubleClick,\n\t\tonChange,\n\t\tonPaste,\n\t\tonKeyDown,\n\t\teditor,\n\t\tshapeId,\n\t\thasCustomTabBehavior,\n\t])\n\n\tif (!isEditing || !tipTapConfig) {\n\t\treturn null\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tid={tipTapId}\n\t\t\tref={ref}\n\t\t\ttabIndex={-1}\n\t\t\tdata-testid=\"rich-text-area\"\n\t\t\tclassName=\"tl-rich-text tl-text tl-text-input\"\n\t\t\tonContextMenu={isEditing ? stopEventPropagation : undefined}\n\t\t\t// N.B. When PointerStateExtension was introduced, this was moved there.\n\t\t\t// However, that caused selecting over list items to break.\n\t\t\t// The handleDOMEvents in TipTap don't seem to support the pointerDownCapture event.\n\t\t\tonPointerDownCapture={stopEventPropagation}\n\t\t\t// This onTouchEnd is important for Android to be able to change selection on text.\n\t\t\tonTouchEnd={stopEventPropagation}\n\t\t\t// On FF, there's a behavior where dragging a selection will grab that selection into\n\t\t\t// the drag event. However, once the drag is over, and you select away from the textarea,\n\t\t\t// starting a drag over the textarea will restart a selection drag instead of a shape drag.\n\t\t\t// This prevents that default behavior in FF.\n\t\t\tonDragStart={preventDefault}\n\t\t>\n\t\t\t<div className=\"tl-rich-text\" ref={rTextEditorEl} />\n\t\t</div>\n\t)\n})\n\n// Prevent exiting the editor when hitting Tab.\n// Also, insert a tab character at the front of the line if the shift key isn't pressed,\n// otherwise if shift is pressed, remove a tab character from the front of the line.\nfunction handleTab(editor: Editor, view: EditorView, event: KeyboardEvent) {\n\t// Don't exit the editor.\n\tevent.preventDefault()\n\n\tconst textEditor = editor.getRichTextEditor()\n\tif (textEditor?.isActive('bulletList') || textEditor?.isActive('orderedList')) return\n\n\tconst { state, dispatch } = view\n\tconst { $from, $to } = state.selection\n\tconst isShift = event.shiftKey\n\n\t// Create a new transaction\n\tlet tr = state.tr\n\n\t// Iterate over each line in the selection in reverse so that the positions\n\t// are stable as we modify the document.\n\tlet pos = $to.end()\n\twhile (pos >= $from.start()) {\n\t\tconst line = state.doc.resolve(pos).blockRange()\n\t\tif (!line) break\n\n\t\tconst lineStart = line.start\n\t\tconst lineEnd = line.end\n\t\tconst lineText = state.doc.textBetween(lineStart, lineEnd, '\\n')\n\n\t\t// Check if the current line or any of its parent nodes are part of a list\n\t\tlet isInList = false\n\t\tstate.doc.nodesBetween(lineStart, lineEnd, (node) => {\n\t\t\tif (node.type.name === 'bulletList' || node.type.name === 'orderedList') {\n\t\t\t\tisInList = true\n\t\t\t\treturn false // Stop iteration\n\t\t\t}\n\t\t})\n\n\t\t// TODO: for now skip over lists. Later, we might consider handling them using\n\t\t// sinkListItem and liftListItem from @tiptap/pm/schema-list\n\t\tif (!isInList) {\n\t\t\tif (!isShift) {\n\t\t\t\t// Insert a tab character at the start of the line\n\t\t\t\ttr = tr.insertText('\\t', lineStart + 1)\n\t\t\t} else {\n\t\t\t\t// Remove a tab character from the start of the line\n\t\t\t\tif (lineText.startsWith('\\t')) {\n\t\t\t\t\ttr = tr.delete(lineStart + 1, lineStart + 2)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpos = lineStart - 1\n\t}\n\n\tconst mappedSelection = state.selection.map(tr.doc, tr.mapping)\n\ttr.setSelection(mappedSelection)\n\n\tif (tr.docChanged) {\n\t\tdispatch(tr)\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { EditorView } from '@tiptap/pm/view'\nimport {\n\tEditorEvents,\n\tJSONContent,\n\tEditor as TextEditor,\n\ttype Editor as TTEditor,\n} from '@tiptap/react'\nimport {\n\tEditor,\n\tTLRichText,\n\tTLShapeId,\n\tpreventDefault,\n\tuseEditor,\n\tuseEvent,\n\tuseUniqueSafeId,\n} from '@tldraw/editor'\nimport React, { useLayoutEffect, useRef } from 'react'\n\n/** @public */\nexport interface TextAreaProps {\n\tisEditing: boolean\n\ttext?: string\n\tshapeId: TLShapeId\n\trichText?: TLRichText\n\thandleFocus(): void\n\thandleBlur(): void\n\thandleKeyDown(e: KeyboardEvent): void\n\thandleChange(changeInfo: { plaintext?: string; richText?: TLRichText }): void\n\thandleInputPointerDown(e: React.PointerEvent<HTMLElement>): void\n\thandleDoubleClick(e: any): any\n\thandlePaste(e: ClipboardEvent | React.ClipboardEvent<HTMLTextAreaElement>): void\n\thasCustomTabBehavior?: boolean\n}\n\n/**\n * N.B. In Development mode you need to ensure you're testing this without StrictMode on.\n * Otherwise it's not gonna work as expected on iOS.\n * Specifically, it means that the virtual keyboard won't pop open sometimes\n * (iOS starts flipping out when you render multiple times when trying to focus something) .\n */\n\n/**\n * A rich text area that can be used for editing text with rich text formatting.\n * This component uses the TipTap editor under the hood.\n *\n * @public @react\n */\nexport const RichTextArea = React.forwardRef<HTMLDivElement, TextAreaProps>(function RichTextArea(\n\t{\n\t\tshapeId,\n\t\tisEditing,\n\t\trichText,\n\t\thandleFocus,\n\t\thandleChange,\n\t\thandleBlur,\n\t\thandleKeyDown,\n\t\thandleDoubleClick,\n\t\thasCustomTabBehavior,\n\t\thandlePaste,\n\t},\n\tref\n) {\n\tconst editor = useEditor()\n\tconst tipTapId = useUniqueSafeId('tip-tap-editor')\n\tconst tipTapConfig = editor.getTextOptions().tipTapConfig\n\n\tconst rInitialRichText = useRef(richText)\n\tconst rTextEditor = useRef<TTEditor | null>(null)\n\tconst rTextEditorEl = useRef<HTMLDivElement>(null)\n\n\tuseLayoutEffect(() => {\n\t\tif (!rTextEditor.current) {\n\t\t\trInitialRichText.current = richText\n\t\t} else if (rInitialRichText.current !== richText) {\n\t\t\trTextEditor.current.commands.setContent(richText as JSONContent)\n\t\t}\n\t}, [richText])\n\n\t// The order of events is:\n\t// - editor begins editing any shape\n\t// - we set listeners for select all / place caret events\n\t// - if the user is editing this shape, this component is rendered\n\t// - editor emits the select all event / place caret event\n\t// - the text editor is onCreate callback is called\n\tconst rCreateInfo = useRef({\n\t\tselectAll: false,\n\t\tcaretPosition: null as { x: number; y: number } | null,\n\t})\n\n\tuseLayoutEffect(() => {\n\t\tfunction selectAllIfEditing(event: { shapeId: TLShapeId }) {\n\t\t\tif (event.shapeId === editor.getEditingShapeId()) {\n\t\t\t\trCreateInfo.current.selectAll = true\n\t\t\t}\n\t\t}\n\n\t\tfunction placeCaret(event: { shapeId: TLShapeId; point: { x: number; y: number } }) {\n\t\t\tif (event.shapeId === editor.getEditingShapeId()) {\n\t\t\t\trCreateInfo.current.caretPosition = event.point\n\t\t\t}\n\t\t}\n\n\t\teditor.on('select-all-text', selectAllIfEditing)\n\t\teditor.on('place-caret', placeCaret)\n\t\treturn () => {\n\t\t\teditor.off('select-all-text', selectAllIfEditing)\n\t\t\teditor.off('place-caret', placeCaret)\n\t\t}\n\t}, [editor, isEditing])\n\n\tconst onChange = useEvent(handleChange)\n\tconst onKeyDown = useEvent(handleKeyDown)\n\tconst onFocus = useEvent(handleFocus)\n\tconst onBlur = useEvent(handleBlur)\n\tconst onDoubleClick = useEvent(handleDoubleClick)\n\tconst onPaste = useEvent(handlePaste)\n\tuseLayoutEffect(() => {\n\t\tif (!isEditing || !tipTapConfig || !rTextEditorEl.current) return\n\n\t\tconst { editorProps, ...restOfTipTapConfig } = tipTapConfig\n\n\t\t// Because React can double-render in Strict Mode, we need to make sure we're not setting\n\t\t// the text editor twice. This became more much more prevalent in React 19, but also it\n\t\t// started manifesting in some cases in Next 14.2 (which maybe patches React 18.3 in weird\n\t\t// ways). So we used to use EditorProvider but we into weird rendering issues.\n\t\tconst textEditorInstance = new TextEditor({\n\t\t\telement: rTextEditorEl.current,\n\t\t\tautofocus: true,\n\t\t\teditable: isEditing,\n\t\t\tonUpdate: (props: EditorEvents['update']) => {\n\t\t\t\tconst content: TLRichText = props.editor.state.doc.toJSON()\n\t\t\t\trInitialRichText.current = content\n\t\t\t\tonChange({ richText: content })\n\t\t\t},\n\t\t\tonFocus,\n\t\t\tonBlur,\n\t\t\t// onCreate is called after a `setTimeout(0)`\n\t\t\tonCreate: (props) => {\n\t\t\t\t// If we're not still editing the original shape, then don't do anything.\n\t\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\n\t\t\t\tconst textEditor = props.editor\n\t\t\t\teditor.setRichTextEditor(textEditor)\n\n\t\t\t\tconst { selectAll, caretPosition } = rCreateInfo.current\n\n\t\t\t\tif (selectAll) {\n\t\t\t\t\t// Select all of the text\n\t\t\t\t\ttextEditor.chain().focus().selectAll().run()\n\t\t\t\t} else if (caretPosition) {\n\t\t\t\t\t// Set the initial caret screen position\n\t\t\t\t\tconst pos = textEditor.view.posAtCoords({\n\t\t\t\t\t\tleft: caretPosition.x,\n\t\t\t\t\t\ttop: caretPosition.y,\n\t\t\t\t\t})?.pos\n\n\t\t\t\t\tif (pos) {\n\t\t\t\t\t\t// Focus to that position.\n\t\t\t\t\t\ttextEditor.chain().focus().setTextSelection(pos).run()\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If no position, default to select all.\n\t\t\t\t\t\ttextEditor.chain().focus().selectAll().run()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\teditorProps: {\n\t\t\t\thandleKeyDown: (view: EditorView, event: KeyboardEvent) => {\n\t\t\t\t\tif (!hasCustomTabBehavior && event.key === 'Tab') {\n\t\t\t\t\t\thandleTab(editor, view, event)\n\t\t\t\t\t}\n\n\t\t\t\t\tonKeyDown(event)\n\t\t\t\t},\n\t\t\t\thandlePaste: (view: EditorView, event: ClipboardEvent) => {\n\t\t\t\t\tonPaste(event)\n\t\t\t\t\tif (event.defaultPrevented) return true\n\t\t\t\t},\n\t\t\t\thandleDoubleClick: (_view, _pos, event) => onDoubleClick(event),\n\t\t\t\t...editorProps,\n\t\t\t},\n\t\t\tcoreExtensionOptions: {\n\t\t\t\tclipboardTextSerializer: {\n\t\t\t\t\tblockSeparator: '\\n',\n\t\t\t\t},\n\t\t\t},\n\t\t\t...restOfTipTapConfig,\n\t\t\tcontent: rInitialRichText.current as JSONContent,\n\t\t})\n\n\t\t// XXX: When creating a brand new shape and double-clicking into it quickly to edit it,\n\t\t// there's some kind of race condition happening where the editor doesn't focus properly.\n\t\tconst timeout = editor.timers.setTimeout(() => {\n\t\t\tif (rCreateInfo.current.caretPosition || rCreateInfo.current.selectAll) {\n\t\t\t\ttextEditorInstance.commands.focus()\n\t\t\t} else {\n\t\t\t\ttextEditorInstance.commands.focus('end')\n\t\t\t}\n\n\t\t\trCreateInfo.current.selectAll = false\n\t\t\trCreateInfo.current.caretPosition = null\n\t\t}, 100)\n\n\t\trTextEditor.current = textEditorInstance\n\n\t\treturn () => {\n\t\t\trTextEditor.current = null\n\t\t\tclearTimeout(timeout)\n\t\t\ttextEditorInstance.destroy()\n\t\t}\n\t}, [\n\t\tisEditing,\n\t\ttipTapConfig,\n\t\tonFocus,\n\t\tonBlur,\n\t\tonDoubleClick,\n\t\tonChange,\n\t\tonPaste,\n\t\tonKeyDown,\n\t\teditor,\n\t\tshapeId,\n\t\thasCustomTabBehavior,\n\t])\n\n\tif (!isEditing || !tipTapConfig) {\n\t\treturn null\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tid={tipTapId}\n\t\t\tref={ref}\n\t\t\ttabIndex={-1}\n\t\t\tdata-testid=\"rich-text-area\"\n\t\t\tclassName=\"tl-rich-text tl-text tl-text-input\"\n\t\t\tonContextMenu={isEditing ? (e) => e.stopPropagation() : undefined}\n\t\t\t// N.B. When PointerStateExtension was introduced, this was moved there.\n\t\t\t// However, that caused selecting over list items to break.\n\t\t\t// The handleDOMEvents in TipTap don't seem to support the pointerDownCapture event.\n\t\t\tonPointerDownCapture={(e) => e.stopPropagation()}\n\t\t\t// This onTouchEnd is important for Android to be able to change selection on text.\n\t\t\tonTouchEnd={(e) => e.stopPropagation()}\n\t\t\t// On FF, there's a behavior where dragging a selection will grab that selection into\n\t\t\t// the drag event. However, once the drag is over, and you select away from the textarea,\n\t\t\t// starting a drag over the textarea will restart a selection drag instead of a shape drag.\n\t\t\t// This prevents that default behavior in FF.\n\t\t\tonDragStart={preventDefault}\n\t\t>\n\t\t\t<div className=\"tl-rich-text\" ref={rTextEditorEl} />\n\t\t</div>\n\t)\n})\n\n// Prevent exiting the editor when hitting Tab.\n// Also, insert a tab character at the front of the line if the shift key isn't pressed,\n// otherwise if shift is pressed, remove a tab character from the front of the line.\nfunction handleTab(editor: Editor, view: EditorView, event: KeyboardEvent) {\n\t// Don't exit the editor.\n\tevent.preventDefault()\n\n\tconst textEditor = editor.getRichTextEditor()\n\tif (textEditor?.isActive('bulletList') || textEditor?.isActive('orderedList')) return\n\n\tconst { state, dispatch } = view\n\tconst { $from, $to } = state.selection\n\tconst isShift = event.shiftKey\n\n\t// Create a new transaction\n\tlet tr = state.tr\n\n\t// Iterate over each line in the selection in reverse so that the positions\n\t// are stable as we modify the document.\n\tlet pos = $to.end()\n\twhile (pos >= $from.start()) {\n\t\tconst line = state.doc.resolve(pos).blockRange()\n\t\tif (!line) break\n\n\t\tconst lineStart = line.start\n\t\tconst lineEnd = line.end\n\t\tconst lineText = state.doc.textBetween(lineStart, lineEnd, '\\n')\n\n\t\t// Check if the current line or any of its parent nodes are part of a list\n\t\tlet isInList = false\n\t\tstate.doc.nodesBetween(lineStart, lineEnd, (node) => {\n\t\t\tif (node.type.name === 'bulletList' || node.type.name === 'orderedList') {\n\t\t\t\tisInList = true\n\t\t\t\treturn false // Stop iteration\n\t\t\t}\n\t\t})\n\n\t\t// TODO: for now skip over lists. Later, we might consider handling them using\n\t\t// sinkListItem and liftListItem from @tiptap/pm/schema-list\n\t\tif (!isInList) {\n\t\t\tif (!isShift) {\n\t\t\t\t// Insert a tab character at the start of the line\n\t\t\t\ttr = tr.insertText('\\t', lineStart + 1)\n\t\t\t} else {\n\t\t\t\t// Remove a tab character from the start of the line\n\t\t\t\tif (lineText.startsWith('\\t')) {\n\t\t\t\t\ttr = tr.delete(lineStart + 1, lineStart + 2)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpos = lineStart - 1\n\t}\n\n\tconst mappedSelection = state.selection.map(tr.doc, tr.mapping)\n\ttr.setSelection(mappedSelection)\n\n\tif (tr.docChanged) {\n\t\tdispatch(tr)\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["RichTextArea"]
7
7
  }
@@ -95,6 +95,8 @@ class DraggingHandle extends StateNode {
95
95
  exactTimeout = -1;
96
96
  // Only relevant to arrows
97
97
  resetExactTimeout() {
98
+ const arrowUtil = this.editor.getShapeUtil("arrow");
99
+ const timeoutValue = arrowUtil.options.pointingPreciseTimeout;
98
100
  if (this.exactTimeout !== -1) {
99
101
  this.clearExactTimeout();
100
102
  }
@@ -105,7 +107,7 @@ class DraggingHandle extends StateNode {
105
107
  this.update();
106
108
  }
107
109
  this.exactTimeout = -1;
108
- }, 750);
110
+ }, timeoutValue);
109
111
  }
110
112
  // Only relevant to arrows
111
113
  clearExactTimeout() {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/tools/SelectTool/childStates/DraggingHandle.tsx"],
4
- "sourcesContent": ["import {\n\tMat,\n\tStateNode,\n\tTLArrowShape,\n\tTLHandle,\n\tTLLineShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\tTLShapePartial,\n\tVec,\n\tkickoutOccludedShapes,\n\tsnapAngle,\n\tsortByIndex,\n\tstructuredClone,\n} from '@tldraw/editor'\nimport { clearArrowTargetState } from '../../../shapes/arrow/arrowTargetState'\nimport { getArrowBindings } from '../../../shapes/arrow/shared'\n\nexport type DraggingHandleInfo = TLPointerEventInfo & {\n\tshape: TLArrowShape | TLLineShape\n\ttarget: 'handle'\n\tonInteractionEnd?: string\n\tisCreating?: boolean\n\tcreatingMarkId?: string\n}\n\nexport class DraggingHandle extends StateNode {\n\tstatic override id = 'dragging_handle'\n\n\tshapeId!: TLShapeId\n\tinitialHandle!: TLHandle\n\tinitialAdjacentHandle!: TLHandle | null\n\tinitialPagePoint!: Vec\n\n\tmarkId!: string\n\tinitialPageTransform!: Mat\n\tinitialPageRotation!: number\n\n\tinfo!: DraggingHandleInfo\n\n\tisPrecise = false\n\tisPreciseId: TLShapeId | null = null\n\tpointingId: TLShapeId | null = null\n\n\toverride onEnter(info: DraggingHandleInfo) {\n\t\tconst { shape, isCreating, creatingMarkId, handle } = info\n\t\tthis.info = info\n\t\tthis.parent.setCurrentToolIdMask(info.onInteractionEnd)\n\t\tthis.shapeId = shape.id\n\t\tthis.markId = ''\n\n\t\tif (isCreating) {\n\t\t\tif (creatingMarkId) {\n\t\t\t\tthis.markId = creatingMarkId\n\t\t\t} else {\n\t\t\t\t// handle legacy implicit `creating:{shapeId}` marks\n\t\t\t\tconst markId = this.editor.getMarkIdMatching(\n\t\t\t\t\t`creating:${this.editor.getOnlySelectedShapeId()}`\n\t\t\t\t)\n\t\t\t\tif (markId) {\n\t\t\t\t\tthis.markId = markId\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.markId = this.editor.markHistoryStoppingPoint('dragging handle')\n\t\t}\n\n\t\tthis.initialHandle = structuredClone(handle)\n\n\t\tthis.initialPageTransform = this.editor.getShapePageTransform(shape)!\n\t\tthis.initialPageRotation = this.initialPageTransform.rotation()\n\t\tthis.initialPagePoint = this.editor.inputs.originPagePoint.clone()\n\n\t\tthis.editor.setCursor({ type: isCreating ? 'cross' : 'grabbing', rotation: 0 })\n\n\t\tconst handles = this.editor.getShapeHandles(shape)!.sort(sortByIndex)\n\t\tconst index = handles.findIndex((h) => h.id === info.handle.id)\n\n\t\t// Find the adjacent handle\n\t\tthis.initialAdjacentHandle = null\n\n\t\t// Start from the handle and work forward\n\t\tfor (let i = index + 1; i < handles.length; i++) {\n\t\t\tconst handle = handles[i]\n\t\t\tif (handle.type === 'vertex' && handle.id !== 'middle' && handle.id !== info.handle.id) {\n\t\t\t\tthis.initialAdjacentHandle = handle\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// If still no handle, start from the end and work backward\n\t\tif (!this.initialAdjacentHandle) {\n\t\t\tfor (let i = handles.length - 1; i >= 0; i--) {\n\t\t\t\tconst handle = handles[i]\n\t\t\t\tif (handle.type === 'vertex' && handle.id !== 'middle' && handle.id !== info.handle.id) {\n\t\t\t\t\tthis.initialAdjacentHandle = handle\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// <!-- Only relevant to arrows\n\t\tif (this.editor.isShapeOfType<TLArrowShape>(shape, 'arrow')) {\n\t\t\tconst initialBinding = getArrowBindings(this.editor, shape)[info.handle.id as 'start' | 'end']\n\n\t\t\tthis.isPrecise = false\n\n\t\t\tif (initialBinding) {\n\t\t\t\tthis.isPrecise = initialBinding.props.isPrecise\n\t\t\t\tif (this.isPrecise) {\n\t\t\t\t\tthis.isPreciseId = initialBinding.toId\n\t\t\t\t} else {\n\t\t\t\t\tthis.resetExactTimeout()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// -->\n\n\t\t// Call onHandleDragStart callback\n\t\tconst handleDragInfo = {\n\t\t\thandle: this.initialHandle,\n\t\t\tisPrecise: this.isPrecise,\n\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\tinitial: shape,\n\t\t}\n\t\tconst util = this.editor.getShapeUtil(shape)\n\t\tconst startChanges = util.onHandleDragStart?.(shape, handleDragInfo)\n\t\tif (startChanges) {\n\t\t\tthis.editor.updateShapes([{ ...startChanges, id: shape.id, type: shape.type }])\n\t\t}\n\n\t\tthis.update()\n\n\t\tthis.editor.select(this.shapeId)\n\t}\n\n\t// Only relevant to arrows\n\tprivate exactTimeout = -1 as any\n\n\t// Only relevant to arrows\n\tprivate resetExactTimeout() {\n\t\tif (this.exactTimeout !== -1) {\n\t\t\tthis.clearExactTimeout()\n\t\t}\n\n\t\tthis.exactTimeout = this.editor.timers.setTimeout(() => {\n\t\t\tif (this.getIsActive() && !this.isPrecise) {\n\t\t\t\tthis.isPrecise = true\n\t\t\t\tthis.isPreciseId = this.pointingId\n\t\t\t\tthis.update()\n\t\t\t}\n\t\t\tthis.exactTimeout = -1\n\t\t}, 750)\n\t}\n\n\t// Only relevant to arrows\n\tprivate clearExactTimeout() {\n\t\tif (this.exactTimeout !== -1) {\n\t\t\tclearTimeout(this.exactTimeout)\n\t\t\tthis.exactTimeout = -1\n\t\t}\n\t}\n\n\toverride onPointerMove() {\n\t\tthis.update()\n\t}\n\n\toverride onKeyDown() {\n\t\tthis.update()\n\t}\n\n\toverride onKeyUp() {\n\t\tthis.update()\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onComplete() {\n\t\tthis.update()\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onExit() {\n\t\tthis.parent.setCurrentToolIdMask(undefined)\n\t\tclearArrowTargetState(this.editor)\n\t\tthis.editor.snaps.clearIndicators()\n\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t}\n\n\tprivate complete() {\n\t\tthis.editor.snaps.clearIndicators()\n\t\tkickoutOccludedShapes(this.editor, [this.shapeId])\n\n\t\t// Call onHandleDragEnd callback before state transitions\n\t\tconst shape = this.editor.getShape(this.shapeId)\n\t\tif (shape) {\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst handleDragInfo = {\n\t\t\t\thandle: this.initialHandle,\n\t\t\t\tisPrecise: this.isPrecise,\n\t\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\t\tinitial: this.info.shape,\n\t\t\t}\n\t\t\tconst endChanges = util.onHandleDragEnd?.(shape, handleDragInfo)\n\t\t\tif (endChanges) {\n\t\t\t\tthis.editor.updateShapes([{ ...endChanges, id: shape.id, type: shape.type }])\n\t\t\t}\n\t\t}\n\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (this.editor.getInstanceState().isToolLocked && onInteractionEnd) {\n\t\t\t// Return to the tool that was active before this one,\n\t\t\t// but only if tool lock is turned on!\n\t\t\tthis.editor.setCurrentTool(onInteractionEnd, { shapeId: this.shapeId })\n\t\t\treturn\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tprivate cancel() {\n\t\t// Call onHandleDragCancel callback before bailing to mark\n\t\tconst shape = this.editor.getShape(this.shapeId)\n\t\tif (shape) {\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst handleDragInfo = {\n\t\t\t\thandle: this.initialHandle,\n\t\t\t\tisPrecise: this.isPrecise,\n\t\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\t\tinitial: this.info.shape,\n\t\t\t}\n\t\t\tutil.onHandleDragCancel?.(shape, handleDragInfo)\n\t\t}\n\n\t\tthis.editor.bailToMark(this.markId)\n\t\tthis.editor.snaps.clearIndicators()\n\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\t// Return to the tool that was active before this one,\n\t\t\t// whether tool lock is turned on or not!\n\t\t\tthis.editor.setCurrentTool(onInteractionEnd, { shapeId: this.shapeId })\n\t\t\treturn\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tprivate update() {\n\t\tconst { editor, shapeId, initialPagePoint } = this\n\t\tconst { initialHandle, initialPageRotation, initialAdjacentHandle } = this\n\t\tconst isSnapMode = this.editor.user.getIsSnapMode()\n\t\tconst {\n\t\t\tsnaps,\n\t\t\tinputs: { currentPagePoint, shiftKey, ctrlKey, altKey, pointerVelocity },\n\t\t} = editor\n\n\t\tconst initial = this.info.shape\n\n\t\tconst shape = editor.getShape(shapeId)\n\t\tif (!shape) return\n\t\tconst util = editor.getShapeUtil(shape)\n\n\t\tconst initialBinding = editor.isShapeOfType<TLArrowShape>(shape, 'arrow')\n\t\t\t? getArrowBindings(editor, shape)[initialHandle.id as 'start' | 'end']\n\t\t\t: undefined\n\n\t\tlet point = currentPagePoint\n\t\t\t.clone()\n\t\t\t.sub(initialPagePoint)\n\t\t\t.rot(-initialPageRotation)\n\t\t\t.add(initialHandle)\n\n\t\tif (shiftKey && initialAdjacentHandle && initialHandle.id !== 'middle') {\n\t\t\tconst angle = Vec.Angle(initialAdjacentHandle, point)\n\t\t\tconst snappedAngle = snapAngle(angle, 24)\n\t\t\tconst angleDifference = snappedAngle - angle\n\t\t\tpoint = Vec.RotWith(point, initialAdjacentHandle, angleDifference)\n\t\t}\n\n\t\t// Clear any existing snaps\n\t\teditor.snaps.clearIndicators()\n\n\t\tlet nextHandle = { ...initialHandle, x: point.x, y: point.y }\n\n\t\tif (initialHandle.canSnap && (isSnapMode ? !ctrlKey : ctrlKey)) {\n\t\t\t// We're snapping\n\t\t\tconst pageTransform = editor.getShapePageTransform(shape.id)\n\t\t\tif (!pageTransform) throw Error('Expected a page transform')\n\n\t\t\tconst snap = snaps.handles.snapHandle({ currentShapeId: shapeId, handle: nextHandle })\n\n\t\t\tif (snap) {\n\t\t\t\tsnap.nudge.rot(-editor.getShapeParentTransform(shape)!.rotation())\n\t\t\t\tpoint.add(snap.nudge)\n\t\t\t\tnextHandle = { ...initialHandle, x: point.x, y: point.y }\n\t\t\t}\n\t\t}\n\n\t\tconst changes = util.onHandleDrag?.(shape, {\n\t\t\thandle: nextHandle,\n\t\t\tisPrecise: this.isPrecise || altKey,\n\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\tinitial: initial,\n\t\t})\n\n\t\tconst next: TLShapePartial<any> = { id: shape.id, type: shape.type, ...changes }\n\n\t\t// Arrows\n\t\tif (\n\t\t\tinitialHandle.type === 'vertex' &&\n\t\t\tthis.editor.isShapeOfType<TLArrowShape>(shape, 'arrow')\n\t\t) {\n\t\t\tconst bindingAfter = getArrowBindings(editor, shape)[initialHandle.id as 'start' | 'end']\n\n\t\t\tif (bindingAfter) {\n\t\t\t\tif (initialBinding?.toId !== bindingAfter.toId) {\n\t\t\t\t\tthis.pointingId = bindingAfter.toId\n\t\t\t\t\tthis.isPrecise = pointerVelocity.len() < 0.5 || altKey\n\t\t\t\t\tthis.isPreciseId = this.isPrecise ? bindingAfter.toId : null\n\t\t\t\t\tthis.resetExactTimeout()\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (initialBinding) {\n\t\t\t\t\tthis.pointingId = null\n\t\t\t\t\tthis.isPrecise = false\n\t\t\t\t\tthis.isPreciseId = null\n\t\t\t\t\tthis.resetExactTimeout()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (changes) {\n\t\t\teditor.updateShapes([next])\n\t\t}\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tMat,\n\tStateNode,\n\tTLArrowShape,\n\tTLHandle,\n\tTLLineShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\tTLShapePartial,\n\tVec,\n\tkickoutOccludedShapes,\n\tsnapAngle,\n\tsortByIndex,\n\tstructuredClone,\n} from '@tldraw/editor'\nimport { ArrowShapeUtil } from '../../../shapes/arrow/ArrowShapeUtil'\nimport { clearArrowTargetState } from '../../../shapes/arrow/arrowTargetState'\nimport { getArrowBindings } from '../../../shapes/arrow/shared'\n\nexport type DraggingHandleInfo = TLPointerEventInfo & {\n\tshape: TLArrowShape | TLLineShape\n\ttarget: 'handle'\n\tonInteractionEnd?: string\n\tisCreating?: boolean\n\tcreatingMarkId?: string\n}\n\nexport class DraggingHandle extends StateNode {\n\tstatic override id = 'dragging_handle'\n\n\tshapeId!: TLShapeId\n\tinitialHandle!: TLHandle\n\tinitialAdjacentHandle!: TLHandle | null\n\tinitialPagePoint!: Vec\n\n\tmarkId!: string\n\tinitialPageTransform!: Mat\n\tinitialPageRotation!: number\n\n\tinfo!: DraggingHandleInfo\n\n\tisPrecise = false\n\tisPreciseId: TLShapeId | null = null\n\tpointingId: TLShapeId | null = null\n\n\toverride onEnter(info: DraggingHandleInfo) {\n\t\tconst { shape, isCreating, creatingMarkId, handle } = info\n\t\tthis.info = info\n\t\tthis.parent.setCurrentToolIdMask(info.onInteractionEnd)\n\t\tthis.shapeId = shape.id\n\t\tthis.markId = ''\n\n\t\tif (isCreating) {\n\t\t\tif (creatingMarkId) {\n\t\t\t\tthis.markId = creatingMarkId\n\t\t\t} else {\n\t\t\t\t// handle legacy implicit `creating:{shapeId}` marks\n\t\t\t\tconst markId = this.editor.getMarkIdMatching(\n\t\t\t\t\t`creating:${this.editor.getOnlySelectedShapeId()}`\n\t\t\t\t)\n\t\t\t\tif (markId) {\n\t\t\t\t\tthis.markId = markId\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.markId = this.editor.markHistoryStoppingPoint('dragging handle')\n\t\t}\n\n\t\tthis.initialHandle = structuredClone(handle)\n\n\t\tthis.initialPageTransform = this.editor.getShapePageTransform(shape)!\n\t\tthis.initialPageRotation = this.initialPageTransform.rotation()\n\t\tthis.initialPagePoint = this.editor.inputs.originPagePoint.clone()\n\n\t\tthis.editor.setCursor({ type: isCreating ? 'cross' : 'grabbing', rotation: 0 })\n\n\t\tconst handles = this.editor.getShapeHandles(shape)!.sort(sortByIndex)\n\t\tconst index = handles.findIndex((h) => h.id === info.handle.id)\n\n\t\t// Find the adjacent handle\n\t\tthis.initialAdjacentHandle = null\n\n\t\t// Start from the handle and work forward\n\t\tfor (let i = index + 1; i < handles.length; i++) {\n\t\t\tconst handle = handles[i]\n\t\t\tif (handle.type === 'vertex' && handle.id !== 'middle' && handle.id !== info.handle.id) {\n\t\t\t\tthis.initialAdjacentHandle = handle\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// If still no handle, start from the end and work backward\n\t\tif (!this.initialAdjacentHandle) {\n\t\t\tfor (let i = handles.length - 1; i >= 0; i--) {\n\t\t\t\tconst handle = handles[i]\n\t\t\t\tif (handle.type === 'vertex' && handle.id !== 'middle' && handle.id !== info.handle.id) {\n\t\t\t\t\tthis.initialAdjacentHandle = handle\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// <!-- Only relevant to arrows\n\t\tif (this.editor.isShapeOfType<TLArrowShape>(shape, 'arrow')) {\n\t\t\tconst initialBinding = getArrowBindings(this.editor, shape)[info.handle.id as 'start' | 'end']\n\n\t\t\tthis.isPrecise = false\n\n\t\t\tif (initialBinding) {\n\t\t\t\tthis.isPrecise = initialBinding.props.isPrecise\n\t\t\t\tif (this.isPrecise) {\n\t\t\t\t\tthis.isPreciseId = initialBinding.toId\n\t\t\t\t} else {\n\t\t\t\t\tthis.resetExactTimeout()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// -->\n\n\t\t// Call onHandleDragStart callback\n\t\tconst handleDragInfo = {\n\t\t\thandle: this.initialHandle,\n\t\t\tisPrecise: this.isPrecise,\n\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\tinitial: shape,\n\t\t}\n\t\tconst util = this.editor.getShapeUtil(shape)\n\t\tconst startChanges = util.onHandleDragStart?.(shape, handleDragInfo)\n\t\tif (startChanges) {\n\t\t\tthis.editor.updateShapes([{ ...startChanges, id: shape.id, type: shape.type }])\n\t\t}\n\n\t\tthis.update()\n\n\t\tthis.editor.select(this.shapeId)\n\t}\n\n\t// Only relevant to arrows\n\tprivate exactTimeout = -1\n\n\t// Only relevant to arrows\n\tprivate resetExactTimeout() {\n\t\tconst arrowUtil = this.editor.getShapeUtil<ArrowShapeUtil>('arrow')\n\t\tconst timeoutValue = arrowUtil.options.pointingPreciseTimeout\n\n\t\tif (this.exactTimeout !== -1) {\n\t\t\tthis.clearExactTimeout()\n\t\t}\n\n\t\tthis.exactTimeout = this.editor.timers.setTimeout(() => {\n\t\t\tif (this.getIsActive() && !this.isPrecise) {\n\t\t\t\tthis.isPrecise = true\n\t\t\t\tthis.isPreciseId = this.pointingId\n\t\t\t\tthis.update()\n\t\t\t}\n\t\t\tthis.exactTimeout = -1\n\t\t}, timeoutValue)\n\t}\n\n\t// Only relevant to arrows\n\tprivate clearExactTimeout() {\n\t\tif (this.exactTimeout !== -1) {\n\t\t\tclearTimeout(this.exactTimeout)\n\t\t\tthis.exactTimeout = -1\n\t\t}\n\t}\n\n\toverride onPointerMove() {\n\t\tthis.update()\n\t}\n\n\toverride onKeyDown() {\n\t\tthis.update()\n\t}\n\n\toverride onKeyUp() {\n\t\tthis.update()\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onComplete() {\n\t\tthis.update()\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onExit() {\n\t\tthis.parent.setCurrentToolIdMask(undefined)\n\t\tclearArrowTargetState(this.editor)\n\t\tthis.editor.snaps.clearIndicators()\n\n\t\tthis.editor.setCursor({ type: 'default', rotation: 0 })\n\t}\n\n\tprivate complete() {\n\t\tthis.editor.snaps.clearIndicators()\n\t\tkickoutOccludedShapes(this.editor, [this.shapeId])\n\n\t\t// Call onHandleDragEnd callback before state transitions\n\t\tconst shape = this.editor.getShape(this.shapeId)\n\t\tif (shape) {\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst handleDragInfo = {\n\t\t\t\thandle: this.initialHandle,\n\t\t\t\tisPrecise: this.isPrecise,\n\t\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\t\tinitial: this.info.shape,\n\t\t\t}\n\t\t\tconst endChanges = util.onHandleDragEnd?.(shape, handleDragInfo)\n\t\t\tif (endChanges) {\n\t\t\t\tthis.editor.updateShapes([{ ...endChanges, id: shape.id, type: shape.type }])\n\t\t\t}\n\t\t}\n\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (this.editor.getInstanceState().isToolLocked && onInteractionEnd) {\n\t\t\t// Return to the tool that was active before this one,\n\t\t\t// but only if tool lock is turned on!\n\t\t\tthis.editor.setCurrentTool(onInteractionEnd, { shapeId: this.shapeId })\n\t\t\treturn\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tprivate cancel() {\n\t\t// Call onHandleDragCancel callback before bailing to mark\n\t\tconst shape = this.editor.getShape(this.shapeId)\n\t\tif (shape) {\n\t\t\tconst util = this.editor.getShapeUtil(shape)\n\t\t\tconst handleDragInfo = {\n\t\t\t\thandle: this.initialHandle,\n\t\t\t\tisPrecise: this.isPrecise,\n\t\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\t\tinitial: this.info.shape,\n\t\t\t}\n\t\t\tutil.onHandleDragCancel?.(shape, handleDragInfo)\n\t\t}\n\n\t\tthis.editor.bailToMark(this.markId)\n\t\tthis.editor.snaps.clearIndicators()\n\n\t\tconst { onInteractionEnd } = this.info\n\t\tif (onInteractionEnd) {\n\t\t\t// Return to the tool that was active before this one,\n\t\t\t// whether tool lock is turned on or not!\n\t\t\tthis.editor.setCurrentTool(onInteractionEnd, { shapeId: this.shapeId })\n\t\t\treturn\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tprivate update() {\n\t\tconst { editor, shapeId, initialPagePoint } = this\n\t\tconst { initialHandle, initialPageRotation, initialAdjacentHandle } = this\n\t\tconst isSnapMode = this.editor.user.getIsSnapMode()\n\t\tconst {\n\t\t\tsnaps,\n\t\t\tinputs: { currentPagePoint, shiftKey, ctrlKey, altKey, pointerVelocity },\n\t\t} = editor\n\n\t\tconst initial = this.info.shape\n\n\t\tconst shape = editor.getShape(shapeId)\n\t\tif (!shape) return\n\t\tconst util = editor.getShapeUtil(shape)\n\n\t\tconst initialBinding = editor.isShapeOfType<TLArrowShape>(shape, 'arrow')\n\t\t\t? getArrowBindings(editor, shape)[initialHandle.id as 'start' | 'end']\n\t\t\t: undefined\n\n\t\tlet point = currentPagePoint\n\t\t\t.clone()\n\t\t\t.sub(initialPagePoint)\n\t\t\t.rot(-initialPageRotation)\n\t\t\t.add(initialHandle)\n\n\t\tif (shiftKey && initialAdjacentHandle && initialHandle.id !== 'middle') {\n\t\t\tconst angle = Vec.Angle(initialAdjacentHandle, point)\n\t\t\tconst snappedAngle = snapAngle(angle, 24)\n\t\t\tconst angleDifference = snappedAngle - angle\n\t\t\tpoint = Vec.RotWith(point, initialAdjacentHandle, angleDifference)\n\t\t}\n\n\t\t// Clear any existing snaps\n\t\teditor.snaps.clearIndicators()\n\n\t\tlet nextHandle = { ...initialHandle, x: point.x, y: point.y }\n\n\t\tif (initialHandle.canSnap && (isSnapMode ? !ctrlKey : ctrlKey)) {\n\t\t\t// We're snapping\n\t\t\tconst pageTransform = editor.getShapePageTransform(shape.id)\n\t\t\tif (!pageTransform) throw Error('Expected a page transform')\n\n\t\t\tconst snap = snaps.handles.snapHandle({ currentShapeId: shapeId, handle: nextHandle })\n\n\t\t\tif (snap) {\n\t\t\t\tsnap.nudge.rot(-editor.getShapeParentTransform(shape)!.rotation())\n\t\t\t\tpoint.add(snap.nudge)\n\t\t\t\tnextHandle = { ...initialHandle, x: point.x, y: point.y }\n\t\t\t}\n\t\t}\n\n\t\tconst changes = util.onHandleDrag?.(shape, {\n\t\t\thandle: nextHandle,\n\t\t\tisPrecise: this.isPrecise || altKey,\n\t\t\tisCreatingShape: !!this.info.isCreating,\n\t\t\tinitial: initial,\n\t\t})\n\n\t\tconst next: TLShapePartial<any> = { id: shape.id, type: shape.type, ...changes }\n\n\t\t// Arrows\n\t\tif (\n\t\t\tinitialHandle.type === 'vertex' &&\n\t\t\tthis.editor.isShapeOfType<TLArrowShape>(shape, 'arrow')\n\t\t) {\n\t\t\tconst bindingAfter = getArrowBindings(editor, shape)[initialHandle.id as 'start' | 'end']\n\n\t\t\tif (bindingAfter) {\n\t\t\t\tif (initialBinding?.toId !== bindingAfter.toId) {\n\t\t\t\t\tthis.pointingId = bindingAfter.toId\n\t\t\t\t\tthis.isPrecise = pointerVelocity.len() < 0.5 || altKey\n\t\t\t\t\tthis.isPreciseId = this.isPrecise ? bindingAfter.toId : null\n\t\t\t\t\tthis.resetExactTimeout()\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (initialBinding) {\n\t\t\t\t\tthis.pointingId = null\n\t\t\t\t\tthis.isPrecise = false\n\t\t\t\t\tthis.isPreciseId = null\n\t\t\t\t\tthis.resetExactTimeout()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (changes) {\n\t\t\teditor.updateShapes([next])\n\t\t}\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["handle"]
7
7
  }
@@ -1,7 +1,6 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import {
3
3
  debugFlags,
4
- stopEventPropagation,
5
4
  unsafe__withoutCapture,
6
5
  useContainer,
7
6
  useEditor,
@@ -19,7 +18,7 @@ function SkipToMainContent() {
19
18
  const button = useRef(null);
20
19
  const handleNavigateToFirstShape = useCallback(
21
20
  (e) => {
22
- stopEventPropagation(e);
21
+ editor.markEventAsHandled(e);
23
22
  button.current?.blur();
24
23
  const shapes = editor.getCurrentPageShapesInReadingOrder();
25
24
  if (!shapes.length) return;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/ui/components/A11y.tsx"],
4
- "sourcesContent": ["import {\n\tdebugFlags,\n\tEditor,\n\tstopEventPropagation,\n\tTLGeoShape,\n\tTLShapeId,\n\tunsafe__withoutCapture,\n\tuseContainer,\n\tuseEditor,\n\tuseMaybeEditor,\n\tuseReactor,\n\tuseValue,\n} from '@tldraw/editor'\nimport { memo, MouseEvent, useCallback, useEffect, useRef } from 'react'\nimport { useA11y } from '../context/a11y'\nimport { useTranslation } from '../hooks/useTranslation/useTranslation'\nimport { TldrawUiButton } from './primitives/Button/TldrawUiButton'\n\nexport function SkipToMainContent() {\n\tconst editor = useEditor()\n\tconst msg = useTranslation()\n\tconst button = useRef<HTMLButtonElement>(null)\n\n\tconst handleNavigateToFirstShape = useCallback(\n\t\t(e: MouseEvent | KeyboardEvent) => {\n\t\t\tstopEventPropagation(e)\n\t\t\tbutton.current?.blur()\n\t\t\tconst shapes = editor.getCurrentPageShapesInReadingOrder()\n\t\t\tif (!shapes.length) return\n\t\t\teditor.setSelectedShapes([shapes[0].id])\n\t\t\teditor.zoomToSelectionIfOffscreen(256, {\n\t\t\t\tanimation: {\n\t\t\t\t\tduration: editor.options.animationMediumMs,\n\t\t\t\t},\n\t\t\t\tinset: 0,\n\t\t\t})\n\n\t\t\t// N.B. If we don't do this, then we go into editing mode for some reason...\n\t\t\t// Not sure of a better solution at the moment...\n\t\t\teditor.timers.setTimeout(() => editor.getContainer().focus(), 100)\n\t\t},\n\t\t[editor]\n\t)\n\n\treturn (\n\t\t<TldrawUiButton\n\t\t\tref={button}\n\t\t\ttype=\"low\"\n\t\t\ttabIndex={0}\n\t\t\tclassName=\"tl-skip-to-main-content\"\n\t\t\tonClick={handleNavigateToFirstShape}\n\t\t>\n\t\t\t{msg('a11y.skip-to-main-content')}\n\t\t</TldrawUiButton>\n\t)\n}\n\n/** @public @react */\nexport const DefaultA11yAnnouncer = memo(function TldrawUiA11yAnnouncer() {\n\tconst a11y = useA11y()\n\tconst translation = useTranslation()\n\tconst msg = useValue('a11y-msg', () => a11y.currentMsg.get(), [])\n\tuseA11yDebug(msg.msg)\n\n\tuseSelectedShapesAnnouncer()\n\n\treturn (\n\t\tmsg.msg && (\n\t\t\t<div\n\t\t\t\taria-label={translation('a11y.status')}\n\t\t\t\taria-live={msg.priority || 'assertive'}\n\t\t\t\trole=\"status\"\n\t\t\t\taria-hidden=\"false\"\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\ttop: '-10000px',\n\t\t\t\t\tleft: '-10000px',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{msg.msg}\n\t\t\t</div>\n\t\t)\n\t)\n})\n\n/**\n * Core function to generate accessibility announcements for selected shapes\n * @public\n */\nexport function generateShapeAnnouncementMessage(args: {\n\teditor: Editor\n\tselectedShapeIds: TLShapeId[]\n\tmsg(id: string, values?: Record<string, any>): string\n}) {\n\tconst { editor, selectedShapeIds, msg } = args\n\tlet a11yLive = ''\n\tconst numShapes = selectedShapeIds.length\n\n\tif (numShapes > 1) {\n\t\ta11yLive = msg('a11y.multiple-shapes').replace('{num}', numShapes.toString())\n\t} else if (numShapes === 1) {\n\t\tconst shapeId = selectedShapeIds[0]\n\t\tconst shape = editor.getShape(shapeId)\n\t\tif (!shape) return ''\n\n\t\tconst shapeUtil = editor.getShapeUtil(shape.type)\n\n\t\tconst isMedia = ['image', 'video'].includes(shape.type)\n\t\t// Yeah, yeah this is a bit of a hack, we should get better translations.\n\t\tlet shapeType = ''\n\t\tif (shape.type === 'geo') {\n\t\t\tshapeType = msg(`geo-style.${(shape as TLGeoShape).props.geo}`)\n\t\t} else if (isMedia) {\n\t\t\tshapeType = msg(`a11y.shape-${shape.type}`)\n\t\t} else {\n\t\t\tshapeType = msg(`tool.${shape.type}`)\n\t\t}\n\n\t\t// Get shape index in reading order\n\t\tconst readingOrderShapes = editor.getCurrentPageShapesInReadingOrder()\n\t\tconst currentShapeIndex = (readingOrderShapes.findIndex((s) => s.id === shapeId) + 1).toString()\n\t\tconst totalShapes = readingOrderShapes.length.toString()\n\t\tconst shapeIndex = msg('a11y.shape-index')\n\t\t\t.replace('{num}', currentShapeIndex)\n\t\t\t.replace('{total}', totalShapes)\n\n\t\t// Get describing text (alt text or shape text)\n\t\tconst describingText = shapeUtil.getAriaDescriptor(shape) || shapeUtil.getText(shape) || ''\n\n\t\t// Build the full announcement\n\t\ta11yLive = (describingText ? `${describingText}, ` : '') + `${shapeType}. ${shapeIndex}`\n\t}\n\n\treturn a11yLive\n}\n\n/** @public */\nexport const useSelectedShapesAnnouncer = () => {\n\tconst editor = useMaybeEditor()\n\tconst a11y = useA11y()\n\tconst msg = useTranslation()\n\n\tconst rPrevSelectedShapeIds = useRef<string[]>([])\n\n\tuseReactor(\n\t\t'announce selection',\n\t\t() => {\n\t\t\tif (!editor) return\n\n\t\t\tconst isInSelecting = editor.isIn('select.idle')\n\t\t\tif (isInSelecting) {\n\t\t\t\tconst selectedShapeIds = editor.getSelectedShapeIds()\n\t\t\t\tif (selectedShapeIds !== rPrevSelectedShapeIds.current) {\n\t\t\t\t\trPrevSelectedShapeIds.current = selectedShapeIds\n\t\t\t\t\tunsafe__withoutCapture(() => {\n\t\t\t\t\t\tconst a11yLive = generateShapeAnnouncementMessage({\n\t\t\t\t\t\t\teditor,\n\t\t\t\t\t\t\tselectedShapeIds,\n\t\t\t\t\t\t\tmsg,\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tif (a11yLive) {\n\t\t\t\t\t\t\ta11y.announce({ msg: a11yLive })\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, a11y, msg]\n\t)\n}\n\nconst useA11yDebug = (msg: string | undefined) => {\n\tconst container = useContainer()\n\n\tuseEffect(() => {\n\t\tif (debugFlags.a11y.get()) {\n\t\t\tconst log = (msg: string) => {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.debug(\n\t\t\t\t\t`%ca11y%c: ${msg}`,\n\t\t\t\t\t`color: white; background: #40C057; padding: 2px;border-radius: 3px;`,\n\t\t\t\t\t'font-weight: normal'\n\t\t\t\t)\n\t\t\t}\n\t\t\tconst handleKeyUp = (e: KeyboardEvent) => {\n\t\t\t\tconst el = document.activeElement\n\t\t\t\tif (\n\t\t\t\t\te.key === 'Tab' &&\n\t\t\t\t\tel &&\n\t\t\t\t\tel !== document.body &&\n\t\t\t\t\t!el.classList.contains('tl-container')\n\t\t\t\t) {\n\t\t\t\t\tconst label = el.getAttribute('aria-label') || el.getAttribute('title') || el.textContent\n\t\t\t\t\tif (label) {\n\t\t\t\t\t\tlog(label)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (msg) {\n\t\t\t\tlog(msg)\n\t\t\t}\n\n\t\t\tdocument.addEventListener('keyup', handleKeyUp)\n\t\t\treturn () => document.removeEventListener('keyup', handleKeyUp)\n\t\t}\n\t}, [container, msg])\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tdebugFlags,\n\tEditor,\n\tTLGeoShape,\n\tTLShapeId,\n\tunsafe__withoutCapture,\n\tuseContainer,\n\tuseEditor,\n\tuseMaybeEditor,\n\tuseReactor,\n\tuseValue,\n} from '@tldraw/editor'\nimport { memo, MouseEvent, useCallback, useEffect, useRef } from 'react'\nimport { useA11y } from '../context/a11y'\nimport { useTranslation } from '../hooks/useTranslation/useTranslation'\nimport { TldrawUiButton } from './primitives/Button/TldrawUiButton'\n\nexport function SkipToMainContent() {\n\tconst editor = useEditor()\n\tconst msg = useTranslation()\n\tconst button = useRef<HTMLButtonElement>(null)\n\n\tconst handleNavigateToFirstShape = useCallback(\n\t\t(e: MouseEvent | KeyboardEvent) => {\n\t\t\teditor.markEventAsHandled(e)\n\t\t\tbutton.current?.blur()\n\t\t\tconst shapes = editor.getCurrentPageShapesInReadingOrder()\n\t\t\tif (!shapes.length) return\n\t\t\teditor.setSelectedShapes([shapes[0].id])\n\t\t\teditor.zoomToSelectionIfOffscreen(256, {\n\t\t\t\tanimation: {\n\t\t\t\t\tduration: editor.options.animationMediumMs,\n\t\t\t\t},\n\t\t\t\tinset: 0,\n\t\t\t})\n\n\t\t\t// N.B. If we don't do this, then we go into editing mode for some reason...\n\t\t\t// Not sure of a better solution at the moment...\n\t\t\teditor.timers.setTimeout(() => editor.getContainer().focus(), 100)\n\t\t},\n\t\t[editor]\n\t)\n\n\treturn (\n\t\t<TldrawUiButton\n\t\t\tref={button}\n\t\t\ttype=\"low\"\n\t\t\ttabIndex={0}\n\t\t\tclassName=\"tl-skip-to-main-content\"\n\t\t\tonClick={handleNavigateToFirstShape}\n\t\t>\n\t\t\t{msg('a11y.skip-to-main-content')}\n\t\t</TldrawUiButton>\n\t)\n}\n\n/** @public @react */\nexport const DefaultA11yAnnouncer = memo(function TldrawUiA11yAnnouncer() {\n\tconst a11y = useA11y()\n\tconst translation = useTranslation()\n\tconst msg = useValue('a11y-msg', () => a11y.currentMsg.get(), [])\n\tuseA11yDebug(msg.msg)\n\n\tuseSelectedShapesAnnouncer()\n\n\treturn (\n\t\tmsg.msg && (\n\t\t\t<div\n\t\t\t\taria-label={translation('a11y.status')}\n\t\t\t\taria-live={msg.priority || 'assertive'}\n\t\t\t\trole=\"status\"\n\t\t\t\taria-hidden=\"false\"\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\ttop: '-10000px',\n\t\t\t\t\tleft: '-10000px',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{msg.msg}\n\t\t\t</div>\n\t\t)\n\t)\n})\n\n/**\n * Core function to generate accessibility announcements for selected shapes\n * @public\n */\nexport function generateShapeAnnouncementMessage(args: {\n\teditor: Editor\n\tselectedShapeIds: TLShapeId[]\n\tmsg(id: string, values?: Record<string, any>): string\n}) {\n\tconst { editor, selectedShapeIds, msg } = args\n\tlet a11yLive = ''\n\tconst numShapes = selectedShapeIds.length\n\n\tif (numShapes > 1) {\n\t\ta11yLive = msg('a11y.multiple-shapes').replace('{num}', numShapes.toString())\n\t} else if (numShapes === 1) {\n\t\tconst shapeId = selectedShapeIds[0]\n\t\tconst shape = editor.getShape(shapeId)\n\t\tif (!shape) return ''\n\n\t\tconst shapeUtil = editor.getShapeUtil(shape.type)\n\n\t\tconst isMedia = ['image', 'video'].includes(shape.type)\n\t\t// Yeah, yeah this is a bit of a hack, we should get better translations.\n\t\tlet shapeType = ''\n\t\tif (shape.type === 'geo') {\n\t\t\tshapeType = msg(`geo-style.${(shape as TLGeoShape).props.geo}`)\n\t\t} else if (isMedia) {\n\t\t\tshapeType = msg(`a11y.shape-${shape.type}`)\n\t\t} else {\n\t\t\tshapeType = msg(`tool.${shape.type}`)\n\t\t}\n\n\t\t// Get shape index in reading order\n\t\tconst readingOrderShapes = editor.getCurrentPageShapesInReadingOrder()\n\t\tconst currentShapeIndex = (readingOrderShapes.findIndex((s) => s.id === shapeId) + 1).toString()\n\t\tconst totalShapes = readingOrderShapes.length.toString()\n\t\tconst shapeIndex = msg('a11y.shape-index')\n\t\t\t.replace('{num}', currentShapeIndex)\n\t\t\t.replace('{total}', totalShapes)\n\n\t\t// Get describing text (alt text or shape text)\n\t\tconst describingText = shapeUtil.getAriaDescriptor(shape) || shapeUtil.getText(shape) || ''\n\n\t\t// Build the full announcement\n\t\ta11yLive = (describingText ? `${describingText}, ` : '') + `${shapeType}. ${shapeIndex}`\n\t}\n\n\treturn a11yLive\n}\n\n/** @public */\nexport const useSelectedShapesAnnouncer = () => {\n\tconst editor = useMaybeEditor()\n\tconst a11y = useA11y()\n\tconst msg = useTranslation()\n\n\tconst rPrevSelectedShapeIds = useRef<string[]>([])\n\n\tuseReactor(\n\t\t'announce selection',\n\t\t() => {\n\t\t\tif (!editor) return\n\n\t\t\tconst isInSelecting = editor.isIn('select.idle')\n\t\t\tif (isInSelecting) {\n\t\t\t\tconst selectedShapeIds = editor.getSelectedShapeIds()\n\t\t\t\tif (selectedShapeIds !== rPrevSelectedShapeIds.current) {\n\t\t\t\t\trPrevSelectedShapeIds.current = selectedShapeIds\n\t\t\t\t\tunsafe__withoutCapture(() => {\n\t\t\t\t\t\tconst a11yLive = generateShapeAnnouncementMessage({\n\t\t\t\t\t\t\teditor,\n\t\t\t\t\t\t\tselectedShapeIds,\n\t\t\t\t\t\t\tmsg,\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tif (a11yLive) {\n\t\t\t\t\t\t\ta11y.announce({ msg: a11yLive })\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, a11y, msg]\n\t)\n}\n\nconst useA11yDebug = (msg: string | undefined) => {\n\tconst container = useContainer()\n\n\tuseEffect(() => {\n\t\tif (debugFlags.a11y.get()) {\n\t\t\tconst log = (msg: string) => {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.debug(\n\t\t\t\t\t`%ca11y%c: ${msg}`,\n\t\t\t\t\t`color: white; background: #40C057; padding: 2px;border-radius: 3px;`,\n\t\t\t\t\t'font-weight: normal'\n\t\t\t\t)\n\t\t\t}\n\t\t\tconst handleKeyUp = (e: KeyboardEvent) => {\n\t\t\t\tconst el = document.activeElement\n\t\t\t\tif (\n\t\t\t\t\te.key === 'Tab' &&\n\t\t\t\t\tel &&\n\t\t\t\t\tel !== document.body &&\n\t\t\t\t\t!el.classList.contains('tl-container')\n\t\t\t\t) {\n\t\t\t\t\tconst label = el.getAttribute('aria-label') || el.getAttribute('title') || el.textContent\n\t\t\t\t\tif (label) {\n\t\t\t\t\t\tlog(label)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (msg) {\n\t\t\t\tlog(msg)\n\t\t\t}\n\n\t\t\tdocument.addEventListener('keyup', handleKeyUp)\n\t\t\treturn () => document.removeEventListener('keyup', handleKeyUp)\n\t\t}\n\t}, [container, msg])\n}\n"],
5
+ "mappings": "AA4CE;AA5CF;AAAA,EACC;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,MAAkB,aAAa,WAAW,cAAc;AACjE,SAAS,eAAe;AACxB,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAExB,SAAS,oBAAoB;AACnC,QAAM,SAAS,UAAU;AACzB,QAAM,MAAM,eAAe;AAC3B,QAAM,SAAS,OAA0B,IAAI;AAE7C,QAAM,6BAA6B;AAAA,IAClC,CAAC,MAAkC;AAClC,aAAO,mBAAmB,CAAC;AAC3B,aAAO,SAAS,KAAK;AACrB,YAAM,SAAS,OAAO,mCAAmC;AACzD,UAAI,CAAC,OAAO,OAAQ;AACpB,aAAO,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;AACvC,aAAO,2BAA2B,KAAK;AAAA,QACtC,WAAW;AAAA,UACV,UAAU,OAAO,QAAQ;AAAA,QAC1B;AAAA,QACA,OAAO;AAAA,MACR,CAAC;AAID,aAAO,OAAO,WAAW,MAAM,OAAO,aAAa,EAAE,MAAM,GAAG,GAAG;AAAA,IAClE;AAAA,IACA,CAAC,MAAM;AAAA,EACR;AAEA,SACC;AAAA,IAAC;AAAA;AAAA,MACA,KAAK;AAAA,MACL,MAAK;AAAA,MACL,UAAU;AAAA,MACV,WAAU;AAAA,MACV,SAAS;AAAA,MAER,cAAI,2BAA2B;AAAA;AAAA,EACjC;AAEF;AAGO,MAAM,uBAAuB,KAAK,SAAS,wBAAwB;AACzE,QAAM,OAAO,QAAQ;AACrB,QAAM,cAAc,eAAe;AACnC,QAAM,MAAM,SAAS,YAAY,MAAM,KAAK,WAAW,IAAI,GAAG,CAAC,CAAC;AAChE,eAAa,IAAI,GAAG;AAEpB,6BAA2B;AAE3B,SACC,IAAI,OACH;AAAA,IAAC;AAAA;AAAA,MACA,cAAY,YAAY,aAAa;AAAA,MACrC,aAAW,IAAI,YAAY;AAAA,MAC3B,MAAK;AAAA,MACL,eAAY;AAAA,MACZ,OAAO;AAAA,QACN,UAAU;AAAA,QACV,KAAK;AAAA,QACL,MAAM;AAAA,MACP;AAAA,MAEC,cAAI;AAAA;AAAA,EACN;AAGH,CAAC;AAMM,SAAS,iCAAiC,MAI9C;AACF,QAAM,EAAE,QAAQ,kBAAkB,IAAI,IAAI;AAC1C,MAAI,WAAW;AACf,QAAM,YAAY,iBAAiB;AAEnC,MAAI,YAAY,GAAG;AAClB,eAAW,IAAI,sBAAsB,EAAE,QAAQ,SAAS,UAAU,SAAS,CAAC;AAAA,EAC7E,WAAW,cAAc,GAAG;AAC3B,UAAM,UAAU,iBAAiB,CAAC;AAClC,UAAM,QAAQ,OAAO,SAAS,OAAO;AACrC,QAAI,CAAC,MAAO,QAAO;AAEnB,UAAM,YAAY,OAAO,aAAa,MAAM,IAAI;AAEhD,UAAM,UAAU,CAAC,SAAS,OAAO,EAAE,SAAS,MAAM,IAAI;AAEtD,QAAI,YAAY;AAChB,QAAI,MAAM,SAAS,OAAO;AACzB,kBAAY,IAAI,aAAc,MAAqB,MAAM,GAAG,EAAE;AAAA,IAC/D,WAAW,SAAS;AACnB,kBAAY,IAAI,cAAc,MAAM,IAAI,EAAE;AAAA,IAC3C,OAAO;AACN,kBAAY,IAAI,QAAQ,MAAM,IAAI,EAAE;AAAA,IACrC;AAGA,UAAM,qBAAqB,OAAO,mCAAmC;AACrE,UAAM,qBAAqB,mBAAmB,UAAU,CAAC,MAAM,EAAE,OAAO,OAAO,IAAI,GAAG,SAAS;AAC/F,UAAM,cAAc,mBAAmB,OAAO,SAAS;AACvD,UAAM,aAAa,IAAI,kBAAkB,EACvC,QAAQ,SAAS,iBAAiB,EAClC,QAAQ,WAAW,WAAW;AAGhC,UAAM,iBAAiB,UAAU,kBAAkB,KAAK,KAAK,UAAU,QAAQ,KAAK,KAAK;AAGzF,gBAAY,iBAAiB,GAAG,cAAc,OAAO,MAAM,GAAG,SAAS,KAAK,UAAU;AAAA,EACvF;AAEA,SAAO;AACR;AAGO,MAAM,6BAA6B,MAAM;AAC/C,QAAM,SAAS,eAAe;AAC9B,QAAM,OAAO,QAAQ;AACrB,QAAM,MAAM,eAAe;AAE3B,QAAM,wBAAwB,OAAiB,CAAC,CAAC;AAEjD;AAAA,IACC;AAAA,IACA,MAAM;AACL,UAAI,CAAC,OAAQ;AAEb,YAAM,gBAAgB,OAAO,KAAK,aAAa;AAC/C,UAAI,eAAe;AAClB,cAAM,mBAAmB,OAAO,oBAAoB;AACpD,YAAI,qBAAqB,sBAAsB,SAAS;AACvD,gCAAsB,UAAU;AAChC,iCAAuB,MAAM;AAC5B,kBAAM,WAAW,iCAAiC;AAAA,cACjD;AAAA,cACA;AAAA,cACA;AAAA,YACD,CAAC;AAED,gBAAI,UAAU;AACb,mBAAK,SAAS,EAAE,KAAK,SAAS,CAAC;AAAA,YAChC;AAAA,UACD,CAAC;AAAA,QACF;AAAA,MACD;AAAA,IACD;AAAA,IACA,CAAC,QAAQ,MAAM,GAAG;AAAA,EACnB;AACD;AAEA,MAAM,eAAe,CAAC,QAA4B;AACjD,QAAM,YAAY,aAAa;AAE/B,YAAU,MAAM;AACf,QAAI,WAAW,KAAK,IAAI,GAAG;AAC1B,YAAM,MAAM,CAACA,SAAgB;AAE5B,gBAAQ;AAAA,UACP,aAAaA,IAAG;AAAA,UAChB;AAAA,UACA;AAAA,QACD;AAAA,MACD;AACA,YAAM,cAAc,CAAC,MAAqB;AACzC,cAAM,KAAK,SAAS;AACpB,YACC,EAAE,QAAQ,SACV,MACA,OAAO,SAAS,QAChB,CAAC,GAAG,UAAU,SAAS,cAAc,GACpC;AACD,gBAAM,QAAQ,GAAG,aAAa,YAAY,KAAK,GAAG,aAAa,OAAO,KAAK,GAAG;AAC9E,cAAI,OAAO;AACV,gBAAI,KAAK;AAAA,UACV;AAAA,QACD;AAAA,MACD;AAEA,UAAI,KAAK;AACR,YAAI,GAAG;AAAA,MACR;AAEA,eAAS,iBAAiB,SAAS,WAAW;AAC9C,aAAO,MAAM,SAAS,oBAAoB,SAAS,WAAW;AAAA,IAC/D;AAAA,EACD,GAAG,CAAC,WAAW,GAAG,CAAC;AACpB;",
6
6
  "names": ["msg"]
7
7
  }
@@ -1,8 +1,8 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import {
3
+ ToggleEnhancedA11yModeItem,
3
4
  ToggleKeyboardShortcutsItem,
4
- ToggleReduceMotionItem,
5
- ToggleUiLabelsItem
5
+ ToggleReduceMotionItem
6
6
  } from "./menu-items.mjs";
7
7
  import { TldrawUiMenuGroup } from "./primitives/menus/TldrawUiMenuGroup.mjs";
8
8
  import { TldrawUiMenuSubmenu } from "./primitives/menus/TldrawUiMenuSubmenu.mjs";
@@ -10,7 +10,7 @@ function AccessibilityMenu() {
10
10
  return /* @__PURE__ */ jsx(TldrawUiMenuSubmenu, { id: "help menu accessibility", label: "menu.accessibility", children: /* @__PURE__ */ jsxs(TldrawUiMenuGroup, { id: "accessibility", children: [
11
11
  /* @__PURE__ */ jsx(ToggleReduceMotionItem, {}),
12
12
  /* @__PURE__ */ jsx(ToggleKeyboardShortcutsItem, {}),
13
- /* @__PURE__ */ jsx(ToggleUiLabelsItem, {})
13
+ /* @__PURE__ */ jsx(ToggleEnhancedA11yModeItem, {})
14
14
  ] }) });
15
15
  }
16
16
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/ui/components/AccessibilityMenu.tsx"],
4
- "sourcesContent": ["import {\n\tToggleKeyboardShortcutsItem,\n\tToggleReduceMotionItem,\n\tToggleUiLabelsItem,\n} from './menu-items'\nimport { TldrawUiMenuGroup } from './primitives/menus/TldrawUiMenuGroup'\nimport { TldrawUiMenuSubmenu } from './primitives/menus/TldrawUiMenuSubmenu'\n\n/** @public @react */\nexport function AccessibilityMenu() {\n\treturn (\n\t\t<TldrawUiMenuSubmenu id=\"help menu accessibility\" label=\"menu.accessibility\">\n\t\t\t<TldrawUiMenuGroup id=\"accessibility\">\n\t\t\t\t<ToggleReduceMotionItem />\n\t\t\t\t<ToggleKeyboardShortcutsItem />\n\t\t\t\t<ToggleUiLabelsItem />\n\t\t\t</TldrawUiMenuGroup>\n\t\t</TldrawUiMenuSubmenu>\n\t)\n}\n"],
5
- "mappings": "AAYG,SACC,KADD;AAZH;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AAG7B,SAAS,oBAAoB;AACnC,SACC,oBAAC,uBAAoB,IAAG,2BAA0B,OAAM,sBACvD,+BAAC,qBAAkB,IAAG,iBACrB;AAAA,wBAAC,0BAAuB;AAAA,IACxB,oBAAC,+BAA4B;AAAA,IAC7B,oBAAC,sBAAmB;AAAA,KACrB,GACD;AAEF;",
4
+ "sourcesContent": ["import {\n\tToggleEnhancedA11yModeItem,\n\tToggleKeyboardShortcutsItem,\n\tToggleReduceMotionItem,\n} from './menu-items'\nimport { TldrawUiMenuGroup } from './primitives/menus/TldrawUiMenuGroup'\nimport { TldrawUiMenuSubmenu } from './primitives/menus/TldrawUiMenuSubmenu'\n\n/** @public @react */\nexport function AccessibilityMenu() {\n\treturn (\n\t\t<TldrawUiMenuSubmenu id=\"help menu accessibility\" label=\"menu.accessibility\">\n\t\t\t<TldrawUiMenuGroup id=\"accessibility\">\n\t\t\t\t<ToggleReduceMotionItem />\n\t\t\t\t<ToggleKeyboardShortcutsItem />\n\t\t\t\t<ToggleEnhancedA11yModeItem />\n\t\t\t</TldrawUiMenuGroup>\n\t\t</TldrawUiMenuSubmenu>\n\t)\n}\n"],
5
+ "mappings": "AAYG,SACC,KADD;AAZH;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AAG7B,SAAS,oBAAoB;AACnC,SACC,oBAAC,uBAAoB,IAAG,2BAA0B,OAAM,sBACvD,+BAAC,qBAAkB,IAAG,iBACrB;AAAA,wBAAC,0BAAuB;AAAA,IACxB,oBAAC,+BAA4B;AAAA,IAC7B,oBAAC,8BAA2B;AAAA,KAC7B,GACD;AAEF;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,57 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useEditor, useValue } from "@tldraw/editor";
3
+ import { useUiEvents } from "../context/events.mjs";
4
+ import { TldrawUiMenuCheckboxItem } from "./primitives/menus/TldrawUiMenuCheckboxItem.mjs";
5
+ import { TldrawUiMenuGroup } from "./primitives/menus/TldrawUiMenuGroup.mjs";
6
+ import { TldrawUiMenuSubmenu } from "./primitives/menus/TldrawUiMenuSubmenu.mjs";
7
+ const MODES = ["auto", "trackpad", "mouse"];
8
+ function InputModeMenu() {
9
+ const editor = useEditor();
10
+ const trackEvent = useUiEvents();
11
+ const inputMode = useValue("inputMode", () => editor.user.getUserPreferences().inputMode, [
12
+ editor
13
+ ]);
14
+ const wheelBehavior = useValue("wheelBehavior", () => editor.getCameraOptions().wheelBehavior, [
15
+ editor
16
+ ]);
17
+ const isModeChecked = (mode) => {
18
+ if (mode === "auto") {
19
+ return inputMode === null;
20
+ }
21
+ return inputMode === mode;
22
+ };
23
+ const getLabel = (mode, wheelBehavior2) => {
24
+ if (mode === "auto") {
25
+ return `action.toggle-auto-${wheelBehavior2}`;
26
+ }
27
+ return mode === "trackpad" ? "action.toggle-trackpad" : "action.toggle-mouse";
28
+ };
29
+ return /* @__PURE__ */ jsx(TldrawUiMenuSubmenu, { id: "help menu input-mode", label: "menu.input-mode", children: /* @__PURE__ */ jsx(TldrawUiMenuGroup, { id: "peripheral-mode", children: MODES.map((mode) => /* @__PURE__ */ jsx(
30
+ TldrawUiMenuCheckboxItem,
31
+ {
32
+ id: `peripheral-mode-${mode}`,
33
+ label: getLabel(mode, wheelBehavior),
34
+ checked: isModeChecked(mode),
35
+ readonlyOk: true,
36
+ onSelect: () => {
37
+ trackEvent("input-mode", { source: "menu", value: mode });
38
+ switch (mode) {
39
+ case "auto":
40
+ editor.user.updateUserPreferences({ inputMode: null });
41
+ break;
42
+ case "trackpad":
43
+ editor.user.updateUserPreferences({ inputMode: "trackpad" });
44
+ break;
45
+ case "mouse":
46
+ editor.user.updateUserPreferences({ inputMode: "mouse" });
47
+ break;
48
+ }
49
+ }
50
+ },
51
+ mode
52
+ )) }) });
53
+ }
54
+ export {
55
+ InputModeMenu
56
+ };
57
+ //# sourceMappingURL=InputModeMenu.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/lib/ui/components/InputModeMenu.tsx"],
4
+ "sourcesContent": ["import { useEditor, useValue } from '@tldraw/editor'\nimport { useUiEvents } from '../context/events'\nimport { TldrawUiMenuCheckboxItem } from './primitives/menus/TldrawUiMenuCheckboxItem'\nimport { TldrawUiMenuGroup } from './primitives/menus/TldrawUiMenuGroup'\nimport { TldrawUiMenuSubmenu } from './primitives/menus/TldrawUiMenuSubmenu'\n\nconst MODES = ['auto', 'trackpad', 'mouse'] as const\n\n/** @public @react */\nexport function InputModeMenu() {\n\tconst editor = useEditor()\n\tconst trackEvent = useUiEvents()\n\n\tconst inputMode = useValue('inputMode', () => editor.user.getUserPreferences().inputMode, [\n\t\teditor,\n\t])\n\tconst wheelBehavior = useValue('wheelBehavior', () => editor.getCameraOptions().wheelBehavior, [\n\t\teditor,\n\t])\n\n\tconst isModeChecked = (mode: string) => {\n\t\tif (mode === 'auto') {\n\t\t\treturn inputMode === null\n\t\t}\n\t\treturn inputMode === mode\n\t}\n\n\tconst getLabel = (mode: string, wheelBehavior: 'zoom' | 'pan' | 'none') => {\n\t\tif (mode === 'auto') {\n\t\t\treturn `action.toggle-auto-${wheelBehavior}`\n\t\t}\n\n\t\treturn mode === 'trackpad' ? 'action.toggle-trackpad' : 'action.toggle-mouse'\n\t}\n\n\treturn (\n\t\t<TldrawUiMenuSubmenu id=\"help menu input-mode\" label=\"menu.input-mode\">\n\t\t\t<TldrawUiMenuGroup id=\"peripheral-mode\">\n\t\t\t\t{MODES.map((mode) => (\n\t\t\t\t\t<TldrawUiMenuCheckboxItem\n\t\t\t\t\t\tid={`peripheral-mode-${mode}`}\n\t\t\t\t\t\tkey={mode}\n\t\t\t\t\t\tlabel={getLabel(mode, wheelBehavior)}\n\t\t\t\t\t\tchecked={isModeChecked(mode)}\n\t\t\t\t\t\treadonlyOk\n\t\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t\ttrackEvent('input-mode', { source: 'menu', value: mode })\n\t\t\t\t\t\t\tswitch (mode) {\n\t\t\t\t\t\t\t\tcase 'auto':\n\t\t\t\t\t\t\t\t\teditor.user.updateUserPreferences({ inputMode: null })\n\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\tcase 'trackpad':\n\t\t\t\t\t\t\t\t\teditor.user.updateUserPreferences({ inputMode: 'trackpad' })\n\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t\tcase 'mouse':\n\t\t\t\t\t\t\t\t\teditor.user.updateUserPreferences({ inputMode: 'mouse' })\n\t\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</TldrawUiMenuGroup>\n\t\t</TldrawUiMenuSubmenu>\n\t)\n}\n"],
5
+ "mappings": "AAuCK;AAvCL,SAAS,WAAW,gBAAgB;AACpC,SAAS,mBAAmB;AAC5B,SAAS,gCAAgC;AACzC,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AAEpC,MAAM,QAAQ,CAAC,QAAQ,YAAY,OAAO;AAGnC,SAAS,gBAAgB;AAC/B,QAAM,SAAS,UAAU;AACzB,QAAM,aAAa,YAAY;AAE/B,QAAM,YAAY,SAAS,aAAa,MAAM,OAAO,KAAK,mBAAmB,EAAE,WAAW;AAAA,IACzF;AAAA,EACD,CAAC;AACD,QAAM,gBAAgB,SAAS,iBAAiB,MAAM,OAAO,iBAAiB,EAAE,eAAe;AAAA,IAC9F;AAAA,EACD,CAAC;AAED,QAAM,gBAAgB,CAAC,SAAiB;AACvC,QAAI,SAAS,QAAQ;AACpB,aAAO,cAAc;AAAA,IACtB;AACA,WAAO,cAAc;AAAA,EACtB;AAEA,QAAM,WAAW,CAAC,MAAcA,mBAA2C;AAC1E,QAAI,SAAS,QAAQ;AACpB,aAAO,sBAAsBA,cAAa;AAAA,IAC3C;AAEA,WAAO,SAAS,aAAa,2BAA2B;AAAA,EACzD;AAEA,SACC,oBAAC,uBAAoB,IAAG,wBAAuB,OAAM,mBACpD,8BAAC,qBAAkB,IAAG,mBACpB,gBAAM,IAAI,CAAC,SACX;AAAA,IAAC;AAAA;AAAA,MACA,IAAI,mBAAmB,IAAI;AAAA,MAE3B,OAAO,SAAS,MAAM,aAAa;AAAA,MACnC,SAAS,cAAc,IAAI;AAAA,MAC3B,YAAU;AAAA,MACV,UAAU,MAAM;AACf,mBAAW,cAAc,EAAE,QAAQ,QAAQ,OAAO,KAAK,CAAC;AACxD,gBAAQ,MAAM;AAAA,UACb,KAAK;AACJ,mBAAO,KAAK,sBAAsB,EAAE,WAAW,KAAK,CAAC;AACrD;AAAA,UACD,KAAK;AACJ,mBAAO,KAAK,sBAAsB,EAAE,WAAW,WAAW,CAAC;AAC3D;AAAA,UACD,KAAK;AACJ,mBAAO,KAAK,sBAAsB,EAAE,WAAW,QAAQ,CAAC;AACxD;AAAA,QACF;AAAA,MACD;AAAA;AAAA,IAjBK;AAAA,EAkBN,CACA,GACF,GACD;AAEF;",
6
+ "names": ["wheelBehavior"]
7
+ }
@@ -13,6 +13,7 @@ function LanguageMenu() {
13
13
  TldrawUiMenuCheckboxItem,
14
14
  {
15
15
  id: `language-${locale}`,
16
+ lang: locale,
16
17
  title: locale,
17
18
  label,
18
19
  checked: locale === currentLanguage,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/ui/components/LanguageMenu.tsx"],
4
- "sourcesContent": ["import { LANGUAGES, useMaybeEditor, useValue } from '@tldraw/editor'\nimport { useUiEvents } from '../context/events'\nimport { TldrawUiMenuCheckboxItem } from './primitives/menus/TldrawUiMenuCheckboxItem'\nimport { TldrawUiMenuGroup } from './primitives/menus/TldrawUiMenuGroup'\nimport { TldrawUiMenuSubmenu } from './primitives/menus/TldrawUiMenuSubmenu'\n\n/** @public @react */\nexport function LanguageMenu() {\n\tconst editor = useMaybeEditor()\n\tconst trackEvent = useUiEvents()\n\tconst currentLanguage = useValue('locale', () => editor?.user.getLocale(), [editor])\n\n\tif (!editor) return null\n\n\treturn (\n\t\t<TldrawUiMenuSubmenu id=\"help menu language\" label=\"menu.language\">\n\t\t\t<TldrawUiMenuGroup id=\"languages\" className=\"tlui-language-menu\">\n\t\t\t\t{LANGUAGES.map(({ locale, label }) => (\n\t\t\t\t\t<TldrawUiMenuCheckboxItem\n\t\t\t\t\t\tid={`language-${locale}`}\n\t\t\t\t\t\tkey={locale}\n\t\t\t\t\t\ttitle={locale}\n\t\t\t\t\t\tlabel={label}\n\t\t\t\t\t\tchecked={locale === currentLanguage}\n\t\t\t\t\t\treadonlyOk\n\t\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t\teditor.user.updateUserPreferences({ locale })\n\t\t\t\t\t\t\ttrackEvent('change-language', { source: 'menu', locale })\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</TldrawUiMenuGroup>\n\t\t</TldrawUiMenuSubmenu>\n\t)\n}\n"],
5
- "mappings": "AAkBK;AAlBL,SAAS,WAAW,gBAAgB,gBAAgB;AACpD,SAAS,mBAAmB;AAC5B,SAAS,gCAAgC;AACzC,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AAG7B,SAAS,eAAe;AAC9B,QAAM,SAAS,eAAe;AAC9B,QAAM,aAAa,YAAY;AAC/B,QAAM,kBAAkB,SAAS,UAAU,MAAM,QAAQ,KAAK,UAAU,GAAG,CAAC,MAAM,CAAC;AAEnF,MAAI,CAAC,OAAQ,QAAO;AAEpB,SACC,oBAAC,uBAAoB,IAAG,sBAAqB,OAAM,iBAClD,8BAAC,qBAAkB,IAAG,aAAY,WAAU,sBAC1C,oBAAU,IAAI,CAAC,EAAE,QAAQ,MAAM,MAC/B;AAAA,IAAC;AAAA;AAAA,MACA,IAAI,YAAY,MAAM;AAAA,MAEtB,OAAO;AAAA,MACP;AAAA,MACA,SAAS,WAAW;AAAA,MACpB,YAAU;AAAA,MACV,UAAU,MAAM;AACf,eAAO,KAAK,sBAAsB,EAAE,OAAO,CAAC;AAC5C,mBAAW,mBAAmB,EAAE,QAAQ,QAAQ,OAAO,CAAC;AAAA,MACzD;AAAA;AAAA,IARK;AAAA,EASN,CACA,GACF,GACD;AAEF;",
4
+ "sourcesContent": ["import { LANGUAGES, useMaybeEditor, useValue } from '@tldraw/editor'\nimport { useUiEvents } from '../context/events'\nimport { TldrawUiMenuCheckboxItem } from './primitives/menus/TldrawUiMenuCheckboxItem'\nimport { TldrawUiMenuGroup } from './primitives/menus/TldrawUiMenuGroup'\nimport { TldrawUiMenuSubmenu } from './primitives/menus/TldrawUiMenuSubmenu'\n\n/** @public @react */\nexport function LanguageMenu() {\n\tconst editor = useMaybeEditor()\n\tconst trackEvent = useUiEvents()\n\tconst currentLanguage = useValue('locale', () => editor?.user.getLocale(), [editor])\n\n\tif (!editor) return null\n\n\treturn (\n\t\t<TldrawUiMenuSubmenu id=\"help menu language\" label=\"menu.language\">\n\t\t\t<TldrawUiMenuGroup id=\"languages\" className=\"tlui-language-menu\">\n\t\t\t\t{LANGUAGES.map(({ locale, label }) => (\n\t\t\t\t\t<TldrawUiMenuCheckboxItem\n\t\t\t\t\t\tid={`language-${locale}`}\n\t\t\t\t\t\tlang={locale}\n\t\t\t\t\t\tkey={locale}\n\t\t\t\t\t\ttitle={locale}\n\t\t\t\t\t\tlabel={label}\n\t\t\t\t\t\tchecked={locale === currentLanguage}\n\t\t\t\t\t\treadonlyOk\n\t\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t\teditor.user.updateUserPreferences({ locale })\n\t\t\t\t\t\t\ttrackEvent('change-language', { source: 'menu', locale })\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</TldrawUiMenuGroup>\n\t\t</TldrawUiMenuSubmenu>\n\t)\n}\n"],
5
+ "mappings": "AAkBK;AAlBL,SAAS,WAAW,gBAAgB,gBAAgB;AACpD,SAAS,mBAAmB;AAC5B,SAAS,gCAAgC;AACzC,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AAG7B,SAAS,eAAe;AAC9B,QAAM,SAAS,eAAe;AAC9B,QAAM,aAAa,YAAY;AAC/B,QAAM,kBAAkB,SAAS,UAAU,MAAM,QAAQ,KAAK,UAAU,GAAG,CAAC,MAAM,CAAC;AAEnF,MAAI,CAAC,OAAQ,QAAO;AAEpB,SACC,oBAAC,uBAAoB,IAAG,sBAAqB,OAAM,iBAClD,8BAAC,qBAAkB,IAAG,aAAY,WAAU,sBAC1C,oBAAU,IAAI,CAAC,EAAE,QAAQ,MAAM,MAC/B;AAAA,IAAC;AAAA;AAAA,MACA,IAAI,YAAY,MAAM;AAAA,MACtB,MAAM;AAAA,MAEN,OAAO;AAAA,MACP;AAAA,MACA,SAAS,WAAW;AAAA,MACpB,YAAU;AAAA,MACV,UAAU,MAAM;AACf,eAAO,KAAK,sBAAsB,EAAE,OAAO,CAAC;AAC5C,mBAAW,mBAAmB,EAAE,QAAQ,QAAQ,OAAO,CAAC;AAAA,MACzD;AAAA;AAAA,IARK;AAAA,EASN,CACA,GACF,GACD;AAEF;",
6
6
  "names": []
7
7
  }
@@ -3,6 +3,7 @@ import { useCanRedo, useCanUndo } from "../../hooks/menu-hooks.mjs";
3
3
  import { AccessibilityMenu } from "../AccessibilityMenu.mjs";
4
4
  import { ColorSchemeMenu } from "../ColorSchemeMenu.mjs";
5
5
  import { KeyboardShortcutsMenuItem } from "../HelpMenu/DefaultHelpMenuContent.mjs";
6
+ import { InputModeMenu } from "../InputModeMenu.mjs";
6
7
  import { LanguageMenu } from "../LanguageMenu.mjs";
7
8
  import {
8
9
  ClipboardMenuGroup,
@@ -122,6 +123,7 @@ function PreferencesGroup() {
122
123
  /* @__PURE__ */ jsx(TogglePasteAtCursorItem, {}),
123
124
  /* @__PURE__ */ jsx(ToggleDebugModeItem, {})
124
125
  ] }),
126
+ /* @__PURE__ */ jsx(TldrawUiMenuGroup, { id: "input-mode", children: /* @__PURE__ */ jsx(InputModeMenu, {}) }),
125
127
  /* @__PURE__ */ jsx(TldrawUiMenuGroup, { id: "color-scheme", children: /* @__PURE__ */ jsx(ColorSchemeMenu, {}) }),
126
128
  /* @__PURE__ */ jsx(TldrawUiMenuGroup, { id: "accessibility-menu", children: /* @__PURE__ */ jsx(AccessibilityMenu, {}) })
127
129
  ] }),
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/ui/components/MainMenu/DefaultMainMenuContent.tsx"],
4
- "sourcesContent": ["import { useCanRedo, useCanUndo } from '../../hooks/menu-hooks'\nimport { AccessibilityMenu } from '../AccessibilityMenu'\nimport { ColorSchemeMenu } from '../ColorSchemeMenu'\nimport { KeyboardShortcutsMenuItem } from '../HelpMenu/DefaultHelpMenuContent'\nimport { LanguageMenu } from '../LanguageMenu'\nimport {\n\tClipboardMenuGroup,\n\tConversionsMenuGroup,\n\tConvertToBookmarkMenuItem,\n\tConvertToEmbedMenuItem,\n\tEditLinkMenuItem,\n\tFitFrameToContentMenuItem,\n\tFlattenMenuItem,\n\tGroupMenuItem,\n\tRemoveFrameMenuItem,\n\tSelectAllMenuItem,\n\tToggleAutoSizeMenuItem,\n\tToggleDebugModeItem,\n\tToggleDynamicSizeModeItem,\n\tToggleEdgeScrollingItem,\n\tToggleFocusModeItem,\n\tToggleGridItem,\n\tToggleLockMenuItem,\n\tTogglePasteAtCursorItem,\n\tToggleSnapModeItem,\n\tToggleToolLockItem,\n\tToggleTransparentBgMenuItem,\n\tToggleWrapModeItem,\n\tUngroupMenuItem,\n\tUnlockAllMenuItem,\n\tZoomTo100MenuItem,\n\tZoomToFitMenuItem,\n\tZoomToSelectionMenuItem,\n} from '../menu-items'\nimport { TldrawUiMenuActionItem } from '../primitives/menus/TldrawUiMenuActionItem'\nimport { TldrawUiMenuGroup } from '../primitives/menus/TldrawUiMenuGroup'\nimport { TldrawUiMenuSubmenu } from '../primitives/menus/TldrawUiMenuSubmenu'\n\n/** @public @react */\nexport function DefaultMainMenuContent() {\n\treturn (\n\t\t<>\n\t\t\t<TldrawUiMenuGroup id=\"basic\">\n\t\t\t\t<EditSubmenu />\n\t\t\t\t<ViewSubmenu />\n\t\t\t\t<ExportFileContentSubMenu />\n\t\t\t\t<ExtrasGroup />\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<PreferencesGroup />\n\t\t</>\n\t)\n}\n\n/** @public @react */\nexport function ExportFileContentSubMenu() {\n\treturn (\n\t\t<TldrawUiMenuSubmenu id=\"export-all-as\" label=\"context-menu.export-all-as\" size=\"small\">\n\t\t\t<TldrawUiMenuGroup id=\"export-all-as-group\">\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"export-all-as-svg\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"export-all-as-png\" />\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<TldrawUiMenuGroup id=\"export-all-as-bg\">\n\t\t\t\t<ToggleTransparentBgMenuItem />\n\t\t\t</TldrawUiMenuGroup>\n\t\t</TldrawUiMenuSubmenu>\n\t)\n}\n\n/** @public @react */\nexport function EditSubmenu() {\n\treturn (\n\t\t<TldrawUiMenuSubmenu id=\"edit\" label=\"menu.edit\">\n\t\t\t<UndoRedoGroup />\n\t\t\t<ClipboardMenuGroup />\n\t\t\t<ConversionsMenuGroup />\n\t\t\t<MiscMenuGroup />\n\t\t\t<LockGroup />\n\t\t\t<TldrawUiMenuGroup id=\"select-all\">\n\t\t\t\t<SelectAllMenuItem />\n\t\t\t</TldrawUiMenuGroup>\n\t\t</TldrawUiMenuSubmenu>\n\t)\n}\n\n/** @public @react */\nexport function MiscMenuGroup() {\n\treturn (\n\t\t<TldrawUiMenuGroup id=\"misc\">\n\t\t\t<GroupMenuItem />\n\t\t\t<UngroupMenuItem />\n\t\t\t<EditLinkMenuItem />\n\t\t\t<ToggleAutoSizeMenuItem />\n\t\t\t<RemoveFrameMenuItem />\n\t\t\t<FitFrameToContentMenuItem />\n\t\t\t<ConvertToEmbedMenuItem />\n\t\t\t<ConvertToBookmarkMenuItem />\n\t\t\t<FlattenMenuItem />\n\t\t</TldrawUiMenuGroup>\n\t)\n}\n\n/** @public @react */\nexport function LockGroup() {\n\treturn (\n\t\t<TldrawUiMenuGroup id=\"lock\">\n\t\t\t<ToggleLockMenuItem />\n\t\t\t<UnlockAllMenuItem />\n\t\t</TldrawUiMenuGroup>\n\t)\n}\n\n/** @public @react */\nexport function UndoRedoGroup() {\n\tconst canUndo = useCanUndo()\n\tconst canRedo = useCanRedo()\n\treturn (\n\t\t<TldrawUiMenuGroup id=\"undo-redo\">\n\t\t\t<TldrawUiMenuActionItem actionId=\"undo\" disabled={!canUndo} />\n\t\t\t<TldrawUiMenuActionItem actionId=\"redo\" disabled={!canRedo} />\n\t\t</TldrawUiMenuGroup>\n\t)\n}\n\n/** @public @react */\nexport function ViewSubmenu() {\n\treturn (\n\t\t<TldrawUiMenuSubmenu id=\"view\" label=\"menu.view\">\n\t\t\t<TldrawUiMenuGroup id=\"view-actions\">\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"zoom-in\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"zoom-out\" />\n\t\t\t\t<ZoomTo100MenuItem />\n\t\t\t\t<ZoomToFitMenuItem />\n\t\t\t\t<ZoomToSelectionMenuItem />\n\t\t\t</TldrawUiMenuGroup>\n\t\t</TldrawUiMenuSubmenu>\n\t)\n}\n\n/** @public @react */\nexport function ExtrasGroup() {\n\treturn (\n\t\t<>\n\t\t\t<TldrawUiMenuActionItem actionId=\"insert-embed\" />\n\t\t\t<TldrawUiMenuActionItem actionId=\"insert-media\" />\n\t\t</>\n\t)\n}\n\n/* ------------------- Preferences ------------------ */\n\n/** @public @react */\nexport function PreferencesGroup() {\n\treturn (\n\t\t<TldrawUiMenuGroup id=\"preferences\">\n\t\t\t<TldrawUiMenuSubmenu id=\"preferences\" label=\"menu.preferences\">\n\t\t\t\t<TldrawUiMenuGroup id=\"preferences-actions\">\n\t\t\t\t\t<ToggleSnapModeItem />\n\t\t\t\t\t<ToggleToolLockItem />\n\t\t\t\t\t<ToggleGridItem />\n\t\t\t\t\t<ToggleWrapModeItem />\n\t\t\t\t\t<ToggleFocusModeItem />\n\t\t\t\t\t<ToggleEdgeScrollingItem />\n\t\t\t\t\t<ToggleDynamicSizeModeItem />\n\t\t\t\t\t<TogglePasteAtCursorItem />\n\t\t\t\t\t<ToggleDebugModeItem />\n\t\t\t\t</TldrawUiMenuGroup>\n\t\t\t\t<TldrawUiMenuGroup id=\"color-scheme\">\n\t\t\t\t\t<ColorSchemeMenu />\n\t\t\t\t</TldrawUiMenuGroup>\n\t\t\t\t<TldrawUiMenuGroup id=\"accessibility-menu\">\n\t\t\t\t\t<AccessibilityMenu />\n\t\t\t\t</TldrawUiMenuGroup>\n\t\t\t</TldrawUiMenuSubmenu>\n\t\t\t<LanguageMenu />\n\t\t\t<KeyboardShortcutsMenuItem />\n\t\t</TldrawUiMenuGroup>\n\t)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { useCanRedo, useCanUndo } from '../../hooks/menu-hooks'\nimport { AccessibilityMenu } from '../AccessibilityMenu'\nimport { ColorSchemeMenu } from '../ColorSchemeMenu'\nimport { KeyboardShortcutsMenuItem } from '../HelpMenu/DefaultHelpMenuContent'\nimport { InputModeMenu } from '../InputModeMenu'\nimport { LanguageMenu } from '../LanguageMenu'\nimport {\n\tClipboardMenuGroup,\n\tConversionsMenuGroup,\n\tConvertToBookmarkMenuItem,\n\tConvertToEmbedMenuItem,\n\tEditLinkMenuItem,\n\tFitFrameToContentMenuItem,\n\tFlattenMenuItem,\n\tGroupMenuItem,\n\tRemoveFrameMenuItem,\n\tSelectAllMenuItem,\n\tToggleAutoSizeMenuItem,\n\tToggleDebugModeItem,\n\tToggleDynamicSizeModeItem,\n\tToggleEdgeScrollingItem,\n\tToggleFocusModeItem,\n\tToggleGridItem,\n\tToggleLockMenuItem,\n\tTogglePasteAtCursorItem,\n\tToggleSnapModeItem,\n\tToggleToolLockItem,\n\tToggleTransparentBgMenuItem,\n\tToggleWrapModeItem,\n\tUngroupMenuItem,\n\tUnlockAllMenuItem,\n\tZoomTo100MenuItem,\n\tZoomToFitMenuItem,\n\tZoomToSelectionMenuItem,\n} from '../menu-items'\nimport { TldrawUiMenuActionItem } from '../primitives/menus/TldrawUiMenuActionItem'\nimport { TldrawUiMenuGroup } from '../primitives/menus/TldrawUiMenuGroup'\nimport { TldrawUiMenuSubmenu } from '../primitives/menus/TldrawUiMenuSubmenu'\n\n/** @public @react */\nexport function DefaultMainMenuContent() {\n\treturn (\n\t\t<>\n\t\t\t<TldrawUiMenuGroup id=\"basic\">\n\t\t\t\t<EditSubmenu />\n\t\t\t\t<ViewSubmenu />\n\t\t\t\t<ExportFileContentSubMenu />\n\t\t\t\t<ExtrasGroup />\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<PreferencesGroup />\n\t\t</>\n\t)\n}\n\n/** @public @react */\nexport function ExportFileContentSubMenu() {\n\treturn (\n\t\t<TldrawUiMenuSubmenu id=\"export-all-as\" label=\"context-menu.export-all-as\" size=\"small\">\n\t\t\t<TldrawUiMenuGroup id=\"export-all-as-group\">\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"export-all-as-svg\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"export-all-as-png\" />\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<TldrawUiMenuGroup id=\"export-all-as-bg\">\n\t\t\t\t<ToggleTransparentBgMenuItem />\n\t\t\t</TldrawUiMenuGroup>\n\t\t</TldrawUiMenuSubmenu>\n\t)\n}\n\n/** @public @react */\nexport function EditSubmenu() {\n\treturn (\n\t\t<TldrawUiMenuSubmenu id=\"edit\" label=\"menu.edit\">\n\t\t\t<UndoRedoGroup />\n\t\t\t<ClipboardMenuGroup />\n\t\t\t<ConversionsMenuGroup />\n\t\t\t<MiscMenuGroup />\n\t\t\t<LockGroup />\n\t\t\t<TldrawUiMenuGroup id=\"select-all\">\n\t\t\t\t<SelectAllMenuItem />\n\t\t\t</TldrawUiMenuGroup>\n\t\t</TldrawUiMenuSubmenu>\n\t)\n}\n\n/** @public @react */\nexport function MiscMenuGroup() {\n\treturn (\n\t\t<TldrawUiMenuGroup id=\"misc\">\n\t\t\t<GroupMenuItem />\n\t\t\t<UngroupMenuItem />\n\t\t\t<EditLinkMenuItem />\n\t\t\t<ToggleAutoSizeMenuItem />\n\t\t\t<RemoveFrameMenuItem />\n\t\t\t<FitFrameToContentMenuItem />\n\t\t\t<ConvertToEmbedMenuItem />\n\t\t\t<ConvertToBookmarkMenuItem />\n\t\t\t<FlattenMenuItem />\n\t\t</TldrawUiMenuGroup>\n\t)\n}\n\n/** @public @react */\nexport function LockGroup() {\n\treturn (\n\t\t<TldrawUiMenuGroup id=\"lock\">\n\t\t\t<ToggleLockMenuItem />\n\t\t\t<UnlockAllMenuItem />\n\t\t</TldrawUiMenuGroup>\n\t)\n}\n\n/** @public @react */\nexport function UndoRedoGroup() {\n\tconst canUndo = useCanUndo()\n\tconst canRedo = useCanRedo()\n\treturn (\n\t\t<TldrawUiMenuGroup id=\"undo-redo\">\n\t\t\t<TldrawUiMenuActionItem actionId=\"undo\" disabled={!canUndo} />\n\t\t\t<TldrawUiMenuActionItem actionId=\"redo\" disabled={!canRedo} />\n\t\t</TldrawUiMenuGroup>\n\t)\n}\n\n/** @public @react */\nexport function ViewSubmenu() {\n\treturn (\n\t\t<TldrawUiMenuSubmenu id=\"view\" label=\"menu.view\">\n\t\t\t<TldrawUiMenuGroup id=\"view-actions\">\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"zoom-in\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"zoom-out\" />\n\t\t\t\t<ZoomTo100MenuItem />\n\t\t\t\t<ZoomToFitMenuItem />\n\t\t\t\t<ZoomToSelectionMenuItem />\n\t\t\t</TldrawUiMenuGroup>\n\t\t</TldrawUiMenuSubmenu>\n\t)\n}\n\n/** @public @react */\nexport function ExtrasGroup() {\n\treturn (\n\t\t<>\n\t\t\t<TldrawUiMenuActionItem actionId=\"insert-embed\" />\n\t\t\t<TldrawUiMenuActionItem actionId=\"insert-media\" />\n\t\t</>\n\t)\n}\n\n/* ------------------- Preferences ------------------ */\n\n/** @public @react */\nexport function PreferencesGroup() {\n\treturn (\n\t\t<TldrawUiMenuGroup id=\"preferences\">\n\t\t\t<TldrawUiMenuSubmenu id=\"preferences\" label=\"menu.preferences\">\n\t\t\t\t<TldrawUiMenuGroup id=\"preferences-actions\">\n\t\t\t\t\t<ToggleSnapModeItem />\n\t\t\t\t\t<ToggleToolLockItem />\n\t\t\t\t\t<ToggleGridItem />\n\t\t\t\t\t<ToggleWrapModeItem />\n\t\t\t\t\t<ToggleFocusModeItem />\n\t\t\t\t\t<ToggleEdgeScrollingItem />\n\t\t\t\t\t<ToggleDynamicSizeModeItem />\n\t\t\t\t\t<TogglePasteAtCursorItem />\n\t\t\t\t\t<ToggleDebugModeItem />\n\t\t\t\t</TldrawUiMenuGroup>\n\t\t\t\t<TldrawUiMenuGroup id=\"input-mode\">\n\t\t\t\t\t<InputModeMenu />\n\t\t\t\t</TldrawUiMenuGroup>\n\t\t\t\t<TldrawUiMenuGroup id=\"color-scheme\">\n\t\t\t\t\t<ColorSchemeMenu />\n\t\t\t\t</TldrawUiMenuGroup>\n\t\t\t\t<TldrawUiMenuGroup id=\"accessibility-menu\">\n\t\t\t\t\t<AccessibilityMenu />\n\t\t\t\t</TldrawUiMenuGroup>\n\t\t\t</TldrawUiMenuSubmenu>\n\t\t\t<LanguageMenu />\n\t\t\t<KeyboardShortcutsMenuItem />\n\t\t</TldrawUiMenuGroup>\n\t)\n}\n"],
5
+ "mappings": "AA0CE,mBAEE,KADD,YADD;AA1CF,SAAS,YAAY,kBAAkB;AACvC,SAAS,yBAAyB;AAClC,SAAS,uBAAuB;AAChC,SAAS,iCAAiC;AAC1C,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,8BAA8B;AACvC,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AAG7B,SAAS,yBAAyB;AACxC,SACC,iCACC;AAAA,yBAAC,qBAAkB,IAAG,SACrB;AAAA,0BAAC,eAAY;AAAA,MACb,oBAAC,eAAY;AAAA,MACb,oBAAC,4BAAyB;AAAA,MAC1B,oBAAC,eAAY;AAAA,OACd;AAAA,IACA,oBAAC,oBAAiB;AAAA,KACnB;AAEF;AAGO,SAAS,2BAA2B;AAC1C,SACC,qBAAC,uBAAoB,IAAG,iBAAgB,OAAM,8BAA6B,MAAK,SAC/E;AAAA,yBAAC,qBAAkB,IAAG,uBACrB;AAAA,0BAAC,0BAAuB,UAAS,qBAAoB;AAAA,MACrD,oBAAC,0BAAuB,UAAS,qBAAoB;AAAA,OACtD;AAAA,IACA,oBAAC,qBAAkB,IAAG,oBACrB,8BAAC,+BAA4B,GAC9B;AAAA,KACD;AAEF;AAGO,SAAS,cAAc;AAC7B,SACC,qBAAC,uBAAoB,IAAG,QAAO,OAAM,aACpC;AAAA,wBAAC,iBAAc;AAAA,IACf,oBAAC,sBAAmB;AAAA,IACpB,oBAAC,wBAAqB;AAAA,IACtB,oBAAC,iBAAc;AAAA,IACf,oBAAC,aAAU;AAAA,IACX,oBAAC,qBAAkB,IAAG,cACrB,8BAAC,qBAAkB,GACpB;AAAA,KACD;AAEF;AAGO,SAAS,gBAAgB;AAC/B,SACC,qBAAC,qBAAkB,IAAG,QACrB;AAAA,wBAAC,iBAAc;AAAA,IACf,oBAAC,mBAAgB;AAAA,IACjB,oBAAC,oBAAiB;AAAA,IAClB,oBAAC,0BAAuB;AAAA,IACxB,oBAAC,uBAAoB;AAAA,IACrB,oBAAC,6BAA0B;AAAA,IAC3B,oBAAC,0BAAuB;AAAA,IACxB,oBAAC,6BAA0B;AAAA,IAC3B,oBAAC,mBAAgB;AAAA,KAClB;AAEF;AAGO,SAAS,YAAY;AAC3B,SACC,qBAAC,qBAAkB,IAAG,QACrB;AAAA,wBAAC,sBAAmB;AAAA,IACpB,oBAAC,qBAAkB;AAAA,KACpB;AAEF;AAGO,SAAS,gBAAgB;AAC/B,QAAM,UAAU,WAAW;AAC3B,QAAM,UAAU,WAAW;AAC3B,SACC,qBAAC,qBAAkB,IAAG,aACrB;AAAA,wBAAC,0BAAuB,UAAS,QAAO,UAAU,CAAC,SAAS;AAAA,IAC5D,oBAAC,0BAAuB,UAAS,QAAO,UAAU,CAAC,SAAS;AAAA,KAC7D;AAEF;AAGO,SAAS,cAAc;AAC7B,SACC,oBAAC,uBAAoB,IAAG,QAAO,OAAM,aACpC,+BAAC,qBAAkB,IAAG,gBACrB;AAAA,wBAAC,0BAAuB,UAAS,WAAU;AAAA,IAC3C,oBAAC,0BAAuB,UAAS,YAAW;AAAA,IAC5C,oBAAC,qBAAkB;AAAA,IACnB,oBAAC,qBAAkB;AAAA,IACnB,oBAAC,2BAAwB;AAAA,KAC1B,GACD;AAEF;AAGO,SAAS,cAAc;AAC7B,SACC,iCACC;AAAA,wBAAC,0BAAuB,UAAS,gBAAe;AAAA,IAChD,oBAAC,0BAAuB,UAAS,gBAAe;AAAA,KACjD;AAEF;AAKO,SAAS,mBAAmB;AAClC,SACC,qBAAC,qBAAkB,IAAG,eACrB;AAAA,yBAAC,uBAAoB,IAAG,eAAc,OAAM,oBAC3C;AAAA,2BAAC,qBAAkB,IAAG,uBACrB;AAAA,4BAAC,sBAAmB;AAAA,QACpB,oBAAC,sBAAmB;AAAA,QACpB,oBAAC,kBAAe;AAAA,QAChB,oBAAC,sBAAmB;AAAA,QACpB,oBAAC,uBAAoB;AAAA,QACrB,oBAAC,2BAAwB;AAAA,QACzB,oBAAC,6BAA0B;AAAA,QAC3B,oBAAC,2BAAwB;AAAA,QACzB,oBAAC,uBAAoB;AAAA,SACtB;AAAA,MACA,oBAAC,qBAAkB,IAAG,cACrB,8BAAC,iBAAc,GAChB;AAAA,MACA,oBAAC,qBAAkB,IAAG,gBACrB,8BAAC,mBAAgB,GAClB;AAAA,MACA,oBAAC,qBAAkB,IAAG,sBACrB,8BAAC,qBAAkB,GACpB;AAAA,OACD;AAAA,IACA,oBAAC,gBAAa;AAAA,IACd,oBAAC,6BAA0B;AAAA,KAC5B;AAEF;",
6
6
  "names": []
7
7
  }
@@ -132,7 +132,7 @@ function DefaultMinimap() {
132
132
  type: "pointer",
133
133
  target: "canvas",
134
134
  name: "pointer_move",
135
- ...getPointerInfo(e),
135
+ ...getPointerInfo(editor, e),
136
136
  point: screenPoint,
137
137
  isPen: editor.getInstanceState().isPenMode
138
138
  };
@@ -169,6 +169,7 @@ function DefaultMinimap() {
169
169
  {
170
170
  role: "img",
171
171
  "aria-label": msg("navigation-zone.minimap"),
172
+ "data-testid": "minimap.canvas",
172
173
  ref: rCanvas,
173
174
  className: "tlui-minimap__canvas",
174
175
  onDoubleClick,