@dxos/plugin-deck 0.8.2-main.fbd8ed0 → 0.8.2-staging.7ac8446

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 (151) hide show
  1. package/dist/lib/browser/{app-graph-builder-R7COZ4A6.mjs → app-graph-builder-VYZ4IWI3.mjs} +15 -16
  2. package/dist/lib/browser/app-graph-builder-VYZ4IWI3.mjs.map +7 -0
  3. package/dist/lib/browser/{check-app-scheme-7AXGR6UT.mjs → check-app-scheme-SEYECDHI.mjs} +3 -2
  4. package/dist/lib/browser/check-app-scheme-SEYECDHI.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-6ZSOFCPP.mjs +117 -0
  6. package/dist/lib/browser/chunk-6ZSOFCPP.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-B4LOJUWW.mjs +24 -0
  8. package/dist/lib/browser/chunk-B4LOJUWW.mjs.map +7 -0
  9. package/dist/lib/browser/{chunk-KIGMELV2.mjs → chunk-FJBMNSUC.mjs} +336 -366
  10. package/dist/lib/browser/chunk-FJBMNSUC.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-FLOVGNYB.mjs +81 -0
  12. package/dist/lib/browser/chunk-FLOVGNYB.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-RJNCG4ND.mjs +154 -0
  14. package/dist/lib/browser/chunk-RJNCG4ND.mjs.map +7 -0
  15. package/dist/lib/browser/index.mjs +5 -6
  16. package/dist/lib/browser/index.mjs.map +2 -2
  17. package/dist/lib/browser/{intent-resolver-MAKOS57L.mjs → intent-resolver-UDYKO2QW.mjs} +89 -130
  18. package/dist/lib/browser/intent-resolver-UDYKO2QW.mjs.map +7 -0
  19. package/dist/lib/browser/meta.json +1 -1
  20. package/dist/lib/browser/{react-root-DGQVIHXP.mjs → react-root-XLXN2VEW.mjs} +6 -6
  21. package/dist/lib/browser/{react-surface-PXBXIOPU.mjs → react-surface-WNGMZL7I.mjs} +6 -6
  22. package/dist/lib/browser/{settings-UBWJF7J7.mjs → settings-HMDGSBGO.mjs} +6 -6
  23. package/dist/lib/browser/settings-HMDGSBGO.mjs.map +7 -0
  24. package/dist/lib/browser/{chunk-OF5RIATN.mjs → state-7TN26M42.mjs} +7 -10
  25. package/dist/lib/browser/state-7TN26M42.mjs.map +7 -0
  26. package/dist/lib/browser/{tools-IVPIPTVA.mjs → tools-SC6QEN7R.mjs} +7 -7
  27. package/dist/lib/browser/tools-SC6QEN7R.mjs.map +7 -0
  28. package/dist/lib/browser/types.mjs +1 -1
  29. package/dist/lib/browser/{url-handler-JSYGSVSB.mjs → url-handler-ODG4B6NX.mjs} +4 -4
  30. package/dist/lib/browser/url-handler-ODG4B6NX.mjs.map +7 -0
  31. package/dist/types/src/capabilities/app-graph-builder.d.ts +179 -2
  32. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  33. package/dist/types/src/capabilities/capabilities.d.ts +6 -8
  34. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  35. package/dist/types/src/capabilities/check-app-scheme.d.ts +2 -2
  36. package/dist/types/src/capabilities/check-app-scheme.d.ts.map +1 -1
  37. package/dist/types/src/capabilities/index.d.ts +182 -7
  38. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  39. package/dist/types/src/capabilities/intent-resolver.d.ts +2 -2
  40. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  41. package/dist/types/src/capabilities/state.d.ts +6 -7
  42. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  43. package/dist/types/src/capabilities/tools.d.ts.map +1 -1
  44. package/dist/types/src/capabilities/url-handler.d.ts +2 -2
  45. package/dist/types/src/capabilities/url-handler.d.ts.map +1 -1
  46. package/dist/types/src/components/DeckLayout/Banner.d.ts.map +1 -1
  47. package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts.map +1 -1
  48. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
  49. package/dist/types/src/components/DeckLayout/Fullscreen.d.ts +5 -0
  50. package/dist/types/src/components/DeckLayout/Fullscreen.d.ts.map +1 -0
  51. package/dist/types/src/components/DeckLayout/StatusBar.d.ts.map +1 -1
  52. package/dist/types/src/components/DeckLayout/Toast.d.ts.map +1 -1
  53. package/dist/types/src/components/DeckSettings/DeckSettings.d.ts.map +1 -1
  54. package/dist/types/src/components/Plank/Plank.d.ts +5 -18
  55. package/dist/types/src/components/Plank/Plank.d.ts.map +1 -1
  56. package/dist/types/src/components/Plank/Plank.stories.d.ts +3 -3
  57. package/dist/types/src/components/Plank/Plank.stories.d.ts.map +1 -1
  58. package/dist/types/src/components/Plank/PlankControls.d.ts +2 -3
  59. package/dist/types/src/components/Plank/PlankControls.d.ts.map +1 -1
  60. package/dist/types/src/components/Plank/PlankError.d.ts.map +1 -1
  61. package/dist/types/src/components/Plank/PlankHeading.d.ts +2 -3
  62. package/dist/types/src/components/Plank/PlankHeading.d.ts.map +1 -1
  63. package/dist/types/src/components/Sidebar/ComplementarySidebar.d.ts.map +1 -1
  64. package/dist/types/src/components/Sidebar/Sidebar.d.ts.map +1 -1
  65. package/dist/types/src/components/Sidebar/SidebarButton.d.ts +1 -2
  66. package/dist/types/src/components/Sidebar/SidebarButton.d.ts.map +1 -1
  67. package/dist/types/src/hooks/index.d.ts +1 -5
  68. package/dist/types/src/hooks/index.d.ts.map +1 -1
  69. package/dist/types/src/hooks/useNodeActionExpander.d.ts.map +1 -1
  70. package/dist/types/src/index.d.ts +1 -1
  71. package/dist/types/src/index.d.ts.map +1 -1
  72. package/dist/types/src/layout.d.ts.map +1 -1
  73. package/dist/types/src/translations.d.ts +0 -2
  74. package/dist/types/src/translations.d.ts.map +1 -1
  75. package/dist/types/src/types.d.ts +104 -106
  76. package/dist/types/src/types.d.ts.map +1 -1
  77. package/dist/types/src/util/index.d.ts +4 -1
  78. package/dist/types/src/util/index.d.ts.map +1 -1
  79. package/dist/types/src/util/layoutAppliesTopbar.d.ts +1 -2
  80. package/dist/types/src/util/layoutAppliesTopbar.d.ts.map +1 -1
  81. package/dist/types/src/util/overscroll.d.ts.map +1 -1
  82. package/dist/types/src/util/set-active.d.ts.map +1 -1
  83. package/dist/types/src/util/useBreakpoints.d.ts.map +1 -0
  84. package/dist/types/src/util/useCompanions.d.ts.map +1 -0
  85. package/dist/types/src/util/useHoistStatusbar.d.ts +2 -0
  86. package/dist/types/src/util/useHoistStatusbar.d.ts.map +1 -0
  87. package/dist/types/tsconfig.tsbuildinfo +1 -1
  88. package/package.json +29 -36
  89. package/src/capabilities/app-graph-builder.ts +92 -120
  90. package/src/capabilities/check-app-scheme.ts +7 -3
  91. package/src/capabilities/index.ts +2 -3
  92. package/src/capabilities/intent-resolver.ts +133 -175
  93. package/src/capabilities/settings.ts +4 -4
  94. package/src/capabilities/state.ts +4 -7
  95. package/src/capabilities/tools.ts +3 -4
  96. package/src/capabilities/url-handler.ts +4 -4
  97. package/src/components/DeckLayout/ContentEmpty.tsx +4 -9
  98. package/src/components/DeckLayout/DeckLayout.tsx +188 -123
  99. package/src/components/DeckLayout/Fullscreen.tsx +31 -0
  100. package/src/components/Plank/Plank.stories.tsx +8 -20
  101. package/src/components/Plank/Plank.tsx +68 -104
  102. package/src/components/Plank/PlankControls.tsx +57 -53
  103. package/src/components/Plank/PlankError.tsx +6 -2
  104. package/src/components/Plank/PlankHeading.tsx +12 -29
  105. package/src/components/Sidebar/ComplementarySidebar.tsx +54 -33
  106. package/src/components/Sidebar/Sidebar.tsx +4 -7
  107. package/src/components/Sidebar/SidebarButton.tsx +7 -30
  108. package/src/components/fragments.ts +1 -1
  109. package/src/hooks/index.ts +1 -5
  110. package/src/hooks/useNodeActionExpander.ts +8 -3
  111. package/src/index.ts +1 -1
  112. package/src/translations.ts +0 -2
  113. package/src/types.ts +71 -75
  114. package/src/util/index.ts +4 -1
  115. package/src/util/layoutAppliesTopbar.ts +2 -8
  116. package/src/{hooks → util}/useCompanions.ts +3 -3
  117. package/src/{hooks → util}/useHoistStatusbar.ts +4 -9
  118. package/dist/lib/browser/app-graph-builder-R7COZ4A6.mjs.map +0 -7
  119. package/dist/lib/browser/check-app-scheme-7AXGR6UT.mjs.map +0 -7
  120. package/dist/lib/browser/chunk-3O2UZVBA.mjs +0 -121
  121. package/dist/lib/browser/chunk-3O2UZVBA.mjs.map +0 -7
  122. package/dist/lib/browser/chunk-JAYQ5BTF.mjs +0 -157
  123. package/dist/lib/browser/chunk-JAYQ5BTF.mjs.map +0 -7
  124. package/dist/lib/browser/chunk-KIGMELV2.mjs.map +0 -7
  125. package/dist/lib/browser/chunk-OF5RIATN.mjs.map +0 -7
  126. package/dist/lib/browser/chunk-TRFYUEBA.mjs +0 -145
  127. package/dist/lib/browser/chunk-TRFYUEBA.mjs.map +0 -7
  128. package/dist/lib/browser/intent-resolver-MAKOS57L.mjs.map +0 -7
  129. package/dist/lib/browser/settings-UBWJF7J7.mjs.map +0 -7
  130. package/dist/lib/browser/state-4WFB4SDO.mjs +0 -10
  131. package/dist/lib/browser/state-4WFB4SDO.mjs.map +0 -7
  132. package/dist/lib/browser/tools-IVPIPTVA.mjs.map +0 -7
  133. package/dist/lib/browser/url-handler-JSYGSVSB.mjs.map +0 -7
  134. package/dist/types/src/components/DeckLayout/Dialog.d.ts +0 -3
  135. package/dist/types/src/components/DeckLayout/Dialog.d.ts.map +0 -1
  136. package/dist/types/src/components/DeckLayout/Popover.d.ts +0 -5
  137. package/dist/types/src/components/DeckLayout/Popover.d.ts.map +0 -1
  138. package/dist/types/src/hooks/useBreakpoints.d.ts.map +0 -1
  139. package/dist/types/src/hooks/useCompanions.d.ts.map +0 -1
  140. package/dist/types/src/hooks/useDeckCompanions.d.ts +0 -13
  141. package/dist/types/src/hooks/useDeckCompanions.d.ts.map +0 -1
  142. package/dist/types/src/hooks/useHoistStatusbar.d.ts +0 -3
  143. package/dist/types/src/hooks/useHoistStatusbar.d.ts.map +0 -1
  144. package/src/components/DeckLayout/Dialog.tsx +0 -36
  145. package/src/components/DeckLayout/Popover.tsx +0 -104
  146. package/src/hooks/useDeckCompanions.ts +0 -33
  147. /package/dist/lib/browser/{react-root-DGQVIHXP.mjs.map → react-root-XLXN2VEW.mjs.map} +0 -0
  148. /package/dist/lib/browser/{react-surface-PXBXIOPU.mjs.map → react-surface-WNGMZL7I.mjs.map} +0 -0
  149. /package/dist/types/src/{hooks → util}/useBreakpoints.d.ts +0 -0
  150. /package/dist/types/src/{hooks → util}/useCompanions.d.ts +0 -0
  151. /package/src/{hooks → util}/useBreakpoints.ts +0 -0
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { batch } from '@preact/signals-core';
6
- import { Schema, Effect, pipe, Option } from 'effect';
6
+ import { pipe } 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 PluginContext,
14
+ type PluginsContext,
15
15
  createIntent,
16
16
  chain,
17
17
  } from '@dxos/app-framework';
18
- import { getTypename } from '@dxos/echo-schema';
18
+ import { getTypename, S } from '@dxos/echo-schema';
19
19
  import { invariant } from '@dxos/invariant';
20
- import { isLiveObject } from '@dxos/live-object';
20
+ import { isReactiveObject } from '@dxos/live-object';
21
21
  import { log } from '@dxos/log';
22
22
  import { AttentionCapabilities } from '@dxos/plugin-attention';
23
- import { isActionLike } from '@dxos/plugin-graph';
23
+ import { type Node } 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: PluginContext) =>
41
+ export default (context: PluginsContext) =>
42
42
  contributes(Capabilities.IntentResolver, [
43
43
  createResolver({
44
44
  intent: IntentAction.ShowUndo,
45
45
  resolve: (data) => {
46
- const layout = context.getCapability(DeckCapabilities.MutableDeckState);
47
- const { undoPromise: undo } = context.getCapability(Capabilities.IntentDispatcher);
46
+ const layout = context.requestCapability(DeckCapabilities.MutableDeckState);
47
+ const { undoPromise: undo } = context.requestCapability(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: PluginContext) =>
67
67
  }),
68
68
  createResolver({
69
69
  intent: LayoutAction.UpdateLayout,
70
- // TODO(wittjosiah): This should be able to just be `Schema.is(LayoutAction.UpdateSidebar.fields.input)`
70
+ // TODO(wittjosiah): This should be able to just be `S.is(LayoutAction.UpdateSidebar.fields.input)`
71
71
  // but the filter is not being applied correctly.
72
- filter: (data): data is Schema.Schema.Type<typeof LayoutAction.UpdateSidebar.fields.input> =>
73
- Schema.is(LayoutAction.UpdateSidebar.fields.input)(data),
72
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.UpdateSidebar.fields.input> =>
73
+ S.is(LayoutAction.UpdateSidebar.fields.input)(data),
74
74
  resolve: ({ options }) => {
75
- const layout = context.getCapability(DeckCapabilities.MutableDeckState);
75
+ const layout = context.requestCapability(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: PluginContext) =>
81
81
  }),
82
82
  createResolver({
83
83
  intent: LayoutAction.UpdateLayout,
84
- // TODO(wittjosiah): This should be able to just be `Schema.is(LayoutAction.UpdateComplementary.fields.input)`
84
+ // TODO(wittjosiah): This should be able to just be `S.is(LayoutAction.UpdateComplementary.fields.input)`
85
85
  // but the filter is not being applied correctly.
86
- filter: (data): data is Schema.Schema.Type<typeof LayoutAction.UpdateComplementary.fields.input> =>
87
- Schema.is(LayoutAction.UpdateComplementary.fields.input)(data),
86
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.UpdateComplementary.fields.input> =>
87
+ S.is(LayoutAction.UpdateComplementary.fields.input)(data),
88
88
  resolve: ({ subject, options }) => {
89
- const layout = context.getCapability(DeckCapabilities.MutableDeckState);
89
+ const layout = context.requestCapability(DeckCapabilities.MutableDeckState);
90
90
 
91
91
  if (layout.complementarySidebarPanel !== subject) {
92
92
  layout.complementarySidebarPanel = subject;
@@ -100,12 +100,12 @@ export default (context: PluginContext) =>
100
100
  }),
101
101
  createResolver({
102
102
  intent: LayoutAction.UpdateLayout,
103
- // TODO(wittjosiah): This should be able to just be `Schema.is(LayoutAction.UpdateDialog.fields.input)`
103
+ // TODO(wittjosiah): This should be able to just be `S.is(LayoutAction.UpdateDialog.fields.input)`
104
104
  // but the filter is not being applied correctly.
105
- filter: (data): data is Schema.Schema.Type<typeof LayoutAction.UpdateDialog.fields.input> =>
106
- Schema.is(LayoutAction.UpdateDialog.fields.input)(data),
105
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.UpdateDialog.fields.input> =>
106
+ S.is(LayoutAction.UpdateDialog.fields.input)(data),
107
107
  resolve: ({ subject, options }) => {
108
- const layout = context.getCapability(DeckCapabilities.MutableDeckState);
108
+ const layout = context.requestCapability(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,40 +114,35 @@ export default (context: PluginContext) =>
114
114
  }),
115
115
  createResolver({
116
116
  intent: LayoutAction.UpdateLayout,
117
- // TODO(wittjosiah): This should be able to just be `Schema.is(LayoutAction.UpdatePopover.fields.input)`
117
+ // TODO(wittjosiah): This should be able to just be `S.is(LayoutAction.UpdatePopover.fields.input)`
118
118
  // but the filter is not being applied correctly.
119
- filter: (data): data is Schema.Schema.Type<typeof LayoutAction.UpdatePopover.fields.input> =>
120
- Schema.is(LayoutAction.UpdatePopover.fields.input)(data),
119
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.UpdatePopover.fields.input> =>
120
+ S.is(LayoutAction.UpdatePopover.fields.input)(data),
121
121
  resolve: ({ subject, options }) => {
122
- const layout = context.getCapability(DeckCapabilities.MutableDeckState);
122
+ const layout = context.requestCapability(DeckCapabilities.MutableDeckState);
123
123
  layout.popoverOpen = options.state ?? Boolean(subject);
124
- layout.popoverContent =
125
- typeof subject === 'string' ? { component: subject, props: options.props } : subject ? { subject } : null;
124
+ layout.popoverContent = subject ? { component: subject, props: options.props } : null;
125
+ layout.popoverAnchorId = options.anchorId;
126
126
  layout.popoverSide = options.side;
127
- if (options.variant === 'virtual') {
128
- layout.popoverAnchor = options.anchor;
129
- } else {
130
- layout.popoverAnchorId = options.anchorId;
131
- }
132
127
  },
133
128
  }),
134
129
  createResolver({
135
130
  intent: LayoutAction.UpdateLayout,
136
- // TODO(wittjosiah): This should be able to just be `Schema.is(LayoutAction.AddToast.fields.input)`
131
+ // TODO(wittjosiah): This should be able to just be `S.is(LayoutAction.AddToast.fields.input)`
137
132
  // but the filter is not being applied correctly.
138
- filter: (data): data is Schema.Schema.Type<typeof LayoutAction.AddToast.fields.input> =>
139
- Schema.is(LayoutAction.AddToast.fields.input)(data),
133
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.AddToast.fields.input> =>
134
+ S.is(LayoutAction.AddToast.fields.input)(data),
140
135
  resolve: ({ subject }) => {
141
- const layout = context.getCapability(DeckCapabilities.MutableDeckState);
136
+ const layout = context.requestCapability(DeckCapabilities.MutableDeckState);
142
137
  layout.toasts.push(subject);
143
138
  },
144
139
  }),
145
140
  createResolver({
146
141
  intent: LayoutAction.UpdateLayout,
147
- // TODO(wittjosiah): This should be able to just be `Schema.is(LayoutAction.SetLayoutMode.fields.input)`
142
+ // TODO(wittjosiah): This should be able to just be `S.is(LayoutAction.SetLayoutMode.fields.input)`
148
143
  // but the filter is not being applied correctly.
149
- filter: (data): data is Schema.Schema.Type<typeof LayoutAction.SetLayoutMode.fields.input> => {
150
- if (!Schema.is(LayoutAction.SetLayoutMode.fields.input)(data)) {
144
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.SetLayoutMode.fields.input> => {
145
+ if (!S.is(LayoutAction.SetLayoutMode.fields.input)(data)) {
151
146
  return false;
152
147
  }
153
148
 
@@ -158,7 +153,7 @@ export default (context: PluginContext) =>
158
153
  return true;
159
154
  },
160
155
  resolve: ({ subject, options }) => {
161
- const state = context.getCapability(DeckCapabilities.MutableDeckState);
156
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
162
157
 
163
158
  const setMode = (mode: LayoutMode) => {
164
159
  const deck = state.deck;
@@ -179,8 +174,10 @@ export default (context: PluginContext) =>
179
174
  deck.initialized = true;
180
175
  }
181
176
 
182
- if (mode === 'solo--fullscreen') {
183
- deck.fullscreen = !deck.fullscreen;
177
+ if (mode === 'fullscreen' && !deck.fullscreen) {
178
+ deck.fullscreen = true;
179
+ } else if (mode !== 'fullscreen' && deck.fullscreen) {
180
+ deck.fullscreen = false;
184
181
  }
185
182
  };
186
183
 
@@ -202,11 +199,10 @@ export default (context: PluginContext) =>
202
199
  }),
203
200
  createResolver({
204
201
  intent: LayoutAction.UpdateLayout,
205
- filter: (data): data is Schema.Schema.Type<typeof LayoutAction.SwitchWorkspace.fields.input> =>
206
- Schema.is(LayoutAction.SwitchWorkspace.fields.input)(data),
202
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.SwitchWorkspace.fields.input> =>
203
+ S.is(LayoutAction.SwitchWorkspace.fields.input)(data),
207
204
  resolve: ({ subject }) => {
208
- const { graph } = context.getCapability(Capabilities.AppGraph);
209
- const state = context.getCapability(DeckCapabilities.MutableDeckState);
205
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
210
206
  batch(() => {
211
207
  // TODO(wittjosiah): This is a hack to prevent the previous deck from being set for pinned items.
212
208
  // Ideally this should be worked into the data model in a generic way.
@@ -224,22 +220,15 @@ export default (context: PluginContext) =>
224
220
  return {
225
221
  intents: [createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: first })],
226
222
  };
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
- }
234
223
  }
235
224
  },
236
225
  }),
237
226
  createResolver({
238
227
  intent: LayoutAction.UpdateLayout,
239
- filter: (data): data is Schema.Schema.Type<typeof LayoutAction.RevertWorkspace.fields.input> =>
240
- Schema.is(LayoutAction.RevertWorkspace.fields.input)(data),
228
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.RevertWorkspace.fields.input> =>
229
+ S.is(LayoutAction.RevertWorkspace.fields.input)(data),
241
230
  resolve: () => {
242
- const state = context.getCapability(DeckCapabilities.MutableDeckState);
231
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
243
232
  return {
244
233
  intents: [createIntent(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: state.previousDeck })],
245
234
  };
@@ -247,78 +236,65 @@ export default (context: PluginContext) =>
247
236
  }),
248
237
  createResolver({
249
238
  intent: LayoutAction.UpdateLayout,
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;
260
-
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
- }
239
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.Open.fields.input> =>
240
+ S.is(LayoutAction.Open.fields.input)(data),
241
+ resolve: ({ subject, options }) => {
242
+ const { graph } = context.requestCapability(Capabilities.AppGraph);
243
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
244
+ const attention = context.requestCapability(AttentionCapabilities.Attention);
245
+ const settings = context
246
+ .requestCapabilities(Capabilities.SettingsStore)[0]
247
+ ?.getStore<DeckSettingsProps>(DECK_PLUGIN)?.value;
267
248
 
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
- );
249
+ const previouslyOpenIds = new Set<string>(state.deck.solo ? [state.deck.solo] : state.deck.active);
250
+ batch(() => {
251
+ const next = state.deck.solo
252
+ ? (subject as string[]).map((id) => createEntryId(id, options?.variant))
253
+ : subject.reduce(
254
+ (acc, entryId) =>
255
+ openEntry(acc, entryId, {
256
+ key: options?.key,
257
+ positioning: options?.positioning ?? settings?.newPlankPositioning,
258
+ pivotId: options?.pivotId,
259
+ variant: options?.variant,
260
+ }),
261
+ state.deck.active,
262
+ );
282
263
 
283
- return setActive({ next, state, attention });
284
- });
264
+ return setActive({ next, state, attention });
265
+ });
285
266
 
286
- const ids = state.deck.solo ? [state.deck.solo] : state.deck.active;
287
- const newlyOpen = ids.filter((i) => !previouslyOpenIds.has(i));
267
+ const ids = state.deck.solo ? [state.deck.solo] : state.deck.active;
268
+ const newlyOpen = ids.filter((i) => !previouslyOpenIds.has(i));
288
269
 
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
- }),
270
+ return {
271
+ intents: [
272
+ ...(options?.scrollIntoView !== false
273
+ ? [createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: newlyOpen[0] ?? subject[0] })]
274
+ : []),
275
+ createIntent(LayoutAction.Expose, { part: 'navigation', subject: newlyOpen[0] ?? subject[0] }),
276
+ ...newlyOpen.map((subjectId) => {
277
+ const active = graph?.findNode(subjectId)?.data;
278
+ const typename = isReactiveObject(active) ? getTypename(active) : undefined;
279
+ return createIntent(ObservabilityAction.SendEvent, {
280
+ name: 'navigation.activate',
281
+ properties: {
282
+ subjectId,
283
+ typename,
284
+ },
285
+ });
286
+ }),
287
+ ],
288
+ };
289
+ },
314
290
  }),
315
291
  createResolver({
316
292
  intent: LayoutAction.UpdateLayout,
317
- filter: (data): data is Schema.Schema.Type<typeof LayoutAction.Close.fields.input> =>
318
- Schema.is(LayoutAction.Close.fields.input)(data),
293
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.Close.fields.input> =>
294
+ S.is(LayoutAction.Close.fields.input)(data),
319
295
  resolve: ({ subject }) => {
320
- const state = context.getCapability(DeckCapabilities.MutableDeckState);
321
- const attention = context.getCapability(AttentionCapabilities.Attention);
296
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
297
+ const attention = context.requestCapability(AttentionCapabilities.Attention);
322
298
  const active = state.deck.solo ? [state.deck.solo] : state.deck.active;
323
299
  const next = subject.reduce((acc, id) => closeEntry(acc, id), active);
324
300
  const toAttend = setActive({ next, state, attention });
@@ -337,11 +313,11 @@ export default (context: PluginContext) =>
337
313
  }),
338
314
  createResolver({
339
315
  intent: LayoutAction.UpdateLayout,
340
- filter: (data): data is Schema.Schema.Type<typeof LayoutAction.Set.fields.input> =>
341
- Schema.is(LayoutAction.Set.fields.input)(data),
316
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.Set.fields.input> =>
317
+ S.is(LayoutAction.Set.fields.input)(data),
342
318
  resolve: ({ subject }) => {
343
- const state = context.getCapability(DeckCapabilities.MutableDeckState);
344
- const attention = context.getCapability(AttentionCapabilities.Attention);
319
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
320
+ const attention = context.requestCapability(AttentionCapabilities.Attention);
345
321
  const toAttend = setActive({ next: subject as string[], state, attention });
346
322
  return {
347
323
  intents: toAttend ? [createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: toAttend })] : [],
@@ -350,24 +326,24 @@ export default (context: PluginContext) =>
350
326
  }),
351
327
  createResolver({
352
328
  intent: LayoutAction.UpdateLayout,
353
- filter: (data): data is Schema.Schema.Type<typeof LayoutAction.ScrollIntoView.fields.input> =>
354
- Schema.is(LayoutAction.ScrollIntoView.fields.input)(data),
329
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.ScrollIntoView.fields.input> =>
330
+ S.is(LayoutAction.ScrollIntoView.fields.input)(data),
355
331
  resolve: ({ subject }) => {
356
- const layout = context.getCapability(DeckCapabilities.MutableDeckState);
332
+ const layout = context.requestCapability(DeckCapabilities.MutableDeckState);
357
333
  layout.scrollIntoView = subject;
358
334
  },
359
335
  }),
360
336
  createResolver({
361
337
  intent: DeckAction.UpdatePlankSize,
362
338
  resolve: (data) => {
363
- const state = context.getCapability(DeckCapabilities.MutableDeckState);
339
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
364
340
  state.deck.plankSizing[data.id] = data.size;
365
341
  },
366
342
  }),
367
343
  createResolver({
368
344
  intent: DeckAction.ChangeCompanion,
369
345
  resolve: (data) => {
370
- const state = context.getCapability(DeckCapabilities.MutableDeckState);
346
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
371
347
  // TODO(thure): Reactivity only works when creating a lexically new `activeCompanions`… Are these not proxy objects?
372
348
  if (data.companion === null) {
373
349
  const { [data.primary]: _, ...nextActiveCompanions } = state.deck.activeCompanions ?? {};
@@ -384,9 +360,9 @@ export default (context: PluginContext) =>
384
360
  createResolver({
385
361
  intent: DeckAction.Adjust,
386
362
  resolve: (adjustment) => {
387
- const state = context.getCapability(DeckCapabilities.MutableDeckState);
388
- const attention = context.getCapability(AttentionCapabilities.Attention);
389
- const { graph } = context.getCapability(Capabilities.AppGraph);
363
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
364
+ const attention = context.requestCapability(AttentionCapabilities.Attention);
365
+ const { graph } = context.requestCapability(Capabilities.AppGraph);
390
366
 
391
367
  return batch(() => {
392
368
  if (adjustment.type === 'increment-end' || adjustment.type === 'increment-start') {
@@ -398,28 +374,23 @@ export default (context: PluginContext) =>
398
374
  }
399
375
 
400
376
  if (adjustment.type === 'companion') {
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
- );
377
+ const node = graph.findNode(adjustment.id);
378
+ const [companion] = node
379
+ ? graph
380
+ .nodes(node, { filter: (n): n is Node<any> => n.type === PLANK_COMPANION_TYPE })
381
+ .toSorted((a, b) => byPosition(a.properties, b.properties))
382
+ : [];
383
+ if (companion) {
384
+ return {
385
+ intents: [
386
+ // TODO(wittjosiah): This should remember the previously selected companion.
387
+ createIntent(DeckAction.ChangeCompanion, { primary: adjustment.id, companion: companion.id }),
388
+ ],
389
+ };
390
+ }
420
391
  }
421
392
 
422
- if (adjustment.type.startsWith('solo')) {
393
+ if (adjustment.type === 'solo') {
423
394
  const entryId = adjustment.id;
424
395
  if (!state.deck.solo) {
425
396
  // Solo the entry.
@@ -428,34 +399,21 @@ export default (context: PluginContext) =>
428
399
  createIntent(LayoutAction.SetLayoutMode, {
429
400
  part: 'mode',
430
401
  subject: entryId,
431
- options: { mode: adjustment.type },
402
+ options: { mode: 'solo' },
432
403
  }),
433
404
  ],
434
405
  };
435
406
  } else {
436
- if (adjustment.type === 'solo--fullscreen') {
437
- // Toggle fullscreen on the current entry.
438
- return {
439
- intents: [
440
- createIntent(LayoutAction.SetLayoutMode, {
441
- part: 'mode',
442
- subject: entryId,
443
- options: { mode: 'solo--fullscreen' },
444
- }),
445
- ],
446
- };
447
- } else if (adjustment.type === 'solo') {
448
- // Un-solo the current entry.
449
- return {
450
- intents: [
451
- // NOTE: The order of these is important.
452
- pipe(
453
- createIntent(LayoutAction.SetLayoutMode, { part: 'mode', options: { mode: 'deck' } }),
454
- chain(LayoutAction.Open, { part: 'main', subject: [entryId] }),
455
- ),
456
- ],
457
- };
458
- }
407
+ // Un-solo the current entry.
408
+ return {
409
+ intents: [
410
+ // NOTE: The order of these is important.
411
+ pipe(
412
+ createIntent(LayoutAction.SetLayoutMode, { part: 'mode', options: { mode: 'deck' } }),
413
+ chain(LayoutAction.Open, { part: 'main', subject: [entryId] }),
414
+ ),
415
+ ],
416
+ };
459
417
  }
460
418
  }
461
419
  });
@@ -3,17 +3,17 @@
3
3
  //
4
4
 
5
5
  import { Capabilities, contributes } from '@dxos/app-framework';
6
- import { live } from '@dxos/live-object';
6
+ import { create } from '@dxos/live-object';
7
7
 
8
8
  import { DECK_PLUGIN } from '../meta';
9
9
  import { DeckSettingsSchema, type DeckSettingsProps } from '../types';
10
10
 
11
11
  export default () => {
12
- const settings = live<DeckSettingsProps>({
12
+ const settings = create<DeckSettingsProps>({
13
13
  showHints: false,
14
- enableDeck: false,
15
- enableStatusbar: false,
14
+ enableDeck: true,
16
15
  enableNativeRedirect: false,
16
+ enableStatusbar: false,
17
17
  newPlankPositioning: 'start',
18
18
  overscroll: 'none',
19
19
  });
@@ -4,13 +4,13 @@
4
4
 
5
5
  import { Capabilities, contributes } from '@dxos/app-framework';
6
6
  import { invariant } from '@dxos/invariant';
7
- import { live } from '@dxos/live-object';
7
+ import { create } from '@dxos/live-object';
8
8
  import { LocalStorageStore } from '@dxos/local-storage';
9
9
  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 DeckPluginState, defaultDeck, type DeckState } from '../types';
13
+ import { getMode, type DeckState, type DeckPluginState, defaultDeck } 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
- const DeckStateFactory = () => {
32
+ export default () => {
33
33
  migrateSidebarState();
34
34
 
35
35
  const state = new LocalStorageStore<DeckPluginState>(DECK_PLUGIN, {
@@ -41,7 +41,6 @@ const DeckStateFactory = () => {
41
41
  dialogBlockAlign: undefined,
42
42
  dialogType: undefined,
43
43
  popoverContent: null,
44
- popoverAnchor: undefined,
45
44
  popoverAnchorId: undefined,
46
45
  popoverOpen: false,
47
46
  toasts: [],
@@ -68,7 +67,7 @@ const DeckStateFactory = () => {
68
67
  .prop({ key: 'activeDeck', type: LocalStorageStore.string() })
69
68
  .prop({ key: 'previousDeck', type: LocalStorageStore.string() });
70
69
 
71
- const layout = live<Capabilities.Layout>({
70
+ const layout = create<Capabilities.Layout>({
72
71
  get mode() {
73
72
  return getMode(state.values.deck);
74
73
  },
@@ -100,5 +99,3 @@ const DeckStateFactory = () => {
100
99
  contributes(Capabilities.Layout, layout),
101
100
  ];
102
101
  };
103
-
104
- export default DeckStateFactory;
@@ -2,8 +2,6 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Schema } from 'effect';
6
-
7
5
  import {
8
6
  contributes,
9
7
  createIntent,
@@ -12,6 +10,7 @@ import {
12
10
  type PromiseIntentDispatcher,
13
11
  } from '@dxos/app-framework';
14
12
  import { defineTool, ToolResult } from '@dxos/artifact';
13
+ import { S } from '@dxos/echo-schema';
15
14
  import { invariant } from '@dxos/invariant';
16
15
 
17
16
  import { meta } from '../meta';
@@ -36,8 +35,8 @@ export default () =>
36
35
  `,
37
36
  caption: 'Showing item...',
38
37
  // TODO(wittjosiah): Refactor Layout/Navigation/Deck actions so that they can be used directly.
39
- schema: Schema.Struct({
40
- id: Schema.String.annotations({
38
+ schema: S.Struct({
39
+ id: S.String.annotations({
41
40
  description: 'The ID of the item to show.',
42
41
  }),
43
42
  }),
@@ -2,16 +2,16 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Capabilities, contributes, createIntent, LayoutAction, type PluginContext } from '@dxos/app-framework';
5
+ import { Capabilities, contributes, createIntent, LayoutAction, type PluginsContext } 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: PluginContext) => {
13
- const { dispatchPromise: dispatch } = context.getCapability(Capabilities.IntentDispatcher);
14
- const state = context.getCapability(DeckCapabilities.MutableDeckState);
12
+ export default async (context: PluginsContext) => {
13
+ const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher) ?? {};
14
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
15
15
 
16
16
  const handleNavigation = async () => {
17
17
  const pathname = window.location.pathname;
@@ -4,24 +4,19 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { Surface, useCapability } from '@dxos/app-framework';
7
+ import { Surface } from '@dxos/app-framework';
8
8
 
9
- import { DeckCapabilities } from '../../capabilities';
10
- import { useBreakpoints } from '../../hooks';
11
- import { getMode } from '../../types';
12
- import { layoutAppliesTopbar } from '../../util';
9
+ import { layoutAppliesTopbar, useBreakpoints } from '../../util';
13
10
  import { ToggleSidebarButton } from '../Sidebar';
14
11
  import { fixedSidebarToggleStyles } from '../fragments';
15
12
 
16
13
  export const ContentEmpty = () => {
17
14
  const breakpoint = useBreakpoints();
18
- const { deck } = useCapability(DeckCapabilities.MutableDeckState);
19
- const layoutMode = getMode(deck);
20
- const topbar = layoutAppliesTopbar(breakpoint, layoutMode);
15
+ const topbar = layoutAppliesTopbar(breakpoint);
21
16
  return (
22
17
  <div
23
18
  role='none'
24
- className='grid place-items-center p-8 relative bg-deckSurface'
19
+ className='grid place-items-center p-8 relative bg-deck'
25
20
  data-testid='layoutPlugin.firstRunMessage'
26
21
  >
27
22
  <Surface role='keyshortcuts' />