/** Function returned by {@link useCycle} for advancing or jumping the index. */
export type Cycle = (next?: number) => void;
/**
 * State returned by {@link useCycle}: an object with a reactive `.current`
 * getter and a `cycle` function. Both reads and writes flow through the
 * same object, so consumers don't need to destructure (which would
 * snapshot `.current` and lose reactivity under runes).
 */
export type CycleState<T> = {
    readonly current: T;
    cycle: Cycle;
};
/**
 * Function that returns the current items list, used by the reactive
 * overload of {@link useCycle}. The function is re-invoked on every read
 * so changes to the underlying reactive source propagate automatically.
 */
export type CycleItemsGetter<T> = () => readonly T[];
/**
 * Cycles through a series of values. Mirrors framer-motion's `useCycle`.
 *
 * Two call forms:
 *
 * - **Varargs** — `useCycle(...items)` — items are captured once and stay
 *   fixed for the cycle's lifetime. Matches React framer-motion's signature.
 * - **Reactive getter** — `useCycle(() => items)` — items are read on every
 *   access, so passing a `$state`/`$derived` source lets the cycle pick up
 *   list changes without recreating it.
 *
 * In both forms:
 *
 * - `state.current` is reactive — read it in templates / `$derived` / `$effect`
 *   and it tracks both index changes and (in the getter form) item changes.
 * - `state.cycle()` advances to the next item (wrapping at the end).
 * - `state.cycle(i)` jumps to index `i`. The index is stored as-given;
 *   `.current` then clamps on read so any out-of-range index — negative,
 *   overflow, or items shrinking underneath the reactive-getter form —
 *   resolves to the nearest valid edge (`items[0]` or `items[length - 1]`)
 *   instead of `undefined`. This is a defensive divergence from React
 *   framer-motion (which returns `items[i]`, possibly undefined) so the
 *   reactive form stays safe and `.current` always honors its `T` type.
 *   If the reactive getter ever returns an empty list, `.current` throws.
 * - Calls that resolve to the current index are no-ops, matching React
 *   `useState`'s `Object.is` bail-out.
 *
 * Two deliberate divergences from React's `useCycle`:
 *
 * 1. Return shape — React's `[value, cycle]` tuple can't survive
 *    destructuring under Svelte 5 runes (snapshots the value, loses
 *    reactivity), so we return `{ current, cycle }`.
 * 2. Out-of-range reads always clamp (see above) instead of returning
 *    `items[i]` undefined.
 *
 * Otherwise 1:1 with React, including same-index no-op bail-out and
 * the `wrap(0, length, index + 1)` advance semantics.
 *
 * Ambiguity: `useCycle(fn)` with a single function value is treated as the
 * reactive overload, not as a single-item cycle. To cycle through one
 * function value, use `useCycle(() => [fn])` or just call it directly —
 * a single-item cycle is a no-op anyway.
 *
 * @see https://motion.dev/docs/react-use-cycle
 *
 * @example Static varargs
 * ```svelte
 * <script lang="ts">
 *   import { motion, useCycle } from '@humanspeak/svelte-motion'
 *
 *   const x = useCycle(0, 50, 100)
 * </script>
 *
 * <motion.div animate={{ x: x.current }} onclick={() => x.cycle()} />
 * ```
 *
 * @example Reactive items
 * ```svelte
 * <script lang="ts">
 *   let { labels }: { labels: string[] } = $props()
 *   const variant = useCycle(() => labels)
 * </script>
 *
 * <motion.div animate={variant.current} onclick={() => variant.cycle()} />
 * ```
 *
 * @param itemsGetter Function returning the current items list; re-invoked
 *   on every `.current` read so reactive sources propagate. Use this form
 *   when items can change between mount and unmount. (Reactive overload.)
 * @param items One or more values to cycle through. Captured once at call
 *   time and fixed for the cycle's lifetime. (Varargs overload.)
 * @returns A `CycleState<T>` with a reactive `.current` getter and a
 *   `cycle(next?: number)` advance/jump function. `.current` always
 *   honors its `T` type by clamping out-of-range indexes; it throws
 *   if a reactive getter empties the items list mid-cycle.
 *   `.cycle()` throws on non-integer (`NaN`, `1.5`, `Infinity`)
 *   indexes and returns early as a no-op on empty items.
 */
export declare function useCycle<T>(itemsGetter: CycleItemsGetter<T>): CycleState<T>;
export declare function useCycle<T>(...items: T[]): CycleState<T>;
