import * as React from 'react'; /** * The banner severity scale. * * `response` is the fifth member, added when `Transcript` supplied the second witness * `.system-messages`' binding said the granularity gap needed — see `chatLogEventStyles`. Figma's six * message types now map onto five treatments rather than four, with `interrupt` and `profile` sharing * `response` and `call start`/`call ended` sharing `success`. */ export declare const CHAT_LOG_EVENT_VARIANTS: readonly ["info", "success", "warning", "error", "response"]; export type ChatLogEventVariant = (typeof CHAT_LOG_EVENT_VARIANTS)[number]; /** * The author emphasis axis. * * cr-web-demo paints the agent's name `#F83D53` and the user's plain white, and this list was built to * replace those with "theme-adaptive ink that clears 4.5:1 against `--color-surface-base` in *both* * themes — `default` 19.37/17.85, `accent` 6.98/12.12, `success` 6.00/10.71, `error` 7.09/7.51". * * **THAT ARGUMENT IS VOID AND FIGMA CONFIRMS THE SOURCE.** Rule 3 removed the light theme, so "in both * themes" is a constraint against a rendering that no longer exists — and `Transcript`'s `Text` (22:3610) * draws `red/red-400` **#f83d53** on the agent prefix, which is cr-web-demo's hex exactly. The port * treated a dark-only hex as evidence of carelessness when it was evidence of the design. * * `agent` is a FIFTH member rather than a re-point of `accent`, which resolves to `#bed6ff` — a pale blue * at 11.04:1 where Figma draws a red at 4.48:1. Better ratio, different hue: the substitution signature. * `accent` is unchanged because eight other components share it and none of them is a transcript. * * The test still derives this list from the cva rather than naming it, so a sixth member cannot be added * without being measured — but the floor is now per-member, because `agent` is a logged conflict and the * other four are not. */ export declare const CHAT_LOG_AUTHOR_COLORS: readonly ["default", "accent", "success", "error", "agent"]; export type ChatLogAuthorColor = (typeof CHAT_LOG_AUTHOR_COLORS)[number]; export declare const CHAT_LOG_SCROLLBARS: readonly ["pill", "hidden", "none"]; export type ChatLogScrollbar = (typeof CHAT_LOG_SCROLLBARS)[number]; declare const chatLogStyles: (props?: ({ scrollbar?: "pill" | "hidden" | "none" | null | undefined; } & import("class-variance-authority/types").ClassProp) | undefined) => string; declare const chatLogMessageStyles: (props?: ({ side?: "end" | "start" | null | undefined; } & import("class-variance-authority/types").ClassProp) | undefined) => string; /** * The author name. * * The source pins it to `w-14` (agent) and `w-12` (user) — two widths chosen for two * specific English words. `min-w-14` keeps the column rhythm without truncating a * longer name. */ declare const chatLogAuthorStyles: (props?: ({ color?: "accent" | "default" | "error" | "success" | "agent" | null | undefined; } & import("class-variance-authority/types").ClassProp) | undefined) => string; declare const chatLogTextStyles: (props?: import("class-variance-authority/types").ClassProp | undefined) => string; /** * The highlighted term's ink. * * **THE REFUSAL HERE IS VOID, AND IT IS THE EXACT ARGUMENT RULE 3 RETIRED.** It read: the source uses * `#3acefa`, "which is exactly `--color-highlight` and measures **1.84:1** against the light surface — * unusable as text on a theme-adaptive page", so `--color-text-accent-strong` was substituted at * 6.98:1 light / 12.12:1 dark. There is no light surface: the file is authored dark-only, and CLAUDE.md * rule 3 states that "it fails in light" is no longer a reason to refuse a Figma value. * * On the transcript panel Figma actually draws this on, `#3acefa` measures **8.82:1** — comfortably past * 4.5:1. `--color-highlight` already carries the literal, so nothing needed minting. * * The `font-semibold` stays, and for a reason the refusal stated well: the extra weight means the * emphasis survives where the hue does not read (a monochrome display, a user stylesheet). That is a 1.4.1 * belt-and-braces addition Figma does not contradict, so rule 4 breaks no tie. */ declare const chatLogHighlightStyles: (props?: import("class-variance-authority/types").ClassProp | undefined) => string; /** * The event banner. * * Geometry is the Figma system-message source's: a **4px left rule**, 4px radius, 12px * horizontal and 8px vertical padding. `rounded-medium` is Figma's name for its 4px step * (`bindings/system-messages.json` records `radius/medium`) — deliberately *not* the 8px * control / 12px nested-panel / 16px shell steps of cr-web-demo's radius hierarchy. * * **This said "a full 1px outline" and was wrong, and the error ran in the expensive * direction.** cr-web-demo drew a 4px left rule; a previous pass changed it to a full * outline to "match Figma" and recorded that as a correction. Figma draws the left rule — * `get_design_context` puts `border-l-4 border-solid` in the *shared* root class string of * `.system-messages` (22:5672), before any per-variant branch, so it holds for all six * variants. The REST payload reported a stroke and its colour but not its **sidedness**, so * a stroke was read as a box. The upstream source had been right all along. * * A `not.toContain('border-l-4')` assertion was then added, which pinned the wrong geometry * in place and would have failed on any move back toward the design. It now asserts the rule. * * Ink is PER VARIANT, not shared: Figma's ink on the four light fills and white on `error`'s * opaque `red-600` and on `warning`'s tint. `warning` is the ONLY surface left that is a * translucent `rgba()`, so it is the only one whose effective contrast still depends on the page * behind it — `--color-text-primary` is `#ffffff` in dark and clears 17.85:1 against * `--color-surface-base`, which is what sits there. Every other variant is measured against its * own fill. * * Toast's per-variant *glyphs* are reused below, but not its per-variant icon inks: * `--color-icon-warning` measures 2.61:1 on the light page and 2.37:1 on its own light surface, so * an icon painted with it would fail WCAG 1.4.11 as a non-text signal. Figma's own glyph inks are a * different question and are applied — see `chatLogEventIconStyles`. * * The boundary is decorative rather than a control boundary. The glyph and the * visually-hidden variant name remain the semantic signals, so the event never relies * on color alone. */ declare const chatLogEventStyles: (props?: ({ variant?: "error" | "success" | "warning" | "info" | "response" | null | undefined; } & import("class-variance-authority/types").ClassProp) | undefined) => string; /** * THE GLYPH IS NOT THE TEXT INK, on three of Figma's six banners. * * Every glyph here inherited the banner ink through `text-inherit`, and the manifest defended that * as a WCAG 1.4.11 choice — `--color-icon-warning` measures 2.61:1 on the light page, so an icon * painted with it would fail as a non-text signal. That measurement is about `--color-icon-warning`. * It is not about these two: reading `.system-messages` (22:5672) for its ICONS rather than its * fills, `informative`'s microphone is `accesible-red-dark-theme` at **4.23:1** on the white fill * and `response`/`profile`'s user glyphs are `blue-600` at **7.05:1**, both clear of 3:1. The * refusal does not transfer, so the glyph ink is Figma's. * * `success` and `error` state their inherited value explicitly rather than omitting it — Figma does * paint those two glyphs the text ink, and an omission would read as "not yet checked" next to two * neighbours that were. `warning` is the rule-2 gap, as everywhere else in this component. * * A SEPARATE `cva` FROM `chatLogEventStyles`, and deliberately: that one is guarded by a test * asserting exactly ONE ink per variant, because `cva` concatenates and a second ink there would be * resolved by stylesheet order. An icon ink belongs to the icon slot, not to the banner, so it goes * on the element it paints and the banner's guard keeps its meaning. */ declare const chatLogEventIconStyles: (props?: ({ variant?: "error" | "success" | "warning" | "info" | "response" | null | undefined; } & import("class-variance-authority/types").ClassProp) | undefined) => string; /** A line of conversation. */ export interface ChatLogMessageEntry { /** Stable identity. Used as the React key when present. */ id?: string; type: 'message'; /** Speaker name, rendered in the gutter. Any string — this component knows no roles. */ author: string; text: string; /** * `end` mirrors the row, for the viewer's own messages. * @default 'start' */ side?: 'start' | 'end'; /** * Author-name emphasis. Every option clears 4.5:1 in both themes. * @default 'default' */ authorColor?: ChatLogAuthorColor; } /** A banner's single action. */ export interface ChatLogEventAction { label: string; onClick: () => void; /** * `inline` is an underlined run of the banner's own copy, continuing the sentence — what Figma * draws on the one banner it gives an action (`.system-messages` 22:5673: "Connection error. " * then an underlined "Try again"). `button` is the boxed `Button` the upstream consent replies * used; Figma draws no such control, so it is opt-in. * @default 'inline' */ variant?: 'inline' | 'button'; /** * A trailing glyph, e.g. `ArrowCycleIcon` on Figma's retry. Decorative, and inside the control * rather than beside it — Figma packs it hard against the label, which a sibling of the * `flex-1` copy could not be, and it enlarges the target without changing what is drawn. */ icon?: React.ReactNode; } /** A banner about something that happened, optionally with one action. */ export interface ChatLogEventEntry { /** Stable identity. Used as the React key when present. */ id?: string; type: 'event'; /** Semantic severity. Drives the surface, the stripe, the glyph, and the hidden label. */ variant: ChatLogEventVariant; /** * The banner copy. `ReactNode` because Figma's banners are one sentence with mixed emphasis and * a `string` could not carry it; the hidden variant label is still prepended, so severity does * not depend on what a caller passes. */ text: React.ReactNode; /** Override the variant's glyph. Decorative — the hidden variant label carries the meaning. */ icon?: React.ReactNode; /** A single action, e.g. a retry or a consent reply. */ action?: ChatLogEventAction; } /** An escape hatch: rendered verbatim inside a keyed, slotted wrapper. */ export interface ChatLogCustomEntry { /** Stable identity. Used as the React key when present. */ id?: string; type: 'custom'; render: React.ReactNode; } export type ChatLogEntry = ChatLogMessageEntry | ChatLogEventEntry | ChatLogCustomEntry; export interface ChatLogProps extends React.ComponentPropsWithoutRef<'div'> { /** The log, oldest first. */ entries: ChatLogEntry[]; /** Terms to emphasise wherever they appear as whole words in message text. */ highlights?: string[]; /** * Scroll to the newest entry when entries change — but only if the reader is * already at the bottom. * @default true */ autoScroll?: boolean; /** * Scrollbar appearance. * - `pill` (default): Figma's 8px gray-700 pill scrollbar. * - `hidden` / `none`: Suppresses the scrollbar (`scrollbar-width: none` / `::-webkit-scrollbar: none`). * @default 'pill' */ scrollbar?: ChatLogScrollbar; /** * Optional ref to an external scroll container (e.g. ScrollArea viewport), if ChatLog is wrapped * and should autoscroll that container instead of its own root element. */ scrollContainerRef?: React.RefObject | React.MutableRefObject; /** Replaces the default `EmptyState` entirely when `entries` is empty. */ emptyState?: React.ReactNode; /** * Default empty-state headline. * @default 'No messages yet' */ emptyTitle?: string; /** * Default empty-state body. * @default 'Messages will appear here as the conversation goes on.' */ emptyBody?: string; /** * Visually-hidden prefix naming an event's severity, so the severity is not carried * by colour alone. * @default { info: 'Information:', success: 'Success:', warning: 'Warning:', error: 'Error:', response: 'Information:' } */ variantLabels?: Record; } /** * Wrap every whole-word occurrence of `highlights` in an emphasised span. * * Ported from the source's `highlightText`, whose two subtleties are both load-bearing: * * 1. **Every term is regex-escaped** before being joined into the alternation, so a * term like `a.b` or `c++` matches literally instead of as a pattern (and cannot * throw on an unbalanced `(`). * 2. **The split relies on capture-group parity.** `String.prototype.split` with a * regex that contains *one* capture group interleaves the captures into the result: * index 0 is the text before the first match, index 1 is the first match, index 2 * is the text between matches, and so on. So odd indices are exactly the matches, * and no second pass over the text is needed. This only holds because the pattern * has precisely one group — adding another would shift the parity, which is why the * lookaround assertions are non-capturing. * * The `(? */ export declare function ChatLogEvent({ entry, variantLabel }: ChatLogEventProps): React.JSX.Element; /** * A scrolling conversation log: messages with an author gutter, semantic event * banners, and an escape hatch for anything else. * * The extraction of cr-web-demo's `TranscriptSection`, with the voice-call domain * removed. The source's union is welded to one product — `call_start`, `call_ended`, * `interrupt`, `connection_error`, `profile_updated`, `language`, `voice`, plus a * `tool` entry whose two hardcoded consent button-sets are named `requestContact` and * `requestMarketing`. Here there are three entry types and no product vocabulary: * * - The five system banners collapse to a semantic `variant` axis. `connection_error` * was the only red one, the two call-lifecycle events were the only blue ones, and * the rest were plain — that is a severity scale being spelled out by hand. * - The `tool` entry becomes `action` on an event entry rather than the `custom` * hatch. It is a banner with a button, which is a shape the pattern can own; what * was product-specific about it was the *button sets*, and those are now the * caller's `{ label, onClick }`. `custom` remains for anything genuinely outside * the vocabulary — an inline chart, a typing indicator — so the escape hatch is not * spent on the common case. * * Also dropped: `isMicPending` and its banner (an event entry), `onClear` and the * "call ended" clear button (a caller's own `custom` entry or an event `action`), the * embedded `ChatInput` (compose it — the stories do), and react-i18next. * * @example * */ export declare const ChatLog: React.ForwardRefExoticComponent>; export { chatLogStyles, chatLogMessageStyles, chatLogAuthorStyles, chatLogTextStyles, chatLogHighlightStyles, chatLogEventStyles, chatLogEventIconStyles, highlightText, }; //# sourceMappingURL=chat-log.d.ts.map