@dxos/plugin-deck 0.8.2-main.f081794 → 0.8.2-main.fbd8ed0
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-VYZ4IWI3.mjs → app-graph-builder-R7COZ4A6.mjs} +16 -15
- package/dist/lib/browser/app-graph-builder-R7COZ4A6.mjs.map +7 -0
- package/dist/lib/browser/{check-app-scheme-SEYECDHI.mjs → check-app-scheme-7AXGR6UT.mjs} +2 -3
- package/dist/lib/browser/check-app-scheme-7AXGR6UT.mjs.map +7 -0
- package/dist/lib/browser/chunk-3O2UZVBA.mjs +121 -0
- package/dist/lib/browser/chunk-3O2UZVBA.mjs.map +7 -0
- package/dist/lib/browser/chunk-JAYQ5BTF.mjs +157 -0
- package/dist/lib/browser/chunk-JAYQ5BTF.mjs.map +7 -0
- package/dist/lib/browser/{chunk-VP6FCWFV.mjs → chunk-KIGMELV2.mjs} +257 -247
- package/dist/lib/browser/chunk-KIGMELV2.mjs.map +7 -0
- package/dist/lib/browser/{state-Z6UY2Z3M.mjs → chunk-OF5RIATN.mjs} +6 -4
- package/dist/lib/browser/chunk-OF5RIATN.mjs.map +7 -0
- package/dist/lib/browser/chunk-TRFYUEBA.mjs +145 -0
- package/dist/lib/browser/chunk-TRFYUEBA.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +4 -5
- package/dist/lib/browser/index.mjs.map +1 -1
- package/dist/lib/browser/{intent-resolver-6AK45PT5.mjs → intent-resolver-MAKOS57L.mjs} +86 -63
- package/dist/lib/browser/intent-resolver-MAKOS57L.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-root-KA2IL5RA.mjs → react-root-DGQVIHXP.mjs} +6 -6
- package/dist/lib/browser/{react-surface-LIPGYEYN.mjs → react-surface-PXBXIOPU.mjs} +6 -6
- package/dist/lib/browser/{settings-6NU7CF2B.mjs → settings-UBWJF7J7.mjs} +4 -4
- package/dist/lib/browser/{settings-6NU7CF2B.mjs.map → settings-UBWJF7J7.mjs.map} +3 -3
- package/dist/lib/browser/state-4WFB4SDO.mjs +10 -0
- package/dist/lib/browser/state-4WFB4SDO.mjs.map +7 -0
- package/dist/lib/browser/{tools-VDVQTJMD.mjs → tools-IVPIPTVA.mjs} +7 -7
- package/dist/lib/browser/tools-IVPIPTVA.mjs.map +7 -0
- package/dist/lib/browser/types.mjs +1 -1
- package/dist/lib/browser/{url-handler-3CARFXQK.mjs → url-handler-JSYGSVSB.mjs} +4 -4
- package/dist/lib/browser/url-handler-JSYGSVSB.mjs.map +7 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts +2 -179
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/check-app-scheme.d.ts +2 -2
- package/dist/types/src/capabilities/check-app-scheme.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +5 -180
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +2 -2
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/state.d.ts +2 -2
- package/dist/types/src/capabilities/state.d.ts.map +1 -1
- package/dist/types/src/capabilities/tools.d.ts.map +1 -1
- package/dist/types/src/capabilities/url-handler.d.ts +2 -2
- package/dist/types/src/capabilities/url-handler.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Banner.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/Popover.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/StatusBar.d.ts.map +1 -1
- package/dist/types/src/components/DeckLayout/Toast.d.ts.map +1 -1
- package/dist/types/src/components/DeckSettings/DeckSettings.d.ts.map +1 -1
- package/dist/types/src/components/Plank/Plank.d.ts +18 -5
- package/dist/types/src/components/Plank/Plank.d.ts.map +1 -1
- package/dist/types/src/components/Plank/Plank.stories.d.ts +3 -3
- package/dist/types/src/components/Plank/Plank.stories.d.ts.map +1 -1
- package/dist/types/src/components/Plank/PlankControls.d.ts +1 -0
- package/dist/types/src/components/Plank/PlankControls.d.ts.map +1 -1
- package/dist/types/src/components/Plank/PlankError.d.ts.map +1 -1
- package/dist/types/src/components/Plank/PlankHeading.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/ComplementarySidebar.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/Sidebar.d.ts.map +1 -1
- package/dist/types/src/components/Sidebar/SidebarButton.d.ts +2 -1
- package/dist/types/src/components/Sidebar/SidebarButton.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +5 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useBreakpoints.d.ts.map +1 -0
- package/dist/types/src/hooks/useCompanions.d.ts.map +1 -0
- package/dist/types/src/hooks/useDeckCompanions.d.ts +13 -0
- package/dist/types/src/hooks/useDeckCompanions.d.ts.map +1 -0
- package/dist/types/src/hooks/useHoistStatusbar.d.ts.map +1 -0
- package/dist/types/src/hooks/useNodeActionExpander.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/layout.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +104 -104
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -4
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/layoutAppliesTopbar.d.ts.map +1 -1
- package/dist/types/src/util/overscroll.d.ts.map +1 -1
- package/dist/types/src/util/set-active.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +36 -29
- package/src/capabilities/app-graph-builder.ts +120 -92
- package/src/capabilities/check-app-scheme.ts +3 -7
- package/src/capabilities/index.ts +1 -0
- package/src/capabilities/intent-resolver.ts +140 -114
- package/src/capabilities/settings.ts +2 -2
- package/src/capabilities/state.ts +4 -2
- package/src/capabilities/tools.ts +4 -3
- package/src/capabilities/url-handler.ts +4 -4
- package/src/components/DeckLayout/ContentEmpty.tsx +3 -2
- package/src/components/DeckLayout/DeckLayout.tsx +12 -10
- package/src/components/DeckLayout/Popover.tsx +71 -43
- package/src/components/Plank/Plank.stories.tsx +20 -8
- package/src/components/Plank/Plank.tsx +101 -66
- package/src/components/Plank/PlankControls.tsx +26 -30
- package/src/components/Plank/PlankError.tsx +2 -6
- package/src/components/Plank/PlankHeading.tsx +23 -8
- package/src/components/Sidebar/ComplementarySidebar.tsx +4 -35
- package/src/components/Sidebar/Sidebar.tsx +2 -1
- package/src/components/Sidebar/SidebarButton.tsx +30 -7
- package/src/components/fragments.ts +1 -1
- package/src/hooks/index.ts +5 -1
- package/src/{util → hooks}/useCompanions.ts +3 -3
- package/src/hooks/useDeckCompanions.ts +33 -0
- package/src/hooks/useNodeActionExpander.ts +3 -8
- package/src/index.ts +1 -1
- package/src/types.ts +72 -71
- package/src/util/index.ts +1 -4
- package/dist/lib/browser/app-graph-builder-VYZ4IWI3.mjs.map +0 -7
- package/dist/lib/browser/check-app-scheme-SEYECDHI.mjs.map +0 -7
- package/dist/lib/browser/chunk-4QSEGMY3.mjs +0 -24
- package/dist/lib/browser/chunk-4QSEGMY3.mjs.map +0 -7
- package/dist/lib/browser/chunk-6HJZL3WT.mjs +0 -118
- package/dist/lib/browser/chunk-6HJZL3WT.mjs.map +0 -7
- package/dist/lib/browser/chunk-FLOVGNYB.mjs +0 -81
- package/dist/lib/browser/chunk-FLOVGNYB.mjs.map +0 -7
- package/dist/lib/browser/chunk-VP6FCWFV.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZMJMCN7O.mjs +0 -157
- package/dist/lib/browser/chunk-ZMJMCN7O.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-6AK45PT5.mjs.map +0 -7
- package/dist/lib/browser/state-Z6UY2Z3M.mjs.map +0 -7
- package/dist/lib/browser/tools-VDVQTJMD.mjs.map +0 -7
- package/dist/lib/browser/url-handler-3CARFXQK.mjs.map +0 -7
- package/dist/types/src/util/useBreakpoints.d.ts.map +0 -1
- package/dist/types/src/util/useCompanions.d.ts.map +0 -1
- package/dist/types/src/util/useHoistStatusbar.d.ts.map +0 -1
- /package/dist/lib/browser/{react-root-KA2IL5RA.mjs.map → react-root-DGQVIHXP.mjs.map} +0 -0
- /package/dist/lib/browser/{react-surface-LIPGYEYN.mjs.map → react-surface-PXBXIOPU.mjs.map} +0 -0
- /package/dist/types/src/{util → hooks}/useBreakpoints.d.ts +0 -0
- /package/dist/types/src/{util → hooks}/useCompanions.d.ts +0 -0
- /package/dist/types/src/{util → hooks}/useHoistStatusbar.d.ts +0 -0
- /package/src/{util → hooks}/useBreakpoints.ts +0 -0
- /package/src/{util → hooks}/useHoistStatusbar.ts +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { batch } from '@preact/signals-core';
|
|
6
|
-
import { pipe } from 'effect';
|
|
6
|
+
import { Schema, Effect, pipe, Option } from 'effect';
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
Capabilities,
|
|
@@ -11,16 +11,16 @@ import {
|
|
|
11
11
|
contributes,
|
|
12
12
|
IntentAction,
|
|
13
13
|
LayoutAction,
|
|
14
|
-
type
|
|
14
|
+
type PluginContext,
|
|
15
15
|
createIntent,
|
|
16
16
|
chain,
|
|
17
17
|
} from '@dxos/app-framework';
|
|
18
|
-
import { getTypename
|
|
18
|
+
import { getTypename } from '@dxos/echo-schema';
|
|
19
19
|
import { invariant } from '@dxos/invariant';
|
|
20
20
|
import { isLiveObject } from '@dxos/live-object';
|
|
21
21
|
import { log } from '@dxos/log';
|
|
22
22
|
import { AttentionCapabilities } from '@dxos/plugin-attention';
|
|
23
|
-
import {
|
|
23
|
+
import { isActionLike } from '@dxos/plugin-graph';
|
|
24
24
|
import { ObservabilityAction } from '@dxos/plugin-observability/types';
|
|
25
25
|
import { byPosition, isNonNullable } from '@dxos/util';
|
|
26
26
|
|
|
@@ -38,13 +38,13 @@ import {
|
|
|
38
38
|
} from '../types';
|
|
39
39
|
import { setActive } from '../util';
|
|
40
40
|
|
|
41
|
-
export default (context:
|
|
41
|
+
export default (context: PluginContext) =>
|
|
42
42
|
contributes(Capabilities.IntentResolver, [
|
|
43
43
|
createResolver({
|
|
44
44
|
intent: IntentAction.ShowUndo,
|
|
45
45
|
resolve: (data) => {
|
|
46
|
-
const layout = context.
|
|
47
|
-
const { undoPromise: undo } = context.
|
|
46
|
+
const layout = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
47
|
+
const { undoPromise: undo } = context.getCapability(Capabilities.IntentDispatcher);
|
|
48
48
|
|
|
49
49
|
// TODO(wittjosiah): Support undoing further back than the last action.
|
|
50
50
|
if (layout.currentUndoId) {
|
|
@@ -67,12 +67,12 @@ export default (context: PluginsContext) =>
|
|
|
67
67
|
}),
|
|
68
68
|
createResolver({
|
|
69
69
|
intent: LayoutAction.UpdateLayout,
|
|
70
|
-
// TODO(wittjosiah): This should be able to just be `
|
|
70
|
+
// TODO(wittjosiah): This should be able to just be `Schema.is(LayoutAction.UpdateSidebar.fields.input)`
|
|
71
71
|
// but the filter is not being applied correctly.
|
|
72
|
-
filter: (data): data is
|
|
73
|
-
|
|
72
|
+
filter: (data): data is Schema.Schema.Type<typeof LayoutAction.UpdateSidebar.fields.input> =>
|
|
73
|
+
Schema.is(LayoutAction.UpdateSidebar.fields.input)(data),
|
|
74
74
|
resolve: ({ options }) => {
|
|
75
|
-
const layout = context.
|
|
75
|
+
const layout = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
76
76
|
const next = options?.state ?? layout.sidebarState;
|
|
77
77
|
if (next !== layout.sidebarState) {
|
|
78
78
|
layout.sidebarState = next;
|
|
@@ -81,12 +81,12 @@ export default (context: PluginsContext) =>
|
|
|
81
81
|
}),
|
|
82
82
|
createResolver({
|
|
83
83
|
intent: LayoutAction.UpdateLayout,
|
|
84
|
-
// TODO(wittjosiah): This should be able to just be `
|
|
84
|
+
// TODO(wittjosiah): This should be able to just be `Schema.is(LayoutAction.UpdateComplementary.fields.input)`
|
|
85
85
|
// but the filter is not being applied correctly.
|
|
86
|
-
filter: (data): data is
|
|
87
|
-
|
|
86
|
+
filter: (data): data is Schema.Schema.Type<typeof LayoutAction.UpdateComplementary.fields.input> =>
|
|
87
|
+
Schema.is(LayoutAction.UpdateComplementary.fields.input)(data),
|
|
88
88
|
resolve: ({ subject, options }) => {
|
|
89
|
-
const layout = context.
|
|
89
|
+
const layout = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
90
90
|
|
|
91
91
|
if (layout.complementarySidebarPanel !== subject) {
|
|
92
92
|
layout.complementarySidebarPanel = subject;
|
|
@@ -100,12 +100,12 @@ export default (context: PluginsContext) =>
|
|
|
100
100
|
}),
|
|
101
101
|
createResolver({
|
|
102
102
|
intent: LayoutAction.UpdateLayout,
|
|
103
|
-
// TODO(wittjosiah): This should be able to just be `
|
|
103
|
+
// TODO(wittjosiah): This should be able to just be `Schema.is(LayoutAction.UpdateDialog.fields.input)`
|
|
104
104
|
// but the filter is not being applied correctly.
|
|
105
|
-
filter: (data): data is
|
|
106
|
-
|
|
105
|
+
filter: (data): data is Schema.Schema.Type<typeof LayoutAction.UpdateDialog.fields.input> =>
|
|
106
|
+
Schema.is(LayoutAction.UpdateDialog.fields.input)(data),
|
|
107
107
|
resolve: ({ subject, options }) => {
|
|
108
|
-
const layout = context.
|
|
108
|
+
const layout = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
109
109
|
layout.dialogOpen = options.state ?? Boolean(subject);
|
|
110
110
|
layout.dialogContent = subject ? { component: subject, props: options.props } : null;
|
|
111
111
|
layout.dialogBlockAlign = options.blockAlign ?? 'center';
|
|
@@ -114,12 +114,12 @@ export default (context: PluginsContext) =>
|
|
|
114
114
|
}),
|
|
115
115
|
createResolver({
|
|
116
116
|
intent: LayoutAction.UpdateLayout,
|
|
117
|
-
// TODO(wittjosiah): This should be able to just be `
|
|
117
|
+
// TODO(wittjosiah): This should be able to just be `Schema.is(LayoutAction.UpdatePopover.fields.input)`
|
|
118
118
|
// but the filter is not being applied correctly.
|
|
119
|
-
filter: (data): data is
|
|
120
|
-
|
|
119
|
+
filter: (data): data is Schema.Schema.Type<typeof LayoutAction.UpdatePopover.fields.input> =>
|
|
120
|
+
Schema.is(LayoutAction.UpdatePopover.fields.input)(data),
|
|
121
121
|
resolve: ({ subject, options }) => {
|
|
122
|
-
const layout = context.
|
|
122
|
+
const layout = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
123
123
|
layout.popoverOpen = options.state ?? Boolean(subject);
|
|
124
124
|
layout.popoverContent =
|
|
125
125
|
typeof subject === 'string' ? { component: subject, props: options.props } : subject ? { subject } : null;
|
|
@@ -133,21 +133,21 @@ export default (context: PluginsContext) =>
|
|
|
133
133
|
}),
|
|
134
134
|
createResolver({
|
|
135
135
|
intent: LayoutAction.UpdateLayout,
|
|
136
|
-
// TODO(wittjosiah): This should be able to just be `
|
|
136
|
+
// TODO(wittjosiah): This should be able to just be `Schema.is(LayoutAction.AddToast.fields.input)`
|
|
137
137
|
// but the filter is not being applied correctly.
|
|
138
|
-
filter: (data): data is
|
|
139
|
-
|
|
138
|
+
filter: (data): data is Schema.Schema.Type<typeof LayoutAction.AddToast.fields.input> =>
|
|
139
|
+
Schema.is(LayoutAction.AddToast.fields.input)(data),
|
|
140
140
|
resolve: ({ subject }) => {
|
|
141
|
-
const layout = context.
|
|
141
|
+
const layout = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
142
142
|
layout.toasts.push(subject);
|
|
143
143
|
},
|
|
144
144
|
}),
|
|
145
145
|
createResolver({
|
|
146
146
|
intent: LayoutAction.UpdateLayout,
|
|
147
|
-
// TODO(wittjosiah): This should be able to just be `
|
|
147
|
+
// TODO(wittjosiah): This should be able to just be `Schema.is(LayoutAction.SetLayoutMode.fields.input)`
|
|
148
148
|
// but the filter is not being applied correctly.
|
|
149
|
-
filter: (data): data is
|
|
150
|
-
if (!
|
|
149
|
+
filter: (data): data is Schema.Schema.Type<typeof LayoutAction.SetLayoutMode.fields.input> => {
|
|
150
|
+
if (!Schema.is(LayoutAction.SetLayoutMode.fields.input)(data)) {
|
|
151
151
|
return false;
|
|
152
152
|
}
|
|
153
153
|
|
|
@@ -158,7 +158,7 @@ export default (context: PluginsContext) =>
|
|
|
158
158
|
return true;
|
|
159
159
|
},
|
|
160
160
|
resolve: ({ subject, options }) => {
|
|
161
|
-
const state = context.
|
|
161
|
+
const state = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
162
162
|
|
|
163
163
|
const setMode = (mode: LayoutMode) => {
|
|
164
164
|
const deck = state.deck;
|
|
@@ -202,10 +202,11 @@ export default (context: PluginsContext) =>
|
|
|
202
202
|
}),
|
|
203
203
|
createResolver({
|
|
204
204
|
intent: LayoutAction.UpdateLayout,
|
|
205
|
-
filter: (data): data is
|
|
206
|
-
|
|
205
|
+
filter: (data): data is Schema.Schema.Type<typeof LayoutAction.SwitchWorkspace.fields.input> =>
|
|
206
|
+
Schema.is(LayoutAction.SwitchWorkspace.fields.input)(data),
|
|
207
207
|
resolve: ({ subject }) => {
|
|
208
|
-
const
|
|
208
|
+
const { graph } = context.getCapability(Capabilities.AppGraph);
|
|
209
|
+
const state = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
209
210
|
batch(() => {
|
|
210
211
|
// TODO(wittjosiah): This is a hack to prevent the previous deck from being set for pinned items.
|
|
211
212
|
// Ideally this should be worked into the data model in a generic way.
|
|
@@ -223,15 +224,22 @@ export default (context: PluginsContext) =>
|
|
|
223
224
|
return {
|
|
224
225
|
intents: [createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: first })],
|
|
225
226
|
};
|
|
227
|
+
} else {
|
|
228
|
+
const [item] = graph.getConnections(subject).filter((node) => !isActionLike(node));
|
|
229
|
+
if (item) {
|
|
230
|
+
return {
|
|
231
|
+
intents: [createIntent(LayoutAction.Open, { part: 'main', subject: [item.id] })],
|
|
232
|
+
};
|
|
233
|
+
}
|
|
226
234
|
}
|
|
227
235
|
},
|
|
228
236
|
}),
|
|
229
237
|
createResolver({
|
|
230
238
|
intent: LayoutAction.UpdateLayout,
|
|
231
|
-
filter: (data): data is
|
|
232
|
-
|
|
239
|
+
filter: (data): data is Schema.Schema.Type<typeof LayoutAction.RevertWorkspace.fields.input> =>
|
|
240
|
+
Schema.is(LayoutAction.RevertWorkspace.fields.input)(data),
|
|
233
241
|
resolve: () => {
|
|
234
|
-
const state = context.
|
|
242
|
+
const state = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
235
243
|
return {
|
|
236
244
|
intents: [createIntent(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: state.previousDeck })],
|
|
237
245
|
};
|
|
@@ -239,65 +247,78 @@ export default (context: PluginsContext) =>
|
|
|
239
247
|
}),
|
|
240
248
|
createResolver({
|
|
241
249
|
intent: LayoutAction.UpdateLayout,
|
|
242
|
-
filter: (data): data is
|
|
243
|
-
|
|
244
|
-
resolve: ({ subject, options }) =>
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
250
|
+
filter: (data): data is Schema.Schema.Type<typeof LayoutAction.Open.fields.input> =>
|
|
251
|
+
Schema.is(LayoutAction.Open.fields.input)(data),
|
|
252
|
+
resolve: ({ subject, options }) =>
|
|
253
|
+
Effect.gen(function* () {
|
|
254
|
+
const { graph } = context.getCapability(Capabilities.AppGraph);
|
|
255
|
+
const state = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
256
|
+
const attention = context.getCapability(AttentionCapabilities.Attention);
|
|
257
|
+
const settings = context
|
|
258
|
+
.getCapabilities(Capabilities.SettingsStore)[0]
|
|
259
|
+
?.getStore<DeckSettingsProps>(DECK_PLUGIN)?.value;
|
|
251
260
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
openEntry(acc, entryId, {
|
|
259
|
-
key: options?.key,
|
|
260
|
-
positioning: options?.positioning ?? settings?.newPlankPositioning,
|
|
261
|
-
pivotId: options?.pivotId,
|
|
262
|
-
variant: options?.variant,
|
|
263
|
-
}),
|
|
264
|
-
state.deck.active,
|
|
265
|
-
);
|
|
261
|
+
if (options?.workspace && state.activeDeck !== options?.workspace) {
|
|
262
|
+
const { dispatch } = context.getCapability(Capabilities.IntentDispatcher);
|
|
263
|
+
yield* dispatch(
|
|
264
|
+
createIntent(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: options.workspace }),
|
|
265
|
+
);
|
|
266
|
+
}
|
|
266
267
|
|
|
267
|
-
|
|
268
|
-
|
|
268
|
+
const previouslyOpenIds = new Set<string>(state.deck.solo ? [state.deck.solo] : state.deck.active);
|
|
269
|
+
batch(() => {
|
|
270
|
+
const next = state.deck.solo
|
|
271
|
+
? (subject as string[]).map((id) => createEntryId(id, options?.variant))
|
|
272
|
+
: subject.reduce(
|
|
273
|
+
(acc, entryId) =>
|
|
274
|
+
openEntry(acc, entryId, {
|
|
275
|
+
key: options?.key,
|
|
276
|
+
positioning: options?.positioning ?? settings?.newPlankPositioning,
|
|
277
|
+
pivotId: options?.pivotId,
|
|
278
|
+
variant: options?.variant,
|
|
279
|
+
}),
|
|
280
|
+
state.deck.active,
|
|
281
|
+
);
|
|
269
282
|
|
|
270
|
-
|
|
271
|
-
|
|
283
|
+
return setActive({ next, state, attention });
|
|
284
|
+
});
|
|
272
285
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
286
|
+
const ids = state.deck.solo ? [state.deck.solo] : state.deck.active;
|
|
287
|
+
const newlyOpen = ids.filter((i) => !previouslyOpenIds.has(i));
|
|
288
|
+
|
|
289
|
+
return {
|
|
290
|
+
intents: [
|
|
291
|
+
...(options?.scrollIntoView !== false
|
|
292
|
+
? [createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: newlyOpen[0] ?? subject[0] })]
|
|
293
|
+
: []),
|
|
294
|
+
createIntent(LayoutAction.Expose, { part: 'navigation', subject: newlyOpen[0] ?? subject[0] }),
|
|
295
|
+
...newlyOpen.map((subjectId) => {
|
|
296
|
+
const typename = Option.match(graph.getNode(subjectId), {
|
|
297
|
+
onNone: () => undefined,
|
|
298
|
+
onSome: (node) => {
|
|
299
|
+
const active = node.data;
|
|
300
|
+
return isLiveObject(active) ? getTypename(active) : undefined;
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
return createIntent(ObservabilityAction.SendEvent, {
|
|
304
|
+
name: 'navigation.activate',
|
|
305
|
+
properties: {
|
|
306
|
+
subjectId,
|
|
307
|
+
typename,
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
}),
|
|
311
|
+
],
|
|
312
|
+
};
|
|
313
|
+
}),
|
|
293
314
|
}),
|
|
294
315
|
createResolver({
|
|
295
316
|
intent: LayoutAction.UpdateLayout,
|
|
296
|
-
filter: (data): data is
|
|
297
|
-
|
|
317
|
+
filter: (data): data is Schema.Schema.Type<typeof LayoutAction.Close.fields.input> =>
|
|
318
|
+
Schema.is(LayoutAction.Close.fields.input)(data),
|
|
298
319
|
resolve: ({ subject }) => {
|
|
299
|
-
const state = context.
|
|
300
|
-
const attention = context.
|
|
320
|
+
const state = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
321
|
+
const attention = context.getCapability(AttentionCapabilities.Attention);
|
|
301
322
|
const active = state.deck.solo ? [state.deck.solo] : state.deck.active;
|
|
302
323
|
const next = subject.reduce((acc, id) => closeEntry(acc, id), active);
|
|
303
324
|
const toAttend = setActive({ next, state, attention });
|
|
@@ -316,11 +337,11 @@ export default (context: PluginsContext) =>
|
|
|
316
337
|
}),
|
|
317
338
|
createResolver({
|
|
318
339
|
intent: LayoutAction.UpdateLayout,
|
|
319
|
-
filter: (data): data is
|
|
320
|
-
|
|
340
|
+
filter: (data): data is Schema.Schema.Type<typeof LayoutAction.Set.fields.input> =>
|
|
341
|
+
Schema.is(LayoutAction.Set.fields.input)(data),
|
|
321
342
|
resolve: ({ subject }) => {
|
|
322
|
-
const state = context.
|
|
323
|
-
const attention = context.
|
|
343
|
+
const state = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
344
|
+
const attention = context.getCapability(AttentionCapabilities.Attention);
|
|
324
345
|
const toAttend = setActive({ next: subject as string[], state, attention });
|
|
325
346
|
return {
|
|
326
347
|
intents: toAttend ? [createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: toAttend })] : [],
|
|
@@ -329,24 +350,24 @@ export default (context: PluginsContext) =>
|
|
|
329
350
|
}),
|
|
330
351
|
createResolver({
|
|
331
352
|
intent: LayoutAction.UpdateLayout,
|
|
332
|
-
filter: (data): data is
|
|
333
|
-
|
|
353
|
+
filter: (data): data is Schema.Schema.Type<typeof LayoutAction.ScrollIntoView.fields.input> =>
|
|
354
|
+
Schema.is(LayoutAction.ScrollIntoView.fields.input)(data),
|
|
334
355
|
resolve: ({ subject }) => {
|
|
335
|
-
const layout = context.
|
|
356
|
+
const layout = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
336
357
|
layout.scrollIntoView = subject;
|
|
337
358
|
},
|
|
338
359
|
}),
|
|
339
360
|
createResolver({
|
|
340
361
|
intent: DeckAction.UpdatePlankSize,
|
|
341
362
|
resolve: (data) => {
|
|
342
|
-
const state = context.
|
|
363
|
+
const state = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
343
364
|
state.deck.plankSizing[data.id] = data.size;
|
|
344
365
|
},
|
|
345
366
|
}),
|
|
346
367
|
createResolver({
|
|
347
368
|
intent: DeckAction.ChangeCompanion,
|
|
348
369
|
resolve: (data) => {
|
|
349
|
-
const state = context.
|
|
370
|
+
const state = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
350
371
|
// TODO(thure): Reactivity only works when creating a lexically new `activeCompanions`… Are these not proxy objects?
|
|
351
372
|
if (data.companion === null) {
|
|
352
373
|
const { [data.primary]: _, ...nextActiveCompanions } = state.deck.activeCompanions ?? {};
|
|
@@ -363,9 +384,9 @@ export default (context: PluginsContext) =>
|
|
|
363
384
|
createResolver({
|
|
364
385
|
intent: DeckAction.Adjust,
|
|
365
386
|
resolve: (adjustment) => {
|
|
366
|
-
const state = context.
|
|
367
|
-
const attention = context.
|
|
368
|
-
const { graph } = context.
|
|
387
|
+
const state = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
388
|
+
const attention = context.getCapability(AttentionCapabilities.Attention);
|
|
389
|
+
const { graph } = context.getCapability(Capabilities.AppGraph);
|
|
369
390
|
|
|
370
391
|
return batch(() => {
|
|
371
392
|
if (adjustment.type === 'increment-end' || adjustment.type === 'increment-start') {
|
|
@@ -377,20 +398,25 @@ export default (context: PluginsContext) =>
|
|
|
377
398
|
}
|
|
378
399
|
|
|
379
400
|
if (adjustment.type === 'companion') {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
.
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
401
|
+
return pipe(
|
|
402
|
+
graph.getNode(adjustment.id),
|
|
403
|
+
Option.map((node) =>
|
|
404
|
+
graph
|
|
405
|
+
.getConnections(node.id)
|
|
406
|
+
.filter((n) => n.type === PLANK_COMPANION_TYPE)
|
|
407
|
+
.toSorted((a, b) => byPosition(a.properties, b.properties)),
|
|
408
|
+
),
|
|
409
|
+
Option.flatMap((companions) => (companions.length > 0 ? Option.some(companions[0]) : Option.none())),
|
|
410
|
+
Option.match({
|
|
411
|
+
onNone: () => ({}),
|
|
412
|
+
onSome: (companion) => ({
|
|
413
|
+
intents: [
|
|
414
|
+
// TODO(wittjosiah): This should remember the previously selected companion.
|
|
415
|
+
createIntent(DeckAction.ChangeCompanion, { primary: adjustment.id, companion: companion.id }),
|
|
416
|
+
],
|
|
417
|
+
}),
|
|
418
|
+
}),
|
|
419
|
+
);
|
|
394
420
|
}
|
|
395
421
|
|
|
396
422
|
if (adjustment.type.startsWith('solo')) {
|
|
@@ -11,9 +11,9 @@ import { DeckSettingsSchema, type DeckSettingsProps } from '../types';
|
|
|
11
11
|
export default () => {
|
|
12
12
|
const settings = live<DeckSettingsProps>({
|
|
13
13
|
showHints: false,
|
|
14
|
-
enableDeck:
|
|
15
|
-
enableNativeRedirect: false,
|
|
14
|
+
enableDeck: false,
|
|
16
15
|
enableStatusbar: false,
|
|
16
|
+
enableNativeRedirect: false,
|
|
17
17
|
newPlankPositioning: 'start',
|
|
18
18
|
overscroll: 'none',
|
|
19
19
|
});
|
|
@@ -10,7 +10,7 @@ import { type SidebarState } from '@dxos/react-ui';
|
|
|
10
10
|
|
|
11
11
|
import { DeckCapabilities } from './capabilities';
|
|
12
12
|
import { DECK_PLUGIN } from '../meta';
|
|
13
|
-
import { getMode, type
|
|
13
|
+
import { getMode, type DeckPluginState, defaultDeck, type DeckState } from '../types';
|
|
14
14
|
|
|
15
15
|
const boolean = /true|false/;
|
|
16
16
|
|
|
@@ -29,7 +29,7 @@ const migrateSidebarState = () => {
|
|
|
29
29
|
});
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
const DeckStateFactory = () => {
|
|
33
33
|
migrateSidebarState();
|
|
34
34
|
|
|
35
35
|
const state = new LocalStorageStore<DeckPluginState>(DECK_PLUGIN, {
|
|
@@ -100,3 +100,5 @@ export default () => {
|
|
|
100
100
|
contributes(Capabilities.Layout, layout),
|
|
101
101
|
];
|
|
102
102
|
};
|
|
103
|
+
|
|
104
|
+
export default DeckStateFactory;
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Schema } from 'effect';
|
|
6
|
+
|
|
5
7
|
import {
|
|
6
8
|
contributes,
|
|
7
9
|
createIntent,
|
|
@@ -10,7 +12,6 @@ import {
|
|
|
10
12
|
type PromiseIntentDispatcher,
|
|
11
13
|
} from '@dxos/app-framework';
|
|
12
14
|
import { defineTool, ToolResult } from '@dxos/artifact';
|
|
13
|
-
import { S } from '@dxos/echo-schema';
|
|
14
15
|
import { invariant } from '@dxos/invariant';
|
|
15
16
|
|
|
16
17
|
import { meta } from '../meta';
|
|
@@ -35,8 +36,8 @@ export default () =>
|
|
|
35
36
|
`,
|
|
36
37
|
caption: 'Showing item...',
|
|
37
38
|
// TODO(wittjosiah): Refactor Layout/Navigation/Deck actions so that they can be used directly.
|
|
38
|
-
schema:
|
|
39
|
-
id:
|
|
39
|
+
schema: Schema.Struct({
|
|
40
|
+
id: Schema.String.annotations({
|
|
40
41
|
description: 'The ID of the item to show.',
|
|
41
42
|
}),
|
|
42
43
|
}),
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { Capabilities, contributes, createIntent, LayoutAction, type
|
|
5
|
+
import { Capabilities, contributes, createIntent, LayoutAction, type PluginContext } from '@dxos/app-framework';
|
|
6
6
|
import { scheduledEffect } from '@dxos/echo-signals/core';
|
|
7
7
|
|
|
8
8
|
import { DeckCapabilities } from './capabilities';
|
|
9
9
|
import { defaultDeck } from '../types';
|
|
10
10
|
|
|
11
11
|
// TODO(wittjosiah): Cleanup the url handling. May justify introducing routing capabilities.
|
|
12
|
-
export default async (context:
|
|
13
|
-
const { dispatchPromise: dispatch } = context.
|
|
14
|
-
const state = context.
|
|
12
|
+
export default async (context: PluginContext) => {
|
|
13
|
+
const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);
|
|
14
|
+
const state = context.getCapability(DeckCapabilities.MutableDeckState);
|
|
15
15
|
|
|
16
16
|
const handleNavigation = async () => {
|
|
17
17
|
const pathname = window.location.pathname;
|
|
@@ -7,8 +7,9 @@ import React from 'react';
|
|
|
7
7
|
import { Surface, useCapability } from '@dxos/app-framework';
|
|
8
8
|
|
|
9
9
|
import { DeckCapabilities } from '../../capabilities';
|
|
10
|
+
import { useBreakpoints } from '../../hooks';
|
|
10
11
|
import { getMode } from '../../types';
|
|
11
|
-
import { layoutAppliesTopbar
|
|
12
|
+
import { layoutAppliesTopbar } from '../../util';
|
|
12
13
|
import { ToggleSidebarButton } from '../Sidebar';
|
|
13
14
|
import { fixedSidebarToggleStyles } from '../fragments';
|
|
14
15
|
|
|
@@ -20,7 +21,7 @@ export const ContentEmpty = () => {
|
|
|
20
21
|
return (
|
|
21
22
|
<div
|
|
22
23
|
role='none'
|
|
23
|
-
className='grid place-items-center p-8 relative bg-
|
|
24
|
+
className='grid place-items-center p-8 relative bg-deckSurface'
|
|
24
25
|
data-testid='layoutPlugin.firstRunMessage'
|
|
25
26
|
>
|
|
26
27
|
<Surface role='keyshortcuts' />
|
|
@@ -26,9 +26,10 @@ import { StatusBar } from './StatusBar';
|
|
|
26
26
|
import { Toast } from './Toast';
|
|
27
27
|
import { Topbar } from './Topbar';
|
|
28
28
|
import { DeckCapabilities } from '../../capabilities';
|
|
29
|
+
import { useBreakpoints, useHoistStatusbar } from '../../hooks';
|
|
29
30
|
import { DECK_PLUGIN } from '../../meta';
|
|
30
31
|
import { type DeckSettingsProps, getMode } from '../../types';
|
|
31
|
-
import { calculateOverscroll, layoutAppliesTopbar
|
|
32
|
+
import { calculateOverscroll, layoutAppliesTopbar } from '../../util';
|
|
32
33
|
import { Plank } from '../Plank';
|
|
33
34
|
import { ComplementarySidebar, Sidebar, ToggleComplementarySidebarButton, ToggleSidebarButton } from '../Sidebar';
|
|
34
35
|
import { fixedComplementarySidebarToggleStyles, fixedSidebarToggleStyles } from '../fragments';
|
|
@@ -38,7 +39,7 @@ export type DeckLayoutProps = {
|
|
|
38
39
|
};
|
|
39
40
|
|
|
40
41
|
const PlankSeparator = ({ order }: { order: number }) =>
|
|
41
|
-
order > 0 ? <span role='separator' className='row-span-2 bg-
|
|
42
|
+
order > 0 ? <span role='separator' className='row-span-2 bg-deckSurface is-4' style={{ gridColumn: order }} /> : null;
|
|
42
43
|
|
|
43
44
|
export const DeckLayout = ({ onDismissToast }: DeckLayoutProps) => {
|
|
44
45
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
@@ -59,7 +60,7 @@ export const DeckLayout = ({ onDismissToast }: DeckLayoutProps) => {
|
|
|
59
60
|
useEffect(() => {
|
|
60
61
|
// NOTE: Not `useAttended` so that the layout component is not re-rendered when the attended list changes.
|
|
61
62
|
const attended = untracked(() => {
|
|
62
|
-
const attention = pluginManager.context.
|
|
63
|
+
const attention = pluginManager.context.getCapability(AttentionCapabilities.Attention);
|
|
63
64
|
return attention.current;
|
|
64
65
|
});
|
|
65
66
|
const firstId = solo ?? active[0];
|
|
@@ -78,7 +79,7 @@ export const DeckLayout = ({ onDismissToast }: DeckLayoutProps) => {
|
|
|
78
79
|
if (!isNotMobile && getMode(deck) === 'deck') {
|
|
79
80
|
// NOTE: Not `useAttended` so that the layout component is not re-rendered when the attended list changes.
|
|
80
81
|
const attended = untracked(() => {
|
|
81
|
-
const attention = pluginManager.context.
|
|
82
|
+
const attention = pluginManager.context.getCapability(AttentionCapabilities.Attention);
|
|
82
83
|
return attention.current;
|
|
83
84
|
});
|
|
84
85
|
|
|
@@ -91,14 +92,15 @@ export const DeckLayout = ({ onDismissToast }: DeckLayoutProps) => {
|
|
|
91
92
|
}
|
|
92
93
|
}, [isNotMobile, deck, dispatch]);
|
|
93
94
|
|
|
94
|
-
//
|
|
95
|
+
// When deck is disabled in settings, set to solo mode if the current layout mode is deck.
|
|
96
|
+
// TODO(thure): Applying this as an effect should be avoided over emitting the intent only when the setting changes.
|
|
95
97
|
useEffect(() => {
|
|
96
|
-
if (!settings.enableDeck) {
|
|
98
|
+
if (!settings.enableDeck && layoutMode === 'deck') {
|
|
97
99
|
void dispatch(
|
|
98
100
|
createIntent(LayoutAction.SetLayoutMode, { part: 'mode', subject: active[0], options: { mode: 'solo' } }),
|
|
99
101
|
);
|
|
100
102
|
}
|
|
101
|
-
}, [settings.enableDeck, dispatch, active]);
|
|
103
|
+
}, [settings.enableDeck, dispatch, active, layoutMode]);
|
|
102
104
|
|
|
103
105
|
/**
|
|
104
106
|
* Clear scroll restoration state if the window is resized
|
|
@@ -190,8 +192,8 @@ export const DeckLayout = ({ onDismissToast }: DeckLayoutProps) => {
|
|
|
190
192
|
{!isEmpty && (
|
|
191
193
|
<Main.Content
|
|
192
194
|
bounce
|
|
193
|
-
classNames={mainPosition}
|
|
194
195
|
handlesFocus
|
|
196
|
+
classNames={mainPosition}
|
|
195
197
|
style={
|
|
196
198
|
{
|
|
197
199
|
'--dx-main-sidebarWidth':
|
|
@@ -213,7 +215,7 @@ export const DeckLayout = ({ onDismissToast }: DeckLayoutProps) => {
|
|
|
213
215
|
>
|
|
214
216
|
<div
|
|
215
217
|
role='none'
|
|
216
|
-
className={!solo ? 'relative bg-
|
|
218
|
+
className={!solo ? 'relative bg-deckSurface overflow-hidden' : 'sr-only'}
|
|
217
219
|
{...(solo && { inert: '' })}
|
|
218
220
|
>
|
|
219
221
|
{!topbar && !fullscreen && <ToggleSidebarButton classNames={fixedSidebarToggleStyles} />}
|
|
@@ -247,7 +249,7 @@ export const DeckLayout = ({ onDismissToast }: DeckLayoutProps) => {
|
|
|
247
249
|
</div>
|
|
248
250
|
<div
|
|
249
251
|
role='none'
|
|
250
|
-
className={solo ? 'relative bg-
|
|
252
|
+
className={solo ? 'relative bg-deckSurface overflow-hidden' : 'sr-only'}
|
|
251
253
|
{...(!solo && { inert: '' })}
|
|
252
254
|
>
|
|
253
255
|
{!topbar && !fullscreen && <ToggleSidebarButton classNames={fixedSidebarToggleStyles} />}
|