/* Excluded from this release type: ArraySet */

/**
 * An Atom is a signal that can be updated directly by calling {@link Atom.set} or {@link Atom.update}.
 *
 * Atoms are created using the {@link atom} function.
 *
 * @example
 * ```ts
 * const name = atom('name', 'John')
 *
 * print(name.get()) // 'John'
 * ```
 *
 * @public
 */
export declare interface Atom<Value, Diff = unknown> extends Signal<Value, Diff> {
    /**
     * Sets the value of this atom to the given value. If the value is the same as the current value, this is a no-op.
     *
     * @param value - The new value to set.
     * @param diff - The diff to use for the update. If not provided, the diff will be computed using {@link AtomOptions.computeDiff}.
     */
    set(value: Value, diff?: Diff): Value;
    /**
     * Updates the value of this atom using the given updater function. If the returned value is the same as the current value, this is a no-op.
     *
     * @param updater - A function that takes the current value and returns the new value.
     */
    update(updater: (value: Value) => Value): Value;
}

/**
 * Creates a new {@link Atom}.
 *
 * An Atom is a signal that can be updated directly by calling {@link Atom.set} or {@link Atom.update}.
 *
 * @example
 * ```ts
 * const name = atom('name', 'John')
 *
 * name.get() // 'John'
 *
 * name.set('Jane')
 *
 * name.get() // 'Jane'
 * ```
 *
 * @public
 */
export declare function atom<Value, Diff = unknown>(
/**
 * A name for the signal. This is used for debugging and profiling purposes, it does not need to be unique.
 */
name: string, 
/**
 * The initial value of the signal.
 */
initialValue: Value, 
/**
 * The options to configure the atom. See {@link AtomOptions}.
 */
options?: AtomOptions<Value, Diff>): Atom<Value, Diff>;

/**
 * The options to configure an atom, passed into the {@link atom} function.
 * @public
 */
export declare interface AtomOptions<Value, Diff> {
    /**
     * The maximum number of diffs to keep in the history buffer.
     *
     * If you don't need to compute diffs, or if you will supply diffs manually via {@link Atom.set}, you can leave this as `undefined` and no history buffer will be created.
     *
     * If you expect the value to be part of an active effect subscription all the time, and to not change multiple times inside of a single transaction, you can set this to a relatively low number (e.g. 10).
     *
     * Otherwise, set this to a higher number based on your usage pattern and memory constraints.
     *
     */
    historyLength?: number;
    /**
     * A method used to compute a diff between the atom's old and new values. If provided, it will not be used unless you also specify {@link AtomOptions.historyLength}.
     */
    computeDiff?: ComputeDiff<Value, Diff>;
    /**
     * If provided, this will be used to compare the old and new values of the atom to determine if the value has changed.
     * By default, values are compared using first using strict equality (`===`), then `Object.is`, and finally any `.equals` method present in the object's prototype chain.
     * @param a - The old value
     * @param b - The new value
     * @returns True if the values are equal, false otherwise.
     */
    isEqual?(a: any, b: any): boolean;
}

/* Excluded from this release type: Child */

/**
 * A computed signal created via the `computed` function or `@computed` decorator.
 * Computed signals derive their values from other signals and automatically update when their dependencies change.
 * They use lazy evaluation, only recalculating when accessed and dependencies have changed.
 *
 * @example
 * ```ts
 * const firstName = atom('firstName', 'John')
 * const lastName = atom('lastName', 'Doe')
 * const fullName = computed('fullName', () => `${firstName.get()} ${lastName.get()}`)
 *
 * console.log(fullName.get()) // "John Doe"
 * firstName.set('Jane')
 * console.log(fullName.get()) // "Jane Doe"
 * ```
 *
 * @public
 */
export declare interface Computed<Value, Diff = unknown> extends Signal<Value, Diff> {
    /**
     * Whether this computed signal is involved in an actively-running effect graph.
     * Returns true if there are any reactions or other computed signals depending on this one.
     * @public
     */
    readonly isActivelyListening: boolean;
    /* Excluded from this release type: parentSet */
    /* Excluded from this release type: parents */
    /* Excluded from this release type: parentEpochs */
}

/**
 * Creates a computed signal that derives its value from other signals.
 * Computed signals automatically update when their dependencies change and use lazy evaluation
 * for optimal performance.
 *
 * @example
 * ```ts
 * const name = atom('name', 'John')
 * const greeting = computed('greeting', () => `Hello ${name.get()}!`)
 * console.log(greeting.get()) // 'Hello John!'
 * ```
 *
 * `computed` may also be used as a decorator for creating computed getter methods.
 *
 * @example
 * ```ts
 * class Counter {
 *   max = 100
 *   count = atom<number>(0)
 *
 *   @computed getRemaining() {
 *     return this.max - this.count.get()
 *   }
 * }
 * ```
 *
 * You may optionally pass in a {@link ComputedOptions} when used as a decorator:
 *
 * @example
 * ```ts
 * class Counter {
 *   max = 100
 *   count = atom<number>(0)
 *
 *   @computed({isEqual: (a, b) => a === b})
 *   getRemaining() {
 *     return this.max - this.count.get()
 *   }
 * }
 * ```
 *
 * @param name - The name of the signal for debugging purposes
 * @param compute - The function that computes the value of the signal. Receives the previous value and last computed epoch
 * @param options - Optional configuration for the computed signal
 * @returns A new computed signal
 * @public
 */
export declare function computed<Value, Diff = unknown>(name: string, compute: (previousValue: typeof UNINITIALIZED | Value, lastComputedEpoch: number) => Value | WithDiff<Value, Diff>, options?: ComputedOptions<Value, Diff>): Computed<Value, Diff>;

/**
 * TC39 decorator for creating computed methods in classes.
 *
 * @example
 * ```ts
 * class MyClass {
 *   value = atom('value', 10)
 *
 *   @computed
 *   doubled() {
 *     return this.value.get() * 2
 *   }
 * }
 * ```
 *
 * @param compute - The method to be decorated
 * @param context - The decorator context provided by TypeScript
 * @returns The decorated method
 * @public
 */
export declare function computed<This extends object, Value>(compute: () => Value, context: ClassMethodDecoratorContext<This, () => Value>): () => Value;

/**
 * Legacy TypeScript decorator for creating computed methods in classes.
 *
 * @example
 * ```ts
 * class MyClass {
 *   value = atom('value', 10)
 *
 *   @computed
 *   doubled() {
 *     return this.value.get() * 2
 *   }
 * }
 * ```
 *
 * @param target - The class prototype
 * @param key - The property key
 * @param descriptor - The property descriptor
 * @returns The modified property descriptor
 * @public
 */
export declare function computed(target: any, key: string, descriptor: PropertyDescriptor): PropertyDescriptor;

/**
 * Decorator factory for creating computed methods with options.
 *
 * @example
 * ```ts
 * class MyClass {
 *   items = atom('items', [1, 2, 3])
 *
 *   @computed({ historyLength: 10 })
 *   sum() {
 *     return this.items.get().reduce((a, b) => a + b, 0)
 *   }
 * }
 * ```
 *
 * @param options - Configuration options for the computed signal
 * @returns A decorator function that can be applied to methods
 * @public
 */
export declare function computed<Value, Diff = unknown>(options?: ComputedOptions<Value, Diff>): ((target: any, key: string, descriptor: PropertyDescriptor) => PropertyDescriptor) & (<This>(compute: () => Value, context: ClassMethodDecoratorContext<This, () => Value>) => () => Value);

/**
 * A function type that computes the difference between two values of a signal.
 *
 * This function is used to generate incremental diffs that can be applied to
 * reconstruct state changes over time. It's particularly useful for features
 * like undo/redo, synchronization, and change tracking.
 *
 * The function should analyze the previous and current values and return a
 * diff object that represents the change. If the diff cannot be computed
 * (e.g., the values are too different or incompatible), it should return
 * the unique symbol RESET_VALUE to indicate that a full state reset is required.
 *
 * @param previousValue - The previous value of the signal
 * @param currentValue - The current value of the signal
 * @param lastComputedEpoch - The epoch when the previous value was set
 * @param currentEpoch - The epoch when the current value was set
 * @returns A diff object representing the change, or the unique symbol RESET_VALUE if no diff can be computed
 *
 * @example
 * ```ts
 * import { atom, RESET_VALUE } from '@tldraw/state'
 *
 * // Simple numeric diff
 * const numberDiff: ComputeDiff<number, number> = (prev, curr) => curr - prev
 *
 * // Array diff with reset fallback
 * const arrayDiff: ComputeDiff<string[], { added: string[], removed: string[] }> = (prev, curr) => {
 *   if (prev.length > 1000 || curr.length > 1000) {
 *     return RESET_VALUE // Too complex, force reset
 *   }
 *   return {
 *     added: curr.filter(item => !prev.includes(item)),
 *     removed: prev.filter(item => !curr.includes(item))
 *   }
 * }
 *
 * const count = atom('count', 0, { computeDiff: numberDiff })
 * ```
 *
 * @public
 */
export declare type ComputeDiff<Value, Diff> = (previousValue: Value, currentValue: Value, lastComputedEpoch: number, currentEpoch: number) => Diff | RESET_VALUE;

/**
 * Options for configuring computed signals. Used when calling `computed` or using the `@computed` decorator.
 *
 * @example
 * ```ts
 * const greeting = computed('greeting', () => `Hello ${name.get()}!`, {
 *   historyLength: 10,
 *   isEqual: (a, b) => a === b,
 *   computeDiff: (oldVal, newVal) => ({ type: 'change', from: oldVal, to: newVal })
 * })
 * ```
 *
 * @public
 */
export declare interface ComputedOptions<Value, Diff> {
    /**
     * The maximum number of diffs to keep in the history buffer.
     *
     * If you don't need to compute diffs, or if you will supply diffs manually via {@link Atom.set}, you can leave this as `undefined` and no history buffer will be created.
     *
     * If you expect the value to be part of an active effect subscription all the time, and to not change multiple times inside of a single transaction, you can set this to a relatively low number (e.g. 10).
     *
     * Otherwise, set this to a higher number based on your usage pattern and memory constraints.
     *
     */
    historyLength?: number;
    /**
     * A method used to compute a diff between the computed's old and new values. If provided, it will not be used unless you also specify {@link ComputedOptions.historyLength}.
     */
    computeDiff?: ComputeDiff<Value, Diff>;
    /**
     * If provided, this will be used to compare the old and new values of the computed to determine if the value has changed.
     * By default, values are compared using first using strict equality (`===`), then `Object.is`, and finally any `.equals` method present in the object's prototype chain.
     * @param a - The old value
     * @param b - The new value
     * @returns True if the values are equal, false otherwise.
     */
    isEqual?(a: any, b: any): boolean;
}

/* Excluded from this release type: deferAsyncEffects */

/**
 * An EffectScheduler is responsible for executing side effects in response to changes in state.
 *
 * You probably don't need to use this directly unless you're integrating this library with a framework of some kind.
 *
 * Instead, use the {@link react} and {@link reactor} functions.
 *
 * @example
 * ```ts
 * const render = new EffectScheduler('render', drawToCanvas)
 *
 * render.attach()
 * render.execute()
 * ```
 *
 * @public
 */
export declare const EffectScheduler: new <Result>(name: string, runEffect: (lastReactedEpoch: number) => Result, options?: EffectSchedulerOptions | undefined) => EffectScheduler<Result>;

/** @public */
export declare interface EffectScheduler<Result> {
    /**
     * Whether this scheduler is attached and actively listening to its parents.
     * @public
     */
    readonly isActivelyListening: boolean;
    /* Excluded from this release type: lastTraversedEpoch */
    /** @public */
    readonly name: string;
    /* Excluded from this release type: __debug_ancestor_epochs__ */
    /**
     * The number of times this effect has been scheduled.
     * @public
     */
    readonly scheduleCount: number;
    /* Excluded from this release type: parentSet */
    /* Excluded from this release type: parentEpochs */
    /* Excluded from this release type: parents */
    /* Excluded from this release type: maybeScheduleEffect */
    /* Excluded from this release type: scheduleEffect */
    /* Excluded from this release type: maybeExecute */
    /**
     * Makes this scheduler become 'actively listening' to its parents.
     * If it has been executed before it will immediately become eligible to receive 'maybeScheduleEffect' calls.
     * If it has not executed before it will need to be manually executed once to become eligible for scheduling, i.e. by calling `EffectScheduler.execute`.
     * @public
     */
    attach(): void;
    /**
     * Makes this scheduler stop 'actively listening' to its parents.
     * It will no longer be eligible to receive 'maybeScheduleEffect' calls until `EffectScheduler.attach` is called again.
     * @public
     */
    detach(): void;
    /**
     * Executes the effect immediately and returns the result.
     * @returns The result of the effect.
     * @public
     */
    execute(): Result;
}

/** @public */
export declare interface EffectSchedulerOptions {
    /**
     * scheduleEffect is a function that will be called when the effect is scheduled.
     *
     * It can be used to defer running effects until a later time, for example to batch them together with requestAnimationFrame.
     *
     *
     * @example
     * ```ts
     * let isRafScheduled = false
     * const scheduledEffects: Array<() => void> = []
     * const scheduleEffect = (runEffect: () => void) => {
     * 	scheduledEffects.push(runEffect)
     * 	if (!isRafScheduled) {
     * 		isRafScheduled = true
     * 		requestAnimationFrame(() => {
     * 			isRafScheduled = false
     * 			scheduledEffects.forEach((runEffect) => runEffect())
     * 			scheduledEffects.length = 0
     * 		})
     * 	}
     * }
     * const stop = react('set page title', () => {
     * 	document.title = doc.title,
     * }, scheduleEffect)
     * ```
     *
     * @param execute - A function that will execute the effect.
     * @returns void
     */
    scheduleEffect?: (execute: () => void) => void;
}

/**
 * @public
 */
export declare const EMPTY_ARRAY: [];

/**
 * Retrieves the underlying computed instance for a given property created with the `computed`
 * decorator.
 *
 * @example
 * ```ts
 * class Counter {
 *   max = 100
 *   count = atom(0)
 *
 *   @computed getRemaining() {
 *     return this.max - this.count.get()
 *   }
 * }
 *
 * const c = new Counter()
 * const remaining = getComputedInstance(c, 'getRemaining')
 * remaining.get() === 100 // true
 * c.count.set(13)
 * remaining.get() === 87 // true
 * ```
 *
 * @param obj - The object
 * @param propertyName - The property name
 * @public
 */
export declare function getComputedInstance<Obj extends object, Prop extends keyof Obj>(obj: Obj, propertyName: Prop): Computed<Obj[Prop]>;

/**
 * Returns true if the given value is an {@link Atom}.
 *
 * @param value - The value to check
 * @returns True if the value is an Atom, false otherwise
 * @example
 * ```ts
 * const myAtom = atom('test', 42)
 * const notAtom = 'hello'
 *
 * console.log(isAtom(myAtom)) // true
 * console.log(isAtom(notAtom)) // false
 * ```
 * @public
 */
export declare function isAtom(value: unknown): value is Atom<unknown>;

/**
 * Type guard function that determines whether a value is a signal (either an Atom or Computed).
 *
 * This utility function is helpful when working with mixed data types and you need to
 * differentiate between regular values and reactive signal containers. It returns `true`
 * if the provided value is either an atomic signal created with `atom()` or a computed
 * signal created with `computed()`.
 *
 * @param value - The value to check, can be of any type
 * @returns `true` if the value is a Signal (Atom or Computed), `false` otherwise
 *
 * @example
 * ```ts
 * import { atom, computed, isSignal } from '@tldraw/state'
 *
 * const count = atom('count', 5)
 * const doubled = computed('doubled', () => count.get() * 2)
 * const regularValue = 'hello'
 *
 * console.log(isSignal(count))        // true
 * console.log(isSignal(doubled))      // true
 * console.log(isSignal(regularValue)) // false
 * console.log(isSignal(null))         // false
 * ```
 *
 * @public
 */
export declare function isSignal(value: any): value is Signal<any>;

/**
 * Call this inside a computed signal function to determine whether it is the first time the function is being called.
 *
 * Mainly useful for incremental signal computation.
 *
 * @example
 * ```ts
 * const count = atom('count', 0)
 * const double = computed('double', (prevValue) => {
 *   if (isUninitialized(prevValue)) {
 *     print('First time!')
 *   }
 *   return count.get() * 2
 * })
 * ```
 *
 * @param value - The value to check.
 * @public
 */
export declare function isUninitialized(value: any): value is UNINITIALIZED;

/**
 * Creates a new {@link Atom} that persists its value to localStorage.
 *
 * The atom is automatically synced with localStorage - changes to the atom are saved to localStorage,
 * and the initial value is read from localStorage if it exists. Returns both the atom and a cleanup
 * function that should be called to stop syncing when the atom is no longer needed. If you need to delete
 * the atom, you should do it manually after all cleanup functions have been called.
 *
 * @example
 * ```ts
 * const [theme, cleanup] = localStorageAtom('theme', 'light')
 *
 * theme.get() // 'light' or value from localStorage if it exists
 *
 * theme.set('dark') // updates atom and saves to localStorage
 *
 * // When done:
 * cleanup() // stops syncing to localStorage
 * ```
 *
 * @param name - The localStorage key and atom name. This is used for both localStorage persistence
 *   and debugging/profiling purposes.
 * @param initialValue - The initial value of the atom, used if no value exists in localStorage.
 * @param options - Optional atom configuration. See {@link AtomOptions}.
 * @returns A tuple containing the atom and a cleanup function to stop localStorage syncing.
 * @public
 */
export declare function localStorageAtom<Value, Diff = unknown>(name: string, initialValue: Value, options?: AtomOptions<Value, Diff>): [Atom<Value, Diff>, () => void];

/**
 * Starts a new effect scheduler, scheduling the effect immediately.
 *
 * Returns a function that can be called to stop the scheduler.
 *
 * @example
 * ```ts
 * const color = atom('color', 'red')
 * const stop = react('set style', () => {
 *   divElem.style.color = color.get()
 * })
 * color.set('blue')
 * // divElem.style.color === 'blue'
 * stop()
 * color.set('green')
 * // divElem.style.color === 'blue'
 * ```
 *
 *
 * Also useful in React applications for running effects outside of the render cycle.
 *
 * @example
 * ```ts
 * useEffect(() => react('set style', () => {
 *   divRef.current.style.color = color.get()
 * }), [])
 * ```
 *
 * @public
 */
export declare function react(name: string, fn: (lastReactedEpoch: number) => any, options?: EffectSchedulerOptions): () => void;

/**
 * The reactor is a user-friendly interface for starting and stopping an `EffectScheduler`.
 *
 * Calling `.start()` will attach the scheduler and execute the effect immediately the first time it is called.
 *
 * If the reactor is stopped, calling `.start()` will re-attach the scheduler but will only execute the effect if any of its parents have changed since it was stopped.
 *
 * You can create a reactor with {@link reactor}.
 * @public
 */
export declare interface Reactor<T = unknown> {
    /**
     * The underlying effect scheduler.
     * @public
     */
    scheduler: EffectScheduler<T>;
    /**
     * Start the scheduler. The first time this is called the effect will be scheduled immediately.
     *
     * If the reactor is stopped, calling this will start the scheduler again but will only execute the effect if any of its parents have changed since it was stopped.
     *
     * If you need to force re-execution of the effect, pass `{ force: true }`.
     * @public
     */
    start(options?: {
        force?: boolean;
    }): void;
    /**
     * Stop the scheduler.
     * @public
     */
    stop(): void;
}

/**
 * Creates a {@link Reactor}, which is a thin wrapper around an `EffectScheduler`.
 *
 * @public
 */
export declare function reactor<Result>(name: string, fn: (lastReactedEpoch: number) => Result, options?: EffectSchedulerOptions): Reactor<Result>;

/**
 * A unique symbol used to indicate that a signal's value should be reset or that
 * there is insufficient history to compute diffs between epochs.
 *
 * This value is returned by {@link Signal.getDiffSince} when the requested epoch
 * is too far in the past and the diff sequence cannot be reconstructed.
 *
 * @example
 * ```ts
 * import { atom, getGlobalEpoch, RESET_VALUE } from '@tldraw/state'
 *
 * const count = atom('count', 0, { historyLength: 3 })
 * const oldEpoch = getGlobalEpoch()
 *
 * // Make many changes that exceed history length
 * count.set(1)
 * count.set(2)
 * count.set(3)
 * count.set(4)
 *
 * const diffs = count.getDiffSince(oldEpoch)
 * if (diffs === RESET_VALUE) {
 *   console.log('Too many changes, need to reset state')
 * }
 * ```
 *
 * @public
 */
export declare const RESET_VALUE: unique symbol;

/**
 * Type representing the the unique symbol RESET_VALUE symbol, used in type annotations
 * to indicate when a signal value should be reset or when diff computation
 * cannot proceed due to insufficient history.
 *
 * @public
 */
export declare type RESET_VALUE = typeof RESET_VALUE;

/**
 * A reactive value container that can change over time and track diffs between sequential values.
 *
 * Signals are the foundation of the \@tldraw/state reactive system. They automatically manage
 * dependencies and trigger updates when their values change. Any computed signal or effect
 * that reads from this signal will be automatically recomputed when the signal's value changes.
 *
 * There are two types of signal:
 * - **Atomic signals** - Created using `atom()`. These are mutable containers that can be
 *   directly updated using `set()` or `update()` methods.
 * - **Computed signals** - Created using `computed()`. These derive their values from other
 *   signals and are automatically recomputed when dependencies change.
 *
 * @example
 * ```ts
 * import { atom, computed } from '@tldraw/state'
 *
 * // Create an atomic signal
 * const count = atom('count', 0)
 *
 * // Create a computed signal that derives from the atom
 * const doubled = computed('doubled', () => count.get() * 2)
 *
 * console.log(doubled.get()) // 0
 * count.set(5)
 * console.log(doubled.get()) // 10
 * ```
 *
 * @public
 */
export declare interface Signal<Value, Diff = unknown> {
    /**
     * A human-readable identifier for this signal, used primarily for debugging and performance profiling.
     *
     * The name is displayed in debug output from {@link whyAmIRunning} and other diagnostic tools.
     * It does not need to be globally unique within your application.
     */
    name: string;
    /**
     * Gets the current value of the signal and establishes a dependency relationship.
     *
     * When called from within a computed signal or effect, this signal will be automatically
     * tracked as a dependency. If this signal's value changes, any dependent computations
     * or effects will be marked for re-execution.
     *
     * @returns The current value stored in the signal
     */
    get(): Value;
    /**
     * The global epoch number when this signal's value last changed.
     *
     * Note that this represents when the value actually changed, not when it was last computed.
     * A computed signal may recalculate and produce the same value without changing its epoch.
     * This is used internally for dependency tracking and history management.
     */
    lastChangedEpoch: number;
    /**
     * Gets the sequence of diffs that occurred between a specific epoch and the current state.
     *
     * This method enables incremental synchronization by providing a list of changes that
     * have occurred since a specific point in time. If the requested epoch is too far in
     * the past or the signal doesn't have enough history, it returns the unique symbol RESET_VALUE
     * to indicate that a full state reset is required.
     *
     * @param epoch - The epoch timestamp to get diffs since
     * @returns An array of diff objects representing changes since the epoch, or the unique symbol RESET_VALUE if insufficient history is available
     */
    getDiffSince(epoch: number): Diff[] | RESET_VALUE;
    /**
     * Gets the current value of the signal without establishing a dependency relationship.
     *
     * This method bypasses the automatic dependency tracking system, making it useful for
     * performance-critical code paths where the overhead of dependency capture would be
     * problematic. Use with caution as it breaks the reactive guarantees of the system.
     *
     * **Warning**: This method should only be used when you're certain that you don't need
     * the calling context to react to changes in this signal.
     *
     * @param ignoreErrors - Whether to suppress errors during value retrieval (optional)
     * @returns The current value without establishing dependencies
     */
    __unsafe__getWithoutCapture(ignoreErrors?: boolean): Value;
    /* Excluded from this release type: children */
}

/**
 * Like {@link transaction}, but does not create a new transaction if there is already one in progress.
 * This is the preferred way to batch state updates when you don't need the rollback functionality.
 *
 * @example
 * ```ts
 * const count = atom('count', 0)
 * const doubled = atom('doubled', 0)
 *
 * react('update doubled', () => {
 *   console.log(`Count: ${count.get()}, Doubled: ${doubled.get()}`)
 * })
 *
 * // This batches both updates into a single reaction
 * transact(() => {
 *   count.set(5)
 *   doubled.set(count.get() * 2)
 * })
 * // Logs: "Count: 5, Doubled: 10"
 * ```
 *
 * @param fn - The function to run in a transaction
 * @returns The return value of the function
 * @public
 */
export declare function transact<T>(fn: () => T): T;

/**
 * Batches state updates, deferring side effects until after the transaction completes.
 * Unlike {@link transact}, this function always creates a new transaction, allowing for nested transactions.
 *
 * @example
 * ```ts
 * const firstName = atom('firstName', 'John')
 * const lastName = atom('lastName', 'Doe')
 *
 * react('greet', () => {
 *   console.log(`Hello, ${firstName.get()} ${lastName.get()}!`)
 * })
 *
 * // Logs "Hello, John Doe!"
 *
 * transaction(() => {
 *  firstName.set('Jane')
 *  lastName.set('Smith')
 * })
 *
 * // Logs "Hello, Jane Smith!"
 * ```
 *
 * If the function throws, the transaction is aborted and any signals that were updated during the transaction revert to their state before the transaction began.
 *
 * @example
 * ```ts
 * const firstName = atom('firstName', 'John')
 * const lastName = atom('lastName', 'Doe')
 *
 * react('greet', () => {
 *   console.log(`Hello, ${firstName.get()} ${lastName.get()}!`)
 * })
 *
 * // Logs "Hello, John Doe!"
 *
 * transaction(() => {
 *  firstName.set('Jane')
 *  throw new Error('oops')
 * })
 *
 * // Does not log
 * // firstName.get() === 'John'
 * ```
 *
 * A `rollback` callback is passed into the function.
 * Calling this will prevent the transaction from committing and will revert any signals that were updated during the transaction to their state before the transaction began.
 *
 * @example
 * ```ts
 * const firstName = atom('firstName', 'John')
 * const lastName = atom('lastName', 'Doe')
 *
 * react('greet', () => {
 *   console.log(`Hello, ${firstName.get()} ${lastName.get()}!`)
 * })
 *
 * // Logs "Hello, John Doe!"
 *
 * transaction((rollback) => {
 *  firstName.set('Jane')
 *  lastName.set('Smith')
 *  rollback()
 * })
 *
 * // Does not log
 * // firstName.get() === 'John'
 * // lastName.get() === 'Doe'
 * ```
 *
 * @param fn - The function to run in a transaction, called with a function to roll back the change.
 * @returns The return value of the function
 * @public
 */
export declare function transaction<T>(fn: (rollback: () => void) => T): T;

/**
 * A special symbol used to indicate that a computed signal has not been initialized yet.
 * This is passed as the `previousValue` parameter to a computed signal function on its first run.
 *
 * @example
 * ```ts
 * const count = atom('count', 0)
 * const double = computed('double', (prevValue) => {
 *   if (isUninitialized(prevValue)) {
 *     console.log('First computation!')
 *   }
 *   return count.get() * 2
 * })
 * ```
 *
 * @public
 */
export declare const UNINITIALIZED: unique symbol;

/**
 * The type of the first value passed to a computed signal function as the 'prevValue' parameter.
 * This type represents the uninitialized state of a computed signal before its first calculation.
 *
 * @see {@link isUninitialized}
 * @public
 */
export declare type UNINITIALIZED = typeof UNINITIALIZED;

/**
 * Executes the given function without capturing any parents in the current capture context.
 *
 * This is mainly useful if you want to run an effect only when certain signals change while also
 * dereferencing other signals which should not cause the effect to rerun on their own.
 *
 * @example
 * ```ts
 * const name = atom('name', 'Sam')
 * const time = atom('time', () => new Date().getTime())
 *
 * setInterval(() => {
 *   time.set(new Date().getTime())
 * })
 *
 * react('log name changes', () => {
 * 	 print(name.get(), 'was changed at', unsafe__withoutCapture(() => time.get()))
 * })
 *
 * ```
 *
 * @public
 */
export declare function unsafe__withoutCapture<T>(fn: () => T): T;

/**
 * A debugging tool that tells you why a computed signal or effect is running.
 * Call in the body of a computed signal or effect function.
 *
 * @example
 * ```ts
 * const name = atom('name', 'Bob')
 * react('greeting', () => {
 * 	whyAmIRunning()
 *	print('Hello', name.get())
 * })
 *
 * name.set('Alice')
 *
 * // 'greeting' is running because:
 * //     'name' changed => 'Alice'
 * ```
 *
 * @public
 */
export declare function whyAmIRunning(): void;

/**
 * A singleton class used to wrap computed signal values along with their diffs.
 * This class is used internally by the {@link withDiff} function to provide both
 * the computed value and its diff to the signal system.
 *
 * @example
 * ```ts
 * const count = atom('count', 0)
 * const double = computed('double', (prevValue) => {
 *   const nextValue = count.get() * 2
 *   if (isUninitialized(prevValue)) {
 *     return nextValue
 *   }
 *   return withDiff(nextValue, nextValue - prevValue)
 * })
 * ```
 *
 * @public
 */
export declare const WithDiff: {
    new <Value, Diff>(value: Value, diff: Diff): {
        diff: Diff;
        value: Value;
    };
};

/**
 * Interface representing a value wrapped with its corresponding diff.
 * Used in incremental computation to provide both the new value and the diff from the previous value.
 *
 * @public
 */
export declare interface WithDiff<Value, Diff> {
    /**
     * The computed value.
     */
    value: Value;
    /**
     * The diff between the previous and current value.
     */
    diff: Diff;
}

/**
 * When writing incrementally-computed signals it is convenient (and usually more performant) to incrementally compute the diff too.
 *
 * You can use this function to wrap the return value of a computed signal function to indicate that the diff should be used instead of calculating a new one with {@link AtomOptions.computeDiff}.
 *
 * @example
 * ```ts
 * const count = atom('count', 0)
 * const double = computed('double', (prevValue) => {
 *   const nextValue = count.get() * 2
 *   if (isUninitialized(prevValue)) {
 *     return nextValue
 *   }
 *   return withDiff(nextValue, nextValue - prevValue)
 * }, { historyLength: 10 })
 * ```
 *
 *
 * @param value - The value.
 * @param diff - The diff.
 * @public
 */
export declare function withDiff<Value, Diff>(value: Value, diff: Diff): WithDiff<Value, Diff>;

export { }
