UNPKG

@solidjs/signals

Version:

SolidJS' standalone reactivity implementation

193 lines (192 loc) 11 kB
import type { Disposable } from "./core/index.js"; export declare function onCleanup(fn: Disposable): Disposable; export type Accessor<T> = () => T; export declare function accessor<T>(node: any): Accessor<T>; export type Setter<in out T> = { <U extends T>(...args: undefined extends T ? [] : [value: Exclude<U, Function> | ((prev: T) => U)]): undefined extends T ? undefined : U; <U extends T>(value: (prev: T) => U): U; <U extends T>(value: Exclude<U, Function>): U; <U extends T>(value: Exclude<U, Function> | ((prev: T) => U)): U; }; export type Signal<T> = [get: Accessor<T>, set: Setter<T>]; export type ComputeFunction<Prev, Next extends Prev = Prev> = (v: Prev) => PromiseLike<Next> | AsyncIterable<Next> | Next; export type EffectFunction<Prev, Next extends Prev = Prev> = (v: Next, p?: Prev) => (() => void) | void; export type EffectBundle<Prev, Next extends Prev = Prev> = { effect: EffectFunction<Prev, Next>; error: (err: unknown, cleanup: () => void) => void; }; /** Options for effect primitives (`createEffect`, `createRenderEffect`, `createTrackedEffect`, `createReaction`). */ export interface EffectOptions { /** Debug name (dev mode only) */ name?: string; /** When true, defers the initial effect execution until the next change */ defer?: boolean; } /** Options for plain signals created with `createSignal(value)` or `createOptimistic(value)`. */ export interface SignalOptions<T> { /** Debug name (dev mode only) */ name?: string; /** Custom equality function, or `false` to always notify subscribers */ equals?: false | ((prev: T, next: T) => boolean); /** Suppress dev-mode warnings when writing inside an owned scope */ pureWrite?: boolean; /** Callback invoked when the signal loses all subscribers */ unobserved?: () => void; } /** * Options for read-only memos created with `createMemo`. * Also used in combination with `SignalOptions` for writable memos * (`createSignal(fn)` / `createOptimistic(fn)`). */ export interface MemoOptions<T> { /** Stable identifier for the owner hierarchy */ id?: string; /** Debug name (dev mode only) */ name?: string; /** When true, the owner is invisible to the ID scheme -- inherits parent ID and doesn't consume a childCount slot */ transparent?: boolean; /** Custom equality function, or `false` to always notify subscribers */ equals?: false | ((prev: T, next: T) => boolean); /** Callback invoked when the computed loses all subscribers */ unobserved?: () => void; /** When true, defers the initial computation until the value is first read */ lazy?: boolean; } export type NoInfer<T extends any> = [T][T extends any ? 0 : never]; /** * Creates a simple reactive state with a getter and setter. * * When called with a plain value, creates a signal with `SignalOptions` (name, equals, pureWrite, unobserved). * When called with a function, creates a writable memo with `SignalOptions & MemoOptions` (adds id, lazy). * * ```typescript * // Plain signal * const [state, setState] = createSignal<T>(value, options?: SignalOptions<T>); * // Writable memo (function overload) * const [state, setState] = createSignal<T>(fn, initialValue?, options?: SignalOptions<T> & MemoOptions<T>); * ``` * @param value initial value of the state; if empty, the state's type will automatically extended with undefined * @param options optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity * * @returns `[state: Accessor<T>, setState: Setter<T>]` * * @description https://docs.solidjs.com/reference/basic-reactivity/create-signal */ export declare function createSignal<T>(): Signal<T | undefined>; export declare function createSignal<T>(value: Exclude<T, Function>, options?: SignalOptions<T>): Signal<T>; export declare function createSignal<T>(fn: ComputeFunction<T>, initialValue?: T, options?: SignalOptions<T> & MemoOptions<T>): Signal<T>; /** * Creates a readonly derived reactive memoized signal. * * ```typescript * const value = createMemo<T>(compute, initialValue?, options?: MemoOptions<T>); * ``` * @param compute a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation * @param value an optional initial value for the computation; if set, fn will never receive undefined as first argument * @param options `MemoOptions` -- id, name, equals, unobserved, lazy * * @description https://docs.solidjs.com/reference/basic-reactivity/create-memo */ export declare function createMemo<Next extends Prev, Prev = Next>(compute: ComputeFunction<undefined | NoInfer<Prev>, Next>): Accessor<Next>; export declare function createMemo<Next extends Prev, Init = Next, Prev = Next>(compute: ComputeFunction<Init | Prev, Next>, value: Init, options?: MemoOptions<Next>): Accessor<Next>; /** * Creates a reactive effect that runs after the render phase. * * ```typescript * createEffect<T>(compute, effectFn | { effect, error }, initialValue?, options?: EffectOptions); * ``` * @param compute a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation * @param effectFn a function that receives the new value and is used to perform side effects (return a cleanup function), or an `EffectBundle` with `effect` and `error` handlers * @param value an optional initial value for the computation; if set, fn will never receive undefined as first argument * @param options `EffectOptions` -- name, defer * * @description https://docs.solidjs.com/reference/basic-reactivity/create-effect */ export declare function createEffect<Next>(compute: ComputeFunction<undefined | NoInfer<Next>, Next>, effectFn: EffectFunction<NoInfer<Next>, Next> | EffectBundle<NoInfer<Next>, Next>): void; export declare function createEffect<Next, Init = Next>(compute: ComputeFunction<Init | Next, Next>, effect: EffectFunction<Next, Next> | EffectBundle<Next, Next>, value: Init, options?: EffectOptions): void; /** * Creates a reactive computation that runs during the render phase as DOM elements * are created and updated but not necessarily connected. * * ```typescript * createRenderEffect<T>(compute, effectFn, initialValue?, options?: EffectOptions); * ``` * @param compute a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation * @param effectFn a function that receives the new value and is used to perform side effects * @param value an optional initial value for the computation; if set, fn will never receive undefined as first argument * @param options `EffectOptions` -- name, defer * * @description https://docs.solidjs.com/reference/secondary-primitives/create-render-effect */ export declare function createRenderEffect<Next>(compute: ComputeFunction<undefined | NoInfer<Next>, Next>, effectFn: EffectFunction<NoInfer<Next>, Next>): void; export declare function createRenderEffect<Next, Init = Next>(compute: ComputeFunction<Init | Next, Next>, effectFn: EffectFunction<Next, Next>, value: Init, options?: EffectOptions): void; /** * Creates a tracked reactive effect where dependency tracking and side effects happen * in the same scope. * * WARNING: Because tracking and effects happen in the same scope, this primitive * may run multiple times for a single change or show tearing (reading inconsistent * state). Use only when dynamic subscription patterns require same-scope tracking. * * ```typescript * createTrackedEffect(compute, options?: EffectOptions); * ``` * @param compute a function that contains reactive reads to track and returns an optional cleanup function to run on disposal or before next execution * @param options `EffectOptions` -- name, defer * * @description https://docs.solidjs.com/reference/secondary-primitives/create-tracked-effect */ export declare function createTrackedEffect(compute: () => void | (() => void), options?: EffectOptions): void; /** * Creates a reactive computation that runs after the render phase with flexible tracking. * * ```typescript * const track = createReaction(effectFn, options?: EffectOptions); * track(() => { // reactive reads }); * ``` * @param effectFn a function (or `EffectBundle`) that is called when tracked function is invalidated * @param options `EffectOptions` -- name, defer * * @description https://docs.solidjs.com/reference/secondary-primitives/create-reaction */ export declare function createReaction(effectFn: EffectFunction<undefined> | EffectBundle<undefined>, options?: EffectOptions): (tracking: () => void) => void; /** * Returns a promise of the resolved value of a reactive expression * @param fn a reactive expression to resolve */ export declare function resolve<T>(fn: () => T): Promise<T>; /** * Creates an optimistic signal that can be used to optimistically update a value * and then revert it back to the previous value at end of transition. * * When called with a plain value, creates an optimistic signal with `SignalOptions` (name, equals, pureWrite, unobserved). * When called with a function, creates a writable optimistic memo with `SignalOptions & MemoOptions` (adds id, lazy). * * ```typescript * // Plain optimistic signal * const [state, setState] = createOptimistic<T>(value, options?: SignalOptions<T>); * // Writable optimistic memo (function overload) * const [state, setState] = createOptimistic<T>(fn, initialValue?, options?: SignalOptions<T> & MemoOptions<T>); * ``` * @param value initial value of the signal; if empty, the signal's type will automatically extended with undefined * @param options optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity * * @returns `[state: Accessor<T>, setState: Setter<T>]` * * @description https://docs.solidjs.com/reference/basic-reactivity/create-optimistic-signal */ export declare function createOptimistic<T>(): Signal<T | undefined>; export declare function createOptimistic<T>(value: Exclude<T, Function>, options?: SignalOptions<T>): Signal<T>; export declare function createOptimistic<T>(fn: ComputeFunction<T>, initialValue?: T, options?: SignalOptions<T> & MemoOptions<T>): Signal<T>; /** * Runs a callback after the current flush cycle completes. * * When called within a reactive context (owner), uses a tracked effect with untracked * reads - this means normal signal reads won't create subscriptions, but uninitialized * async values will throw NotReadyError, causing the callback to re-run when they settle. * * When called without an owner, runs once and immediately calls any returned cleanup. * * @param callback Function to run, may return a cleanup function */ export declare function onSettled(callback: () => void | (() => void)): void;