@dxos/react-ui 0.1.32-next.77d513e → 0.1.33
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/lib/browser/index.mjs +611 -527
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/Clipboard/ClipboardProvider.d.ts +9 -0
- package/dist/types/src/components/Clipboard/ClipboardProvider.d.ts.map +1 -0
- package/dist/types/src/components/Clipboard/CopyButton.d.ts +5 -0
- package/dist/types/src/components/Clipboard/CopyButton.d.ts.map +1 -0
- package/dist/types/src/components/Clipboard/index.d.ts +3 -0
- package/dist/types/src/components/Clipboard/index.d.ts.map +1 -0
- package/dist/types/src/components/InvitationEmoji/InvitationEmoji.d.ts +7 -0
- package/dist/types/src/components/InvitationEmoji/InvitationEmoji.d.ts.map +1 -0
- package/dist/types/src/components/InvitationEmoji/index.d.ts +2 -0
- package/dist/types/src/components/InvitationEmoji/index.d.ts.map +1 -0
- package/dist/types/src/components/InvitationList/InvitationList.d.ts.map +1 -1
- package/dist/types/src/components/InvitationList/InvitationListItem.d.ts.map +1 -1
- package/dist/types/src/components/InvitationList/InvitationStatusAvatar.d.ts +2 -1
- package/dist/types/src/components/InvitationList/InvitationStatusAvatar.d.ts.map +1 -1
- package/dist/types/src/components/InvitationList/InvitationStatusAvatar.stories.d.ts +1 -1
- package/dist/types/src/components/index.d.ts +2 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/panels/JoinPanel/JoinHeading.d.ts.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/package.json +13 -13
- package/src/components/Clipboard/ClipboardProvider.tsx +26 -0
- package/src/components/Clipboard/CopyButton.tsx +38 -0
- package/src/components/Clipboard/index.ts +6 -0
- package/src/components/InvitationEmoji/InvitationEmoji.tsx +32 -0
- package/src/components/InvitationEmoji/index.ts +5 -0
- package/src/components/InvitationList/InvitationList.tsx +7 -4
- package/src/components/InvitationList/InvitationListItem.tsx +6 -11
- package/src/components/InvitationList/InvitationStatusAvatar.tsx +37 -26
- package/src/components/index.ts +2 -0
- package/src/panels/JoinPanel/JoinHeading.tsx +3 -12
- package/src/translations/locales/en-US.ts +1 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { ComponentPropsWithoutRef } from 'react';
|
|
6
|
+
|
|
7
|
+
import { getSize, mx } from '@dxos/react-components';
|
|
8
|
+
|
|
9
|
+
import { toEmoji } from '../../util';
|
|
10
|
+
|
|
11
|
+
export type InvitationEmojiProps = {
|
|
12
|
+
invitationId?: string;
|
|
13
|
+
size?: 'lg' | 'sm';
|
|
14
|
+
} & ComponentPropsWithoutRef<'div'>;
|
|
15
|
+
|
|
16
|
+
export const InvitationEmoji = ({ invitationId, size = 'lg', ...rootProps }: InvitationEmojiProps) => {
|
|
17
|
+
const invitationEmoji = invitationId && toEmoji(invitationId);
|
|
18
|
+
return (
|
|
19
|
+
<div
|
|
20
|
+
role='none'
|
|
21
|
+
{...rootProps}
|
|
22
|
+
className={mx(
|
|
23
|
+
getSize(size === 'sm' ? 8 : 12),
|
|
24
|
+
'inline-flex items-center justify-center leading-none',
|
|
25
|
+
size === 'sm' ? 'text-2xl' : 'text-5xl bg-neutral-300 dark:bg-neutral-700 rounded-full',
|
|
26
|
+
rootProps.className
|
|
27
|
+
)}
|
|
28
|
+
>
|
|
29
|
+
<span role='none'>{invitationEmoji}</span>
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
@@ -7,6 +7,7 @@ import React from 'react';
|
|
|
7
7
|
import type { CancellableInvitationObservable } from '@dxos/client';
|
|
8
8
|
import { defaultDescription, DensityProvider, mx, useTranslation } from '@dxos/react-components';
|
|
9
9
|
|
|
10
|
+
import { ClipboardProvider } from '../Clipboard';
|
|
10
11
|
import { InvitationListItem, InvitationListItemProps } from './InvitationListItem';
|
|
11
12
|
|
|
12
13
|
export interface InvitationListProps extends Omit<InvitationListItemProps, 'invitation' | 'value'> {
|
|
@@ -18,10 +19,12 @@ export const InvitationList = ({ invitations, ...invitationProps }: InvitationLi
|
|
|
18
19
|
return invitations.length ? (
|
|
19
20
|
<AccordionRoot type='single' collapsible className='flex flex-col gap-1'>
|
|
20
21
|
<DensityProvider density='fine'>
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
<ClipboardProvider>
|
|
23
|
+
{invitations.map((invitation, index) => {
|
|
24
|
+
const value = invitation.invitation?.invitationId ?? `inv_${index}`;
|
|
25
|
+
return <InvitationListItem key={value} value={value} invitation={invitation} {...invitationProps} />;
|
|
26
|
+
})}
|
|
27
|
+
</ClipboardProvider>
|
|
25
28
|
</DensityProvider>
|
|
26
29
|
</AccordionRoot>
|
|
27
30
|
) : (
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
|
-
import {
|
|
4
|
+
import { ProhibitInset, QrCode, X } from '@phosphor-icons/react';
|
|
5
5
|
import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
|
6
6
|
import { QRCodeSVG } from 'qrcode.react';
|
|
7
7
|
import React, { useCallback } from 'react';
|
|
@@ -11,6 +11,7 @@ import { useInvitationStatus } from '@dxos/react-client';
|
|
|
11
11
|
import { Button, getSize, mx, useId, useTranslation } from '@dxos/react-components';
|
|
12
12
|
|
|
13
13
|
import { invitationStatusValue } from '../../util';
|
|
14
|
+
import { CopyButton } from '../Clipboard';
|
|
14
15
|
import { SharedInvitationListProps } from './InvitationListProps';
|
|
15
16
|
import { InvitationStatusAvatar } from './InvitationStatusAvatar';
|
|
16
17
|
|
|
@@ -39,16 +40,13 @@ export const InvitationListItem = ({
|
|
|
39
40
|
const handleClickRemove = useCallback(() => onClickRemove(invitation), [invitation, onClickRemove]);
|
|
40
41
|
|
|
41
42
|
const invitationUrl = invitationCode && createInvitationUrl(invitationCode);
|
|
42
|
-
const handleClickCopy = useCallback(() => {
|
|
43
|
-
if (invitationUrl) {
|
|
44
|
-
void navigator.clipboard.writeText(invitationUrl);
|
|
45
|
-
}
|
|
46
|
-
}, [invitationUrl]);
|
|
47
43
|
|
|
48
44
|
return (
|
|
49
45
|
<AccordionPrimitive.Item value={value}>
|
|
50
46
|
<AccordionPrimitive.Header className='flex gap-2 items-center'>
|
|
51
|
-
<InvitationStatusAvatar
|
|
47
|
+
<InvitationStatusAvatar
|
|
48
|
+
{...{ status, haltedAt, size: 8, invitationId: invitation?.invitation?.invitationId }}
|
|
49
|
+
/>
|
|
52
50
|
{showShare && invitationUrl ? (
|
|
53
51
|
<>
|
|
54
52
|
<AccordionPrimitive.Trigger asChild>
|
|
@@ -57,10 +55,7 @@ export const InvitationListItem = ({
|
|
|
57
55
|
<QrCode className={getSize(4)} weight='bold' />
|
|
58
56
|
</Button>
|
|
59
57
|
</AccordionPrimitive.Trigger>
|
|
60
|
-
<
|
|
61
|
-
<span className='pli-1'>{t('copy invitation code label')}</span>
|
|
62
|
-
<Copy className={getSize(4)} weight='bold' />
|
|
63
|
-
</Button>
|
|
58
|
+
<CopyButton value={invitationUrl} />
|
|
64
59
|
</>
|
|
65
60
|
) : showAuthCode ? (
|
|
66
61
|
<p className='grow text-xl text-center text-success-500 dark:text-success-300 font-mono'>
|
|
@@ -9,6 +9,7 @@ import { getSize, mx, Size } from '@dxos/react-components';
|
|
|
9
9
|
|
|
10
10
|
import { inactiveStrokeColor, activeStrokeColor, resolvedStrokeColor } from '../../styles';
|
|
11
11
|
import { invitationStatusValue } from '../../util';
|
|
12
|
+
import { InvitationEmoji } from '../InvitationEmoji';
|
|
12
13
|
|
|
13
14
|
export interface InvitationStatusAvatarSlots {
|
|
14
15
|
svg?: ComponentPropsWithoutRef<'svg'>;
|
|
@@ -19,6 +20,7 @@ export interface InvitationStatusAvatarProps {
|
|
|
19
20
|
status: Invitation.State;
|
|
20
21
|
haltedAt?: Invitation.State;
|
|
21
22
|
slots?: InvitationStatusAvatarSlots;
|
|
23
|
+
invitationId?: string;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
const svgSize = 32;
|
|
@@ -40,41 +42,50 @@ const circleProps: ComponentPropsWithoutRef<'circle'> = {
|
|
|
40
42
|
strokeDasharray: `${segment - gap} ${2 * segment + gap}`
|
|
41
43
|
};
|
|
42
44
|
|
|
43
|
-
export const InvitationStatusAvatar = ({
|
|
45
|
+
export const InvitationStatusAvatar = ({
|
|
46
|
+
size = 10,
|
|
47
|
+
status,
|
|
48
|
+
haltedAt,
|
|
49
|
+
slots = {},
|
|
50
|
+
invitationId
|
|
51
|
+
}: InvitationStatusAvatarProps) => {
|
|
44
52
|
const resolvedColor = resolvedStrokeColor(status);
|
|
45
53
|
const halted =
|
|
46
54
|
status === Invitation.State.CANCELLED || status === Invitation.State.TIMEOUT || status === Invitation.State.ERROR;
|
|
47
55
|
const cursor = invitationStatusValue.get(halted ? haltedAt! : status)!;
|
|
48
56
|
return (
|
|
49
|
-
<
|
|
50
|
-
{
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
index
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
<div className='inline-block relative'>
|
|
58
|
+
<InvitationEmoji {...{ invitationId }} size='sm' className='absolute inset-0 text-base' />
|
|
59
|
+
<svg {...slots.svg} viewBox={`0 0 ${svgSize} ${svgSize}`} className={mx(getSize(size), slots.svg?.className)}>
|
|
60
|
+
{[...Array(nSegments)].map((_, index) => (
|
|
61
|
+
<circle
|
|
62
|
+
key={index}
|
|
63
|
+
{...circleProps}
|
|
64
|
+
strokeDashoffset={index * segment + baseOffset}
|
|
65
|
+
className={
|
|
66
|
+
index === 0
|
|
67
|
+
? cursor === 1
|
|
68
|
+
? halted
|
|
69
|
+
? resolvedColor
|
|
70
|
+
: activeStrokeColor
|
|
71
|
+
: cursor > 1
|
|
59
72
|
? resolvedColor
|
|
60
|
-
:
|
|
61
|
-
:
|
|
62
|
-
?
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
73
|
+
: inactiveStrokeColor
|
|
74
|
+
: index === 1
|
|
75
|
+
? cursor === 3
|
|
76
|
+
? halted
|
|
77
|
+
? resolvedColor
|
|
78
|
+
: activeStrokeColor
|
|
79
|
+
: cursor > 3
|
|
67
80
|
? resolvedColor
|
|
68
|
-
:
|
|
81
|
+
: inactiveStrokeColor
|
|
69
82
|
: cursor > 3
|
|
70
83
|
? resolvedColor
|
|
71
84
|
: inactiveStrokeColor
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
))}
|
|
78
|
-
</svg>
|
|
85
|
+
}
|
|
86
|
+
/>
|
|
87
|
+
))}
|
|
88
|
+
</svg>
|
|
89
|
+
</div>
|
|
79
90
|
);
|
|
80
91
|
};
|
package/src/components/index.ts
CHANGED
|
@@ -7,8 +7,8 @@ import React, { cloneElement, ForwardedRef, forwardRef } from 'react';
|
|
|
7
7
|
import { useSpace } from '@dxos/react-client';
|
|
8
8
|
import { Button, defaultDescription, getSize, Heading, mx, useId, useTranslation } from '@dxos/react-components';
|
|
9
9
|
|
|
10
|
+
import { InvitationEmoji } from '../../components';
|
|
10
11
|
import { defaultSurface } from '../../styles';
|
|
11
|
-
import { toEmoji } from '../../util';
|
|
12
12
|
import { JoinPanelMode } from './JoinPanelProps';
|
|
13
13
|
import { JoinState } from './joinMachine';
|
|
14
14
|
|
|
@@ -33,8 +33,7 @@ export const JoinHeading = forwardRef(
|
|
|
33
33
|
const name = space?.properties.name;
|
|
34
34
|
const nameId = useId(mode === 'halo-only' ? 'identityDisplayName' : 'spaceDisplayName');
|
|
35
35
|
|
|
36
|
-
const
|
|
37
|
-
const invitationEmoji = invitationKey && toEmoji(invitationKey);
|
|
36
|
+
const invitationId = joinState?.context[mode === 'halo-only' ? 'halo' : 'space'].invitation?.invitationId;
|
|
38
37
|
|
|
39
38
|
const exitButton = (
|
|
40
39
|
<Button
|
|
@@ -65,15 +64,7 @@ export const JoinHeading = forwardRef(
|
|
|
65
64
|
{t(mode === 'halo-only' ? 'selecting identity heading' : 'joining space heading')}
|
|
66
65
|
</Heading>
|
|
67
66
|
<div role='group' className='flex items-center justify-center gap-2'>
|
|
68
|
-
<
|
|
69
|
-
role='none'
|
|
70
|
-
className={mx(
|
|
71
|
-
getSize(12),
|
|
72
|
-
'bg-neutral-300 dark:bg-neutral-700 rounded-full text-center text-4xl leading-[3rem]'
|
|
73
|
-
)}
|
|
74
|
-
>
|
|
75
|
-
{invitationEmoji}
|
|
76
|
-
</span>
|
|
67
|
+
<InvitationEmoji {...{ invitationId }} />
|
|
77
68
|
{name && <p id={nameId}>{name}</p>}
|
|
78
69
|
</div>
|
|
79
70
|
</div>
|
|
@@ -7,6 +7,7 @@ export const os = {
|
|
|
7
7
|
'identity offline description': 'Offline',
|
|
8
8
|
'sidebar label': 'DXOS sidebar',
|
|
9
9
|
'copy invitation code label': 'Copy',
|
|
10
|
+
'copy invitation code success label': 'Copied',
|
|
10
11
|
'open share panel label': 'Share',
|
|
11
12
|
'joining space heading': 'Joining space',
|
|
12
13
|
'join space heading': 'Join a space',
|