tldraw 3.16.0-canary.efdec30fc411 → 3.16.0-canary.f293c3bb58f5

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 (264) hide show
  1. package/dist-cjs/index.d.ts +116 -4
  2. package/dist-cjs/index.js +8 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/canvas/TldrawScribble.js +1 -1
  5. package/dist-cjs/lib/canvas/TldrawScribble.js.map +2 -2
  6. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +3 -3
  7. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  8. package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js +3 -3
  9. package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js.map +1 -1
  10. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +3 -3
  11. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +1 -1
  13. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +1 -1
  14. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +12 -12
  15. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  16. package/dist-cjs/lib/shapes/frame/components/FrameHeading.js +1 -1
  17. package/dist-cjs/lib/shapes/frame/components/FrameHeading.js.map +2 -2
  18. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +2 -2
  19. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  20. package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js +2 -1
  21. package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js.map +2 -2
  22. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +5 -1
  23. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
  24. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -3
  25. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +1 -1
  26. package/dist-cjs/lib/shapes/line/LineShapeUtil.js +5 -1
  27. package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
  28. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +4 -4
  29. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  30. package/dist-cjs/lib/shapes/shared/ShapeFill.js +4 -4
  31. package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
  32. package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
  33. package/dist-cjs/lib/shapes/text/TextShapeUtil.js +2 -2
  34. package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
  35. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +3 -3
  36. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +1 -1
  37. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +25 -1
  38. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  39. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +12 -0
  40. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  41. package/dist-cjs/lib/ui/TldrawUi.js +14 -0
  42. package/dist-cjs/lib/ui/TldrawUi.js.map +3 -3
  43. package/dist-cjs/lib/ui/assetUrls.js +13 -10
  44. package/dist-cjs/lib/ui/assetUrls.js.map +2 -2
  45. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +10 -2
  46. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
  47. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +1 -1
  48. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
  49. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +4 -4
  50. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
  51. package/dist-cjs/lib/ui/components/MobileStylePanel.js +5 -3
  52. package/dist-cjs/lib/ui/components/MobileStylePanel.js.map +2 -2
  53. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js +1 -1
  54. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +2 -2
  55. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +1 -1
  56. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  57. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +66 -22
  58. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js.map +3 -3
  59. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +188 -78
  60. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +3 -3
  61. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js +1 -1
  62. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +2 -2
  63. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +15 -3
  64. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  65. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +146 -168
  66. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  67. package/dist-cjs/lib/ui/components/primitives/layout.js +30 -5
  68. package/dist-cjs/lib/ui/components/primitives/layout.js.map +2 -2
  69. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuContext.js.map +2 -2
  70. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +25 -12
  71. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
  72. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +3 -19
  73. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  74. package/dist-cjs/lib/ui/context/actions.js +16 -2
  75. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  76. package/dist-cjs/lib/ui/hooks/useTools.js +21 -3
  77. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  78. package/dist-cjs/lib/ui/version.js +3 -3
  79. package/dist-cjs/lib/ui/version.js.map +1 -1
  80. package/dist-esm/index.d.mts +116 -4
  81. package/dist-esm/index.mjs +12 -2
  82. package/dist-esm/index.mjs.map +2 -2
  83. package/dist-esm/lib/canvas/TldrawScribble.mjs +1 -1
  84. package/dist-esm/lib/canvas/TldrawScribble.mjs.map +2 -2
  85. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +4 -3
  86. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  87. package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs +3 -3
  88. package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs.map +1 -1
  89. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +4 -3
  90. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
  91. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +1 -1
  92. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +1 -1
  93. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +13 -12
  94. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  95. package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs +1 -1
  96. package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs.map +2 -2
  97. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +3 -2
  98. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  99. package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs +2 -1
  100. package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs.map +2 -2
  101. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +6 -1
  102. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
  103. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -3
  104. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +1 -1
  105. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +6 -1
  106. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
  107. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +5 -4
  108. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  109. package/dist-esm/lib/shapes/shared/ShapeFill.mjs +5 -4
  110. package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
  111. package/dist-esm/lib/shapes/shared/freehand/svg.mjs.map +2 -2
  112. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +3 -2
  113. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
  114. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +3 -3
  115. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +1 -1
  116. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +26 -1
  117. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  118. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +13 -0
  119. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  120. package/dist-esm/lib/ui/TldrawUi.mjs +16 -2
  121. package/dist-esm/lib/ui/TldrawUi.mjs.map +3 -3
  122. package/dist-esm/lib/ui/assetUrls.mjs +13 -10
  123. package/dist-esm/lib/ui/assetUrls.mjs.map +2 -2
  124. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +10 -2
  125. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
  126. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +1 -1
  127. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
  128. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +4 -4
  129. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
  130. package/dist-esm/lib/ui/components/MobileStylePanel.mjs +6 -3
  131. package/dist-esm/lib/ui/components/MobileStylePanel.mjs.map +2 -2
  132. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs +1 -1
  133. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +2 -2
  134. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +1 -1
  135. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  136. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs +56 -22
  137. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs.map +2 -2
  138. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +192 -80
  139. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +3 -3
  140. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +2 -1
  141. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +2 -2
  142. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +16 -4
  143. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  144. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +155 -170
  145. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  146. package/dist-esm/lib/ui/components/primitives/layout.mjs +31 -6
  147. package/dist-esm/lib/ui/components/primitives/layout.mjs.map +2 -2
  148. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuContext.mjs.map +2 -2
  149. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs +25 -12
  150. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
  151. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +3 -19
  152. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  153. package/dist-esm/lib/ui/context/actions.mjs +16 -2
  154. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  155. package/dist-esm/lib/ui/hooks/useTools.mjs +22 -3
  156. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  157. package/dist-esm/lib/ui/version.mjs +3 -3
  158. package/dist-esm/lib/ui/version.mjs.map +1 -1
  159. package/package.json +11 -34
  160. package/src/index.ts +8 -0
  161. package/src/lib/canvas/TldrawScribble.tsx +1 -1
  162. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +2 -1
  163. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +4 -3
  164. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +7 -6
  165. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +4 -3
  166. package/src/lib/shapes/arrow/elbow/ElbowArrowDebug.tsx +3 -3
  167. package/src/lib/shapes/draw/DrawShapeTool.test.ts +0 -5
  168. package/src/lib/shapes/draw/DrawShapeUtil.tsx +4 -3
  169. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
  170. package/src/lib/shapes/frame/FrameShapeUtil.tsx +21 -14
  171. package/src/lib/shapes/frame/components/FrameHeading.tsx +1 -1
  172. package/src/lib/shapes/geo/GeoShapeUtil.tsx +3 -2
  173. package/src/lib/shapes/geo/components/GeoShapeBody.tsx +2 -2
  174. package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +7 -1
  175. package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -3
  176. package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -3
  177. package/src/lib/shapes/line/LineShapeUtil.tsx +6 -1
  178. package/src/lib/shapes/line/__snapshots__/LineShapeUtil.test.tsx.snap +2 -2
  179. package/src/lib/shapes/note/NoteShapeUtil.tsx +9 -4
  180. package/src/lib/shapes/shared/ShapeFill.tsx +5 -4
  181. package/src/lib/shapes/shared/freehand/svg.ts +2 -0
  182. package/src/lib/shapes/text/TextShapeTool.test.ts +6 -5
  183. package/src/lib/shapes/text/TextShapeUtil.tsx +3 -2
  184. package/src/lib/shapes/video/VideoShapeUtil.tsx +3 -3
  185. package/src/lib/tools/EraserTool/childStates/Erasing.ts +34 -1
  186. package/src/lib/tools/EraserTool/childStates/Pointing.ts +20 -0
  187. package/src/lib/ui/TldrawUi.tsx +17 -2
  188. package/src/lib/ui/assetUrls.ts +13 -10
  189. package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +13 -2
  190. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +1 -1
  191. package/src/lib/ui/components/Minimap/MinimapManager.ts +4 -4
  192. package/src/lib/ui/components/MobileStylePanel.tsx +9 -6
  193. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +1 -1
  194. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +1 -1
  195. package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +55 -24
  196. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +208 -56
  197. package/src/lib/ui/components/primitives/TldrawUiButtonPicker.tsx +3 -2
  198. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +22 -5
  199. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +184 -191
  200. package/src/lib/ui/components/primitives/layout.tsx +79 -5
  201. package/src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx +0 -1
  202. package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +29 -16
  203. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +5 -18
  204. package/src/lib/ui/context/actions.tsx +16 -2
  205. package/src/lib/ui/hooks/useTools.tsx +25 -3
  206. package/src/lib/ui/version.ts +3 -3
  207. package/src/lib/ui.css +349 -243
  208. package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +5 -5
  209. package/src/lib/utils/tldr/__snapshots__/buildFromV1Document.test.ts.snap +4 -4
  210. package/src/test/A11y.test.tsx +3 -2
  211. package/src/test/ClickManager.test.ts +7 -6
  212. package/src/test/Editor.test.tsx +20 -19
  213. package/src/test/EraserTool.test.ts +184 -13
  214. package/src/test/HandTool.test.ts +10 -9
  215. package/src/test/HighlightShape.test.ts +2 -1
  216. package/src/test/SelectTool.test.ts +3 -2
  217. package/src/test/TLUserPreferences.test.ts +4 -3
  218. package/src/test/TestEditor.ts +13 -15
  219. package/src/test/TldrawEditor.test.tsx +11 -10
  220. package/src/test/ZoomTool.test.ts +7 -6
  221. package/src/test/__snapshots__/drawing.test.ts.snap +2 -2
  222. package/src/test/__snapshots__/groups.test.tsx.snap +6 -6
  223. package/src/test/__snapshots__/resizing.test.ts.snap +2 -2
  224. package/src/test/arrows-megabus.test.tsx +5 -4
  225. package/src/test/bindings.test.tsx +24 -37
  226. package/src/test/bookmark-shapes.test.ts +1 -8
  227. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +23 -7
  228. package/src/test/commands/__snapshots__/packShapes.test.ts.snap +8 -8
  229. package/src/test/commands/__snapshots__/zoomToFit.test.ts.snap +2 -2
  230. package/src/test/commands/alignShapes.test.tsx +25 -24
  231. package/src/test/commands/animationSpeed.test.ts +2 -1
  232. package/src/test/commands/centerOnPoint.test.ts +3 -2
  233. package/src/test/commands/clipboard.test.ts +3 -2
  234. package/src/test/commands/createShapes.test.ts +2 -1
  235. package/src/test/commands/deleteShapes.test.ts +2 -1
  236. package/src/test/commands/distributeShapes.test.tsx +11 -10
  237. package/src/test/commands/getSvgString.test.ts +2 -1
  238. package/src/test/commands/packShapes.test.ts +5 -4
  239. package/src/test/commands/resizeShape.test.ts +2 -1
  240. package/src/test/commands/rotateShapes.test.ts +7 -6
  241. package/src/test/commands/setCamera.test.ts +4 -3
  242. package/src/test/commands/setCurrentPage.test.ts +3 -2
  243. package/src/test/commands/stackShapes.test.ts +11 -10
  244. package/src/test/commands/stretch.test.tsx +13 -12
  245. package/src/test/createDeepLink.test.tsx +2 -1
  246. package/src/test/cropping.test.ts +3 -2
  247. package/src/test/drawing.test.ts +2 -1
  248. package/src/test/flipShapes.test.ts +4 -3
  249. package/src/test/frames.test.ts +25 -24
  250. package/src/test/getCulledShapes.test.tsx +3 -2
  251. package/src/test/groups.test.tsx +1 -1
  252. package/src/test/handleDeepLink.test.tsx +2 -1
  253. package/src/test/maxShapes.test.ts +3 -2
  254. package/src/test/modifiers.test.ts +5 -4
  255. package/src/test/navigation.test.ts +12 -11
  256. package/src/test/panning.test.ts +2 -1
  257. package/src/test/perf/perf.test.ts +2 -1
  258. package/src/test/registerDeepLinkListener.test.tsx +10 -9
  259. package/src/test/resizing.test.ts +39 -38
  260. package/src/test/select.test.tsx +4 -3
  261. package/src/test/selection-omnibus.test.ts +11 -10
  262. package/src/test/shapeutils.test.ts +4 -3
  263. package/src/test/translating.test.ts +9 -8
  264. package/tldraw.css +642 -533
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/ui/hooks/useTools.tsx"],
4
- "sourcesContent": ["import {\n\tassertExists,\n\tcreateShapeId,\n\tEditor,\n\tGeoShapeGeoStyle,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\ttoRichText,\n\tuseMaybeEditor,\n} from '@tldraw/editor'\nimport * as React from 'react'\nimport { EmbedDialog } from '../components/EmbedDialog'\nimport { TLUiIconJsx } from '../components/primitives/TldrawUiIcon'\nimport { useA11y } from '../context/a11y'\nimport { TLUiEventSource, useUiEvents } from '../context/events'\nimport { TLUiIconType } from '../icon-types'\nimport { TLUiOverrideHelpers, useDefaultHelpers } from '../overrides'\nimport { TLUiTranslationKey } from './useTranslation/TLUiTranslationKey'\nimport { useTranslation } from './useTranslation/useTranslation'\n\n/** @public */\nexport interface TLUiToolItem<\n\tTranslationKey extends string = string,\n\tIconType extends string = string,\n> {\n\tid: string\n\tlabel: TranslationKey\n\tshortcutsLabel?: TranslationKey\n\ticon: IconType | TLUiIconJsx\n\tonSelect(source: TLUiEventSource): void\n\tonDragStart?(source: TLUiEventSource, info: TLPointerEventInfo): void\n\t/**\n\t * The keyboard shortcut for this tool. This is a string that can be a single key,\n\t * or a combination of keys.\n\t * For example, `cmd+z` or `cmd+shift+z` or `cmd+u,ctrl+u`, or just `v` or `a`.\n\t * We have backwards compatibility with the old system, where we used to use\n\t * symbols to denote cmd/alt/shift, using `!` for shift, `$` for cmd, and `?` for alt.\n\t */\n\tkbd?: string\n\treadonlyOk?: boolean\n\tmeta?: {\n\t\t[key: string]: any\n\t}\n}\n\n/** @public */\nexport type TLUiToolsContextType = Record<string, TLUiToolItem>\n\n/** @internal */\nexport const ToolsContext = React.createContext<null | TLUiToolsContextType>(null)\n\n/** @public */\nexport interface TLUiToolsProviderProps {\n\toverrides?(\n\t\teditor: Editor,\n\t\ttools: TLUiToolsContextType,\n\t\thelpers: Partial<TLUiOverrideHelpers>\n\t): TLUiToolsContextType\n\tchildren: React.ReactNode\n}\n\n/** @internal */\nexport function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {\n\tconst editor = useMaybeEditor()\n\tconst trackEvent = useUiEvents()\n\n\tconst a11y = useA11y()\n\tconst msg = useTranslation()\n\tconst helpers = useDefaultHelpers()\n\n\tconst onToolSelect = React.useCallback(\n\t\t(\n\t\t\tsource: TLUiEventSource,\n\t\t\ttool: TLUiToolItem<TLUiTranslationKey, TLUiIconType>,\n\t\t\tid?: string\n\t\t) => {\n\t\t\ta11y.announce({ msg: msg(tool.label) })\n\t\t\ttrackEvent('select-tool', { source, id: id ?? tool.id })\n\t\t},\n\t\t[a11y, msg, trackEvent]\n\t)\n\n\tconst tools = React.useMemo<TLUiToolsContextType>(() => {\n\t\tif (!editor) return {}\n\t\tconst toolsArray: TLUiToolItem<TLUiTranslationKey, TLUiIconType>[] = [\n\t\t\t{\n\t\t\t\tid: 'select',\n\t\t\t\tlabel: 'tool.select',\n\t\t\t\ticon: 'tool-pointer',\n\t\t\t\tkbd: 'v',\n\t\t\t\treadonlyOk: true,\n\t\t\t\tonSelect(source) {\n\t\t\t\t\tif (editor.isIn('select')) {\n\t\t\t\t\t\t// There's a quirk of select mode, where editing a shape is a sub-state of select.\n\t\t\t\t\t\t// Because the text tool can be locked/sticky, we need to make sure we exit the\n\t\t\t\t\t\t// text tool.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// psst, if you're changing this code, also change the code\n\t\t\t\t\t\t// in strange-tools.test.ts! Sadly it's duplicated there.\n\t\t\t\t\t\tconst currentNode = editor.root.getCurrent()!\n\t\t\t\t\t\tcurrentNode.exit({}, currentNode.id)\n\t\t\t\t\t\tcurrentNode.enter({}, currentNode.id)\n\t\t\t\t\t}\n\t\t\t\t\teditor.setCurrentTool('select')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'hand',\n\t\t\t\tlabel: 'tool.hand',\n\t\t\t\ticon: 'tool-hand',\n\t\t\t\tkbd: 'h',\n\t\t\t\treadonlyOk: true,\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('hand')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'eraser',\n\t\t\t\tlabel: 'tool.eraser',\n\t\t\t\ticon: 'tool-eraser',\n\t\t\t\tkbd: 'e',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('eraser')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'draw',\n\t\t\t\tlabel: 'tool.draw',\n\t\t\t\ticon: 'tool-pencil',\n\t\t\t\tkbd: 'd,b,x',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('draw')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t...[...GeoShapeGeoStyle.values].map((geo) => ({\n\t\t\t\tid: geo,\n\t\t\t\tlabel: `tool.${geo}` as TLUiTranslationKey,\n\t\t\t\tmeta: {\n\t\t\t\t\tgeo,\n\t\t\t\t},\n\t\t\t\tkbd: geo === 'rectangle' ? 'r' : geo === 'ellipse' ? 'o' : undefined,\n\t\t\t\ticon: ('geo-' + geo) as TLUiIconType,\n\t\t\t\tonSelect(source: TLUiEventSource) {\n\t\t\t\t\teditor.run(() => {\n\t\t\t\t\t\teditor.setStyleForNextShapes(GeoShapeGeoStyle, geo)\n\t\t\t\t\t\teditor.setCurrentTool('geo')\n\t\t\t\t\t\tonToolSelect(source, this, `geo-${geo}`)\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tonDragStart(source: TLUiEventSource, info: TLPointerEventInfo) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) => editor.createShape({ id, type: 'geo', props: { geo } }),\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'geo' })\n\t\t\t\t},\n\t\t\t})),\n\t\t\t{\n\t\t\t\tid: 'arrow',\n\t\t\t\tlabel: 'tool.arrow',\n\t\t\t\ticon: 'tool-arrow',\n\t\t\t\tkbd: 'a',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('arrow')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t\tonDragStart(source: TLUiEventSource, info: TLPointerEventInfo) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) =>\n\t\t\t\t\t\t\teditor.createShape({\n\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\ttype: 'arrow',\n\t\t\t\t\t\t\t\tprops: { start: { x: 0, y: 0 }, end: { x: 200, y: 0 } },\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'arrow' })\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'line',\n\t\t\t\tlabel: 'tool.line',\n\t\t\t\ticon: 'tool-line',\n\t\t\t\tkbd: 'l',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('line')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'frame',\n\t\t\t\tlabel: 'tool.frame',\n\t\t\t\ticon: 'tool-frame',\n\t\t\t\tkbd: 'f',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('frame')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t\tonDragStart(source, info) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) => editor.createShape({ id, type: 'frame' }),\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'frame' })\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'text',\n\t\t\t\tlabel: 'tool.text',\n\t\t\t\ticon: 'tool-text',\n\t\t\t\tkbd: 't',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('text')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t\tonDragStart(source, info) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) =>\n\t\t\t\t\t\t\teditor.createShape({ id, type: 'text', props: { richText: toRichText('Text') } }),\n\t\t\t\t\t\tonDragEnd: (id) => {\n\t\t\t\t\t\t\teditor.emit('select-all-text', { shapeId: id })\n\t\t\t\t\t\t\teditor.setEditingShape(id)\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'text' })\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'asset',\n\t\t\t\tlabel: 'tool.media',\n\t\t\t\ticon: 'tool-media',\n\t\t\t\tkbd: 'cmd+u,ctrl+u',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\thelpers.insertMedia()\n\t\t\t\t\tonToolSelect(source, this, 'media')\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'note',\n\t\t\t\tlabel: 'tool.note',\n\t\t\t\ticon: 'tool-note',\n\t\t\t\tkbd: 'n',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('note')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t\tonDragStart(source, info) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) => editor.createShape({ id, type: 'note' }),\n\t\t\t\t\t\tonDragEnd: (id) => {\n\t\t\t\t\t\t\teditor.emit('select-all-text', { shapeId: id })\n\t\t\t\t\t\t\teditor.setEditingShape(id)\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'note' })\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'laser',\n\t\t\t\tlabel: 'tool.laser',\n\t\t\t\treadonlyOk: true,\n\t\t\t\ticon: 'tool-laser',\n\t\t\t\tkbd: 'k',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('laser')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'embed',\n\t\t\t\tlabel: 'tool.embed',\n\t\t\t\ticon: 'dot',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\thelpers.addDialog({ component: EmbedDialog })\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'highlight',\n\t\t\t\tlabel: 'tool.highlight',\n\t\t\t\ticon: 'tool-highlight',\n\t\t\t\t// TODO: pick a better shortcut\n\t\t\t\tkbd: 'shift+d',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('highlight')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t]\n\n\t\ttoolsArray.forEach((t) => (t.onSelect = t.onSelect.bind(t)))\n\n\t\tconst tools = Object.fromEntries(toolsArray.map((t) => [t.id, t]))\n\n\t\tif (overrides) {\n\t\t\treturn overrides(editor, tools, helpers)\n\t\t}\n\n\t\treturn tools\n\t}, [overrides, editor, helpers, onToolSelect, trackEvent])\n\n\treturn <ToolsContext.Provider value={tools}>{children}</ToolsContext.Provider>\n}\n\n/** @public */\nexport function useTools() {\n\tconst ctx = React.useContext(ToolsContext)\n\n\tif (!ctx) {\n\t\tthrow new Error('useTools must be used within a ToolProvider')\n\t}\n\n\treturn ctx\n}\n\n/**\n * Options for {@link onDragFromToolbarToCreateShape}.\n * @public\n */\nexport interface OnDragFromToolbarToCreateShapesOpts {\n\t/**\n\t * Create the shape being dragged. You don't need to worry about positioning it, as it'll be\n\t * immediately updated with the correct position.\n\t */\n\tcreateShape(id: TLShapeId): void\n\t/**\n\t * Called once the drag interaction has finished.\n\t */\n\tonDragEnd?(id: TLShapeId): void\n}\n\n/**\n * A helper method to use in {@link TLUiToolItem#onDragStart} to create a shape by dragging it from\n * the toolbar.\n * @public\n */\nexport function onDragFromToolbarToCreateShape(\n\teditor: Editor,\n\tinfo: TLPointerEventInfo,\n\topts: OnDragFromToolbarToCreateShapesOpts\n) {\n\tconst { x, y } = editor.inputs.currentPagePoint\n\n\tconst stoppingPoint = editor.markHistoryStoppingPoint('drag shape tool')\n\teditor.setCurrentTool('select.translating')\n\n\tconst id = createShapeId()\n\topts.createShape(id)\n\tconst shape = assertExists(editor.getShape(id), 'Shape not found')\n\n\tconst { w, h } = editor.getShapePageBounds(id)!\n\teditor.updateShape({ id, type: shape.type, x: x - w / 2, y: y - h / 2 })\n\teditor.select(id)\n\n\teditor.setCurrentTool('select.translating', {\n\t\t...info,\n\t\ttarget: 'shape',\n\t\tshape: editor.getShape(id),\n\t\tisCreating: true,\n\t\tcreatingMarkId: stoppingPoint,\n\t\tonCreate() {\n\t\t\teditor.setCurrentTool('select.idle')\n\t\t\teditor.select(id)\n\t\t\topts.onDragEnd?.(id)\n\t\t},\n\t})\n\teditor.getCurrentTool().setCurrentToolIdMask(shape.type)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tassertExists,\n\tcreateShapeId,\n\tEditor,\n\tGeoShapeGeoStyle,\n\tgetIndicesBetween,\n\tTLLineShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\ttoRichText,\n\tuseMaybeEditor,\n} from '@tldraw/editor'\nimport * as React from 'react'\nimport { EmbedDialog } from '../components/EmbedDialog'\nimport { TLUiIconJsx } from '../components/primitives/TldrawUiIcon'\nimport { useA11y } from '../context/a11y'\nimport { TLUiEventSource, useUiEvents } from '../context/events'\nimport { TLUiIconType } from '../icon-types'\nimport { TLUiOverrideHelpers, useDefaultHelpers } from '../overrides'\nimport { TLUiTranslationKey } from './useTranslation/TLUiTranslationKey'\nimport { useTranslation } from './useTranslation/useTranslation'\n\n/** @public */\nexport interface TLUiToolItem<\n\tTranslationKey extends string = string,\n\tIconType extends string = string,\n> {\n\tid: string\n\tlabel: TranslationKey\n\tshortcutsLabel?: TranslationKey\n\ticon: IconType | TLUiIconJsx\n\tonSelect(source: TLUiEventSource): void\n\tonDragStart?(source: TLUiEventSource, info: TLPointerEventInfo): void\n\t/**\n\t * The keyboard shortcut for this tool. This is a string that can be a single key,\n\t * or a combination of keys.\n\t * For example, `cmd+z` or `cmd+shift+z` or `cmd+u,ctrl+u`, or just `v` or `a`.\n\t * We have backwards compatibility with the old system, where we used to use\n\t * symbols to denote cmd/alt/shift, using `!` for shift, `$` for cmd, and `?` for alt.\n\t */\n\tkbd?: string\n\treadonlyOk?: boolean\n\tmeta?: {\n\t\t[key: string]: any\n\t}\n}\n\n/** @public */\nexport type TLUiToolsContextType = Record<string, TLUiToolItem>\n\n/** @internal */\nexport const ToolsContext = React.createContext<null | TLUiToolsContextType>(null)\n\n/** @public */\nexport interface TLUiToolsProviderProps {\n\toverrides?(\n\t\teditor: Editor,\n\t\ttools: TLUiToolsContextType,\n\t\thelpers: Partial<TLUiOverrideHelpers>\n\t): TLUiToolsContextType\n\tchildren: React.ReactNode\n}\n\n/** @internal */\nexport function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {\n\tconst editor = useMaybeEditor()\n\tconst trackEvent = useUiEvents()\n\n\tconst a11y = useA11y()\n\tconst msg = useTranslation()\n\tconst helpers = useDefaultHelpers()\n\n\tconst onToolSelect = React.useCallback(\n\t\t(\n\t\t\tsource: TLUiEventSource,\n\t\t\ttool: TLUiToolItem<TLUiTranslationKey, TLUiIconType>,\n\t\t\tid?: string\n\t\t) => {\n\t\t\ta11y.announce({ msg: msg(tool.label) })\n\t\t\ttrackEvent('select-tool', { source, id: id ?? tool.id })\n\t\t},\n\t\t[a11y, msg, trackEvent]\n\t)\n\n\tconst tools = React.useMemo<TLUiToolsContextType>(() => {\n\t\tif (!editor) return {}\n\t\tconst toolsArray: TLUiToolItem<TLUiTranslationKey, TLUiIconType>[] = [\n\t\t\t{\n\t\t\t\tid: 'select',\n\t\t\t\tlabel: 'tool.select',\n\t\t\t\ticon: 'tool-pointer',\n\t\t\t\tkbd: 'v',\n\t\t\t\treadonlyOk: true,\n\t\t\t\tonSelect(source) {\n\t\t\t\t\tif (editor.isIn('select')) {\n\t\t\t\t\t\t// There's a quirk of select mode, where editing a shape is a sub-state of select.\n\t\t\t\t\t\t// Because the text tool can be locked/sticky, we need to make sure we exit the\n\t\t\t\t\t\t// text tool.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// psst, if you're changing this code, also change the code\n\t\t\t\t\t\t// in strange-tools.test.ts! Sadly it's duplicated there.\n\t\t\t\t\t\tconst currentNode = editor.root.getCurrent()!\n\t\t\t\t\t\tcurrentNode.exit({}, currentNode.id)\n\t\t\t\t\t\tcurrentNode.enter({}, currentNode.id)\n\t\t\t\t\t}\n\t\t\t\t\teditor.setCurrentTool('select')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'hand',\n\t\t\t\tlabel: 'tool.hand',\n\t\t\t\ticon: 'tool-hand',\n\t\t\t\tkbd: 'h',\n\t\t\t\treadonlyOk: true,\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('hand')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'eraser',\n\t\t\t\tlabel: 'tool.eraser',\n\t\t\t\ticon: 'tool-eraser',\n\t\t\t\tkbd: 'e',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('eraser')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'draw',\n\t\t\t\tlabel: 'tool.draw',\n\t\t\t\ticon: 'tool-pencil',\n\t\t\t\tkbd: 'd,b,x',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('draw')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t...[...GeoShapeGeoStyle.values].map((geo) => ({\n\t\t\t\tid: geo,\n\t\t\t\tlabel: `tool.${geo}` as TLUiTranslationKey,\n\t\t\t\tmeta: {\n\t\t\t\t\tgeo,\n\t\t\t\t},\n\t\t\t\tkbd: geo === 'rectangle' ? 'r' : geo === 'ellipse' ? 'o' : undefined,\n\t\t\t\ticon: ('geo-' + geo) as TLUiIconType,\n\t\t\t\tonSelect(source: TLUiEventSource) {\n\t\t\t\t\teditor.run(() => {\n\t\t\t\t\t\teditor.setStyleForNextShapes(GeoShapeGeoStyle, geo)\n\t\t\t\t\t\teditor.setCurrentTool('geo')\n\t\t\t\t\t\tonToolSelect(source, this, `geo-${geo}`)\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tonDragStart(source: TLUiEventSource, info: TLPointerEventInfo) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) =>\n\t\t\t\t\t\t\teditor.createShape({ id, type: 'geo', props: { w: 200, h: 200, geo } }),\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'geo' })\n\t\t\t\t},\n\t\t\t})),\n\t\t\t{\n\t\t\t\tid: 'arrow',\n\t\t\t\tlabel: 'tool.arrow',\n\t\t\t\ticon: 'tool-arrow',\n\t\t\t\tkbd: 'a',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('arrow')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t\tonDragStart(source: TLUiEventSource, info: TLPointerEventInfo) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) =>\n\t\t\t\t\t\t\teditor.createShape({\n\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\ttype: 'arrow',\n\t\t\t\t\t\t\t\tprops: { start: { x: 0, y: 0 }, end: { x: 200, y: 0 } },\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'arrow' })\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'line',\n\t\t\t\tlabel: 'tool.line',\n\t\t\t\ticon: 'tool-line',\n\t\t\t\tkbd: 'l',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('line')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t\tonDragStart(source, info) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) => {\n\t\t\t\t\t\t\tconst [start, end] = getIndicesBetween(null, null, 2)\n\t\t\t\t\t\t\teditor.createShape<TLLineShape>({\n\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\ttype: 'line',\n\t\t\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\t\t\tpoints: {\n\t\t\t\t\t\t\t\t\t\t[start]: { id: start, index: start, x: 0, y: 200 },\n\t\t\t\t\t\t\t\t\t\t[end]: { id: end, index: end, x: 200, y: 0 },\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\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\ttrackEvent('drag-tool', { source, id: 'line' })\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'frame',\n\t\t\t\tlabel: 'tool.frame',\n\t\t\t\ticon: 'tool-frame',\n\t\t\t\tkbd: 'f',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('frame')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t\tonDragStart(source, info) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) => editor.createShape({ id, type: 'frame' }),\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'frame' })\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'text',\n\t\t\t\tlabel: 'tool.text',\n\t\t\t\ticon: 'tool-text',\n\t\t\t\tkbd: 't',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('text')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t\tonDragStart(source, info) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) =>\n\t\t\t\t\t\t\teditor.createShape({ id, type: 'text', props: { richText: toRichText('Text') } }),\n\t\t\t\t\t\tonDragEnd: (id) => {\n\t\t\t\t\t\t\teditor.setEditingShape(id)\n\t\t\t\t\t\t\teditor.emit('select-all-text', { shapeId: id })\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'text' })\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'asset',\n\t\t\t\tlabel: 'tool.media',\n\t\t\t\ticon: 'tool-media',\n\t\t\t\tkbd: 'cmd+u,ctrl+u',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\thelpers.insertMedia()\n\t\t\t\t\tonToolSelect(source, this, 'media')\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'note',\n\t\t\t\tlabel: 'tool.note',\n\t\t\t\ticon: 'tool-note',\n\t\t\t\tkbd: 'n',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('note')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t\tonDragStart(source, info) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) => editor.createShape({ id, type: 'note' }),\n\t\t\t\t\t\tonDragEnd: (id) => {\n\t\t\t\t\t\t\teditor.setEditingShape(id)\n\t\t\t\t\t\t\teditor.emit('select-all-text', { shapeId: id })\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'note' })\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'laser',\n\t\t\t\tlabel: 'tool.laser',\n\t\t\t\treadonlyOk: true,\n\t\t\t\ticon: 'tool-laser',\n\t\t\t\tkbd: 'k',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('laser')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'embed',\n\t\t\t\tlabel: 'tool.embed',\n\t\t\t\ticon: 'dot',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\thelpers.addDialog({ component: EmbedDialog })\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'highlight',\n\t\t\t\tlabel: 'tool.highlight',\n\t\t\t\ticon: 'tool-highlight',\n\t\t\t\t// TODO: pick a better shortcut\n\t\t\t\tkbd: 'shift+d',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('highlight')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t]\n\n\t\ttoolsArray.forEach((t) => (t.onSelect = t.onSelect.bind(t)))\n\n\t\tconst tools = Object.fromEntries(toolsArray.map((t) => [t.id, t]))\n\n\t\tif (overrides) {\n\t\t\treturn overrides(editor, tools, helpers)\n\t\t}\n\n\t\treturn tools\n\t}, [overrides, editor, helpers, onToolSelect, trackEvent])\n\n\treturn <ToolsContext.Provider value={tools}>{children}</ToolsContext.Provider>\n}\n\n/** @public */\nexport function useTools() {\n\tconst ctx = React.useContext(ToolsContext)\n\n\tif (!ctx) {\n\t\tthrow new Error('useTools must be used within a ToolProvider')\n\t}\n\n\treturn ctx\n}\n\n/**\n * Options for {@link onDragFromToolbarToCreateShape}.\n * @public\n */\nexport interface OnDragFromToolbarToCreateShapesOpts {\n\t/**\n\t * Create the shape being dragged. You don't need to worry about positioning it, as it'll be\n\t * immediately updated with the correct position.\n\t */\n\tcreateShape(id: TLShapeId): void\n\t/**\n\t * Called once the drag interaction has finished.\n\t */\n\tonDragEnd?(id: TLShapeId): void\n}\n\n/**\n * A helper method to use in {@link TLUiToolItem#onDragStart} to create a shape by dragging it from\n * the toolbar.\n * @public\n */\nexport function onDragFromToolbarToCreateShape(\n\teditor: Editor,\n\tinfo: TLPointerEventInfo,\n\topts: OnDragFromToolbarToCreateShapesOpts\n) {\n\tconst { x, y } = editor.inputs.currentPagePoint\n\n\tconst stoppingPoint = editor.markHistoryStoppingPoint('drag shape tool')\n\teditor.setCurrentTool('select.translating')\n\n\tconst id = createShapeId()\n\topts.createShape(id)\n\tconst shape = assertExists(editor.getShape(id), 'Shape not found')\n\n\tconst { w, h } = editor.getShapePageBounds(id)!\n\teditor.updateShape({ id, type: shape.type, x: x - w / 2, y: y - h / 2 })\n\teditor.select(id)\n\n\teditor.setCurrentTool('select.translating', {\n\t\t...info,\n\t\ttarget: 'shape',\n\t\tshape: editor.getShape(id),\n\t\tisCreating: true,\n\t\tcreatingMarkId: stoppingPoint,\n\t\tonCreate() {\n\t\t\teditor.setCurrentTool('select.idle')\n\t\t\teditor.select(id)\n\t\t\topts.onDragEnd?.(id)\n\t\t},\n\t})\n\n\teditor.getCurrentTool().setCurrentToolIdMask(shape.type)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["tools"]
7
7
  }
@@ -1,8 +1,8 @@
1
- const version = "3.16.0-canary.efdec30fc411";
1
+ const version = "3.16.0-canary.f293c3bb58f5";
2
2
  const publishDates = {
3
3
  major: "2024-09-13T14:36:29.063Z",
4
- minor: "2025-08-08T14:53:46.305Z",
5
- patch: "2025-08-08T14:53:46.305Z"
4
+ minor: "2025-08-21T12:41:23.735Z",
5
+ patch: "2025-08-21T12:41:23.735Z"
6
6
  };
7
7
  export {
8
8
  publishDates,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/ui/version.ts"],
4
- "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.16.0-canary.efdec30fc411'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-08-08T14:53:46.305Z',\n\tpatch: '2025-08-08T14:53:46.305Z',\n}\n"],
4
+ "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.16.0-canary.f293c3bb58f5'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-08-21T12:41:23.735Z',\n\tpatch: '2025-08-21T12:41:23.735Z',\n}\n"],
5
5
  "mappings": "AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tldraw",
3
3
  "description": "A tiny little drawing editor.",
4
- "version": "3.16.0-canary.efdec30fc411",
4
+ "version": "3.16.0-canary.f293c3bb58f5",
5
5
  "author": {
6
6
  "name": "tldraw Inc.",
7
7
  "email": "hello@tldraw.com"
@@ -27,9 +27,9 @@
27
27
  ],
28
28
  "main": "dist-cjs/index.js",
29
29
  "scripts": {
30
- "test-ci": "lazy inherit",
31
- "test": "yarn run -T jest",
32
- "test-coverage": "lazy inherit",
30
+ "test-ci": "yarn run -T vitest run --passWithNoTests",
31
+ "test": "yarn run -T vitest --passWithNoTests",
32
+ "test-coverage": "yarn run -T vitest run --coverage --passWithNoTests",
33
33
  "predev": "node ./scripts/copy-css-files.mjs",
34
34
  "dev": "chokidar '../{editor/editor,tldraw/src/lib/ui}.css' -c 'node ./scripts/copy-css-files.mjs'",
35
35
  "prebuild": "node ./scripts/copy-css-files.mjs",
@@ -38,7 +38,8 @@
38
38
  "prepack": "yarn run -T tsx ../../internal/scripts/prepack.ts",
39
39
  "postpack": "../../internal/scripts/postpack.sh",
40
40
  "pack-tarball": "yarn pack",
41
- "lint": "yarn run -T tsx ../../internal/scripts/lint.ts"
41
+ "lint": "yarn run -T tsx ../../internal/scripts/lint.ts",
42
+ "context": "yarn run -T tsx ../../internal/scripts/context.ts"
42
43
  },
43
44
  "files": [
44
45
  "tldraw.css",
@@ -54,13 +55,13 @@
54
55
  "@tiptap/pm": "^2.9.1",
55
56
  "@tiptap/react": "^2.9.1",
56
57
  "@tiptap/starter-kit": "^2.9.1",
57
- "@tldraw/editor": "3.16.0-canary.efdec30fc411",
58
- "@tldraw/store": "3.16.0-canary.efdec30fc411",
58
+ "@tldraw/editor": "3.16.0-canary.f293c3bb58f5",
59
+ "@tldraw/store": "3.16.0-canary.f293c3bb58f5",
59
60
  "classnames": "^2.5.1",
60
61
  "hotkeys-js": "^3.13.9",
61
62
  "idb": "^7.1.1",
62
63
  "lz-string": "^1.5.0",
63
- "radix-ui": "^1.3.4"
64
+ "radix-ui": "^1.4.2"
64
65
  },
65
66
  "peerDependencies": {
66
67
  "react": "^18.2.0 || ^19.0.0",
@@ -68,40 +69,16 @@
68
69
  },
69
70
  "devDependencies": {
70
71
  "@peculiar/webcrypto": "^1.5.0",
71
- "@testing-library/jest-dom": "^5.17.0",
72
72
  "@testing-library/react": "^15.0.7",
73
73
  "@types/classnames": "^2.3.4",
74
74
  "@types/lz-string": "^1.5.0",
75
75
  "@types/react": "^18.3.18",
76
76
  "chokidar-cli": "^3.0.0",
77
- "jest-canvas-mock": "^2.5.2",
78
- "jest-environment-jsdom": "^29.7.0",
79
77
  "lazyrepo": "0.0.0-alpha.27",
80
78
  "react": "^18.3.1",
81
79
  "react-dom": "^18.3.1",
82
- "resize-observer-polyfill": "^1.5.1"
83
- },
84
- "jest": {
85
- "preset": "../../internal/config/jest/node/jest-preset.js",
86
- "testEnvironment": "../../../packages/utils/patchedJestJsDom.js",
87
- "fakeTimers": {
88
- "enableGlobally": true
89
- },
90
- "testPathIgnorePatterns": [
91
- "^.+\\.*.css$"
92
- ],
93
- "moduleNameMapper": {
94
- "^~(.*)": "<rootDir>/src/$1",
95
- "\\.(css|less|scss|sass)$": "identity-obj-proxy"
96
- },
97
- "setupFiles": [
98
- "raf/polyfill",
99
- "jest-canvas-mock",
100
- "<rootDir>/setupTests.js"
101
- ],
102
- "setupFilesAfterEnv": [
103
- "../../internal/config/setupJest.ts"
104
- ]
80
+ "resize-observer-polyfill": "^1.5.1",
81
+ "vitest": "^3.2.4"
105
82
  },
106
83
  "module": "dist-esm/index.mjs",
107
84
  "source": "src/index.ts",
package/src/index.ts CHANGED
@@ -26,8 +26,13 @@ export { AccessibilityMenu } from './lib/ui/components/AccessibilityMenu'
26
26
  export { ColorSchemeMenu } from './lib/ui/components/ColorSchemeMenu'
27
27
  export { DefaultDialogs } from './lib/ui/components/Dialogs'
28
28
  export {
29
+ TldrawUiColumn,
29
30
  TldrawUiGrid,
31
+ TldrawUiOrientationProvider,
30
32
  TldrawUiRow,
33
+ useTldrawUiOrientation,
34
+ type TldrawUiOrientationContext,
35
+ type TldrawUiOrientationProviderProps,
31
36
  type TLUiLayoutProps,
32
37
  } from './lib/ui/components/primitives/layout'
33
38
  export {
@@ -161,6 +166,9 @@ export {
161
166
  type TLDefaultFont,
162
167
  type TLDefaultFonts,
163
168
  } from './lib/shapes/shared/defaultFonts'
169
+ export { getStrokePoints } from './lib/shapes/shared/freehand/getStrokePoints'
170
+ export { getSvgPathFromStrokePoints } from './lib/shapes/shared/freehand/svg'
171
+ export { type StrokeOptions, type StrokePoint } from './lib/shapes/shared/freehand/types'
164
172
  export {
165
173
  PlainTextLabel,
166
174
  TextLabel,
@@ -31,7 +31,7 @@ export function TldrawScribble({ scribble, zoom, color, opacity, className }: TL
31
31
  <path
32
32
  className="tl-scribble"
33
33
  d={d}
34
- fill={color ?? `var(--color-${scribble.color})`}
34
+ fill={color ?? `var(--tl-color-${scribble.color})`}
35
35
  opacity={opacity ?? scribble.opacity}
36
36
  />
37
37
  </svg>
@@ -1,4 +1,5 @@
1
1
  import { TLArrowShape, createShapeId } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from '../../../test/TestEditor'
3
4
  import { ArrowShapeUtil } from './ArrowShapeUtil'
4
5
  import { updateArrowTargetState } from './arrowTargetState'
@@ -12,7 +13,7 @@ const ids = {
12
13
  arrow1: createShapeId('arrow1'),
13
14
  }
14
15
 
15
- jest.useFakeTimers()
16
+ vi.useFakeTimers()
16
17
 
17
18
  window.requestAnimationFrame = function requestAnimationFrame(cb) {
18
19
  return setTimeout(cb, 1000 / 60)
@@ -1,4 +1,5 @@
1
1
  import { IndexKey, TLArrowShape, TLShapeId, Vec, createShapeId } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from '../../../test/TestEditor'
3
4
  import { getArrowTargetState } from './arrowTargetState'
4
5
  import { getArrowBindings } from './shared'
@@ -13,7 +14,7 @@ global.cancelAnimationFrame = function cancelAnimationFrame(id) {
13
14
  clearTimeout(id)
14
15
  }
15
16
 
16
- jest.useFakeTimers()
17
+ vi.useFakeTimers()
17
18
 
18
19
  const ids = {
19
20
  box1: createShapeId('box1'),
@@ -242,7 +243,7 @@ describe('When pointing an end shape', () => {
242
243
  },
243
244
  })
244
245
 
245
- jest.advanceTimersByTime(1000)
246
+ vi.advanceTimersByTime(1000)
246
247
 
247
248
  arrow = editor.getCurrentPageShapes()[editor.getCurrentPageShapes().length - 1]
248
249
 
@@ -306,7 +307,7 @@ describe('When pointing an end shape', () => {
306
307
  })
307
308
 
308
309
  // Give time for the velocity to die down
309
- jest.advanceTimersByTime(1000)
310
+ vi.advanceTimersByTime(1000)
310
311
 
311
312
  arrow = editor.getCurrentPageShapes()[editor.getCurrentPageShapes().length - 1]
312
313
 
@@ -1,4 +1,5 @@
1
1
  import { HALF_PI, TLArrowShape, TLShapeId, createShapeId, toRichText } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from '../../../test/TestEditor'
3
4
  import { createOrUpdateArrowBinding, getArrowBindings } from './shared'
4
5
 
@@ -12,7 +13,7 @@ const ids = {
12
13
  arrow1: createShapeId('arrow1'),
13
14
  }
14
15
 
15
- jest.useFakeTimers()
16
+ vi.useFakeTimers()
16
17
 
17
18
  window.requestAnimationFrame = function requestAnimationFrame(cb) {
18
19
  return setTimeout(cb, 1000 / 60)
@@ -217,7 +218,7 @@ describe('Other cases when arrow are moved', () => {
217
218
  // When box one is not selected, unbinds box1 and keeps binding to box2
218
219
  editor.select(ids.arrow1, ids.box2, ids.box3)
219
220
  editor.alignShapes(editor.getSelectedShapeIds(), 'right')
220
- jest.advanceTimersByTime(1000)
221
+ vi.advanceTimersByTime(1000)
221
222
 
222
223
  expect(bindings()).toMatchObject({
223
224
  start: { toId: ids.box1, props: { isPrecise: false } },
@@ -227,7 +228,7 @@ describe('Other cases when arrow are moved', () => {
227
228
  // maintains bindings if they would still be over the same shape (but makes them precise), but unbinds others
228
229
  editor.select(ids.arrow1, ids.box3)
229
230
  editor.alignShapes(editor.getSelectedShapeIds(), 'top')
230
- jest.advanceTimersByTime(1000)
231
+ vi.advanceTimersByTime(1000)
231
232
 
232
233
  expect(bindings()).toMatchObject({
233
234
  start: { toId: ids.box1, props: { isPrecise: true } },
@@ -244,7 +245,7 @@ describe('Other cases when arrow are moved', () => {
244
245
  // When box one is not selected, unbinds box1 and keeps binding to box2
245
246
  editor.select(ids.arrow1, ids.box2, ids.box3)
246
247
  editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
247
- jest.advanceTimersByTime(1000)
248
+ vi.advanceTimersByTime(1000)
248
249
 
249
250
  expect(bindings()).toMatchObject({
250
251
  start: { toId: ids.box1, props: { isPrecise: false } },
@@ -254,7 +255,7 @@ describe('Other cases when arrow are moved', () => {
254
255
  // unbinds when only the arrow is selected (not its bound shapes) if the arrow itself has moved
255
256
  editor.select(ids.arrow1, ids.box3, ids.box4)
256
257
  editor.distributeShapes(editor.getSelectedShapeIds(), 'vertical')
257
- jest.advanceTimersByTime(1000)
258
+ vi.advanceTimersByTime(1000)
258
259
 
259
260
  // The arrow didn't actually move
260
261
  expect(bindings()).toMatchObject({
@@ -265,7 +266,7 @@ describe('Other cases when arrow are moved', () => {
265
266
  // The arrow will not move because it is still bound to another shape
266
267
  editor.updateShapes([{ id: ids.box4, type: 'geo', y: -600 }])
267
268
  editor.distributeShapes(editor.getSelectedShapeIds(), 'vertical')
268
- jest.advanceTimersByTime(1000)
269
+ vi.advanceTimersByTime(1000)
269
270
 
270
271
  expect(bindings()).toMatchObject({
271
272
  start: undefined,
@@ -31,6 +31,7 @@ import {
31
31
  clamp,
32
32
  debugFlags,
33
33
  exhaustiveSwitchError,
34
+ getColorValue,
34
35
  getDefaultColorTheme,
35
36
  getFontsFromRichText,
36
37
  invLerp,
@@ -785,8 +786,8 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
785
786
  lineHeight={TEXT_PROPS.lineHeight}
786
787
  align="middle"
787
788
  verticalAlign="middle"
789
+ labelColor={getColorValue(theme, shape.props.labelColor, 'solid')}
788
790
  richText={shape.props.richText}
789
- labelColor={theme[shape.props.labelColor].solid}
790
791
  textWidth={labelPosition.box.w - ARROW_LABEL_PADDING * 2 * shape.props.scale}
791
792
  isSelected={isSelected}
792
793
  padding={0}
@@ -934,8 +935,8 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
934
935
  font={shape.props.font}
935
936
  align="middle"
936
937
  verticalAlign="middle"
938
+ labelColor={getColorValue(theme, shape.props.labelColor, 'solid')}
937
939
  richText={shape.props.richText}
938
- labelColor={theme[shape.props.labelColor].solid}
939
940
  bounds={getArrowLabelPosition(this.editor, shape)
940
941
  .box.clone()
941
942
  .expandBy(-ARROW_LABEL_PADDING * shape.props.scale)}
@@ -1077,7 +1078,7 @@ const ArrowSvg = track(function ArrowSvg({
1077
1078
  </defs>
1078
1079
  <g
1079
1080
  fill="none"
1080
- stroke={theme[shape.props.color].solid}
1081
+ stroke={getColorValue(theme, shape.props.color, 'solid')}
1081
1082
  strokeWidth={strokeWidth}
1082
1083
  strokeLinejoin="round"
1083
1084
  strokeLinecap="round"
@@ -98,7 +98,7 @@ export function ElbowArrowDebug({ arrow }: { arrow: TLArrowShape }) {
98
98
  y={fullBox.minY - 3}
99
99
  fontSize={10}
100
100
  fill="black"
101
- stroke="var(--color-background)"
101
+ stroke="var(--tl-color-background)"
102
102
  strokeWidth={2}
103
103
  paintOrder="stroke"
104
104
  >
@@ -109,7 +109,7 @@ export function ElbowArrowDebug({ arrow }: { arrow: TLArrowShape }) {
109
109
  y={info.A.expanded.y}
110
110
  fontSize={10}
111
111
  fill="black"
112
- stroke="var(--color-background)"
112
+ stroke="var(--tl-color-background)"
113
113
  strokeWidth={2}
114
114
  paintOrder="stroke"
115
115
  >
@@ -121,7 +121,7 @@ export function ElbowArrowDebug({ arrow }: { arrow: TLArrowShape }) {
121
121
  y={info.B.expanded.y}
122
122
  fontSize={10}
123
123
  fill="black"
124
- stroke="var(--color-background)"
124
+ stroke="var(--tl-color-background)"
125
125
  strokeWidth={2}
126
126
  paintOrder="stroke"
127
127
  >
@@ -1,5 +1,4 @@
1
1
  import { TestEditor } from '../../../test/TestEditor'
2
- import { DrawShapeTool } from './DrawShapeTool'
3
2
 
4
3
  let editor: TestEditor
5
4
 
@@ -10,10 +9,6 @@ afterEach(() => {
10
9
  editor?.dispose()
11
10
  })
12
11
 
13
- describe(DrawShapeTool, () => {
14
- return
15
- })
16
-
17
12
  describe('When in the idle state', () => {
18
13
  it('Returns to select on cancel', () => {
19
14
  editor.setCurrentTool('draw')
@@ -14,6 +14,7 @@ import {
14
14
  VecLike,
15
15
  drawShapeMigrations,
16
16
  drawShapeProps,
17
+ getColorValue,
17
18
  last,
18
19
  lerp,
19
20
  rng,
@@ -289,7 +290,7 @@ function DrawShapeSvg({ shape, zoomOverride }: { shape: TLDrawShape; zoomOverrid
289
290
  <path
290
291
  d={svgInk(allPointsFromSegments, options)}
291
292
  strokeLinecap="round"
292
- fill={theme[shape.props.color].solid}
293
+ fill={getColorValue(theme, shape.props.color, 'solid')}
293
294
  />
294
295
  </>
295
296
  )
@@ -313,8 +314,8 @@ function DrawShapeSvg({ shape, zoomOverride }: { shape: TLDrawShape; zoomOverrid
313
314
  <path
314
315
  d={solidStrokePath}
315
316
  strokeLinecap="round"
316
- fill={isDot ? theme[shape.props.color].solid : 'none'}
317
- stroke={theme[shape.props.color].solid}
317
+ fill={isDot ? getColorValue(theme, shape.props.color, 'solid') : 'none'}
318
+ stroke={getColorValue(theme, shape.props.color, 'solid')}
318
319
  strokeWidth={sw}
319
320
  strokeDasharray={isDot ? 'none' : getDrawShapeStrokeDashArray(shape, sw, dotAdjustment)}
320
321
  strokeDashoffset="0"
@@ -144,7 +144,7 @@ export class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {
144
144
  border: 0,
145
145
  boxShadow: getRotatedBoxShadow(pageRotation),
146
146
  borderRadius: embedInfo?.definition.overrideOutlineRadius ?? 8,
147
- background: embedInfo?.definition.backgroundColor ?? 'var(--color-background)',
147
+ background: embedInfo?.definition.backgroundColor ?? 'var(--tl-color-background)',
148
148
  width: w,
149
149
  height: h,
150
150
  }}
@@ -19,6 +19,7 @@ import {
19
19
  compact,
20
20
  frameShapeMigrations,
21
21
  frameShapeProps,
22
+ getColorValue,
22
23
  getDefaultColorTheme,
23
24
  lerp,
24
25
  resizeBox,
@@ -220,13 +221,16 @@ export class FrameShapeUtil extends BaseBoxShapeUtil<TLFrameShape> {
220
221
  )
221
222
 
222
223
  const showFrameColors = this.options.showColors
223
-
224
- const color = theme[shape.props.color]
225
- const frameFill = showFrameColors ? color.frame.fill : theme.black.frame.fill
226
- const frameStroke = showFrameColors ? color.frame.stroke : theme.black.frame.stroke
227
- const frameHeadingStroke = showFrameColors ? color.frame.headingStroke : theme.background
228
- const frameHeadingFill = showFrameColors ? color.frame.headingFill : theme.background
229
- const frameHeadingText = showFrameColors ? color.frame.text : theme.text
224
+ const colorToUse = showFrameColors ? shape.props.color : 'black'
225
+ const frameFill = getColorValue(theme, colorToUse, 'frameFill')
226
+ const frameStroke = getColorValue(theme, colorToUse, 'frameStroke')
227
+ const frameHeadingStroke = showFrameColors
228
+ ? getColorValue(theme, colorToUse, 'frameHeadingStroke')
229
+ : theme.background
230
+ const frameHeadingFill = showFrameColors
231
+ ? getColorValue(theme, colorToUse, 'frameHeadingFill')
232
+ : theme.background
233
+ const frameHeadingText = getColorValue(theme, colorToUse, 'frameText')
230
234
 
231
235
  return (
232
236
  <>
@@ -277,13 +281,16 @@ export class FrameShapeUtil extends BaseBoxShapeUtil<TLFrameShape> {
277
281
  const text = createTextJsxFromSpans(this.editor, spans, opts)
278
282
 
279
283
  const showFrameColors = this.options.showColors
280
-
281
- const color = theme[shape.props.color]
282
- const frameFill = showFrameColors ? color.frame.fill : theme.black.frame.fill
283
- const frameStroke = showFrameColors ? color.frame.stroke : theme.black.frame.stroke
284
- const frameHeadingStroke = showFrameColors ? color.frame.headingStroke : theme.background
285
- const frameHeadingFill = showFrameColors ? color.frame.headingFill : theme.background
286
- const frameHeadingText = showFrameColors ? color.frame.text : theme.text
284
+ const colorToUse = showFrameColors ? shape.props.color : 'black'
285
+ const frameFill = getColorValue(theme, colorToUse, 'frameFill')
286
+ const frameStroke = getColorValue(theme, colorToUse, 'frameStroke')
287
+ const frameHeadingStroke = showFrameColors
288
+ ? getColorValue(theme, colorToUse, 'frameHeadingStroke')
289
+ : theme.background
290
+ const frameHeadingFill = showFrameColors
291
+ ? getColorValue(theme, colorToUse, 'frameHeadingFill')
292
+ : theme.background
293
+ const frameHeadingText = getColorValue(theme, colorToUse, 'frameText')
287
294
 
288
295
  return (
289
296
  <>
@@ -64,7 +64,7 @@ export const FrameHeading = memo(function FrameHeading({
64
64
  overflow: isEditing ? 'visible' : 'hidden',
65
65
  maxWidth: `calc(var(--tl-zoom) * ${
66
66
  side === 0 || side === 2 ? Math.ceil(width) : Math.ceil(height)
67
- }px + ${showColors ? '0px' : 'var(--frame-offset-width)'})`,
67
+ }px + ${showColors ? '0px' : 'var(--tl-frame-offset-width)'})`,
68
68
  bottom: '100%',
69
69
  transform: `${translation} scale(var(--tl-scale)) translateX(${offsetX}px)`,
70
70
  }}
@@ -18,6 +18,7 @@ import {
18
18
  exhaustiveSwitchError,
19
19
  geoShapeMigrations,
20
20
  geoShapeProps,
21
+ getColorValue,
21
22
  getDefaultColorTheme,
22
23
  getFontsFromRichText,
23
24
  isEqual,
@@ -220,7 +221,7 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
220
221
  verticalAlign={verticalAlign}
221
222
  richText={richText}
222
223
  isSelected={isOnlySelected}
223
- labelColor={theme[props.labelColor].solid}
224
+ labelColor={getColorValue(theme, props.labelColor, 'solid')}
224
225
  wrap
225
226
  />
226
227
  </HTMLContainer>
@@ -278,7 +279,7 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
278
279
  align={props.align}
279
280
  verticalAlign={props.verticalAlign}
280
281
  richText={props.richText}
281
- labelColor={theme[props.labelColor].solid}
282
+ labelColor={getColorValue(theme, props.labelColor, 'solid')}
282
283
  bounds={bounds}
283
284
  padding={LABEL_PADDING}
284
285
  />
@@ -1,4 +1,4 @@
1
- import { TLGeoShape } from '@tldraw/editor'
1
+ import { getColorValue, TLGeoShape } from '@tldraw/editor'
2
2
  import { ShapeFill } from '../../shared/ShapeFill'
3
3
  import { STROKE_SIZES } from '../../shared/default-shape-constants'
4
4
  import { useDefaultColorTheme } from '../../shared/useDefaultColorTheme'
@@ -33,7 +33,7 @@ export function GeoShapeBody({
33
33
  strokeWidth,
34
34
  forceSolid,
35
35
  randomSeed: shape.id,
36
- props: { fill: 'none', stroke: theme[color].solid },
36
+ props: { fill: 'none', stroke: getColorValue(theme, color, 'solid') },
37
37
  })}
38
38
  </>
39
39
  )
@@ -10,6 +10,7 @@ import {
10
10
  TLHighlightShapeProps,
11
11
  TLResizeInfo,
12
12
  VecLike,
13
+ getColorValue,
13
14
  highlightShapeMigrations,
14
15
  highlightShapeProps,
15
16
  last,
@@ -289,7 +290,12 @@ function HighlightRenderer({
289
290
  : getShapeDot(shape.props.segments[0].points[0])
290
291
 
291
292
  const colorSpace = useColorSpace()
292
- const color = theme[shape.props.color].highlight[colorSpace]
293
+
294
+ const color = getColorValue(
295
+ theme,
296
+ shape.props.color,
297
+ colorSpace === 'p3' ? 'highlightP3' : 'highlightSrgb'
298
+ )
293
299
 
294
300
  return (
295
301
  <path
@@ -314,9 +314,9 @@ const ImageShape = memo(function ImageShape({ shape }: { shape: TLImageShape })
314
314
  overflow: 'hidden',
315
315
  width: shape.props.w,
316
316
  height: shape.props.h,
317
- color: 'var(--color-text-3)',
318
- backgroundColor: 'var(--color-low)',
319
- border: '1px solid var(--color-low-border)',
317
+ color: 'var(--tl-color-text-3)',
318
+ backgroundColor: 'var(--tl-color-low)',
319
+ border: '1px solid var(--tl-color-low-border)',
320
320
  }}
321
321
  >
322
322
  <div