diff --git a/packages/transducers-hdom/README.md b/packages/transducers-hdom/README.md index b555ccc4c5..6e2f223c66 100644 --- a/packages/transducers-hdom/README.md +++ b/packages/transducers-hdom/README.md @@ -17,7 +17,7 @@ This project is part of the ## About -This package provides a single `updateUI` function, a side-effecting & +This package provides a single `updateDOM` function, a side-effecting & stateful transducer which receives [@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/master/packages/hdom) component trees, diffs each against the previous value and applies any @@ -25,14 +25,23 @@ required changes to the browser DOM, starting at given root element. By default, incoming values are first normalized using @thi.ng/hdom's `normalizeTree()` function. +If the `hydrate` option is given, the first received tree is only used +to inject event listeners and initialize components with lifecycle +`init()` methods and expects an otherwise identical pre-existing DOM. +All succeeding trees are diffed then as usual. + This transducer is primarily intended for [@thi.ng/rstream](https://github.com/thi-ng/umbrella/tree/master/packages/rstream)-based -dataflow graphs, where this transducer can be used as final leaf -subscription / transformer to reflect UI changes back to the user, -without using the standard RAF update loop used by @thi.ng/hdom by -default. In this setup, UI updates will only be performed if the stream -this transducer is attached to receives new values (i.e. hdom component -trees). +dataflow graphs, where it can be used as final leaf subscription / +stream transformer to reflect UI changes back to the user, without using +the usual RAF update loop used by @thi.ng/hdom by default. In this +setup, DOM updates will only be performed if the stream this transducer +is attached to receives new values (i.e. hdom component trees). + +Please also see the following hdom references for further details: + +- [start()](https://github.com/thi-ng/umbrella/tree/master/packages/hdom/src/start.ts) +- [HDOMOpts](https://github.com/thi-ng/umbrella/tree/master/packages/hdom/src/api.ts#L19) ## Installation diff --git a/packages/transducers-hdom/src/index.ts b/packages/transducers-hdom/src/index.ts index f2d49efb19..0d7aa6c5a3 100644 --- a/packages/transducers-hdom/src/index.ts +++ b/packages/transducers-hdom/src/index.ts @@ -1,5 +1,7 @@ import { isString } from "@thi.ng/checks/is-string"; +import { HDOMOpts } from "@thi.ng/hdom/api"; import { diffElement } from "@thi.ng/hdom/diff"; +import { hydrateDOM } from "@thi.ng/hdom/dom"; import { normalizeTree } from "@thi.ng/hdom/normalize"; import { Transducer } from "@thi.ng/transducers/api"; import { reducer } from "@thi.ng/transducers/reduce"; @@ -14,27 +16,44 @@ import { scan } from "@thi.ng/transducers/xform/scan"; * `normalizeTree()` function and the given (optional) `ctx` object is * provided to all embedded component functions in the tree. * + * If the `hydrate` option is given, the first received tree is only + * used to inject event listeners and initialize components with + * lifecycle `init()` methods and expects an otherwise identical, + * pre-existing DOM. All succeeding trees are diffed then as usual. + * * This transducer is primarily intended for @thi.ng/rstream dataflow - * graph based applications, where this transducer can be used as final - * leaf subscription to reactively reflect UI changes back to the user, - * without using the standard RAF update loop used by hdom by default. - * In this setup, UI updates will only be performed when the stream this + * graph based applications, where it can be used as final leaf + * subscription to reactively reflect UI changes back to the user, + * without using the usual RAF update loop used by hdom by default. In + * this setup, DOM updates will only be performed when the stream this * transducer is attached to emits new values (i.e. hdom component * trees). * - * @param root root element (or ID) - * @param ctx hdom user context - * @param normalize + * Please see here for further details: + * https://github.com/thi-ng/umbrella/blob/master/packages/hdom/src/start.ts + * + * @param opts hdom options */ -export const updateUI = (root: string | Element, ctx?: any, normalize = true): Transducer => { - root = isString(root) ? document.getElementById(root) : root; +export const updateDOM = (opts?: Partial): Transducer => { + opts = { root: "app", span: true, normalize: true, ...opts }; + const root = isString(opts.root) ? + document.getElementById(opts.root) : + opts.root; return scan( reducer( () => [], (prev, curr) => { - normalize && (curr = normalizeTree(curr, ctx)); - diffElement(root, prev, curr); - return curr; + opts.normalize && (curr = normalizeTree(curr, opts.ctx, [0], opts.span)); + if (curr != null) { + if (opts.hydrate) { + hydrateDOM(root, curr); + opts.hydrate = false; + } else { + diffElement(root, prev, curr); + } + return curr; + } + return prev; } ) );