@dxos/app-framework 0.8.4-main.406dc2a → 0.8.4-main.548089c
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/{app-graph-builder-LG4RG2LM.mjs → app-graph-builder-JPUFNED5.mjs} +7 -7
- package/dist/lib/browser/app-graph-builder-JPUFNED5.mjs.map +7 -0
- package/dist/lib/browser/{chunk-2GRQ4QXA.mjs → chunk-LVSO2N4X.mjs} +160 -199
- package/dist/lib/browser/chunk-LVSO2N4X.mjs.map +7 -0
- package/dist/lib/browser/{chunk-FRUTKCPG.mjs → chunk-XRAWIHTQ.mjs} +101 -90
- package/dist/lib/browser/chunk-XRAWIHTQ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +5 -33
- package/dist/lib/browser/index.mjs.map +2 -2
- package/dist/lib/browser/{intent-dispatcher-6SHA5B3N.mjs → intent-dispatcher-TNEVDPI6.mjs} +2 -2
- package/dist/lib/browser/{intent-resolver-UZZ4OANZ.mjs → intent-resolver-SYLXP62Y.mjs} +2 -2
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/react/index.mjs +32 -0
- package/dist/lib/browser/{store-ACBEYK4B.mjs → store-3HDXKFXP.mjs} +2 -2
- package/dist/lib/browser/testing/index.mjs +5 -4
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/{app-graph-builder-FMHVHPWA.mjs → app-graph-builder-VO6RTSOS.mjs} +7 -7
- package/dist/lib/node-esm/app-graph-builder-VO6RTSOS.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-KSPOOYT3.mjs → chunk-FO5NIDOR.mjs} +160 -199
- package/dist/lib/node-esm/chunk-FO5NIDOR.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-CXT6CYPE.mjs → chunk-JH3SFOXA.mjs} +101 -90
- package/dist/lib/node-esm/chunk-JH3SFOXA.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +5 -33
- package/dist/lib/node-esm/index.mjs.map +2 -2
- package/dist/lib/node-esm/{intent-dispatcher-SIYQ5ZIU.mjs → intent-dispatcher-WUNOPJES.mjs} +2 -2
- package/dist/lib/node-esm/{intent-resolver-7FYJMXAG.mjs → intent-resolver-VTZI3NO7.mjs} +2 -2
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/react/index.mjs +33 -0
- package/dist/lib/node-esm/{store-6OBLTVXC.mjs → store-PAJPVOLG.mjs} +2 -2
- package/dist/lib/node-esm/testing/index.mjs +5 -4
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/types/src/common/capabilities.d.ts +36 -42
- package/dist/types/src/common/capabilities.d.ts.map +1 -1
- package/dist/types/src/common/surface.d.ts +1 -0
- package/dist/types/src/common/surface.d.ts.map +1 -1
- package/dist/types/src/core/capabilities.d.ts +12 -12
- package/dist/types/src/core/capabilities.d.ts.map +1 -1
- package/dist/types/src/core/manager.d.ts +1 -1
- package/dist/types/src/core/manager.d.ts.map +1 -1
- package/dist/types/src/core/plugin.d.ts +4 -0
- package/dist/types/src/core/plugin.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/playground/generator/Main.d.ts.map +1 -1
- package/dist/types/src/react/App.d.ts.map +1 -0
- package/dist/types/src/react/App.stories.d.ts.map +1 -0
- package/dist/types/src/react/DefaultFallback.d.ts.map +1 -0
- package/dist/types/src/react/Surface.d.ts +4 -4
- package/dist/types/src/react/Surface.d.ts.map +1 -1
- package/dist/types/src/react/Surface.stories.d.ts +3 -6
- package/dist/types/src/react/Surface.stories.d.ts.map +1 -1
- package/dist/types/src/react/index.d.ts +2 -0
- package/dist/types/src/react/index.d.ts.map +1 -1
- package/dist/types/src/react/types.d.ts +6 -0
- package/dist/types/src/react/types.d.ts.map +1 -0
- package/dist/types/src/{components → react}/useApp.d.ts +2 -2
- package/dist/types/src/react/useApp.d.ts.map +1 -0
- package/dist/types/src/react/useLoading.d.ts.map +1 -0
- package/dist/types/src/testing/withPluginManager.d.ts +4 -3
- package/dist/types/src/testing/withPluginManager.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/moon.yml +1 -1
- package/package.json +36 -33
- package/src/common/capabilities.ts +18 -19
- package/src/common/collaboration.ts +2 -2
- package/src/common/surface.ts +1 -0
- package/src/core/capabilities.test.ts +1 -1
- package/src/core/capabilities.ts +23 -19
- package/src/core/manager.ts +2 -2
- package/src/core/plugin.ts +5 -0
- package/src/index.ts +0 -2
- package/src/playground/generator/Main.tsx +0 -1
- package/src/playground/playground.stories.tsx +1 -1
- package/src/plugin-settings/app-graph-builder.ts +5 -5
- package/src/plugin-settings/translations.ts +1 -1
- package/src/{components → react}/App.tsx +1 -1
- package/src/{components → react}/DefaultFallback.tsx +1 -1
- package/src/react/Surface.stories.tsx +69 -45
- package/src/react/Surface.tsx +56 -33
- package/src/react/index.ts +4 -0
- package/src/react/types.ts +13 -0
- package/src/{components → react}/useApp.tsx +13 -12
- package/src/react/useCapabilities.ts +2 -2
- package/src/testing/withPluginManager.tsx +9 -4
- package/tsconfig.json +9 -0
- package/dist/lib/browser/app-graph-builder-LG4RG2LM.mjs.map +0 -7
- package/dist/lib/browser/chunk-2GRQ4QXA.mjs.map +0 -7
- package/dist/lib/browser/chunk-FRUTKCPG.mjs.map +0 -7
- package/dist/lib/browser/worker.mjs +0 -77
- package/dist/lib/node-esm/app-graph-builder-FMHVHPWA.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-CXT6CYPE.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-KSPOOYT3.mjs.map +0 -7
- package/dist/lib/node-esm/worker.mjs +0 -78
- package/dist/types/src/components/App.d.ts.map +0 -1
- package/dist/types/src/components/App.stories.d.ts.map +0 -1
- package/dist/types/src/components/DefaultFallback.d.ts.map +0 -1
- package/dist/types/src/components/index.d.ts +0 -2
- package/dist/types/src/components/index.d.ts.map +0 -1
- package/dist/types/src/components/useApp.d.ts.map +0 -1
- package/dist/types/src/components/useLoading.d.ts.map +0 -1
- package/dist/types/src/worker.d.ts +0 -4
- package/dist/types/src/worker.d.ts.map +0 -1
- package/src/components/index.ts +0 -5
- package/src/worker.ts +0 -11
- /package/dist/lib/browser/{intent-dispatcher-6SHA5B3N.mjs.map → intent-dispatcher-TNEVDPI6.mjs.map} +0 -0
- /package/dist/lib/browser/{intent-resolver-UZZ4OANZ.mjs.map → intent-resolver-SYLXP62Y.mjs.map} +0 -0
- /package/dist/lib/browser/{worker.mjs.map → react/index.mjs.map} +0 -0
- /package/dist/lib/browser/{store-ACBEYK4B.mjs.map → store-3HDXKFXP.mjs.map} +0 -0
- /package/dist/lib/node-esm/{intent-dispatcher-SIYQ5ZIU.mjs.map → intent-dispatcher-WUNOPJES.mjs.map} +0 -0
- /package/dist/lib/node-esm/{intent-resolver-7FYJMXAG.mjs.map → intent-resolver-VTZI3NO7.mjs.map} +0 -0
- /package/dist/lib/node-esm/{worker.mjs.map → react/index.mjs.map} +0 -0
- /package/dist/lib/node-esm/{store-6OBLTVXC.mjs.map → store-PAJPVOLG.mjs.map} +0 -0
- /package/dist/types/src/{components → react}/App.d.ts +0 -0
- /package/dist/types/src/{components → react}/App.stories.d.ts +0 -0
- /package/dist/types/src/{components → react}/DefaultFallback.d.ts +0 -0
- /package/dist/types/src/{components → react}/useLoading.d.ts +0 -0
- /package/src/{components → react}/App.stories.tsx +0 -0
- /package/src/{components → react}/useLoading.tsx +0 -0
package/src/react/Surface.tsx
CHANGED
|
@@ -23,64 +23,87 @@ import { useCapabilities } from './useCapabilities';
|
|
|
23
23
|
|
|
24
24
|
const DEFAULT_PLACEHOLDER = <Fragment />;
|
|
25
25
|
|
|
26
|
-
/**
|
|
27
|
-
* @internal
|
|
28
|
-
*/
|
|
29
|
-
export const useSurfaces = () => {
|
|
30
|
-
const surfaces = useCapabilities(Capabilities.ReactSurface);
|
|
31
|
-
return useMemo(() => surfaces.flat(), [surfaces]);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const findCandidates = (surfaces: SurfaceDefinition[], { role, data }: Pick<SurfaceProps, 'role' | 'data'>) => {
|
|
35
|
-
return Object.values(surfaces)
|
|
36
|
-
.filter((definition) =>
|
|
37
|
-
Array.isArray(definition.role) ? definition.role.includes(role) : definition.role === role,
|
|
38
|
-
)
|
|
39
|
-
.filter(({ filter }) => (filter ? filter(data ?? {}) : true))
|
|
40
|
-
.toSorted(byPosition);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* @returns `true` if there is a contributed surface which matches the specified role & data, `false` otherwise.
|
|
45
|
-
*/
|
|
46
|
-
export const isSurfaceAvailable = (context: PluginContext, { role, data }: Pick<SurfaceProps, 'role' | 'data'>) => {
|
|
47
|
-
const surfaces = context.getCapabilities(Capabilities.ReactSurface);
|
|
48
|
-
const candidates = findCandidates(surfaces.flat(), { role, data });
|
|
49
|
-
return candidates.length > 0;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
26
|
/**
|
|
53
27
|
* A surface is a named region of the screen that can be populated by plugins.
|
|
54
28
|
*/
|
|
55
29
|
export const Surface: NamedExoticComponent<SurfaceProps & RefAttributes<HTMLElement>> = memo(
|
|
56
30
|
forwardRef(
|
|
57
|
-
(
|
|
31
|
+
(
|
|
32
|
+
{ id: _id, role, data: dataParam, limit, fallback = DefaultFallback, placeholder = DEFAULT_PLACEHOLDER, ...rest },
|
|
33
|
+
forwardedRef,
|
|
34
|
+
) => {
|
|
58
35
|
// TODO(wittjosiah): This will make all surfaces depend on a single signal.
|
|
59
36
|
// This isn't ideal because it means that any change to the data will cause all surfaces to re-render.
|
|
60
37
|
// This effectively means that plugin modules which contribute surfaces need to all be activated at startup.
|
|
61
|
-
// This should be fine for now because it's how it worked prior to capabilities api
|
|
38
|
+
// This should be fine for now because it's how it worked prior to capabilities api anyway.
|
|
62
39
|
// In the future, it would be nice to be able to bucket the surface contributions by role.
|
|
63
40
|
const surfaces = useSurfaces();
|
|
64
|
-
const data = useDefaultValue(
|
|
41
|
+
const data = useDefaultValue(dataParam, () => ({}));
|
|
65
42
|
|
|
66
43
|
// NOTE: Memoizing the candidates makes the surface not re-render based on reactivity within data.
|
|
67
44
|
const definitions = findCandidates(surfaces, { role, data });
|
|
68
45
|
const candidates = limit ? definitions.slice(0, limit) : definitions;
|
|
69
|
-
const nodes = candidates.map(({ component: Component
|
|
46
|
+
const nodes = candidates.map(({ id, component: Component }) => (
|
|
70
47
|
<Component ref={forwardedRef} key={id} id={id} role={role} data={data} limit={limit} {...rest} />
|
|
71
48
|
));
|
|
72
49
|
|
|
50
|
+
// TODO(burdon): Able to inject DOM properties into root (e.g., object.id).
|
|
73
51
|
const suspense = <Suspense fallback={placeholder}>{nodes}</Suspense>;
|
|
74
52
|
|
|
75
|
-
return
|
|
53
|
+
return (
|
|
76
54
|
<ErrorBoundary data={data} fallback={fallback}>
|
|
77
55
|
{suspense}
|
|
78
56
|
</ErrorBoundary>
|
|
79
|
-
) : (
|
|
80
|
-
suspense
|
|
81
57
|
);
|
|
82
58
|
},
|
|
83
59
|
),
|
|
84
60
|
);
|
|
85
61
|
|
|
62
|
+
// TODO(burdon): Make user facing, with telemetry.
|
|
63
|
+
// TODO(burdon): Change based on dev/prod mode; infer subject type, id.
|
|
64
|
+
const DefaultFallback = ({ data, error, dev }: { data: any; error: Error; dev?: boolean }) => {
|
|
65
|
+
if (dev) {
|
|
66
|
+
return (
|
|
67
|
+
<div className='flex flex-col gap-4 p-4 is-full overflow-y-auto'>
|
|
68
|
+
<h1 className='flex gap-2 text-sm mbs-2'>{error.message}</h1>
|
|
69
|
+
<pre className='overflow-auto text-xs text-description'>{JSON.stringify(data, null, 2)}</pre>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<div className='flex flex-col gap-4 p-4 is-full overflow-y-auto border border-rose-500'>
|
|
76
|
+
<h1 className='flex gap-2 text-sm mbs-2 text-rose-500'>{error.message}</h1>
|
|
77
|
+
<pre className='overflow-auto text-xs text-description'>{error.stack}</pre>
|
|
78
|
+
<pre className='overflow-auto text-xs text-description'>{JSON.stringify(data, null, 2)}</pre>
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @internal
|
|
85
|
+
*/
|
|
86
|
+
export const useSurfaces = () => {
|
|
87
|
+
const surfaces = useCapabilities(Capabilities.ReactSurface);
|
|
88
|
+
return useMemo(() => surfaces.flat(), [surfaces]);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @returns `true` if there is a contributed surface which matches the specified role & data, `false` otherwise.
|
|
93
|
+
*/
|
|
94
|
+
export const isSurfaceAvailable = (context: PluginContext, { role, data }: Pick<SurfaceProps, 'role' | 'data'>) => {
|
|
95
|
+
const surfaces = context.getCapabilities(Capabilities.ReactSurface);
|
|
96
|
+
const candidates = findCandidates(surfaces.flat(), { role, data });
|
|
97
|
+
return candidates.length > 0;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const findCandidates = (surfaces: SurfaceDefinition[], { role, data }: Pick<SurfaceProps, 'role' | 'data'>) => {
|
|
101
|
+
return Object.values(surfaces)
|
|
102
|
+
.filter((definition) =>
|
|
103
|
+
Array.isArray(definition.role) ? definition.role.includes(role) : definition.role === role,
|
|
104
|
+
)
|
|
105
|
+
.filter(({ filter }) => (filter ? filter(data ?? {}) : true))
|
|
106
|
+
.toSorted(byPosition);
|
|
107
|
+
};
|
|
108
|
+
|
|
86
109
|
Surface.displayName = 'Surface';
|
package/src/react/index.ts
CHANGED
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
export * from './common';
|
|
6
|
+
export * from './types';
|
|
7
|
+
|
|
6
8
|
export * from './ErrorBoundary';
|
|
7
9
|
export * from './PluginManagerProvider';
|
|
8
10
|
export * from './Surface';
|
|
11
|
+
|
|
12
|
+
export * from './useApp';
|
|
9
13
|
export * from './useCapabilities';
|
|
10
14
|
export * from './useIntentResolver';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Obj } from '@dxos/echo';
|
|
6
|
+
|
|
7
|
+
// TODO(burdon): PluginSettings, ObjectSettings.
|
|
8
|
+
// TODO(burdon): Base class for surface components.
|
|
9
|
+
|
|
10
|
+
export type SurfaceComponentProps<T extends Obj.Any = Obj.Any, Props = {}> = {
|
|
11
|
+
role?: 'article' | 'section' | 'card';
|
|
12
|
+
object: T;
|
|
13
|
+
} & Props;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { RegistryContext } from '@effect-
|
|
5
|
+
import { RegistryContext } from '@effect-atom/atom-react';
|
|
6
6
|
import { effect } from '@preact/signals-core';
|
|
7
7
|
import React, { type FC, useCallback, useEffect, useMemo } from 'react';
|
|
8
8
|
|
|
@@ -12,10 +12,11 @@ import { useAsyncEffect, useDefaultValue } from '@dxos/react-hooks';
|
|
|
12
12
|
|
|
13
13
|
import { Capabilities, Events } from '../common';
|
|
14
14
|
import { type Plugin, PluginManager, type PluginManagerOptions } from '../core';
|
|
15
|
-
import { ErrorBoundary, PluginManagerProvider } from '../react';
|
|
16
15
|
|
|
17
16
|
import { App } from './App';
|
|
18
17
|
import { DefaultFallback } from './DefaultFallback';
|
|
18
|
+
import { ErrorBoundary } from './ErrorBoundary';
|
|
19
|
+
import { PluginManagerProvider } from './PluginManagerProvider';
|
|
19
20
|
|
|
20
21
|
const ENABLED_KEY = 'dxos.org/app-framework/enabled';
|
|
21
22
|
|
|
@@ -59,30 +60,30 @@ export type UseAppOptions = {
|
|
|
59
60
|
*/
|
|
60
61
|
export const useApp = ({
|
|
61
62
|
pluginManager,
|
|
62
|
-
pluginLoader:
|
|
63
|
-
plugins:
|
|
64
|
-
core:
|
|
65
|
-
defaults:
|
|
63
|
+
pluginLoader: pluginLoaderParam,
|
|
64
|
+
plugins: pluginsParam,
|
|
65
|
+
core: coreParam,
|
|
66
|
+
defaults: defaultsParam,
|
|
66
67
|
placeholder,
|
|
67
68
|
fallback = DefaultFallback,
|
|
68
69
|
cacheEnabled = false,
|
|
69
70
|
safeMode = false,
|
|
70
71
|
debounce = 0,
|
|
71
72
|
}: UseAppOptions) => {
|
|
72
|
-
const plugins = useDefaultValue(
|
|
73
|
-
const core = useDefaultValue(
|
|
74
|
-
const defaults = useDefaultValue(
|
|
73
|
+
const plugins = useDefaultValue(pluginsParam, () => []);
|
|
74
|
+
const core = useDefaultValue(coreParam, () => plugins.map(({ meta }) => meta.id));
|
|
75
|
+
const defaults = useDefaultValue(defaultsParam, () => []);
|
|
75
76
|
|
|
76
77
|
// TODO(wittjosiah): Provide a custom plugin loader which supports loading via url.
|
|
77
78
|
const pluginLoader = useMemo(
|
|
78
79
|
() =>
|
|
79
|
-
|
|
80
|
+
pluginLoaderParam ??
|
|
80
81
|
((id: string) => {
|
|
81
82
|
const plugin = plugins.find((plugin) => plugin.meta.id === id);
|
|
82
83
|
invariant(plugin, `Plugin not found: ${id}`);
|
|
83
84
|
return plugin;
|
|
84
85
|
}),
|
|
85
|
-
[
|
|
86
|
+
[pluginLoaderParam, plugins],
|
|
86
87
|
);
|
|
87
88
|
|
|
88
89
|
const state = useMemo(() => live({ ready: false, error: null }), []);
|
|
@@ -129,7 +130,7 @@ export const useApp = ({
|
|
|
129
130
|
manager.context.contributeCapability({
|
|
130
131
|
interface: Capabilities.RxRegistry,
|
|
131
132
|
implementation: manager.registry,
|
|
132
|
-
module: 'dxos.org/app-framework/
|
|
133
|
+
module: 'dxos.org/app-framework/atom-registry',
|
|
133
134
|
});
|
|
134
135
|
|
|
135
136
|
await Promise.all([
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { useAtomValue } from '@effect-atom/atom-react';
|
|
6
6
|
|
|
7
7
|
import { invariant } from '@dxos/invariant';
|
|
8
8
|
|
|
@@ -16,7 +16,7 @@ import { usePluginManager } from './PluginManagerProvider';
|
|
|
16
16
|
*/
|
|
17
17
|
export const useCapabilities = <T>(interfaceDef: InterfaceDef<T>) => {
|
|
18
18
|
const manager = usePluginManager();
|
|
19
|
-
return
|
|
19
|
+
return useAtomValue(manager.context.capabilities(interfaceDef));
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { type Decorator } from '@storybook/react';
|
|
5
|
+
import { type Decorator, type StoryContext } from '@storybook/react';
|
|
6
6
|
import React, { useEffect, useMemo } from 'react';
|
|
7
7
|
|
|
8
8
|
import { raise } from '@dxos/debug';
|
|
@@ -10,7 +10,6 @@ import { useAsyncEffect } from '@dxos/react-hooks';
|
|
|
10
10
|
import { type MaybeProvider, getProviderValue } from '@dxos/util';
|
|
11
11
|
|
|
12
12
|
import { Capabilities, Events } from '../common';
|
|
13
|
-
import { type UseAppOptions, useApp } from '../components';
|
|
14
13
|
import {
|
|
15
14
|
type ActivationEvent,
|
|
16
15
|
type AnyCapability,
|
|
@@ -20,6 +19,7 @@ import {
|
|
|
20
19
|
defineModule,
|
|
21
20
|
definePlugin,
|
|
22
21
|
} from '../core';
|
|
22
|
+
import { type UseAppOptions, useApp } from '../react';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* @internal
|
|
@@ -57,13 +57,18 @@ export type WithPluginManagerOptions = UseAppOptions & {
|
|
|
57
57
|
fireEvents?: (ActivationEvent | string)[];
|
|
58
58
|
};
|
|
59
59
|
|
|
60
|
+
export type WithPluginManagerInitializer<Args = void> =
|
|
61
|
+
| WithPluginManagerOptions
|
|
62
|
+
| ((context: StoryContext<Args>) => WithPluginManagerOptions);
|
|
63
|
+
|
|
60
64
|
/**
|
|
61
65
|
* Wraps a story with a plugin manager.
|
|
62
66
|
* NOTE: This builds up and tears down the plugin manager on every render.
|
|
63
67
|
*/
|
|
64
|
-
export const withPluginManager = (
|
|
68
|
+
export const withPluginManager = <Args,>(init: WithPluginManagerInitializer<Args> = {}): Decorator => {
|
|
65
69
|
return (Story, context) => {
|
|
66
|
-
const
|
|
70
|
+
const options = typeof init === 'function' ? init(context as any) : init;
|
|
71
|
+
const pluginManager = useMemo(() => setupPluginManager(options), [init]);
|
|
67
72
|
|
|
68
73
|
// Set-up root capability.
|
|
69
74
|
useEffect(() => {
|
package/tsconfig.json
CHANGED
|
@@ -38,6 +38,9 @@
|
|
|
38
38
|
{
|
|
39
39
|
"path": "../../core/ai"
|
|
40
40
|
},
|
|
41
|
+
{
|
|
42
|
+
"path": "../../core/assistant"
|
|
43
|
+
},
|
|
41
44
|
{
|
|
42
45
|
"path": "../../core/blueprints"
|
|
43
46
|
},
|
|
@@ -62,6 +65,9 @@
|
|
|
62
65
|
{
|
|
63
66
|
"path": "../../ui/react-ui-syntax-highlighter"
|
|
64
67
|
},
|
|
68
|
+
{
|
|
69
|
+
"path": "../../ui/react-ui-theme"
|
|
70
|
+
},
|
|
65
71
|
{
|
|
66
72
|
"path": "../app-graph"
|
|
67
73
|
},
|
|
@@ -70,6 +76,9 @@
|
|
|
70
76
|
},
|
|
71
77
|
{
|
|
72
78
|
"path": "../schema"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"path": "../types"
|
|
73
82
|
}
|
|
74
83
|
]
|
|
75
84
|
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/plugin-settings/app-graph-builder.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Rx } from '@effect-rx/rx-react';\nimport * as Function from 'effect/Function';\nimport * as Option from 'effect/Option';\n\nimport { ROOT_ID, createExtension } from '@dxos/app-graph';\nimport { type SettingsStore, type SettingsValue } from '@dxos/local-storage';\nimport { isNonNullable } from '@dxos/util';\n\nimport { Capabilities } from '../common';\nimport { type PluginContext, type PluginMeta, contributes } from '../core';\nimport { createIntent } from '../plugin-intent';\n\nimport { SETTINGS_ID, SETTINGS_KEY, SettingsAction } from './actions';\nimport { meta } from './meta';\n\nexport default (context: PluginContext) =>\n contributes(Capabilities.AppGraphBuilder, [\n createExtension({\n id: `${meta.id}/action`,\n actions: (node) =>\n Rx.make((get) =>\n Function.pipe(\n get(node),\n Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),\n Option.map(() => [\n {\n id: meta.id,\n data: async () => {\n const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);\n await dispatch(createIntent(SettingsAction.Open));\n },\n properties: {\n label: ['open settings label', { ns: meta.id }],\n icon: 'ph--gear--regular',\n disposition: 'menu',\n keyBinding: {\n macos: 'meta+,',\n windows: 'alt+,',\n },\n },\n },\n ]),\n Option.getOrElse(() => []),\n ),\n ),\n }),\n createExtension({\n id: `${meta.id}/core`,\n connector: (node) =>\n Rx.make((get) =>\n Function.pipe(\n get(node),\n Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),\n Option.map(() => [\n {\n id: SETTINGS_ID,\n type: meta.id,\n properties: {\n label: ['app settings label', { ns: meta.id }],\n icon: 'ph--gear--regular',\n disposition: 'pin-end',\n position: 'hoist',\n testId: 'treeView.appSettings',\n },\n },\n ]),\n Option.getOrElse(() => []),\n ),\n ),\n }),\n createExtension({\n id: `${meta.id}/core-plugins`,\n connector: (node) =>\n Rx.make((get) =>\n Function.pipe(\n get(node),\n Option.flatMap((node) => (node.id !== SETTINGS_ID ? Option.none() : Option.some(node))),\n Option.map(() => {\n const manager = get(context.capability(Capabilities.PluginManager));\n const [settingsStore] = get(context.capabilities(Capabilities.SettingsStore));\n return [\n ...manager.plugins\n .filter((plugin) => manager.core.includes(plugin.meta.id))\n .map((plugin): [PluginMeta, SettingsStore<SettingsValue>] | null => {\n const settings = settingsStore?.getStore(plugin.meta.id);\n if (!settings) {\n return null;\n }\n\n return [plugin.meta, settings];\n })\n .filter(isNonNullable)\n .map(([meta, settings]) => ({\n id: `${SETTINGS_KEY}:${meta.id.replaceAll('/', ':')}`,\n type: 'category',\n data: settings,\n properties: {\n label: meta.name ?? meta.id,\n icon: meta.icon ?? 'ph--circle--regular',\n },\n })),\n\n {\n id: `${SETTINGS_KEY}:custom-plugins`,\n type: 'category',\n properties: {\n label: ['custom plugins label', { ns: meta.id }],\n icon: 'ph--squares-four--regular',\n role: 'branch',\n disposition: 'collection',\n },\n },\n ];\n }),\n Option.getOrElse(() => []),\n ),\n ),\n }),\n createExtension({\n id: `${meta.id}/custom-plugins`,\n connector: (node) =>\n Rx.make((get) =>\n Function.pipe(\n get(node),\n Option.flatMap((node) =>\n node.id !== `${SETTINGS_KEY}:custom-plugins` ? Option.none() : Option.some(node),\n ),\n Option.map(() => {\n const manager = get(context.capability(Capabilities.PluginManager));\n const [settingsStore] = get(context.capabilities(Capabilities.SettingsStore));\n return manager.plugins\n .filter((plugin) => !manager.core.includes(plugin.meta.id))\n .map((plugin): [PluginMeta, SettingsStore<SettingsValue>] | null => {\n const settings = settingsStore?.getStore(plugin.meta.id);\n if (!settings) {\n return null;\n }\n\n return [plugin.meta, settings];\n })\n .filter(isNonNullable)\n .map(([meta, settings]) => ({\n id: `${SETTINGS_KEY}:${meta.id.replaceAll('/', ':')}`,\n type: 'category',\n data: settings,\n properties: {\n label: meta.name ?? meta.id,\n icon: meta.icon ?? 'ph--circle--regular',\n },\n }));\n }),\n Option.getOrElse(() => []),\n ),\n ),\n }),\n ]);\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["Rx", "Function", "Option", "ROOT_ID", "createExtension", "isNonNullable", "context", "contributes", "Capabilities", "AppGraphBuilder", "createExtension", "id", "meta", "actions", "node", "Rx", "make", "get", "pipe", "flatMap", "ROOT_ID", "some", "none", "map", "data", "dispatchPromise", "dispatch", "getCapability", "IntentDispatcher", "createIntent", "SettingsAction", "Open", "properties", "label", "ns", "icon", "disposition", "keyBinding", "macos", "windows", "getOrElse", "connector", "SETTINGS_ID", "type", "position", "testId", "manager", "capability", "PluginManager", "settingsStore", "capabilities", "SettingsStore", "plugins", "filter", "plugin", "core", "includes", "settings", "getStore", "isNonNullable", "SETTINGS_KEY", "replaceAll", "name", "role"]
|
|
7
|
-
}
|