/**
 * Reactive primitives — signal / computed / createEffect / batch, plus an
 * ownership layer (createRoot / onCleanup / getOwner / runWithOwner) and untrack.
 *
 * Design reference: SwiftUI @Observable + Solid.js fine-grained reactivity.
 *
 *   View = f(State)
 *   signal      — reactive source (@State)
 *   computed    — derived, LAZY + memoized (SwiftUI computed property / Solid memo)
 *   createEffect— side effect that re-runs when its reads change (≈ body)
 *   ownership   — effects/memos form an owner tree; disposing a scope disposes
 *                 everything created under it (critical for MPA: tear down a page
 *                 and every effect it spawned is cleaned up in one call).
 *
 * Model (push-pull scheduling + lazy memos):
 *   - Reading a source inside a computation links them both ways.
 *   - Writing a signal marks direct observers DIRTY and their transitive memo
 *     observers CHECK ("maybe dirty"), scheduling any dependent effects. Effects
 *     flush once (deduped — diamond dependencies run an effect a single time).
 *   - Memos recompute lazily on read, and only re-notify their observers when
 *     their derived value actually changes (via `equals`). A CHECK computation
 *     first pulls its sources up to date; if none changed value, it is skipped —
 *     so a memo whose output is stable never wakes the effects behind it.
 *   - Every computation is owned; re-running or disposing it first disposes its
 *     owned children and runs its cleanups (no leaked nested effects).
 */
export type Getter<T> = () => T;
export type Setter<T> = (value: T | ((prev: T) => T)) => void;
export interface SignalOptions<T> {
    /** Custom equality. Defaults to Object.is. Return true to skip the update. */
    equals?: (prev: T, next: T) => boolean;
}
/** Anything a computation can subscribe to (a signal, or a memo). */
interface SourceLike {
    observers: Set<Computation>;
}
/** Staleness of a computation. CLEAN → up to date; CHECK → a memo source may
 *  have changed (verify before recomputing); DIRTY → definitely recompute. */
declare const CLEAN = 0;
declare const CHECK = 1;
declare const DIRTY = 2;
type State = typeof CLEAN | typeof CHECK | typeof DIRTY;
/** An effect or a memo — a node that runs a function and tracks its reads. */
interface Computation extends Owner {
    fn: () => unknown;
    /** Sources (signals / memos) read during the last run. */
    sources: Set<SourceLike>;
    isEffect: boolean;
    running: boolean;
    disposed: boolean;
    state: State;
    observers: Set<Computation>;
    value: unknown;
    equals: (a: unknown, b: unknown) => boolean;
}
/** A node that can own child computations + cleanups (effect, memo, or root). */
export interface Owner {
    owned: Computation[];
    cleanups: Array<() => void>;
    owner: Owner | null;
}
/**
 * Create a reactive value. Returns a `[getter, setter]` tuple.
 *
 *   const [count, setCount] = signal(0);
 *   count();               // read — auto-tracked inside computed / createEffect
 *   setCount(1);           // write — notifies dependents; skipped if unchanged
 *   setCount((n) => n + 1) // updater form
 */
export declare function signal<T>(initial: T, options?: SignalOptions<T>): [Getter<T>, Setter<T>];
/**
 * Derived, read-only, LAZY + memoized value. Recomputes only when read after a
 * dependency changed; unread memos never recompute. When a recompute produces an
 * equal value (default `Object.is`, override via `options.equals`) the memo does
 * NOT notify its observers — so effects behind a value-stable memo stay asleep.
 * Owned by the current scope, so it is disposed when that scope is.
 *
 *   const fullName = computed(() => `${first()} ${last()}`);
 *   fullName(); // computes on first read, caches until a dep's value changes
 */
export declare function computed<T>(fn: () => T, options?: SignalOptions<T>): Getter<T>;
/**
 * Run `fn` immediately, then re-run it whenever a signal/memo it read changes.
 * Owned by the current scope. `fn` may return a cleanup, called before each
 * re-run and on dispose. Returns a dispose function.
 *
 *   const dispose = createEffect(() => {
 *     el.textContent = `Count: ${count()}`;
 *     return () => {}; // optional cleanup
 *   });
 */
export declare function createEffect(fn: () => void | (() => void)): () => void;
/**
 * Coalesce multiple writes into one flush. Effects run once after `fn` returns,
 * deduplicated. Nested batches are absorbed by the outermost one.
 */
export declare function batch(fn: () => void): void;
/** Read signals without subscribing the current computation to them. */
export declare function untrack<T>(fn: () => T): T;
/**
 * Create a disposable reactive scope. Effects/memos created inside are owned by
 * it; calling the passed `dispose` tears them all down. Use one per page/route
 * in an MPA/SPA so navigating away cleans up every effect that page spawned.
 *
 *   const dispose = createRoot((dispose) => { renderPage(); return dispose; });
 *   // ...later, on navigation:
 *   dispose();
 */
export declare function createRoot<T>(fn: (dispose: () => void) => T): T;
/** Register a cleanup on the current scope, run when it re-runs or is disposed. */
export declare function onCleanup(fn: () => void): void;
/** The current owner scope (for advanced integrations, e.g. a router). */
export declare function getOwner(): Owner | null;
/** Run `fn` under a specific owner scope (pairs with getOwner). */
export declare function runWithOwner<T>(owner: Owner | null, fn: () => T): T;
export {};
