ranui
Version:
A framework-agnostic Web Components UI library built on native custom elements, with TypeScript types, light/dark theming, SSR and PWA support.
80 lines (79 loc) • 3.36 kB
TypeScript
import { EventManager } from '../../utils/builder';
import { RanElement } from '../../utils';
import '@/components/disclosure-row';
import type { DisclosureRow } from '../disclosure-row';
/**
* `<r-reasoning>` — a collapsible chain of thought.
*
* Reasoning is the one part of a response a reader wants to watch while it happens and
* almost never wants to keep afterwards. So the element expands while `streaming` is set and
* collapses when it clears, and the collapsed line keeps showing where the thinking has got
* to — see {@link summaryOf}.
*
* **Until the reader touches it.** Once they expand or collapse it themselves, the automatic
* behaviour stops for good — the same ownership rule `createBottomFollower` applies to
* scrolling, and for the same reason: an interface that keeps re-deciding something the
* reader has already decided is worse than one that never decided at all. Setting `open`
* from script counts as taking control too, since script is acting for a caller who has an
* opinion.
*
* The header is `r-disclosure-row`, the same chrome a tool call uses, so a transcript
* carrying both has one disclosure language rather than two.
*
* ```ts
* const reasoning = document.querySelector('r-reasoning');
* reasoning.streaming = true; // expands, and sweeps
* reasoning.content += delta; // grows while visible
* reasoning.streaming = false; // collapses, unless the reader intervened
* reasoning.duration = 4200; // "4.2s" beside the label
* ```
*
* Attributes: `open`, `streaming`, `label`, `duration` (ms), `sheet`. The default slot
* replaces the rendered text, for a caller that wants `<r-markdown>` in the body.
*/
export declare class Reasoning extends RanElement {
_events: EventManager;
_shadowDom: ShadowRoot;
_row: DisclosureRow;
_text: HTMLElement;
/**
* Whether the reader (or a caller acting for them) has decided the open state.
*
* Once true, `streaming` no longer opens or closes anything.
*/
private _readerOwns;
/** Guards the element's own `open` writes from being mistaken for the reader's. */
private _writingOpen;
private _content;
static get observedAttributes(): string[];
constructor();
/** The reasoning text. Assigning repeatedly is the streaming path. */
get content(): string;
set content(value: string);
/** Whether reasoning is still arriving. */
get streaming(): boolean;
set streaming(value: boolean);
/** Whether the body is expanded. */
get open(): boolean;
set open(value: boolean);
/** Summary text. Defaults to `Reasoning`. */
get label(): string;
set label(value: string);
/** How long the model spent, in milliseconds. Rendered beside the label when set. */
get duration(): number | null;
set duration(value: number | null);
get sheet(): string;
set sheet(value: string);
connectedCallback(): void;
disconnectedCallback(): void;
attributeChangedCallback(name: string, old: string | null, next: string | null): void;
handlerExternalCss: () => void;
/**
* Expands while reasoning arrives and collapses when it stops.
*
* @param streaming Whether reasoning is still arriving.
*/
private _followStreaming;
private _syncRow;
}
export default Reasoning;