Socket
Socket
Sign inDemoInstall

snabbdom

Package Overview
Dependencies
Maintainers
5
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

snabbdom - npm Package Compare versions

Comparing version 0.7.4 to 1.0.1

build/package/h.d.ts

211

package.json
{
"name": "snabbdom",
"version": "0.7.4",
"version": "1.0.1",
"description": "A virtual DOM library with focus on simplicity, modularity, powerful features and performance.",
"main": "snabbdom.js",
"module": "es/snabbdom.js",
"typings": "snabbdom.d.ts",
"type": "module",
"exports": {
"./init": "./build/package/init.js",
"./h": "./build/package/h.js",
"./helpers/attachto": "./build/package/helpers/attachto.js",
"./hooks": "./build/package/hooks.js",
"./htmldomapi": "./build/package/htmldomapi.js",
"./is": "./build/package/is.js",
"./jsx": "./build/package/jsx.js",
"./modules/attributes": "./build/package/modules/attributes.js",
"./modules/class": "./build/package/modules/class.js",
"./modules/dataset": "./build/package/modules/dataset.js",
"./modules/eventlisteners": "./build/package/modules/eventlisteners.js",
"./modules/hero": "./build/package/modules/hero.js",
"./modules/module": "./build/package/modules/module.js",
"./modules/props": "./build/package/modules/props.js",
"./modules/style": "./build/package/modules/style.js",
"./thunk": "./build/package/thunk.js",
"./tovnode": "./build/package/tovnode.js",
"./vnode": "./build/package/vnode.js"
},
"directories": {

@@ -13,32 +31,65 @@ "example": "examples",

"devDependencies": {
"benchmark": "^2.1.4",
"browserify": "^14.4.0",
"fake-raf": "1.0.1",
"gulp": "^3.9.1",
"gulp-clean": "^0.3.2",
"gulp-rename": "^1.2.2",
"gulp-sourcemaps": "^2.6.0",
"gulp-uglify": "^3.0.0",
"husky": "^3.0.5",
"karma": "^3.0.0",
"karma-browserstack-launcher": "^1.3.0",
"karma-chrome-launcher": "^2.2.0",
"karma-firefox-launcher": "^1.2.0",
"karma-mocha": "^1.3.0",
"karma-typescript": "^3.0.13",
"knuth-shuffle": "^1.0.1",
"mocha": "^5.2.0",
"typescript": "^3.0.3",
"xyz": "2.1.0"
"@babel/core": "7.10.2",
"@babel/preset-env": "7.10.2",
"@commitlint/cli": "8.3.5",
"@commitlint/travis-cli": "9.0.1",
"@types/chai": "4.2.11",
"@types/faker": "4.1.12",
"@types/lodash.shuffle": "4.2.6",
"@types/mathjs": "6.0.5",
"@types/mocha": "7.0.2",
"@typescript-eslint/eslint-plugin": "3.3.0",
"babel-loader": "8.1.0",
"benchmark": "2.1.4",
"chai": "4.2.0",
"chalk": "4.1.0",
"core-js": "3.6.5",
"cross-env": "7.0.2",
"editorconfig-checker": "3.1.0",
"eslint": "7.2.0",
"eslint-config-standard-with-typescript": "18.0.2",
"eslint-plugin-import": "2.21.2",
"eslint-plugin-markdown": "2.0.0-alpha.0",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-promise": "4.2.1",
"eslint-plugin-standard": "4.0.1",
"faker": "4.1.0",
"husky": "4.2.5",
"is-path-inside": "3.0.2",
"karma": "5.1.0",
"karma-browserstack-launcher": "1.6.0",
"karma-chrome-launcher": "3.1.0",
"karma-firefox-launcher": "1.3.0",
"karma-mocha": "2.0.1",
"karma-mocha-reporter": "2.2.5",
"karma-webpack": "4.0.2",
"latest-snabbdom-release": "npm:snabbdom@0.7.4",
"lodash.shuffle": "4.2.0",
"mathjs": "7.0.1",
"mocha": "8.0.1",
"npm-run-all": "4.1.5",
"p-map-series": "2.1.0",
"p-reduce": "2.1.0",
"remark-cli": "8.0.0",
"remark-toc": "7.0.0",
"standard-version": "8.0.0",
"ts-transform-import-path-rewrite": "0.2.1",
"tsconfigs": "5.0.0",
"tty-table": "4.1.3",
"ttypescript": "1.5.10",
"typescript": "3.9.5",
"webpack": "4.43.0"
},
"scripts": {
"pretest": "npm run compile",
"test": "karma start",
"compile": "npm run compile-es && npm run compile-commonjs",
"compile-es": "tsc --outDir es --module es6 --moduleResolution node",
"compile-commonjs": "tsc --outDir ./",
"prepublish": "npm run compile",
"release-major": "xyz --repo git@github.com:paldepind/snabbdom.git --increment major",
"release-minor": "xyz --repo git@github.com:paldepind/snabbdom.git --increment minor",
"release-patch": "xyz --repo git@github.com:paldepind/snabbdom.git --increment patch"
"docs": "remark . --output",
"check-clean": "git diff --exit-code",
"lint:js": "eslint --ext .ts,.tsx,.cjs,.md,.mjs --ignore-path .gitignore .",
"lint:editorconfig": "editorconfig-checker",
"lint": "run-s lint:editorconfig lint:js",
"unit": "cross-env FILES_PATTERN=\"build/test/unit/**/*.js\" karma start karma.conf.cjs",
"benchmark": "cross-env FILES_PATTERN=\"build/test/benchmark/**/*.js\" karma start karma.conf.cjs --concurrency=1",
"make-release-commit": "standard-version",
"test": "run-s lint compile unit",
"compile": "ttsc --build src/test/tsconfig.json",
"prepublishOnly": "npm run compile"
},

@@ -61,8 +112,100 @@ "repository": {

},
"remarkConfig": {
"plugins": [
[
"toc",
{
"tight": true
}
]
],
"settings": {
"listItemIndent": "1",
"bullet": "*",
"tablePipeAlign": false
}
},
"homepage": "https://github.com/paldepind/snabbdom#readme",
"husky": {
"hooks": {
"pre-commit": "npm test"
"commit-msg": "commitlint --config commitlint.config.json -E HUSKY_GIT_PARAMS",
"pre-commit": "run-s docs check-clean test"
}
}
},
"files": [
"/build/package/h.d.ts",
"/build/package/h.js",
"/build/package/h.js.map",
"/build/package/helpers/attachto.d.ts",
"/build/package/helpers/attachto.js",
"/build/package/helpers/attachto.js.map",
"/build/package/hooks.d.ts",
"/build/package/hooks.js",
"/build/package/hooks.js.map",
"/build/package/htmldomapi.d.ts",
"/build/package/htmldomapi.js",
"/build/package/htmldomapi.js.map",
"/build/package/init.d.ts",
"/build/package/init.js",
"/build/package/init.js.map",
"/build/package/is.d.ts",
"/build/package/is.js",
"/build/package/is.js.map",
"/build/package/jsx-global.d.ts",
"/build/package/jsx.d.ts",
"/build/package/jsx.js",
"/build/package/jsx.js.map",
"/build/package/modules/attributes.d.ts",
"/build/package/modules/attributes.js",
"/build/package/modules/attributes.js.map",
"/build/package/modules/class.d.ts",
"/build/package/modules/class.js",
"/build/package/modules/class.js.map",
"/build/package/modules/dataset.d.ts",
"/build/package/modules/dataset.js",
"/build/package/modules/dataset.js.map",
"/build/package/modules/eventlisteners.d.ts",
"/build/package/modules/eventlisteners.js",
"/build/package/modules/eventlisteners.js.map",
"/build/package/modules/hero.d.ts",
"/build/package/modules/hero.js",
"/build/package/modules/hero.js.map",
"/build/package/modules/module.d.ts",
"/build/package/modules/module.js",
"/build/package/modules/module.js.map",
"/build/package/modules/props.d.ts",
"/build/package/modules/props.js",
"/build/package/modules/props.js.map",
"/build/package/modules/style.d.ts",
"/build/package/modules/style.js",
"/build/package/modules/style.js.map",
"/build/package/thunk.d.ts",
"/build/package/thunk.js",
"/build/package/thunk.js.map",
"/build/package/tovnode.d.ts",
"/build/package/tovnode.js",
"/build/package/tovnode.js.map",
"/build/package/vnode.d.ts",
"/build/package/vnode.js",
"/build/package/vnode.js.map",
"/src/package/h.ts",
"/src/package/helpers/attachto.ts",
"/src/package/hooks.ts",
"/src/package/htmldomapi.ts",
"/src/package/init.ts",
"/src/package/is.ts",
"/src/package/jsx-global.ts",
"/src/package/jsx.ts",
"/src/package/modules/attributes.ts",
"/src/package/modules/class.ts",
"/src/package/modules/dataset.ts",
"/src/package/modules/eventlisteners.ts",
"/src/package/modules/hero.ts",
"/src/package/modules/module.ts",
"/src/package/modules/props.ts",
"/src/package/modules/style.ts",
"/src/package/thunk.ts",
"/src/package/tovnode.ts",
"/src/package/vnode.ts"
]
}

546

README.md

@@ -1,2 +0,2 @@

<img src="logo.png" width="356px">
<img alt="Snabbdom" src="logo.png" width="356px">

@@ -6,2 +6,4 @@ A virtual DOM library with focus on simplicity, modularity, powerful features

* * *
[![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)

@@ -16,16 +18,4 @@ [![Build Status](https://travis-ci.org/snabbdom/snabbdom.svg?branch=master)](https://travis-ci.org/snabbdom/snabbdom)

## Table of contents
## Introduction
* [Introduction](#introduction)
* [Features](#features)
* [Inline example](#inline-example)
* [Examples](#examples)
* [Core documentation](#core-documentation)
* [Modules documentation](#modules-documentation)
* [Helpers](#helpers)
* [Virtual Node documentation](#virtual-node)
* [Structuring applications](#structuring-applications)
## Why
Virtual DOM is awesome. It allows us to express our application's view

@@ -36,4 +26,2 @@ as a function of its state. But existing solutions were way way too

## Introduction
Snabbdom consists of an extremely simple, performant and extensible

@@ -57,6 +45,5 @@ core that is only ≈ 200 SLOC. It offers a modular architecture with

to hook into any part of the diff and patch process.
* Splendid performance. Snabbdom is among the fastest virtual DOM libraries
in the [Virtual DOM Benchmark](http://vdom-benchmark.github.io/vdom-benchmark/).
* Splendid performance. Snabbdom is among the fastest virtual DOM libraries.
* Patch function with a function signature equivalent to a reduce/scan
function. Allows for easier integration with a FRP library.
function. Allows for easier integration with a FRP library.
* Features in modules

@@ -75,37 +62,39 @@ * `h` function for easily creating virtual DOM nodes.

## Inline example
## Example
```javascript
var snabbdom = require('snabbdom');
var patch = snabbdom.init([ // Init patch function with chosen modules
require('snabbdom/modules/class').default, // makes it easy to toggle classes
require('snabbdom/modules/props').default, // for setting properties on DOM elements
require('snabbdom/modules/style').default, // handles styling on elements with support for animations
require('snabbdom/modules/eventlisteners').default, // attaches event listeners
]);
var h = require('snabbdom/h').default; // helper function for creating vnodes
```mjs
import { init } from 'snabbdom/init'
import { classModule } from 'snabbdom/modules/class'
import { propsModule } from 'snabbdom/modules/props'
import { styleModule } from 'snabbdom/modules/style'
import { eventListenersModule } from 'snabbdom/modules/eventlisteners'
import { h } from 'snabbdom/h' // helper function for creating vnodes
var container = document.getElementById('container');
var patch = init([ // Init patch function with chosen modules
classModule, // makes it easy to toggle classes
propsModule, // for setting properties on DOM elements
styleModule, // handles styling on elements with support for animations
eventListenersModule, // attaches event listeners
])
var vnode = h('div#container.two.classes', {on: {click: someFn}}, [
h('span', {style: {fontWeight: 'bold'}}, 'This is bold'),
var container = document.getElementById('container')
var vnode = h('div#container.two.classes', { on: { click: someFn } }, [
h('span', { style: { fontWeight: 'bold' } }, 'This is bold'),
' and this is just normal text',
h('a', {props: {href: '/foo'}}, 'I\'ll take you places!')
]);
h('a', { props: { href: '/foo' } }, 'I\'ll take you places!')
])
// Patch into empty DOM element – this modifies the DOM as a side effect
patch(container, vnode);
patch(container, vnode)
var newVnode = h('div#container.two.classes', {on: {click: anotherEventHandler}}, [
h('span', {style: {fontWeight: 'normal', fontStyle: 'italic'}}, 'This is now italic type'),
var newVnode = h('div#container.two.classes', { on: { click: anotherEventHandler } }, [
h('span', { style: { fontWeight: 'normal', fontStyle: 'italic' } }, 'This is now italic type'),
' and this is still just normal text',
h('a', {props: {href: '/bar'}}, 'I\'ll take you places!')
]);
h('a', { props: { href: '/bar' } }, 'I\'ll take you places!')
])
// Second `patch` invocation
patch(vnode, newVnode); // Snabbdom efficiently updates the old view to the new state
// to unmount from the DOM and clean up, simply pass null
patch(newVnode, null)
patch(vnode, newVnode) // Snabbdom efficiently updates the old view to the new state
```
## Examples
## More examples

@@ -116,2 +105,45 @@ * [Animated reordering of elements](http://snabbdom.github.io/snabbdom/examples/reorder-animation/)

* * *
## Table of contents
* [Core documentation](#core-documentation)
* [`init`](#init)
* [`patch`](#patch)
* [Unmounting](#unmounting)
* [`snabbdom/h`](#snabbdomh)
* [`snabbdom/tovnode`](#snabbdomtovnode)
* [Hooks](#hooks)
* [Overview](#overview)
* [Usage](#usage)
* [The `init` hook](#the-init-hook)
* [The `insert` hook](#the-insert-hook)
* [The `remove` hook](#the-remove-hook)
* [The `destroy` hook](#the-destroy-hook)
* [Creating modules](#creating-modules)
* [Modules documentation](#modules-documentation)
* [The class module](#the-class-module)
* [The props module](#the-props-module)
* [The attributes module](#the-attributes-module)
* [The dataset module](#the-dataset-module)
* [The style module](#the-style-module)
* [Custom properties (CSS variables)](#custom-properties-css-variables)
* [Delayed properties](#delayed-properties)
* [Set properties on `remove`](#set-properties-on-remove)
* [Set properties on `destroy`](#set-properties-on-destroy)
* [Eventlisteners module](#eventlisteners-module)
* [SVG](#svg)
* [Classes in SVG Elements](#classes-in-svg-elements)
* [Thunks](#thunks)
* [Virtual Node](#virtual-node)
* [sel : String](#sel--string)
* [data : Object](#data--object)
* [children : Array<vnode>](#children--arrayvnode)
* [text : string](#text--string)
* [elm : Element](#elm--element)
* [key : string | number](#key--string--number)
* [Structuring applications](#structuring-applications)
* [Common errors](#common-errors)
* [Opportunity for community feedback](#opportunity-for-community-feedback)
## Core documentation

@@ -123,13 +155,13 @@

### `snabbdom.init`
### `init`
The core exposes only one single function `snabbdom.init`. This `init`
The core exposes only one single function `init`. This `init`
takes a list of modules and returns a `patch` function that uses the
specified set of modules.
```javascript
var patch = snabbdom.init([
require('snabbdom/modules/class').default,
require('snabbdom/modules/style').default,
]);
```mjs
import { classModule } from 'snabbdom/modules/class'
import { styleModule } from 'snabbdom/modules/style'
var patch = init([classModule, styleModule])
```

@@ -154,6 +186,16 @@

```javascript
patch(oldVnode, newVnode);
```mjs
patch(oldVnode, newVnode)
```
#### Unmounting
While there is no API specifically for removing a VNode tree from its mount point element, one way of almost achieving this is providing a comment VNode as the second argument to `patch`, such as:
```mjs
patch(oldVnode, h('!', { hooks: { post: () => { /* patch complete */ } } }))
```
Of course, then there is still a single comment node at the mount point.
### `snabbdom/h`

@@ -165,8 +207,9 @@

```javascript
var h = require('snabbdom/h').default;
var vnode = h('div', {style: {color: '#000'}}, [
```mjs
import { h } from 'snabbdom/h'
var vnode = h('div', { style: { color: '#000' } }, [
h('h1', 'Headline'),
h('p', 'A paragraph'),
]);
])
```

@@ -179,17 +222,22 @@

```javascript
var snabbdom = require('snabbdom')
var patch = snabbdom.init([ // Init patch function with chosen modules
require('snabbdom/modules/class').default, // makes it easy to toggle classes
require('snabbdom/modules/props').default, // for setting properties on DOM elements
require('snabbdom/modules/style').default, // handles styling on elements with support for animations
require('snabbdom/modules/eventlisteners').default, // attaches event listeners
]);
var h = require('snabbdom/h').default; // helper function for creating vnodes
var toVNode = require('snabbdom/tovnode').default;
```mjs
import { init } from 'snabbdom/init'
import { classModule } from 'snabbdom/modules/class'
import { propsModule } from 'snabbdom/modules/props'
import { styleModule } from 'snabbdom/modules/style'
import { eventListenersModule } from 'snabbdom/modules/eventlisteners'
import { h } from 'snabbdom/h' // helper function for creating vnodes
import { toVNode } from 'snabbdom/tovnode'
var newVNode = h('div', {style: {color: '#000'}}, [
var patch = init([ // Init patch function with chosen modules
classModule, // makes it easy to toggle classes
propsModule, // for setting properties on DOM elements
styleModule, // handles styling on elements with support for animations
eventListenersModule, // attaches event listeners
])
var newVNode = h('div', { style: { color: '#000' } }, [
h('h1', 'Headline'),
h('p', 'A paragraph'),
]);
])

@@ -208,14 +256,14 @@ patch(toVNode(document.querySelector('.container')), newVNode)

| Name | Triggered when | Arguments to callback |
| ----------- | -------------- | ----------------------- |
| `pre` | the patch process begins | none |
| `init` | a vnode has been added | `vnode` |
| `create` | a DOM element has been created based on a vnode | `emptyVnode, vnode` |
| `insert` | an element has been inserted into the DOM | `vnode` |
| `prepatch` | an element is about to be patched | `oldVnode, vnode` |
| `update` | an element is being updated | `oldVnode, vnode` |
| `postpatch` | an element has been patched | `oldVnode, vnode` |
| `destroy` | an element is directly or indirectly being removed | `vnode` |
| `remove` | an element is directly being removed from the DOM | `vnode, removeCallback` |
| `post` | the patch process is done | none |
| Name | Triggered when | Arguments to callback |
| - | - | - |
| `pre` | the patch process begins | none |
| `init` | a vnode has been added | `vnode` |
| `create` | a DOM element has been created based on a vnode | `emptyVnode, vnode` |
| `insert` | an element has been inserted into the DOM | `vnode` |
| `prepatch` | an element is about to be patched | `oldVnode, vnode` |
| `update` | an element is being updated | `oldVnode, vnode` |
| `postpatch` | an element has been patched | `oldVnode, vnode` |
| `destroy` | an element is directly or indirectly being removed | `vnode` |
| `remove` | an element is directly being removed from the DOM | `vnode, removeCallback` |
| `post` | the patch process is done | none |

@@ -234,9 +282,9 @@ The following hooks are available for modules: `pre`, `create`,

```javascript
```mjs
h('div.row', {
key: movie.rank,
hook: {
insert: (vnode) => { movie.elmHeight = vnode.elm.offsetHeight; }
insert: (vnode) => { movie.elmHeight = vnode.elm.offsetHeight }
}
});
})
```

@@ -281,7 +329,7 @@

```js
var vnode1 = h('div', [h('div', [h('span', 'Hello')])]);
var vnode2 = h('div', []);
patch(container, vnode1);
patch(vnode1, vnode2);
```mjs
var vnode1 = h('div', [h('div', [h('span', 'Hello')])])
var vnode2 = h('div', [])
patch(container, vnode1)
patch(vnode1, vnode2)
```

@@ -302,11 +350,11 @@

```javascript
```mjs
var myModule = {
create: function(oldVnode, vnode) {
create: function (oldVnode, vnode) {
// invoked whenever a new virtual node is created
},
update: function(oldVnode, vnode) {
update: function (oldVnode, vnode) {
// invoked whenever a virtual node is updated
}
};
}
```

@@ -329,4 +377,4 @@

```javascript
h('a', {class: {active: true, selected: false}}, 'Toggle');
```mjs
h('a', { class: { active: true, selected: false } }, 'Toggle')
```

@@ -338,6 +386,14 @@

```javascript
h('a', {props: {href: '/foo'}}, 'Go to Foo');
```mjs
h('a', { props: { href: '/foo' } }, 'Go to Foo')
```
Properties can only be set. Not removed. Even though browsers allow addition and
deletion of custom properties, deletion will not be attempted by this module.
This makes sense, because native DOM properties cannot be removed. And
if you are using custom properties for storing values or referencing
objects on the DOM, then please consider using
[data-\* attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes)
instead. Perhaps via [the dataset module](#the-dataset-module).
### The attributes module

@@ -347,4 +403,4 @@

```javascript
h('a', {attrs: {href: '/foo'}}, 'Go to Foo');
```mjs
h('a', { attrs: { href: '/foo' } }, 'Go to Foo')
```

@@ -371,4 +427,4 @@

```javascript
h('button', {dataset: {action: 'reset'}}, 'Reset');
```mjs
h('button', { dataset: { action: 'reset' } }, 'Reset')
```

@@ -381,6 +437,6 @@

```javascript
```mjs
h('span', {
style: {border: '1px solid #bada55', color: '#c0ffee', fontWeight: 'bold'}
}, 'Say my name, and every colour illuminates');
style: { border: '1px solid #bada55', color: '#c0ffee', fontWeight: 'bold' }
}, 'Say my name, and every colour illuminates')
```

@@ -392,6 +448,6 @@

```javascript
```mjs
h('div', {
style: {position: shouldFollow ? 'fixed' : ''}
}, 'I, I follow, I follow you');
style: { position: shouldFollow ? 'fixed' : '' }
}, 'I, I follow, I follow you')
```

@@ -404,6 +460,6 @@

```javascript
```mjs
h('div', {
style: {'--warnColor': 'yellow'}
}, 'Warning');
style: { '--warnColor': 'yellow' }
}, 'Warning')
```

@@ -416,6 +472,6 @@

```javascript
```mjs
h('span', {
style: {opacity: '0', transition: 'opacity 1s', delayed: {opacity: '1'}}
}, 'Imma fade right in!');
style: { opacity: '0', transition: 'opacity 1s', delayed: { opacity: '1' } }
}, 'Imma fade right in!')
```

@@ -432,7 +488,10 @@

```javascript
```mjs
h('span', {
style: {opacity: '1', transition: 'opacity 1s',
remove: {opacity: '0'}}
}, 'It\'s better to fade out than to burn away');
style: {
opacity: '1',
transition: 'opacity 1s',
remove: { opacity: '0' }
}
}, 'It\'s better to fade out than to burn away')
```

@@ -444,7 +503,10 @@

```javascript
```mjs
h('span', {
style: {opacity: '1', transition: 'opacity 1s',
destroy: {opacity: '0'}}
}, 'It\'s better to fade out than to burn away');
style: {
opacity: '1',
transition: 'opacity 1s',
destroy: { opacity: '0' }
}
}, 'It\'s better to fade out than to burn away')
```

@@ -462,5 +524,7 @@

```javascript
function clickHandler(ev) { console.log('got clicked'); }
h('div', {on: {click: clickHandler}});
```mjs
function clickHandler (ev) {
console.log('got clicked')
}
h('div', { on: { click: clickHandler } })
```

@@ -481,17 +545,24 @@

```javascript
function clickHandler(number) { console.log('button ' + number + ' was clicked!'); }
```mjs
function clickHandler (number) {
console.log('button ' + number + ' was clicked!')
}
h('div', [
h('a', {on: {click: [clickHandler, 1]}}),
h('a', {on: {click: [clickHandler, 2]}}),
h('a', {on: {click: [clickHandler, 3]}}),
]);
h('a', { on: { click: [clickHandler, 1] } }),
h('a', { on: { click: [clickHandler, 2] } }),
h('a', { on: { click: [clickHandler, 3] } }),
])
```
Each handler is called not only with the given arguments but also with the current event and vnode appended to the argument list. It also supports using multiple listeners per event by specifying an array of handlers:
```javascript
stopPropagation = function(ev) { ev.stopPropagation() }
sendValue = function(func, ev, vnode) { func(vnode.elm.value) }
h('a', { on:{ click:[[sendValue, console.log], stopPropagation] } });
```mjs
stopPropagation = function (ev) {
ev.stopPropagation()
}
sendValue = function (func, ev, vnode) {
func(vnode.elm.value)
}
h('a', { on: { click: [[sendValue, console.log], stopPropagation] } })
```

@@ -510,15 +581,21 @@

```javascript
```mjs
// Does not work
var sharedHandler = {
change: function(e){ console.log('you chose: ' + e.target.value); }
};
change: function (e) { console.log('you chose: ' + e.target.value) }
}
h('div', [
h('input', {props: {type: 'radio', name: 'test', value: '0'},
on: sharedHandler}),
h('input', {props: {type: 'radio', name: 'test', value: '1'},
on: sharedHandler}),
h('input', {props: {type: 'radio', name: 'test', value: '2'},
on: sharedHandler})
]);
h('input', {
props: { type: 'radio', name: 'test', value: '0' },
on: sharedHandler
}),
h('input', {
props: { type: 'radio', name: 'test', value: '1' },
on: sharedHandler
}),
h('input', {
props: { type: 'radio', name: 'test', value: '2' },
on: sharedHandler
})
])
```

@@ -529,19 +606,25 @@

```javascript
```mjs
// Works
var sharedHandler = function(e){ console.log('you chose: ' + e.target.value); };
var sharedHandler = function (e) {
console.log('you chose: ' + e.target.value)
}
h('div', [
h('input', {props: {type: 'radio', name: 'test', value: '0'},
on: {change: sharedHandler}}),
h('input', {props: {type: 'radio', name: 'test', value: '1'},
on: {change: sharedHandler}}),
h('input', {props: {type: 'radio', name: 'test', value: '2'},
on: {change: sharedHandler}})
]);
h('input', {
props: { type: 'radio', name: 'test', value: '0' },
on: { change: sharedHandler }
}),
h('input', {
props: { type: 'radio', name: 'test', value: '1' },
on: { change: sharedHandler }
}),
h('input', {
props: { type: 'radio', name: 'test', value: '2' },
on: { change: sharedHandler }
})
])
```
## Helpers
## SVG
### SVG
SVG just works when using the `h` function for creating virtual

@@ -551,8 +634,8 @@ nodes. SVG elements are automatically created with the appropriate

```javascript
```mjs
var vnode = h('div', [
h('svg', {attrs: {width: 100, height: 100}}, [
h('circle', {attrs: {cx: 50, cy: 50, r: 40, stroke: 'green', 'stroke-width': 4, fill: 'yellow'}})
h('svg', { attrs: { width: 100, height: 100 } }, [
h('circle', { attrs: { cx: 50, cy: 50, r: 40, stroke: 'green', 'stroke-width': 4, fill: 'yellow' } })
])
]);
])
```

@@ -562,28 +645,10 @@

#### Using Classes in SVG Elements
### Classes in SVG Elements
Certain browsers (like IE <=11) [do not support `classList` property in SVG elements](http://caniuse.com/#feat=classlist).
Hence, the _class_ module (which uses `classList` property internally) will not work for these browsers.
Certain browsers (like IE &lt;=11) [do not support `classList` property in SVG elements](http://caniuse.com/#feat=classlist).
Because the _class_ module internally uses `classList`, it will not work in this case unless you use a [classList polyfill](https://www.npmjs.com/package/classlist-polyfill).
(If you don't want to use a polyfill, you can use the `class` attribute with the _attributes_ module).
The classes in selectors for SVG elements work fine from version 0.6.7.
## Thunks
You can add dynamic classes to SVG elements for these cases by using the _attributes_ module and an Array as shown below:
```js
h('svg', [
h('text.underline', { // 'underline' is a selector class, remain unchanged between renders.
attrs: {
// 'active' and 'red' are dynamic classes, they can change between renders
// so we need to put them in the class attribute.
// (Normally we'd use the classModule, but it doesn't work inside SVG)
class: [isActive && "active", isColored && "red"].filter(Boolean).join(" ")
}
},
'Hello World'
)
])
```
### Thunks
The `thunk` function takes a selector, a key for identifying a thunk,

@@ -596,2 +661,4 @@ a function that returns a vnode and a variable amount of state

The `renderFn` is invoked only if the `renderFn` is changed or `[stateArguments]` array length or it's elements are changed.
The `key` is optional. It should be supplied when the `selector` is

@@ -606,5 +673,5 @@ not unique among the thunks siblings. This ensures that the thunk is

```js
function numberView(n) {
return h('div', 'Number is: ' + n);
```mjs
function numberView (n) {
return h('div', 'Number is: ' + n)
}

@@ -618,5 +685,5 @@ ```

```js
function render(state) {
return thunk('num', numberView, [state.number]);
```mjs
function render (state) {
return thunk('num', numberView, [state.number])
}

@@ -636,12 +703,14 @@ ```

## Virtual Node
**Properties**
- [sel](#sel--string)
- [data](#data--object)
- [children](#children--array)
- [text](#text--string)
- [elm](#elm--element)
- [key](#key--string--number)
#### sel : String
* [sel](#sel--string)
* [data](#data--object)
* [children](#children--array)
* [text](#text--string)
* [elm](#elm--element)
* [key](#key--string--number)
### sel : String
The `.sel` property of a virtual node is the CSS selector passed to

@@ -652,3 +721,3 @@ [`h()`](#snabbdomh) during creation. For example: `h('div#container',

#### data : Object
### data : Object

@@ -663,12 +732,14 @@ The `.data` property of a virtual node is the place to add information

For example `h('div', {props: {className: 'container'}}, [...])` will produce a virtual node with
```js
{
"props": {
className: "container"
```mjs
({
props: {
className: 'container'
}
}
})
```
as its `.data` object.
#### children : Array<vnode>
### children : Array<vnode>

@@ -683,12 +754,12 @@ The `.children` property of a virtual node is the third (optional)

```js
```mjs
[
{
sel: 'h1',
data: {},
children: undefined,
text: 'Hello, World',
elm: Element,
key: undefined,
}
{
sel: 'h1',
data: {},
children: undefined,
text: 'Hello, World',
elm: Element,
key: undefined,
}
]

@@ -699,3 +770,3 @@ ```

#### text : string
### text : string

@@ -709,3 +780,3 @@ The `.text` property is created when a virtual node is created with

#### elm : Element
### elm : Element

@@ -717,3 +788,3 @@ The `.elm` property of a virtual node is a pointer to the real DOM

#### key : string | number
### key : string | number

@@ -729,6 +800,7 @@ The `.key` property is created when a key is provided inside of your

If provided, the `.key` property must be unique among sibling elements.
For example: `h('div', {key: 1}, [])` will create a virtual node
object with a `.key` property with the value of `1`.
## Structuring applications

@@ -745,7 +817,7 @@

* [Cycle.js](https://cycle.js.org/) –
"A functional and reactive JavaScript framework for cleaner code"
uses Snabbdom
"A functional and reactive JavaScript framework for cleaner code"
uses Snabbdom
* [Vue.js](http://vuejs.org/) use a fork of snabbdom.
* [scheme-todomvc](https://github.com/amirouche/scheme-todomvc/) build
redux-like architecture on top of snabbdom bindings.
redux-like architecture on top of snabbdom bindings.
* [kaiju](https://github.com/AlexGalays/kaiju) -

@@ -767,2 +839,3 @@ Stateful components and observables on top of snabbdom

* [Pureact](https://github.com/irony/pureact) - "65 lines implementation of React incl Redux and hooks with only one dependency - Snabbdom"
* [Snabberb](https://github.com/tobymao/snabberb) - A minimalistic Ruby framework using [Opal](https://github.com/opal/opal) and Snabbdom for building reactive views.

@@ -774,9 +847,11 @@ Be sure to share it if you're building an application in another way

```
```text
Uncaught NotFoundError: Failed to execute 'insertBefore' on 'Node':
The node before which the new node is to be inserted is not a child of this node.
```
The reason for this error is reusing of vnodes between patches (see code example), snabbdom stores actual dom nodes inside the virtual dom nodes passed to it as performance improvement, so reusing nodes between patches is not supported.
```js
var sharedNode = h('div', {}, 'Selected');
```mjs
var sharedNode = h('div', {}, 'Selected')
var vnode1 = h('div', [

@@ -786,3 +861,3 @@ h('div', {}, ['One']),

h('div', {}, [sharedNode]),
]);
])
var vnode2 = h('div', [

@@ -792,8 +867,10 @@ h('div', {}, ['One']),

h('div', {}, ['Three']),
]);
patch(container, vnode1);
patch(vnode1, vnode2);
])
patch(container, vnode1)
patch(vnode1, vnode2)
```
You can fix this issue by creating a shallow copy of the object (here with object spread syntax):
```js
```mjs
var vnode2 = h('div', [

@@ -803,7 +880,9 @@ h('div', {}, ['One']),

h('div', {}, ['Three']),
]);
])
```
Another solution would be to wrap shared vnodes in a factory function:
```js
var sharedNode = () => h('div', {}, 'Selected');
```mjs
var sharedNode = () => h('div', {}, 'Selected')
var vnode1 = h('div', [

@@ -813,3 +892,8 @@ h('div', {}, ['One']),

h('div', {}, [sharedNode()]),
]);
])
```
## Opportunity for community feedback
Pull requests that the community may care to provide feedback on should be
merged after such opportunity of a few days was provided.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc