UNPKG

@zeix/cause-effect

Version:

Cause & Effect - reactive state management primitives library for TypeScript.

69 lines (68 loc) 3.27 kB
import { type Signal, type SignalOptions } from '../graph'; /** * A descriptor for a derived reactive value with an optional setter. * * @template T - The type of value */ type SlotDescriptor<T extends {}> = { /** Reads the value, tracking dependencies. */ get(): T; /** Optional setter to update the source value. */ set?(next: T): void; }; /** * A signal that delegates its value to a swappable backing signal. * * Slots provide a stable reactive source at a fixed position (e.g. an object property) * while allowing the backing signal to be replaced without breaking subscribers. * The object shape is compatible with `Object.defineProperty()` descriptors: * `get`, `set`, `configurable`, and `enumerable` are used by the property definition; * `replace()` and `current()` are kept on the slot object for integration-layer control. * * Slots are not `MutableSignal`s: they are forwarding layers, not value owners. * `set()` delegates to the backing signal; `update()` is intentionally absent. * * @template T - The type of value held by the delegated signal. */ type Slot<T extends {}> = { readonly [Symbol.toStringTag]: 'Slot'; /** Descriptor field: allows the property to be redefined or deleted. */ configurable: true; /** Descriptor field: the property shows up during enumeration. */ enumerable: true; /** Reads the current value from the delegated signal, tracking dependencies. */ get(): T; /** Writes a value to the delegated signal. Throws `ReadonlySignalError` if the delegated signal is read-only. */ set(next: T): void; /** Swaps the backing signal, invalidating all downstream subscribers. Narrowing (`U extends T`) is allowed. */ replace<U extends T>(next: Signal<U> | SlotDescriptor<U>): void; /** Returns the currently delegated signal. */ current(): Signal<T> | SlotDescriptor<T>; }; /** * Creates a slot signal that delegates its value to a swappable backing signal. * * A slot acts as a stable reactive source usable as a property descriptor via * `Object.defineProperty(target, key, slot)`. Subscribers link to the slot itself, * so replacing the backing signal with `replace()` invalidates them without breaking * existing edges. `set()` forwards to the current backing signal if it is writable; * `update()` is absent — a slot is a forwarding layer, not a value owner. * * @since 0.18.3 * @template T - The type of value held by the delegated signal. * @param initialSignal - The initial signal to delegate to. * @param options - Optional configuration for the slot. * @param options.equals - Custom equality function. Defaults to strict equality (`===`). * @param options.guard - Type guard to validate values passed to `set()`. * @returns A `Slot<T>` object usable both as a property descriptor and as a reactive signal. */ declare function createSlot<T extends {}>(initialSignal: Signal<T> | SlotDescriptor<T>, options?: SignalOptions<T>): Slot<T>; /** * Checks if a value is a Slot signal. * * @since 0.18.3 * @param value - The value to check * @returns True if the value is a Slot */ declare function isSlot<T extends {} = unknown & {}>(value: unknown): value is Slot<T>; export { createSlot, isSlot, type Slot, type SlotDescriptor };