@dxos/plugin-space 0.7.3-staging.cc8dd3e → 0.7.3

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 (31) hide show
  1. package/dist/lib/browser/index.mjs +77 -76
  2. package/dist/lib/browser/index.mjs.map +3 -3
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +63 -61
  5. package/dist/lib/node/index.cjs.map +3 -3
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +77 -76
  8. package/dist/lib/node-esm/index.mjs.map +3 -3
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/SpacePlugin.d.ts.map +1 -1
  11. package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts.map +1 -1
  12. package/dist/types/src/components/JoinDialog.d.ts +1 -1
  13. package/dist/types/src/components/JoinDialog.d.ts.map +1 -1
  14. package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.d.ts.map +1 -1
  15. package/dist/types/src/components/SyncStatus/InlineSyncStatus.d.ts +1 -0
  16. package/dist/types/src/components/SyncStatus/InlineSyncStatus.d.ts.map +1 -1
  17. package/dist/types/src/components/SyncStatus/InlineSyncStatus.stories.d.ts +6 -0
  18. package/dist/types/src/components/SyncStatus/InlineSyncStatus.stories.d.ts.map +1 -0
  19. package/dist/types/src/components/SyncStatus/SyncStatus.stories.d.ts +3 -2
  20. package/dist/types/src/components/SyncStatus/SyncStatus.stories.d.ts.map +1 -1
  21. package/dist/types/src/components/SyncStatus/SyncStatusDetail.stories.d.ts +3 -2
  22. package/dist/types/src/components/SyncStatus/SyncStatusDetail.stories.d.ts.map +1 -1
  23. package/package.json +38 -38
  24. package/src/SpacePlugin.tsx +35 -53
  25. package/src/components/CreateDialog/CreateObjectDialog.tsx +3 -2
  26. package/src/components/JoinDialog.tsx +3 -1
  27. package/src/components/SpaceSettings/SpaceSettingsDialog.tsx +4 -4
  28. package/src/components/SyncStatus/InlineSyncStatus.stories.tsx +57 -0
  29. package/src/components/SyncStatus/InlineSyncStatus.tsx +20 -4
  30. package/src/components/SyncStatus/SyncStatus.stories.tsx +15 -13
  31. package/src/components/SyncStatus/SyncStatusDetail.stories.tsx +10 -8
@@ -6,7 +6,7 @@ import React, { useCallback, useRef } from 'react';
6
6
 
7
7
  import { type MetadataResolver, NavigationAction, useIntentDispatcher } from '@dxos/app-framework';
8
8
  import { useClient } from '@dxos/react-client';
9
- import { type AbstractTypedObject, isReactiveObject, isSpace, useSpaces } from '@dxos/react-client/echo';
9
+ import { type AbstractTypedObject, getSpace, isReactiveObject, isSpace, useSpaces } from '@dxos/react-client/echo';
10
10
  import { Button, Dialog, Icon, useTranslation } from '@dxos/react-ui';
11
11
 
12
12
  import { CreateObjectPanel, type CreateObjectPanelProps } from './CreateObjectPanel';
@@ -52,7 +52,8 @@ export const CreateObjectDialog = ({
52
52
  // NOTE: Must close before navigating or attention won't follow object.
53
53
  closeRef.current?.click();
54
54
 
55
- const result = await dispatch({ action: createObjectAction, data: { name } });
55
+ const space = isSpace(target) ? target : getSpace(target);
56
+ const result = await dispatch({ action: createObjectAction, data: { name, space } });
56
57
  const object = result?.data;
57
58
  if (isReactiveObject(object)) {
58
59
  await dispatch([
@@ -18,7 +18,7 @@ export type JoinDialogProps = JoinPanelProps & {
18
18
  navigableCollections?: boolean;
19
19
  };
20
20
 
21
- export const JoinDialog = ({ navigableCollections, ...props }: JoinDialogProps) => {
21
+ export const JoinDialog = ({ navigableCollections, onDone, ...props }: JoinDialogProps) => {
22
22
  const { t } = useTranslation(SPACE_PLUGIN);
23
23
  const dispatch = useIntentDispatcher();
24
24
  const spaces = useSpaces();
@@ -75,6 +75,8 @@ export const JoinDialog = ({ navigableCollections, ...props }: JoinDialogProps)
75
75
  ]);
76
76
  }
77
77
 
78
+ await onDone?.(result);
79
+
78
80
  if (space) {
79
81
  await dispatch({
80
82
  action: ObservabilityAction.SEND_EVENT,
@@ -5,9 +5,9 @@
5
5
  import React, { useState } from 'react';
6
6
 
7
7
  import { useClient } from '@dxos/react-client';
8
- import { Button, Dialog, Icon, toLocalizedString, useTranslation } from '@dxos/react-ui';
8
+ import { Button, Clipboard, Dialog, Icon, toLocalizedString, useTranslation } from '@dxos/react-ui';
9
9
  import { Tabs, type TabsRootProps, type TabsActivePart } from '@dxos/react-ui-tabs';
10
- import { ClipboardProvider, SpacePanel, type SpacePanelProps } from '@dxos/shell/react';
10
+ import { SpacePanel, type SpacePanelProps } from '@dxos/shell/react';
11
11
 
12
12
  import { SpaceSettingsPanel, type SpaceSettingsPanelProps } from './SpaceSettingsPanel';
13
13
  import { SPACE_PLUGIN } from '../../meta';
@@ -92,9 +92,9 @@ export const SpaceSettingsDialog = ({
92
92
 
93
93
  {/* TODO(wittjosiah): Weird focus ring when tabpanel is focused. */}
94
94
  <Tabs.Tabpanel value='members' classNames='pli-3 @md:pli-5 max-bs-dvh overflow-y-auto'>
95
- <ClipboardProvider>
95
+ <Clipboard.Provider>
96
96
  <SpacePanel space={space} hideHeading target={target} createInvitationUrl={createInvitationUrl} />
97
- </ClipboardProvider>
97
+ </Clipboard.Provider>
98
98
  </Tabs.Tabpanel>
99
99
  </Tabs.Viewport>
100
100
  </Tabs.Root>
@@ -0,0 +1,57 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import { type Meta } from '@storybook/react';
8
+ import React, { useEffect, useState } from 'react';
9
+
10
+ import { withTheme, withLayout } from '@dxos/storybook-utils';
11
+ import { range } from '@dxos/util';
12
+
13
+ import { InlineSyncStatusIndicator } from './InlineSyncStatus';
14
+ import translations from '../../translations';
15
+
16
+ const DefaultStory = () => {
17
+ const [spaces, setSpaces] = useState(
18
+ new Map<string, boolean>(range(8).map((i) => [`space-${i + 1}`, Math.random() > 0.5])),
19
+ );
20
+
21
+ useEffect(() => {
22
+ const t = setInterval(
23
+ () => {
24
+ setSpaces((spaces) => {
25
+ const space = Array.from(spaces.keys())[Math.floor(Math.random() * spaces.size)];
26
+ spaces.set(space, !spaces.get(space));
27
+ return new Map(spaces);
28
+ });
29
+ },
30
+ 2_000 + Math.random() * 3_000,
31
+ );
32
+ return () => clearInterval(t);
33
+ });
34
+
35
+ return (
36
+ <div className='flex flex-col p-2 w-[200px]'>
37
+ {Array.from(spaces.entries()).map(([space, sync]) => (
38
+ <div key={space} className='flex items-center'>
39
+ <div className='grow'>{space}</div>
40
+ {sync && <InlineSyncStatusIndicator />}
41
+ </div>
42
+ ))}
43
+ </div>
44
+ );
45
+ };
46
+
47
+ const meta: Meta = {
48
+ title: 'plugins/plugin-space/InlineSyncStatusIndicator',
49
+ component: InlineSyncStatusIndicator,
50
+ render: DefaultStory,
51
+ decorators: [withTheme, withLayout({ fullscreen: true })],
52
+ parameters: { translations },
53
+ };
54
+
55
+ export default meta;
56
+
57
+ export const Default = {};
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import React, { useEffect, useState } from 'react';
5
+ import React, { type CSSProperties, useEffect, useMemo, useState } from 'react';
6
6
 
7
7
  import { QueryEdgeStatusResponse } from '@dxos/protocols/proto/dxos/client/services';
8
8
  import { EdgeReplicationSetting } from '@dxos/protocols/proto/dxos/echo/metadata';
@@ -27,8 +27,6 @@ const useEdgeStatus = (): QueryEdgeStatusResponse.EdgeStatus => {
27
27
  };
28
28
 
29
29
  export const InlineSyncStatus = ({ space }: { space: Space }) => {
30
- const { t } = useTranslation(SPACE_PLUGIN);
31
-
32
30
  const connectedToEdge = useEdgeStatus() === QueryEdgeStatusResponse.EdgeStatus.CONNECTED;
33
31
  // TODO(wittjosiah): This is not reactive.
34
32
  const edgeSyncEnabled = space.internal.data.edgeReplication === EdgeReplicationSetting.ENABLED;
@@ -37,9 +35,27 @@ export const InlineSyncStatus = ({ space }: { space: Space }) => {
37
35
  return null;
38
36
  }
39
37
 
38
+ return <InlineSyncStatusIndicator />;
39
+ };
40
+
41
+ export const InlineSyncStatusIndicator = () => {
42
+ const { t } = useTranslation(SPACE_PLUGIN);
43
+ const animationProps = useMemo<CSSProperties>(
44
+ () => ({
45
+ // Synchronize animations.
46
+ animationDelay: `-${Date.now() % 2_000}ms`,
47
+ }),
48
+ [],
49
+ );
50
+
40
51
  return (
41
52
  <div role='status' aria-label={t('syncing message')} className='flex items-center'>
42
- <Icon icon='ph--arrows-clockwise--regular' size={3} classNames='animate-spin' />
53
+ <Icon
54
+ icon='ph--circle-notch--regular'
55
+ size={3}
56
+ style={animationProps}
57
+ classNames='text-subdued animate-[spin_2s_linear_infinite]'
58
+ />
43
59
  </div>
44
60
  );
45
61
  };
@@ -14,32 +14,34 @@ import translations from '../../translations';
14
14
 
15
15
  const DefaultStory = (props: any) => {
16
16
  return (
17
- <div className='flex flex-col-reverse p-4 '>
17
+ <div className='flex flex-col-reverse p-4'>
18
18
  <SyncStatusIndicator {...props} />
19
19
  </div>
20
20
  );
21
21
  };
22
22
 
23
- export const Default: StoryObj<typeof SyncStatusIndicator> = {
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
+ };
30
+
31
+ export default meta;
32
+
33
+ type Story = StoryObj<typeof SyncStatusIndicator>;
34
+
35
+ export const Default: Story = {
24
36
  args: {
25
37
  state: {},
26
38
  saved: true,
27
39
  },
28
40
  };
29
41
 
30
- export const Saving: StoryObj<typeof SyncStatusIndicator> = {
42
+ export const Saving: Story = {
31
43
  args: {
32
44
  state: {},
33
45
  saved: false,
34
46
  },
35
47
  };
36
-
37
- const meta: Meta = {
38
- title: 'plugins/plugin-space/SyncStatusIndicator',
39
- component: SyncStatusIndicator,
40
- render: DefaultStory,
41
- decorators: [withTheme, withLayout({ fullscreen: true })],
42
- parameters: { translations },
43
- };
44
-
45
- export default meta;
@@ -17,14 +17,6 @@ import translations from '../../translations';
17
17
 
18
18
  const random = ({ min, max }: { min: number; max: number }) => min + Math.floor(Math.random() * (max - min));
19
19
 
20
- export const Default: StoryObj<typeof SyncStatusDetail> = {};
21
-
22
- export const Empty: StoryObj<typeof SyncStatusDetail> = {
23
- render: (args) => {
24
- return <SyncStatusDetail {...args} state={{}} />;
25
- },
26
- };
27
-
28
20
  const meta: Meta = {
29
21
  title: 'plugins/plugin-space/SyncStatusDetail',
30
22
  component: SyncStatusDetail,
@@ -81,3 +73,13 @@ const meta: Meta = {
81
73
  };
82
74
 
83
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
+ };