@dxos/plugin-deck 0.8.4-main.f5c0578 → 0.8.4-main.fcfe5033a5

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 (479) hide show
  1. package/dist/lib/browser/add-toast-3V7TYC2M.mjs +24 -0
  2. package/dist/lib/browser/add-toast-3V7TYC2M.mjs.map +7 -0
  3. package/dist/lib/browser/adjust-ZMPN7P7J.mjs +96 -0
  4. package/dist/lib/browser/adjust-ZMPN7P7J.mjs.map +7 -0
  5. package/dist/lib/browser/change-companion-F7GCREGM.mjs +34 -0
  6. package/dist/lib/browser/change-companion-F7GCREGM.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-BRZAVPMC.mjs +48 -0
  8. package/dist/lib/browser/chunk-BRZAVPMC.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-DF2VZ6W3.mjs +69 -0
  10. package/dist/lib/browser/chunk-DF2VZ6W3.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-FUWSZ6IC.mjs +88 -0
  12. package/dist/lib/browser/chunk-FUWSZ6IC.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-GN52IRQ7.mjs +216 -0
  14. package/dist/lib/browser/chunk-GN52IRQ7.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
  16. package/dist/lib/browser/chunk-KUTDCWZF.mjs +30 -0
  17. package/dist/lib/browser/chunk-KUTDCWZF.mjs.map +7 -0
  18. package/dist/lib/browser/close-N2F26CVG.mjs +44 -0
  19. package/dist/lib/browser/close-N2F26CVG.mjs.map +7 -0
  20. package/dist/lib/browser/index.mjs +161 -134
  21. package/dist/lib/browser/index.mjs.map +4 -4
  22. package/dist/lib/browser/meta.json +1 -1
  23. package/dist/lib/browser/open-VWO7VOOU.mjs +150 -0
  24. package/dist/lib/browser/open-VWO7VOOU.mjs.map +7 -0
  25. package/dist/lib/browser/operations/index.mjs +13 -0
  26. package/dist/lib/browser/operations/index.mjs.map +7 -0
  27. package/dist/lib/browser/revert-workspace-LGKZZKCI.mjs +21 -0
  28. package/dist/lib/browser/revert-workspace-LGKZZKCI.mjs.map +7 -0
  29. package/dist/lib/browser/scroll-into-view-TSVSNKIH.mjs +21 -0
  30. package/dist/lib/browser/scroll-into-view-TSVSNKIH.mjs.map +7 -0
  31. package/dist/lib/browser/set-N2LGA2BY.mjs +37 -0
  32. package/dist/lib/browser/set-N2LGA2BY.mjs.map +7 -0
  33. package/dist/lib/browser/set-layout-mode-TONTQO6G.mjs +90 -0
  34. package/dist/lib/browser/set-layout-mode-TONTQO6G.mjs.map +7 -0
  35. package/dist/lib/browser/show-undo-IFXNEIQY.mjs +59 -0
  36. package/dist/lib/browser/show-undo-IFXNEIQY.mjs.map +7 -0
  37. package/dist/lib/browser/switch-workspace-ZJDC5SSR.mjs +68 -0
  38. package/dist/lib/browser/switch-workspace-ZJDC5SSR.mjs.map +7 -0
  39. package/dist/lib/browser/types/index.mjs +12 -12
  40. package/dist/lib/browser/update-complementary-ELUOK3GD.mjs +28 -0
  41. package/dist/lib/browser/update-complementary-ELUOK3GD.mjs.map +7 -0
  42. package/dist/lib/browser/update-dialog-LMGLOTWX.mjs +29 -0
  43. package/dist/lib/browser/update-dialog-LMGLOTWX.mjs.map +7 -0
  44. package/dist/lib/browser/update-plank-size-WQAPELII.mjs +28 -0
  45. package/dist/lib/browser/update-plank-size-WQAPELII.mjs.map +7 -0
  46. package/dist/lib/browser/update-popover-P6YO6FWJ.mjs +33 -0
  47. package/dist/lib/browser/update-popover-P6YO6FWJ.mjs.map +7 -0
  48. package/dist/lib/browser/update-sidebar-NGWS6IDJ.mjs +25 -0
  49. package/dist/lib/browser/update-sidebar-NGWS6IDJ.mjs.map +7 -0
  50. package/dist/lib/node-esm/add-toast-G4OQEGOS.mjs +25 -0
  51. package/dist/lib/node-esm/add-toast-G4OQEGOS.mjs.map +7 -0
  52. package/dist/lib/node-esm/adjust-KSNI7C3B.mjs +97 -0
  53. package/dist/lib/node-esm/adjust-KSNI7C3B.mjs.map +7 -0
  54. package/dist/lib/node-esm/change-companion-LCJPT6AX.mjs +35 -0
  55. package/dist/lib/node-esm/change-companion-LCJPT6AX.mjs.map +7 -0
  56. package/dist/lib/node-esm/chunk-4ED7B7OZ.mjs +217 -0
  57. package/dist/lib/node-esm/chunk-4ED7B7OZ.mjs.map +7 -0
  58. package/dist/lib/node-esm/chunk-7KL65RLL.mjs +89 -0
  59. package/dist/lib/node-esm/chunk-7KL65RLL.mjs.map +7 -0
  60. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
  61. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
  62. package/dist/lib/node-esm/chunk-IRWCUYJY.mjs +71 -0
  63. package/dist/lib/node-esm/chunk-IRWCUYJY.mjs.map +7 -0
  64. package/dist/lib/node-esm/chunk-MB4SDDVY.mjs +50 -0
  65. package/dist/lib/node-esm/chunk-MB4SDDVY.mjs.map +7 -0
  66. package/dist/lib/node-esm/chunk-MLVJ2ODW.mjs +32 -0
  67. package/dist/lib/node-esm/chunk-MLVJ2ODW.mjs.map +7 -0
  68. package/dist/lib/node-esm/close-YHIBVE2S.mjs +45 -0
  69. package/dist/lib/node-esm/close-YHIBVE2S.mjs.map +7 -0
  70. package/dist/lib/node-esm/index.mjs +202 -0
  71. package/dist/lib/node-esm/index.mjs.map +7 -0
  72. package/dist/lib/node-esm/meta.json +1 -0
  73. package/dist/lib/node-esm/open-353DYMMN.mjs +151 -0
  74. package/dist/lib/node-esm/open-353DYMMN.mjs.map +7 -0
  75. package/dist/lib/node-esm/operations/index.mjs +14 -0
  76. package/dist/lib/node-esm/operations/index.mjs.map +7 -0
  77. package/dist/lib/node-esm/revert-workspace-OS5R3PFJ.mjs +22 -0
  78. package/dist/lib/node-esm/revert-workspace-OS5R3PFJ.mjs.map +7 -0
  79. package/dist/lib/node-esm/scroll-into-view-LC2SVKCW.mjs +22 -0
  80. package/dist/lib/node-esm/scroll-into-view-LC2SVKCW.mjs.map +7 -0
  81. package/dist/lib/node-esm/set-3EZ7LJFU.mjs +38 -0
  82. package/dist/lib/node-esm/set-3EZ7LJFU.mjs.map +7 -0
  83. package/dist/lib/node-esm/set-layout-mode-3YBHGEK6.mjs +91 -0
  84. package/dist/lib/node-esm/set-layout-mode-3YBHGEK6.mjs.map +7 -0
  85. package/dist/lib/node-esm/show-undo-RAHLRPUU.mjs +60 -0
  86. package/dist/lib/node-esm/show-undo-RAHLRPUU.mjs.map +7 -0
  87. package/dist/lib/node-esm/switch-workspace-S6CXDPXZ.mjs +69 -0
  88. package/dist/lib/node-esm/switch-workspace-S6CXDPXZ.mjs.map +7 -0
  89. package/dist/lib/node-esm/types/index.mjs +33 -0
  90. package/dist/lib/node-esm/types/index.mjs.map +7 -0
  91. package/dist/lib/node-esm/update-complementary-V5Y2RMYL.mjs +29 -0
  92. package/dist/lib/node-esm/update-complementary-V5Y2RMYL.mjs.map +7 -0
  93. package/dist/lib/node-esm/update-dialog-IMTCLAWR.mjs +30 -0
  94. package/dist/lib/node-esm/update-dialog-IMTCLAWR.mjs.map +7 -0
  95. package/dist/lib/node-esm/update-plank-size-I3DKCPHZ.mjs +29 -0
  96. package/dist/lib/node-esm/update-plank-size-I3DKCPHZ.mjs.map +7 -0
  97. package/dist/lib/node-esm/update-popover-7JX3KWYL.mjs +34 -0
  98. package/dist/lib/node-esm/update-popover-7JX3KWYL.mjs.map +7 -0
  99. package/dist/lib/node-esm/update-sidebar-B5DCSREP.mjs +26 -0
  100. package/dist/lib/node-esm/update-sidebar-B5DCSREP.mjs.map +7 -0
  101. package/dist/types/src/DeckPlugin.d.ts +2 -1
  102. package/dist/types/src/DeckPlugin.d.ts.map +1 -1
  103. package/dist/types/src/capabilities/app-graph-builder.d.ts +4 -2
  104. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  105. package/dist/types/src/capabilities/check-app-scheme.d.ts +17 -2
  106. package/dist/types/src/capabilities/check-app-scheme.d.ts.map +1 -1
  107. package/dist/types/src/capabilities/index.d.ts +196 -12
  108. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  109. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  110. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  111. package/dist/types/src/capabilities/react-root.d.ts +4 -2
  112. package/dist/types/src/capabilities/react-root.d.ts.map +1 -1
  113. package/dist/types/src/capabilities/react-surface.d.ts +3 -2
  114. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  115. package/dist/types/src/capabilities/settings.d.ts +5 -2
  116. package/dist/types/src/capabilities/settings.d.ts.map +1 -1
  117. package/dist/types/src/capabilities/state.d.ts +134 -44
  118. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  119. package/dist/types/src/capabilities/tools.d.ts +4 -3
  120. package/dist/types/src/capabilities/tools.d.ts.map +1 -1
  121. package/dist/types/src/capabilities/url-handler.d.ts +3 -2
  122. package/dist/types/src/capabilities/url-handler.d.ts.map +1 -1
  123. package/dist/types/src/components/DeckSettings/DeckSettings.d.ts +4 -4
  124. package/dist/types/src/components/DeckSettings/DeckSettings.d.ts.map +1 -1
  125. package/dist/types/src/components/DeckSettings/DeckSettings.stories.d.ts +71 -0
  126. package/dist/types/src/components/DeckSettings/DeckSettings.stories.d.ts.map +1 -0
  127. package/dist/types/src/components/DeckSettings/index.d.ts +1 -1
  128. package/dist/types/src/components/DeckSettings/index.d.ts.map +1 -1
  129. package/dist/types/src/components/Matrix/Matrix.d.ts +41 -0
  130. package/dist/types/src/components/Matrix/Matrix.d.ts.map +1 -0
  131. package/dist/types/src/components/Matrix/Matrix.stories.d.ts +17 -0
  132. package/dist/types/src/components/Matrix/Matrix.stories.d.ts.map +1 -0
  133. package/dist/types/src/components/Matrix/index.d.ts +3 -0
  134. package/dist/types/src/components/Matrix/index.d.ts.map +1 -0
  135. package/dist/types/src/components/index.d.ts +3 -2
  136. package/dist/types/src/components/index.d.ts.map +1 -1
  137. package/dist/types/src/containers/Deck/Banner.d.ts.map +1 -0
  138. package/dist/types/src/containers/Deck/Deck.d.ts +25 -0
  139. package/dist/types/src/containers/Deck/Deck.d.ts.map +1 -0
  140. package/dist/types/src/containers/Deck/Deck.stories.d.ts +71 -0
  141. package/dist/types/src/containers/Deck/Deck.stories.d.ts.map +1 -0
  142. package/dist/types/src/containers/Deck/DeckContent.d.ts +7 -0
  143. package/dist/types/src/containers/Deck/DeckContent.d.ts.map +1 -0
  144. package/dist/types/src/containers/Deck/DeckRoot.d.ts +42 -0
  145. package/dist/types/src/containers/Deck/DeckRoot.d.ts.map +1 -0
  146. package/dist/types/src/containers/Deck/DeckViewport.d.ts +19 -0
  147. package/dist/types/src/containers/Deck/DeckViewport.d.ts.map +1 -0
  148. package/dist/types/src/containers/Deck/StatusBar.d.ts.map +1 -0
  149. package/dist/types/src/containers/Deck/index.d.ts +2 -0
  150. package/dist/types/src/containers/Deck/index.d.ts.map +1 -0
  151. package/dist/types/src/containers/DeckLayout/ActiveNode.d.ts.map +1 -0
  152. package/dist/types/src/containers/DeckLayout/DeckLayout.d.ts +5 -0
  153. package/dist/types/src/containers/DeckLayout/DeckLayout.d.ts.map +1 -0
  154. package/dist/types/src/containers/DeckLayout/DeckLayout.stories.d.ts +73 -0
  155. package/dist/types/src/containers/DeckLayout/DeckLayout.stories.d.ts.map +1 -0
  156. package/dist/types/src/containers/DeckLayout/Dialog.d.ts.map +1 -0
  157. package/dist/types/src/containers/DeckLayout/Fallback.d.ts +2 -0
  158. package/dist/types/src/containers/DeckLayout/Fallback.d.ts.map +1 -0
  159. package/dist/types/src/containers/DeckLayout/Popover.d.ts +5 -0
  160. package/dist/types/src/containers/DeckLayout/Popover.d.ts.map +1 -0
  161. package/dist/types/src/containers/DeckLayout/Toast.d.ts +10 -0
  162. package/dist/types/src/containers/DeckLayout/Toast.d.ts.map +1 -0
  163. package/dist/types/src/containers/DeckLayout/constants.d.ts.map +1 -0
  164. package/dist/types/src/containers/DeckLayout/index.d.ts +4 -0
  165. package/dist/types/src/containers/DeckLayout/index.d.ts.map +1 -0
  166. package/dist/types/src/containers/Plank/Plank.d.ts +17 -0
  167. package/dist/types/src/containers/Plank/Plank.d.ts.map +1 -0
  168. package/dist/types/src/containers/Plank/Plank.stories.d.ts +71 -0
  169. package/dist/types/src/containers/Plank/Plank.stories.d.ts.map +1 -0
  170. package/dist/types/src/containers/Plank/PlankComponent.d.ts +17 -0
  171. package/dist/types/src/containers/Plank/PlankComponent.d.ts.map +1 -0
  172. package/dist/types/src/containers/Plank/PlankContent.d.ts +10 -0
  173. package/dist/types/src/containers/Plank/PlankContent.d.ts.map +1 -0
  174. package/dist/types/src/{components → containers}/Plank/PlankControls.d.ts +5 -6
  175. package/dist/types/src/containers/Plank/PlankControls.d.ts.map +1 -0
  176. package/dist/types/src/containers/Plank/PlankError.d.ts +15 -0
  177. package/dist/types/src/containers/Plank/PlankError.d.ts.map +1 -0
  178. package/dist/types/src/{components → containers}/Plank/PlankHeading.d.ts +5 -4
  179. package/dist/types/src/containers/Plank/PlankHeading.d.ts.map +1 -0
  180. package/dist/types/src/{components → containers}/Plank/PlankLoading.d.ts.map +1 -1
  181. package/dist/types/src/containers/Plank/PlankRoot.d.ts +37 -0
  182. package/dist/types/src/containers/Plank/PlankRoot.d.ts.map +1 -0
  183. package/dist/types/src/containers/Plank/index.d.ts +4 -0
  184. package/dist/types/src/containers/Plank/index.d.ts.map +1 -0
  185. package/dist/types/src/containers/Sidebar/ComplementarySidebar.d.ts.map +1 -0
  186. package/dist/types/src/containers/Sidebar/Sidebar.d.ts.map +1 -0
  187. package/dist/types/src/containers/Sidebar/SidebarButton.d.ts.map +1 -0
  188. package/dist/types/src/{components → containers}/Sidebar/index.d.ts.map +1 -1
  189. package/dist/types/src/containers/index.d.ts +6 -0
  190. package/dist/types/src/containers/index.d.ts.map +1 -0
  191. package/dist/types/src/hooks/index.d.ts +2 -0
  192. package/dist/types/src/hooks/index.d.ts.map +1 -1
  193. package/dist/types/src/hooks/useDeckCompanions.d.ts +3 -4
  194. package/dist/types/src/hooks/useDeckCompanions.d.ts.map +1 -1
  195. package/dist/types/src/hooks/useDeckState.d.ts +17 -0
  196. package/dist/types/src/hooks/useDeckState.d.ts.map +1 -0
  197. package/dist/types/src/hooks/useHoistStatusbar.d.ts +1 -1
  198. package/dist/types/src/hooks/useHoistStatusbar.d.ts.map +1 -1
  199. package/dist/types/src/hooks/useMainSize.d.ts +2 -2
  200. package/dist/types/src/hooks/useNodeActionExpander.d.ts +1 -1
  201. package/dist/types/src/hooks/useNodeActionExpander.d.ts.map +1 -1
  202. package/dist/types/src/hooks/useSelectedCompanion.d.ts +13 -0
  203. package/dist/types/src/hooks/useSelectedCompanion.d.ts.map +1 -0
  204. package/dist/types/src/index.d.ts +1 -2
  205. package/dist/types/src/index.d.ts.map +1 -1
  206. package/dist/types/src/layout.d.ts +20 -9
  207. package/dist/types/src/layout.d.ts.map +1 -1
  208. package/dist/types/src/layout.test.d.ts +2 -0
  209. package/dist/types/src/layout.test.d.ts.map +1 -0
  210. package/dist/types/src/meta.d.ts +2 -3
  211. package/dist/types/src/meta.d.ts.map +1 -1
  212. package/dist/types/src/operations/add-toast.d.ts +5 -0
  213. package/dist/types/src/operations/add-toast.d.ts.map +1 -0
  214. package/dist/types/src/operations/adjust.d.ts +5 -0
  215. package/dist/types/src/operations/adjust.d.ts.map +1 -0
  216. package/dist/types/src/operations/change-companion.d.ts +5 -0
  217. package/dist/types/src/operations/change-companion.d.ts.map +1 -0
  218. package/dist/types/src/operations/close.d.ts +5 -0
  219. package/dist/types/src/operations/close.d.ts.map +1 -0
  220. package/dist/types/src/operations/definitions.d.ts +18 -0
  221. package/dist/types/src/operations/definitions.d.ts.map +1 -0
  222. package/dist/types/src/operations/helpers.d.ts +3 -0
  223. package/dist/types/src/operations/helpers.d.ts.map +1 -0
  224. package/dist/types/src/operations/index.d.ts +4 -0
  225. package/dist/types/src/operations/index.d.ts.map +1 -0
  226. package/dist/types/src/operations/open.d.ts +5 -0
  227. package/dist/types/src/operations/open.d.ts.map +1 -0
  228. package/dist/types/src/operations/revert-workspace.d.ts +5 -0
  229. package/dist/types/src/operations/revert-workspace.d.ts.map +1 -0
  230. package/dist/types/src/operations/scroll-into-view.d.ts +5 -0
  231. package/dist/types/src/operations/scroll-into-view.d.ts.map +1 -0
  232. package/dist/types/src/operations/set-layout-mode.d.ts +9 -0
  233. package/dist/types/src/operations/set-layout-mode.d.ts.map +1 -0
  234. package/dist/types/src/operations/set.d.ts +5 -0
  235. package/dist/types/src/operations/set.d.ts.map +1 -0
  236. package/dist/types/src/operations/show-undo.d.ts +5 -0
  237. package/dist/types/src/operations/show-undo.d.ts.map +1 -0
  238. package/dist/types/src/operations/switch-workspace.d.ts +5 -0
  239. package/dist/types/src/operations/switch-workspace.d.ts.map +1 -0
  240. package/dist/types/src/operations/update-complementary.d.ts +5 -0
  241. package/dist/types/src/operations/update-complementary.d.ts.map +1 -0
  242. package/dist/types/src/operations/update-dialog.d.ts +5 -0
  243. package/dist/types/src/operations/update-dialog.d.ts.map +1 -0
  244. package/dist/types/src/operations/update-plank-size.d.ts +5 -0
  245. package/dist/types/src/operations/update-plank-size.d.ts.map +1 -0
  246. package/dist/types/src/operations/update-popover.d.ts +5 -0
  247. package/dist/types/src/operations/update-popover.d.ts.map +1 -0
  248. package/dist/types/src/operations/update-sidebar.d.ts +5 -0
  249. package/dist/types/src/operations/update-sidebar.d.ts.map +1 -0
  250. package/dist/types/src/translations.d.ts +52 -52
  251. package/dist/types/src/translations.d.ts.map +1 -1
  252. package/dist/types/src/types/Settings.d.ts +11 -0
  253. package/dist/types/src/types/Settings.d.ts.map +1 -0
  254. package/dist/types/src/{capabilities → types}/capabilities.d.ts +103 -96
  255. package/dist/types/src/types/capabilities.d.ts.map +1 -0
  256. package/dist/types/src/types/events.d.ts +7 -0
  257. package/dist/types/src/types/events.d.ts.map +1 -0
  258. package/dist/types/src/types/index.d.ts +3 -0
  259. package/dist/types/src/types/index.d.ts.map +1 -1
  260. package/dist/types/src/types/schema.d.ts +68 -56
  261. package/dist/types/src/types/schema.d.ts.map +1 -1
  262. package/dist/types/src/util/index.d.ts +2 -1
  263. package/dist/types/src/util/index.d.ts.map +1 -1
  264. package/dist/types/src/util/layoutAppliesTopbar.d.ts +1 -1
  265. package/dist/types/src/util/layoutAppliesTopbar.d.ts.map +1 -1
  266. package/dist/types/src/util/plank-url-params.d.ts +14 -0
  267. package/dist/types/src/util/plank-url-params.d.ts.map +1 -0
  268. package/dist/types/src/util/plank-url-params.test.d.ts +2 -0
  269. package/dist/types/src/util/plank-url-params.test.d.ts.map +1 -0
  270. package/dist/types/src/util/sanitize-persisted-state.d.ts +19 -0
  271. package/dist/types/src/util/sanitize-persisted-state.d.ts.map +1 -0
  272. package/dist/types/src/util/sanitize-persisted-state.test.d.ts +2 -0
  273. package/dist/types/src/util/sanitize-persisted-state.test.d.ts.map +1 -0
  274. package/dist/types/src/util/set-active.d.ts +19 -4
  275. package/dist/types/src/util/set-active.d.ts.map +1 -1
  276. package/dist/types/src/util/set-active.test.d.ts +2 -0
  277. package/dist/types/src/util/set-active.test.d.ts.map +1 -0
  278. package/dist/types/tsconfig.tsbuildinfo +1 -1
  279. package/package.json +87 -49
  280. package/src/DeckPlugin.ts +43 -69
  281. package/src/capabilities/app-graph-builder.ts +112 -127
  282. package/src/capabilities/check-app-scheme.ts +123 -24
  283. package/src/capabilities/index.ts +13 -14
  284. package/src/capabilities/operation-handler.ts +16 -0
  285. package/src/capabilities/react-root.tsx +37 -29
  286. package/src/capabilities/react-surface.tsx +28 -22
  287. package/src/capabilities/settings.ts +30 -19
  288. package/src/capabilities/state.ts +74 -88
  289. package/src/capabilities/tools.ts +57 -50
  290. package/src/capabilities/url-handler.ts +221 -50
  291. package/src/components/DeckSettings/DeckSettings.stories.tsx +37 -0
  292. package/src/components/DeckSettings/DeckSettings.tsx +55 -70
  293. package/src/components/DeckSettings/index.ts +2 -2
  294. package/src/components/Matrix/Matrix.stories.tsx +216 -0
  295. package/src/components/Matrix/Matrix.tsx +205 -0
  296. package/src/components/Matrix/SPEC.md +219 -0
  297. package/src/components/Matrix/index.ts +6 -0
  298. package/src/components/index.ts +6 -3
  299. package/src/{components/DeckLayout → containers/Deck}/Banner.tsx +13 -11
  300. package/src/containers/Deck/Deck.stories.tsx +81 -0
  301. package/src/containers/Deck/Deck.tsx +21 -0
  302. package/src/containers/Deck/DeckContent.tsx +105 -0
  303. package/src/containers/Deck/DeckRoot.tsx +50 -0
  304. package/src/containers/Deck/DeckViewport.tsx +456 -0
  305. package/src/{components/DeckLayout → containers/Deck}/StatusBar.tsx +4 -4
  306. package/src/containers/Deck/index.ts +5 -0
  307. package/src/{components → containers}/DeckLayout/ActiveNode.tsx +8 -3
  308. package/src/containers/DeckLayout/DeckLayout.stories.tsx +393 -0
  309. package/src/containers/DeckLayout/DeckLayout.tsx +62 -0
  310. package/src/containers/DeckLayout/Dialog.tsx +52 -0
  311. package/src/containers/DeckLayout/Fallback.tsx +24 -0
  312. package/src/containers/DeckLayout/Popover.tsx +161 -0
  313. package/src/{components → containers}/DeckLayout/Toast.tsx +30 -5
  314. package/src/{components → containers}/DeckLayout/constants.ts +1 -0
  315. package/src/{components → containers}/DeckLayout/index.ts +3 -2
  316. package/src/containers/Plank/Plank.stories.tsx +106 -0
  317. package/src/containers/Plank/Plank.tsx +22 -0
  318. package/src/containers/Plank/PlankComponent.tsx +217 -0
  319. package/src/containers/Plank/PlankContent.tsx +45 -0
  320. package/src/{components → containers}/Plank/PlankControls.tsx +45 -38
  321. package/src/containers/Plank/PlankError.tsx +79 -0
  322. package/src/{components → containers}/Plank/PlankHeading.tsx +68 -64
  323. package/src/{components → containers}/Plank/PlankLoading.tsx +1 -1
  324. package/src/containers/Plank/PlankRoot.tsx +49 -0
  325. package/src/{components → containers}/Plank/index.ts +0 -2
  326. package/src/containers/Sidebar/ComplementarySidebar.tsx +209 -0
  327. package/src/containers/Sidebar/Sidebar.tsx +44 -0
  328. package/src/containers/Sidebar/SidebarButton.tsx +94 -0
  329. package/src/containers/index.ts +11 -0
  330. package/src/hooks/index.ts +2 -0
  331. package/src/hooks/useCompanions.ts +3 -3
  332. package/src/hooks/useDeckCompanions.ts +7 -10
  333. package/src/hooks/useDeckState.ts +73 -0
  334. package/src/hooks/useHoistStatusbar.ts +4 -5
  335. package/src/hooks/useMainSize.ts +2 -2
  336. package/src/hooks/useNodeActionExpander.ts +4 -4
  337. package/src/hooks/useSelectedCompanion.ts +32 -0
  338. package/src/index.ts +1 -2
  339. package/src/layout.test.ts +59 -0
  340. package/src/layout.ts +38 -40
  341. package/src/meta.ts +8 -5
  342. package/src/operations/add-toast.ts +24 -0
  343. package/src/operations/adjust.ts +83 -0
  344. package/src/operations/change-companion.ts +35 -0
  345. package/src/operations/close.ts +35 -0
  346. package/src/operations/definitions.ts +62 -0
  347. package/src/operations/helpers.ts +22 -0
  348. package/src/operations/index.ts +26 -0
  349. package/src/operations/open.ts +184 -0
  350. package/src/operations/revert-workspace.ts +22 -0
  351. package/src/operations/scroll-into-view.ts +24 -0
  352. package/src/operations/set-layout-mode.ts +84 -0
  353. package/src/operations/set.ts +36 -0
  354. package/src/operations/show-undo.ts +47 -0
  355. package/src/operations/switch-workspace.ts +60 -0
  356. package/src/operations/update-complementary.ts +33 -0
  357. package/src/operations/update-dialog.ts +34 -0
  358. package/src/operations/update-plank-size.ts +29 -0
  359. package/src/operations/update-popover.ts +36 -0
  360. package/src/operations/update-sidebar.ts +28 -0
  361. package/src/translations.ts +52 -52
  362. package/src/types/Settings.ts +17 -0
  363. package/src/types/capabilities.ts +35 -0
  364. package/src/types/events.ts +21 -0
  365. package/src/types/index.ts +3 -0
  366. package/src/types/schema.ts +52 -50
  367. package/src/util/index.ts +2 -1
  368. package/src/util/layoutAppliesTopbar.ts +2 -2
  369. package/src/util/plank-url-params.test.ts +85 -0
  370. package/src/util/plank-url-params.ts +36 -0
  371. package/src/util/sanitize-persisted-state.test.ts +79 -0
  372. package/src/util/sanitize-persisted-state.ts +52 -0
  373. package/src/util/set-active.test.ts +106 -0
  374. package/src/util/set-active.ts +50 -30
  375. package/src/vite-env.d.ts +5 -0
  376. package/dist/lib/browser/app-graph-builder-DVEKLXB4.mjs +0 -152
  377. package/dist/lib/browser/app-graph-builder-DVEKLXB4.mjs.map +0 -7
  378. package/dist/lib/browser/check-app-scheme-3BQJXWEY.mjs +0 -32
  379. package/dist/lib/browser/check-app-scheme-3BQJXWEY.mjs.map +0 -7
  380. package/dist/lib/browser/chunk-6MQIYIPY.mjs +0 -1494
  381. package/dist/lib/browser/chunk-6MQIYIPY.mjs.map +0 -7
  382. package/dist/lib/browser/chunk-CNTGBCMK.mjs +0 -145
  383. package/dist/lib/browser/chunk-CNTGBCMK.mjs.map +0 -7
  384. package/dist/lib/browser/chunk-F5BQOOEG.mjs +0 -160
  385. package/dist/lib/browser/chunk-F5BQOOEG.mjs.map +0 -7
  386. package/dist/lib/browser/chunk-M57WD3V6.mjs +0 -16
  387. package/dist/lib/browser/chunk-M57WD3V6.mjs.map +0 -7
  388. package/dist/lib/browser/chunk-MX7WRVX3.mjs +0 -127
  389. package/dist/lib/browser/chunk-MX7WRVX3.mjs.map +0 -7
  390. package/dist/lib/browser/chunk-NRCPV6AV.mjs +0 -129
  391. package/dist/lib/browser/chunk-NRCPV6AV.mjs.map +0 -7
  392. package/dist/lib/browser/chunk-Z5KITAZW.mjs +0 -13
  393. package/dist/lib/browser/chunk-Z5KITAZW.mjs.map +0 -7
  394. package/dist/lib/browser/intent-resolver-2SUIIV6N.mjs +0 -521
  395. package/dist/lib/browser/intent-resolver-2SUIIV6N.mjs.map +0 -7
  396. package/dist/lib/browser/react-root-GVZANZX7.mjs +0 -43
  397. package/dist/lib/browser/react-root-GVZANZX7.mjs.map +0 -7
  398. package/dist/lib/browser/react-surface-NXSSD2GW.mjs +0 -40
  399. package/dist/lib/browser/react-surface-NXSSD2GW.mjs.map +0 -7
  400. package/dist/lib/browser/settings-LUPQPZ27.mjs +0 -29
  401. package/dist/lib/browser/settings-LUPQPZ27.mjs.map +0 -7
  402. package/dist/lib/browser/state-CRXR7X63.mjs +0 -12
  403. package/dist/lib/browser/toolkit-OBKFXX23.mjs +0 -47
  404. package/dist/lib/browser/toolkit-OBKFXX23.mjs.map +0 -7
  405. package/dist/lib/browser/url-handler-LROZYQ26.mjs +0 -70
  406. package/dist/lib/browser/url-handler-LROZYQ26.mjs.map +0 -7
  407. package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
  408. package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
  409. package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
  410. package/dist/types/src/capabilities/toolkit.d.ts +0 -5
  411. package/dist/types/src/capabilities/toolkit.d.ts.map +0 -1
  412. package/dist/types/src/components/DeckLayout/ActiveNode.d.ts.map +0 -1
  413. package/dist/types/src/components/DeckLayout/Banner.d.ts.map +0 -1
  414. package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts +0 -3
  415. package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts.map +0 -1
  416. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts +0 -6
  417. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +0 -1
  418. package/dist/types/src/components/DeckLayout/Dialog.d.ts.map +0 -1
  419. package/dist/types/src/components/DeckLayout/Fallback.d.ts +0 -3
  420. package/dist/types/src/components/DeckLayout/Fallback.d.ts.map +0 -1
  421. package/dist/types/src/components/DeckLayout/Popover.d.ts +0 -5
  422. package/dist/types/src/components/DeckLayout/Popover.d.ts.map +0 -1
  423. package/dist/types/src/components/DeckLayout/StatusBar.d.ts.map +0 -1
  424. package/dist/types/src/components/DeckLayout/Toast.d.ts +0 -5
  425. package/dist/types/src/components/DeckLayout/Toast.d.ts.map +0 -1
  426. package/dist/types/src/components/DeckLayout/Topbar.d.ts +0 -3
  427. package/dist/types/src/components/DeckLayout/Topbar.d.ts.map +0 -1
  428. package/dist/types/src/components/DeckLayout/constants.d.ts.map +0 -1
  429. package/dist/types/src/components/DeckLayout/index.d.ts +0 -4
  430. package/dist/types/src/components/DeckLayout/index.d.ts.map +0 -1
  431. package/dist/types/src/components/Plank/Plank.d.ts +0 -27
  432. package/dist/types/src/components/Plank/Plank.d.ts.map +0 -1
  433. package/dist/types/src/components/Plank/Plank.stories.d.ts +0 -8
  434. package/dist/types/src/components/Plank/Plank.stories.d.ts.map +0 -1
  435. package/dist/types/src/components/Plank/PlankControls.d.ts.map +0 -1
  436. package/dist/types/src/components/Plank/PlankError.d.ts +0 -13
  437. package/dist/types/src/components/Plank/PlankError.d.ts.map +0 -1
  438. package/dist/types/src/components/Plank/PlankHeading.d.ts.map +0 -1
  439. package/dist/types/src/components/Plank/index.d.ts +0 -6
  440. package/dist/types/src/components/Plank/index.d.ts.map +0 -1
  441. package/dist/types/src/components/Sidebar/ComplementarySidebar.d.ts.map +0 -1
  442. package/dist/types/src/components/Sidebar/Sidebar.d.ts.map +0 -1
  443. package/dist/types/src/components/Sidebar/SidebarButton.d.ts.map +0 -1
  444. package/dist/types/src/components/fragments.d.ts +0 -4
  445. package/dist/types/src/components/fragments.d.ts.map +0 -1
  446. package/dist/types/src/events.d.ts +0 -4
  447. package/dist/types/src/events.d.ts.map +0 -1
  448. package/dist/types/src/util/overscroll.d.ts +0 -47
  449. package/dist/types/src/util/overscroll.d.ts.map +0 -1
  450. package/src/capabilities/capabilities.ts +0 -14
  451. package/src/capabilities/intent-resolver.ts +0 -469
  452. package/src/capabilities/toolkit.ts +0 -55
  453. package/src/components/DeckLayout/ContentEmpty.tsx +0 -31
  454. package/src/components/DeckLayout/DeckLayout.tsx +0 -302
  455. package/src/components/DeckLayout/Dialog.tsx +0 -36
  456. package/src/components/DeckLayout/Fallback.tsx +0 -28
  457. package/src/components/DeckLayout/Popover.tsx +0 -104
  458. package/src/components/DeckLayout/Topbar.tsx +0 -11
  459. package/src/components/Plank/Plank.stories.tsx +0 -56
  460. package/src/components/Plank/Plank.tsx +0 -267
  461. package/src/components/Plank/PlankError.tsx +0 -49
  462. package/src/components/Sidebar/ComplementarySidebar.tsx +0 -194
  463. package/src/components/Sidebar/Sidebar.tsx +0 -42
  464. package/src/components/Sidebar/SidebarButton.tsx +0 -87
  465. package/src/components/fragments.ts +0 -14
  466. package/src/events.ts +0 -11
  467. package/src/util/overscroll.ts +0 -69
  468. /package/dist/lib/browser/{state-CRXR7X63.mjs.map → chunk-J5LGTIGS.mjs.map} +0 -0
  469. /package/dist/types/src/{components/DeckLayout → containers/Deck}/Banner.d.ts +0 -0
  470. /package/dist/types/src/{components/DeckLayout → containers/Deck}/StatusBar.d.ts +0 -0
  471. /package/dist/types/src/{components → containers}/DeckLayout/ActiveNode.d.ts +0 -0
  472. /package/dist/types/src/{components → containers}/DeckLayout/Dialog.d.ts +0 -0
  473. /package/dist/types/src/{components → containers}/DeckLayout/constants.d.ts +0 -0
  474. /package/dist/types/src/{components → containers}/Plank/PlankLoading.d.ts +0 -0
  475. /package/dist/types/src/{components → containers}/Sidebar/ComplementarySidebar.d.ts +0 -0
  476. /package/dist/types/src/{components → containers}/Sidebar/Sidebar.d.ts +0 -0
  477. /package/dist/types/src/{components → containers}/Sidebar/SidebarButton.d.ts +0 -0
  478. /package/dist/types/src/{components → containers}/Sidebar/index.d.ts +0 -0
  479. /package/src/{components → containers}/Sidebar/index.ts +0 -0
@@ -0,0 +1,216 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React, { useCallback, useMemo, useRef, useState } from 'react';
7
+
8
+ import { Capabilities, Capability, Plugin } from '@dxos/app-framework';
9
+ import { withPluginManager } from '@dxos/app-framework/testing';
10
+ import { Surface } from '@dxos/app-framework/ui';
11
+ import { Graph } from '@dxos/app-graph';
12
+ import { AppActivationEvents, AppPlugin } from '@dxos/app-toolkit';
13
+ import { Obj } from '@dxos/echo';
14
+ import { corePlugins } from '@dxos/plugin-testing';
15
+ import { random } from '@dxos/random';
16
+ import { Focus, Panel, Toolbar } from '@dxos/react-ui';
17
+ import { useAttentionAttributes } from '@dxos/react-ui-attention';
18
+ import { withAttention } from '@dxos/react-ui-attention/testing';
19
+ import { type MosaicTileProps, Mosaic } from '@dxos/react-ui-mosaic';
20
+ import { StackContext } from '@dxos/react-ui-stack';
21
+ import { Json } from '@dxos/react-ui-syntax-highlighter';
22
+ import { Loading, withLayout, withTheme } from '@dxos/react-ui/testing';
23
+ import { Text } from '@dxos/schema';
24
+ import { Organization, Person } from '@dxos/types';
25
+
26
+ import { DeckState, OperationHandler } from '#capabilities';
27
+ import { meta as pluginMeta } from '#meta';
28
+
29
+ import { Plank } from '../../containers/Plank';
30
+ import { translations } from '../../translations';
31
+ import { Matrix, type MatrixController, type MatrixRootProps } from './Matrix';
32
+
33
+ random.seed(123);
34
+
35
+ const TestPlugin = Plugin.define(pluginMeta).pipe(
36
+ Plugin.addModule({
37
+ id: Capability.getModuleTag(DeckState),
38
+ activatesOn: AppActivationEvents.AppGraphReady,
39
+ activate: () => DeckState(),
40
+ }),
41
+ AppPlugin.addOperationHandlerModule({
42
+ activate: OperationHandler,
43
+ }),
44
+ Plugin.make,
45
+ );
46
+
47
+ /**
48
+ * Simple tile with JSON display and attention tracking.
49
+ */
50
+ const StoryTile = (props: MosaicTileProps<Obj.Any>) => {
51
+ const attentionAttrs = useAttentionAttributes(props.data.id);
52
+ return (
53
+ <Mosaic.Tile {...props} asChild>
54
+ <Focus.Item asChild border current={props.current}>
55
+ <Panel.Root classNames='dx-current dx-hover w-full md:w-[50rem] snap-start shrink-0' {...attentionAttrs}>
56
+ <Panel.Toolbar asChild>
57
+ <Toolbar.Root>
58
+ <p>{Obj.getLabel(props.data)}</p>
59
+ </Toolbar.Root>
60
+ </Panel.Toolbar>
61
+ <Json.Root data={props.data}>
62
+ <Panel.Content asChild>
63
+ <Json.Content>
64
+ <Json.Data />
65
+ </Json.Content>
66
+ </Panel.Content>
67
+ </Json.Root>
68
+ </Panel.Root>
69
+ </Focus.Item>
70
+ </Mosaic.Tile>
71
+ );
72
+ };
73
+
74
+ /**
75
+ * Tile that wraps a Plank for content rendering.
76
+ */
77
+ const PlankTile = (props: MosaicTileProps<Obj.Any>) => {
78
+ const graph = useMemo(() => Graph.make(), []);
79
+ return (
80
+ <StackContext.Provider value={{ orientation: 'horizontal', size: 'contain', rail: true }}>
81
+ <Plank.Root layoutMode='multi' part='multi' graph={graph}>
82
+ <Mosaic.Tile {...props} asChild>
83
+ <Plank.Content solo={false} companion={false} encapsulate={false}>
84
+ <Plank.Component
85
+ id={props.data.id}
86
+ part='multi'
87
+ node={{
88
+ id: props.data.id,
89
+ data: props.data,
90
+ type: 'test',
91
+ properties: {},
92
+ }}
93
+ />
94
+ </Plank.Content>
95
+ </Mosaic.Tile>
96
+ </Plank.Root>
97
+ </StackContext.Provider>
98
+ );
99
+ };
100
+
101
+ const TestExtension = Capability.contributes(
102
+ Capabilities.ReactSurface,
103
+ Surface.create({
104
+ id: 'story-article',
105
+ role: 'article',
106
+ component: ({ data: { subject } }) => {
107
+ if (!subject) {
108
+ return <Loading />;
109
+ }
110
+
111
+ return (
112
+ <Json.Root data={subject}>
113
+ <Json.Content>
114
+ <Json.Data />
115
+ </Json.Content>
116
+ </Json.Root>
117
+ );
118
+ },
119
+ }),
120
+ );
121
+
122
+ type DefaultStoryProps = Pick<MatrixRootProps, 'Tile'>;
123
+
124
+ const DefaultStory = ({ Tile }: DefaultStoryProps) => {
125
+ const items = useMemo(
126
+ () => [
127
+ Organization.make({ name: random.company.name() }),
128
+ Person.make({ fullName: random.person.fullName() }),
129
+ Text.make({ name: 'Bio', content: random.lorem.paragraphs(10) }),
130
+ Text.make({ name: 'Companion', content: 'Companion panel for Bio' }),
131
+ ],
132
+ [],
133
+ );
134
+
135
+ const controller = useRef<MatrixController>(null);
136
+ const [current, setCurrent] = useState<string | undefined>(items[0]?.id);
137
+
138
+ const handleCurrentChange = useCallback((id: string | undefined) => {
139
+ setCurrent(id);
140
+ }, []);
141
+
142
+ const handlePrev = useCallback(() => {
143
+ const index = items.findIndex((item) => item.id === current);
144
+ const prev = items[Math.max(0, index - 1)];
145
+ if (prev) {
146
+ controller.current?.scrollTo(prev.id);
147
+ }
148
+ }, [items, current]);
149
+
150
+ const handleNext = useCallback(() => {
151
+ const index = items.findIndex((item) => item.id === current);
152
+ const next = items[Math.min(items.length - 1, index + 1)];
153
+ if (next) {
154
+ controller.current?.scrollTo(next.id);
155
+ }
156
+ }, [items, current]);
157
+
158
+ const currentIndex = items.findIndex((item) => item.id === current);
159
+
160
+ return (
161
+ <Mosaic.Root>
162
+ <Matrix.Root Tile={Tile} items={items} current={current} onCurrentChange={handleCurrentChange} ref={controller}>
163
+ <Panel.Root>
164
+ <Panel.Toolbar asChild>
165
+ <Toolbar.Root>
166
+ <Toolbar.IconButton icon='ph--caret-left--regular' iconOnly label='Back' onClick={handlePrev} />
167
+ <Toolbar.IconButton icon='ph--caret-right--regular' iconOnly label='Forward' onClick={handleNext} />
168
+ <Toolbar.Text>
169
+ {currentIndex + 1} / {items.length}
170
+ </Toolbar.Text>
171
+ </Toolbar.Root>
172
+ </Panel.Toolbar>
173
+ <Panel.Content asChild>
174
+ <Matrix.Content>
175
+ <Matrix.Viewport />
176
+ </Matrix.Content>
177
+ </Panel.Content>
178
+ </Panel.Root>
179
+ </Matrix.Root>
180
+ </Mosaic.Root>
181
+ );
182
+ };
183
+
184
+ const meta = {
185
+ title: 'plugins/plugin-deck/components/Matrix',
186
+ component: DefaultStory,
187
+ decorators: [withTheme(), withAttention(), withLayout({ layout: 'fullscreen' })],
188
+ parameters: {
189
+ layout: 'fullscreen',
190
+ },
191
+ } satisfies Meta<MatrixRootProps>;
192
+
193
+ export default meta;
194
+
195
+ type Story = StoryObj<typeof meta>;
196
+
197
+ export const Default: Story = {
198
+ args: {
199
+ Tile: StoryTile,
200
+ },
201
+ };
202
+
203
+ export const WithPlank: Story = {
204
+ decorators: [
205
+ withPluginManager({
206
+ plugins: [...corePlugins(), TestPlugin()],
207
+ capabilities: [TestExtension],
208
+ }),
209
+ ],
210
+ parameters: {
211
+ translations,
212
+ },
213
+ args: {
214
+ Tile: PlankTile,
215
+ },
216
+ };
@@ -0,0 +1,205 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { useFocusFinders } from '@fluentui/react-tabster';
6
+ import { createContext } from '@radix-ui/react-context';
7
+ import React, { forwardRef, type PropsWithChildren, useCallback, useEffect, useImperativeHandle, useRef } from 'react';
8
+
9
+ import { Obj } from '@dxos/echo';
10
+ import { ScrollArea } from '@dxos/react-ui';
11
+ import { useAttended } from '@dxos/react-ui-attention';
12
+ import { type MosaicStackTileComponent, Mosaic } from '@dxos/react-ui-mosaic';
13
+ import { composable, composableProps } from '@dxos/ui-theme';
14
+ import { type ComposableProps } from '@dxos/ui-types';
15
+
16
+ //
17
+ // Context
18
+ //
19
+
20
+ const MATRIX_NAME = 'Matrix';
21
+
22
+ type MatrixContextValue = {
23
+ /** Items to render. */
24
+ items: Obj.Any[];
25
+ /** Tile component to render for each item. */
26
+ Tile: MosaicStackTileComponent<Obj.Any>;
27
+ /** Currently attended tile ID. */
28
+ current?: Obj.ID;
29
+ /** Callback when the attended tile changes. */
30
+ onCurrentChange?: (id: Obj.ID | undefined) => void;
31
+ /** Register the viewport element for scroll operations. */
32
+ registerViewport: (element: HTMLElement | null) => void;
33
+ };
34
+
35
+ const [MatrixProvider, useMatrixContext] = createContext<MatrixContextValue>(MATRIX_NAME);
36
+
37
+ //
38
+ // Controller
39
+ //
40
+
41
+ interface MatrixController {
42
+ scrollTo: (id: Obj.ID) => void;
43
+ }
44
+
45
+ //
46
+ // Root
47
+ //
48
+
49
+ const MATRIX_ROOT_NAME = 'Matrix.Root';
50
+
51
+ type MatrixRootProps = PropsWithChildren<{
52
+ /** Items to render. */
53
+ items?: Obj.Any[];
54
+ /** Tile component to render for each item. */
55
+ Tile: MosaicStackTileComponent<Obj.Any>;
56
+ /** Currently attended tile ID. */
57
+ current?: Obj.ID;
58
+ /** Callback when the attended tile changes. */
59
+ onCurrentChange?: (id: Obj.ID | undefined) => void;
60
+ }>;
61
+
62
+ /**
63
+ * Headless root that provides matrix context.
64
+ * Syncs the attention system with `onCurrentChange` — when a tile gains attention, the callback fires.
65
+ */
66
+ const MatrixRoot = forwardRef<MatrixController, MatrixRootProps>(
67
+ ({ children, items = [], Tile, current, onCurrentChange }, forwardedRef) => {
68
+ const viewportRef = useRef<HTMLElement | null>(null);
69
+ const registerViewport = useCallback((element: HTMLElement | null) => {
70
+ viewportRef.current = element;
71
+ }, []);
72
+
73
+ const { findFirstFocusable } = useFocusFinders();
74
+ const findFirstFocusableRef = useRef(findFirstFocusable);
75
+ findFirstFocusableRef.current = findFirstFocusable;
76
+
77
+ // Sync attention system with current tile.
78
+ const attended = useAttended();
79
+ const itemIds = useRef(new Set<string>());
80
+ useEffect(() => {
81
+ itemIds.current = new Set(items.map((item) => item.id));
82
+ }, [items]);
83
+
84
+ useEffect(() => {
85
+ // Find the first attended ID that matches an item.
86
+ const matchedId = attended.find((id) => itemIds.current.has(id));
87
+ if (matchedId !== current) {
88
+ onCurrentChange?.(matchedId);
89
+ }
90
+ }, [attended, current, onCurrentChange]);
91
+
92
+ useImperativeHandle(forwardedRef, () => ({
93
+ scrollTo: (id) => {
94
+ const viewport = viewportRef.current;
95
+ if (!viewport) {
96
+ return;
97
+ }
98
+
99
+ const tile = viewport.querySelector<HTMLElement>(`[data-object-id="${CSS.escape(id)}"]`);
100
+ if (!tile) {
101
+ return;
102
+ }
103
+
104
+ // Focus first focusable element so attention updates immediately, then scroll.
105
+ const focusable = findFirstFocusableRef.current(tile);
106
+ (focusable ?? tile).focus({ preventScroll: true });
107
+
108
+ const tileRect = tile.getBoundingClientRect();
109
+ const viewportRect = viewport.getBoundingClientRect();
110
+ const offset = tileRect.left - viewportRect.left + viewport.scrollLeft;
111
+ if (Math.abs(offset - viewport.scrollLeft) > 1) {
112
+ viewport.scrollTo({ left: offset, behavior: 'smooth' });
113
+ }
114
+ },
115
+ }));
116
+
117
+ return (
118
+ <MatrixProvider
119
+ items={items}
120
+ Tile={Tile}
121
+ current={current}
122
+ onCurrentChange={onCurrentChange}
123
+ registerViewport={registerViewport}
124
+ >
125
+ {children}
126
+ </MatrixProvider>
127
+ );
128
+ },
129
+ );
130
+
131
+ MatrixRoot.displayName = MATRIX_ROOT_NAME;
132
+
133
+ //
134
+ // Content
135
+ //
136
+
137
+ const MATRIX_CONTENT_NAME = 'Matrix.Content';
138
+
139
+ type MatrixContentProps = ComposableProps;
140
+
141
+ /**
142
+ * Styled container wrapping Mosaic.Container for drag-and-drop support.
143
+ */
144
+ const MatrixContent = composable<HTMLDivElement>(({ children, ...props }, forwardedRef) => {
145
+ const { className, ...rest } = composableProps(props);
146
+ return (
147
+ <Mosaic.Container ref={forwardedRef} classNames={className} orientation='horizontal' {...rest}>
148
+ {children}
149
+ </Mosaic.Container>
150
+ );
151
+ });
152
+
153
+ MatrixContent.displayName = MATRIX_CONTENT_NAME;
154
+
155
+ //
156
+ // Viewport
157
+ //
158
+
159
+ const MATRIX_VIEWPORT_NAME = 'Matrix.Viewport';
160
+
161
+ type MatrixViewportProps = ComposableProps;
162
+
163
+ const getId = (item: Obj.Any) => item.id;
164
+
165
+ /**
166
+ * Horizontally scrollable viewport that renders tiles from context.
167
+ */
168
+ const MatrixViewport = composable<HTMLDivElement>(({ ...props }, forwardedRef) => {
169
+ const { items, Tile, registerViewport } = useMatrixContext(MATRIX_VIEWPORT_NAME);
170
+ const viewportRef = useCallback(
171
+ (element: HTMLElement | null) => {
172
+ registerViewport(element);
173
+ },
174
+ [registerViewport],
175
+ );
176
+
177
+ return (
178
+ <ScrollArea.Root orientation='horizontal' padding snap {...composableProps(props)} ref={forwardedRef}>
179
+ <ScrollArea.Viewport ref={viewportRef}>
180
+ <Mosaic.Stack
181
+ orientation='horizontal'
182
+ classNames='snap-x snap-mandatory gap-2'
183
+ getId={getId}
184
+ items={items}
185
+ Tile={Tile}
186
+ draggable={false}
187
+ />
188
+ </ScrollArea.Viewport>
189
+ </ScrollArea.Root>
190
+ );
191
+ });
192
+
193
+ MatrixViewport.displayName = MATRIX_VIEWPORT_NAME;
194
+
195
+ //
196
+ // Matrix
197
+ //
198
+
199
+ export const Matrix = {
200
+ Root: MatrixRoot,
201
+ Content: MatrixContent,
202
+ Viewport: MatrixViewport,
203
+ };
204
+
205
+ export type { MatrixController, MatrixRootProps, MatrixContentProps, MatrixViewportProps };
@@ -0,0 +1,219 @@
1
+ # Matrix
2
+
3
+ We are going to do a very complex refactor. Think deeply about what you are doing and create a plan.
4
+ Our eventual goal is to replace `DeckMain` with a new layout `Matrix` using `react-ui-matrix` instead of `react-ui-stack`.
5
+ We must decide whether to incrementally evolve `Plank` or recreate it.
6
+ Be careful not to mix-up `Mosaic.Stack` with `react-ui-stack` (which is deprecated).
7
+ Ask clarifying questions before you begin.
8
+
9
+ ## Background
10
+
11
+ - Currently `DeckMain` and `Plank` are complex components that have dependencies on `app-toolkit` and `app-framework` hooks and context.
12
+ - We will refactor these into radix-style components (like Dialog.tsx) and provide the necessary context via props (e.g., to a headless `Root` component).
13
+ - DeckMain currently has two modes: `deck` and `solo`;
14
+ - In `deck` mode we have a horizontal scrolling list of `Plank` objects;
15
+ - In `solo` mode we have a single `Plank` object that fills the viewport with a companion `Plank` area to the right;
16
+ - `Matrix` is an experimental alternative to `DeckMain`, which contains a horizontal `Matrix.Stack`.
17
+ - `Matrix` is a low-level component that does not depend directly on `Plank`.
18
+
19
+ ## Implementation
20
+
21
+ ### Phase 1 (Plank)
22
+
23
+ - [x] Refactor `Plank` as radix-style composite component.
24
+ - [x] Create a Tile that wraps `Plank` (which contains `Surface` components).
25
+ - [x] Create a story variant that provides this Tile in the args.
26
+ - [x] The decorator must define react-surface extensions that resolves the Surface to the given object type.
27
+ - [x] The last `Plank` serves as the "companion" area for the `Plank` to its left.
28
+ - [x] Given the items in the current story we should see 4 Planks in the Matrix: Organization, Person, Text, Companion.
29
+ - [x] Make Matrix responsive so that if we're on a phone only one `Plank` is visible at a time.
30
+ - [x] Check everything builds and commit.
31
+
32
+ ### Phase 2 (Deck)
33
+
34
+ - [x] Refactor `DeckMain` as radix-style composite component.
35
+ - This enables us to separate the functionality so that we can isolate the use of react-ui-stack
36
+ - Instead of `useAtomCapability` and `usePluginManager` pass the associated objects into `Root`.
37
+ - [x] Analyze the `DeckMain` and `Plank` components and make recommendations for how to simplify.
38
+ - [x] Create a concise spec for the functionality of both `DeckMain` and `Plank` (about 20 bullets each).
39
+ - [x] Check everything builds and commit.
40
+
41
+ #### Decisions
42
+
43
+ 1. ~~Merge PlankComponent into Plank.Article~~ — deferred.
44
+ 2. **Remove `Plank.Content`**: Solo layout container moves to DeckMain (`Deck.Content`). Plank is layout-agnostic.
45
+ 3. **Reduce `part` to `deck | solo | complementary`**: Remove `solo-primary`/`solo-companion` variants. Deck handles companion column layout.
46
+ 4. **Remove dual-mount pattern**: Only mount the active mode (deck or solo). Scroll position tracked via `scrollLeftRef`.
47
+ 5. **Remove all framework hooks from Plank**: Lift `Graph.expand`, `Graph.getActions`, and `useActionRunner` from PlankHeading into ConnectedPlank. Resolved actions passed through PlankContext.
48
+
49
+ ### Phase 3 (Cleanup)
50
+
51
+ - [ ] Remove `Plank.Content` — move solo grid layout to `Deck.Content`.
52
+ - [ ] Reduce `ResolvedPart` to `'deck' | 'solo' | 'complementary'`.
53
+ - [ ] Remove dual-mount in DeckMain — only render active mode.
54
+ - [ ] Lift action resolution from PlankHeading to ConnectedPlank/PlankContext.
55
+ - [ ] Refactor DeckMain to use `Deck.Root` / `Deck.Content` radix structure.
56
+ - [ ] Remove `useAppGraph`, `useActionRunner` from PlankHeading.
57
+
58
+ ### Phase 4 (Attention)
59
+
60
+ - [x] Concisely document the attention system (`react-ui-attention`) and how it works with the deck.
61
+
62
+ ## Attention System
63
+
64
+ The attention system (`react-ui-attention`) tracks which plank currently has user focus.
65
+ It is separate from DOM focus — attention is a higher-level concept derived from focus events.
66
+
67
+ ### Architecture
68
+
69
+ - **`AttentionManager`** — core state: maintains an array of currently attended IDs (qualified, `/`-separated paths).
70
+ - **`RootAttentionProvider`** — listens for `focusCapture` events at the app root. Walks up from the focused element collecting `data-attendable-id` attributes. Calls `AttentionManager.update()` with the collected IDs.
71
+ - **`useAttentionAttributes(id)`** — returns `{ 'data-attendable-id': id }` for a DOM element. Makes the element participate in attention tracking.
72
+ - **`useAttention(id)`** — subscribes to attention state for a specific ID. Returns `{ hasAttention, isAncestor, isRelated }`.
73
+
74
+ ### How attention changes
75
+
76
+ 1. User clicks or tabs into a plank → DOM focus event fires.
77
+ 2. `RootAttentionProvider` captures the focus event at the root.
78
+ 3. Walks up from `event.target`, collecting all `data-attendable-id` values.
79
+ 4. Calls `attention.update(ids)` — the first ID is the primary attended element; ancestors get `isAncestor: true`.
80
+ 5. All subscribers (e.g., `useAttention`) are notified via atoms.
81
+
82
+ ### Hierarchy and related items
83
+
84
+ IDs are `/`-separated paths (e.g., `root/space/document`). When `root/space/document` is attended:
85
+
86
+ - `root/space/document` → `{ hasAttention: true }`
87
+ - `root/space` → `{ isAncestor: true }`
88
+ - `root` → `{ isAncestor: true }`
89
+
90
+ IDs sharing the same last segment are marked `isRelated: true` (e.g., the same object shown in two places).
91
+ IDs with a `~` prefix on the last segment (e.g., `root/obj/~settings`) mark the parent as both ancestor and related.
92
+
93
+ ### Integration with the Deck
94
+
95
+ - **Plank** uses `useAttentionAttributes(id)` on the root element, making each plank attendable.
96
+ - `isAttendable` is true for `solo`, `solo-primary`, `solo-companion`, and `deck` parts.
97
+ - The `dx-attention-surface` CSS class provides visual feedback.
98
+ - **DeckMain** ensures attention is initialized:
99
+ - On first render, focuses the first plank's button if nothing is attended.
100
+ - On mobile breakpoint: reads the currently attended ID to determine which plank to show in solo mode.
101
+ - **Keyboard** — `plugin-attention` syncs `Keyboard.singleton.setCurrentContext(id)` with the attended ID, so keyboard shortcuts apply to the attended plank.
102
+
103
+ ### Attention vs Focus vs Matrix.current
104
+
105
+ | Concept | Scope | Mechanism |
106
+ | -------------- | ----------- | ------------------------------------------------------ |
107
+ | DOM focus | Browser | `tabIndex`, `focus()`, focus/blur events |
108
+ | Attention | App-wide | `data-attendable-id` + `RootAttentionProvider` capture |
109
+ | Matrix.current | Matrix only | `focusin` on viewport → resolve `data-object-id` |
110
+
111
+ Currently, Matrix.current and the attention system are independent. For the Matrix to participate in the attention system, tiles would need `data-attendable-id` attributes and the `RootAttentionProvider` would track them automatically via DOM focus. The `onCurrentChange` callback on Matrix.Root could then be driven by attention rather than raw focus events.
112
+
113
+ ## Design
114
+
115
+ ### Plank Radix-Style Structure
116
+
117
+ ```
118
+ Plank (connected wrapper — calls useAppGraph, useOperationInvoker, useDeckState)
119
+ └── Plank.Root (PlankProvider — injects context)
120
+ ├── Plank.Container (layout: solo grid vs passthrough)
121
+ ├── Plank.Article (PlankComponent — attention, resize, Surface)
122
+ │ ├── Plank.Heading (icon, label, controls)
123
+ │ │ └── Plank.Controls (solo/deck/close/companion buttons)
124
+ │ ├── Surface.Surface role='article' (main content)
125
+ │ └── StackItem.ResizeHandle (deck mode only)
126
+ └── [Companion Plank.Article] (optional)
127
+ ```
128
+
129
+ ### PlankContext
130
+
131
+ Context replaces direct hook usage within Plank sub-components:
132
+
133
+ - `graph` — ExpandableGraph for node resolution.
134
+ - `node` — the resolved graph node.
135
+ - `layoutMode` — 'deck' | 'solo' | 'solo--fullscreen'.
136
+ - `part` — 'solo' | 'deck' | 'solo-primary' | 'solo-companion'.
137
+ - `settings` — deck plugin settings.
138
+ - `popoverAnchorId` — for heading menu positioning.
139
+ - Callbacks: `onAdjust`, `onResize`, `onScrollIntoView`, `onChangeCompanion`.
140
+
141
+ ### DeckMain Radix-Style Structure
142
+
143
+ ```
144
+ DeckMain (connected wrapper — calls useAtomCapability, usePluginManager)
145
+ └── DeckMain.Root (DeckMainProvider — injects context)
146
+ ├── DeckMain.Content (Main.Content with sidebars)
147
+ │ ├── Deck mode: Stack + Plank[]
148
+ │ └── Solo mode: StackContext + single Plank
149
+ └── DeckMain.Viewport (scroll container)
150
+ ```
151
+
152
+ ### DeckMainContext
153
+
154
+ Context replaces direct hook usage within DeckMain sub-components:
155
+
156
+ - `settings` — deck plugin settings atom.
157
+ - `pluginManager` — for attention capabilities.
158
+ - `state` — combined persisted + ephemeral state.
159
+ - `deck` — active deck state.
160
+ - `updateState` — state updater function.
161
+ - Callback: `onLayoutChange`.
162
+
163
+ ### Mobile Responsiveness
164
+
165
+ Matrix tiles use `w-full md:w-[50rem]` with `snap-x snap-mandatory` on the viewport.
166
+ On mobile (< md breakpoint), each tile fills the viewport width and scroll-snap ensures
167
+ only one tile is visible at a time.
168
+
169
+ ### Story Variants
170
+
171
+ - **Default** — uses StoryTile (simple JSON display, no Surface).
172
+ - **WithSurface** — uses PlankTile (Surface.Surface role='article') with withPluginManager decorator
173
+ providing a surface extension that resolves any object to a Json component.
174
+
175
+ ## DeckMain Functional Spec
176
+
177
+ 1. Renders the main content area with navigation sidebar (left) and complementary sidebar (right).
178
+ 2. Supports three layout modes: `deck` (horizontal scroll of planks), `solo` (single plank), `solo--fullscreen` (single plank without heading).
179
+ 3. In deck mode, renders a `Stack` with horizontal orientation containing all active planks.
180
+ 4. In solo mode, renders a single `Plank` inside a `StackContext.Provider`.
181
+ 5. Both deck and solo views are always mounted; the inactive one gets `sr-only` class and `inert` attribute.
182
+ 6. Handles responsive breakpoints: auto-switches to solo mode on mobile, reverts on desktop.
183
+ 7. Disables deck mode when `settings.enableDeck` is false.
184
+ 8. Persists and restores scroll position when switching between deck and solo modes.
185
+ 9. Manages sidebar state (open/closed/collapsed) for both navigation and complementary sidebars.
186
+ 10. Renders a topbar (`Banner`) when breakpoint and layout mode require it.
187
+ 11. Renders a status bar when breakpoint requires it.
188
+ 12. Shows empty state (`ContentEmpty`) when no planks are active.
189
+ 13. Applies centering overscroll padding when `settings.overscroll === 'centering'`.
190
+ 14. Calculates plank ordering for grid layout (accounts for companions and separators).
191
+ 15. Renders `PlankSeparator` between planks in deck mode.
192
+ 16. Sets CSS custom properties for sidebar widths and first/last plank widths.
193
+ 17. Attends (focuses) the first plank on initial render.
194
+ 18. Handles fullscreen mode by hiding sidebars.
195
+ 19. Applies `Main.Overlay` for dialog dismissal.
196
+ 20. Passes `companionVariant` to planks when companion is open.
197
+
198
+ ## Plank Functional Spec
199
+
200
+ 1. A plank is the main container for a single object's content within a deck.
201
+ 2. Resolves a graph node by ID via `useNode(graph, id)`.
202
+ 3. Optionally pairs with a companion plank (secondary panel showing related content).
203
+ 4. Companion resolution: finds child nodes of type `PLANK_COMPANION_TYPE`, selects by variant preference.
204
+ 5. In solo mode, wraps content in a grid container (`PlankContainer`) with optional companion column.
205
+ 6. In deck mode, renders as a `StackItem.Root` with resizable width.
206
+ 7. Renders a `PlankHeading` with icon, label, action menu, and layout controls.
207
+ 8. Renders content via `Surface.Surface` with `role='article'` and node data.
208
+ 9. Supports keyboard navigation: Escape focuses the parent main, Enter focuses first child.
209
+ 10. Tracks attention via `useAttentionAttributes` for focus-based highlighting.
210
+ 11. Handles scroll-into-view when state requests it, then clears the request.
211
+ 12. Supports resize via `StackItem.ResizeHandle` with debounced size persistence.
212
+ 13. Shows loading placeholder while content resolves.
213
+ 14. Shows error fallback (with 5s timeout) when node cannot be resolved.
214
+ 15. Applies different CSS for solo vs deck vs companion layouts.
215
+ 16. Supports `encapsulatedPlanks` setting (adds borders and margins).
216
+ 17. PlankHeading shows actions from the graph node's child actions.
217
+ 18. PlankHeading supports companion tabs when in companion mode.
218
+ 19. PlankControls provides solo/deck toggle, increment start/end, close, and companion buttons.
219
+ 20. PlankCompanionControls provides close button for the companion panel.
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export { Matrix } from './Matrix';
6
+ export type { MatrixController, MatrixRootProps, MatrixContentProps, MatrixViewportProps } from './Matrix';
@@ -1,6 +1,9 @@
1
1
  //
2
- // Copyright 2023 DXOS.org
2
+ // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export * from './DeckLayout';
6
- export * from './DeckSettings';
5
+ import { type ComponentType, lazy } from 'react';
6
+
7
+ export const DeckSettings: ComponentType<any> = lazy(() => import('./DeckSettings'));
8
+
9
+ export { Matrix } from './Matrix';