@dxos/app-framework 0.8.4-main.a4bbb77 → 0.8.4-main.abd8ff62ef

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 (571) hide show
  1. package/.storybook/main.mts +2 -4
  2. package/.storybook/preview.mts +2 -2
  3. package/dist/lib/browser/capability-Q5XRXRD2.mjs +38 -0
  4. package/dist/lib/browser/capability-Q5XRXRD2.mjs.map +7 -0
  5. package/dist/lib/browser/capability-V7LR4LQN.mjs +35 -0
  6. package/dist/lib/browser/capability-V7LR4LQN.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-23D4SJUE.mjs +42 -0
  8. package/dist/lib/browser/chunk-23D4SJUE.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-3JWJXGLK.mjs +79 -0
  10. package/dist/lib/browser/chunk-3JWJXGLK.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-3ZS2A3DN.mjs +907 -0
  12. package/dist/lib/browser/chunk-3ZS2A3DN.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-45CHLTBV.mjs +34 -0
  14. package/dist/lib/browser/chunk-45CHLTBV.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-5LAIGWLU.mjs +467 -0
  16. package/dist/lib/browser/chunk-5LAIGWLU.mjs.map +7 -0
  17. package/dist/lib/browser/chunk-66IXTIVK.mjs +48 -0
  18. package/dist/lib/browser/chunk-66IXTIVK.mjs.map +7 -0
  19. package/dist/lib/browser/chunk-FJ4765WW.mjs +8 -0
  20. package/dist/lib/browser/chunk-FJ4765WW.mjs.map +7 -0
  21. package/dist/lib/browser/chunk-G7SDBRKH.mjs +1 -0
  22. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  23. package/dist/lib/browser/chunk-JXCBZSBJ.mjs +372 -0
  24. package/dist/lib/browser/chunk-JXCBZSBJ.mjs.map +7 -0
  25. package/dist/lib/browser/chunk-MX5DKEJH.mjs +584 -0
  26. package/dist/lib/browser/chunk-MX5DKEJH.mjs.map +7 -0
  27. package/dist/lib/browser/chunk-WBHCSOBW.mjs +80 -0
  28. package/dist/lib/browser/chunk-WBHCSOBW.mjs.map +7 -0
  29. package/dist/lib/browser/chunk-Z55LVAGN.mjs +213 -0
  30. package/dist/lib/browser/chunk-Z55LVAGN.mjs.map +7 -0
  31. package/dist/lib/browser/chunk-ZGJAZSNE.mjs +142 -0
  32. package/dist/lib/browser/chunk-ZGJAZSNE.mjs.map +7 -0
  33. package/dist/lib/browser/cli/index.mjs +74 -0
  34. package/dist/lib/browser/cli/index.mjs.map +7 -0
  35. package/dist/lib/browser/common/activation-events.mjs +24 -0
  36. package/dist/lib/browser/common/capabilities.mjs +46 -0
  37. package/dist/lib/browser/core/activation-event.mjs +20 -0
  38. package/dist/lib/browser/core/activation-event.mjs.map +7 -0
  39. package/dist/lib/browser/core/capability.mjs +30 -0
  40. package/dist/lib/browser/core/capability.mjs.map +7 -0
  41. package/dist/lib/browser/core/plugin-manager.mjs +17 -0
  42. package/dist/lib/browser/core/plugin-manager.mjs.map +7 -0
  43. package/dist/lib/browser/core/plugin.mjs +37 -0
  44. package/dist/lib/browser/core/plugin.mjs.map +7 -0
  45. package/dist/lib/browser/core/url-loader.mjs +20 -0
  46. package/dist/lib/browser/core/url-loader.mjs.map +7 -0
  47. package/dist/lib/browser/index.mjs +95 -148
  48. package/dist/lib/browser/index.mjs.map +4 -4
  49. package/dist/lib/browser/invoker-capability-LNX4CGIV.mjs +44 -0
  50. package/dist/lib/browser/invoker-capability-LNX4CGIV.mjs.map +7 -0
  51. package/dist/lib/browser/meta.json +1 -1
  52. package/dist/lib/browser/testing/index.mjs +227 -41
  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 +48 -0
  57. package/dist/lib/browser/ui/index.mjs.map +7 -0
  58. package/dist/lib/node-esm/capability-EW5GJCI6.mjs +39 -0
  59. package/dist/lib/node-esm/capability-EW5GJCI6.mjs.map +7 -0
  60. package/dist/lib/node-esm/capability-YKBMMD53.mjs +36 -0
  61. package/dist/lib/node-esm/capability-YKBMMD53.mjs.map +7 -0
  62. package/dist/lib/node-esm/chunk-37Z53PXZ.mjs +10 -0
  63. package/dist/lib/node-esm/chunk-37Z53PXZ.mjs.map +7 -0
  64. package/dist/lib/node-esm/chunk-6XW6LET6.mjs +35 -0
  65. package/dist/lib/node-esm/chunk-6XW6LET6.mjs.map +7 -0
  66. package/dist/lib/node-esm/chunk-D347W3KO.mjs +143 -0
  67. package/dist/lib/node-esm/chunk-D347W3KO.mjs.map +7 -0
  68. package/dist/lib/node-esm/chunk-D5PO2WXX.mjs +373 -0
  69. package/dist/lib/node-esm/chunk-D5PO2WXX.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-HTBJU5FX.mjs +214 -0
  73. package/dist/lib/node-esm/chunk-HTBJU5FX.mjs.map +7 -0
  74. package/dist/lib/node-esm/chunk-KM2F6GH6.mjs +468 -0
  75. package/dist/lib/node-esm/chunk-KM2F6GH6.mjs.map +7 -0
  76. package/dist/lib/node-esm/chunk-OZ7DZA5Z.mjs +2 -0
  77. package/dist/lib/node-esm/chunk-OZ7DZA5Z.mjs.map +7 -0
  78. package/dist/lib/node-esm/chunk-Q7XBFII4.mjs +908 -0
  79. package/dist/lib/node-esm/chunk-Q7XBFII4.mjs.map +7 -0
  80. package/dist/lib/node-esm/chunk-SBS2YMPT.mjs +43 -0
  81. package/dist/lib/node-esm/chunk-SBS2YMPT.mjs.map +7 -0
  82. package/dist/lib/node-esm/chunk-SDJ4B2LU.mjs +80 -0
  83. package/dist/lib/node-esm/chunk-SDJ4B2LU.mjs.map +7 -0
  84. package/dist/lib/node-esm/chunk-WFSRZKBP.mjs +81 -0
  85. package/dist/lib/node-esm/chunk-WFSRZKBP.mjs.map +7 -0
  86. package/dist/lib/node-esm/chunk-WKTLE7MG.mjs +585 -0
  87. package/dist/lib/node-esm/chunk-WKTLE7MG.mjs.map +7 -0
  88. package/dist/lib/node-esm/chunk-XOCUANHO.mjs +49 -0
  89. package/dist/lib/node-esm/chunk-XOCUANHO.mjs.map +7 -0
  90. package/dist/lib/node-esm/cli/index.mjs +75 -0
  91. package/dist/lib/node-esm/cli/index.mjs.map +7 -0
  92. package/dist/lib/node-esm/common/activation-events.mjs +25 -0
  93. package/dist/lib/node-esm/common/activation-events.mjs.map +7 -0
  94. package/dist/lib/node-esm/common/capabilities.mjs +47 -0
  95. package/dist/lib/node-esm/common/capabilities.mjs.map +7 -0
  96. package/dist/lib/node-esm/core/activation-event.mjs +21 -0
  97. package/dist/lib/node-esm/core/activation-event.mjs.map +7 -0
  98. package/dist/lib/node-esm/core/capability.mjs +31 -0
  99. package/dist/lib/node-esm/core/capability.mjs.map +7 -0
  100. package/dist/lib/node-esm/core/plugin-manager.mjs +18 -0
  101. package/dist/lib/node-esm/core/plugin-manager.mjs.map +7 -0
  102. package/dist/lib/node-esm/core/plugin.mjs +38 -0
  103. package/dist/lib/node-esm/core/plugin.mjs.map +7 -0
  104. package/dist/lib/node-esm/core/url-loader.mjs +21 -0
  105. package/dist/lib/node-esm/core/url-loader.mjs.map +7 -0
  106. package/dist/lib/node-esm/index.mjs +95 -148
  107. package/dist/lib/node-esm/index.mjs.map +4 -4
  108. package/dist/lib/node-esm/invoker-capability-O4T5PHLA.mjs +45 -0
  109. package/dist/lib/node-esm/invoker-capability-O4T5PHLA.mjs.map +7 -0
  110. package/dist/lib/node-esm/meta.json +1 -1
  111. package/dist/lib/node-esm/testing/index.mjs +227 -41
  112. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  113. package/dist/lib/node-esm/testing/react.mjs +79 -0
  114. package/dist/lib/node-esm/testing/react.mjs.map +7 -0
  115. package/dist/lib/node-esm/ui/index.mjs +49 -0
  116. package/dist/lib/node-esm/ui/index.mjs.map +7 -0
  117. package/dist/plugin/node-esm/index.mjs +832 -0
  118. package/dist/plugin/node-esm/index.mjs.map +7 -0
  119. package/dist/plugin/node-esm/meta.json +1 -0
  120. package/dist/types/src/cli/cli.d.ts +39 -0
  121. package/dist/types/src/cli/cli.d.ts.map +1 -0
  122. package/dist/types/src/cli/index.d.ts +2 -0
  123. package/dist/types/src/cli/index.d.ts.map +1 -0
  124. package/dist/types/src/common/activation-events.d.ts +27 -0
  125. package/dist/types/src/common/activation-events.d.ts.map +1 -0
  126. package/dist/types/src/common/capabilities.d.ts +110 -197
  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 +156 -0
  143. package/dist/types/src/core/capability.d.ts.map +1 -0
  144. package/dist/types/src/core/index.d.ts +8 -4
  145. package/dist/types/src/core/index.d.ts.map +1 -1
  146. package/dist/types/src/core/plugin-asset-cache.d.ts +71 -0
  147. package/dist/types/src/core/plugin-asset-cache.d.ts.map +1 -0
  148. package/dist/types/src/core/plugin-manager.d.ts +122 -0
  149. package/dist/types/src/core/plugin-manager.d.ts.map +1 -0
  150. package/dist/types/src/core/plugin-manager.test.d.ts +2 -0
  151. package/dist/types/src/core/plugin-manager.test.d.ts.map +1 -0
  152. package/dist/types/src/core/plugin-manifest.d.ts +76 -0
  153. package/dist/types/src/core/plugin-manifest.d.ts.map +1 -0
  154. package/dist/types/src/core/plugin-manifest.test.d.ts +2 -0
  155. package/dist/types/src/core/plugin-manifest.test.d.ts.map +1 -0
  156. package/dist/types/src/core/plugin.d.ts +207 -39
  157. package/dist/types/src/core/plugin.d.ts.map +1 -1
  158. package/dist/types/src/core/url-loader.d.ts +112 -0
  159. package/dist/types/src/core/url-loader.d.ts.map +1 -0
  160. package/dist/types/src/core/url-loader.test.d.ts +2 -0
  161. package/dist/types/src/core/url-loader.test.d.ts.map +1 -0
  162. package/dist/types/src/helpers.d.ts.map +1 -1
  163. package/dist/types/src/index.d.ts +3 -4
  164. package/dist/types/src/index.d.ts.map +1 -1
  165. package/dist/types/src/plugin-operation/OperationPlugin.d.ts +3 -0
  166. package/dist/types/src/plugin-operation/OperationPlugin.d.ts.map +1 -0
  167. package/dist/types/src/plugin-operation/history/capability.d.ts +7 -0
  168. package/dist/types/src/plugin-operation/history/capability.d.ts.map +1 -0
  169. package/dist/types/src/plugin-operation/history/errors.d.ts +32 -0
  170. package/dist/types/src/plugin-operation/history/errors.d.ts.map +1 -0
  171. package/dist/types/src/plugin-operation/history/history-tracker.d.ts +18 -0
  172. package/dist/types/src/plugin-operation/history/history-tracker.d.ts.map +1 -0
  173. package/dist/types/src/plugin-operation/history/history-tracker.test.d.ts +2 -0
  174. package/dist/types/src/plugin-operation/history/history-tracker.test.d.ts.map +1 -0
  175. package/dist/types/src/plugin-operation/history/index.d.ts +6 -0
  176. package/dist/types/src/plugin-operation/history/index.d.ts.map +1 -0
  177. package/dist/types/src/plugin-operation/history/types.d.ts +13 -0
  178. package/dist/types/src/plugin-operation/history/types.d.ts.map +1 -0
  179. package/dist/types/src/plugin-operation/history/undo-mapping.d.ts +101 -0
  180. package/dist/types/src/plugin-operation/history/undo-mapping.d.ts.map +1 -0
  181. package/dist/types/src/plugin-operation/history/undo-registry.d.ts +23 -0
  182. package/dist/types/src/plugin-operation/history/undo-registry.d.ts.map +1 -0
  183. package/dist/types/src/plugin-operation/history/undo-registry.test.d.ts +2 -0
  184. package/dist/types/src/plugin-operation/history/undo-registry.test.d.ts.map +1 -0
  185. package/dist/types/src/plugin-operation/index.d.ts +3 -0
  186. package/dist/types/src/plugin-operation/index.d.ts.map +1 -0
  187. package/dist/types/src/plugin-operation/invoker-capability.d.ts +6 -0
  188. package/dist/types/src/plugin-operation/invoker-capability.d.ts.map +1 -0
  189. package/dist/types/src/plugin-operation/meta.d.ts +3 -0
  190. package/dist/types/src/plugin-operation/meta.d.ts.map +1 -0
  191. package/dist/types/src/plugin-operation/testing.d.ts +59 -0
  192. package/dist/types/src/plugin-operation/testing.d.ts.map +1 -0
  193. package/dist/types/src/plugin-runtime/RuntimePlugin.d.ts +3 -0
  194. package/dist/types/src/plugin-runtime/RuntimePlugin.d.ts.map +1 -0
  195. package/dist/types/src/plugin-runtime/capability.d.ts +6 -0
  196. package/dist/types/src/plugin-runtime/capability.d.ts.map +1 -0
  197. package/dist/types/src/plugin-runtime/index.d.ts +2 -0
  198. package/dist/types/src/plugin-runtime/index.d.ts.map +1 -0
  199. package/dist/types/src/plugin-runtime/meta.d.ts +3 -0
  200. package/dist/types/src/plugin-runtime/meta.d.ts.map +1 -0
  201. package/dist/types/src/testing/harness.d.ts +67 -0
  202. package/dist/types/src/testing/harness.d.ts.map +1 -0
  203. package/dist/types/src/testing/index.d.ts +2 -0
  204. package/dist/types/src/testing/index.d.ts.map +1 -1
  205. package/dist/types/src/testing/react.d.ts +27 -0
  206. package/dist/types/src/testing/react.d.ts.map +1 -0
  207. package/dist/types/src/testing/react.test.d.ts +2 -0
  208. package/dist/types/src/testing/react.test.d.ts.map +1 -0
  209. package/dist/types/src/testing/service.d.ts +8 -0
  210. package/dist/types/src/testing/service.d.ts.map +1 -0
  211. package/dist/types/src/testing/withPluginManager.d.ts +7 -6
  212. package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
  213. package/dist/types/src/testing/withPluginManager.stories.d.ts.map +1 -1
  214. package/dist/types/src/ui/components/App/App.d.ts +9 -0
  215. package/dist/types/src/ui/components/App/App.d.ts.map +1 -0
  216. package/dist/types/src/ui/components/App/App.stories.d.ts +19 -0
  217. package/dist/types/src/ui/components/App/App.stories.d.ts.map +1 -0
  218. package/dist/types/src/ui/components/App/index.d.ts +2 -0
  219. package/dist/types/src/ui/components/App/index.d.ts.map +1 -0
  220. package/dist/types/src/ui/components/Placeholder/Placeholder.d.ts +64 -0
  221. package/dist/types/src/ui/components/Placeholder/Placeholder.d.ts.map +1 -0
  222. package/dist/types/src/ui/components/Placeholder/Placeholder.stories.d.ts +19 -0
  223. package/dist/types/src/ui/components/Placeholder/Placeholder.stories.d.ts.map +1 -0
  224. package/dist/types/src/ui/components/Placeholder/index.d.ts +2 -0
  225. package/dist/types/src/ui/components/Placeholder/index.d.ts.map +1 -0
  226. package/dist/types/src/{playground/playground.stories.d.ts → ui/components/PluginManager/PluginManagerContext.stories.d.ts} +5 -3
  227. package/dist/types/src/ui/components/PluginManager/PluginManagerContext.stories.d.ts.map +1 -0
  228. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts +10 -0
  229. package/dist/types/src/ui/components/PluginManager/PluginManagerProvider.d.ts.map +1 -0
  230. package/dist/types/src/ui/components/PluginManager/index.d.ts +2 -0
  231. package/dist/types/src/ui/components/PluginManager/index.d.ts.map +1 -0
  232. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts +24 -0
  233. package/dist/types/src/ui/components/Surface/SurfaceComponent.d.ts.map +1 -0
  234. package/dist/types/src/{components/App.stories.d.ts → ui/components/Surface/SurfaceComponent.stories.d.ts} +1 -1
  235. package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -0
  236. package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts +11 -0
  237. package/dist/types/src/ui/components/Surface/SurfaceInfo.d.ts.map +1 -0
  238. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts +48 -0
  239. package/dist/types/src/ui/components/Surface/SurfaceProfilerContext.d.ts.map +1 -0
  240. package/dist/types/src/ui/components/Surface/context.d.ts +5 -0
  241. package/dist/types/src/ui/components/Surface/context.d.ts.map +1 -0
  242. package/dist/types/src/ui/components/Surface/index.d.ts +36 -0
  243. package/dist/types/src/ui/components/Surface/index.d.ts.map +1 -0
  244. package/dist/types/src/ui/components/Surface/types.d.ts +197 -0
  245. package/dist/types/src/ui/components/Surface/types.d.ts.map +1 -0
  246. package/dist/types/src/ui/components/Surface/types.test.d.ts +2 -0
  247. package/dist/types/src/ui/components/Surface/types.test.d.ts.map +1 -0
  248. package/dist/types/src/ui/components/index.d.ts +5 -0
  249. package/dist/types/src/ui/components/index.d.ts.map +1 -0
  250. package/dist/types/src/ui/hooks/index.d.ts +6 -0
  251. package/dist/types/src/ui/hooks/index.d.ts.map +1 -0
  252. package/dist/types/src/ui/hooks/useApp.d.ts +88 -0
  253. package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -0
  254. package/dist/types/src/ui/hooks/useApp.test.d.ts +2 -0
  255. package/dist/types/src/ui/hooks/useApp.test.d.ts.map +1 -0
  256. package/dist/types/src/ui/hooks/useCapabilities.d.ts +31 -0
  257. package/dist/types/src/ui/hooks/useCapabilities.d.ts.map +1 -0
  258. package/dist/types/src/{components → ui/hooks}/useLoading.d.ts +1 -2
  259. package/dist/types/src/ui/hooks/useLoading.d.ts.map +1 -0
  260. package/dist/types/src/ui/hooks/useSettingsState.d.ts +10 -0
  261. package/dist/types/src/ui/hooks/useSettingsState.d.ts.map +1 -0
  262. package/dist/types/src/ui/hooks/useSurface.d.ts +3 -0
  263. package/dist/types/src/ui/hooks/useSurface.d.ts.map +1 -0
  264. package/dist/types/src/ui/index.d.ts +3 -0
  265. package/dist/types/src/ui/index.d.ts.map +1 -0
  266. package/dist/types/src/vite-plugin/boot-loader/BootLoader.stories.d.ts +34 -0
  267. package/dist/types/src/vite-plugin/boot-loader/BootLoader.stories.d.ts.map +1 -0
  268. package/dist/types/src/vite-plugin/boot-loader/index.d.ts +52 -0
  269. package/dist/types/src/vite-plugin/boot-loader/index.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 +37 -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 +25 -6
  284. package/package.json +112 -55
  285. package/src/cli/cli.ts +107 -0
  286. package/src/{components → cli}/index.ts +1 -1
  287. package/src/common/activation-events.ts +44 -0
  288. package/src/common/capabilities.ts +169 -210
  289. package/src/common/index.ts +4 -8
  290. package/src/common/operations.ts +35 -0
  291. package/src/common/translations.ts +18 -10
  292. package/src/context.ts +9 -0
  293. package/src/core/{events.ts → activation-event.ts} +10 -7
  294. package/src/core/capability-manager.test.ts +151 -0
  295. package/src/core/capability-manager.ts +192 -0
  296. package/src/core/capability.ts +247 -0
  297. package/src/core/index.ts +8 -4
  298. package/src/core/plugin-asset-cache.ts +60 -0
  299. package/src/core/plugin-manager.test.ts +1354 -0
  300. package/src/core/plugin-manager.ts +1025 -0
  301. package/src/core/plugin-manifest.test.ts +48 -0
  302. package/src/core/plugin-manifest.ts +102 -0
  303. package/src/core/plugin.ts +365 -45
  304. package/src/core/url-loader.test.ts +178 -0
  305. package/src/core/url-loader.ts +337 -0
  306. package/src/index.ts +3 -4
  307. package/src/plugin-operation/OperationPlugin.ts +24 -0
  308. package/src/plugin-operation/history/capability.ts +36 -0
  309. package/src/plugin-operation/history/errors.ts +7 -0
  310. package/src/plugin-operation/history/history-tracker.test.ts +374 -0
  311. package/src/plugin-operation/history/history-tracker.ts +128 -0
  312. package/src/plugin-operation/history/index.ts +9 -0
  313. package/src/plugin-operation/history/types.ts +17 -0
  314. package/src/plugin-operation/history/undo-mapping.ts +135 -0
  315. package/src/plugin-operation/history/undo-registry.test.ts +72 -0
  316. package/src/plugin-operation/history/undo-registry.ts +54 -0
  317. package/src/plugin-operation/index.ts +6 -0
  318. package/src/plugin-operation/invoker-capability.ts +55 -0
  319. package/src/plugin-operation/meta.ts +11 -0
  320. package/src/plugin-operation/testing.ts +155 -0
  321. package/src/plugin-runtime/RuntimePlugin.ts +19 -0
  322. package/src/plugin-runtime/capability.ts +53 -0
  323. package/src/{playground/layout → plugin-runtime}/index.ts +1 -1
  324. package/src/plugin-runtime/meta.ts +11 -0
  325. package/src/testing/harness.ts +229 -0
  326. package/src/testing/index.ts +2 -0
  327. package/src/testing/react.test.tsx +48 -0
  328. package/src/testing/react.tsx +113 -0
  329. package/src/testing/service.ts +52 -0
  330. package/src/testing/withPluginManager.stories.tsx +8 -9
  331. package/src/testing/withPluginManager.tsx +68 -40
  332. package/src/ui/components/App/App.stories.tsx +92 -0
  333. package/src/ui/components/App/App.tsx +81 -0
  334. package/src/{playground/debug → ui/components/App}/index.ts +1 -1
  335. package/src/ui/components/Placeholder/Placeholder.stories.tsx +77 -0
  336. package/src/ui/components/Placeholder/Placeholder.tsx +155 -0
  337. package/src/{playground/logger → ui/components/Placeholder}/index.ts +1 -1
  338. package/src/ui/components/PluginManager/PluginManagerContext.stories.tsx +185 -0
  339. package/src/{react → ui/components/PluginManager}/PluginManagerProvider.ts +3 -3
  340. package/src/ui/components/PluginManager/index.ts +5 -0
  341. package/src/ui/components/Surface/SurfaceComponent.stories.tsx +144 -0
  342. package/src/ui/components/Surface/SurfaceComponent.tsx +303 -0
  343. package/src/ui/components/Surface/SurfaceInfo.tsx +107 -0
  344. package/src/ui/components/Surface/SurfaceProfilerContext.tsx +207 -0
  345. package/src/ui/components/Surface/context.ts +12 -0
  346. package/src/ui/components/Surface/index.ts +54 -0
  347. package/src/ui/components/Surface/types.test.ts +126 -0
  348. package/src/ui/components/Surface/types.ts +269 -0
  349. package/src/ui/components/index.ts +8 -0
  350. package/src/ui/hooks/index.ts +9 -0
  351. package/src/ui/hooks/useApp.test.tsx +159 -0
  352. package/src/ui/hooks/useApp.tsx +413 -0
  353. package/src/ui/hooks/useCapabilities.ts +67 -0
  354. package/src/{components → ui/hooks}/useLoading.tsx +16 -10
  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 +263 -0
  359. package/src/vite-plugin/boot-loader/boot-loader.css +294 -0
  360. package/src/vite-plugin/boot-loader/boot-loader.js +274 -0
  361. package/src/vite-plugin/boot-loader/index.ts +112 -0
  362. package/src/vite-plugin/composer/index.ts +277 -0
  363. package/src/vite-plugin/import-map/index.ts +524 -0
  364. package/src/vite-plugin/index.ts +10 -0
  365. package/src/vite-plugin/manifest.test.ts +24 -0
  366. package/src/vite-plugin/manifest.ts +50 -0
  367. package/src/vite-plugin/packages.ts +188 -0
  368. package/tsconfig.json +18 -15
  369. package/tsconfig.node.json +2 -4
  370. package/typedoc.json +2 -4
  371. package/vitest.config.ts +1 -1
  372. package/.swc/plugins/linux_x86_64_19.0.0/727453fb3a62f7f1d952a41e051ca8a6f88cadc45cee43c6a4d1aa45f9b75665.wasmer-v7 +0 -0
  373. package/.swc/plugins/linux_x86_64_19.0.0/fce1bdb8e20a094e4af08bad09cc81497ed0e2e7c51223b07d371063cca18429.wasmer-v7 +0 -0
  374. package/dist/lib/browser/app-graph-builder-XH4OYQLC.mjs +0 -137
  375. package/dist/lib/browser/app-graph-builder-XH4OYQLC.mjs.map +0 -7
  376. package/dist/lib/browser/chunk-6V54SRFL.mjs +0 -1638
  377. package/dist/lib/browser/chunk-6V54SRFL.mjs.map +0 -7
  378. package/dist/lib/browser/chunk-RGKMLI6U.mjs +0 -35
  379. package/dist/lib/browser/chunk-RGKMLI6U.mjs.map +0 -7
  380. package/dist/lib/browser/chunk-ZZVFNUHZ.mjs +0 -467
  381. package/dist/lib/browser/chunk-ZZVFNUHZ.mjs.map +0 -7
  382. package/dist/lib/browser/intent-dispatcher-VFMJVO2M.mjs +0 -11
  383. package/dist/lib/browser/intent-resolver-ICAPD4JL.mjs +0 -39
  384. package/dist/lib/browser/intent-resolver-ICAPD4JL.mjs.map +0 -7
  385. package/dist/lib/browser/store-7ZGMHOGB.mjs +0 -30
  386. package/dist/lib/browser/store-7ZGMHOGB.mjs.map +0 -7
  387. package/dist/lib/browser/worker.mjs +0 -77
  388. package/dist/lib/node-esm/app-graph-builder-C7H22SOL.mjs +0 -138
  389. package/dist/lib/node-esm/app-graph-builder-C7H22SOL.mjs.map +0 -7
  390. package/dist/lib/node-esm/chunk-AXSZKZFD.mjs +0 -468
  391. package/dist/lib/node-esm/chunk-AXSZKZFD.mjs.map +0 -7
  392. package/dist/lib/node-esm/chunk-LKPMRTRR.mjs +0 -37
  393. package/dist/lib/node-esm/chunk-LKPMRTRR.mjs.map +0 -7
  394. package/dist/lib/node-esm/chunk-SOVTUUAY.mjs +0 -1640
  395. package/dist/lib/node-esm/chunk-SOVTUUAY.mjs.map +0 -7
  396. package/dist/lib/node-esm/intent-dispatcher-SAPOKSLZ.mjs +0 -12
  397. package/dist/lib/node-esm/intent-resolver-CRNJ6BMD.mjs +0 -40
  398. package/dist/lib/node-esm/intent-resolver-CRNJ6BMD.mjs.map +0 -7
  399. package/dist/lib/node-esm/store-H4F4RMYD.mjs +0 -31
  400. package/dist/lib/node-esm/store-H4F4RMYD.mjs.map +0 -7
  401. package/dist/lib/node-esm/worker.mjs +0 -78
  402. package/dist/types/src/common/collaboration.d.ts +0 -20
  403. package/dist/types/src/common/collaboration.d.ts.map +0 -1
  404. package/dist/types/src/common/events.d.ts +0 -52
  405. package/dist/types/src/common/events.d.ts.map +0 -1
  406. package/dist/types/src/common/file.d.ts +0 -14
  407. package/dist/types/src/common/file.d.ts.map +0 -1
  408. package/dist/types/src/common/graph.d.ts +0 -21
  409. package/dist/types/src/common/graph.d.ts.map +0 -1
  410. package/dist/types/src/common/layout.d.ts +0 -279
  411. package/dist/types/src/common/layout.d.ts.map +0 -1
  412. package/dist/types/src/common/surface.d.ts +0 -59
  413. package/dist/types/src/common/surface.d.ts.map +0 -1
  414. package/dist/types/src/components/App.d.ts +0 -10
  415. package/dist/types/src/components/App.d.ts.map +0 -1
  416. package/dist/types/src/components/App.stories.d.ts.map +0 -1
  417. package/dist/types/src/components/DefaultFallback.d.ts +0 -8
  418. package/dist/types/src/components/DefaultFallback.d.ts.map +0 -1
  419. package/dist/types/src/components/index.d.ts +0 -2
  420. package/dist/types/src/components/index.d.ts.map +0 -1
  421. package/dist/types/src/components/useApp.d.ts +0 -44
  422. package/dist/types/src/components/useApp.d.ts.map +0 -1
  423. package/dist/types/src/components/useLoading.d.ts.map +0 -1
  424. package/dist/types/src/core/capabilities.d.ts +0 -117
  425. package/dist/types/src/core/capabilities.d.ts.map +0 -1
  426. package/dist/types/src/core/capabilities.test.d.ts +0 -2
  427. package/dist/types/src/core/capabilities.test.d.ts.map +0 -1
  428. package/dist/types/src/core/events.d.ts.map +0 -1
  429. package/dist/types/src/core/manager.d.ts +0 -126
  430. package/dist/types/src/core/manager.d.ts.map +0 -1
  431. package/dist/types/src/core/manager.test.d.ts +0 -2
  432. package/dist/types/src/core/manager.test.d.ts.map +0 -1
  433. package/dist/types/src/playground/debug/Debug.d.ts +0 -6
  434. package/dist/types/src/playground/debug/Debug.d.ts.map +0 -1
  435. package/dist/types/src/playground/debug/index.d.ts +0 -2
  436. package/dist/types/src/playground/debug/index.d.ts.map +0 -1
  437. package/dist/types/src/playground/debug/plugin.d.ts +0 -2
  438. package/dist/types/src/playground/debug/plugin.d.ts.map +0 -1
  439. package/dist/types/src/playground/generator/Main.d.ts +0 -6
  440. package/dist/types/src/playground/generator/Main.d.ts.map +0 -1
  441. package/dist/types/src/playground/generator/Toolbar.d.ts +0 -6
  442. package/dist/types/src/playground/generator/Toolbar.d.ts.map +0 -1
  443. package/dist/types/src/playground/generator/generator.d.ts +0 -7
  444. package/dist/types/src/playground/generator/generator.d.ts.map +0 -1
  445. package/dist/types/src/playground/generator/index.d.ts +0 -3
  446. package/dist/types/src/playground/generator/index.d.ts.map +0 -1
  447. package/dist/types/src/playground/generator/plugin.d.ts +0 -2
  448. package/dist/types/src/playground/generator/plugin.d.ts.map +0 -1
  449. package/dist/types/src/playground/layout/Layout.d.ts +0 -8
  450. package/dist/types/src/playground/layout/Layout.d.ts.map +0 -1
  451. package/dist/types/src/playground/layout/index.d.ts +0 -2
  452. package/dist/types/src/playground/layout/index.d.ts.map +0 -1
  453. package/dist/types/src/playground/layout/plugin.d.ts +0 -2
  454. package/dist/types/src/playground/layout/plugin.d.ts.map +0 -1
  455. package/dist/types/src/playground/logger/Toolbar.d.ts +0 -6
  456. package/dist/types/src/playground/logger/Toolbar.d.ts.map +0 -1
  457. package/dist/types/src/playground/logger/index.d.ts +0 -2
  458. package/dist/types/src/playground/logger/index.d.ts.map +0 -1
  459. package/dist/types/src/playground/logger/plugin.d.ts +0 -2
  460. package/dist/types/src/playground/logger/plugin.d.ts.map +0 -1
  461. package/dist/types/src/playground/logger/schema.d.ts +0 -13
  462. package/dist/types/src/playground/logger/schema.d.ts.map +0 -1
  463. package/dist/types/src/playground/playground.stories.d.ts.map +0 -1
  464. package/dist/types/src/plugin-intent/IntentPlugin.d.ts +0 -2
  465. package/dist/types/src/plugin-intent/IntentPlugin.d.ts.map +0 -1
  466. package/dist/types/src/plugin-intent/actions.d.ts +0 -36
  467. package/dist/types/src/plugin-intent/actions.d.ts.map +0 -1
  468. package/dist/types/src/plugin-intent/errors.d.ts +0 -16
  469. package/dist/types/src/plugin-intent/errors.d.ts.map +0 -1
  470. package/dist/types/src/plugin-intent/index.d.ts +0 -6
  471. package/dist/types/src/plugin-intent/index.d.ts.map +0 -1
  472. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts +0 -139
  473. package/dist/types/src/plugin-intent/intent-dispatcher.d.ts.map +0 -1
  474. package/dist/types/src/plugin-intent/intent-dispatcher.test.d.ts +0 -2
  475. package/dist/types/src/plugin-intent/intent-dispatcher.test.d.ts.map +0 -1
  476. package/dist/types/src/plugin-intent/intent.d.ts +0 -63
  477. package/dist/types/src/plugin-intent/intent.d.ts.map +0 -1
  478. package/dist/types/src/plugin-intent/meta.d.ts +0 -3
  479. package/dist/types/src/plugin-intent/meta.d.ts.map +0 -1
  480. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts +0 -2
  481. package/dist/types/src/plugin-settings/SettingsPlugin.d.ts.map +0 -1
  482. package/dist/types/src/plugin-settings/actions.d.ts +0 -25
  483. package/dist/types/src/plugin-settings/actions.d.ts.map +0 -1
  484. package/dist/types/src/plugin-settings/app-graph-builder.d.ts +0 -4
  485. package/dist/types/src/plugin-settings/app-graph-builder.d.ts.map +0 -1
  486. package/dist/types/src/plugin-settings/index.d.ts +0 -3
  487. package/dist/types/src/plugin-settings/index.d.ts.map +0 -1
  488. package/dist/types/src/plugin-settings/intent-resolver.d.ts +0 -4
  489. package/dist/types/src/plugin-settings/intent-resolver.d.ts.map +0 -1
  490. package/dist/types/src/plugin-settings/meta.d.ts +0 -3
  491. package/dist/types/src/plugin-settings/meta.d.ts.map +0 -1
  492. package/dist/types/src/plugin-settings/store.d.ts +0 -5
  493. package/dist/types/src/plugin-settings/store.d.ts.map +0 -1
  494. package/dist/types/src/plugin-settings/translations.d.ts +0 -11
  495. package/dist/types/src/plugin-settings/translations.d.ts.map +0 -1
  496. package/dist/types/src/react/ErrorBoundary.d.ts +0 -30
  497. package/dist/types/src/react/ErrorBoundary.d.ts.map +0 -1
  498. package/dist/types/src/react/IntentContext.d.ts +0 -8
  499. package/dist/types/src/react/IntentContext.d.ts.map +0 -1
  500. package/dist/types/src/react/PluginManagerProvider.d.ts +0 -10
  501. package/dist/types/src/react/PluginManagerProvider.d.ts.map +0 -1
  502. package/dist/types/src/react/Surface.d.ts +0 -12
  503. package/dist/types/src/react/Surface.d.ts.map +0 -1
  504. package/dist/types/src/react/Surface.stories.d.ts +0 -17
  505. package/dist/types/src/react/Surface.stories.d.ts.map +0 -1
  506. package/dist/types/src/react/common.d.ts +0 -13
  507. package/dist/types/src/react/common.d.ts.map +0 -1
  508. package/dist/types/src/react/index.d.ts +0 -7
  509. package/dist/types/src/react/index.d.ts.map +0 -1
  510. package/dist/types/src/react/useCapabilities.d.ts +0 -13
  511. package/dist/types/src/react/useCapabilities.d.ts.map +0 -1
  512. package/dist/types/src/react/useIntentResolver.d.ts +0 -3
  513. package/dist/types/src/react/useIntentResolver.d.ts.map +0 -1
  514. package/dist/types/src/worker.d.ts +0 -4
  515. package/dist/types/src/worker.d.ts.map +0 -1
  516. package/src/common/collaboration.ts +0 -18
  517. package/src/common/events.ts +0 -79
  518. package/src/common/file.ts +0 -22
  519. package/src/common/graph.ts +0 -30
  520. package/src/common/layout.ts +0 -277
  521. package/src/common/surface.ts +0 -83
  522. package/src/components/App.stories.tsx +0 -33
  523. package/src/components/App.tsx +0 -59
  524. package/src/components/DefaultFallback.tsx +0 -26
  525. package/src/components/useApp.tsx +0 -164
  526. package/src/core/capabilities.test.ts +0 -136
  527. package/src/core/capabilities.ts +0 -259
  528. package/src/core/manager.test.ts +0 -516
  529. package/src/core/manager.ts +0 -597
  530. package/src/playground/debug/Debug.tsx +0 -39
  531. package/src/playground/debug/plugin.ts +0 -16
  532. package/src/playground/generator/Main.tsx +0 -71
  533. package/src/playground/generator/Toolbar.tsx +0 -47
  534. package/src/playground/generator/generator.ts +0 -48
  535. package/src/playground/generator/index.ts +0 -6
  536. package/src/playground/generator/plugin.ts +0 -22
  537. package/src/playground/layout/Layout.tsx +0 -33
  538. package/src/playground/layout/plugin.ts +0 -18
  539. package/src/playground/logger/Toolbar.tsx +0 -30
  540. package/src/playground/logger/plugin.ts +0 -41
  541. package/src/playground/logger/schema.ts +0 -12
  542. package/src/playground/playground.stories.tsx +0 -46
  543. package/src/plugin-intent/IntentPlugin.ts +0 -20
  544. package/src/plugin-intent/actions.ts +0 -31
  545. package/src/plugin-intent/errors.ts +0 -40
  546. package/src/plugin-intent/index.ts +0 -9
  547. package/src/plugin-intent/intent-dispatcher.test.ts +0 -279
  548. package/src/plugin-intent/intent-dispatcher.ts +0 -334
  549. package/src/plugin-intent/intent.ts +0 -154
  550. package/src/plugin-intent/meta.ts +0 -10
  551. package/src/plugin-settings/SettingsPlugin.ts +0 -34
  552. package/src/plugin-settings/actions.ts +0 -25
  553. package/src/plugin-settings/app-graph-builder.ts +0 -159
  554. package/src/plugin-settings/index.ts +0 -6
  555. package/src/plugin-settings/intent-resolver.ts +0 -35
  556. package/src/plugin-settings/meta.ts +0 -10
  557. package/src/plugin-settings/store.ts +0 -33
  558. package/src/plugin-settings/translations.ts +0 -19
  559. package/src/react/ErrorBoundary.tsx +0 -54
  560. package/src/react/IntentContext.tsx +0 -35
  561. package/src/react/Surface.stories.tsx +0 -101
  562. package/src/react/Surface.tsx +0 -86
  563. package/src/react/common.ts +0 -13
  564. package/src/react/index.ts +0 -10
  565. package/src/react/useCapabilities.ts +0 -31
  566. package/src/react/useIntentResolver.ts +0 -22
  567. package/src/worker.ts +0 -11
  568. /package/dist/lib/browser/{intent-dispatcher-VFMJVO2M.mjs.map → chunk-G7SDBRKH.mjs.map} +0 -0
  569. /package/dist/lib/browser/{worker.mjs.map → chunk-J5LGTIGS.mjs.map} +0 -0
  570. /package/dist/lib/{node-esm/intent-dispatcher-SAPOKSLZ.mjs.map → browser/common/activation-events.mjs.map} +0 -0
  571. /package/dist/lib/{node-esm/worker.mjs.map → browser/common/capabilities.mjs.map} +0 -0
@@ -0,0 +1,48 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import React from 'react';
7
+ import { describe, test } from 'vitest';
8
+
9
+ import { ActivationEvents, Capabilities } from '../common';
10
+ import { Capability, Plugin } from '../core';
11
+ import { Surface } from '../ui';
12
+ import { createTestApp } from './harness';
13
+ import { render, renderSurface } from './react';
14
+
15
+ const testMeta = { id: 'org.dxos.plugin.test.react-harness', name: 'ReactHarnessTest' };
16
+
17
+ const TestPlugin = Plugin.define(testMeta).pipe(
18
+ Plugin.addModule({
19
+ id: 'surfaces',
20
+ activatesOn: ActivationEvents.SetupReactSurface,
21
+ activate: () =>
22
+ Effect.succeed(
23
+ Capability.contributes(Capabilities.ReactSurface, [
24
+ Surface.create<{ message: string }>({
25
+ id: 'greeting',
26
+ role: 'greeting',
27
+ component: ({ data }) => <span data-testid='greeting'>hello {data.message}</span>,
28
+ }),
29
+ ]),
30
+ ),
31
+ }),
32
+ Plugin.make,
33
+ );
34
+
35
+ describe('testing/react', () => {
36
+ test('render wraps ui in the harness provider tree', async ({ expect }) => {
37
+ await using harness = await createTestApp({ plugins: [TestPlugin()] });
38
+ const view = render(harness, <span data-testid='hello'>world</span>);
39
+ expect(view.getByTestId('hello').textContent).toBe('world');
40
+ });
41
+
42
+ test('renderSurface mounts a surface registered by a plugin', async ({ expect }) => {
43
+ await using harness = await createTestApp({ plugins: [TestPlugin()] });
44
+ const view = renderSurface(harness, { role: 'greeting', data: { message: 'plugins' } });
45
+ const node = await view.findByTestId('greeting');
46
+ expect(node.textContent).toBe('hello plugins');
47
+ });
48
+ });
@@ -0,0 +1,113 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { RegistryContext } from '@effect-atom/atom-react';
6
+ import { render as rtlRender, type RenderOptions, type RenderResult } from '@testing-library/react';
7
+ import React, { type FC, Fragment, type PropsWithChildren, type ReactNode } from 'react';
8
+
9
+ import { ContextProtocolProvider } from '@dxos/web-context-react';
10
+
11
+ import { Capabilities } from '../common';
12
+ import { PluginManagerContext } from '../context';
13
+ import { topologicalSort } from '../helpers';
14
+ import { PluginManagerProvider } from '../ui/components/PluginManager/PluginManagerProvider';
15
+ import { SurfaceComponent } from '../ui/components/Surface/SurfaceComponent';
16
+ import { type TestHarness } from './harness';
17
+
18
+ export type HarnessRenderOptions = Omit<RenderOptions, 'wrapper'> & {
19
+ /** Additional providers to wrap around the harness tree (applied innermost first). */
20
+ reactContexts?: FC<PropsWithChildren>[];
21
+ };
22
+
23
+ /**
24
+ * Renders `ui` wrapped in the same provider tree as `useApp` plus every contributed
25
+ * `Capabilities.ReactContext`.
26
+ */
27
+ export const render = (harness: TestHarness, ui: ReactNode, options?: HarnessRenderOptions): RenderResult => {
28
+ const { reactContexts = [], ...rest } = options ?? {};
29
+ const Wrapper = ({ children }: PropsWithChildren) => (
30
+ <HarnessProviders harness={harness} extra={reactContexts}>
31
+ {children}
32
+ </HarnessProviders>
33
+ );
34
+ return rtlRender(<>{ui}</>, { ...rest, wrapper: Wrapper });
35
+ };
36
+
37
+ export type RenderSurfaceProps = {
38
+ role: string;
39
+ data?: unknown;
40
+ limit?: number;
41
+ fallback?: FC<{ error: Error; data?: any }>;
42
+ placeholder?: ReactNode;
43
+ };
44
+
45
+ /**
46
+ * Renders a `Surface` with the given role/data inside the harness provider tree.
47
+ */
48
+ export const renderSurface = (
49
+ harness: TestHarness,
50
+ props: RenderSurfaceProps,
51
+ options?: HarnessRenderOptions,
52
+ ): RenderResult => {
53
+ const { role, data, limit, fallback, placeholder } = props;
54
+ return render(
55
+ harness,
56
+ <SurfaceComponent role={role} data={data as any} limit={limit} fallback={fallback} placeholder={placeholder} />,
57
+ options,
58
+ );
59
+ };
60
+
61
+ type HarnessProvidersProps = PropsWithChildren<{
62
+ harness: TestHarness;
63
+ extra: FC<PropsWithChildren>[];
64
+ }>;
65
+
66
+ const HarnessProviders = ({ harness, extra, children }: HarnessProvidersProps) => {
67
+ const contributed = harness.getAll(Capabilities.ReactContext);
68
+ const ContributedContext = composeContexts(contributed);
69
+ const ExtraContext = composeExtra(extra);
70
+ return (
71
+ <PluginManagerProvider value={harness.manager}>
72
+ <ContextProtocolProvider value={harness.manager} context={PluginManagerContext}>
73
+ <RegistryContext.Provider value={harness.registry}>
74
+ <ContributedContext>
75
+ <ExtraContext>{children}</ExtraContext>
76
+ </ContributedContext>
77
+ </RegistryContext.Provider>
78
+ </ContextProtocolProvider>
79
+ </PluginManagerProvider>
80
+ );
81
+ };
82
+
83
+ const composeContexts = (contexts: Capabilities.ReactContext[]): FC<PropsWithChildren> => {
84
+ if (contexts.length === 0) {
85
+ return Passthrough;
86
+ }
87
+ return topologicalSort(contexts)
88
+ .map(({ context }) => context)
89
+ .reduce((Acc, Next) => ({ children }: PropsWithChildren) => (
90
+ <Acc>
91
+ <Next>{children}</Next>
92
+ </Acc>
93
+ ));
94
+ };
95
+
96
+ // Composes in innermost-first order: the first context in the array wraps
97
+ // `children` directly; subsequent contexts wrap the accumulator.
98
+ const composeExtra = (contexts: FC<PropsWithChildren>[]): FC<PropsWithChildren> => {
99
+ if (contexts.length === 0) {
100
+ return Passthrough;
101
+ }
102
+ return contexts.reduce<FC<PropsWithChildren>>(
103
+ (Acc, Next) =>
104
+ ({ children }: PropsWithChildren) => (
105
+ <Next>
106
+ <Acc>{children}</Acc>
107
+ </Next>
108
+ ),
109
+ Passthrough,
110
+ );
111
+ };
112
+
113
+ const Passthrough: FC<PropsWithChildren> = ({ children }) => <Fragment>{children}</Fragment>;
@@ -0,0 +1,52 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Layer from 'effect/Layer';
7
+
8
+ import { invariant } from '@dxos/invariant';
9
+
10
+ import { ActivationEvents, Capabilities } from '../common';
11
+ import { Plugin, PluginManager } from '../core';
12
+
13
+ /**
14
+ * Creates a Plugin.Service layer from a list of plugins.
15
+ * This is primarily used for testing.
16
+ */
17
+ export const fromPlugins = (plugins: Plugin.Plugin[]) =>
18
+ Layer.effect(
19
+ Plugin.Service,
20
+ Effect.gen(function* () {
21
+ // TODO(wittjosiah): Try to dedupe logic between here, createCliApp and useApp.
22
+
23
+ const pluginLoader = (id: string) =>
24
+ Effect.sync(() => {
25
+ const plugin = plugins.find((plugin) => plugin.meta.id === id);
26
+ invariant(plugin, `Plugin not found: ${id}`);
27
+ return plugin;
28
+ });
29
+
30
+ const manager = PluginManager.make({
31
+ pluginLoader,
32
+ plugins,
33
+ core: plugins.map((plugin) => plugin.meta.id),
34
+ });
35
+
36
+ manager.capabilities.contribute({
37
+ interface: Capabilities.PluginManager,
38
+ implementation: manager,
39
+ module: 'org.dxos.app-framework.plugin-manager',
40
+ });
41
+
42
+ manager.capabilities.contribute({
43
+ interface: Capabilities.AtomRegistry,
44
+ implementation: manager.registry,
45
+ module: 'org.dxos.app-framework.atom-registry',
46
+ });
47
+
48
+ yield* manager.activate(ActivationEvents.Startup);
49
+
50
+ return manager;
51
+ }),
52
+ );
@@ -7,10 +7,9 @@ import React from 'react';
7
7
 
8
8
  import { withTheme } from '@dxos/react-ui/testing';
9
9
 
10
- import { Capabilities, createSurface } from '../common';
11
- import { contributes } from '../core';
12
- import { Surface } from '../react';
13
-
10
+ import { Capabilities } from '../common';
11
+ import { Capability } from '../core';
12
+ import { Surface } from '../ui';
14
13
  import { withPluginManager } from './withPluginManager';
15
14
 
16
15
  const DefaultStory = () => {
@@ -18,21 +17,21 @@ const DefaultStory = () => {
18
17
  return (
19
18
  <div>
20
19
  <div>Hello</div>
21
- <Surface role='main' />
20
+ <Surface.Surface role='main' />
22
21
  </div>
23
22
  );
24
23
  };
25
24
 
26
25
  const meta = {
27
- title: 'sdk/app-framework/withPluginManager',
26
+ title: 'sdk/app-framework/testing/withPluginManager',
28
27
  render: DefaultStory,
29
28
  decorators: [
30
- withTheme,
29
+ withTheme(),
31
30
  withPluginManager({
32
31
  capabilities: [
33
- contributes(
32
+ Capability.contributes(
34
33
  Capabilities.ReactSurface,
35
- createSurface({
34
+ Surface.create({
36
35
  id: 'test',
37
36
  role: 'main',
38
37
  component: ({ role }) => <span>{JSON.stringify({ role })}</span>,
@@ -2,24 +2,18 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { type Decorator } from '@storybook/react';
6
- import React, { useEffect, useMemo } from 'react';
5
+ import { type Decorator, type StoryContext } from '@storybook/react';
6
+ import * as Effect from 'effect/Effect';
7
+ import React, { useEffect, useState } from 'react';
7
8
 
8
9
  import { raise } from '@dxos/debug';
10
+ import { runAndForwardErrors } from '@dxos/effect';
9
11
  import { useAsyncEffect } from '@dxos/react-hooks';
10
12
  import { type MaybeProvider, getProviderValue } from '@dxos/util';
11
13
 
12
- import { Capabilities, Events } from '../common';
13
- import { type UseAppOptions, useApp } from '../components';
14
- import {
15
- type ActivationEvent,
16
- type AnyCapability,
17
- type PluginContext,
18
- PluginManager,
19
- contributes,
20
- defineModule,
21
- definePlugin,
22
- } from '../core';
14
+ import { ActivationEvents, Capabilities } from '../common';
15
+ import { type ActivationEvent, Capability, type CapabilityManager, Plugin, PluginManager } from '../core';
16
+ import { type UseAppOptions, useApp } from '../ui';
23
17
 
24
18
  /**
25
19
  * @internal
@@ -30,16 +24,16 @@ export const setupPluginManager = ({
30
24
  core = plugins.map(({ meta }) => meta.id),
31
25
  ...options
32
26
  }: UseAppOptions & Pick<WithPluginManagerOptions, 'capabilities'> = {}) => {
33
- const pluginManager = new PluginManager({
27
+ const pluginManager = PluginManager.make({
34
28
  pluginLoader: () => raise(new Error('Not implemented')),
35
- plugins: [StoryPlugin(), ...plugins],
29
+ plugins: [StoryPlugin, ...plugins],
36
30
  core: [StoryPlugin.meta.id, ...core],
37
31
  ...options,
38
32
  });
39
33
 
40
34
  if (capabilities) {
41
- getProviderValue(capabilities, pluginManager.context).forEach((capability) => {
42
- pluginManager.context.contributeCapability({
35
+ getProviderValue(capabilities, pluginManager.capabilities).forEach((capability) => {
36
+ pluginManager.capabilities.contribute({
43
37
  interface: capability.interface,
44
38
  implementation: capability.implementation,
45
39
  module: 'story',
@@ -50,57 +44,91 @@ export const setupPluginManager = ({
50
44
  return pluginManager;
51
45
  };
52
46
 
47
+ type ManagedPluginManagerState = {
48
+ fireEvents?: (ActivationEvent.ActivationEvent | string)[];
49
+ pluginManager: PluginManager.PluginManager;
50
+ setupEvents?: ActivationEvent.ActivationEvent[];
51
+ storyId: string;
52
+ };
53
+
53
54
  export type WithPluginManagerOptions = UseAppOptions & {
54
55
  /** @deprecated */
55
- capabilities?: MaybeProvider<AnyCapability[], PluginContext>;
56
+ capabilities?: MaybeProvider<Capability.Any[], CapabilityManager.CapabilityManager>;
56
57
  /** @deprecated */
57
- fireEvents?: (ActivationEvent | string)[];
58
+ fireEvents?: (ActivationEvent.ActivationEvent | string)[];
58
59
  };
59
60
 
61
+ export type WithPluginManagerInitializer<Args = void> =
62
+ | WithPluginManagerOptions
63
+ | ((context: StoryContext<Args>) => WithPluginManagerOptions);
64
+
60
65
  /**
61
66
  * Wraps a story with a plugin manager.
62
67
  * NOTE: This builds up and tears down the plugin manager on every render.
63
68
  */
64
- export const withPluginManager = (options: WithPluginManagerOptions = {}): Decorator => {
69
+ export const withPluginManager = <Args,>(init: WithPluginManagerInitializer<Args> = {}): Decorator => {
65
70
  return (Story, context) => {
66
- const pluginManager = useMemo(() => setupPluginManager(options), [options]);
71
+ const storyId = context.id;
72
+ const options = typeof init === 'function' ? init(context as any) : init;
73
+ const [managerState, setManagerState] = useState<ManagedPluginManagerState>();
67
74
 
68
- // Set-up root capability.
75
+ // Storybook replaces the full context object often, so key manager ownership by story id.
69
76
  useEffect(() => {
70
- const capability = contributes(Capabilities.ReactRoot, {
71
- id: context.id,
77
+ const pluginManager = setupPluginManager(options);
78
+ const capability = Capability.contributes(Capabilities.ReactRoot, {
79
+ id: storyId,
72
80
  root: () => <Story />,
73
81
  });
74
82
 
75
- pluginManager.context.contributeCapability({
83
+ pluginManager.capabilities.contribute({
76
84
  ...capability,
77
- module: 'dxos.org/app-framework/withPluginManager',
85
+ module: 'org.dxos.app-framework.with-plugin-manager',
86
+ });
87
+
88
+ setManagerState({
89
+ pluginManager,
90
+ setupEvents: options.setupEvents,
91
+ fireEvents: options.fireEvents,
92
+ storyId,
78
93
  });
79
94
 
80
95
  return () => {
81
- pluginManager.context.removeCapability(capability.interface, capability.implementation);
96
+ pluginManager.capabilities.remove(capability.interface, capability.implementation);
97
+ void runAndForwardErrors(pluginManager.shutdown());
82
98
  };
83
- }, [pluginManager, context]);
99
+ }, [storyId, init]);
84
100
 
85
- // Fire events.
86
- useAsyncEffect(async () => {
87
- await Promise.all(options.fireEvents?.map((event) => pluginManager.activate(event)) ?? []);
88
- }, [pluginManager]);
101
+ // Avoid mounting useApp with a stale manager from the previous story.
102
+ if (!managerState || managerState.storyId !== storyId) {
103
+ return <></>;
104
+ }
89
105
 
90
- // Create app.
91
- const App = useApp({ pluginManager });
92
-
93
- return <App />;
106
+ return <WithPluginManagerApp {...managerState} />;
94
107
  };
95
108
  };
96
109
 
110
+ const WithPluginManagerApp = ({ fireEvents, pluginManager, setupEvents, storyId }: ManagedPluginManagerState) => {
111
+ // Fire deprecated events only after the effect-owned manager for this story exists.
112
+ useAsyncEffect(async () => {
113
+ await Promise.all(fireEvents?.map((event) => pluginManager.activate(event)) ?? []);
114
+ }, [fireEvents, pluginManager, storyId]);
115
+
116
+ const App = useApp({ pluginManager, setupEvents });
117
+ return <App />;
118
+ };
119
+
97
120
  const storyMeta = {
98
- id: 'dxos.org/app-framework/story',
121
+ id: 'org.dxos.app-framework.story',
99
122
  name: 'Story',
100
123
  };
101
124
 
102
125
  // No-op plugin to ensure there exists at least one plugin for the startup event.
103
126
  // This is necessary because `createApp` expects the startup event to complete before the app is ready.
104
- const StoryPlugin = definePlugin(storyMeta, () => [
105
- defineModule({ id: storyMeta.id, activatesOn: Events.Startup, activate: () => [] }),
106
- ]);
127
+ const StoryPlugin = Plugin.define(storyMeta).pipe(
128
+ Plugin.addModule({
129
+ id: 'Story',
130
+ activatesOn: ActivationEvents.Startup,
131
+ activate: () => Effect.succeed([]),
132
+ }),
133
+ Plugin.make,
134
+ )();
@@ -0,0 +1,92 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import * as Effect from 'effect/Effect';
7
+ import React, { useEffect } from 'react';
8
+
9
+ import { withTheme } from '@dxos/react-ui/testing';
10
+
11
+ import { ActivationEvents, Capabilities } from '../../../common';
12
+ import { Capability, Plugin } from '../../../core';
13
+ import { useApp } from '../../hooks';
14
+
15
+ // Minimal plugin that contributes a ReactRoot.
16
+ const TestPlugin = Plugin.define<{ error?: boolean }>({
17
+ id: 'org.dxos.plugin.test',
18
+ name: 'Test Plugin',
19
+ }).pipe(
20
+ Plugin.addModule(({ error }) => ({
21
+ id: 'TestMain',
22
+ activatesOn: ActivationEvents.Startup,
23
+ activate: () =>
24
+ Effect.succeed([
25
+ Capability.contributes(Capabilities.ReactRoot, {
26
+ id: 'org.dxos.plugin.test.root',
27
+ root: () => {
28
+ useEffect(() => {
29
+ let t: NodeJS.Timeout;
30
+ if (error) {
31
+ console.log('Ticking...');
32
+ t = setTimeout(() => {
33
+ console.log('Bang!');
34
+ throw new Error('Runtime error');
35
+ }, 3_000);
36
+ }
37
+
38
+ return () => clearTimeout(t);
39
+ }, [error]);
40
+
41
+ return <h1 className='text-lg'>App Started</h1>;
42
+ },
43
+ }),
44
+ ]),
45
+ })),
46
+ Plugin.make,
47
+ );
48
+
49
+ const core = [TestPlugin.meta.id];
50
+
51
+ type DefaultStoryProps = { plugins?: Plugin.Plugin[] };
52
+
53
+ const DefaultStory = ({ plugins }: DefaultStoryProps) => {
54
+ const App = useApp({
55
+ plugins,
56
+ core,
57
+ placeholder: () => {
58
+ return (
59
+ <div role='none' className='text-description'>
60
+ Loading...
61
+ </div>
62
+ );
63
+ },
64
+ });
65
+
66
+ return <App />;
67
+ };
68
+
69
+ const meta = {
70
+ title: 'sdk/app-framework/components/App',
71
+ render: DefaultStory,
72
+ decorators: [withTheme()],
73
+ parameters: {
74
+ layout: 'centered',
75
+ },
76
+ } satisfies Meta;
77
+
78
+ export default meta;
79
+
80
+ type Story = StoryObj<typeof meta>;
81
+
82
+ export const Default: Story = {
83
+ args: {
84
+ plugins: [TestPlugin({})],
85
+ },
86
+ };
87
+
88
+ export const WithError: Story = {
89
+ args: {
90
+ plugins: [TestPlugin({ error: true })],
91
+ },
92
+ };
@@ -0,0 +1,81 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React, { type PropsWithChildren, useEffect } from 'react';
6
+
7
+ import { Capabilities } from '../../../common';
8
+ import { topologicalSort } from '../../../helpers';
9
+ import { LoadingState, type StartupProgress, type UseAppOptions, useCapabilities, useLoading } from '../../hooks';
10
+
11
+ export type AppProps = Pick<UseAppOptions, 'placeholder' | 'debounce'> & {
12
+ ready: boolean;
13
+ error: unknown;
14
+ progress?: StartupProgress;
15
+ };
16
+
17
+ const FIRST_INTERACTIVE_MARK = 'app-framework:first-interactive';
18
+
19
+ export const App = ({ placeholder: Placeholder, ready, error, debounce, progress }: AppProps) => {
20
+ const reactContexts = useCapabilities(Capabilities.ReactContext);
21
+ const reactRoots = useCapabilities(Capabilities.ReactRoot);
22
+ const stage = useLoading(ready, debounce);
23
+ const placeholderDismissed = stage >= LoadingState.Done;
24
+
25
+ // Emit a once-per-app `app-framework:first-interactive` mark the first time
26
+ // the placeholder is dismissed and the real app shell renders. Closes the
27
+ // gap between `Startup` activated and the first interactive paint.
28
+ //
29
+ // Also dismisses the native-DOM boot loader from
30
+ // `@dxos/app-framework/vite-plugin` here — the framework owns the
31
+ // handoff-complete signal, so dismissing in `App` covers both hosts that
32
+ // wire in a `Placeholder` (which may have its own dismiss path) and hosts
33
+ // that don't (the loader would otherwise sit forever as a `z-index: 10`
34
+ // overlay covering the rendered shell).
35
+ useEffect(() => {
36
+ if (!placeholderDismissed) {
37
+ return;
38
+ }
39
+ if (performance.getEntriesByName(FIRST_INTERACTIVE_MARK).length === 0) {
40
+ performance.mark(FIRST_INTERACTIVE_MARK);
41
+ }
42
+ (window as { __bootLoader?: { dismiss?: () => void } }).__bootLoader?.dismiss?.();
43
+ }, [placeholderDismissed]);
44
+
45
+ if (error) {
46
+ // This triggers the error boundary to provide UI feedback for the startup error.
47
+ throw error;
48
+ }
49
+
50
+ // TODO(wittjosiah): Consider using Suspense instead.
51
+ if (!placeholderDismissed) {
52
+ if (!Placeholder) {
53
+ return null;
54
+ }
55
+
56
+ return <Placeholder stage={stage} progress={progress} />;
57
+ }
58
+
59
+ const ComposedContext = composeContexts(reactContexts);
60
+ return (
61
+ <ComposedContext>
62
+ {reactRoots.map(({ id, root: Component }) => (
63
+ <Component key={id} />
64
+ ))}
65
+ </ComposedContext>
66
+ );
67
+ };
68
+
69
+ const composeContexts = (contexts: Capabilities.ReactContext[]) => {
70
+ if (contexts.length === 0) {
71
+ return ({ children }: PropsWithChildren) => <>{children}</>;
72
+ }
73
+
74
+ return topologicalSort(contexts)
75
+ .map(({ context }) => context)
76
+ .reduce((Acc, Next) => ({ children }) => (
77
+ <Acc>
78
+ <Next>{children}</Next>
79
+ </Acc>
80
+ ));
81
+ };
@@ -2,4 +2,4 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export * from './plugin';
5
+ export * from './App';
@@ -0,0 +1,77 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React, { useEffect, useState } from 'react';
7
+ import { expect, within } from 'storybook/test';
8
+
9
+ import { Composer } from '@dxos/brand';
10
+ import { Input, Panel, Toolbar } from '@dxos/react-ui';
11
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
12
+
13
+ import { Placeholder } from './Placeholder';
14
+
15
+ /**
16
+ * The story renders the brand-agnostic `Placeholder` from `@dxos/app-framework/ui`
17
+ * with the Composer brand icon as its `logo`, so the storybook mirrors what
18
+ * composer-app actually mounts in production. The render function form lets
19
+ * the SVG accept the placeholder's animation `className` directly.
20
+ */
21
+ const meta = {
22
+ title: 'sdk/app-framework/components/Placeholder',
23
+ component: Placeholder,
24
+ render: () => {
25
+ const [stage, setStage] = useState(0);
26
+ const [auto, setAuto] = useState(false);
27
+ useEffect(() => {
28
+ if (!auto) {
29
+ return;
30
+ }
31
+
32
+ const interval = setInterval(() => {
33
+ setStage((prev) => {
34
+ return prev >= 2 ? 0 : prev + 1;
35
+ });
36
+ }, 3_000);
37
+
38
+ return () => clearInterval(interval);
39
+ }, [auto]);
40
+
41
+ return (
42
+ <Panel.Root>
43
+ <Panel.Toolbar asChild>
44
+ <Toolbar.Root classNames='gap-2'>
45
+ <Input.Root>
46
+ <Input.Checkbox checked={auto} onCheckedChange={(checked) => setAuto(checked === true)} />
47
+ <Input.Label>Auto</Input.Label>
48
+ </Input.Root>
49
+ <Toolbar.Button onClick={() => setStage((prev) => (prev < 2 ? prev + 1 : 0))}>Next</Toolbar.Button>
50
+ <Toolbar.Text>{stage}</Toolbar.Text>
51
+ </Toolbar.Root>
52
+ </Panel.Toolbar>
53
+ <Panel.Content>
54
+ <Placeholder stage={stage} logo={(logoProps) => <Composer {...logoProps} />} />
55
+ </Panel.Content>
56
+ </Panel.Root>
57
+ );
58
+ },
59
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
60
+ tags: ['test'],
61
+ } satisfies Meta<typeof Placeholder>;
62
+
63
+ export default meta;
64
+
65
+ type Story = StoryObj<typeof meta>;
66
+
67
+ export const Default: Story = {
68
+ args: {
69
+ stage: 0,
70
+ },
71
+ play: async ({ canvasElement }) => {
72
+ const canvas = within(canvasElement);
73
+ // Smoke test: the toolbar's `Next` button is rendered alongside the
74
+ // placeholder, so the story mounted without throwing.
75
+ await expect(canvas.getByRole('button', { name: 'Next' })).toBeInTheDocument();
76
+ },
77
+ };