diff --git a/assets/dot-example.dot b/assets/dot-example.dot deleted file mode 100644 index b2af0bf274..0000000000 --- a/assets/dot-example.dot +++ /dev/null @@ -1,21 +0,0 @@ -digraph g { -rankdir="LR"; -fontname="Inconsolata"; -fontsize="9"; -fontcolor="gray"; -label="Generated with @thi.ng/dot"; -labeljust="l"; -labelloc="b"; -node[style="filled", fontname="Inconsolata", fontsize="11"]; -edge[arrowsize="0.75", fontname="Inconsolata", fontsize="9"]; -"x"[color="black", fontcolor="white", label="x (12)"]; -"y"[color="black", fontcolor="white", label="y (23)"]; -"res"[color="black", fontcolor="white", label="res (8050)", peripheries="2"]; -"op1"[fillcolor="green", shape="Mrecord", label="{ <0> a | <1> b } | op1\n(+) | { out }"]; -"op2"[fillcolor="yellow", shape="Mrecord", label="{ <0> a | <1> b } | op2\n(*) | { out }"]; -"x" -> "op1":"1"; -"y" -> "op1":"0"; -"y" -> "op2":"0"[label="xform", color="blue"]; -"op1":"out" -> "op2":"1"; -"op2":"out" -> "res"; -} \ No newline at end of file diff --git a/assets/dot/hdom-canvas-shapes.dot b/assets/dot/hdom-canvas-shapes.dot new file mode 100644 index 0000000000..454d350a5f --- /dev/null +++ b/assets/dot/hdom-canvas-shapes.dot @@ -0,0 +1,16 @@ +digraph g { + rankdir=LR; + node[fontname=Inconsolata,fontsize=11]; + edge[fontname=Inconsolata,fontsize=9]; + + selection -> scene; + fromRAF -> scene; + + scene -> ui; + scene -> exporter; + trigger -> exporter; + + exporter -> file[style=dashed,label="download"]; + ui -> selection[style=dashed,label="onchange"]; + ui -> trigger[style=dashed,label="onclick"]; +} \ No newline at end of file diff --git a/assets/dot/hdom-v5.xml b/assets/dot/hdom-v5.xml new file mode 100644 index 0000000000..14ee4334ed --- /dev/null +++ b/assets/dot/hdom-v5.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/assets/dot/hdom.xml b/assets/dot/hdom.xml new file mode 100644 index 0000000000..ffc99f9a27 --- /dev/null +++ b/assets/dot/hdom.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/assets/dot/iceps-dataflow.xml b/assets/dot/iceps-dataflow.xml new file mode 100644 index 0000000000..083ed7334e --- /dev/null +++ b/assets/dot/iceps-dataflow.xml @@ -0,0 +1 @@ +7VnJbtswEP0aA+0l0GYnOSaO3RZoiwIO0ObISLTEhtKoFBXb/fqS0lAbnSBNvBSFdTCox+E2bx6HlEf+NF1/ECRPvkBE+chzovXIvxl53tgP1K8GNjUQXI5rIBYsqiG3BRbsN0XQQbRkES16hhKAS5b3wRCyjIayhxEhYNU3WwLvj5qTmFrAIiTcRr+zSCY1ejF2WvwjZXFiRnYdrLkn4UMsoMxwvJHnL6unrk6J6Qvti4REsOpA/mzkTwWArEvpekq5dq1xW91u/kRtM29BM/mSBuc4DbkxS6eR8gS+gpAJxJARPmvR62p5VHfgqrdEphyLdM3kj075TpWds7F+y6TY6CrHvHTroitNmQLuOYQPtwnLanjOuOn6J5Vyg3FCSgkKaif3GSBHu0IKeKBT4CCq5fiX1dPUGDaVo6+XkMk5SRnXQXpLEkgJotva147S3nnS1QgVUIoQrTwMXiJiilZ+Q7NSD4WUKm8oE0E5keyx3zvBOI4bu5ZLVUA6t1OLQz8SXmKns0c9Vc/5VVIFeROuZnR9L1Qpls0KO6HQJ3qVMEkXOamWtlKy75PfRLKmOOakKLBsUTKvHu1qxW8Hd5yJel5KTNMLLpMKSdfPU2M7HRsEqEbcrVyjzlWr/QZLOrqfOG+nabwPBTpn5+OOCN1/XmYNm+1OceY1O4dZw+s06O9eg9j0G7BKUBhG3mU/jryLQXzUU8BWbYgoXsimY5Zrg+Ivxhlu8kN7/1l7Vahn0MZr45MXhfDFKYnsNYlsCeDgQEnEt5LIp0xSNbNcgrBTSC4gpEXBsviUXjr6c46YXwKLwYU6W+soXC710dniia5pWEoG2YnClkJ/ckQKJxaFEStyIsPkK6zevbdYUcuUA9f3PJxBRgfORYhwFqt98yakWuUK0E5j6l50hRUpi6Jq/97GdRsNznN0v2bLfJv+Bue7Jh92yAu2cOftgDvXtejZyfnOPt4156bescn535Oj+WTQzY7egbKjGbujTBJFehH6plXoGkbsbdSoV0v3KFvslg2g/lDhheExBDrU5wH3VndP96+TPo3VET+BmLFP+tztAfagAg1OAt2vQI94vXTt++VJoDu4nuxRoOq1/Xui/ljU/gXkz/4A \ No newline at end of file diff --git a/assets/dot/rstream-constructs.xml b/assets/dot/rstream-constructs.xml new file mode 100644 index 0000000000..4217f16a0d --- /dev/null +++ b/assets/dot/rstream-constructs.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/assets/hdom-dataflow.png b/assets/hdom-dataflow.png index 820ae33df9..ef4580b723 100644 Binary files a/assets/hdom-dataflow.png and b/assets/hdom-dataflow.png differ diff --git a/assets/rstream-merge.png b/assets/rstream-merge.png new file mode 100644 index 0000000000..3dbc03fd1f Binary files /dev/null and b/assets/rstream-merge.png differ diff --git a/assets/rstream-pubsub.png b/assets/rstream-pubsub.png new file mode 100644 index 0000000000..9e4f78554a Binary files /dev/null and b/assets/rstream-pubsub.png differ diff --git a/assets/rstream-sidechain-partition.png b/assets/rstream-sidechain-partition.png new file mode 100644 index 0000000000..ef69d523cc Binary files /dev/null and b/assets/rstream-sidechain-partition.png differ diff --git a/assets/rstream-sidechain-toggle.png b/assets/rstream-sidechain-toggle.png new file mode 100644 index 0000000000..9667eb0ea9 Binary files /dev/null and b/assets/rstream-sidechain-toggle.png differ diff --git a/assets/rstream-sync.png b/assets/rstream-sync.png new file mode 100644 index 0000000000..0402eb91bf Binary files /dev/null and b/assets/rstream-sync.png differ diff --git a/assets/screenshots/gesture-analysis.png b/assets/screenshots/gesture-analysis.png new file mode 100644 index 0000000000..ae9f0c9446 Binary files /dev/null and b/assets/screenshots/gesture-analysis.png differ diff --git a/assets/screenshots/svg-barchart.png b/assets/screenshots/svg-barchart.png new file mode 100644 index 0000000000..055185d2ed Binary files /dev/null and b/assets/screenshots/svg-barchart.png differ diff --git a/examples/async-effect/package.json b/examples/async-effect/package.json index c3ee841618..0098aeece5 100644 --- a/examples/async-effect/package.json +++ b/examples/async-effect/package.json @@ -5,8 +5,9 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "prepare": "mkdir -p out && cp foo.json out", - "build": "yarn prepare && parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "prepare": "yarn clean && mkdir -p out && cp foo.json out", + "build": "yarn prepare && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "yarn prepare && parcel index.html -p 8080 --open -d out" }, "devDependencies": { diff --git a/examples/canvas-dial/package.json b/examples/canvas-dial/package.json index 341bf44c6b..be616f6292 100644 --- a/examples/canvas-dial/package.json +++ b/examples/canvas-dial/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/cellular-automata/package.json b/examples/cellular-automata/package.json index 6076fd1208..5e02a14723 100644 --- a/examples/cellular-automata/package.json +++ b/examples/cellular-automata/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/commit-table-ssr/README.md b/examples/commit-table-ssr/README.md index ee39157b5c..7e69aab4ed 100644 --- a/examples/commit-table-ssr/README.md +++ b/examples/commit-table-ssr/README.md @@ -8,6 +8,17 @@ server-side rendering, static file generation and an extended interactive browser version of a git repo commit log. The server is a simple [express](https://expressjs.com/) app. +There're 3 versions in this example: + +1) A server app which generates a static HTML version of the commit + table, performs caching and provides a route for retrieving + the commits as JSON. This server also includes the [Parcel + middleware](https://parceljs.org/api.html#middleware) to allow + editing the client without having to restart the server. +2) A browser app which constructs the table client-side from the JSON + version of the commits +3) A node app which generates a static HTML file + All of the UI components used on the server side too work in the browser without change, though the browser version has additional functionality (i.e. interactive filtering of commits via user provided search filter). @@ -35,10 +46,10 @@ See [/src/server/index.ts](./src/server/index.ts) for details... git clone https://github.com/thi-ng/umbrella.git cd umbrella/examples/commit-table-ssr yarn install -yarn dev +yarn start ``` -Then open http://localhost:3000/ssr in your browser. +Then open http://localhost:8080/ssr in your browser. ### Browser version @@ -47,8 +58,8 @@ The browser version uses the same UI components, but realizes them via In addition to the SSR version above, this version displays additional repo stats and allows for interactive filtering of the commits. The -commits themselves are loaded as JSON and therefore also require the -server app. +commits themselves are loaded as JSON which are provided by the server +app above. Furthermore, this version utilizes [@thi.ng/rstream](https://github.com/thi-ng/umbrella/tree/master/packages/rstream) @@ -58,11 +69,11 @@ various reactive stream constructs. Comments are included. See [/src/client/index.ts](./src/client/index.ts) for details... ``` -yarn dev-client +yarn start ``` -Once you see a message that the server is running, open -http://localhost:3000 in your browser. +Once you see a message that the server is running and the client app has +been built, open http://localhost:8080 in your browser. ### Static file generation diff --git a/examples/commit-table-ssr/package.json b/examples/commit-table-ssr/package.json index 959c0f50c7..eb6e093ae1 100644 --- a/examples/commit-table-ssr/package.json +++ b/examples/commit-table-ssr/package.json @@ -5,10 +5,11 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { + "clean": "rm -rf .cache build out", + "prepare": "yarn clean && mkdir -p out && cp commits.json out", "build-static": "tsc && node build/server/static.js", - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", - "start-server": "tsc && node build/server/index.js", - "start": "yarn build-client && yarn start-server" + "build": "yarn prepare && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", + "start": "tsc && node build/server/index.js" }, "devDependencies": { "parcel-bundler": "^1.9.7", diff --git a/examples/commit-table-ssr/src/client/index.ts b/examples/commit-table-ssr/src/client/index.ts index 453fa9887d..0a9bb6abca 100644 --- a/examples/commit-table-ssr/src/client/index.ts +++ b/examples/commit-table-ssr/src/client/index.ts @@ -17,6 +17,11 @@ import { link } from "../common/components/link"; import { repoTable } from "../common/components/repo-table"; import { ctx } from "../common/config"; +const COMMITS_URL = + process.env.NODE_ENV === "production" ? + "./commits.json" : + "/commits"; + // UI root component const app = (state) => ["div", @@ -83,7 +88,7 @@ error.subscribe({ next: (e) => alert(`An error occurred:\n${e}`) }); const commits = fromInterval(60 * 60 * 1000) // fetch commits from server .transform( - map(() => fetch("./commits").then( + map(() => fetch(COMMITS_URL).then( (res) => res.ok ? res.json() : error.next("error loading commits"), (e) => error.next(e.message) )) diff --git a/examples/commit-table-ssr/src/server/index.ts b/examples/commit-table-ssr/src/server/index.ts index 302ed03339..5ac57b254e 100644 --- a/examples/commit-table-ssr/src/server/index.ts +++ b/examples/commit-table-ssr/src/server/index.ts @@ -1,11 +1,11 @@ import { TLRUCache } from "@thi.ng/cache"; import * as express from "express"; +import * as Bundler from "parcel-bundler"; import { Commit } from "../common/api"; import { ctx } from "../common/config"; import { buildRepoTableHTML } from "./build-table"; import { repoCommits } from "./git"; -import { html, script } from "./html"; // building the repo commit table takes quite some time // therefore we cache results with 1h expiry time @@ -13,24 +13,19 @@ import { html, script } from "./html"; const rawCache = new TLRUCache(null, { ttl: 60 * 60 * 1000 }); const htmlCache = new TLRUCache(null, { ttl: 60 * 60 * 1000 }); -const app = express(); +// console.log("parcel:", Object.keys(parcel)); +const bundler = new Bundler("index.html", { + outDir: "./out", + outFile: "index.html", + publicUrl: "/out", +}); -app.use(express.static(".")); +const app = express(); // route for browser version -// here we simply return a barebone html doc -// with a reference to the built client JS +// here we simply redirect to the Parcel managed client version app.get("/", (_, res) => { - res.send(html({ - ctx, - head: { - title: "commit-table-hdom", - }, - body: [ - ["div#app"], - [script, { src: "bundle.js" }] - ], - })); + res.redirect("/out/"); }); // route for the client to retrieve the commit log as JSON @@ -61,5 +56,8 @@ app.get("/ssr", (_, res) => { ).then((doc) => res.send(doc)) }); -console.log("starting server @ http://localhost:3000"); -app.listen(3000); +app.use(express.static(".")); +app.use(bundler.middleware()); + +console.log("starting server @ http://localhost:8080"); +app.listen(8080); diff --git a/examples/crypto-chart/package.json b/examples/crypto-chart/package.json index 93e88fc0db..57b9a3e6ed 100644 --- a/examples/crypto-chart/package.json +++ b/examples/crypto-chart/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/dashboard/package.json b/examples/dashboard/package.json index c3681aeb92..322a34ab95 100644 --- a/examples/dashboard/package.json +++ b/examples/dashboard/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/devcards/package.json b/examples/devcards/package.json index cc98b2d0a3..954172b0e2 100644 --- a/examples/devcards/package.json +++ b/examples/devcards/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/gesture-analysis/package.json b/examples/gesture-analysis/package.json index 406e35b016..0bc1934693 100644 --- a/examples/gesture-analysis/package.json +++ b/examples/gesture-analysis/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/hdom-basics/package.json b/examples/hdom-basics/package.json index f20547086a..c462f92b8d 100644 --- a/examples/hdom-basics/package.json +++ b/examples/hdom-basics/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/hdom-benchmark/package.json b/examples/hdom-benchmark/package.json index 7cb7a22eb5..ceb4964fd5 100644 --- a/examples/hdom-benchmark/package.json +++ b/examples/hdom-benchmark/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/hdom-canvas-clock/README.md b/examples/hdom-canvas-clock/README.md index 54dbea8f58..c5b92f327a 100644 --- a/examples/hdom-canvas-clock/README.md +++ b/examples/hdom-canvas-clock/README.md @@ -3,12 +3,13 @@ [Live demo](http://demo.thi.ng/umbrella/hdom-canvas-clock/) Declarative canvas drawing using the upcoming -[@thi.ng/hdom-canvas](https://github.com/thi-ng/umbrella/tree/develop/packages/hdom-canvas) +[@thi.ng/hdom-canvas](https://github.com/thi-ng/umbrella/tree/master/packages/hdom-canvas) package. Related examples: -- [hdom-canvas-shapes](https://github.com/thi-ng/umbrella/tree/develop/examples/hdom-canvas-shapes) +- [hdom-canvas-draw](https://github.com/thi-ng/umbrella/tree/master/examples/hdom-canvas-draw) +- [hdom-canvas-shapes](https://github.com/thi-ng/umbrella/tree/master/examples/hdom-canvas-shapes) ## Building @@ -19,7 +20,7 @@ The example project also assumes that [Parcel](https://parceljs.org) is installed globally. ```bash -git clone -b develop https://github.com/thi-ng/umbrella.git +git clone https://github.com/thi-ng/umbrella.git cd umbrella/examples/hdom-canvas-clock yarn install yarn start diff --git a/examples/hdom-canvas-clock/package.json b/examples/hdom-canvas-clock/package.json index 4577259ed2..056802a80e 100644 --- a/examples/hdom-canvas-clock/package.json +++ b/examples/hdom-canvas-clock/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/hdom-canvas-clock/src/index.ts b/examples/hdom-canvas-clock/src/index.ts index 2d6533f319..4b3feb3083 100644 --- a/examples/hdom-canvas-clock/src/index.ts +++ b/examples/hdom-canvas-clock/src/index.ts @@ -45,7 +45,7 @@ const cancel = start(() => { // applied in a nested manner... // // see here for a list of all supported attribs: - // https://github.com/thi-ng/umbrella/blob/develop/packages/hdom-canvas/src/index.ts#L35 + // https://github.com/thi-ng/umbrella/blob/master/packages/hdom-canvas/src/index.ts#L35 ["g", { translate: [100, 100], @@ -72,7 +72,7 @@ const cancel = start(() => { }), ["circle", {}, [0, 0], 5]]]], ["a.link", - { href: "https://github.com/thi-ng/umbrella/tree/develop/examples/hdom-canvas-clock" }, + { href: "https://github.com/thi-ng/umbrella/tree/master/examples/hdom-canvas-clock" }, "Source code"]]; }); diff --git a/examples/hdom-canvas-draw/.gitignore b/examples/hdom-canvas-draw/.gitignore new file mode 100644 index 0000000000..0c5abcab62 --- /dev/null +++ b/examples/hdom-canvas-draw/.gitignore @@ -0,0 +1,5 @@ +.cache +out +node_modules +yarn.lock +*.js diff --git a/examples/hdom-canvas-draw/README.md b/examples/hdom-canvas-draw/README.md new file mode 100644 index 0000000000..5ca912c7a2 --- /dev/null +++ b/examples/hdom-canvas-draw/README.md @@ -0,0 +1,18 @@ +# hdom-canvas-draw + +[Live demo](http://demo.thi.ng/umbrella/hdom-canvas-draw/) + +```bash +git clone https://github.com/thi-ng/umbrella.git +cd umbrella/examples/hdom-canvas-draw +yarn install +yarn start +``` + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/hdom-canvas-draw/index.html b/examples/hdom-canvas-draw/index.html new file mode 100644 index 0000000000..cdb4c7ffa6 --- /dev/null +++ b/examples/hdom-canvas-draw/index.html @@ -0,0 +1,16 @@ + + + + + + + hdom-canvas-draw + + + + +
+ + + diff --git a/examples/hdom-canvas-draw/package.json b/examples/hdom-canvas-draw/package.json new file mode 100644 index 0000000000..f456ec6f02 --- /dev/null +++ b/examples/hdom-canvas-draw/package.json @@ -0,0 +1,31 @@ +{ + "name": "hdom-canvas-draw", + "version": "0.0.1", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", + "start": "parcel index.html -p 8080 --open" + }, + "devDependencies": { + "parcel-bundler": "^1.9.7", + "terser": "^3.8.2", + "typescript": "^3.0.1" + }, + "dependencies": { + "@thi.ng/hdom-canvas": "latest", + "@thi.ng/rstream": "latest", + "@thi.ng/rstream-gestures": "latest", + "@thi.ng/transducers": "latest", + "@thi.ng/transducers-hdom": "latest", + "@thi.ng/vectors": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "browser": { + "process": false + } +} \ No newline at end of file diff --git a/examples/hdom-canvas-draw/src/index.ts b/examples/hdom-canvas-draw/src/index.ts new file mode 100644 index 0000000000..b26f773d3f --- /dev/null +++ b/examples/hdom-canvas-draw/src/index.ts @@ -0,0 +1,127 @@ +import { canvas } from "@thi.ng/hdom-canvas"; +import { GestureEvent, gestureStream, GestureType } from "@thi.ng/rstream-gestures"; +import { sync } from "@thi.ng/rstream/stream-sync"; +import { trigger } from "@thi.ng/rstream/trigger"; +import { updateDOM } from "@thi.ng/transducers-hdom"; +import { normRange } from "@thi.ng/transducers/iter/norm-range"; +import { repeat } from "@thi.ng/transducers/iter/repeat"; +import { tuples } from "@thi.ng/transducers/iter/tuples"; +import { filter } from "@thi.ng/transducers/xform/filter"; +import { map } from "@thi.ng/transducers/xform/map"; +import { mapcat } from "@thi.ng/transducers/xform/mapcat"; +import { partition } from "@thi.ng/transducers/xform/partition"; +import { HALF_PI, PI } from "@thi.ng/vectors/math"; +import { dist2 } from "@thi.ng/vectors/vec2"; + +// canvas size +const W = 480; + +// higher order line/shape component function +// takes a tuple of 2 points and returns a component fn +const line = ([a, b]: number[][]) => + (_, attribs) => + ["line", { ...attribs, weight: dist2(a, b) / 4 }, a, b]; + +// higher order root component function. takes a @thi.ng/rstream +// `StreamSync` instance as argument to dynamically add a new input +// stream to later +const app = (main) => { + // augment hdom-canvas component w/ `init` lifecycle method: this is + // method is called when the canvas DOM element is first created and + // used to attach a mouse & touch event stream to it. this stream is + // then transformed using a number of transducers and eventually + // outputs a series of `line` components. furthermore this + // transformed stream is added as new input to the `main` stream + // combinator below... + const _canvas = { + ...canvas, + init: (el: HTMLCanvasElement) => + main.add( + gestureStream(el) + .transform( + // only interested in some gesture types + filter((e: GestureEvent) => + e[0] === GestureType.START || + e[0] === GestureType.DRAG + ), + // get current mouse / touch position + map((e) => e[1].pos), + // form consecutive line pairs + partition(2, 1), + // transform into pre-curried line component + map(line) + ), + // name of the new input + "gesture" + ) + }; + // this root component function will produce the actual UI and + // will be attached to the `main` stream combinator below and executes + // each time any inputs have changed... + // the only input used here is the above stream of mouse events + // transformed into line components + return ({ gesture }) => + ["div.sans-serif.ma2", "Click & draw in the box below...", + // all child elements of the canvas component + // are NOT real DOM elements, but are translated into + // canvas API draw calls + [_canvas, { class: "mv2 db", width: W, height: W, __clear: false }, + // semi-transparent bg + ["rect", + { + fill: "rgba(255,255,255,0.1)", + stroke: "black", + dash: [1, 1] + }, + [0, 0], W, W + ], + // use a group node to assign attributes common to all children + ["g", { lineCap: "round" }, + // `mapcat` here returns an iterator of fully + // configured line components + mapcat((attribs) => + map(([[h, translate, theta], delta]: any[]) => + // the `gesture` value is a pre-curried component fn + // (built by the the above transducer chain). we can + // configure it further using additional attributes to + // draw multiple instances. + [gesture, + { + stroke: `hsl(${h + (delta - 0.5) * 40},100%,50%)`, + rotate: theta + (delta - 0.5) * 0.3, + translate + } + ], + // iterator which forms tuples of `[attribs, counter]` + tuples(repeat(attribs), normRange(6)) + ), + // configurations for the replicated strokes + [ + [30, [0, 0], 0], + [120, [W, W], PI], + [210, [W, 0], HALF_PI], + [300, [0, W], -HALF_PI] + ] + ) + ] + ], + // back in normal DOM + ["a.db.link", + { href: "https://github.com/thi-ng/umbrella/tree/master/examples/hdom-canvas-draw" }, + "Source code"] + ]; +}; + +// main stream combinator: initially only a single dummy `trigger` input +// is assigned to kick off rendering... in the 1st frame the canvas +// component's `init` method is called which attaches the above gesture +// stream dynamically. the entire UI then only updates when there are new +// user interactions... +const main = sync({ src: { trigger: trigger() } }); +// transform result stream using the +// root component fn and the hdom differential +// update transducer +main.transform( + map(app(main)), + updateDOM() +); diff --git a/examples/hdom-canvas-draw/tsconfig.json b/examples/hdom-canvas-draw/tsconfig.json new file mode 100644 index 0000000000..bbf112cc18 --- /dev/null +++ b/examples/hdom-canvas-draw/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/examples/hdom-canvas-shapes/README.md b/examples/hdom-canvas-shapes/README.md index 01c0111db1..9ff45425fd 100644 --- a/examples/hdom-canvas-shapes/README.md +++ b/examples/hdom-canvas-shapes/README.md @@ -3,33 +3,34 @@ [Live demo](http://demo.thi.ng/umbrella/hdom-canvas-shapes/) This example demonstrates different features of the upcoming -[@thi.ng/hdom-canvas](https://github.com/thi-ng/umbrella/tree/develop/packages/hdom-canvas) +[@thi.ng/hdom-canvas](https://github.com/thi-ng/umbrella/tree/master/packages/hdom-canvas) package to declare canvas scenegraphs using the same hiccup syntax as the rest of the UI. These shape elements (children of the `canvas` component) are defined via a SVG-like approach (though not using stringified geometry) and, using the new branch-local behavior feature of -[@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/develop/packages/hdom), +[@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/master/packages/hdom), are translated into canvas API draw calls. Shapes can be grouped and any attributes defined on group nodes will be inherited by all children (same as in SVG). Furthermore, this example acts as a test bed for -[@thi.ng/hiccup-svg](https://github.com/thi-ng/umbrella/tree/develop/packages/hiccup-svg)'s +[@thi.ng/hiccup-svg](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup-svg)'s `convertTree()` function to translate and then serialize these scene trees to downloadable SVG files. See the [@thi.ng/hdom-canvas -readme](https://github.com/thi-ng/umbrella/tree/develop/packages/hdom-canvas) +readme](https://github.com/thi-ng/umbrella/tree/master/packages/hdom-canvas) for further details. Related examples: -- [hdom-canvas-clock](https://github.com/thi-ng/umbrella/tree/develop/examples/hdom-canvas-clock) +- [hdom-canvas-clock](https://github.com/thi-ng/umbrella/tree/master/examples/hdom-canvas-clock) +- [hdom-canvas-draw](https://github.com/thi-ng/umbrella/tree/master/examples/hdom-canvas-draw) Dataflow diagram: -![dataflow](https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/hdom-canvas-shapes.png) +![dataflow](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/hdom-canvas-shapes.png) ## Building @@ -40,7 +41,7 @@ The example project also assumes that [Parcel](https://parceljs.org) is installed globally. ```bash -git clone -b develop https://github.com/thi-ng/umbrella.git +git clone https://github.com/thi-ng/umbrella.git cd umbrella/examples/hdom-canvas-shapes yarn install yarn start diff --git a/examples/hdom-canvas-shapes/package.json b/examples/hdom-canvas-shapes/package.json index ce4d870d9e..f8cb57e562 100644 --- a/examples/hdom-canvas-shapes/package.json +++ b/examples/hdom-canvas-shapes/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open --no-cache" }, "devDependencies": { diff --git a/examples/hdom-canvas-shapes/src/index.ts b/examples/hdom-canvas-shapes/src/index.ts index 952b509677..6c43014dda 100644 --- a/examples/hdom-canvas-shapes/src/index.ts +++ b/examples/hdom-canvas-shapes/src/index.ts @@ -11,7 +11,7 @@ import { map } from "@thi.ng/transducers/xform/map"; import { Mat23 } from "@thi.ng/vectors/mat23"; // for testing SVG conversion -import { serialize } from "@thi.ng/hiccup"; +import { COMMENT, serialize } from "@thi.ng/hiccup"; import { convertTree } from "@thi.ng/hiccup-svg/convert"; import { svg } from "@thi.ng/hiccup-svg/svg"; @@ -271,7 +271,7 @@ scene.transform( ["div.ma2.tc", TESTS[id].desc], ["a.link", - { href: "https://github.com/thi-ng/umbrella/tree/develop/examples/hdom-canvas-shapes" }, + { href: "https://github.com/thi-ng/umbrella/tree/master/examples/hdom-canvas-shapes" }, "Source code"] ] ), @@ -289,6 +289,7 @@ sync({ serialize( svg( { width: 300, height: 300, stroke: "none", fill: "none" }, + [COMMENT, `generated by @thi.ng/hiccup-svg @ ${new Date()}`], convertTree(scene.shapes) ) ) diff --git a/examples/hdom-dropdown-fuzzy/package.json b/examples/hdom-dropdown-fuzzy/package.json index 8c7f24f438..daf8a0cf02 100644 --- a/examples/hdom-dropdown-fuzzy/package.json +++ b/examples/hdom-dropdown-fuzzy/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/hdom-dropdown/package.json b/examples/hdom-dropdown/package.json index 383df85b36..2038080090 100644 --- a/examples/hdom-dropdown/package.json +++ b/examples/hdom-dropdown/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/hdom-theme-adr-0003/README.md b/examples/hdom-theme-adr-0003/README.md index 7927f0a027..7d42d4a39c 100644 --- a/examples/hdom-theme-adr-0003/README.md +++ b/examples/hdom-theme-adr-0003/README.md @@ -3,7 +3,7 @@ [Live demo](https://demo.thi.ng/umbrella/hdom-theme-adr-0003/) WIP demo of themed component proposal discussed in -[ADR-0003](https://github.com/thi-ng/umbrella/blob/develop/packages/hdom-components/adr/0003-component-configuration-via-context.md). +[ADR-0003](https://github.com/thi-ng/umbrella/blob/master/packages/hdom-components/adr/0003-component-configuration-via-context.md). ```bash git clone https://github.com/thi-ng/umbrella.git diff --git a/examples/hdom-theme-adr-0003/package.json b/examples/hdom-theme-adr-0003/package.json index 2a356de8ab..f96eeb0a32 100644 --- a/examples/hdom-theme-adr-0003/package.json +++ b/examples/hdom-theme-adr-0003/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/hdom-theme-adr-0003/src/index.ts b/examples/hdom-theme-adr-0003/src/index.ts index 17f9fada5f..9e0b6e2735 100644 --- a/examples/hdom-theme-adr-0003/src/index.ts +++ b/examples/hdom-theme-adr-0003/src/index.ts @@ -140,8 +140,8 @@ const app = (ctx) => [btFixed, { onclick: () => alert("hi"), selected: true }, "Selected"], [btFixed, { disabled: true }, "Disabled"]], ["p", - "Please see ", [link, "https://github.com/thi-ng/umbrella/blob/develop/packages/hdom-components/adr/0003-component-configuration-via-context.md", "ADR-0003"], " for details of this approach."], - ["p", [link, "https://github.com/thi-ng/umbrella/blob/develop/examples/hdom-theme-adr-0003", "Source"]] + "Please see ", [link, "https://github.com/thi-ng/umbrella/blob/master/packages/hdom-components/adr/0003-component-configuration-via-context.md", "ADR-0003"], " for details of this approach."], + ["p", [link, "https://github.com/thi-ng/umbrella/blob/master/examples/hdom-theme-adr-0003", "Source"]] ]; start(app, { ctx }); diff --git a/examples/hmr-basics/package.json b/examples/hmr-basics/package.json index 73520958a1..60d17697e2 100644 --- a/examples/hmr-basics/package.json +++ b/examples/hmr-basics/package.json @@ -5,8 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "clean": "rm -rf out", - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/hydrate-basics/package.json b/examples/hydrate-basics/package.json index 97e6f64cfd..85c6f882db 100644 --- a/examples/hydrate-basics/package.json +++ b/examples/hydrate-basics/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/interceptor-basics/README.md b/examples/interceptor-basics/README.md index e8e4ec03df..17744b1f5c 100644 --- a/examples/interceptor-basics/README.md +++ b/examples/interceptor-basics/README.md @@ -1,6 +1,6 @@ # interceptor-basics -[Live demo](https://demo.thi.ng/umbrella/interceptor-basics/) +[Live demo](http://demo.thi.ng/umbrella/interceptor-basics/) ```bash git clone https://github.com/thi-ng/umbrella.git @@ -8,3 +8,11 @@ cd umbrella/examples/interceptor-basics yarn install yarn start ``` + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/interceptor-basics/index.html b/examples/interceptor-basics/index.html index 854663bf78..e6fa25117b 100644 --- a/examples/interceptor-basics/index.html +++ b/examples/interceptor-basics/index.html @@ -1,57 +1,16 @@ - interceptor-basics + - -

This example demonstrates the use of @thi.ng/atom's event bus and interceptor driven event handling features.

-

See sources for detailed comments (blog post forthcoming): -

-

- + - - \ No newline at end of file + diff --git a/examples/interceptor-basics/package.json b/examples/interceptor-basics/package.json index 792bffeed2..c97371bff5 100644 --- a/examples/interceptor-basics/package.json +++ b/examples/interceptor-basics/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { @@ -16,7 +17,8 @@ "dependencies": { "@thi.ng/api": "latest", "@thi.ng/atom": "latest", - "@thi.ng/hdom": "latest" + "@thi.ng/rstream": "latest", + "@thi.ng/transducers-hdom": "latest" }, "browserslist": [ "last 3 Chrome versions" diff --git a/examples/interceptor-basics/src/index.ts b/examples/interceptor-basics/src/index.ts index 7027aeb40c..428a3b2c46 100644 --- a/examples/interceptor-basics/src/index.ts +++ b/examples/interceptor-basics/src/index.ts @@ -1,137 +1,48 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { start } from "@thi.ng/hdom/start"; -import { EffectDef, EventDef, IDispatch } from "@thi.ng/interceptors/api"; -import { EV_SET_VALUE, EV_UPDATE_VALUE, FX_DISPATCH_NOW } from "@thi.ng/interceptors/api"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; -import { ensureStateGreaterThan, ensureStateLessThan, trace } from "@thi.ng/interceptors/interceptors"; -import { Path } from "@thi.ng/paths"; - -/////////////////////////////////////////////////////////////////////// -// event name and handler definitions - -// best practice tip: -// define event & effect names as consts or enums and -// avoid hardcoded strings for easier refactoring -// additionally/alternatively define dispatch functions -const EV_INC = "inc-counter"; -const EV_DEC = "dec-counter"; -const EV_ADD_COUNTER = "add-counter"; -const EV_ADD_VALUE = "add-value"; - -const FX_ADD_COUNTER = "add-counter"; - -const events: IObjectOf = { - // these event handlers delegate to "updateVal" in same - // processing frame (using FX_DISPATCH_NOW) - // note how we also inject the predicate interceptors here to ensure - // counter values will be always be in the range between 0 .. 100 - [EV_INC]: [ - ensureStateLessThan(100, null, () => console.warn("eek, reached max")), - (_, [__, path]) => ({ [FX_DISPATCH_NOW]: [EV_ADD_VALUE, [path, 1]] }) - ], - [EV_DEC]: [ - ensureStateGreaterThan(0, null, () => console.warn("eek, reached min")), - (_, [__, path]) => ({ [FX_DISPATCH_NOW]: [EV_ADD_VALUE, [path, -1]] }) - ], - - // similar to the EV_INIT handler above, here we just delegate to the - // the built-in EV_UPDATE_VALUE handler to update a given path value. - // Additionally, we inject the `trace` interceptor to log the event - // each time it's triggered - [EV_ADD_VALUE]: [ - trace, - (_, [__, [path, y]]) => - ({ [FX_DISPATCH_NOW]: [EV_UPDATE_VALUE, [path, (x) => x + y]] }) - ], - - // this handler increments the `nextID` state value and - // triggers FX_ADD_COUNTER side effect with config options for the new counter - [EV_ADD_COUNTER]: (state) => ({ - [FX_DISPATCH_NOW]: [EV_ADD_VALUE, ["nextID", 1]], - // the FX_ADD_COUNTER side effect is defined further below - // here we simply prepare some configuration data for the new counter - [FX_ADD_COUNTER]: { - id: state.nextID, - start: ~~(Math.random() * 100), - color: ["gold", "orange", "springgreen", "yellow", "cyan"][~~(Math.random() * 5)] - } +import { Atom } from "@thi.ng/atom"; +import { start } from "@thi.ng/hdom"; +import { choices } from "@thi.ng/transducers"; +import * as icep from "@thi.ng/interceptors"; + +// infinite iterator of random color choices +const colors = choices(["cyan", "yellow", "magenta", "chartreuse"]); + +// central app state (initially empty) +const db = new Atom({}); + +// event bus w/ handlers +// see @thi.ng/interceptors for more details +const bus = new icep.EventBus(db, { + "init": () => ({ + [icep.FX_STATE]: { clicks: 0, color: "grey" } }), -}; - -/////////////////////////////////////////////////////////////////////// -// skeleton for other side effects, ignore for now - -const effects: IObjectOf = { - -}; - -/////////////////////////////////////////////////////////////////////// -// components - -const button = (bus, event, label, id?) => - ["button", { id, onclick: () => bus.dispatch(event) }, label]; - -// counter component function -// calls to this function will be triggered via the "addCounter" event and its side effect -// (see further below) -const counter = (bus: IDispatch, path: Path, start = 0, color: string) => { - const view = bus.state.addView(path); - bus.dispatch([EV_SET_VALUE, [path, start]]); - return ["div.counter", - { style: { background: color } }, - () => view.deref() || 0, - ["div", - button(bus, [EV_DEC, view.path], "-"), - button(bus, [EV_INC, view.path], "+")]]; -} - -// main app -const app = () => { - // an array to store counter component instances - // (only using component local state for KISS reasons) - const counters = []; - - // create event bus with app state atom and configure with above handlers/effects - const bus = new EventBus(null, events, effects); - - // in addition to externally defined event handlers & side effects - // each type can also be added & remove dynamically - // here we define the FX_ADD_COUNTER side effect, responsible for - // creating a new `counter()` component - bus.addEffect(FX_ADD_COUNTER, - ({ id, color, start }, bus) => - counters.push(counter(bus, ["counters", id], start, color))); - - // add derived view subscription for updating JSON state trace - // (only executed when state changes) - const json = bus.state.addView([], (state) => JSON.stringify(state, null, 2)); - - // this not just initializes the given state value - // the changed state will also trigger the 1st DOM rendering (see returned function below) - bus.dispatch([EV_SET_VALUE, ["nextID", 0]]); - - // our actual root component function passed to hdom - const root = () => - ["div", - button(bus, [EV_ADD_COUNTER], "add counter", "addcounter"), - ["div", ...counters], - ["pre", json]]; - - return () => { - // here we do an optional fail fast check, a useful & energy saving - // approach for apps, which purely rely on the central app state. - // this example app is such a case and we can check if there were - // any events processed which caused a state change and only - // return the root component then (i.e. `processQueue()` returned `true`) - - // if there were no changes, we simply return nothing. - // hdom interprets this as a skipped frame (and does nothing until this - // function is called again during the next frame update cycle...) - if (bus.processQueue()) { - return root; - } - } -}; - -// kick off hdom render loop -start(app()); + "inc-counter": [ + icep.valueUpdater("clicks", (x: number) => x + 1), + icep.dispatchNow(["randomize-color"]) + ], + "randomize-color": icep.valueUpdater( + "color", () => colors.next().value + ) +}); + +start( + // this root component function will be executed via RAF. + // it first processes events and then only returns an updated + // component if there was a state update... + (ctx) => ctx.bus.processQueue() ? + ["button", + { + style: { + padding: "1rem", + background: ctx.db.value.color + }, + onclick: () => ctx.bus.dispatch(["inc-counter"]) + }, + `clicks: ${ctx.db.value.clicks}`] : + null, + // hdom options incl. + // arbitrary user context object passed to all components + { ctx: { db, bus } } +); + +// kick off +bus.dispatch(["init"]); diff --git a/examples/interceptor-basics/tsconfig.json b/examples/interceptor-basics/tsconfig.json index b7d63aedf0..bbf112cc18 100644 --- a/examples/interceptor-basics/tsconfig.json +++ b/examples/interceptor-basics/tsconfig.json @@ -8,4 +8,4 @@ "include": [ "./src/**/*.ts" ] -} \ No newline at end of file +} diff --git a/examples/interceptor-basics2/.gitignore b/examples/interceptor-basics2/.gitignore new file mode 100644 index 0000000000..0c5abcab62 --- /dev/null +++ b/examples/interceptor-basics2/.gitignore @@ -0,0 +1,5 @@ +.cache +out +node_modules +yarn.lock +*.js diff --git a/examples/interceptor-basics2/README.md b/examples/interceptor-basics2/README.md new file mode 100644 index 0000000000..5ebb07a76f --- /dev/null +++ b/examples/interceptor-basics2/README.md @@ -0,0 +1,10 @@ +# interceptor-basics2 + +[Live demo](https://demo.thi.ng/umbrella/interceptor-basics2/) + +```bash +git clone https://github.com/thi-ng/umbrella.git +cd umbrella/examples/interceptor-basics2 +yarn install +yarn start +``` diff --git a/examples/interceptor-basics2/index.html b/examples/interceptor-basics2/index.html new file mode 100644 index 0000000000..067b568c89 --- /dev/null +++ b/examples/interceptor-basics2/index.html @@ -0,0 +1,58 @@ + + + + + + + + interceptor-basics + + + + +

This example demonstrates the use of @thi.ng/interceptors' event bus and interceptor driven event handling + features.

+

See sources for detailed comments (blog post forthcoming): +

+

+
+ + + + \ No newline at end of file diff --git a/examples/interceptor-basics2/package.json b/examples/interceptor-basics2/package.json new file mode 100644 index 0000000000..bca3773470 --- /dev/null +++ b/examples/interceptor-basics2/package.json @@ -0,0 +1,28 @@ +{ + "name": "interceptor-basics2", + "version": "0.0.1", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", + "start": "parcel index.html -p 8080 --open" + }, + "devDependencies": { + "parcel-bundler": "^1.9.7", + "terser": "^3.8.2", + "typescript": "^3.0.1" + }, + "dependencies": { + "@thi.ng/api": "latest", + "@thi.ng/atom": "latest", + "@thi.ng/hdom": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "browser": { + "process": false + } +} \ No newline at end of file diff --git a/examples/interceptor-basics2/src/index.ts b/examples/interceptor-basics2/src/index.ts new file mode 100644 index 0000000000..7027aeb40c --- /dev/null +++ b/examples/interceptor-basics2/src/index.ts @@ -0,0 +1,137 @@ +import { IObjectOf } from "@thi.ng/api/api"; +import { start } from "@thi.ng/hdom/start"; +import { EffectDef, EventDef, IDispatch } from "@thi.ng/interceptors/api"; +import { EV_SET_VALUE, EV_UPDATE_VALUE, FX_DISPATCH_NOW } from "@thi.ng/interceptors/api"; +import { EventBus } from "@thi.ng/interceptors/event-bus"; +import { ensureStateGreaterThan, ensureStateLessThan, trace } from "@thi.ng/interceptors/interceptors"; +import { Path } from "@thi.ng/paths"; + +/////////////////////////////////////////////////////////////////////// +// event name and handler definitions + +// best practice tip: +// define event & effect names as consts or enums and +// avoid hardcoded strings for easier refactoring +// additionally/alternatively define dispatch functions +const EV_INC = "inc-counter"; +const EV_DEC = "dec-counter"; +const EV_ADD_COUNTER = "add-counter"; +const EV_ADD_VALUE = "add-value"; + +const FX_ADD_COUNTER = "add-counter"; + +const events: IObjectOf = { + // these event handlers delegate to "updateVal" in same + // processing frame (using FX_DISPATCH_NOW) + // note how we also inject the predicate interceptors here to ensure + // counter values will be always be in the range between 0 .. 100 + [EV_INC]: [ + ensureStateLessThan(100, null, () => console.warn("eek, reached max")), + (_, [__, path]) => ({ [FX_DISPATCH_NOW]: [EV_ADD_VALUE, [path, 1]] }) + ], + [EV_DEC]: [ + ensureStateGreaterThan(0, null, () => console.warn("eek, reached min")), + (_, [__, path]) => ({ [FX_DISPATCH_NOW]: [EV_ADD_VALUE, [path, -1]] }) + ], + + // similar to the EV_INIT handler above, here we just delegate to the + // the built-in EV_UPDATE_VALUE handler to update a given path value. + // Additionally, we inject the `trace` interceptor to log the event + // each time it's triggered + [EV_ADD_VALUE]: [ + trace, + (_, [__, [path, y]]) => + ({ [FX_DISPATCH_NOW]: [EV_UPDATE_VALUE, [path, (x) => x + y]] }) + ], + + // this handler increments the `nextID` state value and + // triggers FX_ADD_COUNTER side effect with config options for the new counter + [EV_ADD_COUNTER]: (state) => ({ + [FX_DISPATCH_NOW]: [EV_ADD_VALUE, ["nextID", 1]], + // the FX_ADD_COUNTER side effect is defined further below + // here we simply prepare some configuration data for the new counter + [FX_ADD_COUNTER]: { + id: state.nextID, + start: ~~(Math.random() * 100), + color: ["gold", "orange", "springgreen", "yellow", "cyan"][~~(Math.random() * 5)] + } + }), +}; + +/////////////////////////////////////////////////////////////////////// +// skeleton for other side effects, ignore for now + +const effects: IObjectOf = { + +}; + +/////////////////////////////////////////////////////////////////////// +// components + +const button = (bus, event, label, id?) => + ["button", { id, onclick: () => bus.dispatch(event) }, label]; + +// counter component function +// calls to this function will be triggered via the "addCounter" event and its side effect +// (see further below) +const counter = (bus: IDispatch, path: Path, start = 0, color: string) => { + const view = bus.state.addView(path); + bus.dispatch([EV_SET_VALUE, [path, start]]); + return ["div.counter", + { style: { background: color } }, + () => view.deref() || 0, + ["div", + button(bus, [EV_DEC, view.path], "-"), + button(bus, [EV_INC, view.path], "+")]]; +} + +// main app +const app = () => { + // an array to store counter component instances + // (only using component local state for KISS reasons) + const counters = []; + + // create event bus with app state atom and configure with above handlers/effects + const bus = new EventBus(null, events, effects); + + // in addition to externally defined event handlers & side effects + // each type can also be added & remove dynamically + // here we define the FX_ADD_COUNTER side effect, responsible for + // creating a new `counter()` component + bus.addEffect(FX_ADD_COUNTER, + ({ id, color, start }, bus) => + counters.push(counter(bus, ["counters", id], start, color))); + + // add derived view subscription for updating JSON state trace + // (only executed when state changes) + const json = bus.state.addView([], (state) => JSON.stringify(state, null, 2)); + + // this not just initializes the given state value + // the changed state will also trigger the 1st DOM rendering (see returned function below) + bus.dispatch([EV_SET_VALUE, ["nextID", 0]]); + + // our actual root component function passed to hdom + const root = () => + ["div", + button(bus, [EV_ADD_COUNTER], "add counter", "addcounter"), + ["div", ...counters], + ["pre", json]]; + + return () => { + // here we do an optional fail fast check, a useful & energy saving + // approach for apps, which purely rely on the central app state. + // this example app is such a case and we can check if there were + // any events processed which caused a state change and only + // return the root component then (i.e. `processQueue()` returned `true`) + + // if there were no changes, we simply return nothing. + // hdom interprets this as a skipped frame (and does nothing until this + // function is called again during the next frame update cycle...) + if (bus.processQueue()) { + return root; + } + } +}; + +// kick off hdom render loop +start(app()); diff --git a/examples/interceptor-basics2/tsconfig.json b/examples/interceptor-basics2/tsconfig.json new file mode 100644 index 0000000000..b7d63aedf0 --- /dev/null +++ b/examples/interceptor-basics2/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} \ No newline at end of file diff --git a/examples/json-components/package.json b/examples/json-components/package.json index 4ebd4780f2..fb45923bdd 100644 --- a/examples/json-components/package.json +++ b/examples/json-components/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/login-form/package.json b/examples/login-form/package.json index af5dd8f583..edd5c6ed6d 100644 --- a/examples/login-form/package.json +++ b/examples/login-form/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/router-basics/package.json b/examples/router-basics/package.json index a53405c184..3b799bd14e 100644 --- a/examples/router-basics/package.json +++ b/examples/router-basics/package.json @@ -6,8 +6,9 @@ "author": "Karsten Schmidt", "license": "Apache-2.0", "scripts": { - "prepare": "mkdir -p out && cp -R assets out", - "build": "yarn prepare && parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "prepare": "yarn clean && mkdir -p out && cp -R assets out", + "build": "yarn prepare && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "yarn prepare && parcel index.html -p 8080 --open -d out" }, "dependencies": { diff --git a/examples/rstream-dataflow/package.json b/examples/rstream-dataflow/package.json index a2f66d9650..5c89544f15 100644 --- a/examples/rstream-dataflow/package.json +++ b/examples/rstream-dataflow/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/rstream-grid/package.json b/examples/rstream-grid/package.json index a033e8e19a..b351005a29 100644 --- a/examples/rstream-grid/package.json +++ b/examples/rstream-grid/package.json @@ -6,7 +6,8 @@ "author": "Karsten Schmidt", "license": "MIT", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "dependencies": { diff --git a/examples/rstream-hdom/package.json b/examples/rstream-hdom/package.json index cf746d6fa2..1030a0bdda 100644 --- a/examples/rstream-hdom/package.json +++ b/examples/rstream-hdom/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/svg-barchart/.gitignore b/examples/svg-barchart/.gitignore new file mode 100644 index 0000000000..0c5abcab62 --- /dev/null +++ b/examples/svg-barchart/.gitignore @@ -0,0 +1,5 @@ +.cache +out +node_modules +yarn.lock +*.js diff --git a/examples/svg-barchart/README.md b/examples/svg-barchart/README.md new file mode 100644 index 0000000000..6068c24e7b --- /dev/null +++ b/examples/svg-barchart/README.md @@ -0,0 +1,22 @@ +# svg-barchart + +[Live demo](http://demo.thi.ng/umbrella/svg-barchart/) + +SVG bar chart component & one-off rendering. + +![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/svg-barchart.png) + +```bash +git clone https://github.com/thi-ng/umbrella.git +cd umbrella/examples/svg-barchart +yarn install +yarn start +``` + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/svg-barchart/index.html b/examples/svg-barchart/index.html new file mode 100644 index 0000000000..19fad9011e --- /dev/null +++ b/examples/svg-barchart/index.html @@ -0,0 +1,16 @@ + + + + + + + svg-barchart + + + + +
+ + + diff --git a/examples/svg-barchart/package.json b/examples/svg-barchart/package.json new file mode 100644 index 0000000000..744136aa03 --- /dev/null +++ b/examples/svg-barchart/package.json @@ -0,0 +1,29 @@ +{ + "name": "svg-barchart", + "version": "0.0.1", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --detailed-report", + "start": "parcel index.html -p 8080 --open" + }, + "devDependencies": { + "parcel-bundler": "^1.9.7", + "terser": "^3.8.2", + "typescript": "^3.0.1" + }, + "dependencies": { + "@thi.ng/api": "latest", + "@thi.ng/atom": "latest", + "@thi.ng/rstream": "latest", + "@thi.ng/transducers-hdom": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "browser": { + "process": false + } +} diff --git a/examples/svg-barchart/src/index.ts b/examples/svg-barchart/src/index.ts new file mode 100644 index 0000000000..cdaa640e43 --- /dev/null +++ b/examples/svg-barchart/src/index.ts @@ -0,0 +1,97 @@ +import { clearDOM, renderOnce } from "@thi.ng/hdom"; +import { range } from "@thi.ng/transducers/iter/range"; +import { map } from "@thi.ng/transducers/xform/map"; +import { mapcat } from "@thi.ng/transducers/xform/mapcat"; + +// fit `x` from range (a,b) => (c,d) +const fit = (x, a, b, c, d) => (x - a) / (b - a) * (d - c) + c; + +// iterator of range mapped tuples: `[mapped, orig]` +const mappedRange = (from, to, step, start, end) => + map( + (n) => [fit(n, from, to, start, end), n], + range(from, to, step)); + +// syntax sugar to create SVG line +const line = (x1, y1, x2, y2) => ["line", { x1, y1, x2, y2 }]; + +// reusuable axis tick & label combo +const tick = (x1, y1, x2, y2, tx, ty, label) => [ + line(x1, y1, x2, y2), + ["text", { x: tx, y: ty, stroke: "none" }, label] +]; + +// mapping fn for x-axis ticks +const tickX = (y) => ([x, n]) => tick(x, y, x, y + 10, x, y + 20, n); + +// mapping fn for y-axis ticks +const tickY = (x) => ([y, n]) => tick(x - 10, y, x, y, x - 15, y, n); + +// x-axis with ticks as SVG group +const axisX = ({ axis: a, domain: d, range: r }) => + ["g", { "text-anchor": "middle" }, + line(a[0], a[2], a[1], a[2]), + mapcat(tickX(a[2]), mappedRange(d[0], d[1], d[2], r[0], r[1]))]; + +// y-axis with ticks as SVG group +const axisY = ({ axis: a, domain: d, range: r }) => + ["g", { "text-anchor": "end" }, + line(a[2], a[0], a[2], a[1]), + mapcat(tickY(a[2]), mappedRange(d[0], d[1], d[2], r[0], r[1]))]; + +// mapping fn to create a single bar from `[domainPos, value]` +const bar = ({ domain: xd, range: xr }, { domain: yd, range: yr }) => + ([xx, yy]) => { + const y = fit(yy, yd[0], yd[1], yr[0], yr[1]); + return ["rect", { + x: fit(xx, xd[0], xd[1], xr[0], xr[1]) - 5, + y, + width: 10, + height: yr[0] - y + }]; + }; + +// complete bar chart component +const barChart = (_, opts, values) => + ["svg", opts.attribs, + ["g", { stroke: opts.axis, fill: opts.axis }, + axisX(opts.x), + axisY(opts.y)], + ["g", { fill: opts.fill }, + map(bar(opts.x, opts.y), values)]]; + + +// one-off DOM creation +renderOnce( + ["div.ma2.sans-serif", + ["h1", "Bar chart example"], + [barChart, + { + attribs: { + width: 500, + height: 200, + "font-size": "10px", + "font-family": "Menlo, sans-serif" + }, + x: { + axis: [40, 490, 170], + domain: [1980, 2021, 10], + range: [60, 480] + }, + y: { + axis: [170, 10, 40], + domain: [0, 101, 25], + range: [160, 20] + }, + axis: "#666", + fill: "#0cc" + }, + map((year) => [year, Math.random() * 100], range(1980, 2020, 2)) + ] + ] +); + +if (process.env.NODE_ENV !== "production") { + const hot = (module).hot; + hot && hot.dispose(() => clearDOM(document.getElementById("app"))); +} \ No newline at end of file diff --git a/examples/svg-barchart/tsconfig.json b/examples/svg-barchart/tsconfig.json new file mode 100644 index 0000000000..bbf112cc18 --- /dev/null +++ b/examples/svg-barchart/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/examples/svg-particles/package.json b/examples/svg-particles/package.json index fa70720857..37ea3e844e 100644 --- a/examples/svg-particles/package.json +++ b/examples/svg-particles/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/svg-waveform/package.json b/examples/svg-waveform/package.json index 6343d08dfc..0bbc730228 100644 --- a/examples/svg-waveform/package.json +++ b/examples/svg-waveform/package.json @@ -6,7 +6,8 @@ "author": "Karsten Schmidt", "license": "MIT", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "dependencies": { diff --git a/examples/todo-list/package.json b/examples/todo-list/package.json index acff6ea8a1..6cf6d8e295 100644 --- a/examples/todo-list/package.json +++ b/examples/todo-list/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/transducers-hdom/package.json b/examples/transducers-hdom/package.json index 4a17ff330a..1e57752011 100644 --- a/examples/transducers-hdom/package.json +++ b/examples/transducers-hdom/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/triple-query/package.json b/examples/triple-query/package.json index 80a9971351..e347eb5c44 100644 --- a/examples/triple-query/package.json +++ b/examples/triple-query/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/examples/triple-query/src/components/triple-table.ts b/examples/triple-query/src/components/triple-table.ts index 2107d1f3de..c3f1ab3ad0 100644 --- a/examples/triple-query/src/components/triple-table.ts +++ b/examples/triple-query/src/components/triple-table.ts @@ -18,18 +18,18 @@ export const tripleTable = () => { }); return (ctx: AppContext, triples: any[], num: number, page: number) => { const [sid, sdir] = ctx.views.sort.deref(); - const icon = sdir ? "🔼" : "🔽"; + const icon = sdir ? "🔽" : "🔼"; return [section, "All triples", ` (${ctx.store.triples.length})`, [table, ["10%", "30%", "30%", "30%"], ["id", ...["subject", "predicate", "object"].map( - (x, i) => [eventLink, - ctx.ui.table.headlink, - [SET_SORT, i], - `${x} ${sid === i ? icon : ""}` - ] + (x, i) => + [eventLink, + ctx.ui.table.headlink, + [SET_SORT, i], + `${x} ${sid === i ? icon : ""}`] ) ], triples], diff --git a/examples/webgl/package.json b/examples/webgl/package.json index 9135ca86f4..cf6087a050 100644 --- a/examples/webgl/package.json +++ b/examples/webgl/package.json @@ -5,7 +5,8 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "parcel build index.html -d out --no-source-maps --no-cache --detailed-report", + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { diff --git a/package.json b/package.json index 14ff0c4f76..6507f79e1d 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "depgraph": "scripts/depgraph && git add assets/deps.png && git commit -m 'docs: update dep graph' && git push", "doc": "lerna run doc", "examples": "scripts/build-examples", - "pub": "lerna publish && yarn doc && scripts/upload-docs", + "pub": "lerna publish --registry https://registry.npmjs.org/ && yarn doc && scripts/upload-docs", "test": "yarn build && lerna run test" } } \ No newline at end of file diff --git a/packages/api/CHANGELOG.md b/packages/api/CHANGELOG.md index b1897709cb..627f601886 100644 --- a/packages/api/CHANGELOG.md +++ b/packages/api/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [4.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/api@4.1.1...@thi.ng/api@4.2.0) (2018-09-22) + + +### Features + +* **api:** add `IToHiccup` interface ([e390a54](https://github.com/thi-ng/umbrella/commit/e390a54)) + + + + + ## [4.1.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/api@4.1.0...@thi.ng/api@4.1.1) (2018-09-10) diff --git a/packages/api/package.json b/packages/api/package.json index 3f645d1331..bd56028e96 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/api", - "version": "4.1.1", + "version": "4.2.0", "description": "Common, generic types & interfaces for thi.ng projects", "main": "./index.js", "typings": "./index.d.ts", @@ -24,11 +24,11 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "dependencies": { - "@thi.ng/errors": "^0.1.7" + "@thi.ng/errors": "^0.1.8" }, "keywords": [ "compare", diff --git a/packages/api/src/api.ts b/packages/api/src/api.ts index 0bf5d75c77..c698bff645 100644 --- a/packages/api/src/api.ts +++ b/packages/api/src/api.ts @@ -412,6 +412,18 @@ export interface IImmutableStack { push(x: V): T; } +export interface IToHiccup { + /** + * Returns a thi.ng/hiccup compatible representation. The optional + * `ctx` arg is an arbitrary user context object passed to all + * hiccup components during serialization (or during DOM creation / + * update if used with thi.ng/hdom) + * + * @param ctx user context object + */ + toHiccup(ctx?: any): any; +} + /** * Interface for types offering observers of internal value changes. * Also see `@IWatch` decorator mixin. diff --git a/packages/associative/CHANGELOG.md b/packages/associative/CHANGELOG.md index 41b0441d4c..36784192b3 100644 --- a/packages/associative/CHANGELOG.md +++ b/packages/associative/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [0.6.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/associative@0.6.7-alpha.1...@thi.ng/associative@0.6.7) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/associative + + + + + ## [0.6.7-alpha.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/associative@0.6.7-alpha.0...@thi.ng/associative@0.6.7-alpha.1) (2018-09-17) diff --git a/packages/associative/package.json b/packages/associative/package.json index 016c48583f..b3bbaff460 100644 --- a/packages/associative/package.json +++ b/packages/associative/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/associative", - "version": "0.6.7-alpha.1", + "version": "0.6.7", "description": "Alternative Set & Map data type implementations with customizable equality semantics & supporting operations", "main": "./index.js", "typings": "./index.d.ts", @@ -24,17 +24,17 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "dependencies": { - "@thi.ng/api": "^4.1.1", - "@thi.ng/checks": "^1.5.9", - "@thi.ng/compare": "^0.1.7", - "@thi.ng/dcons": "^1.1.7-alpha.1", - "@thi.ng/equiv": "^0.1.9", - "@thi.ng/errors": "^0.1.7", - "@thi.ng/transducers": "^2.1.2-alpha.1" + "@thi.ng/api": "^4.2.0", + "@thi.ng/checks": "^1.5.10", + "@thi.ng/compare": "^0.1.8", + "@thi.ng/dcons": "^1.1.7", + "@thi.ng/equiv": "^0.1.10", + "@thi.ng/errors": "^0.1.8", + "@thi.ng/transducers": "^2.1.2" }, "keywords": [ "data structures", diff --git a/packages/atom/CHANGELOG.md b/packages/atom/CHANGELOG.md index 400805e00e..69f48278a0 100644 --- a/packages/atom/CHANGELOG.md +++ b/packages/atom/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [1.5.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/atom@1.5.3-alpha.1...@thi.ng/atom@1.5.3) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/atom + + + + + ## [1.5.3-alpha.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/atom@1.5.3-alpha.0...@thi.ng/atom@1.5.3-alpha.1) (2018-09-17) diff --git a/packages/atom/package.json b/packages/atom/package.json index 3ba102d946..a0d97f5cda 100644 --- a/packages/atom/package.json +++ b/packages/atom/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/atom", - "version": "1.5.3-alpha.1", + "version": "1.5.3", "description": "Mutable wrapper for immutable values", "main": "./index.js", "typings": "./index.d.ts", @@ -24,15 +24,15 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "dependencies": { - "@thi.ng/api": "^4.1.1", - "@thi.ng/checks": "^1.5.9", - "@thi.ng/equiv": "^0.1.9", - "@thi.ng/errors": "^0.1.7", - "@thi.ng/paths": "^1.6.2-alpha.0" + "@thi.ng/api": "^4.2.0", + "@thi.ng/checks": "^1.5.10", + "@thi.ng/equiv": "^0.1.10", + "@thi.ng/errors": "^0.1.8", + "@thi.ng/paths": "^1.6.2" }, "keywords": [ "cursor", diff --git a/packages/bench/CHANGELOG.md b/packages/bench/CHANGELOG.md index 384ed8a012..2af1471229 100644 --- a/packages/bench/CHANGELOG.md +++ b/packages/bench/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [0.2.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/bench@0.2.1...@thi.ng/bench@0.2.2) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/bench + + + + + ## [0.2.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/bench@0.2.0...@thi.ng/bench@0.2.1) (2018-09-10) diff --git a/packages/bench/package.json b/packages/bench/package.json index 1b3880fb47..c7ce4c2b2e 100644 --- a/packages/bench/package.json +++ b/packages/bench/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/bench", - "version": "0.2.1", + "version": "0.2.2", "description": "Basic benchmarking helpers", "main": "./index.js", "typings": "./index.d.ts", @@ -24,7 +24,7 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "keywords": [ diff --git a/packages/bitstream/CHANGELOG.md b/packages/bitstream/CHANGELOG.md index 7ab04aa98c..57e1dacaab 100644 --- a/packages/bitstream/CHANGELOG.md +++ b/packages/bitstream/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [0.4.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/bitstream@0.4.16...@thi.ng/bitstream@0.4.17) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/bitstream + + + + + ## [0.4.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/bitstream@0.4.15...@thi.ng/bitstream@0.4.16) (2018-09-10) diff --git a/packages/bitstream/package.json b/packages/bitstream/package.json index d306525697..3af2100af9 100644 --- a/packages/bitstream/package.json +++ b/packages/bitstream/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/bitstream", - "version": "0.4.16", + "version": "0.4.17", "description": "ES6 iterator based read/write bit streams & support for variable word widths", "main": "./index.js", "typings": "./index.d.ts", @@ -20,14 +20,14 @@ "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" }, "dependencies": { - "@thi.ng/errors": "^0.1.7" + "@thi.ng/errors": "^0.1.8" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "keywords": [ diff --git a/packages/cache/CHANGELOG.md b/packages/cache/CHANGELOG.md index 244843055f..82eb421aea 100644 --- a/packages/cache/CHANGELOG.md +++ b/packages/cache/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [0.2.24](https://github.com/thi-ng/umbrella/compare/@thi.ng/cache@0.2.24-alpha.1...@thi.ng/cache@0.2.24) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/cache + + + + + ## [0.2.24-alpha.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/cache@0.2.24-alpha.0...@thi.ng/cache@0.2.24-alpha.1) (2018-09-17) diff --git a/packages/cache/package.json b/packages/cache/package.json index 29dd918f5e..4262027a13 100644 --- a/packages/cache/package.json +++ b/packages/cache/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/cache", - "version": "0.2.24-alpha.1", + "version": "0.2.24", "description": "In-memory cache implementations with ES6 Map-like API and different eviction strategies", "main": "./index.js", "typings": "./index.d.ts", @@ -24,13 +24,13 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "dependencies": { - "@thi.ng/api": "^4.1.1", - "@thi.ng/dcons": "^1.1.7-alpha.1", - "@thi.ng/transducers": "^2.1.2-alpha.1" + "@thi.ng/api": "^4.2.0", + "@thi.ng/dcons": "^1.1.7", + "@thi.ng/transducers": "^2.1.2" }, "keywords": [ "cache", diff --git a/packages/checks/CHANGELOG.md b/packages/checks/CHANGELOG.md index a7854ae4c6..8210cfbf75 100644 --- a/packages/checks/CHANGELOG.md +++ b/packages/checks/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [1.5.10](https://github.com/thi-ng/umbrella/compare/@thi.ng/checks@1.5.9...@thi.ng/checks@1.5.10) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/checks + + + + + ## [1.5.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/checks@1.5.7...@thi.ng/checks@1.5.8) (2018-09-10) diff --git a/packages/checks/package.json b/packages/checks/package.json index 50cee456b9..25c876f39f 100644 --- a/packages/checks/package.json +++ b/packages/checks/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/checks", - "version": "1.5.9", + "version": "1.5.10", "description": "Single-function sub-modules for type, feature & value checks", "main": "./index.js", "typings": "./index.d.ts", @@ -24,7 +24,7 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "keywords": [ diff --git a/packages/compare/CHANGELOG.md b/packages/compare/CHANGELOG.md index 438c15d1cb..5d5abc360e 100644 --- a/packages/compare/CHANGELOG.md +++ b/packages/compare/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [0.1.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/compare@0.1.7...@thi.ng/compare@0.1.8) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/compare + + + + + ## [0.1.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/compare@0.1.6...@thi.ng/compare@0.1.7) (2018-09-10) diff --git a/packages/compare/package.json b/packages/compare/package.json index 79081ac907..de9145e5c6 100644 --- a/packages/compare/package.json +++ b/packages/compare/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/compare", - "version": "0.1.7", + "version": "0.1.8", "description": "Comparator with optional delegation for types implementing @thi.ng/api/ICompare interface", "main": "./index.js", "typings": "./index.d.ts", @@ -24,7 +24,7 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "keywords": [ diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index d9640fe96c..8cc6e27a0a 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [0.1.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/compose@0.1.2...@thi.ng/compose@0.1.3) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/compose + + + + + ## [0.1.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/compose@0.1.1...@thi.ng/compose@0.1.2) (2018-09-10) diff --git a/packages/compose/package.json b/packages/compose/package.json index 014e5a3b31..23c6081785 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/compose", - "version": "0.1.2", + "version": "0.1.3", "description": "Functional composition helpers", "main": "./index.js", "typings": "./index.d.ts", @@ -24,12 +24,12 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "dependencies": { - "@thi.ng/api": "^4.1.1", - "@thi.ng/errors": "^0.1.7" + "@thi.ng/api": "^4.2.0", + "@thi.ng/errors": "^0.1.8" }, "keywords": [ "composition", diff --git a/packages/csp/CHANGELOG.md b/packages/csp/CHANGELOG.md index bcc4f45385..81c5cdb076 100644 --- a/packages/csp/CHANGELOG.md +++ b/packages/csp/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [0.3.63](https://github.com/thi-ng/umbrella/compare/@thi.ng/csp@0.3.63-alpha.1...@thi.ng/csp@0.3.63) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/csp + + + + + ## [0.3.63-alpha.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/csp@0.3.63-alpha.0...@thi.ng/csp@0.3.63-alpha.1) (2018-09-17) diff --git a/packages/csp/package.json b/packages/csp/package.json index a25a803203..da12962977 100644 --- a/packages/csp/package.json +++ b/packages/csp/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/csp", - "version": "0.3.63-alpha.1", + "version": "0.3.63", "description": "ES6 promise based CSP implementation", "main": "./index.js", "typings": "./index.d.ts", @@ -28,15 +28,15 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "dependencies": { - "@thi.ng/api": "^4.1.1", - "@thi.ng/checks": "^1.5.9", - "@thi.ng/dcons": "^1.1.7-alpha.1", - "@thi.ng/errors": "^0.1.7", - "@thi.ng/transducers": "^2.1.2-alpha.1" + "@thi.ng/api": "^4.2.0", + "@thi.ng/checks": "^1.5.10", + "@thi.ng/dcons": "^1.1.7", + "@thi.ng/errors": "^0.1.8", + "@thi.ng/transducers": "^2.1.2" }, "keywords": [ "async", diff --git a/packages/dcons/CHANGELOG.md b/packages/dcons/CHANGELOG.md index 3990ca5013..51fab06abf 100644 --- a/packages/dcons/CHANGELOG.md +++ b/packages/dcons/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [1.1.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/dcons@1.1.7-alpha.1...@thi.ng/dcons@1.1.7) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/dcons + + + + + ## [1.1.7-alpha.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/dcons@1.1.7-alpha.0...@thi.ng/dcons@1.1.7-alpha.1) (2018-09-17) diff --git a/packages/dcons/package.json b/packages/dcons/package.json index 9cd1c2b653..7082ffd19e 100644 --- a/packages/dcons/package.json +++ b/packages/dcons/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dcons", - "version": "1.1.7-alpha.1", + "version": "1.1.7", "description": "Comprehensive doubly linked list structure w/ iterator support", "main": "./index.js", "typings": "./index.d.ts", @@ -24,16 +24,16 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "dependencies": { - "@thi.ng/api": "^4.1.1", - "@thi.ng/checks": "^1.5.9", - "@thi.ng/compare": "^0.1.7", - "@thi.ng/equiv": "^0.1.9", - "@thi.ng/errors": "^0.1.7", - "@thi.ng/transducers": "^2.1.2-alpha.1" + "@thi.ng/api": "^4.2.0", + "@thi.ng/checks": "^1.5.10", + "@thi.ng/compare": "^0.1.8", + "@thi.ng/equiv": "^0.1.10", + "@thi.ng/errors": "^0.1.8", + "@thi.ng/transducers": "^2.1.2" }, "keywords": [ "datastructure", diff --git a/packages/defmulti/CHANGELOG.md b/packages/defmulti/CHANGELOG.md index 24f9dabe55..e61fa7e8be 100644 --- a/packages/defmulti/CHANGELOG.md +++ b/packages/defmulti/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [0.3.10](https://github.com/thi-ng/umbrella/compare/@thi.ng/defmulti@0.3.9...@thi.ng/defmulti@0.3.10) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/defmulti + + + + + ## [0.3.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/defmulti@0.3.8...@thi.ng/defmulti@0.3.9) (2018-09-10) diff --git a/packages/defmulti/package.json b/packages/defmulti/package.json index cf3872a09d..ee25fd1a8f 100644 --- a/packages/defmulti/package.json +++ b/packages/defmulti/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/defmulti", - "version": "0.3.9", + "version": "0.3.10", "description": "Dynamically extensible multiple dispatch via user supplied dispatch function.", "main": "./index.js", "typings": "./index.d.ts", @@ -24,12 +24,12 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "dependencies": { - "@thi.ng/api": "^4.1.1", - "@thi.ng/errors": "^0.1.7" + "@thi.ng/api": "^4.2.0", + "@thi.ng/errors": "^0.1.8" }, "keywords": [ "ES6", diff --git a/packages/dgraph/CHANGELOG.md b/packages/dgraph/CHANGELOG.md index 73f69a2baa..e2e9f2419b 100644 --- a/packages/dgraph/CHANGELOG.md +++ b/packages/dgraph/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [0.2.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/dgraph@0.2.19-alpha.1...@thi.ng/dgraph@0.2.19) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/dgraph + + + + + ## [0.2.19-alpha.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/dgraph@0.2.19-alpha.0...@thi.ng/dgraph@0.2.19-alpha.1) (2018-09-17) diff --git a/packages/dgraph/package.json b/packages/dgraph/package.json index 708276775f..ad39294a43 100644 --- a/packages/dgraph/package.json +++ b/packages/dgraph/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dgraph", - "version": "0.2.19-alpha.1", + "version": "0.2.19", "description": "Type-agnostic directed acyclic graph (DAG) & graph operations", "main": "./index.js", "typings": "./index.d.ts", @@ -24,15 +24,15 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "dependencies": { - "@thi.ng/api": "^4.1.1", - "@thi.ng/associative": "^0.6.7-alpha.1", - "@thi.ng/equiv": "^0.1.9", - "@thi.ng/errors": "^0.1.7", - "@thi.ng/transducers": "^2.1.2-alpha.1" + "@thi.ng/api": "^4.2.0", + "@thi.ng/associative": "^0.6.7", + "@thi.ng/equiv": "^0.1.10", + "@thi.ng/errors": "^0.1.8", + "@thi.ng/transducers": "^2.1.2" }, "keywords": [ "data structure", diff --git a/packages/diff/CHANGELOG.md b/packages/diff/CHANGELOG.md index fa79fbd481..82c95b3d11 100644 --- a/packages/diff/CHANGELOG.md +++ b/packages/diff/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [1.1.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/diff@1.1.0...@thi.ng/diff@1.1.1) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/diff + + + + + ## [1.0.23](https://github.com/thi-ng/umbrella/compare/@thi.ng/diff@1.0.22...@thi.ng/diff@1.0.23) (2018-09-10) diff --git a/packages/diff/package.json b/packages/diff/package.json index 2885b958e6..2c10157b6c 100644 --- a/packages/diff/package.json +++ b/packages/diff/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/diff", - "version": "1.1.0", + "version": "1.1.1", "description": "Array & object Diff", "main": "./index.js", "typings": "./index.d.ts", @@ -22,12 +22,12 @@ "@types/mocha": "^5.2.5", "@types/node": "^10.5.5", "mocha": "^5.2.0", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "dependencies": { - "@thi.ng/api": "^4.1.1", - "@thi.ng/equiv": "^0.1.9" + "@thi.ng/api": "^4.2.0", + "@thi.ng/equiv": "^0.1.10" }, "keywords": [ "array", diff --git a/packages/dot/CHANGELOG.md b/packages/dot/CHANGELOG.md index eb7d10ee7e..c5e4c9f64d 100644 --- a/packages/dot/CHANGELOG.md +++ b/packages/dot/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [0.1.14](https://github.com/thi-ng/umbrella/compare/@thi.ng/dot@0.1.14-alpha.0...@thi.ng/dot@0.1.14) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/dot + + + + + ## [0.1.14-alpha.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/dot@0.1.13...@thi.ng/dot@0.1.14-alpha.0) (2018-09-17) diff --git a/packages/dot/package.json b/packages/dot/package.json index b90b281872..30ed861624 100644 --- a/packages/dot/package.json +++ b/packages/dot/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dot", - "version": "0.1.14-alpha.0", + "version": "0.1.14", "description": "Graphviz DOM abstraction as vanilla JS objects & serialization to DOT format", "main": "./index.js", "typings": "./index.d.ts", @@ -24,12 +24,12 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "dependencies": { - "@thi.ng/api": "^4.1.1", - "@thi.ng/checks": "^1.5.9" + "@thi.ng/api": "^4.2.0", + "@thi.ng/checks": "^1.5.10" }, "keywords": [ "ES6", diff --git a/packages/equiv/CHANGELOG.md b/packages/equiv/CHANGELOG.md index 3afeec1944..e669a808f3 100644 --- a/packages/equiv/CHANGELOG.md +++ b/packages/equiv/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [0.1.10](https://github.com/thi-ng/umbrella/compare/@thi.ng/equiv@0.1.9...@thi.ng/equiv@0.1.10) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/equiv + + + + + ## [0.1.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/equiv@0.1.7...@thi.ng/equiv@0.1.8) (2018-09-10) diff --git a/packages/equiv/package.json b/packages/equiv/package.json index 6db1beccb6..1d4cf84bb2 100644 --- a/packages/equiv/package.json +++ b/packages/equiv/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/equiv", - "version": "0.1.9", + "version": "0.1.10", "description": "Extensible deep equivalence checking for any data types", "main": "./index.js", "typings": "./index.d.ts", @@ -25,10 +25,9 @@ "benchmark": "^2.1.4", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, - "dependencies": {}, "keywords": [ "deep", "equality", diff --git a/packages/errors/CHANGELOG.md b/packages/errors/CHANGELOG.md index 33daa92a62..2635c94a5f 100644 --- a/packages/errors/CHANGELOG.md +++ b/packages/errors/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [0.1.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/errors@0.1.7...@thi.ng/errors@0.1.8) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/errors + + + + + ## [0.1.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/errors@0.1.6...@thi.ng/errors@0.1.7) (2018-09-10) diff --git a/packages/errors/package.json b/packages/errors/package.json index 71c7de15a6..621495fcf5 100644 --- a/packages/errors/package.json +++ b/packages/errors/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/errors", - "version": "0.1.7", + "version": "0.1.8", "description": "Custom error types and helper fns.", "main": "./index.js", "typings": "./index.d.ts", @@ -24,7 +24,7 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "keywords": [ diff --git a/packages/hdom-canvas/CHANGELOG.md b/packages/hdom-canvas/CHANGELOG.md index c73578b588..10b7c41aff 100644 --- a/packages/hdom-canvas/CHANGELOG.md +++ b/packages/hdom-canvas/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [0.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-canvas@0.1.0-alpha.1...@thi.ng/hdom-canvas@0.1.0) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/hdom-canvas + + + + + # [0.1.0-alpha.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-canvas@0.1.0-alpha.0...@thi.ng/hdom-canvas@0.1.0-alpha.1) (2018-09-17) diff --git a/packages/hdom-canvas/README.md b/packages/hdom-canvas/README.md index e600448306..7c6adb197e 100644 --- a/packages/hdom-canvas/README.md +++ b/packages/hdom-canvas/README.md @@ -45,7 +45,7 @@ Declarative canvas scenegraph & visualization for [@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/master/packages/hdom). This package provides a [re-usable canvas -component](https://github.com/thi-ng/umbrella/tree/develop/packages/hdom-canvas/src/index.ts#L66), +component](https://github.com/thi-ng/umbrella/tree/master/packages/hdom-canvas/src/index.ts#L66), which accepts child nodes defining a scene tree of different shape types in standard [@thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup) @@ -73,8 +73,8 @@ yarn add @thi.ng/hdom-canvas Please see these example projects for reference: -- [hdom-canvas-clock](https://github.com/thi-ng/umbrella/tree/develop/examples/hdom-canvas-clock) -- [hdom-canvas-shapes](https://github.com/thi-ng/umbrella/tree/develop/examples/hdom-canvas-shapes) +- [hdom-canvas-clock](https://github.com/thi-ng/umbrella/tree/master/examples/hdom-canvas-clock) +- [hdom-canvas-shapes](https://github.com/thi-ng/umbrella/tree/master/examples/hdom-canvas-shapes) ```ts import { start } from "@thi.ng/hdom"; diff --git a/packages/hdom-canvas/package.json b/packages/hdom-canvas/package.json index d4814b9b47..d23a371ce1 100644 --- a/packages/hdom-canvas/package.json +++ b/packages/hdom-canvas/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hdom-canvas", - "version": "0.1.0-alpha.1", + "version": "0.1.0", "description": "Declarative canvas scenegraph & visualization for @thi.ng/hdom", "main": "./index.js", "typings": "./index.d.ts", @@ -24,14 +24,14 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "dependencies": { - "@thi.ng/api": "^4.1.1", - "@thi.ng/checks": "^1.5.9", - "@thi.ng/diff": "^1.1.0", - "@thi.ng/hdom": "^5.0.0-alpha.1" + "@thi.ng/api": "^4.2.0", + "@thi.ng/checks": "^1.5.10", + "@thi.ng/diff": "^1.1.1", + "@thi.ng/hdom": "^5.0.0" }, "keywords": [ "ES6", diff --git a/packages/hdom-canvas/src/index.ts b/packages/hdom-canvas/src/index.ts index 3cd60486f8..051a2d8df2 100644 --- a/packages/hdom-canvas/src/index.ts +++ b/packages/hdom-canvas/src/index.ts @@ -101,27 +101,30 @@ const CTX_ATTRIBS = { * @param attribs canvas attribs * @param shapes shape components */ -export const canvas = (_, attribs, ...body: any[]) => { - const cattribs = { ...attribs }; - delete cattribs.__diff; - delete cattribs.__normalize; - const dpr = window.devicePixelRatio || 1; - if (dpr !== 1) { - !cattribs.style && (cattribs.style = {}); - cattribs.style.width = `${cattribs.width}px`; - cattribs.style.height = `${cattribs.height}px`; - cattribs.width *= dpr; - cattribs.height *= dpr; +export const canvas = { + render: (_, attribs, ...body: any[]) => { + const cattribs = { ...attribs }; + delete cattribs.__diff; + delete cattribs.__normalize; + const dpr = window.devicePixelRatio || 1; + if (dpr !== 1) { + !cattribs.style && (cattribs.style = {}); + cattribs.style.width = `${cattribs.width}px`; + cattribs.style.height = `${cattribs.height}px`; + cattribs.width *= dpr; + cattribs.height *= dpr; + } + return ["canvas", cattribs, + ["g", { + __impl: IMPL, + __diff: attribs.__diff !== false, + __normalize: attribs.__normalize !== false, + __release: attribs.__release === true, + __serialize: false, + __clear: attribs.__clear, + scale: dpr !== 1 ? dpr : null, + }, ...body]] } - return ["canvas", cattribs, - ["g", { - __impl: IMPL, - __diff: attribs.__diff !== false, - __normalize: attribs.__normalize !== false, - __release: attribs.__release === true, - __clear: attribs.__clear, - scale: dpr !== 1 ? dpr : null, - }, ...body]] }; export const createTree = (_: Partial, canvas: HTMLCanvasElement, tree: any) => { diff --git a/packages/hdom-components/CHANGELOG.md b/packages/hdom-components/CHANGELOG.md index 1222fa7277..919ab68804 100644 --- a/packages/hdom-components/CHANGELOG.md +++ b/packages/hdom-components/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## [2.2.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-components@2.2.6-alpha.1...@thi.ng/hdom-components@2.2.6) (2018-09-22) + +**Note:** Version bump only for package @thi.ng/hdom-components + + + + + ## [2.2.6-alpha.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-components@2.2.6-alpha.0...@thi.ng/hdom-components@2.2.6-alpha.1) (2018-09-17) diff --git a/packages/hdom-components/package.json b/packages/hdom-components/package.json index 6a92e60679..424eab2c22 100644 --- a/packages/hdom-components/package.json +++ b/packages/hdom-components/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hdom-components", - "version": "2.2.6-alpha.1", + "version": "2.2.6", "description": "Raw, skinnable UI & SVG components for @thi.ng/hdom", "main": "./index.js", "typings": "./index.d.ts", @@ -24,13 +24,13 @@ "@types/node": "^10.5.5", "mocha": "^5.2.0", "nyc": "^12.0.2", - "typedoc": "^0.11.1", + "typedoc": "^0.12.0", "typescript": "^3.0.1" }, "dependencies": { - "@thi.ng/api": "^4.1.1", - "@thi.ng/checks": "^1.5.9", - "@thi.ng/transducers": "^2.1.2-alpha.1", + "@thi.ng/api": "^4.2.0", + "@thi.ng/checks": "^1.5.10", + "@thi.ng/transducers": "^2.1.2", "@types/webgl2": "^0.0.4" }, "keywords": [ diff --git a/packages/hdom/CHANGELOG.md b/packages/hdom/CHANGELOG.md index 8db8d3a76e..5d2b5ff128 100644 --- a/packages/hdom/CHANGELOG.md +++ b/packages/hdom/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [5.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom@5.0.0-alpha.1...@thi.ng/hdom@5.0.0) (2018-09-22) + + +### Features + +* **hdom:** add renderOnce() ([5ef9cf0](https://github.com/thi-ng/umbrella/commit/5ef9cf0)) + + +### Performance Improvements + +* **hdom:** minor updates ([de17db8](https://github.com/thi-ng/umbrella/commit/de17db8)) + + + + + # [5.0.0-alpha.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom@5.0.0-alpha.0...@thi.ng/hdom@5.0.0-alpha.1) (2018-09-17) diff --git a/packages/hdom/README.md b/packages/hdom/README.md index 0c45d52010..e7aa14d541 100644 --- a/packages/hdom/README.md +++ b/packages/hdom/README.md @@ -10,28 +10,40 @@ This project is part of the - [About](#about) - [Minimal example #1: Local state, RAF update](#minimal-example-1-local-state-raf-update) - - [Minimal example #2 (reactive state & transducer update)](#minimal-example-2-reactive-state--transducer-update) + - [Minimal example #2: Reactive, push-based state & update](#minimal-example-2-reactive-push-based-state--update) + - [Minimal example #3: Immutable app state & interceptors](#minimal-example-3-immutable-app-state--interceptors) + - [Minimal example #4: Canvas scene tree / branch-local behavior](#minimal-example-4-canvas-scene-tree--branch-local-behavior) +- [How it works](#how-it-works) + - [The hdom data flow](#the-hdom-data-flow) + - [Nested arrays](#nested-arrays) + - [Attribute objects](#attribute-objects) + - [Pure functions and/or closures](#pure-functions-andor-closures) + - [Iterators](#iterators) + - [Interface support](#interface-support) + - [Component objects with life cycle methods](#component-objects-with-life-cycle-methods) + - [Event & state handling options](#event--state-handling-options) + - [Reusable components](#reusable-components) +- [Status](#status) - [Example projects](#example-projects) - [Realtime crypto candle chart](#realtime-crypto-candle-chart) - [Git commit log table](#git-commit-log-table) - [Interactive SVG grid generator](#interactive-svg-grid-generator) - - [Interactive additive waveform visualization & SVG visualization](#interactive-additive-waveform-visualization--svg-visualization) + - [Interactive additive waveform visualization](#interactive-additive-waveform-visualization) - [Dataflow graph SVG components](#dataflow-graph-svg-components) + - [Mouse gesture analysis](#mouse-gesture-analysis) - [Canvas based radial dial input widget](#canvas-based-radial-dial-input-widget) - [SPA with router and event bus](#spa-with-router-and-event-bus) - - [Multiple apps with & without shared state](#multiple-apps-with--without-shared-state) - - [Interceptor based event handling](#interceptor-based-event-handling) - - [Todo list (w/ undo/redo)](#todo-list-w-undoredo) - - [SVG particles](#svg-particles) - - [Component tree translation](#component-tree-translation) - - [Event & state handling options](#event--state-handling-options) - - [Reusable components](#reusable-components) -- [Status](#status) - [Installation](#installation) - [Dependencies](#dependencies) -- [Usage](#usage) - - [User context injection](#user-context-injection) - - [Component objects & life cycle methods](#component-objects--life-cycle-methods) +- [API & Usage](#api--usage) + - [start()](#start) + - [HDOMOpts config options](#hdomopts-config-options) + - [normalizeTree()](#normalizetree) + - [diffTree()](#difftree) + - [createDOM()](#createdom) + - [hydrateDOM()](#hydratedom) +- [User context](#user-context) + - [Behavior control attributes](#behavior-control-attributes) - [Benchmark](#benchmark) - [Authors](#authors) - [License](#license) @@ -40,53 +52,51 @@ This project is part of the ## About -Lightweight reactive DOM components & VDOM-ish implementation using only -vanilla JS data structures (arrays, objects with life cycle functions, -closures, iterators), based on -[@thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup). -hdom is *very* flexible and supports many different workflows and means -to perform DOM updates... - -- Use the full expressiveness of ES6 / TypeScript to define, annotate & - document components -- Clean, functional component composition and reuse -- No pre-processing / pre-compilation steps -- [Supports - SVG](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup-svg), - arbitrary elements, attributes, events -- Suitable for server side rendering (by passing the same data structure - to @thi.ng/hiccup's `serialize()`) and then "hydrating" listeners and - components with life cycle methods +Extensible, abstract, hierarchical UI component tree definition syntax & +differential tree updates using only vanilla JS data structures (arrays, +iterators, closures, attribute objects or objects with life cycle +functions, closures). By default targets the browser's native DOM, but +supports other arbitrary target implementations in a branch-local +manner, e.g. to [define scene graphs for a canvas +element](https://github.com/thi-ng/umbrella/tree/master/packages/hdom-canvas) +as part of the normal UI tree. + +Benefits: + +- Use the full expressiveness of ES6 / TypeScript to define user interfaces +- No enforced opinion about state handling, very flexible +- Clean, functional component composition & reuse +- No source pre-processing, pre-compilation or string interpolation - Less verbose than HTML / JSX, resulting in smaller file sizes -- Static components can be distributed as JSON (or [transform JSON - into components](https://github.com/thi-ng/umbrella/tree/master/examples/json-components)) +- Supports arbitrary elements (incl. SVG), attributes and events in + uniform, S-expression based syntax +- Supports branch-local custom update behaviors & arbitrary (e.g. + non-DOM) target data structures to which tree diffs are applied to +- Suitable for server-side rendering and then "hydrating" listeners and + components with life cycle methods on the client side +- Static components (or component templates) can be distributed as JSON - Optional user context injection (an arbitrary object passed to all - component functions) -- CSS conversion from JS objects for `style` attribs (for full - hiccup-based CSS-in-JS generation also see: + component functions embedded in the tree) +- Default implementation supports CSS conversion from JS objects for + `style` attribs (also see: [@thi.ng/hiccup-css](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup-css)) -- Auto-deref of embedded value wrappers which implement the - [`IDeref`](https://github.com/thi-ng/umbrella/tree/master/packages/api/api) - interface (e.g. atoms, cursors, derived views, streams etc.) -- Fairly fast (see benchmark example below) -- Only ~5KB gzipped - -In addition to the descriptions in this file, [further information and -examples are available in the -wiki](https://github.com/thi-ng/umbrella/wiki/hdom-recipes). - -Also see the [work-in-progress -ADRs](https://github.com/thi-ng/umbrella/tree/master/packages/hdom-components/adr/) -for component configuration. +- Auto-expansion of embedded values / types which implement the [`IToHiccup`](https://github.com/thi-ng/umbrella/tree/master/packages/api/src/api.ts#L415) or + [`IDeref`](https://github.com/thi-ng/umbrella/tree/master/packages/api/src/api.ts#L166) + interfaces (e.g. [atoms, cursors, derived views](https://github.com/thi-ng/umbrella/tree/master/packages/atom), [streams](https://github.com/thi-ng/umbrella/tree/master/packages/rstream) etc.) +- Fast (see benchmark example below) +- Only ~5.5KB gzipped ### Minimal example #1: Local state, RAF update +[Live demo](https://demo.thi.ng/umbrella/hdom-basics/) | +[standalone example](https://github.com/thi-ng/umbrella/tree/master/examples/hdom-basics) + ```ts import * as hdom from "@thi.ng/hdom"; // stateless component w/ params // the first arg is an auto-injected context object -// (not used here, see `hdom-context-basics` example for details) +// (not used here, details further below) const greeter = (_, name) => ["h1.title", "hello ", name]; // component w/ local state @@ -101,17 +111,13 @@ const app = () => { return ["div#app", [greeter, "world"], counter(), counter(100)]; }; -// start update loop (browser only, see diagram below) +// start RAF update & diff loop hdom.start(app(), { root: document.body }); -// alternatively apply DOM tree only once -// (stateful components won't update though) -hdom.createDOM(document.body, hdom.normalizeTree(app())); +// alternatively create DOM tree only once +hdom.createDOM({}, document.body, hdom.normalizeTree(app())); ``` -[Live demo](https://demo.thi.ng/umbrella/hdom-basics/) | -[standalone example](https://github.com/thi-ng/umbrella/tree/master/examples/hdom-basics) - Alternatively, use the same component function for browser or server side HTML serialization (Note: does not emit attributes w/ functions as values, e.g. a button's `onclick` attrib). @@ -123,17 +129,22 @@ console.log(serialize(app())); //

hello world

``` -### Minimal example #2 (reactive state & transducer update) +### Minimal example #2: Reactive, push-based state & update -This example uses the +This example uses +[@thi.ng/rstream](https://github.com/thi-ng/umbrella/tree/master/packages/rstream) +for reactive state values and the [@thi.ng/transducers-hdom](https://github.com/thi-ng/umbrella/tree/master/packages/transducers-hdom) -support library to perform reactive DOM updates (instead of regular +support library to perform push-based DOM updates (instead of regular diffing via RAF). +[Live demo](https://demo.thi.ng/umbrella/transducers-hdom/) | +[standalone example](https://github.com/thi-ng/umbrella/tree/master/examples/transducers-hdom) + ```ts -import * as rs from "@thi.ng/rstream/stream"; -import * as tx from "@thi.ng/rstream/transducers"; +import { fromInterval, stream, sync } from "@thi.ng/rstream/stream"; import { updateDOM } from "@thi.ng/rstream/transducers-hdom"; +import * as tx from "@thi.ng/rstream/transducers"; // root component function const app = ({ ticks, clicks }) => @@ -144,16 +155,18 @@ const app = ({ ticks, clicks }) => `${clicks} clicks`] ]; -// click stream (click counter) -const clickStream = rs.stream().transform(tx.scan(tx.count(-1))); +// transformed stream to count clicks +const clickStream = stream().transform(tx.scan(tx.count(-1))); +// seed +clickStream.next(0); // stream combinator // waits until all inputs have produced at least one value, -// then updates whenever any input has changed -rs.sync({ - // streams to synchronize +// then updates whenever either input has changed +sync({ + // streams to combine & synchronize src: { - ticks: rs.fromInterval(1000), + ticks: fromInterval(1000), clicks: clickStream, }, }).transform( @@ -162,146 +175,562 @@ rs.sync({ // apply hdom tree to real DOM updateDOM({ root: document.body }) ); +``` + +### Minimal example #3: Immutable app state & interceptors + +This example uses +[@thi.ng/interceptors](https://github.com/thi-ng/umbrella/tree/master/packages/interceptors) +for state & event handling and to skip DOM updates completely if not +needed. + +[Live demo](http://demo.thi.ng/umbrella/interceptor-basics/) | +[Source code](https://github.com/thi-ng/umbrella/tree/master/examples/interceptor-basics) + +```ts +import { Atom } from "@thi.ng/atom"; +import { start } from "@thi.ng/hdom"; +import { choices } from "@thi.ng/transducers"; +import * as icep from "@thi.ng/interceptors"; + +// infinite iterator of random color choices +const colors = choices(["cyan", "yellow", "magenta", "chartreuse"]); + +// central app state (initially empty) +const state = new Atom({}); + +// event bus & event handlers / interceptors +// each handler produces a number of effects (incl. state updates) +// see @thi.ng/interceptors for more details +const bus = new icep.EventBus(state, { + // initializes app state + "init": () => ({ + [icep.FX_STATE]: { clicks: 0, color: "grey" } + }), + // composed event handler + // increments `clicks` state value and + // delegates to another event + "inc-counter": [ + icep.valueUpdater("clicks", (x: number) => x + 1), + icep.dispatchNow(["randomize-color"]) + ], + // sets `colors` state value to a new random choice + "randomize-color": icep.valueUpdater( + "color", () => colors.next().value + ) +}); + +// start hdom update loop +start( + // this root component function will be executed via RAF. + // it first processes events and then only returns an updated + // component if there was a state update... + // DOM update will be skipped if the function returned null + ({ bus, state }) => bus.processQueue() ? + ["button", + { + style: { + padding: "1rem", + background: state.value.color + }, + onclick: () => bus.dispatch(["inc-counter"]) + }, + `clicks: ${state.value.clicks}`] : + null, + // hdom options incl. + // arbitrary user context object passed to all components + { ctx: { state, bus } } +); // kick off -clickStream.next(0); +bus.dispatch(["init"]); ``` -[Live demo](https://demo.thi.ng/umbrella/transducers-hdom/) | -[standalone example](https://github.com/thi-ng/umbrella/tree/master/examples/transducers-hdom) +### Minimal example #4: Canvas scene tree / branch-local behavior -## Example projects +This example uses the +[@thi.ng/hdom-canvas](https://github.com/thi-ng/umbrella/tree/master/packages/hdom-canvas) +component to support the inclusion of (virtual, non-DOM targets) shape +elements as part of the normal HTML component tree. A description of the +actual mechanism can be found further below and in the hdom-canvas +readme. -Most of the 25 -[examples](https://github.com/thi-ng/umbrella/tree/master/examples) -included in this repo are using this package in one way or another. -Please check them out to learn more. Each is heavily commented, incl. -best practice notes. +Related examples: -Non-exhaustive list: +- [Clock](https://github.com/thi-ng/umbrella/tree/master/examples/hdom-canvas-clock) +- [Functional doodling](https://github.com/thi-ng/umbrella/tree/master/examples/hdom-canvas-draw) +- [Shape & SVG conversion](https://github.com/thi-ng/umbrella/tree/master/examples/hdom-canvas-shapes) -### Realtime crypto candle chart +```ts +import { start } from "@thi.ng/hdom"; +import { canvas } from "@thi.ng/hdom-canvas"; -![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/crypto-chart.png) +start(() => + ["div", + ["h1", "Hello hdom"], + // the hdom-canvas component injects a custom branch-local + // implementation of the `HDOMImplementation` interface + // so that one can define virtual child elements representing + // shapes which will not become DOM nodes, but are translated + // into canvas API draw calls + [canvas, { width: 300, height: 300 }, + ["g", { stroke: "none", translate: [50, 50] }, + ["circle", { fill: "red" }, + [0, 0], 25 + 25 * Math.sin(Date.now() * 0.001)], + ["text", { fill: "#fff", align: "center", baseLine: "middle" }, + [0, 0], "Hello"] + ] + ] + ] +); +``` -[Source](https://github.com/thi-ng/umbrella/tree/master/examples/crypto-chart) | -[Live version](https://demo.thi.ng/umbrella/crypto-chart/) +## How it works -### Git commit log table +### The hdom data flow -![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/commit-table-ssr.png) +The usual hdom update process is based on the creation of an up-to-date +component tree, which is first normalized (expanded into a canonical +format) and the used to compute minimal edit set of the recursive +difference to previous DOM tree. -[Source](https://github.com/thi-ng/umbrella/tree/master/examples/commit-table-ssr) | -[Live version](https://demo.thi.ng/umbrella/commit-table-ssr/) +**Important**: -### Interactive SVG grid generator +- hdom uses a RAF render loop only by default, but is in absolutely +no way tied to this +- hdom used the browser DOM only by default, but supports custom target + implementations, which can be defined on branch-local basis in the + tree +- hdom NEVER tracks the real DOM, only its own trees (previous & current) +- hdom can be used **without** diffing, i.e. for compact, one-off DOM + creation -![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/rstream-grid.png) +![hdom dataflow](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/hdom-dataflow.png) -[Source](https://github.com/thi-ng/umbrella/tree/master/examples/rstream-grid) | -[Live version](https://demo.thi.ng/umbrella/rstream-grid/) +The syntax is inspired by Clojure's +[Hiccup](https://github.com/weavejester/hiccup) and +[Reagent](http://reagent-project.github.io/) projects, which themselves +were influenced on [prior art by Phil +Wadler](http://homepages.inf.ed.ac.uk/wadler/papers/next700/next700.pdf) +at Edinburgh University who pioneered this approach in Lisp back in +1999. hdom offers several additional features to these established +approaches. -### Interactive additive waveform visualization & SVG visualization +hdom components are usually nested, vanilla ES6 data structures without +any custom syntax, organized in an S-expression-like manner. This makes +them very amenable to being constructed inline, composed, transformed or +instrumented using the many ES6 language options available. -![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/svg-waveform.png) +### Nested arrays -[Source](https://github.com/thi-ng/umbrella/tree/master/examples/svg-waveform) | -[Live version](https://demo.thi.ng/umbrella/svg-waveform/) +No matter what the initial supported input format was, all components / +elements will eventually be transformed into a tree of nested arrays. +See [`normalizeTree()`](#normalizetree) further down for details. -### Dataflow graph SVG components +The first element of each array is used as tag and if the 2nd +element is a plain object, it will be used to define arbitrary +attributes and event listeners for that element. All further elements +are considered children of the current element. -![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/estuary.jpg) +Emmet-style tags with ID and/or classes are supported. -This is a preview of the WIP -[@thi.ng/estuary](https://github.com/thi-ng/umbrella/tree/feature/estuary/packages/estuary) -package: +```ts +["section#foo.bar.baz", + ["h3", { class: "title" }, "Hello world!"]] +``` -[Source](https://github.com/thi-ng/umbrella/tree/feature/estuary/packages/estuary) -| [Live version](https://demo.thi.ng/umbrella/estuary/) +Equivalent HTML: -### Canvas based radial dial input widget +```html +
+

Hello World!

+
+``` -![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/canvas-dial.png) +### Attribute objects -[Source](https://github.com/thi-ng/umbrella/tree/master/examples/canvas-dial) | -[Live version](https://demo.thi.ng/umbrella/canvas-dial/) +Attributes objects are used to define arbitrary attributes, CSS +properties and event listeners. The latter always have to be prefixed +with `on` and their values always must be functions (naturally). CSS +props are assigned to the `style` attribute, but given as JS object. -### SPA with router and event bus +```ts +["a", { + href: "#", + onclick: (e) => (e.preventDefault(), alert("hi")), + style: { + background: "#000", + color: "#fff", + padding: "1rem", + margin: "0.25rem" + } +}, "Say Hi"] +``` + +```html + +Say Hi +``` -Based on the `create-hdom-app` project scaffolding, this is one of the -more advanced demos, combining functionality of several other @thi.ng -packages. +Attribute values can be functions themselves and if so will be called +with the entire attributes object as sole argument. Same goes for CSS +property function values (which receive the entire `style` object). In +both cases, this supports the creation of derived values based on other +attribs: -[Source](https://github.com/thi-ng/umbrella/tree/master/examples/router-basics) -| [Live version](https://demo.thi.ng/umbrella/router-basics/) +```ts +const btAttribs = { + // event handler are always functions + onclick: (e)=> alert(e.target.id), + class: (attr) => `bt bt-${attr.id}`, + href: (attr) => `#${attr.id}`, +}; + +// reuse attribs object for different elements +["div", + ["a#foo", btAttribs, "Foo"], + ["button#bar", btAttribs, "Bar"]] +``` + +```html +
+ Foo + +
+``` -### Multiple apps with & without shared state +### Pure functions and/or closures -Devcards style BMI calculator(s) with basic SVG viz. +```ts +// inline definition +["ul#users", ["alice", "bob", "charlie"].map((x) => ["li", x])] -[Source](https://github.com/thi-ng/umbrella/tree/master/examples/devcards) -| [Live version](https://demo.thi.ng/umbrella/devcards/) +// reusable component +const unorderedList = (_, attribs, ...items) => + ["ul", attribs, ...items.map((x)=> ["li", x])]; -### Interceptor based event handling +[unorderedList, { id: "users"}, "alice", "bob", "charlie"] +``` -[Source](https://github.com/thi-ng/umbrella/tree/master/examples/interceptor-basics) -| [Live version](https://demo.thi.ng/umbrella/interceptor-basics/) +```html +
    +
  • alice
  • +
  • bob
  • +
  • charlie
  • +
+``` -### Todo list (w/ undo/redo) +Functions used in the "tag" (head) position of an element array are +treated as delayed execution mechanism and will only be called and +recursively expanded during tree normalization with the remaining array +elements passed as arguments. These component functions also receive an +arbitrary [user context object](#user-context) (not used for these +examples here) as additional first argument. -[Source](https://github.com/thi-ng/umbrella/tree/master/examples/todo-list) -| [Live version](https://demo.thi.ng/umbrella/todo-list/) +```ts +const iconButton = (_, icon, onclick, label) => + ["a.bt", { onclick }, ["i", {class: `fas fa-${icon}`}], label]; -### SVG particles +const alignButton = (_, type) => + [iconButton, `align-${type}`, () => alert(type), type]; -[Source](https://github.com/thi-ng/umbrella/tree/master/examples/svg-particles) -| [Live version](https://demo.thi.ng/umbrella/svg-particles/) +["div", + { style: { padding: "1rem" } }, + [alignButton, "left"], + [alignButton, "center"], + [alignButton, "right"]] +``` -### Component tree translation +```html + +
+ left + center + right +
+``` -The actual DOM update is based on the minimal edit set of the recursive -difference between the old and new DOM trees (both expressed as nested -JS arrays). Components can be defined as static arrays, closures or -objects with [life cycle methods](#lifecycle-methods) (init, render, -release). +Functions in other positions of an element array are also supported but +only receive the optional user context object as attribute. -**Note: hdom uses a RAF render loop only by default, but is absolutely -no way tied to this.** +```ts +const now = () => new Date().toLocaleString(); -![hdom dataflow](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/hdom-dataflow.png) +["footer", "Current date: ", now] +``` -The syntax is inspired by Clojure's -[Hiccup](https://github.com/weavejester/hiccup) and -[Reagent](http://reagent-project.github.io/) projects, however the -latter is a wrapper around React, whereas this library is standalone, -more low-level & less opinionated. +```html +
Current date: 9/22/2018, 1:46:41 PM
+``` + +### Iterators + +ES6 iteratables are supported out of the box and their use is encouraged +to avoid the unnecessary allocation of temporary objects caused by +chained application of `Array.map()` to transform raw state values into +components. However, since iterators can only be consumed once, please +see [this issue +comment](https://github.com/thi-ng/umbrella/issues/42#issuecomment-420094339) +for potential pitfalls. + +Please see the +[@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers) +package, which provides 130+ functions to create, compose and work with +iterator based pipelines. + +```ts +import { map, range } from "@thi.ng/transducers"; + +// map() returns an iterator +["ul", map((i) => ["li", i + 1], range(3))] +``` + +```html +
    +
  • 1
  • +
  • 2
  • +
  • 3
  • +
+``` + +### Interface support + +Any type implementing one of the +[`IToHiccup`](https://github.com/thi-ng/umbrella/tree/master/packages/api/src/api.ts#L415) +or +[`IDeref`](https://github.com/thi-ng/umbrella/tree/master/packages/api/src/api.ts#L166) +or interfaces will be auto-expanded during tree normalization. + +This currently includes the following types from other packages in this +repo, but also any user defined custom types: + +- [atoms, cursors, derived + views](https://github.com/thi-ng/umbrella/tree/master/packages/atom) +- [streams](https://github.com/thi-ng/umbrella/tree/master/packages/rstream) + +```ts +class Foo { + deref() { + return ["div.deref"]; + } +} + +// unlike `deref()`, the `toHiccup()` method +// receives current user context as argument +// (see section further below) +class Bar { + toHiccup(ctx) { + return ["div.hiccup", ctx && ctx.foo, this.value]; + } +} + +["div", new Foo(), new Bar()] +``` + +```html +
+
+
+
+``` + +### Component objects with life cycle methods + +Most components can be succinctly expressed via the options discussed so +far, though for some use cases we need to get a handle on the actual +underlying DOM element and can only fully initialize the component once +it's been mounted etc. For those cases components can be specified as +classes or plain objects implementing the following interface: + +```ts +interface ILifecycle { + /** + * Component init method. Called with the actual DOM element, + * hdom user context and any other args when the component is + * first used, but **after** `render()` has been called once already. + */ + init?(el: Element, ctx: any, ...args: any[]); + + /** + * Returns the hdom tree of this component. + * Note: Always will be called first (prior to `init`/`release`) + * to obtain the actual component definition used for diffing. + * Therefore might have to include checks if any local state + * has already been initialized via `init`. This is the only + * mandatory method which MUST be implemented. + * + * `render` is executed before `init` because `normalizeTree()` + * must obtain the component's hdom tree first before it can + * determine if an `init` is necessary. `init` itself will be + * called from `diffTree`, `createDOM` or `hydrateDOM()` in a later + * phase of processing. + */ + render(ctx: any, ...args: any[]): any; + + /** + * Called when the underlying DOM of this component is removed + * (or replaced). Intended for cleanup tasks. + */ + release?(ctx: any, ...args: any[]); +} +``` + +When the component is first used the order of execution is: `render` -> +`init`. The `release` method is only called when the component has been +removed / replaced (basically if it's not present in the new tree +anymore). **The `release` implementation should NOT manually call +`release()` on any children, since that's already handled by +`diffTree()`.** + +The rest `...args` provided are sourced from the component call site as +this simple example demonstrates: + +```ts +// wrap in closure to allow multiple instances +const canvas = () => { + return { + init: (el, ctx, { width, height }, msg, color = "red") => { + const c = el.getContext("2d"); + c.fillStyle = color; + c.fillRect(0, 0, width, height); + c.fillStyle = "white"; + c.textAlign = "center"; + c.fillText(msg, width / 2, height / 2); + }, + render: (ctx, attribs) => ["canvas", attribs], + }; +}; + +// usage scenario #1: static component +// inline initialization is okay here... +start( + [canvas(), { width: 100, height: 100 }, "Hello world"], + { root: document.body } +); + + +// usage scenario #2: dynamic component +// in this example, the root component itself is given as function, +// which is evaluated each frame. +// since `canvas()` is a higher order component it too produces +// a new instance with each call. therefore the canvas instance(s) +// need to be created beforehand +const app = () => { + // pre-instantiate canvases + const c1 = canvas(); + const c2 = canvas(); + // return root component function + return () => ["div", + // use canvas instances + [c1, { width: 100, height: 100 }, "Hello world"], + [c2, { width: 100, height: 100 }, "Goodbye world", "blue"] + ]; +}; + +start(app(), { root: document.body }); +``` ### Event & state handling options -Since this package is purely dealing with the translation of DOM trees, -any form of state / event handling or routing required by a full app is -out of scope. These features are provided by the following packages and -can be used in a mix & match manner: +Since this package is purely dealing with the translation of component +trees, any form of state / event handling or routing required by a full +app is out of scope. These features are provided by the following +packages and can be used in a mix & match manner. Since hdom components +are just plain functions/arrays, **any** solution can be used in +general. - [@thi.ng/atom](https://github.com/thi-ng/umbrella/tree/master/packages/atom) - [@thi.ng/interceptors](https://github.com/thi-ng/umbrella/tree/master/packages/interceptors) - [@thi.ng/router](https://github.com/thi-ng/umbrella/tree/master/packages/router) - [@thi.ng/rstream](https://github.com/thi-ng/umbrella/tree/master/packages/rstream) +- [@thi.ng/rstream-gestures](https://github.com/thi-ng/umbrella/tree/master/packages/rstream-gestures) +- [@thi.ng/rstream-graph](https://github.com/thi-ng/umbrella/tree/master/packages/rstream-graph) - [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers) +- [@thi.ng/transducers-hdom](https://github.com/thi-ng/umbrella/tree/master/packages/transducers-hdom) ### Reusable components A currently small (but growing) number of reusable components are provided by these packages: +- [@thi.ng/hdom-canvas](https://github.com/thi-ng/umbrella/tree/master/packages/hdom-canvas) - [@thi.ng/hdom-components](https://github.com/thi-ng/umbrella/tree/master/packages/hdom-components) - [@thi.ng/hiccup-svg](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup-svg) ## Status -The overall "API" is stable, but there's further work planned on -generalizing the approach beyond standard browser DOM use cases. The -project has been used for several projects in production since 2016. +Stable, in active development. The project has been used for several +projects in production since early 2016. + +## Example projects + +Most of the approx. 30 +[examples](https://github.com/thi-ng/umbrella/tree/master/examples) +included in this repo are using this package in one way or another. +Please check them out to learn more. Each is heavily commented, incl. +some best practice notes. + +Non-exhaustive list: + +### Realtime crypto candle chart + +![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/crypto-chart.png) + +[Source](https://github.com/thi-ng/umbrella/tree/master/examples/crypto-chart) | +[Live version](https://demo.thi.ng/umbrella/crypto-chart/) + +### Git commit log table + +![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/commit-table-ssr.png) + +[Source](https://github.com/thi-ng/umbrella/tree/master/examples/commit-table-ssr) | +[Live version](https://demo.thi.ng/umbrella/commit-table-ssr/) + +### Interactive SVG grid generator + +![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/rstream-grid.png) + +[Source](https://github.com/thi-ng/umbrella/tree/master/examples/rstream-grid) | +[Live version](https://demo.thi.ng/umbrella/rstream-grid/) + +### Interactive additive waveform visualization + +![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/svg-waveform.png) + +[Source](https://github.com/thi-ng/umbrella/tree/master/examples/svg-waveform) | +[Live version](https://demo.thi.ng/umbrella/svg-waveform/) + +### Dataflow graph SVG components + +![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/estuary.jpg) + +This is a preview of the WIP +[@thi.ng/estuary](https://github.com/thi-ng/umbrella/tree/feature/estuary/packages/estuary) +package: + +[Source](https://github.com/thi-ng/umbrella/tree/feature/estuary/packages/estuary) +| [Live version](https://demo.thi.ng/umbrella/estuary/) + +### Mouse gesture analysis + +![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/gesture-analysis.png) + +[Source](https://github.com/thi-ng/umbrella/tree/master/examples/gesture-analysis) +| [Live version](https://demo.thi.ng/umbrella/gesture-analysis) + +### Canvas based radial dial input widget + +![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/canvas-dial.png) + +[Source](https://github.com/thi-ng/umbrella/tree/master/examples/canvas-dial) | +[Live version](https://demo.thi.ng/umbrella/canvas-dial/) + +### SPA with router and event bus + +Based on the `create-hdom-app` project scaffolding... + +[Source](https://github.com/thi-ng/umbrella/tree/master/examples/router-basics) +| [Live version](https://demo.thi.ng/umbrella/router-basics/) ## Installation @@ -309,10 +738,12 @@ project has been used for several projects in production since 2016. yarn add @thi.ng/hdom ``` -Use the customizable +You can use the [create-hdom-app](https://github.com/thi-ng/create-hdom-app) project -generator to create a pre-configured app skeleton using @thi.ng/atom, -@thi.ng/hdom, @thi.ng/interceptors & @thi.ng/router: +generator to create one of several pre-configured app skeletons using +features from @thi.ng/atom, @thi.ng/hdom, @thi.ng/interceptors & +@thi.ng/router. Presets using @thi.ng/rstream for reactive state +handling will be added in the near future. ```bash yarn create hdom-app my-app @@ -330,40 +761,54 @@ yarn start - [@thi.ng/equiv](https://github.com/thi-ng/umbrella/tree/master/packages/equiv) - [@thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup) -## Usage +## API & Usage -Even though the overall approach should be obvious from the code -examples in this document, it's recommended to first study the +Even though the overall approach should be obvious from the various +examples in this document, it's still recommended to also study the [@thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup) -reference to learn about the basics of the approach and syntax used. -Both projects started in early 2016, have somewhat evolved -independently, however should be considered complementary. - -#### `start(tree: any, opts?: Partial): () => any` - -Main user function of this package. For most use cases, this function -should be the only one required in user code. It takes an hiccup tree -(array, function or component object w/ life cycle methods) and an -optional object of [DOM update -options](https://github.com/thi-ng/umbrella/tree/master/packages/hdom/src/api.ts#L19) -(also see below). Starts RAF update loop, in each iteration first -normalizing given tree, then computing diff to previous frame's tree and -applying any changes to the real DOM. The `ctx` option can be used for -passing arbitrary config data or state down into the hiccup component -tree. Any embedded component function in the tree will receive this -context object as first argument, as will life cycle methods in -component objects. See [context description](#user-context) further -below. - -**Selective updates**: No updates will be applied if the given hiccup -tree is `undefined` or `null` or a root component function returns no +reference to learn more about other possible syntax options to define +components. Both projects started in early 2016 and have somewhat +evolved independently, however should be considered complementary. + +### start() + +Params: + +- `tree: any` +- `opts?: Partial` +- `impl?: HDOMImplementation` + +Main user function. For most use cases, this function should be the only +one required in user code. It takes an hiccup tree (array, function or +component object w/ life cycle methods) and an optional object of [DOM +update +options](https://github.com/thi-ng/umbrella/tree/master/packages/hdom/src/api.ts#L44) +(also see section below), as well as an optional `HDOMImplementation`. +If the latter is not given, the `DEFAULT_IMPL` will be used, which +targets the browser DOM. Unless you want to create your own custom +implementation, this should never be changed. + +Starts RAF update loop, in each iteration first normalizing given tree, +then computing diff to previous frame's tree and applying any changes to +the real DOM. The `ctx` option can be used for passing arbitrary config +data or state down into the hiccup component tree. Any embedded +component function in the tree will receive this context object as first +argument, as will life cycle methods in component objects. See [context +description](#user-context) further below. + +#### Selective updates + +No updates will be applied if the current hiccup tree normalizes to +`undefined` or `null`, e.g. a root component function returning no value. This way a given root component function can do some state -handling of its own and implement fail-fast checks to determine no DOM -updates are necessary, saving effort re-creating a new hiccup tree and -request skipping DOM updates via this function. In this case, the -previous DOM tree is kept around until the root function returns a tree -again, which then is diffed and applied against the previous tree kept -as usual. Any number of frames may be skipped this way. +handling of its own and implement fail-fast checks and determine that no +DOM updates are necessary, saving effort re-creating a new hiccup tree +and request skipping DOM updates via this convention. In this case, the +previous DOM tree is kept around until the root function returns a valid +tree again, which then is diffed and applied against the previous tree +kept, as usual. Any number of frames may be skipped this way. This +pattern is often used when working with the [@thi.ng/interceptors +`EventBus`](https://github.com/thi-ng/umbrella/tree/master/packages/interceptors/src/event-bus.ts). **Important:** Unless the `hydrate` option is enabled, the parent element given is assumed to have NO children at the time when `start()` @@ -377,77 +822,59 @@ pre-existing DOM and the hdom trees will cause undefined behavior. `start` returns a function, which when called, immediately cancels the update loop. -#### `HDOMOpts` config options +### HDOMOpts config options Config options object passed to hdom's `start()` or [@thi.ng/transducers-hdom](https://github.com/thi-ng/umbrella/tree/master/packages/transducers-hdom)'s `updateDOM()`: -```ts -interface HDOMOpts { - /** - * Root element or ID (default: "app"). - */ - root?: Element | string; - /** - * Arbitrary user context object, passed to all component functions - * embedded in the tree. - */ - ctx?: any; - /** - * If true (default), all text content will be wrapped in `` - * elements. Spans will never be created inside