chore(refactor): format code with prettier
parent
8d0a666182
commit
37f58835fa
@ -1,47 +1,55 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: [
|
||||
'@typescript-eslint'
|
||||
],
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["@typescript-eslint"],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'prettier',
|
||||
'prettier/@typescript-eslint'
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier",
|
||||
"prettier/@typescript-eslint",
|
||||
],
|
||||
env: {
|
||||
browser: true,
|
||||
node: false,
|
||||
},
|
||||
overrides: [{
|
||||
files: ['*.ts', '*.tsx'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: ['./tsconfig.json', 'test/tsconfig.json']
|
||||
overrides: [
|
||||
{
|
||||
files: ["*.ts", "*.tsx"],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: ["./tsconfig.json", "test/tsconfig.json"],
|
||||
},
|
||||
extends: [
|
||||
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
||||
],
|
||||
rules: {
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-unsafe-member-access": "off",
|
||||
"@typescript-eslint/no-unsafe-assignment": "off",
|
||||
"@typescript-eslint/no-unsafe-call": "off",
|
||||
"@typescript-eslint/no-unsafe-return": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["test/**/*.ts"],
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
},
|
||||
},
|
||||
extends: ['plugin:@typescript-eslint/recommended-requiring-type-checking'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-unsafe-member-access': 'off',
|
||||
'@typescript-eslint/no-unsafe-assignment': 'off',
|
||||
'@typescript-eslint/no-unsafe-call': 'off',
|
||||
'@typescript-eslint/no-unsafe-return': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off'
|
||||
}
|
||||
}, {
|
||||
files: ['test/**/*.ts'],
|
||||
env: {
|
||||
browser: true,
|
||||
node: true
|
||||
}
|
||||
}, {
|
||||
files: ['*.js'],
|
||||
excludedFiles: ['examples/**'],
|
||||
extends: ['plugin:node/recommended'],
|
||||
env: {
|
||||
node: true,
|
||||
browser: false
|
||||
}
|
||||
}],
|
||||
{
|
||||
files: ["*.js"],
|
||||
excludedFiles: ["examples/**"],
|
||||
extends: ["plugin:node/recommended"],
|
||||
env: {
|
||||
node: true,
|
||||
browser: false,
|
||||
},
|
||||
rules: {
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@ -1,29 +1,31 @@
|
||||
{
|
||||
"extends": [
|
||||
"@commitlint/config-conventional"
|
||||
],
|
||||
"extends": ["@commitlint/config-conventional"],
|
||||
"rules": {
|
||||
"scope-empty": [2, "never"],
|
||||
"scope-enum": [2, "always", [
|
||||
"ci",
|
||||
"commitlint",
|
||||
"deps",
|
||||
"docs",
|
||||
"eslint",
|
||||
"eventlisteners",
|
||||
"examples",
|
||||
"exports",
|
||||
"format",
|
||||
"git",
|
||||
"github",
|
||||
"karma",
|
||||
"npm",
|
||||
"package",
|
||||
"relic",
|
||||
"style",
|
||||
"ttypescript",
|
||||
"typescript",
|
||||
"vscode"
|
||||
]]
|
||||
"scope-enum": [
|
||||
2,
|
||||
"always",
|
||||
[
|
||||
"ci",
|
||||
"commitlint",
|
||||
"deps",
|
||||
"docs",
|
||||
"eslint",
|
||||
"eventlisteners",
|
||||
"examples",
|
||||
"exports",
|
||||
"format",
|
||||
"git",
|
||||
"github",
|
||||
"karma",
|
||||
"npm",
|
||||
"package",
|
||||
"relic",
|
||||
"style",
|
||||
"ttypescript",
|
||||
"typescript",
|
||||
"vscode"
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,74 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<meta charset="utf-8">
|
||||
<title>Carousel</title>
|
||||
<script type="module" src="./index.js"></script>
|
||||
<style type="text/css">
|
||||
div.view {
|
||||
margin: 10px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
color: #505000;
|
||||
}
|
||||
svg {
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid gray;
|
||||
}
|
||||
g#carousel {
|
||||
-webkit-transition: -webkit-transform 1s ease;
|
||||
transition: transform 1s ease;
|
||||
}
|
||||
polygon {
|
||||
stroke: #808000;
|
||||
transition: fill 0.5s linear;
|
||||
}
|
||||
polygon#yellow {
|
||||
fill: rgba(255,255,0,0.4);
|
||||
}
|
||||
polygon#yellow:hover, polygon#yellow:active {
|
||||
fill: yellow;
|
||||
}
|
||||
polygon#green {
|
||||
fill: rgba(0,128,0,0.4);
|
||||
}
|
||||
polygon#green:hover, polygon#green:active {
|
||||
fill: green;
|
||||
}
|
||||
polygon#magenta {
|
||||
fill: rgba(255,0,255,0.4);
|
||||
}
|
||||
polygon#magenta:hover, polygon#magenta:active {
|
||||
fill: magenta;
|
||||
}
|
||||
polygon#red {
|
||||
fill: rgba(255,0,0,0.4);
|
||||
}
|
||||
polygon#red:hover, polygon#red:active {
|
||||
fill: red;
|
||||
}
|
||||
polygon#cyan {
|
||||
fill: rgba(0,255,255,0.4);
|
||||
}
|
||||
polygon#cyan:hover, polygon#cyan:active {
|
||||
fill: cyan;
|
||||
}
|
||||
polygon#blue {
|
||||
fill: rgba(0,0,255,0.4);
|
||||
}
|
||||
polygon#blue:hover, polygon#blue:active {
|
||||
fill: blue;
|
||||
}
|
||||
button {
|
||||
font-size: 15px;
|
||||
margin: 0 0.7em 0.7em 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
</body>
|
||||
<head>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||
/>
|
||||
<meta charset="utf-8" />
|
||||
<title>Carousel</title>
|
||||
<script type="module" src="./index.js"></script>
|
||||
<style type="text/css">
|
||||
div.view {
|
||||
margin: 10px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
color: #505000;
|
||||
}
|
||||
svg {
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid gray;
|
||||
}
|
||||
g#carousel {
|
||||
-webkit-transition: -webkit-transform 1s ease;
|
||||
transition: transform 1s ease;
|
||||
}
|
||||
polygon {
|
||||
stroke: #808000;
|
||||
transition: fill 0.5s linear;
|
||||
}
|
||||
polygon#yellow {
|
||||
fill: rgba(255, 255, 0, 0.4);
|
||||
}
|
||||
polygon#yellow:hover,
|
||||
polygon#yellow:active {
|
||||
fill: yellow;
|
||||
}
|
||||
polygon#green {
|
||||
fill: rgba(0, 128, 0, 0.4);
|
||||
}
|
||||
polygon#green:hover,
|
||||
polygon#green:active {
|
||||
fill: green;
|
||||
}
|
||||
polygon#magenta {
|
||||
fill: rgba(255, 0, 255, 0.4);
|
||||
}
|
||||
polygon#magenta:hover,
|
||||
polygon#magenta:active {
|
||||
fill: magenta;
|
||||
}
|
||||
polygon#red {
|
||||
fill: rgba(255, 0, 0, 0.4);
|
||||
}
|
||||
polygon#red:hover,
|
||||
polygon#red:active {
|
||||
fill: red;
|
||||
}
|
||||
polygon#cyan {
|
||||
fill: rgba(0, 255, 255, 0.4);
|
||||
}
|
||||
polygon#cyan:hover,
|
||||
polygon#cyan:active {
|
||||
fill: cyan;
|
||||
}
|
||||
polygon#blue {
|
||||
fill: rgba(0, 0, 255, 0.4);
|
||||
}
|
||||
polygon#blue:hover,
|
||||
polygon#blue:active {
|
||||
fill: blue;
|
||||
}
|
||||
button {
|
||||
font-size: 15px;
|
||||
margin: 0 0.7em 0.7em 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,74 +1,117 @@
|
||||
import { init } from '../../build/package/init.js'
|
||||
import { attributesModule } from '../../build/package/modules/attributes.js'
|
||||
import { styleModule } from '../../build/package/modules/style.js'
|
||||
import { eventListenersModule } from '../../build/package/modules/eventlisteners.js'
|
||||
import { h } from '../../build/package/h.js'
|
||||
import { init } from "../../build/package/init.js";
|
||||
import { attributesModule } from "../../build/package/modules/attributes.js";
|
||||
import { styleModule } from "../../build/package/modules/style.js";
|
||||
import { eventListenersModule } from "../../build/package/modules/eventlisteners.js";
|
||||
import { h } from "../../build/package/h.js";
|
||||
|
||||
var patch = init([attributesModule, styleModule, eventListenersModule])
|
||||
var patch = init([attributesModule, styleModule, eventListenersModule]);
|
||||
|
||||
var vnode
|
||||
var vnode;
|
||||
|
||||
var data = {
|
||||
degRotation: 0
|
||||
}
|
||||
degRotation: 0,
|
||||
};
|
||||
|
||||
function gRotation () {
|
||||
function gRotation() {
|
||||
// console.log("gRotation: %s", data.degRotation);
|
||||
return 'rotate(' + data.degRotation + 'deg)'
|
||||
return "rotate(" + data.degRotation + "deg)";
|
||||
}
|
||||
|
||||
function triangleClick (id) {
|
||||
console.log('triangleClick: %s', id)
|
||||
render()
|
||||
function triangleClick(id) {
|
||||
console.log("triangleClick: %s", id);
|
||||
render();
|
||||
}
|
||||
|
||||
function handleRotate (degs) {
|
||||
data.degRotation += degs
|
||||
console.log('handleRotate: %s, %s', degs, data.degRotation)
|
||||
render()
|
||||
function handleRotate(degs) {
|
||||
data.degRotation += degs;
|
||||
console.log("handleRotate: %s, %s", degs, data.degRotation);
|
||||
render();
|
||||
}
|
||||
|
||||
function handleReset (degs) {
|
||||
data.degRotation = degs
|
||||
console.log('handleReset: %s', degs)
|
||||
render()
|
||||
function handleReset(degs) {
|
||||
data.degRotation = degs;
|
||||
console.log("handleReset: %s", degs);
|
||||
render();
|
||||
}
|
||||
|
||||
function render () {
|
||||
vnode = patch(vnode, view(data))
|
||||
function render() {
|
||||
vnode = patch(vnode, view(data));
|
||||
}
|
||||
|
||||
const hTriangle = (id, degRotation) =>
|
||||
h('polygon#' + id, {
|
||||
h("polygon#" + id, {
|
||||
attrs: {
|
||||
points: '-50,-88 0,-175 50,-88',
|
||||
transform: 'rotate(' + degRotation + ')',
|
||||
'stroke-width': 3
|
||||
points: "-50,-88 0,-175 50,-88",
|
||||
transform: "rotate(" + degRotation + ")",
|
||||
"stroke-width": 3,
|
||||
},
|
||||
on: {
|
||||
click: () => {
|
||||
triangleClick(id);
|
||||
},
|
||||
},
|
||||
on: { click: () => { triangleClick(id) } }
|
||||
})
|
||||
});
|
||||
|
||||
const view = (data) =>
|
||||
h('div.view', [
|
||||
h('h1', 'Snabbdom SVG Carousel'),
|
||||
h('svg', { attrs: { width: 380, height: 380, viewBox: [-190, -190, 380, 380] } }, [
|
||||
h('g#carousel',
|
||||
{ style: { '-webkit-transform': gRotation(), transform: gRotation() } }, [
|
||||
hTriangle('yellow', 0),
|
||||
hTriangle('green', 60),
|
||||
hTriangle('magenta', 120),
|
||||
hTriangle('red', 180),
|
||||
hTriangle('cyan', 240),
|
||||
hTriangle('blue', 300)
|
||||
])
|
||||
]),
|
||||
h('button', { on: { click: () => { handleRotate(60) } } }, 'Rotate Clockwise'),
|
||||
h('button', { on: { click: () => { handleRotate(-60) } } }, 'Rotate Anticlockwise'),
|
||||
h('button', { on: { click: () => { handleReset(0) } } }, 'Reset')
|
||||
])
|
||||
const view = () =>
|
||||
h("div.view", [
|
||||
h("h1", "Snabbdom SVG Carousel"),
|
||||
h(
|
||||
"svg",
|
||||
{ attrs: { width: 380, height: 380, viewBox: [-190, -190, 380, 380] } },
|
||||
[
|
||||
h(
|
||||
"g#carousel",
|
||||
{
|
||||
style: { "-webkit-transform": gRotation(), transform: gRotation() },
|
||||
},
|
||||
[
|
||||
hTriangle("yellow", 0),
|
||||
hTriangle("green", 60),
|
||||
hTriangle("magenta", 120),
|
||||
hTriangle("red", 180),
|
||||
hTriangle("cyan", 240),
|
||||
hTriangle("blue", 300),
|
||||
]
|
||||
),
|
||||
]
|
||||
),
|
||||
h(
|
||||
"button",
|
||||
{
|
||||
on: {
|
||||
click: () => {
|
||||
handleRotate(60);
|
||||
},
|
||||
},
|
||||
},
|
||||
"Rotate Clockwise"
|
||||
),
|
||||
h(
|
||||
"button",
|
||||
{
|
||||
on: {
|
||||
click: () => {
|
||||
handleRotate(-60);
|
||||
},
|
||||
},
|
||||
},
|
||||
"Rotate Anticlockwise"
|
||||
),
|
||||
h(
|
||||
"button",
|
||||
{
|
||||
on: {
|
||||
click: () => {
|
||||
handleReset(0);
|
||||
},
|
||||
},
|
||||
},
|
||||
"Reset"
|
||||
),
|
||||
]);
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
var container = document.getElementById('container')
|
||||
vnode = patch(container, view(data))
|
||||
render()
|
||||
})
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
var container = document.getElementById("container");
|
||||
vnode = patch(container, view(data));
|
||||
render();
|
||||
});
|
||||
|
@ -1,136 +1,233 @@
|
||||
/* jshint esnext: true */
|
||||
import { init } from '../../build/package/init.js'
|
||||
import { classModule } from '../../build/package/modules/class.js'
|
||||
import { heroModule } from '../../build/package/modules/hero.js'
|
||||
import { styleModule } from '../../build/package/modules/style.js'
|
||||
import { eventListenersModule } from '../../build/package/modules/eventlisteners.js'
|
||||
import { h } from '../../build/package/h.js'
|
||||
import { init } from "../../build/package/init.js";
|
||||
import { classModule } from "../../build/package/modules/class.js";
|
||||
import { heroModule } from "../../build/package/modules/hero.js";
|
||||
import { styleModule } from "../../build/package/modules/style.js";
|
||||
import { eventListenersModule } from "../../build/package/modules/eventlisteners.js";
|
||||
import { h } from "../../build/package/h.js";
|
||||
|
||||
var patch = init([classModule, heroModule, styleModule, eventListenersModule])
|
||||
var patch = init([classModule, heroModule, styleModule, eventListenersModule]);
|
||||
|
||||
var vnode
|
||||
var vnode;
|
||||
|
||||
var data = {
|
||||
selected: undefined,
|
||||
movies: [
|
||||
{ rank: 1, title: 'This is an', desc: 'Lorem ipsum dolor sit amet, sed pede integer vitae bibendum, accumsan sit, vulputate aenean tempora ipsum. Lorem sed id et metus, eros posuere suspendisse nec nunc justo, fusce augue placerat nibh purus suspendisse. Aliquam aliquam, ut eget. Mollis a eget sed nibh tincidunt nec, mi integer, proin magna lacus iaculis tortor. Aliquam vel arcu arcu, vivamus a urna fames felis vel wisi, cursus tortor nec erat dignissim cras sem, mauris ac venenatis tellus elit.' },
|
||||
{ rank: 2, title: 'example of', desc: 'Consequuntur ipsum nulla, consequat curabitur in magnis risus. Taciti mattis bibendum tellus nibh, at dui neque eget, odio pede ut, sapien pede, ipsum ut. Sagittis dui, sodales sem, praesent ipsum conubia eget lorem lobortis wisi.' },
|
||||
{ rank: 3, title: 'Snabbdom', desc: 'Quam lorem aliquam fusce wisi, urna purus ipsum pharetra sed, at cras sodales enim vestibulum odio cras, luctus integer phasellus.' },
|
||||
{ rank: 4, title: 'doing hero transitions', desc: 'Et orci hac ultrices id in. Diam ultrices luctus egestas, sem aliquam auctor molestie odio laoreet. Pede nam cubilia, diam vestibulum ornare natoque, aenean etiam fusce id, eget dictum blandit et mauris mauris. Metus amet ad, elit porttitor a aliquet commodo lacus, integer neque imperdiet augue laoreet, nonummy turpis lacus sed pulvinar condimentum platea. Wisi eleifend quis, tristique dictum, ac dictumst. Sem nec tristique vel vehicula fringilla, nibh eu et posuere mi rhoncus.' },
|
||||
{ rank: 5, title: 'using the', desc: 'Pede nam cubilia, diam vestibulum ornare natoque, aenean etiam fusce id, eget dictum blandit et mauris mauris. Metus amet ad, elit porttitor a aliquet commodo lacus, integer neque imperdiet augue laoreet, nonummy turpis lacus sed pulvinar condimentum platea. Wisi eleifend quis, tristique dictum, ac dictumst. Sem nec tristique vel vehicula fringilla, nibh eu et posuere mi rhoncus.' },
|
||||
{ rank: 6, title: 'module for hero transitions', desc: 'Sapien laoreet, ligula elit tortor nulla pellentesque, maecenas enim turpis, quae duis venenatis vivamus ultricies, nunc imperdiet sollicitudin ipsum malesuada. Ut sem. Wisi fusce nullam nibh enim. Nisl hymenaeos id sed sed in. Proin leo et, pulvinar nunc pede laoreet.' },
|
||||
{ rank: 7, title: 'click on ar element in', desc: 'Accumsan quia, id nascetur dui et congue erat, id excepteur, primis ratione nec. At nulla et. Suspendisse lobortis, lobortis in tortor fringilla, duis adipiscing vestibulum voluptates sociosqu auctor.' },
|
||||
{ rank: 8, title: 'the list', desc: 'Ante tellus egestas vel hymenaeos, ut viverra nibh ut, ipsum nibh donec donec dolor. Eros ridiculus vel egestas convallis ipsum, commodo ut venenatis nullam porta iaculis, suspendisse ante proin leo, felis risus etiam.' },
|
||||
{ rank: 9, title: 'to witness', desc: 'Metus amet ad, elit porttitor a aliquet commodo lacus, integer neque imperdiet augue laoreet, nonummy turpis lacus sed pulvinar condimentum platea. Wisi eleifend quis, tristique dictum, ac dictumst.' },
|
||||
{ rank: 10, title: 'the effect', desc: 'Et orci hac ultrices id in. Diam ultrices luctus egestas, sem aliquam auctor molestie odio laoreet. Pede nam cubilia, diam vestibulum ornare natoque, aenean etiam fusce id, eget dictum blandit et mauris mauris' },
|
||||
]
|
||||
}
|
||||
{
|
||||
rank: 1,
|
||||
title: "This is an",
|
||||
desc:
|
||||
"Lorem ipsum dolor sit amet, sed pede integer vitae bibendum, accumsan sit, vulputate aenean tempora ipsum. Lorem sed id et metus, eros posuere suspendisse nec nunc justo, fusce augue placerat nibh purus suspendisse. Aliquam aliquam, ut eget. Mollis a eget sed nibh tincidunt nec, mi integer, proin magna lacus iaculis tortor. Aliquam vel arcu arcu, vivamus a urna fames felis vel wisi, cursus tortor nec erat dignissim cras sem, mauris ac venenatis tellus elit.",
|
||||
},
|
||||
{
|
||||
rank: 2,
|
||||
title: "example of",
|
||||
desc:
|
||||
"Consequuntur ipsum nulla, consequat curabitur in magnis risus. Taciti mattis bibendum tellus nibh, at dui neque eget, odio pede ut, sapien pede, ipsum ut. Sagittis dui, sodales sem, praesent ipsum conubia eget lorem lobortis wisi.",
|
||||
},
|
||||
{
|
||||
rank: 3,
|
||||
title: "Snabbdom",
|
||||
desc:
|
||||
"Quam lorem aliquam fusce wisi, urna purus ipsum pharetra sed, at cras sodales enim vestibulum odio cras, luctus integer phasellus.",
|
||||
},
|
||||
{
|
||||
rank: 4,
|
||||
title: "doing hero transitions",
|
||||
desc:
|
||||
"Et orci hac ultrices id in. Diam ultrices luctus egestas, sem aliquam auctor molestie odio laoreet. Pede nam cubilia, diam vestibulum ornare natoque, aenean etiam fusce id, eget dictum blandit et mauris mauris. Metus amet ad, elit porttitor a aliquet commodo lacus, integer neque imperdiet augue laoreet, nonummy turpis lacus sed pulvinar condimentum platea. Wisi eleifend quis, tristique dictum, ac dictumst. Sem nec tristique vel vehicula fringilla, nibh eu et posuere mi rhoncus.",
|
||||
},
|
||||
{
|
||||
rank: 5,
|
||||
title: "using the",
|
||||
desc:
|
||||
"Pede nam cubilia, diam vestibulum ornare natoque, aenean etiam fusce id, eget dictum blandit et mauris mauris. Metus amet ad, elit porttitor a aliquet commodo lacus, integer neque imperdiet augue laoreet, nonummy turpis lacus sed pulvinar condimentum platea. Wisi eleifend quis, tristique dictum, ac dictumst. Sem nec tristique vel vehicula fringilla, nibh eu et posuere mi rhoncus.",
|
||||
},
|
||||
{
|
||||
rank: 6,
|
||||
title: "module for hero transitions",
|
||||
desc:
|
||||
"Sapien laoreet, ligula elit tortor nulla pellentesque, maecenas enim turpis, quae duis venenatis vivamus ultricies, nunc imperdiet sollicitudin ipsum malesuada. Ut sem. Wisi fusce nullam nibh enim. Nisl hymenaeos id sed sed in. Proin leo et, pulvinar nunc pede laoreet.",
|
||||
},
|
||||
{
|
||||
rank: 7,
|
||||
title: "click on ar element in",
|
||||
desc:
|
||||
"Accumsan quia, id nascetur dui et congue erat, id excepteur, primis ratione nec. At nulla et. Suspendisse lobortis, lobortis in tortor fringilla, duis adipiscing vestibulum voluptates sociosqu auctor.",
|
||||
},
|
||||
{
|
||||
rank: 8,
|
||||
title: "the list",
|
||||
desc:
|
||||
"Ante tellus egestas vel hymenaeos, ut viverra nibh ut, ipsum nibh donec donec dolor. Eros ridiculus vel egestas convallis ipsum, commodo ut venenatis nullam porta iaculis, suspendisse ante proin leo, felis risus etiam.",
|
||||
},
|
||||
{
|
||||
rank: 9,
|
||||
title: "to witness",
|
||||
desc:
|
||||
"Metus amet ad, elit porttitor a aliquet commodo lacus, integer neque imperdiet augue laoreet, nonummy turpis lacus sed pulvinar condimentum platea. Wisi eleifend quis, tristique dictum, ac dictumst.",
|
||||
},
|
||||
{
|
||||
rank: 10,
|
||||
title: "the effect",
|
||||
desc:
|
||||
"Et orci hac ultrices id in. Diam ultrices luctus egestas, sem aliquam auctor molestie odio laoreet. Pede nam cubilia, diam vestibulum ornare natoque, aenean etiam fusce id, eget dictum blandit et mauris mauris",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
function select (m) {
|
||||
data.selected = m
|
||||
render()
|
||||
function select(m) {
|
||||
data.selected = m;
|
||||
render();
|
||||
}
|
||||
|
||||
function render () {
|
||||
vnode = patch(vnode, view(data))
|
||||
function render() {
|
||||
vnode = patch(vnode, view(data));
|
||||
}
|
||||
|
||||
const fadeInOutStyle = {
|
||||
opacity: '0', delayed: { opacity: '1' }, remove: { opacity: '0' }
|
||||
}
|
||||
opacity: "0",
|
||||
delayed: { opacity: "1" },
|
||||
remove: { opacity: "0" },
|
||||
};
|
||||
|
||||
const detailView = (movie) =>
|
||||
h('div.page', { style: fadeInOutStyle }, [
|
||||
h('div.header', [
|
||||
h('div.header-content.detail', {
|
||||
style: { opacity: '1', remove: { opacity: '0' } },
|
||||
}, [
|
||||
h('div.rank', [
|
||||
h('span.header-rank.hero', { hero: { id: 'rank' + movie.rank } }, movie.rank),
|
||||
h('div.rank-circle', {
|
||||
style: {
|
||||
transform: 'scale(0)',
|
||||
delayed: { transform: 'scale(1)' },
|
||||
destroy: { transform: 'scale(0)' }
|
||||
h("div.page", { style: fadeInOutStyle }, [
|
||||
h("div.header", [
|
||||
h(
|
||||
"div.header-content.detail",
|
||||
{
|
||||
style: { opacity: "1", remove: { opacity: "0" } },
|
||||
},
|
||||
[
|
||||
h("div.rank", [
|
||||
h(
|
||||
"span.header-rank.hero",
|
||||
{ hero: { id: "rank" + movie.rank } },
|
||||
movie.rank
|
||||
),
|
||||
h("div.rank-circle", {
|
||||
style: {
|
||||
transform: "scale(0)",
|
||||
delayed: { transform: "scale(1)" },
|
||||
destroy: { transform: "scale(0)" },
|
||||
},
|
||||
}),
|
||||
]),
|
||||
h(
|
||||
"div.hero.header-title",
|
||||
{ hero: { id: movie.title } },
|
||||
movie.title
|
||||
),
|
||||
h("div.spacer"),
|
||||
h(
|
||||
"div.close",
|
||||
{
|
||||
on: {
|
||||
click: () => {
|
||||
select(undefined);
|
||||
},
|
||||
},
|
||||
style: {
|
||||
transform: "scale(0)",
|
||||
delayed: { transform: "scale(1)" },
|
||||
destroy: { transform: "scale(0)" },
|
||||
},
|
||||
},
|
||||
}),
|
||||
]),
|
||||
h('div.hero.header-title', { hero: { id: movie.title } }, movie.title),
|
||||
h('div.spacer'),
|
||||
h('div.close', {
|
||||
on: { click: () => { select(undefined) } },
|
||||
"x"
|
||||
),
|
||||
]
|
||||
),
|
||||
]),
|
||||
h("div.page-content", [
|
||||
h(
|
||||
"div.desc",
|
||||
{
|
||||
style: {
|
||||
transform: 'scale(0)',
|
||||
delayed: { transform: 'scale(1)' },
|
||||
destroy: { transform: 'scale(0)' }
|
||||
opacity: "0",
|
||||
transform: "translateX(3em)",
|
||||
delayed: { opacity: "1", transform: "translate(0)" },
|
||||
remove: {
|
||||
opacity: "0",
|
||||
position: "absolute",
|
||||
top: "0",
|
||||
left: "0",
|
||||
transform: "translateX(3em)",
|
||||
},
|
||||
},
|
||||
}, 'x'),
|
||||
]),
|
||||
]),
|
||||
h('div.page-content', [
|
||||
h('div.desc', {
|
||||
style: {
|
||||
opacity: '0',
|
||||
transform: 'translateX(3em)',
|
||||
delayed: { opacity: '1', transform: 'translate(0)' },
|
||||
remove: {
|
||||
opacity: '0',
|
||||
position: 'absolute',
|
||||
top: '0',
|
||||
left: '0',
|
||||
transform: 'translateX(3em)'
|
||||
}
|
||||
}
|
||||
}, [
|
||||
h('h2', 'Description:'),
|
||||
h('span', movie.desc),
|
||||
]),
|
||||
},
|
||||
[h("h2", "Description:"), h("span", movie.desc)]
|
||||
),
|
||||
]),
|
||||
])
|
||||
]);
|
||||
|
||||
const overviewView = (movies) =>
|
||||
h('div.page', { style: fadeInOutStyle }, [
|
||||
h('div.header', [
|
||||
h('div.header-content.overview', {
|
||||
style: fadeInOutStyle,
|
||||
}, [
|
||||
h('div.header-title', {
|
||||
style: {
|
||||
transform: 'translateY(-2em)',
|
||||
delayed: { transform: 'translate(0)' },
|
||||
destroy: { transform: 'translateY(-2em)' }
|
||||
}
|
||||
}, 'Top 10 movies'),
|
||||
h('div.spacer'),
|
||||
]),
|
||||
h("div.page", { style: fadeInOutStyle }, [
|
||||
h("div.header", [
|
||||
h(
|
||||
"div.header-content.overview",
|
||||
{
|
||||
style: fadeInOutStyle,
|
||||
},
|
||||
[
|
||||
h(
|
||||
"div.header-title",
|
||||
{
|
||||
style: {
|
||||
transform: "translateY(-2em)",
|
||||
delayed: { transform: "translate(0)" },
|
||||
destroy: { transform: "translateY(-2em)" },
|
||||
},
|
||||
},
|
||||
"Top 10 movies"
|
||||
),
|
||||
h("div.spacer"),
|
||||
]
|
||||
),
|
||||
]),
|
||||
h('div.page-content', [
|
||||
h('div.list', {
|
||||
style: {
|
||||
opacity: '0',
|
||||
delayed: { opacity: '1' },
|
||||
remove: { opacity: '0', position: 'absolute', top: '0', left: '0' }
|
||||
}
|
||||
}, movies.map((movie) =>
|
||||
h('div.row', {
|
||||
on: { click: () => { select(movie) } },
|
||||
}, [
|
||||
h('div.hero.rank', [
|
||||
h('span.hero', { hero: { id: 'rank' + movie.rank } }, movie.rank)
|
||||
]),
|
||||
h('div.hero', { hero: { id: movie.title } }, movie.title)
|
||||
])
|
||||
)),
|
||||
h("div.page-content", [
|
||||
h(
|
||||
"div.list",
|
||||
{
|
||||
style: {
|
||||
opacity: "0",
|
||||
delayed: { opacity: "1" },
|
||||
remove: { opacity: "0", position: "absolute", top: "0", left: "0" },
|
||||
},
|
||||
},
|
||||
movies.map((movie) =>
|
||||
h(
|
||||
"div.row",
|
||||
{
|
||||
on: {
|
||||
click: () => {
|
||||
select(movie);
|
||||
},
|
||||
},
|
||||
},
|
||||
[
|
||||
h("div.hero.rank", [
|
||||
h(
|
||||
"span.hero",
|
||||
{ hero: { id: "rank" + movie.rank } },
|
||||
movie.rank
|
||||
),
|
||||
]),
|
||||
h("div.hero", { hero: { id: movie.title } }, movie.title),
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
]),
|
||||
])
|
||||
]);
|
||||
|
||||
const view = (data) =>
|
||||
h('div.page-container', [
|
||||
h("div.page-container", [
|
||||
data.selected ? detailView(data.selected) : overviewView(data.movies),
|
||||
])
|
||||
]);
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
var container = document.getElementById('container')
|
||||
vnode = patch(container, view(data))
|
||||
render()
|
||||
})
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
var container = document.getElementById("container");
|
||||
vnode = patch(container, view(data));
|
||||
render();
|
||||
});
|
||||
|
@ -1,15 +1,24 @@
|
||||
import { init } from '../../build/package/init.js'
|
||||
import { attributesModule } from '../../build/package/modules/attributes.js'
|
||||
import { h } from '../../build/package/h.js'
|
||||
import { init } from "../../build/package/init.js";
|
||||
import { attributesModule } from "../../build/package/modules/attributes.js";
|
||||
import { h } from "../../build/package/h.js";
|
||||
|
||||
var patch = init([attributesModule])
|
||||
var patch = init([attributesModule]);
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
var container = document.getElementById('container')
|
||||
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' } })
|
||||
])
|
||||
])
|
||||
patch(container, vnode)
|
||||
})
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
var container = document.getElementById("container");
|
||||
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",
|
||||
},
|
||||
}),
|
||||
]),
|
||||
]);
|
||||
patch(container, vnode);
|
||||
});
|
||||
|
@ -1,48 +1,50 @@
|
||||
const chalk = require('chalk')
|
||||
const Table = require('tty-table')
|
||||
const chalk = require("chalk");
|
||||
const Table = require("tty-table");
|
||||
|
||||
exports['reporter:benchmark'] = ['type', BenchmarkReporter]
|
||||
exports["reporter:benchmark"] = ["type", BenchmarkReporter];
|
||||
|
||||
function BenchmarkReporter (baseReporterDecorator) {
|
||||
baseReporterDecorator(this)
|
||||
const resultsPerBrowser = new Map()
|
||||
function BenchmarkReporter(baseReporterDecorator) {
|
||||
baseReporterDecorator(this);
|
||||
const resultsPerBrowser = new Map();
|
||||
this.onBrowserInfo = function (browser, info) {
|
||||
if (!info.benchmark) return
|
||||
if (!info.benchmark) return;
|
||||
if (!resultsPerBrowser.has(browser.name)) {
|
||||
resultsPerBrowser.set(browser.name, info.benchmark)
|
||||
resultsPerBrowser.set(browser.name, info.benchmark);
|
||||
}
|
||||
}
|
||||
};
|
||||
this.onRunComplete = function () {
|
||||
if (resultsPerBrowser.size === 0) return
|
||||
this.writeCommonMsg(chalk.underline.bold('\nBENCHMARK (times in seconds):\n'))
|
||||
if (resultsPerBrowser.size === 0) return;
|
||||
this.writeCommonMsg(
|
||||
chalk.underline.bold("\nBENCHMARK (times in seconds):\n")
|
||||
);
|
||||
resultsPerBrowser.forEach((results, browserName) => {
|
||||
this.writeCommonMsg(` ${chalk.bold(browserName)}:\n`)
|
||||
this.writeCommonMsg(` ${chalk.bold(browserName)}:\n`);
|
||||
const rows = results.map(({ cur, ref }, i) => ({
|
||||
i: String(i),
|
||||
cur: cur.toFixed(0),
|
||||
ref: ref.toFixed(0),
|
||||
diff: `${(cur / ref * 100).toFixed(2)}%`,
|
||||
}))
|
||||
diff: `${((cur / ref) * 100).toFixed(2)}%`,
|
||||
}));
|
||||
const header = [
|
||||
{
|
||||
value: 'i',
|
||||
align: 'right'
|
||||
value: "i",
|
||||
align: "right",
|
||||
},
|
||||
{
|
||||
value: 'ref',
|
||||
align: 'right'
|
||||
value: "ref",
|
||||
align: "right",
|
||||
},
|
||||
{
|
||||
value: 'cur',
|
||||
align: 'right'
|
||||
value: "cur",
|
||||
align: "right",
|
||||
},
|
||||
{
|
||||
value: 'diff',
|
||||
align: 'right'
|
||||
value: "diff",
|
||||
align: "right",
|
||||
},
|
||||
]
|
||||
console.log(Table(header, rows).render())
|
||||
})
|
||||
resultsPerBrowser.clear()
|
||||
}
|
||||
];
|
||||
console.log(Table(header, rows).render());
|
||||
});
|
||||
resultsPerBrowser.clear();
|
||||
};
|
||||
}
|
||||
|
@ -1,62 +1,85 @@
|
||||
import { vnode, VNode, VNodeData } from './vnode'
|
||||
import * as is from './is'
|
||||
import { vnode, VNode, VNodeData } from "./vnode";
|
||||
import * as is from "./is";
|
||||
|
||||
export type VNodes = VNode[]
|
||||
export type VNodeChildElement = VNode | string | number | undefined | null
|
||||
export type ArrayOrElement<T> = T | T[]
|
||||
export type VNodeChildren = ArrayOrElement<VNodeChildElement>
|
||||
export type VNodes = VNode[];
|
||||
export type VNodeChildElement = VNode | string | number | undefined | null;
|
||||
export type ArrayOrElement<T> = T | T[];
|
||||
export type VNodeChildren = ArrayOrElement<VNodeChildElement>;
|
||||
|
||||
function addNS (data: any, children: VNodes | undefined, sel: string | undefined): void {
|
||||
data.ns = 'http://www.w3.org/2000/svg'
|
||||
if (sel !== 'foreignObject' && children !== undefined) {
|
||||
function addNS(
|
||||
data: any,
|
||||
children: VNodes | undefined,
|
||||
sel: string | undefined
|
||||
): void {
|
||||
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
|
||||
const childData = children[i].data;
|
||||
if (childData !== undefined) {
|
||||
addNS(childData, (children[i] as VNode).children as VNodes, children[i].sel)
|
||||
addNS(
|
||||
childData,
|
||||
(children[i] as VNode).children as VNodes,
|
||||
children[i].sel
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function h (sel: string): VNode
|
||||
export function h (sel: string, data: VNodeData | null): VNode
|
||||
export function h (sel: string, children: VNodeChildren): VNode
|
||||
export function h (sel: string, data: VNodeData | null, children: VNodeChildren): VNode
|
||||
export function h (sel: any, b?: any, c?: any): VNode {
|
||||
let data: VNodeData = {}
|
||||
let children: any
|
||||
let text: any
|
||||
let i: number
|
||||
export function h(sel: string): VNode;
|
||||
export function h(sel: string, data: VNodeData | null): VNode;
|
||||
export function h(sel: string, children: VNodeChildren): VNode;
|
||||
export function h(
|
||||
sel: string,
|
||||
data: VNodeData | null,
|
||||
children: VNodeChildren
|
||||
): VNode;
|
||||
export function h(sel: any, b?: any, c?: any): VNode {
|
||||
let data: VNodeData = {};
|
||||
let children: any;
|
||||
let text: any;
|
||||
let i: number;
|
||||
if (c !== undefined) {
|
||||
if (b !== null) {
|
||||
data = b
|
||||
data = b;
|
||||
}
|
||||
if (is.array(c)) {
|
||||
children = c
|
||||
children = c;
|
||||
} else if (is.primitive(c)) {
|
||||
text = c
|
||||
text = c;
|
||||
} else if (c && c.sel) {
|
||||
children = [c]
|
||||
children = [c];
|
||||
}
|
||||
} else if (b !== undefined && b !== null) {
|
||||
if (is.array(b)) {
|
||||
children = b
|
||||
children = b;
|
||||
} else if (is.primitive(b)) {
|
||||
text = b
|
||||
text = b;
|
||||
} else if (b && b.sel) {
|
||||
children = [b]
|
||||
} else { data = b }
|
||||
children = [b];
|
||||
} else {
|
||||
data = b;
|
||||
}
|
||||
}
|
||||
if (children !== undefined) {
|
||||
for (i = 0; i < children.length; ++i) {
|
||||
if (is.primitive(children[i])) children[i] = vnode(undefined, undefined, undefined, children[i], undefined)
|
||||
if (is.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] === '#')
|
||||
sel[0] === "s" &&
|
||||
sel[1] === "v" &&
|
||||
sel[2] === "g" &&
|
||||
(sel.length === 3 || sel[3] === "." || sel[3] === "#")
|
||||
) {
|
||||
addNS(data, children, sel)
|
||||
addNS(data, children, sel);
|
||||
}
|
||||
return vnode(sel, data, children, text, undefined)
|
||||
};
|
||||
return vnode(sel, data, children, text, undefined);
|
||||
}
|
||||
|
@ -1,64 +1,64 @@
|
||||
import { VNode, VNodeData } from '../vnode'
|
||||
import { VNode, VNodeData } from "../vnode";
|
||||
|
||||
export interface AttachData {
|
||||
[key: string]: any
|
||||
[i: number]: any
|
||||
placeholder?: any
|
||||
real?: Node
|
||||
[key: string]: any;
|
||||
[i: number]: any;
|
||||
placeholder?: any;
|
||||
real?: Node;
|
||||
}
|
||||
|
||||
interface VNodeDataWithAttach extends VNodeData {
|
||||
attachData: AttachData
|
||||
attachData: AttachData;
|
||||
}
|
||||
|
||||
interface VNodeWithAttachData extends VNode {
|
||||
data: VNodeDataWithAttach
|
||||
data: VNodeDataWithAttach;
|
||||
}
|
||||
|
||||
function pre (vnode: VNodeWithAttachData, newVnode: VNodeWithAttachData): void {
|
||||
const attachData = vnode.data.attachData
|
||||
function pre(vnode: VNodeWithAttachData, newVnode: VNodeWithAttachData): void {
|
||||
const attachData = vnode.data.attachData;
|
||||
// Copy created placeholder and real element from old vnode
|
||||
newVnode.data.attachData.placeholder = attachData.placeholder
|
||||
newVnode.data.attachData.real = attachData.real
|
||||
newVnode.data.attachData.placeholder = attachData.placeholder;
|
||||
newVnode.data.attachData.real = attachData.real;
|
||||
// Mount real element in vnode so the patch process operates on it
|
||||
vnode.elm = vnode.data.attachData.real
|
||||
vnode.elm = vnode.data.attachData.real;
|
||||
}
|
||||
|
||||
function post (_: any, vnode: VNodeWithAttachData): void {
|
||||
function post(_: any, vnode: VNodeWithAttachData): void {
|
||||
// Mount dummy placeholder in vnode so potential reorders use it
|
||||
vnode.elm = vnode.data.attachData.placeholder
|
||||
vnode.elm = vnode.data.attachData.placeholder;
|
||||
}
|
||||
|
||||
function destroy (vnode: VNodeWithAttachData): void {
|
||||
function destroy(vnode: VNodeWithAttachData): void {
|
||||
// Remove placeholder
|
||||
if (vnode.elm !== undefined) {
|
||||
(vnode.elm.parentNode as HTMLElement).removeChild(vnode.elm)
|
||||
(vnode.elm.parentNode as HTMLElement).removeChild(vnode.elm);
|
||||
}
|
||||
// Remove real element from where it was inserted
|
||||
vnode.elm = vnode.data.attachData.real
|
||||
vnode.elm = vnode.data.attachData.real;
|
||||
}
|
||||
|
||||
function create (_: any, vnode: VNodeWithAttachData): void {
|
||||
const real = vnode.elm
|
||||
const attachData = vnode.data.attachData
|
||||
const placeholder = document.createElement('span')
|
||||
function create(_: any, vnode: VNodeWithAttachData): void {
|
||||
const real = vnode.elm;
|
||||
const attachData = vnode.data.attachData;
|
||||
const placeholder = document.createElement("span");
|
||||
// Replace actual element with dummy placeholder
|
||||
// Snabbdom will then insert placeholder instead
|
||||
vnode.elm = placeholder
|
||||
attachData.target.appendChild(real)
|
||||
attachData.real = real
|
||||
attachData.placeholder = placeholder
|
||||
vnode.elm = placeholder;
|
||||
attachData.target.appendChild(real);
|
||||
attachData.real = real;
|
||||
attachData.placeholder = placeholder;
|
||||
}
|
||||
|
||||
export function attachTo (target: Element, vnode: VNode): VNode {
|
||||
if (vnode.data === undefined) vnode.data = {}
|
||||
if (vnode.data.hook === undefined) vnode.data.hook = {}
|
||||
const data = vnode.data
|
||||
const hook = vnode.data.hook
|
||||
data.attachData = { target: target, placeholder: undefined, real: undefined }
|
||||
hook.create = create
|
||||
hook.prepatch = pre
|
||||
hook.postpatch = post
|
||||
hook.destroy = destroy
|
||||
return vnode
|
||||
};
|
||||
export function attachTo(target: Element, vnode: VNode): VNode {
|
||||
if (vnode.data === undefined) vnode.data = {};
|
||||
if (vnode.data.hook === undefined) vnode.data.hook = {};
|
||||
const data = vnode.data;
|
||||
const hook = vnode.data.hook;
|
||||
data.attachData = { target: target, placeholder: undefined, real: undefined };
|
||||
hook.create = create;
|
||||
hook.prepatch = pre;
|
||||
hook.postpatch = post;
|
||||
hook.destroy = destroy;
|
||||
return vnode;
|
||||
}
|
||||
|
@ -1,25 +1,25 @@
|
||||
import { VNode } from './vnode'
|
||||
import { VNode } from "./vnode";
|
||||
|
||||
export type PreHook = () => any
|
||||
export type InitHook = (vNode: VNode) => any
|
||||
export type CreateHook = (emptyVNode: VNode, vNode: VNode) => any
|
||||
export type InsertHook = (vNode: VNode) => any
|
||||
export type PrePatchHook = (oldVNode: VNode, vNode: VNode) => any
|
||||
export type UpdateHook = (oldVNode: VNode, vNode: VNode) => any
|
||||
export type PostPatchHook = (oldVNode: VNode, vNode: VNode) => any
|
||||
export type DestroyHook = (vNode: VNode) => any
|
||||
export type RemoveHook = (vNode: VNode, removeCallback: () => void) => any
|
||||
export type PostHook = () => any
|
||||
export type PreHook = () => any;
|
||||
export type InitHook = (vNode: VNode) => any;
|
||||
export type CreateHook = (emptyVNode: VNode, vNode: VNode) => any;
|
||||
export type InsertHook = (vNode: VNode) => any;
|
||||
export type PrePatchHook = (oldVNode: VNode, vNode: VNode) => any;
|
||||
export type UpdateHook = (oldVNode: VNode, vNode: VNode) => any;
|
||||
export type PostPatchHook = (oldVNode: VNode, vNode: VNode) => any;
|
||||
export type DestroyHook = (vNode: VNode) => any;
|
||||
export type RemoveHook = (vNode: VNode, removeCallback: () => void) => any;
|
||||
export type PostHook = () => any;
|
||||
|
||||
export interface Hooks {
|
||||
pre?: PreHook
|
||||
init?: InitHook
|
||||
create?: CreateHook
|
||||
insert?: InsertHook
|
||||
prepatch?: PrePatchHook
|
||||
update?: UpdateHook
|
||||
postpatch?: PostPatchHook
|
||||
destroy?: DestroyHook
|
||||
remove?: RemoveHook
|
||||
post?: PostHook
|
||||
pre?: PreHook;
|
||||
init?: InitHook;
|
||||
create?: CreateHook;
|
||||
insert?: InsertHook;
|
||||
prepatch?: PrePatchHook;
|
||||
update?: UpdateHook;
|
||||
postpatch?: PostPatchHook;
|
||||
destroy?: DestroyHook;
|
||||
remove?: RemoveHook;
|
||||
post?: PostHook;
|
||||
}
|
||||
|
@ -1,30 +1,30 @@
|
||||
// core
|
||||
export { DOMAPI, htmlDomApi } from './htmldomapi';
|
||||
export { init } from './init';
|
||||
export { ThunkData, Thunk, ThunkFn, thunk } from './thunk';
|
||||
export { Key, VNode, VNodeData, vnode } from './vnode';
|
||||
export { DOMAPI, htmlDomApi } from "./htmldomapi";
|
||||
export { init } from "./init";
|
||||
export { ThunkData, Thunk, ThunkFn, thunk } from "./thunk";
|
||||
export { Key, VNode, VNodeData, vnode } from "./vnode";
|
||||
|
||||
// helpers
|
||||
export { AttachData, attachTo } from './helpers/attachto';
|
||||
export { array, primitive } from './is';
|
||||
export { toVNode } from './tovnode';
|
||||
export { AttachData, attachTo } from "./helpers/attachto";
|
||||
export { array, primitive } from "./is";
|
||||
export { toVNode } from "./tovnode";
|
||||
export {
|
||||
VNodes,
|
||||
VNodeChildElement,
|
||||
ArrayOrElement,
|
||||
VNodeChildren,
|
||||
h,
|
||||
} from './h';
|
||||
} from "./h";
|
||||
|
||||
// types
|
||||
export * from './hooks';
|
||||
export { Module } from './modules/module';
|
||||
export * from "./hooks";
|
||||
export { Module } from "./modules/module";
|
||||
|
||||
// modules
|
||||
export { Attrs, attributesModule } from './modules/attributes';
|
||||
export { Classes, classModule } from './modules/class';
|
||||
export { Dataset, datasetModule } from './modules/dataset';
|
||||
export { On, eventListenersModule } from './modules/eventlisteners';
|
||||
export { Hero, heroModule } from './modules/hero';
|
||||
export { Props, propsModule } from './modules/props';
|
||||
export { VNodeStyle, styleModule } from './modules/style';
|
||||
export { Attrs, attributesModule } from "./modules/attributes";
|
||||
export { Classes, classModule } from "./modules/class";
|
||||
export { Dataset, datasetModule } from "./modules/dataset";
|
||||
export { On, eventListenersModule } from "./modules/eventlisteners";
|
||||
export { Hero, heroModule } from "./modules/hero";
|
||||
export { Props, propsModule } from "./modules/props";
|
||||
export { VNodeStyle, styleModule } from "./modules/style";
|
||||
|
@ -1,4 +1,4 @@
|
||||
export const array = Array.isArray
|
||||
export function primitive (s: any): s is (string | number) {
|
||||
return typeof s === 'string' || typeof s === 'number'
|
||||
export const array = Array.isArray;
|
||||
export function primitive(s: any): s is string | number {
|
||||
return typeof s === "string" || typeof s === "number";
|
||||
}
|
||||
|
@ -1,43 +1,74 @@
|
||||
import { vnode, VNode, VNodeData } from './vnode'
|
||||
import { h, ArrayOrElement } from './h'
|
||||
import { vnode, VNode, VNodeData } from "./vnode";
|
||||
import { h, ArrayOrElement } from "./h";
|
||||
|
||||
// for conditional rendering we support boolean child element e.g cond && <tag />
|
||||
export type JsxVNodeChild = VNode | string | number | boolean | undefined | null
|
||||
export type JsxVNodeChildren = ArrayOrElement<JsxVNodeChild>
|
||||
export type JsxVNodeChild =
|
||||
| VNode
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| undefined
|
||||
| null;
|
||||
export type JsxVNodeChildren = ArrayOrElement<JsxVNodeChild>;
|
||||
|
||||
export type FunctionComponent = (props: {[prop: string]: any} | null, children?: VNode[]) => VNode
|
||||
export type FunctionComponent = (
|
||||
props: { [prop: string]: any } | null,
|
||||
children?: VNode[]
|
||||
) => VNode;
|
||||
|
||||
function flattenAndFilter (children: JsxVNodeChildren[], flattened: VNode[]): VNode[] {
|
||||
function flattenAndFilter(
|
||||
children: JsxVNodeChildren[],
|
||||
flattened: VNode[]
|
||||
): VNode[] {
|
||||
for (const child of children) {
|
||||
// filter out falsey children, except 0 since zero can be a valid value e.g inside a chart
|
||||
if (child !== undefined && child !== null && child !== false && child !== '') {
|
||||
if (
|
||||
child !== undefined &&
|
||||
child !== null &&
|
||||
child !== false &&
|
||||
child !== ""
|
||||
) {
|
||||
if (Array.isArray(child)) {
|
||||
flattenAndFilter(child, flattened)
|
||||
} else if (typeof child === 'string' || typeof child === 'number' || typeof child === 'boolean') {
|
||||
flattened.push(vnode(undefined, undefined, undefined, String(child), undefined))
|
||||
flattenAndFilter(child, flattened);
|
||||
} else if (
|
||||
typeof child === "string" ||
|
||||
typeof child === "number" ||
|
||||
typeof child === "boolean"
|
||||
) {
|
||||
flattened.push(
|
||||
vnode(undefined, undefined, undefined, String(child), undefined)
|
||||
);
|
||||
} else {
|
||||
flattened.push(child)
|
||||
flattened.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
return flattened
|
||||
return flattened;
|
||||
}
|
||||
|
||||
/**
|
||||
* jsx/tsx compatible factory function
|
||||
* see: https://www.typescriptlang.org/docs/handbook/jsx.html#factory-functions
|
||||
*/
|
||||
export function jsx (tag: string | FunctionComponent, data: VNodeData | null, ...children: JsxVNodeChildren[]): VNode {
|
||||
const flatChildren = flattenAndFilter(children, [])
|
||||
if (typeof tag === 'function') {
|
||||
export function jsx(
|
||||
tag: string | FunctionComponent,
|
||||
data: VNodeData | null,
|
||||
...children: JsxVNodeChildren[]
|
||||
): VNode {
|
||||
const flatChildren = flattenAndFilter(children, []);
|
||||
if (typeof tag === "function") {
|
||||
// tag is a function component
|
||||
return tag(data, flatChildren)
|
||||
return tag(data, flatChildren);
|
||||
} else {
|
||||
if (flatChildren.length === 1 && !flatChildren[0].sel && flatChildren[0].text) {
|
||||
if (
|
||||
flatChildren.length === 1 &&
|
||||
!flatChildren[0].sel &&
|
||||
flatChildren[0].text
|
||||
) {
|
||||
// only child is a simple text node, pass as text for a simpler vtree
|
||||
return h(tag, data, flatChildren[0].text)
|
||||
return h(tag, data, flatChildren[0].text);
|
||||
} else {
|
||||
return h(tag, data, flatChildren)
|
||||
return h(tag, data, flatChildren);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +1,32 @@
|
||||
import { VNode, VNodeData } from '../vnode'
|
||||
import { Module } from './module'
|
||||
import { VNode, VNodeData } from "../vnode";
|
||||
import { Module } from "./module";
|
||||
|
||||
export type Classes = Record<string, boolean>
|
||||
export type Classes = Record<string, boolean>;
|
||||
|
||||
function updateClass (oldVnode: VNode, vnode: VNode): void {
|
||||
let cur: any
|
||||
let name: string
|
||||
const elm: Element = vnode.elm as Element
|
||||
let oldClass = (oldVnode.data as VNodeData).class
|
||||
let klass = (vnode.data as VNodeData).class
|
||||
function updateClass(oldVnode: VNode, vnode: VNode): void {
|
||||
let cur: any;
|
||||
let name: string;
|
||||
const elm: Element = vnode.elm as Element;
|
||||
let oldClass = (oldVnode.data as VNodeData).class;
|
||||
let klass = (vnode.data as VNodeData).class;
|
||||
|
||||
if (!oldClass && !klass) return
|
||||
if (oldClass === klass) return
|
||||
oldClass = oldClass || {}
|
||||
klass = klass || {}
|
||||
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)
|
||||
) {
|
||||
if (oldClass[name] && !Object.prototype.hasOwnProperty.call(klass, name)) {
|
||||
// was `true` and now not provided
|
||||
elm.classList.remove(name)
|
||||
elm.classList.remove(name);
|
||||
}
|
||||
}
|
||||
for (name in klass) {
|
||||
cur = klass[name]
|
||||
cur = klass[name];
|
||||
if (cur !== oldClass[name]) {
|
||||
(elm.classList as any)[cur ? 'add' : 'remove'](name)
|
||||
(elm.classList as any)[cur ? "add" : "remove"](name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const classModule: Module = { create: updateClass, update: updateClass }
|
||||
export const classModule: Module = { create: updateClass, update: updateClass };
|
||||
|
@ -1,42 +1,50 @@
|
||||
import { VNode, VNodeData } from '../vnode'
|
||||
import { Module } from './module'
|
||||
import { VNode, VNodeData } from "../vnode";
|
||||
import { Module } from "./module";
|
||||
|
||||
export type Dataset = Record<string, string>
|
||||
export type Dataset = Record<string, string>;
|
||||
|
||||
const CAPS_REGEX = /[A-Z]/g
|
||||
const CAPS_REGEX = /[A-Z]/g;
|
||||
|
||||
function updateDataset (oldVnode: VNode, vnode: VNode): void {
|
||||
const elm: HTMLElement = vnode.elm as HTMLElement
|
||||
let oldDataset = (oldVnode.data as VNodeData).dataset
|
||||
let dataset = (vnode.data as VNodeData).dataset
|
||||
let key: string
|
||||
function updateDataset(oldVnode: VNode, vnode: VNode): void {
|
||||
const elm: HTMLElement = vnode.elm as HTMLElement;
|
||||
let oldDataset = (oldVnode.data as VNodeData).dataset;
|
||||
let dataset = (vnode.data as VNodeData).dataset;
|
||||
let key: string;
|
||||
|
||||
if (!oldDataset && !dataset) return
|
||||
if (oldDataset === dataset) return
|
||||
oldDataset = oldDataset || {}
|
||||
dataset = dataset || {}
|
||||
const d = elm.dataset
|
||||
if (!oldDataset && !dataset) return;
|
||||
if (oldDataset === dataset) return;
|
||||
oldDataset = oldDataset || {};
|
||||
dataset = dataset || {};
|
||||
const d = elm.dataset;
|
||||
|
||||
for (key in oldDataset) {
|
||||
if (!dataset[key]) {
|
||||
if (d) {
|
||||
if (key in d) {
|
||||
delete d[key]
|
||||
delete d[key];
|
||||
}
|
||||
} else {
|
||||
elm.removeAttribute('data-' + key.replace(CAPS_REGEX, '-$&').toLowerCase())
|
||||
elm.removeAttribute(
|
||||
"data-" + key.replace(CAPS_REGEX, "-$&").toLowerCase()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (key in dataset) {
|
||||
if (oldDataset[key] !== dataset[key]) {
|
||||
if (d) {
|
||||
d[key] = dataset[key]
|
||||
d[key] = dataset[key];
|
||||
} else {
|
||||
elm.setAttribute('data-' + key.replace(CAPS_REGEX, '-$&').toLowerCase(), dataset[key])
|
||||
elm.setAttribute(
|
||||
"data-" + key.replace(CAPS_REGEX, "-$&").toLowerCase(),
|
||||
dataset[key]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const datasetModule: Module = { create: updateDataset, update: updateDataset }
|
||||
export const datasetModule: Module = {
|
||||
create: updateDataset,
|
||||
update: updateDataset,
|
||||
};
|
||||
|
@ -1,10 +1,17 @@
|
||||
import { PreHook, CreateHook, UpdateHook, DestroyHook, RemoveHook, PostHook } from '../hooks'
|
||||
import {
|
||||
PreHook,
|
||||
CreateHook,
|
||||
UpdateHook,
|
||||
DestroyHook,
|
||||
RemoveHook,
|
||||
PostHook,
|
||||
} from "../hooks";
|
||||
|
||||
export type Module = Partial<{
|
||||
pre: PreHook
|
||||
create: CreateHook
|
||||
update: UpdateHook
|
||||
destroy: DestroyHook
|
||||
remove: RemoveHook
|
||||
post: PostHook
|
||||
}>
|
||||
pre: PreHook;
|
||||
create: CreateHook;
|
||||
update: UpdateHook;
|
||||
destroy: DestroyHook;
|
||||
remove: RemoveHook;
|
||||
post: PostHook;
|
||||
}>;
|
||||
|
@ -1,28 +1,28 @@
|
||||
import { VNode, VNodeData } from '../vnode'
|
||||
import { Module } from './module'
|
||||
import { VNode, VNodeData } from "../vnode";
|
||||
import { Module } from "./module";
|
||||
|
||||
export type Props = Record<string, any>
|
||||
export type Props = Record<string, any>;
|
||||
|
||||
function updateProps (oldVnode: VNode, vnode: VNode): void {
|
||||
let key: string
|
||||
let cur: any
|
||||
let old: any
|
||||
const elm = vnode.elm
|
||||
let oldProps = (oldVnode.data as VNodeData).props
|
||||
let props = (vnode.data as VNodeData).props
|
||||
function updateProps(oldVnode: VNode, vnode: VNode): void {
|
||||
let key: string;
|
||||
let cur: any;
|
||||
let old: any;
|
||||
const elm = vnode.elm;
|
||||
let oldProps = (oldVnode.data as VNodeData).props;
|
||||
let props = (vnode.data as VNodeData).props;
|
||||
|
||||
if (!oldProps && !props) return
|
||||
if (oldProps === props) return
|
||||
oldProps = oldProps || {}
|
||||
props = 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 as any)[key] !== cur)) {
|
||||
(elm as any)[key] = cur
|
||||
cur = props[key];
|
||||
old = oldProps[key];
|
||||
if (old !== cur && (key !== "value" || (elm as any)[key] !== cur)) {
|
||||
(elm as any)[key] = cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const propsModule: Module = { create: updateProps, update: updateProps }
|
||||
export const propsModule: Module = { create: updateProps, update: updateProps };
|
||||
|
@ -1,64 +1,69 @@
|
||||
import { VNode, VNodeData } from './vnode'
|
||||
import { h } from './h'
|
||||
import { VNode, VNodeData } from "./vnode";
|
||||
import { h } from "./h";
|
||||
|
||||
export interface ThunkData extends VNodeData {
|
||||
fn: () => VNode
|
||||
args: any[]
|
||||
fn: () => VNode;
|
||||
args: any[];
|
||||
}
|
||||
|
||||
export interface Thunk extends VNode {
|
||||
data: ThunkData
|
||||
data: ThunkData;
|
||||
}
|
||||
|
||||
export interface ThunkFn {
|
||||
(sel: string, fn: Function, args: any[]): Thunk
|
||||
(sel: string, key: any, fn: Function, args: any[]): Thunk
|
||||
(sel: string, fn: Function, args: any[]): Thunk;
|
||||
(sel: string, key: any, fn: Function, args: any[]): Thunk;
|
||||
}
|
||||
|
||||
function copyToThunk (vnode: VNode, thunk: VNode): void {
|
||||
function copyToThunk(vnode: VNode, thunk: VNode): void {
|
||||
(vnode.data as VNodeData).fn = (thunk.data as VNodeData).fn;
|
||||
(vnode.data as VNodeData).args = (thunk.data as VNodeData).args
|
||||
thunk.data = vnode.data
|
||||
thunk.children = vnode.children
|
||||
thunk.text = vnode.text
|
||||
thunk.elm = vnode.elm
|
||||
(vnode.data as VNodeData).args = (thunk.data as VNodeData).args;
|
||||
thunk.data = vnode.data;
|
||||
thunk.children = vnode.children;
|
||||
thunk.text = vnode.text;
|
||||
thunk.elm = vnode.elm;
|
||||
}
|
||||
|
||||
function init (thunk: VNode): void {
|
||||
const cur = thunk.data as VNodeData
|
||||
const vnode = (cur.fn as any).apply(undefined, cur.args)
|
||||
copyToThunk(vnode, thunk)
|
||||
function init(thunk: VNode): void {
|
||||
const cur = thunk.data as VNodeData;
|
||||
const vnode = (cur.fn as any).apply(undefined, cur.args);
|
||||
copyToThunk(vnode, thunk);
|
||||
}
|
||||
|
||||
function prepatch (oldVnode: VNode, thunk: VNode): void {
|
||||
let i: number
|
||||
const old = oldVnode.data as VNodeData
|
||||
const cur = thunk.data as VNodeData
|
||||
const oldArgs = old.args
|
||||
const args = cur.args
|
||||
function prepatch(oldVnode: VNode, thunk: VNode): void {
|
||||
let i: number;
|
||||
const old = oldVnode.data as VNodeData;
|
||||
const cur = thunk.data as VNodeData;
|
||||
const oldArgs = old.args;
|
||||
const args = cur.args;
|
||||
if (old.fn !== cur.fn || (oldArgs as any).length !== (args as any).length) {
|
||||
copyToThunk((cur.fn as any).apply(undefined, args), thunk)
|
||||
return
|
||||
copyToThunk((cur.fn as any).apply(undefined, args), thunk);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < (args as any).length; ++i) {
|
||||
if ((oldArgs as any)[i] !== (args as any)[i]) {
|
||||
copyToThunk((cur.fn as any).apply(undefined, args), thunk)
|
||||
return
|
||||
copyToThunk((cur.fn as any).apply(undefined, args), thunk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
copyToThunk(oldVnode, thunk)
|
||||
copyToThunk(oldVnode, thunk);
|
||||
}
|
||||
|
||||
export const thunk = function thunk (sel: string, key?: any, fn?: any, args?: any): VNode {
|
||||
export const thunk = function thunk(
|
||||
sel: string,
|
||||
key?: any,
|
||||
fn?: any,
|
||||
args?: any
|
||||
): VNode {
|
||||
if (args === undefined) {
|
||||
args = fn
|
||||
fn = key
|
||||
key = undefined
|
||||
args = fn;
|
||||
fn = key;
|
||||
key = undefined;
|
||||
}
|
||||
return h(sel, {
|
||||
key: key,
|
||||
hook: { init, prepatch },
|
||||
fn: fn,
|
||||
args: args
|
||||
})
|
||||
} as ThunkFn
|
||||
args: args,
|
||||
});
|
||||
} as ThunkFn;
|
||||
|
@ -1,37 +1,37 @@
|
||||
import { vnode, VNode } from './vnode'
|
||||
import { htmlDomApi, DOMAPI } from './htmldomapi'
|
||||
import { vnode, VNode } from "./vnode";
|
||||
import { htmlDomApi, DOMAPI } from "./htmldomapi";
|
||||
|
||||
export function toVNode (node: Node, domApi?: DOMAPI): VNode {
|
||||
const api: DOMAPI = domApi !== undefined ? domApi : htmlDomApi
|
||||
let text: string
|
||||
export function toVNode(node: Node, domApi?: DOMAPI): VNode {
|
||||
const api: DOMAPI = domApi !== undefined ? domApi : htmlDomApi;
|
||||
let text: string;
|
||||
if (api.isElement(node)) {
|
||||
const id = node.id ? '#' + node.id : ''
|
||||
const cn = node.getAttribute('class')
|
||||
const c = cn ? '.' + cn.split(' ').join('.') : ''
|
||||
const sel = api.tagName(node).toLowerCase() + id + c
|
||||
const attrs: any = {}
|
||||
const children: VNode[] = []
|
||||
let name: string
|
||||
let i: number, n: number
|
||||
const elmAttrs = node.attributes
|
||||
const elmChildren = node.childNodes
|
||||
const id = node.id ? "#" + node.id : "";
|
||||
const cn = node.getAttribute("class");
|
||||
const c = cn ? "." + cn.split(" ").join(".") : "";
|
||||
const sel = api.tagName(node).toLowerCase() + id + c;
|
||||
const attrs: any = {};
|
||||
const children: VNode[] = [];
|
||||
let name: string;
|
||||
let i: number, n: number;
|
||||
const elmAttrs = node.attributes;
|
||||
const elmChildren = node.childNodes;
|
||||
for (i = 0, n = elmAttrs.length; i < n; i++) {
|
||||
name = elmAttrs[i].nodeName
|
||||
if (name !== 'id' && name !== 'class') {
|
||||
attrs[name] = elmAttrs[i].nodeValue
|
||||
name = elmAttrs[i].nodeName;
|
||||
if (name !== "id" && name !== "class") {
|
||||
attrs[name] = elmAttrs[i].nodeValue;
|
||||
}
|
||||
}
|
||||
for (i = 0, n = elmChildren.length; i < n; i++) {
|
||||
children.push(toVNode(elmChildren[i], domApi))
|
||||
children.push(toVNode(elmChildren[i], domApi));
|
||||
}
|
||||
return vnode(sel, { attrs }, children, undefined, node)
|
||||
return vnode(sel, { attrs }, children, undefined, node);
|
||||
} else if (api.isText(node)) {
|
||||
text = api.getTextContent(node) as string
|
||||
return vnode(undefined, undefined, undefined, text, node)
|
||||
text = api.getTextContent(node) as string;
|
||||
return vnode(undefined, undefined, undefined, text, node);
|
||||
} else if (api.isComment(node)) {
|
||||
text = api.getTextContent(node) as string
|
||||
return vnode('!', {}, [], text, node as any)
|
||||
text = api.getTextContent(node) as string;
|
||||
return vnode("!", {}, [], text, node as any);
|
||||
} else {
|
||||
return vnode('', {}, [], undefined, node as any)
|
||||
return vnode("", {}, [], undefined, node as any);
|
||||
}
|
||||
}
|
||||
|
@ -1,47 +1,49 @@
|
||||
import { Hooks } from './hooks'
|
||||
import { AttachData } from './helpers/attachto'
|
||||
import { VNodeStyle } from './modules/style'
|
||||
import { On } from './modules/eventlisteners'
|
||||
import { Attrs } from './modules/attributes'
|
||||
import { Classes } from './modules/class'
|
||||
import { Props } from './modules/props'
|
||||
import { Dataset } from './modules/dataset'
|
||||
import { Hero } from './modules/hero'
|
||||
import { Hooks } from "./hooks";
|
||||
import { AttachData } from "./helpers/attachto";
|
||||
import { VNodeStyle } from "./modules/style";
|
||||
import { On } from "./modules/eventlisteners";
|
||||
import { Attrs } from "./modules/attributes";
|
||||
import { Classes } from "./modules/class";
|
||||
import { Props } from "./modules/props";
|
||||
import { Dataset } from "./modules/dataset";
|
||||
import { Hero } from "./modules/hero";
|
||||
|
||||
export type Key = string | number
|
||||
export type Key = string | number;
|
||||
|
||||
export interface VNode {
|
||||
sel: string | undefined
|
||||
data: VNodeData | undefined
|
||||
children: Array<VNode | string> | undefined
|
||||
elm: Node | undefined
|
||||
text: string | undefined
|
||||
key: Key | undefined
|
||||
sel: string | undefined;
|
||||
data: VNodeData | undefined;
|
||||
children: Array<VNode | string> | undefined;
|
||||
elm: Node | undefined;
|
||||
text: string | undefined;
|
||||
key: Key | undefined;
|
||||
}
|
||||
|
||||
export interface VNodeData {
|
||||
props?: Props
|
||||
attrs?: Attrs
|
||||
class?: Classes
|
||||
style?: VNodeStyle
|
||||
dataset?: Dataset
|
||||
on?: On
|
||||
hero?: Hero
|
||||
attachData?: AttachData
|
||||
hook?: Hooks
|
||||
key?: Key
|
||||
ns?: string // for SVGs
|
||||
fn?: () => VNode // for thunks
|
||||
args?: any[] // for thunks
|
||||
is?: string // for custom elements v1
|
||||
[key: string]: any // for any other 3rd party module
|
||||
props?: Props;
|
||||
attrs?: Attrs;
|
||||
class?: Classes;
|
||||
style?: VNodeStyle;
|
||||
dataset?: Dataset;
|
||||
on?: On;
|
||||
hero?: Hero;
|
||||
attachData?: AttachData;
|
||||
hook?: Hooks;
|
||||
key?: Key;
|
||||
ns?: string; // for SVGs
|
||||
fn?: () => VNode; // for thunks
|
||||
args?: any[]; // for thunks
|
||||
is?: string; // for custom elements v1
|
||||
[key: string]: any; // for any other 3rd party module
|
||||
}
|
||||
|
||||
export function vnode (sel: string | undefined,
|
||||
export function vnode(
|
||||
sel: string | undefined,
|
||||
data: any | undefined,
|
||||
children: Array<VNode | string> | undefined,
|
||||
text: string | undefined,
|
||||
elm: Element | Text | undefined): VNode {
|
||||
const key = data === undefined ? undefined : data.key
|
||||
return { sel, data, children, text, elm, key }
|
||||
elm: Element | Text | undefined
|
||||
): VNode {
|
||||
const key = data === undefined ? undefined : data.key;
|
||||
return { sel, data, children, text, elm, key };
|
||||
}
|
||||
|
@ -1,98 +1,93 @@
|
||||
import { assert } from 'chai'
|
||||
import { assert } from "chai";
|
||||
|
||||
import { init, RemoveHook, attachTo, h } from '../../src/index';
|
||||
import { init, RemoveHook, attachTo, h } from "../../src/index";
|
||||
|
||||
const patch = init([])
|
||||
const patch = init([]);
|
||||
|
||||
describe('attachTo', function () {
|
||||
let elm: any, vnode0: any
|
||||
describe("attachTo", function () {
|
||||
let elm: any, vnode0: any;
|
||||
beforeEach(function () {
|
||||
elm = document.createElement('div')
|
||||
vnode0 = elm
|
||||
})
|
||||
it('adds element to target', function () {
|
||||
const vnode1 = h('div', [
|
||||
h('div#wrapper', [
|
||||
h('div', 'Some element'),
|
||||
attachTo(elm, h('div#attached', 'Test')),
|
||||
elm = document.createElement("div");
|
||||
vnode0 = elm;
|
||||
});
|
||||
it("adds element to target", function () {
|
||||
const vnode1 = h("div", [
|
||||
h("div#wrapper", [
|
||||
h("div", "Some element"),
|
||||
attachTo(elm, h("div#attached", "Test")),
|
||||
]),
|
||||
])
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.children.length, 2)
|
||||
})
|
||||
it('updates element at target', function () {
|
||||
const vnode1 = h('div', [
|
||||
h('div#wrapper', [
|
||||
h('div', 'Some element'),
|
||||
attachTo(elm, h('div#attached', 'First text')),
|
||||
]);
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.children.length, 2);
|
||||
});
|
||||
it("updates element at target", function () {
|
||||
const vnode1 = h("div", [
|
||||
h("div#wrapper", [
|
||||
h("div", "Some element"),
|
||||
attachTo(elm, h("div#attached", "First text")),
|
||||
]),
|
||||
])
|
||||
const vnode2 = h('div', [
|
||||
h('div#wrapper', [
|
||||
h('div', 'Some element'),
|
||||
attachTo(elm, h('div#attached', 'New text')),
|
||||
]);
|
||||
const vnode2 = h("div", [
|
||||
h("div#wrapper", [
|
||||
h("div", "Some element"),
|
||||
attachTo(elm, h("div#attached", "New text")),
|
||||
]),
|
||||
])
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.children[0].innerHTML, 'First text')
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
assert.strictEqual(elm.children[0].innerHTML, 'New text')
|
||||
})
|
||||
it('element can be inserted before modal', function () {
|
||||
const vnode1 = h('div', [
|
||||
h('div#wrapper', [
|
||||
h('div', 'Some element'),
|
||||
attachTo(elm, h('div#attached', 'Text')),
|
||||
]);
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.children[0].innerHTML, "First text");
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
assert.strictEqual(elm.children[0].innerHTML, "New text");
|
||||
});
|
||||
it("element can be inserted before modal", function () {
|
||||
const vnode1 = h("div", [
|
||||
h("div#wrapper", [
|
||||
h("div", "Some element"),
|
||||
attachTo(elm, h("div#attached", "Text")),
|
||||
]),
|
||||
])
|
||||
const vnode2 = h('div', [
|
||||
h('div#wrapper', [
|
||||
h('div', 'Some element'),
|
||||
h('div', 'A new element'),
|
||||
attachTo(elm, h('div#attached', 'Text')),
|
||||
]);
|
||||
const vnode2 = h("div", [
|
||||
h("div#wrapper", [
|
||||
h("div", "Some element"),
|
||||
h("div", "A new element"),
|
||||
attachTo(elm, h("div#attached", "Text")),
|
||||
]),
|
||||
])
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.children[0].innerHTML, 'Text')
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
assert.strictEqual(elm.children[0].innerHTML, 'Text')
|
||||
})
|
||||
it('removes element at target', function () {
|
||||
const vnode1 = h('div', [
|
||||
h('div#wrapper', [
|
||||
h('div', 'Some element'),
|
||||
attachTo(elm, h('div#attached', 'First text')),
|
||||
]);
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.children[0].innerHTML, "Text");
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
assert.strictEqual(elm.children[0].innerHTML, "Text");
|
||||
});
|
||||
it("removes element at target", function () {
|
||||
const vnode1 = h("div", [
|
||||
h("div#wrapper", [
|
||||
h("div", "Some element"),
|
||||
attachTo(elm, h("div#attached", "First text")),
|
||||
]),
|
||||
])
|
||||
const vnode2 = h('div', [
|
||||
h('div#wrapper', [
|
||||
h('div', 'Some element'),
|
||||
]),
|
||||
])
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.children[0].innerHTML, 'First text')
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
assert.strictEqual(elm.children.length, 1)
|
||||
})
|
||||
it('remove hook receives real element', function () {
|
||||
]);
|
||||
const vnode2 = h("div", [h("div#wrapper", [h("div", "Some element")])]);
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.children[0].innerHTML, "First text");
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
assert.strictEqual(elm.children.length, 1);
|
||||
});
|
||||
it("remove hook receives real element", function () {
|
||||
const rm: RemoveHook = (vnode, cb) => {
|
||||
const elm = vnode.elm as HTMLDivElement
|
||||
assert.strictEqual(elm.tagName, 'DIV')
|
||||
assert.strictEqual(elm.innerHTML, 'First text')
|
||||
cb()
|
||||
}
|
||||
const vnode1 = h('div', [
|
||||
h('div#wrapper', [
|
||||
h('div', 'Some element'),
|
||||
attachTo(elm, h('div#attached', { hook: { remove: rm } }, 'First text')),
|
||||
]),
|
||||
])
|
||||
const vnode2 = h('div', [
|
||||
h('div#wrapper', [
|
||||
h('div', 'Some element'),
|
||||
const elm = vnode.elm as HTMLDivElement;
|
||||
assert.strictEqual(elm.tagName, "DIV");
|
||||
assert.strictEqual(elm.innerHTML, "First text");
|
||||
cb();
|
||||
};
|
||||
const vnode1 = h("div", [
|
||||
h("div#wrapper", [
|
||||
h("div", "Some element"),
|
||||
attachTo(
|
||||
elm,
|
||||
h("div#attached", { hook: { remove: rm } }, "First text")
|
||||
),
|
||||
]),
|
||||
])
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
})
|
||||
})
|
||||
]);
|
||||
const vnode2 = h("div", [h("div#wrapper", [h("div", "Some element")])]);
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
});
|
||||
});
|
||||
|
@ -1,97 +1,106 @@
|
||||
import { assert } from 'chai'
|
||||
import { assert } from "chai";
|
||||
|
||||
import { init, attributesModule, h } from '../../src/index';
|
||||
import { init, attributesModule, h } from "../../src/index";
|
||||
|
||||
const patch = init([
|
||||
attributesModule
|
||||
])
|
||||
const patch = init([attributesModule]);
|
||||
|
||||
describe('attributes', function () {
|
||||
let elm: any, vnode0: any
|
||||
describe("attributes", function () {
|
||||
let elm: any, vnode0: any;
|
||||
beforeEach(function () {
|
||||
elm = document.createElement('div')
|
||||
vnode0 = elm
|
||||
})
|
||||
it('have their provided values', function () {
|
||||
const vnode1 = h('div', { attrs: { href: '/foo', minlength: 1, selected: true, disabled: false } })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.getAttribute('href'), '/foo')
|
||||
assert.strictEqual(elm.getAttribute('minlength'), '1')
|
||||
assert.strictEqual(elm.hasAttribute('selected'), true)
|
||||
assert.strictEqual(elm.getAttribute('selected'), '')
|
||||
assert.strictEqual(elm.hasAttribute('disabled'), false)
|
||||
})
|
||||
it('can be memoized', function () {
|
||||
const cachedAttrs = { href: '/foo', minlength: 1, selected: true }
|
||||
const vnode1 = h('div', { attrs: cachedAttrs })
|
||||
const vnode2 = h('div', { attrs: cachedAttrs })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.getAttribute('href'), '/foo')
|
||||
assert.strictEqual(elm.getAttribute('minlength'), '1')
|
||||
assert.strictEqual(elm.getAttribute('selected'), '')
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
assert.strictEqual(elm.getAttribute('href'), '/foo')
|
||||
assert.strictEqual(elm.getAttribute('minlength'), '1')
|
||||
assert.strictEqual(elm.getAttribute('selected'), '')
|
||||
})
|
||||
it('are not omitted when falsy values are provided', function () {
|
||||
const vnode1 = h('div', { attrs: { href: null as any, minlength: 0, value: '', title: 'undefined' } })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.ok(elm.hasAttribute('href'))
|
||||
assert.ok(elm.hasAttribute('minlength'))
|
||||
assert.ok(elm.hasAttribute('value'))
|
||||
assert.ok(elm.hasAttribute('title'))
|
||||
})
|
||||
it('are set correctly when namespaced', function () {
|
||||
const vnode1 = h('div', { attrs: { 'xlink:href': '#foo' } })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.getAttributeNS('http://www.w3.org/1999/xlink', 'href'), '#foo')
|
||||
})
|
||||
it('should not touch class nor id fields', function () {
|
||||
elm = document.createElement('div')
|
||||
elm.id = 'myId'
|
||||
elm.className = 'myClass'
|
||||
vnode0 = elm
|
||||
const vnode1 = h('div#myId.myClass', { attrs: {} }, ['Hello'])
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.tagName, 'DIV')
|
||||
assert.strictEqual(elm.id, 'myId')
|
||||
assert.strictEqual(elm.className, 'myClass')
|
||||
assert.strictEqual(elm.textContent, 'Hello')
|
||||
})
|
||||
describe('boolean attribute', function () {
|
||||
it('is present and empty string if the value is truthy', function () {
|
||||
const vnode1 = h('div', { attrs: { required: true, readonly: 1, noresize: 'truthy' } })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.hasAttribute('required'), true)
|
||||
assert.strictEqual(elm.getAttribute('required'), '')
|
||||
assert.strictEqual(elm.hasAttribute('readonly'), true)
|
||||
assert.strictEqual(elm.getAttribute('readonly'), '1')
|
||||
assert.strictEqual(elm.hasAttribute('noresize'), true)
|
||||
assert.strictEqual(elm.getAttribute('noresize'), 'truthy')
|
||||
})
|
||||
it('is omitted if the value is false', function () {
|
||||
const vnode1 = h('div', { attrs: { required: false } })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.hasAttribute('required'), false)
|
||||
assert.strictEqual(elm.getAttribute('required'), null)
|
||||
})
|
||||
it('is not omitted if the value is falsy', function () {
|
||||
const vnode1 = h('div', { attrs: { readonly: 0, noresize: null as any } })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.ok(elm.hasAttribute('readonly'))
|
||||
assert.ok(elm.hasAttribute('noresize'))
|
||||
})
|
||||
})
|
||||
describe('Object.prototype property', function () {
|
||||
it('is not considered as a boolean attribute and shouldn\'t be omitted', function () {
|
||||
const vnode1 = h('div', { attrs: { constructor: true } })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.hasAttribute('constructor'), true)
|
||||
assert.strictEqual(elm.getAttribute('constructor'), '')
|
||||
const vnode2 = h('div', { attrs: { constructor: false } })
|
||||
elm = patch(vnode0, vnode2).elm
|
||||
assert.strictEqual(elm.hasAttribute('constructor'), false)
|
||||
})
|
||||
})
|
||||
})
|
||||
elm = document.createElement("div");
|
||||
vnode0 = elm;
|
||||
});
|
||||
it("have their provided values", function () {
|
||||
const vnode1 = h("div", {
|
||||
attrs: { href: "/foo", minlength: 1, selected: true, disabled: false },
|
||||
});
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.getAttribute("href"), "/foo");
|
||||
assert.strictEqual(elm.getAttribute("minlength"), "1");
|
||||
assert.strictEqual(elm.hasAttribute("selected"), true);
|
||||
assert.strictEqual(elm.getAttribute("selected"), "");
|
||||
assert.strictEqual(elm.hasAttribute("disabled"), false);
|
||||
});
|
||||
it("can be memoized", function () {
|
||||
const cachedAttrs = { href: "/foo", minlength: 1, selected: true };
|
||||
const vnode1 = h("div", { attrs: cachedAttrs });
|
||||
const vnode2 = h("div", { attrs: cachedAttrs });
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.getAttribute("href"), "/foo");
|
||||
assert.strictEqual(elm.getAttribute("minlength"), "1");
|
||||
assert.strictEqual(elm.getAttribute("selected"), "");
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
assert.strictEqual(elm.getAttribute("href"), "/foo");
|
||||
assert.strictEqual(elm.getAttribute("minlength"), "1");
|
||||
assert.strictEqual(elm.getAttribute("selected"), "");
|
||||
});
|
||||
it("are not omitted when falsy values are provided", function () {
|
||||
const vnode1 = h("div", {
|
||||
attrs: { href: null as any, minlength: 0, value: "", title: "undefined" },
|
||||
});
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.ok(elm.hasAttribute("href"));
|
||||
assert.ok(elm.hasAttribute("minlength"));
|
||||
assert.ok(elm.hasAttribute("value"));
|
||||
assert.ok(elm.hasAttribute("title"));
|
||||
});
|
||||
it("are set correctly when namespaced", function () {
|
||||
const vnode1 = h("div", { attrs: { "xlink:href": "#foo" } });
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(
|
||||
elm.getAttributeNS("http://www.w3.org/1999/xlink", "href"),
|
||||
"#foo"
|
||||
);
|
||||
});
|
||||
it("should not touch class nor id fields", function () {
|
||||
elm = document.createElement("div");
|
||||
elm.id = "myId";
|
||||
elm.className = "myClass";
|
||||
vnode0 = elm;
|
||||
const vnode1 = h("div#myId.myClass", { attrs: {} }, ["Hello"]);
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.tagName, "DIV");
|
||||
assert.strictEqual(elm.id, "myId");
|
||||
assert.strictEqual(elm.className, "myClass");
|
||||
assert.strictEqual(elm.textContent, "Hello");
|
||||
});
|
||||
describe("boolean attribute", function () {
|
||||
it("is present and empty string if the value is truthy", function () {
|
||||
const vnode1 = h("div", {
|
||||
attrs: { required: true, readonly: 1, noresize: "truthy" },
|
||||
});
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.hasAttribute("required"), true);
|
||||
assert.strictEqual(elm.getAttribute("required"), "");
|
||||
assert.strictEqual(elm.hasAttribute("readonly"), true);
|
||||
assert.strictEqual(elm.getAttribute("readonly"), "1");
|
||||
assert.strictEqual(elm.hasAttribute("noresize"), true);
|
||||
assert.strictEqual(elm.getAttribute("noresize"), "truthy");
|
||||
});
|
||||
it("is omitted if the value is false", function () {
|
||||
const vnode1 = h("div", { attrs: { required: false } });
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.hasAttribute("required"), false);
|
||||
assert.strictEqual(elm.getAttribute("required"), null);
|
||||
});
|
||||
it("is not omitted if the value is falsy", function () {
|
||||
const vnode1 = h("div", {
|
||||
attrs: { readonly: 0, noresize: null as any },
|
||||
});
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.ok(elm.hasAttribute("readonly"));
|
||||
assert.ok(elm.hasAttribute("noresize"));
|
||||
});
|
||||
});
|
||||
describe("Object.prototype property", function () {
|
||||
it("is not considered as a boolean attribute and shouldn't be omitted", function () {
|
||||
const vnode1 = h("div", { attrs: { constructor: true } });
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.hasAttribute("constructor"), true);
|
||||
assert.strictEqual(elm.getAttribute("constructor"), "");
|
||||
const vnode2 = h("div", { attrs: { constructor: false } });
|
||||
elm = patch(vnode0, vnode2).elm;
|
||||
assert.strictEqual(elm.hasAttribute("constructor"), false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,57 +1,64 @@
|
||||
import { assert } from 'chai'
|
||||
import { assert } from "chai";
|
||||
|
||||
import { datasetModule, init, h } from '../../src/index';
|
||||
import { datasetModule, init, h } from "../../src/index";
|
||||
|
||||
const patch = init([
|
||||
datasetModule
|
||||
])
|
||||
const patch = init([datasetModule]);
|
||||
|
||||
describe('dataset', function () {
|
||||
describe("dataset", function () {
|
||||
before(function () {
|
||||
if (!Object.hasOwnProperty.call(HTMLElement.prototype, 'dataset')) {
|
||||
this.skip()
|
||||
if (!Object.hasOwnProperty.call(HTMLElement.prototype, "dataset")) {
|
||||
this.skip();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
let elm: any, vnode0: any
|
||||
let elm: any, vnode0: any;
|
||||
beforeEach(function () {
|
||||
elm = document.createElement('div')
|
||||
vnode0 = elm
|
||||
})
|
||||
it('is set on initial element creation', function () {
|
||||
elm = patch(vnode0, h('div', { dataset: { foo: 'foo' } })).elm
|
||||
assert.strictEqual(elm.dataset.foo, 'foo')
|
||||
})
|
||||
it('updates dataset', function () {
|
||||
const vnode1 = h('i', { dataset: { foo: 'foo', bar: 'bar' } })
|
||||
const vnode2 = h('i', { dataset: { baz: 'baz' } })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.dataset.foo, 'foo')
|
||||
assert.strictEqual(elm.dataset.bar, 'bar')
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
assert.strictEqual(elm.dataset.baz, 'baz')
|
||||
assert.strictEqual(elm.dataset.foo, undefined)
|
||||
})
|
||||
it('can be memoized', function () {
|
||||
const cachedDataset = { foo: 'foo', bar: 'bar' }
|
||||
const vnode1 = h('i', { dataset: cachedDataset })
|
||||
const vnode2 = h('i', { dataset: cachedDataset })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.dataset.foo, 'foo')
|
||||
assert.strictEqual(elm.dataset.bar, 'bar')
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
assert.strictEqual(elm.dataset.foo, 'foo')
|
||||
assert.strictEqual(elm.dataset.bar, 'bar')
|
||||
})
|
||||
it('handles string conversions', function () {
|
||||
const vnode1 = h('i', { dataset: { empty: '', dash: '-', dashed: 'foo-bar', camel: 'fooBar', integer: 0 as any, float: 0.1 as any } })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
elm = document.createElement("div");
|
||||
vnode0 = elm;
|
||||
});
|
||||
it("is set on initial element creation", function () {
|
||||
elm = patch(vnode0, h("div", { dataset: { foo: "foo" } })).elm;
|
||||
assert.strictEqual(elm.dataset.foo, "foo");
|
||||
});
|
||||
it("updates dataset", function () {
|
||||
const vnode1 = h("i", { dataset: { foo: "foo", bar: "bar" } });
|
||||
const vnode2 = h("i", { dataset: { baz: "baz" } });
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.dataset.foo, "foo");
|
||||
assert.strictEqual(elm.dataset.bar, "bar");
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
assert.strictEqual(elm.dataset.baz, "baz");
|
||||
assert.strictEqual(elm.dataset.foo, undefined);
|
||||
});
|
||||
it("can be memoized", function () {
|
||||
const cachedDataset = { foo: "foo", bar: "bar" };
|
||||
const vnode1 = h("i", { dataset: cachedDataset });
|
||||
const vnode2 = h("i", { dataset: cachedDataset });
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.dataset.foo, "foo");
|
||||
assert.strictEqual(elm.dataset.bar, "bar");
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
assert.strictEqual(elm.dataset.foo, "foo");
|
||||
assert.strictEqual(elm.dataset.bar, "bar");
|
||||
});
|
||||
it("handles string conversions", function () {
|
||||
const vnode1 = h("i", {
|
||||
dataset: {
|
||||
empty: "",
|
||||
dash: "-",
|
||||
dashed: "foo-bar",
|
||||
camel: "fooBar",
|
||||
integer: 0 as any,
|
||||
float: 0.1 as any,
|
||||
},
|
||||
});
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
|
||||
assert.strictEqual(elm.dataset.empty, '')
|
||||
assert.strictEqual(elm.dataset.dash, '-')
|
||||
assert.strictEqual(elm.dataset.dashed, 'foo-bar')
|
||||
assert.strictEqual(elm.dataset.camel, 'fooBar')
|
||||
assert.strictEqual(elm.dataset.integer, '0')
|
||||
assert.strictEqual(elm.dataset.float, '0.1')
|
||||
})
|
||||
})
|
||||
assert.strictEqual(elm.dataset.empty, "");
|
||||
assert.strictEqual(elm.dataset.dash, "-");
|
||||
assert.strictEqual(elm.dataset.dashed, "foo-bar");
|
||||
assert.strictEqual(elm.dataset.camel, "fooBar");
|
||||
assert.strictEqual(elm.dataset.integer, "0");
|
||||
assert.strictEqual(elm.dataset.float, "0.1");
|
||||
});
|
||||
});
|
||||
|
@ -1,123 +1,125 @@
|
||||
import { assert } from 'chai'
|
||||
import { assert } from "chai";
|
||||
|
||||
import { VNode, init, eventListenersModule, h } from '../../src/index';
|
||||
import { VNode, init, eventListenersModule, h } from "../../src/index";
|
||||
|
||||
const patch = init([
|
||||
eventListenersModule
|
||||
])
|
||||
const patch = init([eventListenersModule]);
|
||||
|
||||
describe('event listeners', function () {
|
||||
let elm: any, vnode0: any
|
||||
describe("event listeners", function () {
|
||||
let elm: any, vnode0: any;
|
||||
beforeEach(function () {
|
||||
elm = document.createElement('div')
|
||||
vnode0 = elm
|
||||
})
|
||||
it('attaches click event handler to element', function () {
|
||||
const result = []
|
||||
function clicked (ev: Event) {
|
||||
result.push(ev)
|
||||
elm = document.createElement("div");
|
||||
vnode0 = elm;
|
||||
});
|
||||
it("attaches click event handler to element", function () {
|
||||
const result = [];
|
||||
function clicked(ev: Event) {
|
||||
result.push(ev);
|
||||
}
|
||||
const vnode = h('div', { on: { click: clicked } }, [
|
||||
h('a', 'Click my parent'),
|
||||
])
|
||||
elm = patch(vnode0, vnode).elm
|
||||
elm.click()
|
||||
assert.strictEqual(1, result.length)
|
||||
})
|
||||
it('does not attach new listener', function () {
|
||||
const result: number[] = []
|
||||
const vnode = h("div", { on: { click: clicked } }, [
|
||||
h("a", "Click my parent"),
|
||||
]);
|
||||
elm = patch(vnode0, vnode).elm;
|
||||
elm.click();
|
||||
assert.strictEqual(1, result.length);
|
||||
});
|
||||
it("does not attach new listener", function () {
|
||||
const result: number[] = [];
|
||||
// function clicked(ev) { result.push(ev); }
|
||||
const vnode1 = h('div', {
|
||||
on: {
|
||||
click: function (ev) {
|
||||
result.push(1)
|
||||
}
|
||||
}
|
||||
}, [
|
||||
h('a', 'Click my parent'),
|
||||
])
|
||||
const vnode2 = h('div', {
|
||||
on: {
|
||||
click: function (ev) {
|
||||
result.push(2)
|
||||
}
|
||||
}
|
||||
}, [
|
||||
h('a', 'Click my parent'),
|
||||
])
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
elm.click()
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
elm.click()
|
||||
assert.deepEqual(result, [1, 2])
|
||||
})
|
||||
it('detach attached click event handler to element', function () {
|
||||
const result: Event[] = []
|
||||
function clicked (ev: Event) {
|
||||
result.push(ev)
|
||||
const vnode1 = h(
|
||||
"div",
|
||||
{
|
||||
on: {
|
||||
click: function (ev) {
|
||||
result.push(1);
|
||||
},
|
||||
},
|
||||
},
|
||||
[h("a", "Click my parent")]
|
||||
);
|
||||
const vnode2 = h(
|
||||
"div",
|
||||
{
|
||||
on: {
|
||||
click: function (ev) {
|
||||
result.push(2);
|
||||
},
|
||||
},
|
||||
},
|
||||
[h("a", "Click my parent")]
|
||||
);
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
elm.click();
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
elm.click();
|
||||
assert.deepEqual(result, [1, 2]);
|
||||
});
|
||||
it("detach attached click event handler to element", function () {
|
||||
const result: Event[] = [];
|
||||
function clicked(ev: Event) {
|
||||
result.push(ev);
|
||||
}
|
||||
const vnode1 = h('div', { on: { click: clicked } }, [
|
||||
h('a', 'Click my parent'),
|
||||
])
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
elm.click()
|
||||
assert.strictEqual(1, result.length)
|
||||
const vnode2 = h('div', { on: {} }, [
|
||||
h('a', 'Click my parent'),
|
||||
])
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
elm.click()
|
||||
assert.strictEqual(1, result.length)
|
||||
})
|
||||
it('multiple event handlers for same event on same element', function () {
|
||||
let called = 0
|
||||
function clicked (ev: Event, vnode: VNode) {
|
||||
++called
|
||||
const vnode1 = h("div", { on: { click: clicked } }, [
|
||||
h("a", "Click my parent"),
|
||||
]);
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
elm.click();
|
||||
assert.strictEqual(1, result.length);
|
||||
const vnode2 = h("div", { on: {} }, [h("a", "Click my parent")]);
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
elm.click();
|
||||
assert.strictEqual(1, result.length);
|
||||
});
|
||||
it("multiple event handlers for same event on same element", function () {
|
||||
let called = 0;
|
||||
function clicked(ev: Event, vnode: VNode) {
|
||||
++called;
|
||||
// Check that the first argument is an event
|
||||
assert.strictEqual(true, 'target' in ev)
|
||||
assert.strictEqual(true, "target" in ev);
|
||||
// Check that the second argument was a vnode
|
||||
assert.strictEqual(vnode.sel, 'div')
|
||||
assert.strictEqual(vnode.sel, "div");
|
||||
}
|
||||
const vnode1 = h('div', { on: { click: [clicked, clicked, clicked] } }, [
|
||||
h('a', 'Click my parent'),
|
||||
])
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
elm.click()
|
||||
assert.strictEqual(3, called)
|
||||
const vnode2 = h('div', { on: { click: [clicked, clicked] } }, [
|
||||
h('a', 'Click my parent'),
|
||||
])
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
elm.click()
|
||||
assert.strictEqual(5, called)
|
||||
})
|
||||
it('access to virtual node in event handler', function () {
|
||||
const result: VNode[] = []
|
||||
function clicked (this: VNode, ev: Event, vnode: VNode) {
|
||||
result.push(this)
|
||||
result.push(vnode)
|
||||
const vnode1 = h("div", { on: { click: [clicked, clicked, clicked] } }, [
|
||||
h("a", "Click my parent"),
|
||||
]);
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
elm.click();
|
||||
assert.strictEqual(3, called);
|
||||
const vnode2 = h("div", { on: { click: [clicked, clicked] } }, [
|
||||
h("a", "Click my parent"),
|
||||
]);
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
elm.click();
|
||||
assert.strictEqual(5, called);
|
||||
});
|
||||
it("access to virtual node in event handler", function () {
|
||||
const result: VNode[] = [];
|
||||
function clicked(this: VNode, ev: Event, vnode: VNode) {
|
||||
result.push(this);
|
||||
result.push(vnode);
|
||||
}
|
||||
const vnode1 = h('div', { on: { click: clicked } }, [
|
||||
h('a', 'Click my parent'),
|
||||
])
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
elm.click()
|
||||
assert.strictEqual(2, result.length)
|
||||
assert.strictEqual(vnode1, result[0])
|
||||
assert.strictEqual(vnode1, result[1])
|
||||
})
|
||||
it('shared handlers in parent and child nodes', function () {
|
||||
const result = []
|
||||
const vnode1 = h("div", { on: { click: clicked } }, [
|
||||
h("a", "Click my parent"),
|
||||
]);
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
elm.click();
|
||||
assert.strictEqual(2, result.length);
|
||||
assert.strictEqual(vnode1, result[0]);
|
||||
assert.strictEqual(vnode1, result[1]);
|
||||
});
|
||||
it("shared handlers in parent and child nodes", function () {
|
||||
const result = [];
|
||||
const sharedHandlers = {
|
||||
click: function (ev: Event) { result.push(ev) }
|
||||
}
|
||||
const vnode1 = h('div', { on: sharedHandlers }, [
|
||||
h('a', { on: sharedHandlers }, 'Click my parent'),
|
||||
])
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
elm.click()
|
||||
assert.strictEqual(1, result.length)
|
||||
elm.firstChild.click()
|
||||
assert.strictEqual(3, result.length)
|
||||
})
|
||||
})
|
||||
click: function (ev: Event) {
|
||||
result.push(ev);
|
||||
},
|
||||
};
|
||||
const vnode1 = h("div", { on: sharedHandlers }, [
|
||||
h("a", { on: sharedHandlers }, "Click my parent"),
|
||||
]);
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
elm.click();
|
||||
assert.strictEqual(1, result.length);
|
||||
elm.firstChild.click();
|
||||
assert.strictEqual(3, result.length);
|
||||
});
|
||||
});
|
||||
|
@ -1,53 +1,50 @@
|
||||
import { assert } from 'chai'
|
||||
import { assert } from "chai";
|
||||
|
||||
import { init, h, attributesModule } from '../../src/index';
|
||||
import { init, h, attributesModule } from "../../src/index";
|
||||
|
||||
const patch = init([
|
||||
attributesModule
|
||||
])
|
||||
const patch = init([attributesModule]);
|
||||
|
||||
describe('svg', function () {
|
||||
let elm: any, vnode0: any
|
||||
describe("svg", function () {
|
||||
let elm: any, vnode0: any;
|
||||
beforeEach(function () {
|
||||
elm = document.createElement('svg')
|
||||
vnode0 = elm
|
||||
})
|
||||
|
||||
it('removes child svg elements', function () {
|
||||
const a = h('svg', {}, [
|
||||
h('g'),
|
||||
h('g')
|
||||
])
|
||||
const b = h('svg', {}, [
|
||||
h('g')
|
||||
])
|
||||
const result = patch(patch(vnode0, a), b).elm as SVGElement
|
||||
assert.strictEqual(result.childNodes.length, 1)
|
||||
})
|
||||
|
||||
it('adds correctly xlink namespaced attribute', function () {
|
||||
const xlinkNS = 'http://www.w3.org/1999/xlink'
|
||||
const testUrl = '/test'
|
||||
const a = h('svg', {}, [
|
||||
h('use', {
|
||||
attrs: { 'xlink:href': testUrl }
|
||||
}, [])
|
||||
])
|
||||
|
||||
const result = patch(vnode0, a).elm as SVGElement
|
||||
assert.strictEqual(result.childNodes.length, 1)
|
||||
const child = result.childNodes[0] as SVGUseElement
|
||||
assert.strictEqual(child.getAttribute('xlink:href'), testUrl)
|
||||
assert.strictEqual(child.getAttributeNS(xlinkNS, 'href'), testUrl)
|
||||
})
|
||||
|
||||
it('adds correctly xml namespaced attribute', function () {
|
||||
const xmlNS = 'http://www.w3.org/XML/1998/namespace'
|
||||
const testAttrValue = 'und'
|
||||
const a = h('svg', { attrs: { 'xml:lang': testAttrValue } }, [])
|
||||
|
||||
const result = patch(vnode0, a).elm as SVGElement
|
||||
assert.strictEqual(result.getAttributeNS(xmlNS, 'lang'), testAttrValue)
|
||||
assert.strictEqual(result.getAttribute('xml:lang'), testAttrValue)
|
||||
})
|
||||
})
|
||||
elm = document.createElement("svg");
|
||||
vnode0 = elm;
|
||||
});
|
||||
|
||||
it("removes child svg elements", function () {
|
||||
const a = h("svg", {}, [h("g"), h("g")]);
|
||||
const b = h("svg", {}, [h("g")]);
|
||||
const result = patch(patch(vnode0, a), b).elm as SVGElement;
|
||||
assert.strictEqual(result.childNodes.length, 1);
|
||||
});
|
||||
|
||||
it("adds correctly xlink namespaced attribute", function () {
|
||||
const xlinkNS = "http://www.w3.org/1999/xlink";
|
||||
const testUrl = "/test";
|
||||
const a = h("svg", {}, [
|
||||
h(
|
||||
"use",
|
||||
{
|
||||
attrs: { "xlink:href": testUrl },
|
||||
},
|
||||
[]
|
||||
),
|
||||
]);
|
||||
|
||||
const result = patch(vnode0, a).elm as SVGElement;
|
||||
assert.strictEqual(result.childNodes.length, 1);
|
||||
const child = result.childNodes[0] as SVGUseElement;
|
||||
assert.strictEqual(child.getAttribute("xlink:href"), testUrl);
|
||||
assert.strictEqual(child.getAttributeNS(xlinkNS, "href"), testUrl);
|
||||
});
|
||||
|
||||
it("adds correctly xml namespaced attribute", function () {
|
||||
const xmlNS = "http://www.w3.org/XML/1998/namespace";
|
||||
const testAttrValue = "und";
|
||||
const a = h("svg", { attrs: { "xml:lang": testAttrValue } }, []);
|
||||
|
||||
const result = patch(vnode0, a).elm as SVGElement;
|
||||
assert.strictEqual(result.getAttributeNS(xmlNS, "lang"), testAttrValue);
|
||||
assert.strictEqual(result.getAttribute("xml:lang"), testAttrValue);
|
||||
});
|
||||
});
|
||||
|
@ -1,167 +1,174 @@
|
||||
import { assert } from 'chai'
|
||||
import { assert } from "chai";
|
||||
|
||||
import { init, styleModule, h, toVNode } from '../../src/index';
|
||||
import { init, styleModule, h, toVNode } from "../../src/index";
|
||||
|
||||
const patch = init([
|
||||
styleModule
|
||||
])
|
||||
const patch = init([styleModule]);
|
||||
|
||||
const featureDiscoveryElm = document.createElement('div')
|
||||
featureDiscoveryElm.style.setProperty('--foo', 'foo')
|
||||
const hasCssVariables = featureDiscoveryElm.style.getPropertyValue('--foo') === 'foo'
|
||||
const featureDiscoveryElm = document.createElement("div");
|
||||
featureDiscoveryElm.style.setProperty("--foo", "foo");
|
||||
const hasCssVariables =
|
||||
featureDiscoveryElm.style.getPropertyValue("--foo") === "foo";
|
||||
|
||||
describe('style', function () {
|
||||
let elm: any, vnode0: any
|
||||
describe("style", function () {
|
||||
let elm: any, vnode0: any;
|
||||
beforeEach(function () {
|
||||
elm = document.createElement('div')
|
||||
vnode0 = elm
|
||||
})
|
||||
it('is being styled', function () {
|
||||
elm = patch(vnode0, h('div', { style: { fontSize: '12px' } })).elm
|
||||
assert.strictEqual(elm.style.fontSize, '12px')
|
||||
})
|
||||
it('can be memoized', function () {
|
||||
const cachedStyles = { fontSize: '14px', display: 'inline' }
|
||||
const vnode1 = h('i', { style: cachedStyles })
|
||||
const vnode2 = h('i', { style: cachedStyles })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.style.fontSize, '14px')
|
||||
assert.strictEqual(elm.style.display, 'inline')
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
assert.strictEqual(elm.style.fontSize, '14px')
|
||||
assert.strictEqual(elm.style.display, 'inline')
|
||||
})
|
||||
it('updates styles', function () {
|
||||
const vnode1 = h('i', { style: { fontSize: '14px', display: 'inline' } })
|
||||
const vnode2 = h('i', { style: { fontSize: '12px', display: 'block' } })
|
||||
const vnode3 = h('i', { style: { fontSize: '10px', display: 'block' } })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.style.fontSize, '14px')
|
||||
assert.strictEqual(elm.style.display, 'inline')
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
assert.strictEqual(elm.style.fontSize, '12px')
|
||||
assert.strictEqual(elm.style.display, 'block')
|
||||
elm = patch(vnode2, vnode3).elm
|
||||
assert.strictEqual(elm.style.fontSize, '10px')
|
||||
assert.strictEqual(elm.style.display, 'block')
|
||||
})
|
||||
it('explicialy removes styles', function () {
|
||||
const vnode1 = h('i', { style: { fontSize: '14px' } })
|
||||
const vnode2 = h('i', { style: { fontSize: '' } })
|
||||
const vnode3 = h('i', { style: { fontSize: '10px' } })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.style.fontSize, '14px')
|
||||
patch(vnode1, vnode2)
|
||||
assert.strictEqual(elm.style.fontSize, '')
|
||||
patch(vnode2, vnode3)
|
||||
assert.strictEqual(elm.style.fontSize, '10px')
|
||||
})
|
||||
it('implicially removes styles from element', function () {
|
||||
const vnode1 = h('div', [h('i', { style: { fontSize: '14px' } })])
|
||||
const vnode2 = h('div', [h('i')])
|
||||
const vnode3 = h('div', [h('i', { style: { fontSize: '10px' } })])
|
||||
patch(vnode0, vnode1)
|
||||
assert.strictEqual(elm.firstChild.style.fontSize, '14px')
|
||||
patch(vnode1, vnode2)
|
||||
assert.strictEqual(elm.firstChild.style.fontSize, '')
|
||||
patch(vnode2, vnode3)
|
||||
assert.strictEqual(elm.firstChild.style.fontSize, '10px')
|
||||
})
|
||||
it('updates css variables', function () {
|
||||
elm = document.createElement("div");
|
||||
vnode0 = elm;
|
||||
});
|
||||
it("is being styled", function () {
|
||||
elm = patch(vnode0, h("div", { style: { fontSize: "12px" } })).elm;
|
||||
assert.strictEqual(elm.style.fontSize, "12px");
|
||||
});
|
||||
it("can be memoized", function () {
|
||||
const cachedStyles = { fontSize: "14px", display: "inline" };
|
||||
const vnode1 = h("i", { style: cachedStyles });
|
||||
const vnode2 = h("i", { style: cachedStyles });
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.style.fontSize, "14px");
|
||||
assert.strictEqual(elm.style.display, "inline");
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
assert.strictEqual(elm.style.fontSize, "14px");
|
||||
assert.strictEqual(elm.style.display, "inline");
|
||||
});
|
||||
it("updates styles", function () {
|
||||
const vnode1 = h("i", { style: { fontSize: "14px", display: "inline" } });
|
||||
const vnode2 = h("i", { style: { fontSize: "12px", display: "block" } });
|
||||
const vnode3 = h("i", { style: { fontSize: "10px", display: "block" } });
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.style.fontSize, "14px");
|
||||
assert.strictEqual(elm.style.display, "inline");
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
assert.strictEqual(elm.style.fontSize, "12px");
|
||||
assert.strictEqual(elm.style.display, "block");
|
||||
elm = patch(vnode2, vnode3).elm;
|
||||
assert.strictEqual(elm.style.fontSize, "10px");
|
||||
assert.strictEqual(elm.style.display, "block");
|
||||
});
|
||||
it("explicialy removes styles", function () {
|
||||
const vnode1 = h("i", { style: { fontSize: "14px" } });
|
||||
const vnode2 = h("i", { style: { fontSize: "" } });
|
||||
const vnode3 = h("i", { style: { fontSize: "10px" } });
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.style.fontSize, "14px");
|
||||
patch(vnode1, vnode2);
|
||||
assert.strictEqual(elm.style.fontSize, "");
|
||||
patch(vnode2, vnode3);
|
||||
assert.strictEqual(elm.style.fontSize, "10px");
|
||||
});
|
||||
it("implicially removes styles from element", function () {
|
||||
const vnode1 = h("div", [h("i", { style: { fontSize: "14px" } })]);
|
||||
const vnode2 = h("div", [h("i")]);
|
||||
const vnode3 = h("div", [h("i", { style: { fontSize: "10px" } })]);
|
||||
patch(vnode0, vnode1);
|
||||
assert.strictEqual(elm.firstChild.style.fontSize, "14px");
|
||||
patch(vnode1, vnode2);
|
||||
assert.strictEqual(elm.firstChild.style.fontSize, "");
|
||||
patch(vnode2, vnode3);
|
||||
assert.strictEqual(elm.firstChild.style.fontSize, "10px");
|
||||
});
|
||||
it("updates css variables", function () {
|
||||
if (!hasCssVariables) {
|
||||
this.skip()
|
||||
this.skip();
|
||||
} else {
|
||||
const vnode1 = h('div', { style: { '--myVar': 1 as any } })
|
||||
const vnode2 = h('div', { style: { '--myVar': 2 as any } })
|
||||
const vnode3 = h('div', { style: { '--myVar': 3 as any } })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.style.getPropertyValue('--myVar'), '1')
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
assert.strictEqual(elm.style.getPropertyValue('--myVar'), '2')
|
||||
elm = patch(vnode2, vnode3).elm
|
||||
assert.strictEqual(elm.style.getPropertyValue('--myVar'), '3')
|
||||
const vnode1 = h("div", { style: { "--myVar": 1 as any } });
|
||||
const vnode2 = h("div", { style: { "--myVar": 2 as any } });
|
||||
const vnode3 = h("div", { style: { "--myVar": 3 as any } });
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.style.getPropertyValue("--myVar"), "1");
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
assert.strictEqual(elm.style.getPropertyValue("--myVar"), "2");
|
||||
elm = patch(vnode2, vnode3).elm;
|
||||
assert.strictEqual(elm.style.getPropertyValue("--myVar"), "3");
|
||||
}
|
||||
})
|
||||
it('explicialy removes css variables', function () {
|
||||
});
|
||||
it("explicialy removes css variables", function () {
|
||||
if (!hasCssVariables) {
|
||||
this.skip()
|
||||
this.skip();
|
||||
} else {
|
||||
const vnode1 = h('i', { style: { '--myVar': 1 as any } })
|
||||
const vnode2 = h('i', { style: { '--myVar': '' } })
|
||||
const vnode3 = h('i', { style: { '--myVar': 2 as any } })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.style.getPropertyValue('--myVar'), '1')
|
||||
patch(vnode1, vnode2)
|
||||
assert.strictEqual(elm.style.getPropertyValue('--myVar'), '')
|
||||
patch(vnode2, vnode3)
|
||||
assert.strictEqual(elm.style.getPropertyValue('--myVar'), '2')
|
||||
const vnode1 = h("i", { style: { "--myVar": 1 as any } });
|
||||
const vnode2 = h("i", { style: { "--myVar": "" } });
|
||||
const vnode3 = h("i", { style: { "--myVar": 2 as any } });
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.style.getPropertyValue("--myVar"), "1");
|
||||
patch(vnode1, vnode2);
|
||||
assert.strictEqual(elm.style.getPropertyValue("--myVar"), "");
|
||||
patch(vnode2, vnode3);
|
||||
assert.strictEqual(elm.style.getPropertyValue("--myVar"), "2");
|
||||
}
|
||||
})
|
||||
it('implicially removes css variables from element', function () {
|
||||
});
|
||||
it("implicially removes css variables from element", function () {
|
||||
if (!hasCssVariables) {
|
||||
this.skip()
|
||||
this.skip();
|
||||
} else {
|
||||
const vnode1 = h('div', [h('i', { style: { '--myVar': 1 as any } })])
|
||||
const vnode2 = h('div', [h('i')])
|
||||
const vnode3 = h('div', [h('i', { style: { '--myVar': 2 as any } })])
|
||||
patch(vnode0, vnode1)
|
||||
assert.strictEqual(elm.firstChild.style.getPropertyValue('--myVar'), '1')
|
||||
patch(vnode1, vnode2)
|
||||
assert.strictEqual(elm.firstChild.style.getPropertyValue('--myVar'), '')
|
||||
patch(vnode2, vnode3)
|
||||
assert.strictEqual(elm.firstChild.style.getPropertyValue('--myVar'), '2')
|
||||
const vnode1 = h("div", [h("i", { style: { "--myVar": 1 as any } })]);
|
||||
const vnode2 = h("div", [h("i")]);
|
||||
const vnode3 = h("div", [h("i", { style: { "--myVar": 2 as any } })]);
|
||||
patch(vnode0, vnode1);
|
||||
assert.strictEqual(elm.firstChild.style.getPropertyValue("--myVar"), "1");
|
||||
patch(vnode1, vnode2);
|
||||
assert.strictEqual(elm.firstChild.style.getPropertyValue("--myVar"), "");
|
||||
patch(vnode2, vnode3);
|
||||
assert.strictEqual(elm.firstChild.style.getPropertyValue("--myVar"), "2");
|
||||
}
|
||||
})
|
||||
it('updates delayed styles in next frame', function (done) {
|
||||
const vnode1 = h('i', { style: { fontSize: '14px', delayed: { fontSize: '16px' } as any } })
|
||||
const vnode2 = h('i', { style: { fontSize: '18px', delayed: { fontSize: '20px' } as any } })
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.style.fontSize, '14px')
|
||||
});
|
||||
it("updates delayed styles in next frame", function (done) {
|
||||
const vnode1 = h("i", {
|
||||
style: { fontSize: "14px", delayed: { fontSize: "16px" } as any },
|
||||
});
|
||||
const vnode2 = h("i", {
|
||||
style: { fontSize: "18px", delayed: { fontSize: "20px" } as any },
|
||||
});
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.style.fontSize, "14px");
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
assert.strictEqual(elm.style.fontSize, '16px')
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
assert.strictEqual(elm.style.fontSize, '18px')
|
||||
assert.strictEqual(elm.style.fontSize, "16px");
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
assert.strictEqual(elm.style.fontSize, "18px");
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
assert.strictEqual(elm.style.fontSize, '20px')
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
it('applies tranform as transition on remove', function (done) {
|
||||
const btn = h('button', {
|
||||
style: {
|
||||
transition: 'transform 0.1s',
|
||||
remove: { transform: 'translateY(100%)' } as any
|
||||
}
|
||||
}, ['A button'])
|
||||
const vnode1 = h('div.parent', {}, [btn])
|
||||
const vnode2 = h('div.parent', {}, [null])
|
||||
document.body.appendChild(vnode0)
|
||||
patch(vnode0, vnode1)
|
||||
patch(vnode1, vnode2)
|
||||
const button = document.querySelector('button') as HTMLButtonElement
|
||||
assert.notStrictEqual(button, null)
|
||||
button.addEventListener('transitionend', function () {
|
||||
assert.strictEqual(document.querySelector('button'), null)
|
||||
done()
|
||||
})
|
||||
})
|
||||
describe('using toVNode()', function () {
|
||||
it('handles (ignoring) comment nodes', function () {
|
||||
const comment = document.createComment('yolo')
|
||||
const prevElm = document.createElement('div')
|
||||
prevElm.appendChild(comment)
|
||||
const nextVNode = h('div', [h('span', 'Hi')])
|
||||
elm = patch(toVNode(prevElm), nextVNode).elm
|
||||
assert.strictEqual(elm, prevElm)
|
||||
assert.strictEqual(elm.tagName, 'DIV')
|
||||
assert.strictEqual(elm.childNodes.length, 1)
|
||||
assert.strictEqual(elm.childNodes[0].tagName, 'SPAN')
|
||||
assert.strictEqual(elm.childNodes[0].textContent, 'Hi')
|
||||
})
|
||||
})
|
||||
})
|
||||
assert.strictEqual(elm.style.fontSize, "20px");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
it("applies tranform as transition on remove", function (done) {
|
||||
const btn = h(
|
||||
"button",
|
||||
{
|
||||
style: {
|
||||
transition: "transform 0.1s",
|
||||
remove: { transform: "translateY(100%)" } as any,
|
||||
},
|
||||
},
|
||||
["A button"]
|
||||
);
|
||||
const vnode1 = h("div.parent", {}, [btn]);
|
||||
const vnode2 = h("div.parent", {}, [null]);
|
||||
document.body.appendChild(vnode0);
|
||||
patch(vnode0, vnode1);
|
||||
patch(vnode1, vnode2);
|
||||
const button = document.querySelector("button") as HTMLButtonElement;
|
||||
assert.notStrictEqual(button, null);
|
||||
button.addEventListener("transitionend", function () {
|
||||
assert.strictEqual(document.querySelector("button"), null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
describe("using toVNode()", function () {
|
||||
it("handles (ignoring) comment nodes", function () {
|
||||
const comment = document.createComment("yolo");
|
||||
const prevElm = document.createElement("div");
|
||||
prevElm.appendChild(comment);
|
||||
const nextVNode = h("div", [h("span", "Hi")]);
|
||||
elm = patch(toVNode(prevElm), nextVNode).elm;
|
||||
assert.strictEqual(elm, prevElm);
|
||||
assert.strictEqual(elm.tagName, "DIV");
|
||||
assert.strictEqual(elm.childNodes.length, 1);
|
||||
assert.strictEqual(elm.childNodes[0].tagName, "SPAN");
|
||||
assert.strictEqual(elm.childNodes[0].textContent, "Hi");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,231 +1,210 @@
|
||||
import { assert } from 'chai'
|
||||
import { assert } from "chai";
|
||||
|
||||
import { init, h, thunk, VNode } from '../../src/index';
|
||||
import { init, h, thunk, VNode } from "../../src/index";
|
||||
|
||||
const patch = init([
|
||||
])
|
||||
const patch = init([]);
|
||||
|
||||
describe('thunk', function () {
|
||||
let elm: any, vnode0: any
|
||||
describe("thunk", function () {
|
||||
let elm: any, vnode0: any;
|
||||
beforeEach(function () {
|
||||
elm = vnode0 = document.createElement('div')
|
||||
})
|
||||
it('returns vnode with data and render function', function () {
|
||||
function numberInSpan (n: number) {
|
||||
return h('span', 'Number is ' + n)
|
||||
}
|
||||
const vnode = thunk('span', 'num', numberInSpan, [22])
|
||||
assert.deepEqual(vnode.sel, 'span')
|
||||
assert.deepEqual(vnode.data.key, 'num')
|
||||
assert.deepEqual(vnode.data.args, [22])
|
||||
})
|
||||
it('calls render function once on data change', function () {
|
||||
let called = 0
|
||||
function numberInSpan (n: number) {
|
||||
called++
|
||||
return h('span', { key: 'num' }, 'Number is ' + n)
|
||||
}
|
||||
const vnode1 = h('div', [
|
||||
thunk('span', 'num', numberInSpan, [1])
|
||||
])
|
||||
const vnode2 = h('div', [
|
||||
thunk('span', 'num', numberInSpan, [2])
|
||||
])
|
||||
patch(vnode0, vnode1)
|
||||
assert.strictEqual(called, 1)
|
||||
patch(vnode1, vnode2)
|
||||
assert.strictEqual(called, 2)
|
||||
})
|
||||
it('does not call render function on data unchanged', function () {
|
||||
let called = 0
|
||||
function numberInSpan (n: number) {
|
||||
called++
|
||||
return h('span', { key: 'num' }, 'Number is ' + n)
|
||||
}
|
||||
const vnode1 = h('div', [
|
||||
thunk('span', 'num', numberInSpan, [1])
|
||||
])
|
||||
const vnode2 = h('div', [
|
||||
thunk('span', 'num', numberInSpan, [1])
|
||||
])
|
||||
patch(vnode0, vnode1)
|
||||
assert.strictEqual(called, 1)
|
||||
patch(vnode1, vnode2)
|
||||
assert.strictEqual(called, 1)
|
||||
})
|
||||
it('calls render function once on data-length change', function () {
|
||||
let called = 0
|
||||
function numberInSpan (n: number) {
|
||||
called++
|
||||
return h('span', { key: 'num' }, 'Number is ' + n)
|
||||
}
|
||||
const vnode1 = h('div', [
|
||||
thunk('span', 'num', numberInSpan, [1])
|
||||
])
|
||||
const vnode2 = h('div', [
|
||||
thunk('span', 'num', numberInSpan, [1, 2])
|
||||
])
|
||||
patch(vnode0, vnode1)
|
||||
assert.strictEqual(called, 1)
|
||||
patch(vnode1, vnode2)
|
||||
assert.strictEqual(called, 2)
|
||||
})
|
||||
it('calls render function once on function change', function () {
|
||||
let called = 0
|
||||
function numberInSpan (n: number) {
|
||||
called++
|
||||
return h('span', { key: 'num' }, 'Number is ' + n)
|
||||
}
|
||||
function numberInSpan2 (n: number) {
|
||||
called++
|
||||
return h('span', { key: 'num' }, 'Number really is ' + n)
|
||||
}
|
||||
const vnode1 = h('div', [
|
||||
thunk('span', 'num', numberInSpan, [1])
|
||||
])
|
||||
const vnode2 = h('div', [
|
||||
thunk('span', 'num', numberInSpan2, [1])
|
||||
])
|
||||
patch(vnode0, vnode1)
|
||||
assert.strictEqual(called, 1)
|
||||
patch(vnode1, vnode2)
|
||||
assert.strictEqual(called, 2)
|
||||
})
|
||||
it('renders correctly', function () {
|
||||
let called = 0
|
||||
function numberInSpan (n: number) {
|
||||
called++
|
||||
return h('span', { key: 'num' }, 'Number is ' + n)
|
||||
}
|
||||
const vnode1 = h('div', [
|
||||
thunk('span', 'num', numberInSpan, [1])
|
||||
])
|
||||
const vnode2 = h('div', [
|
||||
thunk('span', 'num', numberInSpan, [1])
|
||||
])
|
||||
const vnode3 = h('div', [
|
||||
thunk('span', 'num', numberInSpan, [2])
|
||||
])
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), 'span')
|
||||
assert.strictEqual(elm.firstChild.innerHTML, 'Number is 1')
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), 'span')
|
||||
assert.strictEqual(elm.firstChild.innerHTML, 'Number is 1')
|
||||
elm = patch(vnode2, vnode3).elm
|
||||
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), 'span')
|
||||
assert.strictEqual(elm.firstChild.innerHTML, 'Number is 2')
|
||||
assert.strictEqual(called, 2)
|
||||
})
|
||||
it('supports leaving out the `key` argument', function () {
|
||||
function vnodeFn (s: string) {
|
||||
return h('span.number', 'Hello ' + s)
|
||||
}
|
||||
const vnode1 = thunk('span.number', vnodeFn, ['World!'])
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.innerText, 'Hello World!')
|
||||
})
|
||||
it('renders correctly when root', function () {
|
||||
let called = 0
|
||||
function numberInSpan (n: number) {
|
||||
called++
|
||||
return h('span', { key: 'num' }, 'Number is ' + n)
|
||||
}
|
||||
const vnode1 = thunk('span', 'num', numberInSpan, [1])
|
||||
const vnode2 = thunk('span', 'num', numberInSpan, [1])
|
||||
const vnode3 = thunk('span', 'num', numberInSpan, [2])
|
||||
elm = vnode0 = document.createElement("div");
|
||||
});
|
||||
it("returns vnode with data and render function", function () {
|
||||
function numberInSpan(n: number) {
|
||||
return h("span", "Number is " + n);
|
||||
}
|
||||
const vnode = thunk("span", "num", numberInSpan, [22]);
|
||||
assert.deepEqual(vnode.sel, "span");
|
||||
assert.deepEqual(vnode.data.key, "num");
|
||||
assert.deepEqual(vnode.data.args, [22]);
|
||||
});
|
||||
it("calls render function once on data change", function () {
|
||||
let called = 0;
|
||||
function numberInSpan(n: number) {
|
||||
called++;
|
||||
return h("span", { key: "num" }, "Number is " + n);
|
||||
}
|
||||
const vnode1 = h("div", [thunk("span", "num", numberInSpan, [1])]);
|
||||
const vnode2 = h("div", [thunk("span", "num", numberInSpan, [2])]);
|
||||
patch(vnode0, vnode1);
|
||||
assert.strictEqual(called, 1);
|
||||
patch(vnode1, vnode2);
|
||||
assert.strictEqual(called, 2);
|
||||
});
|
||||
it("does not call render function on data unchanged", function () {
|
||||
let called = 0;
|
||||
function numberInSpan(n: number) {
|
||||
called++;
|
||||
return h("span", { key: "num" }, "Number is " + n);
|
||||
}
|
||||
const vnode1 = h("div", [thunk("span", "num", numberInSpan, [1])]);
|
||||
const vnode2 = h("div", [thunk("span", "num", numberInSpan, [1])]);
|
||||
patch(vnode0, vnode1);
|
||||
assert.strictEqual(called, 1);
|
||||
patch(vnode1, vnode2);
|
||||
assert.strictEqual(called, 1);
|
||||
});
|
||||
it("calls render function once on data-length change", function () {
|
||||
let called = 0;
|
||||
function numberInSpan(n: number) {
|
||||
called++;
|
||||
return h("span", { key: "num" }, "Number is " + n);
|
||||
}
|
||||
const vnode1 = h("div", [thunk("span", "num", numberInSpan, [1])]);
|
||||
const vnode2 = h("div", [thunk("span", "num", numberInSpan, [1, 2])]);
|
||||
patch(vnode0, vnode1);
|
||||
assert.strictEqual(called, 1);
|
||||
patch(vnode1, vnode2);
|
||||
assert.strictEqual(called, 2);
|
||||
});
|
||||
it("calls render function once on function change", function () {
|
||||
let called = 0;
|
||||
function numberInSpan(n: number) {
|
||||
called++;
|
||||
return h("span", { key: "num" }, "Number is " + n);
|
||||
}
|
||||
function numberInSpan2(n: number) {
|
||||
called++;
|
||||
return h("span", { key: "num" }, "Number really is " + n);
|
||||
}
|
||||
const vnode1 = h("div", [thunk("span", "num", numberInSpan, [1])]);
|
||||
const vnode2 = h("div", [thunk("span", "num", numberInSpan2, [1])]);
|
||||
patch(vnode0, vnode1);
|
||||
assert.strictEqual(called, 1);
|
||||
patch(vnode1, vnode2);
|
||||
assert.strictEqual(called, 2);
|
||||
});
|
||||
it("renders correctly", function () {
|
||||
let called = 0;
|
||||
function numberInSpan(n: number) {
|
||||
called++;
|
||||
return h("span", { key: "num" }, "Number is " + n);
|
||||
}
|
||||
const vnode1 = h("div", [thunk("span", "num", numberInSpan, [1])]);
|
||||
const vnode2 = h("div", [thunk("span", "num", numberInSpan, [1])]);
|
||||
const vnode3 = h("div", [thunk("span", "num", numberInSpan, [2])]);
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), "span");
|
||||
assert.strictEqual(elm.firstChild.innerHTML, "Number is 1");
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), "span");
|
||||
assert.strictEqual(elm.firstChild.innerHTML, "Number is 1");
|
||||
elm = patch(vnode2, vnode3).elm;
|
||||
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), "span");
|
||||
assert.strictEqual(elm.firstChild.innerHTML, "Number is 2");
|
||||
assert.strictEqual(called, 2);
|
||||
});
|
||||
it("supports leaving out the `key` argument", function () {
|
||||
function vnodeFn(s: string) {
|
||||
return h("span.number", "Hello " + s);
|
||||
}
|
||||
const vnode1 = thunk("span.number", vnodeFn, ["World!"]);
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.innerText, "Hello World!");
|
||||
});
|
||||
it("renders correctly when root", function () {
|
||||
let called = 0;
|
||||
function numberInSpan(n: number) {
|
||||
called++;
|
||||
return h("span", { key: "num" }, "Number is " + n);
|
||||
}
|
||||
const vnode1 = thunk("span", "num", numberInSpan, [1]);
|
||||
const vnode2 = thunk("span", "num", numberInSpan, [1]);
|
||||
const vnode3 = thunk("span", "num", numberInSpan, [2]);
|
||||
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.tagName.toLowerCase(), 'span')
|
||||
assert.strictEqual(elm.innerHTML, 'Number is 1')
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.tagName.toLowerCase(), "span");
|
||||
assert.strictEqual(elm.innerHTML, "Number is 1");
|
||||
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
assert.strictEqual(elm.tagName.toLowerCase(), 'span')
|
||||
assert.strictEqual(elm.innerHTML, 'Number is 1')
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
assert.strictEqual(elm.tagName.toLowerCase(), "span");
|
||||
assert.strictEqual(elm.innerHTML, "Number is 1");
|
||||
|
||||
elm = patch(vnode2, vnode3).elm
|
||||
assert.strictEqual(elm.tagName.toLowerCase(), 'span')
|
||||
assert.strictEqual(elm.innerHTML, 'Number is 2')
|
||||
assert.strictEqual(called, 2)
|
||||
})
|
||||
it('can be replaced and removed', function () {
|
||||
function numberInSpan (n: number) {
|
||||
return h('span', { key: 'num' }, 'Number is ' + n)
|
||||
}
|
||||
function oddEven (n: number): VNode {
|
||||
const prefix = (n % 2) === 0 ? 'Even' : 'Odd'
|
||||
return h('div', { key: oddEven as any }, prefix + ': ' + n)
|
||||
}
|
||||
const vnode1 = h('div', [thunk('span', 'num', numberInSpan, [1])])
|
||||
const vnode2 = h('div', [thunk('div', 'oddEven', oddEven, [4])])
|
||||
elm = patch(vnode2, vnode3).elm;
|
||||
assert.strictEqual(elm.tagName.toLowerCase(), "span");
|
||||
assert.strictEqual(elm.innerHTML, "Number is 2");
|
||||
assert.strictEqual(called, 2);
|
||||
});
|
||||
it("can be replaced and removed", function () {
|
||||
function numberInSpan(n: number) {
|
||||
return h("span", { key: "num" }, "Number is " + n);
|
||||
}
|
||||
function oddEven(n: number): VNode {
|
||||
const prefix = n % 2 === 0 ? "Even" : "Odd";
|
||||
return h("div", { key: oddEven as any }, prefix + ": " + n);
|
||||
}
|
||||
const vnode1 = h("div", [thunk("span", "num", numberInSpan, [1])]);
|
||||
const vnode2 = h("div", [thunk("div", "oddEven", oddEven, [4])]);
|
||||
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), 'span')
|
||||
assert.strictEqual(elm.firstChild.innerHTML, 'Number is 1')
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), "span");
|
||||
assert.strictEqual(elm.firstChild.innerHTML, "Number is 1");
|
||||
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), 'div')
|
||||
assert.strictEqual(elm.firstChild.innerHTML, 'Even: 4')
|
||||
})
|
||||
it('can be replaced and removed when root', function () {
|
||||
function numberInSpan (n: number) {
|
||||
return h('span', { key: 'num' }, 'Number is ' + n)
|
||||
}
|
||||
function oddEven (n: number): VNode {
|
||||
const prefix = (n % 2) === 0 ? 'Even' : 'Odd'
|
||||
return h('div', { key: oddEven as any }, prefix + ': ' + n)
|
||||
}
|
||||
const vnode1 = thunk('span', 'num', numberInSpan, [1])
|
||||
const vnode2 = thunk('div', 'oddEven', oddEven, [4])
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), "div");
|
||||
assert.strictEqual(elm.firstChild.innerHTML, "Even: 4");
|
||||
});
|
||||
it("can be replaced and removed when root", function () {
|
||||
function numberInSpan(n: number) {
|
||||
return h("span", { key: "num" }, "Number is " + n);
|
||||
}
|
||||
function oddEven(n: number): VNode {
|
||||
const prefix = n % 2 === 0 ? "Even" : "Odd";
|
||||
return h("div", { key: oddEven as any }, prefix + ": " + n);
|
||||
}
|
||||
const vnode1 = thunk("span", "num", numberInSpan, [1]);
|
||||
const vnode2 = thunk("div", "oddEven", oddEven, [4]);
|
||||
|
||||
elm = patch(vnode0, vnode1).elm
|
||||
assert.strictEqual(elm.tagName.toLowerCase(), 'span')
|
||||
assert.strictEqual(elm.innerHTML, 'Number is 1')
|
||||
elm = patch(vnode0, vnode1).elm;
|
||||
assert.strictEqual(elm.tagName.toLowerCase(), "span");
|
||||
assert.strictEqual(elm.innerHTML, "Number is 1");
|
||||
|
||||
elm = patch(vnode1, vnode2).elm
|
||||
assert.strictEqual(elm.tagName.toLowerCase(), 'div')
|
||||
assert.strictEqual(elm.innerHTML, 'Even: 4')
|
||||
})
|
||||
it('invokes destroy hook on thunks', function () {
|
||||
let called = 0
|
||||
function destroyHook () {
|
||||
called++
|
||||
}
|
||||
function numberInSpan (n: number) {
|
||||
return h('span', { key: 'num', hook: { destroy: destroyHook } }, 'Number is ' + n)
|
||||
}
|
||||
const vnode1 = h('div', [
|
||||
h('div', 'Foo'),
|
||||
thunk('span', 'num', numberInSpan, [1]),
|
||||
h('div', 'Foo')
|
||||
])
|
||||
const vnode2 = h('div', [
|
||||
h('div', 'Foo'),
|
||||
h('div', 'Foo')
|
||||
])
|
||||
patch(vnode0, vnode1)
|
||||
patch(vnode1, vnode2)
|
||||
assert.strictEqual(called, 1)
|
||||
})
|
||||
it('invokes remove hook on thunks', function () {
|
||||
let called = 0
|
||||
function hook () {
|
||||
called++
|
||||
}
|
||||
function numberInSpan (n: number) {
|
||||
return h('span', { key: 'num', hook: { remove: hook } }, 'Number is ' + n)
|
||||
}
|
||||
const vnode1 = h('div', [
|
||||
h('div', 'Foo'),
|
||||
thunk('span', 'num', numberInSpan, [1]),
|
||||
h('div', 'Foo')
|
||||
])
|
||||
const vnode2 = h('div', [
|
||||
h('div', 'Foo'),
|
||||
h('div', 'Foo')
|
||||
])
|
||||
patch(vnode0, vnode1)
|
||||
patch(vnode1, vnode2)
|
||||
assert.strictEqual(called, 1)
|
||||
})
|
||||
})
|
||||
elm = patch(vnode1, vnode2).elm;
|
||||
assert.strictEqual(elm.tagName.toLowerCase(), "div");
|
||||
assert.strictEqual(elm.innerHTML, "Even: 4");
|
||||
});
|
||||
it("invokes destroy hook on thunks", function () {
|
||||
let called = 0;
|
||||
function destroyHook() {
|
||||
called++;
|
||||
}
|
||||
function numberInSpan(n: number) {
|
||||
return h(
|
||||
"span",
|
||||
{ key: "num", hook: { destroy: destroyHook } },
|
||||
"Number is " + n
|
||||
);
|
||||
}
|
||||
const vnode1 = h("div", [
|
||||
h("div", "Foo"),
|
||||
thunk("span", "num", numberInSpan, [1]),
|
||||
h("div", "Foo"),
|
||||
]);
|
||||
const vnode2 = h("div", [h("div", "Foo"), h("div", "Foo")]);
|
||||
patch(vnode0, vnode1);
|
||||
patch(vnode1, vnode2);
|
||||
assert.strictEqual(called, 1);
|
||||
});
|
||||
it("invokes remove hook on thunks", function () {
|
||||
let called = 0;
|
||||
function hook() {
|
||||
called++;
|
||||
}
|
||||
function numberInSpan(n: number) {
|
||||
return h(
|
||||
"span",
|
||||
{ key: "num", hook: { remove: hook } },
|
||||
"Number is " + n
|
||||
);
|
||||
}
|
||||
const vnode1 = h("div", [
|
||||
h("div", "Foo"),
|
||||
thunk("span", "num", numberInSpan, [1]),
|
||||
h("div", "Foo"),
|
||||
]);
|
||||
const vnode2 = h("div", [h("div", "Foo"), h("div", "Foo")]);
|
||||
patch(vnode0, vnode1);
|
||||
patch(vnode1, vnode2);
|
||||
assert.strictEqual(called, 1);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue