@dxos/app-framework 0.8.4-main.72ec0f3 → 0.8.4-main.74a063c4e0

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 (512) hide show
  1. package/.storybook/main.mts +2 -4
  2. package/.storybook/preview.mts +2 -2
  3. package/dist/lib/browser/capability-BBBBAPDI.mjs +38 -0
  4. package/dist/lib/browser/capability-BBBBAPDI.mjs.map +7 -0
  5. package/dist/lib/browser/capability-OP63CD5N.mjs +35 -0
  6. package/dist/lib/browser/capability-OP63CD5N.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-2CKCJ6PN.mjs +79 -0
  8. package/dist/lib/browser/chunk-2CKCJ6PN.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-F7FW2RK2.mjs +167 -0
  10. package/dist/lib/browser/chunk-F7FW2RK2.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-FU4GAFUQ.mjs +148 -0
  12. package/dist/lib/browser/chunk-FU4GAFUQ.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-GX4TUNM6.mjs +963 -0
  14. package/dist/lib/browser/chunk-GX4TUNM6.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-I34GF4NG.mjs +34 -0
  16. package/dist/lib/browser/chunk-I34GF4NG.mjs.map +7 -0
  17. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  18. package/dist/lib/browser/chunk-JKWMHZP6.mjs +80 -0
  19. package/dist/lib/browser/chunk-JKWMHZP6.mjs.map +7 -0
  20. package/dist/lib/browser/chunk-LVJW5EFU.mjs +157 -0
  21. package/dist/lib/browser/chunk-LVJW5EFU.mjs.map +7 -0
  22. package/dist/lib/browser/chunk-QSXYHXCE.mjs +48 -0
  23. package/dist/lib/browser/chunk-QSXYHXCE.mjs.map +7 -0
  24. package/dist/lib/browser/chunk-RFSO3JRG.mjs +1 -0
  25. package/dist/lib/browser/chunk-T3Y4AEKX.mjs +42 -0
  26. package/dist/lib/browser/chunk-T3Y4AEKX.mjs.map +7 -0
  27. package/dist/lib/browser/chunk-TGX63LTL.mjs +8 -0
  28. package/dist/lib/browser/chunk-TGX63LTL.mjs.map +7 -0
  29. package/dist/lib/browser/chunk-WPE6AL7I.mjs +905 -0
  30. package/dist/lib/browser/chunk-WPE6AL7I.mjs.map +7 -0
  31. package/dist/lib/browser/cli/index.mjs +90 -0
  32. package/dist/lib/browser/cli/index.mjs.map +7 -0
  33. package/dist/lib/browser/common/activation-events.mjs +24 -0
  34. package/dist/lib/browser/common/capabilities.mjs +46 -0
  35. package/dist/lib/browser/core/activation-event.mjs +20 -0
  36. package/dist/lib/browser/core/activation-event.mjs.map +7 -0
  37. package/dist/lib/browser/core/capability.mjs +30 -0
  38. package/dist/lib/browser/core/capability.mjs.map +7 -0
  39. package/dist/lib/browser/core/plugin-manager.mjs +15 -0
  40. package/dist/lib/browser/core/plugin-manager.mjs.map +7 -0
  41. package/dist/lib/browser/core/plugin.mjs +29 -0
  42. package/dist/lib/browser/core/plugin.mjs.map +7 -0
  43. package/dist/lib/browser/core/url-loader.mjs +12 -0
  44. package/dist/lib/browser/core/url-loader.mjs.map +7 -0
  45. package/dist/lib/browser/index.mjs +92 -121
  46. package/dist/lib/browser/index.mjs.map +4 -4
  47. package/dist/lib/browser/invoker-capability-H5PPENOC.mjs +43 -0
  48. package/dist/lib/browser/invoker-capability-H5PPENOC.mjs.map +7 -0
  49. package/dist/lib/browser/meta.json +1 -1
  50. package/dist/lib/browser/testing/index.mjs +108 -40
  51. package/dist/lib/browser/testing/index.mjs.map +4 -4
  52. package/dist/lib/browser/ui/index.mjs +44 -0
  53. package/dist/lib/browser/ui/index.mjs.map +7 -0
  54. package/dist/lib/node-esm/capability-AWBEMRYR.mjs +39 -0
  55. package/dist/lib/node-esm/capability-AWBEMRYR.mjs.map +7 -0
  56. package/dist/lib/node-esm/capability-WFEG6CIZ.mjs +36 -0
  57. package/dist/lib/node-esm/capability-WFEG6CIZ.mjs.map +7 -0
  58. package/dist/lib/node-esm/chunk-42KBWDE4.mjs +80 -0
  59. package/dist/lib/node-esm/chunk-42KBWDE4.mjs.map +7 -0
  60. package/dist/lib/node-esm/chunk-4A3ZCMI3.mjs +158 -0
  61. package/dist/lib/node-esm/chunk-4A3ZCMI3.mjs.map +7 -0
  62. package/dist/lib/node-esm/chunk-BCEOLX47.mjs +964 -0
  63. package/dist/lib/node-esm/chunk-BCEOLX47.mjs.map +7 -0
  64. package/dist/lib/node-esm/chunk-EL3R25OQ.mjs +2 -0
  65. package/dist/lib/node-esm/chunk-EL3R25OQ.mjs.map +7 -0
  66. package/dist/lib/node-esm/chunk-FKE4Z3D6.mjs +10 -0
  67. package/dist/lib/node-esm/chunk-FKE4Z3D6.mjs.map +7 -0
  68. package/dist/lib/node-esm/chunk-G3RTFSNG.mjs +81 -0
  69. package/dist/lib/node-esm/chunk-G3RTFSNG.mjs.map +7 -0
  70. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  71. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
  72. package/dist/lib/node-esm/chunk-LQKOTNJW.mjs +906 -0
  73. package/dist/lib/node-esm/chunk-LQKOTNJW.mjs.map +7 -0
  74. package/dist/lib/node-esm/chunk-ULUEXB7Q.mjs +149 -0
  75. package/dist/lib/node-esm/chunk-ULUEXB7Q.mjs.map +7 -0
  76. package/dist/lib/node-esm/chunk-URWHJQT2.mjs +168 -0
  77. package/dist/lib/node-esm/chunk-URWHJQT2.mjs.map +7 -0
  78. package/dist/lib/node-esm/chunk-VKHGNEDB.mjs +43 -0
  79. package/dist/lib/node-esm/chunk-VKHGNEDB.mjs.map +7 -0
  80. package/dist/lib/node-esm/chunk-WZCSOX5Q.mjs +35 -0
  81. package/dist/lib/node-esm/chunk-WZCSOX5Q.mjs.map +7 -0
  82. package/dist/lib/node-esm/chunk-ZZ7CKK6W.mjs +49 -0
  83. package/dist/lib/node-esm/chunk-ZZ7CKK6W.mjs.map +7 -0
  84. package/dist/lib/node-esm/cli/index.mjs +91 -0
  85. package/dist/lib/node-esm/cli/index.mjs.map +7 -0
  86. package/dist/lib/node-esm/common/activation-events.mjs +25 -0
  87. package/dist/lib/node-esm/common/activation-events.mjs.map +7 -0
  88. package/dist/lib/node-esm/common/capabilities.mjs +47 -0
  89. package/dist/lib/node-esm/common/capabilities.mjs.map +7 -0
  90. package/dist/lib/node-esm/core/activation-event.mjs +21 -0
  91. package/dist/lib/node-esm/core/activation-event.mjs.map +7 -0
  92. package/dist/lib/node-esm/core/capability.mjs +31 -0
  93. package/dist/lib/node-esm/core/capability.mjs.map +7 -0
  94. package/dist/lib/node-esm/core/plugin-manager.mjs +16 -0
  95. package/dist/lib/node-esm/core/plugin-manager.mjs.map +7 -0
  96. package/dist/lib/node-esm/core/plugin.mjs +30 -0
  97. package/dist/lib/node-esm/core/plugin.mjs.map +7 -0
  98. package/dist/lib/node-esm/core/url-loader.mjs +13 -0
  99. package/dist/lib/node-esm/core/url-loader.mjs.map +7 -0
  100. package/dist/lib/node-esm/index.mjs +92 -121
  101. package/dist/lib/node-esm/index.mjs.map +4 -4
  102. package/dist/lib/node-esm/invoker-capability-S3ZA527J.mjs +44 -0
  103. package/dist/lib/node-esm/invoker-capability-S3ZA527J.mjs.map +7 -0
  104. package/dist/lib/node-esm/meta.json +1 -1
  105. package/dist/lib/node-esm/testing/index.mjs +108 -40
  106. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  107. package/dist/lib/node-esm/ui/index.mjs +45 -0
  108. package/dist/lib/node-esm/ui/index.mjs.map +7 -0
  109. package/dist/plugin/node-esm/index.mjs +384 -0
  110. package/dist/plugin/node-esm/index.mjs.map +7 -0
  111. package/dist/plugin/node-esm/meta.json +1 -0
  112. package/dist/types/src/cli/cli.d.ts +39 -0
  113. package/dist/types/src/cli/cli.d.ts.map +1 -0
  114. package/dist/types/src/cli/index.d.ts +2 -0
  115. package/dist/types/src/cli/index.d.ts.map +1 -0
  116. package/dist/types/src/common/activation-events.d.ts +27 -0
  117. package/dist/types/src/common/activation-events.d.ts.map +1 -0
  118. package/dist/types/src/common/capabilities.d.ts +109 -194
  119. package/dist/types/src/common/capabilities.d.ts.map +1 -1
  120. package/dist/types/src/common/index.d.ts +4 -8
  121. package/dist/types/src/common/index.d.ts.map +1 -1
  122. package/dist/types/src/common/operations.d.ts +19 -0
  123. package/dist/types/src/common/operations.d.ts.map +1 -0
  124. package/dist/types/src/common/translations.d.ts +7 -7
  125. package/dist/types/src/common/translations.d.ts.map +1 -1
  126. package/dist/types/src/context.d.ts +5 -0
  127. package/dist/types/src/context.d.ts.map +1 -0
  128. package/dist/types/src/core/{events.d.ts → activation-event.d.ts} +7 -7
  129. package/dist/types/src/core/activation-event.d.ts.map +1 -0
  130. package/dist/types/src/core/capability-manager.d.ts +48 -0
  131. package/dist/types/src/core/capability-manager.d.ts.map +1 -0
  132. package/dist/types/src/core/capability-manager.test.d.ts +2 -0
  133. package/dist/types/src/core/capability-manager.test.d.ts.map +1 -0
  134. package/dist/types/src/core/capability.d.ts +156 -0
  135. package/dist/types/src/core/capability.d.ts.map +1 -0
  136. package/dist/types/src/core/index.d.ts +6 -4
  137. package/dist/types/src/core/index.d.ts.map +1 -1
  138. package/dist/types/src/core/plugin-manager.d.ts +73 -0
  139. package/dist/types/src/core/plugin-manager.d.ts.map +1 -0
  140. package/dist/types/src/core/plugin-manager.test.d.ts +2 -0
  141. package/dist/types/src/core/plugin-manager.test.d.ts.map +1 -0
  142. package/dist/types/src/core/plugin.d.ts +98 -35
  143. package/dist/types/src/core/plugin.d.ts.map +1 -1
  144. package/dist/types/src/core/url-loader.d.ts +25 -0
  145. package/dist/types/src/core/url-loader.d.ts.map +1 -0
  146. package/dist/types/src/core/url-loader.test.d.ts +2 -0
  147. package/dist/types/src/core/url-loader.test.d.ts.map +1 -0
  148. package/dist/types/src/index.d.ts +3 -2
  149. package/dist/types/src/index.d.ts.map +1 -1
  150. package/dist/types/src/plugin-operation/OperationPlugin.d.ts +3 -0
  151. package/dist/types/src/plugin-operation/OperationPlugin.d.ts.map +1 -0
  152. package/dist/types/src/plugin-operation/history/capability.d.ts +7 -0
  153. package/dist/types/src/plugin-operation/history/capability.d.ts.map +1 -0
  154. package/dist/types/src/plugin-operation/history/errors.d.ts +32 -0
  155. package/dist/types/src/plugin-operation/history/errors.d.ts.map +1 -0
  156. package/dist/types/src/plugin-operation/history/history-tracker.d.ts +18 -0
  157. package/dist/types/src/plugin-operation/history/history-tracker.d.ts.map +1 -0
  158. package/dist/types/src/plugin-operation/history/history-tracker.test.d.ts +2 -0
  159. package/dist/types/src/plugin-operation/history/history-tracker.test.d.ts.map +1 -0
  160. package/dist/types/src/plugin-operation/history/index.d.ts +6 -0
  161. package/dist/types/src/plugin-operation/history/index.d.ts.map +1 -0
  162. package/dist/types/src/plugin-operation/history/types.d.ts +13 -0
  163. package/dist/types/src/plugin-operation/history/types.d.ts.map +1 -0
  164. package/dist/types/src/plugin-operation/history/undo-mapping.d.ts +101 -0
  165. package/dist/types/src/plugin-operation/history/undo-mapping.d.ts.map +1 -0
  166. package/dist/types/src/plugin-operation/history/undo-registry.d.ts +23 -0
  167. package/dist/types/src/plugin-operation/history/undo-registry.d.ts.map +1 -0
  168. package/dist/types/src/plugin-operation/history/undo-registry.test.d.ts +2 -0
  169. package/dist/types/src/plugin-operation/history/undo-registry.test.d.ts.map +1 -0
  170. package/dist/types/src/plugin-operation/index.d.ts +3 -0
  171. package/dist/types/src/plugin-operation/index.d.ts.map +1 -0
  172. package/dist/types/src/plugin-operation/invoker-capability.d.ts +6 -0
  173. package/dist/types/src/plugin-operation/invoker-capability.d.ts.map +1 -0
  174. package/dist/types/src/plugin-operation/meta.d.ts +3 -0
  175. package/dist/types/src/plugin-operation/meta.d.ts.map +1 -0
  176. package/dist/types/src/plugin-operation/testing.d.ts +58 -0
  177. package/dist/types/src/plugin-operation/testing.d.ts.map +1 -0
  178. package/dist/types/src/plugin-runtime/RuntimePlugin.d.ts +3 -0
  179. package/dist/types/src/plugin-runtime/RuntimePlugin.d.ts.map +1 -0
  180. package/dist/types/src/plugin-runtime/capability.d.ts +6 -0
  181. package/dist/types/src/plugin-runtime/capability.d.ts.map +1 -0
  182. package/dist/types/src/plugin-runtime/index.d.ts +2 -0
  183. package/dist/types/src/plugin-runtime/index.d.ts.map +1 -0
  184. package/dist/types/src/plugin-runtime/meta.d.ts +3 -0
  185. package/dist/types/src/plugin-runtime/meta.d.ts.map +1 -0
  186. package/dist/types/src/testing/index.d.ts +1 -0
  187. package/dist/types/src/testing/index.d.ts.map +1 -1
  188. package/dist/types/src/testing/service.d.ts +8 -0
  189. package/dist/types/src/testing/service.d.ts.map +1 -0
  190. package/dist/types/src/testing/withPluginManager.d.ts +4 -4
  191. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
  192. package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -1
  193. package/dist/types/src/ui/components/App/App.d.ts +9 -0
  194. package/dist/types/src/ui/components/App/App.d.ts.map +1 -0
  195. package/dist/types/src/ui/components/App/App.stories.d.ts +19 -0
  196. package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -0
  197. package/dist/types/src/ui/components/App/index.d.ts +2 -0
  198. package/dist/types/src/ui/components/App/index.d.ts.map +1 -0
  199. package/dist/types/src/{react/Surface.stories.d.ts → ui/components/PluginManager/PluginManagerContext.stories.d.ts} +2 -3
  200. package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts.map +1 -0
  201. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts +10 -0
  202. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts.map +1 -0
  203. package/dist/types/src/ui/components/PluginManager/index.d.ts +2 -0
  204. package/dist/types/src/ui/components/PluginManager/index.d.ts.map +1 -0
  205. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +12 -0
  206. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -0
  207. package/dist/types/src/{react/App.stories.d.ts → ui/components/Surface/SurfaceComponent.stories.d.ts} +1 -1
  208. package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -0
  209. package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts +11 -0
  210. package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts.map +1 -0
  211. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts +48 -0
  212. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts.map +1 -0
  213. package/dist/types/src/ui/components/Surface/context.d.ts +5 -0
  214. package/dist/types/src/ui/components/Surface/context.d.ts.map +1 -0
  215. package/dist/types/src/ui/components/Surface/index.d.ts +26 -0
  216. package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -0
  217. package/dist/types/src/ui/components/Surface/types.d.ts +96 -0
  218. package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -0
  219. package/dist/types/src/ui/components/index.d.ts +4 -0
  220. package/dist/types/src/ui/components/index.d.ts.map +1 -0
  221. package/dist/types/src/ui/hooks/index.d.ts +6 -0
  222. package/dist/types/src/ui/hooks/index.d.ts.map +1 -0
  223. package/dist/types/src/{react → ui/hooks}/useApp.d.ts +30 -12
  224. package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -0
  225. package/dist/types/src/ui/hooks/useApp.test.d.ts +2 -0
  226. package/dist/types/src/ui/hooks/useApp.test.d.ts.map +1 -0
  227. package/dist/types/src/ui/hooks/useCapabilities.d.ts +31 -0
  228. package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -0
  229. package/dist/types/src/{react → ui/hooks}/useLoading.d.ts +1 -2
  230. package/dist/types/src/ui/hooks/useLoading.d.ts.map +1 -0
  231. package/dist/types/src/ui/hooks/useSettingsState.d.ts +10 -0
  232. package/dist/types/src/ui/hooks/useSettingsState.d.ts.map +1 -0
  233. package/dist/types/src/ui/hooks/useSurface.d.ts +3 -0
  234. package/dist/types/src/ui/hooks/useSurface.d.ts.map +1 -0
  235. package/dist/types/src/ui/index.d.ts +3 -0
  236. package/dist/types/src/ui/index.d.ts.map +1 -0
  237. package/dist/types/src/vite-plugin/composer-plugin.d.ts +18 -0
  238. package/dist/types/src/vite-plugin/composer-plugin.d.ts.map +1 -0
  239. package/dist/types/src/vite-plugin/import-map-plugin.d.ts +16 -0
  240. package/dist/types/src/vite-plugin/import-map-plugin.d.ts.map +1 -0
  241. package/dist/types/src/vite-plugin/index.d.ts +3 -0
  242. package/dist/types/src/vite-plugin/index.d.ts.map +1 -0
  243. package/dist/types/src/vite-plugin/packages.d.ts +7 -0
  244. package/dist/types/src/vite-plugin/packages.d.ts.map +1 -0
  245. package/dist/types/tsconfig.tsbuildinfo +1 -1
  246. package/moon.yml +24 -6
  247. package/package.json +130 -50
  248. package/src/cli/cli.ts +107 -0
  249. package/src/{playground/debug → cli}/index.ts +1 -1
  250. package/src/common/activation-events.ts +44 -0
  251. package/src/common/capabilities.ts +168 -210
  252. package/src/common/index.ts +4 -8
  253. package/src/common/operations.ts +35 -0
  254. package/src/common/translations.ts +17 -9
  255. package/src/context.ts +9 -0
  256. package/src/core/{events.ts → activation-event.ts} +10 -7
  257. package/src/core/capability-manager.test.ts +151 -0
  258. package/src/core/capability-manager.ts +192 -0
  259. package/src/core/capability.ts +247 -0
  260. package/src/core/index.ts +6 -4
  261. package/src/core/plugin-manager.test.ts +1113 -0
  262. package/src/core/plugin-manager.ts +883 -0
  263. package/src/core/plugin.ts +230 -40
  264. package/src/core/url-loader.test.ts +79 -0
  265. package/src/core/url-loader.ts +148 -0
  266. package/src/index.ts +3 -2
  267. package/src/plugin-operation/OperationPlugin.ts +24 -0
  268. package/src/plugin-operation/history/capability.ts +36 -0
  269. package/src/plugin-operation/history/errors.ts +7 -0
  270. package/src/plugin-operation/history/history-tracker.test.ts +373 -0
  271. package/src/plugin-operation/history/history-tracker.ts +128 -0
  272. package/src/plugin-operation/history/index.ts +9 -0
  273. package/src/plugin-operation/history/types.ts +17 -0
  274. package/src/plugin-operation/history/undo-mapping.ts +135 -0
  275. package/src/plugin-operation/history/undo-registry.test.ts +72 -0
  276. package/src/plugin-operation/history/undo-registry.ts +54 -0
  277. package/src/plugin-operation/index.ts +6 -0
  278. package/src/plugin-operation/invoker-capability.ts +54 -0
  279. package/src/plugin-operation/meta.ts +11 -0
  280. package/src/plugin-operation/testing.ts +154 -0
  281. package/src/plugin-runtime/RuntimePlugin.ts +19 -0
  282. package/src/plugin-runtime/capability.ts +53 -0
  283. package/src/{playground/logger → plugin-runtime}/index.ts +1 -1
  284. package/src/plugin-runtime/meta.ts +11 -0
  285. package/src/testing/index.ts +1 -0
  286. package/src/testing/service.ts +52 -0
  287. package/src/testing/withPluginManager.stories.tsx +7 -8
  288. package/src/testing/withPluginManager.tsx +63 -38
  289. package/src/ui/components/App/App.stories.tsx +92 -0
  290. package/src/{react → ui/components/App}/App.tsx +11 -12
  291. package/src/{playground/layout → ui/components/App}/index.ts +1 -1
  292. package/src/ui/components/PluginManager/PluginManagerContext.stories.tsx +183 -0
  293. package/src/{react → ui/components/PluginManager}/PluginManagerProvider.ts +3 -3
  294. package/src/ui/components/PluginManager/index.ts +5 -0
  295. package/src/{react/Surface.stories.tsx → ui/components/Surface/SurfaceComponent.stories.tsx} +55 -36
  296. package/src/ui/components/Surface/SurfaceComponent.tsx +266 -0
  297. package/src/ui/components/Surface/SurfaceInfo.tsx +107 -0
  298. package/src/ui/components/Surface/SurfaceProfilerContext.tsx +207 -0
  299. package/src/ui/components/Surface/context.ts +12 -0
  300. package/src/ui/components/Surface/index.ts +35 -0
  301. package/src/ui/components/Surface/types.ts +117 -0
  302. package/src/ui/components/index.ts +7 -0
  303. package/src/ui/hooks/index.ts +9 -0
  304. package/src/ui/hooks/useApp.test.tsx +159 -0
  305. package/src/ui/hooks/useApp.tsx +289 -0
  306. package/src/ui/hooks/useCapabilities.ts +67 -0
  307. package/src/{react → ui/hooks}/useLoading.tsx +4 -6
  308. package/src/ui/hooks/useSettingsState.ts +26 -0
  309. package/src/ui/hooks/useSurface.ts +13 -0
  310. package/src/ui/index.ts +6 -0
  311. package/src/vite-plugin/composer-plugin.ts +128 -0
  312. package/src/vite-plugin/import-map-plugin.ts +314 -0
  313. package/src/vite-plugin/index.ts +6 -0
  314. package/src/vite-plugin/packages.ts +29 -0
  315. package/tsconfig.json +12 -27
  316. package/tsconfig.node.json +2 -4
  317. package/typedoc.json +2 -4
  318. package/vitest.config.ts +1 -1
  319. package/.swc/plugins/linux_x86_64_19.0.0/fce1bdb8e20a094e4af08bad09cc81497ed0e2e7c51223b07d371063cca18429.wasmer-v7 +0 -0
  320. package/dist/lib/browser/app-graph-builder-OIEZZC45.mjs +0 -138
  321. package/dist/lib/browser/app-graph-builder-OIEZZC45.mjs.map +0 -7
  322. package/dist/lib/browser/chunk-SCPE4ZO2.mjs +0 -35
  323. package/dist/lib/browser/chunk-SCPE4ZO2.mjs.map +0 -7
  324. package/dist/lib/browser/chunk-VFUKEZIN.mjs +0 -483
  325. package/dist/lib/browser/chunk-VFUKEZIN.mjs.map +0 -7
  326. package/dist/lib/browser/chunk-WPW5VVAX.mjs +0 -1651
  327. package/dist/lib/browser/chunk-WPW5VVAX.mjs.map +0 -7
  328. package/dist/lib/browser/intent-dispatcher-LZ4AE66E.mjs +0 -11
  329. package/dist/lib/browser/intent-resolver-QVCKRX6G.mjs +0 -39
  330. package/dist/lib/browser/intent-resolver-QVCKRX6G.mjs.map +0 -7
  331. package/dist/lib/browser/react/index.mjs +0 -34
  332. package/dist/lib/browser/store-CNPHOYTJ.mjs +0 -30
  333. package/dist/lib/browser/store-CNPHOYTJ.mjs.map +0 -7
  334. package/dist/lib/node-esm/app-graph-builder-EBU4NVWD.mjs +0 -139
  335. package/dist/lib/node-esm/app-graph-builder-EBU4NVWD.mjs.map +0 -7
  336. package/dist/lib/node-esm/chunk-IJOHO66N.mjs +0 -484
  337. package/dist/lib/node-esm/chunk-IJOHO66N.mjs.map +0 -7
  338. package/dist/lib/node-esm/chunk-XJZGUJ3H.mjs +0 -1653
  339. package/dist/lib/node-esm/chunk-XJZGUJ3H.mjs.map +0 -7
  340. package/dist/lib/node-esm/chunk-ZX63QUGE.mjs +0 -37
  341. package/dist/lib/node-esm/chunk-ZX63QUGE.mjs.map +0 -7
  342. package/dist/lib/node-esm/intent-dispatcher-MGOJ3CHD.mjs +0 -12
  343. package/dist/lib/node-esm/intent-resolver-URF3HN3G.mjs +0 -40
  344. package/dist/lib/node-esm/intent-resolver-URF3HN3G.mjs.map +0 -7
  345. package/dist/lib/node-esm/react/index.mjs +0 -35
  346. package/dist/lib/node-esm/store-RK5B4XEL.mjs +0 -31
  347. package/dist/lib/node-esm/store-RK5B4XEL.mjs.map +0 -7
  348. package/dist/types/src/common/collaboration.d.ts +0 -20
  349. package/dist/types/src/common/collaboration.d.ts.map +0 -1
  350. package/dist/types/src/common/events.d.ts +0 -52
  351. package/dist/types/src/common/events.d.ts.map +0 -1
  352. package/dist/types/src/common/file.d.ts +0 -14
  353. package/dist/types/src/common/file.d.ts.map +0 -1
  354. package/dist/types/src/common/graph.d.ts +0 -21
  355. package/dist/types/src/common/graph.d.ts.map +0 -1
  356. package/dist/types/src/common/layout.d.ts +0 -279
  357. package/dist/types/src/common/layout.d.ts.map +0 -1
  358. package/dist/types/src/common/surface.d.ts +0 -68
  359. package/dist/types/src/common/surface.d.ts.map +0 -1
  360. package/dist/types/src/core/capabilities.d.ts +0 -117
  361. package/dist/types/src/core/capabilities.d.ts.map +0 -1
  362. package/dist/types/src/core/capabilities.test.d.ts +0 -2
  363. package/dist/types/src/core/capabilities.test.d.ts.map +0 -1
  364. package/dist/types/src/core/events.d.ts.map +0 -1
  365. package/dist/types/src/core/manager.d.ts +0 -126
  366. package/dist/types/src/core/manager.d.ts.map +0 -1
  367. package/dist/types/src/core/manager.test.d.ts +0 -2
  368. package/dist/types/src/core/manager.test.d.ts.map +0 -1
  369. package/dist/types/src/playground/debug/Debug.d.ts +0 -6
  370. package/dist/types/src/playground/debug/Debug.d.ts.map +0 -1
  371. package/dist/types/src/playground/debug/index.d.ts +0 -2
  372. package/dist/types/src/playground/debug/index.d.ts.map +0 -1
  373. package/dist/types/src/playground/debug/plugin.d.ts +0 -2
  374. package/dist/types/src/playground/debug/plugin.d.ts.map +0 -1
  375. package/dist/types/src/playground/generator/Main.d.ts +0 -6
  376. package/dist/types/src/playground/generator/Main.d.ts.map +0 -1
  377. package/dist/types/src/playground/generator/Toolbar.d.ts +0 -6
  378. package/dist/types/src/playground/generator/Toolbar.d.ts.map +0 -1
  379. package/dist/types/src/playground/generator/generator.d.ts +0 -7
  380. package/dist/types/src/playground/generator/generator.d.ts.map +0 -1
  381. package/dist/types/src/playground/generator/index.d.ts +0 -3
  382. package/dist/types/src/playground/generator/index.d.ts.map +0 -1
  383. package/dist/types/src/playground/generator/plugin.d.ts +0 -2
  384. package/dist/types/src/playground/generator/plugin.d.ts.map +0 -1
  385. package/dist/types/src/playground/layout/Layout.d.ts +0 -8
  386. package/dist/types/src/playground/layout/Layout.d.ts.map +0 -1
  387. package/dist/types/src/playground/layout/index.d.ts +0 -2
  388. package/dist/types/src/playground/layout/index.d.ts.map +0 -1
  389. package/dist/types/src/playground/layout/plugin.d.ts +0 -2
  390. package/dist/types/src/playground/layout/plugin.d.ts.map +0 -1
  391. package/dist/types/src/playground/logger/Toolbar.d.ts +0 -6
  392. package/dist/types/src/playground/logger/Toolbar.d.ts.map +0 -1
  393. package/dist/types/src/playground/logger/index.d.ts +0 -2
  394. package/dist/types/src/playground/logger/index.d.ts.map +0 -1
  395. package/dist/types/src/playground/logger/plugin.d.ts +0 -2
  396. package/dist/types/src/playground/logger/plugin.d.ts.map +0 -1
  397. package/dist/types/src/playground/logger/schema.d.ts +0 -13
  398. package/dist/types/src/playground/logger/schema.d.ts.map +0 -1
  399. package/dist/types/src/playground/playground.stories.d.ts +0 -11
  400. package/dist/types/src/playground/playground.stories.d.ts.map +0 -1
  401. package/dist/types/src/plugin-intent/IntentPlugin.d.ts +0 -2
  402. package/dist/types/src/plugin-intent/IntentPlugin.d.ts.map +0 -1
  403. package/dist/types/src/plugin-intent/actions.d.ts +0 -36
  404. package/dist/types/src/plugin-intent/actions.d.ts.map +0 -1
  405. package/dist/types/src/plugin-intent/errors.d.ts +0 -16
  406. package/dist/types/src/plugin-intent/errors.d.ts.map +0 -1
  407. package/dist/types/src/plugin-intent/index.d.ts +0 -6
  408. package/dist/types/src/plugin-intent/index.d.ts.map +0 -1
  409. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts +0 -139
  410. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts.map +0 -1
  411. package/dist/types/src/plugin-intent/intent-dispatcher.test.d.ts +0 -2
  412. package/dist/types/src/plugin-intent/intent-dispatcher.test.d.ts.map +0 -1
  413. package/dist/types/src/plugin-intent/intent.d.ts +0 -63
  414. package/dist/types/src/plugin-intent/intent.d.ts.map +0 -1
  415. package/dist/types/src/plugin-intent/meta.d.ts +0 -3
  416. package/dist/types/src/plugin-intent/meta.d.ts.map +0 -1
  417. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts +0 -2
  418. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts.map +0 -1
  419. package/dist/types/src/plugin-settings/actions.d.ts +0 -25
  420. package/dist/types/src/plugin-settings/actions.d.ts.map +0 -1
  421. package/dist/types/src/plugin-settings/app-graph-builder.d.ts +0 -4
  422. package/dist/types/src/plugin-settings/app-graph-builder.d.ts.map +0 -1
  423. package/dist/types/src/plugin-settings/index.d.ts +0 -3
  424. package/dist/types/src/plugin-settings/index.d.ts.map +0 -1
  425. package/dist/types/src/plugin-settings/intent-resolver.d.ts +0 -4
  426. package/dist/types/src/plugin-settings/intent-resolver.d.ts.map +0 -1
  427. package/dist/types/src/plugin-settings/meta.d.ts +0 -3
  428. package/dist/types/src/plugin-settings/meta.d.ts.map +0 -1
  429. package/dist/types/src/plugin-settings/store.d.ts +0 -5
  430. package/dist/types/src/plugin-settings/store.d.ts.map +0 -1
  431. package/dist/types/src/plugin-settings/translations.d.ts +0 -11
  432. package/dist/types/src/plugin-settings/translations.d.ts.map +0 -1
  433. package/dist/types/src/react/App.d.ts +0 -10
  434. package/dist/types/src/react/App.d.ts.map +0 -1
  435. package/dist/types/src/react/App.stories.d.ts.map +0 -1
  436. package/dist/types/src/react/DefaultFallback.d.ts +0 -8
  437. package/dist/types/src/react/DefaultFallback.d.ts.map +0 -1
  438. package/dist/types/src/react/ErrorBoundary.d.ts +0 -30
  439. package/dist/types/src/react/ErrorBoundary.d.ts.map +0 -1
  440. package/dist/types/src/react/IntentContext.d.ts +0 -8
  441. package/dist/types/src/react/IntentContext.d.ts.map +0 -1
  442. package/dist/types/src/react/PluginManagerProvider.d.ts +0 -10
  443. package/dist/types/src/react/PluginManagerProvider.d.ts.map +0 -1
  444. package/dist/types/src/react/Surface.d.ts +0 -12
  445. package/dist/types/src/react/Surface.d.ts.map +0 -1
  446. package/dist/types/src/react/Surface.stories.d.ts.map +0 -1
  447. package/dist/types/src/react/common.d.ts +0 -13
  448. package/dist/types/src/react/common.d.ts.map +0 -1
  449. package/dist/types/src/react/index.d.ts +0 -9
  450. package/dist/types/src/react/index.d.ts.map +0 -1
  451. package/dist/types/src/react/types.d.ts +0 -14
  452. package/dist/types/src/react/types.d.ts.map +0 -1
  453. package/dist/types/src/react/useApp.d.ts.map +0 -1
  454. package/dist/types/src/react/useCapabilities.d.ts +0 -13
  455. package/dist/types/src/react/useCapabilities.d.ts.map +0 -1
  456. package/dist/types/src/react/useIntentResolver.d.ts +0 -3
  457. package/dist/types/src/react/useIntentResolver.d.ts.map +0 -1
  458. package/dist/types/src/react/useLoading.d.ts.map +0 -1
  459. package/src/common/collaboration.ts +0 -18
  460. package/src/common/events.ts +0 -79
  461. package/src/common/file.ts +0 -22
  462. package/src/common/graph.ts +0 -30
  463. package/src/common/layout.ts +0 -277
  464. package/src/common/surface.ts +0 -88
  465. package/src/core/capabilities.test.ts +0 -136
  466. package/src/core/capabilities.ts +0 -263
  467. package/src/core/manager.test.ts +0 -516
  468. package/src/core/manager.ts +0 -604
  469. package/src/playground/debug/Debug.tsx +0 -39
  470. package/src/playground/debug/plugin.ts +0 -16
  471. package/src/playground/generator/Main.tsx +0 -70
  472. package/src/playground/generator/Toolbar.tsx +0 -47
  473. package/src/playground/generator/generator.ts +0 -48
  474. package/src/playground/generator/index.ts +0 -6
  475. package/src/playground/generator/plugin.ts +0 -22
  476. package/src/playground/layout/Layout.tsx +0 -33
  477. package/src/playground/layout/plugin.ts +0 -18
  478. package/src/playground/logger/Toolbar.tsx +0 -30
  479. package/src/playground/logger/plugin.ts +0 -41
  480. package/src/playground/logger/schema.ts +0 -12
  481. package/src/playground/playground.stories.tsx +0 -46
  482. package/src/plugin-intent/IntentPlugin.ts +0 -20
  483. package/src/plugin-intent/actions.ts +0 -31
  484. package/src/plugin-intent/errors.ts +0 -40
  485. package/src/plugin-intent/index.ts +0 -9
  486. package/src/plugin-intent/intent-dispatcher.test.ts +0 -286
  487. package/src/plugin-intent/intent-dispatcher.ts +0 -342
  488. package/src/plugin-intent/intent.ts +0 -154
  489. package/src/plugin-intent/meta.ts +0 -10
  490. package/src/plugin-settings/SettingsPlugin.ts +0 -34
  491. package/src/plugin-settings/actions.ts +0 -25
  492. package/src/plugin-settings/app-graph-builder.ts +0 -160
  493. package/src/plugin-settings/index.ts +0 -6
  494. package/src/plugin-settings/intent-resolver.ts +0 -35
  495. package/src/plugin-settings/meta.ts +0 -10
  496. package/src/plugin-settings/store.ts +0 -33
  497. package/src/plugin-settings/translations.ts +0 -19
  498. package/src/react/App.stories.tsx +0 -33
  499. package/src/react/DefaultFallback.tsx +0 -26
  500. package/src/react/ErrorBoundary.tsx +0 -56
  501. package/src/react/IntentContext.tsx +0 -35
  502. package/src/react/Surface.tsx +0 -109
  503. package/src/react/common.ts +0 -13
  504. package/src/react/index.ts +0 -14
  505. package/src/react/types.ts +0 -37
  506. package/src/react/useApp.tsx +0 -165
  507. package/src/react/useCapabilities.ts +0 -31
  508. package/src/react/useIntentResolver.ts +0 -22
  509. /package/dist/lib/browser/{intent-dispatcher-LZ4AE66E.mjs.map → chunk-J5LGTIGS.mjs.map} +0 -0
  510. /package/dist/lib/browser/{react/index.mjs.map → chunk-RFSO3JRG.mjs.map} +0 -0
  511. /package/dist/lib/{node-esm/intent-dispatcher-MGOJ3CHD.mjs.map → browser/common/activation-events.mjs.map} +0 -0
  512. /package/dist/lib/{node-esm/react/index.mjs.map → browser/common/capabilities.mjs.map} +0 -0
@@ -0,0 +1,266 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { useAtomValue } from '@effect-atom/atom-react';
6
+ import React, {
7
+ Fragment,
8
+ type NamedExoticComponent,
9
+ Profiler,
10
+ type RefAttributes,
11
+ Suspense,
12
+ forwardRef,
13
+ memo,
14
+ useEffect,
15
+ useMemo,
16
+ useRef,
17
+ } from 'react';
18
+
19
+ import { log } from '@dxos/log';
20
+ import { ErrorBoundary } from '@dxos/react-error-boundary';
21
+ import { useDefaultValue } from '@dxos/react-hooks';
22
+ import { byPosition } from '@dxos/util';
23
+
24
+ import { Capabilities } from '../../../common';
25
+ import { type CapabilityManager } from '../../../core';
26
+ import { usePluginManager } from '../PluginManager/PluginManagerProvider';
27
+ import { SurfaceContext } from './context';
28
+ import { SurfaceInfo } from './SurfaceInfo';
29
+ import { useSurfaceProfilerCallback } from './SurfaceProfilerContext';
30
+ import { type Definition, type Props, type WebComponentDefinition } from './types';
31
+
32
+ const DEBUG = import.meta.env.VITE_DEBUG;
33
+
34
+ const DEFAULT_PLACEHOLDER = <Fragment />;
35
+
36
+ /**
37
+ * Wrapper component for rendering Web Component surfaces.
38
+ * Handles creation, prop setting, and cleanup of Web Components.
39
+ */
40
+ const WebComponentWrapper = memo(
41
+ forwardRef<HTMLElement, Props & { definition: WebComponentDefinition }>(
42
+ ({ id, role, data, limit, definition, ...rest }, forwardedRef) => {
43
+ const containerRef = useRef<HTMLDivElement>(null);
44
+ const elementRef = useRef<HTMLElement | null>(null);
45
+ const propsRef = useRef({ id, role, data, limit, ...rest });
46
+
47
+ // Update props ref on every render
48
+ propsRef.current = { id, role, data, limit, ...rest };
49
+
50
+ // Create element only once
51
+ useEffect(() => {
52
+ if (!containerRef.current || elementRef.current) {
53
+ return;
54
+ }
55
+
56
+ // Create the Web Component
57
+ const element = document.createElement(definition.tagName);
58
+ elementRef.current = element;
59
+
60
+ // Set initial properties on the Web Component
61
+ Object.assign(element, propsRef.current);
62
+
63
+ // Append to container
64
+ containerRef.current.appendChild(element);
65
+
66
+ // Setup ref forwarding if provided
67
+ if (typeof forwardedRef === 'function') {
68
+ forwardedRef(element);
69
+ } else if (forwardedRef) {
70
+ forwardedRef.current = element;
71
+ }
72
+
73
+ // Cleanup on unmount to prevent memory leaks
74
+ return () => {
75
+ if (elementRef.current && containerRef.current?.contains(elementRef.current)) {
76
+ containerRef.current.removeChild(elementRef.current);
77
+ }
78
+ if (typeof forwardedRef === 'function') {
79
+ forwardedRef(null);
80
+ } else if (forwardedRef) {
81
+ forwardedRef.current = null;
82
+ }
83
+ elementRef.current = null;
84
+ };
85
+ }, [definition.tagName, forwardedRef]);
86
+
87
+ // Update props on existing element without recreating it
88
+ // This runs on every render to ensure all props (including those in `rest`) are kept up to date
89
+ useEffect(() => {
90
+ const element = elementRef.current;
91
+ if (!element) {
92
+ return;
93
+ }
94
+
95
+ // Update properties on the existing Web Component
96
+ Object.assign(element, propsRef.current);
97
+ });
98
+
99
+ return <div ref={containerRef} />;
100
+ },
101
+ ),
102
+ );
103
+
104
+ WebComponentWrapper.displayName = 'WebComponentWrapper';
105
+
106
+ /**
107
+ * Wrapper component that provides context for a surface.
108
+ */
109
+ // TODO(burdon): Allow DebugPlugin to provide different fallback using react-ui ErrorFallback.
110
+ const SurfaceContextProvider = memo(
111
+ forwardRef<HTMLElement, Props & { definition: Definition }>(
112
+ ({ id, role, data, limit, fallback = ErrorFallback, definition, ...rest }, forwardedRef) => {
113
+ const contextValue = useMemo(() => ({ id, role, data }), [id, role, data]);
114
+ const onProfilerRender = useSurfaceProfilerCallback();
115
+ const profilerId = `surface/${id}/${role}`;
116
+
117
+ // Handle Web Component surfaces
118
+ if (definition.kind === 'web-component') {
119
+ return (
120
+ <ErrorBoundary name='surface' resetKeys={[data]} FallbackComponent={fallback}>
121
+ <SurfaceContext.Provider value={contextValue}>
122
+ <WebComponentWrapper
123
+ id={id}
124
+ role={role}
125
+ data={data}
126
+ limit={limit}
127
+ definition={definition}
128
+ ref={forwardedRef}
129
+ {...rest}
130
+ />
131
+ </SurfaceContext.Provider>
132
+ </ErrorBoundary>
133
+ );
134
+ }
135
+
136
+ // Handle React component surfaces
137
+ const Component = definition.component;
138
+
139
+ // TODO(burdon): Remove from production build?
140
+ const debug = DEBUG || '__DX_DEBUG__' in window;
141
+ if (debug) {
142
+ return (
143
+ <ErrorBoundary name='surface' resetKeys={[data]} FallbackComponent={fallback}>
144
+ <div role='none' className='contents' data-id={id} data-role={role}>
145
+ <SurfaceContext.Provider value={contextValue}>
146
+ <SurfaceInfo ref={forwardedRef}>
147
+ {onProfilerRender && !profilerId.includes('org.dxos.plugin.debug') ? (
148
+ <Profiler id={profilerId} onRender={onProfilerRender}>
149
+ <Component id={id} role={role} data={data} limit={limit} {...rest} />
150
+ </Profiler>
151
+ ) : (
152
+ <Component id={id} role={role} data={data} limit={limit} {...rest} />
153
+ )}
154
+ </SurfaceInfo>
155
+ </SurfaceContext.Provider>
156
+ </div>
157
+ </ErrorBoundary>
158
+ );
159
+ }
160
+
161
+ return (
162
+ <ErrorBoundary name='surface' resetKeys={[data]} FallbackComponent={fallback}>
163
+ <div role='none' className='contents' data-id={id} data-role={role}>
164
+ <SurfaceContext.Provider value={contextValue}>
165
+ <Component id={id} role={role} data={data} limit={limit} {...rest} ref={forwardedRef} />
166
+ </SurfaceContext.Provider>
167
+ </div>
168
+ </ErrorBoundary>
169
+ );
170
+ },
171
+ ),
172
+ );
173
+
174
+ SurfaceContextProvider.displayName = 'SurfaceContextProvider';
175
+
176
+ /**
177
+ * A surface is a named region of the screen that can be populated by plugins.
178
+ */
179
+ // TODO(burdon): Remove `ref` since relying on this would be error prone.
180
+ export const SurfaceComponent: NamedExoticComponent<Props & RefAttributes<HTMLElement>> = memo(
181
+ forwardRef(({ id: _id, role, data: dataProp, limit, placeholder = DEFAULT_PLACEHOLDER, ...rest }, forwardedRef) => {
182
+ const data = useDefaultValue(dataProp, () => ({}));
183
+
184
+ // TODO(wittjosiah): This will make all surfaces depend on a single signal.
185
+ // This isn't ideal because it means that any change to the data will cause all surfaces to re-render.
186
+ // This effectively means that plugin modules which contribute surfaces need to all be activated at startup.
187
+ // This should be fine for now because it's how it worked prior to capabilities api anyway.
188
+ // In the future, it would be nice to be able to bucket the surface contributions by role.
189
+ const surfaces = useSurfaces();
190
+
191
+ // NOTE: Memoizing the candidates makes the surface not re-render based on reactivity within data.
192
+ const definitions = findCandidates(surfaces, { role, data });
193
+ const candidates = limit ? definitions.slice(0, limit) : definitions;
194
+ if (DEBUG && candidates.length === 0) {
195
+ log.warn('no candidates for surface', { role, data });
196
+ return null;
197
+ }
198
+
199
+ return (
200
+ <Suspense fallback={placeholder}>
201
+ {candidates.map((definition) => (
202
+ <SurfaceContextProvider
203
+ key={definition.id}
204
+ id={definition.id}
205
+ role={role}
206
+ data={data}
207
+ limit={limit}
208
+ definition={definition}
209
+ ref={forwardedRef}
210
+ {...rest}
211
+ />
212
+ ))}
213
+ </Suspense>
214
+ );
215
+ }),
216
+ );
217
+
218
+ SurfaceComponent.displayName = 'Surface';
219
+
220
+ // TODO(burdon): Make user facing, with telemetry.
221
+ const ErrorFallback = ({ error }: Props) => {
222
+ const { message } = error instanceof Error ? error : { message: String(error) };
223
+ return (
224
+ <div role='alert' data-testid='error-boundary-fallback'>
225
+ <h1 className='flex gap-2 text-sm mt-2 text-info-text'>{message}</h1>
226
+ </div>
227
+ );
228
+ };
229
+
230
+ const findCandidates = (surfaces: Definition[], { role, data }: Pick<Props, 'role' | 'data'>) => {
231
+ return Object.values(surfaces)
232
+ .filter((definition) =>
233
+ Array.isArray(definition.role) ? definition.role.includes(role) : definition.role === role,
234
+ )
235
+ .filter(({ filter }) => (filter ? filter(data ?? {}) : true))
236
+ .toSorted(byPosition);
237
+ };
238
+
239
+ /**
240
+ * @internal
241
+ */
242
+ export const useSurfaces = () => {
243
+ const manager = usePluginManager();
244
+ const surfacesByModule = useAtomValue(manager.capabilities.atomByModule(Capabilities.ReactSurface));
245
+ return useMemo(() => {
246
+ const result: Definition[] = [];
247
+ for (const [moduleId, surfaces] of Object.entries(surfacesByModule)) {
248
+ for (const def of surfaces.flat()) {
249
+ result.push({ ...def, id: `${moduleId}.${def.id}` });
250
+ }
251
+ }
252
+ return result;
253
+ }, [surfacesByModule]);
254
+ };
255
+
256
+ /**
257
+ * @returns `true` if there is a contributed surface which matches the specified role & data, `false` otherwise.
258
+ */
259
+ export const isSurfaceAvailable = (
260
+ capabilityManager: CapabilityManager.CapabilityManager,
261
+ { role, data }: Pick<Props, 'role' | 'data'>,
262
+ ) => {
263
+ const surfaces = capabilityManager.getAll(Capabilities.ReactSurface);
264
+ const candidates = findCandidates(surfaces.flat(), { role, data });
265
+ return candidates.length > 0;
266
+ };
@@ -0,0 +1,107 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React, {
6
+ type ReactElement,
7
+ type Ref,
8
+ cloneElement,
9
+ forwardRef,
10
+ useCallback,
11
+ useLayoutEffect,
12
+ useState,
13
+ } from 'react';
14
+ import { createPortal } from 'react-dom';
15
+
16
+ import { addEventListener, combine } from '@dxos/async';
17
+ import { useMergeRefs } from '@dxos/react-hooks';
18
+
19
+ import { useSurface } from '../../hooks';
20
+
21
+ export type SurfaceInfoProps = {
22
+ children: ReactElement<{ ref?: Ref<HTMLElement> }>;
23
+ };
24
+
25
+ /**
26
+ * Debug wrapper for surfaces.
27
+ */
28
+ export const SurfaceInfo = forwardRef<HTMLElement, SurfaceInfoProps>(({ children }, forwardedRef) => {
29
+ const [rect, setRect] = useState<DOMRect | null>(null);
30
+ const [expand, setExpand] = useState(false);
31
+ const info = useSurface();
32
+
33
+ const [root, setRoot] = useState<HTMLElement | null>(null);
34
+ const measureRef = useCallback((node: HTMLElement | null) => setRoot(node), []);
35
+ const mergedRef = useMergeRefs([measureRef, forwardedRef]);
36
+ const childWithRef = cloneElement(children, { ref: mergedRef });
37
+
38
+ useLayoutEffect(() => {
39
+ if (!root) {
40
+ setRect(null);
41
+ return;
42
+ }
43
+
44
+ const measure = () => {
45
+ setRect(root.getBoundingClientRect());
46
+ };
47
+
48
+ const observer = new ResizeObserver(measure);
49
+ observer.observe(root);
50
+ measure();
51
+
52
+ return combine(
53
+ addEventListener(window, 'scroll', measure, true),
54
+ addEventListener(window, 'resize', measure),
55
+ () => {
56
+ observer.disconnect();
57
+ },
58
+ );
59
+ }, [root]);
60
+
61
+ const padding = 0;
62
+ return (
63
+ <>
64
+ {childWithRef}
65
+ {rect &&
66
+ createPortal(
67
+ <div
68
+ role='none'
69
+ className='z-[100] fixed flex flex-col-reverse scrollbar-none overflow-auto pointer-events-none'
70
+ style={{
71
+ top: rect.top + padding,
72
+ left: rect.left + padding,
73
+ width: rect.width - padding * 2,
74
+ height: rect.height - padding * 2,
75
+ }}
76
+ >
77
+ {expand ? (
78
+ <div
79
+ className='absolute inset-0 bg-deck-surface border border-green-500 cursor-pointer pointer-events-auto overflow-auto'
80
+ onPointerDown={(ev) => ev.stopPropagation()}
81
+ onClick={(ev) => {
82
+ ev.stopPropagation();
83
+ setExpand(false);
84
+ }}
85
+ >
86
+ <pre className='p-2 text-xs text-description font-mono'>{JSON.stringify({ info }, null, 2)}</pre>
87
+ </div>
88
+ ) : (
89
+ <span
90
+ className='absolute right-1 bottom-0 flex items-center p-1 text-green-500 opacity-80 hover:opacity-100 text-xl cursor-pointer pointer-events-auto'
91
+ title={info.id}
92
+ onPointerDown={(ev) => ev.stopPropagation()}
93
+ onClick={(ev) => {
94
+ ev.stopPropagation();
95
+ setExpand(true);
96
+ }}
97
+ >
98
+
99
+ </span>
100
+ )}
101
+ </div>,
102
+ // TODO(burdon): Create well-known element to gather all debug portals.
103
+ document.body,
104
+ )}
105
+ </>
106
+ );
107
+ });
@@ -0,0 +1,207 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import React, {
6
+ type Context,
7
+ type PropsWithChildren,
8
+ type ProfilerOnRenderCallback,
9
+ createContext,
10
+ useContext,
11
+ useMemo,
12
+ useRef,
13
+ useSyncExternalStore,
14
+ } from 'react';
15
+
16
+ const MAX_ENTRIES = 500;
17
+
18
+ /**
19
+ * Single profiler record captured from React Profiler onRender callback.
20
+ */
21
+ export type SurfaceProfilerEntry = {
22
+ id: string;
23
+ phase: 'mount' | 'update' | 'nested-update';
24
+ actualDuration: number;
25
+ baseDuration: number;
26
+ startTime: number;
27
+ commitTime: number;
28
+ timestamp: number;
29
+ };
30
+
31
+ /**
32
+ * Aggregated stats for a single profiled surface.
33
+ */
34
+ export type SurfaceProfilerStats = {
35
+ id: string;
36
+ mountCount: number;
37
+ updateCount: number;
38
+ totalRenders: number;
39
+ avgActualDuration: number;
40
+ maxActualDuration: number;
41
+ avgBaseDuration: number;
42
+ lastActualDuration: number;
43
+ lastCommitTime: number;
44
+ };
45
+
46
+ /**
47
+ * Store that collects profiler entries and notifies subscribers.
48
+ */
49
+ class SurfaceProfilerStore {
50
+ private _entries: SurfaceProfilerEntry[] = [];
51
+ private _listeners = new Set<() => void>();
52
+ private _snapshot: readonly SurfaceProfilerEntry[] = [];
53
+ private _pendingNotify = false;
54
+
55
+ /** Records an entry and schedules a deferred notification to avoid re-render loops. */
56
+ record(entry: SurfaceProfilerEntry) {
57
+ this._entries.push(entry);
58
+ if (this._entries.length > MAX_ENTRIES) {
59
+ this._entries = this._entries.slice(-MAX_ENTRIES);
60
+ }
61
+ this._snapshot = [...this._entries];
62
+ this._scheduleNotify();
63
+ }
64
+
65
+ clear() {
66
+ this._entries = [];
67
+ this._snapshot = [];
68
+ this._notifySync();
69
+ }
70
+
71
+ subscribe = (listener: () => void) => {
72
+ this._listeners.add(listener);
73
+ return () => {
74
+ this._listeners.delete(listener);
75
+ };
76
+ };
77
+
78
+ getSnapshot = (): readonly SurfaceProfilerEntry[] => {
79
+ return this._snapshot;
80
+ };
81
+
82
+ /**
83
+ * Defers notification to the next animation frame to break the
84
+ * Profiler onRender → record → notify → re-render → onRender loop.
85
+ */
86
+ private _scheduleNotify() {
87
+ if (!this._pendingNotify) {
88
+ this._pendingNotify = true;
89
+ requestAnimationFrame(() => {
90
+ this._pendingNotify = false;
91
+ this._notifySync();
92
+ });
93
+ }
94
+ }
95
+
96
+ private _notifySync() {
97
+ for (const listener of this._listeners) {
98
+ listener();
99
+ }
100
+ }
101
+ }
102
+
103
+ type SurfaceProfilerContextValue = {
104
+ store: SurfaceProfilerStore;
105
+ };
106
+
107
+ const SurfaceProfilerContext: Context<SurfaceProfilerContextValue | undefined> = createContext<
108
+ SurfaceProfilerContextValue | undefined
109
+ >(undefined);
110
+
111
+ /**
112
+ * Provider that collects React Profiler data from Surface components.
113
+ */
114
+ export const SurfaceProfilerProvider = ({ children }: PropsWithChildren) => {
115
+ const storeRef = useRef<SurfaceProfilerStore>(null);
116
+ if (!storeRef.current) {
117
+ storeRef.current = new SurfaceProfilerStore();
118
+ }
119
+ return (
120
+ <SurfaceProfilerContext.Provider value={{ store: storeRef.current }}>{children}</SurfaceProfilerContext.Provider>
121
+ );
122
+ };
123
+
124
+ /**
125
+ * Returns a stable onRender callback for use with React Profiler.
126
+ */
127
+ export const useSurfaceProfilerCallback = (): ProfilerOnRenderCallback | undefined => {
128
+ const store = useContext(SurfaceProfilerContext)?.store;
129
+ return useMemo<ProfilerOnRenderCallback | undefined>(() => {
130
+ if (!store) {
131
+ return undefined;
132
+ }
133
+ return (id, phase, actualDuration, baseDuration, startTime, commitTime) => {
134
+ store.record({
135
+ id,
136
+ phase,
137
+ actualDuration,
138
+ baseDuration,
139
+ startTime,
140
+ commitTime,
141
+ timestamp: Date.now(),
142
+ });
143
+ };
144
+ }, [store]);
145
+ };
146
+
147
+ /**
148
+ * Returns all profiler entries reactively.
149
+ */
150
+ export const useSurfaceProfilerEntries = (): readonly SurfaceProfilerEntry[] => {
151
+ const context = useContext(SurfaceProfilerContext);
152
+ return useSyncExternalStore(context?.store.subscribe ?? noop, context?.store.getSnapshot ?? emptySnapshot);
153
+ };
154
+
155
+ /**
156
+ * Returns aggregated stats grouped by surface id.
157
+ */
158
+ export const useSurfaceProfilerStats = (): SurfaceProfilerStats[] => {
159
+ const entries = useSurfaceProfilerEntries();
160
+ const statsMap = new Map<string, SurfaceProfilerStats>();
161
+
162
+ for (const entry of entries) {
163
+ let stats = statsMap.get(entry.id);
164
+ if (!stats) {
165
+ stats = {
166
+ id: entry.id,
167
+ mountCount: 0,
168
+ updateCount: 0,
169
+ totalRenders: 0,
170
+ avgActualDuration: 0,
171
+ maxActualDuration: 0,
172
+ avgBaseDuration: 0,
173
+ lastActualDuration: 0,
174
+ lastCommitTime: 0,
175
+ };
176
+ statsMap.set(entry.id, stats);
177
+ }
178
+
179
+ if (entry.phase === 'mount') {
180
+ stats.mountCount++;
181
+ } else {
182
+ stats.updateCount++;
183
+ }
184
+ stats.totalRenders++;
185
+ stats.avgActualDuration =
186
+ (stats.avgActualDuration * (stats.totalRenders - 1) + entry.actualDuration) / stats.totalRenders;
187
+ stats.avgBaseDuration =
188
+ (stats.avgBaseDuration * (stats.totalRenders - 1) + entry.baseDuration) / stats.totalRenders;
189
+ stats.maxActualDuration = Math.max(stats.maxActualDuration, entry.actualDuration);
190
+ stats.lastActualDuration = entry.actualDuration;
191
+ stats.lastCommitTime = entry.commitTime;
192
+ }
193
+
194
+ return [...statsMap.values()].sort((a, b) => b.maxActualDuration - a.maxActualDuration);
195
+ };
196
+
197
+ /**
198
+ * Clears all collected profiler entries.
199
+ */
200
+ export const useSurfaceProfilerClear = (): (() => void) | undefined => {
201
+ const store = useContext(SurfaceProfilerContext)?.store;
202
+ return useMemo(() => (store ? () => store.clear() : undefined), [store]);
203
+ };
204
+
205
+ const noop = () => () => {};
206
+ const EMPTY_SNAPSHOT: readonly SurfaceProfilerEntry[] = [];
207
+ const emptySnapshot = () => EMPTY_SNAPSHOT;
@@ -0,0 +1,12 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type Context, createContext } from 'react';
6
+
7
+ import { type Props } from './types';
8
+
9
+ export type SurfaceContext = Pick<Props, 'id' | 'role' | 'data'>;
10
+
11
+ // TODO(burdon): Use @radix-ui/react-context
12
+ export const SurfaceContext: Context<SurfaceContext | undefined> = createContext<SurfaceContext | undefined>(undefined);
@@ -0,0 +1,35 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ // TODO(wittjosiah): Cleanup to avoid re-naming.
6
+ import { SurfaceContext } from './context';
7
+ import { SurfaceComponent, isSurfaceAvailable } from './SurfaceComponent';
8
+ import {
9
+ SurfaceProfilerProvider,
10
+ useSurfaceProfilerCallback,
11
+ useSurfaceProfilerClear,
12
+ useSurfaceProfilerEntries,
13
+ useSurfaceProfilerStats,
14
+ } from './SurfaceProfilerContext';
15
+ import { type Definition as SurfaceDefinition, create as createSurface, createWeb as createWebSurface } from './types';
16
+
17
+ export namespace Surface {
18
+ export type Definition = SurfaceDefinition;
19
+ export const create = createSurface;
20
+ export const createWeb = createWebSurface;
21
+
22
+ export type Context = SurfaceContext;
23
+ export const Context = SurfaceContext;
24
+
25
+ export const Surface = SurfaceComponent;
26
+ export const isAvailable = isSurfaceAvailable;
27
+
28
+ export const ProfilerProvider = SurfaceProfilerProvider;
29
+ export const useProfilerCallback = useSurfaceProfilerCallback;
30
+ export const useProfilerEntries = useSurfaceProfilerEntries;
31
+ export const useProfilerStats = useSurfaceProfilerStats;
32
+ export const useProfilerClear = useSurfaceProfilerClear;
33
+ }
34
+
35
+ export type { SurfaceProfilerEntry, SurfaceProfilerStats } from './SurfaceProfilerContext';