UNPKG

tilia

Version:

🍃 State management library, domain-driven.

116 lines (110 loc) 5.48 kB
declare const o: unique symbol; declare const r: unique symbol; export type Observer = { readonly [o]: true }; export type Signal<T> = { value: T }; export type Readonly<T> = { readonly data: T }; export type Setter<T> = (v: T) => void; export type Deriver<U> = { derived: <T>(fn: (p: U) => T) => T }; export type Tilia = { /** Transform a regular object or array into a reactive tilia proxy. */ tilia: <T>(branch: T) => T; /** Transform a regular object or array into a reactive tilia proxy, with the possibility to derive state from the object itself. */ carve: <T>(fn: (deriver: Deriver<T>) => T) => T; /** Register a callback to re-run whenever any observed value changes (push reactivity). */ observe: (fn: () => void) => void; /** React to changes: the first function captures values, the second runs when they change. */ watch: <T>(fn: () => T, effect: (v: T) => void) => void; /** Run operations in a batch, blocking notifications until the batch completes. */ batch: (fn: () => void) => void; /** Wrap a primitive in a reactive signal with a `value` field and a setter. */ signal: <T>(value: T) => Signal<T>; /** Derive a signal from other reactive values. */ derived: <T>(fn: () => T) => Signal<T>; /** * Return a reactive source value. The setup runs on first read and re-runs * when tracked dependencies change. The setter updates the value imperatively. */ source: <T>(initialValue: T, fn: (previous: T, set: Setter<T>) => unknown) => T; /** * Return a managed value. The setup runs on first access and re-runs when * dependencies change. It receives a setter and returns the initial value. */ store: <T>(fn: (set: Setter<T>) => T) => T; /** Track key-level writes on a tilia-proxied dict. Returns `{ changes, mute }`. */ changing: <T>(accessor: () => Record<string, T>, guard?: () => boolean) => Changing<T>; /** @internal */ _observe(callback: () => void): Observer; }; /** * Create a new tilia context with its own `tilia`, `observe`, `batch`, etc. * @param gc Maximum cleared watchers before garbage collection (default: 50). */ export function make(flush?: (fn: () => void) => void, gc?: number): Tilia; /** Transform a regular object or array into a reactive tilia proxy. */ export function tilia<T>(branch: T): T; /** Transform a regular object or array into a reactive tilia proxy, with the possibility to derive state from the object itself. */ export function carve<T>(fn: (deriver: Deriver<T>) => T): T; /** Register a callback to re-run whenever any observed value changes (push reactivity). */ export function observe(fn: () => void): void; /** * React to changes of captured values. The first function captures values to * observe; the second runs with the captured result whenever they change. */ export function watch<T>(fn: () => T, effect: (v: T) => void): void; /** Run operations in a batch, blocking notifications until the batch completes. */ export function batch(fn: () => void): void; /** Return a computed value. Cached on read, invalidated when observed values change (pull reactivity). */ export function computed<T>(fn: () => T): T; /** * Return a reactive source value. The setup runs on first read and re-runs * when tracked dependencies change. The setter updates the value imperatively. */ export function source<T>( initialValue: T, fn: (previous: T, set: Setter<T>) => unknown ): T; /** * Return a managed value. The setup runs on first access and re-runs when * dependencies change. It receives a setter and returns the initial value. */ export function store<T>(fn: (set: Setter<T>) => T): T; /** Wrap a value in a readonly holder to avoid tracking. */ export function readonly<T>(data: T): Readonly<T>; /** Wrap a primitive in a reactive signal with a `value` field and a setter. */ export function signal<T>(value: T): [Signal<T>, Setter<T>]; /** Derive a signal from other reactive values. */ export function derived<T>(fn: () => T): Signal<T>; /** Lift a signal into a computed value that tracks its inner `value` field. */ export function lift<T>(s: Signal<T>): T; export interface Changes<T> { upsert: T[]; remove: string[]; } export interface Changing<T> { /** Capture function for `watch`. Drains accumulated changes into `{ upsert, remove }`. */ changes: () => Changes<T>; /** Run a callback with tracking temporarily removed. Includes `batch`. */ mute: (fn: () => void) => void; } /** * Track key-level writes on a tilia-proxied dict. Takes an accessor so the * tracker follows source swaps. Returns `{ changes, mute }`. * `changes` drains accumulated changes: `upsert` contains objects captured at * write time, `remove` contains keys of deleted entries. Last write wins per key. * `mute` runs code without tracking (for inbound sync writes). * Each call creates an independent accumulator. When `guard` returns false, * changes accumulate silently; when it becomes true, all accumulated changes drain. */ export function changing<T>(accessor: () => Record<string, T>, guard?: () => boolean): Changing<T>; /** @internal */ export function _observe(callback: () => void): Observer; /** @internal */ export function _done(observer: Observer): void; /** @internal */ export function _ready(observer: Observer, notifyIfChanged?: boolean): void; /** @internal */ export function _clear(observer: Observer): void; /** @internal */ export function _meta<T>(tree: T): unknown; /** @internal */ export const _ctx: Tilia;