UNPKG

@oazmi/tsignal

Version:

a topological order respecting signals library inspired by SolidJS

65 lines (64 loc) 3.56 kB
/** a context is required for any signal to be functional * @module */ import { EffectFn, MemoFn } from "./signal.js"; import { EqualityFn, FROM_ID, ID, Signal, SignalClass, TO_ID } from "./typedefs.js"; /** if {@link Context | `ctx`} is your context, then these function members are available under {@link Context.dynamic | `ctx.dynamic`}. <br> * the purpose of these functions is to dynamically change an existing signal's `value` (or cached value), equality `equals` checking function, or its recomputation `fn` function. <br> * to use any of these, you must have the signal's {@link Signal.id | original id}, which is typically provided by the {@link SignalClass.create | create function's} first element in the tuple. * // TODO-DOC: give an example */ export interface Context_Dynamic { setValue: <T>(id: ID, new_value: T) => void; setEquals: <T>(id: ID, new_equals: EqualityFn<T>) => void; setFn: <T>(id: ID, new_fn: MemoFn<T> | EffectFn) => void; } /** if {@link Context | `ctx`} is your context, then these function members are available under {@link Context.batch | `ctx.batch`}. <br> * the purpose of these functions is to widthold any signals from firing until the batching is complete, and then all signals are fired together in one single propagation cycle. <br> * this is useful in circumstances where you have a array or dictionary like signal which must undergo many mutations all at once. * // TODO-DOC: give an example */ export interface Context_Batch { startBatching: () => number; endBatching: () => void; scopedBatching: <T extends any = void, ARGS extends any[] = []>(fn: (...args: ARGS) => T, ...args: ARGS) => T; } /** a signal context class is required to create and register signals. * without it, signals won't be able to communicate with each other, * and it would not be possible to build a signals dependency graph. * * @example * ```ts * const ctx = new Context() // create signal context * const createState = ctx.addClass(StateSignal_Factory) // feed the state signal factory function to get a signal generator * const createMemo = ctx.addClass(MemoSignal_Factory) // feed the memo signal factory function to get a signal generator * * const [idNum, getNum, setNum] = createState<number>(0) * const [idNum2, getNum2] = createMemo((memo_id) => { * const num2 = getNum(memo_id) ** 2 * console.log("recomputing number squared:", num2) * return num2 * }, { defer: false }) * * setNum(2) // console.log: "recomputing number squared: 4" * setNum(4) // console.log: "recomputing number squared: 16" * ``` */ export declare class Context { readonly addEdge: (src_id: FROM_ID, dst_id: TO_ID) => boolean; readonly delEdge: (src_id: FROM_ID, dst_id: TO_ID) => boolean; readonly newId: () => ID; readonly getId: (id: ID) => Signal<any> | undefined; readonly setId: (id: ID, signal: Signal<any>) => void; readonly delId: (id: ID) => boolean; readonly runId: (id: ID) => boolean; readonly swapId: (id1: ID, id2: ID) => void; readonly onInit: <T>(id: ID, initialization_func: () => T) => T | undefined; readonly onDelete: (id: ID, cleanup_func: () => void) => void; readonly clearCache: () => void; readonly addClass: <SIGNAL_CLASS extends SignalClass>(factory_fn: (ctx: Context) => SIGNAL_CLASS) => SIGNAL_CLASS["create"]; readonly getClass: <SIGNAL_CLASS extends SignalClass>(factory_fn: (ctx: Context) => SIGNAL_CLASS) => SIGNAL_CLASS; readonly batch: Context_Batch; readonly dynamic: Context_Dynamic; constructor(); }