import * as _angular_core from '@angular/core'; import { InjectionToken, Signal, Type, Injector, Provider } from '@angular/core'; import { ForDrawerSide, ModalSurfaceBase, OverlayRef, OverlayManagerEntry, OverlayManagerCore } from 'forty-cdk/core-overlay'; export { ForDrawerSide } from 'forty-cdk/core-overlay'; import * as forty_cdk_drawer from 'forty-cdk/drawer'; import { VetoableEvent, VetoableNativeEvent } from 'forty-cdk/core'; /** * A snap point. Three accepted shapes: * * - `number ∈ [0, 1]` — fraction of the dimension along the dismissal axis. * - `'NN%'` — equivalent to a fraction, e.g. `'50%' === 0.5`. * - `'NNpx'` — absolute pixel size measured from the anchored edge. */ type ForDrawerSnapPoint = number | `${number}%` | `${number}px`; /** * Reasons emitted via the `(dismiss)` output. A single drawer instance can * cycle through any of these — the consumer typically just flips its * `@if`-gating signal off, but may choose to skip the unmount on specific * reasons (e.g. ignore `'pointerDownOutside'` for a sticky drawer). */ type ForDrawerCloseReason = 'escape' | 'backdrop' | 'pointerDownOutside' | 'focusOutside' | 'closeButton' | 'swipe' | 'programmatic'; /** * Coordination contract owned by `ForDrawer` (declarative) or by the * `ForDrawerManager.open()` machinery (programmatic). Title / Description * register their generated ids so the drawer wires `aria-labelledby` / * `aria-describedby` reactively. Backdrop, Close button and Handle hook * into the same surface to request close / register themselves. * * The drawer's "openness" isn't part of this contract: the directive is * mounted iff the drawer is open, so descendants don't need an open * signal to coordinate. */ interface ForDrawerContext { readonly dismissible: Signal; readonly modal: Signal; readonly alert: Signal; readonly side: Signal; readonly activeSnapPoint: Signal; /** * Whether the backdrop should reflect `data-fade-from-active`. True * when `fadeFromIndex` is set and the active snap point is at or past * that index. Computed by the root. */ readonly fadeFromActive: Signal; /** * `true` while a pointer drag gesture is in flight. Mirrors the host's * `data-dragging` attribute so pieces portaled away from the surface * (the backdrop) can suppress their own transitions during the gesture. */ readonly dragging: Signal; /** * Progress of the current swipe *toward the anchored edge* (dismiss * direction), as a fraction `∈ [0, 1]` of the drawer's dimension along * the dismissal axis. `0` at rest and while growing away from the edge * (with snap points). The backdrop publishes this as the * `--for-drawer-swipe-progress` custom property so consumers can fade it * out as the surface is swiped off-screen — `opacity: calc(1 - var(--for-drawer-swipe-progress))`. */ readonly swipeProgress: 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 drawer's `container` * input; read once per mount. */ readonly container: Signal; /** * Host element of the drawer surface. Exposed so a nested child can * register its parent topology with `ForDrawerStack` without piercing * Angular DI to fetch the parent's `ElementRef`. Read-only — pieces * never mutate the host directly. */ readonly hostElement: HTMLElement; registerLabel(id: string): void; unregisterLabel(id: string): void; registerDescription(id: string): void; unregisterDescription(id: string): void; /** * Register the visual handle element so that `handleOnly === true` * gates the swipe gesture to gestures starting on this element. Pass * `null` to unregister. */ registerHandle(el: HTMLElement | null): void; /** * Register the backdrop element so the dismissible layer treats it as * part of the drawer surface (`exemptElements`) — without this, a * `pointerdown` on the portaled backdrop would fire `pointerDownOutside` * before the backdrop's `click` handler runs, so the consumer would see * close-reason `'pointerDownOutside'` instead of `'backdrop'` (WebKit * was the first to surface this; Chromium happened to dispatch the * events in an order that masked it). Pass `null` to unregister. */ registerBackdrop(el: HTMLElement | null): void; /** * Request that the drawer close. Reasons: * - `'escape'` / `'backdrop'` / `'pointerDownOutside'` / `'focusOutside'` / * `'swipe'`: honored only when `dismissible()` is true. * - `'closeButton'`: always honored. * - `'programmatic'`: always honored, used by `ForDrawerManager.open()` * consumers that drive close imperatively from a child component. * * `value` is the close result, propagated to `ForDrawerRef.close(value)` * in programmatic mode. Ignored in declarative mode. */ requestClose(reason: ForDrawerCloseReason, value?: unknown): void; } declare const FOR_DRAWER_CONTEXT: InjectionToken; /** * Swipe gesture payloads. `ForDrawerSwipeEvent` is surfaced through * `(swipeStart)` / `(swipeMove)` / `(swipeCancel)`; `ForDrawerSwipeEndEvent` * through `(swipeEnd)`. They let consumers drive bespoke visualizations * (e.g. a separate "scaled background" effect, a debug HUD); the directive * itself owns transform application and snap resolution. */ interface ForDrawerSwipeEvent { /** * Progress of the gesture toward the anchored edge (dismiss direction), a * unitless fraction `∈ [0, 1]` of the drawer's dimension along the * dismissal axis. `0` on arm and while growing away from the edge (with * snap points). */ readonly progress: number; readonly originalEvent: PointerEvent; } interface ForDrawerSwipeEndEvent { readonly willClose: boolean; readonly nextSnapPoint: ForDrawerSnapPoint | null; readonly originalEvent: PointerEvent; } /** * Headless implementation of the [WAI-ARIA Modal Dialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/), * specialised as a side / bottom-sheet drawer with optional swipe-to-dismiss * and snap points. * * Apply `[forDrawer]` on the drawer surface itself — not on a wrapper. The * directive moves the host to `document.body` (portal), traps focus, locks * body scroll, listens for Escape, and (when `swipeToDismiss` is on) attaches * pointer-based swipe handlers that translate the surface and resolve to the * nearest snap point or a dismiss on release. `aria-labelledby` and * `aria-describedby` wire automatically via `[forDrawerTitle]` / * `[forDrawerDescription]`; 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. * * For programmatic use (open arbitrary components imperatively, manage * lifecycle externally), see `ForDrawerManager.open()`. */ declare class ForDrawer extends ModalSurfaceBase implements ForDrawerContext { #private; protected readonly entryPoint = "drawer"; /** * Edge the drawer is anchored to. Default `'bottom'` — the most common * mobile-first pattern. The keyboard navigation axis (for swipe direction) * derives from this, as does the `data-side` attribute on the host. */ readonly side: _angular_core.InputSignal; /** * When true (default), Escape, backdrop click, pointer-down outside, * focus outside, and a swipe past the close threshold all emit `(dismiss)`. * Disable for confirm flows that must be answered explicitly. */ readonly dismissible: _angular_core.InputSignalWithTransform; /** * When true (default), sets `aria-modal="true"`, locks body scroll, traps * focus, and inerts body siblings. Set to `false` for a non-modal * navigation drawer that coexists with the rest of the page. */ readonly modal: _angular_core.InputSignalWithTransform; /** When true (default), focus returns to the previously focused element on close. */ readonly returnFocus: _angular_core.InputSignalWithTransform; /** * Where to send focus on mount. `'first'` (default) finds the first * focusable descendant; `'container'` focuses the drawer surface itself * (useful when there's nothing focusable inside). */ readonly initialFocus: _angular_core.InputSignal<"first" | "container">; /** When true (default), swipe toward the anchored edge dismisses past `closeThreshold`. */ readonly swipeToDismiss: _angular_core.InputSignalWithTransform; /** * Fraction past which a release dismisses instead of snapping back. * Default `0.25`. Without `snapPoints` it is a fraction of the * full drawer dimension along the dismissal axis (dragged > 25% of the * surface size toward the edge dismisses); with `snapPoints` it is a * fraction of the **lowest snap's** extent, so a small "peek" snap stays * dismissible without dragging it entirely off-screen. */ readonly closeThreshold: _angular_core.InputSignal; /** * When true, the swipe gesture only arms on a pointerdown that started on * the registered `[forDrawerHandle]` element. Useful when the surface * contains scrollable content that should keep its scroll gesture. */ readonly handleOnly: _angular_core.InputSignalWithTransform; /** * When true, asks the registered `[forDrawerWrapper]` to scale and * translate behind this drawer (the "scale background" effect). No * effect under `prefers-reduced-motion: reduce`, and a no-op if no * wrapper is mounted. Default `false` so existing consumers are * untouched. */ readonly scaleBackground: _angular_core.InputSignalWithTransform; /** * When true (default) and `scaleBackground` is active, paints * `` with `scaleBackgroundColor` so the gap between the scaled * wrapper and the viewport edge does not show through. Only applies * when `scaleBackground` is `true`. */ readonly setBackgroundColorOnScale: _angular_core.InputSignalWithTransform; /** * Snap points: each entry is a `number ∈ [0, 1]`, * a `'NN%'` string, or a `'NNpx'` string. Strictly increasing * (closest-to-edge first). The surface settles at the nearest snap on * release; dragging past the lowest snap by `closeThreshold` of that * snap's own extent dismisses. */ readonly snapPoints: _angular_core.InputSignal; /** * Active snap point. Two-way bindable: write via `[(activeSnapPoint)]` * to drive the surface programmatically, or just read for analytics. * Initialised to `snapPoints?.[0]` on mount when the consumer left it * `null`. The implicit `(activeSnapPointChange)` emitter fires on * internal transitions (mount-time default and drag release), and * stays silent on consumer writes through `[(activeSnapPoint)]`. */ readonly activeSnapPoint: _angular_core.ModelSignal; /** * First index of `snapPoints` from which the backdrop should reflect * `data-fade-from-active`. Consumers tie a CSS opacity transition to * that attribute. Out-of-range values throw on mount. */ readonly fadeFromIndex: _angular_core.InputSignal; /** Fired once on the pointer move that arms the swipe gesture. `progress` is `0`. */ readonly swipeStart: _angular_core.OutputEmitterRef; /** Fired on every pointer move while the swipe is active. `progress` ∈ `[0, 1]` toward the anchored edge. */ readonly swipeMove: _angular_core.OutputEmitterRef; /** Fired on pointer-up. The directive has already applied `activeSnapPoint` / requested close. */ readonly swipeEnd: _angular_core.OutputEmitterRef; /** * Fired on `pointercancel` or a mid-gesture direction abort; the surface * springs back to `activeSnapPoint` and no close is requested. */ readonly swipeCancel: _angular_core.OutputEmitterRef; readonly activeSnapPointAttr: _angular_core.Signal; readonly fadeFromActive: _angular_core.Signal; /** * `true` while a pointer drag gesture is in flight. Mirrors the host's * `data-dragging` attribute; surfaced through `ForDrawerContext` so pieces * portaled away from the surface (the backdrop) can suppress their own * transitions during the gesture. */ readonly dragging: _angular_core.Signal; /** * Progress of the current swipe toward the anchored edge, `∈ [0, 1]`. * Surfaced through `ForDrawerContext` so the backdrop can publish it as the * `--for-drawer-swipe-progress` custom property. */ readonly swipeProgress: _angular_core.Signal; /** * Live swipe displacement along the x axis in CSS px, published on the host * as the `--for-drawer-swipe-movement-x` custom property by the gesture * engine. `0` at rest, and always `0` when the drawer is anchored to a * horizontal edge (`side` `'top'` / `'bottom'`). * * Custom properties are used — rather than the directive writing `translate` * / `transform` directly — because `transform` is reserved for * `ForDrawerScaleCoordinator` and a directly-written inline `translate` is * dropped by Angular when the consumer also binds a template `[style.*]` on * the same host. Compose them on the surface with * `translate: var(--for-drawer-swipe-movement-x, 0px) var(--for-drawer-swipe-movement-y, 0px)`. * The write rides the same change-detection pass as the `data-dragging` / * `data-active-snap-point` changes on release, so the consumer's * `transition: translate` animates back in lockstep with the snap transition. */ readonly swipeMovementX: _angular_core.Signal; /** * Live swipe displacement along the y axis in CSS px — twin of * {@link swipeMovementX}, non-zero only for `side` `'top'` / `'bottom'`. */ readonly swipeMovementY: _angular_core.Signal; /** Host element of this drawer surface — exposed via `ForDrawerContext`. */ get hostElement(): HTMLElement; readonly depthAttr: _angular_core.Signal; /** * `true` while at least one descendant `[forDrawer]` is registered with * `ForDrawerStack` underneath this one — reflected as the presence-only * `data-state-nested` attribute. The actual nested-visual transform * (`scale + translate3d`) on the parent surface is owned by * `ForDrawerScaleCoordinator`, which subscribes to the same stack * signal and applies the inline `style.transform` once per affected * host. The check is one-level (direct child) because the visual * contract only cares about whether *some* child is currently covering * this drawer; deeper descendants cascade naturally through their own * ancestor chain. */ readonly hasChild: _angular_core.Signal; /** * Reflected as `data-scale-background` on the host: `true` when the * directive opted into the effect AND the coordinator is currently * applying it (wrapper registered, not under reduced-motion). Lets * consumers style the drawer differently in scale mode (e.g. larger * corner radii) without polling the coordinator. */ readonly scaleBackgroundActive: _angular_core.Signal; constructor(); registerHandle(el: HTMLElement | null): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * Button that toggles the drawer when clicked. Apply on a focusable element — * preferably a ` * @if (drawerOpen()) { *
* } * ``` */ declare class ForDrawerTrigger { #private; protected readonly buttonType: _angular_core.Signal; /** * Two-way bindable. Bind to the same signal that gates the surrounding * `@if` around `[forDrawer]`. The `model()` change emitter * (`(openChange)`) fires only on internal transitions (trigger click). */ readonly open: _angular_core.ModelSignal; /** * Id of the controlled drawer surface. Mirrored to `aria-controls` while * the drawer is open. The consumer is responsible for setting the same * `id` on `[forDrawer]`. */ readonly controls: _angular_core.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 `