@dxos/app-framework 0.8.4-main.5ea62a8 → 0.8.4-main.60689f5b1c

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 (555) hide show
  1. package/.storybook/main.mts +9 -0
  2. package/.storybook/preview.mts +8 -0
  3. package/LICENSE +102 -5
  4. package/README.md +1 -1
  5. package/dist/lib/browser/capability-K5XIVCQU.mjs +35 -0
  6. package/dist/lib/browser/capability-K5XIVCQU.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-5AHASNDW.mjs +95 -0
  8. package/dist/lib/browser/chunk-5AHASNDW.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-5GY3YOEL.mjs +28 -0
  10. package/dist/lib/browser/chunk-5GY3YOEL.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-66IXTIVK.mjs +48 -0
  12. package/dist/lib/browser/chunk-66IXTIVK.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-BRK6GYNB.mjs +142 -0
  14. package/dist/lib/browser/chunk-BRK6GYNB.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-FJ4765WW.mjs +8 -0
  16. package/dist/lib/browser/chunk-FJ4765WW.mjs.map +7 -0
  17. package/dist/lib/browser/chunk-FO3IYSLV.mjs +68 -0
  18. package/dist/lib/browser/chunk-FO3IYSLV.mjs.map +7 -0
  19. package/dist/lib/browser/chunk-IW44C7UL.mjs +83 -0
  20. package/dist/lib/browser/chunk-IW44C7UL.mjs.map +7 -0
  21. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  22. package/dist/lib/browser/chunk-KFDF7KR3.mjs +42 -0
  23. package/dist/lib/browser/chunk-KFDF7KR3.mjs.map +7 -0
  24. package/dist/lib/browser/chunk-KLHQNYJ2.mjs +422 -0
  25. package/dist/lib/browser/chunk-KLHQNYJ2.mjs.map +7 -0
  26. package/dist/lib/browser/chunk-QLML5QFJ.mjs +581 -0
  27. package/dist/lib/browser/chunk-QLML5QFJ.mjs.map +7 -0
  28. package/dist/lib/browser/chunk-SLX73WRZ.mjs +218 -0
  29. package/dist/lib/browser/chunk-SLX73WRZ.mjs.map +7 -0
  30. package/dist/lib/browser/chunk-UVTGHZQF.mjs +513 -0
  31. package/dist/lib/browser/chunk-UVTGHZQF.mjs.map +7 -0
  32. package/dist/lib/browser/chunk-VJ5PFAWC.mjs +1446 -0
  33. package/dist/lib/browser/chunk-VJ5PFAWC.mjs.map +7 -0
  34. package/dist/lib/browser/cli/index.mjs +74 -0
  35. package/dist/lib/browser/cli/index.mjs.map +7 -0
  36. package/dist/lib/browser/common/activation-events.mjs +20 -0
  37. package/dist/lib/browser/common/capabilities.mjs +56 -0
  38. package/dist/lib/browser/core/activation-event.mjs +20 -0
  39. package/dist/lib/browser/core/capability.mjs +32 -0
  40. package/dist/lib/browser/core/capability.mjs.map +7 -0
  41. package/dist/lib/browser/core/plugin-manager.mjs +19 -0
  42. package/dist/lib/browser/core/plugin-manager.mjs.map +7 -0
  43. package/dist/lib/browser/core/plugin.mjs +39 -0
  44. package/dist/lib/browser/core/plugin.mjs.map +7 -0
  45. package/dist/lib/browser/core/url-loader.mjs +24 -0
  46. package/dist/lib/browser/core/url-loader.mjs.map +7 -0
  47. package/dist/lib/browser/index.mjs +85 -162
  48. package/dist/lib/browser/index.mjs.map +4 -4
  49. package/dist/lib/browser/meta.json +1 -1
  50. package/dist/lib/browser/process-manager-capability-JIWLN7SU.mjs +89 -0
  51. package/dist/lib/browser/process-manager-capability-JIWLN7SU.mjs.map +7 -0
  52. package/dist/lib/browser/testing/index.mjs +248 -53
  53. package/dist/lib/browser/testing/index.mjs.map +4 -4
  54. package/dist/lib/browser/testing/react.mjs +78 -0
  55. package/dist/lib/browser/testing/react.mjs.map +7 -0
  56. package/dist/lib/browser/ui/index.mjs +54 -0
  57. package/dist/lib/browser/ui/index.mjs.map +7 -0
  58. package/dist/lib/node-esm/capability-RLKFFLTB.mjs +36 -0
  59. package/dist/lib/node-esm/capability-RLKFFLTB.mjs.map +7 -0
  60. package/dist/lib/node-esm/chunk-37Z53PXZ.mjs +10 -0
  61. package/dist/lib/node-esm/chunk-37Z53PXZ.mjs.map +7 -0
  62. package/dist/lib/node-esm/chunk-42UNAKYO.mjs +423 -0
  63. package/dist/lib/node-esm/chunk-42UNAKYO.mjs.map +7 -0
  64. package/dist/lib/node-esm/chunk-6S45OMUP.mjs +219 -0
  65. package/dist/lib/node-esm/chunk-6S45OMUP.mjs.map +7 -0
  66. package/dist/lib/node-esm/chunk-BYHYYJZH.mjs +143 -0
  67. package/dist/lib/node-esm/chunk-BYHYYJZH.mjs.map +7 -0
  68. package/dist/lib/node-esm/chunk-CTKEZHKF.mjs +84 -0
  69. package/dist/lib/node-esm/chunk-CTKEZHKF.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-JNT72ZCN.mjs +514 -0
  73. package/dist/lib/node-esm/chunk-JNT72ZCN.mjs.map +7 -0
  74. package/dist/lib/node-esm/chunk-KFZEB6BV.mjs +29 -0
  75. package/dist/lib/node-esm/chunk-KFZEB6BV.mjs.map +7 -0
  76. package/dist/lib/node-esm/chunk-LJNUFNDO.mjs +582 -0
  77. package/dist/lib/node-esm/chunk-LJNUFNDO.mjs.map +7 -0
  78. package/dist/lib/node-esm/chunk-OUEMWPIW.mjs +43 -0
  79. package/dist/lib/node-esm/chunk-OUEMWPIW.mjs.map +7 -0
  80. package/dist/lib/node-esm/chunk-PW2VYGOS.mjs +96 -0
  81. package/dist/lib/node-esm/chunk-PW2VYGOS.mjs.map +7 -0
  82. package/dist/lib/node-esm/chunk-SFYCO3PT.mjs +1447 -0
  83. package/dist/lib/node-esm/chunk-SFYCO3PT.mjs.map +7 -0
  84. package/dist/lib/node-esm/chunk-WK7OIQKI.mjs +70 -0
  85. package/dist/lib/node-esm/chunk-WK7OIQKI.mjs.map +7 -0
  86. package/dist/lib/node-esm/chunk-XOCUANHO.mjs +49 -0
  87. package/dist/lib/node-esm/chunk-XOCUANHO.mjs.map +7 -0
  88. package/dist/lib/node-esm/cli/index.mjs +75 -0
  89. package/dist/lib/node-esm/cli/index.mjs.map +7 -0
  90. package/dist/lib/node-esm/common/activation-events.mjs +21 -0
  91. package/dist/lib/node-esm/common/activation-events.mjs.map +7 -0
  92. package/dist/lib/node-esm/common/capabilities.mjs +57 -0
  93. package/dist/lib/node-esm/common/capabilities.mjs.map +7 -0
  94. package/dist/lib/node-esm/core/activation-event.mjs +21 -0
  95. package/dist/lib/node-esm/core/activation-event.mjs.map +7 -0
  96. package/dist/lib/node-esm/core/capability.mjs +33 -0
  97. package/dist/lib/node-esm/core/capability.mjs.map +7 -0
  98. package/dist/lib/node-esm/core/plugin-manager.mjs +20 -0
  99. package/dist/lib/node-esm/core/plugin-manager.mjs.map +7 -0
  100. package/dist/lib/node-esm/core/plugin.mjs +40 -0
  101. package/dist/lib/node-esm/core/plugin.mjs.map +7 -0
  102. package/dist/lib/node-esm/core/url-loader.mjs +25 -0
  103. package/dist/lib/node-esm/core/url-loader.mjs.map +7 -0
  104. package/dist/lib/node-esm/index.mjs +85 -162
  105. package/dist/lib/node-esm/index.mjs.map +4 -4
  106. package/dist/lib/node-esm/meta.json +1 -1
  107. package/dist/lib/node-esm/process-manager-capability-PHKLO2BL.mjs +90 -0
  108. package/dist/lib/node-esm/process-manager-capability-PHKLO2BL.mjs.map +7 -0
  109. package/dist/lib/node-esm/testing/index.mjs +248 -53
  110. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  111. package/dist/lib/node-esm/testing/react.mjs +79 -0
  112. package/dist/lib/node-esm/testing/react.mjs.map +7 -0
  113. package/dist/lib/node-esm/ui/index.mjs +55 -0
  114. package/dist/lib/node-esm/ui/index.mjs.map +7 -0
  115. package/dist/plugin/node-esm/index.mjs +893 -0
  116. package/dist/plugin/node-esm/index.mjs.map +7 -0
  117. package/dist/plugin/node-esm/meta.json +1 -0
  118. package/dist/types/src/cli/cli.d.ts +37 -0
  119. package/dist/types/src/cli/cli.d.ts.map +1 -0
  120. package/dist/types/src/cli/index.d.ts +2 -0
  121. package/dist/types/src/cli/index.d.ts.map +1 -0
  122. package/dist/types/src/common/activation-events.d.ts +24 -0
  123. package/dist/types/src/common/activation-events.d.ts.map +1 -0
  124. package/dist/types/src/common/annotations.d.ts +1 -0
  125. package/dist/types/src/common/annotations.d.ts.map +1 -0
  126. package/dist/types/src/common/capabilities.d.ts +214 -189
  127. package/dist/types/src/common/capabilities.d.ts.map +1 -1
  128. package/dist/types/src/common/index.d.ts +4 -8
  129. package/dist/types/src/common/index.d.ts.map +1 -1
  130. package/dist/types/src/common/operations.d.ts +19 -0
  131. package/dist/types/src/common/operations.d.ts.map +1 -0
  132. package/dist/types/src/common/translations.d.ts +8 -8
  133. package/dist/types/src/common/translations.d.ts.map +1 -1
  134. package/dist/types/src/context.d.ts +5 -0
  135. package/dist/types/src/context.d.ts.map +1 -0
  136. package/dist/types/src/core/{events.d.ts → activation-event.d.ts} +11 -11
  137. package/dist/types/src/core/activation-event.d.ts.map +1 -0
  138. package/dist/types/src/core/capability-manager.d.ts +48 -0
  139. package/dist/types/src/core/capability-manager.d.ts.map +1 -0
  140. package/dist/types/src/core/capability-manager.test.d.ts +2 -0
  141. package/dist/types/src/core/capability-manager.test.d.ts.map +1 -0
  142. package/dist/types/src/core/capability.d.ts +161 -0
  143. package/dist/types/src/core/capability.d.ts.map +1 -0
  144. package/dist/types/src/core/edge-registry-plugin-provider.d.ts +30 -0
  145. package/dist/types/src/core/edge-registry-plugin-provider.d.ts.map +1 -0
  146. package/dist/types/src/core/index.d.ts +11 -4
  147. package/dist/types/src/core/index.d.ts.map +1 -1
  148. package/dist/types/src/core/plugin-asset-cache.d.ts +71 -0
  149. package/dist/types/src/core/plugin-asset-cache.d.ts.map +1 -0
  150. package/dist/types/src/core/plugin-manager.d.ts +297 -0
  151. package/dist/types/src/core/plugin-manager.d.ts.map +1 -0
  152. package/dist/types/src/core/plugin-manager.test.d.ts +2 -0
  153. package/dist/types/src/core/plugin-manager.test.d.ts.map +1 -0
  154. package/dist/types/src/core/plugin-manifest.d.ts +101 -0
  155. package/dist/types/src/core/plugin-manifest.d.ts.map +1 -0
  156. package/dist/types/src/core/plugin-manifest.test.d.ts +2 -0
  157. package/dist/types/src/core/plugin-manifest.test.d.ts.map +1 -0
  158. package/dist/types/src/core/plugin.d.ts +277 -37
  159. package/dist/types/src/core/plugin.d.ts.map +1 -1
  160. package/dist/types/src/core/registry.d.ts +107 -0
  161. package/dist/types/src/core/registry.d.ts.map +1 -0
  162. package/dist/types/src/core/url-loader.d.ts +127 -0
  163. package/dist/types/src/core/url-loader.d.ts.map +1 -0
  164. package/dist/types/src/core/url-loader.test.d.ts +2 -0
  165. package/dist/types/src/core/url-loader.test.d.ts.map +1 -0
  166. package/dist/types/src/helpers.d.ts.map +1 -1
  167. package/dist/types/src/index.d.ts +2 -4
  168. package/dist/types/src/index.d.ts.map +1 -1
  169. package/dist/types/src/plugin-process-manager/ProcessManagerPlugin.d.ts +3 -0
  170. package/dist/types/src/plugin-process-manager/ProcessManagerPlugin.d.ts.map +1 -0
  171. package/dist/types/src/plugin-process-manager/history/capability.d.ts +7 -0
  172. package/dist/types/src/plugin-process-manager/history/capability.d.ts.map +1 -0
  173. package/dist/types/src/plugin-process-manager/history/errors.d.ts +32 -0
  174. package/dist/types/src/plugin-process-manager/history/errors.d.ts.map +1 -0
  175. package/dist/types/src/plugin-process-manager/history/history-tracker.d.ts +18 -0
  176. package/dist/types/src/plugin-process-manager/history/history-tracker.d.ts.map +1 -0
  177. package/dist/types/src/plugin-process-manager/history/history-tracker.test.d.ts +2 -0
  178. package/dist/types/src/plugin-process-manager/history/history-tracker.test.d.ts.map +1 -0
  179. package/dist/types/src/plugin-process-manager/history/index.d.ts +6 -0
  180. package/dist/types/src/plugin-process-manager/history/index.d.ts.map +1 -0
  181. package/dist/types/src/plugin-process-manager/history/types.d.ts +13 -0
  182. package/dist/types/src/plugin-process-manager/history/types.d.ts.map +1 -0
  183. package/dist/types/src/plugin-process-manager/history/undo-mapping.d.ts +101 -0
  184. package/dist/types/src/plugin-process-manager/history/undo-mapping.d.ts.map +1 -0
  185. package/dist/types/src/plugin-process-manager/history/undo-registry.d.ts +23 -0
  186. package/dist/types/src/plugin-process-manager/history/undo-registry.d.ts.map +1 -0
  187. package/dist/types/src/plugin-process-manager/history/undo-registry.test.d.ts +2 -0
  188. package/dist/types/src/plugin-process-manager/history/undo-registry.test.d.ts.map +1 -0
  189. package/dist/types/src/plugin-process-manager/index.d.ts +3 -0
  190. package/dist/types/src/plugin-process-manager/index.d.ts.map +1 -0
  191. package/dist/types/src/plugin-process-manager/meta.d.ts +3 -0
  192. package/dist/types/src/plugin-process-manager/meta.d.ts.map +1 -0
  193. package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts +8 -0
  194. package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts.map +1 -0
  195. package/dist/types/src/plugin-process-manager/testing.d.ts +59 -0
  196. package/dist/types/src/plugin-process-manager/testing.d.ts.map +1 -0
  197. package/dist/types/src/testing/harness.d.ts +79 -0
  198. package/dist/types/src/testing/harness.d.ts.map +1 -0
  199. package/dist/types/src/testing/index.d.ts +2 -0
  200. package/dist/types/src/testing/index.d.ts.map +1 -1
  201. package/dist/types/src/testing/react.d.ts +27 -0
  202. package/dist/types/src/testing/react.d.ts.map +1 -0
  203. package/dist/types/src/testing/react.test.d.ts +2 -0
  204. package/dist/types/src/testing/react.test.d.ts.map +1 -0
  205. package/dist/types/src/testing/service.d.ts +8 -0
  206. package/dist/types/src/testing/service.d.ts.map +1 -0
  207. package/dist/types/src/testing/withPluginManager.d.ts +9 -10
  208. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
  209. package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -1
  210. package/dist/types/src/ui/components/App/App.d.ts +9 -0
  211. package/dist/types/src/ui/components/App/App.d.ts.map +1 -0
  212. package/dist/types/src/ui/components/App/App.stories.d.ts +19 -0
  213. package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -0
  214. package/dist/types/src/ui/components/App/index.d.ts +2 -0
  215. package/dist/types/src/ui/components/App/index.d.ts.map +1 -0
  216. package/dist/types/src/ui/components/Placeholder/Placeholder.d.ts +64 -0
  217. package/dist/types/src/ui/components/Placeholder/Placeholder.d.ts.map +1 -0
  218. package/dist/types/src/ui/components/Placeholder/Placeholder.stories.d.ts +19 -0
  219. package/dist/types/src/ui/components/Placeholder/Placeholder.stories.d.ts.map +1 -0
  220. package/dist/types/src/ui/components/Placeholder/index.d.ts +2 -0
  221. package/dist/types/src/ui/components/Placeholder/index.d.ts.map +1 -0
  222. package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts +13 -0
  223. package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts.map +1 -0
  224. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts +10 -0
  225. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts.map +1 -0
  226. package/dist/types/src/ui/components/PluginManager/index.d.ts +2 -0
  227. package/dist/types/src/ui/components/PluginManager/index.d.ts.map +1 -0
  228. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +24 -0
  229. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -0
  230. package/dist/types/src/{playground/playground.stories.d.ts → ui/components/Surface/SurfaceComponent.stories.d.ts} +5 -3
  231. package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -0
  232. package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts +11 -0
  233. package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts.map +1 -0
  234. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts +48 -0
  235. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts.map +1 -0
  236. package/dist/types/src/ui/components/Surface/context.d.ts +5 -0
  237. package/dist/types/src/ui/components/Surface/context.d.ts.map +1 -0
  238. package/dist/types/src/ui/components/Surface/index.d.ts +36 -0
  239. package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -0
  240. package/dist/types/src/ui/components/Surface/types.d.ts +197 -0
  241. package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -0
  242. package/dist/types/src/ui/components/Surface/types.test.d.ts +2 -0
  243. package/dist/types/src/ui/components/Surface/types.test.d.ts.map +1 -0
  244. package/dist/types/src/ui/components/index.d.ts +5 -0
  245. package/dist/types/src/ui/components/index.d.ts.map +1 -0
  246. package/dist/types/src/ui/hooks/index.d.ts +7 -0
  247. package/dist/types/src/ui/hooks/index.d.ts.map +1 -0
  248. package/dist/types/src/ui/hooks/useApp.d.ts +86 -0
  249. package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -0
  250. package/dist/types/src/ui/hooks/useApp.test.d.ts +2 -0
  251. package/dist/types/src/ui/hooks/useApp.test.d.ts.map +1 -0
  252. package/dist/types/src/ui/hooks/useCapabilities.d.ts +31 -0
  253. package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -0
  254. package/dist/types/src/ui/hooks/useLoading.d.ts +18 -0
  255. package/dist/types/src/ui/hooks/useLoading.d.ts.map +1 -0
  256. package/dist/types/src/ui/hooks/useProcessManagerRuntime.d.ts +24 -0
  257. package/dist/types/src/ui/hooks/useProcessManagerRuntime.d.ts.map +1 -0
  258. package/dist/types/src/ui/hooks/useSettingsState.d.ts +10 -0
  259. package/dist/types/src/ui/hooks/useSettingsState.d.ts.map +1 -0
  260. package/dist/types/src/ui/hooks/useSurface.d.ts +3 -0
  261. package/dist/types/src/ui/hooks/useSurface.d.ts.map +1 -0
  262. package/dist/types/src/ui/index.d.ts +3 -0
  263. package/dist/types/src/ui/index.d.ts.map +1 -0
  264. package/dist/types/src/vite-plugin/boot-loader/BootLoader.stories.d.ts +34 -0
  265. package/dist/types/src/vite-plugin/boot-loader/BootLoader.stories.d.ts.map +1 -0
  266. package/dist/types/src/vite-plugin/boot-loader/index.d.ts +2 -0
  267. package/dist/types/src/vite-plugin/boot-loader/index.d.ts.map +1 -0
  268. package/dist/types/src/vite-plugin/boot-loader/loader.d.ts +51 -0
  269. package/dist/types/src/vite-plugin/boot-loader/loader.d.ts.map +1 -0
  270. package/dist/types/src/vite-plugin/composer/index.d.ts +34 -0
  271. package/dist/types/src/vite-plugin/composer/index.d.ts.map +1 -0
  272. package/dist/types/src/vite-plugin/import-map/index.d.ts +28 -0
  273. package/dist/types/src/vite-plugin/import-map/index.d.ts.map +1 -0
  274. package/dist/types/src/vite-plugin/index.d.ts +5 -0
  275. package/dist/types/src/vite-plugin/index.d.ts.map +1 -0
  276. package/dist/types/src/vite-plugin/manifest.d.ts +41 -0
  277. package/dist/types/src/vite-plugin/manifest.d.ts.map +1 -0
  278. package/dist/types/src/vite-plugin/manifest.test.d.ts +2 -0
  279. package/dist/types/src/vite-plugin/manifest.test.d.ts.map +1 -0
  280. package/dist/types/src/vite-plugin/packages.d.ts +13 -0
  281. package/dist/types/src/vite-plugin/packages.d.ts.map +1 -0
  282. package/dist/types/tsconfig.tsbuildinfo +1 -1
  283. package/moon.yml +26 -3
  284. package/package.json +119 -55
  285. package/src/cli/cli.ts +102 -0
  286. package/src/{playground/layout → cli}/index.ts +1 -1
  287. package/src/common/activation-events.ts +39 -0
  288. package/src/{playground/debug/index.ts → common/annotations.ts} +0 -2
  289. package/src/common/capabilities.ts +287 -177
  290. package/src/common/index.ts +4 -8
  291. package/src/common/operations.ts +35 -0
  292. package/src/common/translations.ts +18 -10
  293. package/src/context.ts +9 -0
  294. package/src/core/{events.ts → activation-event.ts} +10 -7
  295. package/src/core/capability-manager.test.ts +151 -0
  296. package/src/core/capability-manager.ts +192 -0
  297. package/src/core/capability.ts +254 -0
  298. package/src/core/edge-registry-plugin-provider.ts +92 -0
  299. package/src/core/index.ts +11 -4
  300. package/src/core/plugin-asset-cache.ts +60 -0
  301. package/src/core/plugin-manager.test.ts +1899 -0
  302. package/src/core/plugin-manager.ts +1687 -0
  303. package/src/core/plugin-manifest.test.ts +75 -0
  304. package/src/core/plugin-manifest.ts +134 -0
  305. package/src/core/plugin.ts +419 -43
  306. package/src/core/registry.ts +163 -0
  307. package/src/core/url-loader.test.ts +221 -0
  308. package/src/core/url-loader.ts +388 -0
  309. package/src/index.ts +2 -4
  310. package/src/plugin-process-manager/ProcessManagerPlugin.ts +24 -0
  311. package/src/plugin-process-manager/history/capability.ts +36 -0
  312. package/src/plugin-process-manager/history/errors.ts +7 -0
  313. package/src/plugin-process-manager/history/history-tracker.test.ts +374 -0
  314. package/src/plugin-process-manager/history/history-tracker.ts +128 -0
  315. package/src/plugin-process-manager/history/index.ts +9 -0
  316. package/src/plugin-process-manager/history/types.ts +17 -0
  317. package/src/plugin-process-manager/history/undo-mapping.ts +135 -0
  318. package/src/plugin-process-manager/history/undo-registry.test.ts +72 -0
  319. package/src/plugin-process-manager/history/undo-registry.ts +54 -0
  320. package/src/plugin-process-manager/index.ts +6 -0
  321. package/src/plugin-process-manager/meta.ts +14 -0
  322. package/src/plugin-process-manager/process-manager-capability.ts +178 -0
  323. package/src/plugin-process-manager/testing.ts +155 -0
  324. package/src/testing/harness.ts +247 -0
  325. package/src/testing/index.ts +2 -0
  326. package/src/testing/react.test.tsx +48 -0
  327. package/src/testing/react.tsx +113 -0
  328. package/src/testing/service.ts +52 -0
  329. package/src/testing/withPluginManager.stories.tsx +9 -10
  330. package/src/testing/withPluginManager.tsx +80 -53
  331. package/src/ui/components/App/App.stories.tsx +86 -0
  332. package/src/ui/components/App/App.tsx +81 -0
  333. package/src/{playground/logger → ui/components/App}/index.ts +1 -1
  334. package/src/ui/components/Placeholder/Placeholder.stories.tsx +77 -0
  335. package/src/ui/components/Placeholder/Placeholder.tsx +155 -0
  336. package/src/ui/components/Placeholder/index.ts +5 -0
  337. package/src/ui/components/PluginManager/PluginManagerContext.stories.tsx +184 -0
  338. package/src/{react → ui/components/PluginManager}/PluginManagerProvider.ts +3 -3
  339. package/src/ui/components/PluginManager/index.ts +5 -0
  340. package/src/ui/components/Surface/SurfaceComponent.stories.tsx +144 -0
  341. package/src/ui/components/Surface/SurfaceComponent.tsx +303 -0
  342. package/src/ui/components/Surface/SurfaceInfo.tsx +106 -0
  343. package/src/ui/components/Surface/SurfaceProfilerContext.tsx +207 -0
  344. package/src/ui/components/Surface/context.ts +12 -0
  345. package/src/ui/components/Surface/index.ts +54 -0
  346. package/src/ui/components/Surface/types.test.ts +126 -0
  347. package/src/ui/components/Surface/types.ts +269 -0
  348. package/src/ui/components/index.ts +8 -0
  349. package/src/ui/hooks/index.ts +10 -0
  350. package/src/ui/hooks/useApp.test.tsx +159 -0
  351. package/src/ui/hooks/useApp.tsx +418 -0
  352. package/src/ui/hooks/useCapabilities.ts +67 -0
  353. package/src/ui/hooks/useLoading.tsx +76 -0
  354. package/src/ui/hooks/useProcessManagerRuntime.ts +68 -0
  355. package/src/ui/hooks/useSettingsState.ts +26 -0
  356. package/src/ui/hooks/useSurface.ts +13 -0
  357. package/src/ui/index.ts +6 -0
  358. package/src/vite-plugin/boot-loader/BootLoader.stories.tsx +270 -0
  359. package/src/vite-plugin/boot-loader/boot-loader.css +320 -0
  360. package/src/vite-plugin/boot-loader/boot-loader.js +325 -0
  361. package/src/vite-plugin/boot-loader/index.ts +5 -0
  362. package/src/vite-plugin/boot-loader/loader.ts +123 -0
  363. package/src/vite-plugin/composer/index.ts +306 -0
  364. package/src/vite-plugin/import-map/index.ts +527 -0
  365. package/src/vite-plugin/index.ts +10 -0
  366. package/src/vite-plugin/manifest.test.ts +46 -0
  367. package/src/vite-plugin/manifest.ts +57 -0
  368. package/src/vite-plugin/packages.ts +187 -0
  369. package/tsconfig.json +31 -23
  370. package/tsconfig.node.json +2 -4
  371. package/typedoc.json +2 -4
  372. package/vitest.config.ts +8 -6
  373. package/.swc/plugins/linux_x86_64_19.0.0/727453fb3a62f7f1d952a41e051ca8a6f88cadc45cee43c6a4d1aa45f9b75665.wasmer-v7 +0 -0
  374. package/.swc/plugins/linux_x86_64_19.0.0/fce1bdb8e20a094e4af08bad09cc81497ed0e2e7c51223b07d371063cca18429.wasmer-v7 +0 -0
  375. package/dist/lib/browser/app-graph-builder-AFFC6VB2.mjs +0 -137
  376. package/dist/lib/browser/app-graph-builder-AFFC6VB2.mjs.map +0 -7
  377. package/dist/lib/browser/chunk-DND4XMN4.mjs +0 -441
  378. package/dist/lib/browser/chunk-DND4XMN4.mjs.map +0 -7
  379. package/dist/lib/browser/chunk-ORWHM7CO.mjs +0 -32
  380. package/dist/lib/browser/chunk-ORWHM7CO.mjs.map +0 -7
  381. package/dist/lib/browser/chunk-OZY7HV2A.mjs +0 -1643
  382. package/dist/lib/browser/chunk-OZY7HV2A.mjs.map +0 -7
  383. package/dist/lib/browser/intent-dispatcher-QG7UPGQX.mjs +0 -11
  384. package/dist/lib/browser/intent-resolver-4S4PSTM5.mjs +0 -39
  385. package/dist/lib/browser/intent-resolver-4S4PSTM5.mjs.map +0 -7
  386. package/dist/lib/browser/store-6E33KLGK.mjs +0 -30
  387. package/dist/lib/browser/store-6E33KLGK.mjs.map +0 -7
  388. package/dist/lib/browser/worker.mjs +0 -85
  389. package/dist/lib/node-esm/app-graph-builder-S4OAULX5.mjs +0 -138
  390. package/dist/lib/node-esm/app-graph-builder-S4OAULX5.mjs.map +0 -7
  391. package/dist/lib/node-esm/chunk-E2TK7Z4P.mjs +0 -442
  392. package/dist/lib/node-esm/chunk-E2TK7Z4P.mjs.map +0 -7
  393. package/dist/lib/node-esm/chunk-F63ZRXMK.mjs +0 -1645
  394. package/dist/lib/node-esm/chunk-F63ZRXMK.mjs.map +0 -7
  395. package/dist/lib/node-esm/chunk-UMZQERLE.mjs +0 -34
  396. package/dist/lib/node-esm/chunk-UMZQERLE.mjs.map +0 -7
  397. package/dist/lib/node-esm/intent-dispatcher-NXBGPJOX.mjs +0 -12
  398. package/dist/lib/node-esm/intent-resolver-2ZKXI5ET.mjs +0 -40
  399. package/dist/lib/node-esm/intent-resolver-2ZKXI5ET.mjs.map +0 -7
  400. package/dist/lib/node-esm/store-QQUTQHHT.mjs +0 -31
  401. package/dist/lib/node-esm/store-QQUTQHHT.mjs.map +0 -7
  402. package/dist/lib/node-esm/worker.mjs +0 -86
  403. package/dist/types/src/App.d.ts +0 -43
  404. package/dist/types/src/App.d.ts.map +0 -1
  405. package/dist/types/src/common/collaboration.d.ts +0 -20
  406. package/dist/types/src/common/collaboration.d.ts.map +0 -1
  407. package/dist/types/src/common/events.d.ts +0 -52
  408. package/dist/types/src/common/events.d.ts.map +0 -1
  409. package/dist/types/src/common/file.d.ts +0 -14
  410. package/dist/types/src/common/file.d.ts.map +0 -1
  411. package/dist/types/src/common/graph.d.ts +0 -21
  412. package/dist/types/src/common/graph.d.ts.map +0 -1
  413. package/dist/types/src/common/layout.d.ts +0 -281
  414. package/dist/types/src/common/layout.d.ts.map +0 -1
  415. package/dist/types/src/common/surface.d.ts +0 -65
  416. package/dist/types/src/common/surface.d.ts.map +0 -1
  417. package/dist/types/src/core/capabilities.d.ts +0 -117
  418. package/dist/types/src/core/capabilities.d.ts.map +0 -1
  419. package/dist/types/src/core/capabilities.test.d.ts +0 -2
  420. package/dist/types/src/core/capabilities.test.d.ts.map +0 -1
  421. package/dist/types/src/core/events.d.ts.map +0 -1
  422. package/dist/types/src/core/manager.d.ts +0 -126
  423. package/dist/types/src/core/manager.d.ts.map +0 -1
  424. package/dist/types/src/core/manager.test.d.ts +0 -2
  425. package/dist/types/src/core/manager.test.d.ts.map +0 -1
  426. package/dist/types/src/playground/debug/Debug.d.ts +0 -6
  427. package/dist/types/src/playground/debug/Debug.d.ts.map +0 -1
  428. package/dist/types/src/playground/debug/index.d.ts +0 -2
  429. package/dist/types/src/playground/debug/index.d.ts.map +0 -1
  430. package/dist/types/src/playground/debug/plugin.d.ts +0 -2
  431. package/dist/types/src/playground/debug/plugin.d.ts.map +0 -1
  432. package/dist/types/src/playground/generator/Main.d.ts +0 -6
  433. package/dist/types/src/playground/generator/Main.d.ts.map +0 -1
  434. package/dist/types/src/playground/generator/Toolbar.d.ts +0 -6
  435. package/dist/types/src/playground/generator/Toolbar.d.ts.map +0 -1
  436. package/dist/types/src/playground/generator/generator.d.ts +0 -7
  437. package/dist/types/src/playground/generator/generator.d.ts.map +0 -1
  438. package/dist/types/src/playground/generator/index.d.ts +0 -3
  439. package/dist/types/src/playground/generator/index.d.ts.map +0 -1
  440. package/dist/types/src/playground/generator/plugin.d.ts +0 -2
  441. package/dist/types/src/playground/generator/plugin.d.ts.map +0 -1
  442. package/dist/types/src/playground/layout/Layout.d.ts +0 -8
  443. package/dist/types/src/playground/layout/Layout.d.ts.map +0 -1
  444. package/dist/types/src/playground/layout/index.d.ts +0 -2
  445. package/dist/types/src/playground/layout/index.d.ts.map +0 -1
  446. package/dist/types/src/playground/layout/plugin.d.ts +0 -2
  447. package/dist/types/src/playground/layout/plugin.d.ts.map +0 -1
  448. package/dist/types/src/playground/logger/Toolbar.d.ts +0 -6
  449. package/dist/types/src/playground/logger/Toolbar.d.ts.map +0 -1
  450. package/dist/types/src/playground/logger/index.d.ts +0 -2
  451. package/dist/types/src/playground/logger/index.d.ts.map +0 -1
  452. package/dist/types/src/playground/logger/plugin.d.ts +0 -2
  453. package/dist/types/src/playground/logger/plugin.d.ts.map +0 -1
  454. package/dist/types/src/playground/logger/schema.d.ts +0 -13
  455. package/dist/types/src/playground/logger/schema.d.ts.map +0 -1
  456. package/dist/types/src/playground/playground.stories.d.ts.map +0 -1
  457. package/dist/types/src/plugin-intent/IntentPlugin.d.ts +0 -2
  458. package/dist/types/src/plugin-intent/IntentPlugin.d.ts.map +0 -1
  459. package/dist/types/src/plugin-intent/actions.d.ts +0 -38
  460. package/dist/types/src/plugin-intent/actions.d.ts.map +0 -1
  461. package/dist/types/src/plugin-intent/errors.d.ts +0 -16
  462. package/dist/types/src/plugin-intent/errors.d.ts.map +0 -1
  463. package/dist/types/src/plugin-intent/index.d.ts +0 -6
  464. package/dist/types/src/plugin-intent/index.d.ts.map +0 -1
  465. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts +0 -139
  466. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts.map +0 -1
  467. package/dist/types/src/plugin-intent/intent-dispatcher.test.d.ts +0 -2
  468. package/dist/types/src/plugin-intent/intent-dispatcher.test.d.ts.map +0 -1
  469. package/dist/types/src/plugin-intent/intent.d.ts +0 -63
  470. package/dist/types/src/plugin-intent/intent.d.ts.map +0 -1
  471. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts +0 -2
  472. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts.map +0 -1
  473. package/dist/types/src/plugin-settings/actions.d.ts +0 -27
  474. package/dist/types/src/plugin-settings/actions.d.ts.map +0 -1
  475. package/dist/types/src/plugin-settings/app-graph-builder.d.ts +0 -4
  476. package/dist/types/src/plugin-settings/app-graph-builder.d.ts.map +0 -1
  477. package/dist/types/src/plugin-settings/index.d.ts +0 -3
  478. package/dist/types/src/plugin-settings/index.d.ts.map +0 -1
  479. package/dist/types/src/plugin-settings/intent-resolver.d.ts +0 -4
  480. package/dist/types/src/plugin-settings/intent-resolver.d.ts.map +0 -1
  481. package/dist/types/src/plugin-settings/store.d.ts +0 -5
  482. package/dist/types/src/plugin-settings/store.d.ts.map +0 -1
  483. package/dist/types/src/plugin-settings/translations.d.ts +0 -10
  484. package/dist/types/src/plugin-settings/translations.d.ts.map +0 -1
  485. package/dist/types/src/react/ErrorBoundary.d.ts +0 -30
  486. package/dist/types/src/react/ErrorBoundary.d.ts.map +0 -1
  487. package/dist/types/src/react/IntentContext.d.ts +0 -8
  488. package/dist/types/src/react/IntentContext.d.ts.map +0 -1
  489. package/dist/types/src/react/PluginManagerProvider.d.ts +0 -10
  490. package/dist/types/src/react/PluginManagerProvider.d.ts.map +0 -1
  491. package/dist/types/src/react/Surface.d.ts +0 -12
  492. package/dist/types/src/react/Surface.d.ts.map +0 -1
  493. package/dist/types/src/react/Surface.stories.d.ts +0 -18
  494. package/dist/types/src/react/Surface.stories.d.ts.map +0 -1
  495. package/dist/types/src/react/common.d.ts +0 -13
  496. package/dist/types/src/react/common.d.ts.map +0 -1
  497. package/dist/types/src/react/index.d.ts +0 -7
  498. package/dist/types/src/react/index.d.ts.map +0 -1
  499. package/dist/types/src/react/useCapabilities.d.ts +0 -13
  500. package/dist/types/src/react/useCapabilities.d.ts.map +0 -1
  501. package/dist/types/src/react/useIntentResolver.d.ts +0 -3
  502. package/dist/types/src/react/useIntentResolver.d.ts.map +0 -1
  503. package/dist/types/src/worker.d.ts +0 -4
  504. package/dist/types/src/worker.d.ts.map +0 -1
  505. package/src/App.tsx +0 -280
  506. package/src/common/collaboration.ts +0 -18
  507. package/src/common/events.ts +0 -79
  508. package/src/common/file.ts +0 -22
  509. package/src/common/graph.ts +0 -30
  510. package/src/common/layout.ts +0 -278
  511. package/src/common/surface.ts +0 -86
  512. package/src/core/capabilities.test.ts +0 -136
  513. package/src/core/capabilities.ts +0 -259
  514. package/src/core/manager.test.ts +0 -516
  515. package/src/core/manager.ts +0 -597
  516. package/src/playground/debug/Debug.tsx +0 -39
  517. package/src/playground/debug/plugin.ts +0 -17
  518. package/src/playground/generator/Main.tsx +0 -71
  519. package/src/playground/generator/Toolbar.tsx +0 -47
  520. package/src/playground/generator/generator.ts +0 -48
  521. package/src/playground/generator/index.ts +0 -6
  522. package/src/playground/generator/plugin.ts +0 -23
  523. package/src/playground/layout/Layout.tsx +0 -33
  524. package/src/playground/layout/plugin.ts +0 -17
  525. package/src/playground/logger/Toolbar.tsx +0 -30
  526. package/src/playground/logger/plugin.ts +0 -37
  527. package/src/playground/logger/schema.ts +0 -12
  528. package/src/playground/playground.stories.tsx +0 -47
  529. package/src/plugin-intent/IntentPlugin.ts +0 -21
  530. package/src/plugin-intent/actions.ts +0 -33
  531. package/src/plugin-intent/errors.ts +0 -39
  532. package/src/plugin-intent/index.ts +0 -9
  533. package/src/plugin-intent/intent-dispatcher.test.ts +0 -279
  534. package/src/plugin-intent/intent-dispatcher.ts +0 -335
  535. package/src/plugin-intent/intent.ts +0 -154
  536. package/src/plugin-settings/SettingsPlugin.ts +0 -36
  537. package/src/plugin-settings/actions.ts +0 -29
  538. package/src/plugin-settings/app-graph-builder.ts +0 -158
  539. package/src/plugin-settings/index.ts +0 -6
  540. package/src/plugin-settings/intent-resolver.ts +0 -35
  541. package/src/plugin-settings/store.ts +0 -33
  542. package/src/plugin-settings/translations.ts +0 -19
  543. package/src/react/ErrorBoundary.tsx +0 -54
  544. package/src/react/IntentContext.tsx +0 -35
  545. package/src/react/Surface.stories.tsx +0 -104
  546. package/src/react/Surface.tsx +0 -78
  547. package/src/react/common.ts +0 -13
  548. package/src/react/index.ts +0 -10
  549. package/src/react/useCapabilities.ts +0 -31
  550. package/src/react/useIntentResolver.ts +0 -22
  551. package/src/worker.ts +0 -11
  552. /package/dist/lib/browser/{intent-dispatcher-QG7UPGQX.mjs.map → chunk-J5LGTIGS.mjs.map} +0 -0
  553. /package/dist/lib/browser/{worker.mjs.map → common/activation-events.mjs.map} +0 -0
  554. /package/dist/lib/{node-esm/intent-dispatcher-NXBGPJOX.mjs.map → browser/common/capabilities.mjs.map} +0 -0
  555. /package/dist/lib/{node-esm/worker.mjs.map → browser/core/activation-event.mjs.map} +0 -0
@@ -0,0 +1,184 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Atom, useAtomValue } from '@effect-atom/atom-react';
6
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
7
+ import * as Effect from 'effect/Effect';
8
+ import React, { useEffect, useMemo, useState } from 'react';
9
+
10
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
11
+ import { useWebComponentContext } from '@dxos/web-context-react';
12
+
13
+ import { ActivationEvents, Capabilities } from '../../../common';
14
+ import { PluginManagerContext } from '../../../context';
15
+ import { Capability, Plugin } from '../../../core';
16
+ import { useApp } from '../../hooks';
17
+
18
+ // Define the Counter capability
19
+ const Counter = Capability.make<{ count: number; increment: () => void }>('example/counter');
20
+
21
+ const CountStatus = () => {
22
+ const manager = useWebComponentContext(PluginManagerContext);
23
+ const capabilitiesAtom = useMemo(
24
+ () => manager?.capabilities.atom(Counter) ?? Atom.make<{ count: number; increment: () => void }[]>([]),
25
+ [manager],
26
+ );
27
+ const capabilities = useAtomValue(capabilitiesAtom);
28
+ const counter = (capabilities as any)[0];
29
+ const [count, setCount] = useState(counter?.count ?? 0);
30
+
31
+ useEffect(() => {
32
+ if (!counter) {
33
+ return;
34
+ }
35
+ setCount(counter.count);
36
+ if ('subscribe' in counter && typeof counter.subscribe === 'function') {
37
+ return counter.subscribe(() => setCount(counter.count));
38
+ }
39
+ }, [counter]);
40
+
41
+ if (!manager) {
42
+ return null;
43
+ }
44
+
45
+ const isEven = count % 2 === 0;
46
+
47
+ return (
48
+ <div
49
+ className={`mt-4 px-4 py-2 rounded-full text-sm font-medium transition-colors ${
50
+ isEven
51
+ ? 'bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-400'
52
+ : 'bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-400'
53
+ }`}
54
+ >
55
+ Status: {isEven ? 'Even' : 'Odd'}
56
+ </div>
57
+ );
58
+ };
59
+
60
+ // A component that consumes the PluginManager via web context
61
+ const CounterComponent = () => {
62
+ // Use the web-context hook to get the PluginManager
63
+ const manager = useWebComponentContext(PluginManagerContext);
64
+ const capabilitiesAtom = useMemo(
65
+ () => manager?.capabilities.atom(Counter) ?? Atom.make<{ count: number; increment: () => void }[]>([]),
66
+ [manager],
67
+ );
68
+ const capabilities = useAtomValue(capabilitiesAtom);
69
+ const counter = (capabilities as any)[0];
70
+ const [count, setCount] = useState(counter?.count ?? 0);
71
+
72
+ useEffect(() => {
73
+ if (!counter) {
74
+ return;
75
+ }
76
+ setCount(counter.count);
77
+ if ('subscribe' in counter && typeof counter.subscribe === 'function') {
78
+ return counter.subscribe(() => setCount(counter.count));
79
+ }
80
+ }, [counter]);
81
+
82
+ if (!manager) {
83
+ return <div className='p-4 text-error-text'>Error: Context not found</div>;
84
+ }
85
+
86
+ return (
87
+ <div className='flex flex-col items-center justify-center h-screen bg-neutral-100 dark:bg-neutral-900 text-neutral-900 dark:text-white'>
88
+ <div className='p-8 bg-white dark:bg-neutral-800 rounded-lg shadow-xl border border-neutral-200 dark:border-neutral-700 max-w-md w-full'>
89
+ <h2 className='text-2xl font-bold mb-6 text-center text-primary-600 dark:text-primary-400'>
90
+ Web Context Counter
91
+ </h2>
92
+
93
+ <div className='flex flex-col items-center gap-6'>
94
+ <div className='text-6xl font-mono font-bold tabular-nums tracking-tighter'>{count}</div>
95
+
96
+ <button
97
+ className='px-6 py-3 bg-primary-600 hover:bg-primary-700 text-white font-semibold rounded-full transition-colors shadow-md active:transform active:scale-95'
98
+ onClick={() => {
99
+ const counter = manager.capabilities.get(Counter);
100
+ counter.increment();
101
+ }}
102
+ >
103
+ Increment
104
+ </button>
105
+
106
+ <CountStatus />
107
+ </div>
108
+
109
+ <div className='mt-8 pt-4 border-t border-neutral-200 dark:border-neutral-700 text-center'>
110
+ <p className='text-sm text-neutral-500 dark:text-neutral-400'>
111
+ This component accesses the <code>PluginManager</code> via <code>useWebComponentContext</code>.
112
+ </p>
113
+ </div>
114
+ </div>
115
+ </div>
116
+ );
117
+ };
118
+
119
+ // Plugin that provides the Counter capability and renders the UI
120
+ const CounterPlugin = Plugin.define({
121
+ id: 'org.dxos.plugin.counter',
122
+ name: 'Counter Plugin',
123
+ tags: ['system'],
124
+ }).pipe(
125
+ Plugin.addModule({
126
+ id: 'CounterMain',
127
+ activatesOn: ActivationEvents.Startup,
128
+ activate: () => {
129
+ const listeners = new Set<() => void>();
130
+ const counter = {
131
+ count: 0,
132
+ increment: () => {
133
+ counter.count++;
134
+ listeners.forEach((listener) => listener());
135
+ },
136
+ subscribe: (listener: () => void) => {
137
+ listeners.add(listener);
138
+ return () => listeners.delete(listener);
139
+ },
140
+ };
141
+
142
+ return Effect.succeed([
143
+ // Contribute the state/logic
144
+ Capability.contributes(Counter, counter),
145
+
146
+ // Contribute the UI
147
+ Capability.contributes(Capabilities.ReactRoot, {
148
+ id: 'org.dxos.plugin.counter.root',
149
+ root: CounterComponent,
150
+ }),
151
+ ]);
152
+ },
153
+ }),
154
+ Plugin.make,
155
+ )();
156
+
157
+ const plugins = [CounterPlugin];
158
+ const placeholder = () => (
159
+ <div className='flex h-screen items-center justify-center p-4 text-lg text-neutral-500'>
160
+ Initializing Application...
161
+ </div>
162
+ );
163
+
164
+ const DefaultStory = () => {
165
+ const App = useApp({
166
+ plugins,
167
+ placeholder,
168
+ });
169
+
170
+ return <App />;
171
+ };
172
+
173
+ const meta = {
174
+ title: 'sdk/app-framework/components/PluginManagerContext',
175
+ render: DefaultStory,
176
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
177
+ parameters: {
178
+ layout: 'fullscreen',
179
+ },
180
+ } satisfies Meta;
181
+
182
+ export default meta;
183
+
184
+ export const Default: StoryObj<typeof meta> = {};
@@ -6,14 +6,14 @@ import { createContext, useContext } from 'react';
6
6
 
7
7
  import { raise } from '@dxos/debug';
8
8
 
9
- import { type PluginManager } from '../core';
9
+ import { type PluginManager } from '../../../core';
10
10
 
11
- const PluginManagerContext = createContext<PluginManager | undefined>(undefined);
11
+ const PluginManagerContext = createContext<PluginManager.PluginManager | undefined>(undefined);
12
12
 
13
13
  /**
14
14
  * Get the plugin manager.
15
15
  */
16
- export const usePluginManager = (): PluginManager =>
16
+ export const usePluginManager = (): PluginManager.PluginManager =>
17
17
  useContext(PluginManagerContext) ?? raise(new Error('Missing PluginManagerContext'));
18
18
 
19
19
  /**
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './PluginManagerProvider';
@@ -0,0 +1,144 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React, { forwardRef, useCallback, useEffect, useRef, useState } from 'react';
7
+
8
+ import { random } from '@dxos/random';
9
+ import { List, ListItem, Panel, Toolbar } from '@dxos/react-ui';
10
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
11
+ import { type ColorStyles, getHashStyles, mx } from '@dxos/ui-theme';
12
+
13
+ import { Capabilities } from '../../../common';
14
+ import { withPluginManager } from '../../../testing';
15
+ import { usePluginManager } from '../PluginManager';
16
+ import { SurfaceComponent, useSurfaces } from './SurfaceComponent';
17
+ import { create } from './types';
18
+
19
+ type TestComponentProps = {
20
+ id: string;
21
+ styles: ColorStyles;
22
+ };
23
+
24
+ const TestComponent = forwardRef<HTMLDivElement, TestComponentProps>(({ styles, id }, forwardedRef) => {
25
+ return (
26
+ <div
27
+ className={mx('flex justify-center items-center border rounded-sm', styles.surface, styles.border)}
28
+ ref={forwardedRef}
29
+ >
30
+ <span className={mx('dx-tag font-mono text-lg', styles.text)}>{id}</span>
31
+ </div>
32
+ );
33
+ });
34
+
35
+ const DefaultStory = () => {
36
+ const manager = usePluginManager();
37
+ const surfaces = useSurfaces();
38
+ const [selected, setSelected] = useState<string | undefined>();
39
+
40
+ const handleAdd = useCallback(() => {
41
+ const id = `test-${random.number.int({ min: 0, max: 1_000 })}`;
42
+ const styles = getHashStyles(id);
43
+
44
+ manager.capabilities.contribute({
45
+ module: 'test',
46
+ interface: Capabilities.ReactSurface,
47
+ implementation: create({
48
+ id,
49
+ role: 'item',
50
+ filter: (data): data is any => (data as any)?.id === id,
51
+ component: ({ ref }) => <TestComponent id={id} styles={styles} ref={ref} />,
52
+ }),
53
+ });
54
+
55
+ setSelected(id);
56
+ }, [manager]);
57
+
58
+ const handleSelect = useCallback(() => {
59
+ setSelected(random.helpers.arrayElement(surfaces)?.id);
60
+ }, [surfaces]);
61
+
62
+ const handleError = useCallback(() => {
63
+ manager.capabilities.contribute({
64
+ module: 'error',
65
+ interface: Capabilities.ReactSurface,
66
+ implementation: create({
67
+ id: 'error',
68
+ role: 'item',
69
+ filter: (data): data is any => (data as any)?.id === 'error',
70
+ component: () => {
71
+ const [count, setCount] = useState(3);
72
+ useEffect(() => {
73
+ const interval = setInterval(() => {
74
+ setCount((count) => {
75
+ if (count <= 1) {
76
+ clearInterval(interval);
77
+ }
78
+
79
+ return count - 1;
80
+ });
81
+ }, 1_000);
82
+ return () => clearInterval(interval);
83
+ }, []);
84
+
85
+ if (count <= 0) {
86
+ throw new Error('BANG!');
87
+ }
88
+
89
+ return (
90
+ <div className='flex justify-center items-center border border-rose-fill rounded-sm'>
91
+ <span className='font-mono'>Ticking... {count}</span>
92
+ </div>
93
+ );
94
+ },
95
+ }),
96
+ });
97
+
98
+ setSelected('error');
99
+ }, [manager]);
100
+
101
+ const ref = useRef<HTMLElement>(null);
102
+ useEffect(() => {
103
+ console.log(ref.current);
104
+ }, [ref]);
105
+
106
+ return (
107
+ <Panel.Root>
108
+ <Panel.Toolbar asChild>
109
+ <Toolbar.Root>
110
+ <Toolbar.Button onClick={handleAdd}>Add</Toolbar.Button>
111
+ <Toolbar.Button onClick={handleSelect}>Pick</Toolbar.Button>
112
+ <Toolbar.Button onClick={handleError}>Error</Toolbar.Button>
113
+ </Toolbar.Root>
114
+ </Panel.Toolbar>
115
+ <Panel.Content className='grid grid-cols-2 h-full gap-4 overflow-hidden'>
116
+ <SurfaceComponent role='item' data={selected ? { id: selected } : undefined} limit={1} ref={ref} />
117
+ <div className='overflow-y-auto h-full'>
118
+ <List>
119
+ {surfaces.map((surface) => (
120
+ <ListItem.Root key={surface.id} id={surface.id}>
121
+ <ListItem.Heading classNames='flex items-center'>{surface.id}</ListItem.Heading>
122
+ </ListItem.Root>
123
+ ))}
124
+ </List>
125
+ </div>
126
+ </Panel.Content>
127
+ </Panel.Root>
128
+ );
129
+ };
130
+
131
+ const meta = {
132
+ title: 'sdk/app-framework/components/Surface',
133
+ render: DefaultStory,
134
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' }), withPluginManager({ capabilities: [] })],
135
+ parameters: {
136
+ layout: 'fullscreen',
137
+ },
138
+ } satisfies Meta<typeof DefaultStory>;
139
+
140
+ export default meta;
141
+
142
+ type Story = StoryObj<typeof meta>;
143
+
144
+ export const Default: Story = {};
@@ -0,0 +1,303 @@
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 {
31
+ type Definition,
32
+ type Props,
33
+ type RoleToken,
34
+ type TokenData,
35
+ type TypedProps,
36
+ type WebComponentDefinition,
37
+ } from './types';
38
+
39
+ const DEBUG = import.meta.env.VITE_DEBUG;
40
+
41
+ const DEFAULT_PLACEHOLDER = <Fragment />;
42
+
43
+ /**
44
+ * Wrapper component for rendering Web Component surfaces.
45
+ * Handles creation, prop setting, and cleanup of Web Components.
46
+ */
47
+ const WebComponentWrapper = memo(
48
+ forwardRef<HTMLElement, Omit<Props, 'role'> & { role: string; definition: WebComponentDefinition }>(
49
+ ({ id, role, data, limit, definition, ...rest }, forwardedRef) => {
50
+ const containerRef = useRef<HTMLDivElement>(null);
51
+ const elementRef = useRef<HTMLElement | null>(null);
52
+ const propsRef = useRef({ id, role, data, limit, ...rest });
53
+
54
+ // Update props ref on every render
55
+ propsRef.current = { id, role, data, limit, ...rest };
56
+
57
+ // Create element only once
58
+ useEffect(() => {
59
+ if (!containerRef.current || elementRef.current) {
60
+ return;
61
+ }
62
+
63
+ // Create the Web Component
64
+ const element = document.createElement(definition.tagName);
65
+ elementRef.current = element;
66
+
67
+ // Set initial properties on the Web Component
68
+ Object.assign(element, propsRef.current);
69
+
70
+ // Append to container
71
+ containerRef.current.appendChild(element);
72
+
73
+ // Setup ref forwarding if provided
74
+ if (typeof forwardedRef === 'function') {
75
+ forwardedRef(element);
76
+ } else if (forwardedRef) {
77
+ forwardedRef.current = element;
78
+ }
79
+
80
+ // Cleanup on unmount to prevent memory leaks
81
+ return () => {
82
+ if (elementRef.current && containerRef.current?.contains(elementRef.current)) {
83
+ containerRef.current.removeChild(elementRef.current);
84
+ }
85
+ if (typeof forwardedRef === 'function') {
86
+ forwardedRef(null);
87
+ } else if (forwardedRef) {
88
+ forwardedRef.current = null;
89
+ }
90
+ elementRef.current = null;
91
+ };
92
+ }, [definition.tagName, forwardedRef]);
93
+
94
+ // Update props on existing element without recreating it
95
+ // This runs on every render to ensure all props (including those in `rest`) are kept up to date
96
+ useEffect(() => {
97
+ const element = elementRef.current;
98
+ if (!element) {
99
+ return;
100
+ }
101
+
102
+ // Update properties on the existing Web Component
103
+ Object.assign(element, propsRef.current);
104
+ });
105
+
106
+ return <div ref={containerRef} />;
107
+ },
108
+ ),
109
+ );
110
+
111
+ WebComponentWrapper.displayName = 'WebComponentWrapper';
112
+
113
+ /**
114
+ * Wrapper component that provides context for a surface.
115
+ */
116
+ // TODO(burdon): Allow DebugPlugin to provide different fallback using react-ui ErrorFallback.
117
+ const SurfaceContextProvider = memo(
118
+ forwardRef<HTMLElement, Omit<Props, 'role'> & { role: string; definition: Definition }>(
119
+ ({ id, role, data, limit, fallback = ErrorFallback, definition, ...rest }, forwardedRef) => {
120
+ const contextValue = useMemo(() => ({ id, role, data }), [id, role, data]);
121
+ const onProfilerRender = useSurfaceProfilerCallback();
122
+ const profilerId = `surface/${id}/${role}`;
123
+
124
+ // Handle Web Component surfaces
125
+ if (definition.kind === 'web-component') {
126
+ return (
127
+ <ErrorBoundary name='surface' resetKeys={[data]} FallbackComponent={fallback}>
128
+ <SurfaceContext.Provider value={contextValue}>
129
+ <WebComponentWrapper
130
+ id={id}
131
+ role={role}
132
+ data={data}
133
+ limit={limit}
134
+ definition={definition}
135
+ ref={forwardedRef}
136
+ {...rest}
137
+ />
138
+ </SurfaceContext.Provider>
139
+ </ErrorBoundary>
140
+ );
141
+ }
142
+
143
+ // Handle React component surfaces
144
+ const Component = definition.component;
145
+
146
+ // TODO(burdon): Remove from production build?
147
+ const debug = DEBUG || '__DX_DEBUG__' in window;
148
+ if (debug) {
149
+ return (
150
+ <ErrorBoundary name='surface' resetKeys={[data]} FallbackComponent={fallback}>
151
+ <div className='contents' data-id={id} data-role={role}>
152
+ <SurfaceContext.Provider value={contextValue}>
153
+ <SurfaceInfo ref={forwardedRef}>
154
+ {onProfilerRender && !profilerId.includes('org.dxos.plugin.debug') ? (
155
+ <Profiler id={profilerId} onRender={onProfilerRender}>
156
+ <Component id={id} role={role} data={data} limit={limit} {...rest} />
157
+ </Profiler>
158
+ ) : (
159
+ <Component id={id} role={role} data={data} limit={limit} {...rest} />
160
+ )}
161
+ </SurfaceInfo>
162
+ </SurfaceContext.Provider>
163
+ </div>
164
+ </ErrorBoundary>
165
+ );
166
+ }
167
+
168
+ return (
169
+ <ErrorBoundary name='surface' resetKeys={[data]} FallbackComponent={fallback}>
170
+ <div className='contents' data-id={id} data-role={role}>
171
+ <SurfaceContext.Provider value={contextValue}>
172
+ <Component id={id} role={role} data={data} limit={limit} {...rest} ref={forwardedRef} />
173
+ </SurfaceContext.Provider>
174
+ </div>
175
+ </ErrorBoundary>
176
+ );
177
+ },
178
+ ),
179
+ );
180
+
181
+ SurfaceContextProvider.displayName = 'SurfaceContextProvider';
182
+
183
+ /**
184
+ * A surface is a named region of the screen that can be populated by plugins.
185
+ */
186
+ // TODO(burdon): Remove `ref` since relying on this would be error prone.
187
+ export const SurfaceComponent = memo(
188
+ forwardRef<HTMLElement, Props & { type?: RoleToken<any> }>(
189
+ ({ id: _id, role, type, data: dataProp, limit, placeholder = DEFAULT_PLACEHOLDER, ...rest }, forwardedRef) => {
190
+ const data = useDefaultValue(dataProp, () => ({}));
191
+ // TODO(wittjosiah): This will make all surfaces depend on a single signal.
192
+ // This isn't ideal because it means that any change to the data will cause all surfaces to re-render.
193
+ // This effectively means that plugin modules which contribute surfaces need to all be activated at startup.
194
+ // This should be fine for now because it's how it worked prior to capabilities api anyway.
195
+ // In the future, it would be nice to be able to bucket the surface contributions by role.
196
+ const surfaces = useSurfaces();
197
+
198
+ const effectiveRole = role ?? type?.role;
199
+ if (effectiveRole == null) {
200
+ if (DEBUG) {
201
+ log.warn('Surface has neither `role` nor `type` prop', { id: _id });
202
+ }
203
+ return null;
204
+ }
205
+
206
+ // NOTE: Memoizing the candidates makes the surface not re-render based on reactivity within data.
207
+ const definitions = findCandidates(surfaces, { role: effectiveRole, data });
208
+ const candidates = limit ? definitions.slice(0, limit) : definitions;
209
+ if (DEBUG && candidates.length === 0) {
210
+ log.warn('no candidates for surface', { role: effectiveRole, data });
211
+ return null;
212
+ }
213
+
214
+ return (
215
+ <Suspense fallback={placeholder}>
216
+ {candidates.map((definition) => (
217
+ <SurfaceContextProvider
218
+ key={definition.id}
219
+ id={definition.id}
220
+ role={effectiveRole}
221
+ data={data}
222
+ limit={limit}
223
+ definition={definition}
224
+ ref={forwardedRef}
225
+ {...rest}
226
+ />
227
+ ))}
228
+ </Suspense>
229
+ );
230
+ },
231
+ ),
232
+ ) as (<TToken extends RoleToken<any>>(props: TypedProps<TToken> & RefAttributes<HTMLElement>) => React.ReactNode) &
233
+ NamedExoticComponent<Props & RefAttributes<HTMLElement>>;
234
+
235
+ SurfaceComponent.displayName = 'Surface';
236
+
237
+ // TODO(burdon): Make user facing, with telemetry.
238
+ const ErrorFallback = ({ error }: Props) => {
239
+ const { message } = error instanceof Error ? error : { message: String(error) };
240
+ return (
241
+ <div role='alert' data-testid='error-boundary-fallback'>
242
+ <h1 className='flex gap-2 text-sm mt-2 text-info-text'>{message}</h1>
243
+ </div>
244
+ );
245
+ };
246
+
247
+ const findCandidates = (surfaces: Definition[], { role, data }: { role: string; data: Props['data'] }) => {
248
+ return Object.values(surfaces)
249
+ .filter((definition) =>
250
+ Array.isArray(definition.role) ? definition.role.includes(role) : definition.role === role,
251
+ )
252
+ .filter(({ filter }) => (filter ? filter(data ?? {}, role) : true))
253
+ .toSorted(byPosition);
254
+ };
255
+
256
+ /**
257
+ * @internal
258
+ */
259
+ export const useSurfaces = () => {
260
+ const manager = usePluginManager();
261
+ const surfacesByModule = useAtomValue(manager.capabilities.atomByModule(Capabilities.ReactSurface));
262
+ return useMemo(() => {
263
+ const result: Definition[] = [];
264
+ for (const [moduleId, surfaces] of Object.entries(surfacesByModule)) {
265
+ for (const def of surfaces.flat()) {
266
+ result.push({ ...def, id: `${moduleId}.${def.id}` });
267
+ }
268
+ }
269
+ return result;
270
+ }, [surfacesByModule]);
271
+ };
272
+
273
+ /**
274
+ * @returns `true` if there is a contributed surface which matches the specified role & data, `false` otherwise.
275
+ *
276
+ * Two overloads:
277
+ * - Typed: pass a `type` role token and `data` is constrained to the token's
278
+ * declared contract (e.g. `AppSurface.Section` requires `attendableId`).
279
+ * - Legacy: pass a string `role` and `data` is untyped.
280
+ */
281
+ export function isSurfaceAvailable<TToken extends RoleToken<any>>(
282
+ capabilityManager: CapabilityManager.CapabilityManager,
283
+ args: { type: TToken; data?: TokenData<TToken>; role?: never },
284
+ ): boolean;
285
+ export function isSurfaceAvailable(
286
+ capabilityManager: CapabilityManager.CapabilityManager,
287
+ args: Pick<Props, 'role' | 'data'> & { type?: undefined },
288
+ ): boolean;
289
+ export function isSurfaceAvailable(
290
+ capabilityManager: CapabilityManager.CapabilityManager,
291
+ { role, type, data }: { role?: string; type?: RoleToken<any>; data?: unknown },
292
+ ): boolean {
293
+ const effectiveRole = role ?? type?.role;
294
+ if (effectiveRole == null) {
295
+ return false;
296
+ }
297
+ const surfaces = capabilityManager.getAll(Capabilities.ReactSurface);
298
+ const candidates = findCandidates(surfaces.flat(), {
299
+ role: effectiveRole,
300
+ data: data as Props['data'],
301
+ });
302
+ return candidates.length > 0;
303
+ }