@dxos/plugin-deck 0.8.2-main.f11618f → 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.
Files changed (132) hide show
  1. package/dist/lib/browser/{app-graph-builder-VYZ4IWI3.mjs → app-graph-builder-R7COZ4A6.mjs} +16 -15
  2. package/dist/lib/browser/app-graph-builder-R7COZ4A6.mjs.map +7 -0
  3. package/dist/lib/browser/{check-app-scheme-O7JPE4TM.mjs → check-app-scheme-7AXGR6UT.mjs} +2 -2
  4. package/dist/lib/browser/check-app-scheme-7AXGR6UT.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-3O2UZVBA.mjs +121 -0
  6. package/dist/lib/browser/chunk-3O2UZVBA.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-JAYQ5BTF.mjs +157 -0
  8. package/dist/lib/browser/chunk-JAYQ5BTF.mjs.map +7 -0
  9. package/dist/lib/browser/{chunk-RDFJGGGX.mjs → chunk-KIGMELV2.mjs} +186 -201
  10. package/dist/lib/browser/chunk-KIGMELV2.mjs.map +7 -0
  11. package/dist/lib/browser/{state-Z6UY2Z3M.mjs → chunk-OF5RIATN.mjs} +6 -4
  12. package/dist/lib/browser/chunk-OF5RIATN.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-TRFYUEBA.mjs +145 -0
  14. package/dist/lib/browser/chunk-TRFYUEBA.mjs.map +7 -0
  15. package/dist/lib/browser/index.mjs +4 -5
  16. package/dist/lib/browser/index.mjs.map +1 -1
  17. package/dist/lib/browser/{intent-resolver-JKWXWUV6.mjs → intent-resolver-MAKOS57L.mjs} +78 -62
  18. package/dist/lib/browser/intent-resolver-MAKOS57L.mjs.map +7 -0
  19. package/dist/lib/browser/meta.json +1 -1
  20. package/dist/lib/browser/{react-root-S6ZAKNZA.mjs → react-root-DGQVIHXP.mjs} +6 -6
  21. package/dist/lib/browser/{react-surface-I7WZBOGM.mjs → react-surface-PXBXIOPU.mjs} +6 -6
  22. package/dist/lib/browser/{settings-6NU7CF2B.mjs → settings-UBWJF7J7.mjs} +4 -4
  23. package/dist/lib/browser/{settings-6NU7CF2B.mjs.map → settings-UBWJF7J7.mjs.map} +3 -3
  24. package/dist/lib/browser/state-4WFB4SDO.mjs +10 -0
  25. package/dist/lib/browser/state-4WFB4SDO.mjs.map +7 -0
  26. package/dist/lib/browser/{tools-VDVQTJMD.mjs → tools-IVPIPTVA.mjs} +7 -7
  27. package/dist/lib/browser/tools-IVPIPTVA.mjs.map +7 -0
  28. package/dist/lib/browser/types.mjs +1 -1
  29. package/dist/lib/browser/{url-handler-3CARFXQK.mjs → url-handler-JSYGSVSB.mjs} +4 -4
  30. package/dist/lib/browser/url-handler-JSYGSVSB.mjs.map +7 -0
  31. package/dist/types/src/capabilities/app-graph-builder.d.ts +2 -179
  32. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  33. package/dist/types/src/capabilities/check-app-scheme.d.ts +2 -2
  34. package/dist/types/src/capabilities/check-app-scheme.d.ts.map +1 -1
  35. package/dist/types/src/capabilities/index.d.ts +5 -180
  36. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  37. package/dist/types/src/capabilities/intent-resolver.d.ts +2 -2
  38. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  39. package/dist/types/src/capabilities/state.d.ts +2 -2
  40. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  41. package/dist/types/src/capabilities/tools.d.ts.map +1 -1
  42. package/dist/types/src/capabilities/url-handler.d.ts +2 -2
  43. package/dist/types/src/capabilities/url-handler.d.ts.map +1 -1
  44. package/dist/types/src/components/DeckLayout/Banner.d.ts.map +1 -1
  45. package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts.map +1 -1
  46. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
  47. package/dist/types/src/components/DeckLayout/Popover.d.ts.map +1 -1
  48. package/dist/types/src/components/DeckLayout/StatusBar.d.ts.map +1 -1
  49. package/dist/types/src/components/DeckLayout/Toast.d.ts.map +1 -1
  50. package/dist/types/src/components/DeckSettings/DeckSettings.d.ts.map +1 -1
  51. package/dist/types/src/components/Plank/Plank.d.ts +18 -5
  52. package/dist/types/src/components/Plank/Plank.d.ts.map +1 -1
  53. package/dist/types/src/components/Plank/Plank.stories.d.ts +3 -3
  54. package/dist/types/src/components/Plank/Plank.stories.d.ts.map +1 -1
  55. package/dist/types/src/components/Plank/PlankControls.d.ts +1 -0
  56. package/dist/types/src/components/Plank/PlankControls.d.ts.map +1 -1
  57. package/dist/types/src/components/Plank/PlankError.d.ts.map +1 -1
  58. package/dist/types/src/components/Plank/PlankHeading.d.ts.map +1 -1
  59. package/dist/types/src/components/Sidebar/ComplementarySidebar.d.ts.map +1 -1
  60. package/dist/types/src/components/Sidebar/Sidebar.d.ts.map +1 -1
  61. package/dist/types/src/components/Sidebar/SidebarButton.d.ts +2 -1
  62. package/dist/types/src/components/Sidebar/SidebarButton.d.ts.map +1 -1
  63. package/dist/types/src/hooks/index.d.ts +5 -1
  64. package/dist/types/src/hooks/index.d.ts.map +1 -1
  65. package/dist/types/src/hooks/useBreakpoints.d.ts.map +1 -0
  66. package/dist/types/src/hooks/useCompanions.d.ts.map +1 -0
  67. package/dist/types/src/hooks/useDeckCompanions.d.ts +13 -0
  68. package/dist/types/src/hooks/useDeckCompanions.d.ts.map +1 -0
  69. package/dist/types/src/hooks/useHoistStatusbar.d.ts.map +1 -0
  70. package/dist/types/src/hooks/useNodeActionExpander.d.ts.map +1 -1
  71. package/dist/types/src/index.d.ts +1 -1
  72. package/dist/types/src/index.d.ts.map +1 -1
  73. package/dist/types/src/layout.d.ts.map +1 -1
  74. package/dist/types/src/types.d.ts +104 -104
  75. package/dist/types/src/types.d.ts.map +1 -1
  76. package/dist/types/src/util/index.d.ts +1 -4
  77. package/dist/types/src/util/index.d.ts.map +1 -1
  78. package/dist/types/src/util/layoutAppliesTopbar.d.ts.map +1 -1
  79. package/dist/types/src/util/overscroll.d.ts.map +1 -1
  80. package/dist/types/src/util/set-active.d.ts.map +1 -1
  81. package/dist/types/tsconfig.tsbuildinfo +1 -1
  82. package/package.json +35 -29
  83. package/src/capabilities/app-graph-builder.ts +120 -92
  84. package/src/capabilities/check-app-scheme.ts +3 -5
  85. package/src/capabilities/index.ts +1 -0
  86. package/src/capabilities/intent-resolver.ts +94 -76
  87. package/src/capabilities/settings.ts +2 -2
  88. package/src/capabilities/state.ts +4 -2
  89. package/src/capabilities/tools.ts +4 -3
  90. package/src/capabilities/url-handler.ts +4 -4
  91. package/src/components/DeckLayout/ContentEmpty.tsx +3 -2
  92. package/src/components/DeckLayout/DeckLayout.tsx +12 -10
  93. package/src/components/Plank/Plank.stories.tsx +20 -8
  94. package/src/components/Plank/Plank.tsx +100 -67
  95. package/src/components/Plank/PlankControls.tsx +15 -25
  96. package/src/components/Plank/PlankHeading.tsx +19 -9
  97. package/src/components/Sidebar/ComplementarySidebar.tsx +4 -35
  98. package/src/components/Sidebar/Sidebar.tsx +2 -1
  99. package/src/components/Sidebar/SidebarButton.tsx +30 -7
  100. package/src/components/fragments.ts +1 -1
  101. package/src/hooks/index.ts +5 -1
  102. package/src/{util → hooks}/useCompanions.ts +3 -3
  103. package/src/hooks/useDeckCompanions.ts +33 -0
  104. package/src/hooks/useNodeActionExpander.ts +3 -8
  105. package/src/index.ts +1 -1
  106. package/src/types.ts +72 -71
  107. package/src/util/index.ts +1 -4
  108. package/dist/lib/browser/app-graph-builder-VYZ4IWI3.mjs.map +0 -7
  109. package/dist/lib/browser/check-app-scheme-O7JPE4TM.mjs.map +0 -7
  110. package/dist/lib/browser/chunk-6HJZL3WT.mjs +0 -118
  111. package/dist/lib/browser/chunk-6HJZL3WT.mjs.map +0 -7
  112. package/dist/lib/browser/chunk-FLOVGNYB.mjs +0 -81
  113. package/dist/lib/browser/chunk-FLOVGNYB.mjs.map +0 -7
  114. package/dist/lib/browser/chunk-RBJ6DLAC.mjs +0 -24
  115. package/dist/lib/browser/chunk-RBJ6DLAC.mjs.map +0 -7
  116. package/dist/lib/browser/chunk-RDFJGGGX.mjs.map +0 -7
  117. package/dist/lib/browser/chunk-ZMJMCN7O.mjs +0 -157
  118. package/dist/lib/browser/chunk-ZMJMCN7O.mjs.map +0 -7
  119. package/dist/lib/browser/intent-resolver-JKWXWUV6.mjs.map +0 -7
  120. package/dist/lib/browser/state-Z6UY2Z3M.mjs.map +0 -7
  121. package/dist/lib/browser/tools-VDVQTJMD.mjs.map +0 -7
  122. package/dist/lib/browser/url-handler-3CARFXQK.mjs.map +0 -7
  123. package/dist/types/src/util/useBreakpoints.d.ts.map +0 -1
  124. package/dist/types/src/util/useCompanions.d.ts.map +0 -1
  125. package/dist/types/src/util/useHoistStatusbar.d.ts.map +0 -1
  126. /package/dist/lib/browser/{react-root-S6ZAKNZA.mjs.map → react-root-DGQVIHXP.mjs.map} +0 -0
  127. /package/dist/lib/browser/{react-surface-I7WZBOGM.mjs.map → react-surface-PXBXIOPU.mjs.map} +0 -0
  128. /package/dist/types/src/{util → hooks}/useBreakpoints.d.ts +0 -0
  129. /package/dist/types/src/{util → hooks}/useCompanions.d.ts +0 -0
  130. /package/dist/types/src/{util → hooks}/useHoistStatusbar.d.ts +0 -0
  131. /package/src/{util → hooks}/useBreakpoints.ts +0 -0
  132. /package/src/{util → hooks}/useHoistStatusbar.ts +0 -0
@@ -2,112 +2,140 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Capabilities, contributes, createIntent, LayoutAction, type PluginsContext } from '@dxos/app-framework';
5
+ import { Rx } from '@effect-rx/rx-react';
6
+ import { Option, pipe } from 'effect';
7
+
8
+ import { Capabilities, contributes, createIntent, LayoutAction, type PluginContext } from '@dxos/app-framework';
6
9
  import { AttentionCapabilities } from '@dxos/plugin-attention';
7
- import { createExtension, type Node, ROOT_ID } from '@dxos/plugin-graph';
10
+ import { createExtension, ROOT_ID, rxFromSignal } from '@dxos/plugin-graph';
8
11
 
9
12
  import { DeckCapabilities } from './capabilities';
10
13
  import { DECK_PLUGIN } from '../meta';
11
14
 
12
- export default (context: PluginsContext) =>
15
+ export default (context: PluginContext) =>
13
16
  contributes(
14
17
  Capabilities.AppGraphBuilder,
15
18
  createExtension({
16
19
  id: DECK_PLUGIN,
17
- filter: (node): node is Node<null> => node.id === ROOT_ID,
18
- actions: () => {
19
- const state = context.requestCapability(DeckCapabilities.MutableDeckState);
20
+ actions: (node) =>
21
+ Rx.make((get) =>
22
+ pipe(
23
+ get(node),
24
+ Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
25
+ Option.map(() => {
26
+ const state = context.getCapability(DeckCapabilities.MutableDeckState);
20
27
 
21
- // NOTE(Zan): This is currently disabled.
22
- // TODO(Zan): Fullscreen needs to know the active node and provide that to the layout part.
23
- const _fullscreen = {
24
- id: `${LayoutAction.UpdateLayout._tag}/fullscreen`,
25
- data: async () => {
26
- const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
27
- await dispatch(createIntent(LayoutAction.SetLayoutMode, { part: 'mode', options: { mode: 'fullscreen' } }));
28
- },
29
- properties: {
30
- label: ['toggle fullscreen label', { ns: DECK_PLUGIN }],
31
- icon: 'ph--arrows-out--regular',
32
- keyBinding: {
33
- macos: 'ctrl+meta+f',
34
- windows: 'shift+ctrl+f',
35
- },
36
- },
37
- };
28
+ // NOTE(Zan): This is currently disabled.
29
+ // TODO(Zan): Fullscreen needs to know the active node and provide that to the layout part.
30
+ const _fullscreen = {
31
+ id: `${LayoutAction.UpdateLayout._tag}/fullscreen`,
32
+ data: async () => {
33
+ const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);
34
+ await dispatch(
35
+ createIntent(LayoutAction.SetLayoutMode, { part: 'mode', options: { mode: 'fullscreen' } }),
36
+ );
37
+ },
38
+ properties: {
39
+ label: ['toggle fullscreen label', { ns: DECK_PLUGIN }],
40
+ icon: 'ph--arrows-out--regular',
41
+ keyBinding: {
42
+ macos: 'ctrl+meta+f',
43
+ windows: 'shift+ctrl+f',
44
+ },
45
+ },
46
+ };
38
47
 
39
- const closeCurrent = {
40
- id: `${LayoutAction.Close._tag}/current`,
41
- data: async () => {
42
- const attention = context.requestCapability(AttentionCapabilities.Attention);
43
- const attended = attention.current.at(-1);
44
- if (attended) {
45
- const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
46
- await dispatch(
47
- createIntent(LayoutAction.Close, { part: 'main', subject: [attended], options: { state: false } }),
48
- );
49
- }
50
- },
51
- properties: {
52
- label: ['close current label', { ns: DECK_PLUGIN }],
53
- icon: 'ph--x--regular',
54
- },
55
- };
48
+ const closeCurrent = {
49
+ id: `${LayoutAction.Close._tag}/current`,
50
+ data: async () => {
51
+ const attention = context.getCapability(AttentionCapabilities.Attention);
52
+ const attended = attention.current.at(-1);
53
+ if (attended) {
54
+ const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);
55
+ await dispatch(
56
+ createIntent(LayoutAction.Close, {
57
+ part: 'main',
58
+ subject: [attended],
59
+ options: { state: false },
60
+ }),
61
+ );
62
+ }
63
+ },
64
+ properties: {
65
+ label: ['close current label', { ns: DECK_PLUGIN }],
66
+ icon: 'ph--x--regular',
67
+ },
68
+ };
56
69
 
57
- const closeOthers = {
58
- id: `${LayoutAction.Close._tag}/others`,
59
- data: async () => {
60
- const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
61
- const attention = context.requestCapability(AttentionCapabilities.Attention);
62
- const attended = attention.current.at(-1);
63
- const ids = state.deck.active.filter((id) => id !== attended) ?? [];
64
- await dispatch(createIntent(LayoutAction.Close, { part: 'main', subject: ids, options: { state: false } }));
65
- },
66
- properties: {
67
- label: ['close others label', { ns: DECK_PLUGIN }],
68
- icon: 'ph--x-square--regular',
69
- },
70
- };
70
+ const closeOthers = {
71
+ id: `${LayoutAction.Close._tag}/others`,
72
+ data: async () => {
73
+ const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);
74
+ const attention = context.getCapability(AttentionCapabilities.Attention);
75
+ const attended = attention.current.at(-1);
76
+ const ids = state.deck.active.filter((id) => id !== attended) ?? [];
77
+ await dispatch(
78
+ createIntent(LayoutAction.Close, { part: 'main', subject: ids, options: { state: false } }),
79
+ );
80
+ },
81
+ properties: {
82
+ label: ['close others label', { ns: DECK_PLUGIN }],
83
+ icon: 'ph--x-square--regular',
84
+ },
85
+ };
71
86
 
72
- const closeAll = {
73
- id: `${LayoutAction.Close._tag}/all`,
74
- data: async () => {
75
- const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
76
- await dispatch(
77
- createIntent(LayoutAction.Close, {
78
- part: 'main',
79
- subject: state.deck.active,
80
- options: { state: false },
81
- }),
82
- );
83
- },
84
- properties: {
85
- label: ['close all label', { ns: DECK_PLUGIN }],
86
- icon: 'ph--x-circle--regular',
87
- },
88
- };
87
+ const closeAll = {
88
+ id: `${LayoutAction.Close._tag}/all`,
89
+ data: async () => {
90
+ const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);
91
+ await dispatch(
92
+ createIntent(LayoutAction.Close, {
93
+ part: 'main',
94
+ subject: state.deck.active,
95
+ options: { state: false },
96
+ }),
97
+ );
98
+ },
99
+ properties: {
100
+ label: ['close all label', { ns: DECK_PLUGIN }],
101
+ icon: 'ph--x-circle--regular',
102
+ },
103
+ };
89
104
 
90
- const toggleSidebar = {
91
- id: `${LayoutAction.UpdateSidebar._tag}/nav`,
92
- data: async () => {
93
- state.sidebarState = state.sidebarState === 'expanded' ? 'collapsed' : 'expanded';
94
- },
95
- properties: {
96
- label: [
97
- state.sidebarState === 'expanded' ? 'collapse navigation sidebar label' : 'open navigation sidebar label',
98
- { ns: DECK_PLUGIN },
99
- ],
100
- icon: 'ph--sidebar--regular',
101
- keyBinding: {
102
- macos: 'meta+b',
103
- },
104
- disposition: 'pin-end',
105
- position: 'hoist',
106
- l0Breakpoint: 'lg',
107
- },
108
- };
105
+ const toggleSidebar = {
106
+ id: `${LayoutAction.UpdateSidebar._tag}/nav`,
107
+ data: async () => {
108
+ state.sidebarState = state.sidebarState === 'expanded' ? 'collapsed' : 'expanded';
109
+ },
110
+ properties: {
111
+ label: [
112
+ get(
113
+ rxFromSignal(() =>
114
+ state.sidebarState === 'expanded'
115
+ ? 'collapse navigation sidebar label'
116
+ : 'open navigation sidebar label',
117
+ ),
118
+ ),
119
+ { ns: DECK_PLUGIN },
120
+ ],
121
+ icon: 'ph--sidebar--regular',
122
+ keyBinding: {
123
+ macos: 'meta+b',
124
+ },
125
+ disposition: 'pin-end',
126
+ position: 'hoist',
127
+ l0Breakpoint: 'lg',
128
+ },
129
+ };
109
130
 
110
- return !state.deck.solo ? [closeCurrent, closeOthers, closeAll, toggleSidebar] : [toggleSidebar];
111
- },
131
+ return get(
132
+ rxFromSignal(() =>
133
+ !state.deck.solo ? [closeCurrent, closeOthers, closeAll, toggleSidebar] : [toggleSidebar],
134
+ ),
135
+ );
136
+ }),
137
+ Option.getOrElse(() => []),
138
+ ),
139
+ ),
112
140
  }),
113
141
  );
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Capabilities, contributes, type PluginsContext } from '@dxos/app-framework';
5
+ import { Capabilities, contributes, type PluginContext } from '@dxos/app-framework';
6
6
 
7
7
  import { DECK_PLUGIN } from '../meta';
8
8
  import { type DeckSettingsProps } from '../types';
@@ -30,10 +30,8 @@ const checkAppScheme = (url: string) => {
30
30
  });
31
31
  };
32
32
 
33
- export default async (context: PluginsContext) => {
34
- const settings = context
35
- .requestCapability(Capabilities.SettingsStore)
36
- .getStore<DeckSettingsProps>(DECK_PLUGIN)?.value;
33
+ export default async (context: PluginContext) => {
34
+ const settings = context.getCapability(Capabilities.SettingsStore).getStore<DeckSettingsProps>(DECK_PLUGIN)?.value;
37
35
  if (!isSocket && settings?.enableNativeRedirect) {
38
36
  checkAppScheme(appScheme);
39
37
  }
@@ -15,3 +15,4 @@ export const Tools = lazy(() => import('./tools'));
15
15
  export const UrlHandler = lazy(() => import('./url-handler'));
16
16
 
17
17
  export * from './capabilities';
18
+ export * from './state';
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { batch } from '@preact/signals-core';
6
- import { Effect, 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 PluginsContext,
14
+ type PluginContext,
15
15
  createIntent,
16
16
  chain,
17
17
  } from '@dxos/app-framework';
18
- import { getTypename, S } from '@dxos/echo-schema';
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 { type Node } from '@dxos/plugin-graph';
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: PluginsContext) =>
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.requestCapability(DeckCapabilities.MutableDeckState);
47
- const { undoPromise: undo } = context.requestCapability(Capabilities.IntentDispatcher);
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 `S.is(LayoutAction.UpdateSidebar.fields.input)`
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 S.Schema.Type<typeof LayoutAction.UpdateSidebar.fields.input> =>
73
- S.is(LayoutAction.UpdateSidebar.fields.input)(data),
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.requestCapability(DeckCapabilities.MutableDeckState);
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 `S.is(LayoutAction.UpdateComplementary.fields.input)`
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 S.Schema.Type<typeof LayoutAction.UpdateComplementary.fields.input> =>
87
- S.is(LayoutAction.UpdateComplementary.fields.input)(data),
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.requestCapability(DeckCapabilities.MutableDeckState);
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 `S.is(LayoutAction.UpdateDialog.fields.input)`
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 S.Schema.Type<typeof LayoutAction.UpdateDialog.fields.input> =>
106
- S.is(LayoutAction.UpdateDialog.fields.input)(data),
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.requestCapability(DeckCapabilities.MutableDeckState);
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 `S.is(LayoutAction.UpdatePopover.fields.input)`
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 S.Schema.Type<typeof LayoutAction.UpdatePopover.fields.input> =>
120
- S.is(LayoutAction.UpdatePopover.fields.input)(data),
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.requestCapability(DeckCapabilities.MutableDeckState);
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 `S.is(LayoutAction.AddToast.fields.input)`
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 S.Schema.Type<typeof LayoutAction.AddToast.fields.input> =>
139
- S.is(LayoutAction.AddToast.fields.input)(data),
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.requestCapability(DeckCapabilities.MutableDeckState);
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 `S.is(LayoutAction.SetLayoutMode.fields.input)`
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 S.Schema.Type<typeof LayoutAction.SetLayoutMode.fields.input> => {
150
- if (!S.is(LayoutAction.SetLayoutMode.fields.input)(data)) {
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.requestCapability(DeckCapabilities.MutableDeckState);
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 S.Schema.Type<typeof LayoutAction.SwitchWorkspace.fields.input> =>
206
- S.is(LayoutAction.SwitchWorkspace.fields.input)(data),
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 state = context.requestCapability(DeckCapabilities.MutableDeckState);
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 S.Schema.Type<typeof LayoutAction.RevertWorkspace.fields.input> =>
232
- S.is(LayoutAction.RevertWorkspace.fields.input)(data),
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.requestCapability(DeckCapabilities.MutableDeckState);
242
+ const state = context.getCapability(DeckCapabilities.MutableDeckState);
235
243
  return {
236
244
  intents: [createIntent(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: state.previousDeck })],
237
245
  };
@@ -239,19 +247,19 @@ export default (context: PluginsContext) =>
239
247
  }),
240
248
  createResolver({
241
249
  intent: LayoutAction.UpdateLayout,
242
- filter: (data): data is S.Schema.Type<typeof LayoutAction.Open.fields.input> =>
243
- S.is(LayoutAction.Open.fields.input)(data),
250
+ filter: (data): data is Schema.Schema.Type<typeof LayoutAction.Open.fields.input> =>
251
+ Schema.is(LayoutAction.Open.fields.input)(data),
244
252
  resolve: ({ subject, options }) =>
245
253
  Effect.gen(function* () {
246
- const { graph } = context.requestCapability(Capabilities.AppGraph);
247
- const state = context.requestCapability(DeckCapabilities.MutableDeckState);
248
- const attention = context.requestCapability(AttentionCapabilities.Attention);
254
+ const { graph } = context.getCapability(Capabilities.AppGraph);
255
+ const state = context.getCapability(DeckCapabilities.MutableDeckState);
256
+ const attention = context.getCapability(AttentionCapabilities.Attention);
249
257
  const settings = context
250
- .requestCapabilities(Capabilities.SettingsStore)[0]
258
+ .getCapabilities(Capabilities.SettingsStore)[0]
251
259
  ?.getStore<DeckSettingsProps>(DECK_PLUGIN)?.value;
252
260
 
253
261
  if (options?.workspace && state.activeDeck !== options?.workspace) {
254
- const { dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
262
+ const { dispatch } = context.getCapability(Capabilities.IntentDispatcher);
255
263
  yield* dispatch(
256
264
  createIntent(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: options.workspace }),
257
265
  );
@@ -285,8 +293,13 @@ export default (context: PluginsContext) =>
285
293
  : []),
286
294
  createIntent(LayoutAction.Expose, { part: 'navigation', subject: newlyOpen[0] ?? subject[0] }),
287
295
  ...newlyOpen.map((subjectId) => {
288
- const active = graph?.findNode(subjectId)?.data;
289
- const typename = isLiveObject(active) ? getTypename(active) : undefined;
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
+ });
290
303
  return createIntent(ObservabilityAction.SendEvent, {
291
304
  name: 'navigation.activate',
292
305
  properties: {
@@ -301,11 +314,11 @@ export default (context: PluginsContext) =>
301
314
  }),
302
315
  createResolver({
303
316
  intent: LayoutAction.UpdateLayout,
304
- filter: (data): data is S.Schema.Type<typeof LayoutAction.Close.fields.input> =>
305
- S.is(LayoutAction.Close.fields.input)(data),
317
+ filter: (data): data is Schema.Schema.Type<typeof LayoutAction.Close.fields.input> =>
318
+ Schema.is(LayoutAction.Close.fields.input)(data),
306
319
  resolve: ({ subject }) => {
307
- const state = context.requestCapability(DeckCapabilities.MutableDeckState);
308
- const attention = context.requestCapability(AttentionCapabilities.Attention);
320
+ const state = context.getCapability(DeckCapabilities.MutableDeckState);
321
+ const attention = context.getCapability(AttentionCapabilities.Attention);
309
322
  const active = state.deck.solo ? [state.deck.solo] : state.deck.active;
310
323
  const next = subject.reduce((acc, id) => closeEntry(acc, id), active);
311
324
  const toAttend = setActive({ next, state, attention });
@@ -324,11 +337,11 @@ export default (context: PluginsContext) =>
324
337
  }),
325
338
  createResolver({
326
339
  intent: LayoutAction.UpdateLayout,
327
- filter: (data): data is S.Schema.Type<typeof LayoutAction.Set.fields.input> =>
328
- S.is(LayoutAction.Set.fields.input)(data),
340
+ filter: (data): data is Schema.Schema.Type<typeof LayoutAction.Set.fields.input> =>
341
+ Schema.is(LayoutAction.Set.fields.input)(data),
329
342
  resolve: ({ subject }) => {
330
- const state = context.requestCapability(DeckCapabilities.MutableDeckState);
331
- const attention = context.requestCapability(AttentionCapabilities.Attention);
343
+ const state = context.getCapability(DeckCapabilities.MutableDeckState);
344
+ const attention = context.getCapability(AttentionCapabilities.Attention);
332
345
  const toAttend = setActive({ next: subject as string[], state, attention });
333
346
  return {
334
347
  intents: toAttend ? [createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: toAttend })] : [],
@@ -337,24 +350,24 @@ export default (context: PluginsContext) =>
337
350
  }),
338
351
  createResolver({
339
352
  intent: LayoutAction.UpdateLayout,
340
- filter: (data): data is S.Schema.Type<typeof LayoutAction.ScrollIntoView.fields.input> =>
341
- S.is(LayoutAction.ScrollIntoView.fields.input)(data),
353
+ filter: (data): data is Schema.Schema.Type<typeof LayoutAction.ScrollIntoView.fields.input> =>
354
+ Schema.is(LayoutAction.ScrollIntoView.fields.input)(data),
342
355
  resolve: ({ subject }) => {
343
- const layout = context.requestCapability(DeckCapabilities.MutableDeckState);
356
+ const layout = context.getCapability(DeckCapabilities.MutableDeckState);
344
357
  layout.scrollIntoView = subject;
345
358
  },
346
359
  }),
347
360
  createResolver({
348
361
  intent: DeckAction.UpdatePlankSize,
349
362
  resolve: (data) => {
350
- const state = context.requestCapability(DeckCapabilities.MutableDeckState);
363
+ const state = context.getCapability(DeckCapabilities.MutableDeckState);
351
364
  state.deck.plankSizing[data.id] = data.size;
352
365
  },
353
366
  }),
354
367
  createResolver({
355
368
  intent: DeckAction.ChangeCompanion,
356
369
  resolve: (data) => {
357
- const state = context.requestCapability(DeckCapabilities.MutableDeckState);
370
+ const state = context.getCapability(DeckCapabilities.MutableDeckState);
358
371
  // TODO(thure): Reactivity only works when creating a lexically new `activeCompanions`… Are these not proxy objects?
359
372
  if (data.companion === null) {
360
373
  const { [data.primary]: _, ...nextActiveCompanions } = state.deck.activeCompanions ?? {};
@@ -371,9 +384,9 @@ export default (context: PluginsContext) =>
371
384
  createResolver({
372
385
  intent: DeckAction.Adjust,
373
386
  resolve: (adjustment) => {
374
- const state = context.requestCapability(DeckCapabilities.MutableDeckState);
375
- const attention = context.requestCapability(AttentionCapabilities.Attention);
376
- const { graph } = context.requestCapability(Capabilities.AppGraph);
387
+ const state = context.getCapability(DeckCapabilities.MutableDeckState);
388
+ const attention = context.getCapability(AttentionCapabilities.Attention);
389
+ const { graph } = context.getCapability(Capabilities.AppGraph);
377
390
 
378
391
  return batch(() => {
379
392
  if (adjustment.type === 'increment-end' || adjustment.type === 'increment-start') {
@@ -385,20 +398,25 @@ export default (context: PluginsContext) =>
385
398
  }
386
399
 
387
400
  if (adjustment.type === 'companion') {
388
- const node = graph.findNode(adjustment.id);
389
- const [companion] = node
390
- ? graph
391
- .nodes(node, { filter: (n): n is Node<any> => n.type === PLANK_COMPANION_TYPE })
392
- .toSorted((a, b) => byPosition(a.properties, b.properties))
393
- : [];
394
- if (companion) {
395
- return {
396
- intents: [
397
- // TODO(wittjosiah): This should remember the previously selected companion.
398
- createIntent(DeckAction.ChangeCompanion, { primary: adjustment.id, companion: companion.id }),
399
- ],
400
- };
401
- }
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
+ );
402
420
  }
403
421
 
404
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: true,
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 DeckState, type DeckPluginState, defaultDeck } from '../types';
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
- export default () => {
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;