@dxos/react-ui-thread 0.8.3 → 0.8.4-main.1c7ec43d41
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 +140 -205
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/translations.mjs +25 -0
- package/dist/lib/browser/translations.mjs.map +7 -0
- package/dist/types/src/Message/Message.d.ts +2 -2
- package/dist/types/src/Message/Message.d.ts.map +1 -1
- package/dist/types/src/Message/Message.stories.d.ts +21 -19
- package/dist/types/src/Message/Message.stories.d.ts.map +1 -1
- package/dist/types/src/Thread/Comments.stories.d.ts +22 -39
- package/dist/types/src/Thread/Comments.stories.d.ts.map +1 -1
- package/dist/types/src/Thread/Thread.d.ts +27 -10
- package/dist/types/src/Thread/Thread.d.ts.map +1 -1
- package/dist/types/src/Thread/Thread.stories.d.ts +25 -19
- package/dist/types/src/Thread/Thread.stories.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/testing.d.ts +1 -2
- package/dist/types/src/testing.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +15 -16
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +1 -0
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +37 -29
- package/src/Message/Message.stories.tsx +24 -17
- package/src/Message/Message.tsx +20 -18
- package/src/Thread/Comments.stories.tsx +94 -65
- package/src/Thread/Thread.stories.tsx +31 -22
- package/src/Thread/Thread.tsx +47 -26
- package/src/index.ts +1 -4
- package/src/testing.tsx +10 -14
- package/src/translations.ts +15 -13
- package/src/types.ts +1 -0
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@
|
|
6
|
-
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
7
6
|
import React, { useMemo, useRef, useState } from 'react';
|
|
8
7
|
|
|
9
8
|
import { PublicKey } from '@dxos/keys';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
9
|
+
import { random } from '@dxos/random';
|
|
10
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
11
|
+
import { createBasicExtensions, createThemeExtensions } from '@dxos/ui-editor';
|
|
12
|
+
import { hoverableControls, hoverableFocusedWithinControls } from '@dxos/ui-theme';
|
|
13
|
+
|
|
14
|
+
import { translations } from '#translations';
|
|
14
15
|
|
|
15
|
-
import { Thread, ThreadFooter } from './Thread';
|
|
16
16
|
import { MessageRoot, MessageTextbox } from '../Message';
|
|
17
|
-
import {
|
|
18
|
-
import
|
|
17
|
+
import { type MessageEntity, MessageStoryText } from '../testing';
|
|
18
|
+
import { Thread } from './Thread';
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
random.seed(1);
|
|
21
21
|
|
|
22
22
|
const DefaultStory = () => {
|
|
23
23
|
const [pending, setPending] = useState(false);
|
|
@@ -28,7 +28,7 @@ const DefaultStory = () => {
|
|
|
28
28
|
id: `m${i + 1}`,
|
|
29
29
|
timestamp: new Date().toISOString(),
|
|
30
30
|
authorId: [identityKey1.toHex(), identityKey2.toHex()][i % 2],
|
|
31
|
-
text:
|
|
31
|
+
text: random.lorem.paragraph(),
|
|
32
32
|
})),
|
|
33
33
|
);
|
|
34
34
|
|
|
@@ -59,13 +59,14 @@ const DefaultStory = () => {
|
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
return (
|
|
62
|
-
<
|
|
63
|
-
<Thread id='t1'>
|
|
62
|
+
<div className='mx-auto w-96 overflow-y-auto'>
|
|
63
|
+
<Thread.Root id='t1'>
|
|
64
64
|
{messages.map((message) => (
|
|
65
65
|
<MessageRoot key={message.id} classNames={[hoverableControls, hoverableFocusedWithinControls]} {...message}>
|
|
66
66
|
<MessageStoryText {...message} text={message.text} onDelete={() => console.log('delete')} />
|
|
67
67
|
</MessageRoot>
|
|
68
68
|
))}
|
|
69
|
+
|
|
69
70
|
<MessageTextbox
|
|
70
71
|
id={String(_count)}
|
|
71
72
|
authorId={identityKey1.toHex()}
|
|
@@ -73,18 +74,26 @@ const DefaultStory = () => {
|
|
|
73
74
|
extensions={extensions}
|
|
74
75
|
onSend={handleSend}
|
|
75
76
|
/>
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
|
|
78
|
+
<Thread.Status activity>Processing...</Thread.Status>
|
|
79
|
+
</Thread.Root>
|
|
80
|
+
</div>
|
|
79
81
|
);
|
|
80
82
|
};
|
|
81
83
|
|
|
82
|
-
|
|
84
|
+
const meta = {
|
|
83
85
|
title: 'ui/react-ui-thread/Thread',
|
|
84
|
-
component: Thread,
|
|
86
|
+
component: Thread.Root,
|
|
85
87
|
render: DefaultStory,
|
|
86
|
-
decorators: [withTheme, withLayout({
|
|
87
|
-
parameters: {
|
|
88
|
-
|
|
88
|
+
decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
|
|
89
|
+
parameters: {
|
|
90
|
+
layout: 'fullscreen',
|
|
91
|
+
translations,
|
|
92
|
+
},
|
|
93
|
+
} satisfies Meta<typeof Thread.Root>;
|
|
94
|
+
|
|
95
|
+
export default meta;
|
|
96
|
+
|
|
97
|
+
type Story = StoryObj<typeof meta>;
|
|
89
98
|
|
|
90
|
-
export const Default = {};
|
|
99
|
+
export const Default: Story = {};
|
package/src/Thread/Thread.tsx
CHANGED
|
@@ -2,20 +2,29 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import React, { type ComponentPropsWithRef, forwardRef } from 'react';
|
|
5
|
+
import React, { ComponentPropsWithRef, forwardRef, PropsWithChildren } from 'react';
|
|
7
6
|
|
|
8
|
-
import { type ThemedClassName, useTranslation } from '@dxos/react-ui';
|
|
9
|
-
import { hoverableControlItem, hoverableFocusedWithinControls, mx } from '@dxos/
|
|
7
|
+
import { Icon, type ThemedClassName, useTranslation } from '@dxos/react-ui';
|
|
8
|
+
import { hoverableControlItem, hoverableFocusedWithinControls, mx } from '@dxos/ui-theme';
|
|
9
|
+
|
|
10
|
+
import { translationKey } from '#translations';
|
|
10
11
|
|
|
11
|
-
import { translationKey } from '../translations';
|
|
12
12
|
import type { ThreadEntity } from '../types';
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
// TODO(burdon): Avoid exporting fragments.
|
|
15
|
+
export const threadLayout = 'w-full place-self-start grid grid-cols-[var(--dx-rail-size)_1fr]';
|
|
16
|
+
|
|
17
|
+
//
|
|
18
|
+
// Root
|
|
19
|
+
//
|
|
15
20
|
|
|
16
|
-
|
|
21
|
+
type ThreadRootProps = ThemedClassName<
|
|
22
|
+
PropsWithChildren<
|
|
23
|
+
ThreadEntity & { current?: boolean } & Pick<ComponentPropsWithRef<'div'>, 'onClickCapture' | 'onFocusCapture'>
|
|
24
|
+
>
|
|
25
|
+
>;
|
|
17
26
|
|
|
18
|
-
|
|
27
|
+
const ThreadRoot = forwardRef<HTMLDivElement, ThreadRootProps>(
|
|
19
28
|
({ current, children, classNames, ...props }, forwardedRef) => {
|
|
20
29
|
return (
|
|
21
30
|
<div
|
|
@@ -26,8 +35,7 @@ export const Thread = forwardRef<HTMLDivElement, ThreadProps>(
|
|
|
26
35
|
className={mx(
|
|
27
36
|
threadLayout,
|
|
28
37
|
hoverableFocusedWithinControls,
|
|
29
|
-
'
|
|
30
|
-
'current-related attention-surface [--controls-opacity:0]',
|
|
38
|
+
'bg-[var(--surface-bg)] current-related dx-attention-surface [--controls-opacity:0]',
|
|
31
39
|
classNames,
|
|
32
40
|
)}
|
|
33
41
|
ref={forwardedRef}
|
|
@@ -38,24 +46,25 @@ export const Thread = forwardRef<HTMLDivElement, ThreadProps>(
|
|
|
38
46
|
},
|
|
39
47
|
);
|
|
40
48
|
|
|
41
|
-
|
|
49
|
+
//
|
|
50
|
+
// Heading
|
|
51
|
+
//
|
|
52
|
+
|
|
53
|
+
type ThreadHeaderProps = PropsWithChildren<{ detached?: boolean }>;
|
|
42
54
|
|
|
43
|
-
|
|
44
|
-
({
|
|
55
|
+
const ThreadHeader = forwardRef<HTMLParagraphElement, ThreadHeaderProps>(
|
|
56
|
+
({ children, detached, ...props }, forwardedRef) => {
|
|
45
57
|
return (
|
|
46
58
|
<>
|
|
47
59
|
<div role='none' className='flex items-center justify-center text-description'>
|
|
48
|
-
<
|
|
60
|
+
<Icon icon='ph--caret-double-right--regular' />
|
|
49
61
|
</div>
|
|
50
62
|
<div role='none' className='flex items-center overflow-hidden'>
|
|
51
63
|
<p
|
|
52
64
|
role='heading'
|
|
53
65
|
data-testid='thread.heading'
|
|
54
66
|
{...props}
|
|
55
|
-
className={mx(
|
|
56
|
-
'mie-2 text-description font-medium truncate italic',
|
|
57
|
-
detached && 'line-through decoration-1',
|
|
58
|
-
)}
|
|
67
|
+
className={mx('me-2 text-description font-medium truncate italic', detached && 'line-through decoration-1')}
|
|
59
68
|
ref={forwardedRef}
|
|
60
69
|
>
|
|
61
70
|
{children}
|
|
@@ -66,32 +75,44 @@ export const ThreadHeading = forwardRef<HTMLParagraphElement, ThreadHeadingProps
|
|
|
66
75
|
},
|
|
67
76
|
);
|
|
68
77
|
|
|
69
|
-
|
|
78
|
+
//
|
|
79
|
+
// Status
|
|
80
|
+
//
|
|
81
|
+
|
|
82
|
+
type ThreadStatusProps = ThemedClassName<PropsWithChildren> & {
|
|
70
83
|
activity?: boolean;
|
|
71
84
|
};
|
|
72
85
|
|
|
73
|
-
|
|
86
|
+
const ThreadStatus = forwardRef<HTMLDivElement, ThreadStatusProps>(
|
|
74
87
|
({ activity, classNames, children, ...props }, forwardedRef) => {
|
|
75
88
|
const { t } = useTranslation(translationKey);
|
|
76
89
|
return (
|
|
77
90
|
<div
|
|
78
91
|
{...props}
|
|
79
92
|
className={mx(
|
|
80
|
-
'col-start-2 grid grid-cols-[min-content_1fr_max-content] pb-2
|
|
93
|
+
'col-start-2 grid grid-cols-[min-content_1fr_max-content] pb-2 pe-2 text-xs text-description',
|
|
81
94
|
classNames,
|
|
82
95
|
)}
|
|
83
96
|
ref={forwardedRef}
|
|
84
97
|
>
|
|
85
|
-
<
|
|
86
|
-
|
|
98
|
+
<Icon
|
|
99
|
+
icon='ph--spinner--bold'
|
|
100
|
+
classNames='w-6 h-4 invisible data-[visible=show]:visible animate-spin-slow'
|
|
87
101
|
data-visible={activity ? 'show' : 'hide'}
|
|
88
|
-
className='is-6 bs-4 invisible data-[visible=show]:visible animate-spin-slow'
|
|
89
102
|
/>
|
|
90
|
-
<span className='truncate min-
|
|
103
|
+
<span className='truncate min-w-0' aria-live='polite'>
|
|
91
104
|
{activity ? children : null}
|
|
92
105
|
</span>
|
|
93
|
-
<span className={mx('text-end', hoverableControlItem)}>{t('enter
|
|
106
|
+
<span className={mx('text-end', hoverableControlItem)}>{t('enter-to-send.message')}</span>
|
|
94
107
|
</div>
|
|
95
108
|
);
|
|
96
109
|
},
|
|
97
110
|
);
|
|
111
|
+
|
|
112
|
+
export const Thread = {
|
|
113
|
+
Root: ThreadRoot,
|
|
114
|
+
Header: ThreadHeader,
|
|
115
|
+
Status: ThreadStatus,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export type { ThreadRootProps, ThreadHeaderProps, ThreadStatusProps };
|
package/src/index.ts
CHANGED
package/src/testing.tsx
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
import React, { type PropsWithChildren } from 'react';
|
|
5
|
+
import React from 'react';
|
|
7
6
|
|
|
8
|
-
import {
|
|
9
|
-
import { hoverableControlItem, hoverableControls, hoverableFocusedWithinControls, mx } from '@dxos/
|
|
7
|
+
import { IconButton } from '@dxos/react-ui';
|
|
8
|
+
import { hoverableControlItem, hoverableControls, hoverableFocusedWithinControls, mx } from '@dxos/ui-theme';
|
|
10
9
|
|
|
11
10
|
import { MessageBody, MessageHeading } from './Message';
|
|
12
11
|
import { type MessageMetadata } from './types';
|
|
@@ -26,13 +25,14 @@ export const MessageStoryText = ({ text, onDelete, authorName, timestamp }: Mess
|
|
|
26
25
|
<>
|
|
27
26
|
<MessageHeading authorName={authorName} timestamp={timestamp}>
|
|
28
27
|
{onDelete && (
|
|
29
|
-
<
|
|
28
|
+
<IconButton
|
|
29
|
+
icon='ph--x--regular'
|
|
30
|
+
iconOnly
|
|
31
|
+
label='Delete'
|
|
30
32
|
variant='ghost'
|
|
31
|
-
classNames={['p-1.5 min-
|
|
33
|
+
classNames={['p-1.5 min-h-0 me-1 items-start transition-opacity', hoverableControlItem]}
|
|
32
34
|
onClick={() => onDelete()}
|
|
33
|
-
|
|
34
|
-
<X />
|
|
35
|
-
</Button>
|
|
35
|
+
/>
|
|
36
36
|
)}
|
|
37
37
|
</MessageHeading>
|
|
38
38
|
<MessageBody>{text}</MessageBody>
|
|
@@ -50,13 +50,9 @@ export const MessageStoryBlock = <PartValue,>({ part }: MessagePartProps<PartVal
|
|
|
50
50
|
role='none'
|
|
51
51
|
className={mx('grid grid-cols-subgrid col-span-3', hoverableControls, hoverableFocusedWithinControls)}
|
|
52
52
|
>
|
|
53
|
-
<pre className='font-mono max-
|
|
53
|
+
<pre className='font-mono max-w-full overflow-x-auto col-span-3'>
|
|
54
54
|
<code>{JSON.stringify(part, undefined, 2)}</code>
|
|
55
55
|
</pre>
|
|
56
56
|
</div>
|
|
57
57
|
);
|
|
58
58
|
};
|
|
59
|
-
|
|
60
|
-
export const ThreadStoryContainer = ({ children }: PropsWithChildren) => {
|
|
61
|
-
return <div className={mx('bg-white dark:bg-black mli-auto is-96 overflow-y-auto')}>{children}</div>;
|
|
62
|
-
};
|
package/src/translations.ts
CHANGED
|
@@ -2,23 +2,25 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import { type Resource } from '@dxos/react-ui';
|
|
6
6
|
|
|
7
|
-
export
|
|
7
|
+
export const translationKey = '@dxos/react-ui-thread';
|
|
8
|
+
|
|
9
|
+
export const translations = [
|
|
8
10
|
{
|
|
9
11
|
'en-US': {
|
|
10
12
|
[translationKey]: {
|
|
11
|
-
'plugin
|
|
12
|
-
'thread
|
|
13
|
-
'thread
|
|
14
|
-
'delete
|
|
15
|
-
'create
|
|
16
|
-
'message
|
|
17
|
-
'comment
|
|
18
|
-
'settings
|
|
19
|
-
'anonymous
|
|
20
|
-
'enter
|
|
13
|
+
'plugin.name': 'Threads',
|
|
14
|
+
'thread-title.placeholder': 'New thread',
|
|
15
|
+
'thread-title.label': 'Title',
|
|
16
|
+
'delete-thread.label': 'Delete',
|
|
17
|
+
'create-thread.label': 'Create thread',
|
|
18
|
+
'message.placeholder': 'Enter message...',
|
|
19
|
+
'comment.placeholder': 'Enter comment...',
|
|
20
|
+
'settings-standalone.label': 'Enable standalone thread creation',
|
|
21
|
+
'anonymous.label': 'Anonymous',
|
|
22
|
+
'enter-to-send.message': 'Enter to add ⏎',
|
|
21
23
|
},
|
|
22
24
|
},
|
|
23
25
|
},
|
|
24
|
-
];
|
|
26
|
+
] as const satisfies Resource[];
|