@dxos/react-ui-thread 0.4.10-main.6134ea4 → 0.4.10-main.6f3f81d
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/types/src/Thread/Comments.stories.d.ts +2 -2
- package/dist/types/src/Thread/Comments.stories.d.ts.map +1 -1
- package/dist/types/src/Thread/Thread.stories.d.ts.map +1 -1
- package/package.json +13 -12
- package/src/Thread/Comments.stories.tsx +34 -26
- package/src/Thread/Thread.stories.tsx +25 -9
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '@dxosTheme';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { TextV0Type } from '@braneframe/types';
|
|
4
4
|
import { type Range } from '@dxos/react-ui-editor';
|
|
5
5
|
import { type MessageEntity } from '../types';
|
|
6
6
|
type StoryCommentThread = {
|
|
@@ -9,7 +9,7 @@ type StoryCommentThread = {
|
|
|
9
9
|
range?: Range;
|
|
10
10
|
yPos?: number;
|
|
11
11
|
messages: MessageEntity<{
|
|
12
|
-
|
|
12
|
+
content?: TextV0Type;
|
|
13
13
|
}>[];
|
|
14
14
|
};
|
|
15
15
|
type StoryProps = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Comments.stories.d.ts","sourceRoot":"","sources":["../../../../src/Thread/Comments.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AAGpB,OAAO,KAAwD,MAAM,OAAO,CAAC;AAE7E,OAAO,
|
|
1
|
+
{"version":3,"file":"Comments.stories.d.ts","sourceRoot":"","sources":["../../../../src/Thread/Comments.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AAGpB,OAAO,KAAwD,MAAM,OAAO,CAAC;AAE7E,OAAO,EAAe,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAM5D,OAAO,EAML,KAAK,KAAK,EAMX,MAAM,uBAAuB,CAAC;AAM/B,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAmE9C,KAAK,kBAAkB,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,CAAC;QAAE,OAAO,CAAC,EAAE,UAAU,CAAA;KAAE,CAAC,EAAE,CAAC;CACrD,CAAC;AA6IF,KAAK,UAAU,GAAG;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;;;;;;;;;;mBA+He,UAAU;;;;;;;;;;;;;;;;;;;;;AAJ3B,wBAME;AAWF,eAAO,MAAM,OAAO;;;;CAInB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Thread.stories.d.ts","sourceRoot":"","sources":["../../../../src/Thread/Thread.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AACpB,OAAO,
|
|
1
|
+
{"version":3,"file":"Thread.stories.d.ts","sourceRoot":"","sources":["../../../../src/Thread/Thread.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AACpB,OAAO,KAAoC,MAAM,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AAwFzD,wBAME;AAEF,eAAO,MAAM,OAAO,IAAK,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-thread",
|
|
3
|
-
"version": "0.4.10-main.
|
|
3
|
+
"version": "0.4.10-main.6f3f81d",
|
|
4
4
|
"description": "A set of components to use with threads, including comments and messages.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@radix-ui/react-primitive": "^1.0.2",
|
|
20
20
|
"date-fns": "^3.3.1",
|
|
21
|
-
"@dxos/react-ui": "0.4.10-main.
|
|
22
|
-
"@dxos/react-ui-
|
|
23
|
-
"@dxos/react-ui-
|
|
24
|
-
"@dxos/
|
|
25
|
-
"@dxos/
|
|
21
|
+
"@dxos/react-ui-editor": "0.4.10-main.6f3f81d",
|
|
22
|
+
"@dxos/react-ui-mosaic": "0.4.10-main.6f3f81d",
|
|
23
|
+
"@dxos/react-ui-theme": "0.4.10-main.6f3f81d",
|
|
24
|
+
"@dxos/util": "0.4.10-main.6f3f81d",
|
|
25
|
+
"@dxos/react-ui": "0.4.10-main.6f3f81d"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@phosphor-icons/react": "^2.0.5",
|
|
@@ -30,13 +30,14 @@
|
|
|
30
30
|
"@types/react-dom": "^18.0.6",
|
|
31
31
|
"react": "^18.2.0",
|
|
32
32
|
"react-dom": "^18.2.0",
|
|
33
|
-
"vite": "^5.1.
|
|
33
|
+
"vite": "^5.1.7",
|
|
34
34
|
"vite-plugin-turbosnap": "^1.0.2",
|
|
35
|
-
"@
|
|
36
|
-
"@dxos/
|
|
37
|
-
"@dxos/
|
|
38
|
-
"@dxos/
|
|
39
|
-
"@dxos/
|
|
35
|
+
"@braneframe/types": "0.4.10-main.6f3f81d",
|
|
36
|
+
"@dxos/echo-schema": "0.4.10-main.6f3f81d",
|
|
37
|
+
"@dxos/keys": "0.4.10-main.6f3f81d",
|
|
38
|
+
"@dxos/log": "0.4.10-main.6f3f81d",
|
|
39
|
+
"@dxos/random": "0.4.10-main.6f3f81d",
|
|
40
|
+
"@dxos/storybook-utils": "0.4.10-main.6f3f81d"
|
|
40
41
|
},
|
|
41
42
|
"peerDependencies": {
|
|
42
43
|
"@phosphor-icons/react": "^2.0.5",
|
|
@@ -7,7 +7,8 @@ import '@dxosTheme';
|
|
|
7
7
|
import { Check, Trash } from '@phosphor-icons/react';
|
|
8
8
|
import React, { type FC, useEffect, useMemo, useRef, useState } from 'react';
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { MessageType, TextV0Type } from '@braneframe/types';
|
|
11
|
+
import { createDocAccessor, create } from '@dxos/echo-schema';
|
|
11
12
|
import { PublicKey } from '@dxos/keys';
|
|
12
13
|
import { log } from '@dxos/log';
|
|
13
14
|
import { faker } from '@dxos/random';
|
|
@@ -23,7 +24,7 @@ import {
|
|
|
23
24
|
createBasicExtensions,
|
|
24
25
|
createThemeExtensions,
|
|
25
26
|
automerge,
|
|
26
|
-
|
|
27
|
+
listener,
|
|
27
28
|
} from '@dxos/react-ui-editor';
|
|
28
29
|
import { withTheme } from '@dxos/storybook-utils';
|
|
29
30
|
|
|
@@ -42,7 +43,7 @@ const authorId = PublicKey.random().toHex();
|
|
|
42
43
|
|
|
43
44
|
const Editor: FC<{
|
|
44
45
|
id?: string;
|
|
45
|
-
item:
|
|
46
|
+
item: TextV0Type;
|
|
46
47
|
comments: Comment[];
|
|
47
48
|
selected?: string;
|
|
48
49
|
onCreateComment: CommentsOptions['onCreate'];
|
|
@@ -62,15 +63,14 @@ const Editor: FC<{
|
|
|
62
63
|
const [selected, setSelected] = useState<string>();
|
|
63
64
|
|
|
64
65
|
const { themeMode } = useThemeContext();
|
|
65
|
-
const { doc, accessor } = useDocAccessor(item.text);
|
|
66
66
|
const { parentRef, view } = useTextEditor(
|
|
67
67
|
() => ({
|
|
68
68
|
id,
|
|
69
|
-
doc,
|
|
69
|
+
doc: item.content,
|
|
70
70
|
extensions: [
|
|
71
71
|
createBasicExtensions(),
|
|
72
72
|
createThemeExtensions({ themeMode }),
|
|
73
|
-
automerge(
|
|
73
|
+
automerge(createDocAccessor(item, ['content'])),
|
|
74
74
|
comments({
|
|
75
75
|
onCreate: onCreateComment,
|
|
76
76
|
onDelete: onDeleteComment,
|
|
@@ -79,7 +79,7 @@ const Editor: FC<{
|
|
|
79
79
|
}),
|
|
80
80
|
],
|
|
81
81
|
}),
|
|
82
|
-
[
|
|
82
|
+
[id, item, themeMode],
|
|
83
83
|
);
|
|
84
84
|
useComments(view, id, commentRanges);
|
|
85
85
|
useEffect(() => {
|
|
@@ -103,12 +103,13 @@ type StoryCommentThread = {
|
|
|
103
103
|
cursor?: string;
|
|
104
104
|
range?: Range;
|
|
105
105
|
yPos?: number;
|
|
106
|
-
messages: MessageEntity<{
|
|
106
|
+
messages: MessageEntity<{ content?: TextV0Type }>[];
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
-
const StoryMessageBlock = (props: MessageBlockProps<{
|
|
109
|
+
const StoryMessageBlock = (props: MessageBlockProps<{ content?: TextV0Type }>) => {
|
|
110
110
|
const { themeMode } = useThemeContext();
|
|
111
|
-
const
|
|
111
|
+
const doc = props.block.content?.content;
|
|
112
|
+
const accessor = createDocAccessor(props.block.content!, ['content']);
|
|
112
113
|
const { parentRef } = useTextEditor(
|
|
113
114
|
() => ({
|
|
114
115
|
doc,
|
|
@@ -133,15 +134,17 @@ const StoryThread: FC<{
|
|
|
133
134
|
}> = ({ thread, selected, onSelect, onResolve }) => {
|
|
134
135
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
135
136
|
const { themeMode } = useThemeContext();
|
|
136
|
-
|
|
137
|
-
const
|
|
137
|
+
// TODO(wittjosiah): This is a hack to reset the editor after a message is sent.
|
|
138
|
+
const [_count, _setCount] = useState(0);
|
|
139
|
+
const rerenderEditor = () => _setCount((count) => count + 1);
|
|
140
|
+
const messageRef = useRef('');
|
|
138
141
|
const extensions = useMemo(
|
|
139
142
|
() => [
|
|
140
143
|
createBasicExtensions({ placeholder: 'Enter comment' }),
|
|
141
144
|
createThemeExtensions({ themeMode }),
|
|
142
|
-
|
|
145
|
+
listener({ onChange: (text) => (messageRef.current = text) }),
|
|
143
146
|
],
|
|
144
|
-
[themeMode,
|
|
147
|
+
[themeMode, _count],
|
|
145
148
|
);
|
|
146
149
|
|
|
147
150
|
const [autoFocus, setAutoFocus] = useState(false);
|
|
@@ -156,15 +159,21 @@ const StoryThread: FC<{
|
|
|
156
159
|
}, [selected]);
|
|
157
160
|
|
|
158
161
|
const handleCreateMessage = () => {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
162
|
+
if (messageRef.current?.length) {
|
|
163
|
+
const message = create(MessageType, {
|
|
164
|
+
from: { identityKey: authorId },
|
|
165
|
+
blocks: [
|
|
166
|
+
{
|
|
167
|
+
timestamp: new Date().toISOString(),
|
|
168
|
+
content: create(TextV0Type, { content: messageRef.current }),
|
|
169
|
+
},
|
|
170
|
+
],
|
|
165
171
|
});
|
|
166
|
-
|
|
172
|
+
thread.messages.push(message);
|
|
173
|
+
|
|
174
|
+
messageRef.current = '';
|
|
167
175
|
setAutoFocus(true);
|
|
176
|
+
rerenderEditor();
|
|
168
177
|
}
|
|
169
178
|
};
|
|
170
179
|
|
|
@@ -182,13 +191,12 @@ const StoryThread: FC<{
|
|
|
182
191
|
</ThreadHeading>
|
|
183
192
|
|
|
184
193
|
{thread.messages.map((message) => (
|
|
185
|
-
<Message<{
|
|
194
|
+
<Message<{ content?: TextV0Type }> key={message.id} {...message} MessageBlockComponent={StoryMessageBlock} />
|
|
186
195
|
))}
|
|
187
196
|
|
|
188
197
|
<div ref={containerRef} className='contents'>
|
|
189
198
|
<MessageTextbox
|
|
190
|
-
id={
|
|
191
|
-
doc={doc}
|
|
199
|
+
id={thread.id}
|
|
192
200
|
authorId={authorId}
|
|
193
201
|
autoFocus={autoFocus}
|
|
194
202
|
extensions={extensions}
|
|
@@ -243,7 +251,7 @@ type StoryProps = {
|
|
|
243
251
|
};
|
|
244
252
|
|
|
245
253
|
const Story = ({ text, autoCreate }: StoryProps) => {
|
|
246
|
-
const [item] = useState({
|
|
254
|
+
const [item] = useState(create(TextV0Type, { content: text ?? '' }));
|
|
247
255
|
const [threads, setThreads] = useState<StoryCommentThread[]>([]);
|
|
248
256
|
const [selected, setSelected] = useState<string>();
|
|
249
257
|
|
|
@@ -269,7 +277,7 @@ const Story = ({ text, autoCreate }: StoryProps) => {
|
|
|
269
277
|
blocks: [
|
|
270
278
|
{
|
|
271
279
|
timestamp: new Date().toISOString(),
|
|
272
|
-
|
|
280
|
+
content: create(TextV0Type, { content: faker.lorem.sentence() }),
|
|
273
281
|
},
|
|
274
282
|
],
|
|
275
283
|
}),
|
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import '@dxosTheme';
|
|
6
|
-
import React, { useMemo, useState } from 'react';
|
|
6
|
+
import React, { useMemo, useRef, useState } from 'react';
|
|
7
7
|
|
|
8
|
-
import { setTextContent, TextObject } from '@dxos/echo-schema';
|
|
9
8
|
import { PublicKey } from '@dxos/keys';
|
|
10
|
-
import {
|
|
9
|
+
import { createBasicExtensions, createThemeExtensions } from '@dxos/react-ui-editor';
|
|
11
10
|
import { withTheme } from '@dxos/storybook-utils';
|
|
12
11
|
|
|
13
12
|
import { Thread, ThreadFooter } from './Thread';
|
|
@@ -19,7 +18,7 @@ const Story = () => {
|
|
|
19
18
|
const [pending, setPending] = useState(false);
|
|
20
19
|
const [identityKey1] = useState(PublicKey.random());
|
|
21
20
|
const [identityKey2] = useState(PublicKey.random());
|
|
22
|
-
const [messages] = useState<MessageEntity<{ id: string; text: string }>[]>([
|
|
21
|
+
const [messages, setMesssages] = useState<MessageEntity<{ id: string; text: string }>[]>([
|
|
23
22
|
{
|
|
24
23
|
id: 'm1',
|
|
25
24
|
authorId: identityKey1.toHex(),
|
|
@@ -44,17 +43,34 @@ const Story = () => {
|
|
|
44
43
|
},
|
|
45
44
|
]);
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
const
|
|
46
|
+
// TODO(wittjosiah): This is a hack to reset the editor after a message is sent.
|
|
47
|
+
const [_count, _setCount] = useState(3);
|
|
48
|
+
const rerenderEditor = () => _setCount((count) => count + 1);
|
|
49
|
+
const messageRef = useRef('');
|
|
50
|
+
const extensions = useMemo(() => [createBasicExtensions(), createThemeExtensions()], []);
|
|
50
51
|
|
|
51
52
|
// TODO(thure): Why does pressing Enter clear the text content?
|
|
52
53
|
// Something to do with the in-memory text model perhaps?
|
|
53
54
|
const handleSend = () => {
|
|
54
55
|
setPending(true);
|
|
55
56
|
setTimeout(() => {
|
|
56
|
-
|
|
57
|
+
setMesssages((messages) => [
|
|
58
|
+
...messages,
|
|
59
|
+
{
|
|
60
|
+
id: `m${_count}`,
|
|
61
|
+
authorId: identityKey1.toHex(),
|
|
62
|
+
blocks: [
|
|
63
|
+
{
|
|
64
|
+
id: `b${_count}`,
|
|
65
|
+
timestamp: new Date().toISOString(),
|
|
66
|
+
text: messageRef.current,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
]);
|
|
71
|
+
messageRef.current = '';
|
|
57
72
|
setPending(false);
|
|
73
|
+
rerenderEditor();
|
|
58
74
|
}, 2_000);
|
|
59
75
|
};
|
|
60
76
|
|
|
@@ -64,7 +80,7 @@ const Story = () => {
|
|
|
64
80
|
<Message key={message.id} {...message} />
|
|
65
81
|
))}
|
|
66
82
|
<MessageTextbox
|
|
67
|
-
id={
|
|
83
|
+
id={String(_count)}
|
|
68
84
|
authorId={identityKey1.toHex()}
|
|
69
85
|
disabled={pending}
|
|
70
86
|
extensions={extensions}
|