Skip to content

Commit

Permalink
feat(transducers-hdom): add DOM hydration support, rename (#39)
Browse files Browse the repository at this point in the history
- replace args with HDOMOpts
- add support for `hydrate`
- reflect same logic as w/ hdom `start()` re: null values

BREAKING CHANGE: rename transducer: `updateUI` => `updateDOM`, new API
  • Loading branch information
postspectacular committed Aug 31, 2018
1 parent 5e74a9c commit 0f39694
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 19 deletions.
23 changes: 16 additions & 7 deletions packages/transducers-hdom/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,31 @@ 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
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

Expand Down
43 changes: 31 additions & 12 deletions packages/transducers-hdom/src/index.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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<any, any[]> => {
root = isString(root) ? document.getElementById(root) : root;
export const updateDOM = (opts?: Partial<HDOMOpts>): Transducer<any, any[]> => {
opts = { root: "app", span: true, normalize: true, ...opts };
const root = isString(opts.root) ?
document.getElementById(opts.root) :
opts.root;
return scan<any, any[]>(
reducer(
() => [],
(prev, curr) => {
normalize && (curr = normalizeTree(curr, ctx));
diffElement(<Element>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;
}
)
);
Expand Down

0 comments on commit 0f39694

Please sign in to comment.