diff --git a/assets/deps.png b/assets/deps.png
index 262ed61ea1..49167257a4 100644
Binary files a/assets/deps.png and b/assets/deps.png differ
diff --git a/examples/README.md b/examples/README.md
index 5473fbece5..36644f3e44 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -18,7 +18,8 @@ If you want to [contribute](../CONTRIBUTING.md) an example, please get in touch
| 10 | [pointfree-svg](./pointfree-svg) | generate SVG using pointfree DSL | hiccup, hdom-components, pointfree-lang | intermediate |
| 11 | [router-basics](./router-basics) | complete mini SPA | atom, hdom, interceptors, router | advanced |
| 12 | [rstream-dataflow](./rstream-dataflow) | dataflow graph | atom, hdom, rstream, rstream-gestures, rstream-graph, transducers | intermediate |
-| 13 | [svg-particles](./svg-particles) | hdom SVG generation / animation | hdom, transducers | basic |
-| 13 | [svg-waveform](./svg-waveform) | hdom SVG generation / undo history | atom, hdom, hiccup-svg, interceptors, iterators | intermediate |
-| 14 | [todo-list](./todo-list) | Canonical Todo list with undo/redo | atom, hdom, transducers | intermediate |
-| 15 | [webgl](./webgl) | Canvas component handling | hdom, hdom-components | basic |
+| 13 | [rstream-grid](./rstream-grid) | dataflow graph svg gen | atom, hdom, hiccup-svg, interceptors, rstream-graph, transducers | advanced |
+| 14 | [svg-particles](./svg-particles) | hdom SVG generation / animation | hdom, transducers | basic |
+| 15 | [svg-waveform](./svg-waveform) | hdom SVG generation / undo history | atom, hdom, hiccup-svg, interceptors, iterators | intermediate |
+| 16 | [todo-list](./todo-list) | Canonical Todo list with undo/redo | atom, hdom, transducers | intermediate |
+| 17 | [webgl](./webgl) | Canvas component handling | hdom, hdom-components | basic |
diff --git a/examples/rstream-grid/README.md b/examples/rstream-grid/README.md
new file mode 100644
index 0000000000..6468ec8eee
--- /dev/null
+++ b/examples/rstream-grid/README.md
@@ -0,0 +1,49 @@
+# rstream-grid
+
+## About
+
+[Live demo](http://demo.thi.ng/umbrella/rstream-grid/)
+
+Interactive SVG grid pattern creator with undo, local file download and
+implemented as rstream dataflow graph, combined with interceptor event &
+side effect handling.
+
+- [@thi.ng/atom](https://github.com/thi-ng/umbrella/tree/master/packages/atom)
+- [@thi.ng/interceptors](https://github.com/thi-ng/umbrella/tree/master/packages/interceptors)
+- [@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/master/packages/hdom)
+- [@thi.ng/hiccup-svg](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup-svg)
+- [@thi.ng/rstream-graph](https://github.com/thi-ng/umbrella/tree/master/packages/rstream-graph)
+- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers)
+
+## Building
+
+This example is based on the
+[create-hdom-app](https://github.com/thi-ng/create-hdom-app) project
+template.
+
+### Development
+
+```
+git clone https://github.com/thi-ng/umbrella/
+cd umbrella/examples/rstream-grid
+yarn install
+yarn start
+```
+
+Installs all dependencies, runs `webpack-dev-server` and opens the app
+in your browser.
+
+### Production
+
+```
+yarn build
+```
+
+Builds a minified version of the app and places it in `/public`
+directory.
+
+## Authors
+
+- Karsten Schmidt
+
+© 2018
\ No newline at end of file
diff --git a/examples/rstream-grid/index.html b/examples/rstream-grid/index.html
new file mode 100644
index 0000000000..cf6fed151f
--- /dev/null
+++ b/examples/rstream-grid/index.html
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+ svg-grid
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/rstream-grid/package.json b/examples/rstream-grid/package.json
new file mode 100644
index 0000000000..8eaf075684
--- /dev/null
+++ b/examples/rstream-grid/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "rstream-grid",
+ "version": "0.0.1",
+ "description": "TODO",
+ "repository": "https://github.com/[your-gh-username]/rs-undo",
+ "author": "TODO",
+ "license": "MIT",
+ "scripts": {
+ "build": "webpack --mode production --display-reasons --display-modules",
+ "start": "webpack-dev-server --open --mode development --devtool inline-source-map"
+ },
+ "dependencies": {
+ "@thi.ng/atom": "latest",
+ "@thi.ng/hdom": "latest",
+ "@thi.ng/hiccup-svg": "latest",
+ "@thi.ng/interceptors": "latest",
+ "@thi.ng/rstream-graph": "latest",
+ "@thi.ng/transducers": "latest"
+ },
+ "devDependencies": {
+ "@types/node": "^9.6.2",
+ "typescript": "^2.8.1",
+ "ts-loader": "^4.2.0",
+ "webpack": "^4.5.0",
+ "webpack-cli": "^2.0.14",
+ "webpack-dev-server": "^3.1.3"
+ }
+}
\ No newline at end of file
diff --git a/examples/rstream-grid/src/api.ts b/examples/rstream-grid/src/api.ts
new file mode 100644
index 0000000000..6f788867c0
--- /dev/null
+++ b/examples/rstream-grid/src/api.ts
@@ -0,0 +1,67 @@
+import { IObjectOf } from "@thi.ng/api/api";
+import { IView, ViewTransform } from "@thi.ng/atom/api";
+import { EffectDef, EventDef } from "@thi.ng/interceptors/api";
+import { EventBus } from "@thi.ng/interceptors/event-bus";
+
+/**
+ * Function signature for main app components.
+ * I.e. components representing different app states linked to router.
+ */
+export type AppComponent = (ctx: AppContext, ...args: any[]) => any;
+
+/**
+ * Derived view configurations.
+ */
+export type ViewSpec = string | [string, ViewTransform];
+
+/**
+ * Structure of the overall application config object.
+ * See `src/config.ts`.
+ */
+export interface AppConfig {
+ rootComponent: AppComponent;
+ domRoot: string | Element;
+ effects: IObjectOf;
+ events: IObjectOf;
+ initialState: any;
+ ui: UIAttribs;
+ views: Partial>;
+}
+
+/**
+ * Base structure of derived views exposed by the base app.
+ * Add more declarations here as needed.
+ */
+export interface AppViews extends Record> {
+ svg: IView;
+ cols: IView;
+ rows: IView;
+ theta: IView;
+ stroke: IView;
+}
+
+/**
+ * Helper interface to pre-declare keys of shared UI attributes for
+ * components and so enable autocomplete & type safety.
+ *
+ * See `AppConfig` above and its use in `src/config.ts` and various
+ * component functions.
+ */
+export interface UIAttribs {
+ button: any;
+ buttongroup: any;
+ footer: any;
+ link: any;
+ root: any;
+ slider: { root: any, range: any, label: any, number: any };
+ sidebar: any;
+}
+
+/**
+ * Structure of the context object passed to all component functions
+ */
+export interface AppContext {
+ bus: EventBus;
+ views: AppViews;
+ ui: UIAttribs;
+}
diff --git a/examples/rstream-grid/src/app.ts b/examples/rstream-grid/src/app.ts
new file mode 100644
index 0000000000..b042e6d88e
--- /dev/null
+++ b/examples/rstream-grid/src/app.ts
@@ -0,0 +1,118 @@
+import { IObjectOf } from "@thi.ng/api/api";
+import { Atom } from "@thi.ng/atom/atom";
+import { Cursor } from "@thi.ng/atom/cursor";
+import { History } from "@thi.ng/atom/history";
+import { isArray } from "@thi.ng/checks/is-array";
+import { start } from "@thi.ng/hdom/start";
+import { EventBus } from "@thi.ng/interceptors/event-bus";
+
+import {
+ AppConfig,
+ AppContext,
+ AppViews,
+ ViewSpec
+} from "./api";
+import { initDataflow } from "./dataflow";
+import * as ev from "./events";
+import { PARAM_BASE } from "./paths";
+
+/**
+ * The app does not much more than:
+ *
+ * - initialize state, undo history, event bus, dataflow graph
+ * - attach derived views
+ * - start hdom render & event bus loop
+ */
+export class App {
+
+ config: AppConfig;
+ ctx: AppContext;
+ state: Atom;
+ history: History;
+
+ constructor(config: AppConfig) {
+ this.config = config;
+ this.state = new Atom(config.initialState || {});
+ // note: the undo history only records the `PARAM_BASE` branch
+ // in the app state atom. this is so we don't include the generated
+ // SVG in the history and therefore save a lot of RAM
+ // furthermore, the param changes trigger updates in the dataflow graph
+ // (see `init()` method below) and will regenerate the SVG anyway
+ this.history = new History(new Cursor(this.state, PARAM_BASE), 1000);
+ // define context object passed to all UI component functions
+ this.ctx = {
+ bus: new EventBus(this.state, config.events, config.effects),
+ views: {},
+ ui: config.ui,
+ };
+ // initialize derived views
+ this.addViews(this.config.views);
+ }
+
+ /**
+ * Initializes given derived view specs and attaches them to app
+ * state atom.
+ *
+ * @param specs
+ */
+ addViews(specs: IObjectOf) {
+ const views = this.ctx.views;
+ for (let id in specs) {
+ const spec = specs[id];
+ if (isArray(spec)) {
+ views[id] = this.state.addView(spec[0], spec[1]);
+ } else {
+ views[id] = this.state.addView(spec);
+ }
+ }
+ }
+
+ /**
+ * Calls `init()` and kicks off hdom render loop, including batched
+ * event processing and fast fail check if DOM updates are necessary
+ * (assumes ALL state is held in the app state atom). So if there
+ * weren't any events causing a state change since last frame,
+ * re-rendering is skipped without even attempting to diff DOM
+ * tree).
+ */
+ start() {
+ this.init();
+ // assume main root component is a higher order function
+ // call it here to pre-initialize
+ 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
+ );
+ }
+
+ /**
+ * User initialization hook.
+ * Automatically called from `start()`
+ */
+ init() {
+ // initialize dataflow graph
+ initDataflow(this.ctx.bus);
+
+ // initialize key event handlers for undo/redo
+ document.addEventListener("keypress", (e) => {
+ if (e.ctrlKey) {
+ if (e.key === "z") {
+ this.ctx.bus.dispatch([ev.UNDO]);
+ } else if (e.key === "y") {
+ this.ctx.bus.dispatch([ev.REDO]);
+ }
+ }
+ });
+
+ // record snapshot of initial state
+ this.history.record();
+ }
+}
diff --git a/examples/rstream-grid/src/components/button-group.ts b/examples/rstream-grid/src/components/button-group.ts
new file mode 100644
index 0000000000..acc7cab85a
--- /dev/null
+++ b/examples/rstream-grid/src/components/button-group.ts
@@ -0,0 +1,5 @@
+import { AppContext } from "../api";
+import { button } from "./button";
+
+export const buttonGroup = (ctx: AppContext, ...buttons) =>
+ ["section", ctx.ui.buttongroup, buttons.map((bt) => [button, ...bt])];
diff --git a/examples/rstream-grid/src/components/button.ts b/examples/rstream-grid/src/components/button.ts
new file mode 100644
index 0000000000..73518110e4
--- /dev/null
+++ b/examples/rstream-grid/src/components/button.ts
@@ -0,0 +1,5 @@
+import { AppContext } from "../api";
+import { eventLink } from "./event-link";
+
+export const button = (ctx: AppContext, event: Event, label: string) =>
+ [eventLink, ctx.ui.button, event, label];
diff --git a/examples/rstream-grid/src/components/event-link.ts b/examples/rstream-grid/src/components/event-link.ts
new file mode 100644
index 0000000000..ddc4c8bb7a
--- /dev/null
+++ b/examples/rstream-grid/src/components/event-link.ts
@@ -0,0 +1,23 @@
+import { Event } from "@thi.ng/interceptors/api";
+
+import { AppContext } from "../api";
+
+/**
+ * Customizable hyperlink component emitting given event on event bus
+ * when clicked.
+ *
+ * @param ctx
+ * @param event event tuple of `[event-id, payload]`
+ * @param attribs element attribs
+ * @param body link body
+ */
+export const eventLink = (ctx: AppContext, attribs: any, event: Event, body: any) =>
+ ["a",
+ {
+ ...attribs,
+ onclick: (e) => {
+ e.preventDefault();
+ ctx.bus.dispatch(event);
+ }
+ },
+ body];
diff --git a/examples/rstream-grid/src/components/link.ts b/examples/rstream-grid/src/components/link.ts
new file mode 100644
index 0000000000..dd2890452c
--- /dev/null
+++ b/examples/rstream-grid/src/components/link.ts
@@ -0,0 +1,4 @@
+import { AppContext } from "../api";
+
+export const link = (ctx: AppContext, href, ...body) =>
+ ["a", { ...ctx.ui.link, href }, ...body];
diff --git a/examples/rstream-grid/src/components/main.ts b/examples/rstream-grid/src/components/main.ts
new file mode 100644
index 0000000000..8474453a0e
--- /dev/null
+++ b/examples/rstream-grid/src/components/main.ts
@@ -0,0 +1,9 @@
+import { AppContext } from "../api";
+import { sidebar } from "./sidebar";
+
+import { SLIDERS } from "../sliders";
+
+export const main = (ctx: AppContext) => {
+ const bar = sidebar(ctx, ...SLIDERS);
+ return () => ["div", ctx.ui.root, bar, ctx.views.svg];
+};
diff --git a/examples/rstream-grid/src/components/sidebar.ts b/examples/rstream-grid/src/components/sidebar.ts
new file mode 100644
index 0000000000..9256747aed
--- /dev/null
+++ b/examples/rstream-grid/src/components/sidebar.ts
@@ -0,0 +1,30 @@
+import { AppContext } from "../api";
+import * as ev from "../events";
+
+import { buttonGroup } from "./button-group";
+import { link } from "./link";
+import { slider, SliderOpts } from "./slider";
+
+export const sidebar = (ctx: AppContext, ...specs: SliderOpts[]) => {
+ const sliders = specs.map((s) => slider(ctx, s));
+ return ["div", ctx.ui.sidebar.root,
+ ["h3", ctx.ui.sidebar.title, "@thi.ng/rstream grid"],
+ ...sliders,
+ [buttonGroup,
+ [[ev.UNDO], "undo"],
+ [[ev.REDO], "redo"]],
+ [buttonGroup,
+ [[ev.SAVE_SVG], "download svg"]],
+ [buttonGroup,
+ [[ev.SAVE_ANIM], "download anim"]],
+ ["div",
+ "Undo / Redo can also be triggered via ",
+ ["code", "Ctrl+Z"], " / ", ["code", "Ctrl+Y"],
+ ". The last 1000 edits are stored."],
+ ["div", ctx.ui.footer,
+ [link, "https://github.com/thi-ng/umbrella/tree/master/examples/rstream-grid", "Source"],
+ ["br"],
+ "Made with ",
+ [link, "https://github.com/thi-ng/umbrella/", "@thi.ng/umbrella"]]
+ ];
+};
diff --git a/examples/rstream-grid/src/components/slider.ts b/examples/rstream-grid/src/components/slider.ts
new file mode 100644
index 0000000000..9aa50cd633
--- /dev/null
+++ b/examples/rstream-grid/src/components/slider.ts
@@ -0,0 +1,50 @@
+import { AppContext } from "../api";
+
+export interface SliderOpts {
+ event: PropertyKey;
+ view: PropertyKey;
+ label: string;
+ min?: number;
+ max?: number;
+ step?: number;
+}
+
+/**
+ * Higher-order slider component using both an HTML5 range and number
+ * control connected to the same derived view of an app state value.
+ * Changes as dispatched via event configured via `opts` object.
+ *
+ * Because it's an higher order component, it CANNOT be used in an
+ * inline manner in the parent component and must be initialized
+ * separately.
+ *
+ * See `main.ts` for usage.
+ *
+ * @param ctx
+ * @param opts
+ */
+export const slider = (ctx: AppContext, opts: SliderOpts) => {
+ opts = Object.assign({
+ oninput: (e) => ctx.bus.dispatch([opts.event, parseFloat(e.target.value)]),
+ min: 0,
+ max: 100,
+ step: 1,
+ }, opts);
+ const ui = ctx.ui.slider;
+ return () =>
+ ["section", ui.root,
+ ["input",
+ {
+ ...ui.range,
+ ...opts,
+ type: "range",
+ value: ctx.views[opts.view].deref(),
+ }],
+ ["div", ui.label, opts.label,
+ ["input", {
+ ...ui.number,
+ ...opts,
+ type: "number",
+ value: ctx.views[opts.view].deref(),
+ }]]];
+};
diff --git a/examples/rstream-grid/src/config.ts b/examples/rstream-grid/src/config.ts
new file mode 100644
index 0000000000..5b08bd848b
--- /dev/null
+++ b/examples/rstream-grid/src/config.ts
@@ -0,0 +1,118 @@
+import { serialize } from "@thi.ng/hiccup/serialize";
+import { snapshot, valueSetter } from "@thi.ng/interceptors/interceptors";
+import { getIn } from "@thi.ng/paths";
+import { fromIterable } from "@thi.ng/rstream/from/iterable";
+import { range } from "@thi.ng/transducers/iter/range";
+
+import { AppConfig } from "./api";
+import { main } from "./components/main";
+import { download } from "./download";
+import * as fx from "./effects";
+import * as ev from "./events";
+import * as paths from "./paths";
+import { SLIDERS } from "./sliders";
+
+const FG_COL = "light-silver";
+const LINK_COL = "white";
+
+// main App configuration
+export const CONFIG: AppConfig = {
+
+ // event handlers events are queued and batch processed in app's RAF
+ // render loop event handlers can be single functions, interceptor
+ // objects with `pre`/`post` keys or arrays of either.
+
+ // the event handlers' only task is to transform the event into a
+ // number of side effects. event handlers should be pure functions
+ // and only side effect functions execute any "real" work.
+
+ // Docs here:
+ // https://github.com/thi-ng/umbrella/blob/master/packages/interceptors/src/event-bus.ts#L14
+ events: {
+ // generate slider event handlers. each uses the `snapshot()`
+ // interceptor to record a snapshot of the current app state
+ // before applying new slider value
+ ...SLIDERS.reduce(
+ (events, spec) =>
+ (events[spec.event] = [
+ snapshot(),
+ valueSetter(spec.path)
+ ], events),
+ {}),
+ [ev.UPDATE_SVG]: [valueSetter(paths.SVG)],
+ [ev.SAVE_SVG]: (state) => ({ [fx.SAVE_SVG]: getIn(state, paths.SVG) }),
+ [ev.SAVE_ANIM]: () => ({ [fx.SAVE_ANIM]: true })
+ },
+
+ // custom side effects
+ effects: {
+ // prepares given hiccup format SVG doc with bounds
+ // then uses @thi.ng/hiccup to serialize to XML syntax
+ // finally triggers download to local disk
+ [fx.SAVE_SVG]: (src) => {
+ src = src.slice();
+ src[1] = { ...src[1], width: 1000, height: 1000 };
+ download(`grid-${Date.now()}.svg`, serialize(src));
+ },
+ // triggers download of 18 svg files (each delayed by 1sec),
+ // each with a different rotation in the 0-90 degrees interval
+ [fx.SAVE_ANIM]: (_, bus) =>
+ fromIterable(range(0, 90, 5), 1000)
+ .subscribe({
+ next: (x) => {
+ bus.dispatch([ev.SET_THETA, x]);
+ bus.dispatchLater([ev.SAVE_SVG]);
+ }
+ })
+ },
+
+ rootComponent: main,
+
+ // DOM root element (or ID)
+ domRoot: "app",
+
+ // initial app state
+ initialState: {
+ [paths.PARAM_BASE]: {
+ cols: 5,
+ rows: 5,
+ theta: 35,
+ stroke: 0.3,
+ }
+ },
+
+ // derived view declarations
+ // each key specifies the name of the view and each value is
+ // a state path or `[path, transformer]` tuple
+
+ // docs here:
+ // https://github.com/thi-ng/umbrella/tree/master/packages/atom#derived-views
+ views: {
+ cols: paths.COLS,
+ rows: paths.ROWS,
+ stroke: paths.STROKE,
+ theta: paths.THETA,
+ svg: paths.SVG,
+ },
+
+ // component CSS class config using http://tachyons.io/
+ // these attribs are being passed to all component functions
+ // as part of the AppContext object
+ ui: {
+ button: { class: `pointer bg-${FG_COL} hover-bg-${LINK_COL} bg-animate black pa2 mr1 w-100 ttu b tracked-tight` },
+ buttongroup: { class: "flex mb1" },
+ footer: { class: "absolute bottom-1" },
+ link: { class: `pointer link dim ${LINK_COL} b` },
+ root: { class: "vw-100 vh-100 flex" },
+ sidebar: {
+ root: { class: `bg-near-black pa2 pt3 w5 f7 ${FG_COL}` },
+ title: { class: `mt0 ${FG_COL}` },
+ },
+ slider: {
+ root: { class: `mb3 ttu b tracked-tight ${FG_COL}` },
+ range: { class: "w-100" },
+ label: { class: "pl2" },
+ number: { class: `fr w3 tr ttu bn bg-transparent ${FG_COL}` },
+ },
+ }
+};
diff --git a/examples/rstream-grid/src/dataflow.ts b/examples/rstream-grid/src/dataflow.ts
new file mode 100644
index 0000000000..ca47c6df4f
--- /dev/null
+++ b/examples/rstream-grid/src/dataflow.ts
@@ -0,0 +1,99 @@
+import { svgdoc } from "@thi.ng/hiccup-svg/doc";
+import { group } from "@thi.ng/hiccup-svg/group";
+import { rect } from "@thi.ng/hiccup-svg/rect";
+import { EventBus } from "@thi.ng/interceptors/event-bus";
+import { initGraph, node } from "@thi.ng/rstream-graph/graph";
+import { range2d } from "@thi.ng/transducers/iter/range2d";
+import { iterator } from "@thi.ng/transducers/iterator";
+import { map } from "@thi.ng/transducers/xform/map";
+
+import * as ev from "./events";
+import * as paths from "./paths";
+
+/**
+ * Initializes data flow graph for generating SVG grid. Some of the
+ * nodes are using subscriptions to value changes in certain
+ * paths/locations in the app state atom. The final node (`svg`) in the
+ * graph triggers the `UPDATE_SVG` event each time a new value has been
+ * produced. In turn, this event will update the app state and so
+ * trigger a DOM update to display the new result.
+ *
+ * @param bus
+ */
+export function initDataflow(bus: EventBus) {
+ const graph = initGraph(bus.state, {
+ grid: {
+ fn: grid,
+ ins: {
+ cols: { path: paths.COLS },
+ rows: { path: paths.ROWS },
+ },
+ },
+ rotation: {
+ fn: rotate,
+ ins: {
+ shapes: { stream: "grid" },
+ theta: { path: paths.THETA },
+ },
+ },
+ svg: {
+ fn: createSVG,
+ ins: {
+ shapes: { stream: "rotation" },
+ cols: { path: paths.COLS },
+ rows: { path: paths.ROWS },
+ stroke: { path: paths.STROKE },
+ },
+ // dispatch SVG result doc as event
+ out: (node) => node.subscribe({
+ next: (svg) => bus.dispatch([ev.UPDATE_SVG, svg])
+ })
+ }
+ });
+ return graph;
+};
+
+/**
+ * Implementation for grid generator node.
+ */
+const grid = node(map(
+ ({ cols, rows }) =>
+ [...iterator(
+ map(([x, y]) => ["rect", { x, y, width: 1, height: 1 }]),
+ range2d(cols, rows)
+ )]));
+
+/**
+ * Implementation for rotate node. Injects SVG `transform` attribute in
+ * all received shapes.
+ */
+const rotate = node(map(
+ ({ shapes, theta }) =>
+ [...iterator(
+ map((s) => (s[1].transform = `rotate(${theta} ${s[1].x + 0.5} ${s[1].y + 0.5})`, s)),
+ shapes)]
+));
+
+/**
+ * Implementation for svg dataflow node. Wraps received shapes as
+ * complete svg document in hiccup format.
+ */
+const createSVG = node(map(
+ ({ shapes, cols, rows, stroke }) =>
+ svgdoc(
+ {
+ class: "w-100 h-100",
+ preserveAspectRatio: "xMidYMid",
+ viewBox: `-1 -1 ${cols + 2} ${rows + 2}`
+ },
+ rect([-1, -1], cols + 2, rows + 2, { fill: "black" }),
+ group(
+ {
+ stroke: "white",
+ fill: "none",
+ "stroke-width": stroke,
+ },
+ ...shapes
+ )
+ )
+));
diff --git a/examples/rstream-grid/src/download.ts b/examples/rstream-grid/src/download.ts
new file mode 100644
index 0000000000..07169e5e89
--- /dev/null
+++ b/examples/rstream-grid/src/download.ts
@@ -0,0 +1,24 @@
+/**
+ * Helper function to trigger download of given `src` string as local
+ * file with filename `name` and mime `type`. Wraps `src` as blob and
+ * creates an object URL for download. By default, the URL auto-expires
+ * after 10 seconds to free up memory.
+ *
+ * @param name
+ * @param src
+ * @param type
+ * @param expire
+ */
+export function download(name: string, src: string, type = "image/svg", expire = 10000) {
+ const blob = new Blob([src], { type });
+ const uri = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.download = name;
+ a.href = uri;
+ document.body.appendChild(a);
+ a.click();
+ document.body.removeChild(a);
+ if (uri.indexOf("blob:") === 0) {
+ setTimeout(() => URL.revokeObjectURL(uri), expire);
+ }
+}
diff --git a/examples/rstream-grid/src/effects.ts b/examples/rstream-grid/src/effects.ts
new file mode 100644
index 0000000000..32593dd7d2
--- /dev/null
+++ b/examples/rstream-grid/src/effects.ts
@@ -0,0 +1,7 @@
+// best practice tip: define event & effect names as consts or enums
+// and avoid hardcoded strings for more safety and easier refactoring
+// also see pre-defined event handlers & interceptors in @thi.ng/atom:
+// https://github.com/thi-ng/umbrella/blob/master/packages/interceptors/src/api.ts#L14
+
+export const SAVE_SVG = "save-svg";
+export const SAVE_ANIM = "save-anim";
diff --git a/examples/rstream-grid/src/events.ts b/examples/rstream-grid/src/events.ts
new file mode 100644
index 0000000000..3868641694
--- /dev/null
+++ b/examples/rstream-grid/src/events.ts
@@ -0,0 +1,16 @@
+import { EV_UNDO, EV_REDO } from "@thi.ng/interceptors/api";
+
+// best practice tip: define event & effect names as consts or enums
+// and avoid hardcoded strings for more safety and easier refactoring
+// also see pre-defined event handlers & interceptors in @thi.ng/atom:
+// https://github.com/thi-ng/umbrella/blob/master/packages/interceptors/src/api.ts#L14
+
+export const UNDO = EV_UNDO;
+export const REDO = EV_REDO;
+export const UPDATE_SVG = "update-svg";
+export const SAVE_SVG = "save-svg";
+export const SAVE_ANIM = "save-anim";
+export const SET_COLS = "set-cols";
+export const SET_ROWS = "set-rows";
+export const SET_STROKE = "set-stroke";
+export const SET_THETA = "set-theta";
diff --git a/examples/rstream-grid/src/index.ts b/examples/rstream-grid/src/index.ts
new file mode 100644
index 0000000000..8ebcb7ec8c
--- /dev/null
+++ b/examples/rstream-grid/src/index.ts
@@ -0,0 +1,10 @@
+import { App } from "./app";
+import { CONFIG } from "./config";
+
+// export app to global var in dev mode
+// (for interaction via browser dev tools)
+if (process.env.NODE_ENV === "development") {
+ (window["APP"] = new App(CONFIG)).start();
+} else {
+ new App(CONFIG).start();
+}
diff --git a/examples/rstream-grid/src/paths.ts b/examples/rstream-grid/src/paths.ts
new file mode 100644
index 0000000000..b28b1c9fb6
--- /dev/null
+++ b/examples/rstream-grid/src/paths.ts
@@ -0,0 +1,9 @@
+// single source of truth definitions for parameter paths in central
+// app state atom
+
+export const PARAM_BASE = "params";
+export const COLS = `${PARAM_BASE}.cols`;
+export const ROWS = `${PARAM_BASE}.rows`;
+export const THETA = `${PARAM_BASE}.theta`;
+export const STROKE = `${PARAM_BASE}.stroke`;
+export const SVG = "svg";
diff --git a/examples/rstream-grid/src/sliders.ts b/examples/rstream-grid/src/sliders.ts
new file mode 100644
index 0000000000..2b7c426d80
--- /dev/null
+++ b/examples/rstream-grid/src/sliders.ts
@@ -0,0 +1,13 @@
+import * as ev from "./events";
+import * as paths from "./paths";
+
+/**
+ * Slider definitions used to generate UI components and their
+ * respective event handlers.
+ */
+export const SLIDERS = [
+ { event: ev.SET_COLS, path: paths.COLS, view: "cols", label: "cols", min: 1, max: 16 },
+ { event: ev.SET_ROWS, path: paths.ROWS, view: "rows", label: "rows", min: 1, max: 16 },
+ { event: ev.SET_THETA, path: paths.THETA, view: "theta", label: "rotate", min: 0, max: 360 },
+ { event: ev.SET_STROKE, path: paths.STROKE, view: "stroke", label: "stroke weight", min: 0.01, max: 0.5, step: 0.01 },
+];
diff --git a/examples/rstream-grid/tsconfig.json b/examples/rstream-grid/tsconfig.json
new file mode 100644
index 0000000000..acab3b01c9
--- /dev/null
+++ b/examples/rstream-grid/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "ES6",
+ "outDir": "build",
+ "experimentalDecorators": true,
+ "noUnusedParameters": true,
+ "noUnusedLocals": true,
+ "sourceMap": true,
+ },
+ "include": [
+ "./src/**/*.ts"
+ ],
+ "exclude": [
+ "./**/node_modules"
+ ]
+}
\ No newline at end of file
diff --git a/examples/rstream-grid/webpack.config.js b/examples/rstream-grid/webpack.config.js
new file mode 100644
index 0000000000..e2bf1e8d3a
--- /dev/null
+++ b/examples/rstream-grid/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/todo-list/src/index.ts b/examples/todo-list/src/index.ts
index c73db64bde..7b5767714e 100644
--- a/examples/todo-list/src/index.ts
+++ b/examples/todo-list/src/index.ts
@@ -1,14 +1,3 @@
-/*
- * Obligatory Todo list demo (in < 50 LOC excl. comments)
- * Total filesize: 18KB minified
- *
- * Other packages used:
- * - @thi.ng/atom for state handling
- * - @thi.ng/transducers for task list processing
- *
- * @author Karsten Schmidt
- */
-
import { IObjectOf } from "@thi.ng/api/api";
import { Atom, Cursor, History } from "@thi.ng/atom";
import { start } from "@thi.ng/hdom/start";
@@ -28,6 +17,11 @@ const db = new Atom({ tasks: {}, nextID: 0 });
const tasks = new History>(new Cursor(db, "tasks"), 100);
// cursor for direct access to `nextID`
const nextID = new Cursor(db, "nextID");
+// create derived view of tasks transformed into components
+const items = db.addView(
+ "tasks",
+ (tasks) => [...iterator(map(([id, t]) => taskItem(id, t)), pairs(tasks))]
+);
// state updaters
// each applies its updates via the history atom wrapper
@@ -37,43 +31,47 @@ const toggleTask = (id) => tasks.swap((tasks) => updateIn(tasks, [id, "done"], d
const updateTask = (id, body) => tasks.swap((tasks) => setIn(tasks, [id, "body"], body));
// single task component
-// the text field uses lifecycle hooks to set keyboard focus for new tasks
-const taskItem = (id, task: Task) =>
- ["div",
+const taskItem = (id, task: Task) => {
+ const checkAttribs = {
+ type: "checkbox",
+ checked: task.done,
+ onclick: () => toggleTask(id),
+ };
+ const textAttribs = {
+ type: "text",
+ placeholder: "todo...",
+ value: task.body,
+ onkeydown: (e) => e.key === "Enter" && e.target.blur(),
+ onblur: (e) => updateTask(id, (e.target).value)
+ };
+ return ["div",
{ class: "task" + (task.done ? " done" : "") },
- ["input",
- {
- type: "checkbox",
- checked: task.done,
- onclick: () => toggleTask(id),
- }],
- [{
- init: (el) => !el.value && el.focus(),
- render: () =>
- ["input",
- {
- type: "text",
- placeholder: "todo...",
- value: task.body,
- onkeydown: (e) => e.key === "Enter" && e.target.blur(),
- onblur: (e) => updateTask(id, (e.target).value)
- }]
- }]];
+ ["input", checkAttribs],
+ ["input", textAttribs]]
+};
// complete task list
// uses transducer to transform all tasks using above component function
const taskList = () => {
- const tasks = db.deref().tasks;
- return Object.keys(tasks).length ?
- ["div#tasks", ...iterator(map(([id, t]) => taskItem(id, t)), pairs(tasks))] :
+ const _items = items.deref();
+ return _items.length ?
+ ["div#tasks", _items] :
["div", "nothing todo, get busy..."];
};
-const toolbar = () =>
- ["div#toolbar",
- ["button", { onclick: () => addNewTask() }, "+ Add"],
- ["button", { onclick: () => tasks.undo(), disabled: !tasks.canUndo() }, "Undo"],
- ["button", { onclick: () => tasks.redo(), disabled: !tasks.canRedo() }, "Redo"]];
+const button = (onclick, body) =>
+ (_, disabled) => ["button", { onclick, disabled }, body];
+
+const toolbar = () => {
+ const btAdd = button(() => addNewTask(), "+ Add");
+ const btUndo = button(() => tasks.undo(), "Undo");
+ const btRedo = button(() => tasks.redo(), "Redo");
+ return () =>
+ ["div#toolbar",
+ [btAdd],
+ [btUndo, !tasks.canUndo()],
+ [btRedo, !tasks.canRedo()]];
+};
// static header component (simple array)
const header =
@@ -81,5 +79,9 @@ const header =
["small", "made with \u2764 ",
["a", { href: "https://github.com/thi-ng/umbrella/tree/master/packages/hdom" }, "@thi.ng/hdom"]]];
+const app = () => {
+ return ["div", header, toolbar(), taskList]
+};
+
// kick off UI w/ root component function
-start("app", () => ["div", header, toolbar, taskList]);
+start("app", app());
diff --git a/packages/api/CHANGELOG.md b/packages/api/CHANGELOG.md
index defd6bd200..fc2958d2e2 100644
--- a/packages/api/CHANGELOG.md
+++ b/packages/api/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.
+
+## [2.3.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/api@2.3.0...@thi.ng/api@2.3.1) (2018-04-29)
+
+
+### Performance Improvements
+
+* **api:** major speedup equivObject(), update equivSet() ([7fdf172](https://github.com/thi-ng/umbrella/commit/7fdf172))
+
+
+
+
# [2.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/api@2.2.0...@thi.ng/api@2.3.0) (2018-04-26)
diff --git a/packages/api/package.json b/packages/api/package.json
index 2c84f0cf60..8e3961f500 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/api",
- "version": "2.3.0",
+ "version": "2.3.1",
"description": "Common, generic types & interfaces for thi.ng projects",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,7 +24,7 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/checks": "^1.5.0"
+ "@thi.ng/checks": "^1.5.1"
},
"keywords": [
"compare",
diff --git a/packages/api/src/equiv.ts b/packages/api/src/equiv.ts
index 3f1f07981c..d1f31abdd4 100644
--- a/packages/api/src/equiv.ts
+++ b/packages/api/src/equiv.ts
@@ -32,8 +32,11 @@ export function equiv(a, b): boolean {
if (isArrayLike(a) && isArrayLike(b)) {
return equivArrayLike(a, b);
}
- if ((isSet(a) && isSet(b)) || (isMap(a) && isMap(b))) {
- return equivSetLike(a, b);
+ if (isSet(a) && isSet(b)) {
+ return equivSet(a, b);
+ }
+ if (isMap(a) && isMap(b)) {
+ return equivMap(a, b);
}
if (isDate(a) && isDate(b)) {
return a.getTime() === b.getTime();
@@ -53,22 +56,24 @@ function equivArrayLike(a: ArrayLike, b: ArrayLike) {
return l < 0;
}
-function equivSetLike(a: Set, b: Set) {
+function equivSet(a: Set, b: Set) {
+ if (a.size !== b.size) return false;
+ return equiv([...a.keys()].sort(), [...b.keys()].sort());
+}
+
+function equivMap(a: Map, b: Map) {
if (a.size !== b.size) return false;
return equiv([...a].sort(), [...b].sort());
}
function equivObject(a, b) {
- const keys = new Set(Object.keys(a).concat(Object.keys(b)));
- for (let k of keys) {
- if (a.hasOwnProperty(k)) {
- if (b.hasOwnProperty(k)) {
- if (equiv(a[k], b[k])) {
- continue;
- }
- }
+ const ka = Object.keys(a);
+ if (ka.length !== Object.keys(b).length) return false;
+ for (let i = ka.length, k; --i >= 0;) {
+ k = ka[i];
+ if (!b.hasOwnProperty(k) || !equiv(a[k], b[k])) {
+ return false;
}
- return false;
}
return true;
}
diff --git a/packages/associative/CHANGELOG.md b/packages/associative/CHANGELOG.md
index 9e2bf83e6b..1972097b6f 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.4.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/associative@0.4.5...@thi.ng/associative@0.4.6) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/associative
+
## [0.4.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/associative@0.4.4...@thi.ng/associative@0.4.5) (2018-04-26)
diff --git a/packages/associative/package.json b/packages/associative/package.json
index dd9541d466..7f25322332 100644
--- a/packages/associative/package.json
+++ b/packages/associative/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/associative",
- "version": "0.4.5",
+ "version": "0.4.6",
"description": "Alternative Set & Map data type implementations with customizable equality semantics & supporting operations",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,9 +24,9 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/dcons": "^0.3.2",
- "@thi.ng/iterators": "^4.1.8"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/dcons": "^0.3.3",
+ "@thi.ng/iterators": "^4.1.9"
},
"keywords": [
"data structures",
diff --git a/packages/atom/CHANGELOG.md b/packages/atom/CHANGELOG.md
index f5bd2ced14..8130bd9728 100644
--- a/packages/atom/CHANGELOG.md
+++ b/packages/atom/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.3.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/atom@1.3.5...@thi.ng/atom@1.3.6) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/atom
+
## [1.3.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/atom@1.3.4...@thi.ng/atom@1.3.5) (2018-04-26)
diff --git a/packages/atom/package.json b/packages/atom/package.json
index 30ca7aef46..166ce89a2c 100644
--- a/packages/atom/package.json
+++ b/packages/atom/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/atom",
- "version": "1.3.5",
+ "version": "1.3.6",
"description": "Mutable wrapper for immutable values",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,8 +24,8 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/paths": "^1.3.2"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/paths": "^1.3.3"
},
"keywords": [
"cursor",
diff --git a/packages/bitstream/CHANGELOG.md b/packages/bitstream/CHANGELOG.md
index 955c2e5b26..5f2dd3beb5 100644
--- a/packages/bitstream/CHANGELOG.md
+++ b/packages/bitstream/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.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/bitstream@0.4.6...@thi.ng/bitstream@0.4.7) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/bitstream
+
## [0.4.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/bitstream@0.4.5...@thi.ng/bitstream@0.4.6) (2018-04-26)
diff --git a/packages/bitstream/package.json b/packages/bitstream/package.json
index 5e0ac091b9..e4e7b80b23 100644
--- a/packages/bitstream/package.json
+++ b/packages/bitstream/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/bitstream",
- "version": "0.4.6",
+ "version": "0.4.7",
"description": "ES6 iterator based read/write bit streams & support for variable word widths",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -16,7 +16,7 @@
"test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0"
+ "@thi.ng/api": "^2.3.1"
},
"devDependencies": {
"@types/mocha": "^5.0.0",
diff --git a/packages/cache/CHANGELOG.md b/packages/cache/CHANGELOG.md
index b52cc0d379..5b83bd1405 100644
--- a/packages/cache/CHANGELOG.md
+++ b/packages/cache/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.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/cache@0.2.3...@thi.ng/cache@0.2.4) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/cache
+
## [0.2.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/cache@0.2.2...@thi.ng/cache@0.2.3) (2018-04-26)
diff --git a/packages/cache/package.json b/packages/cache/package.json
index f0c023b003..ed32b53559 100644
--- a/packages/cache/package.json
+++ b/packages/cache/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/cache",
- "version": "0.2.3",
+ "version": "0.2.4",
"description": "In-memory cache implementations with ES6 Map-like API and different eviction strategies",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,9 +24,9 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/dcons": "^0.3.2",
- "@thi.ng/iterators": "^4.1.8"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/dcons": "^0.3.3",
+ "@thi.ng/iterators": "^4.1.9"
},
"keywords": [
"cache",
diff --git a/packages/checks/CHANGELOG.md b/packages/checks/CHANGELOG.md
index 1264f81fb3..505c5eef0f 100644
--- a/packages/checks/CHANGELOG.md
+++ b/packages/checks/CHANGELOG.md
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [1.5.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/checks@1.5.0...@thi.ng/checks@1.5.1) (2018-04-29)
+
+
+### Bug Fixes
+
+* **checks:** exclude functions in isArrayLike() ([ac60404](https://github.com/thi-ng/umbrella/commit/ac60404))
+* **checks:** return type isMap() ([76920f7](https://github.com/thi-ng/umbrella/commit/76920f7))
+
+
+
+
# [1.5.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/checks@1.4.0...@thi.ng/checks@1.5.0) (2018-04-26)
diff --git a/packages/checks/package.json b/packages/checks/package.json
index 5a3d892923..c1de4c39b3 100644
--- a/packages/checks/package.json
+++ b/packages/checks/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/checks",
- "version": "1.5.0",
+ "version": "1.5.1",
"description": "Single-function sub-modules for type, feature & value checks",
"main": "./index.js",
"typings": "./index.d.ts",
diff --git a/packages/checks/src/is-arraylike.ts b/packages/checks/src/is-arraylike.ts
index a770a5b345..7824d8f9dc 100644
--- a/packages/checks/src/is-arraylike.ts
+++ b/packages/checks/src/is-arraylike.ts
@@ -1,3 +1,3 @@
export function isArrayLike(x: any): x is ArrayLike {
- return Array.isArray(x) || (x != null && x.length !== undefined);
+ return (x != null && typeof x !== "function" && x.length !== undefined);
}
diff --git a/packages/checks/src/is-map.ts b/packages/checks/src/is-map.ts
index cf8bb3ed2f..d895c5decc 100644
--- a/packages/checks/src/is-map.ts
+++ b/packages/checks/src/is-map.ts
@@ -1,3 +1,3 @@
-export function isMap(x: any): x is Set {
+export function isMap(x: any): x is Map {
return x instanceof Map;
}
diff --git a/packages/checks/test/index.ts b/packages/checks/test/index.ts
index 98fb3b7059..a735b68aa5 100644
--- a/packages/checks/test/index.ts
+++ b/packages/checks/test/index.ts
@@ -62,6 +62,7 @@ describe("checks", function () {
assert(!isArrayLike(0), "zero");
assert(!isArrayLike(null), "null");
assert(!isArrayLike(undefined), "null");
+ assert(!isArrayLike((x, y) => x + y), "null");
});
it("isObject", () => {
diff --git a/packages/csp/CHANGELOG.md b/packages/csp/CHANGELOG.md
index 158f248c61..75ba56a087 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.32](https://github.com/thi-ng/umbrella/compare/@thi.ng/csp@0.3.31...@thi.ng/csp@0.3.32) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/csp
+
## [0.3.31](https://github.com/thi-ng/umbrella/compare/@thi.ng/csp@0.3.30...@thi.ng/csp@0.3.31) (2018-04-26)
diff --git a/packages/csp/package.json b/packages/csp/package.json
index 0f4a599937..a7b6c72d30 100644
--- a/packages/csp/package.json
+++ b/packages/csp/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/csp",
- "version": "0.3.31",
+ "version": "0.3.32",
"description": "ES6 promise based CSP implementation",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -28,8 +28,8 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/dcons": "^0.3.2",
- "@thi.ng/transducers": "^1.8.3"
+ "@thi.ng/dcons": "^0.3.3",
+ "@thi.ng/transducers": "^1.8.4"
},
"keywords": [
"async",
diff --git a/packages/dcons/CHANGELOG.md b/packages/dcons/CHANGELOG.md
index 4ef560d035..ea2e37d2e7 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.
+
+## [0.3.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/dcons@0.3.2...@thi.ng/dcons@0.3.3) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/dcons
+
## [0.3.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/dcons@0.3.1...@thi.ng/dcons@0.3.2) (2018-04-26)
diff --git a/packages/dcons/package.json b/packages/dcons/package.json
index 5ef78ede7e..842777fc58 100644
--- a/packages/dcons/package.json
+++ b/packages/dcons/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/dcons",
- "version": "0.3.2",
+ "version": "0.3.3",
"description": "Comprehensive doubly linked list structure w/ iterator support",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,7 +24,7 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0"
+ "@thi.ng/api": "^2.3.1"
},
"keywords": [
"datastructure",
diff --git a/packages/dgraph/CHANGELOG.md b/packages/dgraph/CHANGELOG.md
index 50a4a4554e..dfdfd61b84 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.1.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/dgraph@0.1.8...@thi.ng/dgraph@0.1.9) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/dgraph
+
## [0.1.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/dgraph@0.1.7...@thi.ng/dgraph@0.1.8) (2018-04-26)
diff --git a/packages/dgraph/package.json b/packages/dgraph/package.json
index bc97469e39..044da28f32 100644
--- a/packages/dgraph/package.json
+++ b/packages/dgraph/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/dgraph",
- "version": "0.1.8",
+ "version": "0.1.9",
"description": "Type-agnostic directed acyclic graph (DAG) & graph operations",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,9 +24,9 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/associative": "^0.4.5",
- "@thi.ng/iterators": "^4.1.8"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/associative": "^0.4.6",
+ "@thi.ng/iterators": "^4.1.9"
},
"keywords": [
"data structure",
diff --git a/packages/diff/CHANGELOG.md b/packages/diff/CHANGELOG.md
index bc9789af11..86a4ea2510 100644
--- a/packages/diff/CHANGELOG.md
+++ b/packages/diff/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.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/diff@1.0.8...@thi.ng/diff@1.0.9) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/diff
+
## [1.0.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/diff@1.0.7...@thi.ng/diff@1.0.8) (2018-04-26)
diff --git a/packages/diff/package.json b/packages/diff/package.json
index ea1118d149..ce7ac613f7 100644
--- a/packages/diff/package.json
+++ b/packages/diff/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/diff",
- "version": "1.0.8",
+ "version": "1.0.9",
"description": "Array & object Diff",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -22,7 +22,7 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0"
+ "@thi.ng/api": "^2.3.1"
},
"keywords": [
"array",
diff --git a/packages/hdom-components/CHANGELOG.md b/packages/hdom-components/CHANGELOG.md
index 24debd9671..e50f71880e 100644
--- a/packages/hdom-components/CHANGELOG.md
+++ b/packages/hdom-components/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.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-components@2.0.2...@thi.ng/hdom-components@2.0.3) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/hdom-components
+
## [2.0.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-components@2.0.1...@thi.ng/hdom-components@2.0.2) (2018-04-26)
diff --git a/packages/hdom-components/package.json b/packages/hdom-components/package.json
index 86b2e36e53..6e111164bb 100644
--- a/packages/hdom-components/package.json
+++ b/packages/hdom-components/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/hdom-components",
- "version": "2.0.2",
+ "version": "2.0.3",
"description": "Raw, skinnable UI & SVG components for @thi.ng/hdom",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,7 +24,7 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/checks": "^1.5.0",
+ "@thi.ng/checks": "^1.5.1",
"@types/webgl2": "^0.0.3"
},
"keywords": [
diff --git a/packages/hdom/CHANGELOG.md b/packages/hdom/CHANGELOG.md
index 7b773295bb..f823c92a70 100644
--- a/packages/hdom/CHANGELOG.md
+++ b/packages/hdom/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.
+
+## [3.0.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom@3.0.11...@thi.ng/hdom@3.0.12) (2018-04-29)
+
+
+### Performance Improvements
+
+* **hdom:** update event handling in diffAttributes() ([31ec3af](https://github.com/thi-ng/umbrella/commit/31ec3af))
+
+
+
+
## [3.0.11](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom@3.0.10...@thi.ng/hdom@3.0.11) (2018-04-26)
diff --git a/packages/hdom/package.json b/packages/hdom/package.json
index d8b0a84401..322ca77707 100644
--- a/packages/hdom/package.json
+++ b/packages/hdom/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/hdom",
- "version": "3.0.11",
+ "version": "3.0.12",
"description": "Lightweight vanilla ES6 UI component & virtual DOM system",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -16,7 +16,7 @@
"test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js"
},
"devDependencies": {
- "@thi.ng/atom": "^1.3.5",
+ "@thi.ng/atom": "^1.3.6",
"@types/mocha": "^5.0.0",
"@types/node": "^9.6.1",
"mocha": "^5.0.5",
@@ -25,10 +25,10 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/diff": "^1.0.8",
- "@thi.ng/hiccup": "^1.3.11",
- "@thi.ng/iterators": "^4.1.8"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/diff": "^1.0.9",
+ "@thi.ng/hiccup": "^1.3.12",
+ "@thi.ng/iterators": "^4.1.9"
},
"keywords": [
"browser",
diff --git a/packages/hdom/src/diff.ts b/packages/hdom/src/diff.ts
index 06385f4852..a0b0f96ee9 100644
--- a/packages/hdom/src/diff.ts
+++ b/packages/hdom/src/diff.ts
@@ -9,8 +9,6 @@ import {
setAttrib
} from "./dom";
-// import { DEBUG } from "./api";
-
const isArray = isa.isArray;
const isString = iss.isString;
const diffArray = diff.diffArray;
@@ -47,7 +45,7 @@ function _diffElement(parent: Element, prev: any, curr: any, child: number) {
const edits = delta.linear;
const el = parent.children[child];
let i, j, k, eq, e, status, idx, val;
- if (edits[0][0] !== 0 || (i = prev[1]).key !== (j = curr[1]).key || hasChangedEvents(i, j)) {
+ if (edits[0][0] !== 0 || (i = prev[1]).key !== (j = curr[1]).key) {
// DEBUG && console.log("replace:", prev, curr);
releaseDeep(prev);
removeChild(parent, child);
@@ -119,30 +117,25 @@ function releaseDeep(tag: any) {
(tag).__release.apply(tag, (tag).__args);
delete (tag).__release;
}
- for (let i = tag.length - 1; i >= 2; i--) {
+ for (let i = tag.length; --i >= 2;) {
releaseDeep(tag[i]);
}
}
}
-function hasChangedEvents(prev: any, curr: any) {
- for (let k in curr) {
- if (k.indexOf("on") === 0 && prev[k] !== curr[k]) {
- return true;
- }
- }
- return false;
-}
-
function diffAttributes(el: Element, prev: any, curr: any) {
let i, e, edits;
const delta = diffObject(prev, curr);
- removeAttribs(el, delta.dels);
- for (edits = delta.edits, i = edits.length - 1; i >= 0; i--) {
+ removeAttribs(el, delta.dels, prev);
+ for (edits = delta.edits, i = edits.length; --i >= 0;) {
e = edits[i];
- setAttrib(el, e[0], e[1], curr);
+ const a = e[0];
+ if (a.indexOf("on") === 0) {
+ el.removeEventListener(a.substr(2), prev[a]);
+ }
+ setAttrib(el, a, e[1], curr);
}
- for (edits = delta.adds, i = edits.length - 1; i >= 0; i--) {
+ for (edits = delta.adds, i = edits.length; --i >= 0;) {
e = edits[i];
setAttrib(el, e, curr[e], curr);
}
@@ -151,7 +144,7 @@ function diffAttributes(el: Element, prev: any, curr: any) {
function extractEquivElements(edits: diff.DiffLogEntry[]) {
let k, v, e, ek;
const equiv = {};
- for (let i = edits.length - 1; i >= 0; i--) {
+ for (let i = edits.length; --i >= 0;) {
e = edits[i];
v = e[2];
if (isArray(v) && (k = v[1].key) !== undefined) {
diff --git a/packages/hdom/src/dom.ts b/packages/hdom/src/dom.ts
index d36f142dd3..3ccc7ef464 100644
--- a/packages/hdom/src/dom.ts
+++ b/packages/hdom/src/dom.ts
@@ -161,9 +161,14 @@ export function updateValueAttrib(el: HTMLInputElement, v: any) {
}
}
-export function removeAttribs(el: Element, attribs: string[]) {
- for (let i = attribs.length - 1; i >= 0; i--) {
- el.removeAttribute(attribs[i]);
+export function removeAttribs(el: Element, attribs: string[], prev: any) {
+ for (let i = attribs.length; --i >= 0;) {
+ const a = attribs[i];
+ if (a.indexOf("on") === 0) {
+ el.removeEventListener(a.substr(2), prev[a]);
+ } else {
+ el.removeAttribute(a);
+ }
}
}
diff --git a/packages/heaps/CHANGELOG.md b/packages/heaps/CHANGELOG.md
index bb39a565df..12ab8bf6e7 100644
--- a/packages/heaps/CHANGELOG.md
+++ b/packages/heaps/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.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/heaps@0.2.4...@thi.ng/heaps@0.2.5) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/heaps
+
## [0.2.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/heaps@0.2.3...@thi.ng/heaps@0.2.4) (2018-04-26)
diff --git a/packages/heaps/package.json b/packages/heaps/package.json
index e9e56574de..daa89bec47 100644
--- a/packages/heaps/package.json
+++ b/packages/heaps/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/heaps",
- "version": "0.2.4",
+ "version": "0.2.5",
"description": "Generic binary heap & d-ary heap implementations with customizable ordering",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,7 +24,7 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0"
+ "@thi.ng/api": "^2.3.1"
},
"keywords": [
"data structure",
diff --git a/packages/hiccup-css/CHANGELOG.md b/packages/hiccup-css/CHANGELOG.md
index 843aeb44fe..57cb4d6ec8 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.1.14](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-css@0.1.13...@thi.ng/hiccup-css@0.1.14) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/hiccup-css
+
## [0.1.13](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-css@0.1.12...@thi.ng/hiccup-css@0.1.13) (2018-04-26)
diff --git a/packages/hiccup-css/package.json b/packages/hiccup-css/package.json
index 6b935822df..3f1da5a219 100644
--- a/packages/hiccup-css/package.json
+++ b/packages/hiccup-css/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/hiccup-css",
- "version": "0.1.13",
+ "version": "0.1.14",
"description": "CSS from nested JS data structures",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,8 +24,8 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/transducers": "^1.8.3"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/transducers": "^1.8.4"
},
"keywords": [
"clojure",
diff --git a/packages/hiccup-svg/CHANGELOG.md b/packages/hiccup-svg/CHANGELOG.md
index f22aa28e64..cd3420db0f 100644
--- a/packages/hiccup-svg/CHANGELOG.md
+++ b/packages/hiccup-svg/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.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-svg@0.2.8...@thi.ng/hiccup-svg@0.2.9) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/hiccup-svg
+
## [0.2.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-svg@0.2.7...@thi.ng/hiccup-svg@0.2.8) (2018-04-26)
diff --git a/packages/hiccup-svg/package.json b/packages/hiccup-svg/package.json
index a574fadad8..2ada6bc793 100644
--- a/packages/hiccup-svg/package.json
+++ b/packages/hiccup-svg/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/hiccup-svg",
- "version": "0.2.8",
+ "version": "0.2.9",
"description": "SVG element functions for @thi.ng/hiccup & @thi.ng/hdom",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,8 +24,8 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/hiccup": "^1.3.11"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/hiccup": "^1.3.12"
},
"keywords": [
"components",
diff --git a/packages/hiccup/CHANGELOG.md b/packages/hiccup/CHANGELOG.md
index 66217d7a8d..3bb3a2724a 100644
--- a/packages/hiccup/CHANGELOG.md
+++ b/packages/hiccup/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.3.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup@1.3.11...@thi.ng/hiccup@1.3.12) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/hiccup
+
## [1.3.11](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup@1.3.10...@thi.ng/hiccup@1.3.11) (2018-04-26)
diff --git a/packages/hiccup/package.json b/packages/hiccup/package.json
index 27b8744ea1..28900bc83f 100644
--- a/packages/hiccup/package.json
+++ b/packages/hiccup/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/hiccup",
- "version": "1.3.11",
+ "version": "1.3.12",
"description": "HTML/SVG/XML serialization of nested data structures, iterables & closures",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -16,7 +16,7 @@
"test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js"
},
"devDependencies": {
- "@thi.ng/atom": "^1.3.5",
+ "@thi.ng/atom": "^1.3.6",
"@types/mocha": "^5.0.0",
"@types/node": "^9.6.1",
"mocha": "^5.0.5",
@@ -25,8 +25,8 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/checks": "^1.5.0"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/checks": "^1.5.1"
},
"keywords": [
"clojure",
diff --git a/packages/interceptors/CHANGELOG.md b/packages/interceptors/CHANGELOG.md
index 86e350a3e4..de7eb2c0b1 100644
--- a/packages/interceptors/CHANGELOG.md
+++ b/packages/interceptors/CHANGELOG.md
@@ -3,6 +3,36 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [1.6.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/interceptors@1.6.1...@thi.ng/interceptors@1.6.2) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/interceptors
+
+
+## [1.6.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/interceptors@1.6.0...@thi.ng/interceptors@1.6.1) (2018-04-28)
+
+
+### Bug Fixes
+
+* **interceptors:** multiple sidefx value assignment ([c4d8851](https://github.com/thi-ng/umbrella/commit/c4d8851))
+
+
+
+
+
+# [1.6.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/interceptors@1.5.3...@thi.ng/interceptors@1.6.0) (2018-04-27)
+
+
+### Features
+
+* **interceptors:** add dispatchLater() ([f4a095a](https://github.com/thi-ng/umbrella/commit/f4a095a))
+
+
+
+
## [1.5.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/interceptors@1.5.2...@thi.ng/interceptors@1.5.3) (2018-04-26)
diff --git a/packages/interceptors/README.md b/packages/interceptors/README.md
index 35303110fe..5c4ac18d2e 100644
--- a/packages/interceptors/README.md
+++ b/packages/interceptors/README.md
@@ -35,7 +35,10 @@ Introductory:
Advanced:
+- [/examples/rstream-dataflow](https://github.com/thi-ng/umbrella/tree/master/examples/rstream-dataflow) | [live demo](http://demo.thi.ng/umbrella/rstream-dataflow)
+- [/examples/rstream-grid](https://github.com/thi-ng/umbrella/tree/master/examples/rstream-grid) | [live demo](http://demo.thi.ng/umbrella/rstream-grid)
- [/examples/router-basics](https://github.com/thi-ng/umbrella/tree/master/examples/router-basics) | [live demo](http://demo.thi.ng/umbrella/router-basics)
+- [/examples/svg-waveform](https://github.com/thi-ng/umbrella/tree/master/examples/svg-waveform) | [live demo](http://demo.thi.ng/umbrella/svg-waveform)
- [create-hdom-app](https://github.com/thi-ng/create-hdom-app) Yarn project generator. Uses: @thi.ng/atom + hdom + interceptors + router
diff --git a/packages/interceptors/package.json b/packages/interceptors/package.json
index c0c0f1210f..a43327c052 100644
--- a/packages/interceptors/package.json
+++ b/packages/interceptors/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/interceptors",
- "version": "1.5.3",
+ "version": "1.6.2",
"description": "Interceptor based event bus, side effect & immutable state handling",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,9 +24,9 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/atom": "^1.3.5",
- "@thi.ng/paths": "^1.3.2"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/atom": "^1.3.6",
+ "@thi.ng/paths": "^1.3.3"
},
"keywords": [
"ES6",
diff --git a/packages/interceptors/src/api.ts b/packages/interceptors/src/api.ts
index 1e1eb62c06..69eb3191a0 100644
--- a/packages/interceptors/src/api.ts
+++ b/packages/interceptors/src/api.ts
@@ -48,6 +48,7 @@ export interface IDispatch {
readonly state: ReadonlyAtom;
dispatch(event: Event);
dispatchNow(event: Event);
+ dispatchLater(event: Event, delay?: number);
}
export interface Interceptor {
diff --git a/packages/interceptors/src/event-bus.ts b/packages/interceptors/src/event-bus.ts
index d8faee5a6d..28b5f2a2bf 100644
--- a/packages/interceptors/src/event-bus.ts
+++ b/packages/interceptors/src/event-bus.ts
@@ -324,6 +324,17 @@ export class StatelessEventBus implements
(this.currQueue || this.eventQueue).push(e);
}
+ /**
+ * Dispatches given event after `delay` milliseconds
+ * (by default 17).
+ *
+ * @param e
+ * @param delay
+ */
+ dispatchLater(e: api.Event, delay = 17) {
+ setTimeout(() => this.dispatch(e), delay);
+ }
+
/**
* Triggers processing of current event queue and returns `true` if
* any events have been processed.
@@ -489,16 +500,13 @@ export class StatelessEventBus implements
this.dispatchNow(v);
}
} else {
- if (ctx[k]) {
- if (isArray(v[0])) {
- for (let e of v) {
- e !== undefined && ctx[k].push(e);
- }
- } else {
- ctx[k].push(v)
+ ctx[k] || (ctx[k] = []);
+ if (isArray(v[0])) {
+ for (let e of v) {
+ e !== undefined && ctx[k].push(e);
}
} else {
- ctx[k] = [v];
+ ctx[k].push(v)
}
}
}
diff --git a/packages/iterators/CHANGELOG.md b/packages/iterators/CHANGELOG.md
index 017bc1ef22..19f30826e0 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.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/iterators@4.1.8...@thi.ng/iterators@4.1.9) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/iterators
+
## [4.1.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/iterators@4.1.7...@thi.ng/iterators@4.1.8) (2018-04-26)
diff --git a/packages/iterators/package.json b/packages/iterators/package.json
index ec5d640245..63d035b5df 100644
--- a/packages/iterators/package.json
+++ b/packages/iterators/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/iterators",
- "version": "4.1.8",
+ "version": "4.1.9",
"description": "clojure.core inspired, composable ES6 iterators & generators",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,8 +24,8 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/dcons": "^0.3.2"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/dcons": "^0.3.3"
},
"keywords": [
"clojure",
diff --git a/packages/paths/CHANGELOG.md b/packages/paths/CHANGELOG.md
index 4977d9d2a5..9dc894103f 100644
--- a/packages/paths/CHANGELOG.md
+++ b/packages/paths/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.3.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/paths@1.3.2...@thi.ng/paths@1.3.3) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/paths
+
## [1.3.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/paths@1.3.1...@thi.ng/paths@1.3.2) (2018-04-26)
diff --git a/packages/paths/package.json b/packages/paths/package.json
index be5e2002fe..b30772f1dd 100644
--- a/packages/paths/package.json
+++ b/packages/paths/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/paths",
- "version": "1.3.2",
+ "version": "1.3.3",
"description": "immutable, optimized path-based object property / array accessors",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,8 +24,8 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/checks": "^1.5.0"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/checks": "^1.5.1"
},
"keywords": [
"accessors",
diff --git a/packages/pointfree-lang/CHANGELOG.md b/packages/pointfree-lang/CHANGELOG.md
index ccd4d427db..fa9a2a3ab9 100644
--- a/packages/pointfree-lang/CHANGELOG.md
+++ b/packages/pointfree-lang/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.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/pointfree-lang@0.2.5...@thi.ng/pointfree-lang@0.2.6) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/pointfree-lang
+
## [0.2.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/pointfree-lang@0.2.4...@thi.ng/pointfree-lang@0.2.5) (2018-04-26)
diff --git a/packages/pointfree-lang/package.json b/packages/pointfree-lang/package.json
index 2b39a16e9e..91fa458da6 100644
--- a/packages/pointfree-lang/package.json
+++ b/packages/pointfree-lang/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/pointfree-lang",
- "version": "0.2.5",
+ "version": "0.2.6",
"description": "Forth style syntax layer/compiler for the @thi.ng/pointfree DSL",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -26,8 +26,8 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/pointfree": "^0.7.5"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/pointfree": "^0.7.6"
},
"keywords": [
"concatenative",
diff --git a/packages/pointfree/CHANGELOG.md b/packages/pointfree/CHANGELOG.md
index d660174f1a..5a0f87ccc8 100644
--- a/packages/pointfree/CHANGELOG.md
+++ b/packages/pointfree/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.7.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/pointfree@0.7.5...@thi.ng/pointfree@0.7.6) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/pointfree
+
## [0.7.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/pointfree@0.7.4...@thi.ng/pointfree@0.7.5) (2018-04-26)
diff --git a/packages/pointfree/package.json b/packages/pointfree/package.json
index 26aa1bf6a6..efa909dc2b 100644
--- a/packages/pointfree/package.json
+++ b/packages/pointfree/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/pointfree",
- "version": "0.7.5",
+ "version": "0.7.6",
"description": "Pointfree functional composition / Forth style stack execution engine",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,7 +24,7 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0"
+ "@thi.ng/api": "^2.3.1"
},
"keywords": [
"composition",
diff --git a/packages/resolve-map/CHANGELOG.md b/packages/resolve-map/CHANGELOG.md
index 217e7c1c75..71183dde64 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.
-
+
+## [1.0.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/resolve-map@1.0.3...@thi.ng/resolve-map@1.0.4) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/resolve-map
+
+
## [1.0.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/resolve-map@1.0.2...@thi.ng/resolve-map@1.0.3) (2018-04-26)
@@ -11,7 +19,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
**Note:** Version bump only for package @thi.ng/resolve-map
-
+
## [1.0.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/resolve-map@1.0.1...@thi.ng/resolve-map@1.0.2) (2018-04-19)
diff --git a/packages/resolve-map/package.json b/packages/resolve-map/package.json
index 06bddff40a..b52050fe5f 100644
--- a/packages/resolve-map/package.json
+++ b/packages/resolve-map/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/resolve-map",
- "version": "1.0.3",
+ "version": "1.0.4",
"description": "DAG resolution of vanilla objects & arrays with internally linked values",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -22,9 +22,9 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/checks": "^1.5.0",
- "@thi.ng/paths": "^1.3.2"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/checks": "^1.5.1",
+ "@thi.ng/paths": "^1.3.3"
},
"keywords": [
"configuration",
diff --git a/packages/rle-pack/CHANGELOG.md b/packages/rle-pack/CHANGELOG.md
index 811e452638..5ff929f352 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.
+
+## [0.2.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/rle-pack@0.2.15...@thi.ng/rle-pack@0.2.16) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rle-pack
+
## [0.2.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/rle-pack@0.2.14...@thi.ng/rle-pack@0.2.15) (2018-04-26)
diff --git a/packages/rle-pack/package.json b/packages/rle-pack/package.json
index 3437420997..e67fdee3bb 100644
--- a/packages/rle-pack/package.json
+++ b/packages/rle-pack/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/rle-pack",
- "version": "0.2.15",
+ "version": "0.2.16",
"description": "Binary run-length encoding packer w/ flexible repeat bit widths",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -25,7 +25,7 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/bitstream": "^0.4.6"
+ "@thi.ng/bitstream": "^0.4.7"
},
"keywords": [
"binary",
diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md
index 377501326c..e40e8a438b 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.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/router@0.1.8...@thi.ng/router@0.1.9) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/router
+
## [0.1.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/router@0.1.7...@thi.ng/router@0.1.8) (2018-04-26)
diff --git a/packages/router/package.json b/packages/router/package.json
index 15e1618e24..9acf48a4ce 100644
--- a/packages/router/package.json
+++ b/packages/router/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/router",
- "version": "0.1.8",
+ "version": "0.1.9",
"description": "Generic router for browser & non-browser based applications",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -23,7 +23,7 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0"
+ "@thi.ng/api": "^2.3.1"
},
"keywords": [
"declarative",
diff --git a/packages/rstream-csp/CHANGELOG.md b/packages/rstream-csp/CHANGELOG.md
index 3a04598047..2a3e05ea9e 100644
--- a/packages/rstream-csp/CHANGELOG.md
+++ b/packages/rstream-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.1.63](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-csp@0.1.62...@thi.ng/rstream-csp@0.1.63) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-csp
+
## [0.1.62](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-csp@0.1.61...@thi.ng/rstream-csp@0.1.62) (2018-04-26)
diff --git a/packages/rstream-csp/package.json b/packages/rstream-csp/package.json
index 4664b23ba7..7442fec6ca 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.62",
+ "version": "0.1.63",
"description": "@thi.ng/csp bridge module for @thi.ng/rstream",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,8 +24,8 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/csp": "^0.3.31",
- "@thi.ng/rstream": "^1.6.3"
+ "@thi.ng/csp": "^0.3.32",
+ "@thi.ng/rstream": "^1.6.4"
},
"keywords": [
"bridge",
diff --git a/packages/rstream-dot/CHANGELOG.md b/packages/rstream-dot/CHANGELOG.md
index e7e6d21879..135b7e8ef3 100644
--- a/packages/rstream-dot/CHANGELOG.md
+++ b/packages/rstream-dot/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.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-dot@0.2.1...@thi.ng/rstream-dot@0.2.2) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-dot
+
## [0.2.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-dot@0.2.0...@thi.ng/rstream-dot@0.2.1) (2018-04-26)
diff --git a/packages/rstream-dot/package.json b/packages/rstream-dot/package.json
index 076fee2a70..05e377669d 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.1",
+ "version": "0.2.2",
"description": "Graphviz DOT conversion of @thi.ng/rstream dataflow graph topologies",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,9 +24,9 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/rstream": "^1.6.3",
- "@thi.ng/transducers": "^1.8.3"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/rstream": "^1.6.4",
+ "@thi.ng/transducers": "^1.8.4"
},
"keywords": [
"conversion",
diff --git a/packages/rstream-gestures/CHANGELOG.md b/packages/rstream-gestures/CHANGELOG.md
index e6fabdb134..6c2a837d1c 100644
--- a/packages/rstream-gestures/CHANGELOG.md
+++ b/packages/rstream-gestures/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.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-gestures@0.2.4...@thi.ng/rstream-gestures@0.2.5) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-gestures
+
## [0.2.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-gestures@0.2.3...@thi.ng/rstream-gestures@0.2.4) (2018-04-26)
diff --git a/packages/rstream-gestures/package.json b/packages/rstream-gestures/package.json
index 3b16ebd6aa..1655b82842 100644
--- a/packages/rstream-gestures/package.json
+++ b/packages/rstream-gestures/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/rstream-gestures",
- "version": "0.2.4",
+ "version": "0.2.5",
"description": "Unified mouse, mouse wheel & single-touch event stream abstraction",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,9 +24,9 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/rstream": "^1.6.3",
- "@thi.ng/transducers": "^1.8.3"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/rstream": "^1.6.4",
+ "@thi.ng/transducers": "^1.8.4"
},
"keywords": [
"dataflow",
diff --git a/packages/rstream-graph/CHANGELOG.md b/packages/rstream-graph/CHANGELOG.md
index 440b891503..b3977cdcdb 100644
--- a/packages/rstream-graph/CHANGELOG.md
+++ b/packages/rstream-graph/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.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-graph@1.0.4...@thi.ng/rstream-graph@1.0.5) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-graph
+
## [1.0.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-graph@1.0.3...@thi.ng/rstream-graph@1.0.4) (2018-04-26)
diff --git a/packages/rstream-graph/package.json b/packages/rstream-graph/package.json
index 2420ce7bed..4682ffe3a3 100644
--- a/packages/rstream-graph/package.json
+++ b/packages/rstream-graph/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/rstream-graph",
- "version": "1.0.4",
+ "version": "1.0.5",
"description": "Declarative dataflow graph construction for @thi.ng/rstream",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,11 +24,11 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/paths": "^1.3.2",
- "@thi.ng/resolve-map": "^1.0.3",
- "@thi.ng/rstream": "^1.6.3",
- "@thi.ng/transducers": "^1.8.3"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/paths": "^1.3.3",
+ "@thi.ng/resolve-map": "^1.0.4",
+ "@thi.ng/rstream": "^1.6.4",
+ "@thi.ng/transducers": "^1.8.4"
},
"keywords": [
"compute",
diff --git a/packages/rstream-log/CHANGELOG.md b/packages/rstream-log/CHANGELOG.md
index 6d20e3aac3..1643359ac6 100644
--- a/packages/rstream-log/CHANGELOG.md
+++ b/packages/rstream-log/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.14](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log@1.0.13...@thi.ng/rstream-log@1.0.14) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-log
+
## [1.0.13](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log@1.0.12...@thi.ng/rstream-log@1.0.13) (2018-04-26)
diff --git a/packages/rstream-log/package.json b/packages/rstream-log/package.json
index 69e2314d63..64d922c6a2 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.13",
+ "version": "1.0.14",
"description": "Structured, multilevel & hierarchical loggers based on @thi.ng/rstream",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,8 +24,8 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/rstream": "^1.6.3"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/rstream": "^1.6.4"
},
"keywords": [
"ES6",
diff --git a/packages/rstream-query/CHANGELOG.md b/packages/rstream-query/CHANGELOG.md
index 6ebdd537e2..4bba4f0a09 100644
--- a/packages/rstream-query/CHANGELOG.md
+++ b/packages/rstream-query/CHANGELOG.md
@@ -3,6 +3,25 @@
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/rstream-query@0.3.0...@thi.ng/rstream-query@0.3.1) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream-query
+
+
+# [0.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-query@0.2.2...@thi.ng/rstream-query@0.3.0) (2018-04-27)
+
+
+### Features
+
+* **rstream-query:** add obj->triple converter, update readme & example ([6f95bcb](https://github.com/thi-ng/umbrella/commit/6f95bcb))
+
+
+
+
## [0.2.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-query@0.2.1...@thi.ng/rstream-query@0.2.2) (2018-04-26)
diff --git a/packages/rstream-query/README.md b/packages/rstream-query/README.md
index 9dd2bb72ec..98e558c1c4 100644
--- a/packages/rstream-query/README.md
+++ b/packages/rstream-query/README.md
@@ -53,30 +53,47 @@ yarn add @thi.ng/rstream-query
## Usage examples
```typescript
+import { TripleStore, asTriples } from "@thi.ng/rstream-query";
import { trace } from "@thi.ng/rstream";
-import { TripleStore } from "../src";
// create store with initial set of triples / facts
const store = new TripleStore([
["london", "type", "city"],
["london", "part-of", "uk"],
["portland", "type", "city"],
- ["portland", "part-of", "oregon"],
- ["portland", "part-of", "usa"],
+ ["portland", "partOf", "oregon"],
+ ["portland", "partOf", "usa"],
["oregon", "type", "state"],
["usa", "type", "country"],
["uk", "type", "country"],
]);
+// alternatively, convert an object into a sequence of triples
+const store = new TripleStore(asTriples({
+ london: {
+ type: "city",
+ partOf: "uk"
+ },
+ portland: {
+ type: "city",
+ partOf: ["oregon", "usa"]
+ },
+ oregon: { type: "state" },
+ uk: { type: "country" },
+ usa: { type: "country" },
+});
+
// compile the below query spec into a dataflow graph
// pattern items prefixed w/ "?" are query variables
// this query matches the following relationships
// using all currently known triples in the store
+// when matching triples are added or removed, the query
+// result updates automatically...
-// currently only "where" and "path" sub-queries are possible
+// currently only "where" and bounded "path" sub-queries are possible
// in the near future, more query types will be supported
-// (e.g. optional relationships, filters etc.)
+// (e.g. optional relationships, pre/post filters etc.)
store.addQueryFromSpec({
q: [
{
@@ -85,7 +102,7 @@ store.addQueryFromSpec({
// match any subject of type "city"
["?city", "type", "city"],
// match each ?city var's "part-of" relationships (if any)
- ["?city", "part-of", "?country"],
+ ["?city", "partOf", "?country"],
// matched ?country var must have type = "country"
["?country", "type", "country"]
]
@@ -100,7 +117,8 @@ store.addQueryFromSpec({
},
// another post-processing step, only keeps "answer" var in results
select: ["answer"]
-}).subscribe(trace("results"))
+})
+.subscribe(trace("results"))
// results Set {
// { answer: 'london is located in uk' },
// { answer: 'portland is located in usa' } }
@@ -109,7 +127,7 @@ store.addQueryFromSpec({
const addCity = (name, country) =>
store.into([
[name, "type", "city"],
- [name, "part-of", country],
+ [name, "partOf", country],
[country, "type", "country"],
]);
diff --git a/packages/rstream-query/package.json b/packages/rstream-query/package.json
index 5eac9ccbc1..4e7f45e36d 100644
--- a/packages/rstream-query/package.json
+++ b/packages/rstream-query/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/rstream-query",
- "version": "0.2.2",
+ "version": "0.3.1",
"description": "@thi.ng/rstream based triple store & reactive query engine",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,11 +24,11 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/associative": "^0.4.5",
- "@thi.ng/rstream": "^1.6.3",
- "@thi.ng/rstream-dot": "^0.2.1",
- "@thi.ng/transducers": "^1.8.3"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/associative": "^0.4.6",
+ "@thi.ng/rstream": "^1.6.4",
+ "@thi.ng/rstream-dot": "^0.2.2",
+ "@thi.ng/transducers": "^1.8.4"
},
"keywords": [
"dataflow",
diff --git a/packages/rstream-query/src/convert.ts b/packages/rstream-query/src/convert.ts
new file mode 100644
index 0000000000..49ea82d9fb
--- /dev/null
+++ b/packages/rstream-query/src/convert.ts
@@ -0,0 +1,86 @@
+import { isArray } from "@thi.ng/checks/is-array";
+import { isPlainObject } from "@thi.ng/checks/is-plain-object";
+import { concat } from "@thi.ng/transducers/iter/concat";
+import { pairs } from "@thi.ng/transducers/iter/pairs";
+import { iterator } from "@thi.ng/transducers/iterator";
+import { mapcat } from "@thi.ng/transducers/xform/mapcat";
+
+let NEXT_ID = 0;
+
+const mapBNode = (s: any, p: any, o: any) => {
+ const id = `__b${NEXT_ID++}__`;
+ return concat([[s, p, id]], asTriples(o, id));
+};
+
+const mapSubject = (subject: any) =>
+ ([p, o]) => {
+ if (isArray(o)) {
+ return iterator(
+ mapcat((o) =>
+ isPlainObject(o) ?
+ mapBNode(subject, p, o) :
+ [[subject, p, o]]),
+ o);
+ } else if (isPlainObject(o)) {
+ return mapBNode(subject, p, o);
+ }
+ return [[subject, p, o]];
+ };
+
+/**
+ * Converts given object into an iterable of triples, with the following
+ * conversion rules:
+ *
+ * - Toplevel object keys are used as subjects and MUST each have a
+ * plain object as value, where its keys are used as predicates and
+ * values as objects (in the SPO sense).
+ * - Plain objects in SPO object position are translated into unique IDs
+ * in order to allow the nested map to become a subject itself. In RDF
+ * terms, this is equivalent to BNodes.
+ * - Arrays in SPO object position cause multiple triples with same
+ * subject & predicate to be emitted. If any of the items in the array
+ * is a plain object, it will be treated as BNode and transformed as
+ * described in the previous rule
+ *
+ * ```
+ * src = {
+ * "@thi.ng/rstream-query": {
+ * type: "project",
+ * author: "toxi",
+ * tag: ["ES6", "TypeScript", "graph"]
+ * },
+ * toxi: {
+ * type: "person",
+ * hasAccount: [
+ * {type: "twitter", id: "toxi"},
+ * {type: "github", id: "postspectacular"}
+ * ]
+ * }
+ * };
+ *
+ * [...asTriples(src)]
+ * // [ [ '@thi.ng/rstream-query', 'type', 'project' ],
+ * // [ '@thi.ng/rstream-query', 'author', 'toxi' ],
+ * // [ '@thi.ng/rstream-query', 'tag', 'ES6' ],
+ * // [ '@thi.ng/rstream-query', 'tag', 'TypeScript' ],
+ * // [ '@thi.ng/rstream-query', 'tag', 'graph' ],
+ * // [ 'toxi', 'type', 'person' ],
+ * // [ 'toxi', 'hasAccount', '__b0__' ],
+ * // [ '__b0__', 'type', 'twitter' ],
+ * // [ '__b0__', 'id', 'toxi' ],
+ * // [ 'toxi', 'hasAccount', '__b1__' ],
+ * // [ '__b1__', 'type', 'github' ],
+ * // [ '__b1__', 'id', 'postspectacular' ] ]
+ * ```
+ *
+ * @param obj
+ * @param subject internal use only, do not specify!
+ */
+export const asTriples = (obj: any, subject?: any) =>
+ iterator(
+ mapcat(
+ subject === undefined ?
+ ([s, v]: any) => iterator(mapcat(mapSubject(s)), pairs(v)) :
+ mapSubject(subject)
+ ),
+ pairs(obj));
diff --git a/packages/rstream-query/src/index.ts b/packages/rstream-query/src/index.ts
index cde4f0f325..fed8901627 100644
--- a/packages/rstream-query/src/index.ts
+++ b/packages/rstream-query/src/index.ts
@@ -1,4 +1,5 @@
export * from "./api";
+export * from "./convert";
export * from "./pattern";
export * from "./qvar";
export * from "./store";
diff --git a/packages/rstream-query/src/store.ts b/packages/rstream-query/src/store.ts
index 26c9dbbed1..4337dc2ea4 100644
--- a/packages/rstream-query/src/store.ts
+++ b/packages/rstream-query/src/store.ts
@@ -219,7 +219,7 @@ export class TripleStore implements
}
}
return emitTriples ?
- results.subscribe(asTriples(this)) :
+ results.subscribe(resultTriples(this)) :
results;
}
@@ -432,7 +432,7 @@ const indexSel = (key: any): Transducer =>
);
};
-const asTriples = (graph: TripleStore) =>
+const resultTriples = (graph: TripleStore) =>
map>(
(ids) => {
const res = new Set();
diff --git a/packages/rstream-query/test/example.ts b/packages/rstream-query/test/example.ts
index 9a28886371..7cf18581d1 100644
--- a/packages/rstream-query/test/example.ts
+++ b/packages/rstream-query/test/example.ts
@@ -1,7 +1,7 @@
import { trace } from "@thi.ng/rstream";
-import { TripleStore } from "../src";
+import * as q from "../src";
-const store = new TripleStore([
+const store = new q.TripleStore([
["london", "type", "city"],
["london", "part-of", "uk"],
["portland", "type", "city"],
@@ -12,6 +12,21 @@ const store = new TripleStore([
["uk", "type", "country"],
]);
+// alternatively, convert an object into a sequence of triples
+// const store = new q.TripleStore(q.asTriples({
+// london: {
+// type: "city",
+// partOf: "uk"
+// },
+// portland: {
+// type: "city",
+// partOf: ["oregon", "usa"]
+// },
+// oregon: { type: "state" },
+// uk: { type: "country" },
+// usa: { type: "country" },
+// }));
+
// compile the below query spec into a dataflow graph
// pattern items prefixed w/ "?" are query variables
@@ -28,7 +43,7 @@ store.addQueryFromSpec({
// first match any subject of type "city"
["?city", "type", "city"],
// then a city's "part-of" relationships (if any)
- ["?city", "part-of", "?country"],
+ ["?city", "partOf", "?country"],
// the matched ?country must have type = "country"
["?country", "type", "country"]
]
@@ -52,7 +67,7 @@ store.addQueryFromSpec({
const addCity = (name, country) =>
store.into([
[name, "type", "city"],
- [name, "part-of", country],
+ [name, "partOf", country],
[country, "type", "country"],
]);
diff --git a/packages/rstream/CHANGELOG.md b/packages/rstream/CHANGELOG.md
index 5f6efcfc99..fe29baffa3 100644
--- a/packages/rstream/CHANGELOG.md
+++ b/packages/rstream/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.6.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream@1.6.3...@thi.ng/rstream@1.6.4) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/rstream
+
## [1.6.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream@1.6.2...@thi.ng/rstream@1.6.3) (2018-04-26)
diff --git a/packages/rstream/package.json b/packages/rstream/package.json
index ee7ff4f4fa..a92dd1cf12 100644
--- a/packages/rstream/package.json
+++ b/packages/rstream/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/rstream",
- "version": "1.6.3",
+ "version": "1.6.4",
"description": "Reactive multi-tap streams, dataflow & transformation pipeline constructs",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,10 +24,10 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0",
- "@thi.ng/associative": "^0.4.5",
- "@thi.ng/atom": "^1.3.5",
- "@thi.ng/transducers": "^1.8.3"
+ "@thi.ng/api": "^2.3.1",
+ "@thi.ng/associative": "^0.4.6",
+ "@thi.ng/atom": "^1.3.6",
+ "@thi.ng/transducers": "^1.8.4"
},
"keywords": [
"datastructure",
diff --git a/packages/transducers/CHANGELOG.md b/packages/transducers/CHANGELOG.md
index 9598093e57..58e6ae4278 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.
+
+## [1.8.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers@1.8.3...@thi.ng/transducers@1.8.4) (2018-04-29)
+
+
+
+
+**Note:** Version bump only for package @thi.ng/transducers
+
## [1.8.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers@1.8.2...@thi.ng/transducers@1.8.3) (2018-04-26)
diff --git a/packages/transducers/package.json b/packages/transducers/package.json
index 0200cd5f46..4acb3b9d98 100644
--- a/packages/transducers/package.json
+++ b/packages/transducers/package.json
@@ -1,6 +1,6 @@
{
"name": "@thi.ng/transducers",
- "version": "1.8.3",
+ "version": "1.8.4",
"description": "Lightweight transducer implementations for ES6 / TypeScript",
"main": "./index.js",
"typings": "./index.d.ts",
@@ -24,7 +24,7 @@
"typescript": "^2.8.1"
},
"dependencies": {
- "@thi.ng/api": "^2.3.0"
+ "@thi.ng/api": "^2.3.1"
},
"keywords": [
"ES6",