@dxos/react-ui-thread 0.14.0 → 0.16.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.
@@ -14,6 +14,7 @@ import { translationKey } from "#translations";
14
14
  import { HighlightStyle, StreamLanguage, syntaxHighlighting } from "@codemirror/language";
15
15
  import { EditorView } from "@codemirror/view";
16
16
  import { createContext } from "@dxos/react-hooks";
17
+ import { useObject } from "@dxos/echo-react";
17
18
  import { useTextEditor } from "@dxos/react-ui-editor";
18
19
  import * as Avatar from "@dxos/react-ui/Avatar";
19
20
  import { hexToEmoji, hexToHue, isTruthy } from "@dxos/util";
@@ -120,15 +121,16 @@ MessageTime.displayName = "Message.Time";
120
121
  */
121
122
  var MessageBody = ({ message, isAuthor, editing, onSave }) => {
122
123
  const { components } = useThreadContext("Message.Body");
123
- const textBlockIndex = message.blocks.findIndex((block) => block._tag === "text");
124
- const textBlock = textBlockIndex !== -1 ? message.blocks[textBlockIndex] : void 0;
125
- const proposalBlock = message.blocks.find((block) => block._tag === "proposal");
126
- const changeBlock = message.blocks.find((block) => block._tag === "change");
127
- const references = message.blocks.filter((block) => block._tag === "reference").map((block) => block.reference);
124
+ const [{ blocks }] = useObject(message);
125
+ const textBlockIndex = blocks.findIndex((block) => block._tag === "text");
126
+ const textBlock = textBlockIndex !== -1 ? blocks[textBlockIndex] : void 0;
127
+ const proposalBlock = blocks.find((block) => block._tag === "proposal");
128
+ const changeBlock = blocks.find((block) => block._tag === "change");
129
+ const references = blocks.filter((block) => block._tag === "reference").map((block) => block.reference);
128
130
  const Object = components.Object;
129
131
  return /* @__PURE__ */ jsxs(Fragment, { children: [
130
132
  textBlock && /* @__PURE__ */ jsx(TextBlock, {
131
- block: textBlock,
133
+ text: textBlock.text,
132
134
  isAuthor,
133
135
  editing,
134
136
  onSave
@@ -152,9 +154,9 @@ var MessageBody = ({ message, isAuthor, editing, onSave }) => {
152
154
  ] });
153
155
  };
154
156
  MessageBody.displayName = "Message.Body";
155
- var TextBlock = ({ block, isAuthor, editing, onSave }) => {
157
+ var TextBlock = ({ text, isAuthor, editing, onSave }) => {
156
158
  const themeMode = Hooks.useThemeMode();
157
- const inMemoryContentRef = useRef(block.text);
159
+ const inMemoryContentRef = useRef(text);
158
160
  const handleDocumentChange = useCallback((next) => {
159
161
  inMemoryContentRef.current = next;
160
162
  }, []);
@@ -163,7 +165,7 @@ var TextBlock = ({ block, isAuthor, editing, onSave }) => {
163
165
  }, [onSave]);
164
166
  Hooks.useOnTransition(editing, true, false, saveDocumentChange);
165
167
  const { parentRef, focusAttributes, view } = useTextEditor(() => ({
166
- initialValue: block.text,
168
+ initialValue: text,
167
169
  extensions: [
168
170
  createBasicExtensions({ readOnly: !editing }),
169
171
  createThemeExtensions({ themeMode }),
@@ -174,7 +176,7 @@ var TextBlock = ({ block, isAuthor, editing, onSave }) => {
174
176
  ]
175
177
  }), [
176
178
  editing,
177
- editing ? void 0 : block.text,
179
+ editing ? void 0 : text,
178
180
  editing ? void 0 : isAuthor,
179
181
  themeMode,
180
182
  handleDocumentChange
@@ -248,10 +250,11 @@ var MessageTile = ({ message, classNames, continues = true }) => {
248
250
  const { t } = Hooks.useTranslation(translationKey);
249
251
  const { getMetadata, identityDid, editable, onMessageDelete, onAcceptProposal, onAcceptChange, onRejectChange, onMessageSelect, currentMessageId } = useThreadContext("Message.Tile");
250
252
  const [editing, setEditing] = useState(false);
253
+ const [blocks] = useObject(message, "blocks");
251
254
  const metadata = getMetadata(message);
252
255
  const isAuthor = !!identityDid && identityDid === metadata.authorId;
253
- const hasProposal = message.blocks.some((block) => block._tag === "proposal");
254
- const hasChange = message.blocks.some((block) => block._tag === "change");
256
+ const hasProposal = blocks.some((block) => block._tag === "proposal");
257
+ const hasChange = blocks.some((block) => block._tag === "change");
255
258
  const handleEdit = useCallback(() => setEditing((value) => !value), []);
256
259
  const handleDelete = useCallback(() => onMessageDelete?.(message.id), [onMessageDelete, message.id]);
257
260
  const handleAcceptProposal = useCallback(() => onAcceptProposal?.(message.id), [onAcceptProposal, message.id]);
@@ -357,9 +360,10 @@ var MessageGroup = ({ messages, continues = true, classNames }) => {
357
360
  const { getMetadata, identityDid, editable, onMessageDelete, onAcceptProposal } = useThreadContext("Message.Group");
358
361
  const [editing, setEditing] = useState(false);
359
362
  const first = messages[0];
363
+ const [blocks] = useObject(first, "blocks");
360
364
  const metadata = getMetadata(first);
361
365
  const isAuthor = !!identityDid && identityDid === metadata.authorId;
362
- const hasProposal = first.blocks.some((block) => block._tag === "proposal");
366
+ const hasProposal = blocks.some((block) => block._tag === "proposal");
363
367
  const handleEdit = useCallback(() => setEditing((value) => !value), []);
364
368
  const handleDelete = useCallback(() => onMessageDelete?.(first.id), [onMessageDelete, first.id]);
365
369
  const handleAcceptProposal = useCallback(() => onAcceptProposal?.(first.id), [onAcceptProposal, first.id]);
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/command.ts","../../src/context.ts","../../src/Message/Message.tsx","../../src/Thread/Thread.tsx"],"sourcesContent":["//\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-inline dx-tag-indigo mx-0.5'),\n },\n {\n tag: tags.labelName,\n class: mx('dx-tag dx-tag-inline dx-tag-blue mx-0.5'),\n },\n]);\n\n// Center the inline `.dx-tag` pills on the text line. An inline tag is an inline box\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 { type FC, type ReactNode } from 'react';\n\nimport { createContext } from '@dxos/react-hooks';\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.ts';\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 { format } from 'date-fns/format';\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 { type UseTextEditorProps, useTextEditor } from '@dxos/react-ui-editor';\nimport * as Avatar from '@dxos/react-ui/Avatar';\nimport * as Button from '@dxos/react-ui/Button';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport type * as Util from '@dxos/react-ui/Util';\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 { translationKey } from '#translations';\n\nimport { command } from '../command.ts';\nimport { useThreadContext } from '../context.ts';\nimport { type MessageMetadata } from '../types.ts';\n\nconst avatarSize = 'md';\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 = Util.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 // Columns mirror Thread.Header (avatar/rail · content · controls) so trailing\n // controls align with the thread header's controls.\n return (\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.Root\n size={avatarSize}\n hue={authorAvatarProps?.hue || hexToHue(authorId ?? '0')}\n fallback={authorAvatarProps?.emoji || hexToEmoji(authorId ?? '0')}\n src={authorImgSrc}\n label={authorName}\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 );\n },\n);\n\nMessageRoot.displayName = 'Message.Root';\n\n//\n// Heading\n//\n\nexport type MessageHeadingProps = Util.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 flex items-baseline gap-2 min-w-0'>\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 } = Hooks.useTranslation(translationKey);\n return (\n <span className='block truncate min-w-0 shrink text-sm text-fg-subtle'>{authorName ?? t('anonymous.label')}</span>\n );\n};\n\nMessageAuthorName.displayName = 'Message.AuthorName';\n\nexport type MessageTimeProps = Pick<MessageMetadata, 'timestamp'>;\n\nconst MessageTime = ({ timestamp }: MessageTimeProps) => {\n const { dtLocale } = Hooks.useTranslation(translationKey);\n const dt = timestamp ? new Date(timestamp) : undefined;\n return (\n <time className='shrink-0 text-fg-subtle text-xs' dateTime={dt?.toISOString()}>\n {dt ? format(dt, 'p', { locale: dtLocale }) : ''}\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 changeBlock = message.blocks.find((block) => block._tag === 'change') as ContentBlock.Change | 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 {changeBlock && (\n <p className='me-4 text-sm break-words'>\n {changeBlock.before && <span className='line-through opacity-60'>{changeBlock.before}</span>}\n {changeBlock.before && changeBlock.after && ' '}\n {changeBlock.after && <span>{changeBlock.after}</span>}\n </p>\n )}\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 = Hooks.useThemeMode();\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 Hooks.useOnTransition(editing, true, false, saveDocumentChange);\n\n const { parentRef, focusAttributes, view } = useTextEditor(\n () => ({\n initialValue: block.text,\n extensions: [\n // Edit mode is authorisation enough — the control that gets here is already gated on\n // `isAuthor` — and a mid-edit flip to read-only makes the editor drop input silently.\n createBasicExtensions({ readOnly: !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 // While editing, the editor owns its content and its authorisation: pinning both keeps an incoming\n // `block.text` update or member-list refresh from rebuilding the view being typed in. `editing` is\n // itself a dep, so the flip still rebuilds.\n [editing, editing ? undefined : block.text, editing ? undefined : 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 {/*\n Addressable: the reply composer is the only textbox in a thread that is not a message body,\n so without a testid a test can only guess at it by editor order.\n */}\n <div\n ref={parentRef}\n data-testid='thread.reply'\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 /** Whether the avatar-rail continuation line is drawn below the tile; false for the last tile. */\n continues?: boolean;\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, continues = true }: MessageTileProps) => {\n const { t } = Hooks.useTranslation(translationKey);\n const {\n getMetadata,\n identityDid,\n editable,\n onMessageDelete,\n onAcceptProposal,\n onAcceptChange,\n onRejectChange,\n onMessageSelect,\n currentMessageId,\n } = 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 const hasChange = message.blocks.some((block) => block._tag === 'change');\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 handleAcceptChange = useCallback(() => onAcceptChange?.(message.id), [onAcceptChange, message.id]);\n const handleRejectChange = useCallback(() => onRejectChange?.(message.id), [onRejectChange, message.id]);\n const handleSelect = useCallback(() => onMessageSelect?.(message.id), [onMessageSelect, 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 showAcceptChange = hasChange && !!onAcceptChange;\n const showRejectChange = hasChange && !!onRejectChange;\n const showDelete = !!onMessageDelete;\n const controls =\n showEdit || showAccept || showAcceptChange || showRejectChange || showDelete ? (\n <div className={buttonGroupClassNames}>\n {showEdit && (\n <Button.Root\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 <Button.Root\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 {showAcceptChange && (\n <Button.Root\n data-testid='thread.message.accept-change'\n variant='ghost'\n icon='ph--check--regular'\n iconOnly\n label={t('accept-change.label')}\n classNames={[buttonClassNames, hoverableControlItem]}\n onClick={handleAcceptChange}\n />\n )}\n {showRejectChange && (\n <Button.Root\n data-testid='thread.message.reject-change'\n variant='ghost'\n icon='ph--x--regular'\n iconOnly\n label={t('reject-change.label')}\n classNames={[buttonClassNames, hoverableControlItem]}\n onClick={handleRejectChange}\n />\n )}\n {showDelete && (\n <Button.Root\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 continues={continues}\n controls={controls}\n // Selecting a tile is how the host reveals what it refers to (a suggestion's range in the\n // document), so the whole tile is the target — the accent marks which one is showing.\n onClick={onMessageSelect ? handleSelect : undefined}\n aria-current={currentMessageId === message.id ? 'location' : undefined}\n classNames={[\n hoverableControls,\n hoverableFocusedWithinControls,\n onMessageSelect && 'cursor-pointer',\n currentMessageId === message.id && 'bg-current-surface',\n classNames,\n ]}\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// Group\n//\n\nexport type MessageGroupProps = {\n /** Consecutive same-sender messages, in ascending time order, rendered as one tile. */\n messages: readonly MessageType.Message[];\n /** Whether the avatar-rail continuation line is drawn below the tile; false for the last tile. */\n continues?: boolean;\n classNames?: MessageRootProps['classNames'];\n};\n\n/**\n * Groups consecutive same-sender messages (see `Thread.Messages`'s grouping\n * window) into a single tile: one heading (author + first message's\n * timestamp) followed by one body per message, stacked in order. Per-message\n * edit/delete controls are not shown per-row in a group — v1 shows them for\n * the group's first message only, since the heading/controls layout is keyed\n * to a single message.\n */\nconst MessageGroup = ({ messages, continues = true, classNames }: MessageGroupProps) => {\n const { t } = Hooks.useTranslation(translationKey);\n const { getMetadata, identityDid, editable, onMessageDelete, onAcceptProposal } = useThreadContext('Message.Group');\n const [editing, setEditing] = useState(false);\n\n const first = messages[0];\n const metadata = getMetadata(first);\n const isAuthor = !!identityDid && identityDid === metadata.authorId;\n const hasProposal = first.blocks.some((block) => block._tag === 'proposal');\n\n const handleEdit = useCallback(() => setEditing((value) => !value), []);\n const handleDelete = useCallback(() => onMessageDelete?.(first.id), [onMessageDelete, first.id]);\n const handleAcceptProposal = useCallback(() => onAcceptProposal?.(first.id), [onAcceptProposal, first.id]);\n const handleSave = useCallback(\n (text: string) => {\n Obj.update(first, (first) => {\n const block = first.blocks.find((block) => block._tag === 'text');\n if (block && block._tag === 'text') {\n block.text = text;\n }\n });\n },\n [first],\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 <Button.Root\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 <Button.Root\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 <Button.Root\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 continues={continues}\n controls={controls}\n classNames={[hoverableControls, hoverableFocusedWithinControls, classNames]}\n >\n <MessageHeading authorName={metadata.authorName} timestamp={metadata.timestamp} />\n {messages.map((message) => (\n <MessageBody\n key={message.id}\n message={message}\n isAuthor={isAuthor}\n editing={editing && message === first}\n onSave={handleSave}\n />\n ))}\n </MessageRoot>\n );\n};\n\nMessageGroup.displayName = 'Message.Group';\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 Group: MessageGroup,\n};\n","//\n// Copyright 2023 DXOS.org\n//\n\nimport { format } from 'date-fns/format';\nimport { type Locale } from 'date-fns/locale';\nimport { startOfDay } from 'date-fns/startOfDay';\nimport React, {\n type ComponentPropsWithRef,\n type PropsWithChildren,\n type ReactNode,\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport { Obj } from '@dxos/echo';\nimport { type DndContainerHandler } from '@dxos/react-ui-dnd';\nimport { Mosaic, type MosaicTileProps } from '@dxos/react-ui-mosaic';\nimport * as Button from '@dxos/react-ui/Button';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as Icon from '@dxos/react-ui/Icon';\nimport * as ScrollArea from '@dxos/react-ui/ScrollArea';\nimport * as Util from '@dxos/react-ui/Util';\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';\nimport { type ComposableProps } from '@dxos/ui-types';\n\nimport { translationKey } from '#translations';\n\nimport { command } from '../command.ts';\nimport { ThreadContextProvider, useThreadContext } from '../context.ts';\nimport { Message } from '../Message/index.ts';\nimport { type MessageMetadata, type ThreadContextValue } from '../types.ts';\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). Requires an ambient `Dnd.Root` ancestor,\n * within which `Thread.Messages` renders its virtual stack. Renders no DOM of\n * its own — wrap the visible thread chrome in `Thread.Content`.\n */\nconst ThreadRoot = ({\n children,\n getMetadata,\n components,\n identityDid,\n editable,\n onMessageDelete,\n onAcceptProposal,\n onAcceptChange,\n onRejectChange,\n onMessageSelect,\n currentMessageId,\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 onAcceptChange={onAcceptChange}\n onRejectChange={onRejectChange}\n onMessageSelect={onMessageSelect}\n currentMessageId={currentMessageId}\n >\n {children}\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 = Util.composable<HTMLDivElement, ThreadContentExtra>(\n ({ children, current, id, ...props }, forwardedRef) => {\n return (\n <div\n {...Util.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 = Util.composable<HTMLDivElement, ThreadHeaderProps>(\n ({ title, detached, current, controls, onSelect, ...props }, forwardedRef) => {\n const { t } = Hooks.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 {...Util.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 <Button.Root\n iconOnly\n variant='ghost'\n size='sm'\n icon='ph--caret-double-right--regular'\n label={t('select-thread.label')}\n classNames='text-fg-muted'\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-fg-muted',\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\n/** A run of consecutive same-sender messages (within the grouping window) rendered as one tile. */\ntype MessageGroupItem = { kind: 'group'; id: string; messages: MessageType.Message[]; last?: boolean };\n\n/**\n * A divider row between groups: day-labeled (calendar-day boundary) or plain\n * (a same-day gap exceeding `gapDividerMs`). Day boundaries take priority\n * when both coincide on the same message — see `groupMessages`.\n */\ntype DividerItem = { kind: 'divider'; id: string; label?: string };\n\ntype ThreadItem = MessageGroupItem | DividerItem;\n\nconst getThreadItemId = (item: ThreadItem) => item.id;\n\n/** Stable per-sender key: prefers the DID, then the (deprecated) identity key, then name/email, else 'anon'. */\nconst senderKey = (message: MessageType.Message): string =>\n message.sender.identityDid ?? message.sender.identityKey ?? message.sender.name ?? message.sender.email ?? 'anon';\n\n/** Message send time in epoch ms; malformed/missing `created` sorts as if sent at the epoch. */\nconst messageTime = (message: MessageType.Message): number => {\n const time = Date.parse(message.created);\n return Number.isFinite(time) ? time : 0;\n};\n\n/**\n * Preprocesses ascending, time-ordered `messages` into a flat list of divider\n * and group items for `Thread.Messages`'s virtual stack:\n * - A day divider (labeled with the calendar date) precedes the first message\n * of each calendar day.\n * - A plain divider (no label) marks a same-day gap exceeding `gapDividerMs`.\n * - When both would fall on the same message, only the day divider is emitted.\n * - Consecutive messages from the same sender within `groupWindowMs` of the\n * previous message in the group are merged into one `MessageGroupItem`; a\n * divider always starts a new group.\n */\nconst groupMessages = (\n messages: readonly MessageType.Message[],\n {\n groupWindowMs,\n dayDivider,\n gapDividerMs,\n dtLocale,\n }: { groupWindowMs: number; dayDivider: boolean; gapDividerMs: number; dtLocale?: Locale },\n): ThreadItem[] => {\n const items: ThreadItem[] = [];\n let currentGroup: MessageGroupItem | undefined;\n // Tracks the last message appended to `currentGroup`, since `Array.prototype.at(-1)`\n // on `currentGroup.messages` would need a non-null assertion despite `currentGroup`\n // always being non-empty by construction.\n let lastGroupMessage: MessageType.Message | undefined;\n let prevTime: number | undefined;\n let prevDay: number | undefined;\n\n for (const message of messages) {\n const time = messageTime(message);\n const day = startOfDay(time).getTime();\n\n const dayBoundary = dayDivider && (prevDay === undefined || day !== prevDay);\n const gapBoundary = !dayBoundary && prevTime !== undefined && time - prevTime > gapDividerMs;\n\n if (dayBoundary) {\n items.push({\n kind: 'divider',\n id: `divider:day:${day}`,\n label: format(day, 'EEEE, MMMM d', { locale: dtLocale }),\n });\n currentGroup = undefined;\n } else if (gapBoundary) {\n items.push({ kind: 'divider', id: `divider:gap:${time}` });\n currentGroup = undefined;\n }\n\n const sameSenderAsGroup = currentGroup && lastGroupMessage && senderKey(lastGroupMessage) === senderKey(message);\n const withinGroupWindow = currentGroup && lastGroupMessage && time - messageTime(lastGroupMessage) <= groupWindowMs;\n\n if (currentGroup && sameSenderAsGroup && withinGroupWindow) {\n currentGroup.messages.push(message);\n } else {\n currentGroup = { kind: 'group', id: Obj.getURI(message), messages: [message] };\n items.push(currentGroup);\n }\n lastGroupMessage = message;\n\n prevTime = time;\n prevDay = day;\n }\n\n // The trailing group is the last message tile; suppress its avatar-rail continuation line.\n if (currentGroup) {\n currentGroup.last = true;\n }\n\n return items;\n};\n\n//\n// Divider\n//\n\nconst ThreadDivider = ({ label }: { label?: string }) =>\n label ? (\n <div className='flex items-center gap-2 px-2 py-2 text-xs text-fg-muted'>\n <div className='h-px grow bg-separator' />\n <span className='shrink-0'>{label}</span>\n <div className='h-px grow bg-separator' />\n </div>\n ) : (\n <div className='px-2 py-2'>\n <div className='h-px bg-separator' />\n </div>\n );\n\nThreadDivider.displayName = 'Thread.Divider';\n\nconst ThreadItemAdapter = ({ id, data, location, draggable, current, selected }: MosaicTileProps<ThreadItem>) => (\n <Mosaic.Tile id={id} data={data} location={location} draggable={draggable} current={current} selected={selected}>\n {data.kind === 'divider' ? (\n <ThreadDivider label={data.label} />\n ) : (\n <Message.Group messages={data.messages} continues={!data.last} />\n )}\n </Mosaic.Tile>\n);\n\nexport type ThreadMessagesProps = Util.ThemedClassName<{\n messages: readonly MessageType.Message[];\n /** Stable id of the owning thread; scopes the Mosaic container so multiple threads don't collide. */\n id?: string;\n /** Estimated tile height for the virtualizer. */\n estimateSize?: number;\n currentId?: string;\n /** Consecutive same-sender messages within this window (ms) are merged into one tile. */\n groupWindowMs?: number;\n /** Whether to insert a labeled divider before the first message of each calendar day. */\n dayDivider?: boolean;\n /** A same-day gap exceeding this (ms) inserts an unlabeled divider between groups. */\n gapDividerMs?: number;\n}>;\n\nconst DEFAULT_GROUP_WINDOW_MS = 60_000;\nconst DEFAULT_GAP_DIVIDER_MS = 3 * 60 * 60 * 1000;\n\n/** Virtualized stack of message tiles (via Mosaic), within an internal scroll area. */\nconst ThreadMessages = ({\n messages,\n id,\n estimateSize = 80,\n currentId,\n groupWindowMs = DEFAULT_GROUP_WINDOW_MS,\n dayDivider = true,\n gapDividerMs = DEFAULT_GAP_DIVIDER_MS,\n classNames,\n}: ThreadMessagesProps) => {\n const { dtLocale } = Hooks.useTranslation(translationKey);\n const [viewport, setViewport] = useState<HTMLElement | null>(null);\n const items = useMemo(\n () => groupMessages(messages.filter(Boolean), { groupWindowMs, dayDivider, gapDividerMs, dtLocale }),\n [messages, groupWindowMs, dayDivider, gapDividerMs, dtLocale],\n );\n // Per-instance id keeps concurrent threads (incl. the same thread mounted twice) distinct in the DnD registry.\n const instanceId = useId();\n const eventHandler = useMemo<DndContainerHandler>(\n () => ({ id: `thread:${id ?? 'anon'}:${instanceId}`, canDrop: () => false }),\n [id, instanceId],\n );\n\n return (\n <Mosaic.Container\n asChild\n orientation='vertical'\n autoScroll={viewport}\n currentId={currentId}\n eventHandler={eventHandler}\n >\n <ScrollArea.Root classNames={mx('col-span-2 dx-grow', classNames)} orientation='vertical'>\n <ScrollArea.Viewport ref={setViewport}>\n <Mosaic.VirtualStack\n Tile={ThreadItemAdapter}\n items={items}\n getId={getThreadItemId}\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 } = Hooks.useTranslation(translationKey);\n const themeMode = Hooks.useThemeMode();\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 = Util.ThemedClassName<PropsWithChildren> & {\n activity?: boolean;\n};\n\nconst ThreadStatus = forwardRef<HTMLDivElement, ThreadStatusProps>(\n ({ activity, classNames, children, ...props }, forwardedRef) => {\n const { t } = Hooks.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-fg-muted',\n classNames,\n )}\n ref={forwardedRef}\n >\n <Icon.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"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["_Fragment"],"sources":["../../src/command.ts","../../src/context.ts","../../src/Message/Message.tsx","../../src/Thread/Thread.tsx"],"sourcesContent":["//\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-inline dx-tag-indigo mx-0.5'),\n },\n {\n tag: tags.labelName,\n class: mx('dx-tag dx-tag-inline dx-tag-blue mx-0.5'),\n },\n]);\n\n// Center the inline `.dx-tag` pills on the text line. An inline tag is an inline box\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 { type FC, type ReactNode } from 'react';\n\nimport { createContext } from '@dxos/react-hooks';\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.ts';\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 { format } from 'date-fns/format';\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 { useObject } from '@dxos/echo-react';\nimport { type UseTextEditorProps, useTextEditor } from '@dxos/react-ui-editor';\nimport * as Avatar from '@dxos/react-ui/Avatar';\nimport * as Button from '@dxos/react-ui/Button';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport type * as Util from '@dxos/react-ui/Util';\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 { translationKey } from '#translations';\n\nimport { command } from '../command.ts';\nimport { useThreadContext } from '../context.ts';\nimport { type MessageMetadata } from '../types.ts';\n\nconst avatarSize = 'md';\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 = Util.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 // Columns mirror Thread.Header (avatar/rail · content · controls) so trailing\n // controls align with the thread header's controls.\n return (\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.Root\n size={avatarSize}\n hue={authorAvatarProps?.hue || hexToHue(authorId ?? '0')}\n fallback={authorAvatarProps?.emoji || hexToEmoji(authorId ?? '0')}\n src={authorImgSrc}\n label={authorName}\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 );\n },\n);\n\nMessageRoot.displayName = 'Message.Root';\n\n//\n// Heading\n//\n\nexport type MessageHeadingProps = Util.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 flex items-baseline gap-2 min-w-0'>\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 } = Hooks.useTranslation(translationKey);\n return (\n <span className='block truncate min-w-0 shrink text-sm text-fg-subtle'>{authorName ?? t('anonymous.label')}</span>\n );\n};\n\nMessageAuthorName.displayName = 'Message.AuthorName';\n\nexport type MessageTimeProps = Pick<MessageMetadata, 'timestamp'>;\n\nconst MessageTime = ({ timestamp }: MessageTimeProps) => {\n const { dtLocale } = Hooks.useTranslation(translationKey);\n const dt = timestamp ? new Date(timestamp) : undefined;\n return (\n <time className='shrink-0 text-fg-subtle text-xs' dateTime={dt?.toISOString()}>\n {dt ? format(dt, 'p', { locale: dtLocale }) : ''}\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 [{ blocks }] = useObject(message);\n const textBlockIndex = blocks.findIndex((block) => block._tag === 'text');\n const textBlock = textBlockIndex !== -1 ? (blocks[textBlockIndex] as ContentBlock.Text) : undefined;\n const proposalBlock = blocks.find((block) => block._tag === 'proposal') as ContentBlock.Proposal | undefined;\n const changeBlock = blocks.find((block) => block._tag === 'change') as ContentBlock.Change | undefined;\n const references = 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 text={textBlock.text} isAuthor={isAuthor} editing={editing} onSave={onSave} />}\n {proposalBlock && <div className='me-4 italic'>{proposalBlock.text}</div>}\n {changeBlock && (\n <p className='me-4 text-sm break-words'>\n {changeBlock.before && <span className='line-through opacity-60'>{changeBlock.before}</span>}\n {changeBlock.before && changeBlock.after && ' '}\n {changeBlock.after && <span>{changeBlock.after}</span>}\n </p>\n )}\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 text,\n isAuthor,\n editing,\n onSave,\n}: {\n text: string;\n isAuthor?: boolean;\n editing?: boolean;\n onSave?: (text: string) => void;\n}) => {\n const themeMode = Hooks.useThemeMode();\n const inMemoryContentRef = useRef(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 Hooks.useOnTransition(editing, true, false, saveDocumentChange);\n\n const { parentRef, focusAttributes, view } = useTextEditor(\n () => ({\n initialValue: text,\n extensions: [\n // Edit mode is authorisation enough — the control that gets here is already gated on\n // `isAuthor` — and a mid-edit flip to read-only makes the editor drop input silently.\n createBasicExtensions({ readOnly: !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 // While editing, the editor owns its content and its authorisation: pinning both keeps an incoming\n // `text` update or member-list refresh from rebuilding the view being typed in. `editing` is\n // itself a dep, so the flip still rebuilds.\n [editing, editing ? undefined : text, editing ? undefined : 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 {/*\n Addressable: the reply composer is the only textbox in a thread that is not a message body,\n so without a testid a test can only guess at it by editor order.\n */}\n <div\n ref={parentRef}\n data-testid='thread.reply'\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 /** Whether the avatar-rail continuation line is drawn below the tile; false for the last tile. */\n continues?: boolean;\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, continues = true }: MessageTileProps) => {\n const { t } = Hooks.useTranslation(translationKey);\n const {\n getMetadata,\n identityDid,\n editable,\n onMessageDelete,\n onAcceptProposal,\n onAcceptChange,\n onRejectChange,\n onMessageSelect,\n currentMessageId,\n } = useThreadContext('Message.Tile');\n const [editing, setEditing] = useState(false);\n\n const [blocks] = useObject(message, 'blocks');\n const metadata = getMetadata(message);\n const isAuthor = !!identityDid && identityDid === metadata.authorId;\n const hasProposal = blocks.some((block) => block._tag === 'proposal');\n const hasChange = blocks.some((block) => block._tag === 'change');\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 handleAcceptChange = useCallback(() => onAcceptChange?.(message.id), [onAcceptChange, message.id]);\n const handleRejectChange = useCallback(() => onRejectChange?.(message.id), [onRejectChange, message.id]);\n const handleSelect = useCallback(() => onMessageSelect?.(message.id), [onMessageSelect, 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 showAcceptChange = hasChange && !!onAcceptChange;\n const showRejectChange = hasChange && !!onRejectChange;\n const showDelete = !!onMessageDelete;\n const controls =\n showEdit || showAccept || showAcceptChange || showRejectChange || showDelete ? (\n <div className={buttonGroupClassNames}>\n {showEdit && (\n <Button.Root\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 <Button.Root\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 {showAcceptChange && (\n <Button.Root\n data-testid='thread.message.accept-change'\n variant='ghost'\n icon='ph--check--regular'\n iconOnly\n label={t('accept-change.label')}\n classNames={[buttonClassNames, hoverableControlItem]}\n onClick={handleAcceptChange}\n />\n )}\n {showRejectChange && (\n <Button.Root\n data-testid='thread.message.reject-change'\n variant='ghost'\n icon='ph--x--regular'\n iconOnly\n label={t('reject-change.label')}\n classNames={[buttonClassNames, hoverableControlItem]}\n onClick={handleRejectChange}\n />\n )}\n {showDelete && (\n <Button.Root\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 continues={continues}\n controls={controls}\n // Selecting a tile is how the host reveals what it refers to (a suggestion's range in the\n // document), so the whole tile is the target — the accent marks which one is showing.\n onClick={onMessageSelect ? handleSelect : undefined}\n aria-current={currentMessageId === message.id ? 'location' : undefined}\n classNames={[\n hoverableControls,\n hoverableFocusedWithinControls,\n onMessageSelect && 'cursor-pointer',\n currentMessageId === message.id && 'bg-current-surface',\n classNames,\n ]}\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// Group\n//\n\nexport type MessageGroupProps = {\n /** Consecutive same-sender messages, in ascending time order, rendered as one tile. */\n messages: readonly MessageType.Message[];\n /** Whether the avatar-rail continuation line is drawn below the tile; false for the last tile. */\n continues?: boolean;\n classNames?: MessageRootProps['classNames'];\n};\n\n/**\n * Groups consecutive same-sender messages (see `Thread.Messages`'s grouping\n * window) into a single tile: one heading (author + first message's\n * timestamp) followed by one body per message, stacked in order. Per-message\n * edit/delete controls are not shown per-row in a group — v1 shows them for\n * the group's first message only, since the heading/controls layout is keyed\n * to a single message.\n */\nconst MessageGroup = ({ messages, continues = true, classNames }: MessageGroupProps) => {\n const { t } = Hooks.useTranslation(translationKey);\n const { getMetadata, identityDid, editable, onMessageDelete, onAcceptProposal } = useThreadContext('Message.Group');\n const [editing, setEditing] = useState(false);\n\n const first = messages[0];\n const [blocks] = useObject(first, 'blocks');\n const metadata = getMetadata(first);\n const isAuthor = !!identityDid && identityDid === metadata.authorId;\n const hasProposal = blocks.some((block) => block._tag === 'proposal');\n\n const handleEdit = useCallback(() => setEditing((value) => !value), []);\n const handleDelete = useCallback(() => onMessageDelete?.(first.id), [onMessageDelete, first.id]);\n const handleAcceptProposal = useCallback(() => onAcceptProposal?.(first.id), [onAcceptProposal, first.id]);\n const handleSave = useCallback(\n (text: string) => {\n Obj.update(first, (first) => {\n const block = first.blocks.find((block) => block._tag === 'text');\n if (block && block._tag === 'text') {\n block.text = text;\n }\n });\n },\n [first],\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 <Button.Root\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 <Button.Root\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 <Button.Root\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 continues={continues}\n controls={controls}\n classNames={[hoverableControls, hoverableFocusedWithinControls, classNames]}\n >\n <MessageHeading authorName={metadata.authorName} timestamp={metadata.timestamp} />\n {messages.map((message) => (\n <MessageBody\n key={message.id}\n message={message}\n isAuthor={isAuthor}\n editing={editing && message === first}\n onSave={handleSave}\n />\n ))}\n </MessageRoot>\n );\n};\n\nMessageGroup.displayName = 'Message.Group';\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 Group: MessageGroup,\n};\n","//\n// Copyright 2023 DXOS.org\n//\n\nimport { format } from 'date-fns/format';\nimport { type Locale } from 'date-fns/locale';\nimport { startOfDay } from 'date-fns/startOfDay';\nimport React, {\n type ComponentPropsWithRef,\n type PropsWithChildren,\n type ReactNode,\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport { Obj } from '@dxos/echo';\nimport { type DndContainerHandler } from '@dxos/react-ui-dnd';\nimport { Mosaic, type MosaicTileProps } from '@dxos/react-ui-mosaic';\nimport * as Button from '@dxos/react-ui/Button';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as Icon from '@dxos/react-ui/Icon';\nimport * as ScrollArea from '@dxos/react-ui/ScrollArea';\nimport * as Util from '@dxos/react-ui/Util';\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';\nimport { type ComposableProps } from '@dxos/ui-types';\n\nimport { translationKey } from '#translations';\n\nimport { command } from '../command.ts';\nimport { ThreadContextProvider, useThreadContext } from '../context.ts';\nimport { Message } from '../Message/index.ts';\nimport { type MessageMetadata, type ThreadContextValue } from '../types.ts';\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). Requires an ambient `Dnd.Root` ancestor,\n * within which `Thread.Messages` renders its virtual stack. Renders no DOM of\n * its own — wrap the visible thread chrome in `Thread.Content`.\n */\nconst ThreadRoot = ({\n children,\n getMetadata,\n components,\n identityDid,\n editable,\n onMessageDelete,\n onAcceptProposal,\n onAcceptChange,\n onRejectChange,\n onMessageSelect,\n currentMessageId,\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 onAcceptChange={onAcceptChange}\n onRejectChange={onRejectChange}\n onMessageSelect={onMessageSelect}\n currentMessageId={currentMessageId}\n >\n {children}\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 = Util.composable<HTMLDivElement, ThreadContentExtra>(\n ({ children, current, id, ...props }, forwardedRef) => {\n return (\n <div\n {...Util.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 = Util.composable<HTMLDivElement, ThreadHeaderProps>(\n ({ title, detached, current, controls, onSelect, ...props }, forwardedRef) => {\n const { t } = Hooks.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 {...Util.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 <Button.Root\n iconOnly\n variant='ghost'\n size='sm'\n icon='ph--caret-double-right--regular'\n label={t('select-thread.label')}\n classNames='text-fg-muted'\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-fg-muted',\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\n/** A run of consecutive same-sender messages (within the grouping window) rendered as one tile. */\ntype MessageGroupItem = { kind: 'group'; id: string; messages: MessageType.Message[]; last?: boolean };\n\n/**\n * A divider row between groups: day-labeled (calendar-day boundary) or plain\n * (a same-day gap exceeding `gapDividerMs`). Day boundaries take priority\n * when both coincide on the same message — see `groupMessages`.\n */\ntype DividerItem = { kind: 'divider'; id: string; label?: string };\n\ntype ThreadItem = MessageGroupItem | DividerItem;\n\nconst getThreadItemId = (item: ThreadItem) => item.id;\n\n/** Stable per-sender key: prefers the DID, then the (deprecated) identity key, then name/email, else 'anon'. */\nconst senderKey = (message: MessageType.Message): string =>\n message.sender.identityDid ?? message.sender.identityKey ?? message.sender.name ?? message.sender.email ?? 'anon';\n\n/** Message send time in epoch ms; malformed/missing `created` sorts as if sent at the epoch. */\nconst messageTime = (message: MessageType.Message): number => {\n const time = Date.parse(message.created);\n return Number.isFinite(time) ? time : 0;\n};\n\n/**\n * Preprocesses ascending, time-ordered `messages` into a flat list of divider\n * and group items for `Thread.Messages`'s virtual stack:\n * - A day divider (labeled with the calendar date) precedes the first message\n * of each calendar day.\n * - A plain divider (no label) marks a same-day gap exceeding `gapDividerMs`.\n * - When both would fall on the same message, only the day divider is emitted.\n * - Consecutive messages from the same sender within `groupWindowMs` of the\n * previous message in the group are merged into one `MessageGroupItem`; a\n * divider always starts a new group.\n */\nconst groupMessages = (\n messages: readonly MessageType.Message[],\n {\n groupWindowMs,\n dayDivider,\n gapDividerMs,\n dtLocale,\n }: { groupWindowMs: number; dayDivider: boolean; gapDividerMs: number; dtLocale?: Locale },\n): ThreadItem[] => {\n const items: ThreadItem[] = [];\n let currentGroup: MessageGroupItem | undefined;\n // Tracks the last message appended to `currentGroup`, since `Array.prototype.at(-1)`\n // on `currentGroup.messages` would need a non-null assertion despite `currentGroup`\n // always being non-empty by construction.\n let lastGroupMessage: MessageType.Message | undefined;\n let prevTime: number | undefined;\n let prevDay: number | undefined;\n\n for (const message of messages) {\n const time = messageTime(message);\n const day = startOfDay(time).getTime();\n\n const dayBoundary = dayDivider && (prevDay === undefined || day !== prevDay);\n const gapBoundary = !dayBoundary && prevTime !== undefined && time - prevTime > gapDividerMs;\n\n if (dayBoundary) {\n items.push({\n kind: 'divider',\n id: `divider:day:${day}`,\n label: format(day, 'EEEE, MMMM d', { locale: dtLocale }),\n });\n currentGroup = undefined;\n } else if (gapBoundary) {\n items.push({ kind: 'divider', id: `divider:gap:${time}` });\n currentGroup = undefined;\n }\n\n const sameSenderAsGroup = currentGroup && lastGroupMessage && senderKey(lastGroupMessage) === senderKey(message);\n const withinGroupWindow = currentGroup && lastGroupMessage && time - messageTime(lastGroupMessage) <= groupWindowMs;\n\n if (currentGroup && sameSenderAsGroup && withinGroupWindow) {\n currentGroup.messages.push(message);\n } else {\n currentGroup = { kind: 'group', id: Obj.getURI(message), messages: [message] };\n items.push(currentGroup);\n }\n lastGroupMessage = message;\n\n prevTime = time;\n prevDay = day;\n }\n\n // The trailing group is the last message tile; suppress its avatar-rail continuation line.\n if (currentGroup) {\n currentGroup.last = true;\n }\n\n return items;\n};\n\n//\n// Divider\n//\n\nconst ThreadDivider = ({ label }: { label?: string }) =>\n label ? (\n <div className='flex items-center gap-2 px-2 py-2 text-xs text-fg-muted'>\n <div className='h-px grow bg-separator' />\n <span className='shrink-0'>{label}</span>\n <div className='h-px grow bg-separator' />\n </div>\n ) : (\n <div className='px-2 py-2'>\n <div className='h-px bg-separator' />\n </div>\n );\n\nThreadDivider.displayName = 'Thread.Divider';\n\nconst ThreadItemAdapter = ({ id, data, location, draggable, current, selected }: MosaicTileProps<ThreadItem>) => (\n <Mosaic.Tile id={id} data={data} location={location} draggable={draggable} current={current} selected={selected}>\n {data.kind === 'divider' ? (\n <ThreadDivider label={data.label} />\n ) : (\n <Message.Group messages={data.messages} continues={!data.last} />\n )}\n </Mosaic.Tile>\n);\n\nexport type ThreadMessagesProps = Util.ThemedClassName<{\n messages: readonly MessageType.Message[];\n /** Stable id of the owning thread; scopes the Mosaic container so multiple threads don't collide. */\n id?: string;\n /** Estimated tile height for the virtualizer. */\n estimateSize?: number;\n currentId?: string;\n /** Consecutive same-sender messages within this window (ms) are merged into one tile. */\n groupWindowMs?: number;\n /** Whether to insert a labeled divider before the first message of each calendar day. */\n dayDivider?: boolean;\n /** A same-day gap exceeding this (ms) inserts an unlabeled divider between groups. */\n gapDividerMs?: number;\n}>;\n\nconst DEFAULT_GROUP_WINDOW_MS = 60_000;\nconst DEFAULT_GAP_DIVIDER_MS = 3 * 60 * 60 * 1000;\n\n/** Virtualized stack of message tiles (via Mosaic), within an internal scroll area. */\nconst ThreadMessages = ({\n messages,\n id,\n estimateSize = 80,\n currentId,\n groupWindowMs = DEFAULT_GROUP_WINDOW_MS,\n dayDivider = true,\n gapDividerMs = DEFAULT_GAP_DIVIDER_MS,\n classNames,\n}: ThreadMessagesProps) => {\n const { dtLocale } = Hooks.useTranslation(translationKey);\n const [viewport, setViewport] = useState<HTMLElement | null>(null);\n const items = useMemo(\n () => groupMessages(messages.filter(Boolean), { groupWindowMs, dayDivider, gapDividerMs, dtLocale }),\n [messages, groupWindowMs, dayDivider, gapDividerMs, dtLocale],\n );\n // Per-instance id keeps concurrent threads (incl. the same thread mounted twice) distinct in the DnD registry.\n const instanceId = useId();\n const eventHandler = useMemo<DndContainerHandler>(\n () => ({ id: `thread:${id ?? 'anon'}:${instanceId}`, canDrop: () => false }),\n [id, instanceId],\n );\n\n return (\n <Mosaic.Container\n asChild\n orientation='vertical'\n autoScroll={viewport}\n currentId={currentId}\n eventHandler={eventHandler}\n >\n <ScrollArea.Root classNames={mx('col-span-2 dx-grow', classNames)} orientation='vertical'>\n <ScrollArea.Viewport ref={setViewport}>\n <Mosaic.VirtualStack\n Tile={ThreadItemAdapter}\n items={items}\n getId={getThreadItemId}\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 } = Hooks.useTranslation(translationKey);\n const themeMode = Hooks.useThemeMode();\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 = Util.ThemedClassName<PropsWithChildren> & {\n activity?: boolean;\n};\n\nconst ThreadStatus = forwardRef<HTMLDivElement, ThreadStatusProps>(\n ({ activity, classNames, children, ...props }, forwardedRef) => {\n const { t } = Hooks.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-fg-muted',\n classNames,\n )}\n ref={forwardedRef}\n >\n <Icon.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"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../../../src/Message/Message.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../../../src/Message/Message.tsx"],"names":[],"mappings":"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"}