@dxos/plugin-simple-layout 0.8.4-main.69d29f4 → 0.8.4-main.8360d9e660

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 (192) hide show
  1. package/dist/lib/browser/chunk-2YSUM2L4.mjs +1153 -0
  2. package/dist/lib/browser/chunk-2YSUM2L4.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-CLPGTNWJ.mjs → chunk-MRR7PXSM.mjs} +5 -5
  4. package/dist/lib/browser/chunk-MRR7PXSM.mjs.map +7 -0
  5. package/dist/lib/browser/index.mjs +27 -20
  6. package/dist/lib/browser/index.mjs.map +3 -3
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/{operation-resolver-LTB63NKP.mjs → operation-resolver-LV5FK6MN.mjs} +46 -19
  9. package/dist/lib/browser/operation-resolver-LV5FK6MN.mjs.map +7 -0
  10. package/dist/lib/browser/{react-root-6ARAPH3O.mjs → react-root-JR6OENXV.mjs} +5 -5
  11. package/dist/lib/browser/react-root-JR6OENXV.mjs.map +7 -0
  12. package/dist/lib/browser/{react-surface-SO7B23GS.mjs → react-surface-5JOPIP5Z.mjs} +18 -13
  13. package/dist/lib/browser/react-surface-5JOPIP5Z.mjs.map +7 -0
  14. package/dist/lib/browser/{spotlight-dismiss-VSNOPETH.mjs → spotlight-dismiss-67PHYS5B.mjs} +3 -3
  15. package/dist/lib/browser/spotlight-dismiss-67PHYS5B.mjs.map +7 -0
  16. package/dist/lib/browser/{state-H4IGICBB.mjs → state-TXSMUWYI.mjs} +8 -5
  17. package/dist/lib/browser/state-TXSMUWYI.mjs.map +7 -0
  18. package/dist/lib/browser/url-handler-RBRONH7S.mjs +151 -0
  19. package/dist/lib/browser/url-handler-RBRONH7S.mjs.map +7 -0
  20. package/dist/lib/node-esm/chunk-RCQE6FR2.mjs +1154 -0
  21. package/dist/lib/node-esm/chunk-RCQE6FR2.mjs.map +7 -0
  22. package/dist/lib/node-esm/{chunk-MUVVYBUE.mjs → chunk-WMNTJ2MK.mjs} +5 -5
  23. package/dist/lib/node-esm/chunk-WMNTJ2MK.mjs.map +7 -0
  24. package/dist/lib/node-esm/index.mjs +27 -20
  25. package/dist/lib/node-esm/index.mjs.map +3 -3
  26. package/dist/lib/node-esm/meta.json +1 -1
  27. package/dist/lib/node-esm/{operation-resolver-7O6O7T4Q.mjs → operation-resolver-FD3EF2LX.mjs} +46 -19
  28. package/dist/lib/node-esm/operation-resolver-FD3EF2LX.mjs.map +7 -0
  29. package/dist/lib/node-esm/{react-root-2CPA2ZUS.mjs → react-root-CRTCNH3F.mjs} +5 -5
  30. package/dist/lib/node-esm/react-root-CRTCNH3F.mjs.map +7 -0
  31. package/dist/lib/node-esm/{react-surface-FKAV56MO.mjs → react-surface-NRTDSGFB.mjs} +18 -13
  32. package/dist/lib/node-esm/react-surface-NRTDSGFB.mjs.map +7 -0
  33. package/dist/lib/node-esm/{spotlight-dismiss-L5PCWIJG.mjs → spotlight-dismiss-RMLRZUVY.mjs} +3 -3
  34. package/dist/lib/node-esm/spotlight-dismiss-RMLRZUVY.mjs.map +7 -0
  35. package/dist/lib/node-esm/{state-QIU2LMLT.mjs → state-JMX6FAG4.mjs} +8 -5
  36. package/dist/lib/node-esm/state-JMX6FAG4.mjs.map +7 -0
  37. package/dist/lib/node-esm/url-handler-QSMCH3JB.mjs +152 -0
  38. package/dist/lib/node-esm/url-handler-QSMCH3JB.mjs.map +7 -0
  39. package/dist/types/src/SimpleLayoutPlugin.d.ts.map +1 -1
  40. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +2 -2
  41. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +1 -1
  42. package/dist/types/src/capabilities/react-root/react-root.d.ts +1 -1
  43. package/dist/types/src/capabilities/react-root/react-root.d.ts.map +1 -1
  44. package/dist/types/src/capabilities/react-surface/index.d.ts +1 -1
  45. package/dist/types/src/capabilities/react-surface/index.d.ts.map +1 -1
  46. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +2 -2
  47. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +1 -1
  48. package/dist/types/src/capabilities/spotlight-dismiss/index.d.ts +1 -1
  49. package/dist/types/src/capabilities/spotlight-dismiss/index.d.ts.map +1 -1
  50. package/dist/types/src/capabilities/spotlight-dismiss/spotlight-dismiss.d.ts +1 -1
  51. package/dist/types/src/capabilities/spotlight-dismiss/spotlight-dismiss.d.ts.map +1 -1
  52. package/dist/types/src/capabilities/state/index.d.ts +1 -1
  53. package/dist/types/src/capabilities/state/state.d.ts +1 -1
  54. package/dist/types/src/capabilities/state/state.d.ts.map +1 -1
  55. package/dist/types/src/capabilities/url-handler/url-handler.d.ts +5 -3
  56. package/dist/types/src/capabilities/url-handler/url-handler.d.ts.map +1 -1
  57. package/dist/types/src/components/ContentError.stories.d.ts +7 -3
  58. package/dist/types/src/components/ContentError.stories.d.ts.map +1 -1
  59. package/dist/types/src/components/ContentLoading/ContentLoading.d.ts.map +1 -0
  60. package/dist/types/src/components/ContentLoading/ContentLoading.stories.d.ts.map +1 -0
  61. package/dist/types/src/components/ContentLoading/index.d.ts +2 -0
  62. package/dist/types/src/components/ContentLoading/index.d.ts.map +1 -0
  63. package/dist/types/src/components/Home/Home.d.ts.map +1 -1
  64. package/dist/types/src/components/MobileLayout/MobileLayout.d.ts +35 -0
  65. package/dist/types/src/components/MobileLayout/MobileLayout.d.ts.map +1 -0
  66. package/dist/types/src/components/MobileLayout/MobileLayout.stories.d.ts +7 -0
  67. package/dist/types/src/components/MobileLayout/MobileLayout.stories.d.ts.map +1 -0
  68. package/dist/types/src/components/MobileLayout/index.d.ts +2 -0
  69. package/dist/types/src/components/MobileLayout/index.d.ts.map +1 -0
  70. package/dist/types/src/components/NavBranch/NavBranch.d.ts +11 -0
  71. package/dist/types/src/components/NavBranch/NavBranch.d.ts.map +1 -0
  72. package/dist/types/src/components/NavBranch/index.d.ts +2 -0
  73. package/dist/types/src/components/NavBranch/index.d.ts.map +1 -0
  74. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  75. package/dist/types/src/components/SimpleLayout/AppBar.d.ts +26 -0
  76. package/dist/types/src/components/SimpleLayout/AppBar.d.ts.map +1 -0
  77. package/dist/types/src/components/SimpleLayout/AppBar.stories.d.ts +47 -0
  78. package/dist/types/src/components/SimpleLayout/AppBar.stories.d.ts.map +1 -0
  79. package/dist/types/src/components/SimpleLayout/Drawer.d.ts +9 -0
  80. package/dist/types/src/components/SimpleLayout/Drawer.d.ts.map +1 -0
  81. package/dist/types/src/components/SimpleLayout/Main.d.ts +1 -1
  82. package/dist/types/src/components/SimpleLayout/Main.d.ts.map +1 -1
  83. package/dist/types/src/components/SimpleLayout/NavBar.d.ts +13 -3
  84. package/dist/types/src/components/SimpleLayout/NavBar.d.ts.map +1 -1
  85. package/dist/types/src/components/SimpleLayout/NavBar.stories.d.ts +13 -9
  86. package/dist/types/src/components/SimpleLayout/NavBar.stories.d.ts.map +1 -1
  87. package/dist/types/src/components/SimpleLayout/SimpleLayout.d.ts.map +1 -1
  88. package/dist/types/src/components/SimpleLayout/SimpleLayout.stories.d.ts +10 -0
  89. package/dist/types/src/components/SimpleLayout/SimpleLayout.stories.d.ts.map +1 -1
  90. package/dist/types/src/components/SimpleLayout/index.d.ts +3 -0
  91. package/dist/types/src/components/SimpleLayout/index.d.ts.map +1 -1
  92. package/dist/types/src/components/hooks.d.ts +4 -2
  93. package/dist/types/src/components/hooks.d.ts.map +1 -1
  94. package/dist/types/src/components/index.d.ts +2 -1
  95. package/dist/types/src/components/index.d.ts.map +1 -1
  96. package/dist/types/src/hooks/actions.d.ts +19 -0
  97. package/dist/types/src/hooks/actions.d.ts.map +1 -0
  98. package/dist/types/src/hooks/index.d.ts +5 -0
  99. package/dist/types/src/hooks/index.d.ts.map +1 -1
  100. package/dist/types/src/hooks/useAppBarProps.d.ts +7 -0
  101. package/dist/types/src/hooks/useAppBarProps.d.ts.map +1 -0
  102. package/dist/types/src/hooks/useCompanions.d.ts +12 -0
  103. package/dist/types/src/hooks/useCompanions.d.ts.map +1 -0
  104. package/dist/types/src/hooks/useDrawerActions.d.ts +13 -0
  105. package/dist/types/src/hooks/useDrawerActions.d.ts.map +1 -0
  106. package/dist/types/src/hooks/useNavbarActions.d.ts +14 -0
  107. package/dist/types/src/hooks/useNavbarActions.d.ts.map +1 -0
  108. package/dist/types/src/hooks/useSimpleLayoutState.d.ts +3 -3
  109. package/dist/types/src/hooks/useSimpleLayoutState.d.ts.map +1 -1
  110. package/dist/types/src/translations.d.ts +6 -0
  111. package/dist/types/src/translations.d.ts.map +1 -1
  112. package/dist/types/src/types/capabilities.d.ts +8 -3
  113. package/dist/types/src/types/capabilities.d.ts.map +1 -1
  114. package/dist/types/src/types/events.d.ts.map +1 -1
  115. package/dist/types/tsconfig.tsbuildinfo +1 -1
  116. package/package.json +36 -30
  117. package/src/SimpleLayoutPlugin.ts +10 -9
  118. package/src/capabilities/operation-resolver/operation-resolver.ts +44 -19
  119. package/src/capabilities/react-root/react-root.tsx +2 -2
  120. package/src/capabilities/react-surface/react-surface.tsx +14 -11
  121. package/src/capabilities/spotlight-dismiss/spotlight-dismiss.ts +2 -2
  122. package/src/capabilities/state/state.tsx +6 -3
  123. package/src/capabilities/url-handler/url-handler.ts +98 -45
  124. package/src/components/ContentError.stories.tsx +8 -7
  125. package/src/components/{ContentLoading.stories.tsx → ContentLoading/ContentLoading.stories.tsx} +2 -2
  126. package/src/components/{ContentLoading.tsx → ContentLoading/ContentLoading.tsx} +1 -1
  127. package/src/components/ContentLoading/index.ts +5 -0
  128. package/src/components/Dialog/Dialog.tsx +5 -5
  129. package/src/components/Home/Home.tsx +44 -36
  130. package/src/components/MobileLayout/MobileLayout.stories.tsx +129 -0
  131. package/src/components/MobileLayout/MobileLayout.tsx +305 -0
  132. package/src/components/MobileLayout/index.ts +5 -0
  133. package/src/components/NavBranch/NavBranch.tsx +133 -0
  134. package/src/components/{Workspace → NavBranch}/index.ts +1 -1
  135. package/src/components/Popover/Popover.tsx +7 -7
  136. package/src/components/SimpleLayout/AppBar.stories.tsx +144 -0
  137. package/src/components/SimpleLayout/AppBar.tsx +94 -0
  138. package/src/components/SimpleLayout/Drawer.tsx +96 -0
  139. package/src/components/SimpleLayout/Main.tsx +46 -45
  140. package/src/components/SimpleLayout/NavBar.stories.tsx +131 -26
  141. package/src/components/SimpleLayout/NavBar.tsx +18 -59
  142. package/src/components/SimpleLayout/SimpleLayout.stories.tsx +24 -11
  143. package/src/components/SimpleLayout/SimpleLayout.tsx +45 -6
  144. package/src/components/SimpleLayout/index.ts +3 -0
  145. package/src/components/hooks.ts +10 -14
  146. package/src/components/index.ts +2 -1
  147. package/src/hooks/actions.ts +83 -0
  148. package/src/hooks/index.ts +5 -0
  149. package/src/hooks/useAppBarProps.ts +115 -0
  150. package/src/hooks/useCompanions.ts +22 -0
  151. package/src/hooks/useDrawerActions.ts +100 -0
  152. package/src/hooks/useNavbarActions.ts +87 -0
  153. package/src/hooks/useSimpleLayoutState.ts +5 -5
  154. package/src/meta.ts +1 -1
  155. package/src/translations.ts +6 -0
  156. package/src/types/capabilities.ts +13 -4
  157. package/src/types/events.ts +3 -2
  158. package/dist/lib/browser/chunk-CLPGTNWJ.mjs.map +0 -7
  159. package/dist/lib/browser/chunk-FK4M7GJV.mjs +0 -613
  160. package/dist/lib/browser/chunk-FK4M7GJV.mjs.map +0 -7
  161. package/dist/lib/browser/operation-resolver-LTB63NKP.mjs.map +0 -7
  162. package/dist/lib/browser/react-root-6ARAPH3O.mjs.map +0 -7
  163. package/dist/lib/browser/react-surface-SO7B23GS.mjs.map +0 -7
  164. package/dist/lib/browser/spotlight-dismiss-VSNOPETH.mjs.map +0 -7
  165. package/dist/lib/browser/state-H4IGICBB.mjs.map +0 -7
  166. package/dist/lib/browser/url-handler-7CFGTLNG.mjs +0 -54
  167. package/dist/lib/browser/url-handler-7CFGTLNG.mjs.map +0 -7
  168. package/dist/lib/node-esm/chunk-EGFZAVBD.mjs +0 -614
  169. package/dist/lib/node-esm/chunk-EGFZAVBD.mjs.map +0 -7
  170. package/dist/lib/node-esm/chunk-MUVVYBUE.mjs.map +0 -7
  171. package/dist/lib/node-esm/operation-resolver-7O6O7T4Q.mjs.map +0 -7
  172. package/dist/lib/node-esm/react-root-2CPA2ZUS.mjs.map +0 -7
  173. package/dist/lib/node-esm/react-surface-FKAV56MO.mjs.map +0 -7
  174. package/dist/lib/node-esm/spotlight-dismiss-L5PCWIJG.mjs.map +0 -7
  175. package/dist/lib/node-esm/state-QIU2LMLT.mjs.map +0 -7
  176. package/dist/lib/node-esm/url-handler-4LYP3JM7.mjs +0 -55
  177. package/dist/lib/node-esm/url-handler-4LYP3JM7.mjs.map +0 -7
  178. package/dist/types/src/components/ContentError.d.ts +0 -5
  179. package/dist/types/src/components/ContentError.d.ts.map +0 -1
  180. package/dist/types/src/components/ContentLoading.d.ts.map +0 -1
  181. package/dist/types/src/components/ContentLoading.stories.d.ts.map +0 -1
  182. package/dist/types/src/components/SimpleLayout/Banner.d.ts +0 -8
  183. package/dist/types/src/components/SimpleLayout/Banner.d.ts.map +0 -1
  184. package/dist/types/src/components/Workspace/Workspace.d.ts +0 -9
  185. package/dist/types/src/components/Workspace/Workspace.d.ts.map +0 -1
  186. package/dist/types/src/components/Workspace/index.d.ts +0 -2
  187. package/dist/types/src/components/Workspace/index.d.ts.map +0 -1
  188. package/src/components/ContentError.tsx +0 -23
  189. package/src/components/SimpleLayout/Banner.tsx +0 -82
  190. package/src/components/Workspace/Workspace.tsx +0 -115
  191. /package/dist/types/src/components/{ContentLoading.d.ts → ContentLoading/ContentLoading.d.ts} +0 -0
  192. /package/dist/types/src/components/{ContentLoading.stories.d.ts → ContentLoading/ContentLoading.stories.d.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-simple-layout",
3
- "version": "0.8.4-main.69d29f4",
3
+ "version": "0.8.4-main.8360d9e660",
4
4
  "description": "Simple layout plugin for minimal UI contexts like popover windows.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -15,9 +15,9 @@
15
15
  "exports": {
16
16
  ".": {
17
17
  "source": "./src/index.ts",
18
- "types": "./dist/types/src/index.d.ts",
19
18
  "browser": "./dist/lib/browser/index.mjs",
20
- "node": "./dist/lib/node-esm/index.mjs"
19
+ "node": "./dist/lib/node-esm/index.mjs",
20
+ "types": "./dist/types/src/index.d.ts"
21
21
  }
22
22
  },
23
23
  "types": "dist/types/src/index.d.ts",
@@ -26,44 +26,50 @@
26
26
  "src"
27
27
  ],
28
28
  "dependencies": {
29
- "@effect-atom/atom": "^0.4.13",
30
- "@effect-atom/atom-react": "^0.4.6",
29
+ "@effect-atom/atom": "^0.5.1",
30
+ "@effect-atom/atom-react": "^0.5.0",
31
31
  "@radix-ui/react-context": "1.1.1",
32
- "@dxos/log": "0.8.4-main.69d29f4",
33
- "@dxos/app-framework": "0.8.4-main.69d29f4",
34
- "@dxos/operation": "0.8.4-main.69d29f4",
35
- "@dxos/plugin-graph": "0.8.4-main.69d29f4",
36
- "@dxos/react-ui-menu": "0.8.4-main.69d29f4",
37
- "@dxos/react-ui-mosaic": "0.8.4-main.69d29f4",
38
- "@dxos/react-ui-attention": "0.8.4-main.69d29f4",
39
- "@dxos/react-ui-searchlist": "0.8.4-main.69d29f4",
40
- "@dxos/react-ui-stack": "0.8.4-main.69d29f4",
41
- "@dxos/schema": "0.8.4-main.69d29f4",
42
- "@dxos/util": "0.8.4-main.69d29f4"
32
+ "@tauri-apps/plugin-deep-link": "^2.2.0",
33
+ "@tauri-apps/plugin-haptics": "^2.3.2",
34
+ "@dxos/app-toolkit": "0.8.4-main.8360d9e660",
35
+ "@dxos/app-framework": "0.8.4-main.8360d9e660",
36
+ "@dxos/echo": "0.8.4-main.8360d9e660",
37
+ "@dxos/async": "0.8.4-main.8360d9e660",
38
+ "@dxos/log": "0.8.4-main.8360d9e660",
39
+ "@dxos/operation": "0.8.4-main.8360d9e660",
40
+ "@dxos/plugin-graph": "0.8.4-main.8360d9e660",
41
+ "@dxos/react-ui-attention": "0.8.4-main.8360d9e660",
42
+ "@dxos/react-ui-menu": "0.8.4-main.8360d9e660",
43
+ "@dxos/react-ui-mosaic": "0.8.4-main.8360d9e660",
44
+ "@dxos/schema": "0.8.4-main.8360d9e660",
45
+ "@dxos/react-ui-searchlist": "0.8.4-main.8360d9e660",
46
+ "@dxos/util": "0.8.4-main.8360d9e660",
47
+ "@dxos/react-ui-stack": "0.8.4-main.8360d9e660"
43
48
  },
44
49
  "devDependencies": {
45
50
  "@types/react": "~19.2.7",
46
51
  "@types/react-dom": "~19.2.3",
47
- "effect": "3.19.11",
52
+ "effect": "3.19.16",
48
53
  "react": "~19.2.3",
49
54
  "react-dom": "~19.2.3",
50
- "vite": "7.1.9",
51
- "@dxos/plugin-client": "0.8.4-main.69d29f4",
52
- "@dxos/plugin-preview": "0.8.4-main.69d29f4",
53
- "@dxos/plugin-search": "0.8.4-main.69d29f4",
54
- "@dxos/plugin-space": "0.8.4-main.69d29f4",
55
- "@dxos/react-ui": "0.8.4-main.69d29f4",
56
- "@dxos/plugin-testing": "0.8.4-main.69d29f4",
57
- "@dxos/schema": "0.8.4-main.69d29f4",
58
- "@dxos/storybook-utils": "0.8.4-main.69d29f4",
59
- "@dxos/ui-theme": "0.8.4-main.69d29f4"
55
+ "vite": "^7.1.11",
56
+ "@dxos/app-graph": "0.8.4-main.8360d9e660",
57
+ "@dxos/plugin-client": "0.8.4-main.8360d9e660",
58
+ "@dxos/plugin-preview": "0.8.4-main.8360d9e660",
59
+ "@dxos/plugin-search": "0.8.4-main.8360d9e660",
60
+ "@dxos/react-ui": "0.8.4-main.8360d9e660",
61
+ "@dxos/schema": "0.8.4-main.8360d9e660",
62
+ "@dxos/plugin-testing": "0.8.4-main.8360d9e660",
63
+ "@dxos/plugin-space": "0.8.4-main.8360d9e660",
64
+ "@dxos/storybook-utils": "0.8.4-main.8360d9e660",
65
+ "@dxos/ui-theme": "0.8.4-main.8360d9e660"
60
66
  },
61
67
  "peerDependencies": {
62
- "effect": "3.19.11",
68
+ "effect": "3.19.16",
63
69
  "react": "~19.2.3",
64
70
  "react-dom": "~19.2.3",
65
- "@dxos/react-ui": "0.8.4-main.69d29f4",
66
- "@dxos/ui-theme": "0.8.4-main.69d29f4"
71
+ "@dxos/react-ui": "0.8.4-main.8360d9e660",
72
+ "@dxos/ui-theme": "0.8.4-main.8360d9e660"
67
73
  },
68
74
  "publishConfig": {
69
75
  "access": "public"
@@ -2,7 +2,8 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { ActivationEvent, Capability, Common, Plugin } from '@dxos/app-framework';
5
+ import { ActivationEvent, ActivationEvents, Capability, Plugin } from '@dxos/app-framework';
6
+ import { AppActivationEvents, AppPlugin } from '@dxos/app-toolkit';
6
7
 
7
8
  import { OperationResolver, ReactRoot, ReactSurface, SpotlightDismiss, State, UrlHandler } from './capabilities';
8
9
  import { meta } from './meta';
@@ -15,33 +16,33 @@ export type SimpleLayoutPluginOptions = {
15
16
  };
16
17
 
17
18
  export const SimpleLayoutPlugin = Plugin.define<SimpleLayoutPluginOptions>(meta).pipe(
19
+ AppPlugin.addOperationResolverModule({ activate: OperationResolver }),
20
+ AppPlugin.addTranslationsModule({ translations }),
18
21
  Plugin.addModule(({ isPopover = false }) => ({
19
22
  id: Capability.getModuleTag(State),
20
- activatesOn: Common.ActivationEvent.Startup,
21
- activatesAfter: [SimpleLayoutEvents.StateReady, Common.ActivationEvent.LayoutReady],
23
+ activatesOn: ActivationEvents.Startup,
24
+ activatesAfter: [SimpleLayoutEvents.StateReady, AppActivationEvents.LayoutReady],
22
25
  activate: () => State({ initialState: { isPopover } }),
23
26
  })),
24
27
  Plugin.addModule(({ isPopover = false }) => ({
25
28
  id: Capability.getModuleTag(SpotlightDismiss),
26
- activatesOn: Common.ActivationEvent.Startup,
29
+ activatesOn: ActivationEvents.Startup,
27
30
  activate: () => SpotlightDismiss({ isPopover }),
28
31
  })),
29
32
  Plugin.addModule({
30
33
  id: Capability.getModuleTag(ReactRoot),
31
- activatesOn: Common.ActivationEvent.Startup,
34
+ activatesOn: ActivationEvents.Startup,
32
35
  activate: ReactRoot,
33
36
  }),
34
37
  Plugin.addModule({
35
38
  id: Capability.getModuleTag(ReactSurface),
36
- activatesOn: Common.ActivationEvent.Startup,
39
+ activatesOn: ActivationEvents.Startup,
37
40
  activate: ReactSurface,
38
41
  }),
39
42
  Plugin.addModule({
40
43
  id: Capability.getModuleTag(UrlHandler),
41
- activatesOn: ActivationEvent.allOf(Common.ActivationEvent.OperationInvokerReady, SimpleLayoutEvents.StateReady),
44
+ activatesOn: ActivationEvent.allOf(ActivationEvents.OperationInvokerReady, SimpleLayoutEvents.StateReady),
42
45
  activate: UrlHandler,
43
46
  }),
44
- Common.Plugin.addOperationResolverModule({ activate: OperationResolver }),
45
- Common.Plugin.addTranslationsModule({ translations }),
46
47
  Plugin.make,
47
48
  );
@@ -4,7 +4,8 @@
4
4
 
5
5
  import * as Effect from 'effect/Effect';
6
6
 
7
- import { Capability, Common } from '@dxos/app-framework';
7
+ import { Capabilities, Capability } from '@dxos/app-framework';
8
+ import { getCompanionVariant, LayoutOperation, isPinnedWorkspace } from '@dxos/app-toolkit';
8
9
  import { Operation, OperationResolver } from '@dxos/operation';
9
10
 
10
11
  import { type SimpleLayoutState, SimpleLayoutState as SimpleLayoutStateCapability } from '../../types';
@@ -14,7 +15,7 @@ const MAX_HISTORY_LENGTH = 50;
14
15
 
15
16
  export default Capability.makeModule(
16
17
  Effect.fnUntraced(function* () {
17
- const registry = yield* Capability.get(Common.Capability.AtomRegistry);
18
+ const registry = yield* Capability.get(Capabilities.AtomRegistry);
18
19
  const stateAtom = yield* Capability.get(SimpleLayoutStateCapability);
19
20
 
20
21
  const getState = () => registry.get(stateAtom);
@@ -22,28 +23,53 @@ export default Capability.makeModule(
22
23
  registry.set(stateAtom, fn(getState()));
23
24
  };
24
25
 
25
- return Capability.contributes(Common.Capability.OperationResolver, [
26
+ return Capability.contributes(Capabilities.OperationResolver, [
27
+ //
28
+ // SetLayoutMode
29
+ //
30
+ // TODO(burdon): No-op for to fix startup bug?
31
+ OperationResolver.make({
32
+ operation: LayoutOperation.SetLayoutMode,
33
+ handler: Effect.fnUntraced(function* () {}),
34
+ }),
35
+
26
36
  //
27
37
  // UpdateSidebar - No-op for simple layout.
28
38
  //
29
39
  OperationResolver.make({
30
- operation: Common.LayoutOperation.UpdateSidebar,
40
+ operation: LayoutOperation.UpdateSidebar,
31
41
  handler: () => Effect.void,
32
42
  }),
33
43
 
34
44
  //
35
- // UpdateComplementary - No-op for simple layout.
45
+ // UpdateComplementary - Controls companion drawer.
36
46
  //
47
+ // TODO(wittjosiah): Not sure if we should be using this for the drawer.
37
48
  OperationResolver.make({
38
- operation: Common.LayoutOperation.UpdateComplementary,
39
- handler: () => Effect.void,
49
+ operation: LayoutOperation.UpdateComplementary,
50
+ handler: Effect.fnUntraced(function* (input) {
51
+ if (input.state === 'closed') {
52
+ updateState((state) => ({
53
+ ...state,
54
+ drawerState: 'closed',
55
+ companionVariant: undefined,
56
+ }));
57
+ } else if (input.subject) {
58
+ const variant = getCompanionVariant(input.subject);
59
+ updateState((state) => ({
60
+ ...state,
61
+ companionVariant: variant,
62
+ drawerState: input.state === 'expanded' ? 'expanded' : 'open',
63
+ }));
64
+ }
65
+ }),
40
66
  }),
41
67
 
42
68
  //
43
69
  // UpdateDialog
44
70
  //
45
71
  OperationResolver.make({
46
- operation: Common.LayoutOperation.UpdateDialog,
72
+ operation: LayoutOperation.UpdateDialog,
47
73
  handler: Effect.fnUntraced(function* (input) {
48
74
  updateState((state) => ({
49
75
  ...state,
@@ -61,7 +87,7 @@ export default Capability.makeModule(
61
87
  // UpdatePopover
62
88
  //
63
89
  OperationResolver.make({
64
- operation: Common.LayoutOperation.UpdatePopover,
90
+ operation: LayoutOperation.UpdatePopover,
65
91
  handler: Effect.fnUntraced(function* (input) {
66
92
  updateState((state) => ({
67
93
  ...state,
@@ -86,13 +112,13 @@ export default Capability.makeModule(
86
112
  // SwitchWorkspace
87
113
  //
88
114
  OperationResolver.make({
89
- operation: Common.LayoutOperation.SwitchWorkspace,
115
+ operation: LayoutOperation.SwitchWorkspace,
90
116
  handler: Effect.fnUntraced(function* (input) {
91
117
  updateState((state) => ({
92
118
  ...state,
93
119
  // TODO(wittjosiah): This is a hack to prevent the previous deck from being set for pinned items.
94
120
  // Ideally this should be worked into the data model in a generic way.
95
- previousWorkspace: !state.workspace.startsWith('!') ? state.workspace : state.previousWorkspace,
121
+ previousWorkspace: !isPinnedWorkspace(state.workspace) ? state.workspace : state.previousWorkspace,
96
122
  workspace: input.subject,
97
123
  active: undefined,
98
124
  // Clear history when switching workspaces.
@@ -105,10 +131,10 @@ export default Capability.makeModule(
105
131
  // RevertWorkspace
106
132
  //
107
133
  OperationResolver.make({
108
- operation: Common.LayoutOperation.RevertWorkspace,
134
+ operation: LayoutOperation.RevertWorkspace,
109
135
  handler: Effect.fnUntraced(function* () {
110
136
  const state = getState();
111
- yield* Operation.invoke(Common.LayoutOperation.SwitchWorkspace, {
137
+ yield* Operation.invoke(LayoutOperation.SwitchWorkspace, {
112
138
  subject: state.previousWorkspace,
113
139
  });
114
140
  }),
@@ -118,17 +144,16 @@ export default Capability.makeModule(
118
144
  // Open
119
145
  //
120
146
  OperationResolver.make({
121
- operation: Common.LayoutOperation.Open,
147
+ operation: LayoutOperation.Open,
122
148
  handler: Effect.fnUntraced(function* (input) {
149
+ const id = input.subject[0];
123
150
  updateState((state) => {
124
- // Push current active to history if it exists.
125
151
  const newHistory = state.active ? [...state.history, state.active] : state.history;
126
- // Limit history length to prevent memory issues.
127
152
  const trimmedHistory =
128
153
  newHistory.length > MAX_HISTORY_LENGTH ? newHistory.slice(-MAX_HISTORY_LENGTH) : newHistory;
129
154
  return {
130
155
  ...state,
131
- active: input.subject[0],
156
+ active: id,
132
157
  history: trimmedHistory,
133
158
  };
134
159
  });
@@ -139,7 +164,7 @@ export default Capability.makeModule(
139
164
  // Close
140
165
  //
141
166
  OperationResolver.make({
142
- operation: Common.LayoutOperation.Close,
167
+ operation: LayoutOperation.Close,
143
168
  handler: Effect.fnUntraced(function* () {
144
169
  updateState((state) => {
145
170
  // Pop from history if available.
@@ -165,7 +190,7 @@ export default Capability.makeModule(
165
190
  // Set
166
191
  //
167
192
  OperationResolver.make({
168
- operation: Common.LayoutOperation.Set,
193
+ operation: LayoutOperation.Set,
169
194
  handler: Effect.fnUntraced(function* (input) {
170
195
  updateState((state) => ({
171
196
  ...state,
@@ -5,14 +5,14 @@
5
5
  import * as Effect from 'effect/Effect';
6
6
  import React from 'react';
7
7
 
8
- import { Capability, Common } from '@dxos/app-framework';
8
+ import { Capabilities, Capability } from '@dxos/app-framework';
9
9
 
10
10
  import { SimpleLayout } from '../../components';
11
11
  import { meta } from '../../meta';
12
12
 
13
13
  export default Capability.makeModule(() =>
14
14
  Effect.succeed(
15
- Capability.contributes(Common.Capability.ReactRoot, {
15
+ Capability.contributes(Capabilities.ReactRoot, {
16
16
  id: meta.id,
17
17
  root: () => {
18
18
  return <SimpleLayout />;
@@ -5,10 +5,11 @@
5
5
  import * as Effect from 'effect/Effect';
6
6
  import React from 'react';
7
7
 
8
- import { Capability, Common } from '@dxos/app-framework';
8
+ import { Capabilities, Capability } from '@dxos/app-framework';
9
+ import { Surface } from '@dxos/app-framework/ui';
9
10
  import { Node } from '@dxos/plugin-graph';
10
11
 
11
- import { Home, Workspace } from '../../components';
12
+ import { Home, NavBranch } from '../../components';
12
13
  import { meta } from '../../meta';
13
14
 
14
15
  type SurfaceData = {
@@ -16,24 +17,26 @@ type SurfaceData = {
16
17
  properties: Record<string, any>;
17
18
  };
18
19
 
19
- const ALLOWED_DISPOSITIONS = ['workspace', 'user-account', 'pin-end'];
20
+ const ALLOWED_DISPOSITIONS = ['workspace', 'user-account', 'pin-end', 'alternate-tree'];
20
21
 
21
22
  export default Capability.makeModule(() =>
22
23
  Effect.succeed(
23
- Capability.contributes(Common.Capability.ReactSurface, [
24
- Common.createSurface({
25
- id: `${meta.id}/home`,
24
+ Capability.contributes(Capabilities.ReactSurface, [
25
+ Surface.create({
26
+ id: `${meta.id}.home`,
26
27
  role: 'article',
27
28
  filter: (data): data is SurfaceData => data.attendableId === Node.RootId,
28
29
  component: () => <Home />,
29
30
  }),
30
- Common.createSurface({
31
- id: `${meta.id}/workspace-article`,
31
+ Surface.create({
32
+ id: `${meta.id}.nav-branch`,
32
33
  role: 'article',
33
34
  position: 'fallback',
34
- filter: (data): data is SurfaceData =>
35
- ALLOWED_DISPOSITIONS.includes((data.properties as Record<string, any>)?.disposition),
36
- component: ({ data }) => <Workspace id={data.attendableId} />,
35
+ filter: (data): data is SurfaceData => {
36
+ const props = data.properties as Record<string, any>;
37
+ return ALLOWED_DISPOSITIONS.includes(props?.disposition) || props?.role === 'branch';
38
+ },
39
+ component: ({ data }) => <NavBranch id={data.attendableId} />,
37
40
  }),
38
41
  ]),
39
42
  ),
@@ -7,7 +7,7 @@
7
7
 
8
8
  import * as Effect from 'effect/Effect';
9
9
 
10
- import { Capability, Common } from '@dxos/app-framework';
10
+ import { Capabilities, Capability } from '@dxos/app-framework';
11
11
  import { log } from '@dxos/log';
12
12
  import { isTauri } from '@dxos/util';
13
13
 
@@ -76,7 +76,7 @@ export default Capability.makeModule(({ isPopover = false }: SpotlightDismissOpt
76
76
  };
77
77
  window.addEventListener('keydown', handleKeyDown);
78
78
 
79
- return Capability.contributes(Common.Capability.Null, null, () =>
79
+ return Capability.contributes(Capabilities.Null, null, () =>
80
80
  Effect.sync(() => {
81
81
  focusCleanup?.();
82
82
  window.removeEventListener('keydown', handleKeyDown);
@@ -5,7 +5,8 @@
5
5
  import { Atom } from '@effect-atom/atom-react';
6
6
  import * as Effect from 'effect/Effect';
7
7
 
8
- import { Capability, Common } from '@dxos/app-framework';
8
+ import { Capability } from '@dxos/app-framework';
9
+ import { AppCapabilities } from '@dxos/app-toolkit';
9
10
  import { Node } from '@dxos/plugin-graph';
10
11
 
11
12
  import { type SimpleLayoutState } from '../../types';
@@ -17,6 +18,8 @@ const defaultState: SimpleLayoutState = {
17
18
  previousWorkspace: Node.RootId,
18
19
  history: [],
19
20
  isPopover: false,
21
+ companionVariant: undefined,
22
+ drawerState: 'closed',
20
23
  };
21
24
 
22
25
  export type SimpleLayoutStateOptions = {
@@ -27,7 +30,7 @@ export default Capability.makeModule(({ initialState }: SimpleLayoutStateOptions
27
30
  Effect.sync(() => {
28
31
  const stateAtom = Atom.make<SimpleLayoutState>({ ...defaultState, ...initialState });
29
32
 
30
- const layoutAtom = Atom.make((get): Common.Capability.Layout => {
33
+ const layoutAtom = Atom.make((get): AppCapabilities.Layout => {
31
34
  const state = get(stateAtom);
32
35
  return {
33
36
  mode: 'simple',
@@ -43,7 +46,7 @@ export default Capability.makeModule(({ initialState }: SimpleLayoutStateOptions
43
46
 
44
47
  return [
45
48
  Capability.contributes(SimpleLayoutStateCapability, stateAtom),
46
- Capability.contributes(Common.Capability.Layout, layoutAtom),
49
+ Capability.contributes(AppCapabilities.Layout, layoutAtom),
47
50
  ];
48
51
  }),
49
52
  );
@@ -4,77 +4,130 @@
4
4
 
5
5
  import * as Effect from 'effect/Effect';
6
6
 
7
- import { Capability, Common } from '@dxos/app-framework';
8
- import { Node } from '@dxos/plugin-graph';
7
+ import { Capabilities, Capability } from '@dxos/app-framework';
8
+ import { LayoutOperation, fromUrlPath, getWorkspaceFromPath, toUrlPath } from '@dxos/app-toolkit';
9
+ import { log } from '@dxos/log';
10
+ import { isTauri } from '@dxos/util';
9
11
 
10
12
  import { type SimpleLayoutState, SimpleLayoutState as SimpleLayoutStateCapability } from '../../types';
11
13
 
12
14
  /**
13
15
  * URL handler for simple layout that syncs browser URL with layout state.
14
- * URL format: /{workspace} or /{workspace}/{active}
15
- * Root is represented as / or /root.
16
+ * URL paths map directly to qualified graph IDs with the leading `root` segment stripped.
17
+ * Root is represented as `/`.
18
+ *
19
+ * On mobile Tauri, also listens for deep links via the deep-link plugin.
16
20
  */
17
21
  export default Capability.makeModule(
18
22
  Effect.fnUntraced(function* () {
19
- const { invokeSync } = yield* Capability.get(Common.Capability.OperationInvoker);
23
+ const { invokeSync } = yield* Capability.get(Capabilities.OperationInvoker);
20
24
 
21
25
  /**
22
- * Handle navigation events (initial load and popstate).
23
- * Parses URL and updates state accordingly.
26
+ * Handle navigation from a pathname.
27
+ * Restores the qualified graph ID and dispatches layout operations.
24
28
  */
25
- const handleNavigation = () => {
26
- const pathname = window.location.pathname;
29
+ const handlePathNavigation = (pathname: string) => {
30
+ log.info('[UrlHandler] Navigating to path', { pathname });
27
31
 
28
- // Parse URL segments: /{workspace}/{active}
29
- const [_, nextWorkspace, nextActive] = pathname.split('/');
32
+ const qualifiedId = fromUrlPath(pathname);
33
+ const workspace = getWorkspaceFromPath(qualifiedId);
30
34
 
31
- // Determine target workspace (empty or 'root' means Node.RootId).
32
- const targetWorkspace = !nextWorkspace || nextWorkspace === 'root' ? Node.RootId : nextWorkspace;
35
+ invokeSync(LayoutOperation.SwitchWorkspace, { subject: workspace });
33
36
 
34
- // Navigate via operations (they will update state accordingly).
35
- invokeSync(Common.LayoutOperation.SwitchWorkspace, { subject: targetWorkspace });
36
- if (nextActive) {
37
- invokeSync(Common.LayoutOperation.Open, { subject: [nextActive] });
37
+ const activeId = qualifiedId !== workspace ? qualifiedId : undefined;
38
+ if (activeId) {
39
+ invokeSync(LayoutOperation.Open, { subject: [activeId] });
38
40
  }
39
41
  };
40
42
 
41
- // Handle initial URL and listen for browser navigation.
42
- yield* Effect.sync(() => handleNavigation());
43
- window.addEventListener('popstate', handleNavigation);
43
+ const onNavigation = handleNavigation(handlePathNavigation);
44
+
45
+ yield* Effect.sync(() => onNavigation());
46
+ window.addEventListener('popstate', onNavigation);
47
+
48
+ let unlistenDeepLink: (() => void) | undefined;
49
+ if (isTauri()) {
50
+ yield* Effect.tryPromise({
51
+ try: async () => {
52
+ const { getCurrent, onOpenUrl } = await import('@tauri-apps/plugin-deep-link');
53
+
54
+ const launchUrls = await getCurrent();
55
+ if (launchUrls && launchUrls.length > 0) {
56
+ log.info('[UrlHandler] App launched with deep links', { urls: launchUrls });
57
+ for (const url of launchUrls) {
58
+ handleDeepLink(url, handlePathNavigation);
59
+ }
60
+ }
61
+
62
+ unlistenDeepLink = await onOpenUrl((urls) => {
63
+ log.info('[UrlHandler] Deep links received', { urls });
64
+ for (const url of urls) {
65
+ handleDeepLink(url, handlePathNavigation);
66
+ }
67
+ });
68
+
69
+ log.info('[UrlHandler] Deep link listener initialized');
70
+ },
71
+ catch: (error) => {
72
+ log.warn('[UrlHandler] Failed to initialize deep link listener', { error });
73
+ return error;
74
+ },
75
+ }).pipe(Effect.catchAll(() => Effect.void));
76
+ }
44
77
 
45
- // Subscribe to state changes to update the URL.
46
78
  let lastWorkspace: string | undefined;
47
79
  let lastActive: string | undefined;
48
- const unsubscribe = yield* Common.Capability.subscribeAtom(
49
- SimpleLayoutStateCapability,
50
- (state: SimpleLayoutState) => {
51
- const { workspace, active } = state;
52
-
53
- // Only update URL if relevant state changed.
54
- if (workspace !== lastWorkspace || active !== lastActive) {
55
- lastWorkspace = workspace;
56
- lastActive = active;
57
-
58
- // Build path: root is represented as /, other workspaces as /{workspace}.
59
- let path: string;
60
- if (workspace === Node.RootId) {
61
- path = active ? `/${Node.RootId}/${active}` : '/';
62
- } else {
63
- path = active ? `/${workspace}/${active}` : `/${workspace}`;
64
- }
80
+ const unsubscribe = yield* Capabilities.subscribeAtom(SimpleLayoutStateCapability, (state: SimpleLayoutState) => {
81
+ const { workspace, active } = state;
65
82
 
66
- if (window.location.pathname !== path) {
67
- history.pushState(null, '', `${path}${window.location.search}`);
68
- }
83
+ if (workspace !== lastWorkspace || active !== lastActive) {
84
+ lastWorkspace = workspace;
85
+ lastActive = active;
86
+
87
+ const path = active ? toUrlPath(active) : toUrlPath(workspace);
88
+ if (window.location.pathname !== path) {
89
+ history.pushState(null, '', `${path}${window.location.search}`);
69
90
  }
70
- },
71
- );
91
+ }
92
+ });
72
93
 
73
- return Capability.contributes(Common.Capability.Null, null, () =>
94
+ return Capability.contributes(Capabilities.Null, null, () =>
74
95
  Effect.sync(() => {
75
- window.removeEventListener('popstate', handleNavigation);
96
+ window.removeEventListener('popstate', onNavigation);
76
97
  unsubscribe();
98
+ unlistenDeepLink?.();
77
99
  }),
78
100
  );
79
101
  }),
80
102
  );
103
+
104
+ /**
105
+ * Check if a path is a special redirect path that shouldn't be navigated to.
106
+ * These paths are handled by other systems (e.g., OAuth).
107
+ */
108
+ const isRedirectPath = (pathname: string): boolean => pathname.startsWith('/redirect/');
109
+
110
+ /**
111
+ * Returns a handler for navigation events (initial load and popstate) that navigates to current pathname.
112
+ */
113
+ const handleNavigation =
114
+ (navigate: (pathname: string) => void): (() => void) =>
115
+ () =>
116
+ navigate(window.location.pathname);
117
+
118
+ /**
119
+ * Handle deep link URL from Tauri. Parses the URL and calls navigate unless it's a redirect path.
120
+ */
121
+ const handleDeepLink = (urlString: string, navigate: (pathname: string) => void): void => {
122
+ log.info('[UrlHandler] Deep link received', { url: urlString });
123
+ try {
124
+ const url = new URL(urlString);
125
+ if (isRedirectPath(url.pathname)) {
126
+ log.info('[UrlHandler] Skipping redirect path (handled elsewhere)', { pathname: url.pathname });
127
+ return;
128
+ }
129
+ navigate(url.pathname);
130
+ } catch (error) {
131
+ log.warn('[UrlHandler] Failed to parse deep link URL', { urlString, error });
132
+ }
133
+ };
@@ -4,28 +4,29 @@
4
4
 
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
 
7
+ import { ErrorFallback } from '@dxos/react-ui';
7
8
  import { withTheme } from '@dxos/react-ui/testing';
8
9
 
9
10
  import { translations } from '../translations';
10
11
 
11
- import { ContentError } from './ContentError';
12
-
13
12
  const meta = {
14
- title: 'plugins/plugin-simple-layout/ContentError',
15
- component: ContentError,
16
- decorators: [withTheme],
13
+ title: 'plugins/plugin-simple-layout/components/ErrorFallback',
14
+ component: ErrorFallback,
15
+ decorators: [withTheme()],
17
16
  parameters: {
18
17
  layout: 'centered',
19
18
  translations,
20
19
  },
21
- } satisfies Meta<typeof ContentError>;
20
+ } satisfies Meta<typeof ErrorFallback>;
22
21
 
23
22
  export default meta;
24
23
 
25
24
  type Story = StoryObj<typeof meta>;
26
25
 
27
26
  export const Default: Story = {
28
- args: {},
27
+ args: {
28
+ error: new Error('An unexpected error occurred'),
29
+ },
29
30
  };
30
31
 
31
32
  export const WithError: Story = {
@@ -9,9 +9,9 @@ import { withTheme } from '@dxos/react-ui/testing';
9
9
  import { ContentLoading } from './ContentLoading';
10
10
 
11
11
  const meta = {
12
- title: 'plugins/plugin-simple-layout/ContentLoading',
12
+ title: 'plugins/plugin-simple-layout/components/ContentLoading',
13
13
  component: ContentLoading,
14
- decorators: [withTheme],
14
+ decorators: [withTheme()],
15
15
  parameters: {
16
16
  layout: 'centered',
17
17
  },