@dxos/plugin-deck 0.8.4-main.7ace549 → 0.8.4-main.937b3ca

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 (267) hide show
  1. package/dist/lib/browser/app-graph-builder-DTVCULQ4.mjs +120 -0
  2. package/dist/lib/browser/app-graph-builder-DTVCULQ4.mjs.map +7 -0
  3. package/dist/lib/browser/{check-app-scheme-HIEVFAAX.mjs → check-app-scheme-JSRXXIYF.mjs} +9 -9
  4. package/dist/lib/browser/check-app-scheme-JSRXXIYF.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-F3VCCHVL.mjs → chunk-ATFPDN6J.mjs} +149 -19
  6. package/dist/lib/browser/chunk-ATFPDN6J.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-EREEXCHO.mjs +1448 -0
  8. package/dist/lib/browser/chunk-EREEXCHO.mjs.map +7 -0
  9. package/dist/lib/browser/{chunk-CNTGBCMK.mjs → chunk-NHABISX2.mjs} +40 -33
  10. package/dist/lib/browser/chunk-NHABISX2.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-UNG4CLLP.mjs +161 -0
  12. package/dist/lib/browser/chunk-UNG4CLLP.mjs.map +7 -0
  13. package/dist/lib/browser/index.mjs +71 -65
  14. package/dist/lib/browser/index.mjs.map +4 -4
  15. package/dist/lib/browser/meta.json +1 -1
  16. package/dist/lib/browser/operation-resolver-CDYBLZJ4.mjs +595 -0
  17. package/dist/lib/browser/operation-resolver-CDYBLZJ4.mjs.map +7 -0
  18. package/dist/lib/browser/react-root-LYNEKGHM.mjs +47 -0
  19. package/dist/lib/browser/react-root-LYNEKGHM.mjs.map +7 -0
  20. package/dist/lib/browser/react-surface-RPKD7XUR.mjs +42 -0
  21. package/dist/lib/browser/react-surface-RPKD7XUR.mjs.map +7 -0
  22. package/dist/lib/browser/settings-OMHVGZ6V.mjs +37 -0
  23. package/dist/lib/browser/settings-OMHVGZ6V.mjs.map +7 -0
  24. package/dist/lib/browser/state-OC3BSB6E.mjs +103 -0
  25. package/dist/lib/browser/state-OC3BSB6E.mjs.map +7 -0
  26. package/dist/lib/browser/{toolkit-L5CFXJCF.mjs → toolkit-R53LD3EA.mjs} +16 -15
  27. package/dist/lib/browser/toolkit-R53LD3EA.mjs.map +7 -0
  28. package/dist/lib/browser/types/index.mjs +11 -4
  29. package/dist/lib/browser/url-handler-53TE6JZO.mjs +93 -0
  30. package/dist/lib/browser/url-handler-53TE6JZO.mjs.map +7 -0
  31. package/dist/lib/node-esm/app-graph-builder-473BNZDJ.mjs +121 -0
  32. package/dist/lib/node-esm/app-graph-builder-473BNZDJ.mjs.map +7 -0
  33. package/dist/lib/node-esm/check-app-scheme-IVYRHKRH.mjs +33 -0
  34. package/dist/lib/node-esm/check-app-scheme-IVYRHKRH.mjs.map +7 -0
  35. package/dist/lib/node-esm/chunk-ADPMWKLL.mjs +154 -0
  36. package/dist/lib/node-esm/chunk-ADPMWKLL.mjs.map +7 -0
  37. package/dist/lib/node-esm/chunk-SKEVPQ7E.mjs +162 -0
  38. package/dist/lib/node-esm/chunk-SKEVPQ7E.mjs.map +7 -0
  39. package/dist/lib/node-esm/chunk-V6VEXRD4.mjs +1449 -0
  40. package/dist/lib/node-esm/chunk-V6VEXRD4.mjs.map +7 -0
  41. package/dist/lib/node-esm/chunk-XAKTY3EB.mjs +294 -0
  42. package/dist/lib/node-esm/chunk-XAKTY3EB.mjs.map +7 -0
  43. package/dist/lib/node-esm/index.mjs +181 -0
  44. package/dist/lib/node-esm/index.mjs.map +7 -0
  45. package/dist/lib/node-esm/meta.json +1 -0
  46. package/dist/lib/node-esm/operation-resolver-WUOE33ID.mjs +596 -0
  47. package/dist/lib/node-esm/operation-resolver-WUOE33ID.mjs.map +7 -0
  48. package/dist/lib/node-esm/react-root-L7H43AS3.mjs +48 -0
  49. package/dist/lib/node-esm/react-root-L7H43AS3.mjs.map +7 -0
  50. package/dist/lib/node-esm/react-surface-77DKVMDV.mjs +43 -0
  51. package/dist/lib/node-esm/react-surface-77DKVMDV.mjs.map +7 -0
  52. package/dist/lib/node-esm/settings-2HB6FKIK.mjs +38 -0
  53. package/dist/lib/node-esm/settings-2HB6FKIK.mjs.map +7 -0
  54. package/dist/lib/node-esm/state-JRQ45ACJ.mjs +104 -0
  55. package/dist/lib/node-esm/state-JRQ45ACJ.mjs.map +7 -0
  56. package/dist/lib/node-esm/toolkit-JLPZNNKB.mjs +54 -0
  57. package/dist/lib/node-esm/toolkit-JLPZNNKB.mjs.map +7 -0
  58. package/dist/lib/node-esm/types/index.mjs +40 -0
  59. package/dist/lib/node-esm/url-handler-QGF2R24T.mjs +94 -0
  60. package/dist/lib/node-esm/url-handler-QGF2R24T.mjs.map +7 -0
  61. package/dist/types/src/DeckPlugin.d.ts +2 -1
  62. package/dist/types/src/DeckPlugin.d.ts.map +1 -1
  63. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts +6 -0
  64. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +1 -0
  65. package/dist/types/src/capabilities/app-graph-builder/index.d.ts +3 -0
  66. package/dist/types/src/capabilities/app-graph-builder/index.d.ts.map +1 -0
  67. package/dist/types/src/capabilities/check-app-scheme/check-app-scheme.d.ts +5 -0
  68. package/dist/types/src/capabilities/check-app-scheme/check-app-scheme.d.ts.map +1 -0
  69. package/dist/types/src/capabilities/check-app-scheme/index.d.ts +3 -0
  70. package/dist/types/src/capabilities/check-app-scheme/index.d.ts.map +1 -0
  71. package/dist/types/src/capabilities/index.d.ts +8 -13
  72. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  73. package/dist/types/src/capabilities/operation-resolver/index.d.ts +3 -0
  74. package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +1 -0
  75. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +5 -0
  76. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +1 -0
  77. package/dist/types/src/capabilities/react-root/index.d.ts +6 -0
  78. package/dist/types/src/capabilities/react-root/index.d.ts.map +1 -0
  79. package/dist/types/src/capabilities/react-root/react-root.d.ts +9 -0
  80. package/dist/types/src/capabilities/react-root/react-root.d.ts.map +1 -0
  81. package/dist/types/src/capabilities/react-surface/index.d.ts +3 -0
  82. package/dist/types/src/capabilities/react-surface/index.d.ts.map +1 -0
  83. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +5 -0
  84. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +1 -0
  85. package/dist/types/src/capabilities/settings/index.d.ts +19 -0
  86. package/dist/types/src/capabilities/settings/index.d.ts.map +1 -0
  87. package/dist/types/src/capabilities/settings/settings.d.ts +21 -0
  88. package/dist/types/src/capabilities/settings/settings.d.ts.map +1 -0
  89. package/dist/types/src/capabilities/state/index.d.ts +172 -0
  90. package/dist/types/src/capabilities/state/index.d.ts.map +1 -0
  91. package/dist/types/src/capabilities/state/state.d.ts +175 -0
  92. package/dist/types/src/capabilities/state/state.d.ts.map +1 -0
  93. package/dist/types/src/capabilities/toolkit/index.d.ts +3 -0
  94. package/dist/types/src/capabilities/toolkit/index.d.ts.map +1 -0
  95. package/dist/types/src/capabilities/{toolkit.d.ts → toolkit/toolkit.d.ts} +5 -4
  96. package/dist/types/src/capabilities/toolkit/toolkit.d.ts.map +1 -0
  97. package/dist/types/src/capabilities/tools/index.d.ts +3 -0
  98. package/dist/types/src/capabilities/tools/index.d.ts.map +1 -0
  99. package/dist/types/src/capabilities/tools/tools.d.ts +12 -0
  100. package/dist/types/src/capabilities/tools/tools.d.ts.map +1 -0
  101. package/dist/types/src/capabilities/url-handler/index.d.ts +3 -0
  102. package/dist/types/src/capabilities/url-handler/index.d.ts.map +1 -0
  103. package/dist/types/src/capabilities/url-handler/url-handler.d.ts +5 -0
  104. package/dist/types/src/capabilities/url-handler/url-handler.d.ts.map +1 -0
  105. package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts.map +1 -1
  106. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
  107. package/dist/types/src/components/DeckLayout/DeckLayout.stories.d.ts.map +1 -1
  108. package/dist/types/src/components/DeckLayout/DeckMain.d.ts.map +1 -1
  109. package/dist/types/src/components/DeckLayout/Dialog.d.ts.map +1 -1
  110. package/dist/types/src/components/DeckLayout/Popover.d.ts.map +1 -1
  111. package/dist/types/src/components/DeckLayout/Toast.d.ts +3 -3
  112. package/dist/types/src/components/DeckLayout/Toast.d.ts.map +1 -1
  113. package/dist/types/src/components/DeckSettings/DeckSettings.d.ts +4 -2
  114. package/dist/types/src/components/DeckSettings/DeckSettings.d.ts.map +1 -1
  115. package/dist/types/src/components/Plank/Plank.d.ts +3 -3
  116. package/dist/types/src/components/Plank/Plank.d.ts.map +1 -1
  117. package/dist/types/src/components/Plank/Plank.stories.d.ts +22 -4
  118. package/dist/types/src/components/Plank/Plank.stories.d.ts.map +1 -1
  119. package/dist/types/src/components/Plank/PlankControls.d.ts +1 -1
  120. package/dist/types/src/components/Plank/PlankControls.d.ts.map +1 -1
  121. package/dist/types/src/components/Plank/PlankError.d.ts +1 -1
  122. package/dist/types/src/components/Plank/PlankError.d.ts.map +1 -1
  123. package/dist/types/src/components/Plank/PlankHeading.d.ts +2 -2
  124. package/dist/types/src/components/Plank/PlankHeading.d.ts.map +1 -1
  125. package/dist/types/src/components/Sidebar/ComplementarySidebar.d.ts.map +1 -1
  126. package/dist/types/src/components/Sidebar/Sidebar.d.ts.map +1 -1
  127. package/dist/types/src/components/Sidebar/SidebarButton.d.ts.map +1 -1
  128. package/dist/types/src/hooks/index.d.ts +1 -0
  129. package/dist/types/src/hooks/index.d.ts.map +1 -1
  130. package/dist/types/src/hooks/useDeckCompanions.d.ts +3 -3
  131. package/dist/types/src/hooks/useDeckCompanions.d.ts.map +1 -1
  132. package/dist/types/src/hooks/useDeckState.d.ts +17 -0
  133. package/dist/types/src/hooks/useDeckState.d.ts.map +1 -0
  134. package/dist/types/src/hooks/useHoistStatusbar.d.ts +1 -1
  135. package/dist/types/src/hooks/useHoistStatusbar.d.ts.map +1 -1
  136. package/dist/types/src/hooks/useNodeActionExpander.d.ts +1 -1
  137. package/dist/types/src/hooks/useNodeActionExpander.d.ts.map +1 -1
  138. package/dist/types/src/index.d.ts +1 -2
  139. package/dist/types/src/index.d.ts.map +1 -1
  140. package/dist/types/src/meta.d.ts +2 -2
  141. package/dist/types/src/meta.d.ts.map +1 -1
  142. package/dist/types/src/{capabilities → types}/capabilities.d.ts +96 -90
  143. package/dist/types/src/types/capabilities.d.ts.map +1 -0
  144. package/dist/types/src/types/events.d.ts +7 -0
  145. package/dist/types/src/types/events.d.ts.map +1 -0
  146. package/dist/types/src/types/index.d.ts +2 -0
  147. package/dist/types/src/types/index.d.ts.map +1 -1
  148. package/dist/types/src/types/schema.d.ts +86 -27
  149. package/dist/types/src/types/schema.d.ts.map +1 -1
  150. package/dist/types/src/util/set-active.d.ts +18 -3
  151. package/dist/types/src/util/set-active.d.ts.map +1 -1
  152. package/dist/types/tsconfig.tsbuildinfo +1 -1
  153. package/package.json +53 -47
  154. package/src/DeckPlugin.ts +27 -48
  155. package/src/capabilities/app-graph-builder/app-graph-builder.ts +118 -0
  156. package/src/capabilities/app-graph-builder/index.ts +7 -0
  157. package/src/capabilities/{check-app-scheme.ts → check-app-scheme/check-app-scheme.ts} +12 -11
  158. package/src/capabilities/check-app-scheme/index.ts +7 -0
  159. package/src/capabilities/index.ts +9 -14
  160. package/src/capabilities/operation-resolver/index.ts +10 -0
  161. package/src/capabilities/operation-resolver/operation-resolver.ts +555 -0
  162. package/src/capabilities/react-root/index.ts +7 -0
  163. package/src/capabilities/react-root/react-root.tsx +47 -0
  164. package/src/capabilities/react-surface/index.ts +7 -0
  165. package/src/capabilities/react-surface/react-surface.tsx +37 -0
  166. package/src/capabilities/settings/index.ts +7 -0
  167. package/src/capabilities/settings/settings.ts +38 -0
  168. package/src/capabilities/state/index.ts +7 -0
  169. package/src/capabilities/state/state.ts +104 -0
  170. package/src/capabilities/toolkit/index.ts +7 -0
  171. package/src/capabilities/{toolkit.ts → toolkit/toolkit.ts} +18 -21
  172. package/src/capabilities/tools/index.ts +7 -0
  173. package/src/capabilities/tools/tools.ts +92 -0
  174. package/src/capabilities/url-handler/index.ts +7 -0
  175. package/src/capabilities/url-handler/url-handler.ts +95 -0
  176. package/src/components/DeckLayout/Banner.tsx +2 -2
  177. package/src/components/DeckLayout/ContentEmpty.tsx +3 -4
  178. package/src/components/DeckLayout/DeckLayout.stories.tsx +16 -28
  179. package/src/components/DeckLayout/DeckLayout.tsx +13 -11
  180. package/src/components/DeckLayout/DeckMain.tsx +41 -36
  181. package/src/components/DeckLayout/Dialog.tsx +13 -10
  182. package/src/components/DeckLayout/Fallback.tsx +1 -1
  183. package/src/components/DeckLayout/Popover.tsx +43 -22
  184. package/src/components/DeckLayout/Toast.tsx +4 -4
  185. package/src/components/DeckSettings/DeckSettings.tsx +18 -8
  186. package/src/components/Plank/Plank.stories.tsx +14 -6
  187. package/src/components/Plank/Plank.tsx +19 -19
  188. package/src/components/Plank/PlankControls.tsx +5 -6
  189. package/src/components/Plank/PlankError.tsx +2 -2
  190. package/src/components/Plank/PlankHeading.tsx +28 -34
  191. package/src/components/Sidebar/ComplementarySidebar.tsx +26 -19
  192. package/src/components/Sidebar/Sidebar.tsx +4 -4
  193. package/src/components/Sidebar/SidebarButton.tsx +30 -24
  194. package/src/components/fragments.ts +1 -1
  195. package/src/hooks/index.ts +1 -0
  196. package/src/hooks/useDeckCompanions.ts +5 -4
  197. package/src/hooks/useDeckState.ts +82 -0
  198. package/src/hooks/useHoistStatusbar.ts +3 -6
  199. package/src/hooks/useNodeActionExpander.ts +4 -4
  200. package/src/index.ts +1 -2
  201. package/src/meta.ts +2 -2
  202. package/src/types/capabilities.ts +33 -0
  203. package/src/types/events.ts +20 -0
  204. package/src/types/index.ts +2 -0
  205. package/src/types/schema.ts +81 -11
  206. package/src/util/layoutAppliesTopbar.ts +1 -1
  207. package/src/util/set-active.ts +49 -29
  208. package/dist/lib/browser/app-graph-builder-D74NTOMK.mjs +0 -128
  209. package/dist/lib/browser/app-graph-builder-D74NTOMK.mjs.map +0 -7
  210. package/dist/lib/browser/check-app-scheme-HIEVFAAX.mjs.map +0 -7
  211. package/dist/lib/browser/chunk-5KMJPIQC.mjs +0 -16
  212. package/dist/lib/browser/chunk-5KMJPIQC.mjs.map +0 -7
  213. package/dist/lib/browser/chunk-CNTGBCMK.mjs.map +0 -7
  214. package/dist/lib/browser/chunk-F3VCCHVL.mjs.map +0 -7
  215. package/dist/lib/browser/chunk-QKCGZ45E.mjs +0 -128
  216. package/dist/lib/browser/chunk-QKCGZ45E.mjs.map +0 -7
  217. package/dist/lib/browser/chunk-UXLU6CMW.mjs +0 -16
  218. package/dist/lib/browser/chunk-UXLU6CMW.mjs.map +0 -7
  219. package/dist/lib/browser/chunk-VBYJ664A.mjs +0 -132
  220. package/dist/lib/browser/chunk-VBYJ664A.mjs.map +0 -7
  221. package/dist/lib/browser/chunk-VUJ6UNIJ.mjs +0 -1553
  222. package/dist/lib/browser/chunk-VUJ6UNIJ.mjs.map +0 -7
  223. package/dist/lib/browser/intent-resolver-UA4YQGAC.mjs +0 -524
  224. package/dist/lib/browser/intent-resolver-UA4YQGAC.mjs.map +0 -7
  225. package/dist/lib/browser/react-root-JAMHKYWN.mjs +0 -44
  226. package/dist/lib/browser/react-root-JAMHKYWN.mjs.map +0 -7
  227. package/dist/lib/browser/react-surface-6LW337ZT.mjs +0 -40
  228. package/dist/lib/browser/react-surface-6LW337ZT.mjs.map +0 -7
  229. package/dist/lib/browser/settings-SDPTOCCM.mjs +0 -30
  230. package/dist/lib/browser/settings-SDPTOCCM.mjs.map +0 -7
  231. package/dist/lib/browser/state-7IFAGZQO.mjs +0 -12
  232. package/dist/lib/browser/toolkit-L5CFXJCF.mjs.map +0 -7
  233. package/dist/lib/browser/url-handler-QEYGYE2H.mjs +0 -70
  234. package/dist/lib/browser/url-handler-QEYGYE2H.mjs.map +0 -7
  235. package/dist/types/src/capabilities/app-graph-builder.d.ts +0 -4
  236. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +0 -1
  237. package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
  238. package/dist/types/src/capabilities/check-app-scheme.d.ts +0 -4
  239. package/dist/types/src/capabilities/check-app-scheme.d.ts.map +0 -1
  240. package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
  241. package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
  242. package/dist/types/src/capabilities/react-root.d.ts +0 -7
  243. package/dist/types/src/capabilities/react-root.d.ts.map +0 -1
  244. package/dist/types/src/capabilities/react-surface.d.ts +0 -4
  245. package/dist/types/src/capabilities/react-surface.d.ts.map +0 -1
  246. package/dist/types/src/capabilities/settings.d.ts +0 -4
  247. package/dist/types/src/capabilities/settings.d.ts.map +0 -1
  248. package/dist/types/src/capabilities/state.d.ts +0 -104
  249. package/dist/types/src/capabilities/state.d.ts.map +0 -1
  250. package/dist/types/src/capabilities/toolkit.d.ts.map +0 -1
  251. package/dist/types/src/capabilities/tools.d.ts +0 -11
  252. package/dist/types/src/capabilities/tools.d.ts.map +0 -1
  253. package/dist/types/src/capabilities/url-handler.d.ts +0 -4
  254. package/dist/types/src/capabilities/url-handler.d.ts.map +0 -1
  255. package/dist/types/src/events.d.ts +0 -4
  256. package/dist/types/src/events.d.ts.map +0 -1
  257. package/src/capabilities/app-graph-builder.ts +0 -143
  258. package/src/capabilities/capabilities.ts +0 -14
  259. package/src/capabilities/intent-resolver.ts +0 -471
  260. package/src/capabilities/react-root.tsx +0 -40
  261. package/src/capabilities/react-surface.tsx +0 -30
  262. package/src/capabilities/settings.ts +0 -27
  263. package/src/capabilities/state.ts +0 -113
  264. package/src/capabilities/tools.ts +0 -84
  265. package/src/capabilities/url-handler.ts +0 -60
  266. package/src/events.ts +0 -11
  267. /package/dist/lib/{browser/state-7IFAGZQO.mjs.map → node-esm/types/index.mjs.map} +0 -0
@@ -2,20 +2,17 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { untracked } from '@preact/signals-core';
6
5
  import React, { Fragment, type UIEvent, useCallback, useEffect, useMemo, useRef } from 'react';
7
6
 
8
- import { Capabilities, LayoutAction, createIntent } from '@dxos/app-framework';
9
- import { useCapability, useIntentDispatcher, usePluginManager } from '@dxos/app-framework/react';
7
+ import { Common } from '@dxos/app-framework';
8
+ import { useAtomCapability, useOperationInvoker, usePluginManager } from '@dxos/app-framework/react';
10
9
  import { AttentionCapabilities } from '@dxos/plugin-attention';
11
10
  import { Main, type MainProps, useMediaQuery, useOnTransition } from '@dxos/react-ui';
12
11
  import { DEFAULT_HORIZONTAL_SIZE, Stack, StackContext } from '@dxos/react-ui-stack';
13
- import { mainPaddingTransitions, mx } from '@dxos/react-ui-theme';
12
+ import { mainPaddingTransitions, mx } from '@dxos/ui-theme';
14
13
 
15
- import { DeckCapabilities } from '../../capabilities';
16
- import { useBreakpoints, useHoistStatusbar } from '../../hooks';
17
- import { meta } from '../../meta';
18
- import { type DeckSettingsProps, getMode } from '../../types';
14
+ import { useBreakpoints, useDeckState, useHoistStatusbar } from '../../hooks';
15
+ import { DeckCapabilities, getMode } from '../../types';
19
16
  import { calculateOverscroll, layoutAppliesTopbar } from '../../util';
20
17
  import { fixedComplementarySidebarToggleStyles, fixedSidebarToggleStyles } from '../fragments';
21
18
  import { Plank } from '../Plank';
@@ -26,10 +23,10 @@ import { StatusBar } from './StatusBar';
26
23
  import { Topbar } from './Topbar';
27
24
 
28
25
  export const DeckMain = () => {
29
- const { dispatchPromise: dispatch } = useIntentDispatcher();
30
- const settings = useCapability(Capabilities.SettingsStore).getStore<DeckSettingsProps>(meta.id)?.value;
31
- const context = useCapability(DeckCapabilities.MutableDeckState);
32
- const { sidebarState, complementarySidebarState, complementarySidebarPanel, deck } = context;
26
+ const { invokeSync } = useOperationInvoker();
27
+ const settings = useAtomCapability(DeckCapabilities.Settings);
28
+ const { state, deck, updateState } = useDeckState();
29
+ const { sidebarState, complementarySidebarState, complementarySidebarPanel } = state;
33
30
  const { active, activeCompanions, fullscreen, solo, plankSizing } = deck;
34
31
  const layoutMode = getMode(deck);
35
32
  const breakpoint = useBreakpoints();
@@ -43,10 +40,8 @@ export const DeckMain = () => {
43
40
  // Ensure the first plank is attended when the deck is first rendered.
44
41
  useEffect(() => {
45
42
  // NOTE: Not `useAttended` so that the layout component is not re-rendered when the attended list changes.
46
- const attended = untracked(() => {
47
- const attention = pluginManager.context.getCapability(AttentionCapabilities.Attention);
48
- return attention.current;
49
- });
43
+ const attention = pluginManager.capabilities.get(AttentionCapabilities.Attention);
44
+ const attended = attention.getCurrent();
50
45
  const firstId = solo ?? active[0];
51
46
  if (attended.length === 0 && firstId) {
52
47
  // TODO(wittjosiah): Focusing the type button is a workaround.
@@ -60,31 +55,26 @@ export const DeckMain = () => {
60
55
  const [isNotMobile] = useMediaQuery('md');
61
56
  const shouldRevert = useRef(false);
62
57
  useEffect(() => {
63
- if (!isNotMobile && getMode(deck) === 'deck') {
58
+ if (!isNotMobile && layoutMode === 'deck') {
64
59
  // NOTE: Not `useAttended` so that the layout component is not re-rendered when the attended list changes.
65
- const attended = untracked(() => {
66
- const attention = pluginManager.context.getCapability(AttentionCapabilities.Attention);
67
- return attention.current;
68
- });
60
+ const attention = pluginManager.capabilities.get(AttentionCapabilities.Attention);
61
+ const attended = attention.getCurrent();
69
62
 
70
63
  shouldRevert.current = true;
71
- void dispatch(
72
- createIntent(LayoutAction.SetLayoutMode, { part: 'mode', subject: attended[0], options: { mode: 'solo' } }),
73
- );
74
- } else if (isNotMobile && getMode(deck) === 'solo' && shouldRevert.current) {
75
- void dispatch(createIntent(LayoutAction.SetLayoutMode, { part: 'mode', options: { revert: true } }));
64
+ invokeSync(Common.LayoutOperation.SetLayoutMode, { subject: attended[0], mode: 'solo' });
65
+ } else if (isNotMobile && layoutMode === 'solo' && shouldRevert.current) {
66
+ invokeSync(Common.LayoutOperation.SetLayoutMode, { revert: true });
76
67
  }
77
- }, [isNotMobile, deck, dispatch]);
68
+ // NOTE: Using `layoutMode` instead of `deck` to avoid infinite loops caused by object reference changes.
69
+ }, [isNotMobile, layoutMode, invokeSync]);
78
70
 
79
71
  // When deck is disabled in settings, set to solo mode if the current layout mode is deck.
80
- // TODO(thure): Applying this as an effect should be avoided over emitting the intent only when the setting changes.
72
+ // TODO(thure): Applying this as an effect should be avoided over emitting the operation only when the setting changes.
81
73
  useEffect(() => {
82
74
  if (!settings?.enableDeck && layoutMode === 'deck') {
83
- void dispatch(
84
- createIntent(LayoutAction.SetLayoutMode, { part: 'mode', subject: active[0], options: { mode: 'solo' } }),
85
- );
75
+ invokeSync(Common.LayoutOperation.SetLayoutMode, { subject: active[0], mode: 'solo' });
86
76
  }
87
- }, [settings?.enableDeck, dispatch, active, layoutMode]);
77
+ }, [settings?.enableDeck, invokeSync, active, layoutMode]);
88
78
 
89
79
  /**
90
80
  * Clear scroll restoration state if the window is resized.
@@ -146,12 +136,26 @@ export const DeckMain = () => {
146
136
  );
147
137
  }, [active, activeCompanions]);
148
138
 
139
+ const handleNavigationSidebarStateChange = useCallback(
140
+ (next: typeof sidebarState) => {
141
+ updateState((s) => ({ ...s, sidebarState: next }));
142
+ },
143
+ [updateState],
144
+ );
145
+
146
+ const handleComplementarySidebarStateChange = useCallback(
147
+ (next: typeof complementarySidebarState) => {
148
+ updateState((s) => ({ ...s, complementarySidebarState: next }));
149
+ },
150
+ [updateState],
151
+ );
152
+
149
153
  return (
150
154
  <Main.Root
151
- navigationSidebarState={fullscreen ? 'closed' : context.sidebarState}
152
- complementarySidebarState={fullscreen ? 'closed' : context.complementarySidebarState}
153
- onNavigationSidebarStateChange={(next) => (context.sidebarState = next)}
154
- onComplementarySidebarStateChange={(next) => (context.complementarySidebarState = next)}
155
+ navigationSidebarState={fullscreen ? 'closed' : sidebarState}
156
+ complementarySidebarState={fullscreen ? 'closed' : complementarySidebarState}
157
+ onNavigationSidebarStateChange={handleNavigationSidebarStateChange}
158
+ onComplementarySidebarStateChange={handleComplementarySidebarStateChange}
155
159
  >
156
160
  {/* Left sidebar. */}
157
161
  <Sidebar />
@@ -233,6 +237,7 @@ export const DeckMain = () => {
233
237
  ))}
234
238
  </Stack>
235
239
  </div>
240
+
236
241
  {/* Solo mode. */}
237
242
  <div
238
243
  role='none'
@@ -2,27 +2,30 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import React from 'react';
5
+ import React, { useCallback } from 'react';
6
6
 
7
- import { Surface, useCapability } from '@dxos/app-framework/react';
7
+ import { Surface } from '@dxos/app-framework/react';
8
8
  import { AlertDialog, Dialog as NaturalDialog } from '@dxos/react-ui';
9
9
 
10
- import { DeckCapabilities } from '../../capabilities';
10
+ import { useDeckState } from '../../hooks';
11
11
  import { PlankContentError } from '../Plank';
12
12
 
13
13
  export const Dialog = () => {
14
- const context = useCapability(DeckCapabilities.MutableDeckState);
15
- const { dialogOpen, dialogType, dialogBlockAlign, dialogOverlayClasses, dialogOverlayStyle, dialogContent } = context;
14
+ const { state, updateEphemeral } = useDeckState();
15
+ const { dialogOpen, dialogType, dialogBlockAlign, dialogOverlayClasses, dialogOverlayStyle, dialogContent } = state;
16
16
  const Root = dialogType === 'alert' ? AlertDialog.Root : NaturalDialog.Root;
17
17
  const Overlay = dialogType === 'alert' ? AlertDialog.Overlay : NaturalDialog.Overlay;
18
18
 
19
+ const handleOpenChange = useCallback(
20
+ (nextOpen: boolean) => {
21
+ updateEphemeral((s) => ({ ...s, dialogOpen: nextOpen }));
22
+ },
23
+ [updateEphemeral],
24
+ );
25
+
19
26
  // TODO(thure): End block alignment affecting `modal` and whether the surface renders in an overlay is tailored to the needs of the ambient chat dialog. As the feature matures, consider separating concerns.
20
27
  return (
21
- <Root
22
- modal={dialogBlockAlign !== 'end'}
23
- open={dialogOpen}
24
- onOpenChange={(nextOpen) => (context.dialogOpen = nextOpen)}
25
- >
28
+ <Root modal={dialogBlockAlign !== 'end'} open={dialogOpen} onOpenChange={handleOpenChange}>
26
29
  {dialogBlockAlign === 'end' ? (
27
30
  // TODO(burdon): Placeholder creates a suspense boundary; replace with defaults.
28
31
  <Surface role='dialog' data={dialogContent} limit={1} fallback={PlankContentError} placeholder={<div />} />
@@ -5,7 +5,7 @@
5
5
  import React from 'react';
6
6
 
7
7
  import { useTranslation } from '@dxos/react-ui';
8
- import { errorText, mx } from '@dxos/react-ui-theme';
8
+ import { errorText, mx } from '@dxos/ui-theme';
9
9
 
10
10
  import { meta } from '../../meta';
11
11
 
@@ -5,10 +5,12 @@
5
5
  import { createContext } from '@radix-ui/react-context';
6
6
  import React, { type PropsWithChildren, useCallback, useEffect, useRef, useState } from 'react';
7
7
 
8
- import { Surface, useCapability } from '@dxos/app-framework/react';
9
- import { Popover, type PopoverContentInteractOutsideEvent } from '@dxos/react-ui';
8
+ import { Surface } from '@dxos/app-framework/react';
9
+ import { Popover, type PopoverContentInteractOutsideEvent, toLocalizedString, useTranslation } from '@dxos/react-ui';
10
+ import { Card } from '@dxos/react-ui-mosaic';
10
11
 
11
- import { DeckCapabilities } from '../../capabilities';
12
+ import { useDeckState } from '../../hooks';
13
+ import { meta } from '../../meta';
12
14
 
13
15
  export type DeckPopoverRootProps = PropsWithChildren<{}>;
14
16
 
@@ -21,32 +23,32 @@ type DeckPopoverContextValue = {
21
23
  const [DeckPopoverProvider, useDeckPopoverContext] = createContext<DeckPopoverContextValue>('DeckPopover');
22
24
 
23
25
  export const PopoverRoot = ({ children }: DeckPopoverRootProps) => {
24
- const layout = useCapability(DeckCapabilities.MutableDeckState);
26
+ const { state } = useDeckState();
25
27
  const virtualRef = useRef<HTMLButtonElement | null>(null);
26
28
  const [virtualIter, setVirtualIter] = useState(0);
27
29
  const [open, setOpen] = useState(false);
28
30
  const debounceRef = useRef<NodeJS.Timeout | null>(null);
29
31
 
30
32
  // TODO(thure): This is a workaround for the race condition between displaying a Popover and either rendering
31
- // the anchor further down the tree or measuring the virtual triggers client rect.
33
+ // the anchor further down the tree or measuring the virtual trigger's client rect.
32
34
  useEffect(() => {
33
35
  setOpen(false);
34
- if (layout.popoverOpen) {
36
+ if (state.popoverOpen) {
35
37
  if (debounceRef.current) {
36
38
  clearTimeout(debounceRef.current);
37
39
  }
38
- if (layout.popoverAnchor && virtualRef.current !== layout.popoverAnchor) {
39
- virtualRef.current = layout.popoverAnchor ?? null;
40
+ if (state.popoverAnchor && virtualRef.current !== state.popoverAnchor) {
41
+ virtualRef.current = state.popoverAnchor ?? null;
40
42
  setVirtualIter((iter) => iter + 1);
41
43
  }
42
44
  debounceRef.current = setTimeout(() => setOpen(true), DEBOUNCE_DELAY);
43
45
  }
44
- }, [layout.popoverOpen, layout.popoverAnchorId, layout.popoverAnchor, layout.popoverContent]);
46
+ }, [state.popoverOpen, state.popoverAnchorId, state.popoverAnchor, state.popoverContent]);
45
47
 
46
48
  return (
47
49
  <DeckPopoverProvider setOpen={setOpen}>
48
50
  <Popover.Root modal={false} open={open}>
49
- {layout.popoverAnchor && <Popover.VirtualTrigger key={virtualIter} virtualRef={virtualRef} />}
51
+ {state.popoverAnchor && <Popover.VirtualTrigger key={virtualIter} virtualRef={virtualRef} />}
50
52
  {children}
51
53
  </Popover.Root>
52
54
  </DeckPopoverProvider>
@@ -54,10 +56,22 @@ export const PopoverRoot = ({ children }: DeckPopoverRootProps) => {
54
56
  };
55
57
 
56
58
  export const PopoverContent = () => {
57
- const layout = useCapability(DeckCapabilities.MutableDeckState);
59
+ const { t } = useTranslation(meta.id);
60
+ const { state, updateEphemeral } = useDeckState();
58
61
  const { setOpen } = useDeckPopoverContext('PopoverContent');
59
62
 
60
- const handleClose = useCallback(
63
+ const handleClose = useCallback(() => {
64
+ setOpen(false);
65
+ updateEphemeral((state) => ({
66
+ ...state,
67
+ popoverOpen: false,
68
+ popoverAnchor: undefined,
69
+ popoverAnchorId: undefined,
70
+ popoverSide: undefined,
71
+ }));
72
+ }, [updateEphemeral]);
73
+
74
+ const handleInteractOutside = useCallback(
61
75
  (event: KeyboardEvent | PopoverContentInteractOutsideEvent) => {
62
76
  if (
63
77
  // TODO(thure): CodeMirror should not focus itself when it updates.
@@ -66,27 +80,34 @@ export const PopoverContent = () => {
66
80
  ) {
67
81
  event.preventDefault();
68
82
  } else {
69
- setOpen(false);
70
- layout.popoverOpen = false;
71
- layout.popoverAnchor = undefined;
72
- layout.popoverAnchorId = undefined;
73
- layout.popoverSide = undefined;
83
+ handleClose();
74
84
  }
75
85
  },
76
- [setOpen],
86
+ [handleClose],
77
87
  );
78
88
 
79
89
  return (
80
90
  <Popover.Portal>
81
91
  <Popover.Content
82
- side={layout.popoverSide}
92
+ side={state.popoverSide}
83
93
  sticky='always'
84
94
  hideWhenDetached
85
- onInteractOutside={handleClose}
86
- onEscapeKeyDown={handleClose}
95
+ onInteractOutside={handleInteractOutside}
96
+ onEscapeKeyDown={handleInteractOutside}
87
97
  >
88
98
  <Popover.Viewport>
89
- <Surface role='card--popover' data={layout.popoverContent} limit={1} />
99
+ {state.popoverKind === 'card' && (
100
+ <Card.Root>
101
+ <Card.Toolbar>
102
+ {/* TODO(wittjosiah): Cleaner way to handle no drag handle in toolbar? */}
103
+ <span />
104
+ {state.popoverTitle ? <Card.Title>{toLocalizedString(state.popoverTitle, t)}</Card.Title> : <span />}
105
+ <Card.Close onClick={handleClose} />
106
+ </Card.Toolbar>
107
+ <Surface role='card--content' data={state.popoverContent} limit={1} />
108
+ </Card.Root>
109
+ )}
110
+ {state.popoverKind === 'base' && <Surface role='popover' data={state.popoverContent} limit={1} />}
90
111
  </Popover.Viewport>
91
112
  <Popover.Arrow />
92
113
  </Popover.Content>
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { type LayoutAction } from '@dxos/app-framework';
7
+ import { type Common } from '@dxos/app-framework';
8
8
  import {
9
9
  Button,
10
10
  Icon,
@@ -28,7 +28,7 @@ export const Toast = ({
28
28
  closeLabel,
29
29
  onAction,
30
30
  onOpenChange,
31
- }: LayoutAction.Toast & Pick<ToastRootProps, 'onOpenChange'>) => {
31
+ }: Common.LayoutOperation.Toast & Pick<ToastRootProps, 'onOpenChange'>) => {
32
32
  const { t } = useTranslation(meta.id);
33
33
 
34
34
  return (
@@ -61,7 +61,7 @@ export const Toast = ({
61
61
  };
62
62
 
63
63
  export type ToasterProps = {
64
- toasts?: LayoutAction.Toast[];
64
+ toasts?: Common.LayoutOperation.Toast[];
65
65
  onDismissToast?: (id: string) => void;
66
66
  };
67
67
 
@@ -72,7 +72,7 @@ export const Toaster = ({ toasts, onDismissToast }: ToasterProps) => {
72
72
  <Toast
73
73
  {...toast}
74
74
  key={toast.id}
75
- onOpenChange={(open) => {
75
+ onOpenChange={(open: boolean) => {
76
76
  if (!open) {
77
77
  onDismissToast?.(toast.id);
78
78
  }
@@ -18,7 +18,12 @@ import {
18
18
 
19
19
  const isSocket = !!(globalThis as any).__args;
20
20
 
21
- export const DeckSettings = ({ settings }: { settings: DeckSettingsProps }) => {
21
+ export type DeckSettingsComponentProps = {
22
+ settings: DeckSettingsProps;
23
+ onSettingsChange: (fn: (current: DeckSettingsProps) => DeckSettingsProps) => void;
24
+ };
25
+
26
+ export const DeckSettings = ({ settings, onSettingsChange }: DeckSettingsComponentProps) => {
22
27
  const { t } = useTranslation(meta.id);
23
28
 
24
29
  return (
@@ -28,20 +33,22 @@ export const DeckSettings = ({ settings }: { settings: DeckSettingsProps }) => {
28
33
  <ControlItemInput title={t('settings enable deck label')}>
29
34
  <Input.Switch
30
35
  checked={settings.enableDeck}
31
- onCheckedChange={(checked) => (settings.enableDeck = checked)}
36
+ onCheckedChange={(checked) => onSettingsChange((s) => ({ ...s, enableDeck: checked }))}
32
37
  />
33
38
  </ControlItemInput>
34
39
  <ControlItemInput title={t('settings encapsulated planks label')}>
35
40
  <Input.Switch
36
41
  checked={settings.encapsulatedPlanks ?? false}
37
- onCheckedChange={(checked) => (settings.encapsulatedPlanks = checked)}
42
+ onCheckedChange={(checked) => onSettingsChange((s) => ({ ...s, encapsulatedPlanks: checked }))}
38
43
  />
39
44
  </ControlItemInput>
40
45
  <ControlItemInput title={t('select new plank positioning label')}>
41
46
  <Select.Root
42
47
  disabled={!settings.enableDeck}
43
48
  value={settings.newPlankPositioning ?? 'start'}
44
- onValueChange={(value) => (settings.newPlankPositioning = value as NewPlankPositioning)}
49
+ onValueChange={(value) =>
50
+ onSettingsChange((s) => ({ ...s, newPlankPositioning: value as NewPlankPositioning }))
51
+ }
45
52
  >
46
53
  <Select.TriggerButton placeholder={t('select new plank positioning placeholder')} />
47
54
  <Select.Portal>
@@ -62,7 +69,7 @@ export const DeckSettings = ({ settings }: { settings: DeckSettingsProps }) => {
62
69
  <Select.Root
63
70
  disabled={!settings.enableDeck}
64
71
  value={settings.overscroll ?? 'none'}
65
- onValueChange={(value) => (settings.overscroll = value as Overscroll)}
72
+ onValueChange={(value) => onSettingsChange((s) => ({ ...s, overscroll: value as Overscroll }))}
66
73
  >
67
74
  <Select.TriggerButton placeholder={t('select overscroll placeholder')} />
68
75
  <Select.Portal>
@@ -82,17 +89,20 @@ export const DeckSettings = ({ settings }: { settings: DeckSettingsProps }) => {
82
89
  <ControlItemInput title={t('settings enable statusbar label')}>
83
90
  <Input.Switch
84
91
  checked={settings.enableStatusbar}
85
- onCheckedChange={(checked) => (settings.enableStatusbar = checked)}
92
+ onCheckedChange={(checked) => onSettingsChange((s) => ({ ...s, enableStatusbar: checked }))}
86
93
  />
87
94
  </ControlItemInput>
88
95
  <ControlItemInput title={t('settings show hints label')}>
89
- <Input.Switch checked={settings.showHints} onCheckedChange={(checked) => (settings.showHints = checked)} />
96
+ <Input.Switch
97
+ checked={settings.showHints}
98
+ onCheckedChange={(checked) => onSettingsChange((s) => ({ ...s, showHints: checked }))}
99
+ />
90
100
  </ControlItemInput>
91
101
  {!isSocket && (
92
102
  <ControlItemInput title={t('settings native redirect label')}>
93
103
  <Input.Switch
94
104
  checked={settings.enableNativeRedirect}
95
- onCheckedChange={(checked) => (settings.enableNativeRedirect = checked)}
105
+ onCheckedChange={(checked) => onSettingsChange((s) => ({ ...s, enableNativeRedirect: checked }))}
96
106
  />
97
107
  </ControlItemInput>
98
108
  )}
@@ -5,18 +5,27 @@
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import React from 'react';
7
7
 
8
- import { IntentPlugin, SettingsPlugin } from '@dxos/app-framework';
8
+ import { Capability, Common, Plugin } from '@dxos/app-framework';
9
9
  import { withPluginManager } from '@dxos/app-framework/testing';
10
- import { AttentionPlugin } from '@dxos/plugin-attention';
11
- import { GraphPlugin } from '@dxos/plugin-graph';
10
+ import { corePlugins } from '@dxos/plugin-testing';
12
11
  import { withTheme } from '@dxos/react-ui/testing';
13
12
  import { Stack } from '@dxos/react-ui-stack';
14
13
 
15
- import { DeckStateFactory } from '../../capabilities';
14
+ import { DeckState } from '../../capabilities';
15
+ import { meta as pluginMeta } from '../../meta';
16
16
  import { translations } from '../../translations';
17
17
 
18
18
  import { Plank } from './Plank';
19
19
 
20
+ const TestPlugin = Plugin.define(pluginMeta).pipe(
21
+ Plugin.addModule({
22
+ id: Capability.getModuleTag(DeckState),
23
+ activatesOn: Common.ActivationEvent.AppGraphReady,
24
+ activate: () => DeckState(),
25
+ }),
26
+ Plugin.make,
27
+ );
28
+
20
29
  const meta = {
21
30
  title: 'plugins/plugin-deck/Plank',
22
31
  component: Plank,
@@ -30,8 +39,7 @@ const meta = {
30
39
  decorators: [
31
40
  withTheme,
32
41
  withPluginManager({
33
- plugins: [AttentionPlugin(), SettingsPlugin(), IntentPlugin(), GraphPlugin()],
34
- capabilities: () => DeckStateFactory(),
42
+ plugins: [...corePlugins(), TestPlugin()],
35
43
  }),
36
44
  ],
37
45
  parameters: {
@@ -13,18 +13,17 @@ import React, {
13
13
  useRef,
14
14
  } from 'react';
15
15
 
16
- import { LayoutAction, createIntent } from '@dxos/app-framework';
17
- import { Surface, useAppGraph, useCapability, useIntentDispatcher } from '@dxos/app-framework/react';
16
+ import { Common } from '@dxos/app-framework';
17
+ import { Surface, useAppGraph, useOperationInvoker } from '@dxos/app-framework/react';
18
18
  import { debounce } from '@dxos/async';
19
19
  import { type Node, useNode } from '@dxos/plugin-graph';
20
20
  import { ATTENDABLE_PATH_SEPARATOR, useAttentionAttributes } from '@dxos/react-ui-attention';
21
21
  import { StackItem, railGridHorizontal } from '@dxos/react-ui-stack';
22
- import { mainIntrinsicSize, mx } from '@dxos/react-ui-theme';
22
+ import { mainIntrinsicSize, mx } from '@dxos/ui-theme';
23
23
 
24
- import { DeckCapabilities } from '../../capabilities';
25
- import { useCompanions, useMainSize } from '../../hooks';
24
+ import { useCompanions, useDeckState, useMainSize } from '../../hooks';
26
25
  import { parseEntryId } from '../../layout';
27
- import { DeckAction, type DeckSettingsProps, type LayoutMode, type ResolvedPart } from '../../types';
26
+ import { DeckOperation, type DeckSettingsProps, type LayoutMode, type ResolvedPart } from '../../types';
28
27
 
29
28
  import { PlankContentError, PlankError } from './PlankError';
30
29
  import { PlankHeading } from './PlankHeading';
@@ -49,10 +48,10 @@ export type PlankProps = Pick<PlankComponentProps, 'layoutMode' | 'part' | 'path
49
48
  // benefits. I think where we anticipate users will definitely want to quickly switch between showing and hiding entire
50
49
  // articles, over the (again probably large) performance benefit that unmounting them would confer, we can mount and
51
50
  // hide them, but I think that scenario in its most unambiguous form is probably rare. You could extrapolate
52
- // the scenario to include all potential planks such as companions, which we could keep mounted and hidden, but I
53
- // dont think the resulting performance would be acceptable. I think the real issue is perceived performance which
51
+ // the scenario to include all "potential" planks such as companions, which we could keep mounted and hidden, but I
52
+ // don't think the resulting performance would be acceptable. I think the real issue is "perceived performance" which
54
53
  // has mitigations that are in between mounting and un-mounting since both of those have tradeoffs; we may need one or more
55
- // partially-mounted experiences, like loading skeletons at the simple end, or screenshots of sleeping planks at
54
+ // "partially-mounted" experiences, like loading skeletons at the simple end, or screenshots of "sleeping" planks at
56
55
  // the advanced end.
57
56
 
58
57
  /**
@@ -138,9 +137,9 @@ type PlankComponentProps = {
138
137
  order?: number;
139
138
  active?: string[];
140
139
  companioned?: 'primary' | 'companion';
141
- node?: Node;
142
- primary?: Node;
143
- companions?: Node[];
140
+ node?: Node.Node;
141
+ primary?: Node.Node;
142
+ companions?: Node.Node[];
144
143
  settings?: DeckSettingsProps;
145
144
  };
146
145
 
@@ -158,8 +157,9 @@ const PlankComponent = memo(
158
157
  companions,
159
158
  settings,
160
159
  }: PlankComponentProps) => {
161
- const { dispatchPromise: dispatch } = useIntentDispatcher();
162
- const { deck, popoverAnchorId, scrollIntoView } = useCapability(DeckCapabilities.DeckState);
160
+ const { invokePromise } = useOperationInvoker();
161
+ const { state, deck } = useDeckState();
162
+ const { popoverAnchorId, scrollIntoView } = state;
163
163
  const { findFirstFocusable } = useFocusFinders();
164
164
  const canResize = layoutMode === 'deck';
165
165
 
@@ -177,12 +177,12 @@ const PlankComponent = memo(
177
177
 
178
178
  const handleSizeChange = useCallback(
179
179
  debounce((nextSize: number) => {
180
- return dispatch(createIntent(DeckAction.UpdatePlankSize, { id: sizeKey, size: nextSize }));
180
+ return invokePromise(DeckOperation.UpdatePlankSize, { id: sizeKey, size: nextSize });
181
181
  }, 200),
182
- [dispatch, sizeKey],
182
+ [invokePromise, sizeKey],
183
183
  );
184
184
 
185
- // TODO(thure): Tabsters focus group should handle moving focus to Main, but something is blocking it.
185
+ // TODO(thure): Tabster's focus group should handle moving focus to Main, but something is blocking it.
186
186
  const handleKeyDown = useCallback((event: KeyboardEvent) => {
187
187
  if (event.target === event.currentTarget) {
188
188
  switch (event.key) {
@@ -200,9 +200,9 @@ const PlankComponent = memo(
200
200
  if (scrollIntoView === id) {
201
201
  layoutMode === 'deck' && rootElement.current?.scrollIntoView({ behavior: 'smooth', inline: 'center' });
202
202
  // Clear the scroll into view state once it has been actioned.
203
- void dispatch(createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: undefined }));
203
+ void invokePromise(Common.LayoutOperation.ScrollIntoView, { subject: undefined });
204
204
  }
205
- }, [id, scrollIntoView, layoutMode]);
205
+ }, [id, scrollIntoView, layoutMode, invokePromise]);
206
206
 
207
207
  const isSolo = layoutMode.startsWith('solo') && part === 'solo';
208
208
  const isAttendable =
@@ -4,13 +4,12 @@
4
4
 
5
5
  import React, { forwardRef, useCallback } from 'react';
6
6
 
7
- import { createIntent } from '@dxos/app-framework';
8
- import { useIntentDispatcher } from '@dxos/app-framework/react';
7
+ import { useOperationInvoker } from '@dxos/app-framework/react';
9
8
  import { invariant } from '@dxos/invariant';
10
9
  import { ButtonGroup, type ButtonGroupProps, type ButtonProps, IconButton, useTranslation } from '@dxos/react-ui';
11
10
 
12
11
  import { meta } from '../../meta';
13
- import { DeckAction, type LayoutMode } from '../../types';
12
+ import { type DeckAction, DeckOperation, type LayoutMode } from '../../types';
14
13
 
15
14
  export type PlankControlHandler = (event: DeckAction.PartAdjustment) => void;
16
15
 
@@ -45,11 +44,11 @@ type PlankComplimentControlsProps = {
45
44
  export const PlankCompanionControls = forwardRef<HTMLDivElement, PlankComplimentControlsProps>(
46
45
  ({ primary }, forwardedRef) => {
47
46
  const { t } = useTranslation(meta.id);
48
- const { dispatchPromise: dispatch } = useIntentDispatcher();
47
+ const { invokePromise } = useOperationInvoker();
49
48
  const handleCloseCompanion = useCallback(() => {
50
49
  invariant(primary);
51
- return dispatch(createIntent(DeckAction.ChangeCompanion, { primary, companion: null }));
52
- }, []);
50
+ return invokePromise(DeckOperation.ChangeCompanion, { primary, companion: null });
51
+ }, [invokePromise, primary]);
53
52
  return (
54
53
  <div ref={forwardedRef} className='contents app-no-drag'>
55
54
  <PlankControl
@@ -6,7 +6,7 @@ import React, { useEffect, useState } from 'react';
6
6
 
7
7
  import { type Node } from '@dxos/plugin-graph';
8
8
  import { useTranslation } from '@dxos/react-ui';
9
- import { descriptionMessage, mx } from '@dxos/react-ui-theme';
9
+ import { descriptionMessage, mx } from '@dxos/ui-theme';
10
10
 
11
11
  import { meta } from '../../meta';
12
12
 
@@ -33,7 +33,7 @@ export const PlankError = ({
33
33
  }: {
34
34
  id: string;
35
35
  part: PlankHeadingProps['part'];
36
- node?: Node;
36
+ node?: Node.Node;
37
37
  error?: Error;
38
38
  }) => {
39
39
  const [timedOut, setTimedOut] = useState(false);