+For this example, take a look at the javascript console, and press the random button several times.
+You'll notice that when the value that gets chosen matches the previous value, the "ACTUAL UPDATE" console message
+doesn't fire. this is because the view hasn't changed, so the thunk doesn't re-evaluate the snabby dom vnode.
+
`
// Patch to DOM:
html.update(document.body, foo)
@@ -22,9 +22,9 @@ Snabby is for creating [Snabbdom](https://github.com/snabbdom/snabbdom) [virtual
## Installation
-```sh
-$ npm install --save snabby
-```
+Snabby version 2.x is a pure es module. It requires node >= v12.17 or a browser that supports the es module format.
+
+If you want the older commonjs build, use the `snabby@1.x` npm module
## Usage
@@ -34,17 +34,17 @@ $ npm install --save snabby
A [tag function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals) that creates a node. This function is usually required as `html` instead of `snabby`:
```js
-var html = require('snabby')
+import html from 'snabby'
// Function to create VNode from params:
-var greet = name => html`
+let greet = name => html`
Hello, ${name}!
`
-var node1 = greet('Jamen')
+let node1 = greet('Jamen')
// Hello, Jamen!
-var node2 = greet('World')
+let node2 = greet('World')
// Hello, World!
```
@@ -83,13 +83,13 @@ If you want to put a node on the DOM, or push updates on it (i.e. from events),
First things first, the Node has to be mounted to the DOM, _before_ you try and update it:
```js
-var html = require('snabby')
+import html from 'snabby'
-var visit = location => html`
+let visit = location => html`
Hello, ${location}!
`
-var node1 = visit('Earth')
+let node1 = visit('Earth')
// Mount node to DOM
html.update(document.body, node1)
@@ -99,7 +99,7 @@ html.update(document.body, node1)
From there, you can patch updates:
```js
-var node2 = visit('TRAPPIST-1')
+let node2 = visit('TRAPPIST-1')
// Patch updates to node1
html.update(node1, node2)
@@ -114,13 +114,20 @@ Create a `snabby` tag function with your own modules.
Here is an equivalent to `snabby` for example:
```js
-var html = require('snabby/create')([
- require('snabbdom/modules/attributes').default,
- require('snabbdom/modules/eventlisteners').default,
- require('snabbdom/modules/class').default,
- require('snabbdom/modules/props').default,
- require('snabbdom/modules/style').default
+import create from './create.js'
+import { classModule } from 'https://cdn.jsdelivr.net/npm/snabbdom@2.1.0/build/package/modules/class.js';
+import { propsModule } from 'https://cdn.jsdelivr.net/npm/snabbdom@2.1.0/build/package/modules/props.js';
+import { styleModule } from 'https://cdn.jsdelivr.net/npm/snabbdom@2.1.0/build/package/modules/style.js';
+import { eventListenersModule } from 'https://cdn.jsdelivr.net/npm/snabbdom@2.1.0/build/package/modules/eventlisteners.js';
+
+
+const html = create([
+ classModule,
+ propsModule,
+ styleModule,
+ eventListenersModule,
])
+
```
As mentioned, you can use directives with 3rd party modules fine. Open an issue if you can't!
diff --git a/rollup.config.js b/rollup.config.js
index 1108345..85e3b01 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -1,10 +1,12 @@
-import resolve from 'rollup-plugin-node-resolve'
-import commonjs from 'rollup-plugin-commonjs'
-import replace from 'rollup-plugin-replace'
+import urlResolve from 'rollup-plugin-url-resolve'
+import resolve from '@rollup/plugin-node-resolve'
+import commonjs from '@rollup/plugin-commonjs'
+import replace from '@rollup/plugin-replace'
export default {
plugins: [
+ urlResolve(),
resolve(),
commonjs(),
replace({
diff --git a/snabby.js b/snabby.js
index e3030cd..fa421ab 100644
--- a/snabby.js
+++ b/snabby.js
@@ -1,630 +1,494 @@
function vnode(sel, data, children, text, elm) {
- var key = data === undefined ? undefined : data.key;
- return { sel: sel, data: data, children: children, text: text, elm: elm, key: key };
+ const key = data === undefined ? undefined : data.key;
+ return { sel, data, children, text, elm, key };
}
-var array = Array.isArray;
+const array = Array.isArray;
function primitive(s) {
- return typeof s === 'string' || typeof s === 'number';
+ return typeof s === 'string' || typeof s === 'number';
}
function createElement(tagName) {
- return document.createElement(tagName);
+ return document.createElement(tagName);
}
function createElementNS(namespaceURI, qualifiedName) {
- return document.createElementNS(namespaceURI, qualifiedName);
+ return document.createElementNS(namespaceURI, qualifiedName);
}
function createTextNode(text) {
- return document.createTextNode(text);
+ return document.createTextNode(text);
}
function createComment(text) {
- return document.createComment(text);
+ return document.createComment(text);
}
function insertBefore(parentNode, newNode, referenceNode) {
- parentNode.insertBefore(newNode, referenceNode);
+ parentNode.insertBefore(newNode, referenceNode);
}
function removeChild(node, child) {
- node.removeChild(child);
+ node.removeChild(child);
}
function appendChild(node, child) {
- node.appendChild(child);
+ node.appendChild(child);
}
function parentNode(node) {
- return node.parentNode;
+ return node.parentNode;
}
function nextSibling(node) {
- return node.nextSibling;
+ return node.nextSibling;
}
function tagName(elm) {
- return elm.tagName;
+ return elm.tagName;
}
function setTextContent(node, text) {
- node.textContent = text;
+ node.textContent = text;
}
function getTextContent(node) {
- return node.textContent;
+ return node.textContent;
}
function isElement(node) {
- return node.nodeType === 1;
+ return node.nodeType === 1;
}
function isText(node) {
- return node.nodeType === 3;
+ return node.nodeType === 3;
}
function isComment(node) {
- return node.nodeType === 8;
+ return node.nodeType === 8;
}
-var htmlDomApi = {
- createElement: createElement,
- createElementNS: createElementNS,
- createTextNode: createTextNode,
- createComment: createComment,
- insertBefore: insertBefore,
- removeChild: removeChild,
- appendChild: appendChild,
- parentNode: parentNode,
- nextSibling: nextSibling,
- tagName: tagName,
- setTextContent: setTextContent,
- getTextContent: getTextContent,
- isElement: isElement,
- isText: isText,
- isComment: isComment,
-};
-
-function addNS(data, children, sel) {
- data.ns = 'http://www.w3.org/2000/svg';
- if (sel !== 'foreignObject' && children !== undefined) {
- for (var i = 0; i < children.length; ++i) {
- var childData = children[i].data;
- if (childData !== undefined) {
- addNS(childData, children[i].children, children[i].sel);
- }
- }
- }
-}
-function h(sel, b, c) {
- var data = {}, children, text, i;
- if (c !== undefined) {
- data = b;
- if (array(c)) {
- children = c;
- }
- else if (primitive(c)) {
- text = c;
- }
- else if (c && c.sel) {
- children = [c];
- }
- }
- else if (b !== undefined) {
- if (array(b)) {
- children = b;
- }
- else if (primitive(b)) {
- text = b;
- }
- else if (b && b.sel) {
- children = [b];
- }
- else {
- data = b;
- }
- }
- if (children !== undefined) {
- for (i = 0; i < children.length; ++i) {
- if (primitive(children[i]))
- children[i] = vnode(undefined, undefined, undefined, children[i], undefined);
- }
- }
- if (sel[0] === 's' && sel[1] === 'v' && sel[2] === 'g' &&
- (sel.length === 3 || sel[3] === '.' || sel[3] === '#')) {
- addNS(data, children, sel);
- }
- return vnode(sel, data, children, text, undefined);
+const htmlDomApi = {
+ createElement,
+ createElementNS,
+ createTextNode,
+ createComment,
+ insertBefore,
+ removeChild,
+ appendChild,
+ parentNode,
+ nextSibling,
+ tagName,
+ setTextContent,
+ getTextContent,
+ isElement,
+ isText,
+ isComment };
+
+function isUndef(s) {
+ return s === undefined;
}
-
-function copyToThunk(vnode, thunk) {
- thunk.elm = vnode.elm;
- vnode.data.fn = thunk.data.fn;
- vnode.data.args = thunk.data.args;
- thunk.data = vnode.data;
- thunk.children = vnode.children;
- thunk.text = vnode.text;
- thunk.elm = vnode.elm;
-}
-function init(thunk) {
- var cur = thunk.data;
- var vnode = cur.fn.apply(undefined, cur.args);
- copyToThunk(vnode, thunk);
-}
-function prepatch(oldVnode, thunk) {
- var i, old = oldVnode.data, cur = thunk.data;
- var oldArgs = old.args, args = cur.args;
- if (old.fn !== cur.fn || oldArgs.length !== args.length) {
- copyToThunk(cur.fn.apply(undefined, args), thunk);
- return;
- }
- for (i = 0; i < args.length; ++i) {
- if (oldArgs[i] !== args[i]) {
- copyToThunk(cur.fn.apply(undefined, args), thunk);
- return;
- }
- }
- copyToThunk(oldVnode, thunk);
+function isDef(s) {
+ return s !== undefined;
}
-var thunk = function thunk(sel, key, fn, args) {
- if (args === undefined) {
- args = fn;
- fn = key;
- key = undefined;
- }
- return h(sel, {
- key: key,
- hook: { init: init, prepatch: prepatch },
- fn: fn,
- args: args
- });
-};
-
-function isUndef(s) { return s === undefined; }
-function isDef(s) { return s !== undefined; }
-var emptyNode = vnode('', {}, [], undefined, undefined);
+const emptyNode = vnode('', {}, [], undefined, undefined);
function sameVnode(vnode1, vnode2) {
- return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel;
+ return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel;
}
function isVnode(vnode) {
- return vnode.sel !== undefined;
+ return vnode.sel !== undefined;
}
function createKeyToOldIdx(children, beginIdx, endIdx) {
- var i, map = {}, key, ch;
- for (i = beginIdx; i <= endIdx; ++i) {
- ch = children[i];
- if (ch != null) {
- key = ch.key;
- if (key !== undefined)
- map[key] = i;
- }
+ var _a;
+ const map = {};
+ for (let i = beginIdx; i <= endIdx; ++i) {
+ const key = (_a = children[i]) === null || _a === void 0 ? void 0 : _a.key;
+ if (key !== undefined) {
+ map[key] = i;
}
- return map;
+ }
+ return map;
}
-var hooks = ['create', 'update', 'remove', 'destroy', 'pre', 'post'];
-function init$1(modules, domApi) {
- var i, j, cbs = {};
- var api = domApi !== undefined ? domApi : htmlDomApi;
- for (i = 0; i < hooks.length; ++i) {
- cbs[hooks[i]] = [];
- for (j = 0; j < modules.length; ++j) {
- var hook = modules[j][hooks[i]];
- if (hook !== undefined) {
- cbs[hooks[i]].push(hook);
- }
- }
- }
- function emptyNodeAt(elm) {
- var id = elm.id ? '#' + elm.id : '';
- var c = elm.className ? '.' + elm.className.split(' ').join('.') : '';
- return vnode(api.tagName(elm).toLowerCase() + id + c, {}, [], undefined, elm);
+const hooks = ['create', 'update', 'remove', 'destroy', 'pre', 'post'];
+function init(modules, domApi) {
+ let i;
+ let j;
+ const cbs = {
+ create: [],
+ update: [],
+ remove: [],
+ destroy: [],
+ pre: [],
+ post: [] };
+
+ const api = domApi !== undefined ? domApi : htmlDomApi;
+ for (i = 0; i < hooks.length; ++i) {
+ cbs[hooks[i]] = [];
+ for (j = 0; j < modules.length; ++j) {
+ const hook = modules[j][hooks[i]];
+ if (hook !== undefined) {
+ cbs[hooks[i]].push(hook);
+ }
}
- function createRmCb(childElm, listeners) {
- return function rmCb() {
- if (--listeners === 0) {
- var parent_1 = api.parentNode(childElm);
- api.removeChild(parent_1, childElm);
- }
- };
+ }
+ function emptyNodeAt(elm) {
+ const id = elm.id ? '#' + elm.id : '';
+ const c = elm.className ? '.' + elm.className.split(' ').join('.') : '';
+ return vnode(api.tagName(elm).toLowerCase() + id + c, {}, [], undefined, elm);
+ }
+ function createRmCb(childElm, listeners) {
+ return function rmCb() {
+ if (--listeners === 0) {
+ const parent = api.parentNode(childElm);
+ api.removeChild(parent, childElm);
+ }
+ };
+ }
+ function createElm(vnode, insertedVnodeQueue) {
+ var _a, _b;
+ let i;
+ let data = vnode.data;
+ if (data !== undefined) {
+ const init = (_a = data.hook) === null || _a === void 0 ? void 0 : _a.init;
+ if (isDef(init)) {
+ init(vnode);
+ data = vnode.data;
+ }
}
- function createElm(vnode, insertedVnodeQueue) {
- var i, data = vnode.data;
- if (data !== undefined) {
- if (isDef(i = data.hook) && isDef(i = i.init)) {
- i(vnode);
- data = vnode.data;
- }
- }
- var children = vnode.children, sel = vnode.sel;
- if (sel === '!') {
- if (isUndef(vnode.text)) {
- vnode.text = '';
- }
- vnode.elm = api.createComment(vnode.text);
- }
- else if (sel !== undefined) {
- // Parse selector
- var hashIdx = sel.indexOf('#');
- var dotIdx = sel.indexOf('.', hashIdx);
- var hash = hashIdx > 0 ? hashIdx : sel.length;
- var dot = dotIdx > 0 ? dotIdx : sel.length;
- var tag = hashIdx !== -1 || dotIdx !== -1 ? sel.slice(0, Math.min(hash, dot)) : sel;
- var elm = vnode.elm = isDef(data) && isDef(i = data.ns) ? api.createElementNS(i, tag)
- : api.createElement(tag);
- if (hash < dot)
- elm.setAttribute('id', sel.slice(hash + 1, dot));
- if (dotIdx > 0)
- elm.setAttribute('class', sel.slice(dot + 1).replace(/\./g, ' '));
- for (i = 0; i < cbs.create.length; ++i)
- cbs.create[i](emptyNode, vnode);
- if (array(children)) {
- for (i = 0; i < children.length; ++i) {
- var ch = children[i];
- if (ch != null) {
- api.appendChild(elm, createElm(ch, insertedVnodeQueue));
- }
- }
- }
- else if (primitive(vnode.text)) {
- api.appendChild(elm, api.createTextNode(vnode.text));
- }
- i = vnode.data.hook; // Reuse variable
- if (isDef(i)) {
- if (i.create)
- i.create(emptyNode, vnode);
- if (i.insert)
- insertedVnodeQueue.push(vnode);
- }
+ const children = vnode.children;
+ const sel = vnode.sel;
+ if (sel === '!') {
+ if (isUndef(vnode.text)) {
+ vnode.text = '';
+ }
+ vnode.elm = api.createComment(vnode.text);
+ } else
+ if (sel !== undefined) {
+ // Parse selector
+ const hashIdx = sel.indexOf('#');
+ const dotIdx = sel.indexOf('.', hashIdx);
+ const hash = hashIdx > 0 ? hashIdx : sel.length;
+ const dot = dotIdx > 0 ? dotIdx : sel.length;
+ const tag = hashIdx !== -1 || dotIdx !== -1 ? sel.slice(0, Math.min(hash, dot)) : sel;
+ const elm = vnode.elm = isDef(data) && isDef(i = data.ns) ?
+ api.createElementNS(i, tag) :
+ api.createElement(tag);
+ if (hash < dot)
+ elm.setAttribute('id', sel.slice(hash + 1, dot));
+ if (dotIdx > 0)
+ elm.setAttribute('class', sel.slice(dot + 1).replace(/\./g, ' '));
+ for (i = 0; i < cbs.create.length; ++i)
+ cbs.create[i](emptyNode, vnode);
+ if (array(children)) {
+ for (i = 0; i < children.length; ++i) {
+ const ch = children[i];
+ if (ch != null) {
+ api.appendChild(elm, createElm(ch, insertedVnodeQueue));
+ }
}
- else {
- vnode.elm = api.createTextNode(vnode.text);
+ } else
+ if (primitive(vnode.text)) {
+ api.appendChild(elm, api.createTextNode(vnode.text));
+ }
+ const hook = vnode.data.hook;
+ if (isDef(hook)) {
+ (_b = hook.create) === null || _b === void 0 ? void 0 : _b.call(hook, emptyNode, vnode);
+ if (hook.insert) {
+ insertedVnodeQueue.push(vnode);
}
- return vnode.elm;
+ }
+ } else
+ {
+ vnode.elm = api.createTextNode(vnode.text);
}
- function addVnodes(parentElm, before, vnodes, startIdx, endIdx, insertedVnodeQueue) {
- for (; startIdx <= endIdx; ++startIdx) {
- var ch = vnodes[startIdx];
- if (ch != null) {
- api.insertBefore(parentElm, createElm(ch, insertedVnodeQueue), before);
- }
- }
+ return vnode.elm;
+ }
+ function addVnodes(parentElm, before, vnodes, startIdx, endIdx, insertedVnodeQueue) {
+ for (; startIdx <= endIdx; ++startIdx) {
+ const ch = vnodes[startIdx];
+ if (ch != null) {
+ api.insertBefore(parentElm, createElm(ch, insertedVnodeQueue), before);
+ }
}
- function invokeDestroyHook(vnode) {
- var i, j, data = vnode.data;
- if (data !== undefined) {
- if (isDef(i = data.hook) && isDef(i = i.destroy))
- i(vnode);
- for (i = 0; i < cbs.destroy.length; ++i)
- cbs.destroy[i](vnode);
- if (vnode.children !== undefined) {
- for (j = 0; j < vnode.children.length; ++j) {
- i = vnode.children[j];
- if (i != null && typeof i !== "string") {
- invokeDestroyHook(i);
- }
- }
- }
+ }
+ function invokeDestroyHook(vnode) {
+ var _a, _b;
+ const data = vnode.data;
+ if (data !== undefined) {
+ (_b = (_a = data === null || data === void 0 ? void 0 : data.hook) === null || _a === void 0 ? void 0 : _a.destroy) === null || _b === void 0 ? void 0 : _b.call(_a, vnode);
+ for (let i = 0; i < cbs.destroy.length; ++i)
+ cbs.destroy[i](vnode);
+ if (vnode.children !== undefined) {
+ for (let j = 0; j < vnode.children.length; ++j) {
+ const child = vnode.children[j];
+ if (child != null && typeof child !== 'string') {
+ invokeDestroyHook(child);
+ }
}
+ }
}
- function removeVnodes(parentElm, vnodes, startIdx, endIdx) {
- for (; startIdx <= endIdx; ++startIdx) {
- var i_1 = void 0, listeners = void 0, rm = void 0, ch = vnodes[startIdx];
- if (ch != null) {
- if (isDef(ch.sel)) {
- invokeDestroyHook(ch);
- listeners = cbs.remove.length + 1;
- rm = createRmCb(ch.elm, listeners);
- for (i_1 = 0; i_1 < cbs.remove.length; ++i_1)
- cbs.remove[i_1](ch, rm);
- if (isDef(i_1 = ch.data) && isDef(i_1 = i_1.hook) && isDef(i_1 = i_1.remove)) {
- i_1(ch, rm);
- }
- else {
- rm();
- }
- }
- else { // Text node
- api.removeChild(parentElm, ch.elm);
- }
- }
+ }
+ function removeVnodes(parentElm, vnodes, startIdx, endIdx) {
+ var _a, _b;
+ for (; startIdx <= endIdx; ++startIdx) {
+ let listeners;
+ let rm;
+ const ch = vnodes[startIdx];
+ if (ch != null) {
+ if (isDef(ch.sel)) {
+ invokeDestroyHook(ch);
+ listeners = cbs.remove.length + 1;
+ rm = createRmCb(ch.elm, listeners);
+ for (let i = 0; i < cbs.remove.length; ++i)
+ cbs.remove[i](ch, rm);
+ const removeHook = (_b = (_a = ch === null || ch === void 0 ? void 0 : ch.data) === null || _a === void 0 ? void 0 : _a.hook) === null || _b === void 0 ? void 0 : _b.remove;
+ if (isDef(removeHook)) {
+ removeHook(ch, rm);
+ } else
+ {
+ rm();
+ }
+ } else
+ {// Text node
+ api.removeChild(parentElm, ch.elm);
}
+ }
}
- function updateChildren(parentElm, oldCh, newCh, insertedVnodeQueue) {
- var oldStartIdx = 0, newStartIdx = 0;
- var oldEndIdx = oldCh.length - 1;
- var oldStartVnode = oldCh[0];
- var oldEndVnode = oldCh[oldEndIdx];
- var newEndIdx = newCh.length - 1;
- var newStartVnode = newCh[0];
- var newEndVnode = newCh[newEndIdx];
- var oldKeyToIdx;
- var idxInOld;
- var elmToMove;
- var before;
- while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
- if (oldStartVnode == null) {
- oldStartVnode = oldCh[++oldStartIdx]; // Vnode might have been moved left
- }
- else if (oldEndVnode == null) {
- oldEndVnode = oldCh[--oldEndIdx];
- }
- else if (newStartVnode == null) {
- newStartVnode = newCh[++newStartIdx];
- }
- else if (newEndVnode == null) {
- newEndVnode = newCh[--newEndIdx];
- }
- else if (sameVnode(oldStartVnode, newStartVnode)) {
- patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue);
- oldStartVnode = oldCh[++oldStartIdx];
- newStartVnode = newCh[++newStartIdx];
- }
- else if (sameVnode(oldEndVnode, newEndVnode)) {
- patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue);
- oldEndVnode = oldCh[--oldEndIdx];
- newEndVnode = newCh[--newEndIdx];
- }
- else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right
- patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue);
- api.insertBefore(parentElm, oldStartVnode.elm, api.nextSibling(oldEndVnode.elm));
- oldStartVnode = oldCh[++oldStartIdx];
- newEndVnode = newCh[--newEndIdx];
- }
- else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left
- patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue);
- api.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm);
- oldEndVnode = oldCh[--oldEndIdx];
- newStartVnode = newCh[++newStartIdx];
- }
- else {
- if (oldKeyToIdx === undefined) {
- oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);
- }
- idxInOld = oldKeyToIdx[newStartVnode.key];
- if (isUndef(idxInOld)) { // New element
- api.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);
- newStartVnode = newCh[++newStartIdx];
- }
- else {
- elmToMove = oldCh[idxInOld];
- if (elmToMove.sel !== newStartVnode.sel) {
- api.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);
- }
- else {
- patchVnode(elmToMove, newStartVnode, insertedVnodeQueue);
- oldCh[idxInOld] = undefined;
- api.insertBefore(parentElm, elmToMove.elm, oldStartVnode.elm);
- }
- newStartVnode = newCh[++newStartIdx];
- }
- }
+ }
+ function updateChildren(parentElm, oldCh, newCh, insertedVnodeQueue) {
+ let oldStartIdx = 0;
+ let newStartIdx = 0;
+ let oldEndIdx = oldCh.length - 1;
+ let oldStartVnode = oldCh[0];
+ let oldEndVnode = oldCh[oldEndIdx];
+ let newEndIdx = newCh.length - 1;
+ let newStartVnode = newCh[0];
+ let newEndVnode = newCh[newEndIdx];
+ let oldKeyToIdx;
+ let idxInOld;
+ let elmToMove;
+ let before;
+ while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
+ if (oldStartVnode == null) {
+ oldStartVnode = oldCh[++oldStartIdx]; // Vnode might have been moved left
+ } else
+ if (oldEndVnode == null) {
+ oldEndVnode = oldCh[--oldEndIdx];
+ } else
+ if (newStartVnode == null) {
+ newStartVnode = newCh[++newStartIdx];
+ } else
+ if (newEndVnode == null) {
+ newEndVnode = newCh[--newEndIdx];
+ } else
+ if (sameVnode(oldStartVnode, newStartVnode)) {
+ patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue);
+ oldStartVnode = oldCh[++oldStartIdx];
+ newStartVnode = newCh[++newStartIdx];
+ } else
+ if (sameVnode(oldEndVnode, newEndVnode)) {
+ patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue);
+ oldEndVnode = oldCh[--oldEndIdx];
+ newEndVnode = newCh[--newEndIdx];
+ } else
+ if (sameVnode(oldStartVnode, newEndVnode)) {// Vnode moved right
+ patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue);
+ api.insertBefore(parentElm, oldStartVnode.elm, api.nextSibling(oldEndVnode.elm));
+ oldStartVnode = oldCh[++oldStartIdx];
+ newEndVnode = newCh[--newEndIdx];
+ } else
+ if (sameVnode(oldEndVnode, newStartVnode)) {// Vnode moved left
+ patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue);
+ api.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm);
+ oldEndVnode = oldCh[--oldEndIdx];
+ newStartVnode = newCh[++newStartIdx];
+ } else
+ {
+ if (oldKeyToIdx === undefined) {
+ oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);
}
- if (oldStartIdx <= oldEndIdx || newStartIdx <= newEndIdx) {
- if (oldStartIdx > oldEndIdx) {
- before = newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm;
- addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);
- }
- else {
- removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
- }
+ idxInOld = oldKeyToIdx[newStartVnode.key];
+ if (isUndef(idxInOld)) {// New element
+ api.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);
+ } else
+ {
+ elmToMove = oldCh[idxInOld];
+ if (elmToMove.sel !== newStartVnode.sel) {
+ api.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);
+ } else
+ {
+ patchVnode(elmToMove, newStartVnode, insertedVnodeQueue);
+ oldCh[idxInOld] = undefined;
+ api.insertBefore(parentElm, elmToMove.elm, oldStartVnode.elm);
+ }
}
+ newStartVnode = newCh[++newStartIdx];
+ }
}
- function patchVnode(oldVnode, vnode, insertedVnodeQueue) {
- var i, hook;
- if (isDef(i = vnode.data) && isDef(hook = i.hook) && isDef(i = hook.prepatch)) {
- i(oldVnode, vnode);
- }
- var elm = vnode.elm = oldVnode.elm;
- var oldCh = oldVnode.children;
- var ch = vnode.children;
- if (oldVnode === vnode)
- return;
- if (vnode.data !== undefined) {
- for (i = 0; i < cbs.update.length; ++i)
- cbs.update[i](oldVnode, vnode);
- i = vnode.data.hook;
- if (isDef(i) && isDef(i = i.update))
- i(oldVnode, vnode);
- }
- if (isUndef(vnode.text)) {
- if (isDef(oldCh) && isDef(ch)) {
- if (oldCh !== ch)
- updateChildren(elm, oldCh, ch, insertedVnodeQueue);
- }
- else if (isDef(ch)) {
- if (isDef(oldVnode.text))
- api.setTextContent(elm, '');
- addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);
- }
- else if (isDef(oldCh)) {
- removeVnodes(elm, oldCh, 0, oldCh.length - 1);
- }
- else if (isDef(oldVnode.text)) {
- api.setTextContent(elm, '');
- }
- }
- else if (oldVnode.text !== vnode.text) {
- if (isDef(oldCh)) {
- removeVnodes(elm, oldCh, 0, oldCh.length - 1);
- }
- api.setTextContent(elm, vnode.text);
- }
- if (isDef(hook) && isDef(i = hook.postpatch)) {
- i(oldVnode, vnode);
- }
+ if (oldStartIdx <= oldEndIdx || newStartIdx <= newEndIdx) {
+ if (oldStartIdx > oldEndIdx) {
+ before = newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm;
+ addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);
+ } else
+ {
+ removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
+ }
}
- return function patch(oldVnode, vnode) {
- var i, elm, parent;
- var insertedVnodeQueue = [];
- for (i = 0; i < cbs.pre.length; ++i)
- cbs.pre[i]();
- if (!isVnode(oldVnode)) {
- oldVnode = emptyNodeAt(oldVnode);
- }
- if (sameVnode(oldVnode, vnode)) {
- patchVnode(oldVnode, vnode, insertedVnodeQueue);
- }
- else {
- elm = oldVnode.elm;
- parent = api.parentNode(elm);
- createElm(vnode, insertedVnodeQueue);
- if (parent !== null) {
- api.insertBefore(parent, vnode.elm, api.nextSibling(elm));
- removeVnodes(parent, [oldVnode], 0, 0);
- }
- }
- for (i = 0; i < insertedVnodeQueue.length; ++i) {
- insertedVnodeQueue[i].data.hook.insert(insertedVnodeQueue[i]);
- }
- for (i = 0; i < cbs.post.length; ++i)
- cbs.post[i]();
- return vnode;
- };
-}
-
-var snabbdom = /*#__PURE__*/Object.freeze({
- __proto__: null,
- init: init$1,
- h: h,
- thunk: thunk
-});
-
-function unwrapExports (x) {
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
-}
-
-function createCommonjsModule(fn, module) {
- return module = { exports: {} }, fn(module, module.exports), module.exports;
-}
-
-var vnode_1 = createCommonjsModule(function (module, exports) {
-Object.defineProperty(exports, "__esModule", { value: true });
-function vnode(sel, data, children, text, elm) {
- var key = data === undefined ? undefined : data.key;
- return { sel: sel, data: data, children: children, text: text, elm: elm, key: key };
-}
-exports.vnode = vnode;
-exports.default = vnode;
-
-});
-
-unwrapExports(vnode_1);
-var vnode_2 = vnode_1.vnode;
-
-var is = createCommonjsModule(function (module, exports) {
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.array = Array.isArray;
-function primitive(s) {
- return typeof s === 'string' || typeof s === 'number';
+ }
+ function patchVnode(oldVnode, vnode, insertedVnodeQueue) {
+ var _a, _b, _c, _d, _e;
+ const hook = (_a = vnode.data) === null || _a === void 0 ? void 0 : _a.hook;
+ (_b = hook === null || hook === void 0 ? void 0 : hook.prepatch) === null || _b === void 0 ? void 0 : _b.call(hook, oldVnode, vnode);
+ const elm = vnode.elm = oldVnode.elm;
+ const oldCh = oldVnode.children;
+ const ch = vnode.children;
+ if (oldVnode === vnode)
+ return;
+ if (vnode.data !== undefined) {
+ for (let i = 0; i < cbs.update.length; ++i)
+ cbs.update[i](oldVnode, vnode);
+ (_d = (_c = vnode.data.hook) === null || _c === void 0 ? void 0 : _c.update) === null || _d === void 0 ? void 0 : _d.call(_c, oldVnode, vnode);
+ }
+ if (isUndef(vnode.text)) {
+ if (isDef(oldCh) && isDef(ch)) {
+ if (oldCh !== ch)
+ updateChildren(elm, oldCh, ch, insertedVnodeQueue);
+ } else
+ if (isDef(ch)) {
+ if (isDef(oldVnode.text))
+ api.setTextContent(elm, '');
+ addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);
+ } else
+ if (isDef(oldCh)) {
+ removeVnodes(elm, oldCh, 0, oldCh.length - 1);
+ } else
+ if (isDef(oldVnode.text)) {
+ api.setTextContent(elm, '');
+ }
+ } else
+ if (oldVnode.text !== vnode.text) {
+ if (isDef(oldCh)) {
+ removeVnodes(elm, oldCh, 0, oldCh.length - 1);
+ }
+ api.setTextContent(elm, vnode.text);
+ }
+ (_e = hook === null || hook === void 0 ? void 0 : hook.postpatch) === null || _e === void 0 ? void 0 : _e.call(hook, oldVnode, vnode);
+ }
+ return function patch(oldVnode, vnode) {
+ let i, elm, parent;
+ const insertedVnodeQueue = [];
+ for (i = 0; i < cbs.pre.length; ++i)
+ cbs.pre[i]();
+ if (!isVnode(oldVnode)) {
+ oldVnode = emptyNodeAt(oldVnode);
+ }
+ if (sameVnode(oldVnode, vnode)) {
+ patchVnode(oldVnode, vnode, insertedVnodeQueue);
+ } else
+ {
+ elm = oldVnode.elm;
+ parent = api.parentNode(elm);
+ createElm(vnode, insertedVnodeQueue);
+ if (parent !== null) {
+ api.insertBefore(parent, vnode.elm, api.nextSibling(elm));
+ removeVnodes(parent, [oldVnode], 0, 0);
+ }
+ }
+ for (i = 0; i < insertedVnodeQueue.length; ++i) {
+ insertedVnodeQueue[i].data.hook.insert(insertedVnodeQueue[i]);
+ }
+ for (i = 0; i < cbs.post.length; ++i)
+ cbs.post[i]();
+ return vnode;
+ };
}
-exports.primitive = primitive;
-
-});
-
-unwrapExports(is);
-var is_1 = is.array;
-var is_2 = is.primitive;
-
-var h_1 = createCommonjsModule(function (module, exports) {
-Object.defineProperty(exports, "__esModule", { value: true });
-
function addNS(data, children, sel) {
- data.ns = 'http://www.w3.org/2000/svg';
- if (sel !== 'foreignObject' && children !== undefined) {
- for (var i = 0; i < children.length; ++i) {
- var childData = children[i].data;
- if (childData !== undefined) {
- addNS(childData, children[i].children, children[i].sel);
- }
- }
+ data.ns = 'http://www.w3.org/2000/svg';
+ if (sel !== 'foreignObject' && children !== undefined) {
+ for (let i = 0; i < children.length; ++i) {
+ const childData = children[i].data;
+ if (childData !== undefined) {
+ addNS(childData, children[i].children, children[i].sel);
+ }
}
+ }
}
function h(sel, b, c) {
- var data = {}, children, text, i;
- if (c !== undefined) {
- data = b;
- if (is.array(c)) {
- children = c;
- }
- else if (is.primitive(c)) {
- text = c;
- }
- else if (c && c.sel) {
- children = [c];
- }
+ var data = {};
+ var children;
+ var text;
+ var i;
+ if (c !== undefined) {
+ if (b !== null) {
+ data = b;
}
- else if (b !== undefined) {
- if (is.array(b)) {
- children = b;
- }
- else if (is.primitive(b)) {
- text = b;
- }
- else if (b && b.sel) {
- children = [b];
- }
- else {
- data = b;
- }
+ if (array(c)) {
+ children = c;
+ } else
+ if (primitive(c)) {
+ text = c;
+ } else
+ if (c && c.sel) {
+ children = [c];
}
- if (children !== undefined) {
- for (i = 0; i < children.length; ++i) {
- if (is.primitive(children[i]))
- children[i] = vnode_1.vnode(undefined, undefined, undefined, children[i], undefined);
- }
+ } else
+ if (b !== undefined && b !== null) {
+ if (array(b)) {
+ children = b;
+ } else
+ if (primitive(b)) {
+ text = b;
+ } else
+ if (b && b.sel) {
+ children = [b];
+ } else
+ {
+ data = b;
}
- if (sel[0] === 's' && sel[1] === 'v' && sel[2] === 'g' &&
- (sel.length === 3 || sel[3] === '.' || sel[3] === '#')) {
- addNS(data, children, sel);
+ }
+ if (children !== undefined) {
+ for (i = 0; i < children.length; ++i) {
+ if (primitive(children[i]))
+ children[i] = vnode(undefined, undefined, undefined, children[i], undefined);
}
- return vnode_1.vnode(sel, data, children, text, undefined);
+ }
+ if (sel[0] === 's' && sel[1] === 'v' && sel[2] === 'g' && (
+ sel.length === 3 || sel[3] === '.' || sel[3] === '#')) {
+ addNS(data, children, sel);
+ }
+ return vnode(sel, data, children, text, undefined);
}
-exports.h = h;
-exports.default = h;
-
-});
-
-unwrapExports(h_1);
-var h_2 = h_1.h;
-
-var thunk$1 = createCommonjsModule(function (module, exports) {
-Object.defineProperty(exports, "__esModule", { value: true });
function copyToThunk(vnode, thunk) {
- thunk.elm = vnode.elm;
- vnode.data.fn = thunk.data.fn;
- vnode.data.args = thunk.data.args;
- thunk.data = vnode.data;
- thunk.children = vnode.children;
- thunk.text = vnode.text;
- thunk.elm = vnode.elm;
+ vnode.data.fn = thunk.data.fn;
+ vnode.data.args = thunk.data.args;
+ thunk.data = vnode.data;
+ thunk.children = vnode.children;
+ thunk.text = vnode.text;
+ thunk.elm = vnode.elm;
}
-function init(thunk) {
- var cur = thunk.data;
- var vnode = cur.fn.apply(undefined, cur.args);
- copyToThunk(vnode, thunk);
+function init$1(thunk) {
+ const cur = thunk.data;
+ const vnode = cur.fn.apply(undefined, cur.args);
+ copyToThunk(vnode, thunk);
}
function prepatch(oldVnode, thunk) {
- var i, old = oldVnode.data, cur = thunk.data;
- var oldArgs = old.args, args = cur.args;
- if (old.fn !== cur.fn || oldArgs.length !== args.length) {
- copyToThunk(cur.fn.apply(undefined, args), thunk);
- return;
- }
- for (i = 0; i < args.length; ++i) {
- if (oldArgs[i] !== args[i]) {
- copyToThunk(cur.fn.apply(undefined, args), thunk);
- return;
- }
+ let i;
+ const old = oldVnode.data;
+ const cur = thunk.data;
+ const oldArgs = old.args;
+ const args = cur.args;
+ if (old.fn !== cur.fn || oldArgs.length !== args.length) {
+ copyToThunk(cur.fn.apply(undefined, args), thunk);
+ return;
+ }
+ for (i = 0; i < args.length; ++i) {
+ if (oldArgs[i] !== args[i]) {
+ copyToThunk(cur.fn.apply(undefined, args), thunk);
+ return;
}
- copyToThunk(oldVnode, thunk);
+ }
+ copyToThunk(oldVnode, thunk);
}
-exports.thunk = function thunk(sel, key, fn, args) {
- if (args === undefined) {
- args = fn;
- fn = key;
- key = undefined;
- }
- return h_1.h(sel, {
- key: key,
- hook: { init: init, prepatch: prepatch },
- fn: fn,
- args: args
- });
-};
-exports.default = exports.thunk;
-
-});
+const thunk = function thunk(sel, key, fn, args) {
+ if (args === undefined) {
+ args = fn;
+ fn = key;
+ key = undefined;
+ }
+ return h(sel, {
+ key: key,
+ hook: { init: init$1, prepatch },
+ fn: fn,
+ args: args });
-unwrapExports(thunk$1);
-var thunk_1 = thunk$1.thunk;
+};
var hyperscriptAttributeToProperty = attributeToProperty;
@@ -936,417 +800,382 @@ var closeRE = RegExp('^(' + [
].join('|') + ')(?:[\.#][a-zA-Z0-9\u007F-\uFFFF_:-]+)*$');
function selfClosing (tag) { return closeRE.test(tag) }
-var thunk$2 = thunk$1.default;
-var h$1 = h_1.default;
-
-
-
-var create_1 = create;
-
-function create (modules, options) {
- if (!options) options = {};
+function create (modules, options={}) {
- // options
- var directive = options.directive || '@';
+ const directive = options.directive || '@';
function createElement (sel, input, content) {
- // Adjust content:
if (content && content.length) {
- if (content.length === 1) {
+ if (content.length === 1)
content = content[0];
- } else {
- // Flatten nested arrays
- content = [].concat.apply([], content);
- }
+ else
+ content = [].concat.apply([], content); // flatten nested arrays
}
- // Attribute names, and handling none faster:
- var names = Object.keys(input);
- if (!names || !names.length) {
- return h$1(sel, content)
- }
+ // attribute names, and handling none faster:
+ const names = Object.keys(input);
+ if (!names || !names.length)
+ return h(sel, content)
- // Parse Snabbdom's `data` from attributes:
- var data = {};
- for (var i = 0, max = names.length; max > i; i++) {
- var name = names[i];
- if (input[name] === 'false') {
+ // parse Snabbdom's `data` from attributes:
+ const data = { };
+ for (let i = 0, max = names.length; max > i; i++) {
+ const name = names[i];
+ if (input[name] === 'false')
input[name] = false;
- }
- // Directive attributes
+ // directive attributes
if (name.indexOf(directive) === 0) {
- var parts = name.slice(1).split(':');
- var previous = data;
- for (var p = 0, pmax = parts.length, last = pmax - 1; p < pmax; p++) {
- var part = parts[p];
- if (p === last) {
+ const parts = name.slice(1).split(':');
+ let previous = data;
+ for (let p = 0, pmax = parts.length, last = pmax - 1; p < pmax; p++) {
+ const part = parts[p];
+ if (p === last)
previous[part] = input[name];
- } else if (!previous[part]) {
- previous = previous[part] = {};
- } else {
+ else if (!previous[part])
+ previous = previous[part] = { };
+ else
previous = previous[part];
- }
}
}
- // Put all other attributes into `data.attrs`
+ // put all other attributes into `data.attrs`
else {
- if (!data.attrs) data.attrs = {};
+ if (!data.attrs)
+ data.attrs = { };
data.attrs[name] = input[name];
}
}
- // Return vnode:
- return h$1(sel, data, content)
+ // return vnode:
+ return h(sel, data, content)
}
- // Create the snabbdom + hyperx functions
- var patch = snabbdom.init(modules || []);
+ // create the snabbdom + hyperx functions
+ const patch = init(modules || [ ]);
- // Create snabby function
- var snabby = hyperx(createElement, { attrToProp: false });
+ // create snabby function
+ const snabby = hyperx(createElement, { attrToProp: false });
- // Create yo-yo-like update function
+ // create yo-yo-like update function
snabby.update = function update (dest, src) {
return patch(dest, src)
};
- snabby.thunk = thunk$2;
+ snabby.thunk = thunk;
return snabby
}
-var attributes = createCommonjsModule(function (module, exports) {
-Object.defineProperty(exports, "__esModule", { value: true });
-var xlinkNS = 'http://www.w3.org/1999/xlink';
-var xmlNS = 'http://www.w3.org/XML/1998/namespace';
-var colonChar = 58;
-var xChar = 120;
+const xlinkNS = 'http://www.w3.org/1999/xlink';
+const xmlNS = 'http://www.w3.org/XML/1998/namespace';
+const colonChar = 58;
+const xChar = 120;
function updateAttrs(oldVnode, vnode) {
- var key, elm = vnode.elm, oldAttrs = oldVnode.data.attrs, attrs = vnode.data.attrs;
- if (!oldAttrs && !attrs)
- return;
- if (oldAttrs === attrs)
- return;
- oldAttrs = oldAttrs || {};
- attrs = attrs || {};
- // update modified attributes, add new attributes
- for (key in attrs) {
- var cur = attrs[key];
- var old = oldAttrs[key];
- if (old !== cur) {
- if (cur === true) {
- elm.setAttribute(key, "");
- }
- else if (cur === false) {
- elm.removeAttribute(key);
- }
- else {
- if (key.charCodeAt(0) !== xChar) {
- elm.setAttribute(key, cur);
- }
- else if (key.charCodeAt(3) === colonChar) {
- // Assume xml namespace
- elm.setAttributeNS(xmlNS, key, cur);
- }
- else if (key.charCodeAt(5) === colonChar) {
- // Assume xlink namespace
- elm.setAttributeNS(xlinkNS, key, cur);
- }
- else {
- elm.setAttribute(key, cur);
- }
- }
- }
- }
- // remove removed attributes
- // use `in` operator since the previous `for` iteration uses it (.i.e. add even attributes with undefined value)
- // the other option is to remove all attributes with value == undefined
- for (key in oldAttrs) {
- if (!(key in attrs)) {
- elm.removeAttribute(key);
- }
- }
-}
-exports.attributesModule = { create: updateAttrs, update: updateAttrs };
-exports.default = exports.attributesModule;
-
-});
-
-unwrapExports(attributes);
-var attributes_1 = attributes.attributesModule;
-
-var eventlisteners = createCommonjsModule(function (module, exports) {
-Object.defineProperty(exports, "__esModule", { value: true });
-function invokeHandler(handler, vnode, event) {
- if (typeof handler === "function") {
- // call function handler
- handler.call(vnode, event, vnode);
- }
- else if (typeof handler === "object") {
- // call handler with arguments
- if (typeof handler[0] === "function") {
- // special case for single argument for performance
- if (handler.length === 2) {
- handler[0].call(vnode, handler[1], event, vnode);
- }
- else {
- var args = handler.slice(1);
- args.push(event);
- args.push(vnode);
- handler[0].apply(vnode, args);
- }
- }
- else {
- // call multiple handlers
- for (var i = 0; i < handler.length; i++) {
- invokeHandler(handler[i], vnode, event);
- }
- }
- }
-}
-function handleEvent(event, vnode) {
- var name = event.type, on = vnode.data.on;
- // call event handler(s) if exists
- if (on && on[name]) {
- invokeHandler(on[name], vnode, event);
- }
-}
-function createListener() {
- return function handler(event) {
- handleEvent(event, handler.vnode);
- };
-}
-function updateEventListeners(oldVnode, vnode) {
- var oldOn = oldVnode.data.on, oldListener = oldVnode.listener, oldElm = oldVnode.elm, on = vnode && vnode.data.on, elm = (vnode && vnode.elm), name;
- // optimization for reused immutable handlers
- if (oldOn === on) {
- return;
- }
- // remove existing listeners which no longer used
- if (oldOn && oldListener) {
- // if element changed or deleted we remove all existing listeners unconditionally
- if (!on) {
- for (name in oldOn) {
- // remove listener if element was changed or existing listeners removed
- oldElm.removeEventListener(name, oldListener, false);
- }
- }
- else {
- for (name in oldOn) {
- // remove listener if existing listener removed
- if (!on[name]) {
- oldElm.removeEventListener(name, oldListener, false);
- }
- }
+ var key;
+ var elm = vnode.elm;
+ var oldAttrs = oldVnode.data.attrs;
+ var attrs = vnode.data.attrs;
+ if (!oldAttrs && !attrs)
+ return;
+ if (oldAttrs === attrs)
+ return;
+ oldAttrs = oldAttrs || {};
+ attrs = attrs || {};
+ // update modified attributes, add new attributes
+ for (key in attrs) {
+ const cur = attrs[key];
+ const old = oldAttrs[key];
+ if (old !== cur) {
+ if (cur === true) {
+ elm.setAttribute(key, '');
+ } else
+ if (cur === false) {
+ elm.removeAttribute(key);
+ } else
+ {
+ if (key.charCodeAt(0) !== xChar) {
+ elm.setAttribute(key, cur);
+ } else
+ if (key.charCodeAt(3) === colonChar) {
+ // Assume xml namespace
+ elm.setAttributeNS(xmlNS, key, cur);
+ } else
+ if (key.charCodeAt(5) === colonChar) {
+ // Assume xlink namespace
+ elm.setAttributeNS(xlinkNS, key, cur);
+ } else
+ {
+ elm.setAttribute(key, cur);
}
+ }
}
- // add new listeners which has not already attached
- if (on) {
- // reuse existing listener or create new
- var listener = vnode.listener = oldVnode.listener || createListener();
- // update vnode for listener
- listener.vnode = vnode;
- // if element changed or added we add all needed listeners unconditionally
- if (!oldOn) {
- for (name in on) {
- // add listener if element was changed or new listeners added
- elm.addEventListener(name, listener, false);
- }
- }
- else {
- for (name in on) {
- // add listener if new listener added
- if (!oldOn[name]) {
- elm.addEventListener(name, listener, false);
- }
- }
- }
+ }
+ // remove removed attributes
+ // use `in` operator since the previous `for` iteration uses it (.i.e. add even attributes with undefined value)
+ // the other option is to remove all attributes with value == undefined
+ for (key in oldAttrs) {
+ if (!(key in attrs)) {
+ elm.removeAttribute(key);
}
+ }
}
-exports.eventListenersModule = {
- create: updateEventListeners,
- update: updateEventListeners,
- destroy: updateEventListeners
-};
-exports.default = exports.eventListenersModule;
-
-});
+const attributesModule = { create: updateAttrs, update: updateAttrs };
-unwrapExports(eventlisteners);
-var eventlisteners_1 = eventlisteners.eventListenersModule;
-
-var _class = createCommonjsModule(function (module, exports) {
-Object.defineProperty(exports, "__esModule", { value: true });
function updateClass(oldVnode, vnode) {
- var cur, name, elm = vnode.elm, oldClass = oldVnode.data.class, klass = vnode.data.class;
- if (!oldClass && !klass)
- return;
- if (oldClass === klass)
- return;
- oldClass = oldClass || {};
- klass = klass || {};
- for (name in oldClass) {
- if (!klass[name]) {
- elm.classList.remove(name);
- }
+ var cur;
+ var name;
+ var elm = vnode.elm;
+ var oldClass = oldVnode.data.class;
+ var klass = vnode.data.class;
+ if (!oldClass && !klass)
+ return;
+ if (oldClass === klass)
+ return;
+ oldClass = oldClass || {};
+ klass = klass || {};
+ for (name in oldClass) {
+ if (oldClass[name] &&
+ !Object.prototype.hasOwnProperty.call(klass, name)) {
+ // was `true` and now not provided
+ elm.classList.remove(name);
}
- for (name in klass) {
- cur = klass[name];
- if (cur !== oldClass[name]) {
- elm.classList[cur ? 'add' : 'remove'](name);
- }
+ }
+ for (name in klass) {
+ cur = klass[name];
+ if (cur !== oldClass[name]) {
+ elm.classList[cur ? 'add' : 'remove'](name);
}
+ }
}
-exports.classModule = { create: updateClass, update: updateClass };
-exports.default = exports.classModule;
-
-});
-
-unwrapExports(_class);
-var _class_1 = _class.classModule;
+const classModule = { create: updateClass, update: updateClass };
-var props = createCommonjsModule(function (module, exports) {
-Object.defineProperty(exports, "__esModule", { value: true });
function updateProps(oldVnode, vnode) {
- var key, cur, old, elm = vnode.elm, oldProps = oldVnode.data.props, props = vnode.data.props;
- if (!oldProps && !props)
- return;
- if (oldProps === props)
- return;
- oldProps = oldProps || {};
- props = props || {};
- for (key in oldProps) {
- if (!props[key]) {
- delete elm[key];
- }
- }
- for (key in props) {
- cur = props[key];
- old = oldProps[key];
- if (old !== cur && (key !== 'value' || elm[key] !== cur)) {
- elm[key] = cur;
- }
+ var key;
+ var cur;
+ var old;
+ var elm = vnode.elm;
+ var oldProps = oldVnode.data.props;
+ var props = vnode.data.props;
+ if (!oldProps && !props)
+ return;
+ if (oldProps === props)
+ return;
+ oldProps = oldProps || {};
+ props = props || {};
+ for (key in props) {
+ cur = props[key];
+ old = oldProps[key];
+ if (old !== cur && (key !== 'value' || elm[key] !== cur)) {
+ elm[key] = cur;
}
+ }
}
-exports.propsModule = { create: updateProps, update: updateProps };
-exports.default = exports.propsModule;
+const propsModule = { create: updateProps, update: updateProps };
-});
-
-unwrapExports(props);
-var props_1 = props.propsModule;
-
-var style = createCommonjsModule(function (module, exports) {
-Object.defineProperty(exports, "__esModule", { value: true });
// Bindig `requestAnimationFrame` like this fixes a bug in IE/Edge. See #360 and #409.
-var raf = (typeof window !== 'undefined' && (window.requestAnimationFrame).bind(window)) || setTimeout;
-var nextFrame = function (fn) { raf(function () { raf(fn); }); };
+var raf = typeof window !== 'undefined' && window.requestAnimationFrame.bind(window) || setTimeout;
+var nextFrame = function (fn) {
+ raf(function () {
+ raf(fn);
+ });
+};
var reflowForced = false;
function setNextFrame(obj, prop, val) {
- nextFrame(function () { obj[prop] = val; });
+ nextFrame(function () {
+ obj[prop] = val;
+ });
}
function updateStyle(oldVnode, vnode) {
- var cur, name, elm = vnode.elm, oldStyle = oldVnode.data.style, style = vnode.data.style;
- if (!oldStyle && !style)
- return;
- if (oldStyle === style)
- return;
- oldStyle = oldStyle || {};
- style = style || {};
- var oldHasDel = 'delayed' in oldStyle;
- for (name in oldStyle) {
- if (!style[name]) {
- if (name[0] === '-' && name[1] === '-') {
- elm.style.removeProperty(name);
- }
- else {
- elm.style[name] = '';
- }
- }
+ var cur;
+ var name;
+ var elm = vnode.elm;
+ var oldStyle = oldVnode.data.style;
+ var style = vnode.data.style;
+ if (!oldStyle && !style)
+ return;
+ if (oldStyle === style)
+ return;
+ oldStyle = oldStyle || {};
+ style = style || {};
+ var oldHasDel = ('delayed' in oldStyle);
+ for (name in oldStyle) {
+ if (!style[name]) {
+ if (name[0] === '-' && name[1] === '-') {
+ elm.style.removeProperty(name);
+ } else
+ {
+ elm.style[name] = '';
+ }
}
- for (name in style) {
- cur = style[name];
- if (name === 'delayed' && style.delayed) {
- for (var name2 in style.delayed) {
- cur = style.delayed[name2];
- if (!oldHasDel || cur !== oldStyle.delayed[name2]) {
- setNextFrame(elm.style, name2, cur);
- }
- }
- }
- else if (name !== 'remove' && cur !== oldStyle[name]) {
- if (name[0] === '-' && name[1] === '-') {
- elm.style.setProperty(name, cur);
- }
- else {
- elm.style[name] = cur;
- }
+ }
+ for (name in style) {
+ cur = style[name];
+ if (name === 'delayed' && style.delayed) {
+ for (const name2 in style.delayed) {
+ cur = style.delayed[name2];
+ if (!oldHasDel || cur !== oldStyle.delayed[name2]) {
+ setNextFrame(elm.style, name2, cur);
}
+ }
+ } else
+ if (name !== 'remove' && cur !== oldStyle[name]) {
+ if (name[0] === '-' && name[1] === '-') {
+ elm.style.setProperty(name, cur);
+ } else
+ {
+ elm.style[name] = cur;
+ }
}
+ }
}
function applyDestroyStyle(vnode) {
- var style, name, elm = vnode.elm, s = vnode.data.style;
- if (!s || !(style = s.destroy))
- return;
- for (name in style) {
- elm.style[name] = style[name];
- }
+ var style;
+ var name;
+ var elm = vnode.elm;
+ var s = vnode.data.style;
+ if (!s || !(style = s.destroy))
+ return;
+ for (name in style) {
+ elm.style[name] = style[name];
+ }
}
function applyRemoveStyle(vnode, rm) {
- var s = vnode.data.style;
- if (!s || !s.remove) {
- rm();
- return;
- }
- if (!reflowForced) {
- vnode.elm.offsetLeft;
- reflowForced = true;
+ var s = vnode.data.style;
+ if (!s || !s.remove) {
+ rm();
+ return;
+ }
+ if (!reflowForced) {
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
+ vnode.elm.offsetLeft;
+ reflowForced = true;
+ }
+ var name;
+ var elm = vnode.elm;
+ var i = 0;
+ var compStyle;
+ var style = s.remove;
+ var amount = 0;
+ var applied = [];
+ for (name in style) {
+ applied.push(name);
+ elm.style[name] = style[name];
+ }
+ compStyle = getComputedStyle(elm);
+ var props = compStyle['transition-property'].split(', ');
+ for (; i < props.length; ++i) {
+ if (applied.indexOf(props[i]) !== -1)
+ amount++;
+ }
+ elm.addEventListener('transitionend', function (ev) {
+ if (ev.target === elm)
+ --amount;
+ if (amount === 0)
+ rm();
+ });
+}
+function forceReflow() {
+ reflowForced = false;
+}
+const styleModule = {
+ pre: forceReflow,
+ create: updateStyle,
+ update: updateStyle,
+ destroy: applyDestroyStyle,
+ remove: applyRemoveStyle };
+
+function invokeHandler(handler, vnode, event) {
+ if (typeof handler === 'function') {
+ // call function handler
+ handler.call(vnode, event, vnode);
+ } else
+ if (typeof handler === 'object') {
+ // call multiple handlers
+ for (var i = 0; i < handler.length; i++) {
+ invokeHandler(handler[i], vnode, event);
}
- var name, elm = vnode.elm, i = 0, compStyle, style = s.remove, amount = 0, applied = [];
- for (name in style) {
- applied.push(name);
- elm.style[name] = style[name];
+ }
+}
+function handleEvent(event, vnode) {
+ var name = event.type;
+ var on = vnode.data.on;
+ // call event handler(s) if exists
+ if (on && on[name]) {
+ invokeHandler(on[name], vnode, event);
+ }
+}
+function createListener() {
+ return function handler(event) {
+ handleEvent(event, handler.vnode);
+ };
+}
+function updateEventListeners(oldVnode, vnode) {
+ var oldOn = oldVnode.data.on;
+ var oldListener = oldVnode.listener;
+ var oldElm = oldVnode.elm;
+ var on = vnode && vnode.data.on;
+ var elm = vnode && vnode.elm;
+ var name;
+ // optimization for reused immutable handlers
+ if (oldOn === on) {
+ return;
+ }
+ // remove existing listeners which no longer used
+ if (oldOn && oldListener) {
+ // if element changed or deleted we remove all existing listeners unconditionally
+ if (!on) {
+ for (name in oldOn) {
+ // remove listener if element was changed or existing listeners removed
+ oldElm.removeEventListener(name, oldListener, false);
+ }
+ } else
+ {
+ for (name in oldOn) {
+ // remove listener if existing listener removed
+ if (!on[name]) {
+ oldElm.removeEventListener(name, oldListener, false);
+ }
+ }
}
- compStyle = getComputedStyle(elm);
- var props = compStyle['transition-property'].split(', ');
- for (; i < props.length; ++i) {
- if (applied.indexOf(props[i]) !== -1)
- amount++;
+ }
+ // add new listeners which has not already attached
+ if (on) {
+ // reuse existing listener or create new
+ var listener = vnode.listener = oldVnode.listener || createListener();
+ // update vnode for listener
+ listener.vnode = vnode;
+ // if element changed or added we add all needed listeners unconditionally
+ if (!oldOn) {
+ for (name in on) {
+ // add listener if element was changed or new listeners added
+ elm.addEventListener(name, listener, false);
+ }
+ } else
+ {
+ for (name in on) {
+ // add listener if new listener added
+ if (!oldOn[name]) {
+ elm.addEventListener(name, listener, false);
+ }
+ }
}
- elm.addEventListener('transitionend', function (ev) {
- if (ev.target === elm)
- --amount;
- if (amount === 0)
- rm();
- });
-}
-function forceReflow() {
- reflowForced = false;
+ }
}
-exports.styleModule = {
- pre: forceReflow,
- create: updateStyle,
- update: updateStyle,
- destroy: applyDestroyStyle,
- remove: applyRemoveStyle
-};
-exports.default = exports.styleModule;
+const eventListenersModule = {
+ create: updateEventListeners,
+ update: updateEventListeners,
+ destroy: updateEventListeners };
-});
+// Inits with common modules out of the box
-unwrapExports(style);
-var style_1 = style.styleModule;
-// Inits with common modules out of the box
-// Also easier to use across multiple files
-var snabby = create_1([
- attributes.default,
- eventlisteners.default,
- _class.default,
- props.default,
- style.default
+var index = create([
+ attributesModule,
+ eventListenersModule,
+ classModule,
+ propsModule,
+ styleModule
]);
-export default snabby;
+export default index;
diff --git a/test.js b/test.js
index 88553fa..a8b7453 100644
--- a/test.js
+++ b/test.js
@@ -1,7 +1,7 @@
-var browserEnv = require('browser-env');
-var snabby = require('./index.js')
-var h = require('snabbdom/h').default
-var test = require('tape')
+import browserEnv from 'browser-env'
+import snabby from './snabby.js'
+import { h } from 'snabbdom/h' // helper function for creating vnodes
+import test from 'tape'
browserEnv()
@@ -75,7 +75,7 @@ test('non-string attribute value', function (t) {
test('flatten array children', function (t) {
t.plan(1)
- var arr = [
+ const arr = [
snabby`1`,
snabby`2`,
]
@@ -90,16 +90,16 @@ test('flatten array children', function (t) {
test('thunk', function (t) {
t.plan(4)
- var invocationCount = 0
+ let invocationCount = 0
- var numberView = function (n) {
+ const numberView = function (n) {
invocationCount += 1
return snabby`Number is ${n}`
}
t.same(invocationCount, 0)
- var view = snabby.update(document.body, snabby`
${snabby.thunk('num', numberView, [1])}
`)
+ let view = snabby.update(document.body, snabby`