@dxos/plugin-space 0.7.5-main.9d26e3a → 0.7.5-main.e9bb01b

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 (211) hide show
  1. package/dist/lib/browser/app-graph-builder-J4NX44Y4.mjs +367 -0
  2. package/dist/lib/browser/app-graph-builder-J4NX44Y4.mjs.map +7 -0
  3. package/dist/lib/browser/app-graph-serializer-QF7VVRCV.mjs +80 -0
  4. package/dist/lib/browser/app-graph-serializer-QF7VVRCV.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-6UIFMVVI.mjs +528 -0
  6. package/dist/lib/browser/chunk-6UIFMVVI.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-PQXZCNAU.mjs +13 -0
  8. package/dist/lib/browser/chunk-PQXZCNAU.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-RLZQJD47.mjs +22 -0
  10. package/dist/lib/browser/chunk-RLZQJD47.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-SDK7RZI3.mjs +133 -0
  12. package/dist/lib/browser/chunk-SDK7RZI3.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-54VE4GTA.mjs → chunk-XPZ6IIXF.mjs} +11 -15
  14. package/dist/lib/browser/chunk-XPZ6IIXF.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-XZ2NH3CP.mjs +1713 -0
  16. package/dist/lib/browser/chunk-XZ2NH3CP.mjs.map +7 -0
  17. package/dist/lib/browser/identity-created-25TK5XNO.mjs +28 -0
  18. package/dist/lib/browser/identity-created-25TK5XNO.mjs.map +7 -0
  19. package/dist/lib/browser/index.mjs +186 -3481
  20. package/dist/lib/browser/index.mjs.map +4 -4
  21. package/dist/lib/browser/intent-resolver-IEDVV74T.mjs +523 -0
  22. package/dist/lib/browser/intent-resolver-IEDVV74T.mjs.map +7 -0
  23. package/dist/lib/browser/meta.json +1 -1
  24. package/dist/lib/browser/react-root-6VRPRLQR.mjs +28 -0
  25. package/dist/lib/browser/react-root-6VRPRLQR.mjs.map +7 -0
  26. package/dist/lib/browser/react-surface-DMNDXLZ7.mjs +231 -0
  27. package/dist/lib/browser/react-surface-DMNDXLZ7.mjs.map +7 -0
  28. package/dist/lib/browser/settings-K4JPYYEM.mjs +24 -0
  29. package/dist/lib/browser/settings-K4JPYYEM.mjs.map +7 -0
  30. package/dist/lib/browser/spaces-ready-2MUWWVVO.mjs +199 -0
  31. package/dist/lib/browser/spaces-ready-2MUWWVVO.mjs.map +7 -0
  32. package/dist/lib/browser/state-6DCY5YJP.mjs +47 -0
  33. package/dist/lib/browser/state-6DCY5YJP.mjs.map +7 -0
  34. package/dist/lib/browser/types/index.mjs +6 -6
  35. package/dist/lib/node/app-graph-builder-ZOPG4MOS.cjs +370 -0
  36. package/dist/lib/node/app-graph-builder-ZOPG4MOS.cjs.map +7 -0
  37. package/dist/lib/node/app-graph-serializer-QE2G4MWB.cjs +88 -0
  38. package/dist/lib/node/app-graph-serializer-QE2G4MWB.cjs.map +7 -0
  39. package/dist/lib/node/chunk-3QWZCN6L.cjs +556 -0
  40. package/dist/lib/node/chunk-3QWZCN6L.cjs.map +7 -0
  41. package/dist/lib/node/{chunk-YF2AQ7KP.cjs → chunk-6MEOP3DH.cjs} +18 -22
  42. package/dist/lib/node/chunk-6MEOP3DH.cjs.map +7 -0
  43. package/dist/lib/node/chunk-D6BFKOXY.cjs +150 -0
  44. package/dist/lib/node/chunk-D6BFKOXY.cjs.map +7 -0
  45. package/dist/lib/node/chunk-SZEIQGQU.cjs +1710 -0
  46. package/dist/lib/node/chunk-SZEIQGQU.cjs.map +7 -0
  47. package/dist/lib/node/chunk-UX3U4RU2.cjs +42 -0
  48. package/dist/lib/node/chunk-UX3U4RU2.cjs.map +7 -0
  49. package/dist/lib/node/{chunk-46S3JOES.cjs → chunk-WZR6OAN3.cjs} +9 -12
  50. package/dist/lib/node/chunk-WZR6OAN3.cjs.map +7 -0
  51. package/dist/lib/node/identity-created-7G5U7R36.cjs +44 -0
  52. package/dist/lib/node/identity-created-7G5U7R36.cjs.map +7 -0
  53. package/dist/lib/node/index.cjs +171 -3469
  54. package/dist/lib/node/index.cjs.map +4 -4
  55. package/dist/lib/node/intent-resolver-N2W2L6OL.cjs +522 -0
  56. package/dist/lib/node/intent-resolver-N2W2L6OL.cjs.map +7 -0
  57. package/dist/lib/node/meta.json +1 -1
  58. package/dist/lib/node/react-root-YD35W3VU.cjs +50 -0
  59. package/dist/lib/node/react-root-YD35W3VU.cjs.map +7 -0
  60. package/dist/lib/node/react-surface-QPLXK7DT.cjs +229 -0
  61. package/dist/lib/node/react-surface-QPLXK7DT.cjs.map +7 -0
  62. package/dist/lib/node/{meta.cjs → settings-TEELGWS4.cjs} +19 -13
  63. package/dist/lib/node/settings-TEELGWS4.cjs.map +7 -0
  64. package/dist/lib/node/spaces-ready-PZZQWS6T.cjs +210 -0
  65. package/dist/lib/node/spaces-ready-PZZQWS6T.cjs.map +7 -0
  66. package/dist/lib/node/state-WPZC4JXB.cjs +61 -0
  67. package/dist/lib/node/state-WPZC4JXB.cjs.map +7 -0
  68. package/dist/lib/node/types/index.cjs +18 -18
  69. package/dist/lib/node/types/index.cjs.map +1 -1
  70. package/dist/lib/node-esm/app-graph-builder-TKGLOK22.mjs +368 -0
  71. package/dist/lib/node-esm/app-graph-builder-TKGLOK22.mjs.map +7 -0
  72. package/dist/lib/node-esm/app-graph-serializer-HLX2JRNF.mjs +81 -0
  73. package/dist/lib/node-esm/app-graph-serializer-HLX2JRNF.mjs.map +7 -0
  74. package/dist/lib/node-esm/chunk-4UX5WGKJ.mjs +134 -0
  75. package/dist/lib/node-esm/chunk-4UX5WGKJ.mjs.map +7 -0
  76. package/dist/lib/node-esm/{chunk-CDZETPO7.mjs → chunk-AAQRELDK.mjs} +11 -15
  77. package/dist/lib/node-esm/chunk-AAQRELDK.mjs.map +7 -0
  78. package/dist/lib/node-esm/{chunk-2MNFEB23.mjs → chunk-ICCM4YRJ.mjs} +5 -7
  79. package/dist/lib/node-esm/chunk-ICCM4YRJ.mjs.map +7 -0
  80. package/dist/lib/node-esm/chunk-LA45TPAN.mjs +529 -0
  81. package/dist/lib/node-esm/chunk-LA45TPAN.mjs.map +7 -0
  82. package/dist/lib/node-esm/chunk-LGL4A5B5.mjs +23 -0
  83. package/dist/lib/node-esm/chunk-LGL4A5B5.mjs.map +7 -0
  84. package/dist/lib/node-esm/chunk-N6EAOMIS.mjs +1714 -0
  85. package/dist/lib/node-esm/chunk-N6EAOMIS.mjs.map +7 -0
  86. package/dist/lib/node-esm/identity-created-7THGZ7EW.mjs +29 -0
  87. package/dist/lib/node-esm/identity-created-7THGZ7EW.mjs.map +7 -0
  88. package/dist/lib/node-esm/index.mjs +186 -3481
  89. package/dist/lib/node-esm/index.mjs.map +4 -4
  90. package/dist/lib/node-esm/intent-resolver-L2TKJU4I.mjs +524 -0
  91. package/dist/lib/node-esm/intent-resolver-L2TKJU4I.mjs.map +7 -0
  92. package/dist/lib/node-esm/meta.json +1 -1
  93. package/dist/lib/node-esm/react-root-Q5MFDXZE.mjs +29 -0
  94. package/dist/lib/node-esm/react-root-Q5MFDXZE.mjs.map +7 -0
  95. package/dist/lib/node-esm/react-surface-RQQZ5BOG.mjs +232 -0
  96. package/dist/lib/node-esm/react-surface-RQQZ5BOG.mjs.map +7 -0
  97. package/dist/lib/node-esm/settings-KXYUZBLN.mjs +25 -0
  98. package/dist/lib/node-esm/settings-KXYUZBLN.mjs.map +7 -0
  99. package/dist/lib/node-esm/spaces-ready-MWNP3WBX.mjs +200 -0
  100. package/dist/lib/node-esm/spaces-ready-MWNP3WBX.mjs.map +7 -0
  101. package/dist/lib/node-esm/state-5GH2D5U4.mjs +48 -0
  102. package/dist/lib/node-esm/state-5GH2D5U4.mjs.map +7 -0
  103. package/dist/lib/node-esm/types/index.mjs +6 -6
  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 +21 -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 +1 -2
  138. package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts.map +1 -1
  139. package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts +6 -6
  140. package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts.map +1 -1
  141. package/dist/types/src/components/CreateDialog/CreateSpaceDialog.d.ts.map +1 -1
  142. package/dist/types/src/components/JoinDialog.d.ts.map +1 -1
  143. package/dist/types/src/components/SpacePluginSettings.d.ts.map +1 -1
  144. package/dist/types/src/components/SpacePresence.d.ts.map +1 -1
  145. package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.d.ts.map +1 -1
  146. package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.d.ts.map +1 -1
  147. package/dist/types/src/components/SyncStatus/SyncStatus.d.ts.map +1 -1
  148. package/dist/types/src/components/index.d.ts +2 -1
  149. package/dist/types/src/components/index.d.ts.map +1 -1
  150. package/dist/types/src/events.d.ts +5 -0
  151. package/dist/types/src/events.d.ts.map +1 -0
  152. package/dist/types/src/index.d.ts +3 -5
  153. package/dist/types/src/index.d.ts.map +1 -1
  154. package/dist/types/src/meta.d.ts +2 -4
  155. package/dist/types/src/meta.d.ts.map +1 -1
  156. package/dist/types/src/translations.d.ts +12 -0
  157. package/dist/types/src/translations.d.ts.map +1 -1
  158. package/dist/types/src/types/types.d.ts +7 -28
  159. package/dist/types/src/types/types.d.ts.map +1 -1
  160. package/dist/types/src/util.d.ts +7 -6
  161. package/dist/types/src/util.d.ts.map +1 -1
  162. package/dist/types/tsconfig.tsbuildinfo +1 -1
  163. package/package.json +38 -46
  164. package/src/SpacePlugin.tsx +114 -1412
  165. package/src/capabilities/app-graph-builder.ts +394 -0
  166. package/src/capabilities/app-graph-serializer.ts +73 -0
  167. package/src/capabilities/capabilities.ts +26 -0
  168. package/src/capabilities/identity-created.ts +26 -0
  169. package/src/capabilities/index.ts +17 -0
  170. package/src/capabilities/intent-resolver.ts +489 -0
  171. package/src/capabilities/react-root.tsx +20 -0
  172. package/src/capabilities/react-surface.tsx +226 -0
  173. package/src/capabilities/settings.ts +17 -0
  174. package/src/capabilities/spaces-ready.ts +230 -0
  175. package/src/capabilities/state.ts +45 -0
  176. package/src/components/AdvancedObjectSettings/AdvancedObjectSettings.tsx +72 -0
  177. package/src/components/AdvancedObjectSettings/ForeignKeys.tsx +51 -0
  178. package/src/components/AdvancedObjectSettings/index.ts +5 -0
  179. package/src/components/AwaitingObject.tsx +5 -11
  180. package/src/components/{DefaultObjectSettings.tsx → BaseObjectSettings.tsx} +2 -2
  181. package/src/components/CreateDialog/CreateObjectDialog.tsx +19 -19
  182. package/src/components/CreateDialog/CreateObjectPanel.tsx +136 -99
  183. package/src/components/CreateDialog/CreateSpaceDialog.tsx +10 -8
  184. package/src/components/JoinDialog.tsx +27 -19
  185. package/src/components/SpacePluginSettings.tsx +5 -10
  186. package/src/components/SpacePresence.tsx +7 -7
  187. package/src/components/SpaceSettings/SpaceSettingsDialog.tsx +16 -1
  188. package/src/components/SpaceSettings/SpaceSettingsPanel.tsx +3 -4
  189. package/src/components/SyncStatus/InlineSyncStatus.tsx +2 -2
  190. package/src/components/SyncStatus/SyncStatus.tsx +2 -1
  191. package/src/components/index.ts +2 -1
  192. package/src/events.ts +12 -0
  193. package/src/index.ts +3 -7
  194. package/src/meta.ts +2 -3
  195. package/src/translations.ts +4 -0
  196. package/src/types/types.ts +12 -51
  197. package/src/util.tsx +38 -28
  198. package/dist/lib/browser/chunk-54VE4GTA.mjs.map +0 -7
  199. package/dist/lib/browser/chunk-73BCBSLP.mjs +0 -15
  200. package/dist/lib/browser/chunk-73BCBSLP.mjs.map +0 -7
  201. package/dist/lib/browser/meta.mjs +0 -11
  202. package/dist/lib/browser/meta.mjs.map +0 -7
  203. package/dist/lib/node/chunk-46S3JOES.cjs.map +0 -7
  204. package/dist/lib/node/chunk-YF2AQ7KP.cjs.map +0 -7
  205. package/dist/lib/node/meta.cjs.map +0 -7
  206. package/dist/lib/node-esm/chunk-2MNFEB23.mjs.map +0 -7
  207. package/dist/lib/node-esm/chunk-CDZETPO7.mjs.map +0 -7
  208. package/dist/lib/node-esm/meta.mjs +0 -12
  209. package/dist/lib/node-esm/meta.mjs.map +0 -7
  210. package/dist/types/src/components/DefaultObjectSettings.d.ts +0 -7
  211. package/dist/types/src/components/DefaultObjectSettings.d.ts.map +0 -1
@@ -5,13 +5,7 @@
5
5
  import { CheckCircle, CircleDashed, CircleNotch } from '@phosphor-icons/react';
6
6
  import React, { useCallback, useEffect, useState } from 'react';
7
7
 
8
- import {
9
- useResolvePlugin,
10
- parseNavigationPlugin,
11
- NavigationAction,
12
- useIntentDispatcher,
13
- createIntent,
14
- } from '@dxos/app-framework';
8
+ import { createIntent, LayoutAction, useIntentDispatcher, useLayout } from '@dxos/app-framework';
15
9
  import { useClient } from '@dxos/react-client';
16
10
  import { Filter, fullyQualifiedId, useQuery } from '@dxos/react-client/echo';
17
11
  import { Button, Toast, useTranslation } from '@dxos/react-ui';
@@ -29,7 +23,7 @@ export const AwaitingObject = ({ id }: { id: string }) => {
29
23
  const [found, setFound] = useState(false);
30
24
  const { t } = useTranslation(SPACE_PLUGIN);
31
25
  const { dispatchPromise: dispatch } = useIntentDispatcher();
32
- const navigationPlugin = useResolvePlugin(parseNavigationPlugin);
26
+ const layout = useLayout();
33
27
 
34
28
  const client = useClient();
35
29
  const objects = useQuery(client.spaces, Filter.all());
@@ -50,11 +44,11 @@ export const AwaitingObject = ({ id }: { id: string }) => {
50
44
  if (objects.findIndex((object) => fullyQualifiedId(object) === id) > -1) {
51
45
  setFound(true);
52
46
 
53
- if (navigationPlugin?.provides.location.active.solo?.[0].id === id) {
47
+ if (layout.active.includes(id)) {
54
48
  setOpen(false);
55
49
  }
56
50
  }
57
- }, [id, objects, navigationPlugin]);
51
+ }, [id, objects, layout]);
58
52
 
59
53
  const handleClose = useCallback(
60
54
  async () => dispatch(createIntent(SpaceAction.WaitForObject, { id: undefined })),
@@ -62,7 +56,7 @@ export const AwaitingObject = ({ id }: { id: string }) => {
62
56
  );
63
57
 
64
58
  const handleNavigate = useCallback(() => {
65
- void dispatch(createIntent(NavigationAction.Open, { activeParts: { main: [id] } }));
59
+ void dispatch(createIntent(LayoutAction.Open, { part: 'main', subject: [id] }));
66
60
  void handleClose();
67
61
  }, [id, handleClose, dispatch]);
68
62
 
@@ -9,11 +9,11 @@ import { Input, useTranslation } from '@dxos/react-ui';
9
9
 
10
10
  import { SPACE_PLUGIN } from '../meta';
11
11
 
12
- export type DefaultObjectSettingsProps = {
12
+ export type BaseObjectSettingsProps = {
13
13
  object: ReactiveEchoObject<any>;
14
14
  };
15
15
 
16
- export const DefaultObjectSettings = ({ object }: DefaultObjectSettingsProps) => {
16
+ export const BaseObjectSettings = ({ object }: BaseObjectSettingsProps) => {
17
17
  const { t } = useTranslation(SPACE_PLUGIN);
18
18
  // TODO(burdon): Standardize forms.
19
19
  return (
@@ -5,7 +5,7 @@
5
5
  import { pipe } from 'effect';
6
6
  import React, { useCallback, useRef } from 'react';
7
7
 
8
- import { chain, createIntent, type MetadataResolver, NavigationAction, useIntentDispatcher } from '@dxos/app-framework';
8
+ import { chain, createIntent, LayoutAction, useIntentDispatcher } from '@dxos/app-framework';
9
9
  import { useClient } from '@dxos/react-client';
10
10
  import {
11
11
  getSpace,
@@ -24,7 +24,7 @@ import { CollectionType, SpaceAction } from '../../types';
24
24
  export const CREATE_OBJECT_DIALOG = `${SPACE_PLUGIN}/CreateObjectDialog`;
25
25
 
26
26
  export type CreateObjectDialogProps = Pick<CreateObjectPanelProps, 'schemas' | 'target' | 'typename' | 'name'> & {
27
- resolve?: MetadataResolver;
27
+ resolve?: (typename: string) => Record<string, any>;
28
28
  shouldNavigate?: (object: ReactiveObject<any>) => boolean;
29
29
  };
30
30
 
@@ -46,11 +46,11 @@ export const CreateObjectDialog = ({
46
46
  async ({
47
47
  schema,
48
48
  target: _target,
49
- name,
49
+ data,
50
50
  }: {
51
51
  schema: TypedObject;
52
52
  target: CreateObjectPanelProps['target'];
53
- name?: string;
53
+ data?: Record<string, any>;
54
54
  }) => {
55
55
  const target = isSpace(_target)
56
56
  ? (_target.properties[CollectionType.typename]?.target as CollectionType | undefined)
@@ -65,13 +65,13 @@ export const CreateObjectDialog = ({
65
65
  closeRef.current?.click();
66
66
 
67
67
  const space = isSpace(target) ? target : getSpace(target);
68
- const result = await dispatch(createObjectIntent({ name, space }));
68
+ const result = await dispatch(createObjectIntent(data, { space }));
69
69
  const object = result.data?.object;
70
70
  if (isReactiveObject(object)) {
71
71
  const addObjectIntent = createIntent(SpaceAction.AddObject, { target, object });
72
72
  const shouldNavigate = _shouldNavigate ?? (() => true);
73
73
  if (shouldNavigate(object)) {
74
- await dispatch(pipe(addObjectIntent, chain(NavigationAction.Open, {})));
74
+ await dispatch(pipe(addObjectIntent, chain(LayoutAction.Open, { part: 'main' })));
75
75
  } else {
76
76
  await dispatch(addObjectIntent);
77
77
  }
@@ -83,7 +83,7 @@ export const CreateObjectDialog = ({
83
83
  return (
84
84
  // TODO(wittjosiah): The tablist dialog pattern is copied from @dxos/plugin-manager.
85
85
  // Consider factoring it out to the tabs package.
86
- <Dialog.Content classNames='p-0 bs-content min-bs-[15rem] max-bs-full md:max-is-[40rem] overflow-hidden'>
86
+ <Dialog.Content classNames='p-0 bs-content max-bs-full md:max-is-[40rem] overflow-hidden'>
87
87
  <div role='none' className='flex justify-between pbs-2 pis-2 pie-2 @md:pbs-4 @md:pis-4 @md:pie-4'>
88
88
  <Dialog.Title>{t('create object dialog title')}</Dialog.Title>
89
89
  <Dialog.Close asChild>
@@ -92,18 +92,18 @@ export const CreateObjectDialog = ({
92
92
  </Button>
93
93
  </Dialog.Close>
94
94
  </div>
95
- <div className='p-4'>
96
- <CreateObjectPanel
97
- schemas={schemas}
98
- spaces={spaces}
99
- target={target}
100
- typename={typename}
101
- name={name}
102
- defaultSpaceId={client.spaces.default.id}
103
- resolve={resolve}
104
- onCreateObject={handleCreateObject}
105
- />
106
- </div>
95
+
96
+ <CreateObjectPanel
97
+ classNames='p-4'
98
+ schemas={schemas}
99
+ spaces={spaces}
100
+ target={target}
101
+ typename={typename}
102
+ name={name}
103
+ defaultSpaceId={client.spaces.default.id}
104
+ resolve={resolve}
105
+ onCreateObject={handleCreateObject}
106
+ />
107
107
  </Dialog.Content>
108
108
  );
109
109
  };
@@ -2,36 +2,61 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import React, { useCallback, useState } from 'react';
5
+ import React, { useCallback, useMemo, useState } from 'react';
6
6
 
7
- import { type MetadataResolver } from '@dxos/app-framework';
8
- import { type TypedObject, getObjectAnnotation, S } from '@dxos/echo-schema';
9
- import { type SpaceId, type Space, isSpace } from '@dxos/react-client/echo';
10
- import { Icon, IconButton, Input, toLocalizedString, useTranslation } from '@dxos/react-ui';
11
- import { Form, InputHeader } from '@dxos/react-ui-form';
7
+ import { Surface, isSurfaceAvailable, usePluginManager } from '@dxos/app-framework';
8
+ import { type TypedObject, getObjectAnnotation, type ObjectAnnotation, S } from '@dxos/echo-schema';
9
+ import { type SpaceId, type Space } from '@dxos/react-client/echo';
10
+ import { Icon, type ThemedClassName, toLocalizedString, useTranslation } from '@dxos/react-ui';
11
+ import { Form, type InputProps } from '@dxos/react-ui-form';
12
12
  import { SearchList } from '@dxos/react-ui-searchlist';
13
+ import { mx } from '@dxos/react-ui-theme';
13
14
  import { nonNullable, type MaybePromise } from '@dxos/util';
14
15
 
15
16
  import { SPACE_PLUGIN } from '../../meta';
16
17
  import { type CollectionType } from '../../types';
17
18
  import { getSpaceDisplayName } from '../../util';
18
19
 
19
- export type CreateObjectPanelProps = {
20
+ // TODO(ZaymonFC): Move this if you find yourself needing it elsewhere.
21
+ /**
22
+ * Creates a surface input component based on plugin context.
23
+ * @param baseData Additional data that will be merged with form data and passed to the surface.
24
+ * This allows providing more context to the surface than what's available from the form itself.
25
+ */
26
+ const useInputSurfaceLookup = (baseData?: Record<string, any>) => {
27
+ const pluginManager = usePluginManager();
28
+
29
+ return useCallback(
30
+ ({ prop, schema, inputProps }: { prop: string; schema: S.Schema<any>; inputProps: InputProps }) => {
31
+ const composedData = { prop, schema, ...baseData };
32
+
33
+ if (!isSurfaceAvailable(pluginManager.context, { role: 'form-input', data: composedData })) {
34
+ return undefined;
35
+ }
36
+
37
+ return <Surface role='form-input' data={composedData} {...inputProps} />;
38
+ },
39
+ [pluginManager, baseData],
40
+ );
41
+ };
42
+
43
+ export type CreateObjectPanelProps = ThemedClassName<{
20
44
  schemas: TypedObject[];
21
45
  spaces: Space[];
22
46
  typename?: string;
23
47
  target?: Space | CollectionType;
24
48
  name?: string;
25
49
  defaultSpaceId?: SpaceId;
26
- resolve?: MetadataResolver;
50
+ resolve?: (typename: string) => Record<string, any>;
27
51
  onCreateObject?: (params: {
28
52
  schema: TypedObject;
29
53
  target: Space | CollectionType;
30
- name?: string;
54
+ data: Record<string, any>;
31
55
  }) => MaybePromise<void>;
32
- };
56
+ }>;
33
57
 
34
58
  export const CreateObjectPanel = ({
59
+ classNames,
35
60
  schemas,
36
61
  spaces,
37
62
  typename: initialTypename,
@@ -45,125 +70,137 @@ export const CreateObjectPanel = ({
45
70
  const [typename, setTypename] = useState<string | undefined>(initialTypename);
46
71
  const [target, setTarget] = useState<Space | CollectionType | undefined>(initialTarget);
47
72
  const schema = schemas.find((schema) => getObjectAnnotation(schema)?.typename === typename);
48
- const options = schemas.map(getObjectAnnotation).filter(nonNullable);
49
-
50
- const handleClearSchema = useCallback(() => setTypename(undefined), []);
51
- const handleClearTarget = useCallback(() => setTarget(undefined), []);
73
+ const options: ObjectAnnotation[] = schemas
74
+ .map(getObjectAnnotation)
75
+ .filter(nonNullable)
76
+ .sort((a, b) => {
77
+ const nameA = t('typename label', { ns: a.typename, defaultValue: a.typename });
78
+ const nameB = t('typename label', { ns: b.typename, defaultValue: b.typename });
79
+ return nameA.localeCompare(nameB);
80
+ });
52
81
 
53
82
  const handleCreateObject = useCallback(
54
- async ({ name }: { name?: string }) => {
83
+ async (props: Record<string, any>) => {
55
84
  if (!schema || !target) {
56
85
  return;
57
86
  }
58
-
59
- await onCreateObject?.({ schema, target, name });
87
+ await onCreateObject?.({ schema, target, data: props });
60
88
  },
61
89
  [onCreateObject, schema, target],
62
90
  );
63
91
 
64
- // TODO(wittjosiah): All of these inputs should be rolled into a `Form` once it supports the necessary variants.
65
- const schemaInput = (
66
- <SearchList.Root label={t('schema input label')} classNames='flex flex-col grow overflow-hidden'>
92
+ const metadata = useMemo(() => {
93
+ if (!typename) {
94
+ return;
95
+ }
96
+ return resolve?.(typename);
97
+ }, [resolve, typename]);
98
+
99
+ const inputSurfaceLookup = useInputSurfaceLookup({ target });
100
+
101
+ const form = useMemo(() => {
102
+ // TODO(ZaymonFC): Move this default object creation schema somewhere?
103
+ const schema = (metadata?.creationSchema ?? S.Struct({ name: S.optional(S.String) })) as S.Schema<any>;
104
+
105
+ return (
106
+ <Form
107
+ classNames='!p-0'
108
+ autoFocus
109
+ values={{ name: initialName }}
110
+ schema={schema}
111
+ testId='create-object-form'
112
+ onSave={handleCreateObject}
113
+ lookupComponent={inputSurfaceLookup}
114
+ />
115
+ );
116
+ }, [initialName, handleCreateObject, metadata]);
117
+
118
+ // TODO(wittjosiah): These inputs should be rolled into a `Form` once it supports the necessary variants.
119
+ return (
120
+ <div role='form' className={mx('flex flex-col gap-2', classNames)}>
121
+ {!schema ? (
122
+ <SelectSchema options={options} resolve={resolve} onChange={setTypename} />
123
+ ) : !target ? (
124
+ <SelectSpace spaces={spaces} defaultSpaceId={defaultSpaceId} onChange={setTarget} />
125
+ ) : (
126
+ form
127
+ )}
128
+ </div>
129
+ );
130
+ };
131
+
132
+ const SelectSpace = ({
133
+ spaces,
134
+ defaultSpaceId,
135
+ onChange,
136
+ }: { onChange: (space: Space) => void } & Pick<CreateObjectPanelProps, 'spaces' | 'defaultSpaceId'>) => {
137
+ const { t } = useTranslation(SPACE_PLUGIN);
138
+
139
+ return (
140
+ <SearchList.Root label={t('space input label')} classNames='flex flex-col grow overflow-hidden'>
67
141
  <SearchList.Input
68
142
  autoFocus
69
- data-testid='create-object-form.schema-input'
70
- placeholder={t('schema input placeholder')}
143
+ data-testid='create-object-form.space-input'
144
+ placeholder={t('space input placeholder')}
71
145
  classNames='px-1 my-2'
72
146
  />
73
147
  <SearchList.Content classNames='max-bs-[24rem] overflow-auto'>
74
- {options.map((option) => (
75
- <SearchList.Item
76
- key={option.typename}
77
- value={t('typename label', { ns: option.typename, defaultValue: option.typename })}
78
- onSelect={() => setTypename(option.typename)}
79
- classNames='flex items-center gap-2'
80
- >
81
- <span className='flex gap-2 items-center grow truncate'>
82
- <Icon icon={resolve?.(option.typename).icon ?? 'ph--placeholder--regular'} size={5} />
83
- {t('typename label', { ns: option.typename, defaultValue: option.typename })}
84
- </span>
85
- </SearchList.Item>
86
- ))}
148
+ {spaces
149
+ .sort((a, b) => {
150
+ const aName = toLocalizedString(getSpaceDisplayName(a, { personal: a.id === defaultSpaceId }), t);
151
+ const bName = toLocalizedString(getSpaceDisplayName(b, { personal: b.id === defaultSpaceId }), t);
152
+ return aName.localeCompare(bName);
153
+ })
154
+ .map((space) => (
155
+ <SearchList.Item
156
+ key={space.id}
157
+ value={toLocalizedString(getSpaceDisplayName(space, { personal: space.id === defaultSpaceId }), t)}
158
+ onSelect={() => onChange(space)}
159
+ classNames='flex items-center gap-2'
160
+ >
161
+ <span className='grow truncate'>
162
+ {toLocalizedString(getSpaceDisplayName(space, { personal: space.id === defaultSpaceId }), t)}
163
+ </span>
164
+ </SearchList.Item>
165
+ ))}
87
166
  </SearchList.Content>
88
167
  </SearchList.Root>
89
168
  );
169
+ };
90
170
 
91
- const spaceInput = (
92
- <SearchList.Root label={t('space input label')} classNames='flex flex-col grow overflow-hidden'>
171
+ const SelectSchema = ({
172
+ options,
173
+ resolve,
174
+ onChange,
175
+ }: {
176
+ options: ObjectAnnotation[];
177
+ onChange: (type: string) => void;
178
+ } & Pick<CreateObjectPanelProps, 'resolve'>) => {
179
+ const { t } = useTranslation(SPACE_PLUGIN);
180
+
181
+ return (
182
+ <SearchList.Root label={t('schema input label')} classNames='flex flex-col grow overflow-hidden'>
93
183
  <SearchList.Input
94
184
  autoFocus
95
- data-testid='create-object-form.space-input'
96
- placeholder={t('space input placeholder')}
185
+ data-testid='create-object-form.schema-input'
186
+ placeholder={t('schema input placeholder')}
97
187
  classNames='px-1 my-2'
98
188
  />
99
189
  <SearchList.Content classNames='max-bs-[24rem] overflow-auto'>
100
- {spaces.map((space) => (
190
+ {options.map((option) => (
101
191
  <SearchList.Item
102
- key={space.id}
103
- value={toLocalizedString(getSpaceDisplayName(space, { personal: space.id === defaultSpaceId }), t)}
104
- onSelect={() => setTarget(space)}
192
+ key={option.typename}
193
+ value={t('typename label', { ns: option.typename, defaultValue: option.typename })}
194
+ onSelect={() => onChange(option.typename)}
105
195
  classNames='flex items-center gap-2'
106
196
  >
107
- <span className='grow truncate'>
108
- {toLocalizedString(getSpaceDisplayName(space, { personal: space.id === defaultSpaceId }), t)}
197
+ <span className='flex gap-2 items-center grow truncate'>
198
+ <Icon icon={resolve?.(option.typename).icon ?? 'ph--placeholder--regular'} size={5} />
199
+ {t('typename label', { ns: option.typename, defaultValue: option.typename })}
109
200
  </span>
110
201
  </SearchList.Item>
111
202
  ))}
112
203
  </SearchList.Content>
113
204
  </SearchList.Root>
114
205
  );
115
-
116
- const form = (
117
- <Form
118
- autoFocus
119
- values={{ name: initialName }}
120
- schema={S.Struct({ name: S.optional(S.String) })}
121
- testId='create-object-form'
122
- onSave={handleCreateObject}
123
- />
124
- );
125
-
126
- return (
127
- <div role='form' className='flex flex-col gap-2'>
128
- {target && (
129
- <div role='none'>
130
- <Input.Root>
131
- <InputHeader>
132
- <Input.Label>
133
- {t(isSpace(target) ? 'creating in space label' : 'creating in collection label')}
134
- </Input.Label>
135
- </InputHeader>
136
- <div role='none' className='flex gap-2'>
137
- <Input.TextInput
138
- disabled
139
- value={
140
- isSpace(target)
141
- ? toLocalizedString(getSpaceDisplayName(target, { personal: target.id === defaultSpaceId }), t)
142
- : target.name || t('unnamed collection label')
143
- }
144
- />
145
- <IconButton iconOnly icon='ph--x--regular' label={t('clear input label')} onClick={handleClearTarget} />
146
- </div>
147
- </Input.Root>
148
- </div>
149
- )}
150
- {schema && (
151
- <div role='none'>
152
- <Input.Root>
153
- <InputHeader>
154
- <Input.Label>{t('creating object type label')}</Input.Label>
155
- </InputHeader>
156
- <div role='none' className='flex gap-2'>
157
- <Input.TextInput
158
- disabled
159
- value={t('typename label', { ns: schema.typename, defaultValue: schema.typename })}
160
- />
161
- <IconButton iconOnly icon='ph--x--regular' label={t('clear input label')} onClick={handleClearSchema} />
162
- </div>
163
- </Input.Root>
164
- </div>
165
- )}
166
- {!schema ? schemaInput : !target ? spaceInput : form}
167
- </div>
168
- );
169
206
  };
@@ -2,9 +2,10 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
+ import { Effect } from 'effect';
5
6
  import React, { useCallback, useRef } from 'react';
6
7
 
7
- import { createIntent, useIntentDispatcher } from '@dxos/app-framework';
8
+ import { createIntent, LayoutAction, useIntentDispatcher } from '@dxos/app-framework';
8
9
  import { type S } from '@dxos/echo-schema';
9
10
  import { Button, Dialog, Icon, useTranslation } from '@dxos/react-ui';
10
11
  import { Form } from '@dxos/react-ui-form';
@@ -20,15 +21,16 @@ const initialValues: FormValues = { edgeReplication: true };
20
21
  export const CreateSpaceDialog = () => {
21
22
  const closeRef = useRef<HTMLButtonElement | null>(null);
22
23
  const { t } = useTranslation(SPACE_PLUGIN);
23
- const { dispatchPromise: dispatch } = useIntentDispatcher();
24
+ const { dispatch } = useIntentDispatcher();
24
25
 
25
26
  const handleCreateSpace = useCallback(
26
27
  async (data: FormValues) => {
27
- const result = await dispatch(createIntent(SpaceAction.Create, data));
28
- const target = result.data?.space;
29
- if (target) {
30
- await dispatch(createIntent(SpaceAction.OpenCreateObject, { target }));
31
- }
28
+ const program = Effect.gen(function* () {
29
+ const { space } = yield* dispatch(createIntent(SpaceAction.Create, data));
30
+ yield* dispatch(createIntent(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: space.id }));
31
+ yield* dispatch(createIntent(SpaceAction.OpenCreateObject, { target: space }));
32
+ });
33
+ await Effect.runPromise(program);
32
34
  },
33
35
  [dispatch],
34
36
  );
@@ -36,7 +38,7 @@ export const CreateSpaceDialog = () => {
36
38
  return (
37
39
  // TODO(wittjosiah): The tablist dialog pattern is copied from @dxos/plugin-manager.
38
40
  // Consider factoring it out to the tabs package.
39
- <Dialog.Content classNames='p-0 bs-content min-bs-[15rem] max-bs-full md:max-is-[40rem] overflow-hidden'>
41
+ <Dialog.Content classNames='p-0 bs-content min-bs-[16rem] max-bs-full md:max-is-[32rem] overflow-hidden'>
40
42
  <div role='none' className='flex justify-between pbs-2 pis-2 pie-2 @md:pbs-4 @md:pis-4 @md:pie-4'>
41
43
  <Dialog.Title>{t('create space dialog title')}</Dialog.Title>
42
44
  <Dialog.Close asChild>
@@ -4,12 +4,12 @@
4
4
 
5
5
  import React, { useCallback } from 'react';
6
6
 
7
- import { createIntent, LayoutAction, NavigationAction, useIntentDispatcher } from '@dxos/app-framework';
8
- import { useGraph } from '@dxos/plugin-graph';
7
+ import { createIntent, LayoutAction, useAppGraph, useIntentDispatcher } from '@dxos/app-framework';
8
+ import { log } from '@dxos/log';
9
9
  import { ObservabilityAction } from '@dxos/plugin-observability/types';
10
- import { useSpaces } from '@dxos/react-client/echo';
10
+ import { useClient } from '@dxos/react-client';
11
11
  import { type InvitationResult } from '@dxos/react-client/invitations';
12
- import { Dialog, useTranslation } from '@dxos/react-ui';
12
+ import { Dialog } from '@dxos/react-ui';
13
13
  import { JoinPanel, type JoinPanelProps } from '@dxos/shell/react';
14
14
 
15
15
  import { SPACE_PLUGIN } from '../meta';
@@ -21,47 +21,55 @@ export type JoinDialogProps = JoinPanelProps & {
21
21
  };
22
22
 
23
23
  export const JoinDialog = ({ navigableCollections, onDone, ...props }: JoinDialogProps) => {
24
- const { t } = useTranslation(SPACE_PLUGIN);
25
24
  const { dispatchPromise: dispatch } = useIntentDispatcher();
26
- const spaces = useSpaces();
27
- const { graph } = useGraph();
25
+ const client = useClient();
26
+ const { graph } = useAppGraph();
28
27
 
29
28
  const handleDone = useCallback(
30
29
  async (result: InvitationResult | null) => {
31
30
  if (result?.spaceKey) {
32
31
  await Promise.all([
33
32
  dispatch(
34
- createIntent(LayoutAction.SetLayout, {
35
- element: 'toast',
33
+ createIntent(LayoutAction.AddToast, {
34
+ part: 'toast',
36
35
  subject: {
37
36
  id: `${SPACE_PLUGIN}/join-success`,
38
37
  duration: 5_000,
39
- title: t('join success label'),
40
- closeLabel: t('dismiss label'),
38
+ title: ['join success label', { ns: SPACE_PLUGIN }],
39
+ closeLabel: ['dismiss label', { ns: SPACE_PLUGIN }],
41
40
  },
42
41
  }),
43
42
  ),
44
43
  dispatch(
45
- createIntent(LayoutAction.SetLayout, {
46
- element: 'dialog',
47
- state: false,
44
+ createIntent(LayoutAction.UpdateDialog, {
45
+ part: 'dialog',
46
+ options: {
47
+ state: false,
48
+ },
48
49
  }),
49
50
  ),
50
51
  ]);
51
52
  }
52
53
 
53
- const space = spaces.find(({ key }) => result?.spaceKey?.equals(key));
54
+ const space = result?.spaceKey ? client.spaces.get(result.spaceKey) : undefined;
55
+ if (!space) {
56
+ log.warn('Space not found', result?.spaceKey);
57
+ return;
58
+ }
59
+
60
+ await dispatch(createIntent(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: space.id }));
61
+
54
62
  // TODO(wittjosiah): If navigableCollections is false and there's no target,
55
63
  // should try to navigate to the first object of the space replicates.
56
64
  // Potentially this could also be done on the inviters side to ensure there's always a target.
57
65
  const target = result?.target || (navigableCollections ? space?.id : undefined);
58
66
  if (target) {
59
- // Wait for up to 1 second before navigating to the target node.
67
+ // Wait before navigating to the target node.
60
68
  // If the target has not yet replicated, this will trigger a loading toast.
61
69
  await graph.waitForPath({ target }).catch(() => {});
62
70
  await Promise.all([
63
- dispatch(createIntent(NavigationAction.Open, { activeParts: { main: [target] } })),
64
- dispatch(createIntent(NavigationAction.Expose, { id: target })),
71
+ dispatch(createIntent(LayoutAction.Open, { part: 'main', subject: [target] })),
72
+ dispatch(createIntent(LayoutAction.Expose, { part: 'navigation', subject: target })),
65
73
  ]);
66
74
  }
67
75
 
@@ -73,7 +81,7 @@ export const JoinDialog = ({ navigableCollections, onDone, ...props }: JoinDialo
73
81
  );
74
82
  }
75
83
  },
76
- [dispatch, spaces],
84
+ [dispatch, client, graph],
77
85
  );
78
86
 
79
87
  return (
@@ -4,25 +4,20 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { createIntent, useIntentDispatcher } from '@dxos/app-framework';
8
7
  import { Input, useTranslation } from '@dxos/react-ui';
9
- import { DeprecatedFormInput } from '@dxos/react-ui-form';
8
+ import { DeprecatedFormContainer, DeprecatedFormInput } from '@dxos/react-ui-form';
10
9
 
11
10
  import { SPACE_PLUGIN } from '../meta';
12
- import { SpaceAction, type SpaceSettingsProps } from '../types';
11
+ import { type SpaceSettingsProps } from '../types';
13
12
 
14
13
  export const SpacePluginSettings = ({ settings }: { settings: SpaceSettingsProps }) => {
15
14
  const { t } = useTranslation(SPACE_PLUGIN);
16
- const { dispatchPromise: dispatch } = useIntentDispatcher();
17
15
 
18
16
  return (
19
- <>
17
+ <DeprecatedFormContainer>
20
18
  <DeprecatedFormInput label={t('show hidden spaces label')}>
21
- <Input.Switch
22
- checked={settings.showHidden}
23
- onCheckedChange={(checked) => dispatch(createIntent(SpaceAction.ToggleHidden, { state: !!checked }))}
24
- />
19
+ <Input.Switch checked={settings.showHidden} onCheckedChange={(checked) => (settings.showHidden = !!checked)} />
25
20
  </DeprecatedFormInput>
26
- </>
21
+ </DeprecatedFormContainer>
27
22
  );
28
23
  };