@dxos/shell 0.3.11-main.8a2cfe6 → 0.3.11-main.8be6c8a
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.
- package/dist/bundle/shell.mjs +36416 -0
- package/dist/bundle/shell.mjs.map +1 -0
- package/dist/bundle/shell.umd.js +210 -0
- package/dist/bundle/shell.umd.js.map +1 -0
- package/dist/bundle/style.css +1 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/react.mjs +317 -266
- package/dist/lib/browser/react.mjs.map +4 -4
- package/dist/types/src/components/IdentityList/DeviceList.d.ts.map +1 -1
- package/dist/types/src/components/IdentityList/DeviceList.js +5 -3
- package/dist/types/src/components/IdentityList/DeviceList.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.js +10 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.d.ts +6 -0
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.js +26 -3
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts +7 -6
- package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/identityMachine.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/identityMachine.js +2 -1
- package/dist/types/src/panels/IdentityPanel/identityMachine.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/DeviceManager.d.ts +10 -0
- package/dist/types/src/panels/IdentityPanel/steps/DeviceManager.d.ts.map +1 -0
- package/dist/types/src/panels/IdentityPanel/steps/DeviceManager.js +23 -0
- package/dist/types/src/panels/IdentityPanel/steps/DeviceManager.js.map +1 -0
- package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.js +4 -0
- package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.d.ts +0 -1
- package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.js +2 -3
- package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/index.d.ts +1 -0
- package/dist/types/src/panels/IdentityPanel/steps/index.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/index.js +1 -0
- package/dist/types/src/panels/IdentityPanel/steps/index.js.map +1 -1
- package/dist/types/src/translations/locales/en-US.d.ts +1 -0
- package/dist/types/src/translations/locales/en-US.d.ts.map +1 -1
- package/dist/types/src/translations/locales/en-US.js +2 -1
- package/dist/types/src/translations/locales/en-US.js.map +1 -1
- package/package.json +17 -17
- package/src/components/IdentityList/DeviceList.tsx +7 -5
- package/src/panels/IdentityPanel/IdentityPanel.stories.tsx +44 -2
- package/src/panels/IdentityPanel/IdentityPanel.tsx +14 -3
- package/src/panels/IdentityPanel/IdentityPanelProps.ts +7 -6
- package/src/panels/IdentityPanel/identityMachine.ts +2 -1
- package/src/panels/IdentityPanel/steps/DeviceManager.tsx +41 -0
- package/src/panels/IdentityPanel/steps/IdentityActionChooser.tsx +6 -1
- package/src/panels/IdentityPanel/steps/ProfileForm.tsx +1 -1
- package/src/panels/IdentityPanel/steps/index.ts +1 -0
- package/src/translations/locales/en-US.ts +2 -1
|
@@ -8,6 +8,7 @@ import { faker } from '@faker-js/faker';
|
|
|
8
8
|
import React from 'react';
|
|
9
9
|
|
|
10
10
|
import { PublicKey } from '@dxos/react-client';
|
|
11
|
+
import { DeviceKind } from '@dxos/react-client/halo';
|
|
11
12
|
import { Invitation } from '@dxos/react-client/invitations';
|
|
12
13
|
import { withTheme } from '@dxos/storybook-utils';
|
|
13
14
|
|
|
@@ -16,6 +17,7 @@ import type { IdentityPanelImplProps } from './IdentityPanelProps';
|
|
|
16
17
|
import { IdentityActionChooserImpl } from './steps';
|
|
17
18
|
import { StorybookDialog } from '../../components/StorybookDialog';
|
|
18
19
|
import { InvitationManager, type InvitationManagerProps } from '../../steps';
|
|
20
|
+
import { osTranslations } from '../../translations';
|
|
19
21
|
|
|
20
22
|
faker.seed(1234);
|
|
21
23
|
|
|
@@ -30,12 +32,13 @@ const noOpProps: IdentityPanelImplProps = {
|
|
|
30
32
|
displayName: faker.person.firstName(),
|
|
31
33
|
},
|
|
32
34
|
},
|
|
35
|
+
devices: [],
|
|
33
36
|
};
|
|
34
37
|
|
|
35
38
|
export default {
|
|
36
|
-
title: '
|
|
39
|
+
title: 'react-shell/IdentityPanel',
|
|
37
40
|
decorators: [withTheme],
|
|
38
|
-
parameters: { chromatic: { disableSnapshot: false } },
|
|
41
|
+
parameters: { translations: [osTranslations], chromatic: { disableSnapshot: false } },
|
|
39
42
|
};
|
|
40
43
|
|
|
41
44
|
export const IdentityActionChooser = () => {
|
|
@@ -50,6 +53,45 @@ export const IdentityActionChooser = () => {
|
|
|
50
53
|
);
|
|
51
54
|
};
|
|
52
55
|
|
|
56
|
+
export const UpdateProfileForm = () => {
|
|
57
|
+
return (
|
|
58
|
+
<StorybookDialog inOverlayLayout>
|
|
59
|
+
<IdentityPanelImpl
|
|
60
|
+
{...noOpProps}
|
|
61
|
+
activeView='update profile form'
|
|
62
|
+
IdentityActionChooser={IdentityActionChooserImpl}
|
|
63
|
+
/>
|
|
64
|
+
</StorybookDialog>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const DeviceManager = () => {
|
|
69
|
+
return (
|
|
70
|
+
<StorybookDialog inOverlayLayout>
|
|
71
|
+
<IdentityPanelImpl
|
|
72
|
+
{...{
|
|
73
|
+
...noOpProps,
|
|
74
|
+
devices: [
|
|
75
|
+
{ deviceKey: PublicKey.random(), kind: DeviceKind.CURRENT },
|
|
76
|
+
{ deviceKey: PublicKey.random(), kind: DeviceKind.TRUSTED },
|
|
77
|
+
{ deviceKey: PublicKey.random(), kind: DeviceKind.TRUSTED },
|
|
78
|
+
],
|
|
79
|
+
}}
|
|
80
|
+
activeView='device manager'
|
|
81
|
+
IdentityActionChooser={IdentityActionChooserImpl}
|
|
82
|
+
/>
|
|
83
|
+
</StorybookDialog>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const DeviceManagerEmpty = () => {
|
|
88
|
+
return (
|
|
89
|
+
<StorybookDialog inOverlayLayout>
|
|
90
|
+
<IdentityPanelImpl {...noOpProps} activeView='device manager' IdentityActionChooser={IdentityActionChooserImpl} />
|
|
91
|
+
</StorybookDialog>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
53
95
|
const DeviceInvitationManagerWithState = (extraProps: InvitationManagerProps) => (
|
|
54
96
|
<StorybookDialog inOverlayLayout>
|
|
55
97
|
<IdentityPanelImpl
|
|
@@ -6,7 +6,7 @@ import React, { useEffect, useMemo } from 'react';
|
|
|
6
6
|
import { generateName } from '@dxos/display-name';
|
|
7
7
|
import { log } from '@dxos/log';
|
|
8
8
|
import { useClient } from '@dxos/react-client';
|
|
9
|
-
import { type Identity, useIdentity } from '@dxos/react-client/halo';
|
|
9
|
+
import { type Identity, useIdentity, useDevices } from '@dxos/react-client/halo';
|
|
10
10
|
import { useInvitationStatus } from '@dxos/react-client/invitations';
|
|
11
11
|
import type { CancellableInvitationObservable } from '@dxos/react-client/invitations';
|
|
12
12
|
import { Avatar, DensityProvider, useId, useJdenticonHref, useTranslation } from '@dxos/react-ui';
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
type IdentityPanelProps,
|
|
18
18
|
} from './IdentityPanelProps';
|
|
19
19
|
import { useIdentityMachine } from './identityMachine';
|
|
20
|
-
import { IdentityActionChooser, ProfileForm } from './steps';
|
|
20
|
+
import { DeviceManager, IdentityActionChooser, ProfileForm } from './steps';
|
|
21
21
|
import { Viewport, Heading, CloseButton } from '../../components';
|
|
22
22
|
import { InvitationManager } from '../../steps';
|
|
23
23
|
|
|
@@ -54,12 +54,14 @@ export const IdentityPanelImpl = (props: IdentityPanelImplProps) => {
|
|
|
54
54
|
const title = useMemo(() => {
|
|
55
55
|
switch (activeView) {
|
|
56
56
|
case 'device manager':
|
|
57
|
-
case 'device invitation manager':
|
|
58
57
|
return t('choose devices label');
|
|
58
|
+
case 'device invitation manager':
|
|
59
|
+
return t('choose add device label');
|
|
59
60
|
default:
|
|
60
61
|
return t('identity heading');
|
|
61
62
|
}
|
|
62
63
|
}, [activeView, t]);
|
|
64
|
+
console.log('[IdentityPanelImpl]', { activeView });
|
|
63
65
|
return (
|
|
64
66
|
<DensityProvider density='fine'>
|
|
65
67
|
<IdentityHeading {...{ identity, titleId, title, onDone }} />
|
|
@@ -75,6 +77,9 @@ export const IdentityPanelImpl = (props: IdentityPanelImplProps) => {
|
|
|
75
77
|
invitationUrl={rest.createInvitationUrl(rest.invitationCode!)}
|
|
76
78
|
/>
|
|
77
79
|
</Viewport.View>
|
|
80
|
+
<Viewport.View id='device manager' classNames={viewStyles}>
|
|
81
|
+
<DeviceManager active={activeView === 'device manager'} {...rest} />
|
|
82
|
+
</Viewport.View>
|
|
78
83
|
<Viewport.View classNames={viewStyles} id='update profile form'>
|
|
79
84
|
<ProfileForm
|
|
80
85
|
send={rest.send}
|
|
@@ -105,6 +110,7 @@ export const IdentityPanel = ({
|
|
|
105
110
|
}: IdentityPanelProps) => {
|
|
106
111
|
const titleId = useId('identityPanel__heading', propsTitleId);
|
|
107
112
|
const client = useClient();
|
|
113
|
+
const devices = useDevices();
|
|
108
114
|
const identity = useIdentity();
|
|
109
115
|
if (!identity) {
|
|
110
116
|
console.error('IdentityPanel rendered with no active identity.');
|
|
@@ -126,6 +132,8 @@ export const IdentityPanel = ({
|
|
|
126
132
|
return 'identity action chooser';
|
|
127
133
|
case identityState.matches('managingDeviceInvitation'):
|
|
128
134
|
return 'device invitation manager';
|
|
135
|
+
case identityState.matches('managingDevices'):
|
|
136
|
+
return 'device manager';
|
|
129
137
|
case [{ managingProfile: 'idle' }, { managingProfile: 'pending' }].some(identityState.matches):
|
|
130
138
|
return 'update profile form';
|
|
131
139
|
// case identityState.matches('signingOut'):
|
|
@@ -135,6 +143,8 @@ export const IdentityPanel = ({
|
|
|
135
143
|
}
|
|
136
144
|
}, [identityState]);
|
|
137
145
|
|
|
146
|
+
console.log({ activeView, identityState });
|
|
147
|
+
|
|
138
148
|
const onUpdateProfile = async (profile: NonNullable<Identity['profile']>) => {
|
|
139
149
|
identitySend({ type: 'updateProfile' });
|
|
140
150
|
await client.halo.updateProfile(profile);
|
|
@@ -143,6 +153,7 @@ export const IdentityPanel = ({
|
|
|
143
153
|
const implProps = {
|
|
144
154
|
...props,
|
|
145
155
|
identity,
|
|
156
|
+
devices,
|
|
146
157
|
activeView,
|
|
147
158
|
send: identitySend,
|
|
148
159
|
titleId,
|
|
@@ -2,19 +2,20 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import type { cloneElement } from 'react';
|
|
6
|
+
import type { Event, SingleOrArray } from 'xstate';
|
|
7
7
|
|
|
8
|
-
import type { Identity } from '@dxos/react-client/halo';
|
|
9
|
-
import {
|
|
8
|
+
import type { Device, Identity } from '@dxos/react-client/halo';
|
|
9
|
+
import type { InvitationStatus } from '@dxos/react-client/invitations';
|
|
10
10
|
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import type { IdentityEvent } from './identityMachine';
|
|
12
|
+
import type { InvitationManagerProps } from '../../steps';
|
|
13
13
|
|
|
14
14
|
export type IdentityPanelImplProps = {
|
|
15
15
|
titleId: string;
|
|
16
16
|
activeView: 'device manager' | 'update profile form' | 'device invitation manager' | 'identity action chooser';
|
|
17
17
|
identity: Identity;
|
|
18
|
+
devices: Device[];
|
|
18
19
|
onUpdateProfile?: (profile: NonNullable<Identity['profile']>) => Promise<void>;
|
|
19
20
|
createInvitationUrl: (invitationCode: string) => string;
|
|
20
21
|
send?: (event: SingleOrArray<Event<IdentityEvent>>) => void;
|
|
@@ -58,6 +58,7 @@ const identityMachine = createMachine<IdentityMachineContext, IdentityEvent>(
|
|
|
58
58
|
states: {
|
|
59
59
|
choosingAction: {},
|
|
60
60
|
managingDeviceInvitation: {},
|
|
61
|
+
managingDevices: {},
|
|
61
62
|
managingProfile: {
|
|
62
63
|
initial: 'idle',
|
|
63
64
|
states: {
|
|
@@ -73,9 +74,9 @@ const identityMachine = createMachine<IdentityMachineContext, IdentityEvent>(
|
|
|
73
74
|
},
|
|
74
75
|
on: {
|
|
75
76
|
unchooseAction: { target: '.choosingAction', actions: ['unsetInvitation', 'log'] },
|
|
76
|
-
chooseDevices: { target: '.managingDeviceInvitation', actions: ['unsetInvitation', 'log'] },
|
|
77
77
|
deselectInvitation: { target: '.choosingAction', actions: ['unsetInvitation', 'log'] },
|
|
78
78
|
selectInvitation: { target: '.managingDeviceInvitation', actions: ['setInvitation', 'log'] },
|
|
79
|
+
chooseDevices: { target: '.managingDevices', actions: 'log' },
|
|
79
80
|
chooseProfile: { target: '.managingProfile', actions: 'log' },
|
|
80
81
|
// chooseSignOut: { target: '.signingOut', actions: 'log' },
|
|
81
82
|
},
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { type Event, type SingleOrArray } from 'xstate';
|
|
7
|
+
|
|
8
|
+
import { type Device } from '@dxos/react-client/halo';
|
|
9
|
+
import { useTranslation } from '@dxos/react-ui';
|
|
10
|
+
|
|
11
|
+
import { Action, Actions, DeviceList } from '../../../components';
|
|
12
|
+
import type { IdentityPanelStepProps } from '../IdentityPanelProps';
|
|
13
|
+
import type { IdentityEvent } from '../identityMachine';
|
|
14
|
+
|
|
15
|
+
export interface DeviceManagerProps extends Omit<IdentityPanelStepProps, 'send'> {
|
|
16
|
+
send?: (event: SingleOrArray<Event<IdentityEvent>>) => void;
|
|
17
|
+
devices: Device[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const DeviceManager = ({ devices, active, send }: DeviceManagerProps) => {
|
|
21
|
+
const { t } = useTranslation('os');
|
|
22
|
+
const disabled = !active;
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<>
|
|
26
|
+
<div role='none' className='grow'>
|
|
27
|
+
<DeviceList devices={devices} />
|
|
28
|
+
</div>
|
|
29
|
+
<Actions>
|
|
30
|
+
<Action
|
|
31
|
+
variant='ghost'
|
|
32
|
+
disabled={disabled}
|
|
33
|
+
onClick={() => send?.({ type: 'unchooseAction' })}
|
|
34
|
+
data-testid={'manage-devices-back'}
|
|
35
|
+
>
|
|
36
|
+
{t('back label')}
|
|
37
|
+
</Action>
|
|
38
|
+
</Actions>
|
|
39
|
+
</>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { CaretRight, Plus, Power, UserGear } from '@phosphor-icons/react';
|
|
5
|
+
import { CaretRight, Devices, Plus, Power, UserGear } from '@phosphor-icons/react';
|
|
6
6
|
import React, { useCallback } from 'react';
|
|
7
7
|
|
|
8
8
|
import { useClient } from '@dxos/react-client';
|
|
@@ -70,6 +70,11 @@ export const IdentityActionChooserImpl = ({
|
|
|
70
70
|
classNames='plb-4'
|
|
71
71
|
>
|
|
72
72
|
<Plus className={getSize(6)} />
|
|
73
|
+
<span className='grow mli-3'>{t('choose add device label')}</span>
|
|
74
|
+
<CaretRight weight='bold' className={getSize(4)} />
|
|
75
|
+
</Action>
|
|
76
|
+
<Action data-testid='manage-devices' onClick={() => send?.({ type: 'chooseDevices' })} classNames='plb-4'>
|
|
77
|
+
<Devices className={getSize(6)} />
|
|
73
78
|
<span className='grow mli-3'>{t('choose devices label')}</span>
|
|
74
79
|
<CaretRight weight='bold' className={getSize(4)} />
|
|
75
80
|
</Action>
|
|
@@ -37,7 +37,7 @@ export const ProfileForm = (props: ProfileFormProps) => {
|
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
// TODO(zhenyasav): impl shouldn't need send()
|
|
40
|
-
|
|
40
|
+
const ProfileFormImpl = (props: ProfileFormImplProps) => {
|
|
41
41
|
const { active, profile, send, onUpdateProfile, validationMessage } = props;
|
|
42
42
|
const disabled = !active;
|
|
43
43
|
const { t } = useTranslation('os');
|
|
@@ -69,7 +69,8 @@ export const os = {
|
|
|
69
69
|
'selecting identity heading': 'Selecting identity',
|
|
70
70
|
'devices heading': 'Devices',
|
|
71
71
|
'identity heading': 'Profile settings',
|
|
72
|
-
'choose
|
|
72
|
+
'choose add device label': 'Add device',
|
|
73
|
+
'choose devices label': 'Manage devices',
|
|
73
74
|
'choose profile label': 'Edit profile',
|
|
74
75
|
'choose sign out label': 'Sign out',
|
|
75
76
|
'empty space members message': 'There is nobody in this space yet.',
|