@dxos/plugin-space 0.7.2 → 0.7.3-staging.0905f03

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 (99) hide show
  1. package/dist/lib/browser/{chunk-DJE2HYFV.mjs → chunk-FTKV32QZ.mjs} +9 -2
  2. package/dist/lib/browser/chunk-FTKV32QZ.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-OWZKSWMX.mjs → chunk-MWKXNS5S.mjs} +13 -3
  4. package/dist/lib/browser/{chunk-OWZKSWMX.mjs.map → chunk-MWKXNS5S.mjs.map} +3 -3
  5. package/dist/lib/browser/index.mjs +1167 -786
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/meta.mjs +3 -1
  9. package/dist/lib/browser/types/index.mjs +5 -3
  10. package/dist/lib/node/{chunk-FYWGZYJB.cjs → chunk-6SNOZF7Y.cjs} +18 -7
  11. package/dist/lib/node/chunk-6SNOZF7Y.cjs.map +7 -0
  12. package/dist/lib/node/{chunk-JFDDZI4Y.cjs → chunk-QNVEU2UD.cjs} +12 -4
  13. package/dist/lib/node/chunk-QNVEU2UD.cjs.map +7 -0
  14. package/dist/lib/node/index.cjs +1210 -839
  15. package/dist/lib/node/index.cjs.map +4 -4
  16. package/dist/lib/node/meta.cjs +7 -5
  17. package/dist/lib/node/meta.cjs.map +2 -2
  18. package/dist/lib/node/meta.json +1 -1
  19. package/dist/lib/node/types/index.cjs +14 -12
  20. package/dist/lib/node/types/index.cjs.map +2 -2
  21. package/dist/lib/node-esm/{chunk-MCEAI4CV.mjs → chunk-OHEAWSCA.mjs} +13 -3
  22. package/dist/lib/node-esm/{chunk-MCEAI4CV.mjs.map → chunk-OHEAWSCA.mjs.map} +3 -3
  23. package/dist/lib/node-esm/{chunk-DVUZ7A7G.mjs → chunk-UMV7XREB.mjs} +9 -2
  24. package/dist/lib/node-esm/chunk-UMV7XREB.mjs.map +7 -0
  25. package/dist/lib/node-esm/index.mjs +1167 -786
  26. package/dist/lib/node-esm/index.mjs.map +4 -4
  27. package/dist/lib/node-esm/meta.json +1 -1
  28. package/dist/lib/node-esm/meta.mjs +3 -1
  29. package/dist/lib/node-esm/types/index.mjs +5 -3
  30. package/dist/types/src/SpacePlugin.d.ts.map +1 -1
  31. package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts +9 -0
  32. package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts.map +1 -0
  33. package/dist/types/src/components/CreateDialog/CreateObjectDialog.stories.d.ts +10 -0
  34. package/dist/types/src/components/CreateDialog/CreateObjectDialog.stories.d.ts.map +1 -0
  35. package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts +22 -0
  36. package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts.map +1 -0
  37. package/dist/types/src/components/CreateDialog/CreateSpaceDialog.d.ts +3 -0
  38. package/dist/types/src/components/CreateDialog/CreateSpaceDialog.d.ts.map +1 -0
  39. package/dist/types/src/components/CreateDialog/index.d.ts +3 -0
  40. package/dist/types/src/components/CreateDialog/index.d.ts.map +1 -0
  41. package/dist/types/src/components/PopoverRenameObject.d.ts +1 -1
  42. package/dist/types/src/components/SpacePluginSettings.d.ts.map +1 -1
  43. package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.d.ts.map +1 -1
  44. package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.d.ts.map +1 -1
  45. package/dist/types/src/components/SyncStatus/InlineSyncStatus.d.ts +7 -0
  46. package/dist/types/src/components/SyncStatus/InlineSyncStatus.d.ts.map +1 -0
  47. package/dist/types/src/components/SyncStatus/InlineSyncStatus.stories.d.ts +6 -0
  48. package/dist/types/src/components/SyncStatus/InlineSyncStatus.stories.d.ts.map +1 -0
  49. package/dist/types/src/components/SyncStatus/Space.d.ts +8 -3
  50. package/dist/types/src/components/SyncStatus/Space.d.ts.map +1 -1
  51. package/dist/types/src/components/SyncStatus/SyncStatus.d.ts +3 -2
  52. package/dist/types/src/components/SyncStatus/SyncStatus.d.ts.map +1 -1
  53. package/dist/types/src/components/SyncStatus/SyncStatus.stories.d.ts +4 -4
  54. package/dist/types/src/components/SyncStatus/SyncStatus.stories.d.ts.map +1 -1
  55. package/dist/types/src/components/SyncStatus/SyncStatusDetail.stories.d.ts +9 -0
  56. package/dist/types/src/components/SyncStatus/SyncStatusDetail.stories.d.ts.map +1 -0
  57. package/dist/types/src/components/SyncStatus/index.d.ts +1 -0
  58. package/dist/types/src/components/SyncStatus/index.d.ts.map +1 -1
  59. package/dist/types/src/components/SyncStatus/sync-state.d.ts +5 -1
  60. package/dist/types/src/components/SyncStatus/sync-state.d.ts.map +1 -1
  61. package/dist/types/src/components/index.d.ts +1 -0
  62. package/dist/types/src/components/index.d.ts.map +1 -1
  63. package/dist/types/src/meta.d.ts +5 -0
  64. package/dist/types/src/meta.d.ts.map +1 -1
  65. package/dist/types/src/translations.d.ts +224 -0
  66. package/dist/types/src/translations.d.ts.map +1 -1
  67. package/dist/types/src/types/types.d.ts +14 -14
  68. package/dist/types/src/types/types.d.ts.map +1 -1
  69. package/dist/types/src/util.d.ts +3 -13
  70. package/dist/types/src/util.d.ts.map +1 -1
  71. package/package.json +38 -35
  72. package/src/SpacePlugin.tsx +203 -128
  73. package/src/components/AwaitingObject.tsx +2 -2
  74. package/src/components/CreateDialog/CreateObjectDialog.stories.tsx +83 -0
  75. package/src/components/CreateDialog/CreateObjectDialog.tsx +98 -0
  76. package/src/components/CreateDialog/CreateObjectPanel.tsx +169 -0
  77. package/src/components/CreateDialog/CreateSpaceDialog.tsx +57 -0
  78. package/src/components/CreateDialog/index.ts +6 -0
  79. package/src/components/PopoverRenameObject.tsx +1 -1
  80. package/src/components/SpacePluginSettings.tsx +3 -32
  81. package/src/components/SpaceSettings/SpaceSettingsDialog.tsx +5 -5
  82. package/src/components/SpaceSettings/SpaceSettingsPanel.tsx +2 -6
  83. package/src/components/SyncStatus/InlineSyncStatus.stories.tsx +57 -0
  84. package/src/components/SyncStatus/InlineSyncStatus.tsx +61 -0
  85. package/src/components/SyncStatus/Space.tsx +30 -6
  86. package/src/components/SyncStatus/SyncStatus.stories.tsx +15 -42
  87. package/src/components/SyncStatus/SyncStatus.tsx +32 -14
  88. package/src/components/SyncStatus/SyncStatusDetail.stories.tsx +85 -0
  89. package/src/components/SyncStatus/index.ts +1 -0
  90. package/src/components/SyncStatus/sync-state.ts +24 -0
  91. package/src/components/index.ts +1 -0
  92. package/src/meta.ts +6 -0
  93. package/src/translations.ts +15 -0
  94. package/src/types/types.ts +20 -16
  95. package/src/util.tsx +51 -141
  96. package/dist/lib/browser/chunk-DJE2HYFV.mjs.map +0 -7
  97. package/dist/lib/node/chunk-FYWGZYJB.cjs.map +0 -7
  98. package/dist/lib/node/chunk-JFDDZI4Y.cjs.map +0 -7
  99. package/dist/lib/node-esm/chunk-DVUZ7A7G.mjs.map +0 -7
@@ -4,11 +4,15 @@
4
4
 
5
5
  import React, { type HTMLAttributes, useEffect, useState } from 'react';
6
6
 
7
- import { Icon } from '@dxos/react-ui';
7
+ import { useClient } from '@dxos/react-client';
8
+ import { type SpaceId, useSpace } from '@dxos/react-client/echo';
9
+ import { Icon, toLocalizedString, useTranslation } from '@dxos/react-ui';
8
10
  import { type ThemedClassName } from '@dxos/react-ui';
9
11
  import { mx } from '@dxos/react-ui-theme';
10
12
 
11
13
  import { type Progress, type PeerSyncState } from './sync-state';
14
+ import { SPACE_PLUGIN } from '../../meta';
15
+ import { getSpaceDisplayName } from '../../util';
12
16
 
13
17
  export const SYNC_STALLED_TIMEOUT = 5_000;
14
18
 
@@ -41,24 +45,44 @@ const useActive = (count: number) => {
41
45
  return active;
42
46
  };
43
47
 
48
+ export type SpaceRowContainerProps = Omit<SpaceRowProps, 'spaceName'>;
49
+
50
+ export const SpaceRowContainer = ({ spaceId, state }: SpaceRowContainerProps) => {
51
+ const { t } = useTranslation(SPACE_PLUGIN);
52
+ const client = useClient();
53
+ const space = useSpace(spaceId);
54
+ if (!space) {
55
+ return null;
56
+ }
57
+
58
+ const spaceName = toLocalizedString(getSpaceDisplayName(space, { personal: space === client.spaces.default }), t);
59
+
60
+ return <SpaceRow spaceId={spaceId} spaceName={spaceName} state={state} />;
61
+ };
62
+
63
+ export type SpaceRowProps = {
64
+ spaceId: SpaceId;
65
+ spaceName: string;
66
+ state: PeerSyncState;
67
+ };
68
+
44
69
  export const SpaceRow = ({
45
70
  spaceId,
71
+ spaceName,
46
72
  state: { localDocumentCount, remoteDocumentCount, missingOnLocal, missingOnRemote },
47
- }: {
48
- spaceId: string;
49
- state: PeerSyncState;
50
- }) => {
73
+ }: SpaceRowProps) => {
51
74
  const downActive = useActive(localDocumentCount);
52
75
  const upActive = useActive(remoteDocumentCount);
53
76
 
54
77
  return (
55
78
  <div
56
- className={mx('flex items-center mx-[2px] gap-[2px] cursor-pointer', styles.barHover)}
79
+ className='flex items-center mx-0.5 gap-0.5 cursor-pointer'
57
80
  title={spaceId}
58
81
  onClick={() => {
59
82
  void navigator.clipboard.writeText(spaceId);
60
83
  }}
61
84
  >
85
+ <span className='is-1/2 truncate'>{spaceName}</span>
62
86
  <Icon
63
87
  icon='ph--arrow-fat-line-left--regular'
64
88
  size={3}
@@ -7,68 +7,41 @@ import '@dxos-theme';
7
7
  import { type Meta, type StoryObj } from '@storybook/react';
8
8
  import React from 'react';
9
9
 
10
- import { SpaceId } from '@dxos/keys';
11
10
  import { withTheme, withLayout } from '@dxos/storybook-utils';
12
11
 
13
- import { SyncStatusDetail, SyncStatusIndicator } from './SyncStatus';
14
- import { getSyncSummary, type SpaceSyncStateMap } from './sync-state';
12
+ import { SyncStatusIndicator } from './SyncStatus';
15
13
  import translations from '../../translations';
16
14
 
17
15
  const DefaultStory = (props: any) => {
18
16
  return (
19
- <div className='flex flex-col-reverse p-4 '>
17
+ <div className='flex flex-col-reverse p-4'>
20
18
  <SyncStatusIndicator {...props} />
21
19
  </div>
22
20
  );
23
21
  };
24
22
 
25
- const random = ({ min, max }: { min: number; max: number }) => min + Math.floor(Math.random() * (max - min));
23
+ const meta: Meta = {
24
+ title: 'plugins/plugin-space/SyncStatusIndicator',
25
+ component: SyncStatusIndicator,
26
+ render: DefaultStory,
27
+ decorators: [withTheme, withLayout({ fullscreen: true })],
28
+ parameters: { translations },
29
+ };
26
30
 
27
- const state: SpaceSyncStateMap = Array.from({ length: 5 }).reduce<SpaceSyncStateMap>((map) => {
28
- const total = random({ min: 10, max: 500 });
29
- const haveLocal = random({ min: 0, max: total });
30
- const haveRemote = random({ min: 0, max: total });
31
- map[SpaceId.random()] = {
32
- localDocumentCount: haveLocal,
33
- remoteDocumentCount: haveRemote,
34
- missingOnLocal: total - haveLocal,
35
- missingOnRemote: total - haveRemote,
36
- differentDocuments: 0,
37
- };
31
+ export default meta;
38
32
 
39
- return map;
40
- }, {});
33
+ type Story = StoryObj<typeof SyncStatusIndicator>;
41
34
 
42
- export const Default: StoryObj<typeof SyncStatusIndicator> = {
35
+ export const Default: Story = {
43
36
  args: {
44
- state,
37
+ state: {},
45
38
  saved: true,
46
39
  },
47
40
  };
48
41
 
49
- export const Saving: StoryObj<typeof SyncStatusIndicator> = {
42
+ export const Saving: Story = {
50
43
  args: {
51
- state,
44
+ state: {},
52
45
  saved: false,
53
46
  },
54
47
  };
55
-
56
- // TODO(wittjosiah): Separate story path for separate component.
57
- export const Detail: StoryObj<typeof SyncStatusDetail> = {
58
- render: SyncStatusDetail,
59
- args: {
60
- state,
61
- summary: getSyncSummary(state),
62
- classNames: 'm-2 w-[200px] border border-separator rounded-md',
63
- },
64
- };
65
-
66
- const meta: Meta = {
67
- title: 'plugins/plugin-space/SyncStatusIndicator',
68
- component: SyncStatusIndicator,
69
- render: DefaultStory,
70
- decorators: [withTheme, withLayout({ fullscreen: true })],
71
- parameters: { translations },
72
- };
73
-
74
- export default meta;
@@ -2,16 +2,17 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import React, { useEffect, useState } from 'react';
5
+ import React, { useCallback, useEffect, useState } from 'react';
6
6
 
7
7
  import { StatusBar } from '@dxos/plugin-status-bar';
8
8
  import { useClient } from '@dxos/react-client';
9
- import { Icon, Popover, useTranslation } from '@dxos/react-ui';
9
+ import { type SpaceId } from '@dxos/react-client/echo';
10
+ import { Icon, Input, Popover, useTranslation } from '@dxos/react-ui';
10
11
  import { type ThemedClassName } from '@dxos/react-ui';
11
12
  import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
12
13
  import { mx } from '@dxos/react-ui-theme';
13
14
 
14
- import { SpaceRow, SYNC_STALLED_TIMEOUT } from './Space';
15
+ import { SpaceRowContainer, SYNC_STALLED_TIMEOUT } from './Space';
15
16
  import { createClientSaveTracker } from './save-tracker';
16
17
  import { getIcon, getStatus } from './status';
17
18
  import { type PeerSyncState, type SpaceSyncStateMap, getSyncSummary, useSyncState } from './sync-state';
@@ -74,26 +75,43 @@ export const SyncStatusIndicator = ({ state, saved }: { state: SpaceSyncStateMap
74
75
  }
75
76
  };
76
77
 
77
- export const SyncStatusDetail = ({
78
- classNames,
79
- state,
80
- summary,
81
- debug,
82
- }: ThemedClassName<{
78
+ export type SyncStatusDetailProps = ThemedClassName<{
83
79
  state: SpaceSyncStateMap;
84
80
  summary: PeerSyncState;
85
81
  debug?: boolean;
86
- }>) => {
82
+ }>;
83
+
84
+ // TODO(wittjosiah): This currently does not show `differentDocuments` at all.
85
+ export const SyncStatusDetail = ({ classNames, state, summary, debug }: SyncStatusDetailProps) => {
86
+ const [showAll, setShowAll] = useState(false);
87
87
  const { t } = useTranslation(SPACE_PLUGIN);
88
- const entries = Object.entries(state).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
88
+ const entries = Object.entries(state)
89
+ .filter(([_, value]) => showAll || value.missingOnLocal + value.missingOnRemote > 0)
90
+ .toSorted(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
91
+
92
+ const handleCheckedChange = useCallback((state: boolean) => setShowAll(state), [setShowAll]);
89
93
 
90
94
  // TODO(burdon): Normalize to max document count?
91
95
  return (
92
- <div className={mx('flex flex-col gap-3 p-2 text-xs min-w-[16rem]', classNames)}>
93
- <h1>{t('sync status title')}</h1>
96
+ <div className={mx('flex flex-col gap-3 p-2 text-xs min-w-96', classNames)}>
97
+ <div role='none' className='flex items-center'>
98
+ <h1 className='flex-1'>{t('sync status title')}</h1>
99
+ <div className='flex items-center gap-2'>
100
+ <Input.Root>
101
+ <Input.Label classNames='text-xs'>{t('show all label')}</Input.Label>
102
+ <Input.Checkbox checked={showAll} onCheckedChange={handleCheckedChange} />
103
+ </Input.Root>
104
+ </div>
105
+ </div>
94
106
  <div className='flex flex-col gap-2'>
107
+ {entries.length === 0 && (
108
+ <div role='none' className='flex justify-center'>
109
+ {/* TODO(wittjosiah): This text should be updated once status includes different documents. */}
110
+ {t('no sync status label')}
111
+ </div>
112
+ )}
95
113
  {entries.map(([spaceId, state]) => (
96
- <SpaceRow key={spaceId} spaceId={spaceId} state={state} />
114
+ <SpaceRowContainer key={spaceId} spaceId={spaceId as SpaceId} state={state} />
97
115
  ))}
98
116
  </div>
99
117
  {debug && <SyntaxHighlighter language='json'>{JSON.stringify(summary, null, 2)}</SyntaxHighlighter>}
@@ -0,0 +1,85 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import { type Meta, type StoryObj } from '@storybook/react';
8
+ import React from 'react';
9
+
10
+ import { faker } from '@dxos/random';
11
+ import { useStoryClientData, withClientProvider } from '@dxos/react-client/testing';
12
+ import { withTheme, withLayout } from '@dxos/storybook-utils';
13
+
14
+ import { SyncStatusDetail } from './SyncStatus';
15
+ import { getSyncSummary, type SpaceSyncStateMap } from './sync-state';
16
+ import translations from '../../translations';
17
+
18
+ const random = ({ min, max }: { min: number; max: number }) => min + Math.floor(Math.random() * (max - min));
19
+
20
+ const meta: Meta = {
21
+ title: 'plugins/plugin-space/SyncStatusDetail',
22
+ component: SyncStatusDetail,
23
+ render: (args) => {
24
+ const { state } = useStoryClientData<{ state: SpaceSyncStateMap }>();
25
+
26
+ return <SyncStatusDetail {...args} state={state} summary={getSyncSummary(state)} />;
27
+ },
28
+ decorators: [
29
+ withTheme,
30
+ withLayout({ fullscreen: true }),
31
+ withClientProvider({
32
+ createIdentity: true,
33
+ onIdentityCreated: async ({ client }) => {
34
+ const spaces = await Promise.all(
35
+ Array.from({ length: 10 }).map(() => client.spaces.create({ name: faker.company.name() })),
36
+ );
37
+
38
+ const state: SpaceSyncStateMap = spaces.reduce<SpaceSyncStateMap>((map, space, i) => {
39
+ if (i > 4) {
40
+ const total = random({ min: 10, max: 500 });
41
+ map[space.id] = {
42
+ localDocumentCount: total,
43
+ remoteDocumentCount: total,
44
+ missingOnLocal: 0,
45
+ missingOnRemote: 0,
46
+ differentDocuments: 0,
47
+ };
48
+ return map;
49
+ }
50
+
51
+ const total = random({ min: 10, max: 500 });
52
+ const haveLocal = random({ min: 0, max: total });
53
+ const haveRemote = random({ min: 0, max: total });
54
+ map[space.id] = {
55
+ localDocumentCount: haveLocal,
56
+ remoteDocumentCount: haveRemote,
57
+ missingOnLocal: total - haveLocal,
58
+ missingOnRemote: total - haveRemote,
59
+ differentDocuments: 0,
60
+ };
61
+
62
+ return map;
63
+ }, {});
64
+
65
+ return { state };
66
+ },
67
+ }),
68
+ ],
69
+ parameters: { translations },
70
+ args: {
71
+ classNames: 'm-2 border border-separator rounded-md',
72
+ },
73
+ };
74
+
75
+ export default meta;
76
+
77
+ type Story = StoryObj<typeof SyncStatusDetail>;
78
+
79
+ export const Default: Story = {};
80
+
81
+ export const Empty: Story = {
82
+ render: (args) => {
83
+ return <SyncStatusDetail {...args} state={{}} />;
84
+ },
85
+ };
@@ -2,4 +2,5 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
+ export * from './InlineSyncStatus';
5
6
  export * from './SyncStatus';
@@ -75,3 +75,27 @@ export const useSyncState = (): SpaceSyncStateMap => {
75
75
 
76
76
  return spaceState;
77
77
  };
78
+
79
+ /**
80
+ * Hook Subscribes to sync state for a single space.
81
+ */
82
+ // TODO(wittjosiah): Reconcile w/ useSyncState.
83
+ export const useSpaceSyncState = (space: Space): PeerSyncState | undefined => {
84
+ const [spaceState, setSpaceState] = useState<PeerSyncState>();
85
+
86
+ useEffect(() => {
87
+ const ctx = new Context();
88
+ space.crud.subscribeToSyncState(ctx, ({ peers = [] }) => {
89
+ const syncState = peers.find((state) => isEdgePeerId(state.peerId, space.id));
90
+ if (syncState) {
91
+ setSpaceState(syncState);
92
+ }
93
+ });
94
+
95
+ return () => {
96
+ void ctx.dispose();
97
+ };
98
+ }, [space]);
99
+
100
+ return spaceState;
101
+ };
@@ -3,6 +3,7 @@
3
3
  //
4
4
 
5
5
  export * from './AwaitingObject';
6
+ export * from './CreateDialog';
6
7
  export * from './CollectionMain';
7
8
  export * from './CollectionSection';
8
9
  export * from './DefaultObjectSettings';
package/src/meta.ts CHANGED
@@ -15,6 +15,7 @@ export default {
15
15
 
16
16
  const SPACE_ACTION = `${SPACE_PLUGIN}/action`;
17
17
  export enum SpaceAction {
18
+ OPEN_CREATE_SPACE = `${SPACE_ACTION}/open-create-space`,
18
19
  CREATE = `${SPACE_ACTION}/create`,
19
20
  JOIN = `${SPACE_ACTION}/join`,
20
21
  SHARE = `${SPACE_ACTION}/share`,
@@ -24,6 +25,7 @@ export enum SpaceAction {
24
25
  OPEN = `${SPACE_ACTION}/open`,
25
26
  CLOSE = `${SPACE_ACTION}/close`,
26
27
  MIGRATE = `${SPACE_ACTION}/migrate`,
28
+ OPEN_CREATE_OBJECT = `${SPACE_ACTION}/open-create-object`,
27
29
  ADD_OBJECT = `${SPACE_ACTION}/add-object`,
28
30
  REMOVE_OBJECTS = `${SPACE_ACTION}/remove-objects`,
29
31
  RENAME_OBJECT = `${SPACE_ACTION}/rename-object`,
@@ -32,3 +34,7 @@ export enum SpaceAction {
32
34
  TOGGLE_HIDDEN = `${SPACE_ACTION}/toggle-hidden`,
33
35
  OPEN_SETTINGS = `${SPACE_ACTION}/open-settings`,
34
36
  }
37
+
38
+ export enum CollectionAction {
39
+ CREATE = 'dxos.org/plugin/collection/action/create',
40
+ }
@@ -3,10 +3,14 @@
3
3
  //
4
4
 
5
5
  import { SPACE_PLUGIN } from './meta';
6
+ import { CollectionType } from './types';
6
7
 
7
8
  export default [
8
9
  {
9
10
  'en-US': {
11
+ [CollectionType.typename]: {
12
+ 'typename label': 'Collection',
13
+ },
10
14
  [SPACE_PLUGIN]: {
11
15
  'plugin name': 'Spaces',
12
16
  'first run message': 'Nothing selected.',
@@ -104,6 +108,17 @@ export default [
104
108
  'open space settings label': 'Space Settings',
105
109
  'members tab label': 'Members',
106
110
  'settings tab label': 'Settings',
111
+ 'syncing message': 'Space syncing',
112
+ 'show all label': 'Show all',
113
+ 'no sync status label': 'No space with missing objects.',
114
+ 'create space dialog title': 'Create Space',
115
+ 'create object dialog title': 'Create Object',
116
+ 'space input placeholder': 'Select space',
117
+ 'schema input placeholder': 'Select object type',
118
+ 'creating object type label': 'Type',
119
+ 'creating in space label': 'In Space',
120
+ 'creating in collection label': 'In Collection',
121
+ 'clear input label': 'Clear',
107
122
  },
108
123
  },
109
124
  },
@@ -12,12 +12,10 @@ import type {
12
12
  TranslationsProvides,
13
13
  Plugin,
14
14
  } from '@dxos/app-framework';
15
- import { type Expando } from '@dxos/echo-schema';
16
- import { type SchemaProvides } from '@dxos/plugin-client';
15
+ import { AST, S, type AbstractTypedObject, type Expando } from '@dxos/echo-schema';
17
16
  import { type PanelProvides } from '@dxos/plugin-deck/types';
18
17
  import { type PublicKey } from '@dxos/react-client';
19
18
  import { type Space } from '@dxos/react-client/echo';
20
- import { type Label } from '@dxos/react-ui';
21
19
  import { type ComplexMap } from '@dxos/util';
22
20
 
23
21
  export const SPACE_DIRECTORY_HANDLE = 'dxos.org/plugin/space/directory';
@@ -61,6 +59,12 @@ export type PluginState = {
61
59
  * Determined by whether or not there is an available plugin that can render a collection.
62
60
  */
63
61
  navigableCollections: boolean;
62
+
63
+ /**
64
+ * Tracks whether setting edge replication as default has been run on spaces.
65
+ */
66
+ // TODO(wittjosiah): Systematic way to handle migrations of state outside of spaces.
67
+ enabledEdgeReplication: boolean;
64
68
  };
65
69
 
66
70
  export type SpaceSettingsProps = {
@@ -68,24 +72,19 @@ export type SpaceSettingsProps = {
68
72
  * Show closed spaces.
69
73
  */
70
74
  showHidden?: boolean;
71
-
72
- /**
73
- * Action to perform when a space is created.
74
- */
75
- onSpaceCreate?: string;
76
75
  };
77
76
 
78
- export type SpaceInitProvides = {
79
- space: {
80
- onSpaceCreate: {
81
- label: Label;
82
- action: string;
83
- };
77
+ export type SchemaProvides = {
78
+ echo: {
79
+ schema?: AbstractTypedObject[];
80
+ system?: AbstractTypedObject[];
84
81
  };
85
82
  };
86
83
 
87
- export const parseSpaceInitPlugin = (plugin: Plugin) =>
88
- typeof (plugin.provides as any).space?.onSpaceCreate === 'object' ? (plugin as Plugin<SpaceInitProvides>) : undefined;
84
+ export const parseSchemaPlugin = (plugin?: Plugin) =>
85
+ Array.isArray((plugin?.provides as any).echo?.schema) || Array.isArray((plugin?.provides as any).echo?.system)
86
+ ? (plugin as Plugin<SchemaProvides>)
87
+ : undefined;
89
88
 
90
89
  export type SpacePluginProvides = SurfaceProvides &
91
90
  IntentResolverProvides &
@@ -113,3 +112,8 @@ export interface TypedObjectSerializer<T extends Expando = Expando> {
113
112
  */
114
113
  deserialize(params: { content: string; space: Space; newId?: boolean }): Promise<T>;
115
114
  }
115
+
116
+ export const SpaceForm = S.Struct({
117
+ name: S.optional(S.String.annotations({ [AST.TitleAnnotationId]: 'Name' })),
118
+ edgeReplication: S.Boolean.annotations({ [AST.TitleAnnotationId]: 'Enable EDGE Replication' }),
119
+ });