@dxos/app-framework 0.3.6 → 0.3.7-main.0bad7ea
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.
- package/dist/lib/browser/chunk-C2K6M6WC.mjs +27 -0
- package/dist/lib/browser/chunk-C2K6M6WC.mjs.map +7 -0
- package/dist/lib/browser/chunk-CFZ5JAJF.mjs +18 -0
- package/dist/lib/browser/chunk-CFZ5JAJF.mjs.map +7 -0
- package/dist/lib/browser/chunk-WDA7VA54.mjs +26 -0
- package/dist/lib/browser/chunk-WDA7VA54.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +142 -190
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/plugin-CBPJO5NB.mjs +63 -0
- package/dist/lib/browser/plugin-CBPJO5NB.mjs.map +7 -0
- package/dist/lib/browser/plugin-XEJ5RYCP.mjs +39 -0
- package/dist/lib/browser/plugin-XEJ5RYCP.mjs.map +7 -0
- package/dist/lib/node/index.cjs +334 -188
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/App.d.ts +13 -3
- package/dist/types/src/App.d.ts.map +1 -1
- package/dist/types/src/plugins/IntentPlugin/index.d.ts +1 -1
- package/dist/types/src/plugins/IntentPlugin/index.d.ts.map +1 -1
- package/dist/types/src/plugins/IntentPlugin/meta.d.ts +5 -0
- package/dist/types/src/plugins/IntentPlugin/meta.d.ts.map +1 -0
- package/dist/types/src/plugins/IntentPlugin/plugin.d.ts +9 -0
- package/dist/types/src/plugins/IntentPlugin/plugin.d.ts.map +1 -0
- package/dist/types/src/plugins/IntentPlugin/{IntentPlugin.d.ts → provides.d.ts} +2 -7
- package/dist/types/src/plugins/IntentPlugin/provides.d.ts.map +1 -0
- package/dist/types/src/plugins/PluginHost/PluginContext.d.ts +27 -3
- package/dist/types/src/plugins/PluginHost/PluginContext.d.ts.map +1 -1
- package/dist/types/src/plugins/PluginHost/PluginHost.d.ts +7 -4
- package/dist/types/src/plugins/PluginHost/PluginHost.d.ts.map +1 -1
- package/dist/types/src/plugins/PluginHost/plugin.d.ts +49 -1
- package/dist/types/src/plugins/PluginHost/plugin.d.ts.map +1 -1
- package/dist/types/src/plugins/SurfacePlugin/Surface.d.ts +9 -4
- package/dist/types/src/plugins/SurfacePlugin/Surface.d.ts.map +1 -1
- package/dist/types/src/plugins/SurfacePlugin/SurfaceRootContext.d.ts +8 -2
- package/dist/types/src/plugins/SurfacePlugin/SurfaceRootContext.d.ts.map +1 -1
- package/dist/types/src/plugins/SurfacePlugin/index.d.ts +1 -1
- package/dist/types/src/plugins/SurfacePlugin/index.d.ts.map +1 -1
- package/dist/types/src/plugins/SurfacePlugin/meta.d.ts +5 -0
- package/dist/types/src/plugins/SurfacePlugin/meta.d.ts.map +1 -0
- package/dist/types/src/plugins/SurfacePlugin/plugin.d.ts +8 -0
- package/dist/types/src/plugins/SurfacePlugin/plugin.d.ts.map +1 -0
- package/dist/types/src/plugins/SurfacePlugin/{SurfacePlugin.d.ts → provides.d.ts} +2 -6
- package/dist/types/src/plugins/SurfacePlugin/provides.d.ts.map +1 -0
- package/package.json +8 -6
- package/src/App.tsx +24 -6
- package/src/plugins/IntentPlugin/index.ts +2 -1
- package/src/plugins/IntentPlugin/meta.ts +9 -0
- package/src/plugins/IntentPlugin/{IntentPlugin.tsx → plugin.tsx} +8 -22
- package/src/plugins/IntentPlugin/provides.ts +23 -0
- package/src/plugins/PluginHost/PluginContext.tsx +36 -5
- package/src/plugins/PluginHost/PluginHost.tsx +59 -98
- package/src/plugins/PluginHost/plugin.ts +31 -1
- package/src/plugins/SurfacePlugin/Surface.tsx +34 -27
- package/src/plugins/SurfacePlugin/SurfaceRootContext.tsx +11 -2
- package/src/plugins/SurfacePlugin/index.ts +2 -1
- package/src/plugins/SurfacePlugin/meta.ts +9 -0
- package/src/plugins/SurfacePlugin/plugin.tsx +36 -0
- package/src/plugins/SurfacePlugin/provides.ts +25 -0
- package/tsconfig.json +3 -0
- package/dist/types/src/plugins/IntentPlugin/IntentPlugin.d.ts.map +0 -1
- package/dist/types/src/plugins/SurfacePlugin/SurfacePlugin.d.ts.map +0 -1
- package/src/plugins/SurfacePlugin/SurfacePlugin.tsx +0 -53
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/PluginHost/plugin.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/PluginHost/plugin.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAEnD;;;GAGG;AACH,MAAM,MAAM,cAAc,CAAC,SAAS,IAAI,SAAS,GAAG;IAClD;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC;IAKhC,IAAI,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC;CAC9B,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,MAAM,CAAC,SAAS,GAAG,EAAE,IAAI;IACnC,IAAI,EAAE;QACJ;;;;;;WAMG;QACH,EAAE,EAAE,MAAM,CAAC;QAEX;;;;WAIG;QAEH,OAAO,CAAC,EAAE,MAAM,CAAC;QAEjB;;WAEG;QACH,IAAI,CAAC,EAAE,MAAM,CAAC;QAEd;;WAEG;QACH,WAAW,CAAC,EAAE,MAAM,CAAC;QAErB;;WAEG;QAEH,aAAa,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC;KAC/B,CAAC;IAEF;;OAEG;IACH,QAAQ,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;CACrC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,CAAC,SAAS,GAAG,EAAE,EAAE,mBAAmB,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG;IAClG;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC;IAEzC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAEhE;;;;;OAKG;IACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC;AAEF,eAAO,MAAM,UAAU,SAAU,MAAM,CAAC,MAAM,CAAC;IAvE3C;;;;;;OAMG;QACC,MAAM;IAEV;;;;OAIG;;IAIH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;CA0CiD,CAAC;AAEzD,KAAK,UAAU,CAAC,CAAC,IAAI,MAAM,OAAO,CAAC;IAAE,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,gBAAgB,CAAA;CAAE,CAAC,CAAC;AAEhF,yBAAiB,MAAM,CAAC;IACf,MAAM,IAAI,yFAKhB,CAAC;CACH"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { type FC } from 'react';
|
|
1
|
+
import React, { type FC, type PropsWithChildren } from 'react';
|
|
2
2
|
import { ErrorBoundary } from './ErrorBoundary';
|
|
3
3
|
/**
|
|
4
4
|
* Direction determines how multiple components are laid out.
|
|
5
5
|
*/
|
|
6
6
|
export type Direction = 'inline' | 'inline-reverse' | 'block' | 'block-reverse';
|
|
7
|
-
export type SurfaceProps = {
|
|
7
|
+
export type SurfaceProps = PropsWithChildren<{
|
|
8
8
|
/**
|
|
9
9
|
* Role defines how the data should be rendered.
|
|
10
10
|
*/
|
|
@@ -40,9 +40,14 @@ export type SurfaceProps = {
|
|
|
40
40
|
* NOTE: This is not yet implemented.
|
|
41
41
|
*/
|
|
42
42
|
direction?: Direction;
|
|
43
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Additional props to pass to the component.
|
|
45
|
+
* These props are not used by Surface itself but may be used by components which resolve the surface.
|
|
46
|
+
*/
|
|
47
|
+
[key: string]: unknown;
|
|
48
|
+
}>;
|
|
44
49
|
/**
|
|
45
50
|
* A surface is a named region of the screen that can be populated by plugins.
|
|
46
51
|
*/
|
|
47
|
-
export declare const Surface:
|
|
52
|
+
export declare const Surface: React.ForwardRefExoticComponent<Pick<SurfaceProps, string | number> & React.RefAttributes<HTMLElement>>;
|
|
48
53
|
//# sourceMappingURL=Surface.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Surface.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/SurfacePlugin/Surface.tsx"],"names":[],"mappings":"AAIA,
|
|
1
|
+
{"version":3,"file":"Surface.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/SurfacePlugin/Surface.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAc,KAAK,EAAE,EAA+C,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAGxH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,gBAAgB,GAAG,OAAO,GAAG,eAAe,CAAC;AAEhF,MAAM,MAAM,YAAY,GAAG,iBAAiB,CAAC;IAC3C;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE/B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC;IAEnE;;;OAGG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC;IAE9C;;OAEG;IACH,eAAe,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;IAEzB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE3B;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB;;;OAGG;IACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,OAAO,yGAkBnB,CAAC"}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
import { type Provider, type ReactNode } from 'react';
|
|
1
|
+
import { type Provider, type ReactNode, type ForwardedRef } from 'react';
|
|
2
|
+
import { type SurfaceProps } from './Surface';
|
|
3
|
+
type WithRequiredProperty<Type, Key extends keyof Type> = Type & {
|
|
4
|
+
[Property in Key]-?: Type[Property];
|
|
5
|
+
};
|
|
6
|
+
type SurfaceComponentProps = WithRequiredProperty<SurfaceProps, 'data'>;
|
|
2
7
|
/**
|
|
3
8
|
* Function which resolves a Surface.
|
|
4
9
|
*
|
|
5
10
|
* If a null value is returned, the rendering is deferred to other plugins.
|
|
6
11
|
*/
|
|
7
|
-
export type SurfaceComponent = (
|
|
12
|
+
export type SurfaceComponent = (props: SurfaceComponentProps, forwardedRef: ForwardedRef<HTMLElement>) => ReactNode;
|
|
8
13
|
export type SurfaceRootContext = {
|
|
9
14
|
components: Record<string, SurfaceComponent>;
|
|
10
15
|
};
|
|
11
16
|
export declare const useSurface: () => SurfaceRootContext;
|
|
12
17
|
export declare const SurfaceProvider: Provider<SurfaceRootContext>;
|
|
18
|
+
export {};
|
|
13
19
|
//# sourceMappingURL=SurfaceRootContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SurfaceRootContext.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/SurfacePlugin/SurfaceRootContext.tsx"],"names":[],"mappings":"AAIA,OAAO,EAA2C,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"SurfaceRootContext.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/SurfacePlugin/SurfaceRootContext.tsx"],"names":[],"mappings":"AAIA,OAAO,EAA2C,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAElH,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAG9C,KAAK,oBAAoB,CAAC,IAAI,EAAE,GAAG,SAAS,MAAM,IAAI,IAAI,IAAI,GAAG;KAC9D,QAAQ,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;CACpC,CAAC;AAEF,KAAK,qBAAqB,GAAG,oBAAoB,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;AAExE;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,YAAY,CAAC,WAAW,CAAC,KAAK,SAAS,CAAC;AAEpH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC9C,CAAC;AAIF,eAAO,MAAM,UAAU,0BAAuC,CAAC;AAE/D,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,kBAAkB,CAA+B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/SurfacePlugin/index.ts"],"names":[],"mappings":"AAIA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/SurfacePlugin/index.ts"],"names":[],"mappings":"AAIA,cAAc,YAAY,CAAC;AAE3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/SurfacePlugin/meta.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,WAAW;;CAEhB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type SurfacePluginProvides } from './provides';
|
|
2
|
+
import type { PluginDefinition } from '../PluginHost';
|
|
3
|
+
/**
|
|
4
|
+
* Provides a registry of surface components.
|
|
5
|
+
*/
|
|
6
|
+
declare const SurfacePlugin: () => PluginDefinition<SurfacePluginProvides>;
|
|
7
|
+
export default SurfacePlugin;
|
|
8
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/SurfacePlugin/plugin.tsx"],"names":[],"mappings":"AASA,OAAO,EAAsB,KAAK,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGtD;;GAEG;AACH,QAAA,MAAM,aAAa,QAAO,iBAAiB,qBAAqB,CAiB/D,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type SurfaceComponent, type SurfaceRootContext } from './SurfaceRootContext';
|
|
2
|
-
import type
|
|
2
|
+
import { type Plugin } from '../PluginHost';
|
|
3
3
|
export type SurfaceProvides = {
|
|
4
4
|
surface: {
|
|
5
5
|
/**
|
|
@@ -13,8 +13,4 @@ export type SurfacePluginProvides = {
|
|
|
13
13
|
};
|
|
14
14
|
export declare const parseRootSurfacePlugin: (plugin?: Plugin) => Plugin<SurfacePluginProvides> | undefined;
|
|
15
15
|
export declare const parseSurfacePlugin: (plugin?: Plugin) => Plugin<SurfaceProvides> | undefined;
|
|
16
|
-
|
|
17
|
-
* Provides a registry of surface components.
|
|
18
|
-
*/
|
|
19
|
-
export declare const SurfacePlugin: () => PluginDefinition<SurfacePluginProvides>;
|
|
20
|
-
//# sourceMappingURL=SurfacePlugin.d.ts.map
|
|
16
|
+
//# sourceMappingURL=provides.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provides.d.ts","sourceRoot":"","sources":["../../../../../src/plugins/SurfacePlugin/provides.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE;QACP;;WAEG;QACH,SAAS,EAAE,gBAAgB,CAAC;KAC7B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,kBAAkB,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,sBAAsB,YAAa,MAAM,8CACkD,CAAC;AAEzG,eAAO,MAAM,kBAAkB,YAAa,MAAM,wCAC+C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/app-framework",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7-main.0bad7ea",
|
|
4
4
|
"description": "A framework for building applications from composible plugins.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -12,14 +12,16 @@
|
|
|
12
12
|
},
|
|
13
13
|
"types": "dist/types/src/index.d.ts",
|
|
14
14
|
"dependencies": {
|
|
15
|
+
"@phosphor-icons/react": "^2.0.5",
|
|
15
16
|
"@preact/signals-react": "^1.3.6",
|
|
16
17
|
"deepsignal": "1.4.0-shallow.0",
|
|
17
18
|
"zod": "^3.19.1",
|
|
18
|
-
"@dxos/
|
|
19
|
-
"@dxos/
|
|
20
|
-
"@dxos/debug": "0.3.
|
|
21
|
-
"@dxos/
|
|
22
|
-
"@dxos/
|
|
19
|
+
"@dxos/app-graph": "0.3.7-main.0bad7ea",
|
|
20
|
+
"@dxos/async": "0.3.7-main.0bad7ea",
|
|
21
|
+
"@dxos/debug": "0.3.7-main.0bad7ea",
|
|
22
|
+
"@dxos/invariant": "0.3.7-main.0bad7ea",
|
|
23
|
+
"@dxos/local-storage": "0.3.7-main.0bad7ea",
|
|
24
|
+
"@dxos/log": "0.3.7-main.0bad7ea"
|
|
23
25
|
},
|
|
24
26
|
"devDependencies": {
|
|
25
27
|
"@types/react": "^18.0.21",
|
package/src/App.tsx
CHANGED
|
@@ -6,28 +6,46 @@ import React from 'react';
|
|
|
6
6
|
|
|
7
7
|
import { invariant } from '@dxos/invariant';
|
|
8
8
|
|
|
9
|
-
import { type BootstrapPluginsParams, PluginHost,
|
|
9
|
+
import { type BootstrapPluginsParams, PluginHost, Plugin } from './plugins';
|
|
10
|
+
import IntentMeta from './plugins/IntentPlugin/meta';
|
|
11
|
+
import SurfaceMeta from './plugins/SurfacePlugin/meta';
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Expected usage is for this to be the entrypoint of the application.
|
|
13
15
|
* Initializes plugins and renders the root components.
|
|
14
16
|
*
|
|
15
17
|
* @example
|
|
18
|
+
* const order = [LayoutMeta, MyPluginMeta];
|
|
19
|
+
* const plugins = {
|
|
20
|
+
* [LayoutMeta.id]: Plugin.lazy(() => import('./plugins/LayoutPlugin/plugin')),
|
|
21
|
+
* [MyPluginMeta.id]: Plugin.lazy(() => import('./plugins/MyPlugin/plugin')),
|
|
22
|
+
* };
|
|
23
|
+
* const core = [LayoutMeta.id];
|
|
24
|
+
* const default = [MyPluginMeta.id];
|
|
16
25
|
* const fallback = <div>Initializing Plugins...</div>;
|
|
17
|
-
* const App = createApp({ plugins, fallback });
|
|
26
|
+
* const App = createApp({ order, plugins, core, default, fallback });
|
|
18
27
|
* createRoot(document.getElementById('root')!).render(
|
|
19
28
|
* <StrictMode>
|
|
20
29
|
* <App />
|
|
21
30
|
* </StrictMode>,
|
|
22
31
|
* );
|
|
23
32
|
*
|
|
24
|
-
* @param params.
|
|
33
|
+
* @param params.order Total ordering of plugins.
|
|
34
|
+
* @param params.plugins All plugins available to the application.
|
|
35
|
+
* @param params.core Core plugins which will always be enabled.
|
|
36
|
+
* @param params.default Default plugins are enabled by default but can be disabled by the user.
|
|
25
37
|
* @param params.fallback Fallback component to render while plugins are initializing.
|
|
26
38
|
*/
|
|
27
|
-
export const createApp = ({ plugins,
|
|
39
|
+
export const createApp = ({ order, plugins, core = [], ...params }: BootstrapPluginsParams) => {
|
|
28
40
|
const host = PluginHost({
|
|
29
|
-
|
|
30
|
-
|
|
41
|
+
order: [SurfaceMeta, IntentMeta, ...order],
|
|
42
|
+
plugins: {
|
|
43
|
+
...plugins,
|
|
44
|
+
[SurfaceMeta.id]: Plugin.lazy(() => import('./plugins/SurfacePlugin/plugin')),
|
|
45
|
+
[IntentMeta.id]: Plugin.lazy(() => import('./plugins/IntentPlugin/plugin')),
|
|
46
|
+
},
|
|
47
|
+
core: [SurfaceMeta.id, IntentMeta.id, ...core],
|
|
48
|
+
...params,
|
|
31
49
|
});
|
|
32
50
|
|
|
33
51
|
invariant(host.provides?.context);
|
|
@@ -6,37 +6,21 @@ import { deepSignal } from 'deepsignal/react';
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
|
|
8
8
|
import { type IntentContext, IntentProvider } from './IntentContext';
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
9
|
+
import type { Intent } from './intent';
|
|
10
|
+
import IntentMeta from './meta';
|
|
11
|
+
import { type IntentPluginProvides, type IntentResolverProvides, parseIntentResolverPlugin } from './provides';
|
|
12
|
+
import type { PluginDefinition } from '../PluginHost';
|
|
11
13
|
import { filterPlugins, findPlugin } from '../helpers';
|
|
12
14
|
|
|
13
|
-
export type IntentResolverProvides = {
|
|
14
|
-
intent: {
|
|
15
|
-
resolver: (intent: Intent, plugins: Plugin[]) => any;
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export type IntentPluginProvides = {
|
|
20
|
-
intent: IntentContext;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const parseIntentPlugin = (plugin: Plugin) =>
|
|
24
|
-
(plugin.provides as any).intent?.dispatch ? (plugin as Plugin<IntentPluginProvides>) : undefined;
|
|
25
|
-
|
|
26
|
-
export const parseIntentResolverPlugin = (plugin: Plugin) =>
|
|
27
|
-
(plugin.provides as any).intent?.resolver ? (plugin as Plugin<IntentResolverProvides>) : undefined;
|
|
28
|
-
|
|
29
15
|
/**
|
|
30
16
|
* Allows plugins to register intent handlers and routes sent intents to the appropriate plugin.
|
|
31
17
|
* Inspired by https://developer.android.com/reference/android/content/Intent.
|
|
32
18
|
*/
|
|
33
|
-
|
|
19
|
+
const IntentPlugin = (): PluginDefinition<IntentPluginProvides> => {
|
|
34
20
|
const state = deepSignal<IntentContext>({ dispatch: async () => {} });
|
|
35
21
|
|
|
36
22
|
return {
|
|
37
|
-
meta:
|
|
38
|
-
id: 'dxos.org/plugin/intent',
|
|
39
|
-
},
|
|
23
|
+
meta: IntentMeta,
|
|
40
24
|
ready: async (plugins) => {
|
|
41
25
|
// Dispatch intent to associated plugin.
|
|
42
26
|
const dispatch = async (intent: Intent) => {
|
|
@@ -70,3 +54,5 @@ export const IntentPlugin = (): PluginDefinition<IntentPluginProvides> => {
|
|
|
70
54
|
},
|
|
71
55
|
};
|
|
72
56
|
};
|
|
57
|
+
|
|
58
|
+
export default IntentPlugin;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type IntentContext } from './IntentContext';
|
|
6
|
+
import { type Intent } from './intent';
|
|
7
|
+
import { type Plugin } from '../PluginHost';
|
|
8
|
+
|
|
9
|
+
export type IntentResolverProvides = {
|
|
10
|
+
intent: {
|
|
11
|
+
resolver: (intent: Intent, plugins: Plugin[]) => any;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type IntentPluginProvides = {
|
|
16
|
+
intent: IntentContext;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const parseIntentPlugin = (plugin: Plugin) =>
|
|
20
|
+
(plugin.provides as any).intent?.dispatch ? (plugin as Plugin<IntentPluginProvides>) : undefined;
|
|
21
|
+
|
|
22
|
+
export const parseIntentResolverPlugin = (plugin: Plugin) =>
|
|
23
|
+
(plugin.provides as any).intent?.resolver ? (plugin as Plugin<IntentResolverProvides>) : undefined;
|
|
@@ -4,21 +4,52 @@
|
|
|
4
4
|
|
|
5
5
|
import { type Context, type Provider, createContext, useContext } from 'react';
|
|
6
6
|
|
|
7
|
-
import { type Plugin
|
|
7
|
+
import { type Plugin } from './plugin';
|
|
8
8
|
import { findPlugin, resolvePlugin } from '../helpers';
|
|
9
9
|
|
|
10
10
|
export type PluginContext = {
|
|
11
|
+
/**
|
|
12
|
+
* All plugins are ready.
|
|
13
|
+
*/
|
|
11
14
|
ready: boolean;
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Ids of plugins which are enabled on this device.
|
|
18
|
+
*/
|
|
19
|
+
enabled: string[];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Initialized and ready plugins.
|
|
23
|
+
*/
|
|
14
24
|
plugins: Plugin[];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* All available plugins.
|
|
28
|
+
*/
|
|
29
|
+
available: Plugin['meta'][];
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Mark plugin as enabled.
|
|
33
|
+
*
|
|
34
|
+
* Requires reload to take effect.
|
|
35
|
+
*/
|
|
36
|
+
enablePlugin: (id: string) => void;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Mark plugin as disabled.
|
|
40
|
+
*
|
|
41
|
+
* Requires reload to take effect.
|
|
42
|
+
*/
|
|
43
|
+
disablePlugin: (id: string) => void;
|
|
15
44
|
};
|
|
16
45
|
|
|
17
46
|
const PluginContext: Context<PluginContext> = createContext<PluginContext>({
|
|
18
47
|
ready: false,
|
|
19
|
-
|
|
20
|
-
loading: [],
|
|
48
|
+
enabled: [],
|
|
21
49
|
plugins: [],
|
|
50
|
+
available: [],
|
|
51
|
+
enablePlugin: () => {},
|
|
52
|
+
disablePlugin: () => {},
|
|
22
53
|
});
|
|
23
54
|
|
|
24
55
|
/**
|
|
@@ -2,17 +2,21 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { shallow } from 'deepsignal/react';
|
|
6
6
|
import React, { useEffect, type FC, type PropsWithChildren, type ReactNode } from 'react';
|
|
7
7
|
|
|
8
|
+
import { LocalStorageStore } from '@dxos/local-storage';
|
|
8
9
|
import { log } from '@dxos/log';
|
|
9
10
|
|
|
10
11
|
import { type PluginContext, PluginProvider } from './PluginContext';
|
|
11
12
|
import { type Plugin, type PluginDefinition, type PluginProvides } from './plugin';
|
|
12
13
|
|
|
13
14
|
export type BootstrapPluginsParams = {
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
order: PluginDefinition['meta'][];
|
|
16
|
+
plugins: Record<string, () => Promise<PluginDefinition>>;
|
|
17
|
+
core?: string[];
|
|
18
|
+
defaults?: string[];
|
|
19
|
+
fallback?: ReactNode;
|
|
16
20
|
};
|
|
17
21
|
|
|
18
22
|
export type PluginHostProvides = {
|
|
@@ -22,72 +26,96 @@ export type PluginHostProvides = {
|
|
|
22
26
|
export const parsePluginHost = (plugin: Plugin) =>
|
|
23
27
|
(plugin.provides as PluginHostProvides).plugins ? (plugin as Plugin<PluginHostProvides>) : undefined;
|
|
24
28
|
|
|
29
|
+
const PLUGIN_HOST = 'dxos.org/plugin/host';
|
|
30
|
+
|
|
25
31
|
/**
|
|
26
32
|
* Bootstraps an application by initializing plugins and rendering root components.
|
|
27
33
|
*/
|
|
28
34
|
export const PluginHost = ({
|
|
35
|
+
order,
|
|
29
36
|
plugins: definitions,
|
|
30
|
-
|
|
37
|
+
core = order.map(({ id }) => id),
|
|
38
|
+
defaults = [],
|
|
39
|
+
fallback = null,
|
|
31
40
|
}: BootstrapPluginsParams): PluginDefinition<PluginHostProvides> => {
|
|
32
|
-
const state =
|
|
41
|
+
const state = new LocalStorageStore<PluginContext>(PLUGIN_HOST, {
|
|
42
|
+
ready: false,
|
|
43
|
+
enabled: [...defaults],
|
|
44
|
+
plugins: [],
|
|
45
|
+
available: order.filter(({ id }) => !core.includes(id)),
|
|
46
|
+
enablePlugin: (id: string) => {
|
|
47
|
+
state.values.enabled = [...state.values.enabled, id];
|
|
48
|
+
},
|
|
49
|
+
disablePlugin: (id: string) => {
|
|
50
|
+
state.values.enabled = state.values.enabled.filter((enabled) => enabled !== id);
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
state.prop(state.values.$enabled!, 'enabled', LocalStorageStore.json);
|
|
33
55
|
|
|
34
56
|
return {
|
|
35
57
|
meta: {
|
|
36
|
-
id:
|
|
58
|
+
id: PLUGIN_HOST,
|
|
59
|
+
name: 'Plugin host',
|
|
37
60
|
},
|
|
38
61
|
provides: {
|
|
39
|
-
plugins: state,
|
|
40
|
-
context: ({ children }) => <PluginProvider value={state}>{children}</PluginProvider>,
|
|
62
|
+
plugins: state.values,
|
|
63
|
+
context: ({ children }) => <PluginProvider value={state.values}>{children}</PluginProvider>,
|
|
41
64
|
root: () => {
|
|
42
65
|
useEffect(() => {
|
|
43
|
-
log('initializing plugins', {
|
|
66
|
+
log('initializing plugins', { enabled: state.values.enabled });
|
|
44
67
|
const timeout = setTimeout(async () => {
|
|
45
|
-
|
|
68
|
+
const enabledIds = [...core, ...state.values.enabled].sort((a, b) => {
|
|
69
|
+
const indexA = order.findIndex(({ id }) => id === a);
|
|
70
|
+
const indexB = order.findIndex(({ id }) => id === b);
|
|
71
|
+
return indexA - indexB;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const enabled = await Promise.all(
|
|
75
|
+
enabledIds
|
|
76
|
+
.map((id) => definitions[id])
|
|
77
|
+
// If local storage indicates a plugin is enabled, but it is not available, ignore it.
|
|
78
|
+
.filter((definition): definition is () => Promise<PluginDefinition> => Boolean(definition))
|
|
79
|
+
.map((definition) => definition()),
|
|
80
|
+
);
|
|
81
|
+
|
|
46
82
|
const plugins = await Promise.all(
|
|
47
|
-
|
|
83
|
+
enabled.map(async (definition) => {
|
|
48
84
|
const plugin = await initializePlugin(definition).catch((err) => {
|
|
49
85
|
console.error('Failed to initialize plugin:', definition.meta.id, err);
|
|
50
86
|
return undefined;
|
|
51
87
|
});
|
|
52
|
-
state.initializing = shallow(state.initializing.filter((plugin) => plugin !== definition));
|
|
53
88
|
return plugin;
|
|
54
89
|
}),
|
|
55
90
|
).then((plugins) => plugins.filter((plugin): plugin is Plugin => Boolean(plugin)));
|
|
56
|
-
|
|
57
91
|
log('plugins initialized', { plugins });
|
|
58
|
-
|
|
92
|
+
|
|
59
93
|
await Promise.all(
|
|
60
|
-
|
|
94
|
+
enabled.map(async (pluginDefinition) => {
|
|
61
95
|
await pluginDefinition.ready?.(plugins);
|
|
62
|
-
state.loading = shallow(state.loading.filter((plugin) => plugin !== pluginDefinition));
|
|
63
96
|
}),
|
|
64
97
|
);
|
|
65
|
-
|
|
66
98
|
log('plugins ready', { plugins });
|
|
67
|
-
|
|
68
|
-
state.
|
|
99
|
+
|
|
100
|
+
state.values.plugins = shallow(plugins);
|
|
101
|
+
state.values.ready = true;
|
|
69
102
|
});
|
|
70
103
|
|
|
71
104
|
return () => {
|
|
72
105
|
clearTimeout(timeout);
|
|
73
|
-
state.ready = false;
|
|
74
|
-
|
|
106
|
+
state.values.ready = false;
|
|
107
|
+
// TODO(wittjosiah): Does this ever need to be called prior to having dynamic plugins?
|
|
108
|
+
// void Promise.all(enabled.map((definition) => definition.unload?.()));
|
|
75
109
|
};
|
|
76
110
|
}, []);
|
|
77
111
|
|
|
78
|
-
if (!state.ready) {
|
|
79
|
-
|
|
80
|
-
const FallbackComponent = fallback;
|
|
81
|
-
return (
|
|
82
|
-
<FallbackComponent initializing={state.initializing} loading={state.loading} plugins={state.plugins} />
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
return <>{fallback ?? null}</>;
|
|
112
|
+
if (!state.values.ready) {
|
|
113
|
+
return <>{fallback}</>;
|
|
86
114
|
}
|
|
87
115
|
|
|
88
|
-
const ComposedContext = composeContext(state.plugins);
|
|
116
|
+
const ComposedContext = composeContext(state.values.plugins);
|
|
89
117
|
|
|
90
|
-
return <ComposedContext>{rootComponents(state.plugins)}</ComposedContext>;
|
|
118
|
+
return <ComposedContext>{rootComponents(state.values.plugins)}</ComposedContext>;
|
|
91
119
|
},
|
|
92
120
|
},
|
|
93
121
|
};
|
|
@@ -131,70 +159,3 @@ const compose = (contexts: FC<PropsWithChildren>[]) => {
|
|
|
131
159
|
</Acc>
|
|
132
160
|
));
|
|
133
161
|
};
|
|
134
|
-
// export const PluginHost = ({ plugins: definitions, fallback }: BootstrapPluginsParams): PluginDefinition => {
|
|
135
|
-
// // const state = deepSignal<PluginContext>({ ready: false, initializing: [], loading: [], plugins: [] });
|
|
136
|
-
|
|
137
|
-
// return {
|
|
138
|
-
// meta: {
|
|
139
|
-
// id: 'dxos.org/plugin/host',
|
|
140
|
-
// },
|
|
141
|
-
// provides: {
|
|
142
|
-
// // plugins: state,
|
|
143
|
-
// // context: ({ children }) => <PluginProvider value={state}>{children}</PluginProvider>,
|
|
144
|
-
// root: () => {
|
|
145
|
-
// const [plugins, setPlugins] = useState<Plugin[]>();
|
|
146
|
-
// const [initializing, setInitializing] = useState<PluginDefinition[]>([]);
|
|
147
|
-
// const [loading, setLoading] = useState<PluginDefinition[]>([]);
|
|
148
|
-
// useEffect(() => {
|
|
149
|
-
// log('initializing plugins', { definitions });
|
|
150
|
-
// const timeout = setTimeout(async () => {
|
|
151
|
-
// setInitializing(definitions);
|
|
152
|
-
// const plugins = await Promise.all(
|
|
153
|
-
// definitions.map(async (definition) => {
|
|
154
|
-
// const plugin = await initializePlugin(definition).catch((err) => {
|
|
155
|
-
// console.error('Failed to initialize plugin:', definition.meta.id, err);
|
|
156
|
-
// return undefined;
|
|
157
|
-
// });
|
|
158
|
-
// setInitializing((initializing) => initializing.filter((plugin) => plugin !== definition));
|
|
159
|
-
// return plugin;
|
|
160
|
-
// }),
|
|
161
|
-
// ).then((plugins) => plugins.filter((plugin): plugin is Plugin => Boolean(plugin)));
|
|
162
|
-
|
|
163
|
-
// log('plugins initialized', { plugins });
|
|
164
|
-
// setLoading(definitions);
|
|
165
|
-
// await Promise.all(
|
|
166
|
-
// definitions.map(async (pluginDefinition) => {
|
|
167
|
-
// await pluginDefinition.ready?.(plugins);
|
|
168
|
-
// setLoading((loading) => loading.filter((plugin) => plugin !== pluginDefinition));
|
|
169
|
-
// }),
|
|
170
|
-
// );
|
|
171
|
-
|
|
172
|
-
// log('plugins ready', { plugins });
|
|
173
|
-
// setPlugins(plugins);
|
|
174
|
-
// });
|
|
175
|
-
|
|
176
|
-
// return () => {
|
|
177
|
-
// clearTimeout(timeout);
|
|
178
|
-
// void Promise.all(definitions.map((definition) => definition.unload?.()));
|
|
179
|
-
// };
|
|
180
|
-
// }, []);
|
|
181
|
-
|
|
182
|
-
// if (!plugins) {
|
|
183
|
-
// if (typeof fallback === 'function') {
|
|
184
|
-
// const FallbackComponent = fallback;
|
|
185
|
-
// return <FallbackComponent initializing={initializing} loading={loading} />;
|
|
186
|
-
// }
|
|
187
|
-
// return <>{fallback ?? null}</>;
|
|
188
|
-
// }
|
|
189
|
-
|
|
190
|
-
// const ComposedContext = composeContext(plugins);
|
|
191
|
-
|
|
192
|
-
// return (
|
|
193
|
-
// <PluginProvider value={{ plugins, initializing, loading, ready: true }}>
|
|
194
|
-
// <ComposedContext>{rootComponents(plugins)}</ComposedContext>
|
|
195
|
-
// </PluginProvider>
|
|
196
|
-
// );
|
|
197
|
-
// },
|
|
198
|
-
// },
|
|
199
|
-
// };
|
|
200
|
-
// };
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import type { IconProps } from '@phosphor-icons/react';
|
|
6
|
+
import type { FC, PropsWithChildren } from 'react';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Capabilities provided by a plugin.
|
|
@@ -42,6 +43,22 @@ export type Plugin<TProvides = {}> = {
|
|
|
42
43
|
*/
|
|
43
44
|
// TODO(wittjosiah): How should these be managed?
|
|
44
45
|
shortId?: string;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Human readable name.
|
|
49
|
+
*/
|
|
50
|
+
name?: string;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Short description of plugin functionality.
|
|
54
|
+
*/
|
|
55
|
+
description?: string;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Component to render icon for the plugin when displayed in a list.
|
|
59
|
+
*/
|
|
60
|
+
// TODO(wittjosiah): Convert to `icon` and make serializable.
|
|
61
|
+
iconComponent?: FC<IconProps>;
|
|
45
62
|
};
|
|
46
63
|
|
|
47
64
|
/**
|
|
@@ -80,3 +97,16 @@ export type PluginDefinition<TProvides = {}, TInitializeProvides = {}> = Omit<Pl
|
|
|
80
97
|
*/
|
|
81
98
|
unload?: () => Promise<void>;
|
|
82
99
|
};
|
|
100
|
+
|
|
101
|
+
export const pluginMeta = (meta: Plugin['meta']) => meta;
|
|
102
|
+
|
|
103
|
+
type LazyPlugin<T> = () => Promise<{ default: (props: T) => PluginDefinition }>;
|
|
104
|
+
|
|
105
|
+
export namespace Plugin {
|
|
106
|
+
export const lazy = <T>(p: LazyPlugin<T>, props?: T) => {
|
|
107
|
+
return () =>
|
|
108
|
+
p().then(({ default: definition }) => {
|
|
109
|
+
return definition(props as T);
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
}
|