/**
 * Pan gesture session.
 *
 * Direct port of framer-motion's `PanSession`
 * (`packages/framer-motion/src/gestures/pan/PanSession.ts`) and `PanGesture`
 * (`packages/framer-motion/src/gestures/pan/index.ts`). Pan is the
 * primitive that powers swipe-to-dismiss drawers, swipe-to-delete rows,
 * carousels, and any gesture that tracks pointer offset/velocity without
 * the constraint/momentum/snap-to-origin baggage of `drag`.
 *
 * Critical design notes (mirrors upstream):
 *
 * - `pointermove`, `pointerup`, `pointercancel` subscribe on the
 *   `contextWindow` (defaults to `window`), NOT the source element. This
 *   keeps the gesture alive even when the pointer leaves the element's
 *   bounds during a fast swipe — the original element is only used for
 *   the initial `pointerdown` and for scroll-compensation tracking.
 *
 * - `distanceThreshold` (default `3`px) gates the `onStart` callback so
 *   a steady press without movement doesn't fire a pan. `onSessionStart`
 *   fires immediately on pointerdown for setup work.
 *
 * - Per-frame throttling via `frame.update(updatePoint, true)` so a flood
 *   of pointermove events doesn't run handlers more than once per render
 *   frame. On top of that, individual handlers are routed onto motion-dom's
 *   step lanes (see `wrapUpdate` / `wrapPostRender` above):
 *   `onSessionStart` / `onStart` / `onMove` land on `update`,
 *   `onEnd` / `onSessionEnd` on `postRender`. Matches upstream's
 *   `asyncHandler` + `frame.postRender` split byte-for-byte.
 *
 * - `getPanInfo` returns `{ point, delta, offset, velocity }` — identical
 *   shape to motion-dom's `DragInfo` / framer-motion's `PanInfo`.
 *
 * - Velocity uses a 100ms history window with the "skip the pointer-down
 *   origin if it's too stale" tweak upstream added for hold-then-flick
 *   gestures.
 */
import type { DragInfo } from '../types';
export interface PanHandlers {
    /** Fires on `pointerdown` regardless of whether movement follows. */
    onSessionStart?: (event: PointerEvent, info: DragInfo) => void;
    /** Fires the first time pointer offset crosses `distanceThreshold`. */
    onStart?: (event: PointerEvent, info: DragInfo) => void;
    /** Fires on every per-frame-throttled pointermove past threshold. */
    onMove?: (event: PointerEvent, info: DragInfo) => void;
    /** Fires on `pointerup` / `pointercancel` if `onStart` ever fired. */
    onEnd?: (event: PointerEvent, info: DragInfo) => void;
    /** Fires on `pointerup` / `pointercancel` always (paired with `onSessionStart`). */
    onSessionEnd?: (event: PointerEvent, info: DragInfo) => void;
}
export interface AttachPanOptions {
    /**
     * Movement distance (in pixels) required before `onStart`/`onMove`
     * fire. Default `3` — same as framer-motion. A steady press with
     * sub-threshold drift is reported via `onSessionStart` / `onSessionEnd`
     * only.
     */
    distanceThreshold?: number;
    /**
     * Window to attach the move/up/cancel listeners to. Defaults to the
     * source element's owner window. Override for iframe / shadow-root
     * scenarios.
     */
    contextWindow?: Window | null;
}
/**
 * Cleanup function returned by `attachPan`. Carries an `update` method
 * that hot-swaps the live handler set without tearing down the active
 * `PanSession` — call this when a consumer's `onPan` reference changes
 * mid-gesture (the canonical Svelte 5 pattern of inline arrow handlers
 * passes a fresh closure every render). Without this, the host
 * `$effect` would have to teardown + re-attach and the user's in-flight
 * pan would silently die.
 */
export type AttachPanCleanup = (() => void) & {
    update: (next: PanHandlers) => void;
};
/**
 * Attach a pan gesture session to `el`. Returns a cleanup function that
 * tears down the pointerdown listener and ends any in-flight session,
 * with a `.update(next)` method for hot-swapping handlers mid-gesture.
 *
 * Internally a fresh `PanSession` spawns on each pointerdown — the
 * outer attachment just keeps the pointerdown listener alive across the
 * element's lifetime.
 *
 * SSR-safe: returns a no-op cleanup if `window` is undefined. The Svelte
 * `$effect` consumer never fires on the server anyway, but defending the
 * boundary lets the module load cleanly in node-only test runners.
 *
 * Lifecycle guarantee: when the returned cleanup runs mid-gesture, the
 * session synthesizes `onEnd` + `onSessionEnd` against the raw handlers
 * BEFORE removing listeners (see `PanSession.dispatchTerminal`). Hosts
 * (e.g. `_MotionContainer`'s pan `$effect`) can put their `whilePan`
 * revert logic inside the user-supplied `onEnd` and rely on it firing
 * exactly once per gesture — whether the user released or the host
 * forced teardown.
 *
 * @param el Target element to bind `pointerdown` on. Move/up/cancel
 *   events are listened for on the element's owning window so a fast
 *   swipe past the element's bounds keeps the gesture alive.
 * @param handlers Pan lifecycle handlers. Any subset of
 *   `onSessionStart` (fires on pointerdown), `onStart` (fires the first
 *   time the cumulative offset crosses `distanceThreshold`), `onMove`
 *   (per-frame-throttled on every pointermove past threshold), `onEnd`
 *   (fires on pointerup/cancel if `onStart` ever fired), `onSessionEnd`
 *   (fires on every pointerup/cancel where a pointermove occurred).
 * @param options Per-session config. `distanceThreshold` (default 3px)
 *   gates the start callback; `contextWindow` overrides the owning
 *   window (use for shadow-root / iframe scenarios).
 * @returns A cleanup function with an attached `.update(next)` method.
 *   Calling the cleanup ends the session + removes the pointerdown
 *   listener. Calling `.update(next)` swaps handlers in place on the
 *   live session without rebuilding it — the canonical Svelte pattern
 *   for inline arrow handlers that change identity each render.
 *
 * @example
 * ```ts
 * const cleanup = attachPan(node, {
 *   onStart: (_event, info) => console.log('start', info.offset),
 *   onMove: (_event, info) => x.set(info.offset.x),
 *   onEnd: (_event, info) => {
 *     if (Math.abs(info.velocity.x) > 600) commit()
 *     else animate(x, 0, { type: 'spring' })
 *   }
 * })
 *
 * // Later, swap handlers without ending the live gesture:
 * cleanup.update({ onMove: (_e, info) => x.set(info.offset.x * 2) })
 *
 * // On unmount:
 * cleanup()
 * ```
 */
export declare const attachPan: (el: HTMLElement, handlers: PanHandlers, options?: AttachPanOptions) => AttachPanCleanup;
