@dxos/plugin-space 0.7.4 → 0.7.5-feature-compute.4d9d99a

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 (255) hide show
  1. package/dist/lib/browser/app-graph-builder-5D2QB43K.mjs +365 -0
  2. package/dist/lib/browser/app-graph-builder-5D2QB43K.mjs.map +7 -0
  3. package/dist/lib/browser/app-graph-serializer-VNWPLPDF.mjs +80 -0
  4. package/dist/lib/browser/app-graph-serializer-VNWPLPDF.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-5TBRONF6.mjs +133 -0
  6. package/dist/lib/browser/chunk-5TBRONF6.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-6SWQRWOD.mjs +1672 -0
  8. package/dist/lib/browser/chunk-6SWQRWOD.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-HCXWKGTE.mjs +316 -0
  10. package/dist/lib/browser/chunk-HCXWKGTE.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-SOXNANA6.mjs +12 -0
  12. package/dist/lib/browser/chunk-SOXNANA6.mjs.map +7 -0
  13. package/dist/lib/browser/chunk-UH5P4UL3.mjs +21 -0
  14. package/dist/lib/browser/chunk-UH5P4UL3.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-ZBKFJNHH.mjs +523 -0
  16. package/dist/lib/browser/chunk-ZBKFJNHH.mjs.map +7 -0
  17. package/dist/lib/browser/identity-created-EC5FOCX2.mjs +28 -0
  18. package/dist/lib/browser/identity-created-EC5FOCX2.mjs.map +7 -0
  19. package/dist/lib/browser/index.mjs +192 -3521
  20. package/dist/lib/browser/index.mjs.map +4 -4
  21. package/dist/lib/browser/intent-resolver-VBL572N7.mjs +459 -0
  22. package/dist/lib/browser/intent-resolver-VBL572N7.mjs.map +7 -0
  23. package/dist/lib/browser/meta.json +1 -1
  24. package/dist/lib/browser/react-root-AZJFNTKK.mjs +28 -0
  25. package/dist/lib/browser/react-root-AZJFNTKK.mjs.map +7 -0
  26. package/dist/lib/browser/react-surface-E2VSYVNZ.mjs +238 -0
  27. package/dist/lib/browser/react-surface-E2VSYVNZ.mjs.map +7 -0
  28. package/dist/lib/browser/settings-ASFF5BZL.mjs +24 -0
  29. package/dist/lib/browser/settings-ASFF5BZL.mjs.map +7 -0
  30. package/dist/lib/browser/spaces-ready-4SFNS5JQ.mjs +200 -0
  31. package/dist/lib/browser/spaces-ready-4SFNS5JQ.mjs.map +7 -0
  32. package/dist/lib/browser/state-MS4KYJWI.mjs +47 -0
  33. package/dist/lib/browser/state-MS4KYJWI.mjs.map +7 -0
  34. package/dist/lib/browser/types/index.mjs +14 -5
  35. package/dist/lib/node/app-graph-builder-ZQ5S62YR.cjs +368 -0
  36. package/dist/lib/node/app-graph-builder-ZQ5S62YR.cjs.map +7 -0
  37. package/dist/lib/node/app-graph-serializer-72S7P33H.cjs +88 -0
  38. package/dist/lib/node/app-graph-serializer-72S7P33H.cjs.map +7 -0
  39. package/dist/lib/node/chunk-56NGXG2A.cjs +41 -0
  40. package/dist/lib/node/chunk-56NGXG2A.cjs.map +7 -0
  41. package/dist/lib/node/{meta.cjs → chunk-AO4EW2RX.cjs} +12 -13
  42. package/dist/lib/node/chunk-AO4EW2RX.cjs.map +7 -0
  43. package/dist/lib/node/chunk-BQRNTKSQ.cjs +150 -0
  44. package/dist/lib/node/chunk-BQRNTKSQ.cjs.map +7 -0
  45. package/dist/lib/node/chunk-DDZYVNVP.cjs +345 -0
  46. package/dist/lib/node/chunk-DDZYVNVP.cjs.map +7 -0
  47. package/dist/lib/node/chunk-M64YG2FY.cjs +1669 -0
  48. package/dist/lib/node/chunk-M64YG2FY.cjs.map +7 -0
  49. package/dist/lib/node/chunk-Z34MTEU7.cjs +551 -0
  50. package/dist/lib/node/chunk-Z34MTEU7.cjs.map +7 -0
  51. package/dist/lib/node/identity-created-IMDS4A6A.cjs +44 -0
  52. package/dist/lib/node/identity-created-IMDS4A6A.cjs.map +7 -0
  53. package/dist/lib/node/index.cjs +175 -3506
  54. package/dist/lib/node/index.cjs.map +4 -4
  55. package/dist/lib/node/intent-resolver-S4HZABYI.cjs +458 -0
  56. package/dist/lib/node/intent-resolver-S4HZABYI.cjs.map +7 -0
  57. package/dist/lib/node/meta.json +1 -1
  58. package/dist/lib/node/react-root-RB3OM3QG.cjs +50 -0
  59. package/dist/lib/node/react-root-RB3OM3QG.cjs.map +7 -0
  60. package/dist/lib/node/react-surface-TLKQEHHT.cjs +233 -0
  61. package/dist/lib/node/react-surface-TLKQEHHT.cjs.map +7 -0
  62. package/dist/lib/node/settings-QLCKAUHK.cjs +38 -0
  63. package/dist/lib/node/settings-QLCKAUHK.cjs.map +7 -0
  64. package/dist/lib/node/spaces-ready-RZTKEXOL.cjs +211 -0
  65. package/dist/lib/node/spaces-ready-RZTKEXOL.cjs.map +7 -0
  66. package/dist/lib/node/state-4UIOUKLJ.cjs +61 -0
  67. package/dist/lib/node/state-4UIOUKLJ.cjs.map +7 -0
  68. package/dist/lib/node/types/index.cjs +23 -14
  69. package/dist/lib/node/types/index.cjs.map +2 -2
  70. package/dist/lib/node-esm/app-graph-builder-CD6IYPSS.mjs +366 -0
  71. package/dist/lib/node-esm/app-graph-builder-CD6IYPSS.mjs.map +7 -0
  72. package/dist/lib/node-esm/app-graph-serializer-CFXS6ZE2.mjs +81 -0
  73. package/dist/lib/node-esm/app-graph-serializer-CFXS6ZE2.mjs.map +7 -0
  74. package/dist/lib/node-esm/chunk-375RB3CZ.mjs +22 -0
  75. package/dist/lib/node-esm/chunk-375RB3CZ.mjs.map +7 -0
  76. package/dist/lib/node-esm/chunk-7FUVU45N.mjs +14 -0
  77. package/dist/lib/node-esm/chunk-7FUVU45N.mjs.map +7 -0
  78. package/dist/lib/node-esm/chunk-CLGCKZ2D.mjs +317 -0
  79. package/dist/lib/node-esm/chunk-CLGCKZ2D.mjs.map +7 -0
  80. package/dist/lib/node-esm/chunk-CMKML5IN.mjs +1673 -0
  81. package/dist/lib/node-esm/chunk-CMKML5IN.mjs.map +7 -0
  82. package/dist/lib/node-esm/chunk-FUMGYUD3.mjs +524 -0
  83. package/dist/lib/node-esm/chunk-FUMGYUD3.mjs.map +7 -0
  84. package/dist/lib/node-esm/chunk-M4XTHK35.mjs +134 -0
  85. package/dist/lib/node-esm/chunk-M4XTHK35.mjs.map +7 -0
  86. package/dist/lib/node-esm/identity-created-SJYZZ7Q3.mjs +29 -0
  87. package/dist/lib/node-esm/identity-created-SJYZZ7Q3.mjs.map +7 -0
  88. package/dist/lib/node-esm/index.mjs +192 -3521
  89. package/dist/lib/node-esm/index.mjs.map +4 -4
  90. package/dist/lib/node-esm/intent-resolver-OIQH7HN7.mjs +460 -0
  91. package/dist/lib/node-esm/intent-resolver-OIQH7HN7.mjs.map +7 -0
  92. package/dist/lib/node-esm/meta.json +1 -1
  93. package/dist/lib/node-esm/react-root-WKJWCHXR.mjs +29 -0
  94. package/dist/lib/node-esm/react-root-WKJWCHXR.mjs.map +7 -0
  95. package/dist/lib/node-esm/react-surface-RVEHOSAD.mjs +239 -0
  96. package/dist/lib/node-esm/react-surface-RVEHOSAD.mjs.map +7 -0
  97. package/dist/lib/node-esm/settings-WLVEO4JM.mjs +25 -0
  98. package/dist/lib/node-esm/settings-WLVEO4JM.mjs.map +7 -0
  99. package/dist/lib/node-esm/spaces-ready-ITGYYT5A.mjs +201 -0
  100. package/dist/lib/node-esm/spaces-ready-ITGYYT5A.mjs.map +7 -0
  101. package/dist/lib/node-esm/state-BMISGQ2O.mjs +48 -0
  102. package/dist/lib/node-esm/state-BMISGQ2O.mjs.map +7 -0
  103. package/dist/lib/node-esm/types/index.mjs +14 -5
  104. package/dist/types/src/SpacePlugin.d.ts +1 -24
  105. package/dist/types/src/SpacePlugin.d.ts.map +1 -1
  106. package/dist/types/src/capabilities/app-graph-builder.d.ts +181 -0
  107. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  108. package/dist/types/src/capabilities/app-graph-serializer.d.ts +4 -0
  109. package/dist/types/src/capabilities/app-graph-serializer.d.ts.map +1 -0
  110. package/dist/types/src/capabilities/capabilities.d.ts +15 -0
  111. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -0
  112. package/dist/types/src/capabilities/identity-created.d.ts +4 -0
  113. package/dist/types/src/capabilities/identity-created.d.ts.map +1 -0
  114. package/dist/types/src/capabilities/index.d.ts +195 -0
  115. package/dist/types/src/capabilities/index.d.ts.map +1 -0
  116. package/dist/types/src/capabilities/intent-resolver.d.ts +8 -0
  117. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
  118. package/dist/types/src/capabilities/react-root.d.ts +7 -0
  119. package/dist/types/src/capabilities/react-root.d.ts.map +1 -0
  120. package/dist/types/src/capabilities/react-surface.d.ts +7 -0
  121. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  122. package/dist/types/src/capabilities/settings.d.ts +4 -0
  123. package/dist/types/src/capabilities/settings.d.ts.map +1 -0
  124. package/dist/types/src/capabilities/spaces-ready.d.ts +4 -0
  125. package/dist/types/src/capabilities/spaces-ready.d.ts.map +1 -0
  126. package/dist/types/src/capabilities/state.d.ts +5 -0
  127. package/dist/types/src/capabilities/state.d.ts.map +1 -0
  128. package/dist/types/src/components/AdvancedObjectSettings/AdvancedObjectSettings.d.ts +7 -0
  129. package/dist/types/src/components/AdvancedObjectSettings/AdvancedObjectSettings.d.ts.map +1 -0
  130. package/dist/types/src/components/AdvancedObjectSettings/ForeignKeys.d.ts +8 -0
  131. package/dist/types/src/components/AdvancedObjectSettings/ForeignKeys.d.ts.map +1 -0
  132. package/dist/types/src/components/AdvancedObjectSettings/index.d.ts +2 -0
  133. package/dist/types/src/components/AdvancedObjectSettings/index.d.ts.map +1 -0
  134. package/dist/types/src/components/AwaitingObject.d.ts.map +1 -1
  135. package/dist/types/src/components/BaseObjectSettings.d.ts +7 -0
  136. package/dist/types/src/components/BaseObjectSettings.d.ts.map +1 -0
  137. package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts +5 -4
  138. package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts.map +1 -1
  139. package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts +5 -6
  140. package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts.map +1 -1
  141. package/dist/types/src/components/CreateDialog/CreateSpaceDialog.d.ts +1 -0
  142. package/dist/types/src/components/CreateDialog/CreateSpaceDialog.d.ts.map +1 -1
  143. package/dist/types/src/components/JoinDialog.d.ts +1 -0
  144. package/dist/types/src/components/JoinDialog.d.ts.map +1 -1
  145. package/dist/types/src/components/PopoverRenameObject.d.ts +1 -0
  146. package/dist/types/src/components/PopoverRenameObject.d.ts.map +1 -1
  147. package/dist/types/src/components/PopoverRenameSpace.d.ts +1 -0
  148. package/dist/types/src/components/PopoverRenameSpace.d.ts.map +1 -1
  149. package/dist/types/src/components/ShareSpaceButton.d.ts.map +1 -1
  150. package/dist/types/src/components/SpacePluginSettings.d.ts.map +1 -1
  151. package/dist/types/src/components/SpacePresence.d.ts +9 -6
  152. package/dist/types/src/components/SpacePresence.d.ts.map +1 -1
  153. package/dist/types/src/components/SpacePresence.stories.d.ts +1 -1
  154. package/dist/types/src/components/SpacePresence.stories.d.ts.map +1 -1
  155. package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.d.ts +1 -0
  156. package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.d.ts.map +1 -1
  157. package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.stories.d.ts.map +1 -1
  158. package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.d.ts +4 -3
  159. package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.d.ts.map +1 -1
  160. package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.stories.d.ts.map +1 -1
  161. package/dist/types/src/components/SyncStatus/InlineSyncStatus.d.ts +3 -3
  162. package/dist/types/src/components/SyncStatus/InlineSyncStatus.d.ts.map +1 -1
  163. package/dist/types/src/components/SyncStatus/SyncStatusDetail.stories.d.ts +2 -2
  164. package/dist/types/src/components/SyncStatus/SyncStatusDetail.stories.d.ts.map +1 -1
  165. package/dist/types/src/components/index.d.ts +2 -1
  166. package/dist/types/src/components/index.d.ts.map +1 -1
  167. package/dist/types/src/events.d.ts +5 -0
  168. package/dist/types/src/events.d.ts.map +1 -0
  169. package/dist/types/src/hooks/index.d.ts +2 -0
  170. package/dist/types/src/hooks/index.d.ts.map +1 -0
  171. package/dist/types/src/hooks/usePath.d.ts +11 -0
  172. package/dist/types/src/hooks/usePath.d.ts.map +1 -0
  173. package/dist/types/src/index.d.ts +3 -5
  174. package/dist/types/src/index.d.ts.map +1 -1
  175. package/dist/types/src/meta.d.ts +1 -27
  176. package/dist/types/src/meta.d.ts.map +1 -1
  177. package/dist/types/src/translations.d.ts +18 -3
  178. package/dist/types/src/translations.d.ts.map +1 -1
  179. package/dist/types/src/types/collection.d.ts +8 -12
  180. package/dist/types/src/types/collection.d.ts.map +1 -1
  181. package/dist/types/src/types/thread.d.ts +180 -186
  182. package/dist/types/src/types/thread.d.ts.map +1 -1
  183. package/dist/types/src/types/types.d.ts +228 -16
  184. package/dist/types/src/types/types.d.ts.map +1 -1
  185. package/dist/types/src/util.d.ts +9 -8
  186. package/dist/types/src/util.d.ts.map +1 -1
  187. package/dist/types/tsconfig.tsbuildinfo +1 -0
  188. package/package.json +38 -46
  189. package/src/SpacePlugin.tsx +119 -1541
  190. package/src/capabilities/app-graph-builder.ts +392 -0
  191. package/src/capabilities/app-graph-serializer.ts +73 -0
  192. package/src/capabilities/capabilities.ts +23 -0
  193. package/src/capabilities/identity-created.ts +26 -0
  194. package/src/capabilities/index.ts +17 -0
  195. package/src/capabilities/intent-resolver.ts +420 -0
  196. package/src/capabilities/react-root.tsx +20 -0
  197. package/src/capabilities/react-surface.tsx +234 -0
  198. package/src/capabilities/settings.ts +17 -0
  199. package/src/capabilities/spaces-ready.ts +231 -0
  200. package/src/capabilities/state.ts +45 -0
  201. package/src/components/AdvancedObjectSettings/AdvancedObjectSettings.tsx +72 -0
  202. package/src/components/AdvancedObjectSettings/ForeignKeys.tsx +51 -0
  203. package/src/components/AdvancedObjectSettings/index.ts +5 -0
  204. package/src/components/AwaitingObject.tsx +15 -19
  205. package/src/components/{DefaultObjectSettings.tsx → BaseObjectSettings.tsx} +2 -2
  206. package/src/components/CreateDialog/CreateObjectDialog.tsx +36 -25
  207. package/src/components/CreateDialog/CreateObjectPanel.tsx +61 -24
  208. package/src/components/CreateDialog/CreateSpaceDialog.tsx +10 -14
  209. package/src/components/JoinDialog.tsx +18 -34
  210. package/src/components/PersistenceStatus.tsx +1 -1
  211. package/src/components/PopoverRenameObject.tsx +2 -0
  212. package/src/components/PopoverRenameSpace.tsx +2 -0
  213. package/src/components/ShareSpaceButton.tsx +5 -4
  214. package/src/components/SpacePluginSettings.tsx +2 -13
  215. package/src/components/SpacePresence.stories.tsx +25 -17
  216. package/src/components/SpacePresence.tsx +42 -21
  217. package/src/components/SpaceSettings/SpaceSettingsDialog.stories.tsx +2 -3
  218. package/src/components/SpaceSettings/SpaceSettingsDialog.tsx +3 -1
  219. package/src/components/SpaceSettings/SpaceSettingsPanel.stories.tsx +7 -5
  220. package/src/components/SpaceSettings/SpaceSettingsPanel.tsx +6 -5
  221. package/src/components/SyncStatus/InlineSyncStatus.tsx +37 -27
  222. package/src/components/SyncStatus/SyncStatusDetail.stories.tsx +55 -51
  223. package/src/components/index.ts +2 -1
  224. package/src/events.ts +12 -0
  225. package/src/hooks/index.ts +5 -0
  226. package/src/hooks/usePath.ts +44 -0
  227. package/src/index.ts +3 -7
  228. package/src/meta.ts +1 -29
  229. package/src/translations.ts +7 -2
  230. package/src/types/collection.ts +3 -3
  231. package/src/types/thread.ts +6 -6
  232. package/src/types/types.ts +177 -42
  233. package/src/util.tsx +77 -64
  234. package/dist/lib/browser/chunk-FTKV32QZ.mjs +0 -43
  235. package/dist/lib/browser/chunk-FTKV32QZ.mjs.map +0 -7
  236. package/dist/lib/browser/chunk-MWKXNS5S.mjs +0 -124
  237. package/dist/lib/browser/chunk-MWKXNS5S.mjs.map +0 -7
  238. package/dist/lib/browser/meta.mjs +0 -15
  239. package/dist/lib/browser/meta.mjs.map +0 -7
  240. package/dist/lib/node/chunk-6SNOZF7Y.cjs +0 -152
  241. package/dist/lib/node/chunk-6SNOZF7Y.cjs.map +0 -7
  242. package/dist/lib/node/chunk-QNVEU2UD.cjs +0 -69
  243. package/dist/lib/node/chunk-QNVEU2UD.cjs.map +0 -7
  244. package/dist/lib/node/meta.cjs.map +0 -7
  245. package/dist/lib/node-esm/chunk-OHEAWSCA.mjs +0 -126
  246. package/dist/lib/node-esm/chunk-OHEAWSCA.mjs.map +0 -7
  247. package/dist/lib/node-esm/chunk-UMV7XREB.mjs +0 -45
  248. package/dist/lib/node-esm/chunk-UMV7XREB.mjs.map +0 -7
  249. package/dist/lib/node-esm/meta.mjs +0 -16
  250. package/dist/lib/node-esm/meta.mjs.map +0 -7
  251. package/dist/types/src/components/DefaultObjectSettings.d.ts +0 -7
  252. package/dist/types/src/components/DefaultObjectSettings.d.ts.map +0 -1
  253. package/dist/types/src/components/SyncStatus/InlineSyncStatus.stories.d.ts +0 -6
  254. package/dist/types/src/components/SyncStatus/InlineSyncStatus.stories.d.ts.map +0 -1
  255. package/src/components/SyncStatus/InlineSyncStatus.stories.tsx +0 -57
@@ -0,0 +1,420 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import {
6
+ Capabilities,
7
+ contributes,
8
+ createIntent,
9
+ createResolver,
10
+ firstIdInPart,
11
+ LayoutAction,
12
+ NavigationAction,
13
+ openIds,
14
+ type PluginsContext,
15
+ } from '@dxos/app-framework';
16
+ import { type Expando, getTypename, type HasId } from '@dxos/echo-schema';
17
+ import { invariant } from '@dxos/invariant';
18
+ import { create, makeRef, type ReactiveObject } from '@dxos/live-object';
19
+ import { Migrations } from '@dxos/migrations';
20
+ import { ClientCapabilities } from '@dxos/plugin-client';
21
+ import { ObservabilityAction } from '@dxos/plugin-observability/types';
22
+ import { EdgeReplicationSetting } from '@dxos/protocols/proto/dxos/echo/metadata';
23
+ import { isSpace, getSpace, SpaceState, type Space, fullyQualifiedId, isEchoObject } from '@dxos/react-client/echo';
24
+
25
+ import { SpaceCapabilities } from './capabilities';
26
+ import {
27
+ CREATE_SPACE_DIALOG,
28
+ JOIN_DIALOG,
29
+ SPACE_SETTINGS_DIALOG,
30
+ type SpaceSettingsDialogProps,
31
+ type JoinDialogProps,
32
+ POPOVER_RENAME_SPACE,
33
+ CREATE_OBJECT_DIALOG,
34
+ type CreateObjectDialogProps,
35
+ POPOVER_RENAME_OBJECT,
36
+ } from '../components';
37
+ import { SPACE_PLUGIN } from '../meta';
38
+ import { CollectionAction, CollectionType, SpaceAction } from '../types';
39
+ import { cloneObject, COMPOSER_SPACE_LOCK, getNestedObjects } from '../util';
40
+
41
+ // TODO(wittjosiah): Remove.
42
+ const SPACE_MAX_OBJECTS = 500;
43
+
44
+ type IntentResolverOptions = {
45
+ createInvitationUrl: (invitationCode: string) => string;
46
+ context: PluginsContext;
47
+ };
48
+
49
+ export default ({ createInvitationUrl, context }: IntentResolverOptions) => {
50
+ const resolve = (typename: string) =>
51
+ context.requestCapabilities(Capabilities.Metadata).find(({ id }) => id === typename)?.metadata ?? {};
52
+
53
+ return contributes(Capabilities.IntentResolver, [
54
+ createResolver(SpaceAction.OpenCreateSpace, () => ({
55
+ intents: [
56
+ createIntent(LayoutAction.SetLayout, {
57
+ element: 'dialog',
58
+ component: CREATE_SPACE_DIALOG,
59
+ dialogBlockAlign: 'start',
60
+ }),
61
+ ],
62
+ })),
63
+ createResolver(SpaceAction.Create, async ({ name, edgeReplication }) => {
64
+ const client = context.requestCapability(ClientCapabilities.Client);
65
+ const space = await client.spaces.create({ name });
66
+ if (edgeReplication) {
67
+ await space.internal.setEdgeReplicationPreference(EdgeReplicationSetting.ENABLED);
68
+ }
69
+ await space.waitUntilReady();
70
+ const collection = create(CollectionType, { objects: [], views: {} });
71
+ space.properties[CollectionType.typename] = makeRef(collection);
72
+
73
+ if (Migrations.versionProperty) {
74
+ space.properties[Migrations.versionProperty] = Migrations.targetVersion;
75
+ }
76
+
77
+ return {
78
+ data: {
79
+ space,
80
+ id: space.id,
81
+ activeParts: { main: [space.id] },
82
+ },
83
+ intents: [
84
+ createIntent(ObservabilityAction.SendEvent, {
85
+ name: 'space.create',
86
+ properties: {
87
+ spaceId: space.id,
88
+ },
89
+ }),
90
+ ],
91
+ };
92
+ }),
93
+ createResolver(SpaceAction.Join, ({ invitationCode }) => ({
94
+ intents: [
95
+ createIntent(LayoutAction.SetLayout, {
96
+ element: 'dialog',
97
+ component: JOIN_DIALOG,
98
+ dialogBlockAlign: 'start',
99
+ subject: {
100
+ initialInvitationCode: invitationCode,
101
+ } satisfies Partial<JoinDialogProps>,
102
+ }),
103
+ ],
104
+ })),
105
+ createResolver(
106
+ SpaceAction.Share,
107
+ ({ space }) => {
108
+ const location = context.requestCapability(Capabilities.Location);
109
+ const layout = context.requestCapability(Capabilities.Layout);
110
+ const current = firstIdInPart(location.active, layout.layoutMode === 'solo' ? 'solo' : 'main');
111
+ const target = current?.startsWith(space.id) ? current : undefined;
112
+
113
+ return {
114
+ intents: [
115
+ createIntent(LayoutAction.SetLayout, {
116
+ element: 'dialog',
117
+ component: SPACE_SETTINGS_DIALOG,
118
+ dialogBlockAlign: 'start',
119
+ subject: {
120
+ space,
121
+ target,
122
+ initialTab: 'members',
123
+ createInvitationUrl,
124
+ } satisfies Partial<SpaceSettingsDialogProps>,
125
+ }),
126
+ createIntent(ObservabilityAction.SendEvent, {
127
+ name: 'space.share',
128
+ properties: {
129
+ space: space.id,
130
+ },
131
+ }),
132
+ ],
133
+ };
134
+ },
135
+ { filter: (data): data is { space: Space } => !data.space.properties[COMPOSER_SPACE_LOCK] },
136
+ ),
137
+ createResolver(SpaceAction.Lock, ({ space }) => {
138
+ space.properties[COMPOSER_SPACE_LOCK] = true;
139
+ return {
140
+ intents: [
141
+ createIntent(ObservabilityAction.SendEvent, {
142
+ name: 'space.lock',
143
+ properties: {
144
+ spaceId: space.id,
145
+ },
146
+ }),
147
+ ],
148
+ };
149
+ }),
150
+ createResolver(SpaceAction.Unlock, ({ space }) => {
151
+ space.properties[COMPOSER_SPACE_LOCK] = false;
152
+ return {
153
+ intents: [
154
+ createIntent(ObservabilityAction.SendEvent, {
155
+ name: 'space.unlock',
156
+ properties: {
157
+ spaceId: space.id,
158
+ },
159
+ }),
160
+ ],
161
+ };
162
+ }),
163
+ createResolver(SpaceAction.Rename, ({ caller, space }) => {
164
+ return {
165
+ intents: [
166
+ createIntent(LayoutAction.SetLayout, {
167
+ element: 'popover',
168
+ anchorId: `dxos.org/ui/${caller}/${space.id}`,
169
+ component: POPOVER_RENAME_SPACE,
170
+ subject: space,
171
+ }),
172
+ ],
173
+ };
174
+ }),
175
+ createResolver(SpaceAction.OpenSettings, ({ space }) => {
176
+ return {
177
+ intents: [
178
+ createIntent(LayoutAction.SetLayout, {
179
+ element: 'dialog',
180
+ component: SPACE_SETTINGS_DIALOG,
181
+ dialogBlockAlign: 'start',
182
+ subject: {
183
+ space,
184
+ initialTab: 'settings',
185
+ createInvitationUrl,
186
+ } satisfies Partial<SpaceSettingsDialogProps>,
187
+ }),
188
+ ],
189
+ };
190
+ }),
191
+ createResolver(SpaceAction.Open, async ({ space }) => {
192
+ await space.open();
193
+ }),
194
+ createResolver(SpaceAction.Close, async ({ space }) => {
195
+ await space.close();
196
+ }),
197
+ createResolver(SpaceAction.Migrate, async ({ space, version }) => {
198
+ const state = context.requestCapability(SpaceCapabilities.MutableState);
199
+
200
+ if (space.state.get() === SpaceState.SPACE_REQUIRES_MIGRATION) {
201
+ state.sdkMigrationRunning[space.id] = true;
202
+ await space.internal.migrate();
203
+ state.sdkMigrationRunning[space.id] = false;
204
+ }
205
+ const result = await Migrations.migrate(space, version);
206
+ return {
207
+ data: result,
208
+ intents: [
209
+ createIntent(ObservabilityAction.SendEvent, {
210
+ name: 'space.migrate',
211
+ properties: {
212
+ spaceId: space.id,
213
+ version,
214
+ },
215
+ }),
216
+ ],
217
+ };
218
+ }),
219
+ createResolver(SpaceAction.OpenCreateObject, ({ target, navigable = true }) => {
220
+ const state = context.requestCapability(SpaceCapabilities.State);
221
+
222
+ return {
223
+ intents: [
224
+ createIntent(LayoutAction.SetLayout, {
225
+ element: 'dialog',
226
+ component: CREATE_OBJECT_DIALOG,
227
+ dialogBlockAlign: 'start',
228
+ subject: {
229
+ target,
230
+ shouldNavigate: navigable
231
+ ? (object: ReactiveObject<any>) => !(object instanceof CollectionType) || state.navigableCollections
232
+ : () => false,
233
+ } satisfies Partial<CreateObjectDialogProps>,
234
+ }),
235
+ ],
236
+ };
237
+ }),
238
+ createResolver(SpaceAction.AddObject, async ({ target, object }) => {
239
+ const space = isSpace(target) ? target : getSpace(target);
240
+ invariant(space, 'Space not found.');
241
+
242
+ if (space.db.coreDatabase.getAllObjectIds().length >= SPACE_MAX_OBJECTS) {
243
+ return {
244
+ error: new Error('Space limit reached.'),
245
+ intents: [
246
+ createIntent(LayoutAction.SetLayout, {
247
+ element: 'toast',
248
+ subject: {
249
+ id: `${SPACE_PLUGIN}/space-limit`,
250
+ title: ['space limit label', { ns: SPACE_PLUGIN }],
251
+ description: ['space limit description', { ns: SPACE_PLUGIN }],
252
+ duration: 5_000,
253
+ icon: 'ph--warning--regular',
254
+ actionLabel: ['remove deleted objects label', { ns: SPACE_PLUGIN }],
255
+ actionAlt: ['remove deleted objects alt', { ns: SPACE_PLUGIN }],
256
+ closeLabel: ['close label', { ns: 'os' }],
257
+ onAction: () => space.db.coreDatabase.unlinkDeletedObjects(),
258
+ },
259
+ }),
260
+ createIntent(ObservabilityAction.SendEvent, {
261
+ name: 'space.limit',
262
+ properties: {
263
+ spaceId: space.id,
264
+ },
265
+ }),
266
+ ],
267
+ };
268
+ }
269
+
270
+ if (target instanceof CollectionType) {
271
+ target.objects.push(makeRef(object as HasId));
272
+ } else if (isSpace(target)) {
273
+ const collection = space.properties[CollectionType.typename]?.target;
274
+ if (collection instanceof CollectionType) {
275
+ collection.objects.push(makeRef(object as HasId));
276
+ } else {
277
+ // TODO(wittjosiah): Can't add non-echo objects by including in a collection because of types.
278
+ const collection = create(CollectionType, { objects: [makeRef(object as HasId)], views: {} });
279
+ space.properties[CollectionType.typename] = makeRef(collection);
280
+ }
281
+ }
282
+
283
+ return {
284
+ data: {
285
+ id: fullyQualifiedId(object),
286
+ object: object as HasId,
287
+ activeParts: { main: [fullyQualifiedId(object)] },
288
+ },
289
+ intents: [
290
+ createIntent(ObservabilityAction.SendEvent, {
291
+ name: 'space.object.add',
292
+ properties: {
293
+ spaceId: space.id,
294
+ objectId: object.id,
295
+ typename: getTypename(object),
296
+ },
297
+ }),
298
+ ],
299
+ };
300
+ }),
301
+ createResolver(SpaceAction.RemoveObjects, async ({ objects, target, deletionData }, undo) => {
302
+ const location = context.requestCapability(Capabilities.Location);
303
+
304
+ // All objects must be a member of the same space.
305
+ const space = getSpace(objects[0]);
306
+ invariant(space && objects.every((obj) => isEchoObject(obj) && getSpace(obj) === space));
307
+ const openObjectIds = new Set<string>(openIds(location.active));
308
+
309
+ if (!undo) {
310
+ const parentCollection: CollectionType = target ?? space.properties[CollectionType.typename]?.target;
311
+ const nestedObjectsList = await Promise.all(objects.map((obj) => getNestedObjects(obj, resolve)));
312
+
313
+ const deletionData = {
314
+ objects,
315
+ parentCollection,
316
+ indices: objects.map((obj) =>
317
+ parentCollection instanceof CollectionType
318
+ ? parentCollection.objects.findIndex((object) => object.target === obj)
319
+ : -1,
320
+ ),
321
+ nestedObjectsList,
322
+ wasActive: objects
323
+ .flatMap((obj, i) => [obj, ...nestedObjectsList[i]])
324
+ .map((obj) => fullyQualifiedId(obj))
325
+ .filter((id) => openObjectIds.has(id)),
326
+ } satisfies SpaceAction.DeletionData;
327
+
328
+ if (deletionData.parentCollection instanceof CollectionType) {
329
+ [...deletionData.indices]
330
+ .sort((a, b) => b - a)
331
+ .forEach((index: number) => {
332
+ if (index !== -1) {
333
+ deletionData.parentCollection.objects.splice(index, 1);
334
+ }
335
+ });
336
+ }
337
+
338
+ deletionData.nestedObjectsList.flat().forEach((obj) => {
339
+ space.db.remove(obj);
340
+ });
341
+ objects.forEach((obj) => space.db.remove(obj));
342
+
343
+ const undoMessageKey = objects.some((obj) => obj instanceof CollectionType)
344
+ ? 'collection deleted label'
345
+ : objects.length > 1
346
+ ? 'objects deleted label'
347
+ : 'object deleted label';
348
+
349
+ return {
350
+ undoable: {
351
+ // TODO(ZaymonFC): Pluralize if more than one object.
352
+ message: [undoMessageKey, { ns: SPACE_PLUGIN }],
353
+ data: { deletionData },
354
+ },
355
+ intents:
356
+ deletionData.wasActive.length > 0
357
+ ? [createIntent(NavigationAction.Close, { activeParts: { main: deletionData.wasActive } })]
358
+ : undefined,
359
+ };
360
+ } else {
361
+ if (
362
+ deletionData?.objects?.length &&
363
+ deletionData.objects.every(isEchoObject) &&
364
+ deletionData.parentCollection instanceof CollectionType
365
+ ) {
366
+ // Restore the object to the space.
367
+ const restoredObjects = deletionData.objects.map((obj: Expando) => space.db.add(obj));
368
+
369
+ // Restore nested objects to the space.
370
+ deletionData.nestedObjectsList.flat().forEach((obj: Expando) => {
371
+ space.db.add(obj);
372
+ });
373
+
374
+ deletionData.indices.forEach((index: number, i: number) => {
375
+ if (index !== -1) {
376
+ deletionData.parentCollection.objects.splice(index, 0, makeRef(restoredObjects[i] as Expando));
377
+ }
378
+ });
379
+
380
+ return {
381
+ intents:
382
+ deletionData.wasActive.length > 0
383
+ ? [
384
+ createIntent(NavigationAction.Open, {
385
+ activeParts: { main: deletionData.wasActive as string[] },
386
+ }),
387
+ ]
388
+ : undefined,
389
+ };
390
+ }
391
+ }
392
+ }),
393
+ createResolver(SpaceAction.RenameObject, async ({ object, caller }) => ({
394
+ intents: [
395
+ createIntent(LayoutAction.SetLayout, {
396
+ element: 'popover',
397
+ anchorId: `dxos.org/ui/${caller}/${fullyQualifiedId(object)}`,
398
+ component: POPOVER_RENAME_OBJECT,
399
+ subject: object,
400
+ }),
401
+ ],
402
+ })),
403
+ createResolver(SpaceAction.DuplicateObject, async ({ object, target }) => {
404
+ const space = isSpace(target) ? target : getSpace(target);
405
+ invariant(space, 'Space not found.');
406
+
407
+ const newObject = await cloneObject(object, resolve, space);
408
+ return {
409
+ intents: [createIntent(SpaceAction.AddObject, { object: newObject, target })],
410
+ };
411
+ }),
412
+ createResolver(SpaceAction.WaitForObject, async ({ id }) => {
413
+ const state = context.requestCapability(SpaceCapabilities.MutableState);
414
+ state.awaiting = id;
415
+ }),
416
+ createResolver(CollectionAction.Create, async ({ name }) => ({
417
+ data: { object: create(CollectionType, { name, objects: [], views: {} }) },
418
+ })),
419
+ ]);
420
+ };
@@ -0,0 +1,20 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { Capabilities, contributes, useCapability } from '@dxos/app-framework';
8
+
9
+ import { SpaceCapabilities } from './capabilities';
10
+ import { AwaitingObject } from '../components';
11
+ import { SPACE_PLUGIN } from '../meta';
12
+
13
+ export default () =>
14
+ contributes(Capabilities.ReactRoot, {
15
+ id: SPACE_PLUGIN,
16
+ root: () => {
17
+ const state = useCapability(SpaceCapabilities.State);
18
+ return state.awaiting ? <AwaitingObject id={state.awaiting} /> : null;
19
+ },
20
+ });
@@ -0,0 +1,234 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback } from 'react';
6
+
7
+ import {
8
+ Capabilities,
9
+ contributes,
10
+ createSurface,
11
+ Surface,
12
+ useCapability,
13
+ useCapabilities,
14
+ usePluginManager,
15
+ } from '@dxos/app-framework';
16
+ import { ClientCapabilities } from '@dxos/plugin-client';
17
+ import {
18
+ getSpace,
19
+ isEchoObject,
20
+ isReactiveObject,
21
+ isSpace,
22
+ SpaceState,
23
+ type ReactiveEchoObject,
24
+ type Space,
25
+ } from '@dxos/react-client/echo';
26
+ import { type JoinPanelProps } from '@dxos/shell/react';
27
+
28
+ import { SpaceCapabilities } from './capabilities';
29
+ import {
30
+ AdvancedObjectSettings,
31
+ BaseObjectSettings,
32
+ CollectionMain,
33
+ CollectionSection,
34
+ CREATE_OBJECT_DIALOG,
35
+ CREATE_SPACE_DIALOG,
36
+ CreateObjectDialog,
37
+ CreateSpaceDialog,
38
+ InlineSyncStatus,
39
+ JOIN_DIALOG,
40
+ JoinDialog,
41
+ MenuFooter,
42
+ POPOVER_RENAME_OBJECT,
43
+ POPOVER_RENAME_SPACE,
44
+ PopoverRenameObject,
45
+ PopoverRenameSpace,
46
+ ShareSpaceButton,
47
+ SmallPresenceLive,
48
+ SPACE_SETTINGS_DIALOG,
49
+ SpacePluginSettings,
50
+ SpacePresence,
51
+ SpaceSettingsDialog,
52
+ SpaceSettingsPanel,
53
+ SyncStatus,
54
+ type CreateObjectDialogProps,
55
+ type SpaceSettingsDialogProps,
56
+ } from '../components';
57
+ import { SPACE_PLUGIN } from '../meta';
58
+ import { CollectionType, type SpaceSettingsProps } from '../types';
59
+ import { COMPOSER_SPACE_LOCK } from '../util';
60
+
61
+ type ReactSurfaceOptions = {
62
+ createInvitationUrl: (invitationCode: string) => string;
63
+ };
64
+
65
+ export default ({ createInvitationUrl }: ReactSurfaceOptions) =>
66
+ contributes(Capabilities.ReactSurface, [
67
+ createSurface({
68
+ id: `${SPACE_PLUGIN}/article`,
69
+ role: 'article',
70
+ filter: (data): data is { subject: Space } =>
71
+ // TODO(wittjosiah): Need to avoid shotgun parsing space state everywhere.
72
+ isSpace(data.subject) && data.subject.state.get() === SpaceState.SPACE_READY,
73
+ component: ({ data, role, ...rest }) => (
74
+ <Surface
75
+ data={{ id: data.subject.id, subject: data.subject.properties[CollectionType.typename]?.target }}
76
+ role={role}
77
+ {...rest}
78
+ />
79
+ ),
80
+ }),
81
+ createSurface({
82
+ id: `${SPACE_PLUGIN}/collection-fallback`,
83
+ role: 'article',
84
+ disposition: 'fallback',
85
+ filter: (data): data is { subject: CollectionType } => data.subject instanceof CollectionType,
86
+ component: ({ data }) => <CollectionMain collection={data.subject} />,
87
+ }),
88
+ createSurface({
89
+ id: `${SPACE_PLUGIN}/settings-panel`,
90
+ // TODO(burdon): Add role name syntax to minimal plugin docs.
91
+ role: 'complementary--settings',
92
+ filter: (data): data is { subject: Space } => isSpace(data.subject),
93
+ component: ({ data }) => <SpaceSettingsPanel space={data.subject} />,
94
+ }),
95
+ createSurface({
96
+ id: `${SPACE_PLUGIN}/object-settings-base-panel`,
97
+ role: 'complementary--settings',
98
+ disposition: 'hoist',
99
+ filter: (data): data is { subject: ReactiveEchoObject<any> } => isEchoObject(data.subject),
100
+ component: ({ data }) => <BaseObjectSettings object={data.subject} />,
101
+ }),
102
+ createSurface({
103
+ id: `${SPACE_PLUGIN}/object-settings-advanced-panel`,
104
+ role: 'complementary--settings',
105
+ disposition: 'fallback',
106
+ filter: (data): data is { subject: ReactiveEchoObject<any> } => isEchoObject(data.subject),
107
+ component: ({ data }) => <AdvancedObjectSettings object={data.subject} />,
108
+ }),
109
+ createSurface({
110
+ id: SPACE_SETTINGS_DIALOG,
111
+ role: 'dialog',
112
+ filter: (data): data is { subject: SpaceSettingsDialogProps } => data.component === SPACE_SETTINGS_DIALOG,
113
+ component: ({ data }) => <SpaceSettingsDialog {...data.subject} createInvitationUrl={createInvitationUrl} />,
114
+ }),
115
+ createSurface({
116
+ id: JOIN_DIALOG,
117
+ role: 'dialog',
118
+ filter: (data): data is { subject: JoinPanelProps } => data.component === JOIN_DIALOG,
119
+ component: ({ data }) => <JoinDialog {...data.subject} />,
120
+ }),
121
+ createSurface({
122
+ id: CREATE_SPACE_DIALOG,
123
+ role: 'dialog',
124
+ filter: (data): data is any => data.component === CREATE_SPACE_DIALOG,
125
+ component: () => <CreateSpaceDialog />,
126
+ }),
127
+ createSurface({
128
+ id: CREATE_OBJECT_DIALOG,
129
+ role: 'dialog',
130
+ filter: (data): data is { subject: Partial<CreateObjectDialogProps> } => data.component === CREATE_OBJECT_DIALOG,
131
+ component: ({ data }) => {
132
+ const schemas = useCapabilities(ClientCapabilities.Schema).flat();
133
+ const manager = usePluginManager();
134
+
135
+ const resolve = useCallback(
136
+ (typename: string) => {
137
+ return (
138
+ manager.context.requestCapabilities(Capabilities.Metadata).find(({ id }) => id === typename)?.metadata ??
139
+ {}
140
+ );
141
+ },
142
+ [manager],
143
+ );
144
+
145
+ return <CreateObjectDialog schemas={schemas} resolve={resolve} {...data.subject} />;
146
+ },
147
+ }),
148
+ createSurface({
149
+ id: POPOVER_RENAME_SPACE,
150
+ role: 'popover',
151
+ filter: (data): data is { subject: Space } => data.component === POPOVER_RENAME_SPACE && isSpace(data.subject),
152
+ component: ({ data }) => <PopoverRenameSpace space={data.subject} />,
153
+ }),
154
+ createSurface({
155
+ id: POPOVER_RENAME_OBJECT,
156
+ role: 'popover',
157
+ filter: (data): data is { subject: ReactiveEchoObject<any> } =>
158
+ data.component === POPOVER_RENAME_OBJECT && isReactiveObject(data.subject),
159
+ component: ({ data }) => <PopoverRenameObject object={data.subject} />,
160
+ }),
161
+ createSurface({
162
+ id: `${SPACE_PLUGIN}/navtree-presence`,
163
+ role: 'navtree-item-end',
164
+ filter: (data): data is { id: string; subject: ReactiveEchoObject<any>; open?: boolean } =>
165
+ typeof data.id === 'string' && isEchoObject(data.subject),
166
+ component: ({ data }) => {
167
+ // TODO(wittjosiah): Doesn't need to be mutable but readonly type messes with ComplexMap.
168
+ const state = useCapability(SpaceCapabilities.MutableState);
169
+ return <SmallPresenceLive id={data.id} open={data.open} viewers={state.viewersByObject[data.id]} />;
170
+ },
171
+ }),
172
+ createSurface({
173
+ // TODO(wittjosiah): Attention glyph for non-echo items should be handled elsewhere.
174
+ id: `${SPACE_PLUGIN}/navtree-presence-fallback`,
175
+ role: 'navtree-item-end',
176
+ disposition: 'fallback',
177
+ filter: (data): data is { id: string; open?: boolean } => typeof data.id === 'string',
178
+ component: ({ data }) => <SmallPresenceLive id={data.id} open={data.open} />,
179
+ }),
180
+ createSurface({
181
+ id: `${SPACE_PLUGIN}/navtree-sync-status`,
182
+ role: 'navtree-item-end',
183
+ filter: (data): data is { subject: Space; open?: boolean } => isSpace(data.subject),
184
+ component: ({ data }) => <InlineSyncStatus space={data.subject} open={data.open} />,
185
+ }),
186
+ createSurface({
187
+ id: `${SPACE_PLUGIN}/navbar-presence`,
188
+ role: 'navbar-end',
189
+ disposition: 'hoist',
190
+ filter: (data): data is { subject: Space | ReactiveEchoObject<any> } =>
191
+ isSpace(data.subject) || isEchoObject(data.subject),
192
+ component: ({ data }) => {
193
+ const space = isSpace(data.subject) ? data.subject : getSpace(data.subject);
194
+ const object = isSpace(data.subject)
195
+ ? data.subject.state.get() === SpaceState.SPACE_READY
196
+ ? (space?.properties[CollectionType.typename]?.target as CollectionType)
197
+ : undefined
198
+ : data.subject;
199
+
200
+ return space && object ? (
201
+ <>
202
+ <SpacePresence object={object} />
203
+ {space.properties[COMPOSER_SPACE_LOCK] ? null : <ShareSpaceButton space={space} />}
204
+ </>
205
+ ) : null;
206
+ },
207
+ }),
208
+ createSurface({
209
+ id: `${SPACE_PLUGIN}/collection-section`,
210
+ role: 'section',
211
+ filter: (data): data is { subject: CollectionType } => data.subject instanceof CollectionType,
212
+ component: ({ data }) => <CollectionSection collection={data.subject} />,
213
+ }),
214
+ createSurface({
215
+ id: `${SPACE_PLUGIN}/settings`,
216
+ role: 'settings',
217
+ filter: (data): data is any => data.subject === SPACE_PLUGIN,
218
+ component: () => {
219
+ const settings = useCapability(Capabilities.SettingsStore).getStore<SpaceSettingsProps>(SPACE_PLUGIN)!.value;
220
+ return <SpacePluginSettings settings={settings} />;
221
+ },
222
+ }),
223
+ createSurface({
224
+ id: `${SPACE_PLUGIN}/menu-footer`,
225
+ role: 'menu-footer',
226
+ filter: (data): data is { subject: ReactiveEchoObject<any> } => isEchoObject(data.subject),
227
+ component: ({ data }) => <MenuFooter object={data.subject} />,
228
+ }),
229
+ createSurface({
230
+ id: `${SPACE_PLUGIN}/status`,
231
+ role: 'status',
232
+ component: () => <SyncStatus />,
233
+ }),
234
+ ]);
@@ -0,0 +1,17 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Capabilities, contributes } from '@dxos/app-framework';
6
+ import { create } from '@dxos/live-object';
7
+
8
+ import { SPACE_PLUGIN } from '../meta';
9
+ import { type SpaceSettingsProps, SpaceSettingsSchema } from '../types';
10
+
11
+ export default () => {
12
+ const settings = create<SpaceSettingsProps>({
13
+ showHidden: false,
14
+ });
15
+
16
+ return contributes(Capabilities.Settings, { schema: SpaceSettingsSchema, prefix: SPACE_PLUGIN, value: settings });
17
+ };