/**
 * Tween Plugin for ECSpresso
 *
 * Declarative property animation within the ECS. Tween any numeric component
 * field over time with standard easing functions, sequences, and completion events.
 */
import { type BasePluginOptions } from 'ecspresso';
import type { ComponentsOfWorld, AnyECSpresso } from 'ecspresso';
import { type EasingFn } from '../../utils/easing';
/**
 * Data structure published when a tween completes.
 * Use this type when defining tween completion events in your EventTypes interface.
 */
export interface TweenEventData {
    /** The entity ID the tween belongs to */
    entityId: number;
    /** Number of steps in the tween */
    stepCount: number;
}
export interface TweenTarget {
    /** Component name on the entity */
    component: string;
    /** Pre-split field path (e.g., ['position', 'x']) */
    path: readonly string[];
    /** Starting value. null = resolve from current value on first tick */
    from: number | null;
    /** Target value */
    to: number;
}
export interface TweenStep {
    targets: TweenTarget[];
    duration: number;
    easing: EasingFn;
}
export interface Tween {
    steps: TweenStep[];
    currentStep: number;
    elapsed: number;
    loop: LoopMode;
    totalLoops: number;
    completedLoops: number;
    direction: 1 | -1;
    state: 'pending' | 'active' | 'complete';
    onComplete?: (data: TweenEventData) => void;
    justFinished: boolean;
}
export type LoopMode = 'once' | 'loop' | 'yoyo';
/**
 * Component types provided by the tween plugin.
 */
export interface TweenComponentTypes {
    tween: Tween;
}
export interface TweenPluginOptions<G extends string = 'tweens'> extends BasePluginOptions<G> {
}
export interface TweenOptions {
    /** Explicit starting value (default: captures current value on first tick) */
    from?: number;
    /** Easing function (default: linear) */
    easing?: EasingFn;
    /** Loop mode (default: 'once') */
    loop?: LoopMode;
    /** Number of loops. -1 = infinite (default: 1) */
    loops?: number;
    /** Callback invoked when tween completes */
    onComplete?: (data: TweenEventData) => void;
}
/**
 * Create a single-target tween component.
 *
 * @param component Component name on the entity
 * @param field Field path (dot-separated for nested, e.g. 'position.x')
 * @param to Target value
 * @param duration Duration in seconds
 * @param options Optional configuration
 * @returns Component object suitable for spreading into spawn()
 */
export declare function createTween(component: string, field: string, to: number, duration: number, options?: TweenOptions): Pick<TweenComponentTypes, 'tween'>;
export interface TweenSequenceStepInput {
    targets: ReadonlyArray<{
        component: string;
        field: string;
        to: number;
        from?: number;
    }>;
    duration: number;
    easing?: EasingFn;
}
export interface TweenSequenceOptions {
    /** Loop mode (default: 'once') */
    loop?: LoopMode;
    /** Number of loops. -1 = infinite (default: 1) */
    loops?: number;
    /** Callback invoked when tween completes */
    onComplete?: (data: TweenEventData) => void;
}
/**
 * Create a multi-step tween sequence. Each step can have parallel targets.
 *
 * @param steps Array of step definitions
 * @param options Optional configuration
 * @returns Component object suitable for spreading into spawn()
 */
export declare function createTweenSequence(steps: ReadonlyArray<TweenSequenceStepInput>, options?: TweenSequenceOptions): Pick<TweenComponentTypes, 'tween'>;
/**
 * Recursively produce a union of dot-separated paths that resolve to `number`
 * within type T. Depth-limited to 4 levels to prevent TS recursion errors.
 *
 * @example
 * NumericPaths<{ x: number; y: number }> // 'x' | 'y'
 * NumericPaths<{ position: { x: number }; rotation: number }> // 'position.x' | 'rotation'
 */
export type NumericPaths<T, Depth extends readonly unknown[] = []> = Depth['length'] extends 4 ? never : T extends readonly unknown[] ? never : T extends Record<string, unknown> ? {
    [K in keyof T & string]: NonNullable<T[K]> extends number ? K : NonNullable<T[K]> extends readonly unknown[] ? never : NonNullable<T[K]> extends Record<string, unknown> ? `${K}.${NumericPaths<NonNullable<T[K]>, [...Depth, unknown]>}` : never;
}[keyof T & string] : never;
/**
 * Discriminated union over component names: each variant constrains `field`
 * to the numeric paths of that component. TS narrows inline object literals
 * by `component` discriminant — zero runtime overhead.
 */
export type TypedTweenTargetInput<C extends Record<string, any>> = {
    [K in keyof C & string]: {
        component: K;
        field: NumericPaths<C[K]>;
        to: number;
        from?: number;
    };
}[keyof C & string];
export interface TypedTweenSequenceStepInput<C extends Record<string, any>> {
    targets: ReadonlyArray<TypedTweenTargetInput<C>>;
    duration: number;
    easing?: EasingFn;
}
export interface TweenHelpers<W extends AnyECSpresso> {
    createTween: <K extends keyof ComponentsOfWorld<W> & string>(component: K, field: NumericPaths<ComponentsOfWorld<W>[K]>, to: number, duration: number, options?: {
        from?: number;
        easing?: EasingFn;
        loop?: LoopMode;
        loops?: number;
        onComplete?: (data: TweenEventData) => void;
    }) => Pick<TweenComponentTypes, 'tween'>;
    createTweenSequence: (steps: ReadonlyArray<TypedTweenSequenceStepInput<ComponentsOfWorld<W>>>, options?: {
        loop?: LoopMode;
        loops?: number;
        onComplete?: (data: TweenEventData) => void;
    }) => Pick<TweenComponentTypes, 'tween'>;
}
export declare function createTweenHelpers<W extends AnyECSpresso>(_world?: W): TweenHelpers<W>;
/**
 * Create a tween plugin for ECSpresso.
 *
 * This plugin provides:
 * - Tween system that processes all tween components each frame
 * - Support for single-field, multi-target, and multi-step sequences
 * - 31 standard easing functions
 * - Loop modes: once, loop, yoyo
 * - `justFinished` flag for one-frame completion detection
 * - `onComplete` callback on completion
 * - Change detection via markChanged
 */
export declare function createTweenPlugin<G extends string = 'tweens'>(options?: TweenPluginOptions<G>): import("ecspresso").Plugin<import("ecspresso").WithComponents<import("ecspresso").EmptyConfig, TweenComponentTypes>, import("ecspresso").EmptyConfig, "tween-update", G, never, never>;
