@dxos/plugin-deck 0.8.4-main.1da679c → 0.8.4-main.21d9917

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 (279) 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-BKIOCWXT.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-F5BQOOEG.mjs → chunk-ATFPDN6J.mjs} +155 -23
  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 +73 -68
  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-R53LD3EA.mjs +53 -0
  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/toolkit.d.ts +26 -0
  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 +2 -3
  107. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
  108. package/dist/types/src/components/DeckLayout/DeckLayout.stories.d.ts +74 -0
  109. package/dist/types/src/components/DeckLayout/DeckLayout.stories.d.ts.map +1 -0
  110. package/dist/types/src/components/DeckLayout/DeckMain.d.ts +3 -0
  111. package/dist/types/src/components/DeckLayout/DeckMain.d.ts.map +1 -0
  112. package/dist/types/src/components/DeckLayout/Dialog.d.ts.map +1 -1
  113. package/dist/types/src/components/DeckLayout/Popover.d.ts.map +1 -1
  114. package/dist/types/src/components/DeckLayout/Toast.d.ts +7 -2
  115. package/dist/types/src/components/DeckLayout/Toast.d.ts.map +1 -1
  116. package/dist/types/src/components/DeckSettings/DeckSettings.d.ts +4 -2
  117. package/dist/types/src/components/DeckSettings/DeckSettings.d.ts.map +1 -1
  118. package/dist/types/src/components/Plank/Plank.d.ts +3 -3
  119. package/dist/types/src/components/Plank/Plank.d.ts.map +1 -1
  120. package/dist/types/src/components/Plank/Plank.stories.d.ts +25 -6
  121. package/dist/types/src/components/Plank/Plank.stories.d.ts.map +1 -1
  122. package/dist/types/src/components/Plank/PlankControls.d.ts +1 -1
  123. package/dist/types/src/components/Plank/PlankControls.d.ts.map +1 -1
  124. package/dist/types/src/components/Plank/PlankError.d.ts +1 -1
  125. package/dist/types/src/components/Plank/PlankError.d.ts.map +1 -1
  126. package/dist/types/src/components/Plank/PlankHeading.d.ts +2 -2
  127. package/dist/types/src/components/Plank/PlankHeading.d.ts.map +1 -1
  128. package/dist/types/src/components/Sidebar/ComplementarySidebar.d.ts.map +1 -1
  129. package/dist/types/src/components/Sidebar/Sidebar.d.ts.map +1 -1
  130. package/dist/types/src/components/Sidebar/SidebarButton.d.ts.map +1 -1
  131. package/dist/types/src/hooks/index.d.ts +1 -0
  132. package/dist/types/src/hooks/index.d.ts.map +1 -1
  133. package/dist/types/src/hooks/useDeckCompanions.d.ts +3 -3
  134. package/dist/types/src/hooks/useDeckCompanions.d.ts.map +1 -1
  135. package/dist/types/src/hooks/useDeckState.d.ts +17 -0
  136. package/dist/types/src/hooks/useDeckState.d.ts.map +1 -0
  137. package/dist/types/src/hooks/useHoistStatusbar.d.ts +1 -1
  138. package/dist/types/src/hooks/useHoistStatusbar.d.ts.map +1 -1
  139. package/dist/types/src/hooks/useNodeActionExpander.d.ts +1 -1
  140. package/dist/types/src/hooks/useNodeActionExpander.d.ts.map +1 -1
  141. package/dist/types/src/index.d.ts +1 -2
  142. package/dist/types/src/index.d.ts.map +1 -1
  143. package/dist/types/src/meta.d.ts +2 -3
  144. package/dist/types/src/meta.d.ts.map +1 -1
  145. package/dist/types/src/translations.d.ts +2 -1
  146. package/dist/types/src/translations.d.ts.map +1 -1
  147. package/dist/types/src/{capabilities → types}/capabilities.d.ts +96 -90
  148. package/dist/types/src/types/capabilities.d.ts.map +1 -0
  149. package/dist/types/src/types/events.d.ts +7 -0
  150. package/dist/types/src/types/events.d.ts.map +1 -0
  151. package/dist/types/src/types/index.d.ts +2 -0
  152. package/dist/types/src/types/index.d.ts.map +1 -1
  153. package/dist/types/src/types/schema.d.ts +90 -30
  154. package/dist/types/src/types/schema.d.ts.map +1 -1
  155. package/dist/types/src/util/set-active.d.ts +18 -3
  156. package/dist/types/src/util/set-active.d.ts.map +1 -1
  157. package/dist/types/tsconfig.tsbuildinfo +1 -1
  158. package/package.json +54 -48
  159. package/src/DeckPlugin.ts +44 -66
  160. package/src/capabilities/app-graph-builder/app-graph-builder.ts +118 -0
  161. package/src/capabilities/app-graph-builder/index.ts +7 -0
  162. package/src/capabilities/{check-app-scheme.ts → check-app-scheme/check-app-scheme.ts} +12 -11
  163. package/src/capabilities/check-app-scheme/index.ts +7 -0
  164. package/src/capabilities/index.ts +9 -14
  165. package/src/capabilities/operation-resolver/index.ts +10 -0
  166. package/src/capabilities/operation-resolver/operation-resolver.ts +555 -0
  167. package/src/capabilities/react-root/index.ts +7 -0
  168. package/src/capabilities/react-root/react-root.tsx +47 -0
  169. package/src/capabilities/react-surface/index.ts +7 -0
  170. package/src/capabilities/react-surface/react-surface.tsx +37 -0
  171. package/src/capabilities/settings/index.ts +7 -0
  172. package/src/capabilities/settings/settings.ts +38 -0
  173. package/src/capabilities/state/index.ts +7 -0
  174. package/src/capabilities/state/state.ts +104 -0
  175. package/src/capabilities/toolkit/index.ts +7 -0
  176. package/src/capabilities/toolkit/toolkit.ts +63 -0
  177. package/src/capabilities/tools/index.ts +7 -0
  178. package/src/capabilities/tools/tools.ts +92 -0
  179. package/src/capabilities/url-handler/index.ts +7 -0
  180. package/src/capabilities/url-handler/url-handler.ts +95 -0
  181. package/src/components/DeckLayout/ActiveNode.tsx +1 -1
  182. package/src/components/DeckLayout/Banner.tsx +5 -5
  183. package/src/components/DeckLayout/ContentEmpty.tsx +3 -4
  184. package/src/components/DeckLayout/DeckLayout.stories.tsx +51 -0
  185. package/src/components/DeckLayout/DeckLayout.tsx +17 -285
  186. package/src/components/DeckLayout/DeckMain.tsx +286 -0
  187. package/src/components/DeckLayout/Dialog.tsx +13 -10
  188. package/src/components/DeckLayout/Fallback.tsx +4 -4
  189. package/src/components/DeckLayout/Popover.tsx +44 -32
  190. package/src/components/DeckLayout/StatusBar.tsx +1 -1
  191. package/src/components/DeckLayout/Toast.tsx +30 -5
  192. package/src/components/DeckSettings/DeckSettings.tsx +26 -10
  193. package/src/components/Plank/Plank.stories.tsx +17 -11
  194. package/src/components/Plank/Plank.tsx +86 -54
  195. package/src/components/Plank/PlankControls.tsx +9 -9
  196. package/src/components/Plank/PlankError.tsx +4 -4
  197. package/src/components/Plank/PlankHeading.tsx +35 -40
  198. package/src/components/Sidebar/ComplementarySidebar.tsx +58 -31
  199. package/src/components/Sidebar/Sidebar.tsx +6 -6
  200. package/src/components/Sidebar/SidebarButton.tsx +39 -32
  201. package/src/components/fragments.ts +1 -1
  202. package/src/hooks/index.ts +1 -0
  203. package/src/hooks/useCompanions.ts +1 -1
  204. package/src/hooks/useDeckCompanions.ts +6 -4
  205. package/src/hooks/useDeckState.ts +82 -0
  206. package/src/hooks/useHoistStatusbar.ts +4 -5
  207. package/src/hooks/useNodeActionExpander.ts +4 -4
  208. package/src/index.ts +1 -2
  209. package/src/meta.ts +8 -5
  210. package/src/translations.ts +2 -1
  211. package/src/types/capabilities.ts +33 -0
  212. package/src/types/events.ts +20 -0
  213. package/src/types/index.ts +2 -0
  214. package/src/types/schema.ts +86 -14
  215. package/src/util/layoutAppliesTopbar.ts +1 -1
  216. package/src/util/set-active.ts +49 -29
  217. package/dist/lib/browser/app-graph-builder-DD2EJBLZ.mjs +0 -152
  218. package/dist/lib/browser/app-graph-builder-DD2EJBLZ.mjs.map +0 -7
  219. package/dist/lib/browser/check-app-scheme-BKIOCWXT.mjs.map +0 -7
  220. package/dist/lib/browser/chunk-CNTGBCMK.mjs.map +0 -7
  221. package/dist/lib/browser/chunk-F5BQOOEG.mjs.map +0 -7
  222. package/dist/lib/browser/chunk-FMGWFTHR.mjs +0 -1498
  223. package/dist/lib/browser/chunk-FMGWFTHR.mjs.map +0 -7
  224. package/dist/lib/browser/chunk-KCXWTPSU.mjs +0 -127
  225. package/dist/lib/browser/chunk-KCXWTPSU.mjs.map +0 -7
  226. package/dist/lib/browser/chunk-M57WD3V6.mjs +0 -16
  227. package/dist/lib/browser/chunk-M57WD3V6.mjs.map +0 -7
  228. package/dist/lib/browser/chunk-NRCPV6AV.mjs +0 -129
  229. package/dist/lib/browser/chunk-NRCPV6AV.mjs.map +0 -7
  230. package/dist/lib/browser/chunk-Z5KITAZW.mjs +0 -13
  231. package/dist/lib/browser/chunk-Z5KITAZW.mjs.map +0 -7
  232. package/dist/lib/browser/intent-resolver-XSCCU7JI.mjs +0 -521
  233. package/dist/lib/browser/intent-resolver-XSCCU7JI.mjs.map +0 -7
  234. package/dist/lib/browser/react-root-E54PO26O.mjs +0 -43
  235. package/dist/lib/browser/react-root-E54PO26O.mjs.map +0 -7
  236. package/dist/lib/browser/react-surface-DIZC3J4P.mjs +0 -40
  237. package/dist/lib/browser/react-surface-DIZC3J4P.mjs.map +0 -7
  238. package/dist/lib/browser/settings-RNPLZT5S.mjs +0 -29
  239. package/dist/lib/browser/settings-RNPLZT5S.mjs.map +0 -7
  240. package/dist/lib/browser/state-CRXR7X63.mjs +0 -12
  241. package/dist/lib/browser/toolkit-HPFRHY67.mjs +0 -61
  242. package/dist/lib/browser/toolkit-HPFRHY67.mjs.map +0 -7
  243. package/dist/lib/browser/url-handler-6IJME37M.mjs +0 -70
  244. package/dist/lib/browser/url-handler-6IJME37M.mjs.map +0 -7
  245. package/dist/types/src/capabilities/app-graph-builder.d.ts +0 -4
  246. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +0 -1
  247. package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
  248. package/dist/types/src/capabilities/check-app-scheme.d.ts +0 -4
  249. package/dist/types/src/capabilities/check-app-scheme.d.ts.map +0 -1
  250. package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
  251. package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
  252. package/dist/types/src/capabilities/react-root.d.ts +0 -7
  253. package/dist/types/src/capabilities/react-root.d.ts.map +0 -1
  254. package/dist/types/src/capabilities/react-surface.d.ts +0 -4
  255. package/dist/types/src/capabilities/react-surface.d.ts.map +0 -1
  256. package/dist/types/src/capabilities/settings.d.ts +0 -4
  257. package/dist/types/src/capabilities/settings.d.ts.map +0 -1
  258. package/dist/types/src/capabilities/state.d.ts +0 -101
  259. package/dist/types/src/capabilities/state.d.ts.map +0 -1
  260. package/dist/types/src/capabilities/toolkit.d.ts +0 -5
  261. package/dist/types/src/capabilities/toolkit.d.ts.map +0 -1
  262. package/dist/types/src/capabilities/tools.d.ts +0 -11
  263. package/dist/types/src/capabilities/tools.d.ts.map +0 -1
  264. package/dist/types/src/capabilities/url-handler.d.ts +0 -4
  265. package/dist/types/src/capabilities/url-handler.d.ts.map +0 -1
  266. package/dist/types/src/events.d.ts +0 -4
  267. package/dist/types/src/events.d.ts.map +0 -1
  268. package/src/capabilities/app-graph-builder.ts +0 -142
  269. package/src/capabilities/capabilities.ts +0 -14
  270. package/src/capabilities/intent-resolver.ts +0 -469
  271. package/src/capabilities/react-root.tsx +0 -39
  272. package/src/capabilities/react-surface.tsx +0 -30
  273. package/src/capabilities/settings.ts +0 -26
  274. package/src/capabilities/state.ts +0 -105
  275. package/src/capabilities/toolkit.ts +0 -55
  276. package/src/capabilities/tools.ts +0 -84
  277. package/src/capabilities/url-handler.ts +0 -60
  278. package/src/events.ts +0 -11
  279. /package/dist/lib/{browser/state-CRXR7X63.mjs.map → node-esm/types/index.mjs.map} +0 -0
@@ -3,12 +3,14 @@
3
3
  //
4
4
 
5
5
  import { createContext } from '@radix-ui/react-context';
6
- import React, { type PropsWithChildren, useCallback, useEffect, useMemo, useRef, useState } from 'react';
6
+ import React, { type PropsWithChildren, useCallback, useEffect, useRef, useState } from 'react';
7
7
 
8
- import { Surface, useCapability } from '@dxos/app-framework';
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,36 +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
- const collisionBoundaries: HTMLElement[] = useMemo(() => {
80
- const closest = layout.popoverAnchor?.closest('[data-popover-collision-boundary]') as
81
- | HTMLElement
82
- | null
83
- | undefined;
84
- return closest ? [closest] : [];
85
- }, [layout.popoverAnchor]);
86
-
87
89
  return (
88
90
  <Popover.Portal>
89
91
  <Popover.Content
90
- side={layout.popoverSide}
91
- onInteractOutside={handleClose}
92
- onEscapeKeyDown={handleClose}
93
- collisionBoundary={collisionBoundaries}
92
+ side={state.popoverSide}
94
93
  sticky='always'
95
94
  hideWhenDetached
95
+ onInteractOutside={handleInteractOutside}
96
+ onEscapeKeyDown={handleInteractOutside}
96
97
  >
97
98
  <Popover.Viewport>
98
- <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} />}
99
111
  </Popover.Viewport>
100
112
  <Popover.Arrow />
101
113
  </Popover.Content>
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { Surface } from '@dxos/app-framework';
7
+ import { Surface } from '@dxos/app-framework/react';
8
8
  import { useLandmarkMover } from '@dxos/react-ui';
9
9
 
10
10
  export const StatusBar = ({ showHints }: { showHints?: boolean }) => {
@@ -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,
@@ -14,7 +14,7 @@ import {
14
14
  useTranslation,
15
15
  } from '@dxos/react-ui';
16
16
 
17
- import { DECK_PLUGIN } from '../../meta';
17
+ import { meta } from '../../meta';
18
18
 
19
19
  // TODO(wittjosiah): Render remaining duration as a progress bar within the toast.
20
20
  export const Toast = ({
@@ -28,14 +28,14 @@ export const Toast = ({
28
28
  closeLabel,
29
29
  onAction,
30
30
  onOpenChange,
31
- }: LayoutAction.Toast & Pick<ToastRootProps, 'onOpenChange'>) => {
32
- const { t } = useTranslation(DECK_PLUGIN);
31
+ }: Common.LayoutOperation.Toast & Pick<ToastRootProps, 'onOpenChange'>) => {
32
+ const { t } = useTranslation(meta.id);
33
33
 
34
34
  return (
35
35
  <NaturalToast.Root data-testid={id} defaultOpen duration={duration} onOpenChange={onOpenChange}>
36
36
  <NaturalToast.Body>
37
37
  <NaturalToast.Title classNames='items-center'>
38
- {icon && <Icon icon={icon} size={5} classNames='inline mr-1' />}
38
+ {icon && <Icon icon={icon} classNames='inline mr-1' />}
39
39
  {title && <span>{toLocalizedString(title, t)}</span>}
40
40
  </NaturalToast.Title>
41
41
  {description && (
@@ -59,3 +59,28 @@ export const Toast = ({
59
59
  </NaturalToast.Root>
60
60
  );
61
61
  };
62
+
63
+ export type ToasterProps = {
64
+ toasts?: Common.LayoutOperation.Toast[];
65
+ onDismissToast?: (id: string) => void;
66
+ };
67
+
68
+ export const Toaster = ({ toasts, onDismissToast }: ToasterProps) => {
69
+ return (
70
+ <>
71
+ {toasts?.map((toast) => (
72
+ <Toast
73
+ {...toast}
74
+ key={toast.id}
75
+ onOpenChange={(open: boolean) => {
76
+ if (!open) {
77
+ onDismissToast?.(toast.id);
78
+ }
79
+
80
+ return open;
81
+ }}
82
+ />
83
+ ))}
84
+ </>
85
+ );
86
+ };
@@ -7,7 +7,7 @@ import React from 'react';
7
7
  import { Input, Select, useTranslation } from '@dxos/react-ui';
8
8
  import { ControlGroup, ControlItemInput, ControlPage, ControlSection } from '@dxos/react-ui-form';
9
9
 
10
- import { DECK_PLUGIN } from '../../meta';
10
+ import { meta } from '../../meta';
11
11
  import {
12
12
  type DeckSettingsProps,
13
13
  type NewPlankPositioning,
@@ -18,24 +18,37 @@ import {
18
18
 
19
19
  const isSocket = !!(globalThis as any).__args;
20
20
 
21
- export const DeckSettings = ({ settings }: { settings: DeckSettingsProps }) => {
22
- const { t } = useTranslation(DECK_PLUGIN);
21
+ export type DeckSettingsComponentProps = {
22
+ settings: DeckSettingsProps;
23
+ onSettingsChange: (fn: (current: DeckSettingsProps) => DeckSettingsProps) => void;
24
+ };
25
+
26
+ export const DeckSettings = ({ settings, onSettingsChange }: DeckSettingsComponentProps) => {
27
+ const { t } = useTranslation(meta.id);
23
28
 
24
29
  return (
25
30
  <ControlPage>
26
- <ControlSection title={t('settings title', { ns: DECK_PLUGIN })}>
31
+ <ControlSection title={t('settings title', { ns: meta.id })}>
27
32
  <ControlGroup>
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 }))}
37
+ />
38
+ </ControlItemInput>
39
+ <ControlItemInput title={t('settings encapsulated planks label')}>
40
+ <Input.Switch
41
+ checked={settings.encapsulatedPlanks ?? false}
42
+ onCheckedChange={(checked) => onSettingsChange((s) => ({ ...s, encapsulatedPlanks: checked }))}
32
43
  />
33
44
  </ControlItemInput>
34
45
  <ControlItemInput title={t('select new plank positioning label')}>
35
46
  <Select.Root
36
47
  disabled={!settings.enableDeck}
37
48
  value={settings.newPlankPositioning ?? 'start'}
38
- onValueChange={(value) => (settings.newPlankPositioning = value as NewPlankPositioning)}
49
+ onValueChange={(value) =>
50
+ onSettingsChange((s) => ({ ...s, newPlankPositioning: value as NewPlankPositioning }))
51
+ }
39
52
  >
40
53
  <Select.TriggerButton placeholder={t('select new plank positioning placeholder')} />
41
54
  <Select.Portal>
@@ -56,7 +69,7 @@ export const DeckSettings = ({ settings }: { settings: DeckSettingsProps }) => {
56
69
  <Select.Root
57
70
  disabled={!settings.enableDeck}
58
71
  value={settings.overscroll ?? 'none'}
59
- onValueChange={(value) => (settings.overscroll = value as Overscroll)}
72
+ onValueChange={(value) => onSettingsChange((s) => ({ ...s, overscroll: value as Overscroll }))}
60
73
  >
61
74
  <Select.TriggerButton placeholder={t('select overscroll placeholder')} />
62
75
  <Select.Portal>
@@ -76,17 +89,20 @@ export const DeckSettings = ({ settings }: { settings: DeckSettingsProps }) => {
76
89
  <ControlItemInput title={t('settings enable statusbar label')}>
77
90
  <Input.Switch
78
91
  checked={settings.enableStatusbar}
79
- onCheckedChange={(checked) => (settings.enableStatusbar = checked)}
92
+ onCheckedChange={(checked) => onSettingsChange((s) => ({ ...s, enableStatusbar: checked }))}
80
93
  />
81
94
  </ControlItemInput>
82
95
  <ControlItemInput title={t('settings show hints label')}>
83
- <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
+ />
84
100
  </ControlItemInput>
85
101
  {!isSocket && (
86
102
  <ControlItemInput title={t('settings native redirect label')}>
87
103
  <Input.Switch
88
104
  checked={settings.enableNativeRedirect}
89
- onCheckedChange={(checked) => (settings.enableNativeRedirect = checked)}
105
+ onCheckedChange={(checked) => onSettingsChange((s) => ({ ...s, enableNativeRedirect: checked }))}
90
106
  />
91
107
  </ControlItemInput>
92
108
  )}
@@ -2,23 +2,30 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
8
6
  import React from 'react';
9
7
 
10
- import { IntentPlugin, SettingsPlugin } from '@dxos/app-framework';
8
+ import { Capability, Common, Plugin } from '@dxos/app-framework';
11
9
  import { withPluginManager } from '@dxos/app-framework/testing';
12
- import { AttentionPlugin } from '@dxos/plugin-attention';
13
- import { GraphPlugin } from '@dxos/plugin-graph';
10
+ import { corePlugins } from '@dxos/plugin-testing';
11
+ import { withTheme } from '@dxos/react-ui/testing';
14
12
  import { Stack } from '@dxos/react-ui-stack';
15
- import { withLayout, withTheme } from '@dxos/storybook-utils';
16
13
 
17
- import { DeckStateFactory } from '../../capabilities';
14
+ import { DeckState } from '../../capabilities';
15
+ import { meta as pluginMeta } from '../../meta';
18
16
  import { translations } from '../../translations';
19
17
 
20
18
  import { Plank } from './Plank';
21
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
+
22
29
  const meta = {
23
30
  title: 'plugins/plugin-deck/Plank',
24
31
  component: Plank,
@@ -30,14 +37,13 @@ const meta = {
30
37
  );
31
38
  },
32
39
  decorators: [
40
+ withTheme,
33
41
  withPluginManager({
34
- plugins: [AttentionPlugin(), SettingsPlugin(), IntentPlugin(), GraphPlugin()],
35
- capabilities: () => DeckStateFactory(),
42
+ plugins: [...corePlugins(), TestPlugin()],
36
43
  }),
37
- withTheme,
38
- withLayout({ fullscreen: true }),
39
44
  ],
40
45
  parameters: {
46
+ layout: 'fullscreen',
41
47
  translations,
42
48
  },
43
49
  } satisfies Meta<typeof Plank>;
@@ -2,6 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
+ import { useFocusFinders } from '@fluentui/react-tabster';
5
6
  import React, {
6
7
  type KeyboardEvent,
7
8
  type PropsWithChildren,
@@ -12,24 +13,17 @@ import React, {
12
13
  useRef,
13
14
  } from 'react';
14
15
 
15
- import {
16
- LayoutAction,
17
- Surface,
18
- createIntent,
19
- useAppGraph,
20
- useCapability,
21
- useIntentDispatcher,
22
- } from '@dxos/app-framework';
16
+ import { Common } from '@dxos/app-framework';
17
+ import { Surface, useAppGraph, useOperationInvoker } from '@dxos/app-framework/react';
23
18
  import { debounce } from '@dxos/async';
24
19
  import { type Node, useNode } from '@dxos/plugin-graph';
25
20
  import { ATTENDABLE_PATH_SEPARATOR, useAttentionAttributes } from '@dxos/react-ui-attention';
26
21
  import { StackItem, railGridHorizontal } from '@dxos/react-ui-stack';
27
- import { mainIntrinsicSize, mx } from '@dxos/react-ui-theme';
22
+ import { mainIntrinsicSize, mx } from '@dxos/ui-theme';
28
23
 
29
- import { DeckCapabilities } from '../../capabilities';
30
- import { useCompanions, useMainSize } from '../../hooks';
24
+ import { useCompanions, useDeckState, useMainSize } from '../../hooks';
31
25
  import { parseEntryId } from '../../layout';
32
- import { DeckAction, type DeckSettingsProps, type LayoutMode, type ResolvedPart } from '../../types';
26
+ import { DeckOperation, type DeckSettingsProps, type LayoutMode, type ResolvedPart } from '../../types';
33
27
 
34
28
  import { PlankContentError, PlankError } from './PlankError';
35
29
  import { PlankHeading } from './PlankHeading';
@@ -37,6 +31,10 @@ import { PlankLoading } from './PlankLoading';
37
31
 
38
32
  const UNKNOWN_ID = 'unknown_id';
39
33
 
34
+ //
35
+ // Plank
36
+ //
37
+
40
38
  export type PlankProps = Pick<PlankComponentProps, 'layoutMode' | 'part' | 'path' | 'order' | 'active' | 'settings'> & {
41
39
  id?: string;
42
40
  companionId?: string;
@@ -50,10 +48,10 @@ export type PlankProps = Pick<PlankComponentProps, 'layoutMode' | 'part' | 'path
50
48
  // benefits. I think where we anticipate users will definitely want to quickly switch between showing and hiding entire
51
49
  // articles, over the (again probably large) performance benefit that unmounting them would confer, we can mount and
52
50
  // hide them, but I think that scenario in its most unambiguous form is probably rare. You could extrapolate
53
- // the scenario to include all potential planks such as companions, which we could keep mounted and hidden, but I
54
- // 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
55
53
  // has mitigations that are in between mounting and un-mounting since both of those have tradeoffs; we may need one or more
56
- // 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
57
55
  // the advanced end.
58
56
 
59
57
  /**
@@ -68,7 +66,11 @@ export const Plank = memo(({ id = UNKNOWN_ID, companionId, ...props }: PlankProp
68
66
  const hasCompanion = !!(companionId && currentCompanion);
69
67
 
70
68
  return (
71
- <PlankContainer solo={props.part === 'solo'} companion={hasCompanion}>
69
+ <PlankContainer
70
+ solo={props.part === 'solo'}
71
+ companion={hasCompanion}
72
+ encapsulate={!!props.settings?.encapsulatedPlanks}
73
+ >
72
74
  <PlankComponent
73
75
  id={id}
74
76
  node={node}
@@ -92,7 +94,13 @@ export const Plank = memo(({ id = UNKNOWN_ID, companionId, ...props }: PlankProp
92
94
  );
93
95
  });
94
96
 
95
- const PlankContainer = ({ children, solo, companion }: PropsWithChildren<{ solo: boolean; companion: boolean }>) => {
97
+ //
98
+ // PlankContainer
99
+ //
100
+
101
+ type PlankContainerProps = PropsWithChildren<{ solo: boolean; companion: boolean; encapsulate: boolean }>;
102
+
103
+ const PlankContainer = ({ children, solo, companion, encapsulate }: PlankContainerProps) => {
96
104
  const sizeAttrs = useMainSize();
97
105
  if (!solo) {
98
106
  return children;
@@ -102,7 +110,14 @@ const PlankContainer = ({ children, solo, companion }: PropsWithChildren<{ solo:
102
110
  return (
103
111
  <div
104
112
  role='none'
105
- className={mx('absolute inset-0 grid', companion && 'grid-cols-[1fr_1fr]', railGridHorizontal, mainIntrinsicSize)}
113
+ data-popover-collision-boundary={true}
114
+ className={mx(
115
+ 'absolute inset-[--main-spacing] grid',
116
+ encapsulate && 'border border-separator rounded overflow-hidden',
117
+ companion && 'grid-cols-[6fr_4fr]', // TODO(burdon): Resize.
118
+ railGridHorizontal,
119
+ mainIntrinsicSize,
120
+ )}
106
121
  {...sizeAttrs}
107
122
  >
108
123
  {children}
@@ -110,6 +125,10 @@ const PlankContainer = ({ children, solo, companion }: PropsWithChildren<{ solo:
110
125
  );
111
126
  };
112
127
 
128
+ //
129
+ // PlankComponent
130
+ //
131
+
113
132
  type PlankComponentProps = {
114
133
  layoutMode: LayoutMode;
115
134
  id: string;
@@ -117,11 +136,10 @@ type PlankComponentProps = {
117
136
  path?: string[];
118
137
  order?: number;
119
138
  active?: string[];
120
- // TODO(burdon): Change to role?
121
139
  companioned?: 'primary' | 'companion';
122
- node?: Node;
123
- primary?: Node;
124
- companions?: Node[];
140
+ node?: Node.Node;
141
+ primary?: Node.Node;
142
+ companions?: Node.Node[];
125
143
  settings?: DeckSettingsProps;
126
144
  };
127
145
 
@@ -139,8 +157,10 @@ const PlankComponent = memo(
139
157
  companions,
140
158
  settings,
141
159
  }: PlankComponentProps) => {
142
- const { dispatchPromise: dispatch } = useIntentDispatcher();
143
- const { deck, popoverAnchorId, scrollIntoView } = useCapability(DeckCapabilities.DeckState);
160
+ const { invokePromise } = useOperationInvoker();
161
+ const { state, deck } = useDeckState();
162
+ const { popoverAnchorId, scrollIntoView } = state;
163
+ const { findFirstFocusable } = useFocusFinders();
144
164
  const canResize = layoutMode === 'deck';
145
165
 
146
166
  const attentionAttrs = useAttentionAttributes(primary?.id ?? id);
@@ -157,29 +177,32 @@ const PlankComponent = memo(
157
177
 
158
178
  const handleSizeChange = useCallback(
159
179
  debounce((nextSize: number) => {
160
- return dispatch(createIntent(DeckAction.UpdatePlankSize, { id: sizeKey, size: nextSize }));
180
+ return invokePromise(DeckOperation.UpdatePlankSize, { id: sizeKey, size: nextSize });
161
181
  }, 200),
162
- [dispatch, sizeKey],
182
+ [invokePromise, sizeKey],
163
183
  );
164
184
 
165
- // 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.
166
186
  const handleKeyDown = useCallback((event: KeyboardEvent) => {
167
- if (event.target === event.currentTarget && event.key === 'Escape') {
168
- rootElement.current?.closest('main')?.focus();
187
+ if (event.target === event.currentTarget) {
188
+ switch (event.key) {
189
+ case 'Escape':
190
+ rootElement.current?.closest('main')?.focus();
191
+ break;
192
+ case 'Enter':
193
+ rootElement.current && findFirstFocusable(rootElement.current)?.focus();
194
+ break;
195
+ }
169
196
  }
170
197
  }, []);
171
198
 
172
199
  useLayoutEffect(() => {
173
200
  if (scrollIntoView === id) {
174
- // TODO(wittjosiah): When focused on page load, the focus is always visible.
175
- // Forcing focus to something smaller than the plank prevents large focus ring in the interim.
176
- const focusable = rootElement.current?.querySelector('button') || rootElement.current;
177
- focusable?.focus({ preventScroll: true });
178
- layoutMode === 'deck' && focusable?.scrollIntoView({ behavior: 'smooth', inline: 'center' });
201
+ layoutMode === 'deck' && rootElement.current?.scrollIntoView({ behavior: 'smooth', inline: 'center' });
179
202
  // Clear the scroll into view state once it has been actioned.
180
- void dispatch(createIntent(LayoutAction.ScrollIntoView, { part: 'current', subject: undefined }));
203
+ void invokePromise(Common.LayoutOperation.ScrollIntoView, { subject: undefined });
181
204
  }
182
- }, [id, scrollIntoView, layoutMode]);
205
+ }, [id, scrollIntoView, layoutMode, invokePromise]);
183
206
 
184
207
  const isSolo = layoutMode.startsWith('solo') && part === 'solo';
185
208
  const isAttendable =
@@ -190,34 +213,42 @@ const PlankComponent = memo(
190
213
  const data = useMemo(
191
214
  () =>
192
215
  node && {
216
+ attendableId: id,
193
217
  subject: node.data,
194
218
  companionTo: primary?.data,
219
+ properties: node.properties,
195
220
  variant,
196
221
  path,
197
222
  popoverAnchorId,
198
223
  },
199
- [node, node?.data, path, popoverAnchorId, primary?.data, variant],
224
+ [node, node?.data, node?.properties, path, popoverAnchorId, primary?.data, variant],
200
225
  );
201
226
 
202
227
  // TODO(wittjosiah): Change prop to accept a component.
203
228
  const placeholder = useMemo(() => <PlankLoading />, []);
204
229
 
205
230
  const Root = part.startsWith('solo') ? 'article' : StackItem.Root;
231
+ const fullscreen = layoutMode === 'solo--fullscreen';
206
232
  const className = mx(
207
233
  'attention-surface relative dx-focus-ring-inset-over-all density-coarse',
208
- isSolo && mainIntrinsicSize,
209
- isSolo && railGridHorizontal,
210
234
  isSolo && 'absolute inset-0',
235
+ isSolo && mainIntrinsicSize,
236
+ railGridHorizontal,
211
237
  part.startsWith('solo') && 'grid',
238
+ part.startsWith('solo-') && 'grid-rows-subgrid row-span-2 min-is-0',
239
+ fullscreen && 'grid-rows-1',
212
240
  part === 'deck' && (companioned === 'companion' ? '!border-separator border-ie' : '!border-separator border-li'),
213
- part.startsWith('solo-') && 'row-span-2 grid-rows-subgrid min-is-0',
214
241
  part === 'solo-companion' && '!border-separator border-is',
242
+ settings?.encapsulatedPlanks &&
243
+ !part.startsWith('solo') &&
244
+ 'mli-[--main-spacing] !border-separator border rounded overflow-hidden',
215
245
  );
216
246
 
217
247
  return (
218
248
  <Root
219
249
  ref={rootElement}
220
250
  data-testid='deck.plank'
251
+ data-popover-collision-boundary={true}
221
252
  tabIndex={0}
222
253
  {...(part.startsWith('solo')
223
254
  ? ({ ...sizeAttrs, className } as any)
@@ -234,19 +265,21 @@ const PlankComponent = memo(
234
265
  >
235
266
  {node ? (
236
267
  <>
237
- <PlankHeading
238
- id={id}
239
- part={part.startsWith('solo-') ? 'solo' : part}
240
- node={node}
241
- layoutMode={layoutMode}
242
- deckEnabled={settings?.enableDeck}
243
- canIncrementStart={canIncrementStart}
244
- canIncrementEnd={canIncrementEnd}
245
- popoverAnchorId={popoverAnchorId}
246
- primaryId={primary?.id}
247
- companioned={companioned}
248
- companions={companions}
249
- />
268
+ {!fullscreen && (
269
+ <PlankHeading
270
+ id={id}
271
+ part={part.startsWith('solo-') ? 'solo' : part}
272
+ node={node}
273
+ layoutMode={layoutMode}
274
+ deckEnabled={settings?.enableDeck}
275
+ canIncrementStart={canIncrementStart}
276
+ canIncrementEnd={canIncrementEnd}
277
+ popoverAnchorId={popoverAnchorId}
278
+ primaryId={primary?.id}
279
+ companioned={companioned}
280
+ companions={companions}
281
+ />
282
+ )}
250
283
  <Surface
251
284
  key={node.id}
252
285
  role='article'
@@ -259,7 +292,6 @@ const PlankComponent = memo(
259
292
  ) : (
260
293
  <PlankError id={id} part={part} />
261
294
  )}
262
-
263
295
  {canResize && <StackItem.ResizeHandle />}
264
296
  </Root>
265
297
  );