@oazmi/tsignal
Version:
a topological order respecting signals library inspired by SolidJS
65 lines (64 loc) • 3.56 kB
TypeScript
/** 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();
}