@dxos/plugin-deck 0.7.5-main.9d2a38b → 0.7.5-main.e94eead

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 (233) hide show
  1. package/dist/lib/browser/{app-graph-builder-67VRUD5K.mjs → app-graph-builder-IYHAGFA3.mjs} +61 -31
  2. package/dist/lib/browser/app-graph-builder-IYHAGFA3.mjs.map +7 -0
  3. package/dist/lib/browser/{check-app-scheme-GEX6W2R5.mjs → check-app-scheme-S3EYUPMF.mjs} +3 -3
  4. package/dist/lib/browser/{check-app-scheme-GEX6W2R5.mjs.map → check-app-scheme-S3EYUPMF.mjs.map} +2 -2
  5. package/dist/lib/browser/{chunk-5VFDMW5M.mjs → chunk-22AQ5IVX.mjs} +2 -2
  6. package/dist/lib/browser/chunk-22AQ5IVX.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-FT33W5CI.mjs +128 -0
  8. package/dist/lib/browser/chunk-FT33W5CI.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-G2X3ZDCE.mjs +24 -0
  10. package/dist/lib/browser/chunk-G2X3ZDCE.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-KANJBSIX.mjs +97 -0
  12. package/dist/lib/browser/chunk-KANJBSIX.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-JQJ5UWVB.mjs → chunk-N7TEPFVR.mjs} +3 -2
  14. package/dist/lib/browser/{chunk-JQJ5UWVB.mjs.map → chunk-N7TEPFVR.mjs.map} +3 -3
  15. package/dist/lib/browser/chunk-O4RFYYQ6.mjs +1114 -0
  16. package/dist/lib/browser/chunk-O4RFYYQ6.mjs.map +7 -0
  17. package/dist/lib/browser/index.mjs +45 -78
  18. package/dist/lib/browser/index.mjs.map +4 -4
  19. package/dist/lib/browser/intent-resolver-ZD67BRUI.mjs +488 -0
  20. package/dist/lib/browser/intent-resolver-ZD67BRUI.mjs.map +7 -0
  21. package/dist/lib/browser/meta.json +1 -1
  22. package/dist/lib/browser/{react-root-UL7ZDRVZ.mjs → react-root-6ILKHD5J.mjs} +12 -17
  23. package/dist/lib/browser/react-root-6ILKHD5J.mjs.map +7 -0
  24. package/dist/lib/browser/react-surface-O75FKXAI.mjs +39 -0
  25. package/dist/lib/browser/react-surface-O75FKXAI.mjs.map +7 -0
  26. package/dist/lib/browser/{settings-FNWW6WIJ.mjs → settings-H35U6NHE.mjs} +6 -7
  27. package/dist/lib/browser/settings-H35U6NHE.mjs.map +7 -0
  28. package/dist/lib/browser/state-U4SHOPJW.mjs +129 -0
  29. package/dist/lib/browser/state-U4SHOPJW.mjs.map +7 -0
  30. package/dist/lib/browser/tools-64LXGLYR.mjs +59 -0
  31. package/dist/lib/browser/tools-64LXGLYR.mjs.map +7 -0
  32. package/dist/lib/browser/types.mjs +16 -4
  33. package/dist/lib/browser/url-handler-MVHTKUYA.mjs +72 -0
  34. package/dist/lib/browser/url-handler-MVHTKUYA.mjs.map +7 -0
  35. package/dist/types/src/DeckPlugin.d.ts.map +1 -1
  36. package/dist/types/src/capabilities/app-graph-builder.d.ts +181 -0
  37. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  38. package/dist/types/src/capabilities/capabilities.d.ts +137 -8
  39. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  40. package/dist/types/src/capabilities/check-app-scheme.d.ts.map +1 -0
  41. package/dist/types/src/capabilities/index.d.ts +188 -3
  42. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  43. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
  44. package/dist/types/src/capabilities/react-root.d.ts.map +1 -0
  45. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  46. package/dist/types/src/capabilities/settings.d.ts.map +1 -0
  47. package/dist/types/src/capabilities/state.d.ts +79 -0
  48. package/dist/types/src/capabilities/state.d.ts.map +1 -0
  49. package/dist/types/src/capabilities/tools.d.ts +10 -0
  50. package/dist/types/src/capabilities/tools.d.ts.map +1 -0
  51. package/dist/types/src/capabilities/url-handler.d.ts.map +1 -0
  52. package/dist/types/src/components/DeckLayout/ActiveNode.d.ts +1 -2
  53. package/dist/types/src/components/DeckLayout/ActiveNode.d.ts.map +1 -1
  54. package/dist/types/src/components/DeckLayout/Banner.d.ts +1 -2
  55. package/dist/types/src/components/DeckLayout/Banner.d.ts.map +1 -1
  56. package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts +1 -4
  57. package/dist/types/src/components/DeckLayout/ComplementarySidebar.d.ts.map +1 -1
  58. package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts +1 -2
  59. package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts.map +1 -1
  60. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts +2 -7
  61. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
  62. package/dist/types/src/components/DeckLayout/Fallback.d.ts +1 -2
  63. package/dist/types/src/components/DeckLayout/Fallback.d.ts.map +1 -1
  64. package/dist/types/src/components/DeckLayout/Fullscreen.d.ts +1 -2
  65. package/dist/types/src/components/DeckLayout/Fullscreen.d.ts.map +1 -1
  66. package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts +3 -3
  67. package/dist/types/src/components/DeckLayout/NodePlankHeading.d.ts.map +1 -1
  68. package/dist/types/src/components/DeckLayout/Plank.d.ts +8 -6
  69. package/dist/types/src/components/DeckLayout/Plank.d.ts.map +1 -1
  70. package/dist/types/src/components/DeckLayout/PlankControls.d.ts +2 -2
  71. package/dist/types/src/components/DeckLayout/PlankControls.d.ts.map +1 -1
  72. package/dist/types/src/components/DeckLayout/PlankError.d.ts +6 -6
  73. package/dist/types/src/components/DeckLayout/PlankError.d.ts.map +1 -1
  74. package/dist/types/src/components/DeckLayout/PlankLoading.d.ts +1 -2
  75. package/dist/types/src/components/DeckLayout/PlankLoading.d.ts.map +1 -1
  76. package/dist/types/src/components/DeckLayout/Sidebar.d.ts +1 -2
  77. package/dist/types/src/components/DeckLayout/Sidebar.d.ts.map +1 -1
  78. package/dist/types/src/components/DeckLayout/SidebarButton.d.ts +6 -5
  79. package/dist/types/src/components/DeckLayout/SidebarButton.d.ts.map +1 -1
  80. package/dist/types/src/components/DeckLayout/StatusBar.d.ts +1 -2
  81. package/dist/types/src/components/DeckLayout/StatusBar.d.ts.map +1 -1
  82. package/dist/types/src/components/DeckLayout/Toast.d.ts +2 -3
  83. package/dist/types/src/components/DeckLayout/Toast.d.ts.map +1 -1
  84. package/dist/types/src/components/DeckLayout/Topbar.d.ts +1 -2
  85. package/dist/types/src/components/DeckLayout/Topbar.d.ts.map +1 -1
  86. package/dist/types/src/components/LayoutSettings.d.ts +1 -2
  87. package/dist/types/src/components/LayoutSettings.d.ts.map +1 -1
  88. package/dist/types/src/components/fragments.d.ts +2 -0
  89. package/dist/types/src/components/fragments.d.ts.map +1 -1
  90. package/dist/types/src/components/index.d.ts +0 -2
  91. package/dist/types/src/components/index.d.ts.map +1 -1
  92. package/dist/types/src/events.d.ts +1 -0
  93. package/dist/types/src/events.d.ts.map +1 -1
  94. package/dist/types/src/hooks/useMainSize.d.ts +2 -2
  95. package/dist/types/src/hooks/useNode.d.ts.map +1 -1
  96. package/dist/types/src/layout.d.ts +5 -19
  97. package/dist/types/src/layout.d.ts.map +1 -1
  98. package/dist/types/src/meta.d.ts +1 -0
  99. package/dist/types/src/meta.d.ts.map +1 -1
  100. package/dist/types/src/translations.d.ts +3 -3
  101. package/dist/types/src/types.d.ts +117 -2
  102. package/dist/types/src/types.d.ts.map +1 -1
  103. package/dist/types/src/util/index.d.ts +3 -1
  104. package/dist/types/src/util/index.d.ts.map +1 -1
  105. package/dist/types/src/util/layoutAppliesTopbar.d.ts +2 -0
  106. package/dist/types/src/util/layoutAppliesTopbar.d.ts.map +1 -0
  107. package/dist/types/src/util/set-active.d.ts +9 -0
  108. package/dist/types/src/util/set-active.d.ts.map +1 -0
  109. package/dist/types/src/util/useHoistStatusbar.d.ts.map +1 -1
  110. package/package.json +32 -31
  111. package/src/DeckPlugin.ts +23 -59
  112. package/src/capabilities/{layout/app-graph-builder.ts → app-graph-builder.ts} +40 -28
  113. package/src/capabilities/capabilities.ts +5 -7
  114. package/src/capabilities/{navigation/check-app-scheme.ts → check-app-scheme.ts} +2 -2
  115. package/src/capabilities/index.ts +12 -3
  116. package/src/capabilities/intent-resolver.ts +368 -0
  117. package/src/capabilities/{layout/react-root.tsx → react-root.tsx} +8 -14
  118. package/src/capabilities/react-surface.tsx +31 -0
  119. package/src/capabilities/{settings/settings.ts → settings.ts} +4 -5
  120. package/src/capabilities/state.ts +108 -0
  121. package/src/capabilities/tools.ts +66 -0
  122. package/src/capabilities/url-handler.ts +65 -0
  123. package/src/components/DeckLayout/ActiveNode.tsx +2 -3
  124. package/src/components/DeckLayout/ComplementarySidebar.tsx +185 -77
  125. package/src/components/DeckLayout/ContentEmpty.tsx +7 -10
  126. package/src/components/DeckLayout/DeckLayout.tsx +141 -84
  127. package/src/components/DeckLayout/Fullscreen.tsx +2 -3
  128. package/src/components/DeckLayout/NodePlankHeading.tsx +57 -65
  129. package/src/components/DeckLayout/Plank.tsx +33 -41
  130. package/src/components/DeckLayout/PlankControls.tsx +12 -11
  131. package/src/components/DeckLayout/PlankError.tsx +6 -5
  132. package/src/components/DeckLayout/Sidebar.tsx +17 -20
  133. package/src/components/DeckLayout/SidebarButton.tsx +25 -31
  134. package/src/components/DeckLayout/StatusBar.tsx +5 -11
  135. package/src/components/DeckLayout/Toast.tsx +2 -2
  136. package/src/components/LayoutSettings.tsx +8 -8
  137. package/src/components/fragments.ts +8 -0
  138. package/src/components/index.ts +0 -2
  139. package/src/events.ts +1 -0
  140. package/src/hooks/useMainSize.ts +3 -3
  141. package/src/hooks/useNode.ts +3 -1
  142. package/src/layout.ts +43 -212
  143. package/src/meta.ts +1 -0
  144. package/src/translations.ts +8 -8
  145. package/src/types.ts +103 -4
  146. package/src/util/index.ts +3 -1
  147. package/src/util/layoutAppliesTopbar.ts +7 -0
  148. package/src/util/set-active.ts +47 -0
  149. package/src/util/useHoistStatusbar.ts +13 -8
  150. package/dist/lib/browser/app-graph-builder-67VRUD5K.mjs.map +0 -7
  151. package/dist/lib/browser/chunk-2M4PXYNB.mjs +0 -1052
  152. package/dist/lib/browser/chunk-2M4PXYNB.mjs.map +0 -7
  153. package/dist/lib/browser/chunk-2PJNBVCY.mjs +0 -39
  154. package/dist/lib/browser/chunk-2PJNBVCY.mjs.map +0 -7
  155. package/dist/lib/browser/chunk-4C2AFTET.mjs +0 -186
  156. package/dist/lib/browser/chunk-4C2AFTET.mjs.map +0 -7
  157. package/dist/lib/browser/chunk-5VFDMW5M.mjs.map +0 -7
  158. package/dist/lib/browser/chunk-KY5WXIXY.mjs +0 -44
  159. package/dist/lib/browser/chunk-KY5WXIXY.mjs.map +0 -7
  160. package/dist/lib/browser/deck-PLCSKPGL.mjs +0 -26
  161. package/dist/lib/browser/deck-PLCSKPGL.mjs.map +0 -7
  162. package/dist/lib/browser/intent-resolver-FVOQSTBX.mjs +0 -152
  163. package/dist/lib/browser/intent-resolver-FVOQSTBX.mjs.map +0 -7
  164. package/dist/lib/browser/intent-resolver-K7GW4A2I.mjs +0 -249
  165. package/dist/lib/browser/intent-resolver-K7GW4A2I.mjs.map +0 -7
  166. package/dist/lib/browser/location-QHRBQBQN.mjs +0 -35
  167. package/dist/lib/browser/location-QHRBQBQN.mjs.map +0 -7
  168. package/dist/lib/browser/react-context-3BDW7W2N.mjs +0 -32
  169. package/dist/lib/browser/react-context-3BDW7W2N.mjs.map +0 -7
  170. package/dist/lib/browser/react-root-UL7ZDRVZ.mjs.map +0 -7
  171. package/dist/lib/browser/react-surface-VPNOGGNN.mjs +0 -28
  172. package/dist/lib/browser/react-surface-VPNOGGNN.mjs.map +0 -7
  173. package/dist/lib/browser/settings-FNWW6WIJ.mjs.map +0 -7
  174. package/dist/lib/browser/state-7I5BD7SE.mjs +0 -34
  175. package/dist/lib/browser/state-7I5BD7SE.mjs.map +0 -7
  176. package/dist/lib/browser/url-handler-Z5B7LD3N.mjs +0 -76
  177. package/dist/lib/browser/url-handler-Z5B7LD3N.mjs.map +0 -7
  178. package/dist/types/src/capabilities/layout/app-graph-builder.d.ts +0 -181
  179. package/dist/types/src/capabilities/layout/app-graph-builder.d.ts.map +0 -1
  180. package/dist/types/src/capabilities/layout/deck.d.ts +0 -4
  181. package/dist/types/src/capabilities/layout/deck.d.ts.map +0 -1
  182. package/dist/types/src/capabilities/layout/index.d.ts +0 -229
  183. package/dist/types/src/capabilities/layout/index.d.ts.map +0 -1
  184. package/dist/types/src/capabilities/layout/intent-resolver.d.ts.map +0 -1
  185. package/dist/types/src/capabilities/layout/react-context.d.ts +0 -8
  186. package/dist/types/src/capabilities/layout/react-context.d.ts.map +0 -1
  187. package/dist/types/src/capabilities/layout/react-root.d.ts.map +0 -1
  188. package/dist/types/src/capabilities/layout/state.d.ts +0 -42
  189. package/dist/types/src/capabilities/layout/state.d.ts.map +0 -1
  190. package/dist/types/src/capabilities/navigation/check-app-scheme.d.ts.map +0 -1
  191. package/dist/types/src/capabilities/navigation/index.d.ts +0 -5
  192. package/dist/types/src/capabilities/navigation/index.d.ts.map +0 -1
  193. package/dist/types/src/capabilities/navigation/intent-resolver.d.ts +0 -4
  194. package/dist/types/src/capabilities/navigation/intent-resolver.d.ts.map +0 -1
  195. package/dist/types/src/capabilities/navigation/location.d.ts +0 -4
  196. package/dist/types/src/capabilities/navigation/location.d.ts.map +0 -1
  197. package/dist/types/src/capabilities/navigation/set-location.d.ts +0 -10
  198. package/dist/types/src/capabilities/navigation/set-location.d.ts.map +0 -1
  199. package/dist/types/src/capabilities/navigation/url-handler.d.ts.map +0 -1
  200. package/dist/types/src/capabilities/settings/index.d.ts +0 -3
  201. package/dist/types/src/capabilities/settings/index.d.ts.map +0 -1
  202. package/dist/types/src/capabilities/settings/react-surface.d.ts.map +0 -1
  203. package/dist/types/src/capabilities/settings/settings.d.ts.map +0 -1
  204. package/dist/types/src/components/DeckContext.d.ts +0 -11
  205. package/dist/types/src/components/DeckContext.d.ts.map +0 -1
  206. package/dist/types/src/components/LayoutContext.d.ts +0 -5
  207. package/dist/types/src/components/LayoutContext.d.ts.map +0 -1
  208. package/dist/types/src/layout.test.d.ts +0 -2
  209. package/dist/types/src/layout.test.d.ts.map +0 -1
  210. package/dist/types/src/util/layout-parts.d.ts +0 -7
  211. package/dist/types/src/util/layout-parts.d.ts.map +0 -1
  212. package/src/capabilities/layout/deck.ts +0 -25
  213. package/src/capabilities/layout/index.ts +0 -12
  214. package/src/capabilities/layout/intent-resolver.ts +0 -128
  215. package/src/capabilities/layout/react-context.tsx +0 -26
  216. package/src/capabilities/layout/state.ts +0 -32
  217. package/src/capabilities/navigation/index.ts +0 -10
  218. package/src/capabilities/navigation/intent-resolver.ts +0 -216
  219. package/src/capabilities/navigation/location.ts +0 -28
  220. package/src/capabilities/navigation/set-location.ts +0 -38
  221. package/src/capabilities/navigation/url-handler.ts +0 -67
  222. package/src/capabilities/settings/index.ts +0 -8
  223. package/src/capabilities/settings/react-surface.tsx +0 -23
  224. package/src/components/DeckContext.ts +0 -19
  225. package/src/components/LayoutContext.ts +0 -12
  226. package/src/layout.test.ts +0 -380
  227. package/src/util/layout-parts.ts +0 -12
  228. /package/dist/types/src/capabilities/{navigation/check-app-scheme.d.ts → check-app-scheme.d.ts} +0 -0
  229. /package/dist/types/src/capabilities/{layout/intent-resolver.d.ts → intent-resolver.d.ts} +0 -0
  230. /package/dist/types/src/capabilities/{layout/react-root.d.ts → react-root.d.ts} +0 -0
  231. /package/dist/types/src/capabilities/{settings/react-surface.d.ts → react-surface.d.ts} +0 -0
  232. /package/dist/types/src/capabilities/{settings/settings.d.ts → settings.d.ts} +0 -0
  233. /package/dist/types/src/capabilities/{navigation/url-handler.d.ts → url-handler.d.ts} +0 -0
package/src/DeckPlugin.ts CHANGED
@@ -5,21 +5,17 @@
5
5
  import { setAutoFreeze } from 'immer';
6
6
 
7
7
  import { allOf, Capabilities, contributes, defineModule, definePlugin, Events, oneOf } from '@dxos/app-framework';
8
- import { AttentionEvents } from '@dxos/plugin-attention';
9
8
  import { translations as stackTranslations } from '@dxos/react-ui-stack';
10
9
 
11
10
  import {
12
11
  AppGraphBuilder,
13
12
  CheckAppScheme,
13
+ DeckSettings,
14
14
  DeckState,
15
15
  LayoutIntentResolver,
16
- LayoutState,
17
- LocationState,
18
- NavigationIntentResolver,
19
- ReactContext,
20
16
  ReactRoot,
21
- DeckSettings,
22
17
  ReactSurface,
18
+ Tools,
23
19
  UrlHandler,
24
20
  } from './capabilities';
25
21
  import { DeckEvents } from './events';
@@ -33,35 +29,23 @@ setAutoFreeze(false);
33
29
 
34
30
  export const DeckPlugin = () =>
35
31
  definePlugin(meta, [
36
- //
37
- // Settings
38
- //
39
-
32
+ defineModule({
33
+ id: `${meta.id}/module/check-app-scheme`,
34
+ activatesOn: Events.SettingsReady,
35
+ activate: CheckAppScheme,
36
+ }),
40
37
  defineModule({
41
38
  id: `${meta.id}/module/settings`,
42
39
  activatesOn: Events.SetupSettings,
43
40
  activate: DeckSettings,
44
41
  }),
45
- defineModule({
46
- id: `${meta.id}/module/react-surface`,
47
- activatesOn: Events.Startup,
48
- activate: ReactSurface,
49
- }),
50
-
51
- //
52
- // Layout
53
- //
54
-
55
42
  defineModule({
56
43
  id: `${meta.id}/module/layout`,
57
- activatesOn: oneOf(Events.Startup, Events.SetupAppGraph),
58
- activatesAfter: [Events.LayoutReady],
59
- activate: LayoutState,
60
- }),
61
- defineModule({
62
- id: `${meta.id}/module/deck`,
63
- activatesOn: oneOf(Events.Startup, Events.SetupAppGraph),
64
- activatesAfter: [DeckEvents.StateReady],
44
+ // TODO(wittjosiah): Does not integrate with settings store.
45
+ // Should this be a different event?
46
+ // Should settings store be renamed to be more generic?
47
+ activatesOn: oneOf(Events.SetupSettings, Events.SetupAppGraph),
48
+ activatesAfter: [Events.LayoutReady, DeckEvents.StateReady],
65
49
  activate: DeckState,
66
50
  }),
67
51
  defineModule({
@@ -69,19 +53,20 @@ export const DeckPlugin = () =>
69
53
  activatesOn: Events.SetupTranslations,
70
54
  activate: () => contributes(Capabilities.Translations, [...translations, ...stackTranslations]),
71
55
  }),
72
- defineModule({
73
- id: `${meta.id}/module/react-context`,
74
- activatesOn: Events.Startup,
75
- activate: ReactContext,
76
- }),
77
56
  defineModule({
78
57
  id: `${meta.id}/module/react-root`,
79
58
  activatesOn: Events.Startup,
59
+ activatesBefore: [DeckEvents.SetupComplementaryPanels],
80
60
  activate: ReactRoot,
81
61
  }),
62
+ defineModule({
63
+ id: `${meta.id}/module/react-surface`,
64
+ activatesOn: Events.SetupReactSurface,
65
+ activate: ReactSurface,
66
+ }),
82
67
  defineModule({
83
68
  id: `${meta.id}/module/layout-intent-resolver`,
84
- activatesOn: Events.SetupIntents,
69
+ activatesOn: Events.SetupIntentResolver,
85
70
  activate: LayoutIntentResolver,
86
71
  }),
87
72
  defineModule({
@@ -89,35 +74,14 @@ export const DeckPlugin = () =>
89
74
  activatesOn: Events.SetupAppGraph,
90
75
  activate: AppGraphBuilder,
91
76
  }),
92
-
93
- //
94
- // Navigation
95
- //
96
-
97
- defineModule({
98
- id: `${meta.id}/module/location`,
99
- activatesOn: oneOf(Events.Startup, Events.SetupAppGraph),
100
- activatesAfter: [Events.LocationReady],
101
- activate: LocationState,
102
- }),
103
77
  defineModule({
104
- id: `${meta.id}/module/check-app-scheme`,
105
- activatesOn: Events.SettingsReady,
106
- activate: CheckAppScheme,
78
+ id: `${meta.id}/module/tools`,
79
+ activatesOn: Events.SetupArtifactDefinition,
80
+ activate: Tools,
107
81
  }),
108
82
  defineModule({
109
83
  id: `${meta.id}/module/url`,
110
- activatesOn: allOf(
111
- Events.DispatcherReady,
112
- Events.LayoutReady,
113
- Events.LocationReady,
114
- AttentionEvents.AttentionReady,
115
- ),
84
+ activatesOn: allOf(Events.DispatcherReady, DeckEvents.StateReady),
116
85
  activate: UrlHandler,
117
86
  }),
118
- defineModule({
119
- id: `${meta.id}/module/navigation-intent-resolver`,
120
- activatesOn: Events.SetupIntents,
121
- activate: NavigationIntentResolver,
122
- }),
123
87
  ]);
@@ -2,19 +2,12 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import {
6
- Capabilities,
7
- contributes,
8
- createIntent,
9
- LayoutAction,
10
- NavigationAction,
11
- openIds,
12
- type PluginsContext,
13
- } from '@dxos/app-framework';
5
+ import { Capabilities, contributes, createIntent, LayoutAction, type PluginsContext } from '@dxos/app-framework';
14
6
  import { AttentionCapabilities } from '@dxos/plugin-attention';
15
7
  import { createExtension, type Node, ROOT_ID } from '@dxos/plugin-graph';
16
8
 
17
- import { DECK_PLUGIN } from '../../meta';
9
+ import { DeckCapabilities } from './capabilities';
10
+ import { DECK_PLUGIN } from '../meta';
18
11
 
19
12
  export default (context: PluginsContext) =>
20
13
  contributes(
@@ -23,13 +16,15 @@ export default (context: PluginsContext) =>
23
16
  id: DECK_PLUGIN,
24
17
  filter: (node): node is Node<null> => node.id === ROOT_ID,
25
18
  actions: () => {
19
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
20
+
26
21
  // NOTE(Zan): This is currently disabled.
27
22
  // TODO(Zan): Fullscreen needs to know the active node and provide that to the layout part.
28
23
  const _fullscreen = {
29
- id: `${LayoutAction.SetLayoutMode._tag}/fullscreen`,
24
+ id: `${LayoutAction.UpdateLayout._tag}/fullscreen`,
30
25
  data: async () => {
31
26
  const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
32
- await dispatch(createIntent(LayoutAction.SetLayoutMode, { layoutMode: 'fullscreen' }));
27
+ await dispatch(createIntent(LayoutAction.SetLayoutMode, { part: 'mode', options: { mode: 'fullscreen' } }));
33
28
  },
34
29
  properties: {
35
30
  label: ['toggle fullscreen label', { ns: DECK_PLUGIN }],
@@ -42,13 +37,15 @@ export default (context: PluginsContext) =>
42
37
  };
43
38
 
44
39
  const closeCurrent = {
45
- id: `${NavigationAction.Close._tag}/current`,
40
+ id: `${LayoutAction.Close._tag}/current`,
46
41
  data: async () => {
47
42
  const attention = context.requestCapability(AttentionCapabilities.Attention);
48
43
  const attended = attention.current.at(-1);
49
44
  if (attended) {
50
45
  const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
51
- await dispatch(createIntent(NavigationAction.Close, { activeParts: { main: [attended] } }));
46
+ await dispatch(
47
+ createIntent(LayoutAction.Close, { part: 'main', subject: [attended], options: { state: false } }),
48
+ );
52
49
  }
53
50
  },
54
51
  properties: {
@@ -58,18 +55,13 @@ export default (context: PluginsContext) =>
58
55
  };
59
56
 
60
57
  const closeOthers = {
61
- id: `${NavigationAction.Close._tag}/others`,
58
+ id: `${LayoutAction.Close._tag}/others`,
62
59
  data: async () => {
63
60
  const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
64
- const location = context.requestCapability(Capabilities.Location);
65
61
  const attention = context.requestCapability(AttentionCapabilities.Attention);
66
62
  const attended = attention.current.at(-1);
67
- const ids = openIds(location.active, ['main']).filter((id) => id !== attended);
68
- await dispatch(
69
- createIntent(NavigationAction.Close, {
70
- activeParts: { main: ids },
71
- }),
72
- );
63
+ const ids = state.deck.active.filter((id) => id !== attended) ?? [];
64
+ await dispatch(createIntent(LayoutAction.Close, { part: 'main', subject: ids, options: { state: false } }));
73
65
  },
74
66
  properties: {
75
67
  label: ['close others label', { ns: DECK_PLUGIN }],
@@ -78,13 +70,14 @@ export default (context: PluginsContext) =>
78
70
  };
79
71
 
80
72
  const closeAll = {
81
- id: `${NavigationAction.Close._tag}/all`,
73
+ id: `${LayoutAction.Close._tag}/all`,
82
74
  data: async () => {
83
75
  const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
84
- const location = context.requestCapability(Capabilities.Location);
85
76
  await dispatch(
86
- createIntent(NavigationAction.Close, {
87
- activeParts: { main: openIds(location.active, ['main']) },
77
+ createIntent(LayoutAction.Close, {
78
+ part: 'main',
79
+ subject: state.deck.active,
80
+ options: { state: false },
88
81
  }),
89
82
  );
90
83
  },
@@ -94,8 +87,27 @@ export default (context: PluginsContext) =>
94
87
  },
95
88
  };
96
89
 
97
- const layoutMode = context.requestCapabilities(Capabilities.Layout)[0]?.layoutMode;
98
- return layoutMode === 'deck' ? [closeCurrent, closeOthers, closeAll] : [];
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
+ };
109
+
110
+ return !state.deck.solo ? [closeCurrent, closeOthers, closeAll, toggleSidebar] : [toggleSidebar];
99
111
  },
100
112
  }),
101
113
  );
@@ -2,16 +2,14 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { defineCapability, type Label } from '@dxos/app-framework';
5
+ import { defineCapability } from '@dxos/app-framework';
6
6
  import { type DeepReadonly } from '@dxos/util';
7
7
 
8
- import { type DeckContextType } from '../components';
9
8
  import { DECK_PLUGIN } from '../meta';
9
+ import { type DeckState, type Panel } from '../types';
10
10
 
11
11
  export namespace DeckCapabilities {
12
- export const DeckState = defineCapability<DeepReadonly<DeckContextType>>(`${DECK_PLUGIN}/capability/state`);
13
- export const MutableDeckState = defineCapability<DeckContextType>(`${DECK_PLUGIN}/capability/state`);
14
- export const ComplementaryPanel = defineCapability<{ id: string; label: Label; icon: string }>(
15
- `${DECK_PLUGIN}/capability/complementary-panel`,
16
- );
12
+ export const DeckState = defineCapability<DeepReadonly<DeckState>>(`${DECK_PLUGIN}/capability/state`);
13
+ export const MutableDeckState = defineCapability<DeckState>(`${DECK_PLUGIN}/capability/state`);
14
+ export const ComplementaryPanel = defineCapability<Panel>(`${DECK_PLUGIN}/capability/complementary-panel`);
17
15
  }
@@ -7,8 +7,8 @@
7
7
 
8
8
  import { Capabilities, contributes, type PluginsContext } from '@dxos/app-framework';
9
9
 
10
- import { DECK_PLUGIN } from '../../meta';
11
- import { type DeckSettingsProps } from '../../types';
10
+ import { DECK_PLUGIN } from '../meta';
11
+ import { type DeckSettingsProps } from '../types';
12
12
 
13
13
  const isSocket = !!(globalThis as any).__args;
14
14
 
@@ -2,7 +2,16 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
+ import { lazy } from '@dxos/app-framework';
6
+
7
+ export const AppGraphBuilder = lazy(() => import('./app-graph-builder'));
8
+ export const CheckAppScheme = lazy(() => import('./check-app-scheme'));
9
+ export const LayoutIntentResolver = lazy(() => import('./intent-resolver'));
10
+ export const ReactRoot = lazy(() => import('./react-root'));
11
+ export const ReactSurface = lazy(() => import('./react-surface'));
12
+ export const DeckSettings = lazy(() => import('./settings'));
13
+ export const DeckState = lazy(() => import('./state'));
14
+ export const Tools = lazy(() => import('./tools'));
15
+ export const UrlHandler = lazy(() => import('./url-handler'));
16
+
5
17
  export * from './capabilities';
6
- export * from './layout';
7
- export * from './navigation';
8
- export * from './settings';
@@ -0,0 +1,368 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { batch } from '@preact/signals-core';
6
+ import { pipe } from 'effect';
7
+
8
+ import {
9
+ Capabilities,
10
+ createResolver,
11
+ contributes,
12
+ IntentAction,
13
+ LayoutAction,
14
+ type PluginsContext,
15
+ createIntent,
16
+ chain,
17
+ } from '@dxos/app-framework';
18
+ import { getTypename, S } from '@dxos/echo-schema';
19
+ import { isReactiveObject } from '@dxos/live-object';
20
+ import { log } from '@dxos/log';
21
+ import { AttentionCapabilities } from '@dxos/plugin-attention';
22
+ import { ObservabilityAction } from '@dxos/plugin-observability/types';
23
+ import { isNonNullable } from '@dxos/util';
24
+
25
+ import { DeckCapabilities } from './capabilities';
26
+ import { closeEntry, incrementPlank, openEntry } from '../layout';
27
+ import { DECK_PLUGIN } from '../meta';
28
+ import { DeckAction, type LayoutMode, type DeckSettingsProps, isLayoutMode, getMode } from '../types';
29
+ import { setActive } from '../util';
30
+
31
+ export default (context: PluginsContext) =>
32
+ contributes(Capabilities.IntentResolver, [
33
+ createResolver({
34
+ intent: IntentAction.ShowUndo,
35
+ resolve: (data) => {
36
+ const layout = context.requestCapability(DeckCapabilities.MutableDeckState);
37
+ const { undoPromise: undo } = context.requestCapability(Capabilities.IntentDispatcher);
38
+
39
+ // TODO(wittjosiah): Support undoing further back than the last action.
40
+ if (layout.currentUndoId) {
41
+ layout.toasts = layout.toasts.filter((toast) => toast.id !== layout.currentUndoId);
42
+ }
43
+ layout.currentUndoId = `${IntentAction.ShowUndo._tag}-${Date.now()}`;
44
+ layout.toasts = [
45
+ ...layout.toasts,
46
+ {
47
+ id: layout.currentUndoId,
48
+ title: data.message ?? ['undo available label', { ns: DECK_PLUGIN }],
49
+ duration: 10_000,
50
+ actionLabel: ['undo action label', { ns: DECK_PLUGIN }],
51
+ actionAlt: ['undo action alt', { ns: DECK_PLUGIN }],
52
+ closeLabel: ['undo close label', { ns: DECK_PLUGIN }],
53
+ onAction: () => undo(),
54
+ },
55
+ ];
56
+ },
57
+ }),
58
+ createResolver({
59
+ intent: LayoutAction.UpdateLayout,
60
+ // TODO(wittjosiah): This should be able to just be `S.is(LayoutAction.UpdateSidebar.fields.input)`
61
+ // but the filter is not being applied correctly.
62
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.UpdateSidebar.fields.input> =>
63
+ S.is(LayoutAction.UpdateSidebar.fields.input)(data),
64
+ resolve: ({ options }) => {
65
+ const layout = context.requestCapability(DeckCapabilities.MutableDeckState);
66
+ const next = options?.state ?? layout.sidebarState;
67
+ if (next !== layout.sidebarState) {
68
+ layout.sidebarState = next;
69
+ }
70
+ },
71
+ }),
72
+ createResolver({
73
+ intent: LayoutAction.UpdateLayout,
74
+ // TODO(wittjosiah): This should be able to just be `S.is(LayoutAction.UpdateComplementary.fields.input)`
75
+ // but the filter is not being applied correctly.
76
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.UpdateComplementary.fields.input> =>
77
+ S.is(LayoutAction.UpdateComplementary.fields.input)(data),
78
+ resolve: ({ subject, options }) => {
79
+ const layout = context.requestCapability(DeckCapabilities.MutableDeckState);
80
+
81
+ if (layout.complementarySidebarPanel !== subject) {
82
+ layout.complementarySidebarPanel = subject;
83
+ }
84
+
85
+ const next = subject ? 'expanded' : options?.state ?? layout.complementarySidebarState;
86
+ if (next !== layout.complementarySidebarState) {
87
+ layout.complementarySidebarState = next;
88
+ }
89
+ },
90
+ }),
91
+ createResolver({
92
+ intent: LayoutAction.UpdateLayout,
93
+ // TODO(wittjosiah): This should be able to just be `S.is(LayoutAction.UpdateDialog.fields.input)`
94
+ // but the filter is not being applied correctly.
95
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.UpdateDialog.fields.input> =>
96
+ S.is(LayoutAction.UpdateDialog.fields.input)(data),
97
+ resolve: ({ subject, options }) => {
98
+ const layout = context.requestCapability(DeckCapabilities.MutableDeckState);
99
+ layout.dialogOpen = options.state ?? Boolean(subject);
100
+ layout.dialogContent = subject ? { component: subject, props: options.props } : null;
101
+ layout.dialogBlockAlign = options.blockAlign ?? 'center';
102
+ layout.dialogType = options.type ?? 'default';
103
+ },
104
+ }),
105
+ createResolver({
106
+ intent: LayoutAction.UpdateLayout,
107
+ // TODO(wittjosiah): This should be able to just be `S.is(LayoutAction.UpdatePopover.fields.input)`
108
+ // but the filter is not being applied correctly.
109
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.UpdatePopover.fields.input> =>
110
+ S.is(LayoutAction.UpdatePopover.fields.input)(data),
111
+ resolve: ({ subject, options }) => {
112
+ const layout = context.requestCapability(DeckCapabilities.MutableDeckState);
113
+ layout.popoverOpen = options.state ?? Boolean(subject);
114
+ layout.popoverContent = subject ? { component: subject, props: options.props } : null;
115
+ layout.popoverAnchorId = options.anchorId;
116
+ layout.popoverSide = options.side;
117
+ },
118
+ }),
119
+ createResolver({
120
+ intent: LayoutAction.UpdateLayout,
121
+ // TODO(wittjosiah): This should be able to just be `S.is(LayoutAction.AddToast.fields.input)`
122
+ // but the filter is not being applied correctly.
123
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.AddToast.fields.input> =>
124
+ S.is(LayoutAction.AddToast.fields.input)(data),
125
+ resolve: ({ subject }) => {
126
+ const layout = context.requestCapability(DeckCapabilities.MutableDeckState);
127
+ layout.toasts.push(subject);
128
+ },
129
+ }),
130
+ createResolver({
131
+ intent: LayoutAction.UpdateLayout,
132
+ // TODO(wittjosiah): This should be able to just be `S.is(LayoutAction.SetLayoutMode.fields.input)`
133
+ // but the filter is not being applied correctly.
134
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.SetLayoutMode.fields.input> => {
135
+ if (!S.is(LayoutAction.SetLayoutMode.fields.input)(data)) {
136
+ return false;
137
+ }
138
+
139
+ if ('mode' in data.options) {
140
+ return isLayoutMode(data.options.mode);
141
+ }
142
+
143
+ return true;
144
+ },
145
+ resolve: ({ subject, options }) => {
146
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
147
+
148
+ const setMode = (mode: LayoutMode) => {
149
+ const deck = state.deck;
150
+ const current = deck.solo ? [deck.solo] : deck.active;
151
+ // When un-soloing, the solo entry is added to the deck.
152
+ const next = (
153
+ mode !== 'deck' ? [subject ?? deck.solo ?? deck.active[0]] : [...deck.active, deck.solo]
154
+ ).filter(isNonNullable);
155
+
156
+ const removed = current.filter((id) => !next.includes(id));
157
+ const closed = Array.from(new Set([...deck.inactive.filter((id) => !next.includes(id)), ...removed]));
158
+ deck.inactive = closed;
159
+
160
+ if (mode !== 'deck' && next[0]) {
161
+ deck.solo = next[0];
162
+ } else if (mode === 'deck' && deck.solo) {
163
+ deck.solo = undefined;
164
+ deck.initialized = true;
165
+ }
166
+
167
+ if (mode === 'fullscreen' && !deck.fullscreen) {
168
+ deck.fullscreen = true;
169
+ } else if (mode !== 'fullscreen' && deck.fullscreen) {
170
+ deck.fullscreen = false;
171
+ }
172
+ };
173
+
174
+ return batch(() => {
175
+ if ('mode' in options) {
176
+ const current = getMode(state.deck);
177
+ if (current !== options.mode) {
178
+ state.previousMode[state.activeDeck] = current;
179
+ }
180
+ setMode(options.mode as LayoutMode);
181
+ } else if ('revert' in options) {
182
+ const last = state.previousMode[state.activeDeck];
183
+ setMode(last ?? 'solo');
184
+ } else {
185
+ log.warn('Invalid layout mode', options);
186
+ }
187
+ });
188
+ },
189
+ }),
190
+ createResolver({
191
+ intent: LayoutAction.UpdateLayout,
192
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.SwitchWorkspace.fields.input> =>
193
+ S.is(LayoutAction.SwitchWorkspace.fields.input)(data),
194
+ resolve: ({ subject }) => {
195
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
196
+ batch(() => {
197
+ // TODO(wittjosiah): This is a hack to prevent the previous deck from being set for pinned items.
198
+ // Ideally this should be worked into the data model in a generic way.
199
+ if (!state.activeDeck.startsWith('!')) {
200
+ state.previousDeck = state.activeDeck;
201
+ }
202
+ state.activeDeck = subject;
203
+ if (!state.decks[subject]) {
204
+ state.decks[subject] = { initialized: false, active: [], inactive: [], fullscreen: false, plankSizing: {} };
205
+ }
206
+ });
207
+
208
+ const first = state.deck.solo ? state.deck.solo : state.deck.active[0];
209
+ if (first) {
210
+ return {
211
+ intents: [createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: first })],
212
+ };
213
+ }
214
+ },
215
+ }),
216
+ createResolver({
217
+ intent: LayoutAction.UpdateLayout,
218
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.RevertWorkspace.fields.input> =>
219
+ S.is(LayoutAction.RevertWorkspace.fields.input)(data),
220
+ resolve: () => {
221
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
222
+ return {
223
+ intents: [createIntent(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: state.previousDeck })],
224
+ };
225
+ },
226
+ }),
227
+ createResolver({
228
+ intent: LayoutAction.UpdateLayout,
229
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.Open.fields.input> =>
230
+ S.is(LayoutAction.Open.fields.input)(data),
231
+ resolve: ({ subject, options }) => {
232
+ const { graph } = context.requestCapability(Capabilities.AppGraph);
233
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
234
+ const attention = context.requestCapability(AttentionCapabilities.Attention);
235
+ const settings = context
236
+ .requestCapabilities(Capabilities.SettingsStore)[0]
237
+ ?.getStore<DeckSettingsProps>(DECK_PLUGIN)?.value;
238
+
239
+ const previouslyOpenIds = new Set<string>(state.deck.solo ? [state.deck.solo] : state.deck.active);
240
+ batch(() => {
241
+ const next = state.deck.solo
242
+ ? (subject as string[])
243
+ : subject.reduce(
244
+ (acc, entryId) =>
245
+ openEntry(acc, entryId, {
246
+ key: options?.key,
247
+ positioning: options?.positioning ?? settings?.newPlankPositioning,
248
+ pivotId: options?.pivotId,
249
+ }),
250
+ state.deck.active,
251
+ );
252
+
253
+ return setActive({ next, state, attention });
254
+ });
255
+
256
+ const ids = state.deck.solo ? [state.deck.solo] : state.deck.active;
257
+ const newlyOpen = ids.filter((i) => !previouslyOpenIds.has(i));
258
+
259
+ return {
260
+ intents: [
261
+ ...(options?.scrollIntoView !== false
262
+ ? [createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: newlyOpen[0] ?? subject[0] })]
263
+ : []),
264
+ createIntent(LayoutAction.Expose, { part: 'navigation', subject: newlyOpen[0] ?? subject[0] }),
265
+ ...newlyOpen.map((id) => {
266
+ const active = graph?.findNode(id)?.data;
267
+ const typename = isReactiveObject(active) ? getTypename(active) : undefined;
268
+ return createIntent(ObservabilityAction.SendEvent, {
269
+ name: 'navigation.activate',
270
+ properties: {
271
+ id,
272
+ typename,
273
+ },
274
+ });
275
+ }),
276
+ ],
277
+ };
278
+ },
279
+ }),
280
+ createResolver({
281
+ intent: LayoutAction.UpdateLayout,
282
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.Close.fields.input> =>
283
+ S.is(LayoutAction.Close.fields.input)(data),
284
+ resolve: ({ subject }) => {
285
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
286
+ const attention = context.requestCapability(AttentionCapabilities.Attention);
287
+ const active = state.deck.solo ? [state.deck.solo] : state.deck.active;
288
+ const next = subject.reduce((acc, id) => closeEntry(acc, id), active);
289
+ const toAttend = setActive({ next, state, attention });
290
+ return {
291
+ intents: toAttend ? [createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: toAttend })] : [],
292
+ };
293
+ },
294
+ }),
295
+ createResolver({
296
+ intent: LayoutAction.UpdateLayout,
297
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.Set.fields.input> =>
298
+ S.is(LayoutAction.Set.fields.input)(data),
299
+ resolve: ({ subject }) => {
300
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
301
+ const attention = context.requestCapability(AttentionCapabilities.Attention);
302
+ const toAttend = setActive({ next: subject as string[], state, attention });
303
+ return {
304
+ intents: toAttend ? [createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: toAttend })] : [],
305
+ };
306
+ },
307
+ }),
308
+ createResolver({
309
+ intent: LayoutAction.UpdateLayout,
310
+ filter: (data): data is S.Schema.Type<typeof LayoutAction.ScrollIntoView.fields.input> =>
311
+ S.is(LayoutAction.ScrollIntoView.fields.input)(data),
312
+ resolve: ({ subject }) => {
313
+ const layout = context.requestCapability(DeckCapabilities.MutableDeckState);
314
+ layout.scrollIntoView = subject;
315
+ },
316
+ }),
317
+ createResolver({
318
+ intent: DeckAction.UpdatePlankSize,
319
+ resolve: (data) => {
320
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
321
+ state.deck.plankSizing[data.id] = data.size;
322
+ },
323
+ }),
324
+ createResolver({
325
+ intent: DeckAction.Adjust,
326
+ resolve: (adjustment) => {
327
+ const state = context.requestCapability(DeckCapabilities.MutableDeckState);
328
+ const attention = context.requestCapability(AttentionCapabilities.Attention);
329
+
330
+ return batch(() => {
331
+ if (adjustment.type === 'increment-end' || adjustment.type === 'increment-start') {
332
+ setActive({
333
+ next: incrementPlank(state.deck.active, adjustment),
334
+ state,
335
+ attention,
336
+ });
337
+ }
338
+
339
+ if (adjustment.type === 'solo') {
340
+ const entryId = adjustment.id;
341
+ if (!state.deck.solo) {
342
+ // Solo the entry.
343
+ return {
344
+ intents: [
345
+ createIntent(LayoutAction.SetLayoutMode, {
346
+ part: 'mode',
347
+ subject: entryId,
348
+ options: { mode: 'solo' },
349
+ }),
350
+ ],
351
+ };
352
+ } else {
353
+ // Un-solo the current entry.
354
+ return {
355
+ intents: [
356
+ // NOTE: The order of these is important.
357
+ pipe(
358
+ createIntent(LayoutAction.SetLayoutMode, { part: 'mode', options: { mode: 'deck' } }),
359
+ chain(LayoutAction.Open, { part: 'main', subject: [entryId] }),
360
+ ),
361
+ ],
362
+ };
363
+ }
364
+ }
365
+ });
366
+ },
367
+ }),
368
+ ]);