@dxos/plugin-deck 0.9.0 → 0.9.1-main.c7dcc2e112

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 (158) hide show
  1. package/dist/lib/neutral/{DeckLayout-DEURA3KR.mjs → DeckLayout-VX2BP4Q2.mjs} +35 -22
  2. package/dist/lib/neutral/DeckLayout-VX2BP4Q2.mjs.map +7 -0
  3. package/dist/lib/neutral/DeckPlugin.mjs +2 -2
  4. package/dist/lib/neutral/DeckPlugin.mjs.map +4 -4
  5. package/dist/lib/neutral/{DeckSettings-W5I57OXM.mjs → DeckSettings-CQQZJ2YS.mjs} +3 -3
  6. package/dist/lib/neutral/DeckSettings-CQQZJ2YS.mjs.map +7 -0
  7. package/dist/lib/neutral/{add-toast-TNB6DXWU.mjs → add-toast-APKTCLIA.mjs} +2 -2
  8. package/dist/lib/neutral/{adjust-HNU5CCRO.mjs → adjust-7CZI4GK3.mjs} +3 -3
  9. package/dist/lib/neutral/{app-graph-builder-HMLT627T.mjs → app-graph-builder-6HTXRTU2.mjs} +5 -5
  10. package/dist/lib/neutral/app-graph-builder-6HTXRTU2.mjs.map +7 -0
  11. package/dist/lib/neutral/capabilities/index.mjs +8 -8
  12. package/dist/lib/neutral/{check-app-scheme-INSOF72J.mjs → check-app-scheme-HSAORHHX.mjs} +2 -2
  13. package/dist/lib/neutral/{chunk-BS4EOYMK.mjs → chunk-CL7JIOI5.mjs} +28 -14
  14. package/dist/lib/neutral/chunk-CL7JIOI5.mjs.map +7 -0
  15. package/dist/lib/neutral/{chunk-WAXJPQJI.mjs → chunk-DNG3L5QN.mjs} +31 -33
  16. package/dist/lib/neutral/chunk-DNG3L5QN.mjs.map +7 -0
  17. package/dist/lib/neutral/chunk-KY7LMF4D.mjs +46 -0
  18. package/dist/lib/neutral/chunk-KY7LMF4D.mjs.map +7 -0
  19. package/dist/lib/neutral/{chunk-324PPIZB.mjs → chunk-KZFJ4PBT.mjs} +4 -4
  20. package/dist/lib/neutral/chunk-KZFJ4PBT.mjs.map +7 -0
  21. package/dist/lib/neutral/{chunk-GBIGQKYW.mjs → chunk-NGX6RXNV.mjs} +4 -4
  22. package/dist/lib/neutral/chunk-NGX6RXNV.mjs.map +7 -0
  23. package/dist/lib/neutral/chunk-UZLAR4DR.mjs +8 -0
  24. package/dist/lib/neutral/{close-ASKR22A6.mjs → close-KJUCFIJ5.mjs} +3 -3
  25. package/dist/lib/neutral/components/index.mjs +1 -1
  26. package/dist/lib/neutral/containers/index.mjs +3 -3
  27. package/dist/lib/neutral/index.mjs +12 -2
  28. package/dist/lib/neutral/meta.json +1 -1
  29. package/dist/lib/neutral/meta.mjs +1 -1
  30. package/dist/lib/neutral/{notification-tracker-P36322BH.mjs → notification-tracker-CUDFRDCF.mjs} +9 -9
  31. package/dist/lib/neutral/{notification-tracker-P36322BH.mjs.map → notification-tracker-CUDFRDCF.mjs.map} +3 -3
  32. package/dist/lib/neutral/{open-5OYNO3RT.mjs → open-VU7YS3HB.mjs} +7 -7
  33. package/dist/lib/neutral/open-VU7YS3HB.mjs.map +7 -0
  34. package/dist/lib/neutral/operations/index.mjs +1 -1
  35. package/dist/lib/neutral/plugin.mjs +2 -2
  36. package/dist/lib/neutral/{react-root-HH5DEUOG.mjs → react-root-E6TAFHX6.mjs} +2 -2
  37. package/dist/lib/neutral/react-root-E6TAFHX6.mjs.map +7 -0
  38. package/dist/lib/neutral/{react-surface-3UVVCK3O.mjs → react-surface-O4POQWYL.mjs} +4 -5
  39. package/dist/lib/neutral/react-surface-O4POQWYL.mjs.map +7 -0
  40. package/dist/lib/neutral/{revert-workspace-B2QLT2C4.mjs → revert-workspace-24TKG3I7.mjs} +2 -2
  41. package/dist/lib/neutral/{scroll-into-view-B52C3PJO.mjs → scroll-into-view-3VXT6TWC.mjs} +2 -2
  42. package/dist/lib/neutral/{set-PA35ONXO.mjs → set-RFOLTI57.mjs} +3 -3
  43. package/dist/lib/neutral/{set-layout-mode-RPCCPQRB.mjs → set-layout-mode-AZ73W52Z.mjs} +2 -2
  44. package/dist/lib/neutral/{settings-EGNYUM4T.mjs → settings-6CDQEB6B.mjs} +3 -3
  45. package/dist/lib/neutral/settings-6CDQEB6B.mjs.map +7 -0
  46. package/dist/lib/neutral/{state-IIDXMQUO.mjs → state-D3YXB5NP.mjs} +3 -3
  47. package/dist/lib/neutral/{state-IIDXMQUO.mjs.map → state-D3YXB5NP.mjs.map} +2 -2
  48. package/dist/lib/neutral/{switch-workspace-LZF4KZXH.mjs → switch-workspace-TBPT23CZ.mjs} +4 -4
  49. package/dist/lib/neutral/switch-workspace-TBPT23CZ.mjs.map +7 -0
  50. package/dist/lib/neutral/translations.mjs +1 -1
  51. package/dist/lib/neutral/translations.mjs.map +3 -3
  52. package/dist/lib/neutral/types/index.mjs +11 -1
  53. package/dist/lib/neutral/{update-companion-YUCZZVGY.mjs → update-companion-5LCY6QME.mjs} +2 -2
  54. package/dist/lib/neutral/{update-complementary-7FZNB55J.mjs → update-complementary-HZ7QXZYE.mjs} +2 -2
  55. package/dist/lib/neutral/{update-dialog-FNQTSSAP.mjs → update-dialog-A7W3R5EI.mjs} +2 -2
  56. package/dist/lib/neutral/{update-plank-size-3YW4NXEY.mjs → update-plank-size-XHTYBLSD.mjs} +2 -2
  57. package/dist/lib/neutral/{update-popover-G2VUD7E6.mjs → update-popover-RDIHG73B.mjs} +2 -2
  58. package/dist/lib/neutral/{update-sidebar-KRHPUHUB.mjs → update-sidebar-GEI7USA5.mjs} +2 -2
  59. package/dist/lib/neutral/{url-handler-A6HLW4RB.mjs → url-handler-PUS4X33T.mjs} +10 -10
  60. package/dist/lib/neutral/url-handler-PUS4X33T.mjs.map +7 -0
  61. package/dist/types/dx.config.d.ts +28 -0
  62. package/dist/types/dx.config.d.ts.map +1 -0
  63. package/dist/types/src/capabilities/index.d.ts +8 -196
  64. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  65. package/dist/types/src/capabilities/react-surface.d.ts +2 -2
  66. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  67. package/dist/types/src/capabilities/state.d.ts +2 -2
  68. package/dist/types/src/components/Matrix/Matrix.stories.d.ts.map +1 -1
  69. package/dist/types/src/containers/Deck/Banner.d.ts.map +1 -1
  70. package/dist/types/src/containers/Deck/DeckViewport.d.ts.map +1 -1
  71. package/dist/types/src/containers/Deck/StatusBar.d.ts.map +1 -1
  72. package/dist/types/src/containers/DeckLayout/DeckLayout.stories.d.ts.map +1 -1
  73. package/dist/types/src/containers/DeckLayout/Popover.d.ts.map +1 -1
  74. package/dist/types/src/containers/Plank/PlankHeading.d.ts.map +1 -1
  75. package/dist/types/src/containers/Sidebar/ComplementarySidebar.d.ts.map +1 -1
  76. package/dist/types/src/meta.d.ts +28 -2
  77. package/dist/types/src/meta.d.ts.map +1 -1
  78. package/dist/types/src/operations/open.d.ts.map +1 -1
  79. package/dist/types/src/operations/switch-workspace.d.ts.map +1 -1
  80. package/dist/types/src/types/DeckCapabilities.d.ts +2 -2
  81. package/dist/types/src/types/DeckCapabilities.d.ts.map +1 -1
  82. package/dist/types/src/types/index.d.ts +1 -0
  83. package/dist/types/src/types/index.d.ts.map +1 -1
  84. package/dist/types/src/types/schema.d.ts +4 -2
  85. package/dist/types/src/types/schema.d.ts.map +1 -1
  86. package/dist/types/src/types/surface.d.ts +12 -0
  87. package/dist/types/src/types/surface.d.ts.map +1 -0
  88. package/dist/types/tsconfig.tsbuildinfo +1 -1
  89. package/dx.config.ts +35 -0
  90. package/package.json +39 -39
  91. package/src/DeckPlugin.test.ts +1 -1
  92. package/src/DeckPlugin.ts +1 -1
  93. package/src/capabilities/app-graph-builder.ts +4 -4
  94. package/src/capabilities/check-app-scheme.ts +3 -3
  95. package/src/capabilities/notification-tracker.ts +8 -8
  96. package/src/capabilities/react-root.tsx +1 -1
  97. package/src/capabilities/react-surface.tsx +3 -4
  98. package/src/capabilities/settings.ts +2 -2
  99. package/src/capabilities/state.ts +1 -1
  100. package/src/capabilities/url-handler.ts +7 -15
  101. package/src/components/DeckSettings/DeckSettings.tsx +2 -2
  102. package/src/components/Matrix/Matrix.stories.tsx +2 -1
  103. package/src/containers/Deck/Banner.tsx +5 -4
  104. package/src/containers/Deck/DeckViewport.tsx +3 -4
  105. package/src/containers/Deck/StatusBar.tsx +4 -2
  106. package/src/containers/DeckLayout/DeckLayout.stories.tsx +6 -9
  107. package/src/containers/DeckLayout/Fallback.tsx +1 -1
  108. package/src/containers/DeckLayout/Popover.tsx +37 -20
  109. package/src/containers/DeckLayout/Toast.tsx +1 -1
  110. package/src/containers/Plank/Plank.stories.tsx +2 -2
  111. package/src/containers/Plank/PlankControls.tsx +2 -2
  112. package/src/containers/Plank/PlankError.tsx +1 -1
  113. package/src/containers/Plank/PlankHeading.tsx +5 -6
  114. package/src/containers/Sidebar/ComplementarySidebar.tsx +6 -5
  115. package/src/containers/Sidebar/Sidebar.tsx +1 -1
  116. package/src/containers/Sidebar/SidebarButton.tsx +3 -3
  117. package/src/meta.ts +2 -27
  118. package/src/operations/open.ts +12 -10
  119. package/src/operations/switch-workspace.ts +2 -2
  120. package/src/translations.ts +1 -1
  121. package/src/types/DeckCapabilities.ts +5 -3
  122. package/src/types/DeckEvents.ts +1 -1
  123. package/src/types/DeckOperation.ts +1 -1
  124. package/src/types/index.ts +1 -0
  125. package/src/types/schema.ts +16 -12
  126. package/src/types/surface.ts +28 -0
  127. package/src/util/plank-url-params.ts +3 -3
  128. package/dist/lib/neutral/DeckLayout-DEURA3KR.mjs.map +0 -7
  129. package/dist/lib/neutral/DeckSettings-W5I57OXM.mjs.map +0 -7
  130. package/dist/lib/neutral/app-graph-builder-HMLT627T.mjs.map +0 -7
  131. package/dist/lib/neutral/chunk-324PPIZB.mjs.map +0 -7
  132. package/dist/lib/neutral/chunk-BS4EOYMK.mjs.map +0 -7
  133. package/dist/lib/neutral/chunk-GBIGQKYW.mjs.map +0 -7
  134. package/dist/lib/neutral/chunk-PYEY5SEC.mjs +0 -37
  135. package/dist/lib/neutral/chunk-PYEY5SEC.mjs.map +0 -7
  136. package/dist/lib/neutral/chunk-Q4W6B4IB.mjs +0 -8
  137. package/dist/lib/neutral/chunk-WAXJPQJI.mjs.map +0 -7
  138. package/dist/lib/neutral/open-5OYNO3RT.mjs.map +0 -7
  139. package/dist/lib/neutral/react-root-HH5DEUOG.mjs.map +0 -7
  140. package/dist/lib/neutral/react-surface-3UVVCK3O.mjs.map +0 -7
  141. package/dist/lib/neutral/settings-EGNYUM4T.mjs.map +0 -7
  142. package/dist/lib/neutral/switch-workspace-LZF4KZXH.mjs.map +0 -7
  143. package/dist/lib/neutral/url-handler-A6HLW4RB.mjs.map +0 -7
  144. /package/dist/lib/neutral/{add-toast-TNB6DXWU.mjs.map → add-toast-APKTCLIA.mjs.map} +0 -0
  145. /package/dist/lib/neutral/{adjust-HNU5CCRO.mjs.map → adjust-7CZI4GK3.mjs.map} +0 -0
  146. /package/dist/lib/neutral/{check-app-scheme-INSOF72J.mjs.map → check-app-scheme-HSAORHHX.mjs.map} +0 -0
  147. /package/dist/lib/neutral/{chunk-Q4W6B4IB.mjs.map → chunk-UZLAR4DR.mjs.map} +0 -0
  148. /package/dist/lib/neutral/{close-ASKR22A6.mjs.map → close-KJUCFIJ5.mjs.map} +0 -0
  149. /package/dist/lib/neutral/{revert-workspace-B2QLT2C4.mjs.map → revert-workspace-24TKG3I7.mjs.map} +0 -0
  150. /package/dist/lib/neutral/{scroll-into-view-B52C3PJO.mjs.map → scroll-into-view-3VXT6TWC.mjs.map} +0 -0
  151. /package/dist/lib/neutral/{set-PA35ONXO.mjs.map → set-RFOLTI57.mjs.map} +0 -0
  152. /package/dist/lib/neutral/{set-layout-mode-RPCCPQRB.mjs.map → set-layout-mode-AZ73W52Z.mjs.map} +0 -0
  153. /package/dist/lib/neutral/{update-companion-YUCZZVGY.mjs.map → update-companion-5LCY6QME.mjs.map} +0 -0
  154. /package/dist/lib/neutral/{update-complementary-7FZNB55J.mjs.map → update-complementary-HZ7QXZYE.mjs.map} +0 -0
  155. /package/dist/lib/neutral/{update-dialog-FNQTSSAP.mjs.map → update-dialog-A7W3R5EI.mjs.map} +0 -0
  156. /package/dist/lib/neutral/{update-plank-size-3YW4NXEY.mjs.map → update-plank-size-XHTYBLSD.mjs.map} +0 -0
  157. /package/dist/lib/neutral/{update-popover-G2VUD7E6.mjs.map → update-popover-RDIHG73B.mjs.map} +0 -0
  158. /package/dist/lib/neutral/{update-sidebar-KRHPUHUB.mjs.map → update-sidebar-GEI7USA5.mjs.map} +0 -0
package/dx.config.ts ADDED
@@ -0,0 +1,35 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Config2 } from '@dxos/app-framework/config';
6
+ import { trim } from '@dxos/util';
7
+
8
+ export default Config2.make({
9
+ plugin: {
10
+ key: 'org.dxos.plugin.deck',
11
+ name: 'Layout',
12
+ author: 'DXOS',
13
+ description: trim`
14
+ The Deck plugin is the core layout engine for DXOS Composer. It manages the multi-plank
15
+ workspace (the "deck"), sidebar panels, dialogs, popovers, and toast notifications, giving
16
+ users a flexible, persistent workspace they can arrange to match their workflow.
17
+
18
+ In multi mode, subjects are opened as resizable "planks" arranged side by side. Users can
19
+ navigate with stack semantics — opening from a pivot truncates planks to the right and
20
+ appends the new one — or switch to solo or fullscreen mode for focused, distraction-free
21
+ viewing.
22
+
23
+ Layout state (active planks, sidebar visibility, plank sizes, companion pane) is persisted
24
+ across sessions via KVS/localStorage. URL routing is handled by the plugin so that any
25
+ workspace configuration can be bookmarked or shared as a deep link.
26
+
27
+ All layout changes are expressed through typed LayoutOperations (Open, Close, SetLayoutMode,
28
+ UpdateSidebar, UpdateDialog, UpdatePopover, etc.) that any plugin in the system can dispatch,
29
+ keeping the layout logic centralised and easy to extend.
30
+ `,
31
+ icon: { key: 'ph--layout--regular' },
32
+ spec: 'PLUGIN.mdl',
33
+ tags: ['system'],
34
+ },
35
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-deck",
3
- "version": "0.9.0",
3
+ "version": "0.9.1-main.c7dcc2e112",
4
4
  "description": "DXOS Surface plugin for the main application layout.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -86,6 +86,7 @@
86
86
  "types": "dist/types/src/index.d.ts",
87
87
  "files": [
88
88
  "dist",
89
+ "dx.config.ts",
89
90
  "src",
90
91
  "PLUGIN.mdl"
91
92
  ],
@@ -95,33 +96,32 @@
95
96
  "@radix-ui/react-context": "1.1.1",
96
97
  "@tauri-apps/plugin-deep-link": "^2.4.9",
97
98
  "immer": "^10.1.1",
98
- "@dxos/app-framework": "0.9.0",
99
- "@dxos/async": "0.9.0",
100
- "@dxos/app-toolkit": "0.9.0",
101
- "@dxos/context": "0.9.0",
102
- "@dxos/app-graph": "0.9.0",
103
- "@dxos/compute": "0.9.0",
104
- "@dxos/echo": "0.9.0",
105
- "@dxos/effect": "0.9.0",
106
- "@dxos/invariant": "0.9.0",
107
- "@dxos/errors": "0.9.0",
108
- "@dxos/keyboard": "0.9.0",
109
- "@dxos/keys": "0.9.0",
110
- "@dxos/log": "0.9.0",
111
- "@dxos/operation": "0.9.0",
112
- "@dxos/plugin-attention": "0.9.0",
113
- "@dxos/plugin-observability": "0.9.0",
114
- "@dxos/plugin-graph": "0.9.0",
115
- "@dxos/react-ui-attention": "0.9.0",
116
- "@dxos/react-ui-form": "0.9.0",
117
- "@dxos/plugin-client": "0.9.0",
118
- "@dxos/react-ui-menu": "0.9.0",
119
- "@dxos/react-ui-mosaic": "0.9.0",
120
- "@dxos/react-ui-tabs": "0.9.0",
121
- "@dxos/react-ui-text-tooltip": "0.9.0",
122
- "@dxos/react-ui-stack": "0.9.0",
123
- "@dxos/ui-types": "0.9.0",
124
- "@dxos/util": "0.9.0"
99
+ "@dxos/app-framework": "0.9.1-main.c7dcc2e112",
100
+ "@dxos/app-graph": "0.9.1-main.c7dcc2e112",
101
+ "@dxos/async": "0.9.1-main.c7dcc2e112",
102
+ "@dxos/compute": "0.9.1-main.c7dcc2e112",
103
+ "@dxos/app-toolkit": "0.9.1-main.c7dcc2e112",
104
+ "@dxos/context": "0.9.1-main.c7dcc2e112",
105
+ "@dxos/errors": "0.9.1-main.c7dcc2e112",
106
+ "@dxos/effect": "0.9.1-main.c7dcc2e112",
107
+ "@dxos/echo": "0.9.1-main.c7dcc2e112",
108
+ "@dxos/invariant": "0.9.1-main.c7dcc2e112",
109
+ "@dxos/log": "0.9.1-main.c7dcc2e112",
110
+ "@dxos/keyboard": "0.9.1-main.c7dcc2e112",
111
+ "@dxos/keys": "0.9.1-main.c7dcc2e112",
112
+ "@dxos/operation": "0.9.1-main.c7dcc2e112",
113
+ "@dxos/plugin-attention": "0.9.1-main.c7dcc2e112",
114
+ "@dxos/plugin-client": "0.9.1-main.c7dcc2e112",
115
+ "@dxos/plugin-graph": "0.9.1-main.c7dcc2e112",
116
+ "@dxos/react-ui-form": "0.9.1-main.c7dcc2e112",
117
+ "@dxos/plugin-observability": "0.9.1-main.c7dcc2e112",
118
+ "@dxos/react-ui-menu": "0.9.1-main.c7dcc2e112",
119
+ "@dxos/react-ui-mosaic": "0.9.1-main.c7dcc2e112",
120
+ "@dxos/react-ui-stack": "0.9.1-main.c7dcc2e112",
121
+ "@dxos/react-ui-tabs": "0.9.1-main.c7dcc2e112",
122
+ "@dxos/ui-types": "0.9.1-main.c7dcc2e112",
123
+ "@dxos/util": "0.9.1-main.c7dcc2e112",
124
+ "@dxos/react-ui-attention": "0.9.1-main.c7dcc2e112"
125
125
  },
126
126
  "devDependencies": {
127
127
  "@effect-atom/atom-react": "^0.5.0",
@@ -132,15 +132,15 @@
132
132
  "react": "~19.2.3",
133
133
  "react-dom": "~19.2.3",
134
134
  "vite": "^8.0.16",
135
- "@dxos/random": "0.9.0",
136
- "@dxos/react-hooks": "0.9.0",
137
- "@dxos/react-ui": "0.9.0",
138
- "@dxos/plugin-testing": "0.9.0",
139
- "@dxos/react-ui-syntax-highlighter": "0.9.0",
140
- "@dxos/schema": "0.9.0",
141
- "@dxos/storybook-utils": "0.9.0",
142
- "@dxos/types": "0.9.0",
143
- "@dxos/ui-theme": "0.9.0"
135
+ "@dxos/plugin-testing": "0.9.1-main.c7dcc2e112",
136
+ "@dxos/react-hooks": "0.9.1-main.c7dcc2e112",
137
+ "@dxos/storybook-utils": "0.9.1-main.c7dcc2e112",
138
+ "@dxos/react-ui-syntax-highlighter": "0.9.1-main.c7dcc2e112",
139
+ "@dxos/schema": "0.9.1-main.c7dcc2e112",
140
+ "@dxos/types": "0.9.1-main.c7dcc2e112",
141
+ "@dxos/ui-theme": "0.9.1-main.c7dcc2e112",
142
+ "@dxos/react-ui": "0.9.1-main.c7dcc2e112",
143
+ "@dxos/random": "0.9.1-main.c7dcc2e112"
144
144
  },
145
145
  "peerDependencies": {
146
146
  "@effect-atom/atom-react": "^0.5.0",
@@ -148,8 +148,8 @@
148
148
  "effect": "3.21.3",
149
149
  "react": "~19.2.3",
150
150
  "react-dom": "~19.2.3",
151
- "@dxos/ui-theme": "0.9.0",
152
- "@dxos/react-ui": "0.9.0"
151
+ "@dxos/react-ui": "0.9.1-main.c7dcc2e112",
152
+ "@dxos/ui-theme": "0.9.1-main.c7dcc2e112"
153
153
  },
154
154
  "publishConfig": {
155
155
  "access": "public"
@@ -11,7 +11,7 @@ import { DeckPlugin } from '#plugin';
11
11
 
12
12
  import { meta } from './meta';
13
13
 
14
- const moduleId = (name: string) => `${meta.id}.module.${name}`;
14
+ const moduleId = (name: string) => `${meta.profile.key}.module.${name}`;
15
15
 
16
16
  describe('DeckPlugin', () => {
17
17
  test('modules activate on the expected events', async ({ expect }) => {
package/src/DeckPlugin.ts CHANGED
@@ -70,7 +70,7 @@ export const DeckPlugin = Plugin.define(meta).pipe(
70
70
  activate: NotificationTracker,
71
71
  }),
72
72
  AppPlugin.addPluginAssetModule({
73
- asset: { pluginId: meta.id, path: 'PLUGIN.mdl', content: pluginSpec, mimeType: 'application/x-mdl' },
73
+ asset: { pluginId: meta.profile.key, path: 'PLUGIN.mdl', content: pluginSpec, mimeType: 'application/x-mdl' },
74
74
  }),
75
75
  Plugin.make,
76
76
  );
@@ -57,7 +57,7 @@ export default Capability.makeModule(
57
57
  }
58
58
  }),
59
59
  properties: {
60
- label: ['close-current.label', { ns: meta.id }],
60
+ label: ['close-current.label', { ns: meta.profile.key }],
61
61
  icon: 'ph--x--regular',
62
62
  },
63
63
  };
@@ -72,7 +72,7 @@ export default Capability.makeModule(
72
72
  yield* Operation.invoke(LayoutOperation.Close, { subject: ids });
73
73
  }),
74
74
  properties: {
75
- label: ['close-others.label', { ns: meta.id }],
75
+ label: ['close-others.label', { ns: meta.profile.key }],
76
76
  icon: 'ph--x-square--regular',
77
77
  },
78
78
  };
@@ -84,7 +84,7 @@ export default Capability.makeModule(
84
84
  yield* Operation.invoke(LayoutOperation.Close, { subject: deck.active });
85
85
  }),
86
86
  properties: {
87
- label: ['close-all.label', { ns: meta.id }],
87
+ label: ['close-all.label', { ns: meta.profile.key }],
88
88
  icon: 'ph--x-circle--regular',
89
89
  },
90
90
  };
@@ -105,7 +105,7 @@ export default Capability.makeModule(
105
105
  state.sidebarState === 'expanded'
106
106
  ? 'collapse-navigation-sidebar.label'
107
107
  : 'open-navigation-sidebar.label',
108
- { ns: meta.id },
108
+ { ns: meta.profile.key },
109
109
  ],
110
110
  icon: 'ph--sidebar--regular',
111
111
  keyBinding: {
@@ -5,7 +5,7 @@
5
5
  import * as Effect from 'effect/Effect';
6
6
 
7
7
  import { Capabilities, Capability } from '@dxos/app-framework';
8
- import { APP_SCHEME, AppCapabilities, LayoutOperation } from '@dxos/app-toolkit';
8
+ import { AppCapabilities, LayoutOperation, NativePasskey } from '@dxos/app-toolkit';
9
9
  import { EffectEx } from '@dxos/effect';
10
10
  import { isTauri } from '@dxos/util';
11
11
 
@@ -24,7 +24,7 @@ const isSafari = (): boolean => {
24
24
  /** Check if the current page URL can be converted to a valid custom scheme URL. */
25
25
  const canRedirectToScheme = (): boolean => {
26
26
  try {
27
- const schemeUrl = APP_SCHEME + window.location.pathname.replace(/^\/+/, '') + window.location.search;
27
+ const schemeUrl = NativePasskey.APP_SCHEME + window.location.pathname.replace(/^\/+/, '') + window.location.search;
28
28
  new URL(schemeUrl);
29
29
  return true;
30
30
  } catch {
@@ -63,7 +63,7 @@ const tryOpenNativeApp = (): Promise<boolean> => {
63
63
  document.addEventListener('visibilitychange', onVisibilityChange);
64
64
 
65
65
  // Try the scheme via hidden iframe.
66
- const schemeUrl = APP_SCHEME + window.location.pathname.replace(/^\/+/, '') + window.location.search;
66
+ const schemeUrl = NativePasskey.APP_SCHEME + window.location.pathname.replace(/^\/+/, '') + window.location.search;
67
67
  const iframe = document.createElement('iframe');
68
68
  iframe.style.display = 'none';
69
69
  iframe.src = schemeUrl;
@@ -105,12 +105,12 @@ export default Capability.makeModule(
105
105
  // Replace any stale plugin-failure toast so at most one is ever visible.
106
106
  const toast: LayoutOperation.Toast = {
107
107
  id: 'plugin-failure',
108
- title: ['plugin-failure.title', { ns: meta.id }],
109
- description: ['plugin-failure.description', { ns: meta.id }],
108
+ title: ['plugin-failure.title', { ns: meta.profile.key }],
109
+ description: ['plugin-failure.description', { ns: meta.profile.key }],
110
110
  icon: 'ph--warning--regular',
111
111
  duration: ERROR_TOAST_DURATION,
112
- actionLabel: ['plugin-failure-action.label', { ns: meta.id }],
113
- actionAlt: ['plugin-failure-action.alt', { ns: meta.id }],
112
+ actionLabel: ['plugin-failure-action.label', { ns: meta.profile.key }],
113
+ actionAlt: ['plugin-failure-action.alt', { ns: meta.profile.key }],
114
114
  onAction: () => void invoker.invokePromise(SettingsOperation.OpenPluginRegistry),
115
115
  };
116
116
  const state = registry.get(ephemeralAtom);
@@ -135,11 +135,11 @@ export default Capability.makeModule(
135
135
  : state.toasts;
136
136
  const toast: LayoutOperation.Toast = {
137
137
  id: undoId,
138
- title: message ?? ['undo-available.label', { ns: meta.id }],
138
+ title: message ?? ['undo-available.label', { ns: meta.profile.key }],
139
139
  duration: UNDO_TOAST_DURATION,
140
- actionLabel: ['undo-action.label', { ns: meta.id }],
141
- actionAlt: ['undo-action.alt', { ns: meta.id }],
142
- closeLabel: ['undo-close.label', { ns: meta.id }],
140
+ actionLabel: ['undo-action.label', { ns: meta.profile.key }],
141
+ actionAlt: ['undo-action.alt', { ns: meta.profile.key }],
142
+ closeLabel: ['undo-close.label', { ns: meta.profile.key }],
143
143
  onAction: onUndo,
144
144
  };
145
145
  registry.set(ephemeralAtom, { ...state, currentUndoId: undoId, toasts: [...toasts, toast] });
@@ -14,7 +14,7 @@ import { meta } from '#meta';
14
14
  export default Capability.makeModule(() =>
15
15
  Effect.succeed(
16
16
  Capability.contributes(Capabilities.ReactRoot, {
17
- id: meta.id,
17
+ id: meta.profile.key,
18
18
  root: () => {
19
19
  const { state, updateEphemeral } = useDeckState();
20
20
 
@@ -7,7 +7,7 @@ import React from 'react';
7
7
 
8
8
  import { Capabilities, Capability } from '@dxos/app-framework';
9
9
  import { Surface, useSettingsState } from '@dxos/app-framework/ui';
10
- import { NOT_FOUND_PATH } from '@dxos/app-toolkit';
10
+ import { NotFound } from '@dxos/app-toolkit';
11
11
  import { AppSurface, NotFoundArticle } from '@dxos/app-toolkit/ui';
12
12
 
13
13
  import { DeckSettings } from '#components';
@@ -19,7 +19,7 @@ export default Capability.makeModule(() =>
19
19
  Capability.contributes(Capabilities.ReactSurface, [
20
20
  Surface.create({
21
21
  id: 'pluginSettings',
22
- filter: AppSurface.settings(AppSurface.Article, meta.id),
22
+ filter: AppSurface.settings(AppSurface.Article, meta.profile.key),
23
23
  component: ({ data: { subject } }) => {
24
24
  const { settings, updateSettings } = useSettingsState<Settings.Settings>(subject.atom);
25
25
  return <DeckSettings settings={settings} onSettingsChange={updateSettings} />;
@@ -27,8 +27,7 @@ export default Capability.makeModule(() =>
27
27
  }),
28
28
  Surface.create({
29
29
  id: 'notFound',
30
- role: 'article',
31
- filter: (data): data is { attendableId: string } => data.attendableId === NOT_FOUND_PATH,
30
+ filter: Surface.makeFilter(AppSurface.Article, (data) => data.attendableId === NotFound.NOT_FOUND_PATH),
32
31
  component: () => <NotFoundArticle />,
33
32
  }),
34
33
  ]),
@@ -14,7 +14,7 @@ import { DeckCapabilities, Settings } from '#types';
14
14
  export default Capability.makeModule(() =>
15
15
  Effect.sync(() => {
16
16
  const settingsAtom = createKvsStore({
17
- key: meta.id,
17
+ key: meta.profile.key,
18
18
  schema: Settings.Settings,
19
19
  defaultValue: () => ({
20
20
  showHints: false,
@@ -27,7 +27,7 @@ export default Capability.makeModule(() =>
27
27
  return [
28
28
  Capability.contributes(DeckCapabilities.Settings, settingsAtom),
29
29
  Capability.contributes(AppCapabilities.Settings, {
30
- prefix: meta.id,
30
+ prefix: meta.profile.key,
31
31
  schema: Settings.Settings,
32
32
  atom: settingsAtom,
33
33
  }),
@@ -49,7 +49,7 @@ export default Capability.makeModule(
49
49
 
50
50
  // Persisted state using KVS store.
51
51
  const stateAtom = createKvsStore({
52
- key: `${meta.id}.state`,
52
+ key: `${meta.profile.key}.state`,
53
53
  schema: StoredDeckState,
54
54
  defaultValue: () => ({ ...defaultDeckState }),
55
55
  });
@@ -5,15 +5,7 @@
5
5
  import * as Effect from 'effect/Effect';
6
6
 
7
7
  import { Capabilities, Capability } from '@dxos/app-framework';
8
- import {
9
- AppCapabilities,
10
- LayoutOperation,
11
- NOT_FOUND_PATH,
12
- expandPath,
13
- fromUrlPath,
14
- getWorkspaceFromPath,
15
- toUrlPath,
16
- } from '@dxos/app-toolkit';
8
+ import { AppCapabilities, LayoutOperation, NotFound, Paths } from '@dxos/app-toolkit';
17
9
  import { Operation } from '@dxos/compute';
18
10
  import { EffectEx } from '@dxos/effect';
19
11
  import { invariant } from '@dxos/invariant';
@@ -91,8 +83,8 @@ export default Capability.makeModule(
91
83
  return;
92
84
  }
93
85
 
94
- const qualifiedId = fromUrlPath(pathname);
95
- const workspace = getWorkspaceFromPath(qualifiedId);
86
+ const qualifiedId = Paths.fromUrlPath(pathname);
87
+ const workspace = Paths.getWorkspaceFromPath(qualifiedId);
96
88
  if (workspace !== Node.RootId && workspace !== state.activeDeck) {
97
89
  yield* Operation.invoke(LayoutOperation.SwitchWorkspace, { subject: workspace });
98
90
  }
@@ -110,10 +102,10 @@ export default Capability.makeModule(
110
102
  mode: 'solo',
111
103
  });
112
104
  }
113
- } else if (deck.solo && deck.solo !== NOT_FOUND_PATH) {
105
+ } else if (deck.solo && deck.solo !== NotFound.NOT_FOUND_PATH) {
114
106
  // Stay in solo mode; redirect URL to reflect the current solo item.
115
107
  // Do not switch to deck mode here — only explicit user action should change layout mode.
116
- const path = toUrlPath(deck.solo);
108
+ const path = Paths.toUrlPath(deck.solo);
117
109
  if (window.location.pathname !== path) {
118
110
  history.replaceState(null, '', `${path}${stripPlanks(window.location.search)}`);
119
111
  }
@@ -122,7 +114,7 @@ export default Capability.makeModule(
122
114
  const plankIds = deserializePlanks(resolvedUrl);
123
115
  if (plankIds.length > 0) {
124
116
  for (const plankId of plankIds) {
125
- expandPath(graph, plankId);
117
+ NotFound.expandPath(graph, plankId);
126
118
  }
127
119
  updateState((state) => updateActiveDeck(state, { active: plankIds, initialized: true }));
128
120
  }
@@ -203,7 +195,7 @@ export default Capability.makeModule(
203
195
  lastActiveDeck = activeDeck;
204
196
  lastActiveKey = activeKey;
205
197
 
206
- const path = solo && solo !== NOT_FOUND_PATH ? toUrlPath(solo) : toUrlPath(activeDeck);
198
+ const path = solo && solo !== NotFound.NOT_FOUND_PATH ? Paths.toUrlPath(solo) : Paths.toUrlPath(activeDeck);
207
199
  const search = !solo
208
200
  ? serializePlanks(deck.active, window.location.search)
209
201
  : stripPlanks(window.location.search);
@@ -16,11 +16,11 @@ const isSocket = !!(globalThis as any).__args;
16
16
  export type DeckSettingsProps = AppSurface.SettingsArticleProps<Settings.Settings>;
17
17
 
18
18
  export const DeckSettings = ({ settings, onSettingsChange }: DeckSettingsProps) => {
19
- const { t } = useTranslation(meta.id);
19
+ const { t } = useTranslation(meta.profile.key);
20
20
 
21
21
  return (
22
22
  <SettingsForm.Viewport>
23
- <SettingsForm.Section title={t('settings.title', { ns: meta.id })}>
23
+ <SettingsForm.Section title={t('settings.title', { ns: meta.profile.key })}>
24
24
  <SettingsForm.FieldSet
25
25
  readonly={!onSettingsChange}
26
26
  schema={Settings.Settings}
@@ -10,6 +10,7 @@ import { withPluginManager } from '@dxos/app-framework/testing';
10
10
  import { Surface } from '@dxos/app-framework/ui';
11
11
  import { Graph } from '@dxos/app-graph';
12
12
  import { AppActivationEvents, AppPlugin } from '@dxos/app-toolkit';
13
+ import { AppSurface } from '@dxos/app-toolkit/ui';
13
14
  import { Obj } from '@dxos/echo';
14
15
  import { corePlugins } from '@dxos/plugin-testing';
15
16
  import { random } from '@dxos/random';
@@ -104,7 +105,7 @@ const TestExtension = Capability.contributes(
104
105
  Capabilities.ReactSurface,
105
106
  Surface.create({
106
107
  id: 'storyArticle',
107
- role: 'article',
108
+ filter: Surface.makeFilter(AppSurface.Article),
108
109
  component: ({ data: { subject } }) => {
109
110
  if (!subject) {
110
111
  return <Loading />;
@@ -5,15 +5,17 @@
5
5
  import React from 'react';
6
6
 
7
7
  import { Surface } from '@dxos/app-framework/ui';
8
+ import { AppSurface } from '@dxos/app-toolkit/ui';
8
9
  import { type ThemedClassName, useTranslation } from '@dxos/react-ui';
9
10
  import { mx, osTranslations } from '@dxos/ui-theme';
10
11
 
11
12
  import { meta } from '#meta';
13
+ import { VersionInfo } from '#types';
12
14
 
13
15
  import { CloseSidebarButton, ToggleSidebarButton } from '../Sidebar';
14
16
 
15
17
  export const Banner = ({ variant, classNames }: ThemedClassName<{ variant?: 'topbar' | 'sidebar' }>) => {
16
- const { t } = useTranslation(meta.id);
18
+ const { t } = useTranslation(meta.profile.key);
17
19
 
18
20
  return (
19
21
  <header
@@ -29,13 +31,12 @@ export const Banner = ({ variant, classNames }: ThemedClassName<{ variant?: 'top
29
31
  {variant === 'topbar' && (
30
32
  <div className='absolute inset-0 pointer-events-none'>
31
33
  <div className='grid h-full pointer-fine:p-1 max-w-md mx-auto pointer-events-auto'>
32
- <Surface.Surface role='search-input' limit={1} />
34
+ <Surface.Surface type={AppSurface.SearchInput} limit={1} />
33
35
  </div>
34
36
  </div>
35
37
  )}
36
38
  <span className='grow' />
37
- <Surface.Surface role='version-info' limit={1} />
38
- <Surface.Surface role='notch-start' limit={1} />
39
+ <Surface.Surface type={VersionInfo} limit={1} />
39
40
  </header>
40
41
  );
41
42
  };
@@ -26,8 +26,7 @@ import { hoverableControls, hoverableFocusedWithinControls, mx } from '@dxos/ui-
26
26
 
27
27
  import { useBreakpoints, useCompanions, useDeckState, useSelectedCompanion } from '#hooks';
28
28
  import { meta } from '#meta';
29
- import { DeckOperation } from '#types';
30
- import { getMode } from '#types';
29
+ import { DeckOperation, getMode, Keyshortcuts } from '#types';
31
30
 
32
31
  import { layoutAppliesTopbar } from '../../util';
33
32
  import { Plank, PlankRootProps, type PlankComponentProps } from '../Plank';
@@ -105,7 +104,7 @@ export const DeckContentEmpty = () => {
105
104
  const topbar = layoutAppliesTopbar(breakpoint, layoutMode);
106
105
  return (
107
106
  <div className='grid place-items-center p-8 relative bg-deck-surface' data-testid='layoutPlugin.firstRunMessage'>
108
- <Surface.Surface role='keyshortcuts' />
107
+ <Surface.Surface type={Keyshortcuts} />
109
108
  {!topbar && <ToggleSidebarButton />}
110
109
  </div>
111
110
  );
@@ -273,7 +272,7 @@ const ToggleComplementarySidebarButton = () => (
273
272
  );
274
273
 
275
274
  const ExitFullscreenButton = ({ onExit }: { onExit: () => void }) => {
276
- const { t } = useTranslation(meta.id);
275
+ const { t } = useTranslation(meta.profile.key);
277
276
  return (
278
277
  <div
279
278
  className={mx(
@@ -7,6 +7,8 @@ import React from 'react';
7
7
  import { Surface } from '@dxos/app-framework/ui';
8
8
  import { useLandmarkMover } from '@dxos/react-ui';
9
9
 
10
+ import { Hints, StatusBar as StatusBarRole } from '#types';
11
+
10
12
  export const StatusBar = ({ showHints }: { showHints?: boolean }) => {
11
13
  const mover = useLandmarkMover(undefined, '3');
12
14
  return (
@@ -15,8 +17,8 @@ export const StatusBar = ({ showHints }: { showHints?: boolean }) => {
15
17
  className='fixed bottom-0 inset-x-0 h-(--dx-statusbar-size) border-y border-separator z-[2] flex text-description'
16
18
  {...mover}
17
19
  >
18
- {showHints && <Surface.Surface role='hints' limit={1} />}
19
- <Surface.Surface role='status-bar' limit={1} />
20
+ {showHints && <Surface.Surface type={Hints} limit={1} />}
21
+ <Surface.Surface type={StatusBarRole} limit={1} />
20
22
  </div>
21
23
  );
22
24
  };
@@ -167,15 +167,14 @@ const TestPlugin = Plugin.define(pluginMeta).pipe(
167
167
  Capability.contributes(Capabilities.ReactSurface, [
168
168
  Surface.create({
169
169
  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} />,
170
+ filter: Surface.makeFilter(AppSurface.Navigation),
171
+ component: ({ data, ref }) => (
172
+ <NavContainer current={data.current} ref={ref as React.Ref<HTMLDivElement>} />
173
+ ),
173
174
  }),
174
175
  Surface.create({
175
176
  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,
177
+ filter: Surface.makeFilter(AppSurface.Article, (data) => data.companionTo == null),
179
178
  component: ({ data }) => {
180
179
  const subject = (data as any)?.subject;
181
180
  const attendableId = (data as any)?.attendableId as string | undefined;
@@ -202,9 +201,7 @@ const TestPlugin = Plugin.define(pluginMeta).pipe(
202
201
  }),
203
202
  Surface.create({
204
203
  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,
204
+ filter: Surface.makeFilter(AppSurface.Article, (data) => data.companionTo != null),
208
205
  component: ({ data: { subject, companionTo, properties, variant } }) => {
209
206
  if (companionTo == null) {
210
207
  return <Loading />;
@@ -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'>