@dxos/plugin-simple-layout 0.0.0 → 0.8.4-main.69d29f4
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-CLPGTNWJ.mjs +29 -0
- package/dist/lib/browser/chunk-CLPGTNWJ.mjs.map +7 -0
- package/dist/lib/browser/chunk-FK4M7GJV.mjs +613 -0
- package/dist/lib/browser/chunk-FK4M7GJV.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +94 -0
- package/dist/lib/browser/index.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -0
- package/dist/lib/browser/operation-resolver-LTB63NKP.mjs +168 -0
- package/dist/lib/browser/operation-resolver-LTB63NKP.mjs.map +7 -0
- package/dist/lib/browser/react-root-6ARAPH3O.mjs +21 -0
- package/dist/lib/browser/react-root-6ARAPH3O.mjs.map +7 -0
- package/dist/lib/browser/react-surface-SO7B23GS.mjs +39 -0
- package/dist/lib/browser/react-surface-SO7B23GS.mjs.map +7 -0
- package/dist/lib/browser/spotlight-dismiss-VSNOPETH.mjs +66 -0
- package/dist/lib/browser/spotlight-dismiss-VSNOPETH.mjs.map +7 -0
- package/dist/lib/browser/state-H4IGICBB.mjs +45 -0
- package/dist/lib/browser/state-H4IGICBB.mjs.map +7 -0
- package/dist/lib/browser/url-handler-7CFGTLNG.mjs +54 -0
- package/dist/lib/browser/url-handler-7CFGTLNG.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-EGFZAVBD.mjs +614 -0
- package/dist/lib/node-esm/chunk-EGFZAVBD.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-MUVVYBUE.mjs +31 -0
- package/dist/lib/node-esm/chunk-MUVVYBUE.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +95 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/operation-resolver-7O6O7T4Q.mjs +169 -0
- package/dist/lib/node-esm/operation-resolver-7O6O7T4Q.mjs.map +7 -0
- package/dist/lib/node-esm/react-root-2CPA2ZUS.mjs +22 -0
- package/dist/lib/node-esm/react-root-2CPA2ZUS.mjs.map +7 -0
- package/dist/lib/node-esm/react-surface-FKAV56MO.mjs +40 -0
- package/dist/lib/node-esm/react-surface-FKAV56MO.mjs.map +7 -0
- package/dist/lib/node-esm/spotlight-dismiss-L5PCWIJG.mjs +68 -0
- package/dist/lib/node-esm/spotlight-dismiss-L5PCWIJG.mjs.map +7 -0
- package/dist/lib/node-esm/state-QIU2LMLT.mjs +46 -0
- package/dist/lib/node-esm/state-QIU2LMLT.mjs.map +7 -0
- package/dist/lib/node-esm/url-handler-4LYP3JM7.mjs +55 -0
- package/dist/lib/node-esm/url-handler-4LYP3JM7.mjs.map +7 -0
- package/dist/types/src/SimpleLayoutPlugin.d.ts +7 -0
- package/dist/types/src/SimpleLayoutPlugin.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +7 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/operation-resolver/index.d.ts +3 -0
- package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +5 -0
- package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-root/index.d.ts +6 -0
- package/dist/types/src/capabilities/react-root/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-root/react-root.d.ts +9 -0
- package/dist/types/src/capabilities/react-root/react-root.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface/index.d.ts +3 -0
- package/dist/types/src/capabilities/react-surface/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts +5 -0
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +1 -0
- package/dist/types/src/capabilities/spotlight-dismiss/index.d.ts +3 -0
- package/dist/types/src/capabilities/spotlight-dismiss/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/spotlight-dismiss/spotlight-dismiss.d.ts +14 -0
- package/dist/types/src/capabilities/spotlight-dismiss/spotlight-dismiss.d.ts.map +1 -0
- package/dist/types/src/capabilities/state/index.d.ts +13 -0
- package/dist/types/src/capabilities/state/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/state/state.d.ts +19 -0
- package/dist/types/src/capabilities/state/state.d.ts.map +1 -0
- package/dist/types/src/capabilities/url-handler/index.d.ts +3 -0
- package/dist/types/src/capabilities/url-handler/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/url-handler/url-handler.d.ts +10 -0
- package/dist/types/src/capabilities/url-handler/url-handler.d.ts.map +1 -0
- package/dist/types/src/components/ContentError.d.ts +5 -0
- package/dist/types/src/components/ContentError.d.ts.map +1 -0
- package/dist/types/src/components/ContentError.stories.d.ts +35 -0
- package/dist/types/src/components/ContentError.stories.d.ts.map +1 -0
- package/dist/types/src/components/ContentLoading.d.ts +3 -0
- package/dist/types/src/components/ContentLoading.d.ts.map +1 -0
- package/dist/types/src/components/ContentLoading.stories.d.ts +13 -0
- package/dist/types/src/components/ContentLoading.stories.d.ts.map +1 -0
- package/dist/types/src/components/Dialog/Dialog.d.ts +3 -0
- package/dist/types/src/components/Dialog/Dialog.d.ts.map +1 -0
- package/dist/types/src/components/Dialog/index.d.ts +2 -0
- package/dist/types/src/components/Dialog/index.d.ts.map +1 -0
- package/dist/types/src/components/Home/Home.d.ts +7 -0
- package/dist/types/src/components/Home/Home.d.ts.map +1 -0
- package/dist/types/src/components/Home/index.d.ts +2 -0
- package/dist/types/src/components/Home/index.d.ts.map +1 -0
- package/dist/types/src/components/Popover/Popover.d.ts +4 -0
- package/dist/types/src/components/Popover/Popover.d.ts.map +1 -0
- package/dist/types/src/components/Popover/index.d.ts +2 -0
- package/dist/types/src/components/Popover/index.d.ts.map +1 -0
- package/dist/types/src/components/SimpleLayout/Banner.d.ts +8 -0
- package/dist/types/src/components/SimpleLayout/Banner.d.ts.map +1 -0
- package/dist/types/src/components/SimpleLayout/Main.d.ts +9 -0
- package/dist/types/src/components/SimpleLayout/Main.d.ts.map +1 -0
- package/dist/types/src/components/SimpleLayout/NavBar.d.ts +8 -0
- package/dist/types/src/components/SimpleLayout/NavBar.d.ts.map +1 -0
- package/dist/types/src/components/SimpleLayout/NavBar.stories.d.ts +39 -0
- package/dist/types/src/components/SimpleLayout/NavBar.stories.d.ts.map +1 -0
- package/dist/types/src/components/SimpleLayout/SimpleLayout.d.ts +3 -0
- package/dist/types/src/components/SimpleLayout/SimpleLayout.d.ts.map +1 -0
- package/dist/types/src/components/SimpleLayout/SimpleLayout.stories.d.ts +37 -0
- package/dist/types/src/components/SimpleLayout/SimpleLayout.stories.d.ts.map +1 -0
- package/dist/types/src/components/SimpleLayout/index.d.ts +2 -0
- package/dist/types/src/components/SimpleLayout/index.d.ts.map +1 -0
- package/dist/types/src/components/Workspace/Workspace.d.ts +9 -0
- package/dist/types/src/components/Workspace/Workspace.d.ts.map +1 -0
- package/dist/types/src/components/Workspace/index.d.ts +2 -0
- package/dist/types/src/components/Workspace/index.d.ts.map +1 -0
- package/dist/types/src/components/hooks.d.ts +5 -0
- package/dist/types/src/components/hooks.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +6 -0
- package/dist/types/src/components/index.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +2 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -0
- package/dist/types/src/hooks/useSimpleLayoutState.d.ts +7 -0
- package/dist/types/src/hooks/useSimpleLayoutState.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/meta.d.ts +3 -0
- package/dist/types/src/meta.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +20 -0
- package/dist/types/src/translations.d.ts.map +1 -0
- package/dist/types/src/types/capabilities.d.ts +31 -0
- package/dist/types/src/types/capabilities.d.ts.map +1 -0
- package/dist/types/src/types/events.d.ts +6 -0
- package/dist/types/src/types/events.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +3 -0
- package/dist/types/src/types/index.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +29 -24
- package/src/SimpleLayoutPlugin.ts +20 -4
- package/src/capabilities/index.ts +3 -0
- package/src/capabilities/operation-resolver/operation-resolver.ts +82 -39
- package/src/capabilities/react-surface/index.ts +7 -0
- package/src/capabilities/react-surface/react-surface.tsx +40 -0
- package/src/capabilities/spotlight-dismiss/index.ts +7 -0
- package/src/{hooks/useSpotlightDismiss.ts → capabilities/spotlight-dismiss/spotlight-dismiss.ts} +31 -40
- package/src/capabilities/state/state.tsx +21 -32
- package/src/capabilities/url-handler/index.ts +7 -0
- package/src/capabilities/url-handler/url-handler.ts +80 -0
- package/src/components/Dialog/Dialog.tsx +14 -14
- package/src/components/Home/Home.tsx +53 -61
- package/src/components/Popover/Popover.tsx +45 -27
- package/src/components/SimpleLayout/Banner.tsx +50 -28
- package/src/components/SimpleLayout/Main.tsx +40 -44
- package/src/components/SimpleLayout/NavBar.tsx +18 -41
- package/src/components/SimpleLayout/SimpleLayout.stories.tsx +2 -9
- package/src/components/SimpleLayout/SimpleLayout.tsx +0 -1
- package/src/components/Workspace/Workspace.tsx +115 -0
- package/src/components/Workspace/index.ts +5 -0
- package/src/components/hooks.ts +30 -0
- package/src/components/index.ts +1 -0
- package/src/hooks/index.ts +1 -1
- package/src/hooks/useSimpleLayoutState.ts +30 -0
- package/src/types/capabilities.ts +8 -1
- package/src/types/events.ts +14 -0
- package/src/types/index.ts +1 -0
- /package/src/components/SimpleLayout/{NavBarstories.tsx → NavBar.stories.tsx} +0 -0
package/package.json
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/plugin-simple-layout",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.4-main.69d29f4",
|
|
4
4
|
"description": "Simple layout plugin for minimal UI contexts like popover windows.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/dxos/dxos"
|
|
10
|
+
},
|
|
7
11
|
"license": "MIT",
|
|
8
12
|
"author": "DXOS.org",
|
|
9
13
|
"sideEffects": true,
|
|
@@ -22,20 +26,20 @@
|
|
|
22
26
|
"src"
|
|
23
27
|
],
|
|
24
28
|
"dependencies": {
|
|
25
|
-
"@
|
|
29
|
+
"@effect-atom/atom": "^0.4.13",
|
|
30
|
+
"@effect-atom/atom-react": "^0.4.6",
|
|
26
31
|
"@radix-ui/react-context": "1.1.1",
|
|
27
|
-
"@dxos/
|
|
28
|
-
"@dxos/
|
|
29
|
-
"@dxos/
|
|
30
|
-
"@dxos/
|
|
31
|
-
"@dxos/
|
|
32
|
-
"@dxos/
|
|
33
|
-
"@dxos/react-ui-
|
|
34
|
-
"@dxos/
|
|
35
|
-
"@dxos/react-ui-
|
|
36
|
-
"@dxos/
|
|
37
|
-
"@dxos/util": "0.8.
|
|
38
|
-
"@dxos/react-ui-mosaic": "0.8.3"
|
|
32
|
+
"@dxos/log": "0.8.4-main.69d29f4",
|
|
33
|
+
"@dxos/app-framework": "0.8.4-main.69d29f4",
|
|
34
|
+
"@dxos/operation": "0.8.4-main.69d29f4",
|
|
35
|
+
"@dxos/plugin-graph": "0.8.4-main.69d29f4",
|
|
36
|
+
"@dxos/react-ui-menu": "0.8.4-main.69d29f4",
|
|
37
|
+
"@dxos/react-ui-mosaic": "0.8.4-main.69d29f4",
|
|
38
|
+
"@dxos/react-ui-attention": "0.8.4-main.69d29f4",
|
|
39
|
+
"@dxos/react-ui-searchlist": "0.8.4-main.69d29f4",
|
|
40
|
+
"@dxos/react-ui-stack": "0.8.4-main.69d29f4",
|
|
41
|
+
"@dxos/schema": "0.8.4-main.69d29f4",
|
|
42
|
+
"@dxos/util": "0.8.4-main.69d29f4"
|
|
39
43
|
},
|
|
40
44
|
"devDependencies": {
|
|
41
45
|
"@types/react": "~19.2.7",
|
|
@@ -44,21 +48,22 @@
|
|
|
44
48
|
"react": "~19.2.3",
|
|
45
49
|
"react-dom": "~19.2.3",
|
|
46
50
|
"vite": "7.1.9",
|
|
47
|
-
"@dxos/
|
|
48
|
-
"@dxos/plugin-
|
|
49
|
-
"@dxos/plugin-
|
|
50
|
-
"@dxos/plugin-space": "0.8.
|
|
51
|
-
"@dxos/
|
|
52
|
-
"@dxos/
|
|
53
|
-
"@dxos/
|
|
54
|
-
"@dxos/storybook-utils": "0.8.
|
|
51
|
+
"@dxos/plugin-client": "0.8.4-main.69d29f4",
|
|
52
|
+
"@dxos/plugin-preview": "0.8.4-main.69d29f4",
|
|
53
|
+
"@dxos/plugin-search": "0.8.4-main.69d29f4",
|
|
54
|
+
"@dxos/plugin-space": "0.8.4-main.69d29f4",
|
|
55
|
+
"@dxos/react-ui": "0.8.4-main.69d29f4",
|
|
56
|
+
"@dxos/plugin-testing": "0.8.4-main.69d29f4",
|
|
57
|
+
"@dxos/schema": "0.8.4-main.69d29f4",
|
|
58
|
+
"@dxos/storybook-utils": "0.8.4-main.69d29f4",
|
|
59
|
+
"@dxos/ui-theme": "0.8.4-main.69d29f4"
|
|
55
60
|
},
|
|
56
61
|
"peerDependencies": {
|
|
57
62
|
"effect": "3.19.11",
|
|
58
63
|
"react": "~19.2.3",
|
|
59
64
|
"react-dom": "~19.2.3",
|
|
60
|
-
"@dxos/react-ui": "0.8.
|
|
61
|
-
"@dxos/ui-theme": "0.
|
|
65
|
+
"@dxos/react-ui": "0.8.4-main.69d29f4",
|
|
66
|
+
"@dxos/ui-theme": "0.8.4-main.69d29f4"
|
|
62
67
|
},
|
|
63
68
|
"publishConfig": {
|
|
64
69
|
"access": "public"
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { Capability, Common, Plugin } from '@dxos/app-framework';
|
|
5
|
+
import { ActivationEvent, Capability, Common, Plugin } from '@dxos/app-framework';
|
|
6
6
|
|
|
7
|
-
import { OperationResolver, ReactRoot,
|
|
7
|
+
import { OperationResolver, ReactRoot, ReactSurface, SpotlightDismiss, State, UrlHandler } from './capabilities';
|
|
8
8
|
import { meta } from './meta';
|
|
9
9
|
import { translations } from './translations';
|
|
10
|
+
import { SimpleLayoutEvents } from './types';
|
|
10
11
|
|
|
11
12
|
export type SimpleLayoutPluginOptions = {
|
|
12
13
|
/** Whether running in popover window context (hides mobile-specific UI). */
|
|
@@ -17,14 +18,29 @@ export const SimpleLayoutPlugin = Plugin.define<SimpleLayoutPluginOptions>(meta)
|
|
|
17
18
|
Plugin.addModule(({ isPopover = false }) => ({
|
|
18
19
|
id: Capability.getModuleTag(State),
|
|
19
20
|
activatesOn: Common.ActivationEvent.Startup,
|
|
20
|
-
activatesAfter: [Common.ActivationEvent.LayoutReady],
|
|
21
|
-
activate: () => State({ initialState: { isPopover } }
|
|
21
|
+
activatesAfter: [SimpleLayoutEvents.StateReady, Common.ActivationEvent.LayoutReady],
|
|
22
|
+
activate: () => State({ initialState: { isPopover } }),
|
|
23
|
+
})),
|
|
24
|
+
Plugin.addModule(({ isPopover = false }) => ({
|
|
25
|
+
id: Capability.getModuleTag(SpotlightDismiss),
|
|
26
|
+
activatesOn: Common.ActivationEvent.Startup,
|
|
27
|
+
activate: () => SpotlightDismiss({ isPopover }),
|
|
22
28
|
})),
|
|
23
29
|
Plugin.addModule({
|
|
24
30
|
id: Capability.getModuleTag(ReactRoot),
|
|
25
31
|
activatesOn: Common.ActivationEvent.Startup,
|
|
26
32
|
activate: ReactRoot,
|
|
27
33
|
}),
|
|
34
|
+
Plugin.addModule({
|
|
35
|
+
id: Capability.getModuleTag(ReactSurface),
|
|
36
|
+
activatesOn: Common.ActivationEvent.Startup,
|
|
37
|
+
activate: ReactSurface,
|
|
38
|
+
}),
|
|
39
|
+
Plugin.addModule({
|
|
40
|
+
id: Capability.getModuleTag(UrlHandler),
|
|
41
|
+
activatesOn: ActivationEvent.allOf(Common.ActivationEvent.OperationInvokerReady, SimpleLayoutEvents.StateReady),
|
|
42
|
+
activate: UrlHandler,
|
|
43
|
+
}),
|
|
28
44
|
Common.Plugin.addOperationResolverModule({ activate: OperationResolver }),
|
|
29
45
|
Common.Plugin.addTranslationsModule({ translations }),
|
|
30
46
|
Plugin.make,
|
|
@@ -7,10 +7,21 @@ import * as Effect from 'effect/Effect';
|
|
|
7
7
|
import { Capability, Common } from '@dxos/app-framework';
|
|
8
8
|
import { Operation, OperationResolver } from '@dxos/operation';
|
|
9
9
|
|
|
10
|
-
import { SimpleLayoutState } from '../../types';
|
|
10
|
+
import { type SimpleLayoutState, SimpleLayoutState as SimpleLayoutStateCapability } from '../../types';
|
|
11
|
+
|
|
12
|
+
/** Maximum number of items to keep in navigation history. */
|
|
13
|
+
const MAX_HISTORY_LENGTH = 50;
|
|
11
14
|
|
|
12
15
|
export default Capability.makeModule(
|
|
13
16
|
Effect.fnUntraced(function* () {
|
|
17
|
+
const registry = yield* Capability.get(Common.Capability.AtomRegistry);
|
|
18
|
+
const stateAtom = yield* Capability.get(SimpleLayoutStateCapability);
|
|
19
|
+
|
|
20
|
+
const getState = () => registry.get(stateAtom);
|
|
21
|
+
const updateState = (fn: (current: SimpleLayoutState) => SimpleLayoutState) => {
|
|
22
|
+
registry.set(stateAtom, fn(getState()));
|
|
23
|
+
};
|
|
24
|
+
|
|
14
25
|
return Capability.contributes(Common.Capability.OperationResolver, [
|
|
15
26
|
//
|
|
16
27
|
// UpdateSidebar - No-op for simple layout.
|
|
@@ -34,13 +45,15 @@ export default Capability.makeModule(
|
|
|
34
45
|
OperationResolver.make({
|
|
35
46
|
operation: Common.LayoutOperation.UpdateDialog,
|
|
36
47
|
handler: Effect.fnUntraced(function* (input) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
updateState((state) => ({
|
|
49
|
+
...state,
|
|
50
|
+
dialogOpen: input.state ?? Boolean(input.subject),
|
|
51
|
+
dialogType: input.type ?? 'default',
|
|
52
|
+
dialogBlockAlign: input.blockAlign ?? 'center',
|
|
53
|
+
dialogOverlayClasses: input.overlayClasses,
|
|
54
|
+
dialogOverlayStyle: input.overlayStyle,
|
|
55
|
+
dialogContent: input.subject ? { component: input.subject, props: input.props } : undefined,
|
|
56
|
+
}));
|
|
44
57
|
}),
|
|
45
58
|
}),
|
|
46
59
|
|
|
@@ -50,21 +63,22 @@ export default Capability.makeModule(
|
|
|
50
63
|
OperationResolver.make({
|
|
51
64
|
operation: Common.LayoutOperation.UpdatePopover,
|
|
52
65
|
handler: Effect.fnUntraced(function* (input) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
updateState((state) => ({
|
|
67
|
+
...state,
|
|
68
|
+
popoverOpen: input.state ?? Boolean(input.subject),
|
|
69
|
+
popoverKind: input.kind ?? 'base',
|
|
70
|
+
popoverTitle: input.kind === 'card' ? input.title : undefined,
|
|
71
|
+
popoverContent:
|
|
72
|
+
typeof input.subject === 'string'
|
|
73
|
+
? { component: input.subject, props: input.props }
|
|
74
|
+
: input.subject
|
|
75
|
+
? { subject: input.subject }
|
|
76
|
+
: undefined,
|
|
77
|
+
popoverSide: input.side,
|
|
78
|
+
popoverVariant: input.variant,
|
|
79
|
+
popoverAnchor: input.variant === 'virtual' ? input.anchor : state.popoverAnchor,
|
|
80
|
+
popoverAnchorId: input.variant !== 'virtual' ? input.anchorId : state.popoverAnchorId,
|
|
81
|
+
}));
|
|
68
82
|
}),
|
|
69
83
|
}),
|
|
70
84
|
|
|
@@ -74,14 +88,16 @@ export default Capability.makeModule(
|
|
|
74
88
|
OperationResolver.make({
|
|
75
89
|
operation: Common.LayoutOperation.SwitchWorkspace,
|
|
76
90
|
handler: Effect.fnUntraced(function* (input) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
91
|
+
updateState((state) => ({
|
|
92
|
+
...state,
|
|
93
|
+
// TODO(wittjosiah): This is a hack to prevent the previous deck from being set for pinned items.
|
|
94
|
+
// Ideally this should be worked into the data model in a generic way.
|
|
95
|
+
previousWorkspace: !state.workspace.startsWith('!') ? state.workspace : state.previousWorkspace,
|
|
96
|
+
workspace: input.subject,
|
|
97
|
+
active: undefined,
|
|
98
|
+
// Clear history when switching workspaces.
|
|
99
|
+
history: [],
|
|
100
|
+
}));
|
|
85
101
|
}),
|
|
86
102
|
}),
|
|
87
103
|
|
|
@@ -91,9 +107,9 @@ export default Capability.makeModule(
|
|
|
91
107
|
OperationResolver.make({
|
|
92
108
|
operation: Common.LayoutOperation.RevertWorkspace,
|
|
93
109
|
handler: Effect.fnUntraced(function* () {
|
|
94
|
-
const
|
|
110
|
+
const state = getState();
|
|
95
111
|
yield* Operation.invoke(Common.LayoutOperation.SwitchWorkspace, {
|
|
96
|
-
subject:
|
|
112
|
+
subject: state.previousWorkspace,
|
|
97
113
|
});
|
|
98
114
|
}),
|
|
99
115
|
}),
|
|
@@ -104,8 +120,18 @@ export default Capability.makeModule(
|
|
|
104
120
|
OperationResolver.make({
|
|
105
121
|
operation: Common.LayoutOperation.Open,
|
|
106
122
|
handler: Effect.fnUntraced(function* (input) {
|
|
107
|
-
|
|
108
|
-
|
|
123
|
+
updateState((state) => {
|
|
124
|
+
// Push current active to history if it exists.
|
|
125
|
+
const newHistory = state.active ? [...state.history, state.active] : state.history;
|
|
126
|
+
// Limit history length to prevent memory issues.
|
|
127
|
+
const trimmedHistory =
|
|
128
|
+
newHistory.length > MAX_HISTORY_LENGTH ? newHistory.slice(-MAX_HISTORY_LENGTH) : newHistory;
|
|
129
|
+
return {
|
|
130
|
+
...state,
|
|
131
|
+
active: input.subject[0],
|
|
132
|
+
history: trimmedHistory,
|
|
133
|
+
};
|
|
134
|
+
});
|
|
109
135
|
}),
|
|
110
136
|
}),
|
|
111
137
|
|
|
@@ -115,8 +141,23 @@ export default Capability.makeModule(
|
|
|
115
141
|
OperationResolver.make({
|
|
116
142
|
operation: Common.LayoutOperation.Close,
|
|
117
143
|
handler: Effect.fnUntraced(function* () {
|
|
118
|
-
|
|
119
|
-
|
|
144
|
+
updateState((state) => {
|
|
145
|
+
// Pop from history if available.
|
|
146
|
+
if (state.history.length > 0) {
|
|
147
|
+
const newHistory = [...state.history];
|
|
148
|
+
const previousActive = newHistory.pop();
|
|
149
|
+
return {
|
|
150
|
+
...state,
|
|
151
|
+
active: previousActive,
|
|
152
|
+
history: newHistory,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// No history, just clear active.
|
|
156
|
+
return {
|
|
157
|
+
...state,
|
|
158
|
+
active: undefined,
|
|
159
|
+
};
|
|
160
|
+
});
|
|
120
161
|
}),
|
|
121
162
|
}),
|
|
122
163
|
|
|
@@ -126,8 +167,10 @@ export default Capability.makeModule(
|
|
|
126
167
|
OperationResolver.make({
|
|
127
168
|
operation: Common.LayoutOperation.Set,
|
|
128
169
|
handler: Effect.fnUntraced(function* (input) {
|
|
129
|
-
|
|
130
|
-
|
|
170
|
+
updateState((state) => ({
|
|
171
|
+
...state,
|
|
172
|
+
active: input.subject[0],
|
|
173
|
+
}));
|
|
131
174
|
}),
|
|
132
175
|
}),
|
|
133
176
|
]);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
import { Capability, Common } from '@dxos/app-framework';
|
|
9
|
+
import { Node } from '@dxos/plugin-graph';
|
|
10
|
+
|
|
11
|
+
import { Home, Workspace } from '../../components';
|
|
12
|
+
import { meta } from '../../meta';
|
|
13
|
+
|
|
14
|
+
type SurfaceData = {
|
|
15
|
+
attendableId: string;
|
|
16
|
+
properties: Record<string, any>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const ALLOWED_DISPOSITIONS = ['workspace', 'user-account', 'pin-end'];
|
|
20
|
+
|
|
21
|
+
export default Capability.makeModule(() =>
|
|
22
|
+
Effect.succeed(
|
|
23
|
+
Capability.contributes(Common.Capability.ReactSurface, [
|
|
24
|
+
Common.createSurface({
|
|
25
|
+
id: `${meta.id}/home`,
|
|
26
|
+
role: 'article',
|
|
27
|
+
filter: (data): data is SurfaceData => data.attendableId === Node.RootId,
|
|
28
|
+
component: () => <Home />,
|
|
29
|
+
}),
|
|
30
|
+
Common.createSurface({
|
|
31
|
+
id: `${meta.id}/workspace-article`,
|
|
32
|
+
role: 'article',
|
|
33
|
+
position: 'fallback',
|
|
34
|
+
filter: (data): data is SurfaceData =>
|
|
35
|
+
ALLOWED_DISPOSITIONS.includes((data.properties as Record<string, any>)?.disposition),
|
|
36
|
+
component: ({ data }) => <Workspace id={data.attendableId} />,
|
|
37
|
+
}),
|
|
38
|
+
]),
|
|
39
|
+
),
|
|
40
|
+
);
|
package/src/{hooks/useSpotlightDismiss.ts → capabilities/spotlight-dismiss/spotlight-dismiss.ts}
RENAMED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
// Based on the frontend-driven dismiss pattern from:
|
|
6
6
|
// https://github.com/Jedliu/tauri-template-demo
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import * as Effect from 'effect/Effect';
|
|
9
9
|
|
|
10
|
+
import { Capability, Common } from '@dxos/app-framework';
|
|
10
11
|
import { log } from '@dxos/log';
|
|
11
12
|
import { isTauri } from '@dxos/util';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Get the Tauri window API from the global object.
|
|
15
|
-
* Returns undefined if not running in Tauri.
|
|
16
16
|
*/
|
|
17
17
|
const getTauriWindow = (): any => {
|
|
18
18
|
const tauri = (globalThis as any).__TAURI__;
|
|
@@ -21,60 +21,46 @@ const getTauriWindow = (): any => {
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Get the Tauri core API (invoke) from the global object.
|
|
24
|
-
* Returns undefined if not running in Tauri.
|
|
25
24
|
*/
|
|
26
25
|
const getTauriCore = (): any => {
|
|
27
26
|
const tauri = (globalThis as any).__TAURI__;
|
|
28
27
|
return tauri?.core;
|
|
29
28
|
};
|
|
30
29
|
|
|
30
|
+
export type SpotlightDismissOptions = {
|
|
31
|
+
/** Whether running in popover window context. */
|
|
32
|
+
isPopover?: boolean;
|
|
33
|
+
};
|
|
34
|
+
|
|
31
35
|
/**
|
|
32
|
-
*
|
|
36
|
+
* Capability that sets up spotlight panel dismiss behavior.
|
|
33
37
|
* When running in Tauri popover mode, listens for focus loss and Escape key
|
|
34
|
-
* to dismiss the spotlight panel.
|
|
38
|
+
* to dismiss the spotlight panel. Runs at startup before React renders.
|
|
35
39
|
*/
|
|
36
|
-
export
|
|
37
|
-
|
|
38
|
-
useEffect(() => {
|
|
40
|
+
export default Capability.makeModule(({ isPopover = false }: SpotlightDismissOptions = {}) =>
|
|
41
|
+
Effect.promise(async () => {
|
|
39
42
|
if (!isPopover || !isTauri()) {
|
|
40
|
-
return;
|
|
43
|
+
return [];
|
|
41
44
|
}
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (!tauriWindow || !tauriCore) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
|
|
46
|
+
// Set up focus listener.
|
|
47
|
+
let focusCleanup: (() => void) | undefined;
|
|
48
|
+
try {
|
|
49
|
+
const tauriWindow = getTauriWindow();
|
|
50
|
+
const tauriCore = getTauriCore();
|
|
51
|
+
if (tauriWindow && tauriCore) {
|
|
53
52
|
const win = tauriWindow.getCurrentWindow();
|
|
54
|
-
|
|
53
|
+
focusCleanup = await win.onFocusChanged(async ({ payload }: { payload: boolean }) => {
|
|
55
54
|
if (!payload) {
|
|
56
55
|
await tauriCore.invoke('hide_spotlight');
|
|
57
56
|
}
|
|
58
57
|
});
|
|
59
|
-
cleanup = unlisten;
|
|
60
|
-
} catch (err) {
|
|
61
|
-
log.catch(err);
|
|
62
58
|
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
void setup();
|
|
66
|
-
|
|
67
|
-
return () => {
|
|
68
|
-
cleanup?.();
|
|
69
|
-
};
|
|
70
|
-
}, [isPopover]);
|
|
71
|
-
|
|
72
|
-
// Handle Escape key to dismiss spotlight.
|
|
73
|
-
useEffect(() => {
|
|
74
|
-
if (!isPopover || !isTauri()) {
|
|
75
|
-
return;
|
|
59
|
+
} catch (err) {
|
|
60
|
+
log.catch(err);
|
|
76
61
|
}
|
|
77
62
|
|
|
63
|
+
// Set up Escape key listener.
|
|
78
64
|
const handleKeyDown = async (event: KeyboardEvent) => {
|
|
79
65
|
if (event.key === 'Escape') {
|
|
80
66
|
event.preventDefault();
|
|
@@ -88,8 +74,13 @@ export const useSpotlightDismiss = (isPopover: boolean | undefined) => {
|
|
|
88
74
|
}
|
|
89
75
|
}
|
|
90
76
|
};
|
|
91
|
-
|
|
92
77
|
window.addEventListener('keydown', handleKeyDown);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
78
|
+
|
|
79
|
+
return Capability.contributes(Common.Capability.Null, null, () =>
|
|
80
|
+
Effect.sync(() => {
|
|
81
|
+
focusCleanup?.();
|
|
82
|
+
window.removeEventListener('keydown', handleKeyDown);
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
85
|
+
}),
|
|
86
|
+
);
|
|
@@ -2,18 +2,20 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Atom } from '@effect-atom/atom-react';
|
|
5
6
|
import * as Effect from 'effect/Effect';
|
|
6
7
|
|
|
7
8
|
import { Capability, Common } from '@dxos/app-framework';
|
|
8
|
-
import {
|
|
9
|
+
import { Node } from '@dxos/plugin-graph';
|
|
9
10
|
|
|
10
11
|
import { type SimpleLayoutState } from '../../types';
|
|
11
12
|
import { SimpleLayoutState as SimpleLayoutStateCapability } from '../../types';
|
|
12
13
|
|
|
13
14
|
const defaultState: SimpleLayoutState = {
|
|
14
15
|
dialogOpen: false,
|
|
15
|
-
workspace:
|
|
16
|
-
previousWorkspace:
|
|
16
|
+
workspace: Node.RootId,
|
|
17
|
+
previousWorkspace: Node.RootId,
|
|
18
|
+
history: [],
|
|
17
19
|
isPopover: false,
|
|
18
20
|
};
|
|
19
21
|
|
|
@@ -23,38 +25,25 @@ export type SimpleLayoutStateOptions = {
|
|
|
23
25
|
|
|
24
26
|
export default Capability.makeModule(({ initialState }: SimpleLayoutStateOptions = {}) =>
|
|
25
27
|
Effect.sync(() => {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
get
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
},
|
|
41
|
-
get workspace() {
|
|
42
|
-
return state.workspace;
|
|
43
|
-
},
|
|
44
|
-
get active() {
|
|
45
|
-
return state.active ? [state.active] : [];
|
|
46
|
-
},
|
|
47
|
-
get inactive() {
|
|
48
|
-
return [];
|
|
49
|
-
},
|
|
50
|
-
get scrollIntoView() {
|
|
51
|
-
return undefined;
|
|
52
|
-
},
|
|
28
|
+
const stateAtom = Atom.make<SimpleLayoutState>({ ...defaultState, ...initialState });
|
|
29
|
+
|
|
30
|
+
const layoutAtom = Atom.make((get): Common.Capability.Layout => {
|
|
31
|
+
const state = get(stateAtom);
|
|
32
|
+
return {
|
|
33
|
+
mode: 'simple',
|
|
34
|
+
dialogOpen: state.dialogOpen,
|
|
35
|
+
sidebarOpen: false,
|
|
36
|
+
complementarySidebarOpen: false,
|
|
37
|
+
workspace: state.workspace,
|
|
38
|
+
active: state.active ? [state.active] : [],
|
|
39
|
+
inactive: [],
|
|
40
|
+
scrollIntoView: undefined,
|
|
41
|
+
};
|
|
53
42
|
});
|
|
54
43
|
|
|
55
44
|
return [
|
|
56
|
-
Capability.contributes(SimpleLayoutStateCapability,
|
|
57
|
-
Capability.contributes(Common.Capability.Layout,
|
|
45
|
+
Capability.contributes(SimpleLayoutStateCapability, stateAtom),
|
|
46
|
+
Capability.contributes(Common.Capability.Layout, layoutAtom),
|
|
58
47
|
];
|
|
59
48
|
}),
|
|
60
49
|
);
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
|
|
7
|
+
import { Capability, Common } from '@dxos/app-framework';
|
|
8
|
+
import { Node } from '@dxos/plugin-graph';
|
|
9
|
+
|
|
10
|
+
import { type SimpleLayoutState, SimpleLayoutState as SimpleLayoutStateCapability } from '../../types';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* URL handler for simple layout that syncs browser URL with layout state.
|
|
14
|
+
* URL format: /{workspace} or /{workspace}/{active}
|
|
15
|
+
* Root is represented as / or /root.
|
|
16
|
+
*/
|
|
17
|
+
export default Capability.makeModule(
|
|
18
|
+
Effect.fnUntraced(function* () {
|
|
19
|
+
const { invokeSync } = yield* Capability.get(Common.Capability.OperationInvoker);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Handle navigation events (initial load and popstate).
|
|
23
|
+
* Parses URL and updates state accordingly.
|
|
24
|
+
*/
|
|
25
|
+
const handleNavigation = () => {
|
|
26
|
+
const pathname = window.location.pathname;
|
|
27
|
+
|
|
28
|
+
// Parse URL segments: /{workspace}/{active}
|
|
29
|
+
const [_, nextWorkspace, nextActive] = pathname.split('/');
|
|
30
|
+
|
|
31
|
+
// Determine target workspace (empty or 'root' means Node.RootId).
|
|
32
|
+
const targetWorkspace = !nextWorkspace || nextWorkspace === 'root' ? Node.RootId : nextWorkspace;
|
|
33
|
+
|
|
34
|
+
// Navigate via operations (they will update state accordingly).
|
|
35
|
+
invokeSync(Common.LayoutOperation.SwitchWorkspace, { subject: targetWorkspace });
|
|
36
|
+
if (nextActive) {
|
|
37
|
+
invokeSync(Common.LayoutOperation.Open, { subject: [nextActive] });
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Handle initial URL and listen for browser navigation.
|
|
42
|
+
yield* Effect.sync(() => handleNavigation());
|
|
43
|
+
window.addEventListener('popstate', handleNavigation);
|
|
44
|
+
|
|
45
|
+
// Subscribe to state changes to update the URL.
|
|
46
|
+
let lastWorkspace: string | undefined;
|
|
47
|
+
let lastActive: string | undefined;
|
|
48
|
+
const unsubscribe = yield* Common.Capability.subscribeAtom(
|
|
49
|
+
SimpleLayoutStateCapability,
|
|
50
|
+
(state: SimpleLayoutState) => {
|
|
51
|
+
const { workspace, active } = state;
|
|
52
|
+
|
|
53
|
+
// Only update URL if relevant state changed.
|
|
54
|
+
if (workspace !== lastWorkspace || active !== lastActive) {
|
|
55
|
+
lastWorkspace = workspace;
|
|
56
|
+
lastActive = active;
|
|
57
|
+
|
|
58
|
+
// Build path: root is represented as /, other workspaces as /{workspace}.
|
|
59
|
+
let path: string;
|
|
60
|
+
if (workspace === Node.RootId) {
|
|
61
|
+
path = active ? `/${Node.RootId}/${active}` : '/';
|
|
62
|
+
} else {
|
|
63
|
+
path = active ? `/${workspace}/${active}` : `/${workspace}`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (window.location.pathname !== path) {
|
|
67
|
+
history.pushState(null, '', `${path}${window.location.search}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
return Capability.contributes(Common.Capability.Null, null, () =>
|
|
74
|
+
Effect.sync(() => {
|
|
75
|
+
window.removeEventListener('popstate', handleNavigation);
|
|
76
|
+
unsubscribe();
|
|
77
|
+
}),
|
|
78
|
+
);
|
|
79
|
+
}),
|
|
80
|
+
);
|