UNPKG

@thi.ng/rdom

Version:

Lightweight, reactive, VDOM-less UI/DOM components with async lifecycle and @thi.ng/hiccup compatible

103 lines 4.25 kB
import type { Fn, NumOrString } from "@thi.ng/api"; import type { ISubscribable } from "@thi.ng/rstream"; import type { IComponent, IMountWithState, NumOrElement } from "./api.js"; import { Component } from "./component.js"; /** * Reactive component wrapper to dynamically switch/replace itself with one of * the given components depending on subscribed value. * * @remarks * Subscribes to `src`, then calls `keyFn` for each received value and uses * result to call one of the given `ctors` async component factories. The value * returned from the chosen factory will be passsed to {@link $compile} and then * mounted in place of this `$switch` wrapper. If an uncaught error occurs in * the selected component factory, the `error` component factory will be used * instead (which is expected to succeed). * * When a new value is received from `src`, the currently active inner component * (if any) will always be fist `unmount`ed and if the optional `loader` is * given, it will be temporarily mounted whilst the actual `ctor` component * factory executes. This is can be used to show a pre-loaders. * * **IMPORTANT:** When a `null` or `undefined` value is received from `src`, the * currently active inner component will be unmounted and the optional loader * shown. However, no other inner component constructor will be called in this * case (until the next valid/non-null value is received). * * All component factories are async functions to facilitate dynamic `import()` * / code splitting and other async initializations (WASM etc.) * * @example * ```ts * import { $switch } from "@thi.ng/rdom"; * import { fromInterval } from "@thi.ng/rstream"; * * $switch( * fromInterval(1000), * (x) => x % 3, * { * 0: async (x) => { * await delayed(null, 500); // fake preload * return ["div.green", {}, x]; * }, * 1: async (x) => ["div.yellow", {}, x] * }, * async (err) => ["div.bg-red", {}, err], * async () => ["div", {}, "Loading..."] * ).mount(document.body) * ``` * * This example uses a 1Hz counter to delegate to 3 different possible * components, however only two are defined, causing the last option to * throw an error and so trigger/use the error component. * * @param src - * @param keyFn - * @param ctors - * @param error - * @param loader - */ export declare const $switch: <T>(src: ISubscribable<T>, keyFn: Fn<T, NumOrString>, ctors: Record<NumOrString, Fn<T, Promise<any>>>, error?: Fn<Error, Promise<any>>, loader?: Fn<T, Promise<any>>) => IComponent<T>; /** * Syntax sugar for {@link $switch} for cases when there's only a single * component which should transition through its entire lifecycle for * each reactive value change. * * @remarks * In other words, for each new value received from `src`. The wrapped * component will first be unmounted, an optional pre-`loader` shown * whilst the async `ctor` component factory executes, its result * `$compile`d and then getting re-mounted. See {@link $switch} for * further details. * * Also see {@link $replace}. * * @example * ```ts * import { $refresh } from "@thi.ng/rdom"; * import { fromInterval } from "@thi.ng/rstream"; * * $refresh(fromInterval(1000), async (x) => ["div", {}, x]) * ``` * * @param src - * @param ctor - * @param error - * @param loader - */ export declare const $refresh: <T>(src: ISubscribable<T>, ctor: Fn<T, Promise<any>>, error?: Fn<Error, Promise<any>>, loader?: Fn<T, Promise<any>>) => IComponent<T>; export declare class Switch<T> extends Component implements IMountWithState<T> { protected keyFn: Fn<T, NumOrString>; protected ctors: Record<NumOrString, Fn<T, Promise<any>>>; protected error: Fn<Error, Promise<any>>; protected loader: Fn<T, Promise<any>>; protected val?: T; protected parent?: ParentNode; protected inner?: IComponent<T>; protected index?: NumOrElement; constructor(keyFn: Fn<T, NumOrString>, ctors: Record<NumOrString, Fn<T, Promise<any>>>, error?: Fn<Error, Promise<any>>, loader?: Fn<T, Promise<any>>); mount(parent: ParentNode, index: NumOrElement, val: T): Promise<Element>; unmount(): Promise<void>; update(val: T): Promise<void>; } //# sourceMappingURL=switch.d.ts.map