import * as i0 from '@angular/core'; import { InjectionToken, Signal, Type, Injector, Provider } from '@angular/core'; import { ModalSurfaceBase, OverlayRef, OverlayManagerEntry, OverlayManagerCore } from 'forty-cdk/core-overlay'; import * as forty_cdk_dialog from 'forty-cdk/dialog'; import { VetoableEvent, VetoableNativeEvent } from 'forty-cdk/core'; type ForDialogCloseReason = 'escape' | 'backdrop' | 'pointerDownOutside' | 'focusOutside' | 'closeButton' | 'programmatic'; /** * Coordination contract owned by `ForDialog` (declarative) or by the * programmatic `ForDialogManager.open()` machinery. Title / Description register * their generated ids so the dialog wires `aria-labelledby` / * `aria-describedby` reactively. Close button and backdrop request close * via `requestClose` — the implementation decides whether to honor the * request based on `dismissible` and on programmatic semantics. * * The dialog's "openness" isn't part of this contract: the directive is * mounted iff the dialog is open, so descendants don't need an open * signal to coordinate. */ interface ForDialogContext { readonly dismissible: Signal; readonly modal: Signal; readonly alert: Signal; readonly labelledBy: Signal; readonly describedBy: Signal; /** * Portal target shared with the backdrop so both resolve the same * container. `null` ⇒ `document.body`. Set via the dialog's `container` * input; read once per mount. */ readonly container: Signal; registerLabel(id: string): void; unregisterLabel(id: string): void; registerDescription(id: string): void; unregisterDescription(id: string): void; /** * Register the backdrop element so the dismissible layer treats it as * part of the dialog surface (`exemptElements`) — without this, a * `pointerdown` on the portaled backdrop (a body sibling of the dialog * host, outside `host.contains()`) fires `pointerDownOutside` and closes * with reason `'pointerDownOutside'`, then the backdrop's own `click` * emits a second `(dismiss)` with reason `'backdrop'` — a double dismiss * with the wrong first reason, and a veto on either channel fails to stop * the other. Exempting the backdrop routes the interaction solely through * the backdrop's `click` → `requestClose('backdrop')`. Pass `null` to * unregister. */ registerBackdrop(el: HTMLElement | null): void; /** * Request that the dialog close. Reasons: * - `'escape'` / `'backdrop'` / `'pointerDownOutside'` / `'focusOutside'`: * honored only when `dismissible()` is true. * - `'closeButton'`: always honored. * - `'programmatic'`: always honored, used by `ForDialogManager.open()` consumers * that drive close imperatively from a child component. * * `value` is the close result, propagated to `ForDialogRef.close(value)` * in programmatic mode. Ignored in declarative mode. */ requestClose(reason: ForDialogCloseReason, value?: unknown): void; } declare const FOR_DIALOG_CONTEXT: InjectionToken; /** * Headless implementation of the [WAI-ARIA Modal Dialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/). * * Apply `[forDialog]` on the dialog box itself — not on a wrapper. The * directive moves the host to `document.body` (portal), traps focus, locks * body scroll, and listens for Escape while mounted. `aria-labelledby` * and `aria-describedby` wire automatically via `[forDialogTitle]` / * `[forDialogDescription]`; pass `ariaLabel` instead if you don't render * a visible title. * * Mount/unmount is the consumer's responsibility — the directive does * not manage `[hidden]`. Wrap with `@if (open())` and let * `animate.enter` / `animate.leave` handle transitions: * * ```html * @if (dialogOpen()) { *
*

Confirm

* *
* } * ``` * * For programmatic use (open arbitrary components imperatively), see * `ForDialogManager.open()`. * * `data-state` is a static `"open"`: because mount is the consumer's * responsibility (the host only exists inside `@if (open())`), the element is * present iff the dialog is open, so the attribute can never be `"closed"`. * This is a deliberate choice: rather than keeping the node mounted and * flipping `data-state="closed"` to drive an exit transition, exit styling * is the consumer's `animate.leave` (see the usage example above), not a * `data-state="closed"` selector — so a `[data-state="closed"]` rule would * never match and is not a bug. */ declare class ForDialog extends ModalSurfaceBase implements ForDialogContext { #private; /** * When true (default), Escape, backdrop click, pointer-down outside, and * focus outside emit `(dismiss)`. Disable for critical confirm flows that * must be answered explicitly via `[forDialogClose]`. */ readonly dismissible: i0.InputSignalWithTransform; /** * When true (default), sets `aria-modal="true"`, locks body scroll, and * traps focus. Set to `false` for non-modal popups (rare for dialogs). */ readonly modal: i0.InputSignalWithTransform; /** When true (default), focus returns to the previously focused element on close. */ readonly returnFocus: i0.InputSignalWithTransform; /** * Where to send focus on mount. `'first'` (default) finds the first * focusable descendant; `'container'` focuses the dialog box itself * (useful when there's nothing focusable inside). */ readonly initialFocus: i0.InputSignal<"first" | "container">; protected readonly entryPoint = "dialog"; constructor(); static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * Button that toggles the dialog when clicked. Apply on a focusable element — * preferably a ` * @if (dialogOpen()) { *
* } * ``` */ declare class ForDialogTrigger { #private; protected readonly buttonType: i0.Signal; /** * Two-way bindable. Bind to the same signal that gates the surrounding * `@if` around `[forDialog]`. The `model()` change emitter (`(openChange)`) * fires only on internal transitions (trigger click), never on consumer * writes via `[(open)]`. */ readonly open: i0.ModelSignal; /** * Id of the controlled dialog box. Mirrored to `aria-controls` while the * dialog is open. The consumer is responsible for setting the same `id` on * `[forDialog]`. Has no effect on focus or behavior — purely the * accessibility relationship between trigger and box. Leaving it unset when * the dialog opens drops `aria-controls` silently; a dev-mode warning fires * so the missing linkage is visible during development. */ readonly controls: i0.InputSignal; /** * When true, click is ignored and the host reflects `data-disabled=""` plus * the native `disabled` attribute so the trigger is announced as disabled by * assistive tech and dropped from the tab order. The native attribute is the * single reflection channel — no `aria-disabled` is emitted, because on a * real single-purpose `