@dxos/plugin-simple-layout 0.8.4-main.d05673bc65 → 0.8.4-main.fcfe5033a5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/dist/lib/browser/index.mjs +35 -56
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +35 -55
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/SimpleLayoutPlugin.d.ts +1 -1
  8. package/dist/types/src/SimpleLayoutPlugin.d.ts.map +1 -1
  9. package/dist/types/src/capabilities/app-graph-builder.d.ts +6 -0
  10. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  11. package/dist/types/src/capabilities/index.d.ts +21 -6
  12. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  13. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  14. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  15. package/dist/types/src/capabilities/react-root.d.ts.map +1 -0
  16. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  17. package/dist/types/src/capabilities/spotlight-dismiss.d.ts.map +1 -0
  18. package/dist/types/src/capabilities/{state/state.d.ts → state.d.ts} +1 -1
  19. package/dist/types/src/capabilities/state.d.ts.map +1 -0
  20. package/dist/types/src/capabilities/{url-handler/url-handler.d.ts → url-handler.d.ts} +1 -1
  21. package/dist/types/src/capabilities/url-handler.d.ts.map +1 -0
  22. package/dist/types/src/components/ContentError.stories.d.ts +25 -18
  23. package/dist/types/src/components/ContentError.stories.d.ts.map +1 -1
  24. package/dist/types/src/components/DebugOverlay/DebugOverlay.d.ts +19 -0
  25. package/dist/types/src/components/DebugOverlay/DebugOverlay.d.ts.map +1 -0
  26. package/dist/types/src/components/DebugOverlay/index.d.ts +2 -0
  27. package/dist/types/src/components/DebugOverlay/index.d.ts.map +1 -0
  28. package/dist/types/src/components/Dialog/Dialog.d.ts.map +1 -1
  29. package/dist/types/src/components/Home/Home.d.ts.map +1 -1
  30. package/dist/types/src/components/Loading/Loading.d.ts +3 -0
  31. package/dist/types/src/components/Loading/Loading.d.ts.map +1 -0
  32. package/dist/types/src/components/{ContentLoading/ContentLoading.stories.d.ts → Loading/Loading.stories.d.ts} +1 -1
  33. package/dist/types/src/components/Loading/Loading.stories.d.ts.map +1 -0
  34. package/dist/types/src/components/Loading/index.d.ts +2 -0
  35. package/dist/types/src/components/Loading/index.d.ts.map +1 -0
  36. package/dist/types/src/components/MobileLayout/MobileLayout.d.ts.map +1 -1
  37. package/dist/types/src/components/MobileLayout/MobileLayout.stories.d.ts.map +1 -1
  38. package/dist/types/src/components/NavBranch/NavBranch.d.ts.map +1 -1
  39. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  40. package/dist/types/src/components/SimpleLayout/AppBar.d.ts +5 -7
  41. package/dist/types/src/components/SimpleLayout/AppBar.d.ts.map +1 -1
  42. package/dist/types/src/components/SimpleLayout/AppBar.stories.d.ts +28 -21
  43. package/dist/types/src/components/SimpleLayout/AppBar.stories.d.ts.map +1 -1
  44. package/dist/types/src/components/SimpleLayout/Drawer.d.ts.map +1 -1
  45. package/dist/types/src/components/SimpleLayout/Main.d.ts.map +1 -1
  46. package/dist/types/src/components/SimpleLayout/NavBar.d.ts +5 -7
  47. package/dist/types/src/components/SimpleLayout/NavBar.d.ts.map +1 -1
  48. package/dist/types/src/components/SimpleLayout/NavBar.stories.d.ts +28 -22
  49. package/dist/types/src/components/SimpleLayout/NavBar.stories.d.ts.map +1 -1
  50. package/dist/types/src/components/SimpleLayout/SimpleLayout.d.ts.map +1 -1
  51. package/dist/types/src/components/SimpleLayout/SimpleLayout.stories.d.ts +26 -25
  52. package/dist/types/src/components/SimpleLayout/SimpleLayout.stories.d.ts.map +1 -1
  53. package/dist/types/src/components/index.d.ts +2 -1
  54. package/dist/types/src/components/index.d.ts.map +1 -1
  55. package/dist/types/src/hooks/actions.d.ts +1 -1
  56. package/dist/types/src/hooks/actions.d.ts.map +1 -1
  57. package/dist/types/src/hooks/useAppBarProps.d.ts +1 -1
  58. package/dist/types/src/hooks/useAppBarProps.d.ts.map +1 -1
  59. package/dist/types/src/hooks/useSimpleLayoutState.d.ts +1 -1
  60. package/dist/types/src/hooks/useSimpleLayoutState.d.ts.map +1 -1
  61. package/dist/types/src/operations/close.d.ts +5 -0
  62. package/dist/types/src/operations/close.d.ts.map +1 -0
  63. package/dist/types/src/operations/index.d.ts +3 -0
  64. package/dist/types/src/operations/index.d.ts.map +1 -0
  65. package/dist/types/src/operations/open.d.ts +5 -0
  66. package/dist/types/src/operations/open.d.ts.map +1 -0
  67. package/dist/types/src/operations/revert-workspace.d.ts +5 -0
  68. package/dist/types/src/operations/revert-workspace.d.ts.map +1 -0
  69. package/dist/types/src/operations/set-layout-mode.d.ts +5 -0
  70. package/dist/types/src/operations/set-layout-mode.d.ts.map +1 -0
  71. package/dist/types/src/operations/set.d.ts +5 -0
  72. package/dist/types/src/operations/set.d.ts.map +1 -0
  73. package/dist/types/src/operations/state-access.d.ts +8 -0
  74. package/dist/types/src/operations/state-access.d.ts.map +1 -0
  75. package/dist/types/src/operations/switch-workspace.d.ts +5 -0
  76. package/dist/types/src/operations/switch-workspace.d.ts.map +1 -0
  77. package/dist/types/src/operations/update-complementary.d.ts +5 -0
  78. package/dist/types/src/operations/update-complementary.d.ts.map +1 -0
  79. package/dist/types/src/operations/update-dialog.d.ts +5 -0
  80. package/dist/types/src/operations/update-dialog.d.ts.map +1 -0
  81. package/dist/types/src/operations/update-popover.d.ts +5 -0
  82. package/dist/types/src/operations/update-popover.d.ts.map +1 -0
  83. package/dist/types/src/operations/update-sidebar.d.ts +5 -0
  84. package/dist/types/src/operations/update-sidebar.d.ts.map +1 -0
  85. package/dist/types/src/translations.d.ts +26 -19
  86. package/dist/types/src/translations.d.ts.map +1 -1
  87. package/dist/types/src/types/capabilities.d.ts +10 -2
  88. package/dist/types/src/types/capabilities.d.ts.map +1 -1
  89. package/dist/types/tsconfig.tsbuildinfo +1 -1
  90. package/package.json +39 -29
  91. package/src/SimpleLayoutPlugin.ts +16 -6
  92. package/src/capabilities/app-graph-builder.ts +21 -0
  93. package/src/capabilities/index.ts +13 -6
  94. package/src/capabilities/operation-handler.ts +14 -0
  95. package/src/capabilities/{react-root/react-root.tsx → react-root.tsx} +2 -2
  96. package/src/capabilities/{react-surface/react-surface.tsx → react-surface.tsx} +11 -4
  97. package/src/capabilities/{state/state.tsx → state.tsx} +2 -2
  98. package/src/capabilities/url-handler.ts +161 -0
  99. package/src/components/DebugOverlay/DebugOverlay.tsx +96 -0
  100. package/src/components/DebugOverlay/index.ts +5 -0
  101. package/src/components/Dialog/Dialog.tsx +14 -3
  102. package/src/components/Home/Home.tsx +29 -29
  103. package/src/components/{ContentLoading/ContentLoading.stories.tsx → Loading/Loading.stories.tsx} +4 -4
  104. package/src/components/{ContentLoading/ContentLoading.tsx → Loading/Loading.tsx} +1 -1
  105. package/src/components/{ContentLoading → Loading}/index.ts +1 -1
  106. package/src/components/MobileLayout/MobileLayout.stories.tsx +21 -17
  107. package/src/components/MobileLayout/MobileLayout.tsx +118 -49
  108. package/src/components/NavBranch/NavBranch.tsx +29 -31
  109. package/src/components/Popover/Popover.tsx +10 -16
  110. package/src/components/SimpleLayout/AppBar.stories.tsx +8 -9
  111. package/src/components/SimpleLayout/AppBar.tsx +60 -60
  112. package/src/components/SimpleLayout/Drawer.tsx +30 -22
  113. package/src/components/SimpleLayout/Main.tsx +19 -23
  114. package/src/components/SimpleLayout/NavBar.stories.tsx +1 -2
  115. package/src/components/SimpleLayout/NavBar.tsx +8 -9
  116. package/src/components/SimpleLayout/SimpleLayout.stories.tsx +43 -66
  117. package/src/components/SimpleLayout/SimpleLayout.tsx +33 -34
  118. package/src/components/hooks.ts +1 -1
  119. package/src/components/index.ts +2 -1
  120. package/src/hooks/actions.ts +4 -3
  121. package/src/hooks/useAppBarProps.ts +9 -9
  122. package/src/hooks/useDrawerActions.ts +6 -6
  123. package/src/hooks/useNavbarActions.ts +3 -3
  124. package/src/hooks/useSimpleLayoutState.ts +1 -1
  125. package/src/operations/close.ts +34 -0
  126. package/src/operations/index.ts +16 -0
  127. package/src/operations/open.ts +63 -0
  128. package/src/operations/revert-workspace.ts +22 -0
  129. package/src/operations/set-layout-mode.ts +12 -0
  130. package/src/operations/set.ts +23 -0
  131. package/src/operations/state-access.ts +19 -0
  132. package/src/operations/switch-workspace.ts +26 -0
  133. package/src/operations/update-complementary.ts +35 -0
  134. package/src/operations/update-dialog.ts +28 -0
  135. package/src/operations/update-popover.ts +35 -0
  136. package/src/operations/update-sidebar.ts +12 -0
  137. package/src/translations.ts +21 -19
  138. package/src/types/capabilities.ts +3 -3
  139. package/dist/lib/browser/chunk-MDPEKLKR.mjs +0 -1163
  140. package/dist/lib/browser/chunk-MDPEKLKR.mjs.map +0 -7
  141. package/dist/lib/browser/chunk-MRR7PXSM.mjs +0 -29
  142. package/dist/lib/browser/chunk-MRR7PXSM.mjs.map +0 -7
  143. package/dist/lib/browser/operation-resolver-VTZ6HZ4B.mjs +0 -194
  144. package/dist/lib/browser/operation-resolver-VTZ6HZ4B.mjs.map +0 -7
  145. package/dist/lib/browser/react-root-WVQYY2JA.mjs +0 -21
  146. package/dist/lib/browser/react-root-WVQYY2JA.mjs.map +0 -7
  147. package/dist/lib/browser/react-surface-VLBR37ED.mjs +0 -44
  148. package/dist/lib/browser/react-surface-VLBR37ED.mjs.map +0 -7
  149. package/dist/lib/browser/spotlight-dismiss-67PHYS5B.mjs +0 -66
  150. package/dist/lib/browser/spotlight-dismiss-67PHYS5B.mjs.map +0 -7
  151. package/dist/lib/browser/state-TXSMUWYI.mjs +0 -48
  152. package/dist/lib/browser/state-TXSMUWYI.mjs.map +0 -7
  153. package/dist/lib/browser/url-handler-RBRONH7S.mjs +0 -151
  154. package/dist/lib/browser/url-handler-RBRONH7S.mjs.map +0 -7
  155. package/dist/lib/node-esm/chunk-DCKASLMP.mjs +0 -1164
  156. package/dist/lib/node-esm/chunk-DCKASLMP.mjs.map +0 -7
  157. package/dist/lib/node-esm/chunk-WMNTJ2MK.mjs +0 -31
  158. package/dist/lib/node-esm/chunk-WMNTJ2MK.mjs.map +0 -7
  159. package/dist/lib/node-esm/operation-resolver-R7CQ6ERU.mjs +0 -195
  160. package/dist/lib/node-esm/operation-resolver-R7CQ6ERU.mjs.map +0 -7
  161. package/dist/lib/node-esm/react-root-XBNDM7BE.mjs +0 -22
  162. package/dist/lib/node-esm/react-root-XBNDM7BE.mjs.map +0 -7
  163. package/dist/lib/node-esm/react-surface-U5NHA367.mjs +0 -45
  164. package/dist/lib/node-esm/react-surface-U5NHA367.mjs.map +0 -7
  165. package/dist/lib/node-esm/spotlight-dismiss-RMLRZUVY.mjs +0 -68
  166. package/dist/lib/node-esm/spotlight-dismiss-RMLRZUVY.mjs.map +0 -7
  167. package/dist/lib/node-esm/state-JMX6FAG4.mjs +0 -49
  168. package/dist/lib/node-esm/state-JMX6FAG4.mjs.map +0 -7
  169. package/dist/lib/node-esm/url-handler-QSMCH3JB.mjs +0 -152
  170. package/dist/lib/node-esm/url-handler-QSMCH3JB.mjs.map +0 -7
  171. package/dist/types/src/capabilities/operation-resolver/index.d.ts +0 -3
  172. package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +0 -1
  173. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +0 -5
  174. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +0 -1
  175. package/dist/types/src/capabilities/react-root/index.d.ts +0 -6
  176. package/dist/types/src/capabilities/react-root/index.d.ts.map +0 -1
  177. package/dist/types/src/capabilities/react-root/react-root.d.ts.map +0 -1
  178. package/dist/types/src/capabilities/react-surface/index.d.ts +0 -3
  179. package/dist/types/src/capabilities/react-surface/index.d.ts.map +0 -1
  180. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +0 -1
  181. package/dist/types/src/capabilities/spotlight-dismiss/index.d.ts +0 -3
  182. package/dist/types/src/capabilities/spotlight-dismiss/index.d.ts.map +0 -1
  183. package/dist/types/src/capabilities/spotlight-dismiss/spotlight-dismiss.d.ts.map +0 -1
  184. package/dist/types/src/capabilities/state/index.d.ts +0 -13
  185. package/dist/types/src/capabilities/state/index.d.ts.map +0 -1
  186. package/dist/types/src/capabilities/state/state.d.ts.map +0 -1
  187. package/dist/types/src/capabilities/url-handler/index.d.ts +0 -3
  188. package/dist/types/src/capabilities/url-handler/index.d.ts.map +0 -1
  189. package/dist/types/src/capabilities/url-handler/url-handler.d.ts.map +0 -1
  190. package/dist/types/src/components/ContentLoading/ContentLoading.d.ts +0 -3
  191. package/dist/types/src/components/ContentLoading/ContentLoading.d.ts.map +0 -1
  192. package/dist/types/src/components/ContentLoading/ContentLoading.stories.d.ts.map +0 -1
  193. package/dist/types/src/components/ContentLoading/index.d.ts +0 -2
  194. package/dist/types/src/components/ContentLoading/index.d.ts.map +0 -1
  195. package/src/capabilities/operation-resolver/index.ts +0 -10
  196. package/src/capabilities/operation-resolver/operation-resolver.ts +0 -202
  197. package/src/capabilities/react-root/index.ts +0 -7
  198. package/src/capabilities/react-surface/index.ts +0 -7
  199. package/src/capabilities/spotlight-dismiss/index.ts +0 -7
  200. package/src/capabilities/state/index.ts +0 -9
  201. package/src/capabilities/url-handler/index.ts +0 -7
  202. package/src/capabilities/url-handler/url-handler.ts +0 -133
  203. /package/dist/types/src/capabilities/{react-root/react-root.d.ts → react-root.d.ts} +0 -0
  204. /package/dist/types/src/capabilities/{react-surface/react-surface.d.ts → react-surface.d.ts} +0 -0
  205. /package/dist/types/src/capabilities/{spotlight-dismiss/spotlight-dismiss.d.ts → spotlight-dismiss.d.ts} +0 -0
  206. /package/src/capabilities/{spotlight-dismiss/spotlight-dismiss.ts → spotlight-dismiss.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.d05673bc65",
3
+ "version": "0.8.4-main.fcfe5033a5",
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",
@@ -12,6 +12,14 @@
12
12
  "author": "DXOS.org",
13
13
  "sideEffects": true,
14
14
  "type": "module",
15
+ "imports": {
16
+ "#capabilities": "./src/capabilities/index.ts",
17
+ "#components": "./src/components/index.ts",
18
+ "#hooks": "./src/hooks/index.ts",
19
+ "#meta": "./src/meta.ts",
20
+ "#operations": "./src/operations/index.ts",
21
+ "#types": "./src/types/index.ts"
22
+ },
15
23
  "exports": {
16
24
  ".": {
17
25
  "source": "./src/index.ts",
@@ -31,45 +39,47 @@
31
39
  "@radix-ui/react-context": "1.1.1",
32
40
  "@tauri-apps/plugin-deep-link": "^2.2.0",
33
41
  "@tauri-apps/plugin-haptics": "^2.3.2",
34
- "@dxos/app-toolkit": "0.8.4-main.d05673bc65",
35
- "@dxos/echo": "0.8.4-main.d05673bc65",
36
- "@dxos/async": "0.8.4-main.d05673bc65",
37
- "@dxos/app-framework": "0.8.4-main.d05673bc65",
38
- "@dxos/log": "0.8.4-main.d05673bc65",
39
- "@dxos/react-ui-attention": "0.8.4-main.d05673bc65",
40
- "@dxos/operation": "0.8.4-main.d05673bc65",
41
- "@dxos/plugin-graph": "0.8.4-main.d05673bc65",
42
- "@dxos/react-ui-menu": "0.8.4-main.d05673bc65",
43
- "@dxos/react-ui-mosaic": "0.8.4-main.d05673bc65",
44
- "@dxos/react-ui-searchlist": "0.8.4-main.d05673bc65",
45
- "@dxos/react-ui-stack": "0.8.4-main.d05673bc65",
46
- "@dxos/schema": "0.8.4-main.d05673bc65",
47
- "@dxos/util": "0.8.4-main.d05673bc65"
42
+ "@dxos/app-toolkit": "0.8.4-main.fcfe5033a5",
43
+ "@dxos/async": "0.8.4-main.fcfe5033a5",
44
+ "@dxos/context": "0.8.4-main.fcfe5033a5",
45
+ "@dxos/effect": "0.8.4-main.fcfe5033a5",
46
+ "@dxos/echo": "0.8.4-main.fcfe5033a5",
47
+ "@dxos/log": "0.8.4-main.fcfe5033a5",
48
+ "@dxos/operation": "0.8.4-main.fcfe5033a5",
49
+ "@dxos/plugin-graph": "0.8.4-main.fcfe5033a5",
50
+ "@dxos/app-framework": "0.8.4-main.fcfe5033a5",
51
+ "@dxos/plugin-client": "0.8.4-main.fcfe5033a5",
52
+ "@dxos/react-ui-attention": "0.8.4-main.fcfe5033a5",
53
+ "@dxos/react-ui-menu": "0.8.4-main.fcfe5033a5",
54
+ "@dxos/react-ui-search": "0.8.4-main.fcfe5033a5",
55
+ "@dxos/react-ui-mosaic": "0.8.4-main.fcfe5033a5",
56
+ "@dxos/schema": "0.8.4-main.fcfe5033a5",
57
+ "@dxos/react-ui-stack": "0.8.4-main.fcfe5033a5",
58
+ "@dxos/util": "0.8.4-main.fcfe5033a5"
48
59
  },
49
60
  "devDependencies": {
50
61
  "@types/react": "~19.2.7",
51
62
  "@types/react-dom": "~19.2.3",
52
- "effect": "3.19.16",
63
+ "effect": "3.20.0",
53
64
  "react": "~19.2.3",
54
65
  "react-dom": "~19.2.3",
55
66
  "vite": "^7.1.11",
56
- "@dxos/app-graph": "0.8.4-main.d05673bc65",
57
- "@dxos/plugin-preview": "0.8.4-main.d05673bc65",
58
- "@dxos/plugin-client": "0.8.4-main.d05673bc65",
59
- "@dxos/plugin-search": "0.8.4-main.d05673bc65",
60
- "@dxos/plugin-space": "0.8.4-main.d05673bc65",
61
- "@dxos/plugin-testing": "0.8.4-main.d05673bc65",
62
- "@dxos/schema": "0.8.4-main.d05673bc65",
63
- "@dxos/react-ui": "0.8.4-main.d05673bc65",
64
- "@dxos/ui-theme": "0.8.4-main.d05673bc65",
65
- "@dxos/storybook-utils": "0.8.4-main.d05673bc65"
67
+ "@dxos/app-graph": "0.8.4-main.fcfe5033a5",
68
+ "@dxos/plugin-preview": "0.8.4-main.fcfe5033a5",
69
+ "@dxos/plugin-search": "0.8.4-main.fcfe5033a5",
70
+ "@dxos/plugin-space": "0.8.4-main.fcfe5033a5",
71
+ "@dxos/react-ui": "0.8.4-main.fcfe5033a5",
72
+ "@dxos/plugin-testing": "0.8.4-main.fcfe5033a5",
73
+ "@dxos/ui-theme": "0.8.4-main.fcfe5033a5",
74
+ "@dxos/storybook-utils": "0.8.4-main.fcfe5033a5",
75
+ "@dxos/schema": "0.8.4-main.fcfe5033a5"
66
76
  },
67
77
  "peerDependencies": {
68
- "effect": "3.19.16",
78
+ "effect": "3.20.0",
69
79
  "react": "~19.2.3",
70
80
  "react-dom": "~19.2.3",
71
- "@dxos/ui-theme": "0.8.4-main.d05673bc65",
72
- "@dxos/react-ui": "0.8.4-main.d05673bc65"
81
+ "@dxos/react-ui": "0.8.4-main.fcfe5033a5",
82
+ "@dxos/ui-theme": "0.8.4-main.fcfe5033a5"
73
83
  },
74
84
  "publishConfig": {
75
85
  "access": "public"
@@ -5,23 +5,33 @@
5
5
  import { ActivationEvent, ActivationEvents, Capability, Plugin } from '@dxos/app-framework';
6
6
  import { AppActivationEvents, AppPlugin } from '@dxos/app-toolkit';
7
7
 
8
- import { OperationResolver, ReactRoot, ReactSurface, SpotlightDismiss, State, UrlHandler } from './capabilities';
9
- import { meta } from './meta';
8
+ import {
9
+ AppGraphBuilder,
10
+ OperationHandler,
11
+ ReactRoot,
12
+ ReactSurface,
13
+ SpotlightDismiss,
14
+ State,
15
+ UrlHandler,
16
+ } from '#capabilities';
17
+ import { meta } from '#meta';
18
+ import { SimpleLayoutEvents } from '#types';
19
+
10
20
  import { translations } from './translations';
11
- import { SimpleLayoutEvents } from './types';
12
21
 
13
22
  export type SimpleLayoutPluginOptions = {
14
- /** Whether running in popover window context (hides mobile-specific UI). */
23
+ /** Determines if running in popover window context (hides mobile-specific UI). */
15
24
  isPopover?: boolean;
16
25
  };
17
26
 
18
27
  export const SimpleLayoutPlugin = Plugin.define<SimpleLayoutPluginOptions>(meta).pipe(
19
- AppPlugin.addOperationResolverModule({ activate: OperationResolver }),
28
+ AppPlugin.addAppGraphModule({ activate: AppGraphBuilder }),
29
+ AppPlugin.addOperationHandlerModule({ activate: OperationHandler }),
20
30
  AppPlugin.addTranslationsModule({ translations }),
21
31
  Plugin.addModule(({ isPopover = false }) => ({
22
32
  id: Capability.getModuleTag(State),
23
33
  activatesOn: ActivationEvents.Startup,
24
- activatesAfter: [SimpleLayoutEvents.StateReady, AppActivationEvents.LayoutReady],
34
+ firesAfterActivation: [SimpleLayoutEvents.StateReady, AppActivationEvents.LayoutReady],
25
35
  activate: () => State({ initialState: { isPopover } }),
26
36
  })),
27
37
  Plugin.addModule(({ isPopover = false }) => ({
@@ -0,0 +1,21 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capability } from '@dxos/app-framework';
8
+ import { AppCapabilities, AppNode } from '@dxos/app-toolkit';
9
+ import { GraphBuilder, NodeMatcher } from '@dxos/plugin-graph';
10
+
11
+ export default Capability.makeModule(
12
+ Effect.fnUntraced(function* () {
13
+ const extensions = yield* GraphBuilder.createExtension({
14
+ id: 'org.dxos.plugin.simple-layout.not-found',
15
+ match: NodeMatcher.whenRoot,
16
+ connector: () => Effect.succeed([AppNode.makeNotFound()]),
17
+ });
18
+
19
+ return Capability.contributes(AppCapabilities.AppGraphBuilder, extensions);
20
+ }),
21
+ );
@@ -2,9 +2,16 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export * from './operation-resolver';
6
- export * from './react-root';
7
- export * from './react-surface';
8
- export * from './spotlight-dismiss';
9
- export * from './state';
10
- export * from './url-handler';
5
+ import { Capability } from '@dxos/app-framework';
6
+ import { OperationHandlerSet } from '@dxos/operation';
7
+
8
+ export const AppGraphBuilder = Capability.lazy('AppGraphBuilder', () => import('./app-graph-builder'));
9
+ export const OperationHandler = Capability.lazy<OperationHandlerSet.OperationHandlerSet>(
10
+ 'OperationHandler',
11
+ () => import('./operation-handler'),
12
+ );
13
+ export const ReactRoot = Capability.lazy('ReactRoot', () => import('./react-root'));
14
+ export const ReactSurface = Capability.lazy('ReactSurface', () => import('./react-surface'));
15
+ export const SpotlightDismiss = Capability.lazy('SpotlightDismiss', () => import('./spotlight-dismiss'));
16
+ export const State = Capability.lazy('State', () => import('./state'));
17
+ export const UrlHandler = Capability.lazy('UrlHandler', () => import('./url-handler'));
@@ -0,0 +1,14 @@
1
+ // Copyright 2025 DXOS.org
2
+
3
+ import * as Effect from 'effect/Effect';
4
+
5
+ import { Capabilities, Capability } from '@dxos/app-framework';
6
+ import type { OperationHandlerSet } from '@dxos/operation';
7
+
8
+ import { SimpleLayoutOperationHandlerSet } from '#operations';
9
+
10
+ export default Capability.makeModule<OperationHandlerSet.OperationHandlerSet>(
11
+ Effect.fnUntraced(function* () {
12
+ return Capability.contributes(Capabilities.OperationHandler, SimpleLayoutOperationHandlerSet);
13
+ }),
14
+ );
@@ -7,8 +7,8 @@ import React from 'react';
7
7
 
8
8
  import { Capabilities, Capability } from '@dxos/app-framework';
9
9
 
10
- import { SimpleLayout } from '../../components';
11
- import { meta } from '../../meta';
10
+ import { SimpleLayout } from '#components';
11
+ import { meta } from '#meta';
12
12
 
13
13
  export default Capability.makeModule(() =>
14
14
  Effect.succeed(
@@ -7,10 +7,11 @@ import React from 'react';
7
7
 
8
8
  import { Capabilities, Capability } from '@dxos/app-framework';
9
9
  import { Surface } from '@dxos/app-framework/ui';
10
+ import { NOT_FOUND_PATH } from '@dxos/app-toolkit';
11
+ import { NotFoundArticle } from '@dxos/app-toolkit/ui';
10
12
  import { Node } from '@dxos/plugin-graph';
11
13
 
12
- import { Home, NavBranch } from '../../components';
13
- import { meta } from '../../meta';
14
+ import { Home, NavBranch } from '#components';
14
15
 
15
16
  type SurfaceData = {
16
17
  attendableId: string;
@@ -23,13 +24,19 @@ export default Capability.makeModule(() =>
23
24
  Effect.succeed(
24
25
  Capability.contributes(Capabilities.ReactSurface, [
25
26
  Surface.create({
26
- id: `${meta.id}.home`,
27
+ id: 'home',
27
28
  role: 'article',
28
29
  filter: (data): data is SurfaceData => data.attendableId === Node.RootId,
29
30
  component: () => <Home />,
30
31
  }),
31
32
  Surface.create({
32
- id: `${meta.id}.nav-branch`,
33
+ id: 'not-found',
34
+ role: 'article',
35
+ filter: (data): data is SurfaceData => data.attendableId === NOT_FOUND_PATH,
36
+ component: () => <NotFoundArticle />,
37
+ }),
38
+ Surface.create({
39
+ id: 'nav-branch',
33
40
  role: 'article',
34
41
  position: 'fallback',
35
42
  filter: (data): data is SurfaceData => {
@@ -9,8 +9,8 @@ import { Capability } from '@dxos/app-framework';
9
9
  import { AppCapabilities } from '@dxos/app-toolkit';
10
10
  import { Node } from '@dxos/plugin-graph';
11
11
 
12
- import { type SimpleLayoutState } from '../../types';
13
- import { SimpleLayoutState as SimpleLayoutStateCapability } from '../../types';
12
+ import { type SimpleLayoutState } from '#types';
13
+ import { SimpleLayoutState as SimpleLayoutStateCapability } from '#types';
14
14
 
15
15
  const defaultState: SimpleLayoutState = {
16
16
  dialogOpen: false,
@@ -0,0 +1,161 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capabilities, Capability } from '@dxos/app-framework';
8
+ import { AppCapabilities, LayoutOperation, fromUrlPath, getWorkspaceFromPath, toUrlPath } from '@dxos/app-toolkit';
9
+ import { runAndForwardErrors } from '@dxos/effect';
10
+ import { log } from '@dxos/log';
11
+ import { isTauri } from '@dxos/util';
12
+
13
+ import { type SimpleLayoutState, SimpleLayoutState as SimpleLayoutStateCapability } from '#types';
14
+
15
+ /**
16
+ * URL handler for simple layout that syncs browser URL with layout state.
17
+ * URL paths map directly to qualified graph IDs with the leading `root` segment stripped.
18
+ * Root is represented as `/`.
19
+ *
20
+ * On Tauri, also listens for deep links via the deep-link plugin.
21
+ */
22
+ export default Capability.makeModule(
23
+ Effect.fnUntraced(function* () {
24
+ const { invokePromise } = yield* Capability.get(Capabilities.OperationInvoker);
25
+ const capabilities = yield* Capability.Service;
26
+
27
+ /** Dispatch all NavigationHandler contributions with a given URL. */
28
+ const dispatchNavigationHandlers = (url: URL) =>
29
+ Effect.gen(function* () {
30
+ const handlers = yield* Capability.getAll(AppCapabilities.NavigationHandler);
31
+ yield* Effect.all(
32
+ handlers.map((handler) => handler(url)),
33
+ { concurrency: 'unbounded' },
34
+ );
35
+ }).pipe(Effect.provideService(Capability.Service, capabilities), runAndForwardErrors);
36
+
37
+ /**
38
+ * Handle navigation from a URL.
39
+ * Dispatches to NavigationHandler contributions, then handles pathname routing.
40
+ */
41
+ const handlePathNavigation = (url?: URL) => {
42
+ const resolvedUrl = url ?? new URL(window.location.href);
43
+ void dispatchNavigationHandlers(resolvedUrl);
44
+
45
+ let pathname = resolvedUrl.pathname;
46
+ if (isFilePath(pathname)) {
47
+ log.info('[UrlHandler] Skipping file path (not a graph node)', { pathname });
48
+ pathname = '/';
49
+ }
50
+
51
+ const qualifiedId = fromUrlPath(pathname);
52
+ const workspace = getWorkspaceFromPath(qualifiedId);
53
+
54
+ void invokePromise(LayoutOperation.SwitchWorkspace, { subject: workspace });
55
+
56
+ const activeId = qualifiedId !== workspace ? qualifiedId : undefined;
57
+ if (activeId) {
58
+ void invokePromise(LayoutOperation.Open, { subject: [activeId] });
59
+ }
60
+ };
61
+
62
+ const onPopState = () => {
63
+ handlePathNavigation();
64
+ };
65
+
66
+ // Initial navigation.
67
+ yield* Effect.sync(() => handlePathNavigation());
68
+ window.addEventListener('popstate', onPopState);
69
+
70
+ // Tauri deep link support.
71
+ let unlistenDeepLink: (() => void) | undefined;
72
+ if (isTauri()) {
73
+ yield* Effect.tryPromise({
74
+ try: async () => {
75
+ const { getCurrent, onOpenUrl } = await import('@tauri-apps/plugin-deep-link');
76
+
77
+ const launchUrls = await getCurrent();
78
+ if (launchUrls && launchUrls.length > 0) {
79
+ log.info('[UrlHandler] App launched with deep links', { urls: launchUrls });
80
+ for (const urlString of launchUrls) {
81
+ handleDeepLink(urlString, handlePathNavigation);
82
+ }
83
+ }
84
+
85
+ unlistenDeepLink = await onOpenUrl((urls) => {
86
+ log.info('[UrlHandler] Deep links received', { urls });
87
+ for (const urlString of urls) {
88
+ handleDeepLink(urlString, handlePathNavigation);
89
+ }
90
+ });
91
+ },
92
+ catch: (error) => {
93
+ log.warn('[UrlHandler] Failed to initialize deep link listener', { error });
94
+ return error;
95
+ },
96
+ }).pipe(Effect.catchAll(() => Effect.void));
97
+ }
98
+
99
+ // Sync URL with layout state changes.
100
+ let lastWorkspace: string | undefined;
101
+ let lastActive: string | undefined;
102
+ const unsubscribe = yield* Capabilities.subscribeAtom(SimpleLayoutStateCapability, (state: SimpleLayoutState) => {
103
+ const { workspace, active } = state;
104
+
105
+ if (workspace !== lastWorkspace || active !== lastActive) {
106
+ lastWorkspace = workspace;
107
+ lastActive = active;
108
+
109
+ const path = active ? toUrlPath(active) : toUrlPath(workspace);
110
+ if (window.location.pathname !== path) {
111
+ history.pushState(null, '', `${path}${window.location.search}`);
112
+ }
113
+ }
114
+ });
115
+
116
+ return Capability.contributes(Capabilities.Null, null, () =>
117
+ Effect.sync(() => {
118
+ window.removeEventListener('popstate', onPopState);
119
+ unsubscribe();
120
+ unlistenDeepLink?.();
121
+ }),
122
+ );
123
+ }),
124
+ );
125
+
126
+ /** Check if a path is a redirect path handled elsewhere (e.g., OAuth). */
127
+ const isRedirectPath = (pathname: string): boolean => pathname.startsWith('/redirect/');
128
+
129
+ /** Paths with file extensions are not graph node paths. */
130
+ const isFilePath = (pathname: string): boolean => /\.[a-z]+$/i.test(pathname);
131
+
132
+ /** Handle a deep link URL string. Merges query params into window.location and navigates. */
133
+ const handleDeepLink = (urlString: string, navigate: (url?: URL) => void): void => {
134
+ log.info('[UrlHandler] Deep link received', { url: urlString });
135
+ try {
136
+ const deepLinkUrl = new URL(urlString);
137
+
138
+ // For custom schemes (e.g., composer://a/b/c), new URL() treats the first segment as the
139
+ // hostname. Reconstruct the full path from hostname + pathname.
140
+ const fullPath =
141
+ deepLinkUrl.protocol !== 'https:' && deepLinkUrl.protocol !== 'http:' && deepLinkUrl.hostname
142
+ ? '/' + deepLinkUrl.hostname + deepLinkUrl.pathname
143
+ : deepLinkUrl.pathname;
144
+
145
+ if (isRedirectPath(fullPath)) {
146
+ return;
147
+ }
148
+
149
+ // Merge deep link query params into the current window URL so handlers can read them.
150
+ const current = new URL(window.location.href);
151
+ if (deepLinkUrl.search) {
152
+ deepLinkUrl.searchParams.forEach((value, key) => current.searchParams.set(key, value));
153
+ }
154
+ current.pathname = fullPath;
155
+ history.replaceState(null, '', current.pathname + current.search);
156
+
157
+ navigate(current);
158
+ } catch (error) {
159
+ log.warn('[UrlHandler] Failed to parse deep link URL', { urlString, error });
160
+ }
161
+ };
@@ -0,0 +1,96 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { createContext } from '@radix-ui/react-context';
6
+ import React, { type PropsWithChildren, useCallback, useRef } from 'react';
7
+
8
+ const DEBUG_OVERLAY_NAME = 'DebugOverlay';
9
+
10
+ //
11
+ // Context
12
+ //
13
+
14
+ type DebugOverlayContextValue = {
15
+ /** Log a timestamped message to the on-screen debug overlay. */
16
+ dbg: (msg: string) => void;
17
+ };
18
+
19
+ // Default to a no-op so hooks can call useDebugLog() safely outside of a provider.
20
+ const [DebugOverlayProvider, useDebugLog] = createContext<DebugOverlayContextValue>(DEBUG_OVERLAY_NAME, {
21
+ dbg: () => {},
22
+ });
23
+
24
+ //
25
+ // Root
26
+ //
27
+
28
+ type DebugOverlayRootProps = PropsWithChildren<{
29
+ /**
30
+ * When true (default), renders the on-screen log panel.
31
+ * Set to false to suppress the overlay while keeping the context available.
32
+ */
33
+ enabled?: boolean;
34
+ maxLines?: number;
35
+ }>;
36
+
37
+ /**
38
+ * Establishes a debug overlay context.
39
+ *
40
+ * When enabled, renders an on-screen monospaced log panel anchored just above
41
+ * the keyboard (via --kb-height CSS variable). Descendants can call
42
+ * useDebugLog() to obtain the dbg() function for logging.
43
+ *
44
+ * Intended for transient mobile debugging in the iOS Simulator where DevTools
45
+ * console output may not be accessible.
46
+ */
47
+ const DebugOverlayRoot = ({ children, enabled = true, maxLines = 10 }: DebugOverlayRootProps) => {
48
+ const overlayRef = useRef<HTMLDivElement>(null);
49
+
50
+ const dbg = useCallback((msg: string) => {
51
+ if (!overlayRef.current) {
52
+ return;
53
+ }
54
+ const line = document.createElement('pre');
55
+ line.textContent = `${(performance.now() / 1000).toFixed(2).padStart(8, ' ')} ${msg}`;
56
+ overlayRef.current.prepend(line);
57
+ while (overlayRef.current.children.length > maxLines) {
58
+ overlayRef.current.lastChild?.remove();
59
+ }
60
+ }, []);
61
+
62
+ return (
63
+ <DebugOverlayProvider dbg={dbg}>
64
+ {children}
65
+ {enabled && (
66
+ <div
67
+ ref={overlayRef}
68
+ style={{
69
+ position: 'fixed',
70
+ bottom: 'calc(var(--kb-height, 0px) + 8px)',
71
+ left: 8,
72
+ right: 8,
73
+ background: 'rgba(0,0,0,0.8)',
74
+ color: '#0f0',
75
+ fontSize: 10,
76
+ fontFamily: 'monospace',
77
+ padding: 6,
78
+ borderRadius: 4,
79
+ zIndex: 9999,
80
+ pointerEvents: 'none',
81
+ }}
82
+ />
83
+ )}
84
+ </DebugOverlayProvider>
85
+ );
86
+ };
87
+
88
+ //
89
+ // Exports
90
+ //
91
+
92
+ export const DebugOverlay = {
93
+ Root: DebugOverlayRoot,
94
+ };
95
+
96
+ export { useDebugLog };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export { DebugOverlay, useDebugLog } from './DebugOverlay';
@@ -5,10 +5,11 @@
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 { AlertDialog, Dialog as NaturalDialog } from '@dxos/react-ui';
9
10
  import { ErrorFallback } from '@dxos/react-ui';
10
11
 
11
- import { useSimpleLayoutState } from '../../hooks';
12
+ import { useSimpleLayoutState } from '#hooks';
12
13
 
13
14
  export const Dialog = () => {
14
15
  const { state, updateState } = useSimpleLayoutState();
@@ -23,14 +24,24 @@ export const Dialog = () => {
23
24
  onOpenChange={(nextOpen) => updateState((state) => ({ ...state, dialogOpen: nextOpen }))}
24
25
  >
25
26
  {state.dialogBlockAlign === 'end' ? (
26
- <Surface.Surface role='dialog' data={state.dialogContent} limit={1} fallback={ErrorFallback} />
27
+ <Surface.Surface
28
+ type={AppSurface.Dialog}
29
+ data={state.dialogContent ?? undefined}
30
+ limit={1}
31
+ fallback={ErrorFallback}
32
+ />
27
33
  ) : (
28
34
  <DialogOverlay
29
35
  blockAlign={state.dialogBlockAlign}
30
36
  classNames={state.dialogOverlayClasses}
31
37
  style={state.dialogOverlayStyle}
32
38
  >
33
- <Surface.Surface role='dialog' data={state.dialogContent} limit={1} fallback={ErrorFallback} />
39
+ <Surface.Surface
40
+ type={AppSurface.Dialog}
41
+ data={state.dialogContent ?? undefined}
42
+ limit={1}
43
+ fallback={ErrorFallback}
44
+ />
34
45
  </DialogOverlay>
35
46
  )}
36
47
  </DialogRoot>
@@ -8,14 +8,15 @@ import { useOperationInvoker } from '@dxos/app-framework/ui';
8
8
  import { LayoutOperation } from '@dxos/app-toolkit';
9
9
  import { useAppGraph } from '@dxos/app-toolkit/ui';
10
10
  import { Node, useConnections } from '@dxos/plugin-graph';
11
- import { Avatar, Icon, Panel, ScrollArea, Toolbar, toLocalizedString, useTranslation } from '@dxos/react-ui';
11
+ import { Avatar, Icon, ScrollArea, toLocalizedString, useTranslation } from '@dxos/react-ui';
12
12
  import { Card } from '@dxos/react-ui';
13
13
  import { Mosaic, type MosaicStackTileComponent } from '@dxos/react-ui-mosaic';
14
- import { SearchList, useSearchListItem, useSearchListResults } from '@dxos/react-ui-searchlist';
14
+ import { SearchPanel, useSearchListItem, useSearchListResults } from '@dxos/react-ui-search';
15
15
  import { mx } from '@dxos/ui-theme';
16
- import { byPosition } from '@dxos/util';
16
+ import { byPosition, getHostPlatform, isTauri } from '@dxos/util';
17
+
18
+ import { meta } from '#meta';
17
19
 
18
- import { meta } from '../../meta';
19
20
  import { useExpandPath } from '../hooks';
20
21
 
21
22
  export type HomeProps = {};
@@ -40,27 +41,24 @@ export const Home = (_: HomeProps) => {
40
41
  extract: (node) => toLocalizedString(node.properties.label, t),
41
42
  });
42
43
 
44
+ const autoFocus = !isTauri() || getHostPlatform() !== 'ios';
45
+
43
46
  return (
44
- <SearchList.Root onSearch={handleSearch}>
45
- <Panel.Root>
46
- <Panel.Toolbar asChild>
47
- <Toolbar.Root>
48
- <SearchList.Input placeholder={t('search placeholder')} autoFocus />
49
- </Toolbar.Root>
50
- </Panel.Toolbar>
51
- <Panel.Content asChild>
52
- <SearchList.Content>
53
- <Mosaic.Container asChild>
54
- <ScrollArea.Root orientation='vertical'>
55
- <ScrollArea.Viewport classNames='p-2'>
56
- <Mosaic.Stack items={results} getId={(node) => node.id} Tile={WorkspaceTile} />
57
- </ScrollArea.Viewport>
58
- </ScrollArea.Root>
59
- </Mosaic.Container>
60
- </SearchList.Content>
61
- </Panel.Content>
62
- </Panel.Root>
63
- </SearchList.Root>
47
+ <SearchPanel onSearch={handleSearch}>
48
+ <Mosaic.Container asChild>
49
+ <ScrollArea.Root centered padding thin>
50
+ <ScrollArea.Viewport>
51
+ <Mosaic.Stack
52
+ classNames='gap-1'
53
+ draggable={false}
54
+ items={results}
55
+ getId={(item) => item.id}
56
+ Tile={WorkspaceTile}
57
+ />
58
+ </ScrollArea.Viewport>
59
+ </ScrollArea.Root>
60
+ </Mosaic.Container>
61
+ </SearchPanel>
64
62
  );
65
63
  };
66
64
 
@@ -106,17 +104,17 @@ const WorkspaceTile: MosaicStackTileComponent<Node.Node> = (props) => {
106
104
  onClick={handleSelect}
107
105
  ref={cardRef}
108
106
  >
109
- <Card.Toolbar density='coarse'>
107
+ <Card.Toolbar density='fine'>
110
108
  <Avatar.Root>
111
109
  <Avatar.Content
112
110
  icon={data.properties.icon}
113
111
  hue={data.properties.hue}
114
112
  hueVariant='transparent'
115
113
  variant='square'
116
- size={12}
114
+ size={8}
117
115
  fallback={name}
118
116
  />
119
- <Avatar.Label>{name}</Avatar.Label>
117
+ <Avatar.Label classNames='cursor-pointer'>{name}</Avatar.Label>
120
118
  <Icon icon='ph--caret-right--regular' />
121
119
  </Avatar.Root>
122
120
  </Card.Toolbar>
@@ -133,6 +131,8 @@ const filterItems = (node: Node.Node, disposition: string) => {
133
131
  const useItemsByDisposition = (disposition: string, sort = false) => {
134
132
  const { graph } = useAppGraph();
135
133
  const connections = useConnections(graph, Node.RootId, 'child');
136
- const filtered = connections.filter((node) => filterItems(node, disposition));
137
- return sort ? filtered.toSorted((a, b) => byPosition(a.properties, b.properties)) : filtered;
134
+ return useMemo(() => {
135
+ const filtered = connections.filter((node) => filterItems(node, disposition));
136
+ return sort ? filtered.toSorted((a, b) => byPosition(a.properties, b.properties)) : filtered;
137
+ }, [connections, disposition, sort]);
138
138
  };