diff --git a/assets/screenshots/canvas-dial.png b/assets/screenshots/canvas-dial.png
new file mode 100644
index 0000000000..b0503c2ac9
Binary files /dev/null and b/assets/screenshots/canvas-dial.png differ
diff --git a/assets/screenshots/commit-table-ssr.png b/assets/screenshots/commit-table-ssr.png
new file mode 100644
index 0000000000..17bb736c5a
Binary files /dev/null and b/assets/screenshots/commit-table-ssr.png differ
diff --git a/assets/crypto-chart.png b/assets/screenshots/crypto-chart.png
similarity index 100%
rename from assets/crypto-chart.png
rename to assets/screenshots/crypto-chart.png
diff --git a/assets/screenshots/estuary.jpg b/assets/screenshots/estuary.jpg
new file mode 100644
index 0000000000..63f6d12c97
Binary files /dev/null and b/assets/screenshots/estuary.jpg differ
diff --git a/assets/iges.png b/assets/screenshots/iges.png
similarity index 100%
rename from assets/iges.png
rename to assets/screenshots/iges.png
diff --git a/assets/screenshots/rstream-grid.png b/assets/screenshots/rstream-grid.png
new file mode 100644
index 0000000000..07ec344a90
Binary files /dev/null and b/assets/screenshots/rstream-grid.png differ
diff --git a/assets/screenshots/svg-waveform.png b/assets/screenshots/svg-waveform.png
new file mode 100644
index 0000000000..29de537048
Binary files /dev/null and b/assets/screenshots/svg-waveform.png differ
diff --git a/examples/README.md b/examples/README.md
index cf3c9dcfbc..e18bb82346 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -4,27 +4,30 @@ This directory contains a growing number of standalone example projects, includi
If you want to [contribute](../CONTRIBUTING.md) an example, please get in touch via PR, issue tracker, email or twitter!
-| # | Name | Description | Packages of interest | Difficulty |
-|----|----------------------------------------------|-----------------------------------------------------|-------------------------------------------------------------------|--------------|
-| 1 | [async-effect](./async-effect) | Async side effect handling (JSON I/O) | atom, hdom, interceptors | intermediate |
-| 2 | [cellular-automata](./cellular-automata) | Transducer based, customizable 2D cellular automata | hdom, hdom-components, transducers | basic |
-| 3 | [crypto-chart](./crypto-chart) | Interactive rstream & transducer based SVG chart | hdom, hiccup-svg, rstream, transducers | advanced |
-| 4 | [dashboard](./cellular-automata) | Barebones components w/ local state | hdom, transducers | basic |
-| 5 | [devcards](./devcards) | Multiple app instances with/without shared state | atom, hdom | intermediate |
-| 6 | [hdom-basics](./hdom-basics) | Hello world | hdom, hiccup | basic |
-| 7 | [hdom-benchmark](./hdom-benchmark) | hdom rendering perf / stress test, FPS counter | hdom, rstream, transducers | intermediate |
-| 8 | [hdom-theme-adr-0003](./hdom-theme-adr-0003) | hdom themed components proposal | hdom | intermediate |
-| 9 | [interceptor-basics](./hdom-benchmark) | Event handling w/ interceptors and side effects | atom, hdom, interceptors | intermediate |
-| 10 | [json-components](./json-components) | JSON->component transformation, live editor | hdom, transducers | intermediate |
-| 11 | [login-form](./login-form) | Basic SPA without router | atom, hdom | intermediate |
-| 12 | [pointfree-svg](./pointfree-svg) | Generate SVG using pointfree DSL | hiccup, hiccup-svg, pointfree-lang | intermediate |
-| 13 | [router-basics](./router-basics) | Complete mini SPA | atom, hdom, interceptors, router | advanced |
-| 14 | [rstream-dataflow](./rstream-dataflow) | Dataflow graph | atom, hdom, rstream, rstream-gestures, rstream-graph, transducers | intermediate |
-| 15 | [rstream-grid](./rstream-grid) | Dataflow graph SVG grid | atom, hdom, hiccup-svg, interceptors, rstream-graph, transducers | advanced |
-| 16 | [rstream-hdom](./rstream-hdom) | rstream based UI updates & state handling | hdom, rstream, transducers | intermediate |
-| 17 | [svg-particles](./svg-particles) | hdom SVG generation / animation | hdom, transducers | basic |
-| 18 | [svg-waveform](./svg-waveform) | hdom SVG generation / undo history | atom, hdom, hiccup-svg, interceptors, iterators | intermediate |
-| 19 | [todo-list](./todo-list) | Canonical Todo list with undo/redo | atom, hdom, transducers | intermediate |
-| 20 | [transducers-hdom](./transducers-hdom) | Transducer & rstream based hdom UI updates | hdom, rstream, transducers-hdom | basic |
-| 21 | [triple-query](./triple-query) | Triple store query results & sortable table | atom, hdom, hdom-components, rstream-query, transducers | intermediate |
-| 22 | [webgl](./webgl) | Canvas component handling | hdom, hdom-components | basic |
+| # | Name | Description | Packages of interest | Difficulty |
+|----|----------------------------------------------|----------------------------------------------------------|-------------------------------------------------------------------|--------------|
+| 1 | [async-effect](./async-effect) | Async side effect handling (JSON I/O) | atom, hdom, interceptors | intermediate |
+| 2 | [canvas-dial](./canvas-dial) | Canvas dial component w/ mouse & touch events | hdom, rstream, rstream-gestures, transducers, transducers-hdom | intermediate |
+| 3 | [cellular-automata](./cellular-automata) | Transducer based, customizable 2D cellular automata | hdom, hdom-components, transducers | basic |
+| 4 | [commit-table-ssr](./commit-table-ssr) | Server-side & static file rendering of hiccup components | hiccup, transducers | intermediate |
+| 5 | [crypto-chart](./crypto-chart) | Interactive rstream & transducer based SVG chart | hdom, hiccup-svg, rstream, transducers | advanced |
+| 6 | [dashboard](./dashboard) | Barebones components w/ local state | hdom, transducers | basic |
+| 7 | [devcards](./devcards) | Multiple app instances with/without shared state | atom, hdom | intermediate |
+| 8 | [hdom-basics](./hdom-basics) | Hello world | hdom, hiccup | basic |
+| 9 | [hdom-benchmark](./hdom-benchmark) | hdom rendering perf / stress test, FPS counter | hdom, rstream, transducers | intermediate |
+| 10 | [hdom-theme-adr-0003](./hdom-theme-adr-0003) | hdom themed components proposal | hdom | intermediate |
+| 11 | [hydrate-basics](./hydrate-basics) | hiccup / hdom DOM hydration | hiccup, hdom | intermediate |
+| 12 | [interceptor-basics](./interceptor-basics) | Event handling w/ interceptors and side effects | atom, hdom, interceptors | intermediate |
+| 13 | [json-components](./json-components) | JSON->component transformation, live editor | hdom, transducers | intermediate |
+| 14 | [login-form](./login-form) | Basic SPA without router | atom, hdom | intermediate |
+| 15 | [pointfree-svg](./pointfree-svg) | Generate SVG using pointfree DSL | hiccup, hiccup-svg, pointfree-lang | intermediate |
+| 16 | [router-basics](./router-basics) | Complete mini SPA | atom, hdom, interceptors, router | advanced |
+| 17 | [rstream-dataflow](./rstream-dataflow) | Dataflow graph | atom, hdom, rstream, rstream-gestures, rstream-graph, transducers | intermediate |
+| 18 | [rstream-grid](./rstream-grid) | Dataflow graph SVG grid | atom, hdom, hiccup-svg, interceptors, rstream-graph, transducers | advanced |
+| 19 | [rstream-hdom](./rstream-hdom) | rstream based UI updates & state handling | hdom, rstream, transducers | intermediate |
+| 20 | [svg-particles](./svg-particles) | hdom SVG generation / animation | hdom, transducers | basic |
+| 21 | [svg-waveform](./svg-waveform) | hdom SVG generation / undo history | atom, hdom, hiccup-svg, interceptors, iterators | intermediate |
+| 22 | [todo-list](./todo-list) | Canonical Todo list with undo/redo | atom, hdom, transducers | intermediate |
+| 23 | [transducers-hdom](./transducers-hdom) | Transducer & rstream based hdom UI updates | hdom, rstream, transducers-hdom | basic |
+| 24 | [triple-query](./triple-query) | Triple store query results & sortable table | atom, hdom, hdom-components, rstream-query, transducers | intermediate |
+| 25 | [webgl](./webgl) | Canvas component handling | hdom, hdom-components | basic |
\ No newline at end of file
diff --git a/examples/async-effect/src/index.ts b/examples/async-effect/src/index.ts
index f7f1af5a9f..f60a8c5da1 100644
--- a/examples/async-effect/src/index.ts
+++ b/examples/async-effect/src/index.ts
@@ -88,4 +88,4 @@ const app = () => {
}
};
-start("app", app());
+start(app());
diff --git a/examples/canvas-dial/.gitignore b/examples/canvas-dial/.gitignore
new file mode 100644
index 0000000000..9c418ce79f
--- /dev/null
+++ b/examples/canvas-dial/.gitignore
@@ -0,0 +1,3 @@
+node_modules
+yarn.lock
+*.js
diff --git a/examples/canvas-dial/README.md b/examples/canvas-dial/README.md
new file mode 100644
index 0000000000..d74977360d
--- /dev/null
+++ b/examples/canvas-dial/README.md
@@ -0,0 +1,21 @@
+# canvas-dial
+
+[Live demo](http://demo.thi.ng/umbrella/canvas-dial/)
+
+Customizable canvas-based radial dial component with mouse & touch
+support.
+
+```bash
+git clone https://github.com/thi-ng/umbrella.git
+cd umbrella/examples/canvas-dial
+yarn install
+yarn start
+```
+
+## Authors
+
+- Karsten Schmidt
+
+## License
+
+© 2018 Karsten Schmidt // Apache Software License 2.0
diff --git a/examples/canvas-dial/index.html b/examples/canvas-dial/index.html
new file mode 100644
index 0000000000..62ff6957ad
--- /dev/null
+++ b/examples/canvas-dial/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+ canvas-dial
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/canvas-dial/package.json b/examples/canvas-dial/package.json
new file mode 100644
index 0000000000..de2be1f868
--- /dev/null
+++ b/examples/canvas-dial/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "canvas-dial",
+ "version": "0.0.1",
+ "repository": "https://github.com/thi-ng/umbrella",
+ "author": "Karsten Schmidt ",
+ "license": "Apache-2.0",
+ "scripts": {
+ "build": "webpack --mode production --display-reasons --display-modules",
+ "start": "webpack-dev-server --open --mode development --devtool inline-source-map"
+ },
+ "devDependencies": {
+ "ts-loader": "^4.4.2",
+ "typescript": "^3.0.1",
+ "webpack": "^4.16.3",
+ "webpack-cli": "^3.1.0",
+ "webpack-dev-server": "^3.1.5"
+ },
+ "dependencies": {
+ "@thi.ng/api": "latest",
+ "@thi.ng/checks": "latest",
+ "@thi.ng/hdom": "latest",
+ "@thi.ng/hdom-components": "latest",
+ "@thi.ng/rstream": "latest",
+ "@thi.ng/rstream-gestures": "latest",
+ "@thi.ng/strings": "latest",
+ "@thi.ng/transducers": "latest"
+ }
+}
\ No newline at end of file
diff --git a/examples/canvas-dial/src/dial.ts b/examples/canvas-dial/src/dial.ts
new file mode 100644
index 0000000000..139f8e4d8d
--- /dev/null
+++ b/examples/canvas-dial/src/dial.ts
@@ -0,0 +1,209 @@
+import { Fn } from "@thi.ng/api/api";
+import { isString } from "@thi.ng/checks/is-string";
+import { canvas2D } from "@thi.ng/hdom-components/canvas";
+import { GestureEvent, gestureStream, GestureType } from "@thi.ng/rstream-gestures";
+import { Subscription } from "@thi.ng/rstream/subscription";
+import { peek } from "@thi.ng/transducers/func/peek";
+import { fitClamped1 } from "@thi.ng/vectors/math";
+import { heading2, sub2 } from "@thi.ng/vectors/vec2";
+
+/**
+ * Dial component options.
+ */
+export interface DialOpts {
+ /**
+ * Dial center X (normalized)
+ * Default: 0.5
+ */
+ cx: number;
+ /**
+ * Dial center Y (normalized)
+ * Default: 0.5
+ */
+ cy: number;
+ /**
+ * Inner radius (normalized)
+ * Default: 0.5
+ */
+ r1: number;
+ /**
+ * Outer radius (normalized)
+ * Default: 0.99
+ */
+ r2: number;
+ /**
+ * Dial min value
+ * Default: 0
+ */
+ min: number;
+ /**
+ * Dial min value
+ * Default: 1
+ */
+ max: number;
+ /**
+ * Orientation / start angle (in radians)
+ * Default: PI/2
+ */
+ base: number;
+ /**
+ * Angular gap between min / max values
+ * Default: PI/10
+ */
+ gap: number;
+ /**
+ * Fill color (or gradient) for value area
+ * Default: black
+ */
+ color: string | GradientDef;
+ /**
+ * Fill color (or gradient) for background ring
+ * Default: rgba(0,0,0,0.1)
+ */
+ bgColor: string | GradientDef;
+ /**
+ * Label formatter. No label will be displayed, if missing.
+ */
+ label: (x: number) => string;
+ /**
+ * Label Y offset from `cy`
+ * Default: 0
+ */
+ labelYOffset: number;
+ /**
+ * Default: black
+ */
+ labelColor: string;
+ /**
+ * Label font CSS string
+ * Default (10px sans-serif)
+ */
+ font: string;
+ /**
+ * Event callback (receives new dial value)
+ */
+ onchange: Fn;
+}
+
+/**
+ * Multi-stop linear gradient definition.
+ */
+export interface GradientDef {
+ /**
+ * Start point (normalized)
+ */
+ from: number[];
+ /**
+ * End point (normalized)
+ */
+ to: number[];
+ /**
+ * Color stops (position normalized)
+ */
+ stops: [number, string][];
+}
+
+const PI = Math.PI;
+const TAU = 2 * PI;
+
+/**
+ * HOF component. Returns pre-configured dial component.
+ *
+ * @param opts
+ */
+export const dial = (opts: Partial) => {
+ opts = {
+ cx: 0.5,
+ cy: 0.5,
+ r1: 0.5,
+ r2: 0.99,
+ min: 0,
+ max: 1,
+ base: PI * 0.5,
+ gap: PI * 0.1,
+ color: "black",
+ bgColor: "rgba(0,0,0,0.1)",
+ labelColor: "black",
+ labelYOffset: 0,
+ font: "10px sans-serif",
+ ...opts
+ };
+ let events: Subscription;
+ let cx, cy;
+ const startTheta = opts.base + opts.gap / 2;
+
+ const drawRing = (ctx: CanvasRenderingContext2D, amount: number, col: any) => {
+ const endTheta = startTheta + (TAU - opts.gap) * amount;
+ ctx.fillStyle = col;
+ ctx.beginPath();
+ ctx.arc(cx, cy, opts.r2, startTheta, endTheta, false);
+ ctx.arc(cx, cy, opts.r1, endTheta, startTheta, true);
+ ctx.fill();
+ };
+
+ const makeGradient = (el: HTMLCanvasElement, ctx: CanvasRenderingContext2D, def: GradientDef) => {
+ const g = ctx.createLinearGradient(
+ def.from[0] * el.width, def.from[1] * el.height,
+ def.to[0] * el.width, def.to[1] * el.height
+ );
+ def.stops.forEach(([pos, col]) => g.addColorStop(pos, col));
+ return g;
+ };
+
+ return canvas2D({
+
+ init: (el, ctx) => {
+ cx = el.width * opts.cx;
+ cy = el.height * opts.cy;
+ ctx.strokeStyle = "none";
+ ctx.textAlign = "center";
+ ctx.textBaseline = "middle";
+ ctx.font = opts.font;
+ const scale = Math.min(cx, cy);
+ opts.r1 *= scale;
+ opts.r2 *= scale;
+ if (!isString(opts.bgColor)) {
+ opts.bgColor = makeGradient(el, ctx, opts.bgColor);
+ }
+ if (!isString(opts.color)) {
+ opts.color = makeGradient(el, ctx, opts.color);
+ }
+ if (opts.onchange) {
+ // add interaction event stream (mouse & touch)
+ // configure stream to return scaled coords (devicePixelRatio)
+ events = gestureStream(el, { scale: true })
+ .subscribe({
+ next: (e) => {
+ if (e[0] === GestureType.START || e[0] === GestureType.DRAG) {
+ let theta = heading2(sub2(e[1].pos, [cx, cy])) - startTheta;
+ if (theta < 0) theta += TAU;
+ theta %= TAU;
+ opts.onchange.call(
+ null,
+ fitClamped1(Math.min(theta / (TAU - opts.gap)), 0, 1, opts.min, opts.max)
+ );
+ }
+ }
+ });
+ }
+ },
+
+ // clean up gesture event stream when component is released
+ release: () => {
+ events && events.unsubscribe();
+ },
+
+ // there're a few args we're not interested in here, so we use var args instead.
+ // the dial value is the last arg
+ update: (el, ctx, ...args: any[]) => {
+ const val = peek(args);
+ ctx.clearRect(0, 0, el.width, el.height);
+ drawRing(ctx, 1, opts.bgColor);
+ drawRing(ctx, fitClamped1(val, opts.min, opts.max, 0.005, 1), opts.color);
+ if (opts.label) {
+ ctx.fillStyle = opts.labelColor;
+ ctx.fillText(opts.label(val), cx, cy + opts.labelYOffset);
+ }
+ }
+ });
+};
diff --git a/examples/canvas-dial/src/index.ts b/examples/canvas-dial/src/index.ts
new file mode 100644
index 0000000000..b3fe03cc38
--- /dev/null
+++ b/examples/canvas-dial/src/index.ts
@@ -0,0 +1,76 @@
+import { stream } from "@thi.ng/rstream/stream";
+import { sync } from "@thi.ng/rstream/stream-sync";
+import { percent } from "@thi.ng/strings/percent";
+import { updateDOM } from "@thi.ng/transducers-hdom";
+import { comp } from "@thi.ng/transducers/func/comp";
+import { map } from "@thi.ng/transducers/xform/map";
+
+import { dial } from "./dial";
+
+// hdom context & app state object
+export const ctx = {
+ // streams to hold dial values
+ streams: {
+ a: stream(),
+ b: stream(),
+ c: stream(),
+ },
+ // component styling
+ ui: {
+ root: { class: "vh-100 flex justify-center items-center" },
+ dial: { width: 100, height: 100, class: "pointer ma1" },
+ }
+};
+
+/**
+ * This HOF (higher-order function) returns a mapping function which
+ * receives a tuple of object of all current stream values and returns a
+ * hdom root component. It will be used by the `sync()` construct
+ * further below.
+ *
+ * The dial components used here are HOFs themselves and therefore must
+ * be pre-initialized before use.
+ */
+const app = () => {
+ const dialA = dial({
+ r1: 0.5,
+ color: { from: [0, 0], to: [1, 1], stops: [[0, "#075"], [1, "#6f9"]] },
+ font: "20px Menlo",
+ label: (x) => percent(0)(x),
+ onchange: (x) => ctx.streams.a.next(x)
+ });
+ const dialB = dial({
+ r1: 0.66,
+ base: -Math.PI / 2,
+ gap: Math.PI / 2,
+ color: { from: [0, 0], to: [1, 0.75], stops: [[0, "#00f"], [0.5, "#f60"], [1, "#ff0"]] },
+ font: "20px Menlo",
+ label: (x) => percent(1)(x),
+ onchange: (x) => ctx.streams.b.next(x)
+ });
+ const dialC = dial({
+ r1: 0.75,
+ gap: Math.PI,
+ color: { from: [0, 0], to: [1, 0], stops: [[0, "#407"], [1, "#09f"]] },
+ font: "20px Menlo",
+ label: (x) => percent(2)(x),
+ onchange: (x) => ctx.streams.c.next(x)
+ });
+ return ({ a, b, c }) =>
+ ["div", ctx.ui.root,
+ [dialA, ctx.ui.dial, a],
+ [dialB, ctx.ui.dial, b],
+ [dialC, ctx.ui.dial, c]
+ ];
+};
+
+// stream combinator & reactive DOM update
+sync({
+ src: ctx.streams,
+ xform: comp(map(app()), updateDOM())
+});
+
+// seed dials with initial values
+ctx.streams.a.next(0.66);
+ctx.streams.b.next(1);
+ctx.streams.c.next(0.75);
diff --git a/examples/canvas-dial/tsconfig.json b/examples/canvas-dial/tsconfig.json
new file mode 100644
index 0000000000..bd6481a5a6
--- /dev/null
+++ b/examples/canvas-dial/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "."
+ },
+ "include": [
+ "./src/**/*.ts"
+ ]
+}
diff --git a/examples/canvas-dial/webpack.config.js b/examples/canvas-dial/webpack.config.js
new file mode 100644
index 0000000000..e2bf1e8d3a
--- /dev/null
+++ b/examples/canvas-dial/webpack.config.js
@@ -0,0 +1,18 @@
+module.exports = {
+ entry: "./src/index.ts",
+ output: {
+ path: __dirname,
+ filename: "bundle.js"
+ },
+ resolve: {
+ extensions: [".ts", ".js"]
+ },
+ module: {
+ rules: [
+ { test: /\.ts$/, use: "ts-loader" }
+ ]
+ },
+ devServer: {
+ contentBase: "."
+ }
+};
diff --git a/examples/cellular-automata/src/index.ts b/examples/cellular-automata/src/index.ts
index 56d6e44f4b..996f69a46b 100644
--- a/examples/cellular-automata/src/index.ts
+++ b/examples/cellular-automata/src/index.ts
@@ -115,18 +115,20 @@ const isPreset = (id) => presets.findIndex((x) => x[0] === id) !== -1;
applyRules(location.hash.length > 18 ? location.hash.substr(1) : presets[1][0]);
// define & start main app component
-start("app", () => {
- const id = location.hash.substr(1);
- return ["div",
- ruleBoxes("birth", 0),
- ruleBoxes("survive", 1),
- ["div",
- ["button", { onclick: () => randomizeRules() }, "randomize rules"],
- ["button", { onclick: () => randomizeGrid() }, "reset grid"],
- [dropdown, { onchange: (e) => applyRules(e.target.value) },
- presets,
- isPreset(id) ? id : ""]
- ],
- ["pre", format(grid = convolve(grid, rules, W, H), W)]
- ];
-});
+start(
+ () => {
+ const id = location.hash.substr(1);
+ return ["div",
+ ruleBoxes("birth", 0),
+ ruleBoxes("survive", 1),
+ ["div",
+ ["button", { onclick: () => randomizeRules() }, "randomize rules"],
+ ["button", { onclick: () => randomizeGrid() }, "reset grid"],
+ [dropdown, { onchange: (e) => applyRules(e.target.value) },
+ presets,
+ isPreset(id) ? id : ""]
+ ],
+ ["pre", format(grid = convolve(grid, rules, W, H), W)]
+ ];
+ }
+);
diff --git a/examples/commit-table-ssr/.gitignore b/examples/commit-table-ssr/.gitignore
new file mode 100644
index 0000000000..9c418ce79f
--- /dev/null
+++ b/examples/commit-table-ssr/.gitignore
@@ -0,0 +1,3 @@
+node_modules
+yarn.lock
+*.js
diff --git a/examples/commit-table-ssr/README.md b/examples/commit-table-ssr/README.md
new file mode 100644
index 0000000000..ee39157b5c
--- /dev/null
+++ b/examples/commit-table-ssr/README.md
@@ -0,0 +1,83 @@
+# commit-table-ssr
+
+[Live version](http://demo.thi.ng/umbrella/commit-table-ssr/)
+
+This example demonstrates isomorphic,
+[@thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup)-based
+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.
+
+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).
+
+The server example builds a large table (~700KB worth of HTML) of this
+repo's 1460+ commits by shelling out to `git` to retrieve and transform
+the raw history / log using
+[transducer](https://github.com/thi-ng/umbrella/tree/master/packages/transducers)
+pipelines. Since this process doesn't need to be performed for each
+server request, the app uses
+[TLRUCaches](https://github.com/thi-ng/umbrella/tree/master/packages/cache#tlru)
+to cache both the raw commits and the rendered HTML. Reloading the page
+will show the timing difference.
+
+To use another local repo on your hard drive, [update the settings
+here](./src/common/config.ts#L24).
+
+## Building & running
+
+### Server-side rendering
+
+See [/src/server/index.ts](./src/server/index.ts) for details...
+
+```bash
+git clone https://github.com/thi-ng/umbrella.git
+cd umbrella/examples/commit-table-ssr
+yarn install
+yarn dev
+```
+
+Then open http://localhost:3000/ssr in your browser.
+
+### Browser version
+
+The browser version uses the same UI components, but realizes them via
+[@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/master/packages/hdom).
+
+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.
+
+Furthermore, this version utilizes
+[@thi.ng/rstream](https://github.com/thi-ng/umbrella/tree/master/packages/rstream)
+to build a simple dataflow graph and handle app state changes via
+various reactive stream constructs. Comments are included.
+
+See [/src/client/index.ts](./src/client/index.ts) for details...
+
+```
+yarn dev-client
+```
+
+Once you see a message that the server is running, open
+http://localhost:3000 in your browser.
+
+### Static file generation
+
+The result will be saved to `table.html` in this example's root directory.
+
+See [/src/server/static.ts](./src/server/static.ts) for details...
+
+```bash
+yarn build-static
+```
+
+## Authors
+
+- Karsten Schmidt
+
+## License
+
+© 2018 Karsten Schmidt // Apache Software License 2.0
diff --git a/examples/commit-table-ssr/package.json b/examples/commit-table-ssr/package.json
new file mode 100644
index 0000000000..5cf5e0f931
--- /dev/null
+++ b/examples/commit-table-ssr/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "commit-table-ssr",
+ "version": "0.0.1",
+ "repository": "https://github.com/thi-ng/umbrella",
+ "author": "Karsten Schmidt ",
+ "license": "Apache-2.0",
+ "scripts": {
+ "build-static": "tsc && node build/server/static.js",
+ "build-client": "webpack --mode production --display-reasons --display-modules",
+ "dev": "tsc && node build/server/index.js",
+ "dev-client": "yarn build-client && yarn dev"
+ },
+ "devDependencies": {
+ "ts-loader": "^4.4.2",
+ "typescript": "^3.0.1",
+ "webpack": "^4.16.3",
+ "webpack-cli": "^3.1.0",
+ "webpack-dev-server": "^3.1.5"
+ },
+ "dependencies": {
+ "express": "^4.16.3",
+ "@thi.ng/associative": "latest",
+ "@thi.ng/cache": "latest",
+ "@thi.ng/hiccup": "latest",
+ "@thi.ng/resolve-map": "latest",
+ "@thi.ng/rstream": "latest",
+ "@thi.ng/transducers": "latest",
+ "@thi.ng/transducers-hdom": "latest",
+ "@types/express": "^4.16.0"
+ }
+}
\ No newline at end of file
diff --git a/examples/commit-table-ssr/src/client/index.ts b/examples/commit-table-ssr/src/client/index.ts
new file mode 100644
index 0000000000..453fa9887d
--- /dev/null
+++ b/examples/commit-table-ssr/src/client/index.ts
@@ -0,0 +1,126 @@
+import { resolve as resolveMap } from "@thi.ng/resolve-map";
+import { fromInterval } from "@thi.ng/rstream/from/interval";
+import { stream } from "@thi.ng/rstream/stream";
+import { sync } from "@thi.ng/rstream/stream-sync";
+import { resolve as resolvePromise } from "@thi.ng/rstream/subs/resolve";
+import { updateDOM } from "@thi.ng/transducers-hdom";
+import { add } from "@thi.ng/transducers/rfn/add";
+import { conj } from "@thi.ng/transducers/rfn/conj";
+import { transduce } from "@thi.ng/transducers/transduce";
+import { map } from "@thi.ng/transducers/xform/map";
+import { pluck } from "@thi.ng/transducers/xform/pluck";
+import { throttleTime } from "@thi.ng/transducers/xform/throttle-time";
+
+import { AppContext, Commit } from "../common/api";
+import { header } from "../common/components/header";
+import { link } from "../common/components/link";
+import { repoTable } from "../common/components/repo-table";
+import { ctx } from "../common/config";
+
+// UI root component
+const app = (state) =>
+ ["div",
+ [header, ctx.repo.name],
+ [stats, state],
+ [repoTable, state.commits],
+ ];
+
+// stats container component
+const stats = (ctx: AppContext, state) =>
+ ["div", ctx.ui.stats.root,
+ ["div.tl", ctx.ui.stats.col,
+ [searchFilter, state]],
+ ["div.tc", ctx.ui.stats.col,
+ ["div", `Authors: ${state.authors}`],
+ ["div", `Total adds: ${state.adds} (${state.avgAdds} avg / commit)`],
+ ["div", `Total dels: ${state.dels} (${state.avgDels} avg / commit)`]
+ ],
+ ["div.tr", ctx.ui.stats.col,
+ [link, { ...ctx.ui.stats.link, href: ctx.repo.url }, ctx.repo.url]
+ ]
+ ];
+
+// search filter input component
+const searchFilter = (ctx: AppContext, state) =>
+ ["div",
+ "Filter:",
+ ["input", {
+ ...ctx.ui.search,
+ type: "text",
+ value: state.search,
+ // emit changes on `search` stream
+ oninput: (e) => search.next(e.target.value.toLowerCase())
+ }],
+ `(${state.commits.length} commits)`
+ ];
+
+// transformation function to filter commits with search string
+// doesn't apply filter if search term is empty
+const filterCommits = ({ commits, search }) =>
+ ({
+ search,
+ commits: search ?
+ commits.filter((x) => x.msg.toLowerCase().indexOf(search) !== -1) :
+ commits
+ });
+
+// transformation function to compute stats of filtered commits
+// uses `resolve-map` package to execute given functions in dependency order
+const computeStats = (state) => resolveMap({
+ ...state,
+ adds: ({ commits }) => transduce(map((x: Commit) => x.add || 0), add(), commits),
+ dels: ({ commits }) => transduce(map((x: Commit) => x.del || 0), add(), commits),
+ authors: ({ commits }) => transduce(pluck("author"), conj(), commits).size,
+ avgAdds: ({ commits, adds }) => (adds / commits.length) | 0,
+ avgDels: ({ commits, dels }) => (dels / commits.length) | 0
+});
+
+// error stream & handler
+const error = stream();
+error.subscribe({ next: (e) => alert(`An error occurred:\n${e}`) });
+
+// commit log stream, reloads every 1h
+const commits = fromInterval(60 * 60 * 1000)
+ // fetch commits from server
+ .transform(
+ map(() => fetch("./commits").then(
+ (res) => res.ok ? res.json() : error.next("error loading commits"),
+ (e) => error.next(e.message)
+ ))
+ )
+ // the above transducer returns a promise
+ // this next subscription resolves it and only then
+ // passes the result downstream
+ .subscribe(
+ resolvePromise({ fail: (e) => error.next(e.message) })
+ );
+
+// stream of commit filter terms
+const search = stream();
+
+// stream combinator & transformation into UI / DOM update
+sync({
+ // streams to synchronize
+ src: {
+ commits,
+ // throttle search stream @ 10Hz (100ms) to minimize
+ // UI lag for fast typists
+ search: search.transform(throttleTime(100)),
+ },
+})
+ // now transform the combined stream
+ // each value is an object tuple of: `{ commits, search }`
+ .transform(
+ map(filterCommits),
+ map(computeStats),
+ // apply root component
+ map(app),
+ // apply hdom tree to real DOM
+ updateDOM({ ctx })
+ );
+
+// manual kick off is needed here, since the above stream sync construct
+// will only execute once all of its inputs have delivered a value.
+// the other input `commits` is triggered automatically because it's
+// tied to a timer
+search.next("");
diff --git a/examples/commit-table-ssr/src/common/api.ts b/examples/commit-table-ssr/src/common/api.ts
new file mode 100644
index 0000000000..294fb33501
--- /dev/null
+++ b/examples/commit-table-ssr/src/common/api.ts
@@ -0,0 +1,56 @@
+/**
+ * Basic HTML document abstraction for hiccup serialization.
+ * See ./html.ts for usage
+ */
+export interface HTMLDoc {
+ lang?: string;
+ head?: Partial;
+ body: any[];
+ /**
+ * This object will be passed to all component functions.
+ */
+ ctx: AppContext;
+}
+
+export interface HTMLHead {
+ title: string;
+ meta: any[];
+ links: { rel: string, href: string }[];
+ scripts: { src: string, type?: string }[];
+ styles: string[];
+}
+
+/**
+ * App context / config object.
+ * Contains repo information & component styles
+ */
+export interface AppContext {
+ repo: Repo;
+ ui: {
+ body: any;
+ link: any;
+ header: any;
+ table: any;
+ stats: any;
+ search: any;
+ }
+}
+
+export interface Repo {
+ name: string;
+ path: string;
+ url: string;
+}
+
+/**
+ * Data structure of a single commit.
+ */
+export interface Commit {
+ sha: string;
+ date: string;
+ author: string;
+ msg: string;
+ files: number;
+ add: number;
+ del: number;
+}
diff --git a/examples/commit-table-ssr/src/common/components/commit-link.ts b/examples/commit-table-ssr/src/common/components/commit-link.ts
new file mode 100644
index 0000000000..0015a8f304
--- /dev/null
+++ b/examples/commit-table-ssr/src/common/components/commit-link.ts
@@ -0,0 +1,13 @@
+import { AppContext } from "../api";
+import { link } from "./link";
+
+/**
+ * Link component which links to given SHA commit hash using the
+ * context's repo URL.
+ *
+ * @param ctx
+ * @param sha
+ * @param body
+ */
+export const commitLink = (ctx: AppContext, sha: string, body: string) =>
+ [link, { ...ctx.ui.link, href: `${ctx.repo.url}/commit/${sha}` }, body];
diff --git a/examples/commit-table-ssr/src/common/components/header.ts b/examples/commit-table-ssr/src/common/components/header.ts
new file mode 100644
index 0000000000..8b54cb395e
--- /dev/null
+++ b/examples/commit-table-ssr/src/common/components/header.ts
@@ -0,0 +1,6 @@
+import { AppContext } from "../api";
+
+export const header = (ctx: AppContext, title: string) =>
+ ["section", ctx.ui.header.root,
+ ["h1", ctx.ui.header.title, title]
+ ];
diff --git a/examples/commit-table-ssr/src/common/components/link.ts b/examples/commit-table-ssr/src/common/components/link.ts
new file mode 100644
index 0000000000..69f78e00bc
--- /dev/null
+++ b/examples/commit-table-ssr/src/common/components/link.ts
@@ -0,0 +1,11 @@
+import { AppContext } from "../api";
+
+/**
+ * Generic HTML link component.
+ *
+ * @param ctx
+ * @param href
+ * @param body
+ */
+export const link = (_: AppContext, attribs: any, body: string) =>
+ ["a", attribs, body];
diff --git a/examples/commit-table-ssr/src/common/components/repo-table.ts b/examples/commit-table-ssr/src/common/components/repo-table.ts
new file mode 100644
index 0000000000..13a672c284
--- /dev/null
+++ b/examples/commit-table-ssr/src/common/components/repo-table.ts
@@ -0,0 +1,44 @@
+import { comp } from "@thi.ng/transducers/func/comp";
+import { repeat } from "@thi.ng/transducers/iter/repeat";
+import { iterator } from "@thi.ng/transducers/iterator";
+import { map } from "@thi.ng/transducers/xform/map";
+import { mapIndexed } from "@thi.ng/transducers/xform/map-indexed";
+import { partitionBy } from "@thi.ng/transducers/xform/partition-by";
+
+import { AppContext, Commit } from "../api";
+import { commitLink } from "./commit-link";
+import { table } from "./table";
+
+/**
+ * Git commit log table component. Consumes iterable of `Commit` objects
+ * and transforms each into a table row.
+ *
+ * @param _
+ * @param commits
+ */
+export const repoTable = (_: AppContext, commits: Iterable) =>
+ [table,
+ ["15%", "15%", "55%", "5%", "5%", "5%"],
+ ["Date", "Author", "Description", "Files", "Adds", "Dels"],
+ iterator(
+ comp(
+ // convert commit into tuple, one value per table cell
+ map((x: Commit) => [
+ x.date.substr(0, 10),
+ x.author,
+ [commitLink, x.sha, x.msg],
+ x.files,
+ x.add ? ["span.green", `+${x.add}`] : null,
+ x.del ? ["span.red", `-${x.del}`] : null,
+ ]),
+ // partition rows by month
+ partitionBy((row: any[]) => row[0].split("-")[1]),
+ // insert month headers (but not in 1st chunk)
+ mapIndexed((i, month) => [
+ i > 0 ? [month[0][0].substr(0, 7), ...repeat("", 5)] : null,
+ month
+ ])
+ ),
+ commits
+ )
+ ];
diff --git a/examples/commit-table-ssr/src/common/components/table.ts b/examples/commit-table-ssr/src/common/components/table.ts
new file mode 100644
index 0000000000..4a32cb6258
--- /dev/null
+++ b/examples/commit-table-ssr/src/common/components/table.ts
@@ -0,0 +1,58 @@
+import { map } from "@thi.ng/transducers/xform/map";
+
+import { AppContext } from "../api";
+import { mapcat } from "@thi.ng/transducers/xform/mapcat";
+
+const thead = (ctx: AppContext, head: Iterable) =>
+ ["thead",
+ [row, ctx.ui.table.head.row,
+ map((x) => ["th", ctx.ui.table.head.cell, x], head)]];
+
+const row = (ctx: AppContext, attribs: any, body: Iterable) =>
+ ["tr", { ...ctx.ui.table.row, ...attribs }, ...body];
+
+/**
+ * Generic HTML table component w/ column layout support & intermediate
+ * headers. The `body` iterable MUST contain groups of rows, each group
+ * with an optional new header row:
+ *
+ * ```
+ * [table,
+ * // column layout
+ * ["25%", "25%", "50%"],
+ * // global header
+ * ["Price","Item","Description"],
+ * // body
+ * [
+ * // row group #1 w/o header
+ * [null, [
+ * [10.99, "Yaki Udon", "noodle dish"],
+ * [4.99, "Asahi", "beer"],
+ * ]],
+ * // row group #2 w/ header
+ * [["Subtotal", "VAT", "Total"], [
+ * [15.98, "20%", 19.18]
+ * ]]
+ * ]
+ * ]
+ * ```
+ *
+ * @param ctx
+ * @param layout column sizes
+ * @param head header cell values
+ * @param body row chunks
+ */
+export const table = (ctx: AppContext, layout: (string | number)[], head: Iterable, body: Iterable>) =>
+ ["table", ctx.ui.table.root,
+ map((x) => ["col", { style: { width: x } }], layout || []),
+ [thead, head],
+ mapcat(([hd, rows]) =>
+ [
+ hd ? [thead, hd] : null,
+ ["tbody",
+ map((cols: any) => [row, null, map((x) => ["td", ctx.ui.table.cell, x], cols)], rows)
+ ]
+ ],
+ body
+ )
+ ];
diff --git a/examples/commit-table-ssr/src/common/config.ts b/examples/commit-table-ssr/src/common/config.ts
new file mode 100644
index 0000000000..a406e81c6e
--- /dev/null
+++ b/examples/commit-table-ssr/src/common/config.ts
@@ -0,0 +1,56 @@
+import { HTMLDoc, AppContext } from "./api";
+
+export const DEFAULT_DOC: HTMLDoc = {
+ head: {
+ meta: [
+ { "http-equiv": "Content-Type", content: "text/html;charset=UTF-8" },
+ { "http-equiv": "X-UA-Compatible", content: "ie=edge" }
+ ],
+ links: [
+ { rel: "stylesheet", href: "https://unpkg.com/tachyons@4.11.1/css/tachyons.min.css" },
+ { rel: "stylesheet", href: "https://fonts.googleapis.com/css?family=Inconsolata" }
+ ],
+ scripts: [],
+ styles: [],
+ title: "",
+ },
+ ctx: null,
+ body: [],
+};
+
+/**
+ * Main app config.
+ */
+export const ctx: AppContext = {
+ repo: {
+ name: "thi.ng/umbrella",
+ path: ".",
+ url: "https://github.com/thi-ng/umbrella",
+ },
+ ui: {
+ body: { class: "sans-serif vh-100" },
+ link: { class: "link blue hover-light-blue" },
+ header: {
+ root: { class: "bg-dark-gray white pa3 ma0 w-100" },
+ title: { class: "tc ma0 pa0 fw1" }
+ },
+ table: {
+ root: {
+ class: "w-100 collapse ba br2 b--black-10 pv2 ph3 f7 f6-ns",
+ style: { "font-family": "Inconsolata, monospace" }
+ },
+ head: {
+ row: { class: "tl bg-black white" },
+ cell: { class: "pv1 pv2-ns ph2 ph3-ns" },
+ },
+ row: { class: "striped--light-gray" },
+ cell: { class: "pv1 pv2-ns ph2 ph3-ns" }
+ },
+ stats: {
+ root: { class: "flex items-center pa2 bg-light-green dark-gray f7" },
+ col: { class: "w-33" },
+ link: { class: "link dark-gray" }
+ },
+ search: { class: "pa1 mh2" }
+ }
+};
diff --git a/examples/commit-table-ssr/src/server/build-table.ts b/examples/commit-table-ssr/src/server/build-table.ts
new file mode 100644
index 0000000000..bf2f22765b
--- /dev/null
+++ b/examples/commit-table-ssr/src/server/build-table.ts
@@ -0,0 +1,18 @@
+import { Commit } from "../common/api";
+import { header } from "../common/components/header";
+import { repoTable } from "../common/components/repo-table";
+import { ctx } from "../common/config";
+import { html } from "./html";
+
+/**
+ * Shared function used by both the server and for static file
+ * generation. Returns serialized HTML string of commit table.
+ */
+export const buildRepoTableHTML = (commits: Iterable) =>
+ html({
+ ctx,
+ body: [
+ [header, ctx.repo.name],
+ [repoTable, commits],
+ ]
+ });
diff --git a/examples/commit-table-ssr/src/server/git.ts b/examples/commit-table-ssr/src/server/git.ts
new file mode 100644
index 0000000000..8120bcca59
--- /dev/null
+++ b/examples/commit-table-ssr/src/server/git.ts
@@ -0,0 +1,86 @@
+import {
+ assocObj,
+ comp,
+ filter,
+ iterator,
+ map,
+ mapcat,
+ partitionBy,
+ transduce,
+ tuples
+} from "@thi.ng/transducers";
+import { execSync } from "child_process";
+import { resolve } from "path";
+
+import { Commit } from "../common/api";
+
+/**
+ * Calls out to git to retrieve raw log string.
+ *
+ * @param repoPath
+ */
+const gitLog = (repoPath: string) =>
+ execSync(
+ `git log --pretty=format:"%ad~~%an~~%h~~%s" --shortstat --date=iso-strict`,
+ { cwd: resolve(repoPath) }
+ ).toString().trim();
+
+/**
+ * Transforms 1st line of a raw commit log into a partial commit
+ * object.
+ *
+ * @param log
+ */
+const parseLog = ([log]: string[]): Partial => {
+ const [date, author, sha, msg] = log.split("~~");
+ return { date, author, sha, msg };
+};
+
+/**
+ * Transforms 2nd line (if present) of a raw commit log into a partial
+ * commit object.
+ *
+ * @param log
+ */
+const parseStats = ([_, stats]: string[]): Partial =>
+ stats ?
+ transduce(
+ map(([k, v]) => [k, parseInt(v)]),
+ assocObj(),
+ tuples(["files", "add", "del"], stats.split(","))
+ ) :
+ null;
+
+/**
+ * Retrieves git log for given `repoPath` and transforms it into an
+ * iterable of `Commit` objects.
+ *
+ * @param repoPath
+ */
+export const repoCommits = (repoPath: string) =>
+ iterator(
+ comp(
+ // get raw log
+ map(gitLog),
+ // split into lines
+ mapcat((x: string) => x.split("\n")),
+ // group related lines:
+ // normal commits have 2 lines + 1 empty
+ // merge commits have only 1 line
+ // pick a random number for merge commits
+ // in case there're successive ones
+ partitionBy(
+ (x) => x.indexOf("~~Merge ") !== -1 ?
+ Math.random() :
+ x.length > 0 ? 1 : 0
+ ),
+ // remove empty lines
+ filter((x) => x[0].length > 0),
+ // parse commit details
+ map((commit) => {
+ ...parseLog(commit),
+ ...parseStats(commit)
+ })
+ ),
+ [repoPath]
+ );
diff --git a/examples/commit-table-ssr/src/server/html.ts b/examples/commit-table-ssr/src/server/html.ts
new file mode 100644
index 0000000000..07781d8d94
--- /dev/null
+++ b/examples/commit-table-ssr/src/server/html.ts
@@ -0,0 +1,39 @@
+import { mergeDeepObj } from "@thi.ng/associative/merge-deep";
+import { serialize } from "@thi.ng/hiccup";
+import { map } from "@thi.ng/transducers/xform/map";
+
+import { AppContext, HTMLDoc } from "../common/api";
+import { DEFAULT_DOC } from "../common/config";
+
+/**
+ * Takes a `HTMLDoc` object and serializes it into an HTML5 string. The
+ * `body` field of the document must contain elements in thi.ng/hiccup
+ * format, i.e. it's an array in which each element is a nested array,
+ * string or ES6 iterable, each encoding a part of the full DOM to be
+ * generated. The resulting HTML string will not contain any whitespace
+ * unless it's part of string values.
+ *
+ * See here for more reference:
+ * https://github.com/thi-ng/umbrella/tree/master/packages/hiccup
+ *
+ * @param doc
+ */
+export const html = (doc: HTMLDoc) => {
+ doc = mergeDeepObj(DEFAULT_DOC, doc);
+ return `${serialize(
+ ["html", { lang: doc.lang || "en" },
+ ["head",
+ map((meta) => ["meta", meta], doc.head.meta),
+ map((s) => script(null, s), doc.head.scripts),
+ map((link) => ["link", link], doc.head.links),
+ map((css) => ["style", css], doc.head.styles),
+ ["title", doc.head.title],
+ ],
+ ["body", doc.ctx.ui.body, ...doc.body]
+ ],
+ doc.ctx
+ )}`;
+};
+
+export const script = (_: AppContext, script: { src: string, type?: string }) =>
+ ["script", { type: "text/javascript", ...script }];
\ No newline at end of file
diff --git a/examples/commit-table-ssr/src/server/index.ts b/examples/commit-table-ssr/src/server/index.ts
new file mode 100644
index 0000000000..302ed03339
--- /dev/null
+++ b/examples/commit-table-ssr/src/server/index.ts
@@ -0,0 +1,65 @@
+import { TLRUCache } from "@thi.ng/cache";
+import * as express from "express";
+
+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
+// (which is also the default)
+const rawCache = new TLRUCache(null, { ttl: 60 * 60 * 1000 });
+const htmlCache = new TLRUCache(null, { ttl: 60 * 60 * 1000 });
+
+const app = express();
+
+app.use(express.static("."));
+
+// route for browser version
+// here we simply return a barebone html doc
+// with a reference to the built client JS
+app.get("/", (_, res) => {
+ res.send(html({
+ ctx,
+ head: {
+ title: "commit-table-hdom",
+ },
+ body: [
+ ["div#app"],
+ [script, { src: "bundle.js" }]
+ ],
+ }));
+});
+
+// route for the client to retrieve the commit log as JSON
+app.get("/commits", (_, res) => {
+ // retrieve raw commit log from cache or
+ // (re)create if missing...
+ rawCache.getSet(
+ ctx.repo.path,
+ async () => [...repoCommits(ctx.repo.path)]
+ ).then(
+ (commits) => res.type("json").send(commits)
+ )
+});
+
+// route for server-side rendering
+// uses both caches
+app.get("/ssr", (_, res) => {
+ // retrieve rendered html from cache or
+ // (re)create if missing...
+ htmlCache.getSet(
+ ctx.repo.path,
+ async () => buildRepoTableHTML(
+ await rawCache.getSet(
+ ctx.repo.path,
+ async () => [...repoCommits(ctx.repo.path)]
+ )
+ )
+ ).then((doc) => res.send(doc))
+});
+
+console.log("starting server @ http://localhost:3000");
+app.listen(3000);
diff --git a/examples/commit-table-ssr/src/server/static.ts b/examples/commit-table-ssr/src/server/static.ts
new file mode 100644
index 0000000000..4170ca5191
--- /dev/null
+++ b/examples/commit-table-ssr/src/server/static.ts
@@ -0,0 +1,8 @@
+import { writeFileSync } from "fs";
+
+import { ctx } from "../common/config";
+import { buildRepoTableHTML } from "./build-table";
+import { repoCommits } from "./git";
+
+// generate as file in example directory
+writeFileSync("table.html", buildRepoTableHTML(repoCommits(ctx.repo.path)));
diff --git a/examples/commit-table-ssr/tsconfig.json b/examples/commit-table-ssr/tsconfig.json
new file mode 100644
index 0000000000..9c5143a908
--- /dev/null
+++ b/examples/commit-table-ssr/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "build"
+ },
+ "include": [
+ "./src/**/*.ts"
+ ]
+}
\ No newline at end of file
diff --git a/examples/crypto-chart/README.md b/examples/crypto-chart/README.md
index f6fb86990c..e3188dedaf 100644
--- a/examples/crypto-chart/README.md
+++ b/examples/crypto-chart/README.md
@@ -2,7 +2,7 @@
[Live demo](https://s3.amazonaws.com/demo.thi.ng/umbrella/crypto-chart/index.html)
-![chart](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/crypto-chart.png)
+![chart](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/crypto-chart.png)
Price data provided by [cryptocompare.com](https://min-api.cryptocompare.com/).
diff --git a/examples/crypto-chart/src/index.ts b/examples/crypto-chart/src/index.ts
index 0039ac4aa2..773266a98c 100644
--- a/examples/crypto-chart/src/index.ts
+++ b/examples/crypto-chart/src/index.ts
@@ -1,6 +1,4 @@
import { dropdown, DropDownOption } from "@thi.ng/hdom-components/dropdown";
-import { diffElement } from "@thi.ng/hdom/diff";
-import { normalizeTree } from "@thi.ng/hdom/normalize";
import { group } from "@thi.ng/hiccup-svg/group";
import { line } from "@thi.ng/hiccup-svg/line";
import { polygon } from "@thi.ng/hiccup-svg/polygon";
@@ -16,6 +14,7 @@ import { sync } from "@thi.ng/rstream/stream-sync";
import { resolve as resolvePromise } from "@thi.ng/rstream/subs/resolve";
import { trace } from "@thi.ng/rstream/subs/trace";
import { padLeft } from "@thi.ng/strings/pad-left";
+import { updateDOM } from "@thi.ng/transducers-hdom";
import { ema } from "@thi.ng/transducers-stats/ema";
import { hma } from "@thi.ng/transducers-stats/hma";
import { sma } from "@thi.ng/transducers-stats/sma";
@@ -23,7 +22,6 @@ import { wma } from "@thi.ng/transducers-stats/wma";
import { comp } from "@thi.ng/transducers/func/comp";
import { pairs } from "@thi.ng/transducers/iter/pairs";
import { range } from "@thi.ng/transducers/iter/range";
-import { reducer } from "@thi.ng/transducers/reduce";
import { max } from "@thi.ng/transducers/rfn/max";
import { min } from "@thi.ng/transducers/rfn/min";
import { push } from "@thi.ng/transducers/rfn/push";
@@ -33,7 +31,6 @@ import { map } from "@thi.ng/transducers/xform/map";
import { mapIndexed } from "@thi.ng/transducers/xform/map-indexed";
import { mapcat } from "@thi.ng/transducers/xform/mapcat";
import { pluck } from "@thi.ng/transducers/xform/pluck";
-import { scan } from "@thi.ng/transducers/xform/scan";
// this example demonstrates how to use @thi.ng/rstream &
// @thi.ng/transducer constructs to create a basic cryptocurrency candle
@@ -404,16 +401,7 @@ sync({
]
),
// perform hdom update / diffing
- scan(
- reducer(
- () => [],
- (prev, curr) => {
- curr = normalizeTree(curr, {});
- diffElement(document.getElementById("app"), prev, curr);
- return curr;
- }
- )
- )
+ updateDOM()
)
});
diff --git a/examples/dashboard/src/index.ts b/examples/dashboard/src/index.ts
index b6aaac01bb..c024977d4d 100644
--- a/examples/dashboard/src/index.ts
+++ b/examples/dashboard/src/index.ts
@@ -31,4 +31,4 @@ const app = (() => {
})();
// start update loop (RAF)
-start("app", app);
+start(app);
diff --git a/examples/devcards/src/index.ts b/examples/devcards/src/index.ts
index e169683e2f..0db3e0b898 100644
--- a/examples/devcards/src/index.ts
+++ b/examples/devcards/src/index.ts
@@ -48,7 +48,7 @@ function defcard(card: CardFn, state?: IAtom, title?: string, parent?: stri
const root = card(state);
// kick off hdom renderloop
- start(parent, () => ["div.card", ["h3", title], ["div.body", root, ["pre", json]]]);
+ start(() => ["div.card", ["h3", title], ["div.body", root, ["pre", json]]], { root: parent });
}
/**
diff --git a/examples/hdom-basics/src/index.ts b/examples/hdom-basics/src/index.ts
index 4733c606e2..d75a570397 100644
--- a/examples/hdom-basics/src/index.ts
+++ b/examples/hdom-basics/src/index.ts
@@ -18,7 +18,7 @@ const app = () => {
};
// start update loop (browser only, see diagram below)
-hdom.start(document.body, app());
+hdom.start(app());
// alternatively apply DOM tree only once
// (stateful components won't update though)
diff --git a/examples/hdom-benchmark/src/index.ts b/examples/hdom-benchmark/src/index.ts
index ea124cdad6..e8bcc63db4 100644
--- a/examples/hdom-benchmark/src/index.ts
+++ b/examples/hdom-benchmark/src/index.ts
@@ -98,4 +98,4 @@ const app = () => {
};
};
-start("app", app(), null, false);
+start(app(), { span: false });
diff --git a/examples/hdom-dropdown-fuzzy/src/index.ts b/examples/hdom-dropdown-fuzzy/src/index.ts
index 9298463047..890bac3535 100644
--- a/examples/hdom-dropdown-fuzzy/src/index.ts
+++ b/examples/hdom-dropdown-fuzzy/src/index.ts
@@ -23,7 +23,7 @@ const ctx = {
const dd = dropdown("theme.dd");
const input = cancelableInput("theme.input");
-start("app",
+start(
(ctx) => {
ctx.bus.processQueue();
return ["div", ctx.theme.root,
@@ -39,6 +39,7 @@ start("app",
],
];
},
- ctx);
+ { ctx }
+);
// window["ctx"] = ctx;
diff --git a/examples/hdom-dropdown/src/index.ts b/examples/hdom-dropdown/src/index.ts
index cbb567aced..a33829c656 100644
--- a/examples/hdom-dropdown/src/index.ts
+++ b/examples/hdom-dropdown/src/index.ts
@@ -11,7 +11,7 @@ bus.instrumentWith([trace]);
const dd = dropdown("theme.dd");
-start("app",
+start(
(ctx) => {
bus.processQueue();
return ["div", ctx.theme.root,
@@ -29,4 +29,5 @@ start("app",
}]],
];
},
- { bus, theme });
+ { ctx: { bus, theme } }
+);
diff --git a/examples/hdom-theme-adr-0003/src/index.ts b/examples/hdom-theme-adr-0003/src/index.ts
index feaef66d73..17f9fada5f 100644
--- a/examples/hdom-theme-adr-0003/src/index.ts
+++ b/examples/hdom-theme-adr-0003/src/index.ts
@@ -144,4 +144,4 @@ const app = (ctx) =>
["p", [link, "https://github.com/thi-ng/umbrella/blob/develop/examples/hdom-theme-adr-0003", "Source"]]
];
-start("app", app, ctx);
+start(app, { ctx });
diff --git a/examples/hydrate-basics/.gitignore b/examples/hydrate-basics/.gitignore
new file mode 100644
index 0000000000..9c418ce79f
--- /dev/null
+++ b/examples/hydrate-basics/.gitignore
@@ -0,0 +1,3 @@
+node_modules
+yarn.lock
+*.js
diff --git a/examples/hydrate-basics/README.md b/examples/hydrate-basics/README.md
new file mode 100644
index 0000000000..4fcad46175
--- /dev/null
+++ b/examples/hydrate-basics/README.md
@@ -0,0 +1,21 @@
+# hydrate-basics
+
+[Live demo](http://demo.thi.ng/umbrella/hydrate-basics/)
+
+This example demonstrates how to hydrate a pre-created HTML DOM (e.g.
+server-side rendering) client-side.
+
+```bash
+git clone https://github.com/thi-ng/umbrella.git
+cd umbrella/examples/hydrate-basics
+yarn install
+yarn start
+```
+
+## Authors
+
+- Karsten Schmidt
+
+## License
+
+© 2018 Karsten Schmidt // Apache Software License 2.0
diff --git a/examples/hydrate-basics/index.html b/examples/hydrate-basics/index.html
new file mode 100644
index 0000000000..710f580a78
--- /dev/null
+++ b/examples/hydrate-basics/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+ hydrate-basics
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/hydrate-basics/package.json b/examples/hydrate-basics/package.json
new file mode 100644
index 0000000000..9fefbe8437
--- /dev/null
+++ b/examples/hydrate-basics/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "hydrate-basics",
+ "version": "0.0.1",
+ "repository": "https://github.com/thi-ng/umbrella",
+ "author": "Karsten Schmidt ",
+ "license": "Apache-2.0",
+ "scripts": {
+ "build": "webpack --mode production --display-reasons --display-modules",
+ "start": "webpack-dev-server --open --mode development --devtool inline-source-map"
+ },
+ "devDependencies": {
+ "ts-loader": "^4.4.2",
+ "typescript": "^3.0.1",
+ "webpack": "^4.16.3",
+ "webpack-cli": "^3.1.0",
+ "webpack-dev-server": "^3.1.5"
+ },
+ "dependencies": {
+ "@thi.ng/api": "latest",
+ "@thi.ng/hdom": "latest",
+ "@thi.ng/rstream": "latest",
+ "@thi.ng/transducers": "latest"
+ }
+}
diff --git a/examples/hydrate-basics/src/index.ts b/examples/hydrate-basics/src/index.ts
new file mode 100644
index 0000000000..0faa1b3e45
--- /dev/null
+++ b/examples/hydrate-basics/src/index.ts
@@ -0,0 +1,84 @@
+import { Atom } from "@thi.ng/atom";
+import { serialize } from "@thi.ng/hiccup/serialize";
+import { start } from "@thi.ng/hdom/start";
+import { canvas2D } from "@thi.ng/hdom-components/canvas";
+import { dropdown } from "@thi.ng/hdom-components/dropdown";
+
+// basic state container
+const state = new Atom({
+ bg: "red",
+ freq: 0.01
+});
+
+// state updates
+const setBg = (x: string) => state.resetIn("bg", x);
+const setFreq = (x: number) => state.resetIn("freq", x);
+
+// root component with different types of child components
+const app = () => {
+ // HOF canvas component w/ life cycle methods see for further
+ // reference:
+ // https://github.com/thi-ng/umbrella/blob/master/packages/hdom-components/src/canvas.ts
+ //
+ // when serializing to html only the component's `render` method
+ // will be invoked. the component's `init` is invoked later when
+ // hydrating the DOM the `update` fn given here is canvas specific
+ const canvas = canvas2D({
+ update: (el, ctx, _, time, __, ___, bg, freq) => {
+ const y = el.height / 2;
+ ctx.fillStyle = bg;
+ ctx.fillRect(0, 0, el.width, el.height);
+ ctx.strokeStyle = "white";
+ ctx.lineWidth = 3;
+ ctx.beginPath();
+ ctx.moveTo(0, y + y * Math.sin(time * freq));
+ for (let x = 5; x < el.width; x += 5) {
+ ctx.lineTo(x, y + y * Math.sin((time + x) * freq));
+ }
+ ctx.stroke();
+ }
+ });
+ // when serializing to HTML all event attributes w/ function values
+ // will be excluded, however the event listeners will be attached
+ // during hydration (1st frame of hdom update loop)
+
+ // btw. the class names are for tachyons css
+ return (state) => {
+ state = state.deref();
+ return ["div#root.w-50-ns.flex.ma2.sans-serif",
+ ["div.w-50-ns",
+ [canvas, { width: 200, height: 200 }, state.bg, state.freq]],
+ ["div.w-50-ns",
+ ["label.db.mb3", { for: "#bg" }, "Background color",
+ [dropdown,
+ {
+ id: "bg",
+ class: "w-100",
+ onchange: (e) => setBg(e.target.value)
+ },
+ [["", "Choose..."], ["red", "Red"], ["green", "Green"], ["blue", "Blue"]],
+ state.bg
+ ]],
+ ["label.db.mb3", { for: "#freq" }, "Frequency",
+ ["input", {
+ id: "freq",
+ class: "w-100",
+ type: "range",
+ min: 0.001,
+ max: 0.02,
+ step: 0.001,
+ value: state.freq,
+ oninput: (e) => setFreq(parseFloat(e.target.value))
+ }]]
+ ],
+ ];
+ };
+};
+
+// emulate SSR by serializing to HTML
+const html = serialize(app()(state), null, false, true);
+document.getElementById("app").innerHTML = html;
+console.log(html);
+
+// ..then start hdom update loop w/ hydrate enabled
+start(app(), { hydrate: true, ctx: state });
diff --git a/examples/hydrate-basics/tsconfig.json b/examples/hydrate-basics/tsconfig.json
new file mode 100644
index 0000000000..bd6481a5a6
--- /dev/null
+++ b/examples/hydrate-basics/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "."
+ },
+ "include": [
+ "./src/**/*.ts"
+ ]
+}
diff --git a/examples/hydrate-basics/webpack.config.js b/examples/hydrate-basics/webpack.config.js
new file mode 100644
index 0000000000..e2bf1e8d3a
--- /dev/null
+++ b/examples/hydrate-basics/webpack.config.js
@@ -0,0 +1,18 @@
+module.exports = {
+ entry: "./src/index.ts",
+ output: {
+ path: __dirname,
+ filename: "bundle.js"
+ },
+ resolve: {
+ extensions: [".ts", ".js"]
+ },
+ module: {
+ rules: [
+ { test: /\.ts$/, use: "ts-loader" }
+ ]
+ },
+ devServer: {
+ contentBase: "."
+ }
+};
diff --git a/examples/interceptor-basics/src/index.ts b/examples/interceptor-basics/src/index.ts
index 75a6ca2558..7027aeb40c 100644
--- a/examples/interceptor-basics/src/index.ts
+++ b/examples/interceptor-basics/src/index.ts
@@ -134,4 +134,4 @@ const app = () => {
};
// kick off hdom render loop
-start("app", app());
+start(app());
diff --git a/examples/json-components/src/index.ts b/examples/json-components/src/index.ts
index 9bd9790bb4..728ae931aa 100644
--- a/examples/json-components/src/index.ts
+++ b/examples/json-components/src/index.ts
@@ -95,7 +95,6 @@ const editor = (() => {
// start UI
start(
- document.getElementById("app"),
() =>
["div#container",
["div", editor],
diff --git a/examples/login-form/src/index.ts b/examples/login-form/src/index.ts
index cb1242cb48..089be68615 100644
--- a/examples/login-form/src/index.ts
+++ b/examples/login-form/src/index.ts
@@ -76,8 +76,8 @@ const currView = db.addView(
// app root component
const app = () =>
- ["div#app",
+ ["div",
currView,
["footer", "Made with @thi.ng/atom and @thi.ng/hdom"]];
-start(document.body, app);
+start(app);
diff --git a/examples/router-basics/src/app.ts b/examples/router-basics/src/app.ts
index 4969d52691..c046f68e70 100644
--- a/examples/router-basics/src/app.ts
+++ b/examples/router-basics/src/app.ts
@@ -110,11 +110,14 @@ export class App {
*/
start() {
this.router.start();
- start(this.config.domRoot, () => {
- if (this.ctx.bus.processQueue()) {
- return this.rootComponent();
- }
- }, this.ctx);
+ start(
+ () => {
+ if (this.ctx.bus.processQueue()) {
+ return this.rootComponent();
+ }
+ },
+ { root: this.config.domRoot, ctx: this.ctx }
+ );
}
/**
diff --git a/examples/rstream-dataflow/src/index.ts b/examples/rstream-dataflow/src/index.ts
index 07cce78ace..d402f326d4 100644
--- a/examples/rstream-dataflow/src/index.ts
+++ b/examples/rstream-dataflow/src/index.ts
@@ -144,16 +144,18 @@ const graph = initGraph(db, {
});
// start @thi.ng/hdom update loop
-start("app", () =>
- ["div",
- ["pre.absolute.top-1.left-1.pa0.ma0.z-2.f7",
- JSON.stringify(db.deref(), null, 2)],
- // note: direct embedding of result stream below. this works
- // since all @thi.ng/rstream subscriptions implement the
- // @thi.ng/api/IDeref interface (like several other types, e.g.
- // @thi.ng/atom's Atom, Cursor, View etc.)
- graph.circle.node
- ]);
+start(
+ () =>
+ ["div",
+ ["pre.absolute.top-1.left-1.pa0.ma0.z-2.f7",
+ JSON.stringify(db.deref(), null, 2)],
+ // note: direct embedding of result stream below. this works
+ // since all @thi.ng/rstream subscriptions implement the
+ // @thi.ng/api/IDeref interface (like several other types, e.g.
+ // @thi.ng/atom's Atom, Cursor, View etc.)
+ graph.circle.node
+ ]
+);
// create a GraphViz DOT file of the entire dataflow graph
// copy the output from the console into a new text file and then run:
diff --git a/examples/rstream-grid/src/app.ts b/examples/rstream-grid/src/app.ts
index b042e6d88e..8a8d10b1fe 100644
--- a/examples/rstream-grid/src/app.ts
+++ b/examples/rstream-grid/src/app.ts
@@ -82,14 +82,13 @@ export class App {
const root = this.config.rootComponent(this.ctx);
let firstFrame = true;
start(
- this.config.domRoot,
() => {
if (this.ctx.bus.processQueue({ history: this.history }) || firstFrame) {
firstFrame = false;
return root();
}
},
- this.ctx
+ { root: this.config.domRoot, ctx: this.ctx }
);
}
diff --git a/examples/rstream-hdom/src/index.ts b/examples/rstream-hdom/src/index.ts
index a0f45120af..ca7f079685 100644
--- a/examples/rstream-hdom/src/index.ts
+++ b/examples/rstream-hdom/src/index.ts
@@ -3,7 +3,7 @@ import { fromRAF } from "@thi.ng/rstream/from/raf";
import { sync } from "@thi.ng/rstream/stream-sync";
import { sidechainPartition } from "@thi.ng/rstream/subs/sidechain-partition";
import { Subscription, subscription } from "@thi.ng/rstream/subscription";
-import { updateUI } from "@thi.ng/transducers-hdom";
+import { updateDOM } from "@thi.ng/transducers-hdom";
import { peek } from "@thi.ng/transducers/func/peek";
import { vals } from "@thi.ng/transducers/iter/vals";
import { reducer } from "@thi.ng/transducers/reduce";
@@ -25,31 +25,33 @@ const ctx = {
};
/**
- * Takes a `parent` DOM element, a stream of `root` component values and
- * an arbitrary user context object which will be implicitly passed to
- * all component functions embedded in the root component. Subscribes to
- * `root` stream & performs DOM diffs / updates using incoming values
- * (i.e. UI components). Additionally, a RAF side chain stream is used
- * here to synchronize DOM updates to be processed during RAF.
+ * Takes a `root` DOM element, a stream of `tree` component values and
+ * an (optional) arbitrary user context object which will be implicitly
+ * passed to all component functions embedded in the root component.
+ * Subscribes to `root` stream & performs DOM diffs / updates using
+ * incoming values (i.e. UI components). Additionally, a RAF side chain
+ * stream is used here to synchronize DOM update requests to be only
+ * processed during RAF. If multiple updates are triggered per frame,
+ * this also ensures that the DOM is only updated once per frame.
*
* Without RAF synchronization, the following would be sufficient:
*
* ```
- * root.transform(updateUI(parent, ctx))
+ * root.transform(updateDOM({root, ctx}))
* ```
*
* Returns stream of hdom trees.
*
- * @param parent root DOM element
- * @param root root hdom component stream
+ * @param root root DOM element
+ * @param tree hdom component stream
* @param ctx user context object
*/
-const domUpdate = (parent: HTMLElement, root: ISubscribable, ctx?: any) =>
- root
+const domUpdate = (root: HTMLElement, tree: ISubscribable, ctx?: any) =>
+ tree
.subscribe(sidechainPartition(fromRAF()))
.transform(
map(peek),
- updateUI(parent, ctx)
+ updateDOM({ root, ctx })
);
/**
diff --git a/examples/svg-particles/src/index.ts b/examples/svg-particles/src/index.ts
index 98b644f188..0e6cf49940 100644
--- a/examples/svg-particles/src/index.ts
+++ b/examples/svg-particles/src/index.ts
@@ -40,4 +40,4 @@ const app = () => {
return ["svg", { width, height }, particles];
};
-start(document.body, app);
\ No newline at end of file
+start(app);
\ No newline at end of file
diff --git a/examples/svg-waveform/src/app.ts b/examples/svg-waveform/src/app.ts
index e5093fbf67..2e5bbf4c2a 100644
--- a/examples/svg-waveform/src/app.ts
+++ b/examples/svg-waveform/src/app.ts
@@ -71,14 +71,13 @@ export class App {
const root = this.config.rootComponent(this.ctx);
let firstFrame = true;
start(
- this.config.domRoot,
() => {
if (this.ctx.bus.processQueue({ history: this.history }) || firstFrame) {
firstFrame = false;
return root();
}
},
- this.ctx
+ { root: this.config.domRoot, ctx: this.ctx }
);
}
diff --git a/examples/todo-list/src/index.ts b/examples/todo-list/src/index.ts
index 246b06df30..f539dd9e96 100644
--- a/examples/todo-list/src/index.ts
+++ b/examples/todo-list/src/index.ts
@@ -83,4 +83,4 @@ const app = () => {
};
// kick off UI w/ root component function
-start("app", app());
+start(app());
diff --git a/examples/transducers-hdom/src/index.ts b/examples/transducers-hdom/src/index.ts
index 399b5c8776..8ae55763e1 100644
--- a/examples/transducers-hdom/src/index.ts
+++ b/examples/transducers-hdom/src/index.ts
@@ -1,7 +1,7 @@
import { fromInterval } from "@thi.ng/rstream/from/interval";
import { stream } from "@thi.ng/rstream/stream";
import { sync } from "@thi.ng/rstream/stream-sync";
-import { updateUI } from "@thi.ng/transducers-hdom";
+import { updateDOM } from "@thi.ng/transducers-hdom";
import { count } from "@thi.ng/transducers/rfn/count";
import { map } from "@thi.ng/transducers/xform/map";
import { scan } from "@thi.ng/transducers/xform/scan";
@@ -41,8 +41,8 @@ sync({
// transform into hdom component
map(app),
// apply hdom tree to real DOM
- updateUI("app")
+ updateDOM()
);
// kick off
-clickStream.next(0);
\ No newline at end of file
+clickStream.next(0);
diff --git a/examples/triple-query/src/app.ts b/examples/triple-query/src/app.ts
index 4fc6785f9c..06a9aba1e5 100644
--- a/examples/triple-query/src/app.ts
+++ b/examples/triple-query/src/app.ts
@@ -76,14 +76,13 @@ export class App {
const root = this.config.rootComponent(this.ctx);
let firstFrame = true;
start(
- this.config.domRoot,
() => {
if (this.ctx.bus.processQueue({ store: this.ctx.store }) || firstFrame) {
firstFrame = false;
return root();
}
},
- this.ctx
+ { root: this.config.domRoot, ctx: this.ctx }
);
}
diff --git a/examples/webgl/src/index.ts b/examples/webgl/src/index.ts
index 0288559c74..3899b07843 100644
--- a/examples/webgl/src/index.ts
+++ b/examples/webgl/src/index.ts
@@ -41,4 +41,4 @@ const app = () => {
[c3, attribs, 400, 0.05]];
};
-start("app", app());
+start(app());
diff --git a/packages/associative/CHANGELOG.md b/packages/associative/CHANGELOG.md
index 4c7a724220..9bc65c3407 100644
--- a/packages/associative/CHANGELOG.md
+++ b/packages/associative/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.6.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/associative@0.6.1...@thi.ng/associative@0.6.2) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/associative
+
## [0.6.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/associative@0.6.0...@thi.ng/associative@0.6.1) (2018-08-24)
diff --git a/packages/associative/README.md b/packages/associative/README.md
index da444655cd..1a1af64ef6 100644
--- a/packages/associative/README.md
+++ b/packages/associative/README.md
@@ -129,7 +129,7 @@ yarn add @thi.ng/associative
- [@thi.ng/dcons](https://github.com/thi-ng/umbrella/tree/master/packages/dcons)
- [@thi.ng/equiv](https://github.com/thi-ng/umbrella/tree/master/packages/equiv)
- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors)
-- [@thi.ng/iterators](https://github.com/thi-ng/umbrella/tree/master/packages/iterators)
+- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers)
## Types
diff --git a/packages/associative/package.json b/packages/associative/package.json
index 419951e996..b69378787d 100644
--- a/packages/associative/package.json
+++ b/packages/associative/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/associative",
- "version": "0.6.1",
+ "version": "0.6.2",
"description": "Alternative Set & Map data type implementations with customizable equality semantics & supporting operations",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -31,10 +31,10 @@
"@thi.ng/api": "^4.1.0",
"@thi.ng/checks": "^1.5.7",
"@thi.ng/compare": "^0.1.6",
- "@thi.ng/dcons": "^1.1.1",
+ "@thi.ng/dcons": "^1.1.2",
"@thi.ng/equiv": "^0.1.7",
"@thi.ng/errors": "^0.1.6",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"data structures",
diff --git a/packages/atom/CHANGELOG.md b/packages/atom/CHANGELOG.md
index 5f933d0779..95d8d3780b 100644
--- a/packages/atom/CHANGELOG.md
+++ b/packages/atom/CHANGELOG.md
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+# [1.5.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/atom@1.4.7...@thi.ng/atom@1.5.0) (2018-08-27)
+
+
+### Features
+
+* **atom:** add .value accessor aliases (for deref()/reset()) ([a0cbd2b](https://github.com/thi-ng/umbrella/commit/a0cbd2b))
+
+
+
+
## [1.4.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/atom@1.4.6...@thi.ng/atom@1.4.7) (2018-08-24)
diff --git a/packages/atom/package.json b/packages/atom/package.json
index 38788878d4..43bb6a58ef 100644
--- a/packages/atom/package.json
+++ b/packages/atom/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/atom",
- "version": "1.4.7",
+ "version": "1.5.0",
"description": "Mutable wrapper for immutable values",
"main": "./index.js",
"typings": "./index.d.ts",
diff --git a/packages/atom/src/atom.ts b/packages/atom/src/atom.ts
index 90e7549118..888d2226cc 100644
--- a/packages/atom/src/atom.ts
+++ b/packages/atom/src/atom.ts
@@ -20,7 +20,7 @@ export class Atom implements
IAtom,
IEquiv {
- protected value: T;
+ protected _value: T;
protected valid: Predicate;
protected _watches: any;
@@ -28,12 +28,20 @@ export class Atom implements
if (valid && !valid(val)) {
illegalState("initial state value did not validate");
}
- this.value = val;
+ this._value = val;
this.valid = valid;
}
+ get value() {
+ return this._value;
+ }
+
+ set value(val: T) {
+ this.reset(val);
+ }
+
deref() {
- return this.value;
+ return this._value;
}
equiv(o: any) {
@@ -41,25 +49,25 @@ export class Atom implements
}
reset(val: T) {
- const old = this.value;
+ const old = this._value;
if (this.valid && !this.valid(val)) {
return old;
}
- this.value = val;
+ this._value = val;
this.notifyWatches(old, val);
return val;
}
resetIn(path: Path, val: V) {
- return this.reset(setIn(this.value, path, val));
+ return this.reset(setIn(this._value, path, val));
}
swap(fn: SwapFn, ...args: any[]) {
- return this.reset(fn.apply(null, [this.value, ...args]));
+ return this.reset(fn.apply(null, [this._value, ...args]));
}
swapIn(path: Path, fn: SwapFn, ...args: any[]) {
- return this.reset(updateIn(this.value, path, fn, ...args));
+ return this.reset(updateIn(this._value, path, fn, ...args));
}
// mixin stub
@@ -84,7 +92,7 @@ export class Atom implements
release() {
delete this._watches;
- delete this.value;
+ delete this._value;
return true;
}
}
diff --git a/packages/atom/src/cursor.ts b/packages/atom/src/cursor.ts
index e873b7d3b4..04e74535d7 100644
--- a/packages/atom/src/cursor.ts
+++ b/packages/atom/src/cursor.ts
@@ -112,6 +112,14 @@ export class Cursor implements
});
}
+ get value() {
+ return this.deref();
+ }
+
+ set value(val: T) {
+ this.reset(val);
+ }
+
deref() {
return this.local.deref();
}
diff --git a/packages/atom/src/history.ts b/packages/atom/src/history.ts
index 97a1b9a52e..fe473c38ce 100644
--- a/packages/atom/src/history.ts
+++ b/packages/atom/src/history.ts
@@ -53,6 +53,14 @@ export class History implements
this.clear();
}
+ get value() {
+ return this.deref();
+ }
+
+ set value(val: T) {
+ this.reset(val);
+ }
+
canUndo() {
return this.history.length > 0;
}
diff --git a/packages/atom/src/view.ts b/packages/atom/src/view.ts
index 20bfee3485..d0ae30f58c 100644
--- a/packages/atom/src/view.ts
+++ b/packages/atom/src/view.ts
@@ -88,6 +88,10 @@ export class View implements
});
}
+ get value() {
+ return this.deref();
+ }
+
/**
* Returns view's value. If the view has a transformer, the
* transformed value is returned. The transformer is only run once
diff --git a/packages/bench/CHANGELOG.md b/packages/bench/CHANGELOG.md
index 78a5a0e3e0..6b30f759bc 100644
--- a/packages/bench/CHANGELOG.md
+++ b/packages/bench/CHANGELOG.md
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+# [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/bench@0.1.5...@thi.ng/bench@0.2.0) (2018-08-28)
+
+
+### Features
+
+* **bench:** add opt prefix arg, update docs ([4a37367](https://github.com/thi-ng/umbrella/commit/4a37367))
+
+
+
+
## [0.1.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/bench@0.1.4...@thi.ng/bench@0.1.5) (2018-08-01)
diff --git a/packages/bench/package.json b/packages/bench/package.json
index cfb9dabf21..63ede8a722 100644
--- a/packages/bench/package.json
+++ b/packages/bench/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/bench",
- "version": "0.1.5",
+ "version": "0.2.0",
"description": "Basic benchmarking helpers",
"main": "./index.js",
"typings": "./index.d.ts",
diff --git a/packages/bench/src/index.ts b/packages/bench/src/index.ts
index d1dfe22447..370d9109f4 100644
--- a/packages/bench/src/index.ts
+++ b/packages/bench/src/index.ts
@@ -1,29 +1,35 @@
/**
* Calls function `fn` without args, prints elapsed time and returns
- * fn's result.
+ * fn's result. The optional `prefix` will be displayed with the output,
+ * allowing to label different measurements.
*
* @param fn
+ * @param prefix
*/
-export function timed(fn: () => T) {
+export function timed(fn: () => T, prefix = "") {
const t0 = Date.now();
const res = fn();
- console.log(Date.now() - t0);
+ console.log(prefix + (Date.now() - t0) + "ms");
return res;
}
/**
* Executes given function `n` times, prints elapsed time to console and
- * returns last result from fn.
+ * returns last result from fn. The optional `prefix` will be displayed
+ * with the output, allowing to label different measurements.
*
* @param fn
* @param n
*/
-export function bench(fn: () => T, n = 1e6) {
+export function bench(fn: () => T, n = 1e6, prefix = "") {
let res: T;
- return timed(() => {
- while (n-- > 0) {
- res = fn();
- }
- return res;
- });
+ return timed(
+ () => {
+ while (n-- > 0) {
+ res = fn();
+ }
+ return res;
+ },
+ prefix
+ );
}
diff --git a/packages/cache/CHANGELOG.md b/packages/cache/CHANGELOG.md
index f71c28c2f2..e0b09622f6 100644
--- a/packages/cache/CHANGELOG.md
+++ b/packages/cache/CHANGELOG.md
@@ -3,6 +3,22 @@
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/cache@0.2.18...@thi.ng/cache@0.2.19) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/cache
+
+
+## [0.2.18](https://github.com/thi-ng/umbrella/compare/@thi.ng/cache@0.2.17...@thi.ng/cache@0.2.18) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/cache
+
## [0.2.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/cache@0.2.16...@thi.ng/cache@0.2.17) (2018-08-24)
diff --git a/packages/cache/README.md b/packages/cache/README.md
index c63796d511..bf2d9cc442 100644
--- a/packages/cache/README.md
+++ b/packages/cache/README.md
@@ -34,8 +34,7 @@ yarn add @thi.ng/cache
- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api)
- [@thi.ng/dcons](https://github.com/thi-ng/umbrella/tree/master/packages/dcons)
-- [@thi.ng/equiv](https://github.com/thi-ng/umbrella/tree/master/packages/equiv)
-- [@thi.ng/iterators](https://github.com/thi-ng/umbrella/tree/master/packages/iterators)
+- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers)
## Usage examples
diff --git a/packages/cache/package.json b/packages/cache/package.json
index f0381899a5..a6becfdc31 100644
--- a/packages/cache/package.json
+++ b/packages/cache/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/cache",
- "version": "0.2.17",
+ "version": "0.2.19",
"description": "In-memory cache implementations with ES6 Map-like API and different eviction strategies",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -29,8 +29,8 @@
},
"dependencies": {
"@thi.ng/api": "^4.1.0",
- "@thi.ng/dcons": "^1.1.1",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/dcons": "^1.1.2",
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"cache",
diff --git a/packages/cache/src/lru.ts b/packages/cache/src/lru.ts
index f937a2d199..4c03175270 100644
--- a/packages/cache/src/lru.ts
+++ b/packages/cache/src/lru.ts
@@ -39,16 +39,16 @@ export class LRUCache implements ICache {
return this.entries();
}
- *entries(): IterableIterator]>> {
- yield* map((e) => <[K, CacheEntry]>[e.k, e], this.items);
+ entries(): IterableIterator]>> {
+ return map((e) => <[K, CacheEntry]>[e.k, e], this.items);
}
- *keys(): IterableIterator> {
- yield* map((e) => e.k, this.items);
+ keys(): IterableIterator> {
+ return map((e) => e.k, this.items);
}
- *values(): IterableIterator> {
- yield* map((e) => e.v, this.items);
+ values(): IterableIterator> {
+ return map((e) => e.v, this.items);
}
copy(): ICache {
diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md
index f99a8b6b78..9ed8d6839d 100644
--- a/packages/compose/CHANGELOG.md
+++ b/packages/compose/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.1.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/compose@0.1.0...@thi.ng/compose@0.1.1) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/compose
+
# 0.1.0 (2018-08-24)
diff --git a/packages/compose/README.md b/packages/compose/README.md
index bd0a07b06f..08bcb9efc7 100644
--- a/packages/compose/README.md
+++ b/packages/compose/README.md
@@ -9,6 +9,7 @@ This project is part of the
- [About](#about)
- [Installation](#installation)
+- [Dependencies](#dependencies)
- [Usage examples](#usage-examples)
- [Authors](#authors)
- [License](#license)
@@ -29,6 +30,11 @@ Functional composition helpers:
yarn add @thi.ng/compose
```
+## Dependencies
+
+- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api)
+- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors)
+
## Usage examples
```ts
diff --git a/packages/compose/package.json b/packages/compose/package.json
index abaa8daa6f..0c15ad06c0 100644
--- a/packages/compose/package.json
+++ b/packages/compose/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/compose",
- "version": "0.1.0",
+ "version": "0.1.1",
"description": "TODO",
"main": "./index.js",
"typings": "./index.d.ts",
diff --git a/packages/csp/CHANGELOG.md b/packages/csp/CHANGELOG.md
index 15be8c8c70..21670205a1 100644
--- a/packages/csp/CHANGELOG.md
+++ b/packages/csp/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.3.58](https://github.com/thi-ng/umbrella/compare/@thi.ng/csp@0.3.57...@thi.ng/csp@0.3.58) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/csp
+
## [0.3.57](https://github.com/thi-ng/umbrella/compare/@thi.ng/csp@0.3.56...@thi.ng/csp@0.3.57) (2018-08-24)
diff --git a/packages/csp/package.json b/packages/csp/package.json
index 3c5373942c..fd76b161eb 100644
--- a/packages/csp/package.json
+++ b/packages/csp/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/csp",
- "version": "0.3.57",
+ "version": "0.3.58",
"description": "ES6 promise based CSP implementation",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -34,9 +34,9 @@
"dependencies": {
"@thi.ng/api": "^4.1.0",
"@thi.ng/checks": "^1.5.7",
- "@thi.ng/dcons": "^1.1.1",
+ "@thi.ng/dcons": "^1.1.2",
"@thi.ng/errors": "^0.1.6",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"async",
diff --git a/packages/dcons/CHANGELOG.md b/packages/dcons/CHANGELOG.md
index 6c23b1c57d..a86da46ee7 100644
--- a/packages/dcons/CHANGELOG.md
+++ b/packages/dcons/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [1.1.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/dcons@1.1.1...@thi.ng/dcons@1.1.2) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/dcons
+
## [1.1.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/dcons@1.1.0...@thi.ng/dcons@1.1.1) (2018-08-24)
diff --git a/packages/dcons/README.md b/packages/dcons/README.md
index 1d72e193ea..7f28690af9 100644
--- a/packages/dcons/README.md
+++ b/packages/dcons/README.md
@@ -39,6 +39,7 @@ yarn add @thi.ng/dcons
- [@thi.ng/compare](https://github.com/thi-ng/umbrella/tree/master/packages/compare)
- [@thi.ng/equiv](https://github.com/thi-ng/umbrella/tree/master/packages/equiv)
- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors)
+- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers)
## Usage
diff --git a/packages/dcons/package.json b/packages/dcons/package.json
index da46f84b78..957fda4413 100644
--- a/packages/dcons/package.json
+++ b/packages/dcons/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/dcons",
- "version": "1.1.1",
+ "version": "1.1.2",
"description": "Comprehensive doubly linked list structure w/ iterator support",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -33,7 +33,7 @@
"@thi.ng/compare": "^0.1.6",
"@thi.ng/equiv": "^0.1.7",
"@thi.ng/errors": "^0.1.6",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"datastructure",
diff --git a/packages/dgraph/CHANGELOG.md b/packages/dgraph/CHANGELOG.md
index 1c3f7bb74e..6aea233e59 100644
--- a/packages/dgraph/CHANGELOG.md
+++ b/packages/dgraph/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.2.14](https://github.com/thi-ng/umbrella/compare/@thi.ng/dgraph@0.2.13...@thi.ng/dgraph@0.2.14) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/dgraph
+
## [0.2.13](https://github.com/thi-ng/umbrella/compare/@thi.ng/dgraph@0.2.12...@thi.ng/dgraph@0.2.13) (2018-08-24)
diff --git a/packages/dgraph/README.md b/packages/dgraph/README.md
index a5ea007034..2a7aa01601 100644
--- a/packages/dgraph/README.md
+++ b/packages/dgraph/README.md
@@ -27,7 +27,7 @@ yarn add @thi.ng/dgraph
- [@thi.ng/associative](https://github.com/thi-ng/umbrella/tree/master/packages/associative)
- [@thi.ng/equiv](https://github.com/thi-ng/umbrella/tree/master/packages/equiv)
- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors)
-- [@thi.ng/iterators](https://github.com/thi-ng/umbrella/tree/master/packages/iterators)
+- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers)
## Usage examples
diff --git a/packages/dgraph/package.json b/packages/dgraph/package.json
index 5407b22c52..28b217eeb3 100644
--- a/packages/dgraph/package.json
+++ b/packages/dgraph/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/dgraph",
- "version": "0.2.13",
+ "version": "0.2.14",
"description": "Type-agnostic directed acyclic graph (DAG) & graph operations",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -29,10 +29,10 @@
},
"dependencies": {
"@thi.ng/api": "^4.1.0",
- "@thi.ng/associative": "^0.6.1",
+ "@thi.ng/associative": "^0.6.2",
"@thi.ng/equiv": "^0.1.7",
"@thi.ng/errors": "^0.1.6",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"data structure",
diff --git a/packages/hdom-components/CHANGELOG.md b/packages/hdom-components/CHANGELOG.md
index 37b53729fb..6101bdc11d 100644
--- a/packages/hdom-components/CHANGELOG.md
+++ b/packages/hdom-components/CHANGELOG.md
@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [2.2.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-components@2.2.0...@thi.ng/hdom-components@2.2.1) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/hdom-components
+
+
+# [2.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-components@2.1.13...@thi.ng/hdom-components@2.2.0) (2018-08-27)
+
+
+### Bug Fixes
+
+* **hdom-components:** call canvas update from init() ([b25edbe](https://github.com/thi-ng/umbrella/commit/b25edbe))
+
+
+### Features
+
+* **hdom-components:** add HDPI adaptation helper for canvas comps ([135d6f1](https://github.com/thi-ng/umbrella/commit/135d6f1))
+
+
+
+
## [2.1.13](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-components@2.1.12...@thi.ng/hdom-components@2.1.13) (2018-08-24)
diff --git a/packages/hdom-components/README.md b/packages/hdom-components/README.md
index 16c08e8d0c..115ac685f9 100644
--- a/packages/hdom-components/README.md
+++ b/packages/hdom-components/README.md
@@ -35,7 +35,7 @@ yarn add @thi.ng/hdom-components
- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api)
- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/master/packages/checks)
-- [@thi.ng/iterators](https://github.com/thi-ng/umbrella/tree/master/packages/iterators)
+- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers)
## Usage examples
diff --git a/packages/hdom-components/package.json b/packages/hdom-components/package.json
index c6ebd07c01..e5a0fe915b 100644
--- a/packages/hdom-components/package.json
+++ b/packages/hdom-components/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/hdom-components",
- "version": "2.1.13",
+ "version": "2.2.1",
"description": "Raw, skinnable UI & SVG components for @thi.ng/hdom",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -30,7 +30,7 @@
"dependencies": {
"@thi.ng/api": "^4.1.0",
"@thi.ng/checks": "^1.5.7",
- "@thi.ng/transducers": "^2.0.1",
+ "@thi.ng/transducers": "^2.0.2",
"@types/webgl2": "^0.0.4"
},
"keywords": [
diff --git a/packages/hdom-components/src/canvas.ts b/packages/hdom-components/src/canvas.ts
index b836455f5c..8e5adca876 100644
--- a/packages/hdom-components/src/canvas.ts
+++ b/packages/hdom-components/src/canvas.ts
@@ -1,23 +1,28 @@
+export type CanvasContext =
+ CanvasRenderingContext2D |
+ WebGLRenderingContext |
+ WebGL2RenderingContext;
+
/**
* User provided canvas life cycle methods. These differ from the usual
* @thi.ng/hdom life cycle methods and are always passed at least the
* canvas DOM element, canvas context and hdom user context. Not all
* handlers need to be implemented.
*/
-export interface CanvasHandlers {
+export interface CanvasHandlers {
/**
* user init handler (called only once when canvas first)
*/
- init: (el: HTMLCanvasElement, gl: T, hctx?: any, ...args: any[]) => void;
+ init: (el: HTMLCanvasElement, ctx: T, hctx?: any, ...args: any[]) => void;
/**
* update handler (called for each hdom update iteration)
*/
- update: (el: HTMLCanvasElement, gl: T, hctx?: any, time?: number, frame?: number, ...args: any[]) => void;
+ update: (el: HTMLCanvasElement, ctx: T, hctx?: any, time?: number, frame?: number, ...args: any[]) => void;
/**
* release handler (called only once when canvas element is removed
* from DOM)
*/
- release: (el: HTMLCanvasElement, gl: T, hctx?: any, ...args: any[]) => void;
+ release: (el: HTMLCanvasElement, ctx: T, hctx?: any, ...args: any[]) => void;
}
/**
@@ -35,9 +40,11 @@ const _canvas = (type, { init, update, release }: Partial>,
return {
init(_el: HTMLCanvasElement, hctx: any, ...args: any[]) {
el = _el;
+ adaptDPI(el, el.width, el.height);
ctx = el.getContext(type, opts);
time = Date.now();
init && init(el, ctx, hctx, ...args);
+ update && update(el, ctx, hctx, time, frame++, ...args);
},
render(hctx: any, ...args: any[]) {
ctx && update && update(el, ctx, hctx, Date.now() - time, frame++, ...args);
@@ -98,3 +105,23 @@ export const canvas2D = (
handlers: Partial>,
opts?: Canvas2DContextAttributes) =>
_canvas("2d", handlers, opts);
+
+/**
+ * Sets the canvas size to given `width` & `height` and adjusts style to
+ * compensate for HDPI devices. Note: For 2D canvases, this will
+ * automatically clear any prior canvas content.
+ *
+ * @param canvas
+ * @param width uncompensated pixel width
+ * @param height uncompensated pixel height
+ */
+export const adaptDPI = (canvas: HTMLCanvasElement, width: number, height: number) => {
+ const dpr = window.devicePixelRatio || 1;
+ if (dpr != 1) {
+ canvas.style.width = `${width}px`;
+ canvas.style.height = `${height}px`;
+ }
+ canvas.width = width * dpr;
+ canvas.height = height * dpr;
+ return dpr;
+};
diff --git a/packages/hdom/CHANGELOG.md b/packages/hdom/CHANGELOG.md
index 204b12d3e3..fa944eff34 100644
--- a/packages/hdom/CHANGELOG.md
+++ b/packages/hdom/CHANGELOG.md
@@ -3,6 +3,39 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [4.0.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom@4.0.0...@thi.ng/hdom@4.0.1) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/hdom
+
+
+# [4.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom@3.0.35...@thi.ng/hdom@4.0.0) (2018-08-31)
+
+
+### Features
+
+* **hdom:** add DOM hydration support (SSR), update start() ([#39](https://github.com/thi-ng/umbrella/issues/39)) ([9f8010d](https://github.com/thi-ng/umbrella/commit/9f8010d))
+* **hdom:** update HDOMOpts & start() ([5e74a9c](https://github.com/thi-ng/umbrella/commit/5e74a9c))
+
+
+### BREAKING CHANGES
+
+* **hdom:** start() args now as options object
+
+
+
+
+
+## [3.0.35](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom@3.0.34...@thi.ng/hdom@3.0.35) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/hdom
+
## [3.0.34](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom@3.0.33...@thi.ng/hdom@3.0.34) (2018-08-24)
diff --git a/packages/hdom/README.md b/packages/hdom/README.md
index 85f7a5ba30..b3056471cb 100644
--- a/packages/hdom/README.md
+++ b/packages/hdom/README.md
@@ -8,7 +8,20 @@ This project is part of the
- [About](#about)
- - [Minimal example](#minimal-example)
+ - [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)
+- [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)
+ - [Dataflow graph SVG components](#dataflow-graph-svg-components)
+ - [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)
@@ -18,20 +31,6 @@ This project is part of the
- [Usage](#usage)
- [User context injection](#user-context-injection)
- [Component objects & life cycle methods](#component-objects--life-cycle-methods)
-- [Example projects](#example-projects)
- - [Interactive SVG grid generator](#interactive-svg-grid-generator)
- - [Interactive additive waveform visualization](#interactive-additive-waveform-visualization)
- - [Dataflow graph SVG components](#dataflow-graph-svg-components)
- - [SPA with router and event bus](#spa-with-router-and-event-bus)
- - [Additive waveform synthesis & SVG visualization](#additive-waveform-synthesis--svg-visualization)
- - [Multiple apps with & without shared state](#multiple-apps-with--without-shared-state)
- - [Interceptor based event handling](#interceptor-based-event-handling)
- - [Todo list](#todo-list)
- - [Cellular automata](#cellular-automata)
- - [SVG particles](#svg-particles)
- - [JSON based components](#json-based-components)
- - [@thi.ng/rstream dataflow graph](#thingrstream-dataflow-graph)
- - [Basic usage patterns](#basic-usage-patterns)
- [Benchmark](#benchmark)
- [Authors](#authors)
- [License](#license)
@@ -40,10 +39,12 @@ This project is part of the
## About
-Lightweight reactive DOM components & VDOM implementation using only
+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
@@ -52,19 +53,22 @@ closures, iterators), based on
- [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
- 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))
- Optional user context injection (an arbitrary object passed to all
component functions)
-- auto-deref of embedded value wrappers which implement the
- [@thi.ng/api/IDeref](https://github.com/thi-ng/umbrella/tree/master/packages/api/api)
+- CSS conversion from JS objects for `style` attribs (for full
+ hiccup-based CSS-in-JS generation 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.)
-- CSS conversion from JS objects for `style` attribs
-- Suitable for server side rendering (by passing the same data structure
- to @thi.ng/hiccup's `serialize()`)
- Fairly fast (see benchmark example below)
-- Only ~4.4KB gzipped
+- Only ~5KB gzipped
In addition to the descriptions in this file, [further information and
examples are available in the
@@ -74,7 +78,7 @@ Also see the [work-in-progress
ADRs](https://github.com/thi-ng/umbrella/tree/master/packages/hdom-components/adr/)
for component configuration.
-### Minimal example
+### Minimal example #1: Local state, RAF update
```ts
import * as hdom from "@thi.ng/hdom";
@@ -97,7 +101,7 @@ const app = () => {
};
// start update loop (browser only, see diagram below)
-hdom.start(document.body, app());
+hdom.start(app(), { root: document.body });
// alternatively apply DOM tree only once
// (stateful components won't update though)
@@ -118,11 +122,139 @@ console.log(serialize(app()));
// hello world
```
-No template engine & no pre-compilation steps needed, just use the full
-expressiveness of ES6/TypeScript to define your DOM tree. Using
-TypeScript gives the additional benefit of making UI components strongly
-typed, and since they're just normal functions, can use generics,
-overrides, varargs etc.
+### Minimal example #2 (reactive state & transducer update)
+
+This example uses 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
+diffing via RAF).
+
+```ts
+import * as rs from "@thi.ng/rstream/stream";
+import * as tx from "@thi.ng/rstream/transducers";
+import { updateDOM } from "@thi.ng/rstream/transducers-hdom";
+
+// root component function
+const app = ({ ticks, clicks }) =>
+ ["div",
+ `${ticks} ticks & `,
+ ["a",
+ { href: "#", onclick: () => clickStream.next(0)},
+ `${clicks} clicks`]
+ ];
+
+// click stream (click counter)
+const clickStream = rs.stream().transform(tx.scan(tx.count(-1)));
+
+// stream combinator
+// waits until all inputs have produced at least one value,
+// then updates whenever any input has changed
+rs.sync({
+ // streams to synchronize
+ src: {
+ ticks: rs.fromInterval(1000),
+ clicks: clickStream,
+ },
+}).transform(
+ // transform tuple into hdom component
+ tx.map(app),
+ // apply hdom tree to real DOM
+ updateDOM({ root: document.body })
+);
+
+// kick off
+clickStream.next(0);
+```
+
+[Live demo](https://demo.thi.ng/umbrella/transducers-hdom/) |
+[standalone example](https://github.com/thi-ng/umbrella/tree/master/examples/transducers-hdom)
+
+## Example projects
+
+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.
+
+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 & SVG 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.png)
+
+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/)
+
+### 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, this is one of the
+more advanced demos, combining functionality of several other @thi.ng
+packages.
+
+[Source](https://github.com/thi-ng/umbrella/tree/master/examples/router-basics)
+| [Live version](https://demo.thi.ng/umbrella/router-basics/)
+
+### Multiple apps with & without shared state
+
+Devcards style BMI calculator(s) with basic SVG viz.
+
+[Source](https://github.com/thi-ng/umbrella/tree/master/examples/devcards)
+| [Live version](https://demo.thi.ng/umbrella/devcards/)
+
+### Interceptor based event handling
+
+[Source](https://github.com/thi-ng/umbrella/tree/master/examples/interceptor-basics)
+| [Live version](https://demo.thi.ng/umbrella/interceptor-basics/)
+
+### Todo list (w/ undo/redo)
+
+[Source](https://github.com/thi-ng/umbrella/tree/master/examples/todo-list)
+| [Live version](https://demo.thi.ng/umbrella/todo-list/)
+
+### SVG particles
+
+[Source](https://github.com/thi-ng/umbrella/tree/master/examples/svg-particles)
+| [Live version](https://demo.thi.ng/umbrella/svg-particles/)
### Component tree translation
@@ -132,6 +264,9 @@ JS arrays). Components can be defined as static arrays, closures or
objects with [life cycle methods](#lifecycle-methods) (init, render,
release).
+**Note: hdom uses a RAF render loop only by default, but is absolutely
+no way tied to this.**
+
![hdom dataflow](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/hdom-dataflow.png)
The syntax is inspired by Clojure's
@@ -164,9 +299,8 @@ provided by these packages:
## Status
The overall "API" is stable, but there's further work planned on
-generalizing the approach beyond standard browser DOM use cases (planned
-for v4.0.0). The project has been used for several projects in
-production since 2016.
+generalizing the approach beyond standard browser DOM use cases. The
+project has been used for several projects in production since 2016.
## Installation
@@ -194,7 +328,6 @@ yarn start
- [@thi.ng/diff](https://github.com/thi-ng/umbrella/tree/master/packages/diff)
- [@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)
-- [@thi.ng/iterators](https://github.com/thi-ng/umbrella/tree/master/packages/iterators)
## Usage
@@ -205,7 +338,7 @@ 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(parent: Element | string, tree: any, ctx?: any, path?: number[], keys?: boolean, span?: boolean): () => boolean`
+#### `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 a parent DOM
@@ -229,10 +362,14 @@ 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.
-**Important:** The parent element given is assumed to have NO children at
-the time when `start()` is called. Since hdom does NOT track the real
-DOM, the resulting changes will result in potentially undefined behavior
-if the parent element wasn't empty.
+**Important:** Unless the `hydrate` option is enabled, the parent
+element given is assumed to have NO children at the time when `start()`
+is called. Since hdom does NOT track the real DOM, the resulting changes
+will result in potentially undefined behavior if the parent element
+wasn't empty. Likewise, if `hydrate` is enabled, it is assumed that an
+equivalent DOM (minus listeners) already exists (i.e. generated via SSR)
+when `start()` is called. Any other discrepancies between the
+pre-existing DOM and the hdom trees will cause undefined behavior.
Returns a function, which when called, immediately cancels the update
loop.
@@ -290,6 +427,14 @@ of elements, if the provided tree is an iterable. Creates DOM text nodes
for non-component values. Returns `parent` if tree is `null` or
`undefined`.
+#### `hydrateDOM(parent: Element, tag: any)`
+
+Takes a DOM root element and normalized hdom tree, then walks tree and
+initializes any event listeners and components with lifecycle init
+methods. Assumes that an equivalent DOM (minus listeners) already exists
+(e.g. generated via SSR) when called. Any other discrepancies between
+the pre-existing DOM and the hdom tree will cause undefined behavior.
+
### User context injection
Since v3.0.0 hdom offers support for an arbitrary "context" object
@@ -349,7 +494,7 @@ const root = [
];
// start hdom update loop
-start("app", root, ctx);
+start(root, { ctx });
```
### Component objects & life cycle methods
@@ -421,8 +566,8 @@ const canvas = () => {
// usage scenario #1: static component
// inline initialization is okay here...
start(
- document.body,
- [canvas(), { width: 100, height: 100 }, "Hello world"]
+ [canvas(), { width: 100, height: 100 }, "Hello world"],
+ { root: document.body }
);
@@ -445,89 +590,9 @@ const app = () => {
];
};
-start(document.body, app());
+start(app(), { root: document.body });
```
-## Example projects
-
-Most of the
-[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.
-
-Non-exhaustive list:
-
-### Interactive SVG grid generator
-
-[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
-
-[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
-
-This is a preview of the upcoming
-[@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/)
-
-### SPA with router and event bus
-
-Based on the `create-hdom-app` project scaffolding, this is one of the
-more advanced demos, combining functionality of several other @thi.ng
-packages.
-
-[Source](https://github.com/thi-ng/umbrella/tree/master/examples/router-basics) | [Live version](https://demo.thi.ng/umbrella/router-basics/)
-
-### Additive waveform synthesis & SVG visualization
-
-[Source](https://github.com/thi-ng/umbrella/tree/master/examples/svg-waveform) | [Live version](https://demo.thi.ng/umbrella/svg-waveform/)
-
-### Multiple apps with & without shared state
-
-Devcards style BMI calculator(s) with basic SVG viz.
-
-[Source](https://github.com/thi-ng/umbrella/tree/master/examples/devcards) | [Live version](https://demo.thi.ng/umbrella/devcards/)
-
-### Interceptor based event handling
-
-[Source](https://github.com/thi-ng/umbrella/tree/master/examples/interceptor-basics) | [Live version](https://demo.thi.ng/umbrella/interceptor-basics/)
-
-### Todo list
-
-A fully documented, obligatory todo list app with undo / redo.
-
-[Source](https://github.com/thi-ng/umbrella/tree/master/examples/todo-list) | [Live version](https://demo.thi.ng/umbrella/todo-list/)
-
-### Cellular automata
-
-[Source](https://github.com/thi-ng/umbrella/tree/master/examples/cellular-automata) | [Live version](https://demo.thi.ng/umbrella/cellular-automata/)
-
-### SVG particles
-
-[Source](https://github.com/thi-ng/umbrella/tree/master/examples/svg-particles) | [Live version](https://demo.thi.ng/umbrella/svg-particles/)
-
-### JSON based components
-
-[Source](https://github.com/thi-ng/umbrella/tree/master/examples/json-components) | [Live version](https://demo.thi.ng/umbrella/json-components/)
-
-### @thi.ng/rstream dataflow graph
-
-A small, interactive dataflow graph example:
-
-[Source](https://github.com/thi-ng/umbrella/tree/master/examples/rstream-dataflow) | [Live version](https://demo.thi.ng/umbrella/rstream-dataflow)
-
-### Basic usage patterns
-
-The code below is also available as standalone project in: [/examples/dashboard](https://github.com/thi-ng/umbrella/tree/master/examples/dashboard)
-
-[Source](https://github.com/thi-ng/umbrella/tree/master/examples/dashboard) | [Live version](https://demo.thi.ng/umbrella/dashboard/)
-
### Benchmark
A stress test benchmark is here:
@@ -540,8 +605,8 @@ Twitter](https://twitter.com/toxi/status/959246871339454464),
performance should be more than acceptable for even quite demanding UIs.
In the 192 / 256 cells configurations **this stress test causes approx.
600 / 800 DOM every single frame**, very unlikely for a typical web app.
-In Chrome 64 on a MBP2016 this still runs at a stable 60fps (192 cells)
-/ 32fps (256 cells). Both FPS readings based the 50 frame
+In Chrome 68 on a MBP2016 this still runs at a stable 60fps (192 cells)
+/ 37fps (256 cells). Both FPS readings based the 50 frame
[SMA](https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average).
## Authors
diff --git a/packages/hdom/package.json b/packages/hdom/package.json
index de3a3af50c..caa7da861a 100644
--- a/packages/hdom/package.json
+++ b/packages/hdom/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/hdom",
- "version": "3.0.34",
+ "version": "4.0.1",
"description": "Lightweight vanilla ES6 UI component & virtual DOM system",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -20,7 +20,7 @@
"test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js"
},
"devDependencies": {
- "@thi.ng/atom": "^1.4.7",
+ "@thi.ng/atom": "^1.5.0",
"@types/mocha": "^5.2.5",
"@types/node": "^10.5.5",
"mocha": "^5.2.0",
@@ -33,7 +33,7 @@
"@thi.ng/checks": "^1.5.7",
"@thi.ng/diff": "^1.0.22",
"@thi.ng/equiv": "^0.1.7",
- "@thi.ng/hiccup": "^2.0.10"
+ "@thi.ng/hiccup": "^2.1.0"
},
"keywords": [
"browser",
diff --git a/packages/hdom/src/api.ts b/packages/hdom/src/api.ts
index 7d32a1e5fd..461285df3d 100644
--- a/packages/hdom/src/api.ts
+++ b/packages/hdom/src/api.ts
@@ -16,4 +16,37 @@ export interface ComponentAttribs {
[_: string]: any;
}
+export 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), text content will be wrapped in ``
+ */
+ span?: boolean;
+ /**
+ * If true (default false), the first frame will only be used to
+ * inject event listeners.
+ *
+ * *Important:* Enabling this option assumes that an equivalent DOM
+ * (minus listeners) already exists (i.e. generated via SSR) when
+ * hdom's `start()` function is called. Any other discrepancies
+ * between the pre-existing DOM and the hdom trees will cause
+ * undefined behavior.
+ */
+ hydrate?: boolean;
+ /**
+ * If true (default), the hdom component tree will be first
+ * normalized before diffing (using `normalizeTree()`). Unless you
+ * know what you're doing, it's best to leave this enabled.
+ */
+ normalize?: boolean;
+}
+
export const DEBUG = false;
diff --git a/packages/hdom/src/diff.ts b/packages/hdom/src/diff.ts
index 9195b9fa2e..50f4df0dab 100644
--- a/packages/hdom/src/diff.ts
+++ b/packages/hdom/src/diff.ts
@@ -34,11 +34,10 @@ const isString = iss.isString;
* @param prev previous tree
* @param curr current tree
*/
-export function diffElement(root: Element, prev: any, curr: any) {
+export const diffElement = (root: Element, prev: any, curr: any) =>
_diffElement(root, prev, curr, 0);
-}
-function _diffElement(parent: Element, prev: any, curr: any, child: number) {
+const _diffElement = (parent: Element, prev: any, curr: any, child: number) => {
const delta = diffArray(prev, curr, equiv, true);
if (delta.distance === 0) {
return;
@@ -109,9 +108,9 @@ function _diffElement(parent: Element, prev: any, curr: any, child: number) {
// DEBUG && console.log("call __init", curr);
i.apply(curr, [el, ...(curr.__args)]);
}
-}
+};
-function releaseDeep(tag: any) {
+const releaseDeep = (tag: any) => {
if (isArray(tag)) {
if ((tag).__release) {
// DEBUG && console.log("call __release", tag);
@@ -122,9 +121,9 @@ function releaseDeep(tag: any) {
releaseDeep(tag[i]);
}
}
-}
+};
-function diffAttributes(el: Element, prev: any, curr: any) {
+const diffAttributes = (el: Element, prev: any, curr: any) => {
let i, e, edits;
const delta = diffObject(prev, curr);
removeAttribs(el, delta.dels, prev);
@@ -152,9 +151,9 @@ function diffAttributes(el: Element, prev: any, curr: any) {
if (value !== SEMAPHORE) {
setAttrib(el, "value", value, curr);
}
-}
+};
-function extractEquivElements(edits: DiffLogEntry[]) {
+const extractEquivElements = (edits: DiffLogEntry[]) => {
let k, v, e, ek;
const equiv = {};
for (let i = edits.length; --i >= 0;) {
@@ -167,4 +166,4 @@ function extractEquivElements(edits: DiffLogEntry[]) {
}
}
return equiv;
-}
+};
diff --git a/packages/hdom/src/dom.ts b/packages/hdom/src/dom.ts
index d9706d9d20..bc06b5b1ea 100644
--- a/packages/hdom/src/dom.ts
+++ b/packages/hdom/src/dom.ts
@@ -23,7 +23,7 @@ const isString = iss.isString;
* @param tag
* @param insert
*/
-export function createDOM(parent: Element, tag: any, insert?: number) {
+export const createDOM = (parent: Element, tag: any, insert?: number) => {
if (isArray(tag)) {
const t = tag[0];
if (isFunction(t)) {
@@ -52,9 +52,47 @@ export function createDOM(parent: Element, tag: any, insert?: number) {
return parent;
}
return createTextElement(parent, tag);
-}
+};
-export function createElement(parent: Element, tag: string, attribs?: any, insert?: number) {
+/**
+ * Takes a DOM root element and normalized hdom tree, then walks tree
+ * and initializes any event listeners and components with lifecycle
+ * `init` methods. Assumes that an equivalent DOM (minus listeners)
+ * already exists (e.g. generated via SSR) when called. Any other
+ * discrepancies between the pre-existing DOM and the hdom tree will
+ * cause undefined behavior.
+ *
+ * @param parent
+ * @param tree
+ * @param i
+ */
+export const hydrateDOM = (parent: Element, tree: any, i = 0) => {
+ if (isArray(tree)) {
+ const el = parent.children[i];
+ if (isFunction(tree[0])) {
+ return hydrateDOM(parent, tree[0].apply(null, tree.slice(1)), i);
+ }
+ if ((tree).__init) {
+ (tree).__init.apply((tree).__this, [el, ...(tree).__args]);
+ }
+ const attr = tree[1];
+ for (let a in attr) {
+ if (a.indexOf("on") === 0) {
+ el.addEventListener(a.substr(2), attr[a]);
+ }
+ }
+ for (let n = tree.length, i = 2; i < n; i++) {
+ hydrateDOM(el, tree[i], i - 2);
+ }
+ } else if (!isString(tree) && isIterable(tree)) {
+ for (let t of tree) {
+ hydrateDOM(parent, t, i);
+ i++;
+ }
+ }
+};
+
+export const createElement = (parent: Element, tag: string, attribs?: any, insert?: number) => {
const el = SVG_TAGS[tag] ?
document.createElementNS(SVG_NS, tag) :
document.createElement(tag);
@@ -69,9 +107,9 @@ export function createElement(parent: Element, tag: string, attribs?: any, inser
setAttribs(el, attribs);
}
return el;
-}
+};
-export function createTextElement(parent: Element, content: string, insert?: number) {
+export const createTextElement = (parent: Element, content: string, insert?: number) => {
const el = document.createTextNode(content);
if (parent) {
if (insert === undefined) {
@@ -81,21 +119,21 @@ export function createTextElement(parent: Element, content: string, insert?: num
}
}
return el;
-}
+};
-export function cloneWithNewAttribs(el: Element, attribs: any) {
+export const cloneWithNewAttribs = (el: Element, attribs: any) => {
const res = el.cloneNode(true);
setAttribs(res, attribs);
el.parentNode.replaceChild(res, el);
return res;
-}
+};
-export function setAttribs(el: Element, attribs: any) {
+export const setAttribs = (el: Element, attribs: any) => {
for (let k in attribs) {
setAttrib(el, k, attribs[k], attribs);
}
return el;
-}
+};
/**
* Sets a single attribute on given element. If attrib name is NOT
@@ -118,7 +156,7 @@ export function setAttribs(el: Element, attribs: any) {
* @param val
* @param attribs
*/
-export function setAttrib(el: Element, id: string, val: any, attribs?: any) {
+export const setAttrib = (el: Element, id: string, val: any, attribs?: any) => {
const isListener = id.indexOf("on") === 0;
if (!isListener && isFunction(val)) {
val = val(attribs);
@@ -146,9 +184,9 @@ export function setAttrib(el: Element, id: string, val: any, attribs?: any) {
el[id] != null ? (el[id] = null) : el.removeAttribute(id);
}
return el;
-}
+};
-export function updateValueAttrib(el: HTMLInputElement, v: any) {
+export const updateValueAttrib = (el: HTMLInputElement, v: any) => {
switch (el.type) {
case "text":
case "textarea":
@@ -166,9 +204,9 @@ export function updateValueAttrib(el: HTMLInputElement, v: any) {
default:
el.value = v;
}
-}
+};
-export function removeAttribs(el: Element, attribs: string[], prev: any) {
+export const removeAttribs = (el: Element, attribs: string[], prev: any) => {
for (let i = attribs.length; --i >= 0;) {
const a = attribs[i];
if (a.indexOf("on") === 0) {
@@ -177,20 +215,17 @@ export function removeAttribs(el: Element, attribs: string[], prev: any) {
el[a] ? (el[a] = null) : el.removeAttribute(a);
}
}
-}
+};
-export function setStyle(el: Element, styles: any) {
- el.setAttribute("style", css(styles));
- return el;
-}
+export const setStyle = (el: Element, styles: any) =>
+ (el.setAttribute("style", css(styles)), el);
-export function clearDOM(el: Element) {
+export const clearDOM = (el: Element) =>
el.innerHTML = "";
-}
-export function removeChild(parent: Element, childIdx: number) {
+export const removeChild = (parent: Element, childIdx: number) => {
const n = parent.children[childIdx];
if (n !== undefined) {
n.remove();
}
-}
+};
diff --git a/packages/hdom/src/normalize.ts b/packages/hdom/src/normalize.ts
index cbda166bb5..725ce30e00 100644
--- a/packages/hdom/src/normalize.ts
+++ b/packages/hdom/src/normalize.ts
@@ -5,7 +5,7 @@ import * as isi from "@thi.ng/checks/is-iterable";
import * as iso from "@thi.ng/checks/is-plain-object";
import * as iss from "@thi.ng/checks/is-string";
import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
-import { TAG_REGEXP } from "@thi.ng/hiccup/api";
+import { NO_SPANS, TAG_REGEXP } from "@thi.ng/hiccup/api";
const isArray = isa.isArray;
const isFunction = isf.isFunction;
@@ -38,7 +38,7 @@ const isString = iss.isString;
* @param spec
* @param keys
*/
-export function normalizeElement(spec: any[], keys: boolean) {
+export const normalizeElement = (spec: any[], keys: boolean) => {
let tag = spec[0], hasAttribs = isPlainObject(spec[1]), match, id, clazz, attribs;
if (!isString(tag) || !(match = TAG_REGEXP.exec(tag))) {
illegalArgs(`${tag} is not a valid tag name`);
@@ -62,12 +62,6 @@ export function normalizeElement(spec: any[], keys: boolean) {
}
}
return [match[1], attribs, ...spec.slice(hasAttribs ? 2 : 1)];
-}
-
-const NO_SPANS = {
- option: 1,
- text: 1,
- textarea: 1,
};
/**
@@ -111,7 +105,7 @@ const NO_SPANS = {
* @param keys
* @param span
*/
-export function normalizeTree(tree: any, ctx?: any, path = [0], keys = true, span = true) {
+export const normalizeTree = (tree: any, ctx?: any, path = [0], keys = true, span = true) => {
if (tree == null) {
return;
}
@@ -182,4 +176,4 @@ export function normalizeTree(tree: any, ctx?: any, path = [0], keys = true, spa
return span ?
["span", keys ? { key: path.join("-") } : {}, tree.toString()] :
tree.toString();
-}
+};
diff --git a/packages/hdom/src/start.ts b/packages/hdom/src/start.ts
index b513daf36d..d40f7ce45b 100644
--- a/packages/hdom/src/start.ts
+++ b/packages/hdom/src/start.ts
@@ -1,6 +1,9 @@
import { isString } from "@thi.ng/checks/is-string";
+
+import { HDOMOpts } from "./api";
import { diffElement } from "./diff";
import { normalizeTree } from "./normalize";
+import { hydrateDOM } from "@thi.ng/hdom/src/dom";
/**
* Takes a parent DOM element (or ID), hiccup tree (array, function or
@@ -23,36 +26,47 @@ import { normalizeTree } from "./normalize";
* which then is diffed and applied against the previous tree kept as
* usual. Any number of frames may be skipped this way.
*
- * Important: The parent element given is assumed to have NO children at
- * the time when `start()` is called. Since hdom does NOT track the real
- * DOM, the resulting changes will result in potentially undefined
- * behavior if the parent element wasn't empty.
+ * **Important:** Unless the `hydrate` option is enabled, the parent
+ * element given is assumed to have NO children at the time when
+ * `start()` is called. Since hdom does NOT track the real DOM, the
+ * resulting changes will result in potentially undefined behavior if
+ * the parent element wasn't empty. Likewise, if `hydrate` is enabled,
+ * it is assumed that an equivalent DOM (minus listeners) already exists
+ * (i.e. generated via SSR) when `start()` is called. Any other
+ * discrepancies between the pre-existing DOM and the hdom trees will
+ * cause undefined behavior.
*
* Returns a function, which when called, immediately cancels the update
* loop.
*
- * @param parent root element or ID
* @param tree hiccup DOM tree
- * @param ctx arbitrary user context object
- * @param spans true (default), if text should be wrapped in ``
+ * @param opts options
*/
-export function start(parent: Element | string, tree: any, ctx?: any, spans = true) {
+export const start = (tree: any, opts?: Partial) => {
+ opts = { root: "app", span: true, normalize: true, ...opts };
let prev = [];
let isActive = true;
- parent = isString(parent) ?
- document.getElementById(parent) :
- parent;
- function update() {
+ const root = isString(opts.root) ?
+ document.getElementById(opts.root) :
+ opts.root;
+ const update = () => {
if (isActive) {
- const curr = normalizeTree(tree, ctx, [0], true, spans);
+ const curr = opts.normalize ?
+ normalizeTree(tree, opts.ctx, [0], true, opts.span) :
+ tree;
if (curr != null) {
- diffElement(parent, prev, curr);
+ if (opts.hydrate) {
+ hydrateDOM(root, curr);
+ opts.hydrate = false;
+ } else {
+ diffElement(root, prev, curr);
+ }
prev = curr;
}
// check again in case one of the components called cancel
isActive && requestAnimationFrame(update);
}
- }
+ };
requestAnimationFrame(update);
return () => (isActive = false);
-}
+};
diff --git a/packages/hiccup-css/CHANGELOG.md b/packages/hiccup-css/CHANGELOG.md
index f2a0f5e5b1..adbccdea69 100644
--- a/packages/hiccup-css/CHANGELOG.md
+++ b/packages/hiccup-css/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.2.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-css@0.2.16...@thi.ng/hiccup-css@0.2.17) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/hiccup-css
+
## [0.2.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-css@0.2.15...@thi.ng/hiccup-css@0.2.16) (2018-08-24)
diff --git a/packages/hiccup-css/package.json b/packages/hiccup-css/package.json
index 751631f270..a5c5348e3c 100644
--- a/packages/hiccup-css/package.json
+++ b/packages/hiccup-css/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/hiccup-css",
- "version": "0.2.16",
+ "version": "0.2.17",
"description": "CSS from nested JS data structures",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -31,7 +31,7 @@
"@thi.ng/api": "^4.1.0",
"@thi.ng/checks": "^1.5.7",
"@thi.ng/errors": "^0.1.6",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"clojure",
diff --git a/packages/hiccup-svg/CHANGELOG.md b/packages/hiccup-svg/CHANGELOG.md
index 6395ebf2d5..8c6264826e 100644
--- a/packages/hiccup-svg/CHANGELOG.md
+++ b/packages/hiccup-svg/CHANGELOG.md
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [1.0.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-svg@1.0.11...@thi.ng/hiccup-svg@1.0.12) (2018-08-31)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/hiccup-svg
+
+
+## [1.0.11](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-svg@1.0.10...@thi.ng/hiccup-svg@1.0.11) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/hiccup-svg
+
## [1.0.10](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-svg@1.0.9...@thi.ng/hiccup-svg@1.0.10) (2018-08-24)
diff --git a/packages/hiccup-svg/package.json b/packages/hiccup-svg/package.json
index e7b8d23648..b31197f38b 100644
--- a/packages/hiccup-svg/package.json
+++ b/packages/hiccup-svg/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/hiccup-svg",
- "version": "1.0.10",
+ "version": "1.0.12",
"description": "SVG element functions for @thi.ng/hiccup & @thi.ng/hdom",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -28,7 +28,7 @@
"typescript": "^3.0.1"
},
"dependencies": {
- "@thi.ng/hiccup": "^2.0.10"
+ "@thi.ng/hiccup": "^2.1.0"
},
"keywords": [
"components",
diff --git a/packages/hiccup/CHANGELOG.md b/packages/hiccup/CHANGELOG.md
index 72b40acabe..fdded8e71e 100644
--- a/packages/hiccup/CHANGELOG.md
+++ b/packages/hiccup/CHANGELOG.md
@@ -3,6 +3,31 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+# [2.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup@2.0.11...@thi.ng/hiccup@2.1.0) (2018-08-31)
+
+
+### Bug Fixes
+
+* **hiccup:** disable spans for certain element types ([1b97a25](https://github.com/thi-ng/umbrella/commit/1b97a25))
+* **hiccup:** serialize() args ([1e8b4ef](https://github.com/thi-ng/umbrella/commit/1e8b4ef))
+
+
+### Features
+
+* **hiccup:** add optional support for spans & auto keying ([#39](https://github.com/thi-ng/umbrella/issues/39)) ([1b0deb2](https://github.com/thi-ng/umbrella/commit/1b0deb2))
+
+
+
+
+
+## [2.0.11](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup@2.0.10...@thi.ng/hiccup@2.0.11) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/hiccup
+
## [2.0.10](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup@2.0.9...@thi.ng/hiccup@2.0.10) (2018-08-24)
diff --git a/packages/hiccup/package.json b/packages/hiccup/package.json
index 38636e955e..bafe767581 100644
--- a/packages/hiccup/package.json
+++ b/packages/hiccup/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/hiccup",
- "version": "2.0.10",
+ "version": "2.1.0",
"description": "HTML/SVG/XML serialization of nested data structures, iterables & closures",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -20,7 +20,7 @@
"test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js"
},
"devDependencies": {
- "@thi.ng/atom": "^1.4.7",
+ "@thi.ng/atom": "^1.5.0",
"@types/mocha": "^5.2.5",
"@types/node": "^10.5.5",
"mocha": "^5.2.0",
diff --git a/packages/hiccup/src/api.ts b/packages/hiccup/src/api.ts
index f6b68d41f9..22d3c1c47c 100644
--- a/packages/hiccup/src/api.ts
+++ b/packages/hiccup/src/api.ts
@@ -21,4 +21,10 @@ export const ENTITIES = {
"'": "'",
};
+export const NO_SPANS = {
+ option: 1,
+ text: 1,
+ textarea: 1,
+};
+
export const ENTITY_RE = new RegExp(`[${Object.keys(ENTITIES)}]`, "g");
diff --git a/packages/hiccup/src/serialize.ts b/packages/hiccup/src/serialize.ts
index 501d223177..9d8aeffe9a 100644
--- a/packages/hiccup/src/serialize.ts
+++ b/packages/hiccup/src/serialize.ts
@@ -1,11 +1,12 @@
-import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
import { implementsFunction } from "@thi.ng/checks/implements-function";
import { isFunction } from "@thi.ng/checks/is-function";
import { isPlainObject } from "@thi.ng/checks/is-plain-object";
import { isString } from "@thi.ng/checks/is-string";
+import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
-import { TAG_REGEXP, VOID_TAGS } from "./api";
+import { NO_SPANS, TAG_REGEXP, VOID_TAGS } from "./api";
import { css } from "./css";
+import { escape } from "./escape";
/**
* Recursively normalizes and serializes given tree as HTML/SVG/XML
@@ -74,12 +75,24 @@ import { css } from "./css";
* strings, numbers, iterables or any type with a suitable `.toString()`
* implementation).
*
- * @param tree elements / component tree
+ * If the optional `span` flag is true (default: false), all text
+ * content will be wrapped in elements (this is to ensure DOM
+ * compatibility with hdom).
+ *
+ * If the optional `keys` flag is true (default: false), all elements
+ * will have an autogenerated `key` attribute injected. If `span` is
+ * enabled, `keys` will be enabled by default too.
+ *
+ * @param tree hiccup elements / component tree
+ * @param ctx arbitrary user context object
* @param escape auto-escape entities
+ * @param span use spans for text content
+ * @param keys attach key attribs
*/
-export const serialize = (tree: any[], ctx?: any, escape = false) => _serialize(tree, ctx, escape);
+export const serialize = (tree: any, ctx?: any, escape = false, span = false, keys = span, path = [0]) =>
+ _serialize(tree, ctx, escape, span, keys, path);
-const _serialize = (tree: any, ctx: any, esc: boolean) => {
+const _serialize = (tree: any, ctx: any, esc: boolean, span: boolean, keys: boolean, path: any[]) => {
if (tree == null) {
return "";
}
@@ -89,10 +102,10 @@ const _serialize = (tree: any, ctx: any, esc: boolean) => {
}
let tag = tree[0];
if (isFunction(tag)) {
- return _serialize(tag.apply(null, [ctx, ...tree.slice(1)]), ctx, esc);
+ return _serialize(tag.apply(null, [ctx, ...tree.slice(1)]), ctx, esc, span, keys, path);
}
if (implementsFunction(tag, "render")) {
- return _serialize(tag.render.apply(null, [ctx, ...tree.slice(1)]), ctx, esc);
+ return _serialize(tag.render.apply(null, [ctx, ...tree.slice(1)]), ctx, esc, span, keys, path);
}
if (isString(tag)) {
tree = normalize(tree);
@@ -100,6 +113,9 @@ const _serialize = (tree: any, ctx: any, esc: boolean) => {
let attribs = tree[1];
let body = tree[2];
let res = `<${tag}`;
+ if (keys && attribs.key === undefined) {
+ attribs.key = path.join("-");
+ }
for (let a in attribs) {
if (attribs.hasOwnProperty(a)) {
let v = attribs[a];
@@ -125,8 +141,9 @@ const _serialize = (tree: any, ctx: any, esc: boolean) => {
illegalArgs(`No body allowed in tag: ${tag}`);
}
res += ">";
+ span = span && !NO_SPANS[tag];
for (let i = 0, n = body.length; i < n; i++) {
- res += _serialize(body[i], ctx, esc);
+ res += _serialize(body[i], ctx, esc, span, keys, [...path, i]);
}
return res += `${tag}>`;
} else if (!VOID_TAGS[tag]) {
@@ -135,26 +152,31 @@ const _serialize = (tree: any, ctx: any, esc: boolean) => {
return res += "/>";
}
if (iter(tree)) {
- return _serializeIter(tree, ctx, esc);
+ return _serializeIter(tree, ctx, esc, span, keys, path);
}
illegalArgs(`invalid tree node: ${tree}`);
}
if (isFunction(tree)) {
- return _serialize(tree(ctx), ctx, esc);
+ return _serialize(tree(ctx), ctx, esc, span, keys, path);
}
if (implementsFunction(tree, "deref")) {
- return _serialize(tree.deref(), ctx, esc);
+ return _serialize(tree.deref(), ctx, esc, span, keys, path);
}
if (iter(tree)) {
- return _serializeIter(tree, ctx, esc);
+ return _serializeIter(tree, ctx, esc, span, keys, path);
}
- return esc ? escape(tree.toString()) : tree;
+ tree = esc ? escape(tree.toString()) : tree;
+ return span ?
+ `${tree}` :
+ tree;
};
-const _serializeIter = (iter: Iterable, ctx: any, esc: boolean) => {
+const _serializeIter = (iter: Iterable, ctx: any, esc: boolean, span: boolean, keys: boolean, path: any[]) => {
const res = [];
+ const p = path.slice(0, path.length - 1);
+ let k = 0;
for (let i of iter) {
- res.push(_serialize(i, ctx, esc));
+ res.push(_serialize(i, ctx, esc, span, keys, [...p, k++]));
}
return res.join("");
}
diff --git a/packages/iges/CHANGELOG.md b/packages/iges/CHANGELOG.md
index 03e4c5923f..73c3f930a0 100644
--- a/packages/iges/CHANGELOG.md
+++ b/packages/iges/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.2.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/iges@0.2.6...@thi.ng/iges@0.2.7) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/iges
+
## [0.2.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/iges@0.2.5...@thi.ng/iges@0.2.6) (2018-08-24)
diff --git a/packages/iges/README.md b/packages/iges/README.md
index 693513e4ee..81e4f5e694 100644
--- a/packages/iges/README.md
+++ b/packages/iges/README.md
@@ -11,7 +11,7 @@ Bare-bones IGES 5.3 serializer for (currently only) polygonal geometry,
both open & closed, for use in various CAD applications (e.g. Rhino,
Houdini, Fusion 360)
-![houdini](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/iges.png)
+![houdini](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/iges.png)
## Installation
@@ -19,6 +19,13 @@ Houdini, Fusion 360)
yarn add @thi.ng/iges
```
+## Dependencies
+
+- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api)
+- [@thi.ng/defmulti](https://github.com/thi-ng/umbrella/tree/master/packages/defmulti)
+- [@thi.ng/strings](https://github.com/thi-ng/umbrella/tree/master/packages/strings)
+- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers)
+
## Usage examples
```ts
diff --git a/packages/iges/package.json b/packages/iges/package.json
index 75069725b3..e8a3a43ce9 100644
--- a/packages/iges/package.json
+++ b/packages/iges/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/iges",
- "version": "0.2.6",
+ "version": "0.2.7",
"description": "IGES 5.3 serializer for (currently only) polygonal geometry, both open & closed",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -30,8 +30,8 @@
"dependencies": {
"@thi.ng/api": "^4.1.0",
"@thi.ng/defmulti": "^0.3.8",
- "@thi.ng/strings": "^0.3.0",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/strings": "^0.3.1",
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"CAD",
diff --git a/packages/interceptors/CHANGELOG.md b/packages/interceptors/CHANGELOG.md
index 634c7cb218..1fd6e192ea 100644
--- a/packages/interceptors/CHANGELOG.md
+++ b/packages/interceptors/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [1.8.11](https://github.com/thi-ng/umbrella/compare/@thi.ng/interceptors@1.8.10...@thi.ng/interceptors@1.8.11) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/interceptors
+
## [1.8.10](https://github.com/thi-ng/umbrella/compare/@thi.ng/interceptors@1.8.9...@thi.ng/interceptors@1.8.10) (2018-08-24)
diff --git a/packages/interceptors/package.json b/packages/interceptors/package.json
index f7494db1b6..5feb96f74d 100644
--- a/packages/interceptors/package.json
+++ b/packages/interceptors/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/interceptors",
- "version": "1.8.10",
+ "version": "1.8.11",
"description": "Interceptor based event bus, side effect & immutable state handling",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -29,7 +29,7 @@
},
"dependencies": {
"@thi.ng/api": "^4.1.0",
- "@thi.ng/atom": "^1.4.7",
+ "@thi.ng/atom": "^1.5.0",
"@thi.ng/checks": "^1.5.7",
"@thi.ng/errors": "^0.1.6",
"@thi.ng/paths": "^1.5.2"
diff --git a/packages/iterators/CHANGELOG.md b/packages/iterators/CHANGELOG.md
index fa3eb52510..6c5f13d6bb 100644
--- a/packages/iterators/CHANGELOG.md
+++ b/packages/iterators/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [4.1.23](https://github.com/thi-ng/umbrella/compare/@thi.ng/iterators@4.1.22...@thi.ng/iterators@4.1.23) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/iterators
+
## [4.1.22](https://github.com/thi-ng/umbrella/compare/@thi.ng/iterators@4.1.21...@thi.ng/iterators@4.1.22) (2018-08-24)
diff --git a/packages/iterators/package.json b/packages/iterators/package.json
index 3da316fd33..a8b1f0b317 100644
--- a/packages/iterators/package.json
+++ b/packages/iterators/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/iterators",
- "version": "4.1.22",
+ "version": "4.1.23",
"description": "clojure.core inspired, composable ES6 iterators & generators",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -29,7 +29,7 @@
},
"dependencies": {
"@thi.ng/api": "^4.1.0",
- "@thi.ng/dcons": "^1.1.1",
+ "@thi.ng/dcons": "^1.1.2",
"@thi.ng/errors": "^0.1.6"
},
"keywords": [
diff --git a/packages/memoize/CHANGELOG.md b/packages/memoize/CHANGELOG.md
index 82c0488b65..432ab995d3 100644
--- a/packages/memoize/CHANGELOG.md
+++ b/packages/memoize/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.1.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/memoize@0.1.1...@thi.ng/memoize@0.1.2) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/memoize
+
## [0.1.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/memoize@0.1.0...@thi.ng/memoize@0.1.1) (2018-08-24)
diff --git a/packages/memoize/README.md b/packages/memoize/README.md
index c989125cb9..4967214b63 100644
--- a/packages/memoize/README.md
+++ b/packages/memoize/README.md
@@ -37,6 +37,10 @@ based on different strategies. See doc strings for further details.
yarn add @thi.ng/memoize
```
+## Dependencies
+
+- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api)
+
## Usage examples
```ts
diff --git a/packages/memoize/package.json b/packages/memoize/package.json
index 5c6af0065d..a2bbbbd396 100644
--- a/packages/memoize/package.json
+++ b/packages/memoize/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/memoize",
- "version": "0.1.1",
+ "version": "0.1.2",
"description": "Function memoization with configurable caches",
"main": "./index.js",
"typings": "./index.d.ts",
diff --git a/packages/range-coder/CHANGELOG.md b/packages/range-coder/CHANGELOG.md
index 077df4fc79..9f65b6df1a 100644
--- a/packages/range-coder/CHANGELOG.md
+++ b/packages/range-coder/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.1.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/range-coder@0.1.6...@thi.ng/range-coder@0.1.7) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/range-coder
+
## [0.1.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/range-coder@0.1.5...@thi.ng/range-coder@0.1.6) (2018-08-24)
diff --git a/packages/range-coder/package.json b/packages/range-coder/package.json
index e274eb5bf7..0ea7873a01 100644
--- a/packages/range-coder/package.json
+++ b/packages/range-coder/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/range-coder",
- "version": "0.1.6",
+ "version": "0.1.7",
"description": "Binary data range encoder / decoder",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -20,7 +20,7 @@
"test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js"
},
"devDependencies": {
- "@thi.ng/transducers": "^2.0.1",
+ "@thi.ng/transducers": "^2.0.2",
"@types/mocha": "^5.2.5",
"@types/node": "^10.5.5",
"mocha": "^5.2.0",
diff --git a/packages/resolve-map/CHANGELOG.md b/packages/resolve-map/CHANGELOG.md
index c9961caf93..017c1809a0 100644
--- a/packages/resolve-map/CHANGELOG.md
+++ b/packages/resolve-map/CHANGELOG.md
@@ -3,7 +3,15 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
-
+
+## [3.0.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/resolve-map@3.0.8...@thi.ng/resolve-map@3.0.9) (2018-08-30)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/resolve-map
+
+
## [3.0.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/resolve-map@3.0.7...@thi.ng/resolve-map@3.0.8) (2018-08-24)
@@ -11,7 +19,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
**Note:** Version bump only for package @thi.ng/resolve-map
-
+
## [3.0.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/resolve-map@3.0.6...@thi.ng/resolve-map@3.0.7) (2018-08-01)
diff --git a/packages/resolve-map/README.md b/packages/resolve-map/README.md
index a2b03a4751..7e1da6f9f2 100644
--- a/packages/resolve-map/README.md
+++ b/packages/resolve-map/README.md
@@ -58,9 +58,11 @@ Any function values are called using two possible conventions:
2) If no de-structure form is found in the function's arguments, the
function is only called with `resolve` as argument.
-**Important:** Since ES6 var names can't contain special characters,
-destructured keys can ALWAYS only be looked up as siblings of the
-currently processed key.
+**Important:** ES6 destructuring can *only* be used for ES6 compile
+targets and *will fail when transpiling to ES5*. If you're not sure, use
+the 2nd (legacy) form. Also, since ES6 var names can't contain special
+characters, destructured keys can ALWAYS only be looked up as siblings
+of the currently processed key.
The `resolve` function provided as arg to the user function accepts a
path (**without `@` prefix**) to look up any other values in the root
@@ -135,22 +137,22 @@ import * as tx from "@thi.ng/transducers";
// will be injected later as well
const stats = {
// sequence average
- mean: ({src}) => tx.reduce(tx.mean(), src),
+ mean: ({ src }) => tx.mean(src),
// sequence range
- range: ({min,max}) => max - min,
+ range: ({ min, max }) => max - min,
// computes sequence min val
- min: ({src}) => tx.reduce(tx.min(), src),
+ min: ({ src }) => tx.min(src),
// computes sequence max val
- max: ({src}) => tx.reduce(tx.max(), src),
+ max: ({ src }) => tx.max(src),
// sorted copy
- sorted: ({src}) => [...src].sort((a, b) => a - b),
+ sorted: ({ src }) => [...src].sort((a, b) => a - b),
// standard deviation
- sd: ({src, mean})=>
+ sd: ({ src, mean })=>
Math.sqrt(
tx.transduce(tx.map((x) => Math.pow(x - mean, 2)), tx.add(), src) /
(src.length - 1)),
// compute 10th - 90th percentiles
- percentiles: ({sorted}) => {
+ percentiles: ({ sorted }) => {
return tx.transduce(
tx.map((x) => sorted[Math.floor(x / 100 * sorted.length)]),
tx.push(),
diff --git a/packages/resolve-map/package.json b/packages/resolve-map/package.json
index e9328786a9..74f27f99ba 100644
--- a/packages/resolve-map/package.json
+++ b/packages/resolve-map/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/resolve-map",
- "version": "3.0.8",
+ "version": "3.0.9",
"description": "DAG resolution of vanilla objects & arrays with internally linked values",
"main": "./index.js",
"typings": "./index.d.ts",
diff --git a/packages/resolve-map/test/index.ts b/packages/resolve-map/test/index.ts
index 94b02ab9a8..98ca8b5adb 100644
--- a/packages/resolve-map/test/index.ts
+++ b/packages/resolve-map/test/index.ts
@@ -73,13 +73,13 @@ describe("resolve-map", () => {
it("destructure", () => {
const stats = {
// sequence average
- mean: ({ src: a }) => tx.reduce(tx.mean(), a),
+ mean: ({ src: a }) => tx.mean(a),
// sequence range
range: ({ min, max }) => max - min,
// computes sequence min val
- min: ({ src }) => tx.reduce(tx.min(), src),
+ min: ({ src }) => tx.min(src),
// computes sequence max val
- max: ({ src }) => tx.reduce(tx.max(), src),
+ max: ({ src }) => tx.max(src),
// sorted copy
sorted: ({ src }) => [...src].sort((a, b) => a - b),
// standard deviation
diff --git a/packages/rle-pack/CHANGELOG.md b/packages/rle-pack/CHANGELOG.md
index 536f3e6998..85f13c422d 100644
--- a/packages/rle-pack/CHANGELOG.md
+++ b/packages/rle-pack/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [1.0.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/rle-pack@1.0.1...@thi.ng/rle-pack@1.0.2) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rle-pack
+
## [1.0.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/rle-pack@1.0.0...@thi.ng/rle-pack@1.0.1) (2018-08-24)
diff --git a/packages/rle-pack/README.md b/packages/rle-pack/README.md
index ff3e2f9d6e..71d8febc30 100644
--- a/packages/rle-pack/README.md
+++ b/packages/rle-pack/README.md
@@ -42,6 +42,7 @@ yarn add @thi.ng/rle-pack
## Dependencies
- [@thi.ng/bitstream](https://github.com/thi-ng/umbrella/tree/master/packages/bitstream)
+- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors)
## API
diff --git a/packages/rle-pack/package.json b/packages/rle-pack/package.json
index 873d0b513f..3863a544e7 100644
--- a/packages/rle-pack/package.json
+++ b/packages/rle-pack/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/rle-pack",
- "version": "1.0.1",
+ "version": "1.0.2",
"description": "Binary run-length encoding packer w/ flexible repeat bit widths",
"main": "./index.js",
"typings": "./index.d.ts",
diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md
index f86c98d1f4..cb47af8d72 100644
--- a/packages/router/CHANGELOG.md
+++ b/packages/router/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.1.22](https://github.com/thi-ng/umbrella/compare/@thi.ng/router@0.1.21...@thi.ng/router@0.1.22) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/router
+
## [0.1.21](https://github.com/thi-ng/umbrella/compare/@thi.ng/router@0.1.20...@thi.ng/router@0.1.21) (2018-08-24)
diff --git a/packages/router/README.md b/packages/router/README.md
index f3a5aab90f..386cfb359d 100644
--- a/packages/router/README.md
+++ b/packages/router/README.md
@@ -50,7 +50,8 @@ yarn start
A complete, full commented demo app is here:
-[Source](https://github.com/thi-ng/umbrella/blob/master/examples/router-basics/) | [Live demo](https://demo.thi.ng/umbrella/router-basics/)
+[Source](https://github.com/thi-ng/umbrella/blob/master/examples/router-basics/) |
+[Live demo](https://demo.thi.ng/umbrella/router-basics/)
```ts
import * as r from "@thi.ng/router";
@@ -142,7 +143,8 @@ router.addListener(r.EV_ROUTE_CHANGED, console.log);
router.start();
```
-See [further comments in source code](https://github.com/thi-ng/umbrella/blob/master/packages/router/src/api.ts)
+See [further comments in source
+code](https://github.com/thi-ng/umbrella/blob/master/packages/router/src/api.ts)
## Authors
diff --git a/packages/router/package.json b/packages/router/package.json
index 69145ff74f..b98018bc49 100644
--- a/packages/router/package.json
+++ b/packages/router/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/router",
- "version": "0.1.21",
+ "version": "0.1.22",
"description": "Generic router for browser & non-browser based applications",
"main": "./index.js",
"typings": "./index.d.ts",
diff --git a/packages/rstream-csp/CHANGELOG.md b/packages/rstream-csp/CHANGELOG.md
index 541a716723..1ade10e636 100644
--- a/packages/rstream-csp/CHANGELOG.md
+++ b/packages/rstream-csp/CHANGELOG.md
@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.1.101](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-csp@0.1.100...@thi.ng/rstream-csp@0.1.101) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-csp
+
+
+## [0.1.100](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-csp@0.1.99...@thi.ng/rstream-csp@0.1.100) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-csp
+
+
+## [0.1.99](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-csp@0.1.98...@thi.ng/rstream-csp@0.1.99) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-csp
+
## [0.1.98](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-csp@0.1.97...@thi.ng/rstream-csp@0.1.98) (2018-08-24)
diff --git a/packages/rstream-csp/package.json b/packages/rstream-csp/package.json
index fc4c509944..41bcd29af1 100644
--- a/packages/rstream-csp/package.json
+++ b/packages/rstream-csp/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/rstream-csp",
- "version": "0.1.98",
+ "version": "0.1.101",
"description": "@thi.ng/csp bridge module for @thi.ng/rstream",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -28,8 +28,8 @@
"typescript": "^3.0.1"
},
"dependencies": {
- "@thi.ng/csp": "^0.3.57",
- "@thi.ng/rstream": "^1.11.4"
+ "@thi.ng/csp": "^0.3.58",
+ "@thi.ng/rstream": "^1.11.7"
},
"keywords": [
"bridge",
diff --git a/packages/rstream-dot/CHANGELOG.md b/packages/rstream-dot/CHANGELOG.md
index efbb648b0b..fc39c52367 100644
--- a/packages/rstream-dot/CHANGELOG.md
+++ b/packages/rstream-dot/CHANGELOG.md
@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.2.40](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-dot@0.2.39...@thi.ng/rstream-dot@0.2.40) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-dot
+
+
+## [0.2.39](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-dot@0.2.38...@thi.ng/rstream-dot@0.2.39) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-dot
+
+
+## [0.2.38](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-dot@0.2.37...@thi.ng/rstream-dot@0.2.38) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-dot
+
## [0.2.37](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-dot@0.2.36...@thi.ng/rstream-dot@0.2.37) (2018-08-24)
diff --git a/packages/rstream-dot/package.json b/packages/rstream-dot/package.json
index 1a3a57f88b..6503f6fead 100644
--- a/packages/rstream-dot/package.json
+++ b/packages/rstream-dot/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/rstream-dot",
- "version": "0.2.37",
+ "version": "0.2.40",
"description": "Graphviz DOT conversion of @thi.ng/rstream dataflow graph topologies",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -28,7 +28,7 @@
"typescript": "^3.0.1"
},
"dependencies": {
- "@thi.ng/rstream": "^1.11.4"
+ "@thi.ng/rstream": "^1.11.7"
},
"keywords": [
"conversion",
diff --git a/packages/rstream-gestures/CHANGELOG.md b/packages/rstream-gestures/CHANGELOG.md
index d6c1f5cbf3..e9a07b7501 100644
--- a/packages/rstream-gestures/CHANGELOG.md
+++ b/packages/rstream-gestures/CHANGELOG.md
@@ -3,6 +3,33 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.5.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-gestures@0.5.1...@thi.ng/rstream-gestures@0.5.2) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-gestures
+
+
+## [0.5.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-gestures@0.5.0...@thi.ng/rstream-gestures@0.5.1) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-gestures
+
+
+# [0.5.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-gestures@0.4.18...@thi.ng/rstream-gestures@0.5.0) (2018-08-27)
+
+
+### Features
+
+* **rstream-gestures:** add options for local & scaled positions ([ccc40a9](https://github.com/thi-ng/umbrella/commit/ccc40a9))
+
+
+
+
## [0.4.18](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-gestures@0.4.17...@thi.ng/rstream-gestures@0.4.18) (2018-08-24)
diff --git a/packages/rstream-gestures/README.md b/packages/rstream-gestures/README.md
index 4c9e4214fa..9b8af9e627 100644
--- a/packages/rstream-gestures/README.md
+++ b/packages/rstream-gestures/README.md
@@ -22,6 +22,10 @@ The `zoom` value is always present, but is only updated with wheel
events. The value will be constrained to `minZoom` ... `maxZoom`
interval (provided via options object).
+Also see the
+[`GestureStreamOpts`](https://github.com/thi-ng/umbrella/tree/master/packages/rstream-gestures/src/index.ts#L26)
+config options for further details.
+
## Installation
```bash
@@ -36,7 +40,12 @@ yarn add @thi.ng/rstream-gestures
## Usage examples
-A small, fully commented project can be found in the `/examples` folder:
+Several small, fully commented projects can be found in the `/examples` folder:
+
+![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)
[Source](https://github.com/thi-ng/umbrella/tree/master/examples/rstream-dataflow) |
[Live version](https://demo.thi.ng/umbrella/rstream-dataflow)
diff --git a/packages/rstream-gestures/package.json b/packages/rstream-gestures/package.json
index 06e8283f1a..4341cd22a4 100644
--- a/packages/rstream-gestures/package.json
+++ b/packages/rstream-gestures/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/rstream-gestures",
- "version": "0.4.18",
+ "version": "0.5.2",
"description": "Unified mouse, mouse wheel & single-touch event stream abstraction",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -29,8 +29,8 @@
},
"dependencies": {
"@thi.ng/api": "^4.1.0",
- "@thi.ng/rstream": "^1.11.4",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/rstream": "^1.11.7",
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"dataflow",
diff --git a/packages/rstream-gestures/src/index.ts b/packages/rstream-gestures/src/index.ts
index 606be865e8..c7c2be9195 100644
--- a/packages/rstream-gestures/src/index.ts
+++ b/packages/rstream-gestures/src/index.ts
@@ -50,6 +50,17 @@ export interface GestureStreamOpts extends IID {
* Scaling factor for zoom changes. Default: 1
*/
smooth: number;
+ /**
+ * Local coordinate flag. If true (default), the elements position
+ * offset is subtracted.
+ */
+ local: boolean;
+ /**
+ * If true (default: false), all positions and delta values are
+ * scaled by `window.devicePixelRatio`. Note: Only enable if `local`
+ * is true.
+ */
+ scale: boolean;
}
/**
@@ -80,7 +91,7 @@ export interface GestureStreamOpts extends IID {
* @param el
* @param opts
*/
-export function gestureStream(el: Element, opts?: Partial): StreamMerge {
+export function gestureStream(el: HTMLElement, opts?: Partial): StreamMerge {
let isDown = false,
clickPos: number[];
opts = Object.assign({
@@ -91,8 +102,11 @@ export function gestureStream(el: Element, opts?: Partial): S
smooth: 1,
eventOpts: { capture: true },
preventDefault: true,
+ local: true,
+ scale: false,
}, opts);
let zoom = Math.min(Math.max(opts.zoom, opts.minZoom), opts.maxZoom);
+ const dpr = window.devicePixelRatio || 1;
return merge({
id: opts.id,
src: [
@@ -120,12 +134,18 @@ export function gestureStream(el: Element, opts?: Partial): S
}[e.type];
evt = e;
}
- const pos = [evt.clientX | 0, evt.clientY | 0];
+ const pos = opts.local ?
+ [(evt.clientX - el.offsetLeft) | 0, (evt.clientY - el.offsetTop) | 0] :
+ [evt.clientX | 0, evt.clientY | 0];
+ if (opts.scale) {
+ pos[0] *= dpr;
+ pos[1] *= dpr;
+ }
const body = { pos, zoom };
switch (type) {
case GestureType.START:
isDown = true;
- clickPos = pos;
+ clickPos = [...pos];
break;
case GestureType.END:
isDown = false;
diff --git a/packages/rstream-graph/CHANGELOG.md b/packages/rstream-graph/CHANGELOG.md
index 68bc412dad..d25181ef6e 100644
--- a/packages/rstream-graph/CHANGELOG.md
+++ b/packages/rstream-graph/CHANGELOG.md
@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [2.1.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-graph@2.1.25...@thi.ng/rstream-graph@2.1.26) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-graph
+
+
+## [2.1.25](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-graph@2.1.24...@thi.ng/rstream-graph@2.1.25) (2018-08-30)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-graph
+
+
+## [2.1.24](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-graph@2.1.23...@thi.ng/rstream-graph@2.1.24) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-graph
+
+
+## [2.1.23](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-graph@2.1.22...@thi.ng/rstream-graph@2.1.23) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-graph
+
## [2.1.22](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-graph@2.1.21...@thi.ng/rstream-graph@2.1.22) (2018-08-24)
diff --git a/packages/rstream-graph/package.json b/packages/rstream-graph/package.json
index 7b0185b116..384cc421af 100644
--- a/packages/rstream-graph/package.json
+++ b/packages/rstream-graph/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/rstream-graph",
- "version": "2.1.22",
+ "version": "2.1.26",
"description": "Declarative dataflow graph construction for @thi.ng/rstream",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -32,9 +32,9 @@
"@thi.ng/checks": "^1.5.7",
"@thi.ng/errors": "^0.1.6",
"@thi.ng/paths": "^1.5.2",
- "@thi.ng/resolve-map": "^3.0.8",
- "@thi.ng/rstream": "^1.11.4",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/resolve-map": "^3.0.9",
+ "@thi.ng/rstream": "^1.11.7",
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"compute",
diff --git a/packages/rstream-log/CHANGELOG.md b/packages/rstream-log/CHANGELOG.md
index f58fd3b18c..0ecc92b62c 100644
--- a/packages/rstream-log/CHANGELOG.md
+++ b/packages/rstream-log/CHANGELOG.md
@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [1.0.52](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log@1.0.51...@thi.ng/rstream-log@1.0.52) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-log
+
+
+## [1.0.51](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log@1.0.50...@thi.ng/rstream-log@1.0.51) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-log
+
+
+## [1.0.50](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log@1.0.49...@thi.ng/rstream-log@1.0.50) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-log
+
## [1.0.49](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log@1.0.48...@thi.ng/rstream-log@1.0.49) (2018-08-24)
diff --git a/packages/rstream-log/package.json b/packages/rstream-log/package.json
index 08e5afef24..e67b35abbb 100644
--- a/packages/rstream-log/package.json
+++ b/packages/rstream-log/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/rstream-log",
- "version": "1.0.49",
+ "version": "1.0.52",
"description": "Structured, multilevel & hierarchical loggers based on @thi.ng/rstream",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -31,8 +31,8 @@
"@thi.ng/api": "^4.1.0",
"@thi.ng/checks": "^1.5.7",
"@thi.ng/errors": "^0.1.6",
- "@thi.ng/rstream": "^1.11.4",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/rstream": "^1.11.7",
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"ES6",
diff --git a/packages/rstream-query/CHANGELOG.md b/packages/rstream-query/CHANGELOG.md
index 3b7f15928c..a365a0c4ea 100644
--- a/packages/rstream-query/CHANGELOG.md
+++ b/packages/rstream-query/CHANGELOG.md
@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.3.39](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-query@0.3.38...@thi.ng/rstream-query@0.3.39) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-query
+
+
+## [0.3.38](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-query@0.3.37...@thi.ng/rstream-query@0.3.38) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-query
+
+
+## [0.3.37](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-query@0.3.36...@thi.ng/rstream-query@0.3.37) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-query
+
## [0.3.36](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-query@0.3.35...@thi.ng/rstream-query@0.3.36) (2018-08-24)
diff --git a/packages/rstream-query/package.json b/packages/rstream-query/package.json
index 1fed827ca6..0d58dcee4a 100644
--- a/packages/rstream-query/package.json
+++ b/packages/rstream-query/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/rstream-query",
- "version": "0.3.36",
+ "version": "0.3.39",
"description": "@thi.ng/rstream based triple store & reactive query engine",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -29,13 +29,13 @@
},
"dependencies": {
"@thi.ng/api": "^4.1.0",
- "@thi.ng/associative": "^0.6.1",
+ "@thi.ng/associative": "^0.6.2",
"@thi.ng/checks": "^1.5.7",
"@thi.ng/equiv": "^0.1.7",
"@thi.ng/errors": "^0.1.6",
- "@thi.ng/rstream": "^1.11.4",
- "@thi.ng/rstream-dot": "^0.2.37",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/rstream": "^1.11.7",
+ "@thi.ng/rstream-dot": "^0.2.40",
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"dataflow",
diff --git a/packages/rstream/CHANGELOG.md b/packages/rstream/CHANGELOG.md
index 53e626be94..288e185ed5 100644
--- a/packages/rstream/CHANGELOG.md
+++ b/packages/rstream/CHANGELOG.md
@@ -3,6 +3,33 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [1.11.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream@1.11.6...@thi.ng/rstream@1.11.7) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream
+
+
+## [1.11.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream@1.11.5...@thi.ng/rstream@1.11.6) (2018-08-27)
+
+
+### Bug Fixes
+
+* **rstream:** Fix unbound this in method call expression ([34a97b4](https://github.com/thi-ng/umbrella/commit/34a97b4))
+
+
+
+
+
+## [1.11.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream@1.11.4...@thi.ng/rstream@1.11.5) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream
+
## [1.11.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream@1.11.3...@thi.ng/rstream@1.11.4) (2018-08-24)
diff --git a/packages/rstream/package.json b/packages/rstream/package.json
index 07214d4910..e115ba34b3 100644
--- a/packages/rstream/package.json
+++ b/packages/rstream/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/rstream",
- "version": "1.11.4",
+ "version": "1.11.7",
"description": "Reactive multi-tap streams, dataflow & transformation pipeline constructs",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -29,12 +29,12 @@
},
"dependencies": {
"@thi.ng/api": "^4.1.0",
- "@thi.ng/associative": "^0.6.1",
- "@thi.ng/atom": "^1.4.7",
+ "@thi.ng/associative": "^0.6.2",
+ "@thi.ng/atom": "^1.5.0",
"@thi.ng/checks": "^1.5.7",
"@thi.ng/errors": "^0.1.6",
"@thi.ng/paths": "^1.5.2",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"datastructure",
diff --git a/packages/rstream/src/stream-merge.ts b/packages/rstream/src/stream-merge.ts
index 3e5f7a24d8..feb2415c2a 100644
--- a/packages/rstream/src/stream-merge.ts
+++ b/packages/rstream/src/stream-merge.ts
@@ -47,6 +47,24 @@ export interface StreamMergeOpts extends IID {
* // 20
* // 30
* ```
+ *
+ * Use the `labeled()` transducer for each input to create a stream of
+ * labeled values and track their provenance:
+ *
+ * ```
+ * merge({
+ * src: [
+ * fromIterable([1,2,3]).transform(labeled("a")),
+ * fromIterable([10,20,30]).transform(labeled("b")),
+ * ]
+ * }).subscribe(trace());
+ * // ["a", 1]
+ * // ["b", 10]
+ * // ["a", 2]
+ * // ["b", 20]
+ * // ["a", 3]
+ * // ["b", 30]
+ * ```
*/
export function merge(opts?: Partial>) {
return new StreamMerge(opts);
diff --git a/packages/rstream/src/subs/resolve.ts b/packages/rstream/src/subs/resolve.ts
index ee1feac494..ee86cced37 100644
--- a/packages/rstream/src/subs/resolve.ts
+++ b/packages/rstream/src/subs/resolve.ts
@@ -57,7 +57,14 @@ export class Resolver extends Subscription, T> {
DEBUG && console.log(`resolved value in ${State[this.state]} state (${x})`);
}
},
- (e) => (this.fail || this.error)(e)
+ (e) => {
+ if (this.fail) {
+ this.fail(e);
+ }
+ else {
+ this.error(e);
+ }
+ }
);
}
diff --git a/packages/sax/CHANGELOG.md b/packages/sax/CHANGELOG.md
index b77a2251b6..d5e9a28f54 100644
--- a/packages/sax/CHANGELOG.md
+++ b/packages/sax/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.3.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/sax@0.3.15...@thi.ng/sax@0.3.16) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/sax
+
## [0.3.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/sax@0.3.14...@thi.ng/sax@0.3.15) (2018-08-24)
diff --git a/packages/sax/README.md b/packages/sax/README.md
index 91c3423991..5b35c8b726 100644
--- a/packages/sax/README.md
+++ b/packages/sax/README.md
@@ -32,6 +32,7 @@ yarn add @thi.ng/sax
## Dependencies
+- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api)
- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers)
- [@thi.ng/transducers-fsm](https://github.com/thi-ng/umbrella/tree/master/packages/transducers-fsm)
diff --git a/packages/sax/package.json b/packages/sax/package.json
index 52d927ee86..20736419b5 100644
--- a/packages/sax/package.json
+++ b/packages/sax/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/sax",
- "version": "0.3.15",
+ "version": "0.3.16",
"description": "Transducer-based, SAX-like, non-validating, speedy & tiny XML parser",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -29,8 +29,8 @@
},
"dependencies": {
"@thi.ng/api": "^4.1.0",
- "@thi.ng/transducers": "^2.0.1",
- "@thi.ng/transducers-fsm": "^0.2.14"
+ "@thi.ng/transducers": "^2.0.2",
+ "@thi.ng/transducers-fsm": "^0.2.15"
},
"keywords": [
"ES6",
diff --git a/packages/strings/CHANGELOG.md b/packages/strings/CHANGELOG.md
index 898574ca0c..ff8ce77449 100644
--- a/packages/strings/CHANGELOG.md
+++ b/packages/strings/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.3.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/strings@0.3.0...@thi.ng/strings@0.3.1) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/strings
+
# [0.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/strings@0.2.0...@thi.ng/strings@0.3.0) (2018-08-24)
diff --git a/packages/strings/README.md b/packages/strings/README.md
index 689e9735cc..ebd814a649 100644
--- a/packages/strings/README.md
+++ b/packages/strings/README.md
@@ -9,6 +9,7 @@ This project is part of the
- [About](#about)
- [Installation](#installation)
+- [Dependencies](#dependencies)
- [Usage examples](#usage-examples)
- [Authors](#authors)
- [License](#license)
@@ -26,6 +27,10 @@ functions, some memoized. WIP / Alpha.
yarn add @thi.ng/strings
```
+## Dependencies
+
+- [@thi.ng/memoize](https://github.com/thi-ng/umbrella/tree/master/packages/memoize)
+
## Usage examples
```ts
diff --git a/packages/strings/package.json b/packages/strings/package.json
index 8b051efd01..93b848ff0d 100644
--- a/packages/strings/package.json
+++ b/packages/strings/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/strings",
- "version": "0.3.0",
+ "version": "0.3.1",
"description": "Various string formatting & utility functions",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -28,7 +28,7 @@
"typescript": "^3.0.1"
},
"dependencies": {
- "@thi.ng/memoize": "^0.1.1"
+ "@thi.ng/memoize": "^0.1.2"
},
"keywords": [
"ES6",
diff --git a/packages/transducers-fsm/CHANGELOG.md b/packages/transducers-fsm/CHANGELOG.md
index 7e2fcde8ef..ac0a5adae6 100644
--- a/packages/transducers-fsm/CHANGELOG.md
+++ b/packages/transducers-fsm/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.2.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-fsm@0.2.14...@thi.ng/transducers-fsm@0.2.15) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/transducers-fsm
+
## [0.2.14](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-fsm@0.2.13...@thi.ng/transducers-fsm@0.2.14) (2018-08-24)
diff --git a/packages/transducers-fsm/README.md b/packages/transducers-fsm/README.md
index adc1ae8c94..070be1b205 100644
--- a/packages/transducers-fsm/README.md
+++ b/packages/transducers-fsm/README.md
@@ -21,6 +21,7 @@ yarn add @thi.ng/transducers-fsm
## Dependencies
+- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api)
- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers)
## Usage examples
diff --git a/packages/transducers-fsm/package.json b/packages/transducers-fsm/package.json
index d676a73f32..e7d15606c6 100644
--- a/packages/transducers-fsm/package.json
+++ b/packages/transducers-fsm/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/transducers-fsm",
- "version": "0.2.14",
+ "version": "0.2.15",
"description": "Transducer-based Finite State Machine transformer",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -29,7 +29,7 @@
},
"dependencies": {
"@thi.ng/api": "^4.1.0",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"ES6",
diff --git a/packages/transducers-hdom/CHANGELOG.md b/packages/transducers-hdom/CHANGELOG.md
index 07ff96fd9b..aa418b9fd8 100644
--- a/packages/transducers-hdom/CHANGELOG.md
+++ b/packages/transducers-hdom/CHANGELOG.md
@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [1.0.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-hdom@1.0.0...@thi.ng/transducers-hdom@1.0.1) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/transducers-hdom
+
+
+# [1.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-hdom@0.1.5...@thi.ng/transducers-hdom@1.0.0) (2018-08-31)
+
+
+### Features
+
+* **transducers-hdom:** add DOM hydration support, rename ([#39](https://github.com/thi-ng/umbrella/issues/39)) ([0f39694](https://github.com/thi-ng/umbrella/commit/0f39694))
+
+
+### BREAKING CHANGES
+
+* **transducers-hdom:** rename transducer: `updateUI` => `updateDOM`, new API
+
+
+
+
+
+## [0.1.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-hdom@0.1.4...@thi.ng/transducers-hdom@0.1.5) (2018-08-27)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/transducers-hdom
+
## [0.1.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-hdom@0.1.3...@thi.ng/transducers-hdom@0.1.4) (2018-08-24)
diff --git a/packages/transducers-hdom/README.md b/packages/transducers-hdom/README.md
index b555ccc4c5..d3464cd8cc 100644
--- a/packages/transducers-hdom/README.md
+++ b/packages/transducers-hdom/README.md
@@ -17,7 +17,7 @@ This project is part of the
## About
-This package provides a single `updateUI` function, a side-effecting &
+This package provides a single `updateDOM` function, a side-effecting &
stateful transducer which receives
[@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/master/packages/hdom)
component trees, diffs each against the previous value and applies any
@@ -25,14 +25,23 @@ required changes to the browser DOM, starting at given root element. By
default, incoming values are first normalized using @thi.ng/hdom's
`normalizeTree()` function.
+If the `hydrate` option is given, the first received tree is only used
+to inject event listeners and initialize components with lifecycle
+`init()` methods and expects an otherwise identical pre-existing DOM.
+All succeeding trees are diffed then as usual.
+
This transducer is primarily intended for
[@thi.ng/rstream](https://github.com/thi-ng/umbrella/tree/master/packages/rstream)-based
-dataflow graphs, where this transducer can be used as final leaf
-subscription / transformer to reflect UI changes back to the user,
-without using the standard RAF update loop used by @thi.ng/hdom by
-default. In this setup, UI updates will only be performed if the stream
-this transducer is attached to receives new values (i.e. hdom component
-trees).
+dataflow graphs, where it can be used as final leaf subscription /
+stream transformer to reflect UI changes back to the user, without using
+the usual RAF update loop used by @thi.ng/hdom by default. In this
+setup, DOM updates will only be performed if the stream this transducer
+is attached to receives new values (i.e. hdom component trees).
+
+Please also see the following hdom references for further details:
+
+- [start()](https://github.com/thi-ng/umbrella/tree/master/packages/hdom/src/start.ts)
+- [HDOMOpts](https://github.com/thi-ng/umbrella/tree/master/packages/hdom/src/api.ts#L19)
## Installation
@@ -40,6 +49,12 @@ trees).
yarn add @thi.ng/transducers-hdom
```
+## Dependencies
+
+- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/master/packages/checks)
+- [@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/master/packages/hdom)
+- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers)
+
## Usage examples
The below example is also available in the
@@ -51,7 +66,7 @@ directory.
```ts
import * as rs from "@thi.ng/rstream";
import * as tx from "@thi.ng/transducers";
-import { updateUI } from "@thi.ng/transducers-hdom";
+import { updateDOM } from "@thi.ng/transducers-hdom";
// root component function
const app = ({ ticks, clicks }) =>
@@ -76,7 +91,7 @@ rs.sync({
// transform into hdom component
tx.map(app),
// apply as DOM
- updateUI(document.body)
+ updateDOM({ root: document.body })
);
// kick off
diff --git a/packages/transducers-hdom/package.json b/packages/transducers-hdom/package.json
index 764ee11430..0b948dd59f 100644
--- a/packages/transducers-hdom/package.json
+++ b/packages/transducers-hdom/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/transducers-hdom",
- "version": "0.1.4",
+ "version": "1.0.1",
"description": "Transducer based UI updater for @thi.ng/hdom",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -29,8 +29,8 @@
},
"dependencies": {
"@thi.ng/checks": "^1.5.7",
- "@thi.ng/hdom": "^3.0.34",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/hdom": "^4.0.1",
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"diff",
diff --git a/packages/transducers-hdom/src/index.ts b/packages/transducers-hdom/src/index.ts
index f2d49efb19..0d7aa6c5a3 100644
--- a/packages/transducers-hdom/src/index.ts
+++ b/packages/transducers-hdom/src/index.ts
@@ -1,5 +1,7 @@
import { isString } from "@thi.ng/checks/is-string";
+import { HDOMOpts } from "@thi.ng/hdom/api";
import { diffElement } from "@thi.ng/hdom/diff";
+import { hydrateDOM } from "@thi.ng/hdom/dom";
import { normalizeTree } from "@thi.ng/hdom/normalize";
import { Transducer } from "@thi.ng/transducers/api";
import { reducer } from "@thi.ng/transducers/reduce";
@@ -14,27 +16,44 @@ import { scan } from "@thi.ng/transducers/xform/scan";
* `normalizeTree()` function and the given (optional) `ctx` object is
* provided to all embedded component functions in the tree.
*
+ * If the `hydrate` option is given, the first received tree is only
+ * used to inject event listeners and initialize components with
+ * lifecycle `init()` methods and expects an otherwise identical,
+ * pre-existing DOM. All succeeding trees are diffed then as usual.
+ *
* This transducer is primarily intended for @thi.ng/rstream dataflow
- * graph based applications, where this transducer can be used as final
- * leaf subscription to reactively reflect UI changes back to the user,
- * without using the standard RAF update loop used by hdom by default.
- * In this setup, UI updates will only be performed when the stream this
+ * graph based applications, where it can be used as final leaf
+ * subscription to reactively reflect UI changes back to the user,
+ * without using the usual RAF update loop used by hdom by default. In
+ * this setup, DOM updates will only be performed when the stream this
* transducer is attached to emits new values (i.e. hdom component
* trees).
*
- * @param root root element (or ID)
- * @param ctx hdom user context
- * @param normalize
+ * Please see here for further details:
+ * https://github.com/thi-ng/umbrella/blob/master/packages/hdom/src/start.ts
+ *
+ * @param opts hdom options
*/
-export const updateUI = (root: string | Element, ctx?: any, normalize = true): Transducer => {
- root = isString(root) ? document.getElementById(root) : root;
+export const updateDOM = (opts?: Partial): Transducer => {
+ opts = { root: "app", span: true, normalize: true, ...opts };
+ const root = isString(opts.root) ?
+ document.getElementById(opts.root) :
+ opts.root;
return scan(
reducer(
() => [],
(prev, curr) => {
- normalize && (curr = normalizeTree(curr, ctx));
- diffElement(root, prev, curr);
- return curr;
+ opts.normalize && (curr = normalizeTree(curr, opts.ctx, [0], opts.span));
+ if (curr != null) {
+ if (opts.hydrate) {
+ hydrateDOM(root, curr);
+ opts.hydrate = false;
+ } else {
+ diffElement(root, prev, curr);
+ }
+ return curr;
+ }
+ return prev;
}
)
);
diff --git a/packages/transducers-stats/CHANGELOG.md b/packages/transducers-stats/CHANGELOG.md
index 1033c6651d..2762fae944 100644
--- a/packages/transducers-stats/CHANGELOG.md
+++ b/packages/transducers-stats/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.4.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-stats@0.4.1...@thi.ng/transducers-stats@0.4.2) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/transducers-stats
+
## [0.4.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-stats@0.4.0...@thi.ng/transducers-stats@0.4.1) (2018-08-24)
diff --git a/packages/transducers-stats/README.md b/packages/transducers-stats/README.md
index f2adeefb6a..041049b2d8 100644
--- a/packages/transducers-stats/README.md
+++ b/packages/transducers-stats/README.md
@@ -10,6 +10,7 @@ This project is part of the
- [About](#about)
- [Supported indicators](#supported-indicators)
- [Installation](#installation)
+- [Dependencies](#dependencies)
- [Usage examples](#usage-examples)
- [Authors](#authors)
- [License](#license)
@@ -53,13 +54,19 @@ transforming ES6 iterator (generator) instead of a transducer.
yarn add @thi.ng/transducers-stats
```
+## Dependencies
+
+- [@thi.ng/dcons](https://github.com/thi-ng/umbrella/tree/master/packages/dcons)
+- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors)
+- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers)
+
## Usage examples
For some realworld use, please see the [crypto
chart](https://github.com/thi-ng/umbrella/tree/master/examples/crypto-chart)
example.
-![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/crypto-chart.png)
+![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/crypto-chart.png)
```ts
import * as tx from "@thi.ng/transducers";
diff --git a/packages/transducers-stats/package.json b/packages/transducers-stats/package.json
index e3a5cb865a..f69a93f93f 100644
--- a/packages/transducers-stats/package.json
+++ b/packages/transducers-stats/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/transducers-stats",
- "version": "0.4.1",
+ "version": "0.4.2",
"description": "Transducers for statistical / technical analysis",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -28,9 +28,9 @@
"typescript": "^3.0.1"
},
"dependencies": {
- "@thi.ng/dcons": "^1.1.1",
+ "@thi.ng/dcons": "^1.1.2",
"@thi.ng/errors": "^0.1.6",
- "@thi.ng/transducers": "^2.0.1"
+ "@thi.ng/transducers": "^2.0.2"
},
"keywords": [
"ES6",
diff --git a/packages/transducers/CHANGELOG.md b/packages/transducers/CHANGELOG.md
index 7dc8879d0c..32890f7d31 100644
--- a/packages/transducers/CHANGELOG.md
+++ b/packages/transducers/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [2.0.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers@2.0.1...@thi.ng/transducers@2.0.2) (2018-09-01)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/transducers
+
## [2.0.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers@2.0.0...@thi.ng/transducers@2.0.1) (2018-08-24)
diff --git a/packages/transducers/README.md b/packages/transducers/README.md
index cd070a5012..b21a389566 100644
--- a/packages/transducers/README.md
+++ b/packages/transducers/README.md
@@ -88,6 +88,8 @@ yarn add @thi.ng/transducers
- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api)
- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/master/packages/checks)
- [@thi.ng/compare](https://github.com/thi-ng/umbrella/tree/master/packages/compare)
+- [@thi.ng/compose](https://github.com/thi-ng/umbrella/tree/master/packages/compose)
+- [@thi.ng/equiv](https://github.com/thi-ng/umbrella/tree/master/packages/equiv)
- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors)
- [@thi.ng/strings](https://github.com/thi-ng/umbrella/tree/master/packages/strings)
diff --git a/packages/transducers/package.json b/packages/transducers/package.json
index f517d30984..6d23bd371c 100644
--- a/packages/transducers/package.json
+++ b/packages/transducers/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/transducers",
- "version": "2.0.1",
+ "version": "2.0.2",
"description": "Lightweight transducer implementations for ES6 / TypeScript",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -31,10 +31,10 @@
"@thi.ng/api": "^4.1.0",
"@thi.ng/checks": "^1.5.7",
"@thi.ng/compare": "^0.1.6",
- "@thi.ng/compose": "^0.1.0",
+ "@thi.ng/compose": "^0.1.1",
"@thi.ng/equiv": "^0.1.7",
"@thi.ng/errors": "^0.1.6",
- "@thi.ng/strings": "^0.3.0"
+ "@thi.ng/strings": "^0.3.1"
},
"keywords": [
"ES6",
diff --git a/packages/vectors/CHANGELOG.md b/packages/vectors/CHANGELOG.md
index db644ea934..3106ffe1f7 100644
--- a/packages/vectors/CHANGELOG.md
+++ b/packages/vectors/CHANGELOG.md
@@ -3,6 +3,59 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.5.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/vectors@0.5.1...@thi.ng/vectors@0.5.2) (2018-09-01)
+
+
+### Bug Fixes
+
+* **vectors:** add missing deps ([d2b4faf](https://github.com/thi-ng/umbrella/commit/d2b4faf))
+
+
+
+
+
+## [0.5.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/vectors@0.5.0...@thi.ng/vectors@0.5.1) (2018-08-31)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/vectors
+
+
+# [0.5.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/vectors@0.4.0...@thi.ng/vectors@0.5.0) (2018-08-30)
+
+
+### Features
+
+* **vectors:** consolidate vector consts, add toJSON() impls ([bdb5d37](https://github.com/thi-ng/umbrella/commit/bdb5d37))
+* **vectors:** update types, update GVec, add maths fns, swap impls ([d5cec94](https://github.com/thi-ng/umbrella/commit/d5cec94))
+
+
+
+
+
+# [0.4.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/vectors@0.3.0...@thi.ng/vectors@0.4.0) (2018-08-28)
+
+
+### Features
+
+* **vectors:** add more vec2/3 ops ([cd834f8](https://github.com/thi-ng/umbrella/commit/cd834f8))
+
+
+
+
+
+# [0.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/vectors@0.2.1...@thi.ng/vectors@0.3.0) (2018-08-27)
+
+
+### Features
+
+* **vectors:** add mix1(), minor cleanups ([cfb2b74](https://github.com/thi-ng/umbrella/commit/cfb2b74))
+
+
+
+
## [0.2.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/vectors@0.2.0...@thi.ng/vectors@0.2.1) (2018-08-24)
diff --git a/packages/vectors/README.md b/packages/vectors/README.md
index 152d9d19d4..d67d60bae7 100644
--- a/packages/vectors/README.md
+++ b/packages/vectors/README.md
@@ -11,6 +11,7 @@ This project is part of the
- [Vectors](#vectors)
- [Matrices](#matrices)
- [Installation](#installation)
+- [Dependencies](#dependencies)
- [Usage examples](#usage-examples)
- [Basics](#basics)
- [Vector classes & interleaved vectors in large buffer](#vector-classes--interleaved-vectors-in-large-buffer)
@@ -46,7 +47,8 @@ All of the vector operations listed below are also available via class
wrappers of strided buffer views. These vector classes (`Vec2/3/4`) are
array-like themselves and provide array index and `.x`, `.y`, `.z`, `.w`
property accessors (including `.length`). The `GVec` class wrapper only
-provides `.length` read access. All classes are also iterable.
+provides `.length` read access and element access via `getAt()` and
+`setAt()`. All classes are iterable.
```ts
buf = [0, 1, 0, 2, 0, 3];
@@ -85,62 +87,67 @@ zero-copy vector operations on sections of larger buffers. The default
start index is 0, default stride 1. See examples below and
[tests](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/test/).
-| Operation | Generic | 2D | 3D | 4D |
-|---------------------------------|--------------|------------------|--------------------|------------------|
-| Get vector (dense copy) | `get` | `get2` | `get3` | `get4` |
-| Set vector components (vector) | `set` | `set2` | `set3` | `set4` |
-| Set vector components (uniform) | `setN` | `setN2` | `setN3` | `setN4` |
-| Set vector components (scalars) | | `setS2` | `setS3` | `setS4` |
-| Swizzle vector components | | `swizzle2` | `swizzle3` | `swizzle4` |
-| Equality (w/ epsilon) | `eqDelta` | `eqDelta2` | `eqDelta3` | `eqDelta4` |
-| Vector addition | `add` | `add2` | `add3` | `add4` |
-| Vector subtraction | `sub` | `sub2` | `sub3` | `sub4` |
-| Vector multiplication | `mul` | `mul2` | `mul3` | `mul4` |
-| Vector division | `div` | `div2` | `div3` | `div4` |
-| Uniform scalar addition | `addN` | `addN2` | `addN3` | `addN4` |
-| Uniform scalar subtraction | `subN` | `subN2` | `subN3` | `subN4` |
-| Uniform scalar multiply | `mulN` | `mulN2` | `mulN3` | `mulN4` |
-| Uniform scalar multiply | `divN` | `divN2` | `divN3` | `divN4` |
-| Vector negation | `neg` | `neg2` | `neg3` | `neg4` |
-| Multiply-add vectors | `madd` | `madd2` | `madd3` | `madd4` |
-| Multiply-add scalar | `maddN` | `maddN2` | `maddN3` | `maddN4` |
-| Linear interpolation (vector) | `mix` | `mix2` | `mix3` | `mix4` |
-| Linear interpolation (uniform) | `mixN` | `mixN2` | `mixN3` | `mixN4` |
-| Dot product | `dot` | `dot2` | `dot3` | `dot4` |
-| Cross product | | `cross2` | `cross3` | |
-| Magnitude | `mag` | `mag2` | `mag3` | `mag4` |
-| Magnitude (squared) | `magSq` | `magSq2` | `magSq3` | `magSq4` |
-| Normalize (w/ opt length) | `normalize` | `normalize2` | `normalize3` | `normalize4` |
-| Limit to length | | `limit2` | `limit3` | `limit4` |
-| Distance | `dist` | `dist2` | `dist3` | `dist4` |
-| Distance (squared) | `distSq` | `distSq2` | `distSq3` | `distSq4` |
-| Manhattan distance | | `distManhattan2` | `distManhattan3` | `distManhattan4` |
-| Chebyshev distance | | `distChebyshev2` | `distChebyshev3` | `distChebyshev4` |
-| Reflection | | `reflect2` | `reflect3` | `reflect4` |
-| RotationX | | | `rotateX3` | |
-| RotationY | | | `rotateY3` | |
-| RotationZ | | `rotate2` | `rotateZ3` | |
-| Heading XY | | `heading2` | `headingXY3` | |
-| Heading XZ | | | `headingXZ3` | |
-| Heading YZ | | | `headingYZ3` | |
-| Cartesian -> Polar | | `toPolar2` | `toSpherical3` | |
-| Polar -> Cartesian | | `toCartesian2` | `toCartesian3` | |
-| Cartesian -> Cylindrical | | | `toCylindrical3` | |
-| Cylindrical -> Cartesian | | | `fromCylindrical3` | |
-| Minor axis | | `minorAxis2` | `minorAxis3` | `minorAxis4` |
-| Major axis | | `majorAxis2` | `majorAxis3` | `majorAxis4` |
-| Minimum | `min` | `min2` | `min3` | `min4` |
-| Maximum | `max` | `max2` | `max3` | `max4` |
-| Range clamping | `clamp` | `clamp2` | `clamp3` | `clamp4` |
-| Step (like GLSL) | `step` | `step2` | `step3` | `step4` |
-| SmoothStep (like GLSL) | `smoothStep` | `smoothStep2` | `smoothStep3` | `smoothStep4` |
-| Absolute value | `abs` | `abs2` | `abs3` | `abs4` |
-| Sign (w/ opt epsilon) | `sign` | `sign2` | `sign3` | `sign4` |
-| Round down | `floor` | `floor2` | `floor3` | `floor4` |
-| Round up | `ceil` | `ceil2` | `ceil3` | `ceil4` |
-| Square root | `sqrt` | `sqrt2` | `sqrt3` | `sqrt4` |
-| Power (vector) | `pow` | `pow2` | `pow3` | `pow4` |
-| Power (uniform) | `powN` | `powN2` | `powN3` | `powN4` |
+| Operation | Generic | 2D | 3D | 4D |
+|---------------------------------|--------------|----------------------|---------------------|------------------|
+| Get vector (dense copy) | `get` | `get2` | `get3` | `get4` |
+| Set vector components (vector) | `set` | `set2` | `set3` | `set4` |
+| Set vector components (uniform) | `setN` | `setN2` | `setN3` | `setN4` |
+| Set vector components (scalars) | | `setS2` | `setS3` | `setS4` |
+| Swizzle vector components | | `swizzle2` | `swizzle3` | `swizzle4` |
+| Swap vectors | | `swap2` | `swap3` | `swap4` |
+| Equality (w/ epsilon) | `eqDelta` | `eqDelta2` | `eqDelta3` | `eqDelta4` |
+| Vector addition | `add` | `add2` | `add3` | `add4` |
+| Vector subtraction | `sub` | `sub2` | `sub3` | `sub4` |
+| Vector multiplication | `mul` | `mul2` | `mul3` | `mul4` |
+| Vector division | `div` | `div2` | `div3` | `div4` |
+| Uniform scalar addition | `addN` | `addN2` | `addN3` | `addN4` |
+| Uniform scalar subtraction | `subN` | `subN2` | `subN3` | `subN4` |
+| Uniform scalar multiply | `mulN` | `mulN2` | `mulN3` | `mulN4` |
+| Uniform scalar multiply | `divN` | `divN2` | `divN3` | `divN4` |
+| Vector negation | `neg` | `neg2` | `neg3` | `neg4` |
+| Multiply-add vectors | `madd` | `madd2` | `madd3` | `madd4` |
+| Multiply-add scalar | `maddN` | `maddN2` | `maddN3` | `maddN4` |
+| Linear interpolation (vector) | `mix` | `mix2` | `mix3` | `mix4` |
+| Linear interpolation (uniform) | `mixN` | `mixN2` | `mixN3` | `mixN4` |
+| Dot product | `dot` | `dot2` | `dot3` | `dot4` |
+| Cross product | | `cross2` | `cross3` | |
+| Magnitude | `mag` | `mag2` | `mag3` | `mag4` |
+| Magnitude (squared) | `magSq` | `magSq2` | `magSq3` | `magSq4` |
+| Normalize (w/ opt length) | `normalize` | `normalize2` | `normalize3` | `normalize4` |
+| Limit to length | | `limit2` | `limit3` | `limit4` |
+| Distance | `dist` | `dist2` | `dist3` | `dist4` |
+| Distance (squared) | `distSq` | `distSq2` | `distSq3` | `distSq4` |
+| Manhattan distance | | `distManhattan2` | `distManhattan3` | `distManhattan4` |
+| Chebyshev distance | | `distChebyshev2` | `distChebyshev3` | `distChebyshev4` |
+| Reflection | | `reflect2` | `reflect3` | `reflect4` |
+| RotationX | | | `rotateX3` | |
+| RotationY | | | `rotateY3` | |
+| RotationZ | | `rotate2` | `rotateZ3` | |
+| Rotation around point | | `rotateAroundPoint2` | | |
+| Rotation around axis | | | `rotateAroundAxis3` | |
+| Heading XY | | `heading2` | `headingXY3` | |
+| Heading XZ | | | `headingXZ3` | |
+| Heading YZ | | | `headingYZ3` | |
+| Angle between vectors | | `angleBetween2` | `angleBetween3` | |
+| Bisector angle | | `bisect2` | | |
+| Cartesian -> Polar | | `toPolar2` | `toSpherical3` | |
+| Polar -> Cartesian | | `toCartesian2` | `toCartesian3` | |
+| Cartesian -> Cylindrical | | | `toCylindrical3` | |
+| Cylindrical -> Cartesian | | | `fromCylindrical3` | |
+| Minor axis | | `minorAxis2` | `minorAxis3` | `minorAxis4` |
+| Major axis | | `majorAxis2` | `majorAxis3` | `majorAxis4` |
+| Minimum | `min` | `min2` | `min3` | `min4` |
+| Maximum | `max` | `max2` | `max3` | `max4` |
+| Range clamping | `clamp` | `clamp2` | `clamp3` | `clamp4` |
+| Step (like GLSL) | `step` | `step2` | `step3` | `step4` |
+| SmoothStep (like GLSL) | `smoothStep` | `smoothStep2` | `smoothStep3` | `smoothStep4` |
+| Absolute value | `abs` | `abs2` | `abs3` | `abs4` |
+| Sign (w/ opt epsilon) | `sign` | `sign2` | `sign3` | `sign4` |
+| Round down | `floor` | `floor2` | `floor3` | `floor4` |
+| Round up | `ceil` | `ceil2` | `ceil3` | `ceil4` |
+| Square root | `sqrt` | `sqrt2` | `sqrt3` | `sqrt4` |
+| Power (vector) | `pow` | `pow2` | `pow3` | `pow4` |
+| Power (uniform) | `powN` | `powN2` | `powN3` | `powN4` |
### Matrices
@@ -188,6 +195,12 @@ non-suffixed naming.**
yarn add @thi.ng/vectors
```
+## Dependencies
+
+- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api)
+- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/master/packages/checks)
+- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors)
+
## Usage examples
### Basics
diff --git a/packages/vectors/package.json b/packages/vectors/package.json
index 6320e44fb6..1e75d5e307 100644
--- a/packages/vectors/package.json
+++ b/packages/vectors/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/vectors",
- "version": "0.2.1",
+ "version": "0.5.2",
"description": "Vector algebra for fixed & variable sizes, memory mapped, flexible layouts",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -29,7 +29,8 @@
},
"dependencies": {
"@thi.ng/api": "^4.1.0",
- "@thi.ng/checks": "^1.5.7"
+ "@thi.ng/checks": "^1.5.7",
+ "@thi.ng/errors": "^0.1.6"
},
"keywords": [
"ES6",
diff --git a/packages/vectors/src/api.ts b/packages/vectors/src/api.ts
index 81efc2408a..9b0f209618 100644
--- a/packages/vectors/src/api.ts
+++ b/packages/vectors/src/api.ts
@@ -1,15 +1,43 @@
import { NumericArray } from "@thi.ng/api/api";
export type Vec = NumericArray;
-export type ReadonlyVec = ArrayLike;
+export type ReadonlyVec = ArrayLike & Iterable;
export type Mat = NumericArray;
-export type ReadonlyMat = ArrayLike;
+export type ReadonlyMat = ArrayLike & Iterable;
-export type VecOp = (a: Vec, b: ReadonlyVec, ia: number, ib: number, sa: number, sb: number) => Vec;
+/**
+ * A vector operation involving only a single vector. The vector might
+ * be modified.
+ */
+export type VecOp1 = (v: Vec, i: number, s?: number) => T;
+
+/**
+ * A vector operation involving two vectors. The first vector might be
+ * modified.
+ */
+export type VecOp2 = (a: Vec, b: ReadonlyVec, ia: number, ib: number, sa?: number, sb?: number) => T;
+
+/**
+ * A readonly vector operation involving only a single vector.
+ */
+export type ReadonlyVecOp1 = (v: ReadonlyVec, i: number, s?: number) => T;
+
+/**
+ * A readonly vector operation involving two vectors.
+ */
+export type ReadonlyVecOp2 = (a: ReadonlyVec, b: ReadonlyVec, ia: number, ib: number, sa?: number, sb?: number) => T;
export interface IVec {
buf: Vec;
+ length: number;
i: number;
s: number;
}
+
+const min = Number.NEGATIVE_INFINITY;
+const max = Number.POSITIVE_INFINITY;
+export const MIN4 = Object.freeze([min, min, min, min]);
+export const MAX4 = Object.freeze([max, max, max, max]);
+export const ONE4 = Object.freeze([1, 1, 1, 1]);
+export const ZERO4 = Object.freeze([0, 0, 0, 0]);
diff --git a/packages/vectors/src/common.ts b/packages/vectors/src/common.ts
index e393990774..c0cc5231a0 100644
--- a/packages/vectors/src/common.ts
+++ b/packages/vectors/src/common.ts
@@ -1,4 +1,4 @@
-import { ReadonlyVec, Vec, VecOp } from "./api";
+import { ReadonlyVec, Vec, VecOp2 } from "./api";
import { EPS, eqDelta1 } from "./math";
export const x = (v: ReadonlyVec, i = 0, _?: number) => v[i];
@@ -31,7 +31,7 @@ export const w = (v: ReadonlyVec, i = 0, s = 1) => v[i + 3 * s];
* @param csb component stride `b`
* @param esa element stride `a`
*/
-export const transformVectors1 = (fn: VecOp, a: Vec, b: ReadonlyVec, num: number, ia: number, ib: number, csa: number, csb: number, esa: number) => {
+export const transformVectors1 = (fn: VecOp2, a: Vec, b: ReadonlyVec, num: number, ia: number, ib: number, csa: number, csb: number, esa: number) => {
for (; num > 0; num-- , ia += esa) {
fn(a, b, ia, ib, csa, csb);
}
@@ -50,7 +50,7 @@ export const transformVectors1 = (fn: VecOp, a: Vec, b: ReadonlyVec, num: number
* @param esa
* @param esb
*/
-export const transformVectors2 = (fn: VecOp, a: Vec, b: ReadonlyVec, n: number, ia: number, ib: number, csa: number, csb: number, esa: number, esb: number) => {
+export const transformVectors2 = (fn: VecOp2, a: Vec, b: ReadonlyVec, n: number, ia: number, ib: number, csa: number, csb: number, esa: number, esb: number) => {
for (; n > 0; n-- , ia += esa, ib += esb) {
fn(a, b, ia, ib, csa, csb);
}
@@ -75,11 +75,19 @@ export const eqDelta = (a: ReadonlyVec, b: ReadonlyVec, n: number, eps = EPS, ia
return true;
};
-export const declareIndices = (proto: any, indices: number[]) =>
+export const declareIndices = (proto: any, indices: number[]) => {
+ const get = (i: number) => function () { return this.buf[this.i + i * this.s]; };
+ const set = (i: number) => function (n: number) { this.buf[this.i + i * this.s] = n; };
indices.forEach((i) => {
Object.defineProperty(proto, i, {
- get: function () { return this.buf[this.i + i * this.s]; },
- set: function (n: number) { this.buf[this.i + i * this.s] = n; },
+ get: get(i),
+ set: set(i),
+ enumerable: true,
+ });
+ Object.defineProperty(proto, "xyzw"[i], {
+ get: get(i),
+ set: set(i),
enumerable: true,
});
});
+};
diff --git a/packages/vectors/src/gvec.ts b/packages/vectors/src/gvec.ts
index aa68389d83..653287f499 100644
--- a/packages/vectors/src/gvec.ts
+++ b/packages/vectors/src/gvec.ts
@@ -1,4 +1,9 @@
-import { ICopy, IEqualsDelta, IEquiv, ILength } from "@thi.ng/api/api";
+import {
+ ICopy,
+ IEqualsDelta,
+ IEquiv,
+ ILength
+} from "@thi.ng/api/api";
import { isArrayLike } from "@thi.ng/checks/is-arraylike";
import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
@@ -7,6 +12,7 @@ import { eqDelta, equiv } from "./common";
import {
clamp1,
EPS,
+ fract1,
sign1,
smoothStep1,
step1
@@ -132,6 +138,9 @@ export const floor = (a: Vec, num = a.length, i = 0, s = 1) =>
export const ceil = (a: Vec, num = a.length, i = 0, s = 1) =>
opg1(Math.ceil, a, num, i, s);
+export const fract = (a: Vec, num = a.length, i = 0, s = 1) =>
+ opg1(fract1, a, num, i, s);
+
export const sin = (a: Vec, num = a.length, i = 0, s = 1) =>
opg1(Math.sin, a, num, i, s);
@@ -195,15 +204,25 @@ export class GVec implements
return this.n;
}
+ getAt(i: number, safe = true) {
+ safe && this.ensureIndex(i);
+ return this.buf[this.i + i * this.s];
+ }
+
+ setAt(i: number, x: number, safe = true) {
+ safe && this.ensureIndex(i);
+ this.buf[this.i + i * this.s] = x;
+ }
+
copy() {
- return new GVec(get(this.buf, this.n, this.i, this.s), this.n);
+ return new GVec(get(this.buf, this.n, this.i, this.s));
}
equiv(v: any) {
return v instanceof GVec && v.n === this.n ?
equiv(this.buf, v.buf, this.n, this.i, v.i, this.s, v.s) :
isArrayLike(v) && v.length === this.n ?
- equiv(this.buf, v, this.n, this.i, 0, this.s, 1) :
+ equiv(this.buf, v, this.n, this.i, 0, this.s, 1) :
false;
}
@@ -325,6 +344,11 @@ export class GVec implements
return this;
}
+ fract() {
+ fract(this.buf, this.n, this.i, this.s);
+ return this;
+ }
+
floor() {
floor(this.buf, this.n, this.i, this.s);
return this;
@@ -392,7 +416,15 @@ export class GVec implements
return `[${get(this.buf, this.n, this.i, this.s).join(", ")}]`;
}
+ toJSON() {
+ return get(this.buf, this.n, this.i, this.s);
+ }
+
protected ensureSize(v: Readonly) {
this.n !== v.n && illegalArgs(`vector size: ${v.n} (needed ${this.n})`);
}
+
+ protected ensureIndex(i: number) {
+ (i < 0 && i >= this.n) && illegalArgs(`index out of bounds: ${i}`);
+ }
}
diff --git a/packages/vectors/src/mat23.ts b/packages/vectors/src/mat23.ts
index b8ea298e45..d9078af2f0 100644
--- a/packages/vectors/src/mat23.ts
+++ b/packages/vectors/src/mat23.ts
@@ -1,6 +1,6 @@
import { ICopy, IEqualsDelta } from "@thi.ng/api/api";
import { isArrayLike } from "@thi.ng/checks/is-arraylike";
-import { Mat, ReadonlyMat, Vec } from "./api";
+import { Mat, ReadonlyMat, Vec, ReadonlyVec } from "./api";
import { eqDelta } from "./common";
import { EPS } from "./math";
import {
@@ -11,9 +11,9 @@ import {
} from "./vec2";
export const get23 = (a: Mat, i = 0) =>
- set23(new ((a.constructor))(6), a, 0, i);
+ a.slice(i, i + 6);
-export const set23 = (a: Mat, b: Mat, ia = 0, ib = 0) => (
+export const set23 = (a: Mat, b: ReadonlyMat, ia = 0, ib = 0) => (
a[ia] = b[ib],
a[ia + 1] = b[ib + 1],
a[ia + 2] = b[ib + 2],
@@ -38,15 +38,20 @@ export const set23 = (a: Mat, b: Mat, ia = 0, ib = 0) => (
* @param m21
* @param i
*/
-export const setS23 = (m: Mat, m00: number, m01: number, m10: number, m11: number, m20: number, m21: number, i = 0) => (
- m[i] = m00,
- m[i + 1] = m01,
- m[i + 2] = m10,
- m[i + 3] = m11,
- m[i + 4] = m20,
- m[i + 5] = m21,
- m
-);
+export const setS23 = (
+ m: Mat,
+ m00: number, m01: number,
+ m10: number, m11: number,
+ m20: number, m21: number,
+ i = 0) => (
+ m[i] = m00,
+ m[i + 1] = m01,
+ m[i + 2] = m10,
+ m[i + 3] = m11,
+ m[i + 4] = m20,
+ m[i + 5] = m21,
+ m
+ );
export const identity23 = (m?: Mat, i = 0) =>
setS23(m || [], 1, 0, 0, 1, 0, 0, i);
@@ -57,7 +62,7 @@ export const rotation23 = (m: Mat, theta: number, i = 0) => {
return setS23(m || [], c, s, -s, c, 0, 0, i);
};
-export const rotationAroundPoint23 = (m: Mat, p: Vec, theta: number, im = 0, iv = 0, sv = 1) =>
+export const rotationAroundPoint23 = (m: Mat, p: ReadonlyVec, theta: number, im = 0, iv = 0, sv = 1) =>
concat23(
translationV23(m || [], p, im, iv, sv), im,
rotation23([], theta),
@@ -73,14 +78,14 @@ export const scaleN23 = (m: Mat, n: number, i = 0) =>
export const scaleS23 = (m: Mat, sx: number, sy: number, i = 0) =>
setS23(m || [], sx, 0, 0, sy, 0, 0, i);
-export const scaleWithCenter23 = (m: Mat, p: Vec, sx: number, sy: number, im = 0, iv = 0, sv = 1) =>
+export const scaleWithCenter23 = (m: Mat, p: ReadonlyVec, sx: number, sy: number, im = 0, iv = 0, sv = 1) =>
concat23(
translationV23(m || [], p, im, iv, sv), im,
scaleS23([], sx, sy),
translationS23([], -p[iv], -p[iv + sv])
);
-export const translationV23 = (m: Mat, v: Vec, i = 0, iv = 0, sv = 1) =>
+export const translationV23 = (m: Mat, v: ReadonlyVec, i = 0, iv = 0, sv = 1) =>
translationS23(m, v[iv], v[iv + sv], i);
export const translationS23 = (m: Mat, x: number, y: number, i = 0) =>
@@ -118,7 +123,7 @@ export const concat23 = (a: Mat, ia: number, ...xs: (ReadonlyMat | [ReadonlyMat,
a
);
-export const mulV23 = (m: ReadonlyMat, v: Vec, im = 0, iv = 0, sv = 1) =>
+export const mulV23 = (v: Vec, m: ReadonlyMat, iv = 0, im = 0, sv = 1) =>
setS2(
v,
dot2(m, v, im, iv, 2, sv) + m[im + 4],
@@ -161,7 +166,7 @@ export class Mat23 implements
return new Mat23(rotation23([], theta));
}
- static rotationAroundPoint(p: Vec2, theta: number) {
+ static rotationAroundPoint(p: Readonly, theta: number) {
return new Mat23(rotationAroundPoint23([], p.buf, theta, 0, p.i, p.s));
}
@@ -176,11 +181,11 @@ export class Mat23 implements
);
}
- static scaleWithCenter(p: Vec2, sx: number, sy = sx) {
+ static scaleWithCenter(p: Readonly, sx: number, sy = sx) {
return new Mat23(scaleWithCenter23([], p.buf, sx, sy, p.i, p.s));
}
- static translation(v: Vec2): Mat23;
+ static translation(v: Readonly): Mat23;
static translation(x: number, y: number): Mat23;
static translation(x: any, y?: any) {
return new Mat23(
@@ -214,8 +219,8 @@ export class Mat23 implements
buf: Mat;
i: number;
- constructor(buf: Mat, i = 0) {
- this.buf = buf;
+ constructor(buf?: Mat, i = 0) {
+ this.buf = buf || (new Array(6).fill(0));
this.i = i;
}
@@ -248,7 +253,7 @@ export class Mat23 implements
}
mulV(v: Vec2) {
- mulV23(this.buf, v.buf, this.i, v.i, v.s);
+ mulV23(v.buf, this.buf, v.i, this.i, v.s);
return v;
}
@@ -266,4 +271,8 @@ export class Mat23 implements
const i = this.i;
return `${b[i]} ${b[i + 2]} ${b[i + 4]}\n${b[i + 1]} ${b[i + 3]} ${b[i + 5]}`;
}
+
+ toJSON() {
+ return get23(this.buf, this.i);
+ }
}
diff --git a/packages/vectors/src/mat33.ts b/packages/vectors/src/mat33.ts
index 75fe93863e..3cf65e3488 100644
--- a/packages/vectors/src/mat33.ts
+++ b/packages/vectors/src/mat33.ts
@@ -1,6 +1,6 @@
import { ICopy, IEqualsDelta } from "@thi.ng/api/api";
import { isArrayLike } from "@thi.ng/checks/is-arraylike";
-import { Mat, ReadonlyMat, Vec } from "./api";
+import { Mat, ReadonlyMat, Vec, ReadonlyVec } from "./api";
import { eqDelta } from "./common";
import { EPS } from "./math";
import {
@@ -12,9 +12,9 @@ import {
import { setS4 } from "./vec4";
export const get33 = (a: Mat, i = 0) =>
- set33(new ((a.constructor))(9), a, 0, i);
+ a.slice(i, i + 9);
-export const set33 = (a: Mat, b: Mat, ia = 0, ib = 0) => (
+export const set33 = (a: Mat, b: ReadonlyMat, ia = 0, ib = 0) => (
a[ia] = b[ib],
a[ia + 1] = b[ib + 1],
a[ia + 2] = b[ib + 2],
@@ -46,18 +46,23 @@ export const set33 = (a: Mat, b: Mat, ia = 0, ib = 0) => (
* @param m22
* @param i
*/
-export const setS33 = (m: Mat, m00: number, m01: number, m02: number, m10: number, m11: number, m12: number, m20: number, m21: number, m22: number, i = 0) => (
- m[i] = m00,
- m[i + 1] = m01,
- m[i + 2] = m02,
- m[i + 3] = m10,
- m[i + 4] = m11,
- m[i + 5] = m12,
- m[i + 6] = m20,
- m[i + 7] = m21,
- m[i + 8] = m22,
- m
-);
+export const setS33 = (
+ m: Mat,
+ m00: number, m01: number, m02: number,
+ m10: number, m11: number, m12: number,
+ m20: number, m21: number, m22: number,
+ i = 0) => (
+ m[i] = m00,
+ m[i + 1] = m01,
+ m[i + 2] = m02,
+ m[i + 3] = m10,
+ m[i + 4] = m11,
+ m[i + 5] = m12,
+ m[i + 6] = m20,
+ m[i + 7] = m21,
+ m[i + 8] = m22,
+ m
+ );
export const identity33 = (m?: Mat, i = 0) =>
setS33(m || [],
@@ -100,7 +105,7 @@ export const rotationZ33 = (m: Mat, theta: number, i = 0) => {
);
};
-export const scaleV33 = (m: Mat, v: Vec, i = 0, iv = 0, sv = 1) =>
+export const scaleV33 = (m: Mat, v: ReadonlyVec, i = 0, iv = 0, sv = 1) =>
scaleS33(m, v[iv], v[iv + sv], v[iv + 2 * sv], i);
export const scaleN33 = (m: Mat, n: number, i = 0) =>
@@ -137,7 +142,7 @@ export const concat33 = (a: Mat, ia: number, ...xs: (ReadonlyMat | [ReadonlyMat,
a
);
-export const mulV33 = (m: ReadonlyMat, v: Vec, im = 0, iv = 0, sv = 1) =>
+export const mulV33 = (v: Vec, m: ReadonlyMat, iv = 0, im = 0, sv = 1) =>
setS3(
v,
dot3(m, v, im, iv, 3, sv),
@@ -204,7 +209,7 @@ export const transpose33 = (m: Mat, i = 0) =>
i
);
-export const mat33to44 = (m44: Mat, m33: Mat, ia = 0, ib = 0) => (
+export const mat33to44 = (m44: Mat, m33: ReadonlyMat, ia = 0, ib = 0) => (
set3(m44, m33, ia, ib),
set3(m44, m33, ia + 4, ib + 3),
set3(m44, m33, ia + 8, ib + 6),
@@ -229,7 +234,7 @@ export class Mat33 implements
return new Mat33(rotationZ33([], theta));
}
- static scale(v: Vec3): Mat33;
+ static scale(v: Readonly): Mat33;
static scale(n: number): Mat33;
static scale(x: number, y: number, z: number): Mat33;
static scale(x: any, y = x, z = x) {
@@ -248,8 +253,8 @@ export class Mat33 implements
buf: Mat;
i: number;
- constructor(buf: Mat, i = 0) {
- this.buf = buf;
+ constructor(buf?: Mat, i = 0) {
+ this.buf = buf || (new Array(9).fill(0));
this.i = i;
}
@@ -271,7 +276,9 @@ export class Mat33 implements
return this;
}
- setS(m00: number, m01: number, m02: number, m10: number, m11: number, m12: number, m20: number, m21: number, m22: number) {
+ setS(m00: number, m01: number, m02: number,
+ m10: number, m11: number, m12: number,
+ m20: number, m21: number, m22: number) {
setS33(this.buf, m00, m01, m02, m10, m11, m12, m20, m21, m22, this.i);
return this;
}
@@ -282,7 +289,7 @@ export class Mat33 implements
}
mulV(v: Vec3) {
- mulV33(this.buf, v.buf, this.i, v.i, v.s);
+ mulV33(v.buf, this.buf, v.i, this.i, v.s);
return v;
}
@@ -305,4 +312,8 @@ export class Mat33 implements
const i = this.i;
return `${b[i]} ${b[i + 3]} ${b[i + 6]}\n${b[i + 1]} ${b[i + 4]} ${b[i + 7]}\n${b[i + 2]} ${b[i + 5]} ${b[i + 8]}`;
}
+
+ toJSON() {
+ return get33(this.buf, this.i);
+ }
}
diff --git a/packages/vectors/src/mat44.ts b/packages/vectors/src/mat44.ts
index 0ef1aa0a31..23cfee8ed7 100644
--- a/packages/vectors/src/mat44.ts
+++ b/packages/vectors/src/mat44.ts
@@ -1,6 +1,6 @@
import { ICopy, IEqualsDelta } from "@thi.ng/api/api";
import { isArrayLike } from "@thi.ng/checks/is-arraylike";
-import { Mat, ReadonlyMat, Vec } from "./api";
+import { Mat, ReadonlyMat, Vec, ReadonlyVec } from "./api";
import { eqDelta } from "./common";
import { Mat33 } from "./mat33";
import { EPS, rad } from "./math";
@@ -17,9 +17,9 @@ import {
import { dot4, setS4, Vec4 } from "./vec4";
export const get44 = (a: Mat, i = 0) =>
- set44(new ((a.constructor))(16), a, 0, i);
+ a.slice(i, i + 16);
-export const set44 = (a: Mat, b: Mat, ia = 0, ib = 0) => {
+export const set44 = (a: Mat, b: ReadonlyMat, ia = 0, ib = 0) => {
for (let i = 0; i < 16; i++) {
a[ia + i] = b[ib + i];
}
@@ -34,7 +34,9 @@ export const set44 = (a: Mat, b: Mat, ia = 0, ib = 0) => {
* m03 m13 m23 m33
* ```
*/
-export const setS44 = (m: Mat, m00: number, m01: number, m02: number, m03: number,
+export const setS44 = (
+ m: Mat,
+ m00: number, m01: number, m02: number, m03: number,
m10: number, m11: number, m12: number, m13: number,
m20: number, m21: number, m22: number, m23: number,
m30: number, m31: number, m32: number, m33: number,
@@ -103,7 +105,7 @@ export const rotationZ44 = (m: Mat, theta: number, i = 0) => {
);
};
-export const scaleV44 = (m: Mat, v: Vec, i = 0, iv = 0, sv = 1) =>
+export const scaleV44 = (m: Mat, v: ReadonlyVec, i = 0, iv = 0, sv = 1) =>
scaleS44(m, v[iv], v[iv + sv], v[iv + 2 * sv], i);
export const scaleN44 = (m: Mat, n: number, i = 0) =>
@@ -118,14 +120,14 @@ export const scaleS44 = (m: Mat, sx: number, sy: number, sz: number, i = 0) =>
i
);
-export const scaleWithCenter44 = (m: Mat, p: Vec, sx: number, sy: number, sz: number, im = 0, iv = 0, sv = 1) =>
+export const scaleWithCenter44 = (m: Mat, p: ReadonlyVec, sx: number, sy: number, sz: number, im = 0, iv = 0, sv = 1) =>
concat44(
translationV44(m || [], p, im, iv, sv), im,
scaleS44([], sx, sy, sz),
translationS44([], -p[iv], -p[iv + sv], -p[iv + 2 * sv])
);
-export const translationV44 = (m: Mat, v: Vec, i = 0, iv = 0, sv = 1) =>
+export const translationV44 = (m: Mat, v: ReadonlyVec, i = 0, iv = 0, sv = 1) =>
translationS44(m, v[iv], v[iv + sv], v[iv + 2 * sv], i);
export const translationS44 = (m: Mat, x: number, y: number, z: number, i = 0) =>
@@ -181,18 +183,15 @@ export const ortho = (m: Mat, left: number, right: number, bottom: number, top:
);
};
-export const lookAt = (m: Mat, eye: Vec, target: Vec, up: Vec, im = 0, ie = 0, it = 0, iu = 0, se = 1, st = 1, su = 1) => {
- eye = get3(eye, ie, se);
- target = get3(target, it, st);
- up = get3(up, iu, su);
- const z = normalize3(sub3([...eye], target));
- const x = normalize3(cross3(up, z));
+export const lookAt = (m: Mat, eye: ReadonlyVec, target: ReadonlyVec, up: ReadonlyVec, im = 0, ie = 0, it = 0, iu = 0, se = 1, st = 1, su = 1) => {
+ const z = normalize3(sub3(get3(eye, ie, se), get3(target, it, st)));
+ const x = normalize3(cross3(get3(up, iu, su), z));
const y = normalize3(cross3([...z], x));
return setS44(m || [],
x[0], y[0], z[0], 0,
x[1], y[1], z[1], 0,
x[2], y[2], z[2], 0,
- -dot3(eye, x), -dot3(eye, y), -dot3(eye, z), 1,
+ -dot3(eye, x, ie, 0, se), -dot3(eye, y, ie, 0, se), -dot3(eye, z, ie, 0, se), 1,
im
);
}
@@ -227,7 +226,7 @@ export const concat44 = (a: Mat, ia: number, ...xs: (ReadonlyMat | [ReadonlyMat,
a
);
-export const mulV344 = (m: ReadonlyMat, v: Vec, im = 0, iv = 0, sv = 1) =>
+export const mulV344 = (v: Vec, m: ReadonlyMat, iv = 0, im = 0, sv = 1) =>
setS3(
v,
dot3(m, v, im, iv, 4, sv) + m[12],
@@ -236,7 +235,7 @@ export const mulV344 = (m: ReadonlyMat, v: Vec, im = 0, iv = 0, sv = 1) =>
iv, sv
);
-export const mulV44 = (m: ReadonlyMat, v: Vec, im = 0, iv = 0, sv = 1) =>
+export const mulV44 = (v: Vec, m: ReadonlyMat, iv = 0, im = 0, sv = 1) =>
setS4(
v,
dot4(m, v, im, iv, 4, sv),
@@ -279,7 +278,7 @@ const detCoeffs44 = (m: ReadonlyMat, i = 0) => {
];
};
-export const det44 = (m: Mat, i = 0) => {
+export const det44 = (m: ReadonlyMat, i = 0) => {
const d = detCoeffs44(m, i);
return d[0] * d[11] - d[1] * d[10] + d[2] * d[9] +
d[3] * d[8] - d[4] * d[7] + d[5] * d[6];
@@ -352,7 +351,7 @@ export const transpose44 = (m: Mat, i = 0) =>
i
);
-export const normal44 = (a: Mat, b: Mat, ia = 0, ib = 0) => {
+export const normal44 = (a: Mat, b: ReadonlyMat, ia = 0, ib = 0) => {
const m00 = b[ib];
const m01 = b[ib + 1];
const m02 = b[ib + 2];
@@ -382,7 +381,7 @@ export const normal44 = (a: Mat, b: Mat, ia = 0, ib = 0) => {
return a;
};
-export const mat44to33 = (m33: Mat, m44: Mat, ia = 0, ib = 0) => (
+export const mat44to33 = (m33: Mat, m44: ReadonlyMat, ia = 0, ib = 0) => (
set3(m33, m44, ia, ib),
set3(m33, m44, ia + 3, ib + 4),
set3(m33, m44, ia + 6, ib + 8),
@@ -405,7 +404,7 @@ export class Mat44 implements
return new Mat44(rotationZ44([], theta));
}
- static scale(v: Vec3): Mat44;
+ static scale(v: Readonly): Mat44;
static scale(n: number): Mat44;
static scale(x: number, y: number, z: number): Mat44;
static scale(x: any, y = x, z = x) {
@@ -416,11 +415,11 @@ export class Mat44 implements
);
}
- static scaleWithCenter(p: Vec3, sx: number, sy = sx, sz = sy) {
+ static scaleWithCenter(p: Readonly, sx: number, sy = sx, sz = sy) {
return new Mat44(scaleWithCenter44([], p.buf, sx, sy, sz, p.i, p.s));
}
- static translation(v: Vec3): Mat44;
+ static translation(v: Readonly): Mat44;
static translation(x: number, y: number, z: number): Mat44;
static translation(x: any, y?: any, z?: any) {
return new Mat44(
@@ -430,6 +429,27 @@ export class Mat44 implements
);
}
+ static perspective(fov: number, aspect: number, near: number, far: number) {
+ return new Mat44(perspective([], fov, aspect, near, far));
+ }
+
+ static ortho(left: number, right: number, bottom: number, top: number, near: number, far: number) {
+ return new Mat44(ortho([], left, right, bottom, top, near, far));
+ }
+
+ static frustum(left: number, right: number, bottom: number, top: number, near: number, far: number) {
+ return new Mat44(frustum([], left, right, bottom, top, near, far));
+ }
+
+ static lookAt(eye: Readonly, target: Readonly, up: Readonly) {
+ return new Mat44(lookAt(
+ [],
+ eye.buf, target.buf, up.buf,
+ 0, eye.i, target.i, up.i,
+ eye.s, target.s, up.s
+ ));
+ }
+
static concat(m: Mat44, ...xs: Readonly[]) {
concat44.apply(null, [m.buf, m.i, ...<[ReadonlyMat, number][]>xs.map((x) => [x.buf, x.i])]);
return m;
@@ -438,8 +458,8 @@ export class Mat44 implements
buf: Mat;
i: number;
- constructor(buf: Mat, i = 0) {
- this.buf = buf;
+ constructor(buf?: Mat, i = 0) {
+ this.buf = buf || (new Array(16).fill(0));
this.i = i;
}
@@ -475,12 +495,12 @@ export class Mat44 implements
}
mulV3(v: Vec3) {
- mulV344(this.buf, v.buf, this.i, v.i, v.s);
+ mulV344(v.buf, this.buf, v.i, this.i, v.s);
return v;
}
mulV(v: Vec4) {
- mulV44(this.buf, v.buf, this.i, v.i, v.s);
+ mulV44(v.buf, this.buf, v.i, this.i, v.s);
return v;
}
@@ -511,8 +531,12 @@ export class Mat44 implements
}
toString() {
- const b = this.buf;
const i = this.i;
+ const b = [...this.buf.slice(i, i+16)].map((x)=>x.toFixed(4));
return `${b[i]} ${b[i + 4]} ${b[i + 8]} ${b[i + 12]}\n${b[i + 1]} ${b[i + 5]} ${b[i + 9]} ${b[i + 13]}\n${b[i + 2]} ${b[i + 6]} ${b[i + 10]} ${b[i + 14]}\n${b[i + 3]} ${b[i + 7]} ${b[i + 11]} ${b[i + 15]}`;
}
+
+ toJSON() {
+ return get44(this.buf, this.i);
+ }
}
diff --git a/packages/vectors/src/math.ts b/packages/vectors/src/math.ts
index 9f8d9fb182..282ba4df39 100644
--- a/packages/vectors/src/math.ts
+++ b/packages/vectors/src/math.ts
@@ -8,10 +8,10 @@ export const RAD2DEG = 180 / PI;
export let EPS = 1e-6;
-export const absDiff = (x: number, y: number) =>
+export const absDiff1 = (x: number, y: number) =>
Math.abs(x - y);
-export const atan2Abs = (y: number, x: number) => {
+export const atan2Abs1 = (y: number, x: number) => {
const theta = Math.atan2(y, x);
return theta < 0 ? TAU + theta : theta;
};
@@ -48,7 +48,8 @@ export const eqDelta1 = (a: number, b: number, eps = EPS) => {
* @param a
* @param b
*/
-export const fmod1 = (a: number, b: number) => a - b * Math.floor(a / b);
+export const fmod1 = (a: number, b: number) =>
+ a - b * Math.floor(a / b);
/**
* Step/threshold function.
@@ -57,7 +58,8 @@ export const fmod1 = (a: number, b: number) => a - b * Math.floor(a / b);
* @param x test value
* @returns 0, if `x < e`, else 1
*/
-export const step1 = (edge: number, x: number) => x < edge ? 0 : 1;
+export const step1 = (edge: number, x: number) =>
+ x < edge ? 0 : 1;
/**
* GLSL-style smoothStep threshold function.
@@ -72,7 +74,16 @@ export const smoothStep1 = (edge: number, edge2: number, x: number) => {
return (3 - 2 * t) * t * t;
};
-export const min2id = (a, b) => a <= b ? 0 : 1;
+export const expStep1 = (x: number, k: number, n: number) =>
+ Math.exp(-k * Math.pow(x, n));
+
+export const gain1 = (x: number, k: number) =>
+ x < 0.5 ?
+ 0.5 * Math.pow(2 * x, k) :
+ 1 - 0.5 * Math.pow(2 - 2 * x, k);
+
+export const min2id = (a, b) =>
+ a <= b ? 0 : 1;
export const min3id = (a, b, c) =>
(a <= b) ?
@@ -88,7 +99,8 @@ export const min4id = (a, b, c, d) =>
(b <= d ? 1 : 3) :
(c <= d ? 2 : 3));
-export const max2id = (a, b) => a >= b ? 0 : 1;
+export const max2id = (a, b) =>
+ a >= b ? 0 : 1;
export const max3id = (a, b, c) =>
(a >= b) ?
@@ -104,16 +116,28 @@ export const max4id = (a, b, c, d) =>
(b >= d ? 1 : 3) :
(c >= d ? 2 : 3));
+export const smin1 = (a: number, b: number, k: number) =>
+ -Math.log(Math.exp(-k * a) + Math.exp(-k * b)) / k;
+
+export const smax1 = (a: number, b: number, k: number) =>
+ Math.log(Math.exp(a) + Math.exp(b)) / k;
+
/**
- * Clamps value `x` to given closed interval.
- *
- * @param x value to clamp
- * @param min lower bound
- * @param max upper bound
- */
+* Clamps value `x` to given closed interval.
+*
+* @param x value to clamp
+* @param min lower bound
+* @param max upper bound
+*/
export const clamp1 = (x: number, min: number, max: number) =>
x < min ? min : x > max ? max : x;
+export const mix1 = (a: number, b: number, t: number) =>
+ a + (b - a) * t;
+
+export const norm1 = (x: number, a: number, b: number) =>
+ (x - a) / (b - a);
+
export const fit1 = (x: number, a: number, b: number, c: number, d: number) =>
c + (d - c) * (x - a) / (b - a);
@@ -123,6 +147,9 @@ export const fitClamped1 = (x: number, a: number, b: number, c: number, d: numbe
export const sign1 = (x: number, eps = EPS) =>
x > eps ? 1 : x < -eps ? -1 : 0;
+export const fract1 = (x: number) =>
+ x - Math.floor(x);
+
export const trunc1 = (x: number) =>
x < 0 ? Math.ceil(x) : Math.floor(x);
@@ -136,7 +163,7 @@ export const roundTo1 = (x: number, prec = 1) =>
* @param min
* @param max
*/
-export const inRange = (x: number, min: number, max: number) =>
+export const inRange1 = (x: number, min: number, max: number) =>
x >= min && x <= max;
/**
@@ -146,5 +173,8 @@ export const inRange = (x: number, min: number, max: number) =>
* @param min
* @param max
*/
-export const inOpenRange = (x: number, min: number, max: number) =>
+export const inOpenRange1 = (x: number, min: number, max: number) =>
x > min && x < max;
+
+export const hash1 = (x: number) =>
+ fract1(Math.sin(x) * 758.5453);
diff --git a/packages/vectors/src/vec2.ts b/packages/vectors/src/vec2.ts
index bcb13cafb4..26d117b03e 100644
--- a/packages/vectors/src/vec2.ts
+++ b/packages/vectors/src/vec2.ts
@@ -6,21 +6,29 @@ import {
} from "@thi.ng/api/api";
import { isArrayLike } from "@thi.ng/checks/is-arraylike";
-import { IVec, ReadonlyVec, Vec } from "./api";
+import {
+ IVec,
+ MAX4,
+ MIN4,
+ ONE4,
+ ReadonlyVec,
+ Vec,
+ ZERO4
+} from "./api";
import { declareIndices } from "./common";
import {
- atan2Abs,
+ atan2Abs1,
EPS,
eqDelta1,
+ fract1,
+ HALF_PI,
max2id,
min2id,
+ PI,
smoothStep1,
step1
} from "./math";
-export const ZERO2 = Object.freeze([0, 0]);
-export const ONE2 = Object.freeze([1, 1]);
-
export const op2 = (fn: (x: number) => number, a: Vec, ia = 0, sa = 1) =>
(a[ia] = fn(a[ia]), a[ia + sa] = fn(a[ia + sa]), a);
@@ -42,7 +50,7 @@ export const setN2 = (a: Vec, n: number, ia = 0, sa = 1) =>
export const setS2 = (a: Vec, x: number, y: number, ia = 0, sa = 1) =>
(a[ia] = x, a[ia + sa] = y, a);
-export const swizzle2 = (a: Vec, b: Vec, x: number, y: number, ia = 0, ib = 0, sa = 1, sb = 1) => {
+export const swizzle2 = (a: Vec, b: ReadonlyVec, x: number, y: number, ia = 0, ib = 0, sa = 1, sb = 1) => {
const xx = b[ib + x * sb];
const yy = b[ib + y * sb];
a[ia] = xx;
@@ -50,6 +58,13 @@ export const swizzle2 = (a: Vec, b: Vec, x: number, y: number, ia = 0, ib = 0, s
return a;
};
+export const swap2 = (a: Vec, b: Vec, ia = 0, ib = 0, sa = 1, sb = 1) => {
+ let t = a[ia]; a[ia] = b[ib]; b[ib] = t;
+ ia += sa; ib += sb;
+ t = a[ia]; a[ia] = b[ib]; b[ib] = t;
+ return a;
+};
+
export const equiv2 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) =>
a[ia] === b[ib] &&
a[ia + sa] === b[ib + sb];
@@ -97,6 +112,9 @@ export const floor2 = (a: Vec, ia = 0, sa = 1) =>
export const ceil2 = (a: Vec, ia = 0, sa = 1) =>
op2(Math.ceil, a, ia, sa);
+export const fract2 = (a: Vec, ia = 0, sa = 1) =>
+ op2(fract1, a, ia, sa);
+
export const sin2 = (a: Vec, ia = 0, sa = 1) =>
op2(Math.sin, a, ia, sa);
@@ -208,15 +226,38 @@ export const rotate2 = (a: Vec, theta: number, ia = 0, sa = 1) => {
return setS2(a, x * c - y * s, x * s + y * c, ia, sa);
};
+export const rotateAroundPoint2 = (a: Vec, b: Vec, theta: number, ia = 0, ib = 0, sa = 1, sb = 1) => {
+ const x = a[ia] - b[ib];
+ const y = a[ia + sa] - b[ib + sb];
+ const s = Math.sin(theta);
+ const c = Math.cos(theta);
+ return setS2(
+ a,
+ x * c - y * s + b[ib],
+ x * s + y * c + b[ib + sb],
+ ia, sa
+ );
+};
+
export const heading2 = (a: ReadonlyVec, ia = 0, sa = 1) =>
- atan2Abs(a[ia + sa], a[ia]);
+ atan2Abs1(a[ia + sa], a[ia]);
+
+export const angleBetween2 = (a: ReadonlyVec, b: ReadonlyVec, normalize = false, ia = 0, ib = 0, sa = 1, sb = 1): number =>
+ normalize ?
+ angleBetween2(get2(a, ia, sa), get2(b, ib, sb)) :
+ Math.acos(dot2(a, b, ia, ib, sa, sb));
+
+export const bisect2 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => {
+ const theta = (heading2(a, ia, sa) + heading2(b, ib, sb)) / 2;
+ return theta <= HALF_PI ? theta : PI - theta;
+}
export const toPolar2 = (a: Vec, ia = 0, sa = 1) => {
const x = a[ia], y = a[ia + sa];
- return setS2(a, Math.sqrt(x * x + y * y), atan2Abs(y, x), ia, sa);
+ return setS2(a, Math.sqrt(x * x + y * y), atan2Abs1(y, x), ia, sa);
};
-export const toCartesian2 = (a: Vec, b: ReadonlyVec = ZERO2, ia = 0, ib = 0, sa = 1, sb = 1) => {
+export const toCartesian2 = (a: Vec, b: ReadonlyVec = ZERO4, ia = 0, ib = 0, sa = 1, sb = 1) => {
const r = a[ia], theta = a[ia + sa];
return setS2(
a,
@@ -266,12 +307,16 @@ export class Vec2 implements
return res;
}
- static ZERO = Object.freeze(new Vec2(ZERO2));
- static ONE = Object.freeze(new Vec2(ONE2));
+ static readonly ZERO = Object.freeze(new Vec2(ZERO4));
+ static readonly ONE = Object.freeze(new Vec2(ONE4));
+ static readonly MIN = Object.freeze(new Vec2(MIN4));
+ static readonly MAX = Object.freeze(new Vec2(MAX4));
buf: Vec;
i: number;
s: number;
+ x: number;
+ y: number;
[0]: number;
[1]: number;
@@ -282,28 +327,15 @@ export class Vec2 implements
}
*[Symbol.iterator]() {
- yield this.x;
- yield this.y;
- }
-
- get length() {
- return 2;
- }
-
- get x() {
- return this.buf[this.i];
+ yield* this.array();
}
- set x(x: number) {
- this.buf[this.i] = x;
+ array() {
+ return get2(this.buf, this.i, this.s);
}
- get y() {
- return this.buf[this.i + this.s];
- }
-
- set y(y: number) {
- this.buf[this.i + this.s] = y;
+ get length() {
+ return 2;
}
copy() {
@@ -314,7 +346,7 @@ export class Vec2 implements
return v instanceof Vec2 ?
equiv2(this.buf, v.buf, this.i, v.i, this.s, v.s) :
isArrayLike(v) && v.length === 2 ?
- equiv2(this.buf, v, this.i, 0, this.s, 1) :
+ equiv2(this.buf, v, this.i, 0, this.s, 1) :
false;
}
@@ -342,6 +374,11 @@ export class Vec2 implements
return this;
}
+ swap(v: Vec2) {
+ swap2(this.buf, v.buf, this.i, v.i, this.s, v.s);
+ return this;
+ }
+
add(v: Readonly) {
add2(this.buf, v.buf, this.i, v.i, this.s, v.s);
return this;
@@ -407,6 +444,11 @@ export class Vec2 implements
return this;
}
+ fract() {
+ fract2(this.buf, this.i, this.s);
+ return this;
+ }
+
sqrt() {
sqrt2(this.buf, this.i, this.s);
return this;
@@ -537,10 +579,23 @@ export class Vec2 implements
return this;
}
+ rotateAroundPoint(v: Readonly, theta: number) {
+ rotateAroundPoint2(this.buf, v.buf, theta, this.i, v.i, this.s, v.s);
+ return this;
+ }
+
heading() {
return heading2(this.buf, this.i, this.s);
}
+ angleBetween(v: Readonly, normalize = false) {
+ return angleBetween2(this.buf, v.buf, normalize, this.i, v.i, this.s, v.s);
+ }
+
+ bisect(v: Readonly) {
+ return bisect2(this.buf, v.buf, this.i, v.i, this.s, v.s);
+ }
+
toPolar() {
toPolar2(this.buf, this.i, this.s);
return this;
@@ -554,6 +609,10 @@ export class Vec2 implements
toString() {
return `[${this.buf[this.i]}, ${this.buf[this.i + this.s]}]`;
}
+
+ toJSON() {
+ return this.array();
+ }
}
declareIndices(Vec2.prototype, [0, 1]);
diff --git a/packages/vectors/src/vec3.ts b/packages/vectors/src/vec3.ts
index b430a866d5..48415fe0af 100644
--- a/packages/vectors/src/vec3.ts
+++ b/packages/vectors/src/vec3.ts
@@ -6,12 +6,21 @@ import {
} from "@thi.ng/api/api";
import { isArrayLike } from "@thi.ng/checks/is-arraylike";
-import { IVec, ReadonlyVec, Vec } from "./api";
+import {
+ IVec,
+ MAX4,
+ MIN4,
+ ONE4,
+ ReadonlyVec,
+ Vec,
+ ZERO4
+} from "./api";
import { declareIndices } from "./common";
import {
- atan2Abs,
+ atan2Abs1,
EPS,
eqDelta1,
+ fract1,
max3id,
min3id,
sign1,
@@ -25,9 +34,6 @@ import {
toPolar2
} from "./vec2";
-export const ZERO3 = Object.freeze([0, 0, 0]);
-export const ONE3 = Object.freeze([1, 1, 1]);
-
export const op3 = (fn: (x: number) => number, a: Vec, ia = 0, sa = 1) => (
a[ia] = fn(a[ia]),
a[ia + sa] = fn(a[ia + sa]),
@@ -62,7 +68,7 @@ export const setN3 = (a: Vec, n: number, ia = 0, sa = 1) => (
export const setS3 = (a: Vec, x: number, y: number, z: number, ia = 0, sa = 1) =>
(a[ia] = x, a[ia + sa] = y, a[ia + 2 * sa] = z, a);
-export const swizzle3 = (a: Vec, b: Vec, x: number, y: number, z: number, ia = 0, ib = 0, sa = 1, sb = 1) => {
+export const swizzle3 = (a: Vec, b: ReadonlyVec, x: number, y: number, z: number, ia = 0, ib = 0, sa = 1, sb = 1) => {
const xx = b[ib + x * sb];
const yy = b[ib + y * sb];
const zz = b[ib + z * sb];
@@ -72,6 +78,15 @@ export const swizzle3 = (a: Vec, b: Vec, x: number, y: number, z: number, ia = 0
return a;
};
+export const swap3 = (a: Vec, b: Vec, ia = 0, ib = 0, sa = 1, sb = 1) => {
+ let t = a[ia]; a[ia] = b[ib]; b[ib] = t;
+ ia += sa; ib += sb;
+ t = a[ia]; a[ia] = b[ib]; b[ib] = t;
+ ia += sa; ib += sb;
+ t = a[ia]; a[ia] = b[ib]; b[ib] = t;
+ return a;
+};
+
export const equiv3 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) =>
a[ia] === b[ib] &&
a[ia + sa] === b[ib + sb] &&
@@ -137,6 +152,9 @@ export const floor3 = (a: Vec, ia = 0, sa = 1) =>
export const ceil3 = (a: Vec, ia = 0, sa = 1) =>
op3(Math.ceil, a, ia, sa);
+export const fract3 = (a: Vec, ia = 0, sa = 1) =>
+ op3(fract1, a, ia, sa);
+
export const sin3 = (a: Vec, ia = 0, sa = 1) =>
op3(Math.sin, a, ia, sa);
@@ -282,23 +300,55 @@ export const rotateY3 = (a: Vec, theta: number, ia = 0, sa = 1) =>
export const rotateZ3 = rotate2;
+export const rotateAroundAxis3 = (v: Vec, axis: Vec, theta: number, ia = 0, ib = 0, sa = 1, sb = 1) => {
+ const x = v[ia];
+ const y = v[ia + sa];
+ const z = v[ia + 2 * sa];
+ const ax = axis[ib];
+ const ay = axis[ib + sb];
+ const az = axis[ib + 2 * sb];
+ const ux = ax * x;
+ const uy = ax * y;
+ const uz = ax * z;
+ const vx = ay * x;
+ const vy = ay * y;
+ const vz = ay * z;
+ const wx = az * x;
+ const wy = az * y;
+ const wz = az * z;
+ const uvw = ux + vy + wz;
+ const s = Math.sin(theta);
+ const c = Math.cos(theta);
+ return setS3(v,
+ (ax * uvw + (x * (ay * ay + az * az) - ax * (vy + wz)) * c + (-wy + vz) * s),
+ (ay * uvw + (y * (ax * ax + az * az) - ay * (ux + wz)) * c + (wx - uz) * s),
+ (az * uvw + (z * (ax * ax + ay * ay) - az * (ux + vy)) * c + (-vx + uy) * s),
+ ia, sa
+ );
+}
+
export const headingXY3 = heading2;
export const headingXZ3 = (a: ReadonlyVec, ia = 0, sa = 1) =>
- atan2Abs(a[ia + 2 * sa], a[ia]);
+ atan2Abs1(a[ia + 2 * sa], a[ia]);
export const headingYZ3 = (a: ReadonlyVec, ia = 0, sa = 1) =>
- atan2Abs(a[ia + 2 * sa], a[ia + sa]);
+ atan2Abs1(a[ia + 2 * sa], a[ia + sa]);
+
+export const angleBetween3 = (a: ReadonlyVec, b: ReadonlyVec, normalize = false, ia = 0, ib = 0, sa = 1, sb = 1): number =>
+ normalize ?
+ angleBetween3(get3(a, ia, sa), get3(b, ib, sb)) :
+ Math.acos(dot3(a, b, ia, ib, sa, sb));
export const toSpherical3 = (a: Vec, ia = 0, sa = 1) => {
const x = a[ia];
const y = a[ia + sa];
const z = a[ia + 2 * sa];
const r = Math.sqrt(x * x + y * y + z * z);
- return setS3(a, r, Math.asin(z / r), atan2Abs(y, x), ia, sa);
+ return setS3(a, r, Math.asin(z / r), atan2Abs1(y, x), ia, sa);
};
-export const toCartesian3 = (a: Vec, b: ReadonlyVec = ZERO3, ia = 0, ib = 0, sa = 1, sb = 1) => {
+export const toCartesian3 = (a: Vec, b: ReadonlyVec = ZERO4, ia = 0, ib = 0, sa = 1, sb = 1) => {
const r = a[ia];
const theta = a[ia + sa];
const phi = a[ia + 2 * sa];
@@ -313,7 +363,7 @@ export const toCartesian3 = (a: Vec, b: ReadonlyVec = ZERO3, ia = 0, ib = 0, sa
export const toCylindrical3 = toPolar2;
-export const fromCylindrical3 = (a: Vec, b: ReadonlyVec = ZERO3, ia = 0, ib = 0, sa = 1, sb = 1) => {
+export const fromCylindrical3 = (a: Vec, b: ReadonlyVec = ZERO4, ia = 0, ib = 0, sa = 1, sb = 1) => {
toCartesian2(a, b, ia, ib, sa, sb);
a[ia + 2 * sa] += b[ib + 2 * sb];
return a;
@@ -363,12 +413,17 @@ export class Vec3 implements
return new Vec3(orthoNormal3(a.buf, b.buf, c.buf, a.i, b.i, c.i, a.s, b.s, c.s));
}
- static ZERO = Object.freeze(new Vec3(ZERO3));
- static ONE = Object.freeze(new Vec3(ONE3));
+ static readonly ZERO = Object.freeze(new Vec3(ZERO4));
+ static readonly ONE = Object.freeze(new Vec3(ONE4));
+ static readonly MIN = Object.freeze(new Vec3(MIN4));
+ static readonly MAX = Object.freeze(new Vec3(MAX4));
buf: Vec;
i: number;
s: number;
+ x: number;
+ y: number;
+ z: number;
[0]: number;
[1]: number;
[2]: number;
@@ -380,37 +435,15 @@ export class Vec3 implements
}
*[Symbol.iterator]() {
- yield this.x;
- yield this.y;
- yield this.z;
- }
-
- get length() {
- return 3;
- }
-
- get x() {
- return this.buf[this.i];
- }
-
- set x(x: number) {
- this.buf[this.i] = x;
+ yield* this.array();
}
- get y() {
- return this.buf[this.i + this.s];
+ array() {
+ return get3(this.buf, this.i, this.s);
}
- set y(y: number) {
- this.buf[this.i + this.s] = y;
- }
-
- get z() {
- return this.buf[this.i + 2 * this.s];
- }
-
- set z(z: number) {
- this.buf[this.i + 2 * this.s] = z;
+ get length() {
+ return 3;
}
copy() {
@@ -421,7 +454,7 @@ export class Vec3 implements
return v instanceof Vec3 ?
equiv3(this.buf, v.buf, this.i, v.i, this.s, v.s) :
isArrayLike(v) && v.length === 3 ?
- equiv3(this.buf, v, this.i, 0, this.s, 1) :
+ equiv3(this.buf, v, this.i, 0, this.s, 1) :
false;
}
@@ -449,6 +482,11 @@ export class Vec3 implements
return this;
}
+ swap(v: Vec3) {
+ swap3(this.buf, v.buf, this.i, v.i, this.s, v.s);
+ return this;
+ }
+
add(v: Readonly) {
add3(this.buf, v.buf, this.i, v.i, this.s, v.s);
return this;
@@ -514,6 +552,11 @@ export class Vec3 implements
return this;
}
+ fract() {
+ fract3(this.buf, this.i, this.s);
+ return this;
+ }
+
sqrt() {
sqrt3(this.buf, this.i, this.s);
return this;
@@ -659,6 +702,11 @@ export class Vec3 implements
return this;
}
+ rotateAroundAxis(axis: Vec3, theta: number) {
+ rotateAroundAxis3(this.buf, axis.buf, theta, this.i, axis.i, this.s, axis.s);
+ return this;
+ }
+
headingXY() {
return headingXY3(this.buf, this.i, this.s);
}
@@ -671,6 +719,10 @@ export class Vec3 implements
return headingYZ3(this.buf, this.i, this.s);
}
+ angleBetween(v: Readonly, normalize = false) {
+ return angleBetween3(this.buf, v.buf, normalize, this.i, v.i, this.s, v.s);
+ }
+
toSpherical() {
toSpherical3(this.buf, this.i, this.s);
return this;
@@ -694,6 +746,10 @@ export class Vec3 implements
toString() {
return `[${this.buf[this.i]}, ${this.buf[this.i + this.s]}, ${this.buf[this.i + 2 * this.s]}]`;
}
+
+ toJSON() {
+ return this.array();
+ }
}
declareIndices(Vec3.prototype, [0, 1, 2]);
diff --git a/packages/vectors/src/vec4.ts b/packages/vectors/src/vec4.ts
index 4f4c34fa25..c0c2303a0f 100644
--- a/packages/vectors/src/vec4.ts
+++ b/packages/vectors/src/vec4.ts
@@ -6,20 +6,26 @@ import {
} from "@thi.ng/api/api";
import { isArrayLike } from "@thi.ng/checks/is-arraylike";
-import { IVec, ReadonlyVec, Vec } from "./api";
+import {
+ IVec,
+ MAX4,
+ MIN4,
+ ONE4,
+ ReadonlyVec,
+ Vec,
+ ZERO4
+} from "./api";
import { declareIndices } from "./common";
import {
EPS,
eqDelta1,
+ fract1,
max4id,
min4id,
smoothStep1,
step1
} from "./math";
-export const ZERO4 = Object.freeze([0, 0, 0, 0]);
-export const ONE4 = Object.freeze([1, 1, 1, 1]);
-
export const op4 = (fn: (x: number) => number, a: Vec, ia = 0, sa = 1) => (
a[ia] = fn(a[ia]),
a[ia + sa] = fn(a[ia + sa]),
@@ -63,7 +69,7 @@ export const setS4 = (a: Vec, x: number, y: number, z: number, w: number, ia = 0
a
);
-export const swizzle4 = (a: Vec, b: Vec, x: number, y: number, z: number, w: number, ia = 0, ib = 0, sa = 1, sb = 1) => {
+export const swizzle4 = (a: Vec, b: ReadonlyVec, x: number, y: number, z: number, w: number, ia = 0, ib = 0, sa = 1, sb = 1) => {
const xx = b[ib + x * sb];
const yy = b[ib + y * sb];
const zz = b[ib + z * sb];
@@ -75,6 +81,17 @@ export const swizzle4 = (a: Vec, b: Vec, x: number, y: number, z: number, w: num
return a;
};
+export const swap4 = (a: Vec, b: Vec, ia = 0, ib = 0, sa = 1, sb = 1) => {
+ let t = a[ia]; a[ia] = b[ib]; b[ib] = t;
+ ia += sa; ib += sb;
+ t = a[ia]; a[ia] = b[ib]; b[ib] = t;
+ ia += sa; ib += sb;
+ t = a[ia]; a[ia] = b[ib]; b[ib] = t;
+ ia += sa; ib += sb;
+ t = a[ia]; a[ia] = b[ib]; b[ib] = t;
+ return a;
+};
+
export const equiv4 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) =>
a[ia] === b[ib] &&
a[ia + sa] === b[ib + sb] &&
@@ -146,6 +163,9 @@ export const floor4 = (a: Vec, ia = 0, sa = 1) =>
export const ceil4 = (a: Vec, ia = 0, sa = 1) =>
op4(Math.ceil, a, ia, sa);
+export const fract4 = (a: Vec, ia = 0, sa = 1) =>
+ op4(fract1, a, ia, sa);
+
export const sin4 = (a: Vec, ia = 0, sa = 1) =>
op4(Math.sin, a, ia, sa);
@@ -315,12 +335,18 @@ export class Vec4 implements
return res;
}
- static ZERO = Object.freeze(new Vec4(ZERO4));
- static ONE = Object.freeze(new Vec4(ONE4));
+ static readonly ZERO = Object.freeze(new Vec4(ZERO4));
+ static readonly ONE = Object.freeze(new Vec4(ONE4));
+ static readonly MIN = Object.freeze(new Vec4(MIN4));
+ static readonly MAX = Object.freeze(new Vec4(MAX4));
buf: Vec;
i: number;
s: number;
+ x: number;
+ y: number;
+ z: number;
+ w: number;
[0]: number;
[1]: number;
[2]: number;
@@ -333,46 +359,15 @@ export class Vec4 implements
}
*[Symbol.iterator]() {
- yield this.x;
- yield this.y;
- yield this.z;
- yield this.w;
- }
-
- get length() {
- return 4;
- }
-
- get x() {
- return this.buf[this.i];
- }
-
- set x(x: number) {
- this.buf[this.i] = x;
- }
-
- get y() {
- return this.buf[this.i + this.s];
+ yield* this.array();
}
- set y(y: number) {
- this.buf[this.i + this.s] = y;
+ array() {
+ return get4(this.buf, this.i, this.s);
}
- get z() {
- return this.buf[this.i + 2 * this.s];
- }
-
- set z(z: number) {
- this.buf[this.i + 2 * this.s] = z;
- }
-
- get w() {
- return this.buf[this.i + 3 * this.s];
- }
-
- set w(w: number) {
- this.buf[this.i + 3 * this.s] = w;
+ get length() {
+ return 4;
}
copy() {
@@ -383,7 +378,7 @@ export class Vec4 implements
return v instanceof Vec4 ?
equiv4(this.buf, v.buf, this.i, v.i, this.s, v.s) :
isArrayLike(v) && v.length === 4 ?
- equiv4(this.buf, v, this.i, 0, this.s, 1) :
+ equiv4(this.buf, v, this.i, 0, this.s, 1) :
false;
}
@@ -411,6 +406,11 @@ export class Vec4 implements
return this;
}
+ swap(v: Vec4) {
+ swap4(this.buf, v.buf, this.i, v.i, this.s, v.s);
+ return this;
+ }
+
add(v: Readonly) {
add4(this.buf, v.buf, this.i, v.i, this.s, v.s);
return this;
@@ -476,6 +476,11 @@ export class Vec4 implements
return this;
}
+ fract() {
+ fract4(this.buf, this.i, this.s);
+ return this;
+ }
+
sqrt() {
sqrt4(this.buf, this.i, this.s);
return this;
@@ -600,6 +605,10 @@ export class Vec4 implements
toString() {
return `[${this.buf[this.i]}, ${this.buf[this.i + this.s]}, ${this.buf[this.i + 2 * this.s]}, ${this.buf[this.i + 3 * this.s]}]`;
}
+
+ toJSON() {
+ return this.array();
+ }
}
declareIndices(Vec4.prototype, [0, 1, 2, 3]);
diff --git a/scripts/make-module b/scripts/make-module
index 9ce8e70bf2..431659b7db 100755
--- a/scripts/make-module
+++ b/scripts/make-module
@@ -55,7 +55,7 @@ cat << EOF > $MODULE/package.json
"typescript": "^3.0.1"
},
"dependencies": {
- "@thi.ng/api": "^4.0.6"
+ "@thi.ng/api": "^4.1.0"
},
"keywords": [
"ES6",
diff --git a/yarn.lock b/yarn.lock
index 37ca9107df..8e151c7470 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8,23 +8,23 @@
dependencies:
"@babel/highlight" "7.0.0-beta.51"
-"@babel/code-frame@7.0.0-rc.2":
- version "7.0.0-rc.2"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-rc.2.tgz#12b6daeb408238360744649d16c0e9fa7ab3859e"
+"@babel/code-frame@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8"
dependencies:
- "@babel/highlight" "7.0.0-rc.2"
+ "@babel/highlight" "^7.0.0"
"@babel/core@^7.0.0-beta.46":
- version "7.0.0-rc.2"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.0.0-rc.2.tgz#dcb46b3adb63e35b1e82c35d9130d9c27be58427"
- dependencies:
- "@babel/code-frame" "7.0.0-rc.2"
- "@babel/generator" "7.0.0-rc.2"
- "@babel/helpers" "7.0.0-rc.2"
- "@babel/parser" "7.0.0-rc.2"
- "@babel/template" "7.0.0-rc.2"
- "@babel/traverse" "7.0.0-rc.2"
- "@babel/types" "7.0.0-rc.2"
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.0.0.tgz#0cb0c0fd2e78a0a2bec97698f549ae9ce0b99515"
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ "@babel/generator" "^7.0.0"
+ "@babel/helpers" "^7.0.0"
+ "@babel/parser" "^7.0.0"
+ "@babel/template" "^7.0.0"
+ "@babel/traverse" "^7.0.0"
+ "@babel/types" "^7.0.0"
convert-source-map "^1.1.0"
debug "^3.1.0"
json5 "^0.5.0"
@@ -43,11 +43,11 @@
source-map "^0.5.0"
trim-right "^1.0.1"
-"@babel/generator@7.0.0-rc.2":
- version "7.0.0-rc.2"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-rc.2.tgz#7aed8fb4ef1bdcc168225096b5b431744ba76bf8"
+"@babel/generator@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0.tgz#1efd58bffa951dc846449e58ce3a1d7f02d393aa"
dependencies:
- "@babel/types" "7.0.0-rc.2"
+ "@babel/types" "^7.0.0"
jsesc "^2.5.1"
lodash "^4.17.10"
source-map "^0.5.0"
@@ -61,13 +61,13 @@
"@babel/template" "7.0.0-beta.51"
"@babel/types" "7.0.0-beta.51"
-"@babel/helper-function-name@7.0.0-rc.2":
- version "7.0.0-rc.2"
- resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-rc.2.tgz#ad7bb9df383c5f53e4bf38c0fe0c7f93e6a27729"
+"@babel/helper-function-name@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0.tgz#a68cc8d04420ccc663dd258f9cc41b8261efa2d4"
dependencies:
- "@babel/helper-get-function-arity" "7.0.0-rc.2"
- "@babel/template" "7.0.0-rc.2"
- "@babel/types" "7.0.0-rc.2"
+ "@babel/helper-get-function-arity" "^7.0.0"
+ "@babel/template" "^7.0.0"
+ "@babel/types" "^7.0.0"
"@babel/helper-get-function-arity@7.0.0-beta.51":
version "7.0.0-beta.51"
@@ -75,11 +75,11 @@
dependencies:
"@babel/types" "7.0.0-beta.51"
-"@babel/helper-get-function-arity@7.0.0-rc.2":
- version "7.0.0-rc.2"
- resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-rc.2.tgz#323cb82e2d805b40c0c36be1dfcb8ffcbd0434f3"
+"@babel/helper-get-function-arity@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3"
dependencies:
- "@babel/types" "7.0.0-rc.2"
+ "@babel/types" "^7.0.0"
"@babel/helper-split-export-declaration@7.0.0-beta.51":
version "7.0.0-beta.51"
@@ -87,19 +87,19 @@
dependencies:
"@babel/types" "7.0.0-beta.51"
-"@babel/helper-split-export-declaration@7.0.0-rc.2":
- version "7.0.0-rc.2"
- resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-rc.2.tgz#726b2dec4e46baeab32db67caa6e88b6521464f8"
+"@babel/helper-split-export-declaration@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813"
dependencies:
- "@babel/types" "7.0.0-rc.2"
+ "@babel/types" "^7.0.0"
-"@babel/helpers@7.0.0-rc.2":
- version "7.0.0-rc.2"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.0.0-rc.2.tgz#e21f54451824f55b4f5022c6e9d6fa7df65e8746"
+"@babel/helpers@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.0.0.tgz#7213388341eeb07417f44710fd7e1d00acfa6ac0"
dependencies:
- "@babel/template" "7.0.0-rc.2"
- "@babel/traverse" "7.0.0-rc.2"
- "@babel/types" "7.0.0-rc.2"
+ "@babel/template" "^7.0.0"
+ "@babel/traverse" "^7.0.0"
+ "@babel/types" "^7.0.0"
"@babel/highlight@7.0.0-beta.51":
version "7.0.0-beta.51"
@@ -109,9 +109,9 @@
esutils "^2.0.2"
js-tokens "^3.0.0"
-"@babel/highlight@7.0.0-rc.2":
- version "7.0.0-rc.2"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-rc.2.tgz#0af688a69e3709d9cf392e1837cda18c08d34d4f"
+"@babel/highlight@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4"
dependencies:
chalk "^2.0.0"
esutils "^2.0.2"
@@ -121,9 +121,9 @@
version "7.0.0-beta.51"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.0.0-beta.51.tgz#27cec2df409df60af58270ed8f6aa55409ea86f6"
-"@babel/parser@7.0.0-rc.2":
- version "7.0.0-rc.2"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.0.0-rc.2.tgz#a98c01af5834e71d48a5108e3aeeee333cdf26c4"
+"@babel/parser@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.0.0.tgz#697655183394facffb063437ddf52c0277698775"
"@babel/template@7.0.0-beta.51":
version "7.0.0-beta.51"
@@ -134,13 +134,13 @@
"@babel/types" "7.0.0-beta.51"
lodash "^4.17.5"
-"@babel/template@7.0.0-rc.2":
- version "7.0.0-rc.2"
- resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-rc.2.tgz#53f6be6c1336ddc7744625c9bdca9d10be5d5d72"
+"@babel/template@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0.tgz#c2bc9870405959c89a9c814376a2ecb247838c80"
dependencies:
- "@babel/code-frame" "7.0.0-rc.2"
- "@babel/parser" "7.0.0-rc.2"
- "@babel/types" "7.0.0-rc.2"
+ "@babel/code-frame" "^7.0.0"
+ "@babel/parser" "^7.0.0"
+ "@babel/types" "^7.0.0"
"@babel/traverse@7.0.0-beta.51":
version "7.0.0-beta.51"
@@ -157,16 +157,16 @@
invariant "^2.2.0"
lodash "^4.17.5"
-"@babel/traverse@7.0.0-rc.2":
- version "7.0.0-rc.2"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-rc.2.tgz#6e54ebe82aa1b3b3cf5ec05594bc14d7c59c9766"
- dependencies:
- "@babel/code-frame" "7.0.0-rc.2"
- "@babel/generator" "7.0.0-rc.2"
- "@babel/helper-function-name" "7.0.0-rc.2"
- "@babel/helper-split-export-declaration" "7.0.0-rc.2"
- "@babel/parser" "7.0.0-rc.2"
- "@babel/types" "7.0.0-rc.2"
+"@babel/traverse@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0.tgz#b1fe9b6567fdf3ab542cfad6f3b31f854d799a61"
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ "@babel/generator" "^7.0.0"
+ "@babel/helper-function-name" "^7.0.0"
+ "@babel/helper-split-export-declaration" "^7.0.0"
+ "@babel/parser" "^7.0.0"
+ "@babel/types" "^7.0.0"
debug "^3.1.0"
globals "^11.1.0"
lodash "^4.17.10"
@@ -179,9 +179,9 @@
lodash "^4.17.5"
to-fast-properties "^2.0.0"
-"@babel/types@7.0.0-rc.2":
- version "7.0.0-rc.2"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-rc.2.tgz#8e025b78764cee8751823e308558a3ca144ebd9d"
+"@babel/types@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0.tgz#6e191793d3c854d19c6749989e3bc55f0e962118"
dependencies:
esutils "^2.0.2"
lodash "^4.17.10"
@@ -230,8 +230,8 @@
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.5.tgz#8a4accfc403c124a0bafe8a9fc61a05ec1032073"
"@types/node@*", "@types/node@^10.5.5":
- version "10.9.1"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.1.tgz#06f002136fbcf51e730995149050bb3c45ee54e6"
+ version "10.9.3"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.3.tgz#85f288502503ade0b3bfc049fe1777b05d0327d5"
"@types/shelljs@0.7.8":
version "0.7.8"
@@ -412,6 +412,10 @@ add-stream@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa"
+ajv-errors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.0.tgz#ecf021fa108fd17dfb5e6b383f2dd233e31ffc59"
+
ajv-keywords@^3.1.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a"
@@ -437,6 +441,10 @@ amdefine@>=0.0.4:
version "1.0.1"
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
+ansi-colors@^3.0.0:
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.0.5.tgz#cb9dc64993b64fd6945485f797fc3853137d9a7b"
+
ansi-escapes@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30"
@@ -470,11 +478,11 @@ anymatch@^2.0.0:
micromatch "^3.1.4"
normalize-path "^2.1.1"
-append-transform@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991"
+append-transform@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab"
dependencies:
- default-require-extensions "^1.0.0"
+ default-require-extensions "^2.0.0"
aproba@^1.0.3, aproba@^1.1.1:
version "1.2.0"
@@ -525,13 +533,6 @@ array-ify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
-array-includes@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d"
- dependencies:
- define-properties "^1.1.2"
- es-abstract "^1.7.0"
-
array-union@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
@@ -1040,7 +1041,7 @@ center-align@^0.1.1:
chalk@^1.1.3:
version "1.1.3"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+ resolved "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
dependencies:
ansi-styles "^2.2.1"
escape-string-regexp "^1.0.2"
@@ -1048,7 +1049,7 @@ chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
-chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1:
+chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
dependencies:
@@ -1170,14 +1171,14 @@ collection-visit@^1.0.0:
object-visit "^1.0.0"
color-convert@^1.9.0:
- version "1.9.2"
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147"
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
dependencies:
- color-name "1.1.1"
+ color-name "1.1.3"
-color-name@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689"
+color-name@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
columnify@^1.5.4:
version "1.5.4"
@@ -1504,7 +1505,7 @@ cross-spawn@^5.0.1:
shebang-command "^1.2.0"
which "^1.2.9"
-cross-spawn@^6.0.5:
+cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
dependencies:
@@ -1540,12 +1541,6 @@ cyclist@~0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
-d@1:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f"
- dependencies:
- es5-ext "^0.10.9"
-
dargs@^4.0.1:
version "4.1.0"
resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17"
@@ -1609,12 +1604,25 @@ deep-extend@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
+default-gateway@^2.6.0:
+ version "2.7.2"
+ resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-2.7.2.tgz#b7ef339e5e024b045467af403d50348db4642d0f"
+ dependencies:
+ execa "^0.10.0"
+ ip-regex "^2.1.0"
+
default-require-extensions@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8"
dependencies:
strip-bom "^2.0.0"
+default-require-extensions@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7"
+ dependencies:
+ strip-bom "^3.0.0"
+
defaults@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
@@ -1798,7 +1806,7 @@ error-ex@^1.2.0, error-ex@^1.3.1:
dependencies:
is-arrayish "^0.2.1"
-es-abstract@^1.5.1, es-abstract@^1.7.0:
+es-abstract@^1.5.1:
version "1.12.0"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165"
dependencies:
@@ -1816,29 +1824,6 @@ es-to-primitive@^1.1.1:
is-date-object "^1.0.1"
is-symbol "^1.0.1"
-es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14:
- version "0.10.46"
- resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.46.tgz#efd99f67c5a7ec789baa3daa7f79870388f7f572"
- dependencies:
- es6-iterator "~2.0.3"
- es6-symbol "~3.1.1"
- next-tick "1"
-
-es6-iterator@~2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
- dependencies:
- d "1"
- es5-ext "^0.10.35"
- es6-symbol "^3.1.1"
-
-es6-symbol@^3.1.1, es6-symbol@~3.1.1:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77"
- dependencies:
- d "1"
- es5-ext "~0.10.14"
-
escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
@@ -1897,6 +1882,18 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
md5.js "^1.3.4"
safe-buffer "^5.1.1"
+execa@^0.10.0:
+ version "0.10.0"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50"
+ dependencies:
+ cross-spawn "^6.0.0"
+ get-stream "^3.0.0"
+ is-stream "^1.1.0"
+ npm-run-path "^2.0.0"
+ p-finally "^1.0.0"
+ signal-exit "^3.0.0"
+ strip-eof "^1.0.0"
+
execa@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
@@ -2267,7 +2264,7 @@ glob-parent@^3.1.0:
is-glob "^3.1.0"
path-dirname "^1.0.0"
-glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2:
+glob@7.1.2:
version "7.1.2"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
dependencies:
@@ -2278,6 +2275,17 @@ glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glo
once "^1.3.0"
path-is-absolute "^1.0.0"
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2:
+ version "7.1.3"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
global-modules-path@^2.1.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/global-modules-path/-/global-modules-path-2.3.0.tgz#b0e2bac6beac39745f7db5c59d26a36a0b94f7dc"
@@ -2348,10 +2356,6 @@ has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
-has-symbols@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44"
-
has-unicode@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
@@ -2588,11 +2592,12 @@ inquirer@^6.0.0:
strip-ansi "^4.0.0"
through "^2.3.6"
-internal-ip@1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-1.2.0.tgz#ae9fbf93b984878785d50a8de1b356956058cf5c"
+internal-ip@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-3.0.1.tgz#df5c99876e1d2eb2ea2d74f520e3f669a00ece27"
dependencies:
- meow "^3.3.0"
+ default-gateway "^2.6.0"
+ ipaddr.js "^1.5.2"
interpret@^1.0.0, interpret@^1.1.0:
version "1.1.0"
@@ -2608,6 +2613,10 @@ invert-kv@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
+ip-regex@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
+
ip@^1.1.0, ip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
@@ -2616,6 +2625,10 @@ ipaddr.js@1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e"
+ipaddr.js@^1.5.2:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.1.tgz#fa4b79fa47fd3def5e3b159825161c0a519c9427"
+
is-accessor-descriptor@^0.1.6:
version "0.1.6"
resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
@@ -2834,7 +2847,7 @@ isobject@^3.0.0, isobject@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
-istanbul-lib-coverage@^1.1.2, istanbul-lib-coverage@^1.2.0:
+istanbul-lib-coverage@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz#f7d8f2e42b97e37fe796114cb0f9d68b5e3a4341"
@@ -2843,10 +2856,10 @@ istanbul-lib-coverage@^2.0.1:
resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#2aee0e073ad8c5f6a0b00e0dfbf52b4667472eda"
istanbul-lib-hook@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz#8538d970372cb3716d53e55523dd54b557a8d89b"
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.1.tgz#f614ec45287b2a8fc4f07f5660af787575601805"
dependencies:
- append-transform "^0.4.0"
+ append-transform "^1.0.0"
istanbul-lib-instrument@^2.1.0:
version "2.3.2"
@@ -2861,10 +2874,10 @@ istanbul-lib-instrument@^2.1.0:
semver "^5.5.0"
istanbul-lib-report@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.3.tgz#2df12188c0fa77990c0d2176d2d0ba3394188259"
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz#e886cdf505c4ebbd8e099e4396a90d0a28e2acb5"
dependencies:
- istanbul-lib-coverage "^1.1.2"
+ istanbul-lib-coverage "^1.2.0"
mkdirp "^0.5.1"
path-parse "^1.0.5"
supports-color "^3.1.2"
@@ -3099,23 +3112,10 @@ lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.3.0:
version "4.17.10"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
-log-symbols@^2.1.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
- dependencies:
- chalk "^2.0.1"
-
loglevel@^1.4.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa"
-loglevelnext@^1.0.1:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/loglevelnext/-/loglevelnext-1.0.5.tgz#36fc4f5996d6640f539ff203ba819641680d75a2"
- dependencies:
- es6-symbol "^3.1.1"
- object.assign "^4.1.0"
-
long@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
@@ -3286,25 +3286,21 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
-"mime-db@>= 1.34.0 < 2":
+"mime-db@>= 1.34.0 < 2", mime-db@~1.36.0:
version "1.36.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397"
-mime-db@~1.35.0:
- version "1.35.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47"
-
mime-types@~2.1.17, mime-types@~2.1.18:
- version "2.1.19"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.19.tgz#71e464537a7ef81c15f2db9d97e913fc0ff606f0"
+ version "2.1.20"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19"
dependencies:
- mime-db "~1.35.0"
+ mime-db "~1.36.0"
mime@1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
-mime@^2.1.0:
+mime@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369"
@@ -3386,7 +3382,7 @@ mixin-deep@^1.2.0:
mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0:
version "0.5.1"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+ resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
dependencies:
minimist "0.0.8"
@@ -3445,8 +3441,8 @@ mute-stream@0.0.7:
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
nan@^2.9.2:
- version "2.10.0"
- resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
+ version "2.11.0"
+ resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.0.tgz#574e360e4d954ab16966ec102c0c049fd961a099"
nanomatch@^1.2.9:
version "1.2.13"
@@ -3480,13 +3476,9 @@ neo-async@^2.5.0:
version "2.5.2"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.2.tgz#489105ce7bc54e709d736b195f82135048c50fcc"
-next-tick@1:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
-
nice-try@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4"
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
node-forge@0.7.5:
version "0.7.5"
@@ -3631,7 +3623,7 @@ object-copy@^0.1.0:
define-property "^0.2.5"
kind-of "^3.0.3"
-object-keys@^1.0.11, object-keys@^1.0.12:
+object-keys@^1.0.12:
version "1.0.12"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2"
@@ -3641,15 +3633,6 @@ object-visit@^1.0.0:
dependencies:
isobject "^3.0.0"
-object.assign@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
- dependencies:
- define-properties "^1.1.2"
- function-bind "^1.1.1"
- has-symbols "^1.0.0"
- object-keys "^1.0.11"
-
object.getownpropertydescriptors@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
@@ -4333,6 +4316,14 @@ schema-utils@^0.4.4, schema-utils@^0.4.5:
ajv "^6.1.0"
ajv-keywords "^3.1.0"
+schema-utils@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
+ dependencies:
+ ajv "^6.1.0"
+ ajv-errors "^1.0.0"
+ ajv-keywords "^3.1.0"
+
select-hose@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
@@ -4807,13 +4798,12 @@ tempfile@^1.1.1:
uuid "^2.0.1"
test-exclude@^4.2.0:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.1.tgz#dfa222f03480bca69207ca728b37d74b45f724fa"
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.2.tgz#8b67aa8408f84afc225b06669e25c510f8582820"
dependencies:
arrify "^1.0.1"
- micromatch "^3.1.8"
- object-assign "^4.1.0"
- read-pkg-up "^1.0.1"
+ minimatch "^3.0.4"
+ read-pkg-up "^3.0.0"
require-main-filename "^1.0.1"
text-extensions@^1.0.0:
@@ -4977,7 +4967,7 @@ typedoc@^0.11.1:
typescript@2.7.2:
version "2.7.2"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836"
+ resolved "http://registry.npmjs.org/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836"
typescript@^3.0.1:
version "3.0.1"
@@ -5129,7 +5119,7 @@ uuid@^2.0.1:
version "2.0.3"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
-uuid@^3.0.1, uuid@^3.1.0:
+uuid@^3.0.1, uuid@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
@@ -5190,24 +5180,23 @@ webpack-cli@^3.1.0:
v8-compile-cache "^2.0.0"
yargs "^12.0.1"
-webpack-dev-middleware@3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.1.3.tgz#8b32aa43da9ae79368c1bf1183f2b6cf5e1f39ed"
+webpack-dev-middleware@3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.2.0.tgz#a20ceef194873710052da678f3c6ee0aeed92552"
dependencies:
loud-rejection "^1.6.0"
memory-fs "~0.4.1"
- mime "^2.1.0"
+ mime "^2.3.1"
path-is-absolute "^1.0.0"
range-parser "^1.0.3"
url-join "^4.0.0"
- webpack-log "^1.0.1"
+ webpack-log "^2.0.0"
webpack-dev-server@^3.1.5:
- version "3.1.5"
- resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.5.tgz#87477252e1ac6789303fb8cd3e585fa5d508a401"
+ version "3.1.7"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.7.tgz#cbf8071cc092d9493732aee4f062f0e065994854"
dependencies:
ansi-html "0.0.7"
- array-includes "^3.0.3"
bonjour "^3.5.0"
chokidar "^2.0.0"
compression "^1.5.2"
@@ -5218,12 +5207,13 @@ webpack-dev-server@^3.1.5:
html-entities "^1.2.0"
http-proxy-middleware "~0.18.0"
import-local "^1.0.0"
- internal-ip "1.2.0"
+ internal-ip "^3.0.1"
ip "^1.1.5"
killable "^1.0.0"
loglevel "^1.4.1"
opn "^5.1.0"
portfinder "^1.0.9"
+ schema-utils "^1.0.0"
selfsigned "^1.9.1"
serve-index "^1.7.2"
sockjs "0.3.19"
@@ -5231,22 +5221,20 @@ webpack-dev-server@^3.1.5:
spdy "^3.4.1"
strip-ansi "^3.0.0"
supports-color "^5.1.0"
- webpack-dev-middleware "3.1.3"
- webpack-log "^1.1.2"
- yargs "11.0.0"
+ webpack-dev-middleware "3.2.0"
+ webpack-log "^2.0.0"
+ yargs "12.0.1"
-webpack-log@^1.0.1, webpack-log@^1.1.2:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-1.2.0.tgz#a4b34cda6b22b518dbb0ab32e567962d5c72a43d"
+webpack-log@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f"
dependencies:
- chalk "^2.1.0"
- log-symbols "^2.1.0"
- loglevelnext "^1.0.1"
- uuid "^3.1.0"
+ ansi-colors "^3.0.0"
+ uuid "^3.3.2"
webpack-sources@^1.0.1, webpack-sources@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.1.0.tgz#a101ebae59d6507354d71d8013950a3a8b7a5a54"
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.2.0.tgz#18181e0d013fce096faf6f8e6d41eeffffdceac2"
dependencies:
source-list-map "^2.0.0"
source-map "~0.6.1"
@@ -5419,23 +5407,6 @@ yargs-parser@^9.0.2:
dependencies:
camelcase "^4.1.0"
-yargs@11.0.0:
- version "11.0.0"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.0.0.tgz#c052931006c5eee74610e5fc0354bedfd08a201b"
- dependencies:
- cliui "^4.0.0"
- decamelize "^1.1.1"
- find-up "^2.1.0"
- get-caller-file "^1.0.1"
- os-locale "^2.0.0"
- require-directory "^2.1.1"
- require-main-filename "^1.0.1"
- set-blocking "^2.0.0"
- string-width "^2.0.0"
- which-module "^2.0.0"
- y18n "^3.2.1"
- yargs-parser "^9.0.2"
-
yargs@11.1.0:
version "11.1.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77"
@@ -5453,7 +5424,7 @@ yargs@11.1.0:
y18n "^3.2.1"
yargs-parser "^9.0.2"
-yargs@^12.0.1:
+yargs@12.0.1, yargs@^12.0.1:
version "12.0.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.1.tgz#6432e56123bb4e7c3562115401e98374060261c2"
dependencies: