@dxos/plugin-space 0.8.4-main.a4bbb77 → 0.8.4-main.ae835ea

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 (224) hide show
  1. package/dist/lib/browser/{CollectionMain-AX7KKXWP.mjs → CollectionMain-HTKSZCRR.mjs} +2 -2
  2. package/dist/lib/browser/ObjectDetailsPanel-5B45G744.mjs +145 -0
  3. package/dist/lib/browser/ObjectDetailsPanel-5B45G744.mjs.map +7 -0
  4. package/dist/lib/browser/ObjectSettings-UFTKBP7B.mjs +146 -0
  5. package/dist/lib/browser/ObjectSettings-UFTKBP7B.mjs.map +7 -0
  6. package/dist/lib/browser/RecordMain-BCSXTSEB.mjs +99 -0
  7. package/dist/lib/browser/RecordMain-BCSXTSEB.mjs.map +7 -0
  8. package/dist/lib/browser/{app-graph-builder-W7RVDAUA.mjs → app-graph-builder-QJFO4ANM.mjs} +37 -34
  9. package/dist/lib/browser/app-graph-builder-QJFO4ANM.mjs.map +7 -0
  10. package/dist/lib/browser/{app-graph-serializer-VLHVTDX4.mjs → app-graph-serializer-3R5NVV7U.mjs} +5 -5
  11. package/dist/lib/browser/{chunk-E2I747A7.mjs → chunk-2NS3VPSY.mjs} +2 -2
  12. package/dist/lib/browser/chunk-2NS3VPSY.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-ZIZ2JLW6.mjs → chunk-4V4JNJ33.mjs} +12 -4
  14. package/dist/lib/browser/chunk-4V4JNJ33.mjs.map +7 -0
  15. package/dist/lib/browser/{chunk-2BFVC5K6.mjs → chunk-ENBBJSNE.mjs} +230 -254
  16. package/dist/lib/browser/chunk-ENBBJSNE.mjs.map +7 -0
  17. package/dist/lib/browser/chunk-HS2VD6DN.mjs +166 -0
  18. package/dist/lib/browser/chunk-HS2VD6DN.mjs.map +7 -0
  19. package/dist/lib/browser/{chunk-PN27K4I7.mjs → chunk-OWNBEI5J.mjs} +23 -14
  20. package/dist/lib/browser/chunk-OWNBEI5J.mjs.map +7 -0
  21. package/dist/lib/browser/{chunk-JCHSUOPF.mjs → chunk-SLDQWMQ2.mjs} +12 -7
  22. package/dist/lib/browser/chunk-SLDQWMQ2.mjs.map +7 -0
  23. package/dist/lib/browser/chunk-VZBIIYFM.mjs +16 -0
  24. package/dist/lib/browser/chunk-VZBIIYFM.mjs.map +7 -0
  25. package/dist/lib/browser/{chunk-EIXZABXD.mjs → chunk-WJXU4GKV.mjs} +2 -2
  26. package/dist/lib/browser/index.mjs +31 -31
  27. package/dist/lib/browser/index.mjs.map +3 -3
  28. package/dist/lib/browser/{intent-resolver-HA7DPAUE.mjs → intent-resolver-MBVOLXFQ.mjs} +30 -23
  29. package/dist/lib/browser/intent-resolver-MBVOLXFQ.mjs.map +7 -0
  30. package/dist/lib/browser/meta.json +1 -1
  31. package/dist/lib/browser/{react-root-YQUJU64P.mjs → react-root-NKEKCEYM.mjs} +7 -7
  32. package/dist/lib/browser/{react-surface-HTXYMRSW.mjs → react-surface-PYSN2MBY.mjs} +15 -46
  33. package/dist/lib/browser/react-surface-PYSN2MBY.mjs.map +7 -0
  34. package/dist/lib/browser/{schema-defs-R56ZDBZ7.mjs → schema-defs-DWYK7TYW.mjs} +3 -3
  35. package/dist/lib/browser/{settings-5XPQMSPO.mjs → settings-ZUCC3ZLB.mjs} +3 -3
  36. package/dist/lib/browser/{spaces-ready-YY77ANIF.mjs → spaces-ready-HTWWJHLR.mjs} +6 -6
  37. package/dist/lib/browser/spaces-ready-HTWWJHLR.mjs.map +7 -0
  38. package/dist/lib/browser/{state-Y4RVCG4A.mjs → state-ISVAKMO7.mjs} +3 -3
  39. package/dist/lib/browser/types/index.mjs +2 -2
  40. package/dist/lib/node-esm/{CollectionMain-EU57SRYK.mjs → CollectionMain-OUHGG6OC.mjs} +2 -2
  41. package/dist/lib/node-esm/ObjectDetailsPanel-4SDHQVQU.mjs +146 -0
  42. package/dist/lib/node-esm/ObjectDetailsPanel-4SDHQVQU.mjs.map +7 -0
  43. package/dist/lib/node-esm/ObjectSettings-EU6F43RP.mjs +147 -0
  44. package/dist/lib/node-esm/ObjectSettings-EU6F43RP.mjs.map +7 -0
  45. package/dist/lib/node-esm/RecordMain-SD76DGOR.mjs +100 -0
  46. package/dist/lib/node-esm/RecordMain-SD76DGOR.mjs.map +7 -0
  47. package/dist/lib/node-esm/{app-graph-builder-5ZJJUMQI.mjs → app-graph-builder-B23W62HY.mjs} +37 -34
  48. package/dist/lib/node-esm/app-graph-builder-B23W62HY.mjs.map +7 -0
  49. package/dist/lib/node-esm/{app-graph-serializer-EZJSGJUT.mjs → app-graph-serializer-3Z3EXEEF.mjs} +5 -5
  50. package/dist/lib/node-esm/chunk-BDEFTL6K.mjs +18 -0
  51. package/dist/lib/node-esm/chunk-BDEFTL6K.mjs.map +7 -0
  52. package/dist/lib/node-esm/{chunk-5XRYHWL7.mjs → chunk-G4PDWB7G.mjs} +12 -4
  53. package/dist/lib/node-esm/chunk-G4PDWB7G.mjs.map +7 -0
  54. package/dist/lib/node-esm/{chunk-SVFKU7EW.mjs → chunk-H4JILUJK.mjs} +2 -2
  55. package/dist/lib/node-esm/{chunk-BLPXWPLB.mjs → chunk-KKPCCA5O.mjs} +230 -254
  56. package/dist/lib/node-esm/chunk-KKPCCA5O.mjs.map +7 -0
  57. package/dist/lib/node-esm/chunk-PM4ZIGKC.mjs +167 -0
  58. package/dist/lib/node-esm/chunk-PM4ZIGKC.mjs.map +7 -0
  59. package/dist/lib/node-esm/{chunk-XDQXUZMK.mjs → chunk-XEVIWD3O.mjs} +23 -14
  60. package/dist/lib/node-esm/chunk-XEVIWD3O.mjs.map +7 -0
  61. package/dist/lib/node-esm/{chunk-6WNZW6KT.mjs → chunk-YFQXFQGT.mjs} +12 -7
  62. package/dist/lib/node-esm/chunk-YFQXFQGT.mjs.map +7 -0
  63. package/dist/lib/node-esm/{chunk-IJVBBVCL.mjs → chunk-ZLMFLI7G.mjs} +2 -2
  64. package/dist/lib/node-esm/chunk-ZLMFLI7G.mjs.map +7 -0
  65. package/dist/lib/node-esm/index.mjs +31 -31
  66. package/dist/lib/node-esm/index.mjs.map +3 -3
  67. package/dist/lib/node-esm/{intent-resolver-LQNHMPIX.mjs → intent-resolver-IWI47NTW.mjs} +30 -23
  68. package/dist/lib/node-esm/intent-resolver-IWI47NTW.mjs.map +7 -0
  69. package/dist/lib/node-esm/meta.json +1 -1
  70. package/dist/lib/node-esm/{react-root-UTLJEIKE.mjs → react-root-LX7SIG6M.mjs} +7 -7
  71. package/dist/lib/node-esm/{react-surface-LYDYON3U.mjs → react-surface-6SVGOZNJ.mjs} +15 -46
  72. package/dist/lib/node-esm/react-surface-6SVGOZNJ.mjs.map +7 -0
  73. package/dist/lib/node-esm/{schema-defs-7IMJPIWS.mjs → schema-defs-EOG2UPJU.mjs} +3 -3
  74. package/dist/lib/node-esm/{settings-XBSK5KHH.mjs → settings-ZDJNLFGW.mjs} +3 -3
  75. package/dist/lib/node-esm/{spaces-ready-YX4IHT4P.mjs → spaces-ready-VUGYPF4L.mjs} +6 -6
  76. package/dist/lib/node-esm/spaces-ready-VUGYPF4L.mjs.map +7 -0
  77. package/dist/lib/node-esm/{state-HOHAVPUO.mjs → state-QZ4Q6ZRL.mjs} +3 -3
  78. package/dist/lib/node-esm/types/index.mjs +2 -2
  79. package/dist/types/src/SpacePlugin.d.ts.map +1 -1
  80. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  81. package/dist/types/src/capabilities/capabilities.d.ts +2 -1
  82. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  83. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  84. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  85. package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts.map +1 -1
  86. package/dist/types/src/components/CreateDialog/CreateObjectDialog.stories.d.ts +80 -0
  87. package/dist/types/src/components/CreateDialog/CreateObjectDialog.stories.d.ts.map +1 -1
  88. package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts +1 -1
  89. package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts.map +1 -1
  90. package/dist/types/src/components/CreateDialog/CreateSpaceDialog.d.ts.map +1 -1
  91. package/dist/types/src/components/MembersContainer.stories.d.ts +80 -0
  92. package/dist/types/src/components/MembersContainer.stories.d.ts.map +1 -1
  93. package/dist/types/src/components/ObjectDetailsPanel/ObjectDetailsPanel.d.ts +9 -0
  94. package/dist/types/src/components/ObjectDetailsPanel/ObjectDetailsPanel.d.ts.map +1 -0
  95. package/dist/types/src/components/ObjectDetailsPanel/ObjectForm.d.ts +10 -0
  96. package/dist/types/src/components/ObjectDetailsPanel/ObjectForm.d.ts.map +1 -0
  97. package/dist/types/src/components/ObjectDetailsPanel/index.d.ts +3 -0
  98. package/dist/types/src/components/ObjectDetailsPanel/index.d.ts.map +1 -0
  99. package/dist/types/src/components/ObjectSettings/BaseObjectSettings.d.ts +2 -2
  100. package/dist/types/src/components/ObjectSettings/BaseObjectSettings.d.ts.map +1 -1
  101. package/dist/types/src/components/ObjectSettings/BaseObjectSettings.stories.d.ts +1500 -0
  102. package/dist/types/src/components/ObjectSettings/BaseObjectSettings.stories.d.ts.map +1 -0
  103. package/dist/types/src/components/ObjectSettings/ForeignKeys.d.ts +1 -1
  104. package/dist/types/src/components/ObjectSettings/ForeignKeys.d.ts.map +1 -1
  105. package/dist/types/src/components/ObjectSettings/index.d.ts +2 -1
  106. package/dist/types/src/components/ObjectSettings/index.d.ts.map +1 -1
  107. package/dist/types/src/components/RecordMain.d.ts +4 -3
  108. package/dist/types/src/components/RecordMain.d.ts.map +1 -1
  109. package/dist/types/src/components/RecordMain.stories.d.ts +1667 -0
  110. package/dist/types/src/components/RecordMain.stories.d.ts.map +1 -0
  111. package/dist/types/src/components/SpacePresence.stories.d.ts +80 -0
  112. package/dist/types/src/components/SpacePresence.stories.d.ts.map +1 -1
  113. package/dist/types/src/components/SpaceSettings/SpaceSettingsContainer.d.ts.map +1 -1
  114. package/dist/types/src/components/SpaceSettings/SpaceSettingsContainer.stories.d.ts +80 -0
  115. package/dist/types/src/components/SpaceSettings/SpaceSettingsContainer.stories.d.ts.map +1 -1
  116. package/dist/types/src/components/SyncStatus/SyncStatus.d.ts.map +1 -1
  117. package/dist/types/src/components/SyncStatus/SyncStatus.stories.d.ts +81 -1
  118. package/dist/types/src/components/SyncStatus/SyncStatus.stories.d.ts.map +1 -1
  119. package/dist/types/src/components/ViewEditor.d.ts.map +1 -1
  120. package/dist/types/src/components/index.d.ts +4 -6
  121. package/dist/types/src/components/index.d.ts.map +1 -1
  122. package/dist/types/src/hooks/index.d.ts +1 -0
  123. package/dist/types/src/hooks/index.d.ts.map +1 -1
  124. package/dist/types/src/hooks/useInputSurfaceLookup.d.ts +1 -1
  125. package/dist/types/src/hooks/useInputSurfaceLookup.d.ts.map +1 -1
  126. package/dist/types/src/hooks/usePath.d.ts +1 -1
  127. package/dist/types/src/hooks/usePath.d.ts.map +1 -1
  128. package/dist/types/src/hooks/useTypeOptions.d.ts +10 -0
  129. package/dist/types/src/hooks/useTypeOptions.d.ts.map +1 -0
  130. package/dist/types/src/meta.d.ts.map +1 -1
  131. package/dist/types/src/translations.d.ts +80 -0
  132. package/dist/types/src/translations.d.ts.map +1 -1
  133. package/dist/types/src/types/types.d.ts +6 -4
  134. package/dist/types/src/types/types.d.ts.map +1 -1
  135. package/dist/types/src/util.d.ts +4 -1
  136. package/dist/types/src/util.d.ts.map +1 -1
  137. package/dist/types/tsconfig.tsbuildinfo +1 -1
  138. package/package.json +50 -48
  139. package/src/SpacePlugin.ts +7 -13
  140. package/src/capabilities/app-graph-builder.ts +29 -24
  141. package/src/capabilities/capabilities.ts +7 -2
  142. package/src/capabilities/intent-resolver.ts +13 -8
  143. package/src/capabilities/react-surface.tsx +6 -77
  144. package/src/capabilities/spaces-ready.ts +1 -1
  145. package/src/components/CreateDialog/CreateObjectDialog.tsx +5 -4
  146. package/src/components/CreateDialog/CreateObjectPanel.tsx +2 -2
  147. package/src/components/CreateDialog/CreateSpaceDialog.tsx +2 -1
  148. package/src/components/MembersContainer.tsx +1 -1
  149. package/src/components/{ObjectDetailsPanel.tsx → ObjectDetailsPanel/ObjectDetailsPanel.tsx} +8 -35
  150. package/src/components/ObjectDetailsPanel/ObjectForm.tsx +75 -0
  151. package/src/components/ObjectDetailsPanel/index.ts +7 -0
  152. package/src/components/ObjectSettings/AdvancedObjectSettings.tsx +1 -1
  153. package/src/components/ObjectSettings/BaseObjectSettings.stories.tsx +63 -0
  154. package/src/components/ObjectSettings/BaseObjectSettings.tsx +86 -26
  155. package/src/components/ObjectSettings/ForeignKeys.tsx +1 -1
  156. package/src/components/ObjectSettings/index.ts +3 -1
  157. package/src/components/RecordMain.stories.tsx +116 -0
  158. package/src/components/RecordMain.tsx +69 -29
  159. package/src/components/SchemaContainer.tsx +1 -1
  160. package/src/components/SpacePresence.tsx +1 -1
  161. package/src/components/SpaceSettings/SpaceSettingsContainer.tsx +4 -3
  162. package/src/components/SyncStatus/InlineSyncStatus.tsx +5 -5
  163. package/src/components/SyncStatus/SyncStatus.stories.tsx +3 -2
  164. package/src/components/SyncStatus/SyncStatus.tsx +93 -3
  165. package/src/components/ViewEditor.tsx +6 -7
  166. package/src/components/index.ts +1 -1
  167. package/src/hooks/index.ts +1 -0
  168. package/src/hooks/useInputSurfaceLookup.tsx +1 -1
  169. package/src/hooks/usePath.ts +1 -1
  170. package/src/hooks/useTypeOptions.ts +59 -0
  171. package/src/meta.ts +5 -0
  172. package/src/translations.ts +10 -1
  173. package/src/types/types.ts +9 -5
  174. package/src/util.tsx +22 -8
  175. package/dist/lib/browser/ObjectDetailsPanel-ETI5YBTH.mjs +0 -90
  176. package/dist/lib/browser/ObjectDetailsPanel-ETI5YBTH.mjs.map +0 -7
  177. package/dist/lib/browser/RecordMain-TEBGAVSL.mjs +0 -68
  178. package/dist/lib/browser/RecordMain-TEBGAVSL.mjs.map +0 -7
  179. package/dist/lib/browser/app-graph-builder-W7RVDAUA.mjs.map +0 -7
  180. package/dist/lib/browser/chunk-2BFVC5K6.mjs.map +0 -7
  181. package/dist/lib/browser/chunk-E2I747A7.mjs.map +0 -7
  182. package/dist/lib/browser/chunk-ELJDGQTO.mjs +0 -94
  183. package/dist/lib/browser/chunk-ELJDGQTO.mjs.map +0 -7
  184. package/dist/lib/browser/chunk-IRKDREHY.mjs +0 -11
  185. package/dist/lib/browser/chunk-IRKDREHY.mjs.map +0 -7
  186. package/dist/lib/browser/chunk-JCHSUOPF.mjs.map +0 -7
  187. package/dist/lib/browser/chunk-PN27K4I7.mjs.map +0 -7
  188. package/dist/lib/browser/chunk-ZIZ2JLW6.mjs.map +0 -7
  189. package/dist/lib/browser/intent-resolver-HA7DPAUE.mjs.map +0 -7
  190. package/dist/lib/browser/react-surface-HTXYMRSW.mjs.map +0 -7
  191. package/dist/lib/browser/spaces-ready-YY77ANIF.mjs.map +0 -7
  192. package/dist/lib/node-esm/ObjectDetailsPanel-TQ5GN4QJ.mjs +0 -91
  193. package/dist/lib/node-esm/ObjectDetailsPanel-TQ5GN4QJ.mjs.map +0 -7
  194. package/dist/lib/node-esm/RecordMain-WLYJMYER.mjs +0 -70
  195. package/dist/lib/node-esm/RecordMain-WLYJMYER.mjs.map +0 -7
  196. package/dist/lib/node-esm/app-graph-builder-5ZJJUMQI.mjs.map +0 -7
  197. package/dist/lib/node-esm/chunk-5XRYHWL7.mjs.map +0 -7
  198. package/dist/lib/node-esm/chunk-6WNZW6KT.mjs.map +0 -7
  199. package/dist/lib/node-esm/chunk-BLPXWPLB.mjs.map +0 -7
  200. package/dist/lib/node-esm/chunk-IJVBBVCL.mjs.map +0 -7
  201. package/dist/lib/node-esm/chunk-MWNATOXL.mjs +0 -13
  202. package/dist/lib/node-esm/chunk-MWNATOXL.mjs.map +0 -7
  203. package/dist/lib/node-esm/chunk-Q6AAQLQG.mjs +0 -96
  204. package/dist/lib/node-esm/chunk-Q6AAQLQG.mjs.map +0 -7
  205. package/dist/lib/node-esm/chunk-XDQXUZMK.mjs.map +0 -7
  206. package/dist/lib/node-esm/intent-resolver-LQNHMPIX.mjs.map +0 -7
  207. package/dist/lib/node-esm/react-surface-LYDYON3U.mjs.map +0 -7
  208. package/dist/lib/node-esm/spaces-ready-YX4IHT4P.mjs.map +0 -7
  209. package/dist/types/src/components/ObjectDetailsPanel.d.ts +0 -9
  210. package/dist/types/src/components/ObjectDetailsPanel.d.ts.map +0 -1
  211. /package/dist/lib/browser/{CollectionMain-AX7KKXWP.mjs.map → CollectionMain-HTKSZCRR.mjs.map} +0 -0
  212. /package/dist/lib/browser/{app-graph-serializer-VLHVTDX4.mjs.map → app-graph-serializer-3R5NVV7U.mjs.map} +0 -0
  213. /package/dist/lib/browser/{chunk-EIXZABXD.mjs.map → chunk-WJXU4GKV.mjs.map} +0 -0
  214. /package/dist/lib/browser/{react-root-YQUJU64P.mjs.map → react-root-NKEKCEYM.mjs.map} +0 -0
  215. /package/dist/lib/browser/{schema-defs-R56ZDBZ7.mjs.map → schema-defs-DWYK7TYW.mjs.map} +0 -0
  216. /package/dist/lib/browser/{settings-5XPQMSPO.mjs.map → settings-ZUCC3ZLB.mjs.map} +0 -0
  217. /package/dist/lib/browser/{state-Y4RVCG4A.mjs.map → state-ISVAKMO7.mjs.map} +0 -0
  218. /package/dist/lib/node-esm/{CollectionMain-EU57SRYK.mjs.map → CollectionMain-OUHGG6OC.mjs.map} +0 -0
  219. /package/dist/lib/node-esm/{app-graph-serializer-EZJSGJUT.mjs.map → app-graph-serializer-3Z3EXEEF.mjs.map} +0 -0
  220. /package/dist/lib/node-esm/{chunk-SVFKU7EW.mjs.map → chunk-H4JILUJK.mjs.map} +0 -0
  221. /package/dist/lib/node-esm/{react-root-UTLJEIKE.mjs.map → react-root-LX7SIG6M.mjs.map} +0 -0
  222. /package/dist/lib/node-esm/{schema-defs-7IMJPIWS.mjs.map → schema-defs-EOG2UPJU.mjs.map} +0 -0
  223. /package/dist/lib/node-esm/{settings-XBSK5KHH.mjs.map → settings-ZDJNLFGW.mjs.map} +0 -0
  224. /package/dist/lib/node-esm/{state-HOHAVPUO.mjs.map → state-QZ4Q6ZRL.mjs.map} +0 -0
@@ -2,42 +2,82 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import React, { useCallback } from 'react';
5
+ import React, { useMemo } from 'react';
6
6
 
7
- import { Obj } from '@dxos/echo';
8
- import { type JsonPath, setValue } from '@dxos/echo-schema';
9
- import { invariant } from '@dxos/invariant';
10
- import { getSpace } from '@dxos/react-client/echo';
11
- import { Form, useRefQueryLookupHandler } from '@dxos/react-ui-form';
7
+ import { Surface } from '@dxos/app-framework';
8
+ import { Filter, type Obj, Ref, Relation } from '@dxos/echo';
9
+ import { getSpace, useQuery } from '@dxos/react-client/echo';
10
+ import { useTranslation } from '@dxos/react-ui';
11
+ import { Masonry } from '@dxos/react-ui-masonry';
12
+ import { StackItem } from '@dxos/react-ui-stack';
13
+ import { mx } from '@dxos/react-ui-theme';
14
+ import { isNonNullable } from '@dxos/util';
12
15
 
13
- export const RecordMain = ({ record }: { record: Obj.Any }) => {
16
+ import { meta } from '../meta';
17
+
18
+ export type RecordMainProps = {
19
+ record: Obj.Any;
20
+ };
21
+
22
+ export const RecordMain = ({ record }: RecordMainProps) => {
23
+ const { t } = useTranslation(meta.id);
14
24
  const space = getSpace(record);
15
- const schema = Obj.getSchema(record);
16
- invariant(schema, 'Record has no schema.');
17
-
18
- const handleRefQueryLookup = useRefQueryLookupHandler({ space });
19
-
20
- const handleSave = useCallback(
21
- (values: any, { changed }: { changed: Record<JsonPath, boolean> }) => {
22
- const id = values.id;
23
- invariant(typeof id === 'string');
24
-
25
- const changedPaths = Object.keys(changed).filter((path) => changed[path as JsonPath]) as JsonPath[];
26
- for (const path of changedPaths) {
27
- const value = values[path];
28
- setValue(record, path, value);
29
- }
30
- },
31
- [record],
32
- );
25
+ const data = useMemo(() => ({ subject: record }), [record]);
26
+
27
+ // TODO(wittjosiah): This is a hack. ECHO needs to have a back reference index to easily query for related objects.
28
+ const objects = useQuery(space, Filter.everything());
29
+ const related = useMemo(() => {
30
+ const relations = objects.filter((obj) => Relation.isRelation(obj));
31
+ const targetObjects = relations
32
+ .filter((relation) => Relation.getSource(relation) === record)
33
+ .map((relation) => Relation.getTarget(relation));
34
+ const sourceObjects = relations
35
+ .filter((relation) => Relation.getTarget(relation) === record)
36
+ .map((relation) => Relation.getSource(relation));
37
+
38
+ const references = getReferencesFromObject(record);
39
+ const referencedObjects = references.map((ref) => ref.target).filter(isNonNullable);
40
+ const referencingObjects = objects.filter((obj) => {
41
+ const refs = getReferencesFromObject(obj);
42
+ return refs.some((ref) => ref.target === record);
43
+ });
44
+
45
+ return [...referencedObjects, ...referencingObjects, ...targetObjects, ...sourceObjects];
46
+ }, [record, objects]);
33
47
 
34
48
  return (
35
- <div role='none' className='container-max-width flex flex-col p-2 gap-1 overflow-y-auto'>
36
- <div key={record.id} className='border border-separator rounded'>
37
- <Form autoSave schema={schema} values={record} onSave={handleSave} onQueryRefOptions={handleRefQueryLookup} />
49
+ <StackItem.Content classNames='flex flex-col items-center'>
50
+ <div role='none' className={mx('flex flex-col gap-4 p-6 is-full overflow-y-auto')}>
51
+ <div role='none' className={mx('flex flex-col gap-1 card-min-width card-max-width')}>
52
+ <Surface role='section' data={data} limit={1} />
53
+ </div>
54
+
55
+ {/* TODO(wittjosiah): This should maybe be in a separate stack item. */}
56
+ {related.length > 0 && (
57
+ <div role='none' className={mx('flex flex-col gap-1', related.length === 1 ? 'card-max-width' : 'is-full')}>
58
+ <label className='text-description text-sm mbs-2'>{t('related objects label')}</label>
59
+ <Masonry.Root<Obj.Any>
60
+ items={related}
61
+ render={Card}
62
+ intrinsicHeight
63
+ columnCount={related.length === 1 ? 1 : undefined}
64
+ />
65
+ </div>
66
+ )}
38
67
  </div>
39
- </div>
68
+ </StackItem.Content>
40
69
  );
41
70
  };
42
71
 
72
+ const Card = ({ data: subject }: { data: Obj.Any }) => {
73
+ const data = useMemo(() => ({ subject }), [subject]);
74
+ return <Surface role='card' data={data} limit={1} />;
75
+ };
76
+
77
+ const getReferencesFromObject = (obj: Obj.Any): Ref.Any[] => {
78
+ return Object.getOwnPropertyNames(obj)
79
+ .map((name) => obj[name as keyof Obj.Any])
80
+ .filter((value) => Ref.isRef(value)) as Ref.Any[];
81
+ };
82
+
43
83
  export default RecordMain;
@@ -41,7 +41,7 @@ export const SchemaContainer = ({ space }: SchemaPanelProps) => {
41
41
  const schemas = useQuerySpaceSchemas(space);
42
42
 
43
43
  return (
44
- <StackItem.Content classNames='block overflow-y-auto'>
44
+ <StackItem.Content scrollable>
45
45
  <ControlPage>
46
46
  <ControlSection title={t('schema verbose label')} description={t('schema description')}>
47
47
  <div role='none' className={controlItemClasses}>
@@ -2,7 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { Option } from 'effect';
5
+ import * as Option from 'effect/Option';
6
6
  import React, { forwardRef, useCallback, useEffect, useState } from 'react';
7
7
 
8
8
  import { useAppGraph, useCapability } from '@dxos/app-framework';
@@ -2,7 +2,8 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Schema, pipe } from 'effect';
5
+ import * as Function from 'effect/Function';
6
+ import * as Schema from 'effect/Schema';
6
7
  import React, { type ChangeEvent, useCallback, useMemo, useState } from 'react';
7
8
 
8
9
  import { LayoutAction, chain, createIntent, useIntentDispatcher } from '@dxos/app-framework';
@@ -69,7 +70,7 @@ export const SpaceSettingsContainer = ({ space }: SpaceSettingsContainerProps) =
69
70
  }
70
71
  if (properties.archived && !archived) {
71
72
  void dispatch(
72
- pipe(
73
+ Function.pipe(
73
74
  createIntent(SpaceAction.Close, { space }),
74
75
  chain(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: client.spaces.default.id }),
75
76
  ),
@@ -162,7 +163,7 @@ export const SpaceSettingsContainer = ({ space }: SpaceSettingsContainerProps) =
162
163
  );
163
164
 
164
165
  return (
165
- <StackItem.Content classNames='block overflow-y-auto'>
166
+ <StackItem.Content scrollable>
166
167
  <ControlPage>
167
168
  <ControlSection
168
169
  title={t('space properties settings verbose label', { ns: meta.id })}
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Option } from 'effect';
5
+ import * as Option from 'effect/Option';
6
6
  import React, { useEffect, useState } from 'react';
7
7
 
8
8
  import { useAppGraph } from '@dxos/app-framework';
@@ -16,12 +16,12 @@ import { AttentionGlyph, useAttended, useAttention } from '@dxos/react-ui-attent
16
16
  import { usePath } from '../../hooks';
17
17
  import { meta } from '../../meta';
18
18
 
19
- const useEdgeStatus = (): EdgeStatus => {
20
- const [status, setStatus] = useState(EdgeStatus.NOT_CONNECTED);
19
+ const useEdgeStatus = (): EdgeStatus.ConnectionState => {
20
+ const [status, setStatus] = useState(EdgeStatus.ConnectionState.NOT_CONNECTED);
21
21
  const client = useClient();
22
22
  useEffect(() => {
23
23
  client.services.services.EdgeAgentService?.queryEdgeStatus().subscribe(({ status }) => {
24
- setStatus(status);
24
+ setStatus(status.state);
25
25
  });
26
26
  }, [client]);
27
27
 
@@ -43,7 +43,7 @@ export const InlineSyncStatus = ({ space, open }: { space: Space; open?: boolean
43
43
  const path = usePath(graph, startOfAttention);
44
44
  const containsAttended = !open && !isAttended && id && Option.isSome(path) ? path.value.includes(id) : false;
45
45
 
46
- const connectedToEdge = useEdgeStatus() === EdgeStatus.CONNECTED;
46
+ const connectedToEdge = useEdgeStatus() === EdgeStatus.ConnectionState.CONNECTED;
47
47
  // TODO(wittjosiah): This is not reactive.
48
48
  const edgeSyncEnabled = space.internal.data.edgeReplication === EdgeReplicationSetting.ENABLED;
49
49
  const syncState = useSpaceSyncState(space);
@@ -4,6 +4,7 @@
4
4
 
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
 
7
+ import { withClientProvider } from '@dxos/react-client/testing';
7
8
  import { withTheme } from '@dxos/react-ui/testing';
8
9
 
9
10
  import { translations } from '../../translations';
@@ -13,10 +14,10 @@ import { SyncStatusIndicator } from './SyncStatus';
13
14
  const meta = {
14
15
  title: 'plugins/plugin-space/SyncStatusIndicator',
15
16
  component: SyncStatusIndicator,
16
- decorators: [withTheme],
17
+ decorators: [withTheme, withClientProvider({ createIdentity: true })],
17
18
  parameters: {
18
- translations,
19
19
  layout: 'centered',
20
+ translations,
20
21
  },
21
22
  } satisfies Meta<typeof SyncStatusIndicator>;
22
23
 
@@ -5,9 +5,14 @@
5
5
  import React, { useEffect, useState } from 'react';
6
6
 
7
7
  import { StatusBar } from '@dxos/plugin-status-bar';
8
+ import { EdgeStatus } from '@dxos/protocols/proto/dxos/client/services';
9
+ import type { QueryEdgeStatusResponse } from '@dxos/protocols/proto/dxos/client/services';
8
10
  import { useClient } from '@dxos/react-client';
11
+ import { useStream } from '@dxos/react-client/devtools';
9
12
  import { type SpaceSyncStateMap, getSyncSummary, useSyncState } from '@dxos/react-client/echo';
10
- import { Icon, useTranslation } from '@dxos/react-ui';
13
+ import { Icon, Popover, useTranslation } from '@dxos/react-ui';
14
+ import { mx } from '@dxos/react-ui-theme';
15
+ import { Unit } from '@dxos/util';
11
16
 
12
17
  import { meta } from '../../meta';
13
18
 
@@ -53,7 +58,92 @@ export const SyncStatusIndicator = ({ state, saved }: { state: SpaceSyncStateMap
53
58
  }, [offline, needsToUpload, needsToDownload]);
54
59
 
55
60
  const title = t(`${status} label`);
56
- const icon = <Icon icon={getIcon(status)} size={4} classNames={classNames} />;
61
+ const icon = <Icon icon={getIcon(status)} classNames={classNames} />;
57
62
 
58
- return <StatusBar.Item title={title}>{icon}</StatusBar.Item>;
63
+ return (
64
+ <Popover.Root>
65
+ <Popover.Trigger asChild>
66
+ <StatusBar.Item title={title}>{icon}</StatusBar.Item>
67
+ </Popover.Trigger>
68
+ <Popover.Portal>
69
+ <Popover.Content>
70
+ <EdgeConnectionPopover />
71
+ <Popover.Arrow />
72
+ </Popover.Content>
73
+ </Popover.Portal>
74
+ </Popover.Root>
75
+ );
76
+ };
77
+
78
+ const useEdgeStatus = (): EdgeStatus | undefined => {
79
+ const client = useClient();
80
+ const { status } = useStream(
81
+ () => client.services.services.EdgeAgentService!.queryEdgeStatus(),
82
+ {} as QueryEdgeStatusResponse,
83
+ );
84
+ return status;
85
+ };
86
+
87
+ const EdgeConnectionPopover = () => {
88
+ const status = useEdgeStatus();
89
+ const { t } = useTranslation(meta.id);
90
+
91
+ const isConnected = status?.state === EdgeStatus.ConnectionState.CONNECTED;
92
+
93
+ return (
94
+ <div className='min-is-[240px] p-2'>
95
+ {/* Connection Status Header */}
96
+ <div className='flex items-center gap-2 mbe-2'>
97
+ <Icon
98
+ icon={isConnected ? 'ph--check-circle--regular' : 'ph--warning-circle--regular'}
99
+ classNames={mx(isConnected ? 'text-successText' : 'text-errorText animate-pulse')}
100
+ />
101
+ <span className='font-medium text-sm'>
102
+ {isConnected ? t('sync edge connected label') : t('sync edge disconnected label')}
103
+ </span>
104
+ </div>
105
+
106
+ {/* Connection Details */}
107
+ {status?.state === EdgeStatus.ConnectionState.NOT_CONNECTED && (
108
+ <div className='flex items-center gap-2 text-sm text-description'>
109
+ <Icon icon='ph--cloud-x--regular' />
110
+ <span>{t('sync no connection label')}</span>
111
+ </div>
112
+ )}
113
+
114
+ {status?.state === EdgeStatus.ConnectionState.CONNECTED && (
115
+ <div className='space-y-2'>
116
+ {/* Latency */}
117
+ <div className='flex items-center justify-between'>
118
+ <div className='flex items-center gap-2 text-sm text-description'>
119
+ <Icon icon='ph--timer--regular' />
120
+ <span>{t('sync latency label')}</span>
121
+ </div>
122
+ <span className='text-sm font-mono text-subdued'>
123
+ {status.rtt.toFixed(0)}
124
+ ms
125
+ </span>
126
+ </div>
127
+
128
+ {/* Upload Speed */}
129
+ <div className='flex items-center justify-between'>
130
+ <div className='flex items-center gap-2 text-sm text-description'>
131
+ <Icon icon='ph--arrow-up--regular' />
132
+ <span>{t('sync upload label')}</span>
133
+ </div>
134
+ <span className='text-sm font-mono text-subdued'>{Unit.Kilobyte(status.rateBytesUp, 0)}/s</span>
135
+ </div>
136
+
137
+ {/* Download Speed */}
138
+ <div className='flex items-center justify-between'>
139
+ <div className='flex items-center gap-2 text-sm text-description'>
140
+ <Icon icon='ph--arrow-down--regular' />
141
+ <span>{t('sync download label')}</span>
142
+ </div>
143
+ <span className='text-sm font-mono text-subdued'>{Unit.Kilobyte(status.rateBytesDown, 0)}/s</span>
144
+ </div>
145
+ </div>
146
+ )}
147
+ </div>
148
+ );
59
149
  };
@@ -5,12 +5,12 @@
5
5
  import React, { useCallback } from 'react';
6
6
 
7
7
  import { createIntent, useIntentDispatcher } from '@dxos/app-framework';
8
- import { Filter, Query, Type } from '@dxos/echo';
8
+ import { type QueryAST, Type } from '@dxos/echo';
9
9
  import { invariant } from '@dxos/invariant';
10
10
  import { useClient } from '@dxos/react-client';
11
11
  import { getSpace, useSchema } from '@dxos/react-client/echo';
12
12
  import { ViewEditor as NaturalViewEditor } from '@dxos/react-ui-form';
13
- import { type DataType, typenameFromQuery } from '@dxos/schema';
13
+ import { type DataType, getTypenameFromQuery } from '@dxos/schema';
14
14
 
15
15
  import { SpaceAction } from '../types';
16
16
 
@@ -20,17 +20,16 @@ export const ViewEditor = ({ view }: ViewEditorProps) => {
20
20
  const { dispatchPromise: dispatch } = useIntentDispatcher();
21
21
  const client = useClient();
22
22
  const space = getSpace(view);
23
- const typename = view.query ? typenameFromQuery(view.query.ast) : undefined;
23
+ const typename = view.query ? getTypenameFromQuery(view.query.ast) : undefined;
24
24
  const schema = useSchema(client, space, typename);
25
25
 
26
26
  const handleUpdateQuery = useCallback(
27
- (typename: string) => {
27
+ (newQuery: QueryAST.Query) => {
28
28
  invariant(schema);
29
29
  invariant(Type.isMutable(schema));
30
30
 
31
- const newQuery = Query.select(Filter.typename(typename));
32
- view.query.ast = newQuery.ast;
33
- schema.updateTypename(typename);
31
+ view.query.ast = newQuery;
32
+ schema.updateTypename(getTypenameFromQuery(newQuery));
34
33
  },
35
34
  [view, schema],
36
35
  );
@@ -10,7 +10,6 @@ export * from './CollectionSection';
10
10
  export * from './JoinDialog';
11
11
  export * from './MembersContainer';
12
12
  export * from './MenuFooter';
13
- export * from './ObjectSettings';
14
13
  export * from './PersistenceStatus';
15
14
  export * from './PopoverRenameObject';
16
15
  export * from './PopoverRenameSpace';
@@ -23,4 +22,5 @@ export * from './ViewEditor';
23
22
 
24
23
  export const CollectionMain = lazy(() => import('./CollectionMain'));
25
24
  export const ObjectDetailsPanel = lazy(() => import('./ObjectDetailsPanel'));
25
+ export const ObjectSettingsContainer = lazy(() => import('./ObjectSettings'));
26
26
  export const RecordMain = lazy(() => import('./RecordMain'));
@@ -5,3 +5,4 @@
5
5
  export * from './useActiveSpace';
6
6
  export * from './useInputSurfaceLookup';
7
7
  export * from './usePath';
8
+ export * from './useTypeOptions';
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { type Schema } from 'effect';
5
+ import type * as Schema from 'effect/Schema';
6
6
  import React, { useCallback } from 'react';
7
7
 
8
8
  import { Surface, isSurfaceAvailable, usePluginManager } from '@dxos/app-framework';
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Option } from 'effect';
5
+ import * as Option from 'effect/Option';
6
6
  import { useEffect, useState } from 'react';
7
7
 
8
8
  import { type ReadableGraph } from '@dxos/plugin-graph';
@@ -0,0 +1,59 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { useMemo } from 'react';
6
+
7
+ import { useCapabilities } from '@dxos/app-framework';
8
+ import { Type } from '@dxos/echo';
9
+ import { ClientCapabilities } from '@dxos/plugin-client';
10
+ import { useClient } from '@dxos/react-client';
11
+ import { type Space } from '@dxos/react-client/echo';
12
+ import { useTranslation } from '@dxos/react-ui';
13
+ import { DataType, type TypenameAnnotation, getTypenames } from '@dxos/schema';
14
+
15
+ import { SpaceCapabilities } from '../capabilities';
16
+
17
+ const OMIT = [DataType.Collection.typename, Type.getTypename(DataType.QueryCollection)];
18
+
19
+ export const useTypeOptions = ({ space, annotation }: { space?: Space; annotation: TypenameAnnotation[] }) => {
20
+ const { t } = useTranslation();
21
+ const client = useClient();
22
+
23
+ const schemaWhitelists = useCapabilities(ClientCapabilities.SchemaWhiteList);
24
+ const whitelistedTypenames = useMemo(
25
+ () => new Set(schemaWhitelists.flatMap((typeArray) => typeArray.map((type) => Type.getTypename(type)))),
26
+ [schemaWhitelists],
27
+ );
28
+
29
+ const objectForms = useCapabilities(SpaceCapabilities.ObjectForm);
30
+ const objectFormTypenames = useMemo(
31
+ () =>
32
+ new Set(
33
+ objectForms
34
+ .map((form) => Type.getTypename(form.objectSchema))
35
+ // TODO(wittjosiah): Remove.
36
+ .filter((typename) => !OMIT.includes(typename) && !typename.endsWith('View')),
37
+ ),
38
+ [objectForms],
39
+ );
40
+
41
+ const typenames = getTypenames({
42
+ annotation,
43
+ whitelistedTypenames,
44
+ objectFormTypenames,
45
+ space,
46
+ client,
47
+ });
48
+
49
+ return useMemo(
50
+ () =>
51
+ typenames
52
+ .map((typename) => ({
53
+ value: typename,
54
+ label: t('typename label', { ns: typename, defaultValue: typename }),
55
+ }))
56
+ .toSorted((a, b) => a.label.localeCompare(b.label)),
57
+ [t, typenames],
58
+ );
59
+ };
package/src/meta.ts CHANGED
@@ -3,9 +3,14 @@
3
3
  //
4
4
 
5
5
  import { type PluginMeta } from '@dxos/app-framework';
6
+ import { trim } from '@dxos/util';
6
7
 
7
8
  export const meta: PluginMeta = {
8
9
  id: 'dxos.org/plugin/space',
9
10
  name: 'Spaces',
11
+ description: trim`
12
+ Core workspace container system for organizing and sharing collaborative environments.
13
+ Create, manage, and share spaces with granular access control and invitation management.
14
+ `,
10
15
  icon: 'ph--planet--regular',
11
16
  };
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { Type } from '@dxos/echo';
6
- import { StoredSchema } from '@dxos/echo-schema';
6
+ import { StoredSchema } from '@dxos/echo/internal';
7
7
  import { type Resource } from '@dxos/react-ui';
8
8
  import { DataType } from '@dxos/schema';
9
9
 
@@ -190,10 +190,12 @@ export const translations = [
190
190
  'creating in collection label': 'In Collection',
191
191
  'clear input label': 'Clear',
192
192
  'expose object label': 'Expose in navtree',
193
+ 'add tag label': 'Add tag',
193
194
  'advanced settings label': 'Advanced',
194
195
  'foreign keys': 'Foreign Keys',
195
196
  'add key': 'Add Key',
196
197
  'open space settings label': 'Open settings',
198
+ 'related objects label': 'Related',
197
199
 
198
200
  'row details no selection label': 'No objects selected',
199
201
  'companion selected objects label': 'Selected',
@@ -229,6 +231,13 @@ export const translations = [
229
231
  'Archiving a space will remove it from the sidebar and stop replicating updates, but will not delete the data. You can unarchive it by enabling archived spaces in the app settings.',
230
232
  'archive space label': 'Archive',
231
233
  'unarchive space label': 'Unarchive',
234
+
235
+ 'sync edge connected label': 'Edge connected',
236
+ 'sync edge disconnected label': 'Edge disconnected',
237
+ 'sync no connection label': 'No connection to edge service',
238
+ 'sync latency label': 'Latency',
239
+ 'sync upload label': 'Upload',
240
+ 'sync download label': 'Download',
232
241
  },
233
242
  },
234
243
  },
@@ -2,11 +2,11 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { Schema } from 'effect';
5
+ import * as Schema from 'effect/Schema';
6
6
 
7
7
  import { type AnyIntentChain } from '@dxos/app-framework';
8
8
  import { type Obj, Type } from '@dxos/echo';
9
- import { type BaseObject, EchoSchema, StoredSchema, type TypedObject } from '@dxos/echo-schema';
9
+ import { type BaseObject, EchoSchema, StoredSchema } from '@dxos/echo/internal';
10
10
  import { type PublicKey } from '@dxos/react-client';
11
11
  // TODO(wittjosiah): This pulls in full client.
12
12
  import { EchoObjectSchema, ReactiveObjectSchema, type Space, SpaceSchema } from '@dxos/react-client/echo';
@@ -106,8 +106,7 @@ export const SpaceForm = Schema.Struct({
106
106
  });
107
107
 
108
108
  export type ObjectForm<T extends BaseObject = BaseObject> = {
109
- // TODO(dmaretskyi): Change to Schema.Schema.AnyNoContext
110
- objectSchema: TypedObject;
109
+ objectSchema: Schema.Schema.AnyNoContext;
111
110
  formSchema?: Schema.Schema<T, any>;
112
111
  hidden?: boolean;
113
112
  getIntent: (props: T, options: { space: Space }) => AnyIntentChain;
@@ -231,6 +230,8 @@ export namespace SpaceAction {
231
230
  input: Schema.Struct({
232
231
  space: SpaceSchema,
233
232
  typename: Schema.String,
233
+ // TODO(wittjosiah): This is leaky.
234
+ show: Schema.optional(Schema.Boolean),
234
235
  }),
235
236
  output: Schema.Struct({}),
236
237
  }) {}
@@ -244,6 +245,8 @@ export namespace SpaceAction {
244
245
  version: Schema.optional(Schema.String),
245
246
  // TODO(wittjosiah): Schema for schema?
246
247
  schema: Schema.Any,
248
+ // TODO(wittjosiah): This is leaky.
249
+ show: Schema.optional(Schema.Boolean),
247
250
  }),
248
251
  output: Schema.Struct({
249
252
  // TODO(wittjosiah): ObjectId.
@@ -325,7 +328,8 @@ export namespace SpaceAction {
325
328
 
326
329
  export class RemoveObjects extends Schema.TaggedClass<RemoveObjects>()(`${SPACE_ACTION}/remove-objects`, {
327
330
  input: Schema.Struct({
328
- objects: Schema.Array(EchoObjectSchema),
331
+ // TODO(wittjosiah): Should be Schema.Union(Type.Obj, Type.Relation).
332
+ objects: Schema.Array(ReactiveObjectSchema),
329
333
  target: Schema.optional(DataType.Collection),
330
334
  deletionData: Schema.optional(DeletionData),
331
335
  }),