@thi.ng/rdom
Version:
Lightweight, reactive, VDOM-less UI/DOM components with async lifecycle and @thi.ng/hiccup compatible
103 lines • 4.25 kB
TypeScript
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