@tldraw/editor 4.6.0-next.0eb36d65eec3 → 4.6.0-next.1a05e8ec7833

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 (300) hide show
  1. package/dist-cjs/index.d.ts +816 -112
  2. package/dist-cjs/index.js +22 -6
  3. package/dist-cjs/index.js.map +3 -3
  4. package/dist-cjs/lib/TldrawEditor.js +59 -14
  5. package/dist-cjs/lib/TldrawEditor.js.map +3 -3
  6. package/dist-cjs/lib/components/LiveCollaborators.js +1 -0
  7. package/dist-cjs/lib/components/LiveCollaborators.js.map +2 -2
  8. package/dist-cjs/lib/components/MenuClickCapture.js +99 -38
  9. package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
  10. package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +10 -3
  11. package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +3 -3
  12. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +5 -2
  13. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  14. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +1 -1
  15. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
  16. package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js +1 -0
  17. package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js.map +2 -2
  18. package/dist-cjs/lib/config/{createTLUser.js → createTLCurrentUser.js} +9 -9
  19. package/dist-cjs/lib/config/createTLCurrentUser.js.map +7 -0
  20. package/dist-cjs/lib/config/createTLStore.js +30 -0
  21. package/dist-cjs/lib/config/createTLStore.js.map +2 -2
  22. package/dist-cjs/lib/config/defaultAssets.js +36 -0
  23. package/dist-cjs/lib/config/defaultAssets.js.map +7 -0
  24. package/dist-cjs/lib/editor/Editor.js +389 -13
  25. package/dist-cjs/lib/editor/Editor.js.map +3 -3
  26. package/dist-cjs/lib/editor/assets/AssetUtil.js +67 -0
  27. package/dist-cjs/lib/editor/assets/AssetUtil.js.map +7 -0
  28. package/dist-cjs/lib/editor/bindings/BindingUtil.js +1 -0
  29. package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +1 -1
  30. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +1 -0
  31. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +1 -1
  32. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +1 -0
  33. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +1 -1
  34. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +1 -0
  35. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +1 -1
  36. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +2 -0
  37. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
  38. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +2 -0
  39. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +1 -1
  40. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +12 -0
  41. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
  42. package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.js +80 -0
  43. package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.js.map +7 -0
  44. package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceManager.js +466 -0
  45. package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceManager.js.map +7 -0
  46. package/dist-cjs/lib/editor/managers/PerformanceManager/perf-types.js +17 -0
  47. package/dist-cjs/lib/editor/managers/PerformanceManager/perf-types.js.map +7 -0
  48. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +1 -0
  49. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +1 -1
  50. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +1 -0
  51. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +1 -1
  52. package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js +1 -0
  53. package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js.map +1 -1
  54. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +2 -1
  55. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
  56. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +1 -0
  57. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +1 -1
  58. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +1 -0
  59. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +1 -1
  60. package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js +107 -0
  61. package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js.map +7 -0
  62. package/dist-cjs/lib/editor/managers/ThemeManager/defaultThemes.js +586 -0
  63. package/dist-cjs/lib/editor/managers/ThemeManager/defaultThemes.js.map +7 -0
  64. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +1 -0
  65. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +1 -1
  66. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +8 -4
  67. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  68. package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js +76 -0
  69. package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js.map +7 -0
  70. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +32 -2
  71. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  72. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +1 -1
  73. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
  74. package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js +6 -0
  75. package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js.map +2 -2
  76. package/dist-cjs/lib/editor/tools/StateNode.js +15 -17
  77. package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
  78. package/dist-cjs/lib/editor/types/SvgExportContext.js.map +2 -2
  79. package/dist-cjs/lib/editor/types/clipboard-types.js.map +1 -1
  80. package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
  81. package/dist-cjs/lib/exports/ExportDelay.js +1 -0
  82. package/dist-cjs/lib/exports/ExportDelay.js.map +1 -1
  83. package/dist-cjs/lib/exports/StyleEmbedder.js +1 -0
  84. package/dist-cjs/lib/exports/StyleEmbedder.js.map +1 -1
  85. package/dist-cjs/lib/exports/getSvgJsx.js +14 -8
  86. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  87. package/dist-cjs/lib/globals/environment.js +18 -1
  88. package/dist-cjs/lib/globals/environment.js.map +2 -2
  89. package/dist-cjs/lib/hooks/useCanvasEvents.js +25 -4
  90. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  91. package/dist-cjs/lib/hooks/{useIsDarkMode.js → useColorMode.js} +14 -10
  92. package/dist-cjs/lib/hooks/useColorMode.js.map +7 -0
  93. package/dist-cjs/lib/hooks/useCursor.js +3 -7
  94. package/dist-cjs/lib/hooks/useCursor.js.map +2 -2
  95. package/dist-cjs/lib/hooks/useDarkMode.js +4 -4
  96. package/dist-cjs/lib/hooks/useDarkMode.js.map +2 -2
  97. package/dist-cjs/lib/hooks/useGestureEvents.js +171 -127
  98. package/dist-cjs/lib/hooks/useGestureEvents.js.map +3 -3
  99. package/dist-cjs/lib/options.js +2 -0
  100. package/dist-cjs/lib/options.js.map +2 -2
  101. package/dist-cjs/lib/primitives/Vec.js +3 -0
  102. package/dist-cjs/lib/primitives/Vec.js.map +1 -1
  103. package/dist-cjs/lib/primitives/geometry/Circle2d.js +1 -0
  104. package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +1 -1
  105. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +1 -0
  106. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +1 -1
  107. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +2 -0
  108. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +1 -1
  109. package/dist-cjs/lib/primitives/geometry/Stadium2d.js +1 -0
  110. package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +1 -1
  111. package/dist-cjs/lib/utils/EditorAtom.js +2 -0
  112. package/dist-cjs/lib/utils/EditorAtom.js.map +1 -1
  113. package/dist-cjs/lib/utils/reparenting.js +2 -1
  114. package/dist-cjs/lib/utils/reparenting.js.map +2 -2
  115. package/dist-cjs/lib/utils/richText.js.map +2 -2
  116. package/dist-cjs/lib/utils/runtime.js +2 -1
  117. package/dist-cjs/lib/utils/runtime.js.map +2 -2
  118. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +2 -0
  119. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +1 -1
  120. package/dist-cjs/lib/utils/sync/hardReset.js +0 -8
  121. package/dist-cjs/lib/utils/sync/hardReset.js.map +2 -2
  122. package/dist-cjs/version.js +3 -3
  123. package/dist-cjs/version.js.map +1 -1
  124. package/dist-esm/index.d.mts +816 -112
  125. package/dist-esm/index.mjs +27 -9
  126. package/dist-esm/index.mjs.map +2 -2
  127. package/dist-esm/lib/TldrawEditor.mjs +62 -14
  128. package/dist-esm/lib/TldrawEditor.mjs.map +3 -3
  129. package/dist-esm/lib/components/LiveCollaborators.mjs +1 -0
  130. package/dist-esm/lib/components/LiveCollaborators.mjs.map +2 -2
  131. package/dist-esm/lib/components/MenuClickCapture.mjs +100 -39
  132. package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
  133. package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +10 -3
  134. package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +3 -3
  135. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +5 -2
  136. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  137. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +1 -1
  138. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  139. package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs +1 -0
  140. package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs.map +2 -2
  141. package/dist-esm/lib/config/{createTLUser.mjs → createTLCurrentUser.mjs} +6 -6
  142. package/dist-esm/lib/config/createTLCurrentUser.mjs.map +7 -0
  143. package/dist-esm/lib/config/createTLStore.mjs +36 -1
  144. package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
  145. package/dist-esm/lib/config/defaultAssets.mjs +16 -0
  146. package/dist-esm/lib/config/defaultAssets.mjs.map +7 -0
  147. package/dist-esm/lib/editor/Editor.mjs +391 -13
  148. package/dist-esm/lib/editor/Editor.mjs.map +3 -3
  149. package/dist-esm/lib/editor/assets/AssetUtil.mjs +47 -0
  150. package/dist-esm/lib/editor/assets/AssetUtil.mjs.map +7 -0
  151. package/dist-esm/lib/editor/bindings/BindingUtil.mjs +1 -0
  152. package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +1 -1
  153. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +1 -0
  154. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +1 -1
  155. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +1 -0
  156. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +1 -1
  157. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +1 -0
  158. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +1 -1
  159. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +2 -0
  160. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
  161. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +2 -0
  162. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +1 -1
  163. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +12 -0
  164. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
  165. package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.mjs +60 -0
  166. package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.mjs.map +7 -0
  167. package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceManager.mjs +438 -0
  168. package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceManager.mjs.map +7 -0
  169. package/dist-esm/lib/editor/managers/PerformanceManager/perf-types.mjs +1 -0
  170. package/dist-esm/lib/editor/managers/PerformanceManager/perf-types.mjs.map +7 -0
  171. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +1 -0
  172. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +1 -1
  173. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +1 -0
  174. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +1 -1
  175. package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs +1 -0
  176. package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs.map +1 -1
  177. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +2 -1
  178. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
  179. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +1 -0
  180. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +1 -1
  181. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +1 -0
  182. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +1 -1
  183. package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs +89 -0
  184. package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs.map +7 -0
  185. package/dist-esm/lib/editor/managers/ThemeManager/defaultThemes.mjs +568 -0
  186. package/dist-esm/lib/editor/managers/ThemeManager/defaultThemes.mjs.map +7 -0
  187. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +1 -0
  188. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +1 -1
  189. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +8 -4
  190. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  191. package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs +56 -0
  192. package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs.map +7 -0
  193. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +32 -2
  194. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  195. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +1 -1
  196. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
  197. package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs +6 -0
  198. package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs.map +2 -2
  199. package/dist-esm/lib/editor/tools/StateNode.mjs +15 -17
  200. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  201. package/dist-esm/lib/editor/types/SvgExportContext.mjs.map +2 -2
  202. package/dist-esm/lib/exports/ExportDelay.mjs +1 -0
  203. package/dist-esm/lib/exports/ExportDelay.mjs.map +1 -1
  204. package/dist-esm/lib/exports/StyleEmbedder.mjs +1 -0
  205. package/dist-esm/lib/exports/StyleEmbedder.mjs.map +1 -1
  206. package/dist-esm/lib/exports/getSvgJsx.mjs +14 -11
  207. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  208. package/dist-esm/lib/globals/environment.mjs +18 -1
  209. package/dist-esm/lib/globals/environment.mjs.map +2 -2
  210. package/dist-esm/lib/hooks/useCanvasEvents.mjs +25 -4
  211. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  212. package/dist-esm/lib/hooks/useColorMode.mjs +19 -0
  213. package/dist-esm/lib/hooks/useColorMode.mjs.map +7 -0
  214. package/dist-esm/lib/hooks/useCursor.mjs +3 -7
  215. package/dist-esm/lib/hooks/useCursor.mjs.map +2 -2
  216. package/dist-esm/lib/hooks/useDarkMode.mjs +4 -4
  217. package/dist-esm/lib/hooks/useDarkMode.mjs.map +2 -2
  218. package/dist-esm/lib/hooks/useGestureEvents.mjs +171 -127
  219. package/dist-esm/lib/hooks/useGestureEvents.mjs.map +3 -3
  220. package/dist-esm/lib/options.mjs +2 -0
  221. package/dist-esm/lib/options.mjs.map +2 -2
  222. package/dist-esm/lib/primitives/Vec.mjs +3 -0
  223. package/dist-esm/lib/primitives/Vec.mjs.map +1 -1
  224. package/dist-esm/lib/primitives/geometry/Circle2d.mjs +1 -0
  225. package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +1 -1
  226. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +1 -0
  227. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +1 -1
  228. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +2 -0
  229. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +1 -1
  230. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +1 -0
  231. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +1 -1
  232. package/dist-esm/lib/utils/EditorAtom.mjs +2 -0
  233. package/dist-esm/lib/utils/EditorAtom.mjs.map +1 -1
  234. package/dist-esm/lib/utils/reparenting.mjs +2 -1
  235. package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
  236. package/dist-esm/lib/utils/richText.mjs.map +2 -2
  237. package/dist-esm/lib/utils/runtime.mjs +2 -1
  238. package/dist-esm/lib/utils/runtime.mjs.map +2 -2
  239. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +2 -0
  240. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +1 -1
  241. package/dist-esm/lib/utils/sync/hardReset.mjs +0 -8
  242. package/dist-esm/lib/utils/sync/hardReset.mjs.map +2 -2
  243. package/dist-esm/version.mjs +3 -3
  244. package/dist-esm/version.mjs.map +1 -1
  245. package/editor.css +13 -37
  246. package/package.json +8 -9
  247. package/src/index.ts +30 -7
  248. package/src/lib/TldrawEditor.tsx +98 -19
  249. package/src/lib/components/LiveCollaborators.tsx +8 -2
  250. package/src/lib/components/MenuClickCapture.tsx +129 -49
  251. package/src/lib/components/default-components/CanvasShapeIndicators.tsx +14 -3
  252. package/src/lib/components/default-components/DefaultCanvas.tsx +6 -2
  253. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +2 -2
  254. package/src/lib/components/default-components/DefaultShapeIndicators.tsx +2 -0
  255. package/src/lib/config/{createTLUser.ts → createTLCurrentUser.ts} +6 -6
  256. package/src/lib/config/createTLStore.ts +57 -2
  257. package/src/lib/config/defaultAssets.ts +19 -0
  258. package/src/lib/editor/Editor.ts +526 -42
  259. package/src/lib/editor/assets/AssetUtil.ts +85 -0
  260. package/src/lib/editor/managers/FontManager/FontManager.test.ts +9 -2
  261. package/src/lib/editor/managers/FontManager/FontManager.ts +1 -67
  262. package/src/lib/editor/managers/InputsManager/InputsManager.ts +12 -0
  263. package/src/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.ts +82 -0
  264. package/src/lib/editor/managers/PerformanceManager/PerformanceManager.test.ts +522 -0
  265. package/src/lib/editor/managers/PerformanceManager/PerformanceManager.ts +583 -0
  266. package/src/lib/editor/managers/PerformanceManager/perf-types.ts +196 -0
  267. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +13 -2
  268. package/src/lib/editor/managers/SnapManager/SnapManager.ts +1 -1
  269. package/src/lib/editor/managers/ThemeManager/ThemeManager.ts +116 -0
  270. package/src/lib/editor/managers/ThemeManager/defaultThemes.ts +605 -0
  271. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +25 -31
  272. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +7 -5
  273. package/src/lib/editor/shapes/BaseFrameLikeShapeUtil.tsx +121 -0
  274. package/src/lib/editor/shapes/ShapeUtil.ts +50 -3
  275. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +1 -1
  276. package/src/lib/editor/shapes/shared/getPerfectDashProps.ts +7 -0
  277. package/src/lib/editor/tools/StateNode.ts +16 -18
  278. package/src/lib/editor/types/SvgExportContext.tsx +5 -0
  279. package/src/lib/editor/types/clipboard-types.ts +2 -1
  280. package/src/lib/editor/types/external-content.ts +1 -0
  281. package/src/lib/exports/getSvgJsx.tsx +23 -16
  282. package/src/lib/globals/environment.ts +18 -0
  283. package/src/lib/hooks/useCanvasEvents.ts +40 -3
  284. package/src/lib/hooks/{useIsDarkMode.ts → useColorMode.ts} +9 -5
  285. package/src/lib/hooks/useCursor.ts +3 -7
  286. package/src/lib/hooks/useDarkMode.ts +4 -4
  287. package/src/lib/hooks/useGestureEvents.ts +240 -168
  288. package/src/lib/options.ts +14 -0
  289. package/src/lib/primitives/Box.test.ts +30 -0
  290. package/src/lib/primitives/geometry/Geometry2d.test.ts +21 -0
  291. package/src/lib/utils/reparenting.ts +6 -2
  292. package/src/lib/utils/richText.ts +1 -1
  293. package/src/lib/utils/runtime.ts +3 -1
  294. package/src/lib/utils/sync/hardReset.ts +0 -8
  295. package/src/version.ts +3 -3
  296. package/dist-cjs/lib/config/createTLUser.js.map +0 -7
  297. package/dist-cjs/lib/hooks/useIsDarkMode.js.map +0 -7
  298. package/dist-esm/lib/config/createTLUser.mjs.map +0 -7
  299. package/dist-esm/lib/hooks/useIsDarkMode.mjs +0 -15
  300. package/dist-esm/lib/hooks/useIsDarkMode.mjs.map +0 -7
@@ -1,6 +1,6 @@
1
1
  import { atom } from '@tldraw/state'
2
2
  import { Mocked, vi } from 'vitest'
3
- import { TLUser } from '../../../config/createTLUser'
3
+ import { TLCurrentUser } from '../../../config/createTLCurrentUser'
4
4
  import { TLUserPreferences, defaultUserPreferences } from '../../../config/TLUserPreferences'
5
5
  import { UserPreferencesManager } from './UserPreferencesManager'
6
6
 
@@ -9,7 +9,7 @@ const mockMatchMedia = vi.fn()
9
9
  window.matchMedia = mockMatchMedia
10
10
 
11
11
  describe('UserPreferencesManager', () => {
12
- let mockUser: Mocked<TLUser>
12
+ let mockUser: Mocked<TLCurrentUser>
13
13
  let mockUserPreferences: TLUserPreferences
14
14
  let userPreferencesAtom: any
15
15
  let userPreferencesManager: UserPreferencesManager
@@ -61,7 +61,7 @@ describe('UserPreferencesManager', () => {
61
61
  // Test when window.matchMedia is not available
62
62
  delete (window as any).matchMedia
63
63
 
64
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
64
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
65
65
 
66
66
  expect(userPreferencesManager.systemColorScheme.get()).toBe('light')
67
67
 
@@ -76,7 +76,7 @@ describe('UserPreferencesManager', () => {
76
76
  removeEventListener: vi.fn(),
77
77
  })
78
78
 
79
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
79
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
80
80
 
81
81
  expect(userPreferencesManager.systemColorScheme.get()).toBe('light')
82
82
  })
@@ -88,7 +88,7 @@ describe('UserPreferencesManager', () => {
88
88
  removeEventListener: vi.fn(),
89
89
  })
90
90
 
91
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
91
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'system')
92
92
 
93
93
  expect(userPreferencesManager.systemColorScheme.get()).toBe('dark')
94
94
  })
@@ -103,7 +103,7 @@ describe('UserPreferencesManager', () => {
103
103
  removeEventListener: mockRemoveEventListener,
104
104
  })
105
105
 
106
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
106
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'system')
107
107
 
108
108
  expect(mockAddEventListener).toHaveBeenCalledWith('change', expect.any(Function))
109
109
  })
@@ -123,7 +123,7 @@ describe('UserPreferencesManager', () => {
123
123
  removeEventListener: vi.fn(),
124
124
  })
125
125
 
126
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
126
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'system')
127
127
 
128
128
  expect(userPreferencesManager.systemColorScheme.get()).toBe('light')
129
129
 
@@ -141,7 +141,7 @@ describe('UserPreferencesManager', () => {
141
141
  delete (global as any).window
142
142
 
143
143
  expect(() => {
144
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
144
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
145
145
  }).not.toThrow()
146
146
 
147
147
  global.window = originalWindow
@@ -158,14 +158,14 @@ describe('UserPreferencesManager', () => {
158
158
  removeEventListener: mockRemoveEventListener,
159
159
  })
160
160
 
161
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
161
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'system')
162
162
  userPreferencesManager.dispose()
163
163
 
164
164
  expect(mockRemoveEventListener).toHaveBeenCalledWith('change', expect.any(Function))
165
165
  })
166
166
 
167
167
  it('should call all disposables', () => {
168
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
168
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
169
169
 
170
170
  const mockDisposable1 = vi.fn()
171
171
  const mockDisposable2 = vi.fn()
@@ -182,7 +182,7 @@ describe('UserPreferencesManager', () => {
182
182
 
183
183
  describe('updateUserPreferences', () => {
184
184
  beforeEach(() => {
185
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
185
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
186
186
  })
187
187
 
188
188
  it('should update user preferences with partial data', () => {
@@ -216,7 +216,7 @@ describe('UserPreferencesManager', () => {
216
216
 
217
217
  describe('getUserPreferences', () => {
218
218
  beforeEach(() => {
219
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
219
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
220
220
  })
221
221
 
222
222
  it('should return complete user preferences with computed values', () => {
@@ -255,7 +255,7 @@ describe('UserPreferencesManager', () => {
255
255
 
256
256
  describe('getIsDarkMode', () => {
257
257
  beforeEach(() => {
258
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
258
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
259
259
  })
260
260
 
261
261
  it('should return true when colorScheme is dark', () => {
@@ -282,24 +282,18 @@ describe('UserPreferencesManager', () => {
282
282
  expect(userPreferencesManager.getIsDarkMode()).toBe(true)
283
283
  })
284
284
 
285
- it('should use inferDarkMode when colorScheme is undefined', () => {
285
+ it('should default to light when colorScheme is undefined', () => {
286
286
  userPreferencesAtom.set({ ...mockUserPreferences, colorScheme: undefined })
287
287
 
288
- // With inferDarkMode = true
289
- const managerWithInfer = new UserPreferencesManager(mockUser, true)
290
- managerWithInfer.systemColorScheme.set('dark')
291
- expect(managerWithInfer.getIsDarkMode()).toBe(true)
292
-
293
- // With inferDarkMode = false
294
- const managerWithoutInfer = new UserPreferencesManager(mockUser, false)
295
- managerWithoutInfer.systemColorScheme.set('dark')
296
- expect(managerWithoutInfer.getIsDarkMode()).toBe(false)
288
+ const manager = new UserPreferencesManager(mockUser, 'light')
289
+ manager.systemColorScheme.set('dark')
290
+ expect(manager.getIsDarkMode()).toBe(false)
297
291
  })
298
292
  })
299
293
 
300
294
  describe('individual preference getters', () => {
301
295
  beforeEach(() => {
302
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
296
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
303
297
  })
304
298
 
305
299
  describe('getId', () => {
@@ -499,7 +493,7 @@ describe('UserPreferencesManager', () => {
499
493
 
500
494
  describe('reactive behavior', () => {
501
495
  beforeEach(() => {
502
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
496
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
503
497
  })
504
498
 
505
499
  it('should react to user preferences changes', () => {
@@ -533,7 +527,7 @@ describe('UserPreferencesManager', () => {
533
527
 
534
528
  describe('edge cases and error handling', () => {
535
529
  beforeEach(() => {
536
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
530
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
537
531
  })
538
532
 
539
533
  it('should handle undefined user preferences gracefully', () => {
@@ -589,14 +583,14 @@ describe('UserPreferencesManager', () => {
589
583
  mockMatchMedia.mockReturnValue(null)
590
584
 
591
585
  expect(() => {
592
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
586
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
593
587
  }).not.toThrow()
594
588
 
595
589
  expect(userPreferencesManager.systemColorScheme.get()).toBe('light')
596
590
  })
597
591
 
598
592
  it('should handle dispose gracefully in all cases', () => {
599
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
593
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
600
594
 
601
595
  // Should not throw even if dispose is called multiple times
602
596
  expect(() => userPreferencesManager.dispose()).not.toThrow()
@@ -608,7 +602,7 @@ describe('UserPreferencesManager', () => {
608
602
  const originalWindow = global.window
609
603
  delete (global as any).window
610
604
 
611
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
605
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
612
606
 
613
607
  expect(() => userPreferencesManager.dispose()).not.toThrow()
614
608
  expect(userPreferencesManager.disposables.size).toBe(0)
@@ -619,7 +613,7 @@ describe('UserPreferencesManager', () => {
619
613
 
620
614
  describe('integration scenarios', () => {
621
615
  it('should work with real-world preference scenarios', () => {
622
- userPreferencesManager = new UserPreferencesManager(mockUser, true)
616
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
623
617
 
624
618
  // User starts with system preference
625
619
  userPreferencesManager.updateUserPreferences({ colorScheme: 'system' })
@@ -641,7 +635,7 @@ describe('UserPreferencesManager', () => {
641
635
  })
642
636
 
643
637
  it('should handle preference updates with multiple fields', () => {
644
- userPreferencesManager = new UserPreferencesManager(mockUser, false)
638
+ userPreferencesManager = new UserPreferencesManager(mockUser, 'light')
645
639
 
646
640
  const updates = {
647
641
  name: 'New User',
@@ -1,5 +1,5 @@
1
1
  import { atom, computed } from '@tldraw/state'
2
- import { TLUser } from '../../../config/createTLUser'
2
+ import { TLCurrentUser } from '../../../config/createTLCurrentUser'
3
3
  import { TLUserPreferences, defaultUserPreferences } from '../../../config/TLUserPreferences'
4
4
  import { getGlobalWindow } from '../../../utils/dom'
5
5
 
@@ -11,8 +11,8 @@ export class UserPreferencesManager {
11
11
  this.disposables.forEach((d) => d())
12
12
  }
13
13
  constructor(
14
- private readonly user: TLUser,
15
- private readonly inferDarkMode: boolean
14
+ private readonly user: TLCurrentUser,
15
+ private readonly colorScheme: 'light' | 'dark' | 'system'
16
16
  ) {
17
17
  if (typeof window === 'undefined' || !getGlobalWindow().matchMedia) return
18
18
 
@@ -57,7 +57,9 @@ export class UserPreferencesManager {
57
57
  }
58
58
 
59
59
  @computed getIsDarkMode() {
60
- switch (this.user.userPreferences.get().colorScheme) {
60
+ const userColorScheme = this.user.userPreferences.get().colorScheme
61
+ const scheme = userColorScheme ?? this.colorScheme
62
+ switch (scheme) {
61
63
  case 'dark':
62
64
  return true
63
65
  case 'light':
@@ -65,7 +67,7 @@ export class UserPreferencesManager {
65
67
  case 'system':
66
68
  return this.systemColorScheme.get() === 'dark'
67
69
  default:
68
- return this.inferDarkMode ? this.systemColorScheme.get() === 'dark' : false
70
+ return false
69
71
  }
70
72
  }
71
73
 
@@ -0,0 +1,121 @@
1
+ import { TLShape, TLShapeId } from '@tldraw/tlschema'
2
+ import { IndexKey, compact } from '@tldraw/utils'
3
+ import { Vec } from '../../primitives/Vec'
4
+ import { BaseBoxShapeUtil, TLBaseBoxShape } from './BaseBoxShapeUtil'
5
+ import { TLDragShapesInInfo, TLDragShapesOutInfo } from './ShapeUtil'
6
+
7
+ /**
8
+ * A base class for frame-like shapes — containers that clip their children,
9
+ * require full-brush selection, block erasure from inside, and support
10
+ * drag-and-drop reparenting.
11
+ *
12
+ * Extending this class is the easiest way to create a custom frame-like shape.
13
+ * It provides sensible defaults for all frame-like behaviors:
14
+ *
15
+ * - `isFrameLike()` returns `true`
16
+ * - `providesBackgroundForChildren()` returns `true`
17
+ * - `canReceiveNewChildrenOfType()` returns `true` unless the container is locked
18
+ * - `getClipPath()` returns the shape geometry's vertices
19
+ * - `onDragShapesIn()` reparents shapes into the frame (with index restoration)
20
+ * - `onDragShapesOut()` reparents shapes back to the page
21
+ *
22
+ * All methods can be overridden for custom behavior.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * class MyContainerUtil extends BaseFrameLikeShapeUtil<MyContainerShape> {
27
+ * static override type = 'my-container' as const
28
+ * static override props = myContainerShapeProps
29
+ *
30
+ * override getDefaultProps() {
31
+ * return { w: 300, h: 200 }
32
+ * }
33
+ *
34
+ * override component(shape: MyContainerShape) {
35
+ * return <SVGContainer>...</SVGContainer>
36
+ * }
37
+ *
38
+ * override indicator(shape: MyContainerShape) {
39
+ * return <rect width={shape.props.w} height={shape.props.h} />
40
+ * }
41
+ * }
42
+ * ```
43
+ *
44
+ * @public
45
+ */
46
+ export abstract class BaseFrameLikeShapeUtil<
47
+ Shape extends TLBaseBoxShape,
48
+ > extends BaseBoxShapeUtil<Shape> {
49
+ override isFrameLike(_shape: Shape): boolean {
50
+ return true
51
+ }
52
+
53
+ override providesBackgroundForChildren(): boolean {
54
+ return true
55
+ }
56
+
57
+ override canReceiveNewChildrenOfType(shape: Shape, _type: TLShape['type']): boolean {
58
+ return !shape.isLocked
59
+ }
60
+
61
+ override getClipPath(shape: Shape): Vec[] | undefined {
62
+ return this.editor.getShapeGeometry(shape.id).vertices
63
+ }
64
+
65
+ override onDragShapesIn(
66
+ shape: Shape,
67
+ draggingShapes: TLShape[],
68
+ { initialParentIds, initialIndices }: TLDragShapesInInfo
69
+ ): void {
70
+ const { editor } = this
71
+
72
+ if (draggingShapes.every((s) => s.parentId === shape.id)) return
73
+
74
+ // Check to see whether any of the shapes can have their old index restored
75
+ let canRestoreOriginalIndices = false
76
+ const previousChildren = draggingShapes.filter(
77
+ (s) => shape.id === (initialParentIds.get(s.id) as TLShapeId)
78
+ )
79
+
80
+ if (previousChildren.length > 0) {
81
+ const currentChildren = compact(
82
+ editor.getSortedChildIdsForParent(shape).map((id) => editor.getShape(id))
83
+ )
84
+ if (previousChildren.every((s) => !currentChildren.find((c) => c.index === s.index))) {
85
+ canRestoreOriginalIndices = true
86
+ }
87
+ }
88
+
89
+ // If any of the children are the ancestor of the frame, quit here
90
+ if (draggingShapes.some((s) => editor.hasAncestor(shape, s.id))) return
91
+
92
+ editor.reparentShapes(draggingShapes, shape.id)
93
+
94
+ if (canRestoreOriginalIndices) {
95
+ for (const s of previousChildren) {
96
+ editor.updateShape({
97
+ id: s.id,
98
+ type: s.type,
99
+ index: initialIndices.get(s.id) as IndexKey,
100
+ })
101
+ }
102
+ }
103
+ }
104
+
105
+ override onDragShapesOut(
106
+ shape: Shape,
107
+ draggingShapes: TLShape[],
108
+ info: TLDragShapesOutInfo
109
+ ): void {
110
+ const { editor } = this
111
+ // When a user drags shapes out and we're not dragging into a new shape,
112
+ // reparent the dragging shapes onto the current page instead
113
+ if (!info.nextDraggingOverShapeId) {
114
+ // Locked shapes are already filtered out upstream by DragAndDropManager.
115
+ editor.reparentShapes(
116
+ draggingShapes.filter((s) => s.parentId === shape.id),
117
+ editor.getCurrentPageId()
118
+ )
119
+ }
120
+ }
121
+ }
@@ -3,6 +3,7 @@ import { EMPTY_ARRAY } from '@tldraw/state'
3
3
  import { LegacyMigrations, MigrationSequence } from '@tldraw/store'
4
4
  import {
5
5
  RecordProps,
6
+ TLAsset,
6
7
  TLHandle,
7
8
  TLParentId,
8
9
  TLPropsMigrations,
@@ -11,14 +12,15 @@ import {
11
12
  TLShapeId,
12
13
  TLShapePartial,
13
14
  TLUnknownShape,
15
+ VecModel,
14
16
  } from '@tldraw/tlschema'
17
+ import { TLFontFace } from '@tldraw/tlschema'
15
18
  import { IndexKey } from '@tldraw/utils'
16
19
  import { ReactElement } from 'react'
17
20
  import { Box, SelectionHandle } from '../../primitives/Box'
18
21
  import { Geometry2d } from '../../primitives/geometry/Geometry2d'
19
22
  import { Vec } from '../../primitives/Vec'
20
23
  import type { Editor } from '../Editor'
21
- import { TLFontFace } from '../managers/FontManager/FontManager'
22
24
  import { BoundsSnapGeometry } from '../managers/SnapManager/BoundsSnaps'
23
25
  import { HandleSnapGeometry } from '../managers/SnapManager/HandleSnaps'
24
26
  import { TLClickEventInfo } from '../types/event-types'
@@ -31,6 +33,7 @@ export interface TLShapeUtilConstructor<T extends TLShape, U extends ShapeUtil<T
31
33
  type: T['type']
32
34
  props?: RecordProps<T>
33
35
  migrations?: LegacyMigrations | TLPropsMigrations | MigrationSequence
36
+ handledAssetTypes?: readonly string[]
34
37
  }
35
38
 
36
39
  /**
@@ -168,6 +171,16 @@ export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
168
171
  */
169
172
  static type: string
170
173
 
174
+ /**
175
+ * The asset types that this shape can be created from.
176
+ * When a file is dropped on the canvas, the editor finds the shape util
177
+ * whose `handledAssetTypes` includes the asset's type and calls
178
+ * {@link ShapeUtil.createShapeForAsset} to produce the shape.
179
+ *
180
+ * @public
181
+ */
182
+ static handledAssetTypes?: readonly string[]
183
+
171
184
  /**
172
185
  * Get the default props for a shape.
173
186
  *
@@ -175,6 +188,18 @@ export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
175
188
  */
176
189
  abstract getDefaultProps(): Shape['props']
177
190
 
191
+ /**
192
+ * Create a shape partial for placing an asset on the canvas.
193
+ * Only called for shapes whose constructor declares matching
194
+ * {@link ShapeUtil.handledAssetTypes | `handledAssetTypes`}.
195
+ *
196
+ * @param asset - The asset to create a shape for.
197
+ * @param position - Where to place the shape.
198
+ * @returns A shape partial, or null if this shape can't be created for the asset.
199
+ * @public
200
+ */
201
+ createShapeForAsset?(asset: TLAsset, position: VecModel): TLShapePartial | null
202
+
178
203
  /**
179
204
  * Get the shape's geometry.
180
205
  *
@@ -276,7 +301,7 @@ export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
276
301
  *
277
302
  * @public
278
303
  */
279
- canBind(_opts: TLShapeUtilCanBindOpts): boolean {
304
+ canBind(opts: TLShapeUtilCanBindOpts): boolean {
280
305
  return true
281
306
  }
282
307
 
@@ -467,6 +492,17 @@ export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
467
492
  return false
468
493
  }
469
494
 
495
+ /**
496
+ * Whether the shape behaves like a frame — a container that has child shapes,
497
+ * requires full-brush selection, blocks erasure from inside, etc.
498
+ *
499
+ * @param shape - The shape.
500
+ * @public
501
+ */
502
+ isFrameLike(_shape: Shape): boolean {
503
+ return false
504
+ }
505
+
470
506
  /**
471
507
  * By default, the bounds of an image export are the bounds of all the shapes it contains, plus
472
508
  * some padding. If an export includes a shape where `isExportBoundsContainer` is true, then the
@@ -526,7 +562,7 @@ export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
526
562
  * @param type - The shape type.
527
563
  * @public
528
564
  */
529
- canReceiveNewChildrenOfType(shape: Shape, _type: TLShape['type']) {
565
+ canReceiveNewChildrenOfType(shape: Shape, type: TLShape['type']) {
530
566
  return false
531
567
  }
532
568
 
@@ -590,6 +626,17 @@ export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
590
626
  return undefined
591
627
  }
592
628
 
629
+ /**
630
+ * Return user IDs referenced in shape-specific props.
631
+ * Used when copying shapes to include referenced users on the clipboard.
632
+ * Override this if your shape stores user IDs in custom props.
633
+ *
634
+ * @public
635
+ */
636
+ getReferencedUserIds(shape: Shape): string[] {
637
+ return EMPTY_ARRAY
638
+ }
639
+
593
640
  getAriaDescriptor(shape: Shape): string | undefined {
594
641
  return undefined
595
642
  }
@@ -12,7 +12,7 @@ export class GroupShapeUtil extends ShapeUtil<TLGroupShape> {
12
12
  static override props = groupShapeProps
13
13
  static override migrations = groupShapeMigrations
14
14
 
15
- override hideSelectionBoundsFg() {
15
+ override hideSelectionBoundsFg(shape: TLGroupShape) {
16
16
  return true
17
17
  }
18
18
 
@@ -43,6 +43,13 @@ export function getPerfectDashProps(
43
43
  }
44
44
  }
45
45
 
46
+ if (style === 'none') {
47
+ return {
48
+ strokeDasharray: 'none',
49
+ strokeDashoffset: 'none',
50
+ }
51
+ }
52
+
46
53
  switch (style) {
47
54
  case 'dashed': {
48
55
  ratio = 1
@@ -17,20 +17,6 @@ import {
17
17
  TLWheelEventInfo,
18
18
  } from '../types/event-types'
19
19
 
20
- const STATE_NODES_TO_MEASURE = [
21
- 'brushing',
22
- 'cropping',
23
- 'dragging',
24
- 'dragging_handle',
25
- 'drawing',
26
- 'erasing',
27
- 'lasering',
28
- 'resizing',
29
- 'rotating',
30
- 'scribble_brushing',
31
- 'translating',
32
- ]
33
-
34
20
  /** @public */
35
21
  export interface TLStateNodeConstructor {
36
22
  new (editor: Editor, parent?: StateNode): StateNode
@@ -39,6 +25,7 @@ export interface TLStateNodeConstructor {
39
25
  children?(): TLStateNodeConstructor[]
40
26
  isLockable: boolean
41
27
  useCoalescedEvents: boolean
28
+ trackPerformance: boolean
42
29
  }
43
30
 
44
31
  /** @public */
@@ -94,6 +81,8 @@ export abstract class StateNode implements Partial<TLEventHandlers> {
94
81
  static children?: () => TLStateNodeConstructor[]
95
82
  static isLockable = true
96
83
  static useCoalescedEvents = false
84
+ /** Set to `true` in subclasses to emit interaction-start/end performance events when this state is entered/exited. */
85
+ static trackPerformance = false
97
86
 
98
87
  id: string
99
88
  type: 'branch' | 'leaf' | 'root'
@@ -191,8 +180,12 @@ export abstract class StateNode implements Partial<TLEventHandlers> {
191
180
 
192
181
  // todo: move this logic into transition
193
182
  enter(info: any, from: string) {
194
- if (debugFlags.measurePerformance.get() && STATE_NODES_TO_MEASURE.includes(this.id)) {
195
- this.performanceTracker.start(this.id)
183
+ const track = (this.constructor as TLStateNodeConstructor).trackPerformance
184
+ if (track) {
185
+ if (debugFlags.measurePerformance.get()) {
186
+ this.performanceTracker.start(this.id)
187
+ }
188
+ this.editor.performance._notifyInteractionStart(this.id, this.getPath())
196
189
  }
197
190
 
198
191
  this._isActive.set(true)
@@ -207,9 +200,14 @@ export abstract class StateNode implements Partial<TLEventHandlers> {
207
200
 
208
201
  // todo: move this logic into transition
209
202
  exit(info: any, to: string) {
210
- if (debugFlags.measurePerformance.get() && this.performanceTracker.isStarted()) {
211
- this.performanceTracker.stop()
203
+ const track = (this.constructor as TLStateNodeConstructor).trackPerformance
204
+ if (track) {
205
+ if (debugFlags.measurePerformance.get() && this.performanceTracker.isStarted()) {
206
+ this.performanceTracker.stop()
207
+ }
208
+ this.editor.performance._notifyInteractionEnd()
212
209
  }
210
+
213
211
  this._isActive.set(false)
214
212
  this.onExit?.(info, to)
215
213
 
@@ -42,6 +42,11 @@ export interface SvgExportContext {
42
42
  */
43
43
  readonly isDarkMode: boolean
44
44
 
45
+ /**
46
+ * The color mode to use for this export.
47
+ */
48
+ readonly colorMode: 'light' | 'dark'
49
+
45
50
  /**
46
51
  * The scale of the export - how much CSS pixels will be scaled up/down by.
47
52
  */
@@ -1,5 +1,5 @@
1
1
  import { SerializedSchema } from '@tldraw/store'
2
- import { TLAsset, TLBinding, TLShape, TLShapeId } from '@tldraw/tlschema'
2
+ import { TLAsset, TLBinding, TLShape, TLShapeId, TLUser } from '@tldraw/tlschema'
3
3
 
4
4
  /** @public */
5
5
  export interface TLContent {
@@ -8,4 +8,5 @@ export interface TLContent {
8
8
  rootShapeIds: TLShapeId[]
9
9
  assets: TLAsset[]
10
10
  schema: SerializedSchema
11
+ users?: TLUser[]
11
12
  }
@@ -60,6 +60,7 @@ export interface TLFileReplaceExternalContent extends TLBaseExternalContent {
60
60
  type: 'file-replace'
61
61
  file: File
62
62
  shapeId: TLShapeId
63
+ /** @deprecated This field is no longer used by the default handler. It may be removed in a future version. */
63
64
  isImage: boolean
64
65
  }
65
66