@dxos/plugin-deck 0.7.5-main.9d26e3a → 0.7.5-main.9d2a38b
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-67VRUD5K.mjs +121 -0
- package/dist/lib/browser/app-graph-builder-67VRUD5K.mjs.map +7 -0
- package/dist/lib/browser/check-app-scheme-GEX6W2R5.mjs +33 -0
- package/dist/lib/browser/check-app-scheme-GEX6W2R5.mjs.map +7 -0
- package/dist/lib/browser/chunk-2M4PXYNB.mjs +1052 -0
- package/dist/lib/browser/chunk-2M4PXYNB.mjs.map +7 -0
- package/dist/lib/browser/chunk-2PJNBVCY.mjs +39 -0
- package/dist/lib/browser/chunk-2PJNBVCY.mjs.map +7 -0
- package/dist/lib/browser/chunk-4C2AFTET.mjs +186 -0
- package/dist/lib/browser/chunk-4C2AFTET.mjs.map +7 -0
- package/dist/lib/browser/chunk-5VFDMW5M.mjs +17 -0
- package/dist/lib/browser/chunk-5VFDMW5M.mjs.map +7 -0
- package/dist/lib/browser/{chunk-GVOGPULO.mjs → chunk-JQJ5UWVB.mjs} +3 -3
- package/dist/lib/browser/chunk-JQJ5UWVB.mjs.map +7 -0
- package/dist/lib/browser/{chunk-ZC3K6C2W.mjs → chunk-KY5WXIXY.mjs} +11 -4
- package/dist/lib/browser/chunk-KY5WXIXY.mjs.map +7 -0
- package/dist/lib/browser/deck-PLCSKPGL.mjs +26 -0
- package/dist/lib/browser/deck-PLCSKPGL.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +131 -1770
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/intent-resolver-FVOQSTBX.mjs +152 -0
- package/dist/lib/browser/intent-resolver-FVOQSTBX.mjs.map +7 -0
- package/dist/lib/browser/intent-resolver-K7GW4A2I.mjs +249 -0
- package/dist/lib/browser/intent-resolver-K7GW4A2I.mjs.map +7 -0
- package/dist/lib/browser/location-QHRBQBQN.mjs +35 -0
- package/dist/lib/browser/location-QHRBQBQN.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/react-context-3BDW7W2N.mjs +32 -0
- package/dist/lib/browser/react-context-3BDW7W2N.mjs.map +7 -0
- package/dist/lib/browser/react-root-UL7ZDRVZ.mjs +50 -0
- package/dist/lib/browser/react-root-UL7ZDRVZ.mjs.map +7 -0
- package/dist/lib/browser/react-surface-VPNOGGNN.mjs +28 -0
- package/dist/lib/browser/react-surface-VPNOGGNN.mjs.map +7 -0
- package/dist/lib/browser/settings-FNWW6WIJ.mjs +29 -0
- package/dist/lib/browser/settings-FNWW6WIJ.mjs.map +7 -0
- package/dist/lib/browser/state-7I5BD7SE.mjs +34 -0
- package/dist/lib/browser/state-7I5BD7SE.mjs.map +7 -0
- package/dist/lib/browser/types.mjs +6 -6
- package/dist/lib/browser/url-handler-Z5B7LD3N.mjs +76 -0
- package/dist/lib/browser/url-handler-Z5B7LD3N.mjs.map +7 -0
- package/dist/types/src/DeckPlugin.d.ts +1 -5
- package/dist/types/src/DeckPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts +13 -0
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +5 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/layout/app-graph-builder.d.ts +181 -0
- package/dist/types/src/capabilities/layout/app-graph-builder.d.ts.map +1 -0
- package/dist/types/src/capabilities/layout/deck.d.ts +4 -0
- package/dist/types/src/capabilities/layout/deck.d.ts.map +1 -0
- package/dist/types/src/capabilities/layout/index.d.ts +229 -0
- package/dist/types/src/capabilities/layout/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/layout/intent-resolver.d.ts +4 -0
- package/dist/types/src/capabilities/layout/intent-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/layout/react-context.d.ts +8 -0
- package/dist/types/src/capabilities/layout/react-context.d.ts.map +1 -0
- package/dist/types/src/capabilities/layout/react-root.d.ts +7 -0
- package/dist/types/src/capabilities/layout/react-root.d.ts.map +1 -0
- package/dist/types/src/capabilities/layout/state.d.ts +42 -0
- package/dist/types/src/capabilities/layout/state.d.ts.map +1 -0
- package/dist/types/src/capabilities/navigation/check-app-scheme.d.ts +4 -0
- package/dist/types/src/capabilities/navigation/check-app-scheme.d.ts.map +1 -0
- package/dist/types/src/capabilities/navigation/index.d.ts +5 -0
- package/dist/types/src/capabilities/navigation/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/navigation/intent-resolver.d.ts +4 -0
- package/dist/types/src/capabilities/navigation/intent-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/navigation/location.d.ts +4 -0
- package/dist/types/src/capabilities/navigation/location.d.ts.map +1 -0
- package/dist/types/src/capabilities/navigation/set-location.d.ts +10 -0
- package/dist/types/src/capabilities/navigation/set-location.d.ts.map +1 -0
- package/dist/types/src/capabilities/navigation/url-handler.d.ts +4 -0
- package/dist/types/src/capabilities/navigation/url-handler.d.ts.map +1 -0
- package/dist/types/src/capabilities/settings/index.d.ts +3 -0
- package/dist/types/src/capabilities/settings/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/settings/react-surface.d.ts +4 -0
- package/dist/types/src/capabilities/settings/react-surface.d.ts.map +1 -0
- package/dist/types/src/capabilities/settings/settings.d.ts +4 -0
- package/dist/types/src/capabilities/settings/settings.d.ts.map +1 -0
- package/dist/types/src/components/DeckContext.d.ts +3 -0
- package/dist/types/src/components/DeckContext.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Banner.d.ts +6 -0
- package/dist/types/src/components/DeckLayout/Banner.d.ts.map +1 -0
- package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Plank.d.ts +1 -1
- package/dist/types/src/components/DeckLayout/Plank.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Sidebar.d.ts +1 -5
- package/dist/types/src/components/DeckLayout/Sidebar.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/SidebarButton.d.ts +6 -0
- package/dist/types/src/components/DeckLayout/SidebarButton.d.ts.map +1 -0
- package/dist/types/src/components/DeckLayout/Topbar.d.ts +3 -0
- package/dist/types/src/components/DeckLayout/Topbar.d.ts.map +1 -0
- package/dist/types/src/components/fragments.d.ts +2 -0
- package/dist/types/src/components/fragments.d.ts.map +1 -0
- package/dist/types/src/events.d.ts +4 -0
- package/dist/types/src/events.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +3 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +3 -4
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +2 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +12 -20
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -1
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/useBreakpoints.d.ts +2 -0
- package/dist/types/src/util/useBreakpoints.d.ts.map +1 -0
- package/dist/types/src/util/useHoistStatusbar.d.ts +2 -0
- package/dist/types/src/util/useHoistStatusbar.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +29 -35
- package/src/DeckPlugin.ts +123 -0
- package/src/capabilities/capabilities.ts +17 -0
- package/src/capabilities/index.ts +8 -0
- package/src/capabilities/layout/app-graph-builder.ts +101 -0
- package/src/capabilities/layout/deck.ts +25 -0
- package/src/capabilities/layout/index.ts +12 -0
- package/src/capabilities/layout/intent-resolver.ts +128 -0
- package/src/capabilities/layout/react-context.tsx +26 -0
- package/src/capabilities/layout/react-root.tsx +52 -0
- package/src/capabilities/layout/state.ts +32 -0
- package/src/capabilities/navigation/check-app-scheme.ts +44 -0
- package/src/capabilities/navigation/index.ts +10 -0
- package/src/capabilities/navigation/intent-resolver.ts +216 -0
- package/src/capabilities/navigation/location.ts +28 -0
- package/src/capabilities/navigation/set-location.ts +38 -0
- package/src/capabilities/navigation/url-handler.ts +67 -0
- package/src/capabilities/settings/index.ts +8 -0
- package/src/capabilities/settings/react-surface.tsx +23 -0
- package/src/capabilities/settings/settings.ts +22 -0
- package/src/components/DeckContext.ts +6 -1
- package/src/components/DeckLayout/Banner.tsx +37 -0
- package/src/components/DeckLayout/ComplementarySidebar.tsx +74 -52
- package/src/components/DeckLayout/ContentEmpty.tsx +10 -2
- package/src/components/DeckLayout/DeckLayout.tsx +28 -33
- package/src/components/DeckLayout/NodePlankHeading.tsx +15 -20
- package/src/components/DeckLayout/Plank.tsx +7 -7
- package/src/components/DeckLayout/Sidebar.tsx +21 -8
- package/src/components/DeckLayout/SidebarButton.tsx +74 -0
- package/src/components/DeckLayout/StatusBar.tsx +2 -2
- package/src/components/DeckLayout/Topbar.tsx +11 -0
- package/src/components/fragments.ts +6 -0
- package/src/events.ts +11 -0
- package/src/index.ts +3 -4
- package/src/meta.ts +2 -2
- package/src/translations.ts +2 -0
- package/src/types.ts +12 -37
- package/src/util/index.ts +1 -1
- package/src/util/useBreakpoints.ts +11 -0
- package/src/util/useHoistStatusbar.ts +15 -0
- package/dist/lib/browser/chunk-GVOGPULO.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZC3K6C2W.mjs.map +0 -7
- package/dist/lib/browser/meta.mjs +0 -9
- package/dist/lib/browser/meta.mjs.map +0 -7
- package/dist/types/src/util/check-app-scheme.d.ts +0 -2
- package/dist/types/src/util/check-app-scheme.d.ts.map +0 -1
- package/src/DeckPlugin.tsx +0 -623
- package/src/util/check-app-scheme.ts +0 -21
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { setAutoFreeze } from 'immer';
|
|
6
|
+
|
|
7
|
+
import { allOf, Capabilities, contributes, defineModule, definePlugin, Events, oneOf } from '@dxos/app-framework';
|
|
8
|
+
import { AttentionEvents } from '@dxos/plugin-attention';
|
|
9
|
+
import { translations as stackTranslations } from '@dxos/react-ui-stack';
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
AppGraphBuilder,
|
|
13
|
+
CheckAppScheme,
|
|
14
|
+
DeckState,
|
|
15
|
+
LayoutIntentResolver,
|
|
16
|
+
LayoutState,
|
|
17
|
+
LocationState,
|
|
18
|
+
NavigationIntentResolver,
|
|
19
|
+
ReactContext,
|
|
20
|
+
ReactRoot,
|
|
21
|
+
DeckSettings,
|
|
22
|
+
ReactSurface,
|
|
23
|
+
UrlHandler,
|
|
24
|
+
} from './capabilities';
|
|
25
|
+
import { DeckEvents } from './events';
|
|
26
|
+
import { meta } from './meta';
|
|
27
|
+
import translations from './translations';
|
|
28
|
+
|
|
29
|
+
// NOTE(Zan): When producing values with immer, we shouldn't auto-freeze them because
|
|
30
|
+
// our signal implementation needs to add some hidden properties to the produced values.
|
|
31
|
+
// TODO(Zan): Move this to a more global location if we use immer more broadly.
|
|
32
|
+
setAutoFreeze(false);
|
|
33
|
+
|
|
34
|
+
export const DeckPlugin = () =>
|
|
35
|
+
definePlugin(meta, [
|
|
36
|
+
//
|
|
37
|
+
// Settings
|
|
38
|
+
//
|
|
39
|
+
|
|
40
|
+
defineModule({
|
|
41
|
+
id: `${meta.id}/module/settings`,
|
|
42
|
+
activatesOn: Events.SetupSettings,
|
|
43
|
+
activate: DeckSettings,
|
|
44
|
+
}),
|
|
45
|
+
defineModule({
|
|
46
|
+
id: `${meta.id}/module/react-surface`,
|
|
47
|
+
activatesOn: Events.Startup,
|
|
48
|
+
activate: ReactSurface,
|
|
49
|
+
}),
|
|
50
|
+
|
|
51
|
+
//
|
|
52
|
+
// Layout
|
|
53
|
+
//
|
|
54
|
+
|
|
55
|
+
defineModule({
|
|
56
|
+
id: `${meta.id}/module/layout`,
|
|
57
|
+
activatesOn: oneOf(Events.Startup, Events.SetupAppGraph),
|
|
58
|
+
activatesAfter: [Events.LayoutReady],
|
|
59
|
+
activate: LayoutState,
|
|
60
|
+
}),
|
|
61
|
+
defineModule({
|
|
62
|
+
id: `${meta.id}/module/deck`,
|
|
63
|
+
activatesOn: oneOf(Events.Startup, Events.SetupAppGraph),
|
|
64
|
+
activatesAfter: [DeckEvents.StateReady],
|
|
65
|
+
activate: DeckState,
|
|
66
|
+
}),
|
|
67
|
+
defineModule({
|
|
68
|
+
id: `${meta.id}/module/translations`,
|
|
69
|
+
activatesOn: Events.SetupTranslations,
|
|
70
|
+
activate: () => contributes(Capabilities.Translations, [...translations, ...stackTranslations]),
|
|
71
|
+
}),
|
|
72
|
+
defineModule({
|
|
73
|
+
id: `${meta.id}/module/react-context`,
|
|
74
|
+
activatesOn: Events.Startup,
|
|
75
|
+
activate: ReactContext,
|
|
76
|
+
}),
|
|
77
|
+
defineModule({
|
|
78
|
+
id: `${meta.id}/module/react-root`,
|
|
79
|
+
activatesOn: Events.Startup,
|
|
80
|
+
activate: ReactRoot,
|
|
81
|
+
}),
|
|
82
|
+
defineModule({
|
|
83
|
+
id: `${meta.id}/module/layout-intent-resolver`,
|
|
84
|
+
activatesOn: Events.SetupIntents,
|
|
85
|
+
activate: LayoutIntentResolver,
|
|
86
|
+
}),
|
|
87
|
+
defineModule({
|
|
88
|
+
id: `${meta.id}/module/app-graph-builder`,
|
|
89
|
+
activatesOn: Events.SetupAppGraph,
|
|
90
|
+
activate: AppGraphBuilder,
|
|
91
|
+
}),
|
|
92
|
+
|
|
93
|
+
//
|
|
94
|
+
// Navigation
|
|
95
|
+
//
|
|
96
|
+
|
|
97
|
+
defineModule({
|
|
98
|
+
id: `${meta.id}/module/location`,
|
|
99
|
+
activatesOn: oneOf(Events.Startup, Events.SetupAppGraph),
|
|
100
|
+
activatesAfter: [Events.LocationReady],
|
|
101
|
+
activate: LocationState,
|
|
102
|
+
}),
|
|
103
|
+
defineModule({
|
|
104
|
+
id: `${meta.id}/module/check-app-scheme`,
|
|
105
|
+
activatesOn: Events.SettingsReady,
|
|
106
|
+
activate: CheckAppScheme,
|
|
107
|
+
}),
|
|
108
|
+
defineModule({
|
|
109
|
+
id: `${meta.id}/module/url`,
|
|
110
|
+
activatesOn: allOf(
|
|
111
|
+
Events.DispatcherReady,
|
|
112
|
+
Events.LayoutReady,
|
|
113
|
+
Events.LocationReady,
|
|
114
|
+
AttentionEvents.AttentionReady,
|
|
115
|
+
),
|
|
116
|
+
activate: UrlHandler,
|
|
117
|
+
}),
|
|
118
|
+
defineModule({
|
|
119
|
+
id: `${meta.id}/module/navigation-intent-resolver`,
|
|
120
|
+
activatesOn: Events.SetupIntents,
|
|
121
|
+
activate: NavigationIntentResolver,
|
|
122
|
+
}),
|
|
123
|
+
]);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { defineCapability, type Label } from '@dxos/app-framework';
|
|
6
|
+
import { type DeepReadonly } from '@dxos/util';
|
|
7
|
+
|
|
8
|
+
import { type DeckContextType } from '../components';
|
|
9
|
+
import { DECK_PLUGIN } from '../meta';
|
|
10
|
+
|
|
11
|
+
export namespace DeckCapabilities {
|
|
12
|
+
export const DeckState = defineCapability<DeepReadonly<DeckContextType>>(`${DECK_PLUGIN}/capability/state`);
|
|
13
|
+
export const MutableDeckState = defineCapability<DeckContextType>(`${DECK_PLUGIN}/capability/state`);
|
|
14
|
+
export const ComplementaryPanel = defineCapability<{ id: string; label: Label; icon: string }>(
|
|
15
|
+
`${DECK_PLUGIN}/capability/complementary-panel`,
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
Capabilities,
|
|
7
|
+
contributes,
|
|
8
|
+
createIntent,
|
|
9
|
+
LayoutAction,
|
|
10
|
+
NavigationAction,
|
|
11
|
+
openIds,
|
|
12
|
+
type PluginsContext,
|
|
13
|
+
} from '@dxos/app-framework';
|
|
14
|
+
import { AttentionCapabilities } from '@dxos/plugin-attention';
|
|
15
|
+
import { createExtension, type Node, ROOT_ID } from '@dxos/plugin-graph';
|
|
16
|
+
|
|
17
|
+
import { DECK_PLUGIN } from '../../meta';
|
|
18
|
+
|
|
19
|
+
export default (context: PluginsContext) =>
|
|
20
|
+
contributes(
|
|
21
|
+
Capabilities.AppGraphBuilder,
|
|
22
|
+
createExtension({
|
|
23
|
+
id: DECK_PLUGIN,
|
|
24
|
+
filter: (node): node is Node<null> => node.id === ROOT_ID,
|
|
25
|
+
actions: () => {
|
|
26
|
+
// NOTE(Zan): This is currently disabled.
|
|
27
|
+
// TODO(Zan): Fullscreen needs to know the active node and provide that to the layout part.
|
|
28
|
+
const _fullscreen = {
|
|
29
|
+
id: `${LayoutAction.SetLayoutMode._tag}/fullscreen`,
|
|
30
|
+
data: async () => {
|
|
31
|
+
const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
|
|
32
|
+
await dispatch(createIntent(LayoutAction.SetLayoutMode, { layoutMode: 'fullscreen' }));
|
|
33
|
+
},
|
|
34
|
+
properties: {
|
|
35
|
+
label: ['toggle fullscreen label', { ns: DECK_PLUGIN }],
|
|
36
|
+
icon: 'ph--arrows-out--regular',
|
|
37
|
+
keyBinding: {
|
|
38
|
+
macos: 'ctrl+meta+f',
|
|
39
|
+
windows: 'shift+ctrl+f',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const closeCurrent = {
|
|
45
|
+
id: `${NavigationAction.Close._tag}/current`,
|
|
46
|
+
data: async () => {
|
|
47
|
+
const attention = context.requestCapability(AttentionCapabilities.Attention);
|
|
48
|
+
const attended = attention.current.at(-1);
|
|
49
|
+
if (attended) {
|
|
50
|
+
const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
|
|
51
|
+
await dispatch(createIntent(NavigationAction.Close, { activeParts: { main: [attended] } }));
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
properties: {
|
|
55
|
+
label: ['close current label', { ns: DECK_PLUGIN }],
|
|
56
|
+
icon: 'ph--x--regular',
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const closeOthers = {
|
|
61
|
+
id: `${NavigationAction.Close._tag}/others`,
|
|
62
|
+
data: async () => {
|
|
63
|
+
const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
|
|
64
|
+
const location = context.requestCapability(Capabilities.Location);
|
|
65
|
+
const attention = context.requestCapability(AttentionCapabilities.Attention);
|
|
66
|
+
const attended = attention.current.at(-1);
|
|
67
|
+
const ids = openIds(location.active, ['main']).filter((id) => id !== attended);
|
|
68
|
+
await dispatch(
|
|
69
|
+
createIntent(NavigationAction.Close, {
|
|
70
|
+
activeParts: { main: ids },
|
|
71
|
+
}),
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
properties: {
|
|
75
|
+
label: ['close others label', { ns: DECK_PLUGIN }],
|
|
76
|
+
icon: 'ph--x-square--regular',
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const closeAll = {
|
|
81
|
+
id: `${NavigationAction.Close._tag}/all`,
|
|
82
|
+
data: async () => {
|
|
83
|
+
const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
|
|
84
|
+
const location = context.requestCapability(Capabilities.Location);
|
|
85
|
+
await dispatch(
|
|
86
|
+
createIntent(NavigationAction.Close, {
|
|
87
|
+
activeParts: { main: openIds(location.active, ['main']) },
|
|
88
|
+
}),
|
|
89
|
+
);
|
|
90
|
+
},
|
|
91
|
+
properties: {
|
|
92
|
+
label: ['close all label', { ns: DECK_PLUGIN }],
|
|
93
|
+
icon: 'ph--x-circle--regular',
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const layoutMode = context.requestCapabilities(Capabilities.Layout)[0]?.layoutMode;
|
|
98
|
+
return layoutMode === 'deck' ? [closeCurrent, closeOthers, closeAll] : [];
|
|
99
|
+
},
|
|
100
|
+
}),
|
|
101
|
+
);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { contributes } from '@dxos/app-framework';
|
|
6
|
+
import { LocalStorageStore } from '@dxos/local-storage';
|
|
7
|
+
|
|
8
|
+
import { type DeckContextType } from '../../components';
|
|
9
|
+
import { DeckCapabilities } from '../capabilities';
|
|
10
|
+
|
|
11
|
+
// NOTE: The key is this currently for backwards compatibility of storage.
|
|
12
|
+
const DECK_KEY = 'dxos.org/settings/deck';
|
|
13
|
+
|
|
14
|
+
export default () => {
|
|
15
|
+
const deck = new LocalStorageStore<DeckContextType>(DECK_KEY, {
|
|
16
|
+
plankSizing: {},
|
|
17
|
+
currentUndoId: undefined,
|
|
18
|
+
// TODO(Zan): Cap depth!
|
|
19
|
+
layoutModeHistory: [],
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
deck.prop({ key: 'plankSizing', type: LocalStorageStore.json<Record<string, number>>() });
|
|
23
|
+
|
|
24
|
+
return contributes(DeckCapabilities.DeckState, deck.values, () => deck.close());
|
|
25
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { lazy } from '@dxos/app-framework';
|
|
6
|
+
|
|
7
|
+
export const DeckState = lazy(() => import('./deck'));
|
|
8
|
+
export const AppGraphBuilder = lazy(() => import('./app-graph-builder'));
|
|
9
|
+
export const LayoutIntentResolver = lazy(() => import('./intent-resolver'));
|
|
10
|
+
export const LayoutState = lazy(() => import('./state'));
|
|
11
|
+
export const ReactContext = lazy(() => import('./react-context'));
|
|
12
|
+
export const ReactRoot = lazy(() => import('./react-root'));
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { batch } from '@preact/signals-core';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
Capabilities,
|
|
9
|
+
createResolver,
|
|
10
|
+
contributes,
|
|
11
|
+
IntentAction,
|
|
12
|
+
LayoutAction,
|
|
13
|
+
openIds,
|
|
14
|
+
Toast as ToastSchema,
|
|
15
|
+
type LayoutMode,
|
|
16
|
+
type PluginsContext,
|
|
17
|
+
} from '@dxos/app-framework';
|
|
18
|
+
import { S } from '@dxos/echo-schema';
|
|
19
|
+
import { log } from '@dxos/log';
|
|
20
|
+
|
|
21
|
+
import { DECK_PLUGIN } from '../../meta';
|
|
22
|
+
import { DeckAction } from '../../types';
|
|
23
|
+
import { DeckCapabilities } from '../capabilities';
|
|
24
|
+
|
|
25
|
+
export default (context: PluginsContext) =>
|
|
26
|
+
contributes(Capabilities.IntentResolver, [
|
|
27
|
+
createResolver(DeckAction.UpdatePlankSize, (data) => {
|
|
28
|
+
const deck = context.requestCapability(DeckCapabilities.MutableDeckState);
|
|
29
|
+
deck.plankSizing[data.id] = data.size;
|
|
30
|
+
}),
|
|
31
|
+
createResolver(IntentAction.ShowUndo, (data) => {
|
|
32
|
+
const deck = context.requestCapability(DeckCapabilities.MutableDeckState);
|
|
33
|
+
const layout = context.requestCapability(Capabilities.MutableLayout);
|
|
34
|
+
const { undoPromise: undo } = context.requestCapability(Capabilities.IntentDispatcher);
|
|
35
|
+
|
|
36
|
+
// TODO(wittjosiah): Support undoing further back than the last action.
|
|
37
|
+
if (deck.currentUndoId) {
|
|
38
|
+
layout.toasts = layout.toasts.filter((toast) => toast.id !== deck.currentUndoId);
|
|
39
|
+
}
|
|
40
|
+
deck.currentUndoId = `${IntentAction.ShowUndo._tag}-${Date.now()}`;
|
|
41
|
+
layout.toasts = [
|
|
42
|
+
...layout.toasts,
|
|
43
|
+
{
|
|
44
|
+
id: deck.currentUndoId,
|
|
45
|
+
title: data.message ?? ['undo available label', { ns: DECK_PLUGIN }],
|
|
46
|
+
duration: 10_000,
|
|
47
|
+
actionLabel: ['undo action label', { ns: DECK_PLUGIN }],
|
|
48
|
+
actionAlt: ['undo action alt', { ns: DECK_PLUGIN }],
|
|
49
|
+
closeLabel: ['undo close label', { ns: DECK_PLUGIN }],
|
|
50
|
+
onAction: () => undo(),
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
}),
|
|
54
|
+
createResolver(
|
|
55
|
+
LayoutAction.SetLayout,
|
|
56
|
+
({ element, state, component, subject, anchorId, dialogBlockAlign, dialogType }) => {
|
|
57
|
+
const layout = context.requestCapability(Capabilities.MutableLayout);
|
|
58
|
+
switch (element) {
|
|
59
|
+
case 'sidebar': {
|
|
60
|
+
layout.sidebarOpen = state ?? !layout.sidebarOpen;
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
case 'complementary': {
|
|
65
|
+
layout.complementarySidebarOpen = !!state;
|
|
66
|
+
// TODO(thure): Hoist content into the c11y sidebar of Deck.
|
|
67
|
+
// layout.complementarySidebarContent = component || subject ? { component, subject } : null;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
case 'dialog': {
|
|
72
|
+
layout.dialogOpen = state ?? Boolean(component);
|
|
73
|
+
layout.dialogContent = component ? { component, subject } : null;
|
|
74
|
+
layout.dialogBlockAlign = dialogBlockAlign ?? 'center';
|
|
75
|
+
layout.dialogType = dialogType;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
case 'popover': {
|
|
80
|
+
layout.popoverOpen = state ?? Boolean(component);
|
|
81
|
+
layout.popoverContent = component ? { component, subject } : null;
|
|
82
|
+
layout.popoverAnchorId = anchorId;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
case 'toast': {
|
|
87
|
+
if (S.is(ToastSchema)(subject)) {
|
|
88
|
+
layout.toasts = [...layout.toasts, subject];
|
|
89
|
+
}
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
),
|
|
95
|
+
createResolver(LayoutAction.SetLayoutMode, (data) => {
|
|
96
|
+
const layout = context.requestCapability(Capabilities.MutableLayout);
|
|
97
|
+
const location = context.requestCapability(Capabilities.MutableLocation);
|
|
98
|
+
const deck = context.requestCapability(DeckCapabilities.MutableDeckState);
|
|
99
|
+
|
|
100
|
+
const setMode = (mode: LayoutMode) => {
|
|
101
|
+
const main = openIds(location.active, ['main']);
|
|
102
|
+
const solo = openIds(location.active, ['solo']);
|
|
103
|
+
const current = layout.layoutMode === 'solo' ? solo : main;
|
|
104
|
+
// When un-soloing, the solo entry is added to the deck.
|
|
105
|
+
const next = mode === 'solo' ? solo : [...main, ...solo];
|
|
106
|
+
const removed = current.filter((id) => !next.includes(id));
|
|
107
|
+
const closed = Array.from(new Set([...location.closed.filter((id) => !next.includes(id)), ...removed]));
|
|
108
|
+
|
|
109
|
+
location.closed = closed;
|
|
110
|
+
layout.layoutMode = mode;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return batch(() => {
|
|
114
|
+
if ('layoutMode' in data) {
|
|
115
|
+
deck.layoutModeHistory.push(layout.layoutMode);
|
|
116
|
+
setMode(data.layoutMode);
|
|
117
|
+
} else if (data.revert) {
|
|
118
|
+
setMode(deck.layoutModeHistory.pop() ?? 'solo');
|
|
119
|
+
} else {
|
|
120
|
+
log.warn('Invalid layout mode', data);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}),
|
|
124
|
+
createResolver(LayoutAction.ScrollIntoView, ({ id }) => {
|
|
125
|
+
const layout = context.requestCapability(Capabilities.MutableLayout);
|
|
126
|
+
layout.scrollIntoView = id;
|
|
127
|
+
}),
|
|
128
|
+
]);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { type PropsWithChildren } from 'react';
|
|
6
|
+
|
|
7
|
+
import { Capabilities, contributes, useCapability } from '@dxos/app-framework';
|
|
8
|
+
|
|
9
|
+
import { DeckContext, LayoutContext } from '../../components';
|
|
10
|
+
import { DECK_PLUGIN } from '../../meta';
|
|
11
|
+
import { DeckCapabilities } from '../capabilities';
|
|
12
|
+
|
|
13
|
+
export default () =>
|
|
14
|
+
contributes(Capabilities.ReactContext, {
|
|
15
|
+
id: DECK_PLUGIN,
|
|
16
|
+
context: (props: PropsWithChildren) => {
|
|
17
|
+
const layout = useCapability(Capabilities.Layout);
|
|
18
|
+
const deck = useCapability(DeckCapabilities.MutableDeckState);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<LayoutContext.Provider value={layout}>
|
|
22
|
+
<DeckContext.Provider value={deck}>{props.children}</DeckContext.Provider>
|
|
23
|
+
</LayoutContext.Provider>
|
|
24
|
+
);
|
|
25
|
+
},
|
|
26
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useCallback } from 'react';
|
|
6
|
+
|
|
7
|
+
import { Capabilities, contributes, useCapabilities, useCapability } from '@dxos/app-framework';
|
|
8
|
+
|
|
9
|
+
import { DeckLayout } from '../../components';
|
|
10
|
+
import { DECK_PLUGIN } from '../../meta';
|
|
11
|
+
import { type DeckSettingsProps } from '../../types';
|
|
12
|
+
import { DeckCapabilities } from '../capabilities';
|
|
13
|
+
|
|
14
|
+
export default () =>
|
|
15
|
+
contributes(Capabilities.ReactRoot, {
|
|
16
|
+
id: DECK_PLUGIN,
|
|
17
|
+
root: () => {
|
|
18
|
+
const layout = useCapability(Capabilities.Layout);
|
|
19
|
+
const location = useCapability(Capabilities.Location);
|
|
20
|
+
const deck = useCapability(DeckCapabilities.MutableDeckState);
|
|
21
|
+
const settings = useCapability(Capabilities.SettingsStore).getStore<DeckSettingsProps>(DECK_PLUGIN)!.value;
|
|
22
|
+
const panels = useCapabilities(DeckCapabilities.ComplementaryPanel);
|
|
23
|
+
|
|
24
|
+
const handleDismissToast = useCallback(
|
|
25
|
+
(id: string) => {
|
|
26
|
+
const index = layout.toasts.findIndex((toast) => toast.id === id);
|
|
27
|
+
if (index !== -1) {
|
|
28
|
+
// Allow time for the toast to animate out.
|
|
29
|
+
// TODO(burdon): Factor out and unregister timeout.
|
|
30
|
+
setTimeout(() => {
|
|
31
|
+
if (layout.toasts[index].id === deck.currentUndoId) {
|
|
32
|
+
deck.currentUndoId = undefined;
|
|
33
|
+
}
|
|
34
|
+
layout.toasts.splice(index, 1);
|
|
35
|
+
}, 1_000);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
[layout.toasts],
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<DeckLayout
|
|
43
|
+
layoutParts={location.active}
|
|
44
|
+
showHints={settings.showHints}
|
|
45
|
+
overscroll={settings.overscroll}
|
|
46
|
+
toasts={layout.toasts}
|
|
47
|
+
panels={panels}
|
|
48
|
+
onDismissToast={handleDismissToast}
|
|
49
|
+
/>
|
|
50
|
+
);
|
|
51
|
+
},
|
|
52
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Capabilities, contributes, type LayoutMode, type Layout } from '@dxos/app-framework';
|
|
6
|
+
import { LocalStorageStore } from '@dxos/local-storage';
|
|
7
|
+
|
|
8
|
+
// NOTE: The key is this currently for backwards compatibility of storage.
|
|
9
|
+
const LAYOUT_KEY = 'dxos.org/settings/layout';
|
|
10
|
+
|
|
11
|
+
export default () => {
|
|
12
|
+
const layout = new LocalStorageStore<Layout>(LAYOUT_KEY, {
|
|
13
|
+
layoutMode: 'solo',
|
|
14
|
+
sidebarOpen: true,
|
|
15
|
+
complementarySidebarOpen: false,
|
|
16
|
+
dialogContent: null,
|
|
17
|
+
dialogOpen: false,
|
|
18
|
+
dialogBlockAlign: undefined,
|
|
19
|
+
dialogType: undefined,
|
|
20
|
+
popoverContent: null,
|
|
21
|
+
popoverAnchorId: undefined,
|
|
22
|
+
popoverOpen: false,
|
|
23
|
+
toasts: [],
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
layout
|
|
27
|
+
.prop({ key: 'layoutMode', type: LocalStorageStore.enum<LayoutMode>() })
|
|
28
|
+
.prop({ key: 'sidebarOpen', type: LocalStorageStore.bool() })
|
|
29
|
+
.prop({ key: 'complementarySidebarOpen', type: LocalStorageStore.bool() });
|
|
30
|
+
|
|
31
|
+
return contributes(Capabilities.Layout, layout.values, () => layout.close());
|
|
32
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
//
|
|
5
|
+
// Copyright 2025 DXOS.org
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import { Capabilities, contributes, type PluginsContext } from '@dxos/app-framework';
|
|
9
|
+
|
|
10
|
+
import { DECK_PLUGIN } from '../../meta';
|
|
11
|
+
import { type DeckSettingsProps } from '../../types';
|
|
12
|
+
|
|
13
|
+
const isSocket = !!(globalThis as any).__args;
|
|
14
|
+
|
|
15
|
+
// TODO(mjamesderocher): Can we get this directly from Socket?
|
|
16
|
+
const appScheme = 'composer://';
|
|
17
|
+
|
|
18
|
+
// TODO(mjamesderocher): Factor out as part of NavigationPlugin.
|
|
19
|
+
const checkAppScheme = (url: string) => {
|
|
20
|
+
const iframe = document.createElement('iframe');
|
|
21
|
+
iframe.style.display = 'none';
|
|
22
|
+
document.body.appendChild(iframe);
|
|
23
|
+
|
|
24
|
+
iframe.src = url + window.location.pathname.replace(/^\/+/, '') + window.location.search;
|
|
25
|
+
|
|
26
|
+
const timer = setTimeout(() => {
|
|
27
|
+
document.body.removeChild(iframe);
|
|
28
|
+
}, 3000);
|
|
29
|
+
|
|
30
|
+
window.addEventListener('pagehide', (event) => {
|
|
31
|
+
clearTimeout(timer);
|
|
32
|
+
document.body.removeChild(iframe);
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default async (context: PluginsContext) => {
|
|
37
|
+
const settingsStore = context.requestCapability(Capabilities.SettingsStore);
|
|
38
|
+
const settings = settingsStore.getStore<DeckSettingsProps>(DECK_PLUGIN)?.value;
|
|
39
|
+
if (!isSocket && settings?.enableNativeRedirect) {
|
|
40
|
+
checkAppScheme(appScheme);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return contributes(Capabilities.Null, null);
|
|
44
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { lazy } from '@dxos/app-framework';
|
|
6
|
+
|
|
7
|
+
export const CheckAppScheme = lazy(() => import('./check-app-scheme'));
|
|
8
|
+
export const LocationState = lazy(() => import('./location'));
|
|
9
|
+
export const NavigationIntentResolver = lazy(() => import('./intent-resolver'));
|
|
10
|
+
export const UrlHandler = lazy(() => import('./url-handler'));
|