import{type TemplateResult,type PropertyValues}from'lit';import{LyraElement}from'../../../internal/lyra-element.js';import{type LyraTimestamp}from'../timestamp.js';import'../../utility/live-region/live-region.class.js';export type ChatMessageRole='user'|'assistant'|'system';export type ChatMessageStatus='sending'|'sent'|'failed'|'streaming';export type ChatMessageActionsPosition='inside'|'outside';export interface ChatMessageToggleDetail{collapsed:boolean;}export interface LyraChatMessageEventMap{'lr-message-retry':CustomEvent<{messageId?:string;}>;'lr-toggle-request':CustomEvent;'lr-toggle':CustomEvent;} /** * `` — a role-based message bubble *shell* for a chat/ * agent conversation surface. It renders none of the message content itself: * the default slot carries whatever a consumer wants to display (plain * text, a ``, a custom template, anything at all) and this * component only supplies the surrounding chrome — alignment/coloring by * `role`, an avatar/badges header row, an optional collapse toggle, an * attachments strip, and a status-aware footer (a live-updating status dot + * text, the formatted `timestamp`, a built-in retry affordance for * `status="failed"`, and an `actions` slot for everything else). * * No built-in copy button is rendered. Deciding what "the copyable text" of * an arbitrary slotted message even means (plain text? the rendered * markdown source? something else?) is exactly the kind of content * interpretation this shell deliberately stays out of — slot a copy control * into `actions` instead. Compose `` with the intended source * text, or emit `lr-copy` from a custom control only after its clipboard write * fulfills, with frozen `detail: { ok: true, text }`. This matches the success * contract used by copy controls across the conversation surface. * * Accessibility of `status`: the current status is always available as * plain visible text (`[part="status-text"]`), never color alone. A * transition *to* `"failed"`, or *from* `"streaming"` to `"sent"` (a stream * finishing), is additionally announced through an internal * `` (see that component's header for the throttled- * announcement wiring this composes) so a screen-reader user who isn't * currently focused on this message still learns about it — *unless* the * `failure` slot has content, in which case this internal announcement is * skipped: the host's own `role="alert"` failure content is expected to * announce itself, and firing both would double-announce the same failure * with two different (and differently specific) messages. This differs * from ``'s deliberately simpler `role="status"` * approach — that component only ever has one thing to announce (its own * mount); this one has a `status` that can flip between several values * across a single element's lifetime, which is exactly the coalescing job * `` exists for. * * `messageRole` identifies the author (`user`/`assistant`/`system`, matching * the vocabulary of chat/completion APIs). The platform `role` property remains available for * host semantics; the localized author identity directly names the internal article through its * `aria-label`, and a host `aria-label` overrides that fallback by attribute presence. * * `actionsPosition="outside"` renders the `actions` slot as a sibling immediately after the * message bubble instead of nested inside the footer. * * @customElement lr-chat-message * @slot - The message body. * @slot avatar - An avatar/icon for the message author. * @slot badges - Small status/metric chips (e.g. token count, latency, model name) — entirely app-supplied; this component computes none of that itself. * @slot actions - Action controls (e.g. copy, retry), rendered at the end of the footer. * @slot attachments - File/image attachment chips, rendered below the message body by default; see `attachments-position`. * @slot failure - Only ever rendered while `status="failed"`. Empty (the default), the footer keeps * its built-in `[part="status-text"]`/`[part="retry-button"]` exactly as before. The moment this * slot has assigned content, that built-in status text and retry button are suppressed — the host * is now fully responsible for presenting its own failure UI, and the built-in `chatFailedAnnounce` * live-region announcement is suppressed too (see `@event lr-message-retry` below for the effect on that * event, and the "Accessibility of `status`" paragraph above for the built-in announcement this * replaces). Content assigned here should carry `role="alert"` itself when it represents an * actionable send failure — this component does not add that role on the host's behalf, since it * has no way to know what markup the host puts in this slot. This mirrors `lr-flow-node`'s `header` * slot, which replaces that component's own built-in heading row the same way. * @event lr-message-retry - Fired by the built-in retry button, only rendered when `status="failed"` and the * `failure` slot is empty. `detail: { messageId?: string }` includes this element's stable * `messageId` when supplied, so a conversation surface can identify the message without a * closure around each row. A host using the `failure` slot owns its own retry control and is not * required to use this event at all — but nothing stops that control from dispatching its own * `new CustomEvent('lr-message-retry', { bubbles: true, composed: true })` to stay consistent with the * same event contract a listener further up a conversation surface already relies on for every * other message. * @event lr-toggle-request - Cancelable request to change collapse state. `detail: { collapsed }`. * @event lr-toggle - Collapse state committed. `detail: { collapsed }`. * @csspart bubble - The message article and bubble root. Programmatically focusable (`tabindex="-1"`) so focus has a stable place to land when the built-in retry button is removed. Its fill, text, and geometry derive from the documented theme hooks. * @csspart header - The row above the message body — avatar, badges, and the collapse toggle. Hidden entirely when none of those have anything to show. * @csspart avatar - The wrapper around the `avatar` slot. * @csspart badges - The wrapper around the `badges` slot. * @csspart collapse-button - The built-in collapse/expand toggle (only rendered when `collapsible`). * @csspart body - The wrapper around the default slot (the message content). Hidden while `collapsed`. * @csspart attachments - The wrapper around the `attachments` slot. * @csspart failure - The `failure` slot itself (`display: contents` — it contributes no box of its * own, so the host's own content lays out exactly as if it were a direct child of `bubble`, with no * `::part(failure)` override needed to get there). Only present in the DOM while `status="failed"`. * @csspart footer - The row below the message body — status, timestamp, retry, and actions. Hidden entirely when none of those have anything to show. * @csspart status-indicator - A small decorative (`aria-hidden`) dot reflecting `status`; absent while `status="sent"`. * @csspart status-text - The visible text twin of `status-indicator` — carries the state in text, not just color. * @csspart timestamp - The formatted `timestamp`, rendered in a `