@dxos/app-framework 0.8.1-main.ba2dec9 → 0.8.1-staging.5be625a

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 (76) hide show
  1. package/dist/lib/browser/{app-graph-builder-IAEV7KKF.mjs → app-graph-builder-OD3G2J2U.mjs} +2 -2
  2. package/dist/lib/browser/{chunk-PWAAJE2Z.mjs → chunk-CESGLKOM.mjs} +4 -3
  3. package/dist/lib/browser/{chunk-PWAAJE2Z.mjs.map → chunk-CESGLKOM.mjs.map} +3 -3
  4. package/dist/lib/browser/{chunk-CIP4C47B.mjs → chunk-KP6FVIAA.mjs} +7 -6
  5. package/dist/lib/browser/chunk-KP6FVIAA.mjs.map +7 -0
  6. package/dist/lib/browser/index.mjs +7 -6
  7. package/dist/lib/browser/index.mjs.map +3 -3
  8. package/dist/lib/browser/{intent-dispatcher-UR566RVO.mjs → intent-dispatcher-RTXTATZJ.mjs} +2 -2
  9. package/dist/lib/browser/{intent-resolver-LEJ3X6CP.mjs → intent-resolver-ZL6WBF2L.mjs} +2 -2
  10. package/dist/lib/browser/meta.json +1 -1
  11. package/dist/lib/browser/{store-5TN4OLFQ.mjs → store-JIKLP4JL.mjs} +2 -2
  12. package/dist/lib/browser/testing/index.mjs +4 -3
  13. package/dist/lib/browser/testing/index.mjs.map +3 -3
  14. package/dist/lib/browser/worker.mjs +1 -1
  15. package/dist/lib/node/{app-graph-builder-3RWOZENP.cjs → app-graph-builder-S3ER53EH.cjs} +12 -12
  16. package/dist/lib/node/{chunk-JLQABYHB.cjs → chunk-4YBMWZR3.cjs} +23 -22
  17. package/dist/lib/node/chunk-4YBMWZR3.cjs.map +7 -0
  18. package/dist/lib/node/{chunk-XP4TI5DS.cjs → chunk-KRK7EH6Z.cjs} +7 -6
  19. package/dist/lib/node/{chunk-XP4TI5DS.cjs.map → chunk-KRK7EH6Z.cjs.map} +2 -2
  20. package/dist/lib/node/index.cjs +68 -67
  21. package/dist/lib/node/index.cjs.map +3 -3
  22. package/dist/lib/node/{intent-dispatcher-EDW7NFJ4.cjs → intent-dispatcher-TBTSYYGJ.cjs} +8 -8
  23. package/dist/lib/node/{intent-dispatcher-EDW7NFJ4.cjs.map → intent-dispatcher-TBTSYYGJ.cjs.map} +2 -2
  24. package/dist/lib/node/{intent-resolver-34J5IM27.cjs → intent-resolver-IYW254AY.cjs} +8 -8
  25. package/dist/lib/node/meta.json +1 -1
  26. package/dist/lib/node/{store-3I3UFH5D.cjs → store-KGQB37IW.cjs} +7 -7
  27. package/dist/lib/node/testing/index.cjs +10 -9
  28. package/dist/lib/node/testing/index.cjs.map +3 -3
  29. package/dist/lib/node/worker.cjs +37 -37
  30. package/dist/lib/node/worker.cjs.map +1 -1
  31. package/dist/lib/node-esm/{app-graph-builder-RG3DT2OD.mjs → app-graph-builder-UP3LWWYO.mjs} +2 -2
  32. package/dist/lib/node-esm/{chunk-T2URISUU.mjs → chunk-MZCAK52M.mjs} +7 -6
  33. package/dist/lib/node-esm/chunk-MZCAK52M.mjs.map +7 -0
  34. package/dist/lib/node-esm/{chunk-NIVSBD3D.mjs → chunk-RQWO2T4E.mjs} +4 -3
  35. package/dist/lib/node-esm/{chunk-NIVSBD3D.mjs.map → chunk-RQWO2T4E.mjs.map} +3 -3
  36. package/dist/lib/node-esm/index.mjs +7 -6
  37. package/dist/lib/node-esm/index.mjs.map +3 -3
  38. package/dist/lib/node-esm/{intent-dispatcher-7GCMKMSQ.mjs → intent-dispatcher-7UNJKY3C.mjs} +2 -2
  39. package/dist/lib/node-esm/{intent-resolver-7T6UOQOS.mjs → intent-resolver-6MHZSVCT.mjs} +2 -2
  40. package/dist/lib/node-esm/meta.json +1 -1
  41. package/dist/lib/node-esm/{store-PTKVELJP.mjs → store-YSFTF2GM.mjs} +2 -2
  42. package/dist/lib/node-esm/testing/index.mjs +4 -3
  43. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  44. package/dist/lib/node-esm/worker.mjs +1 -1
  45. package/dist/types/src/common/surface.d.ts +4 -7
  46. package/dist/types/src/common/surface.d.ts.map +1 -1
  47. package/dist/types/src/core/plugin.d.ts +1 -1
  48. package/dist/types/src/core/plugin.d.ts.map +1 -1
  49. package/dist/types/src/react/Surface.d.ts.map +1 -1
  50. package/package.json +18 -18
  51. package/src/common/surface.ts +6 -1
  52. package/src/core/manager.test.ts +30 -30
  53. package/src/core/plugin.ts +1 -1
  54. package/src/playground/debug/plugin.ts +1 -1
  55. package/src/playground/generator/generator.ts +1 -1
  56. package/src/playground/generator/plugin.ts +1 -1
  57. package/src/playground/layout/plugin.ts +1 -1
  58. package/src/playground/logger/plugin.ts +1 -1
  59. package/src/plugin-intent/IntentPlugin.tsx +1 -1
  60. package/src/plugin-settings/SettingsPlugin.ts +1 -1
  61. package/src/react/Surface.tsx +5 -3
  62. package/src/testing/withPluginManager.tsx +1 -1
  63. package/dist/lib/browser/chunk-CIP4C47B.mjs.map +0 -7
  64. package/dist/lib/node/chunk-JLQABYHB.cjs.map +0 -7
  65. package/dist/lib/node-esm/chunk-T2URISUU.mjs.map +0 -7
  66. /package/dist/lib/browser/{app-graph-builder-IAEV7KKF.mjs.map → app-graph-builder-OD3G2J2U.mjs.map} +0 -0
  67. /package/dist/lib/browser/{intent-dispatcher-UR566RVO.mjs.map → intent-dispatcher-RTXTATZJ.mjs.map} +0 -0
  68. /package/dist/lib/browser/{intent-resolver-LEJ3X6CP.mjs.map → intent-resolver-ZL6WBF2L.mjs.map} +0 -0
  69. /package/dist/lib/browser/{store-5TN4OLFQ.mjs.map → store-JIKLP4JL.mjs.map} +0 -0
  70. /package/dist/lib/node/{app-graph-builder-3RWOZENP.cjs.map → app-graph-builder-S3ER53EH.cjs.map} +0 -0
  71. /package/dist/lib/node/{intent-resolver-34J5IM27.cjs.map → intent-resolver-IYW254AY.cjs.map} +0 -0
  72. /package/dist/lib/node/{store-3I3UFH5D.cjs.map → store-KGQB37IW.cjs.map} +0 -0
  73. /package/dist/lib/node-esm/{app-graph-builder-RG3DT2OD.mjs.map → app-graph-builder-UP3LWWYO.mjs.map} +0 -0
  74. /package/dist/lib/node-esm/{intent-dispatcher-7GCMKMSQ.mjs.map → intent-dispatcher-7UNJKY3C.mjs.map} +0 -0
  75. /package/dist/lib/node-esm/{intent-resolver-7T6UOQOS.mjs.map → intent-resolver-6MHZSVCT.mjs.map} +0 -0
  76. /package/dist/lib/node-esm/{store-PTKVELJP.mjs.map → store-YSFTF2GM.mjs.map} +0 -0
@@ -28,7 +28,7 @@ const Total = defineCapability<{ total: number }>('dxos.org/test/total');
28
28
  const CountEvent = defineEvent('dxos.org/test/count');
29
29
  const FailEvent = defineEvent('dxos.org/test/fail');
30
30
 
31
- const testMeta = { id: 'dxos.org/plugin/test' };
31
+ const testMeta = { id: 'dxos.org/plugin/test', name: 'Test' };
32
32
 
33
33
  describe('PluginManager', () => {
34
34
  let plugins: Plugin[] = [];
@@ -180,46 +180,46 @@ describe('PluginManager', () => {
180
180
  });
181
181
 
182
182
  it('should be able to fire custom activation events', async () => {
183
- const One = definePlugin({ id: 'dxos.org/test/one' }, [
183
+ const Plugin1 = definePlugin({ id: 'dxos.org/test/plugin-1', name: 'Plugin 1' }, [
184
184
  defineModule({
185
- id: 'dxos.org/test/one',
185
+ id: 'dxos.org/test/plugin-1',
186
186
  activatesOn: CountEvent,
187
187
  activate: () => [contributes(Number, { number: 1 })],
188
188
  }),
189
189
  ]);
190
- const Two = definePlugin({ id: 'dxos.org/test/two' }, [
190
+ const Plugin2 = definePlugin({ id: 'dxos.org/test/plugin-2', name: 'Plugin 2' }, [
191
191
  defineModule({
192
- id: 'dxos.org/test/two',
192
+ id: 'dxos.org/test/plugin-2',
193
193
  activatesOn: CountEvent,
194
194
  activate: () => [contributes(Number, { number: 2 })],
195
195
  }),
196
196
  ]);
197
- const Three = definePlugin({ id: 'dxos.org/test/three' }, [
197
+ const Plugin3 = definePlugin({ id: 'dxos.org/test/plugin-3', name: 'Plugin 3' }, [
198
198
  defineModule({
199
- id: 'dxos.org/test/three',
199
+ id: 'dxos.org/test/plugin-3',
200
200
  activatesOn: CountEvent,
201
201
  activate: () => [contributes(Number, { number: 3 })],
202
202
  }),
203
203
  ]);
204
- plugins = [One, Two, Three];
204
+ plugins = [Plugin1, Plugin2, Plugin3];
205
205
 
206
206
  const manager = new PluginManager({ pluginLoader });
207
207
  expect(manager.active).toEqual([]);
208
208
  expect(manager.context.requestCapabilities(Number)).toHaveLength(0);
209
209
 
210
- await manager.add(One.meta.id);
210
+ await manager.add(Plugin1.meta.id);
211
211
  await manager.activate(CountEvent);
212
- expect(manager.active).toEqual([One.meta.id]);
212
+ expect(manager.active).toEqual([Plugin1.meta.id]);
213
213
  expect(manager.context.requestCapabilities(Number)).toHaveLength(1);
214
214
 
215
- await manager.add(Two.meta.id);
215
+ await manager.add(Plugin2.meta.id);
216
216
  await manager.activate(CountEvent);
217
- expect(manager.active).toEqual([One.meta.id, Two.meta.id]);
217
+ expect(manager.active).toEqual([Plugin1.meta.id, Plugin2.meta.id]);
218
218
  expect(manager.context.requestCapabilities(Number)).toHaveLength(2);
219
219
 
220
- await manager.add(Three.meta.id);
220
+ await manager.add(Plugin3.meta.id);
221
221
  await manager.activate(CountEvent);
222
- expect(manager.active).toEqual([One.meta.id, Two.meta.id, Three.meta.id]);
222
+ expect(manager.active).toEqual([Plugin1.meta.id, Plugin2.meta.id, Plugin3.meta.id]);
223
223
  expect(manager.context.requestCapabilities(Number)).toHaveLength(3);
224
224
  });
225
225
 
@@ -283,7 +283,7 @@ describe('PluginManager', () => {
283
283
  state.total = numbers.reduce((acc, n) => acc + n.number, 0);
284
284
  };
285
285
 
286
- const Count = definePlugin({ id: 'dxos.org/test/count' }, [
286
+ const Count = definePlugin({ id: 'dxos.org/test/count', name: 'Count' }, [
287
287
  defineModule({
288
288
  id: 'dxos.org/test/count',
289
289
  activatesOn: Events.Startup,
@@ -297,17 +297,17 @@ describe('PluginManager', () => {
297
297
 
298
298
  const Test = definePlugin(testMeta, [
299
299
  defineModule({
300
- id: 'dxos.org/test/one',
300
+ id: 'dxos.org/test/plugin-1',
301
301
  activatesOn: CountEvent,
302
302
  activate: () => contributes(Number, { number: 1 }),
303
303
  }),
304
304
  defineModule({
305
- id: 'dxos.org/test/two',
305
+ id: 'dxos.org/test/plugin-2',
306
306
  activatesOn: CountEvent,
307
307
  activate: () => contributes(Number, { number: 2 }),
308
308
  }),
309
309
  defineModule({
310
- id: 'dxos.org/test/three',
310
+ id: 'dxos.org/test/plugin-3',
311
311
  activatesOn: CountEvent,
312
312
  activate: () => contributes(Number, { number: 3 }),
313
313
  }),
@@ -390,28 +390,28 @@ describe('PluginManager', () => {
390
390
  });
391
391
 
392
392
  it('should be reactive', async () => {
393
- const One = definePlugin({ id: 'dxos.org/test/one' }, [
393
+ const Plugin1 = definePlugin({ id: 'dxos.org/test/plugin-1', name: 'Plugin 1' }, [
394
394
  defineModule({
395
- id: 'dxos.org/test/one',
395
+ id: 'dxos.org/test/plugin-1',
396
396
  activatesOn: CountEvent,
397
397
  activate: () => [contributes(Number, { number: 1 })],
398
398
  }),
399
399
  ]);
400
- const Two = definePlugin({ id: 'dxos.org/test/two' }, [
400
+ const Plugin2 = definePlugin({ id: 'dxos.org/test/plugin-2', name: 'Plugin 2' }, [
401
401
  defineModule({
402
- id: 'dxos.org/test/two',
402
+ id: 'dxos.org/test/plugin-2',
403
403
  activatesOn: CountEvent,
404
404
  activate: () => [contributes(Number, { number: 2 })],
405
405
  }),
406
406
  ]);
407
- const Three = definePlugin({ id: 'dxos.org/test/three' }, [
407
+ const Plugin3 = definePlugin({ id: 'dxos.org/test/plugin-3', name: 'Plugin 3' }, [
408
408
  defineModule({
409
- id: 'dxos.org/test/three',
409
+ id: 'dxos.org/test/plugin-3',
410
410
  activatesOn: CountEvent,
411
411
  activate: () => [contributes(Number, { number: 3 })],
412
412
  }),
413
413
  ]);
414
- plugins = [One, Two, Three];
414
+ plugins = [Plugin1, Plugin2, Plugin3];
415
415
 
416
416
  const manager = new PluginManager({ pluginLoader });
417
417
  using pluginUpdates = updateCounter(() => {
@@ -439,7 +439,7 @@ describe('PluginManager', () => {
439
439
  expect(eventsFiredUpdates.count).toEqual(0);
440
440
  expect(pendingResetUpdates.count).toEqual(0);
441
441
 
442
- await manager.add(One.meta.id);
442
+ await manager.add(Plugin1.meta.id);
443
443
  expect(pluginUpdates.count).toEqual(1);
444
444
  expect(enabledUpdates.count).toEqual(1);
445
445
  expect(modulesUpdates.count).toEqual(1);
@@ -455,7 +455,7 @@ describe('PluginManager', () => {
455
455
  expect(eventsFiredUpdates.count).toEqual(1);
456
456
  expect(pendingResetUpdates.count).toEqual(0);
457
457
 
458
- await manager.add(Two.meta.id);
458
+ await manager.add(Plugin2.meta.id);
459
459
  expect(pluginUpdates.count).toEqual(2);
460
460
  expect(enabledUpdates.count).toEqual(2);
461
461
  expect(modulesUpdates.count).toEqual(2);
@@ -471,7 +471,7 @@ describe('PluginManager', () => {
471
471
  expect(eventsFiredUpdates.count).toEqual(1);
472
472
  expect(pendingResetUpdates.count).toEqual(2);
473
473
 
474
- await manager.add(Three.meta.id);
474
+ await manager.add(Plugin3.meta.id);
475
475
  expect(pluginUpdates.count).toEqual(3);
476
476
  expect(enabledUpdates.count).toEqual(3);
477
477
  expect(modulesUpdates.count).toEqual(3);
@@ -488,7 +488,7 @@ describe('PluginManager', () => {
488
488
  expect(eventsFiredUpdates.count).toEqual(1);
489
489
  expect(pendingResetUpdates.count).toEqual(4);
490
490
 
491
- await manager.disable(One.meta.id);
491
+ await manager.disable(Plugin1.meta.id);
492
492
  expect(pluginUpdates.count).toEqual(3);
493
493
  expect(enabledUpdates.count).toEqual(4);
494
494
  expect(modulesUpdates.count).toEqual(4);
@@ -496,7 +496,7 @@ describe('PluginManager', () => {
496
496
  expect(eventsFiredUpdates.count).toEqual(1);
497
497
  expect(pendingResetUpdates.count).toEqual(4);
498
498
 
499
- await manager.remove(One.meta.id);
499
+ await manager.remove(Plugin1.meta.id);
500
500
  expect(pluginUpdates.count).toEqual(4);
501
501
  expect(enabledUpdates.count).toEqual(4);
502
502
  expect(modulesUpdates.count).toEqual(4);
@@ -79,7 +79,7 @@ export type PluginMeta = {
79
79
  /**
80
80
  * Human-readable name.
81
81
  */
82
- name?: string;
82
+ name: string;
83
83
 
84
84
  /**
85
85
  * Short description of plugin functionality.
@@ -8,7 +8,7 @@ import { defineModule, definePlugin, lazy } from '../../core';
8
8
  const Debug = lazy(() => import('./Debug'));
9
9
 
10
10
  export const DebugPlugin = () =>
11
- definePlugin({ id: 'dxos.org/test/debug' }, [
11
+ definePlugin({ id: 'dxos.org/test/plugin-debug', name: 'Debug' }, [
12
12
  defineModule({
13
13
  id: 'dxos.org/test/debug/main',
14
14
  activatesOn: Events.Startup,
@@ -26,7 +26,7 @@ export const createGeneratorIntent = (id: string) => {
26
26
  export const createNumberPlugin = (id: string) => {
27
27
  const number = Math.floor(Math.random() * 100);
28
28
 
29
- return definePlugin({ id }, [
29
+ return definePlugin({ id, name: `Plugin ${id}` }, [
30
30
  defineModule({
31
31
  id: `${id}/main`,
32
32
  activatesOn: CountEvent,
@@ -9,7 +9,7 @@ const Main = lazy(() => import('./Main'));
9
9
  const Toolbar = lazy(() => import('./Toolbar'));
10
10
 
11
11
  export const GeneratorPlugin = () =>
12
- definePlugin({ id: 'dxos.org/test/generator' }, [
12
+ definePlugin({ id: 'dxos.org/test/generator', name: 'Generator' }, [
13
13
  defineModule({
14
14
  id: 'dxos.org/test/generator/main',
15
15
  activatesOn: Events.Startup,
@@ -8,7 +8,7 @@ import { definePlugin, lazy, defineModule } from '../../core';
8
8
  const Layout = lazy(() => import('./Layout'));
9
9
 
10
10
  export const LayoutPlugin = () =>
11
- definePlugin({ id: 'dxos.org/test/layout' }, [
11
+ definePlugin({ id: 'dxos.org/test/layout', name: 'Layout' }, [
12
12
  defineModule({
13
13
  id: 'dxos.org/test/layout/root',
14
14
  activatesOn: Events.Startup,
@@ -12,7 +12,7 @@ import { createResolver } from '../../plugin-intent';
12
12
  const Toolbar = lazy(() => import('./Toolbar'));
13
13
 
14
14
  export const LoggerPlugin = () =>
15
- definePlugin({ id: 'dxos.org/test/logger' }, [
15
+ definePlugin({ id: 'dxos.org/test/logger', name: 'Logger' }, [
16
16
  defineModule({
17
17
  id: 'dxos.org/test/logger/intents',
18
18
  activatesOn: Events.SetupIntentResolver,
@@ -7,7 +7,7 @@ import { Events } from '../common';
7
7
  import { defineModule, definePlugin, lazy } from '../core';
8
8
 
9
9
  export const IntentPlugin = () =>
10
- definePlugin({ id: INTENT_PLUGIN }, [
10
+ definePlugin({ id: INTENT_PLUGIN, name: 'Intent' }, [
11
11
  defineModule({
12
12
  id: `${INTENT_PLUGIN}/module/dispatcher`,
13
13
  // TODO(wittjosiah): This will mean that startup needs to be reset when intents are added or removed.
@@ -9,7 +9,7 @@ import { contributes, defineModule, definePlugin, lazy } from '../core';
9
9
 
10
10
  // TODO(wittjosiah): Add options to exclude some modules.
11
11
  export const SettingsPlugin = () =>
12
- definePlugin({ id: SETTINGS_PLUGIN }, [
12
+ definePlugin({ id: SETTINGS_PLUGIN, name: 'Settings' }, [
13
13
  defineModule({
14
14
  id: `${SETTINGS_PLUGIN}/module/store`,
15
15
  activatesOn: Events.Startup,
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import React, { memo, forwardRef, Suspense, useMemo } from 'react';
5
+ import React, { memo, forwardRef, Suspense, useMemo, Fragment } from 'react';
6
6
 
7
7
  import { useDefaultValue } from '@dxos/react-hooks';
8
8
  import { byPosition } from '@dxos/util';
@@ -12,6 +12,8 @@ import { useCapabilities } from './useCapabilities';
12
12
  import { Capabilities, type SurfaceDefinition, type SurfaceProps } from '../common';
13
13
  import { type PluginsContext } from '../core';
14
14
 
15
+ const DEFAULT_PLACEHOLDER = <Fragment />;
16
+
15
17
  /**
16
18
  * @internal
17
19
  */
@@ -43,7 +45,7 @@ export const isSurfaceAvailable = (context: PluginsContext, { role, data }: Pick
43
45
  */
44
46
  export const Surface = memo(
45
47
  forwardRef<HTMLElement, SurfaceProps>(
46
- ({ id: _id, role, data: _data, limit, fallback, placeholder, ...rest }, forwardedRef) => {
48
+ ({ id: _id, role, data: _data, limit, fallback, placeholder = DEFAULT_PLACEHOLDER, ...rest }, forwardedRef) => {
47
49
  // TODO(wittjosiah): This will make all surfaces depend on a single signal.
48
50
  // This isn't ideal because it means that any change to the data will cause all surfaces to re-render.
49
51
  // This effectively means that plugin modules which contribute surfaces need to all be activated at startup.
@@ -59,7 +61,7 @@ export const Surface = memo(
59
61
  <Component ref={forwardedRef} key={id} id={id} role={role} data={data} limit={limit} {...rest} />
60
62
  ));
61
63
 
62
- const suspense = placeholder ? <Suspense fallback={placeholder}>{nodes}</Suspense> : nodes;
64
+ const suspense = <Suspense fallback={placeholder}>{nodes}</Suspense>;
63
65
 
64
66
  return fallback ? (
65
67
  <ErrorBoundary data={data} fallback={fallback}>
@@ -86,6 +86,6 @@ export const withPluginManager = (options: WithPluginManagerOptions = {}): Decor
86
86
  // This is necessary because `createApp` expects the startup event to complete before the app is ready.
87
87
  const STORY_PLUGIN = 'dxos.org/app-framework/story';
88
88
  const StoryPlugin = () =>
89
- definePlugin({ id: STORY_PLUGIN }, [
89
+ definePlugin({ id: STORY_PLUGIN, name: 'Story' }, [
90
90
  defineModule({ id: STORY_PLUGIN, activatesOn: Events.Startup, activate: () => [] }),
91
91
  ]);
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/react/PluginManagerProvider.ts", "../../../src/react/useCapabilities.ts", "../../../src/react/common.ts", "../../../src/react/ErrorBoundary.tsx", "../../../src/react/Surface.tsx", "../../../src/react/useIntentResolver.ts", "../../../src/App.tsx", "../../../src/helpers.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { createContext, useContext } from 'react';\n\nimport { raise } from '@dxos/debug';\n\nimport { type PluginManager } from '../core';\n\nconst PluginManagerContext = createContext<PluginManager | undefined>(undefined);\n\n/**\n * Get the plugin manager.\n */\nexport const usePluginManager = (): PluginManager =>\n useContext(PluginManagerContext) ?? raise(new Error('Missing PluginManagerContext'));\n\n/**\n * Context provider for a plugin manager.\n */\nexport const PluginManagerProvider = PluginManagerContext.Provider;\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { computed } from '@preact/signals-core';\nimport { useMemo } from 'react';\n\nimport { usePluginManager } from './PluginManagerProvider';\nimport { type InterfaceDef } from '../core';\n\n/**\n * Hook to request capabilities from the plugin context.\n * @returns An array of capabilities.\n */\nexport const useCapabilities = <T, U extends T = T>(\n interfaceDef: InterfaceDef<T>,\n filter?: (capability: T, moduleId: string) => capability is U,\n) => {\n const manager = usePluginManager();\n const signal = useMemo(\n () => computed(() => manager.context.requestCapabilities(interfaceDef, filter)),\n [interfaceDef],\n );\n\n return signal.value;\n};\n\n/**\n * Hook to request a capability from the plugin context.\n * @returns The capability.\n * @throws If no capability is found.\n */\nexport const useCapability = <T, U extends T = T>(\n interfaceDef: InterfaceDef<T>,\n filter?: (capability: T, moduleId: string) => capability is U,\n) => {\n const manager = usePluginManager();\n const signal = useMemo(() => computed(() => manager.context.requestCapability(interfaceDef, filter)), [interfaceDef]);\n return signal.value;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useCapability } from './useCapabilities';\nimport { Capabilities } from '../common';\n\nexport const useIntentDispatcher = () => useCapability(Capabilities.IntentDispatcher);\n\nexport const useAppGraph = () => useCapability(Capabilities.AppGraph);\n\nexport const useLayout = () => useCapability(Capabilities.Layout);\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { Component, type FC, type PropsWithChildren } from 'react';\n\ntype Props = PropsWithChildren<{ data?: any; fallback: FC<{ data?: any; error: Error; reset: () => void }> }>;\ntype State = { error: Error | undefined };\n\n/**\n * Surface error boundary.\n *\n * For basic usage prefer providing a fallback component to `Surface`.\n *\n * For more information on error boundaries, see:\n * https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary\n */\nexport class ErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { error: undefined };\n }\n\n static getDerivedStateFromError(error: Error) {\n return { error };\n }\n\n override componentDidUpdate(prevProps: Props): void {\n if (prevProps.data !== this.props.data) {\n this.resetError();\n }\n }\n\n override render() {\n if (this.state.error) {\n return <this.props.fallback data={this.props.data} error={this.state.error} reset={this.resetError} />;\n }\n\n return this.props.children;\n }\n\n private resetError() {\n this.setState({ error: undefined });\n }\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { memo, forwardRef, Suspense, useMemo } from 'react';\n\nimport { useDefaultValue } from '@dxos/react-hooks';\nimport { byPosition } from '@dxos/util';\n\nimport { ErrorBoundary } from './ErrorBoundary';\nimport { useCapabilities } from './useCapabilities';\nimport { Capabilities, type SurfaceDefinition, type SurfaceProps } from '../common';\nimport { type PluginsContext } from '../core';\n\n/**\n * @internal\n */\nexport const useSurfaces = () => {\n const surfaces = useCapabilities(Capabilities.ReactSurface);\n return useMemo(() => surfaces.flat(), [surfaces]);\n};\n\nconst findCandidates = (surfaces: SurfaceDefinition[], { role, data }: Pick<SurfaceProps, 'role' | 'data'>) => {\n return Object.values(surfaces)\n .filter((definition) =>\n Array.isArray(definition.role) ? definition.role.includes(role) : definition.role === role,\n )\n .filter(({ filter }) => (filter ? filter(data ?? {}) : true))\n .toSorted(byPosition);\n};\n\n/**\n * @returns `true` if there is a contributed surface which matches the specified role & data, `false` otherwise.\n */\nexport const isSurfaceAvailable = (context: PluginsContext, { role, data }: Pick<SurfaceProps, 'role' | 'data'>) => {\n const surfaces = context.requestCapabilities(Capabilities.ReactSurface);\n const candidates = findCandidates(surfaces.flat(), { role, data });\n return candidates.length > 0;\n};\n\n/**\n * A surface is a named region of the screen that can be populated by plugins.\n */\nexport const Surface = memo(\n forwardRef<HTMLElement, SurfaceProps>(\n ({ id: _id, role, data: _data, limit, fallback, placeholder, ...rest }, forwardedRef) => {\n // TODO(wittjosiah): This will make all surfaces depend on a single signal.\n // This isn't ideal because it means that any change to the data will cause all surfaces to re-render.\n // This effectively means that plugin modules which contribute surfaces need to all be activated at startup.\n // This should be fine for now because it's how it worked prior to capabilities api anyways.\n // In the future, it would be nice to be able to bucket the surface contributions by role.\n const surfaces = useSurfaces();\n const data = useDefaultValue(_data, () => ({}));\n\n // NOTE: Memoizing the candidates makes the surface not re-render based on reactivity within data.\n const definitions = findCandidates(surfaces, { role, data });\n const candidates = limit ? definitions.slice(0, limit) : definitions;\n const nodes = candidates.map(({ component: Component, id }) => (\n <Component ref={forwardedRef} key={id} id={id} role={role} data={data} limit={limit} {...rest} />\n ));\n\n const suspense = placeholder ? <Suspense fallback={placeholder}>{nodes}</Suspense> : nodes;\n\n return fallback ? (\n <ErrorBoundary data={data} fallback={fallback}>\n {suspense}\n </ErrorBoundary>\n ) : (\n suspense\n );\n },\n ),\n);\n\nSurface.displayName = 'Surface';\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { useEffect } from 'react';\n\nimport { Capabilities } from '../common';\nimport { type AnyIntentResolver } from '../plugin-intent';\nimport { usePluginManager } from '../react';\n\nexport const useIntentResolver = (module: string, resolver: AnyIntentResolver) => {\n const manager = usePluginManager();\n useEffect(() => {\n manager.context.contributeCapability({\n module,\n interface: Capabilities.IntentResolver,\n implementation: resolver,\n });\n\n return () => manager.context.removeCapability(Capabilities.IntentResolver, resolver);\n }, [module, resolver]);\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { effect } from '@preact/signals-core';\nimport React, { type PropsWithChildren, type ReactNode } from 'react';\n\nimport { invariant } from '@dxos/invariant';\nimport { create } from '@dxos/live-object';\n\nimport { Capabilities, Events } from './common';\nimport { PluginManager, type PluginManagerOptions, type Plugin } from './core';\nimport { topologicalSort } from './helpers';\nimport { ErrorBoundary, PluginManagerProvider, useCapabilities } from './react';\n\nconst ENABLED_KEY = 'dxos.org/app-framework/enabled';\n\nexport type CreateAppOptions = {\n pluginManager?: PluginManager;\n pluginLoader?: PluginManagerOptions['pluginLoader'];\n plugins?: Plugin[];\n core?: string[];\n defaults?: string[];\n placeholder?: ReactNode;\n fallback?: ErrorBoundary['props']['fallback'];\n cacheEnabled?: boolean;\n};\n\n/**\n * Expected usage is for this to be the entrypoint of the application.\n * Initializes plugins and renders the root components.\n *\n * @example\n * const plugins = [LayoutPlugin(), MyPlugin()];\n * const core = [LayoutPluginId];\n * const default = [MyPluginId];\n * const fallback = <div>Initializing Plugins...</div>;\n * const App = createApp({ plugins, core, default, fallback });\n * createRoot(document.getElementById('root')!).render(\n * <StrictMode>\n * <App />\n * </StrictMode>,\n * );\n *\n * @param params.pluginLoader A function which loads new plugins.\n * @param params.plugins All plugins available to the application.\n * @param params.core Core plugins which will always be enabled.\n * @param params.defaults Default plugins are enabled by default but can be disabled by the user.\n * @param params.placeholder Placeholder component to render during startup.\n * @param params.fallback Fallback component to render if an error occurs during startup.\n * @param params.cacheEnabled Whether to cache enabled plugins in localStorage.\n */\nexport const createApp = ({\n pluginManager,\n pluginLoader: _pluginLoader,\n plugins = [],\n core = plugins.map(({ meta }) => meta.id),\n defaults = [],\n placeholder = null,\n fallback = DefaultFallback,\n cacheEnabled = false,\n}: CreateAppOptions) => {\n // TODO(wittjosiah): Provide a custom plugin loader which supports loading via url.\n const pluginLoader =\n _pluginLoader ??\n ((id: string) => {\n const plugin = plugins.find((plugin) => plugin.meta.id === id);\n invariant(plugin, `Plugin not found: ${id}`);\n return plugin;\n });\n\n const state = create({ ready: false, error: null });\n const cached: string[] = JSON.parse(localStorage.getItem(ENABLED_KEY) ?? '[]');\n const enabled = cacheEnabled && cached.length > 0 ? cached : defaults;\n const manager = pluginManager ?? new PluginManager({ pluginLoader, plugins, core, enabled });\n\n manager.activation.on(({ event, state: _state, error }) => {\n // Once the app is ready the first time, don't show the fallback again.\n if (!state.ready && event === Events.Startup.id) {\n state.ready = _state === 'activated';\n }\n\n if (error && !state.ready && !state.error) {\n state.error = error;\n }\n });\n\n effect(() => {\n cacheEnabled && localStorage.setItem(ENABLED_KEY, JSON.stringify(manager.enabled));\n });\n\n manager.context.contributeCapability({\n interface: Capabilities.PluginManager,\n implementation: manager,\n module: 'dxos.org/app-framework/plugin-manager',\n });\n\n setupDevtools(manager);\n\n // TODO(wittjosiah): Factor out such that this could be called per surface role when attempting to render.\n void manager.activate(Events.SetupReactSurface);\n void manager.activate(Events.Startup);\n\n return () => (\n <ErrorBoundary fallback={fallback}>\n <PluginManagerProvider value={manager}>\n <App placeholder={placeholder} state={state} />\n </PluginManagerProvider>\n </ErrorBoundary>\n );\n};\n\ntype AppProps = Required<Pick<CreateAppOptions, 'placeholder'>> & {\n state: { ready: boolean; error: unknown };\n};\n\nconst App = ({ placeholder, state }: AppProps) => {\n const reactContexts = useCapabilities(Capabilities.ReactContext);\n const reactRoots = useCapabilities(Capabilities.ReactRoot);\n\n if (state.error) {\n // This trigger the error boundary to provide UI feedback for the startup error.\n throw state.error;\n }\n\n // TODO(wittjosiah): Consider using Suspense instead?\n if (!state.ready) {\n return <>{placeholder}</>;\n }\n\n const ComposedContext = composeContexts(reactContexts);\n return (\n <ComposedContext>\n {reactRoots.map(({ id, root: Component }) => (\n <Component key={id} />\n ))}\n </ComposedContext>\n );\n};\n\n// Default fallback does not use tailwind or theme.\nconst DefaultFallback = ({ error }: { error: Error }) => {\n return (\n <div style={{ padding: '1rem' }}>\n {/* TODO(wittjosiah): Link to docs for replacing default. */}\n <h1 style={{ fontSize: '1.2rem', fontWeight: 700, margin: '0.5rem 0' }}>{error.message}</h1>\n <pre>{error.stack}</pre>\n </div>\n );\n};\n\nconst composeContexts = (contexts: Capabilities.ReactContext[]) => {\n if (contexts.length === 0) {\n return ({ children }: PropsWithChildren) => <>{children}</>;\n }\n\n return topologicalSort(contexts)\n .map(({ context }) => context)\n .reduce((Acc, Next) => ({ children }) => (\n <Acc>\n <Next>{children}</Next>\n </Acc>\n ));\n};\n\nconst setupDevtools = (manager: PluginManager) => {\n (globalThis as any).composer ??= {};\n (globalThis as any).composer.manager = manager;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\ntype DependencyNode = {\n id: string;\n dependsOn?: string[];\n};\n\n/**\n * Topologically sorts a list of nodes based on their dependencies.\n */\n// TODO(wittjosiah): Factor out?\nexport const topologicalSort = <T extends DependencyNode>(nodes: T[]): T[] => {\n const getDependencies = (nodeId: string, seen = new Set<string>(), path = new Set<string>()): string[] => {\n if (path.has(nodeId)) {\n throw new Error(`Circular dependency detected involving ${nodeId}`);\n }\n if (seen.has(nodeId)) {\n return [];\n }\n\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) {\n throw new Error(`Node ${nodeId} not found but is listed as a dependency`);\n }\n\n const newPath = new Set([...path, nodeId]);\n const newSeen = new Set([...seen, nodeId]);\n\n const dependsOn = node.dependsOn ?? [];\n return [...dependsOn.flatMap((depId) => getDependencies(depId, newSeen, newPath)), nodeId];\n };\n\n // Get all unique dependencies.\n const allDependencies = nodes\n .map((node) => node.id)\n .flatMap((id) => getDependencies(id))\n .filter((id, index, self) => self.indexOf(id) === index);\n\n // Map back to original nodes\n return allDependencies\n .map((id) => nodes.find((node) => node.id === id))\n .filter((node): node is T => node !== undefined);\n};\n"],
5
- "mappings": "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",
6
- "names": ["createContext", "useContext", "raise", "PluginManagerContext", "createContext", "undefined", "usePluginManager", "useContext", "raise", "Error", "PluginManagerProvider", "Provider", "computed", "useMemo", "useCapabilities", "interfaceDef", "filter", "manager", "usePluginManager", "signal", "useMemo", "computed", "context", "requestCapabilities", "value", "useCapability", "requestCapability", "useIntentDispatcher", "useCapability", "Capabilities", "IntentDispatcher", "useAppGraph", "AppGraph", "useLayout", "Layout", "React", "Component", "ErrorBoundary", "Component", "constructor", "props", "state", "error", "undefined", "getDerivedStateFromError", "componentDidUpdate", "prevProps", "data", "resetError", "render", "this", "fallback", "reset", "children", "setState", "React", "memo", "forwardRef", "Suspense", "useMemo", "useDefaultValue", "byPosition", "useSurfaces", "surfaces", "useCapabilities", "Capabilities", "ReactSurface", "useMemo", "flat", "findCandidates", "role", "data", "Object", "values", "filter", "definition", "Array", "isArray", "includes", "toSorted", "byPosition", "isSurfaceAvailable", "context", "requestCapabilities", "candidates", "length", "Surface", "memo", "forwardRef", "id", "_id", "_data", "limit", "fallback", "placeholder", "rest", "forwardedRef", "useDefaultValue", "definitions", "slice", "nodes", "map", "component", "Component", "React", "ref", "key", "suspense", "Suspense", "ErrorBoundary", "displayName", "useEffect", "useIntentResolver", "module", "resolver", "manager", "usePluginManager", "useEffect", "context", "contributeCapability", "interface", "Capabilities", "IntentResolver", "implementation", "removeCapability", "effect", "React", "invariant", "create", "topologicalSort", "nodes", "getDependencies", "nodeId", "seen", "Set", "path", "has", "Error", "node", "find", "n", "id", "newPath", "newSeen", "dependsOn", "flatMap", "depId", "allDependencies", "map", "filter", "index", "self", "indexOf", "undefined", "ENABLED_KEY", "createApp", "pluginManager", "pluginLoader", "_pluginLoader", "plugins", "core", "map", "meta", "id", "defaults", "placeholder", "fallback", "DefaultFallback", "cacheEnabled", "plugin", "find", "invariant", "state", "create", "ready", "error", "cached", "JSON", "parse", "localStorage", "getItem", "enabled", "length", "manager", "PluginManager", "activation", "on", "event", "_state", "Events", "Startup", "effect", "setItem", "stringify", "context", "contributeCapability", "interface", "Capabilities", "implementation", "module", "setupDevtools", "activate", "SetupReactSurface", "React", "ErrorBoundary", "PluginManagerProvider", "value", "App", "reactContexts", "useCapabilities", "ReactContext", "reactRoots", "ReactRoot", "ComposedContext", "composeContexts", "root", "Component", "key", "div", "style", "padding", "h1", "fontSize", "fontWeight", "margin", "message", "pre", "stack", "contexts", "children", "topologicalSort", "reduce", "Acc", "Next", "globalThis", "composer"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/react/PluginManagerProvider.ts", "../../../src/react/useCapabilities.ts", "../../../src/react/common.ts", "../../../src/react/ErrorBoundary.tsx", "../../../src/react/Surface.tsx", "../../../src/react/useIntentResolver.ts", "../../../src/App.tsx", "../../../src/helpers.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { createContext, useContext } from 'react';\n\nimport { raise } from '@dxos/debug';\n\nimport { type PluginManager } from '../core';\n\nconst PluginManagerContext = createContext<PluginManager | undefined>(undefined);\n\n/**\n * Get the plugin manager.\n */\nexport const usePluginManager = (): PluginManager =>\n useContext(PluginManagerContext) ?? raise(new Error('Missing PluginManagerContext'));\n\n/**\n * Context provider for a plugin manager.\n */\nexport const PluginManagerProvider = PluginManagerContext.Provider;\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { computed } from '@preact/signals-core';\nimport { useMemo } from 'react';\n\nimport { usePluginManager } from './PluginManagerProvider';\nimport { type InterfaceDef } from '../core';\n\n/**\n * Hook to request capabilities from the plugin context.\n * @returns An array of capabilities.\n */\nexport const useCapabilities = <T, U extends T = T>(\n interfaceDef: InterfaceDef<T>,\n filter?: (capability: T, moduleId: string) => capability is U,\n) => {\n const manager = usePluginManager();\n const signal = useMemo(\n () => computed(() => manager.context.requestCapabilities(interfaceDef, filter)),\n [interfaceDef],\n );\n\n return signal.value;\n};\n\n/**\n * Hook to request a capability from the plugin context.\n * @returns The capability.\n * @throws If no capability is found.\n */\nexport const useCapability = <T, U extends T = T>(\n interfaceDef: InterfaceDef<T>,\n filter?: (capability: T, moduleId: string) => capability is U,\n) => {\n const manager = usePluginManager();\n const signal = useMemo(() => computed(() => manager.context.requestCapability(interfaceDef, filter)), [interfaceDef]);\n return signal.value;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useCapability } from './useCapabilities';\nimport { Capabilities } from '../common';\n\nexport const useIntentDispatcher = () => useCapability(Capabilities.IntentDispatcher);\n\nexport const useAppGraph = () => useCapability(Capabilities.AppGraph);\n\nexport const useLayout = () => useCapability(Capabilities.Layout);\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { Component, type FC, type PropsWithChildren } from 'react';\n\ntype Props = PropsWithChildren<{ data?: any; fallback: FC<{ data?: any; error: Error; reset: () => void }> }>;\ntype State = { error: Error | undefined };\n\n/**\n * Surface error boundary.\n *\n * For basic usage prefer providing a fallback component to `Surface`.\n *\n * For more information on error boundaries, see:\n * https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary\n */\nexport class ErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { error: undefined };\n }\n\n static getDerivedStateFromError(error: Error) {\n return { error };\n }\n\n override componentDidUpdate(prevProps: Props): void {\n if (prevProps.data !== this.props.data) {\n this.resetError();\n }\n }\n\n override render() {\n if (this.state.error) {\n return <this.props.fallback data={this.props.data} error={this.state.error} reset={this.resetError} />;\n }\n\n return this.props.children;\n }\n\n private resetError() {\n this.setState({ error: undefined });\n }\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { memo, forwardRef, Suspense, useMemo } from 'react';\n\nimport { useDefaultValue } from '@dxos/react-hooks';\nimport { byPosition } from '@dxos/util';\n\nimport { ErrorBoundary } from './ErrorBoundary';\nimport { useCapabilities } from './useCapabilities';\nimport { Capabilities, type SurfaceDefinition, type SurfaceProps } from '../common';\nimport { type PluginsContext } from '../core';\n\n/**\n * @internal\n */\nexport const useSurfaces = () => {\n const surfaces = useCapabilities(Capabilities.ReactSurface);\n return useMemo(() => surfaces.flat(), [surfaces]);\n};\n\nconst findCandidates = (surfaces: SurfaceDefinition[], { role, data }: Pick<SurfaceProps, 'role' | 'data'>) => {\n return Object.values(surfaces)\n .filter((definition) =>\n Array.isArray(definition.role) ? definition.role.includes(role) : definition.role === role,\n )\n .filter(({ filter }) => (filter ? filter(data ?? {}) : true))\n .toSorted(byPosition);\n};\n\n/**\n * @returns `true` if there is a contributed surface which matches the specified role & data, `false` otherwise.\n */\nexport const isSurfaceAvailable = (context: PluginsContext, { role, data }: Pick<SurfaceProps, 'role' | 'data'>) => {\n const surfaces = context.requestCapabilities(Capabilities.ReactSurface);\n const candidates = findCandidates(surfaces.flat(), { role, data });\n return candidates.length > 0;\n};\n\n/**\n * A surface is a named region of the screen that can be populated by plugins.\n */\nexport const Surface = memo(\n forwardRef<HTMLElement, SurfaceProps>(\n ({ id: _id, role, data: _data, limit, fallback, placeholder, ...rest }, forwardedRef) => {\n // TODO(wittjosiah): This will make all surfaces depend on a single signal.\n // This isn't ideal because it means that any change to the data will cause all surfaces to re-render.\n // This effectively means that plugin modules which contribute surfaces need to all be activated at startup.\n // This should be fine for now because it's how it worked prior to capabilities api anyways.\n // In the future, it would be nice to be able to bucket the surface contributions by role.\n const surfaces = useSurfaces();\n const data = useDefaultValue(_data, () => ({}));\n\n // NOTE: Memoizing the candidates makes the surface not re-render based on reactivity within data.\n const definitions = findCandidates(surfaces, { role, data });\n const candidates = limit ? definitions.slice(0, limit) : definitions;\n const nodes = candidates.map(({ component: Component, id }) => (\n <Component ref={forwardedRef} key={id} id={id} role={role} data={data} limit={limit} {...rest} />\n ));\n\n const suspense = placeholder ? <Suspense fallback={placeholder}>{nodes}</Suspense> : nodes;\n\n return fallback ? (\n <ErrorBoundary data={data} fallback={fallback}>\n {suspense}\n </ErrorBoundary>\n ) : (\n suspense\n );\n },\n ),\n);\n\nSurface.displayName = 'Surface';\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { useEffect } from 'react';\n\nimport { Capabilities } from '../common';\nimport { type AnyIntentResolver } from '../plugin-intent';\nimport { usePluginManager } from '../react';\n\nexport const useIntentResolver = (module: string, resolver: AnyIntentResolver) => {\n const manager = usePluginManager();\n useEffect(() => {\n manager.context.contributeCapability({\n module,\n interface: Capabilities.IntentResolver,\n implementation: resolver,\n });\n\n return () => manager.context.removeCapability(Capabilities.IntentResolver, resolver);\n }, [module, resolver]);\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { effect } from '@preact/signals-core';\nimport React, { type PropsWithChildren, type ReactNode } from 'react';\n\nimport { invariant } from '@dxos/invariant';\nimport { create } from '@dxos/live-object';\n\nimport { Capabilities, Events } from './common';\nimport { PluginManager, type PluginManagerOptions, type Plugin } from './core';\nimport { topologicalSort } from './helpers';\nimport { ErrorBoundary, PluginManagerProvider, useCapabilities } from './react';\n\nconst ENABLED_KEY = 'dxos.org/app-framework/enabled';\n\nexport type CreateAppOptions = {\n pluginManager?: PluginManager;\n pluginLoader?: PluginManagerOptions['pluginLoader'];\n plugins?: Plugin[];\n core?: string[];\n defaults?: string[];\n placeholder?: ReactNode;\n fallback?: ErrorBoundary['props']['fallback'];\n cacheEnabled?: boolean;\n};\n\n/**\n * Expected usage is for this to be the entrypoint of the application.\n * Initializes plugins and renders the root components.\n *\n * @example\n * const plugins = [LayoutPlugin(), MyPlugin()];\n * const core = [LayoutPluginId];\n * const default = [MyPluginId];\n * const fallback = <div>Initializing Plugins...</div>;\n * const App = createApp({ plugins, core, default, fallback });\n * createRoot(document.getElementById('root')!).render(\n * <StrictMode>\n * <App />\n * </StrictMode>,\n * );\n *\n * @param params.pluginLoader A function which loads new plugins.\n * @param params.plugins All plugins available to the application.\n * @param params.core Core plugins which will always be enabled.\n * @param params.defaults Default plugins are enabled by default but can be disabled by the user.\n * @param params.placeholder Placeholder component to render during startup.\n * @param params.fallback Fallback component to render if an error occurs during startup.\n * @param params.cacheEnabled Whether to cache enabled plugins in localStorage.\n */\nexport const createApp = ({\n pluginManager,\n pluginLoader: _pluginLoader,\n plugins = [],\n core = plugins.map(({ meta }) => meta.id),\n defaults = [],\n placeholder = null,\n fallback = DefaultFallback,\n cacheEnabled = false,\n}: CreateAppOptions) => {\n // TODO(wittjosiah): Provide a custom plugin loader which supports loading via url.\n const pluginLoader =\n _pluginLoader ??\n ((id: string) => {\n const plugin = plugins.find((plugin) => plugin.meta.id === id);\n invariant(plugin, `Plugin not found: ${id}`);\n return plugin;\n });\n\n const state = create({ ready: false, error: null });\n const cached: string[] = JSON.parse(localStorage.getItem(ENABLED_KEY) ?? '[]');\n const enabled = cacheEnabled && cached.length > 0 ? cached : defaults;\n const manager = pluginManager ?? new PluginManager({ pluginLoader, plugins, core, enabled });\n\n manager.activation.on(({ event, state: _state, error }) => {\n // Once the app is ready the first time, don't show the fallback again.\n if (!state.ready && event === Events.Startup.id) {\n state.ready = _state === 'activated';\n }\n\n if (error && !state.ready && !state.error) {\n state.error = error;\n }\n });\n\n effect(() => {\n cacheEnabled && localStorage.setItem(ENABLED_KEY, JSON.stringify(manager.enabled));\n });\n\n manager.context.contributeCapability({\n interface: Capabilities.PluginManager,\n implementation: manager,\n module: 'dxos.org/app-framework/plugin-manager',\n });\n\n setupDevtools(manager);\n\n // TODO(wittjosiah): Factor out such that this could be called per surface role when attempting to render.\n void manager.activate(Events.SetupReactSurface);\n void manager.activate(Events.Startup);\n\n return () => (\n <ErrorBoundary fallback={fallback}>\n <PluginManagerProvider value={manager}>\n <App placeholder={placeholder} state={state} />\n </PluginManagerProvider>\n </ErrorBoundary>\n );\n};\n\ntype AppProps = Required<Pick<CreateAppOptions, 'placeholder'>> & {\n state: { ready: boolean; error: unknown };\n};\n\nconst App = ({ placeholder, state }: AppProps) => {\n const reactContexts = useCapabilities(Capabilities.ReactContext);\n const reactRoots = useCapabilities(Capabilities.ReactRoot);\n\n if (state.error) {\n // This trigger the error boundary to provide UI feedback for the startup error.\n throw state.error;\n }\n\n // TODO(wittjosiah): Consider using Suspense instead?\n if (!state.ready) {\n return <>{placeholder}</>;\n }\n\n const ComposedContext = composeContexts(reactContexts);\n return (\n <ComposedContext>\n {reactRoots.map(({ id, root: Component }) => (\n <Component key={id} />\n ))}\n </ComposedContext>\n );\n};\n\n// Default fallback does not use tailwind or theme.\nconst DefaultFallback = ({ error }: { error: Error }) => {\n return (\n <div style={{ padding: '1rem' }}>\n {/* TODO(wittjosiah): Link to docs for replacing default. */}\n <h1 style={{ fontSize: '1.2rem', fontWeight: 700, margin: '0.5rem 0' }}>{error.message}</h1>\n <pre>{error.stack}</pre>\n </div>\n );\n};\n\nconst composeContexts = (contexts: Capabilities.ReactContext[]) => {\n if (contexts.length === 0) {\n return ({ children }: PropsWithChildren) => <>{children}</>;\n }\n\n return topologicalSort(contexts)\n .map(({ context }) => context)\n .reduce((Acc, Next) => ({ children }) => (\n <Acc>\n <Next>{children}</Next>\n </Acc>\n ));\n};\n\nconst setupDevtools = (manager: PluginManager) => {\n (globalThis as any).composer ??= {};\n (globalThis as any).composer.manager = manager;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\ntype DependencyNode = {\n id: string;\n dependsOn?: string[];\n};\n\n/**\n * Topologically sorts a list of nodes based on their dependencies.\n */\n// TODO(wittjosiah): Factor out?\nexport const topologicalSort = <T extends DependencyNode>(nodes: T[]): T[] => {\n const getDependencies = (nodeId: string, seen = new Set<string>(), path = new Set<string>()): string[] => {\n if (path.has(nodeId)) {\n throw new Error(`Circular dependency detected involving ${nodeId}`);\n }\n if (seen.has(nodeId)) {\n return [];\n }\n\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) {\n throw new Error(`Node ${nodeId} not found but is listed as a dependency`);\n }\n\n const newPath = new Set([...path, nodeId]);\n const newSeen = new Set([...seen, nodeId]);\n\n const dependsOn = node.dependsOn ?? [];\n return [...dependsOn.flatMap((depId) => getDependencies(depId, newSeen, newPath)), nodeId];\n };\n\n // Get all unique dependencies.\n const allDependencies = nodes\n .map((node) => node.id)\n .flatMap((id) => getDependencies(id))\n .filter((id, index, self) => self.indexOf(id) === index);\n\n // Map back to original nodes\n return allDependencies\n .map((id) => nodes.find((node) => node.id === id))\n .filter((node): node is T => node !== undefined);\n};\n"],
5
- "mappings": "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",
6
- "names": ["import_react", "import_signals_core", "PluginManagerContext", "createContext", "undefined", "usePluginManager", "useContext", "raise", "Error", "PluginManagerProvider", "Provider", "useCapabilities", "interfaceDef", "filter", "manager", "signal", "useMemo", "computed", "context", "requestCapabilities", "value", "useCapability", "requestCapability", "useIntentDispatcher", "Capabilities", "IntentDispatcher", "useAppGraph", "AppGraph", "useLayout", "Layout", "ErrorBoundary", "Component", "constructor", "props", "state", "error", "getDerivedStateFromError", "componentDidUpdate", "prevProps", "data", "resetError", "render", "React", "this", "fallback", "reset", "children", "setState", "useSurfaces", "surfaces", "ReactSurface", "flat", "findCandidates", "role", "Object", "values", "definition", "Array", "isArray", "includes", "toSorted", "byPosition", "isSurfaceAvailable", "candidates", "length", "Surface", "memo", "forwardRef", "id", "_id", "_data", "limit", "placeholder", "rest", "forwardedRef", "useDefaultValue", "definitions", "slice", "nodes", "map", "component", "ref", "key", "suspense", "Suspense", "displayName", "useIntentResolver", "module", "resolver", "useEffect", "contributeCapability", "interface", "IntentResolver", "implementation", "removeCapability", "topologicalSort", "getDependencies", "nodeId", "seen", "Set", "path", "has", "node", "find", "n", "newPath", "newSeen", "dependsOn", "flatMap", "depId", "allDependencies", "index", "self", "indexOf", "ENABLED_KEY", "createApp", "pluginManager", "pluginLoader", "_pluginLoader", "plugins", "core", "meta", "defaults", "DefaultFallback", "cacheEnabled", "plugin", "invariant", "create", "ready", "cached", "JSON", "parse", "localStorage", "getItem", "enabled", "PluginManager", "activation", "on", "event", "_state", "Events", "Startup", "effect", "setItem", "stringify", "setupDevtools", "activate", "SetupReactSurface", "App", "reactContexts", "ReactContext", "reactRoots", "ReactRoot", "ComposedContext", "composeContexts", "root", "div", "style", "padding", "h1", "fontSize", "fontWeight", "margin", "message", "pre", "stack", "contexts", "reduce", "Acc", "Next", "globalThis", "composer"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/react/PluginManagerProvider.ts", "../../../src/react/useCapabilities.ts", "../../../src/react/common.ts", "../../../src/react/ErrorBoundary.tsx", "../../../src/react/Surface.tsx", "../../../src/react/useIntentResolver.ts", "../../../src/App.tsx", "../../../src/helpers.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { createContext, useContext } from 'react';\n\nimport { raise } from '@dxos/debug';\n\nimport { type PluginManager } from '../core';\n\nconst PluginManagerContext = createContext<PluginManager | undefined>(undefined);\n\n/**\n * Get the plugin manager.\n */\nexport const usePluginManager = (): PluginManager =>\n useContext(PluginManagerContext) ?? raise(new Error('Missing PluginManagerContext'));\n\n/**\n * Context provider for a plugin manager.\n */\nexport const PluginManagerProvider = PluginManagerContext.Provider;\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { computed } from '@preact/signals-core';\nimport { useMemo } from 'react';\n\nimport { usePluginManager } from './PluginManagerProvider';\nimport { type InterfaceDef } from '../core';\n\n/**\n * Hook to request capabilities from the plugin context.\n * @returns An array of capabilities.\n */\nexport const useCapabilities = <T, U extends T = T>(\n interfaceDef: InterfaceDef<T>,\n filter?: (capability: T, moduleId: string) => capability is U,\n) => {\n const manager = usePluginManager();\n const signal = useMemo(\n () => computed(() => manager.context.requestCapabilities(interfaceDef, filter)),\n [interfaceDef],\n );\n\n return signal.value;\n};\n\n/**\n * Hook to request a capability from the plugin context.\n * @returns The capability.\n * @throws If no capability is found.\n */\nexport const useCapability = <T, U extends T = T>(\n interfaceDef: InterfaceDef<T>,\n filter?: (capability: T, moduleId: string) => capability is U,\n) => {\n const manager = usePluginManager();\n const signal = useMemo(() => computed(() => manager.context.requestCapability(interfaceDef, filter)), [interfaceDef]);\n return signal.value;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useCapability } from './useCapabilities';\nimport { Capabilities } from '../common';\n\nexport const useIntentDispatcher = () => useCapability(Capabilities.IntentDispatcher);\n\nexport const useAppGraph = () => useCapability(Capabilities.AppGraph);\n\nexport const useLayout = () => useCapability(Capabilities.Layout);\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { Component, type FC, type PropsWithChildren } from 'react';\n\ntype Props = PropsWithChildren<{ data?: any; fallback: FC<{ data?: any; error: Error; reset: () => void }> }>;\ntype State = { error: Error | undefined };\n\n/**\n * Surface error boundary.\n *\n * For basic usage prefer providing a fallback component to `Surface`.\n *\n * For more information on error boundaries, see:\n * https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary\n */\nexport class ErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { error: undefined };\n }\n\n static getDerivedStateFromError(error: Error) {\n return { error };\n }\n\n override componentDidUpdate(prevProps: Props): void {\n if (prevProps.data !== this.props.data) {\n this.resetError();\n }\n }\n\n override render() {\n if (this.state.error) {\n return <this.props.fallback data={this.props.data} error={this.state.error} reset={this.resetError} />;\n }\n\n return this.props.children;\n }\n\n private resetError() {\n this.setState({ error: undefined });\n }\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { memo, forwardRef, Suspense, useMemo } from 'react';\n\nimport { useDefaultValue } from '@dxos/react-hooks';\nimport { byPosition } from '@dxos/util';\n\nimport { ErrorBoundary } from './ErrorBoundary';\nimport { useCapabilities } from './useCapabilities';\nimport { Capabilities, type SurfaceDefinition, type SurfaceProps } from '../common';\nimport { type PluginsContext } from '../core';\n\n/**\n * @internal\n */\nexport const useSurfaces = () => {\n const surfaces = useCapabilities(Capabilities.ReactSurface);\n return useMemo(() => surfaces.flat(), [surfaces]);\n};\n\nconst findCandidates = (surfaces: SurfaceDefinition[], { role, data }: Pick<SurfaceProps, 'role' | 'data'>) => {\n return Object.values(surfaces)\n .filter((definition) =>\n Array.isArray(definition.role) ? definition.role.includes(role) : definition.role === role,\n )\n .filter(({ filter }) => (filter ? filter(data ?? {}) : true))\n .toSorted(byPosition);\n};\n\n/**\n * @returns `true` if there is a contributed surface which matches the specified role & data, `false` otherwise.\n */\nexport const isSurfaceAvailable = (context: PluginsContext, { role, data }: Pick<SurfaceProps, 'role' | 'data'>) => {\n const surfaces = context.requestCapabilities(Capabilities.ReactSurface);\n const candidates = findCandidates(surfaces.flat(), { role, data });\n return candidates.length > 0;\n};\n\n/**\n * A surface is a named region of the screen that can be populated by plugins.\n */\nexport const Surface = memo(\n forwardRef<HTMLElement, SurfaceProps>(\n ({ id: _id, role, data: _data, limit, fallback, placeholder, ...rest }, forwardedRef) => {\n // TODO(wittjosiah): This will make all surfaces depend on a single signal.\n // This isn't ideal because it means that any change to the data will cause all surfaces to re-render.\n // This effectively means that plugin modules which contribute surfaces need to all be activated at startup.\n // This should be fine for now because it's how it worked prior to capabilities api anyways.\n // In the future, it would be nice to be able to bucket the surface contributions by role.\n const surfaces = useSurfaces();\n const data = useDefaultValue(_data, () => ({}));\n\n // NOTE: Memoizing the candidates makes the surface not re-render based on reactivity within data.\n const definitions = findCandidates(surfaces, { role, data });\n const candidates = limit ? definitions.slice(0, limit) : definitions;\n const nodes = candidates.map(({ component: Component, id }) => (\n <Component ref={forwardedRef} key={id} id={id} role={role} data={data} limit={limit} {...rest} />\n ));\n\n const suspense = placeholder ? <Suspense fallback={placeholder}>{nodes}</Suspense> : nodes;\n\n return fallback ? (\n <ErrorBoundary data={data} fallback={fallback}>\n {suspense}\n </ErrorBoundary>\n ) : (\n suspense\n );\n },\n ),\n);\n\nSurface.displayName = 'Surface';\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { useEffect } from 'react';\n\nimport { Capabilities } from '../common';\nimport { type AnyIntentResolver } from '../plugin-intent';\nimport { usePluginManager } from '../react';\n\nexport const useIntentResolver = (module: string, resolver: AnyIntentResolver) => {\n const manager = usePluginManager();\n useEffect(() => {\n manager.context.contributeCapability({\n module,\n interface: Capabilities.IntentResolver,\n implementation: resolver,\n });\n\n return () => manager.context.removeCapability(Capabilities.IntentResolver, resolver);\n }, [module, resolver]);\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { effect } from '@preact/signals-core';\nimport React, { type PropsWithChildren, type ReactNode } from 'react';\n\nimport { invariant } from '@dxos/invariant';\nimport { create } from '@dxos/live-object';\n\nimport { Capabilities, Events } from './common';\nimport { PluginManager, type PluginManagerOptions, type Plugin } from './core';\nimport { topologicalSort } from './helpers';\nimport { ErrorBoundary, PluginManagerProvider, useCapabilities } from './react';\n\nconst ENABLED_KEY = 'dxos.org/app-framework/enabled';\n\nexport type CreateAppOptions = {\n pluginManager?: PluginManager;\n pluginLoader?: PluginManagerOptions['pluginLoader'];\n plugins?: Plugin[];\n core?: string[];\n defaults?: string[];\n placeholder?: ReactNode;\n fallback?: ErrorBoundary['props']['fallback'];\n cacheEnabled?: boolean;\n};\n\n/**\n * Expected usage is for this to be the entrypoint of the application.\n * Initializes plugins and renders the root components.\n *\n * @example\n * const plugins = [LayoutPlugin(), MyPlugin()];\n * const core = [LayoutPluginId];\n * const default = [MyPluginId];\n * const fallback = <div>Initializing Plugins...</div>;\n * const App = createApp({ plugins, core, default, fallback });\n * createRoot(document.getElementById('root')!).render(\n * <StrictMode>\n * <App />\n * </StrictMode>,\n * );\n *\n * @param params.pluginLoader A function which loads new plugins.\n * @param params.plugins All plugins available to the application.\n * @param params.core Core plugins which will always be enabled.\n * @param params.defaults Default plugins are enabled by default but can be disabled by the user.\n * @param params.placeholder Placeholder component to render during startup.\n * @param params.fallback Fallback component to render if an error occurs during startup.\n * @param params.cacheEnabled Whether to cache enabled plugins in localStorage.\n */\nexport const createApp = ({\n pluginManager,\n pluginLoader: _pluginLoader,\n plugins = [],\n core = plugins.map(({ meta }) => meta.id),\n defaults = [],\n placeholder = null,\n fallback = DefaultFallback,\n cacheEnabled = false,\n}: CreateAppOptions) => {\n // TODO(wittjosiah): Provide a custom plugin loader which supports loading via url.\n const pluginLoader =\n _pluginLoader ??\n ((id: string) => {\n const plugin = plugins.find((plugin) => plugin.meta.id === id);\n invariant(plugin, `Plugin not found: ${id}`);\n return plugin;\n });\n\n const state = create({ ready: false, error: null });\n const cached: string[] = JSON.parse(localStorage.getItem(ENABLED_KEY) ?? '[]');\n const enabled = cacheEnabled && cached.length > 0 ? cached : defaults;\n const manager = pluginManager ?? new PluginManager({ pluginLoader, plugins, core, enabled });\n\n manager.activation.on(({ event, state: _state, error }) => {\n // Once the app is ready the first time, don't show the fallback again.\n if (!state.ready && event === Events.Startup.id) {\n state.ready = _state === 'activated';\n }\n\n if (error && !state.ready && !state.error) {\n state.error = error;\n }\n });\n\n effect(() => {\n cacheEnabled && localStorage.setItem(ENABLED_KEY, JSON.stringify(manager.enabled));\n });\n\n manager.context.contributeCapability({\n interface: Capabilities.PluginManager,\n implementation: manager,\n module: 'dxos.org/app-framework/plugin-manager',\n });\n\n setupDevtools(manager);\n\n // TODO(wittjosiah): Factor out such that this could be called per surface role when attempting to render.\n void manager.activate(Events.SetupReactSurface);\n void manager.activate(Events.Startup);\n\n return () => (\n <ErrorBoundary fallback={fallback}>\n <PluginManagerProvider value={manager}>\n <App placeholder={placeholder} state={state} />\n </PluginManagerProvider>\n </ErrorBoundary>\n );\n};\n\ntype AppProps = Required<Pick<CreateAppOptions, 'placeholder'>> & {\n state: { ready: boolean; error: unknown };\n};\n\nconst App = ({ placeholder, state }: AppProps) => {\n const reactContexts = useCapabilities(Capabilities.ReactContext);\n const reactRoots = useCapabilities(Capabilities.ReactRoot);\n\n if (state.error) {\n // This trigger the error boundary to provide UI feedback for the startup error.\n throw state.error;\n }\n\n // TODO(wittjosiah): Consider using Suspense instead?\n if (!state.ready) {\n return <>{placeholder}</>;\n }\n\n const ComposedContext = composeContexts(reactContexts);\n return (\n <ComposedContext>\n {reactRoots.map(({ id, root: Component }) => (\n <Component key={id} />\n ))}\n </ComposedContext>\n );\n};\n\n// Default fallback does not use tailwind or theme.\nconst DefaultFallback = ({ error }: { error: Error }) => {\n return (\n <div style={{ padding: '1rem' }}>\n {/* TODO(wittjosiah): Link to docs for replacing default. */}\n <h1 style={{ fontSize: '1.2rem', fontWeight: 700, margin: '0.5rem 0' }}>{error.message}</h1>\n <pre>{error.stack}</pre>\n </div>\n );\n};\n\nconst composeContexts = (contexts: Capabilities.ReactContext[]) => {\n if (contexts.length === 0) {\n return ({ children }: PropsWithChildren) => <>{children}</>;\n }\n\n return topologicalSort(contexts)\n .map(({ context }) => context)\n .reduce((Acc, Next) => ({ children }) => (\n <Acc>\n <Next>{children}</Next>\n </Acc>\n ));\n};\n\nconst setupDevtools = (manager: PluginManager) => {\n (globalThis as any).composer ??= {};\n (globalThis as any).composer.manager = manager;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\ntype DependencyNode = {\n id: string;\n dependsOn?: string[];\n};\n\n/**\n * Topologically sorts a list of nodes based on their dependencies.\n */\n// TODO(wittjosiah): Factor out?\nexport const topologicalSort = <T extends DependencyNode>(nodes: T[]): T[] => {\n const getDependencies = (nodeId: string, seen = new Set<string>(), path = new Set<string>()): string[] => {\n if (path.has(nodeId)) {\n throw new Error(`Circular dependency detected involving ${nodeId}`);\n }\n if (seen.has(nodeId)) {\n return [];\n }\n\n const node = nodes.find((n) => n.id === nodeId);\n if (!node) {\n throw new Error(`Node ${nodeId} not found but is listed as a dependency`);\n }\n\n const newPath = new Set([...path, nodeId]);\n const newSeen = new Set([...seen, nodeId]);\n\n const dependsOn = node.dependsOn ?? [];\n return [...dependsOn.flatMap((depId) => getDependencies(depId, newSeen, newPath)), nodeId];\n };\n\n // Get all unique dependencies.\n const allDependencies = nodes\n .map((node) => node.id)\n .flatMap((id) => getDependencies(id))\n .filter((id, index, self) => self.indexOf(id) === index);\n\n // Map back to original nodes\n return allDependencies\n .map((id) => nodes.find((node) => node.id === id))\n .filter((node): node is T => node !== undefined);\n};\n"],
5
- "mappings": "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",
6
- "names": ["createContext", "useContext", "raise", "PluginManagerContext", "createContext", "undefined", "usePluginManager", "useContext", "raise", "Error", "PluginManagerProvider", "Provider", "computed", "useMemo", "useCapabilities", "interfaceDef", "filter", "manager", "usePluginManager", "signal", "useMemo", "computed", "context", "requestCapabilities", "value", "useCapability", "requestCapability", "useIntentDispatcher", "useCapability", "Capabilities", "IntentDispatcher", "useAppGraph", "AppGraph", "useLayout", "Layout", "React", "Component", "ErrorBoundary", "Component", "constructor", "props", "state", "error", "undefined", "getDerivedStateFromError", "componentDidUpdate", "prevProps", "data", "resetError", "render", "this", "fallback", "reset", "children", "setState", "React", "memo", "forwardRef", "Suspense", "useMemo", "useDefaultValue", "byPosition", "useSurfaces", "surfaces", "useCapabilities", "Capabilities", "ReactSurface", "useMemo", "flat", "findCandidates", "role", "data", "Object", "values", "filter", "definition", "Array", "isArray", "includes", "toSorted", "byPosition", "isSurfaceAvailable", "context", "requestCapabilities", "candidates", "length", "Surface", "memo", "forwardRef", "id", "_id", "_data", "limit", "fallback", "placeholder", "rest", "forwardedRef", "useDefaultValue", "definitions", "slice", "nodes", "map", "component", "Component", "React", "ref", "key", "suspense", "Suspense", "ErrorBoundary", "displayName", "useEffect", "useIntentResolver", "module", "resolver", "manager", "usePluginManager", "useEffect", "context", "contributeCapability", "interface", "Capabilities", "IntentResolver", "implementation", "removeCapability", "effect", "React", "invariant", "create", "topologicalSort", "nodes", "getDependencies", "nodeId", "seen", "Set", "path", "has", "Error", "node", "find", "n", "id", "newPath", "newSeen", "dependsOn", "flatMap", "depId", "allDependencies", "map", "filter", "index", "self", "indexOf", "undefined", "ENABLED_KEY", "createApp", "pluginManager", "pluginLoader", "_pluginLoader", "plugins", "core", "map", "meta", "id", "defaults", "placeholder", "fallback", "DefaultFallback", "cacheEnabled", "plugin", "find", "invariant", "state", "create", "ready", "error", "cached", "JSON", "parse", "localStorage", "getItem", "enabled", "length", "manager", "PluginManager", "activation", "on", "event", "_state", "Events", "Startup", "effect", "setItem", "stringify", "context", "contributeCapability", "interface", "Capabilities", "implementation", "module", "setupDevtools", "activate", "SetupReactSurface", "React", "ErrorBoundary", "PluginManagerProvider", "value", "App", "reactContexts", "useCapabilities", "ReactContext", "reactRoots", "ReactRoot", "ComposedContext", "composeContexts", "root", "Component", "key", "div", "style", "padding", "h1", "fontSize", "fontWeight", "margin", "message", "pre", "stack", "contexts", "children", "topologicalSort", "reduce", "Acc", "Next", "globalThis", "composer"]
7
- }