@dxos/plugin-space 0.7.5-labs.ea4b4c2 → 0.7.5-labs.f400bbc

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 (223) hide show
  1. package/dist/lib/browser/{app-graph-builder-TTM2YZVS.mjs → app-graph-builder-MGK5HWPZ.mjs} +21 -100
  2. package/dist/lib/browser/app-graph-builder-MGK5HWPZ.mjs.map +7 -0
  3. package/dist/lib/browser/{app-graph-serializer-ZGM5NDXE.mjs → app-graph-serializer-FOWFLYGU.mjs} +4 -4
  4. package/dist/lib/browser/{chunk-S5IGZNXJ.mjs → chunk-23RVI5FZ.mjs} +16 -5
  5. package/dist/lib/browser/chunk-23RVI5FZ.mjs.map +7 -0
  6. package/dist/lib/browser/{chunk-RLZQJD47.mjs → chunk-NU7WDVGN.mjs} +2 -1
  7. package/dist/lib/browser/chunk-NU7WDVGN.mjs.map +7 -0
  8. package/dist/lib/browser/{chunk-2NMUVDMZ.mjs → chunk-S6B7627U.mjs} +304 -210
  9. package/dist/lib/browser/chunk-S6B7627U.mjs.map +7 -0
  10. package/dist/lib/browser/{chunk-ENRYFGYE.mjs → chunk-UDWHTKB5.mjs} +6 -3
  11. package/dist/lib/browser/chunk-UDWHTKB5.mjs.map +7 -0
  12. package/dist/lib/browser/{chunk-H2AR4OLP.mjs → chunk-ULA2UQJ4.mjs} +15 -6
  13. package/dist/lib/browser/chunk-ULA2UQJ4.mjs.map +7 -0
  14. package/dist/lib/browser/{identity-created-VICTPQX7.mjs → identity-created-FYGS6TBH.mjs} +2 -2
  15. package/dist/lib/browser/index.mjs +53 -19
  16. package/dist/lib/browser/index.mjs.map +3 -3
  17. package/dist/lib/browser/{intent-resolver-A5274MUR.mjs → intent-resolver-QVR4MSJV.mjs} +26 -8
  18. package/dist/lib/browser/intent-resolver-QVR4MSJV.mjs.map +7 -0
  19. package/dist/lib/browser/meta.json +1 -1
  20. package/dist/lib/browser/{react-root-N6QTWYCV.mjs → react-root-IP2ZB245.mjs} +5 -5
  21. package/dist/lib/browser/{react-surface-STMNA7W7.mjs → react-surface-BT3EHB6V.mjs} +16 -22
  22. package/dist/lib/browser/react-surface-BT3EHB6V.mjs.map +7 -0
  23. package/dist/lib/browser/schema-5W3DSY2E.mjs +24 -0
  24. package/dist/lib/browser/schema-5W3DSY2E.mjs.map +7 -0
  25. package/dist/lib/browser/{settings-HN5UIYQO.mjs → settings-PHPCXX33.mjs} +2 -2
  26. package/dist/lib/browser/{spaces-ready-F57ITJDR.mjs → spaces-ready-K47RR7N2.mjs} +4 -4
  27. package/dist/lib/browser/{state-6DCY5YJP.mjs → state-INJ63O57.mjs} +2 -2
  28. package/dist/lib/browser/types/index.mjs +5 -5
  29. package/dist/lib/node/{app-graph-builder-6N4TEVHH.cjs → app-graph-builder-ZIUBXRPA.cjs} +45 -124
  30. package/dist/lib/node/app-graph-builder-ZIUBXRPA.cjs.map +7 -0
  31. package/dist/lib/node/{app-graph-serializer-AWKVTYAB.cjs → app-graph-serializer-VQOGHKXL.cjs} +20 -20
  32. package/dist/lib/node/{chunk-2RCJT3P2.cjs → chunk-N2FS7PRA.cjs} +365 -270
  33. package/dist/lib/node/chunk-N2FS7PRA.cjs.map +7 -0
  34. package/dist/lib/node/{chunk-MMXP2NHE.cjs → chunk-OVGKWJOC.cjs} +51 -40
  35. package/dist/lib/node/chunk-OVGKWJOC.cjs.map +7 -0
  36. package/dist/lib/node/{chunk-I2LRRRMV.cjs → chunk-U6DYXAR3.cjs} +10 -7
  37. package/dist/lib/node/chunk-U6DYXAR3.cjs.map +7 -0
  38. package/dist/lib/node/{chunk-SPCSJ2CY.cjs → chunk-WAJKBO3J.cjs} +21 -12
  39. package/dist/lib/node/chunk-WAJKBO3J.cjs.map +7 -0
  40. package/dist/lib/node/{chunk-UX3U4RU2.cjs → chunk-YZKNRFHU.cjs} +5 -4
  41. package/dist/lib/node/chunk-YZKNRFHU.cjs.map +7 -0
  42. package/dist/lib/node/{identity-created-JNDKMFKI.cjs → identity-created-AXI64BLE.cjs} +6 -6
  43. package/dist/lib/node/index.cjs +106 -73
  44. package/dist/lib/node/index.cjs.map +3 -3
  45. package/dist/lib/node/{intent-resolver-NVTAESKB.cjs → intent-resolver-MLENGECT.cjs} +76 -59
  46. package/dist/lib/node/intent-resolver-MLENGECT.cjs.map +7 -0
  47. package/dist/lib/node/meta.json +1 -1
  48. package/dist/lib/node/{react-root-YCHSAYQE.cjs → react-root-3OX5Z5CX.cjs} +10 -10
  49. package/dist/lib/node/{react-surface-ANSZ4FKK.cjs → react-surface-5NYCMXSM.cjs} +49 -57
  50. package/dist/lib/node/react-surface-5NYCMXSM.cjs.map +7 -0
  51. package/dist/lib/node/schema-YN7WVFRX.cjs +40 -0
  52. package/dist/lib/node/schema-YN7WVFRX.cjs.map +7 -0
  53. package/dist/lib/node/{settings-RBBL22DJ.cjs → settings-5QYFWNH7.cjs} +6 -6
  54. package/dist/lib/node/{spaces-ready-WHU4J6E5.cjs → spaces-ready-FQNAKR7G.cjs} +13 -13
  55. package/dist/lib/node/{state-WPZC4JXB.cjs → state-57UE3DYE.cjs} +6 -6
  56. package/dist/lib/node/types/index.cjs +18 -18
  57. package/dist/lib/node/types/index.cjs.map +1 -1
  58. package/dist/lib/node-esm/{app-graph-builder-MS6BI5EW.mjs → app-graph-builder-TERVM2SL.mjs} +21 -100
  59. package/dist/lib/node-esm/app-graph-builder-TERVM2SL.mjs.map +7 -0
  60. package/dist/lib/node-esm/{app-graph-serializer-AWAWDSCM.mjs → app-graph-serializer-GZRSWHEN.mjs} +4 -4
  61. package/dist/lib/node-esm/{chunk-ESWV7ICX.mjs → chunk-2TQ2AJEZ.mjs} +6 -3
  62. package/dist/lib/node-esm/chunk-2TQ2AJEZ.mjs.map +7 -0
  63. package/dist/lib/node-esm/{chunk-LGL4A5B5.mjs → chunk-6RSVVEPS.mjs} +2 -1
  64. package/dist/lib/node-esm/chunk-6RSVVEPS.mjs.map +7 -0
  65. package/dist/lib/node-esm/{chunk-4HICD7AU.mjs → chunk-DIKRH2IK.mjs} +304 -210
  66. package/dist/lib/node-esm/chunk-DIKRH2IK.mjs.map +7 -0
  67. package/dist/lib/node-esm/{chunk-77RE7Y5J.mjs → chunk-PGH5L7MV.mjs} +16 -5
  68. package/dist/lib/node-esm/chunk-PGH5L7MV.mjs.map +7 -0
  69. package/dist/lib/node-esm/{chunk-S6VAU6VJ.mjs → chunk-TRNZQEEN.mjs} +15 -6
  70. package/dist/lib/node-esm/chunk-TRNZQEEN.mjs.map +7 -0
  71. package/dist/lib/node-esm/{identity-created-3AUSSVEK.mjs → identity-created-3CGEXNPO.mjs} +2 -2
  72. package/dist/lib/node-esm/index.mjs +53 -19
  73. package/dist/lib/node-esm/index.mjs.map +3 -3
  74. package/dist/lib/node-esm/{intent-resolver-KJ67TU34.mjs → intent-resolver-BLW4RM6X.mjs} +26 -8
  75. package/dist/lib/node-esm/intent-resolver-BLW4RM6X.mjs.map +7 -0
  76. package/dist/lib/node-esm/meta.json +1 -1
  77. package/dist/lib/node-esm/{react-root-NBQQKAZD.mjs → react-root-7XXGP56B.mjs} +5 -5
  78. package/dist/lib/node-esm/{react-surface-G2H5T2D2.mjs → react-surface-R2ECJSFB.mjs} +16 -22
  79. package/dist/lib/node-esm/react-surface-R2ECJSFB.mjs.map +7 -0
  80. package/dist/lib/node-esm/schema-LOR2EVGY.mjs +25 -0
  81. package/dist/lib/node-esm/schema-LOR2EVGY.mjs.map +7 -0
  82. package/dist/lib/node-esm/{settings-VBAUB37B.mjs → settings-H6MXTEQM.mjs} +2 -2
  83. package/dist/lib/node-esm/{spaces-ready-ABADUX2P.mjs → spaces-ready-HKAQG5SA.mjs} +4 -4
  84. package/dist/lib/node-esm/{state-5GH2D5U4.mjs → state-VYA6OFHD.mjs} +2 -2
  85. package/dist/lib/node-esm/types/index.mjs +5 -5
  86. package/dist/types/src/SpacePlugin.d.ts.map +1 -1
  87. package/dist/types/src/capabilities/app-graph-builder.d.ts +88 -88
  88. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  89. package/dist/types/src/capabilities/capabilities.d.ts +2 -1
  90. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  91. package/dist/types/src/capabilities/index.d.ts +112 -111
  92. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  93. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  94. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  95. package/dist/types/src/capabilities/schema.d.ts +4 -0
  96. package/dist/types/src/capabilities/schema.d.ts.map +1 -0
  97. package/dist/types/src/components/AdvancedObjectSettings/AdvancedObjectSettings.d.ts +1 -2
  98. package/dist/types/src/components/AdvancedObjectSettings/AdvancedObjectSettings.d.ts.map +1 -1
  99. package/dist/types/src/components/AdvancedObjectSettings/ForeignKeys.d.ts +1 -2
  100. package/dist/types/src/components/AdvancedObjectSettings/ForeignKeys.d.ts.map +1 -1
  101. package/dist/types/src/components/AwaitingObject.d.ts +1 -2
  102. package/dist/types/src/components/AwaitingObject.d.ts.map +1 -1
  103. package/dist/types/src/components/BaseObjectSettings.d.ts +1 -2
  104. package/dist/types/src/components/BaseObjectSettings.d.ts.map +1 -1
  105. package/dist/types/src/components/CollectionMain.d.ts +1 -2
  106. package/dist/types/src/components/CollectionMain.d.ts.map +1 -1
  107. package/dist/types/src/components/CollectionSection.d.ts +1 -2
  108. package/dist/types/src/components/CollectionSection.d.ts.map +1 -1
  109. package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts +2 -4
  110. package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts.map +1 -1
  111. package/dist/types/src/components/CreateDialog/CreateObjectDialog.stories.d.ts.map +1 -1
  112. package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts +5 -7
  113. package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts.map +1 -1
  114. package/dist/types/src/components/CreateDialog/CreateSpaceDialog.d.ts +1 -2
  115. package/dist/types/src/components/CreateDialog/CreateSpaceDialog.d.ts.map +1 -1
  116. package/dist/types/src/components/JoinDialog.d.ts +1 -2
  117. package/dist/types/src/components/JoinDialog.d.ts.map +1 -1
  118. package/dist/types/src/components/MenuFooter.d.ts +1 -2
  119. package/dist/types/src/components/MenuFooter.d.ts.map +1 -1
  120. package/dist/types/src/components/PersistenceStatus.d.ts +1 -2
  121. package/dist/types/src/components/PersistenceStatus.d.ts.map +1 -1
  122. package/dist/types/src/components/PopoverAddSpace.d.ts +3 -0
  123. package/dist/types/src/components/PopoverAddSpace.d.ts.map +1 -0
  124. package/dist/types/src/components/PopoverRenameObject.d.ts +1 -2
  125. package/dist/types/src/components/PopoverRenameObject.d.ts.map +1 -1
  126. package/dist/types/src/components/PopoverRenameSpace.d.ts +1 -2
  127. package/dist/types/src/components/PopoverRenameSpace.d.ts.map +1 -1
  128. package/dist/types/src/components/ShareSpaceButton.d.ts +2 -3
  129. package/dist/types/src/components/ShareSpaceButton.d.ts.map +1 -1
  130. package/dist/types/src/components/SpacePluginSettings.d.ts +1 -2
  131. package/dist/types/src/components/SpacePluginSettings.d.ts.map +1 -1
  132. package/dist/types/src/components/SpacePresence.d.ts +4 -5
  133. package/dist/types/src/components/SpacePresence.d.ts.map +1 -1
  134. package/dist/types/src/components/SpacePresence.stories.d.ts +2 -3
  135. package/dist/types/src/components/SpacePresence.stories.d.ts.map +1 -1
  136. package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.d.ts +1 -2
  137. package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.d.ts.map +1 -1
  138. package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.d.ts +3 -5
  139. package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.d.ts.map +1 -1
  140. package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.stories.d.ts.map +1 -1
  141. package/dist/types/src/components/SyncStatus/InlineSyncStatus.d.ts +1 -2
  142. package/dist/types/src/components/SyncStatus/InlineSyncStatus.d.ts.map +1 -1
  143. package/dist/types/src/components/SyncStatus/Space.d.ts +2 -3
  144. package/dist/types/src/components/SyncStatus/Space.d.ts.map +1 -1
  145. package/dist/types/src/components/SyncStatus/SyncStatus.d.ts +3 -4
  146. package/dist/types/src/components/SyncStatus/SyncStatus.d.ts.map +1 -1
  147. package/dist/types/src/components/index.d.ts +1 -0
  148. package/dist/types/src/components/index.d.ts.map +1 -1
  149. package/dist/types/src/events.d.ts +4 -0
  150. package/dist/types/src/events.d.ts.map +1 -1
  151. package/dist/types/src/index.d.ts +1 -1
  152. package/dist/types/src/index.d.ts.map +1 -1
  153. package/dist/types/src/translations.d.ts +9 -0
  154. package/dist/types/src/translations.d.ts.map +1 -1
  155. package/dist/types/src/types/collection.d.ts +2 -2
  156. package/dist/types/src/types/thread.d.ts +34 -34
  157. package/dist/types/src/types/types.d.ts +35 -13
  158. package/dist/types/src/types/types.d.ts.map +1 -1
  159. package/dist/types/src/util.d.ts +3 -2
  160. package/dist/types/src/util.d.ts.map +1 -1
  161. package/package.json +40 -38
  162. package/src/SpacePlugin.tsx +35 -11
  163. package/src/capabilities/app-graph-builder.ts +15 -89
  164. package/src/capabilities/capabilities.ts +3 -1
  165. package/src/capabilities/index.ts +1 -0
  166. package/src/capabilities/intent-resolver.ts +18 -0
  167. package/src/capabilities/react-surface.tsx +12 -28
  168. package/src/capabilities/schema.ts +27 -0
  169. package/src/components/BaseObjectSettings.tsx +7 -0
  170. package/src/components/CreateDialog/CreateObjectDialog.stories.tsx +1 -3
  171. package/src/components/CreateDialog/CreateObjectDialog.tsx +29 -21
  172. package/src/components/CreateDialog/CreateObjectPanel.tsx +41 -43
  173. package/src/components/PopoverAddSpace.tsx +46 -0
  174. package/src/components/SpaceSettings/SpaceSettingsPanel.stories.tsx +5 -1
  175. package/src/components/SpaceSettings/SpaceSettingsPanel.tsx +27 -4
  176. package/src/components/index.ts +1 -0
  177. package/src/events.ts +6 -0
  178. package/src/index.ts +1 -1
  179. package/src/translations.ts +3 -0
  180. package/src/types/types.ts +21 -6
  181. package/src/util.tsx +8 -2
  182. package/dist/lib/browser/app-graph-builder-TTM2YZVS.mjs.map +0 -7
  183. package/dist/lib/browser/chunk-2NMUVDMZ.mjs.map +0 -7
  184. package/dist/lib/browser/chunk-ENRYFGYE.mjs.map +0 -7
  185. package/dist/lib/browser/chunk-H2AR4OLP.mjs.map +0 -7
  186. package/dist/lib/browser/chunk-RLZQJD47.mjs.map +0 -7
  187. package/dist/lib/browser/chunk-S5IGZNXJ.mjs.map +0 -7
  188. package/dist/lib/browser/intent-resolver-A5274MUR.mjs.map +0 -7
  189. package/dist/lib/browser/react-surface-STMNA7W7.mjs.map +0 -7
  190. package/dist/lib/node/app-graph-builder-6N4TEVHH.cjs.map +0 -7
  191. package/dist/lib/node/chunk-2RCJT3P2.cjs.map +0 -7
  192. package/dist/lib/node/chunk-I2LRRRMV.cjs.map +0 -7
  193. package/dist/lib/node/chunk-MMXP2NHE.cjs.map +0 -7
  194. package/dist/lib/node/chunk-SPCSJ2CY.cjs.map +0 -7
  195. package/dist/lib/node/chunk-UX3U4RU2.cjs.map +0 -7
  196. package/dist/lib/node/intent-resolver-NVTAESKB.cjs.map +0 -7
  197. package/dist/lib/node/react-surface-ANSZ4FKK.cjs.map +0 -7
  198. package/dist/lib/node-esm/app-graph-builder-MS6BI5EW.mjs.map +0 -7
  199. package/dist/lib/node-esm/chunk-4HICD7AU.mjs.map +0 -7
  200. package/dist/lib/node-esm/chunk-77RE7Y5J.mjs.map +0 -7
  201. package/dist/lib/node-esm/chunk-ESWV7ICX.mjs.map +0 -7
  202. package/dist/lib/node-esm/chunk-LGL4A5B5.mjs.map +0 -7
  203. package/dist/lib/node-esm/chunk-S6VAU6VJ.mjs.map +0 -7
  204. package/dist/lib/node-esm/intent-resolver-KJ67TU34.mjs.map +0 -7
  205. package/dist/lib/node-esm/react-surface-G2H5T2D2.mjs.map +0 -7
  206. /package/dist/lib/browser/{app-graph-serializer-ZGM5NDXE.mjs.map → app-graph-serializer-FOWFLYGU.mjs.map} +0 -0
  207. /package/dist/lib/browser/{identity-created-VICTPQX7.mjs.map → identity-created-FYGS6TBH.mjs.map} +0 -0
  208. /package/dist/lib/browser/{react-root-N6QTWYCV.mjs.map → react-root-IP2ZB245.mjs.map} +0 -0
  209. /package/dist/lib/browser/{settings-HN5UIYQO.mjs.map → settings-PHPCXX33.mjs.map} +0 -0
  210. /package/dist/lib/browser/{spaces-ready-F57ITJDR.mjs.map → spaces-ready-K47RR7N2.mjs.map} +0 -0
  211. /package/dist/lib/browser/{state-6DCY5YJP.mjs.map → state-INJ63O57.mjs.map} +0 -0
  212. /package/dist/lib/node/{app-graph-serializer-AWKVTYAB.cjs.map → app-graph-serializer-VQOGHKXL.cjs.map} +0 -0
  213. /package/dist/lib/node/{identity-created-JNDKMFKI.cjs.map → identity-created-AXI64BLE.cjs.map} +0 -0
  214. /package/dist/lib/node/{react-root-YCHSAYQE.cjs.map → react-root-3OX5Z5CX.cjs.map} +0 -0
  215. /package/dist/lib/node/{settings-RBBL22DJ.cjs.map → settings-5QYFWNH7.cjs.map} +0 -0
  216. /package/dist/lib/node/{spaces-ready-WHU4J6E5.cjs.map → spaces-ready-FQNAKR7G.cjs.map} +0 -0
  217. /package/dist/lib/node/{state-WPZC4JXB.cjs.map → state-57UE3DYE.cjs.map} +0 -0
  218. /package/dist/lib/node-esm/{app-graph-serializer-AWAWDSCM.mjs.map → app-graph-serializer-GZRSWHEN.mjs.map} +0 -0
  219. /package/dist/lib/node-esm/{identity-created-3AUSSVEK.mjs.map → identity-created-3CGEXNPO.mjs.map} +0 -0
  220. /package/dist/lib/node-esm/{react-root-NBQQKAZD.mjs.map → react-root-7XXGP56B.mjs.map} +0 -0
  221. /package/dist/lib/node-esm/{settings-VBAUB37B.mjs.map → settings-H6MXTEQM.mjs.map} +0 -0
  222. /package/dist/lib/node-esm/{spaces-ready-ABADUX2P.mjs.map → spaces-ready-HKAQG5SA.mjs.map} +0 -0
  223. /package/dist/lib/node-esm/{state-5GH2D5U4.mjs.map → state-VYA6OFHD.mjs.map} +0 -0
@@ -2,19 +2,10 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import React, { useCallback } from 'react';
5
+ import React from 'react';
6
6
 
7
- import {
8
- Capabilities,
9
- contributes,
10
- createSurface,
11
- Surface,
12
- useCapability,
13
- useCapabilities,
14
- usePluginManager,
15
- } from '@dxos/app-framework';
7
+ import { Capabilities, contributes, createSurface, Surface, useCapability } from '@dxos/app-framework';
16
8
  import { SettingsStore } from '@dxos/local-storage';
17
- import { ClientCapabilities } from '@dxos/plugin-client';
18
9
  import {
19
10
  getSpace,
20
11
  isEchoObject,
@@ -53,6 +44,8 @@ import {
53
44
  SyncStatus,
54
45
  type CreateObjectDialogProps,
55
46
  type SpaceSettingsDialogProps,
47
+ POPOVER_ADD_SPACE,
48
+ PopoverAddSpace,
56
49
  } from '../components';
57
50
  import { SPACE_PLUGIN } from '../meta';
58
51
  import { CollectionType, type SpaceSettingsProps } from '../types';
@@ -126,23 +119,8 @@ export default ({ createInvitationUrl }: ReactSurfaceOptions) =>
126
119
  createSurface({
127
120
  id: CREATE_OBJECT_DIALOG,
128
121
  role: 'dialog',
129
- filter: (data): data is { props: Partial<CreateObjectDialogProps> } => data.component === CREATE_OBJECT_DIALOG,
130
- component: ({ data }) => {
131
- const schemas = useCapabilities(ClientCapabilities.Schema).flat();
132
- const manager = usePluginManager();
133
-
134
- const resolve = useCallback(
135
- (typename: string) => {
136
- return (
137
- manager.context.requestCapabilities(Capabilities.Metadata).find(({ id }) => id === typename)?.metadata ??
138
- {}
139
- );
140
- },
141
- [manager],
142
- );
143
-
144
- return <CreateObjectDialog schemas={schemas} resolve={resolve} {...data.props} />;
145
- },
122
+ filter: (data): data is { props: CreateObjectDialogProps } => data.component === CREATE_OBJECT_DIALOG,
123
+ component: ({ data }) => <CreateObjectDialog {...data.props} />,
146
124
  }),
147
125
  createSurface({
148
126
  id: POPOVER_RENAME_SPACE,
@@ -157,6 +135,12 @@ export default ({ createInvitationUrl }: ReactSurfaceOptions) =>
157
135
  data.component === POPOVER_RENAME_OBJECT && isReactiveObject(data.props),
158
136
  component: ({ data }) => <PopoverRenameObject object={data.props} />,
159
137
  }),
138
+ createSurface({
139
+ id: POPOVER_ADD_SPACE,
140
+ role: 'popover',
141
+ filter: (data): data is any => data.component === POPOVER_ADD_SPACE,
142
+ component: () => <PopoverAddSpace />,
143
+ }),
160
144
  createSurface({
161
145
  id: `${SPACE_PLUGIN}/navtree-presence`,
162
146
  role: 'navtree-item-end',
@@ -0,0 +1,27 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { effect } from '@preact/signals-core';
6
+
7
+ import { Capabilities, contributes, type PluginsContext } from '@dxos/app-framework';
8
+ import { ClientCapabilities } from '@dxos/plugin-client';
9
+
10
+ import { SpaceCapabilities } from './capabilities';
11
+ import { type ObjectForm } from '../types';
12
+
13
+ export default (context: PluginsContext) => {
14
+ const client = context.requestCapability(ClientCapabilities.Client);
15
+
16
+ // TODO(wittjosiah): Unregister schemas when they are disabled.
17
+ let previous: ObjectForm[] = [];
18
+ const unsubscribe = effect(() => {
19
+ const forms = Array.from(new Set(context.requestCapabilities(SpaceCapabilities.ObjectForm)));
20
+ // TODO(wittjosiah): Filter out schemas which the client has already registered.
21
+ const newSchemas = forms.filter((form) => !previous.includes(form)).map((form) => form.objectSchema);
22
+ previous = forms;
23
+ client.addTypes(newSchemas);
24
+ });
25
+
26
+ return contributes(Capabilities.Null, null, () => unsubscribe());
27
+ };
@@ -15,17 +15,24 @@ export type BaseObjectSettingsProps = {
15
15
 
16
16
  export const BaseObjectSettings = ({ object }: BaseObjectSettingsProps) => {
17
17
  const { t } = useTranslation(SPACE_PLUGIN);
18
+ const inputRef = React.useRef<HTMLInputElement>(null);
18
19
  // TODO(burdon): Standardize forms.
19
20
  return (
20
21
  <div role='form' className='flex flex-col w-full p-2 gap-1'>
21
22
  <Input.Root>
22
23
  <Input.Label>{t('name label')}</Input.Label>
23
24
  <Input.TextInput
25
+ ref={inputRef}
24
26
  placeholder={t('name placeholder')}
25
27
  value={object.name ?? ''}
26
28
  onChange={(event) => {
27
29
  object.name = event.target.value;
28
30
  }}
31
+ onKeyDown={(event) => {
32
+ if (event.key === 'Enter') {
33
+ inputRef.current?.blur();
34
+ }
35
+ }}
29
36
  />
30
37
  </Input.Root>
31
38
  </div>
@@ -40,9 +40,7 @@ const meta: Meta<typeof CreateObjectDialog> = {
40
40
  parameters: {
41
41
  translations: [...translations, osTranslations],
42
42
  },
43
- args: {
44
- schemas: [CollectionType],
45
- },
43
+ args: {},
46
44
  };
47
45
 
48
46
  export default meta;
@@ -5,58 +5,65 @@
5
5
  import { pipe } from 'effect';
6
6
  import React, { useCallback, useRef } from 'react';
7
7
 
8
- import { chain, createIntent, LayoutAction, useIntentDispatcher } from '@dxos/app-framework';
9
- import { useClient } from '@dxos/react-client';
10
8
  import {
11
- getSpace,
12
- isReactiveObject,
13
- isSpace,
14
- type ReactiveObject,
15
- type TypedObject,
16
- useSpaces,
17
- } from '@dxos/react-client/echo';
9
+ Capabilities,
10
+ chain,
11
+ createIntent,
12
+ LayoutAction,
13
+ useCapabilities,
14
+ useIntentDispatcher,
15
+ usePluginManager,
16
+ } from '@dxos/app-framework';
17
+ import { invariant } from '@dxos/invariant';
18
+ import { useClient } from '@dxos/react-client';
19
+ import { getSpace, isReactiveObject, isSpace, type ReactiveObject, useSpaces } from '@dxos/react-client/echo';
18
20
  import { Button, Dialog, Icon, useTranslation } from '@dxos/react-ui';
19
21
 
20
22
  import { CreateObjectPanel, type CreateObjectPanelProps } from './CreateObjectPanel';
23
+ import { SpaceCapabilities } from '../../capabilities';
21
24
  import { SPACE_PLUGIN } from '../../meta';
22
- import { CollectionType, SpaceAction } from '../../types';
25
+ import { CollectionType, type ObjectForm, SpaceAction } from '../../types';
23
26
 
24
27
  export const CREATE_OBJECT_DIALOG = `${SPACE_PLUGIN}/CreateObjectDialog`;
25
28
 
26
- export type CreateObjectDialogProps = Pick<CreateObjectPanelProps, 'schemas' | 'target' | 'typename' | 'name'> & {
27
- resolve?: (typename: string) => Record<string, any>;
29
+ export type CreateObjectDialogProps = Pick<CreateObjectPanelProps, 'target' | 'typename' | 'name'> & {
28
30
  shouldNavigate?: (object: ReactiveObject<any>) => boolean;
29
31
  };
30
32
 
31
33
  export const CreateObjectDialog = ({
32
- schemas,
33
34
  target,
34
35
  typename,
35
36
  name,
36
37
  shouldNavigate: _shouldNavigate,
37
- resolve,
38
38
  }: CreateObjectDialogProps) => {
39
39
  const closeRef = useRef<HTMLButtonElement | null>(null);
40
+ const manager = usePluginManager();
40
41
  const { t } = useTranslation(SPACE_PLUGIN);
41
42
  const client = useClient();
42
43
  const spaces = useSpaces();
43
44
  const { dispatchPromise: dispatch } = useIntentDispatcher();
45
+ const forms = useCapabilities(SpaceCapabilities.ObjectForm);
46
+
47
+ const resolve = useCallback(
48
+ (typename: string) =>
49
+ manager.context.requestCapabilities(Capabilities.Metadata).find(({ id }) => id === typename)?.metadata ?? {},
50
+ [manager],
51
+ );
44
52
 
45
53
  const handleCreateObject = useCallback(
46
54
  async ({
47
- schema,
55
+ form,
48
56
  target: _target,
49
- data,
57
+ data = {},
50
58
  }: {
51
- schema: TypedObject;
59
+ form: ObjectForm;
52
60
  target: CreateObjectPanelProps['target'];
53
61
  data?: Record<string, any>;
54
62
  }) => {
55
63
  const target = isSpace(_target)
56
64
  ? (_target.properties[CollectionType.typename]?.target as CollectionType | undefined)
57
65
  : _target;
58
- const createObjectIntent = resolve?.(schema.typename)?.createObject;
59
- if (!createObjectIntent || !target) {
66
+ if (!target) {
60
67
  // TODO(wittjosiah): UI feedback.
61
68
  return;
62
69
  }
@@ -65,7 +72,8 @@ export const CreateObjectDialog = ({
65
72
  closeRef.current?.click();
66
73
 
67
74
  const space = isSpace(target) ? target : getSpace(target);
68
- const result = await dispatch(createObjectIntent(data, { space }));
75
+ invariant(space, 'Missing space');
76
+ const result = await dispatch(form.getIntent(data, { space }));
69
77
  const object = result.data?.object;
70
78
  if (isReactiveObject(object)) {
71
79
  const addObjectIntent = createIntent(SpaceAction.AddObject, { target, object });
@@ -95,7 +103,7 @@ export const CreateObjectDialog = ({
95
103
 
96
104
  <CreateObjectPanel
97
105
  classNames='p-4'
98
- schemas={schemas}
106
+ forms={forms}
99
107
  spaces={spaces}
100
108
  target={target}
101
109
  typename={typename}
@@ -2,19 +2,20 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import React, { useCallback, useMemo, useState } from 'react';
5
+ import React, { useCallback, useState } from 'react';
6
6
 
7
7
  import { Surface, isSurfaceAvailable, usePluginManager } from '@dxos/app-framework';
8
- import { type TypedObject, getObjectAnnotation, type ObjectAnnotation, S } from '@dxos/echo-schema';
8
+ import { getObjectAnnotation, type ObjectAnnotation, type S } from '@dxos/echo-schema';
9
+ import { invariant } from '@dxos/invariant';
9
10
  import { type SpaceId, type Space } from '@dxos/react-client/echo';
10
11
  import { Icon, type ThemedClassName, toLocalizedString, useTranslation } from '@dxos/react-ui';
11
12
  import { Form, type InputProps } from '@dxos/react-ui-form';
12
13
  import { SearchList } from '@dxos/react-ui-searchlist';
13
14
  import { mx } from '@dxos/react-ui-theme';
14
- import { nonNullable, type MaybePromise } from '@dxos/util';
15
+ import { isNonNullable, type MaybePromise } from '@dxos/util';
15
16
 
16
17
  import { SPACE_PLUGIN } from '../../meta';
17
- import { type CollectionType } from '../../types';
18
+ import { type ObjectForm, type CollectionType } from '../../types';
18
19
  import { getSpaceDisplayName } from '../../util';
19
20
 
20
21
  // TODO(ZaymonFC): Move this if you find yourself needing it elsewhere.
@@ -40,7 +41,7 @@ const useInputSurfaceLookup = (baseData?: Record<string, any>) => {
40
41
  };
41
42
 
42
43
  export type CreateObjectPanelProps = ThemedClassName<{
43
- schemas: TypedObject[];
44
+ forms: ObjectForm[];
44
45
  spaces: Space[];
45
46
  typename?: string;
46
47
  target?: Space | CollectionType;
@@ -48,15 +49,15 @@ export type CreateObjectPanelProps = ThemedClassName<{
48
49
  defaultSpaceId?: SpaceId;
49
50
  resolve?: (typename: string) => Record<string, any>;
50
51
  onCreateObject?: (params: {
51
- schema: TypedObject;
52
+ form: ObjectForm;
52
53
  target: Space | CollectionType;
53
- data: Record<string, any>;
54
+ data?: Record<string, any>;
54
55
  }) => MaybePromise<void>;
55
56
  }>;
56
57
 
57
58
  export const CreateObjectPanel = ({
58
59
  classNames,
59
- schemas,
60
+ forms,
60
61
  spaces,
61
62
  typename: initialTypename,
62
63
  target: initialTarget,
@@ -68,10 +69,10 @@ export const CreateObjectPanel = ({
68
69
  const { t } = useTranslation(SPACE_PLUGIN);
69
70
  const [typename, setTypename] = useState<string | undefined>(initialTypename);
70
71
  const [target, setTarget] = useState<Space | CollectionType | undefined>(initialTarget);
71
- const schema = schemas.find((schema) => getObjectAnnotation(schema)?.typename === typename);
72
- const options: ObjectAnnotation[] = schemas
73
- .map(getObjectAnnotation)
74
- .filter(nonNullable)
72
+ const form = forms.find((form) => getObjectAnnotation(form.objectSchema)?.typename === typename);
73
+ const options: ObjectAnnotation[] = forms
74
+ .map((form) => getObjectAnnotation(form.objectSchema))
75
+ .filter(isNonNullable)
75
76
  .sort((a, b) => {
76
77
  const nameA = t('typename label', { ns: a.typename, defaultValue: a.typename });
77
78
  const nameB = t('typename label', { ns: b.typename, defaultValue: b.typename });
@@ -80,50 +81,47 @@ export const CreateObjectPanel = ({
80
81
 
81
82
  const handleCreateObject = useCallback(
82
83
  async (props: Record<string, any>) => {
83
- if (!schema || !target) {
84
+ if (!form || !target) {
84
85
  return;
85
86
  }
86
- await onCreateObject?.({ schema, target, data: props });
87
+ await onCreateObject?.({ form, target, data: props });
87
88
  },
88
- [onCreateObject, schema, target],
89
+ [onCreateObject, form, target],
89
90
  );
90
91
 
91
- const metadata = useMemo(() => {
92
- if (!typename) {
93
- return;
94
- }
95
- return resolve?.(typename);
96
- }, [resolve, typename]);
92
+ const handleSetTypename = useCallback(
93
+ async (typename: string) => {
94
+ invariant(target, 'target is required');
95
+ const form = forms.find((form) => getObjectAnnotation(form.objectSchema)?.typename === typename);
96
+ if (form && !form.formSchema) {
97
+ await onCreateObject?.({ form, target });
98
+ } else {
99
+ setTypename(typename);
100
+ }
101
+ },
102
+ [forms, onCreateObject, target],
103
+ );
97
104
 
98
105
  const inputSurfaceLookup = useInputSurfaceLookup({ target });
99
106
 
100
- const form = useMemo(() => {
101
- // TODO(ZaymonFC): Move this default object creation schema somewhere?
102
- const schema = (metadata?.creationSchema ?? S.Struct({ name: S.optional(S.String) })) as S.Schema<any>;
103
-
104
- return (
105
- <Form
106
- classNames='!p-0'
107
- autoFocus
108
- values={{ name: initialName }}
109
- schema={schema}
110
- testId='create-object-form'
111
- onSave={handleCreateObject}
112
- lookupComponent={inputSurfaceLookup}
113
- />
114
- );
115
- }, [initialName, handleCreateObject, metadata]);
116
-
117
107
  // TODO(wittjosiah): These inputs should be rolled into a `Form` once it supports the necessary variants.
118
108
  return (
119
109
  <div role='form' className={mx('flex flex-col gap-2', classNames)}>
120
- {!schema ? (
121
- <SelectSchema options={options} resolve={resolve} onChange={setTypename} />
110
+ {!form ? (
111
+ <SelectSchema options={options} resolve={resolve} onChange={handleSetTypename} />
122
112
  ) : !target ? (
123
113
  <SelectSpace spaces={spaces} defaultSpaceId={defaultSpaceId} onChange={setTarget} />
124
- ) : (
125
- form
126
- )}
114
+ ) : form.formSchema ? (
115
+ <Form
116
+ classNames='!p-0'
117
+ autoFocus
118
+ values={{ name: initialName }}
119
+ schema={form.formSchema}
120
+ testId='create-object-form'
121
+ onSave={handleCreateObject}
122
+ lookupComponent={inputSurfaceLookup}
123
+ />
124
+ ) : undefined}
127
125
  </div>
128
126
  );
129
127
  };
@@ -0,0 +1,46 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { createIntent, LayoutAction, useIntentDispatcher } from '@dxos/app-framework';
8
+ import { IconButton, useTranslation } from '@dxos/react-ui';
9
+
10
+ import { SPACE_PLUGIN } from '../meta';
11
+ import { SpaceAction } from '../types';
12
+
13
+ export const POPOVER_ADD_SPACE = `${SPACE_PLUGIN}/PopoverRenameSpace`;
14
+
15
+ export const PopoverAddSpace = () => {
16
+ const { t } = useTranslation(SPACE_PLUGIN);
17
+ const { dispatchPromise: dispatch } = useIntentDispatcher();
18
+ return (
19
+ <div role='none' className='grid grid-cols-1 gap-1 [&>button]:justify-start'>
20
+ <IconButton
21
+ variant='ghost'
22
+ label={t('create space label')}
23
+ icon='ph--plus--regular'
24
+ onClick={() => {
25
+ void dispatch(createIntent(SpaceAction.OpenCreateSpace));
26
+ void dispatch(
27
+ createIntent(LayoutAction.UpdatePopover, { part: 'popover', options: { anchorId: '', state: false } }),
28
+ );
29
+ }}
30
+ data-testid='spacePlugin.createSpace'
31
+ />
32
+ <IconButton
33
+ variant='ghost'
34
+ label={t('join space label')}
35
+ icon='ph--sign-in--regular'
36
+ onClick={() => {
37
+ void dispatch(createIntent(SpaceAction.Join));
38
+ void dispatch(
39
+ createIntent(LayoutAction.UpdatePopover, { part: 'popover', options: { anchorId: '', state: false } }),
40
+ );
41
+ }}
42
+ data-testid='spacePlugin.joinSpace'
43
+ />
44
+ </div>
45
+ );
46
+ };
@@ -15,7 +15,11 @@ import translations from '../../translations';
15
15
 
16
16
  const Story = (args: Partial<SpaceSettingsPanelProps>) => {
17
17
  const { space } = useClientProvider();
18
- return <SpaceSettingsPanel {...args} space={space!} classNames='p-2 border border-primary-500 rounded' />;
18
+ return (
19
+ <div role='none' className='p-2 border border-primary-500 rounded'>
20
+ <SpaceSettingsPanel {...args} space={space!} />
21
+ </div>
22
+ );
19
23
  };
20
24
 
21
25
  const meta: Meta = {
@@ -8,16 +8,17 @@ import { log } from '@dxos/log';
8
8
  import { EdgeReplicationSetting } from '@dxos/protocols/proto/dxos/echo/metadata';
9
9
  import { useClient } from '@dxos/react-client';
10
10
  import { type Space } from '@dxos/react-client/echo';
11
- import { type ThemedClassName, Input, useTranslation } from '@dxos/react-ui';
11
+ import { Input, Toolbar, useTranslation } from '@dxos/react-ui';
12
12
  import { DeprecatedFormContainer, DeprecatedFormInput } from '@dxos/react-ui-form';
13
+ import { HuePicker, IconPicker } from '@dxos/react-ui-pickers';
13
14
 
14
15
  import { SPACE_PLUGIN } from '../../meta';
15
16
 
16
- export type SpaceSettingsPanelProps = ThemedClassName<{
17
+ export type SpaceSettingsPanelProps = {
17
18
  space: Space;
18
- }>;
19
+ };
19
20
 
20
- export const SpaceSettingsPanel = ({ classNames, space }: SpaceSettingsPanelProps) => {
21
+ export const SpaceSettingsPanel = ({ space }: SpaceSettingsPanelProps) => {
21
22
  const { t } = useTranslation(SPACE_PLUGIN);
22
23
 
23
24
  const client = useClient();
@@ -50,6 +51,28 @@ export const SpaceSettingsPanel = ({ classNames, space }: SpaceSettingsPanelProp
50
51
  }}
51
52
  />
52
53
  </DeprecatedFormInput>
54
+ <DeprecatedFormInput label={t('icon label')}>
55
+ <Toolbar.Root>
56
+ <IconPicker
57
+ value={space.properties.icon}
58
+ onChange={(nextIcon) => (space.properties.icon = nextIcon)}
59
+ onReset={() => {
60
+ space.properties.icon = undefined;
61
+ }}
62
+ />
63
+ </Toolbar.Root>
64
+ </DeprecatedFormInput>
65
+ <DeprecatedFormInput label={t('hue label')}>
66
+ <Toolbar.Root>
67
+ <HuePicker
68
+ value={space.properties.hue}
69
+ onChange={(nextHue) => (space.properties.hue = nextHue)}
70
+ onReset={() => {
71
+ space.properties.hue = undefined;
72
+ }}
73
+ />
74
+ </Toolbar.Root>
75
+ </DeprecatedFormInput>
53
76
  {edgeEnabled && (
54
77
  <DeprecatedFormInput label={t('edge replication label')}>
55
78
  <Input.Switch checked={edgeReplication} onCheckedChange={toggleEdgeReplication} />
@@ -11,6 +11,7 @@ export * from './CollectionSection';
11
11
  export * from './JoinDialog';
12
12
  export * from './MenuFooter';
13
13
  export * from './PersistenceStatus';
14
+ export * from './PopoverAddSpace';
14
15
  export * from './PopoverRenameObject';
15
16
  export * from './PopoverRenameSpace';
16
17
  export * from './ShareSpaceButton';
package/src/events.ts CHANGED
@@ -7,6 +7,12 @@ import { defineEvent } from '@dxos/app-framework';
7
7
  import { SPACE_PLUGIN } from './meta';
8
8
 
9
9
  export namespace SpaceEvents {
10
+ export const SetupSettingsPanel = defineEvent(`${SPACE_PLUGIN}/event/setup-settings-panel`);
10
11
  export const StateReady = defineEvent(`${SPACE_PLUGIN}/event/state-ready`);
11
12
  export const DefaultSpaceReady = defineEvent(`${SPACE_PLUGIN}/event/default-space-ready`);
12
13
  }
14
+
15
+ // TODO(wittjosiah): Factor out.
16
+ export namespace ThreadEvents {
17
+ export const SetupThread = defineEvent(`${SPACE_PLUGIN}/event/setup-thread`);
18
+ }
package/src/index.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  export { SpaceCapabilities, ThreadCapabilities } from './capabilities';
6
- export { SpaceEvents } from './events';
6
+ export { SpaceEvents, ThreadEvents } from './events';
7
7
 
8
8
  export * from './components';
9
9
  export * from './meta';
@@ -14,6 +14,7 @@ export default [
14
14
  [SPACE_PLUGIN]: {
15
15
  'plugin name': 'Spaces',
16
16
  'first run message': 'Nothing selected.',
17
+ 'add space label': 'Create or join a space',
17
18
  'create space label': 'Create space',
18
19
  'join space label': 'Join space',
19
20
  'empty space message': 'No documents',
@@ -124,6 +125,8 @@ export default [
124
125
  'advanced settings label': 'Advanced',
125
126
  'foreign keys': 'Foreign Keys',
126
127
  'add key': 'Add Key',
128
+ 'icon label': 'Icon',
129
+ 'hue label': 'Color',
127
130
  },
128
131
  },
129
132
  },
@@ -2,19 +2,16 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { AST, S, type Expando } from '@dxos/echo-schema';
5
+ import { type AnyIntentChain } from '@dxos/app-framework';
6
+ import { AST, S, type Expando, type BaseObject, type TypedObject } from '@dxos/echo-schema';
6
7
  import { type PublicKey } from '@dxos/react-client';
8
+ // TODO(wittjosiah): This pulls in full client.
7
9
  import { EchoObjectSchema, ReactiveObjectSchema, type Space, SpaceSchema } from '@dxos/react-client/echo';
8
10
  import { type ComplexMap } from '@dxos/util';
9
11
 
10
12
  import { CollectionType } from './collection';
11
13
  import { SPACE_PLUGIN } from '../meta';
12
14
 
13
- // I've copy pasted this here to not depend on the whole @dxos/app-framework package in types entrypoint.
14
- /** @deprecated */
15
- export const ActiveParts = S.Record({ key: S.String, value: S.Union(S.String, S.mutable(S.Array(S.String))) });
16
- export type ActiveParts = S.Schema.Type<typeof ActiveParts>;
17
-
18
15
  export const SPACE_DIRECTORY_HANDLE = 'dxos.org/plugin/space/directory';
19
16
 
20
17
  export type ObjectViewerProps = {
@@ -96,6 +93,14 @@ export const SpaceForm = S.Struct({
96
93
  edgeReplication: S.Boolean.annotations({ [AST.TitleAnnotationId]: 'Enable EDGE Replication' }),
97
94
  });
98
95
 
96
+ export type ObjectForm<T extends BaseObject = BaseObject> = {
97
+ objectSchema: TypedObject;
98
+ formSchema?: S.Schema<T, any>;
99
+ getIntent: (props: T, options: { space: Space }) => AnyIntentChain;
100
+ };
101
+
102
+ export const defineObjectForm = <T extends BaseObject>(form: ObjectForm<T>) => form;
103
+
99
104
  export const SPACE_ACTION = `${SPACE_PLUGIN}/action`;
100
105
 
101
106
  export namespace SpaceAction {
@@ -150,6 +155,16 @@ export namespace SpaceAction {
150
155
  output: S.Void,
151
156
  }) {}
152
157
 
158
+ export class AddSpace extends S.TaggedClass<AddSpace>()(`${SPACE_ACTION}/add-space`, {
159
+ input: S.Void,
160
+ output: S.Void,
161
+ }) {}
162
+
163
+ export class AddSpaceMenuGroup extends S.TaggedClass<AddSpaceMenuGroup>()(`${SPACE_ACTION}/add-space-menu-group`, {
164
+ input: S.Void,
165
+ output: S.Void,
166
+ }) {}
167
+
153
168
  export class OpenSettings extends S.TaggedClass<OpenSettings>()(`${SPACE_ACTION}/open-settings`, {
154
169
  input: S.Struct({
155
170
  space: SpaceSchema,
package/src/util.tsx CHANGED
@@ -205,7 +205,11 @@ export const constructSpaceNode = ({
205
205
  ...partials,
206
206
  label: getSpaceDisplayName(space, { personal, namesCache }),
207
207
  description: space.state.get() === SpaceState.SPACE_READY && space.properties.description,
208
- icon: 'ph--planet--regular',
208
+ hue: space.state.get() === SpaceState.SPACE_READY && space.properties.hue,
209
+ icon:
210
+ space.state.get() === SpaceState.SPACE_READY && space.properties.icon
211
+ ? `ph--${space.properties.icon}--regular`
212
+ : undefined,
209
213
  disabled: !navigable || space.state.get() !== SpaceState.SPACE_READY || hasPendingMigration,
210
214
  testId: 'spacePlugin.space',
211
215
  },
@@ -415,6 +419,8 @@ export const constructObjectActions = ({
415
419
  navigable?: boolean;
416
420
  }) => {
417
421
  const object = node.data;
422
+ const space = getSpace(object);
423
+ invariant(space, 'Space not found');
418
424
  const getId = (id: string) => `${id}/${fullyQualifiedId(object)}`;
419
425
  const actions: NodeArg<ActionData>[] = [
420
426
  ...(object instanceof CollectionType
@@ -477,7 +483,7 @@ export const constructObjectActions = ({
477
483
  id: getId('copy-link'),
478
484
  type: ACTION_TYPE,
479
485
  data: async () => {
480
- const url = `${window.location.origin}/${fullyQualifiedId(object)}`;
486
+ const url = `${window.location.origin}/${space.id}/${fullyQualifiedId(object)}`;
481
487
  await navigator.clipboard.writeText(url);
482
488
  },
483
489
  properties: {