@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
@@ -0,0 +1,219 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { useCallback, useEffect, useMemo } from 'react';
6
+
7
+ import { useOperationInvoker } from '@dxos/app-framework/ui';
8
+ import { LayoutOperation } from '@dxos/app-toolkit';
9
+ import { type AttentionSigilAction } from '@dxos/app-toolkit/ui';
10
+ import { useAppGraph } from '@dxos/app-toolkit/ui';
11
+ import { Graph, type Node, useActionRunner, useActions, useNode } from '@dxos/plugin-graph';
12
+ import { getLinkedVariant, useAttention } from '@dxos/react-ui-attention';
13
+
14
+ import { useBreakpoints, useCompanions, useDeckState, useSelectedCompanion, useSelectedCompanionVariant } from '#hooks';
15
+ import { meta } from '#meta';
16
+ import { DeckOperation, type LayoutMode, PLANK_COMPANION_TYPE, type ResolvedPart } from '#types';
17
+
18
+ /** Sigil-menu dispositions surfaced as plank actions. */
19
+ const PLANK_ACTION_DISPOSITIONS = ['list-item', 'list-item-primary', 'heading-list-item'];
20
+
21
+ /** Capability flags that gate the plank toolbar controls. */
22
+ export type PlankCapabilities = {
23
+ deck?: boolean;
24
+ solo?: boolean;
25
+ incrementStart?: boolean;
26
+ incrementEnd?: boolean;
27
+ fullscreen?: boolean;
28
+ companion?: boolean;
29
+ };
30
+
31
+ export type UseDeckPlankOptions = {
32
+ id: string;
33
+ /** Resolved part for the primary plank (`solo` | `multi` | `complementary`). */
34
+ part: ResolvedPart;
35
+ layoutMode: LayoutMode;
36
+ /** Ordered active planks (multi mode); enables increment/close-range semantics. */
37
+ active?: string[];
38
+ /** Whether the companion pane should be shown for this plank (gated further by attention in multi-mode). */
39
+ companionShown?: boolean;
40
+ deckEnabled?: boolean;
41
+ };
42
+
43
+ export type DeckPlank = {
44
+ node: Node.Node | undefined;
45
+ companions: Node.Node[];
46
+ resolvedCompanionId: string | undefined;
47
+ currentCompanion: Node.Node | undefined;
48
+ hasCompanion: boolean;
49
+ /** Splitter orientation for the companion pane (defaults to `horizontal`). */
50
+ companionOrientation: 'horizontal' | 'vertical';
51
+ capabilities: PlankCapabilities;
52
+ /** Grouped sigil-menu actions, or `undefined` when the node is unresolved. */
53
+ sigilActions: AttentionSigilAction[][] | undefined;
54
+ popoverAnchorId?: string;
55
+ scrollIntoView?: string;
56
+ onAction: (action: AttentionSigilAction) => void;
57
+ onAdjust: (type: DeckOperation.PartAdjustment) => void;
58
+ onResize: (size: number) => void;
59
+ onScrollIntoView: (subject?: string) => void;
60
+ onUpdateCompanion: (companion: string | null) => void;
61
+ };
62
+
63
+ /**
64
+ * Resolves the graph node, companions, capabilities and sigil actions for a deck plank, and exposes the
65
+ * operation dispatchers that mutate deck layout state. This re-homes the framework wiring that the legacy
66
+ * `PlankContainer`/`PlankHeading` bundled, so the presentational components stay free of capabilities.
67
+ */
68
+ export const useDeckPlank = ({
69
+ id,
70
+ part,
71
+ layoutMode,
72
+ active,
73
+ companionShown,
74
+ deckEnabled,
75
+ }: UseDeckPlankOptions): DeckPlank => {
76
+ const { graph } = useAppGraph();
77
+ const { invokePromise } = useOperationInvoker();
78
+ const { state, deck } = useDeckState();
79
+ const runAction = useActionRunner();
80
+ const breakpoint = useBreakpoints();
81
+ const node = useNode(graph, id);
82
+ // Subscribe reactively to the node's actions: they are loaded asynchronously by `Graph.expand`
83
+ // below, and the node atom does not re-emit when action edges arrive, so a one-shot read would
84
+ // leave a freshly-created plank's sigil menu empty until an unrelated re-render.
85
+ const actions = useActions(graph, node?.id);
86
+ const companions = useCompanions(id);
87
+ const { hasAttention } = useAttention(id);
88
+ const selectedVariant = useSelectedCompanionVariant();
89
+
90
+ // The companion is shown when open; in multi mode it attaches only to the attended plank (hidden until
91
+ // a plank gains attention). Which companion shows follows the globally-selected variant (view state),
92
+ // falling back to the first when none is stored.
93
+ const showCompanion = !!companionShown && (layoutMode !== 'multi' || hasAttention);
94
+ const { companionId } = useSelectedCompanion(companions, showCompanion ? selectedVariant : undefined);
95
+ const resolvedCompanionId = showCompanion ? companionId : undefined;
96
+ const currentCompanion = companions.find((companion) => companion.id === resolvedCompanionId);
97
+ const hasCompanion = !!(resolvedCompanionId && currentCompanion);
98
+ const companionOrientation = deck.companionOrientation ?? 'horizontal';
99
+
100
+ // Ordering within the active stack drives the increment-start/end affordances.
101
+ const index = active ? active.findIndex((entryId) => entryId === id) : -1;
102
+ const isOrdered = !!active && index >= 0;
103
+ const canIncrementStart = isOrdered && index > 0;
104
+ const canIncrementEnd = isOrdered && index < (active?.length ?? 1) - 1;
105
+
106
+ const isCompanionNode = node?.type === PLANK_COMPANION_TYPE;
107
+ const capabilities = useMemo<PlankCapabilities>(
108
+ () => ({
109
+ deck: deckEnabled ?? true,
110
+ solo: breakpoint !== 'mobile' && (part === 'solo' || part === 'multi'),
111
+ incrementStart: canIncrementStart,
112
+ incrementEnd: canIncrementEnd,
113
+ fullscreen: !isCompanionNode,
114
+ // Offer to open the companion (solo, or the attended plank in multi) when one exists and isn't shown.
115
+ companion: !isCompanionNode && companions.length > 0 && !hasCompanion && (layoutMode !== 'multi' || hasAttention),
116
+ }),
117
+ [
118
+ deckEnabled,
119
+ breakpoint,
120
+ part,
121
+ canIncrementStart,
122
+ canIncrementEnd,
123
+ isCompanionNode,
124
+ layoutMode,
125
+ companions.length,
126
+ hasCompanion,
127
+ hasAttention,
128
+ ],
129
+ );
130
+
131
+ // Load the node's child actions so the sigil menu is populated.
132
+ useEffect(() => {
133
+ const frame = requestAnimationFrame(() => {
134
+ if (node) {
135
+ void Graph.expand(graph, node.id, 'child');
136
+ }
137
+ });
138
+
139
+ return () => cancelAnimationFrame(frame);
140
+ }, [graph, node]);
141
+
142
+ const variant = isCompanionNode ? getLinkedVariant(id) : undefined;
143
+ const sigilActions = useMemo<AttentionSigilAction[][] | undefined>(() => {
144
+ if (!node) {
145
+ return undefined;
146
+ }
147
+ if (variant) {
148
+ return [];
149
+ }
150
+
151
+ return [actions.filter((action) => PLANK_ACTION_DISPOSITIONS.includes(action.properties.disposition))].filter(
152
+ (group) => group.length > 0,
153
+ );
154
+ }, [actions, node, variant]);
155
+
156
+ const onAction = useCallback(
157
+ (action: AttentionSigilAction) => {
158
+ // Only actions whose `data` is a function are runnable graph actions; the menu-action view type
159
+ // (AttentionSigilAction) is widened, so narrow at this runtime-checked boundary.
160
+ if (typeof action.data === 'function') {
161
+ void runAction(action as Node.Action, { parent: node, caller: meta.profile.key });
162
+ }
163
+ },
164
+ [node, runAction],
165
+ );
166
+
167
+ const onAdjust = useCallback(
168
+ (type: DeckOperation.PartAdjustment) => {
169
+ if (type === 'close') {
170
+ if (part === 'complementary') {
171
+ return invokePromise(LayoutOperation.UpdateComplementary, { state: 'collapsed' });
172
+ }
173
+ if (active) {
174
+ // Close the plank and everything to its right (stack pop).
175
+ const closeIndex = active.indexOf(id);
176
+ const toClose = closeIndex !== -1 ? active.slice(closeIndex) : [id];
177
+ return invokePromise(LayoutOperation.Close, { subject: toClose });
178
+ }
179
+ return invokePromise(LayoutOperation.Close, { subject: [id] });
180
+ }
181
+
182
+ return invokePromise(DeckOperation.Adjust, { type, id });
183
+ },
184
+ [invokePromise, part, active, id],
185
+ );
186
+
187
+ const onResize = useCallback(
188
+ (size: number) => invokePromise(DeckOperation.UpdatePlankSize, { id, size }),
189
+ [invokePromise, id],
190
+ );
191
+
192
+ const onScrollIntoView = useCallback(
193
+ (subject?: string) => invokePromise(LayoutOperation.ScrollIntoView, { subject }),
194
+ [invokePromise],
195
+ );
196
+
197
+ const onUpdateCompanion = useCallback(
198
+ (companion: string | null) => invokePromise(LayoutOperation.UpdateCompanion, { subject: companion }),
199
+ [invokePromise],
200
+ );
201
+
202
+ return {
203
+ node,
204
+ companions,
205
+ resolvedCompanionId,
206
+ currentCompanion,
207
+ hasCompanion,
208
+ companionOrientation,
209
+ capabilities,
210
+ sigilActions,
211
+ popoverAnchorId: state.popoverAnchorId,
212
+ scrollIntoView: state.scrollIntoView,
213
+ onAction,
214
+ onAdjust,
215
+ onResize,
216
+ onScrollIntoView,
217
+ onUpdateCompanion,
218
+ };
219
+ };
@@ -17,10 +17,12 @@ import { GraphBuilder, Node, NodeMatcher, useConnections } from '@dxos/plugin-gr
17
17
  import { corePlugins } from '@dxos/plugin-testing';
18
18
  import { random } from '@dxos/random';
19
19
  import { useAsyncEffect } from '@dxos/react-hooks';
20
- import { Icon, List, ListItem, Panel } from '@dxos/react-ui';
20
+ import { Panel } from '@dxos/react-ui';
21
21
  import { linkedSegment } from '@dxos/react-ui-attention';
22
+ import { Listbox } from '@dxos/react-ui-list';
22
23
  import { Syntax } from '@dxos/react-ui-syntax-highlighter';
23
24
  import { Loading, withLayout } from '@dxos/react-ui/testing';
25
+ import { Position } from '@dxos/util';
24
26
 
25
27
  import { OperationHandler } from '#capabilities';
26
28
  import { meta as pluginMeta } from '#meta';
@@ -28,11 +30,11 @@ import { translations } from '#translations';
28
30
  import {
29
31
  DeckCapabilities,
30
32
  type EphemeralDeckState,
33
+ PLANK_COMPANION_TYPE,
31
34
  type Settings,
32
35
  type StoredDeckState,
33
36
  defaultDeck,
34
37
  getMode,
35
- PLANK_COMPANION_TYPE,
36
38
  } from '#types';
37
39
 
38
40
  import { DeckLayout } from './DeckLayout';
@@ -167,15 +169,14 @@ const TestPlugin = Plugin.define(pluginMeta).pipe(
167
169
  Capability.contributes(Capabilities.ReactSurface, [
168
170
  Surface.create({
169
171
  id: 'storyNavigation',
170
- role: 'navigation',
171
- filter: (data): data is { current: string } => typeof (data as any).current === 'string',
172
- component: ({ data, ref }) => <NavContainer current={data.current} ref={ref} />,
172
+ filter: Surface.makeFilter(AppSurface.Navigation),
173
+ component: ({ data, ref }) => (
174
+ <NavContainer current={data.current} ref={ref as React.Ref<HTMLDivElement>} />
175
+ ),
173
176
  }),
174
177
  Surface.create({
175
178
  id: 'storyArticle',
176
- role: 'article',
177
- filter: (data): data is Record<string, unknown> =>
178
- typeof data === 'object' && data !== null && (data as { companionTo?: unknown }).companionTo == null,
179
+ filter: Surface.makeFilter(AppSurface.Article, (data) => data.companionTo == null),
179
180
  component: ({ data }) => {
180
181
  const subject = (data as any)?.subject;
181
182
  const attendableId = (data as any)?.attendableId as string | undefined;
@@ -202,9 +203,7 @@ const TestPlugin = Plugin.define(pluginMeta).pipe(
202
203
  }),
203
204
  Surface.create({
204
205
  id: 'storyArticleCompanion',
205
- role: 'article',
206
- filter: (data): data is AppSurface.ArticleData<unknown, {}, unknown> =>
207
- typeof data === 'object' && data !== null && (data as { companionTo?: unknown }).companionTo != null,
206
+ filter: Surface.makeFilter(AppSurface.Article, (data) => data.companionTo != null),
208
207
  component: ({ data: { subject, companionTo, properties, variant } }) => {
209
208
  if (companionTo == null) {
210
209
  return <Loading />;
@@ -248,7 +247,7 @@ const TestPlugin = Plugin.define(pluginMeta).pipe(
248
247
  label: 'Companion Alpha',
249
248
  icon: 'ph--sidebar--regular',
250
249
  data: { variant: 'alpha', parentId: node.id },
251
- position: 'first',
250
+ position: Position.first,
252
251
  }),
253
252
  AppNode.makeCompanion({
254
253
  id: linkedSegment('beta'),
@@ -279,24 +278,23 @@ const NavContainer = forwardRef<HTMLDivElement, NavContainerProps>((_props, forw
279
278
 
280
279
  return (
281
280
  <div className='dx-container overflow-y-auto p-2' ref={forwardedRef}>
282
- <List>
283
- {items.map((node) => (
284
- <ListItem.Root
285
- key={node.id}
286
- classNames={activeSet.has(node.id) ? 'bg-current-surface' : undefined}
287
- onClick={() => void invokePromise(LayoutOperation.Set, { subject: [node.id] })}
288
- >
289
- {node.properties.icon && (
290
- <ListItem.Endcap>
291
- <Icon icon={node.properties.icon} />
292
- </ListItem.Endcap>
293
- )}
294
- <ListItem.Heading classNames='cursor-pointer'>
295
- {typeof node.properties.label === 'string' ? node.properties.label : node.id}
296
- </ListItem.Heading>
297
- </ListItem.Root>
298
- ))}
299
- </List>
281
+ <Listbox.Root>
282
+ <Listbox.Content aria-label='Navigation'>
283
+ {items.map((node) => (
284
+ <Listbox.Item
285
+ key={node.id}
286
+ id={node.id}
287
+ classNames={activeSet.has(node.id) ? 'bg-current-surface' : undefined}
288
+ onClick={() => void invokePromise(LayoutOperation.Set, { subject: [node.id] })}
289
+ >
290
+ <Listbox.ItemContent
291
+ icon={node.properties.icon}
292
+ title={typeof node.properties.label === 'string' ? node.properties.label : node.id}
293
+ />
294
+ </Listbox.Item>
295
+ ))}
296
+ </Listbox.Content>
297
+ </Listbox.Root>
300
298
  </div>
301
299
  );
302
300
  });
@@ -315,36 +313,22 @@ const ItemComponent = ({ id }: ItemComponentProps) => {
315
313
  );
316
314
 
317
315
  return (
318
- <List>
319
- {items.map((node) => {
320
- const open = () =>
321
- void invokePromise(LayoutOperation.Open, { subject: [node.id], pivotId: id, navigation: 'immediate' });
322
- return (
323
- <ListItem.Root
324
- key={node.id}
325
- classNames='dx-hover cursor-pointer'
326
- role='button'
327
- tabIndex={0}
328
- onClick={open}
329
- onKeyDown={(event) => {
330
- if (event.key === 'Enter' || event.key === ' ') {
331
- event.preventDefault();
332
- open();
333
- }
334
- }}
335
- >
336
- {node.properties.icon && (
337
- <ListItem.Endcap>
338
- <Icon icon={node.properties.icon} size={4} />
339
- </ListItem.Endcap>
340
- )}
341
- <ListItem.Heading classNames='truncate'>
342
- {typeof node.properties.label === 'string' ? node.properties.label : node.id}
343
- </ListItem.Heading>
344
- </ListItem.Root>
345
- );
346
- })}
347
- </List>
316
+ <Listbox.Root>
317
+ <Listbox.Content aria-label='Items'>
318
+ {items.map((node) => {
319
+ const open = () =>
320
+ void invokePromise(LayoutOperation.Open, { subject: [node.id], pivotId: id, navigation: 'immediate' });
321
+ return (
322
+ <Listbox.Item key={node.id} id={node.id} classNames='dx-hover cursor-pointer' onClick={open}>
323
+ <Listbox.ItemContent
324
+ icon={node.properties.icon}
325
+ title={typeof node.properties.label === 'string' ? node.properties.label : node.id}
326
+ />
327
+ </Listbox.Item>
328
+ );
329
+ })}
330
+ </Listbox.Content>
331
+ </Listbox.Root>
348
332
  );
349
333
  };
350
334
 
@@ -10,7 +10,7 @@ import { AlertDialog, Dialog as NaturalDialog } from '@dxos/react-ui';
10
10
 
11
11
  import { useDeckState } from '#hooks';
12
12
 
13
- import { PlankErrorFallback } from '../Plank';
13
+ import { PlankErrorFallback } from '../Deck/PlankFallback';
14
14
 
15
15
  export const Dialog = () => {
16
16
  const { state, updateEphemeral } = useDeckState();
@@ -9,7 +9,7 @@ import { useTranslation } from '@dxos/react-ui';
9
9
  import { meta } from '#meta';
10
10
 
11
11
  const Fallback = () => {
12
- const { t } = useTranslation(meta.id);
12
+ const { t } = useTranslation(meta.profile.key);
13
13
 
14
14
  return (
15
15
  <div className='min-h-screen w-full flex items-center justify-center p-8'>
@@ -10,10 +10,12 @@ import { AppSurface, useObjectMenuItems } from '@dxos/app-toolkit/ui';
10
10
  import { Obj } from '@dxos/echo';
11
11
  import {
12
12
  Card,
13
+ Icon,
14
+ IconButton,
13
15
  Popover,
14
16
  type PopoverContentInteractOutsideEvent,
15
17
  toLocalizedString,
16
- Toolbar,
18
+ useMediaQuery,
17
19
  useTranslation,
18
20
  } from '@dxos/react-ui';
19
21
  import { Menu } from '@dxos/react-ui-menu';
@@ -54,9 +56,12 @@ export const PopoverRoot = ({ children }: PopoverRootProps) => {
54
56
  }
55
57
  }, [state.popoverOpen, state.popoverAnchorId, state.popoverAnchor, state.popoverContent]);
56
58
 
59
+ // The rename popover is modal so other navtree item menus are inert while it is open.
60
+ const modal = state.popoverKind === 'rename';
61
+
57
62
  return (
58
63
  <DeckPopoverProvider setOpen={setOpen}>
59
- <Popover.Root modal={false} open={open}>
64
+ <Popover.Root modal={modal} open={open}>
60
65
  {state.popoverAnchor && <Popover.VirtualTrigger key={virtualIter} virtualRef={virtualRef} />}
61
66
  {children}
62
67
  </Popover.Root>
@@ -65,7 +70,7 @@ export const PopoverRoot = ({ children }: PopoverRootProps) => {
65
70
  };
66
71
 
67
72
  export const PopoverContent = () => {
68
- const { t } = useTranslation(meta.id);
73
+ const { t } = useTranslation(meta.profile.key);
69
74
  const { state, updateEphemeral } = useDeckState();
70
75
  const { setOpen } = useDeckPopoverContext('PopoverContent');
71
76
  const popoverSubject =
@@ -75,8 +80,14 @@ export const PopoverContent = () => {
75
80
  const title = state.popoverTitle ? toLocalizedString(state.popoverTitle, t) : 'Unknown';
76
81
  const icon = isObjectPopover ? (Obj.getIcon(popoverSubject)?.icon ?? 'ph--circle-dashed--regular') : undefined;
77
82
  const content = state.popoverContent;
78
- // A base popover renders a plugin-provided component; everything else falls through to the card.
79
- const isBasePopover = state.popoverKind === 'base' && !!content && 'component' in content;
83
+ // Base and rename popovers render a plugin-provided component; everything else falls through to the card.
84
+ const isComponentPopover =
85
+ (state.popoverKind === 'base' || state.popoverKind === 'rename') && !!content && 'component' in content;
86
+ const isRename = state.popoverKind === 'rename';
87
+
88
+ // Anchor to the right of the row on wide displays; drop centered below on narrow ones.
89
+ const [isLg] = useMediaQuery('lg', { fallback: [true] });
90
+ const side = isRename ? (isLg ? 'right' : 'bottom') : state.popoverSide;
80
91
 
81
92
  const handleClose = useCallback(() => {
82
93
  setOpen(false);
@@ -91,15 +102,14 @@ export const PopoverContent = () => {
91
102
 
92
103
  const handleInteractOutside = useCallback(
93
104
  (event: KeyboardEvent | PopoverContentInteractOutsideEvent) => {
94
- if (
95
- // TODO(thure): CodeMirror should not focus itself when it updates.
96
- event.type === 'dismissableLayer.focusOutside' &&
97
- (event.currentTarget as HTMLElement | undefined)?.classList.contains('cm-content')
98
- ) {
105
+ // Focus leaving the popover (clicking into the card surfaces a portaled menu, or CodeMirror
106
+ // re-focusing itself) must not dismiss it only a pointer-down genuinely outside the card, or
107
+ // Escape, closes. (Clicks inside the card never reach here; Radix scopes them to the content.)
108
+ if (event.type === 'dismissableLayer.focusOutside') {
99
109
  event.preventDefault();
100
- } else {
101
- handleClose();
110
+ return;
102
111
  }
112
+ handleClose();
103
113
  },
104
114
  [handleClose],
105
115
  );
@@ -107,15 +117,22 @@ export const PopoverContent = () => {
107
117
  return (
108
118
  <Popover.Portal>
109
119
  <Popover.Content
110
- side={state.popoverSide}
120
+ side={side}
111
121
  sticky='always'
112
122
  hideWhenDetached
113
- onOpenAutoFocus={(event) => event.preventDefault()}
123
+ // Rename focuses its input; other popovers keep focus where it was.
124
+ onOpenAutoFocus={isRename ? undefined : (event) => event.preventDefault()}
114
125
  onInteractOutside={handleInteractOutside}
115
126
  onEscapeKeyDown={handleInteractOutside}
127
+ // Reuse the dialog's enter/exit motion so the rename popover does not flicker on open.
128
+ classNames={
129
+ isRename
130
+ ? ['data-[state=open]:animate-slide-up-and-fade', 'data-[state=closed]:animate-slide-down-and-fade']
131
+ : undefined
132
+ }
116
133
  >
117
134
  <Popover.Viewport>
118
- {isBasePopover && content && 'component' in content ? (
135
+ {isComponentPopover && content && 'component' in content ? (
119
136
  /* Base popover: a plugin-provided component (e.g. editor link preview). */
120
137
  <Surface.Surface type={AppSurface.Popover} data={content} limit={1} />
121
138
  ) : (
@@ -129,12 +146,12 @@ export const PopoverContent = () => {
129
146
  <Menu.Root>
130
147
  <Card.Root border={false} classNames='dx-card-popover'>
131
148
  <Card.Header>
132
- <Card.IconBlock>{icon && <Card.Icon icon={icon} />}</Card.IconBlock>
149
+ <Card.Block>{icon && <Icon icon={icon} />}</Card.Block>
133
150
  <Card.Title>{title}</Card.Title>
134
151
  {/* TODO(wittjosiah): Reconcile with Card.Menu. */}
135
- <Card.IconBlock>
152
+ <Card.Block end>
136
153
  <Menu.Trigger asChild disabled={!objectMenuItems.length}>
137
- <Toolbar.IconButton
154
+ <IconButton
138
155
  variant='ghost'
139
156
  density='sm'
140
157
  icon='ph--dots-three-vertical--regular'
@@ -143,11 +160,11 @@ export const PopoverContent = () => {
143
160
  />
144
161
  </Menu.Trigger>
145
162
  <Menu.Content items={objectMenuItems} />
146
- </Card.IconBlock>
163
+ </Card.Block>
147
164
  </Card.Header>
148
165
 
149
166
  {content && 'subject' in content ? (
150
- <Surface.Surface type={AppSurface.Card} data={content} limit={1} />
167
+ <Surface.Surface type={AppSurface.CardContent} data={content} limit={1} />
151
168
  ) : (
152
169
  <Card.Body classNames='min-bs-8'>
153
170
  <Card.Row>
@@ -21,7 +21,7 @@ export const Toast = ({
21
21
  onAction,
22
22
  onOpenChange,
23
23
  }: LayoutOperation.Toast & Pick<ToastRootProps, 'onOpenChange'>) => {
24
- const { t } = useTranslation(meta.id);
24
+ const { t } = useTranslation(meta.profile.key);
25
25
 
26
26
  // Control the open state so closing flips Radix's `open` (playing the exit animation) rather than
27
27
  // unmounting abruptly. Both the close button and Radix's own timeout/swipe route through here.
@@ -11,7 +11,7 @@ import { translations } from '#translations';
11
11
  import { DeckSettings } from './DeckSettings';
12
12
 
13
13
  const meta = {
14
- title: 'plugins/plugin-deck/components/DeckSettings',
14
+ title: 'plugins/plugin-deck/containers/DeckSettings',
15
15
  tags: ['settings'],
16
16
  component: DeckSettings,
17
17
  decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
@@ -0,0 +1,42 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { type AppSurface } from '@dxos/app-toolkit/ui';
8
+ import { useTranslation } from '@dxos/react-ui';
9
+ import { Form } from '@dxos/react-ui-form';
10
+
11
+ import { meta } from '#meta';
12
+ import { Settings } from '#types';
13
+
14
+ const isSocket = !!(globalThis as any).__args;
15
+
16
+ export type DeckSettingsProps = AppSurface.SettingsProps<Settings.Settings>;
17
+
18
+ export const DeckSettings = ({ settings, onSettingsChange }: DeckSettingsProps) => {
19
+ const { t } = useTranslation(meta.profile.key);
20
+
21
+ return (
22
+ <Form.Root
23
+ variant='settings'
24
+ schema={Settings.Settings}
25
+ values={settings}
26
+ readonly={!onSettingsChange}
27
+ onValuesChanged={(values) => onSettingsChange?.((current) => ({ ...current, ...values }))}
28
+ >
29
+ <Form.Viewport scroll>
30
+ <Form.Content>
31
+ <Form.Section title={meta.profile.name ?? meta.profile.key}>
32
+ <Form.FieldSet
33
+ filter={(properties) =>
34
+ isSocket ? properties.filter((property) => property.name !== 'enableNativeRedirect') : properties
35
+ }
36
+ />
37
+ </Form.Section>
38
+ </Form.Content>
39
+ </Form.Viewport>
40
+ </Form.Root>
41
+ );
42
+ };
@@ -6,7 +6,8 @@ import React, { type MouseEvent, useCallback, useEffect, useMemo, useState } fro
6
6
 
7
7
  import { Surface, useOperationInvoker } from '@dxos/app-framework/ui';
8
8
  import { LayoutOperation } from '@dxos/app-toolkit';
9
- import { IconButton, type Label, Main, Panel, toLocalizedString, Toolbar, useTranslation } from '@dxos/react-ui';
9
+ import { AppSurface } from '@dxos/app-toolkit/ui';
10
+ import { IconButton, type Label, Main, Panel, Toolbar, toLocalizedString, useTranslation } from '@dxos/react-ui';
10
11
  import { getLinkedVariant } from '@dxos/react-ui-attention';
11
12
  import { Tabs } from '@dxos/react-ui-tabs';
12
13
  import { iconSize, mx } from '@dxos/ui-theme';
@@ -16,10 +17,10 @@ import { meta } from '#meta';
16
17
  import { getMode } from '#types';
17
18
 
18
19
  import { layoutAppliesTopbar } from '../../util';
19
- import { PlankErrorFallback, PlankLoading } from '../Plank';
20
+ import { PlankErrorFallback, PlankLoading } from '../Deck/PlankFallback';
20
21
  import { ToggleComplementarySidebarButton } from './SidebarButton';
21
22
 
22
- const label = ['complementary-sidebar.title', { ns: meta.id }] satisfies Label;
23
+ const label = ['complementary-sidebar.title', { ns: meta.profile.key }] satisfies Label;
23
24
 
24
25
  export type ComplementarySidebarProps = {
25
26
  current?: string;
@@ -27,7 +28,7 @@ export type ComplementarySidebarProps = {
27
28
 
28
29
  export const ComplementarySidebar = ({ current }: ComplementarySidebarProps) => {
29
30
  const { invokePromise } = useOperationInvoker();
30
- const { t } = useTranslation(meta.id);
31
+ const { t } = useTranslation(meta.profile.key);
31
32
  const { state, deck, updateState } = useDeckState();
32
33
  const layoutMode = getMode(deck);
33
34
  const breakpoint = useBreakpoints();
@@ -117,7 +118,7 @@ export const ComplementarySidebar = ({ current }: ComplementarySidebarProps) =>
117
118
  className='grid grid-cols-1 auto-rows-(--dx-rail-item) py-0.5 gap-0.5 overflow-y-auto scrollbar-none'
118
119
  style={iconSize(4)}
119
120
  >
120
- <Surface.Surface role='status-indicator' />
121
+ <Surface.Surface type={AppSurface.StatusIndicator} />
121
122
  </div>
122
123
  <div className='hidden lg:grid grid-cols-1 auto-rows-(--dx-rail-action) p-1'>
123
124
  <ToggleComplementarySidebarButton />
@@ -154,7 +155,7 @@ type ComplementarySidebarPanelProps = {
154
155
  };
155
156
 
156
157
  const ComplementarySidebarPanel = ({ companion, activeId, data }: ComplementarySidebarPanelProps) => {
157
- const { t } = useTranslation(meta.id);
158
+ const { t } = useTranslation(meta.profile.key);
158
159
 
159
160
  if (getLinkedVariant(companion.id) !== activeId && !data) {
160
161
  return null;
@@ -178,7 +179,7 @@ const ComplementarySidebarPanel = ({ companion, activeId, data }: ComplementaryS
178
179
  </Panel.Toolbar>
179
180
  <Panel.Content classNames='bg-r1-surface'>
180
181
  <Surface.Surface
181
- role={`deck-companion--${getLinkedVariant(companion.id)}`}
182
+ type={AppSurface.deckCompanion(getLinkedVariant(companion.id))}
182
183
  data={data}
183
184
  fallback={PlankErrorFallback}
184
185
  placeholder={<PlankLoading />}
@@ -14,7 +14,7 @@ import { getMode } from '#types';
14
14
 
15
15
  import { layoutAppliesTopbar } from '../../util';
16
16
 
17
- const label = ['sidebar.title', { ns: meta.id }] satisfies Label;
17
+ const label = ['sidebar.title', { ns: meta.profile.key }] satisfies Label;
18
18
 
19
19
  export const Sidebar = () => {
20
20
  const { state, deck } = useDeckState();