/**
 * Local mirrors of `motion-utils`'s `Axis` / `Box` / `AxisDelta` /
 * `Delta` types. Inlined because `motion-utils` is a runtime-only
 * transitive dep through `motion-dom` — the runtime helpers
 * (`calcBoxDelta`, `createDelta`, `isDeltaZero`) are re-exported, but
 * the type aliases are not. Same approach we use in
 * `src/lib/components/Reorder/context.ts`.
 *
 * Values match upstream byte-for-byte so handoff between our types and
 * the runtime helpers from motion-dom is implicit.
 */
export interface Axis {
    min: number;
    max: number;
}
export interface Box {
    x: Axis;
    y: Axis;
}
export interface AxisDelta {
    translate: number;
    scale: number;
    origin: number;
    originPoint: number;
}
export interface Delta {
    x: AxisDelta;
    y: AxisDelta;
}
/**
 * Event names the projection node fans out. Mirrors framer-motion's
 * `LayoutEvents` subset that's actually consumed externally.
 *
 * - `willUpdate` — fires inside `willUpdate()`, AFTER the pre-mutation
 *   snapshot has been captured. Receives the snapshot Box.
 * - `didUpdate` — fires inside `didUpdate()`, AFTER the post-mutation
 *   re-measure. Receives the full `LayoutUpdateData` payload (layout,
 *   snapshot, delta, hasLayoutChanged).
 * - `measure` — fires every time `measure()` returns a non-null Box.
 *   Useful for debug overlays and follow-up event consumers.
 */
export type ProjectionEventName = 'willUpdate' | 'didUpdate' | 'measure';
/**
 * Payload delivered to `didUpdate` listeners.
 *
 * `layout` is the post-mutation measurement; `snapshot` is the
 * pre-mutation one. `delta` is `calcBoxDelta(snapshot, layout)` and is
 * the value drag-listeners apply via `originPoint += delta.translate`
 * + `motionValue.set(motionValue.get() + delta.translate)` to keep a
 * dragged element under the cursor while its slot moves.
 *
 * `hasLayoutChanged` is `!isDeltaZero(delta)`. `isDeltaZero` (from
 * motion-dom) treats an axis as unchanged only when its translate is
 * within ±0.01px and its scale within ±0.0001 of identity — a tight
 * floating-point epsilon, NOT a 1px rounding threshold. A genuine
 * sub-pixel layout shift (say 0.4px) is therefore reported as a change.
 */
export interface ProjectionDidUpdateData {
    layout: Box;
    snapshot: Box;
    delta: Delta;
    hasLayoutChanged: boolean;
}
type Listener<E extends ProjectionEventName> = E extends 'didUpdate' ? (data: ProjectionDidUpdateData) => void : E extends 'willUpdate' ? (snapshot: Box) => void : (layout: Box) => void;
/**
 * Options passed at `ProjectionNode` construction time. All optional —
 * a node with no options still works as a leaf measurement target.
 */
export interface ProjectionNodeOptions {
    /**
     * Parent node in the projection tree. Wire-up is callsite-driven
     * (the consumer reads `getProjectionParent()` from the Svelte
     * context system and passes the result here); the node stores it
     * as `this.parent` and registers self in `parent.children` on
     * `mount()`.
     */
    parent?: ProjectionNode | null;
    /**
     * Thunk returning the `layoutScroll` ancestor chain at measure
     * time. Used as the second argument to `measureRect`, which
     * shifts the returned rect by the viewport scroll plus the sum of
     * ancestor `scrollLeft`/`scrollTop` so FLIP deltas stay correct
     * when the page or scrollable ancestors scroll between two measurements.
     *
     * Returning `[]` (or omitting the option entirely) gives
     * viewport-relative measurements — fine for the common case.
     */
    getScrollContainers?: () => HTMLElement[];
    /**
     * Thunk returning the element's USER-authored `transform` — the
     * value `measure()` resets to while reading, so the motion-applied
     * portion (`initial`/`animate`/FLIP/drag) is stripped but the user's
     * own transform is preserved.
     *
     * Preferred over the mount-time `baseTransform` capture, because at
     * mount the inline `style.transform` already carries any
     * transform-type `initial` keyframe (it is serialized inline before
     * effects run). The consumer therefore sources this from the `style`
     * prop instead (see `extractTransform`). When omitted, the node
     * falls back to the mount-captured `baseTransform`.
     */
    getBaseTransform?: () => string;
}
/**
 * Per-element node in the projection tree. Created at component setup
 * time in `_MotionContainer.svelte`, mounted when the element ref
 * binds, unmounted on cleanup.
 *
 * Lifecycle:
 * 1. `new ProjectionNode({ parent, getScrollContainers })` at setup.
 * 2. `node.mount(element)` once the element ref binds.
 * 3. `node.willUpdate()` before any layout-mutating state change (e.g.
 *    a `values` reassign that reorders DOM children).
 * 4. State mutates → Svelte commits the DOM update.
 * 5. `node.didUpdate()` after the DOM update is flushed — fires
 *    `didUpdate` listeners with the snapshot→current delta.
 * 6. `node.unmount()` on cleanup.
 */
export declare class ProjectionNode {
    /** The mounted element. `null` until `mount()` runs. */
    element: HTMLElement | null;
    /**
     * Parent node in the projection tree. Captured at construction
     * from the Svelte context. Set to `null` for root-level motion
     * elements that have no motion ancestor.
     */
    parent: ProjectionNode | null;
    /**
     * Descendant nodes registered via `mount()`. Iterated when we
     * need to broadcast to the subtree (none in this PR; reserved
     * for follow-up work).
     */
    readonly children: Set<ProjectionNode>;
    /** Most-recent post-mutation measurement, or `null` before first measure. */
    latestLayout: Box | null;
    /**
     * Pre-mutation snapshot captured by `willUpdate`. Cleared by
     * `didUpdate` after the delta has been computed. Idempotent for
     * repeat `willUpdate` calls in the same frame — only the first
     * snapshots; subsequent calls no-op so a parent broadcasting
     * `willUpdate` to its children doesn't clobber a child's own
     * earlier snapshot.
     */
    snapshot: Box | null;
    /** Whether `mount()` has been called and `unmount()` has not. */
    isMounted: boolean;
    /**
     * Fallback user-authored base transform, captured from
     * `element.style.transform` at `mount()` time. Used only when no
     * `getBaseTransform` thunk was provided (e.g. unit tests that
     * construct a bare node and set the transform before mounting).
     *
     * For real `motion.*` elements the `getBaseTransform` thunk is
     * preferred: capturing at mount is unsafe because a transform-type
     * `initial` keyframe is serialized into the inline `style.transform`
     * BEFORE effects run, so the mount-time value can be a motion
     * transform rather than the user's. `resolveBaseTransform()` picks
     * the thunk first.
     *
     * `measure()` resets ancestors (and self, via `measureRect`) to this
     * base rather than to `'none'`, removing the motion-applied portion
     * while leaving the user-authored part intact — the same distinction
     * framer-motion draws by only subtracting motion-tracked
     * `latestValues` in `removeBoxTransforms`.
     */
    baseTransform: string;
    private readonly listeners;
    private readonly getScrollContainers;
    private readonly getBaseTransform;
    constructor(options?: ProjectionNodeOptions);
    /**
     * The transform `measure()` resets this node's element to while
     * reading. Prefers the `getBaseTransform` thunk (the user's authored
     * `style` transform, motion-independent); falls back to the
     * mount-captured `baseTransform`. See `getBaseTransform` /
     * `baseTransform` for why the thunk is the safe source.
     */
    private resolveBaseTransform;
    /**
     * Register this node with its parent + bind to a DOM element.
     * Idempotent — calling `mount()` twice on the same element is a
     * no-op for the registration steps.
     *
     * Re-mounting onto a DIFFERENT element swaps the element in place
     * WITHOUT a full `unmount()`. A full unmount would `children.clear()`,
     * orphaning still-mounted descendants that registered themselves in
     * this node's `children` (they keep their `parent` pointer but the
     * set would never be repopulated). Listeners and children are
     * therefore preserved across an element swap.
     *
     * @param element The DOM element this node represents.
     */
    mount(element: HTMLElement): void;
    /**
     * Tear down. Detaches from parent, clears children references,
     * drops all listeners. Safe to call on a never-mounted node and
     * safe to call twice.
     */
    unmount(): void;
    /**
     * Read the element's layout box with every ancestor's
     * motion-applied transform temporarily removed, while preserving
     * each ancestor's user-authored base transform.
     *
     * Mechanism:
     * 1. Walk `this.parent` chain bottom-up, collecting every
     *    mounted ancestor node (excludes self — `measureRect`
     *    handles self's transform internally).
     * 2. Snapshot each ancestor's current `el.style.transform`.
     * 3. Set each to its node's resolved base transform (the
     *    user-authored value, via `resolveBaseTransform`). This strips
     *    any FLIP/drag/initial transform while keeping the user's static
     *    one — see `getBaseTransform` / `baseTransform`.
     * 4. Delegate to `measureRect(self.element, scrollContainers,
     *    self base)`, which applies self's base transform inside its own
     *    try/finally and returns the scroll-compensated DOMRect.
     * 5. Restore ancestor transforms in reverse order inside a
     *    `finally` block — guarantees restoration even if measure
     *    throws.
     * 6. Convert DOMRect → Box and cache as `latestLayout`.
     *
     * Returns `null` when `element` is not mounted.
     */
    measure(): Box | null;
    /**
     * Snapshot the current layout box for use by the next
     * `didUpdate()`. Caller's contract: invoke this BEFORE the
     * layout-mutating state change so the snapshot reflects the
     * pre-mutation position.
     *
     * Idempotent within a frame — once a snapshot exists, subsequent
     * `willUpdate()` calls are no-ops until `didUpdate()` consumes it.
     * This means a parent that broadcasts `willUpdate` to its
     * children before its own snapshot is fine: children snapshot
     * themselves first via their own willUpdate, parent's broadcast
     * is a no-op.
     */
    willUpdate(): void;
    /**
     * Re-measure post-mutation, compute the delta against the
     * snapshot, fire `didUpdate` listeners. No-op when there's no
     * snapshot (matches upstream — `willUpdate` MUST precede
     * `didUpdate` for the cycle to fire).
     *
     * Always clears the snapshot at the end so the next gesture's
     * `willUpdate`/`didUpdate` cycle starts fresh.
     */
    didUpdate(): void;
    /**
     * Observer-driven layout-change commit. Unlike the explicit
     * `willUpdate()` → mutate → `didUpdate()` cycle (used when a
     * consumer controls the exact mutation moment, e.g. Reorder.Group
     * before a `values` reassign), this is for the reactive path where
     * a layout change has ALREADY happened and we only learn about it
     * after the fact (the existing `observeLayoutChanges` FLIP loop in
     * `_MotionContainer`).
     *
     * Uses the cached `latestLayout` (the pre-change position from
     * mount or the previous commit) as the snapshot, re-measures the
     * post-change position, and fires `didUpdate` with the delta.
     *
     * First call after mount just seeds `latestLayout` (no prior
     * position to diff against) and fires nothing.
     *
     * Returns the freshly-measured `Box` (or `null` when unmounted) so
     * the caller can reuse it — the FLIP loop in `_MotionContainer` uses
     * this as its `next` rect instead of measuring a second time per
     * frame.
     *
     * The `didUpdate` fan-out is gated on a non-zero delta. The FLIP
     * animation this commit runs alongside writes its own inverse
     * `transform` to the element every frame, and those writes re-trigger
     * the same `observeLayoutChanges` signal that drives this method.
     * Those re-fires carry no real layout change (the ancestor-stripped
     * measure is identical to the previous one), so without the
     * `isDeltaZero` gate every animation frame would fan out a `delta: 0`
     * event and clobber the genuine delta from the originating change.
     */
    commitLayoutChange(): Box | null;
    /**
     * Subscribe to a projection event. Returns an unsubscribe
     * function. Safe to call after `unmount()` (becomes a no-op).
     */
    addEventListener<E extends ProjectionEventName>(name: E, cb: Listener<E>): () => void;
    private notify;
}
export {};
