@dxos/plugin-deck 0.9.0 → 0.9.1-staging.ee54ba693a

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 (314) hide show
  1. package/PLUGIN.mdl +3 -1
  2. package/dist/lib/neutral/{DeckLayout-DEURA3KR.mjs → DeckLayout-B3RUUV5P.mjs} +36 -22
  3. package/dist/lib/neutral/DeckLayout-B3RUUV5P.mjs.map +7 -0
  4. package/dist/lib/neutral/DeckPlugin.mjs +4 -8
  5. package/dist/lib/neutral/DeckPlugin.mjs.map +4 -4
  6. package/dist/lib/neutral/DeckSettings-Z7GMB7XJ.mjs +32 -0
  7. package/dist/lib/neutral/DeckSettings-Z7GMB7XJ.mjs.map +7 -0
  8. package/dist/lib/neutral/{add-toast-TNB6DXWU.mjs → add-toast-BHNEH5UY.mjs} +2 -2
  9. package/dist/lib/neutral/{adjust-HNU5CCRO.mjs → adjust-MJB6UMRQ.mjs} +16 -10
  10. package/dist/lib/neutral/adjust-MJB6UMRQ.mjs.map +7 -0
  11. package/dist/lib/neutral/{app-graph-builder-HMLT627T.mjs → app-graph-builder-2F7P4IFQ.mjs} +8 -7
  12. package/dist/lib/neutral/app-graph-builder-2F7P4IFQ.mjs.map +7 -0
  13. package/dist/lib/neutral/capabilities/index.mjs +8 -8
  14. package/dist/lib/neutral/{check-app-scheme-INSOF72J.mjs → check-app-scheme-HSAORHHX.mjs} +2 -2
  15. package/dist/lib/neutral/chunk-FKGYHBUB.mjs +8 -0
  16. package/dist/lib/neutral/{chunk-BS4EOYMK.mjs → chunk-ICOJ4GMB.mjs} +37 -19
  17. package/dist/lib/neutral/chunk-ICOJ4GMB.mjs.map +7 -0
  18. package/dist/lib/neutral/chunk-KY7LMF4D.mjs +46 -0
  19. package/dist/lib/neutral/chunk-KY7LMF4D.mjs.map +7 -0
  20. package/dist/lib/neutral/{chunk-324PPIZB.mjs → chunk-KZFJ4PBT.mjs} +4 -4
  21. package/dist/lib/neutral/chunk-KZFJ4PBT.mjs.map +7 -0
  22. package/dist/lib/neutral/{chunk-GBIGQKYW.mjs → chunk-PP32NEVY.mjs} +4 -4
  23. package/dist/lib/neutral/chunk-PP32NEVY.mjs.map +7 -0
  24. package/dist/lib/neutral/chunk-SONATB35.mjs +20 -0
  25. package/dist/lib/neutral/chunk-SONATB35.mjs.map +7 -0
  26. package/dist/lib/neutral/chunk-Z2B5RSVI.mjs +1096 -0
  27. package/dist/lib/neutral/chunk-Z2B5RSVI.mjs.map +7 -0
  28. package/dist/lib/neutral/{close-ASKR22A6.mjs → close-2YGB5IIP.mjs} +4 -3
  29. package/dist/lib/neutral/{close-ASKR22A6.mjs.map → close-2YGB5IIP.mjs.map} +1 -1
  30. package/dist/lib/neutral/components/index.mjs +201 -16
  31. package/dist/lib/neutral/components/index.mjs.map +4 -4
  32. package/dist/lib/neutral/containers/index.mjs +6 -11
  33. package/dist/lib/neutral/containers/index.mjs.map +3 -3
  34. package/dist/lib/neutral/hooks/index.mjs +101 -17
  35. package/dist/lib/neutral/hooks/index.mjs.map +4 -4
  36. package/dist/lib/neutral/index.mjs +18 -2
  37. package/dist/lib/neutral/meta.json +1 -1
  38. package/dist/lib/neutral/meta.mjs +1 -1
  39. package/dist/lib/neutral/{notification-tracker-P36322BH.mjs → notification-tracker-Y5CRTWJM.mjs} +12 -10
  40. package/dist/lib/neutral/notification-tracker-Y5CRTWJM.mjs.map +7 -0
  41. package/dist/lib/neutral/{open-5OYNO3RT.mjs → open-P6XQ56M7.mjs} +8 -7
  42. package/dist/lib/neutral/open-P6XQ56M7.mjs.map +7 -0
  43. package/dist/lib/neutral/operations/index.mjs +1 -1
  44. package/dist/lib/neutral/plugin.mjs +2 -2
  45. package/dist/lib/neutral/{react-root-HH5DEUOG.mjs → react-root-E6TAFHX6.mjs} +2 -2
  46. package/dist/lib/neutral/react-root-E6TAFHX6.mjs.map +7 -0
  47. package/dist/lib/neutral/{react-surface-3UVVCK3O.mjs → react-surface-H63FXUK3.mjs} +5 -6
  48. package/dist/lib/neutral/react-surface-H63FXUK3.mjs.map +7 -0
  49. package/dist/lib/neutral/{revert-workspace-B2QLT2C4.mjs → revert-workspace-RXWP2TEE.mjs} +2 -2
  50. package/dist/lib/neutral/{scroll-into-view-B52C3PJO.mjs → scroll-into-view-HFV5EGYZ.mjs} +2 -2
  51. package/dist/lib/neutral/{set-PA35ONXO.mjs → set-HOOVB7E4.mjs} +4 -3
  52. package/dist/lib/neutral/{set-PA35ONXO.mjs.map → set-HOOVB7E4.mjs.map} +1 -1
  53. package/dist/lib/neutral/{set-layout-mode-RPCCPQRB.mjs → set-layout-mode-XAGSZZGB.mjs} +2 -2
  54. package/dist/lib/neutral/{settings-EGNYUM4T.mjs → settings-6CDQEB6B.mjs} +3 -3
  55. package/dist/lib/neutral/settings-6CDQEB6B.mjs.map +7 -0
  56. package/dist/lib/neutral/{state-IIDXMQUO.mjs → state-F4X5GPGZ.mjs} +4 -3
  57. package/dist/lib/neutral/state-F4X5GPGZ.mjs.map +7 -0
  58. package/dist/lib/neutral/{switch-workspace-LZF4KZXH.mjs → switch-workspace-PA7N6EUX.mjs} +4 -4
  59. package/dist/lib/neutral/switch-workspace-PA7N6EUX.mjs.map +7 -0
  60. package/dist/lib/neutral/translations.mjs +3 -3
  61. package/dist/lib/neutral/translations.mjs.map +3 -3
  62. package/dist/lib/neutral/types/index.mjs +11 -1
  63. package/dist/lib/neutral/{update-companion-YUCZZVGY.mjs → update-companion-6A2SKQAI.mjs} +14 -6
  64. package/dist/lib/neutral/update-companion-6A2SKQAI.mjs.map +7 -0
  65. package/dist/lib/neutral/{update-complementary-7FZNB55J.mjs → update-complementary-K55I5EV5.mjs} +2 -2
  66. package/dist/lib/neutral/{update-dialog-FNQTSSAP.mjs → update-dialog-Z3GEXMVV.mjs} +2 -2
  67. package/dist/lib/neutral/{update-plank-size-3YW4NXEY.mjs → update-plank-size-BTESVV7N.mjs} +2 -2
  68. package/dist/lib/neutral/{update-popover-G2VUD7E6.mjs → update-popover-QEVDSZSH.mjs} +2 -2
  69. package/dist/lib/neutral/{update-sidebar-KRHPUHUB.mjs → update-sidebar-VSRCN47U.mjs} +2 -2
  70. package/dist/lib/neutral/{url-handler-A6HLW4RB.mjs → url-handler-ERZXXEYR.mjs} +11 -10
  71. package/dist/lib/neutral/url-handler-ERZXXEYR.mjs.map +7 -0
  72. package/dist/types/dx.config.d.ts +28 -0
  73. package/dist/types/dx.config.d.ts.map +1 -0
  74. package/dist/types/src/DeckPlugin.d.ts.map +1 -1
  75. package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -2
  76. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  77. package/dist/types/src/capabilities/index.d.ts +8 -196
  78. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  79. package/dist/types/src/capabilities/notification-tracker.d.ts +1 -1
  80. package/dist/types/src/capabilities/notification-tracker.d.ts.map +1 -1
  81. package/dist/types/src/capabilities/react-root.d.ts +1 -5
  82. package/dist/types/src/capabilities/react-root.d.ts.map +1 -1
  83. package/dist/types/src/capabilities/react-surface.d.ts +2 -2
  84. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  85. package/dist/types/src/capabilities/settings.d.ts +1 -3
  86. package/dist/types/src/capabilities/settings.d.ts.map +1 -1
  87. package/dist/types/src/capabilities/state.d.ts +1 -187
  88. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  89. package/dist/types/src/capabilities/tools.d.ts +1 -1
  90. package/dist/types/src/capabilities/url-handler.d.ts +1 -1
  91. package/dist/types/src/components/Companion/Companion.d.ts +17 -0
  92. package/dist/types/src/components/Companion/Companion.d.ts.map +1 -0
  93. package/dist/types/src/components/Companion/index.d.ts +2 -0
  94. package/dist/types/src/components/Companion/index.d.ts.map +1 -0
  95. package/dist/types/src/components/Matrix/Matrix.d.ts +1 -1
  96. package/dist/types/src/components/Matrix/Matrix.d.ts.map +1 -1
  97. package/dist/types/src/components/Matrix/Matrix.stories.d.ts +2 -2
  98. package/dist/types/src/components/Matrix/Matrix.stories.d.ts.map +1 -1
  99. package/dist/types/src/components/Matrix/index.d.ts +1 -1
  100. package/dist/types/src/components/Matrix/index.d.ts.map +1 -1
  101. package/dist/types/src/components/Pane/Pane.d.ts +45 -0
  102. package/dist/types/src/components/Pane/Pane.d.ts.map +1 -0
  103. package/dist/types/src/components/Pane/Pane.stories.d.ts +7 -0
  104. package/dist/types/src/components/Pane/Pane.stories.d.ts.map +1 -0
  105. package/dist/types/src/components/Pane/index.d.ts +2 -0
  106. package/dist/types/src/components/Pane/index.d.ts.map +1 -0
  107. package/dist/types/src/components/Plank/Plank.d.ts +74 -0
  108. package/dist/types/src/components/Plank/Plank.d.ts.map +1 -0
  109. package/dist/types/src/components/Plank/Plank.stories.d.ts +6 -0
  110. package/dist/types/src/components/Plank/Plank.stories.d.ts.map +1 -0
  111. package/dist/types/src/components/Plank/index.d.ts +2 -0
  112. package/dist/types/src/components/Plank/index.d.ts.map +1 -0
  113. package/dist/types/src/components/index.d.ts +3 -2
  114. package/dist/types/src/components/index.d.ts.map +1 -1
  115. package/dist/types/src/containers/Deck/Banner.d.ts.map +1 -1
  116. package/dist/types/src/containers/Deck/Deck.d.ts +1 -1
  117. package/dist/types/src/containers/Deck/Deck.d.ts.map +1 -1
  118. package/dist/types/src/containers/Deck/Deck.stories.d.ts +2 -2
  119. package/dist/types/src/containers/Deck/DeckPlank.d.ts +21 -0
  120. package/dist/types/src/containers/Deck/DeckPlank.d.ts.map +1 -0
  121. package/dist/types/src/containers/Deck/DeckViewport.d.ts +3 -1
  122. package/dist/types/src/containers/Deck/DeckViewport.d.ts.map +1 -1
  123. package/dist/types/src/containers/{Plank → Deck}/PlankControls.d.ts +3 -10
  124. package/dist/types/src/containers/Deck/PlankControls.d.ts.map +1 -0
  125. package/dist/types/src/containers/Deck/PlankFallback.d.ts +6 -0
  126. package/dist/types/src/containers/Deck/PlankFallback.d.ts.map +1 -0
  127. package/dist/types/src/containers/Deck/StatusBar.d.ts.map +1 -1
  128. package/dist/types/src/containers/Deck/useDeckPlank.d.ts +49 -0
  129. package/dist/types/src/containers/Deck/useDeckPlank.d.ts.map +1 -0
  130. package/dist/types/src/containers/DeckLayout/DeckLayout.stories.d.ts +2 -2
  131. package/dist/types/src/containers/DeckLayout/DeckLayout.stories.d.ts.map +1 -1
  132. package/dist/types/src/containers/DeckLayout/Popover.d.ts.map +1 -1
  133. package/dist/types/src/{components → containers}/DeckSettings/DeckSettings.d.ts +1 -1
  134. package/dist/types/src/containers/DeckSettings/DeckSettings.d.ts.map +1 -0
  135. package/dist/types/src/{components → containers}/DeckSettings/DeckSettings.stories.d.ts +2 -2
  136. package/dist/types/src/{components → containers}/DeckSettings/DeckSettings.stories.d.ts.map +1 -1
  137. package/dist/types/src/containers/DeckSettings/index.d.ts.map +1 -0
  138. package/dist/types/src/containers/Sidebar/ComplementarySidebar.d.ts.map +1 -1
  139. package/dist/types/src/containers/index.d.ts +1 -1
  140. package/dist/types/src/containers/index.d.ts.map +1 -1
  141. package/dist/types/src/hooks/index.d.ts +2 -0
  142. package/dist/types/src/hooks/index.d.ts.map +1 -1
  143. package/dist/types/src/hooks/useCompanionSplit.d.ts +28 -0
  144. package/dist/types/src/hooks/useCompanionSplit.d.ts.map +1 -0
  145. package/dist/types/src/hooks/useCompanions.d.ts +11 -7
  146. package/dist/types/src/hooks/useCompanions.d.ts.map +1 -1
  147. package/dist/types/src/hooks/useDeckCompanions.d.ts +2 -2
  148. package/dist/types/src/hooks/useDeckCompanions.d.ts.map +1 -1
  149. package/dist/types/src/hooks/useDeckState.d.ts +1 -1
  150. package/dist/types/src/hooks/useDeckState.d.ts.map +1 -1
  151. package/dist/types/src/hooks/useSelectedCompanionVariant.d.ts +6 -0
  152. package/dist/types/src/hooks/useSelectedCompanionVariant.d.ts.map +1 -0
  153. package/dist/types/src/index.d.ts +1 -0
  154. package/dist/types/src/index.d.ts.map +1 -1
  155. package/dist/types/src/meta.d.ts +32 -2
  156. package/dist/types/src/meta.d.ts.map +1 -1
  157. package/dist/types/src/operations/adjust.d.ts.map +1 -1
  158. package/dist/types/src/operations/open.d.ts.map +1 -1
  159. package/dist/types/src/operations/switch-workspace.d.ts.map +1 -1
  160. package/dist/types/src/operations/update-companion.d.ts.map +1 -1
  161. package/dist/types/src/translations.d.ts +2 -2
  162. package/dist/types/src/translations.d.ts.map +1 -1
  163. package/dist/types/src/types/DeckCapabilities.d.ts +4 -4
  164. package/dist/types/src/types/DeckCapabilities.d.ts.map +1 -1
  165. package/dist/types/src/types/DeckOperation.d.ts +2 -2
  166. package/dist/types/src/types/DeckOperation.d.ts.map +1 -1
  167. package/dist/types/src/types/index.d.ts +1 -0
  168. package/dist/types/src/types/index.d.ts.map +1 -1
  169. package/dist/types/src/types/schema.d.ts +11 -9
  170. package/dist/types/src/types/schema.d.ts.map +1 -1
  171. package/dist/types/src/types/surface.d.ts +12 -0
  172. package/dist/types/src/types/surface.d.ts.map +1 -0
  173. package/dist/types/src/util/companion-view-state.d.ts +16 -0
  174. package/dist/types/src/util/companion-view-state.d.ts.map +1 -0
  175. package/dist/types/src/util/index.d.ts +1 -0
  176. package/dist/types/src/util/index.d.ts.map +1 -1
  177. package/dist/types/src/util/plank-url-params.d.ts +2 -0
  178. package/dist/types/src/util/plank-url-params.d.ts.map +1 -1
  179. package/dist/types/tsconfig.tsbuildinfo +1 -1
  180. package/dx.config.ts +35 -0
  181. package/package.json +50 -48
  182. package/src/DeckPlugin.test.ts +1 -1
  183. package/src/DeckPlugin.ts +2 -3
  184. package/src/capabilities/app-graph-builder.ts +7 -6
  185. package/src/capabilities/check-app-scheme.ts +3 -3
  186. package/src/capabilities/notification-tracker.ts +11 -9
  187. package/src/capabilities/react-root.tsx +1 -1
  188. package/src/capabilities/react-surface.tsx +4 -5
  189. package/src/capabilities/settings.ts +2 -2
  190. package/src/capabilities/state.ts +1 -1
  191. package/src/capabilities/url-handler.ts +7 -15
  192. package/src/components/Companion/Companion.tsx +91 -0
  193. package/src/components/Companion/index.ts +5 -0
  194. package/src/components/Matrix/Matrix.stories.tsx +15 -27
  195. package/src/components/Matrix/Matrix.tsx +3 -3
  196. package/src/components/Matrix/SPEC.md +1 -1
  197. package/src/components/Matrix/index.ts +1 -1
  198. package/src/components/Pane/Pane.stories.tsx +92 -0
  199. package/src/components/Pane/Pane.tsx +178 -0
  200. package/src/components/Pane/index.ts +5 -0
  201. package/src/components/Plank/Plank.stories.tsx +103 -0
  202. package/src/components/Plank/Plank.tsx +149 -0
  203. package/src/components/Plank/index.ts +5 -0
  204. package/src/components/index.ts +3 -4
  205. package/src/containers/Deck/Banner.tsx +5 -4
  206. package/src/containers/Deck/Deck.tsx +3 -3
  207. package/src/containers/Deck/DeckPlank.tsx +187 -0
  208. package/src/containers/Deck/DeckViewport.tsx +118 -246
  209. package/src/containers/{Plank → Deck}/PlankControls.tsx +21 -19
  210. package/src/containers/Deck/PlankFallback.tsx +42 -0
  211. package/src/containers/Deck/StatusBar.tsx +4 -2
  212. package/src/containers/Deck/useDeckPlank.ts +219 -0
  213. package/src/containers/DeckLayout/DeckLayout.stories.tsx +44 -60
  214. package/src/containers/DeckLayout/Dialog.tsx +1 -1
  215. package/src/containers/DeckLayout/Fallback.tsx +1 -1
  216. package/src/containers/DeckLayout/Popover.tsx +37 -20
  217. package/src/containers/DeckLayout/Toast.tsx +1 -1
  218. package/src/{components → containers}/DeckSettings/DeckSettings.stories.tsx +1 -1
  219. package/src/containers/DeckSettings/DeckSettings.tsx +42 -0
  220. package/src/containers/Sidebar/ComplementarySidebar.tsx +8 -7
  221. package/src/containers/Sidebar/Sidebar.tsx +1 -1
  222. package/src/containers/Sidebar/SidebarButton.tsx +3 -3
  223. package/src/containers/index.ts +1 -1
  224. package/src/hooks/index.ts +2 -0
  225. package/src/hooks/useCompanionSplit.ts +78 -0
  226. package/src/hooks/useCompanions.ts +39 -7
  227. package/src/hooks/useDeckCompanions.ts +3 -3
  228. package/src/hooks/useDeckState.ts +1 -1
  229. package/src/hooks/useSelectedCompanionVariant.ts +14 -0
  230. package/src/index.ts +7 -0
  231. package/src/meta.ts +2 -27
  232. package/src/operations/adjust.ts +23 -12
  233. package/src/operations/open.ts +12 -10
  234. package/src/operations/switch-workspace.ts +2 -2
  235. package/src/operations/update-companion.ts +10 -6
  236. package/src/translations.ts +3 -3
  237. package/src/types/DeckCapabilities.ts +6 -4
  238. package/src/types/DeckEvents.ts +1 -1
  239. package/src/types/DeckOperation.ts +3 -2
  240. package/src/types/index.ts +1 -0
  241. package/src/types/schema.ts +21 -16
  242. package/src/types/surface.ts +28 -0
  243. package/src/util/companion-view-state.ts +28 -0
  244. package/src/util/index.ts +1 -0
  245. package/src/util/plank-url-params.test.ts +5 -0
  246. package/src/util/plank-url-params.ts +5 -3
  247. package/src/util/sanitize-persisted-state.test.ts +1 -1
  248. package/src/util/set-active.test.ts +1 -1
  249. package/dist/lib/neutral/DeckLayout-DEURA3KR.mjs.map +0 -7
  250. package/dist/lib/neutral/DeckSettings-W5I57OXM.mjs +0 -27
  251. package/dist/lib/neutral/DeckSettings-W5I57OXM.mjs.map +0 -7
  252. package/dist/lib/neutral/adjust-HNU5CCRO.mjs.map +0 -7
  253. package/dist/lib/neutral/app-graph-builder-HMLT627T.mjs.map +0 -7
  254. package/dist/lib/neutral/chunk-324PPIZB.mjs.map +0 -7
  255. package/dist/lib/neutral/chunk-BS4EOYMK.mjs.map +0 -7
  256. package/dist/lib/neutral/chunk-GBIGQKYW.mjs.map +0 -7
  257. package/dist/lib/neutral/chunk-PYEY5SEC.mjs +0 -37
  258. package/dist/lib/neutral/chunk-PYEY5SEC.mjs.map +0 -7
  259. package/dist/lib/neutral/chunk-Q4W6B4IB.mjs +0 -8
  260. package/dist/lib/neutral/chunk-WAXJPQJI.mjs +0 -1306
  261. package/dist/lib/neutral/chunk-WAXJPQJI.mjs.map +0 -7
  262. package/dist/lib/neutral/notification-tracker-P36322BH.mjs.map +0 -7
  263. package/dist/lib/neutral/open-5OYNO3RT.mjs.map +0 -7
  264. package/dist/lib/neutral/react-root-HH5DEUOG.mjs.map +0 -7
  265. package/dist/lib/neutral/react-surface-3UVVCK3O.mjs.map +0 -7
  266. package/dist/lib/neutral/settings-EGNYUM4T.mjs.map +0 -7
  267. package/dist/lib/neutral/state-IIDXMQUO.mjs.map +0 -7
  268. package/dist/lib/neutral/switch-workspace-LZF4KZXH.mjs.map +0 -7
  269. package/dist/lib/neutral/update-companion-YUCZZVGY.mjs.map +0 -7
  270. package/dist/lib/neutral/url-handler-A6HLW4RB.mjs.map +0 -7
  271. package/dist/types/src/components/DeckSettings/DeckSettings.d.ts.map +0 -1
  272. package/dist/types/src/components/DeckSettings/index.d.ts.map +0 -1
  273. package/dist/types/src/containers/Plank/Plank.d.ts +0 -17
  274. package/dist/types/src/containers/Plank/Plank.d.ts.map +0 -1
  275. package/dist/types/src/containers/Plank/Plank.stories.d.ts +0 -67
  276. package/dist/types/src/containers/Plank/Plank.stories.d.ts.map +0 -1
  277. package/dist/types/src/containers/Plank/PlankComponent.d.ts +0 -17
  278. package/dist/types/src/containers/Plank/PlankComponent.d.ts.map +0 -1
  279. package/dist/types/src/containers/Plank/PlankContent.d.ts +0 -10
  280. package/dist/types/src/containers/Plank/PlankContent.d.ts.map +0 -1
  281. package/dist/types/src/containers/Plank/PlankControls.d.ts.map +0 -1
  282. package/dist/types/src/containers/Plank/PlankError.d.ts +0 -15
  283. package/dist/types/src/containers/Plank/PlankError.d.ts.map +0 -1
  284. package/dist/types/src/containers/Plank/PlankHeading.d.ts +0 -22
  285. package/dist/types/src/containers/Plank/PlankHeading.d.ts.map +0 -1
  286. package/dist/types/src/containers/Plank/PlankLoading.d.ts +0 -3
  287. package/dist/types/src/containers/Plank/PlankLoading.d.ts.map +0 -1
  288. package/dist/types/src/containers/Plank/PlankRoot.d.ts +0 -37
  289. package/dist/types/src/containers/Plank/PlankRoot.d.ts.map +0 -1
  290. package/dist/types/src/containers/Plank/index.d.ts +0 -4
  291. package/dist/types/src/containers/Plank/index.d.ts.map +0 -1
  292. package/src/components/DeckSettings/DeckSettings.tsx +0 -34
  293. package/src/containers/Plank/Plank.stories.tsx +0 -108
  294. package/src/containers/Plank/Plank.tsx +0 -22
  295. package/src/containers/Plank/PlankComponent.tsx +0 -223
  296. package/src/containers/Plank/PlankContent.tsx +0 -45
  297. package/src/containers/Plank/PlankError.tsx +0 -82
  298. package/src/containers/Plank/PlankHeading.tsx +0 -237
  299. package/src/containers/Plank/PlankLoading.tsx +0 -10
  300. package/src/containers/Plank/PlankRoot.tsx +0 -49
  301. package/src/containers/Plank/index.ts +0 -7
  302. /package/dist/lib/neutral/{add-toast-TNB6DXWU.mjs.map → add-toast-BHNEH5UY.mjs.map} +0 -0
  303. /package/dist/lib/neutral/{check-app-scheme-INSOF72J.mjs.map → check-app-scheme-HSAORHHX.mjs.map} +0 -0
  304. /package/dist/lib/neutral/{chunk-Q4W6B4IB.mjs.map → chunk-FKGYHBUB.mjs.map} +0 -0
  305. /package/dist/lib/neutral/{revert-workspace-B2QLT2C4.mjs.map → revert-workspace-RXWP2TEE.mjs.map} +0 -0
  306. /package/dist/lib/neutral/{scroll-into-view-B52C3PJO.mjs.map → scroll-into-view-HFV5EGYZ.mjs.map} +0 -0
  307. /package/dist/lib/neutral/{set-layout-mode-RPCCPQRB.mjs.map → set-layout-mode-XAGSZZGB.mjs.map} +0 -0
  308. /package/dist/lib/neutral/{update-complementary-7FZNB55J.mjs.map → update-complementary-K55I5EV5.mjs.map} +0 -0
  309. /package/dist/lib/neutral/{update-dialog-FNQTSSAP.mjs.map → update-dialog-Z3GEXMVV.mjs.map} +0 -0
  310. /package/dist/lib/neutral/{update-plank-size-3YW4NXEY.mjs.map → update-plank-size-BTESVV7N.mjs.map} +0 -0
  311. /package/dist/lib/neutral/{update-popover-G2VUD7E6.mjs.map → update-popover-QEVDSZSH.mjs.map} +0 -0
  312. /package/dist/lib/neutral/{update-sidebar-KRHPUHUB.mjs.map → update-sidebar-VSRCN47U.mjs.map} +0 -0
  313. /package/dist/types/src/{components → containers}/DeckSettings/index.d.ts +0 -0
  314. /package/src/{components → containers}/DeckSettings/index.ts +0 -0
package/dx.config.ts ADDED
@@ -0,0 +1,35 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Config2 } from '@dxos/app-framework/config';
6
+ import { trim } from '@dxos/util';
7
+
8
+ export default Config2.make({
9
+ plugin: {
10
+ key: 'org.dxos.plugin.deck',
11
+ name: 'Layout',
12
+ author: 'DXOS',
13
+ description: trim`
14
+ The Deck plugin is the core layout engine for DXOS Composer. It manages the multi-plank
15
+ workspace (the "deck"), sidebar panels, dialogs, popovers, and toast notifications, giving
16
+ users a flexible, persistent workspace they can arrange to match their workflow.
17
+
18
+ In multi mode, subjects are opened as resizable "planks" arranged side by side. Users can
19
+ navigate with stack semantics — opening from a pivot truncates planks to the right and
20
+ appends the new one — or switch to solo or fullscreen mode for focused, distraction-free
21
+ viewing.
22
+
23
+ Layout state (active planks, sidebar visibility, plank sizes, companion pane) is persisted
24
+ across sessions via KVS/localStorage. URL routing is handled by the plugin so that any
25
+ workspace configuration can be bookmarked or shared as a deep link.
26
+
27
+ All layout changes are expressed through typed LayoutOperations (Open, Close, SetLayoutMode,
28
+ UpdateSidebar, UpdateDialog, UpdatePopover, etc.) that any plugin in the system can dispatch,
29
+ keeping the layout logic centralised and easy to extend.
30
+ `,
31
+ icon: { key: 'ph--layout--regular' },
32
+ spec: 'PLUGIN.mdl',
33
+ tags: ['system'],
34
+ },
35
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-deck",
3
- "version": "0.9.0",
3
+ "version": "0.9.1-staging.ee54ba693a",
4
4
  "description": "DXOS Surface plugin for the main application layout.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -86,6 +86,7 @@
86
86
  "types": "dist/types/src/index.d.ts",
87
87
  "files": [
88
88
  "dist",
89
+ "dx.config.ts",
89
90
  "src",
90
91
  "PLUGIN.mdl"
91
92
  ],
@@ -93,63 +94,64 @@
93
94
  "@effect-atom/atom-react": "^0.5.0",
94
95
  "@fluentui/react-tabster": "9.26.11",
95
96
  "@radix-ui/react-context": "1.1.1",
97
+ "@radix-ui/react-slot": "1.1.2",
96
98
  "@tauri-apps/plugin-deep-link": "^2.4.9",
97
99
  "immer": "^10.1.1",
98
- "@dxos/app-framework": "0.9.0",
99
- "@dxos/async": "0.9.0",
100
- "@dxos/app-toolkit": "0.9.0",
101
- "@dxos/context": "0.9.0",
102
- "@dxos/app-graph": "0.9.0",
103
- "@dxos/compute": "0.9.0",
104
- "@dxos/echo": "0.9.0",
105
- "@dxos/effect": "0.9.0",
106
- "@dxos/invariant": "0.9.0",
107
- "@dxos/errors": "0.9.0",
108
- "@dxos/keyboard": "0.9.0",
109
- "@dxos/keys": "0.9.0",
110
- "@dxos/log": "0.9.0",
111
- "@dxos/operation": "0.9.0",
112
- "@dxos/plugin-attention": "0.9.0",
113
- "@dxos/plugin-observability": "0.9.0",
114
- "@dxos/plugin-graph": "0.9.0",
115
- "@dxos/react-ui-attention": "0.9.0",
116
- "@dxos/react-ui-form": "0.9.0",
117
- "@dxos/plugin-client": "0.9.0",
118
- "@dxos/react-ui-menu": "0.9.0",
119
- "@dxos/react-ui-mosaic": "0.9.0",
120
- "@dxos/react-ui-tabs": "0.9.0",
121
- "@dxos/react-ui-text-tooltip": "0.9.0",
122
- "@dxos/react-ui-stack": "0.9.0",
123
- "@dxos/ui-types": "0.9.0",
124
- "@dxos/util": "0.9.0"
100
+ "@dxos/app-toolkit": "0.9.1-staging.ee54ba693a",
101
+ "@dxos/app-framework": "0.9.1-staging.ee54ba693a",
102
+ "@dxos/app-graph": "0.9.1-staging.ee54ba693a",
103
+ "@dxos/context": "0.9.1-staging.ee54ba693a",
104
+ "@dxos/async": "0.9.1-staging.ee54ba693a",
105
+ "@dxos/echo": "0.9.1-staging.ee54ba693a",
106
+ "@dxos/compute": "0.9.1-staging.ee54ba693a",
107
+ "@dxos/invariant": "0.9.1-staging.ee54ba693a",
108
+ "@dxos/errors": "0.9.1-staging.ee54ba693a",
109
+ "@dxos/effect": "0.9.1-staging.ee54ba693a",
110
+ "@dxos/keyboard": "0.9.1-staging.ee54ba693a",
111
+ "@dxos/operation": "0.9.1-staging.ee54ba693a",
112
+ "@dxos/log": "0.9.1-staging.ee54ba693a",
113
+ "@dxos/plugin-attention": "0.9.1-staging.ee54ba693a",
114
+ "@dxos/plugin-graph": "0.9.1-staging.ee54ba693a",
115
+ "@dxos/plugin-client": "0.9.1-staging.ee54ba693a",
116
+ "@dxos/keys": "0.9.1-staging.ee54ba693a",
117
+ "@dxos/plugin-observability": "0.9.1-staging.ee54ba693a",
118
+ "@dxos/react-ui-attention": "0.9.1-staging.ee54ba693a",
119
+ "@dxos/react-ui-dnd": "0.9.1-staging.ee54ba693a",
120
+ "@dxos/react-ui-form": "0.9.1-staging.ee54ba693a",
121
+ "@dxos/react-ui-list": "0.9.1-staging.ee54ba693a",
122
+ "@dxos/react-ui-mosaic": "0.9.1-staging.ee54ba693a",
123
+ "@dxos/react-ui-menu": "0.9.1-staging.ee54ba693a",
124
+ "@dxos/react-ui-tabs": "0.9.1-staging.ee54ba693a",
125
+ "@dxos/util": "0.9.1-staging.ee54ba693a",
126
+ "@dxos/ui-types": "0.9.1-staging.ee54ba693a"
125
127
  },
126
128
  "devDependencies": {
127
129
  "@effect-atom/atom-react": "^0.5.0",
128
- "@effect/platform": "0.96.1",
129
- "@types/react": "~19.2.7",
130
+ "@effect/platform": "0.96.2",
131
+ "@types/react": "~19.2.17",
130
132
  "@types/react-dom": "~19.2.3",
131
- "effect": "3.21.3",
132
- "react": "~19.2.3",
133
- "react-dom": "~19.2.3",
133
+ "effect": "3.21.4",
134
+ "react": "~19.2.7",
135
+ "react-dom": "~19.2.7",
134
136
  "vite": "^8.0.16",
135
- "@dxos/random": "0.9.0",
136
- "@dxos/react-hooks": "0.9.0",
137
- "@dxos/react-ui": "0.9.0",
138
- "@dxos/plugin-testing": "0.9.0",
139
- "@dxos/react-ui-syntax-highlighter": "0.9.0",
140
- "@dxos/schema": "0.9.0",
141
- "@dxos/storybook-utils": "0.9.0",
142
- "@dxos/types": "0.9.0",
143
- "@dxos/ui-theme": "0.9.0"
137
+ "@dxos/plugin-testing": "0.9.1-staging.ee54ba693a",
138
+ "@dxos/react-hooks": "0.9.1-staging.ee54ba693a",
139
+ "@dxos/react-ui": "0.9.1-staging.ee54ba693a",
140
+ "@dxos/random": "0.9.1-staging.ee54ba693a",
141
+ "@dxos/react-ui-syntax-highlighter": "0.9.1-staging.ee54ba693a",
142
+ "@dxos/schema": "0.9.1-staging.ee54ba693a",
143
+ "@dxos/storybook-utils": "0.9.1-staging.ee54ba693a",
144
+ "@dxos/types": "0.9.1-staging.ee54ba693a",
145
+ "@dxos/ui-theme": "0.9.1-staging.ee54ba693a"
144
146
  },
145
147
  "peerDependencies": {
146
148
  "@effect-atom/atom-react": "^0.5.0",
147
- "@effect/platform": "0.96.1",
148
- "effect": "3.21.3",
149
- "react": "~19.2.3",
150
- "react-dom": "~19.2.3",
151
- "@dxos/ui-theme": "0.9.0",
152
- "@dxos/react-ui": "0.9.0"
149
+ "@effect/platform": "0.96.2",
150
+ "effect": "3.21.4",
151
+ "react": "~19.2.7",
152
+ "react-dom": "~19.2.7",
153
+ "@dxos/react-ui": "0.9.1-staging.ee54ba693a",
154
+ "@dxos/ui-theme": "0.9.1-staging.ee54ba693a"
153
155
  },
154
156
  "publishConfig": {
155
157
  "access": "public"
@@ -11,7 +11,7 @@ import { DeckPlugin } from '#plugin';
11
11
 
12
12
  import { meta } from './meta';
13
13
 
14
- const moduleId = (name: string) => `${meta.id}.module.${name}`;
14
+ const moduleId = (name: string) => `${meta.profile.key}.module.${name}`;
15
15
 
16
16
  describe('DeckPlugin', () => {
17
17
  test('modules activate on the expected events', async ({ expect }) => {
package/src/DeckPlugin.ts CHANGED
@@ -6,7 +6,6 @@ import { setAutoFreeze } from 'immer';
6
6
 
7
7
  import { ActivationEvent, ActivationEvents, Plugin } from '@dxos/app-framework';
8
8
  import { AppActivationEvents, AppPlugin } from '@dxos/app-toolkit';
9
- import { translations as stackTranslations } from '@dxos/react-ui-stack/translations';
10
9
 
11
10
  import {
12
11
  AppGraphBuilder,
@@ -35,7 +34,7 @@ export const DeckPlugin = Plugin.define(meta).pipe(
35
34
  AppPlugin.addAppGraphModule({ activate: AppGraphBuilder }),
36
35
  AppPlugin.addOperationHandlerModule({ activate: OperationHandler }),
37
36
  AppPlugin.addSurfaceModule({ activate: ReactSurface }),
38
- AppPlugin.addTranslationsModule({ translations: [...translations, ...stackTranslations] }),
37
+ AppPlugin.addTranslationsModule({ translations }),
39
38
  Plugin.addModule({
40
39
  activatesOn: AppActivationEvents.SetupSettings,
41
40
  firesAfterActivation: [DeckEvents.SettingsReady],
@@ -70,7 +69,7 @@ export const DeckPlugin = Plugin.define(meta).pipe(
70
69
  activate: NotificationTracker,
71
70
  }),
72
71
  AppPlugin.addPluginAssetModule({
73
- asset: { pluginId: meta.id, path: 'PLUGIN.mdl', content: pluginSpec, mimeType: 'application/x-mdl' },
72
+ asset: { pluginId: meta.profile.key, path: 'PLUGIN.mdl', content: pluginSpec, mimeType: 'application/x-mdl' },
74
73
  }),
75
74
  Plugin.make,
76
75
  );
@@ -9,6 +9,7 @@ import { AppCapabilities, AppNode, LayoutOperation } from '@dxos/app-toolkit';
9
9
  import { Operation } from '@dxos/compute';
10
10
  import { AttentionCapabilities } from '@dxos/plugin-attention';
11
11
  import { GraphBuilder, NodeMatcher } from '@dxos/plugin-graph';
12
+ import { Position } from '@dxos/util';
12
13
 
13
14
  import { meta } from '#meta';
14
15
  import { DeckCapabilities } from '#types';
@@ -57,7 +58,7 @@ export default Capability.makeModule(
57
58
  }
58
59
  }),
59
60
  properties: {
60
- label: ['close-current.label', { ns: meta.id }],
61
+ label: ['close-current.label', { ns: meta.profile.key }],
61
62
  icon: 'ph--x--regular',
62
63
  },
63
64
  };
@@ -72,7 +73,7 @@ export default Capability.makeModule(
72
73
  yield* Operation.invoke(LayoutOperation.Close, { subject: ids });
73
74
  }),
74
75
  properties: {
75
- label: ['close-others.label', { ns: meta.id }],
76
+ label: ['close-others.label', { ns: meta.profile.key }],
76
77
  icon: 'ph--x-square--regular',
77
78
  },
78
79
  };
@@ -84,7 +85,7 @@ export default Capability.makeModule(
84
85
  yield* Operation.invoke(LayoutOperation.Close, { subject: deck.active });
85
86
  }),
86
87
  properties: {
87
- label: ['close-all.label', { ns: meta.id }],
88
+ label: ['close-all.label', { ns: meta.profile.key }],
88
89
  icon: 'ph--x-circle--regular',
89
90
  },
90
91
  };
@@ -105,20 +106,20 @@ export default Capability.makeModule(
105
106
  state.sidebarState === 'expanded'
106
107
  ? 'collapse-navigation-sidebar.label'
107
108
  : 'open-navigation-sidebar.label',
108
- { ns: meta.id },
109
+ { ns: meta.profile.key },
109
110
  ],
110
111
  icon: 'ph--sidebar--regular',
111
112
  keyBinding: {
112
113
  macos: "meta+'",
113
114
  },
114
115
  disposition: 'pin-end',
115
- position: 'last',
116
+ position: Position.last,
116
117
  l0Breakpoint: 'lg',
117
118
  },
118
119
  };
119
120
 
120
121
  return !deck?.solo ? [closeCurrent, closeOthers, closeAll, toggleSidebar] : [toggleSidebar];
121
- }),
122
+ }).pipe(Effect.orDie),
122
123
  }),
123
124
  ]);
124
125
 
@@ -5,7 +5,7 @@
5
5
  import * as Effect from 'effect/Effect';
6
6
 
7
7
  import { Capabilities, Capability } from '@dxos/app-framework';
8
- import { APP_SCHEME, AppCapabilities, LayoutOperation } from '@dxos/app-toolkit';
8
+ import { AppCapabilities, LayoutOperation, NativePasskey } from '@dxos/app-toolkit';
9
9
  import { EffectEx } from '@dxos/effect';
10
10
  import { isTauri } from '@dxos/util';
11
11
 
@@ -24,7 +24,7 @@ const isSafari = (): boolean => {
24
24
  /** Check if the current page URL can be converted to a valid custom scheme URL. */
25
25
  const canRedirectToScheme = (): boolean => {
26
26
  try {
27
- const schemeUrl = APP_SCHEME + window.location.pathname.replace(/^\/+/, '') + window.location.search;
27
+ const schemeUrl = NativePasskey.APP_SCHEME + window.location.pathname.replace(/^\/+/, '') + window.location.search;
28
28
  new URL(schemeUrl);
29
29
  return true;
30
30
  } catch {
@@ -63,7 +63,7 @@ const tryOpenNativeApp = (): Promise<boolean> => {
63
63
  document.addEventListener('visibilitychange', onVisibilityChange);
64
64
 
65
65
  // Try the scheme via hidden iframe.
66
- const schemeUrl = APP_SCHEME + window.location.pathname.replace(/^\/+/, '') + window.location.search;
66
+ const schemeUrl = NativePasskey.APP_SCHEME + window.location.pathname.replace(/^\/+/, '') + window.location.search;
67
67
  const iframe = document.createElement('iframe');
68
68
  iframe.style.display = 'none';
69
69
  iframe.src = schemeUrl;
@@ -4,11 +4,13 @@
4
4
 
5
5
  import * as Effect from 'effect/Effect';
6
6
  import * as Fiber from 'effect/Fiber';
7
+ import * as Option from 'effect/Option';
7
8
  import * as Stream from 'effect/Stream';
8
9
 
9
10
  import { Capabilities, Capability, type PluginManager } from '@dxos/app-framework';
10
11
  import { type LayoutOperation, SettingsOperation } from '@dxos/app-toolkit';
11
12
  import { Process } from '@dxos/compute';
13
+ import { Annotation } from '@dxos/echo';
12
14
 
13
15
  import { meta } from '#meta';
14
16
  import { DeckCapabilities } from '#types';
@@ -56,7 +58,7 @@ export default Capability.makeModule(
56
58
  continue;
57
59
  }
58
60
 
59
- const notify = process.params.notify;
61
+ const notify = Option.getOrNull(Annotation.getDictionary(process.params.annotations, Process.NotifyAnnotation));
60
62
  if (!notify) {
61
63
  continue;
62
64
  }
@@ -105,12 +107,12 @@ export default Capability.makeModule(
105
107
  // Replace any stale plugin-failure toast so at most one is ever visible.
106
108
  const toast: LayoutOperation.Toast = {
107
109
  id: 'plugin-failure',
108
- title: ['plugin-failure.title', { ns: meta.id }],
109
- description: ['plugin-failure.description', { ns: meta.id }],
110
+ title: ['plugin-failure.title', { ns: meta.profile.key }],
111
+ description: ['plugin-failure.description', { ns: meta.profile.key }],
110
112
  icon: 'ph--warning--regular',
111
113
  duration: ERROR_TOAST_DURATION,
112
- actionLabel: ['plugin-failure-action.label', { ns: meta.id }],
113
- actionAlt: ['plugin-failure-action.alt', { ns: meta.id }],
114
+ actionLabel: ['plugin-failure-action.label', { ns: meta.profile.key }],
115
+ actionAlt: ['plugin-failure-action.alt', { ns: meta.profile.key }],
114
116
  onAction: () => void invoker.invokePromise(SettingsOperation.OpenPluginRegistry),
115
117
  };
116
118
  const state = registry.get(ephemeralAtom);
@@ -135,11 +137,11 @@ export default Capability.makeModule(
135
137
  : state.toasts;
136
138
  const toast: LayoutOperation.Toast = {
137
139
  id: undoId,
138
- title: message ?? ['undo-available.label', { ns: meta.id }],
140
+ title: message ?? ['undo-available.label', { ns: meta.profile.key }],
139
141
  duration: UNDO_TOAST_DURATION,
140
- actionLabel: ['undo-action.label', { ns: meta.id }],
141
- actionAlt: ['undo-action.alt', { ns: meta.id }],
142
- closeLabel: ['undo-close.label', { ns: meta.id }],
142
+ actionLabel: ['undo-action.label', { ns: meta.profile.key }],
143
+ actionAlt: ['undo-action.alt', { ns: meta.profile.key }],
144
+ closeLabel: ['undo-close.label', { ns: meta.profile.key }],
143
145
  onAction: onUndo,
144
146
  };
145
147
  registry.set(ephemeralAtom, { ...state, currentUndoId: undoId, toasts: [...toasts, toast] });
@@ -14,7 +14,7 @@ import { meta } from '#meta';
14
14
  export default Capability.makeModule(() =>
15
15
  Effect.succeed(
16
16
  Capability.contributes(Capabilities.ReactRoot, {
17
- id: meta.id,
17
+ id: meta.profile.key,
18
18
  root: () => {
19
19
  const { state, updateEphemeral } = useDeckState();
20
20
 
@@ -7,10 +7,10 @@ import React from 'react';
7
7
 
8
8
  import { Capabilities, Capability } from '@dxos/app-framework';
9
9
  import { Surface, useSettingsState } from '@dxos/app-framework/ui';
10
- import { NOT_FOUND_PATH } from '@dxos/app-toolkit';
10
+ import { NotFound } from '@dxos/app-toolkit';
11
11
  import { AppSurface, NotFoundArticle } from '@dxos/app-toolkit/ui';
12
12
 
13
- import { DeckSettings } from '#components';
13
+ import { DeckSettings } from '#containers';
14
14
  import { meta } from '#meta';
15
15
  import { type Settings } from '#types';
16
16
 
@@ -19,7 +19,7 @@ export default Capability.makeModule(() =>
19
19
  Capability.contributes(Capabilities.ReactSurface, [
20
20
  Surface.create({
21
21
  id: 'pluginSettings',
22
- filter: AppSurface.settings(AppSurface.Article, meta.id),
22
+ filter: AppSurface.settings(AppSurface.Article, meta.profile.key),
23
23
  component: ({ data: { subject } }) => {
24
24
  const { settings, updateSettings } = useSettingsState<Settings.Settings>(subject.atom);
25
25
  return <DeckSettings settings={settings} onSettingsChange={updateSettings} />;
@@ -27,8 +27,7 @@ export default Capability.makeModule(() =>
27
27
  }),
28
28
  Surface.create({
29
29
  id: 'notFound',
30
- role: 'article',
31
- filter: (data): data is { attendableId: string } => data.attendableId === NOT_FOUND_PATH,
30
+ filter: Surface.makeFilter(AppSurface.Article, (data) => data.attendableId === NotFound.NOT_FOUND_PATH),
32
31
  component: () => <NotFoundArticle />,
33
32
  }),
34
33
  ]),
@@ -14,7 +14,7 @@ import { DeckCapabilities, Settings } from '#types';
14
14
  export default Capability.makeModule(() =>
15
15
  Effect.sync(() => {
16
16
  const settingsAtom = createKvsStore({
17
- key: meta.id,
17
+ key: meta.profile.key,
18
18
  schema: Settings.Settings,
19
19
  defaultValue: () => ({
20
20
  showHints: false,
@@ -27,7 +27,7 @@ export default Capability.makeModule(() =>
27
27
  return [
28
28
  Capability.contributes(DeckCapabilities.Settings, settingsAtom),
29
29
  Capability.contributes(AppCapabilities.Settings, {
30
- prefix: meta.id,
30
+ prefix: meta.profile.key,
31
31
  schema: Settings.Settings,
32
32
  atom: settingsAtom,
33
33
  }),
@@ -49,7 +49,7 @@ export default Capability.makeModule(
49
49
 
50
50
  // Persisted state using KVS store.
51
51
  const stateAtom = createKvsStore({
52
- key: `${meta.id}.state`,
52
+ key: `${meta.profile.key}.state`,
53
53
  schema: StoredDeckState,
54
54
  defaultValue: () => ({ ...defaultDeckState }),
55
55
  });
@@ -5,15 +5,7 @@
5
5
  import * as Effect from 'effect/Effect';
6
6
 
7
7
  import { Capabilities, Capability } from '@dxos/app-framework';
8
- import {
9
- AppCapabilities,
10
- LayoutOperation,
11
- NOT_FOUND_PATH,
12
- expandPath,
13
- fromUrlPath,
14
- getWorkspaceFromPath,
15
- toUrlPath,
16
- } from '@dxos/app-toolkit';
8
+ import { AppCapabilities, LayoutOperation, NotFound, Paths } from '@dxos/app-toolkit';
17
9
  import { Operation } from '@dxos/compute';
18
10
  import { EffectEx } from '@dxos/effect';
19
11
  import { invariant } from '@dxos/invariant';
@@ -91,8 +83,8 @@ export default Capability.makeModule(
91
83
  return;
92
84
  }
93
85
 
94
- const qualifiedId = fromUrlPath(pathname);
95
- const workspace = getWorkspaceFromPath(qualifiedId);
86
+ const qualifiedId = Paths.fromUrlPath(pathname);
87
+ const workspace = Paths.getWorkspaceFromPath(qualifiedId);
96
88
  if (workspace !== Node.RootId && workspace !== state.activeDeck) {
97
89
  yield* Operation.invoke(LayoutOperation.SwitchWorkspace, { subject: workspace });
98
90
  }
@@ -110,10 +102,10 @@ export default Capability.makeModule(
110
102
  mode: 'solo',
111
103
  });
112
104
  }
113
- } else if (deck.solo && deck.solo !== NOT_FOUND_PATH) {
105
+ } else if (deck.solo && deck.solo !== NotFound.NOT_FOUND_PATH) {
114
106
  // Stay in solo mode; redirect URL to reflect the current solo item.
115
107
  // Do not switch to deck mode here — only explicit user action should change layout mode.
116
- const path = toUrlPath(deck.solo);
108
+ const path = Paths.toUrlPath(deck.solo);
117
109
  if (window.location.pathname !== path) {
118
110
  history.replaceState(null, '', `${path}${stripPlanks(window.location.search)}`);
119
111
  }
@@ -122,7 +114,7 @@ export default Capability.makeModule(
122
114
  const plankIds = deserializePlanks(resolvedUrl);
123
115
  if (plankIds.length > 0) {
124
116
  for (const plankId of plankIds) {
125
- expandPath(graph, plankId);
117
+ NotFound.expandPath(graph, plankId);
126
118
  }
127
119
  updateState((state) => updateActiveDeck(state, { active: plankIds, initialized: true }));
128
120
  }
@@ -203,7 +195,7 @@ export default Capability.makeModule(
203
195
  lastActiveDeck = activeDeck;
204
196
  lastActiveKey = activeKey;
205
197
 
206
- const path = solo && solo !== NOT_FOUND_PATH ? toUrlPath(solo) : toUrlPath(activeDeck);
198
+ const path = solo && solo !== NotFound.NOT_FOUND_PATH ? Paths.toUrlPath(solo) : Paths.toUrlPath(activeDeck);
207
199
  const search = !solo
208
200
  ? serializePlanks(deck.active, window.location.search)
209
201
  : stripPlanks(window.location.search);
@@ -0,0 +1,91 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import React, { type ReactNode, useMemo } from 'react';
6
+
7
+ import { Surface } from '@dxos/app-framework/ui';
8
+ import { AppSurface } from '@dxos/app-toolkit/ui';
9
+ import { type Node } from '@dxos/plugin-graph';
10
+ import { type ThemedClassName, toLocalizedString, useTranslation } from '@dxos/react-ui';
11
+ import { getLinkedVariant } from '@dxos/react-ui-attention';
12
+ import { mx } from '@dxos/ui-theme';
13
+
14
+ import { meta } from '#meta';
15
+
16
+ import { Pane, type PaneTab } from '../Pane';
17
+
18
+ //
19
+ // Companion
20
+ //
21
+ // A higher-level companion pane bound to a set of companion {@link Node}s: a {@link Pane} whose toolbar
22
+ // holds the companion tab strip and whose body renders the companions' content Surfaces. All panels stay
23
+ // mounted (inactive hidden) so switching tabs preserves each companion's state. Shares attention with the
24
+ // primary plank via `attendableId`. Controls (e.g. close) are supplied by the container.
25
+ //
26
+
27
+ export type CompanionProps = ThemedClassName<{
28
+ companions: Node.Node[];
29
+ /** Selected companion id. */
30
+ value?: string;
31
+ onValueChange?: (id: string) => void;
32
+ /** Primary plank attendable id; the companion shares its attention. */
33
+ attendableId?: string;
34
+ /** Primary plank subject; companion Article surfaces filter on (and operate against) `companionTo`. */
35
+ companionTo?: unknown;
36
+ /** Toolbar controls rendered after the tabs (e.g. close). */
37
+ controls?: ReactNode;
38
+ }>;
39
+
40
+ export const Companion = ({
41
+ classNames,
42
+ companions,
43
+ value,
44
+ onValueChange,
45
+ attendableId,
46
+ companionTo,
47
+ controls,
48
+ }: CompanionProps) => {
49
+ const { t } = useTranslation(meta.profile.key);
50
+
51
+ // Fall back to the first companion when uncontrolled so a panel is always visible.
52
+ const selected = value ?? companions[0]?.id;
53
+ const tabs = useMemo<PaneTab[]>(
54
+ () =>
55
+ companions.map((node) => ({
56
+ id: node.id,
57
+ icon: node.properties?.icon ?? 'ph--circle-dashed--regular',
58
+ label: toLocalizedString(node.properties?.label ?? '', t),
59
+ })),
60
+ [companions, t],
61
+ );
62
+
63
+ // Stable per-companion data objects so companion article surfaces don't receive a new prop reference on
64
+ // every parent re-render (the same pattern as the inline data fix in Plank).
65
+ const companionDataList = useMemo(
66
+ () =>
67
+ companions.map((node) => ({
68
+ attendableId,
69
+ subject: node.data,
70
+ companionTo,
71
+ variant: getLinkedVariant(node.id),
72
+ properties: node.properties,
73
+ })),
74
+ [companions, attendableId, companionTo],
75
+ );
76
+
77
+ return (
78
+ <Pane.Root classNames={classNames}>
79
+ <Pane.Toolbar>
80
+ <Pane.Tabs tabs={tabs} value={selected} onValueChange={onValueChange} attendableId={attendableId} related />
81
+ {controls}
82
+ </Pane.Toolbar>
83
+ {/* Panels stay mounted; the inactive ones are hidden so switching companions preserves their state. */}
84
+ {companions.map((node, index) => (
85
+ <Pane.Content key={node.id} classNames={mx(node.id !== selected && 'hidden')}>
86
+ <Surface.Surface type={AppSurface.Article} data={companionDataList[index]} limit={1} />
87
+ </Pane.Content>
88
+ ))}
89
+ </Pane.Root>
90
+ );
91
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export * from './Companion';