@dxos/plugin-tldraw 0.10.0

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 (401) hide show
  1. package/LICENSE +105 -0
  2. package/PLUGIN.mdl +412 -0
  3. package/README.md +3 -0
  4. package/dist/assets/embed-icons/codepen.png +0 -0
  5. package/dist/assets/embed-icons/codesandbox.png +0 -0
  6. package/dist/assets/embed-icons/desmos.png +0 -0
  7. package/dist/assets/embed-icons/excalidraw.png +0 -0
  8. package/dist/assets/embed-icons/felt.png +0 -0
  9. package/dist/assets/embed-icons/figma.png +0 -0
  10. package/dist/assets/embed-icons/github_gist.png +0 -0
  11. package/dist/assets/embed-icons/google_calendar.png +0 -0
  12. package/dist/assets/embed-icons/google_maps.png +0 -0
  13. package/dist/assets/embed-icons/google_slides.png +0 -0
  14. package/dist/assets/embed-icons/observable.png +0 -0
  15. package/dist/assets/embed-icons/replit.png +0 -0
  16. package/dist/assets/embed-icons/scratch.png +0 -0
  17. package/dist/assets/embed-icons/spotify.png +0 -0
  18. package/dist/assets/embed-icons/tldraw.png +0 -0
  19. package/dist/assets/embed-icons/val_town.png +0 -0
  20. package/dist/assets/embed-icons/vimeo.png +0 -0
  21. package/dist/assets/embed-icons/youtube.png +0 -0
  22. package/dist/assets/fonts/IBMPlexMono-Medium.woff2 +0 -0
  23. package/dist/assets/fonts/IBMPlexSans-Medium.woff2 +0 -0
  24. package/dist/assets/fonts/IBMPlexSerif-Medium.woff2 +0 -0
  25. package/dist/assets/fonts/Montserrat-Regular.woff2 +0 -0
  26. package/dist/assets/fonts/Shantell_Sans-Tldrawish.woff2 +0 -0
  27. package/dist/assets/icons/icon/0_merged.svg +1 -0
  28. package/dist/assets/icons/icon/align-bottom.svg +1 -0
  29. package/dist/assets/icons/icon/align-center-horizontal.svg +1 -0
  30. package/dist/assets/icons/icon/align-center-vertical.svg +1 -0
  31. package/dist/assets/icons/icon/align-left.svg +1 -0
  32. package/dist/assets/icons/icon/align-right.svg +1 -0
  33. package/dist/assets/icons/icon/align-top.svg +1 -0
  34. package/dist/assets/icons/icon/arrow-left.svg +1 -0
  35. package/dist/assets/icons/icon/arrowhead-arrow.svg +1 -0
  36. package/dist/assets/icons/icon/arrowhead-bar.svg +1 -0
  37. package/dist/assets/icons/icon/arrowhead-diamond.svg +1 -0
  38. package/dist/assets/icons/icon/arrowhead-dot.svg +1 -0
  39. package/dist/assets/icons/icon/arrowhead-none.svg +1 -0
  40. package/dist/assets/icons/icon/arrowhead-square.svg +1 -0
  41. package/dist/assets/icons/icon/arrowhead-triangle-inverted.svg +1 -0
  42. package/dist/assets/icons/icon/arrowhead-triangle.svg +1 -0
  43. package/dist/assets/icons/icon/blob.svg +1 -0
  44. package/dist/assets/icons/icon/bring-forward.svg +1 -0
  45. package/dist/assets/icons/icon/bring-to-front.svg +1 -0
  46. package/dist/assets/icons/icon/broken.svg +1 -0
  47. package/dist/assets/icons/icon/chat-teardrop-text.svg +1 -0
  48. package/dist/assets/icons/icon/check-circle.svg +1 -0
  49. package/dist/assets/icons/icon/check.svg +1 -0
  50. package/dist/assets/icons/icon/chevron-down.svg +1 -0
  51. package/dist/assets/icons/icon/chevron-left.svg +1 -0
  52. package/dist/assets/icons/icon/chevron-right.svg +1 -0
  53. package/dist/assets/icons/icon/chevron-up.svg +1 -0
  54. package/dist/assets/icons/icon/chevrons-ne.svg +1 -0
  55. package/dist/assets/icons/icon/chevrons-sw.svg +1 -0
  56. package/dist/assets/icons/icon/clipboard-copied.svg +1 -0
  57. package/dist/assets/icons/icon/clipboard-copy.svg +1 -0
  58. package/dist/assets/icons/icon/color.svg +1 -0
  59. package/dist/assets/icons/icon/cross-2.svg +1 -0
  60. package/dist/assets/icons/icon/cross-circle.svg +1 -0
  61. package/dist/assets/icons/icon/dash-dashed.svg +1 -0
  62. package/dist/assets/icons/icon/dash-dotted.svg +1 -0
  63. package/dist/assets/icons/icon/dash-draw.svg +1 -0
  64. package/dist/assets/icons/icon/dash-solid.svg +1 -0
  65. package/dist/assets/icons/icon/disconnected.svg +1 -0
  66. package/dist/assets/icons/icon/discord.svg +1 -0
  67. package/dist/assets/icons/icon/distribute-horizontal.svg +1 -0
  68. package/dist/assets/icons/icon/distribute-vertical.svg +1 -0
  69. package/dist/assets/icons/icon/dot.svg +1 -0
  70. package/dist/assets/icons/icon/dots-horizontal.svg +1 -0
  71. package/dist/assets/icons/icon/dots-vertical.svg +1 -0
  72. package/dist/assets/icons/icon/drag-handle-dots.svg +1 -0
  73. package/dist/assets/icons/icon/duplicate.svg +1 -0
  74. package/dist/assets/icons/icon/edit.svg +1 -0
  75. package/dist/assets/icons/icon/external-link.svg +1 -0
  76. package/dist/assets/icons/icon/fill-fill.svg +1 -0
  77. package/dist/assets/icons/icon/fill-none.svg +1 -0
  78. package/dist/assets/icons/icon/fill-pattern.svg +1 -0
  79. package/dist/assets/icons/icon/fill-semi.svg +1 -0
  80. package/dist/assets/icons/icon/fill-solid.svg +1 -0
  81. package/dist/assets/icons/icon/follow.svg +1 -0
  82. package/dist/assets/icons/icon/following.svg +1 -0
  83. package/dist/assets/icons/icon/font-draw.svg +8 -0
  84. package/dist/assets/icons/icon/font-mono.svg +1 -0
  85. package/dist/assets/icons/icon/font-sans.svg +1 -0
  86. package/dist/assets/icons/icon/font-serif.svg +1 -0
  87. package/dist/assets/icons/icon/geo-arrow-down.svg +1 -0
  88. package/dist/assets/icons/icon/geo-arrow-left.svg +1 -0
  89. package/dist/assets/icons/icon/geo-arrow-right.svg +1 -0
  90. package/dist/assets/icons/icon/geo-arrow-up.svg +1 -0
  91. package/dist/assets/icons/icon/geo-check-box.svg +1 -0
  92. package/dist/assets/icons/icon/geo-cloud.svg +1 -0
  93. package/dist/assets/icons/icon/geo-diamond.svg +1 -0
  94. package/dist/assets/icons/icon/geo-ellipse.svg +1 -0
  95. package/dist/assets/icons/icon/geo-heart.svg +1 -0
  96. package/dist/assets/icons/icon/geo-hexagon.svg +1 -0
  97. package/dist/assets/icons/icon/geo-octagon.svg +1 -0
  98. package/dist/assets/icons/icon/geo-oval.svg +1 -0
  99. package/dist/assets/icons/icon/geo-pentagon.svg +1 -0
  100. package/dist/assets/icons/icon/geo-rectangle.svg +1 -0
  101. package/dist/assets/icons/icon/geo-rhombus-2.svg +1 -0
  102. package/dist/assets/icons/icon/geo-rhombus.svg +1 -0
  103. package/dist/assets/icons/icon/geo-star.svg +1 -0
  104. package/dist/assets/icons/icon/geo-trapezoid.svg +1 -0
  105. package/dist/assets/icons/icon/geo-triangle.svg +1 -0
  106. package/dist/assets/icons/icon/geo-x-box.svg +1 -0
  107. package/dist/assets/icons/icon/github.svg +1 -0
  108. package/dist/assets/icons/icon/group.svg +1 -0
  109. package/dist/assets/icons/icon/horizontal-align-end.svg +1 -0
  110. package/dist/assets/icons/icon/horizontal-align-middle.svg +1 -0
  111. package/dist/assets/icons/icon/horizontal-align-start.svg +1 -0
  112. package/dist/assets/icons/icon/icon-names.json +143 -0
  113. package/dist/assets/icons/icon/info-circle.svg +1 -0
  114. package/dist/assets/icons/icon/leading.svg +1 -0
  115. package/dist/assets/icons/icon/link.svg +1 -0
  116. package/dist/assets/icons/icon/lock.svg +1 -0
  117. package/dist/assets/icons/icon/menu.svg +1 -0
  118. package/dist/assets/icons/icon/minus.svg +1 -0
  119. package/dist/assets/icons/icon/mixed.svg +1 -0
  120. package/dist/assets/icons/icon/pack.svg +1 -0
  121. package/dist/assets/icons/icon/plus.svg +1 -0
  122. package/dist/assets/icons/icon/question-mark-circle.svg +1 -0
  123. package/dist/assets/icons/icon/question-mark.svg +1 -0
  124. package/dist/assets/icons/icon/redo.svg +1 -0
  125. package/dist/assets/icons/icon/reset-zoom.svg +1 -0
  126. package/dist/assets/icons/icon/rotate-ccw.svg +1 -0
  127. package/dist/assets/icons/icon/rotate-cw.svg +1 -0
  128. package/dist/assets/icons/icon/send-backward.svg +1 -0
  129. package/dist/assets/icons/icon/send-to-back.svg +1 -0
  130. package/dist/assets/icons/icon/share-1.svg +1 -0
  131. package/dist/assets/icons/icon/size-extra-large.svg +1 -0
  132. package/dist/assets/icons/icon/size-large.svg +1 -0
  133. package/dist/assets/icons/icon/size-medium.svg +1 -0
  134. package/dist/assets/icons/icon/size-small.svg +1 -0
  135. package/dist/assets/icons/icon/spline-cubic.svg +1 -0
  136. package/dist/assets/icons/icon/spline-line.svg +1 -0
  137. package/dist/assets/icons/icon/stack-horizontal.svg +1 -0
  138. package/dist/assets/icons/icon/stack-vertical.svg +1 -0
  139. package/dist/assets/icons/icon/status-offline.svg +1 -0
  140. package/dist/assets/icons/icon/stretch-horizontal.svg +1 -0
  141. package/dist/assets/icons/icon/stretch-vertical.svg +1 -0
  142. package/dist/assets/icons/icon/text-align-center.svg +1 -0
  143. package/dist/assets/icons/icon/text-align-left.svg +1 -0
  144. package/dist/assets/icons/icon/text-align-right.svg +1 -0
  145. package/dist/assets/icons/icon/toggle-off.svg +1 -0
  146. package/dist/assets/icons/icon/toggle-on.svg +1 -0
  147. package/dist/assets/icons/icon/tool-arrow.svg +1 -0
  148. package/dist/assets/icons/icon/tool-eraser.svg +1 -0
  149. package/dist/assets/icons/icon/tool-frame.svg +1 -0
  150. package/dist/assets/icons/icon/tool-hand.svg +1 -0
  151. package/dist/assets/icons/icon/tool-highlight.svg +1 -0
  152. package/dist/assets/icons/icon/tool-laser.svg +1 -0
  153. package/dist/assets/icons/icon/tool-line.svg +1 -0
  154. package/dist/assets/icons/icon/tool-media.svg +1 -0
  155. package/dist/assets/icons/icon/tool-note.svg +1 -0
  156. package/dist/assets/icons/icon/tool-pencil.svg +1 -0
  157. package/dist/assets/icons/icon/tool-pointer.svg +1 -0
  158. package/dist/assets/icons/icon/tool-screenshot.svg +1 -0
  159. package/dist/assets/icons/icon/tool-text.svg +1 -0
  160. package/dist/assets/icons/icon/trash.svg +1 -0
  161. package/dist/assets/icons/icon/twitter.svg +1 -0
  162. package/dist/assets/icons/icon/undo.svg +1 -0
  163. package/dist/assets/icons/icon/ungroup.svg +1 -0
  164. package/dist/assets/icons/icon/unlock.svg +1 -0
  165. package/dist/assets/icons/icon/vertical-align-end.svg +1 -0
  166. package/dist/assets/icons/icon/vertical-align-middle.svg +1 -0
  167. package/dist/assets/icons/icon/vertical-align-start.svg +1 -0
  168. package/dist/assets/icons/icon/warning-triangle.svg +1 -0
  169. package/dist/assets/icons/icon/zoom-in.svg +1 -0
  170. package/dist/assets/icons/icon/zoom-out.svg +1 -0
  171. package/dist/assets/translations/ar.json +295 -0
  172. package/dist/assets/translations/ca.json +295 -0
  173. package/dist/assets/translations/cs.json +352 -0
  174. package/dist/assets/translations/da.json +160 -0
  175. package/dist/assets/translations/de.json +310 -0
  176. package/dist/assets/translations/en.json +1 -0
  177. package/dist/assets/translations/es.json +299 -0
  178. package/dist/assets/translations/fa.json +384 -0
  179. package/dist/assets/translations/fi.json +312 -0
  180. package/dist/assets/translations/fr.json +372 -0
  181. package/dist/assets/translations/gl.json +349 -0
  182. package/dist/assets/translations/he.json +86 -0
  183. package/dist/assets/translations/hi-in.json +290 -0
  184. package/dist/assets/translations/hr.json +358 -0
  185. package/dist/assets/translations/hu.json +365 -0
  186. package/dist/assets/translations/id.json +373 -0
  187. package/dist/assets/translations/it.json +330 -0
  188. package/dist/assets/translations/ja.json +351 -0
  189. package/dist/assets/translations/ko-kr.json +396 -0
  190. package/dist/assets/translations/ku.json +93 -0
  191. package/dist/assets/translations/languages.json +150 -0
  192. package/dist/assets/translations/main.json +396 -0
  193. package/dist/assets/translations/my.json +112 -0
  194. package/dist/assets/translations/ne.json +295 -0
  195. package/dist/assets/translations/no.json +62 -0
  196. package/dist/assets/translations/pl.json +113 -0
  197. package/dist/assets/translations/pt-br.json +333 -0
  198. package/dist/assets/translations/pt-pt.json +86 -0
  199. package/dist/assets/translations/ro.json +371 -0
  200. package/dist/assets/translations/ru.json +375 -0
  201. package/dist/assets/translations/sl.json +373 -0
  202. package/dist/assets/translations/sv.json +96 -0
  203. package/dist/assets/translations/te.json +112 -0
  204. package/dist/assets/translations/th.json +295 -0
  205. package/dist/assets/translations/tr.json +355 -0
  206. package/dist/assets/translations/uk.json +375 -0
  207. package/dist/assets/translations/vi.json +295 -0
  208. package/dist/assets/translations/zh-cn.json +386 -0
  209. package/dist/assets/translations/zh-tw.json +340 -0
  210. package/dist/lib/TldrawPlugin.mjs +22 -0
  211. package/dist/lib/TldrawPlugin.mjs.map +1 -0
  212. package/dist/lib/assets/plugin-tldraw-BDrn_mrV.css +24 -0
  213. package/dist/lib/capabilities.mjs +8 -0
  214. package/dist/lib/capabilities.mjs.map +1 -0
  215. package/dist/lib/chunk-TldrawArticle.mjs +60 -0
  216. package/dist/lib/chunk-TldrawArticle.mjs.map +1 -0
  217. package/dist/lib/chunk-TldrawCard.mjs +35 -0
  218. package/dist/lib/chunk-TldrawCard.mjs.map +1 -0
  219. package/dist/lib/chunk-meta.mjs +40 -0
  220. package/dist/lib/chunk-meta.mjs.map +1 -0
  221. package/dist/lib/chunk-settings.mjs +23 -0
  222. package/dist/lib/chunk-settings.mjs.map +1 -0
  223. package/dist/lib/chunk-sketch-variant.mjs +23 -0
  224. package/dist/lib/chunk-sketch-variant.mjs.map +1 -0
  225. package/dist/lib/chunk-types.mjs +73 -0
  226. package/dist/lib/chunk-types.mjs.map +1 -0
  227. package/dist/lib/components.mjs +443 -0
  228. package/dist/lib/components.mjs.map +1 -0
  229. package/dist/lib/containers.mjs +8 -0
  230. package/dist/lib/containers.mjs.map +1 -0
  231. package/dist/lib/hooks.mjs +116 -0
  232. package/dist/lib/hooks.mjs.map +1 -0
  233. package/dist/lib/index.mjs +4 -0
  234. package/dist/lib/meta.mjs +2 -0
  235. package/dist/lib/model.mjs +905 -0
  236. package/dist/lib/model.mjs.map +1 -0
  237. package/dist/lib/plugin.mjs +8 -0
  238. package/dist/lib/plugin.mjs.map +1 -0
  239. package/dist/lib/testing.mjs +246 -0
  240. package/dist/lib/testing.mjs.map +1 -0
  241. package/dist/lib/translations.mjs +10 -0
  242. package/dist/lib/translations.mjs.map +1 -0
  243. package/dist/lib/types.mjs +2 -0
  244. package/dist/types/dx.config.d.ts +28 -0
  245. package/dist/types/dx.config.d.ts.map +1 -0
  246. package/dist/types/src/TldrawPlugin.d.ts +4 -0
  247. package/dist/types/src/TldrawPlugin.d.ts.map +1 -0
  248. package/dist/types/src/capabilities/index.d.ts +4 -0
  249. package/dist/types/src/capabilities/index.d.ts.map +1 -0
  250. package/dist/types/src/capabilities/settings.d.ts +5 -0
  251. package/dist/types/src/capabilities/settings.d.ts.map +1 -0
  252. package/dist/types/src/capabilities/sketch-variant.d.ts +5 -0
  253. package/dist/types/src/capabilities/sketch-variant.d.ts.map +1 -0
  254. package/dist/types/src/components/Canvas/Canvas.d.ts +17 -0
  255. package/dist/types/src/components/Canvas/Canvas.d.ts.map +1 -0
  256. package/dist/types/src/components/Canvas/Canvas.stories.d.ts +15 -0
  257. package/dist/types/src/components/Canvas/Canvas.stories.d.ts.map +1 -0
  258. package/dist/types/src/components/Canvas/index.d.ts +4 -0
  259. package/dist/types/src/components/Canvas/index.d.ts.map +1 -0
  260. package/dist/types/src/components/actions.d.ts +6 -0
  261. package/dist/types/src/components/actions.d.ts.map +1 -0
  262. package/dist/types/src/components/custom/CustomGrid.d.ts +12 -0
  263. package/dist/types/src/components/custom/CustomGrid.d.ts.map +1 -0
  264. package/dist/types/src/components/custom/CustomMenu.d.ts +4 -0
  265. package/dist/types/src/components/custom/CustomMenu.d.ts.map +1 -0
  266. package/dist/types/src/components/custom/CustomStylePanel.d.ts +4 -0
  267. package/dist/types/src/components/custom/CustomStylePanel.d.ts.map +1 -0
  268. package/dist/types/src/components/custom/CustomToolbar.d.ts +10 -0
  269. package/dist/types/src/components/custom/CustomToolbar.d.ts.map +1 -0
  270. package/dist/types/src/components/custom/DottedGrid.d.ts +4 -0
  271. package/dist/types/src/components/custom/DottedGrid.d.ts.map +1 -0
  272. package/dist/types/src/components/custom/MeshGrid.d.ts +4 -0
  273. package/dist/types/src/components/custom/MeshGrid.d.ts.map +1 -0
  274. package/dist/types/src/components/custom/index.d.ts +6 -0
  275. package/dist/types/src/components/custom/index.d.ts.map +1 -0
  276. package/dist/types/src/components/index.d.ts +2 -0
  277. package/dist/types/src/components/index.d.ts.map +1 -0
  278. package/dist/types/src/containers/TldrawArticle/TldrawArticle.d.ts +8 -0
  279. package/dist/types/src/containers/TldrawArticle/TldrawArticle.d.ts.map +1 -0
  280. package/dist/types/src/containers/TldrawArticle/index.d.ts +2 -0
  281. package/dist/types/src/containers/TldrawArticle/index.d.ts.map +1 -0
  282. package/dist/types/src/containers/TldrawCard/TldrawCard.d.ts +9 -0
  283. package/dist/types/src/containers/TldrawCard/TldrawCard.d.ts.map +1 -0
  284. package/dist/types/src/containers/TldrawCard/TldrawCard.stories.d.ts +15 -0
  285. package/dist/types/src/containers/TldrawCard/TldrawCard.stories.d.ts.map +1 -0
  286. package/dist/types/src/containers/TldrawCard/index.d.ts +2 -0
  287. package/dist/types/src/containers/TldrawCard/index.d.ts.map +1 -0
  288. package/dist/types/src/containers/index.d.ts +4 -0
  289. package/dist/types/src/containers/index.d.ts.map +1 -0
  290. package/dist/types/src/hooks/adapter.d.ts +15 -0
  291. package/dist/types/src/hooks/adapter.d.ts.map +1 -0
  292. package/dist/types/src/hooks/adapter.test.d.ts +2 -0
  293. package/dist/types/src/hooks/adapter.test.d.ts.map +1 -0
  294. package/dist/types/src/hooks/index.d.ts +3 -0
  295. package/dist/types/src/hooks/index.d.ts.map +1 -0
  296. package/dist/types/src/hooks/useStoreAdapter.d.ts +11 -0
  297. package/dist/types/src/hooks/useStoreAdapter.d.ts.map +1 -0
  298. package/dist/types/src/index.d.ts +4 -0
  299. package/dist/types/src/index.d.ts.map +1 -0
  300. package/dist/types/src/meta.d.ts +33 -0
  301. package/dist/types/src/meta.d.ts.map +1 -0
  302. package/dist/types/src/migrations/index.d.ts +3 -0
  303. package/dist/types/src/migrations/index.d.ts.map +1 -0
  304. package/dist/types/src/migrations/migrate.d.ts +9 -0
  305. package/dist/types/src/migrations/migrate.d.ts.map +1 -0
  306. package/dist/types/src/migrations/schema.d.ts +7 -0
  307. package/dist/types/src/migrations/schema.d.ts.map +1 -0
  308. package/dist/types/src/model/TldrawBuilder.d.ts +110 -0
  309. package/dist/types/src/model/TldrawBuilder.d.ts.map +1 -0
  310. package/dist/types/src/model/TldrawBuilder.test.d.ts +2 -0
  311. package/dist/types/src/model/TldrawBuilder.test.d.ts.map +1 -0
  312. package/dist/types/src/model/apply.d.ts +5 -0
  313. package/dist/types/src/model/apply.d.ts.map +1 -0
  314. package/dist/types/src/model/builder.d.ts +3 -0
  315. package/dist/types/src/model/builder.d.ts.map +1 -0
  316. package/dist/types/src/model/index.d.ts +6 -0
  317. package/dist/types/src/model/index.d.ts.map +1 -0
  318. package/dist/types/src/model/read.d.ts +8 -0
  319. package/dist/types/src/model/read.d.ts.map +1 -0
  320. package/dist/types/src/model/render.d.ts +27 -0
  321. package/dist/types/src/model/render.d.ts.map +1 -0
  322. package/dist/types/src/model/scene.test.d.ts +2 -0
  323. package/dist/types/src/model/scene.test.d.ts.map +1 -0
  324. package/dist/types/src/plugin.d.ts +3 -0
  325. package/dist/types/src/plugin.d.ts.map +1 -0
  326. package/dist/types/src/testing/data.d.ts +242 -0
  327. package/dist/types/src/testing/data.d.ts.map +1 -0
  328. package/dist/types/src/testing/index.d.ts +2 -0
  329. package/dist/types/src/testing/index.d.ts.map +1 -0
  330. package/dist/types/src/testing/schema.d.ts +7 -0
  331. package/dist/types/src/testing/schema.d.ts.map +1 -0
  332. package/dist/types/src/translations.d.ts +9 -0
  333. package/dist/types/src/translations.d.ts.map +1 -0
  334. package/dist/types/src/types/Settings.d.ts +10 -0
  335. package/dist/types/src/types/Settings.d.ts.map +1 -0
  336. package/dist/types/src/types/Tldraw.d.ts +25 -0
  337. package/dist/types/src/types/Tldraw.d.ts.map +1 -0
  338. package/dist/types/src/types/TldrawCapabilities.d.ts +4 -0
  339. package/dist/types/src/types/TldrawCapabilities.d.ts.map +1 -0
  340. package/dist/types/src/types/index.d.ts +4 -0
  341. package/dist/types/src/types/index.d.ts.map +1 -0
  342. package/dist/types/src/types/types.d.ts +6 -0
  343. package/dist/types/src/types/types.d.ts.map +1 -0
  344. package/dist/types/src/variant.test.d.ts +2 -0
  345. package/dist/types/src/variant.test.d.ts.map +1 -0
  346. package/dist/types/tsconfig.tsbuildinfo +1 -0
  347. package/dx.config.ts +35 -0
  348. package/package.json +157 -0
  349. package/src/TldrawPlugin.tsx +31 -0
  350. package/src/capabilities/index.ts +8 -0
  351. package/src/capabilities/settings.ts +31 -0
  352. package/src/capabilities/sketch-variant.ts +29 -0
  353. package/src/components/Canvas/Canvas.stories.tsx +101 -0
  354. package/src/components/Canvas/Canvas.tsx +284 -0
  355. package/src/components/Canvas/index.ts +9 -0
  356. package/src/components/Canvas/theme.css +23 -0
  357. package/src/components/actions.ts +42 -0
  358. package/src/components/custom/CustomGrid.tsx +61 -0
  359. package/src/components/custom/CustomMenu.tsx +31 -0
  360. package/src/components/custom/CustomStylePanel.tsx +38 -0
  361. package/src/components/custom/CustomToolbar.tsx +88 -0
  362. package/src/components/custom/DottedGrid.tsx +53 -0
  363. package/src/components/custom/MeshGrid.tsx +47 -0
  364. package/src/components/custom/index.ts +9 -0
  365. package/src/components/index.ts +5 -0
  366. package/src/containers/TldrawArticle/TldrawArticle.tsx +78 -0
  367. package/src/containers/TldrawArticle/index.ts +5 -0
  368. package/src/containers/TldrawCard/TldrawCard.stories.tsx +53 -0
  369. package/src/containers/TldrawCard/TldrawCard.tsx +32 -0
  370. package/src/containers/TldrawCard/index.ts +5 -0
  371. package/src/containers/index.ts +8 -0
  372. package/src/hooks/adapter.test.ts +20 -0
  373. package/src/hooks/adapter.ts +83 -0
  374. package/src/hooks/index.ts +6 -0
  375. package/src/hooks/useStoreAdapter.ts +55 -0
  376. package/src/index.ts +7 -0
  377. package/src/meta.ts +9 -0
  378. package/src/migrations/index.ts +6 -0
  379. package/src/migrations/migrate.ts +49 -0
  380. package/src/migrations/schema.ts +98 -0
  381. package/src/model/TldrawBuilder.test.ts +72 -0
  382. package/src/model/TldrawBuilder.ts +443 -0
  383. package/src/model/apply.ts +132 -0
  384. package/src/model/builder.ts +31 -0
  385. package/src/model/index.ts +9 -0
  386. package/src/model/read.ts +203 -0
  387. package/src/model/render.ts +191 -0
  388. package/src/model/scene.test.ts +222 -0
  389. package/src/plugin.ts +9 -0
  390. package/src/testing/data.ts +238 -0
  391. package/src/testing/index.ts +5 -0
  392. package/src/testing/schema.ts +98 -0
  393. package/src/translations.ts +18 -0
  394. package/src/types/Settings.ts +32 -0
  395. package/src/types/Tldraw.ts +38 -0
  396. package/src/types/TldrawCapabilities.ts +17 -0
  397. package/src/types/index.ts +8 -0
  398. package/src/types/types.ts +11 -0
  399. package/src/typings.d.ts +8 -0
  400. package/src/variant.test.ts +142 -0
  401. package/src/vite-env.d.ts +10 -0
package/dx.config.ts ADDED
@@ -0,0 +1,35 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Config2 } from '@dxos/app-framework/config';
6
+ import { trim } from '@dxos/util';
7
+
8
+ export default Config2.make({
9
+ plugin: {
10
+ key: 'org.dxos.plugin.tldraw',
11
+ name: 'tldraw',
12
+ author: 'DXOS',
13
+ description: trim`
14
+ tldraw is the canvas renderer that powers collaborative whiteboards in DXOS Composer,
15
+ giving every workspace a full-featured infinite canvas. Draw freehand strokes, place
16
+ geometric shapes, add text and arrows, and organise ideas visually — all within the same
17
+ local-first environment as the rest of your documents.
18
+
19
+ The plugin contributes a sketch variant to the Illustrator plugin: the base \`Sketch\`
20
+ object references a tldraw Canvas whose content is stored as a plain JSON record in ECHO,
21
+ so no binary blobs or external storage are required. Toolbar actions, grid settings, and
22
+ custom tools are wired through the Composer plugin system, and a builder maps the
23
+ Illustrator scene DSL onto tldraw records so agents can draw and edit diagrams.
24
+
25
+ Because Canvas data lives in ECHO, every edit is replicated peer-to-peer in real time.
26
+ Collaborators see each other's strokes as they draw, and changes made offline merge
27
+ automatically when connectivity is restored using ECHO's CRDT semantics.
28
+ `,
29
+ source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-tldraw',
30
+ dependsOn: ['org.dxos.plugin.illustrator'],
31
+ icon: { key: 'ph--compass-tool--regular', hue: 'indigo' },
32
+ spec: 'PLUGIN.mdl',
33
+ screenshots: [{ dark: 'https://dxos.network/plugin-details-sketch-dark.png' }],
34
+ },
35
+ });
package/package.json ADDED
@@ -0,0 +1,157 @@
1
+ {
2
+ "name": "@dxos/plugin-tldraw",
3
+ "version": "0.10.0",
4
+ "description": "tldraw canvas renderer for the DXOS Illustrator plugin.",
5
+ "homepage": "https://dxos.org",
6
+ "bugs": "https://github.com/dxos/dxos/issues",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/dxos/dxos"
10
+ },
11
+ "license": "FSL-1.1-Apache-2.0",
12
+ "author": "DXOS.org",
13
+ "sideEffects": true,
14
+ "type": "module",
15
+ "imports": {
16
+ "#capabilities": {
17
+ "source": "./src/capabilities/index.ts",
18
+ "types": "./dist/types/src/capabilities/index.d.ts",
19
+ "default": "./dist/lib/capabilities.mjs"
20
+ },
21
+ "#components": {
22
+ "source": "./src/components/index.ts",
23
+ "types": "./dist/types/src/components/index.d.ts",
24
+ "default": "./dist/lib/components.mjs"
25
+ },
26
+ "#containers": {
27
+ "source": "./src/containers/index.ts",
28
+ "types": "./dist/types/src/containers/index.d.ts",
29
+ "default": "./dist/lib/containers.mjs"
30
+ },
31
+ "#hooks": {
32
+ "source": "./src/hooks/index.ts",
33
+ "types": "./dist/types/src/hooks/index.d.ts",
34
+ "default": "./dist/lib/hooks.mjs"
35
+ },
36
+ "#model": {
37
+ "source": "./src/model/index.ts",
38
+ "types": "./dist/types/src/model/index.d.ts",
39
+ "default": "./dist/lib/model.mjs"
40
+ },
41
+ "#meta": {
42
+ "source": "./src/meta.ts",
43
+ "types": "./dist/types/src/meta.d.ts",
44
+ "default": "./dist/lib/meta.mjs"
45
+ },
46
+ "#plugin": {
47
+ "source": "./src/TldrawPlugin.tsx",
48
+ "types": "./dist/types/src/TldrawPlugin.d.ts",
49
+ "default": "./dist/lib/TldrawPlugin.mjs"
50
+ },
51
+ "#testing": "./src/testing/index.ts",
52
+ "#translations": {
53
+ "source": "./src/translations.ts",
54
+ "types": "./dist/types/src/translations.d.ts",
55
+ "default": "./dist/lib/translations.mjs"
56
+ },
57
+ "#types": {
58
+ "source": "./src/types/index.ts",
59
+ "types": "./dist/types/src/types/index.d.ts",
60
+ "default": "./dist/lib/types.mjs"
61
+ }
62
+ },
63
+ "exports": {
64
+ ".": {
65
+ "source": "./src/index.ts",
66
+ "types": "./dist/types/src/index.d.ts",
67
+ "import": "./dist/lib/index.mjs"
68
+ },
69
+ "./assets/PLUGIN.mdl": "./PLUGIN.mdl",
70
+ "./plugin": {
71
+ "source": "./src/plugin.ts",
72
+ "types": "./dist/types/src/plugin.d.ts",
73
+ "import": "./dist/lib/plugin.mjs"
74
+ },
75
+ "./testing": {
76
+ "source": "./src/testing/index.ts",
77
+ "types": "./dist/types/src/testing/index.d.ts",
78
+ "import": "./dist/lib/testing.mjs"
79
+ },
80
+ "./translations": {
81
+ "source": "./src/translations.ts",
82
+ "types": "./dist/types/src/translations.d.ts",
83
+ "import": "./dist/lib/translations.mjs"
84
+ }
85
+ },
86
+ "types": "dist/types/src/index.d.ts",
87
+ "files": [
88
+ "dist",
89
+ "dx.config.ts",
90
+ "src",
91
+ "PLUGIN.mdl"
92
+ ],
93
+ "dependencies": {
94
+ "@automerge/automerge": "3.3.0-fragments.2",
95
+ "@effect-atom/atom-react": "^0.5.0",
96
+ "@tldraw/assets": "^3.0.0",
97
+ "@tldraw/editor": "^3.0.0",
98
+ "@tldraw/state": "^3.0.0",
99
+ "@tldraw/store": "^3.0.0",
100
+ "@tldraw/tldraw": "^3.0.0",
101
+ "@tldraw/tlschema": "^3.0.0",
102
+ "@tldraw/utils": "^3.0.0",
103
+ "effect": "3.21.4",
104
+ "lodash.defaultsdeep": "^4.6.1",
105
+ "react-resize-detector": "^11.0.1",
106
+ "@dxos/app-framework": "0.10.0",
107
+ "@dxos/app-toolkit": "0.10.0",
108
+ "@dxos/async": "0.10.0",
109
+ "@dxos/client": "0.10.0",
110
+ "@dxos/echo": "0.10.0",
111
+ "@dxos/echo-client": "0.10.0",
112
+ "@dxos/invariant": "0.10.0",
113
+ "@dxos/compute": "0.10.0",
114
+ "@dxos/effect": "0.10.0",
115
+ "@dxos/echo-doc": "0.10.0",
116
+ "@dxos/log": "0.10.0",
117
+ "@dxos/plugin-illustrator": "0.10.0",
118
+ "@dxos/keys": "0.10.0",
119
+ "@dxos/react-client": "0.10.0",
120
+ "@dxos/react-ui-attention": "0.10.0",
121
+ "@dxos/react-hooks": "0.10.0",
122
+ "@dxos/plugin-graph": "0.10.0",
123
+ "@dxos/plugin-space": "0.10.0",
124
+ "@dxos/react-ui-form": "0.10.0",
125
+ "@dxos/schema": "0.10.0",
126
+ "@dxos/util": "0.10.0"
127
+ },
128
+ "devDependencies": {
129
+ "@effect/vitest": "0.29.0",
130
+ "@types/lodash.defaultsdeep": "^4.6.6",
131
+ "@types/react": "~19.2.17",
132
+ "@types/react-dom": "~19.2.3",
133
+ "react": "~19.2.7",
134
+ "react-dom": "~19.2.7",
135
+ "vite": "^8.1.4",
136
+ "@dxos/plugin-testing": "0.10.0",
137
+ "@dxos/random": "0.10.0",
138
+ "@dxos/react-ui": "0.10.0",
139
+ "@dxos/react-ui-mosaic": "0.10.0",
140
+ "@dxos/storybook-utils": "0.10.0",
141
+ "@dxos/ui-theme": "0.10.0",
142
+ "@dxos/agent-runtime": "0.10.0"
143
+ },
144
+ "peerDependencies": {
145
+ "effect": "3.21.4",
146
+ "react": "~19.2.7",
147
+ "react-dom": "~19.2.7",
148
+ "@dxos/react-ui": "^0.10.0",
149
+ "@dxos/ui-theme": "^0.10.0"
150
+ },
151
+ "publishConfig": {
152
+ "access": "public"
153
+ },
154
+ "scripts": {
155
+ "copy:assets": "./scripts/copy_assets.sh"
156
+ }
157
+ }
@@ -0,0 +1,31 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { Plugin } from '@dxos/app-framework';
6
+ import { AppActivationEvents, AppPlugin } from '@dxos/app-toolkit';
7
+
8
+ import { SketchVariant, TldrawSettings } from '#capabilities';
9
+ import { meta } from '#meta';
10
+ import { translations } from '#translations';
11
+ import { Tldraw } from '#types';
12
+
13
+ // eslint-disable-next-line import/no-relative-packages
14
+ import pluginSpec from '../PLUGIN.mdl?raw';
15
+
16
+ export const TldrawPlugin = Plugin.define(meta).pipe(
17
+ Plugin.addModule({
18
+ id: 'sketch-variant',
19
+ activatesOn: AppActivationEvents.SetupSchema,
20
+ activate: SketchVariant,
21
+ }),
22
+ AppPlugin.addSchemaModule({ schema: [Tldraw.Canvas] }),
23
+ AppPlugin.addSettingsModule({ activate: TldrawSettings }),
24
+ AppPlugin.addTranslationsModule({ translations }),
25
+ AppPlugin.addPluginAssetModule({
26
+ asset: { pluginId: meta.profile.key, path: 'PLUGIN.mdl', content: pluginSpec, mimeType: 'application/x-mdl' },
27
+ }),
28
+ Plugin.make,
29
+ );
30
+
31
+ export default TldrawPlugin;
@@ -0,0 +1,8 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Capability } from '@dxos/app-framework';
6
+
7
+ export const SketchVariant = Capability.lazy('SketchVariant', () => import('./sketch-variant'));
8
+ export const TldrawSettings = Capability.lazy('TldrawSettings', () => import('./settings'));
@@ -0,0 +1,31 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capability } from '@dxos/app-framework';
8
+ import { AppCapabilities } from '@dxos/app-toolkit';
9
+ import { createKvsStore } from '@dxos/effect';
10
+
11
+ import { meta } from '#meta';
12
+ import { Settings, TldrawCapabilities } from '#types';
13
+
14
+ export default Capability.makeModule(() =>
15
+ Effect.sync(() => {
16
+ const settingsAtom = createKvsStore({
17
+ key: meta.profile.key,
18
+ schema: Settings.Settings,
19
+ defaultValue: () => ({}),
20
+ });
21
+
22
+ return [
23
+ Capability.contributes(TldrawCapabilities.Settings, settingsAtom),
24
+ Capability.contributes(AppCapabilities.Settings, {
25
+ prefix: meta.profile.key,
26
+ schema: Settings.Settings,
27
+ atom: settingsAtom,
28
+ }),
29
+ ];
30
+ }),
31
+ );
@@ -0,0 +1,29 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capability } from '@dxos/app-framework';
8
+ import { Type } from '@dxos/echo';
9
+ import { IllustratorCapabilities, type SketchVariant } from '@dxos/plugin-illustrator/types';
10
+
11
+ import { TldrawArticle, TldrawCard } from '#containers';
12
+ import { tldrawBuilder } from '#model';
13
+
14
+ import { Tldraw } from '../types';
15
+
16
+ const variant: SketchVariant = {
17
+ id: Type.getTypename(Tldraw.Canvas),
18
+ label: 'tldraw',
19
+ icon: 'ph--compass-tool--regular',
20
+ canvasType: Tldraw.Canvas,
21
+ createCanvas: () => Effect.sync(() => Tldraw.makeCanvas()),
22
+ builder: tldrawBuilder,
23
+ card: TldrawCard,
24
+ article: TldrawArticle,
25
+ };
26
+
27
+ export default Capability.makeModule(() =>
28
+ Effect.succeed(Capability.contributes(IllustratorCapabilities.VariantProvider, variant)),
29
+ );
@@ -0,0 +1,101 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React, { useState } from 'react';
7
+
8
+ import { createObject } from '@dxos/echo-client';
9
+ import { Button, Panel, Toolbar } from '@dxos/react-ui';
10
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
11
+
12
+ import { TldrawBuilder } from '#model';
13
+ import { data } from '#testing';
14
+ import { Tldraw } from '#types';
15
+
16
+ import { migrateCanvas } from '../../migrations';
17
+ import { CanvasComponent } from './Canvas';
18
+
19
+ const DefaultStory = () => {
20
+ const [canvas, setCanvas] = useState(createObject(Tldraw.makeCanvas({ content: data.v2 })));
21
+
22
+ const handleClear = () => {
23
+ setCanvas(createObject(Tldraw.makeCanvas()));
24
+ };
25
+
26
+ const handleCreate = () => {
27
+ const canvas = createObject(Tldraw.makeCanvas({ content: data.v2 }));
28
+ console.log(JSON.stringify(canvas, undefined, 2));
29
+ setCanvas(canvas);
30
+ };
31
+
32
+ const handleMigrate = async () => {
33
+ const content = await migrateCanvas(data.v1);
34
+ setCanvas(createObject(Tldraw.makeCanvas({ content })));
35
+ };
36
+
37
+ return (
38
+ <Panel.Root>
39
+ <Panel.Toolbar asChild>
40
+ <Toolbar.Root>
41
+ <Button variant='primary' onClick={handleClear}>
42
+ Clear
43
+ </Button>
44
+ <Button variant='ghost' onClick={handleCreate}>
45
+ Create
46
+ </Button>
47
+ <Button variant='ghost' onClick={handleMigrate}>
48
+ Load V1 Sample
49
+ </Button>
50
+ </Toolbar.Root>
51
+ </Panel.Toolbar>
52
+ <Panel.Content asChild>
53
+ <CanvasComponent classNames='dx-attention-surface' canvas={canvas} assetsBaseUrl={null} autoCenter />
54
+ </Panel.Content>
55
+ </Panel.Root>
56
+ );
57
+ };
58
+
59
+ const meta = {
60
+ title: 'plugins/plugin-tldraw/components/Canvas',
61
+ render: DefaultStory,
62
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
63
+ parameters: {
64
+ layout: 'fullscreen',
65
+ },
66
+ } satisfies Meta<typeof DefaultStory>;
67
+
68
+ export default meta;
69
+
70
+ type Story = StoryObj<typeof meta>;
71
+
72
+ export const Default: Story = {};
73
+
74
+ const BuilderStory = () => {
75
+ const [canvas] = useState(() =>
76
+ createObject(
77
+ Tldraw.makeCanvas({
78
+ content: new TldrawBuilder()
79
+ .rectangle({ id: 'a', x: 0, y: 0, text: 'DXOS', color: 'blue', fill: 'solid' })
80
+ .ellipse({ id: 'b', x: 360, y: 0, text: 'ECHO', color: 'green' })
81
+ .geo('star', { id: 'c', x: 180, y: 280, text: 'EDGE', color: 'yellow' })
82
+ .text({ x: 0, y: 480, text: 'Built with TldrawBuilder', font: 'mono' })
83
+ .arrow({ from: 'a', to: 'b', text: 'syncs' })
84
+ .arrow({ from: 'b', to: 'c' })
85
+ .build(),
86
+ }),
87
+ ),
88
+ );
89
+
90
+ return (
91
+ <Panel.Root>
92
+ <Panel.Content asChild>
93
+ <CanvasComponent classNames='dx-attention-surface' canvas={canvas} assetsBaseUrl={null} autoCenter />
94
+ </Panel.Content>
95
+ </Panel.Root>
96
+ );
97
+ };
98
+
99
+ export const Builder: Story = {
100
+ render: BuilderStory,
101
+ };
@@ -0,0 +1,284 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import '@tldraw/tldraw/tldraw.css';
6
+ import './theme.css';
7
+
8
+ import { getAssetUrls } from '@tldraw/assets/selfHosted';
9
+ import { type TLEventInfo, type TLGridProps, type TLInstance } from '@tldraw/editor';
10
+ import { DefaultToolbar, type Editor, Tldraw as TldrawEditor, type TLUiAssetUrlOverrides } from '@tldraw/tldraw';
11
+ import defaultsDeep from 'lodash.defaultsdeep';
12
+ import React, { type FC, useEffect, useMemo, useState } from 'react';
13
+ import { useResizeDetector } from 'react-resize-detector';
14
+
15
+ import { Obj } from '@dxos/echo';
16
+ import { useMergeRefs } from '@dxos/react-hooks';
17
+ import { composable, composableProps } from '@dxos/react-ui';
18
+
19
+ import { useStoreAdapter } from '#hooks';
20
+ import { type Settings, type Tldraw } from '#types';
21
+
22
+ import { handleSnap } from '../actions';
23
+ import { CustomMenu, CustomStylePanel, DefaultToolbarContent, DottedGrid, MeshGrid } from '../custom';
24
+
25
+ const threadToolId = 'thread';
26
+
27
+ const gridComponents: Record<Settings.GridType, FC<TLGridProps>> = {
28
+ mesh: MeshGrid,
29
+ dotted: DottedGrid,
30
+ };
31
+
32
+ export type CanvasProps = {
33
+ canvas: Tldraw.Canvas;
34
+ readonly?: boolean;
35
+ autoCenter?: boolean;
36
+ hideUi?: boolean;
37
+ assetsBaseUrl?: string | null;
38
+ settings?: Settings.Settings;
39
+ onThreadCreate?: () => void;
40
+ };
41
+
42
+ export const CanvasComponent = composable<HTMLDivElement, CanvasProps>(
43
+ (
44
+ {
45
+ canvas,
46
+ readonly = false,
47
+ autoCenter = true,
48
+ hideUi = false,
49
+ assetsBaseUrl = '/assets/plugin-tldraw',
50
+ settings,
51
+ onThreadCreate,
52
+ ...props
53
+ },
54
+ forwardedRef,
55
+ ) => {
56
+ const adapter = useStoreAdapter(canvas);
57
+ const [editor, setEditor] = useState<Editor>();
58
+
59
+ // Focus.
60
+ useEffect(() => {
61
+ hideUi ? editor?.blur() : editor?.focus();
62
+ }, [hideUi, editor]);
63
+
64
+ // Editor State.
65
+ useEffect(() => {
66
+ if (!settings) {
67
+ return;
68
+ }
69
+
70
+ const cleanup = editor?.store.listen(
71
+ ({ changes: { updated } }) => {
72
+ for (const [id, [from, to]] of Object.entries(updated)) {
73
+ if (id === 'instance:instance') {
74
+ const fromInstance = from as TLInstance;
75
+ const toInstance = to as TLInstance;
76
+ if (fromInstance.isGridMode !== toInstance.isGridMode) {
77
+ settings.showGrid = toInstance.isGridMode;
78
+ }
79
+ }
80
+ }
81
+ },
82
+ { source: 'user', scope: 'all' },
83
+ );
84
+
85
+ // TODO(burdon): Combine.
86
+ return () => cleanup?.();
87
+ }, [settings, editor]);
88
+
89
+ // Editor events.
90
+ useEffect(() => {
91
+ // https://tldraw.dev/examples/editor-api/canvas-events
92
+ const handleEvent = ({ type, name }: TLEventInfo) => {
93
+ if (type === 'pointer' && name === 'pointer_up') {
94
+ // Defer: the 'event' stream fires before the active tool commits its shape to the
95
+ // store, so an immediate save flushes one gesture behind (losing the final stroke).
96
+ setTimeout(() => adapter.save());
97
+ }
98
+ };
99
+
100
+ editor?.on('event', handleEvent);
101
+ return () => {
102
+ editor?.off('event', handleEvent);
103
+ };
104
+ }, [adapter, editor]);
105
+
106
+ // UI state.
107
+ useEffect(() => {
108
+ if (editor) {
109
+ editor.user.updateUserPreferences({
110
+ // TODO(burdon): Adjust snap threshold.
111
+ isSnapMode: true,
112
+ });
113
+ editor.updateInstanceState({
114
+ isGridMode: settings?.showGrid !== false && !hideUi,
115
+ isReadonly: readonly || hideUi,
116
+ });
117
+ if (readonly || hideUi) {
118
+ editor.setCurrentTool('hand');
119
+ }
120
+ }
121
+ }, [editor, settings, hideUi, readonly]);
122
+
123
+ // Zoom to fit.
124
+ const { ref: resizeRef, width = 0, height } = useResizeDetector();
125
+ const containerRef = useMergeRefs([forwardedRef, resizeRef]);
126
+ const [ready, setReady] = useState(!autoCenter);
127
+ useEffect(() => {
128
+ if (!editor || !adapter || width === undefined || height === undefined) {
129
+ return;
130
+ }
131
+
132
+ const isLocked = readonly || hideUi;
133
+
134
+ // Unlock to allow programmatic camera positioning.
135
+ editor.setCameraOptions({ isLocked: false });
136
+
137
+ // Set frame so that top left of grid is inset with our border (if no content).
138
+ editor.setCamera({ x: -1, y: -1, z: 1 }, { animation: { duration: 0 } });
139
+ editor.resetZoom();
140
+
141
+ setReady(true);
142
+ if (!autoCenter) {
143
+ editor.setCameraOptions({ isLocked: isLocked });
144
+ return;
145
+ }
146
+
147
+ const zoom = () => {
148
+ zoomToFit(editor, width, height, false);
149
+ };
150
+
151
+ zoom();
152
+ editor.setCameraOptions({ isLocked: isLocked });
153
+
154
+ let timer: ReturnType<typeof setTimeout> | undefined;
155
+ const onUpdate = () => {
156
+ clearTimeout(timer);
157
+ timer = setTimeout(() => {
158
+ editor.setCameraOptions({ isLocked: false });
159
+ zoom();
160
+ editor.setCameraOptions({ isLocked: isLocked });
161
+ }, 200);
162
+ };
163
+ const subscription = isLocked ? adapter.store?.listen(() => onUpdate(), { scope: 'document' }) : undefined;
164
+ return () => {
165
+ clearTimeout(timer);
166
+ subscription?.();
167
+ };
168
+ }, [editor, adapter, width, height, autoCenter, readonly, hideUi]);
169
+
170
+ // NOTE: Currently copying assets to composer-app public/assets/tldraw.
171
+ // https://tldraw.dev/installation#Self-hosting-static-assets
172
+ const assetUrls: TLUiAssetUrlOverrides = useMemo(() => {
173
+ if (!assetsBaseUrl) {
174
+ return undefined;
175
+ }
176
+
177
+ return defaultsDeep(
178
+ {
179
+ // Change default draw font.
180
+ // TODO(burdon): Change icon to match font.
181
+ fonts: { draw: `${assetsBaseUrl}/fonts/Montserrat-Regular.woff2` },
182
+ icons: {
183
+ 'thread-icon': `${assetsBaseUrl}/icons/icon/chat-teardrop-text.svg`,
184
+ },
185
+ },
186
+ getAssetUrls({ baseUrl: assetsBaseUrl }),
187
+ );
188
+ }, [assetsBaseUrl]);
189
+
190
+ const overrides = useMemo(
191
+ () => ({
192
+ actions: (_editor: Editor, actions: any, _helpers: any) => ({
193
+ ...actions,
194
+ snap: {
195
+ id: 'grid-snap',
196
+ label: 'Snap',
197
+ kbd: 's',
198
+ icon: 'horizontal-align-middle',
199
+ onSelect: () => {
200
+ void handleSnap(canvas);
201
+ },
202
+ },
203
+ }),
204
+ tools: (_editor: Editor, tools: any) => {
205
+ const newTools = { ...tools };
206
+ newTools[threadToolId] = {
207
+ id: threadToolId,
208
+ icon: 'thread-icon',
209
+ label: 'Comment', // TODO(Zan): Use translation lookup here.
210
+ onSelect: () => onThreadCreate?.(),
211
+ };
212
+ return newTools;
213
+ },
214
+ }),
215
+ [canvas, onThreadCreate],
216
+ );
217
+
218
+ const components = useMemo(
219
+ () => ({
220
+ DebugPanel: null,
221
+ Grid: gridComponents[settings?.gridType ?? 'mesh'],
222
+ HelpMenu: null,
223
+ MenuPanel: CustomMenu,
224
+ NavigationPanel: null,
225
+ StylePanel: CustomStylePanel,
226
+ TopPanel: null,
227
+ ZoomMenu: null,
228
+ Toolbar: (props: any) => (
229
+ <DefaultToolbar {...props}>
230
+ <DefaultToolbarContent toolsToSplice={[{ toolId: 'thread', position: 8 }]} />
231
+ </DefaultToolbar>
232
+ ),
233
+ }),
234
+ [settings],
235
+ );
236
+
237
+ if (!adapter.store) {
238
+ return null;
239
+ }
240
+
241
+ return (
242
+ <div
243
+ {...composableProps(props, { classNames: 'dx-expander' })}
244
+ style={{ visibility: ready ? 'visible' : 'hidden' }}
245
+ ref={containerRef}
246
+ >
247
+ <TldrawEditor
248
+ // Rebind when the adapter recreates its store (e.g. an effect-churn reopen) — a stale
249
+ // binding draws into an orphaned store whose change listeners are gone, so saves no-op.
250
+ key={`${Obj.getURI(canvas)}:${adapter.store.id}`}
251
+ store={adapter.store}
252
+ hideUi={hideUi}
253
+ inferDarkMode
254
+ className='outline-hidden!'
255
+ maxAssetSize={1024 * 1024}
256
+ assetUrls={assetUrls}
257
+ overrides={overrides}
258
+ components={components}
259
+ onMount={setEditor}
260
+ />
261
+ </div>
262
+ );
263
+ },
264
+ );
265
+
266
+ /**
267
+ * Fit content within the viewport and center it, zooming out for oversized content but never
268
+ * magnifying past 100% (zoom is capped at 1).
269
+ */
270
+ const zoomToFit = (editor: Editor, width: number, height: number, animate = true) => {
271
+ const commonBounds = editor.getCurrentPageBounds();
272
+ if (width && height && commonBounds?.width && commonBounds?.height) {
273
+ const padding = 60;
274
+ // Zoom out to fit oversized content; cap at 1 so small content is never zoomed in.
275
+ const zoom = Math.min(1, (width - padding) / commonBounds.width, (height - padding) / commonBounds.height);
276
+ const center = {
277
+ x: (width - commonBounds.width * zoom) / 2 / zoom - commonBounds.minX,
278
+ y: (height - commonBounds.height * zoom) / 2 / zoom - commonBounds.minY,
279
+ z: zoom,
280
+ };
281
+
282
+ editor.setCamera(center, animate ? { animation: { duration: 250 } } : undefined);
283
+ }
284
+ };
@@ -0,0 +1,9 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { CanvasComponent } from './Canvas';
6
+
7
+ export * from './Canvas';
8
+
9
+ export default CanvasComponent;