/**
 * @license
 * Copyright 2026 Kai-Orion & Sandlada
 * SPDX-License-Identifier: MIT
 *
 * @fileoverview
 * ReactiveController that manages an element's show/close animation based on
 * edge-slide (in-flow collapse or floating peek) behavior, with optional
 * scroll-driven auto-show/hide.
 *
 * **Positioning model**:
 * - `floating = false`: The host stays in the document flow; on hide its
 *   height/width animates to `0` (fully removed from layout). No blank gap
 *   is left behind.
 * - `floating = true`: The host floats on the page (`position: fixed` must
 *   be set by the host component). On hide it animates to `peekSize` — a
 *   small sliver remains visible. Mouse hover expands the bar.
 *
 * **Direction mapping** (derived from `placement`):
 * - Vertical placements (`top` / `bottom`):
 *     scroll down → hide, scroll up → show, at top → show.
 * - Horizontal placements (`left` / `right`):
 *     scroll right → hide, scroll left → show, at left → show.
 *
 * **Animation**:
 * The host dimension height/width keyframes are interleaved with the inner
 * container translateX/translateY keyframes. The controller splits them and
 * animates each element independently via the Web Animations API.
 *
 * **Lifecycle** mirrors the FAB/dialog pattern: a `generation` counter
 * invalidates stale async operations, an `isConnectedPromise` defers DOM
 * work until connected, and `open` / `close` events are cancelable (followed
 * by non-cancelable `opened` / `closed`).
 *
 * @example
 * ```ts
 * const slide = new EdgeSlideController(this, {
 *   placement: 'bottom',
 *   floating: true,
 *   autoHide: true,
 *   peekSize: 24,
 * })
 * ```
 */
import { type ReactiveController, type ReactiveControllerHost } from 'lit';
/**
 * The viewport / document edge the host is docked to. The slide-out direction
 * is derived from this value:
 * - `top`    → slides up (out the top)
 * - `bottom` → slides down (out the bottom)
 * - `left`   → slides left (out the left)
 * - `right`  → slides right (out the right)
 */
export type Placement = 'top' | 'bottom' | 'left' | 'right';
export declare const Placement: {
    readonly Top: 'top';
    readonly Bottom: 'bottom';
    readonly Left: 'left';
    readonly Right: 'right';
};
/**
 * Host contract required by {@link EdgeSlideController}.
 *
 * The host must provide a `containerElement` — the inner element whose
 * `transform` is animated during show/close.
 */
export interface IEdgeSlideHost extends ReactiveControllerHost, HTMLElement {
    /** The inner element that is translated during show/close animation. */
    containerElement: HTMLElement | null;
}
/**
 * Configuration options for {@link EdgeSlideController}.
 * All fields are optional — unspecified fields retain their defaults.
 */
export interface EdgeSlideOptions {
    /**
     * When `true` the host is expected to use `position: fixed` and floats
     * above the page content. When hiding it shrinks to `peekSize` (peek
     * mode). Mouse hover expands the bar.
     *
     * When `false` (default) the host stays in the document flow. When hiding
     * it collapses to `0` (full mode).
     */
    floating?: boolean;
    /**
     * The edge the host is docked to. Drives the slide-out / slide-in
     * direction.
     * @default 'bottom'
     */
    placement?: Placement;
    /**
     * When `true` the controller listens to scroll events on the target
     * element (resolved via `scrollElementId`, falling back to `window`) and
     * automatically hides or shows the host based on scroll direction.
     * @default false
     */
    autoHide?: boolean;
    /**
     * The `id` of the scrollable element to observe. When empty or missing,
     * the controller falls back to `window`.
     * @default ''
     */
    scrollElementId?: string;
    /**
     * Visible sliver size in pixels when hidden in `floating` (peek) mode.
     * @default 24
     */
    peekSize?: number;
    /**
     * When `true` the show/close transitions are skipped — the host jumps
     * directly to the target state.
     * @default false
     */
    quick?: boolean;
}
export declare class EdgeSlideController implements ReactiveController {
    private readonly host;
    private _floating;
    private _placement;
    private _autoHide;
    private _scrollElementId;
    private _peekSize;
    private _quick;
    private _isOpen;
    private _isOpening;
    /** Generation counter — incremented before each `show()` / `close()` to
     *  invalidate stale async operations. */
    private generation;
    /** Resolved once in `hostConnected()`, re-created in `hostDisconnected()`. */
    private isConnectedPromiseResolve;
    private isConnectedPromise;
    private animationAbort;
    private hoverTimer;
    private readonly handleMouseEnterBound;
    private readonly handleMouseLeaveBound;
    private scrollTarget;
    private lastScrollTop;
    private lastScrollLeft;
    /** Tracks the last scroll-driven action so we don't repeat it every frame. */
    private lastScrollAction;
    private scrollRafId;
    private readonly handleScrollBound;
    constructor(host: IEdgeSlideHost, options?: EdgeSlideOptions);
    get floating(): boolean;
    set floating(value: boolean);
    get placement(): Placement;
    set placement(value: Placement);
    get autoHide(): boolean;
    set autoHide(value: boolean);
    get scrollElementId(): string;
    set scrollElementId(value: string);
    get peekSize(): number;
    set peekSize(value: number);
    get quick(): boolean;
    set quick(value: boolean);
    /** Whether the host is currently shown. */
    get isOpen(): boolean;
    /** Whether the host is currently animating open. */
    get isOpening(): boolean;
    hostConnected(): void;
    hostDisconnected(): void;
    /**
     * Re-resolve the scroll target and re-attach the listener. Call this when
     * `scrollElementId`, `autoHide`, or `placement` changes externally.
     */
    rebindScroll(): void;
    /**
     * Imperatively show the host (animate in).
     * Fires cancelable `open` → animates → fires `opened`.
     */
    show(): Promise<void>;
    /**
     * Imperatively hide the host (animate out).
     * Fires cancelable `close` → animates → fires `closed`.
     */
    close(): Promise<void>;
    private createConnectedPromise;
    /**
     * Cancel all WAAPI animations on the host and container, and abort any
     * in-flight show/close. Call this before measuring the natural size or
     * starting a new animation cycle so stale `fill:forwards` doesn't
     * interfere with layout measurement or leave a ghost state behind.
     */
    private cleanupAnimations;
    /**
     * Animate the host dimension + inner container translate. Splits the
     * interleaved keyframes array: even-indexed entries → host dimension
     * keyframes, odd-indexed entries → inner container translate keyframes.
     */
    private animateBar;
    /** Build open keyframes: host grows to natural size, inner slides in. */
    private getOpenKeyframes;
    /** Build close keyframes: host shrinks to hidden size, inner slides out. */
    private getCloseKeyframes;
    /** Which host dimension collapses: vertical placements → height, horizontal → width. */
    private collapseAxis;
    /** Which inner translate axis: vertical placements → translateY, horizontal → translateX. */
    private translateAxis;
    /**
     * Natural (shown) host size in px along the collapse axis. Cancels any
     * stale fill:forwards and temporarily clears the inline hidden-size style
     * so the true natural layout size can be read via getBoundingClientRect.
     */
    private naturalSize;
    /**
     * Target host size when hidden:
     * - `floating = true` (peek mode): `peekSize`
     * - `floating = false` (full mode): `0`
     */
    private hiddenSize;
    /**
     * Container translate offset (px) when entering the hidden / peek state
     * (the CLOSE direction). The bar moves from shown (translate=0) toward
     * this offset so the un-docked edge disappears first:
     *
     * Full mode (!floating):
     *   bottom → +natural (down)   → 1→2→3  (top vanishes first)
     *   top    → 0                 → 3→2→1  (host natural clip)
     *   left   → +natural (right)  → c→b→a  (right vanishes first)
     *   right  → -natural (left)   → a→b→c  (left vanishes first)
     *
     * Peek mode (floating, container slides **away** from the anchor so the
     * edge-opposite content stays visible in the clipped host):
     *   bottom → 0                 → shows top part via host clip
     *   top    → -(natural-peek)   → shows bottom part
     *   left   → -(natural-peek)   → shows right part
     *   right  → 0                 → shows left part via host clip
     */
    private closeOffset;
    /**
     * Container translate offset (px) when starting the SHOW animation.
     * The bar animates FROM this offset TO 0 while the host grows.
     *
     * Full mode (!floating) — the container starts on the opposite side of
     * the close direction so it slides **through** the host clip:
     *   bottom → -natural (up)    → slides down into view
     *   top    → 0                → no translation, host just grows
     *   left   → -natural (left)  → slides right into view
     *   right  → +natural (right) → slides left into view
     *
     * Peek mode (floating) — same as `closeOffset` since the container is
     * already at the peek position and animates to 0 during show.
     */
    private openOffset;
    /** Clear inline animation styles once shown (let CSS take over). */
    private applyShownState;
    /** Apply the resting hidden state inline (host sized, inner translated). */
    private applyHiddenState;
    /** Hover shows the full bar (floating / peek mode); mouse leave restores peek. */
    private handleMouseEnter;
    private handleMouseLeave;
    private clearHoverTimer;
    private resolveScrollTarget;
    private recordScrollBaseline;
    private detachScroll;
    private cancelScrollRaf;
    private scheduleScrollCheck;
    private checkScroll;
    private dispatchScrollAction;
    private updateScrollBaseline;
}
//# sourceMappingURL=edge-slide-controller.d.ts.map