@dxos/shell 0.4.4-main.c5da621 → 0.4.4-main.d035bb3
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 +7671 -7616
- package/dist/bundle/shell.mjs.map +1 -1
- package/dist/bundle/shell.umd.js +73 -73
- package/dist/bundle/shell.umd.js.map +1 -1
- package/dist/bundle/style.css +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/react.mjs +56 -30
- package/dist/lib/browser/react.mjs.map +3 -3
- package/dist/types/src/components/Clipboard/CopyButton.js +5 -5
- package/dist/types/src/components/Clipboard/CopyButton.js.map +1 -1
- package/dist/types/src/components/IdentityList/IdentityListItem.d.ts +3 -1
- package/dist/types/src/components/IdentityList/IdentityListItem.d.ts.map +1 -1
- package/dist/types/src/components/IdentityList/IdentityListItem.js +3 -3
- package/dist/types/src/components/IdentityList/IdentityListItem.js.map +1 -1
- package/dist/types/src/components/InvitationList/InvitationListItem.d.ts +8 -5
- package/dist/types/src/components/InvitationList/InvitationListItem.d.ts.map +1 -1
- package/dist/types/src/components/InvitationList/InvitationListItem.js +10 -10
- package/dist/types/src/components/InvitationList/InvitationListItem.js.map +1 -1
- package/dist/types/src/components/Panel/Action.js +3 -3
- package/dist/types/src/components/Panel/Action.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.js +1 -1
- package/dist/types/src/panels/IdentityPanel/IdentityPanel.js.map +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.d.ts +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.d.ts.map +1 -1
- package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.js +10 -1
- package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.js.map +1 -1
- package/dist/types/src/panels/SpacePanel/SpacePanel.js +1 -1
- package/dist/types/src/panels/SpacePanel/SpacePanel.js.map +1 -1
- package/dist/types/src/react.d.ts +1 -0
- package/dist/types/src/react.d.ts.map +1 -1
- package/dist/types/src/react.js +1 -0
- package/dist/types/src/react.js.map +1 -1
- package/dist/types/src/translations/locales/en-US.d.ts +2 -1
- 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 +19 -19
- package/src/components/Clipboard/CopyButton.tsx +5 -5
- package/src/components/IdentityList/IdentityListItem.tsx +28 -26
- package/src/components/InvitationList/InvitationListItem.tsx +42 -15
- package/src/components/Panel/Action.tsx +3 -3
- package/src/panels/IdentityPanel/IdentityPanel.tsx +1 -1
- package/src/panels/IdentityPanel/steps/ProfileForm.tsx +21 -5
- package/src/panels/SpacePanel/SpacePanel.tsx +1 -1
- package/src/react.ts +1 -0
- package/src/translations/locales/en-US.ts +2 -1
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React, { forwardRef } from 'react';
|
|
5
|
+
import React, { type ComponentPropsWithoutRef, forwardRef } from 'react';
|
|
6
6
|
|
|
7
7
|
import { generateName } from '@dxos/display-name';
|
|
8
8
|
import { SpaceMember } from '@dxos/react-client/echo';
|
|
9
9
|
import { type Identity } from '@dxos/react-client/halo';
|
|
10
|
-
import { ListItem, Avatar, useJdenticonHref, useId } from '@dxos/react-ui';
|
|
10
|
+
import { ListItem, Avatar, useJdenticonHref, useId, type ThemedClassName } from '@dxos/react-ui';
|
|
11
11
|
import { mx } from '@dxos/react-ui-theme';
|
|
12
12
|
|
|
13
13
|
type IdentityListItemProps = {
|
|
@@ -16,27 +16,29 @@ type IdentityListItemProps = {
|
|
|
16
16
|
onClick?: () => void;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
export const IdentityListItem = forwardRef<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
19
|
+
export const IdentityListItem = forwardRef<
|
|
20
|
+
HTMLLIElement,
|
|
21
|
+
ThemedClassName<ComponentPropsWithoutRef<'li'>> & IdentityListItemProps
|
|
22
|
+
>(({ identity, presence, onClick, classNames, ...props }, forwardedRef) => {
|
|
23
|
+
const fallbackValue = identity.identityKey.toHex();
|
|
24
|
+
const labelId = useId('identityListItem__label');
|
|
25
|
+
const jdenticon = useJdenticonHref(fallbackValue ?? '', 12);
|
|
26
|
+
const displayName = identity.profile?.displayName ?? generateName(identity.identityKey.toHex());
|
|
27
|
+
return (
|
|
28
|
+
<ListItem.Root
|
|
29
|
+
{...props}
|
|
30
|
+
classNames={mx('flex gap-2 pis-3 pie-1 items-center', onClick && 'cursor-pointer', classNames)}
|
|
31
|
+
onClick={() => onClick?.()}
|
|
32
|
+
data-testid='identity-list-item'
|
|
33
|
+
labelId={labelId}
|
|
34
|
+
ref={forwardedRef}
|
|
35
|
+
>
|
|
36
|
+
<Avatar.Root status={presence === SpaceMember.PresenceState.ONLINE ? 'active' : 'inactive'} labelId={labelId}>
|
|
37
|
+
<Avatar.Frame classNames='place-self-center'>
|
|
38
|
+
<Avatar.Fallback href={jdenticon} />
|
|
39
|
+
</Avatar.Frame>
|
|
40
|
+
<Avatar.Label classNames='text-sm truncate pli-2'>{displayName}</Avatar.Label>
|
|
41
|
+
</Avatar.Root>
|
|
42
|
+
</ListItem.Root>
|
|
43
|
+
);
|
|
44
|
+
});
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
import { X } from '@phosphor-icons/react';
|
|
5
|
-
import React, { useCallback } from 'react';
|
|
5
|
+
import React, { type ComponentPropsWithoutRef, useCallback } from 'react';
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
type CancellableInvitationObservable,
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
useThemeContext,
|
|
19
19
|
type AvatarRootProps,
|
|
20
20
|
Tooltip,
|
|
21
|
+
type ThemedClassName,
|
|
21
22
|
} from '@dxos/react-ui';
|
|
22
23
|
import { focusRing, getSize, mx } from '@dxos/react-ui-theme';
|
|
23
24
|
|
|
@@ -26,14 +27,15 @@ import { toEmoji } from '../../util';
|
|
|
26
27
|
import { AuthCode } from '../AuthCode';
|
|
27
28
|
import { CopyButtonIconOnly } from '../Clipboard';
|
|
28
29
|
|
|
29
|
-
export
|
|
30
|
+
export type InvitationListItemProps = SharedInvitationListProps & {
|
|
30
31
|
invitation: CancellableInvitationObservable;
|
|
31
32
|
onClickRemove?: (invitation: CancellableInvitationObservable) => void;
|
|
32
|
-
|
|
33
|
+
reverseEffects?: boolean;
|
|
34
|
+
} & ThemedClassName<ComponentPropsWithoutRef<'li'>>;
|
|
33
35
|
|
|
34
|
-
export
|
|
36
|
+
export type InvitationListItemImplProps = InvitationListItemProps & {
|
|
35
37
|
invitationStatus: InvitationStatus;
|
|
36
|
-
}
|
|
38
|
+
};
|
|
37
39
|
|
|
38
40
|
export const InvitationListItem = (props: InvitationListItemProps) => {
|
|
39
41
|
const { invitation } = props;
|
|
@@ -43,13 +45,21 @@ export const InvitationListItem = (props: InvitationListItemProps) => {
|
|
|
43
45
|
|
|
44
46
|
const avatarProps: Pick<AvatarRootProps, 'size' | 'variant'> = { size: 10, variant: 'circle' };
|
|
45
47
|
|
|
46
|
-
const AvatarStackEffect = ({
|
|
48
|
+
const AvatarStackEffect = ({
|
|
49
|
+
animation,
|
|
50
|
+
status,
|
|
51
|
+
reverseEffects,
|
|
52
|
+
}: Pick<AvatarRootProps, 'status' | 'animation'> & Pick<InvitationListItemProps, 'reverseEffects'>) => {
|
|
47
53
|
const { tx } = useThemeContext();
|
|
48
54
|
return (
|
|
49
55
|
<>
|
|
50
56
|
<span
|
|
51
57
|
role='none'
|
|
52
|
-
className={mx(
|
|
58
|
+
className={mx(
|
|
59
|
+
'absolute inline-end-auto opacity-20',
|
|
60
|
+
reverseEffects ? 'inline-start-3' : 'inline-start-1',
|
|
61
|
+
getSize(avatarProps.size!),
|
|
62
|
+
)}
|
|
53
63
|
>
|
|
54
64
|
<span
|
|
55
65
|
role='none'
|
|
@@ -59,7 +69,11 @@ const AvatarStackEffect = ({ animation, status }: Pick<AvatarRootProps, 'status'
|
|
|
59
69
|
</span>
|
|
60
70
|
<span
|
|
61
71
|
role='none'
|
|
62
|
-
className={mx(
|
|
72
|
+
className={mx(
|
|
73
|
+
'absolute inline-end-auto opacity-50',
|
|
74
|
+
reverseEffects ? 'inline-start-2' : 'inline-start-2',
|
|
75
|
+
getSize(avatarProps.size!),
|
|
76
|
+
)}
|
|
63
77
|
>
|
|
64
78
|
<span
|
|
65
79
|
role='none'
|
|
@@ -77,6 +91,8 @@ export const InvitationListItemImpl = ({
|
|
|
77
91
|
send,
|
|
78
92
|
onClickRemove,
|
|
79
93
|
createInvitationUrl,
|
|
94
|
+
reverseEffects,
|
|
95
|
+
...props
|
|
80
96
|
}: InvitationListItemImplProps) => {
|
|
81
97
|
const { t } = useTranslation('os');
|
|
82
98
|
const { cancel, status: invitationStatus, invitationCode, authCode, type } = propsInvitationStatus;
|
|
@@ -120,15 +136,21 @@ export const InvitationListItemImpl = ({
|
|
|
120
136
|
const avatarStatus = avatarError ? 'error' : avatarGreen ? 'active' : 'inactive';
|
|
121
137
|
|
|
122
138
|
return (
|
|
123
|
-
<ListItem.Root
|
|
139
|
+
<ListItem.Root
|
|
140
|
+
id={invitationCode}
|
|
141
|
+
{...props}
|
|
142
|
+
classNames={['flex gap-2 pis-3 pie-1 items-center relative', props.classNames]}
|
|
143
|
+
>
|
|
124
144
|
<ListItem.Heading classNames='sr-only'>
|
|
125
145
|
{t(type === Invitation.Type.MULTIUSE ? 'invite many list item label' : 'invite one list item label')}
|
|
126
146
|
</ListItem.Heading>
|
|
127
|
-
{type === Invitation.Type.MULTIUSE &&
|
|
147
|
+
{type === Invitation.Type.MULTIUSE && (
|
|
148
|
+
<AvatarStackEffect status={avatarStatus} animation={avatarAnimation} reverseEffects={reverseEffects} />
|
|
149
|
+
)}
|
|
128
150
|
<Tooltip.Root>
|
|
129
151
|
<Avatar.Root {...avatarProps} animation={avatarAnimation} status={avatarStatus}>
|
|
130
152
|
<Tooltip.Trigger asChild>
|
|
131
|
-
<Avatar.Frame tabIndex={0} classNames={[focusRing, 'relative rounded-full']}>
|
|
153
|
+
<Avatar.Frame tabIndex={0} classNames={[focusRing, 'relative rounded-full place-self-center']}>
|
|
132
154
|
<Avatar.Fallback text={toEmoji(invitationId)} />
|
|
133
155
|
</Avatar.Frame>
|
|
134
156
|
</Tooltip.Trigger>
|
|
@@ -168,14 +190,19 @@ export const InvitationListItemImpl = ({
|
|
|
168
190
|
<span className='grow'> </span>
|
|
169
191
|
)}
|
|
170
192
|
{isCancellable ? (
|
|
171
|
-
<Button variant='ghost' classNames='flex gap-1' onClick={cancel} data-testid='cancel-invitation'>
|
|
193
|
+
<Button variant='ghost' classNames='flex gap-1 pli-0' onClick={cancel} data-testid='cancel-invitation'>
|
|
172
194
|
<span className='sr-only'>{t('cancel invitation label')}</span>
|
|
173
|
-
<X className={getSize(
|
|
195
|
+
<X className={getSize(4)} />
|
|
174
196
|
</Button>
|
|
175
197
|
) : (
|
|
176
|
-
<Button
|
|
198
|
+
<Button
|
|
199
|
+
variant='ghost'
|
|
200
|
+
classNames='flex gap-1 pli-0'
|
|
201
|
+
onClick={handleClickRemove}
|
|
202
|
+
data-testid='remove-invitation'
|
|
203
|
+
>
|
|
177
204
|
<span className='sr-only'>{t('remove invitation label')}</span>
|
|
178
|
-
<X className={getSize(
|
|
205
|
+
<X className={getSize(4)} />
|
|
179
206
|
</Button>
|
|
180
207
|
)}
|
|
181
208
|
</ListItem.Root>
|
|
@@ -66,14 +66,14 @@ export const BifurcatedAction = forwardRef<HTMLButtonElement, BifurcatedActionPr
|
|
|
66
66
|
variant={variant}
|
|
67
67
|
onClick={activeAction.onClick}
|
|
68
68
|
>
|
|
69
|
-
{activeAction.icon && <activeAction.icon />}
|
|
69
|
+
{activeAction.icon && <activeAction.icon className={getSize(5)} />}
|
|
70
70
|
<span>{activeAction.label}</span>
|
|
71
71
|
</Button>
|
|
72
72
|
<DropdownMenu.Root>
|
|
73
73
|
<DropdownMenu.Trigger asChild>
|
|
74
74
|
<Button classNames={['bs-11 flex-none rounded-is-none', classNames]}>
|
|
75
75
|
<span className='sr-only'>{t('invite options label')}</span>
|
|
76
|
-
<CaretDown />
|
|
76
|
+
<CaretDown className={getSize(4)} />
|
|
77
77
|
</Button>
|
|
78
78
|
</DropdownMenu.Trigger>
|
|
79
79
|
{/* TODO(thure): Putting `DropdownMenu.Portal` here breaks highlighting and focus. Why? */}
|
|
@@ -99,7 +99,7 @@ export const BifurcatedAction = forwardRef<HTMLButtonElement, BifurcatedActionPr
|
|
|
99
99
|
)}
|
|
100
100
|
</div>
|
|
101
101
|
<DropdownMenu.ItemIndicator asChild>
|
|
102
|
-
<Check />
|
|
102
|
+
<Check weight='bold' className={getSize(4)} />
|
|
103
103
|
</DropdownMenu.ItemIndicator>
|
|
104
104
|
</DropdownMenu.CheckboxItem>
|
|
105
105
|
);
|
|
@@ -87,7 +87,7 @@ export const IdentityPanelImpl = (props: IdentityPanelImplProps) => {
|
|
|
87
87
|
<ProfileForm
|
|
88
88
|
send={rest.send}
|
|
89
89
|
active={activeView === 'update profile form'}
|
|
90
|
-
|
|
90
|
+
identity={identity}
|
|
91
91
|
onUpdateProfile={onUpdateProfile}
|
|
92
92
|
/>
|
|
93
93
|
</Viewport.View>
|
|
@@ -9,14 +9,14 @@ import { log } from '@dxos/log';
|
|
|
9
9
|
import { type Identity } from '@dxos/react-client/halo';
|
|
10
10
|
import { useTranslation } from '@dxos/react-ui';
|
|
11
11
|
|
|
12
|
-
import { Action, Actions, StepHeading, Input } from '../../../components';
|
|
12
|
+
import { Action, Actions, StepHeading, Input, useClipboardContext } from '../../../components';
|
|
13
13
|
import { type IdentityPanelStepProps } from '../IdentityPanelProps';
|
|
14
14
|
import { type IdentityEvent } from '../identityMachine';
|
|
15
15
|
|
|
16
16
|
export interface ProfileFormProps extends Omit<IdentityPanelStepProps, 'send'> {
|
|
17
17
|
send?: (event: SingleOrArray<Event<IdentityEvent>>) => void;
|
|
18
18
|
onUpdateProfile?: (profile: NonNullable<Identity['profile']>) => Promise<void>;
|
|
19
|
-
|
|
19
|
+
identity?: Identity;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export type ProfileFormImplProps = ProfileFormProps & {
|
|
@@ -38,10 +38,14 @@ export const ProfileForm = (props: ProfileFormProps) => {
|
|
|
38
38
|
|
|
39
39
|
// TODO(zhenyasav): impl shouldn't need send()
|
|
40
40
|
const ProfileFormImpl = (props: ProfileFormImplProps) => {
|
|
41
|
-
const { active,
|
|
41
|
+
const { active, identity, send, onUpdateProfile, validationMessage } = props;
|
|
42
|
+
const profile = identity?.profile;
|
|
42
43
|
const disabled = !active;
|
|
43
44
|
const { t } = useTranslation('os');
|
|
44
45
|
const [inputValue, setInputValue] = useState(profile?.displayName ?? '');
|
|
46
|
+
const { textValue, setTextValue } = useClipboardContext();
|
|
47
|
+
const identityHex = identity?.identityKey.toHex();
|
|
48
|
+
const copied = textValue === identityHex;
|
|
45
49
|
return (
|
|
46
50
|
<>
|
|
47
51
|
<div role='none' className='grow flex flex-col justify-center'>
|
|
@@ -57,11 +61,23 @@ const ProfileFormImpl = (props: ProfileFormImplProps) => {
|
|
|
57
61
|
/>
|
|
58
62
|
</div>
|
|
59
63
|
<Actions>
|
|
64
|
+
<Action
|
|
65
|
+
variant='ghost'
|
|
66
|
+
disabled={disabled}
|
|
67
|
+
onClick={() => {
|
|
68
|
+
if (identityHex) {
|
|
69
|
+
void setTextValue(identityHex);
|
|
70
|
+
}
|
|
71
|
+
}}
|
|
72
|
+
data-testid='update-profile-form-copy-key'
|
|
73
|
+
>
|
|
74
|
+
{t(copied ? 'copy success label' : 'copy self public key label')}
|
|
75
|
+
</Action>
|
|
60
76
|
<Action
|
|
61
77
|
variant='ghost'
|
|
62
78
|
disabled={disabled}
|
|
63
79
|
onClick={() => send?.({ type: 'unchooseAction' })}
|
|
64
|
-
data-testid=
|
|
80
|
+
data-testid='update-profile-form-back'
|
|
65
81
|
>
|
|
66
82
|
{t('back label')}
|
|
67
83
|
</Action>
|
|
@@ -69,7 +85,7 @@ const ProfileFormImpl = (props: ProfileFormImplProps) => {
|
|
|
69
85
|
variant='primary'
|
|
70
86
|
disabled={disabled}
|
|
71
87
|
onClick={() => onUpdateProfile?.({ displayName: inputValue })}
|
|
72
|
-
data-testid=
|
|
88
|
+
data-testid='update-profile-form-continue'
|
|
73
89
|
>
|
|
74
90
|
{t('done label')}
|
|
75
91
|
</Action>
|
|
@@ -27,7 +27,7 @@ const SpacePanelHeading = ({ titleId, space, onDone }: SpacePanelHeadingProps) =
|
|
|
27
27
|
corner={<CloseButton data-testid='identity-panel-done' onDone={onDone} />}
|
|
28
28
|
>
|
|
29
29
|
<div role='none' className='flex gap-4 items-center justify-center mlb-4'>
|
|
30
|
-
<Planet size={32} />
|
|
30
|
+
<Planet size={32} weight='light' />
|
|
31
31
|
<div className='block text-start font-light text-xl'>{name ?? space.key.truncate()}</div>
|
|
32
32
|
</div>
|
|
33
33
|
</Heading>
|
package/src/react.ts
CHANGED
|
@@ -7,7 +7,8 @@ export const os = {
|
|
|
7
7
|
'identity offline description': 'Offline',
|
|
8
8
|
'sidebar label': 'DXOS sidebar',
|
|
9
9
|
'copy invitation code label': 'Copy URL',
|
|
10
|
-
'copy
|
|
10
|
+
'copy success label': 'Copied',
|
|
11
|
+
'copy self public key label': 'Copy public key',
|
|
11
12
|
'open share panel label': 'View QR code',
|
|
12
13
|
'joining space heading': 'Joining space',
|
|
13
14
|
'join space heading': 'Enter space invitation',
|