@dxos/react-ui-thread 0.4.10-main.7ce71da → 0.4.10-main.8583d5a
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 +35 -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;AAO5D,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.8583d5a",
|
|
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.8583d5a",
|
|
22
|
+
"@dxos/react-ui": "0.4.10-main.8583d5a",
|
|
23
|
+
"@dxos/react-ui-mosaic": "0.4.10-main.8583d5a",
|
|
24
|
+
"@dxos/util": "0.4.10-main.8583d5a",
|
|
25
|
+
"@dxos/react-ui-theme": "0.4.10-main.8583d5a"
|
|
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/keys": "0.4.10-main.
|
|
38
|
-
"@dxos/random": "0.4.10-main.
|
|
39
|
-
"@dxos/
|
|
35
|
+
"@braneframe/types": "0.4.10-main.8583d5a",
|
|
36
|
+
"@dxos/echo-schema": "0.4.10-main.8583d5a",
|
|
37
|
+
"@dxos/keys": "0.4.10-main.8583d5a",
|
|
38
|
+
"@dxos/random": "0.4.10-main.8583d5a",
|
|
39
|
+
"@dxos/log": "0.4.10-main.8583d5a",
|
|
40
|
+
"@dxos/storybook-utils": "0.4.10-main.8583d5a"
|
|
40
41
|
},
|
|
41
42
|
"peerDependencies": {
|
|
42
43
|
"@phosphor-icons/react": "^2.0.5",
|
|
@@ -7,7 +7,9 @@ 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 * as E from '@dxos/echo-schema';
|
|
12
|
+
import { createDocAccessor } from '@dxos/echo-schema';
|
|
11
13
|
import { PublicKey } from '@dxos/keys';
|
|
12
14
|
import { log } from '@dxos/log';
|
|
13
15
|
import { faker } from '@dxos/random';
|
|
@@ -23,7 +25,7 @@ import {
|
|
|
23
25
|
createBasicExtensions,
|
|
24
26
|
createThemeExtensions,
|
|
25
27
|
automerge,
|
|
26
|
-
|
|
28
|
+
listener,
|
|
27
29
|
} from '@dxos/react-ui-editor';
|
|
28
30
|
import { withTheme } from '@dxos/storybook-utils';
|
|
29
31
|
|
|
@@ -42,7 +44,7 @@ const authorId = PublicKey.random().toHex();
|
|
|
42
44
|
|
|
43
45
|
const Editor: FC<{
|
|
44
46
|
id?: string;
|
|
45
|
-
item:
|
|
47
|
+
item: TextV0Type;
|
|
46
48
|
comments: Comment[];
|
|
47
49
|
selected?: string;
|
|
48
50
|
onCreateComment: CommentsOptions['onCreate'];
|
|
@@ -62,15 +64,14 @@ const Editor: FC<{
|
|
|
62
64
|
const [selected, setSelected] = useState<string>();
|
|
63
65
|
|
|
64
66
|
const { themeMode } = useThemeContext();
|
|
65
|
-
const { doc, accessor } = useDocAccessor(item.text);
|
|
66
67
|
const { parentRef, view } = useTextEditor(
|
|
67
68
|
() => ({
|
|
68
69
|
id,
|
|
69
|
-
doc,
|
|
70
|
+
doc: item.content,
|
|
70
71
|
extensions: [
|
|
71
72
|
createBasicExtensions(),
|
|
72
73
|
createThemeExtensions({ themeMode }),
|
|
73
|
-
automerge(
|
|
74
|
+
automerge(createDocAccessor(item, ['content'])),
|
|
74
75
|
comments({
|
|
75
76
|
onCreate: onCreateComment,
|
|
76
77
|
onDelete: onDeleteComment,
|
|
@@ -79,7 +80,7 @@ const Editor: FC<{
|
|
|
79
80
|
}),
|
|
80
81
|
],
|
|
81
82
|
}),
|
|
82
|
-
[
|
|
83
|
+
[id, item, themeMode],
|
|
83
84
|
);
|
|
84
85
|
useComments(view, id, commentRanges);
|
|
85
86
|
useEffect(() => {
|
|
@@ -103,12 +104,13 @@ type StoryCommentThread = {
|
|
|
103
104
|
cursor?: string;
|
|
104
105
|
range?: Range;
|
|
105
106
|
yPos?: number;
|
|
106
|
-
messages: MessageEntity<{
|
|
107
|
+
messages: MessageEntity<{ content?: TextV0Type }>[];
|
|
107
108
|
};
|
|
108
109
|
|
|
109
|
-
const StoryMessageBlock = (props: MessageBlockProps<{
|
|
110
|
+
const StoryMessageBlock = (props: MessageBlockProps<{ content?: TextV0Type }>) => {
|
|
110
111
|
const { themeMode } = useThemeContext();
|
|
111
|
-
const
|
|
112
|
+
const doc = props.block.content?.content;
|
|
113
|
+
const accessor = E.createDocAccessor(props.block.content!, ['content']);
|
|
112
114
|
const { parentRef } = useTextEditor(
|
|
113
115
|
() => ({
|
|
114
116
|
doc,
|
|
@@ -133,15 +135,17 @@ const StoryThread: FC<{
|
|
|
133
135
|
}> = ({ thread, selected, onSelect, onResolve }) => {
|
|
134
136
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
135
137
|
const { themeMode } = useThemeContext();
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
+
// TODO(wittjosiah): This is a hack to reset the editor after a message is sent.
|
|
139
|
+
const [_count, _setCount] = useState(0);
|
|
140
|
+
const rerenderEditor = () => _setCount((count) => count + 1);
|
|
141
|
+
const messageRef = useRef('');
|
|
138
142
|
const extensions = useMemo(
|
|
139
143
|
() => [
|
|
140
144
|
createBasicExtensions({ placeholder: 'Enter comment' }),
|
|
141
145
|
createThemeExtensions({ themeMode }),
|
|
142
|
-
|
|
146
|
+
listener({ onChange: (text) => (messageRef.current = text) }),
|
|
143
147
|
],
|
|
144
|
-
[themeMode,
|
|
148
|
+
[themeMode, _count],
|
|
145
149
|
);
|
|
146
150
|
|
|
147
151
|
const [autoFocus, setAutoFocus] = useState(false);
|
|
@@ -156,15 +160,21 @@ const StoryThread: FC<{
|
|
|
156
160
|
}, [selected]);
|
|
157
161
|
|
|
158
162
|
const handleCreateMessage = () => {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
if (messageRef.current?.length) {
|
|
164
|
+
const message = E.object(MessageType, {
|
|
165
|
+
from: { identityKey: authorId },
|
|
166
|
+
blocks: [
|
|
167
|
+
{
|
|
168
|
+
timestamp: new Date().toISOString(),
|
|
169
|
+
content: E.object(TextV0Type, { content: messageRef.current }),
|
|
170
|
+
},
|
|
171
|
+
],
|
|
165
172
|
});
|
|
166
|
-
|
|
173
|
+
thread.messages.push(message);
|
|
174
|
+
|
|
175
|
+
messageRef.current = '';
|
|
167
176
|
setAutoFocus(true);
|
|
177
|
+
rerenderEditor();
|
|
168
178
|
}
|
|
169
179
|
};
|
|
170
180
|
|
|
@@ -182,13 +192,12 @@ const StoryThread: FC<{
|
|
|
182
192
|
</ThreadHeading>
|
|
183
193
|
|
|
184
194
|
{thread.messages.map((message) => (
|
|
185
|
-
<Message<{
|
|
195
|
+
<Message<{ content?: TextV0Type }> key={message.id} {...message} MessageBlockComponent={StoryMessageBlock} />
|
|
186
196
|
))}
|
|
187
197
|
|
|
188
198
|
<div ref={containerRef} className='contents'>
|
|
189
199
|
<MessageTextbox
|
|
190
|
-
id={
|
|
191
|
-
doc={doc}
|
|
200
|
+
id={thread.id}
|
|
192
201
|
authorId={authorId}
|
|
193
202
|
autoFocus={autoFocus}
|
|
194
203
|
extensions={extensions}
|
|
@@ -243,7 +252,7 @@ type StoryProps = {
|
|
|
243
252
|
};
|
|
244
253
|
|
|
245
254
|
const Story = ({ text, autoCreate }: StoryProps) => {
|
|
246
|
-
const [item] = useState({
|
|
255
|
+
const [item] = useState(E.object(TextV0Type, { content: text ?? '' }));
|
|
247
256
|
const [threads, setThreads] = useState<StoryCommentThread[]>([]);
|
|
248
257
|
const [selected, setSelected] = useState<string>();
|
|
249
258
|
|
|
@@ -269,7 +278,7 @@ const Story = ({ text, autoCreate }: StoryProps) => {
|
|
|
269
278
|
blocks: [
|
|
270
279
|
{
|
|
271
280
|
timestamp: new Date().toISOString(),
|
|
272
|
-
|
|
281
|
+
content: E.object(TextV0Type, { content: faker.lorem.sentence() }),
|
|
273
282
|
},
|
|
274
283
|
],
|
|
275
284
|
}),
|
|
@@ -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}
|