@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
@@ -25,8 +25,10 @@ import {
25
25
  PageRecordType,
26
26
  TLDOCUMENT_ID,
27
27
  TLINSTANCE_ID,
28
+ UserRecordType,
28
29
  createBindingId,
29
30
  createShapeId,
31
+ createUserId,
30
32
  getShapePropKeysByStyle,
31
33
  isPageId,
32
34
  isShapeId
@@ -62,7 +64,8 @@ import {
62
64
  uniqueId
63
65
  } from "@tldraw/utils";
64
66
  import EventEmitter from "eventemitter3";
65
- import { createTLUser } from "../config/createTLUser.mjs";
67
+ import { createTLCurrentUser } from "../config/createTLCurrentUser.mjs";
68
+ import { checkAssets } from "../config/defaultAssets.mjs";
66
69
  import { checkBindings } from "../config/defaultBindings.mjs";
67
70
  import { checkShapesAndAddCore } from "../config/defaultShapes.mjs";
68
71
  import {
@@ -113,10 +116,12 @@ import { FocusManager } from "./managers/FocusManager/FocusManager.mjs";
113
116
  import { FontManager } from "./managers/FontManager/FontManager.mjs";
114
117
  import { HistoryManager } from "./managers/HistoryManager/HistoryManager.mjs";
115
118
  import { InputsManager } from "./managers/InputsManager/InputsManager.mjs";
119
+ import { PerformanceManager } from "./managers/PerformanceManager/PerformanceManager.mjs";
116
120
  import { ScribbleManager } from "./managers/ScribbleManager/ScribbleManager.mjs";
117
121
  import { SnapManager } from "./managers/SnapManager/SnapManager.mjs";
118
122
  import { SpatialIndexManager } from "./managers/SpatialIndexManager/SpatialIndexManager.mjs";
119
123
  import { TextManager } from "./managers/TextManager/TextManager.mjs";
124
+ import { ThemeManager, resolveThemes } from "./managers/ThemeManager/ThemeManager.mjs";
120
125
  import { TickManager } from "./managers/TickManager/TickManager.mjs";
121
126
  import { UserPreferencesManager } from "./managers/UserPreferencesManager/UserPreferencesManager.mjs";
122
127
  import { RootState } from "./tools/RootState.mjs";
@@ -127,6 +132,7 @@ class Editor extends EventEmitter {
127
132
  user,
128
133
  shapeUtils,
129
134
  bindingUtils,
135
+ assetUtils: assetUtilConstructors,
130
136
  tools,
131
137
  getContainer,
132
138
  // needs to be here for backwards compatibility with TldrawEditor
@@ -134,13 +140,15 @@ class Editor extends EventEmitter {
134
140
  cameraOptions,
135
141
  initialState,
136
142
  autoFocus,
137
- inferDarkMode,
138
143
  options: _options,
139
144
  // needs to be here for backwards compatibility with TldrawEditor
140
145
  // eslint-disable-next-line @typescript-eslint/no-deprecated
141
146
  textOptions: _textOptions,
142
147
  getShapeVisibility,
143
- fontAssetUrls
148
+ colorScheme,
149
+ fontAssetUrls,
150
+ themes,
151
+ initialTheme
144
152
  }) {
145
153
  super();
146
154
  this._getShapeVisibility = getShapeVisibility;
@@ -163,15 +171,27 @@ class Editor extends EventEmitter {
163
171
  ...cameraOptions,
164
172
  ...options?.camera
165
173
  });
174
+ this.getContainer = getContainer;
166
175
  this._textOptions = atom("text options", options?.text ?? null);
167
- this.user = new UserPreferencesManager(user ?? createTLUser(), inferDarkMode ?? false);
176
+ this.user = new UserPreferencesManager(user ?? createTLCurrentUser(), colorScheme ?? "light");
168
177
  this.disposables.add(() => this.user.dispose());
169
- this.getContainer = getContainer;
170
178
  this.textMeasure = new TextManager(this);
171
179
  this.disposables.add(() => this.textMeasure.dispose());
172
- this.fonts = new FontManager(this, fontAssetUrls);
180
+ this._themeManager = new ThemeManager(this, {
181
+ themes: resolveThemes(themes),
182
+ initial: initialTheme ?? "default"
183
+ });
184
+ this.disposables.add(() => this._themeManager.dispose());
173
185
  this._tickManager = new TickManager(this);
186
+ this.disposables.add(() => this._tickManager.dispose());
187
+ this.disposables.add(() => {
188
+ this.off("tick", this._decayCameraStateTimeout);
189
+ this._setCameraState("idle");
190
+ });
191
+ this.fonts = new FontManager(this, fontAssetUrls);
174
192
  this.inputs = new InputsManager(this);
193
+ this.performance = new PerformanceManager(this);
194
+ this.disposables.add(() => this.performance.dispose());
175
195
  class NewRoot extends RootState {
176
196
  static initial = initialState ?? "";
177
197
  }
@@ -199,6 +219,16 @@ class Editor extends EventEmitter {
199
219
  }
200
220
  this.shapeUtils = _shapeUtils;
201
221
  this.styleProps = _styleProps;
222
+ const _shapeUtilsByAssetType = {};
223
+ for (const Util of allShapeUtils) {
224
+ const assetTypes = Util.handledAssetTypes;
225
+ if (assetTypes) {
226
+ for (const assetType of assetTypes) {
227
+ _shapeUtilsByAssetType[assetType] = _shapeUtils[Util.type];
228
+ }
229
+ }
230
+ }
231
+ this._shapeUtilsByAssetType = _shapeUtilsByAssetType;
202
232
  const allBindingUtils = checkBindings(bindingUtils);
203
233
  const _bindingUtils = {};
204
234
  for (const Util of allBindingUtils) {
@@ -206,6 +236,15 @@ class Editor extends EventEmitter {
206
236
  _bindingUtils[Util.type] = util;
207
237
  }
208
238
  this.bindingUtils = _bindingUtils;
239
+ if (assetUtilConstructors) {
240
+ const allAssetUtils = checkAssets(assetUtilConstructors);
241
+ const _assetUtils = {};
242
+ for (const Util of allAssetUtils) {
243
+ const util = new Util(this);
244
+ _assetUtils[Util.type] = util;
245
+ }
246
+ this.assetUtils = _assetUtils;
247
+ }
209
248
  for (const Tool of [...tools]) {
210
249
  if (hasOwnProperty(this.root.children, Tool.id)) {
211
250
  throw Error(`Can't override tool with id "${Tool.id}"`);
@@ -547,6 +586,14 @@ class Editor extends EventEmitter {
547
586
  })
548
587
  );
549
588
  }
589
+ this.disposables.add(
590
+ react("sync current user record", () => {
591
+ const user2 = this.store.props.users.currentUser.get();
592
+ if (user2) {
593
+ this._ensureUserRecord(user2);
594
+ }
595
+ })
596
+ );
550
597
  }
551
598
  _getShapeVisibility;
552
599
  getIsShapeHiddenCache() {
@@ -638,6 +685,17 @@ class Editor extends EventEmitter {
638
685
  * @public
639
686
  */
640
687
  snaps;
688
+ /**
689
+ * A manager for performance measurement hooks.
690
+ *
691
+ * @public
692
+ */
693
+ performance;
694
+ /**
695
+ * A manager for the spatial index, tracking where shapes exist on the canvas.
696
+ *
697
+ * @internal
698
+ */
641
699
  _spatialIndex;
642
700
  /**
643
701
  * A manager for the any asynchronous events and making sure they're
@@ -652,6 +710,12 @@ class Editor extends EventEmitter {
652
710
  * @public
653
711
  */
654
712
  user;
713
+ /**
714
+ * A manager for the editor's themes.
715
+ *
716
+ * @internal
717
+ */
718
+ _themeManager;
655
719
  /**
656
720
  * A helper for measuring text.
657
721
  *
@@ -723,12 +787,117 @@ class Editor extends EventEmitter {
723
787
  * @public
724
788
  */
725
789
  dispose() {
790
+ this.stopCameraAnimation();
791
+ if (this.getInstanceState().followingUserId) {
792
+ this.stopFollowingUser();
793
+ }
726
794
  this.disposables.forEach((dispose) => dispose());
727
795
  this.disposables.clear();
796
+ this.menus.clearOpenMenus();
728
797
  this.store.dispose();
729
798
  this.isDisposed = true;
730
799
  this.emit("dispose");
731
800
  }
801
+ /* ------------------ Themes (shadowing the theme manager) ------------------ */
802
+ /**
803
+ * Get the current color mode (`'light'` or `'dark'`), based on the user's dark mode preference.
804
+ *
805
+ * @public
806
+ */
807
+ getColorMode() {
808
+ return this._themeManager.getColorMode();
809
+ }
810
+ /**
811
+ * Set the color mode. Note that this is a convenience method that passes the mode to
812
+ * `user.updateUserPreferences`, which is the source of truth for the user's color mode preference.
813
+ *
814
+ * @public
815
+ */
816
+ setColorMode(mode) {
817
+ this.user.updateUserPreferences({ colorScheme: mode });
818
+ return this;
819
+ }
820
+ /**
821
+ * Get the id of the current theme.
822
+ *
823
+ * @public
824
+ */
825
+ getCurrentThemeId() {
826
+ return this._themeManager.getCurrentThemeId();
827
+ }
828
+ /**
829
+ * Get the current theme definition.
830
+ *
831
+ * @public
832
+ */
833
+ getCurrentTheme() {
834
+ return this._themeManager.getCurrentTheme();
835
+ }
836
+ /**
837
+ * Set the current theme by id.
838
+ *
839
+ * @public
840
+ */
841
+ setCurrentTheme(id) {
842
+ this._themeManager.setCurrentTheme(id);
843
+ return this;
844
+ }
845
+ /**
846
+ * Get all registered theme definitions.
847
+ *
848
+ * @public
849
+ */
850
+ getThemes() {
851
+ return this._themeManager.getThemes();
852
+ }
853
+ /**
854
+ * Get a single theme definition by id.
855
+ *
856
+ * @public
857
+ */
858
+ getTheme(id) {
859
+ return this._themeManager.getTheme(id);
860
+ }
861
+ /**
862
+ * Replace all theme definitions, or update them via a callback that receives a deep copy.
863
+ * The `'default'` theme must always be present in the result.
864
+ *
865
+ * @example
866
+ * ```ts
867
+ * // Replace all themes
868
+ * editor.updateThemes({ default: myDefaultTheme, ocean: myOceanTheme })
869
+ *
870
+ * // Update via callback
871
+ * editor.updateThemes((themes) => {
872
+ * delete themes.ocean
873
+ * return themes
874
+ * })
875
+ * ```
876
+ *
877
+ * @public
878
+ */
879
+ updateThemes(themes) {
880
+ this._themeManager.updateThemes(themes);
881
+ return this;
882
+ }
883
+ /**
884
+ * Register or update a single theme definition. The theme is keyed by its `id` property.
885
+ *
886
+ * @example
887
+ * ```ts
888
+ * // Override a property on the default theme
889
+ * editor.updateTheme({ ...editor.getTheme('default')!, fontSize: 24 })
890
+ *
891
+ * // Register a new theme
892
+ * editor.updateTheme({ id: 'ocean', ...myOceanTheme })
893
+ * ```
894
+ *
895
+ * @public
896
+ */
897
+ updateTheme(theme) {
898
+ this._themeManager.updateTheme(theme);
899
+ return this;
900
+ }
732
901
  /* ------------------- Shape Utils ------------------ */
733
902
  /**
734
903
  * A map of shape utility classes (TLShapeUtils) by shape type.
@@ -736,6 +905,8 @@ class Editor extends EventEmitter {
736
905
  * @public
737
906
  */
738
907
  shapeUtils;
908
+ /** @internal */
909
+ _shapeUtilsByAssetType = {};
739
910
  styleProps;
740
911
  getShapeUtil(arg) {
741
912
  const type = typeof arg === "string" ? arg : arg.type;
@@ -747,6 +918,17 @@ class Editor extends EventEmitter {
747
918
  const type = typeof arg === "string" ? arg : arg.type;
748
919
  return hasOwnProperty(this.shapeUtils, type);
749
920
  }
921
+ /**
922
+ * Get the shape util that handles the given asset type.
923
+ * Returns the shape util whose {@link ShapeUtil.handledAssetTypes} includes
924
+ * the given asset type, or undefined if none matches.
925
+ *
926
+ * @param assetType - The asset type string.
927
+ * @public
928
+ */
929
+ getShapeUtilForAssetType(assetType) {
930
+ return getOwnProperty(this._shapeUtilsByAssetType, assetType);
931
+ }
750
932
  /* ------------------- Binding Utils ------------------ */
751
933
  /**
752
934
  * A map of shape utility classes (TLShapeUtils) by shape type.
@@ -760,6 +942,42 @@ class Editor extends EventEmitter {
760
942
  assert(bindingUtil, `No binding util found for type "${type}"`);
761
943
  return bindingUtil;
762
944
  }
945
+ /* ------------------- Asset Utils ------------------ */
946
+ /**
947
+ * A map of asset utility classes by asset type.
948
+ *
949
+ * @public
950
+ */
951
+ assetUtils = {};
952
+ getAssetUtil(arg) {
953
+ const type = typeof arg === "string" ? arg : arg.type;
954
+ const assetUtil = getOwnProperty(this.assetUtils, type);
955
+ assert(assetUtil, `No asset util found for type "${type}"`);
956
+ return assetUtil;
957
+ }
958
+ /**
959
+ * Returns true if the editor has an asset util for the given asset type.
960
+ *
961
+ * @public
962
+ */
963
+ hasAssetUtil(arg) {
964
+ const type = typeof arg === "string" ? arg : arg.type;
965
+ return hasOwnProperty(this.assetUtils, type);
966
+ }
967
+ /**
968
+ * Get the asset util that accepts the given MIME type.
969
+ * Returns null if no registered asset util accepts the MIME type.
970
+ *
971
+ * @public
972
+ */
973
+ getAssetUtilForMimeType(mimeType) {
974
+ for (const util of Object.values(this.assetUtils)) {
975
+ if (util && util.acceptsMimeType(mimeType)) {
976
+ return util;
977
+ }
978
+ }
979
+ return null;
980
+ }
763
981
  /* --------------------- History -------------------- */
764
982
  /**
765
983
  * A manager for the editor's history.
@@ -781,6 +999,7 @@ class Editor extends EventEmitter {
781
999
  this._flushEventsForTick(0);
782
1000
  this.complete();
783
1001
  this.history.undo();
1002
+ this.performance._notifyUndoRedo("undo", this.history.getNumUndos(), this.history.getNumRedos());
784
1003
  return this;
785
1004
  }
786
1005
  canUndo() {
@@ -803,6 +1022,7 @@ class Editor extends EventEmitter {
803
1022
  this._flushEventsForTick(0);
804
1023
  this.complete();
805
1024
  this.history.redo();
1025
+ this.performance._notifyUndoRedo("redo", this.history.getNumUndos(), this.history.getNumRedos());
806
1026
  return this;
807
1027
  }
808
1028
  canRedo() {
@@ -2853,6 +3073,76 @@ class Editor extends EventEmitter {
2853
3073
  const currentPageId = this.getCurrentPageId();
2854
3074
  return this.getCollaborators().filter((c) => c.currentPageId === currentPageId);
2855
3075
  }
3076
+ // Attribution
3077
+ /**
3078
+ * Get the current user's ID for attribution purposes.
3079
+ * Also ensures a `user:` record exists in the store for the current user.
3080
+ * Returns `null` when the user store has no current user.
3081
+ *
3082
+ * @public
3083
+ */
3084
+ getAttributionUserId() {
3085
+ const user = this.store.props.users.currentUser.get();
3086
+ if (!user) return null;
3087
+ this._ensureUserRecord(user);
3088
+ return UserRecordType.parseId(user.id);
3089
+ }
3090
+ /**
3091
+ * Ensure a user record exists in the store for the given user,
3092
+ * updating it if the data has changed.
3093
+ *
3094
+ * @internal
3095
+ */
3096
+ _ensureUserRecord(user) {
3097
+ const existing = this.store.get(user.id);
3098
+ if (existing && existing.name === user.name && existing.color === user.color && existing.imageUrl === user.imageUrl && existing.meta === user.meta) {
3099
+ return;
3100
+ }
3101
+ this.run(
3102
+ () => {
3103
+ this.store.put([user]);
3104
+ },
3105
+ { history: "ignore" }
3106
+ );
3107
+ }
3108
+ /**
3109
+ * Resolve a display name for a user ID. Asks the
3110
+ * {@link @tldraw/tlschema#TLUserStore} first (the app's source of truth),
3111
+ * falling back to the `user:` record in the store.
3112
+ *
3113
+ * @public
3114
+ */
3115
+ getAttributionDisplayName(userId) {
3116
+ if (!userId) return null;
3117
+ return this.store.props.users.resolve(userId).get()?.name ?? this.store.get(createUserId(userId))?.name ?? null;
3118
+ }
3119
+ /**
3120
+ * Resolve a user record by ID. Asks the
3121
+ * {@link @tldraw/tlschema#TLUserStore} first (the app's source of truth),
3122
+ * falling back to the `user:` record in the store.
3123
+ *
3124
+ * @public
3125
+ */
3126
+ getAttributionUser(userId) {
3127
+ if (!userId) return null;
3128
+ return this.store.props.users.resolve(userId).get() ?? this.store.get(createUserId(userId)) ?? null;
3129
+ }
3130
+ /**
3131
+ * Collect user IDs referenced by a set of shapes via shape-specific props
3132
+ * (e.g. `textFirstEditedBy` on notes).
3133
+ *
3134
+ * @internal
3135
+ */
3136
+ _getReferencedUserIds(shapes) {
3137
+ const userIds = /* @__PURE__ */ new Set();
3138
+ for (const shape of shapes) {
3139
+ const util = this.getShapeUtil(shape);
3140
+ for (const id of util.getReferencedUserIds(shape)) {
3141
+ userIds.add(id);
3142
+ }
3143
+ }
3144
+ return userIds;
3145
+ }
2856
3146
  // Following
2857
3147
  // When we are 'locked on' to a user, our camera is derived from their camera.
2858
3148
  _isLockedOnFollowingUser = atom("isLockedOnFollowingUser", false);
@@ -3887,7 +4177,7 @@ class Editor extends EventEmitter {
3887
4177
  const searchMargin = Math.max(innerMargin, outerMargin, this.options.hitTestMargin / zoomLevel);
3888
4178
  const candidateIds = this._spatialIndex.getShapeIdsAtPoint(point, searchMargin);
3889
4179
  const shapesToCheck = (opts.renderingOnly ? this.getCurrentPageRenderingShapesSorted() : this.getCurrentPageShapesSorted()).filter((shape) => {
3890
- if (!candidateIds.has(shape.id) && !this.isShapeOfType(shape, "frame")) return false;
4180
+ if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) return false;
3891
4181
  if (shape.isLocked && !hitLocked || this.isShapeHidden(shape) || this.isShapeOfType(shape, "group"))
3892
4182
  return false;
3893
4183
  const pageMask = this.getShapeMask(shape);
@@ -3900,14 +4190,16 @@ class Editor extends EventEmitter {
3900
4190
  const geometry = this.getShapeGeometry(shape);
3901
4191
  const isGroup = geometry instanceof Group2d;
3902
4192
  const pointInShapeSpace = this.getPointInShapeSpace(shape, point);
3903
- if (this.isShapeOfType(shape, "frame") || (this.isShapeOfType(shape, "note") || this.isShapeOfType(shape, "arrow") || this.isShapeOfType(shape, "geo") && shape.props.fill === "none") && this.getShapeUtil(shape).getText(shape)?.trim()) {
4193
+ const shapeUtil = this.getShapeUtil(shape);
4194
+ const isShapeFrameLike = this.isShapeFrameLike(shape);
4195
+ if (isShapeFrameLike || (this.isShapeOfType(shape, "note") || this.isShapeOfType(shape, "arrow") || this.isShapeOfType(shape, "geo") && shape.props.fill === "none") && shapeUtil.getText(shape)?.trim()) {
3904
4196
  for (const childGeometry of geometry.children) {
3905
4197
  if (childGeometry.isLabel && childGeometry.isPointInBounds(pointInShapeSpace)) {
3906
4198
  return shape;
3907
4199
  }
3908
4200
  }
3909
4201
  }
3910
- if (this.isShapeOfType(shape, "frame")) {
4202
+ if (isShapeFrameLike) {
3911
4203
  const distance2 = geometry.distanceToPoint(pointInShapeSpace, hitFrameInside);
3912
4204
  if (hitFrameInside ? distance2 > 0 && distance2 <= outerMargin || distance2 <= 0 && distance2 > -innerMargin : distance2 > 0 && distance2 <= outerMargin) {
3913
4205
  return inMarginClosestToEdgeHit || shape;
@@ -4001,7 +4293,7 @@ class Editor extends EventEmitter {
4001
4293
  const candidateIds = this._spatialIndex.getShapeIdsAtPoint(point, margin);
4002
4294
  return this.getCurrentPageShapesSorted().filter((shape) => {
4003
4295
  if (this.isShapeHidden(shape)) return false;
4004
- if (!candidateIds.has(shape.id) && !this.isShapeOfType(shape, "frame")) return false;
4296
+ if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) return false;
4005
4297
  return this.isPointInShape(shape, point, opts);
4006
4298
  }).reverse();
4007
4299
  }
@@ -4114,6 +4406,24 @@ class Editor extends EventEmitter {
4114
4406
  if (!shape) return false;
4115
4407
  return shape.type === type;
4116
4408
  }
4409
+ /**
4410
+ * Get whether a shape behaves like a frame — a container that has child
4411
+ * shapes, requires full-brush selection, blocks erasure from inside, etc.
4412
+ *
4413
+ * @example
4414
+ * ```ts
4415
+ * const isFrameLike = editor.isShapeFrameLike(someShape)
4416
+ * ```
4417
+ *
4418
+ * @param shape - The shape (or shape id) to test.
4419
+ *
4420
+ * @public
4421
+ */
4422
+ isShapeFrameLike(shape) {
4423
+ const _shape = typeof shape === "string" ? this.getShape(shape) : shape;
4424
+ if (!_shape) return false;
4425
+ return this.getShapeUtil(_shape).isFrameLike(_shape);
4426
+ }
4117
4427
  /**
4118
4428
  * Get a shape by its id.
4119
4429
  *
@@ -6566,12 +6876,22 @@ class Editor extends EventEmitter {
6566
6876
  if (!asset) continue;
6567
6877
  assets.push(asset);
6568
6878
  }
6879
+ const users = [];
6880
+ const seenUserIds = /* @__PURE__ */ new Set();
6881
+ for (const userId of this._getReferencedUserIds(shapes2)) {
6882
+ const recordId = createUserId(userId);
6883
+ if (seenUserIds.has(recordId)) continue;
6884
+ seenUserIds.add(recordId);
6885
+ const user = this.store.get(recordId);
6886
+ if (user) users.push(user);
6887
+ }
6569
6888
  return {
6570
6889
  schema: this.store.schema.serialize(),
6571
6890
  shapes: shapes2,
6572
6891
  rootShapeIds,
6573
6892
  bindings,
6574
- assets
6893
+ assets,
6894
+ users
6575
6895
  };
6576
6896
  });
6577
6897
  }
@@ -6621,13 +6941,15 @@ class Editor extends EventEmitter {
6621
6941
  const assets = [];
6622
6942
  const shapes = [];
6623
6943
  const bindings = [];
6944
+ const users = [];
6624
6945
  const store = {
6625
6946
  store: {
6626
6947
  ...Object.fromEntries(content.assets.map((asset) => [asset.id, asset])),
6627
6948
  ...Object.fromEntries(content.shapes.map((shape) => [shape.id, shape])),
6628
6949
  ...Object.fromEntries(
6629
6950
  content.bindings?.map((bindings2) => [bindings2.id, bindings2]) ?? []
6630
- )
6951
+ ),
6952
+ ...Object.fromEntries(content.users?.map((user) => [user.id, user]) ?? [])
6631
6953
  },
6632
6954
  schema: content.schema
6633
6955
  };
@@ -6649,6 +6971,19 @@ class Editor extends EventEmitter {
6649
6971
  bindings.push(record);
6650
6972
  break;
6651
6973
  }
6974
+ case "user": {
6975
+ users.push(record);
6976
+ break;
6977
+ }
6978
+ }
6979
+ }
6980
+ if (users.length > 0) {
6981
+ const existingUserIds = new Set(
6982
+ this.store.allRecords().filter((r) => r.typeName === "user").map((r) => r.id)
6983
+ );
6984
+ const usersToCreate = users.filter((u) => !existingUserIds.has(u.id));
6985
+ if (usersToCreate.length > 0) {
6986
+ this.store.put(usersToCreate);
6652
6987
  }
6653
6988
  }
6654
6989
  const shapeIdMap = new Map(
@@ -7614,6 +7949,7 @@ class Editor extends EventEmitter {
7614
7949
  ),
7615
7950
  { immediate: true }
7616
7951
  );
7952
+ this.performance._notifyCameraOperation("zooming");
7617
7953
  this.emit("event", info);
7618
7954
  return;
7619
7955
  }
@@ -7675,6 +8011,7 @@ class Editor extends EventEmitter {
7675
8011
  immediate: true
7676
8012
  });
7677
8013
  this.maybeTrackPerformance("Zooming");
8014
+ this.performance._notifyCameraOperation("zooming");
7678
8015
  this.root.handleEvent(info);
7679
8016
  this.emit("event", info);
7680
8017
  return;
@@ -7684,6 +8021,7 @@ class Editor extends EventEmitter {
7684
8021
  immediate: true
7685
8022
  });
7686
8023
  this.maybeTrackPerformance("Panning");
8024
+ this.performance._notifyCameraOperation("panning");
7687
8025
  this.root.handleEvent(info);
7688
8026
  this.emit("event", info);
7689
8027
  return;
@@ -7730,6 +8068,10 @@ class Editor extends EventEmitter {
7730
8068
  }
7731
8069
  this.inputs.setIsPanning(true);
7732
8070
  clearTimeout(this._longPressTimeout);
8071
+ } else if (info.button === RIGHT_MOUSE_BUTTON && this.options.rightClickPanning) {
8072
+ this.inputs.setIsRightPointing(true);
8073
+ clearTimeout(this._longPressTimeout);
8074
+ return this;
7733
8075
  }
7734
8076
  if (this.inputs.getIsPanning()) {
7735
8077
  this.stopCameraAnimation();
@@ -7741,6 +8083,22 @@ class Editor extends EventEmitter {
7741
8083
  case "pointer_move": {
7742
8084
  if (!isPen && isPenMode) return;
7743
8085
  const { x: cx, y: cy, z: cz } = unsafe__withoutCapture(() => this.getCamera());
8086
+ if (this.inputs.getIsRightPointing() && !this.inputs.getIsPanning()) {
8087
+ const currentScreenPoint = this.inputs.getCurrentScreenPoint();
8088
+ const originScreenPoint = this.inputs.getOriginScreenPoint();
8089
+ if (Vec.Dist2(originScreenPoint, currentScreenPoint) > this.options.dragDistanceSquared) {
8090
+ this._prevCursor = this.getInstanceState().cursor.type;
8091
+ this.inputs.setIsPanning(true);
8092
+ this.setCursor({ type: "grabbing", rotation: 0 });
8093
+ this.stopCameraAnimation();
8094
+ const offset = Vec.Sub(currentScreenPoint, originScreenPoint);
8095
+ this.setCamera(new Vec(cx + offset.x / cz, cy + offset.y / cz, cz), {
8096
+ immediate: true
8097
+ });
8098
+ this.maybeTrackPerformance("Panning");
8099
+ }
8100
+ return;
8101
+ }
7744
8102
  if (this.inputs.getIsPanning() && this.inputs.getIsPointing()) {
7745
8103
  const currentScreenPoint = this.inputs.getCurrentScreenPoint();
7746
8104
  const previousScreenPoint = this.inputs.getPreviousScreenPoint();
@@ -7749,6 +8107,7 @@ class Editor extends EventEmitter {
7749
8107
  immediate: true
7750
8108
  });
7751
8109
  this.maybeTrackPerformance("Panning");
8110
+ this.performance._notifyCameraOperation("panning");
7752
8111
  return;
7753
8112
  }
7754
8113
  if (inputs.getIsPointing() && !inputs.getIsDragging() && Vec.Dist2(inputs.getOriginPagePoint(), inputs.getCurrentPagePoint()) * this.getZoomLevel() > (instanceState.isCoarsePointer ? this.options.coarseDragDistanceSquared : this.options.dragDistanceSquared) / cz) {
@@ -7763,6 +8122,12 @@ class Editor extends EventEmitter {
7763
8122
  clearTimeout(this._longPressTimeout);
7764
8123
  inputs.buttons.delete(info.button);
7765
8124
  if (instanceState.isPenMode && !isPen) return;
8125
+ if (this.inputs.getIsRightPointing() && !this.inputs.getIsPanning()) {
8126
+ this.inputs.setIsRightPointing(false);
8127
+ this._selectedShapeIdsAtPointerDown = [];
8128
+ break;
8129
+ }
8130
+ this.inputs.setIsRightPointing(false);
7766
8131
  if (this.capturedPointerId === info.pointerId) {
7767
8132
  this.capturedPointerId = null;
7768
8133
  info.button = 0;
@@ -7780,11 +8145,24 @@ class Editor extends EventEmitter {
7780
8145
  break;
7781
8146
  }
7782
8147
  case MIDDLE_MOUSE_BUTTON: {
7783
- if (this.inputs.keys.has(" ")) {
8148
+ if (this.inputs.keys.has("Space")) {
7784
8149
  this.setCursor({ type: "grab", rotation: 0 });
7785
8150
  } else {
7786
8151
  this.setCursor({ type: this._prevCursor, rotation: 0 });
7787
8152
  }
8153
+ break;
8154
+ }
8155
+ case RIGHT_MOUSE_BUTTON: {
8156
+ if (this.inputs.keys.has("Space")) {
8157
+ this.setCursor({ type: "grab", rotation: 0 });
8158
+ } else {
8159
+ this.setCursor({ type: this._prevCursor, rotation: 0 });
8160
+ }
8161
+ if (slideSpeed > 0) {
8162
+ this.slideCamera({ speed: slideSpeed, direction: slideDirection });
8163
+ }
8164
+ this._selectedShapeIdsAtPointerDown = [];
8165
+ return this;
7788
8166
  }
7789
8167
  }
7790
8168
  if (slideSpeed > 0) {