@tldraw/editor 4.6.0-next.30b99cd52fc8 → 4.6.0-next.35cf541abcf9

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 (284) hide show
  1. package/dist-cjs/index.d.ts +758 -96
  2. package/dist-cjs/index.js +18 -3
  3. package/dist-cjs/index.js.map +3 -3
  4. package/dist-cjs/lib/TldrawEditor.js +55 -12
  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/createTLStore.js +7 -0
  19. package/dist-cjs/lib/config/createTLStore.js.map +2 -2
  20. package/dist-cjs/lib/config/defaultAssets.js +36 -0
  21. package/dist-cjs/lib/config/defaultAssets.js.map +7 -0
  22. package/dist-cjs/lib/editor/Editor.js +279 -10
  23. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  24. package/dist-cjs/lib/editor/assets/AssetUtil.js +67 -0
  25. package/dist-cjs/lib/editor/assets/AssetUtil.js.map +7 -0
  26. package/dist-cjs/lib/editor/bindings/BindingUtil.js +1 -0
  27. package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +1 -1
  28. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +1 -0
  29. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +1 -1
  30. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +1 -0
  31. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +1 -1
  32. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +1 -0
  33. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +1 -1
  34. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +2 -0
  35. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
  36. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +2 -0
  37. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +1 -1
  38. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +12 -0
  39. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
  40. package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.js +80 -0
  41. package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.js.map +7 -0
  42. package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceManager.js +466 -0
  43. package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceManager.js.map +7 -0
  44. package/dist-cjs/lib/editor/managers/PerformanceManager/perf-types.js +17 -0
  45. package/dist-cjs/lib/editor/managers/PerformanceManager/perf-types.js.map +7 -0
  46. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +1 -0
  47. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +1 -1
  48. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +1 -0
  49. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +1 -1
  50. package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js +1 -0
  51. package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js.map +1 -1
  52. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +2 -1
  53. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
  54. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +1 -0
  55. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +1 -1
  56. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +1 -0
  57. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +1 -1
  58. package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js +107 -0
  59. package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js.map +7 -0
  60. package/dist-cjs/lib/editor/managers/ThemeManager/defaultThemes.js +586 -0
  61. package/dist-cjs/lib/editor/managers/ThemeManager/defaultThemes.js.map +7 -0
  62. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +1 -0
  63. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +1 -1
  64. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +8 -4
  65. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  66. package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js +76 -0
  67. package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js.map +7 -0
  68. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +22 -2
  69. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  70. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +1 -1
  71. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
  72. package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js +6 -0
  73. package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js.map +2 -2
  74. package/dist-cjs/lib/editor/tools/StateNode.js +15 -17
  75. package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
  76. package/dist-cjs/lib/editor/types/SvgExportContext.js.map +2 -2
  77. package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
  78. package/dist-cjs/lib/exports/ExportDelay.js +1 -0
  79. package/dist-cjs/lib/exports/ExportDelay.js.map +1 -1
  80. package/dist-cjs/lib/exports/StyleEmbedder.js +1 -0
  81. package/dist-cjs/lib/exports/StyleEmbedder.js.map +1 -1
  82. package/dist-cjs/lib/exports/getSvgJsx.js +14 -8
  83. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  84. package/dist-cjs/lib/globals/environment.js +18 -1
  85. package/dist-cjs/lib/globals/environment.js.map +2 -2
  86. package/dist-cjs/lib/hooks/useCanvasEvents.js +25 -4
  87. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  88. package/dist-cjs/lib/hooks/{useIsDarkMode.js → useColorMode.js} +14 -10
  89. package/dist-cjs/lib/hooks/useColorMode.js.map +7 -0
  90. package/dist-cjs/lib/hooks/useCursor.js +3 -7
  91. package/dist-cjs/lib/hooks/useCursor.js.map +2 -2
  92. package/dist-cjs/lib/hooks/useDarkMode.js +4 -4
  93. package/dist-cjs/lib/hooks/useDarkMode.js.map +2 -2
  94. package/dist-cjs/lib/options.js +2 -0
  95. package/dist-cjs/lib/options.js.map +2 -2
  96. package/dist-cjs/lib/primitives/Vec.js +3 -0
  97. package/dist-cjs/lib/primitives/Vec.js.map +1 -1
  98. package/dist-cjs/lib/primitives/geometry/Circle2d.js +1 -0
  99. package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +1 -1
  100. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +1 -0
  101. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +1 -1
  102. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +2 -0
  103. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +1 -1
  104. package/dist-cjs/lib/primitives/geometry/Stadium2d.js +1 -0
  105. package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +1 -1
  106. package/dist-cjs/lib/utils/EditorAtom.js +2 -0
  107. package/dist-cjs/lib/utils/EditorAtom.js.map +1 -1
  108. package/dist-cjs/lib/utils/reparenting.js +2 -1
  109. package/dist-cjs/lib/utils/reparenting.js.map +2 -2
  110. package/dist-cjs/lib/utils/richText.js.map +2 -2
  111. package/dist-cjs/lib/utils/runtime.js +2 -1
  112. package/dist-cjs/lib/utils/runtime.js.map +2 -2
  113. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +2 -0
  114. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +1 -1
  115. package/dist-cjs/lib/utils/sync/hardReset.js +0 -8
  116. package/dist-cjs/lib/utils/sync/hardReset.js.map +2 -2
  117. package/dist-cjs/version.js +3 -3
  118. package/dist-cjs/version.js.map +1 -1
  119. package/dist-esm/index.d.mts +758 -96
  120. package/dist-esm/index.mjs +19 -6
  121. package/dist-esm/index.mjs.map +2 -2
  122. package/dist-esm/lib/TldrawEditor.mjs +58 -12
  123. package/dist-esm/lib/TldrawEditor.mjs.map +3 -3
  124. package/dist-esm/lib/components/LiveCollaborators.mjs +1 -0
  125. package/dist-esm/lib/components/LiveCollaborators.mjs.map +2 -2
  126. package/dist-esm/lib/components/MenuClickCapture.mjs +100 -39
  127. package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
  128. package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +10 -3
  129. package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +3 -3
  130. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +5 -2
  131. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  132. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +1 -1
  133. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  134. package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs +1 -0
  135. package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs.map +2 -2
  136. package/dist-esm/lib/config/createTLStore.mjs +10 -1
  137. package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
  138. package/dist-esm/lib/config/defaultAssets.mjs +16 -0
  139. package/dist-esm/lib/config/defaultAssets.mjs.map +7 -0
  140. package/dist-esm/lib/editor/Editor.mjs +279 -10
  141. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  142. package/dist-esm/lib/editor/assets/AssetUtil.mjs +47 -0
  143. package/dist-esm/lib/editor/assets/AssetUtil.mjs.map +7 -0
  144. package/dist-esm/lib/editor/bindings/BindingUtil.mjs +1 -0
  145. package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +1 -1
  146. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +1 -0
  147. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +1 -1
  148. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +1 -0
  149. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +1 -1
  150. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +1 -0
  151. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +1 -1
  152. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +2 -0
  153. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
  154. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +2 -0
  155. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +1 -1
  156. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +12 -0
  157. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
  158. package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.mjs +60 -0
  159. package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.mjs.map +7 -0
  160. package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceManager.mjs +438 -0
  161. package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceManager.mjs.map +7 -0
  162. package/dist-esm/lib/editor/managers/PerformanceManager/perf-types.mjs +1 -0
  163. package/dist-esm/lib/editor/managers/PerformanceManager/perf-types.mjs.map +7 -0
  164. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +1 -0
  165. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +1 -1
  166. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +1 -0
  167. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +1 -1
  168. package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs +1 -0
  169. package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs.map +1 -1
  170. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +2 -1
  171. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
  172. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +1 -0
  173. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +1 -1
  174. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +1 -0
  175. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +1 -1
  176. package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs +89 -0
  177. package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs.map +7 -0
  178. package/dist-esm/lib/editor/managers/ThemeManager/defaultThemes.mjs +568 -0
  179. package/dist-esm/lib/editor/managers/ThemeManager/defaultThemes.mjs.map +7 -0
  180. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +1 -0
  181. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +1 -1
  182. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +8 -4
  183. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  184. package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs +56 -0
  185. package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs.map +7 -0
  186. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +22 -2
  187. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  188. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +1 -1
  189. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
  190. package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs +6 -0
  191. package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs.map +2 -2
  192. package/dist-esm/lib/editor/tools/StateNode.mjs +15 -17
  193. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  194. package/dist-esm/lib/editor/types/SvgExportContext.mjs.map +2 -2
  195. package/dist-esm/lib/exports/ExportDelay.mjs +1 -0
  196. package/dist-esm/lib/exports/ExportDelay.mjs.map +1 -1
  197. package/dist-esm/lib/exports/StyleEmbedder.mjs +1 -0
  198. package/dist-esm/lib/exports/StyleEmbedder.mjs.map +1 -1
  199. package/dist-esm/lib/exports/getSvgJsx.mjs +14 -11
  200. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  201. package/dist-esm/lib/globals/environment.mjs +18 -1
  202. package/dist-esm/lib/globals/environment.mjs.map +2 -2
  203. package/dist-esm/lib/hooks/useCanvasEvents.mjs +25 -4
  204. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  205. package/dist-esm/lib/hooks/useColorMode.mjs +19 -0
  206. package/dist-esm/lib/hooks/useColorMode.mjs.map +7 -0
  207. package/dist-esm/lib/hooks/useCursor.mjs +3 -7
  208. package/dist-esm/lib/hooks/useCursor.mjs.map +2 -2
  209. package/dist-esm/lib/hooks/useDarkMode.mjs +4 -4
  210. package/dist-esm/lib/hooks/useDarkMode.mjs.map +2 -2
  211. package/dist-esm/lib/options.mjs +2 -0
  212. package/dist-esm/lib/options.mjs.map +2 -2
  213. package/dist-esm/lib/primitives/Vec.mjs +3 -0
  214. package/dist-esm/lib/primitives/Vec.mjs.map +1 -1
  215. package/dist-esm/lib/primitives/geometry/Circle2d.mjs +1 -0
  216. package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +1 -1
  217. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +1 -0
  218. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +1 -1
  219. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +2 -0
  220. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +1 -1
  221. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +1 -0
  222. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +1 -1
  223. package/dist-esm/lib/utils/EditorAtom.mjs +2 -0
  224. package/dist-esm/lib/utils/EditorAtom.mjs.map +1 -1
  225. package/dist-esm/lib/utils/reparenting.mjs +2 -1
  226. package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
  227. package/dist-esm/lib/utils/richText.mjs.map +2 -2
  228. package/dist-esm/lib/utils/runtime.mjs +2 -1
  229. package/dist-esm/lib/utils/runtime.mjs.map +2 -2
  230. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +2 -0
  231. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +1 -1
  232. package/dist-esm/lib/utils/sync/hardReset.mjs +0 -8
  233. package/dist-esm/lib/utils/sync/hardReset.mjs.map +2 -2
  234. package/dist-esm/version.mjs +3 -3
  235. package/dist-esm/version.mjs.map +1 -1
  236. package/editor.css +0 -37
  237. package/package.json +7 -7
  238. package/src/index.ts +24 -6
  239. package/src/lib/TldrawEditor.tsx +90 -13
  240. package/src/lib/components/LiveCollaborators.tsx +8 -2
  241. package/src/lib/components/MenuClickCapture.tsx +129 -49
  242. package/src/lib/components/default-components/CanvasShapeIndicators.tsx +14 -3
  243. package/src/lib/components/default-components/DefaultCanvas.tsx +6 -2
  244. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +2 -2
  245. package/src/lib/components/default-components/DefaultShapeIndicators.tsx +2 -0
  246. package/src/lib/config/createTLStore.ts +22 -1
  247. package/src/lib/config/defaultAssets.ts +19 -0
  248. package/src/lib/editor/Editor.ts +387 -40
  249. package/src/lib/editor/assets/AssetUtil.ts +85 -0
  250. package/src/lib/editor/managers/FontManager/FontManager.test.ts +9 -2
  251. package/src/lib/editor/managers/FontManager/FontManager.ts +1 -67
  252. package/src/lib/editor/managers/InputsManager/InputsManager.ts +12 -0
  253. package/src/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.ts +82 -0
  254. package/src/lib/editor/managers/PerformanceManager/PerformanceManager.test.ts +522 -0
  255. package/src/lib/editor/managers/PerformanceManager/PerformanceManager.ts +583 -0
  256. package/src/lib/editor/managers/PerformanceManager/perf-types.ts +196 -0
  257. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +13 -2
  258. package/src/lib/editor/managers/SnapManager/SnapManager.ts +1 -1
  259. package/src/lib/editor/managers/ThemeManager/ThemeManager.ts +116 -0
  260. package/src/lib/editor/managers/ThemeManager/defaultThemes.ts +605 -0
  261. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +23 -29
  262. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +5 -3
  263. package/src/lib/editor/shapes/BaseFrameLikeShapeUtil.tsx +121 -0
  264. package/src/lib/editor/shapes/ShapeUtil.ts +39 -3
  265. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +1 -1
  266. package/src/lib/editor/shapes/shared/getPerfectDashProps.ts +7 -0
  267. package/src/lib/editor/tools/StateNode.ts +16 -18
  268. package/src/lib/editor/types/SvgExportContext.tsx +5 -0
  269. package/src/lib/editor/types/external-content.ts +1 -0
  270. package/src/lib/exports/getSvgJsx.tsx +23 -16
  271. package/src/lib/globals/environment.ts +18 -0
  272. package/src/lib/hooks/useCanvasEvents.ts +40 -3
  273. package/src/lib/hooks/{useIsDarkMode.ts → useColorMode.ts} +9 -5
  274. package/src/lib/hooks/useCursor.ts +3 -7
  275. package/src/lib/hooks/useDarkMode.ts +4 -4
  276. package/src/lib/options.ts +14 -0
  277. package/src/lib/utils/reparenting.ts +6 -2
  278. package/src/lib/utils/richText.ts +1 -1
  279. package/src/lib/utils/runtime.ts +3 -1
  280. package/src/lib/utils/sync/hardReset.ts +0 -8
  281. package/src/version.ts +3 -3
  282. package/dist-cjs/lib/hooks/useIsDarkMode.js.map +0 -7
  283. package/dist-esm/lib/hooks/useIsDarkMode.mjs +0 -15
  284. package/dist-esm/lib/hooks/useIsDarkMode.mjs.map +0 -7
@@ -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',
@@ -12,7 +12,7 @@ export class UserPreferencesManager {
12
12
  }
13
13
  constructor(
14
14
  private readonly user: TLCurrentUser,
15
- private readonly inferDarkMode: boolean
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
 
@@ -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
  */
@@ -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
 
@@ -1,11 +1,6 @@
1
1
  import { useAtom, useValue } from '@tldraw/state-react'
2
- import {
3
- TLFrameShape,
4
- TLShape,
5
- TLShapeId,
6
- getColorValue,
7
- getDefaultColorTheme,
8
- } from '@tldraw/tlschema'
2
+ import { TLFrameShape, TLShape, TLShapeId } from '@tldraw/tlschema'
3
+ import { TLFontFace } from '@tldraw/tlschema'
9
4
  import { hasOwnProperty, promiseWithResolve, uniqueId } from '@tldraw/utils'
10
5
  import {
11
6
  ComponentType,
@@ -21,7 +16,7 @@ import { flushSync } from 'react-dom'
21
16
  import { ErrorBoundary } from '../components/ErrorBoundary'
22
17
  import { InnerShape, InnerShapeBackground } from '../components/Shape'
23
18
  import type { Editor, TLRenderingShape } from '../editor/Editor'
24
- import { TLFontFace } from '../editor/managers/FontManager/FontManager'
19
+ import { getColorValue } from '../editor/managers/ThemeManager/defaultThemes'
25
20
  import { ShapeUtil } from '../editor/shapes/ShapeUtil'
26
21
  import { TLImageExportOptions } from '../editor/types/misc-types'
27
22
  import {
@@ -54,7 +49,9 @@ export function getSvgJsx(editor: Editor, ids: TLShapeId[], opts: TLImageExportO
54
49
  const renderPadding =
55
50
  typeof opts.padding === 'number' ? opts.padding : editor.options.defaultSvgPadding
56
51
 
57
- const isDarkMode = opts.darkMode ?? editor.user.getIsDarkMode()
52
+ const colorMode: 'light' | 'dark' =
53
+ opts.darkMode !== undefined ? (opts.darkMode ? 'dark' : 'light') : editor.getColorMode()
54
+ const isDarkMode = colorMode === 'dark'
58
55
 
59
56
  // ---Figure out which shapes we need to include
60
57
  const shapeIdsToInclude = editor.getShapeAndDescendantIds(ids)
@@ -63,8 +60,9 @@ export function getSvgJsx(editor: Editor, ids: TLShapeId[], opts: TLImageExportO
63
60
  .filter(({ id }) => shapeIdsToInclude.has(id))
64
61
 
65
62
  // --- Common bounding box of all shapes
63
+ const singleFrameShape = ids.length === 1 ? editor.getShape(ids[0]) : null
66
64
  const singleFrameShapeId =
67
- ids.length === 1 && editor.isShapeOfType(editor.getShape(ids[0])!, 'frame') ? ids[0] : null
65
+ singleFrameShape && editor.isShapeFrameLike(singleFrameShape) ? ids[0] : null
68
66
 
69
67
  let bbox: null | Box = null
70
68
  let paddingWasApplied = false
@@ -116,6 +114,7 @@ export function getSvgJsx(editor: Editor, ids: TLShapeId[], opts: TLImageExportO
116
114
  background={background}
117
115
  singleFrameShapeId={singleFrameShapeId}
118
116
  isDarkMode={isDarkMode}
117
+ colorMode={colorMode}
119
118
  renderingShapes={renderingShapes}
120
119
  onMount={initialEffectPromise.resolve}
121
120
  waitUntil={exportDelay.waitUntil}
@@ -206,6 +205,7 @@ function SvgExport({
206
205
  background,
207
206
  singleFrameShapeId,
208
207
  isDarkMode,
208
+ colorMode,
209
209
  renderingShapes,
210
210
  onMount,
211
211
  waitUntil,
@@ -218,12 +218,13 @@ function SvgExport({
218
218
  background: boolean
219
219
  singleFrameShapeId: TLShapeId | null
220
220
  isDarkMode: boolean
221
+ colorMode: 'light' | 'dark'
221
222
  renderingShapes: TLRenderingShape[]
222
223
  onMount(): void
223
224
  waitUntil(promise: Promise<void>): void
224
225
  }) {
225
226
  const masksId = useUniqueSafeId()
226
- const theme = getDefaultColorTheme({ isDarkMode })
227
+ const theme = editor.getCurrentTheme()
227
228
 
228
229
  const stateAtom = useAtom<{
229
230
  defsById: Record<
@@ -257,6 +258,7 @@ function SvgExport({
257
258
  const exportContext = useMemo(
258
259
  (): SvgExportContext => ({
259
260
  isDarkMode,
261
+ colorMode,
260
262
  waitUntil,
261
263
  addExportDef,
262
264
  scale,
@@ -272,7 +274,7 @@ function SvgExport({
272
274
  })
273
275
  },
274
276
  }),
275
- [isDarkMode, waitUntil, addExportDef, scale, pixelRatio, editor]
277
+ [isDarkMode, colorMode, waitUntil, addExportDef, scale, pixelRatio, editor]
276
278
  )
277
279
 
278
280
  const didRenderRef = useRef(false)
@@ -443,17 +445,22 @@ function SvgExport({
443
445
  onMount()
444
446
  }, [onMount, shapeElements])
445
447
 
446
- let backgroundColor = background ? theme.background : 'transparent'
448
+ const colors = theme.colors[colorMode]
449
+ let backgroundColor = background ? colors.background : 'transparent'
447
450
 
448
451
  if (singleFrameShapeId && background) {
449
452
  const frameShapeUtil = editor.getShapeUtil('frame') as any as
450
453
  | undefined
451
- | { options: { showColors: boolean } }
454
+ | {
455
+ options: {
456
+ showColors: boolean
457
+ }
458
+ }
452
459
  if (frameShapeUtil?.options.showColors) {
453
460
  const shape = editor.getShape(singleFrameShapeId)! as TLFrameShape
454
- backgroundColor = getColorValue(theme, shape.props.color, 'frameFill')
461
+ backgroundColor = getColorValue(colors, shape.props.color, 'frameFill')
455
462
  } else {
456
- backgroundColor = theme.solid
463
+ backgroundColor = colors.solid
457
464
  }
458
465
  }
459
466