@dxos/react-ui-thread 0.10.0 → 0.11.0

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.
Files changed (39) hide show
  1. package/dist/lib/index.mjs +738 -0
  2. package/dist/lib/index.mjs.map +1 -0
  3. package/dist/lib/translations.mjs +25 -0
  4. package/dist/lib/translations.mjs.map +1 -0
  5. package/dist/types/src/Message/Message.d.ts +19 -2
  6. package/dist/types/src/Message/Message.d.ts.map +1 -1
  7. package/dist/types/src/Message/Message.stories.d.ts +3 -0
  8. package/dist/types/src/Message/Message.stories.d.ts.map +1 -1
  9. package/dist/types/src/Message/index.d.ts +1 -1
  10. package/dist/types/src/Message/index.d.ts.map +1 -1
  11. package/dist/types/src/Thread/Thread.d.ts +20 -6
  12. package/dist/types/src/Thread/Thread.d.ts.map +1 -1
  13. package/dist/types/src/Thread/Thread.stories.d.ts +4 -0
  14. package/dist/types/src/Thread/Thread.stories.d.ts.map +1 -1
  15. package/dist/types/src/context.d.ts +1 -0
  16. package/dist/types/src/context.d.ts.map +1 -1
  17. package/dist/types/src/index.d.ts +1 -1
  18. package/dist/types/src/index.d.ts.map +1 -1
  19. package/dist/types/src/translations.d.ts +2 -0
  20. package/dist/types/src/translations.d.ts.map +1 -1
  21. package/dist/types/src/types.d.ts +9 -1
  22. package/dist/types/src/types.d.ts.map +1 -1
  23. package/dist/types/tsconfig.tsbuildinfo +1 -1
  24. package/package.json +24 -24
  25. package/src/Message/Message.stories.tsx +52 -0
  26. package/src/Message/Message.tsx +181 -9
  27. package/src/Message/index.ts +1 -0
  28. package/src/Thread/Thread.stories.tsx +78 -1
  29. package/src/Thread/Thread.tsx +173 -19
  30. package/src/index.ts +1 -0
  31. package/src/translations.ts +2 -0
  32. package/src/types.ts +9 -1
  33. package/dist/lib/browser/chunk-QFRRLZVL.mjs +0 -31
  34. package/dist/lib/browser/chunk-QFRRLZVL.mjs.map +0 -7
  35. package/dist/lib/browser/index.mjs +0 -554
  36. package/dist/lib/browser/index.mjs.map +0 -7
  37. package/dist/lib/browser/meta.json +0 -1
  38. package/dist/lib/browser/translations.mjs +0 -9
  39. package/dist/lib/browser/translations.mjs.map +0 -7
@@ -1,554 +0,0 @@
1
- import {
2
- translationKey
3
- } from "./chunk-QFRRLZVL.mjs";
4
-
5
- // src/Thread/Thread.tsx
6
- import React2, { forwardRef as forwardRef2, useCallback as useCallback2, useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
7
- import { Obj as Obj2 } from "@dxos/echo";
8
- import { Icon, IconButton as IconButton2, ScrollArea, composable, composableProps, useThemeContext as useThemeContext2, useTranslation as useTranslation2 } from "@dxos/react-ui";
9
- import { Mosaic } from "@dxos/react-ui-mosaic";
10
- import { createBasicExtensions as createBasicExtensions2, createThemeExtensions as createThemeExtensions2, listener as listener2 } from "@dxos/ui-editor";
11
- import { hoverableControlItem as hoverableControlItem2, hoverableControls as hoverableControls2, hoverableFocusedWithinControls as hoverableFocusedWithinControls2, mx as mx3 } from "@dxos/ui-theme";
12
-
13
- // src/command.ts
14
- import { HighlightStyle, StreamLanguage, syntaxHighlighting } from "@codemirror/language";
15
- import { EditorView } from "@codemirror/view";
16
- import { tags } from "@dxos/ui-editor";
17
- import { mx } from "@dxos/ui-theme";
18
- var parser = StreamLanguage.define({
19
- startState: () => ({
20
- count: 0
21
- }),
22
- token: (stream, state) => {
23
- state.count++;
24
- if (stream.eatSpace()) {
25
- return null;
26
- }
27
- if (state.count === 1 && stream.match(/^\/\w+/)) {
28
- return "tagName";
29
- }
30
- if (stream.match(/^@\w+/)) {
31
- return "labelName";
32
- }
33
- stream.next();
34
- return null;
35
- }
36
- });
37
- var styles = HighlightStyle.define([
38
- {
39
- tag: tags.tagName,
40
- class: mx("dx-tag dx-tag--indigo")
41
- },
42
- {
43
- tag: tags.labelName,
44
- class: mx("dx-tag dx-tag--blue")
45
- }
46
- ]);
47
- var theme = EditorView.theme({
48
- ".dx-tag": {
49
- verticalAlign: "bottom"
50
- }
51
- });
52
- var command = [
53
- parser,
54
- syntaxHighlighting(styles),
55
- theme
56
- ];
57
-
58
- // src/context.ts
59
- import { createContext } from "@radix-ui/react-context";
60
- var [ThreadContextProvider, useThreadContext] = createContext("Thread");
61
-
62
- // src/Message/Message.tsx
63
- import { EditorView as EditorView2 } from "@codemirror/view";
64
- import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
65
- import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
66
- import { Obj, Ref } from "@dxos/echo";
67
- import { Avatar, IconButton, useOnTransition, useThemeContext, useTranslation } from "@dxos/react-ui";
68
- import { useTextEditor } from "@dxos/react-ui-editor";
69
- import { createBasicExtensions, createThemeExtensions, keymap, listener } from "@dxos/ui-editor";
70
- import { hoverableControlItem, hoverableControls, hoverableFocusedWithinControls, mx as mx2 } from "@dxos/ui-theme";
71
- import { hexToEmoji, hexToHue, isTruthy } from "@dxos/util";
72
- var avatarSize = 7;
73
- var buttonGroupClassNames = "flex flex-row items-center gap-0.5 pe-2";
74
- var buttonClassNames = "p-1! transition-opacity";
75
- var MessageRoot = /* @__PURE__ */ forwardRef(({ authorImgSrc, authorId, authorName, authorAvatarProps, continues = true, controls, children, classNames, ...rootProps }, forwardedRef) => {
76
- return /* @__PURE__ */ React.createElement(Avatar.Root, null, /* @__PURE__ */ React.createElement("div", {
77
- "data-testid": "thread.message",
78
- ...rootProps,
79
- className: mx2("grid grid-cols-[var(--dx-rail-size)_1fr_min-content] w-full", classNames),
80
- ref: forwardedRef
81
- }, /* @__PURE__ */ React.createElement("div", {
82
- className: "flex flex-col items-center gap-2 pt-1"
83
- }, /* @__PURE__ */ React.createElement(Avatar.Content, {
84
- size: avatarSize,
85
- hue: authorAvatarProps?.hue || hexToHue(authorId ?? "0"),
86
- fallback: authorAvatarProps?.emoji || hexToEmoji(authorId ?? "0"),
87
- ...authorImgSrc && {
88
- imgSrc: authorImgSrc
89
- }
90
- }), continues && /* @__PURE__ */ React.createElement("div", {
91
- className: "w-px grow bg-separator"
92
- })), /* @__PURE__ */ React.createElement("div", {
93
- className: "py-1 min-w-0"
94
- }, children), controls && /* @__PURE__ */ React.createElement("div", {
95
- className: "self-start"
96
- }, controls)));
97
- });
98
- MessageRoot.displayName = "Message.Root";
99
- var MessageHeading = ({ children, classNames, timestamp, authorName, ...props }) => {
100
- return /* @__PURE__ */ React.createElement("div", {
101
- ...props,
102
- className: mx2("flex gap-2 items-start", classNames)
103
- }, /* @__PURE__ */ React.createElement("p", {
104
- className: "grow"
105
- }, /* @__PURE__ */ React.createElement(MessageAuthorName, {
106
- authorName
107
- }), timestamp && /* @__PURE__ */ React.createElement(MessageTime, {
108
- timestamp
109
- })), children);
110
- };
111
- MessageHeading.displayName = "Message.Heading";
112
- var MessageAuthorName = ({ authorName }) => {
113
- const { t } = useTranslation(translationKey);
114
- return /* @__PURE__ */ React.createElement(Avatar.Label, {
115
- classNames: "block truncate text-sm text-subdued"
116
- }, authorName ?? t("anonymous.label"));
117
- };
118
- MessageAuthorName.displayName = "Message.AuthorName";
119
- var MessageTime = ({ timestamp }) => {
120
- const { dtLocale } = useTranslation(translationKey);
121
- const dt = timestamp ? new Date(timestamp) : void 0;
122
- return /* @__PURE__ */ React.createElement("time", {
123
- className: "block text-subdued text-xs pb-0.5",
124
- dateTime: dt?.toISOString()
125
- }, dt ? formatDistanceToNow(dt, {
126
- locale: dtLocale,
127
- addSuffix: true
128
- }) : "");
129
- };
130
- MessageTime.displayName = "Message.Time";
131
- var MessageBody = ({ message, isAuthor, editing, onSave }) => {
132
- const { components } = useThreadContext("Message.Body");
133
- const textBlockIndex = message.blocks.findIndex((block) => block._tag === "text");
134
- const textBlock = textBlockIndex !== -1 ? message.blocks[textBlockIndex] : void 0;
135
- const proposalBlock = message.blocks.find((block) => block._tag === "proposal");
136
- const references = message.blocks.filter((block) => block._tag === "reference").map((block) => block.reference);
137
- const Object = components.Object;
138
- return /* @__PURE__ */ React.createElement(React.Fragment, null, textBlock && /* @__PURE__ */ React.createElement(TextBlock, {
139
- block: textBlock,
140
- isAuthor,
141
- editing,
142
- onSave
143
- }), proposalBlock && /* @__PURE__ */ React.createElement("div", {
144
- className: "me-4 italic"
145
- }, proposalBlock.text), Object && Ref.Array.targets(references).map((reference, index) => /* @__PURE__ */ React.createElement(Object, {
146
- key: index,
147
- subject: reference
148
- })));
149
- };
150
- MessageBody.displayName = "Message.Body";
151
- var TextBlock = ({ block, isAuthor, editing, onSave }) => {
152
- const { themeMode } = useThemeContext();
153
- const inMemoryContentRef = useRef(block.text);
154
- const handleDocumentChange = useCallback((next) => {
155
- inMemoryContentRef.current = next;
156
- }, []);
157
- const saveDocumentChange = useCallback(() => {
158
- onSave?.(inMemoryContentRef.current);
159
- }, [
160
- onSave
161
- ]);
162
- useOnTransition(editing, true, false, saveDocumentChange);
163
- const { parentRef, focusAttributes, view } = useTextEditor(() => ({
164
- initialValue: block.text,
165
- extensions: [
166
- createBasicExtensions({
167
- readOnly: !isAuthor || !editing
168
- }),
169
- createThemeExtensions({
170
- themeMode
171
- }),
172
- command,
173
- EditorView2.updateListener.of((update) => {
174
- if (update.docChanged) {
175
- handleDocumentChange(update.state.doc.toString());
176
- }
177
- })
178
- ]
179
- }), [
180
- block.text,
181
- editing,
182
- isAuthor,
183
- themeMode,
184
- handleDocumentChange
185
- ]);
186
- useEffect(() => {
187
- if (editing) {
188
- view?.focus();
189
- }
190
- }, [
191
- editing,
192
- view
193
- ]);
194
- return /* @__PURE__ */ React.createElement("div", {
195
- ref: parentRef,
196
- className: "me-4",
197
- ...focusAttributes
198
- });
199
- };
200
- var keyBindings = ({ onSend, onClear }) => [
201
- {
202
- key: "Enter",
203
- run: () => {
204
- if (onSend) {
205
- onSend();
206
- return true;
207
- }
208
- return false;
209
- }
210
- },
211
- {
212
- key: "Meta+Backspace",
213
- run: () => {
214
- if (onClear) {
215
- onClear();
216
- return true;
217
- }
218
- return false;
219
- }
220
- }
221
- ];
222
- var MessageTextbox = /* @__PURE__ */ forwardRef(({ id, authorId, authorName, authorImgSrc, authorAvatarProps, disabled, extensions, onSend, onClear, onEditorFocus, ...editorProps }, forwardedRef) => {
223
- const { parentRef, focusAttributes, view } = useTextEditor(() => ({
224
- id,
225
- extensions: [
226
- keymap.of(keyBindings({
227
- onSend,
228
- onClear
229
- })),
230
- listener({
231
- onFocus: ({ focusing }) => {
232
- if (focusing) {
233
- onEditorFocus?.();
234
- }
235
- }
236
- }),
237
- extensions
238
- ].filter(isTruthy),
239
- ...editorProps
240
- }), [
241
- id,
242
- extensions
243
- ]);
244
- useImperativeHandle(forwardedRef, () => ({
245
- focus: () => view?.focus()
246
- }), [
247
- view
248
- ]);
249
- return /* @__PURE__ */ React.createElement(MessageRoot, {
250
- id,
251
- authorId,
252
- authorName,
253
- authorImgSrc,
254
- authorAvatarProps,
255
- continues: false
256
- }, /* @__PURE__ */ React.createElement("div", {
257
- ref: parentRef,
258
- className: mx2("py-0.5 me-1 rounded-xs dx-focus-ring", disabled && "opacity-50"),
259
- ...focusAttributes
260
- }));
261
- });
262
- MessageTextbox.displayName = "Message.Textbox";
263
- var MessageTile = ({ message, classNames }) => {
264
- const { t } = useTranslation(translationKey);
265
- const { getMetadata, identityDid, editable, onMessageDelete, onAcceptProposal } = useThreadContext("Message.Tile");
266
- const [editing, setEditing] = useState(false);
267
- const metadata = getMetadata(message);
268
- const isAuthor = !!identityDid && identityDid === metadata.authorId;
269
- const hasProposal = message.blocks.some((block) => block._tag === "proposal");
270
- const handleEdit = useCallback(() => setEditing((value) => !value), []);
271
- const handleDelete = useCallback(() => onMessageDelete?.(message.id), [
272
- onMessageDelete,
273
- message.id
274
- ]);
275
- const handleAcceptProposal = useCallback(() => onAcceptProposal?.(message.id), [
276
- onAcceptProposal,
277
- message.id
278
- ]);
279
- const handleSave = useCallback((text) => {
280
- Obj.update(message, (message2) => {
281
- const block = message2.blocks.find((block2) => block2._tag === "text");
282
- if (block && block._tag === "text") {
283
- block.text = text;
284
- }
285
- });
286
- }, [
287
- message
288
- ]);
289
- const showEdit = isAuthor && editable;
290
- const showAccept = hasProposal && !!onAcceptProposal;
291
- const showDelete = !!onMessageDelete;
292
- const controls = showEdit || showAccept || showDelete ? /* @__PURE__ */ React.createElement("div", {
293
- className: buttonGroupClassNames
294
- }, showEdit && /* @__PURE__ */ React.createElement(IconButton, {
295
- "data-testid": editing ? "thread.message.save" : "thread.message.edit",
296
- variant: "ghost",
297
- icon: editing ? "ph--check--regular" : "ph--pencil-simple--regular",
298
- iconOnly: true,
299
- label: t(editing ? "save-message.label" : "edit-message.label"),
300
- classNames: [
301
- buttonClassNames,
302
- hoverableControlItem
303
- ],
304
- onClick: handleEdit
305
- }), showAccept && /* @__PURE__ */ React.createElement(IconButton, {
306
- "data-testid": "thread.message.accept",
307
- variant: "ghost",
308
- icon: "ph--check--regular",
309
- iconOnly: true,
310
- label: t("accept-proposal.label"),
311
- classNames: [
312
- buttonClassNames,
313
- hoverableControlItem
314
- ],
315
- onClick: handleAcceptProposal
316
- }), showDelete && /* @__PURE__ */ React.createElement(IconButton, {
317
- "data-testid": "thread.message.delete",
318
- variant: "ghost",
319
- icon: "ph--x--regular",
320
- iconOnly: true,
321
- label: t("delete-message.label"),
322
- classNames: [
323
- buttonClassNames,
324
- hoverableControlItem
325
- ],
326
- onClick: handleDelete
327
- })) : void 0;
328
- return /* @__PURE__ */ React.createElement(MessageRoot, {
329
- ...metadata,
330
- controls,
331
- classNames: [
332
- hoverableControls,
333
- hoverableFocusedWithinControls,
334
- classNames
335
- ]
336
- }, /* @__PURE__ */ React.createElement(MessageHeading, {
337
- authorName: metadata.authorName,
338
- timestamp: metadata.timestamp
339
- }), /* @__PURE__ */ React.createElement(MessageBody, {
340
- message,
341
- isAuthor,
342
- editing,
343
- onSave: handleSave
344
- }));
345
- };
346
- MessageTile.displayName = "Message.Tile";
347
- var Message = {
348
- Root: MessageRoot,
349
- Heading: MessageHeading,
350
- AuthorName: MessageAuthorName,
351
- Time: MessageTime,
352
- Body: MessageBody,
353
- Textbox: MessageTextbox,
354
- Tile: MessageTile
355
- };
356
-
357
- // src/Thread/Thread.tsx
358
- var getMessageId = (message) => Obj2.getURI(message);
359
- var ThreadRoot = ({ children, getMetadata, components, identityDid, editable, onMessageDelete, onAcceptProposal }) => {
360
- const composerFocus = useRef2(void 0);
361
- const registerComposerFocus = useCallback2((focus) => {
362
- composerFocus.current = focus;
363
- }, []);
364
- const focusComposer = useCallback2(() => composerFocus.current?.(), []);
365
- return /* @__PURE__ */ React2.createElement(ThreadContextProvider, {
366
- getMetadata,
367
- components: components ?? {},
368
- identityDid,
369
- editable,
370
- registerComposerFocus,
371
- focusComposer,
372
- onMessageDelete,
373
- onAcceptProposal
374
- }, /* @__PURE__ */ React2.createElement(Mosaic.Root, null, children));
375
- };
376
- ThreadRoot.displayName = "Thread.Root";
377
- var ThreadContent = composable(({ children, current, id, ...props }, forwardedRef) => {
378
- return /* @__PURE__ */ React2.createElement("div", {
379
- ...composableProps(props, {
380
- role: "group",
381
- classNames: [
382
- "flex flex-col bg-[var(--surface-bg)] current-related dx-attention-surface [--controls-opacity:0]",
383
- hoverableFocusedWithinControls2
384
- ]
385
- }),
386
- "data-testid": "thread",
387
- id,
388
- "aria-current": current ? "location" : void 0,
389
- ref: forwardedRef
390
- }, children);
391
- });
392
- ThreadContent.displayName = "Thread.Content";
393
- var ThreadHeader = composable(({ title, detached, current, controls, onSelect, ...props }, forwardedRef) => {
394
- const { t } = useTranslation2(translationKey);
395
- const { focusComposer } = useThreadContext("Thread.Header");
396
- const handleSelect = useCallback2(() => {
397
- onSelect?.();
398
- focusComposer();
399
- }, [
400
- onSelect,
401
- focusComposer
402
- ]);
403
- return /* @__PURE__ */ React2.createElement("div", {
404
- ...composableProps(props, {
405
- classNames: [
406
- "grid grid-cols-[var(--dx-rail-size)_1fr_min-content] items-center",
407
- hoverableControls2,
408
- hoverableFocusedWithinControls2
409
- ]
410
- }),
411
- ref: forwardedRef
412
- }, /* @__PURE__ */ React2.createElement("div", {
413
- className: "flex items-center justify-center"
414
- }, /* @__PURE__ */ React2.createElement(IconButton2, {
415
- iconOnly: true,
416
- variant: "ghost",
417
- density: "sm",
418
- icon: "ph--caret-double-right--regular",
419
- label: t("select-thread.label"),
420
- classNames: "text-description",
421
- onClick: handleSelect
422
- })), /* @__PURE__ */ React2.createElement("div", {
423
- className: "flex items-center overflow-hidden"
424
- }, /* @__PURE__ */ React2.createElement("p", {
425
- role: "heading",
426
- "data-testid": "thread.heading",
427
- className: mx3("me-2 font-medium truncate italic", current ? "text-accent-text" : "text-description", detached && "line-through decoration-1")
428
- }, title)), controls);
429
- });
430
- ThreadHeader.displayName = "Thread.Header";
431
- var MessageTileAdapter = ({ id, data, location, draggable, current, selected }) => /* @__PURE__ */ React2.createElement(Mosaic.Tile, {
432
- id,
433
- data,
434
- location,
435
- draggable,
436
- current,
437
- selected
438
- }, /* @__PURE__ */ React2.createElement(Message.Tile, {
439
- message: data
440
- }));
441
- var ThreadMessages = ({ messages, estimateSize = 80, currentId, classNames }) => {
442
- const [viewport, setViewport] = useState2(null);
443
- const items = useMemo(() => messages.filter(Boolean), [
444
- messages
445
- ]);
446
- return /* @__PURE__ */ React2.createElement(Mosaic.Container, {
447
- asChild: true,
448
- orientation: "vertical",
449
- autoScroll: viewport,
450
- currentId,
451
- eventHandler: {
452
- id: "thread",
453
- canDrop: () => false
454
- }
455
- }, /* @__PURE__ */ React2.createElement(ScrollArea.Root, {
456
- classNames: mx3("col-span-2", classNames),
457
- orientation: "vertical"
458
- }, /* @__PURE__ */ React2.createElement(ScrollArea.Viewport, {
459
- ref: setViewport
460
- }, /* @__PURE__ */ React2.createElement(Mosaic.VirtualStack, {
461
- items,
462
- getId: getMessageId,
463
- Tile: MessageTileAdapter,
464
- draggable: false,
465
- getScrollElement: () => viewport,
466
- estimateSize: () => estimateSize
467
- }))));
468
- };
469
- ThreadMessages.displayName = "Thread.Messages";
470
- var ThreadTextbox = ({ placeholder, autoFocus, disabled, extensions, onSend, ...metadata }) => {
471
- const { t } = useTranslation2(translationKey);
472
- const { themeMode } = useThemeContext2();
473
- const { registerComposerFocus } = useThreadContext("Thread.Textbox");
474
- const composerRef = useRef2(null);
475
- const messageRef = useRef2("");
476
- const [count, setCount] = useState2(0);
477
- useEffect2(() => {
478
- registerComposerFocus(() => composerRef.current?.focus());
479
- return () => registerComposerFocus(void 0);
480
- }, [
481
- registerComposerFocus
482
- ]);
483
- const editorExtensions = useMemo(() => [
484
- createBasicExtensions2({
485
- placeholder: placeholder ?? t("message.placeholder")
486
- }),
487
- createThemeExtensions2({
488
- themeMode
489
- }),
490
- listener2({
491
- onChange: ({ text }) => messageRef.current = text
492
- }),
493
- command,
494
- extensions
495
- ].filter(Boolean), [
496
- themeMode,
497
- placeholder,
498
- t,
499
- extensions,
500
- count
501
- ]);
502
- const handleSend = useCallback2(() => {
503
- const text = messageRef.current;
504
- if (!text?.length || !onSend) {
505
- return;
506
- }
507
- if (onSend(text)) {
508
- messageRef.current = "";
509
- setCount((value) => value + 1);
510
- }
511
- }, []);
512
- return /* @__PURE__ */ React2.createElement(Message.Textbox, {
513
- ref: composerRef,
514
- ...metadata,
515
- autoFocus,
516
- disabled,
517
- extensions: editorExtensions,
518
- onSend: handleSend
519
- });
520
- };
521
- ThreadTextbox.displayName = "Thread.Textbox";
522
- var ThreadStatus = /* @__PURE__ */ forwardRef2(({ activity, classNames, children, ...props }, forwardedRef) => {
523
- const { t } = useTranslation2(translationKey);
524
- return /* @__PURE__ */ React2.createElement("div", {
525
- ...props,
526
- className: mx3("col-start-2 grid grid-cols-[min-content_1fr_max-content] pb-2 pe-2 text-xs text-description", classNames),
527
- ref: forwardedRef
528
- }, /* @__PURE__ */ React2.createElement(Icon, {
529
- icon: "ph--spinner--bold",
530
- classNames: "w-6 h-4 invisible data-[visible=show]:visible animate-spin-slow",
531
- "data-visible": activity ? "show" : "hide"
532
- }), /* @__PURE__ */ React2.createElement("span", {
533
- className: "truncate min-w-0",
534
- "aria-live": "polite"
535
- }, activity ? children : null), /* @__PURE__ */ React2.createElement("span", {
536
- className: mx3("text-end", hoverableControlItem2)
537
- }, t("enter-to-send.message")));
538
- });
539
- ThreadStatus.displayName = "Thread.Status";
540
- var Thread = {
541
- Root: ThreadRoot,
542
- Content: ThreadContent,
543
- Header: ThreadHeader,
544
- Messages: ThreadMessages,
545
- Textbox: ThreadTextbox,
546
- Status: ThreadStatus
547
- };
548
- export {
549
- Message,
550
- Thread,
551
- command,
552
- useThreadContext
553
- };
554
- //# sourceMappingURL=index.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/Thread/Thread.tsx", "../../../src/command.ts", "../../../src/context.ts", "../../../src/Message/Message.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React, {\n type ComponentPropsWithRef,\n type PropsWithChildren,\n type ReactNode,\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport { Obj } from '@dxos/echo';\nimport {\n type ComposableProps,\n Icon,\n IconButton,\n ScrollArea,\n type ThemedClassName,\n composable,\n composableProps,\n useThemeContext,\n useTranslation,\n} from '@dxos/react-ui';\nimport { Mosaic, type MosaicTileProps } from '@dxos/react-ui-mosaic';\nimport { type Message as MessageType } from '@dxos/types';\nimport { type Extension, createBasicExtensions, createThemeExtensions, listener } from '@dxos/ui-editor';\nimport { hoverableControlItem, hoverableControls, hoverableFocusedWithinControls, mx } from '@dxos/ui-theme';\n\nimport { command } from '../command';\nimport { ThreadContextProvider, useThreadContext } from '../context';\nimport { Message } from '../Message';\nimport { translationKey } from '../translations';\nimport { type MessageMetadata, type ThreadContextValue } from '../types';\n\nconst getMessageId = (message: MessageType.Message) => Obj.getURI(message);\n\n//\n// Root\n//\n\nexport type ThreadRootProps = PropsWithChildren<\n Omit<ThreadContextValue, 'components'> & Partial<Pick<ThreadContextValue, 'components'>>\n>;\n\n/**\n * Headless root of a thread. Provides message-tile context (metadata resolver,\n * injected renderers, callbacks) and the Mosaic root that `Thread.Messages`\n * renders its virtual stack within. Renders no DOM of its own — wrap the visible\n * thread chrome in `Thread.Content`.\n */\nconst ThreadRoot = ({\n children,\n getMetadata,\n components,\n identityDid,\n editable,\n onMessageDelete,\n onAcceptProposal,\n}: ThreadRootProps) => {\n // Composer focus handler registered by Thread.Textbox; invoked by Thread.Header's caret.\n const composerFocus = useRef<(() => void) | undefined>(undefined);\n\n const registerComposerFocus = useCallback((focus: (() => void) | undefined) => {\n composerFocus.current = focus;\n }, []);\n\n const focusComposer = useCallback(() => composerFocus.current?.(), []);\n\n return (\n <ThreadContextProvider\n getMetadata={getMetadata}\n components={components ?? {}}\n identityDid={identityDid}\n editable={editable}\n registerComposerFocus={registerComposerFocus}\n focusComposer={focusComposer}\n onMessageDelete={onMessageDelete}\n onAcceptProposal={onAcceptProposal}\n >\n <Mosaic.Root>{children}</Mosaic.Root>\n </ThreadContextProvider>\n );\n};\n\nThreadRoot.displayName = 'Thread.Root';\n\n//\n// Content\n//\n\ntype ThreadContentExtra = {\n id?: string;\n current?: boolean | string;\n} & Pick<ComponentPropsWithRef<'div'>, 'onClickCapture' | 'onFocusCapture'>;\n\nexport type ThreadContentProps = ComposableProps<ThreadContentExtra>;\n\n/** Visible thread container (the attention surface that hosts header / messages / composer). */\nconst ThreadContent = composable<HTMLDivElement, ThreadContentExtra>(\n ({ children, current, id, ...props }, forwardedRef) => {\n return (\n <div\n {...composableProps(props, {\n role: 'group',\n classNames: [\n 'flex flex-col bg-[var(--surface-bg)] current-related dx-attention-surface [--controls-opacity:0]',\n hoverableFocusedWithinControls,\n ],\n })}\n data-testid='thread'\n id={id}\n aria-current={current ? 'location' : undefined}\n ref={forwardedRef}\n >\n {children}\n </div>\n );\n },\n);\n\nThreadContent.displayName = 'Thread.Content';\n\n//\n// Header\n//\n\nexport type ThreadHeaderProps = Omit<\n ComposableProps<{\n /** Snippet text rendered inside a `<p>` (a string, not a DOM element). */\n title?: string;\n detached?: boolean;\n /** Whether this is the current/selected thread; accents the title. */\n current?: boolean;\n /** Trailing controls rendered in the right column (aligns with message-tile controls). */\n controls?: ReactNode;\n /** Invoked when the caret affordance is activated to select/focus this thread. */\n onSelect?: () => void;\n }>,\n 'children'\n>;\n\n/**\n * Thread header row: caret (rail) · snippet (content) · controls. Owns its own\n * `[rail · 1fr · controls]` grid so the trailing controls align with message-tile\n * controls (which use the same template) — no grid is leaked in from the caller.\n */\nconst ThreadHeader = composable<HTMLDivElement, ThreadHeaderProps>(\n ({ title, detached, current, controls, onSelect, ...props }, forwardedRef) => {\n const { t } = useTranslation(translationKey);\n const { focusComposer } = useThreadContext('Thread.Header');\n const handleSelect = useCallback(() => {\n onSelect?.();\n focusComposer();\n }, [onSelect, focusComposer]);\n\n return (\n <div\n {...composableProps(props, {\n classNames: [\n 'grid grid-cols-[var(--dx-rail-size)_1fr_min-content] items-center',\n hoverableControls,\n hoverableFocusedWithinControls,\n ],\n })}\n ref={forwardedRef}\n >\n <div className='flex items-center justify-center'>\n <IconButton\n iconOnly\n variant='ghost'\n density='sm'\n icon='ph--caret-double-right--regular'\n label={t('select-thread.label')}\n classNames='text-description'\n onClick={handleSelect}\n />\n </div>\n <div className='flex items-center overflow-hidden'>\n <p\n role='heading'\n data-testid='thread.heading'\n className={mx(\n 'me-2 font-medium truncate italic',\n current ? 'text-accent-text' : 'text-description',\n detached && 'line-through decoration-1',\n )}\n >\n {title}\n </p>\n </div>\n {controls}\n </div>\n );\n },\n);\n\nThreadHeader.displayName = 'Thread.Header';\n\n//\n// Messages\n//\n\nconst MessageTileAdapter = ({\n id,\n data,\n location,\n draggable,\n current,\n selected,\n}: MosaicTileProps<MessageType.Message>) => (\n <Mosaic.Tile id={id} data={data} location={location} draggable={draggable} current={current} selected={selected}>\n <Message.Tile message={data} />\n </Mosaic.Tile>\n);\n\nexport type ThreadMessagesProps = ThemedClassName<{\n messages: readonly MessageType.Message[];\n /** Estimated tile height for the virtualizer. */\n estimateSize?: number;\n currentId?: string;\n}>;\n\n/** Virtualized stack of message tiles (via Mosaic), within an internal scroll area. */\nconst ThreadMessages = ({ messages, estimateSize = 80, currentId, classNames }: ThreadMessagesProps) => {\n const [viewport, setViewport] = useState<HTMLElement | null>(null);\n const items = useMemo(() => messages.filter(Boolean), [messages]);\n\n return (\n <Mosaic.Container\n asChild\n orientation='vertical'\n autoScroll={viewport}\n currentId={currentId}\n eventHandler={{ id: 'thread', canDrop: () => false }}\n >\n <ScrollArea.Root classNames={mx('col-span-2', classNames)} orientation='vertical'>\n <ScrollArea.Viewport ref={setViewport}>\n <Mosaic.VirtualStack\n items={items}\n getId={getMessageId}\n Tile={MessageTileAdapter}\n draggable={false}\n getScrollElement={() => viewport}\n estimateSize={() => estimateSize}\n />\n </ScrollArea.Viewport>\n </ScrollArea.Root>\n </Mosaic.Container>\n );\n};\n\nThreadMessages.displayName = 'Thread.Messages';\n\n//\n// Textbox\n//\n\nexport type ThreadTextboxProps = MessageMetadata & {\n placeholder?: string;\n autoFocus?: boolean;\n disabled?: boolean;\n extensions?: Extension;\n /**\n * Called with the composer content on send. Return `true` to accept (the\n * editor is cleared and remounted), `false` to reject.\n */\n onSend?: (text: string) => boolean;\n};\n\n/** Message composer pinned at the foot of a thread. */\nconst ThreadTextbox = ({ placeholder, autoFocus, disabled, extensions, onSend, ...metadata }: ThreadTextboxProps) => {\n const { t } = useTranslation(translationKey);\n const { themeMode } = useThemeContext();\n const { registerComposerFocus } = useThreadContext('Thread.Textbox');\n const composerRef = useRef<{ focus: () => void } | null>(null);\n const messageRef = useRef('');\n const [count, setCount] = useState(0);\n\n // Expose the composer's focus to Thread.Root so the header caret can focus it.\n useEffect(() => {\n registerComposerFocus(() => composerRef.current?.focus());\n return () => registerComposerFocus(undefined);\n }, [registerComposerFocus]);\n\n const editorExtensions = useMemo(\n () =>\n [\n createBasicExtensions({ placeholder: placeholder ?? t('message.placeholder') }),\n createThemeExtensions({ themeMode }),\n listener({ onChange: ({ text }) => (messageRef.current = text) }),\n command,\n extensions,\n ].filter(Boolean) as Extension[],\n [themeMode, placeholder, t, extensions, count],\n );\n\n const handleSend = useCallback(() => {\n const text = messageRef.current;\n if (!text?.length || !onSend) {\n return;\n }\n if (onSend(text)) {\n messageRef.current = '';\n setCount((value) => value + 1);\n }\n }, []);\n\n return (\n <Message.Textbox\n ref={composerRef}\n {...metadata}\n autoFocus={autoFocus}\n disabled={disabled}\n extensions={editorExtensions}\n onSend={handleSend}\n />\n );\n};\n\nThreadTextbox.displayName = 'Thread.Textbox';\n\n//\n// Status\n//\n\nexport type ThreadStatusProps = ThemedClassName<PropsWithChildren> & {\n activity?: boolean;\n};\n\nconst ThreadStatus = forwardRef<HTMLDivElement, ThreadStatusProps>(\n ({ activity, classNames, children, ...props }, forwardedRef) => {\n const { t } = useTranslation(translationKey);\n return (\n <div\n {...props}\n className={mx(\n 'col-start-2 grid grid-cols-[min-content_1fr_max-content] pb-2 pe-2 text-xs text-description',\n classNames,\n )}\n ref={forwardedRef}\n >\n <Icon\n icon='ph--spinner--bold'\n classNames='w-6 h-4 invisible data-[visible=show]:visible animate-spin-slow'\n data-visible={activity ? 'show' : 'hide'}\n />\n <span className='truncate min-w-0' aria-live='polite'>\n {activity ? children : null}\n </span>\n <span className={mx('text-end', hoverableControlItem)}>{t('enter-to-send.message')}</span>\n </div>\n );\n },\n);\n\nThreadStatus.displayName = 'Thread.Status';\n\n//\n// Thread\n//\n\nexport const Thread = {\n Root: ThreadRoot,\n Content: ThreadContent,\n Header: ThreadHeader,\n Messages: ThreadMessages,\n Textbox: ThreadTextbox,\n Status: ThreadStatus,\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { HighlightStyle, StreamLanguage, syntaxHighlighting } from '@codemirror/language';\nimport { type Extension } from '@codemirror/state';\nimport { EditorView } from '@codemirror/view';\n\nimport { tags } from '@dxos/ui-editor';\nimport { mx } from '@dxos/ui-theme';\n\n/**\n * Highlights leading slash-commands (e.g. `/resolve`) and `@mention` tags\n * (e.g. `@Kai`, anywhere) in the message composer.\n * https://github.com/codemirror/stream-parser/blob/main/test/test-stream-parser.ts\n */\nconst parser = StreamLanguage.define<{ count: number }>({\n startState: () => ({ count: 0 }),\n token: (stream, state) => {\n state.count++;\n if (stream.eatSpace()) {\n return null;\n }\n // Leading slash-command (first token only).\n if (state.count === 1 && stream.match(/^\\/\\w+/)) {\n return 'tagName';\n }\n // @mention (anywhere).\n if (stream.match(/^@\\w+/)) {\n return 'labelName';\n }\n stream.next();\n return null;\n },\n});\n\nconst styles = HighlightStyle.define([\n {\n tag: tags.tagName,\n class: mx('dx-tag dx-tag--indigo'),\n },\n {\n tag: tags.labelName,\n class: mx('dx-tag dx-tag--blue'),\n },\n]);\n\n// Center the inline `.dx-tag` pills on the text line. `.dx-tag` is `inline-block`\n// with vertical padding, so on a CodeMirror line it baseline-aligns and rides\n// high; overriding `vertical-align` recentres it (cf. the `cm-reference-pill`\n// precedent in `@dxos/react-ui-chat`).\nconst theme = EditorView.theme({\n '.dx-tag': {\n verticalAlign: 'bottom',\n },\n});\n\nexport const command: Extension = [parser, syntaxHighlighting(styles), theme];\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { createContext } from '@radix-ui/react-context';\nimport { type FC, type ReactNode } from 'react';\n\n// Imported so TypeScript can name this type in the emitted .d.ts (ThreadContext → Message).\n// eslint-disable-next-line unused-imports/no-unused-imports\nimport { type Message } from '@dxos/types';\n\nimport { type ThreadContextValue } from './types';\n\n/**\n * Context provided by `Thread.Root` and consumed by its parts. Extends the\n * consumer-facing {@link ThreadContextValue} with internal coordination (e.g.\n * focusing the composer from the header's select affordance).\n */\nexport type ThreadContext = ThreadContextValue & {\n /** Register the composer's focus handler (set by `Thread.Textbox`). */\n registerComposerFocus: (focus: (() => void) | undefined) => void;\n /** Focus the thread composer (used by `Thread.Header`'s select affordance). */\n focusComposer: () => void;\n};\n\nexport const [ThreadContextProvider, useThreadContext]: readonly [\n FC<ThreadContext & { children: ReactNode }>,\n (consumerName: string) => ThreadContext,\n] = createContext<ThreadContext>('Thread');\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { EditorView } from '@codemirror/view';\nimport { formatDistanceToNow } from 'date-fns/formatDistanceToNow';\nimport React, {\n type ComponentPropsWithoutRef,\n type ComponentPropsWithRef,\n type ReactNode,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\n\nimport { Obj, Ref } from '@dxos/echo';\nimport {\n Avatar,\n IconButton,\n type ThemedClassName,\n useOnTransition,\n useThemeContext,\n useTranslation,\n} from '@dxos/react-ui';\nimport { type UseTextEditorProps, useTextEditor } from '@dxos/react-ui-editor';\nimport { type ContentBlock, type Message as MessageType } from '@dxos/types';\nimport { createBasicExtensions, createThemeExtensions, keymap, listener } from '@dxos/ui-editor';\nimport { hoverableControlItem, hoverableControls, hoverableFocusedWithinControls, mx } from '@dxos/ui-theme';\nimport { hexToEmoji, hexToHue, isTruthy } from '@dxos/util';\n\nimport { command } from '../command';\nimport { useThreadContext } from '../context';\nimport { translationKey } from '../translations';\nimport { type MessageMetadata } from '../types';\n\nconst avatarSize = 7;\n\nconst buttonGroupClassNames = 'flex flex-row items-center gap-0.5 pe-2';\nconst buttonClassNames = 'p-1! transition-opacity';\n\n//\n// Root\n//\n\nexport type MessageRootProps = ThemedClassName<\n ComponentPropsWithRef<'div'> & MessageMetadata & Partial<{ continues: boolean; controls: ReactNode }>\n>;\n\n// TODO(burdon): Show authorName on tooltip.\nconst MessageRoot = forwardRef<HTMLDivElement, MessageRootProps>(\n (\n {\n authorImgSrc,\n authorId,\n authorName,\n authorAvatarProps,\n continues = true,\n controls,\n children,\n classNames,\n ...rootProps\n },\n forwardedRef,\n ) => {\n // Must wrap the message since Avatar.Label may be used in the content.\n // Columns mirror Thread.Header (avatar/rail · content · controls) so trailing\n // controls align with the thread header's controls.\n return (\n <Avatar.Root>\n <div\n data-testid='thread.message'\n {...rootProps}\n className={mx('grid grid-cols-[var(--dx-rail-size)_1fr_min-content] w-full', classNames)}\n ref={forwardedRef}\n >\n <div className='flex flex-col items-center gap-2 pt-1'>\n <Avatar.Content\n size={avatarSize}\n hue={authorAvatarProps?.hue || hexToHue(authorId ?? '0')}\n fallback={authorAvatarProps?.emoji || hexToEmoji(authorId ?? '0')}\n {...(authorImgSrc && { imgSrc: authorImgSrc })}\n />\n {continues && <div className='w-px grow bg-separator' />}\n </div>\n <div className='py-1 min-w-0'>{children}</div>\n {controls && <div className='self-start'>{controls}</div>}\n </div>\n </Avatar.Root>\n );\n },\n);\n\nMessageRoot.displayName = 'Message.Root';\n\n//\n// Heading\n//\n\nexport type MessageHeadingProps = ThemedClassName<ComponentPropsWithoutRef<'div'>> &\n Pick<MessageMetadata, 'authorName' | 'timestamp'>;\n\nconst MessageHeading = ({ children, classNames, timestamp, authorName, ...props }: MessageHeadingProps) => {\n return (\n <div {...props} className={mx('flex gap-2 items-start', classNames)}>\n <p className='grow'>\n <MessageAuthorName authorName={authorName} />\n {timestamp && <MessageTime timestamp={timestamp} />}\n </p>\n {children}\n </div>\n );\n};\n\nMessageHeading.displayName = 'Message.Heading';\n\nexport type MessageAuthorNameProps = Pick<MessageMetadata, 'authorName'>;\n\nconst MessageAuthorName = ({ authorName }: MessageAuthorNameProps) => {\n const { t } = useTranslation(translationKey);\n return (\n <Avatar.Label classNames='block truncate text-sm text-subdued'>{authorName ?? t('anonymous.label')}</Avatar.Label>\n );\n};\n\nMessageAuthorName.displayName = 'Message.AuthorName';\n\nexport type MessageTimeProps = Pick<MessageMetadata, 'timestamp'>;\n\nconst MessageTime = ({ timestamp }: MessageTimeProps) => {\n const { dtLocale } = useTranslation(translationKey);\n const dt = timestamp ? new Date(timestamp) : undefined;\n return (\n <time className='block text-subdued text-xs pb-0.5' dateTime={dt?.toISOString()}>\n {dt ? formatDistanceToNow(dt, { locale: dtLocale, addSuffix: true }) : ''}\n </time>\n );\n};\n\nMessageTime.displayName = 'Message.Time';\n\n//\n// Body\n//\n\nexport type MessageBodyProps = {\n /** The message whose content blocks are rendered. */\n message: MessageType.Message;\n /** When true, the local user authored this message. */\n isAuthor?: boolean;\n /** When true, the text block is editable. */\n editing?: boolean;\n /** Persist an edited text block. */\n onSave?: (text: string) => void;\n};\n\n/**\n * Renders a message's content blocks: text (via editor), proposal, and\n * object/reference tiles (delegated to the injected `Object` component).\n */\nconst MessageBody = ({ message, isAuthor, editing, onSave }: MessageBodyProps) => {\n const { components } = useThreadContext('Message.Body');\n const textBlockIndex = message.blocks.findIndex((block) => block._tag === 'text');\n const textBlock = textBlockIndex !== -1 ? (message.blocks[textBlockIndex] as ContentBlock.Text) : undefined;\n const proposalBlock = message.blocks.find((block) => block._tag === 'proposal') as ContentBlock.Proposal | undefined;\n const references = message.blocks\n .filter((block) => block._tag === 'reference')\n .map((block) => (block as ContentBlock.Reference).reference);\n const Object = components.Object;\n\n return (\n <>\n {textBlock && <TextBlock block={textBlock} isAuthor={isAuthor} editing={editing} onSave={onSave} />}\n {proposalBlock && <div className='me-4 italic'>{proposalBlock.text}</div>}\n {Object &&\n Ref.Array.targets(references).map((reference, index) => (\n <Object key={index} subject={reference as Obj.Unknown} />\n ))}\n </>\n );\n};\n\nMessageBody.displayName = 'Message.Body';\n\nconst TextBlock = ({\n block,\n isAuthor,\n editing,\n onSave,\n}: {\n block: ContentBlock.Text;\n isAuthor?: boolean;\n editing?: boolean;\n onSave?: (text: string) => void;\n}) => {\n const { themeMode } = useThemeContext();\n const inMemoryContentRef = useRef(block.text);\n\n const handleDocumentChange = useCallback((next: string) => {\n inMemoryContentRef.current = next;\n }, []);\n\n const saveDocumentChange = useCallback(() => {\n onSave?.(inMemoryContentRef.current);\n }, [onSave]);\n\n useOnTransition(editing, true, false, saveDocumentChange);\n\n const { parentRef, focusAttributes, view } = useTextEditor(\n () => ({\n initialValue: block.text,\n extensions: [\n createBasicExtensions({ readOnly: !isAuthor || !editing }),\n createThemeExtensions({ themeMode }),\n command,\n EditorView.updateListener.of((update) => {\n if (update.docChanged) {\n handleDocumentChange(update.state.doc.toString());\n }\n }),\n ],\n }),\n [block.text, editing, isAuthor, themeMode, handleDocumentChange],\n );\n\n useEffect(() => {\n if (editing) {\n view?.focus();\n }\n }, [editing, view]);\n\n return <div ref={parentRef} className='me-4' {...focusAttributes} />;\n};\n\n//\n// Textbox\n//\n\nexport type MessageTextboxProps = {\n disabled?: boolean;\n onSend?: () => void;\n onClear?: () => void;\n onEditorFocus?: () => void;\n} & MessageMetadata &\n UseTextEditorProps;\n\nconst keyBindings = ({ onSend, onClear }: Pick<MessageTextboxProps, 'onSend' | 'onClear'>) => [\n {\n key: 'Enter',\n run: () => {\n if (onSend) {\n onSend();\n return true;\n }\n return false;\n },\n },\n {\n key: 'Meta+Backspace',\n run: () => {\n if (onClear) {\n onClear();\n return true;\n }\n return false;\n },\n },\n];\n\nexport type MessageTextboxHandle = { focus: () => void };\n\nconst MessageTextbox = forwardRef<MessageTextboxHandle, MessageTextboxProps>(\n (\n {\n id,\n authorId,\n authorName,\n authorImgSrc,\n authorAvatarProps,\n disabled,\n extensions,\n onSend,\n onClear,\n onEditorFocus,\n ...editorProps\n },\n forwardedRef,\n ) => {\n const { parentRef, focusAttributes, view } = useTextEditor(\n () => ({\n id,\n extensions: [\n keymap.of(keyBindings({ onSend, onClear })),\n listener({\n onFocus: ({ focusing }) => {\n if (focusing) {\n onEditorFocus?.();\n }\n },\n }),\n extensions,\n ].filter(isTruthy),\n ...editorProps,\n }),\n [id, extensions],\n );\n\n useImperativeHandle(forwardedRef, () => ({ focus: () => view?.focus() }), [view]);\n\n return (\n <MessageRoot {...{ id, authorId, authorName, authorImgSrc, authorAvatarProps }} continues={false}>\n <div\n ref={parentRef}\n className={mx('py-0.5 me-1 rounded-xs dx-focus-ring', disabled && 'opacity-50')}\n {...focusAttributes}\n />\n </MessageRoot>\n );\n },\n);\n\nMessageTextbox.displayName = 'Message.Textbox';\n\n//\n// Tile\n//\n\nexport type MessageTileProps = {\n message: MessageType.Message;\n classNames?: MessageRootProps['classNames'];\n};\n\n/**\n * Full message tile (frame + heading + controls + body). Reads `Thread.Root`\n * context for metadata resolution, injected renderers, and callbacks. This is\n * the unit rendered by `Thread.Messages`.\n */\nconst MessageTile = ({ message, classNames }: MessageTileProps) => {\n const { t } = useTranslation(translationKey);\n const { getMetadata, identityDid, editable, onMessageDelete, onAcceptProposal } = useThreadContext('Message.Tile');\n const [editing, setEditing] = useState(false);\n\n const metadata = getMetadata(message);\n const isAuthor = !!identityDid && identityDid === metadata.authorId;\n const hasProposal = message.blocks.some((block) => block._tag === 'proposal');\n\n const handleEdit = useCallback(() => setEditing((value) => !value), []);\n const handleDelete = useCallback(() => onMessageDelete?.(message.id), [onMessageDelete, message.id]);\n const handleAcceptProposal = useCallback(() => onAcceptProposal?.(message.id), [onAcceptProposal, message.id]);\n const handleSave = useCallback(\n (text: string) => {\n Obj.update(message, (message) => {\n const block = message.blocks.find((block) => block._tag === 'text');\n if (block && block._tag === 'text') {\n block.text = text;\n }\n });\n },\n [message],\n );\n\n const showEdit = isAuthor && editable;\n const showAccept = hasProposal && !!onAcceptProposal;\n const showDelete = !!onMessageDelete;\n const controls =\n showEdit || showAccept || showDelete ? (\n <div className={buttonGroupClassNames}>\n {showEdit && (\n <IconButton\n data-testid={editing ? 'thread.message.save' : 'thread.message.edit'}\n variant='ghost'\n icon={editing ? 'ph--check--regular' : 'ph--pencil-simple--regular'}\n iconOnly\n label={t(editing ? 'save-message.label' : 'edit-message.label')}\n classNames={[buttonClassNames, hoverableControlItem]}\n onClick={handleEdit}\n />\n )}\n {showAccept && (\n <IconButton\n data-testid='thread.message.accept'\n variant='ghost'\n icon='ph--check--regular'\n iconOnly\n label={t('accept-proposal.label')}\n classNames={[buttonClassNames, hoverableControlItem]}\n onClick={handleAcceptProposal}\n />\n )}\n {showDelete && (\n <IconButton\n data-testid='thread.message.delete'\n variant='ghost'\n icon='ph--x--regular'\n iconOnly\n label={t('delete-message.label')}\n classNames={[buttonClassNames, hoverableControlItem]}\n onClick={handleDelete}\n />\n )}\n </div>\n ) : undefined;\n\n return (\n <MessageRoot\n {...metadata}\n controls={controls}\n classNames={[hoverableControls, hoverableFocusedWithinControls, classNames]}\n >\n <MessageHeading authorName={metadata.authorName} timestamp={metadata.timestamp} />\n <MessageBody message={message} isAuthor={isAuthor} editing={editing} onSave={handleSave} />\n </MessageRoot>\n );\n};\n\nMessageTile.displayName = 'Message.Tile';\n\n//\n// Message\n//\n\nexport const Message = {\n Root: MessageRoot,\n Heading: MessageHeading,\n AuthorName: MessageAuthorName,\n Time: MessageTime,\n Body: MessageBody,\n Textbox: MessageTextbox,\n Tile: MessageTile,\n};\n"],
5
- "mappings": "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",
6
- "names": ["React", "forwardRef", "useCallback", "useEffect", "useMemo", "useRef", "useState", "Obj", "Icon", "IconButton", "ScrollArea", "composable", "composableProps", "useThemeContext", "useTranslation", "Mosaic", "createBasicExtensions", "createThemeExtensions", "listener", "hoverableControlItem", "hoverableControls", "hoverableFocusedWithinControls", "mx", "HighlightStyle", "StreamLanguage", "syntaxHighlighting", "EditorView", "tags", "mx", "parser", "define", "startState", "count", "token", "stream", "state", "eatSpace", "match", "next", "styles", "tag", "tagName", "class", "labelName", "theme", "verticalAlign", "command", "createContext", "ThreadContextProvider", "useThreadContext", "EditorView", "formatDistanceToNow", "React", "forwardRef", "useCallback", "useEffect", "useImperativeHandle", "useRef", "useState", "Obj", "Ref", "Avatar", "IconButton", "useOnTransition", "useThemeContext", "useTranslation", "useTextEditor", "createBasicExtensions", "createThemeExtensions", "keymap", "listener", "hoverableControlItem", "hoverableControls", "hoverableFocusedWithinControls", "mx", "hexToEmoji", "hexToHue", "isTruthy", "avatarSize", "buttonGroupClassNames", "buttonClassNames", "MessageRoot", "forwardRef", "authorImgSrc", "authorId", "authorName", "authorAvatarProps", "continues", "controls", "children", "classNames", "rootProps", "forwardedRef", "Avatar", "Root", "div", "data-testid", "className", "mx", "ref", "Content", "size", "hue", "hexToHue", "fallback", "emoji", "hexToEmoji", "imgSrc", "displayName", "MessageHeading", "timestamp", "props", "p", "MessageAuthorName", "MessageTime", "t", "useTranslation", "translationKey", "Label", "dtLocale", "dt", "Date", "undefined", "time", "dateTime", "toISOString", "formatDistanceToNow", "locale", "addSuffix", "MessageBody", "message", "isAuthor", "editing", "onSave", "components", "useThreadContext", "textBlockIndex", "blocks", "findIndex", "block", "_tag", "textBlock", "proposalBlock", "find", "references", "filter", "map", "reference", "Object", "TextBlock", "text", "Ref", "Array", "targets", "index", "key", "subject", "themeMode", "useThemeContext", "inMemoryContentRef", "useRef", "handleDocumentChange", "useCallback", "next", "current", "saveDocumentChange", "useOnTransition", "parentRef", "focusAttributes", "view", "useTextEditor", "initialValue", "extensions", "createBasicExtensions", "readOnly", "createThemeExtensions", "command", "EditorView", "updateListener", "of", "update", "docChanged", "state", "doc", "toString", "useEffect", "focus", "keyBindings", "onSend", "onClear", "run", "MessageTextbox", "id", "disabled", "onEditorFocus", "editorProps", "keymap", "listener", "onFocus", "focusing", "isTruthy", "useImperativeHandle", "MessageTile", "getMetadata", "identityDid", "editable", "onMessageDelete", "onAcceptProposal", "setEditing", "useState", "metadata", "hasProposal", "some", "handleEdit", "value", "handleDelete", "handleAcceptProposal", "handleSave", "Obj", "showEdit", "showAccept", "showDelete", "IconButton", "variant", "icon", "iconOnly", "label", "hoverableControlItem", "onClick", "hoverableControls", "hoverableFocusedWithinControls", "Message", "Heading", "AuthorName", "Time", "Body", "Textbox", "Tile", "getMessageId", "message", "Obj", "getURI", "ThreadRoot", "children", "getMetadata", "components", "identityDid", "editable", "onMessageDelete", "onAcceptProposal", "composerFocus", "useRef", "undefined", "registerComposerFocus", "useCallback", "focus", "current", "focusComposer", "React", "ThreadContextProvider", "Mosaic", "Root", "displayName", "ThreadContent", "composable", "id", "props", "forwardedRef", "div", "composableProps", "role", "classNames", "hoverableFocusedWithinControls", "data-testid", "aria-current", "ref", "ThreadHeader", "title", "detached", "controls", "onSelect", "t", "useTranslation", "translationKey", "useThreadContext", "handleSelect", "hoverableControls", "className", "IconButton", "iconOnly", "variant", "density", "icon", "label", "onClick", "p", "mx", "MessageTileAdapter", "data", "location", "draggable", "selected", "Tile", "Message", "ThreadMessages", "messages", "estimateSize", "currentId", "viewport", "setViewport", "useState", "items", "useMemo", "filter", "Boolean", "Container", "asChild", "orientation", "autoScroll", "eventHandler", "canDrop", "ScrollArea", "Viewport", "VirtualStack", "getId", "getScrollElement", "ThreadTextbox", "placeholder", "autoFocus", "disabled", "extensions", "onSend", "metadata", "themeMode", "useThemeContext", "composerRef", "messageRef", "count", "setCount", "useEffect", "editorExtensions", "createBasicExtensions", "createThemeExtensions", "listener", "onChange", "text", "command", "handleSend", "length", "value", "Textbox", "ThreadStatus", "forwardRef", "activity", "Icon", "data-visible", "span", "aria-live", "hoverableControlItem", "Thread", "Content", "Header", "Messages", "Status"]
7
- }