import{type TemplateResult,type PropertyValues}from'lit';import{LyraElement}from'../../../internal/lyra-element.js';import type{LyraSize}from'../../../internal/variants.js';import{type FormOwnerValue}from'../../../internal/form-associated.js';import{type LyraFormValidator}from'../form-validator.js';export interface LyraRadioEventMap{'lr-invalid':CustomEvent;input:Event;change:Event;'lr-input':CustomEvent<{checked:boolean;value:string;}>;'lr-change':CustomEvent<{checked:boolean;value:string;}>;focus:FocusEvent;blur:FocusEvent;}export type RadioAppearance='default'|'button';type RadioButtonRunPosition='standalone'|'start'|'middle'|'end'; /** * `` — a form-associated single-choice control. Radios can be used * alone or inside ``. * * Deliberately no hint/error chrome of its own -- the default slot already carries real, visible * label text (see `@slot` below), so a labeled-field frame built around `label`/`hint`/`errorText` * props has nothing to add here. A consumer needing shared hint/error messaging for a set of * options composes it once on the owning `` (which does carry `hint`/`errorText`), * the same way a native radio `
`/`` pairs with one externally-owned error node * shared across all its `` children rather than one per option. * Flattened forwarding-slot changes keep the visual label wrapper synchronized; element-only and * decorative `aria-hidden` visuals still count as visual content. A host `aria-label` retains * accessible-name precedence by presence, including an explicitly empty value. * A standalone radio is bounded by its allocation: an unbroken default label wraps within the * available inline size in both LTR and RTL while the circular indicator remains fixed. * In `appearance="button"`, the same `start`/`prefix` and `end`/`suffix` adornment aliases as * `` render around the label. Empty leading, label, and trailing wrappers stay * hidden so only present content contributes the button's flex gaps. * * Host `aria-describedby` references resolve onto the internal radio, including button appearance, * and track live target changes, reconnect and document adoption. Explicit `checked` assignments * mark live state dirty even when unchanged; later default changes affect live state only after reset. * * @customElement lr-radio * @slot - Label content, including forwarded or element-only visuals. * @slot start - Leading content in `appearance="button"`, typically an icon. * @slot prefix - Shoelace-compatible alias for `start` in `appearance="button"`. * @slot end - Trailing content in `appearance="button"`. * @slot suffix - Shoelace-compatible alias for `end` in `appearance="button"`. * @event input - A standalone radio was selected; native-style and composed. * @event lr-input - Standalone prefixed compatibility alias for `input`. * `detail: { checked, value }`. * @event change - A standalone radio was selected; native-style and composed. * @event lr-change - Standalone prefixed compatibility alias for `change`. * `detail: { checked, value }`. An owning radio group emits its aggregate value-event sequence * instead of any child value events. * @event focus - The internal radio received focus. * @event blur - The internal radio lost focus. * @event lr-invalid - The standalone radio failed a validity check. Aggregate groups emit their * own alias instead. Cancelable: calling `preventDefault()` also cancels the native `invalid` * event behind it, suppressing the browser's own validation bubble so an app can present the * failure its own way. * @cssstate required - Matches while the radio is required, either by its own `required` attribute * or by an owning ``. Style with `lr-radio:state(required)`. * @cssstate optional - Matches while it is neither — the complement of `required`. * @cssstate valid - Matches while the control satisfies its constraints, including any * `setCustomValidity()` error. * @cssstate invalid - Matches while it does not — from the very first render, before the user has * touched anything. * @cssstate user-valid - `valid`, but only after the user has interacted with this radio: * selecting it, blurring it, `reportValidity()`, or a submission attempt. Not after a silent * `checkValidity()` alone. * @cssstate user-invalid - `invalid` after that same interaction. Style validation errors with this * rather than `invalid`: a pristine required radio is genuinely invalid, but colouring it red * before the user has done anything is hostile. * @cssstate checked - Matches while this option is selected. * @cssstate disabled - Matches while disabled directly, by a group, or by an ancestor fieldset. * @csspart base - The interactive radio control. * @csspart circle - The circular radio indicator. * @csspart control - WA/Shoelace name for the indicator, or the interactive button in * `appearance="button"`. * @csspart control--checked - Shoelace state alias on the selected indicator. * @csspart dot - The selected indicator. * @csspart checked-icon - WA/Shoelace name for the same selected indicator. * @csspart button - Shoelace button-chrome alias in `appearance="button"` mode. * @csspart button--checked - Shoelace selected-button state alias. * @csspart start - The `appearance="button"` leading-content wrapper; hidden while empty. * @csspart prefix - Shoelace-compatible alias on the same leading-content wrapper. * @csspart label - The default slot wrapper; hidden while it has no real content. * @csspart end - The `appearance="button"` trailing-content wrapper; hidden while empty. * @csspart suffix - Shoelace-compatible alias on the same trailing-content wrapper. * @cssprop [--lr-radio-label-indent=calc(var(--lr-radio-circle-size) + var(--lr-space-s))] - * The inline distance from the control's start edge to the start of the label text, i.e. the * circle's own floor plus the gap next to it — so it tracks `size` along with the circle. Published * so a consumer composing per-option hint text under the label can align it without re-deriving that * formula from the shadow styles, and used as the source of the real gap so the two cannot drift. * Setting it on the element (or on `lr-radio` in your own stylesheet) moves the label; because * custom properties inherit down and not sideways, it is *not* readable from a sibling node in your * tree — align a sibling by computing the same formula from `--lr-theme-icon-button-size`, * `--lr-theme-form-control-height-*` and `--lr-theme-space-s`, which you control. * @cssprop [--lr-radio-checked-border-color=var(--lr-color-brand)] - Border color of `[part='circle']` * while `checked`. Retint just this control's checked ring without touching the shared * `--lr-color-brand` token every other component also reads. * @cssprop [--lr-radio-checked-dot-color=var(--lr-color-brand)] - Background of `[part='dot']` * while `checked`. * @cssprop [--lr-radio-hover-border-color=var(--lr-color-brand)] - Indicator border while the * interactive row is hovered. * @cssprop [--lr-radio-active-border-color=var(--lr-radio-hover-border-color)] - Indicator border * while the interactive row is pressed. * @cssprop [--lr-radio-active-ring-color=var(--lr-color-brand-quiet)] - Indicator ring while the * interactive row is pressed. * @cssprop [--checked-icon-color=var(--lr-radio-checked-dot-color)] - WA-compatible selected-glyph * color alias. * @cssprop [--checked-icon-scale=1] - WA-compatible selected-glyph scale alias. * @cssprop [--lr-radio-circle-size=min(var(--lr-icon-button-size), calc(var(--lr-form-control-height) * 0.7))] - * Edge length of `[part='circle']`. Derived from the `size` tier's shared control height so a radio * lines up with an ``/``/`` of the same `size`. * @cssprop [--lr-radio-dot-size=min(calc(var(--lr-radio-circle-size) * 0.5), calc(var(--lr-form-control-height) * 0.3))] - * Edge length of `[part='dot']`, capped at half the circle so it can never outgrow its ring. * @cssprop [--lr-radio-radius=var(--lr-radius-pill)] - Corner radius of the control's own chrome. * A circular indicator is fully round at every setting; `` re-points this knob at * the shared control radius and swaps it for a pill when `pill` is set. * @cssprop [--lr-radio-button-gap=var(--lr-space-xs)] - Gap between the present start/prefix, * label, and end/suffix wrappers in `appearance="button"`. * @status stable * @since 4.0.0 */ export declare class LyraRadio extends LyraElement{ /** Public WA-compatible intrinsic validator catalog, inherited by radio-button. */ static get validators():LyraFormValidator[];static styles:import("lit").CSSResultGroup[];static formAssociated:boolean;static properties:{customError:{attribute:string;reflect:boolean;noAccessor:boolean;};checked:{attribute:boolean;noAccessor:boolean;};defaultChecked:{attribute:string;type:BooleanConstructor;reflect:boolean;useDefault:boolean;noAccessor:boolean;};appearance:{reflect:boolean;converter:import("lit").ComplexAttributeConverter;};disabled:{type:BooleanConstructor;reflect:boolean;noAccessor:boolean;};name:{reflect:boolean;noAccessor:boolean;converter:import("lit").ComplexAttributeConverter;};pill:{type:BooleanConstructor;reflect:boolean;};required:{type:BooleanConstructor;reflect:boolean;noAccessor:boolean;};size:{reflect:boolean;converter:import("lit").ComplexAttributeConverter;};value:{reflect:boolean;noAccessor:boolean;};}; /** * Control size, on the library's shared ladder. Accepts both spellings of every tier — * `2xs`/`xs`/`s`/`m`/`l`/`xl` and Web Awesome's `small`/`medium`/`large` — so migrating either way * is a tag rename. Scales the indicator off the same `--lr-form-control-*` values * ``/``/`` use, so controls of one `size` line up in a row. The * slotted label keeps the library's standard control-label type size at every tier; restyle it * through `::part(label)` if you want it to track the control. An owning group exposes its * projected tier through `effectiveSize` without overwriting this authored property; likewise, * `effectiveName` reports aggregate name authority without rewriting `name`. */ size:LyraSize; /** WA-compatible visual mode. `button` keeps the same radio semantics and group ownership. */ appearance:RadioAppearance; /** * Rounds the control's own chrome into a pill instead of the shared control radius. A plain * ``'s indicator is a circle at every setting, so this is visible on * ``, which inherits this class and renders rectangular chrome; it is declared * here so both tags carry one property with one meaning. */ pill:boolean;private hasLabel;private hasStart;private hasEnd;private labelObserver?; /** Whether the user has acted on this radio yet, which is what gates the `user-valid`/ * `user-invalid` custom states: a selection, a blur, or interactive validation * (`reportValidity()` or a submission attempt, via `installInteractionOnInvalid()`). A silent * `checkValidity()` alone never counts. A pristine required radio is genuinely invalid, but * styling it as an error before the user has done anything is hostile, which is the entire * reason the `user-*` pair exists. Not `@state`: nothing in `render()` reads it. */ private hasInteracted;private internals;private validityController; /** Consumer-supplied validation message reflected through `custom-error`. */ customError:string|null;private _checked;private _disabled;private _required;private _name;private _value;private _fieldsetDisabled;private _groupDisabled;private _groupRequired;private _groupSize;private _tabbable;private _buttonRunPosition;private groupOwner;private _defaultChecked;private _checkedDirty;private settingDefaultChecked;private reflectingDefaultChecked;get checked():boolean;set checked(value:boolean); /** Reflected current reset default; changing it never overwrites dirty live `checked` state. */ get defaultChecked():boolean;set defaultChecked(value:boolean);get disabled():boolean;set disabled(value:boolean);get required():boolean;set required(value:boolean);get name():string;set name(value:string|null);get value():string;set value(value:string);get effectiveDisabled():boolean;get effectiveRequired():boolean; /** Name used by the owning aggregate group without rewriting this option's authored `name`. */ get effectiveName():string; /** Size projected by the owning group without rewriting this option's authored `size`. */ get effectiveSize():LyraSize;get form():HTMLFormElement|null;set form(owner:FormOwnerValue);getForm():HTMLFormElement|null;get labels():NodeList;get validity():ValidityState;get validationMessage():string;get willValidate():boolean;constructor(); /** `attachInternals()` throws in any environment without a real `ElementInternals` * implementation (e.g. a downstream consumer's happy-dom test suite) -- merely constructing * (or importing) this component must not hard-crash there. Falls back to an inert stand-in: * form participation and validity reporting are unavailable in that environment (there is no * polyfillable substitute), but rendering and every non-form-associated feature keep working. * Mirrors lr-graph-query-builder's identical guard. */ private safeAttachInternals;private inertInternals;private externalDescriptionLease?;private syncExternalDescription;protected updated(changed:PropertyValues):void;private releaseExternalDescription;connectedCallback():void;adoptedCallback():void;disconnectedCallback():void;formResetCallback():void;private restoreCheckedFromDefault;formStateRestoreCallback(state:string|File|FormData|null,reason:'autocomplete'|'restore'):void;formDisabledCallback(disabled:boolean):void; /** Shared with every other form control: disabled (own, fieldset, or group) bars validation. */ private get barredFromValidation();private updateValidity; /** Republishes the six validity custom states (`required`/`optional`, `valid`/`invalid`, * `user-valid`/`user-invalid`) from whatever `ElementInternals` currently holds. `required` * here is the EFFECTIVE one -- a radio inside a `required` `` is required even * with no attribute of its own, and that is what its validity is already computed from. */ private reflectValidityStates;private markInteracted; /** Whether the radio currently satisfies its constraints — the silent query, so it deliberately * does not count as interaction for the `user-*` custom states. * `withStaticValidityCheck()` tells the `installInteractionOnInvalid()` listener above that * whatever `invalid` event fires synchronously inside this call is this call, not a * submission attempt. */ checkValidity():boolean; /** `checkValidity()`, plus the browser's own validation UI on failure. */ reportValidity():boolean; /** * Sets or clears a consumer-supplied validation error — the standard channel for a server-side * rejection ("that plan is no longer available") that no client-side constraint can express. A * non-empty `message` raises `customError` and becomes `validationMessage`, so the control fails * `checkValidity()`, blocks form submission, and matches `:state(invalid)`; `''` clears it. * * Clearing restores the control's own computed validity rather than forcing it valid: a * required-and-unselected radio whose custom error is cleared stays `valueMissing`. The custom * error also survives every intrinsic recomputation in between (each selection, and every * group-driven `required` change, re-runs `updateValidity()`) and a form reset, exactly like a * native control — only another `setCustomValidity('')` clears it. * * A standalone radio owns this validity. Inside ``, the group is the aggregate * form-associated owner, so this method delegates the consumer error to the group. * * The message is caller-supplied content, so it is used verbatim and never localized here. */ setCustomValidity(message:string):void; /** Clears consumer-supplied validity on the standalone radio or its owning group. */ resetValidity():void;click():void;focus(options?:FocusOptions):void;blur():void;private syncFormState;private currentGroup;private group;private select; /** Roving-tabindex state an owning group imposes; `` reads it for its own * `tabindex`, which is the only reason it is not private. */ protected get groupTabbable():boolean; /** Actual contiguous button-run position. Standalone and non-adjacent controls stay rounded. */ protected get buttonRunPosition():RadioButtonRunPosition;private isNestedInteractiveEvent;protected onClick:()=>void;protected onKeyDown:(event:KeyboardEvent)=>void;protected onFocus:(event:FocusEvent)=>void;protected onBlur:(event:FocusEvent)=>void;private isDefaultLabelNode;private labelForwardingSlots;private adornmentForwardingSlots;private observeLabelNode;private bindLabelObserverTargets;private recomputeHasLabel;private assignedAdornmentNodes;private recomputeButtonAdornments;private handleLabelSlotChange;private onLabelSlotChange;private onSlotChange;private onAdornmentSlotChange;render():TemplateResult;}declare global{interface HTMLElementTagNameMap{'lr-radio':LyraRadio;}}export{};