import{type TemplateResult,type PropertyValues}from'lit';import{LyraElement}from'../../../internal/lyra-element.js';import type{LyraSize}from'../../../internal/variants.js';import{type LyraHeadingLevel}from'../../../internal/heading-level.js';import{type OverlayDeactivateOptions}from'../../../internal/overlay-manager.js';import{type RegisteredAnimationSpec}from'../../../internal/registered-animation.js'; /** * Reason a dialog was dismissed, forwarded as the `lr-close` event * detail. `'escape'` and `'backdrop'` are emitted by the dialog's own built-in * dismiss triggers; `'close-button'` by the built-in header close button * (rendered when `closable` is set); `'unmount'` is emitted when the dialog is * removed from the DOM while still open by something other than its own * `close()` (e.g. a consumer's own cleanup code, or a parent re-render that * drops it); any other string is whatever a caller passes to `close()` (e.g. a * consumer's own footer close button, or confirm.ts's `'confirm'`/`'cancel'`). * `'api'` covers `close()` with no argument, `hide()`, and `open = false`. */ export type DialogCloseReason='escape'|'backdrop'|'close-button'|'api'|'unmount'|(string&Record); /** Shoelace-compatible reason a built-in affordance asked a dialog to close. */ export type LyraDialogRequestCloseSource='close-button'|'keyboard'|'overlay';export interface LyraDialogRequestCloseDetail{source:LyraDialogRequestCloseSource;} /** Web Awesome-compatible source element carried by `lr-hide`. */ export interface LyraDialogHideDetail{source:Element;} /** Compatibility controller used while a third-party modal temporarily owns focus. */ export interface LyraDialogModalController{activateExternal():void;deactivateExternal():void;}export interface LyraDialogEventMap{'lr-show':CustomEvent;'lr-after-show':CustomEvent;'lr-hide':CustomEvent;'lr-after-hide':CustomEvent;'lr-initial-focus':CustomEvent;'lr-request-close':CustomEvent;'lr-close':CustomEvent;} /** * `` — a general-purpose modal/overlay. `role="dialog"`, * focus-trapped while open, dismissible via Escape or (opt-in) a backdrop click, and * scroll-locks the document for as long as it's open. While open it is promoted into the * browser top layer, so no consumer stacking context can render on top of it. The mapped * `label` property renders as a visible title and the close affordance is present by default; * `closable="false"` plus either header-suppression spelling support custom chrome. `no-header` is * Shoelace's name for it and `without-header` is Web Awesome's; both are current upstream * spellings, neither is deprecated, and both are read. * * Lifecycle: `show()` emits `lr-show` (cancelable) and then, once the enter animation has * finished, `lr-after-show`. `hide()`/`close()` emit `lr-hide` (cancelable), then * `lr-close` (cancelable, carrying the dismissal reason), then — once the exit animation * has finished — `lr-after-hide`. Assigning `open` runs the same lifecycle, so the property, the * reflected attribute, and the two method calls can never disagree. Markup that renders open * from the start emits nothing, matching ``. * The panel resolves `dialog.show`/`dialog.hide` through the public animation registry; the * backdrop resolves `dialog.overlay.show`/`dialog.overlay.hide`. A per-element registration wins * over a page default, while keyframes-only overrides retain the dialog's token-derived timing. * * Accessible naming and visible-title precedence are independent. A host `aria-label` wins by * attribute presence, including an explicitly empty value, followed by `accessible-label`, then * the text of a direct light-DOM heading. Otherwise the visible title wrapper names the panel. * Within that wrapper the rich `label` slot wins over the `label` property, which wins over the * legacy `heading` property. Explicit accessible-only naming never suppresses that visible title. * * The slotted-heading case deliberately uses `aria-label` (a copied string) * rather than `aria-labelledby` pointing at the heading's `id`: the heading is * *light-DOM* content while `[part="panel"]` lives in this element's * *shadow* tree, and an ID-reference attribute can't resolve across that * boundary (verified against axe's `aria-dialog-name` rule) — unlike the * mapped-title cases above, where the target element is rendered * inside the same shadow root it labels, so `aria-labelledby` there is safe. * The `label` *slot* is safe for the same reason: `aria-labelledby` targets the shadow-owned * `part="heading"` wrapper, and the accessible-name computation flattens the slot inside it. * That generated visible title is a level-three heading by default; set `heading-level` from * `1`–`6` to fit the surrounding outline, or `none` for visual-only title text. A direct * light-DOM heading retains its own level instead. * * `closable` defaults to true and renders a close (X) button in the header row (creating one, with * no heading text, if neither `heading` nor the `label` slot is set) that closes the dialog via * the same `close()` path as Escape/backdrop-dismiss, with reason `'close-button'`. * * The `body` part is the element that scrolls, so it carries `tabindex="-1"`: a dialog holding * only prose, a table, or a rendered document would otherwise have no keyboard stop at all and * its content would be readable by mouse alone. It joins the Tab order only while it actually * overflows, sorts behind any control inside it for initial focus, and shows the standard focus * ring on `::part(body)` when it takes focus. * * Stacking: opening one `` while another is already open (e.g. a * `confirm()` launched from within an already-open dialog) is supported -- * Escape and the Tab focus trap only ever act on the topmost open dialog, so * dialogs beneath it stay open and untouched until the one on top closes. * * Removing label safely omits its fallback title. Open dialog and drawer names follow supported name and exclusion attribute changes on direct unslotted headings, while host naming retains precedence; nested and slot-empty headings remain outside automatic discovery. * * @customElement lr-dialog * @slot - The dialog body. * @slot label - Rich header content, rendered in the header row and used as the panel's * accessible name. Wins over the plain-string `label` and legacy `heading` properties. * @slot header-actions - Extra controls rendered in the header row, before the built-in close * button. * @slot footer - Action buttons, rendered in a bottom row. * @event lr-show - The dialog is about to open. Cancelable — `preventDefault()` keeps it closed. * Descendants emit the same name; handle it as this dialog's event only when * `event.target === event.currentTarget`. * @event lr-after-show - The dialog is open and its enter animation has finished. Descendants * emit the same name; handle it as this dialog's event only when * `event.target === event.currentTarget`. * @event lr-hide - The dialog is about to close, for every dismissal path. Cancelable — * `preventDefault()` keeps it open and stops `lr-close` from firing at all. Detail is * `{ source: Element }`, the affordance or host that requested the transition. The single * exception is an open dialog being removed from the document: the close has already happened * and cannot be undone, so that one is announced non-cancelable. Descendants emit the same * name; handle it as this dialog's event only when `event.target === event.currentTarget`. * @event lr-after-hide - The dialog is closed and its exit animation has finished. Descendants * emit the same name; handle it as this dialog's event only when * `event.target === event.currentTarget`. * @event lr-initial-focus - Emitted immediately before the first automatic focus movement for an * open activation. Cancelable; vetoing it leaves focus where the caller put it. CSS-hidden * dialogs defer it until rendered, and reconnecting the same open dialog does not repeat it. * @event lr-request-close - A built-in affordance requested dismissal. Cancelable; detail is * `{ source: 'close-button' | 'keyboard' | 'overlay' }`. * @event lr-close - `detail: DialogCloseReason`. Cancelable — a listener calling * `preventDefault()` stops the dialog from closing, for every dismissal path (Escape, backdrop, * the built-in close button, `hide()`, `open = false`, or a consumer's own `close()` call). * Fires after `lr-hide` and carries the one thing `lr-hide` does not: which affordance asked * for the close. The plain `lr-close` spelling matches ``, * ``, and ``, whose own docs already describe * their close-reason detail as mirroring this shape. Also fired (with reason `'unmount'`, * non-cancelable there since the element is already being removed) when the dialog is removed * from the DOM while still open. * * **The name is not dialog-scoped, so filter by target.** `lr-close` is emitted by nine * components in this library, several of which are commonly nested *inside* a dialog: * `` (an inline notice above a form), ``/``, * ``, ``, ``, and the three * tool dialogs. Library events bubble and are composed, so a listener bound directly on * `` also receives a descendant's close — and a closable callout inside a dialog would * otherwise dismiss the whole dialog. Their details differ too (`` and `` * carry none, where this event carries a `DialogCloseReason`), so a handler reading * `event.detail.reason` would throw on a foreign one. This is latent rather than * broken-on-arrival, because a callout or tab only emits once given a close affordance — which * is what makes it a bad failure mode: it appears later and presents as the dialog dismissing * itself. Guard on the target, the way `` already does internally: * * ```js * dialog.addEventListener('lr-close', (event) => { * if (event.target !== event.currentTarget) return; // a descendant's close, not this dialog's * // ... * }); * ``` * @csspart base - Shoelace wrapper alias. * @csspart backdrop - The full-viewport scrim behind the panel; also carries `overlay`. * @csspart overlay - Shoelace alias on the backdrop. * @csspart panel - The dialog panel itself (`role="dialog"` while open); also carries `dialog`. * Shrink-wraps to its * content by default, capped at `--lr-dialog-max-width` (default `32rem` at the `size="m"` tier — * see the `size` property); set * `--lr-dialog-width` for an assertive width instead of only a cap. `--lr-dialog-height` is the * same idea on the block axis: left unset the panel stays content-sized (capped at the * viewport), and set it gives `body` a definite size to fill and scroll within while `header`/ * `footer` keep their natural size. * @csspart dialog - Web Awesome alias on the panel. * @csspart header - The header row, rendered when the `label` slot is filled, `label`/`heading` * is set (and no heading is slotted into the default slot), `header-actions` is filled, and/or * `closable` is `true` — and never when `noHeader` or `withoutHeader` is set. * @csspart heading - The visible title inside `header`; also carries `title` and `label`, and owns * the configured heading semantics unless opted out. * @csspart title - Mapped alias on the visible title. * @csspart header-actions - The wrapper around the `header-actions` slot. * @csspart close-button - The built-in close button, rendered inside `header` * only when `closable` is `true`. * @csspart close-button__base - Exported mapped alias on the close button, on the same node. * @csspart close-button__control - The composed ``'s own native control, forwarded * because the painted surface now sits one shadow boundary deeper than `close-button`. As of * 16.0.0 the close button IS an ``, so its background, radius, hover/press mixes, * focus ring and hit-area floor come from `--lr-icon-button-*`; a rule that painted through * `::part(close-button)` moves here or onto the token. * @csspart label - Mapped alias on the visible title. * @csspart body - The wrapper around the default slot. * @csspart footer - The wrapper around the `footer` slot. * @cssprop [--lr-dialog-overlay-color=var(--lr-color-overlay)] - Backdrop scrim color. * @cssprop [--lr-dialog-backdrop-filter=none] - `backdrop-filter` applied to the scrim, for a * frosted-glass treatment over the page behind it. * @cssprop [--backdrop-filter=var(--lr-dialog-backdrop-filter,none)] - Mapped backdrop-filter * alias. * @cssprop [--width=var(--lr-dialog-width,auto)] - Mapped panel width alias. * @cssprop [--spacing=var(--lr-dialog-spacing,var(--lr-space-l))] - Mapped shared region spacing. * @cssprop [--header-spacing] - Mapped header padding override. * @cssprop [--body-spacing] - Shoelace body padding override. * @cssprop [--footer-spacing] - Shoelace footer padding override. * @cssprop [--show-duration] - Mapped opening animation duration. * @cssprop [--hide-duration] - Mapped closing animation duration. * @cssprop [--lr-dialog-width=auto] - Assertive inline size for the panel. Left at `auto` the panel * shrink-wraps to its content. * @cssprop [--lr-dialog-max-width=var(--lr-dialog-width, var(--_lr-dialog-max-width))] - Cap on the * panel's inline size. Falls back to `--lr-dialog-width` when that is set, so an assertive width * is not clipped by the tier default; the viewport (`100%`) is always a hard limit on top. The * innermost fallback steps with `size` across the shared six-step ladder (`20rem` at `2xs` up to * `48rem` at `xl`, `32rem` unchanged at the `m` default) -- an inherited or direct value here * still wins outright over every tier. * @cssprop [--lr-dialog-height=auto] - Assertive block size for the panel, mirroring * `--lr-dialog-width` on the other axis. Left at `auto` the panel shrink-wraps to its content, * unchanged from before this property existed; always capped at `100%` (the viewport) like * every other panel dimension. With it set, `body`'s own `flex: 1 1 auto` is what actually gives * slotted content a definite, fillable block size -- `header` and `footer` keep their natural * size and only `body` grows or shrinks into the remaining space. * @cssprop [--lr-dialog-spacing=var(--lr-space-l)] - Padding inside the body, and the inline * padding of the header and footer rows. * @cssprop [--lr-dialog-spacing-block=var(--lr-space-m)] - Block padding of the header and footer * rows, which are tighter than the body by default. * @cssprop [--lr-dialog-panel-duration=var(--lr-duration-base)] - Duration of the panel's * enter/exit animation. * @cssprop [--lr-dialog-backdrop-duration=var(--lr-duration-fast)] - Duration of the backdrop's * fade. * @cssprop [--lr-overlay-surface=var(--lr-color-surface-overlay)] - Shared floating-surface fill, * on the panel. The same family every anchored popup now reads, so one declaration retints the * dialog and the popups opened from it together. * @cssprop [--lr-overlay-border=var(--lr-color-border)] - Shared floating-surface edge colour, on * the panel and on the header's and footer's dividing rules. * @cssprop [--lr-overlay-radius=var(--lr-radius)] - Shared floating-surface corner radius, on the * panel and on the close button. * @cssprop [--lr-overlay-shadow-modal=var(--lr-shadow-xl)] - Elevation of a modal panel. A separate * tier from `--lr-overlay-shadow-anchored`, so raising popups never raises dialogs. * @status stable * @since 4.0.0 */ export declare class LyraDialog extends LyraElement{static styles:import("lit").CSSResultGroup[];private _open; /** * Whether the dialog is open. Assigning it runs the full `lr-show`/`lr-hide` lifecycle, so it * stays in sync with `show()`/`hide()`/`close()` and can be vetoed the same way. Markup that * renders open from the start emits nothing. * @default false */ get open():boolean;set open(next:boolean); /** Visible mapped title. The richer `label` slot wins when both are supplied. */ label:string; /** Semantic level of the generated visible title. Use `none` for visual-only text. A direct * light-DOM heading retains its own native/ARIA level; invalid untyped values use level 3. */ headingLevel:LyraHeadingLevel; /** Legacy visible title fallback. The richer `label` slot and mapped `label` property win. Has * no effect when a direct light-DOM heading already supplies custom title chrome. */ heading?:string; /** Renders a built-in close (X) button in the header row (creating one, * with no heading text, if `label` and `heading` are unset), wired to the same * `close()` path Escape/backdrop-dismiss already use, with reason * `'close-button'`. */ closable:boolean; /** Suppresses the header row entirely, whatever `heading`, `closable`, the `label` slot or the * `header-actions` slot would otherwise render. For a dialog that owns its own chrome. This is * Web Awesome's spelling (`wa-dialog`'s `without-header`); `noHeader` below is Shoelace's. Both * are current upstream names, both are read, and neither is deprecated. */ withoutHeader:boolean; /** Shoelace's spelling (`sl-dialog`'s `no-header`) for suppressing the header row, read alongside * Web Awesome's `withoutHeader` above so a consumer arriving from either upstream finds their * own attribute working. Neither is deprecated. */ noHeader:boolean; /** SSR hint that keeps the footer wrapper rendered before slot assignment is observable. */ withFooter:boolean; /** Visual width tier for the panel, on the library's shared six-step size ladder. `'m'` (the * default) is this component's pre-existing behaviour, unchanged: an unset panel still caps at * `--lr-dialog-max-width`'s literal `32rem` default. Every other tier scales that same cap, from * a compact `20rem` at `2xs` up to a roomy `48rem` at `xl`; an explicit `--lr-dialog-width` or * `--lr-dialog-max-width` override still wins over any tier. */ size:LyraSize; /** Explicit accessible-only panel name. Unlike `label`, it never renders visible text. */ accessibleLabel:string; /** Host-level `aria-label` override for the panel's accessible name — wins by attribute * presence, including an explicitly empty value, over every other naming source (a slotted * heading, the `label` slot, `heading`, the `label` property) without suppressing visible * heading chrome, matching ``'s `accessibleLabel` pattern. See the class doc for * the full precedence order. Set as a plain `aria-label` attribute on `` itself, not * a public JS property. */ private hostAriaLabel; /** Dismisses the dialog on a backdrop click. Opt-in and `false` by default, matching * `wa-dialog`. This was previously spelled `no-light-dismiss` — an opt-*out* whose default left * backdrop dismissal on, so a mechanical `wa-dialog` → `lr-dialog` rename silently flipped the * behaviour of every migrated dialog. A rename that changes what the markup does with nothing * to warn on is worse than no rename at all, so the polarity now matches upstream exactly. */ lightDismiss:boolean;private hasFooterSlot;private hasLabelSlot;private hasHeaderActionsSlot;private headingText?;private overlay?; /** Set by `deactivateOverlay()` when a close defers releasing the scroll lock. Flushed once the * exit animation actually finishes (`settleTransition()`'s `'lr-after-hide'` branch), or right * away on disconnect/reopen, since nothing is left to visually protect in either case. */ private pendingScrollLockRelease?;private headingObserver?;private headingObserverDocument?;private headingObserverGeneration; /** Invalidates any in-flight `lr-after-show`/`lr-after-hide` wait, so a lifecycle interrupted by * the opposite transition (or by a disconnect) never announces a completion that never * happened. */ private transitionToken; /** Target currently in its cancelable lifecycle preflight. Writes from a listener are captured * here so same-target requests coalesce and an opposite request supersedes the outer commit. */ private openRequestTarget?;private openRequestDuringPreflight?;private transitionAnimations;private initialFocusDecision?;private readonly headingId;private externalModalDepth; /** Shoelace-compatible modal controller. External activation suspends this dialog's focus/Escape * ownership without changing its logical `open` state; deactivation restores it. */ modal:LyraDialogModalController; /** Drawer overrides this for its nonmodal `contained` mode. */ protected get modalSurface():boolean;protected willUpdate(changed:PropertyValues):void; /** Releases a scroll lock held past its close so a component's own exit animation can finish * first. Safe to call unconditionally -- a no-op once already flushed or when nothing is * pending. */ private flushPendingScrollLockRelease;protected updated(changed:PropertyValues):void;connectedCallback():void;disconnectedCallback():void;adoptedCallback():void;private armHeadingObserver;private resetHeadingObserver; /** Whether an external-removal hide request can preserve open state for a later reconnect. */ protected get disconnectHideCancelable():boolean;private onDefaultSlotChange;private onFooterSlotChange;private detectLightDomChrome; /** * Open the dialog. Emits `lr-show` first — a listener calling `preventDefault()` leaves the * dialog closed and the `open` attribute untouched — then `lr-after-show` once the enter * animation has finished. */ show():Promise; /** * Close the dialog with reason `'api'`. Identical to `close()`; it exists so every Lyra overlay * exposes the same `show()`/`hide()`/`open` surface. */ hide():Promise; /** * Close the dialog and return focus to whatever had it before the dialog * opened. `reason` is forwarded as the `lr-close` detail -- * built-in triggers pass `'escape'`/`'backdrop'`/`'close-button'`; a * consumer's own close affordance (e.g. a footer Cancel button) should * call this directly with its own reason string, so every dismissal path * funnels through the same event instead of the consumer having to also * toggle `open` itself. `lr-hide` is emitted first and vetoing it stops * `lr-close` from being emitted at all. */ close(reason?:DialogCloseReason):Promise;private closeFrom;private coalesceOpenRequest;private beginOpenRequest;private openRequestWasSuperseded;private finishOpenRequest;private applyOpenState; /** A vetoed transition must leave the reflected attribute agreeing with the property. Lit only * reflects properties it saw change, and an attribute a consumer wrote by hand (or a Lit * `?open=` binding wrote) is already on the element by the time the veto is known. */ private syncOpenAttribute;protected panelAnimationName(showing:boolean):string;protected overlayAnimationName(showing:boolean):string;protected panelAnimationSpec(showing:boolean):RegisteredAnimationSpec;protected overlayAnimationSpec(showing:boolean):RegisteredAnimationSpec;private cancelTransitionAnimations; /** Resolves once the registry-backed panel/backdrop animation has finished, then emits the * matching `lr-after-*` event. A `null` registration intentionally skips native motion but * retains the same event and promise lifecycle. */ private settleTransition; /** * Promotes the host into the browser top layer for as long as it is open, so a consumer's * stacking context (a `transform`ed ancestor, an `isolation: isolate` wrapper, a * `z-index: 2147483647` header) cannot render on top of a modal dialog — which no `z-index` * value can prevent on its own. `manual` rather than `auto`: light dismiss and Escape are this * component's own contract, routed through the shared overlay manager so only the topmost * dialog reacts, and an `auto` popover would close on the user agent's terms instead. The * `z-index` in the stylesheet remains as the fallback for a user agent without popover support. */ protected enterTopLayer():void;protected leaveTopLayer():void;private isTopLayer;private onBackdropClick;private onCloseButtonClick;private requestClose;protected focusInitial():void;protected activateOverlay():void;protected deactivateOverlay(options?:OverlayDeactivateOptions):(()=>void)|undefined;render():TemplateResult;}declare global{interface HTMLElementTagNameMap{'lr-dialog':LyraDialog;}}